2 function actionAddEntity(way) {
3 return function(graph) {
4 return graph.replace(way);
8 var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
14 function createCommonjsModule(fn, module) {
15 return module = { exports: {} }, fn(module, module.exports), module.exports;
18 var lodash = createCommonjsModule(function (module, exports) {
21 * Lodash <https://lodash.com/>
22 * Copyright JS Foundation and other contributors <https://js.foundation/>
23 * Released under MIT license <https://lodash.com/license>
24 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
25 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
29 /** Used as a safe reference for `undefined` in pre-ES5 environments. */
32 /** Used as the semantic version number. */
33 var VERSION = '4.17.4';
35 /** Used as the size to enable large array optimizations. */
36 var LARGE_ARRAY_SIZE = 200;
38 /** Error message constants. */
39 var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
40 FUNC_ERROR_TEXT = 'Expected a function';
42 /** Used to stand-in for `undefined` hash values. */
43 var HASH_UNDEFINED = '__lodash_hash_undefined__';
45 /** Used as the maximum memoize cache size. */
46 var MAX_MEMOIZE_SIZE = 500;
48 /** Used as the internal argument placeholder. */
49 var PLACEHOLDER = '__lodash_placeholder__';
51 /** Used to compose bitmasks for cloning. */
52 var CLONE_DEEP_FLAG = 1,
54 CLONE_SYMBOLS_FLAG = 4;
56 /** Used to compose bitmasks for value comparisons. */
57 var COMPARE_PARTIAL_FLAG = 1,
58 COMPARE_UNORDERED_FLAG = 2;
60 /** Used to compose bitmasks for function metadata. */
61 var WRAP_BIND_FLAG = 1,
62 WRAP_BIND_KEY_FLAG = 2,
63 WRAP_CURRY_BOUND_FLAG = 4,
65 WRAP_CURRY_RIGHT_FLAG = 16,
66 WRAP_PARTIAL_FLAG = 32,
67 WRAP_PARTIAL_RIGHT_FLAG = 64,
69 WRAP_REARG_FLAG = 256,
72 /** Used as default options for `_.truncate`. */
73 var DEFAULT_TRUNC_LENGTH = 30,
74 DEFAULT_TRUNC_OMISSION = '...';
76 /** Used to detect hot functions by number of calls within a span of milliseconds. */
80 /** Used to indicate the type of lazy iteratees. */
81 var LAZY_FILTER_FLAG = 1,
85 /** Used as references for various `Number` constants. */
87 MAX_SAFE_INTEGER = 9007199254740991,
88 MAX_INTEGER = 1.7976931348623157e+308,
91 /** Used as references for the maximum length and index of an array. */
92 var MAX_ARRAY_LENGTH = 4294967295,
93 MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
94 HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
96 /** Used to associate wrap methods with their bit flags. */
98 ['ary', WRAP_ARY_FLAG],
99 ['bind', WRAP_BIND_FLAG],
100 ['bindKey', WRAP_BIND_KEY_FLAG],
101 ['curry', WRAP_CURRY_FLAG],
102 ['curryRight', WRAP_CURRY_RIGHT_FLAG],
103 ['flip', WRAP_FLIP_FLAG],
104 ['partial', WRAP_PARTIAL_FLAG],
105 ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
106 ['rearg', WRAP_REARG_FLAG]
109 /** `Object#toString` result references. */
110 var argsTag = '[object Arguments]',
111 arrayTag = '[object Array]',
112 asyncTag = '[object AsyncFunction]',
113 boolTag = '[object Boolean]',
114 dateTag = '[object Date]',
115 domExcTag = '[object DOMException]',
116 errorTag = '[object Error]',
117 funcTag = '[object Function]',
118 genTag = '[object GeneratorFunction]',
119 mapTag = '[object Map]',
120 numberTag = '[object Number]',
121 nullTag = '[object Null]',
122 objectTag = '[object Object]',
123 promiseTag = '[object Promise]',
124 proxyTag = '[object Proxy]',
125 regexpTag = '[object RegExp]',
126 setTag = '[object Set]',
127 stringTag = '[object String]',
128 symbolTag = '[object Symbol]',
129 undefinedTag = '[object Undefined]',
130 weakMapTag = '[object WeakMap]',
131 weakSetTag = '[object WeakSet]';
133 var arrayBufferTag = '[object ArrayBuffer]',
134 dataViewTag = '[object DataView]',
135 float32Tag = '[object Float32Array]',
136 float64Tag = '[object Float64Array]',
137 int8Tag = '[object Int8Array]',
138 int16Tag = '[object Int16Array]',
139 int32Tag = '[object Int32Array]',
140 uint8Tag = '[object Uint8Array]',
141 uint8ClampedTag = '[object Uint8ClampedArray]',
142 uint16Tag = '[object Uint16Array]',
143 uint32Tag = '[object Uint32Array]';
145 /** Used to match empty string literals in compiled template source. */
146 var reEmptyStringLeading = /\b__p \+= '';/g,
147 reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
148 reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
150 /** Used to match HTML entities and HTML characters. */
151 var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
152 reUnescapedHtml = /[&<>"']/g,
153 reHasEscapedHtml = RegExp(reEscapedHtml.source),
154 reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
156 /** Used to match template delimiters. */
157 var reEscape = /<%-([\s\S]+?)%>/g,
158 reEvaluate = /<%([\s\S]+?)%>/g,
159 reInterpolate = /<%=([\s\S]+?)%>/g;
161 /** Used to match property names within property paths. */
162 var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
163 reIsPlainProp = /^\w*$/,
164 reLeadingDot = /^\./,
165 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
168 * Used to match `RegExp`
169 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
171 var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
172 reHasRegExpChar = RegExp(reRegExpChar.source);
174 /** Used to match leading and trailing whitespace. */
175 var reTrim = /^\s+|\s+$/g,
176 reTrimStart = /^\s+/,
179 /** Used to match wrap detail comments. */
180 var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
181 reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
182 reSplitDetails = /,? & /;
184 /** Used to match words composed of alphanumeric characters. */
185 var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
187 /** Used to match backslashes in property paths. */
188 var reEscapeChar = /\\(\\)?/g;
192 * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
194 var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
196 /** Used to match `RegExp` flags from their coerced string values. */
197 var reFlags = /\w*$/;
199 /** Used to detect bad signed hexadecimal string values. */
200 var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
202 /** Used to detect binary string values. */
203 var reIsBinary = /^0b[01]+$/i;
205 /** Used to detect host constructors (Safari). */
206 var reIsHostCtor = /^\[object .+?Constructor\]$/;
208 /** Used to detect octal string values. */
209 var reIsOctal = /^0o[0-7]+$/i;
211 /** Used to detect unsigned integer values. */
212 var reIsUint = /^(?:0|[1-9]\d*)$/;
214 /** Used to match Latin Unicode letters (excluding mathematical operators). */
215 var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
217 /** Used to ensure capturing order of template delimiters. */
218 var reNoMatch = /($^)/;
220 /** Used to match unescaped characters in compiled string literals. */
221 var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
223 /** Used to compose unicode character classes. */
224 var rsAstralRange = '\\ud800-\\udfff',
225 rsComboMarksRange = '\\u0300-\\u036f',
226 reComboHalfMarksRange = '\\ufe20-\\ufe2f',
227 rsComboSymbolsRange = '\\u20d0-\\u20ff',
228 rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
229 rsDingbatRange = '\\u2700-\\u27bf',
230 rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
231 rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
232 rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
233 rsPunctuationRange = '\\u2000-\\u206f',
234 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',
235 rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
236 rsVarRange = '\\ufe0e\\ufe0f',
237 rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
239 /** Used to compose unicode capture groups. */
240 var rsApos = "['\u2019]",
241 rsAstral = '[' + rsAstralRange + ']',
242 rsBreak = '[' + rsBreakRange + ']',
243 rsCombo = '[' + rsComboRange + ']',
245 rsDingbat = '[' + rsDingbatRange + ']',
246 rsLower = '[' + rsLowerRange + ']',
247 rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
248 rsFitz = '\\ud83c[\\udffb-\\udfff]',
249 rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
250 rsNonAstral = '[^' + rsAstralRange + ']',
251 rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
252 rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
253 rsUpper = '[' + rsUpperRange + ']',
256 /** Used to compose unicode regexes. */
257 var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
258 rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
259 rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
260 rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
261 reOptMod = rsModifier + '?',
262 rsOptVar = '[' + rsVarRange + ']?',
263 rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
264 rsOrdLower = '\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)',
265 rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)',
266 rsSeq = rsOptVar + reOptMod + rsOptJoin,
267 rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
268 rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
270 /** Used to match apostrophes. */
271 var reApos = RegExp(rsApos, 'g');
274 * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
275 * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
277 var reComboMark = RegExp(rsCombo, 'g');
279 /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
280 var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
282 /** Used to match complex or compound words. */
283 var reUnicodeWord = RegExp([
284 rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
285 rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
286 rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
287 rsUpper + '+' + rsOptContrUpper,
294 /** 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/). */
295 var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
297 /** Used to detect strings that need a more robust regexp to match words. */
298 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 ]/;
300 /** Used to assign default `context` object properties. */
302 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
303 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
304 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
305 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
306 '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
309 /** Used to make template sourceURLs easier to identify. */
310 var templateCounter = -1;
312 /** Used to identify `toStringTag` values of typed arrays. */
313 var typedArrayTags = {};
314 typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
315 typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
316 typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
317 typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
318 typedArrayTags[uint32Tag] = true;
319 typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
320 typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
321 typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
322 typedArrayTags[errorTag] = typedArrayTags[funcTag] =
323 typedArrayTags[mapTag] = typedArrayTags[numberTag] =
324 typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
325 typedArrayTags[setTag] = typedArrayTags[stringTag] =
326 typedArrayTags[weakMapTag] = false;
328 /** Used to identify `toStringTag` values supported by `_.clone`. */
329 var cloneableTags = {};
330 cloneableTags[argsTag] = cloneableTags[arrayTag] =
331 cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
332 cloneableTags[boolTag] = cloneableTags[dateTag] =
333 cloneableTags[float32Tag] = cloneableTags[float64Tag] =
334 cloneableTags[int8Tag] = cloneableTags[int16Tag] =
335 cloneableTags[int32Tag] = cloneableTags[mapTag] =
336 cloneableTags[numberTag] = cloneableTags[objectTag] =
337 cloneableTags[regexpTag] = cloneableTags[setTag] =
338 cloneableTags[stringTag] = cloneableTags[symbolTag] =
339 cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
340 cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
341 cloneableTags[errorTag] = cloneableTags[funcTag] =
342 cloneableTags[weakMapTag] = false;
344 /** Used to map Latin Unicode letters to basic Latin letters. */
345 var deburredLetters = {
346 // Latin-1 Supplement block.
347 '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
348 '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
349 '\xc7': 'C', '\xe7': 'c',
350 '\xd0': 'D', '\xf0': 'd',
351 '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
352 '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
353 '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
354 '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
355 '\xd1': 'N', '\xf1': 'n',
356 '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
357 '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
358 '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
359 '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
360 '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
361 '\xc6': 'Ae', '\xe6': 'ae',
362 '\xde': 'Th', '\xfe': 'th',
364 // Latin Extended-A block.
365 '\u0100': 'A', '\u0102': 'A', '\u0104': 'A',
366 '\u0101': 'a', '\u0103': 'a', '\u0105': 'a',
367 '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
368 '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
369 '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
370 '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
371 '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
372 '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
373 '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
374 '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
375 '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
376 '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
377 '\u0134': 'J', '\u0135': 'j',
378 '\u0136': 'K', '\u0137': 'k', '\u0138': 'k',
379 '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
380 '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
381 '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
382 '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
383 '\u014c': 'O', '\u014e': 'O', '\u0150': 'O',
384 '\u014d': 'o', '\u014f': 'o', '\u0151': 'o',
385 '\u0154': 'R', '\u0156': 'R', '\u0158': 'R',
386 '\u0155': 'r', '\u0157': 'r', '\u0159': 'r',
387 '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
388 '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's',
389 '\u0162': 'T', '\u0164': 'T', '\u0166': 'T',
390 '\u0163': 't', '\u0165': 't', '\u0167': 't',
391 '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
392 '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
393 '\u0174': 'W', '\u0175': 'w',
394 '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y',
395 '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z',
396 '\u017a': 'z', '\u017c': 'z', '\u017e': 'z',
397 '\u0132': 'IJ', '\u0133': 'ij',
398 '\u0152': 'Oe', '\u0153': 'oe',
399 '\u0149': "'n", '\u017f': 's'
402 /** Used to map characters to HTML entities. */
411 /** Used to map HTML entities to characters. */
412 var htmlUnescapes = {
420 /** Used to escape characters for inclusion in compiled string literals. */
421 var stringEscapes = {
430 /** Built-in method references without a dependency on `root`. */
431 var freeParseFloat = parseFloat,
432 freeParseInt = parseInt;
434 /** Detect free variable `global` from Node.js. */
435 var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
437 /** Detect free variable `self`. */
438 var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
440 /** Used as a reference to the global object. */
441 var root = freeGlobal || freeSelf || Function('return this')();
443 /** Detect free variable `exports`. */
444 var freeExports = 'object' == 'object' && exports && !exports.nodeType && exports;
446 /** Detect free variable `module`. */
447 var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
449 /** Detect the popular CommonJS extension `module.exports`. */
450 var moduleExports = freeModule && freeModule.exports === freeExports;
452 /** Detect free variable `process` from Node.js. */
453 var freeProcess = moduleExports && freeGlobal.process;
455 /** Used to access faster Node.js helpers. */
456 var nodeUtil = (function() {
458 return freeProcess && freeProcess.binding && freeProcess.binding('util');
462 /* Node.js helper references. */
463 var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
464 nodeIsDate = nodeUtil && nodeUtil.isDate,
465 nodeIsMap = nodeUtil && nodeUtil.isMap,
466 nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
467 nodeIsSet = nodeUtil && nodeUtil.isSet,
468 nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
470 /*--------------------------------------------------------------------------*/
473 * Adds the key-value `pair` to `map`.
476 * @param {Object} map The map to modify.
477 * @param {Array} pair The key-value pair to add.
478 * @returns {Object} Returns `map`.
480 function addMapEntry(map, pair) {
481 // Don't return `map.set` because it's not chainable in IE 11.
482 map.set(pair[0], pair[1]);
487 * Adds `value` to `set`.
490 * @param {Object} set The set to modify.
491 * @param {*} value The value to add.
492 * @returns {Object} Returns `set`.
494 function addSetEntry(set, value) {
495 // Don't return `set.add` because it's not chainable in IE 11.
501 * A faster alternative to `Function#apply`, this function invokes `func`
502 * with the `this` binding of `thisArg` and the arguments of `args`.
505 * @param {Function} func The function to invoke.
506 * @param {*} thisArg The `this` binding of `func`.
507 * @param {Array} args The arguments to invoke `func` with.
508 * @returns {*} Returns the result of `func`.
510 function apply(func, thisArg, args) {
511 switch (args.length) {
512 case 0: return func.call(thisArg);
513 case 1: return func.call(thisArg, args[0]);
514 case 2: return func.call(thisArg, args[0], args[1]);
515 case 3: return func.call(thisArg, args[0], args[1], args[2]);
517 return func.apply(thisArg, args);
521 * A specialized version of `baseAggregator` for arrays.
524 * @param {Array} [array] The array to iterate over.
525 * @param {Function} setter The function to set `accumulator` values.
526 * @param {Function} iteratee The iteratee to transform keys.
527 * @param {Object} accumulator The initial aggregated object.
528 * @returns {Function} Returns `accumulator`.
530 function arrayAggregator(array, setter, iteratee, accumulator) {
532 length = array == null ? 0 : array.length;
534 while (++index < length) {
535 var value = array[index];
536 setter(accumulator, value, iteratee(value), array);
542 * A specialized version of `_.forEach` for arrays without support for
543 * iteratee shorthands.
546 * @param {Array} [array] The array to iterate over.
547 * @param {Function} iteratee The function invoked per iteration.
548 * @returns {Array} Returns `array`.
550 function arrayEach(array, iteratee) {
552 length = array == null ? 0 : array.length;
554 while (++index < length) {
555 if (iteratee(array[index], index, array) === false) {
563 * A specialized version of `_.forEachRight` for arrays without support for
564 * iteratee shorthands.
567 * @param {Array} [array] The array to iterate over.
568 * @param {Function} iteratee The function invoked per iteration.
569 * @returns {Array} Returns `array`.
571 function arrayEachRight(array, iteratee) {
572 var length = array == null ? 0 : array.length;
575 if (iteratee(array[length], length, array) === false) {
583 * A specialized version of `_.every` for arrays without support for
584 * iteratee shorthands.
587 * @param {Array} [array] The array to iterate over.
588 * @param {Function} predicate The function invoked per iteration.
589 * @returns {boolean} Returns `true` if all elements pass the predicate check,
592 function arrayEvery(array, predicate) {
594 length = array == null ? 0 : array.length;
596 while (++index < length) {
597 if (!predicate(array[index], index, array)) {
605 * A specialized version of `_.filter` for arrays without support for
606 * iteratee shorthands.
609 * @param {Array} [array] The array to iterate over.
610 * @param {Function} predicate The function invoked per iteration.
611 * @returns {Array} Returns the new filtered array.
613 function arrayFilter(array, predicate) {
615 length = array == null ? 0 : array.length,
619 while (++index < length) {
620 var value = array[index];
621 if (predicate(value, index, array)) {
622 result[resIndex++] = value;
629 * A specialized version of `_.includes` for arrays without support for
630 * specifying an index to search from.
633 * @param {Array} [array] The array to inspect.
634 * @param {*} target The value to search for.
635 * @returns {boolean} Returns `true` if `target` is found, else `false`.
637 function arrayIncludes(array, value) {
638 var length = array == null ? 0 : array.length;
639 return !!length && baseIndexOf(array, value, 0) > -1;
643 * This function is like `arrayIncludes` except that it accepts a comparator.
646 * @param {Array} [array] The array to inspect.
647 * @param {*} target The value to search for.
648 * @param {Function} comparator The comparator invoked per element.
649 * @returns {boolean} Returns `true` if `target` is found, else `false`.
651 function arrayIncludesWith(array, value, comparator) {
653 length = array == null ? 0 : array.length;
655 while (++index < length) {
656 if (comparator(value, array[index])) {
664 * A specialized version of `_.map` for arrays without support for iteratee
668 * @param {Array} [array] The array to iterate over.
669 * @param {Function} iteratee The function invoked per iteration.
670 * @returns {Array} Returns the new mapped array.
672 function arrayMap(array, iteratee) {
674 length = array == null ? 0 : array.length,
675 result = Array(length);
677 while (++index < length) {
678 result[index] = iteratee(array[index], index, array);
684 * Appends the elements of `values` to `array`.
687 * @param {Array} array The array to modify.
688 * @param {Array} values The values to append.
689 * @returns {Array} Returns `array`.
691 function arrayPush(array, values) {
693 length = values.length,
694 offset = array.length;
696 while (++index < length) {
697 array[offset + index] = values[index];
703 * A specialized version of `_.reduce` for arrays without support for
704 * iteratee shorthands.
707 * @param {Array} [array] The array to iterate over.
708 * @param {Function} iteratee The function invoked per iteration.
709 * @param {*} [accumulator] The initial value.
710 * @param {boolean} [initAccum] Specify using the first element of `array` as
712 * @returns {*} Returns the accumulated value.
714 function arrayReduce(array, iteratee, accumulator, initAccum) {
716 length = array == null ? 0 : array.length;
718 if (initAccum && length) {
719 accumulator = array[++index];
721 while (++index < length) {
722 accumulator = iteratee(accumulator, array[index], index, array);
728 * A specialized version of `_.reduceRight` for arrays without support for
729 * iteratee shorthands.
732 * @param {Array} [array] The array to iterate over.
733 * @param {Function} iteratee The function invoked per iteration.
734 * @param {*} [accumulator] The initial value.
735 * @param {boolean} [initAccum] Specify using the last element of `array` as
737 * @returns {*} Returns the accumulated value.
739 function arrayReduceRight(array, iteratee, accumulator, initAccum) {
740 var length = array == null ? 0 : array.length;
741 if (initAccum && length) {
742 accumulator = array[--length];
745 accumulator = iteratee(accumulator, array[length], length, array);
751 * A specialized version of `_.some` for arrays without support for iteratee
755 * @param {Array} [array] The array to iterate over.
756 * @param {Function} predicate The function invoked per iteration.
757 * @returns {boolean} Returns `true` if any element passes the predicate check,
760 function arraySome(array, predicate) {
762 length = array == null ? 0 : array.length;
764 while (++index < length) {
765 if (predicate(array[index], index, array)) {
773 * Gets the size of an ASCII `string`.
776 * @param {string} string The string inspect.
777 * @returns {number} Returns the string size.
779 var asciiSize = baseProperty('length');
782 * Converts an ASCII `string` to an array.
785 * @param {string} string The string to convert.
786 * @returns {Array} Returns the converted array.
788 function asciiToArray(string) {
789 return string.split('');
793 * Splits an ASCII `string` into an array of its words.
796 * @param {string} The string to inspect.
797 * @returns {Array} Returns the words of `string`.
799 function asciiWords(string) {
800 return string.match(reAsciiWord) || [];
804 * The base implementation of methods like `_.findKey` and `_.findLastKey`,
805 * without support for iteratee shorthands, which iterates over `collection`
809 * @param {Array|Object} collection The collection to inspect.
810 * @param {Function} predicate The function invoked per iteration.
811 * @param {Function} eachFunc The function to iterate over `collection`.
812 * @returns {*} Returns the found element or its key, else `undefined`.
814 function baseFindKey(collection, predicate, eachFunc) {
816 eachFunc(collection, function(value, key, collection) {
817 if (predicate(value, key, collection)) {
826 * The base implementation of `_.findIndex` and `_.findLastIndex` without
827 * support for iteratee shorthands.
830 * @param {Array} array The array to inspect.
831 * @param {Function} predicate The function invoked per iteration.
832 * @param {number} fromIndex The index to search from.
833 * @param {boolean} [fromRight] Specify iterating from right to left.
834 * @returns {number} Returns the index of the matched value, else `-1`.
836 function baseFindIndex(array, predicate, fromIndex, fromRight) {
837 var length = array.length,
838 index = fromIndex + (fromRight ? 1 : -1);
840 while ((fromRight ? index-- : ++index < length)) {
841 if (predicate(array[index], index, array)) {
849 * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
852 * @param {Array} array The array to inspect.
853 * @param {*} value The value to search for.
854 * @param {number} fromIndex The index to search from.
855 * @returns {number} Returns the index of the matched value, else `-1`.
857 function baseIndexOf(array, value, fromIndex) {
858 return value === value
859 ? strictIndexOf(array, value, fromIndex)
860 : baseFindIndex(array, baseIsNaN, fromIndex);
864 * This function is like `baseIndexOf` except that it accepts a comparator.
867 * @param {Array} array The array to inspect.
868 * @param {*} value The value to search for.
869 * @param {number} fromIndex The index to search from.
870 * @param {Function} comparator The comparator invoked per element.
871 * @returns {number} Returns the index of the matched value, else `-1`.
873 function baseIndexOfWith(array, value, fromIndex, comparator) {
874 var index = fromIndex - 1,
875 length = array.length;
877 while (++index < length) {
878 if (comparator(array[index], value)) {
886 * The base implementation of `_.isNaN` without support for number objects.
889 * @param {*} value The value to check.
890 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
892 function baseIsNaN(value) {
893 return value !== value;
897 * The base implementation of `_.mean` and `_.meanBy` without support for
898 * iteratee shorthands.
901 * @param {Array} array The array to iterate over.
902 * @param {Function} iteratee The function invoked per iteration.
903 * @returns {number} Returns the mean.
905 function baseMean(array, iteratee) {
906 var length = array == null ? 0 : array.length;
907 return length ? (baseSum(array, iteratee) / length) : NAN;
911 * The base implementation of `_.property` without support for deep paths.
914 * @param {string} key The key of the property to get.
915 * @returns {Function} Returns the new accessor function.
917 function baseProperty(key) {
918 return function(object) {
919 return object == null ? undefined : object[key];
924 * The base implementation of `_.propertyOf` without support for deep paths.
927 * @param {Object} object The object to query.
928 * @returns {Function} Returns the new accessor function.
930 function basePropertyOf(object) {
931 return function(key) {
932 return object == null ? undefined : object[key];
937 * The base implementation of `_.reduce` and `_.reduceRight`, without support
938 * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
941 * @param {Array|Object} collection The collection to iterate over.
942 * @param {Function} iteratee The function invoked per iteration.
943 * @param {*} accumulator The initial value.
944 * @param {boolean} initAccum Specify using the first or last element of
945 * `collection` as the initial value.
946 * @param {Function} eachFunc The function to iterate over `collection`.
947 * @returns {*} Returns the accumulated value.
949 function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
950 eachFunc(collection, function(value, index, collection) {
951 accumulator = initAccum
952 ? (initAccum = false, value)
953 : iteratee(accumulator, value, index, collection);
959 * The base implementation of `_.sortBy` which uses `comparer` to define the
960 * sort order of `array` and replaces criteria objects with their corresponding
964 * @param {Array} array The array to sort.
965 * @param {Function} comparer The function to define sort order.
966 * @returns {Array} Returns `array`.
968 function baseSortBy(array, comparer) {
969 var length = array.length;
971 array.sort(comparer);
973 array[length] = array[length].value;
979 * The base implementation of `_.sum` and `_.sumBy` without support for
980 * iteratee shorthands.
983 * @param {Array} array The array to iterate over.
984 * @param {Function} iteratee The function invoked per iteration.
985 * @returns {number} Returns the sum.
987 function baseSum(array, iteratee) {
990 length = array.length;
992 while (++index < length) {
993 var current = iteratee(array[index]);
994 if (current !== undefined) {
995 result = result === undefined ? current : (result + current);
1002 * The base implementation of `_.times` without support for iteratee shorthands
1003 * or max array length checks.
1006 * @param {number} n The number of times to invoke `iteratee`.
1007 * @param {Function} iteratee The function invoked per iteration.
1008 * @returns {Array} Returns the array of results.
1010 function baseTimes(n, iteratee) {
1014 while (++index < n) {
1015 result[index] = iteratee(index);
1021 * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
1022 * of key-value pairs for `object` corresponding to the property names of `props`.
1025 * @param {Object} object The object to query.
1026 * @param {Array} props The property names to get values for.
1027 * @returns {Object} Returns the key-value pairs.
1029 function baseToPairs(object, props) {
1030 return arrayMap(props, function(key) {
1031 return [key, object[key]];
1036 * The base implementation of `_.unary` without support for storing metadata.
1039 * @param {Function} func The function to cap arguments for.
1040 * @returns {Function} Returns the new capped function.
1042 function baseUnary(func) {
1043 return function(value) {
1049 * The base implementation of `_.values` and `_.valuesIn` which creates an
1050 * array of `object` property values corresponding to the property names
1054 * @param {Object} object The object to query.
1055 * @param {Array} props The property names to get values for.
1056 * @returns {Object} Returns the array of property values.
1058 function baseValues(object, props) {
1059 return arrayMap(props, function(key) {
1065 * Checks if a `cache` value for `key` exists.
1068 * @param {Object} cache The cache to query.
1069 * @param {string} key The key of the entry to check.
1070 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
1072 function cacheHas(cache, key) {
1073 return cache.has(key);
1077 * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
1078 * that is not found in the character symbols.
1081 * @param {Array} strSymbols The string symbols to inspect.
1082 * @param {Array} chrSymbols The character symbols to find.
1083 * @returns {number} Returns the index of the first unmatched string symbol.
1085 function charsStartIndex(strSymbols, chrSymbols) {
1087 length = strSymbols.length;
1089 while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
1094 * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
1095 * that is not found in the character symbols.
1098 * @param {Array} strSymbols The string symbols to inspect.
1099 * @param {Array} chrSymbols The character symbols to find.
1100 * @returns {number} Returns the index of the last unmatched string symbol.
1102 function charsEndIndex(strSymbols, chrSymbols) {
1103 var index = strSymbols.length;
1105 while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
1110 * Gets the number of `placeholder` occurrences in `array`.
1113 * @param {Array} array The array to inspect.
1114 * @param {*} placeholder The placeholder to search for.
1115 * @returns {number} Returns the placeholder count.
1117 function countHolders(array, placeholder) {
1118 var length = array.length,
1122 if (array[length] === placeholder) {
1130 * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
1131 * letters to basic Latin letters.
1134 * @param {string} letter The matched letter to deburr.
1135 * @returns {string} Returns the deburred letter.
1137 var deburrLetter = basePropertyOf(deburredLetters);
1140 * Used by `_.escape` to convert characters to HTML entities.
1143 * @param {string} chr The matched character to escape.
1144 * @returns {string} Returns the escaped character.
1146 var escapeHtmlChar = basePropertyOf(htmlEscapes);
1149 * Used by `_.template` to escape characters for inclusion in compiled string literals.
1152 * @param {string} chr The matched character to escape.
1153 * @returns {string} Returns the escaped character.
1155 function escapeStringChar(chr) {
1156 return '\\' + stringEscapes[chr];
1160 * Gets the value at `key` of `object`.
1163 * @param {Object} [object] The object to query.
1164 * @param {string} key The key of the property to get.
1165 * @returns {*} Returns the property value.
1167 function getValue(object, key) {
1168 return object == null ? undefined : object[key];
1172 * Checks if `string` contains Unicode symbols.
1175 * @param {string} string The string to inspect.
1176 * @returns {boolean} Returns `true` if a symbol is found, else `false`.
1178 function hasUnicode(string) {
1179 return reHasUnicode.test(string);
1183 * Checks if `string` contains a word composed of Unicode symbols.
1186 * @param {string} string The string to inspect.
1187 * @returns {boolean} Returns `true` if a word is found, else `false`.
1189 function hasUnicodeWord(string) {
1190 return reHasUnicodeWord.test(string);
1194 * Converts `iterator` to an array.
1197 * @param {Object} iterator The iterator to convert.
1198 * @returns {Array} Returns the converted array.
1200 function iteratorToArray(iterator) {
1204 while (!(data = iterator.next()).done) {
1205 result.push(data.value);
1211 * Converts `map` to its key-value pairs.
1214 * @param {Object} map The map to convert.
1215 * @returns {Array} Returns the key-value pairs.
1217 function mapToArray(map) {
1219 result = Array(map.size);
1221 map.forEach(function(value, key) {
1222 result[++index] = [key, value];
1228 * Creates a unary function that invokes `func` with its argument transformed.
1231 * @param {Function} func The function to wrap.
1232 * @param {Function} transform The argument transform.
1233 * @returns {Function} Returns the new function.
1235 function overArg(func, transform) {
1236 return function(arg) {
1237 return func(transform(arg));
1242 * Replaces all `placeholder` elements in `array` with an internal placeholder
1243 * and returns an array of their indexes.
1246 * @param {Array} array The array to modify.
1247 * @param {*} placeholder The placeholder to replace.
1248 * @returns {Array} Returns the new array of placeholder indexes.
1250 function replaceHolders(array, placeholder) {
1252 length = array.length,
1256 while (++index < length) {
1257 var value = array[index];
1258 if (value === placeholder || value === PLACEHOLDER) {
1259 array[index] = PLACEHOLDER;
1260 result[resIndex++] = index;
1267 * Converts `set` to an array of its values.
1270 * @param {Object} set The set to convert.
1271 * @returns {Array} Returns the values.
1273 function setToArray(set) {
1275 result = Array(set.size);
1277 set.forEach(function(value) {
1278 result[++index] = value;
1284 * Converts `set` to its value-value pairs.
1287 * @param {Object} set The set to convert.
1288 * @returns {Array} Returns the value-value pairs.
1290 function setToPairs(set) {
1292 result = Array(set.size);
1294 set.forEach(function(value) {
1295 result[++index] = [value, value];
1301 * A specialized version of `_.indexOf` which performs strict equality
1302 * comparisons of values, i.e. `===`.
1305 * @param {Array} array The array to inspect.
1306 * @param {*} value The value to search for.
1307 * @param {number} fromIndex The index to search from.
1308 * @returns {number} Returns the index of the matched value, else `-1`.
1310 function strictIndexOf(array, value, fromIndex) {
1311 var index = fromIndex - 1,
1312 length = array.length;
1314 while (++index < length) {
1315 if (array[index] === value) {
1323 * A specialized version of `_.lastIndexOf` which performs strict equality
1324 * comparisons of values, i.e. `===`.
1327 * @param {Array} array The array to inspect.
1328 * @param {*} value The value to search for.
1329 * @param {number} fromIndex The index to search from.
1330 * @returns {number} Returns the index of the matched value, else `-1`.
1332 function strictLastIndexOf(array, value, fromIndex) {
1333 var index = fromIndex + 1;
1335 if (array[index] === value) {
1343 * Gets the number of symbols in `string`.
1346 * @param {string} string The string to inspect.
1347 * @returns {number} Returns the string size.
1349 function stringSize(string) {
1350 return hasUnicode(string)
1351 ? unicodeSize(string)
1352 : asciiSize(string);
1356 * Converts `string` to an array.
1359 * @param {string} string The string to convert.
1360 * @returns {Array} Returns the converted array.
1362 function stringToArray(string) {
1363 return hasUnicode(string)
1364 ? unicodeToArray(string)
1365 : asciiToArray(string);
1369 * Used by `_.unescape` to convert HTML entities to characters.
1372 * @param {string} chr The matched character to unescape.
1373 * @returns {string} Returns the unescaped character.
1375 var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
1378 * Gets the size of a Unicode `string`.
1381 * @param {string} string The string inspect.
1382 * @returns {number} Returns the string size.
1384 function unicodeSize(string) {
1385 var result = reUnicode.lastIndex = 0;
1386 while (reUnicode.test(string)) {
1393 * Converts a Unicode `string` to an array.
1396 * @param {string} string The string to convert.
1397 * @returns {Array} Returns the converted array.
1399 function unicodeToArray(string) {
1400 return string.match(reUnicode) || [];
1404 * Splits a Unicode `string` into an array of its words.
1407 * @param {string} The string to inspect.
1408 * @returns {Array} Returns the words of `string`.
1410 function unicodeWords(string) {
1411 return string.match(reUnicodeWord) || [];
1414 /*--------------------------------------------------------------------------*/
1417 * Create a new pristine `lodash` function using the `context` object.
1423 * @param {Object} [context=root] The context object.
1424 * @returns {Function} Returns a new `lodash` function.
1427 * _.mixin({ 'foo': _.constant('foo') });
1429 * var lodash = _.runInContext();
1430 * lodash.mixin({ 'bar': lodash.constant('bar') });
1432 * _.isFunction(_.foo);
1434 * _.isFunction(_.bar);
1437 * lodash.isFunction(lodash.foo);
1439 * lodash.isFunction(lodash.bar);
1442 * // Create a suped-up `defer` in Node.js.
1443 * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
1445 var runInContext = (function runInContext(context) {
1446 context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
1448 /** Built-in constructor references. */
1449 var Array = context.Array,
1450 Date = context.Date,
1451 Error = context.Error,
1452 Function = context.Function,
1453 Math = context.Math,
1454 Object = context.Object,
1455 RegExp = context.RegExp,
1456 String = context.String,
1457 TypeError = context.TypeError;
1459 /** Used for built-in method references. */
1460 var arrayProto = Array.prototype,
1461 funcProto = Function.prototype,
1462 objectProto = Object.prototype;
1464 /** Used to detect overreaching core-js shims. */
1465 var coreJsData = context['__core-js_shared__'];
1467 /** Used to resolve the decompiled source of functions. */
1468 var funcToString = funcProto.toString;
1470 /** Used to check objects for own properties. */
1471 var hasOwnProperty = objectProto.hasOwnProperty;
1473 /** Used to generate unique IDs. */
1476 /** Used to detect methods masquerading as native. */
1477 var maskSrcKey = (function() {
1478 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
1479 return uid ? ('Symbol(src)_1.' + uid) : '';
1483 * Used to resolve the
1484 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
1487 var nativeObjectToString = objectProto.toString;
1489 /** Used to infer the `Object` constructor. */
1490 var objectCtorString = funcToString.call(Object);
1492 /** Used to restore the original `_` reference in `_.noConflict`. */
1493 var oldDash = root._;
1495 /** Used to detect if a method is native. */
1496 var reIsNative = RegExp('^' +
1497 funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
1498 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
1501 /** Built-in value references. */
1502 var Buffer = moduleExports ? context.Buffer : undefined,
1503 Symbol = context.Symbol,
1504 Uint8Array = context.Uint8Array,
1505 allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,
1506 getPrototype = overArg(Object.getPrototypeOf, Object),
1507 objectCreate = Object.create,
1508 propertyIsEnumerable = objectProto.propertyIsEnumerable,
1509 splice = arrayProto.splice,
1510 spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,
1511 symIterator = Symbol ? Symbol.iterator : undefined,
1512 symToStringTag = Symbol ? Symbol.toStringTag : undefined;
1514 var defineProperty = (function() {
1516 var func = getNative(Object, 'defineProperty');
1522 /** Mocked built-ins. */
1523 var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
1524 ctxNow = Date && Date.now !== root.Date.now && Date.now,
1525 ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
1527 /* Built-in method references for those with the same name as other `lodash` methods. */
1528 var nativeCeil = Math.ceil,
1529 nativeFloor = Math.floor,
1530 nativeGetSymbols = Object.getOwnPropertySymbols,
1531 nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
1532 nativeIsFinite = context.isFinite,
1533 nativeJoin = arrayProto.join,
1534 nativeKeys = overArg(Object.keys, Object),
1535 nativeMax = Math.max,
1536 nativeMin = Math.min,
1537 nativeNow = Date.now,
1538 nativeParseInt = context.parseInt,
1539 nativeRandom = Math.random,
1540 nativeReverse = arrayProto.reverse;
1542 /* Built-in method references that are verified to be native. */
1543 var DataView = getNative(context, 'DataView'),
1544 Map = getNative(context, 'Map'),
1545 Promise = getNative(context, 'Promise'),
1546 Set = getNative(context, 'Set'),
1547 WeakMap = getNative(context, 'WeakMap'),
1548 nativeCreate = getNative(Object, 'create');
1550 /** Used to store function metadata. */
1551 var metaMap = WeakMap && new WeakMap;
1553 /** Used to lookup unminified function names. */
1556 /** Used to detect maps, sets, and weakmaps. */
1557 var dataViewCtorString = toSource(DataView),
1558 mapCtorString = toSource(Map),
1559 promiseCtorString = toSource(Promise),
1560 setCtorString = toSource(Set),
1561 weakMapCtorString = toSource(WeakMap);
1563 /** Used to convert symbols to primitives and strings. */
1564 var symbolProto = Symbol ? Symbol.prototype : undefined,
1565 symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
1566 symbolToString = symbolProto ? symbolProto.toString : undefined;
1568 /*------------------------------------------------------------------------*/
1571 * Creates a `lodash` object which wraps `value` to enable implicit method
1572 * chain sequences. Methods that operate on and return arrays, collections,
1573 * and functions can be chained together. Methods that retrieve a single value
1574 * or may return a primitive value will automatically end the chain sequence
1575 * and return the unwrapped value. Otherwise, the value must be unwrapped
1578 * Explicit chain sequences, which must be unwrapped with `_#value`, may be
1579 * enabled using `_.chain`.
1581 * The execution of chained methods is lazy, that is, it's deferred until
1582 * `_#value` is implicitly or explicitly called.
1584 * Lazy evaluation allows several methods to support shortcut fusion.
1585 * Shortcut fusion is an optimization to merge iteratee calls; this avoids
1586 * the creation of intermediate arrays and can greatly reduce the number of
1587 * iteratee executions. Sections of a chain sequence qualify for shortcut
1588 * fusion if the section is applied to an array and iteratees accept only
1589 * one argument. The heuristic for whether a section qualifies for shortcut
1590 * fusion is subject to change.
1592 * Chaining is supported in custom builds as long as the `_#value` method is
1593 * directly or indirectly included in the build.
1595 * In addition to lodash methods, wrappers have `Array` and `String` methods.
1597 * The wrapper `Array` methods are:
1598 * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
1600 * The wrapper `String` methods are:
1601 * `replace` and `split`
1603 * The wrapper methods that support shortcut fusion are:
1604 * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
1605 * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
1606 * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
1608 * The chainable wrapper methods are:
1609 * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
1610 * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
1611 * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
1612 * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
1613 * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
1614 * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
1615 * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
1616 * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
1617 * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
1618 * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
1619 * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
1620 * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
1621 * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
1622 * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
1623 * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
1624 * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
1625 * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
1626 * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
1627 * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
1628 * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
1629 * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
1630 * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
1631 * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
1632 * `zipObject`, `zipObjectDeep`, and `zipWith`
1634 * The wrapper methods that are **not** chainable by default are:
1635 * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
1636 * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
1637 * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
1638 * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
1639 * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
1640 * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
1641 * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
1642 * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
1643 * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
1644 * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
1645 * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
1646 * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
1647 * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
1648 * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
1649 * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
1650 * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
1651 * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
1652 * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
1653 * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
1654 * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
1655 * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
1656 * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
1657 * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
1658 * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
1659 * `upperFirst`, `value`, and `words`
1664 * @param {*} value The value to wrap in a `lodash` instance.
1665 * @returns {Object} Returns the new `lodash` wrapper instance.
1668 * function square(n) {
1672 * var wrapped = _([1, 2, 3]);
1674 * // Returns an unwrapped value.
1675 * wrapped.reduce(_.add);
1678 * // Returns a wrapped value.
1679 * var squares = wrapped.map(square);
1681 * _.isArray(squares);
1684 * _.isArray(squares.value());
1687 function lodash(value) {
1688 if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
1689 if (value instanceof LodashWrapper) {
1692 if (hasOwnProperty.call(value, '__wrapped__')) {
1693 return wrapperClone(value);
1696 return new LodashWrapper(value);
1700 * The base implementation of `_.create` without support for assigning
1701 * properties to the created object.
1704 * @param {Object} proto The object to inherit from.
1705 * @returns {Object} Returns the new object.
1707 var baseCreate = (function() {
1708 function object() {}
1709 return function(proto) {
1710 if (!isObject(proto)) {
1714 return objectCreate(proto);
1716 object.prototype = proto;
1717 var result = new object;
1718 object.prototype = undefined;
1724 * The function whose prototype chain sequence wrappers inherit from.
1728 function baseLodash() {
1729 // No operation performed.
1733 * The base constructor for creating `lodash` wrapper objects.
1736 * @param {*} value The value to wrap.
1737 * @param {boolean} [chainAll] Enable explicit method chain sequences.
1739 function LodashWrapper(value, chainAll) {
1740 this.__wrapped__ = value;
1741 this.__actions__ = [];
1742 this.__chain__ = !!chainAll;
1744 this.__values__ = undefined;
1748 * By default, the template delimiters used by lodash are like those in
1749 * embedded Ruby (ERB) as well as ES2015 template strings. Change the
1750 * following template settings to use alternative delimiters.
1756 lodash.templateSettings = {
1759 * Used to detect `data` property values to be HTML-escaped.
1761 * @memberOf _.templateSettings
1767 * Used to detect code to be evaluated.
1769 * @memberOf _.templateSettings
1772 'evaluate': reEvaluate,
1775 * Used to detect `data` property values to inject.
1777 * @memberOf _.templateSettings
1780 'interpolate': reInterpolate,
1783 * Used to reference the data object in the template text.
1785 * @memberOf _.templateSettings
1791 * Used to import variables into the compiled template.
1793 * @memberOf _.templateSettings
1799 * A reference to the `lodash` function.
1801 * @memberOf _.templateSettings.imports
1808 // Ensure wrappers are instances of `baseLodash`.
1809 lodash.prototype = baseLodash.prototype;
1810 lodash.prototype.constructor = lodash;
1812 LodashWrapper.prototype = baseCreate(baseLodash.prototype);
1813 LodashWrapper.prototype.constructor = LodashWrapper;
1815 /*------------------------------------------------------------------------*/
1818 * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
1822 * @param {*} value The value to wrap.
1824 function LazyWrapper(value) {
1825 this.__wrapped__ = value;
1826 this.__actions__ = [];
1828 this.__filtered__ = false;
1829 this.__iteratees__ = [];
1830 this.__takeCount__ = MAX_ARRAY_LENGTH;
1831 this.__views__ = [];
1835 * Creates a clone of the lazy wrapper object.
1839 * @memberOf LazyWrapper
1840 * @returns {Object} Returns the cloned `LazyWrapper` object.
1842 function lazyClone() {
1843 var result = new LazyWrapper(this.__wrapped__);
1844 result.__actions__ = copyArray(this.__actions__);
1845 result.__dir__ = this.__dir__;
1846 result.__filtered__ = this.__filtered__;
1847 result.__iteratees__ = copyArray(this.__iteratees__);
1848 result.__takeCount__ = this.__takeCount__;
1849 result.__views__ = copyArray(this.__views__);
1854 * Reverses the direction of lazy iteration.
1858 * @memberOf LazyWrapper
1859 * @returns {Object} Returns the new reversed `LazyWrapper` object.
1861 function lazyReverse() {
1862 if (this.__filtered__) {
1863 var result = new LazyWrapper(this);
1864 result.__dir__ = -1;
1865 result.__filtered__ = true;
1867 result = this.clone();
1868 result.__dir__ *= -1;
1874 * Extracts the unwrapped value from its lazy wrapper.
1878 * @memberOf LazyWrapper
1879 * @returns {*} Returns the unwrapped value.
1881 function lazyValue() {
1882 var array = this.__wrapped__.value(),
1884 isArr = isArray(array),
1886 arrLength = isArr ? array.length : 0,
1887 view = getView(0, arrLength, this.__views__),
1890 length = end - start,
1891 index = isRight ? end : (start - 1),
1892 iteratees = this.__iteratees__,
1893 iterLength = iteratees.length,
1895 takeCount = nativeMin(length, this.__takeCount__);
1897 if (!isArr || (!isRight && arrLength == length && takeCount == length)) {
1898 return baseWrapperValue(array, this.__actions__);
1903 while (length-- && resIndex < takeCount) {
1907 value = array[index];
1909 while (++iterIndex < iterLength) {
1910 var data = iteratees[iterIndex],
1911 iteratee = data.iteratee,
1913 computed = iteratee(value);
1915 if (type == LAZY_MAP_FLAG) {
1917 } else if (!computed) {
1918 if (type == LAZY_FILTER_FLAG) {
1925 result[resIndex++] = value;
1930 // Ensure `LazyWrapper` is an instance of `baseLodash`.
1931 LazyWrapper.prototype = baseCreate(baseLodash.prototype);
1932 LazyWrapper.prototype.constructor = LazyWrapper;
1934 /*------------------------------------------------------------------------*/
1937 * Creates a hash object.
1941 * @param {Array} [entries] The key-value pairs to cache.
1943 function Hash(entries) {
1945 length = entries == null ? 0 : entries.length;
1948 while (++index < length) {
1949 var entry = entries[index];
1950 this.set(entry[0], entry[1]);
1955 * Removes all key-value entries from the hash.
1961 function hashClear() {
1962 this.__data__ = nativeCreate ? nativeCreate(null) : {};
1967 * Removes `key` and its value from the hash.
1972 * @param {Object} hash The hash to modify.
1973 * @param {string} key The key of the value to remove.
1974 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
1976 function hashDelete(key) {
1977 var result = this.has(key) && delete this.__data__[key];
1978 this.size -= result ? 1 : 0;
1983 * Gets the hash value for `key`.
1988 * @param {string} key The key of the value to get.
1989 * @returns {*} Returns the entry value.
1991 function hashGet(key) {
1992 var data = this.__data__;
1994 var result = data[key];
1995 return result === HASH_UNDEFINED ? undefined : result;
1997 return hasOwnProperty.call(data, key) ? data[key] : undefined;
2001 * Checks if a hash value for `key` exists.
2006 * @param {string} key The key of the entry to check.
2007 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2009 function hashHas(key) {
2010 var data = this.__data__;
2011 return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
2015 * Sets the hash `key` to `value`.
2020 * @param {string} key The key of the value to set.
2021 * @param {*} value The value to set.
2022 * @returns {Object} Returns the hash instance.
2024 function hashSet(key, value) {
2025 var data = this.__data__;
2026 this.size += this.has(key) ? 0 : 1;
2027 data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
2031 // Add methods to `Hash`.
2032 Hash.prototype.clear = hashClear;
2033 Hash.prototype['delete'] = hashDelete;
2034 Hash.prototype.get = hashGet;
2035 Hash.prototype.has = hashHas;
2036 Hash.prototype.set = hashSet;
2038 /*------------------------------------------------------------------------*/
2041 * Creates an list cache object.
2045 * @param {Array} [entries] The key-value pairs to cache.
2047 function ListCache(entries) {
2049 length = entries == null ? 0 : entries.length;
2052 while (++index < length) {
2053 var entry = entries[index];
2054 this.set(entry[0], entry[1]);
2059 * Removes all key-value entries from the list cache.
2063 * @memberOf ListCache
2065 function listCacheClear() {
2071 * Removes `key` and its value from the list cache.
2075 * @memberOf ListCache
2076 * @param {string} key The key of the value to remove.
2077 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2079 function listCacheDelete(key) {
2080 var data = this.__data__,
2081 index = assocIndexOf(data, key);
2086 var lastIndex = data.length - 1;
2087 if (index == lastIndex) {
2090 splice.call(data, index, 1);
2097 * Gets the list cache value for `key`.
2101 * @memberOf ListCache
2102 * @param {string} key The key of the value to get.
2103 * @returns {*} Returns the entry value.
2105 function listCacheGet(key) {
2106 var data = this.__data__,
2107 index = assocIndexOf(data, key);
2109 return index < 0 ? undefined : data[index][1];
2113 * Checks if a list cache value for `key` exists.
2117 * @memberOf ListCache
2118 * @param {string} key The key of the entry to check.
2119 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2121 function listCacheHas(key) {
2122 return assocIndexOf(this.__data__, key) > -1;
2126 * Sets the list cache `key` to `value`.
2130 * @memberOf ListCache
2131 * @param {string} key The key of the value to set.
2132 * @param {*} value The value to set.
2133 * @returns {Object} Returns the list cache instance.
2135 function listCacheSet(key, value) {
2136 var data = this.__data__,
2137 index = assocIndexOf(data, key);
2141 data.push([key, value]);
2143 data[index][1] = value;
2148 // Add methods to `ListCache`.
2149 ListCache.prototype.clear = listCacheClear;
2150 ListCache.prototype['delete'] = listCacheDelete;
2151 ListCache.prototype.get = listCacheGet;
2152 ListCache.prototype.has = listCacheHas;
2153 ListCache.prototype.set = listCacheSet;
2155 /*------------------------------------------------------------------------*/
2158 * Creates a map cache object to store key-value pairs.
2162 * @param {Array} [entries] The key-value pairs to cache.
2164 function MapCache(entries) {
2166 length = entries == null ? 0 : entries.length;
2169 while (++index < length) {
2170 var entry = entries[index];
2171 this.set(entry[0], entry[1]);
2176 * Removes all key-value entries from the map.
2180 * @memberOf MapCache
2182 function mapCacheClear() {
2186 'map': new (Map || ListCache),
2192 * Removes `key` and its value from the map.
2196 * @memberOf MapCache
2197 * @param {string} key The key of the value to remove.
2198 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2200 function mapCacheDelete(key) {
2201 var result = getMapData(this, key)['delete'](key);
2202 this.size -= result ? 1 : 0;
2207 * Gets the map value for `key`.
2211 * @memberOf MapCache
2212 * @param {string} key The key of the value to get.
2213 * @returns {*} Returns the entry value.
2215 function mapCacheGet(key) {
2216 return getMapData(this, key).get(key);
2220 * Checks if a map value for `key` exists.
2224 * @memberOf MapCache
2225 * @param {string} key The key of the entry to check.
2226 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2228 function mapCacheHas(key) {
2229 return getMapData(this, key).has(key);
2233 * Sets the map `key` to `value`.
2237 * @memberOf MapCache
2238 * @param {string} key The key of the value to set.
2239 * @param {*} value The value to set.
2240 * @returns {Object} Returns the map cache instance.
2242 function mapCacheSet(key, value) {
2243 var data = getMapData(this, key),
2246 data.set(key, value);
2247 this.size += data.size == size ? 0 : 1;
2251 // Add methods to `MapCache`.
2252 MapCache.prototype.clear = mapCacheClear;
2253 MapCache.prototype['delete'] = mapCacheDelete;
2254 MapCache.prototype.get = mapCacheGet;
2255 MapCache.prototype.has = mapCacheHas;
2256 MapCache.prototype.set = mapCacheSet;
2258 /*------------------------------------------------------------------------*/
2262 * Creates an array cache object to store unique values.
2266 * @param {Array} [values] The values to cache.
2268 function SetCache(values) {
2270 length = values == null ? 0 : values.length;
2272 this.__data__ = new MapCache;
2273 while (++index < length) {
2274 this.add(values[index]);
2279 * Adds `value` to the array cache.
2283 * @memberOf SetCache
2285 * @param {*} value The value to cache.
2286 * @returns {Object} Returns the cache instance.
2288 function setCacheAdd(value) {
2289 this.__data__.set(value, HASH_UNDEFINED);
2294 * Checks if `value` is in the array cache.
2298 * @memberOf SetCache
2299 * @param {*} value The value to search for.
2300 * @returns {number} Returns `true` if `value` is found, else `false`.
2302 function setCacheHas(value) {
2303 return this.__data__.has(value);
2306 // Add methods to `SetCache`.
2307 SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
2308 SetCache.prototype.has = setCacheHas;
2310 /*------------------------------------------------------------------------*/
2313 * Creates a stack cache object to store key-value pairs.
2317 * @param {Array} [entries] The key-value pairs to cache.
2319 function Stack(entries) {
2320 var data = this.__data__ = new ListCache(entries);
2321 this.size = data.size;
2325 * Removes all key-value entries from the stack.
2331 function stackClear() {
2332 this.__data__ = new ListCache;
2337 * Removes `key` and its value from the stack.
2342 * @param {string} key The key of the value to remove.
2343 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2345 function stackDelete(key) {
2346 var data = this.__data__,
2347 result = data['delete'](key);
2349 this.size = data.size;
2354 * Gets the stack value for `key`.
2359 * @param {string} key The key of the value to get.
2360 * @returns {*} Returns the entry value.
2362 function stackGet(key) {
2363 return this.__data__.get(key);
2367 * Checks if a stack value for `key` exists.
2372 * @param {string} key The key of the entry to check.
2373 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2375 function stackHas(key) {
2376 return this.__data__.has(key);
2380 * Sets the stack `key` to `value`.
2385 * @param {string} key The key of the value to set.
2386 * @param {*} value The value to set.
2387 * @returns {Object} Returns the stack cache instance.
2389 function stackSet(key, value) {
2390 var data = this.__data__;
2391 if (data instanceof ListCache) {
2392 var pairs = data.__data__;
2393 if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2394 pairs.push([key, value]);
2395 this.size = ++data.size;
2398 data = this.__data__ = new MapCache(pairs);
2400 data.set(key, value);
2401 this.size = data.size;
2405 // Add methods to `Stack`.
2406 Stack.prototype.clear = stackClear;
2407 Stack.prototype['delete'] = stackDelete;
2408 Stack.prototype.get = stackGet;
2409 Stack.prototype.has = stackHas;
2410 Stack.prototype.set = stackSet;
2412 /*------------------------------------------------------------------------*/
2415 * Creates an array of the enumerable property names of the array-like `value`.
2418 * @param {*} value The value to query.
2419 * @param {boolean} inherited Specify returning inherited property names.
2420 * @returns {Array} Returns the array of property names.
2422 function arrayLikeKeys(value, inherited) {
2423 var isArr = isArray(value),
2424 isArg = !isArr && isArguments(value),
2425 isBuff = !isArr && !isArg && isBuffer(value),
2426 isType = !isArr && !isArg && !isBuff && isTypedArray(value),
2427 skipIndexes = isArr || isArg || isBuff || isType,
2428 result = skipIndexes ? baseTimes(value.length, String) : [],
2429 length = result.length;
2431 for (var key in value) {
2432 if ((inherited || hasOwnProperty.call(value, key)) &&
2434 // Safari 9 has enumerable `arguments.length` in strict mode.
2436 // Node.js 0.10 has enumerable non-index properties on buffers.
2437 (isBuff && (key == 'offset' || key == 'parent')) ||
2438 // PhantomJS 2 has enumerable non-index properties on typed arrays.
2439 (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
2440 // Skip index properties.
2441 isIndex(key, length)
2450 * A specialized version of `_.sample` for arrays.
2453 * @param {Array} array The array to sample.
2454 * @returns {*} Returns the random element.
2456 function arraySample(array) {
2457 var length = array.length;
2458 return length ? array[baseRandom(0, length - 1)] : undefined;
2462 * A specialized version of `_.sampleSize` for arrays.
2465 * @param {Array} array The array to sample.
2466 * @param {number} n The number of elements to sample.
2467 * @returns {Array} Returns the random elements.
2469 function arraySampleSize(array, n) {
2470 return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
2474 * A specialized version of `_.shuffle` for arrays.
2477 * @param {Array} array The array to shuffle.
2478 * @returns {Array} Returns the new shuffled array.
2480 function arrayShuffle(array) {
2481 return shuffleSelf(copyArray(array));
2485 * This function is like `assignValue` except that it doesn't assign
2486 * `undefined` values.
2489 * @param {Object} object The object to modify.
2490 * @param {string} key The key of the property to assign.
2491 * @param {*} value The value to assign.
2493 function assignMergeValue(object, key, value) {
2494 if ((value !== undefined && !eq(object[key], value)) ||
2495 (value === undefined && !(key in object))) {
2496 baseAssignValue(object, key, value);
2501 * Assigns `value` to `key` of `object` if the existing value is not equivalent
2502 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
2503 * for equality comparisons.
2506 * @param {Object} object The object to modify.
2507 * @param {string} key The key of the property to assign.
2508 * @param {*} value The value to assign.
2510 function assignValue(object, key, value) {
2511 var objValue = object[key];
2512 if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
2513 (value === undefined && !(key in object))) {
2514 baseAssignValue(object, key, value);
2519 * Gets the index at which the `key` is found in `array` of key-value pairs.
2522 * @param {Array} array The array to inspect.
2523 * @param {*} key The key to search for.
2524 * @returns {number} Returns the index of the matched value, else `-1`.
2526 function assocIndexOf(array, key) {
2527 var length = array.length;
2529 if (eq(array[length][0], key)) {
2537 * Aggregates elements of `collection` on `accumulator` with keys transformed
2538 * by `iteratee` and values set by `setter`.
2541 * @param {Array|Object} collection The collection to iterate over.
2542 * @param {Function} setter The function to set `accumulator` values.
2543 * @param {Function} iteratee The iteratee to transform keys.
2544 * @param {Object} accumulator The initial aggregated object.
2545 * @returns {Function} Returns `accumulator`.
2547 function baseAggregator(collection, setter, iteratee, accumulator) {
2548 baseEach(collection, function(value, key, collection) {
2549 setter(accumulator, value, iteratee(value), collection);
2555 * The base implementation of `_.assign` without support for multiple sources
2556 * or `customizer` functions.
2559 * @param {Object} object The destination object.
2560 * @param {Object} source The source object.
2561 * @returns {Object} Returns `object`.
2563 function baseAssign(object, source) {
2564 return object && copyObject(source, keys(source), object);
2568 * The base implementation of `_.assignIn` without support for multiple sources
2569 * or `customizer` functions.
2572 * @param {Object} object The destination object.
2573 * @param {Object} source The source object.
2574 * @returns {Object} Returns `object`.
2576 function baseAssignIn(object, source) {
2577 return object && copyObject(source, keysIn(source), object);
2581 * The base implementation of `assignValue` and `assignMergeValue` without
2585 * @param {Object} object The object to modify.
2586 * @param {string} key The key of the property to assign.
2587 * @param {*} value The value to assign.
2589 function baseAssignValue(object, key, value) {
2590 if (key == '__proto__' && defineProperty) {
2591 defineProperty(object, key, {
2592 'configurable': true,
2598 object[key] = value;
2603 * The base implementation of `_.at` without support for individual paths.
2606 * @param {Object} object The object to iterate over.
2607 * @param {string[]} paths The property paths to pick.
2608 * @returns {Array} Returns the picked elements.
2610 function baseAt(object, paths) {
2612 length = paths.length,
2613 result = Array(length),
2614 skip = object == null;
2616 while (++index < length) {
2617 result[index] = skip ? undefined : get(object, paths[index]);
2623 * The base implementation of `_.clamp` which doesn't coerce arguments.
2626 * @param {number} number The number to clamp.
2627 * @param {number} [lower] The lower bound.
2628 * @param {number} upper The upper bound.
2629 * @returns {number} Returns the clamped number.
2631 function baseClamp(number, lower, upper) {
2632 if (number === number) {
2633 if (upper !== undefined) {
2634 number = number <= upper ? number : upper;
2636 if (lower !== undefined) {
2637 number = number >= lower ? number : lower;
2644 * The base implementation of `_.clone` and `_.cloneDeep` which tracks
2645 * traversed objects.
2648 * @param {*} value The value to clone.
2649 * @param {boolean} bitmask The bitmask flags.
2651 * 2 - Flatten inherited properties
2653 * @param {Function} [customizer] The function to customize cloning.
2654 * @param {string} [key] The key of `value`.
2655 * @param {Object} [object] The parent object of `value`.
2656 * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
2657 * @returns {*} Returns the cloned value.
2659 function baseClone(value, bitmask, customizer, key, object, stack) {
2661 isDeep = bitmask & CLONE_DEEP_FLAG,
2662 isFlat = bitmask & CLONE_FLAT_FLAG,
2663 isFull = bitmask & CLONE_SYMBOLS_FLAG;
2666 result = object ? customizer(value, key, object, stack) : customizer(value);
2668 if (result !== undefined) {
2671 if (!isObject(value)) {
2674 var isArr = isArray(value);
2676 result = initCloneArray(value);
2678 return copyArray(value, result);
2681 var tag = getTag(value),
2682 isFunc = tag == funcTag || tag == genTag;
2684 if (isBuffer(value)) {
2685 return cloneBuffer(value, isDeep);
2687 if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
2688 result = (isFlat || isFunc) ? {} : initCloneObject(value);
2691 ? copySymbolsIn(value, baseAssignIn(result, value))
2692 : copySymbols(value, baseAssign(result, value));
2695 if (!cloneableTags[tag]) {
2696 return object ? value : {};
2698 result = initCloneByTag(value, tag, baseClone, isDeep);
2701 // Check for circular references and return its corresponding clone.
2702 stack || (stack = new Stack);
2703 var stacked = stack.get(value);
2707 stack.set(value, result);
2709 var keysFunc = isFull
2710 ? (isFlat ? getAllKeysIn : getAllKeys)
2711 : (isFlat ? keysIn : keys);
2713 var props = isArr ? undefined : keysFunc(value);
2714 arrayEach(props || value, function(subValue, key) {
2717 subValue = value[key];
2719 // Recursively populate clone (susceptible to call stack limits).
2720 assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
2726 * The base implementation of `_.conforms` which doesn't clone `source`.
2729 * @param {Object} source The object of property predicates to conform to.
2730 * @returns {Function} Returns the new spec function.
2732 function baseConforms(source) {
2733 var props = keys(source);
2734 return function(object) {
2735 return baseConformsTo(object, source, props);
2740 * The base implementation of `_.conformsTo` which accepts `props` to check.
2743 * @param {Object} object The object to inspect.
2744 * @param {Object} source The object of property predicates to conform to.
2745 * @returns {boolean} Returns `true` if `object` conforms, else `false`.
2747 function baseConformsTo(object, source, props) {
2748 var length = props.length;
2749 if (object == null) {
2752 object = Object(object);
2754 var key = props[length],
2755 predicate = source[key],
2756 value = object[key];
2758 if ((value === undefined && !(key in object)) || !predicate(value)) {
2766 * The base implementation of `_.delay` and `_.defer` which accepts `args`
2767 * to provide to `func`.
2770 * @param {Function} func The function to delay.
2771 * @param {number} wait The number of milliseconds to delay invocation.
2772 * @param {Array} args The arguments to provide to `func`.
2773 * @returns {number|Object} Returns the timer id or timeout object.
2775 function baseDelay(func, wait, args) {
2776 if (typeof func != 'function') {
2777 throw new TypeError(FUNC_ERROR_TEXT);
2779 return setTimeout(function() { func.apply(undefined, args); }, wait);
2783 * The base implementation of methods like `_.difference` without support
2784 * for excluding multiple arrays or iteratee shorthands.
2787 * @param {Array} array The array to inspect.
2788 * @param {Array} values The values to exclude.
2789 * @param {Function} [iteratee] The iteratee invoked per element.
2790 * @param {Function} [comparator] The comparator invoked per element.
2791 * @returns {Array} Returns the new array of filtered values.
2793 function baseDifference(array, values, iteratee, comparator) {
2795 includes = arrayIncludes,
2797 length = array.length,
2799 valuesLength = values.length;
2805 values = arrayMap(values, baseUnary(iteratee));
2808 includes = arrayIncludesWith;
2811 else if (values.length >= LARGE_ARRAY_SIZE) {
2812 includes = cacheHas;
2814 values = new SetCache(values);
2817 while (++index < length) {
2818 var value = array[index],
2819 computed = iteratee == null ? value : iteratee(value);
2821 value = (comparator || value !== 0) ? value : 0;
2822 if (isCommon && computed === computed) {
2823 var valuesIndex = valuesLength;
2824 while (valuesIndex--) {
2825 if (values[valuesIndex] === computed) {
2831 else if (!includes(values, computed, comparator)) {
2839 * The base implementation of `_.forEach` without support for iteratee shorthands.
2842 * @param {Array|Object} collection The collection to iterate over.
2843 * @param {Function} iteratee The function invoked per iteration.
2844 * @returns {Array|Object} Returns `collection`.
2846 var baseEach = createBaseEach(baseForOwn);
2849 * The base implementation of `_.forEachRight` without support for iteratee shorthands.
2852 * @param {Array|Object} collection The collection to iterate over.
2853 * @param {Function} iteratee The function invoked per iteration.
2854 * @returns {Array|Object} Returns `collection`.
2856 var baseEachRight = createBaseEach(baseForOwnRight, true);
2859 * The base implementation of `_.every` without support for iteratee shorthands.
2862 * @param {Array|Object} collection The collection to iterate over.
2863 * @param {Function} predicate The function invoked per iteration.
2864 * @returns {boolean} Returns `true` if all elements pass the predicate check,
2867 function baseEvery(collection, predicate) {
2869 baseEach(collection, function(value, index, collection) {
2870 result = !!predicate(value, index, collection);
2877 * The base implementation of methods like `_.max` and `_.min` which accepts a
2878 * `comparator` to determine the extremum value.
2881 * @param {Array} array The array to iterate over.
2882 * @param {Function} iteratee The iteratee invoked per iteration.
2883 * @param {Function} comparator The comparator used to compare values.
2884 * @returns {*} Returns the extremum value.
2886 function baseExtremum(array, iteratee, comparator) {
2888 length = array.length;
2890 while (++index < length) {
2891 var value = array[index],
2892 current = iteratee(value);
2894 if (current != null && (computed === undefined
2895 ? (current === current && !isSymbol(current))
2896 : comparator(current, computed)
2898 var computed = current,
2906 * The base implementation of `_.fill` without an iteratee call guard.
2909 * @param {Array} array The array to fill.
2910 * @param {*} value The value to fill `array` with.
2911 * @param {number} [start=0] The start position.
2912 * @param {number} [end=array.length] The end position.
2913 * @returns {Array} Returns `array`.
2915 function baseFill(array, value, start, end) {
2916 var length = array.length;
2918 start = toInteger(start);
2920 start = -start > length ? 0 : (length + start);
2922 end = (end === undefined || end > length) ? length : toInteger(end);
2926 end = start > end ? 0 : toLength(end);
2927 while (start < end) {
2928 array[start++] = value;
2934 * The base implementation of `_.filter` without support for iteratee shorthands.
2937 * @param {Array|Object} collection The collection to iterate over.
2938 * @param {Function} predicate The function invoked per iteration.
2939 * @returns {Array} Returns the new filtered array.
2941 function baseFilter(collection, predicate) {
2943 baseEach(collection, function(value, index, collection) {
2944 if (predicate(value, index, collection)) {
2952 * The base implementation of `_.flatten` with support for restricting flattening.
2955 * @param {Array} array The array to flatten.
2956 * @param {number} depth The maximum recursion depth.
2957 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
2958 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
2959 * @param {Array} [result=[]] The initial result value.
2960 * @returns {Array} Returns the new flattened array.
2962 function baseFlatten(array, depth, predicate, isStrict, result) {
2964 length = array.length;
2966 predicate || (predicate = isFlattenable);
2967 result || (result = []);
2969 while (++index < length) {
2970 var value = array[index];
2971 if (depth > 0 && predicate(value)) {
2973 // Recursively flatten arrays (susceptible to call stack limits).
2974 baseFlatten(value, depth - 1, predicate, isStrict, result);
2976 arrayPush(result, value);
2978 } else if (!isStrict) {
2979 result[result.length] = value;
2986 * The base implementation of `baseForOwn` which iterates over `object`
2987 * properties returned by `keysFunc` and invokes `iteratee` for each property.
2988 * Iteratee functions may exit iteration early by explicitly returning `false`.
2991 * @param {Object} object The object to iterate over.
2992 * @param {Function} iteratee The function invoked per iteration.
2993 * @param {Function} keysFunc The function to get the keys of `object`.
2994 * @returns {Object} Returns `object`.
2996 var baseFor = createBaseFor();
2999 * This function is like `baseFor` except that it iterates over properties
3000 * in the opposite order.
3003 * @param {Object} object The object to iterate over.
3004 * @param {Function} iteratee The function invoked per iteration.
3005 * @param {Function} keysFunc The function to get the keys of `object`.
3006 * @returns {Object} Returns `object`.
3008 var baseForRight = createBaseFor(true);
3011 * The base implementation of `_.forOwn` without support for iteratee shorthands.
3014 * @param {Object} object The object to iterate over.
3015 * @param {Function} iteratee The function invoked per iteration.
3016 * @returns {Object} Returns `object`.
3018 function baseForOwn(object, iteratee) {
3019 return object && baseFor(object, iteratee, keys);
3023 * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
3026 * @param {Object} object The object to iterate over.
3027 * @param {Function} iteratee The function invoked per iteration.
3028 * @returns {Object} Returns `object`.
3030 function baseForOwnRight(object, iteratee) {
3031 return object && baseForRight(object, iteratee, keys);
3035 * The base implementation of `_.functions` which creates an array of
3036 * `object` function property names filtered from `props`.
3039 * @param {Object} object The object to inspect.
3040 * @param {Array} props The property names to filter.
3041 * @returns {Array} Returns the function names.
3043 function baseFunctions(object, props) {
3044 return arrayFilter(props, function(key) {
3045 return isFunction(object[key]);
3050 * The base implementation of `_.get` without support for default values.
3053 * @param {Object} object The object to query.
3054 * @param {Array|string} path The path of the property to get.
3055 * @returns {*} Returns the resolved value.
3057 function baseGet(object, path) {
3058 path = castPath(path, object);
3061 length = path.length;
3063 while (object != null && index < length) {
3064 object = object[toKey(path[index++])];
3066 return (index && index == length) ? object : undefined;
3070 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
3071 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
3072 * symbols of `object`.
3075 * @param {Object} object The object to query.
3076 * @param {Function} keysFunc The function to get the keys of `object`.
3077 * @param {Function} symbolsFunc The function to get the symbols of `object`.
3078 * @returns {Array} Returns the array of property names and symbols.
3080 function baseGetAllKeys(object, keysFunc, symbolsFunc) {
3081 var result = keysFunc(object);
3082 return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
3086 * The base implementation of `getTag` without fallbacks for buggy environments.
3089 * @param {*} value The value to query.
3090 * @returns {string} Returns the `toStringTag`.
3092 function baseGetTag(value) {
3093 if (value == null) {
3094 return value === undefined ? undefinedTag : nullTag;
3096 return (symToStringTag && symToStringTag in Object(value))
3098 : objectToString(value);
3102 * The base implementation of `_.gt` which doesn't coerce arguments.
3105 * @param {*} value The value to compare.
3106 * @param {*} other The other value to compare.
3107 * @returns {boolean} Returns `true` if `value` is greater than `other`,
3110 function baseGt(value, other) {
3111 return value > other;
3115 * The base implementation of `_.has` without support for deep paths.
3118 * @param {Object} [object] The object to query.
3119 * @param {Array|string} key The key to check.
3120 * @returns {boolean} Returns `true` if `key` exists, else `false`.
3122 function baseHas(object, key) {
3123 return object != null && hasOwnProperty.call(object, key);
3127 * The base implementation of `_.hasIn` without support for deep paths.
3130 * @param {Object} [object] The object to query.
3131 * @param {Array|string} key The key to check.
3132 * @returns {boolean} Returns `true` if `key` exists, else `false`.
3134 function baseHasIn(object, key) {
3135 return object != null && key in Object(object);
3139 * The base implementation of `_.inRange` which doesn't coerce arguments.
3142 * @param {number} number The number to check.
3143 * @param {number} start The start of the range.
3144 * @param {number} end The end of the range.
3145 * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
3147 function baseInRange(number, start, end) {
3148 return number >= nativeMin(start, end) && number < nativeMax(start, end);
3152 * The base implementation of methods like `_.intersection`, without support
3153 * for iteratee shorthands, that accepts an array of arrays to inspect.
3156 * @param {Array} arrays The arrays to inspect.
3157 * @param {Function} [iteratee] The iteratee invoked per element.
3158 * @param {Function} [comparator] The comparator invoked per element.
3159 * @returns {Array} Returns the new array of shared values.
3161 function baseIntersection(arrays, iteratee, comparator) {
3162 var includes = comparator ? arrayIncludesWith : arrayIncludes,
3163 length = arrays[0].length,
3164 othLength = arrays.length,
3165 othIndex = othLength,
3166 caches = Array(othLength),
3167 maxLength = Infinity,
3170 while (othIndex--) {
3171 var array = arrays[othIndex];
3172 if (othIndex && iteratee) {
3173 array = arrayMap(array, baseUnary(iteratee));
3175 maxLength = nativeMin(array.length, maxLength);
3176 caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
3177 ? new SetCache(othIndex && array)
3186 while (++index < length && result.length < maxLength) {
3187 var value = array[index],
3188 computed = iteratee ? iteratee(value) : value;
3190 value = (comparator || value !== 0) ? value : 0;
3192 ? cacheHas(seen, computed)
3193 : includes(result, computed, comparator)
3195 othIndex = othLength;
3196 while (--othIndex) {
3197 var cache = caches[othIndex];
3199 ? cacheHas(cache, computed)
3200 : includes(arrays[othIndex], computed, comparator))
3206 seen.push(computed);
3215 * The base implementation of `_.invert` and `_.invertBy` which inverts
3216 * `object` with values transformed by `iteratee` and set by `setter`.
3219 * @param {Object} object The object to iterate over.
3220 * @param {Function} setter The function to set `accumulator` values.
3221 * @param {Function} iteratee The iteratee to transform values.
3222 * @param {Object} accumulator The initial inverted object.
3223 * @returns {Function} Returns `accumulator`.
3225 function baseInverter(object, setter, iteratee, accumulator) {
3226 baseForOwn(object, function(value, key, object) {
3227 setter(accumulator, iteratee(value), key, object);
3233 * The base implementation of `_.invoke` without support for individual
3237 * @param {Object} object The object to query.
3238 * @param {Array|string} path The path of the method to invoke.
3239 * @param {Array} args The arguments to invoke the method with.
3240 * @returns {*} Returns the result of the invoked method.
3242 function baseInvoke(object, path, args) {
3243 path = castPath(path, object);
3244 object = parent(object, path);
3245 var func = object == null ? object : object[toKey(last(path))];
3246 return func == null ? undefined : apply(func, object, args);
3250 * The base implementation of `_.isArguments`.
3253 * @param {*} value The value to check.
3254 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3256 function baseIsArguments(value) {
3257 return isObjectLike(value) && baseGetTag(value) == argsTag;
3261 * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
3264 * @param {*} value The value to check.
3265 * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
3267 function baseIsArrayBuffer(value) {
3268 return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
3272 * The base implementation of `_.isDate` without Node.js optimizations.
3275 * @param {*} value The value to check.
3276 * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
3278 function baseIsDate(value) {
3279 return isObjectLike(value) && baseGetTag(value) == dateTag;
3283 * The base implementation of `_.isEqual` which supports partial comparisons
3284 * and tracks traversed objects.
3287 * @param {*} value The value to compare.
3288 * @param {*} other The other value to compare.
3289 * @param {boolean} bitmask The bitmask flags.
3290 * 1 - Unordered comparison
3291 * 2 - Partial comparison
3292 * @param {Function} [customizer] The function to customize comparisons.
3293 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
3294 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3296 function baseIsEqual(value, other, bitmask, customizer, stack) {
3297 if (value === other) {
3300 if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
3301 return value !== value && other !== other;
3303 return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
3307 * A specialized version of `baseIsEqual` for arrays and objects which performs
3308 * deep comparisons and tracks traversed objects enabling objects with circular
3309 * references to be compared.
3312 * @param {Object} object The object to compare.
3313 * @param {Object} other The other object to compare.
3314 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3315 * @param {Function} customizer The function to customize comparisons.
3316 * @param {Function} equalFunc The function to determine equivalents of values.
3317 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
3318 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
3320 function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
3321 var objIsArr = isArray(object),
3322 othIsArr = isArray(other),
3323 objTag = objIsArr ? arrayTag : getTag(object),
3324 othTag = othIsArr ? arrayTag : getTag(other);
3326 objTag = objTag == argsTag ? objectTag : objTag;
3327 othTag = othTag == argsTag ? objectTag : othTag;
3329 var objIsObj = objTag == objectTag,
3330 othIsObj = othTag == objectTag,
3331 isSameTag = objTag == othTag;
3333 if (isSameTag && isBuffer(object)) {
3334 if (!isBuffer(other)) {
3340 if (isSameTag && !objIsObj) {
3341 stack || (stack = new Stack);
3342 return (objIsArr || isTypedArray(object))
3343 ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
3344 : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
3346 if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
3347 var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
3348 othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
3350 if (objIsWrapped || othIsWrapped) {
3351 var objUnwrapped = objIsWrapped ? object.value() : object,
3352 othUnwrapped = othIsWrapped ? other.value() : other;
3354 stack || (stack = new Stack);
3355 return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
3361 stack || (stack = new Stack);
3362 return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
3366 * The base implementation of `_.isMap` without Node.js optimizations.
3369 * @param {*} value The value to check.
3370 * @returns {boolean} Returns `true` if `value` is a map, else `false`.
3372 function baseIsMap(value) {
3373 return isObjectLike(value) && getTag(value) == mapTag;
3377 * The base implementation of `_.isMatch` without support for iteratee shorthands.
3380 * @param {Object} object The object to inspect.
3381 * @param {Object} source The object of property values to match.
3382 * @param {Array} matchData The property names, values, and compare flags to match.
3383 * @param {Function} [customizer] The function to customize comparisons.
3384 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
3386 function baseIsMatch(object, source, matchData, customizer) {
3387 var index = matchData.length,
3389 noCustomizer = !customizer;
3391 if (object == null) {
3394 object = Object(object);
3396 var data = matchData[index];
3397 if ((noCustomizer && data[2])
3398 ? data[1] !== object[data[0]]
3399 : !(data[0] in object)
3404 while (++index < length) {
3405 data = matchData[index];
3407 objValue = object[key],
3410 if (noCustomizer && data[2]) {
3411 if (objValue === undefined && !(key in object)) {
3415 var stack = new Stack;
3417 var result = customizer(objValue, srcValue, key, object, source, stack);
3419 if (!(result === undefined
3420 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
3431 * The base implementation of `_.isNative` without bad shim checks.
3434 * @param {*} value The value to check.
3435 * @returns {boolean} Returns `true` if `value` is a native function,
3438 function baseIsNative(value) {
3439 if (!isObject(value) || isMasked(value)) {
3442 var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
3443 return pattern.test(toSource(value));
3447 * The base implementation of `_.isRegExp` without Node.js optimizations.
3450 * @param {*} value The value to check.
3451 * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
3453 function baseIsRegExp(value) {
3454 return isObjectLike(value) && baseGetTag(value) == regexpTag;
3458 * The base implementation of `_.isSet` without Node.js optimizations.
3461 * @param {*} value The value to check.
3462 * @returns {boolean} Returns `true` if `value` is a set, else `false`.
3464 function baseIsSet(value) {
3465 return isObjectLike(value) && getTag(value) == setTag;
3469 * The base implementation of `_.isTypedArray` without Node.js optimizations.
3472 * @param {*} value The value to check.
3473 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3475 function baseIsTypedArray(value) {
3476 return isObjectLike(value) &&
3477 isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
3481 * The base implementation of `_.iteratee`.
3484 * @param {*} [value=_.identity] The value to convert to an iteratee.
3485 * @returns {Function} Returns the iteratee.
3487 function baseIteratee(value) {
3488 // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
3489 // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
3490 if (typeof value == 'function') {
3493 if (value == null) {
3496 if (typeof value == 'object') {
3497 return isArray(value)
3498 ? baseMatchesProperty(value[0], value[1])
3499 : baseMatches(value);
3501 return property(value);
3505 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
3508 * @param {Object} object The object to query.
3509 * @returns {Array} Returns the array of property names.
3511 function baseKeys(object) {
3512 if (!isPrototype(object)) {
3513 return nativeKeys(object);
3516 for (var key in Object(object)) {
3517 if (hasOwnProperty.call(object, key) && key != 'constructor') {
3525 * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
3528 * @param {Object} object The object to query.
3529 * @returns {Array} Returns the array of property names.
3531 function baseKeysIn(object) {
3532 if (!isObject(object)) {
3533 return nativeKeysIn(object);
3535 var isProto = isPrototype(object),
3538 for (var key in object) {
3539 if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
3547 * The base implementation of `_.lt` which doesn't coerce arguments.
3550 * @param {*} value The value to compare.
3551 * @param {*} other The other value to compare.
3552 * @returns {boolean} Returns `true` if `value` is less than `other`,
3555 function baseLt(value, other) {
3556 return value < other;
3560 * The base implementation of `_.map` without support for iteratee shorthands.
3563 * @param {Array|Object} collection The collection to iterate over.
3564 * @param {Function} iteratee The function invoked per iteration.
3565 * @returns {Array} Returns the new mapped array.
3567 function baseMap(collection, iteratee) {
3569 result = isArrayLike(collection) ? Array(collection.length) : [];
3571 baseEach(collection, function(value, key, collection) {
3572 result[++index] = iteratee(value, key, collection);
3578 * The base implementation of `_.matches` which doesn't clone `source`.
3581 * @param {Object} source The object of property values to match.
3582 * @returns {Function} Returns the new spec function.
3584 function baseMatches(source) {
3585 var matchData = getMatchData(source);
3586 if (matchData.length == 1 && matchData[0][2]) {
3587 return matchesStrictComparable(matchData[0][0], matchData[0][1]);
3589 return function(object) {
3590 return object === source || baseIsMatch(object, source, matchData);
3595 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
3598 * @param {string} path The path of the property to get.
3599 * @param {*} srcValue The value to match.
3600 * @returns {Function} Returns the new spec function.
3602 function baseMatchesProperty(path, srcValue) {
3603 if (isKey(path) && isStrictComparable(srcValue)) {
3604 return matchesStrictComparable(toKey(path), srcValue);
3606 return function(object) {
3607 var objValue = get(object, path);
3608 return (objValue === undefined && objValue === srcValue)
3609 ? hasIn(object, path)
3610 : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
3615 * The base implementation of `_.merge` without support for multiple sources.
3618 * @param {Object} object The destination object.
3619 * @param {Object} source The source object.
3620 * @param {number} srcIndex The index of `source`.
3621 * @param {Function} [customizer] The function to customize merged values.
3622 * @param {Object} [stack] Tracks traversed source values and their merged
3625 function baseMerge(object, source, srcIndex, customizer, stack) {
3626 if (object === source) {
3629 baseFor(source, function(srcValue, key) {
3630 if (isObject(srcValue)) {
3631 stack || (stack = new Stack);
3632 baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
3635 var newValue = customizer
3636 ? customizer(object[key], srcValue, (key + ''), object, source, stack)
3639 if (newValue === undefined) {
3640 newValue = srcValue;
3642 assignMergeValue(object, key, newValue);
3648 * A specialized version of `baseMerge` for arrays and objects which performs
3649 * deep merges and tracks traversed objects enabling objects with circular
3650 * references to be merged.
3653 * @param {Object} object The destination object.
3654 * @param {Object} source The source object.
3655 * @param {string} key The key of the value to merge.
3656 * @param {number} srcIndex The index of `source`.
3657 * @param {Function} mergeFunc The function to merge values.
3658 * @param {Function} [customizer] The function to customize assigned values.
3659 * @param {Object} [stack] Tracks traversed source values and their merged
3662 function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
3663 var objValue = object[key],
3664 srcValue = source[key],
3665 stacked = stack.get(srcValue);
3668 assignMergeValue(object, key, stacked);
3671 var newValue = customizer
3672 ? customizer(objValue, srcValue, (key + ''), object, source, stack)
3675 var isCommon = newValue === undefined;
3678 var isArr = isArray(srcValue),
3679 isBuff = !isArr && isBuffer(srcValue),
3680 isTyped = !isArr && !isBuff && isTypedArray(srcValue);
3682 newValue = srcValue;
3683 if (isArr || isBuff || isTyped) {
3684 if (isArray(objValue)) {
3685 newValue = objValue;
3687 else if (isArrayLikeObject(objValue)) {
3688 newValue = copyArray(objValue);
3692 newValue = cloneBuffer(srcValue, true);
3696 newValue = cloneTypedArray(srcValue, true);
3702 else if (isPlainObject(srcValue) || isArguments(srcValue)) {
3703 newValue = objValue;
3704 if (isArguments(objValue)) {
3705 newValue = toPlainObject(objValue);
3707 else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
3708 newValue = initCloneObject(srcValue);
3716 // Recursively merge objects and arrays (susceptible to call stack limits).
3717 stack.set(srcValue, newValue);
3718 mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
3719 stack['delete'](srcValue);
3721 assignMergeValue(object, key, newValue);
3725 * The base implementation of `_.nth` which doesn't coerce arguments.
3728 * @param {Array} array The array to query.
3729 * @param {number} n The index of the element to return.
3730 * @returns {*} Returns the nth element of `array`.
3732 function baseNth(array, n) {
3733 var length = array.length;
3737 n += n < 0 ? length : 0;
3738 return isIndex(n, length) ? array[n] : undefined;
3742 * The base implementation of `_.orderBy` without param guards.
3745 * @param {Array|Object} collection The collection to iterate over.
3746 * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
3747 * @param {string[]} orders The sort orders of `iteratees`.
3748 * @returns {Array} Returns the new sorted array.
3750 function baseOrderBy(collection, iteratees, orders) {
3752 iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));
3754 var result = baseMap(collection, function(value, key, collection) {
3755 var criteria = arrayMap(iteratees, function(iteratee) {
3756 return iteratee(value);
3758 return { 'criteria': criteria, 'index': ++index, 'value': value };
3761 return baseSortBy(result, function(object, other) {
3762 return compareMultiple(object, other, orders);
3767 * The base implementation of `_.pick` without support for individual
3768 * property identifiers.
3771 * @param {Object} object The source object.
3772 * @param {string[]} paths The property paths to pick.
3773 * @returns {Object} Returns the new object.
3775 function basePick(object, paths) {
3776 return basePickBy(object, paths, function(value, path) {
3777 return hasIn(object, path);
3782 * The base implementation of `_.pickBy` without support for iteratee shorthands.
3785 * @param {Object} object The source object.
3786 * @param {string[]} paths The property paths to pick.
3787 * @param {Function} predicate The function invoked per property.
3788 * @returns {Object} Returns the new object.
3790 function basePickBy(object, paths, predicate) {
3792 length = paths.length,
3795 while (++index < length) {
3796 var path = paths[index],
3797 value = baseGet(object, path);
3799 if (predicate(value, path)) {
3800 baseSet(result, castPath(path, object), value);
3807 * A specialized version of `baseProperty` which supports deep paths.
3810 * @param {Array|string} path The path of the property to get.
3811 * @returns {Function} Returns the new accessor function.
3813 function basePropertyDeep(path) {
3814 return function(object) {
3815 return baseGet(object, path);
3820 * The base implementation of `_.pullAllBy` without support for iteratee
3824 * @param {Array} array The array to modify.
3825 * @param {Array} values The values to remove.
3826 * @param {Function} [iteratee] The iteratee invoked per element.
3827 * @param {Function} [comparator] The comparator invoked per element.
3828 * @returns {Array} Returns `array`.
3830 function basePullAll(array, values, iteratee, comparator) {
3831 var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
3833 length = values.length,
3836 if (array === values) {
3837 values = copyArray(values);
3840 seen = arrayMap(array, baseUnary(iteratee));
3842 while (++index < length) {
3844 value = values[index],
3845 computed = iteratee ? iteratee(value) : value;
3847 while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
3848 if (seen !== array) {
3849 splice.call(seen, fromIndex, 1);
3851 splice.call(array, fromIndex, 1);
3858 * The base implementation of `_.pullAt` without support for individual
3859 * indexes or capturing the removed elements.
3862 * @param {Array} array The array to modify.
3863 * @param {number[]} indexes The indexes of elements to remove.
3864 * @returns {Array} Returns `array`.
3866 function basePullAt(array, indexes) {
3867 var length = array ? indexes.length : 0,
3868 lastIndex = length - 1;
3871 var index = indexes[length];
3872 if (length == lastIndex || index !== previous) {
3873 var previous = index;
3874 if (isIndex(index)) {
3875 splice.call(array, index, 1);
3877 baseUnset(array, index);
3885 * The base implementation of `_.random` without support for returning
3886 * floating-point numbers.
3889 * @param {number} lower The lower bound.
3890 * @param {number} upper The upper bound.
3891 * @returns {number} Returns the random number.
3893 function baseRandom(lower, upper) {
3894 return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
3898 * The base implementation of `_.range` and `_.rangeRight` which doesn't
3902 * @param {number} start The start of the range.
3903 * @param {number} end The end of the range.
3904 * @param {number} step The value to increment or decrement by.
3905 * @param {boolean} [fromRight] Specify iterating from right to left.
3906 * @returns {Array} Returns the range of numbers.
3908 function baseRange(start, end, step, fromRight) {
3910 length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
3911 result = Array(length);
3914 result[fromRight ? length : ++index] = start;
3921 * The base implementation of `_.repeat` which doesn't coerce arguments.
3924 * @param {string} string The string to repeat.
3925 * @param {number} n The number of times to repeat the string.
3926 * @returns {string} Returns the repeated string.
3928 function baseRepeat(string, n) {
3930 if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
3933 // Leverage the exponentiation by squaring algorithm for a faster repeat.
3934 // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
3939 n = nativeFloor(n / 2);
3949 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
3952 * @param {Function} func The function to apply a rest parameter to.
3953 * @param {number} [start=func.length-1] The start position of the rest parameter.
3954 * @returns {Function} Returns the new function.
3956 function baseRest(func, start) {
3957 return setToString(overRest(func, start, identity), func + '');
3961 * The base implementation of `_.sample`.
3964 * @param {Array|Object} collection The collection to sample.
3965 * @returns {*} Returns the random element.
3967 function baseSample(collection) {
3968 return arraySample(values(collection));
3972 * The base implementation of `_.sampleSize` without param guards.
3975 * @param {Array|Object} collection The collection to sample.
3976 * @param {number} n The number of elements to sample.
3977 * @returns {Array} Returns the random elements.
3979 function baseSampleSize(collection, n) {
3980 var array = values(collection);
3981 return shuffleSelf(array, baseClamp(n, 0, array.length));
3985 * The base implementation of `_.set`.
3988 * @param {Object} object The object to modify.
3989 * @param {Array|string} path The path of the property to set.
3990 * @param {*} value The value to set.
3991 * @param {Function} [customizer] The function to customize path creation.
3992 * @returns {Object} Returns `object`.
3994 function baseSet(object, path, value, customizer) {
3995 if (!isObject(object)) {
3998 path = castPath(path, object);
4001 length = path.length,
4002 lastIndex = length - 1,
4005 while (nested != null && ++index < length) {
4006 var key = toKey(path[index]),
4009 if (index != lastIndex) {
4010 var objValue = nested[key];
4011 newValue = customizer ? customizer(objValue, key, nested) : undefined;
4012 if (newValue === undefined) {
4013 newValue = isObject(objValue)
4015 : (isIndex(path[index + 1]) ? [] : {});
4018 assignValue(nested, key, newValue);
4019 nested = nested[key];
4025 * The base implementation of `setData` without support for hot loop shorting.
4028 * @param {Function} func The function to associate metadata with.
4029 * @param {*} data The metadata.
4030 * @returns {Function} Returns `func`.
4032 var baseSetData = !metaMap ? identity : function(func, data) {
4033 metaMap.set(func, data);
4038 * The base implementation of `setToString` without support for hot loop shorting.
4041 * @param {Function} func The function to modify.
4042 * @param {Function} string The `toString` result.
4043 * @returns {Function} Returns `func`.
4045 var baseSetToString = !defineProperty ? identity : function(func, string) {
4046 return defineProperty(func, 'toString', {
4047 'configurable': true,
4048 'enumerable': false,
4049 'value': constant(string),
4055 * The base implementation of `_.shuffle`.
4058 * @param {Array|Object} collection The collection to shuffle.
4059 * @returns {Array} Returns the new shuffled array.
4061 function baseShuffle(collection) {
4062 return shuffleSelf(values(collection));
4066 * The base implementation of `_.slice` without an iteratee call guard.
4069 * @param {Array} array The array to slice.
4070 * @param {number} [start=0] The start position.
4071 * @param {number} [end=array.length] The end position.
4072 * @returns {Array} Returns the slice of `array`.
4074 function baseSlice(array, start, end) {
4076 length = array.length;
4079 start = -start > length ? 0 : (length + start);
4081 end = end > length ? length : end;
4085 length = start > end ? 0 : ((end - start) >>> 0);
4088 var result = Array(length);
4089 while (++index < length) {
4090 result[index] = array[index + start];
4096 * The base implementation of `_.some` without support for iteratee shorthands.
4099 * @param {Array|Object} collection The collection to iterate over.
4100 * @param {Function} predicate The function invoked per iteration.
4101 * @returns {boolean} Returns `true` if any element passes the predicate check,
4104 function baseSome(collection, predicate) {
4107 baseEach(collection, function(value, index, collection) {
4108 result = predicate(value, index, collection);
4115 * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
4116 * performs a binary search of `array` to determine the index at which `value`
4117 * should be inserted into `array` in order to maintain its sort order.
4120 * @param {Array} array The sorted array to inspect.
4121 * @param {*} value The value to evaluate.
4122 * @param {boolean} [retHighest] Specify returning the highest qualified index.
4123 * @returns {number} Returns the index at which `value` should be inserted
4126 function baseSortedIndex(array, value, retHighest) {
4128 high = array == null ? low : array.length;
4130 if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
4131 while (low < high) {
4132 var mid = (low + high) >>> 1,
4133 computed = array[mid];
4135 if (computed !== null && !isSymbol(computed) &&
4136 (retHighest ? (computed <= value) : (computed < value))) {
4144 return baseSortedIndexBy(array, value, identity, retHighest);
4148 * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
4149 * which invokes `iteratee` for `value` and each element of `array` to compute
4150 * their sort ranking. The iteratee is invoked with one argument; (value).
4153 * @param {Array} array The sorted array to inspect.
4154 * @param {*} value The value to evaluate.
4155 * @param {Function} iteratee The iteratee invoked per element.
4156 * @param {boolean} [retHighest] Specify returning the highest qualified index.
4157 * @returns {number} Returns the index at which `value` should be inserted
4160 function baseSortedIndexBy(array, value, iteratee, retHighest) {
4161 value = iteratee(value);
4164 high = array == null ? 0 : array.length,
4165 valIsNaN = value !== value,
4166 valIsNull = value === null,
4167 valIsSymbol = isSymbol(value),
4168 valIsUndefined = value === undefined;
4170 while (low < high) {
4171 var mid = nativeFloor((low + high) / 2),
4172 computed = iteratee(array[mid]),
4173 othIsDefined = computed !== undefined,
4174 othIsNull = computed === null,
4175 othIsReflexive = computed === computed,
4176 othIsSymbol = isSymbol(computed);
4179 var setLow = retHighest || othIsReflexive;
4180 } else if (valIsUndefined) {
4181 setLow = othIsReflexive && (retHighest || othIsDefined);
4182 } else if (valIsNull) {
4183 setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
4184 } else if (valIsSymbol) {
4185 setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
4186 } else if (othIsNull || othIsSymbol) {
4189 setLow = retHighest ? (computed <= value) : (computed < value);
4197 return nativeMin(high, MAX_ARRAY_INDEX);
4201 * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
4202 * support for iteratee shorthands.
4205 * @param {Array} array The array to inspect.
4206 * @param {Function} [iteratee] The iteratee invoked per element.
4207 * @returns {Array} Returns the new duplicate free array.
4209 function baseSortedUniq(array, iteratee) {
4211 length = array.length,
4215 while (++index < length) {
4216 var value = array[index],
4217 computed = iteratee ? iteratee(value) : value;
4219 if (!index || !eq(computed, seen)) {
4220 var seen = computed;
4221 result[resIndex++] = value === 0 ? 0 : value;
4228 * The base implementation of `_.toNumber` which doesn't ensure correct
4229 * conversions of binary, hexadecimal, or octal string values.
4232 * @param {*} value The value to process.
4233 * @returns {number} Returns the number.
4235 function baseToNumber(value) {
4236 if (typeof value == 'number') {
4239 if (isSymbol(value)) {
4246 * The base implementation of `_.toString` which doesn't convert nullish
4247 * values to empty strings.
4250 * @param {*} value The value to process.
4251 * @returns {string} Returns the string.
4253 function baseToString(value) {
4254 // Exit early for strings to avoid a performance hit in some environments.
4255 if (typeof value == 'string') {
4258 if (isArray(value)) {
4259 // Recursively convert values (susceptible to call stack limits).
4260 return arrayMap(value, baseToString) + '';
4262 if (isSymbol(value)) {
4263 return symbolToString ? symbolToString.call(value) : '';
4265 var result = (value + '');
4266 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
4270 * The base implementation of `_.uniqBy` without support for iteratee shorthands.
4273 * @param {Array} array The array to inspect.
4274 * @param {Function} [iteratee] The iteratee invoked per element.
4275 * @param {Function} [comparator] The comparator invoked per element.
4276 * @returns {Array} Returns the new duplicate free array.
4278 function baseUniq(array, iteratee, comparator) {
4280 includes = arrayIncludes,
4281 length = array.length,
4288 includes = arrayIncludesWith;
4290 else if (length >= LARGE_ARRAY_SIZE) {
4291 var set = iteratee ? null : createSet(array);
4293 return setToArray(set);
4296 includes = cacheHas;
4297 seen = new SetCache;
4300 seen = iteratee ? [] : result;
4303 while (++index < length) {
4304 var value = array[index],
4305 computed = iteratee ? iteratee(value) : value;
4307 value = (comparator || value !== 0) ? value : 0;
4308 if (isCommon && computed === computed) {
4309 var seenIndex = seen.length;
4310 while (seenIndex--) {
4311 if (seen[seenIndex] === computed) {
4316 seen.push(computed);
4320 else if (!includes(seen, computed, comparator)) {
4321 if (seen !== result) {
4322 seen.push(computed);
4331 * The base implementation of `_.unset`.
4334 * @param {Object} object The object to modify.
4335 * @param {Array|string} path The property path to unset.
4336 * @returns {boolean} Returns `true` if the property is deleted, else `false`.
4338 function baseUnset(object, path) {
4339 path = castPath(path, object);
4340 object = parent(object, path);
4341 return object == null || delete object[toKey(last(path))];
4345 * The base implementation of `_.update`.
4348 * @param {Object} object The object to modify.
4349 * @param {Array|string} path The path of the property to update.
4350 * @param {Function} updater The function to produce the updated value.
4351 * @param {Function} [customizer] The function to customize path creation.
4352 * @returns {Object} Returns `object`.
4354 function baseUpdate(object, path, updater, customizer) {
4355 return baseSet(object, path, updater(baseGet(object, path)), customizer);
4359 * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
4360 * without support for iteratee shorthands.
4363 * @param {Array} array The array to query.
4364 * @param {Function} predicate The function invoked per iteration.
4365 * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
4366 * @param {boolean} [fromRight] Specify iterating from right to left.
4367 * @returns {Array} Returns the slice of `array`.
4369 function baseWhile(array, predicate, isDrop, fromRight) {
4370 var length = array.length,
4371 index = fromRight ? length : -1;
4373 while ((fromRight ? index-- : ++index < length) &&
4374 predicate(array[index], index, array)) {}
4377 ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
4378 : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
4382 * The base implementation of `wrapperValue` which returns the result of
4383 * performing a sequence of actions on the unwrapped `value`, where each
4384 * successive action is supplied the return value of the previous.
4387 * @param {*} value The unwrapped value.
4388 * @param {Array} actions Actions to perform to resolve the unwrapped value.
4389 * @returns {*} Returns the resolved value.
4391 function baseWrapperValue(value, actions) {
4393 if (result instanceof LazyWrapper) {
4394 result = result.value();
4396 return arrayReduce(actions, function(result, action) {
4397 return action.func.apply(action.thisArg, arrayPush([result], action.args));
4402 * The base implementation of methods like `_.xor`, without support for
4403 * iteratee shorthands, that accepts an array of arrays to inspect.
4406 * @param {Array} arrays The arrays to inspect.
4407 * @param {Function} [iteratee] The iteratee invoked per element.
4408 * @param {Function} [comparator] The comparator invoked per element.
4409 * @returns {Array} Returns the new array of values.
4411 function baseXor(arrays, iteratee, comparator) {
4412 var length = arrays.length;
4414 return length ? baseUniq(arrays[0]) : [];
4417 result = Array(length);
4419 while (++index < length) {
4420 var array = arrays[index],
4423 while (++othIndex < length) {
4424 if (othIndex != index) {
4425 result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
4429 return baseUniq(baseFlatten(result, 1), iteratee, comparator);
4433 * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
4436 * @param {Array} props The property identifiers.
4437 * @param {Array} values The property values.
4438 * @param {Function} assignFunc The function to assign values.
4439 * @returns {Object} Returns the new object.
4441 function baseZipObject(props, values, assignFunc) {
4443 length = props.length,
4444 valsLength = values.length,
4447 while (++index < length) {
4448 var value = index < valsLength ? values[index] : undefined;
4449 assignFunc(result, props[index], value);
4455 * Casts `value` to an empty array if it's not an array like object.
4458 * @param {*} value The value to inspect.
4459 * @returns {Array|Object} Returns the cast array-like object.
4461 function castArrayLikeObject(value) {
4462 return isArrayLikeObject(value) ? value : [];
4466 * Casts `value` to `identity` if it's not a function.
4469 * @param {*} value The value to inspect.
4470 * @returns {Function} Returns cast function.
4472 function castFunction(value) {
4473 return typeof value == 'function' ? value : identity;
4477 * Casts `value` to a path array if it's not one.
4480 * @param {*} value The value to inspect.
4481 * @param {Object} [object] The object to query keys on.
4482 * @returns {Array} Returns the cast property path array.
4484 function castPath(value, object) {
4485 if (isArray(value)) {
4488 return isKey(value, object) ? [value] : stringToPath(toString(value));
4492 * A `baseRest` alias which can be replaced with `identity` by module
4493 * replacement plugins.
4497 * @param {Function} func The function to apply a rest parameter to.
4498 * @returns {Function} Returns the new function.
4500 var castRest = baseRest;
4503 * Casts `array` to a slice if it's needed.
4506 * @param {Array} array The array to inspect.
4507 * @param {number} start The start position.
4508 * @param {number} [end=array.length] The end position.
4509 * @returns {Array} Returns the cast slice.
4511 function castSlice(array, start, end) {
4512 var length = array.length;
4513 end = end === undefined ? length : end;
4514 return (!start && end >= length) ? array : baseSlice(array, start, end);
4518 * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
4521 * @param {number|Object} id The timer id or timeout object of the timer to clear.
4523 var clearTimeout = ctxClearTimeout || function(id) {
4524 return root.clearTimeout(id);
4528 * Creates a clone of `buffer`.
4531 * @param {Buffer} buffer The buffer to clone.
4532 * @param {boolean} [isDeep] Specify a deep clone.
4533 * @returns {Buffer} Returns the cloned buffer.
4535 function cloneBuffer(buffer, isDeep) {
4537 return buffer.slice();
4539 var length = buffer.length,
4540 result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
4542 buffer.copy(result);
4547 * Creates a clone of `arrayBuffer`.
4550 * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
4551 * @returns {ArrayBuffer} Returns the cloned array buffer.
4553 function cloneArrayBuffer(arrayBuffer) {
4554 var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
4555 new Uint8Array(result).set(new Uint8Array(arrayBuffer));
4560 * Creates a clone of `dataView`.
4563 * @param {Object} dataView The data view to clone.
4564 * @param {boolean} [isDeep] Specify a deep clone.
4565 * @returns {Object} Returns the cloned data view.
4567 function cloneDataView(dataView, isDeep) {
4568 var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
4569 return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
4573 * Creates a clone of `map`.
4576 * @param {Object} map The map to clone.
4577 * @param {Function} cloneFunc The function to clone values.
4578 * @param {boolean} [isDeep] Specify a deep clone.
4579 * @returns {Object} Returns the cloned map.
4581 function cloneMap(map, isDeep, cloneFunc) {
4582 var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
4583 return arrayReduce(array, addMapEntry, new map.constructor);
4587 * Creates a clone of `regexp`.
4590 * @param {Object} regexp The regexp to clone.
4591 * @returns {Object} Returns the cloned regexp.
4593 function cloneRegExp(regexp) {
4594 var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
4595 result.lastIndex = regexp.lastIndex;
4600 * Creates a clone of `set`.
4603 * @param {Object} set The set to clone.
4604 * @param {Function} cloneFunc The function to clone values.
4605 * @param {boolean} [isDeep] Specify a deep clone.
4606 * @returns {Object} Returns the cloned set.
4608 function cloneSet(set, isDeep, cloneFunc) {
4609 var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
4610 return arrayReduce(array, addSetEntry, new set.constructor);
4614 * Creates a clone of the `symbol` object.
4617 * @param {Object} symbol The symbol object to clone.
4618 * @returns {Object} Returns the cloned symbol object.
4620 function cloneSymbol(symbol) {
4621 return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
4625 * Creates a clone of `typedArray`.
4628 * @param {Object} typedArray The typed array to clone.
4629 * @param {boolean} [isDeep] Specify a deep clone.
4630 * @returns {Object} Returns the cloned typed array.
4632 function cloneTypedArray(typedArray, isDeep) {
4633 var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
4634 return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
4638 * Compares values to sort them in ascending order.
4641 * @param {*} value The value to compare.
4642 * @param {*} other The other value to compare.
4643 * @returns {number} Returns the sort order indicator for `value`.
4645 function compareAscending(value, other) {
4646 if (value !== other) {
4647 var valIsDefined = value !== undefined,
4648 valIsNull = value === null,
4649 valIsReflexive = value === value,
4650 valIsSymbol = isSymbol(value);
4652 var othIsDefined = other !== undefined,
4653 othIsNull = other === null,
4654 othIsReflexive = other === other,
4655 othIsSymbol = isSymbol(other);
4657 if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
4658 (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
4659 (valIsNull && othIsDefined && othIsReflexive) ||
4660 (!valIsDefined && othIsReflexive) ||
4664 if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
4665 (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
4666 (othIsNull && valIsDefined && valIsReflexive) ||
4667 (!othIsDefined && valIsReflexive) ||
4676 * Used by `_.orderBy` to compare multiple properties of a value to another
4677 * and stable sort them.
4679 * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
4680 * specify an order of "desc" for descending or "asc" for ascending sort order
4681 * of corresponding values.
4684 * @param {Object} object The object to compare.
4685 * @param {Object} other The other object to compare.
4686 * @param {boolean[]|string[]} orders The order to sort by for each property.
4687 * @returns {number} Returns the sort order indicator for `object`.
4689 function compareMultiple(object, other, orders) {
4691 objCriteria = object.criteria,
4692 othCriteria = other.criteria,
4693 length = objCriteria.length,
4694 ordersLength = orders.length;
4696 while (++index < length) {
4697 var result = compareAscending(objCriteria[index], othCriteria[index]);
4699 if (index >= ordersLength) {
4702 var order = orders[index];
4703 return result * (order == 'desc' ? -1 : 1);
4706 // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
4707 // that causes it, under certain circumstances, to provide the same value for
4708 // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
4709 // for more details.
4711 // This also ensures a stable sort in V8 and other engines.
4712 // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
4713 return object.index - other.index;
4717 * Creates an array that is the composition of partially applied arguments,
4718 * placeholders, and provided arguments into a single array of arguments.
4721 * @param {Array} args The provided arguments.
4722 * @param {Array} partials The arguments to prepend to those provided.
4723 * @param {Array} holders The `partials` placeholder indexes.
4724 * @params {boolean} [isCurried] Specify composing for a curried function.
4725 * @returns {Array} Returns the new array of composed arguments.
4727 function composeArgs(args, partials, holders, isCurried) {
4729 argsLength = args.length,
4730 holdersLength = holders.length,
4732 leftLength = partials.length,
4733 rangeLength = nativeMax(argsLength - holdersLength, 0),
4734 result = Array(leftLength + rangeLength),
4735 isUncurried = !isCurried;
4737 while (++leftIndex < leftLength) {
4738 result[leftIndex] = partials[leftIndex];
4740 while (++argsIndex < holdersLength) {
4741 if (isUncurried || argsIndex < argsLength) {
4742 result[holders[argsIndex]] = args[argsIndex];
4745 while (rangeLength--) {
4746 result[leftIndex++] = args[argsIndex++];
4752 * This function is like `composeArgs` except that the arguments composition
4753 * is tailored for `_.partialRight`.
4756 * @param {Array} args The provided arguments.
4757 * @param {Array} partials The arguments to append to those provided.
4758 * @param {Array} holders The `partials` placeholder indexes.
4759 * @params {boolean} [isCurried] Specify composing for a curried function.
4760 * @returns {Array} Returns the new array of composed arguments.
4762 function composeArgsRight(args, partials, holders, isCurried) {
4764 argsLength = args.length,
4766 holdersLength = holders.length,
4768 rightLength = partials.length,
4769 rangeLength = nativeMax(argsLength - holdersLength, 0),
4770 result = Array(rangeLength + rightLength),
4771 isUncurried = !isCurried;
4773 while (++argsIndex < rangeLength) {
4774 result[argsIndex] = args[argsIndex];
4776 var offset = argsIndex;
4777 while (++rightIndex < rightLength) {
4778 result[offset + rightIndex] = partials[rightIndex];
4780 while (++holdersIndex < holdersLength) {
4781 if (isUncurried || argsIndex < argsLength) {
4782 result[offset + holders[holdersIndex]] = args[argsIndex++];
4789 * Copies the values of `source` to `array`.
4792 * @param {Array} source The array to copy values from.
4793 * @param {Array} [array=[]] The array to copy values to.
4794 * @returns {Array} Returns `array`.
4796 function copyArray(source, array) {
4798 length = source.length;
4800 array || (array = Array(length));
4801 while (++index < length) {
4802 array[index] = source[index];
4808 * Copies properties of `source` to `object`.
4811 * @param {Object} source The object to copy properties from.
4812 * @param {Array} props The property identifiers to copy.
4813 * @param {Object} [object={}] The object to copy properties to.
4814 * @param {Function} [customizer] The function to customize copied values.
4815 * @returns {Object} Returns `object`.
4817 function copyObject(source, props, object, customizer) {
4818 var isNew = !object;
4819 object || (object = {});
4822 length = props.length;
4824 while (++index < length) {
4825 var key = props[index];
4827 var newValue = customizer
4828 ? customizer(object[key], source[key], key, object, source)
4831 if (newValue === undefined) {
4832 newValue = source[key];
4835 baseAssignValue(object, key, newValue);
4837 assignValue(object, key, newValue);
4844 * Copies own symbols of `source` to `object`.
4847 * @param {Object} source The object to copy symbols from.
4848 * @param {Object} [object={}] The object to copy symbols to.
4849 * @returns {Object} Returns `object`.
4851 function copySymbols(source, object) {
4852 return copyObject(source, getSymbols(source), object);
4856 * Copies own and inherited symbols of `source` to `object`.
4859 * @param {Object} source The object to copy symbols from.
4860 * @param {Object} [object={}] The object to copy symbols to.
4861 * @returns {Object} Returns `object`.
4863 function copySymbolsIn(source, object) {
4864 return copyObject(source, getSymbolsIn(source), object);
4868 * Creates a function like `_.groupBy`.
4871 * @param {Function} setter The function to set accumulator values.
4872 * @param {Function} [initializer] The accumulator object initializer.
4873 * @returns {Function} Returns the new aggregator function.
4875 function createAggregator(setter, initializer) {
4876 return function(collection, iteratee) {
4877 var func = isArray(collection) ? arrayAggregator : baseAggregator,
4878 accumulator = initializer ? initializer() : {};
4880 return func(collection, setter, getIteratee(iteratee, 2), accumulator);
4885 * Creates a function like `_.assign`.
4888 * @param {Function} assigner The function to assign values.
4889 * @returns {Function} Returns the new assigner function.
4891 function createAssigner(assigner) {
4892 return baseRest(function(object, sources) {
4894 length = sources.length,
4895 customizer = length > 1 ? sources[length - 1] : undefined,
4896 guard = length > 2 ? sources[2] : undefined;
4898 customizer = (assigner.length > 3 && typeof customizer == 'function')
4899 ? (length--, customizer)
4902 if (guard && isIterateeCall(sources[0], sources[1], guard)) {
4903 customizer = length < 3 ? undefined : customizer;
4906 object = Object(object);
4907 while (++index < length) {
4908 var source = sources[index];
4910 assigner(object, source, index, customizer);
4918 * Creates a `baseEach` or `baseEachRight` function.
4921 * @param {Function} eachFunc The function to iterate over a collection.
4922 * @param {boolean} [fromRight] Specify iterating from right to left.
4923 * @returns {Function} Returns the new base function.
4925 function createBaseEach(eachFunc, fromRight) {
4926 return function(collection, iteratee) {
4927 if (collection == null) {
4930 if (!isArrayLike(collection)) {
4931 return eachFunc(collection, iteratee);
4933 var length = collection.length,
4934 index = fromRight ? length : -1,
4935 iterable = Object(collection);
4937 while ((fromRight ? index-- : ++index < length)) {
4938 if (iteratee(iterable[index], index, iterable) === false) {
4947 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
4950 * @param {boolean} [fromRight] Specify iterating from right to left.
4951 * @returns {Function} Returns the new base function.
4953 function createBaseFor(fromRight) {
4954 return function(object, iteratee, keysFunc) {
4956 iterable = Object(object),
4957 props = keysFunc(object),
4958 length = props.length;
4961 var key = props[fromRight ? length : ++index];
4962 if (iteratee(iterable[key], key, iterable) === false) {
4971 * Creates a function that wraps `func` to invoke it with the optional `this`
4972 * binding of `thisArg`.
4975 * @param {Function} func The function to wrap.
4976 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
4977 * @param {*} [thisArg] The `this` binding of `func`.
4978 * @returns {Function} Returns the new wrapped function.
4980 function createBind(func, bitmask, thisArg) {
4981 var isBind = bitmask & WRAP_BIND_FLAG,
4982 Ctor = createCtor(func);
4984 function wrapper() {
4985 var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
4986 return fn.apply(isBind ? thisArg : this, arguments);
4992 * Creates a function like `_.lowerFirst`.
4995 * @param {string} methodName The name of the `String` case method to use.
4996 * @returns {Function} Returns the new case function.
4998 function createCaseFirst(methodName) {
4999 return function(string) {
5000 string = toString(string);
5002 var strSymbols = hasUnicode(string)
5003 ? stringToArray(string)
5006 var chr = strSymbols
5010 var trailing = strSymbols
5011 ? castSlice(strSymbols, 1).join('')
5014 return chr[methodName]() + trailing;
5019 * Creates a function like `_.camelCase`.
5022 * @param {Function} callback The function to combine each word.
5023 * @returns {Function} Returns the new compounder function.
5025 function createCompounder(callback) {
5026 return function(string) {
5027 return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
5032 * Creates a function that produces an instance of `Ctor` regardless of
5033 * whether it was invoked as part of a `new` expression or by `call` or `apply`.
5036 * @param {Function} Ctor The constructor to wrap.
5037 * @returns {Function} Returns the new wrapped function.
5039 function createCtor(Ctor) {
5041 // Use a `switch` statement to work with class constructors. See
5042 // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
5043 // for more details.
5044 var args = arguments;
5045 switch (args.length) {
5046 case 0: return new Ctor;
5047 case 1: return new Ctor(args[0]);
5048 case 2: return new Ctor(args[0], args[1]);
5049 case 3: return new Ctor(args[0], args[1], args[2]);
5050 case 4: return new Ctor(args[0], args[1], args[2], args[3]);
5051 case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
5052 case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
5053 case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
5055 var thisBinding = baseCreate(Ctor.prototype),
5056 result = Ctor.apply(thisBinding, args);
5058 // Mimic the constructor's `return` behavior.
5059 // See https://es5.github.io/#x13.2.2 for more details.
5060 return isObject(result) ? result : thisBinding;
5065 * Creates a function that wraps `func` to enable currying.
5068 * @param {Function} func The function to wrap.
5069 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5070 * @param {number} arity The arity of `func`.
5071 * @returns {Function} Returns the new wrapped function.
5073 function createCurry(func, bitmask, arity) {
5074 var Ctor = createCtor(func);
5076 function wrapper() {
5077 var length = arguments.length,
5078 args = Array(length),
5080 placeholder = getHolder(wrapper);
5083 args[index] = arguments[index];
5085 var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
5087 : replaceHolders(args, placeholder);
5089 length -= holders.length;
5090 if (length < arity) {
5091 return createRecurry(
5092 func, bitmask, createHybrid, wrapper.placeholder, undefined,
5093 args, holders, undefined, undefined, arity - length);
5095 var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5096 return apply(fn, this, args);
5102 * Creates a `_.find` or `_.findLast` function.
5105 * @param {Function} findIndexFunc The function to find the collection index.
5106 * @returns {Function} Returns the new find function.
5108 function createFind(findIndexFunc) {
5109 return function(collection, predicate, fromIndex) {
5110 var iterable = Object(collection);
5111 if (!isArrayLike(collection)) {
5112 var iteratee = getIteratee(predicate, 3);
5113 collection = keys(collection);
5114 predicate = function(key) { return iteratee(iterable[key], key, iterable); };
5116 var index = findIndexFunc(collection, predicate, fromIndex);
5117 return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
5122 * Creates a `_.flow` or `_.flowRight` function.
5125 * @param {boolean} [fromRight] Specify iterating from right to left.
5126 * @returns {Function} Returns the new flow function.
5128 function createFlow(fromRight) {
5129 return flatRest(function(funcs) {
5130 var length = funcs.length,
5132 prereq = LodashWrapper.prototype.thru;
5138 var func = funcs[index];
5139 if (typeof func != 'function') {
5140 throw new TypeError(FUNC_ERROR_TEXT);
5142 if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
5143 var wrapper = new LodashWrapper([], true);
5146 index = wrapper ? index : length;
5147 while (++index < length) {
5148 func = funcs[index];
5150 var funcName = getFuncName(func),
5151 data = funcName == 'wrapper' ? getData(func) : undefined;
5153 if (data && isLaziable(data[0]) &&
5154 data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
5155 !data[4].length && data[9] == 1
5157 wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
5159 wrapper = (func.length == 1 && isLaziable(func))
5160 ? wrapper[funcName]()
5161 : wrapper.thru(func);
5165 var args = arguments,
5168 if (wrapper && args.length == 1 && isArray(value)) {
5169 return wrapper.plant(value).value();
5172 result = length ? funcs[index].apply(this, args) : value;
5174 while (++index < length) {
5175 result = funcs[index].call(this, result);
5183 * Creates a function that wraps `func` to invoke it with optional `this`
5184 * binding of `thisArg`, partial application, and currying.
5187 * @param {Function|string} func The function or method name to wrap.
5188 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5189 * @param {*} [thisArg] The `this` binding of `func`.
5190 * @param {Array} [partials] The arguments to prepend to those provided to
5192 * @param {Array} [holders] The `partials` placeholder indexes.
5193 * @param {Array} [partialsRight] The arguments to append to those provided
5194 * to the new function.
5195 * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
5196 * @param {Array} [argPos] The argument positions of the new function.
5197 * @param {number} [ary] The arity cap of `func`.
5198 * @param {number} [arity] The arity of `func`.
5199 * @returns {Function} Returns the new wrapped function.
5201 function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
5202 var isAry = bitmask & WRAP_ARY_FLAG,
5203 isBind = bitmask & WRAP_BIND_FLAG,
5204 isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
5205 isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
5206 isFlip = bitmask & WRAP_FLIP_FLAG,
5207 Ctor = isBindKey ? undefined : createCtor(func);
5209 function wrapper() {
5210 var length = arguments.length,
5211 args = Array(length),
5215 args[index] = arguments[index];
5218 var placeholder = getHolder(wrapper),
5219 holdersCount = countHolders(args, placeholder);
5222 args = composeArgs(args, partials, holders, isCurried);
5224 if (partialsRight) {
5225 args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
5227 length -= holdersCount;
5228 if (isCurried && length < arity) {
5229 var newHolders = replaceHolders(args, placeholder);
5230 return createRecurry(
5231 func, bitmask, createHybrid, wrapper.placeholder, thisArg,
5232 args, newHolders, argPos, ary, arity - length
5235 var thisBinding = isBind ? thisArg : this,
5236 fn = isBindKey ? thisBinding[func] : func;
5238 length = args.length;
5240 args = reorder(args, argPos);
5241 } else if (isFlip && length > 1) {
5244 if (isAry && ary < length) {
5247 if (this && this !== root && this instanceof wrapper) {
5248 fn = Ctor || createCtor(fn);
5250 return fn.apply(thisBinding, args);
5256 * Creates a function like `_.invertBy`.
5259 * @param {Function} setter The function to set accumulator values.
5260 * @param {Function} toIteratee The function to resolve iteratees.
5261 * @returns {Function} Returns the new inverter function.
5263 function createInverter(setter, toIteratee) {
5264 return function(object, iteratee) {
5265 return baseInverter(object, setter, toIteratee(iteratee), {});
5270 * Creates a function that performs a mathematical operation on two values.
5273 * @param {Function} operator The function to perform the operation.
5274 * @param {number} [defaultValue] The value used for `undefined` arguments.
5275 * @returns {Function} Returns the new mathematical operation function.
5277 function createMathOperation(operator, defaultValue) {
5278 return function(value, other) {
5280 if (value === undefined && other === undefined) {
5281 return defaultValue;
5283 if (value !== undefined) {
5286 if (other !== undefined) {
5287 if (result === undefined) {
5290 if (typeof value == 'string' || typeof other == 'string') {
5291 value = baseToString(value);
5292 other = baseToString(other);
5294 value = baseToNumber(value);
5295 other = baseToNumber(other);
5297 result = operator(value, other);
5304 * Creates a function like `_.over`.
5307 * @param {Function} arrayFunc The function to iterate over iteratees.
5308 * @returns {Function} Returns the new over function.
5310 function createOver(arrayFunc) {
5311 return flatRest(function(iteratees) {
5312 iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
5313 return baseRest(function(args) {
5315 return arrayFunc(iteratees, function(iteratee) {
5316 return apply(iteratee, thisArg, args);
5323 * Creates the padding for `string` based on `length`. The `chars` string
5324 * is truncated if the number of characters exceeds `length`.
5327 * @param {number} length The padding length.
5328 * @param {string} [chars=' '] The string used as padding.
5329 * @returns {string} Returns the padding for `string`.
5331 function createPadding(length, chars) {
5332 chars = chars === undefined ? ' ' : baseToString(chars);
5334 var charsLength = chars.length;
5335 if (charsLength < 2) {
5336 return charsLength ? baseRepeat(chars, length) : chars;
5338 var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
5339 return hasUnicode(chars)
5340 ? castSlice(stringToArray(result), 0, length).join('')
5341 : result.slice(0, length);
5345 * Creates a function that wraps `func` to invoke it with the `this` binding
5346 * of `thisArg` and `partials` prepended to the arguments it receives.
5349 * @param {Function} func The function to wrap.
5350 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5351 * @param {*} thisArg The `this` binding of `func`.
5352 * @param {Array} partials The arguments to prepend to those provided to
5354 * @returns {Function} Returns the new wrapped function.
5356 function createPartial(func, bitmask, thisArg, partials) {
5357 var isBind = bitmask & WRAP_BIND_FLAG,
5358 Ctor = createCtor(func);
5360 function wrapper() {
5362 argsLength = arguments.length,
5364 leftLength = partials.length,
5365 args = Array(leftLength + argsLength),
5366 fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5368 while (++leftIndex < leftLength) {
5369 args[leftIndex] = partials[leftIndex];
5371 while (argsLength--) {
5372 args[leftIndex++] = arguments[++argsIndex];
5374 return apply(fn, isBind ? thisArg : this, args);
5380 * Creates a `_.range` or `_.rangeRight` function.
5383 * @param {boolean} [fromRight] Specify iterating from right to left.
5384 * @returns {Function} Returns the new range function.
5386 function createRange(fromRight) {
5387 return function(start, end, step) {
5388 if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
5389 end = step = undefined;
5391 // Ensure the sign of `-0` is preserved.
5392 start = toFinite(start);
5393 if (end === undefined) {
5397 end = toFinite(end);
5399 step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
5400 return baseRange(start, end, step, fromRight);
5405 * Creates a function that performs a relational operation on two values.
5408 * @param {Function} operator The function to perform the operation.
5409 * @returns {Function} Returns the new relational operation function.
5411 function createRelationalOperation(operator) {
5412 return function(value, other) {
5413 if (!(typeof value == 'string' && typeof other == 'string')) {
5414 value = toNumber(value);
5415 other = toNumber(other);
5417 return operator(value, other);
5422 * Creates a function that wraps `func` to continue currying.
5425 * @param {Function} func The function to wrap.
5426 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5427 * @param {Function} wrapFunc The function to create the `func` wrapper.
5428 * @param {*} placeholder The placeholder value.
5429 * @param {*} [thisArg] The `this` binding of `func`.
5430 * @param {Array} [partials] The arguments to prepend to those provided to
5432 * @param {Array} [holders] The `partials` placeholder indexes.
5433 * @param {Array} [argPos] The argument positions of the new function.
5434 * @param {number} [ary] The arity cap of `func`.
5435 * @param {number} [arity] The arity of `func`.
5436 * @returns {Function} Returns the new wrapped function.
5438 function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
5439 var isCurry = bitmask & WRAP_CURRY_FLAG,
5440 newHolders = isCurry ? holders : undefined,
5441 newHoldersRight = isCurry ? undefined : holders,
5442 newPartials = isCurry ? partials : undefined,
5443 newPartialsRight = isCurry ? undefined : partials;
5445 bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
5446 bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
5448 if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
5449 bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
5452 func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
5453 newHoldersRight, argPos, ary, arity
5456 var result = wrapFunc.apply(undefined, newData);
5457 if (isLaziable(func)) {
5458 setData(result, newData);
5460 result.placeholder = placeholder;
5461 return setWrapToString(result, func, bitmask);
5465 * Creates a function like `_.round`.
5468 * @param {string} methodName The name of the `Math` method to use when rounding.
5469 * @returns {Function} Returns the new round function.
5471 function createRound(methodName) {
5472 var func = Math[methodName];
5473 return function(number, precision) {
5474 number = toNumber(number);
5475 precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
5477 // Shift with exponential notation to avoid floating-point issues.
5478 // See [MDN](https://mdn.io/round#Examples) for more details.
5479 var pair = (toString(number) + 'e').split('e'),
5480 value = func(pair[0] + 'e' + (+pair[1] + precision));
5482 pair = (toString(value) + 'e').split('e');
5483 return +(pair[0] + 'e' + (+pair[1] - precision));
5485 return func(number);
5490 * Creates a set object of `values`.
5493 * @param {Array} values The values to add to the set.
5494 * @returns {Object} Returns the new set.
5496 var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
5497 return new Set(values);
5501 * Creates a `_.toPairs` or `_.toPairsIn` function.
5504 * @param {Function} keysFunc The function to get the keys of a given object.
5505 * @returns {Function} Returns the new pairs function.
5507 function createToPairs(keysFunc) {
5508 return function(object) {
5509 var tag = getTag(object);
5510 if (tag == mapTag) {
5511 return mapToArray(object);
5513 if (tag == setTag) {
5514 return setToPairs(object);
5516 return baseToPairs(object, keysFunc(object));
5521 * Creates a function that either curries or invokes `func` with optional
5522 * `this` binding and partially applied arguments.
5525 * @param {Function|string} func The function or method name to wrap.
5526 * @param {number} bitmask The bitmask flags.
5529 * 4 - `_.curry` or `_.curryRight` of a bound function
5531 * 16 - `_.curryRight`
5533 * 64 - `_.partialRight`
5537 * @param {*} [thisArg] The `this` binding of `func`.
5538 * @param {Array} [partials] The arguments to be partially applied.
5539 * @param {Array} [holders] The `partials` placeholder indexes.
5540 * @param {Array} [argPos] The argument positions of the new function.
5541 * @param {number} [ary] The arity cap of `func`.
5542 * @param {number} [arity] The arity of `func`.
5543 * @returns {Function} Returns the new wrapped function.
5545 function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
5546 var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
5547 if (!isBindKey && typeof func != 'function') {
5548 throw new TypeError(FUNC_ERROR_TEXT);
5550 var length = partials ? partials.length : 0;
5552 bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
5553 partials = holders = undefined;
5555 ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
5556 arity = arity === undefined ? arity : toInteger(arity);
5557 length -= holders ? holders.length : 0;
5559 if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
5560 var partialsRight = partials,
5561 holdersRight = holders;
5563 partials = holders = undefined;
5565 var data = isBindKey ? undefined : getData(func);
5568 func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
5573 mergeData(newData, data);
5576 bitmask = newData[1];
5577 thisArg = newData[2];
5578 partials = newData[3];
5579 holders = newData[4];
5580 arity = newData[9] = newData[9] === undefined
5581 ? (isBindKey ? 0 : func.length)
5582 : nativeMax(newData[9] - length, 0);
5584 if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
5585 bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
5587 if (!bitmask || bitmask == WRAP_BIND_FLAG) {
5588 var result = createBind(func, bitmask, thisArg);
5589 } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
5590 result = createCurry(func, bitmask, arity);
5591 } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
5592 result = createPartial(func, bitmask, thisArg, partials);
5594 result = createHybrid.apply(undefined, newData);
5596 var setter = data ? baseSetData : setData;
5597 return setWrapToString(setter(result, newData), func, bitmask);
5601 * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
5602 * of source objects to the destination object for all destination properties
5603 * that resolve to `undefined`.
5606 * @param {*} objValue The destination value.
5607 * @param {*} srcValue The source value.
5608 * @param {string} key The key of the property to assign.
5609 * @param {Object} object The parent object of `objValue`.
5610 * @returns {*} Returns the value to assign.
5612 function customDefaultsAssignIn(objValue, srcValue, key, object) {
5613 if (objValue === undefined ||
5614 (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
5621 * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
5622 * objects into destination objects that are passed thru.
5625 * @param {*} objValue The destination value.
5626 * @param {*} srcValue The source value.
5627 * @param {string} key The key of the property to merge.
5628 * @param {Object} object The parent object of `objValue`.
5629 * @param {Object} source The parent object of `srcValue`.
5630 * @param {Object} [stack] Tracks traversed source values and their merged
5632 * @returns {*} Returns the value to assign.
5634 function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
5635 if (isObject(objValue) && isObject(srcValue)) {
5636 // Recursively merge objects and arrays (susceptible to call stack limits).
5637 stack.set(srcValue, objValue);
5638 baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);
5639 stack['delete'](srcValue);
5645 * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
5649 * @param {*} value The value to inspect.
5650 * @param {string} key The key of the property to inspect.
5651 * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
5653 function customOmitClone(value) {
5654 return isPlainObject(value) ? undefined : value;
5658 * A specialized version of `baseIsEqualDeep` for arrays with support for
5659 * partial deep comparisons.
5662 * @param {Array} array The array to compare.
5663 * @param {Array} other The other array to compare.
5664 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5665 * @param {Function} customizer The function to customize comparisons.
5666 * @param {Function} equalFunc The function to determine equivalents of values.
5667 * @param {Object} stack Tracks traversed `array` and `other` objects.
5668 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
5670 function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
5671 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5672 arrLength = array.length,
5673 othLength = other.length;
5675 if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
5678 // Assume cyclic values are equal.
5679 var stacked = stack.get(array);
5680 if (stacked && stack.get(other)) {
5681 return stacked == other;
5685 seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
5687 stack.set(array, other);
5688 stack.set(other, array);
5690 // Ignore non-index properties.
5691 while (++index < arrLength) {
5692 var arrValue = array[index],
5693 othValue = other[index];
5696 var compared = isPartial
5697 ? customizer(othValue, arrValue, index, other, array, stack)
5698 : customizer(arrValue, othValue, index, array, other, stack);
5700 if (compared !== undefined) {
5707 // Recursively compare arrays (susceptible to call stack limits).
5709 if (!arraySome(other, function(othValue, othIndex) {
5710 if (!cacheHas(seen, othIndex) &&
5711 (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
5712 return seen.push(othIndex);
5719 arrValue === othValue ||
5720 equalFunc(arrValue, othValue, bitmask, customizer, stack)
5726 stack['delete'](array);
5727 stack['delete'](other);
5732 * A specialized version of `baseIsEqualDeep` for comparing objects of
5733 * the same `toStringTag`.
5735 * **Note:** This function only supports comparing values with tags of
5736 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
5739 * @param {Object} object The object to compare.
5740 * @param {Object} other The other object to compare.
5741 * @param {string} tag The `toStringTag` of the objects to compare.
5742 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5743 * @param {Function} customizer The function to customize comparisons.
5744 * @param {Function} equalFunc The function to determine equivalents of values.
5745 * @param {Object} stack Tracks traversed `object` and `other` objects.
5746 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5748 function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
5751 if ((object.byteLength != other.byteLength) ||
5752 (object.byteOffset != other.byteOffset)) {
5755 object = object.buffer;
5756 other = other.buffer;
5758 case arrayBufferTag:
5759 if ((object.byteLength != other.byteLength) ||
5760 !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
5768 // Coerce booleans to `1` or `0` and dates to milliseconds.
5769 // Invalid dates are coerced to `NaN`.
5770 return eq(+object, +other);
5773 return object.name == other.name && object.message == other.message;
5777 // Coerce regexes to strings and treat strings, primitives and objects,
5778 // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
5779 // for more details.
5780 return object == (other + '');
5783 var convert = mapToArray;
5786 var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
5787 convert || (convert = setToArray);
5789 if (object.size != other.size && !isPartial) {
5792 // Assume cyclic values are equal.
5793 var stacked = stack.get(object);
5795 return stacked == other;
5797 bitmask |= COMPARE_UNORDERED_FLAG;
5799 // Recursively compare objects (susceptible to call stack limits).
5800 stack.set(object, other);
5801 var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
5802 stack['delete'](object);
5806 if (symbolValueOf) {
5807 return symbolValueOf.call(object) == symbolValueOf.call(other);
5814 * A specialized version of `baseIsEqualDeep` for objects with support for
5815 * partial deep comparisons.
5818 * @param {Object} object The object to compare.
5819 * @param {Object} other The other object to compare.
5820 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5821 * @param {Function} customizer The function to customize comparisons.
5822 * @param {Function} equalFunc The function to determine equivalents of values.
5823 * @param {Object} stack Tracks traversed `object` and `other` objects.
5824 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5826 function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
5827 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5828 objProps = getAllKeys(object),
5829 objLength = objProps.length,
5830 othProps = getAllKeys(other),
5831 othLength = othProps.length;
5833 if (objLength != othLength && !isPartial) {
5836 var index = objLength;
5838 var key = objProps[index];
5839 if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
5843 // Assume cyclic values are equal.
5844 var stacked = stack.get(object);
5845 if (stacked && stack.get(other)) {
5846 return stacked == other;
5849 stack.set(object, other);
5850 stack.set(other, object);
5852 var skipCtor = isPartial;
5853 while (++index < objLength) {
5854 key = objProps[index];
5855 var objValue = object[key],
5856 othValue = other[key];
5859 var compared = isPartial
5860 ? customizer(othValue, objValue, key, other, object, stack)
5861 : customizer(objValue, othValue, key, object, other, stack);
5863 // Recursively compare objects (susceptible to call stack limits).
5864 if (!(compared === undefined
5865 ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
5871 skipCtor || (skipCtor = key == 'constructor');
5873 if (result && !skipCtor) {
5874 var objCtor = object.constructor,
5875 othCtor = other.constructor;
5877 // Non `Object` object instances with different constructors are not equal.
5878 if (objCtor != othCtor &&
5879 ('constructor' in object && 'constructor' in other) &&
5880 !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
5881 typeof othCtor == 'function' && othCtor instanceof othCtor)) {
5885 stack['delete'](object);
5886 stack['delete'](other);
5891 * A specialized version of `baseRest` which flattens the rest array.
5894 * @param {Function} func The function to apply a rest parameter to.
5895 * @returns {Function} Returns the new function.
5897 function flatRest(func) {
5898 return setToString(overRest(func, undefined, flatten), func + '');
5902 * Creates an array of own enumerable property names and symbols of `object`.
5905 * @param {Object} object The object to query.
5906 * @returns {Array} Returns the array of property names and symbols.
5908 function getAllKeys(object) {
5909 return baseGetAllKeys(object, keys, getSymbols);
5913 * Creates an array of own and inherited enumerable property names and
5914 * symbols of `object`.
5917 * @param {Object} object The object to query.
5918 * @returns {Array} Returns the array of property names and symbols.
5920 function getAllKeysIn(object) {
5921 return baseGetAllKeys(object, keysIn, getSymbolsIn);
5925 * Gets metadata for `func`.
5928 * @param {Function} func The function to query.
5929 * @returns {*} Returns the metadata for `func`.
5931 var getData = !metaMap ? noop : function(func) {
5932 return metaMap.get(func);
5936 * Gets the name of `func`.
5939 * @param {Function} func The function to query.
5940 * @returns {string} Returns the function name.
5942 function getFuncName(func) {
5943 var result = (func.name + ''),
5944 array = realNames[result],
5945 length = hasOwnProperty.call(realNames, result) ? array.length : 0;
5948 var data = array[length],
5949 otherFunc = data.func;
5950 if (otherFunc == null || otherFunc == func) {
5958 * Gets the argument placeholder value for `func`.
5961 * @param {Function} func The function to inspect.
5962 * @returns {*} Returns the placeholder value.
5964 function getHolder(func) {
5965 var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
5966 return object.placeholder;
5970 * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
5971 * this function returns the custom method, otherwise it returns `baseIteratee`.
5972 * If arguments are provided, the chosen function is invoked with them and
5973 * its result is returned.
5976 * @param {*} [value] The value to convert to an iteratee.
5977 * @param {number} [arity] The arity of the created iteratee.
5978 * @returns {Function} Returns the chosen function or its result.
5980 function getIteratee() {
5981 var result = lodash.iteratee || iteratee;
5982 result = result === iteratee ? baseIteratee : result;
5983 return arguments.length ? result(arguments[0], arguments[1]) : result;
5987 * Gets the data for `map`.
5990 * @param {Object} map The map to query.
5991 * @param {string} key The reference key.
5992 * @returns {*} Returns the map data.
5994 function getMapData(map, key) {
5995 var data = map.__data__;
5996 return isKeyable(key)
5997 ? data[typeof key == 'string' ? 'string' : 'hash']
6002 * Gets the property names, values, and compare flags of `object`.
6005 * @param {Object} object The object to query.
6006 * @returns {Array} Returns the match data of `object`.
6008 function getMatchData(object) {
6009 var result = keys(object),
6010 length = result.length;
6013 var key = result[length],
6014 value = object[key];
6016 result[length] = [key, value, isStrictComparable(value)];
6022 * Gets the native function at `key` of `object`.
6025 * @param {Object} object The object to query.
6026 * @param {string} key The key of the method to get.
6027 * @returns {*} Returns the function if it's native, else `undefined`.
6029 function getNative(object, key) {
6030 var value = getValue(object, key);
6031 return baseIsNative(value) ? value : undefined;
6035 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
6038 * @param {*} value The value to query.
6039 * @returns {string} Returns the raw `toStringTag`.
6041 function getRawTag(value) {
6042 var isOwn = hasOwnProperty.call(value, symToStringTag),
6043 tag = value[symToStringTag];
6046 value[symToStringTag] = undefined;
6047 var unmasked = true;
6050 var result = nativeObjectToString.call(value);
6053 value[symToStringTag] = tag;
6055 delete value[symToStringTag];
6062 * Creates an array of the own enumerable symbols of `object`.
6065 * @param {Object} object The object to query.
6066 * @returns {Array} Returns the array of symbols.
6068 var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
6069 if (object == null) {
6072 object = Object(object);
6073 return arrayFilter(nativeGetSymbols(object), function(symbol) {
6074 return propertyIsEnumerable.call(object, symbol);
6079 * Creates an array of the own and inherited enumerable symbols of `object`.
6082 * @param {Object} object The object to query.
6083 * @returns {Array} Returns the array of symbols.
6085 var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
6088 arrayPush(result, getSymbols(object));
6089 object = getPrototype(object);
6095 * Gets the `toStringTag` of `value`.
6098 * @param {*} value The value to query.
6099 * @returns {string} Returns the `toStringTag`.
6101 var getTag = baseGetTag;
6103 // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
6104 if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
6105 (Map && getTag(new Map) != mapTag) ||
6106 (Promise && getTag(Promise.resolve()) != promiseTag) ||
6107 (Set && getTag(new Set) != setTag) ||
6108 (WeakMap && getTag(new WeakMap) != weakMapTag)) {
6109 getTag = function(value) {
6110 var result = baseGetTag(value),
6111 Ctor = result == objectTag ? value.constructor : undefined,
6112 ctorString = Ctor ? toSource(Ctor) : '';
6115 switch (ctorString) {
6116 case dataViewCtorString: return dataViewTag;
6117 case mapCtorString: return mapTag;
6118 case promiseCtorString: return promiseTag;
6119 case setCtorString: return setTag;
6120 case weakMapCtorString: return weakMapTag;
6128 * Gets the view, applying any `transforms` to the `start` and `end` positions.
6131 * @param {number} start The start of the view.
6132 * @param {number} end The end of the view.
6133 * @param {Array} transforms The transformations to apply to the view.
6134 * @returns {Object} Returns an object containing the `start` and `end`
6135 * positions of the view.
6137 function getView(start, end, transforms) {
6139 length = transforms.length;
6141 while (++index < length) {
6142 var data = transforms[index],
6145 switch (data.type) {
6146 case 'drop': start += size; break;
6147 case 'dropRight': end -= size; break;
6148 case 'take': end = nativeMin(end, start + size); break;
6149 case 'takeRight': start = nativeMax(start, end - size); break;
6152 return { 'start': start, 'end': end };
6156 * Extracts wrapper details from the `source` body comment.
6159 * @param {string} source The source to inspect.
6160 * @returns {Array} Returns the wrapper details.
6162 function getWrapDetails(source) {
6163 var match = source.match(reWrapDetails);
6164 return match ? match[1].split(reSplitDetails) : [];
6168 * Checks if `path` exists on `object`.
6171 * @param {Object} object The object to query.
6172 * @param {Array|string} path The path to check.
6173 * @param {Function} hasFunc The function to check properties.
6174 * @returns {boolean} Returns `true` if `path` exists, else `false`.
6176 function hasPath(object, path, hasFunc) {
6177 path = castPath(path, object);
6180 length = path.length,
6183 while (++index < length) {
6184 var key = toKey(path[index]);
6185 if (!(result = object != null && hasFunc(object, key))) {
6188 object = object[key];
6190 if (result || ++index != length) {
6193 length = object == null ? 0 : object.length;
6194 return !!length && isLength(length) && isIndex(key, length) &&
6195 (isArray(object) || isArguments(object));
6199 * Initializes an array clone.
6202 * @param {Array} array The array to clone.
6203 * @returns {Array} Returns the initialized clone.
6205 function initCloneArray(array) {
6206 var length = array.length,
6207 result = array.constructor(length);
6209 // Add properties assigned by `RegExp#exec`.
6210 if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
6211 result.index = array.index;
6212 result.input = array.input;
6218 * Initializes an object clone.
6221 * @param {Object} object The object to clone.
6222 * @returns {Object} Returns the initialized clone.
6224 function initCloneObject(object) {
6225 return (typeof object.constructor == 'function' && !isPrototype(object))
6226 ? baseCreate(getPrototype(object))
6231 * Initializes an object clone based on its `toStringTag`.
6233 * **Note:** This function only supports cloning values with tags of
6234 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
6237 * @param {Object} object The object to clone.
6238 * @param {string} tag The `toStringTag` of the object to clone.
6239 * @param {Function} cloneFunc The function to clone values.
6240 * @param {boolean} [isDeep] Specify a deep clone.
6241 * @returns {Object} Returns the initialized clone.
6243 function initCloneByTag(object, tag, cloneFunc, isDeep) {
6244 var Ctor = object.constructor;
6246 case arrayBufferTag:
6247 return cloneArrayBuffer(object);
6251 return new Ctor(+object);
6254 return cloneDataView(object, isDeep);
6256 case float32Tag: case float64Tag:
6257 case int8Tag: case int16Tag: case int32Tag:
6258 case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
6259 return cloneTypedArray(object, isDeep);
6262 return cloneMap(object, isDeep, cloneFunc);
6266 return new Ctor(object);
6269 return cloneRegExp(object);
6272 return cloneSet(object, isDeep, cloneFunc);
6275 return cloneSymbol(object);
6280 * Inserts wrapper `details` in a comment at the top of the `source` body.
6283 * @param {string} source The source to modify.
6284 * @returns {Array} details The details to insert.
6285 * @returns {string} Returns the modified source.
6287 function insertWrapDetails(source, details) {
6288 var length = details.length;
6292 var lastIndex = length - 1;
6293 details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
6294 details = details.join(length > 2 ? ', ' : ' ');
6295 return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
6299 * Checks if `value` is a flattenable `arguments` object or array.
6302 * @param {*} value The value to check.
6303 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
6305 function isFlattenable(value) {
6306 return isArray(value) || isArguments(value) ||
6307 !!(spreadableSymbol && value && value[spreadableSymbol]);
6311 * Checks if `value` is a valid array-like index.
6314 * @param {*} value The value to check.
6315 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
6316 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
6318 function isIndex(value, length) {
6319 length = length == null ? MAX_SAFE_INTEGER : length;
6321 (typeof value == 'number' || reIsUint.test(value)) &&
6322 (value > -1 && value % 1 == 0 && value < length);
6326 * Checks if the given arguments are from an iteratee call.
6329 * @param {*} value The potential iteratee value argument.
6330 * @param {*} index The potential iteratee index or key argument.
6331 * @param {*} object The potential iteratee object argument.
6332 * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
6335 function isIterateeCall(value, index, object) {
6336 if (!isObject(object)) {
6339 var type = typeof index;
6340 if (type == 'number'
6341 ? (isArrayLike(object) && isIndex(index, object.length))
6342 : (type == 'string' && index in object)
6344 return eq(object[index], value);
6350 * Checks if `value` is a property name and not a property path.
6353 * @param {*} value The value to check.
6354 * @param {Object} [object] The object to query keys on.
6355 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
6357 function isKey(value, object) {
6358 if (isArray(value)) {
6361 var type = typeof value;
6362 if (type == 'number' || type == 'symbol' || type == 'boolean' ||
6363 value == null || isSymbol(value)) {
6366 return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
6367 (object != null && value in Object(object));
6371 * Checks if `value` is suitable for use as unique object key.
6374 * @param {*} value The value to check.
6375 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
6377 function isKeyable(value) {
6378 var type = typeof value;
6379 return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
6380 ? (value !== '__proto__')
6385 * Checks if `func` has a lazy counterpart.
6388 * @param {Function} func The function to check.
6389 * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
6392 function isLaziable(func) {
6393 var funcName = getFuncName(func),
6394 other = lodash[funcName];
6396 if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
6399 if (func === other) {
6402 var data = getData(other);
6403 return !!data && func === data[0];
6407 * Checks if `func` has its source masked.
6410 * @param {Function} func The function to check.
6411 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
6413 function isMasked(func) {
6414 return !!maskSrcKey && (maskSrcKey in func);
6418 * Checks if `func` is capable of being masked.
6421 * @param {*} value The value to check.
6422 * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
6424 var isMaskable = coreJsData ? isFunction : stubFalse;
6427 * Checks if `value` is likely a prototype object.
6430 * @param {*} value The value to check.
6431 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
6433 function isPrototype(value) {
6434 var Ctor = value && value.constructor,
6435 proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
6437 return value === proto;
6441 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
6444 * @param {*} value The value to check.
6445 * @returns {boolean} Returns `true` if `value` if suitable for strict
6446 * equality comparisons, else `false`.
6448 function isStrictComparable(value) {
6449 return value === value && !isObject(value);
6453 * A specialized version of `matchesProperty` for source values suitable
6454 * for strict equality comparisons, i.e. `===`.
6457 * @param {string} key The key of the property to get.
6458 * @param {*} srcValue The value to match.
6459 * @returns {Function} Returns the new spec function.
6461 function matchesStrictComparable(key, srcValue) {
6462 return function(object) {
6463 if (object == null) {
6466 return object[key] === srcValue &&
6467 (srcValue !== undefined || (key in Object(object)));
6472 * A specialized version of `_.memoize` which clears the memoized function's
6473 * cache when it exceeds `MAX_MEMOIZE_SIZE`.
6476 * @param {Function} func The function to have its output memoized.
6477 * @returns {Function} Returns the new memoized function.
6479 function memoizeCapped(func) {
6480 var result = memoize(func, function(key) {
6481 if (cache.size === MAX_MEMOIZE_SIZE) {
6487 var cache = result.cache;
6492 * Merges the function metadata of `source` into `data`.
6494 * Merging metadata reduces the number of wrappers used to invoke a function.
6495 * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
6496 * may be applied regardless of execution order. Methods like `_.ary` and
6497 * `_.rearg` modify function arguments, making the order in which they are
6498 * executed important, preventing the merging of metadata. However, we make
6499 * an exception for a safe combined case where curried functions have `_.ary`
6500 * and or `_.rearg` applied.
6503 * @param {Array} data The destination metadata.
6504 * @param {Array} source The source metadata.
6505 * @returns {Array} Returns `data`.
6507 function mergeData(data, source) {
6508 var bitmask = data[1],
6509 srcBitmask = source[1],
6510 newBitmask = bitmask | srcBitmask,
6511 isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
6514 ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
6515 ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
6516 ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
6518 // Exit early if metadata can't be merged.
6519 if (!(isCommon || isCombo)) {
6522 // Use source `thisArg` if available.
6523 if (srcBitmask & WRAP_BIND_FLAG) {
6524 data[2] = source[2];
6525 // Set when currying a bound function.
6526 newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
6528 // Compose partial arguments.
6529 var value = source[3];
6531 var partials = data[3];
6532 data[3] = partials ? composeArgs(partials, value, source[4]) : value;
6533 data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
6535 // Compose partial right arguments.
6539 data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
6540 data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
6542 // Use source `argPos` if available.
6547 // Use source `ary` if it's smaller.
6548 if (srcBitmask & WRAP_ARY_FLAG) {
6549 data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
6551 // Use source `arity` if one is not provided.
6552 if (data[9] == null) {
6553 data[9] = source[9];
6555 // Use source `func` and merge bitmasks.
6556 data[0] = source[0];
6557 data[1] = newBitmask;
6563 * This function is like
6564 * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
6565 * except that it includes inherited enumerable properties.
6568 * @param {Object} object The object to query.
6569 * @returns {Array} Returns the array of property names.
6571 function nativeKeysIn(object) {
6573 if (object != null) {
6574 for (var key in Object(object)) {
6582 * Converts `value` to a string using `Object.prototype.toString`.
6585 * @param {*} value The value to convert.
6586 * @returns {string} Returns the converted string.
6588 function objectToString(value) {
6589 return nativeObjectToString.call(value);
6593 * A specialized version of `baseRest` which transforms the rest array.
6596 * @param {Function} func The function to apply a rest parameter to.
6597 * @param {number} [start=func.length-1] The start position of the rest parameter.
6598 * @param {Function} transform The rest array transform.
6599 * @returns {Function} Returns the new function.
6601 function overRest(func, start, transform) {
6602 start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
6604 var args = arguments,
6606 length = nativeMax(args.length - start, 0),
6607 array = Array(length);
6609 while (++index < length) {
6610 array[index] = args[start + index];
6613 var otherArgs = Array(start + 1);
6614 while (++index < start) {
6615 otherArgs[index] = args[index];
6617 otherArgs[start] = transform(array);
6618 return apply(func, this, otherArgs);
6623 * Gets the parent value at `path` of `object`.
6626 * @param {Object} object The object to query.
6627 * @param {Array} path The path to get the parent value of.
6628 * @returns {*} Returns the parent value.
6630 function parent(object, path) {
6631 return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
6635 * Reorder `array` according to the specified indexes where the element at
6636 * the first index is assigned as the first element, the element at
6637 * the second index is assigned as the second element, and so on.
6640 * @param {Array} array The array to reorder.
6641 * @param {Array} indexes The arranged array indexes.
6642 * @returns {Array} Returns `array`.
6644 function reorder(array, indexes) {
6645 var arrLength = array.length,
6646 length = nativeMin(indexes.length, arrLength),
6647 oldArray = copyArray(array);
6650 var index = indexes[length];
6651 array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
6657 * Sets metadata for `func`.
6659 * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
6660 * period of time, it will trip its breaker and transition to an identity
6661 * function to avoid garbage collection pauses in V8. See
6662 * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
6666 * @param {Function} func The function to associate metadata with.
6667 * @param {*} data The metadata.
6668 * @returns {Function} Returns `func`.
6670 var setData = shortOut(baseSetData);
6673 * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
6676 * @param {Function} func The function to delay.
6677 * @param {number} wait The number of milliseconds to delay invocation.
6678 * @returns {number|Object} Returns the timer id or timeout object.
6680 var setTimeout = ctxSetTimeout || function(func, wait) {
6681 return root.setTimeout(func, wait);
6685 * Sets the `toString` method of `func` to return `string`.
6688 * @param {Function} func The function to modify.
6689 * @param {Function} string The `toString` result.
6690 * @returns {Function} Returns `func`.
6692 var setToString = shortOut(baseSetToString);
6695 * Sets the `toString` method of `wrapper` to mimic the source of `reference`
6696 * with wrapper details in a comment at the top of the source body.
6699 * @param {Function} wrapper The function to modify.
6700 * @param {Function} reference The reference function.
6701 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6702 * @returns {Function} Returns `wrapper`.
6704 function setWrapToString(wrapper, reference, bitmask) {
6705 var source = (reference + '');
6706 return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
6710 * Creates a function that'll short out and invoke `identity` instead
6711 * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
6715 * @param {Function} func The function to restrict.
6716 * @returns {Function} Returns the new shortable function.
6718 function shortOut(func) {
6723 var stamp = nativeNow(),
6724 remaining = HOT_SPAN - (stamp - lastCalled);
6727 if (remaining > 0) {
6728 if (++count >= HOT_COUNT) {
6729 return arguments[0];
6734 return func.apply(undefined, arguments);
6739 * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
6742 * @param {Array} array The array to shuffle.
6743 * @param {number} [size=array.length] The size of `array`.
6744 * @returns {Array} Returns `array`.
6746 function shuffleSelf(array, size) {
6748 length = array.length,
6749 lastIndex = length - 1;
6751 size = size === undefined ? length : size;
6752 while (++index < size) {
6753 var rand = baseRandom(index, lastIndex),
6754 value = array[rand];
6756 array[rand] = array[index];
6757 array[index] = value;
6759 array.length = size;
6764 * Converts `string` to a property path array.
6767 * @param {string} string The string to convert.
6768 * @returns {Array} Returns the property path array.
6770 var stringToPath = memoizeCapped(function(string) {
6772 if (reLeadingDot.test(string)) {
6775 string.replace(rePropName, function(match, number, quote, string) {
6776 result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
6782 * Converts `value` to a string key if it's not a string or symbol.
6785 * @param {*} value The value to inspect.
6786 * @returns {string|symbol} Returns the key.
6788 function toKey(value) {
6789 if (typeof value == 'string' || isSymbol(value)) {
6792 var result = (value + '');
6793 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
6797 * Converts `func` to its source code.
6800 * @param {Function} func The function to convert.
6801 * @returns {string} Returns the source code.
6803 function toSource(func) {
6806 return funcToString.call(func);
6816 * Updates wrapper `details` based on `bitmask` flags.
6819 * @returns {Array} details The details to modify.
6820 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6821 * @returns {Array} Returns `details`.
6823 function updateWrapDetails(details, bitmask) {
6824 arrayEach(wrapFlags, function(pair) {
6825 var value = '_.' + pair[0];
6826 if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
6827 details.push(value);
6830 return details.sort();
6834 * Creates a clone of `wrapper`.
6837 * @param {Object} wrapper The wrapper to clone.
6838 * @returns {Object} Returns the cloned wrapper.
6840 function wrapperClone(wrapper) {
6841 if (wrapper instanceof LazyWrapper) {
6842 return wrapper.clone();
6844 var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
6845 result.__actions__ = copyArray(wrapper.__actions__);
6846 result.__index__ = wrapper.__index__;
6847 result.__values__ = wrapper.__values__;
6851 /*------------------------------------------------------------------------*/
6854 * Creates an array of elements split into groups the length of `size`.
6855 * If `array` can't be split evenly, the final chunk will be the remaining
6862 * @param {Array} array The array to process.
6863 * @param {number} [size=1] The length of each chunk
6864 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
6865 * @returns {Array} Returns the new array of chunks.
6868 * _.chunk(['a', 'b', 'c', 'd'], 2);
6869 * // => [['a', 'b'], ['c', 'd']]
6871 * _.chunk(['a', 'b', 'c', 'd'], 3);
6872 * // => [['a', 'b', 'c'], ['d']]
6874 function chunk(array, size, guard) {
6875 if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
6878 size = nativeMax(toInteger(size), 0);
6880 var length = array == null ? 0 : array.length;
6881 if (!length || size < 1) {
6886 result = Array(nativeCeil(length / size));
6888 while (index < length) {
6889 result[resIndex++] = baseSlice(array, index, (index += size));
6895 * Creates an array with all falsey values removed. The values `false`, `null`,
6896 * `0`, `""`, `undefined`, and `NaN` are falsey.
6902 * @param {Array} array The array to compact.
6903 * @returns {Array} Returns the new array of filtered values.
6906 * _.compact([0, 1, false, 2, '', 3]);
6909 function compact(array) {
6911 length = array == null ? 0 : array.length,
6915 while (++index < length) {
6916 var value = array[index];
6918 result[resIndex++] = value;
6925 * Creates a new array concatenating `array` with any additional arrays
6932 * @param {Array} array The array to concatenate.
6933 * @param {...*} [values] The values to concatenate.
6934 * @returns {Array} Returns the new concatenated array.
6938 * var other = _.concat(array, 2, [3], [[4]]);
6940 * console.log(other);
6941 * // => [1, 2, 3, [4]]
6943 * console.log(array);
6947 var length = arguments.length;
6951 var args = Array(length - 1),
6952 array = arguments[0],
6956 args[index - 1] = arguments[index];
6958 return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
6962 * Creates an array of `array` values not included in the other given arrays
6963 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
6964 * for equality comparisons. The order and references of result values are
6965 * determined by the first array.
6967 * **Note:** Unlike `_.pullAll`, this method returns a new array.
6973 * @param {Array} array The array to inspect.
6974 * @param {...Array} [values] The values to exclude.
6975 * @returns {Array} Returns the new array of filtered values.
6976 * @see _.without, _.xor
6979 * _.difference([2, 1], [2, 3]);
6982 var difference = baseRest(function(array, values) {
6983 return isArrayLikeObject(array)
6984 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
6989 * This method is like `_.difference` except that it accepts `iteratee` which
6990 * is invoked for each element of `array` and `values` to generate the criterion
6991 * by which they're compared. The order and references of result values are
6992 * determined by the first array. The iteratee is invoked with one argument:
6995 * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
7001 * @param {Array} array The array to inspect.
7002 * @param {...Array} [values] The values to exclude.
7003 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7004 * @returns {Array} Returns the new array of filtered values.
7007 * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7010 * // The `_.property` iteratee shorthand.
7011 * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
7012 * // => [{ 'x': 2 }]
7014 var differenceBy = baseRest(function(array, values) {
7015 var iteratee = last(values);
7016 if (isArrayLikeObject(iteratee)) {
7017 iteratee = undefined;
7019 return isArrayLikeObject(array)
7020 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
7025 * This method is like `_.difference` except that it accepts `comparator`
7026 * which is invoked to compare elements of `array` to `values`. The order and
7027 * references of result values are determined by the first array. The comparator
7028 * is invoked with two arguments: (arrVal, othVal).
7030 * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
7036 * @param {Array} array The array to inspect.
7037 * @param {...Array} [values] The values to exclude.
7038 * @param {Function} [comparator] The comparator invoked per element.
7039 * @returns {Array} Returns the new array of filtered values.
7042 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7044 * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
7045 * // => [{ 'x': 2, 'y': 1 }]
7047 var differenceWith = baseRest(function(array, values) {
7048 var comparator = last(values);
7049 if (isArrayLikeObject(comparator)) {
7050 comparator = undefined;
7052 return isArrayLikeObject(array)
7053 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
7058 * Creates a slice of `array` with `n` elements dropped from the beginning.
7064 * @param {Array} array The array to query.
7065 * @param {number} [n=1] The number of elements to drop.
7066 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7067 * @returns {Array} Returns the slice of `array`.
7070 * _.drop([1, 2, 3]);
7073 * _.drop([1, 2, 3], 2);
7076 * _.drop([1, 2, 3], 5);
7079 * _.drop([1, 2, 3], 0);
7082 function drop(array, n, guard) {
7083 var length = array == null ? 0 : array.length;
7087 n = (guard || n === undefined) ? 1 : toInteger(n);
7088 return baseSlice(array, n < 0 ? 0 : n, length);
7092 * Creates a slice of `array` with `n` elements dropped from the end.
7098 * @param {Array} array The array to query.
7099 * @param {number} [n=1] The number of elements to drop.
7100 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7101 * @returns {Array} Returns the slice of `array`.
7104 * _.dropRight([1, 2, 3]);
7107 * _.dropRight([1, 2, 3], 2);
7110 * _.dropRight([1, 2, 3], 5);
7113 * _.dropRight([1, 2, 3], 0);
7116 function dropRight(array, n, guard) {
7117 var length = array == null ? 0 : array.length;
7121 n = (guard || n === undefined) ? 1 : toInteger(n);
7123 return baseSlice(array, 0, n < 0 ? 0 : n);
7127 * Creates a slice of `array` excluding elements dropped from the end.
7128 * Elements are dropped until `predicate` returns falsey. The predicate is
7129 * invoked with three arguments: (value, index, array).
7135 * @param {Array} array The array to query.
7136 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7137 * @returns {Array} Returns the slice of `array`.
7141 * { 'user': 'barney', 'active': true },
7142 * { 'user': 'fred', 'active': false },
7143 * { 'user': 'pebbles', 'active': false }
7146 * _.dropRightWhile(users, function(o) { return !o.active; });
7147 * // => objects for ['barney']
7149 * // The `_.matches` iteratee shorthand.
7150 * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
7151 * // => objects for ['barney', 'fred']
7153 * // The `_.matchesProperty` iteratee shorthand.
7154 * _.dropRightWhile(users, ['active', false]);
7155 * // => objects for ['barney']
7157 * // The `_.property` iteratee shorthand.
7158 * _.dropRightWhile(users, 'active');
7159 * // => objects for ['barney', 'fred', 'pebbles']
7161 function dropRightWhile(array, predicate) {
7162 return (array && array.length)
7163 ? baseWhile(array, getIteratee(predicate, 3), true, true)
7168 * Creates a slice of `array` excluding elements dropped from the beginning.
7169 * Elements are dropped until `predicate` returns falsey. The predicate is
7170 * invoked with three arguments: (value, index, array).
7176 * @param {Array} array The array to query.
7177 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7178 * @returns {Array} Returns the slice of `array`.
7182 * { 'user': 'barney', 'active': false },
7183 * { 'user': 'fred', 'active': false },
7184 * { 'user': 'pebbles', 'active': true }
7187 * _.dropWhile(users, function(o) { return !o.active; });
7188 * // => objects for ['pebbles']
7190 * // The `_.matches` iteratee shorthand.
7191 * _.dropWhile(users, { 'user': 'barney', 'active': false });
7192 * // => objects for ['fred', 'pebbles']
7194 * // The `_.matchesProperty` iteratee shorthand.
7195 * _.dropWhile(users, ['active', false]);
7196 * // => objects for ['pebbles']
7198 * // The `_.property` iteratee shorthand.
7199 * _.dropWhile(users, 'active');
7200 * // => objects for ['barney', 'fred', 'pebbles']
7202 function dropWhile(array, predicate) {
7203 return (array && array.length)
7204 ? baseWhile(array, getIteratee(predicate, 3), true)
7209 * Fills elements of `array` with `value` from `start` up to, but not
7212 * **Note:** This method mutates `array`.
7218 * @param {Array} array The array to fill.
7219 * @param {*} value The value to fill `array` with.
7220 * @param {number} [start=0] The start position.
7221 * @param {number} [end=array.length] The end position.
7222 * @returns {Array} Returns `array`.
7225 * var array = [1, 2, 3];
7227 * _.fill(array, 'a');
7228 * console.log(array);
7229 * // => ['a', 'a', 'a']
7231 * _.fill(Array(3), 2);
7234 * _.fill([4, 6, 8, 10], '*', 1, 3);
7235 * // => [4, '*', '*', 10]
7237 function fill(array, value, start, end) {
7238 var length = array == null ? 0 : array.length;
7242 if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
7246 return baseFill(array, value, start, end);
7250 * This method is like `_.find` except that it returns the index of the first
7251 * element `predicate` returns truthy for instead of the element itself.
7257 * @param {Array} array The array to inspect.
7258 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7259 * @param {number} [fromIndex=0] The index to search from.
7260 * @returns {number} Returns the index of the found element, else `-1`.
7264 * { 'user': 'barney', 'active': false },
7265 * { 'user': 'fred', 'active': false },
7266 * { 'user': 'pebbles', 'active': true }
7269 * _.findIndex(users, function(o) { return o.user == 'barney'; });
7272 * // The `_.matches` iteratee shorthand.
7273 * _.findIndex(users, { 'user': 'fred', 'active': false });
7276 * // The `_.matchesProperty` iteratee shorthand.
7277 * _.findIndex(users, ['active', false]);
7280 * // The `_.property` iteratee shorthand.
7281 * _.findIndex(users, 'active');
7284 function findIndex(array, predicate, fromIndex) {
7285 var length = array == null ? 0 : array.length;
7289 var index = fromIndex == null ? 0 : toInteger(fromIndex);
7291 index = nativeMax(length + index, 0);
7293 return baseFindIndex(array, getIteratee(predicate, 3), index);
7297 * This method is like `_.findIndex` except that it iterates over elements
7298 * of `collection` from right to left.
7304 * @param {Array} array The array to inspect.
7305 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7306 * @param {number} [fromIndex=array.length-1] The index to search from.
7307 * @returns {number} Returns the index of the found element, else `-1`.
7311 * { 'user': 'barney', 'active': true },
7312 * { 'user': 'fred', 'active': false },
7313 * { 'user': 'pebbles', 'active': false }
7316 * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
7319 * // The `_.matches` iteratee shorthand.
7320 * _.findLastIndex(users, { 'user': 'barney', 'active': true });
7323 * // The `_.matchesProperty` iteratee shorthand.
7324 * _.findLastIndex(users, ['active', false]);
7327 * // The `_.property` iteratee shorthand.
7328 * _.findLastIndex(users, 'active');
7331 function findLastIndex(array, predicate, fromIndex) {
7332 var length = array == null ? 0 : array.length;
7336 var index = length - 1;
7337 if (fromIndex !== undefined) {
7338 index = toInteger(fromIndex);
7339 index = fromIndex < 0
7340 ? nativeMax(length + index, 0)
7341 : nativeMin(index, length - 1);
7343 return baseFindIndex(array, getIteratee(predicate, 3), index, true);
7347 * Flattens `array` a single level deep.
7353 * @param {Array} array The array to flatten.
7354 * @returns {Array} Returns the new flattened array.
7357 * _.flatten([1, [2, [3, [4]], 5]]);
7358 * // => [1, 2, [3, [4]], 5]
7360 function flatten(array) {
7361 var length = array == null ? 0 : array.length;
7362 return length ? baseFlatten(array, 1) : [];
7366 * Recursively flattens `array`.
7372 * @param {Array} array The array to flatten.
7373 * @returns {Array} Returns the new flattened array.
7376 * _.flattenDeep([1, [2, [3, [4]], 5]]);
7377 * // => [1, 2, 3, 4, 5]
7379 function flattenDeep(array) {
7380 var length = array == null ? 0 : array.length;
7381 return length ? baseFlatten(array, INFINITY) : [];
7385 * Recursively flatten `array` up to `depth` times.
7391 * @param {Array} array The array to flatten.
7392 * @param {number} [depth=1] The maximum recursion depth.
7393 * @returns {Array} Returns the new flattened array.
7396 * var array = [1, [2, [3, [4]], 5]];
7398 * _.flattenDepth(array, 1);
7399 * // => [1, 2, [3, [4]], 5]
7401 * _.flattenDepth(array, 2);
7402 * // => [1, 2, 3, [4], 5]
7404 function flattenDepth(array, depth) {
7405 var length = array == null ? 0 : array.length;
7409 depth = depth === undefined ? 1 : toInteger(depth);
7410 return baseFlatten(array, depth);
7414 * The inverse of `_.toPairs`; this method returns an object composed
7415 * from key-value `pairs`.
7421 * @param {Array} pairs The key-value pairs.
7422 * @returns {Object} Returns the new object.
7425 * _.fromPairs([['a', 1], ['b', 2]]);
7426 * // => { 'a': 1, 'b': 2 }
7428 function fromPairs(pairs) {
7430 length = pairs == null ? 0 : pairs.length,
7433 while (++index < length) {
7434 var pair = pairs[index];
7435 result[pair[0]] = pair[1];
7441 * Gets the first element of `array`.
7448 * @param {Array} array The array to query.
7449 * @returns {*} Returns the first element of `array`.
7452 * _.head([1, 2, 3]);
7458 function head(array) {
7459 return (array && array.length) ? array[0] : undefined;
7463 * Gets the index at which the first occurrence of `value` is found in `array`
7464 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7465 * for equality comparisons. If `fromIndex` is negative, it's used as the
7466 * offset from the end of `array`.
7472 * @param {Array} array The array to inspect.
7473 * @param {*} value The value to search for.
7474 * @param {number} [fromIndex=0] The index to search from.
7475 * @returns {number} Returns the index of the matched value, else `-1`.
7478 * _.indexOf([1, 2, 1, 2], 2);
7481 * // Search from the `fromIndex`.
7482 * _.indexOf([1, 2, 1, 2], 2, 2);
7485 function indexOf(array, value, fromIndex) {
7486 var length = array == null ? 0 : array.length;
7490 var index = fromIndex == null ? 0 : toInteger(fromIndex);
7492 index = nativeMax(length + index, 0);
7494 return baseIndexOf(array, value, index);
7498 * Gets all but the last element of `array`.
7504 * @param {Array} array The array to query.
7505 * @returns {Array} Returns the slice of `array`.
7508 * _.initial([1, 2, 3]);
7511 function initial(array) {
7512 var length = array == null ? 0 : array.length;
7513 return length ? baseSlice(array, 0, -1) : [];
7517 * Creates an array of unique values that are included in all given arrays
7518 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7519 * for equality comparisons. The order and references of result values are
7520 * determined by the first array.
7526 * @param {...Array} [arrays] The arrays to inspect.
7527 * @returns {Array} Returns the new array of intersecting values.
7530 * _.intersection([2, 1], [2, 3]);
7533 var intersection = baseRest(function(arrays) {
7534 var mapped = arrayMap(arrays, castArrayLikeObject);
7535 return (mapped.length && mapped[0] === arrays[0])
7536 ? baseIntersection(mapped)
7541 * This method is like `_.intersection` except that it accepts `iteratee`
7542 * which is invoked for each element of each `arrays` to generate the criterion
7543 * by which they're compared. The order and references of result values are
7544 * determined by the first array. The iteratee is invoked with one argument:
7551 * @param {...Array} [arrays] The arrays to inspect.
7552 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7553 * @returns {Array} Returns the new array of intersecting values.
7556 * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7559 * // The `_.property` iteratee shorthand.
7560 * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
7561 * // => [{ 'x': 1 }]
7563 var intersectionBy = baseRest(function(arrays) {
7564 var iteratee = last(arrays),
7565 mapped = arrayMap(arrays, castArrayLikeObject);
7567 if (iteratee === last(mapped)) {
7568 iteratee = undefined;
7572 return (mapped.length && mapped[0] === arrays[0])
7573 ? baseIntersection(mapped, getIteratee(iteratee, 2))
7578 * This method is like `_.intersection` except that it accepts `comparator`
7579 * which is invoked to compare elements of `arrays`. The order and references
7580 * of result values are determined by the first array. The comparator is
7581 * invoked with two arguments: (arrVal, othVal).
7587 * @param {...Array} [arrays] The arrays to inspect.
7588 * @param {Function} [comparator] The comparator invoked per element.
7589 * @returns {Array} Returns the new array of intersecting values.
7592 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7593 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
7595 * _.intersectionWith(objects, others, _.isEqual);
7596 * // => [{ 'x': 1, 'y': 2 }]
7598 var intersectionWith = baseRest(function(arrays) {
7599 var comparator = last(arrays),
7600 mapped = arrayMap(arrays, castArrayLikeObject);
7602 comparator = typeof comparator == 'function' ? comparator : undefined;
7606 return (mapped.length && mapped[0] === arrays[0])
7607 ? baseIntersection(mapped, undefined, comparator)
7612 * Converts all elements in `array` into a string separated by `separator`.
7618 * @param {Array} array The array to convert.
7619 * @param {string} [separator=','] The element separator.
7620 * @returns {string} Returns the joined string.
7623 * _.join(['a', 'b', 'c'], '~');
7626 function join(array, separator) {
7627 return array == null ? '' : nativeJoin.call(array, separator);
7631 * Gets the last element of `array`.
7637 * @param {Array} array The array to query.
7638 * @returns {*} Returns the last element of `array`.
7641 * _.last([1, 2, 3]);
7644 function last(array) {
7645 var length = array == null ? 0 : array.length;
7646 return length ? array[length - 1] : undefined;
7650 * This method is like `_.indexOf` except that it iterates over elements of
7651 * `array` from right to left.
7657 * @param {Array} array The array to inspect.
7658 * @param {*} value The value to search for.
7659 * @param {number} [fromIndex=array.length-1] The index to search from.
7660 * @returns {number} Returns the index of the matched value, else `-1`.
7663 * _.lastIndexOf([1, 2, 1, 2], 2);
7666 * // Search from the `fromIndex`.
7667 * _.lastIndexOf([1, 2, 1, 2], 2, 2);
7670 function lastIndexOf(array, value, fromIndex) {
7671 var length = array == null ? 0 : array.length;
7676 if (fromIndex !== undefined) {
7677 index = toInteger(fromIndex);
7678 index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
7680 return value === value
7681 ? strictLastIndexOf(array, value, index)
7682 : baseFindIndex(array, baseIsNaN, index, true);
7686 * Gets the element at index `n` of `array`. If `n` is negative, the nth
7687 * element from the end is returned.
7693 * @param {Array} array The array to query.
7694 * @param {number} [n=0] The index of the element to return.
7695 * @returns {*} Returns the nth element of `array`.
7698 * var array = ['a', 'b', 'c', 'd'];
7706 function nth(array, n) {
7707 return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
7711 * Removes all given values from `array` using
7712 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7713 * for equality comparisons.
7715 * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
7716 * to remove elements from an array by predicate.
7722 * @param {Array} array The array to modify.
7723 * @param {...*} [values] The values to remove.
7724 * @returns {Array} Returns `array`.
7727 * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7729 * _.pull(array, 'a', 'c');
7730 * console.log(array);
7733 var pull = baseRest(pullAll);
7736 * This method is like `_.pull` except that it accepts an array of values to remove.
7738 * **Note:** Unlike `_.difference`, this method mutates `array`.
7744 * @param {Array} array The array to modify.
7745 * @param {Array} values The values to remove.
7746 * @returns {Array} Returns `array`.
7749 * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7751 * _.pullAll(array, ['a', 'c']);
7752 * console.log(array);
7755 function pullAll(array, values) {
7756 return (array && array.length && values && values.length)
7757 ? basePullAll(array, values)
7762 * This method is like `_.pullAll` except that it accepts `iteratee` which is
7763 * invoked for each element of `array` and `values` to generate the criterion
7764 * by which they're compared. The iteratee is invoked with one argument: (value).
7766 * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
7772 * @param {Array} array The array to modify.
7773 * @param {Array} values The values to remove.
7774 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7775 * @returns {Array} Returns `array`.
7778 * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
7780 * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
7781 * console.log(array);
7782 * // => [{ 'x': 2 }]
7784 function pullAllBy(array, values, iteratee) {
7785 return (array && array.length && values && values.length)
7786 ? basePullAll(array, values, getIteratee(iteratee, 2))
7791 * This method is like `_.pullAll` except that it accepts `comparator` which
7792 * is invoked to compare elements of `array` to `values`. The comparator is
7793 * invoked with two arguments: (arrVal, othVal).
7795 * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
7801 * @param {Array} array The array to modify.
7802 * @param {Array} values The values to remove.
7803 * @param {Function} [comparator] The comparator invoked per element.
7804 * @returns {Array} Returns `array`.
7807 * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
7809 * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
7810 * console.log(array);
7811 * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
7813 function pullAllWith(array, values, comparator) {
7814 return (array && array.length && values && values.length)
7815 ? basePullAll(array, values, undefined, comparator)
7820 * Removes elements from `array` corresponding to `indexes` and returns an
7821 * array of removed elements.
7823 * **Note:** Unlike `_.at`, this method mutates `array`.
7829 * @param {Array} array The array to modify.
7830 * @param {...(number|number[])} [indexes] The indexes of elements to remove.
7831 * @returns {Array} Returns the new array of removed elements.
7834 * var array = ['a', 'b', 'c', 'd'];
7835 * var pulled = _.pullAt(array, [1, 3]);
7837 * console.log(array);
7840 * console.log(pulled);
7843 var pullAt = flatRest(function(array, indexes) {
7844 var length = array == null ? 0 : array.length,
7845 result = baseAt(array, indexes);
7847 basePullAt(array, arrayMap(indexes, function(index) {
7848 return isIndex(index, length) ? +index : index;
7849 }).sort(compareAscending));
7855 * Removes all elements from `array` that `predicate` returns truthy for
7856 * and returns an array of the removed elements. The predicate is invoked
7857 * with three arguments: (value, index, array).
7859 * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
7860 * to pull elements from an array by value.
7866 * @param {Array} array The array to modify.
7867 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7868 * @returns {Array} Returns the new array of removed elements.
7871 * var array = [1, 2, 3, 4];
7872 * var evens = _.remove(array, function(n) {
7873 * return n % 2 == 0;
7876 * console.log(array);
7879 * console.log(evens);
7882 function remove(array, predicate) {
7884 if (!(array && array.length)) {
7889 length = array.length;
7891 predicate = getIteratee(predicate, 3);
7892 while (++index < length) {
7893 var value = array[index];
7894 if (predicate(value, index, array)) {
7896 indexes.push(index);
7899 basePullAt(array, indexes);
7904 * Reverses `array` so that the first element becomes the last, the second
7905 * element becomes the second to last, and so on.
7907 * **Note:** This method mutates `array` and is based on
7908 * [`Array#reverse`](https://mdn.io/Array/reverse).
7914 * @param {Array} array The array to modify.
7915 * @returns {Array} Returns `array`.
7918 * var array = [1, 2, 3];
7923 * console.log(array);
7926 function reverse(array) {
7927 return array == null ? array : nativeReverse.call(array);
7931 * Creates a slice of `array` from `start` up to, but not including, `end`.
7933 * **Note:** This method is used instead of
7934 * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
7941 * @param {Array} array The array to slice.
7942 * @param {number} [start=0] The start position.
7943 * @param {number} [end=array.length] The end position.
7944 * @returns {Array} Returns the slice of `array`.
7946 function slice(array, start, end) {
7947 var length = array == null ? 0 : array.length;
7951 if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
7956 start = start == null ? 0 : toInteger(start);
7957 end = end === undefined ? length : toInteger(end);
7959 return baseSlice(array, start, end);
7963 * Uses a binary search to determine the lowest index at which `value`
7964 * should be inserted into `array` in order to maintain its sort order.
7970 * @param {Array} array The sorted array to inspect.
7971 * @param {*} value The value to evaluate.
7972 * @returns {number} Returns the index at which `value` should be inserted
7976 * _.sortedIndex([30, 50], 40);
7979 function sortedIndex(array, value) {
7980 return baseSortedIndex(array, value);
7984 * This method is like `_.sortedIndex` except that it accepts `iteratee`
7985 * which is invoked for `value` and each element of `array` to compute their
7986 * sort ranking. The iteratee is invoked with one argument: (value).
7992 * @param {Array} array The sorted array to inspect.
7993 * @param {*} value The value to evaluate.
7994 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7995 * @returns {number} Returns the index at which `value` should be inserted
7999 * var objects = [{ 'x': 4 }, { 'x': 5 }];
8001 * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8004 * // The `_.property` iteratee shorthand.
8005 * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
8008 function sortedIndexBy(array, value, iteratee) {
8009 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
8013 * This method is like `_.indexOf` except that it performs a binary
8014 * search on a sorted `array`.
8020 * @param {Array} array The array to inspect.
8021 * @param {*} value The value to search for.
8022 * @returns {number} Returns the index of the matched value, else `-1`.
8025 * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
8028 function sortedIndexOf(array, value) {
8029 var length = array == null ? 0 : array.length;
8031 var index = baseSortedIndex(array, value);
8032 if (index < length && eq(array[index], value)) {
8040 * This method is like `_.sortedIndex` except that it returns the highest
8041 * index at which `value` should be inserted into `array` in order to
8042 * maintain its sort order.
8048 * @param {Array} array The sorted array to inspect.
8049 * @param {*} value The value to evaluate.
8050 * @returns {number} Returns the index at which `value` should be inserted
8054 * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
8057 function sortedLastIndex(array, value) {
8058 return baseSortedIndex(array, value, true);
8062 * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
8063 * which is invoked for `value` and each element of `array` to compute their
8064 * sort ranking. The iteratee is invoked with one argument: (value).
8070 * @param {Array} array The sorted array to inspect.
8071 * @param {*} value The value to evaluate.
8072 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8073 * @returns {number} Returns the index at which `value` should be inserted
8077 * var objects = [{ 'x': 4 }, { 'x': 5 }];
8079 * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8082 * // The `_.property` iteratee shorthand.
8083 * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
8086 function sortedLastIndexBy(array, value, iteratee) {
8087 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
8091 * This method is like `_.lastIndexOf` except that it performs a binary
8092 * search on a sorted `array`.
8098 * @param {Array} array The array to inspect.
8099 * @param {*} value The value to search for.
8100 * @returns {number} Returns the index of the matched value, else `-1`.
8103 * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
8106 function sortedLastIndexOf(array, value) {
8107 var length = array == null ? 0 : array.length;
8109 var index = baseSortedIndex(array, value, true) - 1;
8110 if (eq(array[index], value)) {
8118 * This method is like `_.uniq` except that it's designed and optimized
8119 * for sorted arrays.
8125 * @param {Array} array The array to inspect.
8126 * @returns {Array} Returns the new duplicate free array.
8129 * _.sortedUniq([1, 1, 2]);
8132 function sortedUniq(array) {
8133 return (array && array.length)
8134 ? baseSortedUniq(array)
8139 * This method is like `_.uniqBy` except that it's designed and optimized
8140 * for sorted arrays.
8146 * @param {Array} array The array to inspect.
8147 * @param {Function} [iteratee] The iteratee invoked per element.
8148 * @returns {Array} Returns the new duplicate free array.
8151 * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
8154 function sortedUniqBy(array, iteratee) {
8155 return (array && array.length)
8156 ? baseSortedUniq(array, getIteratee(iteratee, 2))
8161 * Gets all but the first element of `array`.
8167 * @param {Array} array The array to query.
8168 * @returns {Array} Returns the slice of `array`.
8171 * _.tail([1, 2, 3]);
8174 function tail(array) {
8175 var length = array == null ? 0 : array.length;
8176 return length ? baseSlice(array, 1, length) : [];
8180 * Creates a slice of `array` with `n` elements taken from the beginning.
8186 * @param {Array} array The array to query.
8187 * @param {number} [n=1] The number of elements to take.
8188 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8189 * @returns {Array} Returns the slice of `array`.
8192 * _.take([1, 2, 3]);
8195 * _.take([1, 2, 3], 2);
8198 * _.take([1, 2, 3], 5);
8201 * _.take([1, 2, 3], 0);
8204 function take(array, n, guard) {
8205 if (!(array && array.length)) {
8208 n = (guard || n === undefined) ? 1 : toInteger(n);
8209 return baseSlice(array, 0, n < 0 ? 0 : n);
8213 * Creates a slice of `array` with `n` elements taken from the end.
8219 * @param {Array} array The array to query.
8220 * @param {number} [n=1] The number of elements to take.
8221 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8222 * @returns {Array} Returns the slice of `array`.
8225 * _.takeRight([1, 2, 3]);
8228 * _.takeRight([1, 2, 3], 2);
8231 * _.takeRight([1, 2, 3], 5);
8234 * _.takeRight([1, 2, 3], 0);
8237 function takeRight(array, n, guard) {
8238 var length = array == null ? 0 : array.length;
8242 n = (guard || n === undefined) ? 1 : toInteger(n);
8244 return baseSlice(array, n < 0 ? 0 : n, length);
8248 * Creates a slice of `array` with elements taken from the end. Elements are
8249 * taken until `predicate` returns falsey. The predicate is invoked with
8250 * three arguments: (value, index, array).
8256 * @param {Array} array The array to query.
8257 * @param {Function} [predicate=_.identity] The function invoked per iteration.
8258 * @returns {Array} Returns the slice of `array`.
8262 * { 'user': 'barney', 'active': true },
8263 * { 'user': 'fred', 'active': false },
8264 * { 'user': 'pebbles', 'active': false }
8267 * _.takeRightWhile(users, function(o) { return !o.active; });
8268 * // => objects for ['fred', 'pebbles']
8270 * // The `_.matches` iteratee shorthand.
8271 * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
8272 * // => objects for ['pebbles']
8274 * // The `_.matchesProperty` iteratee shorthand.
8275 * _.takeRightWhile(users, ['active', false]);
8276 * // => objects for ['fred', 'pebbles']
8278 * // The `_.property` iteratee shorthand.
8279 * _.takeRightWhile(users, 'active');
8282 function takeRightWhile(array, predicate) {
8283 return (array && array.length)
8284 ? baseWhile(array, getIteratee(predicate, 3), false, true)
8289 * Creates a slice of `array` with elements taken from the beginning. Elements
8290 * are taken until `predicate` returns falsey. The predicate is invoked with
8291 * three arguments: (value, index, array).
8297 * @param {Array} array The array to query.
8298 * @param {Function} [predicate=_.identity] The function invoked per iteration.
8299 * @returns {Array} Returns the slice of `array`.
8303 * { 'user': 'barney', 'active': false },
8304 * { 'user': 'fred', 'active': false },
8305 * { 'user': 'pebbles', 'active': true }
8308 * _.takeWhile(users, function(o) { return !o.active; });
8309 * // => objects for ['barney', 'fred']
8311 * // The `_.matches` iteratee shorthand.
8312 * _.takeWhile(users, { 'user': 'barney', 'active': false });
8313 * // => objects for ['barney']
8315 * // The `_.matchesProperty` iteratee shorthand.
8316 * _.takeWhile(users, ['active', false]);
8317 * // => objects for ['barney', 'fred']
8319 * // The `_.property` iteratee shorthand.
8320 * _.takeWhile(users, 'active');
8323 function takeWhile(array, predicate) {
8324 return (array && array.length)
8325 ? baseWhile(array, getIteratee(predicate, 3))
8330 * Creates an array of unique values, in order, from all given arrays using
8331 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8332 * for equality comparisons.
8338 * @param {...Array} [arrays] The arrays to inspect.
8339 * @returns {Array} Returns the new array of combined values.
8342 * _.union([2], [1, 2]);
8345 var union = baseRest(function(arrays) {
8346 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
8350 * This method is like `_.union` except that it accepts `iteratee` which is
8351 * invoked for each element of each `arrays` to generate the criterion by
8352 * which uniqueness is computed. Result values are chosen from the first
8353 * array in which the value occurs. The iteratee is invoked with one argument:
8360 * @param {...Array} [arrays] The arrays to inspect.
8361 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8362 * @returns {Array} Returns the new array of combined values.
8365 * _.unionBy([2.1], [1.2, 2.3], Math.floor);
8368 * // The `_.property` iteratee shorthand.
8369 * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8370 * // => [{ 'x': 1 }, { 'x': 2 }]
8372 var unionBy = baseRest(function(arrays) {
8373 var iteratee = last(arrays);
8374 if (isArrayLikeObject(iteratee)) {
8375 iteratee = undefined;
8377 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
8381 * This method is like `_.union` except that it accepts `comparator` which
8382 * is invoked to compare elements of `arrays`. Result values are chosen from
8383 * the first array in which the value occurs. The comparator is invoked
8384 * with two arguments: (arrVal, othVal).
8390 * @param {...Array} [arrays] The arrays to inspect.
8391 * @param {Function} [comparator] The comparator invoked per element.
8392 * @returns {Array} Returns the new array of combined values.
8395 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8396 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8398 * _.unionWith(objects, others, _.isEqual);
8399 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8401 var unionWith = baseRest(function(arrays) {
8402 var comparator = last(arrays);
8403 comparator = typeof comparator == 'function' ? comparator : undefined;
8404 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
8408 * Creates a duplicate-free version of an array, using
8409 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8410 * for equality comparisons, in which only the first occurrence of each element
8411 * is kept. The order of result values is determined by the order they occur
8418 * @param {Array} array The array to inspect.
8419 * @returns {Array} Returns the new duplicate free array.
8422 * _.uniq([2, 1, 2]);
8425 function uniq(array) {
8426 return (array && array.length) ? baseUniq(array) : [];
8430 * This method is like `_.uniq` except that it accepts `iteratee` which is
8431 * invoked for each element in `array` to generate the criterion by which
8432 * uniqueness is computed. The order of result values is determined by the
8433 * order they occur in the array. The iteratee is invoked with one argument:
8440 * @param {Array} array The array to inspect.
8441 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8442 * @returns {Array} Returns the new duplicate free array.
8445 * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
8448 * // The `_.property` iteratee shorthand.
8449 * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
8450 * // => [{ 'x': 1 }, { 'x': 2 }]
8452 function uniqBy(array, iteratee) {
8453 return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
8457 * This method is like `_.uniq` except that it accepts `comparator` which
8458 * is invoked to compare elements of `array`. The order of result values is
8459 * determined by the order they occur in the array.The comparator is invoked
8460 * with two arguments: (arrVal, othVal).
8466 * @param {Array} array The array to inspect.
8467 * @param {Function} [comparator] The comparator invoked per element.
8468 * @returns {Array} Returns the new duplicate free array.
8471 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
8473 * _.uniqWith(objects, _.isEqual);
8474 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
8476 function uniqWith(array, comparator) {
8477 comparator = typeof comparator == 'function' ? comparator : undefined;
8478 return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
8482 * This method is like `_.zip` except that it accepts an array of grouped
8483 * elements and creates an array regrouping the elements to their pre-zip
8490 * @param {Array} array The array of grouped elements to process.
8491 * @returns {Array} Returns the new array of regrouped elements.
8494 * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
8495 * // => [['a', 1, true], ['b', 2, false]]
8498 * // => [['a', 'b'], [1, 2], [true, false]]
8500 function unzip(array) {
8501 if (!(array && array.length)) {
8505 array = arrayFilter(array, function(group) {
8506 if (isArrayLikeObject(group)) {
8507 length = nativeMax(group.length, length);
8511 return baseTimes(length, function(index) {
8512 return arrayMap(array, baseProperty(index));
8517 * This method is like `_.unzip` except that it accepts `iteratee` to specify
8518 * how regrouped values should be combined. The iteratee is invoked with the
8519 * elements of each group: (...group).
8525 * @param {Array} array The array of grouped elements to process.
8526 * @param {Function} [iteratee=_.identity] The function to combine
8528 * @returns {Array} Returns the new array of regrouped elements.
8531 * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
8532 * // => [[1, 10, 100], [2, 20, 200]]
8534 * _.unzipWith(zipped, _.add);
8535 * // => [3, 30, 300]
8537 function unzipWith(array, iteratee) {
8538 if (!(array && array.length)) {
8541 var result = unzip(array);
8542 if (iteratee == null) {
8545 return arrayMap(result, function(group) {
8546 return apply(iteratee, undefined, group);
8551 * Creates an array excluding all given values using
8552 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8553 * for equality comparisons.
8555 * **Note:** Unlike `_.pull`, this method returns a new array.
8561 * @param {Array} array The array to inspect.
8562 * @param {...*} [values] The values to exclude.
8563 * @returns {Array} Returns the new array of filtered values.
8564 * @see _.difference, _.xor
8567 * _.without([2, 1, 2, 3], 1, 2);
8570 var without = baseRest(function(array, values) {
8571 return isArrayLikeObject(array)
8572 ? baseDifference(array, values)
8577 * Creates an array of unique values that is the
8578 * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
8579 * of the given arrays. The order of result values is determined by the order
8580 * they occur in the arrays.
8586 * @param {...Array} [arrays] The arrays to inspect.
8587 * @returns {Array} Returns the new array of filtered values.
8588 * @see _.difference, _.without
8591 * _.xor([2, 1], [2, 3]);
8594 var xor = baseRest(function(arrays) {
8595 return baseXor(arrayFilter(arrays, isArrayLikeObject));
8599 * This method is like `_.xor` except that it accepts `iteratee` which is
8600 * invoked for each element of each `arrays` to generate the criterion by
8601 * which by which they're compared. The order of result values is determined
8602 * by the order they occur in the arrays. The iteratee is invoked with one
8603 * argument: (value).
8609 * @param {...Array} [arrays] The arrays to inspect.
8610 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8611 * @returns {Array} Returns the new array of filtered values.
8614 * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
8617 * // The `_.property` iteratee shorthand.
8618 * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8619 * // => [{ 'x': 2 }]
8621 var xorBy = baseRest(function(arrays) {
8622 var iteratee = last(arrays);
8623 if (isArrayLikeObject(iteratee)) {
8624 iteratee = undefined;
8626 return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
8630 * This method is like `_.xor` except that it accepts `comparator` which is
8631 * invoked to compare elements of `arrays`. The order of result values is
8632 * determined by the order they occur in the arrays. The comparator is invoked
8633 * with two arguments: (arrVal, othVal).
8639 * @param {...Array} [arrays] The arrays to inspect.
8640 * @param {Function} [comparator] The comparator invoked per element.
8641 * @returns {Array} Returns the new array of filtered values.
8644 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8645 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8647 * _.xorWith(objects, others, _.isEqual);
8648 * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8650 var xorWith = baseRest(function(arrays) {
8651 var comparator = last(arrays);
8652 comparator = typeof comparator == 'function' ? comparator : undefined;
8653 return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
8657 * Creates an array of grouped elements, the first of which contains the
8658 * first elements of the given arrays, the second of which contains the
8659 * second elements of the given arrays, and so on.
8665 * @param {...Array} [arrays] The arrays to process.
8666 * @returns {Array} Returns the new array of grouped elements.
8669 * _.zip(['a', 'b'], [1, 2], [true, false]);
8670 * // => [['a', 1, true], ['b', 2, false]]
8672 var zip = baseRest(unzip);
8675 * This method is like `_.fromPairs` except that it accepts two arrays,
8676 * one of property identifiers and one of corresponding values.
8682 * @param {Array} [props=[]] The property identifiers.
8683 * @param {Array} [values=[]] The property values.
8684 * @returns {Object} Returns the new object.
8687 * _.zipObject(['a', 'b'], [1, 2]);
8688 * // => { 'a': 1, 'b': 2 }
8690 function zipObject(props, values) {
8691 return baseZipObject(props || [], values || [], assignValue);
8695 * This method is like `_.zipObject` except that it supports property paths.
8701 * @param {Array} [props=[]] The property identifiers.
8702 * @param {Array} [values=[]] The property values.
8703 * @returns {Object} Returns the new object.
8706 * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
8707 * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
8709 function zipObjectDeep(props, values) {
8710 return baseZipObject(props || [], values || [], baseSet);
8714 * This method is like `_.zip` except that it accepts `iteratee` to specify
8715 * how grouped values should be combined. The iteratee is invoked with the
8716 * elements of each group: (...group).
8722 * @param {...Array} [arrays] The arrays to process.
8723 * @param {Function} [iteratee=_.identity] The function to combine
8725 * @returns {Array} Returns the new array of grouped elements.
8728 * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
8733 var zipWith = baseRest(function(arrays) {
8734 var length = arrays.length,
8735 iteratee = length > 1 ? arrays[length - 1] : undefined;
8737 iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
8738 return unzipWith(arrays, iteratee);
8741 /*------------------------------------------------------------------------*/
8744 * Creates a `lodash` wrapper instance that wraps `value` with explicit method
8745 * chain sequences enabled. The result of such sequences must be unwrapped
8752 * @param {*} value The value to wrap.
8753 * @returns {Object} Returns the new `lodash` wrapper instance.
8757 * { 'user': 'barney', 'age': 36 },
8758 * { 'user': 'fred', 'age': 40 },
8759 * { 'user': 'pebbles', 'age': 1 }
8765 * .map(function(o) {
8766 * return o.user + ' is ' + o.age;
8770 * // => 'pebbles is 1'
8772 function chain(value) {
8773 var result = lodash(value);
8774 result.__chain__ = true;
8779 * This method invokes `interceptor` and returns `value`. The interceptor
8780 * is invoked with one argument; (value). The purpose of this method is to
8781 * "tap into" a method chain sequence in order to modify intermediate results.
8787 * @param {*} value The value to provide to `interceptor`.
8788 * @param {Function} interceptor The function to invoke.
8789 * @returns {*} Returns `value`.
8793 * .tap(function(array) {
8794 * // Mutate input array.
8801 function tap(value, interceptor) {
8807 * This method is like `_.tap` except that it returns the result of `interceptor`.
8808 * The purpose of this method is to "pass thru" values replacing intermediate
8809 * results in a method chain sequence.
8815 * @param {*} value The value to provide to `interceptor`.
8816 * @param {Function} interceptor The function to invoke.
8817 * @returns {*} Returns the result of `interceptor`.
8823 * .thru(function(value) {
8829 function thru(value, interceptor) {
8830 return interceptor(value);
8834 * This method is the wrapper version of `_.at`.
8840 * @param {...(string|string[])} [paths] The property paths to pick.
8841 * @returns {Object} Returns the new `lodash` wrapper instance.
8844 * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
8846 * _(object).at(['a[0].b.c', 'a[1]']).value();
8849 var wrapperAt = flatRest(function(paths) {
8850 var length = paths.length,
8851 start = length ? paths[0] : 0,
8852 value = this.__wrapped__,
8853 interceptor = function(object) { return baseAt(object, paths); };
8855 if (length > 1 || this.__actions__.length ||
8856 !(value instanceof LazyWrapper) || !isIndex(start)) {
8857 return this.thru(interceptor);
8859 value = value.slice(start, +start + (length ? 1 : 0));
8860 value.__actions__.push({
8862 'args': [interceptor],
8863 'thisArg': undefined
8865 return new LodashWrapper(value, this.__chain__).thru(function(array) {
8866 if (length && !array.length) {
8867 array.push(undefined);
8874 * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
8880 * @returns {Object} Returns the new `lodash` wrapper instance.
8884 * { 'user': 'barney', 'age': 36 },
8885 * { 'user': 'fred', 'age': 40 }
8888 * // A sequence without explicit chaining.
8890 * // => { 'user': 'barney', 'age': 36 }
8892 * // A sequence with explicit chaining.
8898 * // => { 'user': 'barney' }
8900 function wrapperChain() {
8905 * Executes the chain sequence and returns the wrapped result.
8911 * @returns {Object} Returns the new `lodash` wrapper instance.
8914 * var array = [1, 2];
8915 * var wrapped = _(array).push(3);
8917 * console.log(array);
8920 * wrapped = wrapped.commit();
8921 * console.log(array);
8927 * console.log(array);
8930 function wrapperCommit() {
8931 return new LodashWrapper(this.value(), this.__chain__);
8935 * Gets the next value on a wrapped object following the
8936 * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
8942 * @returns {Object} Returns the next iterator value.
8945 * var wrapped = _([1, 2]);
8948 * // => { 'done': false, 'value': 1 }
8951 * // => { 'done': false, 'value': 2 }
8954 * // => { 'done': true, 'value': undefined }
8956 function wrapperNext() {
8957 if (this.__values__ === undefined) {
8958 this.__values__ = toArray(this.value());
8960 var done = this.__index__ >= this.__values__.length,
8961 value = done ? undefined : this.__values__[this.__index__++];
8963 return { 'done': done, 'value': value };
8967 * Enables the wrapper to be iterable.
8969 * @name Symbol.iterator
8973 * @returns {Object} Returns the wrapper object.
8976 * var wrapped = _([1, 2]);
8978 * wrapped[Symbol.iterator]() === wrapped;
8981 * Array.from(wrapped);
8984 function wrapperToIterator() {
8989 * Creates a clone of the chain sequence planting `value` as the wrapped value.
8995 * @param {*} value The value to plant.
8996 * @returns {Object} Returns the new `lodash` wrapper instance.
8999 * function square(n) {
9003 * var wrapped = _([1, 2]).map(square);
9004 * var other = wrapped.plant([3, 4]);
9012 function wrapperPlant(value) {
9016 while (parent instanceof baseLodash) {
9017 var clone = wrapperClone(parent);
9018 clone.__index__ = 0;
9019 clone.__values__ = undefined;
9021 previous.__wrapped__ = clone;
9025 var previous = clone;
9026 parent = parent.__wrapped__;
9028 previous.__wrapped__ = value;
9033 * This method is the wrapper version of `_.reverse`.
9035 * **Note:** This method mutates the wrapped array.
9041 * @returns {Object} Returns the new `lodash` wrapper instance.
9044 * var array = [1, 2, 3];
9046 * _(array).reverse().value()
9049 * console.log(array);
9052 function wrapperReverse() {
9053 var value = this.__wrapped__;
9054 if (value instanceof LazyWrapper) {
9055 var wrapped = value;
9056 if (this.__actions__.length) {
9057 wrapped = new LazyWrapper(this);
9059 wrapped = wrapped.reverse();
9060 wrapped.__actions__.push({
9063 'thisArg': undefined
9065 return new LodashWrapper(wrapped, this.__chain__);
9067 return this.thru(reverse);
9071 * Executes the chain sequence to resolve the unwrapped value.
9076 * @alias toJSON, valueOf
9078 * @returns {*} Returns the resolved unwrapped value.
9081 * _([1, 2, 3]).value();
9084 function wrapperValue() {
9085 return baseWrapperValue(this.__wrapped__, this.__actions__);
9088 /*------------------------------------------------------------------------*/
9091 * Creates an object composed of keys generated from the results of running
9092 * each element of `collection` thru `iteratee`. The corresponding value of
9093 * each key is the number of times the key was returned by `iteratee`. The
9094 * iteratee is invoked with one argument: (value).
9099 * @category Collection
9100 * @param {Array|Object} collection The collection to iterate over.
9101 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9102 * @returns {Object} Returns the composed aggregate object.
9105 * _.countBy([6.1, 4.2, 6.3], Math.floor);
9106 * // => { '4': 1, '6': 2 }
9108 * // The `_.property` iteratee shorthand.
9109 * _.countBy(['one', 'two', 'three'], 'length');
9110 * // => { '3': 2, '5': 1 }
9112 var countBy = createAggregator(function(result, value, key) {
9113 if (hasOwnProperty.call(result, key)) {
9116 baseAssignValue(result, key, 1);
9121 * Checks if `predicate` returns truthy for **all** elements of `collection`.
9122 * Iteration is stopped once `predicate` returns falsey. The predicate is
9123 * invoked with three arguments: (value, index|key, collection).
9125 * **Note:** This method returns `true` for
9126 * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
9127 * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
9128 * elements of empty collections.
9133 * @category Collection
9134 * @param {Array|Object} collection The collection to iterate over.
9135 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9136 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9137 * @returns {boolean} Returns `true` if all elements pass the predicate check,
9141 * _.every([true, 1, null, 'yes'], Boolean);
9145 * { 'user': 'barney', 'age': 36, 'active': false },
9146 * { 'user': 'fred', 'age': 40, 'active': false }
9149 * // The `_.matches` iteratee shorthand.
9150 * _.every(users, { 'user': 'barney', 'active': false });
9153 * // The `_.matchesProperty` iteratee shorthand.
9154 * _.every(users, ['active', false]);
9157 * // The `_.property` iteratee shorthand.
9158 * _.every(users, 'active');
9161 function every(collection, predicate, guard) {
9162 var func = isArray(collection) ? arrayEvery : baseEvery;
9163 if (guard && isIterateeCall(collection, predicate, guard)) {
9164 predicate = undefined;
9166 return func(collection, getIteratee(predicate, 3));
9170 * Iterates over elements of `collection`, returning an array of all elements
9171 * `predicate` returns truthy for. The predicate is invoked with three
9172 * arguments: (value, index|key, collection).
9174 * **Note:** Unlike `_.remove`, this method returns a new array.
9179 * @category Collection
9180 * @param {Array|Object} collection The collection to iterate over.
9181 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9182 * @returns {Array} Returns the new filtered array.
9187 * { 'user': 'barney', 'age': 36, 'active': true },
9188 * { 'user': 'fred', 'age': 40, 'active': false }
9191 * _.filter(users, function(o) { return !o.active; });
9192 * // => objects for ['fred']
9194 * // The `_.matches` iteratee shorthand.
9195 * _.filter(users, { 'age': 36, 'active': true });
9196 * // => objects for ['barney']
9198 * // The `_.matchesProperty` iteratee shorthand.
9199 * _.filter(users, ['active', false]);
9200 * // => objects for ['fred']
9202 * // The `_.property` iteratee shorthand.
9203 * _.filter(users, 'active');
9204 * // => objects for ['barney']
9206 function filter(collection, predicate) {
9207 var func = isArray(collection) ? arrayFilter : baseFilter;
9208 return func(collection, getIteratee(predicate, 3));
9212 * Iterates over elements of `collection`, returning the first element
9213 * `predicate` returns truthy for. The predicate is invoked with three
9214 * arguments: (value, index|key, collection).
9219 * @category Collection
9220 * @param {Array|Object} collection The collection to inspect.
9221 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9222 * @param {number} [fromIndex=0] The index to search from.
9223 * @returns {*} Returns the matched element, else `undefined`.
9227 * { 'user': 'barney', 'age': 36, 'active': true },
9228 * { 'user': 'fred', 'age': 40, 'active': false },
9229 * { 'user': 'pebbles', 'age': 1, 'active': true }
9232 * _.find(users, function(o) { return o.age < 40; });
9233 * // => object for 'barney'
9235 * // The `_.matches` iteratee shorthand.
9236 * _.find(users, { 'age': 1, 'active': true });
9237 * // => object for 'pebbles'
9239 * // The `_.matchesProperty` iteratee shorthand.
9240 * _.find(users, ['active', false]);
9241 * // => object for 'fred'
9243 * // The `_.property` iteratee shorthand.
9244 * _.find(users, 'active');
9245 * // => object for 'barney'
9247 var find = createFind(findIndex);
9250 * This method is like `_.find` except that it iterates over elements of
9251 * `collection` from right to left.
9256 * @category Collection
9257 * @param {Array|Object} collection The collection to inspect.
9258 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9259 * @param {number} [fromIndex=collection.length-1] The index to search from.
9260 * @returns {*} Returns the matched element, else `undefined`.
9263 * _.findLast([1, 2, 3, 4], function(n) {
9264 * return n % 2 == 1;
9268 var findLast = createFind(findLastIndex);
9271 * Creates a flattened array of values by running each element in `collection`
9272 * thru `iteratee` and flattening the mapped results. The iteratee is invoked
9273 * with three arguments: (value, index|key, collection).
9278 * @category Collection
9279 * @param {Array|Object} collection The collection to iterate over.
9280 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9281 * @returns {Array} Returns the new flattened array.
9284 * function duplicate(n) {
9288 * _.flatMap([1, 2], duplicate);
9289 * // => [1, 1, 2, 2]
9291 function flatMap(collection, iteratee) {
9292 return baseFlatten(map(collection, iteratee), 1);
9296 * This method is like `_.flatMap` except that it recursively flattens the
9302 * @category Collection
9303 * @param {Array|Object} collection The collection to iterate over.
9304 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9305 * @returns {Array} Returns the new flattened array.
9308 * function duplicate(n) {
9309 * return [[[n, n]]];
9312 * _.flatMapDeep([1, 2], duplicate);
9313 * // => [1, 1, 2, 2]
9315 function flatMapDeep(collection, iteratee) {
9316 return baseFlatten(map(collection, iteratee), INFINITY);
9320 * This method is like `_.flatMap` except that it recursively flattens the
9321 * mapped results up to `depth` times.
9326 * @category Collection
9327 * @param {Array|Object} collection The collection to iterate over.
9328 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9329 * @param {number} [depth=1] The maximum recursion depth.
9330 * @returns {Array} Returns the new flattened array.
9333 * function duplicate(n) {
9334 * return [[[n, n]]];
9337 * _.flatMapDepth([1, 2], duplicate, 2);
9338 * // => [[1, 1], [2, 2]]
9340 function flatMapDepth(collection, iteratee, depth) {
9341 depth = depth === undefined ? 1 : toInteger(depth);
9342 return baseFlatten(map(collection, iteratee), depth);
9346 * Iterates over elements of `collection` and invokes `iteratee` for each element.
9347 * The iteratee is invoked with three arguments: (value, index|key, collection).
9348 * Iteratee functions may exit iteration early by explicitly returning `false`.
9350 * **Note:** As with other "Collections" methods, objects with a "length"
9351 * property are iterated like arrays. To avoid this behavior use `_.forIn`
9352 * or `_.forOwn` for object iteration.
9358 * @category Collection
9359 * @param {Array|Object} collection The collection to iterate over.
9360 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9361 * @returns {Array|Object} Returns `collection`.
9362 * @see _.forEachRight
9365 * _.forEach([1, 2], function(value) {
9366 * console.log(value);
9368 * // => Logs `1` then `2`.
9370 * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
9373 * // => Logs 'a' then 'b' (iteration order is not guaranteed).
9375 function forEach(collection, iteratee) {
9376 var func = isArray(collection) ? arrayEach : baseEach;
9377 return func(collection, getIteratee(iteratee, 3));
9381 * This method is like `_.forEach` except that it iterates over elements of
9382 * `collection` from right to left.
9388 * @category Collection
9389 * @param {Array|Object} collection The collection to iterate over.
9390 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9391 * @returns {Array|Object} Returns `collection`.
9395 * _.forEachRight([1, 2], function(value) {
9396 * console.log(value);
9398 * // => Logs `2` then `1`.
9400 function forEachRight(collection, iteratee) {
9401 var func = isArray(collection) ? arrayEachRight : baseEachRight;
9402 return func(collection, getIteratee(iteratee, 3));
9406 * Creates an object composed of keys generated from the results of running
9407 * each element of `collection` thru `iteratee`. The order of grouped values
9408 * is determined by the order they occur in `collection`. The corresponding
9409 * value of each key is an array of elements responsible for generating the
9410 * key. The iteratee is invoked with one argument: (value).
9415 * @category Collection
9416 * @param {Array|Object} collection The collection to iterate over.
9417 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9418 * @returns {Object} Returns the composed aggregate object.
9421 * _.groupBy([6.1, 4.2, 6.3], Math.floor);
9422 * // => { '4': [4.2], '6': [6.1, 6.3] }
9424 * // The `_.property` iteratee shorthand.
9425 * _.groupBy(['one', 'two', 'three'], 'length');
9426 * // => { '3': ['one', 'two'], '5': ['three'] }
9428 var groupBy = createAggregator(function(result, value, key) {
9429 if (hasOwnProperty.call(result, key)) {
9430 result[key].push(value);
9432 baseAssignValue(result, key, [value]);
9437 * Checks if `value` is in `collection`. If `collection` is a string, it's
9438 * checked for a substring of `value`, otherwise
9439 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
9440 * is used for equality comparisons. If `fromIndex` is negative, it's used as
9441 * the offset from the end of `collection`.
9446 * @category Collection
9447 * @param {Array|Object|string} collection The collection to inspect.
9448 * @param {*} value The value to search for.
9449 * @param {number} [fromIndex=0] The index to search from.
9450 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9451 * @returns {boolean} Returns `true` if `value` is found, else `false`.
9454 * _.includes([1, 2, 3], 1);
9457 * _.includes([1, 2, 3], 1, 2);
9460 * _.includes({ 'a': 1, 'b': 2 }, 1);
9463 * _.includes('abcd', 'bc');
9466 function includes(collection, value, fromIndex, guard) {
9467 collection = isArrayLike(collection) ? collection : values(collection);
9468 fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
9470 var length = collection.length;
9471 if (fromIndex < 0) {
9472 fromIndex = nativeMax(length + fromIndex, 0);
9474 return isString(collection)
9475 ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
9476 : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
9480 * Invokes the method at `path` of each element in `collection`, returning
9481 * an array of the results of each invoked method. Any additional arguments
9482 * are provided to each invoked method. If `path` is a function, it's invoked
9483 * for, and `this` bound to, each element in `collection`.
9488 * @category Collection
9489 * @param {Array|Object} collection The collection to iterate over.
9490 * @param {Array|Function|string} path The path of the method to invoke or
9491 * the function invoked per iteration.
9492 * @param {...*} [args] The arguments to invoke each method with.
9493 * @returns {Array} Returns the array of results.
9496 * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
9497 * // => [[1, 5, 7], [1, 2, 3]]
9499 * _.invokeMap([123, 456], String.prototype.split, '');
9500 * // => [['1', '2', '3'], ['4', '5', '6']]
9502 var invokeMap = baseRest(function(collection, path, args) {
9504 isFunc = typeof path == 'function',
9505 result = isArrayLike(collection) ? Array(collection.length) : [];
9507 baseEach(collection, function(value) {
9508 result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
9514 * Creates an object composed of keys generated from the results of running
9515 * each element of `collection` thru `iteratee`. The corresponding value of
9516 * each key is the last element responsible for generating the key. The
9517 * iteratee is invoked with one argument: (value).
9522 * @category Collection
9523 * @param {Array|Object} collection The collection to iterate over.
9524 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9525 * @returns {Object} Returns the composed aggregate object.
9529 * { 'dir': 'left', 'code': 97 },
9530 * { 'dir': 'right', 'code': 100 }
9533 * _.keyBy(array, function(o) {
9534 * return String.fromCharCode(o.code);
9536 * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
9538 * _.keyBy(array, 'dir');
9539 * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
9541 var keyBy = createAggregator(function(result, value, key) {
9542 baseAssignValue(result, key, value);
9546 * Creates an array of values by running each element in `collection` thru
9547 * `iteratee`. The iteratee is invoked with three arguments:
9548 * (value, index|key, collection).
9550 * Many lodash methods are guarded to work as iteratees for methods like
9551 * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
9553 * The guarded methods are:
9554 * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
9555 * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
9556 * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
9557 * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
9562 * @category Collection
9563 * @param {Array|Object} collection The collection to iterate over.
9564 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9565 * @returns {Array} Returns the new mapped array.
9568 * function square(n) {
9572 * _.map([4, 8], square);
9575 * _.map({ 'a': 4, 'b': 8 }, square);
9576 * // => [16, 64] (iteration order is not guaranteed)
9579 * { 'user': 'barney' },
9580 * { 'user': 'fred' }
9583 * // The `_.property` iteratee shorthand.
9584 * _.map(users, 'user');
9585 * // => ['barney', 'fred']
9587 function map(collection, iteratee) {
9588 var func = isArray(collection) ? arrayMap : baseMap;
9589 return func(collection, getIteratee(iteratee, 3));
9593 * This method is like `_.sortBy` except that it allows specifying the sort
9594 * orders of the iteratees to sort by. If `orders` is unspecified, all values
9595 * are sorted in ascending order. Otherwise, specify an order of "desc" for
9596 * descending or "asc" for ascending sort order of corresponding values.
9601 * @category Collection
9602 * @param {Array|Object} collection The collection to iterate over.
9603 * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
9604 * The iteratees to sort by.
9605 * @param {string[]} [orders] The sort orders of `iteratees`.
9606 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9607 * @returns {Array} Returns the new sorted array.
9611 * { 'user': 'fred', 'age': 48 },
9612 * { 'user': 'barney', 'age': 34 },
9613 * { 'user': 'fred', 'age': 40 },
9614 * { 'user': 'barney', 'age': 36 }
9617 * // Sort by `user` in ascending order and by `age` in descending order.
9618 * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
9619 * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9621 function orderBy(collection, iteratees, orders, guard) {
9622 if (collection == null) {
9625 if (!isArray(iteratees)) {
9626 iteratees = iteratees == null ? [] : [iteratees];
9628 orders = guard ? undefined : orders;
9629 if (!isArray(orders)) {
9630 orders = orders == null ? [] : [orders];
9632 return baseOrderBy(collection, iteratees, orders);
9636 * Creates an array of elements split into two groups, the first of which
9637 * contains elements `predicate` returns truthy for, the second of which
9638 * contains elements `predicate` returns falsey for. The predicate is
9639 * invoked with one argument: (value).
9644 * @category Collection
9645 * @param {Array|Object} collection The collection to iterate over.
9646 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9647 * @returns {Array} Returns the array of grouped elements.
9651 * { 'user': 'barney', 'age': 36, 'active': false },
9652 * { 'user': 'fred', 'age': 40, 'active': true },
9653 * { 'user': 'pebbles', 'age': 1, 'active': false }
9656 * _.partition(users, function(o) { return o.active; });
9657 * // => objects for [['fred'], ['barney', 'pebbles']]
9659 * // The `_.matches` iteratee shorthand.
9660 * _.partition(users, { 'age': 1, 'active': false });
9661 * // => objects for [['pebbles'], ['barney', 'fred']]
9663 * // The `_.matchesProperty` iteratee shorthand.
9664 * _.partition(users, ['active', false]);
9665 * // => objects for [['barney', 'pebbles'], ['fred']]
9667 * // The `_.property` iteratee shorthand.
9668 * _.partition(users, 'active');
9669 * // => objects for [['fred'], ['barney', 'pebbles']]
9671 var partition = createAggregator(function(result, value, key) {
9672 result[key ? 0 : 1].push(value);
9673 }, function() { return [[], []]; });
9676 * Reduces `collection` to a value which is the accumulated result of running
9677 * each element in `collection` thru `iteratee`, where each successive
9678 * invocation is supplied the return value of the previous. If `accumulator`
9679 * is not given, the first element of `collection` is used as the initial
9680 * value. The iteratee is invoked with four arguments:
9681 * (accumulator, value, index|key, collection).
9683 * Many lodash methods are guarded to work as iteratees for methods like
9684 * `_.reduce`, `_.reduceRight`, and `_.transform`.
9686 * The guarded methods are:
9687 * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
9693 * @category Collection
9694 * @param {Array|Object} collection The collection to iterate over.
9695 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9696 * @param {*} [accumulator] The initial value.
9697 * @returns {*} Returns the accumulated value.
9698 * @see _.reduceRight
9701 * _.reduce([1, 2], function(sum, n) {
9706 * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
9707 * (result[value] || (result[value] = [])).push(key);
9710 * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
9712 function reduce(collection, iteratee, accumulator) {
9713 var func = isArray(collection) ? arrayReduce : baseReduce,
9714 initAccum = arguments.length < 3;
9716 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
9720 * This method is like `_.reduce` except that it iterates over elements of
9721 * `collection` from right to left.
9726 * @category Collection
9727 * @param {Array|Object} collection The collection to iterate over.
9728 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9729 * @param {*} [accumulator] The initial value.
9730 * @returns {*} Returns the accumulated value.
9734 * var array = [[0, 1], [2, 3], [4, 5]];
9736 * _.reduceRight(array, function(flattened, other) {
9737 * return flattened.concat(other);
9739 * // => [4, 5, 2, 3, 0, 1]
9741 function reduceRight(collection, iteratee, accumulator) {
9742 var func = isArray(collection) ? arrayReduceRight : baseReduce,
9743 initAccum = arguments.length < 3;
9745 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
9749 * The opposite of `_.filter`; this method returns the elements of `collection`
9750 * that `predicate` does **not** return truthy for.
9755 * @category Collection
9756 * @param {Array|Object} collection The collection to iterate over.
9757 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9758 * @returns {Array} Returns the new filtered array.
9763 * { 'user': 'barney', 'age': 36, 'active': false },
9764 * { 'user': 'fred', 'age': 40, 'active': true }
9767 * _.reject(users, function(o) { return !o.active; });
9768 * // => objects for ['fred']
9770 * // The `_.matches` iteratee shorthand.
9771 * _.reject(users, { 'age': 40, 'active': true });
9772 * // => objects for ['barney']
9774 * // The `_.matchesProperty` iteratee shorthand.
9775 * _.reject(users, ['active', false]);
9776 * // => objects for ['fred']
9778 * // The `_.property` iteratee shorthand.
9779 * _.reject(users, 'active');
9780 * // => objects for ['barney']
9782 function reject(collection, predicate) {
9783 var func = isArray(collection) ? arrayFilter : baseFilter;
9784 return func(collection, negate(getIteratee(predicate, 3)));
9788 * Gets a random element from `collection`.
9793 * @category Collection
9794 * @param {Array|Object} collection The collection to sample.
9795 * @returns {*} Returns the random element.
9798 * _.sample([1, 2, 3, 4]);
9801 function sample(collection) {
9802 var func = isArray(collection) ? arraySample : baseSample;
9803 return func(collection);
9807 * Gets `n` random elements at unique keys from `collection` up to the
9808 * size of `collection`.
9813 * @category Collection
9814 * @param {Array|Object} collection The collection to sample.
9815 * @param {number} [n=1] The number of elements to sample.
9816 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9817 * @returns {Array} Returns the random elements.
9820 * _.sampleSize([1, 2, 3], 2);
9823 * _.sampleSize([1, 2, 3], 4);
9826 function sampleSize(collection, n, guard) {
9827 if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
9832 var func = isArray(collection) ? arraySampleSize : baseSampleSize;
9833 return func(collection, n);
9837 * Creates an array of shuffled values, using a version of the
9838 * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
9843 * @category Collection
9844 * @param {Array|Object} collection The collection to shuffle.
9845 * @returns {Array} Returns the new shuffled array.
9848 * _.shuffle([1, 2, 3, 4]);
9849 * // => [4, 1, 3, 2]
9851 function shuffle(collection) {
9852 var func = isArray(collection) ? arrayShuffle : baseShuffle;
9853 return func(collection);
9857 * Gets the size of `collection` by returning its length for array-like
9858 * values or the number of own enumerable string keyed properties for objects.
9863 * @category Collection
9864 * @param {Array|Object|string} collection The collection to inspect.
9865 * @returns {number} Returns the collection size.
9868 * _.size([1, 2, 3]);
9871 * _.size({ 'a': 1, 'b': 2 });
9874 * _.size('pebbles');
9877 function size(collection) {
9878 if (collection == null) {
9881 if (isArrayLike(collection)) {
9882 return isString(collection) ? stringSize(collection) : collection.length;
9884 var tag = getTag(collection);
9885 if (tag == mapTag || tag == setTag) {
9886 return collection.size;
9888 return baseKeys(collection).length;
9892 * Checks if `predicate` returns truthy for **any** element of `collection`.
9893 * Iteration is stopped once `predicate` returns truthy. The predicate is
9894 * invoked with three arguments: (value, index|key, collection).
9899 * @category Collection
9900 * @param {Array|Object} collection The collection to iterate over.
9901 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9902 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9903 * @returns {boolean} Returns `true` if any element passes the predicate check,
9907 * _.some([null, 0, 'yes', false], Boolean);
9911 * { 'user': 'barney', 'active': true },
9912 * { 'user': 'fred', 'active': false }
9915 * // The `_.matches` iteratee shorthand.
9916 * _.some(users, { 'user': 'barney', 'active': false });
9919 * // The `_.matchesProperty` iteratee shorthand.
9920 * _.some(users, ['active', false]);
9923 * // The `_.property` iteratee shorthand.
9924 * _.some(users, 'active');
9927 function some(collection, predicate, guard) {
9928 var func = isArray(collection) ? arraySome : baseSome;
9929 if (guard && isIterateeCall(collection, predicate, guard)) {
9930 predicate = undefined;
9932 return func(collection, getIteratee(predicate, 3));
9936 * Creates an array of elements, sorted in ascending order by the results of
9937 * running each element in a collection thru each iteratee. This method
9938 * performs a stable sort, that is, it preserves the original sort order of
9939 * equal elements. The iteratees are invoked with one argument: (value).
9944 * @category Collection
9945 * @param {Array|Object} collection The collection to iterate over.
9946 * @param {...(Function|Function[])} [iteratees=[_.identity]]
9947 * The iteratees to sort by.
9948 * @returns {Array} Returns the new sorted array.
9952 * { 'user': 'fred', 'age': 48 },
9953 * { 'user': 'barney', 'age': 36 },
9954 * { 'user': 'fred', 'age': 40 },
9955 * { 'user': 'barney', 'age': 34 }
9958 * _.sortBy(users, [function(o) { return o.user; }]);
9959 * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9961 * _.sortBy(users, ['user', 'age']);
9962 * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
9964 var sortBy = baseRest(function(collection, iteratees) {
9965 if (collection == null) {
9968 var length = iteratees.length;
9969 if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
9971 } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
9972 iteratees = [iteratees[0]];
9974 return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
9977 /*------------------------------------------------------------------------*/
9980 * Gets the timestamp of the number of milliseconds that have elapsed since
9981 * the Unix epoch (1 January 1970 00:00:00 UTC).
9987 * @returns {number} Returns the timestamp.
9990 * _.defer(function(stamp) {
9991 * console.log(_.now() - stamp);
9993 * // => Logs the number of milliseconds it took for the deferred invocation.
9995 var now = ctxNow || function() {
9996 return root.Date.now();
9999 /*------------------------------------------------------------------------*/
10002 * The opposite of `_.before`; this method creates a function that invokes
10003 * `func` once it's called `n` or more times.
10008 * @category Function
10009 * @param {number} n The number of calls before `func` is invoked.
10010 * @param {Function} func The function to restrict.
10011 * @returns {Function} Returns the new restricted function.
10014 * var saves = ['profile', 'settings'];
10016 * var done = _.after(saves.length, function() {
10017 * console.log('done saving!');
10020 * _.forEach(saves, function(type) {
10021 * asyncSave({ 'type': type, 'complete': done });
10023 * // => Logs 'done saving!' after the two async saves have completed.
10025 function after(n, func) {
10026 if (typeof func != 'function') {
10027 throw new TypeError(FUNC_ERROR_TEXT);
10030 return function() {
10032 return func.apply(this, arguments);
10038 * Creates a function that invokes `func`, with up to `n` arguments,
10039 * ignoring any additional arguments.
10044 * @category Function
10045 * @param {Function} func The function to cap arguments for.
10046 * @param {number} [n=func.length] The arity cap.
10047 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10048 * @returns {Function} Returns the new capped function.
10051 * _.map(['6', '8', '10'], _.ary(parseInt, 1));
10054 function ary(func, n, guard) {
10055 n = guard ? undefined : n;
10056 n = (func && n == null) ? func.length : n;
10057 return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
10061 * Creates a function that invokes `func`, with the `this` binding and arguments
10062 * of the created function, while it's called less than `n` times. Subsequent
10063 * calls to the created function return the result of the last `func` invocation.
10068 * @category Function
10069 * @param {number} n The number of calls at which `func` is no longer invoked.
10070 * @param {Function} func The function to restrict.
10071 * @returns {Function} Returns the new restricted function.
10074 * jQuery(element).on('click', _.before(5, addContactToList));
10075 * // => Allows adding up to 4 contacts to the list.
10077 function before(n, func) {
10079 if (typeof func != 'function') {
10080 throw new TypeError(FUNC_ERROR_TEXT);
10083 return function() {
10085 result = func.apply(this, arguments);
10095 * Creates a function that invokes `func` with the `this` binding of `thisArg`
10096 * and `partials` prepended to the arguments it receives.
10098 * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
10099 * may be used as a placeholder for partially applied arguments.
10101 * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
10102 * property of bound functions.
10107 * @category Function
10108 * @param {Function} func The function to bind.
10109 * @param {*} thisArg The `this` binding of `func`.
10110 * @param {...*} [partials] The arguments to be partially applied.
10111 * @returns {Function} Returns the new bound function.
10114 * function greet(greeting, punctuation) {
10115 * return greeting + ' ' + this.user + punctuation;
10118 * var object = { 'user': 'fred' };
10120 * var bound = _.bind(greet, object, 'hi');
10124 * // Bound with placeholders.
10125 * var bound = _.bind(greet, object, _, '!');
10129 var bind = baseRest(function(func, thisArg, partials) {
10130 var bitmask = WRAP_BIND_FLAG;
10131 if (partials.length) {
10132 var holders = replaceHolders(partials, getHolder(bind));
10133 bitmask |= WRAP_PARTIAL_FLAG;
10135 return createWrap(func, bitmask, thisArg, partials, holders);
10139 * Creates a function that invokes the method at `object[key]` with `partials`
10140 * prepended to the arguments it receives.
10142 * This method differs from `_.bind` by allowing bound functions to reference
10143 * methods that may be redefined or don't yet exist. See
10144 * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
10145 * for more details.
10147 * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
10148 * builds, may be used as a placeholder for partially applied arguments.
10153 * @category Function
10154 * @param {Object} object The object to invoke the method on.
10155 * @param {string} key The key of the method.
10156 * @param {...*} [partials] The arguments to be partially applied.
10157 * @returns {Function} Returns the new bound function.
10162 * 'greet': function(greeting, punctuation) {
10163 * return greeting + ' ' + this.user + punctuation;
10167 * var bound = _.bindKey(object, 'greet', 'hi');
10171 * object.greet = function(greeting, punctuation) {
10172 * return greeting + 'ya ' + this.user + punctuation;
10176 * // => 'hiya fred!'
10178 * // Bound with placeholders.
10179 * var bound = _.bindKey(object, 'greet', _, '!');
10181 * // => 'hiya fred!'
10183 var bindKey = baseRest(function(object, key, partials) {
10184 var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
10185 if (partials.length) {
10186 var holders = replaceHolders(partials, getHolder(bindKey));
10187 bitmask |= WRAP_PARTIAL_FLAG;
10189 return createWrap(key, bitmask, object, partials, holders);
10193 * Creates a function that accepts arguments of `func` and either invokes
10194 * `func` returning its result, if at least `arity` number of arguments have
10195 * been provided, or returns a function that accepts the remaining `func`
10196 * arguments, and so on. The arity of `func` may be specified if `func.length`
10197 * is not sufficient.
10199 * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
10200 * may be used as a placeholder for provided arguments.
10202 * **Note:** This method doesn't set the "length" property of curried functions.
10207 * @category Function
10208 * @param {Function} func The function to curry.
10209 * @param {number} [arity=func.length] The arity of `func`.
10210 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10211 * @returns {Function} Returns the new curried function.
10214 * var abc = function(a, b, c) {
10215 * return [a, b, c];
10218 * var curried = _.curry(abc);
10220 * curried(1)(2)(3);
10223 * curried(1, 2)(3);
10226 * curried(1, 2, 3);
10229 * // Curried with placeholders.
10230 * curried(1)(_, 3)(2);
10233 function curry(func, arity, guard) {
10234 arity = guard ? undefined : arity;
10235 var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10236 result.placeholder = curry.placeholder;
10241 * This method is like `_.curry` except that arguments are applied to `func`
10242 * in the manner of `_.partialRight` instead of `_.partial`.
10244 * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
10245 * builds, may be used as a placeholder for provided arguments.
10247 * **Note:** This method doesn't set the "length" property of curried functions.
10252 * @category Function
10253 * @param {Function} func The function to curry.
10254 * @param {number} [arity=func.length] The arity of `func`.
10255 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10256 * @returns {Function} Returns the new curried function.
10259 * var abc = function(a, b, c) {
10260 * return [a, b, c];
10263 * var curried = _.curryRight(abc);
10265 * curried(3)(2)(1);
10268 * curried(2, 3)(1);
10271 * curried(1, 2, 3);
10274 * // Curried with placeholders.
10275 * curried(3)(1, _)(2);
10278 function curryRight(func, arity, guard) {
10279 arity = guard ? undefined : arity;
10280 var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10281 result.placeholder = curryRight.placeholder;
10286 * Creates a debounced function that delays invoking `func` until after `wait`
10287 * milliseconds have elapsed since the last time the debounced function was
10288 * invoked. The debounced function comes with a `cancel` method to cancel
10289 * delayed `func` invocations and a `flush` method to immediately invoke them.
10290 * Provide `options` to indicate whether `func` should be invoked on the
10291 * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
10292 * with the last arguments provided to the debounced function. Subsequent
10293 * calls to the debounced function return the result of the last `func`
10296 * **Note:** If `leading` and `trailing` options are `true`, `func` is
10297 * invoked on the trailing edge of the timeout only if the debounced function
10298 * is invoked more than once during the `wait` timeout.
10300 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10301 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10303 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10304 * for details over the differences between `_.debounce` and `_.throttle`.
10309 * @category Function
10310 * @param {Function} func The function to debounce.
10311 * @param {number} [wait=0] The number of milliseconds to delay.
10312 * @param {Object} [options={}] The options object.
10313 * @param {boolean} [options.leading=false]
10314 * Specify invoking on the leading edge of the timeout.
10315 * @param {number} [options.maxWait]
10316 * The maximum time `func` is allowed to be delayed before it's invoked.
10317 * @param {boolean} [options.trailing=true]
10318 * Specify invoking on the trailing edge of the timeout.
10319 * @returns {Function} Returns the new debounced function.
10322 * // Avoid costly calculations while the window size is in flux.
10323 * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
10325 * // Invoke `sendMail` when clicked, debouncing subsequent calls.
10326 * jQuery(element).on('click', _.debounce(sendMail, 300, {
10328 * 'trailing': false
10331 * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
10332 * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
10333 * var source = new EventSource('/stream');
10334 * jQuery(source).on('message', debounced);
10336 * // Cancel the trailing debounced invocation.
10337 * jQuery(window).on('popstate', debounced.cancel);
10339 function debounce(func, wait, options) {
10346 lastInvokeTime = 0,
10351 if (typeof func != 'function') {
10352 throw new TypeError(FUNC_ERROR_TEXT);
10354 wait = toNumber(wait) || 0;
10355 if (isObject(options)) {
10356 leading = !!options.leading;
10357 maxing = 'maxWait' in options;
10358 maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
10359 trailing = 'trailing' in options ? !!options.trailing : trailing;
10362 function invokeFunc(time) {
10363 var args = lastArgs,
10364 thisArg = lastThis;
10366 lastArgs = lastThis = undefined;
10367 lastInvokeTime = time;
10368 result = func.apply(thisArg, args);
10372 function leadingEdge(time) {
10373 // Reset any `maxWait` timer.
10374 lastInvokeTime = time;
10375 // Start the timer for the trailing edge.
10376 timerId = setTimeout(timerExpired, wait);
10377 // Invoke the leading edge.
10378 return leading ? invokeFunc(time) : result;
10381 function remainingWait(time) {
10382 var timeSinceLastCall = time - lastCallTime,
10383 timeSinceLastInvoke = time - lastInvokeTime,
10384 result = wait - timeSinceLastCall;
10386 return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
10389 function shouldInvoke(time) {
10390 var timeSinceLastCall = time - lastCallTime,
10391 timeSinceLastInvoke = time - lastInvokeTime;
10393 // Either this is the first call, activity has stopped and we're at the
10394 // trailing edge, the system time has gone backwards and we're treating
10395 // it as the trailing edge, or we've hit the `maxWait` limit.
10396 return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
10397 (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
10400 function timerExpired() {
10402 if (shouldInvoke(time)) {
10403 return trailingEdge(time);
10405 // Restart the timer.
10406 timerId = setTimeout(timerExpired, remainingWait(time));
10409 function trailingEdge(time) {
10410 timerId = undefined;
10412 // Only invoke if we have `lastArgs` which means `func` has been
10413 // debounced at least once.
10414 if (trailing && lastArgs) {
10415 return invokeFunc(time);
10417 lastArgs = lastThis = undefined;
10421 function cancel() {
10422 if (timerId !== undefined) {
10423 clearTimeout(timerId);
10425 lastInvokeTime = 0;
10426 lastArgs = lastCallTime = lastThis = timerId = undefined;
10430 return timerId === undefined ? result : trailingEdge(now());
10433 function debounced() {
10435 isInvoking = shouldInvoke(time);
10437 lastArgs = arguments;
10439 lastCallTime = time;
10442 if (timerId === undefined) {
10443 return leadingEdge(lastCallTime);
10446 // Handle invocations in a tight loop.
10447 timerId = setTimeout(timerExpired, wait);
10448 return invokeFunc(lastCallTime);
10451 if (timerId === undefined) {
10452 timerId = setTimeout(timerExpired, wait);
10456 debounced.cancel = cancel;
10457 debounced.flush = flush;
10462 * Defers invoking the `func` until the current call stack has cleared. Any
10463 * additional arguments are provided to `func` when it's invoked.
10468 * @category Function
10469 * @param {Function} func The function to defer.
10470 * @param {...*} [args] The arguments to invoke `func` with.
10471 * @returns {number} Returns the timer id.
10474 * _.defer(function(text) {
10475 * console.log(text);
10477 * // => Logs 'deferred' after one millisecond.
10479 var defer = baseRest(function(func, args) {
10480 return baseDelay(func, 1, args);
10484 * Invokes `func` after `wait` milliseconds. Any additional arguments are
10485 * provided to `func` when it's invoked.
10490 * @category Function
10491 * @param {Function} func The function to delay.
10492 * @param {number} wait The number of milliseconds to delay invocation.
10493 * @param {...*} [args] The arguments to invoke `func` with.
10494 * @returns {number} Returns the timer id.
10497 * _.delay(function(text) {
10498 * console.log(text);
10499 * }, 1000, 'later');
10500 * // => Logs 'later' after one second.
10502 var delay = baseRest(function(func, wait, args) {
10503 return baseDelay(func, toNumber(wait) || 0, args);
10507 * Creates a function that invokes `func` with arguments reversed.
10512 * @category Function
10513 * @param {Function} func The function to flip arguments for.
10514 * @returns {Function} Returns the new flipped function.
10517 * var flipped = _.flip(function() {
10518 * return _.toArray(arguments);
10521 * flipped('a', 'b', 'c', 'd');
10522 * // => ['d', 'c', 'b', 'a']
10524 function flip(func) {
10525 return createWrap(func, WRAP_FLIP_FLAG);
10529 * Creates a function that memoizes the result of `func`. If `resolver` is
10530 * provided, it determines the cache key for storing the result based on the
10531 * arguments provided to the memoized function. By default, the first argument
10532 * provided to the memoized function is used as the map cache key. The `func`
10533 * is invoked with the `this` binding of the memoized function.
10535 * **Note:** The cache is exposed as the `cache` property on the memoized
10536 * function. Its creation may be customized by replacing the `_.memoize.Cache`
10537 * constructor with one whose instances implement the
10538 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
10539 * method interface of `clear`, `delete`, `get`, `has`, and `set`.
10544 * @category Function
10545 * @param {Function} func The function to have its output memoized.
10546 * @param {Function} [resolver] The function to resolve the cache key.
10547 * @returns {Function} Returns the new memoized function.
10550 * var object = { 'a': 1, 'b': 2 };
10551 * var other = { 'c': 3, 'd': 4 };
10553 * var values = _.memoize(_.values);
10564 * // Modify the result cache.
10565 * values.cache.set(object, ['a', 'b']);
10569 * // Replace `_.memoize.Cache`.
10570 * _.memoize.Cache = WeakMap;
10572 function memoize(func, resolver) {
10573 if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
10574 throw new TypeError(FUNC_ERROR_TEXT);
10576 var memoized = function() {
10577 var args = arguments,
10578 key = resolver ? resolver.apply(this, args) : args[0],
10579 cache = memoized.cache;
10581 if (cache.has(key)) {
10582 return cache.get(key);
10584 var result = func.apply(this, args);
10585 memoized.cache = cache.set(key, result) || cache;
10588 memoized.cache = new (memoize.Cache || MapCache);
10592 // Expose `MapCache`.
10593 memoize.Cache = MapCache;
10596 * Creates a function that negates the result of the predicate `func`. The
10597 * `func` predicate is invoked with the `this` binding and arguments of the
10598 * created function.
10603 * @category Function
10604 * @param {Function} predicate The predicate to negate.
10605 * @returns {Function} Returns the new negated function.
10608 * function isEven(n) {
10609 * return n % 2 == 0;
10612 * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
10615 function negate(predicate) {
10616 if (typeof predicate != 'function') {
10617 throw new TypeError(FUNC_ERROR_TEXT);
10619 return function() {
10620 var args = arguments;
10621 switch (args.length) {
10622 case 0: return !predicate.call(this);
10623 case 1: return !predicate.call(this, args[0]);
10624 case 2: return !predicate.call(this, args[0], args[1]);
10625 case 3: return !predicate.call(this, args[0], args[1], args[2]);
10627 return !predicate.apply(this, args);
10632 * Creates a function that is restricted to invoking `func` once. Repeat calls
10633 * to the function return the value of the first invocation. The `func` is
10634 * invoked with the `this` binding and arguments of the created function.
10639 * @category Function
10640 * @param {Function} func The function to restrict.
10641 * @returns {Function} Returns the new restricted function.
10644 * var initialize = _.once(createApplication);
10647 * // => `createApplication` is invoked once
10649 function once(func) {
10650 return before(2, func);
10654 * Creates a function that invokes `func` with its arguments transformed.
10659 * @category Function
10660 * @param {Function} func The function to wrap.
10661 * @param {...(Function|Function[])} [transforms=[_.identity]]
10662 * The argument transforms.
10663 * @returns {Function} Returns the new function.
10666 * function doubled(n) {
10670 * function square(n) {
10674 * var func = _.overArgs(function(x, y) {
10676 * }, [square, doubled]);
10684 var overArgs = castRest(function(func, transforms) {
10685 transforms = (transforms.length == 1 && isArray(transforms[0]))
10686 ? arrayMap(transforms[0], baseUnary(getIteratee()))
10687 : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
10689 var funcsLength = transforms.length;
10690 return baseRest(function(args) {
10692 length = nativeMin(args.length, funcsLength);
10694 while (++index < length) {
10695 args[index] = transforms[index].call(this, args[index]);
10697 return apply(func, this, args);
10702 * Creates a function that invokes `func` with `partials` prepended to the
10703 * arguments it receives. This method is like `_.bind` except it does **not**
10704 * alter the `this` binding.
10706 * The `_.partial.placeholder` value, which defaults to `_` in monolithic
10707 * builds, may be used as a placeholder for partially applied arguments.
10709 * **Note:** This method doesn't set the "length" property of partially
10710 * applied functions.
10715 * @category Function
10716 * @param {Function} func The function to partially apply arguments to.
10717 * @param {...*} [partials] The arguments to be partially applied.
10718 * @returns {Function} Returns the new partially applied function.
10721 * function greet(greeting, name) {
10722 * return greeting + ' ' + name;
10725 * var sayHelloTo = _.partial(greet, 'hello');
10726 * sayHelloTo('fred');
10727 * // => 'hello fred'
10729 * // Partially applied with placeholders.
10730 * var greetFred = _.partial(greet, _, 'fred');
10734 var partial = baseRest(function(func, partials) {
10735 var holders = replaceHolders(partials, getHolder(partial));
10736 return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
10740 * This method is like `_.partial` except that partially applied arguments
10741 * are appended to the arguments it receives.
10743 * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
10744 * builds, may be used as a placeholder for partially applied arguments.
10746 * **Note:** This method doesn't set the "length" property of partially
10747 * applied functions.
10752 * @category Function
10753 * @param {Function} func The function to partially apply arguments to.
10754 * @param {...*} [partials] The arguments to be partially applied.
10755 * @returns {Function} Returns the new partially applied function.
10758 * function greet(greeting, name) {
10759 * return greeting + ' ' + name;
10762 * var greetFred = _.partialRight(greet, 'fred');
10766 * // Partially applied with placeholders.
10767 * var sayHelloTo = _.partialRight(greet, 'hello', _);
10768 * sayHelloTo('fred');
10769 * // => 'hello fred'
10771 var partialRight = baseRest(function(func, partials) {
10772 var holders = replaceHolders(partials, getHolder(partialRight));
10773 return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
10777 * Creates a function that invokes `func` with arguments arranged according
10778 * to the specified `indexes` where the argument value at the first index is
10779 * provided as the first argument, the argument value at the second index is
10780 * provided as the second argument, and so on.
10785 * @category Function
10786 * @param {Function} func The function to rearrange arguments for.
10787 * @param {...(number|number[])} indexes The arranged argument indexes.
10788 * @returns {Function} Returns the new function.
10791 * var rearged = _.rearg(function(a, b, c) {
10792 * return [a, b, c];
10795 * rearged('b', 'c', 'a')
10796 * // => ['a', 'b', 'c']
10798 var rearg = flatRest(function(func, indexes) {
10799 return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
10803 * Creates a function that invokes `func` with the `this` binding of the
10804 * created function and arguments from `start` and beyond provided as
10807 * **Note:** This method is based on the
10808 * [rest parameter](https://mdn.io/rest_parameters).
10813 * @category Function
10814 * @param {Function} func The function to apply a rest parameter to.
10815 * @param {number} [start=func.length-1] The start position of the rest parameter.
10816 * @returns {Function} Returns the new function.
10819 * var say = _.rest(function(what, names) {
10820 * return what + ' ' + _.initial(names).join(', ') +
10821 * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
10824 * say('hello', 'fred', 'barney', 'pebbles');
10825 * // => 'hello fred, barney, & pebbles'
10827 function rest(func, start) {
10828 if (typeof func != 'function') {
10829 throw new TypeError(FUNC_ERROR_TEXT);
10831 start = start === undefined ? start : toInteger(start);
10832 return baseRest(func, start);
10836 * Creates a function that invokes `func` with the `this` binding of the
10837 * create function and an array of arguments much like
10838 * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
10840 * **Note:** This method is based on the
10841 * [spread operator](https://mdn.io/spread_operator).
10846 * @category Function
10847 * @param {Function} func The function to spread arguments over.
10848 * @param {number} [start=0] The start position of the spread.
10849 * @returns {Function} Returns the new function.
10852 * var say = _.spread(function(who, what) {
10853 * return who + ' says ' + what;
10856 * say(['fred', 'hello']);
10857 * // => 'fred says hello'
10859 * var numbers = Promise.all([
10860 * Promise.resolve(40),
10861 * Promise.resolve(36)
10864 * numbers.then(_.spread(function(x, y) {
10867 * // => a Promise of 76
10869 function spread(func, start) {
10870 if (typeof func != 'function') {
10871 throw new TypeError(FUNC_ERROR_TEXT);
10873 start = start == null ? 0 : nativeMax(toInteger(start), 0);
10874 return baseRest(function(args) {
10875 var array = args[start],
10876 otherArgs = castSlice(args, 0, start);
10879 arrayPush(otherArgs, array);
10881 return apply(func, this, otherArgs);
10886 * Creates a throttled function that only invokes `func` at most once per
10887 * every `wait` milliseconds. The throttled function comes with a `cancel`
10888 * method to cancel delayed `func` invocations and a `flush` method to
10889 * immediately invoke them. Provide `options` to indicate whether `func`
10890 * should be invoked on the leading and/or trailing edge of the `wait`
10891 * timeout. The `func` is invoked with the last arguments provided to the
10892 * throttled function. Subsequent calls to the throttled function return the
10893 * result of the last `func` invocation.
10895 * **Note:** If `leading` and `trailing` options are `true`, `func` is
10896 * invoked on the trailing edge of the timeout only if the throttled function
10897 * is invoked more than once during the `wait` timeout.
10899 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10900 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10902 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10903 * for details over the differences between `_.throttle` and `_.debounce`.
10908 * @category Function
10909 * @param {Function} func The function to throttle.
10910 * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
10911 * @param {Object} [options={}] The options object.
10912 * @param {boolean} [options.leading=true]
10913 * Specify invoking on the leading edge of the timeout.
10914 * @param {boolean} [options.trailing=true]
10915 * Specify invoking on the trailing edge of the timeout.
10916 * @returns {Function} Returns the new throttled function.
10919 * // Avoid excessively updating the position while scrolling.
10920 * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
10922 * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
10923 * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
10924 * jQuery(element).on('click', throttled);
10926 * // Cancel the trailing throttled invocation.
10927 * jQuery(window).on('popstate', throttled.cancel);
10929 function throttle(func, wait, options) {
10930 var leading = true,
10933 if (typeof func != 'function') {
10934 throw new TypeError(FUNC_ERROR_TEXT);
10936 if (isObject(options)) {
10937 leading = 'leading' in options ? !!options.leading : leading;
10938 trailing = 'trailing' in options ? !!options.trailing : trailing;
10940 return debounce(func, wait, {
10941 'leading': leading,
10943 'trailing': trailing
10948 * Creates a function that accepts up to one argument, ignoring any
10949 * additional arguments.
10954 * @category Function
10955 * @param {Function} func The function to cap arguments for.
10956 * @returns {Function} Returns the new capped function.
10959 * _.map(['6', '8', '10'], _.unary(parseInt));
10962 function unary(func) {
10963 return ary(func, 1);
10967 * Creates a function that provides `value` to `wrapper` as its first
10968 * argument. Any additional arguments provided to the function are appended
10969 * to those provided to the `wrapper`. The wrapper is invoked with the `this`
10970 * binding of the created function.
10975 * @category Function
10976 * @param {*} value The value to wrap.
10977 * @param {Function} [wrapper=identity] The wrapper function.
10978 * @returns {Function} Returns the new function.
10981 * var p = _.wrap(_.escape, function(func, text) {
10982 * return '<p>' + func(text) + '</p>';
10985 * p('fred, barney, & pebbles');
10986 * // => '<p>fred, barney, & pebbles</p>'
10988 function wrap(value, wrapper) {
10989 return partial(castFunction(wrapper), value);
10992 /*------------------------------------------------------------------------*/
10995 * Casts `value` as an array if it's not one.
11001 * @param {*} value The value to inspect.
11002 * @returns {Array} Returns the cast array.
11008 * _.castArray({ 'a': 1 });
11009 * // => [{ 'a': 1 }]
11011 * _.castArray('abc');
11014 * _.castArray(null);
11017 * _.castArray(undefined);
11018 * // => [undefined]
11023 * var array = [1, 2, 3];
11024 * console.log(_.castArray(array) === array);
11027 function castArray() {
11028 if (!arguments.length) {
11031 var value = arguments[0];
11032 return isArray(value) ? value : [value];
11036 * Creates a shallow clone of `value`.
11038 * **Note:** This method is loosely based on the
11039 * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
11040 * and supports cloning arrays, array buffers, booleans, date objects, maps,
11041 * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
11042 * arrays. The own enumerable properties of `arguments` objects are cloned
11043 * as plain objects. An empty object is returned for uncloneable values such
11044 * as error objects, functions, DOM nodes, and WeakMaps.
11050 * @param {*} value The value to clone.
11051 * @returns {*} Returns the cloned value.
11055 * var objects = [{ 'a': 1 }, { 'b': 2 }];
11057 * var shallow = _.clone(objects);
11058 * console.log(shallow[0] === objects[0]);
11061 function clone(value) {
11062 return baseClone(value, CLONE_SYMBOLS_FLAG);
11066 * This method is like `_.clone` except that it accepts `customizer` which
11067 * is invoked to produce the cloned value. If `customizer` returns `undefined`,
11068 * cloning is handled by the method instead. The `customizer` is invoked with
11069 * up to four arguments; (value [, index|key, object, stack]).
11075 * @param {*} value The value to clone.
11076 * @param {Function} [customizer] The function to customize cloning.
11077 * @returns {*} Returns the cloned value.
11078 * @see _.cloneDeepWith
11081 * function customizer(value) {
11082 * if (_.isElement(value)) {
11083 * return value.cloneNode(false);
11087 * var el = _.cloneWith(document.body, customizer);
11089 * console.log(el === document.body);
11091 * console.log(el.nodeName);
11093 * console.log(el.childNodes.length);
11096 function cloneWith(value, customizer) {
11097 customizer = typeof customizer == 'function' ? customizer : undefined;
11098 return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
11102 * This method is like `_.clone` except that it recursively clones `value`.
11108 * @param {*} value The value to recursively clone.
11109 * @returns {*} Returns the deep cloned value.
11113 * var objects = [{ 'a': 1 }, { 'b': 2 }];
11115 * var deep = _.cloneDeep(objects);
11116 * console.log(deep[0] === objects[0]);
11119 function cloneDeep(value) {
11120 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
11124 * This method is like `_.cloneWith` except that it recursively clones `value`.
11130 * @param {*} value The value to recursively clone.
11131 * @param {Function} [customizer] The function to customize cloning.
11132 * @returns {*} Returns the deep cloned value.
11136 * function customizer(value) {
11137 * if (_.isElement(value)) {
11138 * return value.cloneNode(true);
11142 * var el = _.cloneDeepWith(document.body, customizer);
11144 * console.log(el === document.body);
11146 * console.log(el.nodeName);
11148 * console.log(el.childNodes.length);
11151 function cloneDeepWith(value, customizer) {
11152 customizer = typeof customizer == 'function' ? customizer : undefined;
11153 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
11157 * Checks if `object` conforms to `source` by invoking the predicate
11158 * properties of `source` with the corresponding property values of `object`.
11160 * **Note:** This method is equivalent to `_.conforms` when `source` is
11161 * partially applied.
11167 * @param {Object} object The object to inspect.
11168 * @param {Object} source The object of property predicates to conform to.
11169 * @returns {boolean} Returns `true` if `object` conforms, else `false`.
11172 * var object = { 'a': 1, 'b': 2 };
11174 * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
11177 * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
11180 function conformsTo(object, source) {
11181 return source == null || baseConformsTo(object, source, keys(source));
11186 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
11187 * comparison between two values to determine if they are equivalent.
11193 * @param {*} value The value to compare.
11194 * @param {*} other The other value to compare.
11195 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11198 * var object = { 'a': 1 };
11199 * var other = { 'a': 1 };
11201 * _.eq(object, object);
11204 * _.eq(object, other);
11210 * _.eq('a', Object('a'));
11216 function eq(value, other) {
11217 return value === other || (value !== value && other !== other);
11221 * Checks if `value` is greater than `other`.
11227 * @param {*} value The value to compare.
11228 * @param {*} other The other value to compare.
11229 * @returns {boolean} Returns `true` if `value` is greater than `other`,
11243 var gt = createRelationalOperation(baseGt);
11246 * Checks if `value` is greater than or equal to `other`.
11252 * @param {*} value The value to compare.
11253 * @param {*} other The other value to compare.
11254 * @returns {boolean} Returns `true` if `value` is greater than or equal to
11255 * `other`, else `false`.
11268 var gte = createRelationalOperation(function(value, other) {
11269 return value >= other;
11273 * Checks if `value` is likely an `arguments` object.
11279 * @param {*} value The value to check.
11280 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
11284 * _.isArguments(function() { return arguments; }());
11287 * _.isArguments([1, 2, 3]);
11290 var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
11291 return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
11292 !propertyIsEnumerable.call(value, 'callee');
11296 * Checks if `value` is classified as an `Array` object.
11302 * @param {*} value The value to check.
11303 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
11306 * _.isArray([1, 2, 3]);
11309 * _.isArray(document.body.children);
11312 * _.isArray('abc');
11315 * _.isArray(_.noop);
11318 var isArray = Array.isArray;
11321 * Checks if `value` is classified as an `ArrayBuffer` object.
11327 * @param {*} value The value to check.
11328 * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
11331 * _.isArrayBuffer(new ArrayBuffer(2));
11334 * _.isArrayBuffer(new Array(2));
11337 var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
11340 * Checks if `value` is array-like. A value is considered array-like if it's
11341 * not a function and has a `value.length` that's an integer greater than or
11342 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
11348 * @param {*} value The value to check.
11349 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
11352 * _.isArrayLike([1, 2, 3]);
11355 * _.isArrayLike(document.body.children);
11358 * _.isArrayLike('abc');
11361 * _.isArrayLike(_.noop);
11364 function isArrayLike(value) {
11365 return value != null && isLength(value.length) && !isFunction(value);
11369 * This method is like `_.isArrayLike` except that it also checks if `value`
11376 * @param {*} value The value to check.
11377 * @returns {boolean} Returns `true` if `value` is an array-like object,
11381 * _.isArrayLikeObject([1, 2, 3]);
11384 * _.isArrayLikeObject(document.body.children);
11387 * _.isArrayLikeObject('abc');
11390 * _.isArrayLikeObject(_.noop);
11393 function isArrayLikeObject(value) {
11394 return isObjectLike(value) && isArrayLike(value);
11398 * Checks if `value` is classified as a boolean primitive or object.
11404 * @param {*} value The value to check.
11405 * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
11408 * _.isBoolean(false);
11411 * _.isBoolean(null);
11414 function isBoolean(value) {
11415 return value === true || value === false ||
11416 (isObjectLike(value) && baseGetTag(value) == boolTag);
11420 * Checks if `value` is a buffer.
11426 * @param {*} value The value to check.
11427 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
11430 * _.isBuffer(new Buffer(2));
11433 * _.isBuffer(new Uint8Array(2));
11436 var isBuffer = nativeIsBuffer || stubFalse;
11439 * Checks if `value` is classified as a `Date` object.
11445 * @param {*} value The value to check.
11446 * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
11449 * _.isDate(new Date);
11452 * _.isDate('Mon April 23 2012');
11455 var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
11458 * Checks if `value` is likely a DOM element.
11464 * @param {*} value The value to check.
11465 * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
11468 * _.isElement(document.body);
11471 * _.isElement('<body>');
11474 function isElement(value) {
11475 return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
11479 * Checks if `value` is an empty object, collection, map, or set.
11481 * Objects are considered empty if they have no own enumerable string keyed
11484 * Array-like values such as `arguments` objects, arrays, buffers, strings, or
11485 * jQuery-like collections are considered empty if they have a `length` of `0`.
11486 * Similarly, maps and sets are considered empty if they have a `size` of `0`.
11492 * @param {*} value The value to check.
11493 * @returns {boolean} Returns `true` if `value` is empty, else `false`.
11505 * _.isEmpty([1, 2, 3]);
11508 * _.isEmpty({ 'a': 1 });
11511 function isEmpty(value) {
11512 if (value == null) {
11515 if (isArrayLike(value) &&
11516 (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
11517 isBuffer(value) || isTypedArray(value) || isArguments(value))) {
11518 return !value.length;
11520 var tag = getTag(value);
11521 if (tag == mapTag || tag == setTag) {
11522 return !value.size;
11524 if (isPrototype(value)) {
11525 return !baseKeys(value).length;
11527 for (var key in value) {
11528 if (hasOwnProperty.call(value, key)) {
11536 * Performs a deep comparison between two values to determine if they are
11539 * **Note:** This method supports comparing arrays, array buffers, booleans,
11540 * date objects, error objects, maps, numbers, `Object` objects, regexes,
11541 * sets, strings, symbols, and typed arrays. `Object` objects are compared
11542 * by their own, not inherited, enumerable properties. Functions and DOM
11543 * nodes are compared by strict equality, i.e. `===`.
11549 * @param {*} value The value to compare.
11550 * @param {*} other The other value to compare.
11551 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11554 * var object = { 'a': 1 };
11555 * var other = { 'a': 1 };
11557 * _.isEqual(object, other);
11560 * object === other;
11563 function isEqual(value, other) {
11564 return baseIsEqual(value, other);
11568 * This method is like `_.isEqual` except that it accepts `customizer` which
11569 * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11570 * are handled by the method instead. The `customizer` is invoked with up to
11571 * six arguments: (objValue, othValue [, index|key, object, other, stack]).
11577 * @param {*} value The value to compare.
11578 * @param {*} other The other value to compare.
11579 * @param {Function} [customizer] The function to customize comparisons.
11580 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11583 * function isGreeting(value) {
11584 * return /^h(?:i|ello)$/.test(value);
11587 * function customizer(objValue, othValue) {
11588 * if (isGreeting(objValue) && isGreeting(othValue)) {
11593 * var array = ['hello', 'goodbye'];
11594 * var other = ['hi', 'goodbye'];
11596 * _.isEqualWith(array, other, customizer);
11599 function isEqualWith(value, other, customizer) {
11600 customizer = typeof customizer == 'function' ? customizer : undefined;
11601 var result = customizer ? customizer(value, other) : undefined;
11602 return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
11606 * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
11607 * `SyntaxError`, `TypeError`, or `URIError` object.
11613 * @param {*} value The value to check.
11614 * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
11617 * _.isError(new Error);
11620 * _.isError(Error);
11623 function isError(value) {
11624 if (!isObjectLike(value)) {
11627 var tag = baseGetTag(value);
11628 return tag == errorTag || tag == domExcTag ||
11629 (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
11633 * Checks if `value` is a finite primitive number.
11635 * **Note:** This method is based on
11636 * [`Number.isFinite`](https://mdn.io/Number/isFinite).
11642 * @param {*} value The value to check.
11643 * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
11649 * _.isFinite(Number.MIN_VALUE);
11652 * _.isFinite(Infinity);
11658 function isFinite(value) {
11659 return typeof value == 'number' && nativeIsFinite(value);
11663 * Checks if `value` is classified as a `Function` object.
11669 * @param {*} value The value to check.
11670 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
11676 * _.isFunction(/abc/);
11679 function isFunction(value) {
11680 if (!isObject(value)) {
11683 // The use of `Object#toString` avoids issues with the `typeof` operator
11684 // in Safari 9 which returns 'object' for typed arrays and other constructors.
11685 var tag = baseGetTag(value);
11686 return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
11690 * Checks if `value` is an integer.
11692 * **Note:** This method is based on
11693 * [`Number.isInteger`](https://mdn.io/Number/isInteger).
11699 * @param {*} value The value to check.
11700 * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
11706 * _.isInteger(Number.MIN_VALUE);
11709 * _.isInteger(Infinity);
11712 * _.isInteger('3');
11715 function isInteger(value) {
11716 return typeof value == 'number' && value == toInteger(value);
11720 * Checks if `value` is a valid array-like length.
11722 * **Note:** This method is loosely based on
11723 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
11729 * @param {*} value The value to check.
11730 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
11736 * _.isLength(Number.MIN_VALUE);
11739 * _.isLength(Infinity);
11745 function isLength(value) {
11746 return typeof value == 'number' &&
11747 value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
11751 * Checks if `value` is the
11752 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
11753 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
11759 * @param {*} value The value to check.
11760 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
11766 * _.isObject([1, 2, 3]);
11769 * _.isObject(_.noop);
11772 * _.isObject(null);
11775 function isObject(value) {
11776 var type = typeof value;
11777 return value != null && (type == 'object' || type == 'function');
11781 * Checks if `value` is object-like. A value is object-like if it's not `null`
11782 * and has a `typeof` result of "object".
11788 * @param {*} value The value to check.
11789 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
11792 * _.isObjectLike({});
11795 * _.isObjectLike([1, 2, 3]);
11798 * _.isObjectLike(_.noop);
11801 * _.isObjectLike(null);
11804 function isObjectLike(value) {
11805 return value != null && typeof value == 'object';
11809 * Checks if `value` is classified as a `Map` object.
11815 * @param {*} value The value to check.
11816 * @returns {boolean} Returns `true` if `value` is a map, else `false`.
11819 * _.isMap(new Map);
11822 * _.isMap(new WeakMap);
11825 var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
11828 * Performs a partial deep comparison between `object` and `source` to
11829 * determine if `object` contains equivalent property values.
11831 * **Note:** This method is equivalent to `_.matches` when `source` is
11832 * partially applied.
11834 * Partial comparisons will match empty array and empty object `source`
11835 * values against any array or object value, respectively. See `_.isEqual`
11836 * for a list of supported value comparisons.
11842 * @param {Object} object The object to inspect.
11843 * @param {Object} source The object of property values to match.
11844 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11847 * var object = { 'a': 1, 'b': 2 };
11849 * _.isMatch(object, { 'b': 2 });
11852 * _.isMatch(object, { 'b': 1 });
11855 function isMatch(object, source) {
11856 return object === source || baseIsMatch(object, source, getMatchData(source));
11860 * This method is like `_.isMatch` except that it accepts `customizer` which
11861 * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11862 * are handled by the method instead. The `customizer` is invoked with five
11863 * arguments: (objValue, srcValue, index|key, object, source).
11869 * @param {Object} object The object to inspect.
11870 * @param {Object} source The object of property values to match.
11871 * @param {Function} [customizer] The function to customize comparisons.
11872 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11875 * function isGreeting(value) {
11876 * return /^h(?:i|ello)$/.test(value);
11879 * function customizer(objValue, srcValue) {
11880 * if (isGreeting(objValue) && isGreeting(srcValue)) {
11885 * var object = { 'greeting': 'hello' };
11886 * var source = { 'greeting': 'hi' };
11888 * _.isMatchWith(object, source, customizer);
11891 function isMatchWith(object, source, customizer) {
11892 customizer = typeof customizer == 'function' ? customizer : undefined;
11893 return baseIsMatch(object, source, getMatchData(source), customizer);
11897 * Checks if `value` is `NaN`.
11899 * **Note:** This method is based on
11900 * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
11901 * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
11902 * `undefined` and other non-number values.
11908 * @param {*} value The value to check.
11909 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
11915 * _.isNaN(new Number(NaN));
11918 * isNaN(undefined);
11921 * _.isNaN(undefined);
11924 function isNaN(value) {
11925 // An `NaN` primitive is the only value that is not equal to itself.
11926 // Perform the `toStringTag` check first to avoid errors with some
11927 // ActiveX objects in IE.
11928 return isNumber(value) && value != +value;
11932 * Checks if `value` is a pristine native function.
11934 * **Note:** This method can't reliably detect native functions in the presence
11935 * of the core-js package because core-js circumvents this kind of detection.
11936 * Despite multiple requests, the core-js maintainer has made it clear: any
11937 * attempt to fix the detection will be obstructed. As a result, we're left
11938 * with little choice but to throw an error. Unfortunately, this also affects
11939 * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
11940 * which rely on core-js.
11946 * @param {*} value The value to check.
11947 * @returns {boolean} Returns `true` if `value` is a native function,
11951 * _.isNative(Array.prototype.push);
11957 function isNative(value) {
11958 if (isMaskable(value)) {
11959 throw new Error(CORE_ERROR_TEXT);
11961 return baseIsNative(value);
11965 * Checks if `value` is `null`.
11971 * @param {*} value The value to check.
11972 * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
11978 * _.isNull(void 0);
11981 function isNull(value) {
11982 return value === null;
11986 * Checks if `value` is `null` or `undefined`.
11992 * @param {*} value The value to check.
11993 * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
12005 function isNil(value) {
12006 return value == null;
12010 * Checks if `value` is classified as a `Number` primitive or object.
12012 * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
12013 * classified as numbers, use the `_.isFinite` method.
12019 * @param {*} value The value to check.
12020 * @returns {boolean} Returns `true` if `value` is a number, else `false`.
12026 * _.isNumber(Number.MIN_VALUE);
12029 * _.isNumber(Infinity);
12035 function isNumber(value) {
12036 return typeof value == 'number' ||
12037 (isObjectLike(value) && baseGetTag(value) == numberTag);
12041 * Checks if `value` is a plain object, that is, an object created by the
12042 * `Object` constructor or one with a `[[Prototype]]` of `null`.
12048 * @param {*} value The value to check.
12049 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
12056 * _.isPlainObject(new Foo);
12059 * _.isPlainObject([1, 2, 3]);
12062 * _.isPlainObject({ 'x': 0, 'y': 0 });
12065 * _.isPlainObject(Object.create(null));
12068 function isPlainObject(value) {
12069 if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
12072 var proto = getPrototype(value);
12073 if (proto === null) {
12076 var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
12077 return typeof Ctor == 'function' && Ctor instanceof Ctor &&
12078 funcToString.call(Ctor) == objectCtorString;
12082 * Checks if `value` is classified as a `RegExp` object.
12088 * @param {*} value The value to check.
12089 * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
12092 * _.isRegExp(/abc/);
12095 * _.isRegExp('/abc/');
12098 var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
12101 * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
12102 * double precision number which isn't the result of a rounded unsafe integer.
12104 * **Note:** This method is based on
12105 * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
12111 * @param {*} value The value to check.
12112 * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
12115 * _.isSafeInteger(3);
12118 * _.isSafeInteger(Number.MIN_VALUE);
12121 * _.isSafeInteger(Infinity);
12124 * _.isSafeInteger('3');
12127 function isSafeInteger(value) {
12128 return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
12132 * Checks if `value` is classified as a `Set` object.
12138 * @param {*} value The value to check.
12139 * @returns {boolean} Returns `true` if `value` is a set, else `false`.
12142 * _.isSet(new Set);
12145 * _.isSet(new WeakSet);
12148 var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
12151 * Checks if `value` is classified as a `String` primitive or object.
12157 * @param {*} value The value to check.
12158 * @returns {boolean} Returns `true` if `value` is a string, else `false`.
12161 * _.isString('abc');
12167 function isString(value) {
12168 return typeof value == 'string' ||
12169 (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
12173 * Checks if `value` is classified as a `Symbol` primitive or object.
12179 * @param {*} value The value to check.
12180 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
12183 * _.isSymbol(Symbol.iterator);
12186 * _.isSymbol('abc');
12189 function isSymbol(value) {
12190 return typeof value == 'symbol' ||
12191 (isObjectLike(value) && baseGetTag(value) == symbolTag);
12195 * Checks if `value` is classified as a typed array.
12201 * @param {*} value The value to check.
12202 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
12205 * _.isTypedArray(new Uint8Array);
12208 * _.isTypedArray([]);
12211 var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
12214 * Checks if `value` is `undefined`.
12220 * @param {*} value The value to check.
12221 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
12224 * _.isUndefined(void 0);
12227 * _.isUndefined(null);
12230 function isUndefined(value) {
12231 return value === undefined;
12235 * Checks if `value` is classified as a `WeakMap` object.
12241 * @param {*} value The value to check.
12242 * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
12245 * _.isWeakMap(new WeakMap);
12248 * _.isWeakMap(new Map);
12251 function isWeakMap(value) {
12252 return isObjectLike(value) && getTag(value) == weakMapTag;
12256 * Checks if `value` is classified as a `WeakSet` object.
12262 * @param {*} value The value to check.
12263 * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
12266 * _.isWeakSet(new WeakSet);
12269 * _.isWeakSet(new Set);
12272 function isWeakSet(value) {
12273 return isObjectLike(value) && baseGetTag(value) == weakSetTag;
12277 * Checks if `value` is less than `other`.
12283 * @param {*} value The value to compare.
12284 * @param {*} other The other value to compare.
12285 * @returns {boolean} Returns `true` if `value` is less than `other`,
12299 var lt = createRelationalOperation(baseLt);
12302 * Checks if `value` is less than or equal to `other`.
12308 * @param {*} value The value to compare.
12309 * @param {*} other The other value to compare.
12310 * @returns {boolean} Returns `true` if `value` is less than or equal to
12311 * `other`, else `false`.
12324 var lte = createRelationalOperation(function(value, other) {
12325 return value <= other;
12329 * Converts `value` to an array.
12335 * @param {*} value The value to convert.
12336 * @returns {Array} Returns the converted array.
12339 * _.toArray({ 'a': 1, 'b': 2 });
12342 * _.toArray('abc');
12343 * // => ['a', 'b', 'c']
12351 function toArray(value) {
12355 if (isArrayLike(value)) {
12356 return isString(value) ? stringToArray(value) : copyArray(value);
12358 if (symIterator && value[symIterator]) {
12359 return iteratorToArray(value[symIterator]());
12361 var tag = getTag(value),
12362 func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
12364 return func(value);
12368 * Converts `value` to a finite number.
12374 * @param {*} value The value to convert.
12375 * @returns {number} Returns the converted number.
12381 * _.toFinite(Number.MIN_VALUE);
12384 * _.toFinite(Infinity);
12385 * // => 1.7976931348623157e+308
12387 * _.toFinite('3.2');
12390 function toFinite(value) {
12392 return value === 0 ? value : 0;
12394 value = toNumber(value);
12395 if (value === INFINITY || value === -INFINITY) {
12396 var sign = (value < 0 ? -1 : 1);
12397 return sign * MAX_INTEGER;
12399 return value === value ? value : 0;
12403 * Converts `value` to an integer.
12405 * **Note:** This method is loosely based on
12406 * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
12412 * @param {*} value The value to convert.
12413 * @returns {number} Returns the converted integer.
12416 * _.toInteger(3.2);
12419 * _.toInteger(Number.MIN_VALUE);
12422 * _.toInteger(Infinity);
12423 * // => 1.7976931348623157e+308
12425 * _.toInteger('3.2');
12428 function toInteger(value) {
12429 var result = toFinite(value),
12430 remainder = result % 1;
12432 return result === result ? (remainder ? result - remainder : result) : 0;
12436 * Converts `value` to an integer suitable for use as the length of an
12437 * array-like object.
12439 * **Note:** This method is based on
12440 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
12446 * @param {*} value The value to convert.
12447 * @returns {number} Returns the converted integer.
12453 * _.toLength(Number.MIN_VALUE);
12456 * _.toLength(Infinity);
12459 * _.toLength('3.2');
12462 function toLength(value) {
12463 return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
12467 * Converts `value` to a number.
12473 * @param {*} value The value to process.
12474 * @returns {number} Returns the number.
12480 * _.toNumber(Number.MIN_VALUE);
12483 * _.toNumber(Infinity);
12486 * _.toNumber('3.2');
12489 function toNumber(value) {
12490 if (typeof value == 'number') {
12493 if (isSymbol(value)) {
12496 if (isObject(value)) {
12497 var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
12498 value = isObject(other) ? (other + '') : other;
12500 if (typeof value != 'string') {
12501 return value === 0 ? value : +value;
12503 value = value.replace(reTrim, '');
12504 var isBinary = reIsBinary.test(value);
12505 return (isBinary || reIsOctal.test(value))
12506 ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
12507 : (reIsBadHex.test(value) ? NAN : +value);
12511 * Converts `value` to a plain object flattening inherited enumerable string
12512 * keyed properties of `value` to own properties of the plain object.
12518 * @param {*} value The value to convert.
12519 * @returns {Object} Returns the converted plain object.
12526 * Foo.prototype.c = 3;
12528 * _.assign({ 'a': 1 }, new Foo);
12529 * // => { 'a': 1, 'b': 2 }
12531 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
12532 * // => { 'a': 1, 'b': 2, 'c': 3 }
12534 function toPlainObject(value) {
12535 return copyObject(value, keysIn(value));
12539 * Converts `value` to a safe integer. A safe integer can be compared and
12540 * represented correctly.
12546 * @param {*} value The value to convert.
12547 * @returns {number} Returns the converted integer.
12550 * _.toSafeInteger(3.2);
12553 * _.toSafeInteger(Number.MIN_VALUE);
12556 * _.toSafeInteger(Infinity);
12557 * // => 9007199254740991
12559 * _.toSafeInteger('3.2');
12562 function toSafeInteger(value) {
12564 ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
12565 : (value === 0 ? value : 0);
12569 * Converts `value` to a string. An empty string is returned for `null`
12570 * and `undefined` values. The sign of `-0` is preserved.
12576 * @param {*} value The value to convert.
12577 * @returns {string} Returns the converted string.
12580 * _.toString(null);
12586 * _.toString([1, 2, 3]);
12589 function toString(value) {
12590 return value == null ? '' : baseToString(value);
12593 /*------------------------------------------------------------------------*/
12596 * Assigns own enumerable string keyed properties of source objects to the
12597 * destination object. Source objects are applied from left to right.
12598 * Subsequent sources overwrite property assignments of previous sources.
12600 * **Note:** This method mutates `object` and is loosely based on
12601 * [`Object.assign`](https://mdn.io/Object/assign).
12607 * @param {Object} object The destination object.
12608 * @param {...Object} [sources] The source objects.
12609 * @returns {Object} Returns `object`.
12621 * Foo.prototype.b = 2;
12622 * Bar.prototype.d = 4;
12624 * _.assign({ 'a': 0 }, new Foo, new Bar);
12625 * // => { 'a': 1, 'c': 3 }
12627 var assign = createAssigner(function(object, source) {
12628 if (isPrototype(source) || isArrayLike(source)) {
12629 copyObject(source, keys(source), object);
12632 for (var key in source) {
12633 if (hasOwnProperty.call(source, key)) {
12634 assignValue(object, key, source[key]);
12640 * This method is like `_.assign` except that it iterates over own and
12641 * inherited source properties.
12643 * **Note:** This method mutates `object`.
12650 * @param {Object} object The destination object.
12651 * @param {...Object} [sources] The source objects.
12652 * @returns {Object} Returns `object`.
12664 * Foo.prototype.b = 2;
12665 * Bar.prototype.d = 4;
12667 * _.assignIn({ 'a': 0 }, new Foo, new Bar);
12668 * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
12670 var assignIn = createAssigner(function(object, source) {
12671 copyObject(source, keysIn(source), object);
12675 * This method is like `_.assignIn` except that it accepts `customizer`
12676 * which is invoked to produce the assigned values. If `customizer` returns
12677 * `undefined`, assignment is handled by the method instead. The `customizer`
12678 * is invoked with five arguments: (objValue, srcValue, key, object, source).
12680 * **Note:** This method mutates `object`.
12685 * @alias extendWith
12687 * @param {Object} object The destination object.
12688 * @param {...Object} sources The source objects.
12689 * @param {Function} [customizer] The function to customize assigned values.
12690 * @returns {Object} Returns `object`.
12691 * @see _.assignWith
12694 * function customizer(objValue, srcValue) {
12695 * return _.isUndefined(objValue) ? srcValue : objValue;
12698 * var defaults = _.partialRight(_.assignInWith, customizer);
12700 * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12701 * // => { 'a': 1, 'b': 2 }
12703 var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
12704 copyObject(source, keysIn(source), object, customizer);
12708 * This method is like `_.assign` except that it accepts `customizer`
12709 * which is invoked to produce the assigned values. If `customizer` returns
12710 * `undefined`, assignment is handled by the method instead. The `customizer`
12711 * is invoked with five arguments: (objValue, srcValue, key, object, source).
12713 * **Note:** This method mutates `object`.
12719 * @param {Object} object The destination object.
12720 * @param {...Object} sources The source objects.
12721 * @param {Function} [customizer] The function to customize assigned values.
12722 * @returns {Object} Returns `object`.
12723 * @see _.assignInWith
12726 * function customizer(objValue, srcValue) {
12727 * return _.isUndefined(objValue) ? srcValue : objValue;
12730 * var defaults = _.partialRight(_.assignWith, customizer);
12732 * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12733 * // => { 'a': 1, 'b': 2 }
12735 var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
12736 copyObject(source, keys(source), object, customizer);
12740 * Creates an array of values corresponding to `paths` of `object`.
12746 * @param {Object} object The object to iterate over.
12747 * @param {...(string|string[])} [paths] The property paths to pick.
12748 * @returns {Array} Returns the picked values.
12751 * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
12753 * _.at(object, ['a[0].b.c', 'a[1]']);
12756 var at = flatRest(baseAt);
12759 * Creates an object that inherits from the `prototype` object. If a
12760 * `properties` object is given, its own enumerable string keyed properties
12761 * are assigned to the created object.
12767 * @param {Object} prototype The object to inherit from.
12768 * @param {Object} [properties] The properties to assign to the object.
12769 * @returns {Object} Returns the new object.
12772 * function Shape() {
12777 * function Circle() {
12778 * Shape.call(this);
12781 * Circle.prototype = _.create(Shape.prototype, {
12782 * 'constructor': Circle
12785 * var circle = new Circle;
12786 * circle instanceof Circle;
12789 * circle instanceof Shape;
12792 function create(prototype, properties) {
12793 var result = baseCreate(prototype);
12794 return properties == null ? result : baseAssign(result, properties);
12798 * Assigns own and inherited enumerable string keyed properties of source
12799 * objects to the destination object for all destination properties that
12800 * resolve to `undefined`. Source objects are applied from left to right.
12801 * Once a property is set, additional values of the same property are ignored.
12803 * **Note:** This method mutates `object`.
12809 * @param {Object} object The destination object.
12810 * @param {...Object} [sources] The source objects.
12811 * @returns {Object} Returns `object`.
12812 * @see _.defaultsDeep
12815 * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12816 * // => { 'a': 1, 'b': 2 }
12818 var defaults = baseRest(function(args) {
12819 args.push(undefined, customDefaultsAssignIn);
12820 return apply(assignInWith, undefined, args);
12824 * This method is like `_.defaults` except that it recursively assigns
12825 * default properties.
12827 * **Note:** This method mutates `object`.
12833 * @param {Object} object The destination object.
12834 * @param {...Object} [sources] The source objects.
12835 * @returns {Object} Returns `object`.
12839 * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
12840 * // => { 'a': { 'b': 2, 'c': 3 } }
12842 var defaultsDeep = baseRest(function(args) {
12843 args.push(undefined, customDefaultsMerge);
12844 return apply(mergeWith, undefined, args);
12848 * This method is like `_.find` except that it returns the key of the first
12849 * element `predicate` returns truthy for instead of the element itself.
12855 * @param {Object} object The object to inspect.
12856 * @param {Function} [predicate=_.identity] The function invoked per iteration.
12857 * @returns {string|undefined} Returns the key of the matched element,
12858 * else `undefined`.
12862 * 'barney': { 'age': 36, 'active': true },
12863 * 'fred': { 'age': 40, 'active': false },
12864 * 'pebbles': { 'age': 1, 'active': true }
12867 * _.findKey(users, function(o) { return o.age < 40; });
12868 * // => 'barney' (iteration order is not guaranteed)
12870 * // The `_.matches` iteratee shorthand.
12871 * _.findKey(users, { 'age': 1, 'active': true });
12874 * // The `_.matchesProperty` iteratee shorthand.
12875 * _.findKey(users, ['active', false]);
12878 * // The `_.property` iteratee shorthand.
12879 * _.findKey(users, 'active');
12882 function findKey(object, predicate) {
12883 return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
12887 * This method is like `_.findKey` except that it iterates over elements of
12888 * a collection in the opposite order.
12894 * @param {Object} object The object to inspect.
12895 * @param {Function} [predicate=_.identity] The function invoked per iteration.
12896 * @returns {string|undefined} Returns the key of the matched element,
12897 * else `undefined`.
12901 * 'barney': { 'age': 36, 'active': true },
12902 * 'fred': { 'age': 40, 'active': false },
12903 * 'pebbles': { 'age': 1, 'active': true }
12906 * _.findLastKey(users, function(o) { return o.age < 40; });
12907 * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
12909 * // The `_.matches` iteratee shorthand.
12910 * _.findLastKey(users, { 'age': 36, 'active': true });
12913 * // The `_.matchesProperty` iteratee shorthand.
12914 * _.findLastKey(users, ['active', false]);
12917 * // The `_.property` iteratee shorthand.
12918 * _.findLastKey(users, 'active');
12921 function findLastKey(object, predicate) {
12922 return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
12926 * Iterates over own and inherited enumerable string keyed properties of an
12927 * object and invokes `iteratee` for each property. The iteratee is invoked
12928 * with three arguments: (value, key, object). Iteratee functions may exit
12929 * iteration early by explicitly returning `false`.
12935 * @param {Object} object The object to iterate over.
12936 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12937 * @returns {Object} Returns `object`.
12938 * @see _.forInRight
12946 * Foo.prototype.c = 3;
12948 * _.forIn(new Foo, function(value, key) {
12949 * console.log(key);
12951 * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
12953 function forIn(object, iteratee) {
12954 return object == null
12956 : baseFor(object, getIteratee(iteratee, 3), keysIn);
12960 * This method is like `_.forIn` except that it iterates over properties of
12961 * `object` in the opposite order.
12967 * @param {Object} object The object to iterate over.
12968 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12969 * @returns {Object} Returns `object`.
12978 * Foo.prototype.c = 3;
12980 * _.forInRight(new Foo, function(value, key) {
12981 * console.log(key);
12983 * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
12985 function forInRight(object, iteratee) {
12986 return object == null
12988 : baseForRight(object, getIteratee(iteratee, 3), keysIn);
12992 * Iterates over own enumerable string keyed properties of an object and
12993 * invokes `iteratee` for each property. The iteratee is invoked with three
12994 * arguments: (value, key, object). Iteratee functions may exit iteration
12995 * early by explicitly returning `false`.
13001 * @param {Object} object The object to iterate over.
13002 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13003 * @returns {Object} Returns `object`.
13004 * @see _.forOwnRight
13012 * Foo.prototype.c = 3;
13014 * _.forOwn(new Foo, function(value, key) {
13015 * console.log(key);
13017 * // => Logs 'a' then 'b' (iteration order is not guaranteed).
13019 function forOwn(object, iteratee) {
13020 return object && baseForOwn(object, getIteratee(iteratee, 3));
13024 * This method is like `_.forOwn` except that it iterates over properties of
13025 * `object` in the opposite order.
13031 * @param {Object} object The object to iterate over.
13032 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13033 * @returns {Object} Returns `object`.
13042 * Foo.prototype.c = 3;
13044 * _.forOwnRight(new Foo, function(value, key) {
13045 * console.log(key);
13047 * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
13049 function forOwnRight(object, iteratee) {
13050 return object && baseForOwnRight(object, getIteratee(iteratee, 3));
13054 * Creates an array of function property names from own enumerable properties
13061 * @param {Object} object The object to inspect.
13062 * @returns {Array} Returns the function names.
13063 * @see _.functionsIn
13067 * this.a = _.constant('a');
13068 * this.b = _.constant('b');
13071 * Foo.prototype.c = _.constant('c');
13073 * _.functions(new Foo);
13076 function functions(object) {
13077 return object == null ? [] : baseFunctions(object, keys(object));
13081 * Creates an array of function property names from own and inherited
13082 * enumerable properties of `object`.
13088 * @param {Object} object The object to inspect.
13089 * @returns {Array} Returns the function names.
13094 * this.a = _.constant('a');
13095 * this.b = _.constant('b');
13098 * Foo.prototype.c = _.constant('c');
13100 * _.functionsIn(new Foo);
13101 * // => ['a', 'b', 'c']
13103 function functionsIn(object) {
13104 return object == null ? [] : baseFunctions(object, keysIn(object));
13108 * Gets the value at `path` of `object`. If the resolved value is
13109 * `undefined`, the `defaultValue` is returned in its place.
13115 * @param {Object} object The object to query.
13116 * @param {Array|string} path The path of the property to get.
13117 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13118 * @returns {*} Returns the resolved value.
13121 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13123 * _.get(object, 'a[0].b.c');
13126 * _.get(object, ['a', '0', 'b', 'c']);
13129 * _.get(object, 'a.b.c', 'default');
13132 function get(object, path, defaultValue) {
13133 var result = object == null ? undefined : baseGet(object, path);
13134 return result === undefined ? defaultValue : result;
13138 * Checks if `path` is a direct property of `object`.
13144 * @param {Object} object The object to query.
13145 * @param {Array|string} path The path to check.
13146 * @returns {boolean} Returns `true` if `path` exists, else `false`.
13149 * var object = { 'a': { 'b': 2 } };
13150 * var other = _.create({ 'a': _.create({ 'b': 2 }) });
13152 * _.has(object, 'a');
13155 * _.has(object, 'a.b');
13158 * _.has(object, ['a', 'b']);
13161 * _.has(other, 'a');
13164 function has(object, path) {
13165 return object != null && hasPath(object, path, baseHas);
13169 * Checks if `path` is a direct or inherited property of `object`.
13175 * @param {Object} object The object to query.
13176 * @param {Array|string} path The path to check.
13177 * @returns {boolean} Returns `true` if `path` exists, else `false`.
13180 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
13182 * _.hasIn(object, 'a');
13185 * _.hasIn(object, 'a.b');
13188 * _.hasIn(object, ['a', 'b']);
13191 * _.hasIn(object, 'b');
13194 function hasIn(object, path) {
13195 return object != null && hasPath(object, path, baseHasIn);
13199 * Creates an object composed of the inverted keys and values of `object`.
13200 * If `object` contains duplicate values, subsequent values overwrite
13201 * property assignments of previous values.
13207 * @param {Object} object The object to invert.
13208 * @returns {Object} Returns the new inverted object.
13211 * var object = { 'a': 1, 'b': 2, 'c': 1 };
13213 * _.invert(object);
13214 * // => { '1': 'c', '2': 'b' }
13216 var invert = createInverter(function(result, value, key) {
13217 result[value] = key;
13218 }, constant(identity));
13221 * This method is like `_.invert` except that the inverted object is generated
13222 * from the results of running each element of `object` thru `iteratee`. The
13223 * corresponding inverted value of each inverted key is an array of keys
13224 * responsible for generating the inverted value. The iteratee is invoked
13225 * with one argument: (value).
13231 * @param {Object} object The object to invert.
13232 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
13233 * @returns {Object} Returns the new inverted object.
13236 * var object = { 'a': 1, 'b': 2, 'c': 1 };
13238 * _.invertBy(object);
13239 * // => { '1': ['a', 'c'], '2': ['b'] }
13241 * _.invertBy(object, function(value) {
13242 * return 'group' + value;
13244 * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
13246 var invertBy = createInverter(function(result, value, key) {
13247 if (hasOwnProperty.call(result, value)) {
13248 result[value].push(key);
13250 result[value] = [key];
13255 * Invokes the method at `path` of `object`.
13261 * @param {Object} object The object to query.
13262 * @param {Array|string} path The path of the method to invoke.
13263 * @param {...*} [args] The arguments to invoke the method with.
13264 * @returns {*} Returns the result of the invoked method.
13267 * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
13269 * _.invoke(object, 'a[0].b.c.slice', 1, 3);
13272 var invoke = baseRest(baseInvoke);
13275 * Creates an array of the own enumerable property names of `object`.
13277 * **Note:** Non-object values are coerced to objects. See the
13278 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
13279 * for more details.
13285 * @param {Object} object The object to query.
13286 * @returns {Array} Returns the array of property names.
13294 * Foo.prototype.c = 3;
13297 * // => ['a', 'b'] (iteration order is not guaranteed)
13302 function keys(object) {
13303 return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
13307 * Creates an array of the own and inherited enumerable property names of `object`.
13309 * **Note:** Non-object values are coerced to objects.
13315 * @param {Object} object The object to query.
13316 * @returns {Array} Returns the array of property names.
13324 * Foo.prototype.c = 3;
13326 * _.keysIn(new Foo);
13327 * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
13329 function keysIn(object) {
13330 return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
13334 * The opposite of `_.mapValues`; this method creates an object with the
13335 * same values as `object` and keys generated by running each own enumerable
13336 * string keyed property of `object` thru `iteratee`. The iteratee is invoked
13337 * with three arguments: (value, key, object).
13343 * @param {Object} object The object to iterate over.
13344 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13345 * @returns {Object} Returns the new mapped object.
13349 * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
13350 * return key + value;
13352 * // => { 'a1': 1, 'b2': 2 }
13354 function mapKeys(object, iteratee) {
13356 iteratee = getIteratee(iteratee, 3);
13358 baseForOwn(object, function(value, key, object) {
13359 baseAssignValue(result, iteratee(value, key, object), value);
13365 * Creates an object with the same keys as `object` and values generated
13366 * by running each own enumerable string keyed property of `object` thru
13367 * `iteratee`. The iteratee is invoked with three arguments:
13368 * (value, key, object).
13374 * @param {Object} object The object to iterate over.
13375 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13376 * @returns {Object} Returns the new mapped object.
13381 * 'fred': { 'user': 'fred', 'age': 40 },
13382 * 'pebbles': { 'user': 'pebbles', 'age': 1 }
13385 * _.mapValues(users, function(o) { return o.age; });
13386 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13388 * // The `_.property` iteratee shorthand.
13389 * _.mapValues(users, 'age');
13390 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13392 function mapValues(object, iteratee) {
13394 iteratee = getIteratee(iteratee, 3);
13396 baseForOwn(object, function(value, key, object) {
13397 baseAssignValue(result, key, iteratee(value, key, object));
13403 * This method is like `_.assign` except that it recursively merges own and
13404 * inherited enumerable string keyed properties of source objects into the
13405 * destination object. Source properties that resolve to `undefined` are
13406 * skipped if a destination value exists. Array and plain object properties
13407 * are merged recursively. Other objects and value types are overridden by
13408 * assignment. Source objects are applied from left to right. Subsequent
13409 * sources overwrite property assignments of previous sources.
13411 * **Note:** This method mutates `object`.
13417 * @param {Object} object The destination object.
13418 * @param {...Object} [sources] The source objects.
13419 * @returns {Object} Returns `object`.
13423 * 'a': [{ 'b': 2 }, { 'd': 4 }]
13427 * 'a': [{ 'c': 3 }, { 'e': 5 }]
13430 * _.merge(object, other);
13431 * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
13433 var merge = createAssigner(function(object, source, srcIndex) {
13434 baseMerge(object, source, srcIndex);
13438 * This method is like `_.merge` except that it accepts `customizer` which
13439 * is invoked to produce the merged values of the destination and source
13440 * properties. If `customizer` returns `undefined`, merging is handled by the
13441 * method instead. The `customizer` is invoked with six arguments:
13442 * (objValue, srcValue, key, object, source, stack).
13444 * **Note:** This method mutates `object`.
13450 * @param {Object} object The destination object.
13451 * @param {...Object} sources The source objects.
13452 * @param {Function} customizer The function to customize assigned values.
13453 * @returns {Object} Returns `object`.
13456 * function customizer(objValue, srcValue) {
13457 * if (_.isArray(objValue)) {
13458 * return objValue.concat(srcValue);
13462 * var object = { 'a': [1], 'b': [2] };
13463 * var other = { 'a': [3], 'b': [4] };
13465 * _.mergeWith(object, other, customizer);
13466 * // => { 'a': [1, 3], 'b': [2, 4] }
13468 var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
13469 baseMerge(object, source, srcIndex, customizer);
13473 * The opposite of `_.pick`; this method creates an object composed of the
13474 * own and inherited enumerable property paths of `object` that are not omitted.
13476 * **Note:** This method is considerably slower than `_.pick`.
13482 * @param {Object} object The source object.
13483 * @param {...(string|string[])} [paths] The property paths to omit.
13484 * @returns {Object} Returns the new object.
13487 * var object = { 'a': 1, 'b': '2', 'c': 3 };
13489 * _.omit(object, ['a', 'c']);
13490 * // => { 'b': '2' }
13492 var omit = flatRest(function(object, paths) {
13494 if (object == null) {
13497 var isDeep = false;
13498 paths = arrayMap(paths, function(path) {
13499 path = castPath(path, object);
13500 isDeep || (isDeep = path.length > 1);
13503 copyObject(object, getAllKeysIn(object), result);
13505 result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
13507 var length = paths.length;
13509 baseUnset(result, paths[length]);
13515 * The opposite of `_.pickBy`; this method creates an object composed of
13516 * the own and inherited enumerable string keyed properties of `object` that
13517 * `predicate` doesn't return truthy for. The predicate is invoked with two
13518 * arguments: (value, key).
13524 * @param {Object} object The source object.
13525 * @param {Function} [predicate=_.identity] The function invoked per property.
13526 * @returns {Object} Returns the new object.
13529 * var object = { 'a': 1, 'b': '2', 'c': 3 };
13531 * _.omitBy(object, _.isNumber);
13532 * // => { 'b': '2' }
13534 function omitBy(object, predicate) {
13535 return pickBy(object, negate(getIteratee(predicate)));
13539 * Creates an object composed of the picked `object` properties.
13545 * @param {Object} object The source object.
13546 * @param {...(string|string[])} [paths] The property paths to pick.
13547 * @returns {Object} Returns the new object.
13550 * var object = { 'a': 1, 'b': '2', 'c': 3 };
13552 * _.pick(object, ['a', 'c']);
13553 * // => { 'a': 1, 'c': 3 }
13555 var pick = flatRest(function(object, paths) {
13556 return object == null ? {} : basePick(object, paths);
13560 * Creates an object composed of the `object` properties `predicate` returns
13561 * truthy for. The predicate is invoked with two arguments: (value, key).
13567 * @param {Object} object The source object.
13568 * @param {Function} [predicate=_.identity] The function invoked per property.
13569 * @returns {Object} Returns the new object.
13572 * var object = { 'a': 1, 'b': '2', 'c': 3 };
13574 * _.pickBy(object, _.isNumber);
13575 * // => { 'a': 1, 'c': 3 }
13577 function pickBy(object, predicate) {
13578 if (object == null) {
13581 var props = arrayMap(getAllKeysIn(object), function(prop) {
13584 predicate = getIteratee(predicate);
13585 return basePickBy(object, props, function(value, path) {
13586 return predicate(value, path[0]);
13591 * This method is like `_.get` except that if the resolved value is a
13592 * function it's invoked with the `this` binding of its parent object and
13593 * its result is returned.
13599 * @param {Object} object The object to query.
13600 * @param {Array|string} path The path of the property to resolve.
13601 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13602 * @returns {*} Returns the resolved value.
13605 * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
13607 * _.result(object, 'a[0].b.c1');
13610 * _.result(object, 'a[0].b.c2');
13613 * _.result(object, 'a[0].b.c3', 'default');
13616 * _.result(object, 'a[0].b.c3', _.constant('default'));
13619 function result(object, path, defaultValue) {
13620 path = castPath(path, object);
13623 length = path.length;
13625 // Ensure the loop is entered when path is empty.
13628 object = undefined;
13630 while (++index < length) {
13631 var value = object == null ? undefined : object[toKey(path[index])];
13632 if (value === undefined) {
13634 value = defaultValue;
13636 object = isFunction(value) ? value.call(object) : value;
13642 * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
13643 * it's created. Arrays are created for missing index properties while objects
13644 * are created for all other missing properties. Use `_.setWith` to customize
13647 * **Note:** This method mutates `object`.
13653 * @param {Object} object The object to modify.
13654 * @param {Array|string} path The path of the property to set.
13655 * @param {*} value The value to set.
13656 * @returns {Object} Returns `object`.
13659 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13661 * _.set(object, 'a[0].b.c', 4);
13662 * console.log(object.a[0].b.c);
13665 * _.set(object, ['x', '0', 'y', 'z'], 5);
13666 * console.log(object.x[0].y.z);
13669 function set(object, path, value) {
13670 return object == null ? object : baseSet(object, path, value);
13674 * This method is like `_.set` except that it accepts `customizer` which is
13675 * invoked to produce the objects of `path`. If `customizer` returns `undefined`
13676 * path creation is handled by the method instead. The `customizer` is invoked
13677 * with three arguments: (nsValue, key, nsObject).
13679 * **Note:** This method mutates `object`.
13685 * @param {Object} object The object to modify.
13686 * @param {Array|string} path The path of the property to set.
13687 * @param {*} value The value to set.
13688 * @param {Function} [customizer] The function to customize assigned values.
13689 * @returns {Object} Returns `object`.
13694 * _.setWith(object, '[0][1]', 'a', Object);
13695 * // => { '0': { '1': 'a' } }
13697 function setWith(object, path, value, customizer) {
13698 customizer = typeof customizer == 'function' ? customizer : undefined;
13699 return object == null ? object : baseSet(object, path, value, customizer);
13703 * Creates an array of own enumerable string keyed-value pairs for `object`
13704 * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
13705 * entries are returned.
13712 * @param {Object} object The object to query.
13713 * @returns {Array} Returns the key-value pairs.
13721 * Foo.prototype.c = 3;
13723 * _.toPairs(new Foo);
13724 * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
13726 var toPairs = createToPairs(keys);
13729 * Creates an array of own and inherited enumerable string keyed-value pairs
13730 * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
13731 * or set, its entries are returned.
13738 * @param {Object} object The object to query.
13739 * @returns {Array} Returns the key-value pairs.
13747 * Foo.prototype.c = 3;
13749 * _.toPairsIn(new Foo);
13750 * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
13752 var toPairsIn = createToPairs(keysIn);
13755 * An alternative to `_.reduce`; this method transforms `object` to a new
13756 * `accumulator` object which is the result of running each of its own
13757 * enumerable string keyed properties thru `iteratee`, with each invocation
13758 * potentially mutating the `accumulator` object. If `accumulator` is not
13759 * provided, a new object with the same `[[Prototype]]` will be used. The
13760 * iteratee is invoked with four arguments: (accumulator, value, key, object).
13761 * Iteratee functions may exit iteration early by explicitly returning `false`.
13767 * @param {Object} object The object to iterate over.
13768 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13769 * @param {*} [accumulator] The custom accumulator value.
13770 * @returns {*} Returns the accumulated value.
13773 * _.transform([2, 3, 4], function(result, n) {
13774 * result.push(n *= n);
13775 * return n % 2 == 0;
13779 * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
13780 * (result[value] || (result[value] = [])).push(key);
13782 * // => { '1': ['a', 'c'], '2': ['b'] }
13784 function transform(object, iteratee, accumulator) {
13785 var isArr = isArray(object),
13786 isArrLike = isArr || isBuffer(object) || isTypedArray(object);
13788 iteratee = getIteratee(iteratee, 4);
13789 if (accumulator == null) {
13790 var Ctor = object && object.constructor;
13792 accumulator = isArr ? new Ctor : [];
13794 else if (isObject(object)) {
13795 accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
13801 (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
13802 return iteratee(accumulator, value, index, object);
13804 return accumulator;
13808 * Removes the property at `path` of `object`.
13810 * **Note:** This method mutates `object`.
13816 * @param {Object} object The object to modify.
13817 * @param {Array|string} path The path of the property to unset.
13818 * @returns {boolean} Returns `true` if the property is deleted, else `false`.
13821 * var object = { 'a': [{ 'b': { 'c': 7 } }] };
13822 * _.unset(object, 'a[0].b.c');
13825 * console.log(object);
13826 * // => { 'a': [{ 'b': {} }] };
13828 * _.unset(object, ['a', '0', 'b', 'c']);
13831 * console.log(object);
13832 * // => { 'a': [{ 'b': {} }] };
13834 function unset(object, path) {
13835 return object == null ? true : baseUnset(object, path);
13839 * This method is like `_.set` except that accepts `updater` to produce the
13840 * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
13841 * is invoked with one argument: (value).
13843 * **Note:** This method mutates `object`.
13849 * @param {Object} object The object to modify.
13850 * @param {Array|string} path The path of the property to set.
13851 * @param {Function} updater The function to produce the updated value.
13852 * @returns {Object} Returns `object`.
13855 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13857 * _.update(object, 'a[0].b.c', function(n) { return n * n; });
13858 * console.log(object.a[0].b.c);
13861 * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
13862 * console.log(object.x[0].y.z);
13865 function update(object, path, updater) {
13866 return object == null ? object : baseUpdate(object, path, castFunction(updater));
13870 * This method is like `_.update` except that it accepts `customizer` which is
13871 * invoked to produce the objects of `path`. If `customizer` returns `undefined`
13872 * path creation is handled by the method instead. The `customizer` is invoked
13873 * with three arguments: (nsValue, key, nsObject).
13875 * **Note:** This method mutates `object`.
13881 * @param {Object} object The object to modify.
13882 * @param {Array|string} path The path of the property to set.
13883 * @param {Function} updater The function to produce the updated value.
13884 * @param {Function} [customizer] The function to customize assigned values.
13885 * @returns {Object} Returns `object`.
13890 * _.updateWith(object, '[0][1]', _.constant('a'), Object);
13891 * // => { '0': { '1': 'a' } }
13893 function updateWith(object, path, updater, customizer) {
13894 customizer = typeof customizer == 'function' ? customizer : undefined;
13895 return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
13899 * Creates an array of the own enumerable string keyed property values of `object`.
13901 * **Note:** Non-object values are coerced to objects.
13907 * @param {Object} object The object to query.
13908 * @returns {Array} Returns the array of property values.
13916 * Foo.prototype.c = 3;
13918 * _.values(new Foo);
13919 * // => [1, 2] (iteration order is not guaranteed)
13924 function values(object) {
13925 return object == null ? [] : baseValues(object, keys(object));
13929 * Creates an array of the own and inherited enumerable string keyed property
13930 * values of `object`.
13932 * **Note:** Non-object values are coerced to objects.
13938 * @param {Object} object The object to query.
13939 * @returns {Array} Returns the array of property values.
13947 * Foo.prototype.c = 3;
13949 * _.valuesIn(new Foo);
13950 * // => [1, 2, 3] (iteration order is not guaranteed)
13952 function valuesIn(object) {
13953 return object == null ? [] : baseValues(object, keysIn(object));
13956 /*------------------------------------------------------------------------*/
13959 * Clamps `number` within the inclusive `lower` and `upper` bounds.
13965 * @param {number} number The number to clamp.
13966 * @param {number} [lower] The lower bound.
13967 * @param {number} upper The upper bound.
13968 * @returns {number} Returns the clamped number.
13971 * _.clamp(-10, -5, 5);
13974 * _.clamp(10, -5, 5);
13977 function clamp(number, lower, upper) {
13978 if (upper === undefined) {
13982 if (upper !== undefined) {
13983 upper = toNumber(upper);
13984 upper = upper === upper ? upper : 0;
13986 if (lower !== undefined) {
13987 lower = toNumber(lower);
13988 lower = lower === lower ? lower : 0;
13990 return baseClamp(toNumber(number), lower, upper);
13994 * Checks if `n` is between `start` and up to, but not including, `end`. If
13995 * `end` is not specified, it's set to `start` with `start` then set to `0`.
13996 * If `start` is greater than `end` the params are swapped to support
14003 * @param {number} number The number to check.
14004 * @param {number} [start=0] The start of the range.
14005 * @param {number} end The end of the range.
14006 * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
14007 * @see _.range, _.rangeRight
14010 * _.inRange(3, 2, 4);
14022 * _.inRange(1.2, 2);
14025 * _.inRange(5.2, 4);
14028 * _.inRange(-3, -2, -6);
14031 function inRange(number, start, end) {
14032 start = toFinite(start);
14033 if (end === undefined) {
14037 end = toFinite(end);
14039 number = toNumber(number);
14040 return baseInRange(number, start, end);
14044 * Produces a random number between the inclusive `lower` and `upper` bounds.
14045 * If only one argument is provided a number between `0` and the given number
14046 * is returned. If `floating` is `true`, or either `lower` or `upper` are
14047 * floats, a floating-point number is returned instead of an integer.
14049 * **Note:** JavaScript follows the IEEE-754 standard for resolving
14050 * floating-point values which can produce unexpected results.
14056 * @param {number} [lower=0] The lower bound.
14057 * @param {number} [upper=1] The upper bound.
14058 * @param {boolean} [floating] Specify returning a floating-point number.
14059 * @returns {number} Returns the random number.
14063 * // => an integer between 0 and 5
14066 * // => also an integer between 0 and 5
14068 * _.random(5, true);
14069 * // => a floating-point number between 0 and 5
14071 * _.random(1.2, 5.2);
14072 * // => a floating-point number between 1.2 and 5.2
14074 function random(lower, upper, floating) {
14075 if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
14076 upper = floating = undefined;
14078 if (floating === undefined) {
14079 if (typeof upper == 'boolean') {
14083 else if (typeof lower == 'boolean') {
14088 if (lower === undefined && upper === undefined) {
14093 lower = toFinite(lower);
14094 if (upper === undefined) {
14098 upper = toFinite(upper);
14101 if (lower > upper) {
14106 if (floating || lower % 1 || upper % 1) {
14107 var rand = nativeRandom();
14108 return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
14110 return baseRandom(lower, upper);
14113 /*------------------------------------------------------------------------*/
14116 * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
14122 * @param {string} [string=''] The string to convert.
14123 * @returns {string} Returns the camel cased string.
14126 * _.camelCase('Foo Bar');
14129 * _.camelCase('--foo-bar--');
14132 * _.camelCase('__FOO_BAR__');
14135 var camelCase = createCompounder(function(result, word, index) {
14136 word = word.toLowerCase();
14137 return result + (index ? capitalize(word) : word);
14141 * Converts the first character of `string` to upper case and the remaining
14148 * @param {string} [string=''] The string to capitalize.
14149 * @returns {string} Returns the capitalized string.
14152 * _.capitalize('FRED');
14155 function capitalize(string) {
14156 return upperFirst(toString(string).toLowerCase());
14160 * Deburrs `string` by converting
14161 * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
14162 * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
14163 * letters to basic Latin letters and removing
14164 * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
14170 * @param {string} [string=''] The string to deburr.
14171 * @returns {string} Returns the deburred string.
14174 * _.deburr('déjà vu');
14177 function deburr(string) {
14178 string = toString(string);
14179 return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
14183 * Checks if `string` ends with the given target string.
14189 * @param {string} [string=''] The string to inspect.
14190 * @param {string} [target] The string to search for.
14191 * @param {number} [position=string.length] The position to search up to.
14192 * @returns {boolean} Returns `true` if `string` ends with `target`,
14196 * _.endsWith('abc', 'c');
14199 * _.endsWith('abc', 'b');
14202 * _.endsWith('abc', 'b', 2);
14205 function endsWith(string, target, position) {
14206 string = toString(string);
14207 target = baseToString(target);
14209 var length = string.length;
14210 position = position === undefined
14212 : baseClamp(toInteger(position), 0, length);
14214 var end = position;
14215 position -= target.length;
14216 return position >= 0 && string.slice(position, end) == target;
14220 * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
14221 * corresponding HTML entities.
14223 * **Note:** No other characters are escaped. To escape additional
14224 * characters use a third-party library like [_he_](https://mths.be/he).
14226 * Though the ">" character is escaped for symmetry, characters like
14227 * ">" and "/" don't need escaping in HTML and have no special meaning
14228 * unless they're part of a tag or unquoted attribute value. See
14229 * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
14230 * (under "semi-related fun fact") for more details.
14232 * When working with HTML you should always
14233 * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
14240 * @param {string} [string=''] The string to escape.
14241 * @returns {string} Returns the escaped string.
14244 * _.escape('fred, barney, & pebbles');
14245 * // => 'fred, barney, & pebbles'
14247 function escape(string) {
14248 string = toString(string);
14249 return (string && reHasUnescapedHtml.test(string))
14250 ? string.replace(reUnescapedHtml, escapeHtmlChar)
14255 * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
14256 * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
14262 * @param {string} [string=''] The string to escape.
14263 * @returns {string} Returns the escaped string.
14266 * _.escapeRegExp('[lodash](https://lodash.com/)');
14267 * // => '\[lodash\]\(https://lodash\.com/\)'
14269 function escapeRegExp(string) {
14270 string = toString(string);
14271 return (string && reHasRegExpChar.test(string))
14272 ? string.replace(reRegExpChar, '\\$&')
14277 * Converts `string` to
14278 * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
14284 * @param {string} [string=''] The string to convert.
14285 * @returns {string} Returns the kebab cased string.
14288 * _.kebabCase('Foo Bar');
14291 * _.kebabCase('fooBar');
14294 * _.kebabCase('__FOO_BAR__');
14297 var kebabCase = createCompounder(function(result, word, index) {
14298 return result + (index ? '-' : '') + word.toLowerCase();
14302 * Converts `string`, as space separated words, to lower case.
14308 * @param {string} [string=''] The string to convert.
14309 * @returns {string} Returns the lower cased string.
14312 * _.lowerCase('--Foo-Bar--');
14315 * _.lowerCase('fooBar');
14318 * _.lowerCase('__FOO_BAR__');
14321 var lowerCase = createCompounder(function(result, word, index) {
14322 return result + (index ? ' ' : '') + word.toLowerCase();
14326 * Converts the first character of `string` to lower case.
14332 * @param {string} [string=''] The string to convert.
14333 * @returns {string} Returns the converted string.
14336 * _.lowerFirst('Fred');
14339 * _.lowerFirst('FRED');
14342 var lowerFirst = createCaseFirst('toLowerCase');
14345 * Pads `string` on the left and right sides if it's shorter than `length`.
14346 * Padding characters are truncated if they can't be evenly divided by `length`.
14352 * @param {string} [string=''] The string to pad.
14353 * @param {number} [length=0] The padding length.
14354 * @param {string} [chars=' '] The string used as padding.
14355 * @returns {string} Returns the padded string.
14361 * _.pad('abc', 8, '_-');
14367 function pad(string, length, chars) {
14368 string = toString(string);
14369 length = toInteger(length);
14371 var strLength = length ? stringSize(string) : 0;
14372 if (!length || strLength >= length) {
14375 var mid = (length - strLength) / 2;
14377 createPadding(nativeFloor(mid), chars) +
14379 createPadding(nativeCeil(mid), chars)
14384 * Pads `string` on the right side if it's shorter than `length`. Padding
14385 * characters are truncated if they exceed `length`.
14391 * @param {string} [string=''] The string to pad.
14392 * @param {number} [length=0] The padding length.
14393 * @param {string} [chars=' '] The string used as padding.
14394 * @returns {string} Returns the padded string.
14397 * _.padEnd('abc', 6);
14400 * _.padEnd('abc', 6, '_-');
14403 * _.padEnd('abc', 3);
14406 function padEnd(string, length, chars) {
14407 string = toString(string);
14408 length = toInteger(length);
14410 var strLength = length ? stringSize(string) : 0;
14411 return (length && strLength < length)
14412 ? (string + createPadding(length - strLength, chars))
14417 * Pads `string` on the left side if it's shorter than `length`. Padding
14418 * characters are truncated if they exceed `length`.
14424 * @param {string} [string=''] The string to pad.
14425 * @param {number} [length=0] The padding length.
14426 * @param {string} [chars=' '] The string used as padding.
14427 * @returns {string} Returns the padded string.
14430 * _.padStart('abc', 6);
14433 * _.padStart('abc', 6, '_-');
14436 * _.padStart('abc', 3);
14439 function padStart(string, length, chars) {
14440 string = toString(string);
14441 length = toInteger(length);
14443 var strLength = length ? stringSize(string) : 0;
14444 return (length && strLength < length)
14445 ? (createPadding(length - strLength, chars) + string)
14450 * Converts `string` to an integer of the specified radix. If `radix` is
14451 * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
14452 * hexadecimal, in which case a `radix` of `16` is used.
14454 * **Note:** This method aligns with the
14455 * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
14461 * @param {string} string The string to convert.
14462 * @param {number} [radix=10] The radix to interpret `value` by.
14463 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14464 * @returns {number} Returns the converted integer.
14467 * _.parseInt('08');
14470 * _.map(['6', '08', '10'], _.parseInt);
14473 function parseInt(string, radix, guard) {
14474 if (guard || radix == null) {
14476 } else if (radix) {
14479 return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
14483 * Repeats the given string `n` times.
14489 * @param {string} [string=''] The string to repeat.
14490 * @param {number} [n=1] The number of times to repeat the string.
14491 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14492 * @returns {string} Returns the repeated string.
14495 * _.repeat('*', 3);
14498 * _.repeat('abc', 2);
14501 * _.repeat('abc', 0);
14504 function repeat(string, n, guard) {
14505 if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
14510 return baseRepeat(toString(string), n);
14514 * Replaces matches for `pattern` in `string` with `replacement`.
14516 * **Note:** This method is based on
14517 * [`String#replace`](https://mdn.io/String/replace).
14523 * @param {string} [string=''] The string to modify.
14524 * @param {RegExp|string} pattern The pattern to replace.
14525 * @param {Function|string} replacement The match replacement.
14526 * @returns {string} Returns the modified string.
14529 * _.replace('Hi Fred', 'Fred', 'Barney');
14530 * // => 'Hi Barney'
14532 function replace() {
14533 var args = arguments,
14534 string = toString(args[0]);
14536 return args.length < 3 ? string : string.replace(args[1], args[2]);
14540 * Converts `string` to
14541 * [snake case](https://en.wikipedia.org/wiki/Snake_case).
14547 * @param {string} [string=''] The string to convert.
14548 * @returns {string} Returns the snake cased string.
14551 * _.snakeCase('Foo Bar');
14554 * _.snakeCase('fooBar');
14557 * _.snakeCase('--FOO-BAR--');
14560 var snakeCase = createCompounder(function(result, word, index) {
14561 return result + (index ? '_' : '') + word.toLowerCase();
14565 * Splits `string` by `separator`.
14567 * **Note:** This method is based on
14568 * [`String#split`](https://mdn.io/String/split).
14574 * @param {string} [string=''] The string to split.
14575 * @param {RegExp|string} separator The separator pattern to split by.
14576 * @param {number} [limit] The length to truncate results to.
14577 * @returns {Array} Returns the string segments.
14580 * _.split('a-b-c', '-', 2);
14583 function split(string, separator, limit) {
14584 if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
14585 separator = limit = undefined;
14587 limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
14591 string = toString(string);
14593 typeof separator == 'string' ||
14594 (separator != null && !isRegExp(separator))
14596 separator = baseToString(separator);
14597 if (!separator && hasUnicode(string)) {
14598 return castSlice(stringToArray(string), 0, limit);
14601 return string.split(separator, limit);
14605 * Converts `string` to
14606 * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
14612 * @param {string} [string=''] The string to convert.
14613 * @returns {string} Returns the start cased string.
14616 * _.startCase('--foo-bar--');
14619 * _.startCase('fooBar');
14622 * _.startCase('__FOO_BAR__');
14625 var startCase = createCompounder(function(result, word, index) {
14626 return result + (index ? ' ' : '') + upperFirst(word);
14630 * Checks if `string` starts with the given target string.
14636 * @param {string} [string=''] The string to inspect.
14637 * @param {string} [target] The string to search for.
14638 * @param {number} [position=0] The position to search from.
14639 * @returns {boolean} Returns `true` if `string` starts with `target`,
14643 * _.startsWith('abc', 'a');
14646 * _.startsWith('abc', 'b');
14649 * _.startsWith('abc', 'b', 1);
14652 function startsWith(string, target, position) {
14653 string = toString(string);
14654 position = position == null
14656 : baseClamp(toInteger(position), 0, string.length);
14658 target = baseToString(target);
14659 return string.slice(position, position + target.length) == target;
14663 * Creates a compiled template function that can interpolate data properties
14664 * in "interpolate" delimiters, HTML-escape interpolated data properties in
14665 * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
14666 * properties may be accessed as free variables in the template. If a setting
14667 * object is given, it takes precedence over `_.templateSettings` values.
14669 * **Note:** In the development build `_.template` utilizes
14670 * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
14671 * for easier debugging.
14673 * For more information on precompiling templates see
14674 * [lodash's custom builds documentation](https://lodash.com/custom-builds).
14676 * For more information on Chrome extension sandboxes see
14677 * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
14683 * @param {string} [string=''] The template string.
14684 * @param {Object} [options={}] The options object.
14685 * @param {RegExp} [options.escape=_.templateSettings.escape]
14686 * The HTML "escape" delimiter.
14687 * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
14688 * The "evaluate" delimiter.
14689 * @param {Object} [options.imports=_.templateSettings.imports]
14690 * An object to import into the template as free variables.
14691 * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
14692 * The "interpolate" delimiter.
14693 * @param {string} [options.sourceURL='lodash.templateSources[n]']
14694 * The sourceURL of the compiled template.
14695 * @param {string} [options.variable='obj']
14696 * The data object variable name.
14697 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14698 * @returns {Function} Returns the compiled template function.
14701 * // Use the "interpolate" delimiter to create a compiled template.
14702 * var compiled = _.template('hello <%= user %>!');
14703 * compiled({ 'user': 'fred' });
14704 * // => 'hello fred!'
14706 * // Use the HTML "escape" delimiter to escape data property values.
14707 * var compiled = _.template('<b><%- value %></b>');
14708 * compiled({ 'value': '<script>' });
14709 * // => '<b><script></b>'
14711 * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
14712 * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
14713 * compiled({ 'users': ['fred', 'barney'] });
14714 * // => '<li>fred</li><li>barney</li>'
14716 * // Use the internal `print` function in "evaluate" delimiters.
14717 * var compiled = _.template('<% print("hello " + user); %>!');
14718 * compiled({ 'user': 'barney' });
14719 * // => 'hello barney!'
14721 * // Use the ES template literal delimiter as an "interpolate" delimiter.
14722 * // Disable support by replacing the "interpolate" delimiter.
14723 * var compiled = _.template('hello ${ user }!');
14724 * compiled({ 'user': 'pebbles' });
14725 * // => 'hello pebbles!'
14727 * // Use backslashes to treat delimiters as plain text.
14728 * var compiled = _.template('<%= "\\<%- value %\\>" %>');
14729 * compiled({ 'value': 'ignored' });
14730 * // => '<%- value %>'
14732 * // Use the `imports` option to import `jQuery` as `jq`.
14733 * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
14734 * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
14735 * compiled({ 'users': ['fred', 'barney'] });
14736 * // => '<li>fred</li><li>barney</li>'
14738 * // Use the `sourceURL` option to specify a custom sourceURL for the template.
14739 * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
14741 * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
14743 * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
14744 * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
14746 * // => function(data) {
14747 * // var __t, __p = '';
14748 * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
14752 * // Use custom template delimiters.
14753 * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
14754 * var compiled = _.template('hello {{ user }}!');
14755 * compiled({ 'user': 'mustache' });
14756 * // => 'hello mustache!'
14758 * // Use the `source` property to inline compiled templates for meaningful
14759 * // line numbers in error messages and stack traces.
14760 * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
14762 * "main": ' + _.template(mainText).source + '\
14766 function template(string, options, guard) {
14767 // Based on John Resig's `tmpl` implementation
14768 // (http://ejohn.org/blog/javascript-micro-templating/)
14769 // and Laura Doktorova's doT.js (https://github.com/olado/doT).
14770 var settings = lodash.templateSettings;
14772 if (guard && isIterateeCall(string, options, guard)) {
14773 options = undefined;
14775 string = toString(string);
14776 options = assignInWith({}, options, settings, customDefaultsAssignIn);
14778 var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
14779 importsKeys = keys(imports),
14780 importsValues = baseValues(imports, importsKeys);
14785 interpolate = options.interpolate || reNoMatch,
14786 source = "__p += '";
14788 // Compile the regexp to match each delimiter.
14789 var reDelimiters = RegExp(
14790 (options.escape || reNoMatch).source + '|' +
14791 interpolate.source + '|' +
14792 (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
14793 (options.evaluate || reNoMatch).source + '|$'
14796 // Use a sourceURL for easier debugging.
14797 var sourceURL = '//# sourceURL=' +
14798 ('sourceURL' in options
14799 ? options.sourceURL
14800 : ('lodash.templateSources[' + (++templateCounter) + ']')
14803 string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
14804 interpolateValue || (interpolateValue = esTemplateValue);
14806 // Escape characters that can't be included in string literals.
14807 source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
14809 // Replace delimiters with snippets.
14812 source += "' +\n__e(" + escapeValue + ") +\n'";
14814 if (evaluateValue) {
14815 isEvaluating = true;
14816 source += "';\n" + evaluateValue + ";\n__p += '";
14818 if (interpolateValue) {
14819 source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
14821 index = offset + match.length;
14823 // The JS engine embedded in Adobe products needs `match` returned in
14824 // order to produce the correct `offset` value.
14830 // If `variable` is not specified wrap a with-statement around the generated
14831 // code to add the data object to the top of the scope chain.
14832 var variable = options.variable;
14834 source = 'with (obj) {\n' + source + '\n}\n';
14836 // Cleanup code by stripping empty strings.
14837 source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
14838 .replace(reEmptyStringMiddle, '$1')
14839 .replace(reEmptyStringTrailing, '$1;');
14841 // Frame code as the function body.
14842 source = 'function(' + (variable || 'obj') + ') {\n' +
14845 : 'obj || (obj = {});\n'
14847 "var __t, __p = ''" +
14849 ? ', __e = _.escape'
14853 ? ', __j = Array.prototype.join;\n' +
14854 "function print() { __p += __j.call(arguments, '') }\n"
14860 var result = attempt(function() {
14861 return Function(importsKeys, sourceURL + 'return ' + source)
14862 .apply(undefined, importsValues);
14865 // Provide the compiled function's source by its `toString` method or
14866 // the `source` property as a convenience for inlining compiled templates.
14867 result.source = source;
14868 if (isError(result)) {
14875 * Converts `string`, as a whole, to lower case just like
14876 * [String#toLowerCase](https://mdn.io/toLowerCase).
14882 * @param {string} [string=''] The string to convert.
14883 * @returns {string} Returns the lower cased string.
14886 * _.toLower('--Foo-Bar--');
14887 * // => '--foo-bar--'
14889 * _.toLower('fooBar');
14892 * _.toLower('__FOO_BAR__');
14893 * // => '__foo_bar__'
14895 function toLower(value) {
14896 return toString(value).toLowerCase();
14900 * Converts `string`, as a whole, to upper case just like
14901 * [String#toUpperCase](https://mdn.io/toUpperCase).
14907 * @param {string} [string=''] The string to convert.
14908 * @returns {string} Returns the upper cased string.
14911 * _.toUpper('--foo-bar--');
14912 * // => '--FOO-BAR--'
14914 * _.toUpper('fooBar');
14917 * _.toUpper('__foo_bar__');
14918 * // => '__FOO_BAR__'
14920 function toUpper(value) {
14921 return toString(value).toUpperCase();
14925 * Removes leading and trailing whitespace or specified characters from `string`.
14931 * @param {string} [string=''] The string to trim.
14932 * @param {string} [chars=whitespace] The characters to trim.
14933 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14934 * @returns {string} Returns the trimmed string.
14940 * _.trim('-_-abc-_-', '_-');
14943 * _.map([' foo ', ' bar '], _.trim);
14944 * // => ['foo', 'bar']
14946 function trim(string, chars, guard) {
14947 string = toString(string);
14948 if (string && (guard || chars === undefined)) {
14949 return string.replace(reTrim, '');
14951 if (!string || !(chars = baseToString(chars))) {
14954 var strSymbols = stringToArray(string),
14955 chrSymbols = stringToArray(chars),
14956 start = charsStartIndex(strSymbols, chrSymbols),
14957 end = charsEndIndex(strSymbols, chrSymbols) + 1;
14959 return castSlice(strSymbols, start, end).join('');
14963 * Removes trailing whitespace or specified characters from `string`.
14969 * @param {string} [string=''] The string to trim.
14970 * @param {string} [chars=whitespace] The characters to trim.
14971 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14972 * @returns {string} Returns the trimmed string.
14975 * _.trimEnd(' abc ');
14978 * _.trimEnd('-_-abc-_-', '_-');
14981 function trimEnd(string, chars, guard) {
14982 string = toString(string);
14983 if (string && (guard || chars === undefined)) {
14984 return string.replace(reTrimEnd, '');
14986 if (!string || !(chars = baseToString(chars))) {
14989 var strSymbols = stringToArray(string),
14990 end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
14992 return castSlice(strSymbols, 0, end).join('');
14996 * Removes leading whitespace or specified characters from `string`.
15002 * @param {string} [string=''] The string to trim.
15003 * @param {string} [chars=whitespace] The characters to trim.
15004 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15005 * @returns {string} Returns the trimmed string.
15008 * _.trimStart(' abc ');
15011 * _.trimStart('-_-abc-_-', '_-');
15014 function trimStart(string, chars, guard) {
15015 string = toString(string);
15016 if (string && (guard || chars === undefined)) {
15017 return string.replace(reTrimStart, '');
15019 if (!string || !(chars = baseToString(chars))) {
15022 var strSymbols = stringToArray(string),
15023 start = charsStartIndex(strSymbols, stringToArray(chars));
15025 return castSlice(strSymbols, start).join('');
15029 * Truncates `string` if it's longer than the given maximum string length.
15030 * The last characters of the truncated string are replaced with the omission
15031 * string which defaults to "...".
15037 * @param {string} [string=''] The string to truncate.
15038 * @param {Object} [options={}] The options object.
15039 * @param {number} [options.length=30] The maximum string length.
15040 * @param {string} [options.omission='...'] The string to indicate text is omitted.
15041 * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
15042 * @returns {string} Returns the truncated string.
15045 * _.truncate('hi-diddly-ho there, neighborino');
15046 * // => 'hi-diddly-ho there, neighbo...'
15048 * _.truncate('hi-diddly-ho there, neighborino', {
15052 * // => 'hi-diddly-ho there,...'
15054 * _.truncate('hi-diddly-ho there, neighborino', {
15056 * 'separator': /,? +/
15058 * // => 'hi-diddly-ho there...'
15060 * _.truncate('hi-diddly-ho there, neighborino', {
15061 * 'omission': ' [...]'
15063 * // => 'hi-diddly-ho there, neig [...]'
15065 function truncate(string, options) {
15066 var length = DEFAULT_TRUNC_LENGTH,
15067 omission = DEFAULT_TRUNC_OMISSION;
15069 if (isObject(options)) {
15070 var separator = 'separator' in options ? options.separator : separator;
15071 length = 'length' in options ? toInteger(options.length) : length;
15072 omission = 'omission' in options ? baseToString(options.omission) : omission;
15074 string = toString(string);
15076 var strLength = string.length;
15077 if (hasUnicode(string)) {
15078 var strSymbols = stringToArray(string);
15079 strLength = strSymbols.length;
15081 if (length >= strLength) {
15084 var end = length - stringSize(omission);
15088 var result = strSymbols
15089 ? castSlice(strSymbols, 0, end).join('')
15090 : string.slice(0, end);
15092 if (separator === undefined) {
15093 return result + omission;
15096 end += (result.length - end);
15098 if (isRegExp(separator)) {
15099 if (string.slice(end).search(separator)) {
15101 substring = result;
15103 if (!separator.global) {
15104 separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
15106 separator.lastIndex = 0;
15107 while ((match = separator.exec(substring))) {
15108 var newEnd = match.index;
15110 result = result.slice(0, newEnd === undefined ? end : newEnd);
15112 } else if (string.indexOf(baseToString(separator), end) != end) {
15113 var index = result.lastIndexOf(separator);
15115 result = result.slice(0, index);
15118 return result + omission;
15122 * The inverse of `_.escape`; this method converts the HTML entities
15123 * `&`, `<`, `>`, `"`, and `'` in `string` to
15124 * their corresponding characters.
15126 * **Note:** No other HTML entities are unescaped. To unescape additional
15127 * HTML entities use a third-party library like [_he_](https://mths.be/he).
15133 * @param {string} [string=''] The string to unescape.
15134 * @returns {string} Returns the unescaped string.
15137 * _.unescape('fred, barney, & pebbles');
15138 * // => 'fred, barney, & pebbles'
15140 function unescape(string) {
15141 string = toString(string);
15142 return (string && reHasEscapedHtml.test(string))
15143 ? string.replace(reEscapedHtml, unescapeHtmlChar)
15148 * Converts `string`, as space separated words, to upper case.
15154 * @param {string} [string=''] The string to convert.
15155 * @returns {string} Returns the upper cased string.
15158 * _.upperCase('--foo-bar');
15161 * _.upperCase('fooBar');
15164 * _.upperCase('__foo_bar__');
15167 var upperCase = createCompounder(function(result, word, index) {
15168 return result + (index ? ' ' : '') + word.toUpperCase();
15172 * Converts the first character of `string` to upper case.
15178 * @param {string} [string=''] The string to convert.
15179 * @returns {string} Returns the converted string.
15182 * _.upperFirst('fred');
15185 * _.upperFirst('FRED');
15188 var upperFirst = createCaseFirst('toUpperCase');
15191 * Splits `string` into an array of its words.
15197 * @param {string} [string=''] The string to inspect.
15198 * @param {RegExp|string} [pattern] The pattern to match words.
15199 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15200 * @returns {Array} Returns the words of `string`.
15203 * _.words('fred, barney, & pebbles');
15204 * // => ['fred', 'barney', 'pebbles']
15206 * _.words('fred, barney, & pebbles', /[^, ]+/g);
15207 * // => ['fred', 'barney', '&', 'pebbles']
15209 function words(string, pattern, guard) {
15210 string = toString(string);
15211 pattern = guard ? undefined : pattern;
15213 if (pattern === undefined) {
15214 return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
15216 return string.match(pattern) || [];
15219 /*------------------------------------------------------------------------*/
15222 * Attempts to invoke `func`, returning either the result or the caught error
15223 * object. Any additional arguments are provided to `func` when it's invoked.
15229 * @param {Function} func The function to attempt.
15230 * @param {...*} [args] The arguments to invoke `func` with.
15231 * @returns {*} Returns the `func` result or error object.
15234 * // Avoid throwing errors for invalid selectors.
15235 * var elements = _.attempt(function(selector) {
15236 * return document.querySelectorAll(selector);
15239 * if (_.isError(elements)) {
15243 var attempt = baseRest(function(func, args) {
15245 return apply(func, undefined, args);
15247 return isError(e) ? e : new Error(e);
15252 * Binds methods of an object to the object itself, overwriting the existing
15255 * **Note:** This method doesn't set the "length" property of bound functions.
15261 * @param {Object} object The object to bind and assign the bound methods to.
15262 * @param {...(string|string[])} methodNames The object method names to bind.
15263 * @returns {Object} Returns `object`.
15268 * 'click': function() {
15269 * console.log('clicked ' + this.label);
15273 * _.bindAll(view, ['click']);
15274 * jQuery(element).on('click', view.click);
15275 * // => Logs 'clicked docs' when clicked.
15277 var bindAll = flatRest(function(object, methodNames) {
15278 arrayEach(methodNames, function(key) {
15280 baseAssignValue(object, key, bind(object[key], object));
15286 * Creates a function that iterates over `pairs` and invokes the corresponding
15287 * function of the first predicate to return truthy. The predicate-function
15288 * pairs are invoked with the `this` binding and arguments of the created
15295 * @param {Array} pairs The predicate-function pairs.
15296 * @returns {Function} Returns the new composite function.
15299 * var func = _.cond([
15300 * [_.matches({ 'a': 1 }), _.constant('matches A')],
15301 * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
15302 * [_.stubTrue, _.constant('no match')]
15305 * func({ 'a': 1, 'b': 2 });
15306 * // => 'matches A'
15308 * func({ 'a': 0, 'b': 1 });
15309 * // => 'matches B'
15311 * func({ 'a': '1', 'b': '2' });
15314 function cond(pairs) {
15315 var length = pairs == null ? 0 : pairs.length,
15316 toIteratee = getIteratee();
15318 pairs = !length ? [] : arrayMap(pairs, function(pair) {
15319 if (typeof pair[1] != 'function') {
15320 throw new TypeError(FUNC_ERROR_TEXT);
15322 return [toIteratee(pair[0]), pair[1]];
15325 return baseRest(function(args) {
15327 while (++index < length) {
15328 var pair = pairs[index];
15329 if (apply(pair[0], this, args)) {
15330 return apply(pair[1], this, args);
15337 * Creates a function that invokes the predicate properties of `source` with
15338 * the corresponding property values of a given object, returning `true` if
15339 * all predicates return truthy, else `false`.
15341 * **Note:** The created function is equivalent to `_.conformsTo` with
15342 * `source` partially applied.
15348 * @param {Object} source The object of property predicates to conform to.
15349 * @returns {Function} Returns the new spec function.
15353 * { 'a': 2, 'b': 1 },
15354 * { 'a': 1, 'b': 2 }
15357 * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
15358 * // => [{ 'a': 1, 'b': 2 }]
15360 function conforms(source) {
15361 return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
15365 * Creates a function that returns `value`.
15371 * @param {*} value The value to return from the new function.
15372 * @returns {Function} Returns the new constant function.
15375 * var objects = _.times(2, _.constant({ 'a': 1 }));
15377 * console.log(objects);
15378 * // => [{ 'a': 1 }, { 'a': 1 }]
15380 * console.log(objects[0] === objects[1]);
15383 function constant(value) {
15384 return function() {
15390 * Checks `value` to determine whether a default value should be returned in
15391 * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
15398 * @param {*} value The value to check.
15399 * @param {*} defaultValue The default value.
15400 * @returns {*} Returns the resolved value.
15403 * _.defaultTo(1, 10);
15406 * _.defaultTo(undefined, 10);
15409 function defaultTo(value, defaultValue) {
15410 return (value == null || value !== value) ? defaultValue : value;
15414 * Creates a function that returns the result of invoking the given functions
15415 * with the `this` binding of the created function, where each successive
15416 * invocation is supplied the return value of the previous.
15422 * @param {...(Function|Function[])} [funcs] The functions to invoke.
15423 * @returns {Function} Returns the new composite function.
15427 * function square(n) {
15431 * var addSquare = _.flow([_.add, square]);
15435 var flow = createFlow();
15438 * This method is like `_.flow` except that it creates a function that
15439 * invokes the given functions from right to left.
15445 * @param {...(Function|Function[])} [funcs] The functions to invoke.
15446 * @returns {Function} Returns the new composite function.
15450 * function square(n) {
15454 * var addSquare = _.flowRight([square, _.add]);
15458 var flowRight = createFlow(true);
15461 * This method returns the first argument it receives.
15467 * @param {*} value Any value.
15468 * @returns {*} Returns `value`.
15471 * var object = { 'a': 1 };
15473 * console.log(_.identity(object) === object);
15476 function identity(value) {
15481 * Creates a function that invokes `func` with the arguments of the created
15482 * function. If `func` is a property name, the created function returns the
15483 * property value for a given element. If `func` is an array or object, the
15484 * created function returns `true` for elements that contain the equivalent
15485 * source properties, otherwise it returns `false`.
15491 * @param {*} [func=_.identity] The value to convert to a callback.
15492 * @returns {Function} Returns the callback.
15496 * { 'user': 'barney', 'age': 36, 'active': true },
15497 * { 'user': 'fred', 'age': 40, 'active': false }
15500 * // The `_.matches` iteratee shorthand.
15501 * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
15502 * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
15504 * // The `_.matchesProperty` iteratee shorthand.
15505 * _.filter(users, _.iteratee(['user', 'fred']));
15506 * // => [{ 'user': 'fred', 'age': 40 }]
15508 * // The `_.property` iteratee shorthand.
15509 * _.map(users, _.iteratee('user'));
15510 * // => ['barney', 'fred']
15512 * // Create custom iteratee shorthands.
15513 * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
15514 * return !_.isRegExp(func) ? iteratee(func) : function(string) {
15515 * return func.test(string);
15519 * _.filter(['abc', 'def'], /ef/);
15522 function iteratee(func) {
15523 return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
15527 * Creates a function that performs a partial deep comparison between a given
15528 * object and `source`, returning `true` if the given object has equivalent
15529 * property values, else `false`.
15531 * **Note:** The created function is equivalent to `_.isMatch` with `source`
15532 * partially applied.
15534 * Partial comparisons will match empty array and empty object `source`
15535 * values against any array or object value, respectively. See `_.isEqual`
15536 * for a list of supported value comparisons.
15542 * @param {Object} source The object of property values to match.
15543 * @returns {Function} Returns the new spec function.
15547 * { 'a': 1, 'b': 2, 'c': 3 },
15548 * { 'a': 4, 'b': 5, 'c': 6 }
15551 * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
15552 * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
15554 function matches(source) {
15555 return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
15559 * Creates a function that performs a partial deep comparison between the
15560 * value at `path` of a given object to `srcValue`, returning `true` if the
15561 * object value is equivalent, else `false`.
15563 * **Note:** Partial comparisons will match empty array and empty object
15564 * `srcValue` values against any array or object value, respectively. See
15565 * `_.isEqual` for a list of supported value comparisons.
15571 * @param {Array|string} path The path of the property to get.
15572 * @param {*} srcValue The value to match.
15573 * @returns {Function} Returns the new spec function.
15577 * { 'a': 1, 'b': 2, 'c': 3 },
15578 * { 'a': 4, 'b': 5, 'c': 6 }
15581 * _.find(objects, _.matchesProperty('a', 4));
15582 * // => { 'a': 4, 'b': 5, 'c': 6 }
15584 function matchesProperty(path, srcValue) {
15585 return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
15589 * Creates a function that invokes the method at `path` of a given object.
15590 * Any additional arguments are provided to the invoked method.
15596 * @param {Array|string} path The path of the method to invoke.
15597 * @param {...*} [args] The arguments to invoke the method with.
15598 * @returns {Function} Returns the new invoker function.
15602 * { 'a': { 'b': _.constant(2) } },
15603 * { 'a': { 'b': _.constant(1) } }
15606 * _.map(objects, _.method('a.b'));
15609 * _.map(objects, _.method(['a', 'b']));
15612 var method = baseRest(function(path, args) {
15613 return function(object) {
15614 return baseInvoke(object, path, args);
15619 * The opposite of `_.method`; this method creates a function that invokes
15620 * the method at a given path of `object`. Any additional arguments are
15621 * provided to the invoked method.
15627 * @param {Object} object The object to query.
15628 * @param {...*} [args] The arguments to invoke the method with.
15629 * @returns {Function} Returns the new invoker function.
15632 * var array = _.times(3, _.constant),
15633 * object = { 'a': array, 'b': array, 'c': array };
15635 * _.map(['a[2]', 'c[0]'], _.methodOf(object));
15638 * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
15641 var methodOf = baseRest(function(object, args) {
15642 return function(path) {
15643 return baseInvoke(object, path, args);
15648 * Adds all own enumerable string keyed function properties of a source
15649 * object to the destination object. If `object` is a function, then methods
15650 * are added to its prototype as well.
15652 * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
15653 * avoid conflicts caused by modifying the original.
15659 * @param {Function|Object} [object=lodash] The destination object.
15660 * @param {Object} source The object of functions to add.
15661 * @param {Object} [options={}] The options object.
15662 * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
15663 * @returns {Function|Object} Returns `object`.
15666 * function vowels(string) {
15667 * return _.filter(string, function(v) {
15668 * return /[aeiou]/i.test(v);
15672 * _.mixin({ 'vowels': vowels });
15673 * _.vowels('fred');
15676 * _('fred').vowels().value();
15679 * _.mixin({ 'vowels': vowels }, { 'chain': false });
15680 * _('fred').vowels();
15683 function mixin(object, source, options) {
15684 var props = keys(source),
15685 methodNames = baseFunctions(source, props);
15687 if (options == null &&
15688 !(isObject(source) && (methodNames.length || !props.length))) {
15692 methodNames = baseFunctions(source, keys(source));
15694 var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
15695 isFunc = isFunction(object);
15697 arrayEach(methodNames, function(methodName) {
15698 var func = source[methodName];
15699 object[methodName] = func;
15701 object.prototype[methodName] = function() {
15702 var chainAll = this.__chain__;
15703 if (chain || chainAll) {
15704 var result = object(this.__wrapped__),
15705 actions = result.__actions__ = copyArray(this.__actions__);
15707 actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
15708 result.__chain__ = chainAll;
15711 return func.apply(object, arrayPush([this.value()], arguments));
15720 * Reverts the `_` variable to its previous value and returns a reference to
15721 * the `lodash` function.
15727 * @returns {Function} Returns the `lodash` function.
15730 * var lodash = _.noConflict();
15732 function noConflict() {
15733 if (root._ === this) {
15740 * This method returns `undefined`.
15748 * _.times(2, _.noop);
15749 * // => [undefined, undefined]
15752 // No operation performed.
15756 * Creates a function that gets the argument at index `n`. If `n` is negative,
15757 * the nth argument from the end is returned.
15763 * @param {number} [n=0] The index of the argument to return.
15764 * @returns {Function} Returns the new pass-thru function.
15767 * var func = _.nthArg(1);
15768 * func('a', 'b', 'c', 'd');
15771 * var func = _.nthArg(-2);
15772 * func('a', 'b', 'c', 'd');
15775 function nthArg(n) {
15777 return baseRest(function(args) {
15778 return baseNth(args, n);
15783 * Creates a function that invokes `iteratees` with the arguments it receives
15784 * and returns their results.
15790 * @param {...(Function|Function[])} [iteratees=[_.identity]]
15791 * The iteratees to invoke.
15792 * @returns {Function} Returns the new function.
15795 * var func = _.over([Math.max, Math.min]);
15797 * func(1, 2, 3, 4);
15800 var over = createOver(arrayMap);
15803 * Creates a function that checks if **all** of the `predicates` return
15804 * truthy when invoked with the arguments it receives.
15810 * @param {...(Function|Function[])} [predicates=[_.identity]]
15811 * The predicates to check.
15812 * @returns {Function} Returns the new function.
15815 * var func = _.overEvery([Boolean, isFinite]);
15826 var overEvery = createOver(arrayEvery);
15829 * Creates a function that checks if **any** of the `predicates` return
15830 * truthy when invoked with the arguments it receives.
15836 * @param {...(Function|Function[])} [predicates=[_.identity]]
15837 * The predicates to check.
15838 * @returns {Function} Returns the new function.
15841 * var func = _.overSome([Boolean, isFinite]);
15852 var overSome = createOver(arraySome);
15855 * Creates a function that returns the value at `path` of a given object.
15861 * @param {Array|string} path The path of the property to get.
15862 * @returns {Function} Returns the new accessor function.
15866 * { 'a': { 'b': 2 } },
15867 * { 'a': { 'b': 1 } }
15870 * _.map(objects, _.property('a.b'));
15873 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
15876 function property(path) {
15877 return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
15881 * The opposite of `_.property`; this method creates a function that returns
15882 * the value at a given path of `object`.
15888 * @param {Object} object The object to query.
15889 * @returns {Function} Returns the new accessor function.
15892 * var array = [0, 1, 2],
15893 * object = { 'a': array, 'b': array, 'c': array };
15895 * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
15898 * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
15901 function propertyOf(object) {
15902 return function(path) {
15903 return object == null ? undefined : baseGet(object, path);
15908 * Creates an array of numbers (positive and/or negative) progressing from
15909 * `start` up to, but not including, `end`. A step of `-1` is used if a negative
15910 * `start` is specified without an `end` or `step`. If `end` is not specified,
15911 * it's set to `start` with `start` then set to `0`.
15913 * **Note:** JavaScript follows the IEEE-754 standard for resolving
15914 * floating-point values which can produce unexpected results.
15920 * @param {number} [start=0] The start of the range.
15921 * @param {number} end The end of the range.
15922 * @param {number} [step=1] The value to increment or decrement by.
15923 * @returns {Array} Returns the range of numbers.
15924 * @see _.inRange, _.rangeRight
15928 * // => [0, 1, 2, 3]
15931 * // => [0, -1, -2, -3]
15934 * // => [1, 2, 3, 4]
15936 * _.range(0, 20, 5);
15937 * // => [0, 5, 10, 15]
15939 * _.range(0, -4, -1);
15940 * // => [0, -1, -2, -3]
15942 * _.range(1, 4, 0);
15948 var range = createRange();
15951 * This method is like `_.range` except that it populates values in
15952 * descending order.
15958 * @param {number} [start=0] The start of the range.
15959 * @param {number} end The end of the range.
15960 * @param {number} [step=1] The value to increment or decrement by.
15961 * @returns {Array} Returns the range of numbers.
15962 * @see _.inRange, _.range
15966 * // => [3, 2, 1, 0]
15968 * _.rangeRight(-4);
15969 * // => [-3, -2, -1, 0]
15971 * _.rangeRight(1, 5);
15972 * // => [4, 3, 2, 1]
15974 * _.rangeRight(0, 20, 5);
15975 * // => [15, 10, 5, 0]
15977 * _.rangeRight(0, -4, -1);
15978 * // => [-3, -2, -1, 0]
15980 * _.rangeRight(1, 4, 0);
15986 var rangeRight = createRange(true);
15989 * This method returns a new empty array.
15995 * @returns {Array} Returns the new empty array.
15998 * var arrays = _.times(2, _.stubArray);
16000 * console.log(arrays);
16003 * console.log(arrays[0] === arrays[1]);
16006 function stubArray() {
16011 * This method returns `false`.
16017 * @returns {boolean} Returns `false`.
16020 * _.times(2, _.stubFalse);
16021 * // => [false, false]
16023 function stubFalse() {
16028 * This method returns a new empty object.
16034 * @returns {Object} Returns the new empty object.
16037 * var objects = _.times(2, _.stubObject);
16039 * console.log(objects);
16042 * console.log(objects[0] === objects[1]);
16045 function stubObject() {
16050 * This method returns an empty string.
16056 * @returns {string} Returns the empty string.
16059 * _.times(2, _.stubString);
16062 function stubString() {
16067 * This method returns `true`.
16073 * @returns {boolean} Returns `true`.
16076 * _.times(2, _.stubTrue);
16077 * // => [true, true]
16079 function stubTrue() {
16084 * Invokes the iteratee `n` times, returning an array of the results of
16085 * each invocation. The iteratee is invoked with one argument; (index).
16091 * @param {number} n The number of times to invoke `iteratee`.
16092 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
16093 * @returns {Array} Returns the array of results.
16096 * _.times(3, String);
16097 * // => ['0', '1', '2']
16099 * _.times(4, _.constant(0));
16100 * // => [0, 0, 0, 0]
16102 function times(n, iteratee) {
16104 if (n < 1 || n > MAX_SAFE_INTEGER) {
16107 var index = MAX_ARRAY_LENGTH,
16108 length = nativeMin(n, MAX_ARRAY_LENGTH);
16110 iteratee = getIteratee(iteratee);
16111 n -= MAX_ARRAY_LENGTH;
16113 var result = baseTimes(length, iteratee);
16114 while (++index < n) {
16121 * Converts `value` to a property path array.
16127 * @param {*} value The value to convert.
16128 * @returns {Array} Returns the new property path array.
16131 * _.toPath('a.b.c');
16132 * // => ['a', 'b', 'c']
16134 * _.toPath('a[0].b.c');
16135 * // => ['a', '0', 'b', 'c']
16137 function toPath(value) {
16138 if (isArray(value)) {
16139 return arrayMap(value, toKey);
16141 return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
16145 * Generates a unique ID. If `prefix` is given, the ID is appended to it.
16151 * @param {string} [prefix=''] The value to prefix the ID with.
16152 * @returns {string} Returns the unique ID.
16155 * _.uniqueId('contact_');
16156 * // => 'contact_104'
16161 function uniqueId(prefix) {
16162 var id = ++idCounter;
16163 return toString(prefix) + id;
16166 /*------------------------------------------------------------------------*/
16169 * Adds two numbers.
16175 * @param {number} augend The first number in an addition.
16176 * @param {number} addend The second number in an addition.
16177 * @returns {number} Returns the total.
16183 var add = createMathOperation(function(augend, addend) {
16184 return augend + addend;
16188 * Computes `number` rounded up to `precision`.
16194 * @param {number} number The number to round up.
16195 * @param {number} [precision=0] The precision to round up to.
16196 * @returns {number} Returns the rounded up number.
16202 * _.ceil(6.004, 2);
16205 * _.ceil(6040, -2);
16208 var ceil = createRound('ceil');
16211 * Divide two numbers.
16217 * @param {number} dividend The first number in a division.
16218 * @param {number} divisor The second number in a division.
16219 * @returns {number} Returns the quotient.
16225 var divide = createMathOperation(function(dividend, divisor) {
16226 return dividend / divisor;
16230 * Computes `number` rounded down to `precision`.
16236 * @param {number} number The number to round down.
16237 * @param {number} [precision=0] The precision to round down to.
16238 * @returns {number} Returns the rounded down number.
16244 * _.floor(0.046, 2);
16247 * _.floor(4060, -2);
16250 var floor = createRound('floor');
16253 * Computes the maximum value of `array`. If `array` is empty or falsey,
16254 * `undefined` is returned.
16260 * @param {Array} array The array to iterate over.
16261 * @returns {*} Returns the maximum value.
16264 * _.max([4, 2, 8, 6]);
16270 function max(array) {
16271 return (array && array.length)
16272 ? baseExtremum(array, identity, baseGt)
16277 * This method is like `_.max` except that it accepts `iteratee` which is
16278 * invoked for each element in `array` to generate the criterion by which
16279 * the value is ranked. The iteratee is invoked with one argument: (value).
16285 * @param {Array} array The array to iterate over.
16286 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16287 * @returns {*} Returns the maximum value.
16290 * var objects = [{ 'n': 1 }, { 'n': 2 }];
16292 * _.maxBy(objects, function(o) { return o.n; });
16295 * // The `_.property` iteratee shorthand.
16296 * _.maxBy(objects, 'n');
16299 function maxBy(array, iteratee) {
16300 return (array && array.length)
16301 ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
16306 * Computes the mean of the values in `array`.
16312 * @param {Array} array The array to iterate over.
16313 * @returns {number} Returns the mean.
16316 * _.mean([4, 2, 8, 6]);
16319 function mean(array) {
16320 return baseMean(array, identity);
16324 * This method is like `_.mean` except that it accepts `iteratee` which is
16325 * invoked for each element in `array` to generate the value to be averaged.
16326 * The iteratee is invoked with one argument: (value).
16332 * @param {Array} array The array to iterate over.
16333 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16334 * @returns {number} Returns the mean.
16337 * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16339 * _.meanBy(objects, function(o) { return o.n; });
16342 * // The `_.property` iteratee shorthand.
16343 * _.meanBy(objects, 'n');
16346 function meanBy(array, iteratee) {
16347 return baseMean(array, getIteratee(iteratee, 2));
16351 * Computes the minimum value of `array`. If `array` is empty or falsey,
16352 * `undefined` is returned.
16358 * @param {Array} array The array to iterate over.
16359 * @returns {*} Returns the minimum value.
16362 * _.min([4, 2, 8, 6]);
16368 function min(array) {
16369 return (array && array.length)
16370 ? baseExtremum(array, identity, baseLt)
16375 * This method is like `_.min` except that it accepts `iteratee` which is
16376 * invoked for each element in `array` to generate the criterion by which
16377 * the value is ranked. The iteratee is invoked with one argument: (value).
16383 * @param {Array} array The array to iterate over.
16384 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16385 * @returns {*} Returns the minimum value.
16388 * var objects = [{ 'n': 1 }, { 'n': 2 }];
16390 * _.minBy(objects, function(o) { return o.n; });
16393 * // The `_.property` iteratee shorthand.
16394 * _.minBy(objects, 'n');
16397 function minBy(array, iteratee) {
16398 return (array && array.length)
16399 ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
16404 * Multiply two numbers.
16410 * @param {number} multiplier The first number in a multiplication.
16411 * @param {number} multiplicand The second number in a multiplication.
16412 * @returns {number} Returns the product.
16415 * _.multiply(6, 4);
16418 var multiply = createMathOperation(function(multiplier, multiplicand) {
16419 return multiplier * multiplicand;
16423 * Computes `number` rounded to `precision`.
16429 * @param {number} number The number to round.
16430 * @param {number} [precision=0] The precision to round to.
16431 * @returns {number} Returns the rounded number.
16437 * _.round(4.006, 2);
16440 * _.round(4060, -2);
16443 var round = createRound('round');
16446 * Subtract two numbers.
16452 * @param {number} minuend The first number in a subtraction.
16453 * @param {number} subtrahend The second number in a subtraction.
16454 * @returns {number} Returns the difference.
16457 * _.subtract(6, 4);
16460 var subtract = createMathOperation(function(minuend, subtrahend) {
16461 return minuend - subtrahend;
16465 * Computes the sum of the values in `array`.
16471 * @param {Array} array The array to iterate over.
16472 * @returns {number} Returns the sum.
16475 * _.sum([4, 2, 8, 6]);
16478 function sum(array) {
16479 return (array && array.length)
16480 ? baseSum(array, identity)
16485 * This method is like `_.sum` except that it accepts `iteratee` which is
16486 * invoked for each element in `array` to generate the value to be summed.
16487 * The iteratee is invoked with one argument: (value).
16493 * @param {Array} array The array to iterate over.
16494 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16495 * @returns {number} Returns the sum.
16498 * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16500 * _.sumBy(objects, function(o) { return o.n; });
16503 * // The `_.property` iteratee shorthand.
16504 * _.sumBy(objects, 'n');
16507 function sumBy(array, iteratee) {
16508 return (array && array.length)
16509 ? baseSum(array, getIteratee(iteratee, 2))
16513 /*------------------------------------------------------------------------*/
16515 // Add methods that return wrapped values in chain sequences.
16516 lodash.after = after;
16518 lodash.assign = assign;
16519 lodash.assignIn = assignIn;
16520 lodash.assignInWith = assignInWith;
16521 lodash.assignWith = assignWith;
16523 lodash.before = before;
16524 lodash.bind = bind;
16525 lodash.bindAll = bindAll;
16526 lodash.bindKey = bindKey;
16527 lodash.castArray = castArray;
16528 lodash.chain = chain;
16529 lodash.chunk = chunk;
16530 lodash.compact = compact;
16531 lodash.concat = concat;
16532 lodash.cond = cond;
16533 lodash.conforms = conforms;
16534 lodash.constant = constant;
16535 lodash.countBy = countBy;
16536 lodash.create = create;
16537 lodash.curry = curry;
16538 lodash.curryRight = curryRight;
16539 lodash.debounce = debounce;
16540 lodash.defaults = defaults;
16541 lodash.defaultsDeep = defaultsDeep;
16542 lodash.defer = defer;
16543 lodash.delay = delay;
16544 lodash.difference = difference;
16545 lodash.differenceBy = differenceBy;
16546 lodash.differenceWith = differenceWith;
16547 lodash.drop = drop;
16548 lodash.dropRight = dropRight;
16549 lodash.dropRightWhile = dropRightWhile;
16550 lodash.dropWhile = dropWhile;
16551 lodash.fill = fill;
16552 lodash.filter = filter;
16553 lodash.flatMap = flatMap;
16554 lodash.flatMapDeep = flatMapDeep;
16555 lodash.flatMapDepth = flatMapDepth;
16556 lodash.flatten = flatten;
16557 lodash.flattenDeep = flattenDeep;
16558 lodash.flattenDepth = flattenDepth;
16559 lodash.flip = flip;
16560 lodash.flow = flow;
16561 lodash.flowRight = flowRight;
16562 lodash.fromPairs = fromPairs;
16563 lodash.functions = functions;
16564 lodash.functionsIn = functionsIn;
16565 lodash.groupBy = groupBy;
16566 lodash.initial = initial;
16567 lodash.intersection = intersection;
16568 lodash.intersectionBy = intersectionBy;
16569 lodash.intersectionWith = intersectionWith;
16570 lodash.invert = invert;
16571 lodash.invertBy = invertBy;
16572 lodash.invokeMap = invokeMap;
16573 lodash.iteratee = iteratee;
16574 lodash.keyBy = keyBy;
16575 lodash.keys = keys;
16576 lodash.keysIn = keysIn;
16578 lodash.mapKeys = mapKeys;
16579 lodash.mapValues = mapValues;
16580 lodash.matches = matches;
16581 lodash.matchesProperty = matchesProperty;
16582 lodash.memoize = memoize;
16583 lodash.merge = merge;
16584 lodash.mergeWith = mergeWith;
16585 lodash.method = method;
16586 lodash.methodOf = methodOf;
16587 lodash.mixin = mixin;
16588 lodash.negate = negate;
16589 lodash.nthArg = nthArg;
16590 lodash.omit = omit;
16591 lodash.omitBy = omitBy;
16592 lodash.once = once;
16593 lodash.orderBy = orderBy;
16594 lodash.over = over;
16595 lodash.overArgs = overArgs;
16596 lodash.overEvery = overEvery;
16597 lodash.overSome = overSome;
16598 lodash.partial = partial;
16599 lodash.partialRight = partialRight;
16600 lodash.partition = partition;
16601 lodash.pick = pick;
16602 lodash.pickBy = pickBy;
16603 lodash.property = property;
16604 lodash.propertyOf = propertyOf;
16605 lodash.pull = pull;
16606 lodash.pullAll = pullAll;
16607 lodash.pullAllBy = pullAllBy;
16608 lodash.pullAllWith = pullAllWith;
16609 lodash.pullAt = pullAt;
16610 lodash.range = range;
16611 lodash.rangeRight = rangeRight;
16612 lodash.rearg = rearg;
16613 lodash.reject = reject;
16614 lodash.remove = remove;
16615 lodash.rest = rest;
16616 lodash.reverse = reverse;
16617 lodash.sampleSize = sampleSize;
16619 lodash.setWith = setWith;
16620 lodash.shuffle = shuffle;
16621 lodash.slice = slice;
16622 lodash.sortBy = sortBy;
16623 lodash.sortedUniq = sortedUniq;
16624 lodash.sortedUniqBy = sortedUniqBy;
16625 lodash.split = split;
16626 lodash.spread = spread;
16627 lodash.tail = tail;
16628 lodash.take = take;
16629 lodash.takeRight = takeRight;
16630 lodash.takeRightWhile = takeRightWhile;
16631 lodash.takeWhile = takeWhile;
16633 lodash.throttle = throttle;
16634 lodash.thru = thru;
16635 lodash.toArray = toArray;
16636 lodash.toPairs = toPairs;
16637 lodash.toPairsIn = toPairsIn;
16638 lodash.toPath = toPath;
16639 lodash.toPlainObject = toPlainObject;
16640 lodash.transform = transform;
16641 lodash.unary = unary;
16642 lodash.union = union;
16643 lodash.unionBy = unionBy;
16644 lodash.unionWith = unionWith;
16645 lodash.uniq = uniq;
16646 lodash.uniqBy = uniqBy;
16647 lodash.uniqWith = uniqWith;
16648 lodash.unset = unset;
16649 lodash.unzip = unzip;
16650 lodash.unzipWith = unzipWith;
16651 lodash.update = update;
16652 lodash.updateWith = updateWith;
16653 lodash.values = values;
16654 lodash.valuesIn = valuesIn;
16655 lodash.without = without;
16656 lodash.words = words;
16657 lodash.wrap = wrap;
16659 lodash.xorBy = xorBy;
16660 lodash.xorWith = xorWith;
16662 lodash.zipObject = zipObject;
16663 lodash.zipObjectDeep = zipObjectDeep;
16664 lodash.zipWith = zipWith;
16667 lodash.entries = toPairs;
16668 lodash.entriesIn = toPairsIn;
16669 lodash.extend = assignIn;
16670 lodash.extendWith = assignInWith;
16672 // Add methods to `lodash.prototype`.
16673 mixin(lodash, lodash);
16675 /*------------------------------------------------------------------------*/
16677 // Add methods that return unwrapped values in chain sequences.
16679 lodash.attempt = attempt;
16680 lodash.camelCase = camelCase;
16681 lodash.capitalize = capitalize;
16682 lodash.ceil = ceil;
16683 lodash.clamp = clamp;
16684 lodash.clone = clone;
16685 lodash.cloneDeep = cloneDeep;
16686 lodash.cloneDeepWith = cloneDeepWith;
16687 lodash.cloneWith = cloneWith;
16688 lodash.conformsTo = conformsTo;
16689 lodash.deburr = deburr;
16690 lodash.defaultTo = defaultTo;
16691 lodash.divide = divide;
16692 lodash.endsWith = endsWith;
16694 lodash.escape = escape;
16695 lodash.escapeRegExp = escapeRegExp;
16696 lodash.every = every;
16697 lodash.find = find;
16698 lodash.findIndex = findIndex;
16699 lodash.findKey = findKey;
16700 lodash.findLast = findLast;
16701 lodash.findLastIndex = findLastIndex;
16702 lodash.findLastKey = findLastKey;
16703 lodash.floor = floor;
16704 lodash.forEach = forEach;
16705 lodash.forEachRight = forEachRight;
16706 lodash.forIn = forIn;
16707 lodash.forInRight = forInRight;
16708 lodash.forOwn = forOwn;
16709 lodash.forOwnRight = forOwnRight;
16714 lodash.hasIn = hasIn;
16715 lodash.head = head;
16716 lodash.identity = identity;
16717 lodash.includes = includes;
16718 lodash.indexOf = indexOf;
16719 lodash.inRange = inRange;
16720 lodash.invoke = invoke;
16721 lodash.isArguments = isArguments;
16722 lodash.isArray = isArray;
16723 lodash.isArrayBuffer = isArrayBuffer;
16724 lodash.isArrayLike = isArrayLike;
16725 lodash.isArrayLikeObject = isArrayLikeObject;
16726 lodash.isBoolean = isBoolean;
16727 lodash.isBuffer = isBuffer;
16728 lodash.isDate = isDate;
16729 lodash.isElement = isElement;
16730 lodash.isEmpty = isEmpty;
16731 lodash.isEqual = isEqual;
16732 lodash.isEqualWith = isEqualWith;
16733 lodash.isError = isError;
16734 lodash.isFinite = isFinite;
16735 lodash.isFunction = isFunction;
16736 lodash.isInteger = isInteger;
16737 lodash.isLength = isLength;
16738 lodash.isMap = isMap;
16739 lodash.isMatch = isMatch;
16740 lodash.isMatchWith = isMatchWith;
16741 lodash.isNaN = isNaN;
16742 lodash.isNative = isNative;
16743 lodash.isNil = isNil;
16744 lodash.isNull = isNull;
16745 lodash.isNumber = isNumber;
16746 lodash.isObject = isObject;
16747 lodash.isObjectLike = isObjectLike;
16748 lodash.isPlainObject = isPlainObject;
16749 lodash.isRegExp = isRegExp;
16750 lodash.isSafeInteger = isSafeInteger;
16751 lodash.isSet = isSet;
16752 lodash.isString = isString;
16753 lodash.isSymbol = isSymbol;
16754 lodash.isTypedArray = isTypedArray;
16755 lodash.isUndefined = isUndefined;
16756 lodash.isWeakMap = isWeakMap;
16757 lodash.isWeakSet = isWeakSet;
16758 lodash.join = join;
16759 lodash.kebabCase = kebabCase;
16760 lodash.last = last;
16761 lodash.lastIndexOf = lastIndexOf;
16762 lodash.lowerCase = lowerCase;
16763 lodash.lowerFirst = lowerFirst;
16767 lodash.maxBy = maxBy;
16768 lodash.mean = mean;
16769 lodash.meanBy = meanBy;
16771 lodash.minBy = minBy;
16772 lodash.stubArray = stubArray;
16773 lodash.stubFalse = stubFalse;
16774 lodash.stubObject = stubObject;
16775 lodash.stubString = stubString;
16776 lodash.stubTrue = stubTrue;
16777 lodash.multiply = multiply;
16779 lodash.noConflict = noConflict;
16780 lodash.noop = noop;
16783 lodash.padEnd = padEnd;
16784 lodash.padStart = padStart;
16785 lodash.parseInt = parseInt;
16786 lodash.random = random;
16787 lodash.reduce = reduce;
16788 lodash.reduceRight = reduceRight;
16789 lodash.repeat = repeat;
16790 lodash.replace = replace;
16791 lodash.result = result;
16792 lodash.round = round;
16793 lodash.runInContext = runInContext;
16794 lodash.sample = sample;
16795 lodash.size = size;
16796 lodash.snakeCase = snakeCase;
16797 lodash.some = some;
16798 lodash.sortedIndex = sortedIndex;
16799 lodash.sortedIndexBy = sortedIndexBy;
16800 lodash.sortedIndexOf = sortedIndexOf;
16801 lodash.sortedLastIndex = sortedLastIndex;
16802 lodash.sortedLastIndexBy = sortedLastIndexBy;
16803 lodash.sortedLastIndexOf = sortedLastIndexOf;
16804 lodash.startCase = startCase;
16805 lodash.startsWith = startsWith;
16806 lodash.subtract = subtract;
16808 lodash.sumBy = sumBy;
16809 lodash.template = template;
16810 lodash.times = times;
16811 lodash.toFinite = toFinite;
16812 lodash.toInteger = toInteger;
16813 lodash.toLength = toLength;
16814 lodash.toLower = toLower;
16815 lodash.toNumber = toNumber;
16816 lodash.toSafeInteger = toSafeInteger;
16817 lodash.toString = toString;
16818 lodash.toUpper = toUpper;
16819 lodash.trim = trim;
16820 lodash.trimEnd = trimEnd;
16821 lodash.trimStart = trimStart;
16822 lodash.truncate = truncate;
16823 lodash.unescape = unescape;
16824 lodash.uniqueId = uniqueId;
16825 lodash.upperCase = upperCase;
16826 lodash.upperFirst = upperFirst;
16829 lodash.each = forEach;
16830 lodash.eachRight = forEachRight;
16831 lodash.first = head;
16833 mixin(lodash, (function() {
16835 baseForOwn(lodash, function(func, methodName) {
16836 if (!hasOwnProperty.call(lodash.prototype, methodName)) {
16837 source[methodName] = func;
16841 }()), { 'chain': false });
16843 /*------------------------------------------------------------------------*/
16846 * The semantic version number.
16852 lodash.VERSION = VERSION;
16854 // Assign default placeholders.
16855 arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
16856 lodash[methodName].placeholder = lodash;
16859 // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
16860 arrayEach(['drop', 'take'], function(methodName, index) {
16861 LazyWrapper.prototype[methodName] = function(n) {
16862 n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
16864 var result = (this.__filtered__ && !index)
16865 ? new LazyWrapper(this)
16868 if (result.__filtered__) {
16869 result.__takeCount__ = nativeMin(n, result.__takeCount__);
16871 result.__views__.push({
16872 'size': nativeMin(n, MAX_ARRAY_LENGTH),
16873 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
16879 LazyWrapper.prototype[methodName + 'Right'] = function(n) {
16880 return this.reverse()[methodName](n).reverse();
16884 // Add `LazyWrapper` methods that accept an `iteratee` value.
16885 arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
16886 var type = index + 1,
16887 isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
16889 LazyWrapper.prototype[methodName] = function(iteratee) {
16890 var result = this.clone();
16891 result.__iteratees__.push({
16892 'iteratee': getIteratee(iteratee, 3),
16895 result.__filtered__ = result.__filtered__ || isFilter;
16900 // Add `LazyWrapper` methods for `_.head` and `_.last`.
16901 arrayEach(['head', 'last'], function(methodName, index) {
16902 var takeName = 'take' + (index ? 'Right' : '');
16904 LazyWrapper.prototype[methodName] = function() {
16905 return this[takeName](1).value()[0];
16909 // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
16910 arrayEach(['initial', 'tail'], function(methodName, index) {
16911 var dropName = 'drop' + (index ? '' : 'Right');
16913 LazyWrapper.prototype[methodName] = function() {
16914 return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
16918 LazyWrapper.prototype.compact = function() {
16919 return this.filter(identity);
16922 LazyWrapper.prototype.find = function(predicate) {
16923 return this.filter(predicate).head();
16926 LazyWrapper.prototype.findLast = function(predicate) {
16927 return this.reverse().find(predicate);
16930 LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
16931 if (typeof path == 'function') {
16932 return new LazyWrapper(this);
16934 return this.map(function(value) {
16935 return baseInvoke(value, path, args);
16939 LazyWrapper.prototype.reject = function(predicate) {
16940 return this.filter(negate(getIteratee(predicate)));
16943 LazyWrapper.prototype.slice = function(start, end) {
16944 start = toInteger(start);
16947 if (result.__filtered__ && (start > 0 || end < 0)) {
16948 return new LazyWrapper(result);
16951 result = result.takeRight(-start);
16952 } else if (start) {
16953 result = result.drop(start);
16955 if (end !== undefined) {
16956 end = toInteger(end);
16957 result = end < 0 ? result.dropRight(-end) : result.take(end - start);
16962 LazyWrapper.prototype.takeRightWhile = function(predicate) {
16963 return this.reverse().takeWhile(predicate).reverse();
16966 LazyWrapper.prototype.toArray = function() {
16967 return this.take(MAX_ARRAY_LENGTH);
16970 // Add `LazyWrapper` methods to `lodash.prototype`.
16971 baseForOwn(LazyWrapper.prototype, function(func, methodName) {
16972 var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
16973 isTaker = /^(?:head|last)$/.test(methodName),
16974 lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
16975 retUnwrapped = isTaker || /^find/.test(methodName);
16980 lodash.prototype[methodName] = function() {
16981 var value = this.__wrapped__,
16982 args = isTaker ? [1] : arguments,
16983 isLazy = value instanceof LazyWrapper,
16984 iteratee = args[0],
16985 useLazy = isLazy || isArray(value);
16987 var interceptor = function(value) {
16988 var result = lodashFunc.apply(lodash, arrayPush([value], args));
16989 return (isTaker && chainAll) ? result[0] : result;
16992 if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
16993 // Avoid lazy use if the iteratee has a "length" value other than `1`.
16994 isLazy = useLazy = false;
16996 var chainAll = this.__chain__,
16997 isHybrid = !!this.__actions__.length,
16998 isUnwrapped = retUnwrapped && !chainAll,
16999 onlyLazy = isLazy && !isHybrid;
17001 if (!retUnwrapped && useLazy) {
17002 value = onlyLazy ? value : new LazyWrapper(this);
17003 var result = func.apply(value, args);
17004 result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
17005 return new LodashWrapper(result, chainAll);
17007 if (isUnwrapped && onlyLazy) {
17008 return func.apply(this, args);
17010 result = this.thru(interceptor);
17011 return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
17015 // Add `Array` methods to `lodash.prototype`.
17016 arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
17017 var func = arrayProto[methodName],
17018 chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
17019 retUnwrapped = /^(?:pop|shift)$/.test(methodName);
17021 lodash.prototype[methodName] = function() {
17022 var args = arguments;
17023 if (retUnwrapped && !this.__chain__) {
17024 var value = this.value();
17025 return func.apply(isArray(value) ? value : [], args);
17027 return this[chainName](function(value) {
17028 return func.apply(isArray(value) ? value : [], args);
17033 // Map minified method names to their real names.
17034 baseForOwn(LazyWrapper.prototype, function(func, methodName) {
17035 var lodashFunc = lodash[methodName];
17037 var key = (lodashFunc.name + ''),
17038 names = realNames[key] || (realNames[key] = []);
17040 names.push({ 'name': methodName, 'func': lodashFunc });
17044 realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
17049 // Add methods to `LazyWrapper`.
17050 LazyWrapper.prototype.clone = lazyClone;
17051 LazyWrapper.prototype.reverse = lazyReverse;
17052 LazyWrapper.prototype.value = lazyValue;
17054 // Add chain sequence methods to the `lodash` wrapper.
17055 lodash.prototype.at = wrapperAt;
17056 lodash.prototype.chain = wrapperChain;
17057 lodash.prototype.commit = wrapperCommit;
17058 lodash.prototype.next = wrapperNext;
17059 lodash.prototype.plant = wrapperPlant;
17060 lodash.prototype.reverse = wrapperReverse;
17061 lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
17063 // Add lazy aliases.
17064 lodash.prototype.first = lodash.prototype.head;
17067 lodash.prototype[symIterator] = wrapperToIterator;
17072 /*--------------------------------------------------------------------------*/
17075 var _ = runInContext();
17077 // Some AMD build optimizers, like r.js, check for condition patterns like:
17078 if (typeof undefined == 'function' && typeof undefined.amd == 'object' && undefined.amd) {
17079 // Expose Lodash on the global object to prevent errors when Lodash is
17080 // loaded by a script tag in the presence of an AMD loader.
17081 // See http://requirejs.org/docs/errors.html#mismatch for more details.
17082 // Use `_.noConflict` to remove Lodash from the global object.
17085 // Define as an anonymous module so, through path mapping, it can be
17086 // referenced as the "underscore" module.
17087 undefined(function() {
17091 // Check for `exports` after `define` in case a build optimizer adds it.
17092 else if (freeModule) {
17093 // Export for Node.js.
17094 (freeModule.exports = _)._ = _;
17095 // Export for CommonJS support.
17099 // Export to the global object.
17102 }.call(commonjsGlobal));
17107 var lodash$1 = Object.freeze({
17109 __moduleExports: lodash
17112 function osmIsInterestingTag(key) {
17113 return key !== 'attribution' &&
17114 key !== 'created_by' &&
17115 key !== 'source' &&
17117 key.indexOf('tiger:') !== 0;
17122 var osmOneWayTags = {
17124 'chair_lift': true,
17125 'mixed_lift': true,
17130 'magic_carpet': true,
17135 'motorway_link': true
17141 'piste:halfpipe': true
17158 var osmPavedTags = {
17169 var dataWikipedia = [
17286 "беларуская (тарашкевіца)",
17287 "беларуская (тарашкевіца)",
17327 "বিষ্ণুপ্রিয়া মণিপুরী",
17356 "Chavacano de Zamboanga",
17357 "Chavacano de Zamboanga",
17361 "Min Dong Chinese",
17402 "Nēhiyawēwin / ᓀᐦᐃᔭᐍᐏᐣ",
17422 "словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ",
17476 "Emiliano-Romagnolo",
17477 "emiliàn e rumagnòl",
17532 "Na Vosa Vakaviti",
17551 "Northern Frisian",
17602 "गोंयची कोंकणी / Gõychi Konknni",
17682 "Bahasa Indonesia",
17722 "ᐃᓄᒃᑎᑐᑦ/inuktitut",
17731 "Jamaican Creole English",
17807 "къарачай-малкъар",
17947 "Baso Minangkabau",
18046 "Norwegian Nynorsk",
18067 "Sesotho sa Leboa",
18131 "Pennsylvania German",
18146 "Norfuk / Pitkern",
18147 "Norfuk / Pitkern",
18272 "srpskohrvatski / српскохрватски",
18336 "Saterland Frisian",
18462 "ئۇيغۇرچە / Uyghurche",
18477 "oʻzbekcha/ўзбекча",
18571 "Classical Chinese",
18576 "Chinese (Min Nan)",
18592 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}}};
18593 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}}};
18594 var dataSuggestions = {
18599 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"]]},{"countryCodes":["ua"],"format":[["housenumber","postcode"],["street"]]},{"countryCodes":["cn"],"format":[["postcode","province"],["city"],["district"],["street","housenumber"]]}];
18601 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"}}];
18603 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"];
18605 var dataLocales = {"af":{"rtl":false},"ar":{"rtl":true},"ar-AA":{"rtl":true},"ast":{"rtl":false},"bg":{"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},"gan":{"rtl":false},"gl":{"rtl":false},"gu":{"rtl":false},"he":{"rtl":true},"hi":{"rtl":false},"hr":{"rtl":false},"hu":{"rtl":false},"hy":{"rtl":false},"ia":{"rtl":false},"id":{"rtl":false},"is":{"rtl":false},"it":{"rtl":false},"ja":{"rtl":false},"jv":{"rtl":false},"km":{"rtl":false},"kn":{"rtl":false},"ko":{"rtl":false},"ku":{"rtl":true},"lij":{"rtl":false},"lt":{"rtl":false},"lv":{"rtl":false},"mg":{"rtl":false},"mk":{"rtl":false},"ml":{"rtl":false},"mn":{"rtl":false},"ms":{"rtl":false},"ne":{"rtl":false},"nl":{"rtl":false},"nn":{"rtl":false},"no":{"rtl":false},"nv":{"rtl":false},"pl":{"rtl":false},"pt":{"rtl":false},"pt-BR":{"rtl":false},"rm":{"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},"ur":{"rtl":true},"vi":{"rtl":false},"yue":{"rtl":false},"zh":{"rtl":false},"zh-CN":{"rtl":false},"zh-HK":{"rtl":false},"zh-TW":{"rtl":false}};
18607 var dataPhoneFormats = {"us":"+1-202-555-1234","ca":"+1-226-555-1234","bs":"+1-242-555-1234","bb":"+1-246-555-1234","ai":"+1-264-555-1234","ag":"+1-268-555-1234","vg":"+1-284-555-1234","vi":"+1-340-555-1234","ky":"+1-345-555-1234","bm":"+1-441-555-1234","gd":"+1-473-555-1234","tc":"+1-649-555-1234","ms":"+1-664-555-1234","mp":"+1-670-555-1234","gu":"+1-671-555-1234","as":"+1-684-555-1234","sx":"+1-721-555-1234","lc":"+1-758-555-1234","dm":"+1-767-555-1234","vc":"+1-784-555-1234","pr":"+1-787-555-1234","do":"+1-809-555-1234","tt":"+1-868-555-1234","kn":"+1-869-555-1234","jm":"+1-876-555-1234","za":"+27 11 907 1111","nl":"+31 42 123 4567","fr":"+33 1 23 45 67 89","es":"+34 989 12 34 56","pt":"+351 211 123456","ie":"+353 20 912 3456","fi":"+358 40 123 4567","hu":"+36 1 123 45 67","hr":"+385 01 123 4567","si":"+386 31 123 4567","it":"+39 01 123 456","va":"+39 01 123 456","gb":"+44 1632 961234","gg":"+44 1632 961234","im":"+44 1632 961234","je":"+44 1632 961234","se":"+46 31 123 4567","no":"+47 22 12 34 56","sj":"+47 22 12 34 56","pl":"+48 42 123 4567","de":"+49 89 1234567","br":"+55 11 0982 1098","ru":"+7 495 1234567","kz":"+7 495 1234567","vn":"+84 1 234 5678","hk":"+852 1234 5678","cn":"+86 10 12345678","tw":"+886 1 2345 6789","tr":"+90 312 123 4567","ua":"+380 44 123 4567"};
18609 var dataShortcuts = [{"tab":"browsing","text":"shortcuts.browsing.title","columns":[{"rows":[{"section":"navigation","text":"shortcuts.browsing.navigation.title"},{"shortcuts":["↓","↑","←","→"],"text":"shortcuts.browsing.navigation.pan","separator":","},{"modifiers":["⌘"],"shortcuts":["↓","↑","←","→"],"text":"shortcuts.browsing.navigation.pan_more","separator":","},{"shortcuts":["+","-"],"text":"shortcuts.browsing.navigation.zoom","separator":","},{"modifiers":["⌘"],"shortcuts":["+","-"],"text":"shortcuts.browsing.navigation.zoom_more","separator":","},{"section":"help","text":"shortcuts.browsing.help.title"},{"shortcuts":["help.key"],"text":"shortcuts.browsing.help.help"},{"shortcuts":["shortcuts.toggle.key"],"text":"shortcuts.browsing.help.keyboard"},{"section":"display_options","text":"shortcuts.browsing.display_options.title"},{"shortcuts":["background.key"],"text":"shortcuts.browsing.display_options.background"},{"modifiers":["⌘"],"shortcuts":["background.key"],"text":"shortcuts.browsing.display_options.background_switch"},{"shortcuts":["map_data.key"],"text":"shortcuts.browsing.display_options.map_data"},{"modifiers":["⌃","⌘"],"shortcuts":["F","F11"],"text":"shortcuts.browsing.display_options.fullscreen"},{"shortcuts":["area_fill.wireframe.key"],"text":"shortcuts.browsing.display_options.wireframe"},{"shortcuts":["background.minimap.key"],"text":"shortcuts.browsing.display_options.minimap"}]},{"rows":[{"section":"selecting","text":"shortcuts.browsing.selecting.title"},{"shortcuts":["Left-click"],"text":"shortcuts.browsing.selecting.select_one"},{"modifiers":["⇧"],"shortcuts":["Left-click"],"text":"shortcuts.browsing.selecting.select_multi"},{"modifiers":["⇧"],"shortcuts":["Left-click"],"gesture":"shortcuts.gesture.drag","text":"shortcuts.browsing.selecting.lasso"},{"shortcuts":[],"text":""},{"section":"with_selected","text":"shortcuts.browsing.with_selected.title"},{"shortcuts":["Right-click","shortcuts.key.space"],"text":"shortcuts.browsing.with_selected.edit_menu"},{"shortcuts":[],"text":""},{"section":"vertex_selected","text":"shortcuts.browsing.vertex_selected.title"},{"shortcuts":["[","↖"],"text":"shortcuts.browsing.vertex_selected.previous"},{"shortcuts":["]","↘"],"text":"shortcuts.browsing.vertex_selected.next"},{"shortcuts":["{","⇞"],"text":"shortcuts.browsing.vertex_selected.first"},{"shortcuts":["}","⇟"],"text":"shortcuts.browsing.vertex_selected.last"},{"shortcuts":["\\","shortcuts.key.pause"],"text":"shortcuts.browsing.vertex_selected.change_parent"}]}]},{"tab":"editing","text":"shortcuts.editing.title","columns":[{"rows":[{"section":"drawing","text":"shortcuts.editing.drawing.title"},{"shortcuts":["1"],"text":"shortcuts.editing.drawing.add_point"},{"shortcuts":["2"],"text":"shortcuts.editing.drawing.add_line"},{"shortcuts":["3"],"text":"shortcuts.editing.drawing.add_area"},{"shortcuts":["Left-click","shortcuts.key.space"],"text":"shortcuts.editing.drawing.place_point"},{"shortcuts":["⌥"],"text":"shortcuts.editing.drawing.disable_snap"},{"shortcuts":["↵","⎋"],"text":"shortcuts.editing.drawing.stop_line"},{"section":"commands","text":"shortcuts.editing.commands.title"},{"modifiers":["⌘"],"shortcuts":["C"],"text":"shortcuts.editing.commands.copy"},{"modifiers":["⌘"],"shortcuts":["V"],"text":"shortcuts.editing.commands.paste"},{"modifiers":["⌘"],"shortcuts":["Z"],"text":"shortcuts.editing.commands.undo"},{"modifiers":["⌘","⇧"],"shortcuts":["Z"],"text":"shortcuts.editing.commands.redo"},{"modifiers":["⌘"],"shortcuts":["S"],"text":"shortcuts.editing.commands.save"}]},{"rows":[{"section":"operations","text":"shortcuts.editing.operations.title"},{"shortcuts":["operations.continue.key"],"text":"shortcuts.editing.operations.continue_line"},{"shortcuts":["operations.merge.key"],"text":"shortcuts.editing.operations.merge"},{"shortcuts":["operations.disconnect.key"],"text":"shortcuts.editing.operations.disconnect"},{"shortcuts":["operations.split.key"],"text":"shortcuts.editing.operations.split"},{"shortcuts":["operations.reverse.key"],"text":"shortcuts.editing.operations.reverse"},{"shortcuts":["operations.move.key"],"text":"shortcuts.editing.operations.move"},{"shortcuts":["operations.rotate.key"],"text":"shortcuts.editing.operations.rotate"},{"shortcuts":["operations.orthogonalize.key"],"text":"shortcuts.editing.operations.orthogonalize"},{"shortcuts":["operations.circularize.key"],"text":"shortcuts.editing.operations.circularize"},{"shortcuts":["operations.reflect.key.long"],"text":"shortcuts.editing.operations.reflect_long"},{"shortcuts":["operations.reflect.key.short"],"text":"shortcuts.editing.operations.reflect_short"},{"modifiers":["⌘"],"shortcuts":["⌫"],"text":"shortcuts.editing.operations.delete"}]}]},{"tab":"tools","text":"shortcuts.tools.title","columns":[{"rows":[{"section":"info","text":"shortcuts.tools.info.title"},{"modifiers":["⌘"],"shortcuts":["info_panels.key"],"text":"shortcuts.tools.info.all"},{"modifiers":["⌘","⇧"],"shortcuts":["info_panels.background.key"],"text":"shortcuts.tools.info.background"},{"modifiers":["⌘","⇧"],"shortcuts":["info_panels.history.key"],"text":"shortcuts.tools.info.history"},{"modifiers":["⌘","⇧"],"shortcuts":["info_panels.location.key"],"text":"shortcuts.tools.info.location"},{"modifiers":["⌘","⇧"],"shortcuts":["info_panels.measurement.key"],"text":"shortcuts.tools.info.measurement"}]}]}];
18611 var type = "FeatureCollection";
18612 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]]]}}];
18613 var dataImperial = {
18618 var type$1 = "FeatureCollection";
18619 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]]]}}];
18620 var dataDriveLeft = {
18622 features: features$1
18625 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."},"too_large":{"single":"This feature can't be deleted because not enough of it is currently visible.","multiple":"These features can't be deleted because not enough of them are currently visible."},"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 their endpoints 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":{"long":"Reflect Long","short":"Reflect Short"},"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 a feature across its long axis.","multiple":"Reflected multiple features across their long axis."},"short":{"single":"Reflected a 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"},"info_panels":{"key":"I","background":{"key":"B","title":"Background","zoom":"Zoom","vintage":"Vintage","unknown":"Unknown","show_tiles":"Show Tiles","hide_tiles":"Hide Tiles"},"history":{"key":"H","title":"History","selected":"{n} selected","version":"Version","last_edit":"Last Edit","edited_by":"Edited By","changeset":"Changeset","unknown":"Unknown","link_text":"History on openstreetmap.org"},"location":{"key":"L","title":"Location","unknown_location":"Unknown Location"},"measurement":{"key":"M","title":"Measurement","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","reverser":"Change Direction"},"radio":{"structure":{"type":"Type","default":"Default","layer":"Layer"}},"add":"Add","none":"None","node":"Node","way":"Way","relation":"Relation","location":"Location","add_fields":"Add field:"},"background":{"title":"Background","description":"Background settings","key":"B","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:\n - {zoom}/{z}, {x}, {y} for Z/X/Y tile scheme\n - {ty} for flipped TMS-style Y coordinates\n - {u} for quadtile scheme\n - {switch:a,b,c} for DNS server multiplexing\n\nExample:\n{example}","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.","key":"/"}},"map_data":{"title":"Map Data","description":"Map Data","key":"F","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.","key":"W"},"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 my changes","reset":"Discard my changes"},"save":{"title":"Save","help":"Review your changes and upload them to OpenStreetMap, making them visible to other users.","no_changes":"No changes to save.","error":"Errors occurred while trying to save","status_code":"Server returned status code {code}","unknown_error_details":"Please ensure you are connected to the internet.","uploading":"Uploading changes to OpenStreetMap...","unsaved_changes":"You have unsaved changes","conflict":{"header":"Resolve conflicting edits","count":"Conflict {num} of {total}","previous":"< Previous","next":"Next >","keep_local":"Keep mine","keep_remote":"Use theirs","restore":"Restore","delete":"Leave Deleted","download_changes":"Or download your changes.","done":"All conflicts resolved!","help":"Another user changed some of the same map features you changed.\nClick on each feature below for more details about the conflict, and choose whether to keep\nyour changes or the other user's changes.\n"}},"merge_remote_changes":{"conflict":{"deleted":"This feature has been deleted by {user}.","location":"This feature was moved by both you and {user}.","nodelist":"Nodes were changed by both you and {user}.","memberlist":"Relation members were changed by both you and {user}.","tags":"You changed the <b>{tag}</b> tag to \"{local}\" and {user} changed it to \"{remote}\"."}},"success":{"edited_osm":"Edited OSM!","just_edited":"You just edited OpenStreetMap!","view_on_osm":"View on OSM","facebook":"Share on Facebook","twitter":"Share on Twitter","google":"Share on Google+","help_html":"Your changes should appear in the \"Standard\" layer in a few minutes. Other layers, and certain features, may take longer.","help_link_text":"Details","help_link_url":"https://wiki.openstreetmap.org/wiki/FAQ#I_have_just_made_some_changes_to_the_map._How_do_I_get_to_see_my_changes.3F"},"confirm":{"okay":"OK","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"},"version":{"whats_new":"What's new in iD {version}"},"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 or building entrances.","old_multipolygon":"Multipolygon tags on outer way","old_multipolygon_tooltip":"This style of multipolygon is deprecated. Please assign the tags to the parent multipolygon instead of the outer way.","untagged_point":"Untagged point","untagged_point_tooltip":"Select a feature type that describes what this point is.","untagged_line":"Untagged line","untagged_line_tooltip":"Select a feature type that describes what this line is.","untagged_area":"Untagged area","untagged_area_tooltip":"Select a feature type that describes what this area is.","untagged_relation":"Untagged relation","untagged_relation_tooltip":"Select a feature type that describes what this relation is.","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","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","key":"H","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\nYou can view a list of keyboard shortcuts by pressing the `?` key.\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","ok":"OK","graph":{"block_number":"<value for addr:block_number>","city":"Three Rivers","county":"<value for addr:county>","district":"<value for addr:district>","hamlet":"<value for addr:hamlet>","neighbourhood":"<value for addr:neighbourhood>","postcode":"49093","province":"<value for addr:province>","quarter":"<value for addr:quarter>","state":"MI","subdistrict":"<value for addr:subdistrict>","suburb":"<value for addr:suburb>","countrycode":"us","name":{"1st-avenue":"1st Avenue","2nd-avenue":"2nd Avenue","4th-avenue":"4th Avenue","5th-avenue":"5th Avenue","6th-avenue":"6th Avenue","6th-street":"6th Street","7th-avenue":"7th Avenue","8th-avenue":"8th Avenue","9th-avenue":"9th Avenue","10th-avenue":"10th Avenue","11th-avenue":"11th Avenue","12th-avenue":"12th Avenue","access-point-employment":"Access Point Employment","adams-street":"Adams Street","andrews-elementary-school":"Andrews Elementary School","andrews-street":"Andrews Street","armitage-street":"Armitage Street","barrows-school":"Barrows School","battle-street":"Battle Street","bennett-street":"Bennett Street","bowman-park":"Bowman Park","collins-drive":"Collins Drive","conrail-railroad":"Conrail Railroad","conservation-park":"Conservation Park","constantine-street":"Constantine Street","cushman-street":"Cushman Street","dollar-tree":"Dollar Tree","douglas-avenue":"Douglas Avenue","east-street":"East Street","elm-street":"Elm Street","flower-street":"Flower Street","foster-street":"Foster Street","french-street":"French Street","garden-street":"Garden Street","gem-pawnbroker":"Gem Pawnbroker","golden-finch-framing":"Golden Finch Framing","grant-avenue":"Grant Avenue","hoffman-pond":"Hoffman Pond","hoffman-street":"Hoffman Street","hook-avenue":"Hook Avenue","jefferson-street":"Jefferson Street","kelsey-street":"Kelsey Street","lafayette-park":"LaFayette Park","las-coffee-cafe":"L.A.'s Coffee Cafe","lincoln-avenue":"Lincoln Avenue","lowrys-books":"Lowry's Books","lynns-garage":"Lynn's Garage","main-street-barbell":"Main Street Barbell","main-street-cafe":"Main Street Cafe","main-street-fitness":"Main Street Fitness","main-street":"Main Street","maple-street":"Maple Street","marina-park":"Marina Park","market-street":"Market Street","memory-isle-park":"Memory Isle Park","memory-isle":"Memory Isle","michigan-avenue":"Michigan Avenue","middle-street":"Middle Street","millard-street":"Millard Street","moore-street":"Moore Street","morris-avenue":"Morris Avenue","mural-mall":"Mural Mall","paisanos-bar-and-grill":"Paisano's Bar and Grill","paisley-emporium":"Paisley Emporium","paparazzi-tattoo":"Paparazzi Tattoo","pealer-street":"Pealer Street","pine-street":"Pine Street","pizza-hut":"Pizza Hut","portage-avenue":"Portage Avenue","portage-river":"Portage River","preferred-insurance-services":"Preferred Insurance Services","railroad-drive":"Railroad Drive","river-city-appliance":"River City Appliance","river-drive":"River Drive","river-road":"River Road","river-street":"River Street","riverside-cemetery":"Riverside Cemetery","riverwalk-trail":"Riverwalk Trail","riviera-theatre":"Riviera Theatre","rocky-river":"Rocky River","saint-joseph-river":"Saint Joseph River","scidmore-park-petting-zoo":"Scidmore Park Petting Zoo","scidmore-park":"Scidmore Park","scouter-park":"Scouter Park","sherwin-williams":"Sherwin-Williams","south-street":"South Street","southern-michigan-bank":"Southern Michigan Bank","spring-street":"Spring Street","sturgeon-river-road":"Sturgeon River Road","three-rivers-city-hall":"Three Rivers City Hall","three-rivers-elementary-school":"Three Rivers Elementary School","three-rivers-fire-department":"Three Rivers Fire Department","three-rivers-high-school":"Three Rivers High School","three-rivers-middle-school":"Three Rivers Middle School","three-rivers-municipal-airport":"Three Rivers Municipal Airport","three-rivers-post-office":"Three Rivers Post Office","three-rivers-public-library":"Three Rivers Public Library","three-rivers":"Three Rivers","unique-jewelry":"Unique Jewelry","walnut-street":"Walnut Street","washington-street":"Washington Street","water-street":"Water Street","west-street":"West Street","wheeler-street":"Wheeler Street","william-towing":"William Towing","willow-drive":"Willow Drive","wood-street":"Wood Street","world-fare":"World Fare"}},"welcome":{"title":"Welcome","welcome":"Welcome! This walkthrough will teach you the basics of editing on OpenStreetMap.","practice":"All of the data in this walkthrough is just for practicing, and any edits that you make in the walkthrough will not be saved.","words":"This walkthrough will introduce some new words and concepts. When we introduce a new word, we'll use *italics*.","mouse":"You can use any input device to edit the map, but this walkthrough assumes you have a mouse with left and right buttons. **If you want to attach a mouse, do so now, then click OK.**","leftclick":"When this tutorial asks you to click or double-click, we mean with the left button. On a trackpad it might be a single-click or single-finger tap. **Left-click {num} times.**","rightclick":"Sometimes we'll also ask you to right-click. This might be the same as control-click, or two-finger tap on a trackpad. Your keyboard might even have a 'menu' key that works like right-click. **Right-click {num} times.**","chapters":"So far, so good! You can use the buttons below to skip chapters at any time or to restart a chapter if you get stuck. Let's begin! **Click '{next}' to continue.**"},"navigation":{"title":"Navigation","drag":"The main map area shows OpenStreetMap data on top of a background.{br}You can drag the map by pressing and holding the left mouse button while moving the mouse around. You can also use the arrow keys on your keyboard. **Drag the map!**","zoom":"You can zoom in or out by scrolling with the mouse wheel or trackpad, or by clicking the {plus} / {minus} buttons. **Zoom the map!**","features":"We use the word *features* to describe the things that appear on the map. Anything in the real world can be mapped as a feature on OpenStreetMap.","points_lines_areas":"Map features are represented using *points, lines, or areas.*","nodes_ways":"In OpenStreetMap, points are sometimes called *nodes*, and lines and areas are sometimes called *ways*.","click_townhall":"All features on the map can be selected by clicking on them. **Click on the point to select it.**","selected_townhall":"Great! The point is now selected. Selected features are drawn with a pulsing glow.","editor_townhall":"When a feature is selected, the *feature editor* is displayed alongside the map.","preset_townhall":"The top part of the feature editor shows the feature's type. This point is a {preset}.","fields_townhall":"The middle part of the feature editor contains *fields* showing the feature's attributes, such as its name and address.","close_townhall":"**Close the feature editor by hitting escape or pressing the {button} button in the upper corner.**","search_street":"You can also search for features in the current view, or worldwide. **Search for '{name}'.**","choose_street":"**Choose {name} from the list to select it.**","selected_street":"Great! {name} is now selected.","editor_street":"The fields shown for a street are different than the fields that were shown for the town hall.{br}For this selected street, the feature editor shows fields like '{field1}' and '{field2}'. **Close the feature editor by hitting escape or pressing the {button} button.**","play":"Try moving the map and clicking on some other features to see what kinds of things can be added to OpenStreetMap. **When you are ready to continue to the next chapter, click '{next}'.**"},"points":{"title":"Points","add_point":"*Points* can be used to represent features such as shops, restaurants, and monuments.{br}They mark a specific location, and describe what's there. **Click the {button} Point button to add a new point.**","place_point":"To place the new point on the map, position your mouse cursor where the point should go, then left-click or press the spacebar. **Move the mouse pointer over this building, then left-click or press the spacebar.**","search_cafe":"There are many different features that can be represented by points. The point you just added is a cafe. **Search for '{preset}'.**","choose_cafe":"**Choose {preset} from the list.**","feature_editor":"The point is now marked as a cafe. Using the feature editor, we can add more information about the cafe.","add_name":"In OpenStreetMap, all of the fields are optional, and it's OK to leave a field blank if you are unsure.{br}Let's pretend that you have local knowledge of this cafe, and you know its name. **Add a name for the cafe.**","add_close":"The feature editor will remember all of your changes automatically. **When you are finished adding the name, hit escape, enter, or 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 cafe you just created.**","update":"Let's fill in some more details for this cafe. You can change its name, add a cuisine, or add an address. **Change the cafe details.**","update_close":"**When you are finished updating the cafe, hit escape, enter, or click the {button} button to close the feature editor.**","rightclick":"You can right-click on any feature to see the *edit menu*, which shows a list of editing operations that can be performed. **Right-click to select the point you created and show the edit menu.**","delete":"It's OK to delete features that don't exist in the real world.{br}Deleting a feature from OpenStreetMap removes it from the map that everyone uses, so you should make sure a feature is really gone before you delete it. **Click on the {button} button to delete the point.**","undo":"You can always undo any changes up until you save your edits to OpenStreetMap. **Click on the {button} button to undo the delete and get the point back.**","play":"Now that you know how to create and edit points, try creating a few more points for practice! **When you are ready to continue to the next chapter, click '{next}'.**"},"areas":{"title":"Areas","add_playground":"*Areas* are used to show the boundaries of features like lakes, buildings, and residential areas.{br}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.**","start_playground":"Let's add this playground to the map by drawing an area. Areas are drawn by placing *nodes* along the outer edge of the feature. **Click or press spacebar to place a starting node on one of the corners of the playground.**","continue_playground":"Continue drawing the area by placing more nodes along the playground's edge. It is OK to connect the area to the existing walking paths.{br}Tip: You can hold down the '{alt}' key to prevent nodes from connecting to other features. **Continue drawing an area for the playground.**","finish_playground":"Finish the area by pressing enter, or clicking again on either the first or last node. **Finish drawing an area for the playground.**","search_playground":"**Search for '{preset}'.**","choose_playground":"**Choose {preset} from the list.**","add_field":"This playground doesn't have an official name, so we won't add anything in the Name field.{br}Instead let's add some additional details about the playground to the Description field. **Open the Add Field list.**","choose_field":"**Choose {field} from the list.**","retry_add_field":"You didn't select the {field} field. Let's try again.","describe_playground":"**Add a description, then click the {button} button to close the feature editor.**","play":"Good job! Try drawing a few more areas, and see what other kinds of area features you can add to OpenStreetMap. **When you are ready to continue to the next chapter, click '{next}'.**"},"lines":{"title":"Lines","add_line":"*Lines* are used to represent features such as roads, railroads, and rivers. **Click the {button} Line button to add a new line.**","start_line":"Here is a road that is missing. Let's add it!{br}In OpenStreetMap, lines should be drawn down the center of the road. You can drag and zoom the map while drawing if necessary. **Start a new line by clicking at the top end of this missing road.**","intersect":"Click or press spacebar to add more nodes to the line.{br}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.**","retry_intersect":"The road needs to intersect {name}. Let's try again!","continue_line":"Continue drawing the line for the new road. Remember that you can drag and zoom the map if needed.{br}When you are finished drawing, click on the last node again. **Finish drawing the road.**","choose_category_road":"**Select {category} from the list.**","choose_preset_residential":"There are many different types of roads, but this one is a residential road. **Choose the {preset} type.**","retry_preset_residential":"You didn't select the {preset} type. **Click here to choose again.**","name_road":"**Give this road a name, then hit escape, enter, or click the {button} button to close the feature editor.**","did_name_road":"Looks good! Next we will learn how to update the shape of a line.","update_line":"Sometimes you will need to change the shape of an existing line. Here is a road that doesn't look quite right.","add_node":"We can add some nodes to this line to improve its shape. One way to add a node is to double-click the line where you want to add a node. **Double-click on the line to create a new node.**","start_drag_endpoint":"When a line is selected, you can drag any of its nodes by clicking and holding down the left mouse button while you drag. **Drag the endpoint to the place where these roads should intersect.**","finish_drag_endpoint":"This spot looks good. **Release the left mouse button to finish dragging.**","start_drag_midpoint":"Small triangles are drawn at the *midpoints* between nodes. Another way to create a new node is to drag a midpoint to a new location. **Drag the midpoint triangle to create a new node along the curve of the road.**","continue_drag_midpoint":"This line is looking much better! Continue to adjust this line by double-clicking or dragging midpoints until the curve matches the road shape. **When you're happy with how the line looks, click OK.**","delete_lines":"It's OK to delete lines for roads that don't exist in the real world.{br}Here's an example where the city planned a {street} but never built it. We can improve this part of the map by deleting the extra lines.","rightclick_intersection":"The last real street is {street1}, so we will *split* {street2} at this intersection and remove everything above it. **Right click on the intersection node.**","split_intersection":"**Click on the {button} button to split {street}.**","retry_split":"You didn't click the Split button. Try again.","did_split_multi":"Good job! {street1} is now split into two pieces. The top part can be removed. **Click the top part of {street2} to select it.**","did_split_single":"**Click the top part of {street2} to select it.**","multi_select":"{selected} is now selected. Let's also select {other1}. You can shift-click to select multiple things. **Shift-click on {other2}.**","multi_rightclick":"Good! Both lines to delete are now selected. **Right-click on one of the lines to show the edit menu.**","multi_delete":"**Click on the {button} button to delete the extra lines.**","retry_delete":"You didn't click the Delete button. Try again.","play":"Great! Use the skills that you've learned in this chapter to practice editing some more lines. **When you are ready to continue to the next chapter, click '{next}'.**"},"buildings":{"title":"Buildings","add_building":"OpenStreetMap is the world's largest database of buildings.{br}You can help improve this database by tracing buildings that aren't already mapped. **Click the {button} Area button to add a new area.**","start_building":"Let's add this house to the map by tracing its outline.{br}Buildings should be traced around their footprint as accurately as possible. **Click or press spacebar to place a starting node on one of the corners of the building.**","continue_building":"Continue adding more nodes to trace the outline of the building. Remember that you can zoom in if you want to add more details.{br}Finish the building by pressing enter, or clicking again on either the first or last node. **Finish tracing the building.**","retry_building":"It looks like you had some trouble placing the nodes at the building corners. Try again!","choose_category_building":"**Choose {category} from the list.**","choose_preset_house":"There are many different types of buildings, but this one is clearly a house.{br}If you're not sure of the type, it's OK to just choose the generic Building type. **Choose the {preset} type.**","close":"**Hit escape or click the {button} button to close the feature editor.**","rightclick_building":"**Right-click to select the building you created and show the edit menu.**","square_building":"The house that you just added will look even better with perfectly square corners. **Click on the {button} button to square the building shape.**","retry_square":"You didn't click the Square button. Try again.","done_square":"See how the corners of the building moved into place? Let's learn another useful trick.","add_tank":"Next we'll trace this circular storage tank. **Click the {button} Area button to add a new area.**","start_tank":"Don't worry, you won't need to draw a perfect circle. Just draw an area inside the tank that touches its edge. **Click or press spacebar to place a starting node on the edge of the tank.**","continue_tank":"Add a few more nodes around the edge. The circle will be created outside the nodes that you draw.{br}Finish the area by pressing enter, or clicking again on either the first or last node. **Finish tracing the tank.**","search_tank":"**Search for '{preset}'.**","choose_tank":"**Choose {preset} from the list.**","rightclick_tank":"**Right-click to select the storage tank you created and show the edit menu.**","circle_tank":"**Click on the {button} button to make the tank a circle.**","retry_circle":"You didn't click the Circularize button. Try again.","play":"Great Job! Practice tracing a few more buildings, and try some of the other commands on the edit menu. **When you are ready to continue to the next chapter, click '{next}'.**"},"startediting":{"title":"Start Editing","help":"You're now ready to edit OpenStreetMap!{br}You can replay this walkthrough anytime or view more documentation by clicking the {button} Help button or pressing the '{key}' key.","shortcuts":"You can view a list of commands along with their keyboard shortcuts by pressing the '{key}' key.","save":"Don't forget to regularly save your changes!","start":"Start mapping!"}},"shortcuts":{"title":"Keyboard shortcuts","tooltip":"Show the keyboard shortcuts screen.","toggle":{"key":"?"},"key":{"alt":"Alt","backspace":"Backspace","cmd":"Cmd","ctrl":"Ctrl","delete":"Delete","del":"Del","end":"End","enter":"Enter","esc":"Esc","home":"Home","option":"Option","pause":"Pause","pgdn":"PgDn","pgup":"PgUp","return":"Return","shift":"Shift","space":"Space"},"gesture":{"drag":"drag"},"or":"-or-","browsing":{"title":"Browsing","navigation":{"title":"Navigation","pan":"Pan map","pan_more":"Pan map by one screenful","zoom":"Zoom in / Zoom out","zoom_more":"Zoom in / Zoom out by a lot"},"help":{"title":"Help","help":"Show help/documentation","keyboard":"Show keyboard shortcuts"},"display_options":{"title":"Display options","background":"Show background options","background_switch":"Switch back to last background","map_data":"Show map data options","fullscreen":"Enter full screen mode","wireframe":"Toggle wireframe mode","minimap":"Toggle minimap"},"selecting":{"title":"Selecting features","select_one":"Select a single feature","select_multi":"Select multiple features","lasso":"Draw a selection lasso around features"},"with_selected":{"title":"With feature selected","edit_menu":"Toggle edit menu"},"vertex_selected":{"title":"With node selected","previous":"Jump to previous node","next":"Jump to next node","first":"Jump to first node","last":"Jump to last node","change_parent":"Switch parent way"}},"editing":{"title":"Editing","drawing":{"title":"Drawing","add_point":"'Add point' mode","add_line":"'Add line' mode","add_area":"'Add area' mode","place_point":"Place a point","disable_snap":"Hold to disable point snapping","stop_line":"Finish drawing a line or area"},"operations":{"title":"Operations","continue_line":"Continue a line at the selected node","merge":"Combine (merge) selected features","disconnect":"Disconnect features at the selected node","split":"Split a line into two at the selected node","reverse":"Reverse a line","move":"Move selected features","rotate":"Rotate selected features","orthogonalize":"Straighten line / Square area corners","circularize":"Circularize a closed line or area","reflect_long":"Reflect features across the longer axis","reflect_short":"Reflect features across the shorter axis","delete":"Delete selected features"},"commands":{"title":"Commands","copy":"Copy selected features","paste":"Paste copied features","undo":"Undo last action","redo":"Redo last action","save":"Save changes"}},"tools":{"title":"Tools","info":{"title":"Information","all":"Toggle all information panels","background":"Toggle background panel","history":"Toggle history panel","location":"Toggle location panel","measurement":"Toggle measurement panel"}}},"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"},"animal_boarding":{"label":"For Animals"},"animal_breeding":{"label":"For Animals"},"animal_shelter":{"label":"For Animals"},"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"}},"club":{"label":"Type"},"collection_times":{"label":"Collection Times"},"communication_multi":{"label":"Communication Types"},"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":"Crops"},"crossing":{"label":"Type"},"cuisine":{"label":"Cuisines"},"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)"},"grape_variety":{"label":"Grape Varieties"},"handicap":{"label":"Handicap","placeholder":"1-18"},"handrail":{"label":"Handrail"},"height":{"label":"Height (Meters)"},"highway":{"label":"Type"},"historic":{"label":"Type"},"historic/civilization":{"label":"Historic Civilization"},"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"},"inscription":{"label":"Inscription"},"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"},"label":{"label":"Label"},"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"},"manhole":{"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"},"maxweight":{"label":"Max Weight"},"mtb/scale":{"label":"Mountain Biking Difficulty","placeholder":"0, 1, 2, 3...","options":{"0":"0: Solid gravel/packed earth, no obstacles, wide curves","1":"1: Some loose surface, small obstacles, wide curves","2":"2: Much loose surface, large obstacles, easy hairpins","3":"3: Slippery surface, large obstacles, tight hairpins","4":"4: Loose surface or boulders, dangerous hairpins","5":"5: Maximum difficulty, boulder fields, landslides","6":"6: Not rideable except by the very best mountain bikers"}},"mtb/scale/imba":{"label":"IMBA Trail Difficulty","placeholder":"Easy, Medium, Difficult...","options":{"0":"Easiest (white circle)","1":"Easy (green circle)","2":"Medium (blue square)","3":"Difficult (black diamond)","4":"Extremely Difficult (double black diamond)"}},"mtb/scale/uphill":{"label":"Mountain Biking Uphill Difficulty","placeholder":"0, 1, 2, 3...","options":{"0":"0: Avg. incline <10%, gravel/packed earth, no obstacles","1":"1: Avg. incline <15%, gravel/packed earth, few small objects","2":"2: Avg. incline <20%, stable surface, fistsize rocks/roots","3":"3: Avg. incline <25%, variable surface, fistsize rocks/branches","4":"4: Avg. incline <30%, poor condition, big rocks/branches","5":"5: Very steep, bike generally needs to be pushed or carried"}},"name":{"label":"Name","placeholder":"Common name (if any)"},"natural":{"label":"Natural"},"network_bicycle":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lcn":"Local","rcn":"Regional","ncn":"National","icn":"International"}},"network_foot":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lwn":"Local","rwn":"Regional","nwn":"National","iwn":"International"}},"network_horse":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lhn":"Local","rhn":"Regional","nhn":"National","ihn":"International"}},"network_road":{"label":"Network"},"network":{"label":"Network"},"note":{"label":"Note"},"office":{"label":"Type"},"oneway_yes":{"label":"One Way","options":{"undefined":"Assumed to be Yes","yes":"Yes","no":"No"}},"oneway":{"label":"One Way","options":{"undefined":"Assumed to be No","yes":"Yes","no":"No"}},"opening_hours":{"label":"Hours"},"operator":{"label":"Operator"},"outdoor_seating":{"label":"Outdoor Seating"},"par":{"label":"Par","placeholder":"3, 4, 5..."},"parallel_direction":{"label":"Direction","options":{"forward":"Forward","backward":"Backward"}},"park_ride":{"label":"Park and Ride"},"parking":{"label":"Type","options":{"surface":"Surface","multi-storey":"Multilevel","underground":"Underground","sheds":"Sheds","carports":"Carports","garage_boxes":"Garage Boxes","lane":"Roadside Lane"}},"payment_multi":{"label":"Payment Types"},"phone":{"label":"Phone","placeholder":"+31 42 123 4567"},"piste/difficulty":{"label":"Difficulty","placeholder":"Easy, Intermediate, Advanced...","options":{"novice":"Novice (instructional)","easy":"Easy (green circle)","intermediate":"Intermediate (blue square)","advanced":"Advanced (black diamond)","expert":"Expert (double black diamond)","freeride":"Freeride (off-piste)","extreme":"Extreme (climbing equipment required)"}},"piste/grooming":{"label":"Grooming","options":{"classic":"Classic","mogul":"Mogul","backcountry":"Backcountry","classic+skating":"Classic and Skating","scooter":"Scooter/Snowmobile","skating":"Skating"}},"piste/type":{"label":"Type","options":{"downhill":"Downhill","nordic":"Nordic","skitour":"Skitour","sled":"Sled","hike":"Hike","sleigh":"Sleigh","ice_skate":"Ice Skate","snow_park":"Snow Park","playground":"Playground"}},"place":{"label":"Type"},"plant":{"label":"Plant"},"population":{"label":"Population"},"power_supply":{"label":"Power Supply"},"power":{"label":"Type"},"produce":{"label":"Produce"},"product":{"label":"Products"},"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_times":{"label":"Service Times"},"service":{"label":"Type"},"service/bicycle":{"label":"Services"},"service/vehicle":{"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":"Sports"},"sport_racing_motor":{"label":"Sports"},"sport_racing_nonmotor":{"label":"Sports"},"sport":{"label":"Sports"},"stars":{"label":"Stars"},"start_date":{"label":"Start Date"},"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"},"tomb":{"label":"Type"},"tourism":{"label":"Type"},"tower/construction":{"label":"Construction","placeholder":"Guyed, Lattice, Concealed, ..."},"tower/type":{"label":"Type"},"tracktype":{"label":"Track Type","placeholder":"Solid, Mostly Solid, Soft...","options":{"grade1":"Solid: paved or heavily compacted hardcore surface","grade2":"Mostly Solid: gravel/rock with some soft material mixed in","grade3":"Even mixture of hard and soft materials","grade4":"Mostly Soft: soil/sand/grass with some hard material mixed in","grade5":"Soft: soil/sand/grass"}},"traffic_calming":{"label":"Type"},"traffic_signals":{"label":"Type"},"trail_visibility":{"label":"Trail Visibility","placeholder":"Excellent, Good, Bad...","options":{"excellent":"Excellent: unambiguous path or markers everywhere","good":"Good: markers visible, sometimes require searching","intermediate":"Intermediate: few markers, path mostly visible","bad":"Bad: no markers, path sometimes invisible/pathless","horrible":"Horrible: often pathless, some orientation skills required","no":"No: pathless, excellent orientation skills required"}},"trees":{"label":"Trees"},"tunnel":{"label":"Tunnel"},"vending":{"label":"Type of Goods"},"visibility":{"label":"Visibility","options":{"house":"Up to 5m (16ft)","street":"5 to 20m (16 to 65ft)","area":"Over 20m (65ft)"}},"wall":{"label":"Type"},"water_point":{"label":"Water Point"},"water":{"label":"Type"},"waterway":{"label":"Type"},"website":{"label":"Website","placeholder":"http://example.com/"},"wetland":{"label":"Type"},"wheelchair":{"label":"Wheelchair Access"},"width":{"label":"Width (Meters)"},"wikipedia":{"label":"Wikipedia"}},"presets":{"aerialway":{"name":"Aerialway","terms":"ski lift,funifor,funitel"},"aeroway":{"name":"Aeroway","terms":""},"amenity":{"name":"Amenity","terms":""},"highway":{"name":"Highway","terms":""},"place":{"name":"Place","terms":""},"power":{"name":"Power","terms":""},"railway":{"name":"Railway","terms":""},"roundabout":{"name":"Roundabout","terms":""},"waterway":{"name":"Waterway","terms":""},"address":{"name":"Address","terms":""},"advertising/billboard":{"name":"Billboard","terms":""},"aerialway/cable_car":{"name":"Cable Car","terms":"tramway,ropeway"},"aerialway/chair_lift":{"name":"Chair Lift","terms":""},"aerialway/drag_lift":{"name":"Drag Lift","terms":""},"aerialway/gondola":{"name":"Gondola","terms":""},"aerialway/goods":{"name":"Goods Aerialway","terms":""},"aerialway/magic_carpet":{"name":"Magic Carpet Lift","terms":""},"aerialway/mixed_lift":{"name":"Mixed Lift","terms":""},"aerialway/platter":{"name":"Platter Lift","terms":"button lift,poma lift"},"aerialway/pylon":{"name":"Aerialway Pylon","terms":""},"aerialway/rope_tow":{"name":"Rope Tow Lift","terms":"handle tow,bugel lift"},"aerialway/station":{"name":"Aerialway Station","terms":""},"aerialway/t-bar":{"name":"T-bar Lift","terms":""},"aeroway/aerodrome":{"name":"Airport","terms":"airplane,airport,aerodrome"},"aeroway/apron":{"name":"Apron","terms":"ramp"},"aeroway/gate":{"name":"Airport Gate","terms":""},"aeroway/hangar":{"name":"Hangar","terms":""},"aeroway/helipad":{"name":"Helipad","terms":"helicopter,helipad,heliport"},"aeroway/runway":{"name":"Runway","terms":"landing strip"},"aeroway/taxiway":{"name":"Taxiway","terms":""},"aeroway/terminal":{"name":"Airport Terminal","terms":"airport,aerodrome"},"amenity/coworking_space":{"name":"Coworking Space","terms":""},"amenity/nursing_home":{"name":"Nursing Home","terms":""},"amenity/register_office":{"name":"Register Office","terms":""},"amenity/swimming_pool":{"name":"Swimming Pool","terms":""},"amenity/animal_boarding":{"name":"Animal Boarding Facility","terms":"boarding,cat,dog,horse,kitten,pet boarding,pet care,pet hotel,puppy,reptile"},"amenity/animal_breeding":{"name":"Animal Breeding Facility","terms":"breeding,bull,cat,cow,dog,horse,husbandry,kitten,livestock,pet breeding,puppy,reptile"},"amenity/animal_shelter":{"name":"Animal Shelter","terms":"adoption,aspca,cat,dog,horse,kitten,pet care,pet rescue,puppy,raptor,reptile,rescue,spca"},"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/driving_school":{"name":"Driving School","terms":""},"amenity/embassy":{"name":"Embassy","terms":""},"amenity/fast_food":{"name":"Fast Food","terms":"restaurant,takeaway"},"amenity/ferry_terminal":{"name":"Ferry Terminal","terms":""},"amenity/fire_station":{"name":"Fire Station","terms":""},"amenity/food_court":{"name":"Food Court","terms":"fast food,restaurant,food"},"amenity/fountain":{"name":"Fountain","terms":""},"amenity/fuel":{"name":"Gas Station","terms":"petrol,fuel,gasoline,propane,diesel,lng,cng,biodiesel"},"amenity/grave_yard":{"name":"Graveyard","terms":""},"amenity/grit_bin":{"name":"Grit Bin","terms":"salt,sand"},"amenity/hospital":{"name":"Hospital Grounds","terms":"clinic,doctor,emergency room,health,infirmary,institution,sanatorium,sanitarium,sick,surgery,ward"},"amenity/hunting_stand":{"name":"Hunting Stand","terms":"game,gun,lookout,rifle,shoot*,wild,watch"},"amenity/ice_cream":{"name":"Ice Cream Shop","terms":"gelato,sorbet,sherbet,frozen,yogurt"},"amenity/internet_cafe":{"name":"Internet Cafe","terms":"cybercafe,taxiphone,teleboutique,coffee,cafe,net,lanhouse"},"amenity/kindergarten":{"name":"Preschool/Kindergarten Grounds","terms":"kindergarden,pre-school"},"amenity/library":{"name":"Library","terms":"book"},"amenity/marketplace":{"name":"Marketplace","terms":""},"amenity/motorcycle_parking":{"name":"Motorcycle Parking","terms":""},"amenity/nightclub":{"name":"Nightclub","terms":"disco*,night club,dancing,dance club"},"amenity/parking_entrance":{"name":"Parking Garage Entrance/Exit","terms":""},"amenity/parking_space":{"name":"Parking Space","terms":""},"amenity/parking":{"name":"Car Parking","terms":""},"amenity/pavilion":{"name":"Pavilion","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/scrapyard":{"name":"Scrap Yard","terms":"car,junk,metal,salvage,scrap,u-pull-it,vehicle,wreck,yard"},"amenity/shelter":{"name":"Shelter","terms":"lean-to,gazebo,picnic"},"amenity/social_facility":{"name":"Social Facility","terms":""},"amenity/social_facility/food_bank":{"name":"Food Bank","terms":""},"amenity/social_facility/group_home":{"name":"Elderly Group Home","terms":"old,senior,living"},"amenity/social_facility/homeless_shelter":{"name":"Homeless Shelter","terms":"houseless,unhoused,displaced"},"amenity/social_facility/nursing_home":{"name":"Nursing Home","terms":"elderly,living,nursing,old,senior"},"amenity/studio":{"name":"Studio","terms":"recording,radio,television"},"amenity/taxi":{"name":"Taxi Stand","terms":"cab"},"amenity/telephone":{"name":"Telephone","terms":"phone"},"amenity/theatre":{"name":"Theater","terms":"theatre,performance,play,musical"},"amenity/toilets":{"name":"Toilets","terms":"bathroom,restroom,outhouse,privy,head,lavatory,latrine,water closet,WC,W.C."},"amenity/townhall":{"name":"Town Hall","terms":"village,city,government,courthouse,municipal"},"amenity/university":{"name":"University Grounds","terms":"college"},"amenity/vending_machine":{"name":"Vending Machine","terms":""},"amenity/vending_machine/news_papers":{"name":"Newspaper Vending Machine","terms":"newspaper"},"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/newspapers":{"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/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":""},"amenity/watering_place":{"name":"Animal Watering Place","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"},"club":{"name":"Club","terms":"social"},"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":"alcohol,beer,beverage,bier,booze,cider"},"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/distillery":{"name":"Distillery","terms":"alcohol,beverage,bourbon,booze,brandy,gin,hooch,liquor,mezcal,moonshine,rum,scotch,spirits,still,tequila,vodka,whiskey,whisky"},"craft/dressmaker":{"name":"Dressmaker","terms":"seamstress"},"craft/electrician":{"name":"Electrician","terms":"power,wire"},"craft/electronics_repair":{"name":"Electronics Repair Shop","terms":""},"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/elevator":{"name":"Elevator","terms":"lift"},"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":"Racetrack (Motorsport)","terms":"auto*,formula one,kart,motocross,nascar,race*,track"},"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/speed_camera":{"name":"Speed Camera","terms":""},"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/tomb":{"name":"Tomb","terms":""},"historic/wayside_cross":{"name":"Wayside Cross","terms":""},"historic/wayside_shrine":{"name":"Wayside Shrine","terms":""},"junction":{"name":"Junction","terms":""},"landuse":{"name":"Land Use","terms":""},"landuse/farm":{"name":"Farmland","terms":""},"landuse/allotments":{"name":"Community Garden","terms":"allotment,garden"},"landuse/aquaculture":{"name":"Aquaculture","terms":"fish farm,crustacean,algae,aquafarming,shrimp farm,oyster farm,mariculture,algaculture"},"landuse/basin":{"name":"Basin","terms":""},"landuse/cemetery":{"name":"Cemetery","terms":""},"landuse/churchyard":{"name":"Churchyard","terms":""},"landuse/commercial":{"name":"Commercial Area","terms":""},"landuse/construction":{"name":"Construction","terms":""},"landuse/farmland":{"name":"Farmland","terms":"crop,grow,plant"},"landuse/farmyard":{"name":"Farmyard","terms":"crop,grow,plant"},"landuse/forest":{"name":"Forest","terms":"tree"},"landuse/garages":{"name":"Garages","terms":""},"landuse/grass":{"name":"Grass","terms":""},"landuse/harbour":{"name":"Harbor","terms":"boat"},"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/railway":{"name":"Railway Corridor","terms":"rail,train,track"},"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/beachvolleyball":{"name":"Beach Volleyball Court","terms":"volleyball"},"leisure/pitch/bowls":{"name":"Bowling Green","terms":""},"leisure/pitch/cricket":{"name":"Cricket Field","terms":""},"leisure/pitch/equestrian":{"name":"Riding Arena","terms":"dressage,equestrian,horse,horseback,riding"},"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":"football"},"leisure/pitch/table_tennis":{"name":"Ping Pong Table","terms":"table tennis,ping pong"},"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":"Racetrack (Running)","terms":"race*,running,sprint,track"},"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":"cycle,dog,greyhound,horse,race*,track"},"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":"Mast","terms":"antenna,broadcast tower,cell phone tower,cell tower,communication mast,communication tower,guyed tower,mobile phone tower,radio mast,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"},"manhole":{"name":"Manhole","terms":"cover,hole,sewer,sewage,telecom"},"manhole/drain":{"name":"Storm Drain","terms":"cover,drain,hole,rain,sewer,sewage,storm"},"natural":{"name":"Natural","terms":""},"natural/bare_rock":{"name":"Bare Rock","terms":"rock"},"natural/bay":{"name":"Bay","terms":""},"natural/beach":{"name":"Beach","terms":"shore"},"natural/cave_entrance":{"name":"Cave Entrance","terms":"cavern,hollow,grotto,shelter,cavity"},"natural/cliff":{"name":"Cliff","terms":"escarpment"},"natural/coastline":{"name":"Coastline","terms":"shore"},"natural/fell":{"name":"Fell","terms":""},"natural/glacier":{"name":"Glacier","terms":""},"natural/grassland":{"name":"Grassland","terms":"prairie,savanna"},"natural/heath":{"name":"Heath","terms":""},"natural/peak":{"name":"Peak","terms":"acme,aiguille,alp,climax,crest,crown,hill,mount,mountain,pinnacle,summit,tip,top"},"natural/ridge":{"name":"Ridge","terms":"crest"},"natural/saddle":{"name":"Saddle","terms":"pass,mountain pass,top"},"natural/sand":{"name":"Sand","terms":"desert"},"natural/scree":{"name":"Scree","terms":"loose rocks"},"natural/scrub":{"name":"Scrub","terms":"bush,shrubs"},"natural/spring":{"name":"Spring","terms":""},"natural/tree_row":{"name":"Tree row","terms":""},"natural/tree":{"name":"Tree","terms":""},"natural/volcano":{"name":"Volcano","terms":"mountain,crater"},"natural/water":{"name":"Water","terms":""},"natural/water/lake":{"name":"Lake","terms":"lakelet,loch,mere"},"natural/water/pond":{"name":"Pond","terms":"lakelet,millpond,tarn,pool,mere"},"natural/water/reservoir":{"name":"Reservoir","terms":""},"natural/wetland":{"name":"Wetland","terms":""},"natural/wood":{"name":"Wood","terms":"tree"},"noexit/yes":{"name":"No Exit","terms":"no exit,road end,dead end"},"office":{"name":"Office","terms":""},"office/travel_agent":{"name":"Travel Agency","terms":""},"office/accountant":{"name":"Accountant","terms":""},"office/administrative":{"name":"Administrative Office","terms":""},"office/architect":{"name":"Architect","terms":""},"office/company":{"name":"Company Office","terms":""},"office/coworking":{"name":"Coworking Space","terms":"coworking,office"},"office/educational_institution":{"name":"Educational Institution","terms":""},"office/employment_agency":{"name":"Employment Agency","terms":"job"},"office/estate_agent":{"name":"Real Estate Office","terms":""},"office/financial":{"name":"Financial Office","terms":""},"office/government":{"name":"Government Office","terms":""},"office/government/register_office":{"name":"Register Office","terms":"clerk,marriage,death,birth,certificate"},"office/insurance":{"name":"Insurance Office","terms":""},"office/it":{"name":"IT Office","terms":""},"office/lawyer":{"name":"Law Office","terms":""},"office/lawyer/notary":{"name":"Notary Office","terms":"clerk,signature,wills,deeds,estate"},"office/newspaper":{"name":"Newspaper","terms":""},"office/ngo":{"name":"NGO Office","terms":""},"office/physician":{"name":"Physician","terms":""},"office/political_party":{"name":"Political Party","terms":""},"office/research":{"name":"Research Office","terms":""},"office/telecommunication":{"name":"Telecom Office","terms":""},"office/therapist":{"name":"Therapist","terms":""},"piste":{"name":"Piste/Ski Trail","terms":"ski,sled,sleigh,snowboard,nordic,downhill,snowmobile"},"place/farm":{"name":"Farm","terms":""},"place/city":{"name":"City","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/quarter":{"name":"Sub-Borough / Quarter","terms":"boro,borough,quarter"},"place/square":{"name":"Square","terms":""},"place/suburb":{"name":"Borough / Suburb","terms":"boro,borough,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":"hydro,solar,turbine,wind"},"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":"metro,transit"},"railway/subway":{"name":"Subway","terms":"metro,transit"},"railway/tram_stop":{"name":"Tram Stop","terms":"light rail,streetcar,tram,trolley"},"railway/tram":{"name":"Tram","terms":"light rail,streetcar,tram,trolley"},"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/appliance":{"name":"Appliance Store","terms":"air conditioner,appliance,dishwasher,dryer,freezer,fridge,grill,kitchen,oven,refrigerator,stove,washer,washing machine"},"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,blueray,camera,computer,dvd,home theater,radio,speaker,tv,video"},"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/gas":{"name":"Bottled Gas Shop","terms":"cng,lpg,natural gas,propane,refill,tank"},"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/perfumery":{"name":"Perfume Store","terms":""},"shop/pet":{"name":"Pet Store","terms":"animal,cat,dog,fish,kitten,puppy,reptile"},"shop/photo":{"name":"Photography Store","terms":"camera,film"},"shop/pyrotechnics":{"name":"Fireworks Store","terms":""},"shop/radiotechnics":{"name":"Radio/Electronic Component Store","terms":""},"shop/religion":{"name":"Religious Store","terms":""},"shop/scuba_diving":{"name":"Scuba Diving Shop","terms":""},"shop/seafood":{"name":"Seafood Shop","terms":"fishmonger"},"shop/second_hand":{"name":"Consignment/Thrift Store","terms":"secondhand,second hand,resale,thrift,used"},"shop/shoes":{"name":"Shoe Store","terms":""},"shop/sports":{"name":"Sporting Goods Store","terms":""},"shop/stationery":{"name":"Stationery Store","terms":"card,paper"},"shop/storage_rental":{"name":"Storage Rental","terms":""},"shop/supermarket":{"name":"Supermarket","terms":"grocery,store,shop"},"shop/tailor":{"name":"Tailor","terms":"clothes,suit"},"shop/tattoo":{"name":"Tattoo Parlor","terms":""},"shop/tea":{"name":"Tea Store","terms":""},"shop/ticket":{"name":"Ticket Seller","terms":""},"shop/tobacco":{"name":"Tobacco Shop","terms":""},"shop/toys":{"name":"Toy Store","terms":""},"shop/travel_agency":{"name":"Travel Agency","terms":""},"shop/tyres":{"name":"Tire Store","terms":""},"shop/vacuum_cleaner":{"name":"Vacuum Cleaner Store","terms":""},"shop/variety_store":{"name":"Variety Store","terms":""},"shop/video_games":{"name":"Video Game Store","terms":""},"shop/video":{"name":"Video Store","terms":"DVD"},"shop/watches":{"name":"Watches Shop","terms":""},"shop/water_sports":{"name":"Watersport/Swim Shop","terms":""},"shop/weapons":{"name":"Weapon Shop","terms":"ammo,gun,knife,knives"},"shop/window_blind":{"name":"Window Blind Store","terms":""},"shop/wine":{"name":"Wine Shop","terms":""},"tourism":{"name":"Tourism","terms":""},"tourism/alpine_hut":{"name":"Alpine Hut","terms":""},"tourism/apartment":{"name":"Guest Apartment / Condo","terms":""},"tourism/aquarium":{"name":"Aquarium","terms":"fish,sea,water"},"tourism/artwork":{"name":"Artwork","terms":"mural,sculpture,statue"},"tourism/attraction":{"name":"Tourist Attraction","terms":""},"tourism/camp_site":{"name":"Campground","terms":"tent,rv"},"tourism/caravan_site":{"name":"RV Park","terms":"Motor Home,Camper"},"tourism/chalet":{"name":"Chalet","terms":""},"tourism/gallery":{"name":"Art Gallery","terms":"art*,exhibit*,paint*,photo*,sculpt*"},"tourism/guest_house":{"name":"Guest House","terms":"B&B,Bed and Breakfast"},"tourism/hostel":{"name":"Hostel","terms":""},"tourism/hotel":{"name":"Hotel","terms":""},"tourism/information":{"name":"Information","terms":""},"tourism/information/board":{"name":"Information Board","terms":""},"tourism/information/guidepost":{"name":"Guidepost","terms":""},"tourism/information/map":{"name":"Map","terms":""},"tourism/information/office":{"name":"Tourist Information Office","terms":""},"tourism/motel":{"name":"Motel","terms":""},"tourism/museum":{"name":"Museum","terms":"art*,exhibit*,gallery,foundation,hall,institution,paint*,photo*,sculpt*"},"tourism/picnic_site":{"name":"Picnic Site","terms":"camp"},"tourism/theme_park":{"name":"Theme Park","terms":""},"tourism/viewpoint":{"name":"Viewpoint","terms":""},"tourism/zoo":{"name":"Zoo","terms":"animal"},"traffic_calming":{"name":"Traffic Calming","terms":"bump,hump,slow,speed"},"traffic_calming/bump":{"name":"Speed Bump","terms":"hump,speed,slow"},"traffic_calming/chicane":{"name":"Traffic Chicane","terms":"driveway link,speed,slow"},"traffic_calming/choker":{"name":"Traffic Choker","terms":"speed,slow"},"traffic_calming/cushion":{"name":"Speed Cushion","terms":"bump,hump,speed,slow"},"traffic_calming/dip":{"name":"Dip","terms":"speed,slow"},"traffic_calming/hump":{"name":"Speed Hump","terms":"bump,speed,slow"},"traffic_calming/island":{"name":"Traffic Island","terms":"circle,roundabout,slow"},"traffic_calming/rumble_strip":{"name":"Rumble Strip","terms":"audible lines,sleeper lines,growlers"},"traffic_calming/table":{"name":"Raised Pedestrian Crossing","terms":"flat top,hump,speed,slow"},"type/multipolygon":{"name":"Multipolygon","terms":""},"type/boundary":{"name":"Boundary","terms":""},"type/boundary/administrative":{"name":"Administrative Boundary","terms":""},"type/restriction":{"name":"Restriction","terms":""},"type/restriction/no_left_turn":{"name":"No Left Turn","terms":""},"type/restriction/no_right_turn":{"name":"No Right Turn","terms":""},"type/restriction/no_straight_on":{"name":"No Straight On","terms":""},"type/restriction/no_u_turn":{"name":"No U-turn","terms":""},"type/restriction/only_left_turn":{"name":"Left Turn Only","terms":""},"type/restriction/only_right_turn":{"name":"Right Turn Only","terms":""},"type/restriction/only_straight_on":{"name":"No Turns","terms":""},"type/route_master":{"name":"Route Master","terms":""},"type/route":{"name":"Route","terms":""},"type/route/bicycle":{"name":"Cycle Route","terms":""},"type/route/bus":{"name":"Bus Route","terms":""},"type/route/detour":{"name":"Detour Route","terms":""},"type/route/ferry":{"name":"Ferry Route","terms":""},"type/route/foot":{"name":"Foot Route","terms":""},"type/route/hiking":{"name":"Hiking Route","terms":""},"type/route/horse":{"name":"Riding Route","terms":""},"type/route/pipeline":{"name":"Pipeline Route","terms":""},"type/route/power":{"name":"Power Route","terms":""},"type/route/road":{"name":"Road Route","terms":""},"type/route/train":{"name":"Train Route","terms":""},"type/route/tram":{"name":"Tram Route","terms":""},"type/site":{"name":"Site","terms":""},"vertex":{"name":"Other","terms":""},"waterway/boatyard":{"name":"Boatyard","terms":""},"waterway/canal":{"name":"Canal","terms":""},"waterway/dam":{"name":"Dam","terms":""},"waterway/ditch":{"name":"Ditch","terms":""},"waterway/dock":{"name":"Wet Dock / Dry Dock","terms":"boat,ship,vessel,marine"},"waterway/drain":{"name":"Drain","terms":""},"waterway/fuel":{"name":"Marine Fuel Station","terms":"petrol,gas,diesel,boat"},"waterway/river":{"name":"River","terms":"beck,branch,brook,course,creek,estuary,rill,rivulet,run,runnel,stream,tributary,watercourse"},"waterway/riverbank":{"name":"Riverbank","terms":""},"waterway/sanitary_dump_station":{"name":"Marine Toilet Disposal","terms":"Boat,Watercraft,Sanitary,Dump Station,Pumpout,Pump out,Elsan,CDP,CTDP,Chemical Toilet"},"waterway/stream":{"name":"Stream","terms":"beck,branch,brook,burn,course,creek,current,drift,flood,flow,freshet,race,rill,rindle,rivulet,run,runnel,rush,spate,spritz,surge,tide,torrent,tributary,watercourse"},"waterway/water_point":{"name":"Marine Drinking Water","terms":""},"waterway/waterfall":{"name":"Waterfall","terms":"fall"},"waterway/weir":{"name":"Weir","terms":""}}},"imagery":{"Bing":{"description":"Satellite and aerial imagery.","name":"Bing aerial imagery"},"DigitalGlobe-Premium":{"attribution":{"text":"Terms & Feedback"},"description":"Premium DigitalGlobe satellite imagery.","name":"DigitalGlobe Premium Imagery"},"DigitalGlobe-Standard":{"attribution":{"text":"Terms & Feedback"},"description":"Standard DigitalGlobe satellite imagery.","name":"DigitalGlobe Standard Imagery"},"MAPNIK":{"attribution":{"text":"© OpenStreetMap contributors, CC-BY-SA"},"description":"The default OpenStreetMap layer.","name":"OpenStreetMap (Standard)"},"Mapbox":{"attribution":{"text":"Terms & Feedback"},"description":"Satellite and aerial imagery.","name":"Mapbox Satellite"},"New_and_Misaligned_TIGER_Roads-2013":{"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","name":"New & Misaligned TIGER Roads"},"OSM_Inspector-Addresses":{"attribution":{"text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA"},"name":"OSM Inspector: Addresses"},"OSM_Inspector-Geometry":{"attribution":{"text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA"},"name":"OSM Inspector: Geometry"},"OSM_Inspector-Highways":{"attribution":{"text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA"},"name":"OSM Inspector: Highways"},"OSM_Inspector-Multipolygon":{"attribution":{"text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA"},"name":"OSM Inspector: Area"},"OSM_Inspector-Places":{"attribution":{"text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA"},"name":"OSM Inspector: Places"},"OSM_Inspector-Routing":{"attribution":{"text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA"},"name":"OSM Inspector: Routing"},"OSM_Inspector-Tagging":{"attribution":{"text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA"},"name":"OSM Inspector: Tagging"},"Waymarked_Trails-Cycling":{"attribution":{"text":"© Sarah Hoffmann, CC by-SA 3.0, map data OpenStreetMap contributors, ODbL 1.0"},"name":"Waymarked Trails: Cycling"},"Waymarked_Trails-Hiking":{"attribution":{"text":"© Sarah Hoffmann, CC by-SA 3.0, map data OpenStreetMap contributors, ODbL 1.0"},"name":"Waymarked Trails: Hiking"},"Waymarked_Trails-MTB":{"attribution":{"text":"© Sarah Hoffmann, CC by-SA 3.0, map data OpenStreetMap contributors, ODbL 1.0"},"name":"Waymarked Trails: MTB"},"Waymarked_Trails-Skating":{"attribution":{"text":"© Sarah Hoffmann, CC by-SA 3.0, map data OpenStreetMap contributors, ODbL 1.0"},"name":"Waymarked Trails: Skating"},"Waymarked_Trails-Winter_Sports":{"attribution":{"text":"© Michael Spreng, CC by-SA 3.0, map data OpenStreetMap contributors, ODbL 1.0"},"name":"Waymarked Trails: Winter Sports"},"basemap.at":{"attribution":{"text":"basemap.at"},"description":"Basemap of Austria, based on goverment data.","name":"basemap.at"},"basemap.at-orthofoto":{"attribution":{"text":"basemap.at"},"description":"Orthofoto layer provided by basemap.at. \"Successor\" of geoimage.at imagery.","name":"basemap.at Orthofoto"},"hike_n_bike":{"attribution":{"text":"© OpenStreetMap contributors"},"name":"Hike & Bike"},"mapbox_locator_overlay":{"attribution":{"text":"Terms & Feedback"},"description":"Shows major features to help orient you.","name":"Locator Overlay"},"openpt_map":{"attribution":{"text":"© OpenStreetMap contributors, CC-BY-SA"},"name":"OpenPT Map (overlay)"},"osm-gps":{"attribution":{"text":"© OpenStreetMap contributors"},"description":"Public GPS traces uploaded to OpenStreetMap.","name":"OpenStreetMap GPS traces"},"osm-mapnik-black_and_white":{"attribution":{"text":"© OpenStreetMap contributors, CC-BY-SA"},"name":"OpenStreetMap (Standard Black & White)"},"osm-mapnik-german_style":{"attribution":{"text":"© OpenStreetMap contributors, CC-BY-SA"},"name":"OpenStreetMap (German Style)"},"qa_no_address":{"attribution":{"text":"Simon Poole, Data ©OpenStreetMap contributors"},"name":"QA No Address"},"skobbler":{"attribution":{"text":"© Tiles: skobbler Map data: OpenStreetMap contributors"},"name":"skobbler"},"stamen-terrain-background":{"attribution":{"text":"Map tiles by Stamen Design, under CC BY 3.0"},"name":"Stamen Terrain"},"tf-cycle":{"attribution":{"text":"Maps © Thunderforest, Data © OpenStreetMap contributors"},"name":"Thunderforest OpenCycleMap"},"tf-landscape":{"attribution":{"text":"Maps © Thunderforest, Data © OpenStreetMap contributors"},"name":"Thunderforest Landscape"}}};
18627 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}","endDate":"2013-06-01T00:00:00.000Z","startDate":"2013-05-01T00:00:00.000Z","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]]],"description":"Public domain aerial imagery taken in May/June 2013 from San Juan County, WA. Resolution is 9 inch."},{"id":"sjcgis.org-Aerials_2016_WM","name":"2016 aerial imagery for San Juan County WA","type":"tms","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/Aerials_2016_WM/MapServer/tile/{zoom}/{y}/{x}","endDate":"2016-07-01T00:00:00.000Z","startDate":"2016-05-01T00:00:00.000Z","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,"description":"Public domain aerial imagery taken in May, June, and July from San Juan County, WA. Resolution is 6 inch countywide."},{"id":"OS7","name":"7th Series (OS7)","type":"tms","template":"http://ooc.openstreetmap.org/os7/{zoom}/{x}/{y}.jpg","polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]]},{"id":"AGRI-black_and_white-2.5m","name":"AGRI black-and-white 2.5m","type":"tms","template":"http://agri.openstreetmap.org/{zoom}/{x}/{y}.png","polygon":[[[112.28778,-28.784589],[112.71488,-31.13894],[114.11263,-34.178287],[113.60788,-37.39012],[117.17992,-37.451794],[119.31538,-37.42096],[121.72262,-36.708394],[123.81925,-35.76893],[125.9547,-34.3066],[127.97368,-33.727398],[130.07031,-33.24166],[130.10913,-33.888704],[131.00214,-34.049705],[131.0798,-34.72257],[132.28342,-35.39],[134.18591,-35.61126],[133.8753,-37.1119],[134.8459,-37.6365],[139.7769,-37.82075],[139.93223,-39.4283],[141.6017,-39.8767],[142.3783,-39.368294],[142.3783,-40.64702],[142.49478,-42.074874],[144.009,-44.060127],[147.23161,-44.03222],[149.05645,-42.534313],[149.52237,-40.99959],[149.9494,-40.852921],[150.8036,-38.09627],[151.81313,-38.12682],[156.20052,-22.667706],[156.20052,-20.10109],[156.62761,-17.417627],[155.26869,-17.19521],[154.14272,-19.51662],[153.5215,-18.34139],[153.05558,-16.5636],[152.78379,-15.256768],[152.27905,-13.4135],[151.3472,-12.391767],[149.48354,-12.05024],[146.9598,-9.992408],[135.9719,-9.992408],[130.3032,-10.33636],[128.09016,-12.164136],[125.91588,-12.315912],[124.3239,-11.860326],[122.03323,-11.974295],[118.26706,-16.9353],[115.93747,-19.11357],[114.0738,-21.11863],[113.49141,-22.596033],[112.28778,-28.784589]]],"terms_text":"AGRI"},{"id":"lu.geoportail.opendata.basemap","name":"Basemap geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/basemap/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","endDate":"2010-07-20T00:00:00.000Z","startDate":"2013-07-19T00:00:00.000Z","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","icon":"https://www.geoportail.lu/static/img/lion.png"},{"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","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","description":"Basemap of Austria, based on goverment data.","icon":"https://www.basemap.at/images/logo_basemap.jpg"},{"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","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,"description":"Orthofoto layer provided by basemap.at. \"Successor\" of geoimage.at imagery.","icon":"https://www.basemap.at/images/logo_basemap.jpg"},{"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 © AGIV","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAABm0lEQVQ4y6WTPUgCYRjHf5oFJVfRUZKVHYFBoBAUFLZE0FBD0NQHRENESzS019LSFNHWx1DQEhGRg0JFREM11FJuLWem4GB5HULdwdkgHprn5LO97/O8v+fj/7y2bDabpQKzFx5S6ntlgE81xvHtclHAbuSNloNT5q/uywP021cAvO4hAPYu5/hI5e6GWpsBCEfjxNSMNUALPvJ7eA3AQPcML3KIzbNhlvdEWmu+6RCcAISiCWtA3fosPztBfrYvAGgX/QCIggdR8DDe6Qbg5E0uAdjyKhhykq+uBeySi9qVCfSAB61HRBQ8RFJpRs6vALiZHMUnNpYO0Ujn+jPkJJnVfbTBNeqfFQB8YqP56H8VJqBKcuHcWsQuuXIOyUX1sN8MnPJKlnOwWS2SIScx0hkcvV3mXUzN0HcSAuBoNMBYZxsADittVXcT/XcPKE/PltqHowkTYLcMkOMoml52+wr9jnIZAJZ8XjYGe0vaUDSdsBxnulsqrUDRdMLReNHg8tYhOAs2M2HdQiSVBqChprpI7/9q5JPYKv3OfxL1n52ATYYBAAAAAElFTkSuQmCC"},{"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 © AGIV","best":true,"icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAABm0lEQVQ4y6WTPUgCYRjHf5oFJVfRUZKVHYFBoBAUFLZE0FBD0NQHRENESzS019LSFNHWx1DQEhGRg0JFREM11FJuLWem4GB5HULdwdkgHprn5LO97/O8v+fj/7y2bDabpQKzFx5S6ntlgE81xvHtclHAbuSNloNT5q/uywP021cAvO4hAPYu5/hI5e6GWpsBCEfjxNSMNUALPvJ7eA3AQPcML3KIzbNhlvdEWmu+6RCcAISiCWtA3fosPztBfrYvAGgX/QCIggdR8DDe6Qbg5E0uAdjyKhhykq+uBeySi9qVCfSAB61HRBQ8RFJpRs6vALiZHMUnNpYO0Ujn+jPkJJnVfbTBNeqfFQB8YqP56H8VJqBKcuHcWsQuuXIOyUX1sN8MnPJKlnOwWS2SIScx0hkcvV3mXUzN0HcSAuBoNMBYZxsADittVXcT/XcPKE/PltqHowkTYLcMkOMoml52+wr9jnIZAJZ8XjYGe0vaUDSdsBxnulsqrUDRdMLReNHg8tYhOAs2M2HdQiSVBqChprpI7/9q5JPYKv3OfxL1n52ATYYBAAAAAElFTkSuQmCC"},{"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/","scaleExtent":[0,22],"default":true,"description":"Satellite and aerial imagery.","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEkAAABJCAYAAABxcwvcAAAGsklEQVR4Xu2aa2wUZRSG393Z3VKhW0AjQgvhjhRMxVoFSkTSVhJEGqUkECkXQSyoiBCJicYYo+GPiAS1MQREMI2GhGI0UQilJJSCFcWqoDYol0ChEG6lLdu9et5vu01ZWpg0nZ3dMM9msrAz03SenHO+c76tDe+tDMHittijP7C4FUuSDixJOrAk6cCSpANLkg4sSTqwJOnAkqQDS5IOLEk6MEySzWaDLfrDBMUwSaFAgKag2e0JL8sQSYyi+1PcSlSguQmhUFB9bpfPeSSaNEMkiRWsHP8kKua/jFdycjHA3RsI+BH0eeXwKYmUlSjYDNlPEkmbC+ZgYWa2+u81zw3sO/kvvvrzF1SfOYXTVy6pa+Byhd/jHGMiSfAx1YJB+OVI7ZGMggfHYnvhfFQteg2fF8zGQ2kDYfP7kQjJZ5gkplSkaDNWghIxAalNaSmpWPLIBOQNGYWQ3we7/S6W1B5qYA3SbHYlyxcMwCOCEoWYSGoPZTntWkIV7phLSkQsSTqwJOnAkqQD0yWxfMd7CTddkp8dt6x0Dlnx4rWxNF2S25Wkmkp/03U1CLOXirdtFtMkUQSH3mF97sXXsxagKDsHfZJ7IuBpRkiG4JCMM21du8k9lWmSFPLwJ69eRlb/dGx9di6qZa77UoTljhiNlKQeSlbgRrMSZmYDapqkEGuRw4krDdew/qf96rPhfe/DvMxs7JlbjCNLVuH9/GcwZdRY9JSU9DU1hLdZEO7aY7kvZZokhRKlYfeJWpxvbFBzHXcNyDAR9takPOwtWordz7+ENU/PwmODhqqoCu9LeZVoh6SjZnCEmS7JJVFSW3caFSePh6Oj9XkpgML4PnHgYLyZk4vyomIcfnEVVoq8Ef0GwOlwwN/ciIAIMxJzJaE17ewObPqtGiF5cXUjLNaMElrjvhS3WXqJ0KwB6VibPwPHildjR+ECLMvJQ8YD6YamnumSmGJwOlFx4jhqzteJjFBYXCt8eK5wlEeJPMd7KHD6yAx8Om0m9kiEPTl4ONDiUdd2N93/E7sAo4Y1ZrNEE+sL95vai2q7jq/Wok0YYR6/H/17udGvZ4oYDxgSUfEhSaWcHduP1eD3+jq4NEdbb8Q0u1VXGEYNIyqykWfUgBMXktR6JkX4vCzzeVs/w+Lvv8Ef9efUOdWB33T1rYTbgTtd1XXiQpJCokESCRebGrGpuhKPblqHeTtLsfu/f3CZDSUvib4nRsSPJFCCrG7SYDqTkuGVxnFb1V68XfEDmlubyI7qVCyIK0msMSzGPk8T+qWkYt3MItV9p7tT1fm7bixpT2TM4JyWpGkonjAFh15YjhWPT4abM1z0DVGoNsJATJWkpnx+zSTpxGN6xsMon7cUJdMKMbh3X/XwfHUWPzzPIyzZuEcx7iffAdUcBgLwttxARv80lMr0XzZ7EXIGDlHLfuThO1u1mJY875LI+1nGmqMX6lRTakRQmSbpmteDVGkA1zxVgIMLX8WcseNUz0NBFNhR/Yl8E0xYv7jNsvzHMkzasgFH68/C5nSp+7sbUyRx9JgzZhwqFq9Qg6tbVrO2h+8kbfjw1EZ5LdJlf1hVgclbPsGGyj3w+qXTdjCKDAgjmCSJo8fUYaMwTib5yKTfUeQQPnYkush3tUcxYfN6vCERdPrqJTiS71G1zShBxBRJhAU5Mqh2tD3Lh2bEqQFXBLHuPLf9C8wo3YgjZ0/B5nLBLtGjJEff3M0YJimyMnUGC3Jn0cOiHF75bLggHfjru3Yif2sJymoOS1o5VO2J7AbEAsMkce+HIu4kqz3qWjlYlNlllxyuQtbGtfj4QLkq9EwtLl9GplZHdLsklTryEDv+qkF903U4tfD3abdLi/b9Du9n3cnbVoJl35bizNUrsLt6wGbXbvszjMSQPwdUc5b0QGnSEK6eOAXzM7ORqjpnRsHN4wVTK7JRduxiPd7dtwtlf9fA7/NCEznUEuvIicYQSYTRE+Iej9+H7EFDsXpSLgpHZ6pz0bLONTZgQ/V+OSrR2NwIOFzQtPAcFw8YJomovoYNYksL/4GpIzLwzhP5mChdNQnK0r7x10P46OA+1J47CyQlqesZOYb9Ul3AUEkRmE5B1hOvV4IkCYuzxmPGyDH4oLIcB07Ugr+Gw8Vu2fzU6oiYSCKRblmlEP9eku+aQ+1I8vNYLeddodtXt86gAkYKvyKySzRp7JRlICXxLIjETFJ7KIURFY+p1RGmSEo0LEk6sCTpwJKkA0uSDixJOrAk6cCSpANLkg4sSTqwJOnAkqQDS5IOLEk6sCTp4H8Lf75Du1VW7QAAAABJRU5ErkJggiAgICAgICAgICAgICAgICAgICAgICAg"},{"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","endDate":"2013-06-01T00:00:00.000Z","startDate":"2009-01-01T00:00:00.000Z","scaleExtent":[9,20],"polygon":[[[-123.3176032,49.3272567],[-123.4405258,49.3268222],[-123.440717,49.3384429],[-123.4398375,49.3430357],[-123.4401258,49.3435398],[-123.4401106,49.3439946],[-123.4406265,49.3444493],[-123.4404747,49.3455762],[-123.4397768,49.3460606],[-123.4389726,49.3461298],[-123.4372904,49.3567236],[-123.4374774,49.3710843],[-123.4335292,49.3709446],[-123.4330357,49.373725],[-123.4332717,49.3751221],[-123.4322847,49.3761001],[-123.4317482,49.3791736],[-123.4314264,49.3795927],[-123.4307826,49.3823866],[-123.4313405,49.3827358],[-123.4312118,49.3838533],[-123.4300415,49.3845883],[-123.4189858,49.3847087],[-123.4192235,49.4135198],[-123.3972532,49.4135691],[-123.3972758,49.4243473],[-123.4006929,49.4243314],[-123.4007741,49.5703491],[-123.4000812,49.570345],[-123.4010761,49.5933838],[-123.3760399,49.5932848],[-123.3769811,49.6756063],[-123.3507288,49.6756396],[-123.3507969,49.7086751],[-123.332887,49.708722],[-123.3327888,49.7256288],[-123.3007111,49.7255625],[-123.3009164,49.7375384],[-123.2885986,49.737638],[-123.2887823,49.8249207],[-123.2997955,49.8249207],[-123.3011721,49.8497814],[-123.3218218,49.850669],[-123.3273284,49.8577696],[-123.3276726,49.9758852],[-123.3008279,49.9752212],[-123.3007204,50.0997002],[-123.2501716,50.100735],[-123.25091,50.2754901],[-123.0224338,50.2755598],[-123.0224879,50.3254853],[-123.0009318,50.3254689],[-123.0007778,50.3423899],[-122.9775023,50.3423408],[-122.9774766,50.3504306],[-122.9508137,50.3504961],[-122.950795,50.3711984],[-122.9325221,50.3711521],[-122.9321048,50.399793],[-122.8874234,50.3999748],[-122.8873385,50.4256108],[-122.6620152,50.4256959],[-122.6623083,50.3994506],[-122.5990316,50.3992413],[-122.5988274,50.3755206],[-122.5724832,50.3753706],[-122.5735621,50.2493891],[-122.5990415,50.2494643],[-122.5991504,50.2265663],[-122.6185016,50.2266359],[-122.6185741,50.2244081],[-122.6490609,50.2245126],[-122.6492181,50.1993528],[-122.7308575,50.1993758],[-122.7311583,50.1244287],[-122.7490352,50.1245109],[-122.7490541,50.0903032],[-122.7687806,50.0903435],[-122.7689801,49.9494546],[-122.999047,49.9494706],[-122.9991199,49.8754553],[-122.9775894,49.8754553],[-122.9778145,49.6995098],[-122.9992362,49.6994781],[-122.9992524,49.6516526],[-123.0221525,49.6516526],[-123.0221162,49.5995096],[-123.0491898,49.5994625],[-123.0491898,49.5940523],[-123.0664647,49.5940405],[-123.0663594,49.5451868],[-123.0699906,49.5451202],[-123.0699008,49.5413153],[-123.0706835,49.5392837],[-123.0708888,49.5379931],[-123.0711454,49.5368773],[-123.0711069,49.5358115],[-123.0713764,49.532822],[-123.0716458,49.5321141],[-123.07171,49.5313896],[-123.0720308,49.5304153],[-123.0739554,49.5303486],[-123.0748023,49.5294992],[-123.0748151,49.5288079],[-123.0743403,49.5280584],[-123.073532,49.5274588],[-123.0733652,49.5270423],[-123.0732882,49.5255932],[-123.0737116,49.5249602],[-123.0736218,49.5244938],[-123.0992583,49.5244854],[-123.0991649,49.4754502],[-123.071052,49.4755252],[-123.071088,49.4663034],[-123.0739204,49.4663054],[-123.07422,49.4505028],[-123.0746319,49.4500858],[-123.074651,49.449329],[-123.0745999,49.449018],[-123.0744619,49.4486927],[-123.0743336,49.4479899],[-123.0742427,49.4477688],[-123.0743061,49.4447473],[-123.0747103,49.4447556],[-123.0746384,49.4377306],[-122.9996506,49.4377363],[-122.9996506,49.4369214],[-122.8606163,49.4415314],[-122.8102616,49.4423972],[-122.8098984,49.3766739],[-122.4036093,49.3766617],[-122.4036341,49.3771944],[-122.264739,49.3773028],[-122.263542,49.2360088],[-122.2155742,49.236139],[-122.0580956,49.235878],[-121.9538274,49.2966525],[-121.9400911,49.3045389],[-121.9235761,49.3142257],[-121.8990871,49.3225436],[-121.8883447,49.3259752],[-121.8552982,49.3363575],[-121.832697,49.3441519],[-121.7671336,49.3654361],[-121.6736683,49.3654589],[-121.6404153,49.3743775],[-121.5961976,49.3860493],[-121.5861178,49.3879193],[-121.5213684,49.3994649],[-121.5117375,49.4038378],[-121.4679302,49.4229024],[-121.4416803,49.4345607],[-121.422429,49.4345788],[-121.3462885,49.3932312],[-121.3480144,49.3412388],[-121.5135035,49.320577],[-121.6031683,49.2771727],[-121.6584065,49.1856125],[-121.679953,49.1654109],[-121.7815793,49.0702559],[-121.8076228,49.0622471],[-121.9393997,49.0636219],[-121.9725524,49.0424179],[-121.9921394,49.0332869],[-122.0035289,49.0273413],[-122.0178564,49.0241067],[-122.1108634,48.9992786],[-122.1493067,48.9995305],[-122.1492705,48.9991498],[-122.1991447,48.9996019],[-122.199181,48.9991974],[-122.234365,48.9994829],[-122.234365,49.000173],[-122.3994722,49.0012385],[-122.4521338,49.0016326],[-122.4521338,49.000883],[-122.4584089,49.0009306],[-122.4584814,48.9993124],[-122.4992458,48.9995022],[-122.4992458,48.9992906],[-122.5492618,48.9995107],[-122.5492564,48.9993206],[-122.6580785,48.9994212],[-122.6581061,48.9954007],[-122.7067604,48.9955344],[-122.7519761,48.9956392],[-122.7922063,48.9957204],[-122.7921907,48.9994331],[-123.0350417,48.9995724],[-123.0350437,49.0000958],[-123.0397091,49.0000536],[-123.0397444,49.0001812],[-123.0485506,49.0001348],[-123.0485329,49.0004712],[-123.0557122,49.000448],[-123.0556324,49.0002284],[-123.0641365,49.0001293],[-123.064158,48.9999421],[-123.074899,48.9996928],[-123.0750717,49.0006218],[-123.0899573,49.0003726],[-123.109229,48.9999421],[-123.1271193,49.0003046],[-123.1359953,48.9998741],[-123.1362716,49.0005765],[-123.153851,48.9998061],[-123.1540533,49.0006806],[-123.1710015,49.0001274],[-123.2000916,48.9996849],[-123.2003446,49.0497785],[-123.2108845,49.0497232],[-123.2112218,49.051989],[-123.2070479,49.0520857],[-123.2078911,49.0607884],[-123.2191688,49.0600978],[-123.218958,49.0612719],[-123.2251766,49.0612719],[-123.2253874,49.0622388],[-123.2297088,49.0620316],[-123.2298142,49.068592],[-123.2331869,49.0687301],[-123.2335031,49.0705945],[-123.249313,49.0702493],[-123.2497346,49.0802606],[-123.2751358,49.0803986],[-123.2751358,49.0870947],[-123.299483,49.0873018],[-123.29944,49.080253],[-123.3254508,49.0803944],[-123.3254353,49.1154662],[-123.2750966,49.1503341],[-123.275181,49.1873267],[-123.2788067,49.1871063],[-123.278891,49.1910741],[-123.3004767,49.1910741],[-123.3004186,49.2622933],[-123.3126185,49.2622416],[-123.3125958,49.2714948],[-123.3154251,49.2714727],[-123.3156628,49.2818906],[-123.3174735,49.2818832],[-123.3174961,49.2918488],[-123.3190353,49.2918488],[-123.3190692,49.298602],[-123.3202349,49.2985651],[-123.3202786,49.3019749],[-123.3222679,49.3019605],[-123.3223943,49.3118263],[-123.3254002,49.3118086],[-123.3253898,49.3201721],[-123.3192695,49.3201957],[-123.3192242,49.3246748],[-123.3179437,49.3246596],[-123.3179861,49.3254065],[-123.3176032,49.3272567]]],"terms_url":"http://imagery.paulnorman.ca/tiles/about.html","terms_text":"Copyright Province of British Columbia, City of Surrey"},{"id":"lu.geoportail.opendata.cadastre","name":"Cadastre geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/cadastre/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/plan-cadastral-numerise-pcn-webservices-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie","icon":"https://www.geoportail.lu/static/img/lion.png"},{"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","endDate":"2015-01-01T00:00:00.000Z","startDate":"2013-01-01T00:00:00.000Z","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","description":"OpenStreetMap use only. City of Cape Town Aerial ortho-photography of the municipal area. 12cm ground sample distance"},{"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","endDate":"2016-01-01T00:00:00.000Z","startDate":"2015-01-01T00:00:00.000Z","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,"description":"OpenStreetMap use only. City of Cape Town Aerial ortho-photography of the municipal area. 8cm ground sample distance"},{"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 orthophoto 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","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","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."},{"id":"DigitalGlobe-Premium","name":"DigitalGlobe Premium Imagery","type":"tms","template":"https://{switch:a,b,c}.tiles.mapbox.com/v4/digitalglobe.316c9a2e/{zoom}/{x}/{y}.png?access_token=pk.eyJ1IjoiZGlnaXRhbGdsb2JlIiwiYSI6ImNqM293YnJ5MTAwajIzMnF0bmV4dnV1MW4ifQ.psvzzOez33BOH8xmRiJZWg","scaleExtent":[0,19],"terms_url":"https://wiki.openstreetmap.org/wiki/DigitalGlobe","terms_text":"Terms & Feedback","default":true,"description":"Premium DigitalGlobe satellite imagery.","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMQAAADECAYAAADApo5rAAAgAElEQVR4nMy9a7Bl2VEm9uU5595bt6puvd9dVa1+6k3rgRCSQLKMEDCBAHsEGptAGE948Bgz88Nhw0w4bBzjmBl7HDE2EzM4PGZgAIMNNkYEDKDBIARIAoQeLSG1uumu7uqq7nq/bt1b9738Y6/M/DL32vdWYzw6u6PrnLP2Wrkyc2V+meux95WFd31fAQR6FdRfRYuF7ujvAhSpdQsgUusLSikQ6e6hfkcpKOJ9AIBo/VBaINRfqd8jd17Lf8HqgspCy8pm6K0Km4pNCYUqimQukHrs/mn1kcuoi979QNsGo02rRNVXjTGf3e9ePRoj2bZe/Oz1a+0j41omLR53+vwqyzBqDoR9casohe6WTmrroPiHVKcA3BkgYgMsXN9csXT3itBNN+lKDp37CUSZLahKIPrGp1FGIQYLeaBIdWhSQnGmjIoqXukYYIQr4IoXCfVPl8oQnaEow/qBUoZl0KZhHKoM3QAL3S9WjwGro+P1CtHLn8a7lhMfYgXFxqtU+mx83m0JKpsWGUadSZCFEdNqHGrodk+otoj9dmSQrhK5paKx+5WQkmpLikjqG2agQrwpkmQEQHHe2AZL11c22FJxxepKsahVTCvFBpadjEe4pHtqyPpbqtu5casuitdXPs2r6XNABuOwqB7EeFMDLUX5T9G4Wg3zqarOZd0n91VcBi1HB2gWu4WjqttXMGiZPhlGqKFGUFCKCyAiHpoCDyV0CL1vdat5mGEWQ0o1GTKrDvOLO5wyZ3XFfN946OxCjK7dFa/p5WpYETn0rnQj6b/pm1LreCjkky6Dyizqt8Y3NJDaIIoAUgqhktQ2xXkWgXDvso0M4nX0vusZNeIqx8S/RnCAxpiN1cdd6Qn15WMSy9lQAv8SywKETJkMk5hjVRhns0ioChLUWfLymJu5ZCWTMWQWiFDmKNRAnaT+o4KZaTBzAsCpIJp48Win6Z71UarlKiB4lLDhU4dlRDNnrTWlmMyayypN0xWlj2Te1BOXlV55loGCB1AEnnGqx1XaharTgMd8Xex3Yd2bIgsNIkd3Zlvp+fxS4dZl6I/rNMkwcu+IA9NLkY2MG4Xxqy0FYaA6BZFwxjQRkxgzDHlpzAOuEGOOIqlOjxUx5HUfLarnwEPEMUIym8go0zQIhdsb/Ft/wTlrbsCmnl2CuShlWIYuChVjS5iizduU7443Q0YNYdXZu2o+mKZ7YVmE+CpG3/otfSlQXIZSaXCEmDYZRoZVRf9hB+w80OYTNFg296Q2yrCFd2png671henVT8rVJd9TmpQWmYqkjbU6Go5Z8b4k/LKQa23E5dGvqkDTDzwkB9rcR5WNUjPWSXFzCXqSUjq5t5FB5xYEZZZmaWTLE0udbzEGampDawrk28XLRdOSKoP4yo5Uw7ZITuUC1R8h+BTKYKtMKkkpahQgb4rLjm4QnYGqpxvcWhsaPpvEqNc7dGqELKpFSih4IspCRkT2ZVZH1IhIpVBkMqJdiFXa6mxhibhEgCqmJ5gzMYqXGgVsUqd9WB4pKFJCVGFJTIaqVNVZUwYwcKH+Fr8tcOmMp84xi8lF4FV1qfM+BzafT6LWs/FnHmiQOHXuutE2KoMvVkyTDKMSDN4N33cB1IPcpW0gCQn4N4qia/XsoqHKL7M581oPaW4c7mgWlUqxfsycKFTHeYaVOu8WSqSmZVrbhikglcGOMSz24askhfrs2nB+avMY0g3zWSyOaAPPi/uxkgyFFV89t6gMjmqdsYlYWqxjY3pQjy/eq42H9ekg5cjqJQrVtjonJcmPYEM2J5syGUYRo/qmFASAV+N1cSgSFL4PsrPCTcElTFZv6GpXCDpmbtFhlIYqMfCMzoEUDTxgEYxBEUNqyiaOOEazGMq7IzJzTK/v0DbxE6mG4sut+VI0DMg6IIONiVYW3aPxSMLqdYMszrJryhkm3hQ9LdoTYLJh6Vexwff83xYTGFegwDBdMozisPiASs9SYzWhQVPyERWJxwaDlnblcsDnC7nfZI0c/qIRuw8VQ66WECHOOF3h+s4k79h0BbTsB5UzqjnL7OimDFbdpVUM5mBIhhYIUG91jNjJ8yyk2DiE4RbltY+ongsGwRAm10a+OOFk5NMqwygyuY0TmIwlerkEetYDCxrNqLImbQQw9Gv3Hipq2NXvITwCKGqw3LqDXRRDsk4IM2jaLbfAbJM6Rxb3Tv9lfIU7ceIehyajq0vOSdiQDApMEXQKdFM0c6a0HECkjkMySbMXDvV8n1d6SC8+cTK9NuNgBbEyhTKMAAR0yrt5bOh+fqREaIeGP0Vm6Q94ECcJV0os5VyzytIJ5hl//xSU/6tteMXfB6nUsOwrRVJ14ImMt2N9eE+KVjqgJEN1Nkc1501qOqD27BtuQm2K67UgGlWSgcvVSHgu6I7E+XgloTNKINSzjnuLJUzH2WmOMKcKTRkqSEyhDJPKghOtlX0y7MR0ct1tu9OGCC8poMTJqtIA7ECf1hfycFUSlBNykpBiwI1KlIdKz42sJnSlqkngxk8TNRRXjq4C2dyuis9Xgdkv2NhNbwWkbFqxA+lSvF8bDLYLEK/meEMyIPZJ48TpikCoHf2GL5Z0KYeYg3fD6vf4CnagSGv5ry5FU59hMk1gS4qdFhkmmiJ4B13rEoh42NKczp0BPriiNWB1IWREDSYy/dI1NCq+XOdKcxRxLWuZGxn3VZXFDieaNhVXoonEjuIDqW3jwIRRNd2oUUBTA9aMpD6MHsU06q+r05ehN80Lk7ioK0/FGJ2ZHnenoMjjg6BzIZ2bBnjcuD7zZW3b0eWrLcOo1I51EIq4Y5TCDWH/x3CoaFaoAoECexYZta1G8ESp1ChSnBaZMBSS2U+L1SeH5rbkqFFvDWcoZJwqOzm+NstoZgfPDNW5K4kIWmnyGR2PBLX/kvodkqHE76IRmnL5YCwl9uX0qQ316X0orOvvalwl0Tb5uu/OB3oOzuM0TTJMzJDrgHW8q3cxQXY8CUKyxxeUcFjPxjVHhhbipggTCEgXxzR6ZMTkf912I6VSFcHHVTzb0xUjR6EYJt1xWmkjy6e5a754taSjI2ZF8QiN1yWw68sgPAg+dlL54fSMQ2Bh/iTYh6vcEIpQXulqDKzMBTWpjJnxMA5VR0L1p0SGUVjXr0ZJm8gKvh1fZNwaGbRO1IdE5uBe3ZtwgYRtas/BQFR1hOjR6xEmyZkOO5A5jRq4Cql1FdmpXx8TdT93Q04PRPlKl9HT9Eg6hMoRx/pv6KKX+lX5ewsTia9sK1wQ+lJ65rwNGRRxVX5C8yBDQwdBNp0fTZEMI5+EOsfOrA5AqeWOZiV80vhz7s36qRZVQA4n1huCYyK3C/rkc3UdTa5j6V9r74F0o6mWsiyqwNin7266VzqPHDqJrvhCxaCfD5T3mjRAtvCXCmIZg3oT72wYLcsDbPyCEWZeqzUWBSIzAGfE7K3Rl+tNpk6GkU4EAfXQevCKiOlqfqE1ehWMHSmuDFX9FAqKhdA2y6TGWb3bEKCzL6vTob/fK+m3nXy1eVB0MQdyGgE9MUmIzwos6bvzTu21TOrxNfOHfqQyPgY81lPVTqghGdhYfKmbeVZhQYPQl6krCK1DX7pnEOYEKqNUYpryhlUdIXouT9z0nS4ZRqUaQuibBSNezMq1I3o8zQzMmGX0zIwkQzUjU8VGYYLnp/xMuB/Wv02WJbZlhWnqh9SWUsJOLHcudlTSq7djnjhFrPcTplg9k0sSbcg2MqheiKSlLamepEmnokkYJ74dx9ZWdUrdrymBUlsfPQajjUyjDCPPodnAkbxYx6pGEsVSRgcgGD0vKVrHAlrGdJwtBou8LR8PSjgjOnFFdR4x46WmVR/eXidofOSsOMlqs+ogQn11ii1Eu1iY8s/urJOOJaVt6lyVX2G+jF4ylDTRHpTBQ4mnGyZ/to40nhV4er6pdAmEijpy/S2apjqxRneJttlmNvLpkmGkDGjeTOAXPiv29dmixE/YWC3C6OS0sxZFWkZNLevSbw6vsO9k2jBjJmczUOI0g0jYRDilN0pSKq8qktLU1a9uIsby1whEOpGKgJL5B3yiXWhlSu/RDwcEFd3ptGTwianSIR6pbdz3MYoISQrpP0d0j4wlTn5LvMdAp+mvH8UGRcw4vtMiw0jqAEk1om7JVIeluoE2AJ1R4vFmcOPwXu8xoheNHooCInasVxT1a8QIKzcmoLj1JxTwaEVr/6QY0jvpz4TrnBLFxoAn1CYD1K4L0Sr0DEXplmNpYqf9AtJ41qLmtpoOEK8UfJsyFK5Ao2uRjuVXsGJoSemnRd00fnEJXaJRMqrniybL4b6O+xTKMPKQxSZvFkffNa0q4GdfC+gTBNrFBzEwD0UNr1MfCqtlvoPMwUIdSesrWxpZzEGoXzVcR5Dq6IRaira2Np4XDkpdkoWQPLobXWz5Lk7soyOaMwt9NyeJ0ckjriZeMihDb9OQZeD5DhTcQDpNR28YKUrUUbhYPYy8yjvivaa3aLsplGESYAjKIFm1OUUnQVe9cwodYAhoj6gyKR2tOJjuqRL6Ux6Ll9gEUoKee5uAhMwdAhNNZY77LtqONeSbakX7oPDMRyvCBqOpwXWoBh/2F1QXLR0oLeXBb7j2ZUgGBzGmxX1wvZ4e69h0m1yk/WoCvGcUj6TY4JEKq7FqyiiIdYmG/RYnMS0y+MZcHYnOMWtoV19wCHAES14WpzbulTx54V1dUyDrM+XGcYUGFiqE7nsIlfCKF4cRNC5R9dc6XT8BqTMf1Fblstq0mlHUEYKiCVqKn6lFGPhKl6KK7CBD1FMCNdJ/0AdTEJcb7MBE3iISAZeWR4rKfyppoHnxwqmTYWTVhb1PjZWbDoyLtVXGggc5AylF4HsepFibEtpUqKTyaJgx4YYjTXXcODllXXnMZBeNS50g1GLmqW0htri/KkOvWYrMgTnlIoFPlqEHwaaugjQE/bHbLo3I/Aw5JBuojk+jGrfvrUROmQwjHizDLhGfqWcmaweWsqWOdKy7ex4JIrPRadz2KCIAPYVsf5G3MT27GySgPF7MsIMzs1wKFiyPokgH9dVXnYe0xeQfNtGMqBd0NSB6lsFCTykRmgldUSftnlmW2FblilbbY9159Dp5JznS074rR5YmUkpVpk+GiaU7EpevSs3hLa9VJvUbAajnA95JXiLzTS06chuciaAQ/bmHy196xmQQbLLAJruJbeO3lQbZ1xKL2JDtd2Y5kbJ8Wagwy2aWQQ7UAoPET4gOpXWT6SQttpJnpaOG1Uo7LK2h/lTHNvbUyLEzGCA4onPfUyLDSOoSoR67tYsMWgBbetXVFHVIB8pmTEqCed+mo0rY7ZcMT6lm+dWhk8N1VZIismFltAi3KZplvnPkUpmDszjS9M7daEN1RpIxfOf+e/f7MvSuHs8llvMKFw8EA1RJ9cN9GgyVOfdpPJMiVU9KPwHwtMhgz1T31t8pl+UVraIELM1wx+z6VCeKhtmtODkjfsbJETLn3bWUFBIjFkcBTifiUpySLCa8v7GyrixVBTt6kFDZESyVjKtQOsiuq+Kf8HEYBI5kG8YXO31DBq4fELLUPRXTiwth53rI2YbAoYTvRN/KxAGtqMwtRyAa+j28WnI6ZBgVtXjx5c2wTAp3LIsQqN5tRwzMghEkpN8MEF0jPz3rfYl3wiRp8qU2oqtL5hPVUPRepm6IzeG3OqIeAbC+WAoybr5v+xXhUVoHHMeN6Jw5jQS19Rk5bE4SJtJZBgJEPUtmTiQqG92nurrzHiJrMOaOZ4HLEPZKbFGjFqlta66vv3WsGCjD9+mSYeSTwaLwH84A+WDwD/UuX/ktwYI8ghiCZ0RzK3aDtifwJTJODNguehXIJ1pQTzFZbU+lKkaRwXfOWTAyTFYc8lyoIQPTUTLkpMYvXyWVKaspP95WBtMDkxG3RENCEsxoIfKl/h1AMSM98x/R3dpQ2uLgEA20ycOUyDCyAGHeFVFL2TdWFJqqE+QdVN9ijx3ZikKt23qAhyJiaktHd/VhCiNVopUab4kYrQKECSzT4r7ZUVRxvNLBY9jHD6sfIDAPQBqgFhkLBYMylL7uMkiYHCCDdecKvFi+rf9XfbJT9mQtbjucPzMdTgHDK2amS4aRepTzUpHJA4a3ScR6E3k2mEqH1+/dJwzCqePqSNy8oomFR+Yk8ZatU+h7trQwea7/G29NqwQpNtZTcZx4od3yGD1CXUFPBmG+8tWSgVILNzquS0wGI/BBD/oGnB4ciLrhChoN9bxIGJ6TgcSde9fldMkw4pTDowXgB4zgKJyXswKyqjLEfpqSgsJUcBeiM8bYzq2HvVUFSBAk6TfxY2RKUkQSQYyFDOE9pgJbmd14yM+bFNLFkM+1+OqQdECGnIZZCpn4FlJnKu+fHnUG7IAkMRwWHlywaLBZhbn+gMzTIEO3U615NwoxI2TjbojBZhIqUwjoyV9SoUWb0k1/g/Fk+k3kMDZjGy3XlaPqxxDEoxBm2wWmg6rxcLKUaPX7oAiokUnbSN3crLoXk82PnvQUY8qiY/IiO8rg7VWxcTLeHARKU/LqjOrV5Jfcno7fSywP85xalFIQ02VzafqrLMOoupEnGgXwZa4Y612ubLnsvbWtGkr67OrSQS4A/uggSc1OXK1BI5f7nRtHXNkofhYLdTxsblOYTZMZVNY/8yJNJOrGWnXEh9Iqz1VhFjirEcRz+j6oLoA6DkfXhgzspUX1qTzQ2CnvOvDqXToWDYSNfWjfrvLQQuh/Lub5nQFX8aCu6DpFMozsL3gqkfAjrKJbWaQCtV9CUjZ+ekbb0NStNxpn7Mr2IFLqIxX6zcNjb66wMN8RN8geLHX3I/gUioyRryy+fudTluavqY4PrETHVSStHpSf5WjLoJbFXaR2dDssNBhYcIUkl2IFg4Hpg1GoUFuXwdLWLEPob7pkGPHNXjiPEFsdmB7sIBE6XhxJGWW1zyBZNYieIL3Y6Chb2DmgfTCK+KOb3gcp0pSUFMh6ykiXVNFL5/hSxIOjWS+UpwbSE5d1RKjYkMEm1tq35mbqnKD+C53b0fEgtAzyljrONUo1ZWD0Ntm1P7pX8rJ1ROtpk2FkD1FUVFKj5/r8Q9GeD0VZiOtxxZ+NSyOH0tD+w71i/bqDM2wXBEMEbE7Eodj3NRCNsGXYpIPsIHl+DfCAaQdep3kgL3Tkn81B20YGizShWUJbvc8gwaz0nM2dTp2xy/Wpk2CEhPAlK9SQjOZaDpp23m2KZBjxfQD2HKz2JkW3n+p3YVruOBYAijqIxNQhyZmPJbgTqkEJ2YLuQDf0NbBKUYICB/TdNG7c1xXjI4cYBHmZ5QAbDVQLObMWbyNDqQgc0FJlqIah38NCAUqilx7cIb0rOxne/BxXR7szm7hRanUVbIsnq/6g1XTJMOpNSETozX3xpKuegAVNTIM8OmFS6YQNPFpA79yQLgeUAl6CtajYq6sMdL8La5J9zWQurhUjlTyWvvPgNaMBj7jxTcNT+zGwoDHvGOI+QTfrPeW7lEEZnLYWCoIe2Q1DaPN6hesVgzJLny3a1ojrWCLGp4534I/SYZtcSycDR/Bpk2ESxgHKt1uUljmw5eMS8Lpq5DQhFPUcuuydqBw2mSSFQJtIpuhiP4lPb0+/RFenYpiNEzZHYT5saAQp4tncKIFIEAB9HdpgWIiVrBbYkfH0eK7TSP0Ui9EU9fisFh+zr7qgMTKg0TEjz9WJe++wJhmc/7kEehpOXAZjV5QCjQd59DTJMCoiYW7byeKRQZ9VJV7JoPTgFC2FshakDq4RrrymP5Log0zr7wUWZv12MVRBQT0tqf/3nanniLUPjVy9B5LYUVgfZJUWZun/EL1IUYVpW//0q1R61pWfPA4MDMhg/XC0Cs5OTw1SdM+TyVL1FZ5TKToZJZ6FAIfmd5pHM99NGeKLkCKfUyLDKCjXWQUnS0UZJvn8ZCKi1yeF8F/q7ISqTIV8EMGa3UkIUVkIQ1AVipDY0i3d4whsU3iufHUeHerASXY8sNEqP/5uHpqAE5xTWhnb0shI6MaaSh6QIRkYnWmlIJgd6aEYSOnNrm04GmM4QjoVI03znFrRuuXnalyG5pyMZJ02GUaWtgSOg0UYAkuwXlAuaJybBoSplK6kt3zGvlgrWmsp5CwJPah/NYze3kIpMfIZi65cD6FkyJUvo+0e7H3mNrmfojKgEXXyEqAPSMt2WlfYM+EUTPlVVLVxc3bcWFwGm0sR+DB7irYuX1/XjuTZSULFXptpk6H7+xCS+kj0bE6gPznH3elqGT8LxUbvXbnBJuNS+fgzf7c2vRtEt9WY7D/MIXSwwNEg1u9dxGQ8/kw0Ut/SEmw7GXIdGsTm+Z4Buj1aua6kgh7thm5aHYb7A31+lWWoZ5mk37ZGBAH8fI5ZZAPLCqInZaVIHxE03bJq4nR0ky8YHD9uamhANDV6iNcNPLEMneDhXj7dG1CiFQkSOaMnhFitq6T/h8qH6lhISZ8ptS0DiBhPEmxfp3meSOsWqltiu4DIOUoy31MmQ3d0QyJvHWPwyCC6/+DWoRtpsT4o1A3FLWdMArMS6nCkUOZKoWcwFMBT6BOG2awIlcmQiKIAWilWLmgolsUiffhDV8k5JP0PKqfv/LjooAy9VSd+ei894iqx3HhSEEn+a1rkFIhTVdMjrRJSNhD5o5Q8dCJTJ4O9l8n5rwY5AG9qxGE7nI23MmDg5jI0nKSfTlhksN/FFMe2bO3DBKt3sxmZO290BPA+ksxJrmi09IBLi746nCAsDOx4tdKFIRnIEWn1PVTRFI1XbYykvmAipzyFnnwmskENJStFDdZaBgRucB+/TIkMtlOt8xld+rNXwMONVjuQXF58a96cApRugVdq/IENV0oxzo21sPpVggaNVtGmSfHKz+CAMDz7+ZhCfXTtVG5SnGq4PubqJyi5L4mpHcKXZjpV8g+mNSBDDxjS6HCEiZtaSpfRN3ZvGiL75NU0f7dv1bMZLK8IMRG4AYogczMtMoxCWKY3aWRUir4Ub9qafqClN3XrnY6YO0/xbyWke4qytthjYU7ApDIChzdsZ3Qt9BkmVvREV8vYggLExiIiV+6LB0mNoh0xJNlBAIMBGRgYepfRct7D3kztg3dzDY1zfqD8FC6i6GdddZXSUKrQQQe2ejRlMozoOB2UPR7fHBUKw14spBDEX4WMprpEjym6b/MF91xbbWoZnHKoLAi1oWXgoJjC7ROsULXQTwPS1P87A6AHi7TcJvrUlg09d5SNQiF2SIa8UsLOyZNCs5+E1NQuGG++1Cgk3y6RDwsJjHguQ3x0tzEPnQIZRuAOdFVJq5rHuRdLdf94jJeF8+MYPMvvHXVgpFbjUSOGb7LEpbzUjuobf/W/YDQWYViBDT4k3S+JRsspSR47IsD9CfqTdTMS/p14DDg1IAMqaATVkjHmCWsDcfubioSabIyBFjPMekD/oj5DZOQJ8xTJ4KddOXSIGzpPZEXLKxO8TR5PfLqB8GZNb23fGE1oaQNfFUZKbMzLo0FZe61LqBA2+9AwPpoLwdt2MsRB8zCgfXLo0DQxh4cUYbVAfboketZ8QAbA/o6CAxfP50rsg4U3HZdYbmzpuCVQBAKKN7A4ysZ1mBYZ6zTJMFIi9clmvymehXFOrl4eUD84np8s9MN5yZh6Rk1LaFxHyZvx5a35fl0WOKRE1VF1IzLkO+KEFLOcRm2lDhQMPDHBkdRoFOvbAxohfiBBgKH1sY0MUHQV7wOUOiQdFPhvT1EZhb1/G30RhAmO+H1jg4ytUB1fDSrOByN1iBDTIUN9c5+Ews7+tFMfM7aFkAKZcw6sN3NRAMdin/FZgELAoF+ov14kQZhQRfQv8Tsty4W5S7jvz2Ko0YpGsjTYQRZDsDq49of7GMG0n6QTcqawJKw0WzJA7aXKIFSoxGwxI93TdCQMo9IpJoIpgfzdHFnIAcz4VReK9PDHCUj1maVpkWEU6NUOunuMSuQU6mgl/SZGfQlMgvMIE9I+SupLUVC92FCE+kS6tB4J2clPCmODU4O2uQ7xr8CeQ28IWR09jmqdLDxA0fHYiIvRhB2DMefUtmE+MiCDsk23HBAqoGlBKfZL7SU4GhSX6aEd5V95DYNOjxwnnoQGQcE5bt6hd02LDHVjjislgyPgDVmCxApWR9iYK+2A2J0xhIN5GTIKIy7YPkh5JTbolcHbV74MJeBlIa0D8SuUxjEd0wNN3uH8NnlACgCipwNKiAZhNS5EiG1kqMoJ8z9VPjoDcbDQZ0OKO2HvT/4ouDAKq2YqOIkbe5in8XcGlIDMDW+YIhlGoCsgedfMaOmR8K6tDpojMz8zUYqYUKIMJ4O2VSXusSgWpCMADYdpT+JB6BJJ9xE1V0BFIDdye8DEcSnwwIYb6XBHSaeUAjKSGm/aRp2V+MkyqO96uaJgalDQjU4SwfXI9dCoJ4Gqv9jY9ocZEa2NITm1zdFt2mSYpGbqP7UCISBAE2RRkHSWS56wVkqKnFo/5cCo5YrUliIU9efqjmoc1N7QXdubAYPaWMfejhyOZfDl2u5XRGcfAG/o/bEM7sk6Qq7H2ZkJ9szvwu5ds9g1N4tdszOYnUwwOzPBaCwYjwJGYWNjE+ubm1hb38Dq6jrura1j6d4KFpdWsLG5GfVp6VfUc6k89PRpoOPgIqEdbEGjO/NWaMC0H9ZHGl8CNNNv/Wa0s018lWWYlIryMUWR+uyDBCQNTqGVzUkqNzRBNgWExyWpPdlO76ivsD87j2ZmMejYXMAcgJSl69zCfamm9Cg7O0vlzZ0J/pRfRXDlpXfmiAZHRLBv724cP7wfxw/tx9GD+3Dy6EGcPn4Yxw/tx7FD+3Fo317sX9iN/Xt3Y25mBrMzY0qdgOWVNSzdW8Htu8u4fmsRV27ewYXLN/D8S1dw8coNvHT1Ji5cuY5rNxexubkJc9IG6LCTmj7JgS2iV7KCoAIAACAASURBVB2oYal90bE7T4fpOx/lsYd1qo34imUPMxOvkZd/4zLsfdeHLbiQL8IP70kz7cvOHRA6NTC8TOhRyEj1d6c/RliiQ5PgZirauhKjtixsYQsRaTTKhZDAaK/ao3K6PRoJzp48gtc/cgaPnT2Bhx44jjPHD+P08UM4eeQg9u2ZDwPJ+zosp17haAj9LgW4fnsRL7x8Fc9duIKnnr+IJ595AX/8xWdx685dOOAwaKVPICrS9JH0m9tU2iGlS2qygc3loH45umhGwOVfBRlk4V0fpiBAiGn0C6UN6TGMYLcaUeC5PN8zhKUb7rbGYzA0oK/MjO5wdGo5I3kjNBqG28EZaFAyz+at3Lj7MR6P8ODJI/j6r3kcb3/Do3j07AmcPnYYxw7tw+5dc1V1ET25fxN1B0cZai8iWLq3ipev3sTT51/G7/3pl/Cbn/gczl28Qipgvesw96zYPxuo47UJGJDGK9VseESjfm7t9A3h/w3JIAvv+nBx4s5yvrhZZIGDUGJLo4b06wywuKOqeqhjsvEmYGOgMrqwg7RCzsA48qrU/PwcvvUdb8Jf+cY344nHH8Th/QvYv3c3ZibjQUPOBs9XdoTtIsVQm61ScHtxGecvXcNv/OFn8bO/9nG8ePl6xZN6CM5S4ipUAoy88hbycdYPkCJB/g4Dku4OWViKEHG+Z0qzMSvW5v9fGWqEiA9ihGO2wYu6zpv2QxHO+gopUk1VdAWK65NDo3q9T40d4XT1Slj5QcjOsz31YqUysYwAKVKxtshhxqMR5nfN4uEHjuM73/u1+ND734ljB/djZjLGaCRxIAau7VKkncq0vNVP6/fG5iZeunoTP/l//w5+9tc/jpt3lrC1teUyqYY5MrPOSA0Y1GWqn0Gr9YlS3+aSaIbyRr9AGq+/fBlsDmHi0LyhKLWC6DCcf3VuHUBB7+mAhs2PAaMxupw7Bp5SYBwwulC34bWGVA0gag9swczMBKePH8YTjz2ID37z1+Pf+trXYd+e3YP9b5WC5XurWF5Zw73VNayur2N9fQPrG5vY3Nqq41gwGo0wHo0wOzPB3OwM5udmsXd+Drvn52y1qSVnC8CGHEivT3z+K/iHP/UR/OmXn8Pi0r0eLQMVS1EKJCILoW9SbQI+vhmzhTgm8WgPT3xbGYWCWD+P+MuUQRbe+WENSKFG6LKUupFRzYkDB/OqdTHUKRHP34fK0PiO9r0mOmcmGBG0Ye67tpuZmeDRMyfwjq95HP/Ov/02fN0bHsP83GzPIDc2t3D99iIuXbuFKzdu4/L123j+pat46eoNvHz9Fq7fWsStxSXcuXsPK2vr2CrdxuRcdYQDC3tw7NB+nDh8AK86dRSvOnUUZ44fxgPHD+HBk0dDnzmNGrpa6dWl67fwz3/5d/BL//qTOH/pGspWhTx7e51RjspS8Kv3THNCOuf0Q42jVOMWpjk0NH1Dh1umy2vOwznEX54MXcrkHLgXVqE8ykUUyBGj8SI6kiudVcrGTLQH07eck21ztRyxE0uRIwKNTqK0zWQ8wmNnT+J9b38j3vf2N+IdX/M45mZnOlXWwdjcKjh38TK+8Mx5PPPiJTz74iWcu3gFL16+jsvXb2Nza6sOqLj6ydHDipnyaf2PceroATx65iSeePxBvPV1D+Mtr3kYp44dhCA6wk6rVXnecmfpHn7zDz+Hf/ZLv4Unnz6Pjc1NbDfPy7qJem4vYoTFjWTn3c+G8de+JBuSB+qQ6TCImpb/EmToJtWJ78yurdX2cva2UnwuFFFqO0QLMvLEqVWhWZAhvk28Nf9hMiePHsR3v+/r8a3vfBPe+NhZWyYFgK2tgpev3cQffu4pfPILz+Arz7+E51+6iis3bmNtfQNu3cLCpDSsfrMBasjg4Rbj0Rinjx/C6x4+jfe+7Q34wLvfgpNHD/UcY7srg8zq+gb++IvP4L/957+MP/7in3fzCqAPSjx+5lhWUMXNluogGRxf0yC1tpbNAGbk0QBLpVU31uj1kwTzfyky0KS6VjBeQtyAu0M1dAFjH9WtocvCGjOfoEIVELSZlBK9D70osZ0ftICoNyBdpZEI/uo3vR1/44Pvw+MPnsL+vbut6dZWwWeeOodf/b1P49kXL2EyGWN+bhazMzNY2D2HmZkJNje3sLh8D9duLuLFy9fwzPlLWFpejaGoxWwzYvbLRiLYv7Abj589iR/4zvfiQ+9/Z5jIA20HGUqxNja38PQLL+GH/sFP4k+/9Fy7X/2itqF2YmKk1ZzGJDbMDXPUCJNgpHFNWYMSbNlEa5L8F5RBFt75fV13Tafrp0mWbljwYzQgL4crI55NYg9XZiUpp4E6Gk5b9bEDraDI2n+tOzszwRsfPYv//Pu/A+9+y2uxe34uoO+txSV8+dxFjEcjPPTAMczNTDAajcwYdUe2VHm3tgq2trawsrqOL527gI99+s/wrz/1JJ67eAX3VtY8lRLeRaUJp90D6dRlEAC75mbxTW9/I/7e3/wQHjx5BJPJuBephybeXAYAz128gu/9u/8TvnzuooFprBdMQG0IoGHs3SNVN8A70WzxqcPPu9+ASNxLslSJMpJWuv1KZLCUycg3vI/2ru2bSh3cIgFFW2BULVUCNFnvXQyozTmE9g7oHzgcCAm98pnJGA+fPo7v+eZ34Ps/8B4cO7Q/IO2wctvLniyv0tBrdW0dn3ryafzMr/8+PvH5r+DStVudYzSvFC0BhOU7uh49cwI/8gPfiW9955vCDjj3v90ycKmT1s98+Rz+03/4k/jScxeo36jP3jywkSol7uOEWwZ4sQaZULJikXbV1oQx2Ncrk2E8d/aJH+tuCd3XyQ1beOeNlgeKE9FORGJ7neToPN2VUw07CBKVUZSuFuv3hlY6e5EgvIfLyijB1aEDC/j2b3wLfvQHvgsffN/XY+/uXY72acBaZVreQlytz/fGoxEePHUU3/7ut+LR0yewvLKKa7cWcW91NcqeE2nOvZMMgODGnbv49Jeeg4jg0TMnsXvXbBiPIV6VX/199OACjh7ch888dQ637y4bDx7FdOxKHA8ethAFKmwGJFe+ksNXsOOIyRmCITjfB0fRWD/y9cplMIfo2rulK/2eoREdpSK1vjuP/nYmwiD1jIlWAKpQjCw8iDDFMj30eHShI9Ovf+QM/ta/9234oQ99C1770OlgwEo7G8/a+gaWllewvLKGra2Cydg34vjiti0nGo1GeOTMCXz9Gx/Dnvk5vHjpOm4tLpsxdYsIrJPSBwX9rIh7d3kFf/bsi9jc2sIbHj2D+bnZZqTIcvHneDzGyaMHsbq+ji88cx6ra+s07Ix89Z9WxNFqbJSA20ArfaAUyCe2DgpFCJihZbU+20Y2bOLplcoge9/1YTrl7KFZiu49sAN5wpSdWZsbhTpgzhDcwNsZgNfJ93JG1cqwBrIuvTe/axZ/5RvejO//wHvwDW96DcZj3/jiiefa+gaeu3gFT527iOcuXsFLV2/g5p0lrK6vo2wVTCZj7J3fhRNHDuB1D5/G217/KM6eONx0qtal9xaX7uGjn3oS//1PfwRfeeElbG01ji6wXKQXB0q/eWj/An7wg+/Df/Z9H8DMZNzjY2gjj/l67sJl/J1/8vP46Cef9JQu9NtaJOEUBcjGYbOAEElq9CuAsIBiHXkDjSCmGonGF/gB4goU2d19yjDpjLjUkAR/BqAnaxTcwSoyn49V8CDElIeYM8H7/TgRroOe0uywRzim3dU5fmQ//sa/+z78tW95J04dPYTRKKJmKQVfPncRv/WJz+H3P/sULl65gTtL97C4vIJ7K6vY2NwKChYRzM/NYP/e3Thx5CDe/ZbX4nu/7Rvw6ledMnbz+j+XAcC+vbvx7e9+K/btmcff/kc/hYuXb9DgkLwWqt0INHr62Auu317ET/zSR/HQA8fwofe/c7DfIScBgAdPHcWHv/09+LNnL+D8pWuuR+WKkY9Qmz/8e7UpHj7L+CSIpjJA55jqLNq3RhDEVE/nrTDeiqeYIRLdvww+qQ4cgwinAaKzSCkyordEHATevj77Qet3ITQISqbvaixaPh6N8IZHTuO//I/+Kt7zta/H3Iw/D7WxuYVbi0v4vT/9Ev63f/X7+PzTL+Du8gpW1zfMQLbLu0Eyzc5McOb4Yfwn3/Mt+J73v2PwiHc3HtEIN7e28Nt/9AV879/9J1hbX6/jMiCk8mAIFysUAU4fO4Rf+Ad/G088/uC2c4fWZ6eXTfwX/+PP4Wd+7eNY29iMOg1RQNmrWYOBXFcqPQHiOSU7hZGE7D0SUO/nyTk48hi9hORQgL9/GWwOYcXqupa7SuycvFeXZbsJc2RSEjM0JAE5OGJp1CxUbnTEnpOq9+MhsI5lH+Ddu2bxgfe8Ff/07/x1vOW1D2My7k6grq6t49kXL+MXfvMP8KM//vP4F7/yuzh38QqWV9a6J9BQHMFMc9oHo7Ub9+bWFm7eXsLvfvqLWFlbxxOPP4g9837sO0/YGaFHoxEeOX0cm1ub3SaZOQ8hSAA1RULiSXVeCpbureL5l6/im77uDdi9a645z8m/ed4zrvz8qz/4LG4tLpsOGEwLj7fEHWAR7oO92eeV5jBSgTfJECIlCCDMJ6TSgNkkPyUH4cUIvCIZfJVJFH39OIHlqVVZ3bJsDLeBYUY2gYW53sTQ0D9utaty8nqzIYSoYApHLKAP6qmjB/G93/aN+Ps//O/jyMF9ALq5wVdeeAkf+b1P47/+iV/EL/32p3D91iKFKphCu76IuD1qV+tayIavdADYKgV/+qXnMDs7wdvf+BjGo1ETpbP+AOCxsyfx2aeexwsvX4sRwRyfQ25d7zPU8M8tFNy6s4y9e3bhra99uDf5z6thmZdSCg4fWMDl67fxqSefqRYe01MIz3dSCFPNkJGXSoMNO+g6yWDpr9ldxAZzCrbwBB5qL8bnfcoQIoS/EsVRnNE9e5p1KpJWikrfeBGI1FSJFaS8SRVXqJwhKAumX7v+X/vQA/hbf+3b8B9/9/sNpV++dgu/8rt/gh//hd/Az/76x3Hp+q3EDynUcj6JitTbKme9L2mkCgq+8Mx5vPHRB/HomROmpyGnUAPdNTeD3bvm8PHPfBkrK2vQKG1zMhFyClqWzqNTBCtr67i3soY3v+YhHD+8f9t+W1GrlIIHjh/G//HRT2B1dc3pk65rQk56IzbC6xXdjmpHrnMbyr4MsT+OGrwiFfkyPrRqKLw/GcazZ574MdeXe6kwKbZBNpYwyJyTspB6mweRBiN0EB0kC8cPAZlDVdqj8Qhve/2j+JH/4Dvxgfe8FXt378LG5ib+4HNfwT/+uV/Hz/767+NLz13A5qZuiFlCGs9MBcCIkSPPw+y5c/1eeVtb38DVW3fw/nd8DfbM72ou6ea5xWg0wt7du/Dsi5fwlRdeMn1pNOhFiGTk2bZuLS7jxJH9ePNrHsIM7WSHyD4QtUQEC7vn8fmnX8BTz79kwBdiAUf9CgQRkf2TT0KDnTibCMtA/YVnJMQNuAjZn84j2LeYzn3KMJ4788SPcZixNWFowqMUnFQ3Ln4swxzIBhru0RVRCw8Gh8LAGFmc5SN+3x0oDuZ4PMa73vQa/L2/+SG884lXY37XHNbWN/Dj//tv4B/99K/ij77w51hc7p4BiMck9DPvk+jg+X3jMa83G4YQPQB3l1fwyOkTeP0jZzB0ZYPcM78LtxaX8AefewrrG5vdWFg/bkThbA/xyyt2axsbEABve90jOHpwXz9SN/jgaDESwWQyxq987NM2HgE0tNBSOG0v4CgQeXV9mS63kUEIBHryAnGCrPXIwGHzWhqnHWQYuYeQIWpHpf4oXSN7UxocnS2lqgauxiHKCssQwlgEiELG5AqSVEvZdF5FBO/92tfjn/7of4i3vu5hzEzGOHfxCv76f/MT+B/+5a/i2QuX62QZxm9mIEwCTcleVmwUOTfWsoRKVV83F5fw23/8JDY2Nl1PZHit/H1mMsYTjz+I17zqFIoNRN+QQ5rGMoiOV1f2J196Fl+sm3YAkFe7hvjQ8jc+9iBe//Dp2Fd1SN8DIH0ofYoC5iQ8lCzSdjIYb9Q3G5ECRTU8yXRzJLoPGbrdKeqjgDbkROz1KzaprQwURnBzktpex5Jva1gtyowOkHlfbeOfKrwvgypqdD92zc3gO979Vvzc3/9hPHjyKO6trOEjH/s0PvQj/xi/+rFPY/neGsmWFElXVE5kqUKVjkYiRUZAI1FEsLm5hecuXMFzFy83c3aWiw3zsbMn8dqHTlekSvw0ZXAdaYqlBrC0vILf/8xTuHnnblhezZty/Ju/H9q3B9/wltdAB9PtncBCUdB4SuNZ1eSpcd/gt5PB9evgU8wAsy6inkr45/5kmACIa7jEiwrjWxGFwlREb8tRMwFKR3wZTMOgp02dQxMi2hvVuF3XbynAvj3z+K73fh3+qx/8IObnZnHlxm38/G/8If6X/+u3cfHqDeN9POqOJkzG3eOak/EY4/GoLsN2uXu33NgtgWo/o9Goe/HtwFXQPSnH8uvjoVtbW9jcKhiPRrh8/TYeO3sy1At0Urp2YGEPHjlzArvn57B0T8866QA0+BHSjemumFF96ovP4Pqtuzi8f6Fp+EPzChHB3vldePOrH8LMZIL1jQ0aLR8HUSQ2oIJH99bR9/BiJq2/vQyhndlFcWMPqRrJYt1XMJOyowyTYny62ZX6r62oaDoEn0DGJyFooAw0+4jo3qoi6e6yKyWTnZ1MsGtuBrvmZrF71yzm52axZ34O73zi1fjBD34zjh3ch43NLZx76Squ3LyNb3r7GzA7M8FkPMbszAQzkzFmZ2YwOzPB7GSM2dlJfVPeDEYjsTdkTMYjTCZjzTgxmYx7b9Hja6tOnu33VsH65ga2tgo2N7ewvrGJPfNzOHPiSGiXI0SeXAPAQ6eO4uC+vVhaXonoVyNj0+BCPVfgsy9ewsUrN/DY2ZO2Q5+voZO94/HIHmd97uIVQ0YDsVb/wSR4nlj/oWHubHlnGQBa+HCD4Y5C8HR6zKz2v70Mky73klCpJGq9yAdaK2YlBFmkn03UupPxCAt75nFg7x7s2zuP/Xt3Y2FP97lvzzz27ZnH3t27sGd+zl73ODc7g12z7hgPnjyKIwcW0G1uCV7zqlN4/MPfgcl4hJnJGOPxuHmmJ//mlZ+h3duh7zu1B/pG3/qdaZ062r3QLM5X4AgYUBgIA6RXrbu+voEnnzmPb3jzazAj48DXTvoQERw5sICHTx/HcxevOGhrBlnISFPKqRhnLKUjDMb2fciAQk5F9VwGW96h/rq2eYVrJxnCu125P95BbPHrIlGgK4CMBAu7d+HowX04dmgfjh06gOOH9uHoof04dnAfjhxYwMKe+e6dprMzmJvp3ms6OzOpr3Lsvs/MjDEzHlsas90xivFohAMLezB0DR20Yzr3m1e3aA0ZfMv4duJHRHDk4D7bQ2nyjLih6WkDaEgU5ASfe/p5bGxuYnam9yrfkCJlOUUEBxb24Mzxw1o5ZiqBExobA0vSQwDNjsmYZWwvg4T9IOWZ+xX2t65cv+f5xjYymIaMUK0UcjGdfUvX7cxkjGOH9uPsySM4c/wwzhw/3IXWE0dw/PB+7J3fFXL1yXhk38fjLjffbhmwtYmVr53u57o7bYy9EuTfbud5J4dp8Z7bHNi7G7tmZ2LIFgdTJwRHYwBsX/4cQcFTz18M850hPlrLrwcW9uDsySOYjEfY2ip2HCd1FxjrltSLPwNjgsL3j1KavJMMMWPRJf8IC6kTZoj4gftVrirARFOODqkdoXfNzuDgwh686oGjeNWp43jo1FGcPXkED548ipNHDmB2ZrJjemDKafweyltNrFSWDa6F6kOhP/++n4gx9LvVT67XcpydUjFuNzc7g8lkHEMz3JACbUF6ETN8wGvRs+cvY70eWmxFhBa46L3JeITv//b34G2vfwTnLl7F8y9dxbMXLuH8pWu4dWepeyv5+gbW1jewsraONe2ndq5THmXGncF5vR8ZisntfuTpkf8IizrUj0WpMC+gtL/Wn7z3a1+PwwcWcPrYITxw7BBOHz+M08cP48yJwzi0b29zgIcMaicDZlpDAzB0DQ3ekLFu53D3K8PQvfuJYENXlqNlmDOTMcZSJ/T1nJUvcCQ+C1kD2Dbc2lbW1nDt1iIOH1gIfOwEQnodObgP7z74Onzjm11nW6Xg9t1lXLxyAy9euo4XL1/H8xev4MKV67h5ZwmLy/ewuLSCxaV7uL20jJXV9ZiGsCnehwy9NKtQWp9DS/3p8QT0ehvNl2DpE+VWmPzLv/dD3RsmtjFgWPv2IO5kfFw+ZEhDqy9D9bcb0KE5wU5OkXloyTfE63ZX5qulKy7b2NzqTr3aDDClSiHWx5vOSuT38o3bvec1WjLsFN31Govg0L69OLRvL97wyBmru7VVcGtxCZeu38Kla7fw8rWb3buqbtzGtZuLuHbrDq7dWsSVG3dwa3HJeb0PGcJNjTYmg6dDfTpULgQuWk4OMhlyhmzA2Ui3SxWyoltovNPKzv2kTPy7xfeQwfHvITocaTLPuT7T2e7aLr1kvtbWN7rddYsC6AGqcOznJVjli8cBwG0zvj4/2+k51891sq7HY8HhAws4tH+vHVsppWB1bR3Xb9/F9VuLuH57EVdvLnbOcuk6Xrx8DRcud1Hm9t17KOk9UaYCRf0QZDr5exHT6qR5Rj6EahGo+02T6riTOZT7Dxla/p7bDA3CTpEgXztFnJ2Q/H6ixJCxb5d3D0XS3H/upyX30soq1jf0xWce6v1JM4I10wenVH2ad5b8LFfms+Xo243vTo6Uo7RINy964NghnDp60O5tbG7hztIy7ty91z2huHQPL1+7iaeefwlPnbuIr7zwEs6/fA0ra+uqxdq2ZjthbtAV6n7FUHbmtl9Ijx59zCGyIQylLa9kPrFT6tNCmFZakem26AwNTL7WNzaxurqOLRSs1ZcQbxVgeWWVHs6J1+bmFpZXVu0FZXyNRLB71xzinpdgftcsxqPuZQRzsxOMR6NtUVd5L6VLOe6trvOow/JnLrMg4cuc/gwwrK6ge0IwZwCtyf0QKA6loUPtW/1wO5FuM/Tw/oWwi765tYWVtXWsrq5jZW0dtxeX8PT5S3jymRfwmS8/h89+5XncvH3X9VGq3CSrRQX2HNJHbVGZqf/UexNmcMgpwlDvEAVy9FCF6Juvu2MNW9jcLPZ9a6vQvYLNzU0srazi7vIKFpdXcHf5Hu4ur2Dp3hqWV1Zwt74BY3llFYtLK1heXcPK6hpW19a7z/UN3Ftdw8raOlZWut8ra+sum2UXldeMIr3ftLTBk7lUv0mP2s7vmsVkNMbs7BhzM91G4/zcbPcsxPwc5ma6TcfFpXv2x05aaI8ez5w4138KgkHkB4XuN7L+Rept157LWvUm4zH2zncvcgCAB44dwuseOYPveu/bAHSAdv7SVXzmy+fwmafO4bNPncOFyzewvLJqY94d8c/gwU6Zogrtm0xaqZFeGUXyvdW1dayub/jn6jpW17ult7X1DaxtbGJtfR13l1dwa3EZt+8u487dZQuPd5bv4e6SGz1/bm2RAMq45s4BHXv6jsbYMW88c4g1JwbiI4hu4XD06crtfUC1mr331vLY6E0FWr/g3spaJ8Ny7MYndeg7F8d/Bh8ba9YNqQwsn+DQ/r1h7IZSvu0i8P2mta1rp1Rzp371+8xkjEdOn8DDDxzHd3/zOwAAl67dwpPPvIAvPHMeXzp3ERcuX8eNO3dx4/Zd3LyzhI3NzToOPMaw77bJzCkTMwDA0Hfp3gru3lvB0vIqFu+tVKRexfK9FdxZ6nK/29XIby8u1+W2zqiXlleweG8Fm5tbPmBsc8aYl9mkyX5zxAG6P3hIdbINBroRxYUJ50STjVnrJf+wolq31MHqoXX4Y45RyDDuLd4tndWIFKMTy6CH7F1ZtW9dfyE8OFLTEga2oblgjvhL91bx9PmXsbK6hoXd81jYM4+F3buwZ/cuzG2zHzVEL/c31G4oTcsynDhyACeOHMD73/EENje3cPXWHTz74mU88+LLePr5l3H+Ujdpv3DlBq7fWrTXiZpy1OhKweSzT53D9epJN+/cxc3FJdxedBS/W52gS1/umUOsrK13qwFZmIH0w+zNxq4OaEn12AgEvmFDuZ6kNi1lRi0C8SQtaqiMWB6QGoD9DTuzs2TN4s3cv1iQyhchUFz37vjKewymAlCfLRlQ+uCgOk3R7uihfT3D3W7Sz2WXrt/C//x/fhRfevYCFupZM3WKfXt248C+PTi4sAeH9u/FwYU9OLCwBwf3dZ+75+fCqeGhifzQ2LXmotvJMB6PcOLwARw/tB/vetOrsbm5hSs3buPFuor1wstX8ecvXsKXn7uIZy9c7pZ+TX+CyQ//d//C/tLNvfqp+TYPtCNkh0T6+J7eMsbyoLKP5IHrlZkaYsoAOOrGao6CLW2qEYUUq58aSeYF0ab8KIsbrw0OSq0X4d6QjOmaw0lMA82xHFQiiwMymLMR6706wMzMGPvTXzxqrSYNIfTS8gqev3gVTz79gvdUnXMyHmHXXHcKeb6eRub/9y/sxqmjB3HqyEGcOHIAJ+3zQO8PUjJvOaLcT5rXkmE8HlkE+bo3PIq19Q3cvHMXV27cweUbt/HM+ZdtLvLshcuYPPn0+QoqES+FJhqsbQ/UA2icr6YhDhhwrd+etLJzUH1Btt50T9Rja5nE+4AjLzt+M5WRHhk6t+nshkFRRJfEm2rX+ZZ+h7FtUwaNSBkwvO6pIwftDeHefXsPpHUtr3ZAaWouzuL6xiY2Nldwd2nF+SHHH4lgRg9wTsbd90l3LP/owX148NRRnD1+GKdPHMHZekLiwZNH7WhQyzH+IjJo+cxkjOOHD+DYof14A87gG978GnzP+9+BpXuruHTtFiaWtRRf1iuaUpQSUmyzaRo3ixfxjQAAIABJREFU71+Nygv9XU3dZy9MQvrGT8yHteLmKwp3+E5lsW8dWDVSlbm7achPRmVSGkk3ZJ/z9j02/LkAVh3pUtMj1UXvD8WYWFkGvYEAGGYcteDxV53CZNx/tqO1qtjSv6bJlhGwzhKPqGOKKsNWKd0S6upaL+159sJl/NEXnrG6CgqTyRhnTxzBI6eP49EzJ/Dw6eN49MxxPHjyKHbNzWCmOpR+smxDMgztr8zNTDA3sxeH9y/gzPHDvA/hw6UpgaOYvu5ePCcWGuyA0LTioYxIiio0mPkYeXA2TT9UYSW+/a0fDkwYqstpkW9u6byaJ54aJ01hltZ4WtRLZdBfXRKbF7B+SvdG9KpPm2/xokFI/2pqWus3ZTD+NToUVyPx/+jZE/aOqE6N2+8xuRq7OjcXl2xjzzfElUYfkX2cq/6IH6kIIDRG2NLHhQXAFja3NvH0Cy/hmfMvB3DTP3559sSR7v962vqBY4ewsHsX9u7unqNZ2L3L5i7ZCXu8JmeZqFYLGaYasw1HUlJPeRzdG5Mlcy6ztr4K2dFyHX43kRmxstukh16EsJSHw1pehrNopmmImGN2/HF/Ka3hUFHUiI35Ss9cpt9ceTbStX6cwPVkCBFWn39nLy8Fr37wFMbj+Cqa7XLzXH7j9l3cvrvkPChYBVBh4ycZlB8FsBBd718GQLC+sYnnLlzBuQuXHagAzM7O4NSRg3jgeHc49czxwzh19CCOHNiHowcXcGj/Ag7v34uD+/ZgZuILq61oUh8hFe8X1WvTpI/MJCC8DyAqAlBZVjIQF0oyUhWvFCavEIQcnD8ZsVqeoQZV+cvOwOgfUyyE9NBQO0dEUq5oH50lxzQP6PUddAJSNB3ayc+79+ZiQn1TlFaNz++aw+MPntw2rWhdOi4ra+u4dvMOVtc2+ilzYMdcnXQKFNPBMA7tJEPIOtCvs7a+gedfvornX75qdMajMQ7u24Pjhw/4w2oH9+P4kf04deQQTh/vjpEcP3QAc7MTk3li3kwdSOjUPwoLY4ZIvGsYNAOXlB5FZfqKSuxLHdTuFQRn6oFrdlCl0vqbTyxrcEgtQ7U976WHotUwLZ6K85nCSCMKKaBWtA7zGO3H+Q7LvT0ZAjsIY1kN6aEHjuHYwf1RL9I/umGt0qT17vIKrty8XfvhQdcP5c15YmDK0QJZl1GlTRkskS1qh93SewAp00X3ZWNzE9dudidrVW+j0Qi75+ewf+9uHFjYg/17d+PIgQWcPXkEj545gUdPH69HN2wuQGGPeLI0kW+kCvZ8h6ZalvoV30vQ6lVAdbyewRUKoyyvAi2ykXaV2oZbP4lWnuOE+QKK/ZGOkMax7HWAt412zAN8sAvUAIs7otJj5wwRYhsZQiqm95yH1z18Gvv2ztvYMK/6PadSnFLdubuMl6/dAlmJzeNEFBTY6RNiAvwn/XrgYExvI4MEA9CU3pSCuACCIGv9AaBgq2xhcanbU7tw5UaVoXs4TpeM4zPV2RmQjc64rUZCp1YDotZ0B2nFhgzaBpel0ElWcoYeyjIyVT7CODDZzL6RJDQ2unEeI6Ts3nPMmuYY+qV7WqQ71tQHavRsmga16e3FJBkUrNwx1WDqmIjgTa9+VXjeRctb3/U3G+O124v1XJXza9mgHaWmsbRI4M7cS69NgJ1lcAQA+I9RMr2wqNGjp/XiONgq9VaXFq6sreNmWcKIw154k0bgGjUXFEsVAvRph6XUkJiE5xDISjOBnI4oP6VUbWkOqf3U8nqv1N/FQlm9Vw0qDgClAyA0Np7Y+Ao8/LszGB/VEGIGlp2mgP4IQmBD38xnLBYVraYIhbQ/IEP3J6cQh8LsouDE4f143cOneyd0+eLUKciH7tU6V2/ewYXL16uhueydVorx7gAAu6O+oiXGG/3NkZ1kIHRKWy26vFtl6NVzeyk6DvchQ91VVxOnQWclATaw+pC4MmNOot8buaLPEYQEd8P1e0KoLoGegTD3UcO8fap35TlLQq+Od17ZoI+MdMYLyUQ278unhFSEdIaeJqeSc7nMF2s7IT2UbWSIcyR40K2g8vpHzuDsiSPB6PkzO0JO91bX1vDn5y9heWUt8FwbOI6Tgau+LA1Vsya9iYKnYEcZHAi7fhyvGHw8TbdxKWruyrfclwyjbgGDI4GPmr2WEoCuiXsa43Qtn/bKwTGYuKK2GnKeKJozEt8qtAeGiLqwNmmtWX8T6quCmNXCfLJsJX3PUQIl0kcXS7r77DgUzYo6COuF+lGnKj6UQzJwxDBIq2M/Ho3w+kfO4IFjB3tzB54zdF1K7zcA3L23iiefOe86rvKajYS3DSONmY5H3jOpsguB6oAMzIuNS0nlqjLWN4GqgeJ9yjBSm+zstASCYvHHOQlKC06hCqgEegPcFzbMNANbEo3EtFWIL1eQKrK1ps65KAGYGwlo0w1sfL3OrUOPqr5ZFmTIjlkVapNpLSM8UHWYM9HNIRmCxsRrlFJw7NB+vPGxs9i9a8544bEbWnplvheX7+GzT51ToaCbs6IvJO4hI+tL+wqwHe8FC+7LwEBFOG1dsBshfDd0DWB/PzKMNH2IhsaRwRGkQ6fIhpNyoQhM/R55LTNoTQWInVJZL73Sf4oZd3/+k5XkCMhRSRIPbiDMs94X+BvJGaEdnXQ+FBYjWBbhMSKAqOXRzolGSwYCKuekq/PomeN486tfZfc4Slj9bdKnrVJw7sIVPP/yVWjEEusXidHsFGbZSYZk0UpvQAZWgdC/+pXLSt/oEhjfnwwj3fSye+YAyl004LhrG3M65UztpKdwZYQHgCa+xYRoISz7ixpDXU9H6Rl7aJ+912RTfTkDOvkrlrbQmJXSTcqonoV+7iOMuVhbcyiWQ+tlmxr6TTJYpAECIMzNTPDE4w/ikdPHuxoS9x2Gdqf52trcwv/zx1+sf0qg81Y7cSDxyEaMcmzcpV0HBXa0fkAGjRLBFgqXw8a+k5H74zZSJ9L3J8Oo71geHYrob2ebJzMhVqTQUNKIsjN2dkSQKkQ3h/JqcGZnGkprOxFaopN68KJQtAiwS3k8Iz9ttNhGm8lEBwy1L6nRlK0z0dNVJCsLwOK89TKkHDW3kcEnri5DQcGBfXvwxOOvsjebuyo8wuT9hlxvZX0dv/XJz9NUJxp3S5zed5FoBZwCivPQkkGjhPPmNhjmPgE8HRQ1awDwimRovA9ald8NqJhnwTw2CFzHXcObejCnWb77KrVuRHNLXSoRS8tq9GDlQLIh8P/Urw52I5e39EXbG7k+X4Y2lfcQDXj+o11pWsS5USGabCKFNuGgEV5hhhxqQAaPqDwsgl2zMzha/9jk0NWaO7CTfOXcS/jzF18OVuOGmHRkTgYDJaXpsrFTe9mQDA2O3cisM71D9etYFbWzBEY7yWB/MIUn1DpGPJnjXNcGw8KPh0pbPXIOXEadsErrnt9XRDD5ya5cERLpsQ6rI/TSAmOthL6lkHzGlxhdtmveuOtM1vkUU35yRFdjdCKw/ORo2k/LMEiGgMYqcyXFfzUor8pxCtU8RiGCj/zen0Q/DIMARCOOiY+rUdwUeqkI7VU0ZGhdeQUxsGagLL3br0SGkZWXdAISDrxxvZfpO1KHkEsiY6B+MAAzbPZ0CQ5QkhCc92uY8s0Zdkrqk1Mc66c4X3n+QXOVbqC8vKA6EvHgrGj/VYNFzSTqI8ggAgjJEAx5exks1aqGvryyiguXrweDbx3VyJc6yp2le/joJ58kXfAYlF676Nhtc+63kmBNWYZ+OzpuYv+ShTVwKGQa9ynDKDqdo5c1LLRuS/870LJxpb7UUFoCcghlCNbONVJomiWRv4jilIsTHVeEuG2bWG5YXa3YOGaHHj2JYp0fOw+O6dkRAAnL0nVWZOlF1bOlQsXlM3p9GfhytQhuLS7js1953l883EgZWt9VJ3/4uadw8coNQ3WXAT5WKkO+xO+GYjLY3j5SQwaOOmHH2r51+jENWpVC9eQVy2DPf/v5cw11aoidUYqktImEN2nqvSAYTeRcWFQDSKMr8HydL4l1TAP0PcwrOBJWxzOHIhkrzHtwqgJ6qKdIo/dMhg7hnFXqm+ZMHRkfUO1HFxCcx1q3+KKFB7m2DNpvTs83NjfxR194Bn/wuafQsj1OmfLkenF5BT/9qx/r/mqr+jrLZ18jwvPVO8JiHaso+V5fBgYDyVEnoHzUFTuT9fkKZBgZmqoxJvTUfwutAESiXtUnwVSFo0PKAdWDC71tTm1fJ6i8fEaEGtGifrYmxMEoCGaF6CbZObQ627QCp/WtTuQvKj/zpewK0VKemE7sqykDUopRZXjq3EX81Ec+hqfPv2TzCb56x2oALC7dwz/7xd/CJ598uvtbEAQ6wbEkF3AGEE/SBq4TYDGWt2Swytl/xP4Z6EPi71cgw3ju7BM/1t2n80AV+UQiU+YenNL0+CRm4IOsyBqX2pQiRQXhk6USaRppUlKOEgES4pKpt1UZ6F79HlbG7N1KXl+q4/vEnzYFqV4XfMT4cLlMUTZgvCKl49T5Ox+xaMhg6gjZOHT179zFy7h+6y5OHD6AE4cPhEcqQeOxtVXw4uXr+Jlf+zh+6iO/i6s3F+l+jEw2NpR26DKzL4EXlMaL29xRLOjtKEOI9hGnK510ZF0i5r9SGcazZ77mx/pr1dy3H+y29WEVrpTGA/GBnY6eEfBjEkrRjJEQ0pboLO/mdiQQnEzPadjgA8oQErvlwVMdgwSiVT+qLIEXNQIy1vhXacjZrJ4DgsoaJsCge8RRTwaI69SONzt4bdVI8eVzF7C4dA+j0cj+Xp+I4O69FTx74TI++qnP43/95d/BL370E7h6azH0SaLqiBILOn7phLMIgVwETVUJO8p2MnTqKaCz5M6bDjnpN/wRxb+ADLLwrg97QsBGWb0cTKzhgUrYdwzj3TAlKOyd3ie5I8AGC/+Zy7O9Oy1xmNX6itq9VAvu1MWNLm8Y2Z+BSnriyNHRQd0EUjrMIzOK/n0g9k31WGCWwV72RlWHVpD2zM/h8bMncfLoQezdvQsjEaysruPyjdt49sIlXLlxp9emf20jA3xsG2xvQ/H+ZeiXF4sSodP/DzLI3nd+uKiXSB1U1DdGlAB12hrJ4xInNPi8fNsa5DD5MsPYRjI2Hq5nhtTx7nU9tjUjQsdE/MlDqjQkaa034jB0i/WobYg4mR929pL6ENdLkkEdQuc7OSVxMoXK+3W0Jt/PV8xWdrK+lNtoi+2caEpkGFlupWlHcYOgPUc73h2ioKKh/rQJTFemO5F9VIbdDzwJyFWJtADdiweKl1taBfhEzstMHvZeyzOJX7oHDcPMl0j8ZJGL0mT5WVYSoNemhE/7rsZRx8L7a8hQYH7CV4g6SrPq24/hlNAmIC031fo5khePlP25qZ9gsPZ+M2DAtMkw8omvHpKDDXLRmrpJVo2Ppedfzc0ejgAmfcmVTPpS0spwANtOk72d10Y603O0nObAfMD5FpWpVLm9n6T6rp7ZqCSbTyPCY2RdOWgoRZ9DSKg7JIMBSolyMbfS6y8QNB5baYeBQ3b02rxPsy9fhPmke2DqZBjxLrReBsRkKLb2zl6llWu4S1YDMy77qZBejUDblu6en4Hi5Vak3JEmm9oWzpMhSCmk26wMktl4pwHIiK4R0groJvGpfYRJWzXkjAHB2EkOu6cyWJ0hGTTi1YhjAKfNIkgVe0CJ+2s4oMneL7dzVsKVUkMCwG54lS9ptJkeGUZsEJwkOappaNF2FHREU4xangcZtggXmcroUBt4OJS+MwbQJXr9oARdzXHspTZkfeG4MDHnswodPKGoRo4Z2vltllezMgMP/nSJ4Gd6lQ5HnWEZQscqe/Rm78VSXpalYZyBZAk+b+lLzzG5OUeHsIAe09Te9dWXYeRnxfkWD5yGiwpQtLKRiTVkIwGDVPETMA/vpV0kt+bO2UEs3DZ5qM5BYbYAPqGvCgtTBNa19dWgX2K7JArUyTsHJxoc4fS3tHZ+yaMaMiRm0DcMbePR0wWjZrnPHg2B60iavbeb+zh7BNeigcjyVZZhZA+sFH3YBoij7J5qUSI7bzBOQuA8H9D7QgNdKqImA++jKDlWsX+cRc35M09UZkvDAHTDplRjj7vBjGaxr4D0pCc+qOe1SVEqbuCTz4glkChVfyZbX4augA2E+eFrCJGBlkeHVJNoOLj7KYPW5e3FPvI5OeHUaIpkGHnK45MSe7WistUwlmFeXSjJqFeYeYpKkuvAkbkVEUH3+Xcjj7TDd+A0TPpNaorCq1D+qXGTdqR77Hjfvoxod8mQpXv3VJXR9J9407+/YWnZgAz9yUk9n9TjcOjqt2+BMHcZVvu4ZYoCnnXwuDjie/n0yDDqA3E9xcnHFhCF5By+F/okO2U/n4uM0m8yRvfkUgMJG6pGssw59VfpSeXRAbh4XU4srZl7oL7KxCrxKww5eBAa5eClSO+beCpWmjAnvgy9tpEhCE6A1Vt14+jDbVmJQY4h2soPDRIvRgyUc8rUzJSmSIZRH+z0aAZ15GEkZkvFQ2F4loIdJYeuxHDmW5m3rEpXn8jTSpH4FpcqVLcCRsqx5ckqAuX84Z2p6njGAB/LVnqUd3LkEpATikVXIceMO9qdcxdqVitFvgzBhmXwts5PSaPfpSY0jmGyxGQUcDxy+x9q6WTyY+muBj8bSYsCzqzrhXL4/sR6emQYmYOQcbgxeJ+F7nX0S2SG0qSAZBziszNoWLRQSwZKUOu5XnRKdx4xJdxXmK20+6dMnV+jwxGnR7w4+oQFCHJKks9JSjLqjo+SdToIpwj6ccJVV4F4HqcGzYygzcsxW6uKeGkvPa5tnKw7gW7YlimUYWQHs2gC2f0U9+aS7EGSddSfnkrRKc2wkqRtiyPngMfb7jN5dukZJykqfzJaqYeR43j+LlE7pCyWU11TyztkUf4k6YT4VDpCO8wZxer9cO4/TnDaMqSXSLcdKJup81hCUTYV7TLS7J89S22SVca6hh4QpKM2UyLDyCaAhGoWtdWrq12bQwf6bipuk25kVp3bNKJFXCHKB9zo1CyovvZTFRnStJQLFnpE1pd2OsH07SIWqUhxhctKFD7jYWG+VGm1rPmcQP5kUGmBYJaBnN9eJbrttSOEwgBAuwkAwydw+238+1A/UlNaspYpk2Hkh+L8hqgRBEsmYyCn6qVHhraApjO9E7mZDzVgRszIpwkTbrBuOWRzNeMnnpnnpT6xRhLaSFVeId2oE0qgDQpWZPQilrPynxf2JUcKa9SnpU4ZNLIM9V7J/ISmTMRXu3rPtKkzcmBlfhpPrTUW1Y1YbyndWGg4/BTJMPLB6AtnL/yundFH/eFOwKsoXWrug2pr6dxLBhKOFDm8VAYcgVUa1l5sZ4oxhvt89jqngGPyAQYYPhBRJ+Gqssq2ilM3pHmDReS4gBDbJhn0HqWhyp8al+MJuWvpq98E1ZdahzRDAv+2QdpUAFwGSXQk6WMKZRjp5JiXVwv8vKt2K/U/fdS01MGueKhD2+vb1u7tVjXk4J1uhsW15cZS21jgaOSEdLPjtyrY5kDk9IUjmTmR9+yrSTFSeSxhmYLXeuWKhj6YfVm7moYgDQOjgW3JoHpJ9UX7MwNk+FWLK15U25q5FWpnLQaiQSvnb1atvAY1TZ8Mo0Lhmu+pA9dxJaE0lVD6tOWkS4QmLLsMG664ExYVg+rzfEJpVdpstqGNKcLr2nKfVa/OXVxn1jfDjdCufTEx3cs5pbPoxQ5Z6VOaVFjvjBxAGqZ+2aAMpIP4PfEY6jAd5bPEtnQ7PNuMHZ43UBwhWqEmp8VgutMjg0WIGF7IK9A9UdYZCB/m00+NHYnxEn92/JPVUUrTY01XXRKtojQkF6KBVKLg4yRKHqwSx8eBpy4jFopwDf3QIMRxrjOErCceRIoUEgioCsQdcxsZ+srrX1E1HImpr9C5ddQzSl15LLbMLNZHWrk2WmysDgzTKcNI/+Qup0w6kewMxjfqWnwra4yiKm+Qga2D6hjzbNQhIhWrFx80UufSB4eIweI0CURq18X7yqgf9eMRxin0v/NtUn4+PCbWJ0dJoZsS6Vk72UaGoCzXRY7oTJPz8HzFAauglG7yCqAxMXRUolMwPxseMMHITo8MI5vsMnBXBpSvYuV0GK3S7wZJHOXcfvu6oY6CcZtxZqOQpAmmp07AkYQjG9NmRxOqJ+keOUtuG8INaZ1lCJEqy0eOkHQReSR+cvssQy+0UIqoPGT1bYfG2yI1Oy+SQQ01vI/Op0yGkWJZv/9quGZjxFhGf/7FyMWD3HuegNux0NnbqNRWsTrjCs8dIJXB67mjMZ/Jbf11GgiC6rJrP1eMUSkpe7i/ThqnqW29fS8dHpLBFNO/WnPdXv/tW7X9tgR27OM+mnsfUyTDyHKtXkbgnuqhWqB/UcgdO4U3wF5UYHMPEQtzQ0YeURscluBHLPiVNAiRgXcTzJmFf+lddRzqmxkr4C2K+qFPfUGzgEQXJkNRGYJeOCrRfaNSXJdofbZl4J+hot7OixP5fhaiAPpXfuIDPdSwRSxfZaDcbqd7UyTDyGy6xNwtrrnX/9TwhDNkQi/O7UTHPjtCsf6sNqFlYcfQlIjyQDu3xDKaE6V0g/rxA2POo5FgpUt9eo11ojYYDLfYBqbzofG2epVFLD7Z2v3T26dQApbfOgAMyWBOJ6y3TgZzzPqdj9X4+LWBkN+20t9ENCEgZAeFv4S5l/atPbolCwPHlMgwKsoYI3fp0LeYkVUjpLxfghYQDCdczC8bgCElQruwEgX+SuWFfppOVdHqSPpViAePKODfgEU+fe5bakTU5xFC+0pc9zNURYVDS0CvtMMQutd1LBu9yqIbzaAMKndWeon9BTMIE1KKioUYsy7UuTMltgPlk7CWh88c3HvMupgmGUZ+uyJxPezn3ldXmUKaZDxUBdCsXbysJwl5Ru+YRagXVKYe2peJwkQ8KdtwVCYn+koT7Y6MMfNrRdnT4Ue9A9s+QMZXdv4knySerYwHtSGDB2d3mn5dQmNKN4kSySD1e0VPbpuNtuHh0rvHqzmpPYHCNMlgDwj5J0UGSlWK9B6D91QmpFDJc5MCwmSyxHuxjMOnCuk04+50oseRzOYR3taOzRty1MhgPBYbmJzvhoUndQApoW04tsL8soxGW0zXxlKhz21kMI9VGYTq9v3X9BjvV4sUP30A8Pur3LRMa73VNuILfKuPLv5cQyyfFhlGvPrJ3sfnZYxudtzgbKkD4QpKx+nzA0XZd1TwwDS/GS/xF5mk7/l+YtvzTD3OrTx2zm/pSuWHWGPBPatUvjj9IX55/AokGjojo0YmH/tBGQIjVq30avicqCGDkabTvazf1C/z3Z8gS39MVTai1V4B+urLMLIxyGHdEnTUQXdDgTLFzpRzn9IoS6L3lki9IUkJNxJNnZJGQtwytovfKxF19DxVNGydJHuIVbRnRYfgxtHABYFOyp2Os6X0uG+xl8RRbLUIUoZlYGUG3fWPOEt2cKptB90kPeSTwJEswnTROgLhiyA+pp7uiP0OIz0lMtgjpIbY8AeEzNtoMHSVKfiOcafeGG/oIb2wgSYShGsHCY0KVb3CivKcQkTSyV49d099atBUxw/KLvXV9d0cysqMx65zRhxhGXJqkMjXaG68ijk1Db7mWNRID1cOykBlgDuu/1Fyr6JL4FRUAaAkGUrQLe/1BJtlYGrEq3gpcjIM9g/0TYMM9gipnbMvjq0a/jWtKghtA7Phh9lrCfeLMaJIR+FTktIs0hUimw2PQhQz6CxQqKTwSeVhqY8iRH5bnK5tW58JvdzAC2zDwuErKqm4bv25AR0hqPK6n7r61ZIh9A2jSSHVVNOEHU7vlI7Ee3xwktmIz4oM6QI12+WTywJ7g+MUymCvoTE1K2IHhE+MS/qtdRJzIapYLTfEsJipEhsaI7ZNAJqYolyfBKayMHD0vSPbNzSxZdgqYxhEOsKiiOad+sA7tQbfJTp5SAPEfIrl78tQNSTOQRSD9F5S1NK6xI85KYFBCfe3RUIirpNnH/+Ox5gu8inUaZFhxMQ19+sMVKB5NvtrHo+wmx0koe9sq5xLsiezzWRbEnVEQkvVhgDIzmAhqdTB6fkq7Ub7SlmIOGTc4diKtlH0Vk9uIYiSUx4LfWeaNrJebH1W5lsyeF+esxu4qPxA1HUoZ3oMZE48qCQgZ+038xNcodIiHmMqGQFqGmTo/iwvR3Nul4zfUL0o02R42og0YdEfjUuRlzqwsJmUYZs7ahw0qdZjHbbbXNMeT8NKz4Yg8F3mzJykMnW60hdEeOhLqm8RINNpKUM7zn3D+m7JED5hovedJl09FhppGBPnf6O1Zrqe2DR5HWJsimQILyrrP93mZHSeoTN1oxzy/xIZY2NiSRh586AnZ9Bowmv25oyDSkhtmB/ro708GAT2H1BnD8c8ihoB/F4ICyURtUbkyH1c8T5y2yjD4HPLqPdS1OKoblPbUs+ahXrOEO/0lsRPUVswFbgd9PdvSuRtSmWoq0zFBTLmnctufGvn1ZBtkqROot89QfQ5hKU0HkGMSY6tnJ9ZyiJ2G7kPXaWy1aoS2+g/hfowRdO8g/0k1XVeSKYc9gt9N5kI6tgvRcm5XJZB1XZCegi+lWTwP+rooqsMAoqkBeDHWXn+pqPJRqlvLCygKEg8VyKw6Sq/OKDqy1fk9GEp51X0r7IKpk6GLkLwhM5GoO5MGxp6CtQL/SL2F4aCZOAyuLcWmCFH1CZn7IVMMcDtbepYm7RRJCkKFFcQs1qYT5atpO8MGLWwt8gAikzipS67OgjrhfpRpyo+lEMycEg1SDNAYSCKffC6u7DDa101ahfZjbvQbnA+0h/GTMdDghq6evVeAI/pkGGkNlk4nDCK2US2BEYYGYOQ2lFvgPvCxnSL2ZJoJKatQny5glSRfpCM6Tn8EIBZvW5DzGu68fU6tw49qtI0ejibAAAPLklEQVT+QfDDvIMrMNQ0LXcy5AzT0zy/OSRD0Jh4DU8DyNCC3qMJ9mWEj40LBd1dF15MCDSYlvIVYDveCxY8HTKMNH2IhsaRAfATl36aKXUdhCIw9XvktcygNRUXXg3fynrplf5TzLjz/KevJNrhpKgkiQd3KOZZ7wt8+ZUR2tFJKs/hUBvLIjxGBBC1PNo50WjJQEDlnOhmoTcXMC1mV0gdSXsByLq+xPpFYjQ7hVl2kiFZtHU+PTJ0f1IrhTXfnVWi3oHmdYqvDvYuoNoJb7xZKlQAn+gQc6a/Tml9hGV/UWPQlx+UnrH3DtPxp8mm+nIGdJKnR1SMpPItJdSz0M99hDEXa2sOxXJovWxTQ79JBos0QAAERdigx8LlML0BCmJO2NsI/A/q0MqdDK3zR73HozmI5Xr6YMpkGPUdi3aJRX872zyZCbEihYZwvoi7ELUjglQhutoX3Vex1bsLtQtb9lIP6RWKFgF2KY9n5KfX3GuUFJOJHtjRvgSIRy369ApbuUaXrAxNMStwhvmcxHotGeLhNTYqOhIjzqeQXlVvvDmGql9ewYl/W8+qNMXpfZd0XolTQB3zKZNhxALYLYV4MxBJ+S0JXMddw5t6MKdZth1fnUaIceXTVyHicprWZweJSuT/qV9Fg0YuXz3b2xu5Pl+GNpX3EA14/qNdaVqk8hqPGeKVXy8S4is41IAMBgzEei9t0DKhe0Qvr7roWFv6HCavaohJRzofs4ip5ArJJj3WzGGmSIaRFuQDUCV0VEKua4Nh4cdDpa0eOQcuo05YpXXP79uJSL1HduWKkEiPdVgdoXcS01groW8pJJ/xJUaX7Zp3rTuTdT7FlJ8c0dUYnQgsPzma9tMyDJIhoLHK3G9RVcLEEzQaoEnvdk8IBgMrjomPq5F2gXupSAkp0rTIMLJyerO0phyKUXG9l+k7UodlMBIZA/WDAZhhs6dLcICShOC8X8OUP3zCTkl9copj/RTnK88/aK7SDZSXF8CfIixe1rGi/VcNFjWTqI8ggwi6Z4cdAUMqsI0MlmqJIObw/s1X1Yzh6JfJh0OUtu+Rql/s2G1z7reSYE3TIkPYqealVGtYaN2W/negZeNKfamhtATkEMoQrJ1rpNA0SyJ/EcUpFyc6rghhe69iuWF1tWLjmB169CSKdX7sPDimZ0cAJCxL11mRpRdVz5YKFZfP6PVl4MvV4o4nUKPIYNXRlp6sheqproVk0H9IhnyJ3w3FZLC9faQpkmHiUaNSFI8DOhcofL8hvEkj8WvrWQdeDSrWl/fd2ktwQcmJeFakfFIKZ80CD37Dj434RBqsNK8I88gWzeA0kY7/dOVIvS8gWYkey+9Bri2D9tvTFzlS2Ak2Nm2EQj9uiMR/CQ3pa8oWuIvWGCo9oBFFpkeGkaFpNcaMnvpvoRWAwBjx75NgqsLRIeWAapT6MJL1qEjI0SX8pRk67Be14RCqyJBy8xBXhegm2Tm0FlKoZ1MaAbRO5C90+v82dyYLEtsgEBX9//9MDlYVDyRPcov70tO2xCYo0GJPTrkkbgFPyUQ6nddVhzVKjDl+Vz8DX1LtaXFxh/yY17cL4M/S5kp/NZ/8mg6/CqQ4oqs9tQTU9PrvDcjbeLog2PTmc9KmWB2Dm2xvKHS5mtWnvrBkyr4MHAsR1V6TbLwKRjk5WhZ70CvH/MKlEJEpuBTbQYIrUhynWmN/0cE/O3xq9a9xmjGafTycXcnFJR6Ct9lrE8b8Uxlf9JvbO1Csxed0+M0I08pA8S53laOGFM9rFUlqDz37XkLebaxY5aAyqsoe193JvLfa0qcM1VYMbC3dHI2zeF4yjZ0Z9uL1MfdvDt3DewSb20nf0pXjoINqbbf7poNsCnvwhHKAVr1qRDaWaCVbHEa9gTPgXWis/1PozEVaJ3gF5PiaDj/WbtpRTgsRQKutb5cEJc4ZHEa7ll1Wja+cnenx+K3gW4sBk2ZQ9I/SwsyBICtWHbDbQS1BBwhLltyBqQzolB6xn61eGxwe5fSKmKTh+dm8iXyct3ke5AZ3HTj5rmdXJvyGZe43Rjk603vLtBScTfj4Ze0p0Ede5s8m/DUdfhpc+9UlO5tQTx24rswitK3BCwptNF24v3EghiIHn2j853HfZPZhxshG4f4D5ZNLTtCIPhqrbRQWw0IefxXdPpHM835DvQ0Kl//HduLt8nzr6R/NCfdIuNSrPtzslO6v3qtQr1+FiZBN9pr6NLe4BslXdPjFduZCTKWdaAOm493K+CVpzzCMUq9QtbKkDHPsXgakI59Y63kJVSKPhv+uiVxdsz5EDZdfkLdZRYftIBcn7JRT+mPwuKPd+8SlT7Zv/60susei+F10EDiMKGmlu2guOdoMxmo2TzA3J83EUIWrglVNSj9WAubnm+cU7kM6/Co96ZDc8iCnWmqTLJDOtjYtmUytVqFGwS6QD7Ixq8zE0JU9UaBv8GTr5785P8kaGGU3yuGDfUSjxvHRw/66AwiJHE3TCY9yGU0xb6ll6p5p3nQwoGTXi9LGwa8RtIwFiqv3vc21dveT5qlfSxHT9mt9ToffPJO+aW8QroERAgejSo2VD49sNTY+dHRaS7hcRtBqTTxn1dsJRykrs9DIROcFBMmEbacxoLNlxwBMRFeG9AXc5CRr82iTtu3Ix8se6ETQw/ekg9u86aCMtzOOAU7dOkil50/kdwlA635e92pZsNHoCAB8hldyxaXPd3T40SHaHN22V2pRPySdwHl+OtGqtmHm6DrRYXeodBhnMDbQBb0zKS2t5hT2og+8rx0XhnA1o9LgBbIaArP1q9vU13PgRwgpMCTecy0q2bLOuw6NsXTv0VxcXPJSl4tzNpLZYt7lyxGY7M7sIIkAgrdB+4gOvzorzlscOKWLDVDa2V0nsYtuULBp1b/XcoQfZRf0Vu08A8Tp9irDDg6k2VyrJvTbYG2KQFub14V+9n5DlaUgfwIcNOaEPxTAkxgi6qLDEGadjqE+lT1LMXSbPA8ascpGc2nzr+41zpXBdekls/zPOvy8BJnacFurj3JFqrPEDN7mnEDgOR/Q/cBA50bU4eC3pYhWikwUUM0/ZcI1b3St5ZWM3M7el2yJZp1XQ3rYiQf1qjUMJXWbnDwjNkAit/2s26nDc4EOQnn4eUPktW4R3UpN0Chwr1MGt0/1D3/Nc3J8XuFLOvjNfUazFELCGS7O8i5rKRUT9ZLCIyvFbLMKmW8ZceE+f1/qSB++WyzD4uyySxSuQtW38qaOep82aCVeS8fPxXLk8P92MOpLX/LabwVxWfaiwzk52c+jHBK+fc7+NxAmy7bax54jC1TVwXEpxK/r39HhdwLxPsW5NzrOg2ZATv69eJ+/z3quC4rfcMaK5NyJhI6qTDYlB79NL7aMBcBZbVlYultFoF5l4kZ4sq5lIqDRTF5Ceq+gyLfnhHnIxc3INx2a4gCsY9WN2Yd9acSmxxttyYNB4mLEy3WWTNdK6UM6/E6wCwAW0WgHBvllpUKeJ9EANsGO33e5JbyrKp8VqkjLjBZnMtizAgbjeHlyq4CaP5itFHgWgMeyRQ91JzNXLARhOLsGArOCYdtq6XmKsrmzFuSuTHnXofqWPDlG/ylNMI5tskQyApzK3N793fapXeUyQ52NxKJACVt2QQ1/Tqy/o4Pf/k3nKGconol7D/3swqBMakjGFD+DQWnRqRYOCqjlufZmAwdP2Aj/Kc1u2ucp05LXdJhxDuJZ6NMWIBCU0K9IxnDqR47jwOQrnK5mnyK8bdWIz3G60JwIev0UZqtpRF09yuPdp8hWEGjDNj+ow88HszCBfH7WyU6P8wIVSrh/VinVn6nu7eR425FfIt67z4jsPJwThprfRCtFGAKn6vfo1oGxqKdCU9cfZJF8MWwCOUUnsMM8UWzfD6639wnOXYd25Hy9BNB005Ix26XpKmLZafba/tJneGVva/RYsfqJ4q/o8PMEEKjmrK2o3n7tgG70y1XKJ8vJ3Jx9LtmirxCxxltLKbfNvbBKJUO2Mm3UgokjyrW08yimt4s4U8FwyWvZlZ94mJRLRtvXrs8JzG+Cyg0Epw4Ifr9K9M/Pv0LoMgCITQOYeYar96m/3/jELmnhLR/T4eeNDoSa3ox9rDZN5EuOaQ60XUvlDB4YO/URb6PtumYMplzfoG2ZstnM8oyn6rDUF+4UrY8O8SVsoyCMRnshWcHpo06kBuY2teSItAaeLp0maEwd9r2c8rSuJFKrXXM3ycHIxEp55lNu2fB5fNRnXM61jGojqXxFh18NxqmcnpXPzQxf+0cFAVdRntK8BtVr6eQygYSZYqaXLUAhsLSh9Xo/G8YCn3IezJFwrN9aBgw+8ESbtM/WNf40nMIQ8wZn5L6A0PsOHXQPZajkk3MVniBc8zS/FdVLrVuZEU1+b5BeDbBKhxh0Ytjjgzr8NDnm8qqe/6otdD18EX7UNPdgbzzU0B686+k33dqO3KKz3DDLWuUsu48Tx6UmxM1H3m1gz4EQ9MlM5iAqzrWa1DMVjzfXnRa11XijYQ3mqevT0ghycTAM7E0H2WW0D/GzAxJ+5XFZl3Zfu1uin3u8ZINbzX9tumVtZvqeDr9EuuY9BfAeVyilUkL0seWkJUIry5Ch40YFYUoNtOd8QrQ2bbpt62NDVFsv97n5Du4sm5k34Sawa59Ws6KcJZ2zFwNy00eZlLQ7kWOtMUzntVcdYIP+95CxtSEdyZm9L24XygpgCjznp6Y/db+1ZFm8SPc7OjhD9PSCqFjp//6YCoQmm3LHEDz7z0d+eB1KmkM0rboMWikaMS+uC1KFwKdI5Bys7ONTwLOXERMZ7mIfDEIf5z1DmHbiICJTRCMgE0QF5h86nMY7P900zMTg1Zib0eGUWnlMLzOHeYyVa9OisxYwfFOHn/7zCksmTSQfh6mNupvcEo0oKn2bDvQOtLHwdOqWkdLt+oNGCi49OAQBs2gCRDbrLF4T9bt9KsMUhfNv3obx5+GxME9mycDN6PTcL/7QoRmrbDEzOmmyDp+fPmAblMZNrgBaiLejEo+B+Wx4wwST/Y4OP092CdxbAMmVvo7DaJv+M0hRKFf+e9oGjJpz2zmnU8SwBOkpCJhJmNlIm4EWaBfjHoJl9m3pBlanDi1TTf0QCMMWXUbIM/tPHY7UghJRMkzz/YXGfyI1g3cNh3rr+B+Yf0yHfwAjBO4Lyccm/wAAAABJRU5ErkJggg=="},{"id":"DigitalGlobe-Standard","name":"DigitalGlobe Standard Imagery","type":"tms","template":"https://{switch:a,b,c}.tiles.mapbox.com/v4/digitalglobe.0a8e44ba/{zoom}/{x}/{y}.png?access_token=pk.eyJ1IjoiZGlnaXRhbGdsb2JlIiwiYSI6ImNqM293Y3Y5ZjAwaWgycW55ZXFncHk0a3QifQ.6Kprj_J4oDmXqV97RricwA","scaleExtent":[0,19],"terms_url":"https://wiki.openstreetmap.org/wiki/DigitalGlobe","terms_text":"Terms & Feedback","default":true,"description":"Standard DigitalGlobe satellite imagery.","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMQAAADECAYAAADApo5rAAAgAElEQVR4nMy9a7Bl2VEm9uU5595bt6puvd9dVa1+6k3rgRCSQLKMEDCBAHsEGptAGE948Bgz88Nhw0w4bBzjmBl7HDE2EzM4PGZgAIMNNkYEDKDBIARIAoQeLSG1uumu7uqq7nq/bt1b9738Y6/M/DL32vdWYzw6u6PrnLP2Wrkyc2V+meux95WFd31fAQR6FdRfRYuF7ujvAhSpdQsgUusLSikQ6e6hfkcpKOJ9AIBo/VBaINRfqd8jd17Lf8HqgspCy8pm6K0Km4pNCYUqimQukHrs/mn1kcuoi979QNsGo02rRNVXjTGf3e9ePRoj2bZe/Oz1a+0j41omLR53+vwqyzBqDoR9casohe6WTmrroPiHVKcA3BkgYgMsXN9csXT3itBNN+lKDp37CUSZLahKIPrGp1FGIQYLeaBIdWhSQnGmjIoqXukYYIQr4IoXCfVPl8oQnaEow/qBUoZl0KZhHKoM3QAL3S9WjwGro+P1CtHLn8a7lhMfYgXFxqtU+mx83m0JKpsWGUadSZCFEdNqHGrodk+otoj9dmSQrhK5paKx+5WQkmpLikjqG2agQrwpkmQEQHHe2AZL11c22FJxxepKsahVTCvFBpadjEe4pHtqyPpbqtu5casuitdXPs2r6XNABuOwqB7EeFMDLUX5T9G4Wg3zqarOZd0n91VcBi1HB2gWu4WjqttXMGiZPhlGqKFGUFCKCyAiHpoCDyV0CL1vdat5mGEWQ0o1GTKrDvOLO5wyZ3XFfN946OxCjK7dFa/p5WpYETn0rnQj6b/pm1LreCjkky6Dyizqt8Y3NJDaIIoAUgqhktQ2xXkWgXDvso0M4nX0vusZNeIqx8S/RnCAxpiN1cdd6Qn15WMSy9lQAv8SywKETJkMk5hjVRhns0ioChLUWfLymJu5ZCWTMWQWiFDmKNRAnaT+o4KZaTBzAsCpIJp48Win6Z71UarlKiB4lLDhU4dlRDNnrTWlmMyayypN0xWlj2Te1BOXlV55loGCB1AEnnGqx1XaharTgMd8Xex3Yd2bIgsNIkd3Zlvp+fxS4dZl6I/rNMkwcu+IA9NLkY2MG4Xxqy0FYaA6BZFwxjQRkxgzDHlpzAOuEGOOIqlOjxUx5HUfLarnwEPEMUIym8go0zQIhdsb/Ft/wTlrbsCmnl2CuShlWIYuChVjS5iizduU7443Q0YNYdXZu2o+mKZ7YVmE+CpG3/otfSlQXIZSaXCEmDYZRoZVRf9hB+w80OYTNFg296Q2yrCFd2png671henVT8rVJd9TmpQWmYqkjbU6Go5Z8b4k/LKQa23E5dGvqkDTDzwkB9rcR5WNUjPWSXFzCXqSUjq5t5FB5xYEZZZmaWTLE0udbzEGampDawrk28XLRdOSKoP4yo5Uw7ZITuUC1R8h+BTKYKtMKkkpahQgb4rLjm4QnYGqpxvcWhsaPpvEqNc7dGqELKpFSih4IspCRkT2ZVZH1IhIpVBkMqJdiFXa6mxhibhEgCqmJ5gzMYqXGgVsUqd9WB4pKFJCVGFJTIaqVNVZUwYwcKH+Fr8tcOmMp84xi8lF4FV1qfM+BzafT6LWs/FnHmiQOHXuutE2KoMvVkyTDKMSDN4N33cB1IPcpW0gCQn4N4qia/XsoqHKL7M581oPaW4c7mgWlUqxfsycKFTHeYaVOu8WSqSmZVrbhikglcGOMSz24askhfrs2nB+avMY0g3zWSyOaAPPi/uxkgyFFV89t6gMjmqdsYlYWqxjY3pQjy/eq42H9ekg5cjqJQrVtjonJcmPYEM2J5syGUYRo/qmFASAV+N1cSgSFL4PsrPCTcElTFZv6GpXCDpmbtFhlIYqMfCMzoEUDTxgEYxBEUNqyiaOOEazGMq7IzJzTK/v0DbxE6mG4sut+VI0DMg6IIONiVYW3aPxSMLqdYMszrJryhkm3hQ9LdoTYLJh6Vexwff83xYTGFegwDBdMozisPiASs9SYzWhQVPyERWJxwaDlnblcsDnC7nfZI0c/qIRuw8VQ66WECHOOF3h+s4k79h0BbTsB5UzqjnL7OimDFbdpVUM5mBIhhYIUG91jNjJ8yyk2DiE4RbltY+ongsGwRAm10a+OOFk5NMqwygyuY0TmIwlerkEetYDCxrNqLImbQQw9Gv3Hipq2NXvITwCKGqw3LqDXRRDsk4IM2jaLbfAbJM6Rxb3Tv9lfIU7ceIehyajq0vOSdiQDApMEXQKdFM0c6a0HECkjkMySbMXDvV8n1d6SC8+cTK9NuNgBbEyhTKMAAR0yrt5bOh+fqREaIeGP0Vm6Q94ECcJV0os5VyzytIJ5hl//xSU/6tteMXfB6nUsOwrRVJ14ImMt2N9eE+KVjqgJEN1Nkc1501qOqD27BtuQm2K67UgGlWSgcvVSHgu6I7E+XgloTNKINSzjnuLJUzH2WmOMKcKTRkqSEyhDJPKghOtlX0y7MR0ct1tu9OGCC8poMTJqtIA7ECf1hfycFUSlBNykpBiwI1KlIdKz42sJnSlqkngxk8TNRRXjq4C2dyuis9Xgdkv2NhNbwWkbFqxA+lSvF8bDLYLEK/meEMyIPZJ48TpikCoHf2GL5Z0KYeYg3fD6vf4CnagSGv5ry5FU59hMk1gS4qdFhkmmiJ4B13rEoh42NKczp0BPriiNWB1IWREDSYy/dI1NCq+XOdKcxRxLWuZGxn3VZXFDieaNhVXoonEjuIDqW3jwIRRNd2oUUBTA9aMpD6MHsU06q+r05ehN80Lk7ioK0/FGJ2ZHnenoMjjg6BzIZ2bBnjcuD7zZW3b0eWrLcOo1I51EIq4Y5TCDWH/x3CoaFaoAoECexYZta1G8ESp1ChSnBaZMBSS2U+L1SeH5rbkqFFvDWcoZJwqOzm+NstoZgfPDNW5K4kIWmnyGR2PBLX/kvodkqHE76IRmnL5YCwl9uX0qQ316X0orOvvalwl0Tb5uu/OB3oOzuM0TTJMzJDrgHW8q3cxQXY8CUKyxxeUcFjPxjVHhhbipggTCEgXxzR6ZMTkf912I6VSFcHHVTzb0xUjR6EYJt1xWmkjy6e5a754taSjI2ZF8QiN1yWw68sgPAg+dlL54fSMQ2Bh/iTYh6vcEIpQXulqDKzMBTWpjJnxMA5VR0L1p0SGUVjXr0ZJm8gKvh1fZNwaGbRO1IdE5uBe3ZtwgYRtas/BQFR1hOjR6xEmyZkOO5A5jRq4Cql1FdmpXx8TdT93Q04PRPlKl9HT9Eg6hMoRx/pv6KKX+lX5ewsTia9sK1wQ+lJ65rwNGRRxVX5C8yBDQwdBNp0fTZEMI5+EOsfOrA5AqeWOZiV80vhz7s36qRZVQA4n1huCYyK3C/rkc3UdTa5j6V9r74F0o6mWsiyqwNin7266VzqPHDqJrvhCxaCfD5T3mjRAtvCXCmIZg3oT72wYLcsDbPyCEWZeqzUWBSIzAGfE7K3Rl+tNpk6GkU4EAfXQevCKiOlqfqE1ehWMHSmuDFX9FAqKhdA2y6TGWb3bEKCzL6vTob/fK+m3nXy1eVB0MQdyGgE9MUmIzwos6bvzTu21TOrxNfOHfqQyPgY81lPVTqghGdhYfKmbeVZhQYPQl6krCK1DX7pnEOYEKqNUYpryhlUdIXouT9z0nS4ZRqUaQuibBSNezMq1I3o8zQzMmGX0zIwkQzUjU8VGYYLnp/xMuB/Wv02WJbZlhWnqh9SWUsJOLHcudlTSq7djnjhFrPcTplg9k0sSbcg2MqheiKSlLamepEmnokkYJ74dx9ZWdUrdrymBUlsfPQajjUyjDCPPodnAkbxYx6pGEsVSRgcgGD0vKVrHAlrGdJwtBou8LR8PSjgjOnFFdR4x46WmVR/eXidofOSsOMlqs+ogQn11ii1Eu1iY8s/urJOOJaVt6lyVX2G+jF4ylDTRHpTBQ4mnGyZ/to40nhV4er6pdAmEijpy/S2apjqxRneJttlmNvLpkmGkDGjeTOAXPiv29dmixE/YWC3C6OS0sxZFWkZNLevSbw6vsO9k2jBjJmczUOI0g0jYRDilN0pSKq8qktLU1a9uIsby1whEOpGKgJL5B3yiXWhlSu/RDwcEFd3ptGTwianSIR6pbdz3MYoISQrpP0d0j4wlTn5LvMdAp+mvH8UGRcw4vtMiw0jqAEk1om7JVIeluoE2AJ1R4vFmcOPwXu8xoheNHooCInasVxT1a8QIKzcmoLj1JxTwaEVr/6QY0jvpz4TrnBLFxoAn1CYD1K4L0Sr0DEXplmNpYqf9AtJ41qLmtpoOEK8UfJsyFK5Ao2uRjuVXsGJoSemnRd00fnEJXaJRMqrniybL4b6O+xTKMPKQxSZvFkffNa0q4GdfC+gTBNrFBzEwD0UNr1MfCqtlvoPMwUIdSesrWxpZzEGoXzVcR5Dq6IRaira2Np4XDkpdkoWQPLobXWz5Lk7soyOaMwt9NyeJ0ckjriZeMihDb9OQZeD5DhTcQDpNR28YKUrUUbhYPYy8yjvivaa3aLsplGESYAjKIFm1OUUnQVe9cwodYAhoj6gyKR2tOJjuqRL6Ux6Ll9gEUoKee5uAhMwdAhNNZY77LtqONeSbakX7oPDMRyvCBqOpwXWoBh/2F1QXLR0oLeXBb7j2ZUgGBzGmxX1wvZ4e69h0m1yk/WoCvGcUj6TY4JEKq7FqyiiIdYmG/RYnMS0y+MZcHYnOMWtoV19wCHAES14WpzbulTx54V1dUyDrM+XGcYUGFiqE7nsIlfCKF4cRNC5R9dc6XT8BqTMf1Fblstq0mlHUEYKiCVqKn6lFGPhKl6KK7CBD1FMCNdJ/0AdTEJcb7MBE3iISAZeWR4rKfyppoHnxwqmTYWTVhb1PjZWbDoyLtVXGggc5AylF4HsepFibEtpUqKTyaJgx4YYjTXXcODllXXnMZBeNS50g1GLmqW0htri/KkOvWYrMgTnlIoFPlqEHwaaugjQE/bHbLo3I/Aw5JBuojk+jGrfvrUROmQwjHizDLhGfqWcmaweWsqWOdKy7ex4JIrPRadz2KCIAPYVsf5G3MT27GySgPF7MsIMzs1wKFiyPokgH9dVXnYe0xeQfNtGMqBd0NSB6lsFCTykRmgldUSftnlmW2FblilbbY9159Dp5JznS074rR5YmUkpVpk+GiaU7EpevSs3hLa9VJvUbAajnA95JXiLzTS06chuciaAQ/bmHy196xmQQbLLAJruJbeO3lQbZ1xKL2JDtd2Y5kbJ8Wagwy2aWQQ7UAoPET4gOpXWT6SQttpJnpaOG1Uo7LK2h/lTHNvbUyLEzGCA4onPfUyLDSOoSoR67tYsMWgBbetXVFHVIB8pmTEqCed+mo0rY7ZcMT6lm+dWhk8N1VZIismFltAi3KZplvnPkUpmDszjS9M7daEN1RpIxfOf+e/f7MvSuHs8llvMKFw8EA1RJ9cN9GgyVOfdpPJMiVU9KPwHwtMhgz1T31t8pl+UVraIELM1wx+z6VCeKhtmtODkjfsbJETLn3bWUFBIjFkcBTifiUpySLCa8v7GyrixVBTt6kFDZESyVjKtQOsiuq+Kf8HEYBI5kG8YXO31DBq4fELLUPRXTiwth53rI2YbAoYTvRN/KxAGtqMwtRyAa+j28WnI6ZBgVtXjx5c2wTAp3LIsQqN5tRwzMghEkpN8MEF0jPz3rfYl3wiRp8qU2oqtL5hPVUPRepm6IzeG3OqIeAbC+WAoybr5v+xXhUVoHHMeN6Jw5jQS19Rk5bE4SJtJZBgJEPUtmTiQqG92nurrzHiJrMOaOZ4HLEPZKbFGjFqlta66vv3WsGCjD9+mSYeSTwaLwH84A+WDwD/UuX/ktwYI8ghiCZ0RzK3aDtifwJTJODNguehXIJ1pQTzFZbU+lKkaRwXfOWTAyTFYc8lyoIQPTUTLkpMYvXyWVKaspP95WBtMDkxG3RENCEsxoIfKl/h1AMSM98x/R3dpQ2uLgEA20ycOUyDCyAGHeFVFL2TdWFJqqE+QdVN9ijx3ZikKt23qAhyJiaktHd/VhCiNVopUab4kYrQKECSzT4r7ZUVRxvNLBY9jHD6sfIDAPQBqgFhkLBYMylL7uMkiYHCCDdecKvFi+rf9XfbJT9mQtbjucPzMdTgHDK2amS4aRepTzUpHJA4a3ScR6E3k2mEqH1+/dJwzCqePqSNy8oomFR+Yk8ZatU+h7trQwea7/G29NqwQpNtZTcZx4od3yGD1CXUFPBmG+8tWSgVILNzquS0wGI/BBD/oGnB4ciLrhChoN9bxIGJ6TgcSde9fldMkw4pTDowXgB4zgKJyXswKyqjLEfpqSgsJUcBeiM8bYzq2HvVUFSBAk6TfxY2RKUkQSQYyFDOE9pgJbmd14yM+bFNLFkM+1+OqQdECGnIZZCpn4FlJnKu+fHnUG7IAkMRwWHlywaLBZhbn+gMzTIEO3U615NwoxI2TjbojBZhIqUwjoyV9SoUWb0k1/g/Fk+k3kMDZjGy3XlaPqxxDEoxBm2wWmg6rxcLKUaPX7oAiokUnbSN3crLoXk82PnvQUY8qiY/IiO8rg7VWxcTLeHARKU/LqjOrV5Jfcno7fSywP85xalFIQ02VzafqrLMOoupEnGgXwZa4Y612ubLnsvbWtGkr67OrSQS4A/uggSc1OXK1BI5f7nRtHXNkofhYLdTxsblOYTZMZVNY/8yJNJOrGWnXEh9Iqz1VhFjirEcRz+j6oLoA6DkfXhgzspUX1qTzQ2CnvOvDqXToWDYSNfWjfrvLQQuh/Lub5nQFX8aCu6DpFMozsL3gqkfAjrKJbWaQCtV9CUjZ+ekbb0NStNxpn7Mr2IFLqIxX6zcNjb66wMN8RN8geLHX3I/gUioyRryy+fudTluavqY4PrETHVSStHpSf5WjLoJbFXaR2dDssNBhYcIUkl2IFg4Hpg1GoUFuXwdLWLEPob7pkGPHNXjiPEFsdmB7sIBE6XhxJGWW1zyBZNYieIL3Y6Chb2DmgfTCK+KOb3gcp0pSUFMh6ykiXVNFL5/hSxIOjWS+UpwbSE5d1RKjYkMEm1tq35mbqnKD+C53b0fEgtAzyljrONUo1ZWD0Ntm1P7pX8rJ1ROtpk2FkD1FUVFKj5/r8Q9GeD0VZiOtxxZ+NSyOH0tD+w71i/bqDM2wXBEMEbE7Eodj3NRCNsGXYpIPsIHl+DfCAaQdep3kgL3Tkn81B20YGizShWUJbvc8gwaz0nM2dTp2xy/Wpk2CEhPAlK9SQjOZaDpp23m2KZBjxfQD2HKz2JkW3n+p3YVruOBYAijqIxNQhyZmPJbgTqkEJ2YLuQDf0NbBKUYICB/TdNG7c1xXjI4cYBHmZ5QAbDVQLObMWbyNDqQgc0FJlqIah38NCAUqilx7cIb0rOxne/BxXR7szm7hRanUVbIsnq/6g1XTJMOpNSETozX3xpKuegAVNTIM8OmFS6YQNPFpA79yQLgeUAl6CtajYq6sMdL8La5J9zWQurhUjlTyWvvPgNaMBj7jxTcNT+zGwoDHvGOI+QTfrPeW7lEEZnLYWCoIe2Q1DaPN6hesVgzJLny3a1ojrWCLGp4534I/SYZtcSycDR/Bpk2ESxgHKt1uUljmw5eMS8Lpq5DQhFPUcuuydqBw2mSSFQJtIpuhiP4lPb0+/RFenYpiNEzZHYT5saAQp4tncKIFIEAB9HdpgWIiVrBbYkfH0eK7TSP0Ui9EU9fisFh+zr7qgMTKg0TEjz9WJe++wJhmc/7kEehpOXAZjV5QCjQd59DTJMCoiYW7byeKRQZ9VJV7JoPTgFC2FshakDq4RrrymP5Log0zr7wUWZv12MVRBQT0tqf/3nanniLUPjVy9B5LYUVgfZJUWZun/EL1IUYVpW//0q1R61pWfPA4MDMhg/XC0Cs5OTw1SdM+TyVL1FZ5TKToZJZ6FAIfmd5pHM99NGeKLkCKfUyLDKCjXWQUnS0UZJvn8ZCKi1yeF8F/q7ISqTIV8EMGa3UkIUVkIQ1AVipDY0i3d4whsU3iufHUeHerASXY8sNEqP/5uHpqAE5xTWhnb0shI6MaaSh6QIRkYnWmlIJgd6aEYSOnNrm04GmM4QjoVI03znFrRuuXnalyG5pyMZJ02GUaWtgSOg0UYAkuwXlAuaJybBoSplK6kt3zGvlgrWmsp5CwJPah/NYze3kIpMfIZi65cD6FkyJUvo+0e7H3mNrmfojKgEXXyEqAPSMt2WlfYM+EUTPlVVLVxc3bcWFwGm0sR+DB7irYuX1/XjuTZSULFXptpk6H7+xCS+kj0bE6gPznH3elqGT8LxUbvXbnBJuNS+fgzf7c2vRtEt9WY7D/MIXSwwNEg1u9dxGQ8/kw0Ut/SEmw7GXIdGsTm+Z4Buj1aua6kgh7thm5aHYb7A31+lWWoZ5mk37ZGBAH8fI5ZZAPLCqInZaVIHxE03bJq4nR0ky8YHD9uamhANDV6iNcNPLEMneDhXj7dG1CiFQkSOaMnhFitq6T/h8qH6lhISZ8ptS0DiBhPEmxfp3meSOsWqltiu4DIOUoy31MmQ3d0QyJvHWPwyCC6/+DWoRtpsT4o1A3FLWdMArMS6nCkUOZKoWcwFMBT6BOG2awIlcmQiKIAWilWLmgolsUiffhDV8k5JP0PKqfv/LjooAy9VSd+ei894iqx3HhSEEn+a1rkFIhTVdMjrRJSNhD5o5Q8dCJTJ4O9l8n5rwY5AG9qxGE7nI23MmDg5jI0nKSfTlhksN/FFMe2bO3DBKt3sxmZO290BPA+ksxJrmi09IBLi746nCAsDOx4tdKFIRnIEWn1PVTRFI1XbYykvmAipzyFnnwmskENJStFDdZaBgRucB+/TIkMtlOt8xld+rNXwMONVjuQXF58a96cApRugVdq/IENV0oxzo21sPpVggaNVtGmSfHKz+CAMDz7+ZhCfXTtVG5SnGq4PubqJyi5L4mpHcKXZjpV8g+mNSBDDxjS6HCEiZtaSpfRN3ZvGiL75NU0f7dv1bMZLK8IMRG4AYogczMtMoxCWKY3aWRUir4Ub9qafqClN3XrnY6YO0/xbyWke4qytthjYU7ApDIChzdsZ3Qt9BkmVvREV8vYggLExiIiV+6LB0mNoh0xJNlBAIMBGRgYepfRct7D3kztg3dzDY1zfqD8FC6i6GdddZXSUKrQQQe2ejRlMozoOB2UPR7fHBUKw14spBDEX4WMprpEjym6b/MF91xbbWoZnHKoLAi1oWXgoJjC7ROsULXQTwPS1P87A6AHi7TcJvrUlg09d5SNQiF2SIa8UsLOyZNCs5+E1NQuGG++1Cgk3y6RDwsJjHguQ3x0tzEPnQIZRuAOdFVJq5rHuRdLdf94jJeF8+MYPMvvHXVgpFbjUSOGb7LEpbzUjuobf/W/YDQWYViBDT4k3S+JRsspSR47IsD9CfqTdTMS/p14DDg1IAMqaATVkjHmCWsDcfubioSabIyBFjPMekD/oj5DZOQJ8xTJ4KddOXSIGzpPZEXLKxO8TR5PfLqB8GZNb23fGE1oaQNfFUZKbMzLo0FZe61LqBA2+9AwPpoLwdt2MsRB8zCgfXLo0DQxh4cUYbVAfboketZ8QAbA/o6CAxfP50rsg4U3HZdYbmzpuCVQBAKKN7A4ysZ1mBYZ6zTJMFIi9clmvymehXFOrl4eUD84np8s9MN5yZh6Rk1LaFxHyZvx5a35fl0WOKRE1VF1IzLkO+KEFLOcRm2lDhQMPDHBkdRoFOvbAxohfiBBgKH1sY0MUHQV7wOUOiQdFPhvT1EZhb1/G30RhAmO+H1jg4ytUB1fDSrOByN1iBDTIUN9c5+Ews7+tFMfM7aFkAKZcw6sN3NRAMdin/FZgELAoF+ov14kQZhQRfQv8Tsty4W5S7jvz2Ko0YpGsjTYQRZDsDq49of7GMG0n6QTcqawJKw0WzJA7aXKIFSoxGwxI93TdCQMo9IpJoIpgfzdHFnIAcz4VReK9PDHCUj1maVpkWEU6NUOunuMSuQU6mgl/SZGfQlMgvMIE9I+SupLUVC92FCE+kS6tB4J2clPCmODU4O2uQ7xr8CeQ28IWR09jmqdLDxA0fHYiIvRhB2DMefUtmE+MiCDsk23HBAqoGlBKfZL7SU4GhSX6aEd5V95DYNOjxwnnoQGQcE5bt6hd02LDHVjjislgyPgDVmCxApWR9iYK+2A2J0xhIN5GTIKIy7YPkh5JTbolcHbV74MJeBlIa0D8SuUxjEd0wNN3uH8NnlACgCipwNKiAZhNS5EiG1kqMoJ8z9VPjoDcbDQZ0OKO2HvT/4ouDAKq2YqOIkbe5in8XcGlIDMDW+YIhlGoCsgedfMaOmR8K6tDpojMz8zUYqYUKIMJ4O2VSXusSgWpCMADYdpT+JB6BJJ9xE1V0BFIDdye8DEcSnwwIYb6XBHSaeUAjKSGm/aRp2V+MkyqO96uaJgalDQjU4SwfXI9dCoJ4Gqv9jY9ocZEa2NITm1zdFt2mSYpGbqP7UCISBAE2RRkHSWS56wVkqKnFo/5cCo5YrUliIU9efqjmoc1N7QXdubAYPaWMfejhyOZfDl2u5XRGcfAG/o/bEM7sk6Qq7H2ZkJ9szvwu5ds9g1N4tdszOYnUwwOzPBaCwYjwJGYWNjE+ubm1hb38Dq6jrura1j6d4KFpdWsLG5GfVp6VfUc6k89PRpoOPgIqEdbEGjO/NWaMC0H9ZHGl8CNNNv/Wa0s018lWWYlIryMUWR+uyDBCQNTqGVzUkqNzRBNgWExyWpPdlO76ivsD87j2ZmMejYXMAcgJSl69zCfamm9Cg7O0vlzZ0J/pRfRXDlpXfmiAZHRLBv724cP7wfxw/tx9GD+3Dy6EGcPn4Yxw/tx7FD+3Fo317sX9iN/Xt3Y25mBrMzY0qdgOWVNSzdW8Htu8u4fmsRV27ewYXLN/D8S1dw8coNvHT1Ji5cuY5rNxexubkJc9IG6LCTmj7JgS2iV7KCoAIAACAASURBVB2oYal90bE7T4fpOx/lsYd1qo34imUPMxOvkZd/4zLsfdeHLbiQL8IP70kz7cvOHRA6NTC8TOhRyEj1d6c/RliiQ5PgZirauhKjtixsYQsRaTTKhZDAaK/ao3K6PRoJzp48gtc/cgaPnT2Bhx44jjPHD+P08UM4eeQg9u2ZDwPJ+zosp17haAj9LgW4fnsRL7x8Fc9duIKnnr+IJ595AX/8xWdx685dOOAwaKVPICrS9JH0m9tU2iGlS2qygc3loH45umhGwOVfBRlk4V0fpiBAiGn0C6UN6TGMYLcaUeC5PN8zhKUb7rbGYzA0oK/MjO5wdGo5I3kjNBqG28EZaFAyz+at3Lj7MR6P8ODJI/j6r3kcb3/Do3j07AmcPnYYxw7tw+5dc1V1ET25fxN1B0cZai8iWLq3ipev3sTT51/G7/3pl/Cbn/gczl28Qipgvesw96zYPxuo47UJGJDGK9VseESjfm7t9A3h/w3JIAvv+nBx4s5yvrhZZIGDUGJLo4b06wywuKOqeqhjsvEmYGOgMrqwg7RCzsA48qrU/PwcvvUdb8Jf+cY344nHH8Th/QvYv3c3ZibjQUPOBs9XdoTtIsVQm61ScHtxGecvXcNv/OFn8bO/9nG8ePl6xZN6CM5S4ipUAoy88hbycdYPkCJB/g4Dku4OWViKEHG+Z0qzMSvW5v9fGWqEiA9ihGO2wYu6zpv2QxHO+gopUk1VdAWK65NDo3q9T40d4XT1Slj5QcjOsz31YqUysYwAKVKxtshhxqMR5nfN4uEHjuM73/u1+ND734ljB/djZjLGaCRxIAau7VKkncq0vNVP6/fG5iZeunoTP/l//w5+9tc/jpt3lrC1teUyqYY5MrPOSA0Y1GWqn0Gr9YlS3+aSaIbyRr9AGq+/fBlsDmHi0LyhKLWC6DCcf3VuHUBB7+mAhs2PAaMxupw7Bp5SYBwwulC34bWGVA0gag9swczMBKePH8YTjz2ID37z1+Pf+trXYd+e3YP9b5WC5XurWF5Zw73VNayur2N9fQPrG5vY3Nqq41gwGo0wHo0wOzPB3OwM5udmsXd+Drvn52y1qSVnC8CGHEivT3z+K/iHP/UR/OmXn8Pi0r0eLQMVS1EKJCILoW9SbQI+vhmzhTgm8WgPT3xbGYWCWD+P+MuUQRbe+WENSKFG6LKUupFRzYkDB/OqdTHUKRHP34fK0PiO9r0mOmcmGBG0Ye67tpuZmeDRMyfwjq95HP/Ov/02fN0bHsP83GzPIDc2t3D99iIuXbuFKzdu4/L123j+pat46eoNvHz9Fq7fWsStxSXcuXsPK2vr2CrdxuRcdYQDC3tw7NB+nDh8AK86dRSvOnUUZ44fxgPHD+HBk0dDnzmNGrpa6dWl67fwz3/5d/BL//qTOH/pGspWhTx7e51RjspS8Kv3THNCOuf0Q42jVOMWpjk0NH1Dh1umy2vOwznEX54MXcrkHLgXVqE8ykUUyBGj8SI6kiudVcrGTLQH07eck21ztRyxE0uRIwKNTqK0zWQ8wmNnT+J9b38j3vf2N+IdX/M45mZnOlXWwdjcKjh38TK+8Mx5PPPiJTz74iWcu3gFL16+jsvXb2Nza6sOqLj6ydHDipnyaf2PceroATx65iSeePxBvPV1D+Mtr3kYp44dhCA6wk6rVXnecmfpHn7zDz+Hf/ZLv4Unnz6Pjc1NbDfPy7qJem4vYoTFjWTn3c+G8de+JBuSB+qQ6TCImpb/EmToJtWJ78yurdX2cva2UnwuFFFqO0QLMvLEqVWhWZAhvk28Nf9hMiePHsR3v+/r8a3vfBPe+NhZWyYFgK2tgpev3cQffu4pfPILz+Arz7+E51+6iis3bmNtfQNu3cLCpDSsfrMBasjg4Rbj0Rinjx/C6x4+jfe+7Q34wLvfgpNHD/UcY7srg8zq+gb++IvP4L/957+MP/7in3fzCqAPSjx+5lhWUMXNluogGRxf0yC1tpbNAGbk0QBLpVU31uj1kwTzfyky0KS6VjBeQtyAu0M1dAFjH9WtocvCGjOfoEIVELSZlBK9D70osZ0ftICoNyBdpZEI/uo3vR1/44Pvw+MPnsL+vbut6dZWwWeeOodf/b1P49kXL2EyGWN+bhazMzNY2D2HmZkJNje3sLh8D9duLuLFy9fwzPlLWFpejaGoxWwzYvbLRiLYv7Abj589iR/4zvfiQ+9/Z5jIA20HGUqxNja38PQLL+GH/sFP4k+/9Fy7X/2itqF2YmKk1ZzGJDbMDXPUCJNgpHFNWYMSbNlEa5L8F5RBFt75fV13Tafrp0mWbljwYzQgL4crI55NYg9XZiUpp4E6Gk5b9bEDraDI2n+tOzszwRsfPYv//Pu/A+9+y2uxe34uoO+txSV8+dxFjEcjPPTAMczNTDAajcwYdUe2VHm3tgq2trawsrqOL527gI99+s/wrz/1JJ67eAX3VtY8lRLeRaUJp90D6dRlEAC75mbxTW9/I/7e3/wQHjx5BJPJuBephybeXAYAz128gu/9u/8TvnzuooFprBdMQG0IoGHs3SNVN8A70WzxqcPPu9+ASNxLslSJMpJWuv1KZLCUycg3vI/2ru2bSh3cIgFFW2BULVUCNFnvXQyozTmE9g7oHzgcCAm98pnJGA+fPo7v+eZ34Ps/8B4cO7Q/IO2wctvLniyv0tBrdW0dn3ryafzMr/8+PvH5r+DStVudYzSvFC0BhOU7uh49cwI/8gPfiW9955vCDjj3v90ycKmT1s98+Rz+03/4k/jScxeo36jP3jywkSol7uOEWwZ4sQaZULJikXbV1oQx2Ncrk2E8d/aJH+tuCd3XyQ1beOeNlgeKE9FORGJ7neToPN2VUw07CBKVUZSuFuv3hlY6e5EgvIfLyijB1aEDC/j2b3wLfvQHvgsffN/XY+/uXY72acBaZVreQlytz/fGoxEePHUU3/7ut+LR0yewvLKKa7cWcW91NcqeE2nOvZMMgODGnbv49Jeeg4jg0TMnsXvXbBiPIV6VX/199OACjh7ch888dQ637y4bDx7FdOxKHA8ethAFKmwGJFe+ksNXsOOIyRmCITjfB0fRWD/y9cplMIfo2rulK/2eoREdpSK1vjuP/nYmwiD1jIlWAKpQjCw8iDDFMj30eHShI9Ovf+QM/ta/9234oQ99C1770OlgwEo7G8/a+gaWllewvLKGra2Cydg34vjiti0nGo1GeOTMCXz9Gx/Dnvk5vHjpOm4tLpsxdYsIrJPSBwX9rIh7d3kFf/bsi9jc2sIbHj2D+bnZZqTIcvHneDzGyaMHsbq+ji88cx6ra+s07Ix89Z9WxNFqbJSA20ArfaAUyCe2DgpFCJihZbU+20Y2bOLplcoge9/1YTrl7KFZiu49sAN5wpSdWZsbhTpgzhDcwNsZgNfJ93JG1cqwBrIuvTe/axZ/5RvejO//wHvwDW96DcZj3/jiiefa+gaeu3gFT527iOcuXsFLV2/g5p0lrK6vo2wVTCZj7J3fhRNHDuB1D5/G217/KM6eONx0qtal9xaX7uGjn3oS//1PfwRfeeElbG01ji6wXKQXB0q/eWj/An7wg+/Df/Z9H8DMZNzjY2gjj/l67sJl/J1/8vP46Cef9JQu9NtaJOEUBcjGYbOAEElq9CuAsIBiHXkDjSCmGonGF/gB4goU2d19yjDpjLjUkAR/BqAnaxTcwSoyn49V8CDElIeYM8H7/TgRroOe0uywRzim3dU5fmQ//sa/+z78tW95J04dPYTRKKJmKQVfPncRv/WJz+H3P/sULl65gTtL97C4vIJ7K6vY2NwKChYRzM/NYP/e3Thx5CDe/ZbX4nu/7Rvw6ledMnbz+j+XAcC+vbvx7e9+K/btmcff/kc/hYuXb9DgkLwWqt0INHr62Auu317ET/zSR/HQA8fwofe/c7DfIScBgAdPHcWHv/09+LNnL+D8pWuuR+WKkY9Qmz/8e7UpHj7L+CSIpjJA55jqLNq3RhDEVE/nrTDeiqeYIRLdvww+qQ4cgwinAaKzSCkyordEHATevj77Qet3ITQISqbvaixaPh6N8IZHTuO//I/+Kt7zta/H3Iw/D7WxuYVbi0v4vT/9Ev63f/X7+PzTL+Du8gpW1zfMQLbLu0Eyzc5McOb4Yfwn3/Mt+J73v2PwiHc3HtEIN7e28Nt/9AV879/9J1hbX6/jMiCk8mAIFysUAU4fO4Rf+Ad/G088/uC2c4fWZ6eXTfwX/+PP4Wd+7eNY29iMOg1RQNmrWYOBXFcqPQHiOSU7hZGE7D0SUO/nyTk48hi9hORQgL9/GWwOYcXqupa7SuycvFeXZbsJc2RSEjM0JAE5OGJp1CxUbnTEnpOq9+MhsI5lH+Ddu2bxgfe8Ff/07/x1vOW1D2My7k6grq6t49kXL+MXfvMP8KM//vP4F7/yuzh38QqWV9a6J9BQHMFMc9oHo7Ub9+bWFm7eXsLvfvqLWFlbxxOPP4g9837sO0/YGaFHoxEeOX0cm1ub3SaZOQ8hSAA1RULiSXVeCpbureL5l6/im77uDdi9a645z8m/ed4zrvz8qz/4LG4tLpsOGEwLj7fEHWAR7oO92eeV5jBSgTfJECIlCCDMJ6TSgNkkPyUH4cUIvCIZfJVJFH39OIHlqVVZ3bJsDLeBYUY2gYW53sTQ0D9utaty8nqzIYSoYApHLKAP6qmjB/G93/aN+Ps//O/jyMF9ALq5wVdeeAkf+b1P47/+iV/EL/32p3D91iKFKphCu76IuD1qV+tayIavdADYKgV/+qXnMDs7wdvf+BjGo1ETpbP+AOCxsyfx2aeexwsvX4sRwRyfQ25d7zPU8M8tFNy6s4y9e3bhra99uDf5z6thmZdSCg4fWMDl67fxqSefqRYe01MIz3dSCFPNkJGXSoMNO+g6yWDpr9ldxAZzCrbwBB5qL8bnfcoQIoS/EsVRnNE9e5p1KpJWikrfeBGI1FSJFaS8SRVXqJwhKAumX7v+X/vQA/hbf+3b8B9/9/sNpV++dgu/8rt/gh//hd/Az/76x3Hp+q3EDynUcj6JitTbKme9L2mkCgq+8Mx5vPHRB/HomROmpyGnUAPdNTeD3bvm8PHPfBkrK2vQKG1zMhFyClqWzqNTBCtr67i3soY3v+YhHD+8f9t+W1GrlIIHjh/G//HRT2B1dc3pk65rQk56IzbC6xXdjmpHrnMbyr4MsT+OGrwiFfkyPrRqKLw/GcazZ574MdeXe6kwKbZBNpYwyJyTspB6mweRBiN0EB0kC8cPAZlDVdqj8Qhve/2j+JH/4Dvxgfe8FXt378LG5ib+4HNfwT/+uV/Hz/767+NLz13A5qZuiFlCGs9MBcCIkSPPw+y5c/1eeVtb38DVW3fw/nd8DfbM72ou6ea5xWg0wt7du/Dsi5fwlRdeMn1pNOhFiGTk2bZuLS7jxJH9ePNrHsIM7WSHyD4QtUQEC7vn8fmnX8BTz79kwBdiAUf9CgQRkf2TT0KDnTibCMtA/YVnJMQNuAjZn84j2LeYzn3KMJ4788SPcZixNWFowqMUnFQ3Ln4swxzIBhru0RVRCw8Gh8LAGFmc5SN+3x0oDuZ4PMa73vQa/L2/+SG884lXY37XHNbWN/Dj//tv4B/99K/ij77w51hc7p4BiMck9DPvk+jg+X3jMa83G4YQPQB3l1fwyOkTeP0jZzB0ZYPcM78LtxaX8AefewrrG5vdWFg/bkThbA/xyyt2axsbEABve90jOHpwXz9SN/jgaDESwWQyxq987NM2HgE0tNBSOG0v4CgQeXV9mS63kUEIBHryAnGCrPXIwGHzWhqnHWQYuYeQIWpHpf4oXSN7UxocnS2lqgauxiHKCssQwlgEiELG5AqSVEvZdF5FBO/92tfjn/7of4i3vu5hzEzGOHfxCv76f/MT+B/+5a/i2QuX62QZxm9mIEwCTcleVmwUOTfWsoRKVV83F5fw23/8JDY2Nl1PZHit/H1mMsYTjz+I17zqFIoNRN+QQ5rGMoiOV1f2J196Fl+sm3YAkFe7hvjQ8jc+9iBe//Dp2Fd1SN8DIH0ofYoC5iQ8lCzSdjIYb9Q3G5ECRTU8yXRzJLoPGbrdKeqjgDbkROz1KzaprQwURnBzktpex5Jva1gtyowOkHlfbeOfKrwvgypqdD92zc3gO979Vvzc3/9hPHjyKO6trOEjH/s0PvQj/xi/+rFPY/neGsmWFElXVE5kqUKVjkYiRUZAI1FEsLm5hecuXMFzFy83c3aWiw3zsbMn8dqHTlekSvw0ZXAdaYqlBrC0vILf/8xTuHnnblhezZty/Ju/H9q3B9/wltdAB9PtncBCUdB4SuNZ1eSpcd/gt5PB9evgU8wAsy6inkr45/5kmACIa7jEiwrjWxGFwlREb8tRMwFKR3wZTMOgp02dQxMi2hvVuF3XbynAvj3z+K73fh3+qx/8IObnZnHlxm38/G/8If6X/+u3cfHqDeN9POqOJkzG3eOak/EY4/GoLsN2uXu33NgtgWo/o9Goe/HtwFXQPSnH8uvjoVtbW9jcKhiPRrh8/TYeO3sy1At0Urp2YGEPHjlzArvn57B0T8866QA0+BHSjemumFF96ovP4Pqtuzi8f6Fp+EPzChHB3vldePOrH8LMZIL1jQ0aLR8HUSQ2oIJH99bR9/BiJq2/vQyhndlFcWMPqRrJYt1XMJOyowyTYny62ZX6r62oaDoEn0DGJyFooAw0+4jo3qoi6e6yKyWTnZ1MsGtuBrvmZrF71yzm52axZ34O73zi1fjBD34zjh3ch43NLZx76Squ3LyNb3r7GzA7M8FkPMbszAQzkzFmZ2YwOzPB7GSM2dlJfVPeDEYjsTdkTMYjTCZjzTgxmYx7b9Hja6tOnu33VsH65ga2tgo2N7ewvrGJPfNzOHPiSGiXI0SeXAPAQ6eO4uC+vVhaXonoVyNj0+BCPVfgsy9ewsUrN/DY2ZO2Q5+voZO94/HIHmd97uIVQ0YDsVb/wSR4nlj/oWHubHlnGQBa+HCD4Y5C8HR6zKz2v70Mky73klCpJGq9yAdaK2YlBFmkn03UupPxCAt75nFg7x7s2zuP/Xt3Y2FP97lvzzz27ZnH3t27sGd+zl73ODc7g12z7hgPnjyKIwcW0G1uCV7zqlN4/MPfgcl4hJnJGOPxuHmmJ//mlZ+h3duh7zu1B/pG3/qdaZ062r3QLM5X4AgYUBgIA6RXrbu+voEnnzmPb3jzazAj48DXTvoQERw5sICHTx/HcxevOGhrBlnISFPKqRhnLKUjDMb2fciAQk5F9VwGW96h/rq2eYVrJxnCu125P95BbPHrIlGgK4CMBAu7d+HowX04dmgfjh06gOOH9uHoof04dnAfjhxYwMKe+e6dprMzmJvp3ms6OzOpr3Lsvs/MjDEzHlsas90xivFohAMLezB0DR20Yzr3m1e3aA0ZfMv4duJHRHDk4D7bQ2nyjLih6WkDaEgU5ASfe/p5bGxuYnam9yrfkCJlOUUEBxb24Mzxw1o5ZiqBExobA0vSQwDNjsmYZWwvg4T9IOWZ+xX2t65cv+f5xjYymIaMUK0UcjGdfUvX7cxkjGOH9uPsySM4c/wwzhw/3IXWE0dw/PB+7J3fFXL1yXhk38fjLjffbhmwtYmVr53u57o7bYy9EuTfbud5J4dp8Z7bHNi7G7tmZ2LIFgdTJwRHYwBsX/4cQcFTz18M850hPlrLrwcW9uDsySOYjEfY2ip2HCd1FxjrltSLPwNjgsL3j1KavJMMMWPRJf8IC6kTZoj4gftVrirARFOODqkdoXfNzuDgwh686oGjeNWp43jo1FGcPXkED548ipNHDmB2ZrJjemDKafweyltNrFSWDa6F6kOhP/++n4gx9LvVT67XcpydUjFuNzc7g8lkHEMz3JACbUF6ETN8wGvRs+cvY70eWmxFhBa46L3JeITv//b34G2vfwTnLl7F8y9dxbMXLuH8pWu4dWepeyv5+gbW1jewsraONe2ndq5THmXGncF5vR8ZisntfuTpkf8IizrUj0WpMC+gtL/Wn7z3a1+PwwcWcPrYITxw7BBOHz+M08cP48yJwzi0b29zgIcMaicDZlpDAzB0DQ3ekLFu53D3K8PQvfuJYENXlqNlmDOTMcZSJ/T1nJUvcCQ+C1kD2Dbc2lbW1nDt1iIOH1gIfOwEQnodObgP7z74Onzjm11nW6Xg9t1lXLxyAy9euo4XL1/H8xev4MKV67h5ZwmLy/ewuLSCxaV7uL20jJXV9ZiGsCnehwy9NKtQWp9DS/3p8QT0ehvNl2DpE+VWmPzLv/dD3RsmtjFgWPv2IO5kfFw+ZEhDqy9D9bcb0KE5wU5OkXloyTfE63ZX5qulKy7b2NzqTr3aDDClSiHWx5vOSuT38o3bvec1WjLsFN31Govg0L69OLRvL97wyBmru7VVcGtxCZeu38Kla7fw8rWb3buqbtzGtZuLuHbrDq7dWsSVG3dwa3HJeb0PGcJNjTYmg6dDfTpULgQuWk4OMhlyhmzA2Ui3SxWyoltovNPKzv2kTPy7xfeQwfHvITocaTLPuT7T2e7aLr1kvtbWN7rddYsC6AGqcOznJVjli8cBwG0zvj4/2+k51891sq7HY8HhAws4tH+vHVsppWB1bR3Xb9/F9VuLuH57EVdvLnbOcuk6Xrx8DRcud1Hm9t17KOk9UaYCRf0QZDr5exHT6qR5Rj6EahGo+02T6riTOZT7Dxla/p7bDA3CTpEgXztFnJ2Q/H6ixJCxb5d3D0XS3H/upyX30soq1jf0xWce6v1JM4I10wenVH2ad5b8LFfms+Xo243vTo6Uo7RINy964NghnDp60O5tbG7hztIy7ty91z2huHQPL1+7iaeefwlPnbuIr7zwEs6/fA0ra+uqxdq2ZjthbtAV6n7FUHbmtl9Ijx59zCGyIQylLa9kPrFT6tNCmFZakem26AwNTL7WNzaxurqOLRSs1ZcQbxVgeWWVHs6J1+bmFpZXVu0FZXyNRLB71xzinpdgftcsxqPuZQRzsxOMR6NtUVd5L6VLOe6trvOow/JnLrMg4cuc/gwwrK6ge0IwZwCtyf0QKA6loUPtW/1wO5FuM/Tw/oWwi765tYWVtXWsrq5jZW0dtxeX8PT5S3jymRfwmS8/h89+5XncvH3X9VGq3CSrRQX2HNJHbVGZqf/UexNmcMgpwlDvEAVy9FCF6Juvu2MNW9jcLPZ9a6vQvYLNzU0srazi7vIKFpdXcHf5Hu4ur2Dp3hqWV1Zwt74BY3llFYtLK1heXcPK6hpW19a7z/UN3Ftdw8raOlZWut8ra+sum2UXldeMIr3ftLTBk7lUv0mP2s7vmsVkNMbs7BhzM91G4/zcbPcsxPwc5ma6TcfFpXv2x05aaI8ez5w4138KgkHkB4XuN7L+Rept157LWvUm4zH2zncvcgCAB44dwuseOYPveu/bAHSAdv7SVXzmy+fwmafO4bNPncOFyzewvLJqY94d8c/gwU6Zogrtm0xaqZFeGUXyvdW1dayub/jn6jpW17ult7X1DaxtbGJtfR13l1dwa3EZt+8u487dZQuPd5bv4e6SGz1/bm2RAMq45s4BHXv6jsbYMW88c4g1JwbiI4hu4XD06crtfUC1mr331vLY6E0FWr/g3spaJ8Ny7MYndeg7F8d/Bh8ba9YNqQwsn+DQ/r1h7IZSvu0i8P2mta1rp1Rzp371+8xkjEdOn8DDDxzHd3/zOwAAl67dwpPPvIAvPHMeXzp3ERcuX8eNO3dx4/Zd3LyzhI3NzToOPMaw77bJzCkTMwDA0Hfp3gru3lvB0vIqFu+tVKRexfK9FdxZ6nK/29XIby8u1+W2zqiXlleweG8Fm5tbPmBsc8aYl9mkyX5zxAG6P3hIdbINBroRxYUJ50STjVnrJf+wolq31MHqoXX4Y45RyDDuLd4tndWIFKMTy6CH7F1ZtW9dfyE8OFLTEga2oblgjvhL91bx9PmXsbK6hoXd81jYM4+F3buwZ/cuzG2zHzVEL/c31G4oTcsynDhyACeOHMD73/EENje3cPXWHTz74mU88+LLePr5l3H+Ujdpv3DlBq7fWrTXiZpy1OhKweSzT53D9epJN+/cxc3FJdxedBS/W52gS1/umUOsrK13qwFZmIH0w+zNxq4OaEn12AgEvmFDuZ6kNi1lRi0C8SQtaqiMWB6QGoD9DTuzs2TN4s3cv1iQyhchUFz37vjKewymAlCfLRlQ+uCgOk3R7uihfT3D3W7Sz2WXrt/C//x/fhRfevYCFupZM3WKfXt248C+PTi4sAeH9u/FwYU9OLCwBwf3dZ+75+fCqeGhifzQ2LXmotvJMB6PcOLwARw/tB/vetOrsbm5hSs3buPFuor1wstX8ecvXsKXn7uIZy9c7pZ+TX+CyQ//d//C/tLNvfqp+TYPtCNkh0T6+J7eMsbyoLKP5IHrlZkaYsoAOOrGao6CLW2qEYUUq58aSeYF0ab8KIsbrw0OSq0X4d6QjOmaw0lMA82xHFQiiwMymLMR6706wMzMGPvTXzxqrSYNIfTS8gqev3gVTz79gvdUnXMyHmHXXHcKeb6eRub/9y/sxqmjB3HqyEGcOHIAJ+3zQO8PUjJvOaLcT5rXkmE8HlkE+bo3PIq19Q3cvHMXV27cweUbt/HM+ZdtLvLshcuYPPn0+QoqES+FJhqsbQ/UA2icr6YhDhhwrd+etLJzUH1Btt50T9Rja5nE+4AjLzt+M5WRHhk6t+nshkFRRJfEm2rX+ZZ+h7FtUwaNSBkwvO6pIwftDeHefXsPpHUtr3ZAaWouzuL6xiY2Nldwd2nF+SHHH4lgRg9wTsbd90l3LP/owX148NRRnD1+GKdPHMHZekLiwZNH7WhQyzH+IjJo+cxkjOOHD+DYof14A87gG978GnzP+9+BpXuruHTtFiaWtRRf1iuaUpQSUmyzaRo3ixfxjQAAIABJREFU71+Nygv9XU3dZy9MQvrGT8yHteLmKwp3+E5lsW8dWDVSlbm7achPRmVSGkk3ZJ/z9j02/LkAVh3pUtMj1UXvD8WYWFkGvYEAGGYcteDxV53CZNx/tqO1qtjSv6bJlhGwzhKPqGOKKsNWKd0S6upaL+159sJl/NEXnrG6CgqTyRhnTxzBI6eP49EzJ/Dw6eN49MxxPHjyKHbNzWCmOpR+smxDMgztr8zNTDA3sxeH9y/gzPHDvA/hw6UpgaOYvu5ePCcWGuyA0LTioYxIiio0mPkYeXA2TT9UYSW+/a0fDkwYqstpkW9u6byaJ54aJ01hltZ4WtRLZdBfXRKbF7B+SvdG9KpPm2/xokFI/2pqWus3ZTD+NToUVyPx/+jZE/aOqE6N2+8xuRq7OjcXl2xjzzfElUYfkX2cq/6IH6kIIDRG2NLHhQXAFja3NvH0Cy/hmfMvB3DTP3559sSR7v962vqBY4ewsHsX9u7unqNZ2L3L5i7ZCXu8JmeZqFYLGaYasw1HUlJPeRzdG5Mlcy6ztr4K2dFyHX43kRmxstukh16EsJSHw1pehrNopmmImGN2/HF/Ka3hUFHUiI35Ss9cpt9ceTbStX6cwPVkCBFWn39nLy8Fr37wFMbj+Cqa7XLzXH7j9l3cvrvkPChYBVBh4ycZlB8FsBBd718GQLC+sYnnLlzBuQuXHagAzM7O4NSRg3jgeHc49czxwzh19CCOHNiHowcXcGj/Ag7v34uD+/ZgZuILq61oUh8hFe8X1WvTpI/MJCC8DyAqAlBZVjIQF0oyUhWvFCavEIQcnD8ZsVqeoQZV+cvOwOgfUyyE9NBQO0dEUq5oH50lxzQP6PUddAJSNB3ayc+79+ZiQn1TlFaNz++aw+MPntw2rWhdOi4ra+u4dvMOVtc2+ilzYMdcnXQKFNPBMA7tJEPIOtCvs7a+gedfvornX75qdMajMQ7u24Pjhw/4w2oH9+P4kf04deQQTh/vjpEcP3QAc7MTk3li3kwdSOjUPwoLY4ZIvGsYNAOXlB5FZfqKSuxLHdTuFQRn6oFrdlCl0vqbTyxrcEgtQ7U976WHotUwLZ6K85nCSCMKKaBWtA7zGO3H+Q7LvT0ZAjsIY1kN6aEHjuHYwf1RL9I/umGt0qT17vIKrty8XfvhQdcP5c15YmDK0QJZl1GlTRkskS1qh93SewAp00X3ZWNzE9dudidrVW+j0Qi75+ewf+9uHFjYg/17d+PIgQWcPXkEj545gUdPH69HN2wuQGGPeLI0kW+kCvZ8h6ZalvoV30vQ6lVAdbyewRUKoyyvAi2ykXaV2oZbP4lWnuOE+QKK/ZGOkMax7HWAt412zAN8sAvUAIs7otJj5wwRYhsZQiqm95yH1z18Gvv2ztvYMK/6PadSnFLdubuMl6/dAlmJzeNEFBTY6RNiAvwn/XrgYExvI4MEA9CU3pSCuACCIGv9AaBgq2xhcanbU7tw5UaVoXs4TpeM4zPV2RmQjc64rUZCp1YDotZ0B2nFhgzaBpel0ElWcoYeyjIyVT7CODDZzL6RJDQ2unEeI6Ts3nPMmuYY+qV7WqQ71tQHavRsmga16e3FJBkUrNwx1WDqmIjgTa9+VXjeRctb3/U3G+O124v1XJXza9mgHaWmsbRI4M7cS69NgJ1lcAQA+I9RMr2wqNGjp/XiONgq9VaXFq6sreNmWcKIw154k0bgGjUXFEsVAvRph6XUkJiE5xDISjOBnI4oP6VUbWkOqf3U8nqv1N/FQlm9Vw0qDgClAyA0Np7Y+Ao8/LszGB/VEGIGlp2mgP4IQmBD38xnLBYVraYIhbQ/IEP3J6cQh8LsouDE4f143cOneyd0+eLUKciH7tU6V2/ewYXL16uhueydVorx7gAAu6O+oiXGG/3NkZ1kIHRKWy26vFtl6NVzeyk6DvchQ91VVxOnQWclATaw+pC4MmNOot8buaLPEYQEd8P1e0KoLoGegTD3UcO8fap35TlLQq+Od17ZoI+MdMYLyUQ278unhFSEdIaeJqeSc7nMF2s7IT2UbWSIcyR40K2g8vpHzuDsiSPB6PkzO0JO91bX1vDn5y9heWUt8FwbOI6Tgau+LA1Vsya9iYKnYEcZHAi7fhyvGHw8TbdxKWruyrfclwyjbgGDI4GPmr2WEoCuiXsa43Qtn/bKwTGYuKK2GnKeKJozEt8qtAeGiLqwNmmtWX8T6quCmNXCfLJsJX3PUQIl0kcXS7r77DgUzYo6COuF+lGnKj6UQzJwxDBIq2M/Ho3w+kfO4IFjB3tzB54zdF1K7zcA3L23iiefOe86rvKajYS3DSONmY5H3jOpsguB6oAMzIuNS0nlqjLWN4GqgeJ9yjBSm+zstASCYvHHOQlKC06hCqgEegPcFzbMNANbEo3EtFWIL1eQKrK1ps65KAGYGwlo0w1sfL3OrUOPqr5ZFmTIjlkVapNpLSM8UHWYM9HNIRmCxsRrlFJw7NB+vPGxs9i9a8544bEbWnplvheX7+GzT51ToaCbs6IvJO4hI+tL+wqwHe8FC+7LwEBFOG1dsBshfDd0DWB/PzKMNH2IhsaRwRGkQ6fIhpNyoQhM/R55LTNoTQWInVJZL73Sf4oZd3/+k5XkCMhRSRIPbiDMs94X+BvJGaEdnXQ+FBYjWBbhMSKAqOXRzolGSwYCKuekq/PomeN486tfZfc4Slj9bdKnrVJw7sIVPP/yVWjEEusXidHsFGbZSYZk0UpvQAZWgdC/+pXLSt/oEhjfnwwj3fSye+YAyl004LhrG3M65UztpKdwZYQHgCa+xYRoISz7ixpDXU9H6Rl7aJ+912RTfTkDOvkrlrbQmJXSTcqonoV+7iOMuVhbcyiWQ+tlmxr6TTJYpAECIMzNTPDE4w/ikdPHuxoS9x2Gdqf52trcwv/zx1+sf0qg81Y7cSDxyEaMcmzcpV0HBXa0fkAGjRLBFgqXw8a+k5H74zZSJ9L3J8Oo71geHYrob2ebJzMhVqTQUNKIsjN2dkSQKkQ3h/JqcGZnGkprOxFaopN68KJQtAiwS3k8Iz9ttNhGm8lEBwy1L6nRlK0z0dNVJCsLwOK89TKkHDW3kcEnri5DQcGBfXvwxOOvsjebuyo8wuT9hlxvZX0dv/XJz9NUJxp3S5zed5FoBZwCivPQkkGjhPPmNhjmPgE8HRQ1awDwimRovA9ald8NqJhnwTw2CFzHXcObejCnWb77KrVuRHNLXSoRS8tq9GDlQLIh8P/Urw52I5e39EXbG7k+X4Y2lfcQDXj+o11pWsS5USGabCKFNuGgEV5hhhxqQAaPqDwsgl2zMzha/9jk0NWaO7CTfOXcS/jzF18OVuOGmHRkTgYDJaXpsrFTe9mQDA2O3cisM71D9etYFbWzBEY7yWB/MIUn1DpGPJnjXNcGw8KPh0pbPXIOXEadsErrnt9XRDD5ya5cERLpsQ6rI/TSAmOthL6lkHzGlxhdtmveuOtM1vkUU35yRFdjdCKw/ORo2k/LMEiGgMYqcyXFfzUor8pxCtU8RiGCj/zen0Q/DIMARCOOiY+rUdwUeqkI7VU0ZGhdeQUxsGagLL3br0SGkZWXdAISDrxxvZfpO1KHkEsiY6B+MAAzbPZ0CQ5QkhCc92uY8s0Zdkrqk1Mc66c4X3n+QXOVbqC8vKA6EvHgrGj/VYNFzSTqI8ggAgjJEAx5exks1aqGvryyiguXrweDbx3VyJc6yp2le/joJ58kXfAYlF676Nhtc+63kmBNWYZ+OzpuYv+ShTVwKGQa9ynDKDqdo5c1LLRuS/870LJxpb7UUFoCcghlCNbONVJomiWRv4jilIsTHVeEuG2bWG5YXa3YOGaHHj2JYp0fOw+O6dkRAAnL0nVWZOlF1bOlQsXlM3p9GfhytQhuLS7js1953l883EgZWt9VJ3/4uadw8coNQ3WXAT5WKkO+xO+GYjLY3j5SQwaOOmHH2r51+jENWpVC9eQVy2DPf/v5cw11aoidUYqktImEN2nqvSAYTeRcWFQDSKMr8HydL4l1TAP0PcwrOBJWxzOHIhkrzHtwqgJ6qKdIo/dMhg7hnFXqm+ZMHRkfUO1HFxCcx1q3+KKFB7m2DNpvTs83NjfxR194Bn/wuafQsj1OmfLkenF5BT/9qx/r/mqr+jrLZ18jwvPVO8JiHaso+V5fBgYDyVEnoHzUFTuT9fkKZBgZmqoxJvTUfwutAESiXtUnwVSFo0PKAdWDC71tTm1fJ6i8fEaEGtGifrYmxMEoCGaF6CbZObQ627QCp/WtTuQvKj/zpewK0VKemE7sqykDUopRZXjq3EX81Ec+hqfPv2TzCb56x2oALC7dwz/7xd/CJ598uvtbEAQ6wbEkF3AGEE/SBq4TYDGWt2Swytl/xP4Z6EPi71cgw3ju7BM/1t2n80AV+UQiU+YenNL0+CRm4IOsyBqX2pQiRQXhk6USaRppUlKOEgES4pKpt1UZ6F79HlbG7N1KXl+q4/vEnzYFqV4XfMT4cLlMUTZgvCKl49T5Ox+xaMhg6gjZOHT179zFy7h+6y5OHD6AE4cPhEcqQeOxtVXw4uXr+Jlf+zh+6iO/i6s3F+l+jEw2NpR26DKzL4EXlMaL29xRLOjtKEOI9hGnK510ZF0i5r9SGcazZ77mx/pr1dy3H+y29WEVrpTGA/GBnY6eEfBjEkrRjJEQ0pboLO/mdiQQnEzPadjgA8oQErvlwVMdgwSiVT+qLIEXNQIy1vhXacjZrJ4DgsoaJsCge8RRTwaI69SONzt4bdVI8eVzF7C4dA+j0cj+Xp+I4O69FTx74TI++qnP43/95d/BL370E7h6azH0SaLqiBILOn7phLMIgVwETVUJO8p2MnTqKaCz5M6bDjnpN/wRxb+ADLLwrg97QsBGWb0cTKzhgUrYdwzj3TAlKOyd3ie5I8AGC/+Zy7O9Oy1xmNX6itq9VAvu1MWNLm8Y2Z+BSnriyNHRQd0EUjrMIzOK/n0g9k31WGCWwV72RlWHVpD2zM/h8bMncfLoQezdvQsjEaysruPyjdt49sIlXLlxp9emf20jA3xsG2xvQ/H+ZeiXF4sSodP/DzLI3nd+uKiXSB1U1DdGlAB12hrJ4xInNPi8fNsa5DD5MsPYRjI2Hq5nhtTx7nU9tjUjQsdE/MlDqjQkaa034jB0i/WobYg4mR929pL6ENdLkkEdQuc7OSVxMoXK+3W0Jt/PV8xWdrK+lNtoi+2caEpkGFlupWlHcYOgPUc73h2ioKKh/rQJTFemO5F9VIbdDzwJyFWJtADdiweKl1taBfhEzstMHvZeyzOJX7oHDcPMl0j8ZJGL0mT5WVYSoNemhE/7rsZRx8L7a8hQYH7CV4g6SrPq24/hlNAmIC031fo5khePlP25qZ9gsPZ+M2DAtMkw8omvHpKDDXLRmrpJVo2Ppedfzc0ejgAmfcmVTPpS0spwANtOk72d10Y603O0nObAfMD5FpWpVLm9n6T6rp7ZqCSbTyPCY2RdOWgoRZ9DSKg7JIMBSolyMbfS6y8QNB5baYeBQ3b02rxPsy9fhPmke2DqZBjxLrReBsRkKLb2zl6llWu4S1YDMy77qZBejUDblu6en4Hi5Vak3JEmm9oWzpMhSCmk26wMktl4pwHIiK4R0groJvGpfYRJWzXkjAHB2EkOu6cyWJ0hGTTi1YhjAKfNIkgVe0CJ+2s4oMneL7dzVsKVUkMCwG54lS9ptJkeGUZsEJwkOappaNF2FHREU4xangcZtggXmcroUBt4OJS+MwbQJXr9oARdzXHspTZkfeG4MDHnswodPKGoRo4Z2vltllezMgMP/nSJ4Gd6lQ5HnWEZQscqe/Rm78VSXpalYZyBZAk+b+lLzzG5OUeHsIAe09Te9dWXYeRnxfkWD5yGiwpQtLKRiTVkIwGDVPETMA/vpV0kt+bO2UEs3DZ5qM5BYbYAPqGvCgtTBNa19dWgX2K7JArUyTsHJxoc4fS3tHZ+yaMaMiRm0DcMbePR0wWjZrnPHg2B60iavbeb+zh7BNeigcjyVZZhZA+sFH3YBoij7J5qUSI7bzBOQuA8H9D7QgNdKqImA++jKDlWsX+cRc35M09UZkvDAHTDplRjj7vBjGaxr4D0pCc+qOe1SVEqbuCTz4glkChVfyZbX4augA2E+eFrCJGBlkeHVJNoOLj7KYPW5e3FPvI5OeHUaIpkGHnK45MSe7WistUwlmFeXSjJqFeYeYpKkuvAkbkVEUH3+Xcjj7TDd+A0TPpNaorCq1D+qXGTdqR77Hjfvoxod8mQpXv3VJXR9J9407+/YWnZgAz9yUk9n9TjcOjqt2+BMHcZVvu4ZYoCnnXwuDjie/n0yDDqA3E9xcnHFhCF5By+F/okO2U/n4uM0m8yRvfkUgMJG6pGssw59VfpSeXRAbh4XU4srZl7oL7KxCrxKww5eBAa5eClSO+beCpWmjAnvgy9tpEhCE6A1Vt14+jDbVmJQY4h2soPDRIvRgyUc8rUzJSmSIZRH+z0aAZ15GEkZkvFQ2F4loIdJYeuxHDmW5m3rEpXn8jTSpH4FpcqVLcCRsqx5ckqAuX84Z2p6njGAB/LVnqUd3LkEpATikVXIceMO9qdcxdqVitFvgzBhmXwts5PSaPfpSY0jmGyxGQUcDxy+x9q6WTyY+muBj8bSYsCzqzrhXL4/sR6emQYmYOQcbgxeJ+F7nX0S2SG0qSAZBziszNoWLRQSwZKUOu5XnRKdx4xJdxXmK20+6dMnV+jwxGnR7w4+oQFCHJKks9JSjLqjo+SdToIpwj6ccJVV4F4HqcGzYygzcsxW6uKeGkvPa5tnKw7gW7YlimUYWQHs2gC2f0U9+aS7EGSddSfnkrRKc2wkqRtiyPngMfb7jN5dukZJykqfzJaqYeR43j+LlE7pCyWU11TyztkUf4k6YT4VDpCO8wZxer9cO4/TnDaMqSXSLcdKJup81hCUTYV7TLS7J89S22SVca6hh4QpKM2UyLDyCaAhGoWtdWrq12bQwf6bipuk25kVp3bNKJFXCHKB9zo1CyovvZTFRnStJQLFnpE1pd2OsH07SIWqUhxhctKFD7jYWG+VGm1rPmcQP5kUGmBYJaBnN9eJbrttSOEwgBAuwkAwydw+238+1A/UlNaspYpk2Hkh+L8hqgRBEsmYyCn6qVHhraApjO9E7mZDzVgRszIpwkTbrBuOWRzNeMnnpnnpT6xRhLaSFVeId2oE0qgDQpWZPQilrPynxf2JUcKa9SnpU4ZNLIM9V7J/ISmTMRXu3rPtKkzcmBlfhpPrTUW1Y1YbyndWGg4/BTJMPLB6AtnL/yundFH/eFOwKsoXWrug2pr6dxLBhKOFDm8VAYcgVUa1l5sZ4oxhvt89jqngGPyAQYYPhBRJ+Gqssq2ilM3pHmDReS4gBDbJhn0HqWhyp8al+MJuWvpq98E1ZdahzRDAv+2QdpUAFwGSXQk6WMKZRjp5JiXVwv8vKt2K/U/fdS01MGueKhD2+vb1u7tVjXk4J1uhsW15cZS21jgaOSEdLPjtyrY5kDk9IUjmTmR9+yrSTFSeSxhmYLXeuWKhj6YfVm7moYgDQOjgW3JoHpJ9UX7MwNk+FWLK15U25q5FWpnLQaiQSvnb1atvAY1TZ8Mo0Lhmu+pA9dxJaE0lVD6tOWkS4QmLLsMG664ExYVg+rzfEJpVdpstqGNKcLr2nKfVa/OXVxn1jfDjdCufTEx3cs5pbPoxQ5Z6VOaVFjvjBxAGqZ+2aAMpIP4PfEY6jAd5bPEtnQ7PNuMHZ43UBwhWqEmp8VgutMjg0WIGF7IK9A9UdYZCB/m00+NHYnxEn92/JPVUUrTY01XXRKtojQkF6KBVKLg4yRKHqwSx8eBpy4jFopwDf3QIMRxrjOErCceRIoUEgioCsQdcxsZ+srrX1E1HImpr9C5ddQzSl15LLbMLNZHWrk2WmysDgzTKcNI/+Qup0w6kewMxjfqWnwra4yiKm+Qga2D6hjzbNQhIhWrFx80UufSB4eIweI0CURq18X7yqgf9eMRxin0v/NtUn4+PCbWJ0dJoZsS6Vk72UaGoCzXRY7oTJPz8HzFAauglG7yCqAxMXRUolMwPxseMMHITo8MI5vsMnBXBpSvYuV0GK3S7wZJHOXcfvu6oY6CcZtxZqOQpAmmp07AkYQjG9NmRxOqJ+keOUtuG8INaZ1lCJEqy0eOkHQReSR+cvssQy+0UIqoPGT1bYfG2yI1Oy+SQQ01vI/Op0yGkWJZv/9quGZjxFhGf/7FyMWD3HuegNux0NnbqNRWsTrjCs8dIJXB67mjMZ/Jbf11GgiC6rJrP1eMUSkpe7i/ThqnqW29fS8dHpLBFNO/WnPdXv/tW7X9tgR27OM+mnsfUyTDyHKtXkbgnuqhWqB/UcgdO4U3wF5UYHMPEQtzQ0YeURscluBHLPiVNAiRgXcTzJmFf+lddRzqmxkr4C2K+qFPfUGzgEQXJkNRGYJeOCrRfaNSXJdofbZl4J+hot7OixP5fhaiAPpXfuIDPdSwRSxfZaDcbqd7UyTDyGy6xNwtrrnX/9TwhDNkQi/O7UTHPjtCsf6sNqFlYcfQlIjyQDu3xDKaE6V0g/rxA2POo5FgpUt9eo11ojYYDLfYBqbzofG2epVFLD7Z2v3T26dQApbfOgAMyWBOJ6y3TgZzzPqdj9X4+LWBkN+20t9ENCEgZAeFv4S5l/atPbolCwPHlMgwKsoYI3fp0LeYkVUjpLxfghYQDCdczC8bgCElQruwEgX+SuWFfppOVdHqSPpViAePKODfgEU+fe5bakTU5xFC+0pc9zNURYVDS0CvtMMQutd1LBu9yqIbzaAMKndWeon9BTMIE1KKioUYsy7UuTMltgPlk7CWh88c3HvMupgmGUZ+uyJxPezn3ldXmUKaZDxUBdCsXbysJwl5Ru+YRagXVKYe2peJwkQ8KdtwVCYn+koT7Y6MMfNrRdnT4Ue9A9s+QMZXdv4knySerYwHtSGDB2d3mn5dQmNKN4kSySD1e0VPbpuNtuHh0rvHqzmpPYHCNMlgDwj5J0UGSlWK9B6D91QmpFDJc5MCwmSyxHuxjMOnCuk04+50oseRzOYR3taOzRty1MhgPBYbmJzvhoUndQApoW04tsL8soxGW0zXxlKhz21kMI9VGYTq9v3X9BjvV4sUP30A8Pur3LRMa73VNuILfKuPLv5cQyyfFhlGvPrJ3sfnZYxudtzgbKkD4QpKx+nzA0XZd1TwwDS/GS/xF5mk7/l+YtvzTD3OrTx2zm/pSuWHWGPBPatUvjj9IX55/AokGjojo0YmH/tBGQIjVq30avicqCGDkabTvazf1C/z3Z8gS39MVTai1V4B+urLMLIxyGHdEnTUQXdDgTLFzpRzn9IoS6L3lki9IUkJNxJNnZJGQtwytovfKxF19DxVNGydJHuIVbRnRYfgxtHABYFOyp2Os6X0uG+xl8RRbLUIUoZlYGUG3fWPOEt2cKptB90kPeSTwJEswnTROgLhiyA+pp7uiP0OIz0lMtgjpIbY8AeEzNtoMHSVKfiOcafeGG/oIb2wgSYShGsHCY0KVb3CivKcQkTSyV49d099atBUxw/KLvXV9d0cysqMx65zRhxhGXJqkMjXaG68ijk1Db7mWNRID1cOykBlgDuu/1Fyr6JL4FRUAaAkGUrQLe/1BJtlYGrEq3gpcjIM9g/0TYMM9gipnbMvjq0a/jWtKghtA7Phh9lrCfeLMaJIR+FTktIs0hUimw2PQhQz6CxQqKTwSeVhqY8iRH5bnK5tW58JvdzAC2zDwuErKqm4bv25AR0hqPK6n7r61ZIh9A2jSSHVVNOEHU7vlI7Ee3xwktmIz4oM6QI12+WTywJ7g+MUymCvoTE1K2IHhE+MS/qtdRJzIapYLTfEsJipEhsaI7ZNAJqYolyfBKayMHD0vSPbNzSxZdgqYxhEOsKiiOad+sA7tQbfJTp5SAPEfIrl78tQNSTOQRSD9F5S1NK6xI85KYFBCfe3RUIirpNnH/+Ox5gu8inUaZFhxMQ19+sMVKB5NvtrHo+wmx0koe9sq5xLsiezzWRbEnVEQkvVhgDIzmAhqdTB6fkq7Ub7SlmIOGTc4diKtlH0Vk9uIYiSUx4LfWeaNrJebH1W5lsyeF+esxu4qPxA1HUoZ3oMZE48qCQgZ+038xNcodIiHmMqGQFqGmTo/iwvR3Nul4zfUL0o02R42og0YdEfjUuRlzqwsJmUYZs7ahw0qdZjHbbbXNMeT8NKz4Yg8F3mzJykMnW60hdEeOhLqm8RINNpKUM7zn3D+m7JED5hovedJl09FhppGBPnf6O1Zrqe2DR5HWJsimQILyrrP93mZHSeoTN1oxzy/xIZY2NiSRh586AnZ9Bowmv25oyDSkhtmB/ro708GAT2H1BnD8c8ihoB/F4ICyURtUbkyH1c8T5y2yjD4HPLqPdS1OKoblPbUs+ahXrOEO/0lsRPUVswFbgd9PdvSuRtSmWoq0zFBTLmnctufGvn1ZBtkqROot89QfQ5hKU0HkGMSY6tnJ9ZyiJ2G7kPXaWy1aoS2+g/hfowRdO8g/0k1XVeSKYc9gt9N5kI6tgvRcm5XJZB1XZCegi+lWTwP+rooqsMAoqkBeDHWXn+pqPJRqlvLCygKEg8VyKw6Sq/OKDqy1fk9GEp51X0r7IKpk6GLkLwhM5GoO5MGxp6CtQL/SL2F4aCZOAyuLcWmCFH1CZn7IVMMcDtbepYm7RRJCkKFFcQs1qYT5atpO8MGLWwt8gAikzipS67OgjrhfpRpyo+lEMycEg1SDNAYSCKffC6u7DDa101ahfZjbvQbnA+0h/GTMdDghq6evVeAI/pkGGkNlk4nDCK2US2BEYYGYOQ2lFvgPvCxnSL2ZJoJKatQny5glSRfpCM6Tn8EIBZvW5DzGu68fU6tw49qtI0ejibAAAPLklEQVT+QfDDvIMrMNQ0LXcy5AzT0zy/OSRD0Jh4DU8DyNCC3qMJ9mWEj40LBd1dF15MCDSYlvIVYDveCxY8HTKMNH2IhsaRAfATl36aKXUdhCIw9XvktcygNRUXXg3fynrplf5TzLjz/KevJNrhpKgkiQd3KOZZ7wt8+ZUR2tFJKs/hUBvLIjxGBBC1PNo50WjJQEDlnOhmoTcXMC1mV0gdSXsByLq+xPpFYjQ7hVl2kiFZtHU+PTJ0f1IrhTXfnVWi3oHmdYqvDvYuoNoJb7xZKlQAn+gQc6a/Tml9hGV/UWPQlx+UnrH3DtPxp8mm+nIGdJKnR1SMpPItJdSz0M99hDEXa2sOxXJovWxTQ79JBos0QAAERdigx8LlML0BCmJO2NsI/A/q0MqdDK3zR73HozmI5Xr6YMpkGPUdi3aJRX872zyZCbEihYZwvoi7ELUjglQhutoX3Vex1bsLtQtb9lIP6RWKFgF2KY9n5KfX3GuUFJOJHtjRvgSIRy369ApbuUaXrAxNMStwhvmcxHotGeLhNTYqOhIjzqeQXlVvvDmGql9ewYl/W8+qNMXpfZd0XolTQB3zKZNhxALYLYV4MxBJ+S0JXMddw5t6MKdZth1fnUaIceXTVyHicprWZweJSuT/qV9Fg0YuXz3b2xu5Pl+GNpX3EA14/qNdaVqk8hqPGeKVXy8S4is41IAMBgzEei9t0DKhe0Qvr7roWFv6HCavaohJRzofs4ip5ArJJj3WzGGmSIaRFuQDUCV0VEKua4Nh4cdDpa0eOQcuo05YpXXP79uJSL1HduWKkEiPdVgdoXcS01groW8pJJ/xJUaX7Zp3rTuTdT7FlJ8c0dUYnQgsPzma9tMyDJIhoLHK3G9RVcLEEzQaoEnvdk8IBgMrjomPq5F2gXupSAkp0rTIMLJyerO0phyKUXG9l+k7UodlMBIZA/WDAZhhs6dLcICShOC8X8OUP3zCTkl9copj/RTnK88/aK7SDZSXF8CfIixe1rGi/VcNFjWTqI8ggwi6Z4cdAUMqsI0MlmqJIObw/s1X1Yzh6JfJh0OUtu+Rql/s2G1z7reSYE3TIkPYqealVGtYaN2W/negZeNKfamhtATkEMoQrJ1rpNA0SyJ/EcUpFyc6rghhe69iuWF1tWLjmB169CSKdX7sPDimZ0cAJCxL11mRpRdVz5YKFZfP6PVl4MvV4o4nUKPIYNXRlp6sheqproVk0H9IhnyJ3w3FZLC9faQpkmHiUaNSFI8DOhcofL8hvEkj8WvrWQdeDSrWl/fd2ktwQcmJeFakfFIKZ80CD37Dj434RBqsNK8I88gWzeA0kY7/dOVIvS8gWYkey+9Bri2D9tvTFzlS2Ak2Nm2EQj9uiMR/CQ3pa8oWuIvWGCo9oBFFpkeGkaFpNcaMnvpvoRWAwBjx75NgqsLRIeWAapT6MJL1qEjI0SX8pRk67Be14RCqyJBy8xBXhegm2Tm0FlKoZ1MaAbRO5C90+v82dyYLEtsgEBX9//9MDlYVDyRPcov70tO2xCYo0GJPTrkkbgFPyUQ6nddVhzVKjDl+Vz8DX1LtaXFxh/yY17cL4M/S5kp/NZ/8mg6/CqQ4oqs9tQTU9PrvDcjbeLog2PTmc9KmWB2Dm2xvKHS5mtWnvrBkyr4MHAsR1V6TbLwKRjk5WhZ70CvH/MKlEJEpuBTbQYIrUhynWmN/0cE/O3xq9a9xmjGafTycXcnFJR6Ct9lrE8b8Uxlf9JvbO1Csxed0+M0I08pA8S53laOGFM9rFUlqDz37XkLebaxY5aAyqsoe193JvLfa0qcM1VYMbC3dHI2zeF4yjZ0Z9uL1MfdvDt3DewSb20nf0pXjoINqbbf7poNsCnvwhHKAVr1qRDaWaCVbHEa9gTPgXWis/1PozEVaJ3gF5PiaDj/WbtpRTgsRQKutb5cEJc4ZHEa7ll1Wja+cnenx+K3gW4sBk2ZQ9I/SwsyBICtWHbDbQS1BBwhLltyBqQzolB6xn61eGxwe5fSKmKTh+dm8iXyct3ke5AZ3HTj5rmdXJvyGZe43Rjk603vLtBScTfj4Ze0p0Ede5s8m/DUdfhpc+9UlO5tQTx24rswitK3BCwptNF24v3EghiIHn2j853HfZPZhxshG4f4D5ZNLTtCIPhqrbRQWw0IefxXdPpHM835DvQ0Kl//HduLt8nzr6R/NCfdIuNSrPtzslO6v3qtQr1+FiZBN9pr6NLe4BslXdPjFduZCTKWdaAOm493K+CVpzzCMUq9QtbKkDHPsXgakI59Y63kJVSKPhv+uiVxdsz5EDZdfkLdZRYftIBcn7JRT+mPwuKPd+8SlT7Zv/60susei+F10EDiMKGmlu2guOdoMxmo2TzA3J83EUIWrglVNSj9WAubnm+cU7kM6/Co96ZDc8iCnWmqTLJDOtjYtmUytVqFGwS6QD7Ixq8zE0JU9UaBv8GTr5785P8kaGGU3yuGDfUSjxvHRw/66AwiJHE3TCY9yGU0xb6ll6p5p3nQwoGTXi9LGwa8RtIwFiqv3vc21dveT5qlfSxHT9mt9ToffPJO+aW8QroERAgejSo2VD49sNTY+dHRaS7hcRtBqTTxn1dsJRykrs9DIROcFBMmEbacxoLNlxwBMRFeG9AXc5CRr82iTtu3Ix8se6ETQw/ekg9u86aCMtzOOAU7dOkil50/kdwlA635e92pZsNHoCAB8hldyxaXPd3T40SHaHN22V2pRPySdwHl+OtGqtmHm6DrRYXeodBhnMDbQBb0zKS2t5hT2og+8rx0XhnA1o9LgBbIaArP1q9vU13PgRwgpMCTecy0q2bLOuw6NsXTv0VxcXPJSl4tzNpLZYt7lyxGY7M7sIIkAgrdB+4gOvzorzlscOKWLDVDa2V0nsYtuULBp1b/XcoQfZRf0Vu08A8Tp9irDDg6k2VyrJvTbYG2KQFub14V+9n5DlaUgfwIcNOaEPxTAkxgi6qLDEGadjqE+lT1LMXSbPA8ascpGc2nzr+41zpXBdekls/zPOvy8BJnacFurj3JFqrPEDN7mnEDgOR/Q/cBA50bU4eC3pYhWikwUUM0/ZcI1b3St5ZWM3M7el2yJZp1XQ3rYiQf1qjUMJXWbnDwjNkAit/2s26nDc4EOQnn4eUPktW4R3UpN0Chwr1MGt0/1D3/Nc3J8XuFLOvjNfUazFELCGS7O8i5rKRUT9ZLCIyvFbLMKmW8ZceE+f1/qSB++WyzD4uyySxSuQtW38qaOep82aCVeS8fPxXLk8P92MOpLX/LabwVxWfaiwzk52c+jHBK+fc7+NxAmy7bax54jC1TVwXEpxK/r39HhdwLxPsW5NzrOg2ZATv69eJ+/z3quC4rfcMaK5NyJhI6qTDYlB79NL7aMBcBZbVlYultFoF5l4kZ4sq5lIqDRTF5Ceq+gyLfnhHnIxc3INx2a4gCsY9WN2Yd9acSmxxttyYNB4mLEy3WWTNdK6UM6/E6wCwAW0WgHBvllpUKeJ9EANsGO33e5JbyrKp8VqkjLjBZnMtizAgbjeHlyq4CaP5itFHgWgMeyRQ91JzNXLARhOLsGArOCYdtq6XmKsrmzFuSuTHnXofqWPDlG/ylNMI5tskQyApzK3N793fapXeUyQ52NxKJACVt2QQ1/Tqy/o4Pf/k3nKGconol7D/3swqBMakjGFD+DQWnRqRYOCqjlufZmAwdP2Aj/Kc1u2ucp05LXdJhxDuJZ6NMWIBCU0K9IxnDqR47jwOQrnK5mnyK8bdWIz3G60JwIev0UZqtpRF09yuPdp8hWEGjDNj+ow88HszCBfH7WyU6P8wIVSrh/VinVn6nu7eR425FfIt67z4jsPJwThprfRCtFGAKn6vfo1oGxqKdCU9cfZJF8MWwCOUUnsMM8UWzfD6639wnOXYd25Hy9BNB005Ix26XpKmLZafba/tJneGVva/RYsfqJ4q/o8PMEEKjmrK2o3n7tgG70y1XKJ8vJ3Jx9LtmirxCxxltLKbfNvbBKJUO2Mm3UgokjyrW08yimt4s4U8FwyWvZlZ94mJRLRtvXrs8JzG+Cyg0Epw4Ifr9K9M/Pv0LoMgCITQOYeYar96m/3/jELmnhLR/T4eeNDoSa3ox9rDZN5EuOaQ60XUvlDB4YO/URb6PtumYMplzfoG2ZstnM8oyn6rDUF+4UrY8O8SVsoyCMRnshWcHpo06kBuY2teSItAaeLp0maEwd9r2c8rSuJFKrXXM3ycHIxEp55lNu2fB5fNRnXM61jGojqXxFh18NxqmcnpXPzQxf+0cFAVdRntK8BtVr6eQygYSZYqaXLUAhsLSh9Xo/G8YCn3IezJFwrN9aBgw+8ESbtM/WNf40nMIQ8wZn5L6A0PsOHXQPZajkk3MVniBc8zS/FdVLrVuZEU1+b5BeDbBKhxh0Ytjjgzr8NDnm8qqe/6otdD18EX7UNPdgbzzU0B686+k33dqO3KKz3DDLWuUsu48Tx6UmxM1H3m1gz4EQ9MlM5iAqzrWa1DMVjzfXnRa11XijYQ3mqevT0ghycTAM7E0H2WW0D/GzAxJ+5XFZl3Zfu1uin3u8ZINbzX9tumVtZvqeDr9EuuY9BfAeVyilUkL0seWkJUIry5Ch40YFYUoNtOd8QrQ2bbpt62NDVFsv97n5Du4sm5k34Sawa59Ws6KcJZ2zFwNy00eZlLQ7kWOtMUzntVcdYIP+95CxtSEdyZm9L24XygpgCjznp6Y/db+1ZFm8SPc7OjhD9PSCqFjp//6YCoQmm3LHEDz7z0d+eB1KmkM0rboMWikaMS+uC1KFwKdI5Bys7ONTwLOXERMZ7mIfDEIf5z1DmHbiICJTRCMgE0QF5h86nMY7P900zMTg1Zib0eGUWnlMLzOHeYyVa9OisxYwfFOHn/7zCksmTSQfh6mNupvcEo0oKn2bDvQOtLHwdOqWkdLt+oNGCi49OAQBs2gCRDbrLF4T9bt9KsMUhfNv3obx5+GxME9mycDN6PTcL/7QoRmrbDEzOmmyDp+fPmAblMZNrgBaiLejEo+B+Wx4wwST/Y4OP092CdxbAMmVvo7DaJv+M0hRKFf+e9oGjJpz2zmnU8SwBOkpCJhJmNlIm4EWaBfjHoJl9m3pBlanDi1TTf0QCMMWXUbIM/tPHY7UghJRMkzz/YXGfyI1g3cNh3rr+B+Yf0yHfwAjBO4Lyccm/wAAAABJRU5ErkJggg=="},{"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 orthophoto 2000","type":"tms","template":"http://e.tile.openstreetmap.hu/ortofoto2000/{zoom}/{x}/{y}.jpg","endDate":"2000-01-01T00:00:00.000Z","startDate":"2000-01-01T00:00:00.000Z","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 orthophoto 2005","type":"tms","template":"http://e.tile.openstreetmap.hu/ortofoto2005/{zoom}/{x}/{y}.jpg","endDate":"2005-01-01T00:00:00.000Z","startDate":"2005-01-01T00:00:00.000Z","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","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","description":"French address registry or Base Adresses Nationale"},{"id":"FR-Cadastre","name":"FR-Cadastre","type":"tms","template":"http://tms.cadastre.openstreetmap.fr/*/tout/{zoom}/{x}/{y}.png","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","description":"French land registry","icon":"https://svn.openstreetmap.org/applications/editors/josm/plugins/cadastre-fr/images/cadastre_small.png"},{"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.","icon":"http://www.freemap.sk/index.php?c=core.download&filename=/JOSM/freemap.png"},{"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.","icon":"http://www.freemap.sk/index.php?c=core.download&filename=/JOSM/freemap.png"},{"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.","icon":"http://www.freemap.sk/index.php?c=core.download&filename=/JOSM/freemap.png"},{"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.","icon":"http://www.freemap.sk/index.php?c=core.download&filename=/JOSM/freemap.png"},{"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,"icon":"http://i.imgur.com/aFlvMpM.png"},{"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","scaleExtent":[0,19],"polygon":[[[-48.2444,-16.0508],[-48.2444,-15.5005],[-47.5695,-15.5005],[-47.5695,-16.0508],[-48.2444,-16.0508]]],"description":"Addresses data from IBGE","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}","endDate":"2016-03-27T00:00:00.000Z","startDate":"2016-03-27T00:00:00.000Z","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","description":"Supplementing incomplete coverage in other sources (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2014-07-31T00:00:00.000Z","startDate":"2014-07-31T00:00:00.000Z","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","description":"Recent summer image of the Alaska Range for mapping natural features (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2014-03-16T00:00:00.000Z","startDate":"2014-03-16T00:00:00.000Z","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","description":"Missing in older pre-2011 images (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-01-01T00:00:00.000Z","startDate":"2014-01-01T00:00:00.000Z","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","description":"Missing Islands in OSM (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2013-10-18T00:00:00.000Z","startDate":"2013-10-18T00:00:00.000Z","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,"description":"For more accurate coastline and glacier mapping (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-09-29T00:00:00.000Z","startDate":"2016-09-29T00:00:00.000Z","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","description":"Up-to-date image for glacier mapping - beware of some fresh snow at higher altitudes (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-12-10T00:00:00.000Z","startDate":"2015-12-10T00:00:00.000Z","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","description":"Missing in other image sources (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-09-21T00:00:00.000Z","startDate":"2016-09-21T00:00:00.000Z","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","description":"Up-to-date image for glacier mapping (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-12-21T00:00:00.000Z","startDate":"2015-12-21T00:00:00.000Z","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","description":"Patchy and partly cloudy coverage in usual sources (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-03-11T00:00:00.000Z","startDate":"2016-03-11T00:00:00.000Z","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","description":"Recent image, only old and poor images in other sources currently (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2014-09-02T00:00:00.000Z","startDate":"2014-09-02T00:00:00.000Z","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","description":"Coastline mostly mapped meanwhile (false color IR)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2013-08-27T00:00:00.000Z","startDate":"2013-08-27T00:00:00.000Z","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","description":"Missing islets and inaccurate coast (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2012-02-05T00:00:00.000Z","startDate":"2012-02-05T00:00:00.000Z","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","description":"2007 ASTER image offering better glacier coverage than common sources (true color with estimated blue)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-01-09T00:00:00.000Z","startDate":"2016-01-09T00:00:00.000Z","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","description":"Fairly clear up-to-date image for updating glacier edges (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"id":"osmim-imagicode-enderby","name":"imagico.de OSM images for mapping: Enderby Land and Kemp Coast","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=enderby&z={zoom}&x={x}&y={-y}","endDate":"2017-03-27T00:00:00.000Z","startDate":"2017-01-25T00:00:00.000Z","scaleExtent":[0,13],"polygon":[[[45.4547,-68.5091],[45.4547,-67.5724],[49.7155,-65.7176],[59.2693,-65.7176],[67.3735,-67.3449],[67.3735,-68.2581],[67.088,-68.5091],[45.4547,-68.5091]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","description":"Sentinel-2 images of Enderby Land and Kemp Coast (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-12-13T00:00:00.000Z","startDate":"2015-12-13T00:00:00.000Z","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","description":"Image from after the 2014/2015 eruption (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-01-01T00:00:00.000Z","startDate":"2013-01-01T00:00:00.000Z","scaleExtent":[0,12],"polygon":[[[-43.9774,59.7171],[-44.545,59.7302],[-44.9203,59.7672],[-45.3587,59.8218],[-45.763,59.8848],[-46.0859,59.9827],[-46.3381,60.119],[-46.577,60.2652],[-46.8114,60.4418],[-47.2635,60.5314],[-47.6937,60.5549],[-48.1457,60.6192],[-48.5771,60.7015],[-48.8689,60.8506],[-49.0578,61.0555],[-49.396,61.2957],[-49.7601,61.4934],[-50.2064,61.7324],[-50.4699,61.9539],[-50.8647,62.1596],[-51.0631,62.3869],[-51.2121,62.6001],[-51.3005,62.8389],[-51.4238,62.9979],[-51.6767,63.1944],[-51.9465,63.4079],[-52.0253,63.6377],[-52.2255,63.8378],[-52.3658,64.0705],[-52.4829,64.3792],[-52.4988,64.6788],[-52.789,64.9063],[-53.2046,65.1321],[-53.6649,65.4753],[-53.9977,65.8019],[-54.1348,66.1568],[-54.1441,66.5235],[-54.2285,66.8319],[-54.4519,67.303],[-54.5141,67.7648],[-54.604,68.2021],[-54.568,68.5698],[-54.598,68.8347],[-54.7606,69.1207],[-55.0028,69.4125],[-55.2735,69.6187],[-55.3808,69.8283],[-55.3945,70.0838],[-55.3094,70.2573],[-55.4307,70.479],[-55.5501,70.6707],[-55.7654,70.861],[-56.2489,71.2343],[-56.5018,71.5429],[-56.5867,71.9015],[-56.5189,72.2355],[-56.5085,72.5258],[-56.8923,72.8144],[-57.4027,73.1054],[-57.8066,73.4566],[-58.1461,73.7696],[-58.3554,74.0972],[-58.5125,74.3783],[-58.7336,74.6328],[-59.3551,74.8869],[-60.1412,75.102],[-61.0067,75.2763],[-61.911,75.3886],[-62.4706,75.5595],[-62.9776,75.7454],[-64.1463,75.779],[-65.4481,75.7235],[-66.7068,75.6792],[-67.8379,75.6525],[-69.0456,75.6195],[-70.055,75.5344],[-71.0898,75.4705],[-72.1119,75.4476],[-74.2311,76.4102],[-74.5601,76.5328],[-74.5601,82.6959],[-14.4462,82.6959],[-14.3994,82.5997],[-13.5339,82.4379],[-12.0312,82.3426],[-10.7796,82.3196],[-10.7796,80.1902],[-11.2123,80.069],[-11.136,79.8103],[-10.7796,79.5176],[-10.7796,79.0441],[-11.2626,78.7128],[-12.2579,78.3558],[-13.2398,78.1272],[-13.7649,77.9279],[-14.1169,77.6779],[-14.7129,77.5278],[-15.5507,77.3655],[-16.0936,77.0771],[-16.0586,76.5548],[-15.838,75.9611],[-15.6879,75.4726],[-16.253,75.058],[-17.0427,74.6425],[-18.3155,74.2702],[-19.4463,73.9378],[-19.8329,73.632],[-20.2938,73.3524],[-20.7831,73.0446],[-21.01,72.6766],[-20.8774,72.2926],[-20.7672,71.8726],[-20.7765,71.4304],[-20.9411,70.9802],[-21.219,70.6126],[-21.5326,70.3001],[-21.8039,70.0911],[-22.166,69.8947],[-22.4831,69.7539],[-22.9027,69.6585],[-23.3545,69.544],[-23.9177,69.4036],[-24.1794,69.3088],[-24.6745,69.1084],[-25.1222,68.9555],[-25.6659,68.7995],[-26.0994,68.583],[-26.6316,68.4043],[-27.7638,68.2813],[-28.4575,68.0023],[-29.353,67.8135],[-30.6456,67.4911],[-31.7673,67.0005],[-32.9783,66.2596],[-33.9313,66.0156],[-34.8956,65.7403],[-35.5914,65.5208],[-36.1483,65.372],[-36.7532,65.2559],[-37.1858,65.1349],[-37.6032,64.9727],[-38.0624,64.4901],[-38.5304,64.1244],[-39.0545,63.7213],[-39.3131,63.4405],[-39.5739,62.7506],[-39.9532,62.2739],[-40.2757,61.8547],[-40.714,61.3365],[-41.2091,60.8495],[-41.821,60.5526],[-42.4368,60.3264],[-42.8643,60.0299],[-43.1131,59.9147],[-43.3282,59.83],[-43.5459,59.7695],[-43.797,59.7284],[-43.9774,59.7171]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","description":"Landsat mosaic of Greenland (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-04-12T00:00:00.000Z","startDate":"2016-04-12T00:00:00.000Z","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","description":"Recent image of Heard island with interior mostly cloud covered but mostly well visible coast (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2013-09-16T00:00:00.000Z","startDate":"2013-09-16T00:00:00.000Z","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","description":"A lot of very coarse coastlines could be improved here, much snow cover though so no use for glacier mapping (false color IR)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-08-07T00:00:00.000Z","startDate":"2016-08-07T00:00:00.000Z","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","description":"State of bridge construction in August 2016 (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-07-17T00:00:00.000Z","startDate":"2016-07-17T00:00:00.000Z","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","description":"Latest images north of the regular Landsat limit (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2013-11-16T00:00:00.000Z","startDate":"2013-11-16T00:00:00.000Z","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","description":"Missing in other image sources (true color with estimated blue)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-10-13T00:00:00.000Z","startDate":"2015-10-13T00:00:00.000Z","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","description":"Missing in other image sources (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2013-05-17T00:00:00.000Z","startDate":"2013-05-17T00:00:00.000Z","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","description":"First available image north of the regular Landsat limit, mostly with seasonal snow cover so difficult to interpret (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-06-13T00:00:00.000Z","startDate":"2016-06-13T00:00:00.000Z","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","description":"Up-to-date image for glacier mapping (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-08-02T00:00:00.000Z","startDate":"2016-08-02T00:00:00.000Z","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","description":"Up-to-date image for glacier mapping (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-06-08T00:00:00.000Z","startDate":"2015-06-08T00:00:00.000Z","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","description":"Many missing islands in OSM (mostly mapped meanwhile) (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"id":"osmim-imagicode-northsea_s2_2016","name":"imagico.de OSM images for mapping: North Sea Coast 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=northsea_s2_2016&z={zoom}&x={x}&y={-y}","endDate":"2016-09-25T00:00:00.000Z","startDate":"2016-09-25T00:00:00.000Z","scaleExtent":[0,13],"polygon":[[[5.1562,52.8755],[5.1615,53.0325],[6.4155,55.7379],[9.8813,55.7459],[9.8813,53.2428],[9.6846,52.8877],[5.1562,52.8755]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","description":"Up-to-date low tide imagery of the coast for updating mapping of tidalflats and shoals (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-08-12T00:00:00.000Z","startDate":"2016-08-12T00:00:00.000Z","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","description":"Up-to-date late summer imagery with few clouds - caution: not all visible snow is glaciers (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2012-07-09T00:00:00.000Z","startDate":"2012-07-09T00:00:00.000Z","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","description":"Assembled from July 2012 ASTER imagery (true color with estimated blue)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2012-07-15T00:00:00.000Z","startDate":"2012-07-08T00:00:00.000Z","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","description":"Assembled from July 2016 ASTER imagery (true color with estimated blue)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-08-21T00:00:00.000Z","startDate":"2015-08-21T00:00:00.000Z","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","description":"Up-to-date low tide imagery of the coast for updating mapping of tidalflats and shoals (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-08-21T00:00:00.000Z","startDate":"2015-08-21T00:00:00.000Z","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","description":"Up-to-date low tide imagery of the coast for updating mapping of tidalflats and shoals (false color IR)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2012-08-13T00:00:00.000Z","startDate":"2005-06-21T00:00:00.000Z","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","description":"Assembled from mostly 2012 ASTER imagery, some 2005 images mainly in the northeast (true color with estimated blue)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2013-03-13T00:00:00.000Z","startDate":"2013-03-13T00:00:00.000Z","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","description":"Glaciers of Northwest Heard Island (mapped meanwhile) (false color IR)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-06-07T00:00:00.000Z","startDate":"2016-06-07T00:00:00.000Z","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","description":"Images of the new locks (but partly cloudy) (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-12-30T00:00:00.000Z","startDate":"2016-12-30T00:00:00.000Z","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","description":"New locks with less clouds than in the Sentinel-2 image - make sure to check image alignment (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"id":"osmim-imagicode-S2A_R078_N68_20160930T081002","name":"imagico.de OSM images for mapping: Pechora Sea Coast","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R078_N68_20160930T081002&z={zoom}&x={x}&y={-y}","endDate":"2016-09-30T00:00:00.000Z","startDate":"2016-09-30T00:00:00.000Z","scaleExtent":[0,13],"polygon":[[[53.1802,67.5344],[53.1821,68.414],[54.2107,69.3367],[55.3584,70.2786],[59.004,70.2786],[60.6947,69.977],[61.9837,69.7161],[61.9823,68.9395],[59.9153,67.5344],[53.1802,67.5344]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","description":"Sentinel-2 image of the Pechora Sea coast in autumn 2016 (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-02-02T00:00:00.000Z","startDate":"2016-02-02T00:00:00.000Z","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","description":"Outside regular Landsat coverage and therefore not in LIMA and Bing/Mapbox (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-08-31T00:00:00.000Z","startDate":"2015-08-31T00:00:00.000Z","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","description":"Late summer imagery where usual sources are severely limited by clouds and snow (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2011-04-15T00:00:00.000Z","startDate":"2011-04-15T00:00:00.000Z","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","description":"Icebridge DMS image of the settlement - alignment might be poor","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-01-01T00:00:00.000Z","startDate":"2015-01-01T00:00:00.000Z","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","description":"Land/water distinction difficult to properly map based on Bing/Mapbox images (false color IR)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-08-28T00:00:00.000Z","startDate":"2015-08-28T00:00:00.000Z","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","description":"Late summer imagery where usual sources are severely limited by clouds and snow (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-02-09T00:00:00.000Z","startDate":"2015-02-09T00:00:00.000Z","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","description":"Recent image of most of the remaining Rwenzori Mountains glaciers (false color IR)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-07-02T00:00:00.000Z","startDate":"2016-07-02T00:00:00.000Z","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","description":"Up-to-date image for glacier mapping (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2014-02-05T00:00:00.000Z","startDate":"2014-02-05T00:00:00.000Z","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","description":"Missing in other image sources (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-12-13T00:00:00.000Z","startDate":"2015-12-13T00:00:00.000Z","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","description":"Missing in other image sources (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2013-09-27T00:00:00.000Z","startDate":"2013-09-27T00:00:00.000Z","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","description":"Missing islands and coarse coastline due to cloud cover in Bing, lakes could also use additional detail (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-02-04T00:00:00.000Z","startDate":"2016-02-04T00:00:00.000Z","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","description":"Outside regular Landsat coverage and therefore not in LIMA and Bing/Mapbox (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"id":"osmim-imagicode-s2sval","name":"imagico.de OSM images for mapping: Svalbard mosaic","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=s2sval&z={zoom}&x={x}&y={-y}","endDate":"2016-01-01T00:00:00.000Z","startDate":"2016-01-01T00:00:00.000Z","scaleExtent":[0,13],"polygon":[[[16.6108,76.4137],[16.4731,76.4268],[16.3788,76.4589],[14.4124,77.1324],[14.0784,77.2536],[10.9875,78.4054],[10.631,78.5605],[10.2314,78.8392],[10.3952,79.6074],[10.516,79.7731],[10.9632,79.8707],[20.2294,80.849],[20.4702,80.8493],[25.1752,80.6817],[33.4391,80.3438],[33.7809,80.3016],[34.0395,80.239],[33.977,80.1527],[25.5722,76.5917],[25.2739,76.481],[25.1416,76.4327],[24.937,76.4176],[16.6108,76.4137]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","description":"Sentinel-2 mosaic of Svalbard (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2011-05-07T00:00:00.000Z","startDate":"2011-05-07T00:00:00.000Z","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","description":"Icebridge DMS image - alignment might be poor","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-09-25T00:00:00.000Z","startDate":"2015-09-25T00:00:00.000Z","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","description":"Icebridge DMS aerial images from Thule Airbase - alignment might be poor","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-10-06T00:00:00.000Z","startDate":"2015-10-06T00:00:00.000Z","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","description":"Icebridge DMS aerial images from Thule Airbase - alignment might be poor","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2015-09-25T00:00:00.000Z","startDate":"2015-09-25T00:00:00.000Z","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","description":"Icebridge DMS aerial images from Thule Airbase - alignment might be poor","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-08-12T00:00:00.000Z","startDate":"2016-08-12T00:00:00.000Z","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","description":"Up-to-date late summer imagery with few clouds (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2014-12-24T00:00:00.000Z","startDate":"2014-12-24T00:00:00.000Z","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","description":"Coarse coastline due to cloud cover in Bing/Mapbox (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-01-31T00:00:00.000Z","startDate":"2016-01-31T00:00:00.000Z","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","description":"Image from after the 2015 eruption (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-06-23T00:00:00.000Z","startDate":"2016-06-23T00:00:00.000Z","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","description":"Recent image showing newest features (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2013-10-09T00:00:00.000Z","startDate":"2013-10-09T00:00:00.000Z","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","description":"Represents approximately minimum snow cover so can be well used for glacier mapping (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"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}","endDate":"2016-05-10T00:00:00.000Z","startDate":"2016-05-10T00:00:00.000Z","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","description":"Poor and outdated imagery in other sources (true color)","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADWElEQVQ4y13TS2gcdQDH8e/szGQ372Tz2irGpoS0KSapoqjRQ4knD0WweLRCCXiQXuJFMR6EYMVC0IsPyKVFsJpWbQ0KQmL14KPWirGmZjdmk+w7mX1kZ2d2dv7/mfFUsX5Pv8Pv+lH4X6/NvTPc239gOlXyp7ZzlaEg8EGYyVaZWY7dc+/CuTde+fu/f+XOeP3iLT2bTMxN9NVm1PZhbfKBGC/OXsDzHJr1EEf6ilSMLZFrxObHJk/OfvDqCQmgArz3TUJfXZm/3K53nZ4YPRw69czjXPrqR+LJHJ4rUFXA3qG33Va3cpknU2vxY1pz9yWzlPZVgL6xobNGXp7u6T9Geq/O+U+usHRtE6du0aJncSyXtnCOcqVC0ZTIhnM44itNhpFeVs5+kRxe//OP22VDar4ncRwHz85TKtY40H2D4n6KwNMRgUPIC9ES0mj2NNwK4rfE2qhWyBnT1YrUQkqA3hwmpIYw63law4JcaR/hR9GVAh2tOmEUHunpwKkJVm10VdOntbptP+VJiaIoKIDv7zPQbVDxJIPRPkRkh8CN0KFrjHdGiXW3kkuXSRYEakid0qQrDkrhEgQ+tZpNtVTmoQdNrGgB6XjUpEJzSxvCgnhOZ+RQFKtcZV8IpO8NhXxfIoWLY9tUS0XePxXHMNrY3BxkOx+lXVX54dc+VjdaiHabXPg6RcMSWFULT3poEGxJ0eit1Wq06w4FMURPl8NObo9MvgnTaOGF402M399DrDNEPJHnl99rZIoWvudvaeGwtux53sOPjffy9pn7CHdKnn5WJ/5XnudnrjF2tJ/F61mGBiIc7fe4mXT5ds0lu1tE8f1lbSDWu5DZyb98fMLVwp0dgINv5Bjpcfj50yloUsAo8Ob8T/iVBociLrtlC9+tCwgW1O8++7A09dxLbUvfrzzRpV7nSCyK0qRDOEwjlUYr7iH2DPx6hXevpLi5YXNjfRsCcQ4aiwrAlxuB/tHCx5fTyaUTg/1pJke6eHR0GF9AKZtnv1BlYSWFWYBEepdyuXwV5EmQ8l9Mn9929asXF+c21xMz5b1NreHewvNcHAc0qRGpQyqfFZZZnQc5C1LepfFOZ946P5xJbkybRmbKzm8f3C3b2GZlyzYLy9WqteD5jbs4/wOHuM2qT5aWEQAAAABJRU5ErkJggg=="},{"id":"IPR-orotofoto-last-tms","name":"IPR ortofoto LAST (tmsproxy)","type":"tms","template":"http://osm-{switch:a,b,c}.zby.cz/tiles_ipr_last.php/{zoom}/{x}/{y}.jpg","scaleExtent":[1,18],"polygon":[[[14.81231552124,49.93089301941],[14.18754582291,49.87687266984],[14.12025456314,50.19881542327],[14.74502426147,50.25247461226],[14.81231552124,49.93089301941]]]},{"id":"IPR-orotofoto-vege-tms","name":"IPR ortofoto Low-Vegetation (tmsproxy)","type":"tms","template":"http://osm-{switch:a,b,c}.zby.cz/tiles_ipr_vege.php/{zoom}/{x}/{y}.jpg","scaleExtent":[1,20],"polygon":[[[14.30454236984,49.99538124382],[14.3160436821,49.94205148763],[14.3499983888,49.94508261663],[14.35383872175,49.92726356386],[14.42385321818,49.93351545169],[14.4200902288,49.95097343212],[14.48865449494,49.95709281879],[14.48479036398,49.9750111737],[14.55385989188,49.98117257481],[14.55011770159,49.99851689993],[14.58455395868,50.0015874108],[14.58829614897,49.98424419323],[14.69168128485,49.99346468175],[14.67633637226,50.06452744171],[14.71278864961,50.06777324036],[14.70115373952,50.12158114828],[14.66470146217,50.11833899243],[14.6610031918,50.13543086714],[14.62755290441,50.13245658485],[14.61965341283,50.16894659259],[14.58542741996,50.16590546732],[14.58162921725,50.18344165464],[14.40776267983,50.167995553],[14.41156088254,50.15045369625],[14.37764851321,50.14743927281],[14.37379555571,50.16523508727],[14.33892816423,50.16213672855],[14.34278112173,50.14433976066],[14.27367931007,50.13819641038],[14.27749028245,50.12058459573],[14.20879964298,50.11447476994],[14.21288816219,50.09557069695],[14.24656290855,50.09856724424],[14.25417384067,50.06335893014],[14.21987061144,50.0603042129],[14.22369648177,50.04259477081],[14.257999711,50.04565061557],[14.26952647673,49.99225864496],[14.30454236984,49.99538124382]]]},{"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","icon":"http://nls.tileserver.com/nls70-nq8.png"},{"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","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAB3RJTUUH3gQOFR0YB1KT3QAAAAlwSFlzAAAewQAAHsEBw2lUUwAAAARnQU1BAACxjwv8YQUAAAS/SURBVHjandN7TFNXHAfwzrn/lm3ZHy7LYrJkybK5zMw9fCEoPjbeChoHTtBVRF7l1ZZSaG8flCtvsFVpoZZHC5Y6jDM+UScDaxF5lIfSAaMIlVKBS8EZN4d+d9voZpbMFX/JN7nnnvM7n5xzcxmM5wrPlX1yFmP2adgmXKHc78bsU+j9ZRT3HzzE+D0n7tjuYdo5h38X47/q+UWD1nE0tw/gktEC66gdN/tG0Dc4hnEHhdG7DujOdqGHxi4ae2AZti8ccJXZYoOxawRPnjzGwcpmzM8//ntOe86MickZTEw7ka+99nJAZ/8YWjqs7ufc6ibM/fbQ/fzHo0eoOduJ8UkKljt2nLhk9hj4/Wlm6VA9A2NUa/ew6wNQE1OzVGvPEGUZvkvZHVNUo2mA6ugfpvoGrNT8/Dz1tMfd/yJgKZ13h6zjzFbzvbwO8wDZaR4kzeZbZG/fIHnTbCOvdzrI9h472dnVT97oociO23NkW+9M3pDVsc/V69rjRYA7Su11/dvbfkRJvDeOcMORuj8CpelLkJO6BVs4vQhj3QD5fTQS2PXYndQAblw2yrUt9c/6/xeoqzulK+VEoCTtawgSM5HCr0Nsmg48ngJhYiukonNIybeg8MQEFIZBFBWIoa4z1XoMaOrbtbHci2BtW4RachnOlO/GZW0SjuZEY2eWGYVEFfYJ+kDo/4ThdDPExadQcbxb5zmgb6/xYZlAxPtDmByFS2U+EHM5yBOyEZZ8HkzeZaQmyxFZROGkgUQIMQSNvkPrMXBM31YdFqNDJK8ZHE4FYgSt2Jl0GpKUGAhFjTiQ2QJDgRBGdSTIvEJ8IXDSQJvngEbfWrWacGJDzn1sJ34FkSqFQbgWTcUrcLWIATlnBzYSE8hOOIBQzk9YK56jgRs1CzlBVXD6bcijCYSwTYjhXUFD7nrUlHyFc6pPUCL4BpskUwhn6iGPSMYG3igN3KxeCKDZyulGddReBKV3YbNkGidkIWhQLMeFiuUoE3ths8iOfXFnoQ5nwTt9xHVFVZ5f0XGjxks0A++sIWyNqYM0TYp6qS9+UHxOn+BjqMQfwF8wgg2x5+ErccCboKA5bloAUGc8tk40i2CmGuGhgQhjX0MZwUY5uRJVuX6QcpPhm2TErlBfBLAa4S2epYHrlZ5fke4K6SVyIjRejz1REfhO2Ab2wavgZJ8EU9gEUek1MDMvIIa5DUFpzVhHzECtbRR4DJRrDP5f8h04ILwAmTQLAkEWCgsLIJVIIcwS4uhRBSQSCfi8FGzP6sbKjLsoV+tWewwolUfe+pR1y7GD1YDd4cGIi4uFgM/HulWr4LdpI5ITE5EQH49dOwMRmtmND/ebLMoy+WueA2VyBmO9opSTcx6HimWQHypGBicF+6MjwdzzLSQEH6UlBSjKFyNS1AnGMm6Csuwww2NApVK6hkv2JMptmTkGiPNqEcc+jFiuGsy0SrD4lciQ1kJW3ICAqJIWeu1ilUq1EEDlHr/6vr/XxozBuQD6jw6UUXRm6DgRQCeQfIA1iaZ+BuP191xrXwpw1RtL16zwSfi5PVg2hZAcyp0gqQOr9548TU+/82zdywGvLH429eZnO8rPBNMbB4ps+MhPpvyna9ELgb8ASvKZeuq+E9sAAAAASUVORK5CYII="},{"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","icon":"http://nls.tileserver.com/nls70-nq8.png"},{"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","endDate":"2011-01-01T00:00:00.000Z","startDate":"2011-01-01T00:00:00.000Z","scaleExtent":[14,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 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","endDate":"2014-01-01T00:00:00.000Z","startDate":"2014-01-01T00:00:00.000Z","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"},{"id":"Aargau-AGIS-2016","name":"Kanton Aargau 25cm (AGIS 2016)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/AGIS2016/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","endDate":"2016-01-01T00:00:00.000Z","startDate":"2016-01-01T00:00:00.000Z","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 OF2016","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,"icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAIVBMVEX///+LKCbMAABycnL+/v7v7+9sbGz39/fz8/Pw8PD8/Pz60siYAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+AIGAsXN84mS+sAAAA4SURBVAjXY2AUBAMBBkYlMCCXwcwABgZYGCwGIJo5AMQGAjYgLgYxLICY05iBwRisjsvY2IGBAQAGpQmjMKkg/wAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wOC0yNFQxMToyMzo1NS0wNDowMLEFqzIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTYtMDgtMjRUMTE6MjM6NTUtMDQ6MDDAWBOOAAAAAElFTkSuQmCC"},{"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","endDate":"2012-05-14T00:00:00.000Z","startDate":"2012-05-13T00:00:00.000Z","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]]],"description":"High quality aerial imagery taken for the City of Kelowna"},{"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","endDate":"2013-09-03T00:00:00.000Z","startDate":"2013-09-03T00:00:00.000Z","scaleExtent":[5,14],"polygon":[[[-60.8550011,6.1765004],[-60.4762612,7.9188291],[-62.161689,8.2778675],[-62.5322549,6.5375488],[-60.8550011,6.1765004]]],"description":"Recent Landsat imagery"},{"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","endDate":"2013-09-12T00:00:00.000Z","startDate":"2013-09-12T00:00:00.000Z","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]]],"description":"Recent lower-resolution landsat imagery for southwest British Columbia"},{"id":"LINZ_NZ_Aerial_Imagery","name":"LINZ NZ Aerial Imagery","type":"tms","template":"https://tiles-a.data-cdn.linz.govt.nz/services;key=3197c6d0e5cb494a95d58dc2de3216c2/tiles/v4/set=2/EPSG:3857/{zoom}/{x}/{y}.png","scaleExtent":[0,21],"polygon":[[[167.2503662109375,-47.21956811231548],[167.244873046875,-47.28016067076474],[167.5030517578125,-47.37975438400816],[168.2501220703125,-47.15610477504402],[168.7445068359375,-46.79629898997744],[169.3267822265625,-46.75491661928188],[169.78271484375,-46.604167162931844],[170.4254150390625,-46.11132565729794],[170.804443359375,-45.95114968669139],[170.9527587890625,-45.440862671781744],[171.309814453125,-44.91035917458493],[171.40869140625,-44.39061697878681],[172.562255859375,-43.92954993561458],[172.90283203125,-43.96909818325171],[173.1610107421875,-43.90976594390799],[173.2598876953125,-43.69567969789881],[172.9742431640625,-43.53660274231031],[172.760009765625,-43.37710501700071],[173.1500244140625,-43.17714134663171],[173.704833984375,-42.63395872267314],[174.36401367187497,-41.78360106648077],[174.320068359375,-41.409775832009544],[174.84741210937497,-41.52914198872309],[175.0726318359375,-41.70572851523751],[175.506591796875,-41.672911819602085],[176.2261962890625,-41.10832999732831],[176.8304443359375,-40.42604212826493],[177.17102050781247,-39.67337039176559],[177.0391845703125,-39.39375459224347],[177.4456787109375,-39.18117526158747],[177.60498046875,-39.3300485529424],[177.978515625,-39.368279149160124],[178.3355712890625,-38.65977773071253],[178.7091064453125,-37.74465712069938],[178.626708984375,-37.54457732085582],[178.3135986328125,-37.43125050179357],[177.6214599609375,-37.37888785004525],[177.0391845703125,-37.39634613318924],[176.561279296875,-37.37015718405751],[176.3360595703125,-37.05956083025124],[176.0064697265625,-36.29741818650809],[175.6768798828125,-36.05354012833974],[174.671630859375,-35.1782983520012],[173.1939697265625,-34.28445325435288],[172.6776123046875,-34.234512362369856],[172.386474609375,-34.40237742424137],[172.4798583984375,-34.71903991764788],[172.9852294921875,-35.32184842037683],[173.56201171875,-36.142310873529986],[174.30908203125,-37.077093191754415],[174.5562744140625,-38.052416771864834],[174.4793701171875,-38.655488159952995],[174.3255615234375,-38.865374851611634],[173.7982177734375,-38.95940879245421],[173.60595703125,-39.232253141714885],[173.6993408203125,-39.56335316582929],[174.5892333984375,-39.95606977009003],[174.9847412109375,-40.216635475391215],[174.9847412109375,-40.49291502689579],[174.7210693359375,-40.805493843894155],[174.1497802734375,-40.65147128144056],[173.2818603515625,-40.43440488077009],[172.5897216796875,-40.350730565917885],[172.0843505859375,-40.534676780615406],[171.7657470703125,-40.826280356677124],[171.57348632812497,-41.3974150664646],[171.2823486328125,-41.652392884268124],[170.8758544921875,-42.53284428171312],[170.35400390625,-42.87193842444846],[168.277587890625,-43.92954993561458],[167.6239013671875,-44.47691085722324],[166.55273437499997,-45.38687734827038],[166.27258300781247,-45.916765867649],[166.4813232421875,-46.22545288226937],[167.6788330078125,-46.471916320870406],[167.2503662109375,-47.21956811231548]]],"terms_url":"http://www.linz.govt.nz/data/licensing-and-using-data/attributing-elevation-or-aerial-imagery-data","terms_text":"Sourced from LINZ CC-BY 3.0","best":true},{"id":"LINZ_NZ_Topo50_Gridless_Maps","name":"LINZ NZ Topo50 Gridless Maps","type":"tms","template":"https://tiles-a.data-cdn.linz.govt.nz/services;key=3197c6d0e5cb494a95d58dc2de3216c2/tiles/v4/layer=2343/EPSG:3857/{zoom}/{x}/{y}.png","scaleExtent":[0,21],"polygon":[[[167.2503662109375,-47.21956811231548],[167.244873046875,-47.28016067076474],[167.5030517578125,-47.37975438400816],[168.2501220703125,-47.15610477504402],[168.7445068359375,-46.79629898997744],[169.3267822265625,-46.75491661928188],[169.78271484375,-46.604167162931844],[170.4254150390625,-46.11132565729794],[170.804443359375,-45.95114968669139],[170.9527587890625,-45.440862671781744],[171.309814453125,-44.91035917458493],[171.40869140625,-44.39061697878681],[172.562255859375,-43.92954993561458],[172.90283203125,-43.96909818325171],[173.1610107421875,-43.90976594390799],[173.2598876953125,-43.69567969789881],[172.9742431640625,-43.53660274231031],[172.760009765625,-43.37710501700071],[173.1500244140625,-43.17714134663171],[173.704833984375,-42.63395872267314],[174.36401367187497,-41.78360106648077],[174.320068359375,-41.409775832009544],[174.84741210937497,-41.52914198872309],[175.0726318359375,-41.70572851523751],[175.506591796875,-41.672911819602085],[176.2261962890625,-41.10832999732831],[176.8304443359375,-40.42604212826493],[177.17102050781247,-39.67337039176559],[177.0391845703125,-39.39375459224347],[177.4456787109375,-39.18117526158747],[177.60498046875,-39.3300485529424],[177.978515625,-39.368279149160124],[178.3355712890625,-38.65977773071253],[178.7091064453125,-37.74465712069938],[178.626708984375,-37.54457732085582],[178.3135986328125,-37.43125050179357],[177.6214599609375,-37.37888785004525],[177.0391845703125,-37.39634613318924],[176.561279296875,-37.37015718405751],[176.3360595703125,-37.05956083025124],[176.0064697265625,-36.29741818650809],[175.6768798828125,-36.05354012833974],[174.671630859375,-35.1782983520012],[173.1939697265625,-34.28445325435288],[172.6776123046875,-34.234512362369856],[172.386474609375,-34.40237742424137],[172.4798583984375,-34.71903991764788],[172.9852294921875,-35.32184842037683],[173.56201171875,-36.142310873529986],[174.30908203125,-37.077093191754415],[174.5562744140625,-38.052416771864834],[174.4793701171875,-38.655488159952995],[174.3255615234375,-38.865374851611634],[173.7982177734375,-38.95940879245421],[173.60595703125,-39.232253141714885],[173.6993408203125,-39.56335316582929],[174.5892333984375,-39.95606977009003],[174.9847412109375,-40.216635475391215],[174.9847412109375,-40.49291502689579],[174.7210693359375,-40.805493843894155],[174.1497802734375,-40.65147128144056],[173.2818603515625,-40.43440488077009],[172.5897216796875,-40.350730565917885],[172.0843505859375,-40.534676780615406],[171.7657470703125,-40.826280356677124],[171.57348632812497,-41.3974150664646],[171.2823486328125,-41.652392884268124],[170.8758544921875,-42.53284428171312],[170.35400390625,-42.87193842444846],[168.277587890625,-43.92954993561458],[167.6239013671875,-44.47691085722324],[166.55273437499997,-45.38687734827038],[166.27258300781247,-45.916765867649],[166.4813232421875,-46.22545288226937],[167.6788330078125,-46.471916320870406],[167.2503662109375,-47.21956811231548]]],"terms_url":"https://data.linz.govt.nz/layer/2343-nz-mainland-topo50-gridless-maps/","terms_text":"Sourced from the LINZ Data Service and licensed by LINZ for re-use under the Creative Commons Attribution 3.0 New Zealand licence."},{"id":"ORT10LT","name":"Lithuania - NŽT ORT10LT","type":"tms","template":"http://ort10lt.openmap.lt/g16/{zoom}/{x}/{y}.jpeg","endDate":"2016-01-01T00:00:00.000Z","startDate":"2010-01-01T00:00:00.000Z","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","scaleExtent":[0,16],"overzoom":false,"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","default":true,"description":"Shows major features to help orient you.","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 2017"},{"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 2017","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 2017"},{"id":"Mapbox","name":"Mapbox Satellite","type":"tms","template":"https://{switch:a,b,c}.tiles.mapbox.com/v4/openstreetmap.map-inh7ifmo/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,19],"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","default":true,"description":"Satellite and aerial imagery.","icon":"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgODAuNDcgMjAuMDIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDgwLjQ3IDIwLjAyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe29wYWNpdHk6MC42O2ZpbGw6I0ZGRkZGRjtlbmFibGUtYmFja2dyb3VuZDpuZXcgICAgO30uc3Qxe29wYWNpdHk6MC42O2VuYWJsZS1iYWNrZ3JvdW5kOm5ldyAgICA7fTwvc3R5bGU+PGc+PHBhdGggY2xhc3M9InN0MCIgZD0iTTc5LjI5LDEzLjYxYzAsMC4xMS0wLjA5LDAuMi0wLjIsMC4yaC0xLjUzYy0wLjEyLDAtMC4yMy0wLjA2LTAuMjktMC4xNmwtMS4zNy0yLjI4bC0xLjM3LDIuMjhjLTAuMDYsMC4xLTAuMTcsMC4xNi0wLjI5LDAuMTZoLTEuNTNjLTAuMDQsMC0wLjA4LTAuMDEtMC4xMS0wLjAzYy0wLjA5LTAuMDYtMC4xMi0wLjE4LTAuMDYtMC4yN2MwLDAsMCwwLDAsMGwyLjMxLTMuNWwtMi4yOC0zLjQ3Yy0wLjAyLTAuMDMtMC4wMy0wLjA3LTAuMDMtMC4xMWMwLTAuMTEsMC4wOS0wLjIsMC4yLTAuMmgxLjUzYzAuMTIsMCwwLjIzLDAuMDYsMC4yOSwwLjE2bDEuMzQsMi4yNWwxLjMzLTIuMjRjMC4wNi0wLjEsMC4xNy0wLjE2LDAuMjktMC4xNmgxLjUzYzAuMDQsMCwwLjA4LDAuMDEsMC4xMSwwLjAzYzAuMDksMC4wNiwwLjEyLDAuMTgsMC4wNiwwLjI3YzAsMCwwLDAsMCwwTDc2Ljk2LDEwbDIuMzEsMy41Qzc5LjI4LDEzLjUzLDc5LjI5LDEzLjU3LDc5LjI5LDEzLjYxeiIvPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik02My4wOSw5LjE2Yy0wLjM3LTEuNzktMS44Ny0zLjEyLTMuNjYtMy4xMmMtMC45OCwwLTEuOTMsMC40LTIuNiwxLjEyVjMuMzdjMC0wLjEyLTAuMS0wLjIyLTAuMjItMC4yMmgtMS4zM2MtMC4xMiwwLTAuMjIsMC4xLTAuMjIsMC4yMnYxMC4yMWMwLDAuMTIsMC4xLDAuMjIsMC4yMiwwLjIyaDEuMzNjMC4xMiwwLDAuMjItMC4xLDAuMjItMC4yMnYtMC43YzAuNjgsMC43MSwxLjYyLDEuMTIsMi42LDEuMTJjMS43OSwwLDMuMjktMS4zNCwzLjY2LTMuMTNDNjMuMjEsMTAuMyw2My4yMSw5LjcyLDYzLjA5LDkuMTZMNjMuMDksOS4xNnogTTU5LjEyLDEyLjQxYy0xLjI2LDAtMi4yOC0xLjA2LTIuMy0yLjM2VjkuOTljMC4wMi0xLjMxLDEuMDQtMi4zNiwyLjMtMi4zNnMyLjMsMS4wNywyLjMsMi4zOVM2MC4zOSwxMi40MSw1OS4xMiwxMi40MXoiLz48cGF0aCBjbGFzcz0ic3QwIiBkPSJNNjguMjYsNi4wNGMtMS44OS0wLjAxLTMuNTQsMS4yOS0zLjk2LDMuMTNjLTAuMTIsMC41Ni0wLjEyLDEuMTMsMCwxLjY5YzAuNDIsMS44NSwyLjA3LDMuMTYsMy45NywzLjE0YzIuMjQsMCw0LjA2LTEuNzgsNC4wNi0zLjk5UzcwLjUxLDYuMDQsNjguMjYsNi4wNHogTTY4LjI0LDEyLjQyYy0xLjI3LDAtMi4zLTEuMDctMi4zLTIuMzlzMS4wMy0yLjQsMi4zLTIuNHMyLjMsMS4wNywyLjMsMi4zOVM2OS41MSwxMi40MSw2OC4yNCwxMi40Mkw2OC4yNCwxMi40MnoiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNNTkuMTIsNy42M2MtMS4yNiwwLTIuMjgsMS4wNi0yLjMsMi4zNnYwLjA2YzAuMDIsMS4zMSwxLjA0LDIuMzYsMi4zLDIuMzZzMi4zLTEuMDcsMi4zLTIuMzlTNjAuMzksNy42Myw1OS4xMiw3LjYzeiBNNTkuMTIsMTEuMjNjLTAuNiwwLTEuMDktMC41My0xLjExLTEuMTlWMTBjMC4wMS0wLjY2LDAuNTEtMS4xOSwxLjExLTEuMTlzMS4xMSwwLjU0LDEuMTEsMS4yMVM1OS43NCwxMS4yMyw1OS4xMiwxMS4yM3oiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNNjguMjQsNy42M2MtMS4yNywwLTIuMywxLjA3LTIuMywyLjM5czEuMDMsMi4zOSwyLjMsMi4zOXMyLjMtMS4wNywyLjMtMi4zOVM2OS41MSw3LjYzLDY4LjI0LDcuNjN6IE02OC4yNCwxMS4yM2MtMC42MSwwLTEuMTEtMC41NC0xLjExLTEuMjFzMC41LTEuMiwxLjExLTEuMnMxLjExLDAuNTQsMS4xMSwxLjIxUzY4Ljg1LDExLjIzLDY4LjI0LDExLjIzeiIvPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00My41Niw2LjI0aC0xLjMzYy0wLjEyLDAtMC4yMiwwLjEtMC4yMiwwLjIydjAuN2MtMC42OC0wLjcxLTEuNjItMS4xMi0yLjYtMS4xMmMtMi4wNywwLTMuNzUsMS43OC0zLjc1LDMuOTlzMS42OSwzLjk5LDMuNzUsMy45OWMwLjk5LDAsMS45My0wLjQxLDIuNi0xLjEzdjAuN2MwLDAuMTIsMC4xLDAuMjIsMC4yMiwwLjIyaDEuMzNjMC4xMiwwLDAuMjItMC4xLDAuMjItMC4yMlY2LjQ0YzAtMC4xMS0wLjA5LTAuMjEtMC4yMS0wLjIxQzQzLjU3LDYuMjQsNDMuNTcsNi4yNCw0My41Niw2LjI0eiBNNDIuMDIsMTAuMDVjLTAuMDEsMS4zMS0xLjA0LDIuMzYtMi4zLDIuMzZzLTIuMy0xLjA3LTIuMy0yLjM5czEuMDMtMi40LDIuMjktMi40YzEuMjcsMCwyLjI4LDEuMDYsMi4zLDIuMzZMNDIuMDIsMTAuMDV6Ii8+PHBhdGggY2xhc3M9InN0MSIgZD0iTTM5LjcyLDcuNjNjLTEuMjcsMC0yLjMsMS4wNy0yLjMsMi4zOXMxLjAzLDIuMzksMi4zLDIuMzlzMi4yOC0xLjA2LDIuMy0yLjM2VjkuOTlDNDIsOC42OCw0MC45OCw3LjYzLDM5LjcyLDcuNjN6IE0zOC42MiwxMC4wMmMwLTAuNjcsMC41LTEuMjEsMS4xMS0xLjIxYzAuNjEsMCwxLjA5LDAuNTMsMS4xMSwxLjE5djAuMDRjLTAuMDEsMC42NS0wLjUsMS4xOC0xLjExLDEuMThTMzguNjIsMTAuNjgsMzguNjIsMTAuMDJ6Ii8+PHBhdGggY2xhc3M9InN0MCIgZD0iTTQ5LjkxLDYuMDRjLTAuOTgsMC0xLjkzLDAuNC0yLjYsMS4xMlY2LjQ1YzAtMC4xMi0wLjEtMC4yMi0wLjIyLTAuMjJoLTEuMzNjLTAuMTIsMC0wLjIyLDAuMS0wLjIyLDAuMjJ2MTAuMjFjMCwwLjEyLDAuMSwwLjIyLDAuMjIsMC4yMmgxLjMzYzAuMTIsMCwwLjIyLTAuMSwwLjIyLTAuMjJ2LTMuNzhjMC42OCwwLjcxLDEuNjIsMS4xMiwyLjYxLDEuMTJjMi4wNywwLDMuNzUtMS43OCwzLjc1LTMuOTlTNTEuOTgsNi4wNCw0OS45MSw2LjA0eiBNNDkuNiwxMi40MmMtMS4yNiwwLTIuMjgtMS4wNi0yLjMtMi4zNlY5Ljk5YzAuMDItMS4zMSwxLjA0LTIuMzcsMi4yOS0yLjM3YzEuMjYsMCwyLjMsMS4wNywyLjMsMi4zOVM1MC44NiwxMi40MSw0OS42LDEyLjQyTDQ5LjYsMTIuNDJ6Ii8+PHBhdGggY2xhc3M9InN0MSIgZD0iTTQ5LjYsNy42M2MtMS4yNiwwLTIuMjgsMS4wNi0yLjMsMi4zNnYwLjA2YzAuMDIsMS4zMSwxLjA0LDIuMzYsMi4zLDIuMzZzMi4zLTEuMDcsMi4zLTIuMzlTNTAuODYsNy42Myw0OS42LDcuNjN6IE00OS42LDExLjIzYy0wLjYsMC0xLjA5LTAuNTMtMS4xMS0xLjE5VjEwQzQ4LjUsOS4zNCw0OSw4LjgxLDQ5LjYsOC44MWMwLjYsMCwxLjExLDAuNTUsMS4xMSwxLjIxUzUwLjIxLDExLjIzLDQ5LjYsMTEuMjN6Ii8+PHBhdGggY2xhc3M9InN0MCIgZD0iTTM0LjM2LDEzLjU5YzAsMC4xMi0wLjEsMC4yMi0wLjIyLDAuMjJoLTEuMzRjLTAuMTIsMC0wLjIyLTAuMS0wLjIyLTAuMjJWOS4yNGMwLTAuOTMtMC43LTEuNjMtMS41NC0xLjYzYy0wLjc2LDAtMS4zOSwwLjY3LTEuNTEsMS41NGwwLjAxLDQuNDRjMCwwLjEyLTAuMSwwLjIyLTAuMjIsMC4yMmgtMS4zNGMtMC4xMiwwLTAuMjItMC4xLTAuMjItMC4yMlY5LjI0YzAtMC45My0wLjctMS42My0xLjU0LTEuNjNjLTAuODEsMC0xLjQ3LDAuNzUtMS41MiwxLjcxdjQuMjdjMCwwLjEyLTAuMSwwLjIyLTAuMjIsMC4yMmgtMS4zM2MtMC4xMiwwLTAuMjItMC4xLTAuMjItMC4yMlY2LjQ0YzAuMDEtMC4xMiwwLjEtMC4yMSwwLjIyLTAuMjFoMS4zM2MwLjEyLDAsMC4yMSwwLjEsMC4yMiwwLjIxdjAuNjNjMC40OC0wLjY1LDEuMjQtMS4wNCwyLjA2LTEuMDVoMC4wM2MxLjA0LDAsMS45OSwwLjU3LDIuNDgsMS40OGMwLjQzLTAuOSwxLjMzLTEuNDgsMi4zMi0xLjQ5YzEuNTQsMCwyLjc5LDEuMTksMi43NiwyLjY1TDM0LjM2LDEzLjU5eiIvPjxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik04MC4zMiwxMi45N2wtMC4wNy0wLjEyTDc4LjM4LDEwbDEuODUtMi44MWMwLjQyLTAuNjQsMC4yNS0xLjQ5LTAuMzktMS45MmMtMC4wMS0wLjAxLTAuMDItMC4wMS0wLjAzLTAuMDJjLTAuMjItMC4xNC0wLjQ4LTAuMjEtMC43NC0wLjIxaC0xLjUzYy0wLjUzLDAtMS4wMywwLjI4LTEuMywwLjc0bC0wLjMyLDAuNTNsLTAuMzItMC41M2MtMC4yOC0wLjQ2LTAuNzctMC43NC0xLjMxLTAuNzRoLTEuNTNjLTAuNTcsMC0xLjA4LDAuMzUtMS4yOSwwLjg4Yy0yLjA5LTEuNTgtNS4wMy0xLjQtNi45MSwwLjQzYy0wLjMzLDAuMzItMC42MiwwLjY5LTAuODUsMS4wOWMtMC44NS0xLjU1LTIuNDUtMi42LTQuMjgtMi42Yy0wLjQ4LDAtMC45NiwwLjA3LTEuNDEsMC4yMlYzLjM3YzAtMC43OC0wLjYzLTEuNDEtMS40LTEuNDFoLTEuMzNjLTAuNzcsMC0xLjQsMC42My0xLjQsMS40djMuNTdjLTAuOS0xLjMtMi4zOC0yLjA4LTMuOTctMi4wOWMtMC43LDAtMS4zOSwwLjE1LTIuMDIsMC40NWMtMC4yMy0wLjE2LTAuNTEtMC4yNS0wLjgtMC4yNWgtMS4zM2MtMC40MywwLTAuODMsMC4yLTEuMSwwLjUzYy0wLjAyLTAuMDMtMC4wNC0wLjA1LTAuMDctMC4wOGMtMC4yNy0wLjI5LTAuNjUtMC40NS0xLjA0LTAuNDVoLTEuMzJjLTAuMjksMC0wLjU3LDAuMDktMC44LDAuMjVDNDAuOCw1LDQwLjEyLDQuODUsMzkuNDIsNC44NWMtMS43NCwwLTMuMjcsMC45NS00LjE2LDIuMzhjLTAuMTktMC40NC0wLjQ2LTAuODUtMC43OS0xLjE5Yy0wLjc2LTAuNzctMS44LTEuMTktMi44OC0xLjE5aC0wLjAxYy0wLjg1LDAuMDEtMS42NywwLjMxLTIuMzQsMC44NGMtMC43LTAuNTQtMS41Ni0wLjg0LTIuNDUtMC44NGgtMC4wM2MtMC4yOCwwLTAuNTUsMC4wMy0wLjgyLDAuMWMtMC4yNywwLjA2LTAuNTMsMC4xNS0wLjc4LDAuMjdjLTAuMi0wLjExLTAuNDMtMC4xNy0wLjY3LTAuMTdoLTEuMzNjLTAuNzgsMC0xLjQsMC42My0xLjQsMS40djcuMTRjMCwwLjc4LDAuNjMsMS40LDEuNCwxLjRoMS4zM2MwLjc4LDAsMS40MS0wLjYzLDEuNDEtMS40MWMwLDAsMCwwLDAsMFY5LjM1YzAuMDMtMC4zNCwwLjIyLTAuNTYsMC4zNC0wLjU2YzAuMTcsMCwwLjM2LDAuMTcsMC4zNiwwLjQ1djQuMzVjMCwwLjc4LDAuNjMsMS40LDEuNCwxLjRoMS4zNGMwLjc4LDAsMS40LTAuNjMsMS40LTEuNGwtMC4wMS00LjM1YzAuMDYtMC4zLDAuMjQtMC40NSwwLjMzLTAuNDVjMC4xNywwLDAuMzYsMC4xNywwLjM2LDAuNDV2NC4zNWMwLDAuNzgsMC42MywxLjQsMS40LDEuNGgxLjM0YzAuNzgsMCwxLjQtMC42MywxLjQtMS40di0wLjM2YzAuOTEsMS4yMywyLjM0LDEuOTYsMy44NywxLjk2YzAuNywwLDEuMzktMC4xNSwyLjAyLTAuNDVjMC4yMywwLjE2LDAuNTEsMC4yNSwwLjgsMC4yNWgxLjMyYzAuMjksMCwwLjU3LTAuMDksMC44LTAuMjV2MS45MWMwLDAuNzgsMC42MywxLjQsMS40LDEuNGgxLjMzYzAuNzgsMCwxLjQtMC42MywxLjQtMS40di0xLjY5YzAuNDYsMC4xNCwwLjk0LDAuMjIsMS40MiwwLjIxYzEuNjIsMCwzLjA3LTAuODMsMy45Ny0yLjF2MC41YzAsMC43OCwwLjYzLDEuNCwxLjQsMS40aDEuMzNjMC4yOSwwLDAuNTctMC4wOSwwLjgtMC4yNWMwLjYzLDAuMywxLjMyLDAuNDUsMi4wMiwwLjQ1YzEuODMsMCwzLjQzLTEuMDUsNC4yOC0yLjZjMS40NywyLjUyLDQuNzEsMy4zNiw3LjIyLDEuODljMC4xNy0wLjEsMC4zNC0wLjIxLDAuNS0wLjM0YzAuMjEsMC41MiwwLjcyLDAuODcsMS4yOSwwLjg2aDEuNTNjMC41MywwLDEuMDMtMC4yOCwxLjMtMC43NGwwLjM1LTAuNThsMC4zNSwwLjU4YzAuMjgsMC40NiwwLjc3LDAuNzQsMS4zMSwwLjc0aDEuNTJjMC43NywwLDEuMzktMC42MywxLjM4LTEuMzlDODAuNDcsMTMuMzgsODAuNDIsMTMuMTcsODAuMzIsMTIuOTdMODAuMzIsMTIuOTd6IE0zNC4xNSwxMy44MWgtMS4zNGMtMC4xMiwwLTAuMjItMC4xLTAuMjItMC4yMlY5LjI0YzAtMC45My0wLjctMS42My0xLjU0LTEuNjNjLTAuNzYsMC0xLjM5LDAuNjctMS41MSwxLjU0bDAuMDEsNC40NGMwLDAuMTItMC4xLDAuMjItMC4yMiwwLjIyaC0xLjM0Yy0wLjEyLDAtMC4yMi0wLjEtMC4yMi0wLjIyVjkuMjRjMC0wLjkzLTAuNy0xLjYzLTEuNTQtMS42M2MtMC44MSwwLTEuNDcsMC43NS0xLjUyLDEuNzF2NC4yN2MwLDAuMTItMC4xLDAuMjItMC4yMiwwLjIyaC0xLjMzYy0wLjEyLDAtMC4yMi0wLjEtMC4yMi0wLjIyVjYuNDRjMC4wMS0wLjEyLDAuMS0wLjIxLDAuMjItMC4yMWgxLjMzYzAuMTIsMCwwLjIxLDAuMSwwLjIyLDAuMjF2MC42M2MwLjQ4LTAuNjUsMS4yNC0xLjA0LDIuMDYtMS4wNWgwLjAzYzEuMDQsMCwxLjk5LDAuNTcsMi40OCwxLjQ4YzAuNDMtMC45LDEuMzMtMS40OCwyLjMyLTEuNDljMS41NCwwLDIuNzksMS4xOSwyLjc2LDIuNjVsMC4wMSw0LjkxQzM0LjM3LDEzLjcsMzQuMjcsMTMuOCwzNC4xNSwxMy44MUMzNC4xNSwxMy44MSwzNC4xNSwxMy44MSwzNC4xNSwxMy44MXogTTQzLjc4LDEzLjU5YzAsMC4xMi0wLjEsMC4yMi0wLjIyLDAuMjJoLTEuMzNjLTAuMTIsMC0wLjIyLTAuMS0wLjIyLTAuMjJ2LTAuNzFDNDEuMzQsMTMuNiw0MC40LDE0LDM5LjQyLDE0Yy0yLjA3LDAtMy43NS0xLjc4LTMuNzUtMy45OXMxLjY5LTMuOTksMy43NS0zLjk5YzAuOTgsMCwxLjkyLDAuNDEsMi42LDEuMTJ2LTAuN2MwLTAuMTIsMC4xLTAuMjIsMC4yMi0wLjIyaDEuMzNjMC4xMS0wLjAxLDAuMjEsMC4wOCwwLjIyLDAuMmMwLDAuMDEsMCwwLjAxLDAsMC4wMlYxMy41OXogTTQ5LjkxLDE0Yy0wLjk4LDAtMS45Mi0wLjQxLTIuNi0xLjEydjMuNzhjMCwwLjEyLTAuMSwwLjIyLTAuMjIsMC4yMmgtMS4zM2MtMC4xMiwwLTAuMjItMC4xLTAuMjItMC4yMlY2LjQ1YzAtMC4xMiwwLjEtMC4yMSwwLjIyLTAuMjFoMS4zM2MwLjEyLDAsMC4yMiwwLjEsMC4yMiwwLjIydjAuN2MwLjY4LTAuNzIsMS42Mi0xLjEyLDIuNi0xLjEyYzIuMDcsMCwzLjc1LDEuNzcsMy43NSwzLjk4UzUxLjk4LDE0LDQ5LjkxLDE0eiBNNjMuMDksMTAuODdDNjIuNzIsMTIuNjUsNjEuMjIsMTQsNTkuNDMsMTRjLTAuOTgsMC0xLjkyLTAuNDEtMi42LTEuMTJ2MC43YzAsMC4xMi0wLjEsMC4yMi0wLjIyLDAuMjJoLTEuMzNjLTAuMTIsMC0wLjIyLTAuMS0wLjIyLTAuMjJWMy4zN2MwLTAuMTIsMC4xLTAuMjIsMC4yMi0wLjIyaDEuMzNjMC4xMiwwLDAuMjIsMC4xLDAuMjIsMC4yMnYzLjc4YzAuNjgtMC43MSwxLjYyLTEuMTIsMi42LTEuMTFjMS43OSwwLDMuMjksMS4zMywzLjY2LDMuMTJDNjMuMjEsOS43Myw2My4yMSwxMC4zMSw2My4wOSwxMC44N0w2My4wOSwxMC44N0w2My4wOSwxMC44N3ogTTY4LjI2LDE0LjAxYy0xLjksMC4wMS0zLjU1LTEuMjktMy45Ny0zLjE0Yy0wLjEyLTAuNTYtMC4xMi0xLjEzLDAtMS42OWMwLjQyLTEuODUsMi4wNy0zLjE1LDMuOTctMy4xNGMyLjI1LDAsNC4wNiwxLjc4LDQuMDYsMy45OVM3MC41LDE0LjAxLDY4LjI2LDE0LjAxTDY4LjI2LDE0LjAxeiBNNzkuMDksMTMuODFoLTEuNTNjLTAuMTIsMC0wLjIzLTAuMDYtMC4yOS0wLjE2bC0xLjM3LTIuMjhsLTEuMzcsMi4yOGMtMC4wNiwwLjEtMC4xNywwLjE2LTAuMjksMC4xNmgtMS41M2MtMC4wNCwwLTAuMDgtMC4wMS0wLjExLTAuMDNjLTAuMDktMC4wNi0wLjEyLTAuMTgtMC4wNi0wLjI3YzAsMCwwLDAsMCwwbDIuMzEtMy41bC0yLjI4LTMuNDdjLTAuMDItMC4wMy0wLjAzLTAuMDctMC4wMy0wLjExYzAtMC4xMSwwLjA5LTAuMiwwLjItMC4yaDEuNTNjMC4xMiwwLDAuMjMsMC4wNiwwLjI5LDAuMTZsMS4zNCwyLjI1bDEuMzQtMi4yNWMwLjA2LTAuMSwwLjE3LTAuMTYsMC4yOS0wLjE2aDEuNTNjMC4wNCwwLDAuMDgsMC4wMSwwLjExLDAuMDNjMC4wOSwwLjA2LDAuMTIsMC4xOCwwLjA2LDAuMjdjMCwwLDAsMCwwLDBMNzYuOTYsMTBsMi4zMSwzLjVjMC4wMiwwLjAzLDAuMDMsMC4wNywwLjAzLDAuMTFDNzkuMjksMTMuNzIsNzkuMiwxMy44MSw3OS4wOSwxMy44MUM3OS4wOSwxMy44MSw3OS4wOSwxMy44MSw3OS4wOSwxMy44MUw3OS4wOSwxMy44MXoiLz48cGF0aCBjbGFzcz0ic3QwIiBkPSJNMTAsMS4yMWMtNC44NywwLTguODEsMy45NS04LjgxLDguODFzMy45NSw4LjgxLDguODEsOC44MXM4LjgxLTMuOTUsOC44MS04LjgxQzE4LjgxLDUuMTUsMTQuODcsMS4yMSwxMCwxLjIxeiBNMTQuMTgsMTIuMTljLTEuODQsMS44NC00LjU1LDIuMi02LjM4LDIuMmMtMC42NywwLTEuMzQtMC4wNS0yLTAuMTVjMCwwLTAuOTctNS4zNywyLjA0LTguMzljMC43OS0wLjc5LDEuODYtMS4yMiwyLjk4LTEuMjJjMS4yMSwwLDIuMzcsMC40OSwzLjIzLDEuMzVDMTUuOCw3LjczLDE1Ljg1LDEwLjUsMTQuMTgsMTIuMTl6Ii8+PHBhdGggY2xhc3M9InN0MSIgZD0iTTEwLDAuMDJjLTUuNTIsMC0xMCw0LjQ4LTEwLDEwczQuNDgsMTAsMTAsMTBzMTAtNC40OCwxMC0xMEMxOS45OSw0LjUsMTUuNTIsMC4wMiwxMCwwLjAyeiBNMTAsMTguODNjLTQuODcsMC04LjgxLTMuOTUtOC44MS04LjgxUzUuMTMsMS4yLDEwLDEuMnM4LjgxLDMuOTUsOC44MSw4LjgxQzE4LjgxLDE0Ljg5LDE0Ljg3LDE4LjgzLDEwLDE4LjgzeiIvPjxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0xNC4wNCw1Ljk4Yy0xLjc1LTEuNzUtNC41My0xLjgxLTYuMi0wLjE0QzQuODMsOC44Niw1LjgsMTQuMjMsNS44LDE0LjIzczUuMzcsMC45Nyw4LjM5LTIuMDRDMTUuODUsMTAuNSwxNS44LDcuNzMsMTQuMDQsNS45OHogTTExLjg4LDkuODdsLTAuODcsMS43OGwtMC44Ni0xLjc4TDguMzgsOS4wMWwxLjc3LTAuODZsMC44Ni0xLjc4bDAuODcsMS43OGwxLjc3LDAuODZMMTEuODgsOS44N3oiLz48cG9seWdvbiBjbGFzcz0ic3QwIiBwb2ludHM9IjEzLjY1LDkuMDEgMTEuODgsOS44NyAxMS4wMSwxMS42NSAxMC4xNSw5Ljg3IDguMzgsOS4wMSAxMC4xNSw4LjE1IDExLjAxLDYuMzcgMTEuODgsOC4xNSAiLz48L2c+PC9zdmc+"},{"id":"geodata.md.gov-MD_SixInchImagery","name":"MD Latest 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","endDate":"2016-01-01T00:00:00.000Z","startDate":"2013-01-01T00:00:00.000Z","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","description":"Six Inch resolution aerial imagery for the State of Maryland"},{"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","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","description":"Maryland State Highway Administration road features and additional Maryland focused landmarks"},{"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","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]]],"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","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABLCAMAAAAf8MQEAAAAAXNSR0IArs4c6QAAAt9QTFRF////q6ytVFplAAAB0owMmWYJRS4EZWx3o6OjYmNl7JoE/agGdE0GBgUA9aQOzIkMKhwCFA0BJBQBNBUAdHV15OXpUlVYGhECkWEJ5ZkOsXYKbkoH/64Qu30LgVYImpqbSTEEa0gG8qIOVTkFEgwBHhQCqnEKMSEE/80So20Kck0HCQYB/7IOMzM0uru+Q0tYRCQA/8ER/9oT/+EUlGMJflUI3ZQN/7kQ/60PaUYGZUMG/7EQ/8oSJhkCil0IOiYDMB8CfH1+yYYM4pcOiFsI2ZIN1Y4N/8URIRYCi4uLa3B5NSQD/74RzooM7qAO/7YQ6+vsiloD+6gP/aoP6p0OrnQLnWkKm2kJWz0FUjYFMSED/9QTjV4JdHZ69ff77J4ODAkBX0AGAAEL+fr7S1BVBQIAtXkLhVkIPikExIMMTjUEFhYXysrLxcXF+qcPwYEM1pENHSIqPSkDLR4Dck0I/qoQRzAEe1MH/+gVWzQAg4SFJCQlelIIDgkBYUEGQiwESElLLSADSi0B/9ESDAIArrS9v4ALTDIEDAwMxsvVklsAHRMBjmAJP0JHAAETdEUAhVcISVRlxoUMd1AI/7sOz9HW1IoChFkHomwK/+UUYj4D96UQZjYAGiQ4OURXg4eMk5mm/6wJwH8M3uHmp3AK/90UNDtJLhQAFxABGQ0Bg1gIglUEJjNJl14FsnMBlmUJ0YcA2drbi5WmFQIAi1MAa2trbHaHW1tck5KS8fL0fEoAOxwAJCw7/7YFUiwAgU0AJQwA6ZcCJy9BDRcrsLCx/8oU2t3j7/H2ChEfu73DAAAA1NXXAAAGWmJtEx42qWoAVDkEzIQAa0YEo2QAAw4lfIGNhY2bdnyIm2QCp6y2eoWXLTA5w34AjZKbRE1hdn+RrHEFxoAAu8DGY26BAQocnZ+kvHkB5JQB/8QOhIqVORcATCYA24wA+6YK8JsCJQYAn6Wu0YsMnai8hY+hU2B4tSvHUAAACMpJREFUWMO1mP9TFPcZx2nfd9do7xutySG3dznuzuOOQ8PCwd65C2eFY69h6ya7CMuXBDRzcNDksOJhUwkYz5IYLFaKDco41qqNEztmnMwk1aaNbZN0MtpYG5O06ZdfajWTpJl2pn9An4WxxS9HhZl+fgBm9/P6fJ7P87yf5/ksBQX/j/E50DAY9Z/4wuLQe+8jxlFYVOwE44LZvRK4fxE0UAJ4jb5VAVtpMIRwuQNYfdf4AxVsFRtBdU00hmJeqEVdHOvwlbvFMTciBpRI+Bo20EEgVzcAd0U/9HAgpMhqzcZwK6CF29pLw52wqc0mPPLoXdD6zqu0Lo5d3yKDQRws6oH1XZuAzY/dheWmysyACSFRllaVJlsAPlMOxB1xxPA/PLDmG/BstUr127IZUzIqbkHNkAN1omzXTdqeRiG+tQC9A0/CJBfpcwetoVR9R6Kp0/dUWuiKAz79aWv+/XfO+jsZ634asK30AKSWGIaJ4HZhDo/kENv9UJ5TN40lakK9ydFamvgMsToPsAPgurdRDPQlWlBU+Owd+T3PiUILbWGvNgHjsPSjv2+EoLJKcP4e3RB91O4FvnMHej84toxeGyabBmwDGN+O70HzFfP0yMbCC4SAUYDWmdp9u34O4PtsDI5Jrvr5Mne1PIyw3eEaD/T1kT1sJQ4msRFwYogM6ANuM39iX/AQDgXZ5JxgOZu/xj+JtK21jk7ct7EqiRkfRsIRwNMP5+Fb6B8cFYubpawv1uCtslVSlsHLS05vO1iWLDY3lg/C20+OYIF2IHOL+ccg8TKbjZaJuaJqOHs6arR6JSqFGFg3TQNlW8rjsJrQDwm9FoycmIv+ih3ACh3/0QucxCckZkCKztoeEiSecEkoMWKMnG7LJuAdRRoyRANkfdKNzNRNxxTsibWIqYzqCoTpYXuQEeowkPG3wwRXW5VpAwKmMFxuFAWRQjc7TdufrmRnrdj8XE4TONYFWZ4k9iXydkDowTQnMZ0mlPKdnMeKuMmPlSrSHTRjYwA49phZrMQZ3Qq2R5YVhn1KDFJ4kNAVMoi1ckYN1rGFEbfEdgv2dE0EouQARy9FoOKBFXAU60X02NEOcw3NVQV6czCTHG94CbBwIqdGpZFOuFGbA59ubx4eFYm14ZEClEntN05e8MoJN+rlDLmKzErANxwv1fOjbEyWZlAMirVs92IwGlo/QMapqVcL8MWDNGHvLH52ohOeRjnDFgPFlXDSU8/W0XEqM8nK7RYh7Ca8uhnJDm+jx5jE6Ln9FKkAUvaD53T8CaDzRE8Hh0ZPMAq+3oxefqMJRoajpG335ygBrblxnAxuiCD94m7fdjxesAbdghdJHV/2c8jBcc0yXtUiaJCmqK4OdoqbMCC6KfMwSllirQFacj1j8KeQntRt3nnoYN/c2Ze9PtrB+4GwVeCc9TwH11DEmFMQiDbDjG46ETZQs1rZ0S7BCL/mmqXO/+JLc5p79s1YM47XFrfqxUhkfWVubHAIAd2xiZawNQuxT49kLob29iJKWnLRbMG+94nH9V+OSbcBdm0wRXNKmnPF6ouUGV3f1PGUrKsgJIdR18UgPBLTO0aVpr01L18KzU4NTc7C7tI2ItLTQoikYTXPxvU4EOwZPlkNC6uhpQso7EXQq/36psrOhtHkKBn0wYO3d+qaonlvXEDWAj/6EqK+zo7XUEa1IDXW6xAaNl38zXxcgik+UtpmxKqKX94DE2ewUkK/E49SW4NdFB06f2a2DDcLZs1VFrv0zs34KLzr0hFYfovVGFYZxoz7cBprSRHoEeM6eXbN/fcgIAvlI/EILuO/3WoZHTUONY3Y8+lEEGAURYnYZYx4U0X4Lorm6tcOPUbANjzdNIKjeGsezrqTiAyhtgpolBElfEuTEKqxj44QN2rpJdXPXg/owvK7cX2td6/Mv8XkfjgUqd1KSUJvZnFV1mSqkW6kZutmrpky8Kbe/948178/xaiiw4zCetP2QjtkJZORIj0Ry0mEbaU011pt6V7obnBJUrkQbgyOZaVgnZX+Mpav6ySbPP9J7TzdbYrhRa3Jjlg1ySzV0BKZJnUHOlnomyvU32Ilnrfz4h9gisVYTSkqu1BtmN2rl0qHik4KhLvDI5QrM9xC2/+exyRrRS8LbWiY6G7VYxwMIkR4WWWTOKOoDB7Mi/8BDZDkLXpLHtyme8EWccOZ8AVyJPtck0ixmLk0sdCVxs7yzRjWW2wf07+3z0ZZ7YGLcEZO8KQERXz5lfz4xGmJb4wX+Xyo9ett3I2v6yHrgka9S9VxaaHtJ96lLicaSTU9VYZG24k/oWD16r+8vAsBSZkb5c0LOO8ClgciHMcxYhqXL5/CH+cer97K6xpmIryiqsG/5udfO+8KScqMKrXiytWrf7ux6jVRt5zr4fSfFxdw3ubGEZuiKswUblGUDgbKyQge+aVTsCc446SdGEH74GZFkd9ln6GcVtl1eAFclHyMzPNad2rzvAVwSlLUzFopS0tfX8B5+1nOx/cG3M8EPzo0b9oeXCeTtGyUlJMfP4Bz/EqXjeMMgotjH56fzuD6tspRNRpVy/F+Pse9LnBBF8sFj7O8N7j8zHzv5VrAz6iGAT748Yd58Cv7xOo6p1RnGJaCYJ+c/+rwiTaQ+6ZbZSEv/m0IljdlH0JO/fr451uu+BGKmllWrl/M/w3xCfYJWuq0Gdd+9cYt6VQoU+wMvPJpfs8f+fyDmz/efceylGI4ync+OlPx48V/TuKnnKpEmSwF7tzEEvCfZenkdQlS3WdYNP0e5BlFifbLC8om7zg7UcHyKlPPqNHs3/GPRfOP4vQ/ZTWqMusZ4csfLv7wB64Osnrf8qjiUvCCf73AKiov+fjMYr/k53x/jVNVmTUW18SxFPwzWcnKnDIsn1oSvlzqoc+FrNzF7l4K/hF9PNazHNtbWbEU/Px1tLjlkYSx45Ol/R+lQpROYoDjtKXhn0qyBQPeNiwNPxeUUFupYYn4q37/ha8eOfKTs7e9+TeLgDxdoqv76wAAAABJRU5ErkJggg==","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","endDate":"2015-05-03T00:00:00.000Z","startDate":"2015-03-29T00:00:00.000Z","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],[-73.890266,40.998039],[-73.933406,40.882078],[-73.933407,40.882077],[-73.933408,40.882076],[-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.466251,39.750764],[-75.466251,39.750765],[-75.46625,39.750767],[-75.466249,39.750768],[-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)","description":"Digital orthophotography of New Jersey, Near Infrared, 1 foot resolution"},{"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","endDate":"2015-05-03T00:00:00.000Z","startDate":"2015-03-29T00:00:00.000Z","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],[-73.890266,40.998039],[-73.933406,40.882078],[-73.933407,40.882077],[-73.933408,40.882076],[-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.466251,39.750764],[-75.466251,39.750765],[-75.46625,39.750767],[-75.466249,39.750768],[-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)","description":"Digital orthophotography of New Jersey, Natural Color, 1 foot resolution"},{"id":"NLS-Bartholomew-hfinch-hist","name":"NLS - Bartholomew Half Inch, 1897-1907","type":"tms","template":"http://geo.nls.uk/mapdata2/bartholomew/great_britain/{zoom}/{x}/{-y}.png","scaleExtent":[0,15],"polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps","icon":"http://nls.tileserver.com/nls70-nq8.png"},{"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","icon":"http://nls.tileserver.com/nls70-nq8.png"},{"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","icon":"http://nls.tileserver.com/nls70-nq8.png"},{"id":"NLS-OS-25inch-hist","name":"NLS - OS 25-inch (Scotland), 1892-1905","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25_inch/scotland_1/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"polygon":[[[-5.2112173,54.8018593],[-5.0642752,54.8026508],[-5.0560354,54.6305176],[-4.3158316,54.6297227],[-4.3117117,54.7448258],[-3.8530325,54.7464112],[-3.8530325,54.8034424],[-3.5522818,54.8034424],[-3.5522818,54.8374644],[-3.468511,54.8406277],[-3.4657644,54.8983158],[-3.3847403,54.8991055],[-3.3888601,54.9559214],[-3.0920786,54.9539468],[-3.0392359,54.9923274],[-3.0212713,55.0493881],[-2.9591232,55.0463283],[-2.9202807,55.0666294],[-2.7857081,55.068652],[-2.7852225,55.0914426],[-2.7337562,55.0922761],[-2.737616,55.151204],[-2.7648395,55.1510672],[-2.7013114,55.1722505],[-2.6635459,55.2192808],[-2.6460364,55.2188891],[-2.629042,55.2233933],[-2.6317886,55.2287781],[-2.6235488,55.2446345],[-2.6197723,55.2454663],[-2.6099017,55.2454174],[-2.6099876,55.2486466],[-2.6408121,55.2590039],[-2.6247896,55.2615631],[-2.6045186,55.2823081],[-2.5693176,55.296132],[-2.5479542,55.3121617],[-2.5091116,55.3234891],[-2.4780376,55.3494471],[-2.4421083,55.3533118],[-2.4052079,55.3439256],[-2.3726772,55.3447539],[-2.3221819,55.3687665],[-2.3241241,55.3999337],[-2.2576062,55.425015],[-2.1985547,55.4273529],[-2.1484296,55.4717466],[-2.1944348,55.484199],[-2.2040479,55.529306],[-2.2960584,55.6379722],[-2.2177808,55.6379722],[-2.1059266,55.7452498],[-1.9716874,55.7462161],[-1.9697453,55.9190951],[-2.1201694,55.9207115],[-2.1242893,55.9776133],[-2.3440159,55.9783817],[-2.3440159,56.0390349],[-2.5046909,56.0413363],[-2.500571,56.1003588],[-2.8823459,56.0957629],[-2.8823459,56.1722898],[-2.4126804,56.1692316],[-2.4181736,56.2334017],[-2.5857151,56.2303484],[-2.5719822,56.3416356],[-2.7257908,56.3462022],[-2.7312839,56.4343808],[-2.6928318,56.4343808],[-2.6928318,56.4859769],[-2.5307834,56.4935587],[-2.5307834,56.570806],[-2.5302878,56.6047947],[-2.3732428,56.6044452],[-2.3684363,56.7398824],[-2.3292975,56.7398824],[-2.3292975,56.7888065],[-2.3145346,56.7891826],[-2.3148779,56.7967036],[-2.171369,56.7967036],[-2.1703979,56.9710595],[-2.0101725,56.9694716],[-2.0101725,57.0846832],[-2.0817687,57.085349],[-2.0488097,57.1259963],[-2.0409133,57.126369],[-2.0383434,57.2411129],[-1.878118,57.2421638],[-1.8771469,57.2978175],[-1.9868771,57.2983422],[-1.9082209,57.3560063],[-1.8752048,57.3560063],[-1.8761758,57.3769527],[-1.8120857,57.4120111],[-1.7120661,57.4120111],[-1.7034646,57.6441388],[-1.8666032,57.6451781],[-1.8646611,57.7033351],[-3.1204292,57.7064705],[-3.1218025,57.7504652],[-3.4445259,57.7526635],[-3.4472724,57.7138067],[-3.5145637,57.7094052],[-3.5118171,57.6939956],[-3.7645027,57.6917938],[-3.7672492,57.6344975],[-3.842378,57.6288312],[-3.8438346,57.5965825],[-3.9414265,57.5916386],[-3.9404554,57.6537782],[-3.8894746,57.6529989],[-3.8826772,57.7676408],[-3.7224517,57.766087],[-3.7195385,57.8819201],[-3.9146888,57.8853352],[-3.916062,57.9546243],[-3.745774,57.9538956],[-3.7471473,58.0688409],[-3.5837256,58.0695672],[-3.5837256,58.1116689],[-3.4560096,58.1138452],[-3.4544646,58.228503],[-3.4379851,58.2283222],[-3.4243233,58.2427725],[-3.412307,58.2438567],[-3.3735115,58.2695057],[-3.3063919,58.2862038],[-3.1229154,58.2859395],[-3.123602,58.3443661],[-2.9574338,58.3447264],[-2.951254,58.6422011],[-2.8812162,58.6429157],[-2.8851004,58.8112825],[-2.7180775,58.8142997],[-2.7161354,58.8715749],[-2.556881,58.8775984],[-2.5544533,58.9923453],[-2.5567617,59.0483775],[-2.391893,59.0485996],[-2.3918002,59.1106996],[-2.4733695,59.1106996],[-2.5591563,59.1783028],[-2.5630406,59.2210646],[-2.3921334,59.224046],[-2.3911409,59.2740075],[-2.3639512,59.2745036],[-2.3658933,59.285417],[-2.3911409,59.284921],[-2.3911409,59.3379505],[-2.2221759,59.3381981],[-2.2233897,59.395965],[-2.3758467,59.396583],[-2.3899271,59.4026383],[-2.4008516,59.3962122],[-2.5637882,59.3952604],[-2.5637882,59.3385811],[-2.7320164,59.3375306],[-2.7333896,59.3952604],[-3.0726511,59.3931174],[-3.0703404,59.3354759],[-3.0753186,59.3355634],[-3.0749753,59.3292593],[-3.0698254,59.3289091],[-3.069801,59.2196159],[-3.2363384,59.2166341],[-3.2336751,59.1606496],[-3.4032766,59.1588895],[-3.394086,58.9279316],[-3.5664497,58.9259268],[-3.5611089,58.8679885],[-3.392508,58.8699339],[-3.3894734,58.8698711],[-3.3891093,58.8684905],[-3.3912942,58.868616],[-3.3884161,58.7543084],[-3.2238208,58.7555677],[-3.2189655,58.691289],[-3.4634113,58.6905753],[-3.4551716,58.6341518],[-3.787508,58.6341518],[-3.7861347,58.5769211],[-3.9028645,58.5733411],[-3.9028645,58.6477304],[-4.0690327,58.6491594],[-4.0690327,58.5912376],[-4.7364521,58.5933845],[-4.7364521,58.6505884],[-5.0715351,58.6520173],[-5.0654779,58.5325854],[-5.2332047,58.5316087],[-5.2283494,58.4719947],[-5.2424298,58.4719947],[-5.2366034,58.4089731],[-5.2283494,58.4094818],[-5.2210664,58.3005859],[-5.5657939,58.2959933],[-5.5580254,58.2372573],[-5.4146722,58.2401326],[-5.4141866,58.2267768],[-5.3885749,58.2272242],[-5.382714,58.1198615],[-5.51043,58.1191362],[-5.5114011,58.006214],[-5.6745397,58.0041559],[-5.6716266,57.9449366],[-5.6716266,57.8887166],[-5.8347652,57.8856193],[-5.8277052,57.5988958],[-6.0384259,57.5986357],[-6.0389115,57.6459559],[-6.1981658,57.6456961],[-6.2076123,57.7600132],[-6.537067,57.7544033],[-6.5312406,57.6402392],[-6.7002056,57.6360809],[-6.6807844,57.5236293],[-6.8516915,57.5152857],[-6.8361545,57.3385811],[-6.6730158,57.3438213],[-6.674958,57.2850883],[-6.5098772,57.2850883],[-6.4982244,57.1757637],[-6.3506228,57.1820797],[-6.3312015,57.1251969],[-6.1797156,57.1230884],[-6.1719471,57.0682265],[-6.4593819,57.059779],[-6.4564687,57.1093806],[-6.6671895,57.1062165],[-6.6730158,57.002708],[-6.5021087,57.0048233],[-6.4836097,56.8917522],[-6.3266104,56.8894062],[-6.3156645,56.7799312],[-6.2146739,56.775675],[-6.2146739,56.7234965],[-6.6866107,56.7224309],[-6.6769001,56.6114413],[-6.8419809,56.607166],[-6.8400387,56.5483307],[-7.1546633,56.5461895],[-7.1488369,56.4872592],[-6.9915246,56.490476],[-6.9876404,56.4325329],[-6.6827265,56.4314591],[-6.6769001,56.5472601],[-6.5292985,56.5504717],[-6.5234721,56.4379018],[-6.3661598,56.4368281],[-6.3642177,56.3766524],[-6.5273563,56.3712749],[-6.5171745,56.2428427],[-6.4869621,56.247421],[-6.4869621,56.1893882],[-6.3001945,56.1985572],[-6.3029411,56.2581017],[-5.9019401,56.256576],[-5.8964469,56.0960466],[-6.0282829,56.0883855],[-6.0392692,56.1557502],[-6.3853385,56.1542205],[-6.3606193,55.96099],[-6.2123039,55.9640647],[-6.2047508,55.9202269],[-6.5185478,55.9129158],[-6.5061881,55.7501763],[-6.6764762,55.7409005],[-6.6599967,55.6263176],[-6.3551261,55.6232161],[-6.3578727,55.5689002],[-6.0392692,55.5720059],[-6.0310294,55.6247669],[-5.7398917,55.6309694],[-5.7371452,55.4569279],[-5.8964469,55.4600426],[-5.8964469,55.2789864],[-5.4350211,55.2821151],[-5.4405143,55.4506979],[-5.2867057,55.4569279],[-5.3086784,55.4070602],[-4.9735954,55.4008223],[-4.9845817,55.2038242],[-5.1493766,55.2038242],[-5.1411369,55.037337],[-5.2152946,55.0341891],[-5.2112173,54.8018593]],[[-2.1646559,60.1622059],[-1.9930299,60.1609801],[-1.9946862,60.1035151],[-2.1663122,60.104743],[-2.1646559,60.1622059]],[[-1.5360658,59.8570831],[-1.3653566,59.8559841],[-1.366847,59.7975565],[-1.190628,59.7964199],[-1.1862046,59.9695391],[-1.0078652,59.9683948],[-1.0041233,60.114145],[-0.8360832,60.1130715],[-0.834574,60.1716772],[-1.0074262,60.1727795],[-1.0052165,60.2583924],[-0.8299659,60.2572778],[-0.826979,60.3726551],[-0.6507514,60.3715381],[-0.6477198,60.4882292],[-0.9984896,60.4904445],[-0.9970279,60.546555],[-0.6425288,60.5443201],[-0.6394896,60.6606792],[-0.8148133,60.6617806],[-0.8132987,60.7196112],[-0.6383298,60.7185141],[-0.635467,60.8275393],[-0.797568,60.8285523],[-0.9941426,60.8297807],[-0.9954966,60.7782667],[-1.1670282,60.7793403],[-1.1700357,60.6646181],[-1.5222599,60.6668304],[-1.5237866,60.6084426],[-1.6975673,60.609536],[-1.7021271,60.4345249],[-1.5260578,60.4334111],[-1.5275203,60.3770719],[-1.8751127,60.3792746],[-1.8781372,60.2624647],[-1.7019645,60.2613443],[-1.7049134,60.1470532],[-1.528659,60.1459283],[-1.5360658,59.8570831]],[[-0.9847667,60.8943762],[-0.9860347,60.8361105],[-0.8078362,60.8351904],[-0.8065683,60.8934578],[-0.9847667,60.8943762]],[[-7.7696901,56.8788231],[-7.7614504,56.7608274],[-7.6009049,56.7641903],[-7.5972473,56.819332],[-7.4479894,56.8203948],[-7.4489319,56.8794098],[-7.2841369,56.8794098],[-7.2813904,57.0471152],[-7.1303283,57.0515969],[-7.1330749,57.511801],[-6.96828,57.5147514],[-6.9765198,57.6854668],[-6.8062317,57.6913392],[-6.8089782,57.8041985],[-6.6496765,57.8071252],[-6.6441833,57.8612267],[-6.3200866,57.8626878],[-6.3200866,58.1551617],[-6.1607849,58.1522633],[-6.1552917,58.20874],[-5.9850036,58.2101869],[-5.9904968,58.2680163],[-6.1497986,58.2665717],[-6.1415588,58.5557514],[-6.3173401,58.5557514],[-6.3091003,58.4983923],[-6.4876282,58.4955218],[-6.4876282,58.4423768],[-6.6606628,58.4395018],[-6.6469299,58.3819525],[-6.8117248,58.3805125],[-6.8117248,58.3286357],[-6.9792663,58.3286357],[-6.9710266,58.2694608],[-7.1413147,58.2680163],[-7.1403816,58.0358742],[-7.3020636,58.0351031],[-7.3030347,57.9774797],[-7.1379539,57.9777372],[-7.1413526,57.9202792],[-7.1398961,57.8640206],[-7.3020636,57.862471],[-7.298484,57.7442293],[-7.4509193,57.7456951],[-7.4550392,57.6899522],[-7.6186131,57.6906048],[-7.6198341,57.7456951],[-7.7901222,57.7442293],[-7.7873756,57.6855477],[-7.6222332,57.6853817],[-7.6173779,57.5712602],[-7.788285,57.5709998],[-7.7892561,57.512109],[-7.7038025,57.5115874],[-7.6999183,57.4546902],[-7.5367796,57.4552126],[-7.5348375,57.5126306],[-7.4581235,57.5131521],[-7.4552103,57.2824165],[-7.6115515,57.2845158],[-7.6144647,57.2272651],[-7.451326,57.2256881],[-7.451326,57.1103873],[-7.6164068,57.1088053],[-7.603783,56.8792358],[-7.7696901,56.8788231]],[[-1.7106618,59.5626284],[-1.5417509,59.562215],[-1.5423082,59.5037224],[-1.7112191,59.5041365],[-1.7106618,59.5626284]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps","icon":"http://nls.tileserver.com/nls70-nq8.png"},{"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","icon":"http://nls.tileserver.com/nls70-nq8.png"},{"id":"NLSC-EMAP5","name":"NLSC General Map with Contour line","type":"tms","template":"http://wmts.nlsc.gov.tw/wmts/EMAP5_OPENDATA/default/EPSG:3857/{zoom}/{y}/{x}","startDate":"2015-01-01T00:00:00.000Z","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":"© National Land Surveying and Mapping Center, Taiwan OGDL 1.0","description":"The emap from Taiwan National Land Surveying and Mapping Center","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABHNCSVQICAgIfAhkiAAAAxJJREFUOI3tlF9oW2UYxn9f4nKW2ixfjJGYMnuctRUZ5mhEpjdJEEaHtmsZaKHq0qt6ZdtZL3Zhk3ilIKS9Ui806UStE7Edjln8kwzEwaB6IshsmJIqK1ttZ7Qlzel2eryQhqZrsDC8EHyuvu993+/53j+8D/yPfxtip4GqH1X1owLkdHI3RSwbkbFu1yAPdx4t3hpSS6YLAM05i/vCqcmzZwpj9T6pIZYOZNArNADhsQj3RVNjtyS1DcKtiHlPIb96PTn67nJiq8++cRgJicTpQ7Yz0oHc7cQZeakzPbTyqr9iKXUr0lfbqOx7LHJgbXrux5/X9M0+G0C8SySeeWTPQPSLxu4jn1vd4tE7m4euDNclrCEvt6E+25/e6H+VuKen57vEe1b8I29b8cKyo6j6Uece6I/VK387jC70crgjMFBDPDEx8aA5aOPkG+f7FhcX9YhGZLIUBSD7VAtSsZOKNpGKNgFU710tbiJ7G0lFm9DucCL2R7uCXjTpQFZbMV6wMu+EbWnpQOIJVKcvFTuDIR+az4nmc1Zt6h4HuV9XGHjIx1D2EvrCKtLnUgE+Pig+kQ6kDeDFc9YQwJdP2rLuBlfzRjklw7yh7JJh0vfZL6Tb70IqdqRSnT/5JfQTBcZfDom4HaBiUjn5k/Xh0VYRe85ztZ11QX53K4ZQyPxwFcO0yP+2Ste9bi6XrxPbfxuvnV9g6uIfPK/dTskwURbOFfPTM2PSIeTT99Bzw4KMhERi5ICIl667OOHuYNzdQV5p/ccBxi89kUmm5vveDou06kLddvNSibasbvZGXvj9fYJGgbldAaYaI+SVVoq7ApxtCNXEH7ZyhL8+Nho00YJeoT3+6Xp0W2KtBU07NpzNlHulem2ecHmGzpUcmlGg+dp83aynitbkK99ayfwSel2tiLUTo3M4lSn3ys12ub5MsFL4O4GGWZq/fyszfvrPsfwSNZtnpw70i+jMfjPdf//MfXf7UYtrASqWQkUoeNzLtHumS0buzePJD4zjV1a5vPX9jmRT9aNGNCKbZXMn0vnfwl+e9BTflqrxKAAAAABJRU5ErkJggg=="},{"id":"MAPNIK","name":"OpenStreetMap (Standard)","type":"tms","template":"https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png","scaleExtent":[0,19],"terms_url":"https://www.openstreetmap.org/","terms_text":"© OpenStreetMap contributors, CC-BY-SA","default":true,"description":"The default OpenStreetMap layer.","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAGb0lEQVR4Xq3MS2xcVx3H8e855z7m3vH1jMdjO43zshIrtpM0SZ3WFEcRVFFKoRWPBYtAHwgWCFUsQN100QeCsqAhCESrirRASdWWIkoUqgKFJm3UZ5o2oW2akrR5uXbi2ON4PPfOfZ17iERW2bCAz1/f3V8/cfDC02UEj4OxKHjdFMUfmUzOlAeXZFZuuVIKN8zi1dPh7Hcn5091G2EOB5b//NplA28/9tAT4bq111jD64ZKHR2VQWPEbULI0aHqZz7NZeLNmSeVMOJu4AfGgNEGLsR/95YuetcRzprcFJvaaVxrpm2mmqfp8FxKSYk8ck+0pt1nykFp0A/k9Tnt/lq3T2dHEOmi2DxSu+EdAAFwcPqp640xe42h26Qa2hqnXsFVHs04pNFuYgvbtOWCmD3aMj2VNaLi1+jwyxgpCKOQRCdMN6ZMd5Bmw1cPfG+5O/7LeX0ECyBppx9Zrn0c6BbNHJNr4qhFYWtsJCWpSFUm3ntxips2bxe+p1BKIJQECpRbkCQ2wu0XzbnIeemvhzYCVNR6JMDm5bdNF9qcwhiKbpvMg2KujZDmUgX1jgqT719gy+iX6QxsPM9F2YqclHbRRpUEXmCRZTGFlZGKxSMbR6+uA0gu863OzLc7cVUZN6jgKI8kicl0ykzjAiW5lGrVAWUwokApSa3UTY/XR2B3UlDgVy1sB8od7tgt2++4AcACOHL+uRW2bW8QQiCxcUoS6XssyBbnF6Y5+8kci8vjlJwqjnQwWpDlgtRYZDpHmxJzWUyk26gOYXxK0g+8G4bXX/snC0DZcmVh9EoQ5DpDSIVJYmIiGvkCurAQpkLU9kkTEEJeCjxbURSCZgTkfVjOApoM6Qtc3109Nj7uWO9M70EbPQT4YMhNjrWQEdHmTPs8SgfUisUgDLoAgcGyEjJtEaeaVlKQ5gVSGYwBhETaEmVJcemQaZ44aRpvyLIEnedGoNHNkNTTeI5DT2kRljeJziVhnKNlE1GaJFfnuRi3SXMDxmA7IUqCI20qdifkxfED+/dlanzb1cYL3BFhsTXPU4Ep0FGKUVALegCb1oLN7FlNpd5HIUNQLYxIsO0EKcByWljuAmXbp7fcIwgVb7xyaNeep3YfUnt272PLjaP1em/lZqmEk4cJQoMKfBxVIcwjlAp47okX6ap3XaoP221CIREyx7La2E6O7/h0eTXK+Bw+8uHrP7znvocXLe6flwCHXj06kab5hJAS6dhQFOgiJ2qXsKLVuHqAgdVD7HrwXibPTKJzFyMMAgECHGXTJTqxE4t3T5xMD7y29+mFRjgpLSUlYJ793T9ORWF0Lk1StCzQNqTTAle30flbzJ/bx6n3Xsa2Fb9/5Eccfu19wnlNFBniWJA3JecbDfa/8y5nJg7bW7ZeuyYKZwyF0QIAkC988Ogzfof6SppapHGZqgNTExPsfngfgaXpqyWk9QF6lwWk7YJlK1fQaTysqk8sE6LwIq4OEMql1DH3/O03PnBHUCk3JMCeA7/q6u1a0ltiNZ1eL719cPrcWR752d+Yn2lx/HSDY40qY2Pb2PapjYxv3YBX1syZ88weP3bp90Omw3PMOxNUe9FTn9gn5uemQqfk5BbAisHBlVo7g7PFx9TdgDMnZvjtzheI51qkWY5xYWxTLxXfJ5IVevIZ6gMDxCYnPjWDXZ0nSiOkEmYqO5l8cGT6FSD6+NhRJMCF1sWV88VkX6f3n/FHd+xl9uwsrTDEOIbPfWEj120eorw0JEzLhGWfop3ixxKrP0CTIQSAEVmhw5/f94uXAANg3b/r+1YrnV1T86ucPDzBrp3PcvHcHGmaUekL+OKtm9m0ailOUEe4FrXyWaKFblM4HmUvElNzF4jTxFiOhRRSJO34JHCOy6RU0i60uepfx07nO+593FycapAkCbX+Kl+/cxvXfXYIU3GjN/Yf2vPPg2/9JVxoNYNqQ+hcilznlKWDcpSwlCWiZrtx/O3Tf+AKClj88I9v/9aD99/aHBkaLlYNDTXuvPubH/3kN3e9vP3bn78HGAP6gSXA6K3fufnOXz+/888vHH3i9O4XH3j1roe+8dDo1pGvAeuAClfa/+aTQH35Yztuenz7l4aPLB9c81O/3H3L5VHFlUACZaAH6AQc/pv1o9cEiwbWbRlev+mrazeOblg3usnj/6nWV2fVyFp71fCa0sDgkOKyq5av4H/xb0Ky8po5hQEuAAAAAElFTkSuQmCC"},{"id":"OpenStreetMap-turistautak","name":"OpenStreetMap (turistautak)","type":"tms","template":"http://{switch:h,i,j}.tile.openstreetmap.hu/turistautak/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"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":"https://www.openstreetmap.org/","terms_text":"© OpenStreetMap contributors"},{"id":"osm-gps","name":"OpenStreetMap GPS traces","type":"tms","template":"https://{switch:a,b,c}.gps-tile.openstreetmap.org/lines/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"terms_url":"https://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;'>←</span> <span style='color: #96f;'>↓</span> <span style='color: #6e0;'>↑</span> <span style='color: #f63;'>→</span> </span></span> © <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap contributors</a>.","description":"Public GPS traces uploaded to OpenStreetMap.","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAGb0lEQVR4Xq3MS2xcVx3H8e855z7m3vH1jMdjO43zshIrtpM0SZ3WFEcRVFFKoRWPBYtAHwgWCFUsQN100QeCsqAhCESrirRASdWWIkoUqgKFJm3UZ5o2oW2akrR5uXbi2ON4PPfOfZ17iERW2bCAz1/f3V8/cfDC02UEj4OxKHjdFMUfmUzOlAeXZFZuuVIKN8zi1dPh7Hcn5091G2EOB5b//NplA28/9tAT4bq111jD64ZKHR2VQWPEbULI0aHqZz7NZeLNmSeVMOJu4AfGgNEGLsR/95YuetcRzprcFJvaaVxrpm2mmqfp8FxKSYk8ck+0pt1nykFp0A/k9Tnt/lq3T2dHEOmi2DxSu+EdAAFwcPqp640xe42h26Qa2hqnXsFVHs04pNFuYgvbtOWCmD3aMj2VNaLi1+jwyxgpCKOQRCdMN6ZMd5Bmw1cPfG+5O/7LeX0ECyBppx9Zrn0c6BbNHJNr4qhFYWtsJCWpSFUm3ntxips2bxe+p1BKIJQECpRbkCQ2wu0XzbnIeemvhzYCVNR6JMDm5bdNF9qcwhiKbpvMg2KujZDmUgX1jgqT719gy+iX6QxsPM9F2YqclHbRRpUEXmCRZTGFlZGKxSMbR6+uA0gu863OzLc7cVUZN6jgKI8kicl0ykzjAiW5lGrVAWUwokApSa3UTY/XR2B3UlDgVy1sB8od7tgt2++4AcACOHL+uRW2bW8QQiCxcUoS6XssyBbnF6Y5+8kci8vjlJwqjnQwWpDlgtRYZDpHmxJzWUyk26gOYXxK0g+8G4bXX/snC0DZcmVh9EoQ5DpDSIVJYmIiGvkCurAQpkLU9kkTEEJeCjxbURSCZgTkfVjOApoM6Qtc3109Nj7uWO9M70EbPQT4YMhNjrWQEdHmTPs8SgfUisUgDLoAgcGyEjJtEaeaVlKQ5gVSGYwBhETaEmVJcemQaZ44aRpvyLIEnedGoNHNkNTTeI5DT2kRljeJziVhnKNlE1GaJFfnuRi3SXMDxmA7IUqCI20qdifkxfED+/dlanzb1cYL3BFhsTXPU4Ep0FGKUVALegCb1oLN7FlNpd5HIUNQLYxIsO0EKcByWljuAmXbp7fcIwgVb7xyaNeep3YfUnt272PLjaP1em/lZqmEk4cJQoMKfBxVIcwjlAp47okX6ap3XaoP221CIREyx7La2E6O7/h0eTXK+Bw+8uHrP7znvocXLe6flwCHXj06kab5hJAS6dhQFOgiJ2qXsKLVuHqAgdVD7HrwXibPTKJzFyMMAgECHGXTJTqxE4t3T5xMD7y29+mFRjgpLSUlYJ793T9ORWF0Lk1StCzQNqTTAle30flbzJ/bx6n3Xsa2Fb9/5Eccfu19wnlNFBniWJA3JecbDfa/8y5nJg7bW7ZeuyYKZwyF0QIAkC988Ogzfof6SppapHGZqgNTExPsfngfgaXpqyWk9QF6lwWk7YJlK1fQaTysqk8sE6LwIq4OEMql1DH3/O03PnBHUCk3JMCeA7/q6u1a0ltiNZ1eL719cPrcWR752d+Yn2lx/HSDY40qY2Pb2PapjYxv3YBX1syZ88weP3bp90Omw3PMOxNUe9FTn9gn5uemQqfk5BbAisHBlVo7g7PFx9TdgDMnZvjtzheI51qkWY5xYWxTLxXfJ5IVevIZ6gMDxCYnPjWDXZ0nSiOkEmYqO5l8cGT6FSD6+NhRJMCF1sWV88VkX6f3n/FHd+xl9uwsrTDEOIbPfWEj120eorw0JEzLhGWfop3ixxKrP0CTIQSAEVmhw5/f94uXAANg3b/r+1YrnV1T86ucPDzBrp3PcvHcHGmaUekL+OKtm9m0ailOUEe4FrXyWaKFblM4HmUvElNzF4jTxFiOhRRSJO34JHCOy6RU0i60uepfx07nO+593FycapAkCbX+Kl+/cxvXfXYIU3GjN/Yf2vPPg2/9JVxoNYNqQ+hcilznlKWDcpSwlCWiZrtx/O3Tf+AKClj88I9v/9aD99/aHBkaLlYNDTXuvPubH/3kN3e9vP3bn78HGAP6gSXA6K3fufnOXz+/888vHH3i9O4XH3j1roe+8dDo1pGvAeuAClfa/+aTQH35Yztuenz7l4aPLB9c81O/3H3L5VHFlUACZaAH6AQc/pv1o9cEiwbWbRlev+mrazeOblg3usnj/6nWV2fVyFp71fCa0sDgkOKyq5av4H/xb0Ky8po5hQEuAAAAAElFTkSuQmCC","overlay":true},{"id":"lu.geoportail.opendata.ortho2010","name":"Ortho 2010 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2010/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","endDate":"2010-07-02T00:00:00.000Z","startDate":"2010-06-24T00:00:00.000Z","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","icon":"https://www.geoportail.lu/static/img/lion.png"},{"id":"lu.geoportail.opendata.ortho2013","name":"Ortho 2013 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2013/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","endDate":"2013-07-20T00:00:00.000Z","startDate":"2013-07-19T00:00:00.000Z","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","icon":"https://www.geoportail.lu/static/img/lion.png"},{"id":"lu.geoportail.opendata.ortho2016","name":"Ortho 2016 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2016/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","endDate":"2016-08-16T00:00:00.000Z","startDate":"2013-08-30T00:00:00.000Z","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,"icon":"https://www.geoportail.lu/static/img/lion.png"},{"id":"OS-historic-25k-OSM_Limited","name":"OS 1:25k historic (OSM)","type":"tms","template":"http://ooc.openstreetmap.org/os1/{zoom}/{x}/{y}.jpg","scaleExtent":[6,17],"polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]]},{"id":"OS-New_Popular_Edition-historic","name":"OS New Popular Edition historic","type":"tms","template":"http://ooc.openstreetmap.org/npe/{zoom}/{x}/{y}.png","polygon":[[[-5.8,49.8],[-5.8,55.8],[1.9,55.8],[1.9,49.8],[-5.8,49.8]]]},{"id":"OS-OpenData_Locator","name":"OS OpenData Locator","type":"tms","template":"http://tiles.itoworld.com/os_locator/{zoom}/{x}/{y}.png","polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"overlay":true},{"id":"OS-OpenData_StreetView","name":"OS OpenData StreetView","type":"tms","template":"http://os.openstreetmap.org/sv/{zoom}/{x}/{y}.png","scaleExtent":[1,18],"polygon":[[[-5.8292886,50.0229734],[-5.8292886,50.254819],[-5.373356,50.254819],[-5.373356,50.3530588],[-5.1756021,50.3530588],[-5.1756021,50.5925406],[-4.9970743,50.5925406],[-4.9970743,50.6935617],[-4.7965738,50.6935617],[-4.7965738,50.7822112],[-4.6949503,50.7822112],[-4.6949503,50.9607371],[-4.6043131,50.9607371],[-4.6043131,51.0692066],[-4.3792215,51.0692066],[-4.3792215,51.2521782],[-3.9039346,51.2521782],[-3.9039346,51.2916998],[-3.7171671,51.2916998],[-3.7171671,51.2453014],[-3.1486246,51.2453014],[-3.1486246,51.362067],[-3.7446329,51.362067],[-3.7446329,51.4340386],[-3.8297769,51.4340386],[-3.8297769,51.5298246],[-4.0852091,51.5298246],[-4.0852091,51.4939284],[-4.3792215,51.4939284],[-4.3792215,51.5427168],[-5.1444195,51.5427168],[-5.1444195,51.6296003],[-5.7387103,51.6296003],[-5.7387103,51.774037],[-5.5095393,51.774037],[-5.5095393,51.9802596],[-5.198799,51.9802596],[-5.198799,52.0973358],[-4.8880588,52.0973358],[-4.8880588,52.1831557],[-4.4957492,52.1831557],[-4.4957492,52.2925739],[-4.3015365,52.2925739],[-4.3015365,52.3685318],[-4.1811246,52.3685318],[-4.1811246,52.7933685],[-4.4413696,52.7933685],[-4.4413696,52.7369614],[-4.8569847,52.7369614],[-4.8569847,52.9317255],[-4.7288044,52.9317255],[-4.7288044,53.5038599],[-4.1578191,53.5038599],[-4.1578191,53.4113498],[-3.3110518,53.4113498],[-3.3110518,53.5038599],[-3.2333667,53.5038599],[-3.2333667,54.0159169],[-3.3926211,54.0159169],[-3.3926211,54.1980953],[-3.559644,54.1980953],[-3.559644,54.433732],[-3.7188984,54.433732],[-3.7188984,54.721897],[-4.3015365,54.721897],[-4.3015365,54.6140739],[-5.0473132,54.6140739],[-5.0473132,54.7532915],[-5.2298731,54.7532915],[-5.2298731,55.2190799],[-5.6532567,55.2190799],[-5.6532567,55.250088],[-5.8979647,55.250088],[-5.8979647,55.4822462],[-6.5933212,55.4822462],[-6.5933212,56.3013441],[-7.1727691,56.3013441],[-7.1727691,56.5601822],[-6.8171722,56.5601822],[-6.8171722,56.6991713],[-6.5315276,56.6991713],[-6.5315276,56.9066964],[-6.811679,56.9066964],[-6.811679,57.3716613],[-6.8721038,57.3716613],[-6.8721038,57.5518893],[-7.0973235,57.5518893],[-7.0973235,57.2411085],[-7.1742278,57.2411085],[-7.1742278,56.9066964],[-7.3719817,56.9066964],[-7.3719817,56.8075885],[-7.5202972,56.8075885],[-7.5202972,56.7142479],[-7.8306806,56.7142479],[-7.8306806,56.8994605],[-7.6494061,56.8994605],[-7.6494061,57.4739617],[-7.8306806,57.4739617],[-7.8306806,57.7915584],[-7.4736249,57.7915584],[-7.4736249,58.086063],[-7.1879804,58.086063],[-7.1879804,58.367197],[-6.8034589,58.367197],[-6.8034589,58.4155786],[-6.638664,58.4155786],[-6.638664,58.4673277],[-6.5178143,58.4673277],[-6.5178143,58.5625632],[-6.0536224,58.5625632],[-6.0536224,58.1568843],[-6.1470062,58.1568843],[-6.1470062,58.1105865],[-6.2799798,58.1105865],[-6.2799798,57.7122664],[-6.1591302,57.7122664],[-6.1591302,57.6667563],[-5.9339104,57.6667563],[-5.9339104,57.8892524],[-5.80643,57.8892524],[-5.80643,57.9621767],[-5.6141692,57.9621767],[-5.6141692,58.0911236],[-5.490819,58.0911236],[-5.490819,58.3733281],[-5.3199118,58.3733281],[-5.3199118,58.75015],[-3.5719977,58.75015],[-3.5719977,59.2091788],[-3.1944501,59.2091788],[-3.1944501,59.4759216],[-2.243583,59.4759216],[-2.243583,59.1388749],[-2.4611012,59.1388749],[-2.4611012,58.8185938],[-2.7407675,58.8185938],[-2.7407675,58.5804743],[-2.9116746,58.5804743],[-2.9116746,58.1157523],[-3.4865441,58.1157523],[-3.4865441,57.740386],[-1.7153245,57.740386],[-1.7153245,57.2225558],[-1.9794538,57.2225558],[-1.9794538,56.8760742],[-2.1658979,56.8760742],[-2.1658979,56.6333186],[-2.3601106,56.6333186],[-2.3601106,56.0477521],[-1.9794538,56.0477521],[-1.9794538,55.8650949],[-1.4745008,55.8650949],[-1.4745008,55.2499926],[-1.3221997,55.2499926],[-1.3221997,54.8221737],[-1.0550014,54.8221737],[-1.0550014,54.6746628],[-0.6618765,54.6746628],[-0.6618765,54.5527463],[-0.3247617,54.5527463],[-0.3247617,54.2865195],[0.0092841,54.2865195],[0.0092841,53.7938518],[0.2081962,53.7938518],[0.2081962,53.5217726],[0.4163548,53.5217726],[0.4163548,53.0298851],[1.4273388,53.0298851],[1.4273388,52.92021],[1.8333912,52.92021],[1.8333912,52.042488],[1.5235504,52.042488],[1.5235504,51.8261335],[1.2697049,51.8261335],[1.2697049,51.6967453],[1.116651,51.6967453],[1.116651,51.440346],[1.5235504,51.440346],[1.5235504,51.3331831],[1.4507565,51.3331831],[1.4507565,51.0207553],[1.0699883,51.0207553],[1.0699883,50.9008416],[0.7788126,50.9008416],[0.7788126,50.729843],[-0.7255952,50.729843],[-0.7255952,50.7038437],[-1.0074383,50.7038437],[-1.0074383,50.5736307],[-2.3625252,50.5736307],[-2.3625252,50.4846421],[-2.4987805,50.4846421],[-2.4987805,50.5736307],[-3.4096378,50.5736307],[-3.4096378,50.2057837],[-3.6922446,50.2057837],[-3.6922446,50.1347737],[-5.005468,50.1347737],[-5.005468,49.9474456],[-5.2839506,49.9474456],[-5.2839506,50.0229734],[-5.8292886,50.0229734]],[[-6.4580707,49.8673563],[-6.4580707,49.9499935],[-6.3978807,49.9499935],[-6.3978807,50.0053797],[-6.1799606,50.0053797],[-6.1799606,49.9168614],[-6.2540201,49.9168614],[-6.2540201,49.8673563],[-6.4580707,49.8673563]],[[-5.8343165,49.932156],[-5.8343165,49.9754641],[-5.7683254,49.9754641],[-5.7683254,49.932156],[-5.8343165,49.932156]],[[-1.9483797,60.6885737],[-1.9483797,60.3058841],[-1.7543149,60.3058841],[-1.7543149,60.1284428],[-1.5754914,60.1284428],[-1.5754914,59.797917],[-1.0316959,59.797917],[-1.0316959,60.0354518],[-0.6626918,60.0354518],[-0.6626918,60.9103862],[-1.1034395,60.9103862],[-1.1034395,60.8040022],[-1.3506319,60.8040022],[-1.3506319,60.6885737],[-1.9483797,60.6885737]],[[-2.203381,60.1968568],[-2.203381,60.0929443],[-1.9864011,60.0929443],[-1.9864011,60.1968568],[-2.203381,60.1968568]],[[-1.7543149,59.5698289],[-1.7543149,59.4639383],[-1.5373349,59.4639383],[-1.5373349,59.5698289],[-1.7543149,59.5698289]],[[-4.5585981,59.1370518],[-4.5585981,58.9569099],[-4.2867004,58.9569099],[-4.2867004,59.1370518],[-4.5585981,59.1370518]],[[-6.2787732,59.2025744],[-6.2787732,59.0227769],[-5.6650612,59.0227769],[-5.6650612,59.2025744],[-6.2787732,59.2025744]],[[-8.7163482,57.9440556],[-8.7163482,57.7305936],[-8.3592926,57.7305936],[-8.3592926,57.9440556],[-8.7163482,57.9440556]],[[-7.6077005,50.4021026],[-7.6077005,50.2688657],[-7.3907205,50.2688657],[-7.3907205,50.4021026],[-7.6077005,50.4021026]],[[-7.7304303,58.3579902],[-7.7304303,58.248313],[-7.5134503,58.248313],[-7.5134503,58.3579902],[-7.7304303,58.3579902]]]},{"id":"OS-Scottish_Popular-historic","name":"OS Scottish Popular historic","type":"tms","template":"http://ooc.openstreetmap.org/npescotland/tiles/{zoom}/{x}/{y}.jpg","scaleExtent":[6,15],"polygon":[[[-7.8,54.5],[-7.8,61.1],[-1.1,61.1],[-1.1,54.5],[-7.8,54.5]]]},{"id":"Pangasinan_Bulacan_HiRes","name":"Pangasinán/Bulacan (Philippines 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":"Actueel_ortho25_WMTS","name":"PDOK Luchtfoto Beeldmateriaal 25cm","type":"tms","template":"http://geodata.nationaalgeoregister.nl/luchtfoto/wmts?FORMAT=image/jpeg&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=2016_ortho25&STYLE=&FORMAT=image/jpeg&tileMatrixSet=OGC:1.0:GoogleMapsCompatible&tileMatrix={zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,18],"polygon":[[[3.1437689,51.3598403],[3.1575018,51.2411346],[3.3387762,51.1154412],[3.9128119,51.0585083],[4.6571356,51.2806657],[4.8933416,51.2634825],[5.1789862,51.1257851],[5.3849798,51.1309561],[5.5442816,51.056782],[5.4206854,50.8595581],[5.4673773,50.7032633],[5.6568914,50.6192567],[6.1485296,50.6214349],[6.3023382,50.8578243],[6.2995916,50.9543819],[6.2638861,51.0183545],[6.3723761,51.0925902],[6.4012152,51.2011393],[6.3737494,51.2510206],[6.4451605,51.3158713],[6.4204413,51.5496009],[6.343537,51.6792182],[6.796723,51.7642909],[7.046662,51.9102418],[7.0713812,52.0455856],[7.2718817,52.1704147],[7.3075872,52.3855111],[7.2059637,52.5319494],[7.282868,52.614576],[7.2993475,52.7785318],[7.4421698,52.9782705],[7.43393,53.2831352],[7.0439154,53.5515877],[6.7829901,53.6363531],[6.2391668,53.5401639],[5.6871039,53.5124077],[5.173493,53.4388477],[4.8164373,53.2338445],[4.6516424,53.0658312],[4.5417791,52.4859784],[4.3220526,52.1956753],[4.08104,52.0136897],[4.0219885,52.0162253],[3.9368445,51.9637937],[3.9519507,51.8807927],[3.844834,51.8494157],[3.6237341,51.7075226],[3.6553198,51.6606936],[3.6333471,51.6274583],[3.5468298,51.622343],[3.3957678,51.5609145],[3.3820349,51.5173524],[3.4987646,51.4326715],[3.3298498,51.3855587],[3.1437689,51.3598403]]],"terms_url":"http://www.nationaalgeoregister.nl/geonetwork/srv/dut/catalog.search#/search?facet.q=license%2FCC-BY&isChild=%27false%27&resultType=details&any_OR_title_OR_keyword=luchtfoto&fast=index&_content_type=json&from=1&to=20&sortBy=relevance","terms_text":"Kadaster / Beeldmateriaal.nl, CC BY 4.0","best":true,"description":"Landsdekkende dataset 25cm resolutie kleuren luchtfotos van de meest recente jaargang.","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGYAAABpCAMAAAD/V6aFAAABQVBMVEVHcEzFxcUIjtE3quLGxsYMlNMxseXFxcXFxcXGxsY3qeC82+c4qeA4quEcod3FxcXGxsbGxsbKysrHx8cGkdLGxsYPl9fExMTGxsbGxsbGxsYGjtDGxsYLlNXFxcXKysrGxsY3qeDFxcXGxsbFxcXGxsY3qeHGxsbIyMjGxsbGxsbFxcXFxcXFxcXGxsYBi883quHExMTGxsbGxsYgpdkYntoeqtXGxsYko93FxcXFxcUio97GxsYDjdAcn9rGxsbGxsbGxsYQmdjGxsYCjdAAis0IktM1qODGxsbHx8fGxsY3quHFxcUco93GxsbGxsbFxcUmotw3q+E4quE3quE3quACjtEKl9XGxsbFxcUZoNkBi883qeHGxsYAis44quEAic0AiM08rOIcnNk6q+IspN4Mk9QFj9EXmdclodzGxsbX17u1AAAAXnRSTlMA7d4ItK8KTHw//QHerC31nSgFHsszjQ5Bw23d6qMYFFmUZtVH78rkCTn4uIZUdvqAFKxPDUAEozao2iLQ5V39lLF/y+z+wd1he76y+hGNgC1uQO7BUNR6mYRR96TdoavfmwAABLhJREFUeF7s08Fqg0AQBuApCC0IBBtCYpBVbMQmNoF4CfGykV5aKKbXAn2B//0foOLspQF0xhQokO80/2l2WH66xnNx18vz6S+c0K+ha8TukQn62RWNFxzfeY2J0K96pLH2zSSf81hjwIHGevsG7nncYkhC45gDgNKdlWOA/Uo7MemsnwBkAYcGQtmcVJINWi8cZhZCR1JZWrSiKacSUkvSeEBnx2llIWQ/Vbegk8UcQ0i9asqTgJ05biF2Jrn1BJ2J0R6DKmzJGmSq371eWOgsSKK8+M4COrmoOimckHPwAR2PBPbRRQUaKKU0zK/hRHy72UDHTmmYqT1nx2tnhadz8ulfuLn5YazseRMEwjhuJDCIOhkXw8DiagchJkQGInZoHKxWk7Y5nkO09ft/gTb3Sjg4nt/4T7jf5XnhIlcR8SRzbUxaeO/XBFQCGxasd7QToLeyMBglvZZ4AUSw9VjyCcTCvTI1Z0TNciIAlydziwZ+ihZe+jUZVUekPNlbNPS3LEwQrXHVoblozdZas7KqmmU7rXstjm7N7sCSaW7TPO//yM4vOYiaJV9EADOfJUcgVoDK/ix9/NaQ5gQEQOzQh+hPOECTgdJkLPBnfRoQqzPa4DUBJZLImAD76ow9vEZP7yrhzVr11kxM2gTr0HfXgxa1t12jVucDr5mqu8MlZkkKLZbHrYao2eg7DEOkSh8Ke55c2zTPskZRI0VOgNYEMulqukl1SlAWb6s1884/GjyKDt4GKDY5UVxZEl9MjXhjTKojTjOnIKGpfNPAQNTMBLegzn4xVPBPDrNhk8XwddzOGbeg/trT+DxyPAOni/ivXfNbbRSIwvgpLCQiYIyIRmAT1hS1RCEJICmCgjdtKKmXe+ML+P4PsCmzG6Y96zczFO/yu3WGzxnPmTl/JCV37gTFXKb4m6e9zk2JQPWBp5cirfMHY1YoJOi+5MqOkHFrY5kXoLL8WsV4c4XMk6lK7QKZiI326QPPMZWJwafx+UtnojL8aCqzAFZWDYyjeJIYbdgVUIkuB04hvllsoJL4bueO79kclOFbA5mSEHkN5hwMZI4ECP9vs2fx9F1fxfGQX47YUiyc+UVfprWBSjIw5OLTVl/mAlT6QYYfA12NDDhZSLhIZRThAOuHAfBKOviJss5rx98ubGfwTQ+gZ2PSFdriY7EShrMDiyn12hmQx71wK3i1qLCjQUWmKqc6P9UyVmhhwrUYmI0NDH0C3LnjzTTZCicPjnhYh+NLNZbofyiim4IYZi2fnU733hm5ACrT0A5fbSti6AQryWm++9HXUhCRPquXzDnABWwCupJ20VlcBsq4Y0YM5aRyTzfC07+uUlcrD3KOpR01hGexI/ZI1/Nhk+cWjbBsoYqMbYm77TjWSkcpU24cnKYJCDMNl7NKaZR3YO8oA+T0Hu6EcnbqLi3D8YmDTyg2Qz3raUYQ7/NynLZtFzYpKT7vW50TgAdSDWkye5Z9bEMq1rKxvfmkS9DcwsEqIzUROC4BNrmXjxOyjn8FpEHagn9PMEEXht2S9NiyvGwaSmYAEyD9N3Zumma6BdkbyXH2NB2nm8xvmpB9L1WOJiRzWHI+CRHLbafh0l+p1Hb2B2WwRgDiX0fTAAAAAElFTkSuQmCC"},{"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":"Geodatastyrelsen_Denmark","name":"SDFE aerial imagery","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,"icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAABGlBMVEX///+y4OQAAAAKCgrL6ezI6exHs8AdorE/sL0FBQX+/v78/v4RERH5/PzS7fC64+chpLLt+Pm95Og+Pj4mprQYGBgAkaLM6u3D5+oAlabc8fMVn671+/wAjp/Y7/EmJiY4ODg4rbsgICBgYGBLtcHk5OT29vYyMjJqamoNnKtISEhYu8aamppMTEzy+vpycnLg8/S/5emjo6NSUlJfvsgsLCzs7Oxsw81NtsKsrKyu3uPo9vd+ytODzdXk9PaEhISBgYFVVVWe193P7O95yNGPj4/x8fGk2uB7e3vd3d3Hx8cuqbfW1tZnwctRuMOxsbG7u7vQ0NB2dnYAl6dzxs+14eWW1NtRUVGZ1dxwxc6r3eKx3+ON0NiR0tk4C4avAAAG00lEQVR4XtzY5Y4qSxQF4JVqV9zdXcfd3Y/Lve//GrcDdTPQyjDnNMl8PyBAUnuxa1c3Ae8S3l9fP/+KFVG24rm4IZfraFiBRCqX+jyRiscD8F1yUp5K5Xbhs36K1qcJ4ofwVzVuChCFr4a0/swmJOCn/dxnk/g6/FSKmwOkovBTMGUJ0FLgI8EmgAYfRa0BMvBTxzIDcRF+2s1ZjuE3+KplDvBZw58la5rbklfzLUjlDuAim8Ub7ekJlmXP8n04qc7fjEpwFF4v3d2Vtk/fEKJ/xrETHKfDiThJQOvfwUmilBGCBiETXHhKQkmWTUwZETQ4OMjFUxPx3BacfGsFo1Qw87hw/cQrllPgQD5v5eLxXOvBubmnreiMxRIoHK1PcTpcpNMynOUz0TmZf+AtzSXmsFwfy3oUonOCQe+1ZLr/r7g8lpTORE0yP+Clz5kDsAkZy/lhCSDw8HLIJUxYTsNyHoSoSfDOc62hJcDyQ9ARombB0FsCUFz2jwUIRvvwELLpgILlbNlsgedaWesQ6ljSlXUIH+FJtxzDIZYUEoLmY3gFTyFTC1hWwbIeMuYRgDc5z81PwB6Wppla0PqKRZxx7Ez9NN5Bb80maJ1jMTrHsrT93CHe5UwQopSQOcCiQmfclN7HO2XXhYwgBIVMRkzgDbKHw/xwT8MfsHe6zvOdgzw+posCVmsgYbU+MVitJsFqvXSxMkexQrkJ3BpPG1iFcXutdwHct9e+V7AyzxWs1oBgta4ZrNRLhBljhS7IRoREsDI3ZADckmv4bKfSUNWNyhhjBoZKEbefIjG13Lu4hA+eGMJE1tYiDJEaMRia5RiRCmvf2zFCfDiUR6TwTAewwkhHwIvKFHcwUTshDSxNUWR4e5mduVqEFNtSbAcU0CUDLEDLmmuFdC45SnJpBR6+q3XMOJbU4tzGn0h1eEiedx63O1u7M7X6XCA8EQjn4S7WxCy5wpg79ARXXEfk+WqV58Xqb1B7RvnRVDiQhLNuQ2We3K+E9bJaHtzA0Y8SX92eqor7tP0BWt49gVyLkUJFevb4RdRo9Ai5gIOrEi0/k0Ax6s8K6LBVV9VbbBKPAFpsALlHdmBrSOtT1dJvAHpgNO+rAjvH5B64JEeuAeQa6QJolGFrnd+eU+UB0Aa8CuRhZ6MNQ6Po3oExuZk83sNGurRtIo6wFxiZhEf2O3A97UPNNUCkAEONjGHjVDQH4A8wtAYIKLC6ZI5hqElNtwD30/nblGwDfOHNAaod5MPWAFlY1WMDGFAhdZcAJ6oGw4391aBjDVBdOADaZUxbUHEO8EIP4LW06TmDNIDtFsDODj2BTVJzDFCIYULtwc6+NcA6+tYASdgqTFugqUWnAGM6e8fkFnaurEP4LxC2HMM0bD2RI1qmax+gzkyjbZIebGXpdehVSQfSAfMOyLAXoc0vMpu2AXpk+n6Dfm51zpsa8AjDKDxffwgHdWmDfsOIXYAx7dAx6cJBVjRdinUYtPmbkQ5Hz/QnV5dcWANsMg16EtpwlKA3Q1r/F801+j9COBzIw0WTfrk2ubcEKDKXMFyqMbhI8CJNUOXFX6DkfDgQNgQCyRBcRabzXY+VzQEG9A7YkG7gpr8virxBFB+GeKUd6mwike7DQ72sTta/ldrzf9HskCYMWKM5XIR2z3/+/HI1xFLqtemEX9boazrwm9NnhX78gR2XN1wVIgr+qqONoqtGW8bHdh0ruCoXZfxV3d6Jq7WKjI+tSRhXUlnBX7XTHLi7/q89u1txFIbiAH6EzZV0xd6shNJHKM1VIFoBd6BXuYshn+//GluWma5qN1od4sD09wDJnyTnHEF45OXl5eXp/nw6IkIQPsAn2BX+8nZxWf7E9oUx7MYwlMJaieZUa005b+Yuhg2zyV+WsRzWqbgW76iYt9jR2OSOmXUJ3qj4h9ITTMuNTTos28FynosuWsG0liU9rIDFzlz08T1MqY1NeixbXguSij5dwRTEkgGDYaGd0GKAlzAhux/A+jsouRjiCMLSdhxgDwsdHwQgXz0APAhAYl4BEDYK8DPqI8SjMlzRC9WCMkztIADLPrMRkTmjyA4PYLlmQSuGopvAmt+BsY1Y0zAUSlj1h9EBZib4GMeh/U/GeXnj3TUQ4XIfx5rrA8yDrWH2hpmkhv85OqneSRcolPbjg4Q2MFuKSXtTnCGwv+pwvwLFiNSlqnyWw1PS8K/c3EvV5UqIy0jVI68QVe7VgK8hJjQOkEFMTCq16R1cxwGa9FsFMFtfAfGjAC3EVI6rAMOmr1A2EFfpVI/DEBnqDyMC0f3ojuMCNlArJ6VSUjqJYRs1MUpd92dY4Q9//EnbIq9ZogAAAABJRU5ErkJggg=="},{"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":"Soskut_Pusztazamor_Tarnok_Diosd_orto_2017","name":"Sóskút, Pusztazámor, Tárnok, Diósd ortophoto 2017","type":"tms","template":"http://adam.openstreetmap.hu/mapproxy/tiles/1.0.0/Soskut-Tarnok-Pusztazamor-Diosd/mercator/{zoom}/{x}/{y}.png","startDate":"2017-03-01T00:00:00.000Z","polygon":[[[18.79273330201,47.37078533804],[18.791936169,47.37048036201],[18.79139114593,47.37063268281],[18.7901097,47.3717614],[18.7891647,47.3734529],[18.78721506824,47.37566027041],[18.7860339,47.37764910001],[18.7849824,47.3790513],[18.783695,47.3803226],[18.782665,47.3819499],[18.781399,47.3836789],[18.7793426,47.3871257],[18.776657,47.3893959],[18.764716,47.396699],[18.7616966,47.3996569],[18.7563102,47.4032821],[18.7583737,47.4065272],[18.75879657883,47.40776342073],[18.76199554897,47.41217224817],[18.7630394973,47.41315137445],[18.7659298,47.4147108],[18.7704058,47.4176575],[18.77247285488,47.41808545272],[18.7724806,47.4202978],[18.8086021,47.4404108],[18.8174212,47.435389],[18.8209188,47.4357228],[18.8280427,47.4375516],[18.8302099,47.4352584],[18.8358533,47.4375371],[18.8404882,47.4334586],[18.847655,47.4357228],[18.8510024,47.4328054],[18.8689996,47.4396086],[18.87361350924,47.43597176329],[18.87499181607,47.43342149293],[18.87386045593,47.43248349864],[18.8760377,47.4279677],[18.8605023,47.4230028],[18.8662101,47.4179794],[18.8724328,47.4108645],[18.8662959,47.4077278],[18.8696433,47.4047072],[18.86776892261,47.40207457802],[18.86509430105,47.40052438512],[18.87081279074,47.3983820654],[18.86772375423,47.39699336542],[18.86992005424,47.39655168559],[18.87648610191,47.39477958954],[18.87748924808,47.39494663392],[18.87866942005,47.39462343887],[18.88358322696,47.3899604942],[18.88290731029,47.3896699544],[18.88538567142,47.38530440107],[18.87747851924,47.38339390377],[18.88181296901,47.37604910406],[18.87914148883,47.37392756692],[18.88638345317,47.36922645965],[18.88205973224,47.36772957402],[18.87973157482,47.36640704749],[18.8746997507,47.36252284243],[18.87282220439,47.36136733615],[18.87027947025,47.36062605465],[18.86687842922,47.3585329683],[18.86234013156,47.35637438604],[18.85566679554,47.35199153827],[18.84873596744,47.34728120653],[18.83192388134,47.3384118486],[18.82497159557,47.34257772442],[18.81619540767,47.34925116493],[18.8107880743,47.35356882392],[18.80823461132,47.35599644336],[18.80645362453,47.35854023611],[18.80707589702,47.359019909],[18.80634633617,47.36021180457],[18.80465118007,47.36175250772],[18.80381433086,47.36335130305],[18.80054616504,47.36544732015],[18.79988097721,47.36617355102],[18.79416204336,47.36974865444],[18.79273330201,47.37078533804]],[[18.91871480064,47.4093812629],[18.91826418952,47.40997664498],[18.9206674488,47.41155945729],[18.92509845809,47.41372304121],[18.93473295288,47.41916790937],[18.94063381271,47.42241278301],[18.94981769638,47.41937843296],[18.95154503898,47.41749820965],[18.95689872818,47.41922598493],[18.95770339088,47.41877589767],[18.95755318717,47.41435467478],[18.9621129425,47.40506817222],[18.96266011314,47.40117592194],[18.96316436843,47.39903360927],[18.95446328239,47.3967314338],[18.95275739746,47.39526437993],[18.95201710777,47.39362297422],[18.95119098739,47.39356487042],[18.94692091064,47.39798783856],[18.94410995559,47.3984526281],[18.94161013679,47.39868502134],[18.93735078887,47.39633199249],[18.93617061691,47.39682584676],[18.93122462348,47.39999947627],[18.93120316581,47.40023186269],[18.92923978881,47.40204734624],[18.92561344223,47.40604845111],[18.92465857582,47.40635342305],[18.92293123321,47.40925782918],[18.91871480064,47.4093812629]]],"terms_url":"http://fototerkep.hu/","terms_text":"Fototerkep.hu","best":true},{"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","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-Orthofoto-2014-2015","name":"South Tyrol Orthofoto 2014/2015","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_2015_EPSG3857&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","endDate":"2015-11-01T00:00:00.000Z","startDate":"2014-07-01T00:00:00.000Z","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 4.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","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","description":"Topographical basemap of South Tyrol"},{"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","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","endDate":"2009-01-01T00:00:00.000Z","startDate":"2007-01-01T00:00:00.000Z","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 orthophoto 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","best":true},{"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}","startDate":"2012-01-01T00:00:00.000Z","scaleExtent":[0,20],"polygon":[[[-99.9985439,34.5601834],[-95.55654502453,33.99257450647],[-93.89679027134,33.61039304449],[-93.98468089634,32.04103124103],[-93.41613841587,31.02505269211],[-93.74531484297,29.57268254375],[-96.50492070332,28.23158511753],[-97.36942054453,26.95467452634],[-97.04866958924,25.80530249434],[-99.0734177889,26.32559221139],[-100.76599193149,29.02531904433],[-102.3315436893,29.8433892263],[-103.13354564242,28.88112103669],[-104.2887874222,29.28831477845],[-104.7269783935,29.94815782859],[-104.72696778796,30.23535241761],[-106.53450082091,31.78456647831],[-106.75767043939,31.78457253947],[-106.75766067978,32.04385536686],[-106.61848436611,32.04385159755],[-103.11949492759,32.04375683439],[-103.09544343487,36.50045758762],[-103.05798056071,36.54268645422],[-100.00042146824,36.54222227302],[-99.9985439,34.5601834]]],"terms_url":"https://tnris.org/maps-and-data/online-mapping-services/"},{"id":"tf-landscape","name":"Thunderforest Landscape","type":"tms","template":"https://{switch:a,b,c}.tile.thunderforest.com/landscape/{zoom}/{x}/{y}.png","scaleExtent":[0,22],"terms_url":"http://www.thunderforest.com/terms/","terms_text":"Maps © Thunderforest, Data © OpenStreetMap contributors"},{"id":"lu.geoportail.opendata.topo","name":"Topographical Map geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/topo/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","endDate":"2010-07-20T00:00:00.000Z","startDate":"2013-07-19T00:00:00.000Z","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","icon":"https://www.geoportail.lu/static/img/lion.png"},{"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}","endDate":"2011-01-01T00:00:00.000Z","startDate":"2008-01-01T00:00:00.000Z","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}","endDate":"2013-01-01T00:00:00.000Z","startDate":"2013-01-01T00:00:00.000Z","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":"https://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]]],"icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAA2CAYAAACCwNb3AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAcppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGFpbnQuTkVUIHYzLjMwPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgofPyfmAABAAElEQVR4AeW9B4AURfY/Xt3TEzdHYMk5I7KICKILhwE8DCe7eieiomRByRmGjKCAIHhgjl+PNUc4UVZEggKSdsmwsMuyOU0O3f3/vJqZZcPMgnfeHf5/BbMz3V3hVdVL9erVa6HNhEciCxS7VtBJKvsDJlWUxCjFa8tdk+6oD/zU1ZOMhyttYXYmK1EhMlbgfnudQWgd161y8+jRnhDZgt6+ZdIkY0nU71N/ijlFyjBneAMNTX/3lSZH8k51u1RR0i3KFHZTvrUy9qy13NWvVbtebkWJ0agq0yusdH9+zv5u0Ym4YgfCw0wHY6Lj93zw5Iw8fz2C2WymjxKo91q/U8xmwGOugufhDUuaFpcV9XJ53T0kSUo+VFooJIaHxSXGxifbnE4lwWASL5cUHRA1YmmEVn/Crsjfx2gjD26f+dzFQJu16wzcv4ZvAWU1AXhUVRWGvrSwvdNj73uxorhNpGTofryiSDIJGm2HpOZ9y1wOKdxoYnar9ezlyuKzbSITbSqTf0mMitvfuVW7febBwyp5mykpEtuxQ2aCUIMOhEaTH/qkQHEOEgShHE801wDg9ZNFELwiY4lhXmFWxbqPVzIgFquGWARoYCJ6zRsz/YS9eLmLqYUCE6SanVDQcZHZFK/S0RQZ0a998p2bhz+zK3XLFk16WppcM2+tK3+bzab9dXqx4lmuoH7G6yc8BHQ8+euXPUq3sNiI/sm33vniX54MVr/AUlNFlp4uY+LFQatn/i2nrDDV7XGnWEQlslRRmFslcFSmEUQmW0DSCtEDkkYjaMIjQP4K00sSixAEZnSzypjwyB/ijNEv7pix8jvKVpv46F49qQY8dzw3+eFiS8UTZV5H3wqmGB3AFpfHwzSihsn4ZjYrANMIzOtVWUSEwACHiH9hBItXsbUMiz5q0Bs3Z8x68U3gG8Etms1mhs81EW31+Xj2/15u8ePJQ0MdLucjFtndzY4JLGcKk71eJogiU1VUSeMjAEhZVpnBIIh6I3IoLAxwxSoahju5kTrjBze37v76xuHjj9M4ABaCqQoeSRZZnKLX6ZnL24CJAo29L+HndZcCsAUAAzKoJgNTLe5wfivPUgdqS14ev2cTvOF2o1b02uwNGQawdhIxcEzxMlmnZS7Fq6/9POS1v02rIKN+CVTmRP0BMK7QFq9f9TJFr2Gq7KlbPzghZhP/0+XUF+c/0Hn248suM1eHMsDE3G7MiwAABUUEshHXlAVZNRjCNRgS0Dv+qEx1uj2YTgFI62Iuqk9kkTkO75A4Z+WQ3gvHfZPcptPYDY88fSGllkQI2jcqj7aIWAmeboDnEuAplQGLB/3i8DBFgzyyCiIBxmvDIjWEWVoUdCqKrLhloKnMLCB2C+ik0F7SO8yl7d1yxrBpf14zd/6Xk5Z8CGRk1RE/KCy4mboltYpZ3WoeN/Orw7tm54tyhMXtBAFgFDAk6LpK40NEIAJ+ozFSQ2oApgMPMbser0Izb0MZG7IC6CaS4J5qObFv8i2Lx5n3zNu4mIgjNRVtod8EC8ZTcDMvuqUyD2c/CrCOPsSKrrdPADb/N6bPrQHsXoFh1pCSImqTEItISuL38Ac4RdOH/tII1voncJYjYAyIO0uU8dqSv01JEWWR1w9YatVN17x+jLEqY9xFQvZqyYeMKk1wj/mjVu68fPrjLE9lhzK73Su4vV5R0CjAP8J9AKZKQF2S9JJTVQQXUNCFqaLfdI+eUz4BhVBEofIlDoey11Yw6LvMX44OXD+vawbUJSKSahDU/AkuCrygcVP7LRy7cmfB6Y+PeiwdSh12r+hRILUFFXjI4ZH97eFbAxgg4RRmg5Sja9As2uDwiETAohe6sNPpzVbtHQ8VZ6cPWDZpM4idIz4RSU0grlz5iCNdNn/9bpOOsx//6ainbPlppyXCYnd60EMZRKFidDSB8aE2MRoamx8eECvzKIpI8ND4YCwlEWJGVETF63B7TtnKxJ/txYtuXTx+16a8/SYiDhAK56KiqoCSiFOAygHSH+OjchkAWAXZi5HHyISUIIFhJlGPAaREncVFrQ/q5GPgyxMo9tu+r1a/jyHVrRMzRjdbTRu2MdNbOa3Abge5qSAMkRaGErQoTO5vSxy7feWADCAXj+w+4ayIyL6UvWfEO2vbE5EQ4gWpVWBmM2+uzYxhG391l00rsNkUjax4UQ1xDvpw6glSNuQtVEhcAcQrSBr0Ldda6f3eljdyyJrZu8+rqoFU2QBSVq8kQBxzvtjS+Lv9Px077i7vU2FzeCTONJgWCE9S6zfBQ51DGXw4zmslUaPKDrd7l62g73tvvfVPah+wUBbQXSCBewV+Xu/fYAHgCYpXlURje8HA+sY32U0wpw5sRZ2qJ/072F9PtVWPfnv9yaNGaVFc6b1o/OwigzLW5XC4RfB+dIS4YNBEtykLvmX6gMNx1SFoZtykjJhcHRiJ+4xiDTt5/uR7lDc9jasRVF31RDih3r746XVnRPdYq9XhAa8lFSWkFYeLs2rw0PxcQazqVft+Q0hLQEqJWR2ub0rO9Rr13OS36AmQ0pfhyl/BDyP7cu/WLT9WXI4CIC6wE60XyB0KYYn7EQw0NvTxDeeVSmv/ghILDsJ0zOlxHbQW9U1Z9sxMypMCY8CVfpCAv84TAQiAsQT0irHGMKlnWMLOlHY9222d9+LnGF0xMJjXeTeqgZelObB5s2fYaytuyLWVLbVUWsHSBHDF0HMBJIdAgaKmyiIYhEbVajRQHkRonRwhqlVe5yfK6Zhbdp/3WJL/+tKSxygDIUEgI36T2iU//PKSBy54LROY3eEFonGJEchT+5sQELCAW3lFgoVggiYlKqqCZTDRVfAEBGfIqpdtDvdhW3HavS/MHoacih8GXigA213PTZ+RLTj7QP11oz19KMLw4wcWBjLDarIKHhLG0A5kiJlQRblE0Yii1upwsNPlhdOe/eSN6AxI2dB6aPB+/c/ukjLrRSdVrSS1l6K8rWIbzPxm6soX9hNEWFQxsznkZPzPgL5Kw+lZmTzHpYL853NVF1mDvNDdSaIETdBPyIwgJphMrLFoLHeJ4gmnwJwGr9zIpnrbX3TbgZIYI6gdwSog8QrVRJPnsLELxbljcPkWkKBK6hJCULn9F08ty3ZZAI8kAJEJ7+okugkVX1Z1oqa9IYpFSYZLxbLnrB4EHmEQOhaqzuhsu4X0GBkaJBkT6iQiEp0gSYXWCnZe0ax87cSJz57s0AFrelriMJYBK+XML9+L2fLj19MrXDbAI0qygppqQRTQr/AE+CFqWmjDWEPJdKlYkc/qYTvQKkrHE15rtBPGDqjaCqmstesg4GA6BCEJHouWxR7OPDwCt1Zf9wTCRRwZDmVFig8Ll9rronZ1btd95Oa/jT5BnRq1aZQ26XKSbE5Pp8s/VjKnu4dvfqHdj2cPDmQON1iqJjRxQGUgztwjIrG8fVKLme2bdP/IPGRIMXV4h6pKmzetGCiez1ybrdrai2ReCWGy53q3W2aXHRW9xr2zoc3GR8efMUP6ZkA4E4H0mDd6WKantAMQ2wOWGxQejp/YTGBaQXNrRMN9PVp0WnRrcv+daZ07WwmeV7Zvb7Dn3C99ThfmLdxrKejqcblBJCwokcCiAQOf4AGDaPRO+ktpKP5a/4ULNSn4kQFt4fDpQ8PKtUoscwIeFfDUIg5k4wnEoej1Ok0PU/zOlo2bzRvcJeXQsN69+R7H6q1bY7cf3fH40aILz+W4HbQmA20HrwmcRayElatMqHwQFfsIhNokkiUqp8/1kgJSA7JY6qCPltvEN5n15eRlq34CgKS7D/lrkmrub/Zt6AUsQfUC/5/u3W+v/1LZpbuLNaThk/SAhTRIIh3aq8hi1/D40sE33d5zyb3Dz1fLJvQHp8X11nFbNqTsPPLz6WPW0nDsitCOSR10AoSwP4leu8Sky2X5t6HcmQw/cVCdHtU93eXlZlsxlEhGHV4Rmy3Jxrivds3f+OddKLeOCvvaU0cOHFiA35/Qp8u8EVuOqRWpqkcmGIMyZEgGsczlZOWSnbj2ayBUhaX6YL9YVDiwFGZrvi4LNbywNGNRpmkhmf6xZ8HGh/egkvfxQaL+q5PvvrsU36v/vHZ2sT3/3FslDrsCI1ZQgqXRYW4vc0ieHpM/fb2pCAEKoSzTfhN2d1RYKtB5iPI6I0vN/ZcStc23m2A4iQsPl26LarL7js59uhFxEAijNm3SHkg6RcThXfPrjugR61bcAAoH+MHVgf8S2GjmGkat1iTLLvdtFtlDa6ughekmdhOUOKhVLWOT5hBxtDA/biCu72+Q97vJpFTjxrTx+S1ik9ZqDUZSF4Lit695US2DmeNs8eVmNDbG2BKukt29fOZNpR5nV5j98TS4moaMqEKR2jJ95Z9vuYsQGnsUZh2pRfhJ1dNuvTho3QS+1zPqnqFPddSGV0Ifk3xlqUTNhA5AiiisyGG/cdimpY3wVGHpTF51eFsYiLkP9AcMTjWDUrXiGAQY6BVNG63JPbB///H0KNVcAx5mVvlYSV8+u+ztFrqwnxnUMN/WSLWK/D99kkWQKwXFcPLsmTaiVhCiI8LDWJTRqDcYjRLp+DDaY59FhewTvFho1ZrSupX+nncg/kCrEKeiIHU0xSm3xbecuXPu+r7rh43JIqlh3mGWuBsIdswnvb2+Z/rnW07+cPEILfBY8ujRQTnUFfiC4uCVx/+1X1fALHDbmnOFiMvwugAAYiIAKRrbHs0aNfyccjzOWriBhJhLv8AHc7jlFt9eUKwx8uNGfPtBqWaBqVkvYQd251miKbwjPfnm4Bd8YByCc+glEYxegCG2ZpGqKzzwag0G1jKu4Wvmu/5S2NmcqktPM7uxzggUUQm2byaud9Gzib0HV0YbIzYzgx5snv7XTT6kZF6HRjWWlFfcHMhx+Kefm5TarTGcJEMxP5IeOokl6iP+uWHgYyUshUnp5hrwMLNgVoA7vI/Nw+K+MWFfHAyAxq9O4p3ARnIxNkTPFeVqxJYxCa8PiG258e5mXV9INias6qgJ/6CjIfJiQ/jTKFBtZOw0wJ6GvTj/ZNSp8ve5QdDjQ7wLi9Bw7W3RTffendy32yfPLnmOWiDCOHDKJzWIWw1dM3fZtuO//LLbXZJ41mUnNypGUoW+r+uETmKfkLqLPn0RD4W4DXFIrA5JItRJWhp94EDTsJiKOwbegVUvYwsWLKjTz/TULXzCW7VsfSFaZ6gAvRHL5WzdP7ZcRPGGaaihKlR63MStGXszmyOuxW4Dt5ZDwsIBVGVNM1HPGic2+YiKduqUGhTp6VkCK/IhocC2x3DvHp+ptDY8PpgE1QmI7R7XjVSWUqGlvJlghHWa1jscPfjtGn+wZlc1ko5l2yy/0IPkdj5CqJEJF60GlnFYPFpxN8QSRkbl/hTBYVHVaK2O9WzV8SZp9+z1L9eubMOOHeGf/rqtTwerdVShtvLBLNkmwRUFLEmEiST4RNau47dck+kSSp7CtDqpoSxYbghLmLdtzpoXd6ISkhqtBg5UzP3TSIdlE7as63X7kgmvHnaWdK2wV3r0hjCtEXtP5b+lwesk78nLeczicQFryD2i/kRbfY3j24dERtTBicZ8d1pph1mPncL1TbASkYcBV5+q187VL1XQFNtt8NPgyUPqzKtb3msDoy2KYlfA7+JVvRzNE0hbjBT1l4Y9dv+B1x6fxNJTU0OCnsJSlAwstVtFJOWcLy30YIqx5Q3vD/ytqpegpiswYbvi1f5QcM4VeJZVVuAppi6AcOpwhECmQHHsi9OtgOdEtcf+n6n4TmftW7TzZlcUsSK53KtIZDEOUrOqeuxeWSorq9BLJAYzs4tE9mYGLXb5BIzv35+sEbSj+M9Rb6+92XQua062UDmk2GmHSijC2hp60whlri0BLr9hwItFkBRpNIpNmWFr1+ZtR30wfm4OVZICuzwGWD2QtpnDdf+auQt2HP3VfMyONZfMPEbRoDqAFxoRmiClIL5Y/P51+kfr8cCRgSboCr7UBhXrDzwUWYndEvvl1+mReG6vnSdwHdh1LrDZ5YjYKKY4XXpy3KudYMORnGDMsaIp6pz/4eG9+9s7ZW9DqHtggcH1fWCgQlt8UcawrP5CSyIu0EzovQ7zArPKzIyVll7OpU6YwsM0vt29uv3FxolUqZfYPbFN+37lhwlrC0g6/0WIL/RO8GIN1zYirttl5MnIMAfN2TkrSyU7p+xwZju8biZEROrDMa5ByANbRbIUGxnGEqIidFImTI1UI9QWcep7mzpl5meHaXUaTaw+qqilLuGSefgT+/D43j+vmzv0QkHeO0edZQb4FcENglwgqOS/lrA5S3tbCqzUUhuN0ZNgjHp69/yXNtPOQDJMt61iBip+T1p15JurO2deOPvmpwWnejJs5EgaiXQSER1VI/SRLNotlnOsCeKL9a9B9x8sVW3M4JKtMYq+tWsoTABnAIoI3suy0/TrmaMDANn7PTfztZbPelcNVJ+aJbBBbbq+ZxO9hyEGHGguCIUAqWUlXK8z7uT7SKijwFYebyfsBcLj75VFUrX6AQtOF8CZk6kH+G1zCtxSMqrlqPXTj9w3J9/pjck5+LzV6w6DixgEGCRILajgOgDlmpliJOPeQC1hBqNY7oF/F19ehaQUDbwzWaFUOYg299Y+8EQ51kA1PHKpPtzjI7/m0w25D/T7y7LOTIgig5RaXZoFGobjI9xOw+Ni476Q0jYt7X+5KO+xtnOHJ+tVsVO54hG14DqwbFX8qjMU9l024ecoKfyDLycu+XDjkR+/e/3Dd77b7yi+UXV7PXzjhtTKkLAHWrzyzRUBAIbdGikcA9CM6bcP7N570rqHxx5DLhFOa0JR1kY1fbRPavRbOnHCP7N+eeECc2NmvF6dRivCIQ6dVaRWkdGsbXiDtU927vViGvsHRiGDS5orrV2HvzBWWHLwdHO/uyt/PLWvCEgZidUC+lRN9fCDTrNKfodFLuzwFufM26+q6T0FwROQFv5svi+fmiW8P3H+SzXu13NBKizt5oczqYeH89N6fI4g7eJFibWIiLOSKTUF/yDh66ndx6CxX0P8a2Z9Gas/C7jkd4lvarPmnYTnLVc2gnJ7SDVohKL3hNcerj/00wzUM+vdkn1kLq9S1fx1cwJh6ZnuT9Iz51Rvr77f0i/ZJ5df0Mk3K9hdhTM9VQKbGlZUWimKuZ1RTHC2jWKlj7SfOfzEt//8buT+RZt79F487h8XvZa0vLJyGdwc2g55btafiIZASVho4D9O2TRmOkfTsPgpe+etfzmLveWXGmUkNUiXVB9at7j1iaLzmw/biwZUum1ctQNBCm7sBxhNRrGLLvJs15btR77+2JQd26hp4kpXLCl057pNosYne59o2dLZc9HYo8xjaa14sLdHDpNBEje5Kqr3nNveYeayKaQp3E9uNVwF9e9+VyumEvGc2x4jhtbHcVQCxwBo4VqU5fN2/i7/vNbJFVUSI6FmUxXhjsysLvtBai+hU2aojNXA8f0kWKnN+mDKwPNUrDexrpFhemK9OnY6fvzyubI8puJQmIA9iBCsmPxVXV52Xq2Y2X3+qIOHFm1OB+1K5hSzAslB+FQjEQFa8trVCwvBOiQpSZZK3A6rip1VLHHsilZnitPpJZOXlUZodBcahkcVV7isF42SvvsFe2nDS56SH/ssHL9+97wND/35hZn5Lpd7YokHqijWAzjAQ6ZhLqQDfJATBawMWPPBWwfre0HRRhtNYpKo294uvuXITyeZswG5iMETMy5jrTHaJwFSVkwcvzc3a/UFwaNDx2F4kDRwV1YVDXbT4U6UHNVk7UvTV81sKwguNipZyzbtJ6K+5smqMVr/44sG+oi9Ea6y+y0uaDb1SGLghuR0ueTtpefu67vw6S3PjJjxWFrTpo5giOD3SbuqND2wGZ1PSefqVK+Yhk22l+fysxN1MArZCDTMLzOCITpNOv86KBV3iV6vnjLqEnLQQumbCSiexJl3pFXcMO/Jg2Cof1Khc+BuHYODPy9QTFQqvR4x2162ZfDKaU9/PX3VBjPWI34JSTK7Cj8y+KG6DH/R0F+kR4pGYmfovU6vM7XWhh3pG9vs2ZQuPTpmLX+rx/dz1t15YNHrT+2a/3LPnOf/0aR1XEIXtOKcuOkF85dTVjzTPizhTzeYYs4nhIdpZQ3cjqHPYQwhJEio0F4VllmgDxCHGGnSa1vrwktuDEscn7X0rTuIOAh4UqkweOAYGd5H317Vsvu8kd8eqix66YLHphPdMihE1Higk5hMBm1yWMLJGxu2uHHbjOcnEXGQmwkrgwfvdUMcVXMQetRrZenYqPFXTRRoBIoXi5HQFELFyKcJ29vyT47C1FWbF2U++eoLf4KG4+Vckk42htorCA0NVrU+xDHpjB3JggUOFxQILtowuZGilrU2RIZC1Ppa+k3PiGlSAb3W8EGEXgeEAlaFSIS/tHdHG9zlXhc7UJn3Um/z6A9mbX8rjtRHFFNRX9B1VYgqq25LDqZGNtaHsWbayAV7zBsWna16xAdKYljNsEzfJtT/jZpPa+jpw7ZsCB+1aUXU5tEzv9+Wn991yRsr/tpEY32yzGnvbmFeg42GGDMaBmNIGCY0wRBxLjLC9O7tbZL/bv7LcBxJZQIAxiBnqOl+C9WdK6eN3Z15ZM1Z1a7HVr8Hbj4i7II43SSL7SJjWfuoRi+Pnbpi0mAQBhEWierNo7lzXQDl/K1e6cB//1dQ3KoJRrUsgyZM0D8//JljtywY8yFTHEMVl0Im0KDuJlQJ7ygdlsLRwV/chS0rsj3b+5jHru/TqtuS54ePLSS1hBAh4xq5NQfMLwTyLGXw5MOGNqFi0OQbXnj3gpmaAmMeNOfvcRN94IAM7nD723n7P55nEYVmIF5iuJxwgrVBzyBJ1AKrRS4yeh4q2Lat/4DlExd8N/PFTWAuJEWwxk2tcqEPVkfte1JnQ/SeyPCoWdtmrNxBD8nsa2gUA3WHU54HxMGwMNQ+vH6i2KTUIjRt1VkzPm08d0qj/Hc1bGjD16v0eeL1F5rm5l+68bylNAq2W2+rqDhvUmzMkXfGzj1LAFID5AZQBIL3D4A6/r2Xmu8/dXTzLxW5d5ZhrQFB5KFVlwdrDZPJKNxgiM7u1qrjqE2PPvvtF9Oe4wiAatQAEvQyjx5ThrPHp1/44O/cq9d/VBJ5rvsU3i9OZesZ69C8zYKi07ahZ9RyrQYjgEMM1cioZjf8RKKVVFE+VVEinjLpJ1hP7XtyyJqZyx59dvmKNB8iCECE3+T+X+ay+4REzeaqrgIAgUszA/uXmHFVXdf4g3N9c1qa+5aF4xYVOYteddnh9EgUUE8FEDOURVIdHs95wZnocAovd5r72JN3rZw5b9v0FVuhfgIJmcbcGQ4oQdYntauW9izeNInfhIhO7TQOHJ1vyCk7zp83rP1403155cUDxywa3T+3olS4ALNsg2MHNL0WjKqINoXtjo+I/eT9cfO2+yvVvDFiSg5+04enbP/3u+PmCeQ/FNdIJ6ePNnOzMj26Z83MUd9m7nvxlGw3wFTn1SFCCYIS0FxoEnRGlhzXbMP8KSun9REErmunpJhZRiYWhiCCOV+81XjfsV83HXCX3lMhO5fzpmLO0SSHYoE8y/X1pxNUS7P0xoipWXesmjolX/C8YLU5vHBO1F6tE9gE1GgkEBPU0CPuUlOmbFuSPWfEiLSXFi3d8vT81/k6JCUFC9WUoAvVK+PgEyFwhvSLqCtP6v7CBhi0AoPBRyB+4VM32+90hzNBMxPhgPhaz3kj0341Vtwpk886HW6qJ3FdDJIY/otKfrlVzteKPa2Vl77pYR71TZQhZtqOmc9hd8PMGKmlCzL4WfZQ1VFPObcpyuqME2a+CB7DXl7+4PS3lq3K8dpb5sOTEvv/IEuYfoG6uR4Hy1UdQEND94YVheNaz3jkwI3N2i77cLz5Y2pk5OZVD2c7Cg98+8yq09UaVbPNbzqzcWMLDu289vy0O3LKC6fvK7pwW7EDm4+QGhKOCUOzwqLIIPUNS8xp3bTF8DefmJaxdeoq7tJ+6nJSldS4dcnEB9L3fPfqKa89FuCzSFjEuF/zH2EfpNqg8J8+dUj8dtrzq29bMrHPLjX/QdnhcsMnTcdtXQHWXbscroHSeEqIICmywysf1ZS3ys8/8doN80c80alhm7n/N272D+aMjGtSu7Bg5LUFaYbf4mAgCzaKoePVI0Fo7ZCZWQ/UoVrw3Td37lyDs5uZ798dXe8YVrb/i1/O6rzNNR4VuyOqtj5JQrWhT3QYEschVTmnsoLl6G2Dmjosg25fOuHNbm1vnL4+bUQRqvcHhPAFafBBceWvBDEjcGpKT+eesVu3f7Pup0vHHz1vh/OGLHi02PsENKBHURuF8C4NdAa3Tqu7iGNblXbVo4nQSD1OluR9NHDZM1+2a9Pur0qlO8dl83zUY8EoS5Sg2WbXas7FR0brC4sKaQvjxkXzRtxazjwdc3G4B34/Xh1UCjc6gnMBmg7RcayhKfr5V2asmUuLcFprkJvJZh/hKrTo+ipj55oTtuJHi5028liwa416k12mg2Z/3ARjBk4ICWzn3HVDsbj8PEuqHFJpteE0G05Q1Yu2vj5jt500H5hbBLnIalOKdK5biy4ey+i9ZPwbKd37TFnx50fKSK0Adwpp0OC+v/UtvfkIKwzno5hJbwiVk86zh1xMX8sM+c/1UGsc/4Gf/JTh8rS0oj8tnX2zq+LCz7kaWzOsKMBEmO5qjfmf4ywahggHanJUm5RjcT+e/2vZ0LQX5y/b8syi5fWYzBkRCK9j+N+X3PfuZ+9vOuCqaICzwrIRZ3dcGHEEsdA2NUWwhobIH2D23ZwQ3XDv3U8MvZwmwMSINPOnbYk/HdjXqMBe8UR5acXrI/9y34jPM/akZJ069tkptXJhCaQCKyghxzjf1o0b1wocbMCJsOTSubUia2g0MhgKDndq1PaZd0ZN/6HtzLVVUiMg1R57ZdmT2zJ+WHPEUxkBdUzWI96RCwEt3NiCbaLXm3IJGNi2ySzzR0sgDuKafPd3r3nTvbctfvrVXTrvk16ckQC3plOG9bDsK72l/ShIHg04midPsUn5gvxE5U9bBz+wes7oTyYv/QxmMOCvr50rpa7tF5kkmUarKbBUuAut5eepVBbcN6pKQxUCN1ZaTXlwZoHKegC9wQFDL6iryvl/kJ9XpaKYUlt1OZj+zOIVuE3qMsfNDEhZ8q74bvSygtQNK2/OKTq/e6+jqKUKtRwqH/yPr96On1AomomKmETek4IlvKTo7LIBSyfe36lt14dfSht5nqtcteKqSbM+fitu/5nDz+/KPfn4ORu5/Ekeg06rcXghNySdlGyIq+zStO2Et0bOfNvfF/b6CL5sIS4ij+17F1ml6PPs6i1bjF9+uyNxDWIv4brfk68+f1tW7pkxFcw5yCZqoitxZsapk5heo9HpoB800Ohko1b/U1xY5GvfTF/1Nvdf8G3wMPNobsVQEOol8suff1z//cXjw3Os5RSSB3suGhGxq3CQQW+41ZhwuXPrlp9tYh8wMzZ2zGj4j5iAuLRW4ESyc95LT93/wsyzZ8oLlx2zlUp04g4UIiGCC+fj9fXPhwiQ97QtBX09izkaOMtzP+23ZMKyH+eun1O9nbr1hK6elAjEWRDOuu2Vq1aNJrcnhrquEEhmKgqnMxxxHGqL1CULDuzLExO8xsT1JY0Gu9RqKxQhAqkBDBmNUrBeSx8/PX+Hqnaas3jsO2c05UMLrdhEhusRtttCBpWoDgLGByYQHOpgGqXYavV+77T1unyo8vi9G+c/+Pm4RV8hL8frQBlp+6+73vmV2Qd5Ky0eHRzRPJD2cFoTm4RHiV0iGnwx4OYBo6b3vyefCsICpUlvlKcyn4WLryM3wcIFWzPLcbnEyWlpJFUuBCp/7ampO/F7J4VsuVSc0+d0fk4UNnLcjQzhUuPwuLJ2DRofWfXw6LOB/HQQ6tTly8RNgf2M3bl6zpD3f9y2+bTqaqg6XF69Ros4UAhvBXWsdUQ06xjd5I3RUyY8PURIslOwL5TjMAXq+6N9A354CkLb6i9oPp2yYvnYd9ftMJ469topT0WnChvWajh1CM5MQRSumqCjE4LpcAZdPldRouaHu2YPWD65+/ezVt9D7eDDibFmRVfwveZ9UCcQy4v16A0RCfFpc99rN+eBRw5hDwuWspqRJ+HcVMps8NaSVSdgDaWK1a4ePADTqnoN2KmEJ2rwlAG8IC+B/ohLhxypd6+c9vhlofiVw+4KCYGvEL0E0SYhRYOXrnkXIfywPBF0Gq/gOe4p0dsvyV8O37hkztvj5i7j6igObFEJKctaZvLCUcQAlcopexDkFYsKfYKla6M2z7w1bvYbW9kL1Z0HuQVqxpa3m2XmZD3icrvuenH+iKRchxXAwUQ873FNpNZ4IiI8Ymuflh2/Nj/wRDY1snRI2iV8VW250kXASY4lM23KELMmg2V4A/FwZ3y7JerggT2vZpZeHHrJSctv0aMXtBqXjHPbBkg1Y3Rej2YdR78yYsqXX05dzhehOCTDiQqZ/9CJ1C10wEseAi8Pm7gXBNN10Mpp888qebNPq07ovbKMdSGc2eDeU4PHBu82XK/BVrSqHdFDvpdzB6csfebrjDkvDiYi4RuLaWm+gldh9tDO4KSlyCYj9tJFIYEKBbNiIZPE1Wevl/ZzrglZqS70Gu6nAAIMgK5DJVov+ImbbZ2+6s2ZH723M/zEnjVnbaX35mNdCkqDFVDEfirWZVdJxGiwwajVCpJ8wVIu7C45v/S+tXNLPnt2ySZS6UhqSVhky3YEFHTKLm3DiEjWJTzhq3v63jZy0m0PkhjVpGAR73MD2UxqqHD3qqkrth3NmHpCtotONyxcZP3wi9IyWthLlrZRrvIhRaXFnsHPT3uvS8sb5q18cFjulPdevivfXlnx3sgZVd6aHP4DzJNxwHeufNn2j+P2Hz847ssdX0/K9FTGMI9X1mKMPThgROuNZmGRrH1kwlsjn3jq6bREBAhIYVLquC2qz3fHzKv7/82fzQe4SgGCIcI3j3tn9btJF86vPucoH5Jjo/Nh/LQnnWa/Kpl4oJoBaXSy0+k6oi0e9Kflk5d9N2v1bLawPxA4gYsNEIB/WRx8BGmaaVnghprsUOA++z9MnLjRPhlxVjz4yDn8vO/B9eb7z5fkrTzqKGvr4dFL+Lhdk7SFMqiBe6ByprhArbRY/566aUlm+ui5PHayZCcvKZwN6KpPqOjQoOmU9AmLXtvOXqwuNThnfnjtopt7zB/x+iHZ1km1Yv0lYi1AthOSjdxNhoYPo4x4rBVOh/qrYtX+Klsfz6soSRu6fuHQTs27Hs7c/dkbty8a34BpNf+AC8HppOg4I4hMLrNaYnCm//Z/7PzqT5dke2yx3Y44DdgSod10FQxBpxe6aSPzOzdpNeb9MXM/+3bGmurw+dQqEO/143Ly+2BPBklF9KvzwjTtxkcnn0Gt9963zjywSenltSfcFZ0RmhQaCc7ngC1x/K2nWTLjgtnoSysq5FOKOCv15cXb08fO+56fB4I6gRMOJLfqT5heLwxhdrfPalilEtQsRZIJxAbrSbUNT0gWEo1XJeaaVdV/RW4kFLIUah77aIL5U+T+9J4XZs44W3pp9gmPLRJ+fDIPrH0NahckLTRYrbdQcUsnLpx5B5vj7chrWmokGSJv0IfvfvCuB//ybG8ejUKE1PA7D/qkBiLNLd1bcHJWtgciTIbfuUarBdVp+cFlrhH4OoKR4T+gClIgEgrn6DmkFphckvC1Z89Xz0Ak3pVsfup5l1dYVuq1shOWQkhthZXhAIsVh16YCxJJ0DgwjIicx3TwKGZNEDmxbUTCG08O/NuzPIxLQGrAJR4iUDZ/9UbDvYcyE7cKwhGuMlw3fln1T+41P0V/MsF2Aojw2UTzdpTtAheKMZfUklUnZWc4XHMowNtVTcKQJPD706o5TguLz7+4CvUkY8eML2midXAf8SKuFlA4GLHxe+BBFAe4POCvH6QTWEHpcWCHifAWwsGrqhyqh/xJiUyqbv0uPwJrIOCsRAzlqykrnpvx7aa/h/34y+JKg3fCaUsZ9tkgTXhc4/qbBJFI4ADu0zpnixFznhqH3C+Kt7boOPnHBS/3JeIgvcvvPOgl58GHNiy6CQh9ZJ+tYFa2rVLVyFxs6UAc9XaTBpPy4DyYTo/gecdLCuT91twX+yG85gHzq1MHt+/doYGsec5jd2RX2KzYDoEQQCER0TjC4F/SQGeUmkv6gt7h8R8MaNejz46560YQcXD4xqXSbj93bhyx6flbv96/98KhoouPUtevHrSBcv0xkx8RZEIE6sH3s9b9/b6eKR1vj2i4tQGiTMLED74U+nRfoNeQJBKcEr3FXluPxzYvuxf3udyINYSDrZGtKpCz5jesRGBeAuYVgbK9tEaulbDBR3ewu5kt2Oz5WK6cZF7PGRUfGKpPJUo6B2EN6g/RQq36fuMlEQcxSFK7nrtjdMWBRa9O7JnU9s52hqhTEtatiLZIx06v2jZUUcnpdLIKr2Pq6t1bjNJrY2f/RLBwCrxMLue+g0p9lk1YvDv35FzspmMIFbdGo4H7Awb3NyZEH8f+oFa9VF4h2yLkpZ3mjtCuTHtyIaqZad7/xaIjew/0PF5woV3bqPi2JoMp+uDFcwd6tOhwqVF82+/XwCrGFyxwCUjBgqO6S/zN5vGL/3n2wNxcyBpJ8ZJ9+o8RtKHa+BVlZdXLaKplrfoZQARSu1Y+ODIXDwYNXTt39LGCi38/4ayEoiSA3YS25BCG4AAWy4HX65niy3/DJY+Ugqg2dh8NEImEwCNAi0PCDO/jqAs3LfqRytd89Bh9V6XUVMmTnu6Om/vUykK5YhpzQJSEiP9VVeZf/QFpi60Cj5ksdBlm8f/GzPkW6+aOt+CIRo7WOu5SZbkKAvDFC6vbA94qtCB4bOJMupY1+Xrnz0MkMpvBzYRczjkn+duLi5KPFWW/ftBa3M1ps9ELnOigAm1b/MuJFonQlcVyq022GGUziETIWvK62dyTnzTbiYp3Hq9W+6nA79TOukH9BgjffHxUzsjwwXf/i/OSzxbmvH7IXdLN5bLDumXQGplG4hQSKPdH+b6dAxpiqup04grWVqld9M6MdPVDWF0e2bRid/7JA9vKBU+j+iIrUq1YGsAM5mVFtoqe606f1k9s29Z1oPjiL6JWNxjnu9HOlaYCUPjuCMyBRfqlcgRg4CnoKoQTSqAcvjnqFLuslZIWR0mrPbiGn799bFApCIRgUOg4BNQ6gnV86npzznfOzOWl2LCGeZdi/gStm/qJMkIRwv5UOiz9xfSsoiri6L/kmYV78k/sP+Io6+a0O0lqgJiuvgBEnVdNBBAAE+FnJJ9V7AtwqOUNKjRwxqgoWMa6Ba0AxyMpvhJO4nuf3vJKy9uXPrNx36XT+4+6Ld1cDic24TUKLO6snP37QRsCKBH4DgpP/TeDDnh9RTIQ+A7Pqcmrf8gIUStxh0QgQpsJg/TvjZ55tH+rzilttOEUdoFiYoXsCp1hg64NhwRP84O7PmtJ1eKkOL0bCqWCF+N3cfANbkEsUdUnURlirPRdK9G9K5+YGICCcx2wEwWvuVbpmpdU5Fo+NUv5rzbDTEvShLYS0ieYVwxo1nF+NNR4jA9FwgiZoKpifBAFWfX2kGit8bfNS7tn5Z5/42d7QXebDS7nElRaQf23pEaw1olIMAmiy2b37NPkPX7nc5Oj/zlj9QMDVky596aFY17D+ZGPEsKj9uBo6fksp4PdGRkTVVZp61rutQ/YdvCH4Rc1Xi2kBkUFR9xYbI5gbZpoDGdt9XFlpCemJA1RM5gvnkCw9q/lHhkayKx8LXmr5yGWdfWEajHdsF7z/QEwibWI6j4EngEkAPm9GnUAkzGXWq0olCgLRw9Cz6DvcuSrgWtn1n/jIiL55Gnzqd6Lxj11TnG9objJgy5Inb4GCBAKuCbZ7I4WuHWiS2xjZ0nZRTCbGlX7cgf+whAFWwA5rnamW4G3dwUe+79rVuB/gREd5GCcVGrlDnH57BtrIg7lZ3+Bl/bE4Kg1SYE6c4Ib8C9XI+OMph3fzVo7EqJDxKfGVIBA6Fplo5j2wwmLFicvHH3zAcVzD/kB4m7QJQNwVCPDYKSJ0PaUbl3y9LifL5zYcAaWDZCMb61BC7n/UIK8hfFWoy2ptLh2qMr9nec9+eH3M18YetO8kbkXZfsbZxi8hUsraFfU/ZOlXEch9UsU7E86ET9Kg/NdoqD14ugu0+lYG0OEvY0xcdrWGS9spAHM8KuJQUEn9KtHvvsWoSJzgHMUl5f+Zo3SAGdnpKBNX7kJZRV7RuRgSvfKnY5bj7jKWuG1TGQjD56gDDSTTCwtuX+DA2zzeUw4hfas0xCIBIPE2J55G97qPPexRVleN+LKIpJ5ED8ljkHQsophPTx2+TwflUK7dT+PhYH8fE8wGDSAugIuPjDdc/z4TwTq49INbR+6kCsdt+b1KhDgz1pXePqgo/HWSayBq7KI38g01yEifzfUlCQzmKeZdUxq8Xz+ecs9l9xWKFLBw/7AmwTzIbGLzkpRPF5e9MQZOqiEN3lh3khqhGrE39a//4VFJIX613vwcpZMV9mDPcwjd/6y+JU3zy17W4h0CevaGcLcsUadsViUNSWykwMk0EsYdVpjpM4gtdSFFSXrY1endElu5ScOAqoO0lSH1IAOh8LBqsKQrOWke1rKTL6yQXXs6tUylpnB270hvmkPFUwJ3Cfo+Pluko6psHCNBHs231OoBFMCG1PcuE+vcKvx0eMcP0OM0MTwSPKgbUNlOnXqFLR+PFLJ2Q6zjoA08lcM71oEstXgplS+eiKmHkhNo+Id0UAYVINRCJ7AYwQVOnyUwdSL5zD7+h489793N1/nhFIp4IAqXoCqIKx9rbHh1yoYOliA1ePlpx3gbhSy0YwFCzjTS+7Z+xDOGkFQQqUMabOjakgLRegddLocHA0rKQVnmkPW/7s/ICLBTGjheerOclb26zZ/REG3xq0HvTt6zjPPvP/KsovFF+9xOO39LtrKowvwuq4GEVHaaJ3xAhag27u167ADgZqtXJmCWY9t2nTVoA2t4hsJ53LLKaYT73zwDgmKBpRr0uop/OU3Ph37KkSS7hu1M+UF8fQLa7ag+AVkBFfAe5FdjspThbknqH2OoDAaYY7hN11XHaLlMuQtK8a7MbIunee21fqhSUGBDHbSZb+gMdI5bh6lBvdqJgKQqsZ5f/h7mjgRNUhqdlxbcKYc0Ef7H9fpB6S6KEPquF3ODrtV1cgPstHaCERZs4Xf5wqijS8HaHyoldq10k0ZDKe5MTI+Cw/9a7La2fg1H0r8eqh7ivvzrZ9CXcqPxsE0eudMnXqxVgbfUtQ4nUmQaNr4CAVqCFr9f+amv0kdPCDcR9zOxPILzgN9Fo5b+OLfRprR4uv+D2+8hP/1/dlFXzgaPApHgzdvR8zVa5ggMOpDfJVIfAkDEGxGcVuwwD3/QllRO2oiA//qTT7kUO5fY47+Je9kJ4prC4wOKqi45QRrw0amiNIR9/3Z+slYM8P+hYBXwBKjCJp8BISYtTDcwr2/LTL9WL9pOIPX0ys6MelnRylhVFDMpeawtmHxiD/buXFzdhDXdHio3exHT4OIbyLswK06ayJflEcBUditjd9/86XmyHPCvHChYPbRGy5/j+QbjFvatBf3HbFpSq2kVeM100GrhkkWBILJbEMv2uHnXkIQbGCIvz+zT8L5IWgIcAIJQhzUDM708mPPyISQo//jxBEVG4rQl+WLeCPREVfpgi6zHzvdc+GYBzft3+9XdfxAwhpBrhHUB4aIkGSloOO35i1b6F7QlEKMGinCqM+MxFtNMSoSDUCwzBhEDb1yGd9/mfX16wlkwIC+H3KMkn0RDuFt40q1aBTivMSyA3NRowkgO2IPSyxSMh4fktTTTg8dbtchAZEKMflB4eEVgPhLsHgqtpT2oOsQC2OeFfDyvkIjuJXhveWc/fqe1P5LiyGN1+Vx4A3gVVb1MFF/hHbBOcrVLoFrwAnTiOi9iDXz8ZKcAZTli0Z5dQipZtGMwGXQcQk8DHwjEx+L4akTynASMAcEi0f0ysa6CTdpa14pl12RedkXOlCO1PT0oPNFhEzP9/16qElhZWUsFSUtJljC6l2maPQOj/tQ0MqCFfpP3wMCYSgkuHm5PMecFW3Ouys+XP/JhsNweFz9wJpZt9C5FRioPP5QqcqYj19OTF236HacXPxoy77PJhB8FBCsNpxAcD64bz4x/TT0+CxCALDsegZc9FwQnBG7Dx2ZSXWZM83YK6r5imIsxoWAtyflKagsm0NvJSIVhK6DJVotR2v1LCoi6rvAc63eeDYacaZI+wqVyIXEA4vKZUvpPWiXv9MwxbebXh3hBP/7OJS/vrK0W7a17EZy90WTQeEB4cCipLJYU1jhpEcmFKJtni9WF5YR53vJVV29ww8gHVByIMig02mfSrewsQwX9Jrj489KX8Kg2K4+AiJuHbqbV4r4c/WHkybeGJVNBAKLatCS/CZWdQVwIMipLHiUKkn/cbZUm6nRfG2ryNTT82MXztxXqgMsGFZOYHSzVvLXy8K1xmNBB7BW/v/aJV75RWtMLXRLuQTvCD/mKG2zszRn0vZLp3d//vN35xtPf+hAzLSH9yZNf/jA97/sOrszNzPjsOj4S5bbRtybZYQIXk3uB/Qca4vPyfqFQGBBCYTyYDYlJ4KeHyvNm4wACGlw0nf73TxwHI8jEqlogagvrN/ipz/YZy1qDsswArkER0i+GFQUbQNZ8uD1YB9SO5RwqOknHU0TEL86tvue+v6Cm5GpxXvBa2/xp+emrKC7GT5rHRblgMcHk8r3i/DsRE72y/mw+kGK0JH2oNXiPrR6iUVrTfs7C4IbUhlUythNbTvsivEiGJ8iY0svODrzPuKN58dsxS0HrJg0F8V8rj90pJc8Hoh4fYyKcKsKLpMGr3XnumRQkKh5X6q2hovQGX7G62qIf3CcDWSp/o3BgTu6W71QUTT2kb8v/RNbf8ZlDph6q83XnjXpjmkfvdn3YvHleRVWKxlTeJ+r13Xlt8pM0JQVJu64rgiEAKSRIFcJkDh2lkTFipfFWxAFPdNRHnEJGzdlzHtznuLpccphDS9wO1wqkDkSHq28cyGCNgTeDdGzWYdPuujCIUA9eD1l8ImikDv08tgSBKc4XHD2H7eteHbtpC2bunLQzKR9MPXVzN2xaX9fPLinedSBXZb8h+AsSJEx6hlw+LDptaxpZOzHLzz41AU/ArHnJy/PbKIPzwVq0e5CSKIlkCrsDnVXSc7UWxaPfRMB9rp8rZ7WgzgU+mQiEMbjr6xKgTXwp1/txX1w9loOtuinMaJe005iks7EmkQlfkb3Elhn1JMirfjr2OxYbfg38KCj29Co6iaaH6ynJBzgUg+V5i0euOzZdUu3v98AjIT7x2UQ8UI1RTYO1/gPXupx7+qZY6DQPKa4oL4GMUbUbcV3J8Jg3BpLQW7grhR8ttAIuiTh5brnnFZ2MPvkt/esnTV75idvtOA10Pig9LKdWxIeXDd37PeHf9px1mM3IrQSef8FrRIMEuSoSs2Z3jage999QsKUh74v0sj9/ZPsE4c++K6rvxLUAnSqKtAHNAR6fRwhntZk95qt6z5eyBHPNznBYKe+yX0Wj3t3t6XgERy2h5EodJA2ag97SWAlBrGLFg6zsnwEQZmsOrjdRGh17bJdlZGF8GeiDSdIFDJ2BE2+ejxq5+hEcUCnXt3XPzzmMLn3kAcDIRJUyJe/Ljo/RnDBxwPSM2gluEnrJqhM2JKWhFZaE4LySWdtslxA+Y1MbOiU1FZn8R4hsIqQxEF5dZAsbq9L7B3bpHj+hKmtB8e1rSQVJC09jcfRunet+bb9+ad+wJtwZRy58xlwqGCtBM4KR2xVjQg3io0UbWUDY9SvFYr7V6siu6IlSR+nDbuxyF7RDIH/WuYqTlYJB0BIWcxfcCmLccI5VlXzQPOuOz6ZuHgAmuPz1WbWsENnPNYbcN4YAx3axwwMT4HTK+LDG9gNYhh6JByrVBWLgak6k6jpeEaxhyEQBqQ2XpRbj68aYrZ4FBxd7W2Ie3Wv+eWR9XC9WiPyP76EqkEUzwmYSxlc0Y2gbCAIrBC7dJSX9Wpxw7SKrN1Dsf+ih0U3pGMftYfAU4KMwADH7IUaqGbd+MEwLCaYFXtyOIUGwgDKhiYOIDUoWPHow8J07WKTniPiYCkpEsyRfPFvhpWsSXzT5zuWFIw5rpRCm9AGNTtSdyAR0Bp6ixNLODSlwXv2WmMzqzUXuXQ+H/sEeG0zAtGERiIaKwT/9iZGRunaxCetJOJIgUqEfhDHl+mo6efPmnfetuTpr/KY6x7EbHaj/qAGEOLcdGbVYoOEZ/bIU17r7UzS3q7DNuM5sk/jKAOFMgUDASvD3i7WUqGIg/pXJ01oI0FdklvGN3qlqOTSSxWynWRJyCDpdJ6Dv+DJ6ZIP0wuftNquPoMiTQI24nEaAJoBnVkOKQRADKrX69a20UWpXTp1WkaOstedilVnoH6nGyAOHj5m7aOjL7dNaDw8zmAir28EsRHoBfNBk9/KIUka8F2EUBUgRohD60Ss8viE+wi2TmHUR3vl4FQuptPoeoc12IVXyfFFP/zKuOpC8JDE2/z4xLOtYxqtZGFGrKvx7okQsFAb9AgfmmewdpFWPTiAgLe9QBUFZ8TpwtCTT8QBu78b9kJdB130j+8+vWAV1ZlRzfuAog3SvQG9+o7qKoWDAas6vAKOjpEETaS/gGphmwPrx7gITo/HbXN5ELDBQ9cUGIHGDnSNmAzBJUfQiunm+jNEtMK3U1ZtaC6a9oMh6DDmQdyIr9TgU5ugmmt0FCgaY0MbrwwLKgoJIeClMqH5KbYAEB9b9SThxUM3JDWf/WrahPMpYB7/zxAIDSNHBizYP528bEvzsKhHm0RGwZKIE/kCYixhgK4Mdc1f4DqE7JQP465qwFZD4QyfASAi+LniCQ8z6nuExf3ytznDSWVgZp/J+Eo7/veZfDn9uRm3GhJ2MYNWh/pdYHFX8tQEhV8RYoIYiJY4TIAP9uvQRQAPqaZuvL5Y110fc/yhB1MHU0V+eHid/mswkRTJfOdf82IiYnonavRWnP/Q0viEgolapdcSEHFiCOk95siPw3S4Jq5OY3ctKZAL39Q9nih8Kv24qUWnv7ZkRhvsckRt9RIJ5UebPnhovgBHfeeXiHEAaCjTqhIRYdI1lcI2fPTMUjKGiBlgHv9PEQgNHsMxTbJqHZy/6d1bGnV4uEtYvJsjJikx8CMkXfa3DgrnzlizwHwKIw/eCI5VYKzRpO0Z1vC9d+ZvvnW00JMfDQVCVk0+hwWEEEDS2X+bNLCPMXGXZNDrQV2kTnnAmTlQ/rzX/EXw4AMKIjzBG4NVWYwIN+l6hifu6nfL0BvHd+5v9UeBqQ0PmEiGl8Zn54y1x/u17NI7OSKxGOs8Hb3MFdVymLiZ+JqhCZ6RKqNxJsIjKQ5tjd5hSBKpSqWjnfEUcPHXnpp8pkNis16djNEWhcQ3TmOhLCFvgK6CNxLiLuBH23yeiS68cE7VNDCaNLfFNH5u37xNT/NimEj6Js85qMkYJ+43r0IK/RE+ONgGONEDwE79AAP9DYmHxAenTB8/9x+De/yp9Y2aqNcaSHpZi4BgOJkHDz+qlN7XwieBVDBZDwLAAl3l31joYmowqWgfSEPSWaZhhk4RH2bSdtZFHu+X2PovGbPXDiMzKl+U1wqPEwCXiIaIZDDOZOxesLFfL0P83Jb6CNiltDgKJotQc0gl8xAsvE0IDz3ZwgELfQgeIswqeOh99/QuEQlPSAAABIhJREFUFsyoAkfPCKNR294YVXp7fPMZ+82b+q0fPNhFxJFeT5BvGh8iko+enp85avioNnfEtni1rSlaNtL4oDmMD8AhPBE8/jHwQhVD9wkWvlikBSP/0D16FoAdY4l+0FILwRAUkC7qQi9pgWCQwmFhdHvy+dj43aoywMUJlm+mLs964JYBHfuaEr6J0Rs1IBS8AjAAB/PBgTkhIwSNCW8X3/Sb5g/w0Dhy/Ab8ZMgQFaz66DRmn+jGx3sltkj5asrzpAaT2yn4k09JEBpMfXh/UZiYTO95I/L9IyVSHARYLYxljpWWtR/OYBhIkhDX2gfiTjQBlP+BF8ztLlhynwJtPISXlTYrAc7RC0KxJ4BxwbTjBaY+nkeoh3HSG4ACWMFiP8EEjpSEo9haSfy2QXjMa/+cvhrvg0PCglzdsYMW8yhUfyIiwYcT+rBXV7e5XHBxWrGjckiB19moDIo03j7na5eYGSIucpgIDqIfHWChPUo8o32DCKCpzqtURmr1P7eNa7y13w09XqWX0RAE1dupH6KaMWsnf7y53dEzJ54stVTcU+yyd7Tg2Hk52saaH21DDmCjlCtHBEd1PKLxo6SH6Zhgx3hFYDx1GJFoBbYGrbbEIGnOmzTaIxjLHexSwacZG9OtICggKf76U0q1uRq4fGqKxVU5qcRh718seCNssJB7uOEW40FjQ/yN4OBCAL9xBoT/xj0sZFgcjOp6D7sUExa5Jykq+s2vJj33FW8GTNNvog40y4R2sx59tMLjbo8KsJFDS8s/TsILtIkzhWPBujV3zf/9gNnHxlkdNabeDpkJMVkGymVwQvlaVfVvrF3Y8UxxTle9TroJQVs6ny4rEpITmnaxed0Son+Q/0/5wdLLZzvFNihzOpyHGsfEH+/cqtORVUOfOB1oLKXahAbuXcM3TL8p2HDzwfJFXp7p9Y82984pyE02GAwdL1sqWoAgjE1jEjva3E5IDXQeEF22lJ0oV7zWznFJlYUVJXtjImMPtWrY6Ai8B3zcGA0TF+aS8xqAqJ6FTMAChQfyw0TPiIArKgpvvVRe3DbMaOyxJ/+idHN847Y2xRtd5nLIThAzaSi01xRvCNOEa3Xlh8vyT/dq0EK+WFr4c+voBLsqSQdbN2ha1LB9m7Pm3oO5N261dgkPq4gjcJ/PFbm0+4O6jXn77cQzuYdvvVxZ1DnCFHbDibKimBtiGrSGq3i0TfaQBiCGSTpvZtGlY4mRMSoOph/DnsnJxlHxh3t0v/EwXi1e9RoPf1AMPzUHWgStX/n5B/9VTSz+Kz2pTSi16/i6pCSy4OJFURerEfo06+po6YvuVzubCMIQM6pZhmpnuJbrq8Hy3oULMVZvEcLBMBaeoBMfad4Nv4IkmG1TOiOuGbl6X4MUC1JD1S2CCQTLXV2qblb7cV5VDR/s+sp4/vIlpfDSZaEczxJMBrVHpy7iw7feE2q8AjVwxpDCUsiQQkhahzgCGembq6wb0wVYyTlTq/6M4Nh98agRb9RV7JUaoX2zcIXM2dXzVP2GhE8dx1/5QZI7aJv/H+y6kJy2/hwbAAAAAElFTkSuQmCC"},{"id":"USGS-Scanned_Topographic","name":"USGS Topographic Maps","type":"tms","template":"https://caltopo.s3.amazonaws.com/topo/{zoom}/{x}/{y}.png","scaleExtent":[0,16],"polygon":[[[-55.9959409871,52.00107125754],[-112.02896100663,52.00107125754],[-112.03994733476,56.01308253302],[-120.0049439862,56.00592357111],[-120.01711631014,60.01202439709],[-132.00196823895,60.00239237126],[-132.01208445818,63.00193292546],[-133.96882922149,63.00050478005],[-133.97240257168,63.9922484722],[-141.04429430438,63.98726254018],[-141.06879354491,69.92045693283],[-156.24893170976,71.51583202984],[-160.44570905351,70.83527373985],[-167.08145124101,68.42906280103],[-164.08218366288,67.03913532024],[-169.01504499101,65.68268604273],[-166.57608014726,64.50777504773],[-161.82998639726,64.0500622981],[-165.08193952226,63.26030016403],[-168.02627545976,59.7862264253],[-162.53311139726,59.73089435789],[-162.35733014726,58.55904663221],[-157.83096295976,58.31752983705],[-158.00674420976,57.52404350658],[-168.22402936601,53.51022153947],[-166.55410749101,53.14277307072],[-158.77578717851,54.88541314654],[-158.68240338944,55.7496444805],[-156.55105573319,56.00847621073],[-156.15554792069,56.7746616888],[-154.70535260819,56.14336689443],[-152.07412702226,57.37034511851],[-151.62918073319,58.22653323066],[-152.00820905351,58.98055685754],[-145.98770124101,60.24740887373],[-140.38467389726,59.48634241018],[-136.53945905351,57.80610084736],[-133.79287702226,54.83482554482],[-133.33145124101,53.14277307072],[-131.46377545976,51.69838238021],[-128.52493268632,51.74602265442],[-129.79385358476,50.90159054062],[-124.56436139726,47.49785657441],[-124.03701764726,45.48627362525],[-124.69619733476,42.90428451679],[-124.49844342851,40.3414647251],[-122.80654889726,37.53929308709],[-119.99404889726,33.37084692374],[-117.24746686601,32.54119524801],[-111.13906842851,31.19770451575],[-106.70059186601,31.23528720858],[-103.20693952226,28.64618215851],[-101.84463483476,29.81580068657],[-99.20791608476,26.28743998885],[-96.79092389726,25.75431753335],[-96.92275983476,27.96911213371],[-93.47305280351,29.68226300815],[-88.94668561601,28.87732407469],[-88.61709577226,30.17736083469],[-86.20010358476,30.3671253082],[-84.96963483476,29.43379356715],[-84.09072858476,30.06332630046],[-82.97012311601,28.95425748047],[-82.97012311601,27.26823750278],[-81.25625592851,25.07956298739],[-82.09121686601,24.5610471236],[-80.06973249101,24.76073298597],[-79.85000592851,27.11188091684],[-81.27822858476,30.70777424386],[-78.99307233476,33.20554049136],[-75.03799420976,35.59830000028],[-75.85098249101,37.2425160052],[-73.74160749101,40.4585957587],[-69.89639264726,41.60224497127],[-70.68740827226,43.17628724449],[-66.93008405351,44.69516042167],[-66.53457624101,43.08006996122],[-64.20547467851,43.35229243812],[-59.50332624101,45.73220792131],[-59.51431256913,46.24761804024],[-60.00320417069,46.25901313529],[-59.99221784257,47.24505773341],[-59.00894147538,47.23759898478],[-58.99795514726,47.50266941922],[-56.51504499101,47.50266941922],[-56.52603131913,46.74770404019],[-53.99917585038,46.74770404019],[-53.97720319413,46.48358117386],[-52.49404889726,46.46354265729],[-52.50503522538,48.75360583388],[-52.99667340898,48.75451123442],[-53.01315290116,49.99551104004],[-55.00167829179,50.00610367548],[-55.03738385819,53.74720613495],[-56.00418073319,53.73421061801],[-55.9959409871,52.00107125754]],[[-59.50126630448,43.7495431608],[-60.50239545487,43.7495431608],[-60.50239545487,43.99999882251],[-59.99839765214,43.99999882251],[-59.99839765214,44.2494016836],[-59.50126630448,44.2494016836],[-59.50126630448,43.7495431608]],[[-155.95024091386,20.49523373356],[-157.3267518687,20.49153389084],[-157.32902509355,21.23181053727],[-155.95251413871,21.23549220541],[-155.95024091386,20.49523373356]],[[-157.64488202714,21.24845058596],[-158.28534362719,21.24673774522],[-158.28689557694,21.7499618541],[-157.6464339769,21.75166877943],[-157.64488202714,21.24845058596]],[[-156.12602216386,20.32469602374],[-154.7461696274,20.3284088686],[-154.74174482011,18.87578125335],[-156.12159735656,18.87203473488],[-156.12602216386,20.32469602374]],[[-159.29077130937,22.24504086823],[-159.2892966564,21.76857042389],[-160.28916841131,21.76590592196],[-160.29064306428,22.24238530626],[-159.29077130937,22.24504086823]]],"terms_url":"https://caltopo.com/","terms_text":"© Caltopo","icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAA2CAYAAACCwNb3AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAcppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGFpbnQuTkVUIHYzLjMwPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgofPyfmAABAAElEQVR4AeW9B4AURfY/Xt3TEzdHYMk5I7KICKILhwE8DCe7eieiomRByRmGjKCAIHhgjl+PNUc4UVZEggKSdsmwsMuyOU0O3f3/vJqZZcPMgnfeHf5/BbMz3V3hVdVL9erVa6HNhEciCxS7VtBJKvsDJlWUxCjFa8tdk+6oD/zU1ZOMhyttYXYmK1EhMlbgfnudQWgd161y8+jRnhDZgt6+ZdIkY0nU71N/ijlFyjBneAMNTX/3lSZH8k51u1RR0i3KFHZTvrUy9qy13NWvVbtebkWJ0agq0yusdH9+zv5u0Ym4YgfCw0wHY6Lj93zw5Iw8fz2C2WymjxKo91q/U8xmwGOugufhDUuaFpcV9XJ53T0kSUo+VFooJIaHxSXGxifbnE4lwWASL5cUHRA1YmmEVn/Crsjfx2gjD26f+dzFQJu16wzcv4ZvAWU1AXhUVRWGvrSwvdNj73uxorhNpGTofryiSDIJGm2HpOZ9y1wOKdxoYnar9ezlyuKzbSITbSqTf0mMitvfuVW7febBwyp5mykpEtuxQ2aCUIMOhEaTH/qkQHEOEgShHE801wDg9ZNFELwiY4lhXmFWxbqPVzIgFquGWARoYCJ6zRsz/YS9eLmLqYUCE6SanVDQcZHZFK/S0RQZ0a998p2bhz+zK3XLFk16WppcM2+tK3+bzab9dXqx4lmuoH7G6yc8BHQ8+euXPUq3sNiI/sm33vniX54MVr/AUlNFlp4uY+LFQatn/i2nrDDV7XGnWEQlslRRmFslcFSmEUQmW0DSCtEDkkYjaMIjQP4K00sSixAEZnSzypjwyB/ijNEv7pix8jvKVpv46F49qQY8dzw3+eFiS8UTZV5H3wqmGB3AFpfHwzSihsn4ZjYrANMIzOtVWUSEwACHiH9hBItXsbUMiz5q0Bs3Z8x68U3gG8Etms1mhs81EW31+Xj2/15u8ePJQ0MdLucjFtndzY4JLGcKk71eJogiU1VUSeMjAEhZVpnBIIh6I3IoLAxwxSoahju5kTrjBze37v76xuHjj9M4ABaCqQoeSRZZnKLX6ZnL24CJAo29L+HndZcCsAUAAzKoJgNTLe5wfivPUgdqS14ev2cTvOF2o1b02uwNGQawdhIxcEzxMlmnZS7Fq6/9POS1v02rIKN+CVTmRP0BMK7QFq9f9TJFr2Gq7KlbPzghZhP/0+XUF+c/0Hn248suM1eHMsDE3G7MiwAABUUEshHXlAVZNRjCNRgS0Dv+qEx1uj2YTgFI62Iuqk9kkTkO75A4Z+WQ3gvHfZPcptPYDY88fSGllkQI2jcqj7aIWAmeboDnEuAplQGLB/3i8DBFgzyyCiIBxmvDIjWEWVoUdCqKrLhloKnMLCB2C+ik0F7SO8yl7d1yxrBpf14zd/6Xk5Z8CGRk1RE/KCy4mboltYpZ3WoeN/Orw7tm54tyhMXtBAFgFDAk6LpK40NEIAJ+ozFSQ2oApgMPMbser0Izb0MZG7IC6CaS4J5qObFv8i2Lx5n3zNu4mIgjNRVtod8EC8ZTcDMvuqUyD2c/CrCOPsSKrrdPADb/N6bPrQHsXoFh1pCSImqTEItISuL38Ac4RdOH/tII1voncJYjYAyIO0uU8dqSv01JEWWR1w9YatVN17x+jLEqY9xFQvZqyYeMKk1wj/mjVu68fPrjLE9lhzK73Su4vV5R0CjAP8J9AKZKQF2S9JJTVQQXUNCFqaLfdI+eUz4BhVBEofIlDoey11Yw6LvMX44OXD+vawbUJSKSahDU/AkuCrygcVP7LRy7cmfB6Y+PeiwdSh12r+hRILUFFXjI4ZH97eFbAxgg4RRmg5Sja9As2uDwiETAohe6sNPpzVbtHQ8VZ6cPWDZpM4idIz4RSU0grlz5iCNdNn/9bpOOsx//6ainbPlppyXCYnd60EMZRKFidDSB8aE2MRoamx8eECvzKIpI8ND4YCwlEWJGVETF63B7TtnKxJ/txYtuXTx+16a8/SYiDhAK56KiqoCSiFOAygHSH+OjchkAWAXZi5HHyISUIIFhJlGPAaREncVFrQ/q5GPgyxMo9tu+r1a/jyHVrRMzRjdbTRu2MdNbOa3Abge5qSAMkRaGErQoTO5vSxy7feWADCAXj+w+4ayIyL6UvWfEO2vbE5EQ4gWpVWBmM2+uzYxhG391l00rsNkUjax4UQ1xDvpw6glSNuQtVEhcAcQrSBr0Ldda6f3eljdyyJrZu8+rqoFU2QBSVq8kQBxzvtjS+Lv9Px077i7vU2FzeCTONJgWCE9S6zfBQ51DGXw4zmslUaPKDrd7l62g73tvvfVPah+wUBbQXSCBewV+Xu/fYAHgCYpXlURje8HA+sY32U0wpw5sRZ2qJ/072F9PtVWPfnv9yaNGaVFc6b1o/OwigzLW5XC4RfB+dIS4YNBEtykLvmX6gMNx1SFoZtykjJhcHRiJ+4xiDTt5/uR7lDc9jasRVF31RDih3r746XVnRPdYq9XhAa8lFSWkFYeLs2rw0PxcQazqVft+Q0hLQEqJWR2ub0rO9Rr13OS36AmQ0pfhyl/BDyP7cu/WLT9WXI4CIC6wE60XyB0KYYn7EQw0NvTxDeeVSmv/ghILDsJ0zOlxHbQW9U1Z9sxMypMCY8CVfpCAv84TAQiAsQT0irHGMKlnWMLOlHY9222d9+LnGF0xMJjXeTeqgZelObB5s2fYaytuyLWVLbVUWsHSBHDF0HMBJIdAgaKmyiIYhEbVajRQHkRonRwhqlVe5yfK6Zhbdp/3WJL/+tKSxygDIUEgI36T2iU//PKSBy54LROY3eEFonGJEchT+5sQELCAW3lFgoVggiYlKqqCZTDRVfAEBGfIqpdtDvdhW3HavS/MHoacih8GXigA213PTZ+RLTj7QP11oz19KMLw4wcWBjLDarIKHhLG0A5kiJlQRblE0Yii1upwsNPlhdOe/eSN6AxI2dB6aPB+/c/ukjLrRSdVrSS1l6K8rWIbzPxm6soX9hNEWFQxsznkZPzPgL5Kw+lZmTzHpYL853NVF1mDvNDdSaIETdBPyIwgJphMrLFoLHeJ4gmnwJwGr9zIpnrbX3TbgZIYI6gdwSog8QrVRJPnsLELxbljcPkWkKBK6hJCULn9F08ty3ZZAI8kAJEJ7+okugkVX1Z1oqa9IYpFSYZLxbLnrB4EHmEQOhaqzuhsu4X0GBkaJBkT6iQiEp0gSYXWCnZe0ax87cSJz57s0AFrelriMJYBK+XML9+L2fLj19MrXDbAI0qygppqQRTQr/AE+CFqWmjDWEPJdKlYkc/qYTvQKkrHE15rtBPGDqjaCqmstesg4GA6BCEJHouWxR7OPDwCt1Zf9wTCRRwZDmVFig8Ll9rronZ1btd95Oa/jT5BnRq1aZQ26XKSbE5Pp8s/VjKnu4dvfqHdj2cPDmQON1iqJjRxQGUgztwjIrG8fVKLme2bdP/IPGRIMXV4h6pKmzetGCiez1ybrdrai2ReCWGy53q3W2aXHRW9xr2zoc3GR8efMUP6ZkA4E4H0mDd6WKantAMQ2wOWGxQejp/YTGBaQXNrRMN9PVp0WnRrcv+daZ07WwmeV7Zvb7Dn3C99ThfmLdxrKejqcblBJCwokcCiAQOf4AGDaPRO+ktpKP5a/4ULNSn4kQFt4fDpQ8PKtUoscwIeFfDUIg5k4wnEoej1Ok0PU/zOlo2bzRvcJeXQsN69+R7H6q1bY7cf3fH40aILz+W4HbQmA20HrwmcRayElatMqHwQFfsIhNokkiUqp8/1kgJSA7JY6qCPltvEN5n15eRlq34CgKS7D/lrkmrub/Zt6AUsQfUC/5/u3W+v/1LZpbuLNaThk/SAhTRIIh3aq8hi1/D40sE33d5zyb3Dz1fLJvQHp8X11nFbNqTsPPLz6WPW0nDsitCOSR10AoSwP4leu8Sky2X5t6HcmQw/cVCdHtU93eXlZlsxlEhGHV4Rmy3Jxrivds3f+OddKLeOCvvaU0cOHFiA35/Qp8u8EVuOqRWpqkcmGIMyZEgGsczlZOWSnbj2ayBUhaX6YL9YVDiwFGZrvi4LNbywNGNRpmkhmf6xZ8HGh/egkvfxQaL+q5PvvrsU36v/vHZ2sT3/3FslDrsCI1ZQgqXRYW4vc0ieHpM/fb2pCAEKoSzTfhN2d1RYKtB5iPI6I0vN/ZcStc23m2A4iQsPl26LarL7js59uhFxEAijNm3SHkg6RcThXfPrjugR61bcAAoH+MHVgf8S2GjmGkat1iTLLvdtFtlDa6ughekmdhOUOKhVLWOT5hBxtDA/biCu72+Q97vJpFTjxrTx+S1ik9ZqDUZSF4Lit695US2DmeNs8eVmNDbG2BKukt29fOZNpR5nV5j98TS4moaMqEKR2jJ95Z9vuYsQGnsUZh2pRfhJ1dNuvTho3QS+1zPqnqFPddSGV0Ifk3xlqUTNhA5AiiisyGG/cdimpY3wVGHpTF51eFsYiLkP9AcMTjWDUrXiGAQY6BVNG63JPbB///H0KNVcAx5mVvlYSV8+u+ztFrqwnxnUMN/WSLWK/D99kkWQKwXFcPLsmTaiVhCiI8LDWJTRqDcYjRLp+DDaY59FhewTvFho1ZrSupX+nncg/kCrEKeiIHU0xSm3xbecuXPu+r7rh43JIqlh3mGWuBsIdswnvb2+Z/rnW07+cPEILfBY8ujRQTnUFfiC4uCVx/+1X1fALHDbmnOFiMvwugAAYiIAKRrbHs0aNfyccjzOWriBhJhLv8AHc7jlFt9eUKwx8uNGfPtBqWaBqVkvYQd251miKbwjPfnm4Bd8YByCc+glEYxegCG2ZpGqKzzwag0G1jKu4Wvmu/5S2NmcqktPM7uxzggUUQm2byaud9Gzib0HV0YbIzYzgx5snv7XTT6kZF6HRjWWlFfcHMhx+Kefm5TarTGcJEMxP5IeOokl6iP+uWHgYyUshUnp5hrwMLNgVoA7vI/Nw+K+MWFfHAyAxq9O4p3ARnIxNkTPFeVqxJYxCa8PiG258e5mXV9INias6qgJ/6CjIfJiQ/jTKFBtZOw0wJ6GvTj/ZNSp8ve5QdDjQ7wLi9Bw7W3RTffendy32yfPLnmOWiDCOHDKJzWIWw1dM3fZtuO//LLbXZJ41mUnNypGUoW+r+uETmKfkLqLPn0RD4W4DXFIrA5JItRJWhp94EDTsJiKOwbegVUvYwsWLKjTz/TULXzCW7VsfSFaZ6gAvRHL5WzdP7ZcRPGGaaihKlR63MStGXszmyOuxW4Dt5ZDwsIBVGVNM1HPGic2+YiKduqUGhTp6VkCK/IhocC2x3DvHp+ptDY8PpgE1QmI7R7XjVSWUqGlvJlghHWa1jscPfjtGn+wZlc1ko5l2yy/0IPkdj5CqJEJF60GlnFYPFpxN8QSRkbl/hTBYVHVaK2O9WzV8SZp9+z1L9eubMOOHeGf/rqtTwerdVShtvLBLNkmwRUFLEmEiST4RNau47dck+kSSp7CtDqpoSxYbghLmLdtzpoXd6ISkhqtBg5UzP3TSIdlE7as63X7kgmvHnaWdK2wV3r0hjCtEXtP5b+lwesk78nLeczicQFryD2i/kRbfY3j24dERtTBicZ8d1pph1mPncL1TbASkYcBV5+q187VL1XQFNtt8NPgyUPqzKtb3msDoy2KYlfA7+JVvRzNE0hbjBT1l4Y9dv+B1x6fxNJTU0OCnsJSlAwstVtFJOWcLy30YIqx5Q3vD/ytqpegpiswYbvi1f5QcM4VeJZVVuAppi6AcOpwhECmQHHsi9OtgOdEtcf+n6n4TmftW7TzZlcUsSK53KtIZDEOUrOqeuxeWSorq9BLJAYzs4tE9mYGLXb5BIzv35+sEbSj+M9Rb6+92XQua062UDmk2GmHSijC2hp60whlri0BLr9hwItFkBRpNIpNmWFr1+ZtR30wfm4OVZICuzwGWD2QtpnDdf+auQt2HP3VfMyONZfMPEbRoDqAFxoRmiClIL5Y/P51+kfr8cCRgSboCr7UBhXrDzwUWYndEvvl1+mReG6vnSdwHdh1LrDZ5YjYKKY4XXpy3KudYMORnGDMsaIp6pz/4eG9+9s7ZW9DqHtggcH1fWCgQlt8UcawrP5CSyIu0EzovQ7zArPKzIyVll7OpU6YwsM0vt29uv3FxolUqZfYPbFN+37lhwlrC0g6/0WIL/RO8GIN1zYirttl5MnIMAfN2TkrSyU7p+xwZju8biZEROrDMa5ByANbRbIUGxnGEqIidFImTI1UI9QWcep7mzpl5meHaXUaTaw+qqilLuGSefgT+/D43j+vmzv0QkHeO0edZQb4FcENglwgqOS/lrA5S3tbCqzUUhuN0ZNgjHp69/yXNtPOQDJMt61iBip+T1p15JurO2deOPvmpwWnejJs5EgaiXQSER1VI/SRLNotlnOsCeKL9a9B9x8sVW3M4JKtMYq+tWsoTABnAIoI3suy0/TrmaMDANn7PTfztZbPelcNVJ+aJbBBbbq+ZxO9hyEGHGguCIUAqWUlXK8z7uT7SKijwFYebyfsBcLj75VFUrX6AQtOF8CZk6kH+G1zCtxSMqrlqPXTj9w3J9/pjck5+LzV6w6DixgEGCRILajgOgDlmpliJOPeQC1hBqNY7oF/F19ehaQUDbwzWaFUOYg299Y+8EQ51kA1PHKpPtzjI7/m0w25D/T7y7LOTIgig5RaXZoFGobjI9xOw+Ni476Q0jYt7X+5KO+xtnOHJ+tVsVO54hG14DqwbFX8qjMU9l024ecoKfyDLycu+XDjkR+/e/3Dd77b7yi+UXV7PXzjhtTKkLAHWrzyzRUBAIbdGikcA9CM6bcP7N570rqHxx5DLhFOa0JR1kY1fbRPavRbOnHCP7N+eeECc2NmvF6dRivCIQ6dVaRWkdGsbXiDtU927vViGvsHRiGDS5orrV2HvzBWWHLwdHO/uyt/PLWvCEgZidUC+lRN9fCDTrNKfodFLuzwFufM26+q6T0FwROQFv5svi+fmiW8P3H+SzXu13NBKizt5oczqYeH89N6fI4g7eJFibWIiLOSKTUF/yDh66ndx6CxX0P8a2Z9Gas/C7jkd4lvarPmnYTnLVc2gnJ7SDVohKL3hNcerj/00wzUM+vdkn1kLq9S1fx1cwJh6ZnuT9Iz51Rvr77f0i/ZJ5df0Mk3K9hdhTM9VQKbGlZUWimKuZ1RTHC2jWKlj7SfOfzEt//8buT+RZt79F487h8XvZa0vLJyGdwc2g55btafiIZASVho4D9O2TRmOkfTsPgpe+etfzmLveWXGmUkNUiXVB9at7j1iaLzmw/biwZUum1ctQNBCm7sBxhNRrGLLvJs15btR77+2JQd26hp4kpXLCl057pNosYne59o2dLZc9HYo8xjaa14sLdHDpNBEje5Kqr3nNveYeayKaQp3E9uNVwF9e9+VyumEvGc2x4jhtbHcVQCxwBo4VqU5fN2/i7/vNbJFVUSI6FmUxXhjsysLvtBai+hU2aojNXA8f0kWKnN+mDKwPNUrDexrpFhemK9OnY6fvzyubI8puJQmIA9iBCsmPxVXV52Xq2Y2X3+qIOHFm1OB+1K5hSzAslB+FQjEQFa8trVCwvBOiQpSZZK3A6rip1VLHHsilZnitPpJZOXlUZodBcahkcVV7isF42SvvsFe2nDS56SH/ssHL9+97wND/35hZn5Lpd7YokHqijWAzjAQ6ZhLqQDfJATBawMWPPBWwfre0HRRhtNYpKo294uvuXITyeZswG5iMETMy5jrTHaJwFSVkwcvzc3a/UFwaNDx2F4kDRwV1YVDXbT4U6UHNVk7UvTV81sKwguNipZyzbtJ6K+5smqMVr/44sG+oi9Ea6y+y0uaDb1SGLghuR0ueTtpefu67vw6S3PjJjxWFrTpo5giOD3SbuqND2wGZ1PSefqVK+Yhk22l+fysxN1MArZCDTMLzOCITpNOv86KBV3iV6vnjLqEnLQQumbCSiexJl3pFXcMO/Jg2Cof1Khc+BuHYODPy9QTFQqvR4x2162ZfDKaU9/PX3VBjPWI34JSTK7Cj8y+KG6DH/R0F+kR4pGYmfovU6vM7XWhh3pG9vs2ZQuPTpmLX+rx/dz1t15YNHrT+2a/3LPnOf/0aR1XEIXtOKcuOkF85dTVjzTPizhTzeYYs4nhIdpZQ3cjqHPYQwhJEio0F4VllmgDxCHGGnSa1vrwktuDEscn7X0rTuIOAh4UqkweOAYGd5H317Vsvu8kd8eqix66YLHphPdMihE1Higk5hMBm1yWMLJGxu2uHHbjOcnEXGQmwkrgwfvdUMcVXMQetRrZenYqPFXTRRoBIoXi5HQFELFyKcJ29vyT47C1FWbF2U++eoLf4KG4+Vckk42htorCA0NVrU+xDHpjB3JggUOFxQILtowuZGilrU2RIZC1Ppa+k3PiGlSAb3W8EGEXgeEAlaFSIS/tHdHG9zlXhc7UJn3Um/z6A9mbX8rjtRHFFNRX9B1VYgqq25LDqZGNtaHsWbayAV7zBsWna16xAdKYljNsEzfJtT/jZpPa+jpw7ZsCB+1aUXU5tEzv9+Wn991yRsr/tpEY32yzGnvbmFeg42GGDMaBmNIGCY0wRBxLjLC9O7tbZL/bv7LcBxJZQIAxiBnqOl+C9WdK6eN3Z15ZM1Z1a7HVr8Hbj4i7II43SSL7SJjWfuoRi+Pnbpi0mAQBhEWierNo7lzXQDl/K1e6cB//1dQ3KoJRrUsgyZM0D8//JljtywY8yFTHEMVl0Im0KDuJlQJ7ygdlsLRwV/chS0rsj3b+5jHru/TqtuS54ePLSS1hBAh4xq5NQfMLwTyLGXw5MOGNqFi0OQbXnj3gpmaAmMeNOfvcRN94IAM7nD723n7P55nEYVmIF5iuJxwgrVBzyBJ1AKrRS4yeh4q2Lat/4DlExd8N/PFTWAuJEWwxk2tcqEPVkfte1JnQ/SeyPCoWdtmrNxBD8nsa2gUA3WHU54HxMGwMNQ+vH6i2KTUIjRt1VkzPm08d0qj/Hc1bGjD16v0eeL1F5rm5l+68bylNAq2W2+rqDhvUmzMkXfGzj1LAFID5AZQBIL3D4A6/r2Xmu8/dXTzLxW5d5ZhrQFB5KFVlwdrDZPJKNxgiM7u1qrjqE2PPvvtF9Oe4wiAatQAEvQyjx5ThrPHp1/44O/cq9d/VBJ5rvsU3i9OZesZ69C8zYKi07ahZ9RyrQYjgEMM1cioZjf8RKKVVFE+VVEinjLpJ1hP7XtyyJqZyx59dvmKNB8iCECE3+T+X+ay+4REzeaqrgIAgUszA/uXmHFVXdf4g3N9c1qa+5aF4xYVOYteddnh9EgUUE8FEDOURVIdHs95wZnocAovd5r72JN3rZw5b9v0FVuhfgIJmcbcGQ4oQdYntauW9izeNInfhIhO7TQOHJ1vyCk7zp83rP1403155cUDxywa3T+3olS4ALNsg2MHNL0WjKqINoXtjo+I/eT9cfO2+yvVvDFiSg5+04enbP/3u+PmCeQ/FNdIJ6ePNnOzMj26Z83MUd9m7nvxlGw3wFTn1SFCCYIS0FxoEnRGlhzXbMP8KSun9REErmunpJhZRiYWhiCCOV+81XjfsV83HXCX3lMhO5fzpmLO0SSHYoE8y/X1pxNUS7P0xoipWXesmjolX/C8YLU5vHBO1F6tE9gE1GgkEBPU0CPuUlOmbFuSPWfEiLSXFi3d8vT81/k6JCUFC9WUoAvVK+PgEyFwhvSLqCtP6v7CBhi0AoPBRyB+4VM32+90hzNBMxPhgPhaz3kj0341Vtwpk886HW6qJ3FdDJIY/otKfrlVzteKPa2Vl77pYR71TZQhZtqOmc9hd8PMGKmlCzL4WfZQ1VFPObcpyuqME2a+CB7DXl7+4PS3lq3K8dpb5sOTEvv/IEuYfoG6uR4Hy1UdQEND94YVheNaz3jkwI3N2i77cLz5Y2pk5OZVD2c7Cg98+8yq09UaVbPNbzqzcWMLDu289vy0O3LKC6fvK7pwW7EDm4+QGhKOCUOzwqLIIPUNS8xp3bTF8DefmJaxdeoq7tJ+6nJSldS4dcnEB9L3fPfqKa89FuCzSFjEuF/zH2EfpNqg8J8+dUj8dtrzq29bMrHPLjX/QdnhcsMnTcdtXQHWXbscroHSeEqIICmywysf1ZS3ys8/8doN80c80alhm7n/N272D+aMjGtSu7Bg5LUFaYbf4mAgCzaKoePVI0Fo7ZCZWQ/UoVrw3Td37lyDs5uZ798dXe8YVrb/i1/O6rzNNR4VuyOqtj5JQrWhT3QYEschVTmnsoLl6G2Dmjosg25fOuHNbm1vnL4+bUQRqvcHhPAFafBBceWvBDEjcGpKT+eesVu3f7Pup0vHHz1vh/OGLHi02PsENKBHURuF8C4NdAa3Tqu7iGNblXbVo4nQSD1OluR9NHDZM1+2a9Pur0qlO8dl83zUY8EoS5Sg2WbXas7FR0brC4sKaQvjxkXzRtxazjwdc3G4B34/Xh1UCjc6gnMBmg7RcayhKfr5V2asmUuLcFprkJvJZh/hKrTo+ipj55oTtuJHi5028liwa416k12mg2Z/3ARjBk4ICWzn3HVDsbj8PEuqHFJpteE0G05Q1Yu2vj5jt500H5hbBLnIalOKdK5biy4ey+i9ZPwbKd37TFnx50fKSK0Adwpp0OC+v/UtvfkIKwzno5hJbwiVk86zh1xMX8sM+c/1UGsc/4Gf/JTh8rS0oj8tnX2zq+LCz7kaWzOsKMBEmO5qjfmf4ywahggHanJUm5RjcT+e/2vZ0LQX5y/b8syi5fWYzBkRCK9j+N+X3PfuZ+9vOuCqaICzwrIRZ3dcGHEEsdA2NUWwhobIH2D23ZwQ3XDv3U8MvZwmwMSINPOnbYk/HdjXqMBe8UR5acXrI/9y34jPM/akZJ069tkptXJhCaQCKyghxzjf1o0b1wocbMCJsOTSubUia2g0MhgKDndq1PaZd0ZN/6HtzLVVUiMg1R57ZdmT2zJ+WHPEUxkBdUzWI96RCwEt3NiCbaLXm3IJGNi2ySzzR0sgDuKafPd3r3nTvbctfvrVXTrvk16ckQC3plOG9bDsK72l/ShIHg04midPsUn5gvxE5U9bBz+wes7oTyYv/QxmMOCvr50rpa7tF5kkmUarKbBUuAut5eepVBbcN6pKQxUCN1ZaTXlwZoHKegC9wQFDL6iryvl/kJ9XpaKYUlt1OZj+zOIVuE3qMsfNDEhZ8q74bvSygtQNK2/OKTq/e6+jqKUKtRwqH/yPr96On1AomomKmETek4IlvKTo7LIBSyfe36lt14dfSht5nqtcteKqSbM+fitu/5nDz+/KPfn4ORu5/Ekeg06rcXghNySdlGyIq+zStO2Et0bOfNvfF/b6CL5sIS4ij+17F1ml6PPs6i1bjF9+uyNxDWIv4brfk68+f1tW7pkxFcw5yCZqoitxZsapk5heo9HpoB800Ohko1b/U1xY5GvfTF/1Nvdf8G3wMPNobsVQEOol8suff1z//cXjw3Os5RSSB3suGhGxq3CQQW+41ZhwuXPrlp9tYh8wMzZ2zGj4j5iAuLRW4ESyc95LT93/wsyzZ8oLlx2zlUp04g4UIiGCC+fj9fXPhwiQ97QtBX09izkaOMtzP+23ZMKyH+eun1O9nbr1hK6elAjEWRDOuu2Vq1aNJrcnhrquEEhmKgqnMxxxHGqL1CULDuzLExO8xsT1JY0Gu9RqKxQhAqkBDBmNUrBeSx8/PX+Hqnaas3jsO2c05UMLrdhEhusRtttCBpWoDgLGByYQHOpgGqXYavV+77T1unyo8vi9G+c/+Pm4RV8hL8frQBlp+6+73vmV2Qd5Ky0eHRzRPJD2cFoTm4RHiV0iGnwx4OYBo6b3vyefCsICpUlvlKcyn4WLryM3wcIFWzPLcbnEyWlpJFUuBCp/7ampO/F7J4VsuVSc0+d0fk4UNnLcjQzhUuPwuLJ2DRofWfXw6LOB/HQQ6tTly8RNgf2M3bl6zpD3f9y2+bTqaqg6XF69Ros4UAhvBXWsdUQ06xjd5I3RUyY8PURIslOwL5TjMAXq+6N9A354CkLb6i9oPp2yYvnYd9ftMJ469topT0WnChvWajh1CM5MQRSumqCjE4LpcAZdPldRouaHu2YPWD65+/ezVt9D7eDDibFmRVfwveZ9UCcQy4v16A0RCfFpc99rN+eBRw5hDwuWspqRJ+HcVMps8NaSVSdgDaWK1a4ePADTqnoN2KmEJ2rwlAG8IC+B/ohLhxypd6+c9vhlofiVw+4KCYGvEL0E0SYhRYOXrnkXIfywPBF0Gq/gOe4p0dsvyV8O37hkztvj5i7j6igObFEJKctaZvLCUcQAlcopexDkFYsKfYKla6M2z7w1bvYbW9kL1Z0HuQVqxpa3m2XmZD3icrvuenH+iKRchxXAwUQ873FNpNZ4IiI8Ymuflh2/Nj/wRDY1snRI2iV8VW250kXASY4lM23KELMmg2V4A/FwZ3y7JerggT2vZpZeHHrJSctv0aMXtBqXjHPbBkg1Y3Rej2YdR78yYsqXX05dzhehOCTDiQqZ/9CJ1C10wEseAi8Pm7gXBNN10Mpp888qebNPq07ovbKMdSGc2eDeU4PHBu82XK/BVrSqHdFDvpdzB6csfebrjDkvDiYi4RuLaWm+gldh9tDO4KSlyCYj9tJFIYEKBbNiIZPE1Wevl/ZzrglZqS70Gu6nAAIMgK5DJVov+ImbbZ2+6s2ZH723M/zEnjVnbaX35mNdCkqDFVDEfirWZVdJxGiwwajVCpJ8wVIu7C45v/S+tXNLPnt2ySZS6UhqSVhky3YEFHTKLm3DiEjWJTzhq3v63jZy0m0PkhjVpGAR73MD2UxqqHD3qqkrth3NmHpCtotONyxcZP3wi9IyWthLlrZRrvIhRaXFnsHPT3uvS8sb5q18cFjulPdevivfXlnx3sgZVd6aHP4DzJNxwHeufNn2j+P2Hz847ssdX0/K9FTGMI9X1mKMPThgROuNZmGRrH1kwlsjn3jq6bREBAhIYVLquC2qz3fHzKv7/82fzQe4SgGCIcI3j3tn9btJF86vPucoH5Jjo/Nh/LQnnWa/Kpl4oJoBaXSy0+k6oi0e9Kflk5d9N2v1bLawPxA4gYsNEIB/WRx8BGmaaVnghprsUOA++z9MnLjRPhlxVjz4yDn8vO/B9eb7z5fkrTzqKGvr4dFL+Lhdk7SFMqiBe6ByprhArbRY/566aUlm+ui5PHayZCcvKZwN6KpPqOjQoOmU9AmLXtvOXqwuNThnfnjtopt7zB/x+iHZ1km1Yv0lYi1AthOSjdxNhoYPo4x4rBVOh/qrYtX+Klsfz6soSRu6fuHQTs27Hs7c/dkbty8a34BpNf+AC8HppOg4I4hMLrNaYnCm//Z/7PzqT5dke2yx3Y44DdgSod10FQxBpxe6aSPzOzdpNeb9MXM/+3bGmurw+dQqEO/143Ly+2BPBklF9KvzwjTtxkcnn0Gt9963zjywSenltSfcFZ0RmhQaCc7ngC1x/K2nWTLjgtnoSysq5FOKOCv15cXb08fO+56fB4I6gRMOJLfqT5heLwxhdrfPalilEtQsRZIJxAbrSbUNT0gWEo1XJeaaVdV/RW4kFLIUah77aIL5U+T+9J4XZs44W3pp9gmPLRJ+fDIPrH0NahckLTRYrbdQcUsnLpx5B5vj7chrWmokGSJv0IfvfvCuB//ybG8ejUKE1PA7D/qkBiLNLd1bcHJWtgciTIbfuUarBdVp+cFlrhH4OoKR4T+gClIgEgrn6DmkFphckvC1Z89Xz0Ak3pVsfup5l1dYVuq1shOWQkhthZXhAIsVh16YCxJJ0DgwjIicx3TwKGZNEDmxbUTCG08O/NuzPIxLQGrAJR4iUDZ/9UbDvYcyE7cKwhGuMlw3fln1T+41P0V/MsF2Aojw2UTzdpTtAheKMZfUklUnZWc4XHMowNtVTcKQJPD706o5TguLz7+4CvUkY8eML2midXAf8SKuFlA4GLHxe+BBFAe4POCvH6QTWEHpcWCHifAWwsGrqhyqh/xJiUyqbv0uPwJrIOCsRAzlqykrnpvx7aa/h/34y+JKg3fCaUsZ9tkgTXhc4/qbBJFI4ADu0zpnixFznhqH3C+Kt7boOPnHBS/3JeIgvcvvPOgl58GHNiy6CQh9ZJ+tYFa2rVLVyFxs6UAc9XaTBpPy4DyYTo/gecdLCuT91twX+yG85gHzq1MHt+/doYGsec5jd2RX2KzYDoEQQCER0TjC4F/SQGeUmkv6gt7h8R8MaNejz46560YQcXD4xqXSbj93bhyx6flbv96/98KhoouPUtevHrSBcv0xkx8RZEIE6sH3s9b9/b6eKR1vj2i4tQGiTMLED74U+nRfoNeQJBKcEr3FXluPxzYvuxf3udyINYSDrZGtKpCz5jesRGBeAuYVgbK9tEaulbDBR3ewu5kt2Oz5WK6cZF7PGRUfGKpPJUo6B2EN6g/RQq36fuMlEQcxSFK7nrtjdMWBRa9O7JnU9s52hqhTEtatiLZIx06v2jZUUcnpdLIKr2Pq6t1bjNJrY2f/RLBwCrxMLue+g0p9lk1YvDv35FzspmMIFbdGo4H7Awb3NyZEH8f+oFa9VF4h2yLkpZ3mjtCuTHtyIaqZad7/xaIjew/0PF5woV3bqPi2JoMp+uDFcwd6tOhwqVF82+/XwCrGFyxwCUjBgqO6S/zN5vGL/3n2wNxcyBpJ8ZJ9+o8RtKHa+BVlZdXLaKplrfoZQARSu1Y+ODIXDwYNXTt39LGCi38/4ayEoiSA3YS25BCG4AAWy4HX65niy3/DJY+Ugqg2dh8NEImEwCNAi0PCDO/jqAs3LfqRytd89Bh9V6XUVMmTnu6Om/vUykK5YhpzQJSEiP9VVeZf/QFpi60Cj5ksdBlm8f/GzPkW6+aOt+CIRo7WOu5SZbkKAvDFC6vbA94qtCB4bOJMupY1+Xrnz0MkMpvBzYRczjkn+duLi5KPFWW/ftBa3M1ps9ELnOigAm1b/MuJFonQlcVyq022GGUziETIWvK62dyTnzTbiYp3Hq9W+6nA79TOukH9BgjffHxUzsjwwXf/i/OSzxbmvH7IXdLN5bLDumXQGplG4hQSKPdH+b6dAxpiqup04grWVqld9M6MdPVDWF0e2bRid/7JA9vKBU+j+iIrUq1YGsAM5mVFtoqe606f1k9s29Z1oPjiL6JWNxjnu9HOlaYCUPjuCMyBRfqlcgRg4CnoKoQTSqAcvjnqFLuslZIWR0mrPbiGn799bFApCIRgUOg4BNQ6gnV86npzznfOzOWl2LCGeZdi/gStm/qJMkIRwv5UOiz9xfSsoiri6L/kmYV78k/sP+Io6+a0O0lqgJiuvgBEnVdNBBAAE+FnJJ9V7AtwqOUNKjRwxqgoWMa6Ba0AxyMpvhJO4nuf3vJKy9uXPrNx36XT+4+6Ld1cDic24TUKLO6snP37QRsCKBH4DgpP/TeDDnh9RTIQ+A7Pqcmrf8gIUStxh0QgQpsJg/TvjZ55tH+rzilttOEUdoFiYoXsCp1hg64NhwRP84O7PmtJ1eKkOL0bCqWCF+N3cfANbkEsUdUnURlirPRdK9G9K5+YGICCcx2wEwWvuVbpmpdU5Fo+NUv5rzbDTEvShLYS0ieYVwxo1nF+NNR4jA9FwgiZoKpifBAFWfX2kGit8bfNS7tn5Z5/42d7QXebDS7nElRaQf23pEaw1olIMAmiy2b37NPkPX7nc5Oj/zlj9QMDVky596aFY17D+ZGPEsKj9uBo6fksp4PdGRkTVVZp61rutQ/YdvCH4Rc1Xi2kBkUFR9xYbI5gbZpoDGdt9XFlpCemJA1RM5gvnkCw9q/lHhkayKx8LXmr5yGWdfWEajHdsF7z/QEwibWI6j4EngEkAPm9GnUAkzGXWq0olCgLRw9Cz6DvcuSrgWtn1n/jIiL55Gnzqd6Lxj11TnG9objJgy5Inb4GCBAKuCbZ7I4WuHWiS2xjZ0nZRTCbGlX7cgf+whAFWwA5rnamW4G3dwUe+79rVuB/gREd5GCcVGrlDnH57BtrIg7lZ3+Bl/bE4Kg1SYE6c4Ib8C9XI+OMph3fzVo7EqJDxKfGVIBA6Fplo5j2wwmLFicvHH3zAcVzD/kB4m7QJQNwVCPDYKSJ0PaUbl3y9LifL5zYcAaWDZCMb61BC7n/UIK8hfFWoy2ptLh2qMr9nec9+eH3M18YetO8kbkXZfsbZxi8hUsraFfU/ZOlXEch9UsU7E86ET9Kg/NdoqD14ugu0+lYG0OEvY0xcdrWGS9spAHM8KuJQUEn9KtHvvsWoSJzgHMUl5f+Zo3SAGdnpKBNX7kJZRV7RuRgSvfKnY5bj7jKWuG1TGQjD56gDDSTTCwtuX+DA2zzeUw4hfas0xCIBIPE2J55G97qPPexRVleN+LKIpJ5ED8ljkHQsophPTx2+TwflUK7dT+PhYH8fE8wGDSAugIuPjDdc/z4TwTq49INbR+6kCsdt+b1KhDgz1pXePqgo/HWSayBq7KI38g01yEifzfUlCQzmKeZdUxq8Xz+ecs9l9xWKFLBw/7AmwTzIbGLzkpRPF5e9MQZOqiEN3lh3khqhGrE39a//4VFJIX613vwcpZMV9mDPcwjd/6y+JU3zy17W4h0CevaGcLcsUadsViUNSWykwMk0EsYdVpjpM4gtdSFFSXrY1endElu5ScOAqoO0lSH1IAOh8LBqsKQrOWke1rKTL6yQXXs6tUylpnB270hvmkPFUwJ3Cfo+Pluko6psHCNBHs231OoBFMCG1PcuE+vcKvx0eMcP0OM0MTwSPKgbUNlOnXqFLR+PFLJ2Q6zjoA08lcM71oEstXgplS+eiKmHkhNo+Id0UAYVINRCJ7AYwQVOnyUwdSL5zD7+h489793N1/nhFIp4IAqXoCqIKx9rbHh1yoYOliA1ePlpx3gbhSy0YwFCzjTS+7Z+xDOGkFQQqUMabOjakgLRegddLocHA0rKQVnmkPW/7s/ICLBTGjheerOclb26zZ/REG3xq0HvTt6zjPPvP/KsovFF+9xOO39LtrKowvwuq4GEVHaaJ3xAhag27u167ADgZqtXJmCWY9t2nTVoA2t4hsJ53LLKaYT73zwDgmKBpRr0uop/OU3Ph37KkSS7hu1M+UF8fQLa7ag+AVkBFfAe5FdjspThbknqH2OoDAaYY7hN11XHaLlMuQtK8a7MbIunee21fqhSUGBDHbSZb+gMdI5bh6lBvdqJgKQqsZ5f/h7mjgRNUhqdlxbcKYc0Ef7H9fpB6S6KEPquF3ODrtV1cgPstHaCERZs4Xf5wqijS8HaHyoldq10k0ZDKe5MTI+Cw/9a7La2fg1H0r8eqh7ivvzrZ9CXcqPxsE0eudMnXqxVgbfUtQ4nUmQaNr4CAVqCFr9f+amv0kdPCDcR9zOxPILzgN9Fo5b+OLfRprR4uv+D2+8hP/1/dlFXzgaPApHgzdvR8zVa5ggMOpDfJVIfAkDEGxGcVuwwD3/QllRO2oiA//qTT7kUO5fY47+Je9kJ4prC4wOKqi45QRrw0amiNIR9/3Z+slYM8P+hYBXwBKjCJp8BISYtTDcwr2/LTL9WL9pOIPX0ys6MelnRylhVFDMpeawtmHxiD/buXFzdhDXdHio3exHT4OIbyLswK06ayJflEcBUditjd9/86XmyHPCvHChYPbRGy5/j+QbjFvatBf3HbFpSq2kVeM100GrhkkWBILJbEMv2uHnXkIQbGCIvz+zT8L5IWgIcAIJQhzUDM708mPPyISQo//jxBEVG4rQl+WLeCPREVfpgi6zHzvdc+GYBzft3+9XdfxAwhpBrhHUB4aIkGSloOO35i1b6F7QlEKMGinCqM+MxFtNMSoSDUCwzBhEDb1yGd9/mfX16wlkwIC+H3KMkn0RDuFt40q1aBTivMSyA3NRowkgO2IPSyxSMh4fktTTTg8dbtchAZEKMflB4eEVgPhLsHgqtpT2oOsQC2OeFfDyvkIjuJXhveWc/fqe1P5LiyGN1+Vx4A3gVVb1MFF/hHbBOcrVLoFrwAnTiOi9iDXz8ZKcAZTli0Z5dQipZtGMwGXQcQk8DHwjEx+L4akTynASMAcEi0f0ysa6CTdpa14pl12RedkXOlCO1PT0oPNFhEzP9/16qElhZWUsFSUtJljC6l2maPQOj/tQ0MqCFfpP3wMCYSgkuHm5PMecFW3Ouys+XP/JhsNweFz9wJpZt9C5FRioPP5QqcqYj19OTF236HacXPxoy77PJhB8FBCsNpxAcD64bz4x/TT0+CxCALDsegZc9FwQnBG7Dx2ZSXWZM83YK6r5imIsxoWAtyflKagsm0NvJSIVhK6DJVotR2v1LCoi6rvAc63eeDYacaZI+wqVyIXEA4vKZUvpPWiXv9MwxbebXh3hBP/7OJS/vrK0W7a17EZy90WTQeEB4cCipLJYU1jhpEcmFKJtni9WF5YR53vJVV29ww8gHVByIMig02mfSrewsQwX9Jrj489KX8Kg2K4+AiJuHbqbV4r4c/WHkybeGJVNBAKLatCS/CZWdQVwIMipLHiUKkn/cbZUm6nRfG2ryNTT82MXztxXqgMsGFZOYHSzVvLXy8K1xmNBB7BW/v/aJV75RWtMLXRLuQTvCD/mKG2zszRn0vZLp3d//vN35xtPf+hAzLSH9yZNf/jA97/sOrszNzPjsOj4S5bbRtybZYQIXk3uB/Qca4vPyfqFQGBBCYTyYDYlJ4KeHyvNm4wACGlw0nf73TxwHI8jEqlogagvrN/ipz/YZy1qDsswArkER0i+GFQUbQNZ8uD1YB9SO5RwqOknHU0TEL86tvue+v6Cm5GpxXvBa2/xp+emrKC7GT5rHRblgMcHk8r3i/DsRE72y/mw+kGK0JH2oNXiPrR6iUVrTfs7C4IbUhlUythNbTvsivEiGJ8iY0svODrzPuKN58dsxS0HrJg0F8V8rj90pJc8Hoh4fYyKcKsKLpMGr3XnumRQkKh5X6q2hovQGX7G62qIf3CcDWSp/o3BgTu6W71QUTT2kb8v/RNbf8ZlDph6q83XnjXpjmkfvdn3YvHleRVWKxlTeJ+r13Xlt8pM0JQVJu64rgiEAKSRIFcJkDh2lkTFipfFWxAFPdNRHnEJGzdlzHtznuLpccphDS9wO1wqkDkSHq28cyGCNgTeDdGzWYdPuujCIUA9eD1l8ImikDv08tgSBKc4XHD2H7eteHbtpC2bunLQzKR9MPXVzN2xaX9fPLinedSBXZb8h+AsSJEx6hlw+LDptaxpZOzHLzz41AU/ArHnJy/PbKIPzwVq0e5CSKIlkCrsDnVXSc7UWxaPfRMB9rp8rZ7WgzgU+mQiEMbjr6xKgTXwp1/txX1w9loOtuinMaJe005iks7EmkQlfkb3Elhn1JMirfjr2OxYbfg38KCj29Co6iaaH6ynJBzgUg+V5i0euOzZdUu3v98AjIT7x2UQ8UI1RTYO1/gPXupx7+qZY6DQPKa4oL4GMUbUbcV3J8Jg3BpLQW7grhR8ttAIuiTh5brnnFZ2MPvkt/esnTV75idvtOA10Pig9LKdWxIeXDd37PeHf9px1mM3IrQSef8FrRIMEuSoSs2Z3jage999QsKUh74v0sj9/ZPsE4c++K6rvxLUAnSqKtAHNAR6fRwhntZk95qt6z5eyBHPNznBYKe+yX0Wj3t3t6XgERy2h5EodJA2ag97SWAlBrGLFg6zsnwEQZmsOrjdRGh17bJdlZGF8GeiDSdIFDJ2BE2+ejxq5+hEcUCnXt3XPzzmMLn3kAcDIRJUyJe/Ljo/RnDBxwPSM2gluEnrJqhM2JKWhFZaE4LySWdtslxA+Y1MbOiU1FZn8R4hsIqQxEF5dZAsbq9L7B3bpHj+hKmtB8e1rSQVJC09jcfRunet+bb9+ad+wJtwZRy58xlwqGCtBM4KR2xVjQg3io0UbWUDY9SvFYr7V6siu6IlSR+nDbuxyF7RDIH/WuYqTlYJB0BIWcxfcCmLccI5VlXzQPOuOz6ZuHgAmuPz1WbWsENnPNYbcN4YAx3axwwMT4HTK+LDG9gNYhh6JByrVBWLgak6k6jpeEaxhyEQBqQ2XpRbj68aYrZ4FBxd7W2Ie3Wv+eWR9XC9WiPyP76EqkEUzwmYSxlc0Y2gbCAIrBC7dJSX9Wpxw7SKrN1Dsf+ih0U3pGMftYfAU4KMwADH7IUaqGbd+MEwLCaYFXtyOIUGwgDKhiYOIDUoWPHow8J07WKTniPiYCkpEsyRfPFvhpWsSXzT5zuWFIw5rpRCm9AGNTtSdyAR0Bp6ixNLODSlwXv2WmMzqzUXuXQ+H/sEeG0zAtGERiIaKwT/9iZGRunaxCetJOJIgUqEfhDHl+mo6efPmnfetuTpr/KY6x7EbHaj/qAGEOLcdGbVYoOEZ/bIU17r7UzS3q7DNuM5sk/jKAOFMgUDASvD3i7WUqGIg/pXJ01oI0FdklvGN3qlqOTSSxWynWRJyCDpdJ6Dv+DJ6ZIP0wuftNquPoMiTQI24nEaAJoBnVkOKQRADKrX69a20UWpXTp1WkaOstedilVnoH6nGyAOHj5m7aOjL7dNaDw8zmAir28EsRHoBfNBk9/KIUka8F2EUBUgRohD60Ss8viE+wi2TmHUR3vl4FQuptPoeoc12IVXyfFFP/zKuOpC8JDE2/z4xLOtYxqtZGFGrKvx7okQsFAb9AgfmmewdpFWPTiAgLe9QBUFZ8TpwtCTT8QBu78b9kJdB130j+8+vWAV1ZlRzfuAog3SvQG9+o7qKoWDAas6vAKOjpEETaS/gGphmwPrx7gITo/HbXN5ELDBQ9cUGIHGDnSNmAzBJUfQiunm+jNEtMK3U1ZtaC6a9oMh6DDmQdyIr9TgU5ugmmt0FCgaY0MbrwwLKgoJIeClMqH5KbYAEB9b9SThxUM3JDWf/WrahPMpYB7/zxAIDSNHBizYP528bEvzsKhHm0RGwZKIE/kCYixhgK4Mdc1f4DqE7JQP465qwFZD4QyfASAi+LniCQ8z6nuExf3ytznDSWVgZp/J+Eo7/veZfDn9uRm3GhJ2MYNWh/pdYHFX8tQEhV8RYoIYiJY4TIAP9uvQRQAPqaZuvL5Y110fc/yhB1MHU0V+eHid/mswkRTJfOdf82IiYnonavRWnP/Q0viEgolapdcSEHFiCOk95siPw3S4Jq5OY3ctKZAL39Q9nih8Kv24qUWnv7ZkRhvsckRt9RIJ5UebPnhovgBHfeeXiHEAaCjTqhIRYdI1lcI2fPTMUjKGiBlgHv9PEQgNHsMxTbJqHZy/6d1bGnV4uEtYvJsjJikx8CMkXfa3DgrnzlizwHwKIw/eCI5VYKzRpO0Z1vC9d+ZvvnW00JMfDQVCVk0+hwWEEEDS2X+bNLCPMXGXZNDrQV2kTnnAmTlQ/rzX/EXw4AMKIjzBG4NVWYwIN+l6hifu6nfL0BvHd+5v9UeBqQ0PmEiGl8Zn54y1x/u17NI7OSKxGOs8Hb3MFdVymLiZ+JqhCZ6RKqNxJsIjKQ5tjd5hSBKpSqWjnfEUcPHXnpp8pkNis16djNEWhcQ3TmOhLCFvgK6CNxLiLuBH23yeiS68cE7VNDCaNLfFNH5u37xNT/NimEj6Js85qMkYJ+43r0IK/RE+ONgGONEDwE79AAP9DYmHxAenTB8/9x+De/yp9Y2aqNcaSHpZi4BgOJkHDz+qlN7XwieBVDBZDwLAAl3l31joYmowqWgfSEPSWaZhhk4RH2bSdtZFHu+X2PovGbPXDiMzKl+U1wqPEwCXiIaIZDDOZOxesLFfL0P83Jb6CNiltDgKJotQc0gl8xAsvE0IDz3ZwgELfQgeIswqeOh99/QuEQlPSAAABIhJREFUFsyoAkfPCKNR294YVXp7fPMZ+82b+q0fPNhFxJFeT5BvGh8iko+enp85avioNnfEtni1rSlaNtL4oDmMD8AhPBE8/jHwQhVD9wkWvlikBSP/0D16FoAdY4l+0FILwRAUkC7qQi9pgWCQwmFhdHvy+dj43aoywMUJlm+mLs964JYBHfuaEr6J0Rs1IBS8AjAAB/PBgTkhIwSNCW8X3/Sb5g/w0Dhy/Ab8ZMgQFaz66DRmn+jGx3sltkj5asrzpAaT2yn4k09JEBpMfXh/UZiYTO95I/L9IyVSHARYLYxljpWWtR/OYBhIkhDX2gfiTjQBlP+BF8ztLlhynwJtPISXlTYrAc7RC0KxJ4BxwbTjBaY+nkeoh3HSG4ACWMFiP8EEjpSEo9haSfy2QXjMa/+cvhrvg0PCglzdsYMW8yhUfyIiwYcT+rBXV7e5XHBxWrGjckiB19moDIo03j7na5eYGSIucpgIDqIfHWChPUo8o32DCKCpzqtURmr1P7eNa7y13w09XqWX0RAE1dupH6KaMWsnf7y53dEzJ54stVTcU+yyd7Tg2Hk52saaH21DDmCjlCtHBEd1PKLxo6SH6Zhgx3hFYDx1GJFoBbYGrbbEIGnOmzTaIxjLHexSwacZG9OtICggKf76U0q1uRq4fGqKxVU5qcRh718seCNssJB7uOEW40FjQ/yN4OBCAL9xBoT/xj0sZFgcjOp6D7sUExa5Jykq+s2vJj33FW8GTNNvog40y4R2sx59tMLjbo8KsJFDS8s/TsILtIkzhWPBujV3zf/9gNnHxlkdNabeDpkJMVkGymVwQvlaVfVvrF3Y8UxxTle9TroJQVs6ny4rEpITmnaxed0Son+Q/0/5wdLLZzvFNihzOpyHGsfEH+/cqtORVUOfOB1oLKXahAbuXcM3TL8p2HDzwfJFXp7p9Y82984pyE02GAwdL1sqWoAgjE1jEjva3E5IDXQeEF22lJ0oV7zWznFJlYUVJXtjImMPtWrY6Ai8B3zcGA0TF+aS8xqAqJ6FTMAChQfyw0TPiIArKgpvvVRe3DbMaOyxJ/+idHN847Y2xRtd5nLIThAzaSi01xRvCNOEa3Xlh8vyT/dq0EK+WFr4c+voBLsqSQdbN2ha1LB9m7Pm3oO5N261dgkPq4gjcJ/PFbm0+4O6jXn77cQzuYdvvVxZ1DnCFHbDibKimBtiGrSGq3i0TfaQBiCGSTpvZtGlY4mRMSoOph/DnsnJxlHxh3t0v/EwXi1e9RoPf1AMPzUHWgStX/n5B/9VTSz+Kz2pTSi16/i6pCSy4OJFURerEfo06+po6YvuVzubCMIQM6pZhmpnuJbrq8Hy3oULMVZvEcLBMBaeoBMfad4Nv4IkmG1TOiOuGbl6X4MUC1JD1S2CCQTLXV2qblb7cV5VDR/s+sp4/vIlpfDSZaEczxJMBrVHpy7iw7feE2q8AjVwxpDCUsiQQkhahzgCGembq6wb0wVYyTlTq/6M4Nh98agRb9RV7JUaoX2zcIXM2dXzVP2GhE8dx1/5QZI7aJv/H+y6kJy2/hwbAAAAAElFTkSuQmCC"},{"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}","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,"description":"Public domain street and address data from the San Juan County, WA. Updated at least quarterly."},{"id":"Vejmidte_Denmark","name":"Vejmidte","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","icon":"https://www.wien.gv.at/layout-a/logo/wappen-klein.gif"},{"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","icon":"https://www.wien.gv.at/layout-a/logo/wappen-klein.gif"},{"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","icon":"https://www.wien.gv.at/layout-a/logo/wappen-klein.gif"}];
18629 var presets = {"aerialway":{"fields":["aerialway"],"geometry":["point","vertex","line"],"tags":{"aerialway":"*"},"terms":["ski lift","funifor","funitel"],"searchable":false,"name":"Aerialway"},"aeroway":{"icon":"airport","fields":["aeroway"],"geometry":["point","vertex","line","area"],"tags":{"aeroway":"*"},"searchable":false,"name":"Aeroway"},"amenity":{"fields":["amenity"],"geometry":["point","vertex","area"],"tags":{"amenity":"*"},"searchable":false,"name":"Amenity"},"highway":{"fields":["highway"],"geometry":["point","vertex","line","area"],"tags":{"highway":"*"},"searchable":false,"name":"Highway"},"place":{"fields":["place"],"geometry":["point","vertex","area"],"tags":{"place":"*"},"searchable":false,"name":"Place"},"power":{"geometry":["point","vertex","line","area"],"tags":{"power":"*"},"fields":["power"],"searchable":false,"name":"Power"},"railway":{"fields":["railway"],"geometry":["point","vertex","line","area"],"tags":{"railway":"*"},"searchable":false,"name":"Railway"},"roundabout":{"geometry":["vertex","line"],"tags":{"junction":"roundabout"},"name":"Roundabout","searchable":false},"waterway":{"fields":["waterway"],"geometry":["point","vertex","line","area"],"tags":{"waterway":"*"},"searchable":false,"name":"Waterway"},"address":{"fields":["address"],"geometry":["point"],"tags":{"addr:housenumber":"*"},"addTags":{},"removeTags":{},"matchScore":0.2,"name":"Address"},"advertising/billboard":{"fields":["parallel_direction","lit"],"geometry":["point","vertex","line"],"tags":{"advertising":"billboard"},"name":"Billboard"},"aerialway/cable_car":{"geometry":["line"],"terms":["tramway","ropeway"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/heating"],"tags":{"aerialway":"cable_car"},"name":"Cable Car"},"aerialway/chair_lift":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"chair_lift"},"name":"Chair Lift"},"aerialway/drag_lift":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"drag_lift"},"name":"Drag Lift"},"aerialway/gondola":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"gondola"},"name":"Gondola"},"aerialway/goods":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"goods"},"name":"Goods Aerialway"},"aerialway/magic_carpet":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration","aerialway/heating"],"tags":{"aerialway":"magic_carpet"},"name":"Magic Carpet Lift"},"aerialway/mixed_lift":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"mixed_lift"},"name":"Mixed Lift"},"aerialway/platter":{"geometry":["line"],"terms":["button lift","poma lift"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"platter"},"name":"Platter Lift"},"aerialway/pylon":{"geometry":["point","vertex"],"fields":["ref"],"tags":{"aerialway":"pylon"},"name":"Aerialway Pylon"},"aerialway/rope_tow":{"geometry":["line"],"terms":["handle tow","bugel lift"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"rope_tow"},"name":"Rope Tow Lift"},"aerialway/station":{"icon":"aerialway","geometry":["point","vertex"],"fields":["aerialway/access","aerialway/summer/access","elevation"],"tags":{"aerialway":"station"},"name":"Aerialway Station"},"aerialway/t-bar":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"t-bar"},"name":"T-bar Lift"},"aeroway/aerodrome":{"icon":"airport","geometry":["point","area"],"fields":["ref","iata","icao","operator","internet_access","internet_access/fee","internet_access/ssid"],"terms":["airplane","airport","aerodrome"],"tags":{"aeroway":"aerodrome"},"name":"Airport"},"aeroway/apron":{"icon":"airport","geometry":["area"],"terms":["ramp"],"fields":["ref","surface"],"tags":{"aeroway":"apron"},"name":"Apron"},"aeroway/gate":{"icon":"airport","geometry":["point"],"fields":["ref"],"tags":{"aeroway":"gate"},"name":"Airport Gate"},"aeroway/hangar":{"geometry":["area"],"fields":["building_area"],"tags":{"aeroway":"hangar"},"name":"Hangar"},"aeroway/helipad":{"icon":"heliport","geometry":["point","area"],"fields":["ref"],"terms":["helicopter","helipad","heliport"],"tags":{"aeroway":"helipad"},"name":"Helipad"},"aeroway/runway":{"geometry":["line","area"],"terms":["landing strip"],"fields":["ref","surface","length","width"],"tags":{"aeroway":"runway"},"name":"Runway"},"aeroway/taxiway":{"geometry":["line"],"fields":["ref","surface"],"tags":{"aeroway":"taxiway"},"name":"Taxiway"},"aeroway/terminal":{"icon":"airport","geometry":["point","area"],"terms":["airport","aerodrome"],"fields":["operator","building_area"],"tags":{"aeroway":"terminal"},"name":"Airport Terminal"},"amenity/coworking_space":{"icon":"commercial","fields":["address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"geometry":["point","area"],"tags":{"amenity":"coworking_space"},"name":"Coworking Space","searchable":false},"amenity/nursing_home":{"icon":"wheelchair","fields":["operator","address","building_area","social_facility","social_facility_for","opening_hours","wheelchair"],"geometry":["point","area"],"tags":{"amenity":"nursing_home"},"reference":{"key":"social_facility","value":"nursing_home"},"name":"Nursing Home","searchable":false},"amenity/register_office":{"icon":"town-hall","fields":["address","building_area","opening_hours","operator"],"geometry":["point","area"],"tags":{"amenity":"register_office"},"reference":{"key":"government","value":"register_office"},"name":"Register Office","searchable":false},"amenity/swimming_pool":{"icon":"swimming","geometry":["point","vertex","area"],"tags":{"amenity":"swimming_pool"},"reference":{"key":"leisure","value":"swimming_pool"},"name":"Swimming Pool","searchable":false},"amenity/animal_boarding":{"icon":"veterinary","fields":["operator","address","building_area","opening_hours","animal_boarding"],"geometry":["point","area"],"terms":["boarding","cat","dog","horse","kitten","pet boarding","pet care","pet hotel","puppy","reptile"],"tags":{"amenity":"animal_boarding"},"name":"Animal Boarding Facility"},"amenity/animal_breeding":{"icon":"veterinary","fields":["operator","address","building_area","opening_hours","animal_breeding"],"geometry":["point","area"],"terms":["breeding","bull","cat","cow","dog","horse","husbandry","kitten","livestock","pet breeding","puppy","reptile"],"tags":{"amenity":"animal_breeding"},"name":"Animal Breeding Facility"},"amenity/animal_shelter":{"icon":"veterinary","fields":["operator","address","building_area","opening_hours","animal_shelter"],"geometry":["point","area"],"terms":["adoption","aspca","cat","dog","horse","kitten","pet care","pet rescue","puppy","raptor","reptile","rescue","spca"],"tags":{"amenity":"animal_shelter"},"name":"Animal Shelter"},"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":{"icon":"poi-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":{"icon":"poi-dice","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":{"icon":"poi-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/driving_school":{"icon":"car","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"amenity":"driving_school"},"name":"Driving School"},"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":{"icon":"poi-fountain","geometry":["point","area"],"tags":{"amenity":"fountain"},"name":"Fountain"},"amenity/fuel":{"icon":"fuel","fields":["operator","address","opening_hours","fuel_multi"],"geometry":["point","area"],"terms":["petrol","fuel","gasoline","propane","diesel","lng","cng","biodiesel"],"tags":{"amenity":"fuel"},"name":"Gas Station"},"amenity/grave_yard":{"icon":"cemetery","fields":["religion","denomination"],"geometry":["point","area"],"tags":{"amenity":"grave_yard"},"name":"Graveyard"},"amenity/grit_bin":{"fields":["access_simple"],"geometry":["point","vertex"],"tags":{"amenity":"grit_bin"},"terms":["salt","sand"],"name":"Grit Bin"},"amenity/hospital":{"icon":"hospital","fields":["operator","address","emergency"],"geometry":["point","area"],"terms":["clinic","doctor","emergency room","health","infirmary","institution","sanatorium","sanitarium","sick","surgery","ward"],"tags":{"amenity":"hospital"},"name":"Hospital Grounds"},"amenity/hunting_stand":{"icon":"poi-binoculars","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":{"icon":"poi-mast","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":{"icon":"shop","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"},"matchScore":0.95,"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/pavilion":{"icon":"shelter","fields":["bin","bench"],"geometry":["point","vertex","area"],"tags":{"amenity":"shelter","shelter_type":"pavilion"},"name":"Pavilion"},"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","service_times"],"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","service_times"],"geometry":["point","area"],"terms":["stupa","vihara","monastery","temple","pagoda","zendo","dojo"],"tags":{"amenity":"place_of_worship","religion":"buddhist"},"reference":{"key":"amenity","value":"place_of_worship"},"name":"Buddhist Temple"},"amenity/place_of_worship/christian":{"icon":"religious-christian","fields":["denomination","building_area","address","service_times"],"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"},"reference":{"key":"amenity","value":"place_of_worship"},"name":"Church"},"amenity/place_of_worship/jewish":{"icon":"religious-jewish","fields":["denomination","building_area","address","service_times"],"geometry":["point","area"],"terms":["jewish"],"tags":{"amenity":"place_of_worship","religion":"jewish"},"reference":{"key":"amenity","value":"place_of_worship"},"name":"Synagogue"},"amenity/place_of_worship/muslim":{"icon":"religious-muslim","fields":["denomination","building_area","address","service_times"],"geometry":["point","area"],"terms":["muslim"],"tags":{"amenity":"place_of_worship","religion":"muslim"},"reference":{"key":"amenity","value":"place_of_worship"},"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":{"icon":"poi-storage-tank","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/scrapyard":{"icon":"car","fields":["operator","address","opening_hours"],"geometry":["point","area"],"terms":["car","junk","metal","salvage","scrap","u-pull-it","vehicle","wreck","yard"],"tags":{"amenity":"scrapyard"},"reference":{"key":"industrial","value":"scrap_yard"},"name":"Scrap Yard"},"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":{"icon":"poi-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":{"icon":"poi-social-facility","fields":["operator","address","building_area","social_facility","social_facility_for","opening_hours"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"social_facility","social_facility":"food_bank"},"reference":{"key":"social_facility","value":"food_bank"},"name":"Food Bank"},"amenity/social_facility/group_home":{"icon":"wheelchair","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"},"reference":{"key":"social_facility","value":"group_home"},"name":"Elderly Group Home"},"amenity/social_facility/homeless_shelter":{"icon":"poi-social-facility","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"},"reference":{"key":"social_facility","value":"shelter"},"name":"Homeless Shelter"},"amenity/social_facility/nursing_home":{"icon":"wheelchair","fields":["operator","address","building_area","social_facility","social_facility_for","opening_hours","wheelchair"],"geometry":["point","area"],"terms":["elderly","living","nursing","old","senior"],"tags":{"amenity":"social_facility","social_facility":"nursing_home","social_facility:for":"senior"},"reference":{"key":"social_facility","value":"nursing_home"},"name":"Nursing Home"},"amenity/studio":{"icon":"karaoke","fields":["studio","address","building_area"],"geometry":["point","area"],"terms":["recording","radio","television"],"tags":{"amenity":"studio"},"name":"Studio"},"amenity/taxi":{"icon":"car","fields":["operator","capacity"],"geometry":["point","vertex","area"],"terms":["cab"],"tags":{"amenity":"taxi"},"name":"Taxi Stand"},"amenity/telephone":{"icon":"telephone","geometry":["point","vertex"],"tags":{"amenity":"telephone"},"terms":["phone"],"name":"Telephone"},"amenity/theatre":{"icon":"theatre","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":["theatre","performance","play","musical"],"tags":{"amenity":"theatre"},"name":"Theater"},"amenity/toilets":{"icon":"toilet","fields":["toilets/disposal","operator","building_area","access_toilets","gender","fee","diaper"],"geometry":["point","vertex","area"],"terms":["bathroom","restroom","outhouse","privy","head","lavatory","latrine","water closet","WC","W.C."],"tags":{"amenity":"toilets"},"name":"Toilets"},"amenity/townhall":{"icon":"town-hall","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":["village","city","government","courthouse","municipal"],"tags":{"amenity":"townhall"},"name":"Town Hall"},"amenity/university":{"icon":"college","fields":["operator","address","internet_access","internet_access/ssid"],"geometry":["point","area"],"terms":["college"],"tags":{"amenity":"university"},"name":"University Grounds"},"amenity/vending_machine":{"icon":"poi-vending-machine","fields":["vending","operator","payment_multi","currency_multi"],"geometry":["point"],"terms":[],"tags":{"amenity":"vending_machine"},"name":"Vending Machine"},"amenity/vending_machine/news_papers":{"icon":"poi-vending-machine","fields":["operator","fee","payment_multi","currency_multi"],"geometry":["point"],"terms":["newspaper"],"tags":{"amenity":"vending_machine","vending":"news_papers"},"reference":{"key":"vending","value":"newspapers"},"name":"Newspaper Vending Machine","searchable":false},"amenity/vending_machine/cigarettes":{"icon":"poi-vending-machine","fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["cigarette"],"tags":{"amenity":"vending_machine","vending":"cigarettes"},"reference":{"key":"vending","value":"cigarettes"},"name":"Cigarette Vending Machine"},"amenity/vending_machine/condoms":{"icon":"poi-vending-machine","fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["condom"],"tags":{"amenity":"vending_machine","vending":"condoms"},"reference":{"key":"vending","value":"condoms"},"name":"Condom Vending Machine"},"amenity/vending_machine/drinks":{"icon":"poi-vending-machine","fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["drink","soda","beverage","juice","pop"],"tags":{"amenity":"vending_machine","vending":"drinks"},"reference":{"key":"vending","value":"drinks"},"name":"Drink Vending Machine"},"amenity/vending_machine/excrement_bags":{"icon":"poi-vending-machine","fields":["operator","fee","bin","payment_multi","currency_multi"],"geometry":["point"],"terms":["excrement bags","poop","dog","animal"],"tags":{"amenity":"vending_machine","vending":"excrement_bags"},"reference":{"key":"vending","value":"excrement_bags"},"name":"Excrement Bag Vending Machine"},"amenity/vending_machine/newspapers":{"icon":"poi-vending-machine","fields":["operator","fee","payment_multi","currency_multi"],"geometry":["point"],"terms":["newspaper"],"tags":{"amenity":"vending_machine","vending":"newspapers"},"reference":{"key":"vending","value":"newspapers"},"name":"Newspaper Vending Machine"},"amenity/vending_machine/parcel_pickup_dropoff":{"icon":"poi-vending-machine","fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["parcel","mail","pickup"],"tags":{"amenity":"vending_machine","vending":"parcel_pickup;parcel_mail_in"},"reference":{"key":"vending","value":"parcel_pickup;parcel_mail_in"},"name":"Parcel Pickup/Dropoff Vending Machine"},"amenity/vending_machine/parking_tickets":{"icon":"poi-vending-machine","fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["parking","ticket"],"tags":{"amenity":"vending_machine","vending":"parking_tickets"},"reference":{"key":"vending","value":"parking_tickets"},"matchScore":0.94,"name":"Parking Ticket Vending Machine"},"amenity/vending_machine/public_transport_tickets":{"icon":"poi-vending-machine","fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["bus","train","ferry","rail","ticket","transportation"],"tags":{"amenity":"vending_machine","vending":"public_transport_tickets"},"reference":{"key":"vending","value":"public_transport_tickets"},"name":"Transit Ticket Vending Machine"},"amenity/vending_machine/sweets":{"icon":"poi-vending-machine","fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["candy","gum","chip","pretzel","cookie","cracker"],"tags":{"amenity":"vending_machine","vending":"sweets"},"reference":{"key":"vending","value":"sweets"},"name":"Snack 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"},"amenity/watering_place":{"icon":"drinking-water","geometry":["area","vertex","point"],"tags":{"amenity":"watering_place"},"name":"Animal Watering Place"},"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"},"club":{"icon":"heart","fields":["club","operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"club":"*"},"terms":["social"],"name":"Club"},"craft":{"icon":"poi-tool","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"},"reference":{"key":"shop","value":"jewelry"},"name":"Jeweler","searchable":false},"craft/locksmith":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"locksmith"},"reference":{"key":"shop","value":"locksmith"},"name":"Locksmith","searchable":false},"craft/optician":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"optician"},"reference":{"key":"shop","value":"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"},"reference":{"key":"shop","value":"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":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"blacksmith"},"name":"Blacksmith"},"craft/boatbuilder":{"icon":"poi-tool","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":"poi-storage-tank","fields":["operator","address","building_area","opening_hours","product"],"geometry":["point","area"],"terms":["alcohol","beer","beverage","bier","booze","cider"],"tags":{"craft":"brewery"},"name":"Brewery"},"craft/carpenter":{"icon":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["woodworker"],"tags":{"craft":"carpenter"},"name":"Carpenter"},"craft/carpet_layer":{"icon":"poi-tool","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":{"icon":"poi-clock","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/distillery":{"icon":"poi-storage-tank","fields":["operator","address","building_area","opening_hours","product"],"geometry":["point","area"],"terms":["alcohol","beverage","bourbon","booze","brandy","gin","hooch","liquor","mezcal","moonshine","rum","scotch","spirits","still","tequila","vodka","whiskey","whisky"],"tags":{"craft":"distillery"},"name":"Distillery"},"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":"poi-power","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["power","wire"],"tags":{"craft":"electrician"},"name":"Electrician"},"craft/electronics_repair":{"icon":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"electronics_repair"},"name":"Electronics Repair Shop"},"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":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["heat*","vent*","air conditioning"],"tags":{"craft":"hvac"},"name":"HVAC"},"craft/insulator":{"icon":"poi-tool","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":"poi-tool","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":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"plasterer"},"name":"Plasterer"},"craft/plumber":{"icon":"poi-tool","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":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"rigger"},"name":"Rigger"},"craft/roofer":{"icon":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"roofer"},"name":"Roofer"},"craft/saddler":{"icon":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"saddler"},"name":"Saddler"},"craft/sailmaker":{"icon":"poi-tool","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":"poi-tool","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":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["cobbler"],"tags":{"craft":"shoemaker"},"name":"Shoemaker"},"craft/stonemason":{"icon":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["masonry"],"tags":{"craft":"stonemason"},"name":"Stonemason"},"craft/sweep":{"icon":"poi-chimney","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"sweep"},"name":"Chimney Sweep"},"craft/tiler":{"icon":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"tiler"},"name":"Tiler"},"craft/tinsmith":{"icon":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"tinsmith"},"name":"Tinsmith"},"craft/upholsterer":{"icon":"poi-tool","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"upholsterer"},"name":"Upholsterer"},"craft/watchmaker":{"icon":"poi-clock","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"watchmaker"},"name":"Watchmaker"},"craft/window_construction":{"icon":"poi-tool","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":"poi-fire-hydrant","fields":["fire_hydrant/type","fire_hydrant/position","ref","operator"],"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"},"reference":{"key":"footway","value":"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"},"reference":{"key":"highway","value":"crossing"},"terms":["zebra crossing"],"name":"Pedestrian Crosswalk"},"footway/sidewalk":{"icon":"highway-footway","fields":["surface","lit","width","structure","access"],"geometry":["line"],"tags":{"highway":"footway","footway":"sidewalk"},"reference":{"key":"footway","value":"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"],"reference":{"key":"golf","value":"bunker"},"name":"Sand Trap"},"golf/fairway":{"icon":"golf","geometry":["area"],"tags":{"golf":"fairway","landuse":"grass"},"reference":{"key":"golf","value":"fairway"},"name":"Fairway"},"golf/green":{"icon":"golf","geometry":["area"],"tags":{"golf":"green","landuse":"grass","leisure":"pitch","sport":"golf"},"reference":{"key":"golf","value":"green"},"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"},"reference":{"key":"golf","value":"lateral_water_hazard"},"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"},"reference":{"key":"golf","value":"rough"},"name":"Rough"},"golf/tee":{"icon":"golf","geometry":["area"],"tags":{"golf":"tee","landuse":"grass"},"terms":["teeing ground"],"reference":{"key":"golf","value":"tee"},"name":"Tee Box"},"golf/water_hazard_area":{"icon":"golf","geometry":["area"],"tags":{"golf":"water_hazard","natural":"water"},"reference":{"key":"golf","value":"water_hazard"},"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"},"reference":{"key":"footway","value":"crossing"},"terms":[],"name":"Street Crossing"},"highway/crosswalk":{"icon":"poi-foot","fields":["crossing","kerb","tactile_paving"],"geometry":["vertex"],"tags":{"highway":"crossing","crossing":"zebra"},"reference":{"key":"highway","value":"crossing"},"terms":["zebra crossing"],"name":"Pedestrian Crosswalk"},"highway/cycleway":{"icon":"highway-cycleway","fields":["oneway","surface","lit","width","structure","access"],"geometry":["line"],"tags":{"highway":"cycleway"},"terms":["bike"],"name":"Cycle Path"},"highway/elevator":{"icon":"poi-elevator","fields":["access_simple","opening_hours","maxweight","ref"],"geometry":["vertex"],"tags":{"highway":"elevator"},"terms":["lift"],"name":"Elevator"},"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":{"icon":"poi-yield","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","lanes","surface","structure","maxheight","access","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":{"icon":"poi-junction","geometry":["vertex"],"tags":{"highway":"motorway_junction"},"fields":["ref"],"name":"Motorway Junction / Exit"},"highway/motorway_link":{"icon":"highway-motorway-link","fields":["ref","oneway_yes","maxspeed","lanes","surface","structure","maxheight","access"],"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":["ref","oneway_yes","maxspeed","lanes","surface","structure","maxheight","toll","access"],"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","lanes","surface","maxheight","ref","cycleway","structure","access"],"geometry":["line"],"tags":{"highway":"primary_link"},"terms":["ramp","on ramp","off ramp"],"name":"Primary Link"},"highway/primary":{"icon":"highway-primary","fields":["oneway","maxspeed","lanes","surface","structure","maxheight","ref","cycleway","access"],"geometry":["line"],"tags":{"highway":"primary"},"terms":[],"name":"Primary Road"},"highway/raceway":{"icon":"highway-unclassified","fields":["oneway","surface","sport_racing_motor","lit","width","lanes","structure"],"geometry":["point","line","area"],"tags":{"highway":"raceway"},"addTags":{"highway":"raceway","sport":"motor"},"terms":["auto*","formula one","kart","motocross","nascar","race*","track"],"name":"Racetrack (Motorsport)"},"highway/residential":{"icon":"highway-residential","fields":["oneway","maxspeed","lanes","surface","structure","maxheight","cycleway","access"],"geometry":["line"],"tags":{"highway":"residential"},"terms":[],"name":"Residential Road"},"highway/rest_area":{"icon":"car","geometry":["point","vertex","area"],"tags":{"highway":"rest_area"},"terms":["rest stop"],"name":"Rest Area"},"highway/road":{"icon":"highway-road","fields":["oneway","maxspeed","lanes","surface","structure","maxheight","access"],"geometry":["line"],"tags":{"highway":"road"},"terms":[],"name":"Unknown Road"},"highway/secondary_link":{"icon":"highway-secondary-link","fields":["oneway","maxspeed","lanes","surface","structure","maxheight","ref","cycleway","access"],"geometry":["line"],"tags":{"highway":"secondary_link"},"terms":["ramp","on ramp","off ramp"],"name":"Secondary Link"},"highway/secondary":{"icon":"highway-secondary","fields":["oneway","maxspeed","lanes","surface","structure","maxheight","ref","cycleway","access"],"geometry":["line"],"tags":{"highway":"secondary"},"terms":[],"name":"Secondary Road"},"highway/service":{"icon":"highway-service","fields":["service","oneway","maxspeed","surface","structure","maxheight","access"],"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"},"reference":{"key":"service","value":"alley"},"name":"Alley"},"highway/service/drive-through":{"icon":"highway-service","fields":["oneway","covered","maxheight","maxspeed","structure","access","surface"],"geometry":["line"],"tags":{"highway":"service","service":"drive-through"},"reference":{"key":"service","value":"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"},"reference":{"key":"service","value":"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"},"reference":{"key":"service","value":"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"},"reference":{"key":"service","value":"parking_aisle"},"name":"Parking Aisle"},"highway/services":{"icon":"car","geometry":["point","vertex","area"],"tags":{"highway":"services"},"terms":["services","travel plaza","service station"],"name":"Service Area"},"highway/speed_camera":{"icon":"attraction","geometry":["point"],"fields":["ref"],"tags":{"highway":"speed_camera"},"terms":[],"name":"Speed Camera"},"highway/steps":{"icon":"highway-steps","fields":["surface","lit","width","incline_steps","handrail","step_count"],"geometry":["line"],"tags":{"highway":"steps"},"terms":["stairs","staircase"],"name":"Steps"},"highway/stop":{"icon":"poi-stop","fields":["stop","parallel_direction"],"geometry":["vertex"],"tags":{"highway":"stop"},"terms":["stop","halt","sign"],"name":"Stop Sign"},"highway/street_lamp":{"icon":"poi-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","lanes","surface","structure","maxheight","ref","cycleway","access"],"geometry":["line"],"tags":{"highway":"tertiary_link"},"terms":["ramp","on ramp","off ramp"],"name":"Tertiary Link"},"highway/tertiary":{"icon":"highway-tertiary","fields":["oneway","maxspeed","lanes","surface","structure","maxheight","ref","cycleway","access"],"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":{"icon":"poi-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":["ref","oneway","maxspeed","lanes","surface","structure","maxheight","access"],"geometry":["line"],"tags":{"highway":"trunk_link"},"terms":["ramp","on ramp","off ramp"],"name":"Trunk Link"},"highway/trunk":{"icon":"highway-trunk","fields":["ref","oneway","maxspeed","lanes","surface","structure","maxheight","toll","access"],"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","lanes","surface","structure","maxheight","cycleway","access"],"geometry":["line"],"tags":{"highway":"unclassified"},"terms":[],"name":"Minor/Unclassified Road"},"historic":{"icon":"poi-ruins","fields":["historic","inscription"],"geometry":["point","vertex","area"],"tags":{"historic":"*"},"name":"Historic Site"},"historic/archaeological_site":{"icon":"poi-ruins","fields":["historic/civilization","inscription"],"geometry":["point","vertex","area"],"tags":{"historic":"archaeological_site"},"name":"Archaeological Site"},"historic/boundary_stone":{"icon":"monument","fields":["inscription"],"geometry":["point","vertex"],"tags":{"historic":"boundary_stone"},"name":"Boundary Stone"},"historic/castle":{"icon":"castle","fields":["castle_type","building_area","historic/civilization"],"geometry":["point","area"],"tags":{"historic":"castle"},"name":"Castle"},"historic/memorial":{"icon":"monument","fields":["inscription"],"geometry":["point","vertex","area"],"tags":{"historic":"memorial"},"name":"Memorial"},"historic/monument":{"icon":"monument","fields":["inscription"],"geometry":["point","vertex","area"],"tags":{"historic":"monument"},"name":"Monument"},"historic/ruins":{"icon":"poi-ruins","fields":["historic/civilization","inscription"],"geometry":["point","vertex","area"],"tags":{"historic":"ruins"},"name":"Ruins"},"historic/tomb":{"icon":"cemetery","fields":["tomb","building_area","inscription"],"geometry":["point","area"],"tags":{"historic":"tomb"},"name":"Tomb"},"historic/wayside_cross":{"icon":"religious-christian","fields":["inscription"],"geometry":["point","vertex","area"],"tags":{"historic":"wayside_cross"},"name":"Wayside Cross"},"historic/wayside_shrine":{"icon":"landmark","fields":["inscription"],"geometry":["point","vertex","area"],"tags":{"historic":"wayside_shrine"},"name":"Wayside Shrine"},"junction":{"icon":"poi-junction","geometry":["vertex","area"],"tags":{"junction":"yes"},"name":"Junction"},"landuse":{"fields":["landuse"],"geometry":["area"],"tags":{"landuse":"*"},"matchScore":0.9,"name":"Land Use"},"landuse/farm":{"icon":"farm","fields":["operator","crop"],"geometry":["point","area"],"tags":{"landuse":"farm"},"terms":[],"name":"Farmland","searchable":false},"landuse/allotments":{"geometry":["area"],"tags":{"landuse":"allotments"},"terms":["allotment","garden"],"name":"Community Garden"},"landuse/aquaculture":{"icon":"aquarium","fields":["operator","produce"],"geometry":["area"],"tags":{"landuse":"aquaculture"},"terms":["fish farm","crustacean","algae","aquafarming","shrimp farm","oyster farm","mariculture","algaculture"],"name":"Aquaculture"},"landuse/basin":{"icon":"water","geometry":["area"],"tags":{"landuse":"basin"},"terms":[],"name":"Basin"},"landuse/cemetery":{"icon":"cemetery","fields":["religion","denomination"],"geometry":["area"],"tags":{"landuse":"cemetery"},"terms":[],"name":"Cemetery"},"landuse/churchyard":{"fields":["religion","denomination"],"geometry":["area"],"tags":{"landuse":"churchyard"},"terms":[],"name":"Churchyard"},"landuse/commercial":{"icon":"commercial","geometry":["area"],"tags":{"landuse":"commercial"},"terms":[],"name":"Commercial Area"},"landuse/construction":{"fields":["construction","operator"],"geometry":["area"],"tags":{"landuse":"construction"},"terms":[],"name":"Construction"},"landuse/farmland":{"icon":"farm","fields":["operator","crop","produce"],"geometry":["area"],"tags":{"landuse":"farmland"},"terms":["crop","grow","plant"],"name":"Farmland"},"landuse/farmyard":{"icon":"farm","fields":["operator","crop"],"geometry":["area"],"tags":{"landuse":"farmyard"},"terms":["crop","grow","plant"],"name":"Farmyard"},"landuse/forest":{"icon":"park-alt1","fields":["leaf_type","leaf_cycle","produce"],"geometry":["area"],"tags":{"landuse":"forest"},"terms":["tree"],"name":"Forest"},"landuse/garages":{"geometry":["area"],"tags":{"landuse":"garages"},"terms":[],"name":"Garages"},"landuse/grass":{"geometry":["area"],"tags":{"landuse":"grass"},"terms":[],"name":"Grass"},"landuse/harbour":{"icon":"harbor","fields":["operator"],"geometry":["area"],"terms":["boat"],"tags":{"landuse":"harbour"},"name":"Harbor"},"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":{"icon":"poi-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":{"icon":"poi-military","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":{"icon":"poi-military","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":{"icon":"barrier","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":{"icon":"poi-military","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":{"icon":"poi-military","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":{"icon":"poi-military","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":{"icon":"poi-military","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":{"icon":"poi-military","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/railway":{"icon":"rail","fields":["operator"],"geometry":["area"],"tags":{"landuse":"railway"},"terms":["rail","train","track"],"name":"Railway Corridor"},"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","grape_variety"],"geometry":["area"],"tags":{"landuse":"vineyard"},"addTags":{"landuse":"vineyard","crop":"grape"},"removeTags":{"landuse":"vineyard","crop":"grape","grape_variety":"*"},"terms":["grape","wine"],"name":"Vineyard"},"leisure":{"icon":"pitch","fields":["leisure"],"geometry":["point","vertex","area"],"tags":{"leisure":"*"},"name":"Leisure"},"leisure/adult_gaming_centre":{"icon":"poi-dice","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":{"icon":"poi-binoculars","fields":["building_area"],"geometry":["point","area"],"tags":{"leisure":"bird_hide"},"terms":["machan","ornithology"],"name":"Bird Hide"},"leisure/bowling_alley":{"icon":"poi-bowling","fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"terms":[],"tags":{"leisure":"bowling_alley"},"name":"Bowling Alley"},"leisure/common":{"icon":"poi-foot","geometry":["point","area"],"terms":["open space"],"tags":{"leisure":"common"},"name":"Common"},"leisure/dance":{"icon":"music","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":{"icon":"fire-station","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"},"reference":{"key":"sport","value":"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"},"reference":{"key":"sport","value":"american_football"},"terms":[],"name":"American Football Field"},"leisure/pitch/baseball":{"icon":"baseball","fields":["lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"baseball"},"reference":{"key":"sport","value":"baseball"},"terms":[],"name":"Baseball Diamond"},"leisure/pitch/basketball":{"icon":"basketball","fields":["surface","hoops","lit","access_simple"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"basketball"},"reference":{"key":"sport","value":"basketball"},"terms":[],"name":"Basketball Court"},"leisure/pitch/beachvolleyball":{"icon":"basketball","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"beachvolleyball"},"addTags":{"leisure":"pitch","sport":"beachvolleyball","surface":"sand"},"removeTags":{"leisure":"pitch","sport":"beachvolleyball","surface":"sand"},"reference":{"key":"sport","value":"beachvolleyball"},"terms":["volleyball"],"name":"Beach Volleyball Court"},"leisure/pitch/bowls":{"icon":"pitch","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"bowls"},"reference":{"key":"sport","value":"bowls"},"terms":[],"name":"Bowling Green"},"leisure/pitch/cricket":{"icon":"cricket","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"cricket"},"reference":{"key":"sport","value":"cricket"},"terms":[],"name":"Cricket Field"},"leisure/pitch/equestrian":{"icon":"horse-riding","fields":["surface","lit","building"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"equestrian"},"reference":{"key":"sport","value":"equestrian"},"terms":["dressage","equestrian","horse","horseback","riding"],"name":"Riding Arena"},"leisure/pitch/rugby_league":{"icon":"america-football","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"rugby_league"},"reference":{"key":"sport","value":"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"},"reference":{"key":"sport","value":"rugby_union"},"terms":[],"name":"Rugby Union Field"},"leisure/pitch/skateboard":{"icon":"pitch","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"skateboard"},"reference":{"key":"sport","value":"skateboard"},"terms":[],"name":"Skate Park"},"leisure/pitch/soccer":{"icon":"soccer","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"soccer"},"reference":{"key":"sport","value":"soccer"},"terms":["football"],"name":"Soccer Field"},"leisure/pitch/table_tennis":{"icon":"tennis","fields":["lit","access_simple"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"table_tennis"},"reference":{"key":"sport","value":"table_tennis"},"terms":["table tennis","ping pong"],"name":"Ping Pong Table"},"leisure/pitch/tennis":{"icon":"tennis","fields":["surface","lit","access_simple"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"tennis"},"reference":{"key":"sport","value":"tennis"},"terms":[],"name":"Tennis Court"},"leisure/pitch/volleyball":{"icon":"basketball","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"volleyball"},"reference":{"key":"sport","value":"volleyball"},"terms":[],"name":"Volleyball Court"},"leisure/playground":{"icon":"playground","geometry":["point","area"],"terms":["jungle gym","play area"],"tags":{"leisure":"playground"},"name":"Playground"},"leisure/resort":{"icon":"lodging","fields":["operator","address","opening_hours"],"geometry":["point","area"],"tags":{"leisure":"resort"},"name":"Resort"},"leisure/running_track":{"icon":"pitch","fields":["surface","sport_racing_nonmotor","lit","width","lanes"],"geometry":["point","line","area"],"tags":{"leisure":"track","sport":"running"},"terms":["race*","running","sprint","track"],"name":"Racetrack (Running)"},"leisure/slipway":{"icon":"poi-beach","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"},"reference":{"key":"sport","value":"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_nonmotor","lit","width","lanes"],"geometry":["point","line","area"],"tags":{"leisure":"track"},"terms":["cycle","dog","greyhound","horse","race*","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":{"icon":"poi-storage-tank","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":{"icon":"triangle","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":{"icon":"poi-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":{"icon":"poi-storage-tank","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":{"icon":"poi-mast","fields":["tower/type","tower/construction","height","communication_multi"],"geometry":["point"],"terms":["antenna","broadcast tower","cell phone tower","cell tower","communication mast","communication tower","guyed tower","mobile phone tower","radio mast","radio tower","television tower","transmission mast","transmission tower","tv tower"],"tags":{"man_made":"mast"},"name":"Mast"},"man_made/observation":{"icon":"poi-tower","geometry":["point","area"],"terms":["lookout tower","fire tower"],"tags":{"man_made":"tower","tower:type":"observation"},"name":"Observation Tower"},"man_made/petroleum_well":{"icon":"poi-storage-tank","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":{"icon":"water","geometry":["point","area"],"tags":{"man_made":"pumping_station"},"name":"Pumping Station"},"man_made/silo":{"icon":"poi-silo","fields":["building_area","crop"],"geometry":["point","area"],"terms":["grain","corn","wheat"],"tags":{"man_made":"silo"},"name":"Silo"},"man_made/storage_tank":{"icon":"poi-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":{"icon":"poi-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"},"manhole":{"icon":"circle-stroked","fields":["manhole","operator","label","ref"],"geometry":["point","vertex"],"tags":{"manhole":"*"},"terms":["cover","hole","sewer","sewage","telecom"],"name":"Manhole"},"manhole/drain":{"icon":"water","fields":["operator","ref"],"geometry":["point","vertex"],"tags":{"manhole":"drain"},"terms":["cover","drain","hole","rain","sewer","sewage","storm"],"name":"Storm Drain"},"natural":{"icon":"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":{"icon":"poi-beach","geometry":["point","area"],"tags":{"natural":"bay"},"terms":[],"name":"Bay"},"natural/beach":{"icon":"poi-beach","fields":["surface"],"geometry":["point","area"],"tags":{"natural":"beach"},"terms":["shore"],"name":"Beach"},"natural/cave_entrance":{"icon":"triangle","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":{"icon":"water","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"},"reference":{"key":"natural","value":"water"},"terms":["lakelet","loch","mere"],"name":"Lake"},"natural/water/pond":{"icon":"water","geometry":["area"],"tags":{"natural":"water","water":"pond"},"reference":{"key":"natural","value":"water"},"terms":["lakelet","millpond","tarn","pool","mere"],"name":"Pond"},"natural/water/reservoir":{"icon":"water","geometry":["area"],"tags":{"natural":"water","water":"reservoir"},"reference":{"key":"natural","value":"water"},"name":"Reservoir"},"natural/wetland":{"icon":"wetland","fields":["wetland"],"geometry":["point","area"],"tags":{"natural":"wetland"},"terms":[],"name":"Wetland"},"natural/wood":{"icon":"park-alt1","fields":["leaf_type","leaf_cycle"],"geometry":["point","area"],"tags":{"natural":"wood"},"terms":["tree"],"name":"Wood"},"noexit/yes":{"icon":"barrier","geometry":["vertex"],"terms":["no exit","road end","dead end"],"tags":{"noexit":"yes"},"reference":{"key":"noexit","value":"*"},"name":"No Exit"},"office":{"icon":"commercial","fields":["office","address","building_area","opening_hours","smoking"],"geometry":["point","vertex","area"],"tags":{"office":"*"},"terms":[],"name":"Office"},"office/travel_agent":{"icon":"suitcase","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"travel_agent"},"reference":{"key":"shop","value":"travel_agency"},"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"},"reference":{"key":"amenity","value":"coworking_space"},"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"},"reference":{"key":"government","value":"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"},"reference":{"key":"office","value":"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/farm":{"icon":"farm","geometry":["point","area"],"tags":{"place":"farm"},"name":"Farm","searchable":false},"place/city":{"icon":"city","fields":["population"],"geometry":["point","area"],"tags":{"place":"city"},"name":"City"},"place/hamlet":{"icon":"triangle-stroked","fields":["population"],"geometry":["point","area"],"tags":{"place":"hamlet"},"name":"Hamlet"},"place/island":{"icon":"mountain","geometry":["point","area"],"terms":["archipelago","atoll","bar","cay","isle","islet","key","reef"],"tags":{"place":"island"},"name":"Island"},"place/isolated_dwelling":{"icon":"home","geometry":["point","area"],"tags":{"place":"isolated_dwelling"},"name":"Isolated Dwelling"},"place/locality":{"icon":"triangle-stroked","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/quarter":{"icon":"triangle-stroked","fields":["population"],"geometry":["point","area"],"tags":{"place":"quarter"},"terms":["boro","borough","quarter"],"name":"Sub-Borough / Quarter"},"place/square":{"icon":"poi-foot","geometry":["point","area"],"tags":{"place":"square"},"name":"Square"},"place/suburb":{"icon":"triangle-stroked","fields":["population"],"geometry":["point","area"],"tags":{"place":"suburb"},"terms":["boro","borough","quarter"],"name":"Borough / Suburb"},"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"},"reference":{"key":"power","value":"substation"},"name":"Substation","searchable":false},"power/generator":{"icon":"poi-power","fields":["operator","generator/source","generator/method","generator/type"],"geometry":["point","vertex","area"],"terms":["hydro","solar","turbine","wind"],"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":{"icon":"poi-power","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":{"icon":"poi-power","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","vertex"],"tags":{"railway":"subway_entrance"},"terms":["metro","transit"],"name":"Subway Entrance"},"railway/subway":{"icon":"railway-subway","geometry":["line"],"tags":{"railway":"subway"},"fields":["structure","gauge","electrified","service_rail"],"terms":["metro","transit"],"name":"Subway"},"railway/tram_stop":{"icon":"rail-light","fields":["network","operator"],"geometry":["vertex"],"tags":{"railway":"tram_stop"},"terms":["light rail","streetcar","tram","trolley"],"name":"Tram Stop"},"railway/tram":{"icon":"railway-light-rail","geometry":["line"],"tags":{"railway":"tram"},"fields":["structure","gauge","electrified","service_rail"],"terms":["light rail","streetcar","tram","trolley"],"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"},"reference":{"key":"shop","value":"seafood"},"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/appliance":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["air conditioner","appliance","dishwasher","dryer","freezer","fridge","grill","kitchen","oven","refrigerator","stove","washer","washing machine"],"tags":{"shop":"appliance"},"name":"Appliance Store"},"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"},"reference":{"key":"shop","value":"beauty"},"name":"Nail Salon"},"shop/beauty/tanning":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"beauty","beauty":"tanning"},"reference":{"key":"leisure","value":"tanning_salon"},"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","service/vehicle"],"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","service/vehicle"],"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":"poi-tool","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","blueray","camera","computer","dvd","home theater","radio","speaker","tv","video"],"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/gas":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["cng","lpg","natural gas","propane","refill","tank"],"tags":{"shop":"gas"},"name":"Bottled Gas Shop"},"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":"poi-tool","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/perfumery":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"perfumery"},"name":"Perfume Store"},"shop/pet":{"icon":"dog-park","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["animal","cat","dog","fish","kitten","puppy","reptile"],"tags":{"shop":"pet"},"name":"Pet Store"},"shop/photo":{"icon":"attraction","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["camera","film"],"tags":{"shop":"photo"},"name":"Photography Store"},"shop/pyrotechnics":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"pyrotechnics"},"name":"Fireworks Store"},"shop/radiotechnics":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"radiotechnics"},"name":"Radio/Electronic Component Store"},"shop/religion":{"icon":"shop","fields":["operator","address","building_area","opening_hours","religion","denomination"],"geometry":["point","area"],"tags":{"shop":"religion"},"name":"Religious Store"},"shop/scuba_diving":{"icon":"swimming","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"scuba_diving"},"name":"Scuba Diving Shop"},"shop/seafood":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["fishmonger"],"tags":{"shop":"seafood"},"name":"Seafood Shop"},"shop/second_hand":{"icon":"shop","fields":["operator","address","building_area","opening_hours","second_hand"],"geometry":["point","area"],"terms":["secondhand","second hand","resale","thrift","used"],"tags":{"shop":"second_hand"},"name":"Consignment/Thrift Store"},"shop/shoes":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"shoes"},"name":"Shoe Store"},"shop/sports":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"sports"},"name":"Sporting Goods Store"},"shop/stationery":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["card","paper"],"tags":{"shop":"stationery"},"name":"Stationery Store"},"shop/storage_rental":{"icon":"shop","fields":["operator","address","building","opening_hours"],"geometry":["point","area"],"tags":{"shop":"storage_rental"},"name":"Storage Rental"},"shop/supermarket":{"icon":"grocery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["grocery","store","shop"],"tags":{"shop":"supermarket"},"name":"Supermarket"},"shop/tailor":{"icon":"clothing-store","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["clothes","suit"],"tags":{"shop":"tailor"},"name":"Tailor"},"shop/tattoo":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"tattoo"},"name":"Tattoo Parlor"},"shop/tea":{"icon":"teahouse","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"tea"},"name":"Tea Store"},"shop/ticket":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"ticket"},"name":"Ticket Seller"},"shop/tobacco":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"tobacco"},"name":"Tobacco Shop"},"shop/toys":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"toys"},"name":"Toy Store"},"shop/travel_agency":{"icon":"suitcase","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"travel_agency"},"name":"Travel Agency"},"shop/tyres":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"tyres"},"name":"Tire Store"},"shop/vacuum_cleaner":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"vacuum_cleaner"},"name":"Vacuum Cleaner Store"},"shop/variety_store":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"variety_store"},"name":"Variety Store"},"shop/video_games":{"icon":"gaming","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"video_games"},"name":"Video Game Store"},"shop/video":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["DVD"],"tags":{"shop":"video"},"name":"Video Store"},"shop/watches":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"watches"},"name":"Watches Shop"},"shop/water_sports":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"water_sports"},"name":"Watersport/Swim Shop"},"shop/weapons":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["ammo","gun","knife","knives"],"tags":{"shop":"weapons"},"name":"Weapon Shop"},"shop/window_blind":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"window_blind"},"name":"Window Blind Store"},"shop/wine":{"icon":"alcohol-shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"wine"},"name":"Wine Shop"},"tourism":{"icon":"attraction","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"},"reference":{"key":"information","value":"board"},"name":"Information Board"},"tourism/information/guidepost":{"icon":"information","fields":["operator","ref"],"geometry":["point","vertex"],"tags":{"tourism":"information","information":"guidepost"},"reference":{"key":"information","value":"guidepost"},"name":"Guidepost"},"tourism/information/map":{"icon":"information","fields":["operator","map_type","map_size"],"geometry":["point","vertex"],"tags":{"tourism":"information","information":"map"},"reference":{"key":"information","value":"map"},"name":"Map"},"tourism/information/office":{"icon":"information","fields":["operator","address","building_area"],"geometry":["point","vertex","area"],"tags":{"tourism":"information","information":"office"},"reference":{"key":"information","value":"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":{"icon":"poi-binoculars","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":{"icon":"poi-warning","fields":["traffic_calming","parallel_direction"],"geometry":["vertex","line"],"tags":{"traffic_calming":"*"},"terms":["bump","hump","slow","speed"],"name":"Traffic Calming"},"traffic_calming/bump":{"icon":"poi-warning","fields":["surface","parallel_direction"],"geometry":["vertex","line"],"terms":["hump","speed","slow"],"tags":{"traffic_calming":"bump"},"name":"Speed Bump"},"traffic_calming/chicane":{"icon":"poi-warning","fields":["parallel_direction"],"geometry":["vertex","line"],"terms":["driveway link","speed","slow"],"tags":{"traffic_calming":"chicane"},"name":"Traffic Chicane"},"traffic_calming/choker":{"icon":"poi-warning","fields":["parallel_direction"],"geometry":["vertex","line"],"terms":["speed","slow"],"tags":{"traffic_calming":"choker"},"name":"Traffic Choker"},"traffic_calming/cushion":{"icon":"poi-warning","fields":["surface","parallel_direction"],"geometry":["vertex","line"],"terms":["bump","hump","speed","slow"],"tags":{"traffic_calming":"cushion"},"name":"Speed Cushion"},"traffic_calming/dip":{"icon":"poi-warning","fields":["surface","parallel_direction"],"geometry":["vertex","line"],"terms":["speed","slow"],"tags":{"traffic_calming":"dip"},"name":"Dip"},"traffic_calming/hump":{"icon":"poi-warning","fields":["surface","parallel_direction"],"geometry":["vertex","line"],"terms":["bump","speed","slow"],"tags":{"traffic_calming":"hump"},"name":"Speed Hump"},"traffic_calming/island":{"icon":"poi-warning","geometry":["vertex"],"terms":["circle","roundabout","slow"],"tags":{"traffic_calming":"island"},"name":"Traffic Island"},"traffic_calming/rumble_strip":{"icon":"poi-warning","fields":["parallel_direction"],"geometry":["vertex","line"],"terms":["audible lines","sleeper lines","growlers"],"tags":{"traffic_calming":"rumble_strip"},"name":"Rumble Strip"},"traffic_calming/table":{"icon":"poi-warning","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":{"icon":"boundary","fields":["admin_level"],"geometry":["relation"],"tags":{"type":"boundary","boundary":"administrative"},"reference":{"key":"boundary","value":"administrative"},"name":"Administrative 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":{"icon":"poi-storage-tank","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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"suggestion":true},"shop/car_repair/Шиномонтаж":{"tags":{"name":"Шиномонтаж","shop":"car_repair"},"name":"Шиномонтаж","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","service/vehicle"],"suggestion":true},"shop/car_repair/СТО":{"tags":{"name":"СТО","shop":"car_repair"},"name":"СТО","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"suggestion":true},"shop/car_repair/шиномонтаж":{"tags":{"name":"шиномонтаж","shop":"car_repair"},"name":"шиномонтаж","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"suggestion":true},"shop/car_repair/Автосервис":{"tags":{"name":"Автосервис","shop":"car_repair"},"name":"Автосервис","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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":"poi-tool","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":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hubo":{"tags":{"name":"Hubo","shop":"doityourself"},"name":"Hubo","icon":"poi-tool","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":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Gamma":{"tags":{"name":"Gamma","shop":"doityourself"},"name":"Gamma","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/OBI":{"tags":{"name":"OBI","shop":"doityourself"},"name":"OBI","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Lowes":{"tags":{"name":"Lowes","shop":"doityourself"},"name":"Lowes","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Wickes":{"tags":{"name":"Wickes","shop":"doityourself"},"name":"Wickes","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hagebau":{"tags":{"name":"Hagebau","shop":"doityourself"},"name":"Hagebau","icon":"poi-tool","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":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Castorama":{"tags":{"name":"Castorama","shop":"doityourself"},"name":"Castorama","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Rona":{"tags":{"name":"Rona","shop":"doityourself"},"name":"Rona","icon":"poi-tool","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":"poi-tool","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":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Homebase":{"tags":{"name":"Homebase","shop":"doityourself"},"name":"Homebase","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Baumax":{"tags":{"name":"Baumax","shop":"doityourself"},"name":"Baumax","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Lagerhaus":{"tags":{"name":"Lagerhaus","shop":"doityourself"},"name":"Lagerhaus","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Bauhaus":{"tags":{"name":"Bauhaus","shop":"doityourself"},"name":"Bauhaus","icon":"poi-tool","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":"poi-tool","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":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hellweg":{"tags":{"name":"Hellweg","shop":"doityourself"},"name":"Hellweg","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Brico":{"tags":{"name":"Brico","shop":"doityourself"},"name":"Brico","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Bricomarché":{"tags":{"name":"Bricomarché","shop":"doityourself"},"name":"Bricomarché","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Toom":{"tags":{"name":"Toom","shop":"doityourself"},"name":"Toom","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hagebaumarkt":{"tags":{"name":"Hagebaumarkt","shop":"doityourself"},"name":"Hagebaumarkt","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Praktiker":{"tags":{"name":"Praktiker","shop":"doityourself"},"name":"Praktiker","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Menards":{"tags":{"name":"Menards","shop":"doityourself"},"name":"Menards","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Weldom":{"tags":{"name":"Weldom","shop":"doityourself"},"name":"Weldom","icon":"poi-tool","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":"poi-tool","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":"poi-tool","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":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Стройматериалы":{"tags":{"name":"Стройматериалы","shop":"doityourself"},"name":"Стройматериалы","icon":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Bricorama":{"tags":{"name":"Bricorama","shop":"doityourself"},"name":"Bricorama","icon":"poi-tool","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":"poi-tool","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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"suggestion":true},"shop/car/Автозапчасти":{"tags":{"name":"Автозапчасти","shop":"car"},"name":"Автозапчасти","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"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","service/vehicle"],"suggestion":true},"shop/car/Автомагазин":{"tags":{"name":"Автомагазин","shop":"car"},"name":"Автомагазин","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand","service/vehicle"],"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":"poi-tool","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hardware/Хозтовары":{"tags":{"name":"Хозтовары","shop":"hardware"},"name":"Хозтовары","icon":"poi-tool","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}};
18631 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","highway/turning_loop","traffic_calming","highway/mini_roundabout","highway/motorway_junction","vertex"],"relation":["category-route","category-restriction","type/boundary","type/multipolygon","type/site","relation"]};
18633 var categories = {"category-barrier":{"icon":"roadblock","geometry":"line","name":"Barrier Features","members":["barrier/fence","barrier/wall","barrier/ditch","barrier/gate","barrier"]},"category-building":{"icon":"building","geometry":"area","name":"Building Features","members":["building","building/house","building/apartments","building/commercial","building/industrial","building/residential"]},"category-golf":{"icon":"golf","geometry":"area","name":"Golf Features","members":["golf/fairway","golf/green","golf/lateral_water_hazard_area","golf/rough","golf/bunker","golf/tee","golf/water_hazard_area"]},"category-landuse":{"icon":"landuse","geometry":"area","name":"Land Use Features","members":["landuse/residential","landuse/industrial","landuse/commercial","landuse/retail","landuse/farmland","landuse/farmyard","landuse/forest","landuse/meadow","landuse/aquaculture","landuse/cemetery","landuse/military"]},"category-natural-area":{"icon":"natural","geometry":"area","name":"Natural Features","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":{"icon":"natural","geometry":"line","name":"Natural Features","members":["natural/coastline","natural/tree_row"]},"category-natural-point":{"icon":"natural","geometry":"point","name":"Natural Features","members":["natural/peak","natural/cliff","natural/beach","natural/cave_entrance"]},"category-path":{"icon":"category-path","geometry":"line","name":"Path Features","members":["footway/crosswalk","footway/sidewalk","highway/steps","highway/path","highway/footway","highway/cycleway","highway/bridleway","highway/pedestrian"]},"category-rail":{"icon":"category-rail","geometry":"line","name":"Rail Features","members":["railway/rail","railway/subway","railway/tram","railway/monorail","railway/disused","railway/abandoned"]},"category-restriction":{"icon":"restriction","geometry":"relation","name":"Restriction Features","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":{"icon":"category-roads","geometry":"line","name":"Road Features","members":["highway/residential","highway/motorway","highway/trunk","highway/primary","highway/secondary","highway/tertiary","highway/living_street","highway/unclassified","highway/service","highway/track","highway/motorway_link","highway/trunk_link","highway/primary_link","highway/secondary_link","highway/tertiary_link","highway/road"]},"category-route":{"icon":"route","geometry":"relation","name":"Route Features","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":{"icon":"water","geometry":"area","name":"Water Features","members":["natural/water/lake","natural/water/pond","natural/water/reservoir","natural/water"]},"category-water-line":{"icon":"category-water","geometry":"line","name":"Water Features","members":["waterway/river","waterway/stream","waterway/canal","waterway/ditch","waterway/drain"]}};
18635 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"},"animal_boarding":{"key":"animal_boarding","type":"semiCombo","label":"For Animals"},"animal_breeding":{"key":"animal_breeding","type":"semiCombo","label":"For Animals"},"animal_shelter":{"key":"animal_shelter","type":"semiCombo","label":"For Animals"},"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"}}},"club":{"key":"club","type":"typeCombo","label":"Type"},"collection_times":{"key":"collection_times","type":"text","label":"Collection Times"},"communication_multi":{"key":"communication:","type":"multiCombo","label":"Communication Types"},"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":"semiCombo","label":"Crops"},"crossing":{"key":"crossing","type":"combo","label":"Type"},"cuisine":{"key":"cuisine","type":"semiCombo","label":"Cuisines"},"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)"},"grape_variety":{"key":"grape_variety","type":"semiCombo","label":"Grape Varieties"},"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"},"historic/civilization":{"key":"historic:civilization","type":"combo","label":"Historic Civilization"},"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"},"inscription":{"key":"inscription","type":"textarea","label":"Inscription"},"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"},"label":{"key":"label","type":"textarea","label":"Label"},"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"},"manhole":{"key":"manhole","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},"maxweight":{"key":"maxweight","type":"combo","label":"Max Weight","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":"onewayCheck","label":"One Way","strings":{"options":{"undefined":"Assumed to be Yes","yes":"Yes","no":"No"}}},"oneway":{"key":"oneway","type":"onewayCheck","label":"One Way","strings":{"options":{"undefined":"Assumed to be No","yes":"Yes","no":"No"}}},"opening_hours":{"key":"opening_hours","type":"combo","label":"Hours","snake_case":false},"operator":{"key":"operator","type":"text","label":"Operator"},"outdoor_seating":{"key":"outdoor_seating","type":"check","label":"Outdoor Seating"},"par":{"key":"par","type":"number","label":"Par","placeholder":"3, 4, 5..."},"parallel_direction":{"key":"direction","type":"combo","label":"Direction","strings":{"options":{"forward":"Forward","backward":"Backward"}}},"park_ride":{"key":"park_ride","type":"check","label":"Park and Ride"},"parking":{"key":"parking","type":"combo","label":"Type","strings":{"options":{"surface":"Surface","multi-storey":"Multilevel","underground":"Underground","sheds":"Sheds","carports":"Carports","garage_boxes":"Garage Boxes","lane":"Roadside Lane"}}},"payment_multi":{"key":"payment:","type":"multiCombo","label":"Payment Types"},"phone":{"key":"phone","type":"tel","icon":"telephone","universal":true,"label":"Phone","placeholder":"+31 42 123 4567"},"piste/difficulty":{"key":"piste:difficulty","type":"combo","label":"Difficulty","placeholder":"Easy, Intermediate, Advanced...","strings":{"options":{"novice":"Novice (instructional)","easy":"Easy (green circle)","intermediate":"Intermediate (blue square)","advanced":"Advanced (black diamond)","expert":"Expert (double black diamond)","freeride":"Freeride (off-piste)","extreme":"Extreme (climbing equipment required)"}}},"piste/grooming":{"key":"piste:grooming","type":"combo","label":"Grooming","strings":{"options":{"classic":"Classic","mogul":"Mogul","backcountry":"Backcountry","classic+skating":"Classic and Skating","scooter":"Scooter/Snowmobile","skating":"Skating"}}},"piste/type":{"key":"piste:type","type":"typeCombo","label":"Type","strings":{"options":{"downhill":"Downhill","nordic":"Nordic","skitour":"Skitour","sled":"Sled","hike":"Hike","sleigh":"Sleigh","ice_skate":"Ice Skate","snow_park":"Snow Park","playground":"Playground"}}},"place":{"key":"place","type":"typeCombo","label":"Type"},"plant":{"key":"plant","type":"combo","label":"Plant"},"population":{"key":"population","type":"text","label":"Population"},"power_supply":{"key":"power_supply","type":"check","label":"Power Supply"},"power":{"key":"power","type":"typeCombo","label":"Type"},"produce":{"key":"produce","type":"semiCombo","label":"Produce"},"product":{"key":"product","type":"semiCombo","label":"Products"},"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_times":{"key":"service_times","type":"text","label":"Service Times"},"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"},"service/vehicle":{"key":"service:vehicle:","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":"semiCombo","label":"Sports","options":["skating","hockey","multi","curling","ice_stock"]},"sport_racing_motor":{"key":"sport","type":"semiCombo","label":"Sports","options":["motor","karting","motocross"]},"sport_racing_nonmotor":{"key":"sport","type":"semiCombo","label":"Sports","options":["bmx","cycling","dog_racing","horse_racing","running"]},"sport":{"key":"sport","type":"semiCombo","label":"Sports"},"stars":{"key":"stars","type":"number","label":"Stars"},"start_date":{"key":"start_date","type":"text","universal":true,"label":"Start Date"},"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":"structureRadio","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"},"tomb":{"key":"tomb","type":"typeCombo","label":"Type"},"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":"semiCombo","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"}};
18637 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"];
18642 var all$2 = Object.freeze({
18647 var Airport = ["airfield","airport","heliport","rocket"];
18648 var Dining = ["bakery","bar","beer","cafe","fast-food","ice-cream","restaurant"];
18649 var Education = ["college","school"];
18650 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"];
18651 var Health = ["dentist","doctor","hospital","pharmacy"];
18652 var Outdoors = ["campsite","cemetery","dog-park","garden","golf","park","picnic-site","playground","zoo"];
18653 var Transit = ["bus","ferry"];
18657 Education: Education,
18660 Outdoors: Outdoors,
18662 "Mountain peak": ["mountain","volcano"],
18663 "Rail station": ["entrance","rail","rail-light","rail-metro"]
18666 var streets$1 = Object.freeze({
18669 Education: Education,
18672 Outdoors: Outdoors,
18677 var require$$0 = ( all$2 && all$1 ) || all$2;
18679 var require$$1 = ( streets$1 && streets ) || streets$1;
18684 streets: require$$1
18688 var dataFeatureIcons = index$1.layouts.all.all;
18691 imagery: dataImagery,
18694 defaults: defaults,
18695 categories: categories,
18700 function osmEntity$$1(attrs) {
18701 // For prototypal inheritance.
18702 if (this instanceof osmEntity$$1) return;
18704 // Create the appropriate subtype.
18705 if (attrs && attrs.type) {
18706 return osmEntity$$1[attrs.type].apply(this, arguments);
18707 } else if (attrs && attrs.id) {
18708 return osmEntity$$1[osmEntity$$1.id.type(attrs.id)].apply(this, arguments);
18711 // Initialize a generic Entity (used only in tests).
18712 return (new osmEntity$$1()).initialize(arguments);
18716 osmEntity$$1.id = function(type) {
18717 return osmEntity$$1.id.fromOSM(type, osmEntity$$1.id.next[type]--);
18721 osmEntity$$1.id.next = {
18722 changeset: -1, node: -1, way: -1, relation: -1
18726 osmEntity$$1.id.fromOSM = function(type, id) {
18727 return type[0] + id;
18731 osmEntity$$1.id.toOSM = function(id) {
18732 return id.slice(1);
18736 osmEntity$$1.id.type = function(id) {
18737 return { 'c': 'changeset', 'n': 'node', 'w': 'way', 'r': 'relation' }[id[0]];
18741 // A function suitable for use as the second argument to d3.selection#data().
18742 osmEntity$$1.key = function(entity) {
18743 return entity.id + 'v' + (entity.v || 0);
18747 osmEntity$$1.prototype = {
18752 initialize: function(sources) {
18753 for (var i = 0; i < sources.length; ++i) {
18754 var source = sources[i];
18755 for (var prop in source) {
18756 if (Object.prototype.hasOwnProperty.call(source, prop)) {
18757 if (source[prop] === undefined) {
18760 this[prop] = source[prop];
18766 if (!this.id && this.type) {
18767 this.id = osmEntity$$1.id(this.type);
18769 if (!this.hasOwnProperty('visible')) {
18770 this.visible = true;
18774 Object.freeze(this);
18775 Object.freeze(this.tags);
18777 if (this.loc) Object.freeze(this.loc);
18778 if (this.nodes) Object.freeze(this.nodes);
18779 if (this.members) Object.freeze(this.members);
18786 copy: function(resolver, copies) {
18787 if (copies[this.id])
18788 return copies[this.id];
18790 var copy = osmEntity$$1(this, {id: undefined, user: undefined, version: undefined});
18791 copies[this.id] = copy;
18797 osmId: function() {
18798 return osmEntity$$1.id.toOSM(this.id);
18802 isNew: function() {
18803 return this.osmId() < 0;
18807 update: function(attrs) {
18808 return osmEntity$$1(this, attrs, {v: 1 + (this.v || 0)});
18812 mergeTags: function(tags) {
18813 var merged = lodash.clone(this.tags), changed = false;
18814 for (var k in tags) {
18815 var t1 = merged[k],
18820 } else if (t1 !== t2) {
18822 merged[k] = lodash.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
18825 return changed ? this.update({tags: merged}) : this;
18829 intersects: function(extent, resolver) {
18830 return this.extent(resolver).intersects(extent);
18834 isUsed: function(resolver) {
18835 return lodash.without(Object.keys(this.tags), 'area').length > 0 ||
18836 resolver.parentRelations(this).length > 0;
18840 hasInterestingTags: function() {
18841 return lodash.keys(this.tags).some(osmIsInterestingTag);
18845 isHighwayIntersection: function() {
18849 isDegenerate: function() {
18853 deprecatedTags: function() {
18854 var tags = lodash.toPairs(this.tags);
18855 var deprecated = {};
18857 dataDeprecated.forEach(function(d) {
18858 var match = lodash.toPairs(d.old)[0];
18859 tags.forEach(function(t) {
18860 if (t[0] === match[0] &&
18861 (t[1] === match[1] || match[1] === '*')) {
18862 deprecated[t[0]] = t[1];
18871 function geoRoundCoords(c) {
18872 return [Math.floor(c[0]), Math.floor(c[1])];
18876 function geoInterp(p1, p2, t) {
18877 return [p1[0] + (p2[0] - p1[0]) * t,
18878 p1[1] + (p2[1] - p1[1]) * t];
18882 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
18883 // Returns a positive value, if OAB makes a counter-clockwise turn,
18884 // negative for clockwise turn, and zero if the points are collinear.
18885 function geoCross(o, a, b) {
18886 return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
18890 // http://jsperf.com/id-dist-optimization
18891 function geoEuclideanDistance(a, b) {
18892 var x = a[0] - b[0], y = a[1] - b[1];
18893 return Math.sqrt((x * x) + (y * y));
18897 // using WGS84 polar radius (6356752.314245179 m)
18898 // const = 2 * PI * r / 360
18899 function geoLatToMeters(dLat) {
18900 return dLat * 110946.257617;
18904 // using WGS84 equatorial radius (6378137.0 m)
18905 // const = 2 * PI * r / 360
18906 function geoLonToMeters(dLon, atLat) {
18907 return Math.abs(atLat) >= 90 ? 0 :
18908 dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
18912 // using WGS84 polar radius (6356752.314245179 m)
18913 // const = 2 * PI * r / 360
18914 function geoMetersToLat(m) {
18915 return m / 110946.257617;
18919 // using WGS84 equatorial radius (6378137.0 m)
18920 // const = 2 * PI * r / 360
18921 function geoMetersToLon(m, atLat) {
18922 return Math.abs(atLat) >= 90 ? 0 :
18923 m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
18927 function geoOffsetToMeters(offset) {
18928 var equatRadius = 6356752.314245179,
18929 polarRadius = 6378137.0,
18933 offset[0] * 2 * Math.PI * equatRadius / tileSize,
18934 -offset[1] * 2 * Math.PI * polarRadius / tileSize
18939 function geoMetersToOffset(meters) {
18940 var equatRadius = 6356752.314245179,
18941 polarRadius = 6378137.0,
18945 meters[0] * tileSize / (2 * Math.PI * equatRadius),
18946 -meters[1] * tileSize / (2 * Math.PI * polarRadius)
18951 // Equirectangular approximation of spherical distances on Earth
18952 function geoSphericalDistance(a, b) {
18953 var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
18954 y = geoLatToMeters(a[1] - b[1]);
18955 return Math.sqrt((x * x) + (y * y));
18959 function geoEdgeEqual(a, b) {
18960 return (a[0] === b[0] && a[1] === b[1]) ||
18961 (a[0] === b[1] && a[1] === b[0]);
18965 // Return the counterclockwise angle in the range (-pi, pi)
18966 // between the positive X axis and the line intersecting a and b.
18967 function geoAngle(a, b, projection) {
18968 a = projection(a.loc);
18969 b = projection(b.loc);
18970 return Math.atan2(b[1] - a[1], b[0] - a[0]);
18974 // Rotate all points counterclockwise around a pivot point by given angle
18975 function geoRotate(points, angle, around) {
18976 return points.map(function(point) {
18977 var radial = [point[0] - around[0], point[1] - around[1]];
18979 radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + around[0],
18980 radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + around[1]
18986 // Choose the edge with the minimal distance from `point` to its orthogonal
18987 // projection onto that edge, if such a projection exists, or the distance to
18988 // the closest vertex on that edge. Returns an object with the `index` of the
18989 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
18990 function geoChooseEdge(nodes, point, projection) {
18991 var dist = geoEuclideanDistance,
18992 points = nodes.map(function(n) { return projection(n.loc); }),
18996 function dot(p, q) {
18997 return p[0] * q[0] + p[1] * q[1];
19000 for (var i = 0; i < points.length - 1; i++) {
19002 s = [points[i + 1][0] - o[0],
19003 points[i + 1][1] - o[1]],
19004 v = [point[0] - o[0],
19006 proj = dot(v, s) / dot(s, s),
19011 } else if (proj > 1) {
19014 p = [o[0] + proj * s[0], o[1] + proj * s[1]];
19017 var d = dist(p, point);
19021 loc = projection.invert(p);
19033 // Return the intersection point of 2 line segments.
19034 // From https://github.com/pgkelley4/line-segments-intersect
19035 // This uses the vector cross product approach described below:
19036 // http://stackoverflow.com/a/565282/786339
19037 function geoLineIntersection(a, b) {
19038 function subtractPoints(point1, point2) {
19039 return [point1[0] - point2[0], point1[1] - point2[1]];
19041 function crossProduct(point1, point2) {
19042 return point1[0] * point2[1] - point1[1] * point2[0];
19045 var p = [a[0][0], a[0][1]],
19046 p2 = [a[1][0], a[1][1]],
19047 q = [b[0][0], b[0][1]],
19048 q2 = [b[1][0], b[1][1]],
19049 r = subtractPoints(p2, p),
19050 s = subtractPoints(q2, q),
19051 uNumerator = crossProduct(subtractPoints(q, p), r),
19052 denominator = crossProduct(r, s);
19054 if (uNumerator && denominator) {
19055 var u = uNumerator / denominator,
19056 t = crossProduct(subtractPoints(q, p), s) / denominator;
19058 if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
19059 return geoInterp(p, p2, t);
19067 function geoPathIntersections(path1, path2) {
19068 var intersections = [];
19069 for (var i = 0; i < path1.length - 1; i++) {
19070 for (var j = 0; j < path2.length - 1; j++) {
19071 var a = [ path1[i], path1[i+1] ],
19072 b = [ path2[j], path2[j+1] ],
19073 hit = geoLineIntersection(a, b);
19074 if (hit) intersections.push(hit);
19077 return intersections;
19081 // Return whether point is contained in polygon.
19083 // `point` should be a 2-item array of coordinates.
19084 // `polygon` should be an array of 2-item arrays of coordinates.
19086 // From https://github.com/substack/point-in-polygon.
19087 // ray-casting algorithm based on
19088 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
19090 function geoPointInPolygon(point, polygon) {
19095 for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
19096 var xi = polygon[i][0], yi = polygon[i][1];
19097 var xj = polygon[j][0], yj = polygon[j][1];
19099 var intersect = ((yi > y) !== (yj > y)) &&
19100 (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
19101 if (intersect) inside = !inside;
19108 function geoPolygonContainsPolygon(outer, inner) {
19109 return lodash.every(inner, function(point) {
19110 return geoPointInPolygon(point, outer);
19115 function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
19116 function testSegments(outer, inner) {
19117 for (var i = 0; i < outer.length - 1; i++) {
19118 for (var j = 0; j < inner.length - 1; j++) {
19119 var a = [ outer[i], outer[i+1] ],
19120 b = [ inner[j], inner[j+1] ];
19121 if (geoLineIntersection(a, b)) return true;
19127 function testPoints(outer, inner) {
19128 return lodash.some(inner, function(point) {
19129 return geoPointInPolygon(point, outer);
19133 return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
19137 function geoPathLength(path) {
19139 for (var i = 0; i < path.length - 1; i++) {
19140 length += geoEuclideanDistance(path[i], path[i + 1]);
19145 function geoExtent$$1(min, max) {
19146 if (!(this instanceof geoExtent$$1)) return new geoExtent$$1(min, max);
19147 if (min instanceof geoExtent$$1) {
19149 } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
19153 this[0] = min || [ Infinity, Infinity];
19154 this[1] = max || min || [-Infinity, -Infinity];
19158 geoExtent$$1.prototype = new Array(2);
19160 lodash.extend(geoExtent$$1.prototype, {
19162 equals: function (obj) {
19163 return this[0][0] === obj[0][0] &&
19164 this[0][1] === obj[0][1] &&
19165 this[1][0] === obj[1][0] &&
19166 this[1][1] === obj[1][1];
19170 extend: function(obj) {
19171 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19172 return geoExtent$$1(
19173 [Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])],
19174 [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]
19179 _extend: function(extent) {
19180 this[0][0] = Math.min(extent[0][0], this[0][0]);
19181 this[0][1] = Math.min(extent[0][1], this[0][1]);
19182 this[1][0] = Math.max(extent[1][0], this[1][0]);
19183 this[1][1] = Math.max(extent[1][1], this[1][1]);
19188 return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
19192 center: function() {
19193 return [(this[0][0] + this[1][0]) / 2,
19194 (this[0][1] + this[1][1]) / 2];
19198 rectangle: function() {
19199 return [this[0][0], this[0][1], this[1][0], this[1][1]];
19204 return { minX: this[0][0], minY: this[0][1], maxX: this[1][0], maxY: this[1][1] };
19208 polygon: function() {
19210 [this[0][0], this[0][1]],
19211 [this[0][0], this[1][1]],
19212 [this[1][0], this[1][1]],
19213 [this[1][0], this[0][1]],
19214 [this[0][0], this[0][1]]
19219 contains: function(obj) {
19220 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19221 return obj[0][0] >= this[0][0] &&
19222 obj[0][1] >= this[0][1] &&
19223 obj[1][0] <= this[1][0] &&
19224 obj[1][1] <= this[1][1];
19228 intersects: function(obj) {
19229 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19230 return obj[0][0] <= this[1][0] &&
19231 obj[0][1] <= this[1][1] &&
19232 obj[1][0] >= this[0][0] &&
19233 obj[1][1] >= this[0][1];
19237 intersection: function(obj) {
19238 if (!this.intersects(obj)) return new geoExtent$$1();
19239 return new geoExtent$$1(
19240 [Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])],
19241 [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]
19246 percentContainedIn: function(obj) {
19247 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19248 var a1 = this.intersection(obj).area(),
19251 if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
19259 padByMeters: function(meters) {
19260 var dLat = geoMetersToLat(meters),
19261 dLon = geoMetersToLon(meters, this.center()[1]);
19262 return geoExtent$$1(
19263 [this[0][0] - dLon, this[0][1] - dLat],
19264 [this[1][0] + dLon, this[1][1] + dLat]
19269 toParam: function() {
19270 return this.rectangle().join(',');
19275 var version = "4.9.1";
19277 var ascending = function(a, b) {
19278 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
19281 var bisector = function(compare) {
19282 if (compare.length === 1) compare = ascendingComparator(compare);
19284 left: function(a, x, lo, hi) {
19285 if (lo == null) lo = 0;
19286 if (hi == null) hi = a.length;
19288 var mid = lo + hi >>> 1;
19289 if (compare(a[mid], x) < 0) lo = mid + 1;
19294 right: function(a, x, lo, hi) {
19295 if (lo == null) lo = 0;
19296 if (hi == null) hi = a.length;
19298 var mid = lo + hi >>> 1;
19299 if (compare(a[mid], x) > 0) hi = mid;
19307 function ascendingComparator(f) {
19308 return function(d, x) {
19309 return ascending(f(d), x);
19313 var ascendingBisect = bisector(ascending);
19314 var bisectRight = ascendingBisect.right;
19315 var bisectLeft = ascendingBisect.left;
19317 var pairs = function(array, f) {
19318 if (f == null) f = pair;
19319 var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);
19320 while (i < n) pairs[i] = f(p, p = array[++i]);
19324 function pair(a, b) {
19328 var cross = function(values0, values1, reduce) {
19329 var n0 = values0.length,
19330 n1 = values1.length,
19331 values = new Array(n0 * n1),
19337 if (reduce == null) reduce = pair;
19339 for (i0 = i = 0; i0 < n0; ++i0) {
19340 for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) {
19341 values[i] = reduce(value0, values1[i1]);
19348 var descending = function(a, b) {
19349 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
19352 var number = function(x) {
19353 return x === null ? NaN : +x;
19356 var variance = function(values, valueof) {
19357 var n = values.length,
19365 if (valueof == null) {
19367 if (!isNaN(value = number(values[i]))) {
19368 delta = value - mean;
19369 mean += delta / ++m;
19370 sum += delta * (value - mean);
19377 if (!isNaN(value = number(valueof(values[i], i, values)))) {
19378 delta = value - mean;
19379 mean += delta / ++m;
19380 sum += delta * (value - mean);
19385 if (m > 1) return sum / (m - 1);
19388 var deviation = function(array, f) {
19389 var v = variance(array, f);
19390 return v ? Math.sqrt(v) : v;
19393 var extent = function(values, valueof) {
19394 var n = values.length,
19400 if (valueof == null) {
19401 while (++i < n) { // Find the first comparable value.
19402 if ((value = values[i]) != null && value >= value) {
19404 while (++i < n) { // Compare the remaining values.
19405 if ((value = values[i]) != null) {
19406 if (min > value) min = value;
19407 if (max < value) max = value;
19415 while (++i < n) { // Find the first comparable value.
19416 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19418 while (++i < n) { // Compare the remaining values.
19419 if ((value = valueof(values[i], i, values)) != null) {
19420 if (min > value) min = value;
19421 if (max < value) max = value;
19431 var array = Array.prototype;
19433 var slice = array.slice;
19434 var map = array.map;
19436 var constant = function(x) {
19437 return function() {
19442 var identity = function(x) {
19446 var sequence = function(start, stop, step) {
19447 start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
19450 n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
19451 range = new Array(n);
19454 range[i] = start + i * step;
19460 var e10 = Math.sqrt(50);
19461 var e5 = Math.sqrt(10);
19462 var e2 = Math.sqrt(2);
19464 var ticks = function(start, stop, count) {
19465 var reverse = stop < start,
19471 if (reverse) n = start, start = stop, stop = n;
19473 if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
19476 start = Math.ceil(start / step);
19477 stop = Math.floor(stop / step);
19478 ticks = new Array(n = Math.ceil(stop - start + 1));
19479 while (++i < n) ticks[i] = (start + i) * step;
19481 start = Math.floor(start * step);
19482 stop = Math.ceil(stop * step);
19483 ticks = new Array(n = Math.ceil(start - stop + 1));
19484 while (++i < n) ticks[i] = (start - i) / step;
19487 if (reverse) ticks.reverse();
19492 function tickIncrement(start, stop, count) {
19493 var step = (stop - start) / Math.max(0, count),
19494 power = Math.floor(Math.log(step) / Math.LN10),
19495 error = step / Math.pow(10, power);
19497 ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power)
19498 : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
19501 function tickStep(start, stop, count) {
19502 var step0 = Math.abs(stop - start) / Math.max(0, count),
19503 step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
19504 error = step0 / step1;
19505 if (error >= e10) step1 *= 10;
19506 else if (error >= e5) step1 *= 5;
19507 else if (error >= e2) step1 *= 2;
19508 return stop < start ? -step1 : step1;
19511 var sturges = function(values) {
19512 return Math.ceil(Math.log(values.length) / Math.LN2) + 1;
19515 var histogram = function() {
19516 var value = identity,
19518 threshold = sturges;
19520 function histogram(data) {
19524 values = new Array(n);
19526 for (i = 0; i < n; ++i) {
19527 values[i] = value(data[i], i, data);
19530 var xz = domain(values),
19533 tz = threshold(values, x0, x1);
19535 // Convert number of thresholds into uniform thresholds.
19536 if (!Array.isArray(tz)) {
19537 tz = tickStep(x0, x1, tz);
19538 tz = sequence(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive
19541 // Remove any thresholds outside the domain.
19543 while (tz[0] <= x0) tz.shift(), --m;
19544 while (tz[m - 1] > x1) tz.pop(), --m;
19546 var bins = new Array(m + 1),
19549 // Initialize bins.
19550 for (i = 0; i <= m; ++i) {
19551 bin = bins[i] = [];
19552 bin.x0 = i > 0 ? tz[i - 1] : x0;
19553 bin.x1 = i < m ? tz[i] : x1;
19556 // Assign data to bins by value, ignoring any outside the domain.
19557 for (i = 0; i < n; ++i) {
19559 if (x0 <= x && x <= x1) {
19560 bins[bisectRight(tz, x, 0, m)].push(data[i]);
19567 histogram.value = function(_) {
19568 return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value;
19571 histogram.domain = function(_) {
19572 return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain;
19575 histogram.thresholds = function(_) {
19576 return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold;
19582 var threshold = function(values, p, valueof) {
19583 if (valueof == null) valueof = number;
19584 if (!(n = values.length)) return;
19585 if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values);
19586 if (p >= 1) return +valueof(values[n - 1], n - 1, values);
19589 i0 = Math.floor(i),
19590 value0 = +valueof(values[i0], i0, values),
19591 value1 = +valueof(values[i0 + 1], i0 + 1, values);
19592 return value0 + (value1 - value0) * (i - i0);
19595 var freedmanDiaconis = function(values, min, max) {
19596 values = map.call(values, number).sort(ascending);
19597 return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3)));
19600 var scott = function(values, min, max) {
19601 return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));
19604 var max = function(values, valueof) {
19605 var n = values.length,
19610 if (valueof == null) {
19611 while (++i < n) { // Find the first comparable value.
19612 if ((value = values[i]) != null && value >= value) {
19614 while (++i < n) { // Compare the remaining values.
19615 if ((value = values[i]) != null && value > max) {
19624 while (++i < n) { // Find the first comparable value.
19625 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19627 while (++i < n) { // Compare the remaining values.
19628 if ((value = valueof(values[i], i, values)) != null && value > max) {
19639 var mean = function(values, valueof) {
19640 var n = values.length,
19646 if (valueof == null) {
19648 if (!isNaN(value = number(values[i]))) sum += value;
19655 if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value;
19660 if (m) return sum / m;
19663 var median = function(values, valueof) {
19664 var n = values.length,
19669 if (valueof == null) {
19671 if (!isNaN(value = number(values[i]))) {
19672 numbers.push(value);
19679 if (!isNaN(value = number(valueof(values[i], i, values)))) {
19680 numbers.push(value);
19685 return threshold(numbers.sort(ascending), 0.5);
19688 var merge = function(arrays) {
19689 var n = arrays.length,
19696 while (++i < n) j += arrays[i].length;
19697 merged = new Array(j);
19703 merged[--j] = array[m];
19710 var min = function(values, valueof) {
19711 var n = values.length,
19716 if (valueof == null) {
19717 while (++i < n) { // Find the first comparable value.
19718 if ((value = values[i]) != null && value >= value) {
19720 while (++i < n) { // Compare the remaining values.
19721 if ((value = values[i]) != null && min > value) {
19730 while (++i < n) { // Find the first comparable value.
19731 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19733 while (++i < n) { // Compare the remaining values.
19734 if ((value = valueof(values[i], i, values)) != null && min > value) {
19745 var permute = function(array, indexes) {
19746 var i = indexes.length, permutes = new Array(i);
19747 while (i--) permutes[i] = array[indexes[i]];
19751 var scan = function(values, compare) {
19752 if (!(n = values.length)) return;
19759 if (compare == null) compare = ascending;
19762 if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) {
19767 if (compare(xj, xj) === 0) return j;
19770 var shuffle = function(array, i0, i1) {
19771 var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),
19776 i = Math.random() * m-- | 0;
19778 array[m + i0] = array[i + i0];
19785 var sum = function(values, valueof) {
19786 var n = values.length,
19791 if (valueof == null) {
19793 if (value = +values[i]) sum += value; // Note: zero and null are equivalent.
19799 if (value = +valueof(values[i], i, values)) sum += value;
19806 var transpose = function(matrix) {
19807 if (!(n = matrix.length)) return [];
19808 for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
19809 for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
19810 row[j] = matrix[j][i];
19816 function length(d) {
19820 var zip = function() {
19821 return transpose(arguments);
19824 var slice$1 = Array.prototype.slice;
19826 var identity$1 = function(x) {
19834 var epsilon = 1e-6;
19836 function translateX(x) {
19837 return "translate(" + (x + 0.5) + ",0)";
19840 function translateY(y) {
19841 return "translate(0," + (y + 0.5) + ")";
19844 function center(scale) {
19845 var offset = Math.max(0, scale.bandwidth() - 1) / 2; // Adjust for 0.5px offset.
19846 if (scale.round()) offset = Math.round(offset);
19847 return function(d) {
19848 return scale(d) + offset;
19852 function entering() {
19853 return !this.__axis;
19856 function axis(orient, scale) {
19857 var tickArguments = [],
19863 k = orient === top || orient === left ? -1 : 1,
19864 x = orient === left || orient === right ? "x" : "y",
19865 transform = orient === top || orient === bottom ? translateX : translateY;
19867 function axis(context) {
19868 var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
19869 format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$1) : tickFormat,
19870 spacing = Math.max(tickSizeInner, 0) + tickPadding,
19871 range = scale.range(),
19872 range0 = range[0] + 0.5,
19873 range1 = range[range.length - 1] + 0.5,
19874 position = (scale.bandwidth ? center : identity$1)(scale.copy()),
19875 selection = context.selection ? context.selection() : context,
19876 path = selection.selectAll(".domain").data([null]),
19877 tick = selection.selectAll(".tick").data(values, scale).order(),
19878 tickExit = tick.exit(),
19879 tickEnter = tick.enter().append("g").attr("class", "tick"),
19880 line = tick.select("line"),
19881 text = tick.select("text");
19883 path = path.merge(path.enter().insert("path", ".tick")
19884 .attr("class", "domain")
19885 .attr("stroke", "#000"));
19887 tick = tick.merge(tickEnter);
19889 line = line.merge(tickEnter.append("line")
19890 .attr("stroke", "#000")
19891 .attr(x + "2", k * tickSizeInner));
19893 text = text.merge(tickEnter.append("text")
19894 .attr("fill", "#000")
19895 .attr(x, k * spacing)
19896 .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em"));
19898 if (context !== selection) {
19899 path = path.transition(context);
19900 tick = tick.transition(context);
19901 line = line.transition(context);
19902 text = text.transition(context);
19904 tickExit = tickExit.transition(context)
19905 .attr("opacity", epsilon)
19906 .attr("transform", function(d) { return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); });
19909 .attr("opacity", epsilon)
19910 .attr("transform", function(d) { var p = this.parentNode.__axis; return transform(p && isFinite(p = p(d)) ? p : position(d)); });
19916 .attr("d", orient === left || orient == right
19917 ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter
19918 : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter);
19921 .attr("opacity", 1)
19922 .attr("transform", function(d) { return transform(position(d)); });
19925 .attr(x + "2", k * tickSizeInner);
19928 .attr(x, k * spacing)
19931 selection.filter(entering)
19932 .attr("fill", "none")
19933 .attr("font-size", 10)
19934 .attr("font-family", "sans-serif")
19935 .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle");
19938 .each(function() { this.__axis = position; });
19941 axis.scale = function(_) {
19942 return arguments.length ? (scale = _, axis) : scale;
19945 axis.ticks = function() {
19946 return tickArguments = slice$1.call(arguments), axis;
19949 axis.tickArguments = function(_) {
19950 return arguments.length ? (tickArguments = _ == null ? [] : slice$1.call(_), axis) : tickArguments.slice();
19953 axis.tickValues = function(_) {
19954 return arguments.length ? (tickValues = _ == null ? null : slice$1.call(_), axis) : tickValues && tickValues.slice();
19957 axis.tickFormat = function(_) {
19958 return arguments.length ? (tickFormat = _, axis) : tickFormat;
19961 axis.tickSize = function(_) {
19962 return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
19965 axis.tickSizeInner = function(_) {
19966 return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
19969 axis.tickSizeOuter = function(_) {
19970 return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
19973 axis.tickPadding = function(_) {
19974 return arguments.length ? (tickPadding = +_, axis) : tickPadding;
19980 function axisTop(scale) {
19981 return axis(top, scale);
19984 function axisRight(scale) {
19985 return axis(right, scale);
19988 function axisBottom(scale) {
19989 return axis(bottom, scale);
19992 function axisLeft(scale) {
19993 return axis(left, scale);
19996 var noop = {value: function() {}};
19998 function dispatch() {
19999 for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
20000 if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t);
20003 return new Dispatch(_);
20006 function Dispatch(_) {
20010 function parseTypenames(typenames, types) {
20011 return typenames.trim().split(/^|\s+/).map(function(t) {
20012 var name = "", i = t.indexOf(".");
20013 if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
20014 if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
20015 return {type: t, name: name};
20019 Dispatch.prototype = dispatch.prototype = {
20020 constructor: Dispatch,
20021 on: function(typename, callback) {
20023 T = parseTypenames(typename + "", _),
20028 // If no callback was specified, return the callback of the given type and name.
20029 if (arguments.length < 2) {
20030 while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
20034 // If a type was specified, set the callback for the given type and name.
20035 // Otherwise, if a null callback was specified, remove callbacks of the given name.
20036 if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
20038 if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);
20039 else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);
20045 var copy = {}, _ = this._;
20046 for (var t in _) copy[t] = _[t].slice();
20047 return new Dispatch(copy);
20049 call: function(type, that) {
20050 if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
20051 if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
20052 for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
20054 apply: function(type, that, args) {
20055 if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
20056 for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
20060 function get(type, name) {
20061 for (var i = 0, n = type.length, c; i < n; ++i) {
20062 if ((c = type[i]).name === name) {
20068 function set(type, name, callback) {
20069 for (var i = 0, n = type.length; i < n; ++i) {
20070 if (type[i].name === name) {
20071 type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
20075 if (callback != null) type.push({name: name, value: callback});
20079 var xhtml = "http://www.w3.org/1999/xhtml";
20082 svg: "http://www.w3.org/2000/svg",
20084 xlink: "http://www.w3.org/1999/xlink",
20085 xml: "http://www.w3.org/XML/1998/namespace",
20086 xmlns: "http://www.w3.org/2000/xmlns/"
20089 var namespace = function(name) {
20090 var prefix = name += "", i = prefix.indexOf(":");
20091 if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
20092 return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
20095 function creatorInherit(name) {
20096 return function() {
20097 var document = this.ownerDocument,
20098 uri = this.namespaceURI;
20099 return uri === xhtml && document.documentElement.namespaceURI === xhtml
20100 ? document.createElement(name)
20101 : document.createElementNS(uri, name);
20105 function creatorFixed(fullname) {
20106 return function() {
20107 return this.ownerDocument.createElementNS(fullname.space, fullname.local);
20111 var creator = function(name) {
20112 var fullname = namespace(name);
20113 return (fullname.local
20115 : creatorInherit)(fullname);
20120 function local$1() {
20125 this._ = "@" + (++nextId).toString(36);
20128 Local.prototype = local$1.prototype = {
20129 constructor: Local,
20130 get: function(node) {
20132 while (!(id in node)) if (!(node = node.parentNode)) return;
20135 set: function(node, value) {
20136 return node[this._] = value;
20138 remove: function(node) {
20139 return this._ in node && delete node[this._];
20141 toString: function() {
20146 var matcher = function(selector) {
20147 return function() {
20148 return this.matches(selector);
20152 if (typeof document !== "undefined") {
20153 var element = document.documentElement;
20154 if (!element.matches) {
20155 var vendorMatches = element.webkitMatchesSelector
20156 || element.msMatchesSelector
20157 || element.mozMatchesSelector
20158 || element.oMatchesSelector;
20159 matcher = function(selector) {
20160 return function() {
20161 return vendorMatches.call(this, selector);
20167 var matcher$1 = matcher;
20169 var filterEvents = {};
20173 if (typeof document !== "undefined") {
20174 var element$1 = document.documentElement;
20175 if (!("onmouseenter" in element$1)) {
20176 filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
20180 function filterContextListener(listener, index, group) {
20181 listener = contextListener(listener, index, group);
20182 return function(event) {
20183 var related = event.relatedTarget;
20184 if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
20185 listener.call(this, event);
20190 function contextListener(listener, index, group) {
20191 return function(event1) {
20192 var event0 = event; // Events can be reentrant (e.g., focus).
20195 listener.call(this, this.__data__, index, group);
20202 function parseTypenames$1(typenames) {
20203 return typenames.trim().split(/^|\s+/).map(function(t) {
20204 var name = "", i = t.indexOf(".");
20205 if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
20206 return {type: t, name: name};
20210 function onRemove(typename) {
20211 return function() {
20212 var on = this.__on;
20214 for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
20215 if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
20216 this.removeEventListener(o.type, o.listener, o.capture);
20221 if (++i) on.length = i;
20222 else delete this.__on;
20226 function onAdd(typename, value, capture) {
20227 var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
20228 return function(d, i, group) {
20229 var on = this.__on, o, listener = wrap(value, i, group);
20230 if (on) for (var j = 0, m = on.length; j < m; ++j) {
20231 if ((o = on[j]).type === typename.type && o.name === typename.name) {
20232 this.removeEventListener(o.type, o.listener, o.capture);
20233 this.addEventListener(o.type, o.listener = listener, o.capture = capture);
20238 this.addEventListener(typename.type, listener, capture);
20239 o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
20240 if (!on) this.__on = [o];
20245 var selection_on = function(typename, value, capture) {
20246 var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t;
20248 if (arguments.length < 2) {
20249 var on = this.node().__on;
20250 if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
20251 for (i = 0, o = on[j]; i < n; ++i) {
20252 if ((t = typenames[i]).type === o.type && t.name === o.name) {
20260 on = value ? onAdd : onRemove;
20261 if (capture == null) capture = false;
20262 for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
20266 function customEvent(event1, listener, that, args) {
20267 var event0 = event;
20268 event1.sourceEvent = event;
20271 return listener.apply(that, args);
20277 var sourceEvent = function() {
20278 var current = event, source;
20279 while (source = current.sourceEvent) current = source;
20283 var point = function(node, event) {
20284 var svg = node.ownerSVGElement || node;
20286 if (svg.createSVGPoint) {
20287 var point = svg.createSVGPoint();
20288 point.x = event.clientX, point.y = event.clientY;
20289 point = point.matrixTransform(node.getScreenCTM().inverse());
20290 return [point.x, point.y];
20293 var rect = node.getBoundingClientRect();
20294 return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
20297 var mouse = function(node) {
20298 var event = sourceEvent();
20299 if (event.changedTouches) event = event.changedTouches[0];
20300 return point(node, event);
20305 var selector = function(selector) {
20306 return selector == null ? none : function() {
20307 return this.querySelector(selector);
20311 var selection_select = function(select) {
20312 if (typeof select !== "function") select = selector(select);
20314 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
20315 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
20316 if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
20317 if ("__data__" in node) subnode.__data__ = node.__data__;
20318 subgroup[i] = subnode;
20323 return new Selection(subgroups, this._parents);
20326 function empty$1() {
20330 var selectorAll = function(selector) {
20331 return selector == null ? empty$1 : function() {
20332 return this.querySelectorAll(selector);
20336 var selection_selectAll = function(select) {
20337 if (typeof select !== "function") select = selectorAll(select);
20339 for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
20340 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
20341 if (node = group[i]) {
20342 subgroups.push(select.call(node, node.__data__, i, group));
20343 parents.push(node);
20348 return new Selection(subgroups, parents);
20351 var selection_filter = function(match) {
20352 if (typeof match !== "function") match = matcher$1(match);
20354 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
20355 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
20356 if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
20357 subgroup.push(node);
20362 return new Selection(subgroups, this._parents);
20365 var sparse = function(update) {
20366 return new Array(update.length);
20369 var selection_enter = function() {
20370 return new Selection(this._enter || this._groups.map(sparse), this._parents);
20373 function EnterNode(parent, datum) {
20374 this.ownerDocument = parent.ownerDocument;
20375 this.namespaceURI = parent.namespaceURI;
20377 this._parent = parent;
20378 this.__data__ = datum;
20381 EnterNode.prototype = {
20382 constructor: EnterNode,
20383 appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
20384 insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
20385 querySelector: function(selector) { return this._parent.querySelector(selector); },
20386 querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
20389 var constant$1 = function(x) {
20390 return function() {
20395 var keyPrefix = "$"; // Protect against keys like “__proto__”.
20397 function bindIndex(parent, group, enter, update, exit, data) {
20400 groupLength = group.length,
20401 dataLength = data.length;
20403 // Put any non-null nodes that fit into update.
20404 // Put any null nodes into enter.
20405 // Put any remaining data into enter.
20406 for (; i < dataLength; ++i) {
20407 if (node = group[i]) {
20408 node.__data__ = data[i];
20411 enter[i] = new EnterNode(parent, data[i]);
20415 // Put any non-null nodes that don’t fit into exit.
20416 for (; i < groupLength; ++i) {
20417 if (node = group[i]) {
20423 function bindKey(parent, group, enter, update, exit, data, key) {
20426 nodeByKeyValue = {},
20427 groupLength = group.length,
20428 dataLength = data.length,
20429 keyValues = new Array(groupLength),
20432 // Compute the key for each node.
20433 // If multiple nodes have the same key, the duplicates are added to exit.
20434 for (i = 0; i < groupLength; ++i) {
20435 if (node = group[i]) {
20436 keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
20437 if (keyValue in nodeByKeyValue) {
20440 nodeByKeyValue[keyValue] = node;
20445 // Compute the key for each datum.
20446 // If there a node associated with this key, join and add it to update.
20447 // If there is not (or the key is a duplicate), add it to enter.
20448 for (i = 0; i < dataLength; ++i) {
20449 keyValue = keyPrefix + key.call(parent, data[i], i, data);
20450 if (node = nodeByKeyValue[keyValue]) {
20452 node.__data__ = data[i];
20453 nodeByKeyValue[keyValue] = null;
20455 enter[i] = new EnterNode(parent, data[i]);
20459 // Add any remaining nodes that were not bound to data to exit.
20460 for (i = 0; i < groupLength; ++i) {
20461 if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
20467 var selection_data = function(value, key) {
20469 data = new Array(this.size()), j = -1;
20470 this.each(function(d) { data[++j] = d; });
20474 var bind = key ? bindKey : bindIndex,
20475 parents = this._parents,
20476 groups = this._groups;
20478 if (typeof value !== "function") value = constant$1(value);
20480 for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
20481 var parent = parents[j],
20483 groupLength = group.length,
20484 data = value.call(parent, parent && parent.__data__, j, parents),
20485 dataLength = data.length,
20486 enterGroup = enter[j] = new Array(dataLength),
20487 updateGroup = update[j] = new Array(dataLength),
20488 exitGroup = exit[j] = new Array(groupLength);
20490 bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
20492 // Now connect the enter nodes to their following update node, such that
20493 // appendChild can insert the materialized enter node before this node,
20494 // rather than at the end of the parent node.
20495 for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
20496 if (previous = enterGroup[i0]) {
20497 if (i0 >= i1) i1 = i0 + 1;
20498 while (!(next = updateGroup[i1]) && ++i1 < dataLength);
20499 previous._next = next || null;
20504 update = new Selection(update, parents);
20505 update._enter = enter;
20506 update._exit = exit;
20510 var selection_exit = function() {
20511 return new Selection(this._exit || this._groups.map(sparse), this._parents);
20514 var selection_merge = function(selection$$1) {
20516 for (var groups0 = this._groups, groups1 = selection$$1._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
20517 for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
20518 if (node = group0[i] || group1[i]) {
20524 for (; j < m0; ++j) {
20525 merges[j] = groups0[j];
20528 return new Selection(merges, this._parents);
20531 var selection_order = function() {
20533 for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
20534 for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
20535 if (node = group[i]) {
20536 if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
20545 var selection_sort = function(compare) {
20546 if (!compare) compare = ascending$1;
20548 function compareNode(a, b) {
20549 return a && b ? compare(a.__data__, b.__data__) : !a - !b;
20552 for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
20553 for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
20554 if (node = group[i]) {
20555 sortgroup[i] = node;
20558 sortgroup.sort(compareNode);
20561 return new Selection(sortgroups, this._parents).order();
20564 function ascending$1(a, b) {
20565 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
20568 var selection_call = function() {
20569 var callback = arguments[0];
20570 arguments[0] = this;
20571 callback.apply(null, arguments);
20575 var selection_nodes = function() {
20576 var nodes = new Array(this.size()), i = -1;
20577 this.each(function() { nodes[++i] = this; });
20581 var selection_node = function() {
20583 for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
20584 for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
20585 var node = group[i];
20586 if (node) return node;
20593 var selection_size = function() {
20595 this.each(function() { ++size; });
20599 var selection_empty = function() {
20600 return !this.node();
20603 var selection_each = function(callback) {
20605 for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
20606 for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
20607 if (node = group[i]) callback.call(node, node.__data__, i, group);
20614 function attrRemove(name) {
20615 return function() {
20616 this.removeAttribute(name);
20620 function attrRemoveNS(fullname) {
20621 return function() {
20622 this.removeAttributeNS(fullname.space, fullname.local);
20626 function attrConstant(name, value) {
20627 return function() {
20628 this.setAttribute(name, value);
20632 function attrConstantNS(fullname, value) {
20633 return function() {
20634 this.setAttributeNS(fullname.space, fullname.local, value);
20638 function attrFunction(name, value) {
20639 return function() {
20640 var v = value.apply(this, arguments);
20641 if (v == null) this.removeAttribute(name);
20642 else this.setAttribute(name, v);
20646 function attrFunctionNS(fullname, value) {
20647 return function() {
20648 var v = value.apply(this, arguments);
20649 if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
20650 else this.setAttributeNS(fullname.space, fullname.local, v);
20654 var selection_attr = function(name, value) {
20655 var fullname = namespace(name);
20657 if (arguments.length < 2) {
20658 var node = this.node();
20659 return fullname.local
20660 ? node.getAttributeNS(fullname.space, fullname.local)
20661 : node.getAttribute(fullname);
20664 return this.each((value == null
20665 ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
20666 ? (fullname.local ? attrFunctionNS : attrFunction)
20667 : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
20670 var defaultView = function(node) {
20671 return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
20672 || (node.document && node) // node is a Window
20673 || node.defaultView; // node is a Document
20676 function styleRemove(name) {
20677 return function() {
20678 this.style.removeProperty(name);
20682 function styleConstant(name, value, priority) {
20683 return function() {
20684 this.style.setProperty(name, value, priority);
20688 function styleFunction(name, value, priority) {
20689 return function() {
20690 var v = value.apply(this, arguments);
20691 if (v == null) this.style.removeProperty(name);
20692 else this.style.setProperty(name, v, priority);
20696 var selection_style = function(name, value, priority) {
20697 return arguments.length > 1
20698 ? this.each((value == null
20699 ? styleRemove : typeof value === "function"
20701 : styleConstant)(name, value, priority == null ? "" : priority))
20702 : styleValue(this.node(), name);
20705 function styleValue(node, name) {
20706 return node.style.getPropertyValue(name)
20707 || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
20710 function propertyRemove(name) {
20711 return function() {
20716 function propertyConstant(name, value) {
20717 return function() {
20718 this[name] = value;
20722 function propertyFunction(name, value) {
20723 return function() {
20724 var v = value.apply(this, arguments);
20725 if (v == null) delete this[name];
20726 else this[name] = v;
20730 var selection_property = function(name, value) {
20731 return arguments.length > 1
20732 ? this.each((value == null
20733 ? propertyRemove : typeof value === "function"
20735 : propertyConstant)(name, value))
20736 : this.node()[name];
20739 function classArray(string) {
20740 return string.trim().split(/^|\s+/);
20743 function classList(node) {
20744 return node.classList || new ClassList(node);
20747 function ClassList(node) {
20749 this._names = classArray(node.getAttribute("class") || "");
20752 ClassList.prototype = {
20753 add: function(name) {
20754 var i = this._names.indexOf(name);
20756 this._names.push(name);
20757 this._node.setAttribute("class", this._names.join(" "));
20760 remove: function(name) {
20761 var i = this._names.indexOf(name);
20763 this._names.splice(i, 1);
20764 this._node.setAttribute("class", this._names.join(" "));
20767 contains: function(name) {
20768 return this._names.indexOf(name) >= 0;
20772 function classedAdd(node, names) {
20773 var list = classList(node), i = -1, n = names.length;
20774 while (++i < n) list.add(names[i]);
20777 function classedRemove(node, names) {
20778 var list = classList(node), i = -1, n = names.length;
20779 while (++i < n) list.remove(names[i]);
20782 function classedTrue(names) {
20783 return function() {
20784 classedAdd(this, names);
20788 function classedFalse(names) {
20789 return function() {
20790 classedRemove(this, names);
20794 function classedFunction(names, value) {
20795 return function() {
20796 (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
20800 var selection_classed = function(name, value) {
20801 var names = classArray(name + "");
20803 if (arguments.length < 2) {
20804 var list = classList(this.node()), i = -1, n = names.length;
20805 while (++i < n) if (!list.contains(names[i])) return false;
20809 return this.each((typeof value === "function"
20810 ? classedFunction : value
20812 : classedFalse)(names, value));
20815 function textRemove() {
20816 this.textContent = "";
20819 function textConstant(value) {
20820 return function() {
20821 this.textContent = value;
20825 function textFunction(value) {
20826 return function() {
20827 var v = value.apply(this, arguments);
20828 this.textContent = v == null ? "" : v;
20832 var selection_text = function(value) {
20833 return arguments.length
20834 ? this.each(value == null
20835 ? textRemove : (typeof value === "function"
20837 : textConstant)(value))
20838 : this.node().textContent;
20841 function htmlRemove() {
20842 this.innerHTML = "";
20845 function htmlConstant(value) {
20846 return function() {
20847 this.innerHTML = value;
20851 function htmlFunction(value) {
20852 return function() {
20853 var v = value.apply(this, arguments);
20854 this.innerHTML = v == null ? "" : v;
20858 var selection_html = function(value) {
20859 return arguments.length
20860 ? this.each(value == null
20861 ? htmlRemove : (typeof value === "function"
20863 : htmlConstant)(value))
20864 : this.node().innerHTML;
20868 if (this.nextSibling) this.parentNode.appendChild(this);
20871 var selection_raise = function() {
20872 return this.each(raise);
20876 if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
20879 var selection_lower = function() {
20880 return this.each(lower);
20883 var selection_append = function(name) {
20884 var create = typeof name === "function" ? name : creator(name);
20885 return this.select(function() {
20886 return this.appendChild(create.apply(this, arguments));
20890 function constantNull() {
20894 var selection_insert = function(name, before) {
20895 var create = typeof name === "function" ? name : creator(name),
20896 select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
20897 return this.select(function() {
20898 return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
20902 function remove() {
20903 var parent = this.parentNode;
20904 if (parent) parent.removeChild(this);
20907 var selection_remove = function() {
20908 return this.each(remove);
20911 var selection_datum = function(value) {
20912 return arguments.length
20913 ? this.property("__data__", value)
20914 : this.node().__data__;
20917 function dispatchEvent(node, type, params) {
20918 var window = defaultView(node),
20919 event = window.CustomEvent;
20921 if (typeof event === "function") {
20922 event = new event(type, params);
20924 event = window.document.createEvent("Event");
20925 if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
20926 else event.initEvent(type, false, false);
20929 node.dispatchEvent(event);
20932 function dispatchConstant(type, params) {
20933 return function() {
20934 return dispatchEvent(this, type, params);
20938 function dispatchFunction(type, params) {
20939 return function() {
20940 return dispatchEvent(this, type, params.apply(this, arguments));
20944 var selection_dispatch = function(type, params) {
20945 return this.each((typeof params === "function"
20947 : dispatchConstant)(type, params));
20952 function Selection(groups, parents) {
20953 this._groups = groups;
20954 this._parents = parents;
20957 function selection() {
20958 return new Selection([[document.documentElement]], root);
20961 Selection.prototype = selection.prototype = {
20962 constructor: Selection,
20963 select: selection_select,
20964 selectAll: selection_selectAll,
20965 filter: selection_filter,
20966 data: selection_data,
20967 enter: selection_enter,
20968 exit: selection_exit,
20969 merge: selection_merge,
20970 order: selection_order,
20971 sort: selection_sort,
20972 call: selection_call,
20973 nodes: selection_nodes,
20974 node: selection_node,
20975 size: selection_size,
20976 empty: selection_empty,
20977 each: selection_each,
20978 attr: selection_attr,
20979 style: selection_style,
20980 property: selection_property,
20981 classed: selection_classed,
20982 text: selection_text,
20983 html: selection_html,
20984 raise: selection_raise,
20985 lower: selection_lower,
20986 append: selection_append,
20987 insert: selection_insert,
20988 remove: selection_remove,
20989 datum: selection_datum,
20991 dispatch: selection_dispatch
20994 var select = function(selector) {
20995 return typeof selector === "string"
20996 ? new Selection([[document.querySelector(selector)]], [document.documentElement])
20997 : new Selection([[selector]], root);
21000 var selectAll = function(selector) {
21001 return typeof selector === "string"
21002 ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
21003 : new Selection([selector == null ? [] : selector], root);
21006 var touch = function(node, touches, identifier) {
21007 if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
21009 for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
21010 if ((touch = touches[i]).identifier === identifier) {
21011 return point(node, touch);
21018 var touches = function(node, touches) {
21019 if (touches == null) touches = sourceEvent().touches;
21021 for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) {
21022 points[i] = point(node, touches[i]);
21028 function nopropagation() {
21029 event.stopImmediatePropagation();
21032 var noevent = function() {
21033 event.preventDefault();
21034 event.stopImmediatePropagation();
21037 var dragDisable = function(view) {
21038 var root = view.document.documentElement,
21039 selection$$1 = select(view).on("dragstart.drag", noevent, true);
21040 if ("onselectstart" in root) {
21041 selection$$1.on("selectstart.drag", noevent, true);
21043 root.__noselect = root.style.MozUserSelect;
21044 root.style.MozUserSelect = "none";
21048 function yesdrag(view, noclick) {
21049 var root = view.document.documentElement,
21050 selection$$1 = select(view).on("dragstart.drag", null);
21052 selection$$1.on("click.drag", noevent, true);
21053 setTimeout(function() { selection$$1.on("click.drag", null); }, 0);
21055 if ("onselectstart" in root) {
21056 selection$$1.on("selectstart.drag", null);
21058 root.style.MozUserSelect = root.__noselect;
21059 delete root.__noselect;
21063 var constant$2 = function(x) {
21064 return function() {
21069 function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) {
21070 this.target = target;
21072 this.subject = subject;
21073 this.identifier = id;
21074 this.active = active;
21082 DragEvent.prototype.on = function() {
21083 var value = this._.on.apply(this._, arguments);
21084 return value === this._ ? this : value;
21087 // Ignore right-click, since that should open the context menu.
21088 function defaultFilter$1() {
21089 return !event.button;
21092 function defaultContainer() {
21093 return this.parentNode;
21096 function defaultSubject(d) {
21097 return d == null ? {x: event.x, y: event.y} : d;
21100 var drag = function() {
21101 var filter = defaultFilter$1,
21102 container = defaultContainer,
21103 subject = defaultSubject,
21105 listeners = dispatch("start", "drag", "end"),
21111 clickDistance2 = 0;
21113 function drag(selection) {
21115 .on("mousedown.drag", mousedowned)
21116 .on("touchstart.drag", touchstarted)
21117 .on("touchmove.drag", touchmoved)
21118 .on("touchend.drag touchcancel.drag", touchended)
21119 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
21122 function mousedowned() {
21123 if (touchending || !filter.apply(this, arguments)) return;
21124 var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments);
21125 if (!gesture) return;
21126 select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
21127 dragDisable(event.view);
21129 mousemoving = false;
21130 mousedownx = event.clientX;
21131 mousedowny = event.clientY;
21135 function mousemoved() {
21137 if (!mousemoving) {
21138 var dx = event.clientX - mousedownx, dy = event.clientY - mousedowny;
21139 mousemoving = dx * dx + dy * dy > clickDistance2;
21141 gestures.mouse("drag");
21144 function mouseupped() {
21145 select(event.view).on("mousemove.drag mouseup.drag", null);
21146 yesdrag(event.view, mousemoving);
21148 gestures.mouse("end");
21151 function touchstarted() {
21152 if (!filter.apply(this, arguments)) return;
21153 var touches$$1 = event.changedTouches,
21154 c = container.apply(this, arguments),
21155 n = touches$$1.length, i, gesture;
21157 for (i = 0; i < n; ++i) {
21158 if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) {
21165 function touchmoved() {
21166 var touches$$1 = event.changedTouches,
21167 n = touches$$1.length, i, gesture;
21169 for (i = 0; i < n; ++i) {
21170 if (gesture = gestures[touches$$1[i].identifier]) {
21177 function touchended() {
21178 var touches$$1 = event.changedTouches,
21179 n = touches$$1.length, i, gesture;
21181 if (touchending) clearTimeout(touchending);
21182 touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
21183 for (i = 0; i < n; ++i) {
21184 if (gesture = gestures[touches$$1[i].identifier]) {
21191 function beforestart(id, container, point, that, args) {
21192 var p = point(container, id), s, dx, dy,
21193 sublisteners = listeners.copy();
21195 if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() {
21196 if ((event.subject = s = subject.apply(that, args)) == null) return false;
21197 dx = s.x - p[0] || 0;
21198 dy = s.y - p[1] || 0;
21202 return function gesture(type) {
21205 case "start": gestures[id] = gesture, n = active++; break;
21206 case "end": delete gestures[id], --active; // nobreak
21207 case "drag": p = point(container, id), n = active; break;
21209 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]);
21213 drag.filter = function(_) {
21214 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter;
21217 drag.container = function(_) {
21218 return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container;
21221 drag.subject = function(_) {
21222 return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject;
21225 drag.on = function() {
21226 var value = listeners.on.apply(listeners, arguments);
21227 return value === listeners ? drag : value;
21230 drag.clickDistance = function(_) {
21231 return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2);
21237 var define = function(constructor, factory, prototype) {
21238 constructor.prototype = factory.prototype = prototype;
21239 prototype.constructor = constructor;
21242 function extend(parent, definition) {
21243 var prototype = Object.create(parent.prototype);
21244 for (var key in definition) prototype[key] = definition[key];
21248 function Color() {}
21251 var brighter = 1 / darker;
21253 var reI = "\\s*([+-]?\\d+)\\s*";
21254 var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*";
21255 var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*";
21256 var reHex3 = /^#([0-9a-f]{3})$/;
21257 var reHex6 = /^#([0-9a-f]{6})$/;
21258 var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$");
21259 var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$");
21260 var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$");
21261 var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$");
21262 var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$");
21263 var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
21266 aliceblue: 0xf0f8ff,
21267 antiquewhite: 0xfaebd7,
21269 aquamarine: 0x7fffd4,
21274 blanchedalmond: 0xffebcd,
21276 blueviolet: 0x8a2be2,
21278 burlywood: 0xdeb887,
21279 cadetblue: 0x5f9ea0,
21280 chartreuse: 0x7fff00,
21281 chocolate: 0xd2691e,
21283 cornflowerblue: 0x6495ed,
21284 cornsilk: 0xfff8dc,
21287 darkblue: 0x00008b,
21288 darkcyan: 0x008b8b,
21289 darkgoldenrod: 0xb8860b,
21290 darkgray: 0xa9a9a9,
21291 darkgreen: 0x006400,
21292 darkgrey: 0xa9a9a9,
21293 darkkhaki: 0xbdb76b,
21294 darkmagenta: 0x8b008b,
21295 darkolivegreen: 0x556b2f,
21296 darkorange: 0xff8c00,
21297 darkorchid: 0x9932cc,
21299 darksalmon: 0xe9967a,
21300 darkseagreen: 0x8fbc8f,
21301 darkslateblue: 0x483d8b,
21302 darkslategray: 0x2f4f4f,
21303 darkslategrey: 0x2f4f4f,
21304 darkturquoise: 0x00ced1,
21305 darkviolet: 0x9400d3,
21306 deeppink: 0xff1493,
21307 deepskyblue: 0x00bfff,
21310 dodgerblue: 0x1e90ff,
21311 firebrick: 0xb22222,
21312 floralwhite: 0xfffaf0,
21313 forestgreen: 0x228b22,
21315 gainsboro: 0xdcdcdc,
21316 ghostwhite: 0xf8f8ff,
21318 goldenrod: 0xdaa520,
21321 greenyellow: 0xadff2f,
21323 honeydew: 0xf0fff0,
21325 indianred: 0xcd5c5c,
21329 lavender: 0xe6e6fa,
21330 lavenderblush: 0xfff0f5,
21331 lawngreen: 0x7cfc00,
21332 lemonchiffon: 0xfffacd,
21333 lightblue: 0xadd8e6,
21334 lightcoral: 0xf08080,
21335 lightcyan: 0xe0ffff,
21336 lightgoldenrodyellow: 0xfafad2,
21337 lightgray: 0xd3d3d3,
21338 lightgreen: 0x90ee90,
21339 lightgrey: 0xd3d3d3,
21340 lightpink: 0xffb6c1,
21341 lightsalmon: 0xffa07a,
21342 lightseagreen: 0x20b2aa,
21343 lightskyblue: 0x87cefa,
21344 lightslategray: 0x778899,
21345 lightslategrey: 0x778899,
21346 lightsteelblue: 0xb0c4de,
21347 lightyellow: 0xffffe0,
21349 limegreen: 0x32cd32,
21353 mediumaquamarine: 0x66cdaa,
21354 mediumblue: 0x0000cd,
21355 mediumorchid: 0xba55d3,
21356 mediumpurple: 0x9370db,
21357 mediumseagreen: 0x3cb371,
21358 mediumslateblue: 0x7b68ee,
21359 mediumspringgreen: 0x00fa9a,
21360 mediumturquoise: 0x48d1cc,
21361 mediumvioletred: 0xc71585,
21362 midnightblue: 0x191970,
21363 mintcream: 0xf5fffa,
21364 mistyrose: 0xffe4e1,
21365 moccasin: 0xffe4b5,
21366 navajowhite: 0xffdead,
21370 olivedrab: 0x6b8e23,
21372 orangered: 0xff4500,
21374 palegoldenrod: 0xeee8aa,
21375 palegreen: 0x98fb98,
21376 paleturquoise: 0xafeeee,
21377 palevioletred: 0xdb7093,
21378 papayawhip: 0xffefd5,
21379 peachpuff: 0xffdab9,
21383 powderblue: 0xb0e0e6,
21385 rebeccapurple: 0x663399,
21387 rosybrown: 0xbc8f8f,
21388 royalblue: 0x4169e1,
21389 saddlebrown: 0x8b4513,
21391 sandybrown: 0xf4a460,
21392 seagreen: 0x2e8b57,
21393 seashell: 0xfff5ee,
21397 slateblue: 0x6a5acd,
21398 slategray: 0x708090,
21399 slategrey: 0x708090,
21401 springgreen: 0x00ff7f,
21402 steelblue: 0x4682b4,
21407 turquoise: 0x40e0d0,
21411 whitesmoke: 0xf5f5f5,
21413 yellowgreen: 0x9acd32
21416 define(Color, color, {
21417 displayable: function() {
21418 return this.rgb().displayable();
21420 toString: function() {
21421 return this.rgb() + "";
21425 function color(format) {
21427 format = (format + "").trim().toLowerCase();
21428 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
21429 : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
21430 : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
21431 : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
21432 : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
21433 : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
21434 : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
21435 : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
21436 : named.hasOwnProperty(format) ? rgbn(named[format])
21437 : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
21442 return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
21445 function rgba(r, g, b, a) {
21446 if (a <= 0) r = g = b = NaN;
21447 return new Rgb(r, g, b, a);
21450 function rgbConvert(o) {
21451 if (!(o instanceof Color)) o = color(o);
21452 if (!o) return new Rgb;
21454 return new Rgb(o.r, o.g, o.b, o.opacity);
21457 function rgb(r, g, b, opacity) {
21458 return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
21461 function Rgb(r, g, b, opacity) {
21465 this.opacity = +opacity;
21468 define(Rgb, rgb, extend(Color, {
21469 brighter: function(k) {
21470 k = k == null ? brighter : Math.pow(brighter, k);
21471 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
21473 darker: function(k) {
21474 k = k == null ? darker : Math.pow(darker, k);
21475 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
21480 displayable: function() {
21481 return (0 <= this.r && this.r <= 255)
21482 && (0 <= this.g && this.g <= 255)
21483 && (0 <= this.b && this.b <= 255)
21484 && (0 <= this.opacity && this.opacity <= 1);
21486 toString: function() {
21487 var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
21488 return (a === 1 ? "rgb(" : "rgba(")
21489 + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
21490 + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
21491 + Math.max(0, Math.min(255, Math.round(this.b) || 0))
21492 + (a === 1 ? ")" : ", " + a + ")");
21496 function hsla(h, s, l, a) {
21497 if (a <= 0) h = s = l = NaN;
21498 else if (l <= 0 || l >= 1) h = s = NaN;
21499 else if (s <= 0) h = NaN;
21500 return new Hsl(h, s, l, a);
21503 function hslConvert(o) {
21504 if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
21505 if (!(o instanceof Color)) o = color(o);
21506 if (!o) return new Hsl;
21507 if (o instanceof Hsl) return o;
21512 min = Math.min(r, g, b),
21513 max = Math.max(r, g, b),
21516 l = (max + min) / 2;
21518 if (r === max) h = (g - b) / s + (g < b) * 6;
21519 else if (g === max) h = (b - r) / s + 2;
21520 else h = (r - g) / s + 4;
21521 s /= l < 0.5 ? max + min : 2 - max - min;
21524 s = l > 0 && l < 1 ? 0 : h;
21526 return new Hsl(h, s, l, o.opacity);
21529 function hsl(h, s, l, opacity) {
21530 return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
21533 function Hsl(h, s, l, opacity) {
21537 this.opacity = +opacity;
21540 define(Hsl, hsl, extend(Color, {
21541 brighter: function(k) {
21542 k = k == null ? brighter : Math.pow(brighter, k);
21543 return new Hsl(this.h, this.s, this.l * k, this.opacity);
21545 darker: function(k) {
21546 k = k == null ? darker : Math.pow(darker, k);
21547 return new Hsl(this.h, this.s, this.l * k, this.opacity);
21550 var h = this.h % 360 + (this.h < 0) * 360,
21551 s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
21553 m2 = l + (l < 0.5 ? l : 1 - l) * s,
21556 hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
21557 hsl2rgb(h, m1, m2),
21558 hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
21562 displayable: function() {
21563 return (0 <= this.s && this.s <= 1 || isNaN(this.s))
21564 && (0 <= this.l && this.l <= 1)
21565 && (0 <= this.opacity && this.opacity <= 1);
21569 /* From FvD 13.37, CSS Color Module Level 3 */
21570 function hsl2rgb(h, m1, m2) {
21571 return (h < 60 ? m1 + (m2 - m1) * h / 60
21573 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
21577 var deg2rad = Math.PI / 180;
21578 var rad2deg = 180 / Math.PI;
21586 var t2 = 3 * t1 * t1;
21587 var t3 = t1 * t1 * t1;
21589 function labConvert(o) {
21590 if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
21591 if (o instanceof Hcl) {
21592 var h = o.h * deg2rad;
21593 return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
21595 if (!(o instanceof Rgb)) o = rgbConvert(o);
21596 var b = rgb2xyz(o.r),
21599 x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
21600 y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
21601 z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
21602 return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
21605 function lab(l, a, b, opacity) {
21606 return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
21609 function Lab(l, a, b, opacity) {
21613 this.opacity = +opacity;
21616 define(Lab, lab, extend(Color, {
21617 brighter: function(k) {
21618 return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
21620 darker: function(k) {
21621 return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
21624 var y = (this.l + 16) / 116,
21625 x = isNaN(this.a) ? y : y + this.a / 500,
21626 z = isNaN(this.b) ? y : y - this.b / 200;
21627 y = Yn * lab2xyz(y);
21628 x = Xn * lab2xyz(x);
21629 z = Zn * lab2xyz(z);
21631 xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
21632 xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
21633 xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
21639 function xyz2lab(t) {
21640 return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
21643 function lab2xyz(t) {
21644 return t > t1 ? t * t * t : t2 * (t - t0);
21647 function xyz2rgb(x) {
21648 return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
21651 function rgb2xyz(x) {
21652 return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
21655 function hclConvert(o) {
21656 if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
21657 if (!(o instanceof Lab)) o = labConvert(o);
21658 var h = Math.atan2(o.b, o.a) * rad2deg;
21659 return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
21662 function hcl(h, c, l, opacity) {
21663 return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
21666 function Hcl(h, c, l, opacity) {
21670 this.opacity = +opacity;
21673 define(Hcl, hcl, extend(Color, {
21674 brighter: function(k) {
21675 return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
21677 darker: function(k) {
21678 return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
21681 return labConvert(this).rgb();
21692 var BC_DA = B * C - D * A;
21694 function cubehelixConvert(o) {
21695 if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
21696 if (!(o instanceof Rgb)) o = rgbConvert(o);
21700 l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
21702 k = (E * (g - l) - C * bl) / D,
21703 s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
21704 h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
21705 return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
21708 function cubehelix(h, s, l, opacity) {
21709 return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
21712 function Cubehelix(h, s, l, opacity) {
21716 this.opacity = +opacity;
21719 define(Cubehelix, cubehelix, extend(Color, {
21720 brighter: function(k) {
21721 k = k == null ? brighter : Math.pow(brighter, k);
21722 return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
21724 darker: function(k) {
21725 k = k == null ? darker : Math.pow(darker, k);
21726 return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
21729 var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
21731 a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
21732 cosh = Math.cos(h),
21733 sinh = Math.sin(h);
21735 255 * (l + a * (A * cosh + B * sinh)),
21736 255 * (l + a * (C * cosh + D * sinh)),
21737 255 * (l + a * (E * cosh)),
21743 function basis(t1, v0, v1, v2, v3) {
21744 var t2 = t1 * t1, t3 = t2 * t1;
21745 return ((1 - 3 * t1 + 3 * t2 - t3) * v0
21746 + (4 - 6 * t2 + 3 * t3) * v1
21747 + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
21751 var basis$1 = function(values) {
21752 var n = values.length - 1;
21753 return function(t) {
21754 var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
21756 v2 = values[i + 1],
21757 v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
21758 v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
21759 return basis((t - i / n) * n, v0, v1, v2, v3);
21763 var basisClosed = function(values) {
21764 var n = values.length;
21765 return function(t) {
21766 var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),
21767 v0 = values[(i + n - 1) % n],
21768 v1 = values[i % n],
21769 v2 = values[(i + 1) % n],
21770 v3 = values[(i + 2) % n];
21771 return basis((t - i / n) * n, v0, v1, v2, v3);
21775 var constant$3 = function(x) {
21776 return function() {
21781 function linear(a, d) {
21782 return function(t) {
21787 function exponential(a, b, y) {
21788 return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
21789 return Math.pow(a + t * b, y);
21793 function hue(a, b) {
21795 return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a);
21798 function gamma(y) {
21799 return (y = +y) === 1 ? nogamma : function(a, b) {
21800 return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a);
21804 function nogamma(a, b) {
21806 return d ? linear(a, d) : constant$3(isNaN(a) ? b : a);
21809 var interpolateRgb = (function rgbGamma(y) {
21810 var color$$1 = gamma(y);
21812 function rgb$$1(start, end) {
21813 var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r),
21814 g = color$$1(start.g, end.g),
21815 b = color$$1(start.b, end.b),
21816 opacity = nogamma(start.opacity, end.opacity);
21817 return function(t) {
21821 start.opacity = opacity(t);
21826 rgb$$1.gamma = rgbGamma;
21831 function rgbSpline(spline) {
21832 return function(colors) {
21833 var n = colors.length,
21838 for (i = 0; i < n; ++i) {
21839 color$$1 = rgb(colors[i]);
21840 r[i] = color$$1.r || 0;
21841 g[i] = color$$1.g || 0;
21842 b[i] = color$$1.b || 0;
21847 color$$1.opacity = 1;
21848 return function(t) {
21852 return color$$1 + "";
21857 var rgbBasis = rgbSpline(basis$1);
21858 var rgbBasisClosed = rgbSpline(basisClosed);
21860 var array$1 = function(a, b) {
21861 var nb = b ? b.length : 0,
21862 na = a ? Math.min(nb, a.length) : 0,
21867 for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]);
21868 for (; i < nb; ++i) c[i] = b[i];
21870 return function(t) {
21871 for (i = 0; i < na; ++i) c[i] = x[i](t);
21876 var date = function(a, b) {
21878 return a = +a, b -= a, function(t) {
21879 return d.setTime(a + b * t), d;
21883 var reinterpolate = function(a, b) {
21884 return a = +a, b -= a, function(t) {
21889 var object = function(a, b) {
21894 if (a === null || typeof a !== "object") a = {};
21895 if (b === null || typeof b !== "object") b = {};
21899 i[k] = interpolateValue(a[k], b[k]);
21905 return function(t) {
21906 for (k in i) c[k] = i[k](t);
21911 var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
21912 var reB = new RegExp(reA.source, "g");
21915 return function() {
21921 return function(t) {
21926 var interpolateString = function(a, b) {
21927 var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
21928 am, // current match in a
21929 bm, // current match in b
21930 bs, // string preceding current number in b, if any
21931 i = -1, // index in s
21932 s = [], // string constants and placeholders
21933 q = []; // number interpolators
21935 // Coerce inputs to strings.
21936 a = a + "", b = b + "";
21938 // Interpolate pairs of numbers in a & b.
21939 while ((am = reA.exec(a))
21940 && (bm = reB.exec(b))) {
21941 if ((bs = bm.index) > bi) { // a string precedes the next number in b
21942 bs = b.slice(bi, bs);
21943 if (s[i]) s[i] += bs; // coalesce with previous string
21946 if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
21947 if (s[i]) s[i] += bm; // coalesce with previous string
21949 } else { // interpolate non-matching numbers
21951 q.push({i: i, x: reinterpolate(am, bm)});
21953 bi = reB.lastIndex;
21956 // Add remains of b.
21957 if (bi < b.length) {
21959 if (s[i]) s[i] += bs; // coalesce with previous string
21963 // Special optimization for only a single match.
21964 // Otherwise, interpolate each of the numbers and rejoin the string.
21965 return s.length < 2 ? (q[0]
21968 : (b = q.length, function(t) {
21969 for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
21974 var interpolateValue = function(a, b) {
21975 var t = typeof b, c;
21976 return b == null || t === "boolean" ? constant$3(b)
21977 : (t === "number" ? reinterpolate
21978 : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString)
21979 : b instanceof color ? interpolateRgb
21980 : b instanceof Date ? date
21981 : Array.isArray(b) ? array$1
21982 : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object
21983 : reinterpolate)(a, b);
21986 var interpolateRound = function(a, b) {
21987 return a = +a, b -= a, function(t) {
21988 return Math.round(a + b * t);
21992 var degrees = 180 / Math.PI;
22003 var decompose = function(a, b, c, d, e, f) {
22004 var scaleX, scaleY, skewX;
22005 if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
22006 if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
22007 if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
22008 if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
22012 rotate: Math.atan2(b, a) * degrees,
22013 skewX: Math.atan(skewX) * degrees,
22024 function parseCss(value) {
22025 if (value === "none") return identity$2;
22026 if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView;
22027 cssNode.style.transform = value;
22028 value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform");
22029 cssRoot.removeChild(cssNode);
22030 value = value.slice(7, -1).split(",");
22031 return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
22034 function parseSvg(value) {
22035 if (value == null) return identity$2;
22036 if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
22037 svgNode.setAttribute("transform", value);
22038 if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2;
22039 value = value.matrix;
22040 return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
22043 function interpolateTransform(parse, pxComma, pxParen, degParen) {
22046 return s.length ? s.pop() + " " : "";
22049 function translate(xa, ya, xb, yb, s, q) {
22050 if (xa !== xb || ya !== yb) {
22051 var i = s.push("translate(", null, pxComma, null, pxParen);
22052 q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)});
22053 } else if (xb || yb) {
22054 s.push("translate(" + xb + pxComma + yb + pxParen);
22058 function rotate(a, b, s, q) {
22060 if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
22061 q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: reinterpolate(a, b)});
22063 s.push(pop(s) + "rotate(" + b + degParen);
22067 function skewX(a, b, s, q) {
22069 q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: reinterpolate(a, b)});
22071 s.push(pop(s) + "skewX(" + b + degParen);
22075 function scale(xa, ya, xb, yb, s, q) {
22076 if (xa !== xb || ya !== yb) {
22077 var i = s.push(pop(s) + "scale(", null, ",", null, ")");
22078 q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)});
22079 } else if (xb !== 1 || yb !== 1) {
22080 s.push(pop(s) + "scale(" + xb + "," + yb + ")");
22084 return function(a, b) {
22085 var s = [], // string constants and placeholders
22086 q = []; // number interpolators
22087 a = parse(a), b = parse(b);
22088 translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
22089 rotate(a.rotate, b.rotate, s, q);
22090 skewX(a.skewX, b.skewX, s, q);
22091 scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
22092 a = b = null; // gc
22093 return function(t) {
22094 var i = -1, n = q.length, o;
22095 while (++i < n) s[(o = q[i]).i] = o.x(t);
22101 var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
22102 var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
22104 var rho = Math.SQRT2;
22107 var epsilon2 = 1e-12;
22110 return ((x = Math.exp(x)) + 1 / x) / 2;
22114 return ((x = Math.exp(x)) - 1 / x) / 2;
22118 return ((x = Math.exp(2 * x)) - 1) / (x + 1);
22121 // p0 = [ux0, uy0, w0]
22122 // p1 = [ux1, uy1, w1]
22123 var interpolateZoom = function(p0, p1) {
22124 var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
22125 ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
22128 d2 = dx * dx + dy * dy,
22132 // Special case for u0 ≅ u1.
22133 if (d2 < epsilon2) {
22134 S = Math.log(w1 / w0) / rho;
22139 w0 * Math.exp(rho * t * S)
22146 var d1 = Math.sqrt(d2),
22147 b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
22148 b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
22149 r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
22150 r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
22151 S = (r1 - r0) / rho;
22155 u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
22159 w0 * coshr0 / cosh(rho * s + r0)
22164 i.duration = S * 1000;
22169 function hsl$1(hue$$1) {
22170 return function(start, end) {
22171 var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h),
22172 s = nogamma(start.s, end.s),
22173 l = nogamma(start.l, end.l),
22174 opacity = nogamma(start.opacity, end.opacity);
22175 return function(t) {
22179 start.opacity = opacity(t);
22185 var hsl$2 = hsl$1(hue);
22186 var hslLong = hsl$1(nogamma);
22188 function lab$1(start, end) {
22189 var l = nogamma((start = lab(start)).l, (end = lab(end)).l),
22190 a = nogamma(start.a, end.a),
22191 b = nogamma(start.b, end.b),
22192 opacity = nogamma(start.opacity, end.opacity);
22193 return function(t) {
22197 start.opacity = opacity(t);
22202 function hcl$1(hue$$1) {
22203 return function(start, end) {
22204 var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h),
22205 c = nogamma(start.c, end.c),
22206 l = nogamma(start.l, end.l),
22207 opacity = nogamma(start.opacity, end.opacity);
22208 return function(t) {
22212 start.opacity = opacity(t);
22218 var hcl$2 = hcl$1(hue);
22219 var hclLong = hcl$1(nogamma);
22221 function cubehelix$1(hue$$1) {
22222 return (function cubehelixGamma(y) {
22225 function cubehelix$$1(start, end) {
22226 var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h),
22227 s = nogamma(start.s, end.s),
22228 l = nogamma(start.l, end.l),
22229 opacity = nogamma(start.opacity, end.opacity);
22230 return function(t) {
22233 start.l = l(Math.pow(t, y));
22234 start.opacity = opacity(t);
22239 cubehelix$$1.gamma = cubehelixGamma;
22241 return cubehelix$$1;
22245 var cubehelix$2 = cubehelix$1(hue);
22246 var cubehelixLong = cubehelix$1(nogamma);
22248 var quantize = function(interpolator, n) {
22249 var samples = new Array(n);
22250 for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));
22257 var pokeDelay = 1000;
22263 var clock = typeof performance === "object" && performance.now ? performance : Date;
22264 var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); };
22267 return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
22270 function clearNow() {
22280 Timer.prototype = timer.prototype = {
22281 constructor: Timer,
22282 restart: function(callback, delay, time) {
22283 if (typeof callback !== "function") throw new TypeError("callback is not a function");
22284 time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
22285 if (!this._next && taskTail !== this) {
22286 if (taskTail) taskTail._next = this;
22287 else taskHead = this;
22290 this._call = callback;
22297 this._time = Infinity;
22303 function timer(callback, delay, time) {
22305 t.restart(callback, delay, time);
22309 function timerFlush() {
22310 now(); // Get the current time, if not already set.
22311 ++frame; // Pretend we’ve set an alarm, if we haven’t already.
22312 var t = taskHead, e;
22314 if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
22321 clockNow = (clockLast = clock.now()) + clockSkew;
22322 frame = timeout = 0;
22333 var now = clock.now(), delay = now - clockLast;
22334 if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
22338 var t0, t1 = taskHead, t2, time = Infinity;
22341 if (time > t1._time) time = t1._time;
22342 t0 = t1, t1 = t1._next;
22344 t2 = t1._next, t1._next = null;
22345 t1 = t0 ? t0._next = t2 : taskHead = t2;
22352 function sleep(time) {
22353 if (frame) return; // Soonest alarm already set, or will be.
22354 if (timeout) timeout = clearTimeout(timeout);
22355 var delay = time - clockNow;
22357 if (time < Infinity) timeout = setTimeout(wake, delay);
22358 if (interval) interval = clearInterval(interval);
22360 if (!interval) clockLast = clockNow, interval = setInterval(poke, pokeDelay);
22361 frame = 1, setFrame(wake);
22365 var timeout$1 = function(callback, delay, time) {
22367 delay = delay == null ? 0 : +delay;
22368 t.restart(function(elapsed) {
22370 callback(elapsed + delay);
22375 var interval$1 = function(callback, delay, time) {
22376 var t = new Timer, total = delay;
22377 if (delay == null) return t.restart(callback, delay, time), t;
22378 delay = +delay, time = time == null ? now() : +time;
22379 t.restart(function tick(elapsed) {
22381 t.restart(tick, total += delay, time);
22387 var emptyOn = dispatch("start", "end", "interrupt");
22388 var emptyTween = [];
22398 var schedule = function(node, name, id, index, group, timing) {
22399 var schedules = node.__transition;
22400 if (!schedules) node.__transition = {};
22401 else if (id in schedules) return;
22404 index: index, // For context during callback.
22405 group: group, // For context during callback.
22409 delay: timing.delay,
22410 duration: timing.duration,
22417 function init(node, id) {
22418 var schedule = node.__transition;
22419 if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late");
22423 function set$1(node, id) {
22424 var schedule = node.__transition;
22425 if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late");
22429 function get$1(node, id) {
22430 var schedule = node.__transition;
22431 if (!schedule || !(schedule = schedule[id])) throw new Error("too late");
22435 function create(node, id, self) {
22436 var schedules = node.__transition,
22439 // Initialize the self timer when the transition is created.
22440 // Note the actual delay is not known until the first callback!
22441 schedules[id] = self;
22442 self.timer = timer(schedule, 0, self.time);
22444 function schedule(elapsed) {
22445 self.state = SCHEDULED;
22446 self.timer.restart(start, self.delay, self.time);
22448 // If the elapsed delay is less than our first sleep, start immediately.
22449 if (self.delay <= elapsed) start(elapsed - self.delay);
22452 function start(elapsed) {
22455 // If the state is not SCHEDULED, then we previously errored on start.
22456 if (self.state !== SCHEDULED) return stop();
22458 for (i in schedules) {
22460 if (o.name !== self.name) continue;
22462 // While this element already has a starting transition during this frame,
22463 // defer starting an interrupting transition until that transition has a
22464 // chance to tick (and possibly end); see d3/d3-transition#54!
22465 if (o.state === STARTED) return timeout$1(start);
22467 // Interrupt the active transition, if any.
22468 // Dispatch the interrupt event.
22469 if (o.state === RUNNING) {
22472 o.on.call("interrupt", node, node.__data__, o.index, o.group);
22473 delete schedules[i];
22476 // Cancel any pre-empted transitions. No interrupt event is dispatched
22477 // because the cancelled transitions never started. Note that this also
22478 // removes this transition from the pending list!
22479 else if (+i < id) {
22482 delete schedules[i];
22486 // Defer the first tick to end of the current frame; see d3/d3#1576.
22487 // Note the transition may be canceled after start and before the first tick!
22488 // Note this must be scheduled before the start event; see d3/d3-transition#16!
22489 // Assuming this is successful, subsequent callbacks go straight to tick.
22490 timeout$1(function() {
22491 if (self.state === STARTED) {
22492 self.state = RUNNING;
22493 self.timer.restart(tick, self.delay, self.time);
22498 // Dispatch the start event.
22499 // Note this must be done before the tween are initialized.
22500 self.state = STARTING;
22501 self.on.call("start", node, node.__data__, self.index, self.group);
22502 if (self.state !== STARTING) return; // interrupted
22503 self.state = STARTED;
22505 // Initialize the tween, deleting null tween.
22506 tween = new Array(n = self.tween.length);
22507 for (i = 0, j = -1; i < n; ++i) {
22508 if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
22512 tween.length = j + 1;
22515 function tick(elapsed) {
22516 var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
22521 tween[i].call(null, t);
22524 // Dispatch the end event.
22525 if (self.state === ENDING) {
22526 self.on.call("end", node, node.__data__, self.index, self.group);
22532 self.state = ENDED;
22534 delete schedules[id];
22535 for (var i in schedules) return; // eslint-disable-line no-unused-vars
22536 delete node.__transition;
22540 var interrupt = function(node, name) {
22541 var schedules = node.__transition,
22547 if (!schedules) return;
22549 name = name == null ? null : name + "";
22551 for (i in schedules) {
22552 if ((schedule$$1 = schedules[i]).name !== name) { empty = false; continue; }
22553 active = schedule$$1.state > STARTING && schedule$$1.state < ENDING;
22554 schedule$$1.state = ENDED;
22555 schedule$$1.timer.stop();
22556 if (active) schedule$$1.on.call("interrupt", node, node.__data__, schedule$$1.index, schedule$$1.group);
22557 delete schedules[i];
22560 if (empty) delete node.__transition;
22563 var selection_interrupt = function(name) {
22564 return this.each(function() {
22565 interrupt(this, name);
22569 function tweenRemove(id, name) {
22570 var tween0, tween1;
22571 return function() {
22572 var schedule$$1 = set$1(this, id),
22573 tween = schedule$$1.tween;
22575 // If this node shared tween with the previous node,
22576 // just assign the updated shared tween and we’re done!
22577 // Otherwise, copy-on-write.
22578 if (tween !== tween0) {
22579 tween1 = tween0 = tween;
22580 for (var i = 0, n = tween1.length; i < n; ++i) {
22581 if (tween1[i].name === name) {
22582 tween1 = tween1.slice();
22583 tween1.splice(i, 1);
22589 schedule$$1.tween = tween1;
22593 function tweenFunction(id, name, value) {
22594 var tween0, tween1;
22595 if (typeof value !== "function") throw new Error;
22596 return function() {
22597 var schedule$$1 = set$1(this, id),
22598 tween = schedule$$1.tween;
22600 // If this node shared tween with the previous node,
22601 // just assign the updated shared tween and we’re done!
22602 // Otherwise, copy-on-write.
22603 if (tween !== tween0) {
22604 tween1 = (tween0 = tween).slice();
22605 for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) {
22606 if (tween1[i].name === name) {
22611 if (i === n) tween1.push(t);
22614 schedule$$1.tween = tween1;
22618 var transition_tween = function(name, value) {
22623 if (arguments.length < 2) {
22624 var tween = get$1(this.node(), id).tween;
22625 for (var i = 0, n = tween.length, t; i < n; ++i) {
22626 if ((t = tween[i]).name === name) {
22633 return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
22636 function tweenValue(transition, name, value) {
22637 var id = transition._id;
22639 transition.each(function() {
22640 var schedule$$1 = set$1(this, id);
22641 (schedule$$1.value || (schedule$$1.value = {}))[name] = value.apply(this, arguments);
22644 return function(node) {
22645 return get$1(node, id).value[name];
22649 var interpolate = function(a, b) {
22651 return (typeof b === "number" ? reinterpolate
22652 : b instanceof color ? interpolateRgb
22653 : (c = color(b)) ? (b = c, interpolateRgb)
22654 : interpolateString)(a, b);
22657 function attrRemove$1(name) {
22658 return function() {
22659 this.removeAttribute(name);
22663 function attrRemoveNS$1(fullname) {
22664 return function() {
22665 this.removeAttributeNS(fullname.space, fullname.local);
22669 function attrConstant$1(name, interpolate$$1, value1) {
22672 return function() {
22673 var value0 = this.getAttribute(name);
22674 return value0 === value1 ? null
22675 : value0 === value00 ? interpolate0
22676 : interpolate0 = interpolate$$1(value00 = value0, value1);
22680 function attrConstantNS$1(fullname, interpolate$$1, value1) {
22683 return function() {
22684 var value0 = this.getAttributeNS(fullname.space, fullname.local);
22685 return value0 === value1 ? null
22686 : value0 === value00 ? interpolate0
22687 : interpolate0 = interpolate$$1(value00 = value0, value1);
22691 function attrFunction$1(name, interpolate$$1, value) {
22695 return function() {
22696 var value0, value1 = value(this);
22697 if (value1 == null) return void this.removeAttribute(name);
22698 value0 = this.getAttribute(name);
22699 return value0 === value1 ? null
22700 : value0 === value00 && value1 === value10 ? interpolate0
22701 : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22705 function attrFunctionNS$1(fullname, interpolate$$1, value) {
22709 return function() {
22710 var value0, value1 = value(this);
22711 if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
22712 value0 = this.getAttributeNS(fullname.space, fullname.local);
22713 return value0 === value1 ? null
22714 : value0 === value00 && value1 === value10 ? interpolate0
22715 : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22719 var transition_attr = function(name, value) {
22720 var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate;
22721 return this.attrTween(name, typeof value === "function"
22722 ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value))
22723 : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname)
22724 : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value + ""));
22727 function attrTweenNS(fullname, value) {
22729 var node = this, i = value.apply(node, arguments);
22730 return i && function(t) {
22731 node.setAttributeNS(fullname.space, fullname.local, i(t));
22734 tween._value = value;
22738 function attrTween(name, value) {
22740 var node = this, i = value.apply(node, arguments);
22741 return i && function(t) {
22742 node.setAttribute(name, i(t));
22745 tween._value = value;
22749 var transition_attrTween = function(name, value) {
22750 var key = "attr." + name;
22751 if (arguments.length < 2) return (key = this.tween(key)) && key._value;
22752 if (value == null) return this.tween(key, null);
22753 if (typeof value !== "function") throw new Error;
22754 var fullname = namespace(name);
22755 return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
22758 function delayFunction(id, value) {
22759 return function() {
22760 init(this, id).delay = +value.apply(this, arguments);
22764 function delayConstant(id, value) {
22765 return value = +value, function() {
22766 init(this, id).delay = value;
22770 var transition_delay = function(value) {
22773 return arguments.length
22774 ? this.each((typeof value === "function"
22776 : delayConstant)(id, value))
22777 : get$1(this.node(), id).delay;
22780 function durationFunction(id, value) {
22781 return function() {
22782 set$1(this, id).duration = +value.apply(this, arguments);
22786 function durationConstant(id, value) {
22787 return value = +value, function() {
22788 set$1(this, id).duration = value;
22792 var transition_duration = function(value) {
22795 return arguments.length
22796 ? this.each((typeof value === "function"
22798 : durationConstant)(id, value))
22799 : get$1(this.node(), id).duration;
22802 function easeConstant(id, value) {
22803 if (typeof value !== "function") throw new Error;
22804 return function() {
22805 set$1(this, id).ease = value;
22809 var transition_ease = function(value) {
22812 return arguments.length
22813 ? this.each(easeConstant(id, value))
22814 : get$1(this.node(), id).ease;
22817 var transition_filter = function(match) {
22818 if (typeof match !== "function") match = matcher$1(match);
22820 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
22821 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
22822 if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
22823 subgroup.push(node);
22828 return new Transition(subgroups, this._parents, this._name, this._id);
22831 var transition_merge = function(transition$$1) {
22832 if (transition$$1._id !== this._id) throw new Error;
22834 for (var groups0 = this._groups, groups1 = transition$$1._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
22835 for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
22836 if (node = group0[i] || group1[i]) {
22842 for (; j < m0; ++j) {
22843 merges[j] = groups0[j];
22846 return new Transition(merges, this._parents, this._name, this._id);
22849 function start(name) {
22850 return (name + "").trim().split(/^|\s+/).every(function(t) {
22851 var i = t.indexOf(".");
22852 if (i >= 0) t = t.slice(0, i);
22853 return !t || t === "start";
22857 function onFunction(id, name, listener) {
22858 var on0, on1, sit = start(name) ? init : set$1;
22859 return function() {
22860 var schedule$$1 = sit(this, id),
22861 on = schedule$$1.on;
22863 // If this node shared a dispatch with the previous node,
22864 // just assign the updated shared dispatch and we’re done!
22865 // Otherwise, copy-on-write.
22866 if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
22868 schedule$$1.on = on1;
22872 var transition_on = function(name, listener) {
22875 return arguments.length < 2
22876 ? get$1(this.node(), id).on.on(name)
22877 : this.each(onFunction(id, name, listener));
22880 function removeFunction(id) {
22881 return function() {
22882 var parent = this.parentNode;
22883 for (var i in this.__transition) if (+i !== id) return;
22884 if (parent) parent.removeChild(this);
22888 var transition_remove = function() {
22889 return this.on("end.remove", removeFunction(this._id));
22892 var transition_select = function(select$$1) {
22893 var name = this._name,
22896 if (typeof select$$1 !== "function") select$$1 = selector(select$$1);
22898 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
22899 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
22900 if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) {
22901 if ("__data__" in node) subnode.__data__ = node.__data__;
22902 subgroup[i] = subnode;
22903 schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
22908 return new Transition(subgroups, this._parents, name, id);
22911 var transition_selectAll = function(select$$1) {
22912 var name = this._name,
22915 if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1);
22917 for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
22918 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
22919 if (node = group[i]) {
22920 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) {
22921 if (child = children[k]) {
22922 schedule(child, name, id, k, children, inherit);
22925 subgroups.push(children);
22926 parents.push(node);
22931 return new Transition(subgroups, parents, name, id);
22934 var Selection$1 = selection.prototype.constructor;
22936 var transition_selection = function() {
22937 return new Selection$1(this._groups, this._parents);
22940 function styleRemove$1(name, interpolate$$1) {
22944 return function() {
22945 var value0 = styleValue(this, name),
22946 value1 = (this.style.removeProperty(name), styleValue(this, name));
22947 return value0 === value1 ? null
22948 : value0 === value00 && value1 === value10 ? interpolate0
22949 : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22953 function styleRemoveEnd(name) {
22954 return function() {
22955 this.style.removeProperty(name);
22959 function styleConstant$1(name, interpolate$$1, value1) {
22962 return function() {
22963 var value0 = styleValue(this, name);
22964 return value0 === value1 ? null
22965 : value0 === value00 ? interpolate0
22966 : interpolate0 = interpolate$$1(value00 = value0, value1);
22970 function styleFunction$1(name, interpolate$$1, value) {
22974 return function() {
22975 var value0 = styleValue(this, name),
22976 value1 = value(this);
22977 if (value1 == null) value1 = (this.style.removeProperty(name), styleValue(this, name));
22978 return value0 === value1 ? null
22979 : value0 === value00 && value1 === value10 ? interpolate0
22980 : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22984 var transition_style = function(name, value, priority) {
22985 var i = (name += "") === "transform" ? interpolateTransformCss : interpolate;
22986 return value == null ? this
22987 .styleTween(name, styleRemove$1(name, i))
22988 .on("end.style." + name, styleRemoveEnd(name))
22989 : this.styleTween(name, typeof value === "function"
22990 ? styleFunction$1(name, i, tweenValue(this, "style." + name, value))
22991 : styleConstant$1(name, i, value + ""), priority);
22994 function styleTween(name, value, priority) {
22996 var node = this, i = value.apply(node, arguments);
22997 return i && function(t) {
22998 node.style.setProperty(name, i(t), priority);
23001 tween._value = value;
23005 var transition_styleTween = function(name, value, priority) {
23006 var key = "style." + (name += "");
23007 if (arguments.length < 2) return (key = this.tween(key)) && key._value;
23008 if (value == null) return this.tween(key, null);
23009 if (typeof value !== "function") throw new Error;
23010 return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
23013 function textConstant$1(value) {
23014 return function() {
23015 this.textContent = value;
23019 function textFunction$1(value) {
23020 return function() {
23021 var value1 = value(this);
23022 this.textContent = value1 == null ? "" : value1;
23026 var transition_text = function(value) {
23027 return this.tween("text", typeof value === "function"
23028 ? textFunction$1(tweenValue(this, "text", value))
23029 : textConstant$1(value == null ? "" : value + ""));
23032 var transition_transition = function() {
23033 var name = this._name,
23037 for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
23038 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
23039 if (node = group[i]) {
23040 var inherit = get$1(node, id0);
23041 schedule(node, name, id1, i, group, {
23042 time: inherit.time + inherit.delay + inherit.duration,
23044 duration: inherit.duration,
23051 return new Transition(groups, this._parents, name, id1);
23056 function Transition(groups, parents, name, id) {
23057 this._groups = groups;
23058 this._parents = parents;
23063 function transition(name) {
23064 return selection().transition(name);
23071 var selection_prototype = selection.prototype;
23073 Transition.prototype = transition.prototype = {
23074 constructor: Transition,
23075 select: transition_select,
23076 selectAll: transition_selectAll,
23077 filter: transition_filter,
23078 merge: transition_merge,
23079 selection: transition_selection,
23080 transition: transition_transition,
23081 call: selection_prototype.call,
23082 nodes: selection_prototype.nodes,
23083 node: selection_prototype.node,
23084 size: selection_prototype.size,
23085 empty: selection_prototype.empty,
23086 each: selection_prototype.each,
23088 attr: transition_attr,
23089 attrTween: transition_attrTween,
23090 style: transition_style,
23091 styleTween: transition_styleTween,
23092 text: transition_text,
23093 remove: transition_remove,
23094 tween: transition_tween,
23095 delay: transition_delay,
23096 duration: transition_duration,
23097 ease: transition_ease
23100 function linear$1(t) {
23104 function quadIn(t) {
23108 function quadOut(t) {
23109 return t * (2 - t);
23112 function quadInOut(t) {
23113 return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
23116 function cubicIn(t) {
23120 function cubicOut(t) {
23121 return --t * t * t + 1;
23124 function cubicInOut(t) {
23125 return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
23130 var polyIn = (function custom(e) {
23133 function polyIn(t) {
23134 return Math.pow(t, e);
23137 polyIn.exponent = custom;
23142 var polyOut = (function custom(e) {
23145 function polyOut(t) {
23146 return 1 - Math.pow(1 - t, e);
23149 polyOut.exponent = custom;
23154 var polyInOut = (function custom(e) {
23157 function polyInOut(t) {
23158 return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2;
23161 polyInOut.exponent = custom;
23167 var halfPi = pi / 2;
23169 function sinIn(t) {
23170 return 1 - Math.cos(t * halfPi);
23173 function sinOut(t) {
23174 return Math.sin(t * halfPi);
23177 function sinInOut(t) {
23178 return (1 - Math.cos(pi * t)) / 2;
23181 function expIn(t) {
23182 return Math.pow(2, 10 * t - 10);
23185 function expOut(t) {
23186 return 1 - Math.pow(2, -10 * t);
23189 function expInOut(t) {
23190 return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2;
23193 function circleIn(t) {
23194 return 1 - Math.sqrt(1 - t * t);
23197 function circleOut(t) {
23198 return Math.sqrt(1 - --t * t);
23201 function circleInOut(t) {
23202 return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2;
23214 var b0 = 1 / b1 / b1;
23216 function bounceIn(t) {
23217 return 1 - bounceOut(1 - t);
23220 function bounceOut(t) {
23221 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;
23224 function bounceInOut(t) {
23225 return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2;
23228 var overshoot = 1.70158;
23230 var backIn = (function custom(s) {
23233 function backIn(t) {
23234 return t * t * ((s + 1) * t - s);
23237 backIn.overshoot = custom;
23242 var backOut = (function custom(s) {
23245 function backOut(t) {
23246 return --t * t * ((s + 1) * t + s) + 1;
23249 backOut.overshoot = custom;
23254 var backInOut = (function custom(s) {
23257 function backInOut(t) {
23258 return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2;
23261 backInOut.overshoot = custom;
23266 var tau = 2 * Math.PI;
23270 var elasticIn = (function custom(a, p) {
23271 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23273 function elasticIn(t) {
23274 return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p);
23277 elasticIn.amplitude = function(a) { return custom(a, p * tau); };
23278 elasticIn.period = function(p) { return custom(a, p); };
23281 })(amplitude, period);
23283 var elasticOut = (function custom(a, p) {
23284 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23286 function elasticOut(t) {
23287 return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p);
23290 elasticOut.amplitude = function(a) { return custom(a, p * tau); };
23291 elasticOut.period = function(p) { return custom(a, p); };
23294 })(amplitude, period);
23296 var elasticInOut = (function custom(a, p) {
23297 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23299 function elasticInOut(t) {
23300 return ((t = t * 2 - 1) < 0
23301 ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p)
23302 : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2;
23305 elasticInOut.amplitude = function(a) { return custom(a, p * tau); };
23306 elasticInOut.period = function(p) { return custom(a, p); };
23308 return elasticInOut;
23309 })(amplitude, period);
23311 var defaultTiming = {
23312 time: null, // Set on use.
23318 function inherit(node, id) {
23320 while (!(timing = node.__transition) || !(timing = timing[id])) {
23321 if (!(node = node.parentNode)) {
23322 return defaultTiming.time = now(), defaultTiming;
23328 var selection_transition = function(name) {
23332 if (name instanceof Transition) {
23333 id = name._id, name = name._name;
23335 id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "";
23338 for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
23339 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
23340 if (node = group[i]) {
23341 schedule(node, name, id, i, group, timing || inherit(node, id));
23346 return new Transition(groups, this._parents, name, id);
23349 selection.prototype.interrupt = selection_interrupt;
23350 selection.prototype.transition = selection_transition;
23352 var root$1 = [null];
23354 var active = function(node, name) {
23355 var schedules = node.__transition,
23360 name = name == null ? null : name + "";
23361 for (i in schedules) {
23362 if ((schedule$$1 = schedules[i]).state > SCHEDULED && schedule$$1.name === name) {
23363 return new Transition([[node]], root$1, name, +i);
23371 var constant$4 = function(x) {
23372 return function() {
23377 var BrushEvent = function(target, type, selection) {
23378 this.target = target;
23380 this.selection = selection;
23383 function nopropagation$1() {
23384 event.stopImmediatePropagation();
23387 var noevent$1 = function() {
23388 event.preventDefault();
23389 event.stopImmediatePropagation();
23392 var MODE_DRAG = {name: "drag"};
23393 var MODE_SPACE = {name: "space"};
23394 var MODE_HANDLE = {name: "handle"};
23395 var MODE_CENTER = {name: "center"};
23399 handles: ["e", "w"].map(type$2),
23400 input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
23401 output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
23406 handles: ["n", "s"].map(type$2),
23407 input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
23408 output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
23413 handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$2),
23414 input: function(xy) { return xy; },
23415 output: function(xy) { return xy; }
23419 overlay: "crosshair",
23475 function type$2(t) {
23479 // Ignore right-click, since that should open the context menu.
23480 function defaultFilter() {
23481 return !event.button;
23484 function defaultExtent() {
23485 var svg = this.ownerSVGElement || this;
23486 return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
23489 // Like d3.local, but with the name “__brush” rather than auto-generated.
23490 function local$$1(node) {
23491 while (!node.__brush) if (!(node = node.parentNode)) return;
23492 return node.__brush;
23495 function empty(extent) {
23496 return extent[0][0] === extent[1][0]
23497 || extent[0][1] === extent[1][1];
23500 function brushSelection(node) {
23501 var state = node.__brush;
23502 return state ? state.dim.output(state.selection) : null;
23505 function brushX() {
23509 function brushY() {
23513 var brush = function() {
23514 return brush$1(XY);
23517 function brush$1(dim) {
23518 var extent = defaultExtent,
23519 filter = defaultFilter,
23520 listeners = dispatch(brush, "start", "brush", "end"),
23524 function brush(group) {
23525 var overlay = group
23526 .property("__brush", initialize)
23527 .selectAll(".overlay")
23528 .data([type$2("overlay")]);
23530 overlay.enter().append("rect")
23531 .attr("class", "overlay")
23532 .attr("pointer-events", "all")
23533 .attr("cursor", cursors.overlay)
23536 var extent = local$$1(this).extent;
23538 .attr("x", extent[0][0])
23539 .attr("y", extent[0][1])
23540 .attr("width", extent[1][0] - extent[0][0])
23541 .attr("height", extent[1][1] - extent[0][1]);
23544 group.selectAll(".selection")
23545 .data([type$2("selection")])
23546 .enter().append("rect")
23547 .attr("class", "selection")
23548 .attr("cursor", cursors.selection)
23549 .attr("fill", "#777")
23550 .attr("fill-opacity", 0.3)
23551 .attr("stroke", "#fff")
23552 .attr("shape-rendering", "crispEdges");
23554 var handle = group.selectAll(".handle")
23555 .data(dim.handles, function(d) { return d.type; });
23557 handle.exit().remove();
23559 handle.enter().append("rect")
23560 .attr("class", function(d) { return "handle handle--" + d.type; })
23561 .attr("cursor", function(d) { return cursors[d.type]; });
23565 .attr("fill", "none")
23566 .attr("pointer-events", "all")
23567 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
23568 .on("mousedown.brush touchstart.brush", started);
23571 brush.move = function(group, selection) {
23572 if (group.selection) {
23574 .on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
23575 .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
23576 .tween("brush", function() {
23578 state = that.__brush,
23579 emit = emitter(that, arguments),
23580 selection0 = state.selection,
23581 selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent),
23582 i = interpolateValue(selection0, selection1);
23584 function tween(t) {
23585 state.selection = t === 1 && empty(selection1) ? null : i(t);
23590 return selection0 && selection1 ? tween : tween(1);
23597 state = that.__brush,
23598 selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent),
23599 emit = emitter(that, args).beforestart();
23602 state.selection = selection1 == null || empty(selection1) ? null : selection1;
23604 emit.start().brush().end();
23609 function redraw() {
23610 var group = select(this),
23611 selection = local$$1(this).selection;
23614 group.selectAll(".selection")
23615 .style("display", null)
23616 .attr("x", selection[0][0])
23617 .attr("y", selection[0][1])
23618 .attr("width", selection[1][0] - selection[0][0])
23619 .attr("height", selection[1][1] - selection[0][1]);
23621 group.selectAll(".handle")
23622 .style("display", null)
23623 .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; })
23624 .attr("y", function(d) { return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; })
23625 .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; })
23626 .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; });
23630 group.selectAll(".selection,.handle")
23631 .style("display", "none")
23634 .attr("width", null)
23635 .attr("height", null);
23639 function emitter(that, args) {
23640 return that.__brush.emitter || new Emitter(that, args);
23643 function Emitter(that, args) {
23646 this.state = that.__brush;
23650 Emitter.prototype = {
23651 beforestart: function() {
23652 if (++this.active === 1) this.state.emitter = this, this.starting = true;
23655 start: function() {
23656 if (this.starting) this.starting = false, this.emit("start");
23659 brush: function() {
23660 this.emit("brush");
23664 if (--this.active === 0) delete this.state.emitter, this.emit("end");
23667 emit: function(type) {
23668 customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
23672 function started() {
23673 if (event.touches) { if (event.changedTouches.length < event.touches.length) return noevent$1(); }
23674 else if (touchending) return;
23675 if (!filter.apply(this, arguments)) return;
23678 type = event.target.__data__.type,
23679 mode = (event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (event.altKey ? MODE_CENTER : MODE_HANDLE),
23680 signX = dim === Y ? null : signsX[type],
23681 signY = dim === X ? null : signsY[type],
23682 state = local$$1(that),
23683 extent = state.extent,
23684 selection = state.selection,
23685 W = extent[0][0], w0, w1,
23686 N = extent[0][1], n0, n1,
23687 E = extent[1][0], e0, e1,
23688 S = extent[1][1], s0, s1,
23692 shifting = signX && signY && event.shiftKey,
23695 point0 = mouse(that),
23697 emit = emitter(that, arguments).beforestart();
23699 if (type === "overlay") {
23700 state.selection = selection = [
23701 [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
23702 [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
23705 w0 = selection[0][0];
23706 n0 = selection[0][1];
23707 e0 = selection[1][0];
23708 s0 = selection[1][1];
23716 var group = select(that)
23717 .attr("pointer-events", "none");
23719 var overlay = group.selectAll(".overlay")
23720 .attr("cursor", cursors[type]);
23722 if (event.touches) {
23724 .on("touchmove.brush", moved, true)
23725 .on("touchend.brush touchcancel.brush", ended, true);
23727 var view = select(event.view)
23728 .on("keydown.brush", keydowned, true)
23729 .on("keyup.brush", keyupped, true)
23730 .on("mousemove.brush", moved, true)
23731 .on("mouseup.brush", ended, true);
23733 dragDisable(event.view);
23742 var point1 = mouse(that);
23743 if (shifting && !lockX && !lockY) {
23744 if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
23756 dx = point[0] - point0[0];
23757 dy = point[1] - point0[1];
23762 if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
23763 if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
23766 case MODE_HANDLE: {
23767 if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
23768 else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
23769 if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
23770 else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
23773 case MODE_CENTER: {
23774 if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
23775 if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
23782 t = w0, w0 = e0, e0 = t;
23783 t = w1, w1 = e1, e1 = t;
23784 if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
23789 t = n0, n0 = s0, s0 = t;
23790 t = n1, n1 = s1, s1 = t;
23791 if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
23794 if (state.selection) selection = state.selection; // May be set by brush.move!
23795 if (lockX) w1 = selection[0][0], e1 = selection[1][0];
23796 if (lockY) n1 = selection[0][1], s1 = selection[1][1];
23798 if (selection[0][0] !== w1
23799 || selection[0][1] !== n1
23800 || selection[1][0] !== e1
23801 || selection[1][1] !== s1) {
23802 state.selection = [[w1, n1], [e1, s1]];
23810 if (event.touches) {
23811 if (event.touches.length) return;
23812 if (touchending) clearTimeout(touchending);
23813 touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
23814 group.on("touchmove.brush touchend.brush touchcancel.brush", null);
23816 yesdrag(event.view, moving);
23817 view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
23819 group.attr("pointer-events", "all");
23820 overlay.attr("cursor", cursors.overlay);
23821 if (state.selection) selection = state.selection; // May be set by brush.move (on start)!
23822 if (empty(selection)) state.selection = null, redraw.call(that);
23826 function keydowned() {
23827 switch (event.keyCode) {
23828 case 16: { // SHIFT
23829 shifting = signX && signY;
23833 if (mode === MODE_HANDLE) {
23834 if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
23835 if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
23836 mode = MODE_CENTER;
23841 case 32: { // SPACE; takes priority over ALT
23842 if (mode === MODE_HANDLE || mode === MODE_CENTER) {
23843 if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
23844 if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
23846 overlay.attr("cursor", cursors.selection);
23856 function keyupped() {
23857 switch (event.keyCode) {
23858 case 16: { // SHIFT
23860 lockX = lockY = shifting = false;
23866 if (mode === MODE_CENTER) {
23867 if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
23868 if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
23869 mode = MODE_HANDLE;
23874 case 32: { // SPACE
23875 if (mode === MODE_SPACE) {
23876 if (event.altKey) {
23877 if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
23878 if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
23879 mode = MODE_CENTER;
23881 if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
23882 if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
23883 mode = MODE_HANDLE;
23885 overlay.attr("cursor", cursors[type]);
23896 function initialize() {
23897 var state = this.__brush || {selection: null};
23898 state.extent = extent.apply(this, arguments);
23903 brush.extent = function(_) {
23904 return arguments.length ? (extent = typeof _ === "function" ? _ : constant$4([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent;
23907 brush.filter = function(_) {
23908 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$4(!!_), brush) : filter;
23911 brush.handleSize = function(_) {
23912 return arguments.length ? (handleSize = +_, brush) : handleSize;
23915 brush.on = function() {
23916 var value = listeners.on.apply(listeners, arguments);
23917 return value === listeners ? brush : value;
23923 var cos = Math.cos;
23924 var sin = Math.sin;
23925 var pi$1 = Math.PI;
23926 var halfPi$1 = pi$1 / 2;
23927 var tau$1 = pi$1 * 2;
23928 var max$1 = Math.max;
23930 function compareValue(compare) {
23931 return function(a, b) {
23933 a.source.value + a.target.value,
23934 b.source.value + b.target.value
23939 var chord = function() {
23942 sortSubgroups = null,
23945 function chord(matrix) {
23946 var n = matrix.length,
23948 groupIndex = sequence(n),
23949 subgroupIndex = [],
23951 groups = chords.groups = new Array(n),
23952 subgroups = new Array(n * n),
23960 // Compute the sum.
23961 k = 0, i = -1; while (++i < n) {
23962 x = 0, j = -1; while (++j < n) {
23966 subgroupIndex.push(sequence(n));
23971 if (sortGroups) groupIndex.sort(function(a, b) {
23972 return sortGroups(groupSums[a], groupSums[b]);
23976 if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
23977 d.sort(function(a, b) {
23978 return sortSubgroups(matrix[i][a], matrix[i][b]);
23982 // Convert the sum to scaling factor for [0, 2pi].
23983 // TODO Allow start and end angle to be specified?
23984 // TODO Allow padding to be specified as percentage?
23985 k = max$1(0, tau$1 - padAngle * n) / k;
23986 dx = k ? padAngle : tau$1 / n;
23988 // Compute the start and end angle for each group and subgroup.
23989 // Note: Opera has a bug reordering object literal properties!
23990 x = 0, i = -1; while (++i < n) {
23991 x0 = x, j = -1; while (++j < n) {
23992 var di = groupIndex[i],
23993 dj = subgroupIndex[di][j],
23994 v = matrix[di][dj],
23997 subgroups[dj * n + di] = {
24009 value: groupSums[di]
24014 // Generate chords for each (non-empty) subgroup-subgroup link.
24015 i = -1; while (++i < n) {
24016 j = i - 1; while (++j < n) {
24017 var source = subgroups[j * n + i],
24018 target = subgroups[i * n + j];
24019 if (source.value || target.value) {
24020 chords.push(source.value < target.value
24021 ? {source: target, target: source}
24022 : {source: source, target: target});
24027 return sortChords ? chords.sort(sortChords) : chords;
24030 chord.padAngle = function(_) {
24031 return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle;
24034 chord.sortGroups = function(_) {
24035 return arguments.length ? (sortGroups = _, chord) : sortGroups;
24038 chord.sortSubgroups = function(_) {
24039 return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
24042 chord.sortChords = function(_) {
24043 return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
24049 var slice$2 = Array.prototype.slice;
24051 var constant$5 = function(x) {
24052 return function() {
24057 var pi$2 = Math.PI;
24058 var tau$2 = 2 * pi$2;
24059 var epsilon$1 = 1e-6;
24060 var tauEpsilon = tau$2 - epsilon$1;
24063 this._x0 = this._y0 = // start of current subpath
24064 this._x1 = this._y1 = null; // end of current subpath
24072 Path.prototype = path.prototype = {
24074 moveTo: function(x, y) {
24075 this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
24077 closePath: function() {
24078 if (this._x1 !== null) {
24079 this._x1 = this._x0, this._y1 = this._y0;
24083 lineTo: function(x, y) {
24084 this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
24086 quadraticCurveTo: function(x1, y1, x, y) {
24087 this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
24089 bezierCurveTo: function(x1, y1, x2, y2, x, y) {
24090 this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
24092 arcTo: function(x1, y1, x2, y2, r) {
24093 x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
24100 l01_2 = x01 * x01 + y01 * y01;
24102 // Is the radius negative? Error.
24103 if (r < 0) throw new Error("negative radius: " + r);
24105 // Is this path empty? Move to (x1,y1).
24106 if (this._x1 === null) {
24107 this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1);
24110 // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
24111 else if (!(l01_2 > epsilon$1)) {}
24113 // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
24114 // Equivalently, is (x1,y1) coincident with (x2,y2)?
24115 // Or, is the radius zero? Line to (x1,y1).
24116 else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon$1) || !r) {
24117 this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1);
24120 // Otherwise, draw an arc!
24124 l21_2 = x21 * x21 + y21 * y21,
24125 l20_2 = x20 * x20 + y20 * y20,
24126 l21 = Math.sqrt(l21_2),
24127 l01 = Math.sqrt(l01_2),
24128 l = r * Math.tan((pi$2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
24132 // If the start tangent is not coincident with (x0,y0), line to.
24133 if (Math.abs(t01 - 1) > epsilon$1) {
24134 this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01);
24137 this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21);
24140 arc: function(x, y, r, a0, a1, ccw) {
24141 x = +x, y = +y, r = +r;
24142 var dx = r * Math.cos(a0),
24143 dy = r * Math.sin(a0),
24147 da = ccw ? a0 - a1 : a1 - a0;
24149 // Is the radius negative? Error.
24150 if (r < 0) throw new Error("negative radius: " + r);
24152 // Is this path empty? Move to (x0,y0).
24153 if (this._x1 === null) {
24154 this._ += "M" + x0 + "," + y0;
24157 // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
24158 else if (Math.abs(this._x1 - x0) > epsilon$1 || Math.abs(this._y1 - y0) > epsilon$1) {
24159 this._ += "L" + x0 + "," + y0;
24162 // Is this arc empty? We’re done.
24165 // Does the angle go the wrong way? Flip the direction.
24166 if (da < 0) da = da % tau$2 + tau$2;
24168 // Is this a complete circle? Draw two arcs to complete the circle.
24169 if (da > tauEpsilon) {
24170 this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0);
24173 // Is this arc non-empty? Draw an arc!
24174 else if (da > epsilon$1) {
24175 this._ += "A" + r + "," + r + ",0," + (+(da >= pi$2)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1));
24178 rect: function(x, y, w, h) {
24179 this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z";
24181 toString: function() {
24186 function defaultSource(d) {
24190 function defaultTarget(d) {
24194 function defaultRadius(d) {
24198 function defaultStartAngle(d) {
24199 return d.startAngle;
24202 function defaultEndAngle(d) {
24206 var ribbon = function() {
24207 var source = defaultSource,
24208 target = defaultTarget,
24209 radius = defaultRadius,
24210 startAngle = defaultStartAngle,
24211 endAngle = defaultEndAngle,
24214 function ribbon() {
24216 argv = slice$2.call(arguments),
24217 s = source.apply(this, argv),
24218 t = target.apply(this, argv),
24219 sr = +radius.apply(this, (argv[0] = s, argv)),
24220 sa0 = startAngle.apply(this, argv) - halfPi$1,
24221 sa1 = endAngle.apply(this, argv) - halfPi$1,
24222 sx0 = sr * cos(sa0),
24223 sy0 = sr * sin(sa0),
24224 tr = +radius.apply(this, (argv[0] = t, argv)),
24225 ta0 = startAngle.apply(this, argv) - halfPi$1,
24226 ta1 = endAngle.apply(this, argv) - halfPi$1;
24228 if (!context) context = buffer = path();
24230 context.moveTo(sx0, sy0);
24231 context.arc(0, 0, sr, sa0, sa1);
24232 if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr?
24233 context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0));
24234 context.arc(0, 0, tr, ta0, ta1);
24236 context.quadraticCurveTo(0, 0, sx0, sy0);
24237 context.closePath();
24239 if (buffer) return context = null, buffer + "" || null;
24242 ribbon.radius = function(_) {
24243 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$5(+_), ribbon) : radius;
24246 ribbon.startAngle = function(_) {
24247 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : startAngle;
24250 ribbon.endAngle = function(_) {
24251 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : endAngle;
24254 ribbon.source = function(_) {
24255 return arguments.length ? (source = _, ribbon) : source;
24258 ribbon.target = function(_) {
24259 return arguments.length ? (target = _, ribbon) : target;
24262 ribbon.context = function(_) {
24263 return arguments.length ? ((context = _ == null ? null : _), ribbon) : context;
24273 Map.prototype = map$1.prototype = {
24275 has: function(key) {
24276 return (prefix + key) in this;
24278 get: function(key) {
24279 return this[prefix + key];
24281 set: function(key, value) {
24282 this[prefix + key] = value;
24285 remove: function(key) {
24286 var property = prefix + key;
24287 return property in this && delete this[property];
24289 clear: function() {
24290 for (var property in this) if (property[0] === prefix) delete this[property];
24294 for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
24297 values: function() {
24299 for (var property in this) if (property[0] === prefix) values.push(this[property]);
24302 entries: function() {
24304 for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
24309 for (var property in this) if (property[0] === prefix) ++size;
24312 empty: function() {
24313 for (var property in this) if (property[0] === prefix) return false;
24316 each: function(f) {
24317 for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
24321 function map$1(object, f) {
24324 // Copy constructor.
24325 if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
24327 // Index array by numeric index or specified key function.
24328 else if (Array.isArray(object)) {
24333 if (f == null) while (++i < n) map.set(i, object[i]);
24334 else while (++i < n) map.set(f(o = object[i], i, object), o);
24337 // Convert object to map.
24338 else if (object) for (var key in object) map.set(key, object[key]);
24343 var nest = function() {
24350 function apply(array, depth, createResult, setResult) {
24351 if (depth >= keys.length) return rollup != null
24352 ? rollup(array) : (sortValues != null
24353 ? array.sort(sortValues)
24358 key = keys[depth++],
24361 valuesByKey = map$1(),
24363 result = createResult();
24366 if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
24367 values.push(value);
24369 valuesByKey.set(keyValue, [value]);
24373 valuesByKey.each(function(values, key) {
24374 setResult(result, key, apply(values, depth, createResult, setResult));
24380 function entries(map, depth) {
24381 if (++depth > keys.length) return map;
24382 var array, sortKey = sortKeys[depth - 1];
24383 if (rollup != null && depth >= keys.length) array = map.entries();
24384 else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); });
24385 return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array;
24389 object: function(array) { return apply(array, 0, createObject, setObject); },
24390 map: function(array) { return apply(array, 0, createMap, setMap); },
24391 entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
24392 key: function(d) { keys.push(d); return nest; },
24393 sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
24394 sortValues: function(order) { sortValues = order; return nest; },
24395 rollup: function(f) { rollup = f; return nest; }
24399 function createObject() {
24403 function setObject(object, key, value) {
24404 object[key] = value;
24407 function createMap() {
24411 function setMap(map, key, value) {
24412 map.set(key, value);
24417 var proto = map$1.prototype;
24419 Set.prototype = set$2.prototype = {
24422 add: function(value) {
24424 this[prefix + value] = value;
24427 remove: proto.remove,
24428 clear: proto.clear,
24429 values: proto.keys,
24431 empty: proto.empty,
24435 function set$2(object, f) {
24438 // Copy constructor.
24439 if (object instanceof Set) object.each(function(value) { set.add(value); });
24441 // Otherwise, assume it’s an array.
24443 var i = -1, n = object.length;
24444 if (f == null) while (++i < n) set.add(object[i]);
24445 else while (++i < n) set.add(f(object[i], i, object));
24451 var keys = function(map) {
24453 for (var key in map) keys.push(key);
24457 var values = function(map) {
24459 for (var key in map) values.push(map[key]);
24463 var entries = function(map) {
24465 for (var key in map) entries.push({key: key, value: map[key]});
24469 function objectConverter(columns) {
24470 return new Function("d", "return {" + columns.map(function(name, i) {
24471 return JSON.stringify(name) + ": d[" + i + "]";
24472 }).join(",") + "}");
24475 function customConverter(columns, f) {
24476 var object = objectConverter(columns);
24477 return function(row, i) {
24478 return f(object(row), i, columns);
24482 // Compute unique columns in order of discovery.
24483 function inferColumns(rows) {
24484 var columnSet = Object.create(null),
24487 rows.forEach(function(row) {
24488 for (var column in row) {
24489 if (!(column in columnSet)) {
24490 columns.push(columnSet[column] = column);
24498 var dsv = function(delimiter) {
24499 var reFormat = new RegExp("[\"" + delimiter + "\n\r]"),
24500 delimiterCode = delimiter.charCodeAt(0);
24502 function parse(text, f) {
24503 var convert, columns, rows = parseRows(text, function(row, i) {
24504 if (convert) return convert(row, i - 1);
24505 columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
24507 rows.columns = columns;
24511 function parseRows(text, f) {
24512 var EOL = {}, // sentinel value for end-of-line
24513 EOF = {}, // sentinel value for end-of-file
24514 rows = [], // output rows
24516 I = 0, // current character index
24517 n = 0, // the current line number
24518 t, // the current token
24519 eol; // is the current token followed by EOL?
24522 if (I >= N) return EOF; // special case: end of file
24523 if (eol) return eol = false, EOL; // special case: end of line
24525 // special case: quotes
24527 if (text.charCodeAt(j) === 34) {
24530 if (text.charCodeAt(i) === 34) {
24531 if (text.charCodeAt(i + 1) !== 34) break;
24536 c = text.charCodeAt(i + 1);
24539 if (text.charCodeAt(i + 2) === 10) ++I;
24540 } else if (c === 10) {
24543 return text.slice(j + 1, i).replace(/""/g, "\"");
24546 // common case: find next delimiter or newline
24549 c = text.charCodeAt(I++);
24550 if (c === 10) eol = true; // \n
24551 else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
24552 else if (c !== delimiterCode) continue;
24553 return text.slice(j, I - k);
24556 // special case: last token before EOF
24557 return text.slice(j);
24560 while ((t = token()) !== EOF) {
24562 while (t !== EOL && t !== EOF) {
24566 if (f && (a = f(a, n++)) == null) continue;
24573 function format(rows, columns) {
24574 if (columns == null) columns = inferColumns(rows);
24575 return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
24576 return columns.map(function(column) {
24577 return formatValue(row[column]);
24578 }).join(delimiter);
24582 function formatRows(rows) {
24583 return rows.map(formatRow).join("\n");
24586 function formatRow(row) {
24587 return row.map(formatValue).join(delimiter);
24590 function formatValue(text) {
24591 return text == null ? ""
24592 : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\""
24598 parseRows: parseRows,
24600 formatRows: formatRows
24604 var csv = dsv(",");
24606 var csvParse = csv.parse;
24607 var csvParseRows = csv.parseRows;
24608 var csvFormat = csv.format;
24609 var csvFormatRows = csv.formatRows;
24611 var tsv = dsv("\t");
24613 var tsvParse = tsv.parse;
24614 var tsvParseRows = tsv.parseRows;
24615 var tsvFormat = tsv.format;
24616 var tsvFormatRows = tsv.formatRows;
24618 var center$1 = function(x, y) {
24621 if (x == null) x = 0;
24622 if (y == null) y = 0;
24631 for (i = 0; i < n; ++i) {
24632 node = nodes[i], sx += node.x, sy += node.y;
24635 for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) {
24636 node = nodes[i], node.x -= sx, node.y -= sy;
24640 force.initialize = function(_) {
24644 force.x = function(_) {
24645 return arguments.length ? (x = +_, force) : x;
24648 force.y = function(_) {
24649 return arguments.length ? (y = +_, force) : y;
24655 var constant$6 = function(x) {
24656 return function() {
24661 var jiggle = function() {
24662 return (Math.random() - 0.5) * 1e-6;
24665 var tree_add = function(d) {
24666 var x = +this._x.call(null, d),
24667 y = +this._y.call(null, d);
24668 return add(this.cover(x, y), x, y, d);
24671 function add(tree, x, y, d) {
24672 if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
24690 // If the tree is empty, initialize the root as a leaf.
24691 if (!node) return tree._root = leaf, tree;
24693 // Find the existing leaf for the new point, or add it.
24694 while (node.length) {
24695 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24696 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24697 if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
24700 // Is the new point is exactly coincident with the existing point?
24701 xp = +tree._x.call(null, node.data);
24702 yp = +tree._y.call(null, node.data);
24703 if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
24705 // Otherwise, split the leaf node until the old and new point are separated.
24707 parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
24708 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24709 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24710 } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
24711 return parent[j] = node, parent[i] = leaf, tree;
24714 function addAll(data) {
24715 var d, i, n = data.length,
24725 // Compute the points and their extent.
24726 for (i = 0; i < n; ++i) {
24727 if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
24730 if (x < x0) x0 = x;
24731 if (x > x1) x1 = x;
24732 if (y < y0) y0 = y;
24733 if (y > y1) y1 = y;
24736 // If there were no (valid) points, inherit the existing extent.
24737 if (x1 < x0) x0 = this._x0, x1 = this._x1;
24738 if (y1 < y0) y0 = this._y0, y1 = this._y1;
24740 // Expand the tree to cover the new points.
24741 this.cover(x0, y0).cover(x1, y1);
24743 // Add the new points.
24744 for (i = 0; i < n; ++i) {
24745 add(this, xz[i], yz[i], data[i]);
24751 var tree_cover = function(x, y) {
24752 if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
24759 // If the quadtree has no extent, initialize them.
24760 // Integer extent are necessary so that if we later double the extent,
24761 // the existing quadrant boundaries don’t change due to floating point error!
24763 x1 = (x0 = Math.floor(x)) + 1;
24764 y1 = (y0 = Math.floor(y)) + 1;
24767 // Otherwise, double repeatedly to cover.
24768 else if (x0 > x || x > x1 || y0 > y || y > y1) {
24774 switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
24776 do parent = new Array(4), parent[i] = node, node = parent;
24777 while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
24781 do parent = new Array(4), parent[i] = node, node = parent;
24782 while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
24786 do parent = new Array(4), parent[i] = node, node = parent;
24787 while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
24791 do parent = new Array(4), parent[i] = node, node = parent;
24792 while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
24797 if (this._root && this._root.length) this._root = node;
24800 // If the quadtree covers the point already, just return.
24810 var tree_data = function() {
24812 this.visit(function(node) {
24813 if (!node.length) do data.push(node.data); while (node = node.next)
24818 var tree_extent = function(_) {
24819 return arguments.length
24820 ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
24821 : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
24824 var Quad = function(node, x0, y0, x1, y1) {
24832 var tree_find = function(x, y, radius) {
24847 if (node) quads.push(new Quad(node, x0, y0, x3, y3));
24848 if (radius == null) radius = Infinity;
24850 x0 = x - radius, y0 = y - radius;
24851 x3 = x + radius, y3 = y + radius;
24855 while (q = quads.pop()) {
24857 // Stop searching if this quadrant can’t contain a closer node.
24858 if (!(node = q.node)
24859 || (x1 = q.x0) > x3
24860 || (y1 = q.y0) > y3
24861 || (x2 = q.x1) < x0
24862 || (y2 = q.y1) < y0) continue;
24864 // Bisect the current quadrant.
24866 var xm = (x1 + x2) / 2,
24867 ym = (y1 + y2) / 2;
24870 new Quad(node[3], xm, ym, x2, y2),
24871 new Quad(node[2], x1, ym, xm, y2),
24872 new Quad(node[1], xm, y1, x2, ym),
24873 new Quad(node[0], x1, y1, xm, ym)
24876 // Visit the closest quadrant first.
24877 if (i = (y >= ym) << 1 | (x >= xm)) {
24878 q = quads[quads.length - 1];
24879 quads[quads.length - 1] = quads[quads.length - 1 - i];
24880 quads[quads.length - 1 - i] = q;
24884 // Visit this point. (Visiting coincident points isn’t necessary!)
24886 var dx = x - +this._x.call(null, node.data),
24887 dy = y - +this._y.call(null, node.data),
24888 d2 = dx * dx + dy * dy;
24890 var d = Math.sqrt(radius = d2);
24891 x0 = x - d, y0 = y - d;
24892 x3 = x + d, y3 = y + d;
24901 var tree_remove = function(d) {
24902 if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
24922 // If the tree is empty, initialize the root as a leaf.
24923 if (!node) return this;
24925 // Find the leaf node for the point.
24926 // While descending, also retain the deepest parent with a non-removed sibling.
24927 if (node.length) while (true) {
24928 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24929 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24930 if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
24931 if (!node.length) break;
24932 if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
24935 // Find the point to remove.
24936 while (node.data !== d) if (!(previous = node, node = node.next)) return this;
24937 if (next = node.next) delete node.next;
24939 // If there are multiple coincident points, remove just the point.
24940 if (previous) return (next ? previous.next = next : delete previous.next), this;
24942 // If this is the root point, remove it.
24943 if (!parent) return this._root = next, this;
24945 // Remove this leaf.
24946 next ? parent[i] = next : delete parent[i];
24948 // If the parent now contains exactly one leaf, collapse superfluous parents.
24949 if ((node = parent[0] || parent[1] || parent[2] || parent[3])
24950 && node === (parent[3] || parent[2] || parent[1] || parent[0])
24952 if (retainer) retainer[j] = node;
24953 else this._root = node;
24959 function removeAll(data) {
24960 for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
24964 var tree_root = function() {
24968 var tree_size = function() {
24970 this.visit(function(node) {
24971 if (!node.length) do ++size; while (node = node.next)
24976 var tree_visit = function(callback) {
24977 var quads = [], q, node = this._root, child, x0, y0, x1, y1;
24978 if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
24979 while (q = quads.pop()) {
24980 if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
24981 var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
24982 if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
24983 if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
24984 if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
24985 if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
24991 var tree_visitAfter = function(callback) {
24992 var quads = [], next = [], q;
24993 if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
24994 while (q = quads.pop()) {
24997 var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
24998 if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
24999 if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
25000 if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
25001 if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
25005 while (q = next.pop()) {
25006 callback(q.node, q.x0, q.y0, q.x1, q.y1);
25011 function defaultX(d) {
25015 var tree_x = function(_) {
25016 return arguments.length ? (this._x = _, this) : this._x;
25019 function defaultY(d) {
25023 var tree_y = function(_) {
25024 return arguments.length ? (this._y = _, this) : this._y;
25027 function quadtree(nodes, x, y) {
25028 var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
25029 return nodes == null ? tree : tree.addAll(nodes);
25032 function Quadtree(x, y, x0, y0, x1, y1) {
25039 this._root = undefined;
25042 function leaf_copy(leaf) {
25043 var copy = {data: leaf.data}, next = copy;
25044 while (leaf = leaf.next) next = next.next = {data: leaf.data};
25048 var treeProto = quadtree.prototype = Quadtree.prototype;
25050 treeProto.copy = function() {
25051 var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
25056 if (!node) return copy;
25058 if (!node.length) return copy._root = leaf_copy(node), copy;
25060 nodes = [{source: node, target: copy._root = new Array(4)}];
25061 while (node = nodes.pop()) {
25062 for (var i = 0; i < 4; ++i) {
25063 if (child = node.source[i]) {
25064 if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
25065 else node.target[i] = leaf_copy(child);
25073 treeProto.add = tree_add;
25074 treeProto.addAll = addAll;
25075 treeProto.cover = tree_cover;
25076 treeProto.data = tree_data;
25077 treeProto.extent = tree_extent;
25078 treeProto.find = tree_find;
25079 treeProto.remove = tree_remove;
25080 treeProto.removeAll = removeAll;
25081 treeProto.root = tree_root;
25082 treeProto.size = tree_size;
25083 treeProto.visit = tree_visit;
25084 treeProto.visitAfter = tree_visitAfter;
25085 treeProto.x = tree_x;
25086 treeProto.y = tree_y;
25096 var collide = function(radius) {
25102 if (typeof radius !== "function") radius = constant$6(radius == null ? 1 : +radius);
25105 var i, n = nodes.length,
25113 for (var k = 0; k < iterations; ++k) {
25114 tree = quadtree(nodes, x, y).visitAfter(prepare);
25115 for (i = 0; i < n; ++i) {
25117 ri = radii[node.index], ri2 = ri * ri;
25118 xi = node.x + node.vx;
25119 yi = node.y + node.vy;
25124 function apply(quad, x0, y0, x1, y1) {
25125 var data = quad.data, rj = quad.r, r = ri + rj;
25127 if (data.index > node.index) {
25128 var x = xi - data.x - data.vx,
25129 y = yi - data.y - data.vy,
25132 if (x === 0) x = jiggle(), l += x * x;
25133 if (y === 0) y = jiggle(), l += y * y;
25134 l = (r - (l = Math.sqrt(l))) / l * strength;
25135 node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
25136 node.vy += (y *= l) * r;
25137 data.vx -= x * (r = 1 - r);
25143 return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
25147 function prepare(quad) {
25148 if (quad.data) return quad.r = radii[quad.data.index];
25149 for (var i = quad.r = 0; i < 4; ++i) {
25150 if (quad[i] && quad[i].r > quad.r) {
25151 quad.r = quad[i].r;
25156 function initialize() {
25157 if (!nodes) return;
25158 var i, n = nodes.length, node;
25159 radii = new Array(n);
25160 for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);
25163 force.initialize = function(_) {
25168 force.iterations = function(_) {
25169 return arguments.length ? (iterations = +_, force) : iterations;
25172 force.strength = function(_) {
25173 return arguments.length ? (strength = +_, force) : strength;
25176 force.radius = function(_) {
25177 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : radius;
25183 function index$3(d) {
25187 function find(nodeById, nodeId) {
25188 var node = nodeById.get(nodeId);
25189 if (!node) throw new Error("missing: " + nodeId);
25193 var link = function(links) {
25195 strength = defaultStrength,
25197 distance = constant$6(30),
25204 if (links == null) links = [];
25206 function defaultStrength(link) {
25207 return 1 / Math.min(count[link.source.index], count[link.target.index]);
25210 function force(alpha) {
25211 for (var k = 0, n = links.length; k < iterations; ++k) {
25212 for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
25213 link = links[i], source = link.source, target = link.target;
25214 x = target.x + target.vx - source.x - source.vx || jiggle();
25215 y = target.y + target.vy - source.y - source.vy || jiggle();
25216 l = Math.sqrt(x * x + y * y);
25217 l = (l - distances[i]) / l * alpha * strengths[i];
25219 target.vx -= x * (b = bias[i]);
25220 target.vy -= y * b;
25221 source.vx += x * (b = 1 - b);
25222 source.vy += y * b;
25227 function initialize() {
25228 if (!nodes) return;
25233 nodeById = map$1(nodes, id),
25236 for (i = 0, count = new Array(n); i < m; ++i) {
25237 link = links[i], link.index = i;
25238 if (typeof link.source !== "object") link.source = find(nodeById, link.source);
25239 if (typeof link.target !== "object") link.target = find(nodeById, link.target);
25240 count[link.source.index] = (count[link.source.index] || 0) + 1;
25241 count[link.target.index] = (count[link.target.index] || 0) + 1;
25244 for (i = 0, bias = new Array(m); i < m; ++i) {
25245 link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
25248 strengths = new Array(m), initializeStrength();
25249 distances = new Array(m), initializeDistance();
25252 function initializeStrength() {
25253 if (!nodes) return;
25255 for (var i = 0, n = links.length; i < n; ++i) {
25256 strengths[i] = +strength(links[i], i, links);
25260 function initializeDistance() {
25261 if (!nodes) return;
25263 for (var i = 0, n = links.length; i < n; ++i) {
25264 distances[i] = +distance(links[i], i, links);
25268 force.initialize = function(_) {
25273 force.links = function(_) {
25274 return arguments.length ? (links = _, initialize(), force) : links;
25277 force.id = function(_) {
25278 return arguments.length ? (id = _, force) : id;
25281 force.iterations = function(_) {
25282 return arguments.length ? (iterations = +_, force) : iterations;
25285 force.strength = function(_) {
25286 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initializeStrength(), force) : strength;
25289 force.distance = function(_) {
25290 return arguments.length ? (distance = typeof _ === "function" ? _ : constant$6(+_), initializeDistance(), force) : distance;
25304 var initialRadius = 10;
25305 var initialAngle = Math.PI * (3 - Math.sqrt(5));
25307 var simulation = function(nodes) {
25311 alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
25313 velocityDecay = 0.6,
25315 stepper = timer(step),
25316 event = dispatch("tick", "end");
25318 if (nodes == null) nodes = [];
25322 event.call("tick", simulation);
25323 if (alpha < alphaMin) {
25325 event.call("end", simulation);
25330 var i, n = nodes.length, node;
25332 alpha += (alphaTarget - alpha) * alphaDecay;
25334 forces.each(function(force) {
25338 for (i = 0; i < n; ++i) {
25340 if (node.fx == null) node.x += node.vx *= velocityDecay;
25341 else node.x = node.fx, node.vx = 0;
25342 if (node.fy == null) node.y += node.vy *= velocityDecay;
25343 else node.y = node.fy, node.vy = 0;
25347 function initializeNodes() {
25348 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25349 node = nodes[i], node.index = i;
25350 if (isNaN(node.x) || isNaN(node.y)) {
25351 var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle;
25352 node.x = radius * Math.cos(angle);
25353 node.y = radius * Math.sin(angle);
25355 if (isNaN(node.vx) || isNaN(node.vy)) {
25356 node.vx = node.vy = 0;
25361 function initializeForce(force) {
25362 if (force.initialize) force.initialize(nodes);
25368 return simulation = {
25371 restart: function() {
25372 return stepper.restart(step), simulation;
25376 return stepper.stop(), simulation;
25379 nodes: function(_) {
25380 return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes;
25383 alpha: function(_) {
25384 return arguments.length ? (alpha = +_, simulation) : alpha;
25387 alphaMin: function(_) {
25388 return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
25391 alphaDecay: function(_) {
25392 return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
25395 alphaTarget: function(_) {
25396 return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
25399 velocityDecay: function(_) {
25400 return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
25403 force: function(name, _) {
25404 return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
25407 find: function(x, y, radius) {
25416 if (radius == null) radius = Infinity;
25417 else radius *= radius;
25419 for (i = 0; i < n; ++i) {
25423 d2 = dx * dx + dy * dy;
25424 if (d2 < radius) closest = node, radius = d2;
25430 on: function(name, _) {
25431 return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
25436 var manyBody = function() {
25440 strength = constant$6(-30),
25443 distanceMax2 = Infinity,
25446 function force(_) {
25447 var i, n = nodes.length, tree = quadtree(nodes, x$1, y$1).visitAfter(accumulate);
25448 for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
25451 function initialize() {
25452 if (!nodes) return;
25453 var i, n = nodes.length, node;
25454 strengths = new Array(n);
25455 for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
25458 function accumulate(quad) {
25459 var strength = 0, q, c, x, y, i;
25461 // For internal nodes, accumulate forces from child quadrants.
25463 for (x = y = i = 0; i < 4; ++i) {
25464 if ((q = quad[i]) && (c = q.value)) {
25465 strength += c, x += c * q.x, y += c * q.y;
25468 quad.x = x / strength;
25469 quad.y = y / strength;
25472 // For leaf nodes, accumulate forces from coincident quadrants.
25477 do strength += strengths[q.data.index];
25478 while (q = q.next);
25481 quad.value = strength;
25484 function apply(quad, x1, _, x2) {
25485 if (!quad.value) return true;
25487 var x = quad.x - node.x,
25488 y = quad.y - node.y,
25492 // Apply the Barnes-Hut approximation if possible.
25493 // Limit forces for very close nodes; randomize direction if coincident.
25494 if (w * w / theta2 < l) {
25495 if (l < distanceMax2) {
25496 if (x === 0) x = jiggle(), l += x * x;
25497 if (y === 0) y = jiggle(), l += y * y;
25498 if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
25499 node.vx += x * quad.value * alpha / l;
25500 node.vy += y * quad.value * alpha / l;
25505 // Otherwise, process points directly.
25506 else if (quad.length || l >= distanceMax2) return;
25508 // Limit forces for very close nodes; randomize direction if coincident.
25509 if (quad.data !== node || quad.next) {
25510 if (x === 0) x = jiggle(), l += x * x;
25511 if (y === 0) y = jiggle(), l += y * y;
25512 if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
25515 do if (quad.data !== node) {
25516 w = strengths[quad.data.index] * alpha / l;
25519 } while (quad = quad.next);
25522 force.initialize = function(_) {
25527 force.strength = function(_) {
25528 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25531 force.distanceMin = function(_) {
25532 return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
25535 force.distanceMax = function(_) {
25536 return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
25539 force.theta = function(_) {
25540 return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
25546 var x$2 = function(x) {
25547 var strength = constant$6(0.1),
25552 if (typeof x !== "function") x = constant$6(x == null ? 0 : +x);
25554 function force(alpha) {
25555 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25556 node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
25560 function initialize() {
25561 if (!nodes) return;
25562 var i, n = nodes.length;
25563 strengths = new Array(n);
25565 for (i = 0; i < n; ++i) {
25566 strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
25570 force.initialize = function(_) {
25575 force.strength = function(_) {
25576 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25579 force.x = function(_) {
25580 return arguments.length ? (x = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : x;
25586 var y$2 = function(y) {
25587 var strength = constant$6(0.1),
25592 if (typeof y !== "function") y = constant$6(y == null ? 0 : +y);
25594 function force(alpha) {
25595 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25596 node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
25600 function initialize() {
25601 if (!nodes) return;
25602 var i, n = nodes.length;
25603 strengths = new Array(n);
25605 for (i = 0; i < n; ++i) {
25606 strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
25610 force.initialize = function(_) {
25615 force.strength = function(_) {
25616 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25619 force.y = function(_) {
25620 return arguments.length ? (y = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : y;
25626 // Computes the decimal coefficient and exponent of the specified number x with
25627 // significant digits p, where x is positive and p is in [1, 21] or undefined.
25628 // For example, formatDecimal(1.23) returns ["123", 0].
25629 var formatDecimal = function(x, p) {
25630 if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
25631 var i, coefficient = x.slice(0, i);
25633 // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
25634 // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
25636 coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
25641 var exponent$1 = function(x) {
25642 return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
25645 var formatGroup = function(grouping, thousands) {
25646 return function(value, width) {
25647 var i = value.length,
25653 while (i > 0 && g > 0) {
25654 if (length + g + 1 > width) g = Math.max(1, width - length);
25655 t.push(value.substring(i -= g, i + g));
25656 if ((length += g + 1) > width) break;
25657 g = grouping[j = (j + 1) % grouping.length];
25660 return t.reverse().join(thousands);
25664 var formatNumerals = function(numerals) {
25665 return function(value) {
25666 return value.replace(/[0-9]/g, function(i) {
25667 return numerals[+i];
25672 var formatDefault = function(x, p) {
25673 x = x.toPrecision(p);
25675 out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
25677 case ".": i0 = i1 = i; break;
25678 case "0": if (i0 === 0) i0 = i; i1 = i; break;
25679 case "e": break out;
25680 default: if (i0 > 0) i0 = 0; break;
25684 return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
25687 var prefixExponent;
25689 var formatPrefixAuto = function(x, p) {
25690 var d = formatDecimal(x, p);
25691 if (!d) return x + "";
25692 var coefficient = d[0],
25694 i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
25695 n = coefficient.length;
25696 return i === n ? coefficient
25697 : i > n ? coefficient + new Array(i - n + 1).join("0")
25698 : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
25699 : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
25702 var formatRounded = function(x, p) {
25703 var d = formatDecimal(x, p);
25704 if (!d) return x + "";
25705 var coefficient = d[0],
25707 return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
25708 : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
25709 : coefficient + new Array(exponent - coefficient.length + 2).join("0");
25712 var formatTypes = {
25714 "%": function(x, p) { return (x * 100).toFixed(p); },
25715 "b": function(x) { return Math.round(x).toString(2); },
25716 "c": function(x) { return x + ""; },
25717 "d": function(x) { return Math.round(x).toString(10); },
25718 "e": function(x, p) { return x.toExponential(p); },
25719 "f": function(x, p) { return x.toFixed(p); },
25720 "g": function(x, p) { return x.toPrecision(p); },
25721 "o": function(x) { return Math.round(x).toString(8); },
25722 "p": function(x, p) { return formatRounded(x * 100, p); },
25723 "r": formatRounded,
25724 "s": formatPrefixAuto,
25725 "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
25726 "x": function(x) { return Math.round(x).toString(16); }
25729 // [[fill]align][sign][symbol][0][width][,][.precision][type]
25730 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
25732 function formatSpecifier(specifier) {
25733 return new FormatSpecifier(specifier);
25736 formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
25738 function FormatSpecifier(specifier) {
25739 if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
25742 fill = match[1] || " ",
25743 align = match[2] || ">",
25744 sign = match[3] || "-",
25745 symbol = match[4] || "",
25747 width = match[6] && +match[6],
25748 comma = !!match[7],
25749 precision = match[8] && +match[8].slice(1),
25750 type = match[9] || "";
25752 // The "n" type is an alias for ",g".
25753 if (type === "n") comma = true, type = "g";
25755 // Map invalid types to the default format.
25756 else if (!formatTypes[type]) type = "";
25758 // If zero fill is specified, padding goes after sign and before digits.
25759 if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
25762 this.align = align;
25764 this.symbol = symbol;
25766 this.width = width;
25767 this.comma = comma;
25768 this.precision = precision;
25772 FormatSpecifier.prototype.toString = function() {
25777 + (this.zero ? "0" : "")
25778 + (this.width == null ? "" : Math.max(1, this.width | 0))
25779 + (this.comma ? "," : "")
25780 + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
25784 var identity$3 = function(x) {
25788 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
25790 var formatLocale = function(locale) {
25791 var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3,
25792 currency = locale.currency,
25793 decimal = locale.decimal,
25794 numerals = locale.numerals ? formatNumerals(locale.numerals) : identity$3,
25795 percent = locale.percent || "%";
25797 function newFormat(specifier) {
25798 specifier = formatSpecifier(specifier);
25800 var fill = specifier.fill,
25801 align = specifier.align,
25802 sign = specifier.sign,
25803 symbol = specifier.symbol,
25804 zero = specifier.zero,
25805 width = specifier.width,
25806 comma = specifier.comma,
25807 precision = specifier.precision,
25808 type = specifier.type;
25810 // Compute the prefix and suffix.
25811 // For SI-prefix, the suffix is lazily computed.
25812 var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
25813 suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : "";
25815 // What format function should we use?
25816 // Is this an integer type?
25817 // Can this type generate exponential notation?
25818 var formatType = formatTypes[type],
25819 maybeSuffix = !type || /[defgprs%]/.test(type);
25821 // Set the default precision if not specified,
25822 // or clamp the specified precision to the supported range.
25823 // For significant precision, it must be in [1, 21].
25824 // For fixed precision, it must be in [0, 20].
25825 precision = precision == null ? (type ? 6 : 12)
25826 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
25827 : Math.max(0, Math.min(20, precision));
25829 function format(value) {
25830 var valuePrefix = prefix,
25831 valueSuffix = suffix,
25834 if (type === "c") {
25835 valueSuffix = formatType(value) + valueSuffix;
25840 // Perform the initial formatting.
25841 var valueNegative = value < 0;
25842 value = formatType(Math.abs(value), precision);
25844 // If a negative value rounds to zero during formatting, treat as positive.
25845 if (valueNegative && +value === 0) valueNegative = false;
25847 // Compute the prefix and suffix.
25848 valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
25849 valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
25851 // Break the formatted value into the integer “value” part that can be
25852 // grouped, and fractional or exponential “suffix” part that is not.
25854 i = -1, n = value.length;
25856 if (c = value.charCodeAt(i), 48 > c || c > 57) {
25857 valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
25858 value = value.slice(0, i);
25865 // If the fill character is not "0", grouping is applied before padding.
25866 if (comma && !zero) value = group(value, Infinity);
25868 // Compute the padding.
25869 var length = valuePrefix.length + value.length + valueSuffix.length,
25870 padding = length < width ? new Array(width - length + 1).join(fill) : "";
25872 // If the fill character is "0", grouping is applied after padding.
25873 if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
25875 // Reconstruct the final output based on the desired alignment.
25877 case "<": value = valuePrefix + value + valueSuffix + padding; break;
25878 case "=": value = valuePrefix + padding + value + valueSuffix; break;
25879 case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
25880 default: value = padding + valuePrefix + value + valueSuffix; break;
25883 return numerals(value);
25886 format.toString = function() {
25887 return specifier + "";
25893 function formatPrefix(specifier, value) {
25894 var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
25895 e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
25896 k = Math.pow(10, -e),
25897 prefix = prefixes[8 + e / 3];
25898 return function(value) {
25899 return f(k * value) + prefix;
25905 formatPrefix: formatPrefix
25917 currency: ["$", ""]
25920 function defaultLocale(definition) {
25921 locale$1 = formatLocale(definition);
25922 format = locale$1.format;
25923 formatPrefix = locale$1.formatPrefix;
25927 var precisionFixed = function(step) {
25928 return Math.max(0, -exponent$1(Math.abs(step)));
25931 var precisionPrefix = function(step, value) {
25932 return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step)));
25935 var precisionRound = function(step, max) {
25936 step = Math.abs(step), max = Math.abs(max) - step;
25937 return Math.max(0, exponent$1(max) - exponent$1(step)) + 1;
25940 // Adds floating point numbers with twice the normal precision.
25941 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
25942 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
25944 // Code adapted from GeographicLib by Charles F. F. Karney,
25945 // http://geographiclib.sourceforge.net/
25947 var adder = function() {
25955 Adder.prototype = {
25956 constructor: Adder,
25957 reset: function() {
25958 this.s = // rounded value
25959 this.t = 0; // exact error
25962 add$1(temp, y, this.t);
25963 add$1(this, temp.s, this.s);
25964 if (this.s) this.t += temp.t;
25965 else this.s = temp.t;
25967 valueOf: function() {
25972 var temp = new Adder;
25974 function add$1(adder, a, b) {
25975 var x = adder.s = a + b,
25978 adder.t = (a - av) + (b - bv);
25981 var epsilon$2 = 1e-6;
25982 var epsilon2$1 = 1e-12;
25983 var pi$3 = Math.PI;
25984 var halfPi$2 = pi$3 / 2;
25985 var quarterPi = pi$3 / 4;
25986 var tau$3 = pi$3 * 2;
25988 var degrees$1 = 180 / pi$3;
25989 var radians = pi$3 / 180;
25991 var abs = Math.abs;
25992 var atan = Math.atan;
25993 var atan2 = Math.atan2;
25994 var cos$1 = Math.cos;
25995 var ceil = Math.ceil;
25996 var exp = Math.exp;
25998 var log = Math.log;
25999 var pow = Math.pow;
26000 var sin$1 = Math.sin;
26001 var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
26002 var sqrt = Math.sqrt;
26003 var tan = Math.tan;
26006 return x > 1 ? 0 : x < -1 ? pi$3 : Math.acos(x);
26010 return x > 1 ? halfPi$2 : x < -1 ? -halfPi$2 : Math.asin(x);
26013 function haversin(x) {
26014 return (x = sin$1(x / 2)) * x;
26017 function noop$1() {}
26019 function streamGeometry(geometry, stream) {
26020 if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
26021 streamGeometryType[geometry.type](geometry, stream);
26025 var streamObjectType = {
26026 Feature: function(object, stream) {
26027 streamGeometry(object.geometry, stream);
26029 FeatureCollection: function(object, stream) {
26030 var features = object.features, i = -1, n = features.length;
26031 while (++i < n) streamGeometry(features[i].geometry, stream);
26035 var streamGeometryType = {
26036 Sphere: function(object, stream) {
26039 Point: function(object, stream) {
26040 object = object.coordinates;
26041 stream.point(object[0], object[1], object[2]);
26043 MultiPoint: function(object, stream) {
26044 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26045 while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
26047 LineString: function(object, stream) {
26048 streamLine(object.coordinates, stream, 0);
26050 MultiLineString: function(object, stream) {
26051 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26052 while (++i < n) streamLine(coordinates[i], stream, 0);
26054 Polygon: function(object, stream) {
26055 streamPolygon(object.coordinates, stream);
26057 MultiPolygon: function(object, stream) {
26058 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26059 while (++i < n) streamPolygon(coordinates[i], stream);
26061 GeometryCollection: function(object, stream) {
26062 var geometries = object.geometries, i = -1, n = geometries.length;
26063 while (++i < n) streamGeometry(geometries[i], stream);
26067 function streamLine(coordinates, stream, closed) {
26068 var i = -1, n = coordinates.length - closed, coordinate;
26069 stream.lineStart();
26070 while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
26074 function streamPolygon(coordinates, stream) {
26075 var i = -1, n = coordinates.length;
26076 stream.polygonStart();
26077 while (++i < n) streamLine(coordinates[i], stream, 1);
26078 stream.polygonEnd();
26081 var geoStream = function(object, stream) {
26082 if (object && streamObjectType.hasOwnProperty(object.type)) {
26083 streamObjectType[object.type](object, stream);
26085 streamGeometry(object, stream);
26089 var areaRingSum = adder();
26091 var areaSum = adder();
26102 polygonStart: function() {
26103 areaRingSum.reset();
26104 areaStream.lineStart = areaRingStart;
26105 areaStream.lineEnd = areaRingEnd;
26107 polygonEnd: function() {
26108 var areaRing = +areaRingSum;
26109 areaSum.add(areaRing < 0 ? tau$3 + areaRing : areaRing);
26110 this.lineStart = this.lineEnd = this.point = noop$1;
26112 sphere: function() {
26113 areaSum.add(tau$3);
26117 function areaRingStart() {
26118 areaStream.point = areaPointFirst;
26121 function areaRingEnd() {
26122 areaPoint(lambda00, phi00);
26125 function areaPointFirst(lambda, phi) {
26126 areaStream.point = areaPoint;
26127 lambda00 = lambda, phi00 = phi;
26128 lambda *= radians, phi *= radians;
26129 lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi);
26132 function areaPoint(lambda, phi) {
26133 lambda *= radians, phi *= radians;
26134 phi = phi / 2 + quarterPi; // half the angular distance from south pole
26136 // Spherical excess E for a spherical triangle with vertices: south pole,
26137 // previous point, current point. Uses a formula derived from Cagnoli’s
26138 // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
26139 var dLambda = lambda - lambda0,
26140 sdLambda = dLambda >= 0 ? 1 : -1,
26141 adLambda = sdLambda * dLambda,
26142 cosPhi = cos$1(phi),
26143 sinPhi = sin$1(phi),
26144 k = sinPhi0 * sinPhi,
26145 u = cosPhi0 * cosPhi + k * cos$1(adLambda),
26146 v = k * sdLambda * sin$1(adLambda);
26147 areaRingSum.add(atan2(v, u));
26149 // Advance the previous points.
26150 lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
26153 var area = function(object) {
26155 geoStream(object, areaStream);
26156 return areaSum * 2;
26159 function spherical(cartesian) {
26160 return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
26163 function cartesian(spherical) {
26164 var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi);
26165 return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)];
26168 function cartesianDot(a, b) {
26169 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
26172 function cartesianCross(a, b) {
26173 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]];
26177 function cartesianAddInPlace(a, b) {
26178 a[0] += b[0], a[1] += b[1], a[2] += b[2];
26181 function cartesianScale(vector, k) {
26182 return [vector[0] * k, vector[1] * k, vector[2] * k];
26186 function cartesianNormalizeInPlace(d) {
26187 var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
26188 d[0] /= l, d[1] /= l, d[2] /= l;
26199 var deltaSum = adder();
26203 var boundsStream = {
26204 point: boundsPoint,
26205 lineStart: boundsLineStart,
26206 lineEnd: boundsLineEnd,
26207 polygonStart: function() {
26208 boundsStream.point = boundsRingPoint;
26209 boundsStream.lineStart = boundsRingStart;
26210 boundsStream.lineEnd = boundsRingEnd;
26212 areaStream.polygonStart();
26214 polygonEnd: function() {
26215 areaStream.polygonEnd();
26216 boundsStream.point = boundsPoint;
26217 boundsStream.lineStart = boundsLineStart;
26218 boundsStream.lineEnd = boundsLineEnd;
26219 if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
26220 else if (deltaSum > epsilon$2) phi1 = 90;
26221 else if (deltaSum < -epsilon$2) phi0 = -90;
26222 range[0] = lambda0$1, range[1] = lambda1;
26226 function boundsPoint(lambda, phi) {
26227 ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
26228 if (phi < phi0) phi0 = phi;
26229 if (phi > phi1) phi1 = phi;
26232 function linePoint(lambda, phi) {
26233 var p = cartesian([lambda * radians, phi * radians]);
26235 var normal = cartesianCross(p0, p),
26236 equatorial = [normal[1], -normal[0], 0],
26237 inflection = cartesianCross(equatorial, normal);
26238 cartesianNormalizeInPlace(inflection);
26239 inflection = spherical(inflection);
26240 var delta = lambda - lambda2,
26241 sign$$1 = delta > 0 ? 1 : -1,
26242 lambdai = inflection[0] * degrees$1 * sign$$1,
26244 antimeridian = abs(delta) > 180;
26245 if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
26246 phii = inflection[1] * degrees$1;
26247 if (phii > phi1) phi1 = phii;
26248 } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
26249 phii = -inflection[1] * degrees$1;
26250 if (phii < phi0) phi0 = phii;
26252 if (phi < phi0) phi0 = phi;
26253 if (phi > phi1) phi1 = phi;
26255 if (antimeridian) {
26256 if (lambda < lambda2) {
26257 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
26259 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
26262 if (lambda1 >= lambda0$1) {
26263 if (lambda < lambda0$1) lambda0$1 = lambda;
26264 if (lambda > lambda1) lambda1 = lambda;
26266 if (lambda > lambda2) {
26267 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
26269 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
26274 ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
26276 if (phi < phi0) phi0 = phi;
26277 if (phi > phi1) phi1 = phi;
26278 p0 = p, lambda2 = lambda;
26281 function boundsLineStart() {
26282 boundsStream.point = linePoint;
26285 function boundsLineEnd() {
26286 range[0] = lambda0$1, range[1] = lambda1;
26287 boundsStream.point = boundsPoint;
26291 function boundsRingPoint(lambda, phi) {
26293 var delta = lambda - lambda2;
26294 deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
26296 lambda00$1 = lambda, phi00$1 = phi;
26298 areaStream.point(lambda, phi);
26299 linePoint(lambda, phi);
26302 function boundsRingStart() {
26303 areaStream.lineStart();
26306 function boundsRingEnd() {
26307 boundsRingPoint(lambda00$1, phi00$1);
26308 areaStream.lineEnd();
26309 if (abs(deltaSum) > epsilon$2) lambda0$1 = -(lambda1 = 180);
26310 range[0] = lambda0$1, range[1] = lambda1;
26314 // Finds the left-right distance between two longitudes.
26315 // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
26316 // the distance between ±180° to be 360°.
26317 function angle(lambda0, lambda1) {
26318 return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
26321 function rangeCompare(a, b) {
26322 return a[0] - b[0];
26325 function rangeContains(range, x) {
26326 return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
26329 var bounds = function(feature) {
26330 var i, n, a, b, merged, deltaMax, delta;
26332 phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
26334 geoStream(feature, boundsStream);
26336 // First, sort ranges by their minimum longitudes.
26337 if (n = ranges.length) {
26338 ranges.sort(rangeCompare);
26340 // Then, merge any ranges that overlap.
26341 for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
26343 if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
26344 if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
26345 if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
26347 merged.push(a = b);
26351 // Finally, find the largest gap between the merged ranges.
26352 // The final bounding box will be the inverse of this gap.
26353 for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
26355 if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
26359 ranges = range = null;
26361 return lambda0$1 === Infinity || phi0 === Infinity
26362 ? [[NaN, NaN], [NaN, NaN]]
26363 : [[lambda0$1, phi0], [lambda1, phi1]];
26381 var z0; // previous point
26383 var centroidStream = {
26385 point: centroidPoint,
26386 lineStart: centroidLineStart,
26387 lineEnd: centroidLineEnd,
26388 polygonStart: function() {
26389 centroidStream.lineStart = centroidRingStart;
26390 centroidStream.lineEnd = centroidRingEnd;
26392 polygonEnd: function() {
26393 centroidStream.lineStart = centroidLineStart;
26394 centroidStream.lineEnd = centroidLineEnd;
26398 // Arithmetic mean of Cartesian vectors.
26399 function centroidPoint(lambda, phi) {
26400 lambda *= radians, phi *= radians;
26401 var cosPhi = cos$1(phi);
26402 centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi));
26405 function centroidPointCartesian(x, y, z) {
26407 X0 += (x - X0) / W0;
26408 Y0 += (y - Y0) / W0;
26409 Z0 += (z - Z0) / W0;
26412 function centroidLineStart() {
26413 centroidStream.point = centroidLinePointFirst;
26416 function centroidLinePointFirst(lambda, phi) {
26417 lambda *= radians, phi *= radians;
26418 var cosPhi = cos$1(phi);
26419 x0 = cosPhi * cos$1(lambda);
26420 y0 = cosPhi * sin$1(lambda);
26422 centroidStream.point = centroidLinePoint;
26423 centroidPointCartesian(x0, y0, z0);
26426 function centroidLinePoint(lambda, phi) {
26427 lambda *= radians, phi *= radians;
26428 var cosPhi = cos$1(phi),
26429 x = cosPhi * cos$1(lambda),
26430 y = cosPhi * sin$1(lambda),
26432 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);
26434 X1 += w * (x0 + (x0 = x));
26435 Y1 += w * (y0 + (y0 = y));
26436 Z1 += w * (z0 + (z0 = z));
26437 centroidPointCartesian(x0, y0, z0);
26440 function centroidLineEnd() {
26441 centroidStream.point = centroidPoint;
26444 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
26445 // J. Applied Mechanics 42, 239 (1975).
26446 function centroidRingStart() {
26447 centroidStream.point = centroidRingPointFirst;
26450 function centroidRingEnd() {
26451 centroidRingPoint(lambda00$2, phi00$2);
26452 centroidStream.point = centroidPoint;
26455 function centroidRingPointFirst(lambda, phi) {
26456 lambda00$2 = lambda, phi00$2 = phi;
26457 lambda *= radians, phi *= radians;
26458 centroidStream.point = centroidRingPoint;
26459 var cosPhi = cos$1(phi);
26460 x0 = cosPhi * cos$1(lambda);
26461 y0 = cosPhi * sin$1(lambda);
26463 centroidPointCartesian(x0, y0, z0);
26466 function centroidRingPoint(lambda, phi) {
26467 lambda *= radians, phi *= radians;
26468 var cosPhi = cos$1(phi),
26469 x = cosPhi * cos$1(lambda),
26470 y = cosPhi * sin$1(lambda),
26472 cx = y0 * z - z0 * y,
26473 cy = z0 * x - x0 * z,
26474 cz = x0 * y - y0 * x,
26475 m = sqrt(cx * cx + cy * cy + cz * cz),
26476 w = asin(m), // line weight = angle
26477 v = m && -w / m; // area weight multiplier
26482 X1 += w * (x0 + (x0 = x));
26483 Y1 += w * (y0 + (y0 = y));
26484 Z1 += w * (z0 + (z0 = z));
26485 centroidPointCartesian(x0, y0, z0);
26488 var d3GeoCentroid = function(object) {
26493 geoStream(object, centroidStream);
26498 m = x * x + y * y + z * z;
26500 // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
26501 if (m < epsilon2$1) {
26502 x = X1, y = Y1, z = Z1;
26503 // If the feature has zero length, fall back to arithmetic mean of point vectors.
26504 if (W1 < epsilon$2) x = X0, y = Y0, z = Z0;
26505 m = x * x + y * y + z * z;
26506 // If the feature still has an undefined ccentroid, then return.
26507 if (m < epsilon2$1) return [NaN, NaN];
26510 return [atan2(y, x) * degrees$1, asin(z / sqrt(m)) * degrees$1];
26513 var constant$7 = function(x) {
26514 return function() {
26519 var compose = function(a, b) {
26521 function compose(x, y) {
26522 return x = a(x, y), b(x[0], x[1]);
26525 if (a.invert && b.invert) compose.invert = function(x, y) {
26526 return x = b.invert(x, y), x && a.invert(x[0], x[1]);
26532 function rotationIdentity(lambda, phi) {
26533 return [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi];
26536 rotationIdentity.invert = rotationIdentity;
26538 function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
26539 return (deltaLambda %= tau$3) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
26540 : rotationLambda(deltaLambda))
26541 : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
26542 : rotationIdentity);
26545 function forwardRotationLambda(deltaLambda) {
26546 return function(lambda, phi) {
26547 return lambda += deltaLambda, [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi];
26551 function rotationLambda(deltaLambda) {
26552 var rotation = forwardRotationLambda(deltaLambda);
26553 rotation.invert = forwardRotationLambda(-deltaLambda);
26557 function rotationPhiGamma(deltaPhi, deltaGamma) {
26558 var cosDeltaPhi = cos$1(deltaPhi),
26559 sinDeltaPhi = sin$1(deltaPhi),
26560 cosDeltaGamma = cos$1(deltaGamma),
26561 sinDeltaGamma = sin$1(deltaGamma);
26563 function rotation(lambda, phi) {
26564 var cosPhi = cos$1(phi),
26565 x = cos$1(lambda) * cosPhi,
26566 y = sin$1(lambda) * cosPhi,
26568 k = z * cosDeltaPhi + x * sinDeltaPhi;
26570 atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
26571 asin(k * cosDeltaGamma + y * sinDeltaGamma)
26575 rotation.invert = function(lambda, phi) {
26576 var cosPhi = cos$1(phi),
26577 x = cos$1(lambda) * cosPhi,
26578 y = sin$1(lambda) * cosPhi,
26580 k = z * cosDeltaGamma - y * sinDeltaGamma;
26582 atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
26583 asin(k * cosDeltaPhi - x * sinDeltaPhi)
26590 var rotation = function(rotate) {
26591 rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
26593 function forward(coordinates) {
26594 coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
26595 return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
26598 forward.invert = function(coordinates) {
26599 coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
26600 return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
26606 // Generates a circle centered at [0°, 0°], with a given radius and precision.
26607 function circleStream(stream, radius, delta, direction, t0, t1) {
26608 if (!delta) return;
26609 var cosRadius = cos$1(radius),
26610 sinRadius = sin$1(radius),
26611 step = direction * delta;
26613 t0 = radius + direction * tau$3;
26614 t1 = radius - step / 2;
26616 t0 = circleRadius(cosRadius, t0);
26617 t1 = circleRadius(cosRadius, t1);
26618 if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$3;
26620 for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
26621 point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]);
26622 stream.point(point[0], point[1]);
26626 // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
26627 function circleRadius(cosRadius, point) {
26628 point = cartesian(point), point[0] -= cosRadius;
26629 cartesianNormalizeInPlace(point);
26630 var radius = acos(-point[1]);
26631 return ((-point[2] < 0 ? -radius : radius) + tau$3 - epsilon$2) % tau$3;
26634 var circle = function() {
26635 var center = constant$7([0, 0]),
26636 radius = constant$7(90),
26637 precision = constant$7(6),
26640 stream = {point: point};
26642 function point(x, y) {
26643 ring.push(x = rotate(x, y));
26644 x[0] *= degrees$1, x[1] *= degrees$1;
26647 function circle() {
26648 var c = center.apply(this, arguments),
26649 r = radius.apply(this, arguments) * radians,
26650 p = precision.apply(this, arguments) * radians;
26652 rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
26653 circleStream(stream, r, p, 1);
26654 c = {type: "Polygon", coordinates: [ring]};
26655 ring = rotate = null;
26659 circle.center = function(_) {
26660 return arguments.length ? (center = typeof _ === "function" ? _ : constant$7([+_[0], +_[1]]), circle) : center;
26663 circle.radius = function(_) {
26664 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), circle) : radius;
26667 circle.precision = function(_) {
26668 return arguments.length ? (precision = typeof _ === "function" ? _ : constant$7(+_), circle) : precision;
26674 var clipBuffer = function() {
26678 point: function(x, y) {
26681 lineStart: function() {
26682 lines.push(line = []);
26685 rejoin: function() {
26686 if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
26688 result: function() {
26689 var result = lines;
26697 var clipLine = function(a, b, x0, y0, x1, y1) {
26709 if (!dx && r > 0) return;
26712 if (r < t0) return;
26713 if (r < t1) t1 = r;
26714 } else if (dx > 0) {
26715 if (r > t1) return;
26716 if (r > t0) t0 = r;
26720 if (!dx && r < 0) return;
26723 if (r > t1) return;
26724 if (r > t0) t0 = r;
26725 } else if (dx > 0) {
26726 if (r < t0) return;
26727 if (r < t1) t1 = r;
26731 if (!dy && r > 0) return;
26734 if (r < t0) return;
26735 if (r < t1) t1 = r;
26736 } else if (dy > 0) {
26737 if (r > t1) return;
26738 if (r > t0) t0 = r;
26742 if (!dy && r < 0) return;
26745 if (r > t1) return;
26746 if (r > t0) t0 = r;
26747 } else if (dy > 0) {
26748 if (r < t0) return;
26749 if (r < t1) t1 = r;
26752 if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
26753 if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
26757 var pointEqual = function(a, b) {
26758 return abs(a[0] - b[0]) < epsilon$2 && abs(a[1] - b[1]) < epsilon$2;
26761 function Intersection(point, points, other, entry) {
26764 this.o = other; // another intersection
26765 this.e = entry; // is an entry?
26766 this.v = false; // visited
26767 this.n = this.p = null; // next & previous
26770 // A generalized polygon clipping algorithm: given a polygon that has been cut
26771 // into its visible line segments, and rejoins the segments by interpolating
26772 // along the clip edge.
26773 var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) {
26779 segments.forEach(function(segment) {
26780 if ((n = segment.length - 1) <= 0) return;
26781 var n, p0 = segment[0], p1 = segment[n], x;
26783 // If the first and last points of a segment are coincident, then treat as a
26784 // closed ring. TODO if all rings are closed, then the winding order of the
26785 // exterior ring should be checked.
26786 if (pointEqual(p0, p1)) {
26787 stream.lineStart();
26788 for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
26793 subject.push(x = new Intersection(p0, segment, null, true));
26794 clip.push(x.o = new Intersection(p0, null, x, false));
26795 subject.push(x = new Intersection(p1, segment, null, false));
26796 clip.push(x.o = new Intersection(p1, null, x, true));
26799 if (!subject.length) return;
26801 clip.sort(compareIntersection);
26805 for (i = 0, n = clip.length; i < n; ++i) {
26806 clip[i].e = startInside = !startInside;
26809 var start = subject[0],
26814 // Find first unvisited intersection.
26815 var current = start,
26817 while (current.v) if ((current = current.n) === start) return;
26818 points = current.z;
26819 stream.lineStart();
26821 current.v = current.o.v = true;
26824 for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
26826 interpolate(current.x, current.n.x, 1, stream);
26828 current = current.n;
26831 points = current.p.z;
26832 for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
26834 interpolate(current.x, current.p.x, -1, stream);
26836 current = current.p;
26838 current = current.o;
26839 points = current.z;
26840 isSubject = !isSubject;
26841 } while (!current.v);
26846 function link$1(array) {
26847 if (!(n = array.length)) return;
26853 a.n = b = array[i];
26857 a.n = b = array[0];
26862 var clipMin = -clipMax;
26864 // TODO Use d3-polygon’s polygonContains here for the ring check?
26865 // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
26867 function clipExtent(x0, y0, x1, y1) {
26869 function visible(x, y) {
26870 return x0 <= x && x <= x1 && y0 <= y && y <= y1;
26873 function interpolate(from, to, direction, stream) {
26876 || (a = corner(from, direction)) !== (a1 = corner(to, direction))
26877 || comparePoint(from, to) < 0 ^ direction > 0) {
26878 do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
26879 while ((a = (a + direction + 4) % 4) !== a1);
26881 stream.point(to[0], to[1]);
26885 function corner(p, direction) {
26886 return abs(p[0] - x0) < epsilon$2 ? direction > 0 ? 0 : 3
26887 : abs(p[0] - x1) < epsilon$2 ? direction > 0 ? 2 : 1
26888 : abs(p[1] - y0) < epsilon$2 ? direction > 0 ? 1 : 0
26889 : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
26892 function compareIntersection(a, b) {
26893 return comparePoint(a.x, b.x);
26896 function comparePoint(a, b) {
26897 var ca = corner(a, 1),
26899 return ca !== cb ? ca - cb
26900 : ca === 0 ? b[1] - a[1]
26901 : ca === 1 ? a[0] - b[0]
26902 : ca === 2 ? a[1] - b[1]
26906 return function(stream) {
26907 var activeStream = stream,
26908 bufferStream = clipBuffer(),
26912 x__, y__, v__, // first point
26913 x_, y_, v_, // previous point
26919 lineStart: lineStart,
26921 polygonStart: polygonStart,
26922 polygonEnd: polygonEnd
26925 function point(x, y) {
26926 if (visible(x, y)) activeStream.point(x, y);
26929 function polygonInside() {
26932 for (var i = 0, n = polygon.length; i < n; ++i) {
26933 for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
26934 a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
26935 if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
26936 else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
26943 // Buffer geometry within a polygon and then clip it en masse.
26944 function polygonStart() {
26945 activeStream = bufferStream, segments = [], polygon = [], clean = true;
26948 function polygonEnd() {
26949 var startInside = polygonInside(),
26950 cleanInside = clean && startInside,
26951 visible = (segments = merge(segments)).length;
26952 if (cleanInside || visible) {
26953 stream.polygonStart();
26955 stream.lineStart();
26956 interpolate(null, null, 1, stream);
26960 clipPolygon(segments, compareIntersection, startInside, interpolate, stream);
26962 stream.polygonEnd();
26964 activeStream = stream, segments = polygon = ring = null;
26967 function lineStart() {
26968 clipStream.point = linePoint;
26969 if (polygon) polygon.push(ring = []);
26975 // TODO rather than special-case polygons, simply handle them separately.
26976 // Ideally, coincident intersection points should be jittered to avoid
26977 // clipping issues.
26978 function lineEnd() {
26980 linePoint(x__, y__);
26981 if (v__ && v_) bufferStream.rejoin();
26982 segments.push(bufferStream.result());
26984 clipStream.point = point;
26985 if (v_) activeStream.lineEnd();
26988 function linePoint(x, y) {
26989 var v = visible(x, y);
26990 if (polygon) ring.push([x, y]);
26992 x__ = x, y__ = y, v__ = v;
26995 activeStream.lineStart();
26996 activeStream.point(x, y);
26999 if (v && v_) activeStream.point(x, y);
27001 var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
27002 b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
27003 if (clipLine(a, b, x0, y0, x1, y1)) {
27005 activeStream.lineStart();
27006 activeStream.point(a[0], a[1]);
27008 activeStream.point(b[0], b[1]);
27009 if (!v) activeStream.lineEnd();
27012 activeStream.lineStart();
27013 activeStream.point(x, y);
27018 x_ = x, y_ = y, v_ = v;
27025 var extent$1 = function() {
27035 stream: function(stream) {
27036 return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream);
27038 extent: function(_) {
27039 return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]];
27044 var sum$1 = adder();
27046 var polygonContains = function(polygon, point) {
27047 var lambda = point[0],
27049 normal = [sin$1(lambda), -cos$1(lambda), 0],
27055 for (var i = 0, n = polygon.length; i < n; ++i) {
27056 if (!(m = (ring = polygon[i]).length)) continue;
27059 point0 = ring[m - 1],
27060 lambda0 = point0[0],
27061 phi0 = point0[1] / 2 + quarterPi,
27062 sinPhi0 = sin$1(phi0),
27063 cosPhi0 = cos$1(phi0);
27065 for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
27066 var point1 = ring[j],
27067 lambda1 = point1[0],
27068 phi1 = point1[1] / 2 + quarterPi,
27069 sinPhi1 = sin$1(phi1),
27070 cosPhi1 = cos$1(phi1),
27071 delta = lambda1 - lambda0,
27072 sign$$1 = delta >= 0 ? 1 : -1,
27073 absDelta = sign$$1 * delta,
27074 antimeridian = absDelta > pi$3,
27075 k = sinPhi0 * sinPhi1;
27077 sum$1.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta)));
27078 angle += antimeridian ? delta + sign$$1 * tau$3 : delta;
27080 // Are the longitudes either side of the point’s meridian (lambda),
27081 // and are the latitudes smaller than the parallel (phi)?
27082 if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
27083 var arc = cartesianCross(cartesian(point0), cartesian(point1));
27084 cartesianNormalizeInPlace(arc);
27085 var intersection = cartesianCross(normal, arc);
27086 cartesianNormalizeInPlace(intersection);
27087 var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
27088 if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
27089 winding += antimeridian ^ delta >= 0 ? 1 : -1;
27095 // First, determine whether the South pole is inside or outside:
27097 // It is inside if:
27098 // * the polygon winds around it in a clockwise direction.
27099 // * the polygon does not (cumulatively) wind around it, but has a negative
27100 // (counter-clockwise) area.
27102 // Second, count the (signed) number of times a segment crosses a lambda
27103 // from the point to the South pole. If it is zero, then the point is the
27104 // same side as the South pole.
27106 return (angle < -epsilon$2 || angle < epsilon$2 && sum$1 < -epsilon$2) ^ (winding & 1);
27109 var lengthSum = adder();
27114 var lengthStream = {
27117 lineStart: lengthLineStart,
27119 polygonStart: noop$1,
27123 function lengthLineStart() {
27124 lengthStream.point = lengthPointFirst;
27125 lengthStream.lineEnd = lengthLineEnd;
27128 function lengthLineEnd() {
27129 lengthStream.point = lengthStream.lineEnd = noop$1;
27132 function lengthPointFirst(lambda, phi) {
27133 lambda *= radians, phi *= radians;
27134 lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi);
27135 lengthStream.point = lengthPoint;
27138 function lengthPoint(lambda, phi) {
27139 lambda *= radians, phi *= radians;
27140 var sinPhi = sin$1(phi),
27141 cosPhi = cos$1(phi),
27142 delta = abs(lambda - lambda0$2),
27143 cosDelta = cos$1(delta),
27144 sinDelta = sin$1(delta),
27145 x = cosPhi * sinDelta,
27146 y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta,
27147 z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta;
27148 lengthSum.add(atan2(sqrt(x * x + y * y), z));
27149 lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi;
27152 var d3GeoLength = function(object) {
27154 geoStream(object, lengthStream);
27158 var coordinates = [null, null];
27159 var object$1 = {type: "LineString", coordinates: coordinates};
27161 var distance = function(a, b) {
27162 coordinates[0] = a;
27163 coordinates[1] = b;
27164 return d3GeoLength(object$1);
27167 var containsObjectType = {
27168 Feature: function(object, point) {
27169 return containsGeometry(object.geometry, point);
27171 FeatureCollection: function(object, point) {
27172 var features = object.features, i = -1, n = features.length;
27173 while (++i < n) if (containsGeometry(features[i].geometry, point)) return true;
27178 var containsGeometryType = {
27179 Sphere: function() {
27182 Point: function(object, point) {
27183 return containsPoint(object.coordinates, point);
27185 MultiPoint: function(object, point) {
27186 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27187 while (++i < n) if (containsPoint(coordinates[i], point)) return true;
27190 LineString: function(object, point) {
27191 return containsLine(object.coordinates, point);
27193 MultiLineString: function(object, point) {
27194 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27195 while (++i < n) if (containsLine(coordinates[i], point)) return true;
27198 Polygon: function(object, point) {
27199 return containsPolygon(object.coordinates, point);
27201 MultiPolygon: function(object, point) {
27202 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27203 while (++i < n) if (containsPolygon(coordinates[i], point)) return true;
27206 GeometryCollection: function(object, point) {
27207 var geometries = object.geometries, i = -1, n = geometries.length;
27208 while (++i < n) if (containsGeometry(geometries[i], point)) return true;
27213 function containsGeometry(geometry, point) {
27214 return geometry && containsGeometryType.hasOwnProperty(geometry.type)
27215 ? containsGeometryType[geometry.type](geometry, point)
27219 function containsPoint(coordinates, point) {
27220 return distance(coordinates, point) === 0;
27223 function containsLine(coordinates, point) {
27224 var ab = distance(coordinates[0], coordinates[1]),
27225 ao = distance(coordinates[0], point),
27226 ob = distance(point, coordinates[1]);
27227 return ao + ob <= ab + epsilon$2;
27230 function containsPolygon(coordinates, point) {
27231 return !!polygonContains(coordinates.map(ringRadians), pointRadians(point));
27234 function ringRadians(ring) {
27235 return ring = ring.map(pointRadians), ring.pop(), ring;
27238 function pointRadians(point) {
27239 return [point[0] * radians, point[1] * radians];
27242 var contains = function(object, point) {
27243 return (object && containsObjectType.hasOwnProperty(object.type)
27244 ? containsObjectType[object.type]
27245 : containsGeometry)(object, point);
27248 function graticuleX(y0, y1, dy) {
27249 var y = sequence(y0, y1 - epsilon$2, dy).concat(y1);
27250 return function(x) { return y.map(function(y) { return [x, y]; }); };
27253 function graticuleY(x0, x1, dx) {
27254 var x = sequence(x0, x1 - epsilon$2, dx).concat(x1);
27255 return function(y) { return x.map(function(x) { return [x, y]; }); };
27258 function graticule() {
27259 var x1, x0, X1, X0,
27261 dx = 10, dy = dx, DX = 90, DY = 360,
27265 function graticule() {
27266 return {type: "MultiLineString", coordinates: lines()};
27270 return sequence(ceil(X0 / DX) * DX, X1, DX).map(X)
27271 .concat(sequence(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
27272 .concat(sequence(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$2; }).map(x))
27273 .concat(sequence(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$2; }).map(y));
27276 graticule.lines = function() {
27277 return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
27280 graticule.outline = function() {
27286 X(X1).reverse().slice(1),
27287 Y(Y0).reverse().slice(1))
27292 graticule.extent = function(_) {
27293 if (!arguments.length) return graticule.extentMinor();
27294 return graticule.extentMajor(_).extentMinor(_);
27297 graticule.extentMajor = function(_) {
27298 if (!arguments.length) return [[X0, Y0], [X1, Y1]];
27299 X0 = +_[0][0], X1 = +_[1][0];
27300 Y0 = +_[0][1], Y1 = +_[1][1];
27301 if (X0 > X1) _ = X0, X0 = X1, X1 = _;
27302 if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
27303 return graticule.precision(precision);
27306 graticule.extentMinor = function(_) {
27307 if (!arguments.length) return [[x0, y0], [x1, y1]];
27308 x0 = +_[0][0], x1 = +_[1][0];
27309 y0 = +_[0][1], y1 = +_[1][1];
27310 if (x0 > x1) _ = x0, x0 = x1, x1 = _;
27311 if (y0 > y1) _ = y0, y0 = y1, y1 = _;
27312 return graticule.precision(precision);
27315 graticule.step = function(_) {
27316 if (!arguments.length) return graticule.stepMinor();
27317 return graticule.stepMajor(_).stepMinor(_);
27320 graticule.stepMajor = function(_) {
27321 if (!arguments.length) return [DX, DY];
27322 DX = +_[0], DY = +_[1];
27326 graticule.stepMinor = function(_) {
27327 if (!arguments.length) return [dx, dy];
27328 dx = +_[0], dy = +_[1];
27332 graticule.precision = function(_) {
27333 if (!arguments.length) return precision;
27335 x = graticuleX(y0, y1, 90);
27336 y = graticuleY(x0, x1, precision);
27337 X = graticuleX(Y0, Y1, 90);
27338 Y = graticuleY(X0, X1, precision);
27343 .extentMajor([[-180, -90 + epsilon$2], [180, 90 - epsilon$2]])
27344 .extentMinor([[-180, -80 - epsilon$2], [180, 80 + epsilon$2]]);
27347 function graticule10() {
27348 return graticule()();
27351 var interpolate$1 = function(a, b) {
27352 var x0 = a[0] * radians,
27353 y0 = a[1] * radians,
27354 x1 = b[0] * radians,
27355 y1 = b[1] * radians,
27360 kx0 = cy0 * cos$1(x0),
27361 ky0 = cy0 * sin$1(x0),
27362 kx1 = cy1 * cos$1(x1),
27363 ky1 = cy1 * sin$1(x1),
27364 d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))),
27367 var interpolate = d ? function(t) {
27368 var B = sin$1(t *= d) / k,
27369 A = sin$1(d - t) / k,
27370 x = A * kx0 + B * kx1,
27371 y = A * ky0 + B * ky1,
27372 z = A * sy0 + B * sy1;
27374 atan2(y, x) * degrees$1,
27375 atan2(z, sqrt(x * x + y * y)) * degrees$1
27378 return [x0 * degrees$1, y0 * degrees$1];
27381 interpolate.distance = d;
27383 return interpolate;
27386 var identity$4 = function(x) {
27390 var areaSum$1 = adder();
27391 var areaRingSum$1 = adder();
27397 var areaStream$1 = {
27401 polygonStart: function() {
27402 areaStream$1.lineStart = areaRingStart$1;
27403 areaStream$1.lineEnd = areaRingEnd$1;
27405 polygonEnd: function() {
27406 areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$1;
27407 areaSum$1.add(abs(areaRingSum$1));
27408 areaRingSum$1.reset();
27410 result: function() {
27411 var area = areaSum$1 / 2;
27417 function areaRingStart$1() {
27418 areaStream$1.point = areaPointFirst$1;
27421 function areaPointFirst$1(x, y) {
27422 areaStream$1.point = areaPoint$1;
27423 x00 = x0$1 = x, y00 = y0$1 = y;
27426 function areaPoint$1(x, y) {
27427 areaRingSum$1.add(y0$1 * x - x0$1 * y);
27428 x0$1 = x, y0$1 = y;
27431 function areaRingEnd$1() {
27432 areaPoint$1(x00, y00);
27435 var x0$2 = Infinity;
27440 var boundsStream$1 = {
27441 point: boundsPoint$1,
27444 polygonStart: noop$1,
27445 polygonEnd: noop$1,
27446 result: function() {
27447 var bounds = [[x0$2, y0$2], [x1, y1]];
27448 x1 = y1 = -(y0$2 = x0$2 = Infinity);
27453 function boundsPoint$1(x, y) {
27454 if (x < x0$2) x0$2 = x;
27455 if (x > x1) x1 = x;
27456 if (y < y0$2) y0$2 = y;
27457 if (y > y1) y1 = y;
27460 // TODO Enforce positive area for exterior, negative area for interior?
27476 var centroidStream$1 = {
27477 point: centroidPoint$1,
27478 lineStart: centroidLineStart$1,
27479 lineEnd: centroidLineEnd$1,
27480 polygonStart: function() {
27481 centroidStream$1.lineStart = centroidRingStart$1;
27482 centroidStream$1.lineEnd = centroidRingEnd$1;
27484 polygonEnd: function() {
27485 centroidStream$1.point = centroidPoint$1;
27486 centroidStream$1.lineStart = centroidLineStart$1;
27487 centroidStream$1.lineEnd = centroidLineEnd$1;
27489 result: function() {
27490 var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1]
27491 : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1]
27492 : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1]
27494 X0$1 = Y0$1 = Z0$1 =
27495 X1$1 = Y1$1 = Z1$1 =
27496 X2$1 = Y2$1 = Z2$1 = 0;
27501 function centroidPoint$1(x, y) {
27507 function centroidLineStart$1() {
27508 centroidStream$1.point = centroidPointFirstLine;
27511 function centroidPointFirstLine(x, y) {
27512 centroidStream$1.point = centroidPointLine;
27513 centroidPoint$1(x0$3 = x, y0$3 = y);
27516 function centroidPointLine(x, y) {
27517 var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy);
27518 X1$1 += z * (x0$3 + x) / 2;
27519 Y1$1 += z * (y0$3 + y) / 2;
27521 centroidPoint$1(x0$3 = x, y0$3 = y);
27524 function centroidLineEnd$1() {
27525 centroidStream$1.point = centroidPoint$1;
27528 function centroidRingStart$1() {
27529 centroidStream$1.point = centroidPointFirstRing;
27532 function centroidRingEnd$1() {
27533 centroidPointRing(x00$1, y00$1);
27536 function centroidPointFirstRing(x, y) {
27537 centroidStream$1.point = centroidPointRing;
27538 centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y);
27541 function centroidPointRing(x, y) {
27544 z = sqrt(dx * dx + dy * dy);
27546 X1$1 += z * (x0$3 + x) / 2;
27547 Y1$1 += z * (y0$3 + y) / 2;
27550 z = y0$3 * x - x0$3 * y;
27551 X2$1 += z * (x0$3 + x);
27552 Y2$1 += z * (y0$3 + y);
27554 centroidPoint$1(x0$3 = x, y0$3 = y);
27557 function PathContext(context) {
27558 this._context = context;
27561 PathContext.prototype = {
27563 pointRadius: function(_) {
27564 return this._radius = _, this;
27566 polygonStart: function() {
27569 polygonEnd: function() {
27572 lineStart: function() {
27575 lineEnd: function() {
27576 if (this._line === 0) this._context.closePath();
27579 point: function(x, y) {
27580 switch (this._point) {
27582 this._context.moveTo(x, y);
27587 this._context.lineTo(x, y);
27591 this._context.moveTo(x + this._radius, y);
27592 this._context.arc(x, y, this._radius, 0, tau$3);
27600 var lengthSum$1 = adder();
27607 var lengthStream$1 = {
27609 lineStart: function() {
27610 lengthStream$1.point = lengthPointFirst$1;
27612 lineEnd: function() {
27613 if (lengthRing) lengthPoint$1(x00$2, y00$2);
27614 lengthStream$1.point = noop$1;
27616 polygonStart: function() {
27619 polygonEnd: function() {
27622 result: function() {
27623 var length = +lengthSum$1;
27624 lengthSum$1.reset();
27629 function lengthPointFirst$1(x, y) {
27630 lengthStream$1.point = lengthPoint$1;
27631 x00$2 = x0$4 = x, y00$2 = y0$4 = y;
27634 function lengthPoint$1(x, y) {
27635 x0$4 -= x, y0$4 -= y;
27636 lengthSum$1.add(sqrt(x0$4 * x0$4 + y0$4 * y0$4));
27637 x0$4 = x, y0$4 = y;
27640 function PathString() {
27644 PathString.prototype = {
27646 _circle: circle$1(4.5),
27647 pointRadius: function(_) {
27648 if ((_ = +_) !== this._radius) this._radius = _, this._circle = null;
27651 polygonStart: function() {
27654 polygonEnd: function() {
27657 lineStart: function() {
27660 lineEnd: function() {
27661 if (this._line === 0) this._string.push("Z");
27664 point: function(x, y) {
27665 switch (this._point) {
27667 this._string.push("M", x, ",", y);
27672 this._string.push("L", x, ",", y);
27676 if (this._circle == null) this._circle = circle$1(this._radius);
27677 this._string.push("M", x, ",", y, this._circle);
27682 result: function() {
27683 if (this._string.length) {
27684 var result = this._string.join("");
27693 function circle$1(radius) {
27694 return "m0," + radius
27695 + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
27696 + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
27700 var index$4 = function(projection, context) {
27701 var pointRadius = 4.5,
27705 function path(object) {
27707 if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
27708 geoStream(object, projectionStream(contextStream));
27710 return contextStream.result();
27713 path.area = function(object) {
27714 geoStream(object, projectionStream(areaStream$1));
27715 return areaStream$1.result();
27718 path.measure = function(object) {
27719 geoStream(object, projectionStream(lengthStream$1));
27720 return lengthStream$1.result();
27723 path.bounds = function(object) {
27724 geoStream(object, projectionStream(boundsStream$1));
27725 return boundsStream$1.result();
27728 path.centroid = function(object) {
27729 geoStream(object, projectionStream(centroidStream$1));
27730 return centroidStream$1.result();
27733 path.projection = function(_) {
27734 return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection;
27737 path.context = function(_) {
27738 if (!arguments.length) return context;
27739 contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _);
27740 if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
27744 path.pointRadius = function(_) {
27745 if (!arguments.length) return pointRadius;
27746 pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
27750 return path.projection(projection).context(context);
27753 var clip = function(pointVisible, clipLine, interpolate, start) {
27754 return function(rotate, sink) {
27755 var line = clipLine(sink),
27756 rotatedStart = rotate.invert(start[0], start[1]),
27757 ringBuffer = clipBuffer(),
27758 ringSink = clipLine(ringBuffer),
27759 polygonStarted = false,
27766 lineStart: lineStart,
27768 polygonStart: function() {
27769 clip.point = pointRing;
27770 clip.lineStart = ringStart;
27771 clip.lineEnd = ringEnd;
27775 polygonEnd: function() {
27776 clip.point = point;
27777 clip.lineStart = lineStart;
27778 clip.lineEnd = lineEnd;
27779 segments = merge(segments);
27780 var startInside = polygonContains(polygon, rotatedStart);
27781 if (segments.length) {
27782 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27783 clipPolygon(segments, compareIntersection, startInside, interpolate, sink);
27784 } else if (startInside) {
27785 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27787 interpolate(null, null, 1, sink);
27790 if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
27791 segments = polygon = null;
27793 sphere: function() {
27794 sink.polygonStart();
27796 interpolate(null, null, 1, sink);
27802 function point(lambda, phi) {
27803 var point = rotate(lambda, phi);
27804 if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi);
27807 function pointLine(lambda, phi) {
27808 var point = rotate(lambda, phi);
27809 line.point(point[0], point[1]);
27812 function lineStart() {
27813 clip.point = pointLine;
27817 function lineEnd() {
27818 clip.point = point;
27822 function pointRing(lambda, phi) {
27823 ring.push([lambda, phi]);
27824 var point = rotate(lambda, phi);
27825 ringSink.point(point[0], point[1]);
27828 function ringStart() {
27829 ringSink.lineStart();
27833 function ringEnd() {
27834 pointRing(ring[0][0], ring[0][1]);
27835 ringSink.lineEnd();
27837 var clean = ringSink.clean(),
27838 ringSegments = ringBuffer.result(),
27839 i, n = ringSegments.length, m,
27844 polygon.push(ring);
27849 // No intersections.
27851 segment = ringSegments[0];
27852 if ((m = segment.length - 1) > 0) {
27853 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27855 for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
27861 // Rejoin connected segments.
27862 // TODO reuse ringBuffer.rejoin()?
27863 if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
27865 segments.push(ringSegments.filter(validSegment));
27872 function validSegment(segment) {
27873 return segment.length > 1;
27876 // Intersections are sorted along the clip edge. For both antimeridian cutting
27877 // and circle clipping, the same comparison is used.
27878 function compareIntersection(a, b) {
27879 return ((a = a.x)[0] < 0 ? a[1] - halfPi$2 - epsilon$2 : halfPi$2 - a[1])
27880 - ((b = b.x)[0] < 0 ? b[1] - halfPi$2 - epsilon$2 : halfPi$2 - b[1]);
27883 var clipAntimeridian = clip(
27884 function() { return true; },
27885 clipAntimeridianLine,
27886 clipAntimeridianInterpolate,
27890 // Takes a line and cuts into visible segments. Return values: 0 - there were
27891 // intersections or the line was empty; 1 - no intersections; 2 - there were
27892 // intersections, and the first and last segments should be rejoined.
27893 function clipAntimeridianLine(stream) {
27897 clean; // no intersections
27900 lineStart: function() {
27901 stream.lineStart();
27904 point: function(lambda1, phi1) {
27905 var sign1 = lambda1 > 0 ? pi$3 : -pi$3,
27906 delta = abs(lambda1 - lambda0);
27907 if (abs(delta - pi$3) < epsilon$2) { // line crosses a pole
27908 stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$2 : -halfPi$2);
27909 stream.point(sign0, phi0);
27911 stream.lineStart();
27912 stream.point(sign1, phi0);
27913 stream.point(lambda1, phi0);
27915 } else if (sign0 !== sign1 && delta >= pi$3) { // line crosses antimeridian
27916 if (abs(lambda0 - sign0) < epsilon$2) lambda0 -= sign0 * epsilon$2; // handle degeneracies
27917 if (abs(lambda1 - sign1) < epsilon$2) lambda1 -= sign1 * epsilon$2;
27918 phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
27919 stream.point(sign0, phi0);
27921 stream.lineStart();
27922 stream.point(sign1, phi0);
27925 stream.point(lambda0 = lambda1, phi0 = phi1);
27928 lineEnd: function() {
27930 lambda0 = phi0 = NaN;
27932 clean: function() {
27933 return 2 - clean; // if intersections, rejoin first and last segments
27938 function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
27941 sinLambda0Lambda1 = sin$1(lambda0 - lambda1);
27942 return abs(sinLambda0Lambda1) > epsilon$2
27943 ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1)
27944 - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0))
27945 / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
27946 : (phi0 + phi1) / 2;
27949 function clipAntimeridianInterpolate(from, to, direction, stream) {
27951 if (from == null) {
27952 phi = direction * halfPi$2;
27953 stream.point(-pi$3, phi);
27954 stream.point(0, phi);
27955 stream.point(pi$3, phi);
27956 stream.point(pi$3, 0);
27957 stream.point(pi$3, -phi);
27958 stream.point(0, -phi);
27959 stream.point(-pi$3, -phi);
27960 stream.point(-pi$3, 0);
27961 stream.point(-pi$3, phi);
27962 } else if (abs(from[0] - to[0]) > epsilon$2) {
27963 var lambda = from[0] < to[0] ? pi$3 : -pi$3;
27964 phi = direction * lambda / 2;
27965 stream.point(-lambda, phi);
27966 stream.point(0, phi);
27967 stream.point(lambda, phi);
27969 stream.point(to[0], to[1]);
27973 var clipCircle = function(radius, delta) {
27974 var cr = cos$1(radius),
27975 smallRadius = cr > 0,
27976 notHemisphere = abs(cr) > epsilon$2; // TODO optimise for this common case
27978 function interpolate(from, to, direction, stream) {
27979 circleStream(stream, radius, delta, direction, from, to);
27982 function visible(lambda, phi) {
27983 return cos$1(lambda) * cos$1(phi) > cr;
27986 // Takes a line and cuts into visible segments. Return values used for polygon
27987 // clipping: 0 - there were intersections or the line was empty; 1 - no
27988 // intersections 2 - there were intersections, and the first and last segments
27989 // should be rejoined.
27990 function clipLine(stream) {
27991 var point0, // previous point
27992 c0, // code for previous point
27993 v0, // visibility of previous point
27994 v00, // visibility of first point
27995 clean; // no intersections
27997 lineStart: function() {
28001 point: function(lambda, phi) {
28002 var point1 = [lambda, phi],
28004 v = visible(lambda, phi),
28006 ? v ? 0 : code(lambda, phi)
28007 : v ? code(lambda + (lambda < 0 ? pi$3 : -pi$3), phi) : 0;
28008 if (!point0 && (v00 = v0 = v)) stream.lineStart();
28009 // Handle degeneracies.
28010 // TODO ignore if not clipping polygons.
28012 point2 = intersect(point0, point1);
28013 if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) {
28014 point1[0] += epsilon$2;
28015 point1[1] += epsilon$2;
28016 v = visible(point1[0], point1[1]);
28022 // outside going in
28023 stream.lineStart();
28024 point2 = intersect(point1, point0);
28025 stream.point(point2[0], point2[1]);
28027 // inside going out
28028 point2 = intersect(point0, point1);
28029 stream.point(point2[0], point2[1]);
28033 } else if (notHemisphere && point0 && smallRadius ^ v) {
28035 // If the codes for two points are different, or are both zero,
28036 // and there this segment intersects with the small circle.
28037 if (!(c & c0) && (t = intersect(point1, point0, true))) {
28040 stream.lineStart();
28041 stream.point(t[0][0], t[0][1]);
28042 stream.point(t[1][0], t[1][1]);
28045 stream.point(t[1][0], t[1][1]);
28047 stream.lineStart();
28048 stream.point(t[0][0], t[0][1]);
28052 if (v && (!point0 || !pointEqual(point0, point1))) {
28053 stream.point(point1[0], point1[1]);
28055 point0 = point1, v0 = v, c0 = c;
28057 lineEnd: function() {
28058 if (v0) stream.lineEnd();
28061 // Rejoin first and last segments if there were intersections and the first
28062 // and last points were visible.
28063 clean: function() {
28064 return clean | ((v00 && v0) << 1);
28069 // Intersects the great circle between a and b with the clip circle.
28070 function intersect(a, b, two) {
28071 var pa = cartesian(a),
28074 // We have two planes, n1.p = d1 and n2.p = d2.
28075 // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
28076 var n1 = [1, 0, 0], // normal
28077 n2 = cartesianCross(pa, pb),
28078 n2n2 = cartesianDot(n2, n2),
28079 n1n2 = n2[0], // cartesianDot(n1, n2),
28080 determinant = n2n2 - n1n2 * n1n2;
28082 // Two polar points.
28083 if (!determinant) return !two && a;
28085 var c1 = cr * n2n2 / determinant,
28086 c2 = -cr * n1n2 / determinant,
28087 n1xn2 = cartesianCross(n1, n2),
28088 A = cartesianScale(n1, c1),
28089 B = cartesianScale(n2, c2);
28090 cartesianAddInPlace(A, B);
28092 // Solve |p(t)|^2 = 1.
28094 w = cartesianDot(A, u),
28095 uu = cartesianDot(u, u),
28096 t2 = w * w - uu * (cartesianDot(A, A) - 1);
28098 if (t2 < 0) return;
28101 q = cartesianScale(u, (-w - t) / uu);
28102 cartesianAddInPlace(q, A);
28105 if (!two) return q;
28107 // Two intersection points.
28108 var lambda0 = a[0],
28114 if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
28116 var delta = lambda1 - lambda0,
28117 polar = abs(delta - pi$3) < epsilon$2,
28118 meridian = polar || delta < epsilon$2;
28120 if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
28122 // Check that the first point is between a and b.
28125 ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$2 ? phi0 : phi1)
28126 : phi0 <= q[1] && q[1] <= phi1
28127 : delta > pi$3 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
28128 var q1 = cartesianScale(u, (-w + t) / uu);
28129 cartesianAddInPlace(q1, A);
28130 return [q, spherical(q1)];
28134 // Generates a 4-bit vector representing the location of a point relative to
28135 // the small circle's bounding box.
28136 function code(lambda, phi) {
28137 var r = smallRadius ? radius : pi$3 - radius,
28139 if (lambda < -r) code |= 1; // left
28140 else if (lambda > r) code |= 2; // right
28141 if (phi < -r) code |= 4; // below
28142 else if (phi > r) code |= 8; // above
28146 return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$3, radius - pi$3]);
28149 var transform = function(methods) {
28151 stream: transformer(methods)
28155 function transformer(methods) {
28156 return function(stream) {
28157 var s = new TransformStream;
28158 for (var key in methods) s[key] = methods[key];
28164 function TransformStream() {}
28166 TransformStream.prototype = {
28167 constructor: TransformStream,
28168 point: function(x, y) { this.stream.point(x, y); },
28169 sphere: function() { this.stream.sphere(); },
28170 lineStart: function() { this.stream.lineStart(); },
28171 lineEnd: function() { this.stream.lineEnd(); },
28172 polygonStart: function() { this.stream.polygonStart(); },
28173 polygonEnd: function() { this.stream.polygonEnd(); }
28176 function fitExtent(projection, extent, object) {
28177 var w = extent[1][0] - extent[0][0],
28178 h = extent[1][1] - extent[0][1],
28179 clip = projection.clipExtent && projection.clipExtent();
28183 .translate([0, 0]);
28185 if (clip != null) projection.clipExtent(null);
28187 geoStream(object, projection.stream(boundsStream$1));
28189 var b = boundsStream$1.result(),
28190 k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
28191 x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
28192 y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
28194 if (clip != null) projection.clipExtent(clip);
28198 .translate([x, y]);
28201 function fitSize(projection, size, object) {
28202 return fitExtent(projection, [[0, 0], size], object);
28206 var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance)
28208 var resample = function(project, delta2) {
28209 return +delta2 ? resample$1(project, delta2) : resampleNone(project);
28212 function resampleNone(project) {
28213 return transformer({
28214 point: function(x, y) {
28216 this.stream.point(x[0], x[1]);
28221 function resample$1(project, delta2) {
28223 function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
28226 d2 = dx * dx + dy * dy;
28227 if (d2 > 4 * delta2 && depth--) {
28231 m = sqrt(a * a + b * b + c * c),
28232 phi2 = asin(c /= m),
28233 lambda2 = abs(abs(c) - 1) < epsilon$2 || abs(lambda0 - lambda1) < epsilon$2 ? (lambda0 + lambda1) / 2 : atan2(b, a),
28234 p = project(lambda2, phi2),
28239 dz = dy * dx2 - dx * dy2;
28240 if (dz * dz / d2 > delta2 // perpendicular projected distance
28241 || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
28242 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
28243 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
28244 stream.point(x2, y2);
28245 resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
28249 return function(stream) {
28250 var lambda00, x00, y00, a00, b00, c00, // first point
28251 lambda0, x0, y0, a0, b0, c0; // previous point
28253 var resampleStream = {
28255 lineStart: lineStart,
28257 polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
28258 polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
28261 function point(x, y) {
28263 stream.point(x[0], x[1]);
28266 function lineStart() {
28268 resampleStream.point = linePoint;
28269 stream.lineStart();
28272 function linePoint(lambda, phi) {
28273 var c = cartesian([lambda, phi]), p = project(lambda, phi);
28274 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);
28275 stream.point(x0, y0);
28278 function lineEnd() {
28279 resampleStream.point = point;
28283 function ringStart() {
28285 resampleStream.point = ringPoint;
28286 resampleStream.lineEnd = ringEnd;
28289 function ringPoint(lambda, phi) {
28290 linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
28291 resampleStream.point = linePoint;
28294 function ringEnd() {
28295 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
28296 resampleStream.lineEnd = lineEnd;
28300 return resampleStream;
28304 var transformRadians = transformer({
28305 point: function(x, y) {
28306 this.stream.point(x * radians, y * radians);
28310 function projection(project) {
28311 return projectionMutator(function() { return project; })();
28314 function projectionMutator(projectAt) {
28317 x = 480, y = 250, // translate
28318 dx, dy, lambda = 0, phi = 0, // center
28319 deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate
28320 theta = null, preclip = clipAntimeridian, // clip angle
28321 x0 = null, y0, x1, y1, postclip = identity$4, // clip extent
28322 delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision
28326 function projection(point) {
28327 point = projectRotate(point[0] * radians, point[1] * radians);
28328 return [point[0] * k + dx, dy - point[1] * k];
28331 function invert(point) {
28332 point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k);
28333 return point && [point[0] * degrees$1, point[1] * degrees$1];
28336 function projectTransform(x, y) {
28337 return x = project(x, y), [x[0] * k + dx, dy - x[1] * k];
28340 projection.stream = function(stream) {
28341 return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream))));
28344 projection.clipAngle = function(_) {
28345 return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
28348 projection.clipExtent = function(_) {
28349 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]];
28352 projection.scale = function(_) {
28353 return arguments.length ? (k = +_, recenter()) : k;
28356 projection.translate = function(_) {
28357 return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
28360 projection.center = function(_) {
28361 return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
28364 projection.rotate = function(_) {
28365 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];
28368 projection.precision = function(_) {
28369 return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
28372 projection.fitExtent = function(extent, object) {
28373 return fitExtent(projection, extent, object);
28376 projection.fitSize = function(size, object) {
28377 return fitSize(projection, size, object);
28380 function recenter() {
28381 projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project);
28382 var center = project(lambda, phi);
28383 dx = x - center[0] * k;
28384 dy = y + center[1] * k;
28389 cache = cacheStream = null;
28393 return function() {
28394 project = projectAt.apply(this, arguments);
28395 projection.invert = project.invert && invert;
28400 function conicProjection(projectAt) {
28403 m = projectionMutator(projectAt),
28406 p.parallels = function(_) {
28407 return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1];
28413 function cylindricalEqualAreaRaw(phi0) {
28414 var cosPhi0 = cos$1(phi0);
28416 function forward(lambda, phi) {
28417 return [lambda * cosPhi0, sin$1(phi) / cosPhi0];
28420 forward.invert = function(x, y) {
28421 return [x / cosPhi0, asin(y * cosPhi0)];
28427 function conicEqualAreaRaw(y0, y1) {
28428 var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2;
28430 // Are the parallels symmetrical around the Equator?
28431 if (abs(n) < epsilon$2) return cylindricalEqualAreaRaw(y0);
28433 var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n;
28435 function project(x, y) {
28436 var r = sqrt(c - 2 * n * sin$1(y)) / n;
28437 return [r * sin$1(x *= n), r0 - r * cos$1(x)];
28440 project.invert = function(x, y) {
28442 return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
28448 var conicEqualArea = function() {
28449 return conicProjection(conicEqualAreaRaw)
28451 .center([0, 33.6442]);
28454 var albers = function() {
28455 return conicEqualArea()
28456 .parallels([29.5, 45.5])
28458 .translate([480, 250])
28460 .center([-0.6, 38.7]);
28463 // The projections must have mutually exclusive clip regions on the sphere,
28464 // as this will avoid emitting interleaving lines and polygons.
28465 function multiplex(streams) {
28466 var n = streams.length;
28468 point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
28469 sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
28470 lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
28471 lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
28472 polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
28473 polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
28477 // A composite projection for the United States, configured by default for
28478 // 960×500. The projection also works quite well at 960×600 if you change the
28479 // scale to 1285 and adjust the translate accordingly. The set of standard
28480 // parallels for each region comes from USGS, which is published here:
28481 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
28482 var albersUsa = function() {
28485 lower48 = albers(), lower48Point,
28486 alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
28487 hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
28488 point, pointStream = {point: function(x, y) { point = [x, y]; }};
28490 function albersUsa(coordinates) {
28491 var x = coordinates[0], y = coordinates[1];
28492 return point = null,
28493 (lower48Point.point(x, y), point)
28494 || (alaskaPoint.point(x, y), point)
28495 || (hawaiiPoint.point(x, y), point);
28498 albersUsa.invert = function(coordinates) {
28499 var k = lower48.scale(),
28500 t = lower48.translate(),
28501 x = (coordinates[0] - t[0]) / k,
28502 y = (coordinates[1] - t[1]) / k;
28503 return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
28504 : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
28505 : lower48).invert(coordinates);
28508 albersUsa.stream = function(stream) {
28509 return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
28512 albersUsa.precision = function(_) {
28513 if (!arguments.length) return lower48.precision();
28514 lower48.precision(_), alaska.precision(_), hawaii.precision(_);
28518 albersUsa.scale = function(_) {
28519 if (!arguments.length) return lower48.scale();
28520 lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
28521 return albersUsa.translate(lower48.translate());
28524 albersUsa.translate = function(_) {
28525 if (!arguments.length) return lower48.translate();
28526 var k = lower48.scale(), x = +_[0], y = +_[1];
28528 lower48Point = lower48
28530 .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
28531 .stream(pointStream);
28533 alaskaPoint = alaska
28534 .translate([x - 0.307 * k, y + 0.201 * k])
28535 .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]])
28536 .stream(pointStream);
28538 hawaiiPoint = hawaii
28539 .translate([x - 0.205 * k, y + 0.212 * k])
28540 .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]])
28541 .stream(pointStream);
28546 albersUsa.fitExtent = function(extent, object) {
28547 return fitExtent(albersUsa, extent, object);
28550 albersUsa.fitSize = function(size, object) {
28551 return fitSize(albersUsa, size, object);
28555 cache = cacheStream = null;
28559 return albersUsa.scale(1070);
28562 function azimuthalRaw(scale) {
28563 return function(x, y) {
28566 k = scale(cx * cy);
28574 function azimuthalInvert(angle) {
28575 return function(x, y) {
28576 var z = sqrt(x * x + y * y),
28581 atan2(x * sc, z * cc),
28582 asin(z && y * sc / z)
28587 var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
28588 return sqrt(2 / (1 + cxcy));
28591 azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
28592 return 2 * asin(z / 2);
28595 var azimuthalEqualArea = function() {
28596 return projection(azimuthalEqualAreaRaw)
28598 .clipAngle(180 - 1e-3);
28601 var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
28602 return (c = acos(c)) && c / sin$1(c);
28605 azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
28609 var azimuthalEquidistant = function() {
28610 return projection(azimuthalEquidistantRaw)
28612 .clipAngle(180 - 1e-3);
28615 function mercatorRaw(lambda, phi) {
28616 return [lambda, log(tan((halfPi$2 + phi) / 2))];
28619 mercatorRaw.invert = function(x, y) {
28620 return [x, 2 * atan(exp(y)) - halfPi$2];
28623 var mercator = function() {
28624 return mercatorProjection(mercatorRaw)
28625 .scale(961 / tau$3);
28628 function mercatorProjection(project) {
28629 var m = projection(project),
28632 translate = m.translate,
28633 clipExtent = m.clipExtent,
28634 x0 = null, y0, x1, y1; // clip extent
28636 m.scale = function(_) {
28637 return arguments.length ? (scale(_), reclip()) : scale();
28640 m.translate = function(_) {
28641 return arguments.length ? (translate(_), reclip()) : translate();
28644 m.center = function(_) {
28645 return arguments.length ? (center(_), reclip()) : center();
28648 m.clipExtent = function(_) {
28649 return arguments.length ? ((_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1])), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]];
28652 function reclip() {
28653 var k = pi$3 * scale(),
28654 t = m(rotation(m.rotate()).invert([0, 0]));
28655 return clipExtent(x0 == null
28656 ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw
28657 ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]]
28658 : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]);
28665 return tan((halfPi$2 + y) / 2);
28668 function conicConformalRaw(y0, y1) {
28669 var cy0 = cos$1(y0),
28670 n = y0 === y1 ? sin$1(y0) : log(cy0 / cos$1(y1)) / log(tany(y1) / tany(y0)),
28671 f = cy0 * pow(tany(y0), n) / n;
28673 if (!n) return mercatorRaw;
28675 function project(x, y) {
28676 if (f > 0) { if (y < -halfPi$2 + epsilon$2) y = -halfPi$2 + epsilon$2; }
28677 else { if (y > halfPi$2 - epsilon$2) y = halfPi$2 - epsilon$2; }
28678 var r = f / pow(tany(y), n);
28679 return [r * sin$1(n * x), f - r * cos$1(n * x)];
28682 project.invert = function(x, y) {
28683 var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy);
28684 return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi$2];
28690 var conicConformal = function() {
28691 return conicProjection(conicConformalRaw)
28693 .parallels([30, 30]);
28696 function equirectangularRaw(lambda, phi) {
28697 return [lambda, phi];
28700 equirectangularRaw.invert = equirectangularRaw;
28702 var equirectangular = function() {
28703 return projection(equirectangularRaw)
28707 function conicEquidistantRaw(y0, y1) {
28708 var cy0 = cos$1(y0),
28709 n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0),
28712 if (abs(n) < epsilon$2) return equirectangularRaw;
28714 function project(x, y) {
28715 var gy = g - y, nx = n * x;
28716 return [gy * sin$1(nx), g - gy * cos$1(nx)];
28719 project.invert = function(x, y) {
28721 return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)];
28727 var conicEquidistant = function() {
28728 return conicProjection(conicEquidistantRaw)
28730 .center([0, 13.9389]);
28733 function gnomonicRaw(x, y) {
28734 var cy = cos$1(y), k = cos$1(x) * cy;
28735 return [cy * sin$1(x) / k, sin$1(y) / k];
28738 gnomonicRaw.invert = azimuthalInvert(atan);
28740 var gnomonic = function() {
28741 return projection(gnomonicRaw)
28746 function scaleTranslate(kx, ky, tx, ty) {
28747 return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity$4 : transformer({
28748 point: function(x, y) {
28749 this.stream.point(x * kx + tx, y * ky + ty);
28754 var identity$5 = function() {
28755 var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform$$1 = identity$4, // scale, translate and reflect
28756 x0 = null, y0, x1, y1, clip = identity$4, // clip extent
28762 cache = cacheStream = null;
28766 return projection = {
28767 stream: function(stream) {
28768 return cache && cacheStream === stream ? cache : cache = transform$$1(clip(cacheStream = stream));
28770 clipExtent: function(_) {
28771 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]];
28773 scale: function(_) {
28774 return arguments.length ? (transform$$1 = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k;
28776 translate: function(_) {
28777 return arguments.length ? (transform$$1 = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty];
28779 reflectX: function(_) {
28780 return arguments.length ? (transform$$1 = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0;
28782 reflectY: function(_) {
28783 return arguments.length ? (transform$$1 = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0;
28785 fitExtent: function(extent, object) {
28786 return fitExtent(projection, extent, object);
28788 fitSize: function(size, object) {
28789 return fitSize(projection, size, object);
28794 function orthographicRaw(x, y) {
28795 return [cos$1(y) * sin$1(x), sin$1(y)];
28798 orthographicRaw.invert = azimuthalInvert(asin);
28800 var orthographic = function() {
28801 return projection(orthographicRaw)
28803 .clipAngle(90 + epsilon$2);
28806 function stereographicRaw(x, y) {
28807 var cy = cos$1(y), k = 1 + cos$1(x) * cy;
28808 return [cy * sin$1(x) / k, sin$1(y) / k];
28811 stereographicRaw.invert = azimuthalInvert(function(z) {
28812 return 2 * atan(z);
28815 var stereographic = function() {
28816 return projection(stereographicRaw)
28821 function transverseMercatorRaw(lambda, phi) {
28822 return [log(tan((halfPi$2 + phi) / 2)), -lambda];
28825 transverseMercatorRaw.invert = function(x, y) {
28826 return [-y, 2 * atan(exp(x)) - halfPi$2];
28829 var transverseMercator = function() {
28830 var m = mercatorProjection(transverseMercatorRaw),
28834 m.center = function(_) {
28835 return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
28838 m.rotate = function(_) {
28839 return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
28842 return rotate([0, 0, 90])
28846 function defaultSeparation(a, b) {
28847 return a.parent === b.parent ? 1 : 2;
28850 function meanX(children) {
28851 return children.reduce(meanXReduce, 0) / children.length;
28854 function meanXReduce(x, c) {
28858 function maxY(children) {
28859 return 1 + children.reduce(maxYReduce, 0);
28862 function maxYReduce(y, c) {
28863 return Math.max(y, c.y);
28866 function leafLeft(node) {
28868 while (children = node.children) node = children[0];
28872 function leafRight(node) {
28874 while (children = node.children) node = children[children.length - 1];
28878 var cluster = function() {
28879 var separation = defaultSeparation,
28884 function cluster(root) {
28888 // First walk, computing the initial x & y values.
28889 root.eachAfter(function(node) {
28890 var children = node.children;
28892 node.x = meanX(children);
28893 node.y = maxY(children);
28895 node.x = previousNode ? x += separation(node, previousNode) : 0;
28897 previousNode = node;
28901 var left = leafLeft(root),
28902 right = leafRight(root),
28903 x0 = left.x - separation(left, right) / 2,
28904 x1 = right.x + separation(right, left) / 2;
28906 // Second walk, normalizing x & y to the desired size.
28907 return root.eachAfter(nodeSize ? function(node) {
28908 node.x = (node.x - root.x) * dx;
28909 node.y = (root.y - node.y) * dy;
28910 } : function(node) {
28911 node.x = (node.x - x0) / (x1 - x0) * dx;
28912 node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
28916 cluster.separation = function(x) {
28917 return arguments.length ? (separation = x, cluster) : separation;
28920 cluster.size = function(x) {
28921 return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
28924 cluster.nodeSize = function(x) {
28925 return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
28931 function count(node) {
28933 children = node.children,
28934 i = children && children.length;
28936 else while (--i >= 0) sum += children[i].value;
28940 var node_count = function() {
28941 return this.eachAfter(count);
28944 var node_each = function(callback) {
28945 var node = this, current, next = [node], children, i, n;
28947 current = next.reverse(), next = [];
28948 while (node = current.pop()) {
28949 callback(node), children = node.children;
28950 if (children) for (i = 0, n = children.length; i < n; ++i) {
28951 next.push(children[i]);
28954 } while (next.length);
28958 var node_eachBefore = function(callback) {
28959 var node = this, nodes = [node], children, i;
28960 while (node = nodes.pop()) {
28961 callback(node), children = node.children;
28962 if (children) for (i = children.length - 1; i >= 0; --i) {
28963 nodes.push(children[i]);
28969 var node_eachAfter = function(callback) {
28970 var node = this, nodes = [node], next = [], children, i, n;
28971 while (node = nodes.pop()) {
28972 next.push(node), children = node.children;
28973 if (children) for (i = 0, n = children.length; i < n; ++i) {
28974 nodes.push(children[i]);
28977 while (node = next.pop()) {
28983 var node_sum = function(value) {
28984 return this.eachAfter(function(node) {
28985 var sum = +value(node.data) || 0,
28986 children = node.children,
28987 i = children && children.length;
28988 while (--i >= 0) sum += children[i].value;
28993 var node_sort = function(compare) {
28994 return this.eachBefore(function(node) {
28995 if (node.children) {
28996 node.children.sort(compare);
29001 var node_path = function(end) {
29003 ancestor = leastCommonAncestor(start, end),
29005 while (start !== ancestor) {
29006 start = start.parent;
29009 var k = nodes.length;
29010 while (end !== ancestor) {
29011 nodes.splice(k, 0, end);
29017 function leastCommonAncestor(a, b) {
29018 if (a === b) return a;
29019 var aNodes = a.ancestors(),
29020 bNodes = b.ancestors(),
29032 var node_ancestors = function() {
29033 var node = this, nodes = [node];
29034 while (node = node.parent) {
29040 var node_descendants = function() {
29042 this.each(function(node) {
29048 var node_leaves = function() {
29050 this.eachBefore(function(node) {
29051 if (!node.children) {
29058 var node_links = function() {
29059 var root = this, links = [];
29060 root.each(function(node) {
29061 if (node !== root) { // Don’t include the root’s parent, if any.
29062 links.push({source: node.parent, target: node});
29068 function hierarchy(data, children) {
29069 var root = new Node(data),
29070 valued = +data.value && (root.value = data.value),
29078 if (children == null) children = defaultChildren;
29080 while (node = nodes.pop()) {
29081 if (valued) node.value = +node.data.value;
29082 if ((childs = children(node.data)) && (n = childs.length)) {
29083 node.children = new Array(n);
29084 for (i = n - 1; i >= 0; --i) {
29085 nodes.push(child = node.children[i] = new Node(childs[i]));
29086 child.parent = node;
29087 child.depth = node.depth + 1;
29092 return root.eachBefore(computeHeight);
29095 function node_copy() {
29096 return hierarchy(this).eachBefore(copyData);
29099 function defaultChildren(d) {
29103 function copyData(node) {
29104 node.data = node.data.data;
29107 function computeHeight(node) {
29109 do node.height = height;
29110 while ((node = node.parent) && (node.height < ++height));
29113 function Node(data) {
29117 this.parent = null;
29120 Node.prototype = hierarchy.prototype = {
29124 eachAfter: node_eachAfter,
29125 eachBefore: node_eachBefore,
29129 ancestors: node_ancestors,
29130 descendants: node_descendants,
29131 leaves: node_leaves,
29136 function Node$2(value) {
29141 var shuffle$1 = function(array) {
29143 n = (array = array.slice()).length,
29148 var next = new Node$2(array[n - 1]);
29149 if (node) node = node.next = next;
29150 else node = head = next;
29151 array[i] = array[--n];
29160 var enclose = function(circles) {
29161 return encloseN(shuffle$1(circles), []);
29164 function encloses(a, b) {
29165 var dx = b.x - a.x,
29168 return dr * dr + 1e-6 > dx * dx + dy * dy;
29171 // Returns the smallest circle that contains circles L and intersects circles B.
29172 function encloseN(L, B) {
29179 switch (B.length) {
29180 case 1: circle = enclose1(B[0]); break;
29181 case 2: circle = enclose2(B[0], B[1]); break;
29182 case 3: circle = enclose3(B[0], B[1], B[2]); break;
29186 p1 = l1._, l2 = l1.next;
29187 if (!circle || !encloses(circle, p1)) {
29189 // Temporarily truncate L before l1.
29190 if (l0) L.tail = l0, l0.next = null;
29191 else L.head = L.tail = null;
29194 circle = encloseN(L, B); // Note: reorders L!
29197 // Move l1 to the front of L and reconnect the truncated list L.
29198 if (L.head) l1.next = L.head, L.head = l1;
29199 else l1.next = null, L.head = L.tail = l1;
29200 l0 = L.tail, l0.next = l2;
29212 function enclose1(a) {
29220 function enclose2(a, b) {
29221 var x1 = a.x, y1 = a.y, r1 = a.r,
29222 x2 = b.x, y2 = b.y, r2 = b.r,
29223 x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
29224 l = Math.sqrt(x21 * x21 + y21 * y21);
29226 x: (x1 + x2 + x21 / l * r21) / 2,
29227 y: (y1 + y2 + y21 / l * r21) / 2,
29228 r: (l + r1 + r2) / 2
29232 function enclose3(a, b, c) {
29233 var x1 = a.x, y1 = a.y, r1 = a.r,
29234 x2 = b.x, y2 = b.y, r2 = b.r,
29235 x3 = c.x, y3 = c.y, r3 = c.r,
29236 a2 = 2 * (x1 - x2),
29237 b2 = 2 * (y1 - y2),
29238 c2 = 2 * (r2 - r1),
29239 d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2,
29240 a3 = 2 * (x1 - x3),
29241 b3 = 2 * (y1 - y3),
29242 c3 = 2 * (r3 - r1),
29243 d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3,
29244 ab = a3 * b2 - a2 * b3,
29245 xa = (b2 * d3 - b3 * d2) / ab - x1,
29246 xb = (b3 * c2 - b2 * c3) / ab,
29247 ya = (a3 * d2 - a2 * d3) / ab - y1,
29248 yb = (a2 * c3 - a3 * c2) / ab,
29249 A = xb * xb + yb * yb - 1,
29250 B = 2 * (xa * xb + ya * yb + r1),
29251 C = xa * xa + ya * ya - r1 * r1,
29252 r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
29254 x: xa + xb * r + x1,
29255 y: ya + yb * r + y1,
29260 function place(a, b, c) {
29267 dc = dx * dx + dy * dy;
29269 var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc),
29270 y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
29271 c.x = ax + x * dx + y * dy;
29272 c.y = ay + x * dy - y * dx;
29279 function intersects(a, b) {
29280 var dx = b.x - a.x,
29283 return dr * dr - 1e-6 > dx * dx + dy * dy;
29286 function distance2(node, x, y) {
29290 dx = (a.x * b.r + b.x * a.r) / ab - x,
29291 dy = (a.y * b.r + b.y * a.r) / ab - y;
29292 return dx * dx + dy * dy;
29295 function Node$1(circle) {
29298 this.previous = null;
29301 function packEnclose(circles) {
29302 if (!(n = circles.length)) return 0;
29306 // Place the first circle.
29307 a = circles[0], a.x = 0, a.y = 0;
29308 if (!(n > 1)) return a.r;
29310 // Place the second circle.
29311 b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
29312 if (!(n > 2)) return a.r + b.r;
29314 // Place the third circle.
29315 place(b, a, c = circles[2]);
29317 // Initialize the weighted centroid.
29318 var aa = a.r * a.r,
29322 ox = aa * a.x + ba * b.x + ca * c.x,
29323 oy = aa * a.y + ba * b.y + ca * c.y,
29324 cx, cy, i, j, k, sj, sk;
29326 // Initialize the front-chain using the first three circles a, b and c.
29327 a = new Node$1(a), b = new Node$1(b), c = new Node$1(c);
29328 a.next = c.previous = b;
29329 b.next = a.previous = c;
29330 c.next = b.previous = a;
29332 // Attempt to place each remaining circle…
29333 pack: for (i = 3; i < n; ++i) {
29334 place(a._, b._, c = circles[i]), c = new Node$1(c);
29336 // Find the closest intersecting circle on the front-chain, if any.
29337 // “Closeness” is determined by linear distance along the front-chain.
29338 // “Ahead” or “behind” is likewise determined by linear distance.
29339 j = b.next, k = a.previous, sj = b._.r, sk = a._.r;
29342 if (intersects(j._, c._)) {
29343 b = j, a.next = b, b.previous = a, --i;
29346 sj += j._.r, j = j.next;
29348 if (intersects(k._, c._)) {
29349 a = k, a.next = b, b.previous = a, --i;
29352 sk += k._.r, k = k.previous;
29354 } while (j !== k.next);
29356 // Success! Insert the new circle c between a and b.
29357 c.previous = a, c.next = b, a.next = b.previous = b = c;
29359 // Update the weighted centroid.
29360 oa += ca = c._.r * c._.r;
29364 // Compute the new closest circle pair to the centroid.
29365 aa = distance2(a, cx = ox / oa, cy = oy / oa);
29366 while ((c = c.next) !== b) {
29367 if ((ca = distance2(c, cx, cy)) < aa) {
29374 // Compute the enclosing circle of the front chain.
29375 a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);
29377 // Translate the circles to put the enclosing circle around the origin.
29378 for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
29383 var siblings = function(circles) {
29384 packEnclose(circles);
29388 function optional(f) {
29389 return f == null ? null : required(f);
29392 function required(f) {
29393 if (typeof f !== "function") throw new Error;
29397 function constantZero() {
29401 var constant$8 = function(x) {
29402 return function() {
29407 function defaultRadius$1(d) {
29408 return Math.sqrt(d.value);
29411 var index$5 = function() {
29415 padding = constantZero;
29417 function pack(root) {
29418 root.x = dx / 2, root.y = dy / 2;
29420 root.eachBefore(radiusLeaf(radius))
29421 .eachAfter(packChildren(padding, 0.5))
29422 .eachBefore(translateChild(1));
29424 root.eachBefore(radiusLeaf(defaultRadius$1))
29425 .eachAfter(packChildren(constantZero, 1))
29426 .eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))
29427 .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
29432 pack.radius = function(x) {
29433 return arguments.length ? (radius = optional(x), pack) : radius;
29436 pack.size = function(x) {
29437 return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
29440 pack.padding = function(x) {
29441 return arguments.length ? (padding = typeof x === "function" ? x : constant$8(+x), pack) : padding;
29447 function radiusLeaf(radius) {
29448 return function(node) {
29449 if (!node.children) {
29450 node.r = Math.max(0, +radius(node) || 0);
29455 function packChildren(padding, k) {
29456 return function(node) {
29457 if (children = node.children) {
29460 n = children.length,
29461 r = padding(node) * k || 0,
29464 if (r) for (i = 0; i < n; ++i) children[i].r += r;
29465 e = packEnclose(children);
29466 if (r) for (i = 0; i < n; ++i) children[i].r -= r;
29472 function translateChild(k) {
29473 return function(node) {
29474 var parent = node.parent;
29477 node.x = parent.x + k * node.x;
29478 node.y = parent.y + k * node.y;
29483 var roundNode = function(node) {
29484 node.x0 = Math.round(node.x0);
29485 node.y0 = Math.round(node.y0);
29486 node.x1 = Math.round(node.x1);
29487 node.y1 = Math.round(node.y1);
29490 var treemapDice = function(parent, x0, y0, x1, y1) {
29491 var nodes = parent.children,
29495 k = parent.value && (x1 - x0) / parent.value;
29498 node = nodes[i], node.y0 = y0, node.y1 = y1;
29499 node.x0 = x0, node.x1 = x0 += node.value * k;
29503 var partition = function() {
29509 function partition(root) {
29510 var n = root.height + 1;
29515 root.eachBefore(positionNode(dy, n));
29516 if (round) root.eachBefore(roundNode);
29520 function positionNode(dy, n) {
29521 return function(node) {
29522 if (node.children) {
29523 treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
29527 x1 = node.x1 - padding,
29528 y1 = node.y1 - padding;
29529 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29530 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29538 partition.round = function(x) {
29539 return arguments.length ? (round = !!x, partition) : round;
29542 partition.size = function(x) {
29543 return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
29546 partition.padding = function(x) {
29547 return arguments.length ? (padding = +x, partition) : padding;
29553 var keyPrefix$1 = "$";
29554 var preroot = {depth: -1};
29555 var ambiguous = {};
29557 function defaultId(d) {
29561 function defaultParentId(d) {
29565 var stratify = function() {
29566 var id = defaultId,
29567 parentId = defaultParentId;
29569 function stratify(data) {
29576 nodes = new Array(n),
29581 for (i = 0; i < n; ++i) {
29582 d = data[i], node = nodes[i] = new Node(d);
29583 if ((nodeId = id(d, i, data)) != null && (nodeId += "")) {
29584 nodeKey = keyPrefix$1 + (node.id = nodeId);
29585 nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node;
29589 for (i = 0; i < n; ++i) {
29590 node = nodes[i], nodeId = parentId(data[i], i, data);
29591 if (nodeId == null || !(nodeId += "")) {
29592 if (root) throw new Error("multiple roots");
29595 parent = nodeByKey[keyPrefix$1 + nodeId];
29596 if (!parent) throw new Error("missing: " + nodeId);
29597 if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
29598 if (parent.children) parent.children.push(node);
29599 else parent.children = [node];
29600 node.parent = parent;
29604 if (!root) throw new Error("no root");
29605 root.parent = preroot;
29606 root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
29607 root.parent = null;
29608 if (n > 0) throw new Error("cycle");
29613 stratify.id = function(x) {
29614 return arguments.length ? (id = required(x), stratify) : id;
29617 stratify.parentId = function(x) {
29618 return arguments.length ? (parentId = required(x), stratify) : parentId;
29624 function defaultSeparation$1(a, b) {
29625 return a.parent === b.parent ? 1 : 2;
29628 // function radialSeparation(a, b) {
29629 // return (a.parent === b.parent ? 1 : 2) / a.depth;
29632 // This function is used to traverse the left contour of a subtree (or
29633 // subforest). It returns the successor of v on this contour. This successor is
29634 // either given by the leftmost child of v or by the thread of v. The function
29635 // returns null if and only if v is on the highest level of its subtree.
29636 function nextLeft(v) {
29637 var children = v.children;
29638 return children ? children[0] : v.t;
29641 // This function works analogously to nextLeft.
29642 function nextRight(v) {
29643 var children = v.children;
29644 return children ? children[children.length - 1] : v.t;
29647 // Shifts the current subtree rooted at w+. This is done by increasing
29648 // prelim(w+) and mod(w+) by shift.
29649 function moveSubtree(wm, wp, shift) {
29650 var change = shift / (wp.i - wm.i);
29658 // All other shifts, applied to the smaller subtrees between w- and w+, are
29659 // performed by this function. To prepare the shifts, we have to adjust
29660 // change(w+), shift(w+), and change(w-).
29661 function executeShifts(v) {
29664 children = v.children,
29665 i = children.length,
29671 shift += w.s + (change += w.c);
29675 // If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
29676 // returns the specified (default) ancestor.
29677 function nextAncestor(vim, v, ancestor) {
29678 return vim.a.parent === v.parent ? vim.a : ancestor;
29681 function TreeNode(node, i) {
29683 this.parent = null;
29684 this.children = null;
29685 this.A = null; // default ancestor
29686 this.a = this; // ancestor
29687 this.z = 0; // prelim
29689 this.c = 0; // change
29690 this.s = 0; // shift
29691 this.t = null; // thread
29692 this.i = i; // number
29695 TreeNode.prototype = Object.create(Node.prototype);
29697 function treeRoot(root) {
29698 var tree = new TreeNode(root, 0),
29706 while (node = nodes.pop()) {
29707 if (children = node._.children) {
29708 node.children = new Array(n = children.length);
29709 for (i = n - 1; i >= 0; --i) {
29710 nodes.push(child = node.children[i] = new TreeNode(children[i], i));
29711 child.parent = node;
29716 (tree.parent = new TreeNode(null, 0)).children = [tree];
29720 // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
29721 var tree = function() {
29722 var separation = defaultSeparation$1,
29727 function tree(root) {
29728 var t = treeRoot(root);
29730 // Compute the layout using Buchheim et al.’s algorithm.
29731 t.eachAfter(firstWalk), t.parent.m = -t.z;
29732 t.eachBefore(secondWalk);
29734 // If a fixed node size is specified, scale x and y.
29735 if (nodeSize) root.eachBefore(sizeNode);
29737 // If a fixed tree size is specified, scale x and y based on the extent.
29738 // Compute the left-most, right-most, and depth-most nodes for extents.
29743 root.eachBefore(function(node) {
29744 if (node.x < left.x) left = node;
29745 if (node.x > right.x) right = node;
29746 if (node.depth > bottom.depth) bottom = node;
29748 var s = left === right ? 1 : separation(left, right) / 2,
29750 kx = dx / (right.x + s + tx),
29751 ky = dy / (bottom.depth || 1);
29752 root.eachBefore(function(node) {
29753 node.x = (node.x + tx) * kx;
29754 node.y = node.depth * ky;
29761 // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
29762 // applied recursively to the children of v, as well as the function
29763 // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
29764 // node v is placed to the midpoint of its outermost children.
29765 function firstWalk(v) {
29766 var children = v.children,
29767 siblings = v.parent.children,
29768 w = v.i ? siblings[v.i - 1] : null;
29771 var midpoint = (children[0].z + children[children.length - 1].z) / 2;
29773 v.z = w.z + separation(v._, w._);
29774 v.m = v.z - midpoint;
29779 v.z = w.z + separation(v._, w._);
29781 v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
29784 // Computes all real x-coordinates by summing up the modifiers recursively.
29785 function secondWalk(v) {
29786 v._.x = v.z + v.parent.m;
29790 // The core of the algorithm. Here, a new subtree is combined with the
29791 // previous subtrees. Threads are used to traverse the inside and outside
29792 // contours of the left and right subtree up to the highest common level. The
29793 // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
29794 // superscript o means outside and i means inside, the subscript - means left
29795 // subtree and + means right subtree. For summing up the modifiers along the
29796 // contour, we use respective variables si+, si-, so-, and so+. Whenever two
29797 // nodes of the inside contours conflict, we compute the left one of the
29798 // greatest uncommon ancestors using the function ANCESTOR and call MOVE
29799 // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
29800 // Finally, we add a new thread (if necessary).
29801 function apportion(v, w, ancestor) {
29806 vom = vip.parent.children[0],
29812 while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
29813 vom = nextLeft(vom);
29814 vop = nextRight(vop);
29816 shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
29818 moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
29827 if (vim && !nextRight(vop)) {
29829 vop.m += sim - sop;
29831 if (vip && !nextLeft(vom)) {
29833 vom.m += sip - som;
29840 function sizeNode(node) {
29842 node.y = node.depth * dy;
29845 tree.separation = function(x) {
29846 return arguments.length ? (separation = x, tree) : separation;
29849 tree.size = function(x) {
29850 return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
29853 tree.nodeSize = function(x) {
29854 return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
29860 var treemapSlice = function(parent, x0, y0, x1, y1) {
29861 var nodes = parent.children,
29865 k = parent.value && (y1 - y0) / parent.value;
29868 node = nodes[i], node.x0 = x0, node.x1 = x1;
29869 node.y0 = y0, node.y1 = y0 += node.value * k;
29873 var phi = (1 + Math.sqrt(5)) / 2;
29875 function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
29877 nodes = parent.children,
29884 value = parent.value,
29894 dx = x1 - x0, dy = y1 - y0;
29896 // Find the next non-empty node.
29897 do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
29898 minValue = maxValue = sumValue;
29899 alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
29900 beta = sumValue * sumValue * alpha;
29901 minRatio = Math.max(maxValue / beta, beta / minValue);
29903 // Keep adding nodes while the aspect ratio maintains or improves.
29904 for (; i1 < n; ++i1) {
29905 sumValue += nodeValue = nodes[i1].value;
29906 if (nodeValue < minValue) minValue = nodeValue;
29907 if (nodeValue > maxValue) maxValue = nodeValue;
29908 beta = sumValue * sumValue * alpha;
29909 newRatio = Math.max(maxValue / beta, beta / minValue);
29910 if (newRatio > minRatio) { sumValue -= nodeValue; break; }
29911 minRatio = newRatio;
29914 // Position and record the row orientation.
29915 rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
29916 if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
29917 else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
29918 value -= sumValue, i0 = i1;
29924 var squarify = (function custom(ratio) {
29926 function squarify(parent, x0, y0, x1, y1) {
29927 squarifyRatio(ratio, parent, x0, y0, x1, y1);
29930 squarify.ratio = function(x) {
29931 return custom((x = +x) > 1 ? x : 1);
29937 var index$6 = function() {
29938 var tile = squarify,
29942 paddingStack = [0],
29943 paddingInner = constantZero,
29944 paddingTop = constantZero,
29945 paddingRight = constantZero,
29946 paddingBottom = constantZero,
29947 paddingLeft = constantZero;
29949 function treemap(root) {
29954 root.eachBefore(positionNode);
29955 paddingStack = [0];
29956 if (round) root.eachBefore(roundNode);
29960 function positionNode(node) {
29961 var p = paddingStack[node.depth],
29966 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29967 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29972 if (node.children) {
29973 p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
29974 x0 += paddingLeft(node) - p;
29975 y0 += paddingTop(node) - p;
29976 x1 -= paddingRight(node) - p;
29977 y1 -= paddingBottom(node) - p;
29978 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29979 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29980 tile(node, x0, y0, x1, y1);
29984 treemap.round = function(x) {
29985 return arguments.length ? (round = !!x, treemap) : round;
29988 treemap.size = function(x) {
29989 return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
29992 treemap.tile = function(x) {
29993 return arguments.length ? (tile = required(x), treemap) : tile;
29996 treemap.padding = function(x) {
29997 return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
30000 treemap.paddingInner = function(x) {
30001 return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$8(+x), treemap) : paddingInner;
30004 treemap.paddingOuter = function(x) {
30005 return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
30008 treemap.paddingTop = function(x) {
30009 return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$8(+x), treemap) : paddingTop;
30012 treemap.paddingRight = function(x) {
30013 return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$8(+x), treemap) : paddingRight;
30016 treemap.paddingBottom = function(x) {
30017 return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$8(+x), treemap) : paddingBottom;
30020 treemap.paddingLeft = function(x) {
30021 return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$8(+x), treemap) : paddingLeft;
30027 var binary = function(parent, x0, y0, x1, y1) {
30028 var nodes = parent.children,
30029 i, n = nodes.length,
30030 sum, sums = new Array(n + 1);
30032 for (sums[0] = sum = i = 0; i < n; ++i) {
30033 sums[i + 1] = sum += nodes[i].value;
30036 partition(0, n, parent.value, x0, y0, x1, y1);
30038 function partition(i, j, value, x0, y0, x1, y1) {
30040 var node = nodes[i];
30041 node.x0 = x0, node.y0 = y0;
30042 node.x1 = x1, node.y1 = y1;
30046 var valueOffset = sums[i],
30047 valueTarget = (value / 2) + valueOffset,
30052 var mid = k + hi >>> 1;
30053 if (sums[mid] < valueTarget) k = mid + 1;
30057 if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k;
30059 var valueLeft = sums[k] - valueOffset,
30060 valueRight = value - valueLeft;
30062 if ((x1 - x0) > (y1 - y0)) {
30063 var xk = (x0 * valueRight + x1 * valueLeft) / value;
30064 partition(i, k, valueLeft, x0, y0, xk, y1);
30065 partition(k, j, valueRight, xk, y0, x1, y1);
30067 var yk = (y0 * valueRight + y1 * valueLeft) / value;
30068 partition(i, k, valueLeft, x0, y0, x1, yk);
30069 partition(k, j, valueRight, x0, yk, x1, y1);
30074 var sliceDice = function(parent, x0, y0, x1, y1) {
30075 (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
30078 var resquarify = (function custom(ratio) {
30080 function resquarify(parent, x0, y0, x1, y1) {
30081 if ((rows = parent._squarify) && (rows.ratio === ratio)) {
30089 value = parent.value;
30092 row = rows[j], nodes = row.children;
30093 for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
30094 if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
30095 else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
30096 value -= row.value;
30099 parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
30100 rows.ratio = ratio;
30104 resquarify.ratio = function(x) {
30105 return custom((x = +x) > 1 ? x : 1);
30111 var d3polygonArea = function(polygon) {
30113 n = polygon.length,
30115 b = polygon[n - 1],
30121 area += a[1] * b[0] - a[0] * b[1];
30127 var d3polygonCentroid = function(polygon) {
30129 n = polygon.length,
30133 b = polygon[n - 1],
30140 k += c = a[0] * b[1] - b[0] * a[1];
30141 x += (a[0] + b[0]) * c;
30142 y += (a[1] + b[1]) * c;
30145 return k *= 3, [x / k, y / k];
30148 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
30149 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
30150 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
30151 // negative if clockwise, and zero if the points are collinear.
30152 var cross$1 = function(a, b, c) {
30153 return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
30156 function lexicographicOrder(a, b) {
30157 return a[0] - b[0] || a[1] - b[1];
30160 // Computes the upper convex hull per the monotone chain algorithm.
30161 // Assumes points.length >= 3, is sorted by x, unique in y.
30162 // Returns an array of indices into points in left-to-right order.
30163 function computeUpperHullIndexes(points) {
30164 var n = points.length,
30168 for (var i = 2; i < n; ++i) {
30169 while (size > 1 && cross$1(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size;
30170 indexes[size++] = i;
30173 return indexes.slice(0, size); // remove popped points
30176 var d3polygonHull = function(points) {
30177 if ((n = points.length) < 3) return null;
30181 sortedPoints = new Array(n),
30182 flippedPoints = new Array(n);
30184 for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i];
30185 sortedPoints.sort(lexicographicOrder);
30186 for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
30188 var upperIndexes = computeUpperHullIndexes(sortedPoints),
30189 lowerIndexes = computeUpperHullIndexes(flippedPoints);
30191 // Construct the hull polygon, removing possible duplicate endpoints.
30192 var skipLeft = lowerIndexes[0] === upperIndexes[0],
30193 skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
30196 // Add upper hull in right-to-l order.
30197 // Then add lower hull in left-to-right order.
30198 for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]);
30199 for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
30204 var contains$1 = function(polygon, point) {
30205 var n = polygon.length,
30206 p = polygon[n - 1],
30207 x = point[0], y = point[1],
30208 x0 = p[0], y0 = p[1],
30212 for (var i = 0; i < n; ++i) {
30213 p = polygon[i], x1 = p[0], y1 = p[1];
30214 if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside;
30221 var length$1 = function(polygon) {
30223 n = polygon.length,
30224 b = polygon[n - 1],
30239 perimeter += Math.sqrt(xa * xa + ya * ya);
30245 var slice$3 = [].slice;
30249 function Queue(size) {
30252 this._error = null;
30258 this._start = 0; // inside a synchronous task callback?
30261 Queue.prototype = queue.prototype = {
30262 constructor: Queue,
30263 defer: function(callback) {
30264 if (typeof callback !== "function") throw new Error("invalid callback");
30265 if (this._call) throw new Error("defer after await");
30266 if (this._error != null) return this;
30267 var t = slice$3.call(arguments, 1);
30269 ++this._waiting, this._tasks.push(t);
30273 abort: function() {
30274 if (this._error == null) abort(this, new Error("abort"));
30277 await: function(callback) {
30278 if (typeof callback !== "function") throw new Error("invalid callback");
30279 if (this._call) throw new Error("multiple await");
30280 this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
30284 awaitAll: function(callback) {
30285 if (typeof callback !== "function") throw new Error("invalid callback");
30286 if (this._call) throw new Error("multiple await");
30287 this._call = callback;
30293 function poke$1(q) {
30295 try { start$1(q); } // let the current task complete
30297 if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously
30298 else if (!q._data) throw e; // await callback errored synchronously
30303 function start$1(q) {
30304 while (q._start = q._waiting && q._active < q._size) {
30305 var i = q._ended + q._active,
30310 --q._waiting, ++q._active;
30311 t = c.apply(null, t);
30312 if (!q._tasks[i]) continue; // task finished synchronously
30313 q._tasks[i] = t || noabort;
30317 function end(q, i) {
30318 return function(e, r) {
30319 if (!q._tasks[i]) return; // ignore multiple callbacks
30320 --q._active, ++q._ended;
30321 q._tasks[i] = null;
30322 if (q._error != null) return; // ignore secondary errors
30327 if (q._waiting) poke$1(q);
30328 else maybeNotify(q);
30333 function abort(q, e) {
30334 var i = q._tasks.length, t;
30335 q._error = e; // ignore active callbacks
30336 q._data = undefined; // allow gc
30337 q._waiting = NaN; // prevent starting
30340 if (t = q._tasks[i]) {
30341 q._tasks[i] = null;
30344 catch (e) { /* ignore */ }
30349 q._active = NaN; // allow notification
30353 function maybeNotify(q) {
30354 if (!q._active && q._call) {
30356 q._data = undefined; // allow gc
30357 q._call(q._error, d);
30361 function queue(concurrency) {
30362 if (concurrency == null) concurrency = Infinity;
30363 else if (!((concurrency = +concurrency) >= 1)) throw new Error("invalid concurrency");
30364 return new Queue(concurrency);
30367 var defaultSource$1 = function() {
30368 return Math.random();
30371 var uniform = (function sourceRandomUniform(source) {
30372 function randomUniform(min, max) {
30373 min = min == null ? 0 : +min;
30374 max = max == null ? 1 : +max;
30375 if (arguments.length === 1) max = min, min = 0;
30377 return function() {
30378 return source() * max + min;
30382 randomUniform.source = sourceRandomUniform;
30384 return randomUniform;
30385 })(defaultSource$1);
30387 var normal = (function sourceRandomNormal(source) {
30388 function randomNormal(mu, sigma) {
30390 mu = mu == null ? 0 : +mu;
30391 sigma = sigma == null ? 1 : +sigma;
30392 return function() {
30395 // If available, use the second previously-generated uniform random.
30396 if (x != null) y = x, x = null;
30398 // Otherwise, generate a new x and y.
30400 x = source() * 2 - 1;
30401 y = source() * 2 - 1;
30403 } while (!r || r > 1);
30405 return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r);
30409 randomNormal.source = sourceRandomNormal;
30411 return randomNormal;
30412 })(defaultSource$1);
30414 var logNormal = (function sourceRandomLogNormal(source) {
30415 function randomLogNormal() {
30416 var randomNormal = normal.source(source).apply(this, arguments);
30417 return function() {
30418 return Math.exp(randomNormal());
30422 randomLogNormal.source = sourceRandomLogNormal;
30424 return randomLogNormal;
30425 })(defaultSource$1);
30427 var irwinHall = (function sourceRandomIrwinHall(source) {
30428 function randomIrwinHall(n) {
30429 return function() {
30430 for (var sum = 0, i = 0; i < n; ++i) sum += source();
30435 randomIrwinHall.source = sourceRandomIrwinHall;
30437 return randomIrwinHall;
30438 })(defaultSource$1);
30440 var bates = (function sourceRandomBates(source) {
30441 function randomBates(n) {
30442 var randomIrwinHall = irwinHall.source(source)(n);
30443 return function() {
30444 return randomIrwinHall() / n;
30448 randomBates.source = sourceRandomBates;
30450 return randomBates;
30451 })(defaultSource$1);
30453 var exponential$1 = (function sourceRandomExponential(source) {
30454 function randomExponential(lambda) {
30455 return function() {
30456 return -Math.log(1 - source()) / lambda;
30460 randomExponential.source = sourceRandomExponential;
30462 return randomExponential;
30463 })(defaultSource$1);
30465 var request = function(url, callback) {
30467 event = dispatch("beforesend", "progress", "load", "error"),
30470 xhr = new XMLHttpRequest,
30477 // If IE does not support CORS, use XDomainRequest.
30478 if (typeof XDomainRequest !== "undefined"
30479 && !("withCredentials" in xhr)
30480 && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest;
30483 ? xhr.onload = xhr.onerror = xhr.ontimeout = respond
30484 : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); };
30486 function respond(o) {
30487 var status = xhr.status, result;
30488 if (!status && hasResponse(xhr)
30489 || status >= 200 && status < 300
30490 || status === 304) {
30493 result = response.call(request, xhr);
30495 event.call("error", request, e);
30501 event.call("load", request, result);
30503 event.call("error", request, o);
30507 xhr.onprogress = function(e) {
30508 event.call("progress", request, e);
30512 header: function(name, value) {
30513 name = (name + "").toLowerCase();
30514 if (arguments.length < 2) return headers.get(name);
30515 if (value == null) headers.remove(name);
30516 else headers.set(name, value + "");
30520 // If mimeType is non-null and no Accept header is set, a default is used.
30521 mimeType: function(value) {
30522 if (!arguments.length) return mimeType;
30523 mimeType = value == null ? null : value + "";
30527 // Specifies what type the response value should take;
30528 // for instance, arraybuffer, blob, document, or text.
30529 responseType: function(value) {
30530 if (!arguments.length) return responseType;
30531 responseType = value;
30535 timeout: function(value) {
30536 if (!arguments.length) return timeout;
30541 user: function(value) {
30542 return arguments.length < 1 ? user : (user = value == null ? null : value + "", request);
30545 password: function(value) {
30546 return arguments.length < 1 ? password : (password = value == null ? null : value + "", request);
30549 // Specify how to convert the response content to a specific type;
30550 // changes the callback value on "load" events.
30551 response: function(value) {
30556 // Alias for send("GET", …).
30557 get: function(data, callback) {
30558 return request.send("GET", data, callback);
30561 // Alias for send("POST", …).
30562 post: function(data, callback) {
30563 return request.send("POST", data, callback);
30566 // If callback is non-null, it will be used for error and load events.
30567 send: function(method, data, callback) {
30568 xhr.open(method, url, true, user, password);
30569 if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*");
30570 if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); });
30571 if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType);
30572 if (responseType != null) xhr.responseType = responseType;
30573 if (timeout > 0) xhr.timeout = timeout;
30574 if (callback == null && typeof data === "function") callback = data, data = null;
30575 if (callback != null && callback.length === 1) callback = fixCallback(callback);
30576 if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); });
30577 event.call("beforesend", request, xhr);
30578 xhr.send(data == null ? null : data);
30582 abort: function() {
30588 var value = event.on.apply(event, arguments);
30589 return value === event ? request : value;
30593 if (callback != null) {
30594 if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
30595 return request.get(callback);
30601 function fixCallback(callback) {
30602 return function(error, xhr) {
30603 callback(error == null ? xhr : null);
30607 function hasResponse(xhr) {
30608 var type = xhr.responseType;
30609 return type && type !== "text"
30610 ? xhr.response // null on error
30611 : xhr.responseText; // "" on error
30614 var type$3 = function(defaultMimeType, response) {
30615 return function(url, callback) {
30616 var r = request(url).mimeType(defaultMimeType).response(response);
30617 if (callback != null) {
30618 if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
30619 return r.get(callback);
30625 var html = type$3("text/html", function(xhr) {
30626 return document.createRange().createContextualFragment(xhr.responseText);
30629 var json = type$3("application/json", function(xhr) {
30630 return JSON.parse(xhr.responseText);
30633 var text = type$3("text/plain", function(xhr) {
30634 return xhr.responseText;
30637 var xml = type$3("application/xml", function(xhr) {
30638 var xml = xhr.responseXML;
30639 if (!xml) throw new Error("parse error");
30643 var dsv$1 = function(defaultMimeType, parse) {
30644 return function(url, row, callback) {
30645 if (arguments.length < 3) callback = row, row = null;
30646 var r = request(url).mimeType(defaultMimeType);
30647 r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; };
30649 return callback ? r.get(callback) : r;
30653 function responseOf(parse, row) {
30654 return function(request$$1) {
30655 return parse(request$$1.responseText, row);
30659 var csv$1 = dsv$1("text/csv", csvParse);
30661 var tsv$1 = dsv$1("text/tab-separated-values", tsvParse);
30663 var array$2 = Array.prototype;
30665 var map$3 = array$2.map;
30666 var slice$4 = array$2.slice;
30668 var implicit = {name: "implicit"};
30670 function ordinal(range) {
30671 var index = map$1(),
30673 unknown = implicit;
30675 range = range == null ? [] : slice$4.call(range);
30677 function scale(d) {
30678 var key = d + "", i = index.get(key);
30680 if (unknown !== implicit) return unknown;
30681 index.set(key, i = domain.push(d));
30683 return range[(i - 1) % range.length];
30686 scale.domain = function(_) {
30687 if (!arguments.length) return domain.slice();
30688 domain = [], index = map$1();
30689 var i = -1, n = _.length, d, key;
30690 while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
30694 scale.range = function(_) {
30695 return arguments.length ? (range = slice$4.call(_), scale) : range.slice();
30698 scale.unknown = function(_) {
30699 return arguments.length ? (unknown = _, scale) : unknown;
30702 scale.copy = function() {
30713 var scale = ordinal().unknown(undefined),
30714 domain = scale.domain,
30715 ordinalRange = scale.range,
30724 delete scale.unknown;
30726 function rescale() {
30727 var n = domain().length,
30728 reverse = range[1] < range[0],
30729 start = range[reverse - 0],
30730 stop = range[1 - reverse];
30731 step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
30732 if (round) step = Math.floor(step);
30733 start += (stop - start - step * (n - paddingInner)) * align;
30734 bandwidth = step * (1 - paddingInner);
30735 if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
30736 var values = sequence(n).map(function(i) { return start + step * i; });
30737 return ordinalRange(reverse ? values.reverse() : values);
30740 scale.domain = function(_) {
30741 return arguments.length ? (domain(_), rescale()) : domain();
30744 scale.range = function(_) {
30745 return arguments.length ? (range = [+_[0], +_[1]], rescale()) : range.slice();
30748 scale.rangeRound = function(_) {
30749 return range = [+_[0], +_[1]], round = true, rescale();
30752 scale.bandwidth = function() {
30756 scale.step = function() {
30760 scale.round = function(_) {
30761 return arguments.length ? (round = !!_, rescale()) : round;
30764 scale.padding = function(_) {
30765 return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
30768 scale.paddingInner = function(_) {
30769 return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
30772 scale.paddingOuter = function(_) {
30773 return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter;
30776 scale.align = function(_) {
30777 return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
30780 scale.copy = function() {
30785 .paddingInner(paddingInner)
30786 .paddingOuter(paddingOuter)
30793 function pointish(scale) {
30794 var copy = scale.copy;
30796 scale.padding = scale.paddingOuter;
30797 delete scale.paddingInner;
30798 delete scale.paddingOuter;
30800 scale.copy = function() {
30801 return pointish(copy());
30807 function point$1() {
30808 return pointish(band().paddingInner(1));
30811 var constant$9 = function(x) {
30812 return function() {
30817 var number$1 = function(x) {
30823 function deinterpolateLinear(a, b) {
30824 return (b -= (a = +a))
30825 ? function(x) { return (x - a) / b; }
30829 function deinterpolateClamp(deinterpolate) {
30830 return function(a, b) {
30831 var d = deinterpolate(a = +a, b = +b);
30832 return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
30836 function reinterpolateClamp(reinterpolate$$1) {
30837 return function(a, b) {
30838 var r = reinterpolate$$1(a = +a, b = +b);
30839 return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
30843 function bimap(domain, range, deinterpolate, reinterpolate$$1) {
30844 var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1];
30845 if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate$$1(r1, r0);
30846 else d0 = deinterpolate(d0, d1), r0 = reinterpolate$$1(r0, r1);
30847 return function(x) { return r0(d0(x)); };
30850 function polymap(domain, range, deinterpolate, reinterpolate$$1) {
30851 var j = Math.min(domain.length, range.length) - 1,
30856 // Reverse descending domains.
30857 if (domain[j] < domain[0]) {
30858 domain = domain.slice().reverse();
30859 range = range.slice().reverse();
30863 d[i] = deinterpolate(domain[i], domain[i + 1]);
30864 r[i] = reinterpolate$$1(range[i], range[i + 1]);
30867 return function(x) {
30868 var i = bisectRight(domain, x, 1, j) - 1;
30869 return r[i](d[i](x));
30873 function copy(source, target) {
30875 .domain(source.domain())
30876 .range(source.range())
30877 .interpolate(source.interpolate())
30878 .clamp(source.clamp());
30881 // deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
30882 // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
30883 function continuous(deinterpolate, reinterpolate$$1) {
30886 interpolate = interpolateValue,
30892 function rescale() {
30893 piecewise = Math.min(domain.length, range.length) > 2 ? polymap : bimap;
30894 output = input = null;
30898 function scale(x) {
30899 return (output || (output = piecewise(domain, range, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate)))(+x);
30902 scale.invert = function(y) {
30903 return (input || (input = piecewise(range, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate$$1) : reinterpolate$$1)))(+y);
30906 scale.domain = function(_) {
30907 return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice();
30910 scale.range = function(_) {
30911 return arguments.length ? (range = slice$4.call(_), rescale()) : range.slice();
30914 scale.rangeRound = function(_) {
30915 return range = slice$4.call(_), interpolate = interpolateRound, rescale();
30918 scale.clamp = function(_) {
30919 return arguments.length ? (clamp = !!_, rescale()) : clamp;
30922 scale.interpolate = function(_) {
30923 return arguments.length ? (interpolate = _, rescale()) : interpolate;
30929 var tickFormat = function(domain, count, specifier) {
30930 var start = domain[0],
30931 stop = domain[domain.length - 1],
30932 step = tickStep(start, stop, count == null ? 10 : count),
30934 specifier = formatSpecifier(specifier == null ? ",f" : specifier);
30935 switch (specifier.type) {
30937 var value = Math.max(Math.abs(start), Math.abs(stop));
30938 if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
30939 return formatPrefix(specifier, value);
30946 if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
30951 if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
30955 return format(specifier);
30958 function linearish(scale) {
30959 var domain = scale.domain;
30961 scale.ticks = function(count) {
30963 return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
30966 scale.tickFormat = function(count, specifier) {
30967 return tickFormat(domain(), count, specifier);
30970 scale.nice = function(count) {
30971 if (count == null) count = 10;
30980 if (stop < start) {
30981 step = start, start = stop, stop = step;
30982 step = i0, i0 = i1, i1 = step;
30985 step = tickIncrement(start, stop, count);
30988 start = Math.floor(start / step) * step;
30989 stop = Math.ceil(stop / step) * step;
30990 step = tickIncrement(start, stop, count);
30991 } else if (step < 0) {
30992 start = Math.ceil(start * step) / step;
30993 stop = Math.floor(stop * step) / step;
30994 step = tickIncrement(start, stop, count);
30998 d[i0] = Math.floor(start / step) * step;
30999 d[i1] = Math.ceil(stop / step) * step;
31001 } else if (step < 0) {
31002 d[i0] = Math.ceil(start * step) / step;
31003 d[i1] = Math.floor(stop * step) / step;
31013 function linear$2() {
31014 var scale = continuous(deinterpolateLinear, reinterpolate);
31016 scale.copy = function() {
31017 return copy(scale, linear$2());
31020 return linearish(scale);
31023 function identity$6() {
31024 var domain = [0, 1];
31026 function scale(x) {
31030 scale.invert = scale;
31032 scale.domain = scale.range = function(_) {
31033 return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice();
31036 scale.copy = function() {
31037 return identity$6().domain(domain);
31040 return linearish(scale);
31043 var nice = function(domain, interval) {
31044 domain = domain.slice();
31047 i1 = domain.length - 1,
31053 t = i0, i0 = i1, i1 = t;
31054 t = x0, x0 = x1, x1 = t;
31057 domain[i0] = interval.floor(x0);
31058 domain[i1] = interval.ceil(x1);
31062 function deinterpolate(a, b) {
31063 return (b = Math.log(b / a))
31064 ? function(x) { return Math.log(x / a) / b; }
31068 function reinterpolate$1(a, b) {
31070 ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
31071 : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
31074 function pow10(x) {
31075 return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
31078 function powp(base) {
31079 return base === 10 ? pow10
31080 : base === Math.E ? Math.exp
31081 : function(x) { return Math.pow(base, x); };
31084 function logp(base) {
31085 return base === Math.E ? Math.log
31086 : base === 10 && Math.log10
31087 || base === 2 && Math.log2
31088 || (base = Math.log(base), function(x) { return Math.log(x) / base; });
31091 function reflect(f) {
31092 return function(x) {
31098 var scale = continuous(deinterpolate, reinterpolate$1).domain([1, 10]),
31099 domain = scale.domain,
31104 function rescale() {
31105 logs = logp(base), pows = powp(base);
31106 if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
31110 scale.base = function(_) {
31111 return arguments.length ? (base = +_, rescale()) : base;
31114 scale.domain = function(_) {
31115 return arguments.length ? (domain(_), rescale()) : domain();
31118 scale.ticks = function(count) {
31121 v = d[d.length - 1],
31124 if (r = v < u) i = u, u = v, v = i;
31131 n = count == null ? 10 : +count,
31134 if (!(base % 1) && j - i < n) {
31135 i = Math.round(i) - 1, j = Math.round(j) + 1;
31136 if (u > 0) for (; i < j; ++i) {
31137 for (k = 1, p = pows(i); k < base; ++k) {
31139 if (t < u) continue;
31143 } else for (; i < j; ++i) {
31144 for (k = base - 1, p = pows(i); k >= 1; --k) {
31146 if (t < u) continue;
31152 z = ticks(i, j, Math.min(j - i, n)).map(pows);
31155 return r ? z.reverse() : z;
31158 scale.tickFormat = function(count, specifier) {
31159 if (specifier == null) specifier = base === 10 ? ".0e" : ",";
31160 if (typeof specifier !== "function") specifier = format(specifier);
31161 if (count === Infinity) return specifier;
31162 if (count == null) count = 10;
31163 var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
31164 return function(d) {
31165 var i = d / pows(Math.round(logs(d)));
31166 if (i * base < base - 0.5) i *= base;
31167 return i <= k ? specifier(d) : "";
31171 scale.nice = function() {
31172 return domain(nice(domain(), {
31173 floor: function(x) { return pows(Math.floor(logs(x))); },
31174 ceil: function(x) { return pows(Math.ceil(logs(x))); }
31178 scale.copy = function() {
31179 return copy(scale, log$1().base(base));
31185 function raise$1(x, exponent) {
31186 return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
31191 scale = continuous(deinterpolate, reinterpolate),
31192 domain = scale.domain;
31194 function deinterpolate(a, b) {
31195 return (b = raise$1(b, exponent) - (a = raise$1(a, exponent)))
31196 ? function(x) { return (raise$1(x, exponent) - a) / b; }
31200 function reinterpolate(a, b) {
31201 b = raise$1(b, exponent) - (a = raise$1(a, exponent));
31202 return function(t) { return raise$1(a + b * t, 1 / exponent); };
31205 scale.exponent = function(_) {
31206 return arguments.length ? (exponent = +_, domain(domain())) : exponent;
31209 scale.copy = function() {
31210 return copy(scale, pow$1().exponent(exponent));
31213 return linearish(scale);
31216 function sqrt$1() {
31217 return pow$1().exponent(0.5);
31220 function quantile() {
31225 function rescale() {
31226 var i = 0, n = Math.max(1, range.length);
31227 thresholds = new Array(n - 1);
31228 while (++i < n) thresholds[i - 1] = threshold(domain, i / n);
31232 function scale(x) {
31233 if (!isNaN(x = +x)) return range[bisectRight(thresholds, x)];
31236 scale.invertExtent = function(y) {
31237 var i = range.indexOf(y);
31238 return i < 0 ? [NaN, NaN] : [
31239 i > 0 ? thresholds[i - 1] : domain[0],
31240 i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
31244 scale.domain = function(_) {
31245 if (!arguments.length) return domain.slice();
31247 for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
31248 domain.sort(ascending);
31252 scale.range = function(_) {
31253 return arguments.length ? (range = slice$4.call(_), rescale()) : range.slice();
31256 scale.quantiles = function() {
31257 return thresholds.slice();
31260 scale.copy = function() {
31269 function quantize$1() {
31276 function scale(x) {
31277 if (x <= x) return range[bisectRight(domain, x, 0, n)];
31280 function rescale() {
31282 domain = new Array(n);
31283 while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
31287 scale.domain = function(_) {
31288 return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
31291 scale.range = function(_) {
31292 return arguments.length ? (n = (range = slice$4.call(_)).length - 1, rescale()) : range.slice();
31295 scale.invertExtent = function(y) {
31296 var i = range.indexOf(y);
31297 return i < 0 ? [NaN, NaN]
31298 : i < 1 ? [x0, domain[0]]
31299 : i >= n ? [domain[n - 1], x1]
31300 : [domain[i - 1], domain[i]];
31303 scale.copy = function() {
31304 return quantize$1()
31309 return linearish(scale);
31312 function threshold$1() {
31313 var domain = [0.5],
31317 function scale(x) {
31318 if (x <= x) return range[bisectRight(domain, x, 0, n)];
31321 scale.domain = function(_) {
31322 return arguments.length ? (domain = slice$4.call(_), n = Math.min(domain.length, range.length - 1), scale) : domain.slice();
31325 scale.range = function(_) {
31326 return arguments.length ? (range = slice$4.call(_), n = Math.min(domain.length, range.length - 1), scale) : range.slice();
31329 scale.invertExtent = function(y) {
31330 var i = range.indexOf(y);
31331 return [domain[i - 1], domain[i]];
31334 scale.copy = function() {
31335 return threshold$1()
31343 var t0$1 = new Date;
31344 var t1$1 = new Date;
31346 function newInterval(floori, offseti, count, field) {
31348 function interval(date) {
31349 return floori(date = new Date(+date)), date;
31352 interval.floor = interval;
31354 interval.ceil = function(date) {
31355 return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
31358 interval.round = function(date) {
31359 var d0 = interval(date),
31360 d1 = interval.ceil(date);
31361 return date - d0 < d1 - date ? d0 : d1;
31364 interval.offset = function(date, step) {
31365 return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
31368 interval.range = function(start, stop, step) {
31370 start = interval.ceil(start);
31371 step = step == null ? 1 : Math.floor(step);
31372 if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
31373 do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop)
31377 interval.filter = function(test) {
31378 return newInterval(function(date) {
31379 if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
31380 }, function(date, step) {
31381 if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty
31386 interval.count = function(start, end) {
31387 t0$1.setTime(+start), t1$1.setTime(+end);
31388 floori(t0$1), floori(t1$1);
31389 return Math.floor(count(t0$1, t1$1));
31392 interval.every = function(step) {
31393 step = Math.floor(step);
31394 return !isFinite(step) || !(step > 0) ? null
31395 : !(step > 1) ? interval
31396 : interval.filter(field
31397 ? function(d) { return field(d) % step === 0; }
31398 : function(d) { return interval.count(0, d) % step === 0; });
31405 var millisecond = newInterval(function() {
31407 }, function(date, step) {
31408 date.setTime(+date + step);
31409 }, function(start, end) {
31410 return end - start;
31413 // An optimized implementation for this simple case.
31414 millisecond.every = function(k) {
31416 if (!isFinite(k) || !(k > 0)) return null;
31417 if (!(k > 1)) return millisecond;
31418 return newInterval(function(date) {
31419 date.setTime(Math.floor(date / k) * k);
31420 }, function(date, step) {
31421 date.setTime(+date + step * k);
31422 }, function(start, end) {
31423 return (end - start) / k;
31427 var milliseconds = millisecond.range;
31429 var durationSecond$1 = 1e3;
31430 var durationMinute$1 = 6e4;
31431 var durationHour$1 = 36e5;
31432 var durationDay$1 = 864e5;
31433 var durationWeek$1 = 6048e5;
31435 var second = newInterval(function(date) {
31436 date.setTime(Math.floor(date / durationSecond$1) * durationSecond$1);
31437 }, function(date, step) {
31438 date.setTime(+date + step * durationSecond$1);
31439 }, function(start, end) {
31440 return (end - start) / durationSecond$1;
31441 }, function(date) {
31442 return date.getUTCSeconds();
31445 var seconds = second.range;
31447 var minute = newInterval(function(date) {
31448 date.setTime(Math.floor(date / durationMinute$1) * durationMinute$1);
31449 }, function(date, step) {
31450 date.setTime(+date + step * durationMinute$1);
31451 }, function(start, end) {
31452 return (end - start) / durationMinute$1;
31453 }, function(date) {
31454 return date.getMinutes();
31457 var minutes = minute.range;
31459 var hour = newInterval(function(date) {
31460 var offset = date.getTimezoneOffset() * durationMinute$1 % durationHour$1;
31461 if (offset < 0) offset += durationHour$1;
31462 date.setTime(Math.floor((+date - offset) / durationHour$1) * durationHour$1 + offset);
31463 }, function(date, step) {
31464 date.setTime(+date + step * durationHour$1);
31465 }, function(start, end) {
31466 return (end - start) / durationHour$1;
31467 }, function(date) {
31468 return date.getHours();
31471 var hours = hour.range;
31473 var day = newInterval(function(date) {
31474 date.setHours(0, 0, 0, 0);
31475 }, function(date, step) {
31476 date.setDate(date.getDate() + step);
31477 }, function(start, end) {
31478 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationDay$1;
31479 }, function(date) {
31480 return date.getDate() - 1;
31483 var days = day.range;
31485 function weekday(i) {
31486 return newInterval(function(date) {
31487 date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
31488 date.setHours(0, 0, 0, 0);
31489 }, function(date, step) {
31490 date.setDate(date.getDate() + step * 7);
31491 }, function(start, end) {
31492 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationWeek$1;
31496 var sunday = weekday(0);
31497 var monday = weekday(1);
31498 var tuesday = weekday(2);
31499 var wednesday = weekday(3);
31500 var thursday = weekday(4);
31501 var friday = weekday(5);
31502 var saturday = weekday(6);
31504 var sundays = sunday.range;
31505 var mondays = monday.range;
31506 var tuesdays = tuesday.range;
31507 var wednesdays = wednesday.range;
31508 var thursdays = thursday.range;
31509 var fridays = friday.range;
31510 var saturdays = saturday.range;
31512 var month = newInterval(function(date) {
31514 date.setHours(0, 0, 0, 0);
31515 }, function(date, step) {
31516 date.setMonth(date.getMonth() + step);
31517 }, function(start, end) {
31518 return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
31519 }, function(date) {
31520 return date.getMonth();
31523 var months = month.range;
31525 var year = newInterval(function(date) {
31526 date.setMonth(0, 1);
31527 date.setHours(0, 0, 0, 0);
31528 }, function(date, step) {
31529 date.setFullYear(date.getFullYear() + step);
31530 }, function(start, end) {
31531 return end.getFullYear() - start.getFullYear();
31532 }, function(date) {
31533 return date.getFullYear();
31536 // An optimized implementation for this simple case.
31537 year.every = function(k) {
31538 return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
31539 date.setFullYear(Math.floor(date.getFullYear() / k) * k);
31540 date.setMonth(0, 1);
31541 date.setHours(0, 0, 0, 0);
31542 }, function(date, step) {
31543 date.setFullYear(date.getFullYear() + step * k);
31547 var years = year.range;
31549 var utcMinute = newInterval(function(date) {
31550 date.setUTCSeconds(0, 0);
31551 }, function(date, step) {
31552 date.setTime(+date + step * durationMinute$1);
31553 }, function(start, end) {
31554 return (end - start) / durationMinute$1;
31555 }, function(date) {
31556 return date.getUTCMinutes();
31559 var utcMinutes = utcMinute.range;
31561 var utcHour = newInterval(function(date) {
31562 date.setUTCMinutes(0, 0, 0);
31563 }, function(date, step) {
31564 date.setTime(+date + step * durationHour$1);
31565 }, function(start, end) {
31566 return (end - start) / durationHour$1;
31567 }, function(date) {
31568 return date.getUTCHours();
31571 var utcHours = utcHour.range;
31573 var utcDay = newInterval(function(date) {
31574 date.setUTCHours(0, 0, 0, 0);
31575 }, function(date, step) {
31576 date.setUTCDate(date.getUTCDate() + step);
31577 }, function(start, end) {
31578 return (end - start) / durationDay$1;
31579 }, function(date) {
31580 return date.getUTCDate() - 1;
31583 var utcDays = utcDay.range;
31585 function utcWeekday(i) {
31586 return newInterval(function(date) {
31587 date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
31588 date.setUTCHours(0, 0, 0, 0);
31589 }, function(date, step) {
31590 date.setUTCDate(date.getUTCDate() + step * 7);
31591 }, function(start, end) {
31592 return (end - start) / durationWeek$1;
31596 var utcSunday = utcWeekday(0);
31597 var utcMonday = utcWeekday(1);
31598 var utcTuesday = utcWeekday(2);
31599 var utcWednesday = utcWeekday(3);
31600 var utcThursday = utcWeekday(4);
31601 var utcFriday = utcWeekday(5);
31602 var utcSaturday = utcWeekday(6);
31604 var utcSundays = utcSunday.range;
31605 var utcMondays = utcMonday.range;
31606 var utcTuesdays = utcTuesday.range;
31607 var utcWednesdays = utcWednesday.range;
31608 var utcThursdays = utcThursday.range;
31609 var utcFridays = utcFriday.range;
31610 var utcSaturdays = utcSaturday.range;
31612 var utcMonth = newInterval(function(date) {
31613 date.setUTCDate(1);
31614 date.setUTCHours(0, 0, 0, 0);
31615 }, function(date, step) {
31616 date.setUTCMonth(date.getUTCMonth() + step);
31617 }, function(start, end) {
31618 return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
31619 }, function(date) {
31620 return date.getUTCMonth();
31623 var utcMonths = utcMonth.range;
31625 var utcYear = newInterval(function(date) {
31626 date.setUTCMonth(0, 1);
31627 date.setUTCHours(0, 0, 0, 0);
31628 }, function(date, step) {
31629 date.setUTCFullYear(date.getUTCFullYear() + step);
31630 }, function(start, end) {
31631 return end.getUTCFullYear() - start.getUTCFullYear();
31632 }, function(date) {
31633 return date.getUTCFullYear();
31636 // An optimized implementation for this simple case.
31637 utcYear.every = function(k) {
31638 return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
31639 date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
31640 date.setUTCMonth(0, 1);
31641 date.setUTCHours(0, 0, 0, 0);
31642 }, function(date, step) {
31643 date.setUTCFullYear(date.getUTCFullYear() + step * k);
31647 var utcYears = utcYear.range;
31649 function localDate(d) {
31650 if (0 <= d.y && d.y < 100) {
31651 var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
31652 date.setFullYear(d.y);
31655 return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
31658 function utcDate(d) {
31659 if (0 <= d.y && d.y < 100) {
31660 var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
31661 date.setUTCFullYear(d.y);
31664 return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
31667 function newYear(y) {
31668 return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
31671 function formatLocale$1(locale) {
31672 var locale_dateTime = locale.dateTime,
31673 locale_date = locale.date,
31674 locale_time = locale.time,
31675 locale_periods = locale.periods,
31676 locale_weekdays = locale.days,
31677 locale_shortWeekdays = locale.shortDays,
31678 locale_months = locale.months,
31679 locale_shortMonths = locale.shortMonths;
31681 var periodRe = formatRe(locale_periods),
31682 periodLookup = formatLookup(locale_periods),
31683 weekdayRe = formatRe(locale_weekdays),
31684 weekdayLookup = formatLookup(locale_weekdays),
31685 shortWeekdayRe = formatRe(locale_shortWeekdays),
31686 shortWeekdayLookup = formatLookup(locale_shortWeekdays),
31687 monthRe = formatRe(locale_months),
31688 monthLookup = formatLookup(locale_months),
31689 shortMonthRe = formatRe(locale_shortMonths),
31690 shortMonthLookup = formatLookup(locale_shortMonths);
31693 "a": formatShortWeekday,
31694 "A": formatWeekday,
31695 "b": formatShortMonth,
31698 "d": formatDayOfMonth,
31699 "e": formatDayOfMonth,
31702 "j": formatDayOfYear,
31703 "L": formatMilliseconds,
31704 "m": formatMonthNumber,
31705 "M": formatMinutes,
31707 "S": formatSeconds,
31708 "U": formatWeekNumberSunday,
31709 "w": formatWeekdayNumber,
31710 "W": formatWeekNumberMonday,
31714 "Y": formatFullYear,
31716 "%": formatLiteralPercent
31720 "a": formatUTCShortWeekday,
31721 "A": formatUTCWeekday,
31722 "b": formatUTCShortMonth,
31723 "B": formatUTCMonth,
31725 "d": formatUTCDayOfMonth,
31726 "e": formatUTCDayOfMonth,
31727 "H": formatUTCHour24,
31728 "I": formatUTCHour12,
31729 "j": formatUTCDayOfYear,
31730 "L": formatUTCMilliseconds,
31731 "m": formatUTCMonthNumber,
31732 "M": formatUTCMinutes,
31733 "p": formatUTCPeriod,
31734 "S": formatUTCSeconds,
31735 "U": formatUTCWeekNumberSunday,
31736 "w": formatUTCWeekdayNumber,
31737 "W": formatUTCWeekNumberMonday,
31740 "y": formatUTCYear,
31741 "Y": formatUTCFullYear,
31742 "Z": formatUTCZone,
31743 "%": formatLiteralPercent
31747 "a": parseShortWeekday,
31749 "b": parseShortMonth,
31751 "c": parseLocaleDateTime,
31752 "d": parseDayOfMonth,
31753 "e": parseDayOfMonth,
31756 "j": parseDayOfYear,
31757 "L": parseMilliseconds,
31758 "m": parseMonthNumber,
31762 "U": parseWeekNumberSunday,
31763 "w": parseWeekdayNumber,
31764 "W": parseWeekNumberMonday,
31765 "x": parseLocaleDate,
31766 "X": parseLocaleTime,
31768 "Y": parseFullYear,
31770 "%": parseLiteralPercent
31773 // These recursive directive definitions must be deferred.
31774 formats.x = newFormat(locale_date, formats);
31775 formats.X = newFormat(locale_time, formats);
31776 formats.c = newFormat(locale_dateTime, formats);
31777 utcFormats.x = newFormat(locale_date, utcFormats);
31778 utcFormats.X = newFormat(locale_time, utcFormats);
31779 utcFormats.c = newFormat(locale_dateTime, utcFormats);
31781 function newFormat(specifier, formats) {
31782 return function(date) {
31786 n = specifier.length,
31791 if (!(date instanceof Date)) date = new Date(+date);
31794 if (specifier.charCodeAt(i) === 37) {
31795 string.push(specifier.slice(j, i));
31796 if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
31797 else pad = c === "e" ? " " : "0";
31798 if (format = formats[c]) c = format(date, pad);
31804 string.push(specifier.slice(j, i));
31805 return string.join("");
31809 function newParse(specifier, newDate) {
31810 return function(string) {
31811 var d = newYear(1900),
31812 i = parseSpecifier(d, specifier, string += "", 0);
31813 if (i != string.length) return null;
31815 // The am-pm flag is 0 for AM, and 1 for PM.
31816 if ("p" in d) d.H = d.H % 12 + d.p * 12;
31818 // Convert day-of-week and week-of-year to day-of-year.
31819 if ("W" in d || "U" in d) {
31820 if (!("w" in d)) d.w = "W" in d ? 1 : 0;
31821 var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
31823 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;
31826 // If a time zone is specified, all fields are interpreted as UTC and then
31827 // offset according to the specified time zone.
31829 d.H += d.Z / 100 | 0;
31834 // Otherwise, all fields are in local time.
31839 function parseSpecifier(d, specifier, string, j) {
31841 n = specifier.length,
31847 if (j >= m) return -1;
31848 c = specifier.charCodeAt(i++);
31850 c = specifier.charAt(i++);
31851 parse = parses[c in pads ? specifier.charAt(i++) : c];
31852 if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
31853 } else if (c != string.charCodeAt(j++)) {
31861 function parsePeriod(d, string, i) {
31862 var n = periodRe.exec(string.slice(i));
31863 return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31866 function parseShortWeekday(d, string, i) {
31867 var n = shortWeekdayRe.exec(string.slice(i));
31868 return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31871 function parseWeekday(d, string, i) {
31872 var n = weekdayRe.exec(string.slice(i));
31873 return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31876 function parseShortMonth(d, string, i) {
31877 var n = shortMonthRe.exec(string.slice(i));
31878 return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31881 function parseMonth(d, string, i) {
31882 var n = monthRe.exec(string.slice(i));
31883 return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31886 function parseLocaleDateTime(d, string, i) {
31887 return parseSpecifier(d, locale_dateTime, string, i);
31890 function parseLocaleDate(d, string, i) {
31891 return parseSpecifier(d, locale_date, string, i);
31894 function parseLocaleTime(d, string, i) {
31895 return parseSpecifier(d, locale_time, string, i);
31898 function formatShortWeekday(d) {
31899 return locale_shortWeekdays[d.getDay()];
31902 function formatWeekday(d) {
31903 return locale_weekdays[d.getDay()];
31906 function formatShortMonth(d) {
31907 return locale_shortMonths[d.getMonth()];
31910 function formatMonth(d) {
31911 return locale_months[d.getMonth()];
31914 function formatPeriod(d) {
31915 return locale_periods[+(d.getHours() >= 12)];
31918 function formatUTCShortWeekday(d) {
31919 return locale_shortWeekdays[d.getUTCDay()];
31922 function formatUTCWeekday(d) {
31923 return locale_weekdays[d.getUTCDay()];
31926 function formatUTCShortMonth(d) {
31927 return locale_shortMonths[d.getUTCMonth()];
31930 function formatUTCMonth(d) {
31931 return locale_months[d.getUTCMonth()];
31934 function formatUTCPeriod(d) {
31935 return locale_periods[+(d.getUTCHours() >= 12)];
31939 format: function(specifier) {
31940 var f = newFormat(specifier += "", formats);
31941 f.toString = function() { return specifier; };
31944 parse: function(specifier) {
31945 var p = newParse(specifier += "", localDate);
31946 p.toString = function() { return specifier; };
31949 utcFormat: function(specifier) {
31950 var f = newFormat(specifier += "", utcFormats);
31951 f.toString = function() { return specifier; };
31954 utcParse: function(specifier) {
31955 var p = newParse(specifier, utcDate);
31956 p.toString = function() { return specifier; };
31962 var pads = {"-": "", "_": " ", "0": "0"};
31963 var numberRe = /^\s*\d+/;
31964 var percentRe = /^%/;
31965 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
31967 function pad(value, fill, width) {
31968 var sign = value < 0 ? "-" : "",
31969 string = (sign ? -value : value) + "",
31970 length = string.length;
31971 return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
31974 function requote(s) {
31975 return s.replace(requoteRe, "\\$&");
31978 function formatRe(names) {
31979 return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
31982 function formatLookup(names) {
31983 var map = {}, i = -1, n = names.length;
31984 while (++i < n) map[names[i].toLowerCase()] = i;
31988 function parseWeekdayNumber(d, string, i) {
31989 var n = numberRe.exec(string.slice(i, i + 1));
31990 return n ? (d.w = +n[0], i + n[0].length) : -1;
31993 function parseWeekNumberSunday(d, string, i) {
31994 var n = numberRe.exec(string.slice(i));
31995 return n ? (d.U = +n[0], i + n[0].length) : -1;
31998 function parseWeekNumberMonday(d, string, i) {
31999 var n = numberRe.exec(string.slice(i));
32000 return n ? (d.W = +n[0], i + n[0].length) : -1;
32003 function parseFullYear(d, string, i) {
32004 var n = numberRe.exec(string.slice(i, i + 4));
32005 return n ? (d.y = +n[0], i + n[0].length) : -1;
32008 function parseYear(d, string, i) {
32009 var n = numberRe.exec(string.slice(i, i + 2));
32010 return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
32013 function parseZone(d, string, i) {
32014 var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
32015 return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
32018 function parseMonthNumber(d, string, i) {
32019 var n = numberRe.exec(string.slice(i, i + 2));
32020 return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
32023 function parseDayOfMonth(d, string, i) {
32024 var n = numberRe.exec(string.slice(i, i + 2));
32025 return n ? (d.d = +n[0], i + n[0].length) : -1;
32028 function parseDayOfYear(d, string, i) {
32029 var n = numberRe.exec(string.slice(i, i + 3));
32030 return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
32033 function parseHour24(d, string, i) {
32034 var n = numberRe.exec(string.slice(i, i + 2));
32035 return n ? (d.H = +n[0], i + n[0].length) : -1;
32038 function parseMinutes(d, string, i) {
32039 var n = numberRe.exec(string.slice(i, i + 2));
32040 return n ? (d.M = +n[0], i + n[0].length) : -1;
32043 function parseSeconds(d, string, i) {
32044 var n = numberRe.exec(string.slice(i, i + 2));
32045 return n ? (d.S = +n[0], i + n[0].length) : -1;
32048 function parseMilliseconds(d, string, i) {
32049 var n = numberRe.exec(string.slice(i, i + 3));
32050 return n ? (d.L = +n[0], i + n[0].length) : -1;
32053 function parseLiteralPercent(d, string, i) {
32054 var n = percentRe.exec(string.slice(i, i + 1));
32055 return n ? i + n[0].length : -1;
32058 function formatDayOfMonth(d, p) {
32059 return pad(d.getDate(), p, 2);
32062 function formatHour24(d, p) {
32063 return pad(d.getHours(), p, 2);
32066 function formatHour12(d, p) {
32067 return pad(d.getHours() % 12 || 12, p, 2);
32070 function formatDayOfYear(d, p) {
32071 return pad(1 + day.count(year(d), d), p, 3);
32074 function formatMilliseconds(d, p) {
32075 return pad(d.getMilliseconds(), p, 3);
32078 function formatMonthNumber(d, p) {
32079 return pad(d.getMonth() + 1, p, 2);
32082 function formatMinutes(d, p) {
32083 return pad(d.getMinutes(), p, 2);
32086 function formatSeconds(d, p) {
32087 return pad(d.getSeconds(), p, 2);
32090 function formatWeekNumberSunday(d, p) {
32091 return pad(sunday.count(year(d), d), p, 2);
32094 function formatWeekdayNumber(d) {
32098 function formatWeekNumberMonday(d, p) {
32099 return pad(monday.count(year(d), d), p, 2);
32102 function formatYear(d, p) {
32103 return pad(d.getFullYear() % 100, p, 2);
32106 function formatFullYear(d, p) {
32107 return pad(d.getFullYear() % 10000, p, 4);
32110 function formatZone(d) {
32111 var z = d.getTimezoneOffset();
32112 return (z > 0 ? "-" : (z *= -1, "+"))
32113 + pad(z / 60 | 0, "0", 2)
32114 + pad(z % 60, "0", 2);
32117 function formatUTCDayOfMonth(d, p) {
32118 return pad(d.getUTCDate(), p, 2);
32121 function formatUTCHour24(d, p) {
32122 return pad(d.getUTCHours(), p, 2);
32125 function formatUTCHour12(d, p) {
32126 return pad(d.getUTCHours() % 12 || 12, p, 2);
32129 function formatUTCDayOfYear(d, p) {
32130 return pad(1 + utcDay.count(utcYear(d), d), p, 3);
32133 function formatUTCMilliseconds(d, p) {
32134 return pad(d.getUTCMilliseconds(), p, 3);
32137 function formatUTCMonthNumber(d, p) {
32138 return pad(d.getUTCMonth() + 1, p, 2);
32141 function formatUTCMinutes(d, p) {
32142 return pad(d.getUTCMinutes(), p, 2);
32145 function formatUTCSeconds(d, p) {
32146 return pad(d.getUTCSeconds(), p, 2);
32149 function formatUTCWeekNumberSunday(d, p) {
32150 return pad(utcSunday.count(utcYear(d), d), p, 2);
32153 function formatUTCWeekdayNumber(d) {
32154 return d.getUTCDay();
32157 function formatUTCWeekNumberMonday(d, p) {
32158 return pad(utcMonday.count(utcYear(d), d), p, 2);
32161 function formatUTCYear(d, p) {
32162 return pad(d.getUTCFullYear() % 100, p, 2);
32165 function formatUTCFullYear(d, p) {
32166 return pad(d.getUTCFullYear() % 10000, p, 4);
32169 function formatUTCZone() {
32173 function formatLiteralPercent() {
32184 dateTime: "%x, %X",
32185 date: "%-m/%-d/%Y",
32186 time: "%-I:%M:%S %p",
32187 periods: ["AM", "PM"],
32188 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
32189 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
32190 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
32191 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
32194 function defaultLocale$1(definition) {
32195 locale$2 = formatLocale$1(definition);
32196 timeFormat = locale$2.format;
32197 timeParse = locale$2.parse;
32198 utcFormat = locale$2.utcFormat;
32199 utcParse = locale$2.utcParse;
32203 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
32205 function formatIsoNative(date) {
32206 return date.toISOString();
32209 var formatIso = Date.prototype.toISOString
32211 : utcFormat(isoSpecifier);
32213 function parseIsoNative(string) {
32214 var date = new Date(string);
32215 return isNaN(date) ? null : date;
32218 var parseIso = +new Date("2000-01-01T00:00:00.000Z")
32220 : utcParse(isoSpecifier);
32222 var durationSecond = 1000;
32223 var durationMinute = durationSecond * 60;
32224 var durationHour = durationMinute * 60;
32225 var durationDay = durationHour * 24;
32226 var durationWeek = durationDay * 7;
32227 var durationMonth = durationDay * 30;
32228 var durationYear = durationDay * 365;
32230 function date$1(t) {
32231 return new Date(t);
32234 function number$2(t) {
32235 return t instanceof Date ? +t : +new Date(+t);
32238 function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) {
32239 var scale = continuous(deinterpolateLinear, reinterpolate),
32240 invert = scale.invert,
32241 domain = scale.domain;
32243 var formatMillisecond = format(".%L"),
32244 formatSecond = format(":%S"),
32245 formatMinute = format("%I:%M"),
32246 formatHour = format("%I %p"),
32247 formatDay = format("%a %d"),
32248 formatWeek = format("%b %d"),
32249 formatMonth = format("%B"),
32250 formatYear = format("%Y");
32252 var tickIntervals = [
32253 [second$$1, 1, durationSecond],
32254 [second$$1, 5, 5 * durationSecond],
32255 [second$$1, 15, 15 * durationSecond],
32256 [second$$1, 30, 30 * durationSecond],
32257 [minute$$1, 1, durationMinute],
32258 [minute$$1, 5, 5 * durationMinute],
32259 [minute$$1, 15, 15 * durationMinute],
32260 [minute$$1, 30, 30 * durationMinute],
32261 [ hour$$1, 1, durationHour ],
32262 [ hour$$1, 3, 3 * durationHour ],
32263 [ hour$$1, 6, 6 * durationHour ],
32264 [ hour$$1, 12, 12 * durationHour ],
32265 [ day$$1, 1, durationDay ],
32266 [ day$$1, 2, 2 * durationDay ],
32267 [ week, 1, durationWeek ],
32268 [ month$$1, 1, durationMonth ],
32269 [ month$$1, 3, 3 * durationMonth ],
32270 [ year$$1, 1, durationYear ]
32273 function tickFormat(date$$1) {
32274 return (second$$1(date$$1) < date$$1 ? formatMillisecond
32275 : minute$$1(date$$1) < date$$1 ? formatSecond
32276 : hour$$1(date$$1) < date$$1 ? formatMinute
32277 : day$$1(date$$1) < date$$1 ? formatHour
32278 : month$$1(date$$1) < date$$1 ? (week(date$$1) < date$$1 ? formatDay : formatWeek)
32279 : year$$1(date$$1) < date$$1 ? formatMonth
32280 : formatYear)(date$$1);
32283 function tickInterval(interval$$1, start, stop, step) {
32284 if (interval$$1 == null) interval$$1 = 10;
32286 // If a desired tick count is specified, pick a reasonable tick interval
32287 // based on the extent of the domain and a rough estimate of tick size.
32288 // Otherwise, assume interval is already a time interval and use it.
32289 if (typeof interval$$1 === "number") {
32290 var target = Math.abs(stop - start) / interval$$1,
32291 i = bisector(function(i) { return i[2]; }).right(tickIntervals, target);
32292 if (i === tickIntervals.length) {
32293 step = tickStep(start / durationYear, stop / durationYear, interval$$1);
32294 interval$$1 = year$$1;
32296 i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
32298 interval$$1 = i[0];
32300 step = tickStep(start, stop, interval$$1);
32301 interval$$1 = millisecond$$1;
32305 return step == null ? interval$$1 : interval$$1.every(step);
32308 scale.invert = function(y) {
32309 return new Date(invert(y));
32312 scale.domain = function(_) {
32313 return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1);
32316 scale.ticks = function(interval$$1, step) {
32319 t1 = d[d.length - 1],
32322 if (r) t = t0, t0 = t1, t1 = t;
32323 t = tickInterval(interval$$1, t0, t1, step);
32324 t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
32325 return r ? t.reverse() : t;
32328 scale.tickFormat = function(count, specifier) {
32329 return specifier == null ? tickFormat : format(specifier);
32332 scale.nice = function(interval$$1, step) {
32334 return (interval$$1 = tickInterval(interval$$1, d[0], d[d.length - 1], step))
32335 ? domain(nice(d, interval$$1))
32339 scale.copy = function() {
32340 return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format));
32346 var time = function() {
32347 return calendar(year, month, sunday, day, hour, minute, second, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]);
32350 var utcTime = function() {
32351 return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]);
32354 var colors = function(s) {
32355 return s.match(/.{6}/g).map(function(x) {
32360 var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf");
32362 var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6");
32364 var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9");
32366 var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5");
32368 var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0));
32370 var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
32372 var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
32374 var rainbow = cubehelix();
32376 var rainbow$1 = function(t) {
32377 if (t < 0 || t > 1) t -= Math.floor(t);
32378 var ts = Math.abs(t - 0.5);
32379 rainbow.h = 360 * t - 100;
32380 rainbow.s = 1.5 - 1.5 * ts;
32381 rainbow.l = 0.8 - 0.9 * ts;
32382 return rainbow + "";
32385 function ramp(range) {
32386 var n = range.length;
32387 return function(t) {
32388 return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];
32392 var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));
32394 var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf"));
32396 var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4"));
32398 var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));
32400 function sequential(interpolator) {
32405 function scale(x) {
32406 var t = (x - x0) / (x1 - x0);
32407 return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t);
32410 scale.domain = function(_) {
32411 return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1];
32414 scale.clamp = function(_) {
32415 return arguments.length ? (clamp = !!_, scale) : clamp;
32418 scale.interpolator = function(_) {
32419 return arguments.length ? (interpolator = _, scale) : interpolator;
32422 scale.copy = function() {
32423 return sequential(interpolator).domain([x0, x1]).clamp(clamp);
32426 return linearish(scale);
32429 var constant$10 = function(x) {
32430 return function constant() {
32435 var abs$1 = Math.abs;
32436 var atan2$1 = Math.atan2;
32437 var cos$2 = Math.cos;
32438 var max$2 = Math.max;
32439 var min$1 = Math.min;
32440 var sin$2 = Math.sin;
32441 var sqrt$2 = Math.sqrt;
32443 var epsilon$3 = 1e-12;
32444 var pi$4 = Math.PI;
32445 var halfPi$3 = pi$4 / 2;
32446 var tau$4 = 2 * pi$4;
32448 function acos$1(x) {
32449 return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x);
32452 function asin$1(x) {
32453 return x >= 1 ? halfPi$3 : x <= -1 ? -halfPi$3 : Math.asin(x);
32456 function arcInnerRadius(d) {
32457 return d.innerRadius;
32460 function arcOuterRadius(d) {
32461 return d.outerRadius;
32464 function arcStartAngle(d) {
32465 return d.startAngle;
32468 function arcEndAngle(d) {
32472 function arcPadAngle(d) {
32473 return d && d.padAngle; // Note: optional!
32476 function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
32477 var x10 = x1 - x0, y10 = y1 - y0,
32478 x32 = x3 - x2, y32 = y3 - y2,
32479 t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10);
32480 return [x0 + t * x10, y0 + t * y10];
32483 // Compute perpendicular offset line of length rc.
32484 // http://mathworld.wolfram.com/Circle-LineIntersection.html
32485 function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
32488 lo = (cw ? rc : -rc) / sqrt$2(x01 * x01 + y01 * y01),
32495 x00 = (x11 + x10) / 2,
32496 y00 = (y11 + y10) / 2,
32499 d2 = dx * dx + dy * dy,
32501 D = x11 * y10 - x10 * y11,
32502 d = (dy < 0 ? -1 : 1) * sqrt$2(max$2(0, r * r * d2 - D * D)),
32503 cx0 = (D * dy - dx * d) / d2,
32504 cy0 = (-D * dx - dy * d) / d2,
32505 cx1 = (D * dy + dx * d) / d2,
32506 cy1 = (-D * dx + dy * d) / d2,
32512 // Pick the closer of the two intersection points.
32513 // TODO Is there a faster way to determine which intersection to use?
32514 if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
32521 x11: cx0 * (r1 / r - 1),
32522 y11: cy0 * (r1 / r - 1)
32526 var arc = function() {
32527 var innerRadius = arcInnerRadius,
32528 outerRadius = arcOuterRadius,
32529 cornerRadius = constant$10(0),
32531 startAngle = arcStartAngle,
32532 endAngle = arcEndAngle,
32533 padAngle = arcPadAngle,
32539 r0 = +innerRadius.apply(this, arguments),
32540 r1 = +outerRadius.apply(this, arguments),
32541 a0 = startAngle.apply(this, arguments) - halfPi$3,
32542 a1 = endAngle.apply(this, arguments) - halfPi$3,
32543 da = abs$1(a1 - a0),
32546 if (!context) context = buffer = path();
32548 // Ensure that the outer radius is always larger than the inner radius.
32549 if (r1 < r0) r = r1, r1 = r0, r0 = r;
32552 if (!(r1 > epsilon$3)) context.moveTo(0, 0);
32554 // Or is it a circle or annulus?
32555 else if (da > tau$4 - epsilon$3) {
32556 context.moveTo(r1 * cos$2(a0), r1 * sin$2(a0));
32557 context.arc(0, 0, r1, a0, a1, !cw);
32558 if (r0 > epsilon$3) {
32559 context.moveTo(r0 * cos$2(a1), r0 * sin$2(a1));
32560 context.arc(0, 0, r0, a1, a0, cw);
32564 // Or is it a circular or annular sector?
32572 ap = padAngle.apply(this, arguments) / 2,
32573 rp = (ap > epsilon$3) && (padRadius ? +padRadius.apply(this, arguments) : sqrt$2(r0 * r0 + r1 * r1)),
32574 rc = min$1(abs$1(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
32580 // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
32581 if (rp > epsilon$3) {
32582 var p0 = asin$1(rp / r0 * sin$2(ap)),
32583 p1 = asin$1(rp / r1 * sin$2(ap));
32584 if ((da0 -= p0 * 2) > epsilon$3) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
32585 else da0 = 0, a00 = a10 = (a0 + a1) / 2;
32586 if ((da1 -= p1 * 2) > epsilon$3) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
32587 else da1 = 0, a01 = a11 = (a0 + a1) / 2;
32590 var x01 = r1 * cos$2(a01),
32591 y01 = r1 * sin$2(a01),
32592 x10 = r0 * cos$2(a10),
32593 y10 = r0 * sin$2(a10);
32595 // Apply rounded corners?
32596 if (rc > epsilon$3) {
32597 var x11 = r1 * cos$2(a11),
32598 y11 = r1 * sin$2(a11),
32599 x00 = r0 * cos$2(a00),
32600 y00 = r0 * sin$2(a00);
32602 // Restrict the corner radius according to the sector angle.
32604 var oc = da0 > epsilon$3 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10],
32609 kc = 1 / sin$2(acos$1((ax * bx + ay * by) / (sqrt$2(ax * ax + ay * ay) * sqrt$2(bx * bx + by * by))) / 2),
32610 lc = sqrt$2(oc[0] * oc[0] + oc[1] * oc[1]);
32611 rc0 = min$1(rc, (r0 - lc) / (kc - 1));
32612 rc1 = min$1(rc, (r1 - lc) / (kc + 1));
32616 // Is the sector collapsed to a line?
32617 if (!(da1 > epsilon$3)) context.moveTo(x01, y01);
32619 // Does the sector’s outer ring have rounded corners?
32620 else if (rc1 > epsilon$3) {
32621 t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
32622 t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
32624 context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
32626 // Have the corners merged?
32627 if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw);
32629 // Otherwise, draw the two corners and the ring.
32631 context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw);
32632 context.arc(0, 0, r1, atan2$1(t0.cy + t0.y11, t0.cx + t0.x11), atan2$1(t1.cy + t1.y11, t1.cx + t1.x11), !cw);
32633 context.arc(t1.cx, t1.cy, rc1, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw);
32637 // Or is the outer ring just a circular arc?
32638 else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
32640 // Is there no inner ring, and it’s a circular sector?
32641 // Or perhaps it’s an annular sector collapsed due to padding?
32642 if (!(r0 > epsilon$3) || !(da0 > epsilon$3)) context.lineTo(x10, y10);
32644 // Does the sector’s inner ring (or point) have rounded corners?
32645 else if (rc0 > epsilon$3) {
32646 t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
32647 t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
32649 context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
32651 // Have the corners merged?
32652 if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw);
32654 // Otherwise, draw the two corners and the ring.
32656 context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw);
32657 context.arc(0, 0, r0, atan2$1(t0.cy + t0.y11, t0.cx + t0.x11), atan2$1(t1.cy + t1.y11, t1.cx + t1.x11), cw);
32658 context.arc(t1.cx, t1.cy, rc0, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw);
32662 // Or is the inner ring just a circular arc?
32663 else context.arc(0, 0, r0, a10, a00, cw);
32666 context.closePath();
32668 if (buffer) return context = null, buffer + "" || null;
32671 arc.centroid = function() {
32672 var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
32673 a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$4 / 2;
32674 return [cos$2(a) * r, sin$2(a) * r];
32677 arc.innerRadius = function(_) {
32678 return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : innerRadius;
32681 arc.outerRadius = function(_) {
32682 return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : outerRadius;
32685 arc.cornerRadius = function(_) {
32686 return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : cornerRadius;
32689 arc.padRadius = function(_) {
32690 return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), arc) : padRadius;
32693 arc.startAngle = function(_) {
32694 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : startAngle;
32697 arc.endAngle = function(_) {
32698 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : endAngle;
32701 arc.padAngle = function(_) {
32702 return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : padAngle;
32705 arc.context = function(_) {
32706 return arguments.length ? ((context = _ == null ? null : _), arc) : context;
32712 function Linear(context) {
32713 this._context = context;
32716 Linear.prototype = {
32717 areaStart: function() {
32720 areaEnd: function() {
32723 lineStart: function() {
32726 lineEnd: function() {
32727 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
32728 this._line = 1 - this._line;
32730 point: function(x, y) {
32732 switch (this._point) {
32733 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
32734 case 1: this._point = 2; // proceed
32735 default: this._context.lineTo(x, y); break;
32740 var curveLinear = function(context) {
32741 return new Linear(context);
32752 var line = function() {
32755 defined = constant$10(true),
32757 curve = curveLinear,
32760 function line(data) {
32767 if (context == null) output = curve(buffer = path());
32769 for (i = 0; i <= n; ++i) {
32770 if (!(i < n && defined(d = data[i], i, data)) === defined0) {
32771 if (defined0 = !defined0) output.lineStart();
32772 else output.lineEnd();
32774 if (defined0) output.point(+x(d, i, data), +y(d, i, data));
32777 if (buffer) return output = null, buffer + "" || null;
32780 line.x = function(_) {
32781 return arguments.length ? (x = typeof _ === "function" ? _ : constant$10(+_), line) : x;
32784 line.y = function(_) {
32785 return arguments.length ? (y = typeof _ === "function" ? _ : constant$10(+_), line) : y;
32788 line.defined = function(_) {
32789 return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), line) : defined;
32792 line.curve = function(_) {
32793 return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
32796 line.context = function(_) {
32797 return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
32803 var area$1 = function() {
32806 y0 = constant$10(0),
32808 defined = constant$10(true),
32810 curve = curveLinear,
32813 function area(data) {
32821 x0z = new Array(n),
32822 y0z = new Array(n);
32824 if (context == null) output = curve(buffer = path());
32826 for (i = 0; i <= n; ++i) {
32827 if (!(i < n && defined(d = data[i], i, data)) === defined0) {
32828 if (defined0 = !defined0) {
32830 output.areaStart();
32831 output.lineStart();
32834 output.lineStart();
32835 for (k = i - 1; k >= j; --k) {
32836 output.point(x0z[k], y0z[k]);
32843 x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
32844 output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
32848 if (buffer) return output = null, buffer + "" || null;
32851 function arealine() {
32852 return line().defined(defined).curve(curve).context(context);
32855 area.x = function(_) {
32856 return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), x1 = null, area) : x0;
32859 area.x0 = function(_) {
32860 return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), area) : x0;
32863 area.x1 = function(_) {
32864 return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : x1;
32867 area.y = function(_) {
32868 return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), y1 = null, area) : y0;
32871 area.y0 = function(_) {
32872 return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), area) : y0;
32875 area.y1 = function(_) {
32876 return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : y1;
32880 area.lineY0 = function() {
32881 return arealine().x(x0).y(y0);
32884 area.lineY1 = function() {
32885 return arealine().x(x0).y(y1);
32888 area.lineX1 = function() {
32889 return arealine().x(x1).y(y0);
32892 area.defined = function(_) {
32893 return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), area) : defined;
32896 area.curve = function(_) {
32897 return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
32900 area.context = function(_) {
32901 return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
32907 var descending$1 = function(a, b) {
32908 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
32911 var identity$7 = function(d) {
32915 var pie = function() {
32916 var value = identity$7,
32917 sortValues = descending$1,
32919 startAngle = constant$10(0),
32920 endAngle = constant$10(tau$4),
32921 padAngle = constant$10(0);
32923 function pie(data) {
32929 index = new Array(n),
32930 arcs = new Array(n),
32931 a0 = +startAngle.apply(this, arguments),
32932 da = Math.min(tau$4, Math.max(-tau$4, endAngle.apply(this, arguments) - a0)),
32934 p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
32935 pa = p * (da < 0 ? -1 : 1),
32938 for (i = 0; i < n; ++i) {
32939 if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
32944 // Optionally sort the arcs by previously-computed values or by data.
32945 if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
32946 else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); });
32948 // Compute the arcs! They are stored in the original data's order.
32949 for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
32950 j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
32963 pie.value = function(_) {
32964 return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), pie) : value;
32967 pie.sortValues = function(_) {
32968 return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
32971 pie.sort = function(_) {
32972 return arguments.length ? (sort = _, sortValues = null, pie) : sort;
32975 pie.startAngle = function(_) {
32976 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : startAngle;
32979 pie.endAngle = function(_) {
32980 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : endAngle;
32983 pie.padAngle = function(_) {
32984 return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : padAngle;
32990 var curveRadialLinear = curveRadial(curveLinear);
32992 function Radial(curve) {
32993 this._curve = curve;
32996 Radial.prototype = {
32997 areaStart: function() {
32998 this._curve.areaStart();
33000 areaEnd: function() {
33001 this._curve.areaEnd();
33003 lineStart: function() {
33004 this._curve.lineStart();
33006 lineEnd: function() {
33007 this._curve.lineEnd();
33009 point: function(a, r) {
33010 this._curve.point(r * Math.sin(a), r * -Math.cos(a));
33014 function curveRadial(curve) {
33016 function radial(context) {
33017 return new Radial(curve(context));
33020 radial._curve = curve;
33025 function radialLine(l) {
33028 l.angle = l.x, delete l.x;
33029 l.radius = l.y, delete l.y;
33031 l.curve = function(_) {
33032 return arguments.length ? c(curveRadial(_)) : c()._curve;
33038 var radialLine$1 = function() {
33039 return radialLine(line().curve(curveRadialLinear));
33042 var radialArea = function() {
33043 var a = area$1().curve(curveRadialLinear),
33050 a.angle = a.x, delete a.x;
33051 a.startAngle = a.x0, delete a.x0;
33052 a.endAngle = a.x1, delete a.x1;
33053 a.radius = a.y, delete a.y;
33054 a.innerRadius = a.y0, delete a.y0;
33055 a.outerRadius = a.y1, delete a.y1;
33056 a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0;
33057 a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1;
33058 a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0;
33059 a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1;
33061 a.curve = function(_) {
33062 return arguments.length ? c(curveRadial(_)) : c()._curve;
33068 var slice$5 = Array.prototype.slice;
33070 var radialPoint = function(x, y) {
33071 return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
33074 function linkSource(d) {
33078 function linkTarget(d) {
33082 function link$2(curve) {
33083 var source = linkSource,
33084 target = linkTarget,
33090 var buffer, argv = slice$5.call(arguments), s = source.apply(this, argv), t = target.apply(this, argv);
33091 if (!context) context = buffer = path();
33092 curve(context, +x.apply(this, (argv[0] = s, argv)), +y.apply(this, argv), +x.apply(this, (argv[0] = t, argv)), +y.apply(this, argv));
33093 if (buffer) return context = null, buffer + "" || null;
33096 link.source = function(_) {
33097 return arguments.length ? (source = _, link) : source;
33100 link.target = function(_) {
33101 return arguments.length ? (target = _, link) : target;
33104 link.x = function(_) {
33105 return arguments.length ? (x = typeof _ === "function" ? _ : constant$10(+_), link) : x;
33108 link.y = function(_) {
33109 return arguments.length ? (y = typeof _ === "function" ? _ : constant$10(+_), link) : y;
33112 link.context = function(_) {
33113 return arguments.length ? ((context = _ == null ? null : _), link) : context;
33119 function curveHorizontal(context, x0, y0, x1, y1) {
33120 context.moveTo(x0, y0);
33121 context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1);
33124 function curveVertical(context, x0, y0, x1, y1) {
33125 context.moveTo(x0, y0);
33126 context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1);
33129 function curveRadial$1(context, x0, y0, x1, y1) {
33130 var p0 = radialPoint(x0, y0),
33131 p1 = radialPoint(x0, y0 = (y0 + y1) / 2),
33132 p2 = radialPoint(x1, y0),
33133 p3 = radialPoint(x1, y1);
33134 context.moveTo(p0[0], p0[1]);
33135 context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]);
33138 function linkHorizontal() {
33139 return link$2(curveHorizontal);
33142 function linkVertical() {
33143 return link$2(curveVertical);
33146 function linkRadial() {
33147 var l = link$2(curveRadial$1);
33148 l.angle = l.x, delete l.x;
33149 l.radius = l.y, delete l.y;
33154 draw: function(context, size) {
33155 var r = Math.sqrt(size / pi$4);
33156 context.moveTo(r, 0);
33157 context.arc(0, 0, r, 0, tau$4);
33162 draw: function(context, size) {
33163 var r = Math.sqrt(size / 5) / 2;
33164 context.moveTo(-3 * r, -r);
33165 context.lineTo(-r, -r);
33166 context.lineTo(-r, -3 * r);
33167 context.lineTo(r, -3 * r);
33168 context.lineTo(r, -r);
33169 context.lineTo(3 * r, -r);
33170 context.lineTo(3 * r, r);
33171 context.lineTo(r, r);
33172 context.lineTo(r, 3 * r);
33173 context.lineTo(-r, 3 * r);
33174 context.lineTo(-r, r);
33175 context.lineTo(-3 * r, r);
33176 context.closePath();
33180 var tan30 = Math.sqrt(1 / 3);
33181 var tan30_2 = tan30 * 2;
33184 draw: function(context, size) {
33185 var y = Math.sqrt(size / tan30_2),
33187 context.moveTo(0, -y);
33188 context.lineTo(x, 0);
33189 context.lineTo(0, y);
33190 context.lineTo(-x, 0);
33191 context.closePath();
33195 var ka = 0.89081309152928522810;
33196 var kr = Math.sin(pi$4 / 10) / Math.sin(7 * pi$4 / 10);
33197 var kx = Math.sin(tau$4 / 10) * kr;
33198 var ky = -Math.cos(tau$4 / 10) * kr;
33201 draw: function(context, size) {
33202 var r = Math.sqrt(size * ka),
33205 context.moveTo(0, -r);
33206 context.lineTo(x, y);
33207 for (var i = 1; i < 5; ++i) {
33208 var a = tau$4 * i / 5,
33211 context.lineTo(s * r, -c * r);
33212 context.lineTo(c * x - s * y, s * x + c * y);
33214 context.closePath();
33219 draw: function(context, size) {
33220 var w = Math.sqrt(size),
33222 context.rect(x, x, w, w);
33226 var sqrt3 = Math.sqrt(3);
33229 draw: function(context, size) {
33230 var y = -Math.sqrt(size / (sqrt3 * 3));
33231 context.moveTo(0, y * 2);
33232 context.lineTo(-sqrt3 * y, -y);
33233 context.lineTo(sqrt3 * y, -y);
33234 context.closePath();
33239 var s = Math.sqrt(3) / 2;
33240 var k = 1 / Math.sqrt(12);
33241 var a = (k / 2 + 1) * 3;
33244 draw: function(context, size) {
33245 var r = Math.sqrt(size / a),
33252 context.moveTo(x0, y0);
33253 context.lineTo(x1, y1);
33254 context.lineTo(x2, y2);
33255 context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
33256 context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
33257 context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
33258 context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
33259 context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
33260 context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
33261 context.closePath();
33275 var symbol = function() {
33276 var type = constant$10(circle$2),
33277 size = constant$10(64),
33280 function symbol() {
33282 if (!context) context = buffer = path();
33283 type.apply(this, arguments).draw(context, +size.apply(this, arguments));
33284 if (buffer) return context = null, buffer + "" || null;
33287 symbol.type = function(_) {
33288 return arguments.length ? (type = typeof _ === "function" ? _ : constant$10(_), symbol) : type;
33291 symbol.size = function(_) {
33292 return arguments.length ? (size = typeof _ === "function" ? _ : constant$10(+_), symbol) : size;
33295 symbol.context = function(_) {
33296 return arguments.length ? (context = _ == null ? null : _, symbol) : context;
33302 var noop$2 = function() {};
33304 function point$2(that, x, y) {
33305 that._context.bezierCurveTo(
33306 (2 * that._x0 + that._x1) / 3,
33307 (2 * that._y0 + that._y1) / 3,
33308 (that._x0 + 2 * that._x1) / 3,
33309 (that._y0 + 2 * that._y1) / 3,
33310 (that._x0 + 4 * that._x1 + x) / 6,
33311 (that._y0 + 4 * that._y1 + y) / 6
33315 function Basis(context) {
33316 this._context = context;
33319 Basis.prototype = {
33320 areaStart: function() {
33323 areaEnd: function() {
33326 lineStart: function() {
33327 this._x0 = this._x1 =
33328 this._y0 = this._y1 = NaN;
33331 lineEnd: function() {
33332 switch (this._point) {
33333 case 3: point$2(this, this._x1, this._y1); // proceed
33334 case 2: this._context.lineTo(this._x1, this._y1); break;
33336 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33337 this._line = 1 - this._line;
33339 point: function(x, y) {
33341 switch (this._point) {
33342 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33343 case 1: this._point = 2; break;
33344 case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed
33345 default: point$2(this, x, y); break;
33347 this._x0 = this._x1, this._x1 = x;
33348 this._y0 = this._y1, this._y1 = y;
33352 var basis$2 = function(context) {
33353 return new Basis(context);
33356 function BasisClosed(context) {
33357 this._context = context;
33360 BasisClosed.prototype = {
33363 lineStart: function() {
33364 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
33365 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
33368 lineEnd: function() {
33369 switch (this._point) {
33371 this._context.moveTo(this._x2, this._y2);
33372 this._context.closePath();
33376 this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
33377 this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
33378 this._context.closePath();
33382 this.point(this._x2, this._y2);
33383 this.point(this._x3, this._y3);
33384 this.point(this._x4, this._y4);
33389 point: function(x, y) {
33391 switch (this._point) {
33392 case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
33393 case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
33394 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;
33395 default: point$2(this, x, y); break;
33397 this._x0 = this._x1, this._x1 = x;
33398 this._y0 = this._y1, this._y1 = y;
33402 var basisClosed$1 = function(context) {
33403 return new BasisClosed(context);
33406 function BasisOpen(context) {
33407 this._context = context;
33410 BasisOpen.prototype = {
33411 areaStart: function() {
33414 areaEnd: function() {
33417 lineStart: function() {
33418 this._x0 = this._x1 =
33419 this._y0 = this._y1 = NaN;
33422 lineEnd: function() {
33423 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33424 this._line = 1 - this._line;
33426 point: function(x, y) {
33428 switch (this._point) {
33429 case 0: this._point = 1; break;
33430 case 1: this._point = 2; break;
33431 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;
33432 case 3: this._point = 4; // proceed
33433 default: point$2(this, x, y); break;
33435 this._x0 = this._x1, this._x1 = x;
33436 this._y0 = this._y1, this._y1 = y;
33440 var basisOpen = function(context) {
33441 return new BasisOpen(context);
33444 function Bundle(context, beta) {
33445 this._basis = new Basis(context);
33449 Bundle.prototype = {
33450 lineStart: function() {
33453 this._basis.lineStart();
33455 lineEnd: function() {
33471 this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
33472 this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
33477 this._x = this._y = null;
33478 this._basis.lineEnd();
33480 point: function(x, y) {
33486 var bundle = (function custom(beta) {
33488 function bundle(context) {
33489 return beta === 1 ? new Basis(context) : new Bundle(context, beta);
33492 bundle.beta = function(beta) {
33493 return custom(+beta);
33499 function point$3(that, x, y) {
33500 that._context.bezierCurveTo(
33501 that._x1 + that._k * (that._x2 - that._x0),
33502 that._y1 + that._k * (that._y2 - that._y0),
33503 that._x2 + that._k * (that._x1 - x),
33504 that._y2 + that._k * (that._y1 - y),
33510 function Cardinal(context, tension) {
33511 this._context = context;
33512 this._k = (1 - tension) / 6;
33515 Cardinal.prototype = {
33516 areaStart: function() {
33519 areaEnd: function() {
33522 lineStart: function() {
33523 this._x0 = this._x1 = this._x2 =
33524 this._y0 = this._y1 = this._y2 = NaN;
33527 lineEnd: function() {
33528 switch (this._point) {
33529 case 2: this._context.lineTo(this._x2, this._y2); break;
33530 case 3: point$3(this, this._x1, this._y1); break;
33532 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33533 this._line = 1 - this._line;
33535 point: function(x, y) {
33537 switch (this._point) {
33538 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33539 case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
33540 case 2: this._point = 3; // proceed
33541 default: point$3(this, x, y); break;
33543 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33544 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33548 var cardinal = (function custom(tension) {
33550 function cardinal(context) {
33551 return new Cardinal(context, tension);
33554 cardinal.tension = function(tension) {
33555 return custom(+tension);
33561 function CardinalClosed(context, tension) {
33562 this._context = context;
33563 this._k = (1 - tension) / 6;
33566 CardinalClosed.prototype = {
33569 lineStart: function() {
33570 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
33571 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
33574 lineEnd: function() {
33575 switch (this._point) {
33577 this._context.moveTo(this._x3, this._y3);
33578 this._context.closePath();
33582 this._context.lineTo(this._x3, this._y3);
33583 this._context.closePath();
33587 this.point(this._x3, this._y3);
33588 this.point(this._x4, this._y4);
33589 this.point(this._x5, this._y5);
33594 point: function(x, y) {
33596 switch (this._point) {
33597 case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
33598 case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
33599 case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
33600 default: point$3(this, x, y); break;
33602 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33603 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33607 var cardinalClosed = (function custom(tension) {
33609 function cardinal$$1(context) {
33610 return new CardinalClosed(context, tension);
33613 cardinal$$1.tension = function(tension) {
33614 return custom(+tension);
33617 return cardinal$$1;
33620 function CardinalOpen(context, tension) {
33621 this._context = context;
33622 this._k = (1 - tension) / 6;
33625 CardinalOpen.prototype = {
33626 areaStart: function() {
33629 areaEnd: function() {
33632 lineStart: function() {
33633 this._x0 = this._x1 = this._x2 =
33634 this._y0 = this._y1 = this._y2 = NaN;
33637 lineEnd: function() {
33638 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33639 this._line = 1 - this._line;
33641 point: function(x, y) {
33643 switch (this._point) {
33644 case 0: this._point = 1; break;
33645 case 1: this._point = 2; break;
33646 case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
33647 case 3: this._point = 4; // proceed
33648 default: point$3(this, x, y); break;
33650 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33651 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33655 var cardinalOpen = (function custom(tension) {
33657 function cardinal$$1(context) {
33658 return new CardinalOpen(context, tension);
33661 cardinal$$1.tension = function(tension) {
33662 return custom(+tension);
33665 return cardinal$$1;
33668 function point$4(that, x, y) {
33674 if (that._l01_a > epsilon$3) {
33675 var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
33676 n = 3 * that._l01_a * (that._l01_a + that._l12_a);
33677 x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
33678 y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
33681 if (that._l23_a > epsilon$3) {
33682 var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
33683 m = 3 * that._l23_a * (that._l23_a + that._l12_a);
33684 x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
33685 y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
33688 that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
33691 function CatmullRom(context, alpha) {
33692 this._context = context;
33693 this._alpha = alpha;
33696 CatmullRom.prototype = {
33697 areaStart: function() {
33700 areaEnd: function() {
33703 lineStart: function() {
33704 this._x0 = this._x1 = this._x2 =
33705 this._y0 = this._y1 = this._y2 = NaN;
33706 this._l01_a = this._l12_a = this._l23_a =
33707 this._l01_2a = this._l12_2a = this._l23_2a =
33710 lineEnd: function() {
33711 switch (this._point) {
33712 case 2: this._context.lineTo(this._x2, this._y2); break;
33713 case 3: this.point(this._x2, this._y2); break;
33715 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33716 this._line = 1 - this._line;
33718 point: function(x, y) {
33722 var x23 = this._x2 - x,
33723 y23 = this._y2 - y;
33724 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33727 switch (this._point) {
33728 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33729 case 1: this._point = 2; break;
33730 case 2: this._point = 3; // proceed
33731 default: point$4(this, x, y); break;
33734 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33735 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33736 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33737 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33741 var catmullRom = (function custom(alpha) {
33743 function catmullRom(context) {
33744 return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
33747 catmullRom.alpha = function(alpha) {
33748 return custom(+alpha);
33754 function CatmullRomClosed(context, alpha) {
33755 this._context = context;
33756 this._alpha = alpha;
33759 CatmullRomClosed.prototype = {
33762 lineStart: function() {
33763 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
33764 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
33765 this._l01_a = this._l12_a = this._l23_a =
33766 this._l01_2a = this._l12_2a = this._l23_2a =
33769 lineEnd: function() {
33770 switch (this._point) {
33772 this._context.moveTo(this._x3, this._y3);
33773 this._context.closePath();
33777 this._context.lineTo(this._x3, this._y3);
33778 this._context.closePath();
33782 this.point(this._x3, this._y3);
33783 this.point(this._x4, this._y4);
33784 this.point(this._x5, this._y5);
33789 point: function(x, y) {
33793 var x23 = this._x2 - x,
33794 y23 = this._y2 - y;
33795 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33798 switch (this._point) {
33799 case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
33800 case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
33801 case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
33802 default: point$4(this, x, y); break;
33805 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33806 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33807 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33808 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33812 var catmullRomClosed = (function custom(alpha) {
33814 function catmullRom$$1(context) {
33815 return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
33818 catmullRom$$1.alpha = function(alpha) {
33819 return custom(+alpha);
33822 return catmullRom$$1;
33825 function CatmullRomOpen(context, alpha) {
33826 this._context = context;
33827 this._alpha = alpha;
33830 CatmullRomOpen.prototype = {
33831 areaStart: function() {
33834 areaEnd: function() {
33837 lineStart: function() {
33838 this._x0 = this._x1 = this._x2 =
33839 this._y0 = this._y1 = this._y2 = NaN;
33840 this._l01_a = this._l12_a = this._l23_a =
33841 this._l01_2a = this._l12_2a = this._l23_2a =
33844 lineEnd: function() {
33845 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33846 this._line = 1 - this._line;
33848 point: function(x, y) {
33852 var x23 = this._x2 - x,
33853 y23 = this._y2 - y;
33854 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33857 switch (this._point) {
33858 case 0: this._point = 1; break;
33859 case 1: this._point = 2; break;
33860 case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
33861 case 3: this._point = 4; // proceed
33862 default: point$4(this, x, y); break;
33865 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33866 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33867 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33868 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33872 var catmullRomOpen = (function custom(alpha) {
33874 function catmullRom$$1(context) {
33875 return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
33878 catmullRom$$1.alpha = function(alpha) {
33879 return custom(+alpha);
33882 return catmullRom$$1;
33885 function LinearClosed(context) {
33886 this._context = context;
33889 LinearClosed.prototype = {
33892 lineStart: function() {
33895 lineEnd: function() {
33896 if (this._point) this._context.closePath();
33898 point: function(x, y) {
33900 if (this._point) this._context.lineTo(x, y);
33901 else this._point = 1, this._context.moveTo(x, y);
33905 var linearClosed = function(context) {
33906 return new LinearClosed(context);
33909 function sign$1(x) {
33910 return x < 0 ? -1 : 1;
33913 // Calculate the slopes of the tangents (Hermite-type interpolation) based on
33914 // the following paper: Steffen, M. 1990. A Simple Method for Monotonic
33915 // Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
33916 // NOV(II), P. 443, 1990.
33917 function slope3(that, x2, y2) {
33918 var h0 = that._x1 - that._x0,
33919 h1 = x2 - that._x1,
33920 s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
33921 s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
33922 p = (s0 * h1 + s1 * h0) / (h0 + h1);
33923 return (sign$1(s0) + sign$1(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
33926 // Calculate a one-sided slope.
33927 function slope2(that, t) {
33928 var h = that._x1 - that._x0;
33929 return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
33932 // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
33933 // "you can express cubic Hermite interpolation in terms of cubic Bézier curves
33934 // with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
33935 function point$5(that, t0, t1) {
33940 dx = (x1 - x0) / 3;
33941 that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
33944 function MonotoneX(context) {
33945 this._context = context;
33948 MonotoneX.prototype = {
33949 areaStart: function() {
33952 areaEnd: function() {
33955 lineStart: function() {
33956 this._x0 = this._x1 =
33957 this._y0 = this._y1 =
33961 lineEnd: function() {
33962 switch (this._point) {
33963 case 2: this._context.lineTo(this._x1, this._y1); break;
33964 case 3: point$5(this, this._t0, slope2(this, this._t0)); break;
33966 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33967 this._line = 1 - this._line;
33969 point: function(x, y) {
33973 if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
33974 switch (this._point) {
33975 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33976 case 1: this._point = 2; break;
33977 case 2: this._point = 3; point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
33978 default: point$5(this, this._t0, t1 = slope3(this, x, y)); break;
33981 this._x0 = this._x1, this._x1 = x;
33982 this._y0 = this._y1, this._y1 = y;
33987 function MonotoneY(context) {
33988 this._context = new ReflectContext(context);
33991 (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
33992 MonotoneX.prototype.point.call(this, y, x);
33995 function ReflectContext(context) {
33996 this._context = context;
33999 ReflectContext.prototype = {
34000 moveTo: function(x, y) { this._context.moveTo(y, x); },
34001 closePath: function() { this._context.closePath(); },
34002 lineTo: function(x, y) { this._context.lineTo(y, x); },
34003 bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
34006 function monotoneX(context) {
34007 return new MonotoneX(context);
34010 function monotoneY(context) {
34011 return new MonotoneY(context);
34014 function Natural(context) {
34015 this._context = context;
34018 Natural.prototype = {
34019 areaStart: function() {
34022 areaEnd: function() {
34025 lineStart: function() {
34029 lineEnd: function() {
34035 this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
34037 this._context.lineTo(x[1], y[1]);
34039 var px = controlPoints(x),
34040 py = controlPoints(y);
34041 for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
34042 this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
34047 if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
34048 this._line = 1 - this._line;
34049 this._x = this._y = null;
34051 point: function(x, y) {
34057 // See https://www.particleincell.com/2012/bezier-splines/ for derivation.
34058 function controlPoints(x) {
34065 a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
34066 for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
34067 a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
34068 for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
34069 a[n - 1] = r[n - 1] / b[n - 1];
34070 for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
34071 b[n - 1] = (x[n] + a[n - 1]) / 2;
34072 for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
34076 var natural = function(context) {
34077 return new Natural(context);
34080 function Step(context, t) {
34081 this._context = context;
34086 areaStart: function() {
34089 areaEnd: function() {
34092 lineStart: function() {
34093 this._x = this._y = NaN;
34096 lineEnd: function() {
34097 if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
34098 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
34099 if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
34101 point: function(x, y) {
34103 switch (this._point) {
34104 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
34105 case 1: this._point = 2; // proceed
34107 if (this._t <= 0) {
34108 this._context.lineTo(this._x, y);
34109 this._context.lineTo(x, y);
34111 var x1 = this._x * (1 - this._t) + x * this._t;
34112 this._context.lineTo(x1, this._y);
34113 this._context.lineTo(x1, y);
34118 this._x = x, this._y = y;
34122 var step = function(context) {
34123 return new Step(context, 0.5);
34126 function stepBefore(context) {
34127 return new Step(context, 0);
34130 function stepAfter(context) {
34131 return new Step(context, 1);
34134 var none$1 = function(series, order) {
34135 if (!((n = series.length) > 1)) return;
34136 for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
34137 s0 = s1, s1 = series[order[i]];
34138 for (j = 0; j < m; ++j) {
34139 s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
34144 var none$2 = function(series) {
34145 var n = series.length, o = new Array(n);
34146 while (--n >= 0) o[n] = n;
34150 function stackValue(d, key) {
34154 var stack = function() {
34155 var keys = constant$10([]),
34158 value = stackValue;
34160 function stack(data) {
34161 var kz = keys.apply(this, arguments),
34168 for (i = 0; i < n; ++i) {
34169 for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
34170 si[j] = sij = [0, +value(data[j], ki, j, data)];
34171 sij.data = data[j];
34176 for (i = 0, oz = order(sz); i < n; ++i) {
34177 sz[oz[i]].index = i;
34184 stack.keys = function(_) {
34185 return arguments.length ? (keys = typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : keys;
34188 stack.value = function(_) {
34189 return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), stack) : value;
34192 stack.order = function(_) {
34193 return arguments.length ? (order = _ == null ? none$2 : typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : order;
34196 stack.offset = function(_) {
34197 return arguments.length ? (offset = _ == null ? none$1 : _, stack) : offset;
34203 var expand = function(series, order) {
34204 if (!((n = series.length) > 0)) return;
34205 for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
34206 for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0;
34207 if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y;
34209 none$1(series, order);
34212 var diverging = function(series, order) {
34213 if (!((n = series.length) > 1)) return;
34214 for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) {
34215 for (yp = yn = 0, i = 0; i < n; ++i) {
34216 if ((dy = (d = series[order[i]][j])[1] - d[0]) >= 0) {
34217 d[0] = yp, d[1] = yp += dy;
34218 } else if (dy < 0) {
34219 d[1] = yn, d[0] = yn += dy;
34227 var silhouette = function(series, order) {
34228 if (!((n = series.length) > 0)) return;
34229 for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
34230 for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0;
34231 s0[j][1] += s0[j][0] = -y / 2;
34233 none$1(series, order);
34236 var wiggle = function(series, order) {
34237 if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
34238 for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
34239 for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
34240 var si = series[order[i]],
34241 sij0 = si[j][1] || 0,
34242 sij1 = si[j - 1][1] || 0,
34243 s3 = (sij0 - sij1) / 2;
34244 for (var k = 0; k < i; ++k) {
34245 var sk = series[order[k]],
34246 skj0 = sk[j][1] || 0,
34247 skj1 = sk[j - 1][1] || 0;
34250 s1 += sij0, s2 += s3 * sij0;
34252 s0[j - 1][1] += s0[j - 1][0] = y;
34253 if (s1) y -= s2 / s1;
34255 s0[j - 1][1] += s0[j - 1][0] = y;
34256 none$1(series, order);
34259 var ascending$2 = function(series) {
34260 var sums = series.map(sum$2);
34261 return none$2(series).sort(function(a, b) { return sums[a] - sums[b]; });
34264 function sum$2(series) {
34265 var s = 0, i = -1, n = series.length, v;
34266 while (++i < n) if (v = +series[i][1]) s += v;
34270 var descending$2 = function(series) {
34271 return ascending$2(series).reverse();
34274 var insideOut = function(series) {
34275 var n = series.length,
34278 sums = series.map(sum$2),
34279 order = none$2(series).sort(function(a, b) { return sums[b] - sums[a]; }),
34285 for (i = 0; i < n; ++i) {
34287 if (top < bottom) {
34296 return bottoms.reverse().concat(tops);
34299 var reverse = function(series) {
34300 return none$2(series).reverse();
34303 var constant$11 = function(x) {
34304 return function() {
34317 function RedBlackTree() {
34318 this._ = null; // root node
34321 function RedBlackNode(node) {
34322 node.U = // parent node
34323 node.C = // color - true for red, false for black
34324 node.L = // left node
34325 node.R = // right node
34326 node.P = // previous node
34327 node.N = null; // next node
34330 RedBlackTree.prototype = {
34331 constructor: RedBlackTree,
34333 insert: function(after, node) {
34334 var parent, grandpa, uncle;
34339 if (after.N) after.N.P = node;
34343 while (after.L) after = after.L;
34349 } else if (this._) {
34350 after = RedBlackFirst(this._);
34353 after.P = after.L = node;
34356 node.P = node.N = null;
34360 node.L = node.R = null;
34365 while (parent && parent.C) {
34366 grandpa = parent.U;
34367 if (parent === grandpa.L) {
34369 if (uncle && uncle.C) {
34370 parent.C = uncle.C = false;
34374 if (after === parent.R) {
34375 RedBlackRotateLeft(this, parent);
34381 RedBlackRotateRight(this, grandpa);
34385 if (uncle && uncle.C) {
34386 parent.C = uncle.C = false;
34390 if (after === parent.L) {
34391 RedBlackRotateRight(this, parent);
34397 RedBlackRotateLeft(this, grandpa);
34405 remove: function(node) {
34406 if (node.N) node.N.P = node.P;
34407 if (node.P) node.P.N = node.N;
34408 node.N = node.P = null;
34410 var parent = node.U,
34417 if (!left) next = right;
34418 else if (!right) next = left;
34419 else next = RedBlackFirst(right);
34422 if (parent.L === node) parent.L = next;
34423 else parent.R = next;
34428 if (left && right) {
34433 if (next !== right) {
34450 if (node) node.U = parent;
34452 if (node && node.C) { node.C = false; return; }
34455 if (node === this._) break;
34456 if (node === parent.L) {
34457 sibling = parent.R;
34461 RedBlackRotateLeft(this, parent);
34462 sibling = parent.R;
34464 if ((sibling.L && sibling.L.C)
34465 || (sibling.R && sibling.R.C)) {
34466 if (!sibling.R || !sibling.R.C) {
34467 sibling.L.C = false;
34469 RedBlackRotateRight(this, sibling);
34470 sibling = parent.R;
34472 sibling.C = parent.C;
34473 parent.C = sibling.R.C = false;
34474 RedBlackRotateLeft(this, parent);
34479 sibling = parent.L;
34483 RedBlackRotateRight(this, parent);
34484 sibling = parent.L;
34486 if ((sibling.L && sibling.L.C)
34487 || (sibling.R && sibling.R.C)) {
34488 if (!sibling.L || !sibling.L.C) {
34489 sibling.R.C = false;
34491 RedBlackRotateLeft(this, sibling);
34492 sibling = parent.L;
34494 sibling.C = parent.C;
34495 parent.C = sibling.L.C = false;
34496 RedBlackRotateRight(this, parent);
34506 if (node) node.C = false;
34510 function RedBlackRotateLeft(tree, node) {
34516 if (parent.L === p) parent.L = q;
34525 if (p.R) p.R.U = p;
34529 function RedBlackRotateRight(tree, node) {
34535 if (parent.L === p) parent.L = q;
34544 if (p.L) p.L.U = p;
34548 function RedBlackFirst(node) {
34549 while (node.L) node = node.L;
34553 function createEdge(left, right, v0, v1) {
34554 var edge = [null, null],
34555 index = edges.push(edge) - 1;
34557 edge.right = right;
34558 if (v0) setEdgeEnd(edge, left, right, v0);
34559 if (v1) setEdgeEnd(edge, right, left, v1);
34560 cells[left.index].halfedges.push(index);
34561 cells[right.index].halfedges.push(index);
34565 function createBorderEdge(left, v0, v1) {
34566 var edge = [v0, v1];
34571 function setEdgeEnd(edge, left, right, vertex) {
34572 if (!edge[0] && !edge[1]) {
34575 edge.right = right;
34576 } else if (edge.left === right) {
34583 // Liang–Barsky line clipping.
34584 function clipEdge(edge, x0, y0, x1, y1) {
34598 if (!dx && r > 0) return;
34601 if (r < t0) return;
34602 if (r < t1) t1 = r;
34603 } else if (dx > 0) {
34604 if (r > t1) return;
34605 if (r > t0) t0 = r;
34609 if (!dx && r < 0) return;
34612 if (r > t1) return;
34613 if (r > t0) t0 = r;
34614 } else if (dx > 0) {
34615 if (r < t0) return;
34616 if (r < t1) t1 = r;
34620 if (!dy && r > 0) return;
34623 if (r < t0) return;
34624 if (r < t1) t1 = r;
34625 } else if (dy > 0) {
34626 if (r > t1) return;
34627 if (r > t0) t0 = r;
34631 if (!dy && r < 0) return;
34634 if (r > t1) return;
34635 if (r > t0) t0 = r;
34636 } else if (dy > 0) {
34637 if (r < t0) return;
34638 if (r < t1) t1 = r;
34641 if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
34643 if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
34644 if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
34648 function connectEdge(edge, x0, y0, x1, y1) {
34650 if (v1) return true;
34654 right = edge.right,
34659 fx = (lx + rx) / 2,
34660 fy = (ly + ry) / 2,
34665 if (fx < x0 || fx >= x1) return;
34667 if (!v0) v0 = [fx, y0];
34668 else if (v0[1] >= y1) return;
34671 if (!v0) v0 = [fx, y1];
34672 else if (v0[1] < y0) return;
34676 fm = (lx - rx) / (ry - ly);
34678 if (fm < -1 || fm > 1) {
34680 if (!v0) v0 = [(y0 - fb) / fm, y0];
34681 else if (v0[1] >= y1) return;
34682 v1 = [(y1 - fb) / fm, y1];
34684 if (!v0) v0 = [(y1 - fb) / fm, y1];
34685 else if (v0[1] < y0) return;
34686 v1 = [(y0 - fb) / fm, y0];
34690 if (!v0) v0 = [x0, fm * x0 + fb];
34691 else if (v0[0] >= x1) return;
34692 v1 = [x1, fm * x1 + fb];
34694 if (!v0) v0 = [x1, fm * x1 + fb];
34695 else if (v0[0] < x0) return;
34696 v1 = [x0, fm * x0 + fb];
34706 function clipEdges(x0, y0, x1, y1) {
34707 var i = edges.length,
34711 if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
34712 || !clipEdge(edge, x0, y0, x1, y1)
34713 || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$4
34714 || Math.abs(edge[0][1] - edge[1][1]) > epsilon$4)) {
34720 function createCell(site) {
34721 return cells[site.index] = {
34727 function cellHalfedgeAngle(cell, edge) {
34728 var site = cell.site,
34731 if (site === vb) vb = va, va = site;
34732 if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
34733 if (site === va) va = edge[1], vb = edge[0];
34734 else va = edge[0], vb = edge[1];
34735 return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
34738 function cellHalfedgeStart(cell, edge) {
34739 return edge[+(edge.left !== cell.site)];
34742 function cellHalfedgeEnd(cell, edge) {
34743 return edge[+(edge.left === cell.site)];
34746 function sortCellHalfedges() {
34747 for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
34748 if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
34749 var index = new Array(m),
34750 array = new Array(m);
34751 for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
34752 index.sort(function(i, j) { return array[j] - array[i]; });
34753 for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
34754 for (j = 0; j < m; ++j) halfedges[j] = array[j];
34759 function clipCells(x0, y0, x1, y1) {
34760 var nCells = cells.length,
34775 for (iCell = 0; iCell < nCells; ++iCell) {
34776 if (cell = cells[iCell]) {
34778 halfedges = cell.halfedges;
34779 iHalfedge = halfedges.length;
34781 // Remove any dangling clipped edges.
34782 while (iHalfedge--) {
34783 if (!edges[halfedges[iHalfedge]]) {
34784 halfedges.splice(iHalfedge, 1);
34788 // Insert any border edges as necessary.
34789 iHalfedge = 0, nHalfedges = halfedges.length;
34790 while (iHalfedge < nHalfedges) {
34791 end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
34792 start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
34793 if (Math.abs(endX - startX) > epsilon$4 || Math.abs(endY - startY) > epsilon$4) {
34794 halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
34795 Math.abs(endX - x0) < epsilon$4 && y1 - endY > epsilon$4 ? [x0, Math.abs(startX - x0) < epsilon$4 ? startY : y1]
34796 : Math.abs(endY - y1) < epsilon$4 && x1 - endX > epsilon$4 ? [Math.abs(startY - y1) < epsilon$4 ? startX : x1, y1]
34797 : Math.abs(endX - x1) < epsilon$4 && endY - y0 > epsilon$4 ? [x1, Math.abs(startX - x1) < epsilon$4 ? startY : y0]
34798 : Math.abs(endY - y0) < epsilon$4 && endX - x0 > epsilon$4 ? [Math.abs(startY - y0) < epsilon$4 ? startX : x0, y0]
34804 if (nHalfedges) cover = false;
34808 // If there weren’t any edges, have the closest site cover the extent.
34809 // It doesn’t matter which corner of the extent we measure!
34811 var dx, dy, d2, dc = Infinity;
34813 for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
34814 if (cell = cells[iCell]) {
34818 d2 = dx * dx + dy * dy;
34819 if (d2 < dc) dc = d2, cover = cell;
34824 var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
34825 cover.halfedges.push(
34826 edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
34827 edges.push(createBorderEdge(site, v01, v11)) - 1,
34828 edges.push(createBorderEdge(site, v11, v10)) - 1,
34829 edges.push(createBorderEdge(site, v10, v00)) - 1
34834 // Lastly delete any cells with no edges; these were entirely clipped.
34835 for (iCell = 0; iCell < nCells; ++iCell) {
34836 if (cell = cells[iCell]) {
34837 if (!cell.halfedges.length) {
34838 delete cells[iCell];
34844 var circlePool = [];
34848 function Circle() {
34849 RedBlackNode(this);
34857 function attachCircle(arc) {
34861 if (!lArc || !rArc) return;
34863 var lSite = lArc.site,
34867 if (lSite === rSite) return;
34871 ax = lSite[0] - bx,
34872 ay = lSite[1] - by,
34873 cx = rSite[0] - bx,
34874 cy = rSite[1] - by;
34876 var d = 2 * (ax * cy - ay * cx);
34877 if (d >= -epsilon2$2) return;
34879 var ha = ax * ax + ay * ay,
34880 hc = cx * cx + cy * cy,
34881 x = (cy * ha - ay * hc) / d,
34882 y = (ax * hc - cx * ha) / d;
34884 var circle = circlePool.pop() || new Circle;
34886 circle.site = cSite;
34888 circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
34890 arc.circle = circle;
34896 if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
34897 if (node.L) node = node.L;
34898 else { before = node.P; break; }
34900 if (node.R) node = node.R;
34901 else { before = node; break; }
34905 circles.insert(before, circle);
34906 if (!before) firstCircle = circle;
34909 function detachCircle(arc) {
34910 var circle = arc.circle;
34912 if (!circle.P) firstCircle = circle.N;
34913 circles.remove(circle);
34914 circlePool.push(circle);
34915 RedBlackNode(circle);
34920 var beachPool = [];
34923 RedBlackNode(this);
34926 this.circle = null;
34929 function createBeach(site) {
34930 var beach = beachPool.pop() || new Beach;
34935 function detachBeach(beach) {
34936 detachCircle(beach);
34937 beaches.remove(beach);
34938 beachPool.push(beach);
34939 RedBlackNode(beach);
34942 function removeBeach(beach) {
34943 var circle = beach.circle,
34947 previous = beach.P,
34949 disappearing = [beach];
34951 detachBeach(beach);
34953 var lArc = previous;
34955 && Math.abs(x - lArc.circle.x) < epsilon$4
34956 && Math.abs(y - lArc.circle.cy) < epsilon$4) {
34958 disappearing.unshift(lArc);
34963 disappearing.unshift(lArc);
34964 detachCircle(lArc);
34968 && Math.abs(x - rArc.circle.x) < epsilon$4
34969 && Math.abs(y - rArc.circle.cy) < epsilon$4) {
34971 disappearing.push(rArc);
34976 disappearing.push(rArc);
34977 detachCircle(rArc);
34979 var nArcs = disappearing.length,
34981 for (iArc = 1; iArc < nArcs; ++iArc) {
34982 rArc = disappearing[iArc];
34983 lArc = disappearing[iArc - 1];
34984 setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
34987 lArc = disappearing[0];
34988 rArc = disappearing[nArcs - 1];
34989 rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
34991 attachCircle(lArc);
34992 attachCircle(rArc);
34995 function addBeach(site) {
34997 directrix = site[1],
35005 dxl = leftBreakPoint(node, directrix) - x;
35006 if (dxl > epsilon$4) node = node.L; else {
35007 dxr = x - rightBreakPoint(node, directrix);
35008 if (dxr > epsilon$4) {
35015 if (dxl > -epsilon$4) {
35018 } else if (dxr > -epsilon$4) {
35022 lArc = rArc = node;
35030 var newArc = createBeach(site);
35031 beaches.insert(lArc, newArc);
35033 if (!lArc && !rArc) return;
35035 if (lArc === rArc) {
35036 detachCircle(lArc);
35037 rArc = createBeach(lArc.site);
35038 beaches.insert(newArc, rArc);
35039 newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
35040 attachCircle(lArc);
35041 attachCircle(rArc);
35045 if (!rArc) { // && lArc
35046 newArc.edge = createEdge(lArc.site, newArc.site);
35050 // else lArc !== rArc
35051 detachCircle(lArc);
35052 detachCircle(rArc);
35054 var lSite = lArc.site,
35060 cx = rSite[0] - ax,
35061 cy = rSite[1] - ay,
35062 d = 2 * (bx * cy - by * cx),
35063 hb = bx * bx + by * by,
35064 hc = cx * cx + cy * cy,
35065 vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
35067 setEdgeEnd(rArc.edge, lSite, rSite, vertex);
35068 newArc.edge = createEdge(lSite, site, null, vertex);
35069 rArc.edge = createEdge(site, rSite, null, vertex);
35070 attachCircle(lArc);
35071 attachCircle(rArc);
35074 function leftBreakPoint(arc, directrix) {
35075 var site = arc.site,
35078 pby2 = rfocy - directrix;
35080 if (!pby2) return rfocx;
35083 if (!lArc) return -Infinity;
35086 var lfocx = site[0],
35088 plby2 = lfocy - directrix;
35090 if (!plby2) return lfocx;
35092 var hl = lfocx - rfocx,
35093 aby2 = 1 / pby2 - 1 / plby2,
35096 if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
35098 return (rfocx + lfocx) / 2;
35101 function rightBreakPoint(arc, directrix) {
35103 if (rArc) return leftBreakPoint(rArc, directrix);
35104 var site = arc.site;
35105 return site[1] === directrix ? site[0] : Infinity;
35108 var epsilon$4 = 1e-6;
35109 var epsilon2$2 = 1e-12;
35115 function triangleArea(a, b, c) {
35116 return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
35119 function lexicographic(a, b) {
35124 function Diagram(sites, extent) {
35125 var site = sites.sort(lexicographic).pop(),
35131 cells = new Array(sites.length);
35132 beaches = new RedBlackTree;
35133 circles = new RedBlackTree;
35136 circle = firstCircle;
35137 if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
35138 if (site[0] !== x || site[1] !== y) {
35140 x = site[0], y = site[1];
35142 site = sites.pop();
35143 } else if (circle) {
35144 removeBeach(circle.arc);
35150 sortCellHalfedges();
35153 var x0 = +extent[0][0],
35154 y0 = +extent[0][1],
35155 x1 = +extent[1][0],
35156 y1 = +extent[1][1];
35157 clipEdges(x0, y0, x1, y1);
35158 clipCells(x0, y0, x1, y1);
35161 this.edges = edges;
35162 this.cells = cells;
35170 Diagram.prototype = {
35171 constructor: Diagram,
35173 polygons: function() {
35174 var edges = this.edges;
35176 return this.cells.map(function(cell) {
35177 var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); });
35178 polygon.data = cell.site.data;
35183 triangles: function() {
35184 var triangles = [],
35185 edges = this.edges;
35187 this.cells.forEach(function(cell, i) {
35188 if (!(m = (halfedges = cell.halfedges).length)) return;
35189 var site = cell.site,
35194 e1 = edges[halfedges[m - 1]],
35195 s1 = e1.left === site ? e1.right : e1.left;
35199 e1 = edges[halfedges[j]];
35200 s1 = e1.left === site ? e1.right : e1.left;
35201 if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
35202 triangles.push([site.data, s0.data, s1.data]);
35210 links: function() {
35211 return this.edges.filter(function(edge) {
35213 }).map(function(edge) {
35215 source: edge.left.data,
35216 target: edge.right.data
35221 find: function(x, y, radius) {
35222 var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell;
35224 // Use the previously-found cell, or start with an arbitrary one.
35225 while (!(cell = that.cells[i1])) if (++i1 >= n) return null;
35226 var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy;
35228 // Traverse the half-edges to find a closer cell, if any.
35230 cell = that.cells[i0 = i1], i1 = null;
35231 cell.halfedges.forEach(function(e) {
35232 var edge = that.edges[e], v = edge.left;
35233 if ((v === cell.site || !v) && !(v = edge.right)) return;
35234 var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy;
35235 if (v2 < d2) d2 = v2, i1 = v.index;
35237 } while (i1 !== null);
35241 return radius == null || d2 <= radius * radius ? cell.site : null;
35245 var voronoi = function() {
35250 function voronoi(data) {
35251 return new Diagram(data.map(function(d, i) {
35252 var s = [Math.round(x(d, i, data) / epsilon$4) * epsilon$4, Math.round(y(d, i, data) / epsilon$4) * epsilon$4];
35259 voronoi.polygons = function(data) {
35260 return voronoi(data).polygons();
35263 voronoi.links = function(data) {
35264 return voronoi(data).links();
35267 voronoi.triangles = function(data) {
35268 return voronoi(data).triangles();
35271 voronoi.x = function(_) {
35272 return arguments.length ? (x = typeof _ === "function" ? _ : constant$11(+_), voronoi) : x;
35275 voronoi.y = function(_) {
35276 return arguments.length ? (y = typeof _ === "function" ? _ : constant$11(+_), voronoi) : y;
35279 voronoi.extent = function(_) {
35280 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]]];
35283 voronoi.size = function(_) {
35284 return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]];
35290 var constant$12 = function(x) {
35291 return function() {
35296 function ZoomEvent(target, type, transform) {
35297 this.target = target;
35299 this.transform = transform;
35302 function Transform(k, x, y) {
35308 Transform.prototype = {
35309 constructor: Transform,
35310 scale: function(k) {
35311 return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
35313 translate: function(x, y) {
35314 return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
35316 apply: function(point) {
35317 return [point[0] * this.k + this.x, point[1] * this.k + this.y];
35319 applyX: function(x) {
35320 return x * this.k + this.x;
35322 applyY: function(y) {
35323 return y * this.k + this.y;
35325 invert: function(location) {
35326 return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
35328 invertX: function(x) {
35329 return (x - this.x) / this.k;
35331 invertY: function(y) {
35332 return (y - this.y) / this.k;
35334 rescaleX: function(x) {
35335 return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
35337 rescaleY: function(y) {
35338 return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
35340 toString: function() {
35341 return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
35345 var identity$8 = new Transform(1, 0, 0);
35347 transform$1.prototype = Transform.prototype;
35349 function transform$1(node) {
35350 return node.__zoom || identity$8;
35353 function nopropagation$2() {
35354 event.stopImmediatePropagation();
35357 var noevent$2 = function() {
35358 event.preventDefault();
35359 event.stopImmediatePropagation();
35362 // Ignore right-click, since that should open the context menu.
35363 function defaultFilter$2() {
35364 return !event.button;
35367 function defaultExtent$1() {
35368 var e = this, w, h;
35369 if (e instanceof SVGElement) {
35370 e = e.ownerSVGElement || e;
35371 w = e.width.baseVal.value;
35372 h = e.height.baseVal.value;
35375 h = e.clientHeight;
35377 return [[0, 0], [w, h]];
35380 function defaultTransform() {
35381 return this.__zoom || identity$8;
35384 var zoom = function() {
35385 var filter = defaultFilter$2,
35386 extent = defaultExtent$1,
35394 interpolate = interpolateZoom,
35396 listeners = dispatch("start", "zoom", "end"),
35401 clickDistance2 = 0;
35403 function zoom(selection$$1) {
35405 .on("wheel.zoom", wheeled)
35406 .on("mousedown.zoom", mousedowned)
35407 .on("dblclick.zoom", dblclicked)
35408 .on("touchstart.zoom", touchstarted)
35409 .on("touchmove.zoom", touchmoved)
35410 .on("touchend.zoom touchcancel.zoom", touchended)
35411 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
35412 .property("__zoom", defaultTransform);
35415 zoom.transform = function(collection, transform$$1) {
35416 var selection$$1 = collection.selection ? collection.selection() : collection;
35417 selection$$1.property("__zoom", defaultTransform);
35418 if (collection !== selection$$1) {
35419 schedule(collection, transform$$1);
35421 selection$$1.interrupt().each(function() {
35422 gesture(this, arguments)
35424 .zoom(null, typeof transform$$1 === "function" ? transform$$1.apply(this, arguments) : transform$$1)
35430 zoom.scaleBy = function(selection$$1, k) {
35431 zoom.scaleTo(selection$$1, function() {
35432 var k0 = this.__zoom.k,
35433 k1 = typeof k === "function" ? k.apply(this, arguments) : k;
35438 zoom.scaleTo = function(selection$$1, k) {
35439 zoom.transform(selection$$1, function() {
35440 var e = extent.apply(this, arguments),
35443 p1 = t0.invert(p0),
35444 k1 = typeof k === "function" ? k.apply(this, arguments) : k;
35445 return constrain(translate(scale(t0, k1), p0, p1), e);
35449 zoom.translateBy = function(selection$$1, x, y) {
35450 zoom.transform(selection$$1, function() {
35451 return constrain(this.__zoom.translate(
35452 typeof x === "function" ? x.apply(this, arguments) : x,
35453 typeof y === "function" ? y.apply(this, arguments) : y
35454 ), extent.apply(this, arguments));
35458 function scale(transform$$1, k) {
35459 k = Math.max(k0, Math.min(k1, k));
35460 return k === transform$$1.k ? transform$$1 : new Transform(k, transform$$1.x, transform$$1.y);
35463 function translate(transform$$1, p0, p1) {
35464 var x = p0[0] - p1[0] * transform$$1.k, y = p0[1] - p1[1] * transform$$1.k;
35465 return x === transform$$1.x && y === transform$$1.y ? transform$$1 : new Transform(transform$$1.k, x, y);
35468 function constrain(transform$$1, extent) {
35469 var dx0 = transform$$1.invertX(extent[0][0]) - x0,
35470 dx1 = transform$$1.invertX(extent[1][0]) - x1,
35471 dy0 = transform$$1.invertY(extent[0][1]) - y0,
35472 dy1 = transform$$1.invertY(extent[1][1]) - y1;
35473 return transform$$1.translate(
35474 dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1),
35475 dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)
35479 function centroid(extent) {
35480 return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
35483 function schedule(transition$$1, transform$$1, center) {
35485 .on("start.zoom", function() { gesture(this, arguments).start(); })
35486 .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
35487 .tween("zoom", function() {
35490 g = gesture(that, args),
35491 e = extent.apply(that, args),
35492 p = center || centroid(e),
35493 w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
35495 b = typeof transform$$1 === "function" ? transform$$1.apply(that, args) : transform$$1,
35496 i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
35497 return function(t) {
35498 if (t === 1) t = b; // Avoid rounding error on end.
35499 else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
35505 function gesture(that, args) {
35506 for (var i = 0, n = gestures.length, g; i < n; ++i) {
35507 if ((g = gestures[i]).that === that) {
35511 return new Gesture(that, args);
35514 function Gesture(that, args) {
35519 this.extent = extent.apply(that, args);
35522 Gesture.prototype = {
35523 start: function() {
35524 if (++this.active === 1) {
35525 this.index = gestures.push(this) - 1;
35526 this.emit("start");
35530 zoom: function(key, transform$$1) {
35531 if (this.mouse && key !== "mouse") this.mouse[1] = transform$$1.invert(this.mouse[0]);
35532 if (this.touch0 && key !== "touch") this.touch0[1] = transform$$1.invert(this.touch0[0]);
35533 if (this.touch1 && key !== "touch") this.touch1[1] = transform$$1.invert(this.touch1[0]);
35534 this.that.__zoom = transform$$1;
35539 if (--this.active === 0) {
35540 gestures.splice(this.index, 1);
35546 emit: function(type) {
35547 customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
35551 function wheeled() {
35552 if (!filter.apply(this, arguments)) return;
35553 var g = gesture(this, arguments),
35555 k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500))),
35558 // If the mouse is in the same location as before, reuse it.
35559 // If there were recent wheel events, reset the wheel idle timeout.
35561 if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
35562 g.mouse[1] = t.invert(g.mouse[0] = p);
35564 clearTimeout(g.wheel);
35567 // If this wheel event won’t trigger a transform change, ignore it.
35568 else if (t.k === k) return;
35570 // Otherwise, capture the mouse point and location at the start.
35572 g.mouse = [p, t.invert(p)];
35578 g.wheel = setTimeout(wheelidled, wheelDelay);
35579 g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent));
35581 function wheelidled() {
35587 function mousedowned() {
35588 if (touchending || !filter.apply(this, arguments)) return;
35589 var g = gesture(this, arguments),
35590 v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
35592 x0 = event.clientX,
35593 y0 = event.clientY;
35595 dragDisable(event.view);
35597 g.mouse = [p, this.__zoom.invert(p)];
35601 function mousemoved() {
35604 var dx = event.clientX - x0, dy = event.clientY - y0;
35605 g.moved = dx * dx + dy * dy > clickDistance2;
35607 g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent));
35610 function mouseupped() {
35611 v.on("mousemove.zoom mouseup.zoom", null);
35612 yesdrag(event.view, g.moved);
35618 function dblclicked() {
35619 if (!filter.apply(this, arguments)) return;
35620 var t0 = this.__zoom,
35622 p1 = t0.invert(p0),
35623 k1 = t0.k * (event.shiftKey ? 0.5 : 2),
35624 t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments));
35627 if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
35628 else select(this).call(zoom.transform, t1);
35631 function touchstarted() {
35632 if (!filter.apply(this, arguments)) return;
35633 var g = gesture(this, arguments),
35634 touches$$1 = event.changedTouches,
35636 n = touches$$1.length, i, t, p;
35639 for (i = 0; i < n; ++i) {
35640 t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
35641 p = [p, this.__zoom.invert(p), t.identifier];
35642 if (!g.touch0) g.touch0 = p, started = true;
35643 else if (!g.touch1) g.touch1 = p;
35646 // If this is a dbltap, reroute to the (optional) dblclick.zoom handler.
35647 if (touchstarting) {
35648 touchstarting = clearTimeout(touchstarting);
35651 p = select(this).on("dblclick.zoom");
35652 if (p) p.apply(this, arguments);
35658 touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay);
35664 function touchmoved() {
35665 var g = gesture(this, arguments),
35666 touches$$1 = event.changedTouches,
35667 n = touches$$1.length, i, t, p, l;
35670 if (touchstarting) touchstarting = clearTimeout(touchstarting);
35671 for (i = 0; i < n; ++i) {
35672 t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
35673 if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;
35674 else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
35678 var p0 = g.touch0[0], l0 = g.touch0[1],
35679 p1 = g.touch1[0], l1 = g.touch1[1],
35680 dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
35681 dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
35682 t = scale(t, Math.sqrt(dp / dl));
35683 p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
35684 l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
35686 else if (g.touch0) p = g.touch0[0], l = g.touch0[1];
35688 g.zoom("touch", constrain(translate(t, p, l), g.extent));
35691 function touchended() {
35692 var g = gesture(this, arguments),
35693 touches$$1 = event.changedTouches,
35694 n = touches$$1.length, i, t;
35697 if (touchending) clearTimeout(touchending);
35698 touchending = setTimeout(function() { touchending = null; }, touchDelay);
35699 for (i = 0; i < n; ++i) {
35701 if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;
35702 else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
35704 if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
35705 if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);
35709 zoom.filter = function(_) {
35710 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$12(!!_), zoom) : filter;
35713 zoom.extent = function(_) {
35714 return arguments.length ? (extent = typeof _ === "function" ? _ : constant$12([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
35717 zoom.scaleExtent = function(_) {
35718 return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1];
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]];
35725 zoom.duration = function(_) {
35726 return arguments.length ? (duration = +_, zoom) : duration;
35729 zoom.interpolate = function(_) {
35730 return arguments.length ? (interpolate = _, zoom) : interpolate;
35733 zoom.on = function() {
35734 var value = listeners.on.apply(listeners, arguments);
35735 return value === listeners ? zoom : value;
35738 zoom.clickDistance = function(_) {
35739 return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2);
35747 var index$2 = Object.freeze({
35749 bisect: bisectRight,
35750 bisectRight: bisectRight,
35751 bisectLeft: bisectLeft,
35752 ascending: ascending,
35753 bisector: bisector,
35755 descending: descending,
35756 deviation: deviation,
35758 histogram: histogram,
35759 thresholdFreedmanDiaconis: freedmanDiaconis,
35760 thresholdScott: scott,
35761 thresholdSturges: sturges,
35769 quantile: threshold,
35775 tickIncrement: tickIncrement,
35776 tickStep: tickStep,
35777 transpose: transpose,
35778 variance: variance,
35781 axisRight: axisRight,
35782 axisBottom: axisBottom,
35783 axisLeft: axisLeft,
35787 brushSelection: brushSelection,
35801 cubehelix: cubehelix,
35802 dispatch: dispatch,
35804 dragDisable: dragDisable,
35805 dragEnable: yesdrag,
35807 csvParse: csvParse,
35808 csvParseRows: csvParseRows,
35809 csvFormat: csvFormat,
35810 csvFormatRows: csvFormatRows,
35811 tsvParse: tsvParse,
35812 tsvParseRows: tsvParseRows,
35813 tsvFormat: tsvFormat,
35814 tsvFormatRows: tsvFormatRows,
35815 easeLinear: linear$1,
35816 easeQuad: quadInOut,
35817 easeQuadIn: quadIn,
35818 easeQuadOut: quadOut,
35819 easeQuadInOut: quadInOut,
35820 easeCubic: cubicInOut,
35821 easeCubicIn: cubicIn,
35822 easeCubicOut: cubicOut,
35823 easeCubicInOut: cubicInOut,
35824 easePoly: polyInOut,
35825 easePolyIn: polyIn,
35826 easePolyOut: polyOut,
35827 easePolyInOut: polyInOut,
35830 easeSinOut: sinOut,
35831 easeSinInOut: sinInOut,
35834 easeExpOut: expOut,
35835 easeExpInOut: expInOut,
35836 easeCircle: circleInOut,
35837 easeCircleIn: circleIn,
35838 easeCircleOut: circleOut,
35839 easeCircleInOut: circleInOut,
35840 easeBounce: bounceOut,
35841 easeBounceIn: bounceIn,
35842 easeBounceOut: bounceOut,
35843 easeBounceInOut: bounceInOut,
35844 easeBack: backInOut,
35845 easeBackIn: backIn,
35846 easeBackOut: backOut,
35847 easeBackInOut: backInOut,
35848 easeElastic: elasticOut,
35849 easeElasticIn: elasticIn,
35850 easeElasticOut: elasticOut,
35851 easeElasticInOut: elasticInOut,
35852 forceCenter: center$1,
35853 forceCollide: collide,
35855 forceManyBody: manyBody,
35856 forceSimulation: simulation,
35859 formatDefaultLocale: defaultLocale,
35860 get format () { return format; },
35861 get formatPrefix () { return formatPrefix; },
35862 formatLocale: formatLocale,
35863 formatSpecifier: formatSpecifier,
35864 precisionFixed: precisionFixed,
35865 precisionPrefix: precisionPrefix,
35866 precisionRound: precisionRound,
35869 geoCentroid: d3GeoCentroid,
35871 geoClipExtent: extent$1,
35872 geoContains: contains,
35873 geoDistance: distance,
35874 geoGraticule: graticule,
35875 geoGraticule10: graticule10,
35876 geoInterpolate: interpolate$1,
35877 geoLength: d3GeoLength,
35880 geoAlbersUsa: albersUsa,
35881 geoAzimuthalEqualArea: azimuthalEqualArea,
35882 geoAzimuthalEqualAreaRaw: azimuthalEqualAreaRaw,
35883 geoAzimuthalEquidistant: azimuthalEquidistant,
35884 geoAzimuthalEquidistantRaw: azimuthalEquidistantRaw,
35885 geoConicConformal: conicConformal,
35886 geoConicConformalRaw: conicConformalRaw,
35887 geoConicEqualArea: conicEqualArea,
35888 geoConicEqualAreaRaw: conicEqualAreaRaw,
35889 geoConicEquidistant: conicEquidistant,
35890 geoConicEquidistantRaw: conicEquidistantRaw,
35891 geoEquirectangular: equirectangular,
35892 geoEquirectangularRaw: equirectangularRaw,
35893 geoGnomonic: gnomonic,
35894 geoGnomonicRaw: gnomonicRaw,
35895 geoIdentity: identity$5,
35896 geoProjection: projection,
35897 geoProjectionMutator: projectionMutator,
35898 geoMercator: mercator,
35899 geoMercatorRaw: mercatorRaw,
35900 geoOrthographic: orthographic,
35901 geoOrthographicRaw: orthographicRaw,
35902 geoStereographic: stereographic,
35903 geoStereographicRaw: stereographicRaw,
35904 geoTransverseMercator: transverseMercator,
35905 geoTransverseMercatorRaw: transverseMercatorRaw,
35906 geoRotation: rotation,
35907 geoStream: geoStream,
35908 geoTransform: transform,
35910 hierarchy: hierarchy,
35912 packSiblings: siblings,
35913 packEnclose: enclose,
35914 partition: partition,
35915 stratify: stratify,
35918 treemapBinary: binary,
35919 treemapDice: treemapDice,
35920 treemapSlice: treemapSlice,
35921 treemapSliceDice: sliceDice,
35922 treemapSquarify: squarify,
35923 treemapResquarify: resquarify,
35924 interpolate: interpolateValue,
35925 interpolateArray: array$1,
35926 interpolateBasis: basis$1,
35927 interpolateBasisClosed: basisClosed,
35928 interpolateDate: date,
35929 interpolateNumber: reinterpolate,
35930 interpolateObject: object,
35931 interpolateRound: interpolateRound,
35932 interpolateString: interpolateString,
35933 interpolateTransformCss: interpolateTransformCss,
35934 interpolateTransformSvg: interpolateTransformSvg,
35935 interpolateZoom: interpolateZoom,
35936 interpolateRgb: interpolateRgb,
35937 interpolateRgbBasis: rgbBasis,
35938 interpolateRgbBasisClosed: rgbBasisClosed,
35939 interpolateHsl: hsl$2,
35940 interpolateHslLong: hslLong,
35941 interpolateLab: lab$1,
35942 interpolateHcl: hcl$2,
35943 interpolateHclLong: hclLong,
35944 interpolateCubehelix: cubehelix$2,
35945 interpolateCubehelixLong: cubehelixLong,
35946 quantize: quantize,
35948 polygonArea: d3polygonArea,
35949 polygonCentroid: d3polygonCentroid,
35950 polygonHull: d3polygonHull,
35951 polygonContains: contains$1,
35952 polygonLength: length$1,
35953 quadtree: quadtree,
35955 randomUniform: uniform,
35956 randomNormal: normal,
35957 randomLogNormal: logNormal,
35958 randomBates: bates,
35959 randomIrwinHall: irwinHall,
35960 randomExponential: exponential$1,
35969 scalePoint: point$1,
35970 scaleIdentity: identity$6,
35971 scaleLinear: linear$2,
35973 scaleOrdinal: ordinal,
35974 scaleImplicit: implicit,
35977 scaleQuantile: quantile,
35978 scaleQuantize: quantize$1,
35979 scaleThreshold: threshold$1,
35982 schemeCategory10: category10,
35983 schemeCategory20b: category20b,
35984 schemeCategory20c: category20c,
35985 schemeCategory20: category20,
35986 interpolateCubehelixDefault: cubehelix$3,
35987 interpolateRainbow: rainbow$1,
35988 interpolateWarm: warm,
35989 interpolateCool: cool,
35990 interpolateViridis: viridis,
35991 interpolateMagma: magma,
35992 interpolateInferno: inferno,
35993 interpolatePlasma: plasma,
35994 scaleSequential: sequential,
35997 matcher: matcher$1,
35999 namespace: namespace,
36000 namespaces: namespaces,
36002 selectAll: selectAll,
36003 selection: selection,
36004 selector: selector,
36005 selectorAll: selectorAll,
36009 window: defaultView,
36010 get event () { return event; },
36011 customEvent: customEvent,
36016 radialArea: radialArea,
36017 radialLine: radialLine$1,
36018 linkHorizontal: linkHorizontal,
36019 linkVertical: linkVertical,
36020 linkRadial: linkRadial,
36023 symbolCircle: circle$2,
36024 symbolCross: cross$2,
36025 symbolDiamond: diamond,
36026 symbolSquare: square,
36028 symbolTriangle: triangle,
36030 curveBasisClosed: basisClosed$1,
36031 curveBasisOpen: basisOpen,
36032 curveBasis: basis$2,
36033 curveBundle: bundle,
36034 curveCardinalClosed: cardinalClosed,
36035 curveCardinalOpen: cardinalOpen,
36036 curveCardinal: cardinal,
36037 curveCatmullRomClosed: catmullRomClosed,
36038 curveCatmullRomOpen: catmullRomOpen,
36039 curveCatmullRom: catmullRom,
36040 curveLinearClosed: linearClosed,
36041 curveLinear: curveLinear,
36042 curveMonotoneX: monotoneX,
36043 curveMonotoneY: monotoneY,
36044 curveNatural: natural,
36046 curveStepAfter: stepAfter,
36047 curveStepBefore: stepBefore,
36049 stackOffsetExpand: expand,
36050 stackOffsetDiverging: diverging,
36051 stackOffsetNone: none$1,
36052 stackOffsetSilhouette: silhouette,
36053 stackOffsetWiggle: wiggle,
36054 stackOrderAscending: ascending$2,
36055 stackOrderDescending: descending$2,
36056 stackOrderInsideOut: insideOut,
36057 stackOrderNone: none$2,
36058 stackOrderReverse: reverse,
36059 timeInterval: newInterval,
36060 timeMillisecond: millisecond,
36061 timeMilliseconds: milliseconds,
36062 utcMillisecond: millisecond,
36063 utcMilliseconds: milliseconds,
36064 timeSecond: second,
36065 timeSeconds: seconds,
36067 utcSeconds: seconds,
36068 timeMinute: minute,
36069 timeMinutes: minutes,
36075 timeWeeks: sundays,
36076 timeSunday: sunday,
36077 timeSundays: sundays,
36078 timeMonday: monday,
36079 timeMondays: mondays,
36080 timeTuesday: tuesday,
36081 timeTuesdays: tuesdays,
36082 timeWednesday: wednesday,
36083 timeWednesdays: wednesdays,
36084 timeThursday: thursday,
36085 timeThursdays: thursdays,
36086 timeFriday: friday,
36087 timeFridays: fridays,
36088 timeSaturday: saturday,
36089 timeSaturdays: saturdays,
36091 timeMonths: months,
36094 utcMinute: utcMinute,
36095 utcMinutes: utcMinutes,
36097 utcHours: utcHours,
36100 utcWeek: utcSunday,
36101 utcWeeks: utcSundays,
36102 utcSunday: utcSunday,
36103 utcSundays: utcSundays,
36104 utcMonday: utcMonday,
36105 utcMondays: utcMondays,
36106 utcTuesday: utcTuesday,
36107 utcTuesdays: utcTuesdays,
36108 utcWednesday: utcWednesday,
36109 utcWednesdays: utcWednesdays,
36110 utcThursday: utcThursday,
36111 utcThursdays: utcThursdays,
36112 utcFriday: utcFriday,
36113 utcFridays: utcFridays,
36114 utcSaturday: utcSaturday,
36115 utcSaturdays: utcSaturdays,
36116 utcMonth: utcMonth,
36117 utcMonths: utcMonths,
36119 utcYears: utcYears,
36120 timeFormatDefaultLocale: defaultLocale$1,
36121 get timeFormat () { return timeFormat; },
36122 get timeParse () { return timeParse; },
36123 get utcFormat () { return utcFormat; },
36124 get utcParse () { return utcParse; },
36125 timeFormatLocale: formatLocale$1,
36126 isoFormat: formatIso,
36127 isoParse: parseIso,
36130 timerFlush: timerFlush,
36131 timeout: timeout$1,
36132 interval: interval$1,
36133 transition: transition,
36135 interrupt: interrupt,
36138 zoomTransform: transform$1,
36139 zoomIdentity: identity$8
36143 Bypasses features of D3's default projection stream pipeline that are unnecessary:
36144 * Antimeridian clipping
36145 * Spherical rotation
36148 function geoRawMercator() {
36149 var project = mercatorRaw,
36150 k = 512 / Math.PI, // scale
36151 x = 0, y = 0, // translate
36152 clipExtent = [[0, 0], [0, 0]];
36155 function projection$$1(point) {
36156 point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
36157 return [point[0] * k + x, y - point[1] * k];
36161 projection$$1.invert = function(point) {
36162 point = project.invert((point[0] - x) / k, (y - point[1]) / k);
36163 return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
36167 projection$$1.scale = function(_) {
36168 if (!arguments.length) return k;
36170 return projection$$1;
36174 projection$$1.translate = function(_) {
36175 if (!arguments.length) return [x, y];
36178 return projection$$1;
36182 projection$$1.clipExtent = function(_) {
36183 if (!arguments.length) return clipExtent;
36185 return projection$$1;
36189 projection$$1.transform = function(_) {
36190 if (!arguments.length) return identity$8.translate(x, y).scale(k);
36194 return projection$$1;
36198 projection$$1.stream = transform({
36199 point: function(x, y) {
36200 x = projection$$1([x, y]);
36201 this.stream.point(x[0], x[1]);
36206 return projection$$1;
36209 function osmChangeset() {
36210 if (!(this instanceof osmChangeset)) {
36211 return (new osmChangeset()).initialize(arguments);
36212 } else if (arguments.length) {
36213 this.initialize(arguments);
36218 osmEntity$$1.changeset = osmChangeset;
36220 osmChangeset.prototype = Object.create(osmEntity$$1.prototype);
36222 lodash.extend(osmChangeset.prototype, {
36227 extent: function() {
36228 return new geoExtent$$1();
36232 geometry: function() {
36233 return 'changeset';
36237 asJXON: function() {
36241 tag: lodash.map(this.tags, function(value, key) {
36242 return { '@k': key, '@v': value };
36252 // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
36253 // XML. Returns a string.
36254 osmChangeJXON: function(changes) {
36255 var changeset_id = this.id;
36257 function nest(x, order) {
36259 for (var i = 0; i < x.length; i++) {
36260 var tagName = Object.keys(x[i])[0];
36261 if (!groups[tagName]) groups[tagName] = [];
36262 groups[tagName].push(x[i][tagName]);
36265 order.forEach(function(o) {
36266 if (groups[o]) ordered[o] = groups[o];
36272 // sort relations in a changeset by dependencies
36273 function sort(changes) {
36275 // find a referenced relation in the current changeset
36276 function resolve(item) {
36277 return lodash.find(relations, function(relation) {
36278 return item.keyAttributes.type === 'relation'
36279 && item.keyAttributes.ref === relation['@id'];
36283 // a new item is an item that has not been already processed
36284 function isNew(item) {
36285 return !sorted[ item['@id'] ] && !lodash.find(processing, function(proc) {
36286 return proc['@id'] === item['@id'];
36290 var processing = [],
36292 relations = changes.relation;
36294 if (!relations) return changes;
36296 for (var i = 0; i < relations.length; i++) {
36297 var relation = relations[i];
36299 // skip relation if already sorted
36300 if (!sorted[relation['@id']]) {
36301 processing.push(relation);
36304 while (processing.length > 0) {
36305 var next = processing[0],
36306 deps = lodash.filter(lodash.compact(next.member.map(resolve)), isNew);
36307 if (deps.length === 0) {
36308 sorted[next['@id']] = next;
36309 processing.shift();
36311 processing = deps.concat(processing);
36316 changes.relation = lodash.values(sorted);
36320 function rep(entity) {
36321 return entity.asJXON(changeset_id);
36327 '@generator': 'iD',
36328 'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])),
36329 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
36330 'delete': lodash.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), { '@if-unused': true })
36336 asGeoJSON: function() {
36342 function osmNode() {
36343 if (!(this instanceof osmNode)) {
36344 return (new osmNode()).initialize(arguments);
36345 } else if (arguments.length) {
36346 this.initialize(arguments);
36350 osmEntity$$1.node = osmNode;
36352 osmNode.prototype = Object.create(osmEntity$$1.prototype);
36354 lodash.extend(osmNode.prototype, {
36359 extent: function() {
36360 return new geoExtent$$1(this.loc);
36364 geometry: function(graph) {
36365 return graph.transient(this, 'geometry', function() {
36366 return graph.isPoi(this) ? 'point' : 'vertex';
36371 move: function(loc) {
36372 return this.update({loc: loc});
36376 isDegenerate: function() {
36378 Array.isArray(this.loc) && this.loc.length === 2 &&
36379 this.loc[0] >= -180 && this.loc[0] <= 180 &&
36380 this.loc[1] >= -90 && this.loc[1] <= 90
36385 isEndpoint: function(resolver) {
36386 return resolver.transient(this, 'isEndpoint', function() {
36388 return resolver.parentWays(this).filter(function(parent) {
36389 return !parent.isClosed() && !!parent.affix(id);
36395 isConnected: function(resolver) {
36396 return resolver.transient(this, 'isConnected', function() {
36397 var parents = resolver.parentWays(this);
36399 function isLine(entity) {
36400 return entity.geometry(resolver) === 'line' &&
36401 entity.hasInterestingTags();
36404 // vertex is connected to multiple parent lines
36405 if (parents.length > 1 && lodash.some(parents, isLine)) {
36408 } else if (parents.length === 1) {
36409 var way = parents[0],
36410 nodes = way.nodes.slice();
36411 if (way.isClosed()) { nodes.pop(); } // ignore connecting node if closed
36413 // return true if vertex appears multiple times (way is self intersecting)
36414 return nodes.indexOf(this.id) !== nodes.lastIndexOf(this.id);
36422 isIntersection: function(resolver) {
36423 return resolver.transient(this, 'isIntersection', function() {
36424 return resolver.parentWays(this).filter(function(parent) {
36425 return (parent.tags.highway ||
36426 parent.tags.waterway ||
36427 parent.tags.railway ||
36428 parent.tags.aeroway) &&
36429 parent.geometry(resolver) === 'line';
36435 isHighwayIntersection: function(resolver) {
36436 return resolver.transient(this, 'isHighwayIntersection', function() {
36437 return resolver.parentWays(this).filter(function(parent) {
36438 return parent.tags.highway && parent.geometry(resolver) === 'line';
36444 isOnAddressLine: function(resolver) {
36445 return resolver.transient(this, 'isOnAddressLine', function() {
36446 return resolver.parentWays(this).filter(function(parent) {
36447 return parent.tags.hasOwnProperty('addr:interpolation') &&
36448 parent.geometry(resolver) === 'line';
36454 asJXON: function(changeset_id) {
36457 '@id': this.osmId(),
36458 '@lon': this.loc[0],
36459 '@lat': this.loc[1],
36460 '@version': (this.version || 0),
36461 tag: lodash.map(this.tags, function(v, k) {
36462 return { keyAttributes: { k: k, v: v } };
36466 if (changeset_id) r.node['@changeset'] = changeset_id;
36471 asGeoJSON: function() {
36474 coordinates: this.loc
36480 Order the nodes of a way in reverse order and reverse any direction dependent tags
36481 other than `oneway`. (We assume that correcting a backwards oneway is the primary
36482 reason for reversing a way.)
36484 The following transforms are performed:
36487 *:right=* ⟺ *:left=*
36488 *:forward=* ⟺ *:backward=*
36489 direction=up ⟺ direction=down
36490 incline=up ⟺ incline=down
36494 role=forward ⟺ role=backward
36495 role=north ⟺ role=south
36496 role=east ⟺ role=west
36498 In addition, numeric-valued `incline` tags are negated.
36500 The JOSM implementation was used as a guide, but transformations that were of unclear benefit
36501 or adjusted tags that don't seem to be used in practice were omitted.
36503 Also, each node on the way is examined for its own tags and the following transformations are performed
36504 in order to ensure associated nodes (eg a Stop Sign) is also reversed
36507 direction=forward ⟺ direction=backward
36508 direction=left ⟺ direction=right
36509 *:forward=* ⟺ *:backward=*
36510 *:left=* ⟺ *:right=*
36513 http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
36514 http://wiki.openstreetmap.org/wiki/Key:direction#Steps
36515 http://wiki.openstreetmap.org/wiki/Key:incline
36516 http://wiki.openstreetmap.org/wiki/Route#Members
36517 http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
36518 http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
36519 http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
36521 function actionReverse(wayId, options) {
36522 var replacements = [
36523 [/:right$/, ':left'], [/:left$/, ':right'],
36524 [/:forward$/, ':backward'], [/:backward$/, ':forward']
36526 numeric = /^([+\-]?)(?=[\d.])/,
36528 forward: 'backward',
36529 backward: 'forward',
36537 function reverseKey(key) {
36538 for (var i = 0; i < replacements.length; ++i) {
36539 var replacement = replacements[i];
36540 if (replacement[0].test(key)) {
36541 return key.replace(replacement[0], replacement[1]);
36548 function reverseValue(key, value) {
36549 if (key === 'incline' && numeric.test(value)) {
36550 return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
36551 } else if (key === 'incline' || key === 'direction') {
36552 return {up: 'down', down: 'up'}[value] || value;
36553 } else if (options && options.reverseOneway && key === 'oneway') {
36554 return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
36556 return {left: 'right', right: 'left'}[value] || value;
36561 function reverseDirectionTags(node) {
36562 // Update the direction based tags as appropriate then return an updated node
36563 return node.update({tags: lodash.transform(node.tags, function(acc, tagValue, tagKey) {
36564 // See if this is a direction tag and reverse (or use existing value if not recognised)
36565 if (tagKey === 'direction') {
36566 acc[tagKey] = {forward: 'backward', backward: 'forward', left: 'right', right: 'left'}[tagValue] || tagValue;
36568 // Use the reverseKey method to cater for situations such as traffic_sign:forward=stop
36569 // This will pass through other tags unchanged
36570 acc[reverseKey(tagKey)] = tagValue;
36577 function reverseTagsOnNodes(graph, nodeIds) {
36578 // Reverse the direction of appropriate tags attached to the nodes (#3076)
36579 return lodash(nodeIds)
36580 // Get each node from the graph
36581 .map(function(nodeId) { return graph.entity(nodeId);})
36582 // Check tags on the node, if there aren't any, we can skip
36583 .filter(function(existingNode) { return existingNode.tags !== undefined;})
36584 // Get a new version of each node with the appropriate tags reversed
36585 .map(function(existingNode) { return reverseDirectionTags(existingNode);})
36586 // Chain together consecutive updates to the graph for each updated node and return
36587 .reduce(function (accGraph, value) { return accGraph.replace(value); }, graph);
36591 return function(graph) {
36592 var way = graph.entity(wayId),
36593 nodes = way.nodes.slice().reverse(),
36594 tags = {}, key, role;
36596 for (key in way.tags) {
36597 tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
36600 graph.parentRelations(way).forEach(function(relation) {
36601 relation.members.forEach(function(member, index) {
36602 if (member.id === way.id && (role = roleReversals[member.role])) {
36603 relation = relation.updateMember({role: role}, index);
36604 graph = graph.replace(relation);
36609 // Reverse any associated directions on nodes on the way and then replace
36610 // the way itself with the reversed node ids and updated way tags
36611 return reverseTagsOnNodes(graph, nodes).replace(way.update({nodes: nodes, tags: tags}));
36615 // For fixing up rendering of multipolygons with tags on the outer member.
36616 // https://github.com/openstreetmap/iD/issues/613
36617 function osmIsSimpleMultipolygonOuterMember(entity, graph) {
36618 if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0)
36621 var parents = graph.parentRelations(entity);
36622 if (parents.length !== 1)
36625 var parent = parents[0];
36626 if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
36629 var members = parent.members, member;
36630 for (var i = 0; i < members.length; i++) {
36631 member = members[i];
36632 if (member.id === entity.id && member.role && member.role !== 'outer')
36633 return false; // Not outer member
36634 if (member.id !== entity.id && (!member.role || member.role === 'outer'))
36635 return false; // Not a simple multipolygon
36642 function osmSimpleMultipolygonOuterMember(entity, graph) {
36643 if (entity.type !== 'way')
36646 var parents = graph.parentRelations(entity);
36647 if (parents.length !== 1)
36650 var parent = parents[0];
36651 if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
36654 var members = parent.members, member, outerMember;
36655 for (var i = 0; i < members.length; i++) {
36656 member = members[i];
36657 if (!member.role || member.role === 'outer') {
36659 return false; // Not a simple multipolygon
36660 outerMember = member;
36667 var outerEntity = graph.hasEntity(outerMember.id);
36668 if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length)
36671 return outerEntity;
36675 // Join `array` into sequences of connecting ways.
36677 // Segments which share identical start/end nodes will, as much as possible,
36678 // be connected with each other.
36680 // The return value is a nested array. Each constituent array contains elements
36681 // of `array` which have been determined to connect. Each consitituent array
36682 // also has a `nodes` property whose value is an ordered array of member nodes,
36683 // with appropriate order reversal and start/end coordinate de-duplication.
36685 // Members of `array` must have, at minimum, `type` and `id` properties.
36686 // Thus either an array of `osmWay`s or a relation member array may be
36689 // If an member has a `tags` property, its tags will be reversed via
36690 // `actionReverse` in the output.
36692 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
36693 // false) and non-way members are ignored.
36695 function osmJoinWays(array, graph) {
36696 var joined = [], member, current, nodes, first, last, i, how, what;
36698 array = array.filter(function(member) {
36699 return member.type === 'way' && graph.hasEntity(member.id);
36702 function resolve(member) {
36703 return graph.childNodes(graph.entity(member.id));
36706 function reverse(member) {
36707 return member.tags ? actionReverse(member.id, { reverseOneway: true })(graph).entity(member.id) : member;
36710 while (array.length) {
36711 member = array.shift();
36712 current = [member];
36713 current.nodes = nodes = resolve(member).slice();
36714 joined.push(current);
36716 while (array.length && lodash.first(nodes) !== lodash.last(nodes)) {
36717 first = lodash.first(nodes);
36718 last = lodash.last(nodes);
36720 for (i = 0; i < array.length; i++) {
36722 what = resolve(member);
36724 if (last === lodash.first(what)) {
36726 what = what.slice(1);
36728 } else if (last === lodash.last(what)) {
36730 what = what.slice(0, -1).reverse();
36731 member = reverse(member);
36733 } else if (first === lodash.last(what)) {
36734 how = nodes.unshift;
36735 what = what.slice(0, -1);
36737 } else if (first === lodash.first(what)) {
36738 how = nodes.unshift;
36739 what = what.slice(1).reverse();
36740 member = reverse(member);
36748 break; // No more joinable ways.
36750 how.apply(current, [member]);
36751 how.apply(nodes, what);
36753 array.splice(i, 1);
36760 function osmRelation() {
36761 if (!(this instanceof osmRelation)) {
36762 return (new osmRelation()).initialize(arguments);
36763 } else if (arguments.length) {
36764 this.initialize(arguments);
36769 osmEntity$$1.relation = osmRelation;
36771 osmRelation.prototype = Object.create(osmEntity$$1.prototype);
36774 osmRelation.creationOrder = function(a, b) {
36775 var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10);
36776 var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10);
36778 if (aId < 0 || bId < 0) return aId - bId;
36783 lodash.extend(osmRelation.prototype, {
36788 copy: function(resolver, copies) {
36789 if (copies[this.id])
36790 return copies[this.id];
36792 var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
36794 var members = this.members.map(function(member) {
36795 return lodash.extend({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id });
36798 copy = copy.update({members: members});
36799 copies[this.id] = copy;
36805 extent: function(resolver, memo) {
36806 return resolver.transient(this, 'extent', function() {
36807 if (memo && memo[this.id]) return geoExtent$$1();
36809 memo[this.id] = true;
36811 var extent$$1 = geoExtent$$1();
36812 for (var i = 0; i < this.members.length; i++) {
36813 var member = resolver.hasEntity(this.members[i].id);
36815 extent$$1._extend(member.extent(resolver, memo));
36823 geometry: function(graph) {
36824 return graph.transient(this, 'geometry', function() {
36825 return this.isMultipolygon() ? 'area' : 'relation';
36830 isDegenerate: function() {
36831 return this.members.length === 0;
36835 // Return an array of members, each extended with an 'index' property whose value
36836 // is the member index.
36837 indexedMembers: function() {
36838 var result = new Array(this.members.length);
36839 for (var i = 0; i < this.members.length; i++) {
36840 result[i] = lodash.extend({}, this.members[i], {index: i});
36846 // Return the first member with the given role. A copy of the member object
36847 // is returned, extended with an 'index' property whose value is the member index.
36848 memberByRole: function(role) {
36849 for (var i = 0; i < this.members.length; i++) {
36850 if (this.members[i].role === role) {
36851 return lodash.extend({}, this.members[i], {index: i});
36857 // Return the first member with the given id. A copy of the member object
36858 // is returned, extended with an 'index' property whose value is the member index.
36859 memberById: function(id) {
36860 for (var i = 0; i < this.members.length; i++) {
36861 if (this.members[i].id === id) {
36862 return lodash.extend({}, this.members[i], {index: i});
36868 // Return the first member with the given id and role. A copy of the member object
36869 // is returned, extended with an 'index' property whose value is the member index.
36870 memberByIdAndRole: function(id, role) {
36871 for (var i = 0; i < this.members.length; i++) {
36872 if (this.members[i].id === id && this.members[i].role === role) {
36873 return lodash.extend({}, this.members[i], {index: i});
36879 addMember: function(member, index) {
36880 var members = this.members.slice();
36881 members.splice(index === undefined ? members.length : index, 0, member);
36882 return this.update({members: members});
36886 updateMember: function(member, index) {
36887 var members = this.members.slice();
36888 members.splice(index, 1, lodash.extend({}, members[index], member));
36889 return this.update({members: members});
36893 removeMember: function(index) {
36894 var members = this.members.slice();
36895 members.splice(index, 1);
36896 return this.update({members: members});
36900 removeMembersWithID: function(id) {
36901 var members = lodash.reject(this.members, function(m) { return m.id === id; });
36902 return this.update({members: members});
36906 // Wherever a member appears with id `needle.id`, replace it with a member
36907 // with id `replacement.id`, type `replacement.type`, and the original role,
36908 // unless a member already exists with that id and role. Return an updated
36910 replaceMember: function(needle, replacement) {
36911 if (!this.memberById(needle.id))
36916 for (var i = 0; i < this.members.length; i++) {
36917 var member = this.members[i];
36918 if (member.id !== needle.id) {
36919 members.push(member);
36920 } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
36921 members.push({id: replacement.id, type: replacement.type, role: member.role});
36925 return this.update({members: members});
36929 asJXON: function(changeset_id) {
36932 '@id': this.osmId(),
36933 '@version': this.version || 0,
36934 member: lodash.map(this.members, function(member) {
36939 ref: osmEntity$$1.id.toOSM(member.id)
36943 tag: lodash.map(this.tags, function(v, k) {
36944 return { keyAttributes: { k: k, v: v } };
36948 if (changeset_id) r.relation['@changeset'] = changeset_id;
36953 asGeoJSON: function(resolver) {
36954 return resolver.transient(this, 'GeoJSON', function () {
36955 if (this.isMultipolygon()) {
36957 type: 'MultiPolygon',
36958 coordinates: this.multipolygon(resolver)
36962 type: 'FeatureCollection',
36963 properties: this.tags,
36964 features: this.members.map(function (member) {
36965 return lodash.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
36973 area: function(resolver) {
36974 return resolver.transient(this, 'area', function() {
36975 return area(this.asGeoJSON(resolver));
36980 isMultipolygon: function() {
36981 return this.tags.type === 'multipolygon';
36985 isComplete: function(resolver) {
36986 for (var i = 0; i < this.members.length; i++) {
36987 if (!resolver.hasEntity(this.members[i].id)) {
36995 isRestriction: function() {
36996 return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
37000 // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
37001 // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
37003 // This corresponds to the structure needed for rendering a multipolygon path using a
37004 // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
37006 // In the case of invalid geometries, this function will still return a result which
37007 // includes the nodes of all way members, but some Nds may be unclosed and some inner
37008 // rings not matched with the intended outer ring.
37010 multipolygon: function(resolver) {
37011 var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
37012 inners = this.members.filter(function(m) { return 'inner' === m.role; });
37014 outers = osmJoinWays(outers, resolver);
37015 inners = osmJoinWays(inners, resolver);
37017 outers = outers.map(function(outer) { return lodash.map(outer.nodes, 'loc'); });
37018 inners = inners.map(function(inner) { return lodash.map(inner.nodes, 'loc'); });
37020 var result = outers.map(function(o) {
37021 // Heuristic for detecting counterclockwise winding order. Assumes
37022 // that OpenStreetMap polygons are not hemisphere-spanning.
37023 return [area({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o];
37026 function findOuter(inner) {
37029 for (o = 0; o < outers.length; o++) {
37031 if (geoPolygonContainsPolygon(outer, inner))
37035 for (o = 0; o < outers.length; o++) {
37037 if (geoPolygonIntersectsPolygon(outer, inner, false))
37042 for (var i = 0; i < inners.length; i++) {
37043 var inner = inners[i];
37045 if (area({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) {
37046 inner = inner.reverse();
37049 var o = findOuter(inners[i]);
37050 if (o !== undefined)
37051 result[o].push(inners[i]);
37053 result.push([inners[i]]); // Invalid geometry
37060 function osmLanes(entity) {
37061 if (entity.type !== 'way') return null;
37062 if (!entity.tags.highway) return null;
37064 var tags = entity.tags;
37065 var isOneWay = entity.isOneWay();
37066 var laneCount = getLaneCount(tags, isOneWay);
37067 var maxspeed = parseMaxspeed(tags);
37069 var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
37070 var forward = laneDirections.forward;
37071 var backward = laneDirections.backward;
37072 var bothways = laneDirections.bothways;
37074 // parse the piped string 'x|y|z' format
37075 var turnLanes = {};
37076 turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
37077 turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
37078 turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
37080 var maxspeedLanes = {};
37081 maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
37082 maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
37083 maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
37086 psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
37087 psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
37088 psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
37091 busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
37092 busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
37093 busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
37095 var taxiLanes = {};
37096 taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
37097 taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
37098 taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
37101 hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
37102 hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
37103 hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
37106 hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
37107 hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
37108 hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
37110 var bicyclewayLanes = {};
37111 bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
37112 bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
37113 bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
37121 // map forward/backward/unspecified of each lane type to lanesObj
37122 mapToLanesObj(lanesObj, turnLanes, 'turnLane');
37123 mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
37124 mapToLanesObj(lanesObj, psvLanes, 'psv');
37125 mapToLanesObj(lanesObj, busLanes, 'bus');
37126 mapToLanesObj(lanesObj, taxiLanes, 'taxi');
37127 mapToLanesObj(lanesObj, hovLanes, 'hov');
37128 mapToLanesObj(lanesObj, hgvLanes, 'hgv');
37129 mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
37136 backward: backward,
37137 bothways: bothways,
37138 turnLanes: turnLanes,
37139 maxspeed: maxspeed,
37140 maxspeedLanes: maxspeedLanes,
37141 psvLanes: psvLanes,
37142 busLanes: busLanes,
37143 taxiLanes: taxiLanes,
37144 hovLanes: hovLanes,
37145 hgvLanes: hgvLanes,
37146 bicyclewayLanes: bicyclewayLanes
37153 function getLaneCount(tags, isOneWay) {
37156 count = parseInt(tags.lanes, 10);
37163 switch (tags.highway) {
37166 count = isOneWay ? 2 : 4;
37169 count = isOneWay ? 1 : 2;
37177 function parseMaxspeed(tags) {
37178 var maxspeed = tags.maxspeed;
37179 if (lodash.isNumber(maxspeed)) return maxspeed;
37180 if (lodash.isString(maxspeed)) {
37181 maxspeed = maxspeed.match(/^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/g);
37182 if (!maxspeed) return;
37183 return parseInt(maxspeed, 10);
37188 function parseLaneDirections(tags, isOneWay, laneCount) {
37189 var forward = parseInt(tags['lanes:forward'], 10);
37190 var backward = parseInt(tags['lanes:backward'], 10);
37191 var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
37193 if (parseInt(tags.oneway, 10) === -1) {
37196 backward = laneCount;
37198 else if (isOneWay) {
37199 forward = laneCount;
37203 else if (lodash.isNaN(forward) && lodash.isNaN(backward)) {
37204 backward = Math.floor((laneCount - bothways) / 2);
37205 forward = laneCount - bothways - backward;
37207 else if (lodash.isNaN(forward)) {
37208 if (backward > laneCount - bothways) {
37209 backward = laneCount - bothways;
37211 forward = laneCount - bothways - backward;
37213 else if (lodash.isNaN(backward)) {
37214 if (forward > laneCount - bothways) {
37215 forward = laneCount - bothways;
37217 backward = laneCount - bothways - forward;
37221 backward: backward,
37227 function parseTurnLanes(tag){
37230 var validValues = [
37231 'left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right',
37232 'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'
37235 return tag.split('|')
37236 .map(function (s) {
37237 if (s === '') s = 'none';
37238 return s.split(';')
37239 .map(function (d) {
37240 return validValues.indexOf(d) === -1 ? 'unknown': d;
37246 function parseMaxspeedLanes(tag, maxspeed) {
37249 return tag.split('|')
37250 .map(function (s) {
37251 if (s === 'none') return s;
37252 var m = parseInt(s, 10);
37253 if (s === '' || m === maxspeed) return null;
37254 return lodash.isNaN(m) ? 'unknown': m;
37259 function parseMiscLanes(tag) {
37262 var validValues = [
37263 'yes', 'no', 'designated'
37266 return tag.split('|')
37267 .map(function (s) {
37268 if (s === '') s = 'no';
37269 return validValues.indexOf(s) === -1 ? 'unknown': s;
37274 function parseBicycleWay(tag) {
37277 var validValues = [
37278 'yes', 'no', 'designated', 'lane'
37281 return tag.split('|')
37282 .map(function (s) {
37283 if (s === '') s = 'no';
37284 return validValues.indexOf(s) === -1 ? 'unknown': s;
37289 function mapToLanesObj(lanesObj, data, key) {
37290 if (data.forward) data.forward.forEach(function(l, i) {
37291 if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
37292 lanesObj.forward[i][key] = l;
37294 if (data.backward) data.backward.forEach(function(l, i) {
37295 if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
37296 lanesObj.backward[i][key] = l;
37298 if (data.unspecified) data.unspecified.forEach(function(l, i) {
37299 if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
37300 lanesObj.unspecified[i][key] = l;
37304 var translations = Object.create(null);
37306 var currentLocale = 'en';
37307 var textDirection = 'ltr';
37309 function setLocale(_) {
37310 if (translations[_] !== undefined) {
37312 } else if (translations[_.split('-')[0]]) {
37313 currentLocale = _.split('-')[0];
37317 function addTranslation(id, value) {
37318 translations[id] = value;
37322 * Given a string identifier, try to find that string in the current
37323 * language, and return it.
37325 * @param {string} s string identifier
37326 * @returns {string?} locale string
37328 function t(s, o, loc) {
37329 loc = loc || currentLocale;
37333 .map(function(s) { return s.replace('<TX_DOT>', '.'); })
37336 var rep = translations[loc];
37338 while (rep !== undefined && path.length) rep = rep[path.pop()];
37340 if (rep !== undefined) {
37341 if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
37345 if (loc !== 'en') {
37346 return t(s, o, 'en');
37349 if (o && 'default' in o) {
37353 var missing = 'Missing ' + loc + ' translation: ' + s;
37354 if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
37360 * Given string 'ltr' or 'rtl', save that setting
37362 * @param {string} s ltr or rtl
37365 function setTextDirection(dir) {
37366 textDirection = dir;
37371 function utilDetect(force) {
37372 if (detected && !force) return detected;
37375 var ua = navigator.userAgent,
37378 m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i); // Edge
37380 detected.browser = m[1];
37381 detected.version = m[2];
37383 if (!detected.browser) {
37384 m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11
37386 detected.browser = 'msie';
37387 detected.version = m[1];
37390 if (!detected.browser) {
37391 m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i); // Opera 15+
37393 detected.browser = 'Opera';
37394 detected.version = m[2];
37397 if (!detected.browser) {
37398 m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
37400 detected.browser = m[1];
37401 detected.version = m[2];
37402 m = ua.match(/version\/([\.\d]+)/i);
37403 if (m !== null) detected.version = m[1];
37406 if (!detected.browser) {
37407 detected.browser = navigator.appName;
37408 detected.version = navigator.appVersion;
37411 // keep major.minor version only..
37412 detected.version = detected.version.split(/\W/).slice(0,2).join('.');
37414 if (detected.browser.toLowerCase() === 'msie') {
37415 detected.ie = true;
37416 detected.browser = 'Internet Explorer';
37417 detected.support = parseFloat(detected.version) >= 11;
37419 detected.ie = false;
37420 detected.support = true;
37423 // Added due to incomplete svg style support. See #715
37424 detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
37426 detected.locale = (navigator.language || navigator.userLanguage || 'en-US');
37427 detected.language = detected.locale.split('-')[0];
37429 // Search `navigator.languages` for a better locale.. Prefer the first language,
37430 // unless the second language is a culture-specific version of the first one, see #3842
37431 if (navigator.languages && navigator.languages.length > 0) {
37432 var code0 = navigator.languages[0],
37433 parts0 = code0.split('-');
37435 detected.locale = code0;
37436 detected.language = parts0[0];
37438 if (navigator.languages.length > 1 && parts0.length === 1) {
37439 var code1 = navigator.languages[1],
37440 parts1 = code1.split('-');
37442 if (parts1[0] === parts0[0]) {
37443 detected.locale = code1;
37448 // Loaded locale is stored in currentLocale
37449 // return that instead (except in the situation where 'en' might override 'en-US')
37450 var loadedLocale = currentLocale || 'en';
37451 if (loadedLocale !== 'en') {
37452 detected.locale = loadedLocale;
37453 detected.language = detected.locale.split('-')[0];
37456 // detect text direction
37457 var q = utilStringQs(window.location.hash.substring(1));
37458 var lang = dataLocales[detected.locale];
37459 if ((lang && lang.rtl) || q.hasOwnProperty('rtl')) {
37460 detected.textDirection = 'rtl';
37462 detected.textDirection = 'ltr';
37464 setTextDirection(detected.textDirection);
37467 var loc = window.top.location;
37468 var origin = loc.origin;
37469 if (!origin) { // for unpatched IE11
37470 origin = loc.protocol + '//' + loc.hostname + (loc.port ? ':' + loc.port: '');
37473 detected.host = origin + loc.pathname;
37475 detected.filedrop = (window.FileReader && 'ondrop' in window);
37478 return navigator.userAgent.indexOf(x) !== -1;
37482 detected.os = 'win';
37483 detected.platform = 'Windows';
37485 else if (nav('Mac')) {
37486 detected.os = 'mac';
37487 detected.platform = 'Macintosh';
37489 else if (nav('X11') || nav('Linux')) {
37490 detected.os = 'linux';
37491 detected.platform = 'Linux';
37494 detected.os = 'win';
37495 detected.platform = 'Unknown';
37501 var remove$1 = removeDiacritics;
37503 var replacementList = [
37512 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",
37518 chars: "\u00C6\u01FC\u01E2",
37527 chars: "\uA738\uA73A",
37533 chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181",
37536 chars: "\u24b8\uff23\uA73E\u1E08\u0106\u0043\u0108\u010A\u010C\u00C7\u0187\u023B",
37539 chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779",
37545 chars: "\u01F1\u01C4",
37548 chars: "\u01F2\u01C5",
37551 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",
37554 chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B",
37557 chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262",
37560 chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D",
37563 chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197",
37566 chars: "\u24BF\uFF2A\u0134\u0248\u0237",
37569 chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2",
37572 chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780",
37581 chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB",
37584 chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E",
37593 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",
37608 chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754",
37611 chars: "\u24C6\uFF31\uA756\uA758\u024A",
37614 chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782",
37617 chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784",
37620 chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786",
37629 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",
37632 chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245",
37638 chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72",
37641 chars: "\u24CD\uFF38\u1E8A\u1E8C",
37644 chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE",
37647 chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762",
37650 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",
37656 chars: "\u00E6\u01FD\u01E3",
37665 chars: "\uA739\uA73B",
37671 chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182",
37674 chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184",
37677 chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA",
37683 chars: "\u01F3\u01C6",
37686 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",
37689 chars: "\u24D5\uFF46\u1E1F\u0192",
37707 chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79",
37710 chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265",
37716 chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131",
37719 chars: "\u24D9\uFF4A\u0135\u01F0\u0249",
37722 chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3",
37725 chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D",
37731 chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F",
37734 chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509",
37740 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",
37755 chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1",
37758 chars: "\u24E0\uFF51\u024B\uA757\uA759",
37761 chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783",
37764 chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282",
37770 chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787",
37779 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",
37782 chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C",
37788 chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73",
37791 chars: "\u24E7\uFF58\u1E8B\u1E8D",
37794 chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF",
37797 chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763",
37801 var diacriticsMap = {};
37802 for (var i = 0; i < replacementList.length; i += 1) {
37803 var chars = replacementList[i].chars;
37804 for (var j = 0; j < chars.length; j += 1) {
37805 diacriticsMap[chars[j]] = replacementList[i].base;
37809 function removeDiacritics(str) {
37810 return str.replace(/[^\u0000-\u007e]/g, function(c) {
37811 return diacriticsMap[c] || c;
37815 // see https://github.com/openstreetmap/iD/pull/3707
37816 // https://gist.github.com/mapmeld/556b09ddec07a2044c76e1ef45f01c60
37819 // madda above alef
37820 1570: { initial: 'آ', isolated: 'ﺁ', medial: 'ﺁ', final: 'ﺂ' },
37822 // hamza above and below alef
37823 1571: { initial: 'أ', isolated: 'ﺃ', medial: '', final: 'ﺄ' },
37825 1573: { initial: 'إ', isolated: 'ﺇ', medial: '', final: 'ﺈ' },
37827 1575: { initial: 'ا', isolated: 'ا', medial: '', final: 'ﺎ' },
37828 1576: { initial: 'ﺑ', isolated: 'ﺏ', medial: 'ﺒ', final: 'ﺐ' },
37831 1577: { initial: '', isolated: 'ة', medial: '', final: 'ﺔ' },
37833 1578: { initial: 'ﺗ', isolated: 'ﺕ', medial: 'ﺘ', final: 'ﺖ' },
37834 1579: { initial: 'ﺛ', isolated: 'ﺙ', medial: 'ﺜ', final: 'ﺚ' },
37835 1580: { initial: 'ﺟ', isolated: 'ﺝ', medial: 'ﺠ', final: 'ﺞ' },
37836 1581: { initial: 'ﺣ', isolated: 'ﺡ', medial: 'ﺤ', final: 'ﺢ' },
37837 1582: { initial: 'ﺧ', isolated: 'ﺥ', medial: 'ﺨ', final: 'ﺦ' },
37838 1583: { initial: 'ﺩ', isolated: 'ﺩ', medial: '', final: 'ﺪ' },
37839 1584: { initial: 'ﺫ', isolated: 'ﺫ', medial: '', final: 'ﺬ' },
37840 1585: { initial: 'ﺭ', isolated: 'ﺭ', medial: '', final: 'ﺮ' },
37841 1586: { initial: 'ﺯ', isolated: 'ﺯ', medial: '', final: 'ﺰ' },
37842 1688: { initial: 'ﮊ', isolated: 'ﮊ', medial: '', final: 'ﮋ' },
37843 1587: { initial: 'ﺳ', isolated: 'ﺱ', medial: 'ﺴ', final: 'ﺲ' },
37844 1588: { initial: 'ﺷ', isolated: 'ﺵ', medial: 'ﺸ', final: 'ﺶ' },
37845 1589: { initial: 'ﺻ', isolated: 'ﺹ', medial: 'ﺼ', final: 'ﺺ' },
37846 1590: { initial: 'ﺿ', isolated: 'ﺽ', medial: 'ﻀ', final: 'ﺾ' },
37847 1591: { initial: 'ﻃ', isolated: 'ﻁ', medial: 'ﻄ', final: 'ﻂ' },
37848 1592: { initial: 'ﻇ', isolated: 'ﻅ', medial: 'ﻈ', final: 'ﻆ' },
37849 1593: { initial: 'ﻋ', isolated: 'ﻉ', medial: 'ﻌ', final: 'ﻊ' },
37850 1594: { initial: 'ﻏ', isolated: 'ﻍ', medial: 'ﻐ', final: 'ﻎ' },
37852 // 1595 ػ - may be very rare
37854 1601: { initial: 'ﻓ', isolated: 'ﻑ', medial: 'ﻔ', final: 'ﻒ' },
37855 1602: { initial: 'ﻗ', isolated: 'ﻕ', medial: 'ﻘ', final: 'ﻖ' },
37856 1604: { initial: 'ﻟ', isolated: 'ﻝ', medial: 'ﻠ', final: 'ﻞ' },
37857 1605: { initial: 'ﻣ', isolated: 'ﻡ', medial: 'ﻤ', final: 'ﻢ' },
37858 1606: { initial: 'ﻧ', isolated: 'ﻥ', medial: 'ﻨ', final: 'ﻦ' },
37859 1607: { initial: 'ﻫ', isolated: 'ﻩ', medial: 'ﻬ', final: 'ﻪ' },
37860 1608: { initial: 'ﻭ', isolated: 'ﻭ', medial: '', final: 'ﻮ' },
37863 1609: { initial: 'ﯨ', isolated: 'ﻯ', medial: 'ﯩ', final: 'ﻰ' },
37865 1610: { initial: 'ﻳ', isolated: 'ﻱ', medial: 'ﻴ', final: 'ﻲ' },
37867 // short vowel sounds / tashkil markings
37869 1662: { initial: 'ﭘ', isolated: 'ﭖ', medial: 'ﭙ', final: 'ﭗ' },
37871 1670: { initial: 'ﭼ', isolated: 'ﭺ', medial: 'ﭽ', final: 'ﭻ' },
37872 1603: { initial: 'ﻛ', isolated: 'ﻙ', medial: 'ﻜ', final: 'ﻚ' },
37873 1705: { initial: 'ﻛ', isolated: 'ﮎ', medial: 'ﻜ', final: 'ﮏ' },
37874 1711: { initial: 'ﮔ', isolated: 'ﮒ', medial: 'ﮕ', final: 'ﮓ' },
37875 1740: { initial: 'ﻳ', isolated: 'ﻯ', medial: 'ﻴ', final: 'ﻰ' },
37876 5000: { initial: 'ﻻ', isolated: 'ﻻ', medial: '', final: 'ﻼ' }
37879 var rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0780-\u07BF]/;
37881 function fixRTLTextForSvg(inputText) {
37882 var context = true;
37884 var rtlBuffer = [];
37885 var arabicRegex = /[\u0600-\u06FF]/g;
37886 var arabicTashkil = /[\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED]/;
37887 var thaanaVowel = /[\u07A6-\u07B0]/;
37888 var hebrewSign = /[\u0591-\u05bd\u05bf\u05c1-\u05c5\u05c7]/;
37890 if (!arabicRegex.test(inputText)) {
37891 // Hebrew or Thaana RTL script
37892 for (var n = 0; n < inputText.length; n++) {
37893 var c = inputText[n];
37894 if ((thaanaVowel.test(c) || hebrewSign.test(c)) && rtlBuffer.length) {
37895 rtlBuffer[rtlBuffer.length - 1] += c;
37896 } else if (rtlRegex.test(c)) {
37898 } else if (c === ' ' && rtlBuffer.length) {
37899 // whitespace within RTL text
37900 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
37902 // non-RTL character
37903 ret += rtlBuffer.reverse().join('') + c;
37908 for (var i = 0, l = inputText.length; i < l; i++) {
37909 var code = inputText[i].charCodeAt(0);
37910 var nextCode = inputText[i + 1] ? inputText[i + 1].charCodeAt(0) : 0;
37912 if (!chars$1[code]) {
37913 if (code === 32 && rtlBuffer.length) {
37915 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
37916 } else if (arabicTashkil.test(inputText[i]) && rtlBuffer.length) {
37918 rtlBuffer[rtlBuffer.length - 1] += inputText[i];
37920 // non-RTL character
37921 ret += rtlBuffer.reverse().join('') + inputText[i];
37927 if (i === l - 1 || nextCode === 32) {
37928 rtlBuffer.push(chars$1[code].isolated);
37930 // special case for لا
37931 if (code === 1604 && nextCode === 1575) {
37932 rtlBuffer.push(chars$1[5000].initial);
37937 rtlBuffer.push(chars$1[code].initial);
37940 if (i === l - 1 || nextCode === 32){
37941 rtlBuffer.push(chars$1[code].final);
37943 // special case for ﻼ
37944 if (code === 1604 && nextCode === 1575){
37945 rtlBuffer.push(chars$1[5000].final);
37950 if (chars$1[code].medial === ''){
37951 rtlBuffer.push(chars$1[code].final);
37953 rtlBuffer.push(chars$1[code].medial);
37957 context = (chars$1[code].medial === '') || nextCode === 32;
37960 ret += rtlBuffer.reverse().join('');
37964 function utilTagText(entity) {
37965 return entries(entity.tags).map(function(e) {
37966 return e.key + '=' + e.value;
37971 function utilEntitySelector(ids) {
37972 return ids.length ? '.' + ids.join(',.') : 'nothing';
37976 function utilEntityOrMemberSelector(ids, graph) {
37977 var s = utilEntitySelector(ids);
37979 ids.forEach(function(id) {
37980 var entity = graph.hasEntity(id);
37981 if (entity && entity.type === 'relation') {
37982 entity.members.forEach(function(member) {
37983 s += ',.' + member.id;
37992 function utilGetAllNodes(ids, graph) {
37995 ids.forEach(getNodes);
37998 function getNodes(id) {
37999 if (seen[id]) return;
38002 var entity = graph.hasEntity(id);
38003 if (!entity) return;
38005 if (entity.type === 'node') {
38006 nodes.push(entity);
38007 } else if (entity.type === 'way') {
38008 entity.nodes.forEach(getNodes);
38010 entity.members.map(function(member) { return member.id; }).forEach(getNodes);
38016 function utilDisplayName(entity) {
38017 var localizedNameKey = 'name:' + utilDetect().locale.toLowerCase().split('-')[0],
38018 name = entity.tags[localizedNameKey] || entity.tags.name || '',
38019 network = entity.tags.cycle_network || entity.tags.network;
38021 if (!name && entity.tags.ref) {
38022 name = entity.tags.ref;
38024 name = network + ' ' + name;
38032 function utilDisplayNameForPath(entity) {
38033 var name = utilDisplayName(entity);
38034 var isFirefox = utilDetect().browser.toLowerCase().indexOf('firefox') > -1;
38036 if (!isFirefox && name && rtlRegex.test(name)) {
38037 name = fixRTLTextForSvg(name);
38044 function utilDisplayType(id) {
38046 n: t('inspector.node'),
38047 w: t('inspector.way'),
38048 r: t('inspector.relation')
38053 function utilStringQs(str) {
38054 return str.split('&').reduce(function(obj, pair){
38055 var parts = pair.split('=');
38056 if (parts.length === 2) {
38057 obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
38064 function utilQsString(obj, noencode) {
38065 function softEncode(s) {
38066 // encode everything except special characters used in certain hash parameters:
38067 // "/" in map states, ":", ",", {" and "}" in background
38068 return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
38070 return Object.keys(obj).sort().map(function(key) {
38071 return encodeURIComponent(key) + '=' + (
38072 noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
38077 function utilPrefixDOMProperty(property) {
38078 var prefixes = ['webkit', 'ms', 'moz', 'o'],
38080 n = prefixes.length,
38086 property = property.substr(0, 1).toUpperCase() + property.substr(1);
38089 if (prefixes[i] + property in s)
38090 return prefixes[i] + property;
38096 function utilPrefixCSSProperty(property) {
38097 var prefixes = ['webkit', 'ms', 'Moz', 'O'],
38099 n = prefixes.length,
38100 s = document.body.style;
38102 if (property.toLowerCase() in s)
38103 return property.toLowerCase();
38106 if (prefixes[i] + property in s)
38107 return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
38113 var transformProperty;
38114 function utilSetTransform(el, x, y, scale) {
38115 var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform'),
38116 translate = utilDetect().opera ?
38117 'translate(' + x + 'px,' + y + 'px)' :
38118 'translate3d(' + x + 'px,' + y + 'px,0)';
38119 return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
38123 // Calculates Levenshtein distance between two strings
38124 // see: https://en.wikipedia.org/wiki/Levenshtein_distance
38125 // first converts the strings to lowercase and replaces diacritic marks with ascii equivalents.
38126 function utilEditDistance(a, b) {
38127 a = remove$1(a.toLowerCase());
38128 b = remove$1(b.toLowerCase());
38129 if (a.length === 0) return b.length;
38130 if (b.length === 0) return a.length;
38132 for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
38133 for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
38134 for (i = 1; i <= b.length; i++) {
38135 for (j = 1; j <= a.length; j++) {
38136 if (b.charAt(i-1) === a.charAt(j-1)) {
38137 matrix[i][j] = matrix[i-1][j-1];
38139 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
38140 Math.min(matrix[i][j-1] + 1, // insertion
38141 matrix[i-1][j] + 1)); // deletion
38145 return matrix[b.length][a.length];
38149 // a d3.mouse-alike which
38150 // 1. Only works on HTML elements, not SVG
38151 // 2. Does not cause style recalculation
38152 function utilFastMouse(container) {
38153 var rect = container.getBoundingClientRect(),
38154 rectLeft = rect.left,
38155 rectTop = rect.top,
38156 clientLeft = +container.clientLeft,
38157 clientTop = +container.clientTop;
38158 if (textDirection === 'rtl') {
38161 return function(e) {
38163 e.clientX - rectLeft - clientLeft,
38164 e.clientY - rectTop - clientTop];
38169 /* eslint-disable no-proto */
38170 var utilGetPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
38171 /* eslint-enable no-proto */
38174 function utilAsyncMap(inputs, func, callback) {
38175 var remaining = inputs.length,
38179 inputs.forEach(function(d, i) {
38180 func(d, function done(err, data) {
38184 if (!remaining) callback(errors, results);
38190 // wraps an index to an interval [0..length-1]
38191 function utilWrap(index, length) {
38193 index += Math.ceil(-index/length)*length;
38194 return index % length;
38199 * a replacement for functor
38201 * @param {*} value any value
38202 * @returns {Function} a function that returns that value or the value if it's a function
38204 function utilFunctor(value) {
38205 if (typeof value === 'function') return value;
38206 return function() {
38212 function utilNoAuto(selection$$1) {
38213 return selection$$1
38214 .attr('autocomplete', 'off')
38215 .attr('autocorrect', 'off')
38216 .attr('autocapitalize', 'off')
38217 .attr('spellcheck', 'false');
38220 // Like selection.property('value', ...), but avoids no-op value sets,
38221 // which can result in layout/repaint thrashing in some situations.
38222 function utilGetSetValue(selection, value) {
38223 function d3_selection_value(value) {
38224 function valueNull() {
38228 function valueConstant() {
38229 if (this.value !== value) {
38230 this.value = value;
38234 function valueFunction() {
38235 var x = value.apply(this, arguments);
38238 } else if (this.value !== x) {
38243 return value == null
38244 ? valueNull : (typeof value === 'function'
38245 ? valueFunction : valueConstant);
38248 if (arguments.length === 1) {
38249 return selection.property('value');
38252 return selection.each(d3_selection_value(value));
38255 // Copies a variable number of methods from source to target.
38256 function utilRebind(target, source) {
38257 var i = 1, n = arguments.length, method;
38259 target[method = arguments[i]] = d3_rebind(target, source, source[method]);
38264 // Method is assumed to be a standard D3 getter-setter:
38265 // If passed with no arguments, gets the value.
38266 // If passed with arguments, sets the value and returns the target.
38267 function d3_rebind(target, source, method) {
38268 return function() {
38269 var value = method.apply(source, arguments);
38270 return value === source ? target : value;
38274 // A per-domain session mutex backed by a cookie and dead man's
38275 // switch. If the session crashes, the mutex will auto-release
38276 // after 5 seconds.
38278 function utilSessionMutex(name) {
38283 var expires = new Date();
38284 expires.setSeconds(expires.getSeconds() + 5);
38285 document.cookie = name + '=1; expires=' + expires.toUTCString();
38288 mutex.lock = function() {
38289 if (intervalID) return true;
38290 var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
38291 if (cookie) return false;
38293 intervalID = window.setInterval(renew, 4000);
38297 mutex.unlock = function() {
38298 if (!intervalID) return;
38299 document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
38300 clearInterval(intervalID);
38304 mutex.locked = function() {
38305 return !!intervalID;
38311 function utilSuggestNames(preset, suggestions) {
38312 preset = preset.id.split('/', 2);
38316 return function(value, callback) {
38318 if (value && value.length > 2) {
38319 if (suggestions[k] && suggestions[k][v]) {
38320 for (var sugg in suggestions[k][v]) {
38321 var dist = utilEditDistance(value, sugg.substring(0, value.length));
38331 result.sort(function(a, b) {
38332 return a.dist - b.dist;
38335 result = result.slice(0,3);
38340 function utilTriggerEvent(target, type) {
38341 target.each(function() {
38342 var evt = document.createEvent('HTMLEvents');
38343 evt.initEvent(type, true, true);
38344 this.dispatchEvent(evt);
38348 function validationDeprecatedTag() {
38350 var validation = function(changes) {
38352 for (var i = 0; i < changes.created.length; i++) {
38353 var change = changes.created[i],
38354 deprecatedTags = change.deprecatedTags();
38356 if (!lodash.isEmpty(deprecatedTags)) {
38357 var tags = utilTagText({ tags: deprecatedTags });
38359 id: 'deprecated_tags',
38360 message: t('validations.deprecated_tags', { tags: tags }),
38373 function validationDisconnectedHighway() {
38376 function isDisconnectedHighway(entity, graph) {
38377 if (!entity.tags.highway) return false;
38378 if (entity.geometry(graph) !== 'line') return false;
38380 return graph.childNodes(entity)
38381 .every(function(vertex) {
38382 var parents = graph.parentWays(vertex);
38383 if (parents.length === 1) { // standalone vertex
38385 } else { // shared vertex
38386 return !vertex.tags.entrance &&
38387 parents.filter(function(parent) {
38388 return parent.tags.highway && parent !== entity;
38395 var validation = function(changes, graph) {
38397 for (var i = 0; i < changes.created.length; i++) {
38398 var entity = changes.created[i];
38400 if (isDisconnectedHighway(entity, graph)) {
38402 id: 'disconnected_highway',
38403 message: t('validations.disconnected_highway'),
38404 tooltip: t('validations.disconnected_highway_tooltip'),
38417 function validationManyDeletions() {
38418 var threshold = 100;
38420 var validation = function(changes) {
38422 if (changes.deleted.length > threshold) {
38424 id: 'many_deletions',
38425 message: t('validations.many_deletions', { n: changes.deleted.length })
38436 function validationMissingTag() {
38438 // Slightly stricter check than Entity#isUsed (#3091)
38439 function hasTags(entity, graph) {
38440 return lodash.without(Object.keys(entity.tags), 'area', 'name').length > 0 ||
38441 graph.parentRelations(entity).length > 0;
38444 var validation = function(changes, graph) {
38445 var types = ['point', 'line', 'area', 'relation'],
38448 for (var i = 0; i < changes.created.length; i++) {
38449 var change = changes.created[i],
38450 geometry = change.geometry(graph);
38452 if (types.indexOf(geometry) !== -1 && !hasTags(change, graph)) {
38455 message: t('validations.untagged_' + geometry),
38456 tooltip: t('validations.untagged_' + geometry + '_tooltip'),
38469 function validationOldMultipolygon() {
38472 return function validation(changes, graph) {
38474 for (var i = 0; i < changes.created.length; i++) {
38475 var entity = changes.created[i];
38476 var parent = osmIsSimpleMultipolygonOuterMember(entity, graph);
38479 id: 'old_multipolygon',
38480 message: t('validations.old_multipolygon'),
38481 tooltip: t('validations.old_multipolygon_tooltip'),
38490 // https://github.com/openstreetmap/josm/blob/mirror/src/org/
38491 // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
38492 function validationTagSuggestsArea() {
38494 function tagSuggestsArea(tags) {
38495 if (lodash.isEmpty(tags)) return false;
38497 var presence = ['landuse', 'amenities', 'tourism', 'shop'];
38498 for (var i = 0; i < presence.length; i++) {
38499 if (tags[presence[i]] !== undefined) {
38500 return presence[i] + '=' + tags[presence[i]];
38504 if (tags.building && tags.building === 'yes') return 'building=yes';
38508 var validation = function(changes, graph) {
38510 for (var i = 0; i < changes.created.length; i++) {
38511 var change = changes.created[i],
38512 geometry = change.geometry(graph),
38513 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
38517 id: 'tag_suggests_area',
38518 message: t('validations.tag_suggests_area', { tag: suggestion }),
38533 var Validations = Object.freeze({
38534 validationDeprecatedTag: validationDeprecatedTag,
38535 validationDisconnectedHighway: validationDisconnectedHighway,
38536 validationManyDeletions: validationManyDeletions,
38537 validationMissingTag: validationMissingTag,
38538 validationOldMultipolygon: validationOldMultipolygon,
38539 validationTagSuggestsArea: validationTagSuggestsArea
38543 iD.Difference represents the difference between two graphs.
38544 It knows how to calculate the set of entities that were
38545 created, modified, or deleted, and also contains the logic
38546 for recursively extending a difference to the complete set
38547 of entities that will require a redraw, taking into account
38548 child and parent relationships.
38550 function coreDifference(base, head) {
38556 function changed(h, b) {
38557 return h !== b && !lodash.isEqual(lodash.omit(h, 'v'), lodash.omit(b, 'v'));
38561 lodash.each(head.entities, function(h, id) {
38562 var b = base.entities[id];
38563 if (changed(h, b)) {
38564 changes[id] = {base: b, head: h};
38570 lodash.each(base.entities, function(b, id) {
38571 var h = head.entities[id];
38572 if (!changes[id] && changed(h, b)) {
38573 changes[id] = {base: b, head: h};
38579 function addParents(parents, result) {
38580 for (var i = 0; i < parents.length; i++) {
38581 var parent = parents[i];
38583 if (parent.id in result)
38586 result[parent.id] = parent;
38587 addParents(head.parentRelations(parent), result);
38592 difference.length = function() {
38597 difference.changes = function() {
38602 difference.extantIDs = function() {
38604 lodash.each(changes, function(change, id) {
38605 if (change.head) result.push(id);
38611 difference.modified = function() {
38613 lodash.each(changes, function(change) {
38614 if (change.base && change.head) result.push(change.head);
38620 difference.created = function() {
38622 lodash.each(changes, function(change) {
38623 if (!change.base && change.head) result.push(change.head);
38629 difference.deleted = function() {
38631 lodash.each(changes, function(change) {
38632 if (change.base && !change.head) result.push(change.base);
38638 difference.summary = function() {
38641 function addEntity(entity, graph, changeType) {
38642 relevant[entity.id] = {
38645 changeType: changeType
38649 function addParents(entity) {
38650 var parents = head.parentWays(entity);
38651 for (var j = parents.length - 1; j >= 0; j--) {
38652 var parent = parents[j];
38653 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
38657 lodash.each(changes, function(change) {
38658 if (change.head && change.head.geometry(head) !== 'vertex') {
38659 addEntity(change.head, head, change.base ? 'modified' : 'created');
38661 } else if (change.base && change.base.geometry(base) !== 'vertex') {
38662 addEntity(change.base, base, 'deleted');
38664 } else if (change.base && change.head) { // modified vertex
38665 var moved = !lodash.isEqual(change.base.loc, change.head.loc),
38666 retagged = !lodash.isEqual(change.base.tags, change.head.tags);
38669 addParents(change.head);
38672 if (retagged || (moved && change.head.hasInterestingTags())) {
38673 addEntity(change.head, head, 'modified');
38676 } else if (change.head && change.head.hasInterestingTags()) { // created vertex
38677 addEntity(change.head, head, 'created');
38679 } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
38680 addEntity(change.base, base, 'deleted');
38684 return values(relevant);
38688 difference.complete = function(extent$$1) {
38689 var result = {}, id, change;
38691 for (id in changes) {
38692 change = changes[id];
38694 var h = change.head,
38699 (!h || !h.intersects(extent$$1, head)) &&
38700 (!b || !b.intersects(extent$$1, base)))
38705 if (entity.type === 'way') {
38706 var nh = h ? h.nodes : [],
38707 nb = b ? b.nodes : [],
38710 diff = lodash.difference(nh, nb);
38711 for (i = 0; i < diff.length; i++) {
38712 result[diff[i]] = head.hasEntity(diff[i]);
38715 diff = lodash.difference(nb, nh);
38716 for (i = 0; i < diff.length; i++) {
38717 result[diff[i]] = head.hasEntity(diff[i]);
38721 addParents(head.parentWays(entity), result);
38722 addParents(head.parentRelations(entity), result);
38732 function coreGraph$$1(other, mutable) {
38733 if (!(this instanceof coreGraph$$1)) return new coreGraph$$1(other, mutable);
38735 if (other instanceof coreGraph$$1) {
38736 var base = other.base();
38737 this.entities = lodash.assign(Object.create(base.entities), other.entities);
38738 this._parentWays = lodash.assign(Object.create(base.parentWays), other._parentWays);
38739 this._parentRels = lodash.assign(Object.create(base.parentRels), other._parentRels);
38742 this.entities = Object.create({});
38743 this._parentWays = Object.create({});
38744 this._parentRels = Object.create({});
38745 this.rebase(other || [], [this]);
38748 this.transients = {};
38749 this._childNodes = {};
38750 this.frozen = !mutable;
38754 coreGraph$$1.prototype = {
38756 hasEntity: function(id) {
38757 return this.entities[id];
38761 entity: function(id) {
38762 var entity = this.entities[id];
38764 //https://github.com/openstreetmap/iD/issues/3973#issuecomment-307052376
38766 entity = this.entities.__proto__[id]; // eslint-disable-line no-proto
38770 throw new Error('entity ' + id + ' not found');
38776 transient: function(entity, key, fn) {
38777 var id = entity.id,
38778 transients = this.transients[id] ||
38779 (this.transients[id] = {});
38781 if (transients[key] !== undefined) {
38782 return transients[key];
38785 transients[key] = fn.call(entity);
38787 return transients[key];
38791 parentWays: function(entity) {
38792 var parents = this._parentWays[entity.id],
38796 for (var i = 0; i < parents.length; i++) {
38797 result.push(this.entity(parents[i]));
38804 isPoi: function(entity) {
38805 var parentWays = this._parentWays[entity.id];
38806 return !parentWays || parentWays.length === 0;
38810 isShared: function(entity) {
38811 var parentWays = this._parentWays[entity.id];
38812 return parentWays && parentWays.length > 1;
38816 parentRelations: function(entity) {
38817 var parents = this._parentRels[entity.id],
38821 for (var i = 0; i < parents.length; i++) {
38822 result.push(this.entity(parents[i]));
38829 childNodes: function(entity) {
38830 if (this._childNodes[entity.id]) return this._childNodes[entity.id];
38831 if (!entity.nodes) return [];
38834 for (var i = 0; i < entity.nodes.length; i++) {
38835 nodes[i] = this.entity(entity.nodes[i]);
38838 if (debug) Object.freeze(nodes);
38840 this._childNodes[entity.id] = nodes;
38841 return this._childNodes[entity.id];
38847 'entities': utilGetPrototypeOf(this.entities),
38848 'parentWays': utilGetPrototypeOf(this._parentWays),
38849 'parentRels': utilGetPrototypeOf(this._parentRels)
38854 // Unlike other graph methods, rebase mutates in place. This is because it
38855 // is used only during the history operation that merges newly downloaded
38856 // data into each state. To external consumers, it should appear as if the
38857 // graph always contained the newly downloaded data.
38858 rebase: function(entities, stack, force) {
38859 var base = this.base(),
38862 for (i = 0; i < entities.length; i++) {
38863 var entity = entities[i];
38865 if (!entity.visible || (!force && base.entities[entity.id]))
38868 // Merging data into the base graph
38869 base.entities[entity.id] = entity;
38870 this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
38872 // Restore provisionally-deleted nodes that are discovered to have an extant parent
38873 if (entity.type === 'way') {
38874 for (j = 0; j < entity.nodes.length; j++) {
38875 id = entity.nodes[j];
38876 for (k = 1; k < stack.length; k++) {
38877 var ents = stack[k].entities;
38878 if (ents.hasOwnProperty(id) && ents[id] === undefined) {
38886 for (i = 0; i < stack.length; i++) {
38887 stack[i]._updateRebased();
38892 _updateRebased: function() {
38893 var base = this.base(),
38894 i, k, child, id, keys;
38896 keys = Object.keys(this._parentWays);
38897 for (i = 0; i < keys.length; i++) {
38899 if (base.parentWays[child]) {
38900 for (k = 0; k < base.parentWays[child].length; k++) {
38901 id = base.parentWays[child][k];
38902 if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentWays[child], id)) {
38903 this._parentWays[child].push(id);
38909 keys = Object.keys(this._parentRels);
38910 for (i = 0; i < keys.length; i++) {
38912 if (base.parentRels[child]) {
38913 for (k = 0; k < base.parentRels[child].length; k++) {
38914 id = base.parentRels[child][k];
38915 if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentRels[child], id)) {
38916 this._parentRels[child].push(id);
38922 this.transients = {};
38924 // this._childNodes is not updated, under the assumption that
38925 // ways are always downloaded with their child nodes.
38929 // Updates calculated properties (parentWays, parentRels) for the specified change
38930 _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
38932 parentWays = parentWays || this._parentWays;
38933 parentRels = parentRels || this._parentRels;
38935 var type = entity && entity.type || oldentity && oldentity.type,
38936 removed, added, ways, rels, i;
38939 if (type === 'way') {
38941 // Update parentWays
38942 if (oldentity && entity) {
38943 removed = lodash.difference(oldentity.nodes, entity.nodes);
38944 added = lodash.difference(entity.nodes, oldentity.nodes);
38945 } else if (oldentity) {
38946 removed = oldentity.nodes;
38948 } else if (entity) {
38950 added = entity.nodes;
38952 for (i = 0; i < removed.length; i++) {
38953 parentWays[removed[i]] = lodash.without(parentWays[removed[i]], oldentity.id);
38955 for (i = 0; i < added.length; i++) {
38956 ways = lodash.without(parentWays[added[i]], entity.id);
38957 ways.push(entity.id);
38958 parentWays[added[i]] = ways;
38961 } else if (type === 'relation') {
38963 // Update parentRels
38964 if (oldentity && entity) {
38965 removed = lodash.difference(oldentity.members, entity.members);
38966 added = lodash.difference(entity.members, oldentity);
38967 } else if (oldentity) {
38968 removed = oldentity.members;
38970 } else if (entity) {
38972 added = entity.members;
38974 for (i = 0; i < removed.length; i++) {
38975 parentRels[removed[i].id] = lodash.without(parentRels[removed[i].id], oldentity.id);
38977 for (i = 0; i < added.length; i++) {
38978 rels = lodash.without(parentRels[added[i].id], entity.id);
38979 rels.push(entity.id);
38980 parentRels[added[i].id] = rels;
38986 replace: function(entity) {
38987 if (this.entities[entity.id] === entity)
38990 return this.update(function() {
38991 this._updateCalculated(this.entities[entity.id], entity);
38992 this.entities[entity.id] = entity;
38997 remove: function(entity) {
38998 return this.update(function() {
38999 this._updateCalculated(entity, undefined);
39000 this.entities[entity.id] = undefined;
39005 revert: function(id) {
39006 var baseEntity = this.base().entities[id],
39007 headEntity = this.entities[id];
39009 if (headEntity === baseEntity)
39012 return this.update(function() {
39013 this._updateCalculated(headEntity, baseEntity);
39014 delete this.entities[id];
39019 update: function() {
39020 var graph = this.frozen ? coreGraph$$1(this, true) : this;
39022 for (var i = 0; i < arguments.length; i++) {
39023 arguments[i].call(graph, graph);
39026 if (this.frozen) graph.frozen = true;
39032 // Obliterates any existing entities
39033 load: function(entities) {
39034 var base = this.base();
39035 this.entities = Object.create(base.entities);
39037 for (var i in entities) {
39038 this.entities[i] = entities[i];
39039 this._updateCalculated(base.entities[i], this.entities[i]);
39046 var index$10 = partialSort;
39048 // Floyd-Rivest selection algorithm:
39049 // Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
39050 // The k-th element will have the (k - left + 1)th smallest value in [left, right]
39052 function partialSort(arr, k, left, right, compare) {
39054 right = right || (arr.length - 1);
39055 compare = compare || defaultCompare;
39057 while (right > left) {
39058 if (right - left > 600) {
39059 var n = right - left + 1;
39060 var m = k - left + 1;
39061 var z = Math.log(n);
39062 var s = 0.5 * Math.exp(2 * z / 3);
39063 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
39064 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
39065 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
39066 partialSort(arr, k, newLeft, newRight, compare);
39073 swap(arr, left, k);
39074 if (compare(arr[right], t) > 0) swap(arr, left, right);
39080 while (compare(arr[i], t) < 0) i++;
39081 while (compare(arr[j], t) > 0) j--;
39084 if (compare(arr[left], t) === 0) swap(arr, left, j);
39087 swap(arr, j, right);
39090 if (j <= k) left = j + 1;
39091 if (k <= j) right = j - 1;
39095 function swap(arr, i, j) {
39101 function defaultCompare(a, b) {
39102 return a < b ? -1 : a > b ? 1 : 0;
39105 var index$9 = rbush;
39109 function rbush(maxEntries, format) {
39110 if (!(this instanceof rbush)) return new rbush(maxEntries, format);
39112 // max entries in a node is 9 by default; min node fill is 40% for best performance
39113 this._maxEntries = Math.max(4, maxEntries || 9);
39114 this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
39117 this._initFormat(format);
39123 rbush.prototype = {
39126 return this._all(this.data, []);
39129 search: function (bbox) {
39131 var node = this.data,
39133 toBBox = this.toBBox;
39135 if (!intersects$1(bbox, node)) return result;
39137 var nodesToSearch = [],
39138 i, len, child, childBBox;
39141 for (i = 0, len = node.children.length; i < len; i++) {
39143 child = node.children[i];
39144 childBBox = node.leaf ? toBBox(child) : child;
39146 if (intersects$1(bbox, childBBox)) {
39147 if (node.leaf) result.push(child);
39148 else if (contains$2(bbox, childBBox)) this._all(child, result);
39149 else nodesToSearch.push(child);
39152 node = nodesToSearch.pop();
39158 collides: function (bbox) {
39160 var node = this.data,
39161 toBBox = this.toBBox;
39163 if (!intersects$1(bbox, node)) return false;
39165 var nodesToSearch = [],
39166 i, len, child, childBBox;
39169 for (i = 0, len = node.children.length; i < len; i++) {
39171 child = node.children[i];
39172 childBBox = node.leaf ? toBBox(child) : child;
39174 if (intersects$1(bbox, childBBox)) {
39175 if (node.leaf || contains$2(bbox, childBBox)) return true;
39176 nodesToSearch.push(child);
39179 node = nodesToSearch.pop();
39185 load: function (data) {
39186 if (!(data && data.length)) return this;
39188 if (data.length < this._minEntries) {
39189 for (var i = 0, len = data.length; i < len; i++) {
39190 this.insert(data[i]);
39195 // recursively build the tree with the given data from stratch using OMT algorithm
39196 var node = this._build(data.slice(), 0, data.length - 1, 0);
39198 if (!this.data.children.length) {
39199 // save as is if tree is empty
39202 } else if (this.data.height === node.height) {
39203 // split root if trees have the same height
39204 this._splitRoot(this.data, node);
39207 if (this.data.height < node.height) {
39208 // swap trees if inserted one is bigger
39209 var tmpNode = this.data;
39214 // insert the small tree into the large tree at appropriate level
39215 this._insert(node, this.data.height - node.height - 1, true);
39221 insert: function (item) {
39222 if (item) this._insert(item, this.data.height - 1);
39226 clear: function () {
39227 this.data = createNode([]);
39231 remove: function (item, equalsFn) {
39232 if (!item) return this;
39234 var node = this.data,
39235 bbox = this.toBBox(item),
39238 i, parent, index, goingUp;
39240 // depth-first iterative tree traversal
39241 while (node || path.length) {
39243 if (!node) { // go up
39245 parent = path[path.length - 1];
39250 if (node.leaf) { // check current node
39251 index = findItem(item, node.children, equalsFn);
39253 if (index !== -1) {
39254 // item found, remove the item and condense tree upwards
39255 node.children.splice(index, 1);
39257 this._condense(path);
39262 if (!goingUp && !node.leaf && contains$2(node, bbox)) { // go down
39267 node = node.children[0];
39269 } else if (parent) { // go right
39271 node = parent.children[i];
39274 } else node = null; // nothing found
39280 toBBox: function (item) { return item; },
39282 compareMinX: compareNodeMinX,
39283 compareMinY: compareNodeMinY,
39285 toJSON: function () { return this.data; },
39287 fromJSON: function (data) {
39292 _all: function (node, result) {
39293 var nodesToSearch = [];
39295 if (node.leaf) result.push.apply(result, node.children);
39296 else nodesToSearch.push.apply(nodesToSearch, node.children);
39298 node = nodesToSearch.pop();
39303 _build: function (items, left, right, height) {
39305 var N = right - left + 1,
39306 M = this._maxEntries,
39310 // reached leaf level; return leaf
39311 node = createNode(items.slice(left, right + 1));
39312 calcBBox(node, this.toBBox);
39317 // target height of the bulk-loaded tree
39318 height = Math.ceil(Math.log(N) / Math.log(M));
39320 // target number of root entries to maximize storage utilization
39321 M = Math.ceil(N / Math.pow(M, height - 1));
39324 node = createNode([]);
39326 node.height = height;
39328 // split the items into M mostly square tiles
39330 var N2 = Math.ceil(N / M),
39331 N1 = N2 * Math.ceil(Math.sqrt(M)),
39332 i, j, right2, right3;
39334 multiSelect(items, left, right, N1, this.compareMinX);
39336 for (i = left; i <= right; i += N1) {
39338 right2 = Math.min(i + N1 - 1, right);
39340 multiSelect(items, i, right2, N2, this.compareMinY);
39342 for (j = i; j <= right2; j += N2) {
39344 right3 = Math.min(j + N2 - 1, right2);
39346 // pack each entry recursively
39347 node.children.push(this._build(items, j, right3, height - 1));
39351 calcBBox(node, this.toBBox);
39356 _chooseSubtree: function (bbox, node, level, path) {
39358 var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
39363 if (node.leaf || path.length - 1 === level) break;
39365 minArea = minEnlargement = Infinity;
39367 for (i = 0, len = node.children.length; i < len; i++) {
39368 child = node.children[i];
39369 area = bboxArea(child);
39370 enlargement = enlargedArea(bbox, child) - area;
39372 // choose entry with the least area enlargement
39373 if (enlargement < minEnlargement) {
39374 minEnlargement = enlargement;
39375 minArea = area < minArea ? area : minArea;
39376 targetNode = child;
39378 } else if (enlargement === minEnlargement) {
39379 // otherwise choose one with the smallest area
39380 if (area < minArea) {
39382 targetNode = child;
39387 node = targetNode || node.children[0];
39393 _insert: function (item, level, isNode) {
39395 var toBBox = this.toBBox,
39396 bbox = isNode ? item : toBBox(item),
39399 // find the best node for accommodating the item, saving all nodes along the path too
39400 var node = this._chooseSubtree(bbox, this.data, level, insertPath);
39402 // put the item into the node
39403 node.children.push(item);
39404 extend$1(node, bbox);
39406 // split on node overflow; propagate upwards if necessary
39407 while (level >= 0) {
39408 if (insertPath[level].children.length > this._maxEntries) {
39409 this._split(insertPath, level);
39414 // adjust bboxes along the insertion path
39415 this._adjustParentBBoxes(bbox, insertPath, level);
39418 // split overflowed node into two
39419 _split: function (insertPath, level) {
39421 var node = insertPath[level],
39422 M = node.children.length,
39423 m = this._minEntries;
39425 this._chooseSplitAxis(node, m, M);
39427 var splitIndex = this._chooseSplitIndex(node, m, M);
39429 var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
39430 newNode.height = node.height;
39431 newNode.leaf = node.leaf;
39433 calcBBox(node, this.toBBox);
39434 calcBBox(newNode, this.toBBox);
39436 if (level) insertPath[level - 1].children.push(newNode);
39437 else this._splitRoot(node, newNode);
39440 _splitRoot: function (node, newNode) {
39442 this.data = createNode([node, newNode]);
39443 this.data.height = node.height + 1;
39444 this.data.leaf = false;
39445 calcBBox(this.data, this.toBBox);
39448 _chooseSplitIndex: function (node, m, M) {
39450 var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
39452 minOverlap = minArea = Infinity;
39454 for (i = m; i <= M - m; i++) {
39455 bbox1 = distBBox(node, 0, i, this.toBBox);
39456 bbox2 = distBBox(node, i, M, this.toBBox);
39458 overlap = intersectionArea(bbox1, bbox2);
39459 area = bboxArea(bbox1) + bboxArea(bbox2);
39461 // choose distribution with minimum overlap
39462 if (overlap < minOverlap) {
39463 minOverlap = overlap;
39466 minArea = area < minArea ? area : minArea;
39468 } else if (overlap === minOverlap) {
39469 // otherwise choose distribution with minimum area
39470 if (area < minArea) {
39480 // sorts node children by the best axis for split
39481 _chooseSplitAxis: function (node, m, M) {
39483 var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
39484 compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
39485 xMargin = this._allDistMargin(node, m, M, compareMinX),
39486 yMargin = this._allDistMargin(node, m, M, compareMinY);
39488 // if total distributions margin value is minimal for x, sort by minX,
39489 // otherwise it's already sorted by minY
39490 if (xMargin < yMargin) node.children.sort(compareMinX);
39493 // total margin of all possible split distributions where each node is at least m full
39494 _allDistMargin: function (node, m, M, compare) {
39496 node.children.sort(compare);
39498 var toBBox = this.toBBox,
39499 leftBBox = distBBox(node, 0, m, toBBox),
39500 rightBBox = distBBox(node, M - m, M, toBBox),
39501 margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
39504 for (i = m; i < M - m; i++) {
39505 child = node.children[i];
39506 extend$1(leftBBox, node.leaf ? toBBox(child) : child);
39507 margin += bboxMargin(leftBBox);
39510 for (i = M - m - 1; i >= m; i--) {
39511 child = node.children[i];
39512 extend$1(rightBBox, node.leaf ? toBBox(child) : child);
39513 margin += bboxMargin(rightBBox);
39519 _adjustParentBBoxes: function (bbox, path, level) {
39520 // adjust bboxes along the given tree path
39521 for (var i = level; i >= 0; i--) {
39522 extend$1(path[i], bbox);
39526 _condense: function (path) {
39527 // go through the path, removing empty nodes and updating bboxes
39528 for (var i = path.length - 1, siblings; i >= 0; i--) {
39529 if (path[i].children.length === 0) {
39531 siblings = path[i - 1].children;
39532 siblings.splice(siblings.indexOf(path[i]), 1);
39534 } else this.clear();
39536 } else calcBBox(path[i], this.toBBox);
39540 _initFormat: function (format) {
39541 // data format (minX, minY, maxX, maxY accessors)
39543 // uses eval-type function compilation instead of just accepting a toBBox function
39544 // because the algorithms are very sensitive to sorting functions performance,
39545 // so they should be dead simple and without inner calls
39547 var compareArr = ['return a', ' - b', ';'];
39549 this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
39550 this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
39552 this.toBBox = new Function('a',
39553 'return {minX: a' + format[0] +
39554 ', minY: a' + format[1] +
39555 ', maxX: a' + format[2] +
39556 ', maxY: a' + format[3] + '};');
39560 function findItem(item, items, equalsFn) {
39561 if (!equalsFn) return items.indexOf(item);
39563 for (var i = 0; i < items.length; i++) {
39564 if (equalsFn(item, items[i])) return i;
39569 // calculate node's bbox from bboxes of its children
39570 function calcBBox(node, toBBox) {
39571 distBBox(node, 0, node.children.length, toBBox, node);
39574 // min bounding rectangle of node children from k to p-1
39575 function distBBox(node, k, p, toBBox, destNode) {
39576 if (!destNode) destNode = createNode(null);
39577 destNode.minX = Infinity;
39578 destNode.minY = Infinity;
39579 destNode.maxX = -Infinity;
39580 destNode.maxY = -Infinity;
39582 for (var i = k, child; i < p; i++) {
39583 child = node.children[i];
39584 extend$1(destNode, node.leaf ? toBBox(child) : child);
39590 function extend$1(a, b) {
39591 a.minX = Math.min(a.minX, b.minX);
39592 a.minY = Math.min(a.minY, b.minY);
39593 a.maxX = Math.max(a.maxX, b.maxX);
39594 a.maxY = Math.max(a.maxY, b.maxY);
39598 function compareNodeMinX(a, b) { return a.minX - b.minX; }
39599 function compareNodeMinY(a, b) { return a.minY - b.minY; }
39601 function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
39602 function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
39604 function enlargedArea(a, b) {
39605 return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
39606 (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
39609 function intersectionArea(a, b) {
39610 var minX = Math.max(a.minX, b.minX),
39611 minY = Math.max(a.minY, b.minY),
39612 maxX = Math.min(a.maxX, b.maxX),
39613 maxY = Math.min(a.maxY, b.maxY);
39615 return Math.max(0, maxX - minX) *
39616 Math.max(0, maxY - minY);
39619 function contains$2(a, b) {
39620 return a.minX <= b.minX &&
39621 a.minY <= b.minY &&
39622 b.maxX <= a.maxX &&
39626 function intersects$1(a, b) {
39627 return b.minX <= a.maxX &&
39628 b.minY <= a.maxY &&
39629 b.maxX >= a.minX &&
39633 function createNode(children) {
39635 children: children,
39645 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
39646 // combines selection algorithm with binary divide & conquer approach
39648 function multiSelect(arr, left, right, n, compare) {
39649 var stack = [left, right],
39652 while (stack.length) {
39653 right = stack.pop();
39654 left = stack.pop();
39656 if (right - left <= n) continue;
39658 mid = left + Math.ceil((right - left) / n / 2) * n;
39659 index$10(arr, mid, left, right, compare);
39661 stack.push(left, mid, mid, right);
39665 function coreTree(head) {
39666 var rtree = index$9(),
39671 function entityBBox(entity) {
39672 var bbox = entity.extent(head).bbox();
39673 bbox.id = entity.id;
39674 bboxes[entity.id] = bbox;
39679 function updateParents(entity, insertions, memo) {
39680 head.parentWays(entity).forEach(function(way) {
39681 if (bboxes[way.id]) {
39682 rtree.remove(bboxes[way.id]);
39683 insertions[way.id] = way;
39685 updateParents(way, insertions, memo);
39688 head.parentRelations(entity).forEach(function(relation) {
39689 if (memo[entity.id]) return;
39690 memo[entity.id] = true;
39691 if (bboxes[relation.id]) {
39692 rtree.remove(bboxes[relation.id]);
39693 insertions[relation.id] = relation;
39695 updateParents(relation, insertions, memo);
39700 tree.rebase = function(entities, force) {
39701 var insertions = {};
39703 for (var i = 0; i < entities.length; i++) {
39704 var entity = entities[i];
39706 if (!entity.visible)
39709 if (head.entities.hasOwnProperty(entity.id) || bboxes[entity.id]) {
39712 } else if (bboxes[entity.id]) {
39713 rtree.remove(bboxes[entity.id]);
39717 insertions[entity.id] = entity;
39718 updateParents(entity, insertions, {});
39721 rtree.load(lodash.map(insertions, entityBBox));
39727 tree.intersects = function(extent, graph) {
39728 if (graph !== head) {
39729 var diff = coreDifference(head, graph),
39734 diff.deleted().forEach(function(entity) {
39735 rtree.remove(bboxes[entity.id]);
39736 delete bboxes[entity.id];
39739 diff.modified().forEach(function(entity) {
39740 rtree.remove(bboxes[entity.id]);
39741 insertions[entity.id] = entity;
39742 updateParents(entity, insertions, {});
39745 diff.created().forEach(function(entity) {
39746 insertions[entity.id] = entity;
39749 rtree.load(lodash.map(insertions, entityBBox));
39752 return rtree.search(extent.bbox()).map(function(bbox) {
39753 return head.entity(bbox.id);
39762 * This code is licensed under the MIT license.
39764 * Copyright © 2013, iD authors.
39766 * Portions copyright © 2011, Keith Cirkel
39767 * See https://github.com/keithamus/jwerty
39770 function d3keybinding(namespace$$1) {
39774 function testBindings(isCapturing) {
39775 var didMatch = false,
39778 // Most key shortcuts will accept either lower or uppercase ('h' or 'H'),
39779 // so we don't strictly match on the shift key, but we prioritize
39780 // shifted bindings first, and fallback to unshifted only if no match.
39781 // (This lets us differentiate between '←'/'⇧←' or '⌘Z'/'⌘⇧Z')
39783 // priority match shifted bindings first
39784 for (i = 0; i < bindings.length; i++) {
39785 binding = bindings[i];
39786 if (!binding.event.modifiers.shiftKey) continue; // no shift
39787 if (!!binding.capture !== isCapturing) continue;
39788 if (matches(binding, true)) {
39789 binding.callback();
39794 // then unshifted bindings
39795 if (didMatch) return;
39796 for (i = 0; i < bindings.length; i++) {
39797 binding = bindings[i];
39798 if (binding.event.modifiers.shiftKey) continue; // shift
39799 if (!!binding.capture !== isCapturing) continue;
39800 if (matches(binding, false)) {
39801 binding.callback();
39806 function matches(binding, testShift) {
39807 var event$$1 = event;
39808 if (event$$1.key !== undefined) {
39809 if (binding.event.key === undefined) {
39811 } else if (lodash.isArray(binding.event.key)) {
39812 if (binding.event.key.map(function(s) { return s.toLowerCase(); }).indexOf(event$$1.key.toLowerCase()) === -1)
39815 if (event$$1.key.toLowerCase() !== binding.event.key.toLowerCase())
39819 // check keycodes if browser doesn't support KeyboardEvent.key
39820 if (event$$1.keyCode !== binding.event.keyCode)
39824 // test modifier keys
39825 if (!(event$$1.ctrlKey && event$$1.altKey)) { // if both are set, assume AltGr and skip it - #4096
39826 if (event$$1.ctrlKey !== binding.event.modifiers.ctrlKey) return false;
39827 if (event$$1.altKey !== binding.event.modifiers.altKey) return false;
39829 if (event$$1.metaKey !== binding.event.modifiers.metaKey) return false;
39830 if (testShift && event$$1.shiftKey !== binding.event.modifiers.shiftKey) return false;
39837 function capture() {
39838 testBindings(true);
39842 function bubble() {
39843 var tagName = select(event.target).node().tagName;
39844 if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
39847 testBindings(false);
39851 function keybinding(selection$$1) {
39852 selection$$1 = selection$$1 || select(document);
39853 selection$$1.on('keydown.capture' + namespace$$1, capture, true);
39854 selection$$1.on('keydown.bubble' + namespace$$1, bubble, false);
39859 keybinding.off = function(selection$$1) {
39861 selection$$1 = selection$$1 || select(document);
39862 selection$$1.on('keydown.capture' + namespace$$1, null);
39863 selection$$1.on('keydown.bubble' + namespace$$1, null);
39868 keybinding.on = function(codes, callback, capture) {
39869 var arr = [].concat(codes);
39870 for (var i = 0; i < arr.length; i++) {
39875 keyCode: 0, // only for browsers that don't support KeyboardEvent.key
39887 code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
39889 for (var j = 0; j < code.length; j++) {
39890 // Normalise matching errors
39891 if (code[j] === '++') code[j] = '+';
39893 if (code[j] in d3keybinding.modifierCodes) {
39894 binding.event.modifiers[d3keybinding.modifierProperties[d3keybinding.modifierCodes[code[j]]]] = true;
39896 binding.event.key = d3keybinding.keys[code[j]] || code[j];
39897 if (code[j] in d3keybinding.keyCodes) {
39898 binding.event.keyCode = d3keybinding.keyCodes[code[j]];
39903 bindings.push(binding);
39913 d3keybinding.modifierCodes = {
39915 '⇧': 16, shift: 16,
39916 // CTRL key, on Mac: ⌃
39918 // ALT key, on Mac: ⌥ (Alt)
39919 '⌥': 18, alt: 18, option: 18,
39920 // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
39921 '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
39924 d3keybinding.modifierProperties = {
39931 d3keybinding.keys = {
39932 // Backspace key, on Mac: ⌫ (Backspace)
39933 '⌫': 'Backspace', backspace: 'Backspace',
39934 // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
39935 '⇥': 'Tab', '⇆': 'Tab', tab: 'Tab',
39937 '↩': 'Enter', 'return': 'Enter', enter: 'Enter', '⌅': 'Enter',
39939 'pause': 'Pause', 'pause-break': 'Pause',
39940 // Caps Lock key, ⇪
39941 '⇪': 'CapsLock', caps: 'CapsLock', 'caps-lock': 'CapsLock',
39942 // Escape key, on Mac: ⎋, on Windows: Esc
39943 '⎋': ['Escape', 'Esc'], escape: ['Escape', 'Esc'], esc: ['Escape', 'Esc'],
39945 space: [' ', 'Spacebar'],
39946 // Page-Up key, or pgup, on Mac: ↖
39947 '↖': 'PageUp', pgup: 'PageUp', 'page-up': 'PageUp',
39948 // Page-Down key, or pgdown, on Mac: ↘
39949 '↘': 'PageDown', pgdown: 'PageDown', 'page-down': 'PageDown',
39950 // END key, on Mac: ⇟
39951 '⇟': 'End', end: 'End',
39952 // HOME key, on Mac: ⇞
39953 '⇞': 'Home', home: 'Home',
39954 // Insert key, or ins
39955 ins: 'Insert', insert: 'Insert',
39956 // Delete key, on Mac: ⌦ (Delete)
39957 '⌦': ['Delete', 'Del'], del: ['Delete', 'Del'], 'delete': ['Delete', 'Del'],
39958 // Left Arrow Key, or ←
39959 '←': ['ArrowLeft', 'Left'], left: ['ArrowLeft', 'Left'], 'arrow-left': ['ArrowLeft', 'Left'],
39960 // Up Arrow Key, or ↑
39961 '↑': ['ArrowUp', 'Up'], up: ['ArrowUp', 'Up'], 'arrow-up': ['ArrowUp', 'Up'],
39962 // Right Arrow Key, or →
39963 '→': ['ArrowRight', 'Right'], right: ['ArrowRight', 'Right'], 'arrow-right': ['ArrowRight', 'Right'],
39964 // Up Arrow Key, or ↓
39965 '↓': ['ArrowDown', 'Down'], down: ['ArrowDown', 'Down'], 'arrow-down': ['ArrowDown', 'Down'],
39966 // odities, stuff for backward compatibility (browsers and code):
39967 // Num-Multiply, or *
39968 '*': ['*', 'Multiply'], star: ['*', 'Multiply'], asterisk: ['*', 'Multiply'], multiply: ['*', 'Multiply'],
39970 '+': ['+', 'Add'], 'plus': ['+', 'Add'],
39971 // Num-Subtract, or -
39972 '-': ['-', 'Subtract'], subtract: ['-', 'Subtract'], 'dash': ['-', 'Subtract'],
39979 // Period, or ., or full-stop
39980 period: '.', 'full-stop': '.',
39981 // Slash, or /, or forward-slash
39982 slash: '/', 'forward-slash': '/',
39983 // Tick, or `, or back-quote
39984 tick: '`', 'back-quote': '`',
39985 // Open bracket, or [
39986 'open-bracket': '[',
39987 // Back slash, or \
39988 'back-slash': '\\',
39989 // Close backet, or ]
39990 'close-bracket': ']',
39991 // Apostrophe, or Quote, or '
39992 quote: '\'', apostrophe: '\'',
40032 d3keybinding.keyCodes = {
40033 // Backspace key, on Mac: ⌫ (Backspace)
40034 '⌫': 8, backspace: 8,
40035 // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
40036 '⇥': 9, '⇆': 9, tab: 9,
40038 '↩': 13, 'return': 13, enter: 13, '⌅': 13,
40040 'pause': 19, 'pause-break': 19,
40041 // Caps Lock key, ⇪
40042 '⇪': 20, caps: 20, 'caps-lock': 20,
40043 // Escape key, on Mac: ⎋, on Windows: Esc
40044 '⎋': 27, escape: 27, esc: 27,
40047 // Page-Up key, or pgup, on Mac: ↖
40048 '↖': 33, pgup: 33, 'page-up': 33,
40049 // Page-Down key, or pgdown, on Mac: ↘
40050 '↘': 34, pgdown: 34, 'page-down': 34,
40051 // END key, on Mac: ⇟
40053 // HOME key, on Mac: ⇞
40055 // Insert key, or ins
40056 ins: 45, insert: 45,
40057 // Delete key, on Mac: ⌦ (Delete)
40058 '⌦': 46, del: 46, 'delete': 46,
40059 // Left Arrow Key, or ←
40060 '←': 37, left: 37, 'arrow-left': 37,
40061 // Up Arrow Key, or ↑
40062 '↑': 38, up: 38, 'arrow-up': 38,
40063 // Right Arrow Key, or →
40064 '→': 39, right: 39, 'arrow-right': 39,
40065 // Up Arrow Key, or ↓
40066 '↓': 40, down: 40, 'arrow-down': 40,
40067 // odities, printing characters that come out wrong:
40070 // Num-Multiply, or *
40071 '*': 106, star: 106, asterisk: 106, multiply: 106,
40073 '+': 107, 'plus': 107,
40074 // Num-Subtract, or -
40075 '-': 109, subtract: 109,
40081 ';': 186, semicolon: 186,
40083 '=': 187, 'equals': 187,
40085 ',': 188, comma: 188,
40086 // Dash / Underscore key
40088 // Period, or ., or full-stop
40089 '.': 190, period: 190, 'full-stop': 190,
40090 // Slash, or /, or forward-slash
40091 '/': 191, slash: 191, 'forward-slash': 191,
40092 // Tick, or `, or back-quote
40093 '`': 192, tick: 192, 'back-quote': 192,
40094 // Open bracket, or [
40095 '[': 219, 'open-bracket': 219,
40096 // Back slash, or \
40097 '\\': 220, 'back-slash': 220,
40098 // Close backet, or ]
40099 ']': 221, 'close-bracket': 221,
40100 // Apostrophe, or Quote, or '
40101 '\'': 222, quote: 222, apostrophe: 222
40107 while (++i$1 < 106) {
40108 d3keybinding.keyCodes['num-' + n] = i$1;
40114 while (++i$1 < 58) {
40115 d3keybinding.keyCodes[n] = i$1;
40121 while (++i$1 < 136) {
40122 d3keybinding.keyCodes['f' + n] = i$1;
40128 while (++i$1 < 91) {
40129 d3keybinding.keyCodes[String.fromCharCode(i$1).toLowerCase()] = i$1;
40132 function tooltip() {
40133 var tooltip = function(selection$$1) {
40134 selection$$1.each(setup);
40136 animation = utilFunctor(false),
40137 html$$1 = utilFunctor(false),
40138 title = function() {
40139 var title = this.getAttribute('data-original-title');
40143 title = this.getAttribute('title');
40144 this.removeAttribute('title');
40145 this.setAttribute('data-original-title', title);
40149 over = 'mouseenter.tooltip',
40150 out = 'mouseleave.tooltip',
40151 placement = utilFunctor('top');
40154 tooltip.title = function(_) {
40155 if (arguments.length) {
40156 title = utilFunctor(_);
40164 tooltip.html = function(_) {
40165 if (arguments.length) {
40166 html$$1 = utilFunctor(_);
40174 tooltip.placement = function(_) {
40175 if (arguments.length) {
40176 placement = utilFunctor(_);
40184 tooltip.show = function(selection$$1) {
40185 selection$$1.each(show);
40189 tooltip.hide = function(selection$$1) {
40190 selection$$1.each(hide);
40194 tooltip.toggle = function(selection$$1) {
40195 selection$$1.each(toggle);
40199 tooltip.destroy = function(selection$$1) {
40203 .attr('title', function() {
40204 return this.getAttribute('data-original-title') || this.getAttribute('title');
40206 .attr('data-original-title', null)
40207 .selectAll('.tooltip')
40213 var root = select(this),
40214 animate = animation.apply(this, arguments),
40215 tip = root.selectAll('.tooltip').data([0]);
40217 var enter = tip.enter()
40219 .attr('class', 'tooltip');
40223 .attr('class', 'tooltip-arrow');
40227 .attr('class', 'tooltip-inner');
40233 tip.classed('fade', true);
40236 var place = placement.apply(this, arguments);
40237 tip.classed(place, true);
40239 root.on(over, show);
40240 root.on(out, hide);
40245 var root = select(this),
40246 content = title.apply(this, arguments),
40247 tip = root.selectAll('.tooltip')
40248 .classed('in', true),
40249 markup = html$$1.apply(this, arguments);
40251 tip.selectAll('.tooltip-inner')[markup ? 'html' : 'text'](content);
40252 var place = placement.apply(this, arguments),
40253 outer = getPosition(root.node()),
40254 inner = getPosition(tip.node()),
40259 pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
40262 pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
40265 pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
40268 pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
40273 tip.style('left', ~~pos.x + 'px').style('top', ~~pos.y + 'px');
40275 tip.style('left', null).style('top', null);
40278 this.tooltipVisible = true;
40283 select(this).selectAll('.tooltip')
40284 .classed('in', false);
40286 this.tooltipVisible = false;
40290 function toggle() {
40291 if (this.tooltipVisible) {
40292 hide.apply(this, arguments);
40294 show.apply(this, arguments);
40302 function getPosition(node) {
40303 var mode = select(node).style('position');
40304 if (mode === 'absolute' || mode === 'static') {
40306 x: node.offsetLeft,
40308 w: node.offsetWidth,
40309 h: node.offsetHeight
40315 w: node.offsetWidth,
40316 h: node.offsetHeight
40321 function svgAreas$$1(projection$$1, context) {
40322 // Patterns only work in Firefox when set directly on element.
40323 // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
40326 cemetery: 'cemetery',
40327 construction: 'construction',
40329 farmland: 'farmland',
40330 grave_yard: 'cemetery',
40332 military: 'construction',
40333 orchard: 'orchard',
40336 wetland: 'wetland',
40339 var patternKeys = ['landuse', 'natural', 'amenity'];
40342 function setPattern(d) {
40343 for (var i = 0; i < patternKeys.length; i++) {
40344 if (d.tags.building && d.tags.building !== 'no') continue;
40346 if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
40347 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
40351 this.style.fill = this.style.stroke = '';
40355 return function drawAreas(selection$$1, graph, entities, filter) {
40356 var path$$1 = svgPath(projection$$1, graph, true),
40360 for (var i = 0; i < entities.length; i++) {
40361 var entity = entities[i];
40362 if (entity.geometry(graph) !== 'area') continue;
40364 multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph);
40365 if (multipolygon) {
40366 areas[multipolygon.id] = {
40367 entity: multipolygon.mergeTags(entity.tags),
40368 area: Math.abs(entity.area(graph))
40370 } else if (!areas[entity.id]) {
40371 areas[entity.id] = {
40373 area: Math.abs(entity.area(graph))
40378 areas = values(areas).filter(function hasPath(a) { return path$$1(a.entity); });
40379 areas.sort(function areaSort(a, b) { return b.area - a.area; });
40380 areas = lodash.map(areas, 'entity');
40382 var strokes = areas.filter(function(area$$1) {
40383 return area$$1.type === 'way';
40393 var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath')
40395 .data(data.clip, osmEntity$$1.key);
40400 var clipPathsEnter = clipPaths.enter()
40401 .append('clipPath')
40402 .attr('class', 'clipPath')
40403 .attr('id', function(entity) { return entity.id + '-clippath'; });
40408 clipPaths.merge(clipPathsEnter)
40410 .attr('d', path$$1);
40413 var layer = selection$$1.selectAll('.layer-areas');
40415 var areagroup = layer
40416 .selectAll('g.areagroup')
40417 .data(['fill', 'shadow', 'stroke']);
40419 areagroup = areagroup.enter()
40421 .attr('class', function(d) { return 'areagroup area-' + d; })
40424 var paths = areagroup
40427 .data(function(layer) { return data[layer]; }, osmEntity$$1.key);
40432 var fills = selection$$1.selectAll('.area-fill path.area').nodes();
40434 var bisect = bisector(function(node) {
40435 return -node.__data__.area(graph);
40438 function sortedByArea(entity) {
40439 if (this._parent.__data__ === 'fill') {
40440 return fills[bisect(fills, -entity.area(graph))];
40444 paths = paths.enter()
40445 .insert('path', sortedByArea)
40447 .each(function(entity) {
40448 var layer = this.parentNode.__data__;
40450 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
40452 if (layer === 'fill') {
40453 this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
40454 setPattern.apply(this, arguments);
40457 .call(svgTagClasses())
40458 .attr('d', path$$1);
40462 function svgDebug(projection$$1, context) {
40464 function multipolygons(imagery) {
40465 return imagery.map(function(data$$1) {
40467 type: 'MultiPolygon',
40468 coordinates: [ data$$1.polygon ]
40473 function drawDebug(selection$$1) {
40474 var showsTile = context.getDebug('tile'),
40475 showsCollision = context.getDebug('collision'),
40476 showsImagery = context.getDebug('imagery'),
40477 showsImperial = context.getDebug('imperial'),
40478 showsDriveLeft = context.getDebug('driveLeft'),
40479 path$$1 = index$4(projection$$1);
40482 var debugData = [];
40484 debugData.push({ class: 'red', label: 'tile' });
40486 if (showsCollision) {
40487 debugData.push({ class: 'yellow', label: 'collision' });
40489 if (showsImagery) {
40490 debugData.push({ class: 'orange', label: 'imagery' });
40492 if (showsImperial) {
40493 debugData.push({ class: 'cyan', label: 'imperial' });
40495 if (showsDriveLeft) {
40496 debugData.push({ class: 'green', label: 'driveLeft' });
40500 var legend = select('#content')
40501 .selectAll('.debug-legend')
40502 .data(debugData.length ? [0] : []);
40507 legend = legend.enter()
40509 .attr('class', 'fillD debug-legend')
40513 var legendItems = legend.selectAll('.debug-legend-item')
40514 .data(debugData, function(d) { return d.label; });
40519 legendItems.enter()
40521 .attr('class', function(d) { return 'debug-legend-item ' + d.class; })
40522 .text(function(d) { return d.label; });
40525 var layer = selection$$1.selectAll('.layer-debug')
40526 .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
40531 layer = layer.enter()
40533 .attr('class', 'layer-debug')
40537 var extent$$1 = context.map().extent(),
40538 dataImagery = data.imagery || [],
40539 availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) {
40540 if (!source.polygon) return false;
40541 return source.polygon.some(function(polygon) {
40542 return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
40546 var imagery = layer.selectAll('path.debug-imagery')
40547 .data(showsImagery ? availableImagery : []);
40554 .attr('class', 'debug-imagery debug orange');
40557 var imperial = layer
40558 .selectAll('path.debug-imperial')
40559 .data(showsImperial ? [dataImperial] : []);
40566 .attr('class', 'debug-imperial debug cyan');
40569 var driveLeft = layer
40570 .selectAll('path.debug-drive-left')
40571 .data(showsDriveLeft ? [dataDriveLeft] : []);
40578 .attr('class', 'debug-drive-left debug green');
40582 layer.selectAll('path')
40583 .attr('d', path$$1);
40587 // This looks strange because `enabled` methods on other layers are
40588 // chainable getter/setters, and this one is just a getter.
40589 drawDebug.enabled = function() {
40590 if (!arguments.length) {
40591 return context.getDebug('tile') ||
40592 context.getDebug('collision') ||
40593 context.getDebug('imagery') ||
40594 context.getDebug('imperial') ||
40595 context.getDebug('driveLeft');
40606 A standalone SVG element that contains only a `defs` sub-element. To be
40607 used once globally, since defs IDs must be unique within a document.
40609 function svgDefs(context) {
40611 function SVGSpriteDefinition(id, href) {
40612 return function(defs) {
40614 .mimeType('image/svg+xml')
40615 .response(function(xhr) { return xhr.responseXML; })
40616 .get(function(err, svg) {
40618 defs.node().appendChild(
40619 select(svg.documentElement).attr('id', id).node()
40626 return function drawDefs(selection$$1) {
40627 var defs = selection$$1.append('defs');
40630 defs.append('marker')
40631 .attr('id', 'oneway-marker')
40632 .attr('viewBox', '0 0 10 10')
40635 .attr('markerWidth', 2)
40636 .attr('markerHeight', 2)
40637 .attr('markerUnits', 'strokeWidth')
40638 .attr('orient', 'auto')
40641 .attr('class', 'oneway')
40642 .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')
40643 .attr('stroke', 'none')
40644 .attr('fill', '#000')
40645 .attr('opacity', '0.75');
40648 var patterns = defs.selectAll('pattern')
40650 // pattern name, pattern image name
40651 ['wetland', 'wetland'],
40652 ['construction', 'construction'],
40653 ['cemetery', 'cemetery'],
40654 ['orchard', 'orchard'],
40655 ['farmland', 'farmland'],
40662 .attr('id', function (d) {
40663 return 'pattern-' + d[0];
40666 .attr('height', 32)
40667 .attr('patternUnits', 'userSpaceOnUse');
40669 patterns.append('rect')
40673 .attr('height', 32)
40674 .attr('class', function (d) {
40675 return 'pattern-color-' + d[0];
40678 patterns.append('image')
40682 .attr('height', 32)
40683 .attr('xlink:href', function (d) {
40684 return context.imagePath('pattern/' + d[1] + '.png');
40689 .data([12, 18, 20, 32, 45])
40691 .append('clipPath')
40692 .attr('id', function (d) {
40693 return 'clip-square-' + d;
40698 .attr('width', function (d) {
40701 .attr('height', function (d) {
40705 defs.call(SVGSpriteDefinition(
40707 context.imagePath('iD-sprite.svg')));
40709 defs.call(SVGSpriteDefinition(
40711 context.imagePath('maki-sprite.svg')));
40715 //[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]
40716 //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
40717 //[5] Name ::= NameStartChar (NameChar)*
40718 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
40719 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
40720 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
40721 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
40722 //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(',')
40724 //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
40725 //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
40726 var S_TAG = 0;//tag name offerring
40727 var S_ATTR = 1;//attr name offerring
40728 var S_ATTR_SPACE=2;//attr name end and space offer
40729 var S_EQ = 3;//=space?
40730 var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
40731 var S_ATTR_END = 5;//attr value end and no space(quot end)
40732 var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
40733 var S_TAG_CLOSE = 7;//closed el<el />
40735 function XMLReader(){
40739 XMLReader.prototype = {
40740 parse:function(source,defaultNSMap,entityMap){
40741 var domBuilder = this.domBuilder;
40742 domBuilder.startDocument();
40743 _copy(defaultNSMap ,defaultNSMap = {});
40744 parse(source,defaultNSMap,entityMap,
40745 domBuilder,this.errorHandler);
40746 domBuilder.endDocument();
40749 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
40750 function fixedFromCharCode(code) {
40751 // String.prototype.fromCharCode does not supports
40752 // > 2 bytes unicode chars directly
40753 if (code > 0xffff) {
40755 var surrogate1 = 0xd800 + (code >> 10)
40756 , surrogate2 = 0xdc00 + (code & 0x3ff);
40758 return String.fromCharCode(surrogate1, surrogate2);
40760 return String.fromCharCode(code);
40763 function entityReplacer(a){
40764 var k = a.slice(1,-1);
40765 if(k in entityMap){
40766 return entityMap[k];
40767 }else if(k.charAt(0) === '#'){
40768 return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
40770 errorHandler.error('entity not found:'+a);
40774 function appendText(end){//has some bugs
40776 var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
40777 locator&&position(start);
40778 domBuilder.characters(xt,0,end-start);
40782 function position(p,m){
40783 while(p>=lineEnd && (m = linePattern.exec(source))){
40784 lineStart = m.index;
40785 lineEnd = lineStart + m[0].length;
40786 locator.lineNumber++;
40787 //console.log('line++:',locator,startPos,endPos)
40789 locator.columnNumber = p-lineStart+1;
40793 var linePattern = /.*(?:\r\n?|\n)|.*$/g;
40794 var locator = domBuilder.locator;
40796 var parseStack = [{currentNSMap:defaultNSMapCopy}];
40801 var tagStart = source.indexOf('<',start);
40803 if(!source.substr(start).match(/^\s*$/)){
40804 var doc = domBuilder.doc;
40805 var text = doc.createTextNode(source.substr(start));
40806 doc.appendChild(text);
40807 domBuilder.currentElement = text;
40811 if(tagStart>start){
40812 appendText(tagStart);
40814 switch(source.charAt(tagStart+1)){
40816 var end = source.indexOf('>',tagStart+3);
40817 var tagName = source.substring(tagStart+2,end);
40818 var config = parseStack.pop();
40821 tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
40822 //console.error('#@@@@@@'+tagName)
40823 errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
40824 end = tagStart+1+tagName.length;
40825 }else if(tagName.match(/\s</)){
40826 tagName = tagName.replace(/[\s<].*/,'');
40827 errorHandler.error("end tag name: "+tagName+' maybe not complete');
40828 end = tagStart+1+tagName.length;
40830 //console.error(parseStack.length,parseStack)
40831 //console.error(config);
40832 var localNSMap = config.localNSMap;
40833 var endMatch = config.tagName == tagName;
40834 var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase();
40835 if(endIgnoreCaseMach){
40836 domBuilder.endElement(config.uri,config.localName,tagName);
40838 for(var prefix in localNSMap){
40839 domBuilder.endPrefixMapping(prefix) ;
40843 errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
40846 parseStack.push(config);
40852 case '?':// <?...?>
40853 locator&&position(tagStart);
40854 end = parseInstruction(source,tagStart,domBuilder);
40856 case '!':// <!doctype,<![CDATA,<!--
40857 locator&&position(tagStart);
40858 end = parseDCC(source,tagStart,domBuilder,errorHandler);
40861 locator&&position(tagStart);
40862 var el = new ElementAttributes();
40863 var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
40865 var end = parseElementStartPart(source,tagStart,el,currentNSMap,entityReplacer,errorHandler);
40866 var len = el.length;
40869 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
40871 if(!entityMap.nbsp){
40872 errorHandler.warning('unclosed xml attribute');
40875 if(locator && len){
40876 var locator2 = copyLocator(locator,{});
40877 //try{//attribute position fixed
40878 for(var i = 0;i<len;i++){
40880 position(a.offset);
40881 a.locator = copyLocator(locator,{});
40883 //}catch(e){console.error('@@@@@'+e)}
40884 domBuilder.locator = locator2;
40885 if(appendElement(el,domBuilder,currentNSMap)){
40886 parseStack.push(el);
40888 domBuilder.locator = locator;
40890 if(appendElement(el,domBuilder,currentNSMap)){
40891 parseStack.push(el);
40897 if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
40898 end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder);
40904 errorHandler.error('element parse error: '+e);
40905 //errorHandler.error('element parse error: '+e);
40912 //TODO: 这里有可能sax回退,有位置错误风险
40913 appendText(Math.max(tagStart,start)+1);
40917 function copyLocator(f,t){
40918 t.lineNumber = f.lineNumber;
40919 t.columnNumber = f.columnNumber;
40924 * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
40925 * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40927 function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
40931 var s = S_TAG;//status
40933 var c = source.charAt(p);
40936 if(s === S_ATTR){//attrName
40937 attrName = source.slice(start,p);
40939 }else if(s === S_ATTR_SPACE){
40942 //fatalError: equal must after attrName or space after attrName
40943 throw new Error('attribute equal must after attrName');
40948 if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
40951 errorHandler.warning('attribute value must after "="');
40952 attrName = source.slice(start,p);
40955 p = source.indexOf(c,start);
40957 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40958 el.add(attrName,value,start-1);
40961 //fatalError: no end quot match
40962 throw new Error('attribute value no end \''+c+'\' match');
40964 }else if(s == S_ATTR_NOQUOT_VALUE){
40965 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40966 //console.log(attrName,value,start,p)
40967 el.add(attrName,value,start);
40969 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
40973 //fatalError: no equal before
40974 throw new Error('attribute value must after "="');
40980 el.setTagName(source.slice(start,p));
40986 case S_ATTR_NOQUOT_VALUE:
40992 throw new Error("attribute invalid close char('/')")
40995 case ''://end document
40996 //throw new Error('unexpected end of input')
40997 errorHandler.error('unexpected end of input');
40999 el.setTagName(source.slice(start,p));
41005 el.setTagName(source.slice(start,p));
41010 case S_ATTR_NOQUOT_VALUE://Compatible state
41012 value = source.slice(start,p);
41013 if(value.slice(-1) === '/'){
41015 value = value.slice(0,-1);
41018 if(s === S_ATTR_SPACE){
41021 if(s == S_ATTR_NOQUOT_VALUE){
41022 errorHandler.warning('attribute "'+value+'" missed quot(")!!');
41023 el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start);
41025 if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){
41026 errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!');
41028 el.add(value,value,start);
41032 throw new Error('attribute value missed!!');
41034 // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
41036 /*xml space '\x20' | #x9 | #xD | #xA; */
41040 if(c<= ' '){//space
41043 el.setTagName(source.slice(start,p));//tagName
41047 attrName = source.slice(start,p);
41050 case S_ATTR_NOQUOT_VALUE:
41051 var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
41052 errorHandler.warning('attribute "'+value+'" missed quot(")!!');
41053 el.add(attrName,value,start);
41057 //case S_TAG_SPACE:
41059 //case S_ATTR_SPACE:
41061 //case S_TAG_CLOSE:
41065 //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
41066 //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
41068 //case S_TAG:void();break;
41069 //case S_ATTR:void();break;
41070 //case S_ATTR_NOQUOT_VALUE:void();break;
41072 var tagName = el.tagName;
41073 if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){
41074 errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!');
41076 el.add(attrName,attrName,start);
41081 errorHandler.warning('attribute space is required"'+attrName+'"!!');
41087 s = S_ATTR_NOQUOT_VALUE;
41091 throw new Error("elements closed character '/' and '>' must be connected to");
41094 }//end outer switch
41095 //console.log('p++',p)
41100 * @return true if has new namespace define
41102 function appendElement(el,domBuilder,currentNSMap){
41103 var tagName = el.tagName;
41104 var localNSMap = null;
41105 //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
41109 var qName = a.qName;
41110 var value = a.value;
41111 var nsp = qName.indexOf(':');
41113 var prefix = a.prefix = qName.slice(0,nsp);
41114 var localName = qName.slice(nsp+1);
41115 var nsPrefix = prefix === 'xmlns' && localName;
41119 nsPrefix = qName === 'xmlns' && '';
41121 //can not set prefix,because prefix !== ''
41122 a.localName = localName ;
41123 //prefix == null for no ns prefix attribute
41124 if(nsPrefix !== false){//hack!!
41125 if(localNSMap == null){
41127 //console.log(currentNSMap,0)
41128 _copy(currentNSMap,currentNSMap={});
41129 //console.log(currentNSMap,1)
41131 currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
41132 a.uri = 'http://www.w3.org/2000/xmlns/';
41133 domBuilder.startPrefixMapping(nsPrefix, value);
41139 var prefix = a.prefix;
41140 if(prefix){//no prefix attribute has no namespace
41141 if(prefix === 'xml'){
41142 a.uri = 'http://www.w3.org/XML/1998/namespace';
41143 }if(prefix !== 'xmlns'){
41144 a.uri = currentNSMap[prefix || ''];
41146 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
41150 var nsp = tagName.indexOf(':');
41152 prefix = el.prefix = tagName.slice(0,nsp);
41153 localName = el.localName = tagName.slice(nsp+1);
41155 prefix = null;//important!!
41156 localName = el.localName = tagName;
41158 //no prefix element has default namespace
41159 var ns = el.uri = currentNSMap[prefix || ''];
41160 domBuilder.startElement(ns,localName,tagName,el);
41161 //endPrefixMapping and startPrefixMapping have not any help for dom builder
41162 //localNSMap = null
41164 domBuilder.endElement(ns,localName,tagName);
41166 for(prefix in localNSMap){
41167 domBuilder.endPrefixMapping(prefix);
41171 el.currentNSMap = currentNSMap;
41172 el.localNSMap = localNSMap;
41173 //parseStack.push(el);
41177 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
41178 if(/^(?:script|textarea)$/i.test(tagName)){
41179 var elEndStart = source.indexOf('</'+tagName+'>',elStartEnd);
41180 var text = source.substring(elStartEnd+1,elEndStart);
41181 if(/[&<]/.test(text)){
41182 if(/^script$/i.test(tagName)){
41183 //if(!/\]\]>/.test(text)){
41184 //lexHandler.startCDATA();
41185 domBuilder.characters(text,0,text.length);
41186 //lexHandler.endCDATA();
41189 }//}else{//text area
41190 text = text.replace(/&#?\w+;/g,entityReplacer);
41191 domBuilder.characters(text,0,text.length);
41197 return elStartEnd+1;
41199 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
41200 //if(tagName in closeMap){
41201 var pos = closeMap[tagName];
41203 //console.log(tagName)
41204 pos = source.lastIndexOf('</'+tagName+'>');
41205 if(pos<elStartEnd){//忘记闭合
41206 pos = source.lastIndexOf('</'+tagName);
41208 closeMap[tagName] =pos;
41210 return pos<elStartEnd;
41213 function _copy(source,target){
41214 for(var n in source){target[n] = source[n];}
41216 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
41217 var next= source.charAt(start+2);
41220 if(source.charAt(start + 3) === '-'){
41221 var end = source.indexOf('-->',start+4);
41222 //append comment source.substring(4,end)//<!--
41224 domBuilder.comment(source,start+4,end-start-4);
41227 errorHandler.error("Unclosed comment");
41235 if(source.substr(start+3,6) == 'CDATA['){
41236 var end = source.indexOf(']]>',start+9);
41237 domBuilder.startCDATA();
41238 domBuilder.characters(source,start+9,end-start-9);
41239 domBuilder.endCDATA();
41243 //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
41244 var matchs = split(source,start);
41245 var len = matchs.length;
41246 if(len>1 && /!doctype/i.test(matchs[0][0])){
41247 var name = matchs[1][0];
41248 var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
41249 var sysid = len>4 && matchs[4][0];
41250 var lastMatch = matchs[len-1];
41251 domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
41252 sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
41253 domBuilder.endDTD();
41255 return lastMatch.index+lastMatch[0].length
41263 function parseInstruction(source,start,domBuilder){
41264 var end = source.indexOf('?>',start);
41266 var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
41268 var len = match[0].length;
41269 domBuilder.processingInstruction(match[1], match[2]) ;
41281 function ElementAttributes(source){
41284 ElementAttributes.prototype = {
41285 setTagName:function(tagName){
41286 if(!tagNamePattern.test(tagName)){
41287 throw new Error('invalid tagName:'+tagName)
41289 this.tagName = tagName;
41291 add:function(qName,value,offset){
41292 if(!tagNamePattern.test(qName)){
41293 throw new Error('invalid attribute:'+qName)
41295 this[this.length++] = {qName:qName,value:value,offset:offset};
41298 getLocalName:function(i){return this[i].localName},
41299 getLocator:function(i){return this[i].locator},
41300 getQName:function(i){return this[i].qName},
41301 getURI:function(i){return this[i].uri},
41302 getValue:function(i){return this[i].value}
41303 // ,getIndex:function(uri, localName)){
41310 // getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
41311 // getType:function(uri,localName){}
41312 // getType:function(i){},
41318 function _set_proto_(thiz,parent){
41319 thiz.__proto__ = parent;
41322 if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
41323 _set_proto_ = function(thiz,parent){
41325 p.prototype = parent;
41327 for(parent in thiz){
41328 p[parent] = thiz[parent];
41334 function split(source,start){
41337 var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
41338 reg.lastIndex = start;
41339 reg.exec(source);//skip <
41340 while(match = reg.exec(source)){
41342 if(match[1])return buf;
41346 var XMLReader_1 = XMLReader;
41349 XMLReader: XMLReader_1
41354 * Object DOMException
41355 * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
41356 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
41359 function copy$1(src,dest){
41365 ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
41366 ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
41368 function _extends(Class,Super){
41369 var pt = Class.prototype;
41371 var ppt = Object.create(Super.prototype);
41372 pt.__proto__ = ppt;
41374 if(!(pt instanceof Super)){
41376 t.prototype = Super.prototype;
41379 Class.prototype = pt = t;
41381 if(pt.constructor != Class){
41382 if(typeof Class != 'function'){
41383 console.error("unknow Class:"+Class);
41385 pt.constructor = Class;
41388 var htmlns = 'http://www.w3.org/1999/xhtml';
41391 var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
41392 var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
41393 var TEXT_NODE = NodeType.TEXT_NODE = 3;
41394 var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4;
41395 var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5;
41396 var ENTITY_NODE = NodeType.ENTITY_NODE = 6;
41397 var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
41398 var COMMENT_NODE = NodeType.COMMENT_NODE = 8;
41399 var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9;
41400 var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10;
41401 var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
41402 var NOTATION_NODE = NodeType.NOTATION_NODE = 12;
41405 var ExceptionCode = {};
41406 var ExceptionMessage = {};
41407 var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1);
41408 var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2);
41409 var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3]="Hierarchy request error"),3);
41410 var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4]="Wrong document"),4);
41411 var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5]="Invalid character"),5);
41412 var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6]="No data allowed"),6);
41413 var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
41414 var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8]="Not found"),8);
41415 var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9]="Not supported"),9);
41416 var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10]="Attribute in use"),10);
41418 var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11]="Invalid state"),11);
41419 var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12]="Syntax error"),12);
41420 var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13]="Invalid modification"),13);
41421 var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14);
41422 var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15]="Invalid access"),15);
41425 function DOMException(code, message) {
41426 if(message instanceof Error){
41427 var error = message;
41430 Error.call(this, ExceptionMessage[code]);
41431 this.message = ExceptionMessage[code];
41432 if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
41435 if(message) this.message = this.message + ": " + message;
41438 DOMException.prototype = Error.prototype;
41439 copy$1(ExceptionCode,DOMException);
41441 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
41442 * 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.
41443 * The items in the NodeList are accessible via an integral index, starting from 0.
41445 function NodeList() {
41447 NodeList.prototype = {
41449 * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
41454 * 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.
41456 * @param index unsigned long
41457 * Index into the collection.
41459 * The node at the indexth position in the NodeList, or null if that is not a valid index.
41461 item: function(index) {
41462 return this[index] || null;
41464 toString:function(isHTML,nodeFilter){
41465 for(var buf = [], i = 0;i<this.length;i++){
41466 serializeToString(this[i],buf,isHTML,nodeFilter);
41468 return buf.join('');
41471 function LiveNodeList(node,refresh){
41473 this._refresh = refresh;
41474 _updateLiveList(this);
41476 function _updateLiveList(list){
41477 var inc = list._node._inc || list._node.ownerDocument._inc;
41478 if(list._inc != inc){
41479 var ls = list._refresh(list._node);
41480 //console.log(ls.length)
41481 __set__(list,'length',ls.length);
41486 LiveNodeList.prototype.item = function(i){
41487 _updateLiveList(this);
41491 _extends(LiveNodeList,NodeList);
41494 * 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.
41495 * NamedNodeMap objects in the DOM are live.
41496 * used for attributes or DocumentType entities
41498 function NamedNodeMap() {
41501 function _findNodeIndex(list,node){
41502 var i = list.length;
41504 if(list[i] === node){return i}
41508 function _addNamedNode(el,list,newAttr,oldAttr){
41510 list[_findNodeIndex(list,oldAttr)] = newAttr;
41512 list[list.length++] = newAttr;
41515 newAttr.ownerElement = el;
41516 var doc = el.ownerDocument;
41518 oldAttr && _onRemoveAttribute(doc,el,oldAttr);
41519 _onAddAttribute(doc,el,newAttr);
41523 function _removeNamedNode(el,list,attr){
41524 //console.log('remove attr:'+attr)
41525 var i = _findNodeIndex(list,attr);
41527 var lastIndex = list.length-1;
41528 while(i<lastIndex){
41529 list[i] = list[++i];
41531 list.length = lastIndex;
41533 var doc = el.ownerDocument;
41535 _onRemoveAttribute(doc,el,attr);
41536 attr.ownerElement = null;
41540 throw DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr))
41543 NamedNodeMap.prototype = {
41545 item:NodeList.prototype.item,
41546 getNamedItem: function(key) {
41547 // if(key.indexOf(':')>0 || key == 'xmlns'){
41551 var i = this.length;
41553 var attr = this[i];
41554 //console.log(attr.nodeName,key)
41555 if(attr.nodeName == key){
41560 setNamedItem: function(attr) {
41561 var el = attr.ownerElement;
41562 if(el && el!=this._ownerElement){
41563 throw new DOMException(INUSE_ATTRIBUTE_ERR);
41565 var oldAttr = this.getNamedItem(attr.nodeName);
41566 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41570 setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
41571 var el = attr.ownerElement, oldAttr;
41572 if(el && el!=this._ownerElement){
41573 throw new DOMException(INUSE_ATTRIBUTE_ERR);
41575 oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
41576 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41581 removeNamedItem: function(key) {
41582 var attr = this.getNamedItem(key);
41583 _removeNamedNode(this._ownerElement,this,attr);
41587 },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
41590 removeNamedItemNS:function(namespaceURI,localName){
41591 var attr = this.getNamedItemNS(namespaceURI,localName);
41592 _removeNamedNode(this._ownerElement,this,attr);
41595 getNamedItemNS: function(namespaceURI, localName) {
41596 var i = this.length;
41598 var node = this[i];
41599 if(node.localName == localName && node.namespaceURI == namespaceURI){
41607 * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
41609 function DOMImplementation(/* Object */ features) {
41610 this._features = {};
41612 for (var feature in features) {
41613 this._features = features[feature];
41618 DOMImplementation.prototype = {
41619 hasFeature: function(/* string */ feature, /* string */ version) {
41620 var versions = this._features[feature.toLowerCase()];
41621 if (versions && (!version || version in versions)) {
41627 // Introduced in DOM Level 2:
41628 createDocument:function(namespaceURI, qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
41629 var doc = new Document();
41630 doc.implementation = this;
41631 doc.childNodes = new NodeList();
41632 doc.doctype = doctype;
41634 doc.appendChild(doctype);
41637 var root = doc.createElementNS(namespaceURI,qualifiedName);
41638 doc.appendChild(root);
41642 // Introduced in DOM Level 2:
41643 createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
41644 var node = new DocumentType();
41645 node.name = qualifiedName;
41646 node.nodeName = qualifiedName;
41647 node.publicId = publicId;
41648 node.systemId = systemId;
41649 // Introduced in DOM Level 2:
41650 //readonly attribute DOMString internalSubset;
41653 // readonly attribute NamedNodeMap entities;
41654 // readonly attribute NamedNodeMap notations;
41661 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
41664 function Node$3() {
41667 Node$3.prototype = {
41670 previousSibling : null,
41671 nextSibling : null,
41675 ownerDocument : null,
41677 namespaceURI : null,
41680 // Modified in DOM Level 2:
41681 insertBefore:function(newChild, refChild){//raises
41682 return _insertBefore(this,newChild,refChild);
41684 replaceChild:function(newChild, oldChild){//raises
41685 this.insertBefore(newChild,oldChild);
41687 this.removeChild(oldChild);
41690 removeChild:function(oldChild){
41691 return _removeChild(this,oldChild);
41693 appendChild:function(newChild){
41694 return this.insertBefore(newChild,null);
41696 hasChildNodes:function(){
41697 return this.firstChild != null;
41699 cloneNode:function(deep){
41700 return cloneNode(this.ownerDocument||this,this,deep);
41702 // Modified in DOM Level 2:
41703 normalize:function(){
41704 var child = this.firstChild;
41706 var next = child.nextSibling;
41707 if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
41708 this.removeChild(next);
41709 child.appendData(next.data);
41716 // Introduced in DOM Level 2:
41717 isSupported:function(feature, version){
41718 return this.ownerDocument.implementation.hasFeature(feature,version);
41720 // Introduced in DOM Level 2:
41721 hasAttributes:function(){
41722 return this.attributes.length>0;
41724 lookupPrefix:function(namespaceURI){
41727 var map = el._nsMap;
41731 if(map[n] == namespaceURI){
41736 el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
41740 // Introduced in DOM Level 3:
41741 lookupNamespaceURI:function(prefix){
41744 var map = el._nsMap;
41748 return map[prefix] ;
41751 el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
41755 // Introduced in DOM Level 3:
41756 isDefaultNamespace:function(namespaceURI){
41757 var prefix = this.lookupPrefix(namespaceURI);
41758 return prefix == null;
41763 function _xmlEncoder(c){
41764 return c == '<' && '<' ||
41765 c == '>' && '>' ||
41766 c == '&' && '&' ||
41767 c == '"' && '"' ||
41768 '&#'+c.charCodeAt()+';'
41772 copy$1(NodeType,Node$3);
41773 copy$1(NodeType,Node$3.prototype);
41776 * @param callback return true for continue,false for break
41777 * @return boolean true: break visit;
41779 function _visitNode(node,callback){
41780 if(callback(node)){
41783 if(node = node.firstChild){
41785 if(_visitNode(node,callback)){return true}
41786 }while(node=node.nextSibling)
41792 function Document(){
41794 function _onAddAttribute(doc,el,newAttr){
41796 var ns = newAttr.namespaceURI;
41797 if(ns == 'http://www.w3.org/2000/xmlns/'){
41799 el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value;
41802 function _onRemoveAttribute(doc,el,newAttr,remove){
41804 var ns = newAttr.namespaceURI;
41805 if(ns == 'http://www.w3.org/2000/xmlns/'){
41807 delete el._nsMap[newAttr.prefix?newAttr.localName:''];
41810 function _onUpdateChild(doc,el,newChild){
41811 if(doc && doc._inc){
41813 //update childNodes
41814 var cs = el.childNodes;
41816 cs[cs.length++] = newChild;
41819 var child = el.firstChild;
41823 child =child.nextSibling;
41834 * writeable properties:
41835 * nodeValue,Attr:value,CharacterData:data
41838 function _removeChild(parentNode,child){
41839 var previous = child.previousSibling;
41840 var next = child.nextSibling;
41842 previous.nextSibling = next;
41844 parentNode.firstChild = next;
41847 next.previousSibling = previous;
41849 parentNode.lastChild = previous;
41851 _onUpdateChild(parentNode.ownerDocument,parentNode);
41855 * preformance key(refChild == null)
41857 function _insertBefore(parentNode,newChild,nextChild){
41858 var cp = newChild.parentNode;
41860 cp.removeChild(newChild);//remove and update
41862 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41863 var newFirst = newChild.firstChild;
41864 if (newFirst == null) {
41867 var newLast = newChild.lastChild;
41869 newFirst = newLast = newChild;
41871 var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
41873 newFirst.previousSibling = pre;
41874 newLast.nextSibling = nextChild;
41878 pre.nextSibling = newFirst;
41880 parentNode.firstChild = newFirst;
41882 if(nextChild == null){
41883 parentNode.lastChild = newLast;
41885 nextChild.previousSibling = newLast;
41888 newFirst.parentNode = parentNode;
41889 }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
41890 _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
41891 //console.log(parentNode.lastChild.nextSibling == null)
41892 if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
41893 newChild.firstChild = newChild.lastChild = null;
41897 function _appendSingleChild(parentNode,newChild){
41898 var cp = newChild.parentNode;
41900 var pre = parentNode.lastChild;
41901 cp.removeChild(newChild);//remove and update
41902 var pre = parentNode.lastChild;
41904 var pre = parentNode.lastChild;
41905 newChild.parentNode = parentNode;
41906 newChild.previousSibling = pre;
41907 newChild.nextSibling = null;
41909 pre.nextSibling = newChild;
41911 parentNode.firstChild = newChild;
41913 parentNode.lastChild = newChild;
41914 _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
41916 //console.log("__aa",parentNode.lastChild.nextSibling == null)
41918 Document.prototype = {
41919 //implementation : null,
41920 nodeName : '#document',
41921 nodeType : DOCUMENT_NODE,
41923 documentElement : null,
41926 insertBefore : function(newChild, refChild){//raises
41927 if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
41928 var child = newChild.firstChild;
41930 var next = child.nextSibling;
41931 this.insertBefore(child,refChild);
41936 if(this.documentElement == null && newChild.nodeType == ELEMENT_NODE){
41937 this.documentElement = newChild;
41940 return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
41942 removeChild : function(oldChild){
41943 if(this.documentElement == oldChild){
41944 this.documentElement = null;
41946 return _removeChild(this,oldChild);
41948 // Introduced in DOM Level 2:
41949 importNode : function(importedNode,deep){
41950 return importNode(this,importedNode,deep);
41952 // Introduced in DOM Level 2:
41953 getElementById : function(id){
41955 _visitNode(this.documentElement,function(node){
41956 if(node.nodeType == ELEMENT_NODE){
41957 if(node.getAttribute('id') == id){
41966 //document factory method:
41967 createElement : function(tagName){
41968 var node = new Element();
41969 node.ownerDocument = this;
41970 node.nodeName = tagName;
41971 node.tagName = tagName;
41972 node.childNodes = new NodeList();
41973 var attrs = node.attributes = new NamedNodeMap();
41974 attrs._ownerElement = node;
41977 createDocumentFragment : function(){
41978 var node = new DocumentFragment();
41979 node.ownerDocument = this;
41980 node.childNodes = new NodeList();
41983 createTextNode : function(data){
41984 var node = new Text();
41985 node.ownerDocument = this;
41986 node.appendData(data);
41989 createComment : function(data){
41990 var node = new Comment();
41991 node.ownerDocument = this;
41992 node.appendData(data);
41995 createCDATASection : function(data){
41996 var node = new CDATASection();
41997 node.ownerDocument = this;
41998 node.appendData(data);
42001 createProcessingInstruction : function(target,data){
42002 var node = new ProcessingInstruction();
42003 node.ownerDocument = this;
42004 node.tagName = node.target = target;
42005 node.nodeValue= node.data = data;
42008 createAttribute : function(name){
42009 var node = new Attr();
42010 node.ownerDocument = this;
42012 node.nodeName = name;
42013 node.localName = name;
42014 node.specified = true;
42017 createEntityReference : function(name){
42018 var node = new EntityReference();
42019 node.ownerDocument = this;
42020 node.nodeName = name;
42023 // Introduced in DOM Level 2:
42024 createElementNS : function(namespaceURI,qualifiedName){
42025 var node = new Element();
42026 var pl = qualifiedName.split(':');
42027 var attrs = node.attributes = new NamedNodeMap();
42028 node.childNodes = new NodeList();
42029 node.ownerDocument = this;
42030 node.nodeName = qualifiedName;
42031 node.tagName = qualifiedName;
42032 node.namespaceURI = namespaceURI;
42033 if(pl.length == 2){
42034 node.prefix = pl[0];
42035 node.localName = pl[1];
42037 //el.prefix = null;
42038 node.localName = qualifiedName;
42040 attrs._ownerElement = node;
42043 // Introduced in DOM Level 2:
42044 createAttributeNS : function(namespaceURI,qualifiedName){
42045 var node = new Attr();
42046 var pl = qualifiedName.split(':');
42047 node.ownerDocument = this;
42048 node.nodeName = qualifiedName;
42049 node.name = qualifiedName;
42050 node.namespaceURI = namespaceURI;
42051 node.specified = true;
42052 if(pl.length == 2){
42053 node.prefix = pl[0];
42054 node.localName = pl[1];
42056 //el.prefix = null;
42057 node.localName = qualifiedName;
42062 _extends(Document,Node$3);
42065 function Element() {
42068 Element.prototype = {
42069 nodeType : ELEMENT_NODE,
42070 hasAttribute : function(name){
42071 return this.getAttributeNode(name)!=null;
42073 getAttribute : function(name){
42074 var attr = this.getAttributeNode(name);
42075 return attr && attr.value || '';
42077 getAttributeNode : function(name){
42078 return this.attributes.getNamedItem(name);
42080 setAttribute : function(name, value){
42081 var attr = this.ownerDocument.createAttribute(name);
42082 attr.value = attr.nodeValue = "" + value;
42083 this.setAttributeNode(attr);
42085 removeAttribute : function(name){
42086 var attr = this.getAttributeNode(name);
42087 attr && this.removeAttributeNode(attr);
42090 //four real opeartion method
42091 appendChild:function(newChild){
42092 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
42093 return this.insertBefore(newChild,null);
42095 return _appendSingleChild(this,newChild);
42098 setAttributeNode : function(newAttr){
42099 return this.attributes.setNamedItem(newAttr);
42101 setAttributeNodeNS : function(newAttr){
42102 return this.attributes.setNamedItemNS(newAttr);
42104 removeAttributeNode : function(oldAttr){
42105 //console.log(this == oldAttr.ownerElement)
42106 return this.attributes.removeNamedItem(oldAttr.nodeName);
42108 //get real attribute name,and remove it by removeAttributeNode
42109 removeAttributeNS : function(namespaceURI, localName){
42110 var old = this.getAttributeNodeNS(namespaceURI, localName);
42111 old && this.removeAttributeNode(old);
42114 hasAttributeNS : function(namespaceURI, localName){
42115 return this.getAttributeNodeNS(namespaceURI, localName)!=null;
42117 getAttributeNS : function(namespaceURI, localName){
42118 var attr = this.getAttributeNodeNS(namespaceURI, localName);
42119 return attr && attr.value || '';
42121 setAttributeNS : function(namespaceURI, qualifiedName, value){
42122 var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
42123 attr.value = attr.nodeValue = "" + value;
42124 this.setAttributeNode(attr);
42126 getAttributeNodeNS : function(namespaceURI, localName){
42127 return this.attributes.getNamedItemNS(namespaceURI, localName);
42130 getElementsByTagName : function(tagName){
42131 return new LiveNodeList(this,function(base){
42133 _visitNode(base,function(node){
42134 if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
42141 getElementsByTagNameNS : function(namespaceURI, localName){
42142 return new LiveNodeList(this,function(base){
42144 _visitNode(base,function(node){
42145 if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
42154 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
42155 Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
42158 _extends(Element,Node$3);
42161 Attr.prototype.nodeType = ATTRIBUTE_NODE;
42162 _extends(Attr,Node$3);
42165 function CharacterData() {
42167 CharacterData.prototype = {
42169 substringData : function(offset, count) {
42170 return this.data.substring(offset, offset+count);
42172 appendData: function(text) {
42173 text = this.data+text;
42174 this.nodeValue = this.data = text;
42175 this.length = text.length;
42177 insertData: function(offset,text) {
42178 this.replaceData(offset,0,text);
42181 appendChild:function(newChild){
42182 throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR])
42184 deleteData: function(offset, count) {
42185 this.replaceData(offset,count,"");
42187 replaceData: function(offset, count, text) {
42188 var start = this.data.substring(0,offset);
42189 var end = this.data.substring(offset+count);
42190 text = start + text + end;
42191 this.nodeValue = this.data = text;
42192 this.length = text.length;
42195 _extends(CharacterData,Node$3);
42199 nodeName : "#text",
42200 nodeType : TEXT_NODE,
42201 splitText : function(offset) {
42202 var text = this.data;
42203 var newText = text.substring(offset);
42204 text = text.substring(0, offset);
42205 this.data = this.nodeValue = text;
42206 this.length = text.length;
42207 var newNode = this.ownerDocument.createTextNode(newText);
42208 if(this.parentNode){
42209 this.parentNode.insertBefore(newNode, this.nextSibling);
42214 _extends(Text,CharacterData);
42215 function Comment() {
42217 Comment.prototype = {
42218 nodeName : "#comment",
42219 nodeType : COMMENT_NODE
42221 _extends(Comment,CharacterData);
42223 function CDATASection() {
42225 CDATASection.prototype = {
42226 nodeName : "#cdata-section",
42227 nodeType : CDATA_SECTION_NODE
42229 _extends(CDATASection,CharacterData);
42232 function DocumentType() {
42234 DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
42235 _extends(DocumentType,Node$3);
42237 function Notation() {
42239 Notation.prototype.nodeType = NOTATION_NODE;
42240 _extends(Notation,Node$3);
42242 function Entity() {
42244 Entity.prototype.nodeType = ENTITY_NODE;
42245 _extends(Entity,Node$3);
42247 function EntityReference() {
42249 EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
42250 _extends(EntityReference,Node$3);
42252 function DocumentFragment() {
42254 DocumentFragment.prototype.nodeName = "#document-fragment";
42255 DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
42256 _extends(DocumentFragment,Node$3);
42259 function ProcessingInstruction() {
42261 ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
42262 _extends(ProcessingInstruction,Node$3);
42263 function XMLSerializer$1(){}
42264 XMLSerializer$1.prototype.serializeToString = function(node,isHtml,nodeFilter){
42265 return nodeSerializeToString.call(node,isHtml,nodeFilter);
42267 Node$3.prototype.toString = nodeSerializeToString;
42268 function nodeSerializeToString(isHtml,nodeFilter){
42270 var refNode = this.nodeType == 9?this.documentElement:this;
42271 var prefix = refNode.prefix;
42272 var uri = refNode.namespaceURI;
42274 if(uri && prefix == null){
42275 //console.log(prefix)
42276 var prefix = refNode.lookupPrefix(uri);
42277 if(prefix == null){
42279 var visibleNamespaces=[
42280 {namespace:uri,prefix:null}
42281 //{namespace:uri,prefix:''}
42285 serializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces);
42286 //console.log('###',this.nodeType,uri,prefix,buf.join(''))
42287 return buf.join('');
42289 function needNamespaceDefine(node,isHTML, visibleNamespaces) {
42290 var prefix = node.prefix||'';
42291 var uri = node.namespaceURI;
42292 if (!prefix && !uri){
42295 if (prefix === "xml" && uri === "http://www.w3.org/XML/1998/namespace"
42296 || uri == 'http://www.w3.org/2000/xmlns/'){
42300 var i = visibleNamespaces.length;
42301 //console.log('@@@@',node.tagName,prefix,uri,visibleNamespaces)
42303 var ns = visibleNamespaces[i];
42304 // get namespace prefix
42305 //console.log(node.nodeType,node.tagName,ns.prefix,prefix)
42306 if (ns.prefix == prefix){
42307 return ns.namespace != uri;
42310 //console.log(isHTML,uri,prefix=='')
42311 //if(isHTML && prefix ==null && uri == 'http://www.w3.org/1999/xhtml'){
42314 //node.flag = '11111'
42315 //console.error(3,true,node.flag,node.prefix,node.namespaceURI)
42318 function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
42320 node = nodeFilter(node);
42322 if(typeof node == 'string'){
42329 //buf.sort.apply(attrs, attributeSorter);
42331 switch(node.nodeType){
42333 if (!visibleNamespaces) visibleNamespaces = [];
42334 var startVisibleNamespaces = visibleNamespaces.length;
42335 var attrs = node.attributes;
42336 var len = attrs.length;
42337 var child = node.firstChild;
42338 var nodeName = node.tagName;
42340 isHTML = (htmlns === node.namespaceURI) ||isHTML;
42341 buf.push('<',nodeName);
42345 for(var i=0;i<len;i++){
42346 // add namespaces for attributes
42347 var attr = attrs.item(i);
42348 if (attr.prefix == 'xmlns') {
42349 visibleNamespaces.push({ prefix: attr.localName, namespace: attr.value });
42350 }else if(attr.nodeName == 'xmlns'){
42351 visibleNamespaces.push({ prefix: '', namespace: attr.value });
42354 for(var i=0;i<len;i++){
42355 var attr = attrs.item(i);
42356 if (needNamespaceDefine(attr,isHTML, visibleNamespaces)) {
42357 var prefix = attr.prefix||'';
42358 var uri = attr.namespaceURI;
42359 var ns = prefix ? ' xmlns:' + prefix : " xmlns";
42360 buf.push(ns, '="' , uri , '"');
42361 visibleNamespaces.push({ prefix: prefix, namespace:uri });
42363 serializeToString(attr,buf,isHTML,nodeFilter,visibleNamespaces);
42365 // add namespace for current node
42366 if (needNamespaceDefine(node,isHTML, visibleNamespaces)) {
42367 var prefix = node.prefix||'';
42368 var uri = node.namespaceURI;
42369 var ns = prefix ? ' xmlns:' + prefix : " xmlns";
42370 buf.push(ns, '="' , uri , '"');
42371 visibleNamespaces.push({ prefix: prefix, namespace:uri });
42374 if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){
42376 //if is cdata child node
42377 if(isHTML && /^script$/i.test(nodeName)){
42380 buf.push(child.data);
42382 serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
42384 child = child.nextSibling;
42389 serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
42390 child = child.nextSibling;
42393 buf.push('</',nodeName,'>');
42397 // remove added visible namespaces
42398 //visibleNamespaces.length = startVisibleNamespaces;
42400 case DOCUMENT_NODE:
42401 case DOCUMENT_FRAGMENT_NODE:
42402 var child = node.firstChild;
42404 serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
42405 child = child.nextSibling;
42408 case ATTRIBUTE_NODE:
42409 return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
42411 return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
42412 case CDATA_SECTION_NODE:
42413 return buf.push( '<![CDATA[',node.data,']]>');
42415 return buf.push( "<!--",node.data,"-->");
42416 case DOCUMENT_TYPE_NODE:
42417 var pubid = node.publicId;
42418 var sysid = node.systemId;
42419 buf.push('<!DOCTYPE ',node.name);
42421 buf.push(' PUBLIC "',pubid);
42422 if (sysid && sysid!='.') {
42423 buf.push( '" "',sysid);
42426 }else if(sysid && sysid!='.'){
42427 buf.push(' SYSTEM "',sysid,'">');
42429 var sub = node.internalSubset;
42431 buf.push(" [",sub,"]");
42436 case PROCESSING_INSTRUCTION_NODE:
42437 return buf.push( "<?",node.target," ",node.data,"?>");
42438 case ENTITY_REFERENCE_NODE:
42439 return buf.push( '&',node.nodeName,';');
42440 //case ENTITY_NODE:
42441 //case NOTATION_NODE:
42443 buf.push('??',node.nodeName);
42446 function importNode(doc,node,deep){
42448 switch (node.nodeType) {
42450 node2 = node.cloneNode(false);
42451 node2.ownerDocument = doc;
42452 //var attrs = node2.attributes;
42453 //var len = attrs.length;
42454 //for(var i=0;i<len;i++){
42455 //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
42457 case DOCUMENT_FRAGMENT_NODE:
42459 case ATTRIBUTE_NODE:
42462 //case ENTITY_REFERENCE_NODE:
42463 //case PROCESSING_INSTRUCTION_NODE:
42464 ////case TEXT_NODE:
42465 //case CDATA_SECTION_NODE:
42466 //case COMMENT_NODE:
42469 //case DOCUMENT_NODE:
42470 //case DOCUMENT_TYPE_NODE:
42471 //cannot be imported.
42472 //case ENTITY_NODE:
42473 //case NOTATION_NODE:
42474 //can not hit in level3
42478 node2 = node.cloneNode(false);//false
42480 node2.ownerDocument = doc;
42481 node2.parentNode = null;
42483 var child = node.firstChild;
42485 node2.appendChild(importNode(doc,child,deep));
42486 child = child.nextSibling;
42492 //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
42493 // attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
42494 function cloneNode(doc,node,deep){
42495 var node2 = new node.constructor();
42496 for(var n in node){
42498 if(typeof v != 'object' ){
42504 if(node.childNodes){
42505 node2.childNodes = new NodeList();
42507 node2.ownerDocument = doc;
42508 switch (node2.nodeType) {
42510 var attrs = node.attributes;
42511 var attrs2 = node2.attributes = new NamedNodeMap();
42512 var len = attrs.length;
42513 attrs2._ownerElement = node2;
42514 for(var i=0;i<len;i++){
42515 node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
42518 case ATTRIBUTE_NODE:
42522 var child = node.firstChild;
42524 node2.appendChild(cloneNode(doc,child,deep));
42525 child = child.nextSibling;
42531 function __set__(object,key,value){
42532 object[key] = value;
42536 if(Object.defineProperty){
42537 Object.defineProperty(LiveNodeList.prototype,'length',{
42539 _updateLiveList(this);
42540 return this.$$length;
42543 Object.defineProperty(Node$3.prototype,'textContent',{
42545 return getTextContent(this);
42547 set:function(data){
42548 switch(this.nodeType){
42550 case DOCUMENT_FRAGMENT_NODE:
42551 while(this.firstChild){
42552 this.removeChild(this.firstChild);
42554 if(data || String(data)){
42555 this.appendChild(this.ownerDocument.createTextNode(data));
42562 this.nodeValue = data;
42567 function getTextContent(node){
42568 switch(node.nodeType){
42570 case DOCUMENT_FRAGMENT_NODE:
42572 node = node.firstChild;
42574 if(node.nodeType!==7 && node.nodeType !==8){
42575 buf.push(getTextContent(node));
42577 node = node.nextSibling;
42579 return buf.join('');
42581 return node.nodeValue;
42584 __set__ = function(object,key,value){
42585 //console.log(value)
42586 object['$$'+key] = value;
42592 //if(typeof require == 'function'){
42593 var DOMImplementation_1 = DOMImplementation;
42594 var XMLSerializer_1 = XMLSerializer$1;
42598 DOMImplementation: DOMImplementation_1,
42599 XMLSerializer: XMLSerializer_1
42602 var domParser = createCommonjsModule(function (module, exports) {
42603 function DOMParser(options){
42604 this.options = options ||{locator:{}};
42607 DOMParser.prototype.parseFromString = function(source,mimeType){
42608 var options = this.options;
42609 var sax$$1 = new XMLReader();
42610 var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
42611 var errorHandler = options.errorHandler;
42612 var locator = options.locator;
42613 var defaultNSMap = options.xmlns||{};
42614 var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
42616 domBuilder.setDocumentLocator(locator);
42619 sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
42620 sax$$1.domBuilder = options.domBuilder || domBuilder;
42621 if(/\/x?html?$/.test(mimeType)){
42622 entityMap.nbsp = '\xa0';
42623 entityMap.copy = '\xa9';
42624 defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
42626 defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
42628 sax$$1.parse(source,defaultNSMap,entityMap);
42630 sax$$1.errorHandler.error("invalid doc source");
42632 return domBuilder.doc;
42634 function buildErrorHandler(errorImpl,domBuilder,locator){
42636 if(domBuilder instanceof DOMHandler){
42639 errorImpl = domBuilder ;
42641 var errorHandler = {};
42642 var isCallback = errorImpl instanceof Function;
42643 locator = locator||{};
42644 function build(key){
42645 var fn = errorImpl[key];
42646 if(!fn && isCallback){
42647 fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl;
42649 errorHandler[key] = fn && function(msg){
42650 fn('[xmldom '+key+']\t'+msg+_locator(locator));
42655 build('fatalError');
42656 return errorHandler;
42659 //console.log('#\n\n\n\n\n\n\n####')
42661 * +ContentHandler+ErrorHandler
42662 * +LexicalHandler+EntityResolver2
42663 * -DeclHandler-DTDHandler
42665 * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
42666 * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
42667 * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
42669 function DOMHandler() {
42670 this.cdata = false;
42672 function position(locator,node){
42673 node.lineNumber = locator.lineNumber;
42674 node.columnNumber = locator.columnNumber;
42677 * @see org.xml.sax.ContentHandler#startDocument
42678 * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
42680 DOMHandler.prototype = {
42681 startDocument : function() {
42682 this.doc = new DOMImplementation().createDocument(null, null, null);
42683 if (this.locator) {
42684 this.doc.documentURI = this.locator.systemId;
42687 startElement:function(namespaceURI, localName, qName, attrs) {
42688 var doc = this.doc;
42689 var el = doc.createElementNS(namespaceURI, qName||localName);
42690 var len = attrs.length;
42691 appendElement(this, el);
42692 this.currentElement = el;
42694 this.locator && position(this.locator,el);
42695 for (var i = 0 ; i < len; i++) {
42696 var namespaceURI = attrs.getURI(i);
42697 var value = attrs.getValue(i);
42698 var qName = attrs.getQName(i);
42699 var attr = doc.createAttributeNS(namespaceURI, qName);
42700 this.locator &&position(attrs.getLocator(i),attr);
42701 attr.value = attr.nodeValue = value;
42702 el.setAttributeNode(attr);
42705 endElement:function(namespaceURI, localName, qName) {
42706 var current = this.currentElement;
42707 var tagName = current.tagName;
42708 this.currentElement = current.parentNode;
42710 startPrefixMapping:function(prefix, uri) {
42712 endPrefixMapping:function(prefix) {
42714 processingInstruction:function(target, data) {
42715 var ins = this.doc.createProcessingInstruction(target, data);
42716 this.locator && position(this.locator,ins);
42717 appendElement(this, ins);
42719 ignorableWhitespace:function(ch, start, length) {
42721 characters:function(chars, start, length) {
42722 chars = _toString.apply(this,arguments);
42723 //console.log(chars)
42726 var charNode = this.doc.createCDATASection(chars);
42728 var charNode = this.doc.createTextNode(chars);
42730 if(this.currentElement){
42731 this.currentElement.appendChild(charNode);
42732 }else if(/^\s*$/.test(chars)){
42733 this.doc.appendChild(charNode);
42736 this.locator && position(this.locator,charNode);
42739 skippedEntity:function(name) {
42741 endDocument:function() {
42742 this.doc.normalize();
42744 setDocumentLocator:function (locator) {
42745 if(this.locator = locator){// && !('lineNumber' in locator)){
42746 locator.lineNumber = 0;
42750 comment:function(chars, start, length) {
42751 chars = _toString.apply(this,arguments);
42752 var comm = this.doc.createComment(chars);
42753 this.locator && position(this.locator,comm);
42754 appendElement(this, comm);
42757 startCDATA:function() {
42758 //used in characters() methods
42761 endCDATA:function() {
42762 this.cdata = false;
42765 startDTD:function(name, publicId, systemId) {
42766 var impl = this.doc.implementation;
42767 if (impl && impl.createDocumentType) {
42768 var dt = impl.createDocumentType(name, publicId, systemId);
42769 this.locator && position(this.locator,dt);
42770 appendElement(this, dt);
42774 * @see org.xml.sax.ErrorHandler
42775 * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
42777 warning:function(error) {
42778 console.warn('[xmldom warning]\t'+error,_locator(this.locator));
42780 error:function(error) {
42781 console.error('[xmldom error]\t'+error,_locator(this.locator));
42783 fatalError:function(error) {
42784 console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
42788 function _locator(l){
42790 return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
42793 function _toString(chars,start,length){
42794 if(typeof chars == 'string'){
42795 return chars.substr(start,length)
42796 }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
42797 if(chars.length >= start+length || start){
42798 return new java.lang.String(chars,start,length)+'';
42805 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
42806 * used method of org.xml.sax.ext.LexicalHandler:
42807 * #comment(chars, start, length)
42810 * #startDTD(name, publicId, systemId)
42813 * IGNORED method of org.xml.sax.ext.LexicalHandler:
42815 * #startEntity(name)
42819 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
42820 * IGNORED method of org.xml.sax.ext.DeclHandler
42821 * #attributeDecl(eName, aName, type, mode, value)
42822 * #elementDecl(name, model)
42823 * #externalEntityDecl(name, publicId, systemId)
42824 * #internalEntityDecl(name, value)
42825 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
42826 * IGNORED method of org.xml.sax.EntityResolver2
42827 * #resolveEntity(String name,String publicId,String baseURI,String systemId)
42828 * #resolveEntity(publicId, systemId)
42829 * #getExternalSubset(name, baseURI)
42830 * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
42831 * IGNORED method of org.xml.sax.DTDHandler
42832 * #notationDecl(name, publicId, systemId) {};
42833 * #unparsedEntityDecl(name, publicId, systemId, notationName) {};
42835 "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
42836 DOMHandler.prototype[key] = function(){return null};
42839 /* 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 */
42840 function appendElement (hander,node) {
42841 if (!hander.currentElement) {
42842 hander.doc.appendChild(node);
42844 hander.currentElement.appendChild(node);
42846 }//appendChild and setAttributeNS are preformance key
42848 //if(typeof require == 'function'){
42849 var XMLReader = sax.XMLReader;
42850 var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation;
42851 exports.XMLSerializer = dom.XMLSerializer ;
42852 exports.DOMParser = DOMParser;
42856 var togeojson = createCommonjsModule(function (module, exports) {
42857 var toGeoJSON = (function() {
42860 var removeSpace = /\s*/g,
42861 trimSpace = /^\s*|\s*$/g,
42862 splitSpace = /\s+/;
42863 // generate a short, numeric hash of a string
42864 function okhash(x) {
42865 if (!x || !x.length) return 0;
42866 for (var i = 0, h = 0; i < x.length; i++) {
42867 h = ((h << 5) - h) + x.charCodeAt(i) | 0;
42870 // all Y children of X
42871 function get(x, y) { return x.getElementsByTagName(y); }
42872 function attr(x, y) { return x.getAttribute(y); }
42873 function attrf(x, y) { return parseFloat(attr(x, y)); }
42874 // one Y child of X, if any, otherwise null
42875 function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
42876 // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
42877 function norm(el) { if (el.normalize) { el.normalize(); } return el; }
42878 // cast array x into numbers
42879 function numarray(x) {
42880 for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); }
42883 // get the content of a text node, if any
42884 function nodeVal(x) {
42885 if (x) { norm(x); }
42886 return (x && x.textContent) || '';
42888 // get the contents of multiple text nodes, if present
42889 function getMulti(x, ys) {
42891 for (k = 0; k < ys.length; k++) {
42892 n = get1(x, ys[k]);
42893 if (n) o[ys[k]] = nodeVal(n);
42897 // add properties of Y to X, overwriting if present in both
42898 function extend(x, y) { for (var k in y) x[k] = y[k]; }
42899 // get one coordinate from a coordinate array, if any
42900 function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
42901 // get all coordinates from a coordinate array as [[],[]]
42902 function coord(v) {
42903 var coords = v.replace(trimSpace, '').split(splitSpace),
42905 for (var i = 0; i < coords.length; i++) {
42906 o.push(coord1(coords[i]));
42910 function coordPair(x) {
42911 var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
42912 ele = get1(x, 'ele'),
42913 // handle namespaced attribute in browser
42914 heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'),
42915 time = get1(x, 'time'),
42918 e = parseFloat(nodeVal(ele));
42925 time: time ? nodeVal(time) : null,
42926 heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null
42930 // create a new feature collection parent object
42933 type: 'FeatureCollection',
42939 if (typeof XMLSerializer !== 'undefined') {
42940 /* istanbul ignore next */
42941 serializer = new XMLSerializer();
42942 // only require xmldom in a node environment
42943 } else if ('object' === 'object' && typeof process === 'object' && !process.browser) {
42944 serializer = new (domParser.XMLSerializer)();
42946 function xml2str(str) {
42947 // IE9 will create a new XMLSerializer but it'll crash immediately.
42948 // This line is ignored because we don't run coverage tests in IE9
42949 /* istanbul ignore next */
42950 if (str.xml !== undefined) return str.xml;
42951 return serializer.serializeToString(str);
42955 kml: function(doc) {
42958 // styleindex keeps track of hashed styles in order to match features
42959 styleIndex = {}, styleByHash = {},
42960 // stylemapindex keeps track of style maps to expose in properties
42961 styleMapIndex = {},
42962 // atomic geospatial types supported by KML - MultiGeometry is
42963 // handled separately
42964 geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'],
42965 // all root placemarks in the file
42966 placemarks = get(doc, 'Placemark'),
42967 styles = get(doc, 'Style'),
42968 styleMaps = get(doc, 'StyleMap');
42970 for (var k = 0; k < styles.length; k++) {
42971 var hash = okhash(xml2str(styles[k])).toString(16);
42972 styleIndex['#' + attr(styles[k], 'id')] = hash;
42973 styleByHash[hash] = styles[k];
42975 for (var l = 0; l < styleMaps.length; l++) {
42976 styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16);
42977 var pairs = get(styleMaps[l], 'Pair');
42979 for (var m = 0; m < pairs.length; m++) {
42980 pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl'));
42982 styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap;
42985 for (var j = 0; j < placemarks.length; j++) {
42986 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
42988 function kmlColor(v) {
42989 var color, opacity;
42991 if (v.substr(0, 1) === '#') { v = v.substr(1); }
42992 if (v.length === 6 || v.length === 3) { color = v; }
42993 if (v.length === 8) {
42994 opacity = parseInt(v.substr(0, 2), 16) / 255;
42995 color = '#' + v.substr(6, 2) +
42999 return [color, isNaN(opacity) ? undefined : opacity];
43001 function gxCoord(v) { return numarray(v.split(' ')); }
43002 function gxCoords(root) {
43003 var elems = get(root, 'coord', 'gx'), coords = [], times = [];
43004 if (elems.length === 0) elems = get(root, 'gx:coord');
43005 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
43006 var timeElems = get(root, 'when');
43007 for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j]));
43013 function getGeometry(root) {
43014 var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = [];
43015 if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); }
43016 if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); }
43017 if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); }
43018 for (i = 0; i < geotypes.length; i++) {
43019 geomNodes = get(root, geotypes[i]);
43021 for (j = 0; j < geomNodes.length; j++) {
43022 geomNode = geomNodes[j];
43023 if (geotypes[i] === 'Point') {
43026 coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
43028 } else if (geotypes[i] === 'LineString') {
43030 type: 'LineString',
43031 coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
43033 } else if (geotypes[i] === 'Polygon') {
43034 var rings = get(geomNode, 'LinearRing'),
43036 for (k = 0; k < rings.length; k++) {
43037 coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
43041 coordinates: coords
43043 } else if (geotypes[i] === 'Track' ||
43044 geotypes[i] === 'gx:Track') {
43045 var track = gxCoords(geomNode);
43047 type: 'LineString',
43048 coordinates: track.coords
43050 if (track.times.length) coordTimes.push(track.times);
43057 coordTimes: coordTimes
43060 function getPlacemark(root) {
43061 var geomsAndTimes = getGeometry(root), i, properties = {},
43062 name = nodeVal(get1(root, 'name')),
43063 address = nodeVal(get1(root, 'address')),
43064 styleUrl = nodeVal(get1(root, 'styleUrl')),
43065 description = nodeVal(get1(root, 'description')),
43066 timeSpan = get1(root, 'TimeSpan'),
43067 timeStamp = get1(root, 'TimeStamp'),
43068 extendedData = get1(root, 'ExtendedData'),
43069 lineStyle = get1(root, 'LineStyle'),
43070 polyStyle = get1(root, 'PolyStyle'),
43071 visibility = get1(root, 'visibility');
43073 if (!geomsAndTimes.geoms.length) return [];
43074 if (name) properties.name = name;
43075 if (address) properties.address = address;
43077 if (styleUrl[0] !== '#') {
43078 styleUrl = '#' + styleUrl;
43081 properties.styleUrl = styleUrl;
43082 if (styleIndex[styleUrl]) {
43083 properties.styleHash = styleIndex[styleUrl];
43085 if (styleMapIndex[styleUrl]) {
43086 properties.styleMapHash = styleMapIndex[styleUrl];
43087 properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
43089 // Try to populate the lineStyle or polyStyle since we got the style hash
43090 var style = styleByHash[properties.styleHash];
43092 if (!lineStyle) lineStyle = get1(style, 'LineStyle');
43093 if (!polyStyle) polyStyle = get1(style, 'PolyStyle');
43096 if (description) properties.description = description;
43098 var begin = nodeVal(get1(timeSpan, 'begin'));
43099 var end = nodeVal(get1(timeSpan, 'end'));
43100 properties.timespan = { begin: begin, end: end };
43103 properties.timestamp = nodeVal(get1(timeStamp, 'when'));
43106 var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))),
43107 color = linestyles[0],
43108 opacity = linestyles[1],
43109 width = parseFloat(nodeVal(get1(lineStyle, 'width')));
43110 if (color) properties.stroke = color;
43111 if (!isNaN(opacity)) properties['stroke-opacity'] = opacity;
43112 if (!isNaN(width)) properties['stroke-width'] = width;
43115 var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))),
43116 pcolor = polystyles[0],
43117 popacity = polystyles[1],
43118 fill = nodeVal(get1(polyStyle, 'fill')),
43119 outline = nodeVal(get1(polyStyle, 'outline'));
43120 if (pcolor) properties.fill = pcolor;
43121 if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
43122 if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0;
43123 if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0;
43125 if (extendedData) {
43126 var datas = get(extendedData, 'Data'),
43127 simpleDatas = get(extendedData, 'SimpleData');
43129 for (i = 0; i < datas.length; i++) {
43130 properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
43132 for (i = 0; i < simpleDatas.length; i++) {
43133 properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
43137 properties.visibility = nodeVal(visibility);
43139 if (geomsAndTimes.coordTimes.length) {
43140 properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
43141 geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
43145 geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : {
43146 type: 'GeometryCollection',
43147 geometries: geomsAndTimes.geoms
43149 properties: properties
43151 if (attr(root, 'id')) feature.id = attr(root, 'id');
43156 gpx: function(doc) {
43158 tracks = get(doc, 'trk'),
43159 routes = get(doc, 'rte'),
43160 waypoints = get(doc, 'wpt'),
43161 // a feature collection
43164 for (i = 0; i < tracks.length; i++) {
43165 feature = getTrack(tracks[i]);
43166 if (feature) gj.features.push(feature);
43168 for (i = 0; i < routes.length; i++) {
43169 feature = getRoute(routes[i]);
43170 if (feature) gj.features.push(feature);
43172 for (i = 0; i < waypoints.length; i++) {
43173 gj.features.push(getPoint(waypoints[i]));
43175 function getPoints(node, pointname) {
43176 var pts = get(node, pointname),
43181 if (l < 2) return {}; // Invalid line in GeoJSON
43182 for (var i = 0; i < l; i++) {
43183 var c = coordPair(pts[i]);
43184 line.push(c.coordinates);
43185 if (c.time) times.push(c.time);
43186 if (c.heartRate) heartRates.push(c.heartRate);
43191 heartRates: heartRates
43194 function getTrack(node) {
43195 var segments = get(node, 'trkseg'),
43200 for (var i = 0; i < segments.length; i++) {
43201 line = getPoints(segments[i], 'trkpt');
43203 if (line.line) track.push(line.line);
43204 if (line.times && line.times.length) times.push(line.times);
43205 if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates);
43208 if (track.length === 0) return;
43209 var properties = getProperties(node);
43210 extend(properties, getLineStyle(get1(node, 'extensions')));
43211 if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times;
43212 if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates;
43215 properties: properties,
43217 type: track.length === 1 ? 'LineString' : 'MultiLineString',
43218 coordinates: track.length === 1 ? track[0] : track
43222 function getRoute(node) {
43223 var line = getPoints(node, 'rtept');
43224 if (!line.line) return;
43225 var prop = getProperties(node);
43226 extend(prop, getLineStyle(get1(node, 'extensions')));
43231 type: 'LineString',
43232 coordinates: line.line
43237 function getPoint(node) {
43238 var prop = getProperties(node);
43239 extend(prop, getMulti(node, ['sym']));
43245 coordinates: coordPair(node).coordinates
43249 function getLineStyle(extensions) {
43252 var lineStyle = get1(extensions, 'line');
43254 var color = nodeVal(get1(lineStyle, 'color')),
43255 opacity = parseFloat(nodeVal(get1(lineStyle, 'opacity'))),
43256 width = parseFloat(nodeVal(get1(lineStyle, 'width')));
43257 if (color) style.stroke = color;
43258 if (!isNaN(opacity)) style['stroke-opacity'] = opacity;
43259 // GPX width is in mm, convert to px with 96 px per inch
43260 if (!isNaN(width)) style['stroke-width'] = width * 96 / 25.4;
43265 function getProperties(node) {
43266 var prop = getMulti(node, ['name', 'cmt', 'desc', 'type', 'time', 'keywords']),
43267 links = get(node, 'link');
43268 if (links.length) prop.links = [];
43269 for (var i = 0, link; i < links.length; i++) {
43270 link = { href: attr(links[i], 'href') };
43271 extend(link, getMulti(links[i], ['text', 'type']));
43272 prop.links.push(link);
43282 module.exports = toGeoJSON;
43285 function svgGpx(projection$$1, context, dispatch$$1) {
43286 var showLabels = true,
43287 detected = utilDetect(),
43292 if (svgGpx.initialized) return; // run once
43294 svgGpx.geojson = {};
43295 svgGpx.enabled = true;
43298 event.stopPropagation();
43299 event.preventDefault();
43300 event.dataTransfer.dropEffect = 'copy';
43304 .attr('dropzone', 'copy')
43305 .on('drop.localgpx', function() {
43306 event.stopPropagation();
43307 event.preventDefault();
43308 if (!detected.filedrop) return;
43309 drawGpx.files(event.dataTransfer.files);
43311 .on('dragenter.localgpx', over)
43312 .on('dragexit.localgpx', over)
43313 .on('dragover.localgpx', over);
43315 svgGpx.initialized = true;
43319 function drawGpx(selection$$1) {
43320 var geojson = svgGpx.geojson,
43321 enabled = svgGpx.enabled;
43323 layer = selection$$1.selectAll('.layer-gpx')
43324 .data(enabled ? [0] : []);
43329 layer = layer.enter()
43331 .attr('class', 'layer-gpx')
43342 paths = paths.enter()
43344 .attr('class', 'gpx')
43348 var path$$1 = index$4(projection$$1);
43351 .attr('d', path$$1);
43354 var labels = layer.selectAll('text')
43355 .data(showLabels && geojson.features ? geojson.features : []);
43360 labels = labels.enter()
43362 .attr('class', 'gpx')
43366 .text(function(d) {
43367 return d.properties.desc || d.properties.name;
43369 .attr('x', function(d) {
43370 var centroid = path$$1.centroid(d);
43371 return centroid[0] + 7;
43373 .attr('y', function(d) {
43374 var centroid = path$$1.centroid(d);
43375 return centroid[1];
43381 function toDom(x) {
43382 return (new DOMParser()).parseFromString(x, 'text/xml');
43386 function getExtension(fileName) {
43387 if (lodash.isUndefined(fileName)) {
43391 var lastDotIndex = fileName.lastIndexOf('.');
43392 if (lastDotIndex < 0) {
43396 return fileName.substr(lastDotIndex);
43400 function parseSaveAndZoom(extension, data) {
43401 switch (extension) {
43403 drawGpx.geojson(togeojson.gpx(toDom(data))).fitZoom();
43406 drawGpx.geojson(togeojson.kml(toDom(data))).fitZoom();
43410 drawGpx.geojson(JSON.parse(data)).fitZoom();
43416 drawGpx.showLabels = function(_) {
43417 if (!arguments.length) return showLabels;
43423 drawGpx.enabled = function(_) {
43424 if (!arguments.length) return svgGpx.enabled;
43425 svgGpx.enabled = _;
43426 dispatch$$1.call('change');
43431 drawGpx.hasGpx = function() {
43432 var geojson = svgGpx.geojson;
43433 return (!(lodash.isEmpty(geojson) || lodash.isEmpty(geojson.features)));
43437 drawGpx.geojson = function(gj) {
43438 if (!arguments.length) return svgGpx.geojson;
43439 if (lodash.isEmpty(gj) || lodash.isEmpty(gj.features)) return this;
43440 svgGpx.geojson = gj;
43441 dispatch$$1.call('change');
43446 drawGpx.url = function(url) {
43447 text(url, function(err, data) {
43449 var extension = getExtension(url);
43450 parseSaveAndZoom(extension, data);
43457 drawGpx.files = function(fileList) {
43458 if (!fileList.length) return this;
43459 var f = fileList[0],
43460 reader = new FileReader();
43462 reader.onload = (function(file) {
43463 var extension = getExtension(file.name);
43465 return function (e) {
43466 parseSaveAndZoom(extension, e.target.result);
43470 reader.readAsText(f);
43475 drawGpx.fitZoom = function() {
43476 if (!this.hasGpx()) return this;
43477 var geojson = svgGpx.geojson;
43479 var map = context.map(),
43480 viewport = map.trimmedExtent().polygon(),
43481 coords = lodash.reduce(geojson.features, function(coords, feature) {
43482 var c = feature.geometry.coordinates;
43484 /* eslint-disable no-fallthrough */
43485 switch (feature.geometry.type) {
43492 case 'MultiPolygon':
43493 c = lodash.flatten(c);
43495 case 'MultiLineString':
43496 c = lodash.flatten(c);
43499 /* eslint-enable no-fallthrough */
43501 return lodash.union(coords, c);
43504 if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
43505 var extent$$1 = geoExtent$$1(bounds({ type: 'LineString', coordinates: coords }));
43506 map.centerZoom(extent$$1.center(), map.trimmedExtentZoom(extent$$1));
43517 function svgIcon(name, svgklass, useklass) {
43518 return function drawIcon(selection) {
43519 selection.selectAll('svg')
43523 .attr('class', 'icon ' + (svgklass || ''))
43525 .attr('xlink:href', name)
43526 .attr('class', useklass);
43530 function svgLabels(projection$$1, context) {
43531 var path$$1 = index$4(projection$$1),
43532 detected = utilDetect(),
43533 baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'),
43534 rdrawn = index$9(),
43535 rskipped = index$9(),
43536 textWidthCache = {},
43539 // Listed from highest to lowest priority
43541 ['line', 'aeroway', '*', 12],
43542 ['line', 'highway', 'motorway', 12],
43543 ['line', 'highway', 'trunk', 12],
43544 ['line', 'highway', 'primary', 12],
43545 ['line', 'highway', 'secondary', 12],
43546 ['line', 'highway', 'tertiary', 12],
43547 ['line', 'highway', '*', 12],
43548 ['line', 'railway', '*', 12],
43549 ['line', 'waterway', '*', 12],
43550 ['area', 'aeroway', '*', 12],
43551 ['area', 'amenity', '*', 12],
43552 ['area', 'building', '*', 12],
43553 ['area', 'historic', '*', 12],
43554 ['area', 'leisure', '*', 12],
43555 ['area', 'man_made', '*', 12],
43556 ['area', 'natural', '*', 12],
43557 ['area', 'shop', '*', 12],
43558 ['area', 'tourism', '*', 12],
43559 ['area', 'camp_site', '*', 12],
43560 ['point', 'aeroway', '*', 10],
43561 ['point', 'amenity', '*', 10],
43562 ['point', 'building', '*', 10],
43563 ['point', 'historic', '*', 10],
43564 ['point', 'leisure', '*', 10],
43565 ['point', 'man_made', '*', 10],
43566 ['point', 'natural', '*', 10],
43567 ['point', 'shop', '*', 10],
43568 ['point', 'tourism', '*', 10],
43569 ['point', 'camp_site', '*', 10],
43570 ['line', 'name', '*', 12],
43571 ['area', 'name', '*', 12],
43572 ['point', 'name', '*', 10]
43576 function blacklisted(preset) {
43577 var noIcons = ['building', 'landuse', 'natural'];
43578 return lodash.some(noIcons, function(s) {
43579 return preset.id.indexOf(s) >= 0;
43584 function get(array, prop) {
43585 return function(d, i) { return array[i][prop]; };
43589 function textWidth(text$$1, size, elem) {
43590 var c = textWidthCache[size];
43591 if (!c) c = textWidthCache[size] = {};
43597 c[text$$1] = elem.getComputedTextLength();
43601 var str = encodeURIComponent(text$$1).match(/%[CDEFcdef]/g);
43602 if (str === null) {
43603 return size / 3 * 2 * text$$1.length;
43605 return size / 3 * (2 * text$$1.length + str.length);
43611 function drawLinePaths(selection$$1, entities, filter, classes, labels) {
43612 var paths = selection$$1.selectAll('path')
43614 .data(entities, osmEntity$$1.key);
43621 .style('stroke-width', get(labels, 'font-size'))
43622 .attr('id', function(d) { return 'labelpath-' + d.id; })
43623 .attr('class', classes)
43625 .attr('d', get(labels, 'lineString'));
43629 function drawLineLabels(selection$$1, entities, filter, classes, labels) {
43630 var texts = selection$$1.selectAll('text.' + classes)
43632 .data(entities, osmEntity$$1.key);
43639 .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
43640 .attr('dy', baselineHack ? '0.35em' : null)
43641 .append('textPath')
43642 .attr('class', 'textpath');
43644 texts = selection$$1.selectAll('text.' + classes);
43646 texts.selectAll('.textpath')
43648 .data(entities, osmEntity$$1.key)
43649 .attr('startOffset', '50%')
43650 .attr('xlink:href', function(d) { return '#labelpath-' + d.id; })
43651 .text(utilDisplayNameForPath);
43655 function drawPointLabels(selection$$1, entities, filter, classes, labels) {
43656 var texts = selection$$1.selectAll('text.' + classes)
43658 .data(entities, osmEntity$$1.key);
43663 texts = texts.enter()
43665 .attr('class', function(d, i) {
43666 return classes + ' ' + labels[i].classes + ' ' + d.id;
43671 .attr('x', get(labels, 'x'))
43672 .attr('y', get(labels, 'y'))
43673 .style('text-anchor', get(labels, 'textAnchor'))
43674 .text(utilDisplayName)
43675 .each(function(d, i) {
43676 textWidth(utilDisplayName(d), labels[i].height, this);
43681 function drawAreaLabels(selection$$1, entities, filter, classes, labels) {
43682 entities = entities.filter(hasText);
43683 labels = labels.filter(hasText);
43684 drawPointLabels(selection$$1, entities, filter, classes, labels);
43686 function hasText(d, i) {
43687 return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
43692 function drawAreaIcons(selection$$1, entities, filter, classes, labels) {
43693 var icons = selection$$1.selectAll('use.' + classes)
43695 .data(entities, osmEntity$$1.key);
43700 icons = icons.enter()
43702 .attr('class', 'icon ' + classes)
43703 .attr('width', '17px')
43704 .attr('height', '17px')
43708 .attr('transform', get(labels, 'transform'))
43709 .attr('xlink:href', function(d) {
43710 var preset = context.presets().match(d, context.graph()),
43711 picon = preset && preset.icon;
43716 var isMaki = dataFeatureIcons.indexOf(picon) !== -1;
43717 return '#' + picon + (isMaki ? '-15' : '');
43723 function drawCollisionBoxes(selection$$1, rtree, which) {
43724 var showDebug = context.getDebug('collision'),
43725 classes = 'debug ' + which + ' ' +
43726 (which === 'debug-skipped' ? 'orange' : 'yellow');
43728 var debug = selection$$1.selectAll('.layer-label-debug')
43729 .data(showDebug ? [true] : []);
43734 debug = debug.enter()
43736 .attr('class', 'layer-label-debug')
43740 var gj = rtree.all().map(function(d) {
43741 return { type: 'Polygon', coordinates: [[
43750 var debugboxes = debug.selectAll('.' + which)
43756 debugboxes = debugboxes.enter()
43758 .attr('class', classes)
43759 .merge(debugboxes);
43762 .attr('d', index$4());
43767 function drawLabels(selection$$1, graph, entities, filter, dimensions, fullRedraw) {
43768 var lowZoom = context.surface().classed('low-zoom');
43770 var labelable = [], i, j, k, entity, geometry;
43771 for (i = 0; i < labelStack.length; i++) {
43772 labelable.push([]);
43780 for (i = 0; i < entities.length; i++) {
43781 entity = entities[i];
43783 .concat(entitybboxes[entity.id] || [])
43784 .concat(entitybboxes[entity.id + 'I'] || []);
43786 for (j = 0; j < toRemove.length; j++) {
43787 rdrawn.remove(toRemove[j]);
43788 rskipped.remove(toRemove[j]);
43793 // Split entities into groups specified by labelStack
43794 for (i = 0; i < entities.length; i++) {
43795 entity = entities[i];
43796 geometry = entity.geometry(graph);
43797 if (geometry === 'vertex') { geometry = 'point'; } // treat vertex like point
43799 var preset = geometry === 'area' && context.presets().match(entity, graph),
43800 icon = preset && !blacklisted(preset) && preset.icon;
43802 if (!icon && !utilDisplayName(entity))
43805 for (k = 0; k < labelStack.length; k++) {
43806 var matchGeom = labelStack[k][0],
43807 matchKey = labelStack[k][1],
43808 matchVal = labelStack[k][2],
43809 hasVal = entity.tags[matchKey];
43811 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
43812 labelable[k].push(entity);
43830 // Try and find a valid label for labellable entities
43831 for (k = 0; k < labelable.length; k++) {
43832 var fontSize = labelStack[k][3];
43833 for (i = 0; i < labelable[k].length; i++) {
43834 entity = labelable[k][i];
43835 geometry = entity.geometry(graph);
43837 var getName = (geometry === 'line') ? utilDisplayNameForPath : utilDisplayName,
43838 name = getName(entity),
43839 width = name && textWidth(name, fontSize),
43842 if (geometry === 'point') {
43843 p = getPointLabel(entity, width, fontSize, geometry);
43844 } else if (geometry === 'vertex' && !lowZoom) {
43845 // don't label vertices at low zoom because they don't have icons
43846 p = getPointLabel(entity, width, fontSize, geometry);
43847 } else if (geometry === 'line') {
43848 p = getLineLabel(entity, width, fontSize);
43849 } else if (geometry === 'area') {
43850 p = getAreaLabel(entity, width, fontSize);
43854 if (geometry === 'vertex') { geometry = 'point'; } // treat vertex like point
43855 p.classes = geometry + ' tag-' + labelStack[k][1];
43856 positions[geometry].push(p);
43857 labelled[geometry].push(entity);
43863 function getPointLabel(entity, width, height, geometry) {
43864 var y = (geometry === 'point' ? -12 : 0),
43866 ltr: [15, y, 'start'],
43867 rtl: [-15, y, 'end']
43870 var coord = projection$$1(entity.loc),
43872 offset = pointOffsets[textDirection],
43876 x: coord[0] + offset[0],
43877 y: coord[1] + offset[1],
43878 textAnchor: offset[2]
43882 if (textDirection === 'rtl') {
43884 minX: p.x - width - margin,
43885 minY: p.y - (height / 2) - margin,
43886 maxX: p.x + margin,
43887 maxY: p.y + (height / 2) + margin
43891 minX: p.x - margin,
43892 minY: p.y - (height / 2) - margin,
43893 maxX: p.x + width + margin,
43894 maxY: p.y + (height / 2) + margin
43898 if (tryInsert([bbox], entity.id, true)) {
43904 function getLineLabel(entity, width, height) {
43905 var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
43906 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection$$1),
43907 length = geoPathLength(nodes);
43909 if (length < width + 20) return;
43911 // % along the line to attempt to place the label
43912 var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
43913 25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
43916 for (var i = 0; i < lineOffsets.length; i++) {
43917 var offset = lineOffsets[i],
43918 middle = offset / 100 * length,
43919 start = middle - width / 2;
43921 if (start < 0 || start + width > length) continue;
43923 // generate subpath and ignore paths that are invalid or don't cross viewport.
43924 var sub = subpath(nodes, start, start + width);
43925 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
43929 var isReverse = reverse$$1(sub);
43931 sub = sub.reverse();
43935 boxsize = (height + 2) / 2;
43937 for (var j = 0; j < sub.length - 1; j++) {
43939 var b = sub[j + 1];
43940 var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
43942 for (var box = 0; box < num; box++) {
43943 var p = geoInterp(a, b, box / num);
43944 var x0 = p[0] - boxsize - margin;
43945 var y0 = p[1] - boxsize - margin;
43946 var x1 = p[0] + boxsize + margin;
43947 var y1 = p[1] + boxsize + margin;
43950 minX: Math.min(x0, x1),
43951 minY: Math.min(y0, y1),
43952 maxX: Math.max(x0, x1),
43953 maxY: Math.max(y0, y1)
43958 if (tryInsert(bboxes, entity.id, false)) {
43960 'font-size': height + 2,
43961 lineString: lineString(sub),
43962 startOffset: offset + '%'
43967 function reverse$$1(p) {
43968 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
43969 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
43972 function lineString(nodes) {
43973 return 'M' + nodes.join('L');
43976 function subpath(nodes, from, to) {
43978 start, end, i0, i1;
43980 for (var i = 0; i < nodes.length - 1; i++) {
43983 var current = geoEuclideanDistance(a, b);
43985 if (!start && sofar + current >= from) {
43986 portion = (from - sofar) / current;
43988 a[0] + portion * (b[0] - a[0]),
43989 a[1] + portion * (b[1] - a[1])
43993 if (!end && sofar + current >= to) {
43994 portion = (to - sofar) / current;
43996 a[0] + portion * (b[0] - a[0]),
43997 a[1] + portion * (b[1] - a[1])
44004 var ret = nodes.slice(i0, i1);
44005 ret.unshift(start);
44012 function getAreaLabel(entity, width, height) {
44013 var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
44014 extent$$1 = entity.extent(graph),
44015 entitywidth = projection$$1(extent$$1[1])[0] - projection$$1(extent$$1[0])[0];
44017 if (isNaN(centroid[0]) || entitywidth < 20) return;
44020 iconX = centroid[0] - (iconSize / 2),
44021 iconY = centroid[1] - (iconSize / 2),
44023 textOffset = iconSize + margin,
44024 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
44029 maxX: iconX + iconSize,
44030 maxY: iconY + iconSize
44034 if (tryInsert([bbox], entity.id + 'I', true)) {
44035 if (width && entitywidth >= width + 20) {
44036 var labelX = centroid[0],
44037 labelY = centroid[1] + textOffset;
44040 minX: labelX - (width / 2) - margin,
44041 minY: labelY - (height / 2) - margin,
44042 maxX: labelX + (width / 2) + margin,
44043 maxY: labelY + (height / 2) + margin
44046 // try to add label
44047 if (tryInsert([bbox], entity.id, true)) {
44050 p.textAnchor = 'middle';
44060 function tryInsert(bboxes, id, saveSkipped) {
44061 var skipped = false,
44064 for (var i = 0; i < bboxes.length; i++) {
44068 // Check that label is visible
44069 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
44073 if (rdrawn.collides(bbox)) {
44079 entitybboxes[id] = bboxes;
44083 rskipped.load(bboxes);
44086 rdrawn.load(bboxes);
44093 var label = selection$$1.selectAll('.layer-label'),
44094 halo = selection$$1.selectAll('.layer-halo');
44097 drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
44098 drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
44101 drawLinePaths(halo, labelled.line, filter, '', positions.line);
44102 drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
44103 drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
44106 drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
44107 drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
44108 drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
44109 drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area);
44112 drawCollisionBoxes(label, rskipped, 'debug-skipped');
44113 drawCollisionBoxes(label, rdrawn, 'debug-drawn');
44115 selection$$1.call(filterLabels);
44119 function filterLabels(selection$$1) {
44120 var layers = selection$$1
44121 .selectAll('.layer-label, .layer-halo');
44123 layers.selectAll('.proximate')
44124 .classed('proximate', false);
44126 var mouse$$1 = context.mouse(),
44127 graph = context.graph(),
44128 selectedIDs = context.selectedIDs(),
44132 // hide labels near the mouse
44135 bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad };
44136 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
44139 // hide labels along selected ways, or near selected vertices
44140 for (var i = 0; i < selectedIDs.length; i++) {
44141 var entity = graph.hasEntity(selectedIDs[i]);
44142 if (!entity) continue;
44143 var geometry = entity.geometry(graph);
44145 if (geometry === 'line') {
44146 ids.push(selectedIDs[i]);
44147 } else if (geometry === 'vertex') {
44148 var point = context.projection(entity.loc);
44150 bbox = { minX: point[0] - pad, minY: point[1] - pad, maxX: point[0] + pad, maxY: point[1] + pad };
44151 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
44155 layers.selectAll(utilEntitySelector(ids))
44156 .classed('proximate', true);
44160 var throttleFilterLabels = lodash.throttle(filterLabels, 100);
44163 drawLabels.observe = function(selection$$1) {
44164 var listener = function() { throttleFilterLabels(selection$$1); };
44165 selection$$1.on('mousemove.hidelabels', listener);
44166 context.on('enter.hidelabels', listener);
44170 drawLabels.off = function(selection$$1) {
44171 throttleFilterLabels.cancel();
44172 selection$$1.on('mousemove.hidelabels', null);
44173 context.on('enter.hidelabels', null);
44180 function refresh(selection, node) {
44181 var cr = node.getBoundingClientRect();
44182 var prop = [cr.width, cr.height];
44183 selection.property('__dimensions__', prop);
44187 function utilGetDimensions(selection, force) {
44188 if (!selection || selection.empty()) {
44191 var node = selection.node(),
44192 cached = selection.property('__dimensions__');
44193 return (!cached || force) ? refresh(selection, node) : cached;
44197 function utilSetDimensions(selection, dimensions) {
44198 if (!selection || selection.empty()) {
44201 var node = selection.node();
44202 if (dimensions === null) {
44203 refresh(selection, node);
44207 .property('__dimensions__', [dimensions[0], dimensions[1]])
44208 .attr('width', dimensions[0])
44209 .attr('height', dimensions[1]);
44212 function svgPointTransform(projection) {
44213 return function(entity) {
44214 // http://jsperf.com/short-array-join
44215 var pt = projection(entity.loc);
44216 return 'translate(' + pt[0] + ',' + pt[1] + ')';
44220 function d3geoTile() {
44221 var size = [960, 500],
44223 scaleExtent = [0, 20],
44224 translate = [size[0] / 2, size[1] / 2],
44227 function bound(_) {
44228 return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
44232 var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
44233 z0 = bound(Math.round(z + zoomDelta)),
44234 k = Math.pow(2, z - z0 + 8),
44235 origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
44237 cols = sequence(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
44238 rows = sequence(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
44240 rows.forEach(function(y) {
44241 cols.forEach(function(x) {
44242 tiles.push([x, y, z0]);
44246 tiles.translate = origin;
44252 tile.scaleExtent = function(_) {
44253 if (!arguments.length) return scaleExtent;
44258 tile.size = function(_) {
44259 if (!arguments.length) return size;
44264 tile.scale = function(_) {
44265 if (!arguments.length) return scale;
44270 tile.translate = function(_) {
44271 if (!arguments.length) return translate;
44276 tile.zoomDelta = function(_) {
44277 if (!arguments.length) return zoomDelta;
44285 /* global Mapillary:false */
44286 var apibase = 'https://a.mapillary.com/v3/';
44287 var viewercss = 'mapillary-js/mapillary.min.css';
44288 var viewerjs = 'mapillary-js/mapillary.min.js';
44289 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
44290 var maxResults = 1000;
44292 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
44293 var mapillaryCache;
44294 var mapillaryClicks;
44295 var mapillaryImage;
44296 var mapillarySignDefs;
44297 var mapillarySignSprite;
44298 var mapillaryViewer;
44301 function abortRequest(i) {
44306 function nearNullIsland(x, y, z) {
44308 var center = Math.pow(2, z - 1),
44309 width = Math.pow(2, z - 6),
44310 min$$1 = center - (width / 2),
44311 max$$1 = center + (width / 2) - 1;
44312 return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
44318 function maxPageAtZoom(z) {
44319 if (z < 15) return 2;
44320 if (z === 15) return 5;
44321 if (z === 16) return 10;
44322 if (z === 17) return 20;
44323 if (z === 18) return 40;
44324 if (z > 18) return 80;
44328 function getTiles(projection$$1) {
44329 var s = projection$$1.scale() * 2 * Math.PI,
44330 z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
44331 ts = 256 * Math.pow(2, z - tileZoom),
44333 s / 2 - projection$$1.translate()[0],
44334 s / 2 - projection$$1.translate()[1]];
44337 .scaleExtent([tileZoom, tileZoom])
44339 .size(projection$$1.clipExtent()[1])
44340 .translate(projection$$1.translate())()
44341 .map(function(tile) {
44342 var x = tile[0] * ts - origin[0],
44343 y = tile[1] * ts - origin[1];
44346 id: tile.toString(),
44348 extent: geoExtent$$1(
44349 projection$$1.invert([x, y + ts]),
44350 projection$$1.invert([x + ts, y])
44357 function loadTiles(which, url, projection$$1) {
44358 var s = projection$$1.scale() * 2 * Math.PI,
44359 currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0));
44361 var tiles = getTiles(projection$$1).filter(function(t) {
44362 return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
44365 lodash.filter(which.inflight, function(v, k) {
44366 var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
44367 if (!wanted) delete which.inflight[k];
44369 }).map(abortRequest);
44371 tiles.forEach(function(tile) {
44372 loadNextTilePage(which, currZoom, url, tile);
44377 function loadNextTilePage(which, currZoom, url, tile) {
44378 var cache = mapillaryCache[which],
44379 rect = tile.extent.rectangle(),
44380 maxPages = maxPageAtZoom(currZoom),
44381 nextPage = cache.nextPage[tile.id] || 0,
44382 nextURL = cache.nextURL[tile.id] || url +
44384 per_page: maxResults,
44386 client_id: clientId,
44387 bbox: [rect[0], rect[1], rect[2], rect[3]].join(','),
44390 if (nextPage > maxPages) return;
44392 var id = tile.id + ',' + String(nextPage);
44393 if (cache.loaded[id] || cache.inflight[id]) return;
44394 cache.inflight[id] = request(nextURL)
44395 .mimeType('application/json')
44396 .response(function(xhr) {
44397 var linkHeader = xhr.getResponseHeader('Link');
44399 var pagination = parsePagination(xhr.getResponseHeader('Link'));
44400 if (pagination.next) {
44401 cache.nextURL[tile.id] = pagination.next;
44405 return JSON.parse(xhr.responseText); })
44406 .get(function(err, data) {
44407 cache.loaded[id] = true;
44408 delete cache.inflight[id];
44409 if (err || !data.features || !data.features.length) return;
44414 for (var i = 0; i < data.features.length; i++) {
44415 feature = data.features[i];
44416 loc = feature.geometry.coordinates;
44417 d = { key: feature.properties.key, loc: loc };
44418 if (which === 'images') d = { ca: feature.properties.ca, key: feature.properties.key, loc: loc };
44419 if (which === 'signs') d = { key: feature.properties.detections[0].image_key, loc: loc, value: feature.properties.value };
44421 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
44424 cache.rtree.load(features);
44426 if (which === 'images') dispatch$2.call('loadedImages');
44427 if (which === 'signs') dispatch$2.call('loadedSigns');
44428 if (data.features.length === maxResults) { // more pages to load
44429 cache.nextPage[tile.id] = nextPage + 1;
44430 loadNextTilePage(which, currZoom, url, tile);
44432 cache.nextPage[tile.id] = Infinity; // no more pages to load
44437 // extract links to pages of API results
44438 function parsePagination(links) {
44439 return links.split(',').map(function(rel) {
44440 var elements = rel.split(';');
44441 if (elements.length === 2) {
44443 /<(.+)>/.exec(elements[0])[1],
44444 /rel="(.+)"/.exec(elements[1])[1]
44449 }).reduce(function(pagination, val) {
44450 pagination[val[1]] = val[0];
44456 // partition viewport into `psize` x `psize` regions
44457 function partitionViewport(psize, projection$$1) {
44458 var dimensions = projection$$1.clipExtent()[1];
44459 psize = psize || 16;
44460 var cols = sequence(0, dimensions[0], psize),
44461 rows = sequence(0, dimensions[1], psize),
44464 rows.forEach(function(y) {
44465 cols.forEach(function(x) {
44466 var min$$1 = [x, y + psize],
44467 max$$1 = [x + psize, y];
44469 geoExtent$$1(projection$$1.invert(min$$1), projection$$1.invert(max$$1)));
44477 // no more than `limit` results per partition.
44478 function searchLimited(psize, limit, projection$$1, rtree) {
44479 limit = limit || 3;
44481 var partitions = partitionViewport(psize, projection$$1);
44482 return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
44483 return rtree.search(extent$$1.bbox())
44485 .map(function(d) { return d.data; });
44491 var serviceMapillary = {
44494 if (!mapillaryCache) {
44498 this.event = utilRebind(this, dispatch$2, 'on');
44501 reset: function() {
44502 var cache = mapillaryCache;
44505 if (cache.images && cache.images.inflight) {
44506 lodash.forEach(cache.images.inflight, abortRequest);
44508 if (cache.signs && cache.signs.inflight) {
44509 lodash.forEach(cache.signs.inflight, abortRequest);
44514 images: { inflight: {}, loaded: {}, nextPage: {}, nextURL: {}, rtree: index$9() },
44515 signs: { inflight: {}, loaded: {}, nextPage: {}, nextURL: {}, rtree: index$9() }
44518 mapillaryImage = null;
44519 mapillaryClicks = [];
44523 images: function(projection$$1) {
44524 var psize = 16, limit = 3;
44525 return searchLimited(psize, limit, projection$$1, mapillaryCache.images.rtree);
44529 signs: function(projection$$1) {
44530 var psize = 32, limit = 3;
44531 return searchLimited(psize, limit, projection$$1, mapillaryCache.signs.rtree);
44535 signsSupported: function() {
44536 var detected = utilDetect();
44537 if (detected.ie) return false;
44538 if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
44543 signHTML: function(d) {
44544 if (!mapillarySignDefs || !mapillarySignSprite) return;
44545 var position = mapillarySignDefs[d.value];
44546 if (!position) return '<div></div>';
44548 'background-image:url(' + mapillarySignSprite + ')',
44549 'background-repeat:no-repeat',
44550 'height:' + position.height + 'px',
44551 'width:' + position.width + 'px',
44552 'background-position-x:-' + position.x + 'px',
44553 'background-position-y:-' + position.y + 'px',
44556 return '<div style="' + iconStyle.join(';') +'"></div>';
44560 loadImages: function(projection$$1) {
44561 var url = apibase + 'images?';
44562 loadTiles('images', url, projection$$1);
44566 loadSigns: function(context, projection$$1) {
44567 var url = apibase + 'objects?';
44568 loadTiles('signs', url, projection$$1);
44570 // load traffic sign defs
44571 if (!mapillarySignDefs) {
44572 mapillarySignSprite = context.asset('img/traffic-signs/traffic-signs.png');
44573 mapillarySignDefs = {};
44574 json(context.asset('img/traffic-signs/traffic-signs.json'), function(err, data) {
44576 mapillarySignDefs = data;
44582 loadViewer: function(context) {
44584 var wrap = select('#content').selectAll('.mapillary-wrap')
44587 var enter = wrap.enter()
44589 .attr('class', 'mapillary-wrap')
44590 .classed('al', true) // 'al'=left, 'ar'=right
44591 .classed('hidden', true);
44595 .attr('class', 'thumb-hide')
44596 .on('click', function () { that.hideViewer(); })
44598 .call(svgIcon('#icon-close'));
44603 .attr('class', 'mly-wrapper')
44604 .classed('active', false);
44606 // load mapillary-viewercss
44607 select('head').selectAll('#mapillary-viewercss')
44611 .attr('id', 'mapillary-viewercss')
44612 .attr('rel', 'stylesheet')
44613 .attr('href', context.asset(viewercss));
44615 // load mapillary-viewerjs
44616 select('head').selectAll('#mapillary-viewerjs')
44620 .attr('id', 'mapillary-viewerjs')
44621 .attr('src', context.asset(viewerjs));
44625 showViewer: function() {
44627 .selectAll('.mapillary-wrap')
44628 .classed('hidden', false)
44629 .selectAll('.mly-wrapper')
44630 .classed('active', true);
44636 hideViewer: function() {
44638 .selectAll('.mapillary-wrap')
44639 .classed('hidden', true)
44640 .selectAll('.mly-wrapper')
44641 .classed('active', false);
44643 selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44644 .classed('selected', false);
44646 mapillaryImage = null;
44651 parsePagination: parsePagination,
44654 updateViewer: function(imageKey, context) {
44655 if (!imageKey) return;
44657 if (!mapillaryViewer) {
44658 this.initViewer(imageKey, context);
44660 mapillaryViewer.moveToKey(imageKey);
44667 initViewer: function(imageKey, context) {
44669 if (Mapillary && imageKey) {
44671 baseImageSize: 320,
44678 mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
44679 mapillaryViewer.on('nodechanged', nodeChanged);
44682 function nodeChanged(node) {
44683 var clicks = mapillaryClicks;
44684 var index = clicks.indexOf(node.key);
44685 if (index > -1) { // nodechange initiated from clicking on a marker..
44686 clicks.splice(index, 1);
44687 } else { // nodechange initiated from the Mapillary viewer controls..
44688 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
44689 context.map().centerEase(loc);
44690 that.selectedImage(node.key, false);
44696 selectedImage: function(imageKey, fromClick) {
44697 if (!arguments.length) return mapillaryImage;
44699 mapillaryImage = imageKey;
44701 mapillaryClicks.push(imageKey);
44704 selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44705 .classed('selected', function(d) { return d.key === imageKey; });
44711 cache: function(_) {
44712 if (!arguments.length) return mapillaryCache;
44713 mapillaryCache = _;
44718 signDefs: function(_) {
44719 if (!arguments.length) return mapillarySignDefs;
44720 mapillarySignDefs = _;
44726 var apibase$1 = 'https://nominatim.openstreetmap.org/';
44728 var nominatimCache;
44731 var serviceNominatim = {
44735 nominatimCache = index$9();
44738 reset: function() {
44739 lodash.forEach(inflight, function(req) { req.abort(); });
44741 nominatimCache = index$9();
44745 countryCode: function (location, callback) {
44746 this.reverse(location, function(err, result) {
44748 return callback(err);
44749 } else if (result.address) {
44750 return callback(null, result.address.country_code);
44752 return callback('Unable to geocode', null);
44758 reverse: function (location, callback) {
44759 var cached = nominatimCache.search(
44760 { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
44763 if (cached.length > 0) {
44764 return callback(null, cached[0].data);
44767 var params = { zoom: 13, format: 'json', addressdetails: 1, lat: location[1], lon: location[0] };
44768 var url = apibase$1 + 'reverse?' + utilQsString(params);
44769 if (inflight[url]) return;
44771 inflight[url] = json(url, function(err, result) {
44772 delete inflight[url];
44775 return callback(err);
44776 } else if (result && result.error) {
44777 return callback(result.error);
44780 var extent$$1 = geoExtent$$1(location).padByMeters(200);
44781 nominatimCache.insert(lodash.assign(extent$$1.bbox(), {data: result}));
44783 callback(null, result);
44788 search: function (val, callback) {
44789 var searchVal = encodeURIComponent(val);
44790 var url = apibase$1 + 'search/' + searchVal + '?limit=10&format=json';
44791 if (inflight[url]) return;
44793 inflight[url] = json(url, function(err, result) {
44794 delete inflight[url];
44795 callback(err, result);
44801 var hashes = createCommonjsModule(function (module, exports) {
44803 * jshashes - https://github.com/h2non/jshashes
44804 * Released under the "New BSD" license
44806 * Algorithms specification:
44808 * MD5 - http://www.ietf.org/rfc/rfc1321.txt
44809 * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
44810 * SHA1 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44811 * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44812 * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44813 * HMAC - http://www.ietf.org/rfc/rfc2104.txt
44818 function utf8Encode(str) {
44819 var x, y, output = '',
44823 if (str && str.length) {
44825 while ((i += 1) < l) {
44826 /* Decode utf-16 surrogate pairs */
44827 x = str.charCodeAt(i);
44828 y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
44829 if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
44830 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
44833 /* Encode output as utf-8 */
44835 output += String.fromCharCode(x);
44836 } else if (x <= 0x7FF) {
44837 output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
44838 0x80 | (x & 0x3F));
44839 } else if (x <= 0xFFFF) {
44840 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
44841 0x80 | ((x >>> 6) & 0x3F),
44842 0x80 | (x & 0x3F));
44843 } else if (x <= 0x1FFFFF) {
44844 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
44845 0x80 | ((x >>> 12) & 0x3F),
44846 0x80 | ((x >>> 6) & 0x3F),
44847 0x80 | (x & 0x3F));
44854 function utf8Decode(str) {
44855 var i, ac, c1, c2, c3, arr = [],
44857 i = ac = c1 = c2 = c3 = 0;
44859 if (str && str.length) {
44864 c1 = str.charCodeAt(i);
44867 arr[ac] = String.fromCharCode(c1);
44869 } else if (c1 > 191 && c1 < 224) {
44870 c2 = str.charCodeAt(i + 1);
44871 arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
44874 c2 = str.charCodeAt(i + 1);
44875 c3 = str.charCodeAt(i + 2);
44876 arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
44881 return arr.join('');
44885 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
44886 * to work around bugs in some JS interpreters.
44889 function safe_add(x, y) {
44890 var lsw = (x & 0xFFFF) + (y & 0xFFFF),
44891 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
44892 return (msw << 16) | (lsw & 0xFFFF);
44896 * Bitwise rotate a 32-bit number to the left.
44899 function bit_rol(num, cnt) {
44900 return (num << cnt) | (num >>> (32 - cnt));
44904 * Convert a raw string to a hex string
44907 function rstr2hex(input, hexcase) {
44908 var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
44912 for (; i < l; i += 1) {
44913 x = input.charCodeAt(i);
44914 output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
44920 * Encode a string as utf-16
44923 function binb2rstr(input) {
44924 var i, l = input.length * 32,
44926 for (i = 0; i < l; i += 8) {
44927 output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
44933 * Convert an array of little-endian words to a string
44936 function binl2rstr(input) {
44937 var i, l = input.length * 32,
44939 for (i = 0; i < l; i += 8) {
44940 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
44946 * Convert a raw string to an array of little-endian words
44947 * Characters >255 have their high-byte silently ignored.
44950 function rstr2binl(input) {
44951 var i, l = input.length * 8,
44952 output = Array(input.length >> 2),
44953 lo = output.length;
44954 for (i = 0; i < lo; i += 1) {
44957 for (i = 0; i < l; i += 8) {
44958 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
44964 * Convert a raw string to an array of big-endian words
44965 * Characters >255 have their high-byte silently ignored.
44968 function rstr2binb(input) {
44969 var i, l = input.length * 8,
44970 output = Array(input.length >> 2),
44971 lo = output.length;
44972 for (i = 0; i < lo; i += 1) {
44975 for (i = 0; i < l; i += 8) {
44976 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
44982 * Convert a raw string to an arbitrary string encoding
44985 function rstr2any(input, encoding) {
44986 var divisor = encoding.length,
44987 remainders = Array(),
44988 i, q, x, ld, quotient, dividend, output, full_length;
44990 /* Convert to an array of 16-bit big-endian values, forming the dividend */
44991 dividend = Array(Math.ceil(input.length / 2));
44992 ld = dividend.length;
44993 for (i = 0; i < ld; i += 1) {
44994 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
44998 * Repeatedly perform a long division. The binary array forms the dividend,
44999 * the length of the encoding is the divisor. Once computed, the quotient
45000 * forms the dividend for the next step. We stop when the dividend is zerHashes.
45001 * All remainders are stored for later use.
45003 while (dividend.length > 0) {
45004 quotient = Array();
45006 for (i = 0; i < dividend.length; i += 1) {
45007 x = (x << 16) + dividend[i];
45008 q = Math.floor(x / divisor);
45010 if (quotient.length > 0 || q > 0) {
45011 quotient[quotient.length] = q;
45014 remainders[remainders.length] = x;
45015 dividend = quotient;
45018 /* Convert the remainders to the output string */
45020 for (i = remainders.length - 1; i >= 0; i--) {
45021 output += encoding.charAt(remainders[i]);
45024 /* Append leading zero equivalents */
45025 full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
45026 for (i = output.length; i < full_length; i += 1) {
45027 output = encoding[0] + output;
45033 * Convert a raw string to a base-64 string
45036 function rstr2b64(input, b64pad) {
45037 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
45039 len = input.length,
45041 b64pad = b64pad || '=';
45042 for (i = 0; i < len; i += 3) {
45043 triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
45044 for (j = 0; j < 4; j += 1) {
45045 if (i * 8 + j * 6 > input.length * 8) {
45048 output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
45057 * @property {String} version
45066 Base64: function() {
45067 // private properties
45068 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
45069 pad = '=', // default pad according with the RFC standard
45070 url = false, // URL encoding support @todo
45071 utf8 = true; // by default enable UTF-8 support encoding
45073 // public method for encoding
45074 this.encode = function(input) {
45077 len = input.length;
45080 input = (utf8) ? utf8Encode(input) : input;
45082 for (i = 0; i < len; i += 3) {
45083 triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
45084 for (j = 0; j < 4; j += 1) {
45085 if (i * 8 + j * 6 > len * 8) {
45088 output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
45095 // public method for decoding
45096 this.decode = function(input) {
45097 // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
45098 var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
45106 input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
45109 do { // unpack four hexets into three octets using index points in b64
45110 h1 = tab.indexOf(input.charAt(i += 1));
45111 h2 = tab.indexOf(input.charAt(i += 1));
45112 h3 = tab.indexOf(input.charAt(i += 1));
45113 h4 = tab.indexOf(input.charAt(i += 1));
45115 bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
45117 o1 = bits >> 16 & 0xff;
45118 o2 = bits >> 8 & 0xff;
45123 arr[ac] = String.fromCharCode(o1);
45124 } else if (h4 === 64) {
45125 arr[ac] = String.fromCharCode(o1, o2);
45127 arr[ac] = String.fromCharCode(o1, o2, o3);
45129 } while (i < input.length);
45131 dec = arr.join('');
45132 dec = (utf8) ? utf8Decode(dec) : dec;
45137 // set custom pad string
45138 this.setPad = function(str) {
45142 // set custom tab string characters
45143 this.setTab = function(str) {
45147 this.setUTF8 = function(bool) {
45148 if (typeof bool === 'boolean') {
45156 * CRC-32 calculation
45160 * @param {String} str Input String
45163 CRC32: function(str) {
45168 str = utf8Encode(str);
45171 '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
45172 '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
45173 '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
45174 '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
45175 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
45176 '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
45177 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
45178 '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
45179 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
45180 '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
45181 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
45182 '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
45183 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
45184 '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
45185 '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
45186 '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
45187 '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
45188 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
45189 '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
45190 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
45191 '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
45192 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
45193 '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
45194 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
45195 '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
45196 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
45200 for (i = 0, iTop = str.length; i < iTop; i += 1) {
45201 y = (crc ^ str.charCodeAt(i)) & 0xFF;
45202 x = '0x' + table.substr(y * 9, 8);
45203 crc = (crc >>> 8) ^ x;
45205 // always return a positive number (that's what >>> 0 does)
45206 return (crc ^ (-1)) >>> 0;
45212 * @param {Object} [config]
45214 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
45215 * Digest Algorithm, as defined in RFC 1321.
45216 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
45217 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45218 * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
45220 MD5: function(options) {
45222 * Private config properties. You may need to tweak these to be compatible with
45223 * the server-side, but the defaults work in most cases.
45224 * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
45226 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
45227 b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
45228 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
45230 // privileged (public) methods
45231 this.hex = function(s) {
45232 return rstr2hex(rstr(s, utf8), hexcase);
45234 this.b64 = function(s) {
45235 return rstr2b64(rstr(s), b64pad);
45237 this.any = function(s, e) {
45238 return rstr2any(rstr(s, utf8), e);
45240 this.raw = function(s) {
45241 return rstr(s, utf8);
45243 this.hex_hmac = function(k, d) {
45244 return rstr2hex(rstr_hmac(k, d), hexcase);
45246 this.b64_hmac = function(k, d) {
45247 return rstr2b64(rstr_hmac(k, d), b64pad);
45249 this.any_hmac = function(k, d, e) {
45250 return rstr2any(rstr_hmac(k, d), e);
45253 * Perform a simple self-test to see if the VM is working
45254 * @return {String} Hexadecimal hash sample
45256 this.vm_test = function() {
45257 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45260 * Enable/disable uppercase hexadecimal returned string
45262 * @return {Object} this
45264 this.setUpperCase = function(a) {
45265 if (typeof a === 'boolean') {
45271 * Defines a base64 pad string
45272 * @param {String} Pad
45273 * @return {Object} this
45275 this.setPad = function(a) {
45276 b64pad = a || b64pad;
45280 * Defines a base64 pad string
45282 * @return {Object} [this]
45284 this.setUTF8 = function(a) {
45285 if (typeof a === 'boolean') {
45294 * Calculate the MD5 of a raw string
45298 s = (utf8) ? utf8Encode(s) : s;
45299 return binl2rstr(binl(rstr2binl(s), s.length * 8));
45303 * Calculate the HMAC-MD5, of a key and some data (raw strings)
45306 function rstr_hmac(key, data) {
45307 var bkey, ipad, opad, hash, i;
45309 key = (utf8) ? utf8Encode(key) : key;
45310 data = (utf8) ? utf8Encode(data) : data;
45311 bkey = rstr2binl(key);
45312 if (bkey.length > 16) {
45313 bkey = binl(bkey, key.length * 8);
45316 ipad = Array(16), opad = Array(16);
45317 for (i = 0; i < 16; i += 1) {
45318 ipad[i] = bkey[i] ^ 0x36363636;
45319 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45321 hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
45322 return binl2rstr(binl(opad.concat(hash), 512 + 128));
45326 * Calculate the MD5 of an array of little-endian words, and a bit length.
45329 function binl(x, len) {
45330 var i, olda, oldb, oldc, oldd,
45336 /* append padding */
45337 x[len >> 5] |= 0x80 << ((len) % 32);
45338 x[(((len + 64) >>> 9) << 4) + 14] = len;
45340 for (i = 0; i < x.length; i += 16) {
45346 a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
45347 d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
45348 c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
45349 b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
45350 a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
45351 d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
45352 c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
45353 b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
45354 a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
45355 d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
45356 c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
45357 b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
45358 a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
45359 d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
45360 c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
45361 b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
45363 a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
45364 d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
45365 c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
45366 b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
45367 a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
45368 d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
45369 c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
45370 b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
45371 a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
45372 d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
45373 c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
45374 b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
45375 a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
45376 d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
45377 c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
45378 b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
45380 a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
45381 d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
45382 c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
45383 b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
45384 a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
45385 d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
45386 c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
45387 b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
45388 a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
45389 d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
45390 c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
45391 b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
45392 a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
45393 d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
45394 c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
45395 b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
45397 a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
45398 d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
45399 c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
45400 b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
45401 a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
45402 d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
45403 c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
45404 b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
45405 a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
45406 d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
45407 c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
45408 b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
45409 a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
45410 d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
45411 c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
45412 b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
45414 a = safe_add(a, olda);
45415 b = safe_add(b, oldb);
45416 c = safe_add(c, oldc);
45417 d = safe_add(d, oldd);
45419 return Array(a, b, c, d);
45423 * These functions implement the four basic operations the algorithm uses.
45426 function md5_cmn(q, a, b, x, s, t) {
45427 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
45430 function md5_ff(a, b, c, d, x, s, t) {
45431 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
45434 function md5_gg(a, b, c, d, x, s, t) {
45435 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
45438 function md5_hh(a, b, c, d, x, s, t) {
45439 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
45442 function md5_ii(a, b, c, d, x, s, t) {
45443 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
45448 * @class Hashes.SHA1
45449 * @param {Object} [config]
45452 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
45453 * Version 2.2 Copyright Paul Johnston 2000 - 2009.
45454 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45455 * See http://pajhome.org.uk/crypt/md5 for details.
45457 SHA1: function(options) {
45459 * Private config properties. You may need to tweak these to be compatible with
45460 * the server-side, but the defaults work in most cases.
45461 * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
45463 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
45464 b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
45465 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
45468 this.hex = function(s) {
45469 return rstr2hex(rstr(s, utf8), hexcase);
45471 this.b64 = function(s) {
45472 return rstr2b64(rstr(s, utf8), b64pad);
45474 this.any = function(s, e) {
45475 return rstr2any(rstr(s, utf8), e);
45477 this.raw = function(s) {
45478 return rstr(s, utf8);
45480 this.hex_hmac = function(k, d) {
45481 return rstr2hex(rstr_hmac(k, d));
45483 this.b64_hmac = function(k, d) {
45484 return rstr2b64(rstr_hmac(k, d), b64pad);
45486 this.any_hmac = function(k, d, e) {
45487 return rstr2any(rstr_hmac(k, d), e);
45490 * Perform a simple self-test to see if the VM is working
45491 * @return {String} Hexadecimal hash sample
45494 this.vm_test = function() {
45495 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45498 * @description Enable/disable uppercase hexadecimal returned string
45500 * @return {Object} this
45503 this.setUpperCase = function(a) {
45504 if (typeof a === 'boolean') {
45510 * @description Defines a base64 pad string
45511 * @param {string} Pad
45512 * @return {Object} this
45515 this.setPad = function(a) {
45516 b64pad = a || b64pad;
45520 * @description Defines a base64 pad string
45522 * @return {Object} this
45525 this.setUTF8 = function(a) {
45526 if (typeof a === 'boolean') {
45535 * Calculate the SHA-512 of a raw string
45539 s = (utf8) ? utf8Encode(s) : s;
45540 return binb2rstr(binb(rstr2binb(s), s.length * 8));
45544 * Calculate the HMAC-SHA1 of a key and some data (raw strings)
45547 function rstr_hmac(key, data) {
45548 var bkey, ipad, opad, i, hash;
45549 key = (utf8) ? utf8Encode(key) : key;
45550 data = (utf8) ? utf8Encode(data) : data;
45551 bkey = rstr2binb(key);
45553 if (bkey.length > 16) {
45554 bkey = binb(bkey, key.length * 8);
45556 ipad = Array(16), opad = Array(16);
45557 for (i = 0; i < 16; i += 1) {
45558 ipad[i] = bkey[i] ^ 0x36363636;
45559 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45561 hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45562 return binb2rstr(binb(opad.concat(hash), 512 + 160));
45566 * Calculate the SHA-1 of an array of big-endian words, and a bit length
45569 function binb(x, len) {
45570 var i, j, t, olda, oldb, oldc, oldd, olde,
45578 /* append padding */
45579 x[len >> 5] |= 0x80 << (24 - len % 32);
45580 x[((len + 64 >> 9) << 4) + 15] = len;
45582 for (i = 0; i < x.length; i += 16) {
45589 for (j = 0; j < 80; j += 1) {
45593 w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
45595 t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
45596 safe_add(safe_add(e, w[j]), sha1_kt(j)));
45599 c = bit_rol(b, 30);
45604 a = safe_add(a, olda);
45605 b = safe_add(b, oldb);
45606 c = safe_add(c, oldc);
45607 d = safe_add(d, oldd);
45608 e = safe_add(e, olde);
45610 return Array(a, b, c, d, e);
45614 * Perform the appropriate triplet combination function for the current
45618 function sha1_ft(t, b, c, d) {
45620 return (b & c) | ((~b) & d);
45626 return (b & c) | (b & d) | (c & d);
45632 * Determine the appropriate additive constant for the current iteration
45635 function sha1_kt(t) {
45636 return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
45637 (t < 60) ? -1894007588 : -899497514;
45641 * @class Hashes.SHA256
45644 * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
45645 * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
45646 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45647 * See http://pajhome.org.uk/crypt/md5 for details.
45648 * Also http://anmar.eu.org/projects/jssha2/
45650 SHA256: function(options) {
45652 * Private properties configuration variables. You may need to tweak these to be compatible with
45653 * the server-side, but the defaults work in most cases.
45654 * @see this.setUpperCase() method
45655 * @see this.setPad() method
45657 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */
45658 b64pad = (options && typeof options.pad === 'string') ? options.pad : '=',
45659 /* base-64 pad character. Default '=' for strict RFC compliance */
45660 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45661 /* enable/disable utf8 encoding */
45664 /* privileged (public) methods */
45665 this.hex = function(s) {
45666 return rstr2hex(rstr(s, utf8));
45668 this.b64 = function(s) {
45669 return rstr2b64(rstr(s, utf8), b64pad);
45671 this.any = function(s, e) {
45672 return rstr2any(rstr(s, utf8), e);
45674 this.raw = function(s) {
45675 return rstr(s, utf8);
45677 this.hex_hmac = function(k, d) {
45678 return rstr2hex(rstr_hmac(k, d));
45680 this.b64_hmac = function(k, d) {
45681 return rstr2b64(rstr_hmac(k, d), b64pad);
45683 this.any_hmac = function(k, d, e) {
45684 return rstr2any(rstr_hmac(k, d), e);
45687 * Perform a simple self-test to see if the VM is working
45688 * @return {String} Hexadecimal hash sample
45691 this.vm_test = function() {
45692 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45695 * Enable/disable uppercase hexadecimal returned string
45697 * @return {Object} this
45700 this.setUpperCase = function(a) {
45701 if (typeof a === 'boolean') {
45707 * @description Defines a base64 pad string
45708 * @param {string} Pad
45709 * @return {Object} this
45712 this.setPad = function(a) {
45713 b64pad = a || b64pad;
45717 * Defines a base64 pad string
45719 * @return {Object} this
45722 this.setUTF8 = function(a) {
45723 if (typeof a === 'boolean') {
45732 * Calculate the SHA-512 of a raw string
45735 function rstr(s, utf8) {
45736 s = (utf8) ? utf8Encode(s) : s;
45737 return binb2rstr(binb(rstr2binb(s), s.length * 8));
45741 * Calculate the HMAC-sha256 of a key and some data (raw strings)
45744 function rstr_hmac(key, data) {
45745 key = (utf8) ? utf8Encode(key) : key;
45746 data = (utf8) ? utf8Encode(data) : data;
45748 bkey = rstr2binb(key),
45752 if (bkey.length > 16) {
45753 bkey = binb(bkey, key.length * 8);
45756 for (; i < 16; i += 1) {
45757 ipad[i] = bkey[i] ^ 0x36363636;
45758 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45761 hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45762 return binb2rstr(binb(opad.concat(hash), 512 + 256));
45766 * Main sha256 function, with its support functions
45769 function sha256_S(X, n) {
45770 return (X >>> n) | (X << (32 - n));
45773 function sha256_R(X, n) {
45777 function sha256_Ch(x, y, z) {
45778 return ((x & y) ^ ((~x) & z));
45781 function sha256_Maj(x, y, z) {
45782 return ((x & y) ^ (x & z) ^ (y & z));
45785 function sha256_Sigma0256(x) {
45786 return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
45789 function sha256_Sigma1256(x) {
45790 return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
45793 function sha256_Gamma0256(x) {
45794 return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
45797 function sha256_Gamma1256(x) {
45798 return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
45802 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
45803 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
45804 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
45805 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
45806 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
45807 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
45808 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
45811 function binb(m, l) {
45812 var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
45813 1359893119, -1694144372, 528734635, 1541459225
45815 var W = new Array(64);
45816 var a, b, c, d, e, f, g, h;
45819 /* append padding */
45820 m[l >> 5] |= 0x80 << (24 - l % 32);
45821 m[((l + 64 >> 9) << 4) + 15] = l;
45823 for (i = 0; i < m.length; i += 16) {
45833 for (j = 0; j < 64; j += 1) {
45837 W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
45838 sha256_Gamma0256(W[j - 15])), W[j - 16]);
45841 T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
45842 sha256_K[j]), W[j]);
45843 T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
45847 e = safe_add(d, T1);
45851 a = safe_add(T1, T2);
45854 HASH[0] = safe_add(a, HASH[0]);
45855 HASH[1] = safe_add(b, HASH[1]);
45856 HASH[2] = safe_add(c, HASH[2]);
45857 HASH[3] = safe_add(d, HASH[3]);
45858 HASH[4] = safe_add(e, HASH[4]);
45859 HASH[5] = safe_add(f, HASH[5]);
45860 HASH[6] = safe_add(g, HASH[6]);
45861 HASH[7] = safe_add(h, HASH[7]);
45869 * @class Hashes.SHA512
45872 * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
45873 * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
45874 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45875 * See http://pajhome.org.uk/crypt/md5 for details.
45877 SHA512: function(options) {
45879 * Private properties configuration variables. You may need to tweak these to be compatible with
45880 * the server-side, but the defaults work in most cases.
45881 * @see this.setUpperCase() method
45882 * @see this.setPad() method
45884 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45885 /* hexadecimal output case format. false - lowercase; true - uppercase */
45886 b64pad = (options && typeof options.pad === 'string') ? options.pad : '=',
45887 /* base-64 pad character. Default '=' for strict RFC compliance */
45888 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45889 /* enable/disable utf8 encoding */
45892 /* privileged (public) methods */
45893 this.hex = function(s) {
45894 return rstr2hex(rstr(s));
45896 this.b64 = function(s) {
45897 return rstr2b64(rstr(s), b64pad);
45899 this.any = function(s, e) {
45900 return rstr2any(rstr(s), e);
45902 this.raw = function(s) {
45903 return rstr(s, utf8);
45905 this.hex_hmac = function(k, d) {
45906 return rstr2hex(rstr_hmac(k, d));
45908 this.b64_hmac = function(k, d) {
45909 return rstr2b64(rstr_hmac(k, d), b64pad);
45911 this.any_hmac = function(k, d, e) {
45912 return rstr2any(rstr_hmac(k, d), e);
45915 * Perform a simple self-test to see if the VM is working
45916 * @return {String} Hexadecimal hash sample
45919 this.vm_test = function() {
45920 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45923 * @description Enable/disable uppercase hexadecimal returned string
45925 * @return {Object} this
45928 this.setUpperCase = function(a) {
45929 if (typeof a === 'boolean') {
45935 * @description Defines a base64 pad string
45936 * @param {string} Pad
45937 * @return {Object} this
45940 this.setPad = function(a) {
45941 b64pad = a || b64pad;
45945 * @description Defines a base64 pad string
45947 * @return {Object} this
45950 this.setUTF8 = function(a) {
45951 if (typeof a === 'boolean') {
45957 /* private methods */
45960 * Calculate the SHA-512 of a raw string
45964 s = (utf8) ? utf8Encode(s) : s;
45965 return binb2rstr(binb(rstr2binb(s), s.length * 8));
45968 * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
45971 function rstr_hmac(key, data) {
45972 key = (utf8) ? utf8Encode(key) : key;
45973 data = (utf8) ? utf8Encode(data) : data;
45976 bkey = rstr2binb(key),
45980 if (bkey.length > 32) {
45981 bkey = binb(bkey, key.length * 8);
45984 for (; i < 32; i += 1) {
45985 ipad[i] = bkey[i] ^ 0x36363636;
45986 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45989 hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
45990 return binb2rstr(binb(opad.concat(hash), 1024 + 512));
45994 * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
45997 function binb(x, len) {
46000 hash = new Array(16),
46001 //Initial hash values
46003 new int64(0x6a09e667, -205731576),
46004 new int64(-1150833019, -2067093701),
46005 new int64(0x3c6ef372, -23791573),
46006 new int64(-1521486534, 0x5f1d36f1),
46007 new int64(0x510e527f, -1377402159),
46008 new int64(-1694144372, 0x2b3e6c1f),
46009 new int64(0x1f83d9ab, -79577749),
46010 new int64(0x5be0cd19, 0x137e2179)
46012 T1 = new int64(0, 0),
46013 T2 = new int64(0, 0),
46014 a = new int64(0, 0),
46015 b = new int64(0, 0),
46016 c = new int64(0, 0),
46017 d = new int64(0, 0),
46018 e = new int64(0, 0),
46019 f = new int64(0, 0),
46020 g = new int64(0, 0),
46021 h = new int64(0, 0),
46022 //Temporary variables not specified by the document
46023 s0 = new int64(0, 0),
46024 s1 = new int64(0, 0),
46025 Ch = new int64(0, 0),
46026 Maj = new int64(0, 0),
46027 r1 = new int64(0, 0),
46028 r2 = new int64(0, 0),
46029 r3 = new int64(0, 0);
46031 if (sha512_k === undefined) {
46034 new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
46035 new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
46036 new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
46037 new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
46038 new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
46039 new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
46040 new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
46041 new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
46042 new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
46043 new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
46044 new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
46045 new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
46046 new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
46047 new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
46048 new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
46049 new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
46050 new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
46051 new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
46052 new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
46053 new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
46054 new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
46055 new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
46056 new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
46057 new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
46058 new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
46059 new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
46060 new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
46061 new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
46062 new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
46063 new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
46064 new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
46065 new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
46066 new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
46067 new int64(-354779690, -840897762), new int64(-176337025, -294727304),
46068 new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
46069 new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
46070 new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
46071 new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
46072 new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
46073 new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
46077 for (i = 0; i < 80; i += 1) {
46078 W[i] = new int64(0, 0);
46081 // append padding to the source string. The format is described in the FIPS.
46082 x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
46083 x[((len + 128 >> 10) << 5) + 31] = len;
46085 for (i = 0; i < l; i += 32) { //32 dwords is the block size
46086 int64copy(a, H[0]);
46087 int64copy(b, H[1]);
46088 int64copy(c, H[2]);
46089 int64copy(d, H[3]);
46090 int64copy(e, H[4]);
46091 int64copy(f, H[5]);
46092 int64copy(g, H[6]);
46093 int64copy(h, H[7]);
46095 for (j = 0; j < 16; j += 1) {
46096 W[j].h = x[i + 2 * j];
46097 W[j].l = x[i + 2 * j + 1];
46100 for (j = 16; j < 80; j += 1) {
46102 int64rrot(r1, W[j - 2], 19);
46103 int64revrrot(r2, W[j - 2], 29);
46104 int64shr(r3, W[j - 2], 6);
46105 s1.l = r1.l ^ r2.l ^ r3.l;
46106 s1.h = r1.h ^ r2.h ^ r3.h;
46108 int64rrot(r1, W[j - 15], 1);
46109 int64rrot(r2, W[j - 15], 8);
46110 int64shr(r3, W[j - 15], 7);
46111 s0.l = r1.l ^ r2.l ^ r3.l;
46112 s0.h = r1.h ^ r2.h ^ r3.h;
46114 int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
46117 for (j = 0; j < 80; j += 1) {
46119 Ch.l = (e.l & f.l) ^ (~e.l & g.l);
46120 Ch.h = (e.h & f.h) ^ (~e.h & g.h);
46123 int64rrot(r1, e, 14);
46124 int64rrot(r2, e, 18);
46125 int64revrrot(r3, e, 9);
46126 s1.l = r1.l ^ r2.l ^ r3.l;
46127 s1.h = r1.h ^ r2.h ^ r3.h;
46130 int64rrot(r1, a, 28);
46131 int64revrrot(r2, a, 2);
46132 int64revrrot(r3, a, 7);
46133 s0.l = r1.l ^ r2.l ^ r3.l;
46134 s0.h = r1.h ^ r2.h ^ r3.h;
46137 Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
46138 Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
46140 int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
46141 int64add(T2, s0, Maj);
46146 int64add(e, d, T1);
46150 int64add(a, T1, T2);
46152 int64add(H[0], H[0], a);
46153 int64add(H[1], H[1], b);
46154 int64add(H[2], H[2], c);
46155 int64add(H[3], H[3], d);
46156 int64add(H[4], H[4], e);
46157 int64add(H[5], H[5], f);
46158 int64add(H[6], H[6], g);
46159 int64add(H[7], H[7], h);
46162 //represent the hash as an array of 32-bit dwords
46163 for (i = 0; i < 8; i += 1) {
46164 hash[2 * i] = H[i].h;
46165 hash[2 * i + 1] = H[i].l;
46170 //A constructor for 64-bit numbers
46172 function int64(h, l) {
46175 //this.toString = int64toString;
46178 //Copies src into dst, assuming both are 64-bit numbers
46180 function int64copy(dst, src) {
46185 //Right-rotates a 64-bit number by shift
46186 //Won't handle cases of shift>=32
46187 //The function revrrot() is for that
46189 function int64rrot(dst, x, shift) {
46190 dst.l = (x.l >>> shift) | (x.h << (32 - shift));
46191 dst.h = (x.h >>> shift) | (x.l << (32 - shift));
46194 //Reverses the dwords of the source and then rotates right by shift.
46195 //This is equivalent to rotation by 32+shift
46197 function int64revrrot(dst, x, shift) {
46198 dst.l = (x.h >>> shift) | (x.l << (32 - shift));
46199 dst.h = (x.l >>> shift) | (x.h << (32 - shift));
46202 //Bitwise-shifts right a 64-bit number by shift
46203 //Won't handle shift>=32, but it's never needed in SHA512
46205 function int64shr(dst, x, shift) {
46206 dst.l = (x.l >>> shift) | (x.h << (32 - shift));
46207 dst.h = (x.h >>> shift);
46210 //Adds two 64-bit numbers
46211 //Like the original implementation, does not rely on 32-bit operations
46213 function int64add(dst, x, y) {
46214 var w0 = (x.l & 0xffff) + (y.l & 0xffff);
46215 var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
46216 var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
46217 var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
46218 dst.l = (w0 & 0xffff) | (w1 << 16);
46219 dst.h = (w2 & 0xffff) | (w3 << 16);
46222 //Same, except with 4 addends. Works faster than adding them one by one.
46224 function int64add4(dst, a, b, c, d) {
46225 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
46226 var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
46227 var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
46228 var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
46229 dst.l = (w0 & 0xffff) | (w1 << 16);
46230 dst.h = (w2 & 0xffff) | (w3 << 16);
46233 //Same, except with 5 addends
46235 function int64add5(dst, a, b, c, d, e) {
46236 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
46237 w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
46238 w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
46239 w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
46240 dst.l = (w0 & 0xffff) | (w1 << 16);
46241 dst.h = (w2 & 0xffff) | (w3 << 16);
46245 * @class Hashes.RMD160
46247 * @param {Object} [config]
46249 * A JavaScript implementation of the RIPEMD-160 Algorithm
46250 * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
46251 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
46252 * See http://pajhome.org.uk/crypt/md5 for details.
46253 * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
46255 RMD160: function(options) {
46257 * Private properties configuration variables. You may need to tweak these to be compatible with
46258 * the server-side, but the defaults work in most cases.
46259 * @see this.setUpperCase() method
46260 * @see this.setPad() method
46262 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
46263 /* hexadecimal output case format. false - lowercase; true - uppercase */
46264 b64pad = (options && typeof options.pad === 'string') ? options.pa : '=',
46265 /* base-64 pad character. Default '=' for strict RFC compliance */
46266 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
46267 /* enable/disable utf8 encoding */
46269 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
46270 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
46271 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
46272 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
46273 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
46276 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
46277 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
46278 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
46279 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
46280 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
46283 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
46284 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
46285 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
46286 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
46287 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
46290 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
46291 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
46292 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
46293 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
46294 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
46297 /* privileged (public) methods */
46298 this.hex = function(s) {
46299 return rstr2hex(rstr(s, utf8));
46301 this.b64 = function(s) {
46302 return rstr2b64(rstr(s, utf8), b64pad);
46304 this.any = function(s, e) {
46305 return rstr2any(rstr(s, utf8), e);
46307 this.raw = function(s) {
46308 return rstr(s, utf8);
46310 this.hex_hmac = function(k, d) {
46311 return rstr2hex(rstr_hmac(k, d));
46313 this.b64_hmac = function(k, d) {
46314 return rstr2b64(rstr_hmac(k, d), b64pad);
46316 this.any_hmac = function(k, d, e) {
46317 return rstr2any(rstr_hmac(k, d), e);
46320 * Perform a simple self-test to see if the VM is working
46321 * @return {String} Hexadecimal hash sample
46324 this.vm_test = function() {
46325 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
46328 * @description Enable/disable uppercase hexadecimal returned string
46330 * @return {Object} this
46333 this.setUpperCase = function(a) {
46334 if (typeof a === 'boolean') {
46340 * @description Defines a base64 pad string
46341 * @param {string} Pad
46342 * @return {Object} this
46345 this.setPad = function(a) {
46346 if (typeof a !== 'undefined') {
46352 * @description Defines a base64 pad string
46354 * @return {Object} this
46357 this.setUTF8 = function(a) {
46358 if (typeof a === 'boolean') {
46364 /* private methods */
46367 * Calculate the rmd160 of a raw string
46371 s = (utf8) ? utf8Encode(s) : s;
46372 return binl2rstr(binl(rstr2binl(s), s.length * 8));
46376 * Calculate the HMAC-rmd160 of a key and some data (raw strings)
46379 function rstr_hmac(key, data) {
46380 key = (utf8) ? utf8Encode(key) : key;
46381 data = (utf8) ? utf8Encode(data) : data;
46383 bkey = rstr2binl(key),
46387 if (bkey.length > 16) {
46388 bkey = binl(bkey, key.length * 8);
46391 for (i = 0; i < 16; i += 1) {
46392 ipad[i] = bkey[i] ^ 0x36363636;
46393 opad[i] = bkey[i] ^ 0x5C5C5C5C;
46395 hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
46396 return binl2rstr(binl(opad.concat(hash), 512 + 160));
46400 * Convert an array of little-endian words to a string
46403 function binl2rstr(input) {
46404 var i, output = '',
46405 l = input.length * 32;
46406 for (i = 0; i < l; i += 8) {
46407 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
46413 * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
46416 function binl(x, len) {
46423 A1, B1, C1, D1, E1,
46424 A2, B2, C2, D2, E2;
46426 /* append padding */
46427 x[len >> 5] |= 0x80 << (len % 32);
46428 x[(((len + 64) >>> 9) << 4) + 14] = len;
46431 for (i = 0; i < l; i += 16) {
46437 for (j = 0; j <= 79; j += 1) {
46438 T = safe_add(A1, rmd160_f(j, B1, C1, D1));
46439 T = safe_add(T, x[i + rmd160_r1[j]]);
46440 T = safe_add(T, rmd160_K1(j));
46441 T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
46444 D1 = bit_rol(C1, 10);
46447 T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
46448 T = safe_add(T, x[i + rmd160_r2[j]]);
46449 T = safe_add(T, rmd160_K2(j));
46450 T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
46453 D2 = bit_rol(C2, 10);
46458 T = safe_add(h1, safe_add(C1, D2));
46459 h1 = safe_add(h2, safe_add(D1, E2));
46460 h2 = safe_add(h3, safe_add(E1, A2));
46461 h3 = safe_add(h4, safe_add(A1, B2));
46462 h4 = safe_add(h0, safe_add(B1, C2));
46465 return [h0, h1, h2, h3, h4];
46468 // specific algorithm methods
46470 function rmd160_f(j, x, y, z) {
46471 return (0 <= j && j <= 15) ? (x ^ y ^ z) :
46472 (16 <= j && j <= 31) ? (x & y) | (~x & z) :
46473 (32 <= j && j <= 47) ? (x | ~y) ^ z :
46474 (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
46475 (64 <= j && j <= 79) ? x ^ (y | ~z) :
46476 'rmd160_f: j out of range';
46479 function rmd160_K1(j) {
46480 return (0 <= j && j <= 15) ? 0x00000000 :
46481 (16 <= j && j <= 31) ? 0x5a827999 :
46482 (32 <= j && j <= 47) ? 0x6ed9eba1 :
46483 (48 <= j && j <= 63) ? 0x8f1bbcdc :
46484 (64 <= j && j <= 79) ? 0xa953fd4e :
46485 'rmd160_K1: j out of range';
46488 function rmd160_K2(j) {
46489 return (0 <= j && j <= 15) ? 0x50a28be6 :
46490 (16 <= j && j <= 31) ? 0x5c4dd124 :
46491 (32 <= j && j <= 47) ? 0x6d703ef3 :
46492 (48 <= j && j <= 63) ? 0x7a6d76e9 :
46493 (64 <= j && j <= 79) ? 0x00000000 :
46494 'rmd160_K2: j out of range';
46500 (function(window, undefined) {
46501 var freeExports = false;
46503 freeExports = exports;
46504 if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
46505 window = commonjsGlobal;
46509 if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) {
46510 // define as an anonymous module, so, through path mapping, it can be aliased
46511 undefined(function() {
46514 } else if (freeExports) {
46515 // in Node.js or RingoJS v0.8.0+
46516 if ('object' === 'object' && module && module.exports === freeExports) {
46517 module.exports = Hashes;
46519 // in Narwhal or RingoJS v0.7.0-
46521 freeExports.Hashes = Hashes;
46524 // in a browser or Rhino
46525 window.Hashes = Hashes;
46531 var immutable = extend$2;
46533 var hasOwnProperty = Object.prototype.hasOwnProperty;
46535 function extend$2() {
46538 for (var i = 0; i < arguments.length; i++) {
46539 var source = arguments[i];
46541 for (var key in source) {
46542 if (hasOwnProperty.call(source, key)) {
46543 target[key] = source[key];
46551 var sha1 = new hashes.SHA1();
46555 ohauth.qsString = function(obj) {
46556 return Object.keys(obj).sort().map(function(key) {
46557 return ohauth.percentEncode(key) + '=' +
46558 ohauth.percentEncode(obj[key]);
46562 ohauth.stringQs = function(str) {
46563 return str.split('&').filter(function (pair) {
46564 return pair !== '';
46565 }).reduce(function(obj, pair){
46566 var parts = pair.split('=');
46567 obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
46568 '' : decodeURIComponent(parts[1]);
46573 ohauth.rawxhr = function(method, url, data, headers, callback) {
46574 var xhr = new XMLHttpRequest(),
46575 twoHundred = /^20\d$/;
46576 xhr.onreadystatechange = function() {
46577 if (4 === xhr.readyState && 0 !== xhr.status) {
46578 if (twoHundred.test(xhr.status)) callback(null, xhr);
46579 else return callback(xhr, null);
46582 xhr.onerror = function(e) { return callback(e, null); };
46583 xhr.open(method, url, true);
46584 for (var h in headers) xhr.setRequestHeader(h, headers[h]);
46589 ohauth.xhr = function(method, url, auth, data, options, callback) {
46590 var headers = (options && options.header) || {
46591 'Content-Type': 'application/x-www-form-urlencoded'
46593 headers.Authorization = 'OAuth ' + ohauth.authHeader(auth);
46594 return ohauth.rawxhr(method, url, data, headers, callback);
46597 ohauth.nonce = function() {
46598 for (var o = ''; o.length < 6;) {
46599 o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
46604 ohauth.authHeader = function(obj) {
46605 return Object.keys(obj).sort().map(function(key) {
46606 return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
46610 ohauth.timestamp = function() { return ~~((+new Date()) / 1000); };
46612 ohauth.percentEncode = function(s) {
46613 return encodeURIComponent(s)
46614 .replace(/\!/g, '%21').replace(/\'/g, '%27')
46615 .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
46618 ohauth.baseString = function(method, url, params) {
46619 if (params.oauth_signature) delete params.oauth_signature;
46622 ohauth.percentEncode(url),
46623 ohauth.percentEncode(ohauth.qsString(params))].join('&');
46626 ohauth.signature = function(oauth_secret, token_secret, baseString) {
46627 return sha1.b64_hmac(
46628 ohauth.percentEncode(oauth_secret) + '&' +
46629 ohauth.percentEncode(token_secret),
46634 * Takes an options object for configuration (consumer_key,
46635 * consumer_secret, version, signature_method, token, token_secret)
46636 * and returns a function that generates the Authorization header
46639 * The returned function takes these parameters:
46640 * - method: GET/POST/...
46641 * - uri: full URI with protocol, port, path and query string
46642 * - extra_params: any extra parameters (that are passed in the POST data),
46643 * can be an object or a from-urlencoded string.
46645 * Returned function returns full OAuth header with "OAuth" string in it.
46648 ohauth.headerGenerator = function(options) {
46649 options = options || {};
46650 var consumer_key = options.consumer_key || '',
46651 consumer_secret = options.consumer_secret || '',
46652 signature_method = options.signature_method || 'HMAC-SHA1',
46653 version = options.version || '1.0',
46654 token = options.token || '',
46655 token_secret = options.token_secret || '';
46657 return function(method, uri, extra_params) {
46658 method = method.toUpperCase();
46659 if (typeof extra_params === 'string' && extra_params.length > 0) {
46660 extra_params = ohauth.stringQs(extra_params);
46663 var uri_parts = uri.split('?', 2),
46664 base_uri = uri_parts[0];
46666 var query_params = uri_parts.length === 2 ?
46667 ohauth.stringQs(uri_parts[1]) : {};
46669 var oauth_params = {
46670 oauth_consumer_key: consumer_key,
46671 oauth_signature_method: signature_method,
46672 oauth_version: version,
46673 oauth_timestamp: ohauth.timestamp(),
46674 oauth_nonce: ohauth.nonce()
46677 if (token) oauth_params.oauth_token = token;
46679 var all_params = immutable({}, oauth_params, query_params, extra_params),
46680 base_str = ohauth.baseString(method, base_uri, all_params);
46682 oauth_params.oauth_signature = ohauth.signature(consumer_secret, token_secret, base_str);
46684 return 'OAuth ' + ohauth.authHeader(oauth_params);
46688 var index$13 = ohauth;
46690 var resolveUrl = createCommonjsModule(function (module, exports) {
46691 // Copyright 2014 Simon Lydell
46692 // X11 (“MIT”) Licensed. (See LICENSE.)
46694 void (function(root, factory) {
46695 if (typeof undefined === "function" && undefined.amd) {
46696 undefined(factory);
46698 module.exports = factory();
46700 }(commonjsGlobal, function() {
46702 function resolveUrl(/* ...urls */) {
46703 var numUrls = arguments.length;
46705 if (numUrls === 0) {
46706 throw new Error("resolveUrl requires at least one argument; got none.")
46709 var base = document.createElement("base");
46710 base.href = arguments[0];
46712 if (numUrls === 1) {
46716 var head = document.getElementsByTagName("head")[0];
46717 head.insertBefore(base, head.firstChild);
46719 var a = document.createElement("a");
46722 for (var index = 1; index < numUrls; index++) {
46723 a.href = arguments[index];
46725 base.href = resolved;
46728 head.removeChild(base);
46738 var assign = make_assign();
46739 var create$2 = make_create();
46740 var trim = make_trim();
46741 var Global = (typeof window !== 'undefined' ? window : commonjsGlobal);
46753 isFunction: isFunction$1,
46754 isObject: isObject$1,
46758 function make_assign() {
46759 if (Object.assign) {
46760 return Object.assign
46762 return function shimAssign(obj, props1, props2, etc) {
46763 for (var i = 1; i < arguments.length; i++) {
46764 each$1(Object(arguments[i]), function(val, key) {
46773 function make_create() {
46774 if (Object.create) {
46775 return function create(obj, assignProps1, assignProps2, etc) {
46776 var assignArgsList = slice$7(arguments, 1);
46777 return assign.apply(this, [Object.create(obj)].concat(assignArgsList))
46780 function F() {} // eslint-disable-line no-inner-declarations
46781 return function create(obj, assignProps1, assignProps2, etc) {
46782 var assignArgsList = slice$7(arguments, 1);
46784 return assign.apply(this, [new F()].concat(assignArgsList))
46789 function make_trim() {
46790 if (String.prototype.trim) {
46791 return function trim(str) {
46792 return String.prototype.trim.call(str)
46795 return function trim(str) {
46796 return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '')
46801 function bind$1(obj, fn) {
46802 return function() {
46803 return fn.apply(obj, Array.prototype.slice.call(arguments, 0))
46807 function slice$7(arr, index) {
46808 return Array.prototype.slice.call(arr, index || 0)
46811 function each$1(obj, fn) {
46812 pluck$1(obj, function(val, key) {
46818 function map$4(obj, fn) {
46819 var res = (isList$1(obj) ? [] : {});
46820 pluck$1(obj, function(v, k) {
46827 function pluck$1(obj, fn) {
46828 if (isList$1(obj)) {
46829 for (var i=0; i<obj.length; i++) {
46830 if (fn(obj[i], i)) {
46835 for (var key in obj) {
46836 if (obj.hasOwnProperty(key)) {
46837 if (fn(obj[key], key)) {
46845 function isList$1(val) {
46846 return (val != null && typeof val != 'function' && typeof val.length == 'number')
46849 function isFunction$1(val) {
46850 return val && {}.toString.call(val) === '[object Function]'
46853 function isObject$1(val) {
46854 return val && {}.toString.call(val) === '[object Object]'
46857 var slice$6 = util.slice;
46858 var pluck = util.pluck;
46859 var each = util.each;
46860 var bind = util.bind;
46861 var create$1 = util.create;
46862 var isList = util.isList;
46863 var isFunction = util.isFunction;
46864 var isObject = util.isObject;
46866 var storeEngine = {
46867 createStore: createStore
46874 // get returns the value of the given key. If that value
46875 // is undefined, it returns optionalDefaultValue instead.
46876 get: function(key, optionalDefaultValue) {
46877 var data = this.storage.read(this._namespacePrefix + key);
46878 return this._deserialize(data, optionalDefaultValue)
46881 // set will store the given value at key and returns value.
46882 // Calling set with value === undefined is equivalent to calling remove.
46883 set: function(key, value) {
46884 if (value === undefined) {
46885 return this.remove(key)
46887 this.storage.write(this._namespacePrefix + key, this._serialize(value));
46891 // remove deletes the key and value stored at the given key.
46892 remove: function(key) {
46893 this.storage.remove(this._namespacePrefix + key);
46896 // each will call the given callback once for each key-value pair
46898 each: function(callback) {
46900 this.storage.each(function(val, namespacedKey) {
46901 callback.call(self, self._deserialize(val), (namespacedKey || '').replace(self._namespaceRegexp, ''));
46905 // clearAll will remove all the stored key-value pairs in this store.
46906 clearAll: function() {
46907 this.storage.clearAll();
46910 // additional functionality that can't live in plugins
46911 // ---------------------------------------------------
46913 // hasNamespace returns true if this store instance has the given namespace.
46914 hasNamespace: function(namespace) {
46915 return (this._namespacePrefix == '__storejs_'+namespace+'_')
46918 // createStore creates a store.js instance with the first
46919 // functioning storage in the list of storage candidates,
46920 // and applies the the given mixins to the instance.
46921 createStore: function() {
46922 return createStore.apply(this, arguments)
46925 addPlugin: function(plugin) {
46926 this._addPlugin(plugin);
46929 namespace: function(namespace) {
46930 return createStore(this.storage, this.plugins, namespace)
46935 var _console = (typeof console == 'undefined' ? null : console);
46936 if (!_console) { return }
46937 var fn = (_console.warn ? _console.warn : _console.log);
46938 fn.apply(_console, arguments);
46941 function createStore(storages, plugins, namespace) {
46945 if (storages && !isList(storages)) {
46946 storages = [storages];
46948 if (plugins && !isList(plugins)) {
46949 plugins = [plugins];
46952 var namespacePrefix = (namespace ? '__storejs_'+namespace+'_' : '');
46953 var namespaceRegexp = (namespace ? new RegExp('^'+namespacePrefix) : null);
46954 var legalNamespaces = /^[a-zA-Z0-9_\-]*$/; // alpha-numeric + underscore and dash
46955 if (!legalNamespaces.test(namespace)) {
46956 throw new Error('store.js namespaces can only have alphanumerics + underscores and dashes')
46959 var _privateStoreProps = {
46960 _namespacePrefix: namespacePrefix,
46961 _namespaceRegexp: namespaceRegexp,
46963 _testStorage: function(storage) {
46965 var testStr = '__storejs__test__';
46966 storage.write(testStr, testStr);
46967 var ok = (storage.read(testStr) === testStr);
46968 storage.remove(testStr);
46975 _assignPluginFnProp: function(pluginFnProp, propName) {
46976 var oldFn = this[propName];
46977 this[propName] = function pluginFn() {
46978 var args = slice$6(arguments, 0);
46981 // super_fn calls the old function which was overwritten by
46983 function super_fn() {
46984 if (!oldFn) { return }
46985 each(arguments, function(arg, i) {
46988 return oldFn.apply(self, args)
46991 // Give mixing function access to super_fn by prefixing all mixin function
46992 // arguments with super_fn.
46993 var newFnArgs = [super_fn].concat(args);
46995 return pluginFnProp.apply(self, newFnArgs)
46999 _serialize: function(obj) {
47000 return JSON.stringify(obj)
47003 _deserialize: function(strVal, defaultVal) {
47004 if (!strVal) { return defaultVal }
47005 // It is possible that a raw string value has been previously stored
47006 // in a storage without using store.js, meaning it will be a raw
47007 // string value instead of a JSON serialized string. By defaulting
47008 // to the raw string value in case of a JSON parse error, we allow
47009 // for past stored values to be forwards-compatible with store.js
47011 try { val = JSON.parse(strVal); }
47012 catch(e) { val = strVal; }
47014 return (val !== undefined ? val : defaultVal)
47017 _addStorage: function(storage) {
47018 if (this.enabled) { return }
47019 if (this._testStorage(storage)) {
47020 this.storage = storage;
47021 this.enabled = true;
47025 _addPlugin: function(plugin) {
47028 // If the plugin is an array, then add all plugins in the array.
47029 // This allows for a plugin to depend on other plugins.
47030 if (isList(plugin)) {
47031 each(plugin, function(plugin) {
47032 self._addPlugin(plugin);
47037 // Keep track of all plugins we've seen so far, so that we
47038 // don't add any of them twice.
47039 var seenPlugin = pluck(this.plugins, function(seenPlugin) {
47040 return (plugin === seenPlugin)
47045 this.plugins.push(plugin);
47047 // Check that the plugin is properly formed
47048 if (!isFunction(plugin)) {
47049 throw new Error('Plugins must be function values that return objects')
47052 var pluginProperties = plugin.call(this);
47053 if (!isObject(pluginProperties)) {
47054 throw new Error('Plugins must return an object of function properties')
47057 // Add the plugin function properties to this store instance.
47058 each(pluginProperties, function(pluginFnProp, propName) {
47059 if (!isFunction(pluginFnProp)) {
47060 throw new Error('Bad plugin property: '+propName+' from plugin '+plugin.name+'. Plugins should only return functions.')
47062 self._assignPluginFnProp(pluginFnProp, propName);
47066 // Put deprecated properties in the private API, so as to not expose it to accidential
47067 // discovery through inspection of the store object.
47069 // Deprecated: addStorage
47070 addStorage: function(storage) {
47071 _warn('store.addStorage(storage) is deprecated. Use createStore([storages])');
47072 this._addStorage(storage);
47076 var store = create$1(_privateStoreProps, storeAPI, {
47080 each(store, function(prop, propName) {
47081 if (isFunction(prop)) {
47082 store.raw[propName] = bind(store, prop);
47085 each(storages, function(storage) {
47086 store._addStorage(storage);
47088 each(plugins, function(plugin) {
47089 store._addPlugin(plugin);
47094 var Global$1 = util.Global;
47096 var localStorage_1 = {
47097 name: 'localStorage',
47102 clearAll: clearAll,
47105 function localStorage$1() {
47106 return Global$1.localStorage
47109 function read(key) {
47110 return localStorage$1().getItem(key)
47113 function write(key, data) {
47114 return localStorage$1().setItem(key, data)
47117 function each$2(fn) {
47118 for (var i = localStorage$1().length - 1; i >= 0; i--) {
47119 var key = localStorage$1().key(i);
47120 fn(read(key), key);
47124 function remove$2(key) {
47125 return localStorage$1().removeItem(key)
47128 function clearAll() {
47129 return localStorage$1().clear()
47132 // oldFF-globalStorage provides storage for Firefox
47133 // versions 6 and 7, where no localStorage, etc
47137 var Global$2 = util.Global;
47139 var oldFFGlobalStorage = {
47140 name: 'oldFF-globalStorage',
47145 clearAll: clearAll$1,
47148 var globalStorage = Global$2.globalStorage;
47150 function read$1(key) {
47151 return globalStorage[key]
47154 function write$1(key, data) {
47155 globalStorage[key] = data;
47158 function each$3(fn) {
47159 for (var i = globalStorage.length - 1; i >= 0; i--) {
47160 var key = globalStorage.key(i);
47161 fn(globalStorage[key], key);
47165 function remove$3(key) {
47166 return globalStorage.removeItem(key)
47169 function clearAll$1() {
47170 each$3(function(key, _) {
47171 delete globalStorage[key];
47175 // oldIE-userDataStorage provides storage for Internet Explorer
47176 // versions 6 and 7, where no localStorage, sessionStorage, etc
47180 var Global$3 = util.Global;
47182 var oldIEUserDataStorage = {
47183 name: 'oldIE-userDataStorage',
47188 clearAll: clearAll$2,
47191 var storageName = 'storejs';
47192 var doc = Global$3.document;
47193 var _withStorageEl = _makeIEStorageElFunction();
47194 var disable = (Global$3.navigator ? Global$3.navigator.userAgent : '').match(/ (MSIE 8|MSIE 9|MSIE 10)\./); // MSIE 9.x, MSIE 10.x
47196 function write$2(unfixedKey, data) {
47197 if (disable) { return }
47198 var fixedKey = fixKey(unfixedKey);
47199 _withStorageEl(function(storageEl) {
47200 storageEl.setAttribute(fixedKey, data);
47201 storageEl.save(storageName);
47205 function read$2(unfixedKey) {
47206 if (disable) { return }
47207 var fixedKey = fixKey(unfixedKey);
47209 _withStorageEl(function(storageEl) {
47210 res = storageEl.getAttribute(fixedKey);
47215 function each$4(callback) {
47216 _withStorageEl(function(storageEl) {
47217 var attributes = storageEl.XMLDocument.documentElement.attributes;
47218 for (var i=attributes.length-1; i>=0; i--) {
47219 var attr = attributes[i];
47220 callback(storageEl.getAttribute(attr.name), attr.name);
47225 function remove$4(unfixedKey) {
47226 var fixedKey = fixKey(unfixedKey);
47227 _withStorageEl(function(storageEl) {
47228 storageEl.removeAttribute(fixedKey);
47229 storageEl.save(storageName);
47233 function clearAll$2() {
47234 _withStorageEl(function(storageEl) {
47235 var attributes = storageEl.XMLDocument.documentElement.attributes;
47236 storageEl.load(storageName);
47237 for (var i=attributes.length-1; i>=0; i--) {
47238 storageEl.removeAttribute(attributes[i].name);
47240 storageEl.save(storageName);
47247 // In IE7, keys cannot start with a digit or contain certain chars.
47248 // See https://github.com/marcuswestin/store.js/issues/40
47249 // See https://github.com/marcuswestin/store.js/issues/83
47250 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
47251 function fixKey(key) {
47252 return key.replace(/^\d/, '___$&').replace(forbiddenCharsRegex, '___')
47255 function _makeIEStorageElFunction() {
47256 if (!doc || !doc.documentElement || !doc.documentElement.addBehavior) {
47259 var scriptTag = 'script',
47264 // Since #userData storage applies only to specific paths, we need to
47265 // somehow link our data to a specific path. We choose /favicon.ico
47266 // as a pretty safe option, since all browsers already make a request to
47267 // this URL anyway and being a 404 will not hurt us here. We wrap an
47268 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
47269 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
47270 // since the iframe access rules appear to allow direct access and
47271 // manipulation of the document element, even for a 404 page. This
47272 // document can be used instead of the current document (which would
47273 // have been limited to the current path) to perform #userData storage.
47275 /* global ActiveXObject */
47276 storageContainer = new ActiveXObject('htmlfile');
47277 storageContainer.open();
47278 storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
47279 storageContainer.close();
47280 storageOwner = storageContainer.w.frames[0].document;
47281 storageEl = storageOwner.createElement('div');
47283 // somehow ActiveXObject instantiation failed (perhaps some special
47284 // security settings or otherwse), fall back to per-path storage
47285 storageEl = doc.createElement('div');
47286 storageOwner = doc.body;
47289 return function(storeFunction) {
47290 var args = [].slice.call(arguments, 0);
47291 args.unshift(storageEl);
47292 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
47293 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
47294 storageOwner.appendChild(storageEl);
47295 storageEl.addBehavior('#default#userData');
47296 storageEl.load(storageName);
47297 storeFunction.apply(this, args);
47298 storageOwner.removeChild(storageEl);
47303 // cookieStorage is useful Safari private browser mode, where localStorage
47304 // doesn't work but cookies do. This implementation is adopted from
47305 // https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage
47308 var Global$4 = util.Global;
47309 var trim$1 = util.trim;
47311 var cookieStorage = {
47312 name: 'cookieStorage',
47317 clearAll: clearAll$3,
47320 var doc$1 = Global$4.document;
47322 function read$3(key) {
47323 if (!key || !_has(key)) { return null }
47324 var regexpStr = "(?:^|.*;\\s*)" +
47325 escape(key).replace(/[\-\.\+\*]/g, "\\$&") +
47326 "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*";
47327 return unescape(doc$1.cookie.replace(new RegExp(regexpStr), "$1"))
47330 function each$5(callback) {
47331 var cookies = doc$1.cookie.split(/; ?/g);
47332 for (var i = cookies.length - 1; i >= 0; i--) {
47333 if (!trim$1(cookies[i])) {
47336 var kvp = cookies[i].split('=');
47337 var key = unescape(kvp[0]);
47338 var val = unescape(kvp[1]);
47339 callback(val, key);
47343 function write$3(key, data) {
47344 if(!key) { return }
47345 doc$1.cookie = escape(key) + "=" + escape(data) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
47348 function remove$5(key) {
47349 if (!key || !_has(key)) {
47352 doc$1.cookie = escape(key) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
47355 function clearAll$3() {
47356 each$5(function(_, key) {
47361 function _has(key) {
47362 return (new RegExp("(?:^|;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(doc$1.cookie)
47365 var Global$5 = util.Global;
47367 var sessionStorage_1 = {
47368 name: 'sessionStorage',
47373 clearAll: clearAll$4
47376 function sessionStorage() {
47377 return Global$5.sessionStorage
47380 function read$4(key) {
47381 return sessionStorage().getItem(key)
47384 function write$4(key, data) {
47385 return sessionStorage().setItem(key, data)
47388 function each$6(fn) {
47389 for (var i = sessionStorage().length - 1; i >= 0; i--) {
47390 var key = sessionStorage().key(i);
47391 fn(read$4(key), key);
47395 function remove$6(key) {
47396 return sessionStorage().removeItem(key)
47399 function clearAll$4() {
47400 return sessionStorage().clear()
47403 // memoryStorage is a useful last fallback to ensure that the store
47404 // is functions (meaning store.get(), store.set(), etc will all function).
47405 // However, stored values will not persist when the browser navigates to
47406 // a new page or reloads the current page.
47408 var memoryStorage_1 = {
47409 name: 'memoryStorage',
47414 clearAll: clearAll$5,
47417 var memoryStorage = {};
47419 function read$5(key) {
47420 return memoryStorage[key]
47423 function write$5(key, data) {
47424 memoryStorage[key] = data;
47427 function each$7(callback) {
47428 for (var key in memoryStorage) {
47429 if (memoryStorage.hasOwnProperty(key)) {
47430 callback(memoryStorage[key], key);
47435 function remove$7(key) {
47436 delete memoryStorage[key];
47439 function clearAll$5(key) {
47440 memoryStorage = {};
47444 // Listed in order of usage preference
47446 oldFFGlobalStorage,
47447 oldIEUserDataStorage,
47453 /* eslint-disable */
47458 // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
47459 // See http://www.JSON.org/js.html
47460 // This code should be minified before deployment.
47461 // See http://javascript.crockford.com/jsmin.html
47463 // USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
47466 // This file creates a global JSON object containing two methods: stringify
47467 // and parse. This file provides the ES5 JSON capability to ES3 systems.
47468 // If a project might run on IE8 or earlier, then this file should be included.
47469 // This file does nothing on ES5 systems.
47471 // JSON.stringify(value, replacer, space)
47472 // value any JavaScript value, usually an object or array.
47473 // replacer an optional parameter that determines how object
47474 // values are stringified for objects. It can be a
47475 // function or an array of strings.
47476 // space an optional parameter that specifies the indentation
47477 // of nested structures. If it is omitted, the text will
47478 // be packed without extra whitespace. If it is a number,
47479 // it will specify the number of spaces to indent at each
47480 // level. If it is a string (such as "\t" or " "),
47481 // it contains the characters used to indent at each level.
47482 // This method produces a JSON text from a JavaScript value.
47483 // When an object value is found, if the object contains a toJSON
47484 // method, its toJSON method will be called and the result will be
47485 // stringified. A toJSON method does not serialize: it returns the
47486 // value represented by the name/value pair that should be serialized,
47487 // or undefined if nothing should be serialized. The toJSON method
47488 // will be passed the key associated with the value, and this will be
47489 // bound to the value.
47491 // For example, this would serialize Dates as ISO strings.
47493 // Date.prototype.toJSON = function (key) {
47495 // // Format integers to have at least two digits.
47500 // return this.getUTCFullYear() + "-" +
47501 // f(this.getUTCMonth() + 1) + "-" +
47502 // f(this.getUTCDate()) + "T" +
47503 // f(this.getUTCHours()) + ":" +
47504 // f(this.getUTCMinutes()) + ":" +
47505 // f(this.getUTCSeconds()) + "Z";
47508 // You can provide an optional replacer method. It will be passed the
47509 // key and value of each member, with this bound to the containing
47510 // object. The value that is returned from your method will be
47511 // serialized. If your method returns undefined, then the member will
47512 // be excluded from the serialization.
47514 // If the replacer parameter is an array of strings, then it will be
47515 // used to select the members to be serialized. It filters the results
47516 // such that only members with keys listed in the replacer array are
47519 // Values that do not have JSON representations, such as undefined or
47520 // functions, will not be serialized. Such values in objects will be
47521 // dropped; in arrays they will be replaced with null. You can use
47522 // a replacer function to replace those with JSON values.
47524 // JSON.stringify(undefined) returns undefined.
47526 // The optional space parameter produces a stringification of the
47527 // value that is filled with line breaks and indentation to make it
47530 // If the space parameter is a non-empty string, then that string will
47531 // be used for indentation. If the space parameter is a number, then
47532 // the indentation will be that many spaces.
47536 // text = JSON.stringify(["e", {pluribus: "unum"}]);
47537 // // text is '["e",{"pluribus":"unum"}]'
47539 // text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t");
47540 // // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
47542 // text = JSON.stringify([new Date()], function (key, value) {
47543 // return this[key] instanceof Date
47544 // ? "Date(" + this[key] + ")"
47547 // // text is '["Date(---current time---)"]'
47549 // JSON.parse(text, reviver)
47550 // This method parses a JSON text to produce an object or array.
47551 // It can throw a SyntaxError exception.
47553 // The optional reviver parameter is a function that can filter and
47554 // transform the results. It receives each of the keys and values,
47555 // and its return value is used instead of the original value.
47556 // If it returns what it received, then the structure is not modified.
47557 // If it returns undefined then the member is deleted.
47561 // // Parse the text. Values that look like ISO date strings will
47562 // // be converted to Date objects.
47564 // myData = JSON.parse(text, function (key, value) {
47566 // if (typeof value === "string") {
47568 // /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
47570 // return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
47577 // myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
47579 // if (typeof value === "string" &&
47580 // value.slice(0, 5) === "Date(" &&
47581 // value.slice(-1) === ")") {
47582 // d = new Date(value.slice(5, -1));
47590 // This is a reference implementation. You are free to copy, modify, or
47598 JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
47599 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
47600 lastIndex, length, parse, prototype, push, replace, slice, stringify,
47601 test, toJSON, toString, valueOf
47605 // Create a JSON object only if one does not already exist. We create the
47606 // methods in a closure to avoid creating global variables.
47608 if (typeof JSON !== "object") {
47615 var rx_one = /^[\],:{}\s]*$/;
47616 var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
47617 var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
47618 var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
47619 var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
47620 var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
47623 // Format integers to have at least two digits.
47629 function this_value() {
47630 return this.valueOf();
47633 if (typeof Date.prototype.toJSON !== "function") {
47635 Date.prototype.toJSON = function () {
47637 return isFinite(this.valueOf())
47638 ? this.getUTCFullYear() + "-" +
47639 f(this.getUTCMonth() + 1) + "-" +
47640 f(this.getUTCDate()) + "T" +
47641 f(this.getUTCHours()) + ":" +
47642 f(this.getUTCMinutes()) + ":" +
47643 f(this.getUTCSeconds()) + "Z"
47647 Boolean.prototype.toJSON = this_value;
47648 Number.prototype.toJSON = this_value;
47649 String.prototype.toJSON = this_value;
47658 function quote(string) {
47660 // If the string contains no control characters, no quote characters, and no
47661 // backslash characters, then we can safely slap some quotes around it.
47662 // Otherwise we must also replace the offending characters with safe escape
47665 rx_escapable.lastIndex = 0;
47666 return rx_escapable.test(string)
47667 ? "\"" + string.replace(rx_escapable, function (a) {
47669 return typeof c === "string"
47671 : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
47673 : "\"" + string + "\"";
47677 function str(key, holder) {
47679 // Produce a string from holder[key].
47681 var i; // The loop counter.
47682 var k; // The member key.
47683 var v; // The member value.
47687 var value = holder[key];
47689 // If the value has a toJSON method, call it to obtain a replacement value.
47691 if (value && typeof value === "object" &&
47692 typeof value.toJSON === "function") {
47693 value = value.toJSON(key);
47696 // If we were called with a replacer function, then call the replacer to
47697 // obtain a replacement value.
47699 if (typeof rep === "function") {
47700 value = rep.call(holder, key, value);
47703 // What happens next depends on the value's type.
47705 switch (typeof value) {
47707 return quote(value);
47711 // JSON numbers must be finite. Encode non-finite numbers as null.
47713 return isFinite(value)
47720 // If the value is a boolean or null, convert it to a string. Note:
47721 // typeof null does not produce "null". The case is included here in
47722 // the remote chance that this gets fixed someday.
47724 return String(value);
47726 // If the type is "object", we might be dealing with an object or an array or
47731 // Due to a specification blunder in ECMAScript, typeof null is "object",
47732 // so watch out for that case.
47738 // Make an array to hold the partial results of stringifying this object value.
47743 // Is the value an array?
47745 if (Object.prototype.toString.apply(value) === "[object Array]") {
47747 // The value is an array. Stringify every element. Use null as a placeholder
47748 // for non-JSON values.
47750 length = value.length;
47751 for (i = 0; i < length; i += 1) {
47752 partial[i] = str(i, value) || "null";
47755 // Join all of the elements together, separated with commas, and wrap them in
47758 v = partial.length === 0
47761 ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]"
47762 : "[" + partial.join(",") + "]";
47767 // If the replacer is an array, use it to select the members to be stringified.
47769 if (rep && typeof rep === "object") {
47770 length = rep.length;
47771 for (i = 0; i < length; i += 1) {
47772 if (typeof rep[i] === "string") {
47776 partial.push(quote(k) + (
47786 // Otherwise, iterate through all of the keys in the object.
47789 if (Object.prototype.hasOwnProperty.call(value, k)) {
47792 partial.push(quote(k) + (
47802 // Join all of the member texts together, separated with commas,
47803 // and wrap them in braces.
47805 v = partial.length === 0
47808 ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
47809 : "{" + partial.join(",") + "}";
47815 // If the JSON object does not yet have a stringify method, give it one.
47817 if (typeof JSON.stringify !== "function") {
47818 meta = { // table of character substitutions
47827 JSON.stringify = function (value, replacer, space) {
47829 // The stringify method takes a value and an optional replacer, and an optional
47830 // space parameter, and returns a JSON text. The replacer can be a function
47831 // that can replace values, or an array of strings that will select the keys.
47832 // A default replacer method can be provided. Use of the space parameter can
47833 // produce text that is more easily readable.
47839 // If the space parameter is a number, make an indent string containing that
47842 if (typeof space === "number") {
47843 for (i = 0; i < space; i += 1) {
47847 // If the space parameter is a string, it will be used as the indent string.
47849 } else if (typeof space === "string") {
47853 // If there is a replacer, it must be a function or an array.
47854 // Otherwise, throw an error.
47857 if (replacer && typeof replacer !== "function" &&
47858 (typeof replacer !== "object" ||
47859 typeof replacer.length !== "number")) {
47860 throw new Error("JSON.stringify");
47863 // Make a fake root object containing our value under the key of "".
47864 // Return the result of stringifying the value.
47866 return str("", {"": value});
47871 // If the JSON object does not yet have a parse method, give it one.
47873 if (typeof JSON.parse !== "function") {
47874 JSON.parse = function (text, reviver) {
47876 // The parse method takes a text and an optional reviver function, and returns
47877 // a JavaScript value if the text is a valid JSON text.
47881 function walk(holder, key) {
47883 // The walk method is used to recursively walk the resulting structure so
47884 // that modifications can be made.
47888 var value = holder[key];
47889 if (value && typeof value === "object") {
47891 if (Object.prototype.hasOwnProperty.call(value, k)) {
47892 v = walk(value, k);
47893 if (v !== undefined) {
47901 return reviver.call(holder, key, value);
47905 // Parsing happens in four stages. In the first stage, we replace certain
47906 // Unicode characters with escape sequences. JavaScript handles many characters
47907 // incorrectly, either silently deleting them, or treating them as line endings.
47909 text = String(text);
47910 rx_dangerous.lastIndex = 0;
47911 if (rx_dangerous.test(text)) {
47912 text = text.replace(rx_dangerous, function (a) {
47914 ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
47918 // In the second stage, we run the text against regular expressions that look
47919 // for non-JSON patterns. We are especially concerned with "()" and "new"
47920 // because they can cause invocation, and "=" because it can cause mutation.
47921 // But just to be safe, we want to reject all unexpected forms.
47923 // We split the second stage into 4 regexp operations in order to work around
47924 // crippling inefficiencies in IE's and Safari's regexp engines. First we
47925 // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
47926 // replace all simple value tokens with "]" characters. Third, we delete all
47927 // open brackets that follow a colon or comma or that begin the text. Finally,
47928 // we look to see that the remaining characters are only whitespace or "]" or
47929 // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.
47934 .replace(rx_two, "@")
47935 .replace(rx_three, "]")
47936 .replace(rx_four, "")
47940 // In the third stage we use the eval function to compile the text into a
47941 // JavaScript structure. The "{" operator is subject to a syntactic ambiguity
47942 // in JavaScript: it can begin a block or an object literal. We wrap the text
47943 // in parens to eliminate the ambiguity.
47945 j = eval("(" + text + ")");
47947 // In the optional fourth stage, we recursively walk the new structure, passing
47948 // each name/value pair to a reviver function for possible transformation.
47950 return (typeof reviver === "function")
47951 ? walk({"": j}, "")
47955 // If the text is not JSON parseable, then a SyntaxError is thrown.
47957 throw new SyntaxError("JSON.parse");
47962 var json2 = json2Plugin;
47964 function json2Plugin() {
47969 var plugins = [json2];
47971 var store_legacy = storeEngine.createStore(all$3, plugins);
47975 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
47976 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
47977 // does not support custom headers, which this uses everywhere.
47978 var index$12 = function(o) {
47982 // authenticated users will also have a request token secret, but it's
47983 // not used in transactions with the server
47984 oauth.authenticated = function() {
47985 return !!(token('oauth_token') && token('oauth_token_secret'));
47988 oauth.logout = function() {
47989 token('oauth_token', '');
47990 token('oauth_token_secret', '');
47991 token('oauth_request_token_secret', '');
47995 // TODO: detect lack of click event
47996 oauth.authenticate = function(callback) {
47997 if (oauth.authenticated()) return callback();
48001 // ## Getting a request token
48002 var params = timenonce(getAuth(o)),
48003 url = o.url + '/oauth/request_token';
48005 params.oauth_signature = index$13.signature(
48006 o.oauth_secret, '',
48007 index$13.baseString('POST', url, params));
48009 if (!o.singlepage) {
48010 // Create a 600x550 popup window in the center of the screen
48011 var w = 600, h = 550,
48013 ['width', w], ['height', h],
48014 ['left', screen.width / 2 - w / 2],
48015 ['top', screen.height / 2 - h / 2]].map(function(x) {
48016 return x.join('=');
48018 popup = window.open('about:blank', 'oauth_window', settings);
48021 // Request a request token. When this is complete, the popup
48022 // window is redirected to OSM's authorization page.
48023 index$13.xhr('POST', url, params, null, {}, reqTokenDone);
48026 function reqTokenDone(err, xhr) {
48028 if (err) return callback(err);
48029 var resp = index$13.stringQs(xhr.response);
48030 token('oauth_request_token_secret', resp.oauth_token_secret);
48031 var authorize_url = o.url + '/oauth/authorize?' + index$13.qsString({
48032 oauth_token: resp.oauth_token,
48033 oauth_callback: resolveUrl(o.landing)
48036 if (o.singlepage) {
48037 location.href = authorize_url;
48039 popup.location = authorize_url;
48043 // Called by a function in a landing page, in the popup window. The
48044 // window closes itself.
48045 window.authComplete = function(token) {
48046 var oauth_token = index$13.stringQs(token.split('?')[1]);
48047 get_access_token(oauth_token.oauth_token);
48048 delete window.authComplete;
48051 // ## Getting an request token
48053 // At this point we have an `oauth_token`, brought in from a function
48054 // call on a landing page popup.
48055 function get_access_token(oauth_token) {
48056 var url = o.url + '/oauth/access_token',
48057 params = timenonce(getAuth(o)),
48058 request_token_secret = token('oauth_request_token_secret');
48059 params.oauth_token = oauth_token;
48060 params.oauth_signature = index$13.signature(
48062 request_token_secret,
48063 index$13.baseString('POST', url, params));
48065 // ## Getting an access token
48067 // The final token required for authentication. At this point
48068 // we have a `request token secret`
48069 index$13.xhr('POST', url, params, null, {}, accessTokenDone);
48073 function accessTokenDone(err, xhr) {
48075 if (err) return callback(err);
48076 var access_token = index$13.stringQs(xhr.response);
48077 token('oauth_token', access_token.oauth_token);
48078 token('oauth_token_secret', access_token.oauth_token_secret);
48079 callback(null, oauth);
48083 oauth.bootstrapToken = function(oauth_token, callback) {
48084 // ## Getting an request token
48085 // At this point we have an `oauth_token`, brought in from a function
48086 // call on a landing page popup.
48087 function get_access_token(oauth_token) {
48088 var url = o.url + '/oauth/access_token',
48089 params = timenonce(getAuth(o)),
48090 request_token_secret = token('oauth_request_token_secret');
48091 params.oauth_token = oauth_token;
48092 params.oauth_signature = index$13.signature(
48094 request_token_secret,
48095 index$13.baseString('POST', url, params));
48097 // ## Getting an access token
48098 // The final token required for authentication. At this point
48099 // we have a `request token secret`
48100 index$13.xhr('POST', url, params, null, {}, accessTokenDone);
48104 function accessTokenDone(err, xhr) {
48106 if (err) return callback(err);
48107 var access_token = index$13.stringQs(xhr.response);
48108 token('oauth_token', access_token.oauth_token);
48109 token('oauth_token_secret', access_token.oauth_token_secret);
48110 callback(null, oauth);
48113 get_access_token(oauth_token);
48118 // A single XMLHttpRequest wrapper that does authenticated calls if the
48119 // user has logged in.
48120 oauth.xhr = function(options, callback) {
48121 if (!oauth.authenticated()) {
48123 return oauth.authenticate(run);
48125 callback('not authenticated', null);
48133 var params = timenonce(getAuth(o)),
48134 oauth_token_secret = token('oauth_token_secret'),
48135 url = (options.prefix !== false) ? o.url + options.path : options.path,
48136 url_parts = url.replace(/#.*$/, '').split('?', 2),
48137 base_url = url_parts[0],
48138 query = (url_parts.length === 2) ? url_parts[1] : '';
48140 // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
48141 if ((!options.options || !options.options.header ||
48142 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
48144 params = immutable(params, index$13.stringQs(options.content));
48147 params.oauth_token = token('oauth_token');
48148 params.oauth_signature = index$13.signature(
48150 oauth_token_secret,
48151 index$13.baseString(options.method, base_url, immutable(params, index$13.stringQs(query)))
48154 return index$13.xhr(options.method, url, params, options.content, options.options, done);
48157 function done(err, xhr) {
48158 if (err) return callback(err);
48159 else if (xhr.responseXML) return callback(err, xhr.responseXML);
48160 else return callback(err, xhr.response);
48164 // pre-authorize this object, if we can just get a token and token_secret
48166 oauth.preauth = function(c) {
48168 if (c.oauth_token) token('oauth_token', c.oauth_token);
48169 if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
48173 oauth.options = function(_) {
48174 if (!arguments.length) return o;
48177 o.url = o.url || 'https://www.openstreetmap.org';
48178 o.landing = o.landing || 'land.html';
48179 o.singlepage = o.singlepage || false;
48181 // Optional loading and loading-done functions for nice UI feedback.
48182 // by default, no-ops
48183 o.loading = o.loading || function() {};
48184 o.done = o.done || function() {};
48186 return oauth.preauth(o);
48189 // 'stamp' an authentication object from `getAuth()`
48190 // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
48192 function timenonce(o) {
48193 o.oauth_timestamp = index$13.timestamp();
48194 o.oauth_nonce = index$13.nonce();
48198 // get/set tokens. These are prefixed with the base URL so that `osm-auth`
48199 // can be used with multiple APIs and the keys in `localStorage`
48203 if (store_legacy.enabled) {
48204 token = function (x, y) {
48205 if (arguments.length === 1) return store_legacy.get(o.url + x);
48206 else if (arguments.length === 2) return store_legacy.set(o.url + x, y);
48210 token = function (x, y) {
48211 if (arguments.length === 1) return storage[o.url + x];
48212 else if (arguments.length === 2) return storage[o.url + x] = y;
48216 // Get an authentication object. If you just add and remove properties
48217 // from a single object, you'll need to use `delete` to make sure that
48218 // it doesn't contain undesired properties for authentication
48219 function getAuth(o) {
48221 oauth_consumer_key: o.oauth_consumer_key,
48222 oauth_signature_method: 'HMAC-SHA1'
48226 // potentially pre-authorize
48232 var JXON = new (function () {
48234 sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
48235 aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
48237 function parseText (sValue) {
48238 if (rIsNull.test(sValue)) { return null; }
48239 if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
48240 if (isFinite(sValue)) { return parseFloat(sValue); }
48241 if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
48245 function EmptyTree () { }
48246 EmptyTree.prototype.toString = function () { return 'null'; };
48247 EmptyTree.prototype.valueOf = function () { return null; };
48249 function objectify (vValue) {
48250 return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
48253 function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
48255 nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
48256 bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
48259 sProp, vContent, nLength = 0, sCollectedTxt = '',
48260 vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
48263 for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
48264 oNode = oParentNode.childNodes.item(nItem);
48265 if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
48266 else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
48267 else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
48271 var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
48273 if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
48275 for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
48276 sProp = aCache[nElId].nodeName.toLowerCase();
48277 vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
48278 if (vResult.hasOwnProperty(sProp)) {
48279 if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
48280 vResult[sProp].push(vContent);
48282 vResult[sProp] = vContent;
48289 nAttrLen = oParentNode.attributes.length,
48290 sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
48292 for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
48293 oAttrib = oParentNode.attributes.item(nAttrib);
48294 oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
48298 if (bFreeze) { Object.freeze(oAttrParent); }
48299 vResult[sAttributesProp] = oAttrParent;
48300 nLength -= nAttrLen - 1;
48304 if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
48305 vResult[sValueProp] = vBuiltVal;
48306 } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
48307 vResult = vBuiltVal;
48310 if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
48312 aCache.length = nLevelStart;
48317 function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
48318 var vValue, oChild;
48320 if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
48321 oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
48322 } else if (oParentObj.constructor === Date) {
48323 oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));
48326 for (var sName in oParentObj) {
48327 vValue = oParentObj[sName];
48328 if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
48329 if (sName === sValueProp) {
48330 if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
48331 } else if (sName === sAttributesProp) { /* verbosity level is 3 */
48332 for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
48333 } else if (sName.charAt(0) === sAttrPref) {
48334 oParentEl.setAttribute(sName.slice(1), vValue);
48335 } else if (vValue.constructor === Array) {
48336 for (var nItem = 0; nItem < vValue.length; nItem++) {
48337 oChild = oXMLDoc.createElement(sName);
48338 loadObjTree(oXMLDoc, oChild, vValue[nItem]);
48339 oParentEl.appendChild(oChild);
48342 oChild = oXMLDoc.createElement(sName);
48343 if (vValue instanceof Object) {
48344 loadObjTree(oXMLDoc, oChild, vValue);
48345 } else if (vValue !== null && vValue !== true) {
48346 oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
48348 oParentEl.appendChild(oChild);
48353 this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
48354 var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
48355 return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);
48358 this.unbuild = function (oObjTree) {
48359 var oNewDoc = document.implementation.createDocument('', '', null);
48360 loadObjTree(oNewDoc, oNewDoc, oObjTree);
48364 this.stringify = function (oObjTree) {
48365 return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
48369 // var myObject = JXON.build(doc);
48370 // we got our javascript object! try: alert(JSON.stringify(myObject));
48372 // var newDoc = JXON.unbuild(myObject);
48373 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
48375 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
48376 var urlroot = 'https://www.openstreetmap.org';
48377 var blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'];
48378 var inflight$1 = {};
48379 var loadedTiles = {};
48380 var tileZoom$1 = 16;
48381 var oauth = index$12({
48383 oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
48384 oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
48385 loading: authLoading,
48388 var rateLimitError;
48389 var userChangesets;
48394 function authLoading() {
48395 dispatch$3.call('authLoading');
48399 function authDone() {
48400 dispatch$3.call('authDone');
48404 function abortRequest$1(i) {
48411 function getLoc(attrs) {
48412 var lon = attrs.lon && attrs.lon.value,
48413 lat = attrs.lat && attrs.lat.value;
48414 return [parseFloat(lon), parseFloat(lat)];
48418 function getNodes(obj) {
48419 var elems = obj.getElementsByTagName('nd'),
48420 nodes = new Array(elems.length);
48421 for (var i = 0, l = elems.length; i < l; i++) {
48422 nodes[i] = 'n' + elems[i].attributes.ref.value;
48428 function getTags(obj) {
48429 var elems = obj.getElementsByTagName('tag'),
48431 for (var i = 0, l = elems.length; i < l; i++) {
48432 var attrs = elems[i].attributes;
48433 tags[attrs.k.value] = attrs.v.value;
48440 function getMembers(obj) {
48441 var elems = obj.getElementsByTagName('member'),
48442 members = new Array(elems.length);
48443 for (var i = 0, l = elems.length; i < l; i++) {
48444 var attrs = elems[i].attributes;
48446 id: attrs.type.value[0] + attrs.ref.value,
48447 type: attrs.type.value,
48448 role: attrs.role.value
48455 function getVisible(attrs) {
48456 return (!attrs.visible || attrs.visible.value !== 'false');
48461 node: function nodeData(obj) {
48462 var attrs = obj.attributes;
48463 return new osmNode({
48464 id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
48465 visible: getVisible(attrs),
48466 version: attrs.version.value,
48467 changeset: attrs.changeset && attrs.changeset.value,
48468 timestamp: attrs.timestamp && attrs.timestamp.value,
48469 user: attrs.user && attrs.user.value,
48470 uid: attrs.uid && attrs.uid.value,
48471 loc: getLoc(attrs),
48476 way: function wayData(obj) {
48477 var attrs = obj.attributes;
48478 return new osmWay({
48479 id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
48480 visible: getVisible(attrs),
48481 version: attrs.version.value,
48482 changeset: attrs.changeset && attrs.changeset.value,
48483 timestamp: attrs.timestamp && attrs.timestamp.value,
48484 user: attrs.user && attrs.user.value,
48485 uid: attrs.uid && attrs.uid.value,
48486 tags: getTags(obj),
48487 nodes: getNodes(obj),
48491 relation: function relationData(obj) {
48492 var attrs = obj.attributes;
48493 return new osmRelation({
48494 id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
48495 visible: getVisible(attrs),
48496 version: attrs.version.value,
48497 changeset: attrs.changeset && attrs.changeset.value,
48498 timestamp: attrs.timestamp && attrs.timestamp.value,
48499 user: attrs.user && attrs.user.value,
48500 uid: attrs.uid && attrs.uid.value,
48501 tags: getTags(obj),
48502 members: getMembers(obj)
48508 function parse$1(xml$$1) {
48509 if (!xml$$1 || !xml$$1.childNodes) return;
48511 var root = xml$$1.childNodes[0],
48512 children = root.childNodes,
48515 for (var i = 0, l = children.length; i < l; i++) {
48516 var child = children[i],
48517 parser = parsers[child.nodeName];
48519 entities.push(parser(child));
48530 utilRebind(this, dispatch$3, 'on');
48534 reset: function() {
48535 userChangesets = undefined;
48536 userDetails = undefined;
48537 rateLimitError = undefined;
48538 lodash.forEach(inflight$1, abortRequest$1);
48545 changesetURL: function(changesetId) {
48546 return urlroot + '/changeset/' + changesetId;
48550 changesetsURL: function(center, zoom$$1) {
48551 var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
48552 return urlroot + '/history#map=' +
48553 Math.floor(zoom$$1) + '/' +
48554 center[1].toFixed(precision) + '/' +
48555 center[0].toFixed(precision);
48559 entityURL: function(entity) {
48560 return urlroot + '/' + entity.type + '/' + entity.osmId();
48564 historyURL: function(entity) {
48565 return urlroot + '/' + entity.type + '/' + entity.osmId() + '/history';
48569 userURL: function(username) {
48570 return urlroot + '/user/' + username;
48574 loadFromAPI: function(path$$1, callback) {
48577 function done(err, xml$$1) {
48578 var isAuthenticated = that.authenticated();
48580 // 400 Bad Request, 401 Unauthorized, 403 Forbidden
48581 // Logout and retry the request..
48582 if (isAuthenticated && err &&
48583 (err.status === 400 || err.status === 401 || err.status === 403)) {
48585 that.loadFromAPI(path$$1, callback);
48587 // else, no retry..
48589 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
48590 // Set the rateLimitError flag and trigger a warning..
48591 if (!isAuthenticated && !rateLimitError && err &&
48592 (err.status === 509 || err.status === 429)) {
48593 rateLimitError = err;
48594 dispatch$3.call('change');
48598 callback(err, parse$1(xml$$1));
48603 if (this.authenticated()) {
48604 return oauth.xhr({ method: 'GET', path: path$$1 }, done);
48606 var url = urlroot + path$$1;
48607 return xml(url).get(done);
48612 loadEntity: function(id, callback) {
48613 var type = osmEntity$$1.id.type(id),
48614 osmID = osmEntity$$1.id.toOSM(id);
48617 '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
48618 function(err, entities) {
48619 if (callback) callback(err, { data: entities });
48625 loadEntityVersion: function(id, version$$1, callback) {
48626 var type = osmEntity$$1.id.type(id),
48627 osmID = osmEntity$$1.id.toOSM(id);
48630 '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
48631 function(err, entities) {
48632 if (callback) callback(err, { data: entities });
48638 loadMultiple: function(ids, callback) {
48640 lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
48641 var type = k + 's',
48642 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
48644 lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
48646 '/api/0.6/' + type + '?' + type + '=' + arr.join(),
48647 function(err, entities) {
48648 if (callback) callback(err, { data: entities });
48656 authenticated: function() {
48657 return oauth.authenticated();
48661 putChangeset: function(changeset, changes, callback) {
48663 // Create the changeset..
48666 path: '/api/0.6/changeset/create',
48667 options: { header: { 'Content-Type': 'text/xml' } },
48668 content: JXON.stringify(changeset.asJXON())
48669 }, createdChangeset);
48672 function createdChangeset(err, changeset_id) {
48673 if (err) return callback(err);
48674 changeset = changeset.update({ id: changeset_id });
48676 // Upload the changeset..
48679 path: '/api/0.6/changeset/' + changeset_id + '/upload',
48680 options: { header: { 'Content-Type': 'text/xml' } },
48681 content: JXON.stringify(changeset.osmChangeJXON(changes))
48682 }, uploadedChangeset);
48686 function uploadedChangeset(err) {
48687 if (err) return callback(err);
48689 // Upload was successful, safe to call the callback.
48690 // Add delay to allow for postgres replication #1646 #2678
48691 window.setTimeout(function() {
48692 callback(null, changeset);
48695 // Still attempt to close changeset, but ignore response because #2667
48698 path: '/api/0.6/changeset/' + changeset.id + '/close',
48699 options: { header: { 'Content-Type': 'text/xml' } }
48700 }, function() { return true; });
48705 userDetails: function(callback) {
48707 callback(undefined, userDetails);
48711 function done(err, user_details) {
48712 if (err) return callback(err);
48714 var u = user_details.getElementsByTagName('user')[0],
48715 img = u.getElementsByTagName('img'),
48718 if (img && img[0] && img[0].getAttribute('href')) {
48719 image_url = img[0].getAttribute('href');
48722 var changesets = u.getElementsByTagName('changesets'),
48723 changesets_count = 0;
48725 if (changesets && changesets[0] && changesets[0].getAttribute('count')) {
48726 changesets_count = changesets[0].getAttribute('count');
48730 id: u.attributes.id.value,
48731 display_name: u.attributes.display_name.value,
48732 image_url: image_url,
48733 changesets_count: changesets_count
48736 callback(undefined, userDetails);
48739 oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
48743 userChangesets: function(callback) {
48744 if (userChangesets) {
48745 callback(undefined, userChangesets);
48749 this.userDetails(function(err, user) {
48755 function done(err, changesets) {
48759 userChangesets = Array.prototype.map.call(
48760 changesets.getElementsByTagName('changeset'),
48761 function (changeset) {
48762 return { tags: getTags(changeset) };
48764 ).filter(function (changeset) {
48765 var comment = changeset.tags.comment;
48766 return comment && comment !== '';
48768 callback(undefined, userChangesets);
48772 oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
48777 status: function(callback) {
48778 function done(xml$$1) {
48779 // update blacklists
48780 var elements = xml$$1.getElementsByTagName('blacklist'),
48782 for (var i = 0; i < elements.length; i++) {
48783 var regex = elements[i].getAttribute('regex'); // needs unencode?
48785 regexes.push(regex);
48788 if (regexes.length) {
48789 blacklists = regexes;
48793 if (rateLimitError) {
48794 callback(rateLimitError, 'rateLimited');
48796 var apiStatus = xml$$1.getElementsByTagName('status'),
48797 val = apiStatus[0].getAttribute('api');
48799 callback(undefined, val);
48803 xml(urlroot + '/api/capabilities').get()
48805 .on('error', callback);
48809 imageryBlacklists: function() {
48814 tileZoom: function(_) {
48815 if (!arguments.length) return tileZoom$1;
48821 loadTiles: function(projection$$1, dimensions, callback) {
48825 s = projection$$1.scale() * 2 * Math.PI,
48826 z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
48827 ts = 256 * Math.pow(2, z - tileZoom$1),
48829 s / 2 - projection$$1.translate()[0],
48830 s / 2 - projection$$1.translate()[1]
48833 var tiles = d3geoTile()
48834 .scaleExtent([tileZoom$1, tileZoom$1])
48837 .translate(projection$$1.translate())()
48838 .map(function(tile) {
48839 var x = tile[0] * ts - origin[0],
48840 y = tile[1] * ts - origin[1];
48843 id: tile.toString(),
48844 extent: geoExtent$$1(
48845 projection$$1.invert([x, y + ts]),
48846 projection$$1.invert([x + ts, y]))
48850 lodash.filter(inflight$1, function(v, i) {
48851 var wanted = lodash.find(tiles, function(tile) {
48852 return i === tile.id;
48854 if (!wanted) delete inflight$1[i];
48856 }).map(abortRequest$1);
48858 tiles.forEach(function(tile) {
48861 if (loadedTiles[id] || inflight$1[id]) return;
48863 if (lodash.isEmpty(inflight$1)) {
48864 dispatch$3.call('loading');
48867 inflight$1[id] = that.loadFromAPI(
48868 '/api/0.6/map?bbox=' + tile.extent.toParam(),
48869 function(err, parsed) {
48870 delete inflight$1[id];
48872 loadedTiles[id] = true;
48876 callback(err, lodash.extend({ data: parsed }, tile));
48879 if (lodash.isEmpty(inflight$1)) {
48880 dispatch$3.call('loaded');
48888 switch: function(options) {
48889 urlroot = options.urlroot;
48891 oauth.options(lodash.extend({
48893 loading: authLoading,
48897 dispatch$3.call('change');
48899 this.userChangesets(function() {}); // eagerly load user details/changesets
48904 toggle: function(_) {
48910 loadedTiles: function(_) {
48911 if (!arguments.length) return loadedTiles;
48917 logout: function() {
48918 userChangesets = undefined;
48919 userDetails = undefined;
48921 dispatch$3.call('change');
48926 authenticate: function(callback) {
48928 userChangesets = undefined;
48929 userDetails = undefined;
48931 function done(err, res) {
48932 rateLimitError = undefined;
48933 dispatch$3.call('change');
48934 if (callback) callback(err, res);
48935 that.userChangesets(function() {}); // eagerly load user details/changesets
48938 return oauth.authenticate(done);
48942 var apibase$2 = 'https://taginfo.openstreetmap.org/api/4/';
48943 var inflight$2 = {};
48944 var popularKeys = {};
48945 var taginfoCache = {};
48947 point: 'count_nodes',
48948 vertex: 'count_nodes',
48949 area: 'count_ways',
48952 var tag_sort_members = {
48953 point: 'count_node_members',
48954 vertex: 'count_node_members',
48955 area: 'count_way_members',
48956 line: 'count_way_members',
48957 relation: 'count_relation_members'
48959 var tag_filters = {
48965 var tag_members_fractions = {
48966 point: 'count_node_members_fraction',
48967 vertex: 'count_node_members_fraction',
48968 area: 'count_way_members_fraction',
48969 line: 'count_way_members_fraction',
48970 relation: 'count_relation_members_fraction'
48974 function sets(params, n, o) {
48975 if (params.geometry && o[params.geometry]) {
48976 params[n] = o[params.geometry];
48982 function setFilter(params) {
48983 return sets(params, 'filter', tag_filters);
48987 function setSort(params) {
48988 return sets(params, 'sortname', tag_sorts);
48992 function setSortMembers(params) {
48993 return sets(params, 'sortname', tag_sort_members);
48997 function clean(params) {
48998 return lodash.omit(params, ['geometry', 'debounce']);
49002 function filterKeys(type) {
49003 var count_type = type ? 'count_' + type : 'count_all';
49004 return function(d) {
49005 return parseFloat(d[count_type]) > 2500 || d.in_wiki;
49010 function filterMultikeys(prefix) {
49011 return function(d) {
49012 // d.key begins with prefix, and d.key contains no additional ':'s
49013 var re = new RegExp('^' + prefix + '(.*)$');
49014 var matches = d.key.match(re) || [];
49015 return (matches.length === 2 && matches[1].indexOf(':') === -1);
49020 function filterValues(allowUpperCase) {
49021 return function(d) {
49022 if (d.value.match(/[;,]/) !== null) return false; // exclude some punctuation
49023 if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false; // exclude uppercase letters
49024 return parseFloat(d.fraction) > 0.0 || d.in_wiki;
49029 function filterRoles(geometry) {
49030 return function(d) {
49031 if (d.role === '') return false; // exclude empty role
49032 if (d.role.match(/[A-Z*;,]/) !== null) return false; // exclude uppercase letters and some punctuation
49033 return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
49038 function valKey(d) {
49046 function valKeyDescription(d) {
49049 title: d.description || d.value
49054 function roleKey(d) {
49062 // sort keys with ':' lower than keys without ':'
49063 function sortKeys(a, b) {
49064 return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
49065 : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
49070 var debouncedRequest = lodash.debounce(request$1, 500, { leading: false });
49072 function request$1(url, params, exactMatch, callback, loaded) {
49073 if (inflight$2[url]) return;
49075 if (checkCache(url, params, exactMatch, callback)) return;
49077 inflight$2[url] = json(url, function (err, data) {
49078 delete inflight$2[url];
49084 function checkCache(url, params, exactMatch, callback) {
49085 var rp = params.rp || 25,
49086 testQuery = params.query || '',
49090 var hit = taginfoCache[testUrl];
49092 // exact match, or shorter match yielding fewer than max results (rp)
49093 if (hit && (url === testUrl || hit.length < rp)) {
49094 callback(null, hit);
49098 // don't try to shorten the query
49099 if (exactMatch || !testQuery.length) return false;
49101 // do shorten the query to see if we already have a cached result
49102 // that has returned fewer than max results (rp)
49103 testQuery = testQuery.slice(0, -1);
49104 testUrl = url.replace(/&query=(.*?)&/, '&query=' + testQuery + '&');
49105 } while (testQuery.length >= 0);
49111 var serviceTaginfo = {
49118 // Fetch popular keys. We'll exclude these from `values`
49119 // lookups because they stress taginfo, and they aren't likely
49120 // to yield meaningful autocomplete results.. see #3955
49121 var params = { rp: 100, sortname: 'values_all', sortorder: 'desc', page: 1, debounce: false };
49122 this.keys(params, function(err, data) {
49124 data.forEach(function(d) {
49125 if (d.value === 'opening_hours') return; // exception
49126 popularKeys[d.value] = true;
49132 reset: function() {
49133 lodash.forEach(inflight$2, function(req) { req.abort(); });
49138 keys: function(params, callback) {
49139 var doRequest = params.debounce ? debouncedRequest : request$1;
49140 params = clean(setSort(params));
49141 params = lodash.extend({ rp: 10, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
49143 var url = apibase$2 + 'keys/all?' + utilQsString(params);
49144 doRequest(url, params, false, callback, function(err, d) {
49148 var f = filterKeys(params.filter);
49149 var result = d.data.filter(f).sort(sortKeys).map(valKey);
49150 taginfoCache[url] = result;
49151 callback(null, result);
49157 multikeys: function(params, callback) {
49158 var doRequest = params.debounce ? debouncedRequest : request$1;
49159 params = clean(setSort(params));
49160 params = lodash.extend({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
49161 var prefix = params.query;
49163 var url = apibase$2 + 'keys/all?' + utilQsString(params);
49164 doRequest(url, params, true, callback, function(err, d) {
49168 var f = filterMultikeys(prefix);
49169 var result = d.data.filter(f).map(valKey);
49170 taginfoCache[url] = result;
49171 callback(null, result);
49177 values: function(params, callback) {
49178 // Exclude popular keys from values lookups.. see #3955
49179 var key = params.key;
49180 if (key && popularKeys[key]) {
49181 callback(null, []);
49185 var doRequest = params.debounce ? debouncedRequest : request$1;
49186 params = clean(setSort(setFilter(params)));
49187 params = lodash.extend({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
49189 var url = apibase$2 + 'key/values?' + utilQsString(params);
49190 doRequest(url, params, false, callback, function(err, d) {
49194 // In most cases we prefer taginfo value results with lowercase letters.
49195 // A few OSM keys expect values to contain uppercase values (see #3377).
49196 // This is not an exhaustive list (e.g. `name` also has uppercase values)
49197 // but these are the fields where taginfo value lookup is most useful.
49198 var re = /network|taxon|genus|species|brand|grape_variety|_hours|_times/;
49199 var allowUpperCase = (params.key.match(re) !== null);
49200 var f = filterValues(allowUpperCase);
49202 var result = d.data.filter(f).map(valKeyDescription);
49203 taginfoCache[url] = result;
49204 callback(null, result);
49210 roles: function(params, callback) {
49211 var doRequest = params.debounce ? debouncedRequest : request$1;
49212 var geometry = params.geometry;
49213 params = clean(setSortMembers(params));
49214 params = lodash.extend({ rp: 25, sortname: 'count_all_members', sortorder: 'desc', page: 1 }, params);
49216 var url = apibase$2 + 'relation/roles?' + utilQsString(params);
49217 doRequest(url, params, true, callback, function(err, d) {
49221 var f = filterRoles(geometry);
49222 var result = d.data.filter(f).map(roleKey);
49223 taginfoCache[url] = result;
49224 callback(null, result);
49230 docs: function(params, callback) {
49231 var doRequest = params.debounce ? debouncedRequest : request$1;
49232 params = clean(setSort(params));
49234 var path$$1 = 'key/wiki_pages?';
49235 if (params.value) path$$1 = 'tag/wiki_pages?';
49236 else if (params.rtype) path$$1 = 'relation/wiki_pages?';
49238 var url = apibase$2 + path$$1 + utilQsString(params);
49239 doRequest(url, params, true, callback, function(err, d) {
49243 taginfoCache[url] = d.data;
49244 callback(null, d.data);
49250 apibase: function(_) {
49251 if (!arguments.length) return apibase$2;
49258 var jsonpCache = {};
49259 window.jsonpCache = jsonpCache;
49261 function jsonpRequest(url, callback) {
49263 if (window.JSONP_FIX) {
49264 if (window.JSONP_DELAY === 0) {
49265 callback(window.JSONP_FIX);
49267 setTimeout(function() {
49268 callback(window.JSONP_FIX);
49269 }, window.JSONP_DELAY || 0);
49275 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
49277 while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
49281 function create(url) {
49282 var e = url.match(/callback=(\w+)/),
49283 c = e ? e[1] : rand();
49284 jsonpCache[c] = function(data) {
49286 delete jsonpCache[c];
49289 return 'jsonpCache.' + c;
49292 var cb = create(url),
49293 script = select('head')
49295 .attr('type', 'text/javascript')
49296 .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
49299 var endpoint = 'https://www.wikidata.org/w/api.php?';
49301 var serviceWikidata = {
49303 init: function() {},
49304 reset: function() {},
49307 // Given a Wikipedia language and article title, return an array of
49308 // corresponding Wikidata entities.
49309 itemsByTitle: function(lang, title, callback) {
49315 lang = lang || 'en';
49316 jsonpRequest(endpoint + utilQsString({
49317 action: 'wbgetentities',
49319 sites: lang.replace(/-/g, '_') + 'wiki',
49321 languages: 'en', // shrink response by filtering to one language
49322 callback: '{callback}'
49323 }), function(data) {
49324 if (!data || data.error) {
49327 callback(title, data.entities || {});
49334 var endpoint$1 = 'https://en.wikipedia.org/w/api.php?';
49336 var serviceWikipedia = {
49338 init: function() {},
49339 reset: function() {},
49342 search: function(lang, query, callback) {
49348 lang = lang || 'en';
49349 jsonpRequest(endpoint$1.replace('en', lang) +
49354 srinfo: 'suggestion',
49356 callback: '{callback}',
49358 }), function(data) {
49359 if (!data || !data.query || !data.query.search || data.error) {
49362 var results = data.query.search.map(function(d) { return d.title; });
49363 callback(query, results);
49370 suggestions: function(lang, query, callback) {
49376 lang = lang || 'en';
49377 jsonpRequest(endpoint$1.replace('en', lang) +
49379 action: 'opensearch',
49383 callback: '{callback}',
49385 }), function(data) {
49386 if (!data || data.error) {
49389 callback(data[0], data[1] || []);
49396 translations: function(lang, title, callback) {
49402 jsonpRequest(endpoint$1.replace('en', lang) +
49407 callback: '{callback}',
49410 }), function(data) {
49411 if (!data || !data.query || !data.query.pages || data.error) {
49414 var list = data.query.pages[Object.keys(data.query.pages)[0]],
49416 if (list && list.langlinks) {
49417 list.langlinks.forEach(function(d) {
49418 translations[d.lang] = d['*'];
49421 callback(translations);
49430 mapillary: serviceMapillary,
49431 geocoder: serviceNominatim,
49433 taginfo: serviceTaginfo,
49434 wikidata: serviceWikidata,
49435 wikipedia: serviceWikipedia
49438 function svgMapillaryImages(projection$$1, context, dispatch$$1) {
49439 var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
49441 minViewfieldZoom = 17,
49442 layer = select(null),
49447 if (svgMapillaryImages.initialized) return; // run once
49448 svgMapillaryImages.enabled = false;
49449 svgMapillaryImages.initialized = true;
49453 function getMapillary() {
49454 if (services.mapillary && !_mapillary) {
49455 _mapillary = services.mapillary;
49456 _mapillary.event.on('loadedImages', throttledRedraw);
49457 } else if (!services.mapillary && _mapillary) {
49465 function showLayer() {
49466 var mapillary = getMapillary();
49467 if (!mapillary) return;
49469 mapillary.loadViewer(context);
49473 .style('opacity', 0)
49476 .style('opacity', 1)
49477 .on('end', function () { dispatch$$1.call('change'); });
49481 function hideLayer() {
49482 var mapillary = getMapillary();
49484 mapillary.hideViewer();
49487 throttledRedraw.cancel();
49492 .style('opacity', 0)
49493 .on('end', editOff);
49497 function editOn() {
49498 layer.style('display', 'block');
49502 function editOff() {
49503 layer.selectAll('.viewfield-group').remove();
49504 layer.style('display', 'none');
49508 function click(d) {
49509 var mapillary = getMapillary();
49510 if (!mapillary) return;
49512 context.map().centerEase(d.loc);
49515 .selectedImage(d.key, true)
49516 .updateViewer(d.key, context)
49521 function transform$$1(d) {
49522 var t = svgPointTransform(projection$$1)(d);
49523 if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
49528 function update() {
49529 var mapillary = getMapillary(),
49530 data = (mapillary ? mapillary.images(projection$$1) : []),
49531 imageKey = mapillary ? mapillary.selectedImage() : null;
49533 var markers = layer.selectAll('.viewfield-group')
49534 .data(data, function(d) { return d.key; });
49539 var enter = markers.enter()
49541 .attr('class', 'viewfield-group')
49542 .classed('selected', function(d) { return d.key === imageKey; })
49543 .on('click', click);
49547 .attr('transform', transform$$1);
49550 var viewfields = markers.selectAll('.viewfield')
49551 .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
49558 .attr('class', 'viewfield')
49559 .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
49560 .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');
49562 markers.selectAll('circle')
49572 function drawImages(selection$$1) {
49573 var enabled = svgMapillaryImages.enabled,
49574 mapillary = getMapillary();
49576 layer = selection$$1.selectAll('.layer-mapillary-images')
49577 .data(mapillary ? [0] : []);
49582 layer = layer.enter()
49584 .attr('class', 'layer-mapillary-images')
49585 .style('display', enabled ? 'block' : 'none')
49589 if (mapillary && ~~context.map().zoom() >= minZoom) {
49592 mapillary.loadImages(projection$$1);
49600 drawImages.enabled = function(_) {
49601 if (!arguments.length) return svgMapillaryImages.enabled;
49602 svgMapillaryImages.enabled = _;
49603 if (svgMapillaryImages.enabled) {
49608 dispatch$$1.call('change');
49613 drawImages.supported = function() {
49614 return !!getMapillary();
49622 function svgMapillarySigns(projection$$1, context, dispatch$$1) {
49623 var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
49625 layer = select(null),
49630 if (svgMapillarySigns.initialized) return; // run once
49631 svgMapillarySigns.enabled = false;
49632 svgMapillarySigns.initialized = true;
49636 function getMapillary() {
49637 if (services.mapillary && !_mapillary) {
49638 _mapillary = services.mapillary;
49639 _mapillary.event.on('loadedSigns', throttledRedraw);
49640 } else if (!services.mapillary && _mapillary) {
49647 function showLayer() {
49652 function hideLayer() {
49653 throttledRedraw.cancel();
49658 function editOn() {
49659 layer.style('display', 'block');
49663 function editOff() {
49664 layer.selectAll('.icon-sign').remove();
49665 layer.style('display', 'none');
49669 function click(d) {
49670 var mapillary = getMapillary();
49671 if (!mapillary) return;
49673 context.map().centerEase(d.loc);
49676 .selectedImage(d.key, true)
49677 .updateViewer(d.key, context)
49682 function update() {
49683 var mapillary = getMapillary(),
49684 data = (mapillary ? mapillary.signs(projection$$1) : []),
49685 imageKey = mapillary ? mapillary.selectedImage() : null;
49687 var signs = layer.selectAll('.icon-sign')
49688 .data(data, function(d) { return d.key; });
49693 var enter = signs.enter()
49694 .append('foreignObject')
49695 .attr('class', 'icon-sign')
49696 .attr('width', '32px') // for Firefox
49697 .attr('height', '32px') // for Firefox
49698 .classed('selected', function(d) { return d.key === imageKey; })
49699 .on('click', click);
49702 .append('xhtml:body')
49703 .attr('class', 'icon-sign-body')
49704 .html(mapillary.signHTML);
49708 .attr('x', function(d) { return projection$$1(d.loc)[0] - 16; }) // offset by -16px to
49709 .attr('y', function(d) { return projection$$1(d.loc)[1] - 16; }); // center signs on loc
49713 function drawSigns(selection$$1) {
49714 var enabled = svgMapillarySigns.enabled,
49715 mapillary = getMapillary();
49717 layer = selection$$1.selectAll('.layer-mapillary-signs')
49718 .data(mapillary ? [0] : []);
49723 layer = layer.enter()
49725 .attr('class', 'layer-mapillary-signs')
49726 .style('display', enabled ? 'block' : 'none')
49730 if (mapillary && ~~context.map().zoom() >= minZoom) {
49733 mapillary.loadSigns(context, projection$$1);
49741 drawSigns.enabled = function(_) {
49742 if (!arguments.length) return svgMapillarySigns.enabled;
49743 svgMapillarySigns.enabled = _;
49744 if (svgMapillarySigns.enabled) {
49749 dispatch$$1.call('change');
49754 drawSigns.supported = function() {
49755 var mapillary = getMapillary();
49756 return (mapillary && mapillary.signsSupported());
49764 function svgOsm() {
49765 return function drawOsm(selection) {
49766 var layers = selection.selectAll('.layer-osm')
49767 .data(['areas', 'lines', 'hit', 'halo', 'label']);
49771 .attr('class', function(d) { return 'layer-osm layer-' + d; });
49775 function svgLayers(projection$$1, context) {
49776 var dispatch$$1 = dispatch('change'),
49777 svg = select(null),
49779 { id: 'osm', layer: svgOsm(projection$$1, context, dispatch$$1) },
49780 { id: 'gpx', layer: svgGpx(projection$$1, context, dispatch$$1) },
49781 { id: 'mapillary-images', layer: svgMapillaryImages(projection$$1, context, dispatch$$1) },
49782 { id: 'mapillary-signs', layer: svgMapillarySigns(projection$$1, context, dispatch$$1) },
49783 { id: 'debug', layer: svgDebug(projection$$1, context, dispatch$$1) }
49787 function drawLayers(selection$$1) {
49788 svg = selection$$1.selectAll('.surface')
49793 .attr('class', 'surface')
49796 var defs = svg.selectAll('.surface-defs')
49801 .attr('class', 'surface-defs');
49803 var groups = svg.selectAll('.data-layer')
49811 .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
49813 .each(function(d) { select(this).call(d.layer); });
49817 drawLayers.all = function() {
49822 drawLayers.layer = function(id) {
49823 var obj = lodash.find(layers, function(o) {return o.id === id;});
49824 return obj && obj.layer;
49828 drawLayers.only = function(what) {
49829 var arr = [].concat(what);
49830 drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
49835 drawLayers.remove = function(what) {
49836 var arr = [].concat(what);
49837 arr.forEach(function(id) {
49838 layers = lodash.reject(layers, function(o) {return o.id === id;});
49840 dispatch$$1.call('change');
49845 drawLayers.add = function(what) {
49846 var arr = [].concat(what);
49847 arr.forEach(function(obj) {
49848 if ('id' in obj && 'layer' in obj) {
49852 dispatch$$1.call('change');
49857 drawLayers.dimensions = function(_) {
49858 if (!arguments.length) return utilGetDimensions(svg);
49859 utilSetDimensions(svg, _);
49864 return utilRebind(drawLayers, dispatch$$1, 'on');
49867 function svgLines$$1(projection$$1, context) {
49868 var detected = utilDetect();
49870 var highway_stack = {
49886 function drawLines(selection$$1, graph, entities, filter) {
49889 function waystack(a, b) {
49890 var selected = context.selectedIDs(),
49891 scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0,
49892 scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0;
49894 if (a.tags.highway) { scoreA -= highway_stack[a.tags.highway]; }
49895 if (b.tags.highway) { scoreB -= highway_stack[b.tags.highway]; }
49896 return scoreA - scoreB;
49900 function drawLineGroup(selection$$1, klass, isSelected) {
49901 var lines = selection$$1
49904 .data(getPathData(isSelected), osmEntity$$1.key);
49909 // Optimization: call simple TagClasses only on enter selection. This
49910 // works because osmEntity.key is defined to include the entity v attribute.
49913 .attr('class', function(d) {
49914 return 'way line ' + klass + ' ' + d.id + (isSelected ? ' selected' : '') +
49915 (oldMultiPolygonOuters[d.id] ? ' old-multipolygon' : '');
49917 .call(svgTagClasses())
49920 .attr('d', getPath)
49921 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
49923 return selection$$1;
49927 function getPathData(isSelected) {
49928 return function() {
49929 var layer = this.parentNode.__data__;
49930 var data = pathdata[layer] || [];
49931 return data.filter(function(d) {
49933 return context.selectedIDs().indexOf(d.id) !== -1;
49935 return context.selectedIDs().indexOf(d.id) === -1;
49941 var getPath = svgPath(projection$$1, graph),
49945 oldMultiPolygonOuters = {};
49947 for (var i = 0; i < entities.length; i++) {
49948 var entity = entities[i],
49949 outer = osmSimpleMultipolygonOuterMember(entity, graph);
49951 ways.push(entity.mergeTags(outer.tags));
49952 oldMultiPolygonOuters[outer.id] = true;
49953 } else if (entity.geometry(graph) === 'line') {
49958 ways = ways.filter(getPath);
49959 pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
49961 lodash.forOwn(pathdata, function(v, k) {
49962 onewaydata[k] = lodash(v)
49963 .filter(function(d) { return d.isOneWay(); })
49964 .map(svgOneWaySegments(projection$$1, graph, 35))
49970 var layer = selection$$1.selectAll('.layer-lines');
49972 var layergroup = layer
49973 .selectAll('g.layergroup')
49974 .data(sequence(-10, 11));
49976 layergroup = layergroup.enter()
49978 .attr('class', function(d) { return 'layergroup layer' + String(d); })
49979 .merge(layergroup);
49982 .selectAll('g.linegroup')
49983 .data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted'])
49986 .attr('class', function(d) { return 'linegroup line-' + d; });
49989 layergroup.selectAll('g.line-shadow')
49990 .call(drawLineGroup, 'shadow', false);
49991 layergroup.selectAll('g.line-casing')
49992 .call(drawLineGroup, 'casing', false);
49993 layergroup.selectAll('g.line-stroke')
49994 .call(drawLineGroup, 'stroke', false);
49996 layergroup.selectAll('g.line-shadow-highlighted')
49997 .call(drawLineGroup, 'shadow', true);
49998 layergroup.selectAll('g.line-casing-highlighted')
49999 .call(drawLineGroup, 'casing', true);
50000 layergroup.selectAll('g.line-stroke-highlighted')
50001 .call(drawLineGroup, 'stroke', true);
50004 var onewaygroup = layergroup
50005 .selectAll('g.onewaygroup')
50008 onewaygroup = onewaygroup.enter()
50010 .attr('class', 'onewaygroup')
50011 .merge(onewaygroup);
50013 var oneways = onewaygroup
50017 function() { return onewaydata[this.parentNode.__data__] || []; },
50018 function(d) { return [d.id, d.index]; }
50024 oneways = oneways.enter()
50026 .attr('class', 'oneway')
50027 .attr('marker-mid', 'url(#oneway-marker)')
50029 .attr('d', function(d) { return d.d; });
50032 oneways.each(function() { this.parentNode.insertBefore(this, this); });
50040 function svgMidpoints$$1(projection, context) {
50042 return function drawMidpoints(selection, graph, entities, filter, extent) {
50043 var layer = selection.selectAll('.layer-hit');
50045 var mode = context.mode();
50046 if (mode && mode.id !== 'select') {
50047 layer.selectAll('g.midpoint').remove();
50051 var poly = extent.polygon(),
50054 for (var i = 0; i < entities.length; i++) {
50055 var entity = entities[i];
50057 if (entity.type !== 'way')
50059 if (!filter(entity))
50061 if (context.selectedIDs().indexOf(entity.id) < 0)
50064 var nodes = graph.childNodes(entity);
50065 for (var j = 0; j < nodes.length - 1; j++) {
50069 id = [a.id, b.id].sort().join('-');
50071 if (midpoints[id]) {
50072 midpoints[id].parents.push(entity);
50074 if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
50075 var point = geoInterp(a.loc, b.loc, 0.5),
50078 if (extent.intersects(point)) {
50081 for (var k = 0; k < 4; k++) {
50082 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
50084 geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
50085 geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
50098 edge: [a.id, b.id],
50108 function midpointFilter(d) {
50109 if (midpoints[d.id])
50112 for (var i = 0; i < d.parents.length; i++) {
50113 if (filter(d.parents[i])) {
50123 .selectAll('g.midpoint')
50124 .filter(midpointFilter)
50125 .data(lodash.values(midpoints), function(d) { return d.id; });
50130 var enter = groups.enter()
50131 .insert('g', ':first-child')
50132 .attr('class', 'midpoint');
50134 enter.append('polygon')
50135 .attr('points', '-6,8 10,0 -6,-8')
50136 .attr('class', 'shadow');
50138 enter.append('polygon')
50139 .attr('points', '-3,4 5,0 -3,-4')
50140 .attr('class', 'fill');
50144 .attr('transform', function(d) {
50145 var translate = svgPointTransform(projection),
50146 a = graph.entity(d.edge[0]),
50147 b = graph.entity(d.edge[1]),
50148 angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
50149 return translate(d) + ' rotate(' + angleVal + ')';
50151 .call(svgTagClasses().tags(
50152 function(d) { return d.parents[0].tags; }
50155 // Propagate data bindings.
50156 groups.select('polygon.shadow');
50157 groups.select('polygon.fill');
50162 function svgOneWaySegments(projection$$1, graph, dt) {
50163 return function(entity) {
50169 clip = identity$5().clipExtent(projection$$1.clipExtent()).stream,
50170 coordinates = graph.childNodes(entity).map(function(n) {
50174 if (entity.tags.oneway === '-1') coordinates.reverse();
50177 type: 'LineString',
50178 coordinates: coordinates
50179 }, projection$$1.stream(clip({
50180 lineStart: function() {},
50181 lineEnd: function() {
50184 point: function(x, y) {
50188 var span = geoEuclideanDistance(a, b) - offset;
50191 var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
50192 dx = dt * Math.cos(angle),
50193 dy = dt * Math.sin(angle),
50194 p = [a[0] + offset * Math.cos(angle),
50195 a[1] + offset * Math.sin(angle)];
50197 var segment = 'M' + a[0] + ',' + a[1] +
50198 'L' + p[0] + ',' + p[1];
50200 for (span -= dt; span >= 0; span -= dt) {
50203 segment += 'L' + p[0] + ',' + p[1];
50206 segment += 'L' + b[0] + ',' + b[1];
50207 segments.push({id: entity.id, index: i, d: segment});
50222 function svgPath(projection$$1, graph, isArea) {
50224 // Explanation of magic numbers:
50225 // "padding" here allows space for strokes to extend beyond the viewport,
50226 // so that the stroke isn't drawn along the edge of the viewport when
50227 // the shape is clipped.
50229 // When drawing lines, pad viewport by 5px.
50230 // When drawing areas, pad viewport by 65px in each direction to allow
50231 // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
50234 padding = isArea ? 65 : 5,
50235 viewport = projection$$1.clipExtent(),
50237 [viewport[0][0] - padding, viewport[0][1] - padding],
50238 [viewport[1][0] + padding, viewport[1][1] + padding]
50240 clip = identity$5().clipExtent(paddedExtent).stream,
50241 project = projection$$1.stream,
50242 path$$1 = index$4()
50243 .projection({stream: function(output) { return project(clip(output)); }});
50245 return function(entity) {
50246 if (entity.id in cache) {
50247 return cache[entity.id];
50249 return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
50254 function svgPoints$$1(projection, context) {
50256 function markerPath(selection, klass) {
50258 .attr('class', klass)
50259 .attr('transform', 'translate(-8, -23)')
50260 .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');
50263 function sortY(a, b) {
50264 return b.loc[1] - a.loc[1];
50268 return function drawPoints(selection, graph, entities, filter) {
50269 var wireframe = context.surface().classed('fill-wireframe'),
50270 points = wireframe ? [] : lodash.filter(entities, function(e) {
50271 return e.geometry(graph) === 'point';
50274 points.sort(sortY);
50276 var layer = selection.selectAll('.layer-hit');
50278 var groups = layer.selectAll('g.point')
50280 .data(points, osmEntity$$1.key);
50285 var enter = groups.enter()
50287 .attr('class', function(d) { return 'node point ' + d.id; })
50290 enter.append('path')
50291 .call(markerPath, 'shadow');
50293 enter.append('ellipse')
50298 .attr('class', 'stroke');
50300 enter.append('path')
50301 .call(markerPath, 'stroke');
50303 enter.append('use')
50304 .attr('transform', 'translate(-5, -19)')
50305 .attr('class', 'icon')
50306 .attr('width', '11px')
50307 .attr('height', '11px');
50311 .attr('transform', svgPointTransform(projection))
50312 .call(svgTagClasses());
50314 // Selecting the following implicitly
50315 // sets the data (point entity) on the element
50316 groups.select('.shadow');
50317 groups.select('.stroke');
50318 groups.select('.icon')
50319 .attr('xlink:href', function(entity) {
50320 var preset = context.presets().match(entity, graph),
50321 picon = preset && preset.icon;
50326 var isMaki = dataFeatureIcons.indexOf(picon) !== -1;
50327 return '#' + picon + (isMaki ? '-11' : '');
50333 function svgRelationMemberTags(graph) {
50334 return function(entity) {
50335 var tags = entity.tags;
50336 graph.parentRelations(entity).forEach(function(relation) {
50337 var type = relation.tags.type;
50338 if (type === 'multipolygon' || type === 'boundary') {
50339 tags = lodash.extend({}, relation.tags, tags);
50346 function svgTagClasses() {
50348 'building', 'highway', 'railway', 'waterway', 'aeroway',
50349 'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
50350 'leisure', 'military', 'place'
50353 'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
50354 'razed', 'demolished', 'obliterated'
50357 'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
50358 'surface', 'tracktype', 'crossing'
50360 tagClassRe = /^tag-/,
50361 tags = function(entity) { return entity.tags; };
50364 var tagClasses = function(selection$$1) {
50365 selection$$1.each(function tagClassesEach(entity) {
50366 var value = this.className,
50367 classes, primary, status;
50369 if (value.baseVal !== undefined) value = value.baseVal;
50371 classes = value.trim().split(/\s+/).filter(function(name) {
50372 return name.length && !tagClassRe.test(name);
50375 var t = tags(entity), i, k, v;
50377 // pick at most one primary classification tag..
50378 for (i = 0; i < primaries.length; i++) {
50381 if (!v || v === 'no') continue;
50384 if (statuses.indexOf(v) !== -1) { // e.g. `railway=abandoned`
50386 classes += ' tag-' + k;
50388 classes += ' tag-' + k + ' tag-' + k + '-' + v;
50394 // add at most one status tag, only if relates to primary tag..
50396 for (i = 0; i < statuses.length; i++) {
50399 if (!v || v === 'no') continue;
50401 if (v === 'yes') { // e.g. `railway=rail + abandoned=yes`
50404 else if (primary && primary === v) { // e.g. `railway=rail + abandoned=railway`
50406 } else if (!primary && primaries.indexOf(v) !== -1) { // e.g. `abandoned=railway`
50409 classes += ' tag-' + v;
50410 } // else ignore e.g. `highway=path + abandoned=railway`
50417 classes += ' tag-status tag-status-' + status;
50420 // add any secondary (structure) tags
50421 for (i = 0; i < secondaries.length; i++) {
50422 k = secondaries[i];
50424 if (!v || v === 'no') continue;
50425 classes += ' tag-' + k + ' tag-' + k + '-' + v;
50428 // For highways, look for surface tagging..
50429 if (primary === 'highway') {
50430 var paved = (t.highway !== 'track');
50433 if (k in osmPavedTags) {
50434 paved = !!osmPavedTags[k][v];
50439 classes += ' tag-unpaved';
50443 classes = classes.trim();
50445 if (classes !== value) {
50446 select(this).attr('class', classes);
50452 tagClasses.tags = function(_) {
50453 if (!arguments.length) return tags;
50461 function svgTurns(projection) {
50463 return function drawTurns(selection, graph, turns) {
50465 function key(turn) {
50466 return [turn.from.node + turn.via.node + turn.to.node].join('-');
50469 function icon(turn) {
50470 var u = turn.u ? '-u' : '';
50471 if (!turn.restriction)
50472 return '#turn-yes' + u;
50473 var restriction = graph.entity(turn.restriction).tags.restriction;
50475 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
50478 var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
50485 var enter = groups.enter()
50487 .attr('class', 'turn');
50490 .filter(function (turn) { return !turn.u; });
50492 nEnter.append('rect')
50493 .attr('transform', 'translate(-22, -12)')
50494 .attr('width', '44')
50495 .attr('height', '24');
50497 nEnter.append('use')
50498 .attr('transform', 'translate(-22, -12)')
50499 .attr('width', '44')
50500 .attr('height', '24');
50504 .filter(function (turn) { return turn.u; });
50506 uEnter.append('circle')
50509 uEnter.append('use')
50510 .attr('transform', 'translate(-16, -16)')
50511 .attr('width', '32')
50512 .attr('height', '32');
50519 .attr('transform', function (turn) {
50520 var v = graph.entity(turn.via.node),
50521 t = graph.entity(turn.to.node),
50522 a = geoAngle(v, t, projection),
50523 p = projection(v.loc),
50524 r = turn.u ? 0 : 60;
50526 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
50527 'rotate(' + a * 180 / Math.PI + ')';
50530 groups.select('use')
50531 .attr('xlink:href', icon);
50533 groups.select('rect');
50534 groups.select('circle');
50540 function svgVertices$$1(projection$$1, context) {
50542 // z16-, z17, z18+, tagged
50543 shadow: [6, 7.5, 7.5, 11.5],
50544 stroke: [2.5, 3.5, 3.5, 7],
50545 fill: [1, 1.5, 1.5, 1.5]
50551 function siblingAndChildVertices(ids, graph, extent$$1) {
50554 function addChildVertices(entity) {
50555 if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
50557 if (entity.type === 'way') {
50558 for (i = 0; i < entity.nodes.length; i++) {
50559 addChildVertices(graph.entity(entity.nodes[i]));
50561 } else if (entity.type === 'relation') {
50562 for (i = 0; i < entity.members.length; i++) {
50563 var member = context.hasEntity(entity.members[i].id);
50565 addChildVertices(member);
50568 } else if (entity.intersects(extent$$1, graph)) {
50569 vertices[entity.id] = entity;
50574 ids.forEach(function(id) {
50575 var entity = context.hasEntity(id);
50576 if (entity && entity.type === 'node') {
50577 vertices[entity.id] = entity;
50578 context.graph().parentWays(entity).forEach(function(entity) {
50579 addChildVertices(entity);
50581 } else if (entity) {
50582 addChildVertices(entity);
50590 function draw(selection$$1, vertices, klass, graph, zoom$$1, siblings$$1) {
50592 function icon(entity) {
50593 if (entity.id in icons) return icons[entity.id];
50595 entity.hasInterestingTags() &&
50596 context.presets().match(entity, graph).icon;
50597 return icons[entity.id];
50600 function setClass(klass) {
50601 return function(entity) {
50602 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
50606 function setAttributes(selection$$1) {
50607 ['shadow','stroke','fill'].forEach(function(klass) {
50608 var rads = radiuses[klass];
50609 selection$$1.selectAll('.' + klass)
50610 .each(function(entity) {
50611 var i = z && icon(entity),
50613 r = rads[i ? 3 : z];
50615 // slightly increase the size of unconnected endpoints #3775
50616 if (entity.isEndpoint(graph) && !entity.isConnected(graph)) {
50620 this.setAttribute('cx', c);
50621 this.setAttribute('cy', -c);
50622 this.setAttribute('r', r);
50623 if (i && klass === 'fill') {
50624 this.setAttribute('visibility', 'hidden');
50626 this.removeAttribute('visibility');
50631 selection$$1.selectAll('use')
50634 this.removeAttribute('visibility');
50636 this.setAttribute('visibility', 'hidden');
50642 siblings$$1 = siblings$$1 || {};
50645 z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
50647 var groups = selection$$1
50648 .data(vertices, osmEntity$$1.key);
50653 var enter = groups.enter()
50655 .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
50657 enter.append('circle')
50658 .each(setClass('shadow'));
50660 enter.append('circle')
50661 .each(setClass('stroke'));
50663 // Vertices with icons get a `use`.
50664 enter.filter(function(d) { return icon(d); })
50666 .attr('transform', 'translate(-5, -6)')
50667 .attr('xlink:href', function(d) {
50668 var picon = icon(d),
50669 isMaki = dataFeatureIcons.indexOf(picon) !== -1;
50670 return '#' + picon + (isMaki ? '-11' : '');
50672 .attr('width', '11px')
50673 .attr('height', '11px')
50674 .each(setClass('icon'));
50676 // Vertices with tags get a fill.
50677 enter.filter(function(d) { return d.hasInterestingTags(); })
50679 .each(setClass('fill'));
50683 .attr('transform', svgPointTransform(projection$$1))
50684 .classed('sibling', function(entity) { return entity.id in siblings$$1; })
50685 .classed('shared', function(entity) { return graph.isShared(entity); })
50686 .classed('endpoint', function(entity) { return entity.isEndpoint(graph); })
50687 .call(setAttributes);
50691 function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
50692 var siblings$$1 = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
50693 wireframe = context.surface().classed('fill-wireframe'),
50696 for (var i = 0; i < entities.length; i++) {
50697 var entity = entities[i],
50698 geometry = entity.geometry(graph);
50700 if (wireframe && geometry === 'point') {
50701 vertices.push(entity);
50705 if (geometry !== 'vertex')
50708 if (entity.id in siblings$$1 ||
50709 entity.hasInterestingTags() ||
50710 entity.isEndpoint(graph) ||
50711 entity.isConnected(graph)) {
50712 vertices.push(entity);
50716 var layer = selection$$1.selectAll('.layer-hit');
50717 layer.selectAll('g.vertex.vertex-persistent')
50719 .call(draw, vertices, 'vertex-persistent', graph, zoom$$1, siblings$$1);
50721 drawHover(selection$$1, graph, extent$$1, zoom$$1);
50725 function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
50726 var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
50727 var layer = selection$$1.selectAll('.layer-hit');
50729 layer.selectAll('g.vertex.vertex-hover')
50730 .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
50734 drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
50735 if (target === hover) return;
50737 drawHover(selection$$1, graph, extent$$1, zoom$$1);
50740 return drawVertices;
50743 function behaviorEdit(context) {
50747 .minzoom(context.minEditableZoom());
50751 edit.off = function() {
50761 The hover behavior adds the `.hover` class on mouseover to all elements to which
50762 the identical datum is bound, and removes it on mouseout.
50764 The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
50765 representation may consist of several elements scattered throughout the DOM hierarchy.
50766 Only one of these elements can have the :hover pseudo-class, but all of them will
50767 have the .hover class.
50769 function behaviorHover(context) {
50770 var dispatch$$1 = dispatch('hover'),
50771 _selection = select(null),
50778 function keydown() {
50779 if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
50780 _selection.selectAll('.hover')
50781 .classed('hover-suppressed', true)
50782 .classed('hover', false);
50785 .classed('hover-disabled', true);
50787 dispatch$$1.call('hover', this, null);
50793 if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
50794 _selection.selectAll('.hover-suppressed')
50795 .classed('hover-suppressed', false)
50796 .classed('hover', true);
50799 .classed('hover-disabled', false);
50801 dispatch$$1.call('hover', this, target ? target.id : null);
50806 var hover = function(selection$$1) {
50807 _selection = selection$$1;
50811 .on('mouseover.hover', mouseover)
50812 .on('mouseout.hover', mouseout)
50813 .on('mousedown.hover', mousedown);
50816 .on('keydown.hover', keydown)
50817 .on('keyup.hover', keyup);
50820 function mouseover() {
50821 if (buttonDown) return;
50822 var target = event.target;
50823 enter(target ? target.__data__ : null);
50827 function mouseout() {
50828 if (buttonDown) return;
50829 var target = event.relatedTarget;
50830 enter(target ? target.__data__ : null);
50834 function mousedown() {
50837 .on('mouseup.hover', mouseup, true);
50841 function mouseup() {
50842 buttonDown = false;
50844 .on('mouseup.hover', null, true);
50848 function enter(d) {
50849 if (d === target) return;
50852 _selection.selectAll('.hover')
50853 .classed('hover', false);
50854 _selection.selectAll('.hover-suppressed')
50855 .classed('hover-suppressed', false);
50857 if (target instanceof osmEntity$$1 && target.id !== newId) {
50859 // If drawing a way, don't hover on a node that was just placed. #3974
50860 var mode = context.mode() && context.mode().id;
50861 if ((mode === 'draw-line' || mode === 'draw-area') && !newId && target.type === 'node') {
50866 var selector$$1 = '.' + target.id;
50868 if (target.type === 'relation') {
50869 target.members.forEach(function(member) {
50870 selector$$1 += ', .' + member.id;
50874 var suppressed = altDisables && event && event.altKey;
50876 _selection.selectAll(selector$$1)
50877 .classed(suppressed ? 'hover-suppressed' : 'hover', true);
50879 dispatch$$1.call('hover', this, !suppressed && target.id);
50882 dispatch$$1.call('hover', this, null);
50889 hover.off = function(selection$$1) {
50890 selection$$1.selectAll('.hover')
50891 .classed('hover', false);
50892 selection$$1.selectAll('.hover-suppressed')
50893 .classed('hover-suppressed', false);
50895 .classed('hover-disabled', false);
50899 .on('mouseover.hover', null)
50900 .on('mouseout.hover', null)
50901 .on('mousedown.hover', null);
50904 .on('keydown.hover', null)
50905 .on('keyup.hover', null);
50909 hover.altDisables = function(_) {
50910 if (!arguments.length) return altDisables;
50916 return utilRebind(hover, dispatch$$1, 'on');
50919 function behaviorTail() {
50923 tooltipSize = [0, 0],
50924 selectionSize = [0, 0];
50927 function tail(selection$$1) {
50928 if (!text$$1) return;
50931 .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
50933 container = select(document.body)
50935 .style('display', 'none')
50936 .attr('class', 'tail tooltip-inner');
50938 container.append('div')
50942 .on('mousemove.tail', mousemove)
50943 .on('mouseenter.tail', mouseenter)
50944 .on('mouseleave.tail', mouseleave);
50947 .on('mousemove.tail', mousemove);
50949 tooltipSize = utilGetDimensions(container);
50950 selectionSize = utilGetDimensions(selection$$1);
50954 container.style('display', 'block');
50955 tooltipSize = utilGetDimensions(container);
50959 function mousemove() {
50960 if (container.style('display') === 'none') show();
50961 var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
50962 -tooltipSize[0] - xmargin : xmargin;
50963 container.classed('left', xoffset > 0);
50964 utilSetTransform(container, event.clientX + xoffset, event.clientY);
50968 function mouseleave() {
50969 if (event.relatedTarget !== container.node()) {
50970 container.style('display', 'none');
50975 function mouseenter() {
50976 if (event.relatedTarget !== container.node()) {
50983 tail.off = function(selection$$1) {
50984 if (!text$$1) return;
50987 .on('mousemove.tail', null)
50991 .on('mousemove.tail', null)
50992 .on('mouseenter.tail', null)
50993 .on('mouseleave.tail', null);
50996 .on('resize.tail', null);
51000 tail.text = function(_) {
51001 if (!arguments.length) return text$$1;
51010 var usedTails = {};
51011 var disableSpace = false;
51012 var lastSpace = null;
51015 function behaviorDraw(context) {
51016 var dispatch$$1 = dispatch('move', 'click', 'clickWay',
51017 'clickNode', 'undo', 'cancel', 'finish'),
51018 keybinding = d3keybinding('draw'),
51019 hover = behaviorHover(context)
51021 .on('hover', context.ui().sidebar.hover),
51022 tail = behaviorTail(),
51023 edit = behaviorEdit(context),
51024 closeTolerance = 4,
51026 mouseLeave = false,
51031 if (event.altKey) return {};
51033 if (event.type === 'keydown') {
51034 return (lastMouse && lastMouse.target.__data__) || {};
51036 return event.target.__data__ || {};
51041 function mousedown() {
51044 var p = context.container().node();
51045 return touchId !== null ? touches(p).filter(function(p) {
51046 return p.identifier === touchId;
51050 var element = select(this),
51051 touchId = event.touches ? event.changedTouches[0].identifier : null,
51055 element.on('mousemove.draw', null);
51057 select(window).on('mouseup.draw', function() {
51058 var t2 = +new Date(),
51060 dist = geoEuclideanDistance(p1, p2);
51062 element.on('mousemove.draw', mousemove);
51063 select(window).on('mouseup.draw', null);
51065 if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
51066 // Prevent a quick second click
51067 select(window).on('click.draw-block', function() {
51068 event.stopPropagation();
51071 context.map().dblclickEnable(false);
51073 window.setTimeout(function() {
51074 context.map().dblclickEnable(true);
51075 select(window).on('click.draw-block', null);
51084 function mousemove() {
51086 dispatch$$1.call('move', this, datum());
51090 function mouseenter() {
51091 mouseLeave = false;
51095 function mouseleave() {
51102 if (d.type === 'way') {
51103 var dims = context.map().dimensions(),
51104 mouse$$1 = context.mouse(),
51106 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
51107 mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
51110 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
51111 edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
51112 dispatch$$1.call('clickWay', this, choice.loc, edge);
51114 dispatch$$1.call('click', this, context.map().mouseCoordinates());
51117 } else if (d.type === 'node') {
51118 dispatch$$1.call('clickNode', this, d);
51121 dispatch$$1.call('click', this, context.map().mouseCoordinates());
51127 event.preventDefault();
51128 event.stopPropagation();
51130 var currSpace = context.mouse();
51131 if (disableSpace && lastSpace) {
51132 var dist = geoEuclideanDistance(lastSpace, currSpace);
51133 if (dist > tolerance) {
51134 disableSpace = false;
51138 if (disableSpace || mouseLeave || !lastMouse) return;
51140 // user must move mouse or release space bar to allow another click
51141 lastSpace = currSpace;
51142 disableSpace = true;
51144 select(window).on('keyup.space-block', function() {
51145 event.preventDefault();
51146 event.stopPropagation();
51147 disableSpace = false;
51148 select(window).on('keyup.space-block', null);
51155 function backspace() {
51156 event.preventDefault();
51157 dispatch$$1.call('undo');
51162 event.preventDefault();
51163 dispatch$$1.call('cancel');
51168 event.preventDefault();
51169 dispatch$$1.call('finish');
51173 function draw(selection$$1) {
51174 context.install(hover);
51175 context.install(edit);
51177 if (!context.inIntro() && !usedTails[tail.text()]) {
51178 context.install(tail);
51182 .on('⌫', backspace)
51186 .on('space', space)
51187 .on('⌥space', space);
51190 .on('mouseenter.draw', mouseenter)
51191 .on('mouseleave.draw', mouseleave)
51192 .on('mousedown.draw', mousedown)
51193 .on('mousemove.draw', mousemove);
51202 draw.off = function(selection$$1) {
51203 context.ui().sidebar.hover.cancel();
51204 context.uninstall(hover);
51205 context.uninstall(edit);
51207 if (!context.inIntro() && !usedTails[tail.text()]) {
51208 context.uninstall(tail);
51209 usedTails[tail.text()] = true;
51213 .on('mouseenter.draw', null)
51214 .on('mouseleave.draw', null)
51215 .on('mousedown.draw', null)
51216 .on('mousemove.draw', null);
51219 .on('mouseup.draw', null);
51220 // note: keyup.space-block, click.draw-block should remain
51223 .call(keybinding.off);
51227 draw.tail = function(_) {
51233 return utilRebind(draw, dispatch$$1, 'on');
51236 function behaviorAddWay(context) {
51237 var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
51238 draw = behaviorDraw(context);
51240 var addWay = function(surface) {
51241 draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
51242 .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
51243 .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
51244 .on('cancel', addWay.cancel)
51245 .on('finish', addWay.cancel);
51248 .dblclickEnable(false);
51250 surface.call(draw);
51254 addWay.off = function(surface) {
51255 surface.call(draw.off);
51259 addWay.cancel = function() {
51260 window.setTimeout(function() {
51261 context.map().dblclickEnable(true);
51264 context.enter(modeBrowse(context));
51268 addWay.tail = function(text$$1) {
51269 draw.tail(text$$1);
51274 return utilRebind(addWay, dispatch$$1, 'on');
51277 function behaviorBreathe() {
51278 var duration = 800,
51280 selector$$1 = '.selected.shadow, .selected .shadow',
51281 selected = select(null),
51288 function ratchetyInterpolator(a, b, steps, units) {
51291 var sample = quantize$1()
51293 .range(quantize(reinterpolate(a, b), steps));
51295 return function(t) {
51296 return String(sample(t)) + (units || '');
51301 function reset(selection$$1) {
51303 .style('stroke-opacity', null)
51304 .style('stroke-width', null)
51305 .style('fill-opacity', null)
51310 function setAnimationParams(transition$$1, fromTo) {
51311 var toFrom = (fromTo === 'from' ? 'to' : 'from');
51314 .styleTween('stroke-opacity', function(d) {
51315 return ratchetyInterpolator(
51316 params[d.id][toFrom].opacity,
51317 params[d.id][fromTo].opacity,
51321 .styleTween('stroke-width', function(d) {
51322 return ratchetyInterpolator(
51323 params[d.id][toFrom].width,
51324 params[d.id][fromTo].width,
51329 .styleTween('fill-opacity', function(d) {
51330 return ratchetyInterpolator(
51331 params[d.id][toFrom].opacity,
51332 params[d.id][fromTo].opacity,
51336 .styleTween('r', function(d) {
51337 return ratchetyInterpolator(
51338 params[d.id][toFrom].width,
51339 params[d.id][fromTo].width,
51347 function calcAnimationParams(selection$$1) {
51350 .each(function(d) {
51351 var s = select(this),
51352 tag = s.node().tagName,
51353 p = {'from': {}, 'to': {}},
51356 // determine base opacity and width
51357 if (tag === 'circle') {
51358 opacity = parseFloat(s.style('fill-opacity') || 0.5);
51359 width = parseFloat(s.style('r') || 15.5);
51361 opacity = parseFloat(s.style('stroke-opacity') || 0.7);
51362 width = parseFloat(s.style('stroke-width') || 10);
51365 // calculate from/to interpolation params..
51367 p.from.opacity = opacity * 0.6;
51368 p.to.opacity = opacity * 1.25;
51369 p.from.width = width * 0.7;
51370 p.to.width = width * (tag === 'circle' ? 1.5 : 1);
51376 function run(surface, fromTo) {
51377 var toFrom = (fromTo === 'from' ? 'to' : 'from'),
51378 currSelected = surface.selectAll(selector$$1),
51379 currClassed = surface.attr('class');
51381 if (done || currSelected.empty()) {
51382 selected.call(reset);
51386 if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
51387 selected.call(reset);
51388 classed = currClassed;
51389 selected = currSelected.call(calcAnimationParams);
51394 .duration(duration)
51395 .call(setAnimationParams, fromTo)
51396 .on('end', function() {
51397 surface.call(run, toFrom);
51402 var breathe = function(surface) {
51404 timer$$1 = timer(function() {
51405 // wait for elements to actually become selected
51406 if (surface.selectAll(selector$$1).empty()) {
51410 surface.call(run, 'from');
51417 breathe.off = function() {
51431 function behaviorCopy(context) {
51432 var keybinding = d3keybinding('copy');
51435 function groupEntities(ids, graph) {
51436 var entities = ids.map(function (id) { return graph.entity(id); });
51437 return lodash.extend({relation: [], way: [], node: []},
51438 lodash.groupBy(entities, function(entity) { return entity.type; }));
51442 function getDescendants(id, graph, descendants) {
51443 var entity = graph.entity(id),
51446 descendants = descendants || {};
51448 if (entity.type === 'relation') {
51449 children = lodash.map(entity.members, 'id');
51450 } else if (entity.type === 'way') {
51451 children = entity.nodes;
51456 for (i = 0; i < children.length; i++) {
51457 if (!descendants[children[i]]) {
51458 descendants[children[i]] = true;
51459 descendants = getDescendants(children[i], graph, descendants);
51463 return descendants;
51467 function doCopy() {
51468 event.preventDefault();
51470 var graph = context.graph(),
51471 selected = groupEntities(context.selectedIDs(), graph),
51476 for (i = 0; i < selected.relation.length; i++) {
51477 entity = selected.relation[i];
51478 if (!skip[entity.id] && entity.isComplete(graph)) {
51479 canCopy.push(entity.id);
51480 skip = getDescendants(entity.id, graph, skip);
51483 for (i = 0; i < selected.way.length; i++) {
51484 entity = selected.way[i];
51485 if (!skip[entity.id]) {
51486 canCopy.push(entity.id);
51487 skip = getDescendants(entity.id, graph, skip);
51490 for (i = 0; i < selected.node.length; i++) {
51491 entity = selected.node[i];
51492 if (!skip[entity.id]) {
51493 canCopy.push(entity.id);
51497 context.copyIDs(canCopy);
51502 keybinding.on(uiCmd('⌘C'), doCopy);
51503 select(document).call(keybinding);
51508 copy.off = function() {
51509 select(document).call(keybinding.off);
51517 `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
51519 * The `origin` function is expected to return an [x, y] tuple rather than an
51521 * The events are `start`, `move`, and `end`.
51522 (https://github.com/mbostock/d3/issues/563)
51523 * The `start` event is not dispatched until the first cursor movement occurs.
51524 (https://github.com/mbostock/d3/pull/368)
51525 * The `move` event has a `point` and `delta` [x, y] tuple properties rather
51526 than `x`, `y`, `dx`, and `dy` properties.
51527 * The `end` event is not dispatched if no movement occurs.
51528 * An `off` function is available that unbinds the drag's internal event handlers.
51531 function behaviorDrag() {
51532 var event$$1 = dispatch('start', 'move', 'end'),
51536 event_, target, surface;
51539 var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
51540 d3_event_userSelectSuppress = function() {
51541 var selection$$1 = selection(),
51542 select$$1 = selection$$1.style(d3_event_userSelectProperty);
51543 selection$$1.style(d3_event_userSelectProperty, 'none');
51544 return function() {
51545 selection$$1.style(d3_event_userSelectProperty, select$$1);
51550 function d3_eventCancel() {
51551 event.stopPropagation();
51552 event.preventDefault();
51556 function eventOf(thiz, argumentz) {
51557 return function(e1) {
51558 e1.target = drag$$1;
51559 customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
51564 function dragstart() {
51566 event_ = eventOf(target, arguments);
51568 var eventTarget = event.target,
51569 touchId = event.touches ? event.changedTouches[0].identifier : null,
51573 selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
51576 .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
51577 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
51580 offset = origin.apply(target, arguments);
51581 offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
51586 if (touchId === null) {
51587 event.stopPropagation();
51592 var p = surface || target.parentNode;
51593 return touchId !== null ? touches(p).filter(function(p) {
51594 return p.identifier === touchId;
51599 function dragmove() {
51601 dx = p[0] - origin_[0],
51602 dy = p[1] - origin_[1];
51604 if (dx === 0 && dy === 0)
51609 event_({ type: 'start' });
51617 point: [p[0] + offset[0], p[1] + offset[1]],
51623 function dragend() {
51625 event_({ type: 'end' });
51628 if (event.target === eventTarget) {
51630 .on('click.drag', click, true);
51635 .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
51636 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
51645 .on('click.drag', null);
51650 function drag$$1(selection$$1) {
51651 var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
51652 delegate = dragstart;
51655 delegate = function() {
51657 target = event.target;
51658 for (; target && target !== root; target = target.parentNode) {
51659 if (target[matchesSelector](selector$$1) &&
51660 (!filter || filter(target.__data__))) {
51661 return dragstart.call(target, target.__data__);
51668 .on('mousedown.drag' + selector$$1, delegate)
51669 .on('touchstart.drag' + selector$$1, delegate);
51673 drag$$1.off = function(selection$$1) {
51675 .on('mousedown.drag' + selector$$1, null)
51676 .on('touchstart.drag' + selector$$1, null);
51680 drag$$1.selector = function(_) {
51681 if (!arguments.length) return selector$$1;
51687 drag$$1.filter = function(_) {
51688 if (!arguments.length) return origin;
51694 drag$$1.origin = function (_) {
51695 if (!arguments.length) return origin;
51701 drag$$1.cancel = function() {
51703 .on('mousemove.drag', null)
51704 .on('mouseup.drag', null);
51709 drag$$1.target = function() {
51710 if (!arguments.length) return target;
51711 target = arguments[0];
51712 event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
51717 drag$$1.surface = function() {
51718 if (!arguments.length) return surface;
51719 surface = arguments[0];
51724 return utilRebind(drag$$1, event$$1, 'on');
51727 function behaviorDrawWay(context, wayId, index, mode, startGraph) {
51729 var origWay = context.entity(wayId),
51730 isArea = context.geometry(wayId) === 'area',
51732 annotation = t((origWay.isDegenerate() ?
51733 'operations.start.annotation.' :
51734 'operations.continue.annotation.') + context.geometry(wayId)),
51735 draw = behaviorDraw(context),
51742 // initialize the temporary drawing entities
51744 startIndex = typeof index === 'undefined' ? origWay.nodes.length - 1 : 0;
51745 start = osmNode({ id: 'nStart', loc: context.entity(origWay.nodes[startIndex]).loc });
51746 end = osmNode({ id: 'nEnd', loc: context.map().mouseCoordinates() });
51747 segment = osmWay({ id: 'wTemp',
51748 nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
51749 tags: lodash.clone(origWay.tags)
51752 end = osmNode({ loc: context.map().mouseCoordinates() });
51755 // Push an annotated state for undo to return back to.
51756 // We must make sure to remove this edit later.
51757 context.perform(actionNoop(), annotation);
51760 // Add the temporary drawing entities to the graph.
51761 // We must make sure to remove this edit later.
51762 context.perform(AddDrawEntities());
51766 function move(datum) {
51769 if (datum.type === 'node' && datum.id !== end.id) {
51772 } else if (datum.type === 'way') {
51773 var dims = context.map().dimensions(),
51774 mouse = context.mouse(),
51776 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
51777 mouse[1] > pad && mouse[1] < dims[1] - pad;
51780 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
51785 loc = context.map().mouseCoordinates();
51788 context.replace(actionMoveNode(end.id, loc));
51789 end = context.entity(end.id);
51793 function undone() {
51794 // Undo popped the history back to the initial annotated no-op edit.
51795 // Remove initial no-op edit and whatever edit happened immediately before it.
51799 if (context.hasEntity(wayId)) {
51800 context.enter(mode);
51802 context.enter(modeBrowse(context));
51807 function setActiveElements() {
51808 var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
51809 context.surface().selectAll(utilEntitySelector(active))
51810 .classed('active', true);
51814 var drawWay = function(surface) {
51815 draw.on('move', move)
51816 .on('click', drawWay.add)
51817 .on('clickWay', drawWay.addWay)
51818 .on('clickNode', drawWay.addNode)
51819 .on('undo', context.undo)
51820 .on('cancel', drawWay.cancel)
51821 .on('finish', drawWay.finish);
51824 .dblclickEnable(false)
51825 .on('drawn.draw', setActiveElements);
51827 setActiveElements();
51829 surface.call(draw);
51832 .on('undone.draw', undone);
51836 drawWay.off = function(surface) {
51837 // Drawing was interrupted unexpectedly.
51838 // This can happen if the user changes modes,
51839 // clicks geolocate button, a hashchange event occurs, etc.
51841 context.pop(tempEdits);
51842 while (context.graph() !== startGraph) {
51848 .on('drawn.draw', null);
51850 surface.call(draw.off)
51851 .selectAll('.active')
51852 .classed('active', false);
51855 .on('undone.draw', null);
51859 function AddDrawEntities() {
51860 return function(graph) {
51862 // For area drawing, there is no need for a temporary node.
51863 // `end` gets inserted into the way as the penultimate node.
51866 .replace(origWay.addNode(end.id));
51868 // For line drawing, add a temporary start, end, and segment to the graph.
51869 // This allows us to class the new segment as `active`, but still
51870 // connect it back to parts of the way that have already been drawn.
51880 function ReplaceDrawEntities(newNode) {
51881 return function(graph) {
51883 // For area drawing, we didn't create a temporary node.
51884 // `newNode` gets inserted into the _original_ way as the penultimate node.
51886 .replace(origWay.addNode(newNode.id))
51889 // For line drawing, add the `newNode` to the way at specified index,
51890 // and remove the temporary start, end, and segment.
51892 .replace(origWay.addNode(newNode.id, index))
51901 // Accept the current position of the temporary node and continue drawing.
51902 drawWay.add = function(loc) {
51903 // prevent duplicate nodes
51904 var last = context.hasEntity(origWay.nodes[origWay.nodes.length - (isArea ? 2 : 1)]);
51905 if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
51907 context.pop(tempEdits);
51915 var newNode = osmNode({loc: loc});
51917 actionAddEntity(newNode),
51918 ReplaceDrawEntities(newNode),
51924 context.enter(mode);
51928 // Connect the way to an existing way.
51929 drawWay.addWay = function(loc, edge) {
51931 context.pop(tempEdits);
51935 actionAddMidpoint({ loc: loc, edge: edge}, end),
51939 var previousEdge = startIndex ?
51940 [origWay.nodes[startIndex], origWay.nodes[startIndex - 1]] :
51941 [origWay.nodes[0], origWay.nodes[1]];
51943 // Avoid creating duplicate segments
51944 if (geoEdgeEqual(edge, previousEdge))
51947 context.pop(tempEdits);
51949 var newNode = osmNode({ loc: loc });
51951 actionAddMidpoint({ loc: loc, edge: edge}, newNode),
51952 ReplaceDrawEntities(newNode),
51958 context.enter(mode);
51962 // Connect the way to an existing node and continue drawing.
51963 drawWay.addNode = function(node) {
51964 // Avoid creating duplicate segments
51965 if (origWay.areAdjacent(node.id, origWay.nodes[origWay.nodes.length - 1])) return;
51967 // Clicks should not occur on the drawing node, however a space keypress can
51968 // sometimes grab that node's datum (before it gets classed as `active`?) #4016
51969 if (node.id === end.id) {
51970 drawWay.add(node.loc);
51974 context.pop(tempEdits);
51977 ReplaceDrawEntities(node),
51982 context.enter(mode);
51986 // Finish the draw operation, removing the temporary edits.
51987 // If the way has enough nodes to be valid, it's selected.
51988 // Otherwise, delete everything and return to browse mode.
51989 drawWay.finish = function() {
51990 context.pop(tempEdits);
51993 var way = context.hasEntity(wayId);
51994 if (!way || way.isDegenerate()) {
51999 window.setTimeout(function() {
52000 context.map().dblclickEnable(true);
52003 context.enter(modeSelect(context, [wayId]).newFeature(true));
52007 // Cancel the draw operation, delete everything, and return to browse mode.
52008 drawWay.cancel = function() {
52009 context.pop(tempEdits);
52012 while (context.graph() !== startGraph) {
52016 window.setTimeout(function() {
52017 context.map().dblclickEnable(true);
52020 context.enter(modeBrowse(context));
52024 drawWay.tail = function(text) {
52033 function behaviorHash(context) {
52034 var s0 = null, // cached window.location.hash
52035 lat = 90 - 1e-8; // allowable latitude range
52038 var parser = function(map, s) {
52039 var q = utilStringQs(s);
52040 var args = (q.map || '').split('/').map(Number);
52042 if (args.length < 3 || args.some(isNaN)) {
52043 return true; // replace bogus hash
52045 } else if (s !== formatter(map).slice(1)) { // hash has changed
52046 var mode = context.mode(),
52047 dist = geoSphericalDistance(map.center(), [args[2], args[1]]),
52050 // Don't allow the hash location to change too much while drawing
52051 // This can happen if the user accidently hit the back button. #3996
52052 if (mode && mode.id.match(/^draw/) !== null && dist > maxdist) {
52053 context.enter(modeBrowse(context));
52056 map.centerZoom([args[2], Math.min(lat, Math.max(-lat, args[1]))], args[0]);
52061 var formatter = function(map) {
52062 var center = map.center(),
52063 zoom$$1 = map.zoom(),
52064 precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
52065 q = lodash.omit(utilStringQs(window.location.hash.substring(1)), ['comment', 'walkthrough']),
52069 var selected = context.selectedIDs().filter(function(id) {
52070 return !context.entity(id).isNew();
52072 if (selected.length) {
52073 newParams.id = selected.join(',');
52076 newParams.map = zoom$$1.toFixed(2) +
52077 '/' + center[1].toFixed(precision) +
52078 '/' + center[0].toFixed(precision);
52080 return '#' + utilQsString(lodash.assign(q, newParams), true);
52084 function update() {
52085 if (context.inIntro()) return;
52086 var s1 = formatter(context.map());
52088 window.location.replace(s0 = s1); // don't recenter the map!
52093 var throttledUpdate = lodash.throttle(update, 500);
52096 function hashchange() {
52097 if (window.location.hash === s0) return; // ignore spurious hashchange events
52098 if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
52099 update(); // replace bogus hash
52106 .on('move.hash', throttledUpdate);
52109 .on('enter.hash', throttledUpdate);
52112 .on('hashchange.hash', hashchange);
52114 if (window.location.hash) {
52116 var q = utilStringQs(window.location.hash.substring(1));
52119 context.zoomToEntity(q.id.split(',')[0], !q.map);
52123 context.storage('comment', q.comment);
52124 context.storage('commentDate', Date.now());
52127 if (q.walkthrough) {
52128 hash.startWalkthrough = true;
52134 hash.hadHash = true;
52140 hash.off = function() {
52141 throttledUpdate.cancel();
52144 .on('move.hash', null);
52147 .on('enter.hash', null);
52150 .on('hashchange.hash', null);
52152 window.location.hash = '';
52159 function behaviorLasso(context) {
52161 var behavior = function(selection$$1) {
52165 function mousedown() {
52166 var button = 0; // left
52167 if (event.button === button && event.shiftKey === true) {
52171 .on('mousemove.lasso', mousemove)
52172 .on('mouseup.lasso', mouseup);
52174 event.stopPropagation();
52179 function mousemove() {
52181 lasso = uiLasso(context);
52182 context.surface().call(lasso);
52185 lasso.p(context.mouse());
52189 function normalize(a, b) {
52191 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
52192 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
52196 function lassoed() {
52197 if (!lasso) return [];
52199 var graph = context.graph(),
52200 bounds$$1 = lasso.extent().map(context.projection.invert),
52201 extent$$1 = geoExtent$$1(normalize(bounds$$1[0], bounds$$1[1]));
52203 return lodash.map(context.intersects(extent$$1).filter(function(entity) {
52204 return entity.type === 'node' &&
52205 geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
52206 !context.features().isHidden(entity, graph, entity.geometry(graph));
52211 function mouseup() {
52213 .on('mousemove.lasso', null)
52214 .on('mouseup.lasso', null);
52216 if (!lasso) return;
52218 var ids = lassoed();
52222 context.enter(modeSelect(context, ids));
52227 .on('mousedown.lasso', mousedown);
52231 behavior.off = function(selection$$1) {
52232 selection$$1.on('mousedown.lasso', null);
52239 /* Creates a keybinding behavior for an operation */
52240 function behaviorOperation() {
52241 var which, keybinding;
52244 function drawIcon(selection$$1) {
52245 var button = selection$$1
52247 .attr('class', 'operation-icon')
52249 .attr('class', 'radial-menu-item radial-menu-item-' + which.id)
52250 .attr('transform', 'translate(10,10)')
52251 .classed('disabled', which.disabled());
52259 .attr('transform', 'translate(-7,-7)')
52260 .attr('width', '14')
52261 .attr('height', '14')
52262 .attr('xlink:href', '#operation-' + which.id);
52264 return selection$$1;
52268 var behavior = function () {
52269 if (which && which.available()) {
52270 keybinding = d3keybinding('behavior.key.' + which.id);
52271 keybinding.on(which.keys, function() {
52272 event.preventDefault();
52273 var disabled = which.disabled();
52280 .attr('class', 'operation-tip')
52281 .text(which.tooltip);
52288 .attr('class', 'operation-tip')
52289 .text(which.annotation() || which.title);
52294 select(document).call(keybinding);
52300 behavior.off = function() {
52302 select(document).call(keybinding.off);
52307 behavior.which = function (_) {
52308 if (!arguments.length) return which;
52317 function behaviorPaste(context) {
52318 var keybinding = d3keybinding('paste');
52321 function doPaste() {
52322 event.preventDefault();
52324 var baseGraph = context.graph(),
52325 mouse$$1 = context.mouse(),
52326 projection$$1 = context.projection,
52327 viewport = geoExtent$$1(projection$$1.clipExtent()).polygon();
52329 if (!geoPointInPolygon(mouse$$1, viewport)) return;
52331 var extent$$1 = geoExtent$$1(),
52332 oldIDs = context.copyIDs(),
52333 oldGraph = context.copyGraph(),
52336 if (!oldIDs.length) return;
52338 var action = actionCopyEntities(oldIDs, oldGraph);
52339 context.perform(action);
52341 var copies = action.copies();
52342 var originals = lodash.invert(lodash.mapValues(copies, 'id'));
52343 for (var id in copies) {
52344 var oldEntity = oldGraph.entity(id),
52345 newEntity = copies[id];
52347 extent$$1._extend(oldEntity.extent(oldGraph));
52349 // Exclude child nodes from newIDs if their parent way was also copied.
52350 var parents = context.graph().parentWays(newEntity),
52351 parentCopied = false;
52352 for (var i = 0; i < parents.length; i++) {
52353 if (originals[parents[i].id]) {
52354 parentCopied = true;
52359 if (!parentCopied) {
52360 newIDs.push(newEntity.id);
52364 // Put pasted objects where mouse pointer is..
52365 var center = projection$$1(extent$$1.center()),
52366 delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
52368 context.perform(actionMove(newIDs, delta, projection$$1));
52369 context.enter(modeMove$$1(context, newIDs, baseGraph));
52374 keybinding.on(uiCmd('⌘V'), doPaste);
52375 select(document).call(keybinding);
52380 paste.off = function() {
52381 select(document).call(keybinding.off);
52388 function behaviorSelect(context) {
52389 var lastMouse = null,
52390 suppressMenu = true,
52396 return mouse(context.container().node());
52400 function keydown() {
52402 if (e && e.shiftKey) {
52404 .classed('behavior-multiselect', true);
52407 if (e && e.keyCode === 93) { // context menu
52408 e.preventDefault();
52409 e.stopPropagation();
52416 if (!e || !e.shiftKey) {
52418 .classed('behavior-multiselect', false);
52422 if (e && e.keyCode === 93) { // context menu
52423 e.preventDefault();
52424 e.stopPropagation();
52430 function mousedown() {
52431 if (!p1) p1 = point();
52433 .on('mouseup.select', mouseup, true);
52435 var isShowAlways = +context.storage('edit-menu-show-always') === 1;
52436 suppressMenu = !isShowAlways;
52440 function mousemove() {
52441 if (event) lastMouse = event;
52445 function mouseup() {
52450 function contextmenu() {
52452 e.preventDefault();
52453 e.stopPropagation();
52455 if (!+e.clientX && !+e.clientY) {
52457 e.sourceEvent = lastMouse;
52463 if (!p1) p1 = point();
52464 suppressMenu = false;
52471 .on('mouseup.select', null, true);
52475 dist = geoEuclideanDistance(p1, p2);
52478 if (dist > tolerance) {
52482 var isMultiselect = event.shiftKey || select('#surface .lasso').node(),
52483 isShowAlways = +context.storage('edit-menu-show-always') === 1,
52484 datum = event.target.__data__ || (lastMouse && lastMouse.target.__data__),
52485 mode = context.mode();
52488 if (datum && datum.type === 'midpoint') {
52489 datum = datum.parents[0];
52492 if (!(datum instanceof osmEntity$$1)) {
52493 // clicked nothing..
52494 if (!isMultiselect && mode.id !== 'browse') {
52495 context.enter(modeBrowse(context));
52499 // clicked an entity..
52500 var selectedIDs = context.selectedIDs();
52502 if (!isMultiselect) {
52503 if (selectedIDs.length > 1 && (!suppressMenu && !isShowAlways)) {
52504 // multiple things already selected, just show the menu...
52505 mode.suppressMenu(false).reselect();
52507 // select a single thing..
52508 context.enter(modeSelect(context, [datum.id]).suppressMenu(suppressMenu));
52512 if (selectedIDs.indexOf(datum.id) !== -1) {
52513 // clicked entity is already in the selectedIDs list..
52514 if (!suppressMenu && !isShowAlways) {
52515 // don't deselect clicked entity, just show the menu.
52516 mode.suppressMenu(false).reselect();
52518 // deselect clicked entity, then reenter select mode or return to browse mode..
52519 selectedIDs = lodash.without(selectedIDs, datum.id);
52520 context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse(context));
52523 // clicked entity is not in the selected list, add it..
52524 selectedIDs = selectedIDs.concat([datum.id]);
52525 context.enter(modeSelect(context, selectedIDs).suppressMenu(suppressMenu));
52530 // reset for next time..
52531 suppressMenu = true;
52535 var behavior = function(selection$$1) {
52537 suppressMenu = true;
52541 .on('keydown.select', keydown)
52542 .on('keyup.select', keyup)
52543 .on('contextmenu.select-window', function() {
52544 // Edge and IE really like to show the contextmenu on the
52545 // menubar when user presses a keyboard menu button
52546 // even after we've already preventdefaulted the key event.
52548 if (+e.clientX === 0 && +e.clientY === 0) {
52549 event.preventDefault();
52550 event.stopPropagation();
52555 .on('mousedown.select', mousedown)
52556 .on('mousemove.select', mousemove)
52557 .on('contextmenu.select', contextmenu);
52559 if (event && event.shiftKey) {
52561 .classed('behavior-multiselect', true);
52566 behavior.off = function(selection$$1) {
52568 .on('keydown.select', null)
52569 .on('keyup.select', null)
52570 .on('contextmenu.select-window', null)
52571 .on('mouseup.select', null, true);
52574 .on('mousedown.select', null)
52575 .on('mousemove.select', null)
52576 .on('contextmenu.select', null);
52579 .classed('behavior-multiselect', false);
52586 function modeAddArea$$1(context) {
52590 title: t('modes.add_area.title'),
52591 description: t('modes.add_area.description'),
52595 var behavior = behaviorAddWay(context)
52596 .tail(t('modes.add_area.tail'))
52597 .on('start', start)
52598 .on('startFromWay', startFromWay)
52599 .on('startFromNode', startFromNode),
52600 defaultTags = { area: 'yes' };
52603 function actionClose(wayId) {
52604 return function (graph) {
52605 return graph.replace(graph.entity(wayId).close());
52610 function start(loc) {
52611 var startGraph = context.graph(),
52612 node = osmNode({ loc: loc }),
52613 way = osmWay({ tags: defaultTags });
52616 actionAddEntity(node),
52617 actionAddEntity(way),
52618 actionAddVertex(way.id, node.id),
52619 actionClose(way.id)
52622 context.enter(modeDrawArea(context, way.id, startGraph));
52626 function startFromWay(loc, edge) {
52627 var startGraph = context.graph(),
52628 node = osmNode({ loc: loc }),
52629 way = osmWay({ tags: defaultTags });
52632 actionAddEntity(node),
52633 actionAddEntity(way),
52634 actionAddVertex(way.id, node.id),
52635 actionClose(way.id),
52636 actionAddMidpoint({ loc: loc, edge: edge }, node)
52639 context.enter(modeDrawArea(context, way.id, startGraph));
52643 function startFromNode(node) {
52644 var startGraph = context.graph(),
52645 way = osmWay({ tags: defaultTags });
52648 actionAddEntity(way),
52649 actionAddVertex(way.id, node.id),
52650 actionClose(way.id)
52653 context.enter(modeDrawArea(context, way.id, startGraph));
52657 mode.enter = function() {
52658 context.install(behavior);
52662 mode.exit = function() {
52663 context.uninstall(behavior);
52670 function modeAddLine$$1(context) {
52674 title: t('modes.add_line.title'),
52675 description: t('modes.add_line.description'),
52679 var behavior = behaviorAddWay(context)
52680 .tail(t('modes.add_line.tail'))
52681 .on('start', start)
52682 .on('startFromWay', startFromWay)
52683 .on('startFromNode', startFromNode);
52686 function start(loc) {
52687 var startGraph = context.graph(),
52688 node = osmNode({ loc: loc }),
52692 actionAddEntity(node),
52693 actionAddEntity(way),
52694 actionAddVertex(way.id, node.id)
52697 context.enter(modeDrawLine(context, way.id, startGraph));
52701 function startFromWay(loc, edge) {
52702 var startGraph = context.graph(),
52703 node = osmNode({ loc: loc }),
52707 actionAddEntity(node),
52708 actionAddEntity(way),
52709 actionAddVertex(way.id, node.id),
52710 actionAddMidpoint({ loc: loc, edge: edge }, node)
52713 context.enter(modeDrawLine(context, way.id, startGraph));
52717 function startFromNode(node) {
52718 var startGraph = context.graph(),
52722 actionAddEntity(way),
52723 actionAddVertex(way.id, node.id)
52726 context.enter(modeDrawLine(context, way.id, startGraph));
52730 mode.enter = function() {
52731 context.install(behavior);
52735 mode.exit = function() {
52736 context.uninstall(behavior);
52742 function modeAddPoint$$1(context) {
52746 title: t('modes.add_point.title'),
52747 description: t('modes.add_point.description'),
52751 var behavior = behaviorDraw(context)
52752 .tail(t('modes.add_point.tail'))
52754 .on('clickWay', addWay)
52755 .on('clickNode', addNode)
52756 .on('cancel', cancel)
52757 .on('finish', cancel);
52760 function add(loc) {
52761 var node = osmNode({ loc: loc });
52764 actionAddEntity(node),
52765 t('operations.add.annotation.point')
52769 modeSelect(context, [node.id]).newFeature(true)
52774 function addWay(loc) {
52779 function addNode(node) {
52784 function cancel() {
52785 context.enter(modeBrowse(context));
52789 mode.enter = function() {
52790 context.install(behavior);
52794 mode.exit = function() {
52795 context.uninstall(behavior);
52802 function modeDragNode$$1(context) {
52814 hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
52815 edit = behaviorEdit(context);
52818 function vecSub(a, b) {
52819 return [a[0] - b[0], a[1] - b[1]];
52822 function edge(point, size) {
52823 var pad = [80, 20, 50, 20], // top, right, bottom, left
52827 if (point[0] > size[0] - pad[1])
52829 if (point[0] < pad[3])
52831 if (point[1] > size[1] - pad[2])
52833 if (point[1] < pad[0])
52844 function startNudge(entity, nudge) {
52845 if (nudgeInterval) window.clearInterval(nudgeInterval);
52846 nudgeInterval = window.setInterval(function() {
52847 context.pan(nudge);
52848 doMove(entity, nudge);
52853 function stopNudge() {
52854 if (nudgeInterval) {
52855 window.clearInterval(nudgeInterval);
52856 nudgeInterval = null;
52861 function moveAnnotation(entity) {
52862 return t('operations.move.annotation.' + entity.geometry(context.graph()));
52866 function connectAnnotation(entity) {
52867 return t('operations.connect.annotation.' + entity.geometry(context.graph()));
52871 function origin(entity) {
52872 return context.projection(entity.loc);
52876 function start(entity) {
52877 wasMidpoint = entity.type === 'midpoint';
52879 isCancelled = event.sourceEvent.shiftKey ||
52880 context.features().hasHiddenConnections(entity, context.graph());
52883 return behavior.cancel();
52887 var midpoint = entity;
52888 entity = osmNode();
52889 context.perform(actionAddMidpoint(midpoint, entity));
52891 var vertex = context.surface().selectAll('.' + entity.id);
52892 behavior.target(vertex.node(), entity);
52895 context.perform(actionNoop());
52898 // activeIDs generate no pointer events. This prevents the node or vertex
52899 // being dragged from trying to connect to itself or its parent element.
52900 activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
52901 activeIDs.push(entity.id);
52902 setActiveElements();
52904 context.enter(mode);
52909 var event$$1 = event && event.sourceEvent;
52910 if (!event$$1 || event$$1.altKey) {
52913 return event$$1.target.__data__ || {};
52918 function doMove(entity, nudge) {
52919 nudge = nudge || [0, 0];
52921 var currPoint = (event && event.point) || context.projection(lastLoc),
52922 currMouse = vecSub(currPoint, nudge),
52923 loc = context.projection.invert(currMouse),
52926 if (!nudgeInterval) {
52927 if (d.type === 'node' && d.id !== entity.id) {
52929 } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
52930 loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
52935 actionMoveNode(entity.id, loc),
52936 moveAnnotation(entity)
52943 function move(entity) {
52944 if (isCancelled) return;
52945 event.sourceEvent.stopPropagation();
52946 lastLoc = context.projection.invert(event.point);
52949 var nudge = edge(event.point, context.map().dimensions());
52951 startNudge(entity, nudge);
52958 function end(entity) {
52959 if (isCancelled) return;
52963 if (d.type === 'way') {
52964 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
52966 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
52967 connectAnnotation(d)
52970 } else if (d.type === 'node' && d.id !== entity.id) {
52972 actionConnect([d.id, entity.id]),
52973 connectAnnotation(d)
52976 } else if (wasMidpoint) {
52979 t('operations.add.annotation.vertex')
52985 moveAnnotation(entity)
52989 var reselection = selectedIDs.filter(function(id) {
52990 return context.graph().hasEntity(id);
52993 if (reselection.length) {
52994 context.enter(modeSelect(context, reselection));
52996 context.enter(modeBrowse(context));
53001 function cancel() {
53003 context.enter(modeBrowse(context));
53007 function setActiveElements() {
53008 context.surface().selectAll(utilEntitySelector(activeIDs))
53009 .classed('active', true);
53013 var behavior = behaviorDrag()
53014 .selector('g.node, g.point, g.midpoint')
53015 .surface(select('#map').node())
53017 .on('start', start)
53022 mode.enter = function() {
53023 context.install(hover);
53024 context.install(edit);
53027 .on('undone.drag-node', cancel);
53030 .on('drawn.drag-node', setActiveElements);
53032 setActiveElements();
53036 mode.exit = function() {
53037 context.ui().sidebar.hover.cancel();
53038 context.uninstall(hover);
53039 context.uninstall(edit);
53042 .on('undone.drag-node', null);
53045 .on('drawn.drag-node', null);
53048 .selectAll('.active')
53049 .classed('active', false);
53055 mode.selectedIDs = function(_) {
53056 if (!arguments.length) return selectedIDs;
53062 mode.behavior = behavior;
53068 function modeBrowse(context) {
53072 title: t('modes.browse.title'),
53073 description: t('modes.browse.description')
53077 behaviorPaste(context),
53078 behaviorHover(context).on('hover', context.ui().sidebar.hover),
53079 behaviorSelect(context),
53080 behaviorLasso(context),
53081 modeDragNode$$1(context).behavior
53085 mode.enter = function() {
53086 behaviors.forEach(function(behavior) {
53087 context.install(behavior);
53090 // Get focus on the body.
53091 if (document.activeElement && document.activeElement.blur) {
53092 document.activeElement.blur();
53096 context.ui().sidebar.show(sidebar);
53098 context.ui().sidebar.select(null);
53103 mode.exit = function() {
53104 context.ui().sidebar.hover.cancel();
53105 behaviors.forEach(function(behavior) {
53106 context.uninstall(behavior);
53110 context.ui().sidebar.hide();
53115 mode.sidebar = function(_) {
53116 if (!arguments.length) return sidebar;
53125 function modeDrawArea(context, wayId, startGraph) {
53134 mode.enter = function() {
53135 var way = context.entity(wayId);
53137 behavior = behaviorDrawWay(context, wayId, undefined, mode, startGraph)
53138 .tail(t('modes.draw_area.tail'));
53140 var addNode = behavior.addNode;
53142 behavior.addNode = function(node) {
53143 var length = way.nodes.length,
53144 penultimate = length > 2 ? way.nodes[length - 2] : null;
53146 if (node.id === way.first() || node.id === penultimate) {
53153 context.install(behavior);
53157 mode.exit = function() {
53158 context.uninstall(behavior);
53162 mode.selectedIDs = function() {
53170 function modeDrawLine(context, wayId, startGraph, affix) {
53179 mode.enter = function() {
53180 var way = context.entity(wayId),
53181 index = (affix === 'prefix') ? 0 : undefined,
53182 headId = (affix === 'prefix') ? way.first() : way.last();
53184 behavior = behaviorDrawWay(context, wayId, index, mode, startGraph)
53185 .tail(t('modes.draw_line.tail'));
53187 var addNode = behavior.addNode;
53189 behavior.addNode = function(node) {
53190 if (node.id === headId) {
53197 context.install(behavior);
53201 mode.exit = function() {
53202 context.uninstall(behavior);
53206 mode.selectedIDs = function() {
53214 function operationCircularize(selectedIDs, context) {
53215 var entityId = selectedIDs[0],
53216 entity = context.entity(entityId),
53217 extent = entity.extent(context.graph()),
53218 geometry = context.geometry(entityId),
53219 action = actionCircularize(entityId, context.projection);
53222 var operation = function() {
53223 context.perform(action, operation.annotation());
53227 operation.available = function() {
53228 return selectedIDs.length === 1 &&
53229 entity.type === 'way' &&
53230 lodash.uniq(entity.nodes).length > 1;
53234 operation.disabled = function() {
53236 if (extent.percentContainedIn(context.extent()) < 0.8) {
53237 reason = 'too_large';
53238 } else if (context.hasHiddenConnections(entityId)) {
53239 reason = 'connected_to_hidden';
53241 return action.disabled(context.graph()) || reason;
53245 operation.tooltip = function() {
53246 var disable = operation.disabled();
53248 t('operations.circularize.' + disable) :
53249 t('operations.circularize.description.' + geometry);
53253 operation.annotation = function() {
53254 return t('operations.circularize.annotation.' + geometry);
53258 operation.id = 'circularize';
53259 operation.keys = [t('operations.circularize.key')];
53260 operation.title = t('operations.circularize.title');
53261 operation.behavior = behaviorOperation(context).which(operation);
53266 function operationContinue(selectedIDs, context) {
53267 var graph = context.graph(),
53268 entities = selectedIDs.map(function(id) { return graph.entity(id); }),
53269 geometries = lodash.extend({ line: [], vertex: [] },
53270 lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
53271 vertex = geometries.vertex[0];
53274 function candidateWays() {
53275 return graph.parentWays(vertex).filter(function(parent) {
53276 return parent.geometry(graph) === 'line' &&
53277 !parent.isClosed() &&
53278 parent.affix(vertex.id) &&
53279 (geometries.line.length === 0 || geometries.line[0] === parent);
53284 var operation = function() {
53285 var candidate = candidateWays()[0];
53287 modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
53292 operation.available = function() {
53293 return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
53294 !context.features().hasHiddenConnections(vertex, context.graph());
53298 operation.disabled = function() {
53299 var candidates = candidateWays();
53300 if (candidates.length === 0)
53301 return 'not_eligible';
53302 if (candidates.length > 1)
53307 operation.tooltip = function() {
53308 var disable = operation.disabled();
53310 t('operations.continue.' + disable) :
53311 t('operations.continue.description');
53315 operation.annotation = function() {
53316 return t('operations.continue.annotation.line');
53320 operation.id = 'continue';
53321 operation.keys = [t('operations.continue.key')];
53322 operation.title = t('operations.continue.title');
53323 operation.behavior = behaviorOperation(context).which(operation);
53328 function operationDelete(selectedIDs, context) {
53329 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
53330 action = actionDeleteMultiple(selectedIDs),
53331 extent = selectedIDs.reduce(function(extent, id) {
53332 return extent.extend(context.entity(id).extent(context.graph()));
53333 }, geoExtent$$1());
53336 var operation = function() {
53337 var nextSelectedID;
53339 if (selectedIDs.length === 1) {
53340 var id = selectedIDs[0],
53341 entity = context.entity(id),
53342 geometry = context.geometry(id),
53343 parents = context.graph().parentWays(entity),
53344 parent = parents[0];
53346 // Select the next closest node in the way.
53347 if (geometry === 'vertex' && parent.nodes.length > 2) {
53348 var nodes = parent.nodes,
53349 i = nodes.indexOf(id);
53353 } else if (i === nodes.length - 1) {
53356 var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
53357 b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
53358 i = a < b ? i - 1 : i + 1;
53361 nextSelectedID = nodes[i];
53365 context.perform(action, operation.annotation());
53367 if (nextSelectedID && context.hasEntity(nextSelectedID)) {
53368 context.enter(modeSelect(context, [nextSelectedID]).follow(true));
53370 context.enter(modeBrowse(context));
53376 operation.available = function() {
53381 operation.disabled = function() {
53383 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
53384 reason = 'too_large';
53385 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
53386 reason = 'connected_to_hidden';
53387 } else if (lodash.some(selectedIDs, protectedMember)) {
53388 reason = 'part_of_relation';
53389 } else if (lodash.some(selectedIDs, incompleteRelation)) {
53390 reason = 'incomplete_relation';
53394 function incompleteRelation(id) {
53395 var entity = context.entity(id);
53396 return entity.type === 'relation' && !entity.isComplete(context.graph());
53399 function protectedMember(id) {
53400 var entity = context.entity(id);
53401 if (entity.type !== 'way') return false;
53403 var parents = context.graph().parentRelations(entity);
53404 for (var i = 0; i < parents.length; i++) {
53405 var parent = parents[i],
53406 type = parent.tags.type,
53407 role = parent.memberById(id).role || 'outer';
53408 if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
53418 operation.tooltip = function() {
53419 var disable = operation.disabled();
53421 t('operations.delete.' + disable + '.' + multi) :
53422 t('operations.delete.description' + '.' + multi);
53426 operation.annotation = function() {
53427 return selectedIDs.length === 1 ?
53428 t('operations.delete.annotation.' + context.geometry(selectedIDs[0])) :
53429 t('operations.delete.annotation.multiple', { n: selectedIDs.length });
53433 operation.id = 'delete';
53434 operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
53435 operation.title = t('operations.delete.title');
53436 operation.behavior = behaviorOperation(context).which(operation);
53441 function operationDisconnect(selectedIDs, context) {
53442 var vertices = lodash.filter(selectedIDs, function(entityId) {
53443 return context.geometry(entityId) === 'vertex';
53446 var entityId = vertices[0],
53447 action = actionDisconnect(entityId);
53449 if (selectedIDs.length > 1) {
53450 action.limitWays(lodash.without(selectedIDs, entityId));
53454 var operation = function() {
53455 context.perform(action, operation.annotation());
53459 operation.available = function() {
53460 return vertices.length === 1;
53464 operation.disabled = function() {
53466 if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
53467 reason = 'connected_to_hidden';
53469 return action.disabled(context.graph()) || reason;
53473 operation.tooltip = function() {
53474 var disable = operation.disabled();
53476 t('operations.disconnect.' + disable) :
53477 t('operations.disconnect.description');
53481 operation.annotation = function() {
53482 return t('operations.disconnect.annotation');
53486 operation.id = 'disconnect';
53487 operation.keys = [t('operations.disconnect.key')];
53488 operation.title = t('operations.disconnect.title');
53489 operation.behavior = behaviorOperation(context).which(operation);
53494 function operationMerge(selectedIDs, context) {
53496 function updatePresetTags(newGraph, ids) {
53498 newEntity = newGraph.hasEntity(id);
53500 if (!newEntity) return;
53502 var newPreset = context.presets().match(newEntity, newGraph);
53504 context.replace(actionChangePreset(id, null, newPreset), operation.annotation());
53508 var join = actionJoin(selectedIDs),
53509 merge = actionMerge(selectedIDs),
53510 mergePolygon = actionMergePolygon(selectedIDs);
53513 var operation = function() {
53514 var origGraph = context.graph(),
53517 if (!join.disabled(origGraph)) {
53519 } else if (!merge.disabled(origGraph)) {
53522 action = mergePolygon;
53525 context.perform(action, operation.annotation());
53527 var ids = selectedIDs.filter(function(id) {
53528 var entity = context.hasEntity(id);
53529 return entity && entity.type !== 'node';
53532 // if we merged tags, rematch preset to update tags if necessary (#3851)
53533 if (action === merge) {
53534 updatePresetTags(context.graph(), ids);
53537 context.enter(modeSelect(context, ids));
53541 operation.available = function() {
53542 return selectedIDs.length >= 2;
53546 operation.disabled = function() {
53547 return join.disabled(context.graph()) &&
53548 merge.disabled(context.graph()) &&
53549 mergePolygon.disabled(context.graph());
53553 operation.tooltip = function() {
53554 var j = join.disabled(context.graph()),
53555 m = merge.disabled(context.graph()),
53556 p = mergePolygon.disabled(context.graph());
53558 if (j === 'restriction' && m && p) {
53559 return t('operations.merge.restriction',
53560 { relation: context.presets().item('type/restriction').name() });
53563 if (p === 'incomplete_relation' && j && m) {
53564 return t('operations.merge.incomplete_relation');
53568 return t('operations.merge.' + j);
53571 return t('operations.merge.description');
53575 operation.annotation = function() {
53576 return t('operations.merge.annotation', { n: selectedIDs.length });
53580 operation.id = 'merge';
53581 operation.keys = [t('operations.merge.key')];
53582 operation.title = t('operations.merge.title');
53583 operation.behavior = behaviorOperation(context).which(operation);
53588 function operationMove(selectedIDs, context) {
53589 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
53590 extent = selectedIDs.reduce(function(extent, id) {
53591 return extent.extend(context.entity(id).extent(context.graph()));
53592 }, geoExtent$$1());
53595 var operation = function() {
53596 context.enter(modeMove$$1(context, selectedIDs));
53600 operation.available = function() {
53601 return selectedIDs.length > 1 ||
53602 context.entity(selectedIDs[0]).type !== 'node';
53606 operation.disabled = function() {
53608 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
53609 reason = 'too_large';
53610 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
53611 reason = 'connected_to_hidden';
53612 } else if (lodash.some(selectedIDs, incompleteRelation)) {
53613 reason = 'incomplete_relation';
53617 function incompleteRelation(id) {
53618 var entity = context.entity(id);
53619 return entity.type === 'relation' && !entity.isComplete(context.graph());
53624 operation.tooltip = function() {
53625 var disable = operation.disabled();
53627 t('operations.move.' + disable + '.' + multi) :
53628 t('operations.move.description.' + multi);
53632 operation.annotation = function() {
53633 return selectedIDs.length === 1 ?
53634 t('operations.move.annotation.' + context.geometry(selectedIDs[0])) :
53635 t('operations.move.annotation.multiple');
53639 operation.id = 'move';
53640 operation.keys = [t('operations.move.key')];
53641 operation.title = t('operations.move.title');
53642 operation.behavior = behaviorOperation(context).which(operation);
53647 function operationOrthogonalize(selectedIDs, context) {
53648 var entityId = selectedIDs[0],
53649 entity = context.entity(entityId),
53650 extent = entity.extent(context.graph()),
53651 geometry = context.geometry(entityId),
53652 action = actionOrthogonalize(entityId, context.projection);
53655 var operation = function() {
53656 context.perform(action, operation.annotation());
53660 operation.available = function() {
53661 return selectedIDs.length === 1 &&
53662 entity.type === 'way' &&
53663 entity.isClosed() &&
53664 lodash.uniq(entity.nodes).length > 2;
53668 operation.disabled = function() {
53670 if (extent.percentContainedIn(context.extent()) < 0.8) {
53671 reason = 'too_large';
53672 } else if (context.hasHiddenConnections(entityId)) {
53673 reason = 'connected_to_hidden';
53675 return action.disabled(context.graph()) || reason;
53679 operation.tooltip = function() {
53680 var disable = operation.disabled();
53682 t('operations.orthogonalize.' + disable) :
53683 t('operations.orthogonalize.description.' + geometry);
53687 operation.annotation = function() {
53688 return t('operations.orthogonalize.annotation.' + geometry);
53692 operation.id = 'orthogonalize';
53693 operation.keys = [t('operations.orthogonalize.key')];
53694 operation.title = t('operations.orthogonalize.title');
53695 operation.behavior = behaviorOperation(context).which(operation);
53700 function operationReflectShort(selectedIDs, context) {
53701 return operationReflect(selectedIDs, context, 'short');
53705 function operationReflectLong(selectedIDs, context) {
53706 return operationReflect(selectedIDs, context, 'long');
53710 function operationReflect(selectedIDs, context, axis) {
53711 axis = axis || 'long';
53712 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
53713 extent = selectedIDs.reduce(function(extent, id) {
53714 return extent.extend(context.entity(id).extent(context.graph()));
53715 }, geoExtent$$1());
53718 var operation = function() {
53719 var action = actionReflect(selectedIDs, context.projection)
53720 .useLongAxis(Boolean(axis === 'long'));
53721 context.perform(action, operation.annotation());
53725 operation.available = function() {
53726 return lodash.some(selectedIDs, hasArea);
53728 function hasArea(id) {
53729 var entity = context.entity(id);
53730 return (entity.type === 'way' && entity.isClosed()) ||
53731 (entity.type ==='relation' && entity.isMultipolygon());
53736 operation.disabled = function() {
53738 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
53739 reason = 'too_large';
53740 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
53741 reason = 'connected_to_hidden';
53742 } else if (lodash.some(selectedIDs, incompleteRelation)) {
53743 reason = 'incomplete_relation';
53747 function incompleteRelation(id) {
53748 var entity = context.entity(id);
53749 return entity.type === 'relation' && !entity.isComplete(context.graph());
53754 operation.tooltip = function() {
53755 var disable = operation.disabled();
53757 t('operations.reflect.' + disable + '.' + multi) :
53758 t('operations.reflect.description.' + axis + '.' + multi);
53762 operation.annotation = function() {
53763 return t('operations.reflect.annotation.' + axis + '.' + multi);
53767 operation.id = 'reflect-' + axis;
53768 operation.keys = [t('operations.reflect.key.' + axis)];
53769 operation.title = t('operations.reflect.title.' + axis);
53770 operation.behavior = behaviorOperation(context).which(operation);
53775 function operationReverse(selectedIDs, context) {
53776 var entityId = selectedIDs[0];
53778 var operation = function() {
53779 context.perform(actionReverse(entityId), operation.annotation());
53783 operation.available = function() {
53784 return selectedIDs.length === 1 && context.geometry(entityId) === 'line';
53788 operation.disabled = function() {
53793 operation.tooltip = function() {
53794 return t('operations.reverse.description');
53798 operation.annotation = function() {
53799 return t('operations.reverse.annotation');
53803 operation.id = 'reverse';
53804 operation.keys = [t('operations.reverse.key')];
53805 operation.title = t('operations.reverse.title');
53806 operation.behavior = behaviorOperation(context).which(operation);
53811 function operationRotate(selectedIDs, context) {
53812 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
53813 extent = selectedIDs.reduce(function(extent, id) {
53814 return extent.extend(context.entity(id).extent(context.graph()));
53815 }, geoExtent$$1());
53818 var operation = function() {
53819 context.enter(modeRotate$$1(context, selectedIDs));
53823 operation.available = function() {
53824 return lodash.some(selectedIDs, hasArea);
53826 function hasArea(id) {
53827 var entity = context.entity(id);
53828 return (entity.type === 'way' && entity.isClosed()) ||
53829 (entity.type ==='relation' && entity.isMultipolygon());
53834 operation.disabled = function() {
53836 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
53837 reason = 'too_large';
53838 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
53839 reason = 'connected_to_hidden';
53840 } else if (lodash.some(selectedIDs, incompleteRelation)) {
53841 reason = 'incomplete_relation';
53845 function incompleteRelation(id) {
53846 var entity = context.entity(id);
53847 return entity.type === 'relation' && !entity.isComplete(context.graph());
53852 operation.tooltip = function() {
53853 var disable = operation.disabled();
53855 t('operations.rotate.' + disable + '.' + multi) :
53856 t('operations.rotate.description.' + multi);
53860 operation.annotation = function() {
53861 return selectedIDs.length === 1 ?
53862 t('operations.rotate.annotation.' + context.geometry(selectedIDs[0])) :
53863 t('operations.rotate.annotation.multiple');
53867 operation.id = 'rotate';
53868 operation.keys = [t('operations.rotate.key')];
53869 operation.title = t('operations.rotate.title');
53870 operation.behavior = behaviorOperation(context).which(operation);
53875 function operationSplit(selectedIDs, context) {
53876 var vertices = lodash.filter(selectedIDs, function(entityId) {
53877 return context.geometry(entityId) === 'vertex';
53880 var entityId = vertices[0],
53881 action = actionSplit(entityId),
53884 if (vertices.length === 1) {
53885 if (selectedIDs.length > 1) {
53886 action.limitWays(lodash.without(selectedIDs, entityId));
53888 ways = action.ways(context.graph());
53892 var operation = function() {
53893 var difference = context.perform(action, operation.annotation());
53894 context.enter(modeSelect(context, difference.extantIDs()));
53898 operation.available = function() {
53899 return vertices.length === 1;
53903 operation.disabled = function() {
53905 if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
53906 reason = 'connected_to_hidden';
53908 return action.disabled(context.graph()) || reason;
53912 operation.tooltip = function() {
53913 var disable = operation.disabled();
53915 return t('operations.split.' + disable);
53917 if (ways.length === 1) {
53918 return t('operations.split.description.' + context.geometry(ways[0].id));
53920 return t('operations.split.description.multiple');
53925 operation.annotation = function() {
53926 return ways.length === 1 ?
53927 t('operations.split.annotation.' + context.geometry(ways[0].id)) :
53928 t('operations.split.annotation.multiple', { n: ways.length });
53932 operation.id = 'split';
53933 operation.keys = [t('operations.split.key')];
53934 operation.title = t('operations.split.title');
53935 operation.behavior = behaviorOperation(context).which(operation);
53940 function operationStraighten(selectedIDs, context) {
53941 var entityId = selectedIDs[0],
53942 action = actionStraighten(entityId, context.projection);
53945 function operation() {
53946 context.perform(action, operation.annotation());
53950 operation.available = function() {
53951 var entity = context.entity(entityId);
53952 return selectedIDs.length === 1 &&
53953 entity.type === 'way' &&
53954 !entity.isClosed() &&
53955 lodash.uniq(entity.nodes).length > 2;
53959 operation.disabled = function() {
53961 if (context.hasHiddenConnections(entityId)) {
53962 reason = 'connected_to_hidden';
53964 return action.disabled(context.graph()) || reason;
53968 operation.tooltip = function() {
53969 var disable = operation.disabled();
53971 t('operations.straighten.' + disable) :
53972 t('operations.straighten.description');
53976 operation.annotation = function() {
53977 return t('operations.straighten.annotation');
53981 operation.id = 'straighten';
53982 operation.keys = [t('operations.straighten.key')];
53983 operation.title = t('operations.straighten.title');
53984 operation.behavior = behaviorOperation(context).which(operation);
53991 var Operations = Object.freeze({
53992 operationCircularize: operationCircularize,
53993 operationContinue: operationContinue,
53994 operationDelete: operationDelete,
53995 operationDisconnect: operationDisconnect,
53996 operationMerge: operationMerge,
53997 operationMove: operationMove,
53998 operationOrthogonalize: operationOrthogonalize,
53999 operationReflectShort: operationReflectShort,
54000 operationReflectLong: operationReflectLong,
54001 operationReverse: operationReverse,
54002 operationRotate: operationRotate,
54003 operationSplit: operationSplit,
54004 operationStraighten: operationStraighten
54007 function modeMove$$1(context, entityIDs, baseGraph) {
54013 var keybinding = d3keybinding('move'),
54015 behaviorEdit(context),
54016 operationCircularize(entityIDs, context).behavior,
54017 operationDelete(entityIDs, context).behavior,
54018 operationOrthogonalize(entityIDs, context).behavior,
54019 operationReflectLong(entityIDs, context).behavior,
54020 operationReflectShort(entityIDs, context).behavior,
54021 operationRotate(entityIDs, context).behavior
54023 annotation = entityIDs.length === 1 ?
54024 t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
54025 t('operations.move.annotation.multiple'),
54032 function vecSub(a, b) {
54033 return [a[0] - b[0], a[1] - b[1]];
54037 function edge(point, size) {
54038 var pad = [80, 20, 50, 20], // top, right, bottom, left
54042 if (point[0] > size[0] - pad[1])
54044 if (point[0] < pad[3])
54046 if (point[1] > size[1] - pad[2])
54048 if (point[1] < pad[0])
54059 function doMove(nudge) {
54060 nudge = nudge || [0, 0];
54063 if (prevGraph !== context.graph()) {
54065 origin = context.map().mouseCoordinates();
54066 fn = context.perform;
54068 fn = context.overwrite;
54071 var currMouse = context.mouse(),
54072 origMouse = context.projection(origin),
54073 delta = vecSub(vecSub(currMouse, origMouse), nudge);
54075 fn(actionMove(entityIDs, delta, context.projection, cache), annotation);
54076 prevGraph = context.graph();
54080 function startNudge(nudge) {
54081 if (nudgeInterval) window.clearInterval(nudgeInterval);
54082 nudgeInterval = window.setInterval(function() {
54083 context.pan(nudge);
54089 function stopNudge() {
54090 if (nudgeInterval) {
54091 window.clearInterval(nudgeInterval);
54092 nudgeInterval = null;
54099 var nudge = edge(context.mouse(), context.map().dimensions());
54108 function finish() {
54109 event.stopPropagation();
54110 context.enter(modeSelect(context, entityIDs));
54115 function cancel() {
54117 while (context.graph() !== baseGraph) context.pop();
54118 context.enter(modeBrowse(context));
54121 context.enter(modeSelect(context, entityIDs));
54127 function undone() {
54128 context.enter(modeBrowse(context));
54132 mode.enter = function() {
54133 origin = context.map().mouseCoordinates();
54137 behaviors.forEach(function(behavior) {
54138 context.install(behavior);
54142 .on('mousemove.move', move)
54143 .on('click.move', finish);
54146 .on('undone.move', undone);
54157 mode.exit = function() {
54160 behaviors.forEach(function(behavior) {
54161 context.uninstall(behavior);
54165 .on('mousemove.move', null)
54166 .on('click.move', null);
54169 .on('undone.move', null);
54178 function modeRotate$$1(context, entityIDs) {
54184 var keybinding = d3keybinding('rotate'),
54186 behaviorEdit(context),
54187 operationCircularize(entityIDs, context).behavior,
54188 operationDelete(entityIDs, context).behavior,
54189 operationMove(entityIDs, context).behavior,
54190 operationOrthogonalize(entityIDs, context).behavior,
54191 operationReflectLong(entityIDs, context).behavior,
54192 operationReflectShort(entityIDs, context).behavior
54194 annotation = entityIDs.length === 1 ?
54195 t('operations.rotate.annotation.' + context.geometry(entityIDs[0])) :
54196 t('operations.rotate.annotation.multiple'),
54203 function doRotate() {
54205 if (context.graph() !== prevGraph) {
54206 fn = context.perform;
54208 fn = context.replace;
54211 // projection changed, recalculate pivot
54212 var projection$$1 = context.projection;
54213 var currTransform = projection$$1.transform();
54214 if (!prevTransform ||
54215 currTransform.k !== prevTransform.k ||
54216 currTransform.x !== prevTransform.x ||
54217 currTransform.y !== prevTransform.y) {
54219 var nodes = utilGetAllNodes(entityIDs, context.graph()),
54220 points = nodes.map(function(n) { return projection$$1(n.loc); });
54222 pivot = d3polygonCentroid(d3polygonHull(points));
54223 prevAngle = undefined;
54227 var currMouse = context.mouse(),
54228 currAngle = Math.atan2(currMouse[1] - pivot[1], currMouse[0] - pivot[0]);
54230 if (typeof prevAngle === 'undefined') prevAngle = currAngle;
54231 var delta = currAngle - prevAngle;
54233 fn(actionRotate(entityIDs, pivot, delta, projection$$1), annotation);
54235 prevTransform = currTransform;
54236 prevAngle = currAngle;
54237 prevGraph = context.graph();
54241 function finish() {
54242 event.stopPropagation();
54243 context.enter(modeSelect(context, entityIDs));
54247 function cancel() {
54249 context.enter(modeSelect(context, entityIDs));
54253 function undone() {
54254 context.enter(modeBrowse(context));
54258 mode.enter = function() {
54259 behaviors.forEach(function(behavior) {
54260 context.install(behavior);
54264 .on('mousemove.rotate', doRotate)
54265 .on('click.rotate', finish);
54268 .on('undone.rotate', undone);
54279 mode.exit = function() {
54280 behaviors.forEach(function(behavior) {
54281 context.uninstall(behavior);
54285 .on('mousemove.rotate', null)
54286 .on('click.rotate', null);
54289 .on('undone.rotate', null);
54298 function modeSave$$1(context) {
54303 var commit = uiCommit(context)
54304 .on('cancel', cancel)
54308 function cancel() {
54309 context.enter(modeBrowse(context));
54313 function save(changeset, tryAgain) {
54315 var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
54316 history = context.history(),
54317 origChanges = history.changes(actionDiscardTags(history.difference())),
54318 localGraph = context.graph(),
54319 remoteGraph = coreGraph$$1(history.base(), true),
54320 modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
54321 toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
54322 toLoad = withChildNodes(toCheck, localGraph),
54327 history.perform(actionNoop()); // checkpoint
54330 context.container().call(loading);
54332 if (toCheck.length) {
54333 context.connection().loadMultiple(toLoad, loaded);
54339 function withChildNodes(ids, graph) {
54340 return lodash.uniq(lodash.reduce(ids, function(result, id) {
54341 var entity = graph.entity(id);
54342 if (entity.type === 'way') {
54344 var cn = graph.childNodes(entity);
54345 result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
54347 /* eslint-disable no-console */
54348 if (typeof console !== 'undefined') console.error(err);
54349 /* eslint-enable no-console */
54353 }, lodash.clone(ids)));
54357 // Reload modified entities into an alternate graph and check for conflicts..
54358 function loaded(err, result) {
54359 if (errors.length) return;
54363 msg: err.responseText,
54364 details: [ t('save.status_code', { code: err.status }) ]
54370 lodash.each(result.data, function(entity) {
54371 remoteGraph.replace(entity);
54372 toLoad = lodash.without(toLoad, entity.id);
54374 // Because loadMultiple doesn't download /full like loadEntity,
54375 // need to also load children that aren't already being checked..
54376 if (!entity.visible) return;
54377 if (entity.type === 'way') {
54378 loadMore.push.apply(loadMore,
54379 lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
54380 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
54381 loadMore.push.apply(loadMore,
54382 lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
54386 if (loadMore.length) {
54387 toLoad.push.apply(toLoad, loadMore);
54388 context.connection().loadMultiple(loadMore, loaded);
54391 if (!toLoad.length) {
54398 function checkConflicts() {
54399 function choice(id, text$$1, action) {
54400 return { id: id, text: text$$1, action: function() { history.replace(action); } };
54402 function formatUser(d) {
54403 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
54405 function entityName(entity) {
54406 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
54409 function compareVersions(local, remote) {
54410 if (local.version !== remote.version) return false;
54412 if (local.type === 'way') {
54413 var children = lodash.union(local.nodes, remote.nodes);
54415 for (var i = 0; i < children.length; i++) {
54416 var a = localGraph.hasEntity(children[i]),
54417 b = remoteGraph.hasEntity(children[i]);
54419 if (a && b && a.version !== b.version) return false;
54426 lodash.each(toCheck, function(id) {
54427 var local = localGraph.entity(id),
54428 remote = remoteGraph.entity(id);
54430 if (compareVersions(local, remote)) return;
54432 var action = actionMergeRemoteChanges,
54433 merge$$1 = action(id, localGraph, remoteGraph, formatUser);
54435 history.replace(merge$$1);
54437 var mergeConflicts = merge$$1.conflicts();
54438 if (!mergeConflicts.length) return; // merged safely
54440 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
54441 forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
54442 keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
54443 keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
54447 name: entityName(local),
54448 details: mergeConflicts,
54451 choice(id, keepMine, forceLocal),
54452 choice(id, keepTheirs, forceRemote)
54461 function upload() {
54462 if (conflicts.length) {
54463 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
54465 } else if (errors.length) {
54468 var changes = history.changes(actionDiscardTags(history.difference()));
54469 if (changes.modified.length || changes.created.length || changes.deleted.length) {
54470 context.connection().putChangeset(changeset, changes, uploadCallback);
54471 } else { // changes were insignificant or reverted by user
54472 select('.inspector-wrap *').remove();
54481 function uploadCallback(err, changeset) {
54484 msg: err.responseText,
54485 details: [ t('save.status_code', { code: err.status }) ]
54489 history.clearSaved();
54490 success(changeset);
54491 // Add delay to allow for postgres replication #1646 #2678
54492 window.setTimeout(function() {
54493 select('.inspector-wrap *').remove();
54501 function showConflicts() {
54502 var selection$$1 = context.container()
54503 .select('#sidebar')
54505 .attr('class','sidebar-component');
54509 selection$$1.call(uiConflicts(context)
54511 .on('download', function() {
54512 var data = JXON.stringify(changeset.update({ id: 'CHANGEME' }).osmChangeJXON(origChanges)),
54513 win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
54516 .on('cancel', function() {
54518 selection$$1.remove();
54520 .on('save', function() {
54521 for (var i = 0; i < conflicts.length; i++) {
54522 if (conflicts[i].chosen === 1) { // user chose "keep theirs"
54523 var entity = context.hasEntity(conflicts[i].id);
54524 if (entity && entity.type === 'way') {
54525 var children = lodash.uniq(entity.nodes);
54526 for (var j = 0; j < children.length; j++) {
54527 history.replace(actionRevert(children[j]));
54530 history.replace(actionRevert(conflicts[i].id));
54534 selection$$1.remove();
54535 save(changeset, true);
54541 function showErrors() {
54542 var selection$$1 = uiConfirm(context.container());
54548 .select('.modal-section.header')
54550 .text(t('save.error'));
54552 addErrors(selection$$1, errors);
54553 selection$$1.okButton();
54557 function addErrors(selection$$1, data) {
54558 var message = selection$$1
54559 .select('.modal-section.message-text');
54561 var items = message
54562 .selectAll('.error-container')
54565 var enter = items.enter()
54567 .attr('class', 'error-container');
54571 .attr('class', 'error-description')
54573 .classed('hide-toggle', true)
54574 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
54575 .on('click', function() {
54576 var error = select(this),
54577 detail = select(this.nextElementSibling),
54578 exp = error.classed('expanded');
54580 detail.style('display', exp ? 'none' : 'block');
54581 error.classed('expanded', !exp);
54583 event.preventDefault();
54586 var details = enter
54588 .attr('class', 'error-detail-container')
54589 .style('display', 'none');
54593 .attr('class', 'error-detail-list')
54595 .data(function(d) { return d.details || []; })
54598 .attr('class', 'error-detail-item')
54599 .text(function(d) { return d; });
54608 function success(changeset) {
54610 context.enter(modeBrowse(context)
54611 .sidebar(uiSuccess(context)
54612 .changeset(changeset)
54613 .on('cancel', function() {
54614 context.ui().sidebar.hide();
54621 mode.enter = function() {
54623 context.ui().sidebar.show(commit);
54626 context.container().selectAll('#content')
54627 .attr('class', 'inactive');
54629 if (context.connection().authenticated()) {
54632 context.connection().authenticate(function(err) {
54643 mode.exit = function() {
54644 context.container().selectAll('#content')
54645 .attr('class', 'active');
54647 context.ui().sidebar.hide();
54653 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
54654 // For example, ⌘Z -> Ctrl+Z
54655 var uiCmd = function (code) {
54656 var detected = utilDetect();
54658 if (detected.os === 'mac') {
54662 if (detected.os === 'win') {
54663 if (code === '⌘⇧Z') return 'Ctrl+Y';
54675 for (var i = 0; i < code.length; i++) {
54676 if (code[i] in replacements) {
54677 result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
54687 // return a display-focused string for a given keyboard code
54688 uiCmd.display = function(code) {
54689 if (code.length !== 1) return code;
54691 var detected = utilDetect();
54692 var mac = (detected.os === 'mac');
54693 var replacements = {
54694 '⌘': mac ? '⌘ ' + t('shortcuts.key.cmd') : t('shortcuts.key.ctrl'),
54695 '⇧': mac ? '⇧ ' + t('shortcuts.key.shift') : t('shortcuts.key.shift'),
54696 '⌥': mac ? '⌥ ' + t('shortcuts.key.option') : t('shortcuts.key.alt'),
54697 '⌃': mac ? '⌃ ' + t('shortcuts.key.ctrl') : t('shortcuts.key.ctrl'),
54698 '⌫': mac ? '⌫ ' + t('shortcuts.key.delete') : t('shortcuts.key.backspace'),
54699 '⌦': mac ? '⌦ ' + t('shortcuts.key.del') : t('shortcuts.key.del'),
54700 '↖': mac ? '↖ ' + t('shortcuts.key.pgup') : t('shortcuts.key.pgup'),
54701 '↘': mac ? '↘ ' + t('shortcuts.key.pgdn') : t('shortcuts.key.pgdn'),
54702 '⇞': mac ? '⇞ ' + t('shortcuts.key.home') : t('shortcuts.key.home'),
54703 '⇟': mac ? '⇟ ' + t('shortcuts.key.end') : t('shortcuts.key.end'),
54704 '↵': mac ? '↵ ' + t('shortcuts.key.return') : t('shortcuts.key.enter'),
54705 '⎋': mac ? '⎋ ' + t('shortcuts.key.esc') : t('shortcuts.key.esc'),
54708 return replacements[code] || code;
54711 // deprecation warning - Radial Menu to be removed in iD v3
54715 function modeSelect(context, selectedIDs) {
54721 var keybinding = d3keybinding('select'),
54724 behaviorCopy(context),
54725 behaviorPaste(context),
54726 behaviorBreathe(context),
54727 behaviorHover(context),
54728 behaviorSelect(context),
54729 behaviorLasso(context),
54730 modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
54734 newFeature = false,
54735 suppressMenu = true,
54739 var wrap = context.container()
54740 .select('.inspector-wrap');
54743 function singular() {
54744 if (selectedIDs.length === 1) {
54745 return context.hasEntity(selectedIDs[0]);
54750 function checkSelectedIDs() {
54752 if (Array.isArray(selectedIDs)) {
54753 ids = selectedIDs.filter(function(id) {
54754 return context.hasEntity(id);
54761 context.enter(modeBrowse(context));
54763 return !!ids.length;
54767 // find the common parent ways for nextVertex, previousVertex
54768 function commonParents() {
54769 var graph = context.graph(),
54770 commonParents = [];
54772 for (var i = 0; i < selectedIDs.length; i++) {
54773 var entity = context.hasEntity(selectedIDs[i]);
54774 if (!entity || entity.geometry(graph) !== 'vertex') {
54775 return []; // selection includes some not vertexes
54778 var currParents = lodash.map(graph.parentWays(entity), 'id');
54779 if (!commonParents.length) {
54780 commonParents = currParents;
54784 commonParents = lodash.intersection(commonParents, currParents);
54785 if (!commonParents.length) {
54790 return commonParents;
54794 function singularParent() {
54795 var parents = commonParents();
54796 if (!parents || parents.length === 0) {
54797 relatedParent = null;
54801 // relatedParent is used when we visit a vertex with multiple
54802 // parents, and we want to remember which parent line we started on.
54804 if (parents.length === 1) {
54805 relatedParent = parents[0]; // remember this parent for later
54806 return relatedParent;
54809 if (parents.indexOf(relatedParent) !== -1) {
54810 return relatedParent; // prefer the previously seen parent
54817 function closeMenu() {
54819 context.surface().call(editMenu.close);
54824 function positionMenu() {
54825 if (!editMenu) { return; }
54827 var entity = singular();
54828 if (entity && context.geometry(entity.id) === 'relation') {
54829 suppressMenu = true;
54831 var point = context.mouse(),
54832 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
54834 if (point && geoPointInPolygon(point, viewport)) {
54835 editMenu.center(point);
54837 suppressMenu = true;
54843 function showMenu() {
54846 context.surface().call(editMenu);
54851 function toggleMenu() {
54852 // deprecation warning - Radial Menu to be removed in iD v3
54853 if (select('.edit-menu, .radial-menu').empty()) {
54862 mode.selectedIDs = function() {
54863 return selectedIDs;
54867 mode.reselect = function() {
54868 if (!checkSelectedIDs()) return;
54870 var surfaceNode = context.surface().node();
54871 if (surfaceNode.focus) { // FF doesn't support it
54872 surfaceNode.focus();
54876 if (!suppressMenu) {
54882 mode.newFeature = function(_) {
54883 if (!arguments.length) return newFeature;
54889 mode.suppressMenu = function(_) {
54890 if (!arguments.length) return suppressMenu;
54896 mode.follow = function(_) {
54897 if (!arguments.length) return follow;
54903 mode.enter = function() {
54905 function update() {
54907 checkSelectedIDs();
54911 function dblclick() {
54912 var target = select(event.target),
54913 datum = target.datum();
54915 if (datum instanceof osmWay && !target.classed('fill')) {
54916 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
54917 prev = datum.nodes[choice.index - 1],
54918 next = datum.nodes[choice.index];
54921 actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, osmNode()),
54922 t('operations.add.annotation.vertex')
54925 event.preventDefault();
54926 event.stopPropagation();
54928 } else if (datum.type === 'midpoint') {
54930 actionAddMidpoint({loc: datum.loc, edge: datum.edge}, osmNode()),
54931 t('operations.add.annotation.vertex'));
54933 event.preventDefault();
54934 event.stopPropagation();
54939 function selectElements(drawn) {
54940 if (!checkSelectedIDs()) return;
54942 var surface = context.surface(),
54943 entity = singular();
54945 if (entity && context.geometry(entity.id) === 'relation') {
54946 suppressMenu = true;
54950 surface.selectAll('.related')
54951 .classed('related', false);
54954 if (relatedParent) {
54955 surface.selectAll(utilEntitySelector([relatedParent]))
54956 .classed('related', true);
54959 var selection$$1 = context.surface()
54960 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
54962 if (selection$$1.empty()) {
54963 // Return to browse mode if selected DOM elements have
54964 // disappeared because the user moved them out of view..
54965 var source = event && event.type === 'zoom' && event.sourceEvent;
54966 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
54967 context.enter(modeBrowse(context));
54971 .classed('selected', true);
54977 context.enter(modeBrowse(context));
54981 function firstVertex() {
54982 event.preventDefault();
54983 var parent = singularParent();
54985 var way = context.entity(parent);
54987 modeSelect(context, [way.first()]).follow(true)
54993 function lastVertex() {
54994 event.preventDefault();
54995 var parent = singularParent();
54997 var way = context.entity(parent);
54999 modeSelect(context, [way.last()]).follow(true)
55005 function previousVertex() {
55006 event.preventDefault();
55007 var parent = singularParent();
55008 if (!parent) return;
55010 var way = context.entity(parent),
55011 length = way.nodes.length,
55012 curr = way.nodes.indexOf(selectedIDs[0]),
55017 } else if (way.isClosed()) {
55018 index = length - 2;
55021 if (index !== -1) {
55023 modeSelect(context, [way.nodes[index]]).follow(true)
55029 function nextVertex() {
55030 event.preventDefault();
55031 var parent = singularParent();
55032 if (!parent) return;
55034 var way = context.entity(parent),
55035 length = way.nodes.length,
55036 curr = way.nodes.indexOf(selectedIDs[0]),
55039 if (curr < length - 1) {
55041 } else if (way.isClosed()) {
55045 if (index !== -1) {
55047 modeSelect(context, [way.nodes[index]]).follow(true)
55053 function nextParent() {
55054 event.preventDefault();
55055 var parents = lodash.uniq(commonParents());
55056 if (!parents || parents.length < 2) return;
55058 var index = parents.indexOf(relatedParent);
55059 if (index < 0 || index > parents.length - 2) {
55060 relatedParent = parents[0];
55062 relatedParent = parents[index + 1];
55065 var surface = context.surface();
55066 surface.selectAll('.related')
55067 .classed('related', false);
55069 if (relatedParent) {
55070 surface.selectAll(utilEntitySelector([relatedParent]))
55071 .classed('related', true);
55076 if (!checkSelectedIDs()) return;
55078 var operations = lodash.without(values(Operations), operationDelete)
55079 .map(function(o) { return o(selectedIDs, context); })
55080 .filter(function(o) { return o.available(); });
55082 // deprecation warning - Radial Menu to be removed in iD v3
55083 var isRadialMenu = context.storage('edit-menu-style') === 'radial';
55084 if (isRadialMenu) {
55085 operations = operations.slice(0,7);
55086 operations.unshift(operationDelete(selectedIDs, context));
55088 operations.push(operationDelete(selectedIDs, context));
55091 operations.forEach(function(operation) {
55092 if (operation.behavior) {
55093 behaviors.push(operation.behavior);
55097 behaviors.forEach(function(behavior) {
55098 context.install(behavior);
55102 .on(['[', 'pgup'], previousVertex)
55103 .on([']', 'pgdown'], nextVertex)
55104 .on(['{', uiCmd('⌘['), 'home'], firstVertex)
55105 .on(['}', uiCmd('⌘]'), 'end'], lastVertex)
55106 .on(['\\', 'pause'], nextParent)
55107 .on('⎋', esc, true)
55108 .on('space', toggleMenu);
55114 // deprecation warning - Radial Menu to be removed in iD v3
55115 editMenu = isRadialMenu
55116 ? uiRadialMenu(context, operations)
55117 : uiEditMenu(context, operations);
55119 context.ui().sidebar
55120 .select(singular() ? singular().id : null, newFeature);
55123 .on('undone.select', update)
55124 .on('redone.select', update);
55127 .on('move.select', closeMenu)
55128 .on('drawn.select', selectElements);
55131 .on('dblclick.select', dblclick);
55136 if (selectedIDs.length > 1) {
55137 var entities = uiSelectionList(context, selectedIDs);
55138 context.ui().sidebar.show(entities);
55142 var extent$$1 = geoExtent$$1(),
55143 graph = context.graph();
55144 selectedIDs.forEach(function(id) {
55145 var entity = context.entity(id);
55146 extent$$1._extend(entity.extent(graph));
55149 var loc = extent$$1.center();
55150 context.map().centerEase(loc);
55151 } else if (singular() && singular().type === 'way') {
55152 context.map().pan([0,0]); // full redraw, to adjust z-sorting #2914
55155 timeout = window.setTimeout(function() {
55157 if (!suppressMenu) {
55160 }, 270); /* after any centerEase completes */
55165 mode.exit = function() {
55166 if (timeout) window.clearTimeout(timeout);
55168 if (inspector) wrap.call(inspector.close);
55170 behaviors.forEach(function(behavior) {
55171 context.uninstall(behavior);
55176 editMenu = undefined;
55179 .on('undone.select', null)
55180 .on('redone.select', null);
55182 var surface = context.surface();
55185 .on('dblclick.select', null);
55188 .selectAll('.selected')
55189 .classed('selected', false);
55192 .selectAll('.related')
55193 .classed('related', false);
55195 context.map().on('drawn.select', null);
55196 context.ui().sidebar.hide();
55203 function uiAccount(context) {
55204 var connection = context.connection();
55207 function update(selection$$1) {
55208 if (!connection.authenticated()) {
55209 selection$$1.selectAll('#userLink, #logoutLink')
55210 .classed('hide', true);
55214 connection.userDetails(function(err, details) {
55215 var userLink = selection$$1.select('#userLink'),
55216 logoutLink = selection$$1.select('#logoutLink');
55219 logoutLink.html('');
55223 selection$$1.selectAll('#userLink, #logoutLink')
55224 .classed('hide', false);
55227 userLink.append('a')
55228 .attr('href', connection.userURL(details.display_name))
55229 .attr('target', '_blank');
55231 // Add thumbnail or dont
55232 if (details.image_url) {
55233 userLink.append('img')
55234 .attr('class', 'icon pre-text user-icon')
55235 .attr('src', details.image_url);
55238 .call(svgIcon('#icon-avatar', 'pre-text light'));
55242 userLink.append('span')
55243 .attr('class', 'label')
55244 .text(details.display_name);
55246 logoutLink.append('a')
55247 .attr('class', 'logout')
55250 .on('click.logout', function() {
55251 event.preventDefault();
55252 connection.logout();
55258 return function(selection$$1) {
55259 selection$$1.append('li')
55260 .attr('id', 'logoutLink')
55261 .classed('hide', true);
55263 selection$$1.append('li')
55264 .attr('id', 'userLink')
55265 .classed('hide', true);
55268 .on('change.account', function() { update(selection$$1); });
55270 update(selection$$1);
55274 function uiAttribution(context) {
55278 function attribution(data, klass) {
55279 var div = selection$$1.selectAll('.' + klass)
55284 .attr('class', klass)
55288 var background = div.selectAll('.attribution')
55289 .data(data, function(d) { return d.name(); });
55294 background = background.enter()
55296 .attr('class', 'attribution')
55297 .each(function(d) {
55298 if (d.terms_html) {
55300 .html(d.terms_html);
55306 selection$$1 = select(this)
55308 .attr('href', d.terms_url)
55309 .attr('target', '_blank');
55311 selection$$1 = select(this);
55315 var id_safe = d.id.replace('.', '<TX_DOT>');
55316 var terms_text = t('imagery.' + id_safe + '.attribution.text',
55317 { default: d.terms_text || d.id || d.name() }
55320 if (d.icon && !d.overlay) {
55323 .attr('class', 'source-image')
55324 .attr('src', d.icon);
55329 .attr('class', 'attribution-text')
55332 .merge(background);
55335 var copyright = background.selectAll('.copyright-notice')
55336 .data(function(d) {
55337 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
55338 return notice ? [notice] : [];
55344 copyright = copyright.enter()
55346 .attr('class', 'copyright-notice')
55354 function update() {
55355 attribution([context.background().baseLayerSource()], 'base-layer-attribution');
55356 attribution(context.background().overlayLayerSources().filter(function (s) {
55357 return s.validZoom(context.map().zoom());
55358 }), 'overlay-layer-attribution');
55362 return function(select$$1) {
55363 selection$$1 = select$$1;
55365 context.background()
55366 .on('change.attribution', update);
55369 .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
55375 function localeDateString(s) {
55376 if (!s) return null;
55377 var d = new Date(s);
55378 if (isNaN(d.getTime())) return null;
55379 return d.toLocaleDateString();
55382 function vintageRange(vintage) {
55384 if (vintage.start || vintage.end) {
55385 s = (vintage.start || '?');
55386 if (vintage.start !== vintage.end) {
55387 s += ' - ' + (vintage.end || '?');
55394 function rendererBackgroundSource(data) {
55395 var source = lodash.clone(data),
55397 name = source.name,
55398 description = source.description,
55399 best = !!source.best,
55400 template = source.template;
55402 source.scaleExtent = data.scaleExtent || [0, 20];
55403 source.overzoom = data.overzoom !== false;
55406 source.offset = function(_) {
55407 if (!arguments.length) return offset;
55413 source.nudge = function(_, zoomlevel) {
55414 offset[0] += _[0] / Math.pow(2, zoomlevel);
55415 offset[1] += _[1] / Math.pow(2, zoomlevel);
55420 source.name = function() {
55421 var id_safe = source.id.replace('.', '<TX_DOT>');
55422 return t('imagery.' + id_safe + '.name', { default: name });
55426 source.description = function() {
55427 var id_safe = source.id.replace('.', '<TX_DOT>');
55428 return t('imagery.' + id_safe + '.description', { default: description });
55432 source.best = function() {
55437 source.area = function() {
55438 if (!data.polygon) return Number.MAX_VALUE; // worldwide
55439 var area$$1 = area({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
55440 return isNaN(area$$1) ? 0 : area$$1;
55444 source.imageryUsed = function() {
55445 return name || source.id;
55449 source.template = function(_) {
55450 if (!arguments.length) return template;
55451 if (source.id === 'custom') template = _;
55456 source.url = function(coord) {
55458 .replace('{x}', coord[0])
55459 .replace('{y}', coord[1])
55460 // TMS-flipped y coordinate
55461 .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
55462 .replace(/\{z(oom)?\}/, coord[2])
55463 .replace(/\{switch:([^}]+)\}/, function(s, r) {
55464 var subdomains = r.split(',');
55465 return subdomains[(coord[0] + coord[1]) % subdomains.length];
55467 .replace('{u}', function() {
55469 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
55471 var mask = 1 << (zoom$$1 - 1);
55472 if ((coord[0] & mask) !== 0) b++;
55473 if ((coord[1] & mask) !== 0) b += 2;
55481 source.intersects = function(extent$$1) {
55482 extent$$1 = extent$$1.polygon();
55483 return !data.polygon || data.polygon.some(function(polygon) {
55484 return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
55489 source.validZoom = function(z) {
55490 return source.scaleExtent[0] <= z &&
55491 (source.overzoom || source.scaleExtent[1] > z);
55495 source.isLocatorOverlay = function() {
55496 return source.id === 'mapbox_locator_overlay';
55500 source.copyrightNotices = function() {};
55503 source.getVintage = function(center, tileCoord, callback) {
55505 start: localeDateString(source.startDate),
55506 end: localeDateString(source.endDate)
55508 vintage.range = vintageRange(vintage);
55509 callback(null, vintage);
55517 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
55518 // http://msdn.microsoft.com/en-us/library/ff701716.aspx
55519 // http://msdn.microsoft.com/en-us/library/ff701701.aspx
55521 data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
55523 var bing = rendererBackgroundSource(data),
55524 key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
55525 url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
55526 key + '&jsonp={callback}',
55530 jsonpRequest(url, function(json$$1) {
55531 providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
55533 attribution: provider.attribution,
55534 areas: provider.coverageAreas.map(function(area$$1) {
55536 zoom: [area$$1.zoomMin, area$$1.zoomMax],
55537 extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
55542 dispatch$$1.call('change');
55546 bing.copyrightNotices = function(zoom$$1, extent$$1) {
55547 zoom$$1 = Math.min(zoom$$1, 21);
55548 return providers.filter(function(provider) {
55549 return lodash.some(provider.areas, function(area$$1) {
55550 return extent$$1.intersects(area$$1.extent) &&
55551 area$$1.zoom[0] <= zoom$$1 &&
55552 area$$1.zoom[1] >= zoom$$1;
55554 }).map(function(provider) {
55555 return provider.attribution;
55560 bing.getVintage = function(center, tileCoord, callback) {
55561 var tileId = tileCoord.slice(0, 3).join('/'),
55562 zoom$$1 = Math.min(tileCoord[2], 21),
55563 centerPoint = center[1] + ',' + center[0], // lat,lng
55564 url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/' + centerPoint +
55565 '?zl=' + zoom$$1 + '&key=' + key + '&jsonp={callback}';
55567 if (!cache[tileId]) {
55568 cache[tileId] = {};
55570 if (cache[tileId] && cache[tileId].vintage) {
55571 return callback(null, cache[tileId].vintage);
55574 jsonpRequest(url, function(result) {
55575 var err = (!result && 'Unknown Error') || result.errorDetails;
55577 return callback(err);
55580 start: localeDateString(result.resourceSets[0].resources[0].vintageStart),
55581 end: localeDateString(result.resourceSets[0].resources[0].vintageEnd)
55583 vintage.range = vintageRange(vintage);
55584 cache[tileId].vintage = vintage;
55585 return callback(null, vintage);
55591 bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
55598 rendererBackgroundSource.None = function() {
55599 var source = rendererBackgroundSource({ id: 'none', template: '' });
55602 source.name = function() {
55603 return t('background.none');
55607 source.imageryUsed = function() {
55612 source.area = function() {
55613 return -1; // sources in background pane are sorted by area
55621 rendererBackgroundSource.Custom = function(template) {
55622 var source = rendererBackgroundSource({ id: 'custom', template: template });
55625 source.name = function() {
55626 return t('background.custom');
55630 source.imageryUsed = function() {
55631 return 'Custom (' + source.template() + ')';
55635 source.area = function() {
55636 return -2; // sources in background pane are sorted by area
55643 function rendererTileLayer(context) {
55644 var tileSize = 256,
55645 tile = d3geoTile(),
55650 transformProp = utilPrefixCSSProperty('Transform'),
55651 source = rendererBackgroundSource.None();
55654 // blacklist overlay tiles around Null Island..
55655 function nearNullIsland(x, y, z) {
55657 var center = Math.pow(2, z - 1),
55658 width = Math.pow(2, z - 6),
55659 min$$1 = center - (width / 2),
55660 max$$1 = center + (width / 2) - 1;
55661 return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
55667 function tileSizeAtZoom(d, z) {
55668 var epsilon = 0.002;
55669 return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
55673 function atZoom(t$$1, distance$$1) {
55674 var power = Math.pow(2, distance$$1);
55676 Math.floor(t$$1[0] * power),
55677 Math.floor(t$$1[1] * power),
55678 t$$1[2] + distance$$1];
55682 function lookUp(d) {
55683 for (var up = -1; up > -d[2]; up--) {
55684 var tile = atZoom(d, up);
55685 if (cache[source.url(tile)] !== false) {
55692 function uniqueBy(a, n) {
55693 var o = [], seen = {};
55694 for (var i = 0; i < a.length; i++) {
55695 if (seen[a[i][n]] === undefined) {
55697 seen[a[i][n]] = true;
55704 function addSource(d) {
55705 d.push(source.url(d));
55710 // Update tiles based on current state of `projection`.
55711 function background(selection$$1) {
55712 tile.scale(projection$$1.scale() * 2 * Math.PI)
55713 .translate(projection$$1.translate());
55716 projection$$1.scale() * Math.PI - projection$$1.translate()[0],
55717 projection$$1.scale() * Math.PI - projection$$1.translate()[1]];
55719 z = Math.max(Math.log(projection$$1.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
55721 render(selection$$1);
55725 // Derive the tiles onscreen, remove those offscreen and position them.
55726 // Important that this part not depend on `projection` because it's
55727 // rentered when tiles load/error (see #644).
55728 function render(selection$$1) {
55730 var showDebug = context.getDebug('tile') && !source.overlay;
55732 if (source.validZoom(z)) {
55733 tile().forEach(function(d) {
55735 if (d[3] === '') return;
55736 if (typeof d[3] !== 'string') return; // Workaround for #2295
55738 if (cache[d[3]] === false && lookUp(d)) {
55739 requests.push(addSource(lookUp(d)));
55743 requests = uniqueBy(requests, 3).filter(function(r) {
55744 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
55747 // don't re-request tiles which have failed in the past
55748 return cache[r[3]] !== false;
55752 var pixelOffset = [
55753 source.offset()[0] * Math.pow(2, z),
55754 source.offset()[1] * Math.pow(2, z)
55759 cache[d[3]] = true;
55763 .classed('tile-loaded', true);
55764 render(selection$$1);
55767 function error(d) {
55768 cache[d[3]] = false;
55773 render(selection$$1);
55776 function imageTransform(d) {
55777 var _ts = tileSize * Math.pow(2, z - d[2]);
55778 var scale = tileSizeAtZoom(d, z);
55779 return 'translate(' +
55780 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
55781 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
55782 'scale(' + scale + ',' + scale + ')';
55785 function tileCenter(d) {
55786 var _ts = tileSize * Math.pow(2, z - d[2]);
55788 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + (_ts / 2)),
55789 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + (_ts / 2))
55793 function debugTransform(d) {
55794 var coord = tileCenter(d);
55795 return 'translate(' + coord[0] + 'px,' + coord[1] + 'px)';
55799 // Pick a representative tile near the center of the viewport
55800 // (This is useful for sampling the imagery vintage)
55801 var dims = tile.size(),
55802 mapCenter = [dims[0] / 2, dims[1] / 2],
55803 minDist = Math.max(dims[0], dims[1]),
55806 requests.forEach(function(d) {
55807 var c = tileCenter(d);
55808 var dist = geoEuclideanDistance(c, mapCenter);
55809 if (dist < minDist) {
55816 var image = selection$$1.selectAll('img')
55817 .data(requests, function(d) { return d[3]; });
55820 .style(transformProp, imageTransform)
55821 .classed('tile-removing', true)
55822 .classed('tile-center', false)
55824 var tile = select(this);
55825 window.setTimeout(function() {
55826 if (tile.classed('tile-removing')) {
55834 .attr('class', 'tile')
55835 .attr('src', function(d) { return d[3]; })
55836 .on('error', error)
55839 .style(transformProp, imageTransform)
55840 .classed('tile-debug', showDebug)
55841 .classed('tile-removing', false)
55842 .classed('tile-center', function(d) { return d === nearCenter; });
55846 var debug = selection$$1.selectAll('.tile-label-debug')
55847 .data(showDebug ? requests : [], function(d) { return d[3]; });
55853 var debugEnter = debug.enter()
55855 .attr('class', 'tile-label-debug');
55859 .attr('class', 'tile-label-debug-coord');
55863 .attr('class', 'tile-label-debug-vintage');
55865 debug = debug.merge(debugEnter);
55868 .style(transformProp, debugTransform);
55871 .selectAll('.tile-label-debug-coord')
55872 .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; });
55875 .selectAll('.tile-label-debug-vintage')
55876 .each(function(d) {
55877 var span = select(this);
55878 var center = context.projection.invert(tileCenter(d));
55879 source.getVintage(center, d, function(err, result) {
55880 span.text((result && result.range) ||
55881 t('info_panels.background.vintage') + ': ' + t('info_panels.background.unknown')
55890 background.projection = function(_) {
55891 if (!arguments.length) return projection$$1;
55897 background.dimensions = function(_) {
55898 if (!arguments.length) return tile.size();
55904 background.source = function(_) {
55905 if (!arguments.length) return source;
55908 tile.scaleExtent(source.scaleExtent);
55916 function rendererBackground(context) {
55917 var dispatch$$1 = dispatch('change'),
55918 baseLayer = rendererTileLayer(context).projection(context.projection),
55919 overlayLayers = [],
55923 function findSource(id) {
55924 return lodash.find(backgroundSources, function(d) {
55925 return d.id && d.id === id;
55930 function background(selection$$1) {
55931 var base = selection$$1.selectAll('.layer-background')
55935 .insert('div', '.layer-data')
55936 .attr('class', 'layer layer-background')
55940 var overlays = selection$$1.selectAll('.layer-overlay')
55941 .data(overlayLayers, function(d) { return d.source().name(); });
55947 .insert('div', '.layer-data')
55948 .attr('class', 'layer layer-overlay')
55950 .each(function(layer) { select(this).call(layer); });
55954 background.updateImagery = function() {
55955 if (context.inIntro()) return;
55957 var b = background.baseLayerSource(),
55959 .filter(function (d) { return !d.source().isLocatorOverlay(); })
55960 .map(function (d) { return d.source().id; })
55962 meters = geoOffsetToMeters(b.offset()),
55964 x = +meters[0].toFixed(2),
55965 y = +meters[1].toFixed(2),
55966 q = utilStringQs(window.location.hash.substring(1));
55969 if (id === 'custom') {
55970 id = 'custom:' + b.template();
55976 delete q.background;
55985 if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
55986 q.offset = x + ',' + y;
55991 window.location.replace('#' + utilQsString(q, true));
55993 var imageryUsed = [b.imageryUsed()];
55996 .filter(function (d) { return !d.source().isLocatorOverlay(); })
55997 .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); });
55999 var gpx = context.layers().layer('gpx');
56000 if (gpx && gpx.enabled() && gpx.hasGpx()) {
56001 imageryUsed.push('Local GPX');
56004 var mapillary_images = context.layers().layer('mapillary-images');
56005 if (mapillary_images && mapillary_images.enabled()) {
56006 imageryUsed.push('Mapillary Images');
56009 var mapillary_signs = context.layers().layer('mapillary-signs');
56010 if (mapillary_signs && mapillary_signs.enabled()) {
56011 imageryUsed.push('Mapillary Signs');
56014 context.history().imageryUsed(imageryUsed);
56018 background.sources = function(extent$$1) {
56019 return backgroundSources.filter(function(source) {
56020 return source.intersects(extent$$1);
56025 background.dimensions = function(_) {
56027 baseLayer.dimensions(_);
56029 overlayLayers.forEach(function(layer) {
56030 layer.dimensions(_);
56035 background.baseLayerSource = function(d) {
56036 if (!arguments.length) return baseLayer.source();
56038 // test source against OSM imagery blacklists..
56039 var blacklists = context.connection().imageryBlacklists();
56041 var template = d.template(),
56046 for (i = 0; i < blacklists.length; i++) {
56048 regex = new RegExp(blacklists[i]);
56049 fail = regex.test(template);
56057 // ensure at least one test was run.
56059 regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*');
56060 fail = regex.test(template);
56063 baseLayer.source(!fail ? d : rendererBackgroundSource.None());
56064 dispatch$$1.call('change');
56065 background.updateImagery();
56070 background.bing = function() {
56071 background.baseLayerSource(findSource('Bing'));
56075 background.showsLayer = function(d) {
56076 return d.id === baseLayer.source().id ||
56077 overlayLayers.some(function(layer) { return d.id === layer.source().id; });
56081 background.overlayLayerSources = function() {
56082 return overlayLayers.map(function (l) { return l.source(); });
56086 background.toggleOverlayLayer = function(d) {
56089 for (var i = 0; i < overlayLayers.length; i++) {
56090 layer = overlayLayers[i];
56091 if (layer.source() === d) {
56092 overlayLayers.splice(i, 1);
56093 dispatch$$1.call('change');
56094 background.updateImagery();
56099 layer = rendererTileLayer(context)
56101 .projection(context.projection)
56102 .dimensions(baseLayer.dimensions());
56104 overlayLayers.push(layer);
56105 dispatch$$1.call('change');
56106 background.updateImagery();
56110 background.nudge = function(d, zoom$$1) {
56111 baseLayer.source().nudge(d, zoom$$1);
56112 dispatch$$1.call('change');
56113 background.updateImagery();
56118 background.offset = function(d) {
56119 if (!arguments.length) return baseLayer.source().offset();
56120 baseLayer.source().offset(d);
56121 dispatch$$1.call('change');
56122 background.updateImagery();
56127 background.init = function() {
56128 function parseMap(qmap) {
56129 if (!qmap) return false;
56130 var args = qmap.split('/').map(Number);
56131 if (args.length < 3 || args.some(isNaN)) return false;
56132 return geoExtent$$1([args[2], args[1]]);
56135 var dataImagery = data.imagery || [],
56136 q = utilStringQs(window.location.hash.substring(1)),
56137 chosen = q.background || q.layer,
56138 extent$$1 = parseMap(q.map),
56141 backgroundSources = dataImagery.map(function(source) {
56142 if (source.type === 'bing') {
56143 return rendererBackgroundSource.Bing(source, dispatch$$1);
56145 return rendererBackgroundSource(source);
56149 backgroundSources.unshift(rendererBackgroundSource.None());
56151 if (!chosen && extent$$1) {
56152 best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
56155 if (chosen && chosen.indexOf('custom:') === 0) {
56156 background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
56158 background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
56161 var locator = lodash.find(backgroundSources, function(d) {
56162 return d.overlay && d.default;
56166 background.toggleOverlayLayer(locator);
56169 var overlays = (q.overlays || '').split(',');
56170 overlays.forEach(function(overlay) {
56171 overlay = findSource(overlay);
56173 background.toggleOverlayLayer(overlay);
56178 var gpx = context.layers().layer('gpx');
56185 var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
56186 return !isNaN(n) && n;
56189 if (offset.length === 2) {
56190 background.offset(geoMetersToOffset(offset));
56196 return utilRebind(background, dispatch$$1, 'on');
56199 function rendererFeatures(context) {
56200 var traffic_roads = {
56202 'motorway_link': true,
56204 'trunk_link': true,
56206 'primary_link': true,
56208 'secondary_link': true,
56210 'tertiary_link': true,
56211 'residential': true,
56212 'unclassified': true,
56213 'living_street': true
56216 var service_roads = {
56228 'pedestrian': true,
56232 var past_futures = {
56234 'construction': true,
56236 'dismantled': true,
56239 'demolished': true,
56240 'obliterated': true
56243 var dispatch$$1 = dispatch('change', 'redraw'),
56252 function update() {
56253 _hidden = features.hidden();
56254 dispatch$$1.call('change');
56255 dispatch$$1.call('redraw');
56259 function defineFeature(k, filter, max$$1) {
56263 enabled: true, // whether the user wants it enabled..
56265 currentMax: (max$$1 || Infinity),
56266 defaultMax: (max$$1 || Infinity),
56267 enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
56268 disable: function() { this.enabled = false; this.currentMax = 0; },
56269 hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
56270 autoHidden: function() { return this.hidden() && this.currentMax > 0; }
56275 defineFeature('points', function isPoint(entity, resolver, geometry) {
56276 return geometry === 'point';
56279 defineFeature('traffic_roads', function isTrafficRoad(entity) {
56280 return traffic_roads[entity.tags.highway];
56283 defineFeature('service_roads', function isServiceRoad(entity) {
56284 return service_roads[entity.tags.highway];
56287 defineFeature('paths', function isPath(entity) {
56288 return paths[entity.tags.highway];
56291 defineFeature('buildings', function isBuilding(entity) {
56293 !!entity.tags['building:part'] ||
56294 (!!entity.tags.building && entity.tags.building !== 'no') ||
56295 entity.tags.amenity === 'shelter' ||
56296 entity.tags.parking === 'multi-storey' ||
56297 entity.tags.parking === 'sheds' ||
56298 entity.tags.parking === 'carports' ||
56299 entity.tags.parking === 'garage_boxes'
56303 defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
56304 return geometry === 'area' &&
56305 !_features.buildings.filter(entity) &&
56306 !_features.water.filter(entity);
56309 defineFeature('boundaries', function isBoundary(entity) {
56310 return !!entity.tags.boundary;
56313 defineFeature('water', function isWater(entity) {
56315 !!entity.tags.waterway ||
56316 entity.tags.natural === 'water' ||
56317 entity.tags.natural === 'coastline' ||
56318 entity.tags.natural === 'bay' ||
56319 entity.tags.landuse === 'pond' ||
56320 entity.tags.landuse === 'basin' ||
56321 entity.tags.landuse === 'reservoir' ||
56322 entity.tags.landuse === 'salt_pond'
56326 defineFeature('rail', function isRail(entity) {
56328 !!entity.tags.railway ||
56329 entity.tags.landuse === 'railway'
56331 traffic_roads[entity.tags.highway] ||
56332 service_roads[entity.tags.highway] ||
56333 paths[entity.tags.highway]
56337 defineFeature('power', function isPower(entity) {
56338 return !!entity.tags.power;
56341 // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
56342 defineFeature('past_future', function isPastFuture(entity) {
56344 traffic_roads[entity.tags.highway] ||
56345 service_roads[entity.tags.highway] ||
56346 paths[entity.tags.highway]
56347 ) { return false; }
56349 var strings = Object.keys(entity.tags);
56351 for (var i = 0; i < strings.length; i++) {
56352 var s = strings[i];
56353 if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
56358 // Lines or areas that don't match another feature filter.
56359 // IMPORTANT: The 'others' feature must be the last one defined,
56360 // so that code in getMatches can skip this test if `hasMatch = true`
56361 defineFeature('others', function isOther(entity, resolver, geometry) {
56362 return (geometry === 'line' || geometry === 'area');
56366 function features() {}
56369 features.features = function() {
56374 features.keys = function() {
56379 features.enabled = function(k) {
56380 if (!arguments.length) {
56381 return _keys.filter(function(k) { return _features[k].enabled; });
56383 return _features[k] && _features[k].enabled;
56387 features.disabled = function(k) {
56388 if (!arguments.length) {
56389 return _keys.filter(function(k) { return !_features[k].enabled; });
56391 return _features[k] && !_features[k].enabled;
56395 features.hidden = function(k) {
56396 if (!arguments.length) {
56397 return _keys.filter(function(k) { return _features[k].hidden(); });
56399 return _features[k] && _features[k].hidden();
56403 features.autoHidden = function(k) {
56404 if (!arguments.length) {
56405 return _keys.filter(function(k) { return _features[k].autoHidden(); });
56407 return _features[k] && _features[k].autoHidden();
56411 features.enable = function(k) {
56412 if (_features[k] && !_features[k].enabled) {
56413 _features[k].enable();
56419 features.disable = function(k) {
56420 if (_features[k] && _features[k].enabled) {
56421 _features[k].disable();
56427 features.toggle = function(k) {
56428 if (_features[k]) {
56429 (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
56435 features.resetStats = function() {
56436 for (var i = 0; i < _keys.length; i++) {
56437 _features[_keys[i]].count = 0;
56439 dispatch$$1.call('change');
56443 features.gatherStats = function(d, resolver, dimensions) {
56444 var needsRedraw = false,
56445 type = lodash.groupBy(d, function(ent) { return ent.type; }),
56446 entities = [].concat(type.relation || [], type.way || [], type.node || []),
56447 currHidden, geometry, matches, i, j;
56449 for (i = 0; i < _keys.length; i++) {
56450 _features[_keys[i]].count = 0;
56453 // adjust the threshold for point/building culling based on viewport size..
56454 // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
56455 _cullFactor = dimensions[0] * dimensions[1] / 1000000;
56457 for (i = 0; i < entities.length; i++) {
56458 geometry = entities[i].geometry(resolver);
56459 if (!(geometry === 'vertex' || geometry === 'relation')) {
56460 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
56461 for (j = 0; j < matches.length; j++) {
56462 _features[matches[j]].count++;
56467 currHidden = features.hidden();
56468 if (currHidden !== _hidden) {
56469 _hidden = currHidden;
56470 needsRedraw = true;
56471 dispatch$$1.call('change');
56474 return needsRedraw;
56478 features.stats = function() {
56479 for (var i = 0; i < _keys.length; i++) {
56480 _stats[_keys[i]] = _features[_keys[i]].count;
56487 features.clear = function(d) {
56488 for (var i = 0; i < d.length; i++) {
56489 features.clearEntity(d[i]);
56494 features.clearEntity = function(entity) {
56495 delete _cache[osmEntity$$1.key(entity)];
56499 features.reset = function() {
56504 features.getMatches = function(entity, resolver, geometry) {
56505 if (geometry === 'vertex' || geometry === 'relation') return {};
56507 var ent = osmEntity$$1.key(entity);
56508 if (!_cache[ent]) {
56512 if (!_cache[ent].matches) {
56516 for (var i = 0; i < _keys.length; i++) {
56517 if (_keys[i] === 'others') {
56518 if (hasMatch) continue;
56520 // Multipolygon members:
56522 // 1. is a way that hasn't matched other 'interesting' feature rules,
56523 // 2. and it belongs to a single parent multipolygon relation
56524 // ...then match whatever feature rules the parent multipolygon has matched.
56525 // see #2548, #2887
56528 // For this to work, getMatches must be called on relations before ways.
56530 if (entity.type === 'way') {
56531 var parents = features.getParents(entity, resolver, geometry);
56532 if (parents.length === 1 && parents[0].isMultipolygon()) {
56533 var pkey = osmEntity$$1.key(parents[0]);
56534 if (_cache[pkey] && _cache[pkey].matches) {
56535 matches = lodash.clone(_cache[pkey].matches);
56542 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
56543 matches[_keys[i]] = hasMatch = true;
56546 _cache[ent].matches = matches;
56549 return _cache[ent].matches;
56553 features.getParents = function(entity, resolver, geometry) {
56554 if (geometry === 'point') return [];
56556 var ent = osmEntity$$1.key(entity);
56557 if (!_cache[ent]) {
56561 if (!_cache[ent].parents) {
56563 if (geometry === 'vertex') {
56564 parents = resolver.parentWays(entity);
56565 } else { // 'line', 'area', 'relation'
56566 parents = resolver.parentRelations(entity);
56568 _cache[ent].parents = parents;
56570 return _cache[ent].parents;
56574 features.isHiddenFeature = function(entity, resolver, geometry) {
56575 if (!_hidden.length) return false;
56576 if (!entity.version) return false;
56578 var matches = features.getMatches(entity, resolver, geometry);
56580 for (var i = 0; i < _hidden.length; i++) {
56581 if (matches[_hidden[i]]) return true;
56587 features.isHiddenChild = function(entity, resolver, geometry) {
56588 if (!_hidden.length) return false;
56589 if (!entity.version || geometry === 'point') return false;
56591 var parents = features.getParents(entity, resolver, geometry);
56592 if (!parents.length) return false;
56594 for (var i = 0; i < parents.length; i++) {
56595 if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
56603 features.hasHiddenConnections = function(entity, resolver) {
56604 if (!_hidden.length) return false;
56605 var childNodes, connections;
56607 if (entity.type === 'midpoint') {
56608 childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
56611 childNodes = entity.nodes ? resolver.childNodes(entity) : [];
56612 connections = features.getParents(entity, resolver, entity.geometry(resolver));
56615 // gather ways connected to child nodes..
56616 connections = lodash.reduce(childNodes, function(result, e) {
56617 return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
56620 return connections.length ? lodash.some(connections, function(e) {
56621 return features.isHidden(e, resolver, e.geometry(resolver));
56626 features.isHidden = function(entity, resolver, geometry) {
56627 if (!_hidden.length) return false;
56628 if (!entity.version) return false;
56630 var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
56631 return fn(entity, resolver, geometry);
56635 features.filter = function(d, resolver) {
56636 if (!_hidden.length) return d;
56639 for (var i = 0; i < d.length; i++) {
56641 if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
56642 result.push(entity);
56649 return utilRebind(features, dispatch$$1, 'on');
56652 function utilBindOnce(target, type, listener, capture) {
56653 var typeOnce = type + '.once';
56655 target.on(typeOnce, null);
56656 listener.apply(this, arguments);
56658 target.on(typeOnce, one, capture);
56662 function rendererMap(context) {
56664 var dimensions = [1, 1],
56665 dispatch$$1 = dispatch('move', 'drawn'),
56666 projection$$1 = context.projection,
56667 curtainProjection = context.curtainProjection,
56668 dblclickEnabled = true,
56669 redrawEnabled = true,
56670 transformStart = projection$$1.transform(),
56672 transformed = false,
56674 drawLayers = svgLayers(projection$$1, context),
56675 drawPoints = svgPoints$$1(projection$$1, context),
56676 drawVertices = svgVertices$$1(projection$$1, context),
56677 drawLines = svgLines$$1(projection$$1, context),
56678 drawAreas = svgAreas$$1(projection$$1, context),
56679 drawMidpoints = svgMidpoints$$1(projection$$1, context),
56680 drawLabels = svgLabels(projection$$1, context),
56681 supersurface = select(null),
56682 wrapper = select(null),
56683 surface = select(null),
56687 var zoom$$1 = zoom()
56688 .scaleExtent([ztok(2), ztok(24)])
56689 .interpolate(interpolateValue)
56690 .filter(zoomEventFilter)
56691 .on('zoom', zoomPan);
56693 var _selection = select(null);
56696 function map(selection$$1) {
56698 _selection = selection$$1;
56701 .on('change.map', immediateRedraw);
56703 context.connection()
56704 .on('change.map', immediateRedraw);
56707 .on('change.map', immediateRedraw)
56708 .on('undone.map redone.map', function(stack$$1) {
56709 var mode = context.mode().id;
56710 if (mode !== 'browse' && mode !== 'select') return;
56712 var followSelected = false;
56713 if (Array.isArray(stack$$1.selectedIDs)) {
56714 followSelected = (stack$$1.selectedIDs.length === 1 && stack$$1.selectedIDs[0][0] === 'n');
56716 modeSelect(context, stack$$1.selectedIDs).follow(followSelected)
56719 if (!followSelected && stack$$1.transform) {
56720 map.transformEase(stack$$1.transform);
56724 context.background()
56725 .on('change.map', immediateRedraw);
56728 .on('redraw.map', immediateRedraw);
56731 .on('change.map', function() {
56732 context.background().updateImagery();
56737 .on('dblclick.map', dblClick)
56739 .call(zoom$$1.transform, projection$$1.transform());
56741 supersurface = selection$$1.append('div')
56742 .attr('id', 'supersurface')
56743 .call(utilSetTransform, 0, 0);
56745 // Need a wrapper div because Opera can't cope with an absolutely positioned
56746 // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
56747 wrapper = supersurface
56749 .attr('class', 'layer layer-data');
56751 map.surface = surface = wrapper
56753 .selectAll('.surface')
56754 .attr('id', 'surface');
56757 .call(drawLabels.observe)
56758 .on('mousedown.zoom', function() {
56759 if (event.button === 2) {
56760 event.stopPropagation();
56763 .on('mouseup.zoom', function() {
56764 if (resetTransform()) immediateRedraw();
56766 .on('mousemove.map', function() {
56769 .on('mouseover.vertices', function() {
56770 if (map.editable() && !transformed) {
56771 var hover = event.target.__data__;
56772 surface.selectAll('.data-layer-osm')
56773 .call(drawVertices.drawHover, context.graph(), hover, map.extent(), map.zoom());
56774 dispatch$$1.call('drawn', this, {full: false});
56777 .on('mouseout.vertices', function() {
56778 if (map.editable() && !transformed) {
56779 var hover = event.relatedTarget && event.relatedTarget.__data__;
56780 surface.selectAll('.data-layer-osm')
56781 .call(drawVertices.drawHover, context.graph(), hover, map.extent(), map.zoom());
56782 dispatch$$1.call('drawn', this, {full: false});
56787 .call(context.background());
56789 context.on('enter.map', function() {
56790 if (map.editable() && !transformed) {
56791 var all = context.intersects(map.extent()),
56792 filter = utilFunctor(true),
56793 graph = context.graph();
56795 all = context.features().filter(all, graph);
56796 surface.selectAll('.data-layer-osm')
56797 .call(drawVertices, graph, all, filter, map.extent(), map.zoom())
56798 .call(drawMidpoints, graph, all, filter, map.trimmedExtent());
56799 dispatch$$1.call('drawn', this, {full: false});
56803 map.dimensions(utilGetDimensions(selection$$1));
56807 function zoomEventFilter() {
56808 // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
56809 // Intercept `mousedown` and check if there is an orphaned zoom gesture.
56810 // This can happen if a previous `mousedown` occurred without a `mouseup`.
56811 // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
56812 // so that d3-zoom won't stop propagation of new `mousedown` events.
56813 if (event.type === 'mousedown') {
56814 var hasOrphan = false;
56815 var listeners = window.__on;
56816 for (var i = 0; i < listeners.length; i++) {
56817 var listener = listeners[i];
56818 if (listener.name === 'zoom' && listener.type === 'mouseup') {
56824 var event$$1 = window.CustomEvent;
56826 event$$1 = new event$$1('mouseup');
56828 event$$1 = window.document.createEvent('Event');
56829 event$$1.initEvent('mouseup', false, false);
56831 // Event needs to be dispatched with an event.view property.
56832 event$$1.view = window;
56833 window.dispatchEvent(event$$1);
56837 return event.button !== 2; // ignore right clicks
56842 return 256 * Math.pow(2, z);
56846 return Math.max(Math.log(k) / Math.LN2 - 8, 0);
56849 function pxCenter() {
56850 return [dimensions[0] / 2, dimensions[1] / 2];
56854 function drawVector(difference, extent$$1) {
56855 var graph = context.graph(),
56856 features = context.features(),
56857 all = context.intersects(map.extent()),
56861 var complete = difference.complete(map.extent());
56862 data = lodash.compact(lodash.values(complete));
56863 filter = function(d) { return d.id in complete; };
56864 features.clear(data);
56867 // force a full redraw if gatherStats detects that a feature
56868 // should be auto-hidden (e.g. points or buildings)..
56869 if (features.gatherStats(all, graph, dimensions)) {
56870 extent$$1 = undefined;
56874 data = context.intersects(map.extent().intersection(extent$$1));
56875 var set = set$2(lodash.map(data, 'id'));
56876 filter = function(d) { return set.has(d.id); };
56880 filter = utilFunctor(true);
56884 data = features.filter(data, graph);
56886 surface.selectAll('.data-layer-osm')
56887 .call(drawVertices, graph, data, filter, map.extent(), map.zoom())
56888 .call(drawLines, graph, data, filter)
56889 .call(drawAreas, graph, data, filter)
56890 .call(drawMidpoints, graph, data, filter, map.trimmedExtent())
56891 .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
56892 .call(drawPoints, graph, data, filter);
56894 dispatch$$1.call('drawn', this, {full: true});
56898 function editOff() {
56899 context.features().resetStats();
56900 surface.selectAll('.layer-osm *').remove();
56901 dispatch$$1.call('drawn', this, {full: true});
56905 function dblClick() {
56906 if (!dblclickEnabled) {
56907 event.preventDefault();
56908 event.stopImmediatePropagation();
56913 function zoomPan(manualEvent) {
56914 var event$$1 = (manualEvent || event),
56915 source = event$$1.sourceEvent,
56916 eventTransform = event$$1.transform;
56918 if (transformStart.x === eventTransform.x &&
56919 transformStart.y === eventTransform.y &&
56920 transformStart.k === eventTransform.k) {
56921 return; // no change
56924 // Normalize mousewheel - #3029
56925 // If wheel delta is provided in LINE units, recalculate it in PIXEL units
56926 // We are essentially redoing the calculations that occur here:
56927 // https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203
56928 // See this for more info:
56929 // https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js
56930 if (source && source.type === 'wheel' && source.deltaMode === 1 /* LINE */) {
56931 // pick sensible scroll amount if user scrolling fast or slow..
56932 var lines = Math.abs(source.deltaY),
56933 scroll = lines > 2 ? 40 : lines * 10;
56935 var t0 = transformed ? transformLast : transformStart,
56936 p0 = mouse$$1(source),
56937 p1 = t0.invert(p0),
56938 k2 = t0.k * Math.pow(2, -source.deltaY * scroll / 500),
56939 x2 = p0[0] - p1[0] * k2,
56940 y2 = p0[1] - p1[1] * k2;
56942 eventTransform = identity$8.translate(x2,y2).scale(k2);
56943 _selection.node().__zoom = eventTransform;
56946 if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
56947 surface.interrupt();
56948 uiFlash().text(t('cannot_zoom'));
56949 setZoom(context.minEditableZoom(), true);
56951 dispatch$$1.call('move', this, map);
56955 projection$$1.transform(eventTransform);
56957 var scale = eventTransform.k / transformStart.k,
56958 tX = (eventTransform.x / scale - transformStart.x) * scale,
56959 tY = (eventTransform.y / scale - transformStart.y) * scale;
56961 if (context.inIntro()) {
56962 curtainProjection.transform({
56963 x: eventTransform.x - tX,
56964 y: eventTransform.y - tY,
56965 k: eventTransform.k
56969 transformed = true;
56970 transformLast = eventTransform;
56971 utilSetTransform(supersurface, tX, tY, scale);
56974 dispatch$$1.call('move', this, map);
56978 function resetTransform() {
56979 if (!transformed) return false;
56981 // deprecation warning - Radial Menu to be removed in iD v3
56982 surface.selectAll('.edit-menu, .radial-menu').interrupt().remove();
56983 utilSetTransform(supersurface, 0, 0);
56984 transformed = false;
56985 if (context.inIntro()) {
56986 curtainProjection.transform(projection$$1.transform());
56992 function redraw(difference, extent$$1) {
56993 if (surface.empty() || !redrawEnabled) return;
56995 // If we are in the middle of a zoom/pan, we can't do differenced redraws.
56996 // It would result in artifacts where differenced entities are redrawn with
56997 // one transform and unchanged entities with another.
56998 if (resetTransform()) {
56999 difference = extent$$1 = undefined;
57002 var z = String(~~map.zoom());
57003 if (surface.attr('data-zoom') !== z) {
57004 surface.attr('data-zoom', z)
57005 .classed('low-zoom', z <= 16);
57009 supersurface.call(context.background());
57016 if (map.editable()) {
57017 context.loadTiles(projection$$1, dimensions);
57018 drawVector(difference, extent$$1);
57023 transformStart = projection$$1.transform();
57029 var queueRedraw = lodash.throttle(redraw, 750);
57032 var immediateRedraw = function(difference, extent$$1) {
57033 if (!difference && !extent$$1) queueRedraw.cancel();
57034 redraw(difference, extent$$1);
57038 function pointLocation(p) {
57039 var translate = projection$$1.translate(),
57040 scale = projection$$1.scale() * 2 * Math.PI;
57041 return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
57045 function locationPoint(l) {
57046 var translate = projection$$1.translate(),
57047 scale = projection$$1.scale() * 2 * Math.PI;
57048 return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
57052 map.mouse = function() {
57053 var event$$1 = mousemove || event;
57056 while ((s = event$$1.sourceEvent)) { event$$1 = s; }
57057 return mouse$$1(event$$1);
57063 map.mouseCoordinates = function() {
57064 return projection$$1.invert(map.mouse());
57068 map.dblclickEnable = function(_) {
57069 if (!arguments.length) return dblclickEnabled;
57070 dblclickEnabled = _;
57075 map.redrawEnable = function(_) {
57076 if (!arguments.length) return redrawEnabled;
57082 function setTransform(t2, duration, force) {
57083 var t$$1 = projection$$1.transform();
57084 if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) {
57091 .duration(duration)
57092 .on('start', function() { map.startEase(); })
57093 .call(zoom$$1.transform, identity$8.translate(t2.x, t2.y).scale(t2.k));
57095 projection$$1.transform(t2);
57096 transformStart = t2;
57097 _selection.call(zoom$$1.transform, transformStart);
57102 function setZoom(z2, force, duration) {
57103 if (z2 === map.zoom() && !force) {
57107 var k = projection$$1.scale(),
57108 k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
57109 center = pxCenter(),
57110 l = pointLocation(center);
57112 projection$$1.scale(k2);
57114 var t$$1 = projection$$1.translate();
57115 l = locationPoint(l);
57117 t$$1[0] += center[0] - l[0];
57118 t$$1[1] += center[1] - l[1];
57121 projection$$1.scale(k); // reset scale
57124 .duration(duration)
57125 .on('start', function() { map.startEase(); })
57126 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k2));
57128 projection$$1.translate(t$$1);
57129 transformStart = projection$$1.transform();
57130 _selection.call(zoom$$1.transform, transformStart);
57137 function setCenter(loc2, duration) {
57138 var c = map.center();
57139 if (loc2[0] === c[0] && loc2[1] === c[1]) {
57143 var t$$1 = projection$$1.translate(),
57144 k = projection$$1.scale(),
57146 ll = projection$$1(loc2);
57148 t$$1[0] = t$$1[0] - ll[0] + pxC[0];
57149 t$$1[1] = t$$1[1] - ll[1] + pxC[1];
57154 .duration(duration)
57155 .on('start', function() { map.startEase(); })
57156 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k));
57158 projection$$1.translate(t$$1);
57159 transformStart = projection$$1.transform();
57160 _selection.call(zoom$$1.transform, transformStart);
57167 map.pan = function(delta, duration) {
57168 var t$$1 = projection$$1.translate(),
57169 k = projection$$1.scale();
57171 t$$1[0] += delta[0];
57172 t$$1[1] += delta[1];
57177 .duration(duration)
57178 .on('start', function() { map.startEase(); })
57179 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k));
57181 projection$$1.translate(t$$1);
57182 transformStart = projection$$1.transform();
57183 _selection.call(zoom$$1.transform, transformStart);
57184 dispatch$$1.call('move', this, map);
57192 map.dimensions = function(_) {
57193 if (!arguments.length) return dimensions;
57194 var center = map.center();
57196 drawLayers.dimensions(dimensions);
57197 context.background().dimensions(dimensions);
57198 projection$$1.clipExtent([[0, 0], dimensions]);
57199 mouse$$1 = utilFastMouse(supersurface.node());
57207 function zoomIn(delta) {
57208 setZoom(~~map.zoom() + delta, true, 250);
57211 function zoomOut(delta) {
57212 setZoom(~~map.zoom() - delta, true, 250);
57215 map.zoomIn = function() { zoomIn(1); };
57216 map.zoomInFurther = function() { zoomIn(4); };
57218 map.zoomOut = function() { zoomOut(1); };
57219 map.zoomOutFurther = function() { zoomOut(4); };
57222 map.center = function(loc2) {
57223 if (!arguments.length) {
57224 return projection$$1.invert(pxCenter());
57227 if (setCenter(loc2)) {
57228 dispatch$$1.call('move', this, map);
57236 map.zoom = function(z2) {
57237 if (!arguments.length) {
57238 return Math.max(ktoz(projection$$1.scale() * 2 * Math.PI), 0);
57241 if (z2 < minzoom) {
57242 surface.interrupt();
57243 uiFlash().text(t('cannot_zoom'));
57244 z2 = context.minEditableZoom();
57248 dispatch$$1.call('move', this, map);
57256 map.zoomTo = function(entity, zoomLimits) {
57257 var extent$$1 = entity.extent(context.graph());
57258 if (!isFinite(extent$$1.area())) return;
57260 var z2 = map.trimmedExtentZoom(extent$$1);
57261 zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
57262 map.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
57266 map.centerZoom = function(loc2, z2) {
57267 var centered = setCenter(loc2),
57268 zoomed = setZoom(z2);
57270 if (centered || zoomed) {
57271 dispatch$$1.call('move', this, map);
57279 map.centerEase = function(loc2, duration) {
57280 duration = duration || 250;
57281 setCenter(loc2, duration);
57286 map.zoomEase = function(z2, duration) {
57287 duration = duration || 250;
57288 setZoom(z2, false, duration);
57293 map.transformEase = function(t2, duration) {
57294 duration = duration || 250;
57295 setTransform(t2, duration, false);
57300 map.startEase = function() {
57301 utilBindOnce(surface, 'mousedown.ease', function() {
57308 map.cancelEase = function() {
57309 _selection.interrupt();
57314 map.extent = function(_) {
57315 if (!arguments.length) {
57316 return new geoExtent$$1(projection$$1.invert([0, dimensions[1]]),
57317 projection$$1.invert([dimensions[0], 0]));
57319 var extent$$1 = geoExtent$$1(_);
57320 map.centerZoom(extent$$1.center(), map.extentZoom(extent$$1));
57325 map.trimmedExtent = function(_) {
57326 if (!arguments.length) {
57327 var headerY = 60, footerY = 30, pad = 10;
57328 return new geoExtent$$1(projection$$1.invert([pad, dimensions[1] - footerY - pad]),
57329 projection$$1.invert([dimensions[0] - pad, headerY + pad]));
57331 var extent$$1 = geoExtent$$1(_);
57332 map.centerZoom(extent$$1.center(), map.trimmedExtentZoom(extent$$1));
57337 function calcZoom(extent$$1, dim) {
57338 var tl = projection$$1([extent$$1[0][0], extent$$1[1][1]]),
57339 br = projection$$1([extent$$1[1][0], extent$$1[0][1]]);
57341 // Calculate maximum zoom that fits extent
57342 var hFactor = (br[0] - tl[0]) / dim[0],
57343 vFactor = (br[1] - tl[1]) / dim[1],
57344 hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
57345 vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
57346 newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);
57352 map.extentZoom = function(_) {
57353 return calcZoom(geoExtent$$1(_), dimensions);
57357 map.trimmedExtentZoom = function(_) {
57358 var trimY = 120, trimX = 40,
57359 trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
57360 return calcZoom(geoExtent$$1(_), trimmed);
57364 map.editable = function() {
57365 return map.zoom() >= context.minEditableZoom();
57369 map.minzoom = function(_) {
57370 if (!arguments.length) return minzoom;
57376 map.layers = drawLayers;
57379 return utilRebind(map, dispatch$$1, 'on');
57382 var TAU = 2 * Math.PI;
57383 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
57384 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
57385 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
57386 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
57389 function uiMapInMap(context) {
57392 function map_in_map(selection$$1) {
57393 var backgroundLayer = rendererTileLayer(context),
57394 overlayLayers = {},
57395 projection$$1 = geoRawMercator(),
57396 gpxLayer = svgGpx(projection$$1, context).showLabels(false),
57397 debugLayer = svgDebug(projection$$1, context),
57399 .scaleExtent([ztok(0.5), ztok(24)])
57400 .on('start', zoomStarted)
57401 .on('zoom', zoomed)
57402 .on('end', zoomEnded),
57403 isTransformed = false,
57405 skipEvents = false,
57407 zDiff = 6, // by default, minimap renders at (main zoom - 6)
57408 wrap = select(null),
57409 tiles = select(null),
57410 viewport = select(null),
57411 tStart, // transform at start of gesture
57412 tCurr, // transform at most recent event
57416 function zoomStarted() {
57417 if (skipEvents) return;
57418 tStart = tCurr = projection$$1.transform();
57423 function zoomed() {
57424 if (skipEvents) return;
57426 var x = event.transform.x,
57427 y = event.transform.y,
57428 k = event.transform.k,
57429 isZooming = (k !== tStart.k),
57430 isPanning = (x !== tStart.x || y !== tStart.y);
57432 if (!isZooming && !isPanning) {
57433 return; // no change
57436 // lock in either zooming or panning, don't allow both in minimap.
57438 gesture = isZooming ? 'zoom' : 'pan';
57441 var tMini = projection$$1.transform(),
57444 if (gesture === 'zoom') {
57445 var dMini = utilGetDimensions(wrap),
57446 cMini = vecScale(dMini, 0.5);
57447 scale = k / tMini.k;
57448 tX = (cMini[0] / scale - cMini[0]) * scale;
57449 tY = (cMini[1] / scale - cMini[1]) * scale;
57457 utilSetTransform(tiles, tX, tY, scale);
57458 utilSetTransform(viewport, 0, 0, scale);
57459 isTransformed = true;
57460 tCurr = identity$8.translate(x, y).scale(k);
57462 var zMain = ktoz(context.projection.scale()),
57465 zDiff = zMain - zMini;
57471 function zoomEnded() {
57472 if (skipEvents) return;
57473 if (gesture !== 'pan') return;
57475 updateProjection();
57477 var dMini = utilGetDimensions(wrap),
57478 cMini = vecScale(dMini, 0.5);
57479 context.map().center(projection$$1.invert(cMini)); // recenter main map..
57483 function updateProjection() {
57484 var loc = context.map().center(),
57485 dMini = utilGetDimensions(wrap),
57486 cMini = vecScale(dMini, 0.5),
57487 tMain = context.projection.transform(),
57488 zMain = ktoz(tMain.k),
57489 zMini = Math.max(zMain - zDiff, 0.5),
57490 kMini = ztok(zMini);
57493 .translate([tMain.x, tMain.y])
57496 var point = projection$$1(loc),
57497 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
57498 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
57499 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
57502 .translate([xMini, yMini])
57503 .clipExtent([[0, 0], dMini]);
57505 tCurr = projection$$1.transform();
57507 if (isTransformed) {
57508 utilSetTransform(tiles, 0, 0);
57509 utilSetTransform(viewport, 0, 0);
57510 isTransformed = false;
57514 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
57517 wrap.call(zoom$$1.transform, tCurr);
57518 skipEvents = false;
57522 function redraw() {
57523 clearTimeout(timeoutId);
57524 if (isHidden) return;
57526 updateProjection();
57528 var dMini = utilGetDimensions(wrap),
57529 zMini = ktoz(projection$$1.scale());
57531 // setup tile container
57533 .selectAll('.map-in-map-tiles')
57536 tiles = tiles.enter()
57538 .attr('class', 'map-in-map-tiles')
57541 // redraw background
57543 .source(context.background().baseLayerSource())
57544 .projection(projection$$1)
57545 .dimensions(dMini);
57547 var background = tiles
57548 .selectAll('.map-in-map-background')
57553 .attr('class', 'map-in-map-background')
57555 .call(backgroundLayer);
57559 var overlaySources = context.background().overlayLayerSources();
57560 var activeOverlayLayers = [];
57561 for (var i = 0; i < overlaySources.length; i++) {
57562 if (overlaySources[i].validZoom(zMini)) {
57563 if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
57564 activeOverlayLayers.push(overlayLayers[i]
57565 .source(overlaySources[i])
57566 .projection(projection$$1)
57567 .dimensions(dMini));
57571 var overlay = tiles
57572 .selectAll('.map-in-map-overlay')
57575 overlay = overlay.enter()
57577 .attr('class', 'map-in-map-overlay')
57581 var overlays = overlay
57583 .data(activeOverlayLayers, function(d) { return d.source().name(); });
57588 overlays = overlays.enter()
57591 .each(function(layer) { select(this).call(layer); });
57594 var dataLayers = tiles
57595 .selectAll('.map-in-map-data')
57601 dataLayers = dataLayers.enter()
57603 .attr('class', 'map-in-map-data')
57609 // redraw viewport bounding box
57610 if (gesture !== 'pan') {
57611 var getPath = index$4(projection$$1),
57612 bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
57614 viewport = wrap.selectAll('.map-in-map-viewport')
57617 viewport = viewport.enter()
57619 .attr('class', 'map-in-map-viewport')
57623 var path$$1 = viewport.selectAll('.map-in-map-bbox')
57628 .attr('class', 'map-in-map-bbox')
57630 .attr('d', getPath)
57631 .classed('thick', function(d) { return getPath.area(d) < 30; });
57636 function queueRedraw() {
57637 clearTimeout(timeoutId);
57638 timeoutId = setTimeout(function() { redraw(); }, 750);
57642 function toggle() {
57643 if (event) event.preventDefault();
57645 isHidden = !isHidden;
57647 var label = select('.minimap-toggle');
57648 label.classed('active', !isHidden)
57649 .select('input').property('checked', !isHidden);
57653 .style('display', 'block')
57654 .style('opacity', '1')
57657 .style('opacity', '0')
57658 .on('end', function() {
57659 selection$$1.selectAll('.map-in-map')
57660 .style('display', 'none');
57664 .style('display', 'block')
57665 .style('opacity', '0')
57668 .style('opacity', '1')
57669 .on('end', function() {
57676 uiMapInMap.toggle = toggle;
57678 wrap = selection$$1.selectAll('.map-in-map')
57681 wrap = wrap.enter()
57683 .attr('class', 'map-in-map')
57684 .style('display', (isHidden ? 'none' : 'block'))
57686 .on('dblclick.zoom', null)
57690 .on('drawn.map-in-map', function(drawn) {
57691 if (drawn.full === true) {
57698 var keybinding = d3keybinding('map-in-map')
57699 .on(t('background.minimap.key'), toggle);
57708 function uiTooltipHtml(text, key, heading) {
57712 s += '<div class="tooltip-heading"><span>' + heading + '</span></div>';
57715 s += '<div class="tooltip-text"><span>' + text + '</span></div>';
57718 s += '<div class="keyhint-wrap"><span>' + t('tooltip_keyhint') + '</span>' +
57719 '<span class="keyhint">' + key + '</span></div>';
57725 function uiBackground(context) {
57726 var key = t('background.key'),
57727 detected = utilDetect(),
57728 opacities = [1, 0.75, 0.5, 0.25],
57730 ['right', [0.5, 0]],
57731 ['top', [0, -0.5]],
57732 ['left', [-0.5, 0]],
57733 ['bottom', [0, 0.5]]],
57734 opacityDefault = (context.storage('background-opacity') !== null) ?
57735 (+context.storage('background-opacity')) : 1.0,
57736 customTemplate = context.storage('background-custom-template') || '',
57737 customSource = rendererBackgroundSource.Custom(customTemplate),
57740 // Can be 0 from <1.3.0 use or due to issue #1923.
57741 if (opacityDefault === 0) opacityDefault = 1.0;
57744 function background(selection$$1) {
57746 function sortSources(a, b) {
57747 return a.best() && !b.best() ? -1
57748 : b.best() && !a.best() ? 1
57749 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
57753 function setOpacity(d) {
57754 var bg = context.container().selectAll('.layer-background')
57756 .style('opacity', d)
57757 .attr('data-opacity', d);
57759 if (!detected.opera) {
57760 utilSetTransform(bg, 0, 0);
57763 opacityList.selectAll('li')
57764 .classed('active', function(_) { return _ === d; });
57766 context.storage('background-opacity', d);
57770 function setTooltips(selection$$1) {
57771 selection$$1.each(function(d, i, nodes) {
57772 var item = select(this).select('label'),
57773 span = item.select('span'),
57774 placement = (i < nodes.length / 2) ? 'bottom' : 'top',
57775 description = d.description(),
57776 isOverflowing = (span.property('clientWidth') !== span.property('scrollWidth'));
57778 if (d === previous) {
57779 item.call(tooltip()
57780 .placement(placement)
57782 .title(function() {
57783 var tip = '<div>' + t('background.switch') + '</div>';
57784 return uiTooltipHtml(tip, uiCmd('⌘' + key));
57787 } else if (description || isOverflowing) {
57788 item.call(tooltip()
57789 .placement(placement)
57790 .title(description || d.name())
57793 item.call(tooltip().destroy);
57799 function selectLayer() {
57800 function active$$1(d) {
57801 return context.background().showsLayer(d);
57804 content.selectAll('.layer, .custom_layer')
57805 .classed('active', active$$1)
57806 .classed('switch', function(d) { return d === previous; })
57808 .selectAll('input')
57809 .property('checked', active$$1);
57813 function clickSetSource(d) {
57814 event.preventDefault();
57815 previous = context.background().baseLayerSource();
57816 context.background().baseLayerSource(d);
57818 document.activeElement.blur();
57822 function editCustom() {
57823 event.preventDefault();
57824 var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png';
57825 var template = window.prompt(
57826 t('background.custom_prompt', { example: example }),
57827 customSource.template() || example
57831 context.storage('background-custom-template', template);
57832 customTemplate = template;
57833 customSource.template(template);
57834 clickSetSource(customSource);
57841 function clickSetOverlay(d) {
57842 event.preventDefault();
57843 context.background().toggleOverlayLayer(d);
57845 document.activeElement.blur();
57849 function drawList(layerList, type, change, filter) {
57850 var sources = context.background()
57851 .sources(context.map().extent())
57854 var layerLinks = layerList.selectAll('li.layer')
57855 .data(sources, function(d) { return d.name(); });
57860 var enter = layerLinks.enter()
57861 .insert('li', '.custom_layer')
57862 .attr('class', 'layer')
57863 .classed('best', function(d) { return d.best(); });
57865 enter.filter(function(d) { return d.best(); })
57867 .attr('class', 'best')
57869 .title(t('background.best_imagery'))
57870 .placement((textDirection === 'rtl') ? 'right' : 'left'))
57879 .attr('type', type)
57880 .attr('name', 'layers')
57881 .on('change', change);
57885 .text(function(d) { return d.name(); });
57888 layerList.selectAll('li.layer')
57890 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
57894 function update() {
57895 backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
57896 overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
57903 function updateOffsetVal() {
57904 var meters = geoOffsetToMeters(context.background().offset()),
57905 x = +meters[0].toFixed(2),
57906 y = +meters[1].toFixed(2);
57908 selectAll('.nudge-inner-rect')
57910 .classed('error', false)
57911 .property('value', x + ', ' + y);
57913 selectAll('.nudge-reset')
57914 .classed('disabled', function() {
57915 return (x === 0 && y === 0);
57920 function resetOffset() {
57921 if (event.button !== 0) return;
57922 context.background().offset([0, 0]);
57927 function nudge(d) {
57928 context.background().nudge(d, context.map().zoom());
57933 function buttonOffset(d) {
57934 if (event.button !== 0) return;
57935 var timeout = window.setTimeout(function() {
57936 interval = window.setInterval(nudge.bind(null, d), 100);
57940 function doneNudge() {
57941 window.clearTimeout(timeout);
57942 window.clearInterval(interval);
57944 .on('mouseup.buttonoffset', null, true)
57945 .on('mousedown.buttonoffset', null, true);
57949 .on('mouseup.buttonoffset', doneNudge, true)
57950 .on('mousedown.buttonoffset', doneNudge, true);
57956 function inputOffset() {
57957 if (event.button !== 0) return;
57958 var input = select(this);
57959 var d = input.node().value;
57961 if (d === '') return resetOffset();
57963 d = d.replace(/;/g, ',').split(',').map(function(n) {
57964 // if n is NaN, it will always get mapped to false.
57965 return !isNaN(n) && n;
57968 if (d.length !== 2 || !d[0] || !d[1]) {
57969 input.classed('error', true);
57973 context.background().offset(geoMetersToOffset(d));
57978 function dragOffset() {
57979 if (event.button !== 0) return;
57980 var origin = [event.clientX, event.clientY];
57982 context.container()
57984 .attr('class', 'nudge-surface');
57987 .on('mousemove.offset', function() {
57988 var latest = [event.clientX, event.clientY];
57990 -(origin[0] - latest[0]) / 4,
57991 -(origin[1] - latest[1]) / 4
57997 .on('mouseup.offset', function() {
57998 if (event.button !== 0) return;
57999 selectAll('.nudge-surface')
58003 .on('mousemove.offset', null)
58004 .on('mouseup.offset', null);
58007 event.preventDefault();
58016 function toggle() {
58017 if (event) event.preventDefault();
58018 tooltipBehavior.hide(button);
58019 setVisible(!button.classed('active'));
58023 function quickSwitch() {
58025 clickSetSource(previous);
58030 function setVisible(show) {
58031 if (show !== shown) {
58032 button.classed('active', show);
58037 .on('mousedown.background-inside', function() {
58038 event.stopPropagation();
58042 .style('display', 'block')
58043 .style('right', '-300px')
58046 .style('right', '0px');
58048 content.selectAll('.layer, .custom_layer')
58049 .call(setTooltips);
58053 .style('display', 'block')
58054 .style('right', '0px')
58057 .style('right', '-300px')
58058 .on('end', function() {
58059 select(this).style('display', 'none');
58063 .on('mousedown.background-inside', null);
58069 var content = selection$$1
58071 .attr('class', 'fillL map-overlay col3 content hide'),
58072 tooltipBehavior = tooltip()
58073 .placement((textDirection === 'rtl') ? 'right' : 'left')
58075 .title(uiTooltipHtml(t('background.description'), key)),
58076 button = selection$$1
58078 .attr('tabindex', -1)
58079 .on('click', toggle)
58080 .call(svgIcon('#icon-layers', 'light'))
58081 .call(tooltipBehavior),
58085 /* opacity switcher */
58087 var opawrap = content
58089 .attr('class', 'opacity-options-wrapper');
58093 .text(t('background.title'));
58095 var opacityList = opawrap
58097 .attr('class', 'opacity-options');
58099 opacityList.selectAll('div.opacity')
58103 .attr('data-original-title', function(d) {
58104 return t('background.percent_brightness', { opacity: (d * 100) });
58106 .on('click.set-opacity', setOpacity)
58107 .html('<div class="select-box"></div>')
58109 .placement((textDirection === 'rtl') ? 'right' : 'left'))
58111 .attr('class', 'opacity')
58112 .style('opacity', function(d) { return 1.25 - d; });
58115 /* background switcher */
58117 var backgroundList = content
58119 .attr('class', 'layer-list')
58120 .attr('dir', 'auto');
58122 var custom = backgroundList
58124 .attr('class', 'custom_layer')
58125 .datum(customSource);
58129 .attr('class', 'layer-browse')
58131 .title(t('background.custom_button'))
58132 .placement((textDirection === 'rtl') ? 'right' : 'left'))
58133 .on('click', editCustom)
58134 .call(svgIcon('#icon-search'));
58141 .attr('type', 'radio')
58142 .attr('name', 'layers')
58143 .on('change', function () {
58144 if (customSource.template()) {
58145 clickSetSource(customSource);
58153 .text(t('background.custom'));
58157 .attr('class', 'imagery-faq')
58159 .attr('target', '_blank')
58160 .attr('tabindex', -1)
58161 .call(svgIcon('#icon-out-link', 'inline'))
58162 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
58164 .text(t('background.imagery_source_faq'));
58166 var overlayList = content
58168 .attr('class', 'layer-list');
58170 var controls = content
58172 .attr('class', 'controls-list');
58175 /* minimap toggle */
58177 var minimapLabel = controls
58181 .title(uiTooltipHtml(t('background.minimap.tooltip'), t('background.minimap.key')))
58186 .classed('minimap-toggle', true)
58188 .attr('type', 'checkbox')
58189 .on('change', function() {
58190 uiMapInMap.toggle();
58191 event.preventDefault();
58196 .text(t('background.minimap.description'));
58199 /* imagery offset controls */
58201 var adjustments = content
58203 .attr('class', 'adjustments');
58207 .text(t('background.fix_misalignment'))
58209 .classed('hide-toggle', true)
58210 .classed('expanded', false)
58211 .on('click', function() {
58212 if (event.button !== 0) return;
58213 var exp = select(this).classed('expanded');
58214 nudgeContainer.style('display', exp ? 'none' : 'block');
58215 select(this).classed('expanded', !exp);
58216 event.preventDefault();
58219 var nudgeContainer = adjustments
58221 .attr('class', 'nudge-container cf')
58222 .style('display', 'none');
58226 .attr('class', 'nudge-instructions')
58227 .text(t('background.offset'));
58229 var nudgeRect = nudgeContainer
58231 .attr('class', 'nudge-outer-rect')
58232 .on('mousedown', dragOffset);
58236 .attr('class', 'nudge-inner-rect')
58238 .on('change', inputOffset)
58239 .on('mousedown', function() {
58240 if (event.button !== 0) return;
58241 event.stopPropagation();
58246 .selectAll('button')
58247 .data(directions).enter()
58249 .attr('class', function(d) { return d[0] + ' nudge'; })
58250 .on('mousedown', function(d) {
58251 if (event.button !== 0) return;
58252 buttonOffset(d[1]);
58257 .attr('title', t('background.reset'))
58258 .attr('class', 'nudge-reset disabled')
58259 .on('click', resetOffset)
58261 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
58265 .on('move.background-update', lodash.debounce(update, 1000));
58267 context.background()
58268 .on('change.background-update', update);
58272 setOpacity(opacityDefault);
58274 var keybinding = d3keybinding('background')
58276 .on(uiCmd('⌘' + key), quickSwitch)
58277 .on([t('map_data.key'), t('help.key')], hide);
58282 context.surface().on('mousedown.background-outside', hide);
58283 context.container().on('mousedown.background-outside', hide);
58289 function uiContributors(context) {
58290 var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
58293 wrap = select(null);
58296 function update() {
58298 entities = context.intersects(context.map().extent());
58300 entities.forEach(function(entity) {
58301 if (entity && entity.user) users[entity.user] = true;
58304 var u = Object.keys(users),
58305 subset = u.slice(0, u.length > limit ? limit - 1 : limit);
58308 .call(svgIcon('#icon-nearby', 'pre-text light'));
58310 var userList = select(document.createElement('span'));
58312 userList.selectAll()
58316 .attr('class', 'user-link')
58317 .attr('href', function(d) { return context.connection().userURL(d); })
58318 .attr('target', '_blank')
58319 .attr('tabindex', -1)
58322 if (u.length > limit) {
58323 var count = select(document.createElement('span'));
58326 .attr('target', '_blank')
58327 .attr('tabindex', -1)
58328 .attr('href', function() {
58329 return context.connection().changesetsURL(context.map().center(), context.map().zoom());
58331 .text(u.length - limit + 1);
58333 wrap.append('span')
58334 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
58337 wrap.append('span')
58338 .html(t('contributors.list', { users: userList.html() }));
58345 .style('opacity', 0);
58347 } else if (hidden) {
58350 .style('opacity', 1);
58355 return function(selection$$1) {
58356 wrap = selection$$1;
58359 context.connection().on('loaded.contributors', debouncedUpdate);
58360 context.map().on('move.contributors', debouncedUpdate);
58364 function uiFeatureInfo(context) {
58365 function update(selection$$1) {
58366 var features = context.features(),
58367 stats = features.stats(),
58369 hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
58372 return String(stats[k]) + ' ' + t('feature.' + k + '.description');
58376 selection$$1.html('');
58378 if (hiddenList.length) {
58379 var tooltipBehavior = tooltip()
58382 .title(function() {
58383 return uiTooltipHtml(hiddenList.join('<br/>'));
58386 var warning = selection$$1.append('a')
58388 .attr('tabindex', -1)
58389 .html(t('feature_info.hidden_warning', { count: count }))
58390 .call(tooltipBehavior)
58391 .on('click', function() {
58392 tooltipBehavior.hide(warning);
58393 // open map data panel?
58394 event.preventDefault();
58399 .classed('hide', !hiddenList.length);
58403 return function(selection$$1) {
58404 update(selection$$1);
58406 context.features().on('change.feature_info', function() {
58407 update(selection$$1);
58412 function uiFullScreen(context) {
58413 var element = context.container().node(),
58414 keybinding = d3keybinding('full-screen');
58418 function getFullScreenFn() {
58419 if (element.requestFullscreen) {
58420 return element.requestFullscreen;
58421 } else if (element.msRequestFullscreen) {
58422 return element.msRequestFullscreen;
58423 } else if (element.mozRequestFullScreen) {
58424 return element.mozRequestFullScreen;
58425 } else if (element.webkitRequestFullscreen) {
58426 return element.webkitRequestFullscreen;
58431 function getExitFullScreenFn() {
58432 if (document.exitFullscreen) {
58433 return document.exitFullscreen;
58434 } else if (document.msExitFullscreen) {
58435 return document.msExitFullscreen;
58436 } else if (document.mozCancelFullScreen) {
58437 return document.mozCancelFullScreen;
58438 } else if (document.webkitExitFullscreen) {
58439 return document.webkitExitFullscreen;
58444 function isFullScreen() {
58445 return document.fullscreenElement ||
58446 document.mozFullScreenElement ||
58447 document.webkitFullscreenElement ||
58448 document.msFullscreenElement;
58452 function isSupported() {
58453 return !!getFullScreenFn();
58457 function fullScreen() {
58458 event.preventDefault();
58459 if (!isFullScreen()) {
58460 // button.classed('active', true);
58461 getFullScreenFn().apply(element);
58463 // button.classed('active', false);
58464 getExitFullScreenFn().apply(document);
58469 return function() { // selection) {
58470 if (!isSupported())
58473 // button = selection.append('button')
58474 // .attr('title', t('full_screen'))
58475 // .attr('tabindex', -1)
58476 // .on('click', fullScreen)
58479 // button.append('span')
58480 // .attr('class', 'icon full-screen');
58482 var detected = utilDetect();
58483 var keys$$1 = detected.os === 'mac' ? [uiCmd('⌃⌘F'), 'f11'] : ['f11'];
58484 keybinding.on(keys$$1, fullScreen);
58491 function uiModal(selection$$1, blocking) {
58492 var keybinding = d3keybinding('modal');
58493 var previous = selection$$1.select('div.modal');
58494 var animate = previous.empty();
58496 previous.transition()
58498 .style('opacity', 0)
58501 var shaded = selection$$1
58503 .attr('class', 'shaded')
58504 .style('opacity', 0);
58506 shaded.close = function() {
58510 .style('opacity',0)
58516 .style('top','0px');
58524 .attr('class', 'modal fillL col6');
58527 shaded.on('click.remove-modal', function() {
58528 if (event.target === this) {
58533 modal.append('button')
58534 .attr('class', 'close')
58535 .on('click', shaded.close)
58536 .call(svgIcon('#icon-close'));
58539 .on('⌫', shaded.close)
58540 .on('⎋', shaded.close);
58548 .attr('class', 'content');
58551 shaded.transition().style('opacity', 1);
58553 shaded.style('opacity', 1);
58560 function uiLoading(context) {
58566 var loading = function(selection) {
58567 modalSelection = uiModal(selection, blocking);
58569 var loadertext = modalSelection.select('.content')
58570 .classed('loading-modal', true)
58572 .attr('class', 'modal-section fillL');
58576 .attr('class', 'loader')
58577 .attr('src', context.imagePath('loader-white.gif'));
58583 modalSelection.select('button.close')
58584 .attr('class', 'hide');
58590 loading.message = function(_) {
58591 if (!arguments.length) return message;
58597 loading.blocking = function(_) {
58598 if (!arguments.length) return blocking;
58604 loading.close = function() {
58605 modalSelection.remove();
58612 function uiGeolocate(context) {
58613 var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
58614 locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
58619 if (context.inIntro()) return;
58620 context.enter(modeBrowse(context));
58621 context.container().call(locating);
58622 navigator.geolocation.getCurrentPosition(success, error, geoOptions);
58624 // This timeout ensures that we still call finish() even if
58625 // the user declines to share their location in Firefox
58626 timeoutId = setTimeout(finish, 10000 /* 10sec */ );
58630 function success(position) {
58631 var map = context.map(),
58632 extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
58633 .padByMeters(position.coords.accuracy);
58635 map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
58645 function finish() {
58646 locating.close(); // unblock ui
58647 if (timeoutId) { clearTimeout(timeoutId); }
58648 timeoutId = undefined;
58652 return function(selection) {
58653 if (!navigator.geolocation) return;
58657 .attr('tabindex', -1)
58658 .attr('title', t('geolocate.title'))
58659 .on('click', click)
58660 .call(svgIcon('#icon-geolocate', 'light'))
58662 .placement((textDirection === 'rtl') ? 'right' : 'left'));
58666 var marked = createCommonjsModule(function (module, exports) {
58668 * marked - a markdown parser
58669 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
58670 * https://github.com/chjj/marked
58676 * Block-Level Grammar
58681 code: /^( {4}[^\n]+\n*)+/,
58683 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
58684 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
58686 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
58687 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
58688 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
58689 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
58690 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
58692 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
58696 block.bullet = /(?:[*+-]|\d+\.)/;
58697 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
58698 block.item = replace(block.item, 'gm')
58699 (/bull/g, block.bullet)
58702 block.list = replace(block.list)
58703 (/bull/g, block.bullet)
58704 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
58705 ('def', '\\n+(?=' + block.def.source + ')')
58708 block.blockquote = replace(block.blockquote)
58712 block._tag = '(?!(?:'
58713 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
58714 + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
58715 + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
58717 block.html = replace(block.html)
58718 ('comment', /<!--[\s\S]*?-->/)
58719 ('closed', /<(tag)[\s\S]+?<\/\1>/)
58720 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
58721 (/tag/g, block._tag)
58724 block.paragraph = replace(block.paragraph)
58726 ('heading', block.heading)
58727 ('lheading', block.lheading)
58728 ('blockquote', block.blockquote)
58729 ('tag', '<' + block._tag)
58734 * Normal Block Grammar
58737 block.normal = merge({}, block);
58740 * GFM Block Grammar
58743 block.gfm = merge({}, block.normal, {
58744 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
58746 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
58749 block.gfm.paragraph = replace(block.paragraph)
58751 + block.gfm.fences.source.replace('\\1', '\\2') + '|'
58752 + block.list.source.replace('\\1', '\\3') + '|')
58756 * GFM + Tables Block Grammar
58759 block.tables = merge({}, block.gfm, {
58760 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
58761 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
58768 function Lexer(options) {
58770 this.tokens.links = {};
58771 this.options = options || marked.defaults;
58772 this.rules = block.normal;
58774 if (this.options.gfm) {
58775 if (this.options.tables) {
58776 this.rules = block.tables;
58778 this.rules = block.gfm;
58784 * Expose Block Rules
58787 Lexer.rules = block;
58790 * Static Lex Method
58793 Lexer.lex = function(src, options) {
58794 var lexer = new Lexer(options);
58795 return lexer.lex(src);
58802 Lexer.prototype.lex = function(src) {
58804 .replace(/\r\n|\r/g, '\n')
58805 .replace(/\t/g, ' ')
58806 .replace(/\u00a0/g, ' ')
58807 .replace(/\u2424/g, '\n');
58809 return this.token(src, true);
58816 Lexer.prototype.token = function(src, top, bq) {
58817 var src = src.replace(/^ +$/gm, '')
58830 if (cap = this.rules.newline.exec(src)) {
58831 src = src.substring(cap[0].length);
58832 if (cap[0].length > 1) {
58840 if (cap = this.rules.code.exec(src)) {
58841 src = src.substring(cap[0].length);
58842 cap = cap[0].replace(/^ {4}/gm, '');
58845 text: !this.options.pedantic
58846 ? cap.replace(/\n+$/, '')
58853 if (cap = this.rules.fences.exec(src)) {
58854 src = src.substring(cap[0].length);
58864 if (cap = this.rules.heading.exec(src)) {
58865 src = src.substring(cap[0].length);
58868 depth: cap[1].length,
58874 // table no leading pipe (gfm)
58875 if (top && (cap = this.rules.nptable.exec(src))) {
58876 src = src.substring(cap[0].length);
58880 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
58881 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
58882 cells: cap[3].replace(/\n$/, '').split('\n')
58885 for (i = 0; i < item.align.length; i++) {
58886 if (/^ *-+: *$/.test(item.align[i])) {
58887 item.align[i] = 'right';
58888 } else if (/^ *:-+: *$/.test(item.align[i])) {
58889 item.align[i] = 'center';
58890 } else if (/^ *:-+ *$/.test(item.align[i])) {
58891 item.align[i] = 'left';
58893 item.align[i] = null;
58897 for (i = 0; i < item.cells.length; i++) {
58898 item.cells[i] = item.cells[i].split(/ *\| */);
58901 this.tokens.push(item);
58907 if (cap = this.rules.lheading.exec(src)) {
58908 src = src.substring(cap[0].length);
58911 depth: cap[2] === '=' ? 1 : 2,
58918 if (cap = this.rules.hr.exec(src)) {
58919 src = src.substring(cap[0].length);
58927 if (cap = this.rules.blockquote.exec(src)) {
58928 src = src.substring(cap[0].length);
58931 type: 'blockquote_start'
58934 cap = cap[0].replace(/^ *> ?/gm, '');
58936 // Pass `top` to keep the current
58937 // "toplevel" state. This is exactly
58938 // how markdown.pl works.
58939 this.token(cap, top, true);
58942 type: 'blockquote_end'
58949 if (cap = this.rules.list.exec(src)) {
58950 src = src.substring(cap[0].length);
58954 type: 'list_start',
58955 ordered: bull.length > 1
58958 // Get each top-level item.
58959 cap = cap[0].match(this.rules.item);
58965 for (; i < l; i++) {
58968 // Remove the list item's bullet
58969 // so it is seen as the next token.
58970 space = item.length;
58971 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
58973 // Outdent whatever the
58974 // list item contains. Hacky.
58975 if (~item.indexOf('\n ')) {
58976 space -= item.length;
58977 item = !this.options.pedantic
58978 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
58979 : item.replace(/^ {1,4}/gm, '');
58982 // Determine whether the next list item belongs here.
58983 // Backpedal if it does not belong in this list.
58984 if (this.options.smartLists && i !== l - 1) {
58985 b = block.bullet.exec(cap[i + 1])[0];
58986 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
58987 src = cap.slice(i + 1).join('\n') + src;
58992 // Determine whether item is loose or not.
58993 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
58994 // for discount behavior.
58995 loose = next || /\n\n(?!\s*$)/.test(item);
58997 next = item.charAt(item.length - 1) === '\n';
58998 if (!loose) loose = next;
59003 ? 'loose_item_start'
59004 : 'list_item_start'
59008 this.token(item, false, bq);
59011 type: 'list_item_end'
59023 if (cap = this.rules.html.exec(src)) {
59024 src = src.substring(cap[0].length);
59026 type: this.options.sanitize
59029 pre: !this.options.sanitizer
59030 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
59037 if ((!bq && top) && (cap = this.rules.def.exec(src))) {
59038 src = src.substring(cap[0].length);
59039 this.tokens.links[cap[1].toLowerCase()] = {
59047 if (top && (cap = this.rules.table.exec(src))) {
59048 src = src.substring(cap[0].length);
59052 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
59053 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
59054 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
59057 for (i = 0; i < item.align.length; i++) {
59058 if (/^ *-+: *$/.test(item.align[i])) {
59059 item.align[i] = 'right';
59060 } else if (/^ *:-+: *$/.test(item.align[i])) {
59061 item.align[i] = 'center';
59062 } else if (/^ *:-+ *$/.test(item.align[i])) {
59063 item.align[i] = 'left';
59065 item.align[i] = null;
59069 for (i = 0; i < item.cells.length; i++) {
59070 item.cells[i] = item.cells[i]
59071 .replace(/^ *\| *| *\| *$/g, '')
59075 this.tokens.push(item);
59080 // top-level paragraph
59081 if (top && (cap = this.rules.paragraph.exec(src))) {
59082 src = src.substring(cap[0].length);
59085 text: cap[1].charAt(cap[1].length - 1) === '\n'
59086 ? cap[1].slice(0, -1)
59093 if (cap = this.rules.text.exec(src)) {
59094 // Top-level should never reach here.
59095 src = src.substring(cap[0].length);
59105 Error('Infinite loop on byte: ' + src.charCodeAt(0));
59109 return this.tokens;
59113 * Inline-Level Grammar
59117 escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
59118 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
59120 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
59121 link: /^!?\[(inside)\]\(href\)/,
59122 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
59123 nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
59124 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
59125 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
59126 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
59127 br: /^ {2,}\n(?!\s*$)/,
59129 text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
59132 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
59133 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
59135 inline.link = replace(inline.link)
59136 ('inside', inline._inside)
59137 ('href', inline._href)
59140 inline.reflink = replace(inline.reflink)
59141 ('inside', inline._inside)
59145 * Normal Inline Grammar
59148 inline.normal = merge({}, inline);
59151 * Pedantic Inline Grammar
59154 inline.pedantic = merge({}, inline.normal, {
59155 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
59156 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
59160 * GFM Inline Grammar
59163 inline.gfm = merge({}, inline.normal, {
59164 escape: replace(inline.escape)('])', '~|])')(),
59165 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
59166 del: /^~~(?=\S)([\s\S]*?\S)~~/,
59167 text: replace(inline.text)
59169 ('|', '|https?://|')
59174 * GFM + Line Breaks Inline Grammar
59177 inline.breaks = merge({}, inline.gfm, {
59178 br: replace(inline.br)('{2,}', '*')(),
59179 text: replace(inline.gfm.text)('{2,}', '*')()
59183 * Inline Lexer & Compiler
59186 function InlineLexer(links, options) {
59187 this.options = options || marked.defaults;
59188 this.links = links;
59189 this.rules = inline.normal;
59190 this.renderer = this.options.renderer || new Renderer;
59191 this.renderer.options = this.options;
59195 Error('Tokens array requires a `links` property.');
59198 if (this.options.gfm) {
59199 if (this.options.breaks) {
59200 this.rules = inline.breaks;
59202 this.rules = inline.gfm;
59204 } else if (this.options.pedantic) {
59205 this.rules = inline.pedantic;
59210 * Expose Inline Rules
59213 InlineLexer.rules = inline;
59216 * Static Lexing/Compiling Method
59219 InlineLexer.output = function(src, links, options) {
59220 var inline = new InlineLexer(links, options);
59221 return inline.output(src);
59228 InlineLexer.prototype.output = function(src) {
59237 if (cap = this.rules.escape.exec(src)) {
59238 src = src.substring(cap[0].length);
59244 if (cap = this.rules.autolink.exec(src)) {
59245 src = src.substring(cap[0].length);
59246 if (cap[2] === '@') {
59247 text = cap[1].charAt(6) === ':'
59248 ? this.mangle(cap[1].substring(7))
59249 : this.mangle(cap[1]);
59250 href = this.mangle('mailto:') + text;
59252 text = escape(cap[1]);
59255 out += this.renderer.link(href, null, text);
59260 if (!this.inLink && (cap = this.rules.url.exec(src))) {
59261 src = src.substring(cap[0].length);
59262 text = escape(cap[1]);
59264 out += this.renderer.link(href, null, text);
59269 if (cap = this.rules.tag.exec(src)) {
59270 if (!this.inLink && /^<a /i.test(cap[0])) {
59271 this.inLink = true;
59272 } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
59273 this.inLink = false;
59275 src = src.substring(cap[0].length);
59276 out += this.options.sanitize
59277 ? this.options.sanitizer
59278 ? this.options.sanitizer(cap[0])
59285 if (cap = this.rules.link.exec(src)) {
59286 src = src.substring(cap[0].length);
59287 this.inLink = true;
59288 out += this.outputLink(cap, {
59292 this.inLink = false;
59297 if ((cap = this.rules.reflink.exec(src))
59298 || (cap = this.rules.nolink.exec(src))) {
59299 src = src.substring(cap[0].length);
59300 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
59301 link = this.links[link.toLowerCase()];
59302 if (!link || !link.href) {
59303 out += cap[0].charAt(0);
59304 src = cap[0].substring(1) + src;
59307 this.inLink = true;
59308 out += this.outputLink(cap, link);
59309 this.inLink = false;
59314 if (cap = this.rules.strong.exec(src)) {
59315 src = src.substring(cap[0].length);
59316 out += this.renderer.strong(this.output(cap[2] || cap[1]));
59321 if (cap = this.rules.em.exec(src)) {
59322 src = src.substring(cap[0].length);
59323 out += this.renderer.em(this.output(cap[2] || cap[1]));
59328 if (cap = this.rules.code.exec(src)) {
59329 src = src.substring(cap[0].length);
59330 out += this.renderer.codespan(escape(cap[2], true));
59335 if (cap = this.rules.br.exec(src)) {
59336 src = src.substring(cap[0].length);
59337 out += this.renderer.br();
59342 if (cap = this.rules.del.exec(src)) {
59343 src = src.substring(cap[0].length);
59344 out += this.renderer.del(this.output(cap[1]));
59349 if (cap = this.rules.text.exec(src)) {
59350 src = src.substring(cap[0].length);
59351 out += this.renderer.text(escape(this.smartypants(cap[0])));
59357 Error('Infinite loop on byte: ' + src.charCodeAt(0));
59368 InlineLexer.prototype.outputLink = function(cap, link) {
59369 var href = escape(link.href)
59370 , title = link.title ? escape(link.title) : null;
59372 return cap[0].charAt(0) !== '!'
59373 ? this.renderer.link(href, title, this.output(cap[1]))
59374 : this.renderer.image(href, title, escape(cap[1]));
59378 * Smartypants Transformations
59381 InlineLexer.prototype.smartypants = function(text) {
59382 if (!this.options.smartypants) return text;
59385 .replace(/---/g, '\u2014')
59387 .replace(/--/g, '\u2013')
59389 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
59390 // closing singles & apostrophes
59391 .replace(/'/g, '\u2019')
59393 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
59395 .replace(/"/g, '\u201d')
59397 .replace(/\.{3}/g, '\u2026');
59404 InlineLexer.prototype.mangle = function(text) {
59405 if (!this.options.mangle) return text;
59411 for (; i < l; i++) {
59412 ch = text.charCodeAt(i);
59413 if (Math.random() > 0.5) {
59414 ch = 'x' + ch.toString(16);
59416 out += '&#' + ch + ';';
59426 function Renderer(options) {
59427 this.options = options || {};
59430 Renderer.prototype.code = function(code, lang, escaped) {
59431 if (this.options.highlight) {
59432 var out = this.options.highlight(code, lang);
59433 if (out != null && out !== code) {
59440 return '<pre><code>'
59441 + (escaped ? code : escape(code, true))
59442 + '\n</code></pre>';
59445 return '<pre><code class="'
59446 + this.options.langPrefix
59447 + escape(lang, true)
59449 + (escaped ? code : escape(code, true))
59450 + '\n</code></pre>\n';
59453 Renderer.prototype.blockquote = function(quote) {
59454 return '<blockquote>\n' + quote + '</blockquote>\n';
59457 Renderer.prototype.html = function(html) {
59461 Renderer.prototype.heading = function(text, level, raw) {
59465 + this.options.headerPrefix
59466 + raw.toLowerCase().replace(/[^\w]+/g, '-')
59474 Renderer.prototype.hr = function() {
59475 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
59478 Renderer.prototype.list = function(body, ordered) {
59479 var type = ordered ? 'ol' : 'ul';
59480 return '<' + type + '>\n' + body + '</' + type + '>\n';
59483 Renderer.prototype.listitem = function(text) {
59484 return '<li>' + text + '</li>\n';
59487 Renderer.prototype.paragraph = function(text) {
59488 return '<p>' + text + '</p>\n';
59491 Renderer.prototype.table = function(header, body) {
59502 Renderer.prototype.tablerow = function(content) {
59503 return '<tr>\n' + content + '</tr>\n';
59506 Renderer.prototype.tablecell = function(content, flags) {
59507 var type = flags.header ? 'th' : 'td';
59508 var tag = flags.align
59509 ? '<' + type + ' style="text-align:' + flags.align + '">'
59510 : '<' + type + '>';
59511 return tag + content + '</' + type + '>\n';
59514 // span level renderer
59515 Renderer.prototype.strong = function(text) {
59516 return '<strong>' + text + '</strong>';
59519 Renderer.prototype.em = function(text) {
59520 return '<em>' + text + '</em>';
59523 Renderer.prototype.codespan = function(text) {
59524 return '<code>' + text + '</code>';
59527 Renderer.prototype.br = function() {
59528 return this.options.xhtml ? '<br/>' : '<br>';
59531 Renderer.prototype.del = function(text) {
59532 return '<del>' + text + '</del>';
59535 Renderer.prototype.link = function(href, title, text) {
59536 if (this.options.sanitize) {
59538 var prot = decodeURIComponent(unescape(href))
59539 .replace(/[^\w:]/g, '')
59544 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
59548 var out = '<a href="' + href + '"';
59550 out += ' title="' + title + '"';
59552 out += '>' + text + '</a>';
59556 Renderer.prototype.image = function(href, title, text) {
59557 var out = '<img src="' + href + '" alt="' + text + '"';
59559 out += ' title="' + title + '"';
59561 out += this.options.xhtml ? '/>' : '>';
59565 Renderer.prototype.text = function(text) {
59570 * Parsing & Compiling
59573 function Parser(options) {
59576 this.options = options || marked.defaults;
59577 this.options.renderer = this.options.renderer || new Renderer;
59578 this.renderer = this.options.renderer;
59579 this.renderer.options = this.options;
59583 * Static Parse Method
59586 Parser.parse = function(src, options, renderer) {
59587 var parser = new Parser(options, renderer);
59588 return parser.parse(src);
59595 Parser.prototype.parse = function(src) {
59596 this.inline = new InlineLexer(src.links, this.options, this.renderer);
59597 this.tokens = src.reverse();
59600 while (this.next()) {
59611 Parser.prototype.next = function() {
59612 return this.token = this.tokens.pop();
59616 * Preview Next Token
59619 Parser.prototype.peek = function() {
59620 return this.tokens[this.tokens.length - 1] || 0;
59624 * Parse Text Tokens
59627 Parser.prototype.parseText = function() {
59628 var body = this.token.text;
59630 while (this.peek().type === 'text') {
59631 body += '\n' + this.next().text;
59634 return this.inline.output(body);
59638 * Parse Current Token
59641 Parser.prototype.tok = function() {
59642 switch (this.token.type) {
59647 return this.renderer.hr();
59650 return this.renderer.heading(
59651 this.inline.output(this.token.text),
59656 return this.renderer.code(this.token.text,
59658 this.token.escaped);
59671 for (i = 0; i < this.token.header.length; i++) {
59672 flags = { header: true, align: this.token.align[i] };
59673 cell += this.renderer.tablecell(
59674 this.inline.output(this.token.header[i]),
59675 { header: true, align: this.token.align[i] }
59678 header += this.renderer.tablerow(cell);
59680 for (i = 0; i < this.token.cells.length; i++) {
59681 row = this.token.cells[i];
59684 for (j = 0; j < row.length; j++) {
59685 cell += this.renderer.tablecell(
59686 this.inline.output(row[j]),
59687 { header: false, align: this.token.align[j] }
59691 body += this.renderer.tablerow(cell);
59693 return this.renderer.table(header, body);
59695 case 'blockquote_start': {
59698 while (this.next().type !== 'blockquote_end') {
59699 body += this.tok();
59702 return this.renderer.blockquote(body);
59704 case 'list_start': {
59706 , ordered = this.token.ordered;
59708 while (this.next().type !== 'list_end') {
59709 body += this.tok();
59712 return this.renderer.list(body, ordered);
59714 case 'list_item_start': {
59717 while (this.next().type !== 'list_item_end') {
59718 body += this.token.type === 'text'
59723 return this.renderer.listitem(body);
59725 case 'loose_item_start': {
59728 while (this.next().type !== 'list_item_end') {
59729 body += this.tok();
59732 return this.renderer.listitem(body);
59735 var html = !this.token.pre && !this.options.pedantic
59736 ? this.inline.output(this.token.text)
59738 return this.renderer.html(html);
59740 case 'paragraph': {
59741 return this.renderer.paragraph(this.inline.output(this.token.text));
59744 return this.renderer.paragraph(this.parseText());
59753 function escape(html, encode) {
59755 .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
59756 .replace(/</g, '<')
59757 .replace(/>/g, '>')
59758 .replace(/"/g, '"')
59759 .replace(/'/g, ''');
59762 function unescape(html) {
59763 // explicitly match decimal, hex, and named HTML entities
59764 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
59765 n = n.toLowerCase();
59766 if (n === 'colon') return ':';
59767 if (n.charAt(0) === '#') {
59768 return n.charAt(1) === 'x'
59769 ? String.fromCharCode(parseInt(n.substring(2), 16))
59770 : String.fromCharCode(+n.substring(1));
59776 function replace(regex, opt) {
59777 regex = regex.source;
59779 return function self(name, val) {
59780 if (!name) return new RegExp(regex, opt);
59781 val = val.source || val;
59782 val = val.replace(/(^|[^\[])\^/g, '$1');
59783 regex = regex.replace(name, val);
59791 function merge(obj) {
59796 for (; i < arguments.length; i++) {
59797 target = arguments[i];
59798 for (key in target) {
59799 if (Object.prototype.hasOwnProperty.call(target, key)) {
59800 obj[key] = target[key];
59813 function marked(src, opt, callback) {
59814 if (callback || typeof opt === 'function') {
59820 opt = merge({}, marked.defaults, opt || {});
59822 var highlight = opt.highlight
59828 tokens = Lexer.lex(src, opt);
59830 return callback(e);
59833 pending = tokens.length;
59835 var done = function(err) {
59837 opt.highlight = highlight;
59838 return callback(err);
59844 out = Parser.parse(tokens, opt);
59849 opt.highlight = highlight;
59853 : callback(null, out);
59856 if (!highlight || highlight.length < 3) {
59860 delete opt.highlight;
59862 if (!pending) return done();
59864 for (; i < tokens.length; i++) {
59866 if (token.type !== 'code') {
59867 return --pending || done();
59869 return highlight(token.text, token.lang, function(err, code) {
59870 if (err) return done(err);
59871 if (code == null || code === token.text) {
59872 return --pending || done();
59875 token.escaped = true;
59876 --pending || done();
59884 if (opt) opt = merge({}, marked.defaults, opt);
59885 return Parser.parse(Lexer.lex(src, opt), opt);
59887 e.message += '\nPlease report this to https://github.com/chjj/marked.';
59888 if ((opt || marked.defaults).silent) {
59889 return '<p>An error occured:</p><pre>'
59890 + escape(e.message + '', true)
59902 marked.setOptions = function(opt) {
59903 merge(marked.defaults, opt);
59907 marked.defaults = {
59918 langPrefix: 'lang-',
59919 smartypants: false,
59921 renderer: new Renderer,
59929 marked.Parser = Parser;
59930 marked.parser = Parser.parse;
59932 marked.Renderer = Renderer;
59934 marked.Lexer = Lexer;
59935 marked.lexer = Lexer.lex;
59937 marked.InlineLexer = InlineLexer;
59938 marked.inlineLexer = InlineLexer.output;
59940 marked.parse = marked;
59943 module.exports = marked;
59946 }).call(function() {
59947 return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
59951 function pointBox(loc, context) {
59952 var rect = context.surfaceRect();
59953 var point = context.curtainProjection(loc);
59955 left: point[0] + rect.left - 40,
59956 top: point[1] + rect.top - 60,
59963 function pad$1(locOrBox, padding, context) {
59965 if (locOrBox instanceof Array) {
59966 var rect = context.surfaceRect();
59967 var point = context.curtainProjection(locOrBox);
59969 left: point[0] + rect.left,
59970 top: point[1] + rect.top
59977 left: box.left - padding,
59978 top: box.top - padding,
59979 width: (box.width || 0) + 2 * padding,
59980 height: (box.width || 0) + 2 * padding
59985 function icon(name, svgklass) {
59986 return '<svg class="icon ' + (svgklass || '') + '">' +
59987 '<use xlink:href="' + name + '"></use></svg>';
59991 function slugify(text$$1) {
59992 return text$$1.toString().toLowerCase()
59993 .replace(/\s+/g, '-') // Replace spaces with -
59994 .replace(/[^\w\-]+/g, '') // Remove all non-word chars
59995 .replace(/\-\-+/g, '-') // Replace multiple - with single -
59996 .replace(/^-+/, '') // Trim - from start of text
59997 .replace(/-+$/, ''); // Trim - from end of text
60001 // console warning for missing walkthrough names
60002 var missingStrings = {};
60003 function checkKey(key, text$$1) {
60004 if (t(key, { default: undefined}) === undefined) {
60005 if (missingStrings.hasOwnProperty(key)) return; // warn once
60006 missingStrings[key] = text$$1;
60007 var missing = key + ': ' + text$$1;
60008 if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line
60013 function localize(obj) {
60016 // Assign name if entity has one..
60017 var name = obj.tags && obj.tags.name;
60019 key = 'intro.graph.name.' + slugify(name);
60020 obj.tags.name = t(key, { default: name });
60021 checkKey(key, name);
60024 // Assign street name if entity has one..
60025 var street = obj.tags && obj.tags['addr:street'];
60027 key = 'intro.graph.name.' + slugify(street);
60028 obj.tags['addr:street'] = t(key, { default: street });
60029 checkKey(key, street);
60031 // Add address details common across walkthrough..
60033 'block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood',
60034 'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb'
60036 addrTags.forEach(function(k) {
60037 var key = 'intro.graph.' + k,
60039 val = obj.tags && obj.tags[tag],
60040 str = t(key, { default: val });
60043 if (str.match(/^<.*>$/) !== null) {
60044 delete obj.tags[tag];
60046 obj.tags[tag] = str;
60056 // Used to detect squareness.. some duplicataion of code from actionOrthogonalize.
60057 function isMostlySquare(points) {
60058 // note: uses 15 here instead of the 12 from actionOrthogonalize because
60059 // actionOrthogonalize can actually straighten some larger angles as it iterates
60060 var threshold$$1 = 15, // degrees within right or straight
60061 lowerBound = Math.cos((90 - threshold$$1) * Math.PI / 180), // near right
60062 upperBound = Math.cos(threshold$$1 * Math.PI / 180), // near straight
60065 for (var i = 0; i < points.length; i++) {
60066 mag = Math.abs(normalizedDotProduct(i, points));
60067 if (mag > lowerBound && mag < upperBound) {
60075 function normalizedDotProduct(i, points) {
60076 var a = points[(i - 1 + points.length) % points.length],
60078 c = points[(i + 1) % points.length],
60079 p = subtractPoints(a, b),
60080 q = subtractPoints(c, b);
60082 p = normalizePoint(p);
60083 q = normalizePoint(q);
60085 return p[0] * q[0] + p[1] * q[1];
60088 function subtractPoints(a, b) {
60089 return [a[0] - b[0], a[1] - b[1]];
60092 function normalizePoint(point) {
60093 var vector = [0, 0];
60094 var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
60095 if (length !== 0) {
60096 vector[0] = point[0] / length;
60097 vector[1] = point[1] / length;
60105 function selectMenuItem(operation) {
60106 var selector$$1 = '.edit-menu .edit-menu-item-' + operation +
60107 ', .radial-menu .radial-menu-item-' + operation;
60108 return select(selector$$1);
60112 function transitionTime(point1, point2) {
60113 var distance$$1 = geoSphericalDistance(point1, point2);
60114 if (distance$$1 === 0)
60116 else if (distance$$1 < 80)
60122 var dataIntroGraph = {"n1":{"id":"n1","loc":[-85.631039,41.948829]},"n10":{"id":"n10","loc":[-85.634733,41.941588]},"n100":{"id":"n100","loc":[-85.637395,41.942252]},"n1000":{"id":"n1000","loc":[-85.632699,41.944763]},"n1001":{"id":"n1001","loc":[-85.632685,41.944763]},"n1002":{"id":"n1002","loc":[-85.632673,41.944755]},"n1003":{"id":"n1003","loc":[-85.632595,41.944682]},"n1004":{"id":"n1004","loc":[-85.632576,41.944673]},"n1005":{"id":"n1005","loc":[-85.632551,41.944667]},"n1006":{"id":"n1006","loc":[-85.63253,41.944667]},"n1007":{"id":"n1007","loc":[-85.632502,41.944669]},"n1008":{"id":"n1008","loc":[-85.632483,41.944677]},"n1009":{"id":"n1009","loc":[-85.632383,41.944731]},"n101":{"id":"n101","loc":[-85.637357,41.942252]},"n1010":{"id":"n1010","loc":[-85.63349,41.944976],"tags":{"addr:city":"Three Rivers","addr:housenumber":"31","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Sherwin-Williams","shop":"paint"}},"n1011":{"id":"n1011","loc":[-85.633548,41.945034],"tags":{"addr:city":"Three Rivers","addr:housenumber":"33","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Unique Jewelry","shop":"jewelry"}},"n1012":{"id":"n1012","loc":[-85.633683,41.945129],"tags":{"addr:city":"Three Rivers","addr:housenumber":"37","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"World Fare","shop":"gift"}},"n1013":{"id":"n1013","loc":[-85.634563,41.945469],"tags":{"addr:city":"Three Rivers","addr:housenumber":"62","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Golden Finch Framing","shop":"frame"}},"n1014":{"id":"n1014","loc":[-85.634469,41.945379],"tags":{"addr:city":"Three Rivers","addr:housenumber":"58","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Dollar Tree","shop":"second_hand"}},"n1015":{"id":"n1015","loc":[-85.634227,41.945159],"tags":{"addr:city":"Three Rivers","addr:housenumber":"48","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","amenity":"theatre","name":"Riviera Theatre"}},"n1016":{"id":"n1016","loc":[-85.634057,41.945012],"tags":{"addr:city":"Three Rivers","addr:housenumber":"42","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"River City Appliance","shop":"appliance"}},"n1017":{"id":"n1017","loc":[-85.633879,41.945325],"tags":{"addr:city":"Three Rivers","addr:housenumber":"45","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Paparazzi Tattoo","shop":"tattoo"}},"n1018":{"id":"n1018","loc":[-85.634914,41.945839],"tags":{"addr:city":"Three Rivers","addr:housenumber":"88","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","amenity":"bank","name":"Southern Michigan Bank"}},"n1019":{"id":"n1019","loc":[-85.634514,41.946176]},"n102":{"id":"n102","loc":[-85.637357,41.942216]},"n1020":{"id":"n1020","loc":[-85.634087,41.946178]},"n1021":{"id":"n1021","loc":[-85.634357,41.945805]},"n1022":{"id":"n1022","loc":[-85.634389,41.945788]},"n1023":{"id":"n1023","loc":[-85.634491,41.94581]},"n1024":{"id":"n1024","loc":[-85.634513,41.945853]},"n1025":{"id":"n1025","loc":[-85.634506,41.94583]},"n1026":{"id":"n1026","loc":[-85.634762,41.946056],"tags":{"crossing":"zebra","highway":"crossing"}},"n1027":{"id":"n1027","loc":[-85.634767,41.946172]},"n1028":{"id":"n1028","loc":[-85.634622,41.946175],"tags":{"crossing":"zebra","highway":"crossing"}},"n1029":{"id":"n1029","loc":[-85.640655,41.942057]},"n103":{"id":"n103","loc":[-85.637386,41.942054]},"n1030":{"id":"n1030","loc":[-85.640947,41.942057]},"n1031":{"id":"n1031","loc":[-85.640957,41.942593]},"n1032":{"id":"n1032","loc":[-85.630953,41.960873]},"n1033":{"id":"n1033","loc":[-85.632174,41.960679]},"n1034":{"id":"n1034","loc":[-85.638785,41.943066]},"n1035":{"id":"n1035","loc":[-85.638853,41.943065]},"n1036":{"id":"n1036","loc":[-85.638855,41.943183]},"n1037":{"id":"n1037","loc":[-85.638552,41.943189]},"n1038":{"id":"n1038","loc":[-85.63855,41.943149]},"n1039":{"id":"n1039","loc":[-85.638638,41.943068]},"n104":{"id":"n104","loc":[-85.637387,41.942125]},"n1040":{"id":"n1040","loc":[-85.638638,41.943078]},"n1041":{"id":"n1041","loc":[-85.638813,41.943163]},"n1042":{"id":"n1042","loc":[-85.638684,41.943165]},"n1043":{"id":"n1043","loc":[-85.638682,41.943105]},"n1044":{"id":"n1044","loc":[-85.638706,41.943105]},"n1045":{"id":"n1045","loc":[-85.638707,41.943117]},"n1046":{"id":"n1046","loc":[-85.638812,41.943115]},"n1047":{"id":"n1047","loc":[-85.638769,41.943407]},"n1048":{"id":"n1048","loc":[-85.638549,41.943407]},"n1049":{"id":"n1049","loc":[-85.638567,41.943555]},"n105":{"id":"n105","loc":[-85.637319,41.942125]},"n1050":{"id":"n1050","loc":[-85.638426,41.943554]},"n1051":{"id":"n1051","loc":[-85.638427,41.94346]},"n1052":{"id":"n1052","loc":[-85.638568,41.943461]},"n1053":{"id":"n1053","loc":[-85.639264,41.943415]},"n1054":{"id":"n1054","loc":[-85.639082,41.943417]},"n1055":{"id":"n1055","loc":[-85.63908,41.943331]},"n1056":{"id":"n1056","loc":[-85.639136,41.94333]},"n1057":{"id":"n1057","loc":[-85.639158,41.943312]},"n1058":{"id":"n1058","loc":[-85.639188,41.943313]},"n1059":{"id":"n1059","loc":[-85.639211,41.943331]},"n106":{"id":"n106","loc":[-85.637319,41.942137]},"n1060":{"id":"n1060","loc":[-85.639262,41.943331]},"n1061":{"id":"n1061","loc":[-85.638986,41.943515]},"n1062":{"id":"n1062","loc":[-85.63888,41.943521]},"n1063":{"id":"n1063","loc":[-85.638871,41.943436]},"n1064":{"id":"n1064","loc":[-85.638958,41.943431]},"n1065":{"id":"n1065","loc":[-85.638979,41.943443]},"n1066":{"id":"n1066","loc":[-85.63926,41.943703]},"n1067":{"id":"n1067","loc":[-85.639152,41.943704]},"n1068":{"id":"n1068","loc":[-85.639152,41.943691]},"n1069":{"id":"n1069","loc":[-85.639063,41.943691]},"n107":{"id":"n107","loc":[-85.637259,41.942137]},"n1070":{"id":"n1070","loc":[-85.639062,41.943613]},"n1071":{"id":"n1071","loc":[-85.639259,41.943611]},"n1072":{"id":"n1072","loc":[-85.639117,41.943726]},"n1073":{"id":"n1073","loc":[-85.639118,41.943767]},"n1074":{"id":"n1074","loc":[-85.639051,41.943768]},"n1075":{"id":"n1075","loc":[-85.63905,41.943727]},"n1076":{"id":"n1076","loc":[-85.638627,41.943716]},"n1077":{"id":"n1077","loc":[-85.63863,41.943634]},"n1078":{"id":"n1078","loc":[-85.63844,41.943631]},"n1079":{"id":"n1079","loc":[-85.638437,41.943729]},"n108":{"id":"n108","loc":[-85.637259,41.942126]},"n1080":{"id":"n1080","loc":[-85.638533,41.94373]},"n1081":{"id":"n1081","loc":[-85.638534,41.943715]},"n1082":{"id":"n1082","loc":[-85.638678,41.943941]},"n1083":{"id":"n1083","loc":[-85.638522,41.943944]},"n1084":{"id":"n1084","loc":[-85.63852,41.943864]},"n1085":{"id":"n1085","loc":[-85.638676,41.943861]},"n1086":{"id":"n1086","loc":[-85.638663,41.944059]},"n1087":{"id":"n1087","loc":[-85.638513,41.944061]},"n1088":{"id":"n1088","loc":[-85.638511,41.943991]},"n1089":{"id":"n1089","loc":[-85.638661,41.943989]},"n109":{"id":"n109","loc":[-85.637193,41.942126]},"n1090":{"id":"n1090","loc":[-85.63865,41.944134]},"n1091":{"id":"n1091","loc":[-85.638429,41.944144]},"n1092":{"id":"n1092","loc":[-85.638426,41.944106]},"n1093":{"id":"n1093","loc":[-85.638476,41.944104]},"n1094":{"id":"n1094","loc":[-85.638475,41.94409]},"n1095":{"id":"n1095","loc":[-85.638594,41.944084]},"n1096":{"id":"n1096","loc":[-85.638595,41.944101]},"n1097":{"id":"n1097","loc":[-85.638647,41.944099]},"n1098":{"id":"n1098","loc":[-85.63829,41.944154]},"n1099":{"id":"n1099","loc":[-85.638558,41.944155]},"n11":{"id":"n11","loc":[-85.634602,41.941523]},"n110":{"id":"n110","loc":[-85.637192,41.942053]},"n1100":{"id":"n1100","loc":[-85.638558,41.944338]},"n1101":{"id":"n1101","loc":[-85.638851,41.944408]},"n1102":{"id":"n1102","loc":[-85.637771,41.943989]},"n1103":{"id":"n1103","loc":[-85.639345,41.943964]},"n1104":{"id":"n1104","loc":[-85.638515,41.94397]},"n1105":{"id":"n1105","loc":[-85.639256,41.943928]},"n1106":{"id":"n1106","loc":[-85.639157,41.943929]},"n1107":{"id":"n1107","loc":[-85.639156,41.9439]},"n1108":{"id":"n1108","loc":[-85.639118,41.9439]},"n1109":{"id":"n1109","loc":[-85.639116,41.94382]},"n111":{"id":"n111","loc":[-85.637248,41.942053]},"n1110":{"id":"n1110","loc":[-85.639202,41.943819]},"n1111":{"id":"n1111","loc":[-85.639202,41.943837]},"n1112":{"id":"n1112","loc":[-85.639293,41.943836]},"n1113":{"id":"n1113","loc":[-85.639295,41.943898]},"n1114":{"id":"n1114","loc":[-85.639255,41.943898]},"n1115":{"id":"n1115","loc":[-85.639296,41.944083]},"n1116":{"id":"n1116","loc":[-85.639144,41.944084]},"n1117":{"id":"n1117","loc":[-85.639143,41.944026]},"n1118":{"id":"n1118","loc":[-85.639162,41.944026]},"n1119":{"id":"n1119","loc":[-85.639162,41.944]},"n112":{"id":"n112","loc":[-85.637248,41.942042]},"n1120":{"id":"n1120","loc":[-85.639295,41.943999]},"n1121":{"id":"n1121","loc":[-85.639131,41.944139]},"n1122":{"id":"n1122","loc":[-85.63901,41.94414]},"n1123":{"id":"n1123","loc":[-85.63901,41.944076]},"n1124":{"id":"n1124","loc":[-85.63913,41.944075]},"n1125":{"id":"n1125","loc":[-85.639092,41.944155]},"n1126":{"id":"n1126","loc":[-85.639093,41.944308]},"n1127":{"id":"n1127","loc":[-85.639225,41.944308]},"n1128":{"id":"n1128","loc":[-85.639225,41.94429]},"n1129":{"id":"n1129","loc":[-85.639253,41.944289]},"n113":{"id":"n113","loc":[-85.637338,41.942041]},"n1130":{"id":"n1130","loc":[-85.639253,41.944269]},"n1131":{"id":"n1131","loc":[-85.639243,41.944269]},"n1132":{"id":"n1132","loc":[-85.639243,41.944229]},"n1133":{"id":"n1133","loc":[-85.639224,41.944229]},"n1134":{"id":"n1134","loc":[-85.639224,41.944196]},"n1135":{"id":"n1135","loc":[-85.639195,41.944196]},"n1136":{"id":"n1136","loc":[-85.639195,41.944155]},"n1137":{"id":"n1137","loc":[-85.639072,41.944154]},"n1138":{"id":"n1138","loc":[-85.638865,41.944154]},"n1139":{"id":"n1139","loc":[-85.638863,41.943967]},"n114":{"id":"n114","loc":[-85.637338,41.942055]},"n1140":{"id":"n1140","loc":[-85.6386,41.942698]},"n1141":{"id":"n1141","loc":[-85.639348,41.942698]},"n1142":{"id":"n1142","loc":[-85.639377,41.944984]},"n1143":{"id":"n1143","loc":[-85.63937,41.945013]},"n1144":{"id":"n1144","loc":[-85.639357,41.945033]},"n1145":{"id":"n1145","loc":[-85.639353,41.945053]},"n1146":{"id":"n1146","loc":[-85.639352,41.945084]},"n1147":{"id":"n1147","loc":[-85.638278,41.945516]},"n1148":{"id":"n1148","loc":[-85.637505,41.945801]},"n1149":{"id":"n1149","loc":[-85.637327,41.945857]},"n115":{"id":"n115","loc":[-85.637583,41.941943]},"n1150":{"id":"n1150","loc":[-85.637168,41.945899]},"n1151":{"id":"n1151","loc":[-85.637017,41.94593]},"n1152":{"id":"n1152","loc":[-85.637185,41.945938]},"n1153":{"id":"n1153","loc":[-85.63682,41.945963]},"n1154":{"id":"n1154","loc":[-85.636639,41.945984]},"n1155":{"id":"n1155","loc":[-85.636439,41.945999]},"n1156":{"id":"n1156","loc":[-85.635801,41.945999]},"n1157":{"id":"n1157","loc":[-85.635769,41.945908]},"n1158":{"id":"n1158","loc":[-85.635953,41.946154]},"n1159":{"id":"n1159","loc":[-85.635472,41.94598]},"n116":{"id":"n116","loc":[-85.637584,41.941983]},"n1160":{"id":"n1160","loc":[-85.635409,41.945981]},"n1161":{"id":"n1161","loc":[-85.635583,41.945987]},"n1162":{"id":"n1162","loc":[-85.636452,41.945805]},"n1163":{"id":"n1163","loc":[-85.636425,41.94582]},"n1164":{"id":"n1164","loc":[-85.636396,41.945817]},"n1165":{"id":"n1165","loc":[-85.636368,41.945797]},"n1166":{"id":"n1166","loc":[-85.636346,41.945767]},"n1167":{"id":"n1167","loc":[-85.636307,41.945745]},"n1168":{"id":"n1168","loc":[-85.636194,41.94565]},"n1169":{"id":"n1169","loc":[-85.636121,41.945579]},"n117":{"id":"n117","loc":[-85.63751,41.941983]},"n1170":{"id":"n1170","loc":[-85.635995,41.945432]},"n1171":{"id":"n1171","loc":[-85.637564,41.943538]},"n1172":{"id":"n1172","loc":[-85.63756,41.943505]},"n1173":{"id":"n1173","loc":[-85.637435,41.943489]},"n1174":{"id":"n1174","loc":[-85.637093,41.943556]},"n1175":{"id":"n1175","loc":[-85.634836,41.941574]},"n1176":{"id":"n1176","loc":[-85.634692,41.9415]},"n1177":{"id":"n1177","loc":[-85.634261,41.941337]},"n1178":{"id":"n1178","loc":[-85.634208,41.940962]},"n1179":{"id":"n1179","loc":[-85.635247,41.940968]},"n118":{"id":"n118","loc":[-85.637509,41.941944]},"n1180":{"id":"n1180","loc":[-85.63514,41.941205]},"n1181":{"id":"n1181","loc":[-85.634858,41.941511]},"n1182":{"id":"n1182","loc":[-85.630725,41.943465]},"n1183":{"id":"n1183","loc":[-85.632591,41.942826]},"n1184":{"id":"n1184","loc":[-85.634487,41.941928]},"n1185":{"id":"n1185","loc":[-85.634499,41.942056]},"n1186":{"id":"n1186","loc":[-85.63433,41.943102]},"n1187":{"id":"n1187","loc":[-85.634158,41.943151]},"n1188":{"id":"n1188","loc":[-85.634107,41.94305]},"n1189":{"id":"n1189","loc":[-85.634279,41.943002]},"n119":{"id":"n119","loc":[-85.637724,41.941973]},"n1190":{"id":"n1190","loc":[-85.634362,41.943762]},"n1191":{"id":"n1191","loc":[-85.634331,41.943731]},"n1192":{"id":"n1192","loc":[-85.634396,41.943695]},"n1193":{"id":"n1193","loc":[-85.634426,41.943726]},"n1194":{"id":"n1194","loc":[-85.621569,41.956021]},"n1195":{"id":"n1195","loc":[-85.621574,41.956164]},"n1196":{"id":"n1196","loc":[-85.621489,41.956165]},"n1197":{"id":"n1197","loc":[-85.621488,41.956136]},"n1198":{"id":"n1198","loc":[-85.621372,41.956139]},"n1199":{"id":"n1199","loc":[-85.621369,41.956049]},"n12":{"id":"n12","loc":[-85.63359,41.941093]},"n120":{"id":"n120","loc":[-85.637633,41.941973]},"n1200":{"id":"n1200","loc":[-85.621493,41.956047]},"n1201":{"id":"n1201","loc":[-85.621492,41.956022]},"n1202":{"id":"n1202","loc":[-85.619744,41.953192]},"n1203":{"id":"n1203","loc":[-85.619059,41.953902]},"n1204":{"id":"n1204","loc":[-85.623984,41.95469]},"n1205":{"id":"n1205","loc":[-85.630159,41.958208]},"n1206":{"id":"n1206","loc":[-85.63002,41.958208]},"n1207":{"id":"n1207","loc":[-85.630021,41.95814]},"n1208":{"id":"n1208","loc":[-85.63,41.95814]},"n1209":{"id":"n1209","loc":[-85.63,41.958043]},"n121":{"id":"n121","loc":[-85.637633,41.941853]},"n1210":{"id":"n1210","loc":[-85.630159,41.958043]},"n1211":{"id":"n1211","loc":[-85.630304,41.957566]},"n1212":{"id":"n1212","loc":[-85.630303,41.957684]},"n1213":{"id":"n1213","loc":[-85.630073,41.957683]},"n1214":{"id":"n1214","loc":[-85.630072,41.957721]},"n1215":{"id":"n1215","loc":[-85.629993,41.95772]},"n1216":{"id":"n1216","loc":[-85.629993,41.95768]},"n1217":{"id":"n1217","loc":[-85.629968,41.95768]},"n1218":{"id":"n1218","loc":[-85.629969,41.957588]},"n1219":{"id":"n1219","loc":[-85.630219,41.95759]},"n122":{"id":"n122","loc":[-85.637724,41.941853]},"n1220":{"id":"n1220","loc":[-85.630219,41.957566]},"n1221":{"id":"n1221","loc":[-85.630717,41.957744]},"n1222":{"id":"n1222","loc":[-85.630596,41.957745]},"n1223":{"id":"n1223","loc":[-85.630598,41.957553]},"n1224":{"id":"n1224","loc":[-85.630717,41.957555]},"n1225":{"id":"n1225","loc":[-85.630609,41.957745]},"n1226":{"id":"n1226","loc":[-85.63061,41.957789]},"n1227":{"id":"n1227","loc":[-85.630327,41.957791]},"n1228":{"id":"n1228","loc":[-85.630324,41.95752]},"n1229":{"id":"n1229","loc":[-85.630325,41.95756]},"n123":{"id":"n123","loc":[-85.637773,41.941988]},"n1230":{"id":"n1230","loc":[-85.63057,41.95756]},"n1231":{"id":"n1231","loc":[-85.63069,41.958016]},"n1232":{"id":"n1232","loc":[-85.630586,41.958017]},"n1233":{"id":"n1233","loc":[-85.630584,41.957956]},"n1234":{"id":"n1234","loc":[-85.630614,41.957956]},"n1235":{"id":"n1235","loc":[-85.630611,41.957835]},"n1236":{"id":"n1236","loc":[-85.630737,41.957833]},"n1237":{"id":"n1237","loc":[-85.630739,41.957921]},"n1238":{"id":"n1238","loc":[-85.630688,41.957922]},"n1239":{"id":"n1239","loc":[-85.630719,41.958291]},"n124":{"id":"n124","loc":[-85.637773,41.942046]},"n1240":{"id":"n1240","loc":[-85.630592,41.958291]},"n1241":{"id":"n1241","loc":[-85.630593,41.958108]},"n1242":{"id":"n1242","loc":[-85.630701,41.958109]},"n1243":{"id":"n1243","loc":[-85.6307,41.958173]},"n1244":{"id":"n1244","loc":[-85.630711,41.958173]},"n1245":{"id":"n1245","loc":[-85.630711,41.958233]},"n1246":{"id":"n1246","loc":[-85.630719,41.958233]},"n1247":{"id":"n1247","loc":[-85.630523,41.958329]},"n1248":{"id":"n1248","loc":[-85.630388,41.958329]},"n1249":{"id":"n1249","loc":[-85.630387,41.958262]},"n125":{"id":"n125","loc":[-85.637693,41.942047]},"n1250":{"id":"n1250","loc":[-85.630523,41.958261]},"n1251":{"id":"n1251","loc":[-85.63072,41.958636]},"n1252":{"id":"n1252","loc":[-85.630721,41.958709]},"n1253":{"id":"n1253","loc":[-85.630503,41.958712]},"n1254":{"id":"n1254","loc":[-85.630498,41.958511]},"n1255":{"id":"n1255","loc":[-85.630635,41.95851]},"n1256":{"id":"n1256","loc":[-85.630638,41.958636]},"n1257":{"id":"n1257","loc":[-85.630437,41.958822]},"n1258":{"id":"n1258","loc":[-85.630437,41.958849]},"n1259":{"id":"n1259","loc":[-85.630393,41.958849]},"n126":{"id":"n126","loc":[-85.637692,41.941988]},"n1260":{"id":"n1260","loc":[-85.630393,41.958822]},"n1261":{"id":"n1261","loc":[-85.630605,41.959102]},"n1262":{"id":"n1262","loc":[-85.63049,41.959104]},"n1263":{"id":"n1263","loc":[-85.630487,41.958996]},"n1264":{"id":"n1264","loc":[-85.630462,41.958996]},"n1265":{"id":"n1265","loc":[-85.63046,41.958922]},"n1266":{"id":"n1266","loc":[-85.630562,41.958921]},"n1267":{"id":"n1267","loc":[-85.630564,41.958992]},"n1268":{"id":"n1268","loc":[-85.630602,41.958992]},"n1269":{"id":"n1269","loc":[-85.630126,41.957096]},"n127":{"id":"n127","loc":[-85.637604,41.941994]},"n1270":{"id":"n1270","loc":[-85.630129,41.957283]},"n1271":{"id":"n1271","loc":[-85.629993,41.957284]},"n1272":{"id":"n1272","loc":[-85.629992,41.957216]},"n1273":{"id":"n1273","loc":[-85.630015,41.957215]},"n1274":{"id":"n1274","loc":[-85.630013,41.957097]},"n1275":{"id":"n1275","loc":[-85.630211,41.956592]},"n1276":{"id":"n1276","loc":[-85.630211,41.956676]},"n1277":{"id":"n1277","loc":[-85.630162,41.956676]},"n1278":{"id":"n1278","loc":[-85.630162,41.95676]},"n1279":{"id":"n1279","loc":[-85.630037,41.956761]},"n128":{"id":"n128","loc":[-85.637604,41.942057]},"n1280":{"id":"n1280","loc":[-85.630037,41.956592]},"n1281":{"id":"n1281","loc":[-85.630309,41.95653]},"n1282":{"id":"n1282","loc":[-85.630326,41.957065]},"n1283":{"id":"n1283","loc":[-85.630118,41.957065]},"n1284":{"id":"n1284","loc":[-85.630119,41.957096]},"n1285":{"id":"n1285","loc":[-85.63067,41.957307]},"n1286":{"id":"n1286","loc":[-85.630536,41.957308]},"n1287":{"id":"n1287","loc":[-85.630533,41.957111]},"n1288":{"id":"n1288","loc":[-85.630667,41.95711]},"n1289":{"id":"n1289","loc":[-85.630676,41.956808]},"n129":{"id":"n129","loc":[-85.63748,41.942057]},"n1290":{"id":"n1290","loc":[-85.630551,41.956808]},"n1291":{"id":"n1291","loc":[-85.630552,41.956982]},"n1292":{"id":"n1292","loc":[-85.63059,41.956982]},"n1293":{"id":"n1293","loc":[-85.63059,41.957001]},"n1294":{"id":"n1294","loc":[-85.630692,41.957001]},"n1295":{"id":"n1295","loc":[-85.630692,41.956936]},"n1296":{"id":"n1296","loc":[-85.630676,41.956936]},"n1297":{"id":"n1297","loc":[-85.630496,41.956889]},"n1298":{"id":"n1298","loc":[-85.630501,41.956947]},"n1299":{"id":"n1299","loc":[-85.630377,41.956953]},"n13":{"id":"n13","loc":[-85.633643,41.941143]},"n130":{"id":"n130","loc":[-85.63748,41.941994]},"n1300":{"id":"n1300","loc":[-85.630359,41.956938]},"n1301":{"id":"n1301","loc":[-85.630359,41.956912]},"n1302":{"id":"n1302","loc":[-85.63038,41.956894]},"n1303":{"id":"n1303","loc":[-85.630679,41.956747]},"n1304":{"id":"n1304","loc":[-85.630572,41.956748]},"n1305":{"id":"n1305","loc":[-85.63057,41.956668]},"n1306":{"id":"n1306","loc":[-85.630501,41.956669]},"n1307":{"id":"n1307","loc":[-85.630499,41.95659]},"n1308":{"id":"n1308","loc":[-85.630565,41.956589]},"n1309":{"id":"n1309","loc":[-85.630564,41.956541]},"n131":{"id":"n131","loc":[-85.637431,41.941832]},"n1310":{"id":"n1310","loc":[-85.630686,41.956539]},"n1311":{"id":"n1311","loc":[-85.630688,41.956631]},"n1312":{"id":"n1312","loc":[-85.630676,41.956631]},"n1313":{"id":"n1313","loc":[-85.630686,41.956487]},"n1314":{"id":"n1314","loc":[-85.63059,41.956487]},"n1315":{"id":"n1315","loc":[-85.63059,41.956396]},"n1316":{"id":"n1316","loc":[-85.630686,41.956396]},"n1317":{"id":"n1317","loc":[-85.630643,41.9563]},"n1318":{"id":"n1318","loc":[-85.630548,41.956301]},"n1319":{"id":"n1319","loc":[-85.630545,41.956217]},"n132":{"id":"n132","loc":[-85.637432,41.94189]},"n1320":{"id":"n1320","loc":[-85.630529,41.956214]},"n1321":{"id":"n1321","loc":[-85.630521,41.956202]},"n1322":{"id":"n1322","loc":[-85.63052,41.95618]},"n1323":{"id":"n1323","loc":[-85.630527,41.956169]},"n1324":{"id":"n1324","loc":[-85.630544,41.956163]},"n1325":{"id":"n1325","loc":[-85.630543,41.956094]},"n1326":{"id":"n1326","loc":[-85.630641,41.956093]},"n1327":{"id":"n1327","loc":[-85.630642,41.956134]},"n1328":{"id":"n1328","loc":[-85.630656,41.956134]},"n1329":{"id":"n1329","loc":[-85.630657,41.956252]},"n133":{"id":"n133","loc":[-85.637412,41.94189]},"n1330":{"id":"n1330","loc":[-85.630643,41.956252]},"n1331":{"id":"n1331","loc":[-85.630409,41.956044]},"n1332":{"id":"n1332","loc":[-85.630409,41.956075]},"n1333":{"id":"n1333","loc":[-85.630195,41.956078]},"n1334":{"id":"n1334","loc":[-85.630195,41.9561]},"n1335":{"id":"n1335","loc":[-85.630088,41.956101]},"n1336":{"id":"n1336","loc":[-85.630087,41.956048]},"n1337":{"id":"n1337","loc":[-85.630345,41.956114]},"n1338":{"id":"n1338","loc":[-85.630328,41.956113]},"n1339":{"id":"n1339","loc":[-85.63034,41.956189]},"n134":{"id":"n134","loc":[-85.637413,41.941938]},"n1340":{"id":"n1340","loc":[-85.630355,41.956185]},"n1341":{"id":"n1341","loc":[-85.630311,41.956117]},"n1342":{"id":"n1342","loc":[-85.630297,41.956125]},"n1343":{"id":"n1343","loc":[-85.630287,41.956136]},"n1344":{"id":"n1344","loc":[-85.630283,41.956149]},"n1345":{"id":"n1345","loc":[-85.630285,41.956162]},"n1346":{"id":"n1346","loc":[-85.630293,41.956174]},"n1347":{"id":"n1347","loc":[-85.630306,41.956183]},"n1348":{"id":"n1348","loc":[-85.630322,41.956188]},"n1349":{"id":"n1349","loc":[-85.630368,41.956179]},"n135":{"id":"n135","loc":[-85.637342,41.941939]},"n1350":{"id":"n1350","loc":[-85.630378,41.95617]},"n1351":{"id":"n1351","loc":[-85.630384,41.956159]},"n1352":{"id":"n1352","loc":[-85.630385,41.956147]},"n1353":{"id":"n1353","loc":[-85.630381,41.956136]},"n1354":{"id":"n1354","loc":[-85.630372,41.956126]},"n1355":{"id":"n1355","loc":[-85.63036,41.956118]},"n1356":{"id":"n1356","loc":[-85.630776,41.956041]},"n1357":{"id":"n1357","loc":[-85.630195,41.956036]},"n1358":{"id":"n1358","loc":[-85.630137,41.956037]},"n1359":{"id":"n1359","loc":[-85.630136,41.956006]},"n136":{"id":"n136","loc":[-85.637342,41.941914]},"n1360":{"id":"n1360","loc":[-85.630194,41.956005]},"n1361":{"id":"n1361","loc":[-85.629864,41.956039]},"n1362":{"id":"n1362","loc":[-85.629864,41.955862]},"n1363":{"id":"n1363","loc":[-85.629541,41.958291]},"n1364":{"id":"n1364","loc":[-85.629419,41.958292]},"n1365":{"id":"n1365","loc":[-85.629417,41.958168]},"n1366":{"id":"n1366","loc":[-85.629445,41.958168]},"n1367":{"id":"n1367","loc":[-85.629444,41.958109]},"n1368":{"id":"n1368","loc":[-85.629537,41.958108]},"n1369":{"id":"n1369","loc":[-85.629351,41.958136]},"n137":{"id":"n137","loc":[-85.637212,41.941916]},"n1370":{"id":"n1370","loc":[-85.629352,41.958202]},"n1371":{"id":"n1371","loc":[-85.629365,41.958202]},"n1372":{"id":"n1372","loc":[-85.629365,41.958223]},"n1373":{"id":"n1373","loc":[-85.629291,41.958224]},"n1374":{"id":"n1374","loc":[-85.62929,41.958137]},"n1375":{"id":"n1375","loc":[-85.629443,41.958073]},"n1376":{"id":"n1376","loc":[-85.629252,41.958075]},"n1377":{"id":"n1377","loc":[-85.629253,41.95827]},"n1378":{"id":"n1378","loc":[-85.629566,41.957585]},"n1379":{"id":"n1379","loc":[-85.629566,41.957692]},"n138":{"id":"n138","loc":[-85.637211,41.941835]},"n1380":{"id":"n1380","loc":[-85.629281,41.957693]},"n1381":{"id":"n1381","loc":[-85.62928,41.957585]},"n1382":{"id":"n1382","loc":[-85.629004,41.957599]},"n1383":{"id":"n1383","loc":[-85.629004,41.957682]},"n1384":{"id":"n1384","loc":[-85.628902,41.957682]},"n1385":{"id":"n1385","loc":[-85.628902,41.957723]},"n1386":{"id":"n1386","loc":[-85.628731,41.957724]},"n1387":{"id":"n1387","loc":[-85.628731,41.9576]},"n1388":{"id":"n1388","loc":[-85.62836,41.957679]},"n1389":{"id":"n1389","loc":[-85.628359,41.957759]},"n139":{"id":"n139","loc":[-85.637293,41.941834]},"n1390":{"id":"n1390","loc":[-85.628062,41.957757]},"n1391":{"id":"n1391","loc":[-85.628063,41.957657]},"n1392":{"id":"n1392","loc":[-85.628198,41.957657]},"n1393":{"id":"n1393","loc":[-85.628198,41.957678]},"n1394":{"id":"n1394","loc":[-85.627775,41.958095]},"n1395":{"id":"n1395","loc":[-85.627608,41.958095]},"n1396":{"id":"n1396","loc":[-85.627606,41.957829]},"n1397":{"id":"n1397","loc":[-85.627774,41.957829]},"n1398":{"id":"n1398","loc":[-85.626816,41.957636]},"n1399":{"id":"n1399","loc":[-85.626787,41.957681]},"n14":{"id":"n14","loc":[-85.633643,41.940122]},"n140":{"id":"n140","loc":[-85.637293,41.941823]},"n1400":{"id":"n1400","loc":[-85.626673,41.95764]},"n1401":{"id":"n1401","loc":[-85.626703,41.957594]},"n1402":{"id":"n1402","loc":[-85.62694,41.95752]},"n1403":{"id":"n1403","loc":[-85.62688,41.957611]},"n1404":{"id":"n1404","loc":[-85.626798,41.957582]},"n1405":{"id":"n1405","loc":[-85.626793,41.95759]},"n1406":{"id":"n1406","loc":[-85.626657,41.95754]},"n1407":{"id":"n1407","loc":[-85.626666,41.957526]},"n1408":{"id":"n1408","loc":[-85.626584,41.957497]},"n1409":{"id":"n1409","loc":[-85.626638,41.957415]},"n141":{"id":"n141","loc":[-85.637363,41.941822]},"n1410":{"id":"n1410","loc":[-85.626731,41.957449]},"n1411":{"id":"n1411","loc":[-85.626725,41.957457]},"n1412":{"id":"n1412","loc":[-85.626843,41.9575]},"n1413":{"id":"n1413","loc":[-85.626851,41.957487]},"n1414":{"id":"n1414","loc":[-85.626579,41.957521]},"n1415":{"id":"n1415","loc":[-85.626537,41.957587]},"n1416":{"id":"n1416","loc":[-85.626427,41.957551]},"n1417":{"id":"n1417","loc":[-85.626468,41.957483]},"n1418":{"id":"n1418","loc":[-85.626592,41.957639]},"n1419":{"id":"n1419","loc":[-85.626807,41.957713]},"n142":{"id":"n142","loc":[-85.637364,41.941833]},"n1420":{"id":"n1420","loc":[-85.627129,41.957401]},"n1421":{"id":"n1421","loc":[-85.627209,41.95742]},"n1422":{"id":"n1422","loc":[-85.627302,41.957435]},"n1423":{"id":"n1423","loc":[-85.629566,41.957048]},"n1424":{"id":"n1424","loc":[-85.629568,41.957215]},"n1425":{"id":"n1425","loc":[-85.629383,41.957216]},"n1426":{"id":"n1426","loc":[-85.629384,41.95727]},"n1427":{"id":"n1427","loc":[-85.629231,41.957271]},"n1428":{"id":"n1428","loc":[-85.62923,41.957198]},"n1429":{"id":"n1429","loc":[-85.629322,41.957198]},"n143":{"id":"n143","loc":[-85.637559,41.942448]},"n1430":{"id":"n1430","loc":[-85.629321,41.957108]},"n1431":{"id":"n1431","loc":[-85.629441,41.957108]},"n1432":{"id":"n1432","loc":[-85.62944,41.957049]},"n1433":{"id":"n1433","loc":[-85.629337,41.957018]},"n1434":{"id":"n1434","loc":[-85.629366,41.957028]},"n1435":{"id":"n1435","loc":[-85.629375,41.957044]},"n1436":{"id":"n1436","loc":[-85.629354,41.957071]},"n1437":{"id":"n1437","loc":[-85.629317,41.957071]},"n1438":{"id":"n1438","loc":[-85.62929,41.957074]},"n1439":{"id":"n1439","loc":[-85.62927,41.957084]},"n144":{"id":"n144","loc":[-85.637036,41.942454]},"n1440":{"id":"n1440","loc":[-85.629232,41.957081]},"n1441":{"id":"n1441","loc":[-85.629222,41.957057]},"n1442":{"id":"n1442","loc":[-85.629259,41.957025]},"n1443":{"id":"n1443","loc":[-85.629293,41.957017]},"n1444":{"id":"n1444","loc":[-85.629251,41.957085]},"n1445":{"id":"n1445","loc":[-85.629235,41.957041]},"n1446":{"id":"n1446","loc":[-85.62937,41.95706]},"n1447":{"id":"n1447","loc":[-85.629531,41.956909]},"n1448":{"id":"n1448","loc":[-85.629408,41.956909]},"n1449":{"id":"n1449","loc":[-85.629402,41.956681]},"n145":{"id":"n145","loc":[-85.636692,41.942828]},"n1450":{"id":"n1450","loc":[-85.62953,41.956681]},"n1451":{"id":"n1451","loc":[-85.629402,41.956728]},"n1452":{"id":"n1452","loc":[-85.629408,41.956845]},"n1453":{"id":"n1453","loc":[-85.629385,41.956845]},"n1454":{"id":"n1454","loc":[-85.629384,41.956728]},"n1455":{"id":"n1455","loc":[-85.629063,41.956973]},"n1456":{"id":"n1456","loc":[-85.629064,41.957009]},"n1457":{"id":"n1457","loc":[-85.62902,41.957009]},"n1458":{"id":"n1458","loc":[-85.629019,41.956973]},"n1459":{"id":"n1459","loc":[-85.629136,41.956633]},"n146":{"id":"n146","loc":[-85.635929,41.942826]},"n1460":{"id":"n1460","loc":[-85.629084,41.956632]},"n1461":{"id":"n1461","loc":[-85.629084,41.956605]},"n1462":{"id":"n1462","loc":[-85.629136,41.956605]},"n1463":{"id":"n1463","loc":[-85.629153,41.956657]},"n1464":{"id":"n1464","loc":[-85.627914,41.956661]},"n1465":{"id":"n1465","loc":[-85.630096,41.956101]},"n1466":{"id":"n1466","loc":[-85.630097,41.95612]},"n1467":{"id":"n1467","loc":[-85.630011,41.956121]},"n1468":{"id":"n1468","loc":[-85.630015,41.956374]},"n1469":{"id":"n1469","loc":[-85.629148,41.95626]},"n147":{"id":"n147","loc":[-85.636433,41.942828]},"n1470":{"id":"n1470","loc":[-85.629527,41.956591]},"n1471":{"id":"n1471","loc":[-85.629405,41.956591]},"n1472":{"id":"n1472","loc":[-85.629405,41.956459]},"n1473":{"id":"n1473","loc":[-85.629369,41.956459]},"n1474":{"id":"n1474","loc":[-85.629369,41.956424]},"n1475":{"id":"n1475","loc":[-85.629413,41.956424]},"n1476":{"id":"n1476","loc":[-85.629414,41.956326]},"n1477":{"id":"n1477","loc":[-85.629522,41.956326]},"n1478":{"id":"n1478","loc":[-85.629522,41.956487]},"n1479":{"id":"n1479","loc":[-85.629527,41.956487]},"n148":{"id":"n148","loc":[-85.636435,41.942864],"tags":{"entrance":"yes"}},"n1480":{"id":"n1480","loc":[-85.629414,41.95634]},"n1481":{"id":"n1481","loc":[-85.629149,41.956338]},"n1482":{"id":"n1482","loc":[-85.62931,41.956531]},"n1483":{"id":"n1483","loc":[-85.629291,41.95655]},"n1484":{"id":"n1484","loc":[-85.629255,41.95655]},"n1485":{"id":"n1485","loc":[-85.629236,41.956533]},"n1486":{"id":"n1486","loc":[-85.629237,41.956461]},"n1487":{"id":"n1487","loc":[-85.629257,41.956445]},"n1488":{"id":"n1488","loc":[-85.629257,41.956428]},"n1489":{"id":"n1489","loc":[-85.629287,41.956428]},"n149":{"id":"n149","loc":[-85.637235,41.942622]},"n1490":{"id":"n1490","loc":[-85.629287,41.956445]},"n1491":{"id":"n1491","loc":[-85.62931,41.95646]},"n1492":{"id":"n1492","loc":[-85.629049,41.956425]},"n1493":{"id":"n1493","loc":[-85.628907,41.956427]},"n1494":{"id":"n1494","loc":[-85.628907,41.956455]},"n1495":{"id":"n1495","loc":[-85.628841,41.956455]},"n1496":{"id":"n1496","loc":[-85.62884,41.956424]},"n1497":{"id":"n1497","loc":[-85.628764,41.956425]},"n1498":{"id":"n1498","loc":[-85.628762,41.956323]},"n1499":{"id":"n1499","loc":[-85.628808,41.956323]},"n15":{"id":"n15","loc":[-85.633477,41.940187]},"n150":{"id":"n150","loc":[-85.637247,41.943116]},"n1500":{"id":"n1500","loc":[-85.628808,41.956314]},"n1501":{"id":"n1501","loc":[-85.628911,41.956313]},"n1502":{"id":"n1502","loc":[-85.628911,41.956322]},"n1503":{"id":"n1503","loc":[-85.62896,41.956322]},"n1504":{"id":"n1504","loc":[-85.62896,41.956348]},"n1505":{"id":"n1505","loc":[-85.629047,41.956347]},"n1506":{"id":"n1506","loc":[-85.628893,41.957263]},"n1507":{"id":"n1507","loc":[-85.628788,41.957264]},"n1508":{"id":"n1508","loc":[-85.628786,41.95711]},"n1509":{"id":"n1509","loc":[-85.628894,41.957109]},"n151":{"id":"n151","loc":[-85.637564,41.943116]},"n1510":{"id":"n1510","loc":[-85.628893,41.957075]},"n1511":{"id":"n1511","loc":[-85.628965,41.957075]},"n1512":{"id":"n1512","loc":[-85.628965,41.957111]},"n1513":{"id":"n1513","loc":[-85.629035,41.95711]},"n1514":{"id":"n1514","loc":[-85.629036,41.957209]},"n1515":{"id":"n1515","loc":[-85.628893,41.95721]},"n1516":{"id":"n1516","loc":[-85.631348,41.95773]},"n1517":{"id":"n1517","loc":[-85.631101,41.957732]},"n1518":{"id":"n1518","loc":[-85.631099,41.957558]},"n1519":{"id":"n1519","loc":[-85.63123,41.957557]},"n152":{"id":"n152","loc":[-85.637552,41.942619]},"n1520":{"id":"n1520","loc":[-85.631231,41.957618]},"n1521":{"id":"n1521","loc":[-85.63129,41.957618]},"n1522":{"id":"n1522","loc":[-85.63129,41.957651]},"n1523":{"id":"n1523","loc":[-85.631346,41.957651]},"n1524":{"id":"n1524","loc":[-85.631366,41.95802]},"n1525":{"id":"n1525","loc":[-85.631141,41.958021]},"n1526":{"id":"n1526","loc":[-85.63114,41.957943]},"n1527":{"id":"n1527","loc":[-85.631167,41.957943]},"n1528":{"id":"n1528","loc":[-85.631166,41.957808]},"n1529":{"id":"n1529","loc":[-85.631301,41.957807]},"n153":{"id":"n153","loc":[-85.63763,41.942528]},"n1530":{"id":"n1530","loc":[-85.631302,41.95789]},"n1531":{"id":"n1531","loc":[-85.631364,41.95789]},"n1532":{"id":"n1532","loc":[-85.631539,41.957754]},"n1533":{"id":"n1533","loc":[-85.631069,41.957756]},"n1534":{"id":"n1534","loc":[-85.631536,41.957518]},"n1535":{"id":"n1535","loc":[-85.631543,41.957995]},"n1536":{"id":"n1536","loc":[-85.631531,41.957748]},"n1537":{"id":"n1537","loc":[-85.631485,41.957748]},"n1538":{"id":"n1538","loc":[-85.631484,41.957698]},"n1539":{"id":"n1539","loc":[-85.631531,41.957698]},"n154":{"id":"n154","loc":[-85.637151,41.94253]},"n1540":{"id":"n1540","loc":[-85.631586,41.957742]},"n1541":{"id":"n1541","loc":[-85.63155,41.957742]},"n1542":{"id":"n1542","loc":[-85.631551,41.957702]},"n1543":{"id":"n1543","loc":[-85.631587,41.957702]},"n1544":{"id":"n1544","loc":[-85.631534,41.95807]},"n1545":{"id":"n1545","loc":[-85.631534,41.958097]},"n1546":{"id":"n1546","loc":[-85.631491,41.958097]},"n1547":{"id":"n1547","loc":[-85.631491,41.95807]},"n1548":{"id":"n1548","loc":[-85.631304,41.958861]},"n1549":{"id":"n1549","loc":[-85.631186,41.958862]},"n155":{"id":"n155","loc":[-85.63715,41.942424]},"n1550":{"id":"n1550","loc":[-85.631182,41.958653]},"n1551":{"id":"n1551","loc":[-85.6313,41.958651]},"n1552":{"id":"n1552","loc":[-85.631293,41.95854]},"n1553":{"id":"n1553","loc":[-85.631176,41.958539]},"n1554":{"id":"n1554","loc":[-85.631176,41.958377]},"n1555":{"id":"n1555","loc":[-85.631297,41.958377]},"n1556":{"id":"n1556","loc":[-85.631297,41.958422]},"n1557":{"id":"n1557","loc":[-85.631333,41.958422]},"n1558":{"id":"n1558","loc":[-85.631333,41.958479]},"n1559":{"id":"n1559","loc":[-85.631293,41.958479]},"n156":{"id":"n156","loc":[-85.637629,41.942422]},"n1560":{"id":"n1560","loc":[-85.631951,41.958908]},"n1561":{"id":"n1561","loc":[-85.631838,41.958909]},"n1562":{"id":"n1562","loc":[-85.631837,41.958847]},"n1563":{"id":"n1563","loc":[-85.631859,41.958847]},"n1564":{"id":"n1564","loc":[-85.631858,41.958746]},"n1565":{"id":"n1565","loc":[-85.631961,41.958745]},"n1566":{"id":"n1566","loc":[-85.631962,41.958812]},"n1567":{"id":"n1567","loc":[-85.631949,41.958813]},"n1568":{"id":"n1568","loc":[-85.631579,41.958913]},"n1569":{"id":"n1569","loc":[-85.631567,41.95864]},"n157":{"id":"n157","loc":[-85.638232,41.942477]},"n1570":{"id":"n1570","loc":[-85.631942,41.958639]},"n1571":{"id":"n1571","loc":[-85.631543,41.958594]},"n1572":{"id":"n1572","loc":[-85.631543,41.958065]},"n1573":{"id":"n1573","loc":[-85.631888,41.958546]},"n1574":{"id":"n1574","loc":[-85.631804,41.958546]},"n1575":{"id":"n1575","loc":[-85.631803,41.95841]},"n1576":{"id":"n1576","loc":[-85.631886,41.958409]},"n1577":{"id":"n1577","loc":[-85.631897,41.958125]},"n1578":{"id":"n1578","loc":[-85.631755,41.958126]},"n1579":{"id":"n1579","loc":[-85.631756,41.958174]},"n158":{"id":"n158","loc":[-85.637775,41.942483]},"n1580":{"id":"n1580","loc":[-85.63178,41.958174]},"n1581":{"id":"n1581","loc":[-85.631782,41.958272]},"n1582":{"id":"n1582","loc":[-85.631922,41.958271]},"n1583":{"id":"n1583","loc":[-85.631922,41.958244]},"n1584":{"id":"n1584","loc":[-85.631883,41.958245]},"n1585":{"id":"n1585","loc":[-85.631882,41.958175]},"n1586":{"id":"n1586","loc":[-85.631898,41.958175]},"n1587":{"id":"n1587","loc":[-85.631924,41.958032]},"n1588":{"id":"n1588","loc":[-85.631762,41.958032]},"n1589":{"id":"n1589","loc":[-85.63176,41.957827]},"n159":{"id":"n159","loc":[-85.638107,41.942512]},"n1590":{"id":"n1590","loc":[-85.631888,41.957826]},"n1591":{"id":"n1591","loc":[-85.631888,41.957892]},"n1592":{"id":"n1592","loc":[-85.631871,41.957892]},"n1593":{"id":"n1593","loc":[-85.631872,41.957949]},"n1594":{"id":"n1594","loc":[-85.631923,41.957949]},"n1595":{"id":"n1595","loc":[-85.631695,41.95795]},"n1596":{"id":"n1596","loc":[-85.631666,41.957975]},"n1597":{"id":"n1597","loc":[-85.63163,41.957975]},"n1598":{"id":"n1598","loc":[-85.6316,41.957951]},"n1599":{"id":"n1599","loc":[-85.6316,41.95785]},"n16":{"id":"n16","loc":[-85.63341,41.94032]},"n160":{"id":"n160","loc":[-85.637763,41.942514]},"n1600":{"id":"n1600","loc":[-85.63166,41.95785]},"n1601":{"id":"n1601","loc":[-85.631696,41.957873]},"n1602":{"id":"n1602","loc":[-85.631924,41.957762]},"n1603":{"id":"n1603","loc":[-85.631762,41.957762]},"n1604":{"id":"n1604","loc":[-85.631762,41.957708]},"n1605":{"id":"n1605","loc":[-85.631785,41.957708]},"n1606":{"id":"n1606","loc":[-85.631785,41.957606]},"n1607":{"id":"n1607","loc":[-85.631734,41.957606]},"n1608":{"id":"n1608","loc":[-85.631734,41.957538]},"n1609":{"id":"n1609","loc":[-85.631821,41.957538]},"n161":{"id":"n161","loc":[-85.637763,41.942445]},"n1610":{"id":"n1610","loc":[-85.631935,41.957545]},"n1611":{"id":"n1611","loc":[-85.631821,41.957544]},"n1612":{"id":"n1612","loc":[-85.631935,41.957645]},"n1613":{"id":"n1613","loc":[-85.631924,41.957645]},"n1614":{"id":"n1614","loc":[-85.627135,41.953828]},"n1615":{"id":"n1615","loc":[-85.633517,41.941353],"tags":{"man_made":"lighthouse"}},"n1616":{"id":"n1616","loc":[-85.633659,41.942041],"tags":{"amenity":"bbq"}},"n1617":{"id":"n1617","loc":[-85.63662,41.942911],"tags":{"amenity":"toilets"}},"n1618":{"id":"n1618","loc":[-85.637487,41.943876],"tags":{"amenity":"toilets"}},"n1619":{"id":"n1619","loc":[-85.634938,41.941917],"tags":{"amenity":"toilets"}},"n162":{"id":"n162","loc":[-85.638107,41.942443]},"n1620":{"id":"n1620","loc":[-85.632427,41.941678],"tags":{"amenity":"bbq"}},"n1621":{"id":"n1621","loc":[-85.638033,41.944568],"tags":{"amenity":"bbq"}},"n1622":{"id":"n1622","loc":[-85.638052,41.944522],"tags":{"amenity":"bbq"}},"n1623":{"id":"n1623","loc":[-85.635001,41.941965]},"n1624":{"id":"n1624","loc":[-85.634635,41.941884]},"n1625":{"id":"n1625","loc":[-85.634667,41.941894]},"n1626":{"id":"n1626","loc":[-85.634791,41.942011]},"n1627":{"id":"n1627","loc":[-85.634749,41.941938]},"n1628":{"id":"n1628","loc":[-85.627295,41.953946],"tags":{"barrier":"gate"}},"n1629":{"id":"n1629","loc":[-85.629076,41.954689]},"n163":{"id":"n163","loc":[-85.638813,41.942475]},"n1630":{"id":"n1630","loc":[-85.640667,41.942595]},"n1631":{"id":"n1631","loc":[-85.639455,41.94261]},"n1632":{"id":"n1632","loc":[-85.643407,41.942336]},"n1633":{"id":"n1633","loc":[-85.641845,41.941316]},"n1634":{"id":"n1634","loc":[-85.643322,41.942224]},"n1635":{"id":"n1635","loc":[-85.643301,41.942124]},"n1636":{"id":"n1636","loc":[-85.640639,41.941326]},"n1637":{"id":"n1637","loc":[-85.640614,41.940058]},"n1638":{"id":"n1638","loc":[-85.639428,41.941335]},"n1639":{"id":"n1639","loc":[-85.643078,41.941293]},"n164":{"id":"n164","loc":[-85.63883,41.942422]},"n1640":{"id":"n1640","loc":[-85.64371,41.942302]},"n1641":{"id":"n1641","loc":[-85.643056,41.94001]},"n1642":{"id":"n1642","loc":[-85.643097,41.942575],"tags":{"highway":"traffic_signals","traffic_signals":"signal"}},"n1643":{"id":"n1643","loc":[-85.641855,41.942586]},"n1644":{"id":"n1644","loc":[-85.643549,41.942209]},"n1645":{"id":"n1645","loc":[-85.639359,41.94007]},"n1646":{"id":"n1646","loc":[-85.642797,41.940522]},"n1647":{"id":"n1647","loc":[-85.642589,41.940523]},"n1648":{"id":"n1648","loc":[-85.642587,41.940287]},"n1649":{"id":"n1649","loc":[-85.642797,41.940286]},"n165":{"id":"n165","loc":[-85.63883,41.942508]},"n1650":{"id":"n1650","loc":[-85.642571,41.940523]},"n1651":{"id":"n1651","loc":[-85.642568,41.940286]},"n1652":{"id":"n1652","loc":[-85.642316,41.940289]},"n1653":{"id":"n1653","loc":[-85.642321,41.940436]},"n1654":{"id":"n1654","loc":[-85.642292,41.940458]},"n1655":{"id":"n1655","loc":[-85.642287,41.940483]},"n1656":{"id":"n1656","loc":[-85.642323,41.940509]},"n1657":{"id":"n1657","loc":[-85.642385,41.940511]},"n1658":{"id":"n1658","loc":[-85.642408,41.940526]},"n1659":{"id":"n1659","loc":[-85.641962,41.94109]},"n166":{"id":"n166","loc":[-85.638364,41.942508]},"n1660":{"id":"n1660","loc":[-85.642753,41.941084]},"n1661":{"id":"n1661","loc":[-85.642752,41.941004]},"n1662":{"id":"n1662","loc":[-85.642806,41.941003]},"n1663":{"id":"n1663","loc":[-85.642803,41.940731]},"n1664":{"id":"n1664","loc":[-85.642741,41.940732]},"n1665":{"id":"n1665","loc":[-85.64274,41.940645]},"n1666":{"id":"n1666","loc":[-85.641957,41.940651]},"n1667":{"id":"n1667","loc":[-85.642937,41.941241]},"n1668":{"id":"n1668","loc":[-85.641776,41.941253]},"n1669":{"id":"n1669","loc":[-85.641766,41.940598]},"n167":{"id":"n167","loc":[-85.638836,41.942167]},"n1670":{"id":"n1670","loc":[-85.64198,41.940598]},"n1671":{"id":"n1671","loc":[-85.641961,41.940137]},"n1672":{"id":"n1672","loc":[-85.642934,41.94012]},"n1673":{"id":"n1673","loc":[-85.643074,41.941173]},"n1674":{"id":"n1674","loc":[-85.642841,41.940997]},"n1675":{"id":"n1675","loc":[-85.642839,41.940721]},"n1676":{"id":"n1676","loc":[-85.643065,41.940552]},"n1677":{"id":"n1677","loc":[-85.642732,41.94124]},"n1678":{"id":"n1678","loc":[-85.641815,41.941246]},"n1679":{"id":"n1679","loc":[-85.641813,41.941132]},"n168":{"id":"n168","loc":[-85.638836,41.94229]},"n1680":{"id":"n1680","loc":[-85.641839,41.941111]},"n1681":{"id":"n1681","loc":[-85.641884,41.941098]},"n1682":{"id":"n1682","loc":[-85.642732,41.941092]},"n1683":{"id":"n1683","loc":[-85.642776,41.941302]},"n1684":{"id":"n1684","loc":[-85.632788,41.946236]},"n1685":{"id":"n1685","loc":[-85.622342,41.953127]},"n1686":{"id":"n1686","loc":[-85.641848,41.941167]},"n1687":{"id":"n1687","loc":[-85.643753,41.941503]},"n1688":{"id":"n1688","loc":[-85.643762,41.942119]},"n1689":{"id":"n1689","loc":[-85.64238,41.942262]},"n169":{"id":"n169","loc":[-85.638594,41.94229]},"n1690":{"id":"n1690","loc":[-85.642374,41.941944]},"n1691":{"id":"n1691","loc":[-85.642518,41.941943]},"n1692":{"id":"n1692","loc":[-85.642519,41.94198]},"n1693":{"id":"n1693","loc":[-85.642831,41.941977]},"n1694":{"id":"n1694","loc":[-85.642837,41.942312]},"n1695":{"id":"n1695","loc":[-85.642495,41.942315]},"n1696":{"id":"n1696","loc":[-85.642494,41.942261]},"n1697":{"id":"n1697","loc":[-85.641087,41.942433]},"n1698":{"id":"n1698","loc":[-85.641081,41.942006]},"n1699":{"id":"n1699","loc":[-85.641244,41.942005]},"n17":{"id":"n17","loc":[-85.633478,41.94081]},"n170":{"id":"n170","loc":[-85.638594,41.942422]},"n1700":{"id":"n1700","loc":[-85.64125,41.942431]},"n1701":{"id":"n1701","loc":[-85.641331,41.942968]},"n1702":{"id":"n1702","loc":[-85.641328,41.942713]},"n1703":{"id":"n1703","loc":[-85.641521,41.942712]},"n1704":{"id":"n1704","loc":[-85.641523,41.942924]},"n1705":{"id":"n1705","loc":[-85.641504,41.942924]},"n1706":{"id":"n1706","loc":[-85.641505,41.942967]},"n1707":{"id":"n1707","loc":[-85.638612,41.942408]},"n1708":{"id":"n1708","loc":[-85.638612,41.942327]},"n1709":{"id":"n1709","loc":[-85.638775,41.942327]},"n171":{"id":"n171","loc":[-85.638364,41.942356]},"n1710":{"id":"n1710","loc":[-85.638775,41.942299]},"n1711":{"id":"n1711","loc":[-85.638835,41.942298]},"n1712":{"id":"n1712","loc":[-85.638835,41.942407]},"n1713":{"id":"n1713","loc":[-85.639116,41.942444]},"n1714":{"id":"n1714","loc":[-85.639114,41.942362]},"n1715":{"id":"n1715","loc":[-85.639294,41.94236]},"n1716":{"id":"n1716","loc":[-85.639296,41.942442]},"n1717":{"id":"n1717","loc":[-85.639808,41.942385]},"n1718":{"id":"n1718","loc":[-85.639805,41.942285]},"n1719":{"id":"n1719","loc":[-85.639988,41.942283]},"n172":{"id":"n172","loc":[-85.638364,41.942167]},"n1720":{"id":"n1720","loc":[-85.63999,41.942383]},"n1721":{"id":"n1721","loc":[-85.639633,41.943023]},"n1722":{"id":"n1722","loc":[-85.639867,41.943019]},"n1723":{"id":"n1723","loc":[-85.639866,41.942964]},"n1724":{"id":"n1724","loc":[-85.639888,41.942963]},"n1725":{"id":"n1725","loc":[-85.639883,41.942779]},"n1726":{"id":"n1726","loc":[-85.639851,41.94278]},"n1727":{"id":"n1727","loc":[-85.63985,41.94274]},"n1728":{"id":"n1728","loc":[-85.639789,41.942741]},"n1729":{"id":"n1729","loc":[-85.639789,41.942753]},"n173":{"id":"n173","loc":[-85.639038,41.942463]},"n1730":{"id":"n1730","loc":[-85.639698,41.942754]},"n1731":{"id":"n1731","loc":[-85.639699,41.942788]},"n1732":{"id":"n1732","loc":[-85.639675,41.942789]},"n1733":{"id":"n1733","loc":[-85.639676,41.94283]},"n1734":{"id":"n1734","loc":[-85.639701,41.942829]},"n1735":{"id":"n1735","loc":[-85.639702,41.942869]},"n1736":{"id":"n1736","loc":[-85.639629,41.94287]},"n1737":{"id":"n1737","loc":[-85.643568,41.942946]},"n1738":{"id":"n1738","loc":[-85.643568,41.942777]},"n1739":{"id":"n1739","loc":[-85.643401,41.942777]},"n174":{"id":"n174","loc":[-85.638897,41.942464]},"n1740":{"id":"n1740","loc":[-85.643401,41.942863]},"n1741":{"id":"n1741","loc":[-85.643448,41.942863]},"n1742":{"id":"n1742","loc":[-85.643448,41.942946]},"n1743":{"id":"n1743","loc":[-85.642836,41.942981]},"n1744":{"id":"n1744","loc":[-85.642917,41.942979]},"n1745":{"id":"n1745","loc":[-85.642914,41.942904]},"n1746":{"id":"n1746","loc":[-85.642938,41.942903]},"n1747":{"id":"n1747","loc":[-85.642935,41.942813]},"n1748":{"id":"n1748","loc":[-85.642775,41.942816]},"n1749":{"id":"n1749","loc":[-85.642778,41.942906]},"n175":{"id":"n175","loc":[-85.638897,41.942423]},"n1750":{"id":"n1750","loc":[-85.642833,41.942905]},"n1751":{"id":"n1751","loc":[-85.642302,41.942886]},"n1752":{"id":"n1752","loc":[-85.642299,41.942721]},"n1753":{"id":"n1753","loc":[-85.642422,41.94272]},"n1754":{"id":"n1754","loc":[-85.642425,41.942868]},"n1755":{"id":"n1755","loc":[-85.642385,41.942869]},"n1756":{"id":"n1756","loc":[-85.642385,41.942885]},"n1757":{"id":"n1757","loc":[-85.641533,41.942939]},"n1758":{"id":"n1758","loc":[-85.64161,41.942877]},"n1759":{"id":"n1759","loc":[-85.641676,41.942922]},"n176":{"id":"n176","loc":[-85.638853,41.942423]},"n1760":{"id":"n1760","loc":[-85.6416,41.942985]},"n1761":{"id":"n1761","loc":[-85.64206,41.942802]},"n1762":{"id":"n1762","loc":[-85.642059,41.942741]},"n1763":{"id":"n1763","loc":[-85.642196,41.942741]},"n1764":{"id":"n1764","loc":[-85.642196,41.942818]},"n1765":{"id":"n1765","loc":[-85.642128,41.942819]},"n1766":{"id":"n1766","loc":[-85.642128,41.942801]},"n1767":{"id":"n1767","loc":[-85.640943,41.942934]},"n1768":{"id":"n1768","loc":[-85.641035,41.942933]},"n1769":{"id":"n1769","loc":[-85.641032,41.942797]},"n177":{"id":"n177","loc":[-85.638852,41.94237]},"n1770":{"id":"n1770","loc":[-85.640997,41.942798]},"n1771":{"id":"n1771","loc":[-85.640996,41.942764]},"n1772":{"id":"n1772","loc":[-85.640861,41.942766]},"n1773":{"id":"n1773","loc":[-85.640862,41.942848]},"n1774":{"id":"n1774","loc":[-85.640941,41.942847]},"n1775":{"id":"n1775","loc":[-85.643766,41.942226]},"n1776":{"id":"n1776","loc":[-85.643768,41.942407]},"n1777":{"id":"n1777","loc":[-85.643218,41.94177]},"n1778":{"id":"n1778","loc":[-85.64321,41.941327]},"n1779":{"id":"n1779","loc":[-85.643649,41.941323]},"n178":{"id":"n178","loc":[-85.638892,41.94237]},"n1780":{"id":"n1780","loc":[-85.643656,41.941716]},"n1781":{"id":"n1781","loc":[-85.64358,41.941717]},"n1782":{"id":"n1782","loc":[-85.64358,41.941767]},"n1783":{"id":"n1783","loc":[-85.64382,41.941495]},"n1784":{"id":"n1784","loc":[-85.643817,41.941317]},"n1785":{"id":"n1785","loc":[-85.643235,41.941833]},"n1786":{"id":"n1786","loc":[-85.64335,41.941842]},"n1787":{"id":"n1787","loc":[-85.643504,41.941903]},"n1788":{"id":"n1788","loc":[-85.643554,41.941946]},"n1789":{"id":"n1789","loc":[-85.643618,41.942015]},"n179":{"id":"n179","loc":[-85.638891,41.942334]},"n1790":{"id":"n1790","loc":[-85.64346,41.941971]},"n1791":{"id":"n1791","loc":[-85.643528,41.942468]},"n1792":{"id":"n1792","loc":[-85.643621,41.942363]},"n1793":{"id":"n1793","loc":[-85.643496,41.942297]},"n1794":{"id":"n1794","loc":[-85.643446,41.942246]},"n1795":{"id":"n1795","loc":[-85.643398,41.942177]},"n1796":{"id":"n1796","loc":[-85.643398,41.942031]},"n1797":{"id":"n1797","loc":[-85.621531,41.952693]},"n1798":{"id":"n1798","loc":[-85.643221,41.942028]},"n1799":{"id":"n1799","loc":[-85.643225,41.942276]},"n18":{"id":"n18","loc":[-85.63345,41.94071]},"n180":{"id":"n180","loc":[-85.639037,41.942334]},"n1800":{"id":"n1800","loc":[-85.643265,41.942347]},"n1801":{"id":"n1801","loc":[-85.643323,41.942413]},"n1802":{"id":"n1802","loc":[-85.643411,41.94247]},"n1803":{"id":"n1803","loc":[-85.643459,41.942435]},"n1804":{"id":"n1804","loc":[-85.643767,41.942307]},"n1805":{"id":"n1805","loc":[-85.643661,41.942293]},"n1806":{"id":"n1806","loc":[-85.643578,41.942247]},"n1807":{"id":"n1807","loc":[-85.643522,41.942125]},"n1808":{"id":"n1808","loc":[-85.643515,41.942061]},"n1809":{"id":"n1809","loc":[-85.643346,41.941924]},"n181":{"id":"n181","loc":[-85.638074,41.941839]},"n1810":{"id":"n1810","loc":[-85.643086,41.94192]},"n1811":{"id":"n1811","loc":[-85.643529,41.94217]},"n1812":{"id":"n1812","loc":[-85.643489,41.942003]},"n1813":{"id":"n1813","loc":[-85.643295,41.941919]},"n1814":{"id":"n1814","loc":[-85.643305,41.942163]},"n1815":{"id":"n1815","loc":[-85.643354,41.942285]},"n1816":{"id":"n1816","loc":[-85.643472,41.942389]},"n1817":{"id":"n1817","loc":[-85.643608,41.942271]},"n1818":{"id":"n1818","loc":[-85.643876,41.941402]},"n1819":{"id":"n1819","loc":[-85.643818,41.941369]},"n182":{"id":"n182","loc":[-85.638076,41.941942]},"n1820":{"id":"n1820","loc":[-85.643682,41.941304]},"n1821":{"id":"n1821","loc":[-85.64359,41.941286]},"n1822":{"id":"n1822","loc":[-85.643317,41.941727]},"n1823":{"id":"n1823","loc":[-85.643301,41.941286]},"n1824":{"id":"n1824","loc":[-85.643553,41.941698]},"n1825":{"id":"n1825","loc":[-85.643543,41.941286]},"n1826":{"id":"n1826","loc":[-85.636967,41.940118]},"n1827":{"id":"n1827","loc":[-85.63378,41.940114]},"n1828":{"id":"n1828","loc":[-85.637254,41.940075]},"n1829":{"id":"n1829","loc":[-85.637002,41.941355]},"n183":{"id":"n183","loc":[-85.637955,41.941944]},"n1830":{"id":"n1830","loc":[-85.643532,41.94204]},"n1831":{"id":"n1831","loc":[-85.638235,41.942615]},"n1832":{"id":"n1832","loc":[-85.637039,41.942624]},"n1833":{"id":"n1833","loc":[-85.636369,41.94266]},"n1834":{"id":"n1834","loc":[-85.63582,41.942771],"tags":{"highway":"traffic_signals","traffic_signals":"emergency"}},"n1835":{"id":"n1835","loc":[-85.634873,41.943044]},"n1836":{"id":"n1836","loc":[-85.643482,41.941976]},"n1837":{"id":"n1837","loc":[-85.64345,41.941945]},"n1838":{"id":"n1838","loc":[-85.641885,41.943851]},"n1839":{"id":"n1839","loc":[-85.641915,41.945121]},"n184":{"id":"n184","loc":[-85.637953,41.94184]},"n1840":{"id":"n1840","loc":[-85.639454,41.943871]},"n1841":{"id":"n1841","loc":[-85.639491,41.945191]},"n1842":{"id":"n1842","loc":[-85.635768,41.940113]},"n1843":{"id":"n1843","loc":[-85.638206,41.941345]},"n1844":{"id":"n1844","loc":[-85.640721,41.94513]},"n1845":{"id":"n1845","loc":[-85.643137,41.945103]},"n1846":{"id":"n1846","loc":[-85.638199,41.940079]},"n1847":{"id":"n1847","loc":[-85.640688,41.943861]},"n1848":{"id":"n1848","loc":[-85.643397,41.941924]},"n1849":{"id":"n1849","loc":[-85.643117,41.943841]},"n185":{"id":"n185","loc":[-85.637953,41.941866]},"n1850":{"id":"n1850","loc":[-85.636731,41.94263]},"n1851":{"id":"n1851","loc":[-85.63518,41.942955],"tags":{"highway":"crossing"}},"n1852":{"id":"n1852","loc":[-85.636152,41.942695]},"n1853":{"id":"n1853","loc":[-85.644202,41.941499]},"n1854":{"id":"n1854","loc":[-85.644211,41.942116]},"n1855":{"id":"n1855","loc":[-85.644233,41.942404]},"n1856":{"id":"n1856","loc":[-85.644231,41.942223]},"n1857":{"id":"n1857","loc":[-85.644133,41.941315]},"n1858":{"id":"n1858","loc":[-85.644136,41.941493]},"n1859":{"id":"n1859","loc":[-85.644345,41.942307]},"n186":{"id":"n186","loc":[-85.637873,41.941867]},"n1860":{"id":"n1860","loc":[-85.644232,41.942304]},"n1861":{"id":"n1861","loc":[-85.644134,41.941403]},"n1862":{"id":"n1862","loc":[-85.63607,41.943005],"tags":{"addr:city":"Three Rivers","addr:housenumber":"333","addr:postcode":"49093","addr:state":"MI","addr:street":"Michigan Avenue","amenity":"fire_station","name":"Three Rivers Fire Department"}},"n1863":{"id":"n1863","loc":[-85.637,41.941236]},"n1864":{"id":"n1864","loc":[-85.634476,41.941475]},"n1865":{"id":"n1865","loc":[-85.635036,41.941858]},"n1866":{"id":"n1866","loc":[-85.635362,41.941962]},"n1867":{"id":"n1867","loc":[-85.635796,41.941962]},"n1868":{"id":"n1868","loc":[-85.63295,41.943006]},"n1869":{"id":"n1869","loc":[-85.634692,41.943098]},"n187":{"id":"n187","loc":[-85.637877,41.941975]},"n1870":{"id":"n1870","loc":[-85.633128,41.940484]},"n1871":{"id":"n1871","loc":[-85.633117,41.942798]},"n1872":{"id":"n1872","loc":[-85.633303,41.942412]},"n1873":{"id":"n1873","loc":[-85.633482,41.941912]},"n1874":{"id":"n1874","loc":[-85.633455,41.941359]},"n1875":{"id":"n1875","loc":[-85.633162,41.942679]},"n1876":{"id":"n1876","loc":[-85.634274,41.943479]},"n1877":{"id":"n1877","loc":[-85.634678,41.942909]},"n1878":{"id":"n1878","loc":[-85.6339,41.941453]},"n1879":{"id":"n1879","loc":[-85.634571,41.942774]},"n188":{"id":"n188","loc":[-85.636855,41.942488]},"n1880":{"id":"n1880","loc":[-85.63419,41.941732]},"n1881":{"id":"n1881","loc":[-85.634067,41.941565]},"n1882":{"id":"n1882","loc":[-85.63436,41.942358]},"n1883":{"id":"n1883","loc":[-85.634327,41.942247]},"n1884":{"id":"n1884","loc":[-85.633391,41.941231]},"n1885":{"id":"n1885","loc":[-85.634303,41.941972]},"n1886":{"id":"n1886","loc":[-85.633541,41.940147]},"n1887":{"id":"n1887","loc":[-85.633433,41.940252]},"n1888":{"id":"n1888","loc":[-85.633402,41.940411]},"n1889":{"id":"n1889","loc":[-85.633551,41.941023]},"n189":{"id":"n189","loc":[-85.636702,41.942488]},"n1890":{"id":"n1890","loc":[-85.633719,41.941186]},"n1891":{"id":"n1891","loc":[-85.633067,41.941845]},"n1892":{"id":"n1892","loc":[-85.634902,41.942766]},"n1893":{"id":"n1893","loc":[-85.634603,41.942202]},"n1894":{"id":"n1894","loc":[-85.634858,41.942152]},"n1895":{"id":"n1895","loc":[-85.634842,41.942269]},"n1896":{"id":"n1896","loc":[-85.634907,41.942313]},"n1897":{"id":"n1897","loc":[-85.635049,41.942331]},"n1898":{"id":"n1898","loc":[-85.635101,41.942281]},"n1899":{"id":"n1899","loc":[-85.635129,41.942144]},"n19":{"id":"n19","loc":[-85.633009,41.942229]},"n190":{"id":"n190","loc":[-85.636702,41.942434]},"n1900":{"id":"n1900","loc":[-85.635531,41.942143]},"n1901":{"id":"n1901","loc":[-85.635534,41.942577]},"n1902":{"id":"n1902","loc":[-85.635158,41.942656]},"n1903":{"id":"n1903","loc":[-85.635121,41.942703]},"n1904":{"id":"n1904","loc":[-85.635087,41.941508]},"n1905":{"id":"n1905","loc":[-85.63536,41.941106]},"n1906":{"id":"n1906","loc":[-85.635442,41.941094]},"n1907":{"id":"n1907","loc":[-85.635508,41.941104]},"n1908":{"id":"n1908","loc":[-85.635569,41.941125]},"n1909":{"id":"n1909","loc":[-85.635583,41.941106]},"n191":{"id":"n191","loc":[-85.636761,41.942434]},"n1910":{"id":"n1910","loc":[-85.635555,41.940976]},"n1911":{"id":"n1911","loc":[-85.635501,41.940915]},"n1912":{"id":"n1912","loc":[-85.635392,41.940922]},"n1913":{"id":"n1913","loc":[-85.635276,41.940974]},"n1914":{"id":"n1914","loc":[-85.63517,41.941204]},"n1915":{"id":"n1915","loc":[-85.634888,41.941517]},"n1916":{"id":"n1916","loc":[-85.634897,41.941576]},"n1917":{"id":"n1917","loc":[-85.634961,41.94164]},"n1918":{"id":"n1918","loc":[-85.635028,41.941659]},"n1919":{"id":"n1919","loc":[-85.635118,41.941621]},"n192":{"id":"n192","loc":[-85.636761,41.942369]},"n1920":{"id":"n1920","loc":[-85.635085,41.941558]},"n1921":{"id":"n1921","loc":[-85.63504,41.94136]},"n1922":{"id":"n1922","loc":[-85.635221,41.941077]},"n1923":{"id":"n1923","loc":[-85.634387,41.941559]},"n1924":{"id":"n1924","loc":[-85.634351,41.941587]},"n1925":{"id":"n1925","loc":[-85.634416,41.941756]},"n1926":{"id":"n1926","loc":[-85.634461,41.941797]},"n1927":{"id":"n1927","loc":[-85.634501,41.941819]},"n1928":{"id":"n1928","loc":[-85.634597,41.941816]},"n1929":{"id":"n1929","loc":[-85.634732,41.941724]},"n193":{"id":"n193","loc":[-85.636855,41.942369]},"n1930":{"id":"n1930","loc":[-85.634672,41.941775]},"n1931":{"id":"n1931","loc":[-85.633403,41.939101]},"n1932":{"id":"n1932","loc":[-85.633297,41.939397]},"n1933":{"id":"n1933","loc":[-85.633205,41.939674]},"n1934":{"id":"n1934","loc":[-85.63322,41.939777]},"n1935":{"id":"n1935","loc":[-85.633345,41.939936]},"n1936":{"id":"n1936","loc":[-85.633376,41.940002]},"n1937":{"id":"n1937","loc":[-85.633266,41.940228]},"n1938":{"id":"n1938","loc":[-85.633236,41.940352]},"n1939":{"id":"n1939","loc":[-85.633282,41.94063]},"n194":{"id":"n194","loc":[-85.636645,41.94249]},"n1940":{"id":"n1940","loc":[-85.633364,41.940874]},"n1941":{"id":"n1941","loc":[-85.633439,41.941052]},"n1942":{"id":"n1942","loc":[-85.633582,41.941172]},"n1943":{"id":"n1943","loc":[-85.633748,41.941273]},"n1944":{"id":"n1944","loc":[-85.634317,41.941527]},"n1945":{"id":"n1945","loc":[-85.634389,41.94174]},"n1946":{"id":"n1946","loc":[-85.634441,41.941801]},"n1947":{"id":"n1947","loc":[-85.634514,41.941837]},"n1948":{"id":"n1948","loc":[-85.634485,41.942005]},"n1949":{"id":"n1949","loc":[-85.63457,41.942202]},"n195":{"id":"n195","loc":[-85.636565,41.94249]},"n1950":{"id":"n1950","loc":[-85.634869,41.942769]},"n1951":{"id":"n1951","loc":[-85.634943,41.942792]},"n1952":{"id":"n1952","loc":[-85.635139,41.942882]},"n1953":{"id":"n1953","loc":[-85.634962,41.943161]},"n1954":{"id":"n1954","loc":[-85.635002,41.943131]},"n1955":{"id":"n1955","loc":[-85.635005,41.943091]},"n1956":{"id":"n1956","loc":[-85.635216,41.943033]},"n1957":{"id":"n1957","loc":[-85.634817,41.94267]},"n1958":{"id":"n1958","loc":[-85.634614,41.942599]},"n1959":{"id":"n1959","loc":[-85.634494,41.942381]},"n196":{"id":"n196","loc":[-85.636565,41.942474]},"n1960":{"id":"n1960","loc":[-85.634486,41.9423]},"n1961":{"id":"n1961","loc":[-85.634671,41.941795]},"n1962":{"id":"n1962","loc":[-85.634595,41.941831]},"n1963":{"id":"n1963","loc":[-85.634332,41.941866]},"n1964":{"id":"n1964","loc":[-85.634207,41.941885]},"n1965":{"id":"n1965","loc":[-85.634133,41.941892]},"n1966":{"id":"n1966","loc":[-85.634131,41.942203]},"n1967":{"id":"n1967","loc":[-85.634047,41.942327]},"n1968":{"id":"n1968","loc":[-85.634219,41.942793]},"n1969":{"id":"n1969","loc":[-85.634061,41.942392]},"n197":{"id":"n197","loc":[-85.636514,41.942474]},"n1970":{"id":"n1970","loc":[-85.633989,41.942407]},"n1971":{"id":"n1971","loc":[-85.633971,41.942356]},"n1972":{"id":"n1972","loc":[-85.63361,41.942423]},"n1973":{"id":"n1973","loc":[-85.633714,41.942682]},"n1974":{"id":"n1974","loc":[-85.633698,41.942863]},"n1975":{"id":"n1975","loc":[-85.633882,41.942865]},"n1976":{"id":"n1976","loc":[-85.633941,41.943007]},"n1977":{"id":"n1977","loc":[-85.633887,41.943035]},"n1978":{"id":"n1978","loc":[-85.633768,41.942815]},"n1979":{"id":"n1979","loc":[-85.633682,41.942351]},"n198":{"id":"n198","loc":[-85.636514,41.942326]},"n1980":{"id":"n1980","loc":[-85.634037,41.942273]},"n1981":{"id":"n1981","loc":[-85.634029,41.942252]},"n1982":{"id":"n1982","loc":[-85.633673,41.942331]},"n1983":{"id":"n1983","loc":[-85.634219,41.942571]},"n1984":{"id":"n1984","loc":[-85.634252,41.942565]},"n1985":{"id":"n1985","loc":[-85.634144,41.942299]},"n1986":{"id":"n1986","loc":[-85.634115,41.942306]},"n1987":{"id":"n1987","loc":[-85.634059,41.943094]},"n1988":{"id":"n1988","loc":[-85.633944,41.942903]},"n1989":{"id":"n1989","loc":[-85.634311,41.942821]},"n199":{"id":"n199","loc":[-85.636561,41.942326]},"n1990":{"id":"n1990","loc":[-85.634351,41.94277]},"n1991":{"id":"n1991","loc":[-85.634153,41.942254]},"n1992":{"id":"n1992","loc":[-85.634092,41.94222]},"n1993":{"id":"n1993","loc":[-85.633571,41.942336]},"n1994":{"id":"n1994","loc":[-85.633513,41.942387]},"n1995":{"id":"n1995","loc":[-85.633509,41.942455]},"n1996":{"id":"n1996","loc":[-85.63363,41.942665]},"n1997":{"id":"n1997","loc":[-85.63414,41.94286]},"n1998":{"id":"n1998","loc":[-85.63397,41.942449]},"n1999":{"id":"n1999","loc":[-85.633551,41.942529]},"n2":{"id":"n2","loc":[-85.627421,41.953877]},"n20":{"id":"n20","loc":[-85.633013,41.941438]},"n200":{"id":"n200","loc":[-85.636561,41.942311]},"n2000":{"id":"n2000","loc":[-85.633741,41.942493]},"n2001":{"id":"n2001","loc":[-85.633894,41.942869]},"n2002":{"id":"n2002","loc":[-85.634132,41.941954]},"n2003":{"id":"n2003","loc":[-85.634032,41.942038]},"n2004":{"id":"n2004","loc":[-85.633765,41.942238]},"n2005":{"id":"n2005","loc":[-85.63376,41.942268]},"n2006":{"id":"n2006","loc":[-85.633768,41.942293]},"n2007":{"id":"n2007","loc":[-85.633808,41.942386]},"n2008":{"id":"n2008","loc":[-85.634946,41.941663]},"n2009":{"id":"n2009","loc":[-85.63511,41.941697]},"n201":{"id":"n201","loc":[-85.636621,41.942311]},"n2010":{"id":"n2010","loc":[-85.635337,41.94168]},"n2011":{"id":"n2011","loc":[-85.634997,41.942251]},"n2012":{"id":"n2012","loc":[-85.635013,41.942173]},"n2013":{"id":"n2013","loc":[-85.634876,41.942157]},"n2014":{"id":"n2014","loc":[-85.634859,41.942235]},"n2015":{"id":"n2015","loc":[-85.634992,41.941951]},"n2016":{"id":"n2016","loc":[-85.634952,41.941877]},"n2017":{"id":"n2017","loc":[-85.634844,41.94191]},"n2018":{"id":"n2018","loc":[-85.634884,41.941983]},"n2019":{"id":"n2019","loc":[-85.635189,41.941691]},"n202":{"id":"n202","loc":[-85.636621,41.942351]},"n2020":{"id":"n2020","loc":[-85.635089,41.941896]},"n2021":{"id":"n2021","loc":[-85.635077,41.941964]},"n2022":{"id":"n2022","loc":[-85.635058,41.942147]},"n2023":{"id":"n2023","loc":[-85.635099,41.942161]},"n2024":{"id":"n2024","loc":[-85.635099,41.942213]},"n2025":{"id":"n2025","loc":[-85.635079,41.942285]},"n2026":{"id":"n2026","loc":[-85.635047,41.942316]},"n2027":{"id":"n2027","loc":[-85.634925,41.9423]},"n2028":{"id":"n2028","loc":[-85.634911,41.942276]},"n2029":{"id":"n2029","loc":[-85.634917,41.942242]},"n203":{"id":"n203","loc":[-85.63666,41.942351]},"n2030":{"id":"n2030","loc":[-85.634698,41.941898]},"n2031":{"id":"n2031","loc":[-85.634964,41.941878]},"n2032":{"id":"n2032","loc":[-85.635025,41.941929]},"n2033":{"id":"n2033","loc":[-85.634862,41.941887]},"n2034":{"id":"n2034","loc":[-85.634811,41.94181]},"n2035":{"id":"n2035","loc":[-85.634731,41.941745]},"n2036":{"id":"n2036","loc":[-85.634933,41.94176]},"n2037":{"id":"n2037","loc":[-85.634942,41.942145]},"n2038":{"id":"n2038","loc":[-85.634944,41.942065]},"n2039":{"id":"n2039","loc":[-85.634914,41.941996]},"n204":{"id":"n204","loc":[-85.63666,41.942453]},"n2040":{"id":"n2040","loc":[-85.634981,41.941979]},"n2041":{"id":"n2041","loc":[-85.633419,41.942172]},"n2042":{"id":"n2042","loc":[-85.633509,41.941631]},"n2043":{"id":"n2043","loc":[-85.633686,41.942937]},"n2044":{"id":"n2044","loc":[-85.633371,41.942722]},"n2045":{"id":"n2045","loc":[-85.633291,41.942538]},"n2046":{"id":"n2046","loc":[-85.633902,41.940941]},"n2047":{"id":"n2047","loc":[-85.635254,41.940939]},"n2048":{"id":"n2048","loc":[-85.635686,41.940829]},"n2049":{"id":"n2049","loc":[-85.635712,41.942681]},"n205":{"id":"n205","loc":[-85.636645,41.942453]},"n2050":{"id":"n2050","loc":[-85.633721,41.942118]},"n2051":{"id":"n2051","loc":[-85.633698,41.942057]},"n2052":{"id":"n2052","loc":[-85.633591,41.942079]},"n2053":{"id":"n2053","loc":[-85.633614,41.94214]},"n2054":{"id":"n2054","loc":[-85.633968,41.941099]},"n2055":{"id":"n2055","loc":[-85.633907,41.941138]},"n2056":{"id":"n2056","loc":[-85.633968,41.941197]},"n2057":{"id":"n2057","loc":[-85.63404,41.941162]},"n2058":{"id":"n2058","loc":[-85.634839,41.941665]},"n2059":{"id":"n2059","loc":[-85.635314,41.943035]},"n206":{"id":"n206","loc":[-85.636394,41.942471]},"n2060":{"id":"n2060","loc":[-85.634919,41.943142]},"n2061":{"id":"n2061","loc":[-85.636433,41.942959],"tags":{"addr:city":"Three Rivers","addr:housenumber":"333","addr:postcode":"49093","addr:state":"MI","addr:street":"Michigan Avenue","amenity":"townhall","name":"Three Rivers City Hall"}},"n2062":{"id":"n2062","loc":[-85.637039,41.942789]},"n2063":{"id":"n2063","loc":[-85.636333,41.94279]},"n2064":{"id":"n2064","loc":[-85.634484,41.940726]},"n2065":{"id":"n2065","loc":[-85.634483,41.940603]},"n2066":{"id":"n2066","loc":[-85.634908,41.940601]},"n2067":{"id":"n2067","loc":[-85.634908,41.94053]},"n2068":{"id":"n2068","loc":[-85.634934,41.94053]},"n2069":{"id":"n2069","loc":[-85.634934,41.940496]},"n207":{"id":"n207","loc":[-85.636262,41.942472]},"n2070":{"id":"n2070","loc":[-85.63504,41.940495]},"n2071":{"id":"n2071","loc":[-85.63504,41.940531]},"n2072":{"id":"n2072","loc":[-85.635068,41.940531]},"n2073":{"id":"n2073","loc":[-85.635071,41.940794]},"n2074":{"id":"n2074","loc":[-85.635183,41.940793]},"n2075":{"id":"n2075","loc":[-85.635185,41.940916]},"n2076":{"id":"n2076","loc":[-85.634799,41.940919]},"n2077":{"id":"n2077","loc":[-85.634798,41.940798]},"n2078":{"id":"n2078","loc":[-85.634925,41.940797]},"n2079":{"id":"n2079","loc":[-85.634924,41.940724]},"n208":{"id":"n208","loc":[-85.636261,41.94233]},"n2080":{"id":"n2080","loc":[-85.637448,41.938233]},"n2081":{"id":"n2081","loc":[-85.634168,41.943279]},"n2082":{"id":"n2082","loc":[-85.635744,41.938248]},"n2083":{"id":"n2083","loc":[-85.638744,41.951211]},"n2084":{"id":"n2084","loc":[-85.636421,41.946392]},"n2085":{"id":"n2085","loc":[-85.635965,41.945809]},"n2086":{"id":"n2086","loc":[-85.635683,41.945449]},"n2087":{"id":"n2087","loc":[-85.635281,41.945025]},"n2088":{"id":"n2088","loc":[-85.632443,41.942574]},"n2089":{"id":"n2089","loc":[-85.638243,41.943674]},"n209":{"id":"n209","loc":[-85.636353,41.942329]},"n2090":{"id":"n2090","loc":[-85.638228,41.943747]},"n2091":{"id":"n2091","loc":[-85.638163,41.943797]},"n2092":{"id":"n2092","loc":[-85.638089,41.943832]},"n2093":{"id":"n2093","loc":[-85.637969,41.943841]},"n2094":{"id":"n2094","loc":[-85.637841,41.943833]},"n2095":{"id":"n2095","loc":[-85.637342,41.943734]},"n2096":{"id":"n2096","loc":[-85.637232,41.943707]},"n2097":{"id":"n2097","loc":[-85.637163,41.943668]},"n2098":{"id":"n2098","loc":[-85.637118,41.943615]},"n2099":{"id":"n2099","loc":[-85.637078,41.943494]},"n21":{"id":"n21","loc":[-85.634126,41.942228]},"n210":{"id":"n210","loc":[-85.636354,41.94239]},"n2100":{"id":"n2100","loc":[-85.632903,41.998429],"tags":{"railway":"level_crossing"}},"n2101":{"id":"n2101","loc":[-85.633616,41.943581],"tags":{"railway":"level_crossing"}},"n2102":{"id":"n2102","loc":[-85.636943,41.947311]},"n2103":{"id":"n2103","loc":[-85.6376,41.94854]},"n2104":{"id":"n2104","loc":[-85.634565,41.93631]},"n2105":{"id":"n2105","loc":[-85.629597,41.942562]},"n2106":{"id":"n2106","loc":[-85.630821,41.943077]},"n2107":{"id":"n2107","loc":[-85.627473,41.940659]},"n2108":{"id":"n2108","loc":[-85.629708,41.942872]},"n2109":{"id":"n2109","loc":[-85.634093,41.935448]},"n211":{"id":"n211","loc":[-85.636393,41.94239]},"n2110":{"id":"n2110","loc":[-85.630413,41.94366]},"n2111":{"id":"n2111","loc":[-85.630488,41.942662]},"n2112":{"id":"n2112","loc":[-85.63361,41.936749]},"n2113":{"id":"n2113","loc":[-85.630038,41.941808]},"n2114":{"id":"n2114","loc":[-85.632016,41.942922]},"n2115":{"id":"n2115","loc":[-85.631525,41.944303]},"n2116":{"id":"n2116","loc":[-85.626862,41.94022]},"n2117":{"id":"n2117","loc":[-85.629673,41.94121]},"n2118":{"id":"n2118","loc":[-85.632752,41.943101]},"n2119":{"id":"n2119","loc":[-85.631147,41.943201]},"n212":{"id":"n212","loc":[-85.63444,41.943176]},"n2120":{"id":"n2120","loc":[-85.624974,41.940579]},"n2121":{"id":"n2121","loc":[-85.629518,41.941783]},"n2122":{"id":"n2122","loc":[-85.632349,41.942699]},"n2123":{"id":"n2123","loc":[-85.628418,41.940356]},"n2124":{"id":"n2124","loc":[-85.629147,41.94129]},"n2125":{"id":"n2125","loc":[-85.631111,41.943979]},"n2126":{"id":"n2126","loc":[-85.632087,41.940013]},"n2127":{"id":"n2127","loc":[-85.634469,41.935057]},"n2128":{"id":"n2128","loc":[-85.630097,41.943449]},"n2129":{"id":"n2129","loc":[-85.6331,41.937878]},"n213":{"id":"n213","loc":[-85.63375,41.942814]},"n2130":{"id":"n2130","loc":[-85.625274,41.941114]},"n2131":{"id":"n2131","loc":[-85.632632,41.941217]},"n2132":{"id":"n2132","loc":[-85.632739,41.941926]},"n2133":{"id":"n2133","loc":[-85.631647,41.94366]},"n2134":{"id":"n2134","loc":[-85.635059,41.935456]},"n2135":{"id":"n2135","loc":[-85.631259,41.944349]},"n2136":{"id":"n2136","loc":[-85.626336,41.940811]},"n2137":{"id":"n2137","loc":[-85.631507,41.943875]},"n2138":{"id":"n2138","loc":[-85.625081,41.940859]},"n2139":{"id":"n2139","loc":[-85.625778,41.940093]},"n214":{"id":"n214","loc":[-85.633674,41.942869]},"n2140":{"id":"n2140","loc":[-85.632641,41.942436]},"n2141":{"id":"n2141","loc":[-85.628825,41.941034]},"n2142":{"id":"n2142","loc":[-85.627913,41.940292]},"n2143":{"id":"n2143","loc":[-85.628943,41.940516]},"n2144":{"id":"n2144","loc":[-85.63139,41.943941]},"n2145":{"id":"n2145","loc":[-85.630081,41.94204]},"n2146":{"id":"n2146","loc":[-85.632194,41.93963]},"n2147":{"id":"n2147","loc":[-85.632913,41.93939]},"n2148":{"id":"n2148","loc":[-85.632001,41.943492]},"n2149":{"id":"n2149","loc":[-85.63149,41.943154]},"n215":{"id":"n215","loc":[-85.633542,41.942768]},"n2150":{"id":"n2150","loc":[-85.625167,41.940117]},"n2151":{"id":"n2151","loc":[-85.63287,41.939941]},"n2152":{"id":"n2152","loc":[-85.630789,41.943732]},"n2153":{"id":"n2153","loc":[-85.632173,41.940348]},"n2154":{"id":"n2154","loc":[-85.626587,41.940113]},"n2155":{"id":"n2155","loc":[-85.62684,41.940667]},"n2156":{"id":"n2156","loc":[-85.632527,41.938904]},"n2157":{"id":"n2157","loc":[-85.624866,41.94018]},"n2158":{"id":"n2158","loc":[-85.633267,41.93872]},"n2159":{"id":"n2159","loc":[-85.62934,41.940843]},"n216":{"id":"n216","loc":[-85.633618,41.942714]},"n2160":{"id":"n2160","loc":[-85.62272,41.953817]},"n2161":{"id":"n2161","loc":[-85.622555,41.954453]},"n2162":{"id":"n2162","loc":[-85.637225,41.944128]},"n2163":{"id":"n2163","loc":[-85.622628,41.953683]},"n2164":{"id":"n2164","loc":[-85.635441,41.943989]},"n2165":{"id":"n2165","loc":[-85.622629,41.953807]},"n2166":{"id":"n2166","loc":[-85.62262,41.953807]},"n2167":{"id":"n2167","loc":[-85.62262,41.953837]},"n2168":{"id":"n2168","loc":[-85.622532,41.953838]},"n2169":{"id":"n2169","loc":[-85.637469,41.944579]},"n217":{"id":"n217","loc":[-85.634001,41.942336]},"n2170":{"id":"n2170","loc":[-85.63688,41.943935]},"n2171":{"id":"n2171","loc":[-85.638263,41.946367]},"n2172":{"id":"n2172","loc":[-85.622532,41.953807]},"n2173":{"id":"n2173","loc":[-85.622353,41.953808]},"n2174":{"id":"n2174","loc":[-85.622352,41.953685]},"n2175":{"id":"n2175","loc":[-85.622464,41.953684]},"n2176":{"id":"n2176","loc":[-85.622464,41.953648]},"n2177":{"id":"n2177","loc":[-85.637136,41.94576]},"n2178":{"id":"n2178","loc":[-85.622521,41.953648]},"n2179":{"id":"n2179","loc":[-85.637129,41.945415]},"n218":{"id":"n218","loc":[-85.633825,41.942376]},"n2180":{"id":"n2180","loc":[-85.637473,41.94607]},"n2181":{"id":"n2181","loc":[-85.622521,41.953683]},"n2182":{"id":"n2182","loc":[-85.622717,41.954104]},"n2183":{"id":"n2183","loc":[-85.637769,41.946095]},"n2184":{"id":"n2184","loc":[-85.623872,41.953515]},"n2185":{"id":"n2185","loc":[-85.623851,41.953588]},"n2186":{"id":"n2186","loc":[-85.631385,41.94433]},"n2187":{"id":"n2187","loc":[-85.623608,41.953543]},"n2188":{"id":"n2188","loc":[-85.637308,41.944882]},"n2189":{"id":"n2189","loc":[-85.634898,41.944041]},"n219":{"id":"n219","loc":[-85.633807,41.942334]},"n2190":{"id":"n2190","loc":[-85.623604,41.953442]},"n2191":{"id":"n2191","loc":[-85.623705,41.953442]},"n2192":{"id":"n2192","loc":[-85.623708,41.953493]},"n2193":{"id":"n2193","loc":[-85.624064,41.952655]},"n2194":{"id":"n2194","loc":[-85.62395,41.952654]},"n2195":{"id":"n2195","loc":[-85.623951,41.952579]},"n2196":{"id":"n2196","loc":[-85.637435,41.944342]},"n2197":{"id":"n2197","loc":[-85.624064,41.952579]},"n2198":{"id":"n2198","loc":[-85.623812,41.952648]},"n2199":{"id":"n2199","loc":[-85.623813,41.952705]},"n22":{"id":"n22","loc":[-85.633531,41.942357]},"n220":{"id":"n220","loc":[-85.633983,41.942294]},"n2200":{"id":"n2200","loc":[-85.637169,41.945098]},"n2201":{"id":"n2201","loc":[-85.623552,41.952707]},"n2202":{"id":"n2202","loc":[-85.623551,41.95263]},"n2203":{"id":"n2203","loc":[-85.623701,41.952629]},"n2204":{"id":"n2204","loc":[-85.635894,41.943719]},"n2205":{"id":"n2205","loc":[-85.637297,41.945992]},"n2206":{"id":"n2206","loc":[-85.623724,41.952648]},"n2207":{"id":"n2207","loc":[-85.623812,41.952438]},"n2208":{"id":"n2208","loc":[-85.625239,41.952197]},"n2209":{"id":"n2209","loc":[-85.625232,41.952257]},"n221":{"id":"n221","loc":[-85.634182,41.942495]},"n2210":{"id":"n2210","loc":[-85.635175,41.94408]},"n2211":{"id":"n2211","loc":[-85.636381,41.943761]},"n2212":{"id":"n2212","loc":[-85.625115,41.952249]},"n2213":{"id":"n2213","loc":[-85.638578,41.946644]},"n2214":{"id":"n2214","loc":[-85.625122,41.952189]},"n2215":{"id":"n2215","loc":[-85.625085,41.952031]},"n2216":{"id":"n2216","loc":[-85.636126,41.943713]},"n2217":{"id":"n2217","loc":[-85.635005,41.944041]},"n2218":{"id":"n2218","loc":[-85.63714,41.945328]},"n2219":{"id":"n2219","loc":[-85.634871,41.943292]},"n222":{"id":"n222","loc":[-85.634149,41.942503]},"n2220":{"id":"n2220","loc":[-85.635705,41.943799]},"n2221":{"id":"n2221","loc":[-85.634995,41.943576]},"n2222":{"id":"n2222","loc":[-85.635026,41.943829]},"n2223":{"id":"n2223","loc":[-85.632874,41.941031]},"n2224":{"id":"n2224","loc":[-85.632531,41.940233]},"n2225":{"id":"n2225","loc":[-85.634247,41.936003]},"n2226":{"id":"n2226","loc":[-85.62929,41.941127]},"n2227":{"id":"n2227","loc":[-85.630428,41.943266]},"n2228":{"id":"n2228","loc":[-85.631608,41.943425]},"n2229":{"id":"n2229","loc":[-85.632316,41.943042]},"n223":{"id":"n223","loc":[-85.634098,41.942373]},"n2230":{"id":"n2230","loc":[-85.628711,41.940744]},"n2231":{"id":"n2231","loc":[-85.627831,41.940536]},"n2232":{"id":"n2232","loc":[-85.625514,41.94052]},"n2233":{"id":"n2233","loc":[-85.631127,41.943545]},"n2234":{"id":"n2234","loc":[-85.632909,41.942531]},"n2235":{"id":"n2235","loc":[-85.632917,41.938796]},"n2236":{"id":"n2236","loc":[-85.626716,41.94044]},"n2237":{"id":"n2237","loc":[-85.630122,41.942852]},"n2238":{"id":"n2238","loc":[-85.632509,41.939674]},"n2239":{"id":"n2239","loc":[-85.634762,41.935237]},"n224":{"id":"n224","loc":[-85.634131,41.942366]},"n2240":{"id":"n2240","loc":[-85.63384,41.937025]},"n2241":{"id":"n2241","loc":[-85.629741,41.941909]},"n2242":{"id":"n2242","loc":[-85.635254,41.945001],"tags":{"railway":"level_crossing"}},"n2243":{"id":"n2243","loc":[-85.634005,41.938168]},"n2244":{"id":"n2244","loc":[-85.63393,41.938335]},"n2245":{"id":"n2245","loc":[-85.633859,41.93846]},"n2246":{"id":"n2246","loc":[-85.633663,41.938776]},"n2247":{"id":"n2247","loc":[-85.633513,41.938936]},"n2248":{"id":"n2248","loc":[-85.635295,41.943225]},"n2249":{"id":"n2249","loc":[-85.635393,41.943293]},"n225":{"id":"n225","loc":[-85.635986,41.94177]},"n2250":{"id":"n2250","loc":[-85.635645,41.94332]},"n2251":{"id":"n2251","loc":[-85.63629,41.943328]},"n2252":{"id":"n2252","loc":[-85.636554,41.943372]},"n2253":{"id":"n2253","loc":[-85.636869,41.943526]},"n2254":{"id":"n2254","loc":[-85.637099,41.943704]},"n2255":{"id":"n2255","loc":[-85.637268,41.943773]},"n2256":{"id":"n2256","loc":[-85.637483,41.943821]},"n2257":{"id":"n2257","loc":[-85.637616,41.943929]},"n2258":{"id":"n2258","loc":[-85.637752,41.944114]},"n2259":{"id":"n2259","loc":[-85.638399,41.944308]},"n226":{"id":"n226","loc":[-85.635982,41.941523]},"n2260":{"id":"n2260","loc":[-85.638573,41.944451]},"n2261":{"id":"n2261","loc":[-85.638702,41.944574]},"n2262":{"id":"n2262","loc":[-85.638718,41.944652]},"n2263":{"id":"n2263","loc":[-85.638715,41.944809]},"n2264":{"id":"n2264","loc":[-85.638766,41.944988]},"n2265":{"id":"n2265","loc":[-85.638773,41.945136]},"n2266":{"id":"n2266","loc":[-85.638705,41.945251]},"n2267":{"id":"n2267","loc":[-85.638335,41.944291]},"n2268":{"id":"n2268","loc":[-85.638474,41.944352]},"n2269":{"id":"n2269","loc":[-85.635408,41.943429]},"n227":{"id":"n227","loc":[-85.636108,41.941521]},"n2270":{"id":"n2270","loc":[-85.635271,41.943654]},"n2271":{"id":"n2271","loc":[-85.635266,41.943744]},"n2272":{"id":"n2272","loc":[-85.635271,41.943819]},"n2273":{"id":"n2273","loc":[-85.635192,41.943876]},"n2274":{"id":"n2274","loc":[-85.635129,41.943857]},"n2275":{"id":"n2275","loc":[-85.635122,41.943764]},"n2276":{"id":"n2276","loc":[-85.635124,41.943664]},"n2277":{"id":"n2277","loc":[-85.63515,41.943611]},"n2278":{"id":"n2278","loc":[-85.635106,41.943534]},"n2279":{"id":"n2279","loc":[-85.634972,41.943197]},"n228":{"id":"n228","loc":[-85.636109,41.941559]},"n2280":{"id":"n2280","loc":[-85.633978,41.938227]},"n2281":{"id":"n2281","loc":[-85.634216,41.943255]},"n2282":{"id":"n2282","loc":[-85.634434,41.943622]},"n2283":{"id":"n2283","loc":[-85.632406,41.940854]},"n2284":{"id":"n2284","loc":[-85.632488,41.941063],"tags":{"leisure":"slipway"}},"n2285":{"id":"n2285","loc":[-85.632726,41.941537]},"n2286":{"id":"n2286","loc":[-85.632639,41.94136]},"n2287":{"id":"n2287","loc":[-85.632704,41.941439]},"n2288":{"id":"n2288","loc":[-85.632289,41.940601]},"n2289":{"id":"n2289","loc":[-85.632541,41.942526]},"n229":{"id":"n229","loc":[-85.636145,41.941559]},"n2290":{"id":"n2290","loc":[-85.634058,41.943173]},"n2291":{"id":"n2291","loc":[-85.636175,41.945974]},"n2292":{"id":"n2292","loc":[-85.636528,41.945975]},"n2293":{"id":"n2293","loc":[-85.637092,41.945893]},"n2294":{"id":"n2294","loc":[-85.637881,41.945647]},"n2295":{"id":"n2295","loc":[-85.639329,41.945162]},"n2296":{"id":"n2296","loc":[-85.639323,41.945026]},"n2297":{"id":"n2297","loc":[-85.638826,41.945032]},"n2298":{"id":"n2298","loc":[-85.638817,41.944174]},"n2299":{"id":"n2299","loc":[-85.638291,41.94418]},"n23":{"id":"n23","loc":[-85.633504,41.942418]},"n230":{"id":"n230","loc":[-85.636145,41.941551]},"n2300":{"id":"n2300","loc":[-85.63828,41.943811]},"n2301":{"id":"n2301","loc":[-85.638195,41.943601]},"n2302":{"id":"n2302","loc":[-85.63719,41.943592]},"n2303":{"id":"n2303","loc":[-85.636697,41.943273]},"n2304":{"id":"n2304","loc":[-85.635375,41.943274]},"n2305":{"id":"n2305","loc":[-85.635091,41.943547]},"n2306":{"id":"n2306","loc":[-85.63442,41.944117]},"n2307":{"id":"n2307","loc":[-85.635117,41.943717]},"n2308":{"id":"n2308","loc":[-85.635601,41.945177]},"n2309":{"id":"n2309","loc":[-85.635819,41.945494]},"n231":{"id":"n231","loc":[-85.636312,41.941549]},"n2310":{"id":"n2310","loc":[-85.635303,41.944891]},"n2311":{"id":"n2311","loc":[-85.637674,41.943802]},"n2312":{"id":"n2312","loc":[-85.638263,41.944272]},"n2313":{"id":"n2313","loc":[-85.634267,41.935266]},"n2314":{"id":"n2314","loc":[-85.639788,41.945152]},"n2315":{"id":"n2315","loc":[-85.639645,41.945167]},"n2316":{"id":"n2316","loc":[-85.639362,41.945233]},"n2317":{"id":"n2317","loc":[-85.638616,41.945163]},"n2318":{"id":"n2318","loc":[-85.638514,41.944936]},"n2319":{"id":"n2319","loc":[-85.638578,41.94503]},"n232":{"id":"n232","loc":[-85.636314,41.941649]},"n2320":{"id":"n2320","loc":[-85.638578,41.945215]},"n2321":{"id":"n2321","loc":[-85.640495,41.947015]},"n2322":{"id":"n2322","loc":[-85.639577,41.946495]},"n2323":{"id":"n2323","loc":[-85.638935,41.946087]},"n2324":{"id":"n2324","loc":[-85.637535,41.94584]},"n2325":{"id":"n2325","loc":[-85.638357,41.945404]},"n2326":{"id":"n2326","loc":[-85.638051,41.94553]},"n2327":{"id":"n2327","loc":[-85.637732,41.945555]},"n2328":{"id":"n2328","loc":[-85.637657,41.945524]},"n2329":{"id":"n2329","loc":[-85.637598,41.945467]},"n233":{"id":"n233","loc":[-85.636152,41.94165]},"n2330":{"id":"n2330","loc":[-85.637669,41.945318]},"n2331":{"id":"n2331","loc":[-85.637894,41.945171]},"n2332":{"id":"n2332","loc":[-85.637923,41.945082]},"n2333":{"id":"n2333","loc":[-85.63793,41.944756]},"n2334":{"id":"n2334","loc":[-85.637976,41.944696]},"n2335":{"id":"n2335","loc":[-85.638044,41.944671]},"n2336":{"id":"n2336","loc":[-85.638129,41.944597]},"n2337":{"id":"n2337","loc":[-85.638252,41.944413]},"n2338":{"id":"n2338","loc":[-85.638092,41.945442]},"n2339":{"id":"n2339","loc":[-85.638409,41.945315]},"n234":{"id":"n234","loc":[-85.636152,41.941628]},"n2340":{"id":"n2340","loc":[-85.638325,41.944771]},"n2341":{"id":"n2341","loc":[-85.638103,41.944744]},"n2342":{"id":"n2342","loc":[-85.637976,41.944781]},"n2343":{"id":"n2343","loc":[-85.637983,41.944865]},"n2344":{"id":"n2344","loc":[-85.638063,41.945074]},"n2345":{"id":"n2345","loc":[-85.638041,41.945206]},"n2346":{"id":"n2346","loc":[-85.637907,41.945309]},"n2347":{"id":"n2347","loc":[-85.637925,41.94539]},"n2348":{"id":"n2348","loc":[-85.637998,41.94545]},"n2349":{"id":"n2349","loc":[-85.637135,41.946254]},"n235":{"id":"n235","loc":[-85.63611,41.941628]},"n2350":{"id":"n2350","loc":[-85.636837,41.946615]},"n2351":{"id":"n2351","loc":[-85.637954,41.948909]},"n2352":{"id":"n2352","loc":[-85.638382,41.949786]},"n2353":{"id":"n2353","loc":[-85.639367,41.951242]},"n2354":{"id":"n2354","loc":[-85.640554,41.951777]},"n2355":{"id":"n2355","loc":[-85.6411,41.952234]},"n2356":{"id":"n2356","loc":[-85.641742,41.952657]},"n2357":{"id":"n2357","loc":[-85.642321,41.952941]},"n2358":{"id":"n2358","loc":[-85.64277,41.953228]},"n2359":{"id":"n2359","loc":[-85.643333,41.953825]},"n236":{"id":"n236","loc":[-85.636113,41.941768]},"n2360":{"id":"n2360","loc":[-85.643579,41.954365]},"n2361":{"id":"n2361","loc":[-85.644439,41.954105]},"n2362":{"id":"n2362","loc":[-85.64506,41.954]},"n2363":{"id":"n2363","loc":[-85.645483,41.953911]},"n2364":{"id":"n2364","loc":[-85.646046,41.953853]},"n2365":{"id":"n2365","loc":[-85.646318,41.953717]},"n2366":{"id":"n2366","loc":[-85.646276,41.953414]},"n2367":{"id":"n2367","loc":[-85.631063,41.957478],"tags":{"emergency":"fire_hydrant"}},"n2368":{"id":"n2368","loc":[-85.630996,41.955857],"tags":{"emergency":"fire_hydrant"}},"n2369":{"id":"n2369","loc":[-85.630976,41.954608],"tags":{"emergency":"fire_hydrant"}},"n237":{"id":"n237","loc":[-85.635983,41.941589],"tags":{"entrance":"yes"}},"n2370":{"id":"n2370","loc":[-85.646,41.953154]},"n2371":{"id":"n2371","loc":[-85.645222,41.953193]},"n2372":{"id":"n2372","loc":[-85.644732,41.953181]},"n2373":{"id":"n2373","loc":[-85.644064,41.953298]},"n2374":{"id":"n2374","loc":[-85.643818,41.953177]},"n2375":{"id":"n2375","loc":[-85.644001,41.95284]},"n2376":{"id":"n2376","loc":[-85.628174,41.95456],"tags":{"emergency":"fire_hydrant"}},"n2377":{"id":"n2377","loc":[-85.644267,41.952591]},"n2378":{"id":"n2378","loc":[-85.644288,41.952328]},"n2379":{"id":"n2379","loc":[-85.627276,41.953987],"tags":{"emergency":"fire_hydrant"}},"n238":{"id":"n238","loc":[-85.635906,41.94159]},"n2380":{"id":"n2380","loc":[-85.644262,41.952153]},"n2381":{"id":"n2381","loc":[-85.644168,41.95204]},"n2382":{"id":"n2382","loc":[-85.64421,41.951749]},"n2383":{"id":"n2383","loc":[-85.64385,41.951586]},"n2384":{"id":"n2384","loc":[-85.62736,41.955964],"tags":{"emergency":"fire_hydrant"}},"n2385":{"id":"n2385","loc":[-85.626307,41.957198],"tags":{"emergency":"fire_hydrant"}},"n2386":{"id":"n2386","loc":[-85.643589,41.951323]},"n2387":{"id":"n2387","loc":[-85.62747,41.957509],"tags":{"emergency":"fire_hydrant"}},"n2388":{"id":"n2388","loc":[-85.628665,41.957492],"tags":{"emergency":"fire_hydrant"}},"n2389":{"id":"n2389","loc":[-85.642535,41.951031]},"n239":{"id":"n239","loc":[-85.635883,41.940182]},"n2390":{"id":"n2390","loc":[-85.642269,41.95088]},"n2391":{"id":"n2391","loc":[-85.641878,41.950814]},"n2392":{"id":"n2392","loc":[-85.641549,41.950806]},"n2393":{"id":"n2393","loc":[-85.641103,41.950549]},"n2394":{"id":"n2394","loc":[-85.630864,41.959046],"tags":{"emergency":"fire_hydrant"}},"n2395":{"id":"n2395","loc":[-85.632249,41.958969],"tags":{"emergency":"fire_hydrant"}},"n2396":{"id":"n2396","loc":[-85.641037,41.949821]},"n2397":{"id":"n2397","loc":[-85.641006,41.949433]},"n2398":{"id":"n2398","loc":[-85.632232,41.95859],"tags":{"emergency":"fire_hydrant"}},"n2399":{"id":"n2399","loc":[-85.632071,41.958345],"tags":{"emergency":"fire_hydrant"}},"n24":{"id":"n24","loc":[-85.634346,41.942792]},"n240":{"id":"n240","loc":[-85.635916,41.94264]},"n2400":{"id":"n2400","loc":[-85.632228,41.9573],"tags":{"emergency":"fire_hydrant"}},"n2401":{"id":"n2401","loc":[-85.641152,41.948257]},"n2402":{"id":"n2402","loc":[-85.641055,41.947304]},"n2403":{"id":"n2403","loc":[-85.638022,41.945897]},"n2404":{"id":"n2404","loc":[-85.638672,41.950778]},"n2405":{"id":"n2405","loc":[-85.63666,41.944492],"tags":{"name":"Memory Isle","place":"island"}},"n2406":{"id":"n2406","loc":[-85.635,41.946389],"tags":{"amenity":"post_office","name":"Three Rivers Post Office"}},"n2407":{"id":"n2407","loc":[-85.633676,41.946036]},"n2408":{"id":"n2408","loc":[-85.633736,41.946078]},"n2409":{"id":"n2409","loc":[-85.633997,41.946185]},"n241":{"id":"n241","loc":[-85.635795,41.941906]},"n2410":{"id":"n2410","loc":[-85.634448,41.945626],"tags":{"highway":"traffic_signals","traffic_signals":"signal"}},"n2411":{"id":"n2411","loc":[-85.63456,41.945731],"tags":{"crossing":"zebra","highway":"crossing"}},"n2412":{"id":"n2412","loc":[-85.634592,41.94578]},"n2413":{"id":"n2413","loc":[-85.634607,41.945815]},"n2414":{"id":"n2414","loc":[-85.634614,41.945864]},"n2415":{"id":"n2415","loc":[-85.636066,41.946185]},"n2416":{"id":"n2416","loc":[-85.636128,41.946352]},"n2417":{"id":"n2417","loc":[-85.636142,41.946452]},"n2418":{"id":"n2418","loc":[-85.635327,41.945292]},"n2419":{"id":"n2419","loc":[-85.635648,41.94558]},"n242":{"id":"n242","loc":[-85.635909,41.941906]},"n2420":{"id":"n2420","loc":[-85.635769,41.945729]},"n2421":{"id":"n2421","loc":[-85.637349,41.945897]},"n2422":{"id":"n2422","loc":[-85.632211,41.95596],"tags":{"emergency":"fire_hydrant"}},"n2423":{"id":"n2423","loc":[-85.635942,41.94598]},"n2424":{"id":"n2424","loc":[-85.636443,41.946042]},"n2425":{"id":"n2425","loc":[-85.635819,41.946052]},"n2426":{"id":"n2426","loc":[-85.636669,41.946025]},"n2427":{"id":"n2427","loc":[-85.636832,41.946005]},"n2428":{"id":"n2428","loc":[-85.637039,41.945968]},"n2429":{"id":"n2429","loc":[-85.636291,41.946046]},"n243":{"id":"n243","loc":[-85.636359,41.941904]},"n2430":{"id":"n2430","loc":[-85.634005,41.943367]},"n2431":{"id":"n2431","loc":[-85.633366,41.943724]},"n2432":{"id":"n2432","loc":[-85.634617,41.946057]},"n2433":{"id":"n2433","loc":[-85.636534,41.944793]},"n2434":{"id":"n2434","loc":[-85.637055,41.945188]},"n2435":{"id":"n2435","loc":[-85.636153,41.944618]},"n2436":{"id":"n2436","loc":[-85.636803,41.944944]},"n2437":{"id":"n2437","loc":[-85.633389,41.945735]},"n2438":{"id":"n2438","loc":[-85.633536,41.94585]},"n2439":{"id":"n2439","loc":[-85.63363,41.945993]},"n244":{"id":"n244","loc":[-85.636351,41.941438]},"n2440":{"id":"n2440","loc":[-85.633268,41.94568]},"n2441":{"id":"n2441","loc":[-85.635947,41.94546]},"n2442":{"id":"n2442","loc":[-85.636277,41.945268]},"n2443":{"id":"n2443","loc":[-85.635203,41.944287]},"n2444":{"id":"n2444","loc":[-85.634876,41.944477]},"n2445":{"id":"n2445","loc":[-85.634975,41.944419]},"n2446":{"id":"n2446","loc":[-85.633877,41.943438]},"n2447":{"id":"n2447","loc":[-85.63508,41.945113]},"n2448":{"id":"n2448","loc":[-85.635372,41.944932]},"n2449":{"id":"n2449","loc":[-85.636594,41.945935]},"n245":{"id":"n245","loc":[-85.635903,41.941436]},"n2450":{"id":"n2450","loc":[-85.636901,41.945747]},"n2451":{"id":"n2451","loc":[-85.636329,41.945228]},"n2452":{"id":"n2452","loc":[-85.636025,41.945417]},"n2453":{"id":"n2453","loc":[-85.634002,41.944644]},"n2454":{"id":"n2454","loc":[-85.63407,41.944692]},"n2455":{"id":"n2455","loc":[-85.634114,41.944756]},"n2456":{"id":"n2456","loc":[-85.633762,41.944809]},"n2457":{"id":"n2457","loc":[-85.634184,41.944807]},"n2458":{"id":"n2458","loc":[-85.634291,41.944819]},"n2459":{"id":"n2459","loc":[-85.634639,41.944845]},"n246":{"id":"n246","loc":[-85.635788,41.941436]},"n2460":{"id":"n2460","loc":[-85.633822,41.944861]},"n2461":{"id":"n2461","loc":[-85.63411,41.944855]},"n2462":{"id":"n2462","loc":[-85.63435,41.944872]},"n2463":{"id":"n2463","loc":[-85.63441,41.944903]},"n2464":{"id":"n2464","loc":[-85.633883,41.944913]},"n2465":{"id":"n2465","loc":[-85.634164,41.944896]},"n2466":{"id":"n2466","loc":[-85.633487,41.944926]},"n2467":{"id":"n2467","loc":[-85.634736,41.944929]},"n2468":{"id":"n2468","loc":[-85.633944,41.944965]},"n2469":{"id":"n2469","loc":[-85.633555,41.944983]},"n247":{"id":"n247","loc":[-85.635929,41.941511]},"n2470":{"id":"n2470","loc":[-85.633995,41.945013]},"n2471":{"id":"n2471","loc":[-85.633614,41.945037]},"n2472":{"id":"n2472","loc":[-85.634848,41.945031]},"n2473":{"id":"n2473","loc":[-85.634049,41.945061]},"n2474":{"id":"n2474","loc":[-85.633678,41.945094]},"n2475":{"id":"n2475","loc":[-85.63317,41.945111]},"n2476":{"id":"n2476","loc":[-85.633357,41.945103]},"n2477":{"id":"n2477","loc":[-85.633728,41.945136]},"n2478":{"id":"n2478","loc":[-85.634146,41.945148]},"n2479":{"id":"n2479","loc":[-85.633416,41.945157]},"n248":{"id":"n248","loc":[-85.635929,41.941317]},"n2480":{"id":"n2480","loc":[-85.634625,41.945172]},"n2481":{"id":"n2481","loc":[-85.633239,41.945174]},"n2482":{"id":"n2482","loc":[-85.63469,41.945185]},"n2483":{"id":"n2483","loc":[-85.634661,41.945203]},"n2484":{"id":"n2484","loc":[-85.63348,41.945214]},"n2485":{"id":"n2485","loc":[-85.633578,41.945221]},"n2486":{"id":"n2486","loc":[-85.634742,41.945231]},"n2487":{"id":"n2487","loc":[-85.634251,41.94525]},"n2488":{"id":"n2488","loc":[-85.633524,41.945254]},"n2489":{"id":"n2489","loc":[-85.63468,41.945271]},"n249":{"id":"n249","loc":[-85.636414,41.941316]},"n2490":{"id":"n2490","loc":[-85.633885,41.945272]},"n2491":{"id":"n2491","loc":[-85.634795,41.945288]},"n2492":{"id":"n2492","loc":[-85.634742,41.94532]},"n2493":{"id":"n2493","loc":[-85.633946,41.945327]},"n2494":{"id":"n2494","loc":[-85.634844,41.945331]},"n2495":{"id":"n2495","loc":[-85.63435,41.945349]},"n2496":{"id":"n2496","loc":[-85.633733,41.945357]},"n2497":{"id":"n2497","loc":[-85.633987,41.945375]},"n2498":{"id":"n2498","loc":[-85.634911,41.945419]},"n2499":{"id":"n2499","loc":[-85.634049,41.945431]},"n25":{"id":"n25","loc":[-85.634333,41.942809]},"n250":{"id":"n250","loc":[-85.636414,41.941511]},"n2500":{"id":"n2500","loc":[-85.633705,41.945461]},"n2501":{"id":"n2501","loc":[-85.633642,41.945408]},"n2502":{"id":"n2502","loc":[-85.634493,41.945475]},"n2503":{"id":"n2503","loc":[-85.634106,41.945484]},"n2504":{"id":"n2504","loc":[-85.635008,41.945505]},"n2505":{"id":"n2505","loc":[-85.633757,41.945506]},"n2506":{"id":"n2506","loc":[-85.634542,41.945519]},"n2507":{"id":"n2507","loc":[-85.634162,41.945536]},"n2508":{"id":"n2508","loc":[-85.633843,41.945547]},"n2509":{"id":"n2509","loc":[-85.634919,41.94556]},"n251":{"id":"n251","loc":[-85.636819,41.941617]},"n2510":{"id":"n2510","loc":[-85.633818,41.945561]},"n2511":{"id":"n2511","loc":[-85.634638,41.94559]},"n2512":{"id":"n2512","loc":[-85.633901,41.945598]},"n2513":{"id":"n2513","loc":[-85.634257,41.945626]},"n2514":{"id":"n2514","loc":[-85.633967,41.945652]},"n2515":{"id":"n2515","loc":[-85.634735,41.945676]},"n2516":{"id":"n2516","loc":[-85.635057,41.945683]},"n2517":{"id":"n2517","loc":[-85.635296,41.945703]},"n2518":{"id":"n2518","loc":[-85.635112,41.945703]},"n2519":{"id":"n2519","loc":[-85.634782,41.945729]},"n252":{"id":"n252","loc":[-85.636718,41.941619]},"n2520":{"id":"n2520","loc":[-85.634052,41.945747]},"n2521":{"id":"n2521","loc":[-85.635296,41.945757]},"n2522":{"id":"n2522","loc":[-85.635314,41.945757]},"n2523":{"id":"n2523","loc":[-85.635112,41.945761]},"n2524":{"id":"n2524","loc":[-85.63484,41.945778]},"n2525":{"id":"n2525","loc":[-85.635314,41.945938]},"n2526":{"id":"n2526","loc":[-85.63484,41.945922]},"n2527":{"id":"n2527","loc":[-85.635461,41.944879]},"n2528":{"id":"n2528","loc":[-85.636024,41.945384]},"n2529":{"id":"n2529","loc":[-85.636145,41.945312]},"n253":{"id":"n253","loc":[-85.636716,41.941509]},"n2530":{"id":"n2530","loc":[-85.6356,41.944797]},"n2531":{"id":"n2531","loc":[-85.635135,41.944354]},"n2532":{"id":"n2532","loc":[-85.632988,41.945369]},"n2533":{"id":"n2533","loc":[-85.633376,41.94563]},"n2534":{"id":"n2534","loc":[-85.633539,41.945534]},"n2535":{"id":"n2535","loc":[-85.633238,41.945248]},"n2536":{"id":"n2536","loc":[-85.633166,41.945216]},"n2537":{"id":"n2537","loc":[-85.633114,41.945188]},"n2538":{"id":"n2538","loc":[-85.633078,41.945127]},"n2539":{"id":"n2539","loc":[-85.633066,41.94508]},"n254":{"id":"n254","loc":[-85.636732,41.941509]},"n2540":{"id":"n2540","loc":[-85.633222,41.945358]},"n2541":{"id":"n2541","loc":[-85.633425,41.945541]},"n2542":{"id":"n2542","loc":[-85.63299,41.9455]},"n2543":{"id":"n2543","loc":[-85.634374,41.944327]},"n2544":{"id":"n2544","loc":[-85.633648,41.943697]},"n2545":{"id":"n2545","loc":[-85.633533,41.943764]},"n2546":{"id":"n2546","loc":[-85.634239,41.944417]},"n2547":{"id":"n2547","loc":[-85.634122,41.944395]},"n2548":{"id":"n2548","loc":[-85.634235,41.944326]},"n2549":{"id":"n2549","loc":[-85.633613,41.943787]},"n255":{"id":"n255","loc":[-85.636731,41.941461]},"n2550":{"id":"n2550","loc":[-85.633915,41.943613]},"n2551":{"id":"n2551","loc":[-85.634015,41.943555]},"n2552":{"id":"n2552","loc":[-85.63433,41.943839]},"n2553":{"id":"n2553","loc":[-85.634236,41.943894]},"n2554":{"id":"n2554","loc":[-85.635413,41.946052]},"n2555":{"id":"n2555","loc":[-85.635405,41.94569]},"n2556":{"id":"n2556","loc":[-85.635684,41.945925]},"n2557":{"id":"n2557","loc":[-85.635614,41.945742]},"n2558":{"id":"n2558","loc":[-85.635401,41.945745]},"n2559":{"id":"n2559","loc":[-85.635406,41.945928]},"n256":{"id":"n256","loc":[-85.636799,41.941461]},"n2560":{"id":"n2560","loc":[-85.633478,41.943663]},"n2561":{"id":"n2561","loc":[-85.633291,41.943526]},"n2562":{"id":"n2562","loc":[-85.633094,41.943541]},"n2563":{"id":"n2563","loc":[-85.633302,41.943492]},"n2564":{"id":"n2564","loc":[-85.633047,41.943623]},"n2565":{"id":"n2565","loc":[-85.633275,41.943562]},"n2566":{"id":"n2566","loc":[-85.633351,41.943518]},"n2567":{"id":"n2567","loc":[-85.633224,41.9434]},"n2568":{"id":"n2568","loc":[-85.633235,41.943369]},"n2569":{"id":"n2569","loc":[-85.635179,41.943911]},"n257":{"id":"n257","loc":[-85.6368,41.9415]},"n2570":{"id":"n2570","loc":[-85.635146,41.943918]},"n2571":{"id":"n2571","loc":[-85.634888,41.943905]},"n2572":{"id":"n2572","loc":[-85.634832,41.943911]},"n2573":{"id":"n2573","loc":[-85.634638,41.944007]},"n2574":{"id":"n2574","loc":[-85.634568,41.94405]},"n2575":{"id":"n2575","loc":[-85.635994,41.94501]},"n2576":{"id":"n2576","loc":[-85.636388,41.944608]},"n2577":{"id":"n2577","loc":[-85.636215,41.944787]},"n2578":{"id":"n2578","loc":[-85.637948,41.944587]},"n2579":{"id":"n2579","loc":[-85.637849,41.944567]},"n258":{"id":"n258","loc":[-85.636814,41.9415]},"n2580":{"id":"n2580","loc":[-85.637895,41.944455]},"n2581":{"id":"n2581","loc":[-85.637996,41.944477]},"n2582":{"id":"n2582","loc":[-85.635525,41.94337]},"n2583":{"id":"n2583","loc":[-85.637847,41.943923]},"n2584":{"id":"n2584","loc":[-85.637891,41.944124]},"n2585":{"id":"n2585","loc":[-85.638167,41.944229]},"n2586":{"id":"n2586","loc":[-85.638236,41.944097]},"n2587":{"id":"n2587","loc":[-85.638207,41.944025]},"n2588":{"id":"n2588","loc":[-85.638141,41.943997]},"n2589":{"id":"n2589","loc":[-85.638057,41.944015]},"n259":{"id":"n259","loc":[-85.636815,41.941538]},"n2590":{"id":"n2590","loc":[-85.637902,41.944231]},"n2591":{"id":"n2591","loc":[-85.638134,41.944307]},"n2592":{"id":"n2592","loc":[-85.638242,41.944294]},"n2593":{"id":"n2593","loc":[-85.638274,41.944222]},"n2594":{"id":"n2594","loc":[-85.638236,41.944174]},"n2595":{"id":"n2595","loc":[-85.638207,41.944157]},"n2596":{"id":"n2596","loc":[-85.637818,41.943984]},"n2597":{"id":"n2597","loc":[-85.634996,41.944439]},"n2598":{"id":"n2598","loc":[-85.633946,41.945804]},"n2599":{"id":"n2599","loc":[-85.634102,41.945864]},"n26":{"id":"n26","loc":[-85.634346,41.942744]},"n260":{"id":"n260","loc":[-85.636827,41.941538]},"n2600":{"id":"n2600","loc":[-85.633819,41.945756]},"n2601":{"id":"n2601","loc":[-85.634025,41.945975]},"n2602":{"id":"n2602","loc":[-85.633742,41.945867]},"n2603":{"id":"n2603","loc":[-85.63373,41.946004]},"n2604":{"id":"n2604","loc":[-85.633947,41.946081]},"n2605":{"id":"n2605","loc":[-85.633872,41.945917]},"n2606":{"id":"n2606","loc":[-85.633825,41.945985]},"n2607":{"id":"n2607","loc":[-85.633762,41.94596]},"n2608":{"id":"n2608","loc":[-85.634224,41.946037]},"n2609":{"id":"n2609","loc":[-85.634357,41.945851]},"n261":{"id":"n261","loc":[-85.636828,41.941584]},"n2610":{"id":"n2610","loc":[-85.634398,41.945813]},"n2611":{"id":"n2611","loc":[-85.634461,41.945812]},"n2612":{"id":"n2612","loc":[-85.634501,41.945852]},"n2613":{"id":"n2613","loc":[-85.634503,41.94597]},"n2614":{"id":"n2614","loc":[-85.634462,41.945971]},"n2615":{"id":"n2615","loc":[-85.634465,41.946036]},"n2616":{"id":"n2616","loc":[-85.634235,41.946072]},"n2617":{"id":"n2617","loc":[-85.634447,41.946036]},"n2618":{"id":"n2618","loc":[-85.634448,41.946052]},"n2619":{"id":"n2619","loc":[-85.634494,41.946051]},"n262":{"id":"n262","loc":[-85.636819,41.941585]},"n2620":{"id":"n2620","loc":[-85.634497,41.946144]},"n2621":{"id":"n2621","loc":[-85.634453,41.946144]},"n2622":{"id":"n2622","loc":[-85.634454,41.94616]},"n2623":{"id":"n2623","loc":[-85.634393,41.946161]},"n2624":{"id":"n2624","loc":[-85.634394,41.94618]},"n2625":{"id":"n2625","loc":[-85.634345,41.94618]},"n2626":{"id":"n2626","loc":[-85.634344,41.946162]},"n2627":{"id":"n2627","loc":[-85.63427,41.946163]},"n2628":{"id":"n2628","loc":[-85.634266,41.946071]},"n2629":{"id":"n2629","loc":[-85.634148,41.946163]},"n263":{"id":"n263","loc":[-85.636854,41.941714]},"n2630":{"id":"n2630","loc":[-85.634213,41.946072]},"n2631":{"id":"n2631","loc":[-85.633293,41.946309]},"n2632":{"id":"n2632","loc":[-85.633122,41.946239]},"n2633":{"id":"n2633","loc":[-85.633295,41.946005]},"n2634":{"id":"n2634","loc":[-85.633395,41.946047]},"n2635":{"id":"n2635","loc":[-85.633404,41.946035]},"n2636":{"id":"n2636","loc":[-85.633459,41.946057]},"n2637":{"id":"n2637","loc":[-85.633387,41.946154]},"n2638":{"id":"n2638","loc":[-85.633403,41.946161]},"n2639":{"id":"n2639","loc":[-85.634176,41.946415]},"n264":{"id":"n264","loc":[-85.636855,41.941774]},"n2640":{"id":"n2640","loc":[-85.634179,41.946339]},"n2641":{"id":"n2641","loc":[-85.634455,41.946345]},"n2642":{"id":"n2642","loc":[-85.634452,41.946422]},"n2643":{"id":"n2643","loc":[-85.63437,41.946421]},"n2644":{"id":"n2644","loc":[-85.634367,41.946497]},"n2645":{"id":"n2645","loc":[-85.634289,41.946495]},"n2646":{"id":"n2646","loc":[-85.634291,41.946448]},"n2647":{"id":"n2647","loc":[-85.634269,41.946448]},"n2648":{"id":"n2648","loc":[-85.63427,41.946417]},"n2649":{"id":"n2649","loc":[-85.63484,41.946328]},"n265":{"id":"n265","loc":[-85.636822,41.941774]},"n2650":{"id":"n2650","loc":[-85.634839,41.946187]},"n2651":{"id":"n2651","loc":[-85.635148,41.946186]},"n2652":{"id":"n2652","loc":[-85.635148,41.946216]},"n2653":{"id":"n2653","loc":[-85.63521,41.946216]},"n2654":{"id":"n2654","loc":[-85.63521,41.946348]},"n2655":{"id":"n2655","loc":[-85.635154,41.946348]},"n2656":{"id":"n2656","loc":[-85.635153,41.946327]},"n2657":{"id":"n2657","loc":[-85.634037,41.946957]},"n2658":{"id":"n2658","loc":[-85.634253,41.946953]},"n2659":{"id":"n2659","loc":[-85.63481,41.946543]},"n266":{"id":"n266","loc":[-85.636822,41.941778]},"n2660":{"id":"n2660","loc":[-85.634809,41.946459]},"n2661":{"id":"n2661","loc":[-85.635154,41.946458]},"n2662":{"id":"n2662","loc":[-85.635155,41.946554]},"n2663":{"id":"n2663","loc":[-85.635022,41.946547]},"n2664":{"id":"n2664","loc":[-85.635022,41.946573]},"n2665":{"id":"n2665","loc":[-85.634909,41.946574]},"n2666":{"id":"n2666","loc":[-85.634909,41.946561]},"n2667":{"id":"n2667","loc":[-85.634896,41.947159]},"n2668":{"id":"n2668","loc":[-85.634894,41.947032]},"n2669":{"id":"n2669","loc":[-85.635024,41.947031]},"n267":{"id":"n267","loc":[-85.636756,41.941779]},"n2670":{"id":"n2670","loc":[-85.635026,41.947158]},"n2671":{"id":"n2671","loc":[-85.635233,41.947105]},"n2672":{"id":"n2672","loc":[-85.635236,41.946991]},"n2673":{"id":"n2673","loc":[-85.635369,41.946993]},"n2674":{"id":"n2674","loc":[-85.635366,41.947107]},"n2675":{"id":"n2675","loc":[-85.634824,41.946929]},"n2676":{"id":"n2676","loc":[-85.634825,41.946818]},"n2677":{"id":"n2677","loc":[-85.63512,41.946819]},"n2678":{"id":"n2678","loc":[-85.635119,41.94693]},"n2679":{"id":"n2679","loc":[-85.634796,41.946806]},"n268":{"id":"n268","loc":[-85.636756,41.941774]},"n2680":{"id":"n2680","loc":[-85.634792,41.946604]},"n2681":{"id":"n2681","loc":[-85.634948,41.946602]},"n2682":{"id":"n2682","loc":[-85.634949,41.946645]},"n2683":{"id":"n2683","loc":[-85.634975,41.946644]},"n2684":{"id":"n2684","loc":[-85.634974,41.946599]},"n2685":{"id":"n2685","loc":[-85.635117,41.946598]},"n2686":{"id":"n2686","loc":[-85.635122,41.946801]},"n2687":{"id":"n2687","loc":[-85.634981,41.946803]},"n2688":{"id":"n2688","loc":[-85.634979,41.946752]},"n2689":{"id":"n2689","loc":[-85.634952,41.946752]},"n269":{"id":"n269","loc":[-85.636721,41.941774]},"n2690":{"id":"n2690","loc":[-85.634953,41.946804]},"n2691":{"id":"n2691","loc":[-85.634649,41.946841]},"n2692":{"id":"n2692","loc":[-85.634331,41.94684]},"n2693":{"id":"n2693","loc":[-85.634183,41.946809]},"n2694":{"id":"n2694","loc":[-85.633699,41.946607]},"n2695":{"id":"n2695","loc":[-85.634487,41.946664]},"n2696":{"id":"n2696","loc":[-85.634486,41.946598]},"n2697":{"id":"n2697","loc":[-85.63423,41.946599]},"n2698":{"id":"n2698","loc":[-85.634231,41.946662]},"n2699":{"id":"n2699","loc":[-85.634284,41.946662]},"n27":{"id":"n27","loc":[-85.634136,41.943183]},"n270":{"id":"n270","loc":[-85.63672,41.941714]},"n2700":{"id":"n2700","loc":[-85.634284,41.946679]},"n2701":{"id":"n2701","loc":[-85.634365,41.946679]},"n2702":{"id":"n2702","loc":[-85.634365,41.946664]},"n2703":{"id":"n2703","loc":[-85.635443,41.947015]},"n2704":{"id":"n2704","loc":[-85.635442,41.946801]},"n2705":{"id":"n2705","loc":[-85.63603,41.9468]},"n2706":{"id":"n2706","loc":[-85.636028,41.947016]},"n2707":{"id":"n2707","loc":[-85.635457,41.946582]},"n2708":{"id":"n2708","loc":[-85.635455,41.946211]},"n2709":{"id":"n2709","loc":[-85.635636,41.946579]},"n271":{"id":"n271","loc":[-85.636767,41.941713]},"n2710":{"id":"n2710","loc":[-85.635716,41.9468]},"n2711":{"id":"n2711","loc":[-85.635969,41.9468]},"n2712":{"id":"n2712","loc":[-85.635973,41.946295]},"n2713":{"id":"n2713","loc":[-85.636019,41.946484]},"n2714":{"id":"n2714","loc":[-85.636022,41.946388]},"n2715":{"id":"n2715","loc":[-85.635961,41.946493]},"n2716":{"id":"n2716","loc":[-85.635713,41.94621]},"n2717":{"id":"n2717","loc":[-85.635416,41.946142]},"n2718":{"id":"n2718","loc":[-85.635759,41.946203]},"n2719":{"id":"n2719","loc":[-85.636153,41.946747]},"n272":{"id":"n272","loc":[-85.636767,41.941706]},"n2720":{"id":"n2720","loc":[-85.635417,41.946915]},"n2721":{"id":"n2721","loc":[-85.636154,41.946915]},"n2722":{"id":"n2722","loc":[-85.635866,41.946473]},"n2723":{"id":"n2723","loc":[-85.635717,41.946633]},"n2724":{"id":"n2724","loc":[-85.635556,41.946166]},"n2725":{"id":"n2725","loc":[-85.63556,41.946556]},"n2726":{"id":"n2726","loc":[-85.635731,41.946594]},"n2727":{"id":"n2727","loc":[-85.635866,41.946595]},"n2728":{"id":"n2728","loc":[-85.635456,41.947028]},"n2729":{"id":"n2729","loc":[-85.635796,41.947023]},"n273":{"id":"n273","loc":[-85.636779,41.941698]},"n2730":{"id":"n2730","loc":[-85.635798,41.947091]},"n2731":{"id":"n2731","loc":[-85.63573,41.947092]},"n2732":{"id":"n2732","loc":[-85.635733,41.947233]},"n2733":{"id":"n2733","loc":[-85.636283,41.946863]},"n2734":{"id":"n2734","loc":[-85.63628,41.946706]},"n2735":{"id":"n2735","loc":[-85.636341,41.946705]},"n2736":{"id":"n2736","loc":[-85.636273,41.946584]},"n2737":{"id":"n2737","loc":[-85.636396,41.946545]},"n2738":{"id":"n2738","loc":[-85.636474,41.946684]},"n2739":{"id":"n2739","loc":[-85.636511,41.946861]},"n274":{"id":"n274","loc":[-85.636798,41.941697]},"n2740":{"id":"n2740","loc":[-85.633713,41.947184]},"n2741":{"id":"n2741","loc":[-85.633651,41.94716]},"n2742":{"id":"n2742","loc":[-85.633704,41.947085]},"n2743":{"id":"n2743","loc":[-85.6336,41.947044]},"n2744":{"id":"n2744","loc":[-85.633506,41.947177]},"n2745":{"id":"n2745","loc":[-85.629586,41.952469]},"n2746":{"id":"n2746","loc":[-85.634723,41.953681]},"n2747":{"id":"n2747","loc":[-85.63478,41.959007]},"n2748":{"id":"n2748","loc":[-85.632793,41.94405],"tags":{"highway":"traffic_signals","traffic_signals":"signal"}},"n2749":{"id":"n2749","loc":[-85.634648,41.947325]},"n275":{"id":"n275","loc":[-85.63681,41.941705]},"n2750":{"id":"n2750","loc":[-85.625078,41.952097]},"n2751":{"id":"n2751","loc":[-85.633195,41.94734]},"n2752":{"id":"n2752","loc":[-85.626447,41.957168]},"n2753":{"id":"n2753","loc":[-85.632023,41.949012]},"n2754":{"id":"n2754","loc":[-85.630835,41.950656]},"n2755":{"id":"n2755","loc":[-85.634655,41.948612]},"n2756":{"id":"n2756","loc":[-85.636182,41.948605]},"n2757":{"id":"n2757","loc":[-85.634729,41.954667]},"n2758":{"id":"n2758","loc":[-85.634686,41.951159]},"n2759":{"id":"n2759","loc":[-85.636206,41.951146]},"n276":{"id":"n276","loc":[-85.63681,41.941714]},"n2760":{"id":"n2760","loc":[-85.634668,41.949891]},"n2761":{"id":"n2761","loc":[-85.634701,41.952422]},"n2762":{"id":"n2762","loc":[-85.634747,41.955907]},"n2763":{"id":"n2763","loc":[-85.627975,41.954695]},"n2764":{"id":"n2764","loc":[-85.626832,41.954698]},"n2765":{"id":"n2765","loc":[-85.632278,41.948624]},"n2766":{"id":"n2766","loc":[-85.628639,41.953725]},"n2767":{"id":"n2767","loc":[-85.636233,41.95241]},"n2768":{"id":"n2768","loc":[-85.631385,41.949913]},"n2769":{"id":"n2769","loc":[-85.630486,41.951194]},"n277":{"id":"n277","loc":[-85.636861,41.942041]},"n2770":{"id":"n2770","loc":[-85.624937,41.952088]},"n2771":{"id":"n2771","loc":[-85.624945,41.952022]},"n2772":{"id":"n2772","loc":[-85.636162,41.94731]},"n2773":{"id":"n2773","loc":[-85.636188,41.949881]},"n2774":{"id":"n2774","loc":[-85.631422,41.948294]},"n2775":{"id":"n2775","loc":[-85.632844,41.945547]},"n2776":{"id":"n2776","loc":[-85.632484,41.945344]},"n2777":{"id":"n2777","loc":[-85.631775,41.944636]},"n2778":{"id":"n2778","loc":[-85.632656,41.945471]},"n2779":{"id":"n2779","loc":[-85.631959,41.944827]},"n278":{"id":"n278","loc":[-85.636862,41.942099]},"n2780":{"id":"n2780","loc":[-85.631679,41.94438]},"n2781":{"id":"n2781","loc":[-85.625129,41.959272]},"n2782":{"id":"n2782","loc":[-85.632446,41.944861]},"n2783":{"id":"n2783","loc":[-85.632804,41.945477]},"n2784":{"id":"n2784","loc":[-85.632255,41.944962]},"n2785":{"id":"n2785","loc":[-85.632736,41.944757]},"n2786":{"id":"n2786","loc":[-85.632543,41.94486]},"n2787":{"id":"n2787","loc":[-85.632889,41.945561]},"n2788":{"id":"n2788","loc":[-85.632091,41.944949]},"n2789":{"id":"n2789","loc":[-85.632537,41.944713]},"n279":{"id":"n279","loc":[-85.636807,41.942099]},"n2790":{"id":"n2790","loc":[-85.632279,41.94485]},"n2791":{"id":"n2791","loc":[-85.632749,41.943247]},"n2792":{"id":"n2792","loc":[-85.632824,41.943152]},"n2793":{"id":"n2793","loc":[-85.632929,41.94317]},"n2794":{"id":"n2794","loc":[-85.632897,41.943078]},"n2795":{"id":"n2795","loc":[-85.632626,41.943231]},"n2796":{"id":"n2796","loc":[-85.634048,41.947257]},"n2797":{"id":"n2797","loc":[-85.634264,41.947252]},"n2798":{"id":"n2798","loc":[-85.635418,41.947317]},"n2799":{"id":"n2799","loc":[-85.635461,41.947237]},"n28":{"id":"n28","loc":[-85.63821,41.944308]},"n280":{"id":"n280","loc":[-85.636807,41.942126]},"n2800":{"id":"n2800","loc":[-85.632868,41.946229]},"n2801":{"id":"n2801","loc":[-85.633673,41.947242]},"n2802":{"id":"n2802","loc":[-85.623604,41.945881],"tags":{"amenity":"school","name":"Barrows School"}},"n2803":{"id":"n2803","loc":[-85.627401,41.943496]},"n2804":{"id":"n2804","loc":[-85.627403,41.943625]},"n2805":{"id":"n2805","loc":[-85.626409,41.943215]},"n2806":{"id":"n2806","loc":[-85.624884,41.943508]},"n2807":{"id":"n2807","loc":[-85.625191,41.943509]},"n2808":{"id":"n2808","loc":[-85.624882,41.94382]},"n2809":{"id":"n2809","loc":[-85.624893,41.945618]},"n281":{"id":"n281","loc":[-85.636726,41.942126]},"n2810":{"id":"n2810","loc":[-85.624912,41.946524]},"n2811":{"id":"n2811","loc":[-85.622721,41.946535]},"n2812":{"id":"n2812","loc":[-85.627399,41.94469]},"n2813":{"id":"n2813","loc":[-85.622716,41.945622]},"n2814":{"id":"n2814","loc":[-85.624886,41.944724]},"n2815":{"id":"n2815","loc":[-85.622674,41.944737]},"n2816":{"id":"n2816","loc":[-85.625092,41.945063]},"n2817":{"id":"n2817","loc":[-85.625233,41.945064]},"n2818":{"id":"n2818","loc":[-85.625229,41.944871]},"n2819":{"id":"n2819","loc":[-85.625066,41.944871]},"n282":{"id":"n282","loc":[-85.636726,41.942098]},"n2820":{"id":"n2820","loc":[-85.625024,41.944901]},"n2821":{"id":"n2821","loc":[-85.625025,41.944924]},"n2822":{"id":"n2822","loc":[-85.625087,41.944926]},"n2823":{"id":"n2823","loc":[-85.625349,41.944506]},"n2824":{"id":"n2824","loc":[-85.625347,41.944388]},"n2825":{"id":"n2825","loc":[-85.625152,41.94439]},"n2826":{"id":"n2826","loc":[-85.625152,41.944431]},"n2827":{"id":"n2827","loc":[-85.625134,41.944431]},"n2828":{"id":"n2828","loc":[-85.625136,41.944508]},"n2829":{"id":"n2829","loc":[-85.623236,41.946341]},"n283":{"id":"n283","loc":[-85.636708,41.942098]},"n2830":{"id":"n2830","loc":[-85.623241,41.946067]},"n2831":{"id":"n2831","loc":[-85.623207,41.946067]},"n2832":{"id":"n2832","loc":[-85.623212,41.945827]},"n2833":{"id":"n2833","loc":[-85.622981,41.945825]},"n2834":{"id":"n2834","loc":[-85.622976,41.946063]},"n2835":{"id":"n2835","loc":[-85.623006,41.946063]},"n2836":{"id":"n2836","loc":[-85.623002,41.946256]},"n2837":{"id":"n2837","loc":[-85.623075,41.946256]},"n2838":{"id":"n2838","loc":[-85.623074,41.946339]},"n2839":{"id":"n2839","loc":[-85.624574,41.951755]},"n284":{"id":"n284","loc":[-85.636708,41.942041]},"n2840":{"id":"n2840","loc":[-85.62498,41.951844]},"n2841":{"id":"n2841","loc":[-85.625086,41.95188]},"n2842":{"id":"n2842","loc":[-85.625135,41.951922]},"n2843":{"id":"n2843","loc":[-85.615273,41.945637]},"n2844":{"id":"n2844","loc":[-85.620172,41.945627]},"n2845":{"id":"n2845","loc":[-85.625167,41.951985]},"n2846":{"id":"n2846","loc":[-85.622741,41.947437]},"n2847":{"id":"n2847","loc":[-85.624907,41.947428]},"n2848":{"id":"n2848","loc":[-85.627046,41.940995]},"n2849":{"id":"n2849","loc":[-85.627295,41.941304]},"n285":{"id":"n285","loc":[-85.635618,41.941852]},"n2850":{"id":"n2850","loc":[-85.627352,41.94148]},"n2851":{"id":"n2851","loc":[-85.62737,41.942261]},"n2852":{"id":"n2852","loc":[-85.6264,41.942263]},"n2853":{"id":"n2853","loc":[-85.622769,41.949228]},"n2854":{"id":"n2854","loc":[-85.624937,41.949218]},"n2855":{"id":"n2855","loc":[-85.630001,41.944664]},"n2856":{"id":"n2856","loc":[-85.624873,41.942022]},"n2857":{"id":"n2857","loc":[-85.622761,41.948333]},"n2858":{"id":"n2858","loc":[-85.624924,41.948334]},"n2859":{"id":"n2859","loc":[-85.620051,41.94383]},"n286":{"id":"n286","loc":[-85.635621,41.94202]},"n2860":{"id":"n2860","loc":[-85.627629,41.946498]},"n2861":{"id":"n2861","loc":[-85.622757,41.950111]},"n2862":{"id":"n2862","loc":[-85.623685,41.954624]},"n2863":{"id":"n2863","loc":[-85.621459,41.944756]},"n2864":{"id":"n2864","loc":[-85.628637,41.944676]},"n2865":{"id":"n2865","loc":[-85.630125,41.944654]},"n2866":{"id":"n2866","loc":[-85.625196,41.952097]},"n2867":{"id":"n2867","loc":[-85.630257,41.944637]},"n2868":{"id":"n2868","loc":[-85.631247,41.944459]},"n2869":{"id":"n2869","loc":[-85.624867,41.94159]},"n287":{"id":"n287","loc":[-85.63524,41.942023]},"n2870":{"id":"n2870","loc":[-85.624958,41.950343]},"n2871":{"id":"n2871","loc":[-85.624948,41.950484]},"n2872":{"id":"n2872","loc":[-85.624813,41.950983]},"n2873":{"id":"n2873","loc":[-85.624723,41.951789]},"n2874":{"id":"n2874","loc":[-85.624262,41.9512]},"n2875":{"id":"n2875","loc":[-85.62414,41.951201]},"n2876":{"id":"n2876","loc":[-85.624139,41.95112]},"n2877":{"id":"n2877","loc":[-85.628481,41.945611]},"n2878":{"id":"n2878","loc":[-85.620072,41.946538]},"n2879":{"id":"n2879","loc":[-85.622763,41.95099]},"n288":{"id":"n288","loc":[-85.635237,41.941855]},"n2880":{"id":"n2880","loc":[-85.62814,41.946963]},"n2881":{"id":"n2881","loc":[-85.628245,41.947031]},"n2882":{"id":"n2882","loc":[-85.628331,41.947066]},"n2883":{"id":"n2883","loc":[-85.629722,41.944444],"tags":{"leisure":"park","name":"Scouter Park"}},"n2884":{"id":"n2884","loc":[-85.629977,41.943907]},"n2885":{"id":"n2885","loc":[-85.629947,41.943775]},"n2886":{"id":"n2886","loc":[-85.629899,41.943625]},"n2887":{"id":"n2887","loc":[-85.632286,41.944257]},"n2888":{"id":"n2888","loc":[-85.632523,41.944179]},"n2889":{"id":"n2889","loc":[-85.632141,41.944293]},"n289":{"id":"n289","loc":[-85.635568,41.940475]},"n2890":{"id":"n2890","loc":[-85.631571,41.9444]},"n2891":{"id":"n2891","loc":[-85.643236,41.941895]},"n2892":{"id":"n2892","loc":[-85.62865,41.945353]},"n2893":{"id":"n2893","loc":[-85.628594,41.945481]},"n2894":{"id":"n2894","loc":[-85.628581,41.947169]},"n2895":{"id":"n2895","loc":[-85.631843,41.943793]},"n2896":{"id":"n2896","loc":[-85.632299,41.943472]},"n2897":{"id":"n2897","loc":[-85.631519,41.944881]},"n2898":{"id":"n2898","loc":[-85.628429,41.947219]},"n2899":{"id":"n2899","loc":[-85.63145,41.945162]},"n29":{"id":"n29","loc":[-85.637963,41.944263]},"n290":{"id":"n290","loc":[-85.634584,41.940477]},"n2900":{"id":"n2900","loc":[-85.630939,41.945519]},"n2901":{"id":"n2901","loc":[-85.62903,41.945719]},"n2902":{"id":"n2902","loc":[-85.630521,41.945559]},"n2903":{"id":"n2903","loc":[-85.629294,41.945585]},"n2904":{"id":"n2904","loc":[-85.629845,41.945543]},"n2905":{"id":"n2905","loc":[-85.631497,41.944625]},"n2906":{"id":"n2906","loc":[-85.630281,41.945553]},"n2907":{"id":"n2907","loc":[-85.628553,41.946973]},"n2908":{"id":"n2908","loc":[-85.631383,41.945338]},"n2909":{"id":"n2909","loc":[-85.628843,41.946103]},"n291":{"id":"n291","loc":[-85.634583,41.940203]},"n2910":{"id":"n2910","loc":[-85.631193,41.945473]},"n2911":{"id":"n2911","loc":[-85.628897,41.945944]},"n2912":{"id":"n2912","loc":[-85.628789,41.946454]},"n2913":{"id":"n2913","loc":[-85.632548,41.944563]},"n2914":{"id":"n2914","loc":[-85.627527,41.944555]},"n2915":{"id":"n2915","loc":[-85.62752,41.943726]},"n2916":{"id":"n2916","loc":[-85.627894,41.943723]},"n2917":{"id":"n2917","loc":[-85.627897,41.943919]},"n2918":{"id":"n2918","loc":[-85.627991,41.943934]},"n2919":{"id":"n2919","loc":[-85.628082,41.943966]},"n292":{"id":"n292","loc":[-85.635567,41.940201]},"n2920":{"id":"n2920","loc":[-85.628177,41.944015]},"n2921":{"id":"n2921","loc":[-85.628193,41.944048]},"n2922":{"id":"n2922","loc":[-85.628167,41.944054]},"n2923":{"id":"n2923","loc":[-85.628193,41.944094]},"n2924":{"id":"n2924","loc":[-85.628213,41.944144]},"n2925":{"id":"n2925","loc":[-85.628214,41.944199]},"n2926":{"id":"n2926","loc":[-85.62833,41.944196]},"n2927":{"id":"n2927","loc":[-85.628328,41.944262]},"n2928":{"id":"n2928","loc":[-85.628173,41.944262]},"n2929":{"id":"n2929","loc":[-85.628171,41.944293]},"n293":{"id":"n293","loc":[-85.635816,41.942673],"tags":{"crossing":"zebra","highway":"crossing"}},"n2930":{"id":"n2930","loc":[-85.628039,41.944296]},"n2931":{"id":"n2931","loc":[-85.62804,41.944329]},"n2932":{"id":"n2932","loc":[-85.627829,41.944335]},"n2933":{"id":"n2933","loc":[-85.627835,41.94455]},"n2936":{"id":"n2936","loc":[-85.632823,41.945994]},"n294":{"id":"n294","loc":[-85.635696,41.942712]},"n2940":{"id":"n2940","loc":[-85.632192,41.945973]},"n2941":{"id":"n2941","loc":[-85.63226,41.94587]},"n2942":{"id":"n2942","loc":[-85.632721,41.946036]},"n2943":{"id":"n2943","loc":[-85.632641,41.946142]},"n2944":{"id":"n2944","loc":[-85.62937,41.947467]},"n2945":{"id":"n2945","loc":[-85.62959,41.942936]},"n2946":{"id":"n2946","loc":[-85.629551,41.94284]},"n2947":{"id":"n2947","loc":[-85.629501,41.942704]},"n2948":{"id":"n2948","loc":[-85.629472,41.942578]},"n2949":{"id":"n2949","loc":[-85.629361,41.941801]},"n295":{"id":"n295","loc":[-85.635679,41.941962]},"n2950":{"id":"n2950","loc":[-85.629339,41.941716]},"n2951":{"id":"n2951","loc":[-85.629315,41.94166]},"n2952":{"id":"n2952","loc":[-85.629279,41.941602]},"n2953":{"id":"n2953","loc":[-85.629227,41.941556]},"n2954":{"id":"n2954","loc":[-85.624261,41.95112]},"n2955":{"id":"n2955","loc":[-85.629153,41.941524]},"n2956":{"id":"n2956","loc":[-85.626904,41.941098]},"n2957":{"id":"n2957","loc":[-85.624588,41.951294]},"n2958":{"id":"n2958","loc":[-85.631844,41.942945]},"n2959":{"id":"n2959","loc":[-85.625854,41.949222]},"n296":{"id":"n296","loc":[-85.635672,41.941337]},"n2960":{"id":"n2960","loc":[-85.625146,41.955238]},"n2961":{"id":"n2961","loc":[-85.626745,41.948296]},"n2962":{"id":"n2962","loc":[-85.625721,41.95524]},"n2963":{"id":"n2963","loc":[-85.624706,41.952317]},"n2964":{"id":"n2964","loc":[-85.62609,41.956147]},"n2965":{"id":"n2965","loc":[-85.624401,41.954928]},"n2966":{"id":"n2966","loc":[-85.626558,41.955367]},"n2967":{"id":"n2967","loc":[-85.62468,41.955096]},"n2968":{"id":"n2968","loc":[-85.624159,41.953929]},"n2969":{"id":"n2969","loc":[-85.62506,41.951113]},"n297":{"id":"n297","loc":[-85.635658,41.941284]},"n2970":{"id":"n2970","loc":[-85.624942,41.951591]},"n2971":{"id":"n2971","loc":[-85.627399,41.947546]},"n2972":{"id":"n2972","loc":[-85.627695,41.947404]},"n2973":{"id":"n2973","loc":[-85.625925,41.94896]},"n2974":{"id":"n2974","loc":[-85.625725,41.950211]},"n2975":{"id":"n2975","loc":[-85.627008,41.947963]},"n2976":{"id":"n2976","loc":[-85.624373,41.953458]},"n2977":{"id":"n2977","loc":[-85.624137,41.954392]},"n2978":{"id":"n2978","loc":[-85.628257,41.947307]},"n2979":{"id":"n2979","loc":[-85.625281,41.95066]},"n298":{"id":"n298","loc":[-85.635602,41.941166]},"n2980":{"id":"n2980","loc":[-85.625865,41.949804]},"n2981":{"id":"n2981","loc":[-85.626508,41.955932]},"n2982":{"id":"n2982","loc":[-85.626333,41.955216]},"n2983":{"id":"n2983","loc":[-85.626637,41.955676]},"n2984":{"id":"n2984","loc":[-85.624223,41.954599]},"n2985":{"id":"n2985","loc":[-85.626219,41.948671]},"n2986":{"id":"n2986","loc":[-85.624556,41.953043]},"n2987":{"id":"n2987","loc":[-85.625598,41.956302]},"n2988":{"id":"n2988","loc":[-85.624571,41.952971]},"n2989":{"id":"n2989","loc":[-85.627141,41.940727]},"n299":{"id":"n299","loc":[-85.635598,41.941138]},"n2990":{"id":"n2990","loc":[-85.627102,41.939144]},"n2991":{"id":"n2991","loc":[-85.627127,41.940086]},"n2992":{"id":"n2992","loc":[-85.627116,41.940843]},"n2993":{"id":"n2993","loc":[-85.627132,41.9402]},"n2994":{"id":"n2994","loc":[-85.629734,41.940078]},"n2995":{"id":"n2995","loc":[-85.6276,41.937412]},"n2996":{"id":"n2996","loc":[-85.627451,41.937549]},"n2997":{"id":"n2997","loc":[-85.627375,41.937618]},"n2998":{"id":"n2998","loc":[-85.627278,41.937728]},"n2999":{"id":"n2999","loc":[-85.627199,41.937842]},"n3":{"id":"n3","loc":[-85.627345,41.953983]},"n30":{"id":"n30","loc":[-85.637882,41.944205]},"n300":{"id":"n300","loc":[-85.635614,41.941076]},"n3000":{"id":"n3000","loc":[-85.627141,41.937981]},"n3001":{"id":"n3001","loc":[-85.627109,41.938153]},"n3002":{"id":"n3002","loc":[-85.627101,41.938699]},"n3003":{"id":"n3003","loc":[-85.628311,41.942261]},"n3004":{"id":"n3004","loc":[-85.628439,41.940082]},"n3005":{"id":"n3005","loc":[-85.619538,41.942622],"tags":{"leisure":"slipway"}},"n3006":{"id":"n3006","loc":[-85.619872,41.942618]},"n3007":{"id":"n3007","loc":[-85.619755,41.942612]},"n3008":{"id":"n3008","loc":[-85.619647,41.942628]},"n3009":{"id":"n3009","loc":[-85.619415,41.942626]},"n301":{"id":"n301","loc":[-85.635659,41.940956]},"n3010":{"id":"n3010","loc":[-85.619212,41.942623]},"n3011":{"id":"n3011","loc":[-85.631485,41.942472]},"n3012":{"id":"n3012","loc":[-85.630986,41.941786]},"n3013":{"id":"n3013","loc":[-85.631797,41.942006]},"n3014":{"id":"n3014","loc":[-85.630972,41.941162]},"n3015":{"id":"n3015","loc":[-85.631396,41.941611],"tags":{"railway":"level_crossing"}},"n3016":{"id":"n3016","loc":[-85.631878,41.941545]},"n3017":{"id":"n3017","loc":[-85.630461,41.94055]},"n3018":{"id":"n3018","loc":[-85.629751,41.939539],"tags":{"railway":"level_crossing"}},"n3019":{"id":"n3019","loc":[-85.631663,41.941513]},"n302":{"id":"n302","loc":[-85.635666,41.940922]},"n3020":{"id":"n3020","loc":[-85.631328,41.941375]},"n3021":{"id":"n3021","loc":[-85.632554,41.941779]},"n3022":{"id":"n3022","loc":[-85.63245,41.941769]},"n3023":{"id":"n3023","loc":[-85.632475,41.941644]},"n3024":{"id":"n3024","loc":[-85.632581,41.941654]},"n3025":{"id":"n3025","loc":[-85.631957,41.941352]},"n3026":{"id":"n3026","loc":[-85.632293,41.941139]},"n3027":{"id":"n3027","loc":[-85.632315,41.941153]},"n3028":{"id":"n3028","loc":[-85.632302,41.941262]},"n3029":{"id":"n3029","loc":[-85.63237,41.941267]},"n303":{"id":"n303","loc":[-85.635667,41.940877]},"n3030":{"id":"n3030","loc":[-85.632356,41.941538]},"n3031":{"id":"n3031","loc":[-85.632134,41.941678]},"n3032":{"id":"n3032","loc":[-85.631942,41.941687]},"n3033":{"id":"n3033","loc":[-85.63203,41.941694]},"n3034":{"id":"n3034","loc":[-85.632166,41.941555]},"n3035":{"id":"n3035","loc":[-85.632412,41.941416]},"n3036":{"id":"n3036","loc":[-85.63248,41.941342]},"n3037":{"id":"n3037","loc":[-85.632502,41.941259]},"n3038":{"id":"n3038","loc":[-85.632453,41.941161]},"n3039":{"id":"n3039","loc":[-85.63235,41.941103]},"n304":{"id":"n304","loc":[-85.635668,41.940655]},"n3040":{"id":"n3040","loc":[-85.632236,41.941118]},"n3041":{"id":"n3041","loc":[-85.631894,41.941355]},"n3042":{"id":"n3042","loc":[-85.631859,41.941411]},"n3043":{"id":"n3043","loc":[-85.632011,41.941587]},"n3044":{"id":"n3044","loc":[-85.632446,41.941379]},"n3045":{"id":"n3045","loc":[-85.632511,41.941416]},"n3046":{"id":"n3046","loc":[-85.632545,41.941634]},"n3047":{"id":"n3047","loc":[-85.632612,41.94164]},"n3048":{"id":"n3048","loc":[-85.632595,41.942197]},"n3049":{"id":"n3049","loc":[-85.632565,41.942241]},"n305":{"id":"n305","loc":[-85.635628,41.940617]},"n3050":{"id":"n3050","loc":[-85.632515,41.942256]},"n3051":{"id":"n3051","loc":[-85.63245,41.94223]},"n3052":{"id":"n3052","loc":[-85.632401,41.942174]},"n3053":{"id":"n3053","loc":[-85.632391,41.942115]},"n3054":{"id":"n3054","loc":[-85.632029,41.941859]},"n3055":{"id":"n3055","loc":[-85.631828,41.941639]},"n3056":{"id":"n3056","loc":[-85.631829,41.941508]},"n3057":{"id":"n3057","loc":[-85.631281,41.94312]},"n3058":{"id":"n3058","loc":[-85.631421,41.943065]},"n3059":{"id":"n3059","loc":[-85.631339,41.942949]},"n306":{"id":"n306","loc":[-85.635623,41.940272]},"n3060":{"id":"n3060","loc":[-85.631199,41.943004]},"n3061":{"id":"n3061","loc":[-85.631102,41.942931]},"n3062":{"id":"n3062","loc":[-85.631009,41.942809]},"n3063":{"id":"n3063","loc":[-85.631383,41.94265]},"n3064":{"id":"n3064","loc":[-85.631477,41.942773]},"n3065":{"id":"n3065","loc":[-85.630638,41.942809]},"n3066":{"id":"n3066","loc":[-85.630738,41.942943]},"n3067":{"id":"n3067","loc":[-85.630841,41.9429]},"n3068":{"id":"n3068","loc":[-85.630741,41.942766]},"n3069":{"id":"n3069","loc":[-85.63054,41.942603]},"n307":{"id":"n307","loc":[-85.635651,41.940183]},"n3070":{"id":"n3070","loc":[-85.630498,41.942619]},"n3071":{"id":"n3071","loc":[-85.630567,41.942718]},"n3072":{"id":"n3072","loc":[-85.630616,41.942698]},"n3073":{"id":"n3073","loc":[-85.630642,41.94273]},"n3074":{"id":"n3074","loc":[-85.630686,41.942714]},"n3075":{"id":"n3075","loc":[-85.630715,41.942754]},"n3076":{"id":"n3076","loc":[-85.6309,41.942681]},"n3077":{"id":"n3077","loc":[-85.630843,41.942605]},"n3078":{"id":"n3078","loc":[-85.6309,41.942581]},"n3079":{"id":"n3079","loc":[-85.630832,41.942487]},"n308":{"id":"n308","loc":[-85.63577,41.940183],"tags":{"crossing":"zebra","highway":"crossing"}},"n3080":{"id":"n3080","loc":[-85.630773,41.942509]},"n3081":{"id":"n3081","loc":[-85.630718,41.942436]},"n3082":{"id":"n3082","loc":[-85.630485,41.942524]},"n3083":{"id":"n3083","loc":[-85.631468,41.941233]},"n3084":{"id":"n3084","loc":[-85.631334,41.94114]},"n3085":{"id":"n3085","loc":[-85.632052,41.940568]},"n3086":{"id":"n3086","loc":[-85.63219,41.940663]},"n3087":{"id":"n3087","loc":[-85.631323,41.940834]},"n3088":{"id":"n3088","loc":[-85.631122,41.941002]},"n3089":{"id":"n3089","loc":[-85.631321,41.941133]},"n309":{"id":"n309","loc":[-85.636939,41.942544]},"n3090":{"id":"n3090","loc":[-85.631521,41.940966]},"n3091":{"id":"n3091","loc":[-85.631103,41.940253]},"n3092":{"id":"n3092","loc":[-85.631226,41.940211]},"n3093":{"id":"n3093","loc":[-85.631597,41.940805]},"n3094":{"id":"n3094","loc":[-85.631474,41.940847]},"n3095":{"id":"n3095","loc":[-85.631811,41.940534]},"n3096":{"id":"n3096","loc":[-85.631588,41.94061]},"n3097":{"id":"n3097","loc":[-85.631438,41.940366]},"n3098":{"id":"n3098","loc":[-85.631661,41.94029]},"n3099":{"id":"n3099","loc":[-85.630621,41.940041]},"n31":{"id":"n31","loc":[-85.63827,41.944203]},"n310":{"id":"n310","loc":[-85.636323,41.942552]},"n3100":{"id":"n3100","loc":[-85.630436,41.939773]},"n3101":{"id":"n3101","loc":[-85.63059,41.939714]},"n3102":{"id":"n3102","loc":[-85.630775,41.939983]},"n3103":{"id":"n3103","loc":[-85.63047,41.940167]},"n3104":{"id":"n3104","loc":[-85.63013,41.939686]},"n3105":{"id":"n3105","loc":[-85.630302,41.939618]},"n3106":{"id":"n3106","loc":[-85.630641,41.9401]},"n3107":{"id":"n3107","loc":[-85.630966,41.940619]},"n3108":{"id":"n3108","loc":[-85.630874,41.940493]},"n3109":{"id":"n3109","loc":[-85.630933,41.940469]},"n311":{"id":"n311","loc":[-85.636257,41.942555]},"n3110":{"id":"n3110","loc":[-85.630763,41.940236]},"n3111":{"id":"n3111","loc":[-85.63088,41.940189]},"n3112":{"id":"n3112","loc":[-85.631142,41.940548]},"n3113":{"id":"n3113","loc":[-85.630958,41.940871]},"n3114":{"id":"n3114","loc":[-85.630874,41.940778]},"n3115":{"id":"n3115","loc":[-85.631062,41.940684]},"n3116":{"id":"n3116","loc":[-85.631146,41.940777]},"n3117":{"id":"n3117","loc":[-85.632031,41.940575]},"n3118":{"id":"n3118","loc":[-85.631777,41.940186]},"n3119":{"id":"n3119","loc":[-85.631346,41.940179]},"n312":{"id":"n312","loc":[-85.636208,41.942561]},"n3120":{"id":"n3120","loc":[-85.631342,41.94012]},"n3121":{"id":"n3121","loc":[-85.631831,41.940118]},"n3122":{"id":"n3122","loc":[-85.632115,41.940543]},"n3123":{"id":"n3123","loc":[-85.631031,41.941683]},"n3124":{"id":"n3124","loc":[-85.630981,41.941608]},"n3125":{"id":"n3125","loc":[-85.631209,41.941516]},"n3126":{"id":"n3126","loc":[-85.631264,41.941586]},"n3127":{"id":"n3127","loc":[-85.630938,41.94155]},"n3128":{"id":"n3128","loc":[-85.631156,41.941462]},"n3129":{"id":"n3129","loc":[-85.631197,41.94152]},"n313":{"id":"n313","loc":[-85.636159,41.942573]},"n3130":{"id":"n3130","loc":[-85.630895,41.941485]},"n3131":{"id":"n3131","loc":[-85.630824,41.941389]},"n3132":{"id":"n3132","loc":[-85.630986,41.941323]},"n3133":{"id":"n3133","loc":[-85.631057,41.941419]},"n3134":{"id":"n3134","loc":[-85.630777,41.941328]},"n3135":{"id":"n3135","loc":[-85.630907,41.941274]},"n3136":{"id":"n3136","loc":[-85.630953,41.941335]},"n3137":{"id":"n3137","loc":[-85.630797,41.941247]},"n3138":{"id":"n3138","loc":[-85.630701,41.94117]},"n3139":{"id":"n3139","loc":[-85.630829,41.941113]},"n314":{"id":"n314","loc":[-85.635743,41.942881]},"n3140":{"id":"n3140","loc":[-85.6309,41.941201]},"n3141":{"id":"n3141","loc":[-85.630765,41.941206]},"n3142":{"id":"n3142","loc":[-85.630739,41.941218]},"n3143":{"id":"n3143","loc":[-85.630582,41.941039]},"n3144":{"id":"n3144","loc":[-85.630412,41.940818]},"n3145":{"id":"n3145","loc":[-85.630509,41.940777]},"n3146":{"id":"n3146","loc":[-85.630678,41.941004]},"n3147":{"id":"n3147","loc":[-85.630773,41.942166]},"n3148":{"id":"n3148","loc":[-85.630708,41.942074]},"n3149":{"id":"n3149","loc":[-85.630863,41.942013]},"n315":{"id":"n315","loc":[-85.635452,41.942966]},"n3150":{"id":"n3150","loc":[-85.630928,41.942105]},"n3151":{"id":"n3151","loc":[-85.630701,41.942026]},"n3152":{"id":"n3152","loc":[-85.630665,41.941971]},"n3153":{"id":"n3153","loc":[-85.630793,41.941918]},"n3154":{"id":"n3154","loc":[-85.630837,41.94197]},"n3155":{"id":"n3155","loc":[-85.630757,41.941871]},"n3156":{"id":"n3156","loc":[-85.630629,41.941923]},"n3157":{"id":"n3157","loc":[-85.630694,41.941783]},"n3158":{"id":"n3158","loc":[-85.630534,41.941847]},"n3159":{"id":"n3159","loc":[-85.630598,41.941935]},"n316":{"id":"n316","loc":[-85.634911,41.943118]},"n3160":{"id":"n3160","loc":[-85.631548,41.93938]},"n3161":{"id":"n3161","loc":[-85.631525,41.939919]},"n3162":{"id":"n3162","loc":[-85.631648,41.940043]},"n3163":{"id":"n3163","loc":[-85.624586,41.951121]},"n3164":{"id":"n3164","loc":[-85.622139,41.952064]},"n3165":{"id":"n3165","loc":[-85.622141,41.952144]},"n3166":{"id":"n3166","loc":[-85.621977,41.952146]},"n3167":{"id":"n3167","loc":[-85.621978,41.952211]},"n3168":{"id":"n3168","loc":[-85.62191,41.952212]},"n3169":{"id":"n3169","loc":[-85.633628,41.935437]},"n317":{"id":"n317","loc":[-85.634743,41.943167]},"n3170":{"id":"n3170","loc":[-85.632849,41.935518]},"n3171":{"id":"n3171","loc":[-85.632376,41.93574]},"n3172":{"id":"n3172","loc":[-85.631517,41.935897]},"n3173":{"id":"n3173","loc":[-85.630433,41.936124]},"n3174":{"id":"n3174","loc":[-85.630207,41.936427]},"n3175":{"id":"n3175","loc":[-85.630346,41.936795]},"n3176":{"id":"n3176","loc":[-85.62996,41.936974]},"n3177":{"id":"n3177","loc":[-85.629916,41.937488]},"n3178":{"id":"n3178","loc":[-85.629946,41.937802]},"n3179":{"id":"n3179","loc":[-85.629977,41.937905]},"n318":{"id":"n318","loc":[-85.634401,41.94328]},"n3180":{"id":"n3180","loc":[-85.63016,41.937909]},"n3181":{"id":"n3181","loc":[-85.630804,41.937791]},"n3182":{"id":"n3182","loc":[-85.631688,41.937808]},"n3183":{"id":"n3183","loc":[-85.631685,41.938008]},"n3184":{"id":"n3184","loc":[-85.631845,41.938116]},"n3185":{"id":"n3185","loc":[-85.63207,41.938181]},"n3186":{"id":"n3186","loc":[-85.632143,41.938371]},"n3187":{"id":"n3187","loc":[-85.632056,41.938435]},"n3188":{"id":"n3188","loc":[-85.631787,41.938457]},"n3189":{"id":"n3189","loc":[-85.631657,41.938728]},"n319":{"id":"n319","loc":[-85.634345,41.943299]},"n3190":{"id":"n3190","loc":[-85.631595,41.93775]},"n3191":{"id":"n3191","loc":[-85.630264,41.937839]},"n3192":{"id":"n3192","loc":[-85.628591,41.948536]},"n3193":{"id":"n3193","loc":[-85.63205,41.951181]},"n3194":{"id":"n3194","loc":[-85.632034,41.949909]},"n3195":{"id":"n3195","loc":[-85.630841,41.951191]},"n3196":{"id":"n3196","loc":[-85.632083,41.9537]},"n3197":{"id":"n3197","loc":[-85.630929,41.959037]},"n3198":{"id":"n3198","loc":[-85.632151,41.959028]},"n3199":{"id":"n3199","loc":[-85.630911,41.957428]},"n32":{"id":"n32","loc":[-85.638273,41.944246]},"n320":{"id":"n320","loc":[-85.634287,41.943326]},"n3200":{"id":"n3200","loc":[-85.63213,41.957427]},"n3201":{"id":"n3201","loc":[-85.632072,41.952447]},"n3202":{"id":"n3202","loc":[-85.632095,41.954677]},"n3203":{"id":"n3203","loc":[-85.632111,41.955911]},"n3204":{"id":"n3204","loc":[-85.630855,41.952457]},"n3205":{"id":"n3205","loc":[-85.630869,41.953709]},"n3206":{"id":"n3206","loc":[-85.63088,41.954682]},"n3207":{"id":"n3207","loc":[-85.630894,41.955913]},"n3208":{"id":"n3208","loc":[-85.633214,41.948619]},"n3209":{"id":"n3209","loc":[-85.633253,41.951171]},"n321":{"id":"n321","loc":[-85.634233,41.943354]},"n3210":{"id":"n3210","loc":[-85.633234,41.949901]},"n3211":{"id":"n3211","loc":[-85.633922,41.948616]},"n3212":{"id":"n3212","loc":[-85.625188,41.947832]},"n3213":{"id":"n3213","loc":[-85.625208,41.947775]},"n3214":{"id":"n3214","loc":[-85.625229,41.94776]},"n3215":{"id":"n3215","loc":[-85.625201,41.947749]},"n3216":{"id":"n3216","loc":[-85.625168,41.947707]},"n3217":{"id":"n3217","loc":[-85.625171,41.947609]},"n3218":{"id":"n3218","loc":[-85.625213,41.947564]},"n3219":{"id":"n3219","loc":[-85.62529,41.94756]},"n322":{"id":"n322","loc":[-85.634099,41.943429]},"n3220":{"id":"n3220","loc":[-85.625303,41.947533]},"n3221":{"id":"n3221","loc":[-85.625344,41.947482]},"n3222":{"id":"n3222","loc":[-85.625442,41.947468]},"n3223":{"id":"n3223","loc":[-85.62565,41.947494]},"n3224":{"id":"n3224","loc":[-85.625726,41.947613]},"n3225":{"id":"n3225","loc":[-85.625703,41.947728]},"n3226":{"id":"n3226","loc":[-85.625534,41.94781]},"n3227":{"id":"n3227","loc":[-85.625391,41.947822]},"n3228":{"id":"n3228","loc":[-85.625304,41.947859]},"n3229":{"id":"n3229","loc":[-85.625203,41.947885]},"n323":{"id":"n323","loc":[-85.633958,41.943507],"tags":{"highway":"crossing"}},"n3230":{"id":"n3230","loc":[-85.624691,41.948659]},"n3231":{"id":"n3231","loc":[-85.624328,41.948661]},"n3232":{"id":"n3232","loc":[-85.624331,41.949046]},"n3233":{"id":"n3233","loc":[-85.624694,41.949045]},"n3234":{"id":"n3234","loc":[-85.623623,41.949606]},"n3235":{"id":"n3235","loc":[-85.623623,41.9497]},"n3236":{"id":"n3236","loc":[-85.623357,41.9497]},"n3237":{"id":"n3237","loc":[-85.623357,41.949614]},"n3238":{"id":"n3238","loc":[-85.623974,41.949429]},"n3239":{"id":"n3239","loc":[-85.623974,41.949605]},"n324":{"id":"n324","loc":[-85.633698,41.943651],"tags":{"railway":"crossing"}},"n3240":{"id":"n3240","loc":[-85.624501,41.951226]},"n3241":{"id":"n3241","loc":[-85.624501,41.951123]},"n3242":{"id":"n3242","loc":[-85.624319,41.951123]},"n3243":{"id":"n3243","loc":[-85.624319,41.951226]},"n3244":{"id":"n3244","loc":[-85.624121,41.950866]},"n3245":{"id":"n3245","loc":[-85.624115,41.950525]},"n3246":{"id":"n3246","loc":[-85.624315,41.950523]},"n3247":{"id":"n3247","loc":[-85.62432,41.950865]},"n3248":{"id":"n3248","loc":[-85.624393,41.950867]},"n3249":{"id":"n3249","loc":[-85.62439,41.950596]},"n325":{"id":"n325","loc":[-85.633508,41.943757]},"n3250":{"id":"n3250","loc":[-85.624673,41.950594]},"n3251":{"id":"n3251","loc":[-85.624675,41.95082]},"n3252":{"id":"n3252","loc":[-85.62451,41.950821]},"n3253":{"id":"n3253","loc":[-85.62451,41.950866]},"n3254":{"id":"n3254","loc":[-85.624101,41.949346]},"n3255":{"id":"n3255","loc":[-85.624244,41.949346]},"n3256":{"id":"n3256","loc":[-85.624244,41.949368]},"n3257":{"id":"n3257","loc":[-85.62434,41.949368]},"n3258":{"id":"n3258","loc":[-85.624342,41.949351]},"n3259":{"id":"n3259","loc":[-85.624725,41.949348]},"n326":{"id":"n326","loc":[-85.634839,41.942974]},"n3260":{"id":"n3260","loc":[-85.624755,41.950495]},"n3261":{"id":"n3261","loc":[-85.624121,41.950502]},"n3262":{"id":"n3262","loc":[-85.625453,41.950163]},"n3263":{"id":"n3263","loc":[-85.625454,41.949976]},"n3264":{"id":"n3264","loc":[-85.625549,41.949977]},"n3265":{"id":"n3265","loc":[-85.62555,41.949833]},"n3266":{"id":"n3266","loc":[-85.625577,41.949833]},"n3267":{"id":"n3267","loc":[-85.625578,41.949656]},"n3268":{"id":"n3268","loc":[-85.625195,41.949655]},"n3269":{"id":"n3269","loc":[-85.625192,41.950162]},"n327":{"id":"n327","loc":[-85.634657,41.943028]},"n3270":{"id":"n3270","loc":[-85.622992,41.949614]},"n3271":{"id":"n3271","loc":[-85.622991,41.949431]},"n3272":{"id":"n3272","loc":[-85.620103,41.951]},"n3273":{"id":"n3273","loc":[-85.605644,41.947468]},"n3274":{"id":"n3274","loc":[-85.617421,41.947457]},"n3275":{"id":"n3275","loc":[-85.620078,41.947444]},"n3276":{"id":"n3276","loc":[-85.620087,41.94924]},"n3277":{"id":"n3277","loc":[-85.62156,41.948333]},"n3278":{"id":"n3278","loc":[-85.620106,41.950132]},"n3279":{"id":"n3279","loc":[-85.637412,41.951136]},"n328":{"id":"n328","loc":[-85.634222,41.943152]},"n3280":{"id":"n3280","loc":[-85.635429,41.948608]},"n3281":{"id":"n3281","loc":[-85.635047,41.947788]},"n3282":{"id":"n3282","loc":[-85.635048,41.947796]},"n3283":{"id":"n3283","loc":[-85.635002,41.947797]},"n3284":{"id":"n3284","loc":[-85.635002,41.947788]},"n3285":{"id":"n3285","loc":[-85.634914,41.94779]},"n3286":{"id":"n3286","loc":[-85.634913,41.947753]},"n3287":{"id":"n3287","loc":[-85.63494,41.947753]},"n3288":{"id":"n3288","loc":[-85.634938,41.947708]},"n3289":{"id":"n3289","loc":[-85.635124,41.947705]},"n329":{"id":"n329","loc":[-85.634099,41.943202]},"n3290":{"id":"n3290","loc":[-85.635126,41.947787]},"n3291":{"id":"n3291","loc":[-85.634972,41.947599]},"n3292":{"id":"n3292","loc":[-85.634921,41.9476]},"n3293":{"id":"n3293","loc":[-85.63485,41.947546]},"n3294":{"id":"n3294","loc":[-85.63485,41.947508]},"n3295":{"id":"n3295","loc":[-85.634924,41.947457]},"n3296":{"id":"n3296","loc":[-85.634967,41.947456]},"n3297":{"id":"n3297","loc":[-85.635041,41.947512]},"n3298":{"id":"n3298","loc":[-85.635041,41.947542]},"n3299":{"id":"n3299","loc":[-85.634244,41.947839]},"n33":{"id":"n33","loc":[-85.638257,41.944188]},"n330":{"id":"n330","loc":[-85.634093,41.943138]},"n3300":{"id":"n3300","loc":[-85.634243,41.947793]},"n3301":{"id":"n3301","loc":[-85.634244,41.947686]},"n3302":{"id":"n3302","loc":[-85.634243,41.947657]},"n3303":{"id":"n3303","loc":[-85.634462,41.947653]},"n3304":{"id":"n3304","loc":[-85.634468,41.947835]},"n3305":{"id":"n3305","loc":[-85.634416,41.948006]},"n3306":{"id":"n3306","loc":[-85.634415,41.947898]},"n3307":{"id":"n3307","loc":[-85.634275,41.947899]},"n3308":{"id":"n3308","loc":[-85.634275,41.947927]},"n3309":{"id":"n3309","loc":[-85.63425,41.947927]},"n331":{"id":"n331","loc":[-85.633938,41.943291]},"n3310":{"id":"n3310","loc":[-85.63425,41.947976]},"n3311":{"id":"n3311","loc":[-85.634274,41.947976]},"n3312":{"id":"n3312","loc":[-85.634275,41.948007]},"n3313":{"id":"n3313","loc":[-85.634342,41.947635]},"n3314":{"id":"n3314","loc":[-85.634339,41.947497]},"n3315":{"id":"n3315","loc":[-85.634313,41.94748]},"n3316":{"id":"n3316","loc":[-85.634287,41.947474]},"n3317":{"id":"n3317","loc":[-85.63498,41.94815]},"n3318":{"id":"n3318","loc":[-85.634891,41.94815]},"n3319":{"id":"n3319","loc":[-85.634892,41.948169]},"n332":{"id":"n332","loc":[-85.633535,41.943511],"tags":{"railway":"crossing"}},"n3320":{"id":"n3320","loc":[-85.634852,41.948169]},"n3321":{"id":"n3321","loc":[-85.634853,41.948268]},"n3322":{"id":"n3322","loc":[-85.634832,41.948268]},"n3323":{"id":"n3323","loc":[-85.634832,41.948296]},"n3324":{"id":"n3324","loc":[-85.634965,41.948295]},"n3325":{"id":"n3325","loc":[-85.634966,41.948321]},"n3326":{"id":"n3326","loc":[-85.634999,41.948321]},"n3327":{"id":"n3327","loc":[-85.634999,41.948295]},"n3328":{"id":"n3328","loc":[-85.635175,41.948293]},"n3329":{"id":"n3329","loc":[-85.635175,41.948262]},"n333":{"id":"n333","loc":[-85.63339,41.943596]},"n3330":{"id":"n3330","loc":[-85.635159,41.948262]},"n3331":{"id":"n3331","loc":[-85.635158,41.948152]},"n3332":{"id":"n3332","loc":[-85.635067,41.948152]},"n3333":{"id":"n3333","loc":[-85.635065,41.947966]},"n3334":{"id":"n3334","loc":[-85.634979,41.947966]},"n3335":{"id":"n3335","loc":[-85.634307,41.948326]},"n3336":{"id":"n3336","loc":[-85.634305,41.948298]},"n3337":{"id":"n3337","loc":[-85.634331,41.948055]},"n3338":{"id":"n3338","loc":[-85.634331,41.948046]},"n3339":{"id":"n3339","loc":[-85.634435,41.948047]},"n334":{"id":"n334","loc":[-85.632842,41.943895]},"n3340":{"id":"n3340","loc":[-85.634434,41.948375]},"n3341":{"id":"n3341","loc":[-85.634463,41.948373]},"n3342":{"id":"n3342","loc":[-85.634464,41.948456]},"n3343":{"id":"n3343","loc":[-85.63443,41.948457]},"n3344":{"id":"n3344","loc":[-85.634432,41.948505]},"n3345":{"id":"n3345","loc":[-85.637386,41.94906]},"n3346":{"id":"n3346","loc":[-85.637113,41.9486]},"n3347":{"id":"n3347","loc":[-85.635448,41.949424]},"n335":{"id":"n335","loc":[-85.633856,41.943315]},"n3352":{"id":"n3352","loc":[-85.635457,41.949787]},"n3353":{"id":"n3353","loc":[-85.635459,41.949886]},"n336":{"id":"n336","loc":[-85.633697,41.943405]},"n337":{"id":"n337","loc":[-85.63347,41.943181]},"n3372":{"id":"n3372","loc":[-85.634423,41.950964]},"n3373":{"id":"n3373","loc":[-85.634424,41.95074]},"n3374":{"id":"n3374","loc":[-85.634394,41.950284]},"n3375":{"id":"n3375","loc":[-85.634398,41.950626]},"n3376":{"id":"n3376","loc":[-85.63452,41.951063]},"n3377":{"id":"n3377","loc":[-85.634511,41.949977]},"n3378":{"id":"n3378","loc":[-85.637409,41.949873]},"n3379":{"id":"n3379","loc":[-85.634824,41.94996]},"n338":{"id":"n338","loc":[-85.633597,41.943109]},"n3380":{"id":"n3380","loc":[-85.635437,41.949954]},"n3381":{"id":"n3381","loc":[-85.634844,41.951064]},"n3382":{"id":"n3382","loc":[-85.635458,41.951058]},"n3383":{"id":"n3383","loc":[-85.633921,41.947333]},"n3384":{"id":"n3384","loc":[-85.634208,41.947793]},"n3385":{"id":"n3385","loc":[-85.634204,41.947687]},"n3386":{"id":"n3386","loc":[-85.63424,41.947475]},"n3387":{"id":"n3387","loc":[-85.63424,41.947635]},"n3388":{"id":"n3388","loc":[-85.634089,41.948328]},"n3389":{"id":"n3389","loc":[-85.63424,41.948299]},"n339":{"id":"n339","loc":[-85.633673,41.943184]},"n3390":{"id":"n3390","loc":[-85.634239,41.948212]},"n3391":{"id":"n3391","loc":[-85.634086,41.948214]},"n3392":{"id":"n3392","loc":[-85.63408,41.948056]},"n3393":{"id":"n3393","loc":[-85.634093,41.948506]},"n3394":{"id":"n3394","loc":[-85.64344,41.941866]},"n3395":{"id":"n3395","loc":[-85.63378,41.95099]},"n3396":{"id":"n3396","loc":[-85.633779,41.950967]},"n3397":{"id":"n3397","loc":[-85.63375,41.950746]},"n3398":{"id":"n3398","loc":[-85.63375,41.950697]},"n3399":{"id":"n3399","loc":[-85.633903,41.950696]},"n34":{"id":"n34","loc":[-85.638176,41.944312]},"n340":{"id":"n340","loc":[-85.633714,41.94316]},"n3400":{"id":"n3400","loc":[-85.633901,41.950436]},"n3401":{"id":"n3401","loc":[-85.633492,41.950438]},"n3402":{"id":"n3402","loc":[-85.633494,41.950756]},"n3403":{"id":"n3403","loc":[-85.633454,41.950756]},"n3404":{"id":"n3404","loc":[-85.633456,41.950992]},"n3405":{"id":"n3405","loc":[-85.633994,41.950284]},"n3406":{"id":"n3406","loc":[-85.633998,41.950628]},"n3407":{"id":"n3407","loc":[-85.633364,41.951068]},"n3408":{"id":"n3408","loc":[-85.633356,41.949982]},"n3409":{"id":"n3409","loc":[-85.643327,41.941903]},"n341":{"id":"n341","loc":[-85.633811,41.943256]},"n3410":{"id":"n3410","loc":[-85.633292,41.953691]},"n3411":{"id":"n3411","loc":[-85.637432,41.952399]},"n3412":{"id":"n3412","loc":[-85.633349,41.957422]},"n3413":{"id":"n3413","loc":[-85.633326,41.955909]},"n3414":{"id":"n3414","loc":[-85.633307,41.954673]},"n3415":{"id":"n3415","loc":[-85.633273,41.952436]},"n3416":{"id":"n3416","loc":[-85.633361,41.95823],"tags":{"highway":"turning_circle"}},"n3417":{"id":"n3417","loc":[-85.619899,41.945527]},"n3418":{"id":"n3418","loc":[-85.643422,41.941946]},"n3419":{"id":"n3419","loc":[-85.643505,41.942033]},"n342":{"id":"n342","loc":[-85.633801,41.943261]},"n3420":{"id":"n3420","loc":[-85.620088,41.945571]},"n3421":{"id":"n3421","loc":[-85.620051,41.945505]},"n3422":{"id":"n3422","loc":[-85.62001,41.94541]},"n3423":{"id":"n3423","loc":[-85.620982,41.944742]},"n3424":{"id":"n3424","loc":[-85.621305,41.944782]},"n3425":{"id":"n3425","loc":[-85.621174,41.944819]},"n3426":{"id":"n3426","loc":[-85.621029,41.944871]},"n3427":{"id":"n3427","loc":[-85.620741,41.945011]},"n3428":{"id":"n3428","loc":[-85.620616,41.945085]},"n3429":{"id":"n3429","loc":[-85.620506,41.945172]},"n343":{"id":"n343","loc":[-85.63374,41.943514]},"n3430":{"id":"n3430","loc":[-85.620394,41.945273]},"n3431":{"id":"n3431","loc":[-85.620316,41.94536]},"n3432":{"id":"n3432","loc":[-85.620257,41.945452]},"n3433":{"id":"n3433","loc":[-85.620212,41.945535]},"n3434":{"id":"n3434","loc":[-85.620101,41.945811]},"n3435":{"id":"n3435","loc":[-85.620081,41.945937]},"n3436":{"id":"n3436","loc":[-85.619899,41.943718]},"n3437":{"id":"n3437","loc":[-85.619969,41.943211]},"n3438":{"id":"n3438","loc":[-85.619894,41.943292]},"n3439":{"id":"n3439","loc":[-85.620047,41.944738]},"n344":{"id":"n344","loc":[-85.633665,41.943441]},"n3440":{"id":"n3440","loc":[-85.620226,41.946088]},"n3441":{"id":"n3441","loc":[-85.620225,41.945864]},"n3442":{"id":"n3442","loc":[-85.620518,41.945863]},"n3443":{"id":"n3443","loc":[-85.620519,41.945944]},"n3444":{"id":"n3444","loc":[-85.620388,41.945944]},"n3445":{"id":"n3445","loc":[-85.620389,41.946088]},"n3446":{"id":"n3446","loc":[-85.618405,41.946566]},"n3447":{"id":"n3447","loc":[-85.619156,41.946562]},"n3448":{"id":"n3448","loc":[-85.619154,41.946319]},"n3449":{"id":"n3449","loc":[-85.618736,41.946322]},"n345":{"id":"n345","loc":[-85.633162,41.942947]},"n3450":{"id":"n3450","loc":[-85.618733,41.94612]},"n3451":{"id":"n3451","loc":[-85.619317,41.946116]},"n3452":{"id":"n3452","loc":[-85.619316,41.946023]},"n3453":{"id":"n3453","loc":[-85.619622,41.946021]},"n3454":{"id":"n3454","loc":[-85.619624,41.946171]},"n3455":{"id":"n3455","loc":[-85.61977,41.94617]},"n3456":{"id":"n3456","loc":[-85.619769,41.94602]},"n3457":{"id":"n3457","loc":[-85.619732,41.94602]},"n3458":{"id":"n3458","loc":[-85.619731,41.945856]},"n3459":{"id":"n3459","loc":[-85.619617,41.945857]},"n346":{"id":"n346","loc":[-85.633598,41.943083]},"n3460":{"id":"n3460","loc":[-85.619616,41.945776]},"n3461":{"id":"n3461","loc":[-85.619447,41.945777]},"n3462":{"id":"n3462","loc":[-85.619415,41.945778]},"n3463":{"id":"n3463","loc":[-85.618378,41.945788]},"n3464":{"id":"n3464","loc":[-85.618384,41.946132]},"n3465":{"id":"n3465","loc":[-85.618503,41.94613]},"n3466":{"id":"n3466","loc":[-85.618506,41.946319]},"n3467":{"id":"n3467","loc":[-85.6184,41.94632]},"n3468":{"id":"n3468","loc":[-85.618248,41.946416]},"n3469":{"id":"n3469","loc":[-85.618247,41.946319]},"n347":{"id":"n347","loc":[-85.63343,41.943179]},"n3470":{"id":"n3470","loc":[-85.618039,41.946321]},"n3471":{"id":"n3471","loc":[-85.61804,41.946418]},"n3472":{"id":"n3472","loc":[-85.620118,41.951895]},"n3473":{"id":"n3473","loc":[-85.617075,41.95469]},"n3474":{"id":"n3474","loc":[-85.620107,41.952113]},"n3475":{"id":"n3475","loc":[-85.620091,41.95232]},"n3476":{"id":"n3476","loc":[-85.620047,41.952505]},"n3477":{"id":"n3477","loc":[-85.61998,41.952715]},"n3478":{"id":"n3478","loc":[-85.619861,41.952986]},"n3479":{"id":"n3479","loc":[-85.619622,41.953365]},"n348":{"id":"n348","loc":[-85.633669,41.94341]},"n3480":{"id":"n3480","loc":[-85.619441,41.953567]},"n3481":{"id":"n3481","loc":[-85.619259,41.953741]},"n3482":{"id":"n3482","loc":[-85.618835,41.954056]},"n3483":{"id":"n3483","loc":[-85.618602,41.954194]},"n3484":{"id":"n3484","loc":[-85.618305,41.954347]},"n3485":{"id":"n3485","loc":[-85.618006,41.954466]},"n3486":{"id":"n3486","loc":[-85.617611,41.954587]},"n3487":{"id":"n3487","loc":[-85.615094,41.943412]},"n3488":{"id":"n3488","loc":[-85.619337,41.943025]},"n3489":{"id":"n3489","loc":[-85.610477,41.945527]},"n349":{"id":"n349","loc":[-85.633566,41.943466]},"n3490":{"id":"n3490","loc":[-85.610477,41.943718]},"n3491":{"id":"n3491","loc":[-85.619804,41.942976]},"n3492":{"id":"n3492","loc":[-85.61921,41.942672]},"n3493":{"id":"n3493","loc":[-85.619862,41.942836]},"n3494":{"id":"n3494","loc":[-85.616326,41.942769]},"n3495":{"id":"n3495","loc":[-85.617953,41.942917]},"n3496":{"id":"n3496","loc":[-85.61972,41.942728]},"n3497":{"id":"n3497","loc":[-85.61944,41.942784]},"n3498":{"id":"n3498","loc":[-85.615323,41.942841]},"n3499":{"id":"n3499","loc":[-85.612923,41.943718]},"n35":{"id":"n35","loc":[-85.637928,41.944249]},"n350":{"id":"n350","loc":[-85.633031,41.942986]},"n3500":{"id":"n3500","loc":[-85.61958,41.942756]},"n3501":{"id":"n3501","loc":[-85.619643,41.942647],"tags":{"leisure":"fishing"}},"n3502":{"id":"n3502","loc":[-85.619935,41.942962]},"n3503":{"id":"n3503","loc":[-85.629677,41.954687]},"n3504":{"id":"n3504","loc":[-85.629083,41.953722]},"n3505":{"id":"n3505","loc":[-85.621907,41.952067]},"n3506":{"id":"n3506","loc":[-85.621788,41.952058]},"n3507":{"id":"n3507","loc":[-85.629665,41.953718]},"n3508":{"id":"n3508","loc":[-85.624454,41.954707]},"n3509":{"id":"n3509","loc":[-85.634609,41.954585]},"n351":{"id":"n351","loc":[-85.633238,41.94283]},"n3510":{"id":"n3510","loc":[-85.634595,41.953772]},"n3511":{"id":"n3511","loc":[-85.633425,41.953783]},"n3512":{"id":"n3512","loc":[-85.633439,41.954596]},"n3517":{"id":"n3517","loc":[-85.621789,41.952179]},"n3518":{"id":"n3518","loc":[-85.624105,41.954704]},"n3519":{"id":"n3519","loc":[-85.623306,41.954542]},"n352":{"id":"n352","loc":[-85.633173,41.943556]},"n3520":{"id":"n3520","loc":[-85.623123,41.954502]},"n3521":{"id":"n3521","loc":[-85.622965,41.954473]},"n3522":{"id":"n3522","loc":[-85.622822,41.954455]},"n3523":{"id":"n3523","loc":[-85.62269,41.954448]},"n3524":{"id":"n3524","loc":[-85.622388,41.954467]},"n3525":{"id":"n3525","loc":[-85.62403,41.954895]},"n3526":{"id":"n3526","loc":[-85.623579,41.954855]},"n3527":{"id":"n3527","loc":[-85.623836,41.954951]},"n3528":{"id":"n3528","loc":[-85.622473,41.954592]},"n3529":{"id":"n3529","loc":[-85.622753,41.95458]},"n353":{"id":"n353","loc":[-85.633127,41.943552]},"n3530":{"id":"n3530","loc":[-85.62404,41.955078]},"n3531":{"id":"n3531","loc":[-85.624126,41.954999]},"n3532":{"id":"n3532","loc":[-85.623171,41.954687]},"n3533":{"id":"n3533","loc":[-85.624276,41.955206]},"n3534":{"id":"n3534","loc":[-85.62491,41.952801]},"n3535":{"id":"n3535","loc":[-85.625186,41.952756]},"n3536":{"id":"n3536","loc":[-85.625552,41.952792]},"n3537":{"id":"n3537","loc":[-85.626001,41.952948]},"n3538":{"id":"n3538","loc":[-85.626528,41.952984]},"n3539":{"id":"n3539","loc":[-85.626942,41.952886]},"n354":{"id":"n354","loc":[-85.632745,41.943222]},"n3540":{"id":"n3540","loc":[-85.627092,41.952685]},"n3541":{"id":"n3541","loc":[-85.627212,41.95244]},"n3542":{"id":"n3542","loc":[-85.627158,41.952226]},"n3543":{"id":"n3543","loc":[-85.627002,41.951972]},"n3544":{"id":"n3544","loc":[-85.626822,41.951838]},"n3545":{"id":"n3545","loc":[-85.626528,41.951807]},"n3546":{"id":"n3546","loc":[-85.625653,41.951852]},"n3547":{"id":"n3547","loc":[-85.625348,41.951834]},"n3548":{"id":"n3548","loc":[-85.625114,41.951767]},"n3549":{"id":"n3549","loc":[-85.620627,41.954682]},"n355":{"id":"n355","loc":[-85.632756,41.943199]},"n3550":{"id":"n3550","loc":[-85.622758,41.951884]},"n3551":{"id":"n3551","loc":[-85.618135,41.954734]},"n3552":{"id":"n3552","loc":[-85.620229,41.95472]},"n3553":{"id":"n3553","loc":[-85.624491,41.955573]},"n3554":{"id":"n3554","loc":[-85.621792,41.958314]},"n3555":{"id":"n3555","loc":[-85.623395,41.960001]},"n3556":{"id":"n3556","loc":[-85.620461,41.956212]},"n3557":{"id":"n3557","loc":[-85.62109,41.956766]},"n3558":{"id":"n3558","loc":[-85.620246,41.956224]},"n3559":{"id":"n3559","loc":[-85.625017,41.956068]},"n356":{"id":"n356","loc":[-85.632855,41.943147]},"n3560":{"id":"n3560","loc":[-85.622795,41.959702]},"n3561":{"id":"n3561","loc":[-85.621573,41.958457]},"n3562":{"id":"n3562","loc":[-85.619631,41.9573]},"n3563":{"id":"n3563","loc":[-85.62095,41.956311]},"n3564":{"id":"n3564","loc":[-85.619694,41.957408]},"n3565":{"id":"n3565","loc":[-85.621079,41.957751]},"n3566":{"id":"n3566","loc":[-85.622426,41.961142]},"n3567":{"id":"n3567","loc":[-85.623251,41.960484]},"n3568":{"id":"n3568","loc":[-85.619084,41.956291]},"n3569":{"id":"n3569","loc":[-85.622227,41.959303]},"n357":{"id":"n357","loc":[-85.632888,41.94315]},"n3570":{"id":"n3570","loc":[-85.620976,41.959104]},"n3571":{"id":"n3571","loc":[-85.621208,41.95653]},"n3572":{"id":"n3572","loc":[-85.623531,41.95951]},"n3573":{"id":"n3573","loc":[-85.623556,41.957935]},"n3574":{"id":"n3574","loc":[-85.623037,41.95746]},"n3575":{"id":"n3575","loc":[-85.621175,41.956427]},"n3576":{"id":"n3576","loc":[-85.622651,41.960109]},"n3577":{"id":"n3577","loc":[-85.621803,41.960747]},"n3578":{"id":"n3578","loc":[-85.620791,41.961874]},"n3579":{"id":"n3579","loc":[-85.625295,41.956786]},"n358":{"id":"n358","loc":[-85.633232,41.943547]},"n3580":{"id":"n3580","loc":[-85.619662,41.956894]},"n3581":{"id":"n3581","loc":[-85.622442,41.958708]},"n3582":{"id":"n3582","loc":[-85.621744,41.955864]},"n3583":{"id":"n3583","loc":[-85.621336,41.959212]},"n3584":{"id":"n3584","loc":[-85.622801,41.957304]},"n3585":{"id":"n3585","loc":[-85.619973,41.957433]},"n3586":{"id":"n3586","loc":[-85.619556,41.955717]},"n3587":{"id":"n3587","loc":[-85.622978,41.958601]},"n3588":{"id":"n3588","loc":[-85.625396,41.956264]},"n3589":{"id":"n3589","loc":[-85.623525,41.958034]},"n359":{"id":"n359","loc":[-85.633302,41.94351]},"n3590":{"id":"n3590","loc":[-85.623299,41.959631]},"n3591":{"id":"n3591","loc":[-85.622678,41.959873]},"n3592":{"id":"n3592","loc":[-85.625553,41.956179]},"n3593":{"id":"n3593","loc":[-85.623557,41.959231]},"n3594":{"id":"n3594","loc":[-85.622843,41.957373]},"n3595":{"id":"n3595","loc":[-85.619378,41.955677]},"n3596":{"id":"n3596","loc":[-85.620092,41.955425]},"n3597":{"id":"n3597","loc":[-85.622666,41.96044]},"n3598":{"id":"n3598","loc":[-85.621996,41.960256]},"n3599":{"id":"n3599","loc":[-85.623273,41.959997]},"n36":{"id":"n36","loc":[-85.637894,41.945551]},"n360":{"id":"n360","loc":[-85.633442,41.943794],"tags":{"highway":"crossing"}},"n3600":{"id":"n3600","loc":[-85.62477,41.95689]},"n3601":{"id":"n3601","loc":[-85.621641,41.955015]},"n3602":{"id":"n3602","loc":[-85.622495,41.960392]},"n3603":{"id":"n3603","loc":[-85.61918,41.955565]},"n3604":{"id":"n3604","loc":[-85.620017,41.955505]},"n3605":{"id":"n3605","loc":[-85.621739,41.956315]},"n3606":{"id":"n3606","loc":[-85.622957,41.959837]},"n3607":{"id":"n3607","loc":[-85.620912,41.960919]},"n3608":{"id":"n3608","loc":[-85.625231,41.956235]},"n3609":{"id":"n3609","loc":[-85.620976,41.961868]},"n361":{"id":"n361","loc":[-85.633381,41.94383]},"n3610":{"id":"n3610","loc":[-85.620956,41.958908]},"n3611":{"id":"n3611","loc":[-85.619035,41.956139]},"n3612":{"id":"n3612","loc":[-85.623643,41.958669]},"n3613":{"id":"n3613","loc":[-85.61949,41.956539]},"n3614":{"id":"n3614","loc":[-85.621927,41.958242]},"n3615":{"id":"n3615","loc":[-85.620826,41.955721]},"n3616":{"id":"n3616","loc":[-85.621202,41.961321]},"n3617":{"id":"n3617","loc":[-85.624877,41.95594]},"n3618":{"id":"n3618","loc":[-85.62065,41.958369]},"n3619":{"id":"n3619","loc":[-85.621524,41.956279]},"n362":{"id":"n362","loc":[-85.632977,41.944053]},"n3620":{"id":"n3620","loc":[-85.624662,41.955932]},"n3621":{"id":"n3621","loc":[-85.623048,41.958509]},"n3622":{"id":"n3622","loc":[-85.62111,41.95754]},"n3623":{"id":"n3623","loc":[-85.621508,41.954847]},"n3624":{"id":"n3624","loc":[-85.620655,41.958601]},"n3625":{"id":"n3625","loc":[-85.62154,41.954971]},"n3626":{"id":"n3626","loc":[-85.621691,41.955521]},"n3627":{"id":"n3627","loc":[-85.62154,41.954739]},"n3628":{"id":"n3628","loc":[-85.621996,41.959913]},"n3629":{"id":"n3629","loc":[-85.622286,41.960699]},"n363":{"id":"n363","loc":[-85.632915,41.943981],"tags":{"crossing":"zebra","highway":"crossing"}},"n3630":{"id":"n3630","loc":[-85.622844,41.9572]},"n3631":{"id":"n3631","loc":[-85.620252,41.955446]},"n3632":{"id":"n3632","loc":[-85.623434,41.957528]},"n3633":{"id":"n3633","loc":[-85.623429,41.956858]},"n3634":{"id":"n3634","loc":[-85.622957,41.957137]},"n3635":{"id":"n3635","loc":[-85.622554,41.959027]},"n3636":{"id":"n3636","loc":[-85.623289,41.958314]},"n3637":{"id":"n3637","loc":[-85.622977,41.960855]},"n3638":{"id":"n3638","loc":[-85.624008,41.956953]},"n3639":{"id":"n3639","loc":[-85.621278,41.960855]},"n364":{"id":"n364","loc":[-85.632724,41.943969],"tags":{"crossing":"zebra","highway":"crossing"}},"n3640":{"id":"n3640","loc":[-85.623128,41.956993]},"n3641":{"id":"n3641","loc":[-85.622452,41.959183]},"n3642":{"id":"n3642","loc":[-85.621095,41.961082]},"n3643":{"id":"n3643","loc":[-85.622011,41.960544]},"n3644":{"id":"n3644","loc":[-85.621637,41.955385]},"n3645":{"id":"n3645","loc":[-85.620999,41.959271]},"n3646":{"id":"n3646","loc":[-85.620044,41.956347]},"n3647":{"id":"n3647","loc":[-85.621936,41.959682]},"n3648":{"id":"n3648","loc":[-85.623761,41.95685]},"n3649":{"id":"n3649","loc":[-85.621239,41.959343]},"n365":{"id":"n365","loc":[-85.632621,41.944034]},"n3650":{"id":"n3650","loc":[-85.621073,41.956012]},"n3651":{"id":"n3651","loc":[-85.621271,41.956184]},"n3652":{"id":"n3652","loc":[-85.623444,41.95778]},"n3653":{"id":"n3653","loc":[-85.62125,41.96186]},"n3654":{"id":"n3654","loc":[-85.62169,41.961059]},"n3655":{"id":"n3655","loc":[-85.620012,41.955637]},"n3656":{"id":"n3656","loc":[-85.621058,41.9573]},"n3657":{"id":"n3657","loc":[-85.621138,41.957663]},"n3658":{"id":"n3658","loc":[-85.620773,41.957895]},"n3659":{"id":"n3659","loc":[-85.62007,41.957157]},"n366":{"id":"n366","loc":[-85.632684,41.944109],"tags":{"crossing":"zebra","highway":"crossing"}},"n3660":{"id":"n3660","loc":[-85.624534,41.955844]},"n3661":{"id":"n3661","loc":[-85.621932,41.960807]},"n3662":{"id":"n3662","loc":[-85.623358,41.958138]},"n3663":{"id":"n3663","loc":[-85.620456,41.955514]},"n3664":{"id":"n3664","loc":[-85.623504,41.957607]},"n3665":{"id":"n3665","loc":[-85.621444,41.960751]},"n3666":{"id":"n3666","loc":[-85.623492,41.960213]},"n3667":{"id":"n3667","loc":[-85.621669,41.954655]},"n3668":{"id":"n3668","loc":[-85.623106,41.958685]},"n3669":{"id":"n3669","loc":[-85.620922,41.957867]},"n367":{"id":"n367","loc":[-85.632738,41.944172]},"n3670":{"id":"n3670","loc":[-85.620092,41.957296]},"n3671":{"id":"n3671","loc":[-85.621669,41.955222]},"n3672":{"id":"n3672","loc":[-85.621614,41.960967]},"n3673":{"id":"n3673","loc":[-85.621691,41.955732]},"n3674":{"id":"n3674","loc":[-85.619207,41.956419]},"n3675":{"id":"n3675","loc":[-85.621116,41.956603]},"n3676":{"id":"n3676","loc":[-85.623311,41.956929]},"n3677":{"id":"n3677","loc":[-85.625671,41.956499]},"n3678":{"id":"n3678","loc":[-85.623525,41.956738]},"n3679":{"id":"n3679","loc":[-85.625381,41.956634]},"n368":{"id":"n368","loc":[-85.63287,41.944135],"tags":{"crossing":"zebra","highway":"crossing"}},"n3680":{"id":"n3680","loc":[-85.620096,41.95677]},"n3681":{"id":"n3681","loc":[-85.623803,41.958745]},"n3682":{"id":"n3682","loc":[-85.623498,41.958457]},"n3683":{"id":"n3683","loc":[-85.624223,41.957009]},"n3684":{"id":"n3684","loc":[-85.620026,41.956946]},"n3685":{"id":"n3685","loc":[-85.623005,41.960124]},"n3686":{"id":"n3686","loc":[-85.619073,41.955832]},"n3687":{"id":"n3687","loc":[-85.621744,41.95501]},"n3688":{"id":"n3688","loc":[-85.620804,41.958781]},"n3689":{"id":"n3689","loc":[-85.619844,41.957448]},"n369":{"id":"n369","loc":[-85.63298,41.944076]},"n3690":{"id":"n3690","loc":[-85.623713,41.958872]},"n3691":{"id":"n3691","loc":[-85.622329,41.960507]},"n3692":{"id":"n3692","loc":[-85.620804,41.956244]},"n3693":{"id":"n3693","loc":[-85.621818,41.955968]},"n3694":{"id":"n3694","loc":[-85.621405,41.958697]},"n3695":{"id":"n3695","loc":[-85.620998,41.960996]},"n3696":{"id":"n3696","loc":[-85.621621,41.960444]},"n3697":{"id":"n3697","loc":[-85.620941,41.961637]},"n3698":{"id":"n3698","loc":[-85.622195,41.958333]},"n3699":{"id":"n3699","loc":[-85.621668,41.961529]},"n37":{"id":"n37","loc":[-85.637611,41.945383]},"n370":{"id":"n370","loc":[-85.633191,41.944471]},"n3700":{"id":"n3700","loc":[-85.621015,41.957049]},"n3701":{"id":"n3701","loc":[-85.619368,41.955521]},"n3702":{"id":"n3702","loc":[-85.651578,41.942534]},"n3703":{"id":"n3703","loc":[-85.651541,41.943847]},"n3704":{"id":"n3704","loc":[-85.651365,41.944817]},"n3705":{"id":"n3705","loc":[-85.651076,41.945985]},"n3706":{"id":"n3706","loc":[-85.650626,41.947213]},"n3707":{"id":"n3707","loc":[-85.649669,41.949161]},"n3708":{"id":"n3708","loc":[-85.641802,41.961801]},"n3709":{"id":"n3709","loc":[-85.623333,41.961987]},"n371":{"id":"n371","loc":[-85.633132,41.94372]},"n3710":{"id":"n3710","loc":[-85.620621,41.965658]},"n3711":{"id":"n3711","loc":[-85.605673,41.965764]},"n3712":{"id":"n3712","loc":[-85.605664,41.962094]},"n3713":{"id":"n3713","loc":[-85.583774,41.962178]},"n3714":{"id":"n3714","loc":[-85.583774,41.961789]},"n3715":{"id":"n3715","loc":[-85.581303,41.961783]},"n3716":{"id":"n3716","loc":[-85.581245,41.958394]},"n3717":{"id":"n3717","loc":[-85.585299,41.955483]},"n3718":{"id":"n3718","loc":[-85.585588,41.955331]},"n3719":{"id":"n3719","loc":[-85.586053,41.955163]},"n372":{"id":"n372","loc":[-85.633011,41.943788]},"n3720":{"id":"n3720","loc":[-85.58632,41.955076]},"n3721":{"id":"n3721","loc":[-85.586478,41.955025]},"n3722":{"id":"n3722","loc":[-85.58692,41.954947]},"n3723":{"id":"n3723","loc":[-85.587345,41.954913]},"n3724":{"id":"n3724","loc":[-85.605592,41.954766]},"n3725":{"id":"n3725","loc":[-85.605303,41.936236]},"n3726":{"id":"n3726","loc":[-85.606941,41.936117]},"n3727":{"id":"n3727","loc":[-85.60876,41.935856]},"n3728":{"id":"n3728","loc":[-85.610092,41.935451]},"n3729":{"id":"n3729","loc":[-85.610681,41.935247]},"n373":{"id":"n373","loc":[-85.632854,41.943632]},"n3730":{"id":"n3730","loc":[-85.611446,41.934955]},"n3731":{"id":"n3731","loc":[-85.612057,41.934696]},"n3732":{"id":"n3732","loc":[-85.613256,41.934084]},"n3733":{"id":"n3733","loc":[-85.613948,41.933682]},"n3734":{"id":"n3734","loc":[-85.614638,41.933212]},"n3735":{"id":"n3735","loc":[-85.619801,41.929305]},"n3736":{"id":"n3736","loc":[-85.619768,41.925548]},"n3737":{"id":"n3737","loc":[-85.625761,41.925597]},"n3738":{"id":"n3738","loc":[-85.6263,41.927323]},"n3739":{"id":"n3739","loc":[-85.633708,41.927402]},"n374":{"id":"n374","loc":[-85.632974,41.943565]},"n3740":{"id":"n3740","loc":[-85.633927,41.929109]},"n3741":{"id":"n3741","loc":[-85.639213,41.929088]},"n3742":{"id":"n3742","loc":[-85.639204,41.925488]},"n3743":{"id":"n3743","loc":[-85.651425,41.925406]},"n3744":{"id":"n3744","loc":[-85.643386,41.941933]},"n3745":{"id":"n3745","loc":[-85.642776,41.941161]},"n3746":{"id":"n3746","loc":[-85.637277,41.948812]},"n3747":{"id":"n3747","loc":[-85.637366,41.94897]},"n3748":{"id":"n3748","loc":[-85.637329,41.94889]},"n3749":{"id":"n3749","loc":[-85.629649,41.952596]},"n375":{"id":"n375","loc":[-85.632741,41.943351]},"n3750":{"id":"n3750","loc":[-85.630291,41.954684]},"n3751":{"id":"n3751","loc":[-85.630284,41.953713]},"n3752":{"id":"n3752","loc":[-85.630269,41.952463]},"n3753":{"id":"n3753","loc":[-85.633933,41.949896]},"n3754":{"id":"n3754","loc":[-85.629339,41.941467]},"n3755":{"id":"n3755","loc":[-85.629857,41.94316]},"n3756":{"id":"n3756","loc":[-85.629987,41.944025]},"n3757":{"id":"n3757","loc":[-85.628538,41.948604]},"n3758":{"id":"n3758","loc":[-85.627415,41.957442]},"n3759":{"id":"n3759","loc":[-85.627019,41.957369]},"n376":{"id":"n376","loc":[-85.63251,41.943481]},"n3760":{"id":"n3760","loc":[-85.62167,41.952179]},"n3761":{"id":"n3761","loc":[-85.62167,41.952138]},"n3762":{"id":"n3762","loc":[-85.621562,41.952139]},"n3763":{"id":"n3763","loc":[-85.621562,41.952058]},"n3764":{"id":"n3764","loc":[-85.621476,41.952043]},"n3765":{"id":"n3765","loc":[-85.621477,41.952132]},"n3766":{"id":"n3766","loc":[-85.621386,41.952132]},"n3767":{"id":"n3767","loc":[-85.621387,41.95214]},"n3768":{"id":"n3768","loc":[-85.621262,41.95214]},"n3769":{"id":"n3769","loc":[-85.621261,41.952038]},"n377":{"id":"n377","loc":[-85.632706,41.943715]},"n3770":{"id":"n3770","loc":[-85.621389,41.952038]},"n3771":{"id":"n3771","loc":[-85.621389,41.952043]},"n3772":{"id":"n3772","loc":[-85.620898,41.952024]},"n3773":{"id":"n3773","loc":[-85.620898,41.952085]},"n3774":{"id":"n3774","loc":[-85.620774,41.952084]},"n3775":{"id":"n3775","loc":[-85.620774,41.952023]},"n3776":{"id":"n3776","loc":[-85.620749,41.952036]},"n3777":{"id":"n3777","loc":[-85.620723,41.952097]},"n3778":{"id":"n3778","loc":[-85.626158,41.958996]},"n3779":{"id":"n3779","loc":[-85.626319,41.958686]},"n378":{"id":"n378","loc":[-85.638683,41.943295]},"n3780":{"id":"n3780","loc":[-85.626119,41.958629]},"n3781":{"id":"n3781","loc":[-85.626064,41.958733]},"n3782":{"id":"n3782","loc":[-85.626155,41.958759]},"n3783":{"id":"n3783","loc":[-85.626048,41.958965]},"n3784":{"id":"n3784","loc":[-85.620648,41.952079]},"n3785":{"id":"n3785","loc":[-85.63826,41.961213]},"n3786":{"id":"n3786","loc":[-85.638003,41.961614]},"n3787":{"id":"n3787","loc":[-85.638817,41.961902]},"n3788":{"id":"n3788","loc":[-85.639073,41.961501]},"n3789":{"id":"n3789","loc":[-85.620674,41.952018]},"n379":{"id":"n379","loc":[-85.638684,41.94323]},"n3790":{"id":"n3790","loc":[-85.62082,41.952106]},"n3791":{"id":"n3791","loc":[-85.620819,41.952143]},"n3792":{"id":"n3792","loc":[-85.620778,41.952143]},"n3793":{"id":"n3793","loc":[-85.620778,41.952106]},"n3794":{"id":"n3794","loc":[-85.620563,41.952276]},"n3795":{"id":"n3795","loc":[-85.620543,41.95238]},"n3796":{"id":"n3796","loc":[-85.620422,41.952367]},"n3797":{"id":"n3797","loc":[-85.620441,41.952263]},"n3798":{"id":"n3798","loc":[-85.620561,41.952266]},"n3799":{"id":"n3799","loc":[-85.620444,41.952254]},"n38":{"id":"n38","loc":[-85.63879,41.943295]},"n380":{"id":"n380","loc":[-85.638627,41.94322]},"n3800":{"id":"n3800","loc":[-85.620773,41.955585]},"n3801":{"id":"n3801","loc":[-85.621265,41.955989]},"n3802":{"id":"n3802","loc":[-85.620692,41.954969]},"n3803":{"id":"n3803","loc":[-85.620691,41.955367]},"n3804":{"id":"n3804","loc":[-85.620458,41.952178]},"n3805":{"id":"n3805","loc":[-85.620575,41.95219]},"n3806":{"id":"n3806","loc":[-85.617609,41.952712]},"n3807":{"id":"n3807","loc":[-85.617533,41.952801],"tags":{"entrance":"yes"}},"n3808":{"id":"n3808","loc":[-85.616816,41.952911]},"n3809":{"id":"n3809","loc":[-85.616797,41.952901]},"n381":{"id":"n381","loc":[-85.638624,41.943294]},"n3810":{"id":"n3810","loc":[-85.616343,41.952694]},"n3811":{"id":"n3811","loc":[-85.616336,41.952729]},"n3812":{"id":"n3812","loc":[-85.616343,41.952772]},"n3813":{"id":"n3813","loc":[-85.628479,41.948649]},"n3814":{"id":"n3814","loc":[-85.628413,41.948679]},"n3815":{"id":"n3815","loc":[-85.628336,41.948694]},"n3816":{"id":"n3816","loc":[-85.62826,41.948694]},"n3817":{"id":"n3817","loc":[-85.628185,41.948679]},"n3818":{"id":"n3818","loc":[-85.628103,41.948649]},"n3819":{"id":"n3819","loc":[-85.627482,41.948395]},"n382":{"id":"n382","loc":[-85.638437,41.943291]},"n3820":{"id":"n3820","loc":[-85.619957,41.951168]},"n3821":{"id":"n3821","loc":[-85.619955,41.952077]},"n3822":{"id":"n3822","loc":[-85.619843,41.952666]},"n3823":{"id":"n3823","loc":[-85.619513,41.95324]},"n3824":{"id":"n3824","loc":[-85.619163,41.953668]},"n3825":{"id":"n3825","loc":[-85.618813,41.953947]},"n3826":{"id":"n3826","loc":[-85.618265,41.954252]},"n3827":{"id":"n3827","loc":[-85.617691,41.954458]},"n3828":{"id":"n3828","loc":[-85.616978,41.95459]},"n3829":{"id":"n3829","loc":[-85.615408,41.954628]},"n383":{"id":"n383","loc":[-85.63844,41.943209]},"n3830":{"id":"n3830","loc":[-85.615374,41.951076]},"n3831":{"id":"n3831","loc":[-85.61932,41.947564]},"n3832":{"id":"n3832","loc":[-85.610553,41.94755]},"n3833":{"id":"n3833","loc":[-85.610572,41.951065]},"n3834":{"id":"n3834","loc":[-85.617548,41.94757]},"n3835":{"id":"n3835","loc":[-85.619842,41.947939]},"n3836":{"id":"n3836","loc":[-85.619874,41.950905]},"n3837":{"id":"n3837","loc":[-85.619695,41.950911]},"n3838":{"id":"n3838","loc":[-85.617591,41.951078]},"n3839":{"id":"n3839","loc":[-85.619551,41.951065]},"n384":{"id":"n384","loc":[-85.632616,41.944021]},"n3840":{"id":"n3840","loc":[-85.626813,41.947337]},"n3841":{"id":"n3841","loc":[-85.616371,41.952814]},"n3842":{"id":"n3842","loc":[-85.617205,41.951308]},"n3843":{"id":"n3843","loc":[-85.616795,41.950953]},"n3844":{"id":"n3844","loc":[-85.617441,41.950889]},"n3845":{"id":"n3845","loc":[-85.619155,41.949377]},"n3846":{"id":"n3846","loc":[-85.618556,41.949377]},"n3847":{"id":"n3847","loc":[-85.618557,41.948372]},"n3848":{"id":"n3848","loc":[-85.619156,41.948372]},"n3849":{"id":"n3849","loc":[-85.61927,41.949796]},"n385":{"id":"n385","loc":[-85.632319,41.944172]},"n3850":{"id":"n3850","loc":[-85.61926,41.948344]},"n3851":{"id":"n3851","loc":[-85.619219,41.948264]},"n3852":{"id":"n3852","loc":[-85.619147,41.948196]},"n3853":{"id":"n3853","loc":[-85.619049,41.948144]},"n3854":{"id":"n3854","loc":[-85.618942,41.948116]},"n3855":{"id":"n3855","loc":[-85.618822,41.948109]},"n3856":{"id":"n3856","loc":[-85.618699,41.94813]},"n3857":{"id":"n3857","loc":[-85.618937,41.951943]},"n3858":{"id":"n3858","loc":[-85.616755,41.952231]},"n3859":{"id":"n3859","loc":[-85.616799,41.95472]},"n386":{"id":"n386","loc":[-85.63221,41.944066]},"n3860":{"id":"n3860","loc":[-85.616458,41.954735]},"n3861":{"id":"n3861","loc":[-85.61763,41.951515]},"n3862":{"id":"n3862","loc":[-85.617735,41.951572]},"n3863":{"id":"n3863","loc":[-85.61929,41.951573]},"n3864":{"id":"n3864","loc":[-85.617134,41.951348]},"n3865":{"id":"n3865","loc":[-85.616598,41.95192]},"n3866":{"id":"n3866","loc":[-85.616572,41.951992]},"n3867":{"id":"n3867","loc":[-85.616583,41.952076]},"n3868":{"id":"n3868","loc":[-85.616636,41.952145]},"n3869":{"id":"n3869","loc":[-85.616916,41.952279]},"n387":{"id":"n387","loc":[-85.632524,41.943912]},"n3870":{"id":"n3870","loc":[-85.617088,41.952254]},"n3871":{"id":"n3871","loc":[-85.61892,41.951467]},"n3872":{"id":"n3872","loc":[-85.618035,41.951473]},"n3873":{"id":"n3873","loc":[-85.618036,41.951572]},"n3874":{"id":"n3874","loc":[-85.61892,41.951573]},"n3875":{"id":"n3875","loc":[-85.618919,41.951957]},"n3876":{"id":"n3876","loc":[-85.619457,41.952237]},"n3877":{"id":"n3877","loc":[-85.618178,41.953618]},"n3878":{"id":"n3878","loc":[-85.617658,41.953366]},"n3879":{"id":"n3879","loc":[-85.617987,41.953024]},"n388":{"id":"n388","loc":[-85.632268,41.943621]},"n3880":{"id":"n3880","loc":[-85.618429,41.953248]},"n3881":{"id":"n3881","loc":[-85.618554,41.953119]},"n3882":{"id":"n3882","loc":[-85.618077,41.952868]},"n3883":{"id":"n3883","loc":[-85.618039,41.952886]},"n3884":{"id":"n3884","loc":[-85.619375,41.952169]},"n3885":{"id":"n3885","loc":[-85.618137,41.953538]},"n3886":{"id":"n3886","loc":[-85.61799,41.953555]},"n3887":{"id":"n3887","loc":[-85.617729,41.953423]},"n3888":{"id":"n3888","loc":[-85.618101,41.953029]},"n3889":{"id":"n3889","loc":[-85.618516,41.953119]},"n389":{"id":"n389","loc":[-85.631951,41.943773]},"n3890":{"id":"n3890","loc":[-85.619132,41.952042]},"n3891":{"id":"n3891","loc":[-85.618235,41.952981]},"n3892":{"id":"n3892","loc":[-85.618485,41.952425]},"n3893":{"id":"n3893","loc":[-85.618676,41.952519]},"n3894":{"id":"n3894","loc":[-85.618942,41.952648]},"n3895":{"id":"n3895","loc":[-85.618287,41.953122]},"n3896":{"id":"n3896","loc":[-85.617914,41.953516]},"n3897":{"id":"n3897","loc":[-85.617836,41.953573]},"n3898":{"id":"n3898","loc":[-85.616477,41.95289]},"n3899":{"id":"n3899","loc":[-85.618441,41.953201]},"n39":{"id":"n39","loc":[-85.619931,41.951013]},"n390":{"id":"n390","loc":[-85.631981,41.943654]},"n3900":{"id":"n3900","loc":[-85.617537,41.953335]},"n3901":{"id":"n3901","loc":[-85.617221,41.953166]},"n3902":{"id":"n3902","loc":[-85.617253,41.953135]},"n3903":{"id":"n3903","loc":[-85.617211,41.953114]},"n3904":{"id":"n3904","loc":[-85.617197,41.95313]},"n3905":{"id":"n3905","loc":[-85.616802,41.952925]},"n3906":{"id":"n3906","loc":[-85.616771,41.952928]},"n3907":{"id":"n3907","loc":[-85.616493,41.952785]},"n3908":{"id":"n3908","loc":[-85.616823,41.952426]},"n3909":{"id":"n3909","loc":[-85.617191,41.952616]},"n391":{"id":"n391","loc":[-85.631886,41.943699]},"n3910":{"id":"n3910","loc":[-85.61724,41.952559]},"n3911":{"id":"n3911","loc":[-85.61721,41.952542]},"n3912":{"id":"n3912","loc":[-85.617395,41.952351]},"n3913":{"id":"n3913","loc":[-85.617426,41.952368]},"n3914":{"id":"n3914","loc":[-85.617483,41.952309]},"n3915":{"id":"n3915","loc":[-85.617332,41.952229]},"n3916":{"id":"n3916","loc":[-85.617451,41.952102]},"n3917":{"id":"n3917","loc":[-85.617477,41.952115]},"n3918":{"id":"n3918","loc":[-85.617658,41.951923]},"n3919":{"id":"n3919","loc":[-85.617634,41.95191]},"n392":{"id":"n392","loc":[-85.631807,41.943606]},"n3920":{"id":"n3920","loc":[-85.617747,41.951786]},"n3921":{"id":"n3921","loc":[-85.618268,41.952056]},"n3922":{"id":"n3922","loc":[-85.618211,41.952122]},"n3923":{"id":"n3923","loc":[-85.618386,41.95222]},"n3924":{"id":"n3924","loc":[-85.618098,41.952527]},"n3925":{"id":"n3925","loc":[-85.617916,41.95243]},"n3926":{"id":"n3926","loc":[-85.617854,41.952498]},"n3927":{"id":"n3927","loc":[-85.617769,41.952453]},"n3928":{"id":"n3928","loc":[-85.617476,41.952773]},"n3929":{"id":"n3929","loc":[-85.617876,41.952973]},"n393":{"id":"n393","loc":[-85.631902,41.943561]},"n3930":{"id":"n3930","loc":[-85.617174,41.953638]},"n3931":{"id":"n3931","loc":[-85.618016,41.953578]},"n3932":{"id":"n3932","loc":[-85.618107,41.953628]},"n3933":{"id":"n3933","loc":[-85.618067,41.954268]},"n3934":{"id":"n3934","loc":[-85.617864,41.954263]},"n3935":{"id":"n3935","loc":[-85.61762,41.954205]},"n3936":{"id":"n3936","loc":[-85.617437,41.954103]},"n3937":{"id":"n3937","loc":[-85.617294,41.953978]},"n3938":{"id":"n3938","loc":[-85.617217,41.95384]},"n3939":{"id":"n3939","loc":[-85.616814,41.954327]},"n394":{"id":"n394","loc":[-85.63236,41.943543]},"n3940":{"id":"n3940","loc":[-85.616778,41.95381]},"n3941":{"id":"n3941","loc":[-85.616585,41.953707]},"n3942":{"id":"n3942","loc":[-85.616458,41.954318]},"n3943":{"id":"n3943","loc":[-85.616643,41.954345]},"n3944":{"id":"n3944","loc":[-85.618133,41.951412]},"n3945":{"id":"n3945","loc":[-85.618326,41.951411]},"n3946":{"id":"n3946","loc":[-85.618503,41.95141]},"n3947":{"id":"n3947","loc":[-85.618681,41.951409]},"n3948":{"id":"n3948","loc":[-85.618868,41.951408]},"n3949":{"id":"n3949","loc":[-85.617047,41.95136]},"n395":{"id":"n395","loc":[-85.633839,41.944082]},"n3950":{"id":"n3950","loc":[-85.616494,41.951959]},"n3951":{"id":"n3951","loc":[-85.616497,41.952072]},"n3952":{"id":"n3952","loc":[-85.616565,41.952165]},"n3953":{"id":"n3953","loc":[-85.616663,41.952218]},"n3954":{"id":"n3954","loc":[-85.616733,41.952255]},"n3955":{"id":"n3955","loc":[-85.617238,41.952512],"tags":{"entrance":"yes"}},"n3956":{"id":"n3956","loc":[-85.617043,41.952406]},"n3957":{"id":"n3957","loc":[-85.617691,41.951711]},"n3958":{"id":"n3958","loc":[-85.617773,41.951679]},"n3959":{"id":"n3959","loc":[-85.619085,41.951681]},"n396":{"id":"n396","loc":[-85.63376,41.944097]},"n3960":{"id":"n3960","loc":[-85.617943,41.952895]},"n3961":{"id":"n3961","loc":[-85.618039,41.952938]},"n3962":{"id":"n3962","loc":[-85.61763,41.95336]},"n3963":{"id":"n3963","loc":[-85.617554,41.95344]},"n3964":{"id":"n3964","loc":[-85.617381,41.952366],"tags":{"entrance":"yes"}},"n3965":{"id":"n3965","loc":[-85.617184,41.952254]},"n3966":{"id":"n3966","loc":[-85.617208,41.952496]},"n3967":{"id":"n3967","loc":[-85.617124,41.952581],"tags":{"entrance":"yes"}},"n3968":{"id":"n3968","loc":[-85.618094,41.952735]},"n3969":{"id":"n3969","loc":[-85.617702,41.952525],"tags":{"entrance":"yes"}},"n397":{"id":"n397","loc":[-85.63361,41.943957]},"n3970":{"id":"n3970","loc":[-85.617554,41.952686],"tags":{"entrance":"yes"}},"n3971":{"id":"n3971","loc":[-85.617959,41.952878]},"n3972":{"id":"n3972","loc":[-85.616367,41.952655]},"n3973":{"id":"n3973","loc":[-85.616416,41.952851]},"n3974":{"id":"n3974","loc":[-85.619777,41.951075]},"n3975":{"id":"n3975","loc":[-85.618611,41.94817]},"n3976":{"id":"n3976","loc":[-85.618538,41.948229]},"n3977":{"id":"n3977","loc":[-85.617421,41.947559]},"n3978":{"id":"n3978","loc":[-85.617395,41.951039]},"n3979":{"id":"n3979","loc":[-85.618488,41.94829]},"n398":{"id":"n398","loc":[-85.633309,41.943886]},"n3980":{"id":"n3980","loc":[-85.610238,41.954774]},"n3981":{"id":"n3981","loc":[-85.617449,41.950756]},"n3982":{"id":"n3982","loc":[-85.617288,41.951286]},"n3983":{"id":"n3983","loc":[-85.61745,41.950197]},"n3984":{"id":"n3984","loc":[-85.617436,41.948908]},"n3985":{"id":"n3985","loc":[-85.615915,41.953804]},"n3986":{"id":"n3986","loc":[-85.615953,41.953968]},"n3987":{"id":"n3987","loc":[-85.616031,41.954085]},"n3988":{"id":"n3988","loc":[-85.616135,41.954181]},"n3989":{"id":"n3989","loc":[-85.616273,41.954263]},"n399":{"id":"n399","loc":[-85.633226,41.943931]},"n3990":{"id":"n3990","loc":[-85.618327,41.951083]},"n3991":{"id":"n3991","loc":[-85.618135,41.951084]},"n3992":{"id":"n3992","loc":[-85.618503,41.951082]},"n3993":{"id":"n3993","loc":[-85.618682,41.951081]},"n3994":{"id":"n3994","loc":[-85.618864,41.951082]},"n3995":{"id":"n3995","loc":[-85.616761,41.950101]},"n3996":{"id":"n3996","loc":[-85.617317,41.947558]},"n3997":{"id":"n3997","loc":[-85.617336,41.948883]},"n3998":{"id":"n3998","loc":[-85.616779,41.949295]},"n3999":{"id":"n3999","loc":[-85.616754,41.949349]},"n4":{"id":"n4","loc":[-85.622764,41.950892],"tags":{"highway":"stop"}},"n40":{"id":"n40","loc":[-85.619841,41.951037]},"n400":{"id":"n400","loc":[-85.63326,41.943966]},"n4000":{"id":"n4000","loc":[-85.616761,41.950865]},"n4001":{"id":"n4001","loc":[-85.616883,41.951041]},"n4002":{"id":"n4002","loc":[-85.617004,41.951142]},"n4003":{"id":"n4003","loc":[-85.617062,41.951248]},"n4004":{"id":"n4004","loc":[-85.616809,41.949273]},"n4005":{"id":"n4005","loc":[-85.616755,41.949489]},"n4006":{"id":"n4006","loc":[-85.616759,41.949971]},"n4007":{"id":"n4007","loc":[-85.616757,41.949702]},"n4008":{"id":"n4008","loc":[-85.618456,41.94836]},"n4009":{"id":"n4009","loc":[-85.618447,41.948428]},"n401":{"id":"n401","loc":[-85.63324,41.943976]},"n4010":{"id":"n4010","loc":[-85.618437,41.949322]},"n4011":{"id":"n4011","loc":[-85.618447,41.949418]},"n4012":{"id":"n4012","loc":[-85.618478,41.949491]},"n4013":{"id":"n4013","loc":[-85.618535,41.949559]},"n4014":{"id":"n4014","loc":[-85.618623,41.94962]},"n4015":{"id":"n4015","loc":[-85.618721,41.94966]},"n4016":{"id":"n4016","loc":[-85.618838,41.949674]},"n4017":{"id":"n4017","loc":[-85.618967,41.949667]},"n4018":{"id":"n4018","loc":[-85.619065,41.949632]},"n4019":{"id":"n4019","loc":[-85.61915,41.949578]},"n402":{"id":"n402","loc":[-85.63327,41.944006]},"n4020":{"id":"n4020","loc":[-85.619216,41.949507]},"n4021":{"id":"n4021","loc":[-85.61927,41.949399]},"n4022":{"id":"n4022","loc":[-85.619074,41.947639]},"n4023":{"id":"n4023","loc":[-85.619073,41.947793]},"n4024":{"id":"n4024","loc":[-85.618912,41.947793]},"n4025":{"id":"n4025","loc":[-85.618911,41.947947]},"n4026":{"id":"n4026","loc":[-85.618752,41.947947]},"n4027":{"id":"n4027","loc":[-85.618754,41.947637]},"n4028":{"id":"n4028","loc":[-85.617896,41.947599]},"n4029":{"id":"n4029","loc":[-85.617898,41.947811]},"n403":{"id":"n403","loc":[-85.633278,41.944002]},"n4030":{"id":"n4030","loc":[-85.617717,41.947812]},"n4031":{"id":"n4031","loc":[-85.617715,41.9476]},"n4032":{"id":"n4032","loc":[-85.619003,41.949828]},"n4033":{"id":"n4033","loc":[-85.619003,41.949882]},"n4034":{"id":"n4034","loc":[-85.618926,41.949882]},"n4035":{"id":"n4035","loc":[-85.618926,41.949828]},"n4036":{"id":"n4036","loc":[-85.618861,41.949809]},"n4037":{"id":"n4037","loc":[-85.618861,41.949898]},"n4038":{"id":"n4038","loc":[-85.618688,41.949898]},"n4039":{"id":"n4039","loc":[-85.618687,41.94981]},"n404":{"id":"n404","loc":[-85.63331,41.944036]},"n4040":{"id":"n4040","loc":[-85.618349,41.949473]},"n4041":{"id":"n4041","loc":[-85.618287,41.949473]},"n4042":{"id":"n4042","loc":[-85.618287,41.94942]},"n4043":{"id":"n4043","loc":[-85.618348,41.949419]},"n4044":{"id":"n4044","loc":[-85.62316,41.951604]},"n4045":{"id":"n4045","loc":[-85.623026,41.951605]},"n4046":{"id":"n4046","loc":[-85.623023,41.951466]},"n4047":{"id":"n4047","loc":[-85.623134,41.951465]},"n4048":{"id":"n4048","loc":[-85.623136,41.951539]},"n4049":{"id":"n4049","loc":[-85.623159,41.951539]},"n405":{"id":"n405","loc":[-85.633348,41.944015]},"n4050":{"id":"n4050","loc":[-85.623025,41.95155]},"n4051":{"id":"n4051","loc":[-85.622955,41.951551]},"n4052":{"id":"n4052","loc":[-85.622953,41.951507]},"n4053":{"id":"n4053","loc":[-85.623024,41.951506]},"n4054":{"id":"n4054","loc":[-85.623318,41.951242]},"n4055":{"id":"n4055","loc":[-85.623175,41.951241]},"n4056":{"id":"n4056","loc":[-85.623176,41.951153]},"n4057":{"id":"n4057","loc":[-85.623319,41.951154]},"n4058":{"id":"n4058","loc":[-85.623077,41.951191]},"n4059":{"id":"n4059","loc":[-85.622973,41.951191]},"n406":{"id":"n406","loc":[-85.63338,41.944048]},"n4060":{"id":"n4060","loc":[-85.622972,41.951349]},"n4061":{"id":"n4061","loc":[-85.623059,41.95135]},"n4062":{"id":"n4062","loc":[-85.62306,41.951301]},"n4063":{"id":"n4063","loc":[-85.623077,41.951301]},"n4064":{"id":"n4064","loc":[-85.623117,41.951405]},"n4065":{"id":"n4065","loc":[-85.62312,41.951087]},"n4066":{"id":"n4066","loc":[-85.623118,41.951274]},"n4067":{"id":"n4067","loc":[-85.62328,41.951275]},"n4068":{"id":"n4068","loc":[-85.62328,41.951242]},"n4069":{"id":"n4069","loc":[-85.623179,41.951392]},"n407":{"id":"n407","loc":[-85.633431,41.94402]},"n4070":{"id":"n4070","loc":[-85.623141,41.951392]},"n4071":{"id":"n4071","loc":[-85.623142,41.95136]},"n4072":{"id":"n4072","loc":[-85.623179,41.951361]},"n4073":{"id":"n4073","loc":[-85.622565,41.951639]},"n4074":{"id":"n4074","loc":[-85.622565,41.951741]},"n4075":{"id":"n4075","loc":[-85.622463,41.95174]},"n4076":{"id":"n4076","loc":[-85.622463,41.95173]},"n4077":{"id":"n4077","loc":[-85.622442,41.95173]},"n4078":{"id":"n4078","loc":[-85.622442,41.951742]},"n4079":{"id":"n4079","loc":[-85.622361,41.951742]},"n408":{"id":"n408","loc":[-85.633425,41.944014]},"n4080":{"id":"n4080","loc":[-85.622362,41.951667]},"n4081":{"id":"n4081","loc":[-85.622441,41.951667]},"n4082":{"id":"n4082","loc":[-85.622441,41.951688]},"n4083":{"id":"n4083","loc":[-85.622461,41.951688]},"n4084":{"id":"n4084","loc":[-85.622461,41.951638]},"n4085":{"id":"n4085","loc":[-85.62255,41.951587]},"n4086":{"id":"n4086","loc":[-85.622449,41.95159]},"n4087":{"id":"n4087","loc":[-85.622441,41.951448]},"n4088":{"id":"n4088","loc":[-85.62253,41.951445]},"n4089":{"id":"n4089","loc":[-85.622532,41.951486]},"n409":{"id":"n409","loc":[-85.633457,41.943997]},"n4090":{"id":"n4090","loc":[-85.622555,41.951485]},"n4091":{"id":"n4091","loc":[-85.622558,41.951531]},"n4092":{"id":"n4092","loc":[-85.622547,41.951531]},"n4093":{"id":"n4093","loc":[-85.622451,41.95159]},"n4094":{"id":"n4094","loc":[-85.622452,41.95161]},"n4095":{"id":"n4095","loc":[-85.622106,41.951617]},"n4096":{"id":"n4096","loc":[-85.622133,41.951443]},"n4097":{"id":"n4097","loc":[-85.622552,41.951379]},"n4098":{"id":"n4098","loc":[-85.622443,41.95138]},"n4099":{"id":"n4099","loc":[-85.622441,41.951281]},"n41":{"id":"n41","loc":[-85.636233,41.942764]},"n410":{"id":"n410","loc":[-85.633429,41.943969]},"n4100":{"id":"n4100","loc":[-85.62255,41.95128]},"n4101":{"id":"n4101","loc":[-85.622541,41.951437]},"n4102":{"id":"n4102","loc":[-85.622441,41.951438]},"n4103":{"id":"n4103","loc":[-85.621561,41.951444]},"n4104":{"id":"n4104","loc":[-85.622302,41.951479]},"n4105":{"id":"n4105","loc":[-85.6223,41.95152]},"n4106":{"id":"n4106","loc":[-85.622169,41.951517]},"n4107":{"id":"n4107","loc":[-85.622171,41.951476]},"n4108":{"id":"n4108","loc":[-85.622543,41.951228]},"n4109":{"id":"n4109","loc":[-85.622433,41.951228]},"n411":{"id":"n411","loc":[-85.633442,41.943962]},"n4110":{"id":"n4110","loc":[-85.622433,41.951133]},"n4111":{"id":"n4111","loc":[-85.622543,41.951133]},"n4112":{"id":"n4112","loc":[-85.622356,41.951256]},"n4113":{"id":"n4113","loc":[-85.622293,41.951256]},"n4114":{"id":"n4114","loc":[-85.622292,41.9512]},"n4115":{"id":"n4115","loc":[-85.622313,41.9512]},"n4116":{"id":"n4116","loc":[-85.622312,41.951173]},"n4117":{"id":"n4117","loc":[-85.622364,41.951173]},"n4118":{"id":"n4118","loc":[-85.622365,41.951231]},"n4119":{"id":"n4119","loc":[-85.622355,41.951231]},"n412":{"id":"n412","loc":[-85.633411,41.943932]},"n4120":{"id":"n4120","loc":[-85.62197,41.951155]},"n4121":{"id":"n4121","loc":[-85.62197,41.951213]},"n4122":{"id":"n4122","loc":[-85.621848,41.951213]},"n4123":{"id":"n4123","loc":[-85.621848,41.951155]},"n4124":{"id":"n4124","loc":[-85.622193,41.951268]},"n4125":{"id":"n4125","loc":[-85.622194,41.951305]},"n4126":{"id":"n4126","loc":[-85.622121,41.951306]},"n4127":{"id":"n4127","loc":[-85.622121,41.951322]},"n4128":{"id":"n4128","loc":[-85.621984,41.951324]},"n4129":{"id":"n4129","loc":[-85.621983,41.951271]},"n413":{"id":"n413","loc":[-85.633421,41.943926]},"n4130":{"id":"n4130","loc":[-85.622171,41.9514]},"n4131":{"id":"n4131","loc":[-85.622148,41.951382]},"n4132":{"id":"n4132","loc":[-85.6221,41.951414]},"n4133":{"id":"n4133","loc":[-85.622122,41.951433]},"n4134":{"id":"n4134","loc":[-85.621782,41.951148]},"n4135":{"id":"n4135","loc":[-85.621783,41.951219]},"n4136":{"id":"n4136","loc":[-85.62164,41.951221]},"n4137":{"id":"n4137","loc":[-85.62164,41.951236]},"n4138":{"id":"n4138","loc":[-85.621556,41.951237]},"n4139":{"id":"n4139","loc":[-85.621555,41.95117]},"n414":{"id":"n414","loc":[-85.633376,41.94388]},"n4140":{"id":"n4140","loc":[-85.621644,41.951169]},"n4141":{"id":"n4141","loc":[-85.621643,41.951139]},"n4142":{"id":"n4142","loc":[-85.621719,41.951138]},"n4143":{"id":"n4143","loc":[-85.621719,41.951148]},"n4144":{"id":"n4144","loc":[-85.621409,41.951322]},"n4145":{"id":"n4145","loc":[-85.621338,41.951322]},"n4146":{"id":"n4146","loc":[-85.621336,41.95115]},"n4147":{"id":"n4147","loc":[-85.621521,41.951149]},"n4148":{"id":"n4148","loc":[-85.621522,41.951228]},"n4149":{"id":"n4149","loc":[-85.621408,41.951228]},"n415":{"id":"n415","loc":[-85.633348,41.943895]},"n4150":{"id":"n4150","loc":[-85.621284,41.951219]},"n4151":{"id":"n4151","loc":[-85.621153,41.951219]},"n4152":{"id":"n4152","loc":[-85.621152,41.951152]},"n4153":{"id":"n4153","loc":[-85.621283,41.951152]},"n4154":{"id":"n4154","loc":[-85.621159,41.951241]},"n4155":{"id":"n4155","loc":[-85.62116,41.951301]},"n4156":{"id":"n4156","loc":[-85.621088,41.951302]},"n4157":{"id":"n4157","loc":[-85.621088,41.951241]},"n4158":{"id":"n4158","loc":[-85.621049,41.951158]},"n4159":{"id":"n4159","loc":[-85.62105,41.951229]},"n416":{"id":"n416","loc":[-85.633341,41.943888]},"n4160":{"id":"n4160","loc":[-85.620976,41.951229]},"n4161":{"id":"n4161","loc":[-85.620977,41.951295]},"n4162":{"id":"n4162","loc":[-85.620887,41.951296]},"n4163":{"id":"n4163","loc":[-85.620886,41.951229]},"n4164":{"id":"n4164","loc":[-85.620862,41.951229]},"n4165":{"id":"n4165","loc":[-85.620861,41.951159]},"n4166":{"id":"n4166","loc":[-85.620626,41.951133]},"n4167":{"id":"n4167","loc":[-85.620626,41.951205]},"n4168":{"id":"n4168","loc":[-85.620412,41.951206]},"n4169":{"id":"n4169","loc":[-85.620411,41.951134]},"n417":{"id":"n417","loc":[-85.633321,41.943898]},"n4170":{"id":"n4170","loc":[-85.621775,41.951443]},"n4171":{"id":"n4171","loc":[-85.621777,41.951264]},"n4172":{"id":"n4172","loc":[-85.621565,41.951654]},"n4173":{"id":"n4173","loc":[-85.621331,41.951439]},"n4174":{"id":"n4174","loc":[-85.621031,41.951443]},"n4175":{"id":"n4175","loc":[-85.621836,41.951724]},"n4176":{"id":"n4176","loc":[-85.621834,41.951621]},"n4177":{"id":"n4177","loc":[-85.62197,41.951619]},"n4178":{"id":"n4178","loc":[-85.621972,41.951722]},"n4179":{"id":"n4179","loc":[-85.621772,41.951638]},"n418":{"id":"n418","loc":[-85.633547,41.943896]},"n4180":{"id":"n4180","loc":[-85.621772,41.951715]},"n4181":{"id":"n4181","loc":[-85.621699,41.951716]},"n4182":{"id":"n4182","loc":[-85.6217,41.951722]},"n4183":{"id":"n4183","loc":[-85.621641,41.951722]},"n4184":{"id":"n4184","loc":[-85.62164,41.951639]},"n4185":{"id":"n4185","loc":[-85.621505,41.951655]},"n4186":{"id":"n4186","loc":[-85.621505,41.951729]},"n4187":{"id":"n4187","loc":[-85.621389,41.951729]},"n4188":{"id":"n4188","loc":[-85.62139,41.951654]},"n4189":{"id":"n4189","loc":[-85.621105,41.951635]},"n419":{"id":"n419","loc":[-85.633467,41.944075]},"n4190":{"id":"n4190","loc":[-85.621104,41.951576]},"n4191":{"id":"n4191","loc":[-85.621168,41.951576]},"n4192":{"id":"n4192","loc":[-85.621168,41.951595]},"n4193":{"id":"n4193","loc":[-85.621261,41.951595]},"n4194":{"id":"n4194","loc":[-85.621261,41.951646]},"n4195":{"id":"n4195","loc":[-85.621294,41.951646]},"n4196":{"id":"n4196","loc":[-85.621294,41.951732]},"n4197":{"id":"n4197","loc":[-85.621251,41.951732]},"n4198":{"id":"n4198","loc":[-85.621251,41.95174]},"n4199":{"id":"n4199","loc":[-85.621175,41.951741]},"n42":{"id":"n42","loc":[-85.635996,41.942727]},"n420":{"id":"n420","loc":[-85.633578,41.944055]},"n4200":{"id":"n4200","loc":[-85.621175,41.951651]},"n4201":{"id":"n4201","loc":[-85.621189,41.951651]},"n4202":{"id":"n4202","loc":[-85.621189,41.951635]},"n4203":{"id":"n4203","loc":[-85.620554,41.951641]},"n4204":{"id":"n4204","loc":[-85.620555,41.951742]},"n4205":{"id":"n4205","loc":[-85.620719,41.951742]},"n4206":{"id":"n4206","loc":[-85.620719,41.951731]},"n4207":{"id":"n4207","loc":[-85.620803,41.95173]},"n4208":{"id":"n4208","loc":[-85.620803,41.951603]},"n4209":{"id":"n4209","loc":[-85.62072,41.951603]},"n421":{"id":"n421","loc":[-85.633462,41.944125]},"n4210":{"id":"n4210","loc":[-85.620721,41.951641]},"n4211":{"id":"n4211","loc":[-85.620269,41.953053]},"n4212":{"id":"n4212","loc":[-85.620229,41.953051]},"n4213":{"id":"n4213","loc":[-85.620231,41.953013]},"n4214":{"id":"n4214","loc":[-85.620271,41.953015]},"n4215":{"id":"n4215","loc":[-85.620215,41.953133]},"n4216":{"id":"n4216","loc":[-85.62013,41.953134]},"n4217":{"id":"n4217","loc":[-85.620129,41.953083]},"n4218":{"id":"n4218","loc":[-85.620214,41.953082]},"n4219":{"id":"n4219","loc":[-85.62016,41.953272]},"n422":{"id":"n422","loc":[-85.633372,41.944061]},"n4220":{"id":"n4220","loc":[-85.620046,41.953273]},"n4221":{"id":"n4221","loc":[-85.620045,41.953171]},"n4222":{"id":"n4222","loc":[-85.620088,41.953171]},"n4223":{"id":"n4223","loc":[-85.620087,41.953162]},"n4224":{"id":"n4224","loc":[-85.620121,41.953162]},"n4225":{"id":"n4225","loc":[-85.620121,41.953173]},"n4226":{"id":"n4226","loc":[-85.620157,41.953173]},"n4227":{"id":"n4227","loc":[-85.620158,41.953196]},"n4228":{"id":"n4228","loc":[-85.620189,41.953196]},"n4229":{"id":"n4229","loc":[-85.620189,41.953246]},"n423":{"id":"n423","loc":[-85.633509,41.943981]},"n4230":{"id":"n4230","loc":[-85.62016,41.953246]},"n4231":{"id":"n4231","loc":[-85.6195,41.954012]},"n4232":{"id":"n4232","loc":[-85.619438,41.954057]},"n4233":{"id":"n4233","loc":[-85.619418,41.954043]},"n4234":{"id":"n4234","loc":[-85.619381,41.954069]},"n4235":{"id":"n4235","loc":[-85.619399,41.954083]},"n4236":{"id":"n4236","loc":[-85.619339,41.954126]},"n4237":{"id":"n4237","loc":[-85.619584,41.954313]},"n4238":{"id":"n4238","loc":[-85.619743,41.954198]},"n4239":{"id":"n4239","loc":[-85.619453,41.954727]},"n424":{"id":"n424","loc":[-85.635421,41.945367]},"n4240":{"id":"n4240","loc":[-85.619503,41.954581]},"n4241":{"id":"n4241","loc":[-85.619597,41.954472]},"n4242":{"id":"n4242","loc":[-85.619862,41.95419]},"n4243":{"id":"n4243","loc":[-85.619506,41.953907]},"n4244":{"id":"n4244","loc":[-85.619261,41.9541]},"n4245":{"id":"n4245","loc":[-85.619246,41.954139]},"n4246":{"id":"n4246","loc":[-85.619244,41.9542]},"n4247":{"id":"n4247","loc":[-85.619259,41.954243]},"n4248":{"id":"n4248","loc":[-85.619285,41.954274]},"n4249":{"id":"n4249","loc":[-85.619123,41.954381]},"n425":{"id":"n425","loc":[-85.634425,41.943552]},"n4250":{"id":"n4250","loc":[-85.619641,41.954607]},"n4251":{"id":"n4251","loc":[-85.619383,41.954615]},"n4252":{"id":"n4252","loc":[-85.61896,41.954391]},"n4253":{"id":"n4253","loc":[-85.619211,41.954178]},"n4254":{"id":"n4254","loc":[-85.619115,41.954102]},"n4255":{"id":"n4255","loc":[-85.619519,41.953821]},"n4256":{"id":"n4256","loc":[-85.619956,41.954156]},"n4257":{"id":"n4257","loc":[-85.619851,41.954266]},"n4258":{"id":"n4258","loc":[-85.619779,41.95436]},"n4259":{"id":"n4259","loc":[-85.620525,41.954364]},"n426":{"id":"n426","loc":[-85.634248,41.943654]},"n4260":{"id":"n4260","loc":[-85.620398,41.954365]},"n4261":{"id":"n4261","loc":[-85.620398,41.954324]},"n4262":{"id":"n4262","loc":[-85.620525,41.954323]},"n4263":{"id":"n4263","loc":[-85.620359,41.954588]},"n4264":{"id":"n4264","loc":[-85.620321,41.954588]},"n4265":{"id":"n4265","loc":[-85.620321,41.954599]},"n4266":{"id":"n4266","loc":[-85.620296,41.954599]},"n4267":{"id":"n4267","loc":[-85.620296,41.954587]},"n4268":{"id":"n4268","loc":[-85.620262,41.954588]},"n4269":{"id":"n4269","loc":[-85.620261,41.954516]},"n427":{"id":"n427","loc":[-85.634177,41.943585]},"n4270":{"id":"n4270","loc":[-85.620282,41.954516]},"n4271":{"id":"n4271","loc":[-85.620282,41.954373]},"n4272":{"id":"n4272","loc":[-85.620378,41.954373]},"n4273":{"id":"n4273","loc":[-85.620379,41.954486]},"n4274":{"id":"n4274","loc":[-85.620348,41.954486]},"n4275":{"id":"n4275","loc":[-85.620348,41.954537]},"n4276":{"id":"n4276","loc":[-85.620359,41.954537]},"n4277":{"id":"n4277","loc":[-85.620463,41.95521]},"n4278":{"id":"n4278","loc":[-85.620409,41.955273]},"n4279":{"id":"n4279","loc":[-85.620205,41.955177]},"n428":{"id":"n428","loc":[-85.634354,41.943484]},"n4280":{"id":"n4280","loc":[-85.620288,41.955079]},"n4281":{"id":"n4281","loc":[-85.620379,41.955121]},"n4282":{"id":"n4282","loc":[-85.620349,41.955157]},"n4283":{"id":"n4283","loc":[-85.620083,41.955101]},"n4284":{"id":"n4284","loc":[-85.620083,41.954986]},"n4285":{"id":"n4285","loc":[-85.620016,41.954986]},"n4286":{"id":"n4286","loc":[-85.620016,41.954999]},"n4287":{"id":"n4287","loc":[-85.619941,41.954999]},"n4288":{"id":"n4288","loc":[-85.619941,41.954988]},"n4289":{"id":"n4289","loc":[-85.619815,41.954988]},"n429":{"id":"n429","loc":[-85.638577,41.943212]},"n4290":{"id":"n4290","loc":[-85.619815,41.955075]},"n4291":{"id":"n4291","loc":[-85.619948,41.955075]},"n4292":{"id":"n4292","loc":[-85.619948,41.955082]},"n4293":{"id":"n4293","loc":[-85.620004,41.955082]},"n4294":{"id":"n4294","loc":[-85.620004,41.955101]},"n4295":{"id":"n4295","loc":[-85.619293,41.955127]},"n4296":{"id":"n4296","loc":[-85.619208,41.955124]},"n4297":{"id":"n4297","loc":[-85.619212,41.955061]},"n4298":{"id":"n4298","loc":[-85.619297,41.955064]},"n4299":{"id":"n4299","loc":[-85.619068,41.954936]},"n43":{"id":"n43","loc":[-85.637047,41.943054]},"n430":{"id":"n430","loc":[-85.638576,41.943219]},"n4300":{"id":"n4300","loc":[-85.619003,41.954936]},"n4301":{"id":"n4301","loc":[-85.619004,41.955003]},"n4302":{"id":"n4302","loc":[-85.618994,41.955003]},"n4303":{"id":"n4303","loc":[-85.618994,41.955016]},"n4304":{"id":"n4304","loc":[-85.618973,41.955016]},"n4305":{"id":"n4305","loc":[-85.618973,41.955071]},"n4306":{"id":"n4306","loc":[-85.619061,41.955071]},"n4307":{"id":"n4307","loc":[-85.61906,41.955024]},"n4308":{"id":"n4308","loc":[-85.619105,41.955024]},"n4309":{"id":"n4309","loc":[-85.619105,41.954956]},"n431":{"id":"n431","loc":[-85.638653,41.943078]},"n4310":{"id":"n4310","loc":[-85.619068,41.954956]},"n4311":{"id":"n4311","loc":[-85.618294,41.954596]},"n4312":{"id":"n4312","loc":[-85.618235,41.954602]},"n4313":{"id":"n4313","loc":[-85.618222,41.954535]},"n4314":{"id":"n4314","loc":[-85.618281,41.954529]},"n4315":{"id":"n4315","loc":[-85.618593,41.954556]},"n4316":{"id":"n4316","loc":[-85.618551,41.954565]},"n4317":{"id":"n4317","loc":[-85.618545,41.954552]},"n4318":{"id":"n4318","loc":[-85.618493,41.954563]},"n4319":{"id":"n4319","loc":[-85.618449,41.954455]},"n432":{"id":"n432","loc":[-85.638654,41.943148]},"n4320":{"id":"n4320","loc":[-85.618544,41.954434]},"n4321":{"id":"n4321","loc":[-85.622545,41.950775]},"n4322":{"id":"n4322","loc":[-85.622546,41.950843]},"n4323":{"id":"n4323","loc":[-85.622503,41.950844]},"n4324":{"id":"n4324","loc":[-85.622503,41.950853]},"n4325":{"id":"n4325","loc":[-85.622479,41.950853]},"n4326":{"id":"n4326","loc":[-85.622478,41.950843]},"n4327":{"id":"n4327","loc":[-85.622425,41.950843]},"n4328":{"id":"n4328","loc":[-85.622425,41.950808]},"n4329":{"id":"n4329","loc":[-85.622366,41.950809]},"n433":{"id":"n433","loc":[-85.638387,41.943151]},"n4330":{"id":"n4330","loc":[-85.622364,41.950673]},"n4331":{"id":"n4331","loc":[-85.622448,41.950673]},"n4332":{"id":"n4332","loc":[-85.622449,41.950732]},"n4333":{"id":"n4333","loc":[-85.622479,41.950731]},"n4334":{"id":"n4334","loc":[-85.622479,41.950775]},"n4335":{"id":"n4335","loc":[-85.621909,41.950641]},"n4336":{"id":"n4336","loc":[-85.621864,41.950641]},"n4337":{"id":"n4337","loc":[-85.621865,41.950567]},"n4338":{"id":"n4338","loc":[-85.62191,41.950567]},"n4339":{"id":"n4339","loc":[-85.621787,41.950829]},"n434":{"id":"n434","loc":[-85.638386,41.94308]},"n4340":{"id":"n4340","loc":[-85.621786,41.950775]},"n4341":{"id":"n4341","loc":[-85.621588,41.950776]},"n4342":{"id":"n4342","loc":[-85.621589,41.950848]},"n4343":{"id":"n4343","loc":[-85.621737,41.950847]},"n4344":{"id":"n4344","loc":[-85.621737,41.950829]},"n4345":{"id":"n4345","loc":[-85.621509,41.950846]},"n4346":{"id":"n4346","loc":[-85.621399,41.950846]},"n4347":{"id":"n4347","loc":[-85.621398,41.95073]},"n4348":{"id":"n4348","loc":[-85.621509,41.95073]},"n4349":{"id":"n4349","loc":[-85.621217,41.950841]},"n435":{"id":"n435","loc":[-85.634427,41.943533]},"n4350":{"id":"n4350","loc":[-85.6211,41.95084]},"n4351":{"id":"n4351","loc":[-85.6211,41.950777]},"n4352":{"id":"n4352","loc":[-85.621218,41.950778]},"n4353":{"id":"n4353","loc":[-85.621055,41.950764]},"n4354":{"id":"n4354","loc":[-85.621054,41.950826]},"n4355":{"id":"n4355","loc":[-85.620988,41.950826]},"n4356":{"id":"n4356","loc":[-85.620988,41.950843]},"n4357":{"id":"n4357","loc":[-85.620842,41.950843]},"n4358":{"id":"n4358","loc":[-85.620842,41.950764]},"n4359":{"id":"n4359","loc":[-85.620825,41.950922]},"n436":{"id":"n436","loc":[-85.63428,41.943229]},"n4360":{"id":"n4360","loc":[-85.620824,41.950553]},"n4361":{"id":"n4361","loc":[-85.620543,41.950771]},"n4362":{"id":"n4362","loc":[-85.620431,41.950772]},"n4363":{"id":"n4363","loc":[-85.62043,41.950585]},"n4364":{"id":"n4364","loc":[-85.620542,41.950585]},"n4365":{"id":"n4365","loc":[-85.62068,41.950505]},"n4366":{"id":"n4366","loc":[-85.620681,41.950552]},"n4367":{"id":"n4367","loc":[-85.620589,41.950553]},"n4368":{"id":"n4368","loc":[-85.620588,41.950506]},"n4369":{"id":"n4369","loc":[-85.620539,41.950407]},"n437":{"id":"n437","loc":[-85.634499,41.943461]},"n4370":{"id":"n4370","loc":[-85.62054,41.950504]},"n4371":{"id":"n4371","loc":[-85.620416,41.950504]},"n4372":{"id":"n4372","loc":[-85.620416,41.950408]},"n4373":{"id":"n4373","loc":[-85.620742,41.95038]},"n4374":{"id":"n4374","loc":[-85.620527,41.95038]},"n4375":{"id":"n4375","loc":[-85.620528,41.950408]},"n4376":{"id":"n4376","loc":[-85.622449,41.950373]},"n4377":{"id":"n4377","loc":[-85.622452,41.950397]},"n4378":{"id":"n4378","loc":[-85.622336,41.950404]},"n4379":{"id":"n4379","loc":[-85.622333,41.950379]},"n438":{"id":"n438","loc":[-85.634514,41.943486]},"n4380":{"id":"n4380","loc":[-85.622263,41.950324]},"n4381":{"id":"n4381","loc":[-85.622261,41.950256]},"n4382":{"id":"n4382","loc":[-85.62236,41.950254]},"n4383":{"id":"n4383","loc":[-85.62236,41.95027]},"n4384":{"id":"n4384","loc":[-85.622402,41.950281]},"n4385":{"id":"n4385","loc":[-85.622403,41.9503]},"n4386":{"id":"n4386","loc":[-85.622439,41.950299]},"n4387":{"id":"n4387","loc":[-85.62244,41.950334]},"n4388":{"id":"n4388","loc":[-85.622414,41.950335]},"n4389":{"id":"n4389","loc":[-85.622414,41.95036]},"n439":{"id":"n439","loc":[-85.63452,41.943511]},"n4390":{"id":"n4390","loc":[-85.62231,41.950362]},"n4391":{"id":"n4391","loc":[-85.622309,41.950323]},"n4392":{"id":"n4392","loc":[-85.622015,41.950539]},"n4393":{"id":"n4393","loc":[-85.621909,41.95054]},"n4394":{"id":"n4394","loc":[-85.621909,41.950472]},"n4395":{"id":"n4395","loc":[-85.622015,41.950471]},"n4396":{"id":"n4396","loc":[-85.62199,41.950439]},"n4397":{"id":"n4397","loc":[-85.621956,41.95044]},"n4398":{"id":"n4398","loc":[-85.621955,41.950405]},"n4399":{"id":"n4399","loc":[-85.621988,41.950404]},"n44":{"id":"n44","loc":[-85.636799,41.943055]},"n440":{"id":"n440","loc":[-85.63451,41.943534]},"n4400":{"id":"n4400","loc":[-85.621668,41.950418]},"n4401":{"id":"n4401","loc":[-85.621667,41.950343]},"n4402":{"id":"n4402","loc":[-85.621745,41.950342]},"n4403":{"id":"n4403","loc":[-85.621744,41.950306]},"n4404":{"id":"n4404","loc":[-85.621764,41.950306]},"n4405":{"id":"n4405","loc":[-85.621763,41.950254]},"n4406":{"id":"n4406","loc":[-85.621861,41.950253]},"n4407":{"id":"n4407","loc":[-85.621861,41.950274]},"n4408":{"id":"n4408","loc":[-85.621896,41.950273]},"n4409":{"id":"n4409","loc":[-85.621898,41.950389]},"n441":{"id":"n441","loc":[-85.634483,41.943556]},"n4410":{"id":"n4410","loc":[-85.621843,41.95039]},"n4411":{"id":"n4411","loc":[-85.621843,41.950425]},"n4412":{"id":"n4412","loc":[-85.621789,41.950425]},"n4413":{"id":"n4413","loc":[-85.621789,41.950386]},"n4414":{"id":"n4414","loc":[-85.621752,41.950387]},"n4415":{"id":"n4415","loc":[-85.621753,41.950417]},"n4416":{"id":"n4416","loc":[-85.621556,41.950562]},"n4417":{"id":"n4417","loc":[-85.621552,41.950217]},"n4418":{"id":"n4418","loc":[-85.621788,41.950562]},"n4419":{"id":"n4419","loc":[-85.621155,41.950562]},"n442":{"id":"n442","loc":[-85.63419,41.943713]},"n4420":{"id":"n4420","loc":[-85.622473,41.950551]},"n4421":{"id":"n4421","loc":[-85.622043,41.950551]},"n4422":{"id":"n4422","loc":[-85.62142,41.950454]},"n4423":{"id":"n4423","loc":[-85.621315,41.950455]},"n4424":{"id":"n4424","loc":[-85.621313,41.950311]},"n4425":{"id":"n4425","loc":[-85.621388,41.950311]},"n4426":{"id":"n4426","loc":[-85.621387,41.950261]},"n4427":{"id":"n4427","loc":[-85.621468,41.95026]},"n4428":{"id":"n4428","loc":[-85.621468,41.950271]},"n4429":{"id":"n4429","loc":[-85.621503,41.95027]},"n443":{"id":"n443","loc":[-85.634462,41.943294]},"n4430":{"id":"n4430","loc":[-85.621505,41.950353]},"n4431":{"id":"n4431","loc":[-85.621483,41.950354]},"n4432":{"id":"n4432","loc":[-85.621483,41.950392]},"n4433":{"id":"n4433","loc":[-85.621419,41.950393]},"n4434":{"id":"n4434","loc":[-85.621213,41.95039]},"n4435":{"id":"n4435","loc":[-85.621127,41.950391]},"n4436":{"id":"n4436","loc":[-85.621126,41.950357]},"n4437":{"id":"n4437","loc":[-85.621094,41.950357]},"n4438":{"id":"n4438","loc":[-85.621094,41.950391]},"n4439":{"id":"n4439","loc":[-85.620977,41.950392]},"n444":{"id":"n444","loc":[-85.634298,41.943389]},"n4440":{"id":"n4440","loc":[-85.620975,41.950278]},"n4441":{"id":"n4441","loc":[-85.621087,41.950277]},"n4442":{"id":"n4442","loc":[-85.621088,41.950331]},"n4443":{"id":"n4443","loc":[-85.621211,41.950312]},"n4444":{"id":"n4444","loc":[-85.621104,41.950313]},"n4445":{"id":"n4445","loc":[-85.621105,41.950331]},"n4446":{"id":"n4446","loc":[-85.620706,41.950328]},"n4447":{"id":"n4447","loc":[-85.620606,41.950327]},"n4448":{"id":"n4448","loc":[-85.620607,41.950261]},"n4449":{"id":"n4449","loc":[-85.620707,41.950262]},"n445":{"id":"n445","loc":[-85.634527,41.943623]},"n4450":{"id":"n4450","loc":[-85.620599,41.950336]},"n4451":{"id":"n4451","loc":[-85.620559,41.950336]},"n4452":{"id":"n4452","loc":[-85.620559,41.950299]},"n4453":{"id":"n4453","loc":[-85.620599,41.950299]},"n4454":{"id":"n4454","loc":[-85.620545,41.950357]},"n4455":{"id":"n4455","loc":[-85.620418,41.950357]},"n4456":{"id":"n4456","loc":[-85.620417,41.950257]},"n4457":{"id":"n4457","loc":[-85.620544,41.950256]},"n4458":{"id":"n4458","loc":[-85.620246,41.950131],"tags":{"highway":"crossing"}},"n4459":{"id":"n4459","loc":[-85.620252,41.950956]},"n446":{"id":"n446","loc":[-85.634608,41.943577]},"n4460":{"id":"n4460","loc":[-85.620245,41.950179]},"n4461":{"id":"n4461","loc":[-85.620246,41.950088]},"n4462":{"id":"n4462","loc":[-85.620251,41.950885]},"n4463":{"id":"n4463","loc":[-85.620103,41.950884],"tags":{"crossing":"zebra","highway":"crossing"}},"n4464":{"id":"n4464","loc":[-85.619992,41.950884]},"n4465":{"id":"n4465","loc":[-85.619704,41.951008]},"n4466":{"id":"n4466","loc":[-85.619599,41.951122]},"n4467":{"id":"n4467","loc":[-85.619264,41.951486]},"n4468":{"id":"n4468","loc":[-85.619179,41.951573],"tags":{"highway":"crossing"}},"n4469":{"id":"n4469","loc":[-85.620251,41.950999],"tags":{"highway":"crossing"}},"n447":{"id":"n447","loc":[-85.634555,41.943531]},"n4470":{"id":"n4470","loc":[-85.620249,41.951066]},"n4471":{"id":"n4471","loc":[-85.620256,41.951374]},"n4472":{"id":"n4472","loc":[-85.620249,41.951389]},"n4473":{"id":"n4473","loc":[-85.620249,41.951407]},"n4474":{"id":"n4474","loc":[-85.620255,41.951423]},"n4475":{"id":"n4475","loc":[-85.62026,41.951853]},"n4476":{"id":"n4476","loc":[-85.620262,41.951894],"tags":{"highway":"crossing"}},"n4477":{"id":"n4477","loc":[-85.620265,41.951957]},"n4478":{"id":"n4478","loc":[-85.620262,41.952135]},"n4479":{"id":"n4479","loc":[-85.620241,41.952424]},"n448":{"id":"n448","loc":[-85.634555,41.943482]},"n4480":{"id":"n4480","loc":[-85.620213,41.952583]},"n4481":{"id":"n4481","loc":[-85.620158,41.952754]},"n4482":{"id":"n4482","loc":[-85.620065,41.952942]},"n4483":{"id":"n4483","loc":[-85.619753,41.953439]},"n4484":{"id":"n4484","loc":[-85.619605,41.953626]},"n4485":{"id":"n4485","loc":[-85.619381,41.953834]},"n4486":{"id":"n4486","loc":[-85.619069,41.954066]},"n4487":{"id":"n4487","loc":[-85.618674,41.95429]},"n4488":{"id":"n4488","loc":[-85.621816,41.952389]},"n4489":{"id":"n4489","loc":[-85.6217,41.952386]},"n449":{"id":"n449","loc":[-85.634509,41.943427]},"n4490":{"id":"n4490","loc":[-85.621705,41.952306]},"n4491":{"id":"n4491","loc":[-85.621821,41.95231]},"n4492":{"id":"n4492","loc":[-85.621819,41.952272]},"n4493":{"id":"n4493","loc":[-85.621778,41.952272]},"n4494":{"id":"n4494","loc":[-85.621778,41.952199]},"n4495":{"id":"n4495","loc":[-85.621818,41.952199]},"n4496":{"id":"n4496","loc":[-85.621754,41.952281]},"n4497":{"id":"n4497","loc":[-85.621701,41.95228]},"n4498":{"id":"n4498","loc":[-85.621702,41.952197]},"n4499":{"id":"n4499","loc":[-85.621755,41.952197]},"n45":{"id":"n45","loc":[-85.636791,41.942792]},"n450":{"id":"n450","loc":[-85.63453,41.943365]},"n4500":{"id":"n4500","loc":[-85.628201,41.954694],"tags":{"highway":"stop","stop":"all"}},"n4501":{"id":"n4501","loc":[-85.627921,41.954783],"tags":{"highway":"stop","stop":"all"}},"n4502":{"id":"n4502","loc":[-85.62775,41.954696],"tags":{"highway":"stop","stop":"all"}},"n4503":{"id":"n4503","loc":[-85.628046,41.954591],"tags":{"highway":"stop","stop":"all"}},"n4504":{"id":"n4504","loc":[-85.631074,41.957428],"tags":{"highway":"stop"}},"n4505":{"id":"n4505","loc":[-85.630768,41.957429],"tags":{"highway":"stop"}},"n4506":{"id":"n4506","loc":[-85.629888,41.957432],"tags":{"highway":"stop"}},"n4507":{"id":"n4507","loc":[-85.629565,41.957433],"tags":{"highway":"stop"}},"n4508":{"id":"n4508","loc":[-85.629559,41.957343]},"n4509":{"id":"n4509","loc":[-85.628723,41.95735]},"n451":{"id":"n451","loc":[-85.634356,41.943468]},"n4510":{"id":"n4510","loc":[-85.62842,41.957515]},"n4511":{"id":"n4511","loc":[-85.627561,41.957525]},"n4512":{"id":"n4512","loc":[-85.630323,41.957508]},"n4513":{"id":"n4513","loc":[-85.630811,41.957506]},"n4514":{"id":"n4514","loc":[-85.630839,41.960874]},"n4515":{"id":"n4515","loc":[-85.631035,41.957506]},"n4516":{"id":"n4516","loc":[-85.632027,41.9575]},"n4517":{"id":"n4517","loc":[-85.631038,41.958066]},"n4518":{"id":"n4518","loc":[-85.630787,41.954769]},"n4519":{"id":"n4519","loc":[-85.630806,41.957342]},"n452":{"id":"n452","loc":[-85.634123,41.943596]},"n4520":{"id":"n4520","loc":[-85.630809,41.957428],"tags":{"highway":"crossing"}},"n4521":{"id":"n4521","loc":[-85.630912,41.957506],"tags":{"highway":"crossing"}},"n4522":{"id":"n4522","loc":[-85.631033,41.957428],"tags":{"highway":"crossing"}},"n4523":{"id":"n4523","loc":[-85.631032,41.957341]},"n4524":{"id":"n4524","loc":[-85.63091,41.957341],"tags":{"highway":"crossing"}},"n4525":{"id":"n4525","loc":[-85.631027,41.95597]},"n4526":{"id":"n4526","loc":[-85.631027,41.955913],"tags":{"highway":"crossing"}},"n4527":{"id":"n4527","loc":[-85.631025,41.955873]},"n4528":{"id":"n4528","loc":[-85.631073,41.955913],"tags":{"highway":"stop"}},"n4529":{"id":"n4529","loc":[-85.631007,41.954766]},"n453":{"id":"n453","loc":[-85.634709,41.943926]},"n4530":{"id":"n4530","loc":[-85.630881,41.954768],"tags":{"highway":"crossing"}},"n4531":{"id":"n4531","loc":[-85.628022,41.954776]},"n4532":{"id":"n4532","loc":[-85.627385,41.95584]},"n4533":{"id":"n4533","loc":[-85.627329,41.955937]},"n4534":{"id":"n4534","loc":[-85.626583,41.957153]},"n4535":{"id":"n4535","loc":[-85.629675,41.954564],"tags":{"highway":"stop"}},"n4536":{"id":"n4536","loc":[-85.630881,41.954806],"tags":{"highway":"stop"}},"n4537":{"id":"n4537","loc":[-85.630879,41.954564],"tags":{"highway":"stop"}},"n4538":{"id":"n4538","loc":[-85.630784,41.954682],"tags":{"highway":"crossing"}},"n4539":{"id":"n4539","loc":[-85.63078,41.954595]},"n454":{"id":"n454","loc":[-85.63525,41.943855]},"n4540":{"id":"n4540","loc":[-85.630879,41.954595],"tags":{"highway":"crossing"}},"n4541":{"id":"n4541","loc":[-85.631004,41.954594]},"n4542":{"id":"n4542","loc":[-85.631006,41.954681],"tags":{"highway":"crossing"}},"n4543":{"id":"n4543","loc":[-85.631045,41.959036],"tags":{"highway":"stop"}},"n4544":{"id":"n4544","loc":[-85.632071,41.959029],"tags":{"highway":"stop"}},"n4545":{"id":"n4545","loc":[-85.632257,41.959027],"tags":{"highway":"stop"}},"n4546":{"id":"n4546","loc":[-85.631966,41.957427],"tags":{"highway":"stop"}},"n4547":{"id":"n4547","loc":[-85.632297,41.957426],"tags":{"highway":"stop"}},"n4548":{"id":"n4548","loc":[-85.631976,41.955911],"tags":{"highway":"give_way"}},"n4549":{"id":"n4549","loc":[-85.632272,41.955911],"tags":{"highway":"give_way"}},"n455":{"id":"n455","loc":[-85.635224,41.943869]},"n4550":{"id":"n4550","loc":[-85.632097,41.954805],"tags":{"highway":"stop"}},"n4551":{"id":"n4551","loc":[-85.632094,41.954566],"tags":{"highway":"stop"}},"n4552":{"id":"n4552","loc":[-85.626519,41.957256]},"n4553":{"id":"n4553","loc":[-85.625334,41.959165]},"n4554":{"id":"n4554","loc":[-85.626483,41.95806]},"n4555":{"id":"n4555","loc":[-85.626481,41.958175]},"n4556":{"id":"n4556","loc":[-85.626412,41.958174]},"n4557":{"id":"n4557","loc":[-85.626412,41.958202]},"n4558":{"id":"n4558","loc":[-85.62628,41.958201]},"n4559":{"id":"n4559","loc":[-85.626283,41.958057]},"n456":{"id":"n456","loc":[-85.638854,41.943104]},"n4560":{"id":"n4560","loc":[-85.622763,41.95109],"tags":{"highway":"stop"}},"n4561":{"id":"n4561","loc":[-85.622858,41.950876],"tags":{"emergency":"fire_hydrant"}},"n4562":{"id":"n4562","loc":[-85.624073,41.950393]},"n4563":{"id":"n4563","loc":[-85.624077,41.950924]},"n4564":{"id":"n4564","loc":[-85.624599,41.950984],"tags":{"highway":"stop"}},"n4565":{"id":"n4565","loc":[-85.624831,41.95119],"tags":{"emergency":"fire_hydrant"}},"n4566":{"id":"n4566","loc":[-85.624437,41.952568],"tags":{"emergency":"fire_hydrant"}},"n4567":{"id":"n4567","loc":[-85.624077,41.954606],"tags":{"emergency":"fire_hydrant"}},"n4568":{"id":"n4568","loc":[-85.624263,41.954888]},"n4569":{"id":"n4569","loc":[-85.624206,41.954919]},"n457":{"id":"n457","loc":[-85.635186,41.943901]},"n4570":{"id":"n4570","loc":[-85.624154,41.954865]},"n4571":{"id":"n4571","loc":[-85.624212,41.954835]},"n4572":{"id":"n4572","loc":[-85.622442,41.954401],"tags":{"emergency":"fire_hydrant"}},"n4573":{"id":"n4573","loc":[-85.619751,41.954658],"tags":{"emergency":"fire_hydrant"}},"n4574":{"id":"n4574","loc":[-85.617785,41.954534]},"n4575":{"id":"n4575","loc":[-85.617416,41.954721]},"n4576":{"id":"n4576","loc":[-85.617662,41.95474]},"n4577":{"id":"n4577","loc":[-85.618014,41.954717]},"n4578":{"id":"n4578","loc":[-85.617886,41.954671]},"n4579":{"id":"n4579","loc":[-85.617831,41.954612]},"n458":{"id":"n458","loc":[-85.635162,41.943917]},"n4580":{"id":"n4580","loc":[-85.617968,41.954752]},"n4581":{"id":"n4581","loc":[-85.617815,41.954752]},"n4582":{"id":"n4582","loc":[-85.617938,41.954695]},"n4583":{"id":"n4583","loc":[-85.617856,41.954642],"tags":{"highway":"stop"}},"n4584":{"id":"n4584","loc":[-85.619116,41.954164],"tags":{"man_made":"flagpole"}},"n4585":{"id":"n4585","loc":[-85.619569,41.953255],"tags":{"emergency":"fire_hydrant"}},"n4586":{"id":"n4586","loc":[-85.620352,41.951894],"tags":{"highway":"stop"}},"n4587":{"id":"n4587","loc":[-85.620485,41.951948],"tags":{"emergency":"fire_hydrant"}},"n4588":{"id":"n4588","loc":[-85.620316,41.950999],"tags":{"highway":"stop"}},"n4589":{"id":"n4589","loc":[-85.620311,41.950131],"tags":{"highway":"stop"}},"n459":{"id":"n459","loc":[-85.634856,41.943905]},"n4590":{"id":"n4590","loc":[-85.620374,41.95018],"tags":{"emergency":"fire_hydrant"}},"n4591":{"id":"n4591","loc":[-85.620301,41.949239],"tags":{"highway":"stop"}},"n4592":{"id":"n4592","loc":[-85.620278,41.947443],"tags":{"highway":"stop"}},"n4593":{"id":"n4593","loc":[-85.619844,41.947444],"tags":{"highway":"stop"}},"n4594":{"id":"n4594","loc":[-85.620191,41.947352],"tags":{"emergency":"fire_hydrant"}},"n4595":{"id":"n4595","loc":[-85.622819,41.947493],"tags":{"emergency":"fire_hydrant"}},"n4596":{"id":"n4596","loc":[-85.622744,41.947541],"tags":{"highway":"stop"}},"n4597":{"id":"n4597","loc":[-85.622739,41.947316],"tags":{"highway":"stop"}},"n4598":{"id":"n4598","loc":[-85.622909,41.948333],"tags":{"highway":"give_way"}},"n4599":{"id":"n4599","loc":[-85.622593,41.948333],"tags":{"highway":"give_way"}},"n46":{"id":"n46","loc":[-85.637131,41.94307]},"n460":{"id":"n460","loc":[-85.634811,41.944007]},"n4600":{"id":"n4600","loc":[-85.622835,41.948387],"tags":{"emergency":"fire_hydrant"}},"n4601":{"id":"n4601","loc":[-85.622768,41.949125],"tags":{"highway":"stop"}},"n4602":{"id":"n4602","loc":[-85.622769,41.949325],"tags":{"highway":"stop"}},"n4603":{"id":"n4603","loc":[-85.622837,41.949329],"tags":{"emergency":"fire_hydrant"}},"n4604":{"id":"n4604","loc":[-85.622614,41.950113],"tags":{"highway":"give_way"}},"n4605":{"id":"n4605","loc":[-85.624777,41.949219],"tags":{"highway":"stop"}},"n4606":{"id":"n4606","loc":[-85.624849,41.949106],"tags":{"emergency":"fire_hydrant"}},"n4607":{"id":"n4607","loc":[-85.624858,41.950119],"tags":{"emergency":"fire_hydrant"}},"n4608":{"id":"n4608","loc":[-85.624752,41.948334],"tags":{"highway":"give_way"}},"n4609":{"id":"n4609","loc":[-85.624845,41.948422],"tags":{"emergency":"fire_hydrant"}},"n461":{"id":"n461","loc":[-85.634987,41.943112]},"n4610":{"id":"n4610","loc":[-85.62484,41.947539],"tags":{"emergency":"fire_hydrant"}},"n4611":{"id":"n4611","loc":[-85.62476,41.947428],"tags":{"highway":"stop"}},"n4612":{"id":"n4612","loc":[-85.620286,41.950926]},"n4613":{"id":"n4613","loc":[-85.618237,41.950963]},"n4614":{"id":"n4614","loc":[-85.618107,41.950876]},"n4615":{"id":"n4615","loc":[-85.618131,41.950393]},"n4616":{"id":"n4616","loc":[-85.61823,41.9499]},"n4617":{"id":"n4617","loc":[-85.619138,41.950212]},"n4618":{"id":"n4618","loc":[-85.619299,41.950388]},"n4619":{"id":"n4619","loc":[-85.619306,41.950897]},"n462":{"id":"n462","loc":[-85.634698,41.943194]},"n4620":{"id":"n4620","loc":[-85.619155,41.950958]},"n4621":{"id":"n4621","loc":[-85.620079,41.947715]},"n4622":{"id":"n4622","loc":[-85.619674,41.947728]},"n4623":{"id":"n4623","loc":[-85.619634,41.947735]},"n4624":{"id":"n4624","loc":[-85.619587,41.947756],"tags":{"barrier":"gate"}},"n4625":{"id":"n4625","loc":[-85.61953,41.947796]},"n4626":{"id":"n4626","loc":[-85.619475,41.947847]},"n4627":{"id":"n4627","loc":[-85.619433,41.947903]},"n4628":{"id":"n4628","loc":[-85.619402,41.947982]},"n4629":{"id":"n4629","loc":[-85.619394,41.948043]},"n463":{"id":"n463","loc":[-85.634632,41.943219]},"n4630":{"id":"n4630","loc":[-85.619395,41.948476]},"n4631":{"id":"n4631","loc":[-85.618367,41.947452]},"n4632":{"id":"n4632","loc":[-85.618371,41.947567],"tags":{"barrier":"gate"}},"n4633":{"id":"n4633","loc":[-85.618341,41.947622]},"n4634":{"id":"n4634","loc":[-85.618138,41.94773]},"n4635":{"id":"n4635","loc":[-85.618078,41.947814]},"n4636":{"id":"n4636","loc":[-85.618072,41.948009]},"n4637":{"id":"n4637","loc":[-85.618269,41.947666]},"n4638":{"id":"n4638","loc":[-85.618099,41.947765]},"n4639":{"id":"n4639","loc":[-85.618378,41.954453]},"n464":{"id":"n464","loc":[-85.63459,41.943239]},"n4640":{"id":"n4640","loc":[-85.618198,41.95453]},"n4641":{"id":"n4641","loc":[-85.618212,41.954623]},"n4642":{"id":"n4642","loc":[-85.635211,41.943103],"tags":{"leisure":"picnic_table"}},"n4643":{"id":"n4643","loc":[-85.635345,41.943448],"tags":{"leisure":"picnic_table"}},"n4644":{"id":"n4644","loc":[-85.635901,41.943353],"tags":{"amenity":"bench"}},"n4645":{"id":"n4645","loc":[-85.635815,41.942638],"tags":{"highway":"stop"}},"n4646":{"id":"n4646","loc":[-85.635355,41.942044],"tags":{"leisure":"picnic_table"}},"n4647":{"id":"n4647","loc":[-85.635206,41.942045],"tags":{"leisure":"picnic_table"}},"n4648":{"id":"n4648","loc":[-85.63504,41.941992],"tags":{"leisure":"picnic_table"}},"n4649":{"id":"n4649","loc":[-85.635185,41.942001]},"n465":{"id":"n465","loc":[-85.634555,41.943263]},"n4650":{"id":"n4650","loc":[-85.635176,41.942021]},"n4651":{"id":"n4651","loc":[-85.635127,41.942008]},"n4652":{"id":"n4652","loc":[-85.635136,41.941988]},"n4653":{"id":"n4653","loc":[-85.635,41.941709],"tags":{"emergency":"fire_hydrant"}},"n4654":{"id":"n4654","loc":[-85.634893,41.941801]},"n4655":{"id":"n4655","loc":[-85.634937,41.941843]},"n4656":{"id":"n4656","loc":[-85.634963,41.941859]},"n4657":{"id":"n4657","loc":[-85.635027,41.941904]},"n4658":{"id":"n4658","loc":[-85.63494,41.94187]},"n4659":{"id":"n4659","loc":[-85.634951,41.941871]},"n466":{"id":"n466","loc":[-85.634526,41.943289]},"n4660":{"id":"n4660","loc":[-85.634753,41.941701],"tags":{"amenity":"drinking_water"}},"n4661":{"id":"n4661","loc":[-85.634717,41.941804],"tags":{"amenity":"bench"}},"n4662":{"id":"n4662","loc":[-85.634554,41.941883],"tags":{"amenity":"bench"}},"n4663":{"id":"n4663","loc":[-85.635002,41.941579],"tags":{"amenity":"fountain"}},"n4664":{"id":"n4664","loc":[-85.635258,41.94188],"tags":{"amenity":"waste_basket"}},"n4665":{"id":"n4665","loc":[-85.635262,41.941581],"tags":{"amenity":"bench"}},"n4666":{"id":"n4666","loc":[-85.635319,41.941744],"tags":{"amenity":"bench"}},"n4667":{"id":"n4667","loc":[-85.634702,41.941473],"tags":{"amenity":"waste_basket"}},"n4668":{"id":"n4668","loc":[-85.633981,41.941966],"tags":{"amenity":"bench"}},"n4669":{"id":"n4669","loc":[-85.63388,41.941743]},"n467":{"id":"n467","loc":[-85.635163,41.944985]},"n4670":{"id":"n4670","loc":[-85.633746,41.941741]},"n4671":{"id":"n4671","loc":[-85.633749,41.941664]},"n4672":{"id":"n4672","loc":[-85.633883,41.941667]},"n4673":{"id":"n4673","loc":[-85.634283,41.941183],"tags":{"leisure":"picnic_table"}},"n4674":{"id":"n4674","loc":[-85.634046,41.941102],"tags":{"amenity":"bbq"}},"n4675":{"id":"n4675","loc":[-85.63401,41.941093],"tags":{"amenity":"bbq"}},"n4676":{"id":"n4676","loc":[-85.633408,41.940862],"tags":{"amenity":"bench"}},"n4677":{"id":"n4677","loc":[-85.633359,41.940651],"tags":{"amenity":"bench"}},"n4678":{"id":"n4678","loc":[-85.634109,41.940831]},"n4679":{"id":"n4679","loc":[-85.63396,41.940867]},"n468":{"id":"n468","loc":[-85.635095,41.945035]},"n4680":{"id":"n4680","loc":[-85.633816,41.940913]},"n4681":{"id":"n4681","loc":[-85.633237,41.940455]},"n4682":{"id":"n4682","loc":[-85.634453,41.940025],"tags":{"emergency":"fire_hydrant"}},"n4683":{"id":"n4683","loc":[-85.635692,41.940218],"tags":{"emergency":"fire_hydrant"}},"n4684":{"id":"n4684","loc":[-85.635566,41.940102],"tags":{"highway":"stop"}},"n4685":{"id":"n4685","loc":[-85.635961,41.940125],"tags":{"highway":"stop"}},"n4686":{"id":"n4686","loc":[-85.635883,41.94012],"tags":{"crossing":"zebra","highway":"crossing"}},"n4687":{"id":"n4687","loc":[-85.635883,41.94006]},"n4688":{"id":"n4688","loc":[-85.635768,41.940051],"tags":{"crossing":"zebra","highway":"crossing"}},"n4689":{"id":"n4689","loc":[-85.635669,41.940043]},"n469":{"id":"n469","loc":[-85.634269,41.944431]},"n4690":{"id":"n4690","loc":[-85.635661,41.940107],"tags":{"crossing":"zebra","highway":"crossing"}},"n4691":{"id":"n4691","loc":[-85.635424,41.941005],"tags":{"amenity":"fountain"}},"n4692":{"id":"n4692","loc":[-85.635542,41.941371],"tags":{"amenity":"bench"}},"n4693":{"id":"n4693","loc":[-85.635709,41.941341],"tags":{"emergency":"fire_hydrant"}},"n4694":{"id":"n4694","loc":[-85.637038,41.942513],"tags":{"highway":"stop"}},"n4695":{"id":"n4695","loc":[-85.637174,41.941354],"tags":{"highway":"stop"}},"n4696":{"id":"n4696","loc":[-85.637091,41.941273],"tags":{"emergency":"fire_hydrant"}},"n4697":{"id":"n4697","loc":[-85.638058,41.941346],"tags":{"highway":"give_way"}},"n4698":{"id":"n4698","loc":[-85.638359,41.941344],"tags":{"highway":"give_way"}},"n4699":{"id":"n4699","loc":[-85.638288,41.941236],"tags":{"emergency":"fire_hydrant"}},"n47":{"id":"n47","loc":[-85.636693,41.943073]},"n470":{"id":"n470","loc":[-85.634352,41.944376]},"n4700":{"id":"n4700","loc":[-85.63935,41.94128],"tags":{"emergency":"fire_hydrant"}},"n4701":{"id":"n4701","loc":[-85.639277,41.941337],"tags":{"highway":"give_way"}},"n4702":{"id":"n4702","loc":[-85.639548,41.941334],"tags":{"highway":"give_way"}},"n4703":{"id":"n4703","loc":[-85.642191,41.940039]},"n4704":{"id":"n4704","loc":[-85.640585,41.941263],"tags":{"emergency":"fire_hydrant"}},"n4705":{"id":"n4705","loc":[-85.64049,41.941327],"tags":{"highway":"stop"}},"n4706":{"id":"n4706","loc":[-85.640803,41.941324],"tags":{"highway":"stop"}},"n4707":{"id":"n4707","loc":[-85.641717,41.941317],"tags":{"highway":"stop"}},"n4708":{"id":"n4708","loc":[-85.641846,41.941415],"tags":{"highway":"stop"}},"n4709":{"id":"n4709","loc":[-85.641756,41.941392],"tags":{"emergency":"fire_hydrant"}},"n471":{"id":"n471","loc":[-85.634747,41.944561],"tags":{"railway":"crossing"}},"n4710":{"id":"n4710","loc":[-85.642014,41.941313],"tags":{"highway":"stop"}},"n4711":{"id":"n4711","loc":[-85.641854,41.942455],"tags":{"highway":"stop"}},"n4712":{"id":"n4712","loc":[-85.641859,41.942739],"tags":{"highway":"stop"}},"n4713":{"id":"n4713","loc":[-85.640754,41.942707],"tags":{"emergency":"fire_hydrant"}},"n4714":{"id":"n4714","loc":[-85.640669,41.942716],"tags":{"highway":"stop"}},"n4715":{"id":"n4715","loc":[-85.640664,41.942478],"tags":{"highway":"stop"}},"n4716":{"id":"n4716","loc":[-85.63964,41.94274],"tags":{"man_made":"flagpole"}},"n4717":{"id":"n4717","loc":[-85.639455,41.942731],"tags":{"highway":"stop"}},"n4718":{"id":"n4718","loc":[-85.63945,41.942492],"tags":{"highway":"stop"}},"n4719":{"id":"n4719","loc":[-85.639527,41.942505],"tags":{"emergency":"fire_hydrant"}},"n472":{"id":"n472","loc":[-85.634667,41.944613]},"n4720":{"id":"n4720","loc":[-85.638238,41.942745],"tags":{"highway":"stop"}},"n4721":{"id":"n4721","loc":[-85.638233,41.942511],"tags":{"highway":"stop"}},"n4722":{"id":"n4722","loc":[-85.638018,41.94299],"tags":{"amenity":"waste_disposal"}},"n4723":{"id":"n4723","loc":[-85.637918,41.944152],"tags":{"amenity":"waste_basket"}},"n4724":{"id":"n4724","loc":[-85.635902,41.943291],"tags":{"leisure":"picnic_table"}},"n4725":{"id":"n4725","loc":[-85.63704,41.942741],"tags":{"highway":"stop"}},"n4726":{"id":"n4726","loc":[-85.633467,41.943818],"tags":{"highway":"stop"}},"n4727":{"id":"n4727","loc":[-85.633987,41.943531],"tags":{"highway":"stop"}},"n4728":{"id":"n4728","loc":[-85.632154,41.943539],"tags":{"emergency":"fire_hydrant"}},"n4729":{"id":"n4729","loc":[-85.633567,41.944641],"tags":{"amenity":"bench"}},"n473":{"id":"n473","loc":[-85.634161,41.944371]},"n4730":{"id":"n4730","loc":[-85.633127,41.944574],"tags":{"amenity":"bench"}},"n4731":{"id":"n4731","loc":[-85.633439,41.944871],"tags":{"amenity":"bench"}},"n4732":{"id":"n4732","loc":[-85.633676,41.944799],"tags":{"amenity":"waste_basket"}},"n4733":{"id":"n4733","loc":[-85.633466,41.944862],"tags":{"amenity":"waste_basket"}},"n4734":{"id":"n4734","loc":[-85.633451,41.944847],"tags":{"emergency":"fire_hydrant"}},"n4735":{"id":"n4735","loc":[-85.634202,41.945543],"tags":{"amenity":"waste_basket"}},"n4736":{"id":"n4736","loc":[-85.634652,41.945472],"tags":{"leisure":"picnic_table"}},"n4737":{"id":"n4737","loc":[-85.6347,41.945445],"tags":{"leisure":"picnic_table"}},"n4738":{"id":"n4738","loc":[-85.634646,41.945662],"tags":{"emergency":"fire_hydrant"}},"n4739":{"id":"n4739","loc":[-85.634673,41.945687],"tags":{"amenity":"waste_basket"}},"n474":{"id":"n474","loc":[-85.633861,41.944117]},"n4740":{"id":"n4740","loc":[-85.63449,41.945827],"tags":{"amenity":"clock","display":"analog"}},"n4741":{"id":"n4741","loc":[-85.63481,41.946056],"tags":{"highway":"stop"}},"n4742":{"id":"n4742","loc":[-85.634814,41.946176],"tags":{"amenity":"post_box"}},"n4743":{"id":"n4743","loc":[-85.638744,41.945328]},"n4744":{"id":"n4744","loc":[-85.63867,41.945228],"tags":{"amenity":"bench"}},"n4745":{"id":"n4745","loc":[-85.639487,41.945042],"tags":{"highway":"stop"}},"n4746":{"id":"n4746","loc":[-85.639635,41.94387],"tags":{"highway":"stop"}},"n4747":{"id":"n4747","loc":[-85.639549,41.943756],"tags":{"emergency":"fire_hydrant"}},"n4748":{"id":"n4748","loc":[-85.64055,41.943862],"tags":{"highway":"stop"}},"n4749":{"id":"n4749","loc":[-85.640864,41.943859],"tags":{"highway":"stop"}},"n475":{"id":"n475","loc":[-85.633906,41.943535]},"n4750":{"id":"n4750","loc":[-85.640718,41.945022],"tags":{"highway":"stop"}},"n4751":{"id":"n4751","loc":[-85.640664,41.945076],"tags":{"emergency":"fire_hydrant"}},"n4752":{"id":"n4752","loc":[-85.641913,41.94502],"tags":{"highway":"stop"}},"n4753":{"id":"n4753","loc":[-85.641838,41.945076],"tags":{"emergency":"fire_hydrant"}},"n4754":{"id":"n4754","loc":[-85.642045,41.94385],"tags":{"highway":"give_way"}},"n4755":{"id":"n4755","loc":[-85.641738,41.943852],"tags":{"highway":"give_way"}},"n4756":{"id":"n4756","loc":[-85.642928,41.943843],"tags":{"highway":"stop"}},"n4757":{"id":"n4757","loc":[-85.64305,41.943902],"tags":{"emergency":"fire_hydrant"}},"n4758":{"id":"n4758","loc":[-85.642986,41.945105],"tags":{"highway":"stop"}},"n4759":{"id":"n4759","loc":[-85.643136,41.94502],"tags":{"highway":"stop"}},"n476":{"id":"n476","loc":[-85.63423,41.943692]},"n4760":{"id":"n4760","loc":[-85.63169,41.947812]},"n4761":{"id":"n4761","loc":[-85.631307,41.947655]},"n4762":{"id":"n4762","loc":[-85.631407,41.947413]},"n4763":{"id":"n4763","loc":[-85.631173,41.947306]},"n4764":{"id":"n4764","loc":[-85.631316,41.947145]},"n4765":{"id":"n4765","loc":[-85.631476,41.947087]},"n4766":{"id":"n4766","loc":[-85.631793,41.946871]},"n4767":{"id":"n4767","loc":[-85.631884,41.946723]},"n4768":{"id":"n4768","loc":[-85.631814,41.946397]},"n4769":{"id":"n4769","loc":[-85.631382,41.947685]},"n477":{"id":"n477","loc":[-85.635096,41.942814]},"n4770":{"id":"n4770","loc":[-85.63109,41.947819]},"n4771":{"id":"n4771","loc":[-85.630921,41.947961]},"n4772":{"id":"n4772","loc":[-85.630249,41.947709]},"n4773":{"id":"n4773","loc":[-85.630149,41.947451]},"n4774":{"id":"n4774","loc":[-85.629733,41.947339]},"n4775":{"id":"n4775","loc":[-85.629755,41.946948]},"n4776":{"id":"n4776","loc":[-85.630457,41.947103]},"n4777":{"id":"n4777","loc":[-85.630934,41.946939]},"n4778":{"id":"n4778","loc":[-85.631277,41.946852]},"n4779":{"id":"n4779","loc":[-85.63142,41.946781]},"n478":{"id":"n478","loc":[-85.635058,41.942795]},"n4780":{"id":"n4780","loc":[-85.631116,41.946474]},"n4781":{"id":"n4781","loc":[-85.63073,41.945965]},"n4782":{"id":"n4782","loc":[-85.631337,41.94571]},"n4783":{"id":"n4783","loc":[-85.631589,41.945487]},"n4784":{"id":"n4784","loc":[-85.632278,41.945784]},"n4785":{"id":"n4785","loc":[-85.632105,41.946034]},"n4786":{"id":"n4786","loc":[-85.632532,41.946198]},"n4787":{"id":"n4787","loc":[-85.632566,41.946151]},"n4788":{"id":"n4788","loc":[-85.632684,41.946196]},"n4789":{"id":"n4789","loc":[-85.628676,41.947106]},"n479":{"id":"n479","loc":[-85.635002,41.94279]},"n4790":{"id":"n4790","loc":[-85.628973,41.946476]},"n4791":{"id":"n4791","loc":[-85.629094,41.946079]},"n4792":{"id":"n4792","loc":[-85.629226,41.94578]},"n4793":{"id":"n4793","loc":[-85.629479,41.945682]},"n4794":{"id":"n4794","loc":[-85.630606,41.94569]},"n4795":{"id":"n4795","loc":[-85.631255,41.945588]},"n4796":{"id":"n4796","loc":[-85.631546,41.945281]},"n4797":{"id":"n4797","loc":[-85.631629,41.944823]},"n4798":{"id":"n4798","loc":[-85.631766,41.944958]},"n4799":{"id":"n4799","loc":[-85.631689,41.945318]},"n48":{"id":"n48","loc":[-85.636689,41.94276]},"n480":{"id":"n480","loc":[-85.634908,41.94279]},"n4800":{"id":"n4800","loc":[-85.615069,41.945527]},"n4801":{"id":"n4801","loc":[-85.615058,41.946677]},"n4802":{"id":"n4802","loc":[-85.613692,41.946689]},"n4803":{"id":"n4803","loc":[-85.613475,41.946531]},"n4804":{"id":"n4804","loc":[-85.611717,41.946252]},"n4805":{"id":"n4805","loc":[-85.611353,41.946385]},"n4806":{"id":"n4806","loc":[-85.611304,41.947397]},"n4807":{"id":"n4807","loc":[-85.610564,41.947401]},"n4808":{"id":"n4808","loc":[-85.610553,41.947122]},"n4809":{"id":"n4809","loc":[-85.610194,41.946992]},"n481":{"id":"n481","loc":[-85.634478,41.942342]},"n4810":{"id":"n4810","loc":[-85.609976,41.946628]},"n4811":{"id":"n4811","loc":[-85.609769,41.946523]},"n4812":{"id":"n4812","loc":[-85.609307,41.946523]},"n4813":{"id":"n4813","loc":[-85.609035,41.946462]},"n4814":{"id":"n4814","loc":[-85.609018,41.943277]},"n4815":{"id":"n4815","loc":[-85.609617,41.943423]},"n4816":{"id":"n4816","loc":[-85.610471,41.943447]},"n4817":{"id":"n4817","loc":[-85.621491,41.949168]},"n4818":{"id":"n4818","loc":[-85.620266,41.94917]},"n4819":{"id":"n4819","loc":[-85.620262,41.947557]},"n482":{"id":"n482","loc":[-85.634521,41.942254]},"n4820":{"id":"n4820","loc":[-85.620825,41.947556]},"n4821":{"id":"n4821","loc":[-85.620827,41.948371]},"n4822":{"id":"n4822","loc":[-85.621489,41.94837]},"n4823":{"id":"n4823","loc":[-85.622865,41.950928]},"n4824":{"id":"n4824","loc":[-85.622858,41.949744]},"n4825":{"id":"n4825","loc":[-85.623696,41.949714]},"n4826":{"id":"n4826","loc":[-85.623696,41.949647]},"n4827":{"id":"n4827","loc":[-85.624019,41.949647]},"n4828":{"id":"n4828","loc":[-85.624024,41.950093]},"n4829":{"id":"n4829","loc":[-85.622885,41.949711]},"n483":{"id":"n483","loc":[-85.63425,41.941819]},"n4830":{"id":"n4830","loc":[-85.624584,41.951049]},"n4831":{"id":"n4831","loc":[-85.624669,41.9511]},"n4832":{"id":"n4832","loc":[-85.624316,41.952218]},"n4833":{"id":"n4833","loc":[-85.623819,41.952094]},"n4834":{"id":"n4834","loc":[-85.623385,41.952101]},"n4835":{"id":"n4835","loc":[-85.623456,41.951238]},"n4836":{"id":"n4836","loc":[-85.623535,41.951051]},"n4837":{"id":"n4837","loc":[-85.624693,41.950921]},"n4838":{"id":"n4838","loc":[-85.624727,41.950897]},"n4839":{"id":"n4839","loc":[-85.624869,41.950341]},"n484":{"id":"n484","loc":[-85.634324,41.942131]},"n4840":{"id":"n4840","loc":[-85.624859,41.949284]},"n4841":{"id":"n4841","loc":[-85.624788,41.949262]},"n4842":{"id":"n4842","loc":[-85.62402,41.949265]},"n4843":{"id":"n4843","loc":[-85.610382,41.954663]},"n4844":{"id":"n4844","loc":[-85.605675,41.954667]},"n4845":{"id":"n4845","loc":[-85.605669,41.949407]},"n4846":{"id":"n4846","loc":[-85.610376,41.949404]},"n4847":{"id":"n4847","loc":[-85.605552,41.958536]},"n4848":{"id":"n4848","loc":[-85.595755,41.958588]},"n4849":{"id":"n4849","loc":[-85.595732,41.956419]},"n485":{"id":"n485","loc":[-85.634211,41.941374]},"n4850":{"id":"n4850","loc":[-85.596908,41.955605]},"n4851":{"id":"n4851","loc":[-85.597723,41.955596]},"n4852":{"id":"n4852","loc":[-85.597715,41.954967]},"n4853":{"id":"n4853","loc":[-85.5874,41.955018]},"n4854":{"id":"n4854","loc":[-85.586615,41.955124]},"n4855":{"id":"n4855","loc":[-85.58613,41.955293]},"n4856":{"id":"n4856","loc":[-85.586166,41.962122]},"n4857":{"id":"n4857","loc":[-85.587008,41.955052]},"n4858":{"id":"n4858","loc":[-85.591685,41.95499]},"n4859":{"id":"n4859","loc":[-85.591718,41.956649]},"n486":{"id":"n486","loc":[-85.634085,41.940704]},"n4860":{"id":"n4860","loc":[-85.591133,41.956649]},"n4861":{"id":"n4861","loc":[-85.591061,41.95582]},"n4862":{"id":"n4862","loc":[-85.590677,41.95613]},"n4863":{"id":"n4863","loc":[-85.590826,41.956369]},"n4864":{"id":"n4864","loc":[-85.591016,41.954991]},"n4865":{"id":"n4865","loc":[-85.587656,41.954855]},"n4866":{"id":"n4866","loc":[-85.5964,41.955274]},"n4867":{"id":"n4867","loc":[-85.58776,41.96178]},"n4868":{"id":"n4868","loc":[-85.601172,41.960448]},"n4869":{"id":"n4869","loc":[-85.589489,41.960478]},"n487":{"id":"n487","loc":[-85.635567,41.940944]},"n4870":{"id":"n4870","loc":[-85.586664,41.960493]},"n4871":{"id":"n4871","loc":[-85.591227,41.95676]},"n4872":{"id":"n4872","loc":[-85.589424,41.958093]},"n4873":{"id":"n4873","loc":[-85.588779,41.957611]},"n4874":{"id":"n4874","loc":[-85.590583,41.956278]},"n4875":{"id":"n4875","loc":[-85.590759,41.957106]},"n4876":{"id":"n4876","loc":[-85.592213,41.958218]},"n4877":{"id":"n4877","loc":[-85.592262,41.958279]},"n4878":{"id":"n4878","loc":[-85.592304,41.958358]},"n4879":{"id":"n4879","loc":[-85.592351,41.95849]},"n488":{"id":"n488","loc":[-85.635542,41.940919]},"n4880":{"id":"n4880","loc":[-85.592363,41.958605]},"n4881":{"id":"n4881","loc":[-85.592383,41.96047]},"n4882":{"id":"n4882","loc":[-85.592376,41.959808]},"n4883":{"id":"n4883","loc":[-85.600825,41.959779]},"n4884":{"id":"n4884","loc":[-85.601084,41.959844]},"n4885":{"id":"n4885","loc":[-85.601144,41.959908]},"n4886":{"id":"n4886","loc":[-85.601164,41.960008]},"n4887":{"id":"n4887","loc":[-85.601162,41.960125]},"n4888":{"id":"n4888","loc":[-85.601134,41.960221]},"n4889":{"id":"n4889","loc":[-85.600993,41.960353]},"n489":{"id":"n489","loc":[-85.635514,41.940906]},"n4890":{"id":"n4890","loc":[-85.600794,41.960449]},"n4891":{"id":"n4891","loc":[-85.60098,41.959792]},"n4892":{"id":"n4892","loc":[-85.601067,41.960294]},"n4893":{"id":"n4893","loc":[-85.596829,41.959793]},"n4894":{"id":"n4894","loc":[-85.596839,41.960459]},"n4895":{"id":"n4895","loc":[-85.589364,41.958048]},"n4896":{"id":"n4896","loc":[-85.587374,41.959511]},"n4897":{"id":"n4897","loc":[-85.587286,41.959564]},"n4898":{"id":"n4898","loc":[-85.587163,41.959632]},"n4899":{"id":"n4899","loc":[-85.586694,41.959865]},"n49":{"id":"n49","loc":[-85.637127,41.942757]},"n490":{"id":"n490","loc":[-85.635469,41.940896]},"n4900":{"id":"n4900","loc":[-85.586634,41.959921]},"n4901":{"id":"n4901","loc":[-85.586607,41.960001]},"n4902":{"id":"n4902","loc":[-85.586599,41.960099]},"n4903":{"id":"n4903","loc":[-85.586602,41.96034]},"n4904":{"id":"n4904","loc":[-85.586669,41.960439]},"n4905":{"id":"n4905","loc":[-85.586758,41.960493]},"n4906":{"id":"n4906","loc":[-85.586618,41.960391]},"n4907":{"id":"n4907","loc":[-85.591201,41.956352]},"n4908":{"id":"n4908","loc":[-85.59112,41.954843]},"n4909":{"id":"n4909","loc":[-85.591536,41.956349]},"n491":{"id":"n491","loc":[-85.635667,41.940826]},"n4910":{"id":"n4910","loc":[-85.590953,41.956354]},"n4911":{"id":"n4911","loc":[-85.591468,41.956406]},"n4912":{"id":"n4912","loc":[-85.591469,41.956478]},"n4913":{"id":"n4913","loc":[-85.591123,41.956481]},"n4914":{"id":"n4914","loc":[-85.591121,41.956409]},"n4915":{"id":"n4915","loc":[-85.590826,41.955954]},"n4916":{"id":"n4916","loc":[-85.590612,41.956115]},"n4917":{"id":"n4917","loc":[-85.590402,41.955962]},"n4918":{"id":"n4918","loc":[-85.590622,41.955804]},"n4919":{"id":"n4919","loc":[-85.59011,41.956502]},"n492":{"id":"n492","loc":[-85.636197,41.940599]},"n4920":{"id":"n4920","loc":[-85.589877,41.956668]},"n4921":{"id":"n4921","loc":[-85.589777,41.95659]},"n4922":{"id":"n4922","loc":[-85.59001,41.956424]},"n4923":{"id":"n4923","loc":[-85.589595,41.956427]},"n4924":{"id":"n4924","loc":[-85.589434,41.956549]},"n4925":{"id":"n4925","loc":[-85.589262,41.956424]},"n4926":{"id":"n4926","loc":[-85.589422,41.956302]},"n4927":{"id":"n4927","loc":[-85.589358,41.956286]},"n4928":{"id":"n4928","loc":[-85.5892,41.956408]},"n4929":{"id":"n4929","loc":[-85.589032,41.956288]},"n493":{"id":"n493","loc":[-85.6362,41.940686]},"n4930":{"id":"n4930","loc":[-85.58919,41.956166]},"n4931":{"id":"n4931","loc":[-85.589165,41.956132]},"n4932":{"id":"n4932","loc":[-85.589002,41.956253]},"n4933":{"id":"n4933","loc":[-85.588826,41.956122]},"n4934":{"id":"n4934","loc":[-85.588989,41.956001]},"n4935":{"id":"n4935","loc":[-85.588673,41.955757]},"n4936":{"id":"n4936","loc":[-85.588502,41.955882]},"n4937":{"id":"n4937","loc":[-85.588339,41.955759]},"n4938":{"id":"n4938","loc":[-85.58851,41.955633]},"n4939":{"id":"n4939","loc":[-85.590382,41.955892]},"n494":{"id":"n494","loc":[-85.635969,41.94069]},"n4940":{"id":"n4940","loc":[-85.589923,41.956231]},"n4941":{"id":"n4941","loc":[-85.58984,41.956168]},"n4942":{"id":"n4942","loc":[-85.5903,41.95583]},"n4943":{"id":"n4943","loc":[-85.589636,41.956038]},"n4944":{"id":"n4944","loc":[-85.589546,41.956105]},"n4945":{"id":"n4945","loc":[-85.589045,41.955729]},"n4946":{"id":"n4946","loc":[-85.589135,41.955662]},"n4947":{"id":"n4947","loc":[-85.590718,41.955293]},"n4948":{"id":"n4948","loc":[-85.590718,41.955374]},"n4949":{"id":"n4949","loc":[-85.589211,41.955369]},"n495":{"id":"n495","loc":[-85.635965,41.940561]},"n4950":{"id":"n4950","loc":[-85.589212,41.955287]},"n4951":{"id":"n4951","loc":[-85.589675,41.956817]},"n4952":{"id":"n4952","loc":[-85.58947,41.95697]},"n4953":{"id":"n4953","loc":[-85.589219,41.956784]},"n4954":{"id":"n4954","loc":[-85.589425,41.95663]},"n4955":{"id":"n4955","loc":[-85.589373,41.95702]},"n4956":{"id":"n4956","loc":[-85.589171,41.957172]},"n4957":{"id":"n4957","loc":[-85.588962,41.957019]},"n4958":{"id":"n4958","loc":[-85.589164,41.956867]},"n4959":{"id":"n4959","loc":[-85.588881,41.955006]},"n496":{"id":"n496","loc":[-85.636031,41.94056]},"n4960":{"id":"n4960","loc":[-85.588804,41.955006]},"n4961":{"id":"n4961","loc":[-85.604773,41.954521]},"n4962":{"id":"n4962","loc":[-85.601603,41.954527]},"n4963":{"id":"n4963","loc":[-85.600823,41.954169]},"n4964":{"id":"n4964","loc":[-85.600828,41.950191]},"n4965":{"id":"n4965","loc":[-85.601673,41.949457]},"n4966":{"id":"n4966","loc":[-85.604464,41.949488]},"n4967":{"id":"n4967","loc":[-85.60538,41.950212]},"n4968":{"id":"n4968","loc":[-85.605395,41.954108]},"n4969":{"id":"n4969","loc":[-85.604771,41.954109]},"n497":{"id":"n497","loc":[-85.636032,41.940602]},"n4970":{"id":"n4970","loc":[-85.600613,41.953916]},"n4971":{"id":"n4971","loc":[-85.599758,41.954649]},"n4972":{"id":"n4972","loc":[-85.591194,41.954663]},"n4973":{"id":"n4973","loc":[-85.591182,41.950465]},"n4974":{"id":"n4974","loc":[-85.591871,41.950464]},"n4975":{"id":"n4975","loc":[-85.591868,41.949209]},"n4976":{"id":"n4976","loc":[-85.592155,41.949209]},"n4977":{"id":"n4977","loc":[-85.592155,41.94848]},"n4978":{"id":"n4978","loc":[-85.600615,41.948482]},"n4979":{"id":"n4979","loc":[-85.605421,41.949378]},"n498":{"id":"n498","loc":[-85.635776,41.940583]},"n4980":{"id":"n4980","loc":[-85.600614,41.949373]},"n4981":{"id":"n4981","loc":[-85.601316,41.94849]},"n4982":{"id":"n4982","loc":[-85.601592,41.947641]},"n4983":{"id":"n4983","loc":[-85.60395,41.947618]},"n4984":{"id":"n4984","loc":[-85.603973,41.948114]},"n4985":{"id":"n4985","loc":[-85.605398,41.948103]},"n4986":{"id":"n4986","loc":[-85.614017,41.965566]},"n4987":{"id":"n4987","loc":[-85.605787,41.965619]},"n4988":{"id":"n4988","loc":[-85.60577,41.963821]},"n4989":{"id":"n4989","loc":[-85.612886,41.963808]},"n499":{"id":"n499","loc":[-85.63589,41.940578]},"n4990":{"id":"n4990","loc":[-85.613207,41.963705]},"n4991":{"id":"n4991","loc":[-85.613511,41.963525]},"n4992":{"id":"n4992","loc":[-85.613667,41.963305]},"n4993":{"id":"n4993","loc":[-85.613779,41.962983]},"n4994":{"id":"n4994","loc":[-85.613797,41.959709]},"n4995":{"id":"n4995","loc":[-85.613663,41.95936]},"n4996":{"id":"n4996","loc":[-85.61339,41.959064]},"n4997":{"id":"n4997","loc":[-85.610503,41.956898]},"n4998":{"id":"n4998","loc":[-85.610485,41.956595]},"n4999":{"id":"n4999","loc":[-85.613892,41.956621]},"n5":{"id":"n5","loc":[-85.622744,41.95268]},"n50":{"id":"n50","loc":[-85.636673,41.943143]},"n500":{"id":"n500","loc":[-85.636198,41.940578]},"n5000":{"id":"n5000","loc":[-85.613866,41.958574]},"n5001":{"id":"n5001","loc":[-85.615262,41.958561]},"n5002":{"id":"n5002","loc":[-85.615279,41.959541]},"n5003":{"id":"n5003","loc":[-85.615314,41.95597]},"n5004":{"id":"n5004","loc":[-85.613887,41.955988]},"n5005":{"id":"n5005","loc":[-85.613074,41.962244]},"n5006":{"id":"n5006","loc":[-85.611678,41.963354]},"n5007":{"id":"n5007","loc":[-85.611678,41.963487]},"n5008":{"id":"n5008","loc":[-85.606906,41.963502]},"n5009":{"id":"n5009","loc":[-85.605777,41.962657]},"n501":{"id":"n501","loc":[-85.636251,41.940584]},"n5010":{"id":"n5010","loc":[-85.605711,41.9599]},"n5011":{"id":"n5011","loc":[-85.608139,41.9585]},"n5012":{"id":"n5012","loc":[-85.60814,41.956306]},"n5013":{"id":"n5013","loc":[-85.608854,41.95581]},"n5014":{"id":"n5014","loc":[-85.610039,41.955883]},"n5015":{"id":"n5015","loc":[-85.610068,41.956754]},"n5016":{"id":"n5016","loc":[-85.613058,41.959411]},"n5017":{"id":"n5017","loc":[-85.610234,41.957068]},"n5018":{"id":"n5018","loc":[-85.609826,41.95581]},"n5019":{"id":"n5019","loc":[-85.606987,41.958505]},"n502":{"id":"n502","loc":[-85.636279,41.940605]},"n5020":{"id":"n5020","loc":[-85.606498,41.958846]},"n5021":{"id":"n5021","loc":[-85.606013,41.959342]},"n5022":{"id":"n5022","loc":[-85.614553,41.961581]},"n5023":{"id":"n5023","loc":[-85.61465,41.96214]},"n5024":{"id":"n5024","loc":[-85.615277,41.962442]},"n5025":{"id":"n5025","loc":[-85.615451,41.962972]},"n5026":{"id":"n5026","loc":[-85.614355,41.964826]},"n5027":{"id":"n5027","loc":[-85.615133,41.964589]},"n5028":{"id":"n5028","loc":[-85.615342,41.963818]},"n5029":{"id":"n5029","loc":[-85.615971,41.963792]},"n503":{"id":"n503","loc":[-85.636285,41.940633]},"n5030":{"id":"n5030","loc":[-85.615751,41.963122]},"n5031":{"id":"n5031","loc":[-85.616575,41.963123]},"n5032":{"id":"n5032","loc":[-85.612527,41.963846]},"n5033":{"id":"n5033","loc":[-85.630653,41.940709]},"n5034":{"id":"n5034","loc":[-85.629858,41.939568]},"n5035":{"id":"n5035","loc":[-85.629847,41.937926]},"n504":{"id":"n504","loc":[-85.636281,41.940662]},"n505":{"id":"n505","loc":[-85.636266,41.940688]},"n506":{"id":"n506","loc":[-85.636236,41.940701]},"n507":{"id":"n507","loc":[-85.63619,41.940706]},"n508":{"id":"n508","loc":[-85.635892,41.940707]},"n509":{"id":"n509","loc":[-85.635777,41.9407]},"n51":{"id":"n51","loc":[-85.636673,41.942864]},"n510":{"id":"n510","loc":[-85.636044,41.940578]},"n511":{"id":"n511","loc":[-85.635946,41.940578]},"n512":{"id":"n512","loc":[-85.636475,41.940732]},"n513":{"id":"n513","loc":[-85.636475,41.940777]},"n514":{"id":"n514","loc":[-85.636405,41.940777]},"n515":{"id":"n515","loc":[-85.636405,41.940732]},"n516":{"id":"n516","loc":[-85.636471,41.940916]},"n517":{"id":"n517","loc":[-85.636471,41.940961]},"n518":{"id":"n518","loc":[-85.636404,41.940961]},"n519":{"id":"n519","loc":[-85.636404,41.940916]},"n52":{"id":"n52","loc":[-85.636227,41.942864]},"n520":{"id":"n520","loc":[-85.636286,41.941127]},"n521":{"id":"n521","loc":[-85.636203,41.941126]},"n522":{"id":"n522","loc":[-85.636204,41.941083]},"n523":{"id":"n523","loc":[-85.636287,41.941083]},"n524":{"id":"n524","loc":[-85.636124,41.941064]},"n525":{"id":"n525","loc":[-85.636,41.941065]},"n526":{"id":"n526","loc":[-85.636,41.940964]},"n527":{"id":"n527","loc":[-85.636045,41.940964]},"n528":{"id":"n528","loc":[-85.636045,41.940928]},"n529":{"id":"n529","loc":[-85.636111,41.940928]},"n53":{"id":"n53","loc":[-85.636227,41.943143]},"n530":{"id":"n530","loc":[-85.636111,41.940961]},"n531":{"id":"n531","loc":[-85.636123,41.940961]},"n532":{"id":"n532","loc":[-85.636124,41.940997]},"n533":{"id":"n533","loc":[-85.636164,41.940997]},"n534":{"id":"n534","loc":[-85.636164,41.941044]},"n535":{"id":"n535","loc":[-85.636124,41.941044]},"n536":{"id":"n536","loc":[-85.636534,41.941256]},"n537":{"id":"n537","loc":[-85.63645,41.941246]},"n538":{"id":"n538","loc":[-85.636462,41.941189]},"n539":{"id":"n539","loc":[-85.636546,41.941199]},"n54":{"id":"n54","loc":[-85.636198,41.943119]},"n540":{"id":"n540","loc":[-85.636802,41.941226]},"n541":{"id":"n541","loc":[-85.636701,41.941215]},"n542":{"id":"n542","loc":[-85.636709,41.941174]},"n543":{"id":"n543","loc":[-85.636656,41.941168]},"n544":{"id":"n544","loc":[-85.636666,41.941122]},"n545":{"id":"n545","loc":[-85.636781,41.941136]},"n546":{"id":"n546","loc":[-85.636774,41.94117]},"n547":{"id":"n547","loc":[-85.636812,41.941175]},"n548":{"id":"n548","loc":[-85.636803,41.941047]},"n549":{"id":"n549","loc":[-85.636785,41.941047]},"n55":{"id":"n55","loc":[-85.635945,41.94312]},"n550":{"id":"n550","loc":[-85.636785,41.941058]},"n551":{"id":"n551","loc":[-85.636644,41.941059]},"n552":{"id":"n552","loc":[-85.636644,41.941038]},"n553":{"id":"n553","loc":[-85.636581,41.941039]},"n554":{"id":"n554","loc":[-85.636581,41.940995]},"n555":{"id":"n555","loc":[-85.636746,41.940995]},"n556":{"id":"n556","loc":[-85.636746,41.940978]},"n557":{"id":"n557","loc":[-85.636803,41.940978]},"n558":{"id":"n558","loc":[-85.636781,41.940768]},"n559":{"id":"n559","loc":[-85.636783,41.940828]},"n56":{"id":"n56","loc":[-85.635943,41.942909]},"n560":{"id":"n560","loc":[-85.636761,41.940828]},"n561":{"id":"n561","loc":[-85.636762,41.940857]},"n562":{"id":"n562","loc":[-85.636641,41.940859]},"n563":{"id":"n563","loc":[-85.63664,41.940805]},"n564":{"id":"n564","loc":[-85.636676,41.940804]},"n565":{"id":"n565","loc":[-85.636675,41.940769]},"n566":{"id":"n566","loc":[-85.636733,41.94033]},"n567":{"id":"n567","loc":[-85.636471,41.940334]},"n568":{"id":"n568","loc":[-85.636469,41.940262]},"n569":{"id":"n569","loc":[-85.636731,41.940257]},"n57":{"id":"n57","loc":[-85.636227,41.942909]},"n570":{"id":"n570","loc":[-85.636798,41.940419]},"n571":{"id":"n571","loc":[-85.6368,41.940524]},"n572":{"id":"n572","loc":[-85.63664,41.940526]},"n573":{"id":"n573","loc":[-85.636638,41.940421]},"n574":{"id":"n574","loc":[-85.636372,41.940551]},"n575":{"id":"n575","loc":[-85.636338,41.94055]},"n576":{"id":"n576","loc":[-85.636339,41.940524]},"n577":{"id":"n577","loc":[-85.636373,41.940525]},"n578":{"id":"n578","loc":[-85.636388,41.940435]},"n579":{"id":"n579","loc":[-85.636222,41.940436]},"n58":{"id":"n58","loc":[-85.63627,41.943175]},"n580":{"id":"n580","loc":[-85.636222,41.940366]},"n581":{"id":"n581","loc":[-85.636387,41.940365]},"n582":{"id":"n582","loc":[-85.636158,41.940482]},"n583":{"id":"n583","loc":[-85.635963,41.940484]},"n584":{"id":"n584","loc":[-85.635961,41.940399]},"n585":{"id":"n585","loc":[-85.636156,41.940397]},"n586":{"id":"n586","loc":[-85.635987,41.940314]},"n587":{"id":"n587","loc":[-85.635987,41.940268]},"n588":{"id":"n588","loc":[-85.635968,41.940268]},"n589":{"id":"n589","loc":[-85.635967,41.940212]},"n59":{"id":"n59","loc":[-85.635531,41.943176]},"n590":{"id":"n590","loc":[-85.636082,41.940211]},"n591":{"id":"n591","loc":[-85.636083,41.94027]},"n592":{"id":"n592","loc":[-85.636064,41.94027]},"n593":{"id":"n593","loc":[-85.636064,41.940313]},"n594":{"id":"n594","loc":[-85.638071,41.941562]},"n595":{"id":"n595","loc":[-85.637953,41.941562]},"n596":{"id":"n596","loc":[-85.637952,41.941522]},"n597":{"id":"n597","loc":[-85.637876,41.941523]},"n598":{"id":"n598","loc":[-85.637876,41.941471]},"n599":{"id":"n599","loc":[-85.638035,41.94147]},"n6":{"id":"n6","loc":[-85.624925,41.950604]},"n60":{"id":"n60","loc":[-85.63542,41.942883]},"n600":{"id":"n600","loc":[-85.638035,41.941513]},"n601":{"id":"n601","loc":[-85.638071,41.941512]},"n602":{"id":"n602","loc":[-85.637038,41.942543],"tags":{"crossing":"zebra","highway":"crossing"}},"n603":{"id":"n603","loc":[-85.637134,41.942542]},"n604":{"id":"n604","loc":[-85.638122,41.942532]},"n605":{"id":"n605","loc":[-85.638121,41.942478]},"n606":{"id":"n606","loc":[-85.638104,41.941424]},"n607":{"id":"n607","loc":[-85.637115,41.941438]},"n608":{"id":"n608","loc":[-85.637133,41.942453]},"n609":{"id":"n609","loc":[-85.637429,41.942004]},"n61":{"id":"n61","loc":[-85.635701,41.942802]},"n610":{"id":"n610","loc":[-85.637125,41.942004]},"n611":{"id":"n611","loc":[-85.637022,41.942004]},"n612":{"id":"n612","loc":[-85.635952,41.943579]},"n613":{"id":"n613","loc":[-85.635872,41.943594]},"n614":{"id":"n614","loc":[-85.635857,41.943551]},"n615":{"id":"n615","loc":[-85.635937,41.943535]},"n616":{"id":"n616","loc":[-85.63671,41.94344]},"n617":{"id":"n617","loc":[-85.636427,41.94334]},"n618":{"id":"n618","loc":[-85.635353,41.943279]},"n619":{"id":"n619","loc":[-85.635319,41.943257]},"n62":{"id":"n62","loc":[-85.6358,41.942997]},"n620":{"id":"n620","loc":[-85.638786,41.943105]},"n621":{"id":"n621","loc":[-85.634957,41.943146]},"n622":{"id":"n622","loc":[-85.635012,41.943119]},"n623":{"id":"n623","loc":[-85.632409,41.944222]},"n624":{"id":"n624","loc":[-85.631863,41.944749]},"n625":{"id":"n625","loc":[-85.631915,41.944722]},"n626":{"id":"n626","loc":[-85.631884,41.94464]},"n627":{"id":"n627","loc":[-85.631792,41.944359]},"n628":{"id":"n628","loc":[-85.631817,41.944703]},"n629":{"id":"n629","loc":[-85.633464,41.945787]},"n63":{"id":"n63","loc":[-85.635808,41.943176]},"n630":{"id":"n630","loc":[-85.633583,41.945919]},"n631":{"id":"n631","loc":[-85.63382,41.945698]},"n632":{"id":"n632","loc":[-85.633681,41.945571]},"n633":{"id":"n633","loc":[-85.634217,41.946824]},"n634":{"id":"n634","loc":[-85.634271,41.946836]},"n635":{"id":"n635","loc":[-85.634319,41.94573]},"n636":{"id":"n636","loc":[-85.634377,41.945672]},"n637":{"id":"n637","loc":[-85.634909,41.945354]},"n638":{"id":"n638","loc":[-85.634726,41.945493],"tags":{"artwork_type":"mural","tourism":"artwork"}},"n639":{"id":"n639","loc":[-85.63546,41.945612]},"n64":{"id":"n64","loc":[-85.63631,41.943253]},"n640":{"id":"n640","loc":[-85.635561,41.945493]},"n641":{"id":"n641","loc":[-85.635417,41.945565]},"n642":{"id":"n642","loc":[-85.635315,41.945583]},"n643":{"id":"n643","loc":[-85.63506,41.945383]},"n644":{"id":"n644","loc":[-85.635198,41.945199]},"n645":{"id":"n645","loc":[-85.635361,41.94558]},"n646":{"id":"n646","loc":[-85.635017,41.945066]},"n647":{"id":"n647","loc":[-85.634779,41.945206]},"n648":{"id":"n648","loc":[-85.63425,41.945655]},"n649":{"id":"n649","loc":[-85.634247,41.945631]},"n65":{"id":"n65","loc":[-85.635398,41.943259]},"n650":{"id":"n650","loc":[-85.634889,41.945921]},"n651":{"id":"n651","loc":[-85.634889,41.945939]},"n652":{"id":"n652","loc":[-85.634889,41.945761]},"n653":{"id":"n653","loc":[-85.634889,41.945778]},"n654":{"id":"n654","loc":[-85.635112,41.945715]},"n655":{"id":"n655","loc":[-85.635025,41.945714]},"n656":{"id":"n656","loc":[-85.635027,41.945761]},"n657":{"id":"n657","loc":[-85.635438,41.945665]},"n658":{"id":"n658","loc":[-85.635416,41.945676]},"n659":{"id":"n659","loc":[-85.635401,41.945709]},"n66":{"id":"n66","loc":[-85.635336,41.943036]},"n660":{"id":"n660","loc":[-85.635271,41.945566]},"n661":{"id":"n661","loc":[-85.636106,41.946268]},"n662":{"id":"n662","loc":[-85.635867,41.946747]},"n663":{"id":"n663","loc":[-85.636476,41.946797]},"n664":{"id":"n664","loc":[-85.63651,41.946796]},"n665":{"id":"n665","loc":[-85.635367,41.946389]},"n666":{"id":"n666","loc":[-85.635367,41.946437]},"n667":{"id":"n667","loc":[-85.634787,41.946441]},"n668":{"id":"n668","loc":[-85.6358,41.946243]},"n669":{"id":"n669","loc":[-85.635784,41.94622]},"n67":{"id":"n67","loc":[-85.635911,41.942899]},"n670":{"id":"n670","loc":[-85.635727,41.946195]},"n671":{"id":"n671","loc":[-85.635708,41.946588]},"n672":{"id":"n672","loc":[-85.635648,41.946561]},"n673":{"id":"n673","loc":[-85.635624,41.946555]},"n674":{"id":"n674","loc":[-85.635417,41.946559]},"n675":{"id":"n675","loc":[-85.634866,41.946561]},"n676":{"id":"n676","loc":[-85.634866,41.946543]},"n677":{"id":"n677","loc":[-85.635085,41.946546]},"n678":{"id":"n678","loc":[-85.635085,41.946554]},"n679":{"id":"n679","loc":[-85.634584,41.94488]},"n68":{"id":"n68","loc":[-85.635915,41.943156]},"n680":{"id":"n680","loc":[-85.634557,41.944882]},"n681":{"id":"n681","loc":[-85.634455,41.944943]},"n682":{"id":"n682","loc":[-85.634305,41.944968]},"n683":{"id":"n683","loc":[-85.634261,41.944927]},"n684":{"id":"n684","loc":[-85.634132,41.944741]},"n685":{"id":"n685","loc":[-85.633705,41.944759]},"n686":{"id":"n686","loc":[-85.633918,41.944616]},"n687":{"id":"n687","loc":[-85.633974,41.944663]},"n688":{"id":"n688","loc":[-85.6336,41.944665]},"n689":{"id":"n689","loc":[-85.633817,41.944528]},"n69":{"id":"n69","loc":[-85.63631,41.943157]},"n690":{"id":"n690","loc":[-85.633889,41.944485]},"n691":{"id":"n691","loc":[-85.633931,41.944525]},"n692":{"id":"n692","loc":[-85.633864,41.944563]},"n693":{"id":"n693","loc":[-85.633456,41.944524]},"n694":{"id":"n694","loc":[-85.633676,41.944399]},"n695":{"id":"n695","loc":[-85.633352,41.944415]},"n696":{"id":"n696","loc":[-85.633655,41.944234]},"n697":{"id":"n697","loc":[-85.633761,41.94435]},"n698":{"id":"n698","loc":[-85.633254,41.944318]},"n699":{"id":"n699","loc":[-85.633472,41.944188]},"n7":{"id":"n7","loc":[-85.638791,41.943231]},"n70":{"id":"n70","loc":[-85.63579,41.942967]},"n700":{"id":"n700","loc":[-85.633524,41.944237]},"n701":{"id":"n701","loc":[-85.633583,41.944202]},"n702":{"id":"n702","loc":[-85.633632,41.944247]},"n703":{"id":"n703","loc":[-85.633165,41.944228]},"n704":{"id":"n704","loc":[-85.633388,41.944105]},"n705":{"id":"n705","loc":[-85.633117,41.944175]},"n706":{"id":"n706","loc":[-85.633302,41.944077]},"n707":{"id":"n707","loc":[-85.633352,41.944126]},"n708":{"id":"n708","loc":[-85.633052,41.944107]},"n709":{"id":"n709","loc":[-85.633237,41.944009]},"n71":{"id":"n71","loc":[-85.637506,41.942824]},"n710":{"id":"n710","loc":[-85.633187,41.943955]},"n711":{"id":"n711","loc":[-85.633,41.944054]},"n712":{"id":"n712","loc":[-85.633155,41.944265]},"n713":{"id":"n713","loc":[-85.633669,41.944765]},"n714":{"id":"n714","loc":[-85.634468,41.945503]},"n715":{"id":"n715","loc":[-85.63455,41.945566]},"n716":{"id":"n716","loc":[-85.634737,41.945729]},"n717":{"id":"n717","loc":[-85.634753,41.945752]},"n718":{"id":"n718","loc":[-85.634756,41.945781]},"n719":{"id":"n719","loc":[-85.634758,41.945978]},"n72":{"id":"n72","loc":[-85.637511,41.943056]},"n720":{"id":"n720","loc":[-85.634363,41.945548],"tags":{"crossing":"zebra","highway":"crossing"}},"n721":{"id":"n721","loc":[-85.634245,41.945599]},"n722":{"id":"n722","loc":[-85.633474,41.944889]},"n723":{"id":"n723","loc":[-85.632997,41.944418]},"n724":{"id":"n724","loc":[-85.63278,41.944183]},"n725":{"id":"n725","loc":[-85.63331,41.944429]},"n726":{"id":"n726","loc":[-85.633568,41.944829],"tags":{"crossing":"zebra","highway":"crossing"}},"n727":{"id":"n727","loc":[-85.634669,41.94567]},"n728":{"id":"n728","loc":[-85.634462,41.945787]},"n729":{"id":"n729","loc":[-85.634272,41.945625]},"n73":{"id":"n73","loc":[-85.637361,41.943058]},"n730":{"id":"n730","loc":[-85.634344,41.945699],"tags":{"crossing":"zebra","highway":"crossing"}},"n731":{"id":"n731","loc":[-85.634426,41.945783]},"n732":{"id":"n732","loc":[-85.632425,41.944137]},"n733":{"id":"n733","loc":[-85.632302,41.944192]},"n734":{"id":"n734","loc":[-85.632762,41.944174]},"n735":{"id":"n735","loc":[-85.632713,41.944179]},"n736":{"id":"n736","loc":[-85.632411,41.944327]},"n737":{"id":"n737","loc":[-85.632362,41.944341]},"n738":{"id":"n738","loc":[-85.632236,41.944204]},"n739":{"id":"n739","loc":[-85.634939,41.942165]},"n74":{"id":"n74","loc":[-85.637356,41.942825]},"n740":{"id":"n740","loc":[-85.635079,41.941535]},"n741":{"id":"n741","loc":[-85.635112,41.941595]},"n742":{"id":"n742","loc":[-85.635113,41.941633]},"n743":{"id":"n743","loc":[-85.635067,41.941652]},"n744":{"id":"n744","loc":[-85.634989,41.941651]},"n745":{"id":"n745","loc":[-85.634921,41.941609]},"n746":{"id":"n746","loc":[-85.634881,41.941544]},"n747":{"id":"n747","loc":[-85.635537,41.940939]},"n748":{"id":"n748","loc":[-85.635573,41.941048]},"n749":{"id":"n749","loc":[-85.635453,41.94091]},"n75":{"id":"n75","loc":[-85.638097,41.942833]},"n750":{"id":"n750","loc":[-85.635319,41.940943]},"n751":{"id":"n751","loc":[-85.637057,41.943224]},"n752":{"id":"n752","loc":[-85.636989,41.943296]},"n753":{"id":"n753","loc":[-85.636851,41.943299]},"n754":{"id":"n754","loc":[-85.636848,41.94322]},"n755":{"id":"n755","loc":[-85.636986,41.943217]},"n756":{"id":"n756","loc":[-85.637569,41.943454]},"n757":{"id":"n757","loc":[-85.637437,41.943458]},"n758":{"id":"n758","loc":[-85.637432,41.943384]},"n759":{"id":"n759","loc":[-85.637564,41.94338]},"n76":{"id":"n76","loc":[-85.638098,41.942912]},"n760":{"id":"n760","loc":[-85.637213,41.943378]},"n761":{"id":"n761","loc":[-85.637217,41.943435]},"n762":{"id":"n762","loc":[-85.637235,41.943434]},"n763":{"id":"n763","loc":[-85.637237,41.943465]},"n764":{"id":"n764","loc":[-85.637424,41.943459]},"n765":{"id":"n765","loc":[-85.637418,41.943371]},"n766":{"id":"n766","loc":[-85.638094,41.943149]},"n767":{"id":"n767","loc":[-85.638096,41.943201]},"n768":{"id":"n768","loc":[-85.638041,41.943202]},"n769":{"id":"n769","loc":[-85.638042,41.943216]},"n77":{"id":"n77","loc":[-85.637705,41.942913]},"n770":{"id":"n770","loc":[-85.637927,41.943218]},"n771":{"id":"n771","loc":[-85.637926,41.943201]},"n772":{"id":"n772","loc":[-85.637897,41.943201]},"n773":{"id":"n773","loc":[-85.637896,41.943155]},"n774":{"id":"n774","loc":[-85.637962,41.943153]},"n775":{"id":"n775","loc":[-85.637962,41.943134]},"n776":{"id":"n776","loc":[-85.638017,41.943132]},"n777":{"id":"n777","loc":[-85.638018,41.943151]},"n778":{"id":"n778","loc":[-85.638045,41.943289]},"n779":{"id":"n779","loc":[-85.638048,41.943363]},"n78":{"id":"n78","loc":[-85.637705,41.942834]},"n780":{"id":"n780","loc":[-85.637842,41.943367]},"n781":{"id":"n781","loc":[-85.637839,41.943296]},"n782":{"id":"n782","loc":[-85.637896,41.943295]},"n783":{"id":"n783","loc":[-85.637897,41.943314]},"n784":{"id":"n784","loc":[-85.637957,41.943312]},"n785":{"id":"n785","loc":[-85.637957,41.943291]},"n786":{"id":"n786","loc":[-85.637816,41.943375]},"n787":{"id":"n787","loc":[-85.637815,41.943416]},"n788":{"id":"n788","loc":[-85.637715,41.943415]},"n789":{"id":"n789","loc":[-85.637716,41.943374]},"n79":{"id":"n79","loc":[-85.638071,41.942298]},"n790":{"id":"n790","loc":[-85.637912,41.943545]},"n791":{"id":"n791","loc":[-85.637909,41.943479]},"n792":{"id":"n792","loc":[-85.637967,41.943477]},"n793":{"id":"n793","loc":[-85.637967,41.94346]},"n794":{"id":"n794","loc":[-85.638077,41.943457]},"n795":{"id":"n795","loc":[-85.638078,41.943473]},"n796":{"id":"n796","loc":[-85.638124,41.943471]},"n797":{"id":"n797","loc":[-85.638126,41.943514]},"n798":{"id":"n798","loc":[-85.638079,41.943515]},"n799":{"id":"n799","loc":[-85.638079,41.943532]},"n8":{"id":"n8","loc":[-85.635241,41.941948]},"n80":{"id":"n80","loc":[-85.638074,41.942431]},"n800":{"id":"n800","loc":[-85.638028,41.943534]},"n801":{"id":"n801","loc":[-85.638028,41.943542]},"n802":{"id":"n802","loc":[-85.638845,41.942983]},"n803":{"id":"n803","loc":[-85.638846,41.94305]},"n804":{"id":"n804","loc":[-85.638661,41.943052]},"n805":{"id":"n805","loc":[-85.63866,41.942984]},"n806":{"id":"n806","loc":[-85.638579,41.942753]},"n807":{"id":"n807","loc":[-85.638445,41.942755]},"n808":{"id":"n808","loc":[-85.638452,41.942978]},"n809":{"id":"n809","loc":[-85.638545,41.942976]},"n81":{"id":"n81","loc":[-85.637836,41.942433]},"n810":{"id":"n810","loc":[-85.638543,41.942935]},"n811":{"id":"n811","loc":[-85.638571,41.942934]},"n812":{"id":"n812","loc":[-85.63857,41.942901]},"n813":{"id":"n813","loc":[-85.638611,41.9429]},"n814":{"id":"n814","loc":[-85.638607,41.942769]},"n815":{"id":"n815","loc":[-85.63858,41.94277]},"n816":{"id":"n816","loc":[-85.638597,41.942614]},"n817":{"id":"n817","loc":[-85.638601,41.94273]},"n818":{"id":"n818","loc":[-85.638686,41.942731]},"n819":{"id":"n819","loc":[-85.638689,41.942917]},"n82":{"id":"n82","loc":[-85.637835,41.94242]},"n820":{"id":"n820","loc":[-85.638558,41.943018]},"n821":{"id":"n821","loc":[-85.638243,41.943019]},"n822":{"id":"n822","loc":[-85.637536,41.943887]},"n823":{"id":"n823","loc":[-85.63749,41.943926]},"n824":{"id":"n824","loc":[-85.63743,41.943886]},"n825":{"id":"n825","loc":[-85.637476,41.943847]},"n826":{"id":"n826","loc":[-85.637527,41.943846]},"n827":{"id":"n827","loc":[-85.637141,41.943728]},"n828":{"id":"n828","loc":[-85.637201,41.943755]},"n829":{"id":"n829","loc":[-85.636987,41.943608]},"n83":{"id":"n83","loc":[-85.63776,41.942421]},"n830":{"id":"n830","loc":[-85.637441,41.943807]},"n831":{"id":"n831","loc":[-85.637673,41.94399]},"n832":{"id":"n832","loc":[-85.637783,41.944137]},"n833":{"id":"n833","loc":[-85.63845,41.944333]},"n834":{"id":"n834","loc":[-85.638159,41.944248]},"n835":{"id":"n835","loc":[-85.637859,41.94416]},"n836":{"id":"n836","loc":[-85.638685,41.944542]},"n837":{"id":"n837","loc":[-85.638714,41.944611]},"n838":{"id":"n838","loc":[-85.638711,41.944757]},"n839":{"id":"n839","loc":[-85.638774,41.945069]},"n84":{"id":"n84","loc":[-85.637758,41.942339]},"n840":{"id":"n840","loc":[-85.638742,41.945205]},"n841":{"id":"n841","loc":[-85.640267,41.942403]},"n842":{"id":"n842","loc":[-85.640154,41.942404]},"n843":{"id":"n843","loc":[-85.640152,41.942249]},"n844":{"id":"n844","loc":[-85.640266,41.942248]},"n845":{"id":"n845","loc":[-85.640366,41.942599]},"n846":{"id":"n846","loc":[-85.640362,41.942192]},"n847":{"id":"n847","loc":[-85.640146,41.942191]},"n848":{"id":"n848","loc":[-85.640122,41.942196]},"n849":{"id":"n849","loc":[-85.640108,41.942211]},"n85":{"id":"n85","loc":[-85.637836,41.942339]},"n850":{"id":"n850","loc":[-85.640101,41.942236]},"n851":{"id":"n851","loc":[-85.640103,41.94241]},"n852":{"id":"n852","loc":[-85.64011,41.942435]},"n853":{"id":"n853","loc":[-85.640126,41.942445]},"n854":{"id":"n854","loc":[-85.640153,41.942451]},"n855":{"id":"n855","loc":[-85.640183,41.942452]},"n856":{"id":"n856","loc":[-85.640364,41.942452]},"n857":{"id":"n857","loc":[-85.640007,41.942452]},"n858":{"id":"n858","loc":[-85.639449,41.942461]},"n859":{"id":"n859","loc":[-85.640049,41.942391]},"n86":{"id":"n86","loc":[-85.637835,41.942301]},"n860":{"id":"n860","loc":[-85.640052,41.942503]},"n861":{"id":"n861","loc":[-85.639575,41.94251]},"n862":{"id":"n862","loc":[-85.639572,41.942398]},"n863":{"id":"n863","loc":[-85.638782,41.942227]},"n864":{"id":"n864","loc":[-85.63843,41.942226]},"n865":{"id":"n865","loc":[-85.63823,41.942183]},"n866":{"id":"n866","loc":[-85.638363,41.942216],"tags":{"barrier":"gate"}},"n867":{"id":"n867","loc":[-85.6384,41.942223]},"n868":{"id":"n868","loc":[-85.636042,41.942797]},"n869":{"id":"n869","loc":[-85.636308,41.942752]},"n87":{"id":"n87","loc":[-85.637566,41.942367]},"n870":{"id":"n870","loc":[-85.636516,41.942729]},"n871":{"id":"n871","loc":[-85.636782,41.942712]},"n872":{"id":"n872","loc":[-85.636944,41.942706]},"n873":{"id":"n873","loc":[-85.63704,41.942706]},"n874":{"id":"n874","loc":[-85.637237,41.942703]},"n875":{"id":"n875","loc":[-85.637553,41.9427]},"n876":{"id":"n876","loc":[-85.638236,41.942697]},"n877":{"id":"n877","loc":[-85.636284,41.942781]},"n878":{"id":"n878","loc":[-85.636551,41.942641]},"n879":{"id":"n879","loc":[-85.633914,41.943693]},"n88":{"id":"n88","loc":[-85.637566,41.94241]},"n880":{"id":"n880","loc":[-85.63389,41.943708]},"n881":{"id":"n881","loc":[-85.633866,41.943686]},"n882":{"id":"n882","loc":[-85.63389,41.943671]},"n883":{"id":"n883","loc":[-85.633857,41.943609]},"n884":{"id":"n884","loc":[-85.634858,41.944474]},"n885":{"id":"n885","loc":[-85.633988,41.943234]},"n886":{"id":"n886","loc":[-85.633999,41.943485]},"n887":{"id":"n887","loc":[-85.634109,41.943449],"tags":{"emergency":"fire_hydrant"}},"n888":{"id":"n888","loc":[-85.635728,41.942655],"tags":{"emergency":"fire_hydrant"}},"n889":{"id":"n889","loc":[-85.636499,41.942845],"tags":{"man_made":"flagpole"}},"n89":{"id":"n89","loc":[-85.637455,41.94241]},"n890":{"id":"n890","loc":[-85.636197,41.943073]},"n891":{"id":"n891","loc":[-85.636227,41.943073]},"n892":{"id":"n892","loc":[-85.637433,41.942933],"tags":{"addr:city":"Three Rivers","addr:housenumber":"401","addr:postcode":"49093","addr:state":"MI","addr:street":"Michigan Avenue","amenity":"restaurant","cuisine":"pizza","name":"Pizza Hut"}},"n893":{"id":"n893","loc":[-85.637907,41.942879],"tags":{"amenity":"car_wash"}},"n894":{"id":"n894","loc":[-85.637661,41.943018]},"n895":{"id":"n895","loc":[-85.636933,41.942733],"tags":{"emergency":"fire_hydrant"}},"n896":{"id":"n896","loc":[-85.637661,41.94304]},"n897":{"id":"n897","loc":[-85.637562,41.943041]},"n898":{"id":"n898","loc":[-85.637556,41.942725]},"n899":{"id":"n899","loc":[-85.637656,41.942724]},"n9":{"id":"n9","loc":[-85.635159,41.941926]},"n90":{"id":"n90","loc":[-85.637454,41.942367]},"n900":{"id":"n900","loc":[-85.637657,41.942779]},"n901":{"id":"n901","loc":[-85.637983,41.942777]},"n902":{"id":"n902","loc":[-85.637982,41.942616]},"n903":{"id":"n903","loc":[-85.637777,41.942778]},"n904":{"id":"n904","loc":[-85.637775,41.942699]},"n905":{"id":"n905","loc":[-85.637772,41.942618]},"n906":{"id":"n906","loc":[-85.637982,41.942698]},"n907":{"id":"n907","loc":[-85.637941,41.942378],"tags":{"addr:city":"Three Rivers","addr:housenumber":"416","addr:postcode":"49093","addr:state":"MI","addr:street":"Michigan Avenue","name":"Gem Pawnbroker","shop":"pawnbroker"}},"n908":{"id":"n908","loc":[-85.637515,41.942394],"tags":{"second_hand":"only","shop":"car"}},"n909":{"id":"n909","loc":[-85.638743,41.942374],"tags":{"addr:city":"Three Rivers","addr:housenumber":"500","addr:postcode":"49093","addr:state":"MI","addr:street":"Michigan Avenue","name":"William Towing","service:vehicle:towing":"yes","service:vehicle:tyres":"yes","shop":"car_repair"}},"n91":{"id":"n91","loc":[-85.637565,41.942341]},"n910":{"id":"n910","loc":[-85.638594,41.942357]},"n911":{"id":"n911","loc":[-85.634312,41.943562],"tags":{"addr:city":"Three Rivers","addr:housenumber":"145","addr:postcode":"49093","addr:state":"MI","addr:street":"Michigan Avenue","amenity":"cafe","cuisine":"coffee_shop","name":"L.A.'s Coffee Cafe","outdoor_seating":"yes"}},"n912":{"id":"n912","loc":[-85.634404,41.943512]},"n913":{"id":"n913","loc":[-85.634391,41.943519],"tags":{"entrance":"yes"}},"n914":{"id":"n914","loc":[-85.634259,41.943538],"tags":{"entrance":"yes"}},"n915":{"id":"n915","loc":[-85.634247,41.943528]},"n916":{"id":"n916","loc":[-85.633747,41.943322],"tags":{"addr:city":"Three Rivers","addr:housenumber":"132","addr:postcode":"49093","addr:state":"MI","addr:street":"Michigan Avenue","name":"Preferred Insurance Services","office":"insurance"}},"n917":{"id":"n917","loc":[-85.63299,41.943686],"tags":{"addr:city":"Three Rivers","addr:housenumber":"101","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Lynn's Garage","service:vehicle:tyres":"yes","shop":"car_repair"}},"n918":{"id":"n918","loc":[-85.633438,41.944883]},"n919":{"id":"n919","loc":[-85.633265,41.944983]},"n92":{"id":"n92","loc":[-85.637481,41.942341]},"n920":{"id":"n920","loc":[-85.633315,41.945027]},"n921":{"id":"n921","loc":[-85.633376,41.944827]},"n922":{"id":"n922","loc":[-85.633199,41.944922]},"n923":{"id":"n923","loc":[-85.633316,41.944772]},"n924":{"id":"n924","loc":[-85.633147,41.944867]},"n925":{"id":"n925","loc":[-85.633261,41.944719]},"n926":{"id":"n926","loc":[-85.633096,41.944812]},"n927":{"id":"n927","loc":[-85.633191,41.944645]},"n928":{"id":"n928","loc":[-85.632981,41.94476]},"n929":{"id":"n929","loc":[-85.633062,41.94483]},"n93":{"id":"n93","loc":[-85.637481,41.94226]},"n930":{"id":"n930","loc":[-85.633146,41.944602]},"n931":{"id":"n931","loc":[-85.632969,41.944703]},"n932":{"id":"n932","loc":[-85.633008,41.944745]},"n933":{"id":"n933","loc":[-85.633088,41.944545]},"n934":{"id":"n934","loc":[-85.632868,41.944655]},"n935":{"id":"n935","loc":[-85.632941,41.944718]},"n936":{"id":"n936","loc":[-85.633028,41.944483]},"n937":{"id":"n937","loc":[-85.632817,41.944605]},"n938":{"id":"n938","loc":[-85.632923,41.944373]},"n939":{"id":"n939","loc":[-85.632692,41.944485]},"n94":{"id":"n94","loc":[-85.637565,41.94226]},"n940":{"id":"n940","loc":[-85.632871,41.944316]},"n941":{"id":"n941","loc":[-85.632655,41.944421]},"n942":{"id":"n942","loc":[-85.632711,41.944478]},"n943":{"id":"n943","loc":[-85.632825,41.94426]},"n944":{"id":"n944","loc":[-85.632606,41.944363]},"n945":{"id":"n945","loc":[-85.63275,41.94418]},"n946":{"id":"n946","loc":[-85.632588,41.944256]},"n947":{"id":"n947","loc":[-85.632611,41.944279]},"n948":{"id":"n948","loc":[-85.632548,41.944306]},"n949":{"id":"n949","loc":[-85.632512,41.944406]},"n95":{"id":"n95","loc":[-85.637188,41.942217]},"n950":{"id":"n950","loc":[-85.632565,41.944463]},"n951":{"id":"n951","loc":[-85.632579,41.944456]},"n952":{"id":"n952","loc":[-85.632634,41.944518]},"n953":{"id":"n953","loc":[-85.632686,41.944569]},"n954":{"id":"n954","loc":[-85.632745,41.944537]},"n955":{"id":"n955","loc":[-85.632659,41.944587]},"n956":{"id":"n956","loc":[-85.632778,41.944705]},"n957":{"id":"n957","loc":[-85.632815,41.944301],"tags":{"addr:city":"Three Rivers","addr:housenumber":"5","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Access Point Employment","office":"employment_agency"}},"n958":{"id":"n958","loc":[-85.6332,41.944174],"tags":{"addr:city":"Three Rivers","addr:housenumber":"6","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Paisley Emporium","shop":"second_hand"}},"n959":{"id":"n959","loc":[-85.633578,41.944568],"tags":{"addr:city":"Three Rivers","addr:housenumber":"22","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","name":"Lowry's Books","shop":"books"}},"n96":{"id":"n96","loc":[-85.637189,41.942303]},"n960":{"id":"n960","loc":[-85.63344,41.944443],"tags":{"addr:city":"Three Rivers","addr:housenumber":"16","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","amenity":"restaurant","cuisine":"pizza","name":"Paisano's Bar and Grill"}},"n961":{"id":"n961","loc":[-85.633009,41.944542],"tags":{"addr:city":"Three Rivers","addr:housenumber":"13","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","amenity":"cafe","cuisine":"american","internet_access":"yes","name":"Main Street Cafe"}},"n962":{"id":"n962","loc":[-85.633674,41.944682],"tags":{"addr:city":"Three Rivers","addr:housenumber":"28","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","leisure":"fitness_centre","name":"Main Street Fitness"}},"n963":{"id":"n963","loc":[-85.633376,41.944868],"tags":{"addr:city":"Three Rivers","addr:housenumber":"27","addr:postcode":"49093","addr:state":"MI","addr:street":"Main Street","leisure":"fitness_centre","name":"Main Street Barbell"}},"n964":{"id":"n964","loc":[-85.633366,41.944783]},"n965":{"id":"n965","loc":[-85.633296,41.94482]},"n966":{"id":"n966","loc":[-85.633214,41.94487]},"n967":{"id":"n967","loc":[-85.633005,41.944988]},"n968":{"id":"n968","loc":[-85.633269,41.944816]},"n969":{"id":"n969","loc":[-85.633215,41.944842]},"n97":{"id":"n97","loc":[-85.637299,41.942302]},"n970":{"id":"n970","loc":[-85.633245,41.944871]},"n971":{"id":"n971","loc":[-85.633296,41.944845]},"n972":{"id":"n972","loc":[-85.633254,41.944845],"tags":{"natural":"tree"}},"n973":{"id":"n973","loc":[-85.633557,41.945515]},"n974":{"id":"n974","loc":[-85.633279,41.945246]},"n975":{"id":"n975","loc":[-85.63324,41.945226]},"n976":{"id":"n976","loc":[-85.6332,41.945213]},"n977":{"id":"n977","loc":[-85.633133,41.945164]},"n978":{"id":"n978","loc":[-85.63312,41.945132]},"n979":{"id":"n979","loc":[-85.633095,41.945081]},"n98":{"id":"n98","loc":[-85.637299,41.942314]},"n980":{"id":"n980","loc":[-85.633064,41.945047]},"n981":{"id":"n981","loc":[-85.632739,41.944742]},"n982":{"id":"n982","loc":[-85.633281,41.945026]},"n983":{"id":"n983","loc":[-85.633155,41.944903]},"n984":{"id":"n984","loc":[-85.633079,41.944829]},"n985":{"id":"n985","loc":[-85.63304,41.944853]},"n986":{"id":"n986","loc":[-85.632949,41.944776]},"n987":{"id":"n987","loc":[-85.632921,41.944725]},"n988":{"id":"n988","loc":[-85.632859,41.944673]},"n989":{"id":"n989","loc":[-85.632895,41.94505]},"n99":{"id":"n99","loc":[-85.637396,41.942313]},"n990":{"id":"n990","loc":[-85.633336,41.945138]},"n991":{"id":"n991","loc":[-85.633466,41.945265]},"n992":{"id":"n992","loc":[-85.633367,41.945327]},"n993":{"id":"n993","loc":[-85.633163,41.945189]},"n994":{"id":"n994","loc":[-85.633678,41.945309]},"n995":{"id":"n995","loc":[-85.633619,41.945261]},"n996":{"id":"n996","loc":[-85.63355,41.945301]},"n997":{"id":"n997","loc":[-85.633607,41.945352]},"n998":{"id":"n998","loc":[-85.633579,41.945327],"tags":{"entrance":"yes"}},"n999":{"id":"n999","loc":[-85.633445,41.945404]},"r2":{"id":"r2","members":[{"id":"w225","role":"outer","type":"way"}],"tags":{"type":"multipolygon","waterway":"riverbank"}},"r5":{"id":"r5","members":[{"id":"w642","role":"outer","type":"way"}],"tags":{"admin_level":"8","border_type":"city","boundary":"administrative","name":"Three Rivers","place":"city","type":"boundary"}},"w1":{"id":"w1","nodes":["n5","n1797"],"tags":{"highway":"residential","name":"12th Avenue"}},"w10":{"id":"w10","nodes":["n54","n55","n56","n57","n891","n890","n54"],"tags":{"building":"yes"}},"w100":{"id":"w100","nodes":["n451","n915","n452"],"tags":{"highway":"footway"}},"w101":{"id":"w101","nodes":["n461","n462","n463","n464","n465","n466"],"tags":{"barrier":"fence"}},"w102":{"id":"w102","nodes":["n467","n468","n469","n470","n472","n467"],"tags":{"amenity":"parking"}},"w103":{"id":"w103","nodes":["n2597","n2444","n471","n472"],"tags":{"highway":"footway"}},"w104":{"id":"w104","nodes":["n473","n474","n325"],"tags":{"footway":"sidewalk","highway":"footway"}},"w105":{"id":"w105","nodes":["n475","n324","n325"],"tags":{"footway":"sidewalk","highway":"footway"}},"w106":{"id":"w106","nodes":["n886","n452","n476"],"tags":{"footway":"sidewalk","highway":"footway"}},"w107":{"id":"w107","nodes":["n485","n4678","n486","n18"],"tags":{"highway":"service"}},"w108":{"id":"w108","nodes":["n300","n487","n488","n489","n490"],"tags":{"highway":"footway"}},"w109":{"id":"w109","nodes":["n490","n491"],"tags":{"highway":"footway"}},"w11":{"id":"w11","nodes":["n58","n63","n59","n315","n60"],"tags":{"highway":"service"}},"w110":{"id":"w110","nodes":["n492","n493","n494","n495","n496","n497","n492"],"tags":{"building":"yes"}},"w111":{"id":"w111","nodes":["n498","n499","n511"],"tags":{"highway":"service"}},"w112":{"id":"w112","nodes":["n510","n500","n501","n502","n503","n504","n505","n506","n507","n508","n509"],"tags":{"highway":"service"}},"w113":{"id":"w113","nodes":["n511","n510"],"tags":{"covered":"yes","highway":"service"}},"w114":{"id":"w114","nodes":["n512","n513","n514","n515","n512"],"tags":{"building":"yes"}},"w115":{"id":"w115","nodes":["n516","n517","n518","n519","n516"],"tags":{"building":"yes"}},"w116":{"id":"w116","nodes":["n520","n521","n522","n523","n520"],"tags":{"building":"yes"}},"w117":{"id":"w117","nodes":["n524","n525","n526","n527","n528","n529","n530","n531","n532","n533","n534","n535","n524"],"tags":{"building":"yes"}},"w118":{"id":"w118","nodes":["n536","n537","n538","n539","n536"],"tags":{"building":"yes"}},"w119":{"id":"w119","nodes":["n540","n541","n542","n543","n544","n545","n546","n547","n540"],"tags":{"building":"yes"}},"w12":{"id":"w12","nodes":["n61","n314","n70","n62","n63"],"tags":{"highway":"service"}},"w120":{"id":"w120","nodes":["n548","n549","n550","n551","n552","n553","n554","n555","n556","n557","n548"],"tags":{"building":"yes"}},"w121":{"id":"w121","nodes":["n558","n559","n560","n561","n562","n563","n564","n565","n558"],"tags":{"building":"yes"}},"w122":{"id":"w122","nodes":["n566","n567","n568","n569","n566"],"tags":{"building":"yes"}},"w123":{"id":"w123","nodes":["n570","n571","n572","n573","n570"],"tags":{"building":"yes"}},"w124":{"id":"w124","nodes":["n574","n575","n576","n577","n574"],"tags":{"building":"yes"}},"w125":{"id":"w125","nodes":["n578","n579","n580","n581","n578"],"tags":{"building":"yes"}},"w126":{"id":"w126","nodes":["n582","n583","n584","n585","n582"],"tags":{"building":"yes"}},"w127":{"id":"w127","nodes":["n586","n587","n588","n589","n590","n591","n592","n593","n586"],"tags":{"building":"yes"}},"w128":{"id":"w128","nodes":["n594","n595","n596","n597","n598","n599","n600","n601","n594"],"tags":{"building":"yes"}},"w129":{"id":"w129","nodes":["n309","n602","n603"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w13":{"id":"w13","nodes":["n64","n65","n66","n67","n68","n69","n64"],"tags":{"amenity":"parking"}},"w130":{"id":"w130","nodes":["n603","n604"],"tags":{"footway":"sidewalk","highway":"footway"}},"w131":{"id":"w131","nodes":["n604","n605","n606"],"tags":{"footway":"sidewalk","highway":"footway"}},"w132":{"id":"w132","nodes":["n606","n607"],"tags":{"footway":"sidewalk","highway":"footway"}},"w133":{"id":"w133","nodes":["n607","n610","n608","n603"],"tags":{"footway":"sidewalk","highway":"footway"}},"w134":{"id":"w134","nodes":["n609","n610","n611"],"tags":{"highway":"service","service":"driveway","surface":"unpaved"}},"w135":{"id":"w135","nodes":["n244","n245","n246"],"tags":{"highway":"service"}},"w136":{"id":"w136","nodes":["n612","n613","n614","n615","n612"],"tags":{"amenity":"shelter"}},"w137":{"id":"w137","nodes":["n2779","n2788","n2776","n2778","n2775","n2787","n2440","n2437","n629","n2438","n630","n2439","n2407","n2408","n2409"],"tags":{"highway":"residential","name":"Foster Street"}},"w138":{"id":"w138","nodes":["n2779","n625","n626","n627"],"tags":{"highway":"residential","name":"Foster Street","oneway":"yes"}},"w139":{"id":"w139","nodes":["n630","n631","n632","n2437"],"tags":{"highway":"service"}},"w14":{"id":"w14","nodes":["n71","n72","n73","n74","n71"],"tags":{"building":"yes"}},"w140":{"id":"w140","nodes":["n643","n637","n715","n2410"],"tags":{"highway":"footway","name":"Mural Mall"}},"w141":{"id":"w141","nodes":["n639","n2516"],"tags":{"barrier":"wall"}},"w142":{"id":"w142","nodes":["n640","n641","n645","n642","n660","n643","n644"],"tags":{"highway":"service"}},"w143":{"id":"w143","nodes":["n646","n647"],"tags":{"highway":"service"}},"w144":{"id":"w144","nodes":["n654","n655","n656"],"tags":{"barrier":"wall"}},"w145":{"id":"w145","nodes":["n665","n666","n667"],"tags":{"barrier":"wall"}},"w146":{"id":"w146","nodes":["n2727","n662","n2719"],"tags":{"highway":"service","oneway":"yes","service":"parking_aisle"}},"w147":{"id":"w147","nodes":["n2725","n674"],"tags":{"highway":"service","oneway":"yes"}},"w148":{"id":"w148","nodes":["n2464","n2460","n2454","n684","n2455","n2464"],"tags":{"building":"yes"}},"w149":{"id":"w149","nodes":["n2456","n685","n686","n687","n2456"],"tags":{"building":"yes"}},"w15":{"id":"w15","nodes":["n75","n76","n77","n78","n75"],"tags":{"building":"yes"}},"w150":{"id":"w150","nodes":["n685","n688","n689","n690","n691","n692","n686","n685"],"tags":{"building":"yes"}},"w151":{"id":"w151","nodes":["n688","n693","n694","n689","n688"],"tags":{"building":"yes"}},"w152":{"id":"w152","nodes":["n693","n695","n702","n696","n697","n694","n693"],"tags":{"building":"yes"}},"w153":{"id":"w153","nodes":["n695","n698","n699","n700","n701","n702","n695"],"tags":{"building":"yes"}},"w154":{"id":"w154","nodes":["n698","n703","n707","n704","n699","n698"],"tags":{"building":"yes"}},"w155":{"id":"w155","nodes":["n703","n705","n706","n707","n703"],"tags":{"building":"yes"}},"w156":{"id":"w156","nodes":["n705","n708","n709","n706","n705"],"tags":{"building":"yes"}},"w157":{"id":"w157","nodes":["n709","n710","n711","n708","n709"],"tags":{"building":"yes"}},"w158":{"id":"w158","nodes":["n369","n712","n725","n713","n714","n715","n727","n716","n717","n718","n719"],"tags":{"footway":"sidewalk","highway":"footway"}},"w159":{"id":"w159","nodes":["n714","n720","n721"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w16":{"id":"w16","nodes":["n79","n80","n81","n82","n83","n84","n85","n86","n79"],"tags":{"building":"yes"}},"w160":{"id":"w160","nodes":["n729","n721","n722","n964","n723","n724"],"tags":{"footway":"sidewalk","highway":"footway"}},"w161":{"id":"w161","nodes":["n713","n726","n722"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w162":{"id":"w162","nodes":["n727","n2411","n728"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w163":{"id":"w163","nodes":["n729","n730","n731"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w164":{"id":"w164","nodes":["n365","n732","n733","n738"],"tags":{"footway":"sidewalk","highway":"footway"}},"w165":{"id":"w165","nodes":["n724","n734","n367","n735","n736","n737"],"tags":{"footway":"sidewalk","highway":"footway"}},"w166":{"id":"w166","nodes":["n739","n2037","n2038","n2039","n2040","n1623","n2032"],"tags":{"highway":"footway"}},"w167":{"id":"w167","nodes":["n150","n751"],"tags":{"highway":"service"}},"w168":{"id":"w168","nodes":["n752","n753","n754","n755","n752"],"tags":{"building":"yes"}},"w169":{"id":"w169","nodes":["n756","n757","n758","n759","n756"],"tags":{"building":"yes"}},"w17":{"id":"w17","nodes":["n87","n88","n89","n90","n87"],"tags":{"building":"yes"}},"w170":{"id":"w170","nodes":["n760","n761","n762","n763","n764","n765","n760"],"tags":{"building":"yes"}},"w171":{"id":"w171","nodes":["n766","n767","n768","n769","n770","n771","n772","n773","n774","n775","n776","n777","n766"],"tags":{"building":"yes"}},"w172":{"id":"w172","nodes":["n778","n779","n780","n781","n782","n783","n784","n785","n778"],"tags":{"building":"yes"}},"w173":{"id":"w173","nodes":["n786","n787","n788","n789","n786"],"tags":{"building":"yes"}},"w174":{"id":"w174","nodes":["n790","n791","n792","n793","n794","n795","n796","n797","n798","n799","n800","n801","n790"],"tags":{"building":"yes"}},"w175":{"id":"w175","nodes":["n802","n803","n804","n805","n802"],"tags":{"building":"yes"}},"w176":{"id":"w176","nodes":["n806","n807","n808","n809","n810","n811","n812","n813","n814","n815","n806"],"tags":{"building":"yes"}},"w177":{"id":"w177","nodes":["n816","n1140","n817","n818","n819","n820","n821"],"tags":{"highway":"service"}},"w178":{"id":"w178","nodes":["n822","n823","n824","n825","n822"],"tags":{"building":"yes"}},"w179":{"id":"w179","nodes":["n841","n842","n843","n844","n841"],"tags":{"building":"yes"}},"w18":{"id":"w18","nodes":["n91","n92","n93","n94","n91"],"tags":{"building":"yes"}},"w180":{"id":"w180","nodes":["n845","n856","n846"],"tags":{"highway":"service"}},"w181":{"id":"w181","nodes":["n846","n847","n848","n849","n850","n851","n852","n853","n854","n855","n856"],"tags":{"highway":"service","oneway":"yes","service":"drive-through"}},"w182":{"id":"w182","nodes":["n857","n858"],"tags":{"highway":"service"}},"w183":{"id":"w183","nodes":["n859","n860","n861","n862","n859"],"tags":{"amenity":"parking"}},"w184":{"id":"w184","nodes":["n863","n864","n867","n866","n865"],"tags":{"highway":"service"}},"w185":{"id":"w185","nodes":["n883","n884"],"tags":{"barrier":"fence"}},"w186":{"id":"w186","nodes":["n1954","n622","n1955"],"tags":{"highway":"path","name":"Riverwalk Trail"}},"w187":{"id":"w187","nodes":["n621","n1954"],"tags":{"highway":"steps","incline":"up","name":"Riverwalk Trail","surface":"wood"}},"w188":{"id":"w188","nodes":["n2274","n2275","n2276","n2277","n2278","n2279","n1953","n621"],"tags":{"highway":"path","name":"Riverwalk Trail","surface":"wood"}},"w189":{"id":"w189","nodes":["n2273","n2274"],"tags":{"highway":"steps","incline":"down","name":"Riverwalk Trail","surface":"wood"}},"w19":{"id":"w19","nodes":["n95","n96","n97","n98","n99","n100","n101","n102","n95"],"tags":{"building":"yes"}},"w190":{"id":"w190","nodes":["n821","n894","n900","n903","n901"],"tags":{"highway":"service"}},"w191":{"id":"w191","nodes":["n896","n897","n898","n899","n900","n894","n896"],"tags":{"amenity":"parking"}},"w192":{"id":"w192","nodes":["n903","n904","n905"],"tags":{"highway":"service"}},"w193":{"id":"w193","nodes":["n901","n906","n902"],"tags":{"highway":"service"}},"w194":{"id":"w194","nodes":["n912","n913"],"tags":{"highway":"footway"}},"w195":{"id":"w195","nodes":["n914","n915"],"tags":{"highway":"footway"}},"w196":{"id":"w196","nodes":["n2466","n918","n919","n920","n2466"],"tags":{"building":"yes"}},"w197":{"id":"w197","nodes":["n918","n921","n922","n919","n918"],"tags":{"building":"yes"}},"w198":{"id":"w198","nodes":["n923","n925","n926","n924","n923"],"tags":{"building":"yes"}},"w199":{"id":"w199","nodes":["n925","n927","n932","n928","n929","n926","n925"],"tags":{"building":"yes"}},"w2":{"id":"w2","nodes":["n3523","n2182","n2160"],"tags":{"highway":"service"}},"w20":{"id":"w20","nodes":["n103","n104","n105","n106","n107","n108","n109","n110","n111","n112","n113","n114","n103"],"tags":{"building":"yes"}},"w200":{"id":"w200","nodes":["n927","n930","n931","n932","n927"],"tags":{"building":"yes"}},"w201":{"id":"w201","nodes":["n930","n933","n934","n935","n931","n930"],"tags":{"building":"yes"}},"w202":{"id":"w202","nodes":["n933","n936","n937","n934","n933"],"tags":{"building":"yes"}},"w203":{"id":"w203","nodes":["n936","n938","n942","n939","n954","n937","n936"],"tags":{"building":"yes"}},"w204":{"id":"w204","nodes":["n938","n940","n941","n942","n938"],"tags":{"building":"yes"}},"w205":{"id":"w205","nodes":["n940","n943","n944","n941","n940"],"tags":{"building":"yes"}},"w206":{"id":"w206","nodes":["n943","n945","n946","n947","n948","n944","n943"],"tags":{"building":"yes"}},"w207":{"id":"w207","nodes":["n944","n949","n950","n951","n941","n944"],"tags":{"building":"yes"}},"w208":{"id":"w208","nodes":["n941","n951","n952","n939","n942","n941"],"tags":{"building":"yes"}},"w209":{"id":"w209","nodes":["n952","n953","n954","n939","n952"],"tags":{"building":"yes"}},"w21":{"id":"w21","nodes":["n115","n116","n117","n118","n115"],"tags":{"building":"yes"}},"w210":{"id":"w210","nodes":["n953","n955","n956","n934","n937","n954","n953"],"tags":{"building":"yes"}},"w211":{"id":"w211","nodes":["n964","n965"],"tags":{"highway":"footway"}},"w212":{"id":"w212","nodes":["n966","n983","n967","n989"],"tags":{"highway":"footway"}},"w213":{"id":"w213","nodes":["n965","n968","n969","n966","n970","n971","n965"],"tags":{"highway":"footway"}},"w214":{"id":"w214","nodes":["n973","n999","n992","n974","n975","n976","n993","n977","n978","n979","n980","n967","n981","n1000","n1001","n1002","n1003","n1004","n1005","n1006","n1007","n1008","n1009"],"tags":{"footway":"sidewalk","highway":"footway"}},"w215":{"id":"w215","nodes":["n978","n982","n983","n984","n985","n986","n987","n988","n981"],"tags":{"highway":"footway"}},"w216":{"id":"w216","nodes":["n976","n990","n991","n992"],"tags":{"highway":"footway"}},"w217":{"id":"w217","nodes":["n998","n999"],"tags":{"highway":"footway"}},"w218":{"id":"w218","nodes":["n1019","n1020","n1021","n1022","n731","n728","n1023","n1025","n1024","n1019"],"tags":{"footway":"sidewalk","highway":"footway"}},"w219":{"id":"w219","nodes":["n719","n1026","n1027"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w22":{"id":"w22","nodes":["n119","n120","n121","n122","n119"],"tags":{"building":"yes"}},"w220":{"id":"w220","nodes":["n1027","n1028","n1019"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w221":{"id":"w221","nodes":["n2080","n1828","n1863","n1829"],"tags":{"highway":"tertiary","name":"Constantine Street"}},"w222":{"id":"w222","nodes":["n1029","n1030","n1031"],"tags":{"highway":"service"}},"w223":{"id":"w223","nodes":["n2213","n2171","n2183","n2180","n2205","n2177","n2179","n2218","n2200","n2188","n2169","n2196","n2162","n2170","n2211","n2216","n2204","n2220","n2164","n2210","n2217","n2189","n460","n453","n2282"],"tags":{"name":"Rocky River","waterway":"river"}},"w224":{"id":"w224","nodes":["n3750","n3751","n3752"],"tags":{"highway":"service","service":"alley","surface":"unpaved"}},"w225":{"id":"w225","nodes":["n2134","n2127","n2313","n2109","n2112","n2129","n2156","n2146","n2126","n2153","n2288","n2283","n2284","n2131","n2286","n2287","n2285","n2132","n2140","n2289","n2122","n2114","n2149","n2119","n2106","n2111","n2145","n2113","n2117","n2159","n2143","n2123","n2142","n2116","n2154","n2139","n2150","n2157","n2120","n2138","n2130","n2136","n2155","n2107","n2141","n2124","n3754","n2121","n2105","n2108","n3755","n2128","n2110","n2152","n2125","n2135","n2186","n2115","n2144","n2137","n2133","n2148","n2118","n1871","n1875","n1872","n2041","n1873","n2042","n1874","n1884","n1870","n2151","n2147","n2158","n2104","n2134"]},"w226":{"id":"w226","nodes":["n2243","n2280","n2244","n2245","n2246","n2247","n1931","n1932","n1933","n1934","n1935","n1936","n1937","n1938","n4681","n1939","n1940","n1941","n1942","n1943","n1944","n1945","n1946","n1947"],"tags":{"highway":"path","name":"Riverwalk Trail","surface":"asphalt","width":"3"}},"w227":{"id":"w227","nodes":["n2994","n3012","n3011","n2958"],"tags":{"highway":"secondary","name":"Main Street"}},"w228":{"id":"w228","nodes":["n2747","n2762","n2757","n2746","n2761","n2758","n2760","n2755","n2749","n2691","n1028","n2432","n2414","n2413","n2412","n2411","n2410","n720","n726","n370","n368","n2748"],"tags":{"highway":"primary","name":"Main Street"}},"w229":{"id":"w229","nodes":["n2083","n2103","n2102","n2084","n2085","n2086","n2087","n2242","n471","n324","n2101","n332","n1868"],"tags":{"name":"Conrail Railroad","railway":"rail"}},"w23":{"id":"w23","nodes":["n123","n124","n125","n126","n123"],"tags":{"building":"yes"}},"w230":{"id":"w230","nodes":["n2232","n2236","n2231","n2230","n2226","n2241","n2237","n2227","n1182","n2233","n2228","n2229","n1183","n2234","n19","n1891","n20","n2223","n2224","n2238","n2235","n2240","n2225","n2239"],"tags":{"name":"Saint Joseph River","waterway":"river"}},"w231":{"id":"w231","nodes":["n456","n1036","n1037","n1038"],"tags":{"barrier":"wall"}},"w232":{"id":"w232","nodes":["n1034","n1039","n1040"],"tags":{"barrier":"wall"}},"w233":{"id":"w233","nodes":["n1041","n1042","n1043","n1044","n1045","n1046","n1041"],"tags":{"access":"private","leisure":"swimming_pool"}},"w234":{"id":"w234","nodes":["n1047","n1048"],"tags":{"barrier":"hedge"}},"w235":{"id":"w235","nodes":["n1049","n1050","n1051","n1052","n1049"],"tags":{"building":"yes"}},"w236":{"id":"w236","nodes":["n1053","n1054","n1055","n1056","n1057","n1058","n1059","n1060","n1053"],"tags":{"building":"yes"}},"w237":{"id":"w237","nodes":["n1061","n1062","n1063","n1064","n1065","n1061"],"tags":{"building":"yes"}},"w238":{"id":"w238","nodes":["n1066","n1067","n1068","n1069","n1070","n1071","n1066"],"tags":{"building":"yes"}},"w239":{"id":"w239","nodes":["n1072","n1073","n1074","n1075","n1072"],"tags":{"building":"yes"}},"w24":{"id":"w24","nodes":["n127","n128","n129","n130","n127"],"tags":{"building":"yes"}},"w240":{"id":"w240","nodes":["n1076","n1077","n1078","n1079","n1080","n1081","n1076"],"tags":{"building":"yes"}},"w241":{"id":"w241","nodes":["n1082","n1083","n1084","n1085","n1082"],"tags":{"building":"yes"}},"w242":{"id":"w242","nodes":["n1086","n1087","n1088","n1089","n1086"],"tags":{"building":"yes"}},"w243":{"id":"w243","nodes":["n1090","n1091","n1092","n1093","n1094","n1095","n1096","n1097","n1090"],"tags":{"building":"yes"}},"w244":{"id":"w244","nodes":["n1098","n1099","n1100","n1101"],"tags":{"barrier":"fence"}},"w245":{"id":"w245","nodes":["n1102","n835","n30","n2590","n35","n29","n2591","n34","n28","n2592","n2312","n32","n2593","n31","n33","n2594","n2595","n1102"],"tags":{"highway":"service"}},"w246":{"id":"w246","nodes":["n1103","n1139","n1104"],"tags":{"barrier":"fence"}},"w247":{"id":"w247","nodes":["n1105","n1106","n1107","n1108","n1109","n1110","n1111","n1112","n1113","n1114","n1105"],"tags":{"building":"yes"}},"w248":{"id":"w248","nodes":["n1115","n1116","n1117","n1118","n1119","n1120","n1115"],"tags":{"building":"yes"}},"w249":{"id":"w249","nodes":["n1121","n1122","n1123","n1124","n1121"],"tags":{"building":"yes"}},"w25":{"id":"w25","nodes":["n131","n132","n133","n134","n135","n136","n137","n138","n139","n140","n141","n142","n131"],"tags":{"building":"yes"}},"w250":{"id":"w250","nodes":["n1125","n1126","n1127","n1128","n1129","n1130","n1131","n1132","n1133","n1134","n1135","n1136","n1125"],"tags":{"building":"yes"}},"w251":{"id":"w251","nodes":["n1137","n1138","n1139"],"tags":{"barrier":"fence"}},"w252":{"id":"w252","nodes":["n876","n1140","n1141"],"tags":{"footway":"sidewalk","highway":"footway"}},"w253":{"id":"w253","nodes":["n1141","n1142","n1143","n1144","n1145","n1146"],"tags":{"footway":"sidewalk","highway":"footway"}},"w254":{"id":"w254","nodes":["n1146","n4743","n1147","n1148"],"tags":{"footway":"sidewalk","highway":"footway"}},"w255":{"id":"w255","nodes":["n1148","n1149","n1150","n1151"],"tags":{"bridge":"yes","footway":"sidewalk","highway":"footway","layer":"1"}},"w256":{"id":"w256","nodes":["n1151","n1153","n1154","n1155"],"tags":{"footway":"sidewalk","highway":"footway"}},"w257":{"id":"w257","nodes":["n1155","n1156"],"tags":{"bridge":"yes","footway":"sidewalk","highway":"footway","layer":"1"}},"w258":{"id":"w258","nodes":["n1157","n1158"],"tags":{"barrier":"retaining_wall"}},"w259":{"id":"w259","nodes":["n1156","n1161","n1159","n1160","n719"],"tags":{"footway":"sidewalk","highway":"footway"}},"w26":{"id":"w26","nodes":["n143","n608","n144"],"tags":{"highway":"service"}},"w260":{"id":"w260","nodes":["n1162","n1163","n1164","n1165","n1166","n1167","n1168","n1169","n1170","n2528"],"tags":{"highway":"footway"}},"w261":{"id":"w261","nodes":["n1171","n1172","n1173"],"tags":{"barrier":"wall"}},"w262":{"id":"w262","nodes":["n1175","n1176","n1177","n1178","n1179","n1180","n1181","n1175"],"tags":{"natural":"wood"}},"w263":{"id":"w263","nodes":["n1947","n1184","n1948","n1185","n1949","n1957","n1950","n480","n1951","n479","n478","n477","n1952","n1851","n1956","n2248","n619","n618","n2249","n2250","n2251","n617","n2252","n616","n2253","n829","n2254","n827","n828","n2255","n830","n2256","n826","n2257","n831","n2258","n832","n835","n834","n2312","n2267","n2259","n833","n2268","n2260","n836","n2261","n837","n2262","n838","n2263","n2264","n839","n2265","n840","n2266"],"tags":{"highway":"path","name":"Riverwalk Trail","surface":"asphalt","width":"3"}},"w264":{"id":"w264","nodes":["n1186","n1187","n1188","n1189","n1186"],"tags":{"building":"yes"}},"w265":{"id":"w265","nodes":["n1190","n1191","n1192","n1193","n1190"],"tags":{"building":"yes"}},"w266":{"id":"w266","nodes":["n1194","n1195","n1196","n1197","n1198","n1199","n1200","n1201","n1194"],"tags":{"building":"yes"}},"w267":{"id":"w267","nodes":["n1205","n1206","n1207","n1208","n1209","n1210","n1205"],"tags":{"building":"house"}},"w268":{"id":"w268","nodes":["n1211","n1212","n1213","n1214","n1215","n1216","n1217","n1218","n1219","n1220","n1211"],"tags":{"building":"house"}},"w269":{"id":"w269","nodes":["n1221","n1225","n1222","n1223","n1224","n1221"],"tags":{"building":"house"}},"w27":{"id":"w27","nodes":["n145","n147","n146"],"tags":{"highway":"footway"}},"w270":{"id":"w270","nodes":["n1225","n1226","n1227","n1229","n1228"],"tags":{"barrier":"fence"}},"w271":{"id":"w271","nodes":["n1229","n1230"],"tags":{"barrier":"fence"}},"w272":{"id":"w272","nodes":["n1231","n1232","n1233","n1234","n1235","n1236","n1237","n1238","n1231"],"tags":{"building":"house"}},"w273":{"id":"w273","nodes":["n1239","n1240","n1241","n1242","n1243","n1244","n1245","n1246","n1239"],"tags":{"building":"house"}},"w274":{"id":"w274","nodes":["n1247","n1248","n1249","n1250","n1247"],"tags":{"building":"house"}},"w275":{"id":"w275","nodes":["n1251","n1252","n1253","n1254","n1255","n1256","n1251"],"tags":{"building":"house"}},"w276":{"id":"w276","nodes":["n1257","n1258","n1259","n1260","n1257"],"tags":{"building":"shed"}},"w277":{"id":"w277","nodes":["n1261","n1262","n1263","n1264","n1265","n1266","n1267","n1268","n1261"],"tags":{"building":"house"}},"w278":{"id":"w278","nodes":["n1269","n1270","n1271","n1272","n1273","n1274","n1284","n1269"],"tags":{"building":"house"}},"w279":{"id":"w279","nodes":["n1275","n1276","n1277","n1278","n1279","n1280","n1275"],"tags":{"building":"house"}},"w28":{"id":"w28","nodes":["n147","n148"],"tags":{"highway":"footway"}},"w280":{"id":"w280","nodes":["n1281","n1282","n1283","n1284"],"tags":{"barrier":"fence"}},"w281":{"id":"w281","nodes":["n1285","n1286","n1287","n1288","n1285"],"tags":{"building":"house"}},"w282":{"id":"w282","nodes":["n1289","n1290","n1291","n1292","n1293","n1294","n1295","n1296","n1289"],"tags":{"building":"house"}},"w283":{"id":"w283","nodes":["n1297","n1298","n1299","n1300","n1301","n1302","n1297"],"tags":{"access":"private","leisure":"swimming_pool"}},"w284":{"id":"w284","nodes":["n1303","n1304","n1305","n1306","n1307","n1308","n1309","n1310","n1311","n1312","n1303"],"tags":{"building":"house"}},"w285":{"id":"w285","nodes":["n1313","n1314","n1315","n1316","n1313"],"tags":{"building":"house"}},"w286":{"id":"w286","nodes":["n1317","n1318","n1319","n1320","n1321","n1322","n1323","n1324","n1325","n1326","n1327","n1328","n1329","n1330","n1317"],"tags":{"building":"house"}},"w287":{"id":"w287","nodes":["n1331","n1332","n1333","n1334","n1465","n1335","n1336","n1331"],"tags":{"building":"yes"}},"w288":{"id":"w288","nodes":["n1349","n1350","n1351","n1352","n1353","n1354","n1355","n1337","n1338","n1341","n1342","n1343","n1344","n1345","n1346","n1347","n1348","n1339","n1340","n1349"],"tags":{"access":"private","leisure":"swimming_pool"}},"w289":{"id":"w289","nodes":["n1356","n1331"],"tags":{"barrier":"fence"}},"w29":{"id":"w29","nodes":["n149","n874","n150","n151","n897","n898","n875","n152"],"tags":{"highway":"service","oneway":"yes"}},"w290":{"id":"w290","nodes":["n1357","n1358","n1359","n1360","n1357"],"tags":{"building":"shed"}},"w291":{"id":"w291","nodes":["n1358","n1361","n1362"],"tags":{"barrier":"fence"}},"w292":{"id":"w292","nodes":["n1363","n1364","n1365","n1366","n1367","n1368","n1363"],"tags":{"building":"house"}},"w293":{"id":"w293","nodes":["n1369","n1370","n1371","n1372","n1373","n1374","n1369"],"tags":{"leisure":"swimming_pool"}},"w294":{"id":"w294","nodes":["n1367","n1375","n1376","n1377"],"tags":{"barrier":"fence"}},"w295":{"id":"w295","nodes":["n1378","n1379","n1380","n1381","n1378"],"tags":{"building":"house"}},"w296":{"id":"w296","nodes":["n1382","n1383","n1384","n1385","n1386","n1387","n1382"],"tags":{"building":"house"}},"w297":{"id":"w297","nodes":["n1388","n1389","n1390","n1391","n1392","n1393","n1388"],"tags":{"building":"house"}},"w298":{"id":"w298","nodes":["n1394","n1395","n1396","n1397","n1394"],"tags":{"building":"house"}},"w299":{"id":"w299","nodes":["n1398","n1399","n1400","n1401","n1398"],"tags":{"access":"private3","leisure":"swimming_pool"}},"w3":{"id":"w3","nodes":["n1","n2"],"tags":{"highway":"track","name":"Water Street"}},"w30":{"id":"w30","nodes":["n153","n154","n155","n156","n153"],"tags":{"amenity":"parking"}},"w300":{"id":"w300","nodes":["n1402","n1403","n1404","n1405","n1406","n1407","n1408","n1409","n1410","n1411","n1412","n1413","n1402"],"tags":{"building":"house"}},"w301":{"id":"w301","nodes":["n1414","n1415","n1416","n1417","n1414"],"tags":{"building":"garage"}},"w302":{"id":"w302","nodes":["n1406","n1418","n1419","n1403"],"tags":{"barrier":"fence"}},"w303":{"id":"w303","nodes":["n1423","n1424","n1425","n1426","n1427","n1428","n1429","n1430","n1431","n1432","n1423"],"tags":{"building":"house"}},"w304":{"id":"w304","nodes":["n1433","n1434","n1435","n1446","n1436","n1437","n1438","n1439","n1444","n1440","n1441","n1445","n1442","n1443","n1433"],"tags":{"access":"private","leisure":"swimming_pool"}},"w305":{"id":"w305","nodes":["n1447","n1448","n1452","n1453","n1454","n1451","n1449","n1450","n1447"],"tags":{"building":"house"}},"w306":{"id":"w306","nodes":["n1455","n1456","n1457","n1458","n1455"],"tags":{"building":"shed"}},"w307":{"id":"w307","nodes":["n1459","n1460","n1461","n1462","n1459"],"tags":{"building":"shed"}},"w308":{"id":"w308","nodes":["n1463","n1464"],"tags":{"barrier":"fence"}},"w309":{"id":"w309","nodes":["n1465","n1466","n1467","n1468"],"tags":{"barrier":"fence"}},"w31":{"id":"w31","nodes":["n157","n605","n158"],"tags":{"highway":"service"}},"w310":{"id":"w310","nodes":["n1469","n1481","n1463"],"tags":{"barrier":"hedge"}},"w311":{"id":"w311","nodes":["n1470","n1471","n1472","n1473","n1474","n1475","n1480","n1476","n1477","n1478","n1479","n1470"],"tags":{"building":"house"}},"w312":{"id":"w312","nodes":["n1480","n1481"],"tags":{"barrier":"wall"}},"w313":{"id":"w313","nodes":["n1482","n1483","n1484","n1485","n1486","n1487","n1488","n1489","n1490","n1491","n1482"],"tags":{"access":"private","leisure":"swimming_pool"}},"w314":{"id":"w314","nodes":["n1492","n1493","n1494","n1495","n1496","n1497","n1498","n1499","n1500","n1501","n1502","n1503","n1504","n1505","n1492"],"tags":{"building":"house"}},"w315":{"id":"w315","nodes":["n1506","n1507","n1508","n1509","n1510","n1511","n1512","n1513","n1514","n1515","n1506"],"tags":{"building":"house"}},"w316":{"id":"w316","nodes":["n1516","n1517","n1518","n1519","n1520","n1521","n1522","n1523","n1516"],"tags":{"building":"house"}},"w317":{"id":"w317","nodes":["n1524","n1525","n1526","n1527","n1528","n1529","n1530","n1531","n1524"],"tags":{"building":"house"}},"w318":{"id":"w318","nodes":["n1532","n1533"],"tags":{"barrier":"fence"}},"w319":{"id":"w319","nodes":["n1534","n1532","n1535"],"tags":{"barrier":"fence"}},"w32":{"id":"w32","nodes":["n159","n160","n161","n162","n159"],"tags":{"amenity":"parking"}},"w320":{"id":"w320","nodes":["n1536","n1537","n1538","n1539","n1536"],"tags":{"building":"shed"}},"w321":{"id":"w321","nodes":["n1540","n1541","n1542","n1543","n1540"],"tags":{"building":"shed"}},"w322":{"id":"w322","nodes":["n1544","n1545","n1546","n1547","n1544"],"tags":{"building":"shed"}},"w323":{"id":"w323","nodes":["n1548","n1549","n1550","n1551","n1548"],"tags":{"building":"house"}},"w324":{"id":"w324","nodes":["n1552","n1553","n1554","n1555","n1556","n1557","n1558","n1559","n1552"],"tags":{"building":"house"}},"w325":{"id":"w325","nodes":["n1560","n1561","n1562","n1563","n1564","n1565","n1566","n1567","n1560"],"tags":{"building":"house"}},"w326":{"id":"w326","nodes":["n1561","n1568","n1569","n1570"],"tags":{"barrier":"wall"}},"w327":{"id":"w327","nodes":["n1571","n1572"],"tags":{"barrier":"fence"}},"w328":{"id":"w328","nodes":["n1573","n1574","n1575","n1576","n1573"],"tags":{"building":"house"}},"w329":{"id":"w329","nodes":["n1577","n1578","n1579","n1580","n1581","n1582","n1583","n1584","n1585","n1586","n1577"],"tags":{"building":"house"}},"w33":{"id":"w33","nodes":["n157","n163"],"tags":{"highway":"service"}},"w330":{"id":"w330","nodes":["n1587","n1588","n1589","n1590","n1591","n1592","n1593","n1594","n1587"],"tags":{"building":"house"}},"w331":{"id":"w331","nodes":["n1595","n1596","n1597","n1598","n1599","n1600","n1601","n1595"],"tags":{"access":"private","leisure":"swimming_pool"}},"w332":{"id":"w332","nodes":["n1602","n1603","n1604","n1605","n1606","n1607","n1608","n1609","n1611","n1610","n1612","n1613","n1602"],"tags":{"building":"house"}},"w333":{"id":"w333","nodes":["n2018","n1626","n1627","n2017","n2018"],"tags":{"amenity":"shelter","shelter_type":"picnic_shelter"}},"w334":{"id":"w334","nodes":["n2","n3","n2764"],"tags":{"highway":"service","name":"Water Street"}},"w335":{"id":"w335","nodes":["n3","n1628","n1614"],"tags":{"highway":"service"}},"w336":{"id":"w336","nodes":["n3198","n4545","n2747"],"tags":{"highway":"residential","name":"Morris Avenue"}},"w337":{"id":"w337","nodes":["n1629","n3504"],"tags":{"highway":"service","service":"alley","surface":"unpaved"}},"w338":{"id":"w338","nodes":["n1813","n1635","n1814","n1634","n1815","n1632","n1816","n1817"],"tags":{"highway":"service","service":"parking_aisle"}},"w339":{"id":"w339","nodes":["n1827","n4684","n4690","n1842","n4686","n4685","n1826","n1828","n1846","n1645","n1637","n4703","n1641"],"tags":{"highway":"residential","name":"Millard Street"}},"w34":{"id":"w34","nodes":["n164","n165","n166","n171","n866","n172","n167","n168","n169","n910","n170","n164"],"tags":{"amenity":"parking"}},"w340":{"id":"w340","nodes":["n1824","n1825"],"tags":{"highway":"service","service":"parking_aisle"}},"w341":{"id":"w341","nodes":["n1701","n1702","n1703","n1704","n1705","n1706","n1701"],"tags":{"building":"yes"}},"w342":{"id":"w342","nodes":["n1855","n1860","n1856","n1775","n1804","n1776","n1855"],"tags":{"amenity":"parking","fee":"no"}},"w343":{"id":"w343","nodes":["n1757","n1758","n1759","n1760","n1757"],"tags":{"building":"yes"}},"w344":{"id":"w344","nodes":["n1659","n1660","n1661","n1662","n1663","n1664","n1665","n1666","n1659"],"tags":{"building":"school"}},"w345":{"id":"w345","nodes":["n1751","n1752","n1753","n1754","n1755","n1756","n1751"],"tags":{"building":"yes"}},"w346":{"id":"w346","nodes":["n1641","n1676","n1673","n1639","n1810","n1642","n1849","n4759","n1845"],"tags":{"highway":"residential","name":"Douglas Avenue"}},"w347":{"id":"w347","nodes":["n1642","n1643","n1031","n1630","n845","n1631","n816","n1831","n902","n905","n152","n149","n1832","n1850","n878","n1833","n1852","n42","n1834","n61","n60","n1851","n1835"],"tags":{"highway":"primary","name":"Michigan Avenue"}},"w348":{"id":"w348","nodes":["n1650","n1651","n1652","n1653","n1654","n1655","n1656","n1657","n1658","n1650"],"tags":{"leisure":"playground"}},"w349":{"id":"w349","nodes":["n1861","n1818","n1819","n1820","n1821","n1825","n1823","n1639"],"tags":{"highway":"service"}},"w35":{"id":"w35","nodes":["n168","n167","n172"],"tags":{"barrier":"fence","fence_type":"chain_link"}},"w350":{"id":"w350","nodes":["n1783","n1819","n1784","n1857","n1861","n1858","n1783"],"tags":{"amenity":"parking"}},"w351":{"id":"w351","nodes":["n1717","n1718","n1719","n1720","n1717"],"tags":{"building":"yes"}},"w352":{"id":"w352","nodes":["n1743","n1744","n1745","n1746","n1747","n1748","n1749","n1750","n1743"],"tags":{"building":"yes"}},"w353":{"id":"w353","nodes":["n1637","n1636","n1029","n4715","n1630"],"tags":{"highway":"residential","name":"Lincoln Avenue"}},"w354":{"id":"w354","nodes":["n1713","n1714","n1715","n1716","n1713"],"tags":{"building":"yes"}},"w355":{"id":"w355","nodes":["n1689","n1690","n1691","n1692","n1693","n1694","n1695","n1696","n1689"],"tags":{"building":"yes"}},"w356":{"id":"w356","nodes":["n1631","n4717","n1840","n4745","n1841"],"tags":{"highway":"residential","name":"Hook Avenue"}},"w357":{"id":"w357","nodes":["n1737","n1738","n1739","n1740","n1741","n1742","n1737"],"tags":{"building":"yes"}},"w358":{"id":"w358","nodes":["n1707","n1708","n1709","n1710","n1711","n1712","n1707"],"tags":{"building":"yes"}},"w359":{"id":"w359","nodes":["n1829","n4695","n4697","n1843","n4698","n4701","n1638","n4702","n4705","n1636","n4706","n4707","n1633"],"tags":{"highway":"residential","name":"South Street"}},"w36":{"id":"w36","nodes":["n910","n171","n866","n172"],"tags":{"barrier":"fence","fence_type":"chain_link"}},"w360":{"id":"w360","nodes":["n1767","n1768","n1769","n1770","n1771","n1772","n1773","n1774","n1767"],"tags":{"building":"yes"}},"w361":{"id":"w361","nodes":["n1859","n1860","n1804","n1640","n1805","n1817","n1806","n1644","n1811","n1807","n1808","n3419","n1812","n1790","n3418","n3744","n1809","n1813","n1810"],"tags":{"highway":"service"}},"w362":{"id":"w362","nodes":["n1639","n1683","n4710","n1633"],"tags":{"highway":"residential","name":"South Street","oneway":"yes"}},"w363":{"id":"w363","nodes":["n1646","n1647","n1648","n1649","n1646"],"tags":{"leisure":"pitch","pitch":"basketball"}},"w364":{"id":"w364","nodes":["n3820","n3821","n3822","n3823","n3824","n3825","n3826","n3827","n3828","n3829","n3830","n3838","n3839","n3820"],"tags":{"amenity":"school","name":"Three Rivers Middle School"}},"w365":{"id":"w365","nodes":["n1721","n1722","n1723","n1724","n1725","n1726","n1727","n1728","n1729","n1730","n1731","n1732","n1733","n1734","n1735","n1736","n1721"],"tags":{"building":"yes"}},"w366":{"id":"w366","nodes":["n1791","n1792","n1793","n1794","n1795","n1796","n1798","n1799","n1800","n1801","n1802","n1803","n1791"],"tags":{"amenity":"parking"}},"w367":{"id":"w367","nodes":["n1633","n4708","n4711","n1643","n4712","n1838","n4752","n1839"],"tags":{"highway":"residential","name":"Grant Avenue"}},"w368":{"id":"w368","nodes":["n1853","n1687","n1688","n1854","n1853"],"tags":{"amenity":"library","building":"yes","name":"Three Rivers Public Library"}},"w369":{"id":"w369","nodes":["n1777","n1778","n1779","n1780","n1781","n1782","n1777"],"tags":{"amenity":"parking"}},"w37":{"id":"w37","nodes":["n173","n174","n175","n176","n177","n178","n179","n180","n173"],"tags":{"building":"yes"}},"w370":{"id":"w370","nodes":["n1645","n1638","n858","n4718","n1631"],"tags":{"highway":"residential","name":"Hook Avenue"}},"w371":{"id":"w371","nodes":["n3836","n3835","n4624","n3831","n4632","n3834","n3832","n3833","n3830","n3838","n3839","n3837","n3836"],"tags":{"amenity":"school","name":"Three Rivers High School"}},"w372":{"id":"w372","nodes":["n1697","n1698","n1699","n1700","n1697"],"tags":{"building":"yes"}},"w373":{"id":"w373","nodes":["n2891","n1785","n1786","n3394","n1787","n1788","n1789","n1830","n1836","n1837","n1848","n3409","n2891"],"tags":{"amenity":"parking"}},"w374":{"id":"w374","nodes":["n1761","n1762","n1763","n1764","n1765","n1766","n1761"],"tags":{"building":"yes"}},"w375":{"id":"w375","nodes":["n1822","n1823"],"tags":{"highway":"service","service":"parking_aisle"}},"w376":{"id":"w376","nodes":["n1677","n1678","n1679","n1680","n1681","n1682","n1677"],"tags":{"amenity":"parking"}},"w377":{"id":"w377","nodes":["n1676","n1675","n1674","n1673"],"tags":{"highway":"service","oneway":"yes"}},"w378":{"id":"w378","nodes":["n1667","n1668","n1669","n1670","n1671","n1672","n1667"],"tags":{"amenity":"school","name":"Andrews Elementary School"}},"w379":{"id":"w379","nodes":["n1630","n4714","n1847","n4750","n1844"],"tags":{"highway":"residential","name":"Lincoln Avenue"}},"w38":{"id":"w38","nodes":["n181","n182","n183","n185","n184","n181"],"tags":{"building":"yes"}},"w380":{"id":"w380","nodes":["n1683","n3745","n1686","n1633"],"tags":{"highway":"service","oneway":"yes","service":"parking_aisle"}},"w381":{"id":"w381","nodes":["n2022","n2037"],"tags":{"highway":"footway"}},"w382":{"id":"w382","nodes":["n1826","n1863"],"tags":{"highway":"residential"}},"w383":{"id":"w383","nodes":["n2011","n2012","n739","n2013","n2014","n2029","n2011"],"tags":{"amenity":"shelter","building":"yes","shelter_type":"picnic_shelter"}},"w384":{"id":"w384","nodes":["n2064","n2065","n2066","n2067","n2068","n2069","n2070","n2071","n2072","n2073","n2074","n2075","n2076","n2077","n2078","n2079","n2064"],"tags":{"building":"yes"}},"w385":{"id":"w385","nodes":["n1923","n1924","n1925","n1926","n1927","n1928","n1930","n1929","n1923"],"tags":{"natural":"water"}},"w386":{"id":"w386","nodes":["n1827","n14","n1886","n15","n1887","n16","n1888","n18","n17","n1889","n12","n13","n1890","n485","n1864","n11","n10","n2058","n2036","n1865","n2020","n9","n8","n1866","n295","n1867"],"tags":{"highway":"service"}},"w387":{"id":"w387","nodes":["n1846","n1843","n865","n157","n4721","n1831"],"tags":{"highway":"residential","name":"Andrews Street"}},"w388":{"id":"w388","nodes":["n2019","n2020","n2021","n2022","n2023","n2024","n2025","n2026","n2027","n2028","n2029"],"tags":{"highway":"footway"}},"w389":{"id":"w389","nodes":["n2217","n2222","n2221","n2219","n1877","n1879","n1882","n1883","n484","n1885","n483","n1880","n1881","n1878","n1884","n2223"],"tags":{"name":"Rocky River","waterway":"river"}},"w39":{"id":"w39","nodes":["n185","n186","n187"],"tags":{"barrier":"fence"}},"w390":{"id":"w390","nodes":["n2050","n2051","n2052","n2053","n2050"],"tags":{"amenity":"shelter","shelter_type":"picnic_shelter"}},"w391":{"id":"w391","nodes":["n2089","n2090","n2091","n2092","n2093","n2094","n2311","n2095","n2096","n2097","n2098","n1174","n2099","n751","n43","n2062","n4725","n873","n1832"],"tags":{"highway":"residential","name":"Constantine Street"}},"w392":{"id":"w392","nodes":["n1869","n212","n436","n2281","n2081"],"tags":{"highway":"primary","name":"Michigan Avenue"}},"w393":{"id":"w393","nodes":["n1829","n611","n144","n4694","n602","n1832"],"tags":{"highway":"tertiary","name":"Constantine Street"}},"w394":{"id":"w394","nodes":["n1997","n1998","n2000","n1999"],"tags":{"highway":"service","service":"parking_aisle"}},"w395":{"id":"w395","nodes":["n1835","n1869"],"tags":{"bridge":"yes","highway":"primary","name":"Michigan Avenue"}},"w396":{"id":"w396","nodes":["n2000","n2001"],"tags":{"highway":"service","service":"parking_aisle"}},"w397":{"id":"w397","nodes":["n2082","n4688","n1842","n308","n498","n509","n246","n241","n1867","n4645","n293","n1834"],"tags":{"highway":"residential","name":"Spring Street"}},"w398":{"id":"w398","nodes":["n2015","n2016","n2017","n2018","n2015"],"tags":{"building":"yes"}},"w399":{"id":"w399","nodes":["n2062","n45","n2063","n877","n41","n1852"],"tags":{"highway":"service"}},"w4":{"id":"w4","nodes":["n7","n38","n378","n379","n7"],"tags":{"building":"yes"}},"w40":{"id":"w40","nodes":["n188","n189","n190","n191","n192","n193","n188"],"tags":{"building":"house"}},"w400":{"id":"w400","nodes":["n1968","n1969","n1970","n1971","n2007","n1972","n1973","n1978","n1974","n1977","n1976","n1975","n1968"],"tags":{"amenity":"parking"}},"w401":{"id":"w401","nodes":["n1963","n1964"],"tags":{"bridge":"yes","highway":"footway"}},"w402":{"id":"w402","nodes":["n1892","n1893","n1894","n1895","n1896","n1897","n1898","n1899","n1900","n1901","n1902","n1903","n1892"],"tags":{"addr:city":"Three Rivers","addr:housenumber":"112","addr:postcode":"49093","addr:state":"MI","addr:street":"Spring Street","barrier":"fence","name":"Scidmore Park Petting Zoo","tourism":"zoo","zoo":"petting_zoo"}},"w403":{"id":"w403","nodes":["n1957","n1958","n1959","n481","n1960","n482","n1949"],"tags":{"highway":"path"}},"w404":{"id":"w404","nodes":["n2281","n27","n330","n1987","n1988"],"tags":{"highway":"service"}},"w405":{"id":"w405","nodes":["n2249","n2269","n2270","n2271","n2272","n454","n455","n2273"],"tags":{"highway":"path","name":"Riverwalk Trail"}},"w406":{"id":"w406","nodes":["n1947","n1624","n1625","n2030","n2033","n4658","n4659","n2031","n2032","n2021"],"tags":{"highway":"footway"}},"w407":{"id":"w407","nodes":["n2034","n2036","n2009"],"tags":{"highway":"footway"}},"w408":{"id":"w408","nodes":["n1964","n1965","n2002","n1966","n21","n1967","n1969"],"tags":{"highway":"footway"}},"w409":{"id":"w409","nodes":["n1904","n1905","n1906","n1907","n1908","n1909","n748","n1910","n747","n1911","n749","n1912","n750","n1913","n1922","n1914","n1921","n1915","n746","n1916","n745","n1917","n744","n1918","n743","n742","n1919","n741","n1920","n740","n1904"],"tags":{"natural":"water"}},"w41":{"id":"w41","nodes":["n194","n195","n196","n197","n198","n199","n200","n201","n202","n203","n204","n205","n194"],"tags":{"building":"house"}},"w410":{"id":"w410","nodes":["n1868","n2088"],"tags":{"bridge":"yes","name":"Conrail Railroad","railway":"rail"}},"w411":{"id":"w411","nodes":["n2010","n2019","n2009","n2008","n2058","n2035","n1961","n1962","n1947","n1963"],"tags":{"highway":"footway"}},"w412":{"id":"w412","nodes":["n2290","n2043","n2044","n2045","n1872","n2041","n1873","n2042","n1874","n2046","n2047","n2048","n2049","n2290"],"tags":{"addr:city":"Three Rivers","addr:housenumber":"112","addr:postcode":"49093","addr:state":"MI","addr:street":"Spring Street","leisure":"park","name":"Scidmore Park"}},"w413":{"id":"w413","nodes":["n1831","n876","n4720","n821","n2089"],"tags":{"highway":"residential","name":"Andrews Street"}},"w414":{"id":"w414","nodes":["n2002","n2003","n2004","n2005","n2006","n2007"],"tags":{"highway":"footway"}},"w415":{"id":"w415","nodes":["n1979","n1980","n1981","n1982","n1979"],"tags":{"amenity":"parking"}},"w416":{"id":"w416","nodes":["n2054","n2055","n2056","n2057","n2054"],"tags":{"amenity":"shelter","shelter_type":"picnic_shelter"}},"w417":{"id":"w417","nodes":["n2291","n2292","n2293","n2294","n2295","n2296","n2297","n2298","n2299","n1098","n2300","n2301","n2302","n2303","n2304","n2059","n2060","n2305","n2307","n2306","n2310","n2308","n2309","n2291"],"tags":{"leisure":"park","name":"Memory Isle Park"}},"w418":{"id":"w418","nodes":["n2033","n2034","n2035"],"tags":{"highway":"footway"}},"w419":{"id":"w419","nodes":["n1983","n1984","n1985","n1986","n1983"],"tags":{"amenity":"parking"}},"w42":{"id":"w42","nodes":["n206","n207","n208","n209","n210","n211","n206"],"tags":{"building":"house"}},"w420":{"id":"w420","nodes":["n1840","n4746","n4748","n1847","n4749","n4755","n1838","n4754","n4756","n1849"],"tags":{"highway":"residential","name":"French Street"}},"w421":{"id":"w421","nodes":["n2337","n2268"],"tags":{"highway":"path"}},"w422":{"id":"w422","nodes":["n2338","n2339","n2320","n2317","n2319","n2318","n2340","n2341","n2342","n2343","n2344","n2345","n2346","n2347","n2348","n2338"],"tags":{"natural":"water"}},"w423":{"id":"w423","nodes":["n2180","n2349","n2350","n2351","n2352","n2404","n2353","n2354","n2355","n2356","n2357","n2358","n2359","n2360","n2361","n2362","n2363","n2364","n2365","n2366","n2370","n2371","n2372","n2373","n2374","n2375","n2377","n2378","n2380","n2381","n2382","n2383","n2386","n2389","n2390","n2391","n2392","n2393","n2396","n2397","n2401","n2402","n2321","n2322","n2323","n2403","n2180"],"tags":{"natural":"wetland"}},"w424":{"id":"w424","nodes":["n2324","n2316","n1841","n2315","n2314","n1844","n1839","n4758","n1845"],"tags":{"highway":"residential","name":"Pealer Street"}},"w425":{"id":"w425","nodes":["n2267","n2337","n2336","n2335","n2334","n2333","n2332","n2331","n2330","n37","n2329","n2328","n2327","n36","n2326","n2325","n2266"],"tags":{"highway":"path","name":"Riverwalk Trail"}},"w426":{"id":"w426","nodes":["n2478","n681","n680","n679","n2459","n2467","n2487","n2478"],"tags":{"building":"yes"}},"w427":{"id":"w427","nodes":["n2671","n2672","n2673","n2674","n2671"],"tags":{"building":"yes"}},"w428":{"id":"w428","nodes":["n2483","n2482","n2486","n2489","n2492","n2502","n2495","n2480","n2483"],"tags":{"building":"yes"}},"w429":{"id":"w429","nodes":["n2707","n2708","n2716","n2712","n2714","n2713","n2715","n2711","n2710","n2723","n2709","n2707"],"tags":{"amenity":"parking"}},"w43":{"id":"w43","nodes":["n1955","n1956"],"tags":{"footway":"sidewalk","highway":"footway","name":"Riverwalk Trail"}},"w430":{"id":"w430","nodes":["n2471","n2474","n2484","n2479","n2471"],"tags":{"building":"yes"}},"w431":{"id":"w431","nodes":["n2218","n2434","n2436","n2433","n2435","n2210"],"tags":{"name":"Rocky River","waterway":"river"}},"w432":{"id":"w432","nodes":["n2782","n2532","n2783","n2784","n2782"],"tags":{"amenity":"parking"}},"w433":{"id":"w433","nodes":["n2513","n649","n2520","n2514","n2507","n2513"],"tags":{"building":"yes"}},"w434":{"id":"w434","nodes":["n2470","n2468","n2461","n2465","n2470"],"tags":{"building":"yes"}},"w435":{"id":"w435","nodes":["n2598","n2599","n648","n649","n2520","n2598"],"tags":{"building":"yes"}},"w436":{"id":"w436","nodes":["n2639","n2640","n2641","n2642","n2643","n2644","n2645","n2646","n2647","n2648","n2639"],"tags":{"building":"yes"}},"w437":{"id":"w437","nodes":["n2503","n2512","n2508","n2499","n2503"],"tags":{"building":"yes"}},"w438":{"id":"w438","nodes":["n2440","n2800","n2774","n1"],"tags":{"highway":"residential","name":"Water Street"}},"w439":{"id":"w439","nodes":["n2675","n2676","n2677","n2678","n2675"],"tags":{"building":"yes"}},"w44":{"id":"w44","nodes":["n213","n214","n215","n216","n213"],"tags":{"building":"yes"}},"w440":{"id":"w440","nodes":["n2512","n2503","n2507","n2514","n2512"],"tags":{"building":"yes"}},"w441":{"id":"w441","nodes":["n2554","n2717","n674","n2720","n2798"],"tags":{"highway":"service","oneway":"yes"}},"w442":{"id":"w442","nodes":["n2583","n2596","n2584","n2585","n2595","n2586","n2587","n2588","n2589","n2583"],"tags":{"amenity":"parking"}},"w443":{"id":"w443","nodes":["n2629","n2627","n2628","n2616","n2630","n2629"],"tags":{"building":"yes"}},"w444":{"id":"w444","nodes":["n2717","n2724","n670","n2718","n669","n668","n2722","n2727"],"tags":{"highway":"service","oneway":"yes","service":"parking_aisle"}},"w445":{"id":"w445","nodes":["n2572","n2573"],"tags":{"bridge":"yes","highway":"path","name":"Riverwalk Trail"}},"w446":{"id":"w446","nodes":["n2603","n2604","n2601","n2605","n2606","n2607","n2603"],"tags":{"building":"yes"}},"w447":{"id":"w447","nodes":["n2780","n2777","n628","n624","n2779"],"tags":{"highway":"residential","name":"Foster Street","oneway":"yes"}},"w448":{"id":"w448","nodes":["n2733","n2734","n2735","n2736","n2737","n2738","n663","n664","n2739","n2733"],"tags":{"building":"yes"}},"w449":{"id":"w449","nodes":["n2564","n2565","n2566","n2567","n2568","n2794","n2795","n2564"],"tags":{"amenity":"parking"}},"w45":{"id":"w45","nodes":["n217","n218","n219","n220","n217"],"tags":{"amenity":"shelter","shelter_type":"picnic_shelter"}},"w450":{"id":"w450","nodes":["n2799","n2728","n2729","n2730","n2731","n2732","n2799"],"tags":{"building":"yes"}},"w451":{"id":"w451","nodes":["n2441","n1170","n2442","n2575","n2443","n2445","n2444","n2448","n2441"],"tags":{"amenity":"parking"}},"w452":{"id":"w452","nodes":["n2273","n457","n2569","n458","n2570"],"tags":{"highway":"path","name":"Riverwalk Trail"}},"w453":{"id":"w453","nodes":["n2447","n2242","n2448","n2527","n2530"],"tags":{"highway":"service"}},"w454":{"id":"w454","nodes":["n2560","n333","n2561"],"tags":{"highway":"service","service":"parking_aisle"}},"w455":{"id":"w455","nodes":["n2679","n2680","n2681","n2682","n2683","n2684","n2685","n2686","n2687","n2688","n2689","n2690","n2679"],"tags":{"building":"yes"}},"w456":{"id":"w456","nodes":["n2425","n2429","n2424"],"tags":{"bridge":"yes","highway":"residential","name":"Moore Street"}},"w457":{"id":"w457","nodes":["n2487","n2467","n2472","n2480","n2495","n2487"],"tags":{"building":"yes"}},"w458":{"id":"w458","nodes":["n2659","n2660","n2661","n2662","n678","n677","n2663","n2664","n2665","n2666","n675","n676","n2659"],"tags":{"building":"yes"}},"w459":{"id":"w459","nodes":["n2600","n2598","n2599","n2601","n2605","n2602","n2600"],"tags":{"building":"yes"}},"w46":{"id":"w46","nodes":["n221","n222","n223","n224","n221"],"tags":{"amenity":"shelter","shelter_type":"picnic_shelter"}},"w460":{"id":"w460","nodes":["n2468","n2464","n2455","n2457","n2461","n2468"],"tags":{"building":"yes"}},"w461":{"id":"w461","nodes":["n2478","n2473","n683","n682","n2463","n681","n2478"],"tags":{"building":"yes"}},"w462":{"id":"w462","nodes":["n2547","n473","n2548","n2549"],"tags":{"highway":"service","service":"parking_aisle"}},"w463":{"id":"w463","nodes":["n2573","n2574"],"tags":{"highway":"path","name":"Riverwalk Trail"}},"w464":{"id":"w464","nodes":["n2445","n2597","n2527","n2528","n2529","n2530","n2531","n2597"],"tags":{"highway":"service","service":"parking_aisle"}},"w465":{"id":"w465","nodes":["n2571","n459","n2572"],"tags":{"highway":"path","name":"Riverwalk Trail"}},"w466":{"id":"w466","nodes":["n2445","n2574","n2552","n442","n2551","n4727","n323","n2446"],"tags":{"highway":"service"}},"w467":{"id":"w467","nodes":["n2484","n2474","n2477","n2485","n2488","n2484"],"tags":{"building":"yes"}},"w468":{"id":"w468","nodes":["n2695","n2696","n2697","n2698","n2699","n2700","n2701","n2702","n2695"],"tags":{"building":"yes"}},"w469":{"id":"w469","nodes":["n2469","n2476","n2481","n2475","n920","n2466","n2469"],"tags":{"building":"yes"}},"w47":{"id":"w47","nodes":["n1988","n1997","n1989","n25","n24","n1990","n26","n1991","n21","n1992","n2006","n1993","n22","n1994","n23","n1995","n1999","n1996","n2001","n1988"],"tags":{"highway":"service"}},"w470":{"id":"w470","nodes":["n2473","n2470","n2465","n2458","n2462","n683","n2473"],"tags":{"building":"yes"}},"w471":{"id":"w471","nodes":["n2490","n2496","n994","n997","n998","n996","n995","n2485","n2477","n2490"],"tags":{"building":"yes"}},"w472":{"id":"w472","nodes":["n2424","n2426","n2427","n2428"],"tags":{"highway":"residential","name":"Moore Street"}},"w473":{"id":"w473","nodes":["n2432","n1026","n4741","n2554","n2425"],"tags":{"highway":"residential","name":"Moore Street"}},"w474":{"id":"w474","nodes":["n2577","n2576"],"tags":{"bridge":"yes","highway":"footway"}},"w475":{"id":"w475","nodes":["n2497","n2505","n2500","n2493","n2497"],"tags":{"building":"yes"}},"w476":{"id":"w476","nodes":["n2493","n2500","n2501","n2496","n2490","n2493"],"tags":{"building":"yes"}},"w477":{"id":"w477","nodes":["n2431","n360","n4726","n418","n397","n396","n2547","n646","n2447","n644","n2418","n424","n640","n2419","n2420","n2423"],"tags":{"highway":"residential","name":"Railroad Drive"}},"w478":{"id":"w478","nodes":["n2515","n2511","n2498","n2504","n2509","n2515"],"tags":{"building":"yes"}},"w479":{"id":"w479","nodes":["n2525","n651","n650","n2526","n2524","n653","n652","n656","n2523","n654","n2518","n2517","n2521","n2522","n2525"],"tags":{"building":"yes"}},"w48":{"id":"w48","nodes":["n225","n237","n226","n227","n228","n229","n230","n231","n232","n233","n234","n235","n236","n225"],"tags":{"building":"yes"}},"w480":{"id":"w480","nodes":["n2703","n2704","n2710","n2711","n2705","n2706","n2703"],"tags":{"amenity":"parking"}},"w481":{"id":"w481","nodes":["n2796","n2657","n2658","n2797","n2796"],"tags":{"building":"yes"}},"w482":{"id":"w482","nodes":["n2550","n2551","n442","n2552","n2553","n2550"],"tags":{"amenity":"parking"}},"w483":{"id":"w483","nodes":["n2790","n2542"],"tags":{"highway":"service","service":"parking_aisle"}},"w484":{"id":"w484","nodes":["n2311","n1102"],"tags":{"highway":"service"}},"w485":{"id":"w485","nodes":["n2515","n2509","n2516","n2519","n2515"],"tags":{"building":"yes"}},"w486":{"id":"w486","nodes":["n2506","n2502","n2492","n2491","n2494","n2506"],"tags":{"building":"yes"}},"w487":{"id":"w487","nodes":["n2667","n2668","n2669","n2670","n2667"],"tags":{"building":"yes"}},"w488":{"id":"w488","nodes":["n2616","n2608","n2617","n2618","n2619","n2620","n2621","n2622","n2623","n2624","n2625","n2626","n2627","n2628","n2616"],"tags":{"building":"yes"}},"w489":{"id":"w489","nodes":["n2081","n2430"],"tags":{"bridge":"yes","highway":"primary","name":"Michigan Avenue"}},"w49":{"id":"w49","nodes":["n237","n238"],"tags":{"highway":"footway"}},"w490":{"id":"w490","nodes":["n2410","n636","n730","n635","n2409","n2694","n2751","n2765","n2753","n2768","n2754","n2769","n2745","n2766","n4503","n2763","n4501","n2752","n2781"],"tags":{"highway":"residential","name":"Portage Avenue"}},"w491":{"id":"w491","nodes":["n2578","n2579","n2580","n2581","n2578"],"tags":{"amenity":"shelter","building":"yes","shelter_type":"picnic_shelter"}},"w492":{"id":"w492","nodes":["n2556","n2557","n2558","n2559","n2556"],"tags":{"amenity":"parking"}},"w493":{"id":"w493","nodes":["n2460","n2456","n687","n2453","n2454","n2460"],"tags":{"building":"yes"}},"w494":{"id":"w494","nodes":["n2471","n2479","n2476","n2469","n2471"],"tags":{"building":"yes"}},"w495":{"id":"w495","nodes":["n2724","n2725","n673","n672","n671","n2726","n2727"],"tags":{"highway":"service","oneway":"yes","service":"parking_aisle"}},"w496":{"id":"w496","nodes":["n2649","n2650","n2651","n2652","n2653","n2654","n2655","n2656","n2649"],"tags":{"building":"yes"}},"w497":{"id":"w497","nodes":["n2430","n2446","n343","n2101","n2560","n2431","n363","n2748"],"tags":{"highway":"primary","name":"Michigan Avenue"}},"w498":{"id":"w498","nodes":["n2691","n2692","n634","n633","n2693","n2694"],"tags":{"highway":"service"}},"w499":{"id":"w499","nodes":["n2423","n2415","n661","n2416","n2417","n2719","n2721","n2772","n2756","n2773","n2759","n2767"],"tags":{"highway":"residential","name":"West Street"}},"w5":{"id":"w5","nodes":["n380","n381","n382","n383","n429","n430","n380"],"tags":{"building":"yes"}},"w50":{"id":"w50","nodes":["n239","n499","n508","n245","n238","n242","n240"],"tags":{"footway":"sidewalk","highway":"footway"}},"w500":{"id":"w500","nodes":["n2428","n1152","n2421","n2324"],"tags":{"bridge":"yes","highway":"residential","name":"Moore Street"}},"w501":{"id":"w501","nodes":["n2608","n2609","n2610","n2611","n2612","n2613","n2614","n2615","n2617","n2608"],"tags":{"building":"yes"}},"w502":{"id":"w502","nodes":["n2570","n2571"],"tags":{"bridge":"yes","highway":"path","name":"Riverwalk Trail"}},"w503":{"id":"w503","nodes":["n2540","n2542","n2787"],"tags":{"highway":"service"}},"w504":{"id":"w504","nodes":["n2269","n2582","n2250"],"tags":{"highway":"path"}},"w505":{"id":"w505","nodes":["n2631","n2632","n2633","n2634","n2635","n2636","n2637","n2638","n2631"],"tags":{"building":"yes"}},"w506":{"id":"w506","nodes":["n2543","n2544","n2545","n395","n2546","n2543"],"tags":{"amenity":"parking"}},"w507":{"id":"w507","nodes":["n2449","n2450","n2451","n2452","n1162","n2449"],"tags":{"leisure":"pitch","sport":"tennis"}},"w508":{"id":"w508","nodes":["n2554","n1160","n2559","n2558","n659","n2555","n658","n657","n2419"],"tags":{"highway":"service"}},"w509":{"id":"w509","nodes":["n2499","n2508","n2510","n2505","n2497","n2499"],"tags":{"building":"yes"}},"w51":{"id":"w51","nodes":["n241","n242","n243","n244"],"tags":{"highway":"service","surface":"unpaved"}},"w510":{"id":"w510","nodes":["n2575","n2577"],"tags":{"highway":"footway"}},"w511":{"id":"w511","nodes":["n2533","n2534","n2535","n2536","n2537","n2538","n2539","n2785","n2786","n2533"],"tags":{"amenity":"parking"}},"w512":{"id":"w512","nodes":["n2801","n2740","n2741","n2742","n2743","n2744","n2801"],"tags":{"building":"yes"}},"w513":{"id":"w513","nodes":["n2720","n2721"],"tags":{"highway":"service","service":"parking_aisle"}},"w514":{"id":"w514","nodes":["n2788","n2790","n2789","n989","n2540","n2541"],"tags":{"highway":"service","service":"parking_aisle"}},"w515":{"id":"w515","nodes":["n2848","n2849","n2850","n2851","n2803","n2804","n2812"],"tags":{"highway":"residential","name":"Middle Street"}},"w516":{"id":"w516","nodes":["n2852","n2805"],"tags":{"access":"private","highway":"service","name":"Battle Street"}},"w517":{"id":"w517","nodes":["n2863","n2815","n2814","n2812","n2864","n2855","n2865","n2867","n2868"],"tags":{"highway":"secondary","name":"Michigan Avenue","name_1":"State Highway 60","ref":"M 60"}},"w518":{"id":"w518","nodes":["n2859","n2808"],"tags":{"highway":"residential","name":"2nd Avenue"}},"w519":{"id":"w519","nodes":["n2823","n2824","n2825","n2826","n2827","n2828","n2823"],"tags":{"building":"yes"}},"w52":{"id":"w52","nodes":["n247","n248","n249","n250","n247"],"tags":{"amenity":"parking"}},"w520":{"id":"w520","nodes":["n2806","n2807","n2803"],"tags":{"highway":"residential","name":"2nd Avenue"}},"w521":{"id":"w521","nodes":["n2829","n2830","n2831","n2832","n2833","n2834","n2835","n2836","n2837","n2838","n2829"],"tags":{"building":"yes"}},"w522":{"id":"w522","nodes":["n2815","n2813","n2811","n4597","n2846","n4596","n2857","n4601","n2853","n4602","n2861","n4","n2879","n4560","n3550","n5","n1685"],"tags":{"highway":"residential","name":"Washington Street"}},"w523":{"id":"w523","nodes":["n2878","n2811","n2810","n2860","n2880","n2881","n2882"],"tags":{"highway":"residential","name":"5th Avenue"}},"w524":{"id":"w524","nodes":["n2816","n2817","n2818","n2819","n2820","n2821","n2822","n2816"],"tags":{"building":"yes"}},"w525":{"id":"w525","nodes":["n2869","n2856","n2806","n2808","n2814","n2809","n2810","n2847","n2858","n2854","n2870","n2871","n6","n2872","n2839","n2862"],"tags":{"highway":"residential","name":"Wood Street"}},"w526":{"id":"w526","nodes":["n2877","n2809","n2813","n2844","n2843"],"tags":{"highway":"residential","name":"4th Avenue"}},"w527":{"id":"w527","nodes":["n4785","n4784","n2936","n4788","n4787","n4786","n4785"],"tags":{"amenity":"parking"}},"w528":{"id":"w528","nodes":["n2864","n2892","n2893","n2877","n2860","n3840"],"tags":{"highway":"residential","name":"Garden Street"}},"w529":{"id":"w529","nodes":["n2868","n2890"],"tags":{"bridge":"yes","highway":"secondary","name":"Michigan Avenue","name_1":"State Highway 60","ref":"M 60"}},"w53":{"id":"w53","nodes":["n251","n252","n253","n254","n255","n256","n257","n258","n259","n260","n261","n262","n251"],"tags":{"building":"yes"}},"w530":{"id":"w530","nodes":["n2914","n2915","n2916","n2917","n2918","n2919","n2920","n2921","n2922","n2923","n2924","n2925","n2926","n2927","n2928","n2929","n2930","n2931","n2932","n2933","n2914"],"tags":{"building":"yes"}},"w531":{"id":"w531","nodes":["n2958","n2896"],"tags":{"bridge":"yes","highway":"secondary","name":"Main Street"}},"w532":{"id":"w532","nodes":["n2896","n394","n364","n2748"],"tags":{"highway":"secondary","name":"Main Street"}},"w533":{"id":"w533","nodes":["n2800","n2943","n2940","n2941","n2942","n2943"],"tags":{"highway":"service","service":"parking_aisle"}},"w534":{"id":"w534","nodes":["n3836","n3837","n3839","n3838","n3834","n4632","n3831","n4624","n3835","n3836"],"tags":{"barrier":"fence"}},"w535":{"id":"w535","nodes":["n2894","n2944","n2774","n2765"],"tags":{"highway":"residential","name":"5th Avenue"}},"w536":{"id":"w536","nodes":["n2890","n2780","n627","n2889","n2887","n623","n2888","n366","n2748"],"tags":{"highway":"secondary","name":"Michigan Avenue","name_1":"State Highway 60","ref":"M 60"}},"w537":{"id":"w537","nodes":["n2895","n738","n2887","n737","n2913"],"tags":{"highway":"residential","name":"Water Street"}},"w538":{"id":"w538","nodes":["n2855","n3756","n2884","n2885","n2886","n2945","n2946","n2947","n2948","n2949","n2950","n2951","n2952","n2953","n2955","n2848","n2956","n2856"],"tags":{"highway":"residential","name":"River Drive"}},"w539":{"id":"w539","nodes":["n2882","n2894"],"tags":{"bridge":"yes","highway":"residential","name":"5th Avenue"}},"w54":{"id":"w54","nodes":["n263","n264","n265","n266","n267","n268","n269","n270","n271","n272","n273","n274","n275","n276","n263"],"tags":{"building":"yes"}},"w540":{"id":"w540","nodes":["n2987","n2964","n2981","n2983","n2966","n2982","n2962","n2960","n2967","n2965","n2984","n2977","n2968","n2976","n2986","n2988","n2963","n2970","n2969","n2979","n2974","n2980","n2959","n2973","n2985","n2961","n2975","n2971","n2972","n2978","n2898","n2907","n2912","n2909","n2911","n2901","n2903","n2904","n2906","n2902","n2900","n2910","n2908","n2899","n2897","n2905","n2186","n2233"],"tags":{"name":"Portage River","waterway":"river"}},"w541":{"id":"w541","nodes":["n2852","n2851","n3003"],"tags":{"highway":"residential","name":"1st Avenue"}},"w542":{"id":"w542","nodes":["n2991","n3004","n2994"],"tags":{"highway":"residential","name":"River Street"}},"w543":{"id":"w543","nodes":["n2993","n2989"],"tags":{"bridge":"yes","highway":"residential","name":"6th Street"}},"w544":{"id":"w544","nodes":["n2995","n2996","n2997","n2998","n2999","n3000","n3001","n3002","n2990","n2991","n2993"],"tags":{"highway":"residential","name":"6th Street"}},"w545":{"id":"w545","nodes":["n2989","n2992","n2848"],"tags":{"highway":"residential","name":"6th Street"}},"w546":{"id":"w546","nodes":["n2313","n3169","n3170","n3171","n3172","n3173","n3174","n3175","n3176","n3177","n3178","n3179","n3180","n3191","n3181","n3190","n3182","n3183","n3184","n3185","n3186","n3187","n3188","n3189","n3160","n3161","n3162","n2126","n2146","n2156","n2129","n2112","n2109","n2313"],"tags":{"natural":"wetland"}},"w547":{"id":"w547","nodes":["n2088","n3013","n3015","n3014","n3017","n3018"],"tags":{"name":"Conrail Railroad","railway":"rail"}},"w548":{"id":"w548","nodes":["n3083","n3084","n3085","n3086","n3083"],"tags":{"building":"yes"}},"w549":{"id":"w549","nodes":["n3020","n2288","n2283","n2284","n2131","n2286","n2287","n2285","n2132","n2140","n2289","n3020"],"tags":{"leisure":"park","name":"Conservation Park"}},"w55":{"id":"w55","nodes":["n277","n278","n279","n280","n281","n282","n283","n284","n277"],"tags":{"building":"yes"}},"w550":{"id":"w550","nodes":["n3056","n3042","n3041","n3040","n3039","n3038","n3037","n3036","n3044","n3035","n3034","n3043","n3016","n3056","n3019","n3015","n3012"],"tags":{"highway":"service"}},"w551":{"id":"w551","nodes":["n3044","n3045","n3046","n3047","n3048","n3049","n3050","n3051","n3052","n3053","n3054","n3055","n3016"],"tags":{"highway":"footway"}},"w552":{"id":"w552","nodes":["n3117","n3118","n3119","n3120","n3121","n3122","n3117"],"tags":{"building":"yes"}},"w553":{"id":"w553","nodes":["n3123","n3124","n3129","n3125","n3126","n3123"],"tags":{"building":"yes"}},"w554":{"id":"w554","nodes":["n3069","n3070","n3071","n3072","n3073","n3074","n3075","n3076","n3077","n3078","n3079","n3080","n3081","n3082","n3069"],"tags":{"building":"yes"}},"w555":{"id":"w555","nodes":["n3087","n3088","n3089","n3090","n3087"],"tags":{"building":"yes"}},"w556":{"id":"w556","nodes":["n3113","n3114","n3115","n3116","n3113"],"tags":{"building":"yes"}},"w557":{"id":"w557","nodes":["n3103","n3104","n3105","n3106","n3103"],"tags":{"building":"yes"}},"w558":{"id":"w558","nodes":["n3127","n3128","n3129","n3124","n3127"],"tags":{"building":"yes"}},"w559":{"id":"w559","nodes":["n3137","n3141","n3142","n3138","n3139","n3140","n3137"],"tags":{"building":"yes"}},"w56":{"id":"w56","nodes":["n285","n286","n287","n288","n285"],"tags":{"amenity":"parking"}},"w560":{"id":"w560","nodes":["n3091","n3092","n3093","n3094","n3091"],"tags":{"building":"yes"}},"w561":{"id":"w561","nodes":["n3155","n3157","n3158","n3159","n3156","n3155"],"tags":{"building":"yes"}},"w562":{"id":"w562","nodes":["n3057","n3058","n3059","n3060","n3057"],"tags":{"building":"yes"}},"w563":{"id":"w563","nodes":["n3107","n3108","n3109","n3110","n3111","n3112","n3107"],"tags":{"building":"yes"}},"w564":{"id":"w564","nodes":["n3134","n3135","n3136","n3131","n3134"],"tags":{"building":"yes"}},"w565":{"id":"w565","nodes":["n3143","n3144","n3145","n3146","n3143"],"tags":{"building":"yes"}},"w566":{"id":"w566","nodes":["n3095","n3096","n3097","n3098","n3095"],"tags":{"building":"yes"}},"w567":{"id":"w567","nodes":["n3130","n3131","n3136","n3132","n3133","n3130"],"tags":{"building":"yes"}},"w568":{"id":"w568","nodes":["n3025","n3026","n3027","n3028","n3029","n3030","n3031","n3033","n3032","n3025"],"tags":{"amenity":"parking"}},"w569":{"id":"w569","nodes":["n3061","n3062","n3063","n3064","n3061"],"tags":{"building":"yes"}},"w57":{"id":"w57","nodes":["n289","n290","n291","n292","n289"],"tags":{"amenity":"parking"}},"w570":{"id":"w570","nodes":["n3155","n3156","n3152","n3153","n3155"],"tags":{"building":"yes"}},"w571":{"id":"w571","nodes":["n3099","n3100","n3101","n3102","n3099"],"tags":{"building":"yes"}},"w572":{"id":"w572","nodes":["n3147","n3148","n3149","n3150","n3147"],"tags":{"building":"yes"}},"w573":{"id":"w573","nodes":["n3039","n2284"],"tags":{"highway":"service"}},"w574":{"id":"w574","nodes":["n3151","n3152","n3153","n3154","n3151"],"tags":{"building":"yes"}},"w575":{"id":"w575","nodes":["n3021","n3022","n3023","n3024","n3021"],"tags":{"amenity":"shelter","shelter_type":"picnic_shelter"}},"w576":{"id":"w576","nodes":["n3065","n3066","n3067","n3068","n3065"],"tags":{"building":"yes"}},"w577":{"id":"w577","nodes":["n2944","n3192","n3757","n3813","n3814","n3815","n3816","n3817","n3818","n3819"],"tags":{"highway":"service","name":"Willow Drive","service":"driveway","surface":"unpaved"}},"w578":{"id":"w578","nodes":["n2163","n2165","n2166","n2167","n2168","n2172","n2173","n2174","n2175","n2176","n2178","n2181","n2163"],"tags":{"building":"yes"}},"w579":{"id":"w579","nodes":["n2754","n3195","n3204","n3205","n4537","n4540","n3206","n4530","n4536","n3207","n4524","n3199","n4521","n3197","n1032"],"tags":{"highway":"residential","name":"Elm Street"}},"w58":{"id":"w58","nodes":["n240","n293","n294"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w580":{"id":"w580","nodes":["n2184","n2185","n2187","n2190","n2191","n2192","n2184"],"tags":{"building":"yes"}},"w581":{"id":"w581","nodes":["n2765","n3208","n3211","n2755","n3280","n2756","n3346"],"tags":{"highway":"residential","name":"Kelsey Street"}},"w582":{"id":"w582","nodes":["n2753","n3194","n3193","n3201","n3196","n4551","n3202","n4550","n3203","n3200","n3198","n1033"],"tags":{"highway":"residential","name":"Walnut Street"}},"w583":{"id":"w583","nodes":["n3272","n4469","n4588","n2879","n4564","n2872"],"tags":{"highway":"residential","name":"10th Avenue"}},"w584":{"id":"w584","nodes":["n3243","n3242","n3241","n3240","n3243"],"tags":{"building":"industrial"}},"w585":{"id":"w585","nodes":["n3273","n3274","n4631","n4593","n3275","n4592","n2846","n4611","n2847"],"tags":{"highway":"residential","name":"6th Avenue"}},"w586":{"id":"w586","nodes":["n3276","n4591","n2853","n4605","n2854"],"tags":{"highway":"residential","name":"8th Avenue"}},"w587":{"id":"w587","nodes":["n3269","n3268","n3267","n3266","n3265","n3264","n3263","n3262","n3269"],"tags":{"building":"industrial"}},"w588":{"id":"w588","nodes":["n3277","n4599","n2857","n4598","n4608","n2858"],"tags":{"highway":"residential","name":"7th Avenue"}},"w589":{"id":"w589","nodes":["n3239","n3238","n3271","n3270","n3237","n3236","n3235","n3234","n3239"],"tags":{"building":"yes"}},"w59":{"id":"w59","nodes":["n294","n295","n296","n297","n298","n299","n300","n301","n302","n303","n491","n304","n305","n306","n307"],"tags":{"footway":"sidewalk","highway":"footway"}},"w590":{"id":"w590","nodes":["n3278","n4458","n4589","n4604","n2861"],"tags":{"highway":"residential","name":"9th Avenue"}},"w591":{"id":"w591","nodes":["n3253","n3252","n3251","n3250","n3249","n3248","n3253"],"tags":{"building":"industrial"}},"w592":{"id":"w592","nodes":["n3229","n3228","n3227","n3226","n3225","n3224","n3223","n3222","n3221","n3220","n3219","n3218","n3217","n3216","n3215","n3214","n3213","n3212","n3229"],"tags":{"natural":"water","water":"pond"}},"w593":{"id":"w593","nodes":["n3261","n3260","n3259","n3258","n3257","n3256","n3255","n3254","n3261"],"tags":{"building":"industrial"}},"w594":{"id":"w594","nodes":["n3233","n3232","n3231","n3230","n3233"],"tags":{"building":"yes"}},"w595":{"id":"w595","nodes":["n3247","n3246","n3245","n3244","n3247"],"tags":{"building":"industrial"}},"w596":{"id":"w596","nodes":["n2769","n3195","n3193","n3209","n2758","n2759","n3279"],"tags":{"highway":"residential","name":"Armitage Street"}},"w597":{"id":"w597","nodes":["n2193","n2194","n2195","n2197","n2193"],"tags":{"building":"yes"}},"w598":{"id":"w598","nodes":["n3404","n3403","n3402","n3401","n3400","n3399","n3398","n3397","n3373","n3372","n3396","n3395","n3404"],"tags":{"building":"school"}},"w6":{"id":"w6","nodes":["n879","n880","n881","n882","n879"],"tags":{"building":"shed"}},"w60":{"id":"w60","nodes":["n239","n308","n307"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w600":{"id":"w600","nodes":["n3387","n3386","n3316","n3315","n3314","n3313","n3387"],"tags":{"building":"yes"}},"w601":{"id":"w601","nodes":["n3304","n3303","n3302","n3301","n3385","n3384","n3300","n3299","n3304"],"tags":{"building":"yes"}},"w602":{"id":"w602","nodes":["n3334","n3333","n3332","n3331","n3330","n3329","n3328","n3327","n3326","n3325","n3324","n3323","n3322","n3321","n3320","n3319","n3318","n3317","n3334"],"tags":{"building":"yes"}},"w603":{"id":"w603","nodes":["n3353","n3352","n3347","n3280","n2798"],"tags":{"highway":"service","service":"alley","surface":"unpaved"}},"w604":{"id":"w604","nodes":["n3753","n3211","n3383"],"tags":{"highway":"service","service":"alley"}},"w605":{"id":"w605","nodes":["n3290","n3289","n3288","n3287","n3286","n3285","n3284","n3283","n3282","n3281","n3290"],"tags":{"building":"yes"}},"w606":{"id":"w606","nodes":["n2198","n2199","n2201","n2202","n2203","n2206","n2198"],"tags":{"building":"yes"}},"w607":{"id":"w607","nodes":["n2198","n2207"],"tags":{"barrier":"wall"}},"w608":{"id":"w608","nodes":["n2751","n3208","n3210","n3209","n3415","n3410","n3414","n3413","n3412","n3416"],"tags":{"highway":"residential","name":"East Street"}},"w609":{"id":"w609","nodes":["n2772","n3346","n3746","n3748","n3747","n3345","n3378","n3279","n3411"],"tags":{"highway":"residential","name":"Maple Street"}},"w61":{"id":"w61","nodes":["n309","n310","n311","n312","n313","n240"],"tags":{"footway":"sidewalk","highway":"footway"}},"w610":{"id":"w610","nodes":["n3379","n3380","n3382","n3381","n3379"],"tags":{"leisure":"park","name":"LaFayette Park"}},"w611":{"id":"w611","nodes":["n2768","n3194","n3210","n3753","n2760","n3353","n2773","n3378"],"tags":{"highway":"residential","name":"Bennett Street"}},"w612":{"id":"w612","nodes":["n2751","n3383","n2749","n2798","n2772"],"tags":{"highway":"residential","name":"Market Street"}},"w613":{"id":"w613","nodes":["n3298","n3297","n3296","n3295","n3294","n3293","n3292","n3291","n3298"],"tags":{"building":"yes"}},"w614":{"id":"w614","nodes":["n3375","n3406","n3405","n3374","n3375"],"tags":{"leisure":"playground"}},"w615":{"id":"w615","nodes":["n3393","n3344","n3343","n3342","n3341","n3340","n3339","n3338","n3337","n3392","n3391","n3390","n3389","n3336","n3335","n3388","n3393"],"tags":{"building":"yes"}},"w616":{"id":"w616","nodes":["n3376","n3407","n3408","n3377","n3376"],"tags":{"amenity":"school","name":"Three Rivers Elementary School"}},"w617":{"id":"w617","nodes":["n3312","n3311","n3310","n3309","n3308","n3307","n3306","n3305","n3312"],"tags":{"building":"yes"}},"w619":{"id":"w619","nodes":["n2863","n3424","n3425","n3426","n3427","n3428","n3429","n3430","n3431","n3432","n3433","n2844"],"tags":{"highway":"secondary","name":"Michigan Avenue","ref":"M 60"}},"w62":{"id":"w62","nodes":["n876","n906","n904","n875","n874","n873","n872","n871","n870","n869","n41","n868","n146","n314","n315","n1956"],"tags":{"footway":"sidewalk","highway":"footway"}},"w620":{"id":"w620","nodes":["n2844","n3420","n3421","n3422","n3439","n2859","n3437","n3493","n3496","n3500","n3497"],"tags":{"highway":"residential"}},"w621":{"id":"w621","nodes":["n3468","n3469","n3470","n3471","n3468"],"tags":{"building":"yes"}},"w622":{"id":"w622","nodes":["n3417","n3436","n3438","n3491","n3488","n3492","n3495","n3494","n3498","n3487","n3499","n3490","n3489","n4800","n3417"],"tags":{"landuse":"cemetery","name":"Riverside Cemetery"}},"w623":{"id":"w623","nodes":["n3440","n3441","n3442","n3443","n3444","n3445","n3440"],"tags":{"building":"yes"}},"w624":{"id":"w624","nodes":["n3446","n3447","n3448","n3449","n3450","n3451","n3452","n3453","n3454","n3455","n3456","n3457","n3458","n3459","n3460","n3461","n3462","n3463","n3464","n3465","n3466","n3467","n3446"],"tags":{"building":"yes"}},"w625":{"id":"w625","nodes":["n2844","n3434","n3435","n2878","n3275","n4621","n3276","n3278","n4463","n3272","n3472","n3474","n3475","n3476","n3477","n3478","n1202","n3479","n3480","n3481","n1203","n3482","n3483","n3484","n3485","n4574","n3486","n3473"],"tags":{"highway":"secondary","name":"Jefferson Street","name_1":"State Highway 60","ref":"M 60"}},"w626":{"id":"w626","nodes":["n3439","n3423","n2863"],"tags":{"highway":"unclassified","name":"Michigan Avenue","name_1":"State Highway 60"}},"w627":{"id":"w627","nodes":["n3500","n3005"],"tags":{"highway":"service"}},"w628":{"id":"w628","nodes":["n3491","n3488","n3492","n3010","n3009","n3005","n3008","n3007","n3006","n3502","n3491"],"tags":{"leisure":"park","name":"Marina Park"}},"w629":{"id":"w629","nodes":["n2208","n2209","n2212","n2214","n2208"],"tags":{"building":"yes"}},"w63":{"id":"w63","nodes":["n1955","n316"],"tags":{"footway":"sidewalk","highway":"footway"}},"w630":{"id":"w630","nodes":["n2757","n3414","n3202","n4542","n3206","n4538","n3750","n3503","n1629","n4500","n2763","n4502","n2764","n3508"],"tags":{"highway":"residential","name":"Hoffman Street"}},"w631":{"id":"w631","nodes":["n2215","n2750","n2770","n2771","n2215"],"tags":{"building":"yes"}},"w632":{"id":"w632","nodes":["n2766","n3504","n3507","n3751","n3205","n3196","n3410","n2746"],"tags":{"highway":"residential","name":"Cushman Street"}},"w633":{"id":"w633","nodes":["n2745","n3749","n3507","n4535","n3503"],"tags":{"highway":"residential","name":"Pine Street"}},"w634":{"id":"w634","nodes":["n3510","n3511","n3512","n3509","n3510"],"tags":{"leisure":"park","name":"Bowman Park"}},"w636":{"id":"w636","nodes":["n2745","n3752","n3204","n3201","n3415","n2761","n2767","n3411"],"tags":{"highway":"residential","name":"Wheeler Street"}},"w637":{"id":"w637","nodes":["n3550","n4586","n4476","n3472"],"tags":{"highway":"residential","name":"11th Avenue"}},"w638":{"id":"w638","nodes":["n3508","n3518"],"tags":{"bridge":"yes","highway":"residential","name":"Hoffman Street"}},"w639":{"id":"w639","nodes":["n3518","n1204","n2862","n3519","n3520","n3521","n3522","n3523","n2161","n3524","n3549","n3552","n4239","n3551","n4577","n4582","n4578","n4583","n4579","n4574"],"tags":{"highway":"residential","name":"Hoffman Street"}},"w64":{"id":"w64","nodes":["n316","n317"],"tags":{"bridge":"yes","footway":"sidewalk","highway":"footway","layer":"1"}},"w640":{"id":"w640","nodes":["n3634","n3640","n3676","n3633","n3678","n3648","n3638","n3683","n3600","n3579","n3679","n3677","n2987","n3592","n3588","n3608","n3559","n3617","n3620","n3660","n3553","n3533","n3530","n3531","n3525","n3527","n3526","n3532","n3529","n3528","n3667","n3627","n3623","n3625","n3601","n3687","n3671","n3644","n3626","n3673","n3582","n3693","n3605","n3619","n3651","n3650","n3615","n3663","n3631","n3596","n3604","n3655","n3586","n3595","n3701","n3603","n3686","n3611","n3568","n3674","n3613","n3580","n3562","n3564","n3689","n3585","n3670","n3659","n3684","n3680","n3646","n3558","n3556","n3692","n3563","n3575","n3571","n3675","n3557","n3700","n3656","n3622","n3657","n3565","n3669","n3658","n3618","n3624","n3688","n3610","n3570","n3645","n3649","n3583","n3694","n3561","n3554","n3614","n3698","n3581","n3635","n3641","n3569","n3647","n3628","n3598","n3696","n3665","n3639","n3607","n3695","n3642","n3672","n3577","n3643","n3691","n3602","n3576","n3591","n3560","n3606","n3685","n3597","n3629","n3661","n3654","n3616","n3697","n3578","n3609","n3653","n3699","n3566","n3637","n3567","n3666","n3555","n3599","n3590","n3572","n3593","n3690","n3681","n3612","n3682","n3668","n3587","n3621","n3636","n3662","n3589","n3573","n3652","n3664","n3632","n3574","n3594","n3584","n3630","n3634"],"tags":{"landuse":"reservoir","name":"Hoffman Pond","natural":"water"}},"w641":{"id":"w641","nodes":["n2988","n3534","n3535","n3536","n3537","n3538","n3539","n3540","n3541","n3542","n3543","n3544","n3545","n3546","n3547","n3548","n2970"],"tags":{"waterway":"river"}},"w642":{"id":"w642","nodes":["n3702","n3703","n3704","n3705","n3706","n3707","n3708","n3709","n3710","n3711","n3712","n3713","n3714","n3715","n3716","n3717","n3718","n3719","n3720","n3721","n3722","n3723","n3724","n3725","n3726","n3727","n3728","n3729","n3730","n3731","n3732","n3733","n3734","n3735","n3736","n3737","n3738","n3739","n3740","n3741","n3742","n3743","n3702"],"tags":{"admin_level":"8","boundary":"administrative"}},"w643":{"id":"w643","nodes":["n2839","n2873"],"tags":{"highway":"service","service":"driveway"}},"w644":{"id":"w644","nodes":["n2873","n2840"],"tags":{"bridge":"yes","highway":"service","layer":"1","service":"driveway"}},"w645":{"id":"w645","nodes":["n2840","n2841","n2842","n2845","n2866"],"tags":{"highway":"service","service":"driveway","surface":"unpaved"}},"w646":{"id":"w646","nodes":["n2752","n3759","n1420","n1421","n1422","n3758","n4507","n4506","n4505","n4520","n3199","n4522","n4504","n4546","n3200","n4547","n3412"],"tags":{"highway":"residential","name":"Flower Street"}},"w647":{"id":"w647","nodes":["n2874","n2875","n2876","n2954","n2874"],"tags":{"building":"industrial"}},"w648":{"id":"w648","nodes":["n3778","n3779","n3780","n3781","n3782","n3783","n3778"],"tags":{"building":"yes"}},"w649":{"id":"w649","nodes":["n3197","n4543","n4544","n3198"],"tags":{"highway":"residential","name":"Morris Avenue","surface":"unpaved"}},"w65":{"id":"w65","nodes":["n317","n318","n319","n320","n321"],"tags":{"footway":"sidewalk","highway":"footway"}},"w650":{"id":"w650","nodes":["n3207","n4526","n4528","n4548","n3203","n4549","n3413","n2762"],"tags":{"highway":"residential","name":"Adams Street"}},"w651":{"id":"w651","nodes":["n3788","n3785","n3786","n3787","n3788"],"tags":{"power":"station"}},"w652":{"id":"w652","nodes":["n2957","n3163","n3241"],"tags":{"barrier":"wall"}},"w653":{"id":"w653","nodes":["n3549","n3802","n3803","n3800","n3801"],"tags":{"highway":"service","surface":"unpaved"}},"w654":{"id":"w654","nodes":["n3164","n3165","n3166","n3167","n3168","n3505","n3164"],"tags":{"building":"yes"}},"w655":{"id":"w655","nodes":["n3506","n3517","n3760","n3761","n3762","n3763","n3506"],"tags":{"building":"yes"}},"w656":{"id":"w656","nodes":["n3764","n3765","n3766","n3767","n3768","n3769","n3770","n3771","n3764"],"tags":{"building":"yes"}},"w657":{"id":"w657","nodes":["n3772","n3773","n3774","n3775","n3772"],"tags":{"building":"yes"}},"w658":{"id":"w658","nodes":["n3776","n3777","n3784","n3789","n3776"],"tags":{"building":"yes"}},"w659":{"id":"w659","nodes":["n3930","n3931","n3932","n3933","n3934","n3935","n3936","n3937","n3938","n3930"],"tags":{"leisure":"pitch","sport":"baseball"}},"w66":{"id":"w66","nodes":["n321","n322"],"tags":{"bridge":"yes","footway":"sidewalk","highway":"footway","layer":"1"}},"w660":{"id":"w660","nodes":["n3982","n3842","n3864","n3865","n3866","n3867","n3868","n3858","n3869","n3870","n3862"],"tags":{"highway":"service"}},"w661":{"id":"w661","nodes":["n3968","n3969"],"tags":{"highway":"footway"}},"w662":{"id":"w662","nodes":["n3875","n3876","n3877","n3878","n3879","n3880","n3881","n3882","n3875"],"tags":{"amenity":"parking"}},"w663":{"id":"w663","nodes":["n3964","n3965"],"tags":{"highway":"footway"}},"w664":{"id":"w664","nodes":["n3966","n3967"],"tags":{"highway":"footway"}},"w665":{"id":"w665","nodes":["n3857","n3890","n3884","n3894","n3889","n3899","n3885","n3886","n3896","n3887"],"tags":{"highway":"service","service":"parking_aisle"}},"w666":{"id":"w666","nodes":["n3895","n3896"],"tags":{"highway":"service","service":"parking_aisle"}},"w667":{"id":"w667","nodes":["n3274","n3977","n3984","n3983","n3981","n3844","n3978","n3982","n3861","n3862","n3873","n3874","n4468","n3863"],"tags":{"access":"private","highway":"service","name":"Collins Drive"}},"w668":{"id":"w668","nodes":["n3900","n3901","n3902","n3903","n3904","n3905","n3808","n3809","n3906","n3907","n3908","n3967","n3909","n3910","n3911","n3955","n3964","n3912","n3913","n3914","n3915","n3916","n3917","n3918","n3919","n3920","n3921","n3922","n3923","n3924","n3925","n3926","n3927","n3969","n3970","n3928","n3807","n3929","n3900"],"tags":{"building":"school"}},"w669":{"id":"w669","nodes":["n3272","n39","n40","n3974","n3863","n3857","n3892","n3883","n3891","n3889"],"tags":{"highway":"service"}},"w67":{"id":"w67","nodes":["n322","n886","n323","n475"],"tags":{"footway":"crossing","highway":"footway"}},"w670":{"id":"w670","nodes":["n3473","n3859","n3860","n3980","n4908","n4865"],"tags":{"highway":"secondary","name":"Hoffman Street","ref":"M 60"}},"w671":{"id":"w671","nodes":["n3970","n3806","n3971"],"tags":{"highway":"footway"}},"w672":{"id":"w672","nodes":["n3892","n3893","n3894"],"tags":{"highway":"service","service":"parking_aisle"}},"w673":{"id":"w673","nodes":["n3945","n3946","n3992","n3990","n3945"],"tags":{"leisure":"pitch","sport":"tennis"}},"w674":{"id":"w674","nodes":["n3890","n3893","n3891"],"tags":{"highway":"service","service":"parking_aisle"}},"w675":{"id":"w675","nodes":["n3947","n3948","n3994","n3993","n3947"],"tags":{"leisure":"pitch","sport":"tennis"}},"w676":{"id":"w676","nodes":["n3858","n3954","n3972","n3810","n3811","n3812","n3841","n3973","n3898","n3963","n3897","n3896"],"tags":{"highway":"service"}},"w677":{"id":"w677","nodes":["n3977","n3996","n3997","n4004","n3998","n3999","n4005","n4007","n4006","n3995","n4000","n3843","n4001","n4002","n4003","n3949","n3950","n3951","n3952","n3953","n3954","n3956","n3966","n3955"],"tags":{"highway":"footway"}},"w678":{"id":"w678","nodes":["n3887","n3888","n3895","n3899"],"tags":{"highway":"service","service":"parking_aisle"}},"w679":{"id":"w679","nodes":["n3946","n3947","n3993","n3992","n3946"],"tags":{"leisure":"pitch","sport":"tennis"}},"w68":{"id":"w68","nodes":["n294","n1952","n326"],"tags":{"footway":"sidewalk","highway":"footway"}},"w680":{"id":"w680","nodes":["n3939","n3940","n3941","n3985","n3986","n3987","n3988","n3989","n3942","n3943","n3939"],"tags":{"leisure":"pitch","sport":"baseball"}},"w681":{"id":"w681","nodes":["n3990","n3991","n3944","n3945","n3990"],"tags":{"leisure":"pitch","sport":"tennis"}},"w682":{"id":"w682","nodes":["n3871","n3872","n3873","n3874","n3871"],"tags":{"amenity":"parking"}},"w683":{"id":"w683","nodes":["n3956","n3965","n3957","n3958","n3959"],"tags":{"footway":"sidewalk","highway":"footway"}},"w684":{"id":"w684","nodes":["n3790","n3791","n3792","n3793","n3790"],"tags":{"building":"shed"}},"w685":{"id":"w685","nodes":["n3794","n3795","n3796","n3797","n3794"],"tags":{"building":"yes"}},"w686":{"id":"w686","nodes":["n3798","n3799","n3804","n3805","n3798"],"tags":{"building":"yes"}},"w687":{"id":"w687","nodes":["n3806","n3807"],"tags":{"highway":"footway"}},"w688":{"id":"w688","nodes":["n3845","n3846","n3847","n3848","n3845"],"tags":{"leisure":"pitch","sport":"american_football"}},"w689":{"id":"w689","nodes":["n3849","n4021","n3850","n3851","n3852","n3853","n3854","n3855","n3856","n3975","n3976","n3979","n4008","n4009","n4010","n4011","n4012","n4013","n4014","n4015","n4016","n4017","n4018","n4019","n4020","n4021"],"tags":{"leisure":"track","sport":"running"}},"w69":{"id":"w69","nodes":["n326","n327"],"tags":{"bridge":"yes","footway":"sidewalk","highway":"footway","layer":"1"}},"w690":{"id":"w690","nodes":["n4022","n4023","n4024","n4025","n4026","n4027","n4022"],"tags":{"building":"yes"}},"w691":{"id":"w691","nodes":["n4028","n4029","n4030","n4031","n4028"],"tags":{"building":"yes"}},"w692":{"id":"w692","nodes":["n4032","n4033","n4034","n4035","n4032"],"tags":{"building":"yes"}},"w693":{"id":"w693","nodes":["n4036","n4037","n4038","n4039","n4036"],"tags":{"building":"yes"}},"w694":{"id":"w694","nodes":["n4040","n4041","n4042","n4043","n4040"],"tags":{"building":"yes"}},"w695":{"id":"w695","nodes":["n4044","n4045","n4050","n4053","n4046","n4047","n4048","n4049","n4044"],"tags":{"building":"yes"}},"w696":{"id":"w696","nodes":["n4050","n4051","n4052","n4053","n4050"],"tags":{"building":"roof"}},"w697":{"id":"w697","nodes":["n4054","n4068","n4055","n4056","n4057","n4054"],"tags":{"building":"yes"}},"w698":{"id":"w698","nodes":["n4058","n4059","n4060","n4061","n4062","n4063","n4058"],"tags":{"building":"yes"}},"w699":{"id":"w699","nodes":["n4064","n4066","n4065"],"tags":{"barrier":"fence"}},"w7":{"id":"w7","nodes":["n43","n44","n45"],"tags":{"highway":"service"}},"w70":{"id":"w70","nodes":["n327","n328","n27","n329"],"tags":{"footway":"sidewalk","highway":"footway"}},"w700":{"id":"w700","nodes":["n4066","n4067","n4068"],"tags":{"barrier":"fence"}},"w701":{"id":"w701","nodes":["n4069","n4070","n4071","n4072","n4069"],"tags":{"building":"shed"}},"w702":{"id":"w702","nodes":["n4073","n4074","n4075","n4076","n4077","n4078","n4079","n4080","n4081","n4082","n4083","n4084","n4073"],"tags":{"building":"yes"}},"w703":{"id":"w703","nodes":["n4085","n4093","n4086","n4087","n4088","n4089","n4090","n4091","n4092","n4085"],"tags":{"building":"yes"}},"w704":{"id":"w704","nodes":["n4093","n4094","n4095","n4096"],"tags":{"barrier":"fence"}},"w705":{"id":"w705","nodes":["n4097","n4098","n4099","n4100","n4097"],"tags":{"building":"yes"}},"w706":{"id":"w706","nodes":["n4098","n4102","n4087"],"tags":{"barrier":"fence"}},"w707":{"id":"w707","nodes":["n4101","n4102","n4096","n4170","n4103"],"tags":{"barrier":"fence"}},"w708":{"id":"w708","nodes":["n4104","n4105","n4106","n4107","n4104"],"tags":{"access":"private","leisure":"swimming_pool"}},"w709":{"id":"w709","nodes":["n4108","n4109","n4110","n4111","n4108"],"tags":{"building":"yes"}},"w71":{"id":"w71","nodes":["n329","n331"],"tags":{"bridge":"yes","footway":"sidewalk","highway":"footway","layer":"1"}},"w710":{"id":"w710","nodes":["n4112","n4113","n4114","n4115","n4116","n4117","n4118","n4119","n4112"],"tags":{"building":"yes"}},"w711":{"id":"w711","nodes":["n4120","n4121","n4122","n4123","n4120"],"tags":{"building":"yes"}},"w712":{"id":"w712","nodes":["n4124","n4125","n4126","n4127","n4128","n4129","n4124"],"tags":{"building":"yes"}},"w713":{"id":"w713","nodes":["n4130","n4131","n4132","n4133","n4130"],"tags":{"building":"shed"}},"w714":{"id":"w714","nodes":["n4134","n4135","n4136","n4137","n4138","n4139","n4140","n4141","n4142","n4143","n4134"],"tags":{"building":"yes"}},"w715":{"id":"w715","nodes":["n4144","n4145","n4146","n4147","n4148","n4149","n4144"],"tags":{"building":"yes"}},"w716":{"id":"w716","nodes":["n4150","n4151","n4152","n4153","n4150"],"tags":{"building":"yes"}},"w717":{"id":"w717","nodes":["n4154","n4155","n4156","n4157","n4154"],"tags":{"building":"yes"}},"w718":{"id":"w718","nodes":["n4158","n4159","n4160","n4161","n4162","n4163","n4164","n4165","n4158"],"tags":{"building":"yes"}},"w719":{"id":"w719","nodes":["n4166","n4167","n4168","n4169","n4166"],"tags":{"building":"yes"}},"w72":{"id":"w72","nodes":["n331","n344","n332","n333","n334"],"tags":{"footway":"sidewalk","highway":"footway"}},"w720":{"id":"w720","nodes":["n4170","n4171"],"tags":{"barrier":"fence"}},"w721":{"id":"w721","nodes":["n4138","n4103"],"tags":{"barrier":"fence"}},"w722":{"id":"w722","nodes":["n4103","n4172"],"tags":{"barrier":"fence"}},"w723":{"id":"w723","nodes":["n4173","n4174"],"tags":{"barrier":"fence"}},"w724":{"id":"w724","nodes":["n4175","n4176","n4177","n4178","n4175"],"tags":{"building":"yes"}},"w725":{"id":"w725","nodes":["n4179","n4180","n4181","n4182","n4183","n4184","n4179"],"tags":{"building":"yes"}},"w726":{"id":"w726","nodes":["n4185","n4186","n4187","n4188","n4185"],"tags":{"building":"yes"}},"w727":{"id":"w727","nodes":["n4189","n4190","n4191","n4192","n4193","n4194","n4195","n4196","n4197","n4198","n4199","n4200","n4201","n4202","n4189"],"tags":{"building":"yes"}},"w728":{"id":"w728","nodes":["n4203","n4204","n4205","n4206","n4207","n4208","n4209","n4210","n4203"],"tags":{"building":"yes"}},"w729":{"id":"w729","nodes":["n4211","n4212","n4213","n4214","n4211"],"tags":{"building":"shed"}},"w73":{"id":"w73","nodes":["n335","n336","n337","n338","n339","n340","n341","n342","n335"],"tags":{"building":"yes"}},"w730":{"id":"w730","nodes":["n4215","n4216","n4217","n4218","n4215"],"tags":{"building":"yes"}},"w731":{"id":"w731","nodes":["n4219","n4220","n4221","n4222","n4223","n4224","n4225","n4226","n4227","n4228","n4229","n4230","n4219"],"tags":{"building":"yes"}},"w732":{"id":"w732","nodes":["n4231","n4232","n4233","n4234","n4235","n4236","n4237","n4238","n4231"],"tags":{"building":"yes"}},"w733":{"id":"w733","nodes":["n4239","n4240","n4241","n4242","n4243","n4244","n4245","n4246","n4247","n4248","n4241"],"tags":{"highway":"service"}},"w734":{"id":"w734","nodes":["n4240","n4249","n4248"],"tags":{"highway":"service","service":"parking_aisle"}},"w735":{"id":"w735","nodes":["n4250","n4251","n4252","n4253","n4254","n4255","n4256","n4257","n4258","n4250"],"tags":{"amenity":"parking"}},"w736":{"id":"w736","nodes":["n4259","n4260","n4261","n4262","n4259"],"tags":{"building":"yes"}},"w737":{"id":"w737","nodes":["n4263","n4264","n4265","n4266","n4267","n4268","n4269","n4270","n4271","n4272","n4273","n4274","n4275","n4276","n4263"],"tags":{"building":"yes"}},"w738":{"id":"w738","nodes":["n4277","n4278","n4279","n4280","n4281","n4282","n4277"],"tags":{"building":"yes"}},"w739":{"id":"w739","nodes":["n4283","n4284","n4285","n4286","n4287","n4288","n4289","n4290","n4291","n4292","n4293","n4294","n4283"],"tags":{"building":"yes"}},"w74":{"id":"w74","nodes":["n343","n344","n345"],"tags":{"highway":"service"}},"w740":{"id":"w740","nodes":["n4295","n4296","n4297","n4298","n4295"],"tags":{"building":"yes"}},"w741":{"id":"w741","nodes":["n4299","n4300","n4301","n4302","n4303","n4304","n4305","n4306","n4307","n4308","n4309","n4310","n4299"],"tags":{"building":"yes"}},"w742":{"id":"w742","nodes":["n4311","n4312","n4313","n4314","n4311"],"tags":{"building":"shed"}},"w743":{"id":"w743","nodes":["n4315","n4316","n4317","n4318","n4319","n4320","n4315"],"tags":{"building":"yes"}},"w744":{"id":"w744","nodes":["n4321","n4322","n4323","n4324","n4325","n4326","n4327","n4328","n4329","n4330","n4331","n4332","n4333","n4334","n4321"],"tags":{"building":"yes"}},"w745":{"id":"w745","nodes":["n4335","n4336","n4337","n4338","n4335"],"tags":{"building":"shed"}},"w746":{"id":"w746","nodes":["n4339","n4340","n4341","n4342","n4343","n4344","n4339"],"tags":{"building":"yes"}},"w747":{"id":"w747","nodes":["n4345","n4346","n4347","n4348","n4345"],"tags":{"building":"yes"}},"w748":{"id":"w748","nodes":["n4349","n4350","n4351","n4352","n4349"],"tags":{"building":"yes"}},"w749":{"id":"w749","nodes":["n4353","n4354","n4355","n4356","n4357","n4358","n4353"],"tags":{"building":"yes"}},"w75":{"id":"w75","nodes":["n346","n347","n348","n349","n350","n351","n346"],"tags":{"amenity":"parking"}},"w750":{"id":"w750","nodes":["n4612","n4359","n4360"],"tags":{"barrier":"fence"}},"w751":{"id":"w751","nodes":["n4361","n4362","n4363","n4364","n4361"],"tags":{"building":"yes"}},"w752":{"id":"w752","nodes":["n4365","n4366","n4367","n4368","n4365"],"tags":{"building":"yes"}},"w753":{"id":"w753","nodes":["n4369","n4370","n4371","n4372","n4375","n4369"],"tags":{"building":"yes"}},"w754":{"id":"w754","nodes":["n4373","n4374","n4375"],"tags":{"barrier":"fence"}},"w755":{"id":"w755","nodes":["n4376","n4377","n4378","n4379","n4376"],"tags":{"building":"shed"}},"w756":{"id":"w756","nodes":["n4380","n4381","n4382","n4383","n4384","n4385","n4386","n4387","n4388","n4389","n4390","n4391","n4380"],"tags":{"building":"yes"}},"w757":{"id":"w757","nodes":["n4392","n4393","n4394","n4395","n4392"],"tags":{"building":"yes"}},"w758":{"id":"w758","nodes":["n4396","n4397","n4398","n4399","n4396"],"tags":{"building":"shed"}},"w759":{"id":"w759","nodes":["n4400","n4401","n4402","n4403","n4404","n4405","n4406","n4407","n4408","n4409","n4410","n4411","n4412","n4413","n4414","n4415","n4400"],"tags":{"building":"yes"}},"w76":{"id":"w76","nodes":["n2561","n359","n2563","n2793","n357","n356","n2792","n355","n354","n2791","n2562","n353","n352","n358","n2561"],"tags":{"highway":"service","oneway":"yes","service":"parking_aisle"}},"w760":{"id":"w760","nodes":["n4416","n4417"],"tags":{"barrier":"fence"}},"w761":{"id":"w761","nodes":["n4418","n4416","n4419"],"tags":{"barrier":"fence"}},"w762":{"id":"w762","nodes":["n4420","n4421"],"tags":{"barrier":"fence"}},"w763":{"id":"w763","nodes":["n4422","n4423","n4424","n4425","n4426","n4427","n4428","n4429","n4430","n4431","n4432","n4433","n4422"],"tags":{"building":"yes"}},"w764":{"id":"w764","nodes":["n4434","n4435","n4436","n4437","n4438","n4439","n4440","n4441","n4442","n4445","n4444","n4443","n4434"],"tags":{"building":"yes"}},"w765":{"id":"w765","nodes":["n4446","n4447","n4448","n4449","n4446"],"tags":{"building":"yes"}},"w766":{"id":"w766","nodes":["n4450","n4451","n4452","n4453","n4450"],"tags":{"building":"yes"}},"w767":{"id":"w767","nodes":["n4454","n4455","n4456","n4457","n4454"],"tags":{"building":"yes"}},"w768":{"id":"w768","nodes":["n4461","n4458","n4460"],"tags":{"footway":"crossing","highway":"footway"}},"w769":{"id":"w769","nodes":["n4460","n4462","n4459"],"tags":{"footway":"sidewalk","highway":"footway"}},"w77":{"id":"w77","nodes":["n325","n360","n361"],"tags":{"footway":"crossing","highway":"footway"}},"w770":{"id":"w770","nodes":["n4462","n4463","n4464"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w771":{"id":"w771","nodes":["n4464","n4465","n4466","n4467"],"tags":{"footway":"sidewalk","highway":"footway"}},"w772":{"id":"w772","nodes":["n3959","n3968","n3971","n3960","n3961","n3962","n3963"],"tags":{"footway":"sidewalk","highway":"footway"}},"w773":{"id":"w773","nodes":["n4467","n4468","n3959"],"tags":{"footway":"crossing","highway":"footway"}},"w774":{"id":"w774","nodes":["n4459","n4469","n4470"],"tags":{"footway":"crossing","highway":"footway"}},"w775":{"id":"w775","nodes":["n4470","n4471","n4472","n4473","n4474","n4475"],"tags":{"footway":"sidewalk","highway":"footway"}},"w776":{"id":"w776","nodes":["n4475","n4476","n4477"],"tags":{"footway":"crossing","highway":"footway"}},"w777":{"id":"w777","nodes":["n4477","n4478","n4479","n4480","n4481","n4482","n4483","n4484","n4485","n4486","n4487"],"tags":{"footway":"sidewalk","highway":"footway"}},"w778":{"id":"w778","nodes":["n4488","n4489","n4490","n4491","n4488"],"tags":{"building":"yes"}},"w779":{"id":"w779","nodes":["n4492","n4493","n4494","n4495","n4492"],"tags":{"building":"yes"}},"w78":{"id":"w78","nodes":["n361","n362","n369"],"tags":{"footway":"sidewalk","highway":"footway"}},"w780":{"id":"w780","nodes":["n4496","n4497","n4498","n4499","n4496"],"tags":{"access":"private","leisure":"swimming_pool"}},"w781":{"id":"w781","nodes":["n4508","n4509"],"tags":{"footway":"sidewalk","highway":"footway"}},"w782":{"id":"w782","nodes":["n4510","n4511"],"tags":{"footway":"sidewalk","highway":"footway"}},"w783":{"id":"w783","nodes":["n4512","n4513"],"tags":{"footway":"sidewalk","highway":"footway"}},"w784":{"id":"w784","nodes":["n4513","n4514"],"tags":{"footway":"sidewalk","highway":"footway"}},"w785":{"id":"w785","nodes":["n4515","n4516"],"tags":{"footway":"sidewalk","highway":"footway"}},"w786":{"id":"w786","nodes":["n4517","n4515"],"tags":{"footway":"sidewalk","highway":"footway"}},"w787":{"id":"w787","nodes":["n4518","n4519"],"tags":{"footway":"sidewalk","highway":"footway"}},"w788":{"id":"w788","nodes":["n4519","n4520","n4513"],"tags":{"footway":"crossing","highway":"footway"}},"w789":{"id":"w789","nodes":["n4515","n4521","n4513"],"tags":{"footway":"crossing","highway":"footway"}},"w79":{"id":"w79","nodes":["n362","n363","n334"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w790":{"id":"w790","nodes":["n4515","n4522","n4523"],"tags":{"footway":"crossing","highway":"footway"}},"w791":{"id":"w791","nodes":["n4523","n4524","n4519"],"tags":{"footway":"crossing","highway":"footway"}},"w792":{"id":"w792","nodes":["n4523","n4525"],"tags":{"footway":"sidewalk","highway":"footway"}},"w793":{"id":"w793","nodes":["n4525","n4526","n4527"],"tags":{"footway":"crossing","highway":"footway"}},"w794":{"id":"w794","nodes":["n4527","n4529"],"tags":{"footway":"sidewalk","highway":"footway"}},"w795":{"id":"w795","nodes":["n4529","n4530","n4518"],"tags":{"footway":"crossing","highway":"footway"}},"w796":{"id":"w796","nodes":["n4518","n4531"],"tags":{"footway":"sidewalk","highway":"footway"}},"w797":{"id":"w797","nodes":["n4531","n4532"],"tags":{"footway":"sidewalk","highway":"footway"}},"w798":{"id":"w798","nodes":["n4533","n4534"],"tags":{"footway":"sidewalk","highway":"footway"}},"w799":{"id":"w799","nodes":["n4518","n4538","n4539"],"tags":{"footway":"crossing","highway":"footway"}},"w8":{"id":"w8","nodes":["n46","n47","n145","n48","n49","n46"],"tags":{"amenity":"parking"}},"w80":{"id":"w80","nodes":["n334","n364","n365"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w800":{"id":"w800","nodes":["n4539","n4540","n4541"],"tags":{"footway":"crossing","highway":"footway"}},"w801":{"id":"w801","nodes":["n4541","n4542","n4529"],"tags":{"footway":"crossing","highway":"footway"}},"w802":{"id":"w802","nodes":["n4552","n4553"],"tags":{"footway":"sidewalk","highway":"footway"}},"w803":{"id":"w803","nodes":["n4554","n4555","n4556","n4557","n4558","n4559","n4554"],"tags":{"building":"yes"}},"w804":{"id":"w804","nodes":["n4562","n4563"],"tags":{"barrier":"retaining_wall"}},"w805":{"id":"w805","nodes":["n4568","n4569","n4570","n4571","n4568"],"tags":{"building":"yes"}},"w806":{"id":"w806","nodes":["n3473","n4575","n4576","n4581","n4580","n3551"],"tags":{"highway":"residential","oneway":"yes"}},"w807":{"id":"w807","nodes":["n4613","n4614","n4615","n4616","n4617","n4618","n4619","n4620","n4613"],"tags":{"leisure":"pitch","sport":"baseball"}},"w808":{"id":"w808","nodes":["n4621","n4622","n4623","n4624","n4625","n4626","n4627","n4628","n4629","n4630"],"tags":{"highway":"service"}},"w809":{"id":"w809","nodes":["n4631","n4632","n4633","n4637","n4634","n4638","n4635","n4636"],"tags":{"highway":"service"}},"w81":{"id":"w81","nodes":["n365","n366","n367"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w810":{"id":"w810","nodes":["n4639","n4640","n4641"],"tags":{"barrier":"fence"}},"w811":{"id":"w811","nodes":["n4649","n4650","n4651","n4652","n4649"],"tags":{"building":"yes"}},"w812":{"id":"w812","nodes":["n4654","n4655"],"tags":{"barrier":"fence"}},"w813":{"id":"w813","nodes":["n4656","n4657"],"tags":{"barrier":"fence"}},"w814":{"id":"w814","nodes":["n4669","n4670","n4671","n4672","n4669"],"tags":{"amenity":"shelter","shelter_type":"picnic_shelters"}},"w815":{"id":"w815","nodes":["n4678","n4679","n4680","n1889"],"tags":{"highway":"service"}},"w816":{"id":"w816","nodes":["n239","n4686","n4687"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w817":{"id":"w817","nodes":["n4687","n4688","n4689"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w818":{"id":"w818","nodes":["n4689","n4690","n307"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w819":{"id":"w819","nodes":["n2266","n4743"],"tags":{"highway":"path"}},"w82":{"id":"w82","nodes":["n724","n368","n369"],"tags":{"crossing":"zebra","footway":"crossing","highway":"footway"}},"w820":{"id":"w820","nodes":["n4785","n4786","n4787","n4788","n1684","n4760","n4769","n4761","n4762","n4763","n4764","n4765","n4766","n4767","n4768","n4785"],"tags":{"natural":"wood"}},"w821":{"id":"w821","nodes":["n4769","n4770","n4771","n4772","n4773","n4774","n4775","n4776","n4777","n4778","n4779","n4780","n4781","n4782","n4783","n4784","n4785","n4768","n4767","n4766","n4765","n4764","n4763","n4762","n4761","n4769"],"tags":{"natural":"scrub"}},"w822":{"id":"w822","nodes":["n4772","n4789","n4790","n4791","n4792","n4793","n4794","n4795","n4796","n4797","n4798","n4799","n4783","n4782","n4781","n4780","n4779","n4778","n4777","n4776","n4775","n4774","n4773","n4772"],"tags":{"natural":"wood"}},"w823":{"id":"w823","nodes":["n4800","n4801","n4802","n4803","n4804","n4805","n4806","n4807","n4808","n4809","n4810","n4811","n4812","n4813","n4814","n4815","n4816","n3490","n3489","n4800"],"tags":{"natural":"wood"}},"w824":{"id":"w824","nodes":["n4817","n4818","n4819","n4820","n4821","n4822","n4817"],"tags":{"landuse":"recreation_ground"}},"w825":{"id":"w825","nodes":["n4563","n4823","n4824","n4829","n4825","n4826","n4827","n4828","n4562","n4563"],"tags":{"landuse":"recreation_ground"}},"w826":{"id":"w826","nodes":["n4830","n4831","n4832","n4833","n4834","n4835","n4836","n4830"],"tags":{"landuse":"industrial"}},"w827":{"id":"w827","nodes":["n4563","n4837","n4838","n4839","n4840","n4841","n4842","n4827","n4828","n4562","n4563"],"tags":{"landuse":"industrial"}},"w828":{"id":"w828","nodes":["n4843","n4844","n4845","n4846","n4843"],"tags":{"landuse":"farmland"}},"w829":{"id":"w829","nodes":["n3712","n4847","n4848","n4849","n4850","n4851","n4852","n4858","n4864","n4959","n4960","n4853","n4857","n4854","n4855","n4856","n3712"],"tags":{"aeroway":"aerodrome","name":"Three Rivers Municipal Airport"}},"w83":{"id":"w83","nodes":["n371","n372","n373","n374","n371"],"tags":{"building":"yes"}},"w830":{"id":"w830","nodes":["n4855","n4854","n4857","n4853","n4960"],"tags":{"barrier":"fence"}},"w831":{"id":"w831","nodes":["n4860","n4859","n4858","n4852","n4851"],"tags":{"barrier":"fence"}},"w832":{"id":"w832","nodes":["n4866","n4878","n4869","n4867"],"tags":{"aeroway":"runway","ref":"5/23"}},"w833":{"id":"w833","nodes":["n4868","n4890","n4894","n4881","n4869","n4905","n4870"],"tags":{"aeroway":"runway","ref":"9/27"}},"w834":{"id":"w834","nodes":["n4871","n4875","n4872","n4895","n4873","n4874","n4871"],"tags":{"aeroway":"apron"}},"w835":{"id":"w835","nodes":["n4875","n4876","n4877","n4878","n4879","n4880","n4882","n4881"],"tags":{"aeroway":"taxiway"}},"w836":{"id":"w836","nodes":["n4882","n4893","n4883","n4891","n4884","n4885","n4886","n4887","n4888","n4892","n4889","n4890"],"tags":{"aeroway":"taxiway"}},"w837":{"id":"w837","nodes":["n4893","n4894"],"tags":{"aeroway":"taxiway"}},"w838":{"id":"w838","nodes":["n4895","n4896","n4897","n4898","n4899","n4900","n4901","n4902","n4903","n4906","n4904","n4905"],"tags":{"aeroway":"taxiway"}},"w839":{"id":"w839","nodes":["n4907","n4908"],"tags":{"highway":"service"}},"w84":{"id":"w84","nodes":["n374","n375","n376","n377","n373","n374"],"tags":{"building":"yes"}},"w840":{"id":"w840","nodes":["n4909","n4907","n4910"],"tags":{"highway":"service"}},"w841":{"id":"w841","nodes":["n4911","n4912","n4913","n4914","n4911"],"tags":{"building":"yes"}},"w842":{"id":"w842","nodes":["n4915","n4916","n4917","n4918","n4915"],"tags":{"aeroway":"hangar","building":"yes"}},"w843":{"id":"w843","nodes":["n4919","n4920","n4921","n4922","n4919"],"tags":{"building":"yes"}},"w844":{"id":"w844","nodes":["n4923","n4924","n4925","n4926","n4923"],"tags":{"aeroway":"hangar","building":"yes"}},"w845":{"id":"w845","nodes":["n4927","n4928","n4929","n4930","n4927"],"tags":{"aeroway":"hangar","building":"yes"}},"w846":{"id":"w846","nodes":["n4931","n4932","n4933","n4934","n4931"],"tags":{"aeroway":"hangar","building":"yes"}},"w847":{"id":"w847","nodes":["n4935","n4936","n4937","n4938","n4935"],"tags":{"aeroway":"hangar","building":"yes"}},"w848":{"id":"w848","nodes":["n4939","n4940","n4941","n4942","n4939"],"tags":{"aeroway":"hangar","building":"yes"}},"w849":{"id":"w849","nodes":["n4943","n4944","n4945","n4946","n4943"],"tags":{"aeroway":"hangar","building":"yes"}},"w85":{"id":"w85","nodes":["n431","n432","n1038","n433","n434","n1040","n431"],"tags":{"building":"yes"}},"w850":{"id":"w850","nodes":["n4947","n4948","n4949","n4950","n4947"],"tags":{"aeroway":"hangar","building":"yes"}},"w851":{"id":"w851","nodes":["n4951","n4952","n4953","n4954","n4951"],"tags":{"aeroway":"hangar","building":"yes"}},"w852":{"id":"w852","nodes":["n4955","n4956","n4957","n4958","n4955"],"tags":{"aeroway":"hangar","building":"yes"}},"w853":{"id":"w853","nodes":["n4959","n4864","n4861","n4862","n4863"],"tags":{"barrier":"fence"}},"w854":{"id":"w854","nodes":["n4961","n4962","n4963","n4964","n4965","n4966","n4967","n4968","n4969","n4961"],"tags":{"landuse":"farmland"}},"w855":{"id":"w855","nodes":["n4970","n4971","n4972","n4973","n4974","n4975","n4976","n4977","n4978","n4980","n4970"],"tags":{"landuse":"farmland"}},"w856":{"id":"w856","nodes":["n4979","n4980","n4978","n4981","n4982","n4983","n4984","n4985","n4979"],"tags":{"natural":"scrub"}},"w857":{"id":"w857","nodes":["n4986","n4987","n4988","n5032","n4989","n4990","n4991","n4992","n4993","n4994","n4995","n4996","n4997","n4998","n4999","n5000","n5001","n5002","n5022","n5023","n5024","n5025","n5030","n5031","n5029","n5028","n5027","n5026","n4986"],"tags":{"landuse":"farmland"}},"w858":{"id":"w858","nodes":["n5001","n5003","n5004","n4999","n5000","n5001"],"tags":{"natural":"scrub"}},"w859":{"id":"w859","nodes":["n5005","n5006","n5007","n5008","n5009","n5010","n5021","n5020","n5019","n5011","n5012","n5013","n5018","n5014","n5015","n5017","n5016","n5005"],"tags":{"landuse":"farmland"}},"w86":{"id":"w86","nodes":["n384","n385","n386","n387","n384"],"tags":{"building":"yes"}},"w860":{"id":"w860","nodes":["n3020","n5033","n5034","n5035","n3179","n3180","n3191","n3181","n3190","n3182","n3183","n3184","n3185","n3186","n3187","n3188","n3189","n3160","n3161","n3162","n2126","n2153","n2288","n3020"],"tags":{"landuse":"industrial"}},"w87":{"id":"w87","nodes":["n387","n388","n389","n386","n387"],"tags":{"building":"yes"}},"w88":{"id":"w88","nodes":["n390","n391","n392","n393","n390"],"tags":{"building":"yes"}},"w89":{"id":"w89","nodes":["n394","n2895"],"tags":{"highway":"service"}},"w9":{"id":"w9","nodes":["n50","n51","n148","n52","n57","n891","n53","n50"],"tags":{"building":"yes"}},"w90":{"id":"w90","nodes":["n398","n399","n400","n401","n402","n403","n404","n405","n406","n407","n408","n409","n410","n411","n412","n413","n414","n415","n416","n417","n398"],"tags":{"building":"yes"}},"w91":{"id":"w91","nodes":["n418","n423","n419"],"tags":{"highway":"service"}},"w92":{"id":"w92","nodes":["n420","n421","n422","n423","n420"],"tags":{"amenity":"parking"}},"w93":{"id":"w93","nodes":["n2282","n1876"],"tags":{"name":"Rocky River","tunnel":"building_passage","waterway":"river"}},"w94":{"id":"w94","nodes":["n1876","n885","n1875","n2234"],"tags":{"name":"Rocky River","waterway":"river"}},"w95":{"id":"w95","nodes":["n425","n426","n427","n914","n428","n913","n425"],"tags":{"building":"yes"}},"w96":{"id":"w96","nodes":["n456","n620","n1034","n1035","n456"],"tags":{"building":"yes"}},"w97":{"id":"w97","nodes":["n435","n912","n451","n321"],"tags":{"highway":"footway"}},"w98":{"id":"w98","nodes":["n436","n319","n437","n438","n439","n440","n441","n476","n442"],"tags":{"highway":"service"}},"w99":{"id":"w99","nodes":["n443","n444","n445","n446","n447","n448","n449","n450","n443"],"tags":{"amenity":"parking"}}};
60124 // toggles the visibility of ui elements, using a combination of the
60125 // hide class, which sets display=none, and a d3 transition for opacity.
60126 // this will cause blinking when called repeatedly, so check that the
60127 // value actually changes between calls.
60128 function uiToggle(show, callback) {
60129 return function(selection$$1) {
60131 .style('opacity', show ? 0 : 1)
60132 .classed('hide', false)
60134 .style('opacity', show ? 1 : 0)
60135 .on('end', function() {
60137 .classed('hide', !show)
60138 .style('opacity', null);
60139 if (callback) callback.apply(this);
60144 // Tooltips and svg mask used to highlight certain features
60145 function uiCurtain() {
60147 var surface = select(null),
60148 tooltip = select(null),
60149 darkness = select(null);
60151 function curtain(selection$$1) {
60152 surface = selection$$1
60154 .attr('id', 'curtain')
60155 .style('z-index', 1000)
60156 .style('pointer-events', 'none')
60157 .style('position', 'absolute')
60161 darkness = surface.append('path')
60164 .attr('class', 'curtain-darkness');
60166 select(window).on('resize.curtain', resize);
60168 tooltip = selection$$1.append('div')
60169 .attr('class', 'tooltip')
60170 .style('z-index', 1002);
60174 .attr('class', 'tooltip-arrow');
60178 .attr('class', 'tooltip-inner');
60183 function resize() {
60185 .attr('width', window.innerWidth)
60186 .attr('height', window.innerHeight);
60187 curtain.cut(darkness.datum());
60193 * Reveal cuts the curtain to highlight the given box,
60194 * and shows a tooltip with instructions next to the box.
60196 * @param {String|ClientRect} [box] box used to cut the curtain
60197 * @param {String} [text] text for a tooltip
60198 * @param {Object} [options]
60199 * @param {string} [options.tooltipClass] optional class to add to the tooltip
60200 * @param {integer} [options.duration] transition time in milliseconds
60201 * @param {string} [options.buttonText] if set, create a button with this text label
60202 * @param {function} [options.buttonCallback] if set, the callback for the button
60203 * @param {String|ClientRect} [options.tooltipBox] box for tooltip position, if different from box for the curtain
60205 curtain.reveal = function(box, text$$1, options) {
60206 if (typeof box === 'string') {
60207 box = select(box).node();
60209 if (box && box.getBoundingClientRect) {
60210 box = copyBox(box.getBoundingClientRect());
60213 options = options || {};
60216 if (options.tooltipBox) {
60217 tooltipBox = options.tooltipBox;
60218 if (typeof tooltipBox === 'string') {
60219 tooltipBox = select(tooltipBox).node();
60221 if (tooltipBox && tooltipBox.getBoundingClientRect) {
60222 tooltipBox = copyBox(tooltipBox.getBoundingClientRect());
60228 if (tooltipBox && text$$1) {
60229 // pseudo markdown bold text for the instruction section..
60230 var parts = text$$1.split('**');
60231 var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
60233 html$$1 += '<span class="instruction">' + parts[1] + '</span>';
60236 html$$1 = html$$1.replace(/\*(.*?)\*/g, '<em>$1</em>'); // emphasis
60237 html$$1 = html$$1.replace(/\{br\}/g, '<br/><br/>'); // linebreak
60239 if (options.buttonText && options.buttonCallback) {
60240 html$$1 += '<div class="button-section">' +
60241 '<button href="#" class="button action col8">' + options.buttonText + '</button></div>';
60244 var classes = 'curtain-tooltip tooltip in ' + (options.tooltipClass || '');
60246 .classed(classes, true)
60247 .selectAll('.tooltip-inner')
60250 if (options.buttonText && options.buttonCallback) {
60251 var button = tooltip.selectAll('.button-section .button.action');
60253 .on('click', function() {
60254 event.preventDefault();
60255 options.buttonCallback();
60259 var tip = copyBox(tooltip.node().getBoundingClientRect()),
60260 w = window.innerWidth,
60261 h = window.innerHeight,
60262 tooltipWidth = 200,
60267 // hack: this will have bottom placement,
60268 // so need to reserve extra space for the tooltip illustration.
60269 if (options.tooltipClass === 'intro-mouse') {
60273 // trim box dimensions to just the portion that fits in the window..
60274 if (tooltipBox.top + tooltipBox.height > h) {
60275 tooltipBox.height -= (tooltipBox.top + tooltipBox.height - h);
60277 if (tooltipBox.left + tooltipBox.width > w) {
60278 tooltipBox.width -= (tooltipBox.left + tooltipBox.width - w);
60281 // determine tooltip placement..
60283 if (tooltipBox.top + tooltipBox.height < 100) {
60284 // tooltip below box..
60287 tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
60288 tooltipBox.top + tooltipBox.height
60291 } else if (tooltipBox.top > h - 140) {
60292 // tooltip above box..
60295 tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
60296 tooltipBox.top - tip.height
60300 // tooltip to the side of the tooltipBox..
60301 var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2;
60303 if (textDirection === 'rtl') {
60304 if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) {
60306 pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
60310 pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
60314 if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
60316 pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
60320 pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
60325 if (options.duration !== 0 || !tooltip.classed(side)) {
60326 tooltip.call(uiToggle(true));
60330 .style('top', pos[1] + 'px')
60331 .style('left', pos[0] + 'px')
60332 .attr('class', classes + ' ' + side);
60335 // shift tooltip-inner if it is very close to the top or bottom edge
60336 // (doesn't affect the placement of the tooltip-arrow)
60338 if (side === 'left' || side === 'right') {
60340 shiftY = 60 - pos[1];
60342 else if (pos[1] + tip.height > h - 100) {
60343 shiftY = h - pos[1] - tip.height - 100;
60346 tooltip.selectAll('.tooltip-inner')
60347 .style('top', shiftY + 'px');
60351 .classed('in', false)
60352 .call(uiToggle(false));
60355 curtain.cut(box, options.duration);
60361 curtain.cut = function(datum, duration) {
60362 darkness.datum(datum)
60366 if (duration === 0) {
60367 selection$$1 = darkness;
60369 selection$$1 = darkness
60371 .duration(duration || 600)
60376 .attr('d', function(d) {
60377 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
60378 window.innerWidth + ',' + window.innerHeight + 'L' +
60379 window.innerWidth + ',0 Z';
60381 if (!d) return string;
60382 return string + 'M' +
60383 d.left + ',' + d.top + 'L' +
60384 d.left + ',' + (d.top + d.height) + 'L' +
60385 (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
60386 (d.left + d.width) + ',' + (d.top) + 'Z';
60392 curtain.remove = function() {
60395 select(window).on('resize.curtain', null);
60399 // ClientRects are immutable, so copy them to an object,
60400 // in case we need to trim the height/width.
60401 function copyBox(src) {
60405 bottom: src.bottom,
60416 function uiIntroWelcome(context, reveal) {
60417 var dispatch$$1 = dispatch('done'),
60418 listener = clickListener();
60421 title: 'intro.welcome.title'
60425 function welcome() {
60426 context.map().centerZoom([-85.63591, 41.94285], 19);
60427 reveal('.intro-nav-wrap .chapter-welcome',
60428 t('intro.welcome.welcome'),
60429 { buttonText: t('intro.ok'), buttonCallback: practice }
60433 function practice() {
60434 reveal('.intro-nav-wrap .chapter-welcome',
60435 t('intro.welcome.practice'),
60436 { buttonText: t('intro.ok'), buttonCallback: words }
60441 reveal('.intro-nav-wrap .chapter-welcome',
60442 t('intro.welcome.words'),
60443 { buttonText: t('intro.ok'), buttonCallback: mouse$$1 }
60448 function mouse$$1() {
60449 reveal('.intro-nav-wrap .chapter-welcome',
60450 t('intro.welcome.mouse'),
60451 { buttonText: t('intro.ok'), buttonCallback: leftClick }
60456 function leftClick() {
60460 var tooltip = reveal('.intro-nav-wrap .chapter-welcome',
60461 t('intro.welcome.leftclick', { num: times }),
60462 { tooltipClass: 'intro-mouse' }
60465 tooltip.selectAll('.tooltip-inner')
60466 .insert('svg', 'span')
60467 .attr('class', 'tooltip-illustration')
60469 .attr('xlink:href', '#walkthrough-mouse');
60473 .attr('class', 'counter');
60475 tooltip.call(listener);
60477 listener.on('click', function(which) {
60478 if (which === 'left') {
60479 select('.curtain-tooltip.intro-mouse .counter')
60480 .text(String(++counter));
60482 if (counter === times) {
60483 window.setTimeout(function() { continueTo(rightClick); }, 1000);
60488 function continueTo(nextStep) {
60489 listener.on('click', null);
60490 tooltip.call(listener.off);
60491 tooltip.select('.counter').remove();
60497 function rightClick() {
60501 var tooltip = reveal('.intro-nav-wrap .chapter-welcome',
60502 t('intro.welcome.rightclick', { num: times }),
60503 { tooltipClass: 'intro-mouse' }
60506 tooltip.selectAll('.tooltip-inner')
60507 .insert('svg', 'span')
60508 .attr('class', 'tooltip-illustration')
60510 .attr('xlink:href', '#walkthrough-mouse');
60514 .attr('class', 'counter');
60516 tooltip.call(listener);
60518 listener.on('click', function(which) {
60519 if (which === 'right') {
60520 select('.curtain-tooltip.intro-mouse .counter')
60521 .text(String(++counter));
60523 if (counter === times) {
60524 window.setTimeout(function() { continueTo(chapters); }, 1000);
60529 function continueTo(nextStep) {
60530 listener.on('click', null);
60531 tooltip.call(listener.off);
60532 tooltip.select('.counter').remove();
60538 function chapters() {
60539 dispatch$$1.call('done');
60540 reveal('.intro-nav-wrap .chapter-navigation',
60541 t('intro.welcome.chapters', { next: t('intro.navigation.title') })
60546 chapter.enter = function() {
60551 chapter.exit = function() {
60556 chapter.restart = function() {
60562 return utilRebind(chapter, dispatch$$1, 'on');
60567 function clickListener() {
60568 var dispatch$$1 = dispatch('click'),
60570 tooltip = select(null),
60573 // `down` keeps track of which buttons/keys are down.
60574 // Setting a property in `down` happens immediately.
60575 // Unsetting a property in `down` is delayed because
60576 // on Windows a contextmenu event happens after keyup/mouseup
60578 function keydown() {
60579 if (event.keyCode === 93) { // context menu
60580 event.preventDefault();
60581 event.stopPropagation();
60582 down.menu = event.timeStamp;
60583 tooltip.classed('rightclick', true);
60589 if (event.keyCode === 93) { // context menu
60590 event.preventDefault();
60591 event.stopPropagation();
60592 var endTime = event.timeStamp,
60593 startTime = down.menu || endTime,
60594 delay = (endTime - startTime < minTime) ? minTime : 0;
60596 window.setTimeout(function() {
60597 tooltip.classed('rightclick', false);
60598 down.menu = undefined; // delayed, for Windows
60601 dispatch$$1.call('click', this, 'right');
60606 function mousedown() {
60607 var button = event.button;
60608 if (button === 0 && !event.ctrlKey) {
60609 tooltip.classed('leftclick', true);
60610 } else if (button === 2) {
60611 tooltip.classed('rightclick', true);
60613 down[button] = event.timeStamp;
60617 function mouseup() {
60618 var button = event.button,
60619 endTime = event.timeStamp,
60620 startTime = down[button] || endTime,
60621 delay = (endTime - startTime < minTime) ? minTime : 0;
60623 if (button === 0 && !event.ctrlKey) {
60624 window.setTimeout(function() {
60625 tooltip.classed('leftclick', false);
60626 down[button] = undefined; // delayed, for Windows
60629 dispatch$$1.call('click', this, 'left');
60631 } else if (button === 2) {
60632 window.setTimeout(function() {
60633 tooltip.classed('rightclick', false);
60634 down[button] = undefined; // delayed, for Windows
60637 dispatch$$1.call('click', this, 'right');
60640 window.setTimeout(function() {
60641 down[button] = undefined; // delayed, for Windows
60647 function contextmenu() {
60648 event.preventDefault();
60649 event.stopPropagation();
60650 if (!down[2] && !down.menu) {
60651 tooltip.classed('rightclick', true);
60652 window.setTimeout(function() {
60653 tooltip.classed('rightclick', false);
60655 dispatch$$1.call('click', this, 'right');
60660 var behavior = function(selection$$1) {
60661 tooltip = selection$$1;
60665 .on('keydown.intro', keydown)
60666 .on('keyup.intro', keyup)
60667 .on('mousedown.intro', mousedown)
60668 .on('mouseup.intro', mouseup)
60669 .on('contextmenu.intro', contextmenu);
60673 behavior.off = function() {
60675 .on('keydown.intro', null)
60676 .on('keyup.intro', null)
60677 .on('mousedown.intro', null)
60678 .on('mouseup.intro', null)
60679 .on('contextmenu.intro', null);
60682 .classed('leftclick', false)
60683 .classed('rightclick', false);
60686 return utilRebind(behavior, dispatch$$1, 'on');
60689 function uiIntroNavigation(context, reveal) {
60690 var dispatch$$1 = dispatch('done'),
60693 townHall = [-85.63591, 41.94285],
60694 springStreetId = 'w397',
60695 springStreetEndId = 'n1834',
60696 springStreet = [-85.63582, 41.94255],
60697 onewayField = context.presets().field('oneway'),
60698 maxspeedField = context.presets().field('maxspeed');
60702 title: 'intro.navigation.title'
60706 function timeout(f, t$$1) {
60707 timeouts.push(window.setTimeout(f, t$$1));
60711 function eventCancel() {
60712 event.stopPropagation();
60713 event.preventDefault();
60717 function isTownHallSelected() {
60718 var ids = context.selectedIDs();
60719 return ids.length === 1 && ids[0] === hallId;
60723 function dragMap() {
60724 context.enter(modeBrowse(context));
60725 context.history().reset('initial');
60727 var msec = transitionTime(townHall, context.map().center());
60728 if (msec) { reveal(null, null, { duration: 0 }); }
60729 context.map().zoom(19).centerEase(townHall, msec);
60731 timeout(function() {
60732 var centerStart = context.map().center();
60734 reveal('#surface', t('intro.navigation.drag'));
60735 context.map().on('drawn.intro', function() {
60736 reveal('#surface', t('intro.navigation.drag'), { duration: 0 });
60739 context.map().on('move.intro', function() {
60740 var centerNow = context.map().center();
60741 if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) {
60742 context.map().on('move.intro', null);
60743 timeout(function() { continueTo(zoomMap); }, 3000);
60749 function continueTo(nextStep) {
60750 context.map().on('move.intro drawn.intro', null);
60756 function zoomMap() {
60757 var zoomStart = context.map().zoom();
60760 t('intro.navigation.zoom', {
60761 plus: icon('#icon-plus', 'pre-text'),
60762 minus: icon('#icon-minus', 'pre-text')
60766 context.map().on('drawn.intro', function() {
60768 t('intro.navigation.zoom', {
60769 plus: icon('#icon-plus', 'pre-text'),
60770 minus: icon('#icon-minus', 'pre-text')
60771 }), { duration: 0 }
60775 context.map().on('move.intro', function() {
60776 if (context.map().zoom() !== zoomStart) {
60777 context.map().on('move.intro', null);
60778 timeout(function() { continueTo(features); }, 3000);
60782 function continueTo(nextStep) {
60783 context.map().on('move.intro drawn.intro', null);
60789 function features() {
60790 var onClick = function() { continueTo(pointsLinesAreas); };
60792 reveal('#surface', t('intro.navigation.features'),
60793 { buttonText: t('intro.ok'), buttonCallback: onClick }
60796 context.map().on('drawn.intro', function() {
60797 reveal('#surface', t('intro.navigation.features'),
60798 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
60802 function continueTo(nextStep) {
60803 context.map().on('drawn.intro', null);
60808 function pointsLinesAreas() {
60809 var onClick = function() { continueTo(nodesWays); };
60811 reveal('#surface', t('intro.navigation.points_lines_areas'),
60812 { buttonText: t('intro.ok'), buttonCallback: onClick }
60815 context.map().on('drawn.intro', function() {
60816 reveal('#surface', t('intro.navigation.points_lines_areas'),
60817 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
60821 function continueTo(nextStep) {
60822 context.map().on('drawn.intro', null);
60827 function nodesWays() {
60828 var onClick = function() { continueTo(clickTownHall); };
60830 reveal('#surface', t('intro.navigation.nodes_ways'),
60831 { buttonText: t('intro.ok'), buttonCallback: onClick }
60834 context.map().on('drawn.intro', function() {
60835 reveal('#surface', t('intro.navigation.nodes_ways'),
60836 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
60840 function continueTo(nextStep) {
60841 context.map().on('drawn.intro', null);
60846 function clickTownHall() {
60847 context.enter(modeBrowse(context));
60848 context.history().reset('initial');
60850 reveal(null, null, { duration: 0 });
60851 context.map().zoomEase(19, 500);
60853 timeout(function() {
60854 var entity = context.hasEntity(hallId);
60855 if (!entity) return;
60856 context.map().centerEase(entity.loc, 500);
60858 timeout(function() {
60859 var entity = context.hasEntity(hallId);
60860 if (!entity) return;
60861 var box = pointBox(entity.loc, context);
60862 reveal(box, t('intro.navigation.click_townhall'));
60864 context.map().on('move.intro drawn.intro', function() {
60865 var entity = context.hasEntity(hallId);
60866 if (!entity) return;
60867 var box = pointBox(entity.loc, context);
60868 reveal(box, t('intro.navigation.click_townhall'), { duration: 0 });
60871 context.on('enter.intro', function() {
60872 if (isTownHallSelected()) continueTo(selectedTownHall);
60875 }, 550); // after centerEase
60877 }, 550); // after zoomEase
60879 context.history().on('change.intro', function() {
60880 if (!context.hasEntity(hallId)) {
60881 continueTo(clickTownHall);
60885 function continueTo(nextStep) {
60886 context.on('enter.intro', null);
60887 context.map().on('move.intro drawn.intro', null);
60888 context.history().on('change.intro', null);
60894 function selectedTownHall() {
60895 if (!isTownHallSelected()) return clickTownHall();
60897 var entity = context.hasEntity(hallId);
60898 if (!entity) return clickTownHall();
60900 var box = pointBox(entity.loc, context);
60901 var onClick = function() { continueTo(editorTownHall); };
60903 reveal(box, t('intro.navigation.selected_townhall'),
60904 { buttonText: t('intro.ok'), buttonCallback: onClick }
60907 context.map().on('move.intro drawn.intro', function() {
60908 var entity = context.hasEntity(hallId);
60909 if (!entity) return;
60910 var box = pointBox(entity.loc, context);
60911 reveal(box, t('intro.navigation.selected_townhall'),
60912 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
60916 context.history().on('change.intro', function() {
60917 if (!context.hasEntity(hallId)) {
60918 continueTo(clickTownHall);
60922 function continueTo(nextStep) {
60923 context.map().on('move.intro drawn.intro', null);
60924 context.history().on('change.intro', null);
60930 function editorTownHall() {
60931 if (!isTownHallSelected()) return clickTownHall();
60933 // disallow scrolling
60934 select('.inspector-wrap').on('wheel.intro', eventCancel);
60936 var onClick = function() { continueTo(presetTownHall); };
60938 reveal('.entity-editor-pane',
60939 t('intro.navigation.editor_townhall'),
60940 { buttonText: t('intro.ok'), buttonCallback: onClick }
60943 context.on('exit.intro', function() {
60944 continueTo(clickTownHall);
60947 context.history().on('change.intro', function() {
60948 if (!context.hasEntity(hallId)) {
60949 continueTo(clickTownHall);
60953 function continueTo(nextStep) {
60954 context.on('exit.intro', null);
60955 context.history().on('change.intro', null);
60956 select('.inspector-wrap').on('wheel.intro', null);
60962 function presetTownHall() {
60963 if (!isTownHallSelected()) return clickTownHall();
60965 // reset pane, in case user happened to change it..
60966 select('.inspector-wrap .panewrap').style('right', '0%');
60967 // disallow scrolling
60968 select('.inspector-wrap').on('wheel.intro', eventCancel);
60970 // preset match, in case the user happened to change it.
60971 var entity = context.entity(context.selectedIDs()[0]);
60972 var preset = context.presets().match(entity, context.graph());
60974 var onClick = function() { continueTo(fieldsTownHall); };
60976 context.on('exit.intro', function() {
60977 continueTo(clickTownHall);
60980 context.history().on('change.intro', function() {
60981 if (!context.hasEntity(hallId)) {
60982 continueTo(clickTownHall);
60986 reveal('.inspector-body .preset-list-item.inspector-inner',
60987 t('intro.navigation.preset_townhall', { preset: preset.name() }),
60988 { buttonText: t('intro.ok'), buttonCallback: onClick }
60991 function continueTo(nextStep) {
60992 context.on('exit.intro', null);
60993 context.history().on('change.intro', null);
60994 select('.inspector-wrap').on('wheel.intro', null);
61000 function fieldsTownHall() {
61001 if (!isTownHallSelected()) return clickTownHall();
61003 // reset pane, in case user happened to change it..
61004 select('.inspector-wrap .panewrap').style('right', '0%');
61005 // disallow scrolling
61006 select('.inspector-wrap').on('wheel.intro', eventCancel);
61008 var onClick = function() { continueTo(closeTownHall); };
61010 reveal('.inspector-body .inspector-preset',
61011 t('intro.navigation.fields_townhall'),
61012 { buttonText: t('intro.ok'), buttonCallback: onClick }
61015 context.on('exit.intro', function() {
61016 continueTo(clickTownHall);
61019 context.history().on('change.intro', function() {
61020 if (!context.hasEntity(hallId)) {
61021 continueTo(clickTownHall);
61025 function continueTo(nextStep) {
61026 context.on('exit.intro', null);
61027 context.history().on('change.intro', null);
61028 select('.inspector-wrap').on('wheel.intro', null);
61034 function closeTownHall() {
61035 if (!isTownHallSelected()) return clickTownHall();
61037 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
61038 var href = select(selector$$1).attr('href') || '#icon-close';
61040 reveal('.entity-editor-pane',
61041 t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') })
61044 context.on('exit.intro', function() {
61045 continueTo(searchStreet);
61048 context.history().on('change.intro', function() {
61049 // update the close icon in the tooltip if the user edits something.
61050 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
61051 var href = select(selector$$1).attr('href') || '#icon-close';
61053 reveal('.entity-editor-pane',
61054 t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }),
61059 function continueTo(nextStep) {
61060 context.on('exit.intro', null);
61061 context.history().on('change.intro', null);
61067 function searchStreet() {
61068 context.enter(modeBrowse(context));
61069 context.history().reset('initial'); // ensure spring street exists
61071 var msec = transitionTime(springStreet, context.map().center());
61072 if (msec) { reveal(null, null, { duration: 0 }); }
61073 context.map().zoom(19).centerEase(springStreet, msec); // ..and user can see it
61075 timeout(function() {
61076 reveal('.search-header input',
61077 t('intro.navigation.search_street', { name: t('intro.graph.name.spring-street') })
61080 select('.search-header input')
61081 .on('keyup.intro', checkSearchResult);
61086 function checkSearchResult() {
61087 var first = select('.feature-list-item:nth-child(0n+2)'), // skip "No Results" item
61088 firstName = first.select('.entity-name'),
61089 name = t('intro.graph.name.spring-street');
61091 if (!firstName.empty() && firstName.text() === name) {
61092 reveal(first.node(),
61093 t('intro.navigation.choose_street', { name: name }),
61097 context.on('exit.intro', function() {
61098 continueTo(selectedStreet);
61101 select('.search-header input')
61102 .on('keydown.intro', eventCancel, true)
61103 .on('keyup.intro', null);
61106 function continueTo(nextStep) {
61107 context.on('exit.intro', null);
61108 select('.search-header input')
61109 .on('keydown.intro', null)
61110 .on('keyup.intro', null);
61116 function selectedStreet() {
61117 if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
61118 return searchStreet();
61121 var onClick = function() { continueTo(editorStreet); };
61122 var entity = context.entity(springStreetEndId);
61123 var box = pointBox(entity.loc, context);
61127 t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }),
61128 { duration: 600, buttonText: t('intro.ok'), buttonCallback: onClick }
61131 timeout(function() {
61132 context.map().on('move.intro drawn.intro', function() {
61133 var entity = context.hasEntity(springStreetEndId);
61134 if (!entity) return;
61135 var box = pointBox(entity.loc, context);
61138 t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }),
61139 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
61142 }, 600); // after reveal.
61144 context.on('enter.intro', function(mode) {
61145 if (!context.hasEntity(springStreetId)) {
61146 return continueTo(searchStreet);
61148 var ids = context.selectedIDs();
61149 if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) {
61150 // keep Spring Street selected..
61151 context.enter(modeSelect(context, [springStreetId]));
61155 context.history().on('change.intro', function() {
61156 if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
61157 timeout(function() {
61158 continueTo(searchStreet);
61159 }, 300); // after any transition (e.g. if user deleted intersection)
61163 function continueTo(nextStep) {
61164 context.map().on('move.intro drawn.intro', null);
61165 context.on('enter.intro', null);
61166 context.history().on('change.intro', null);
61172 function editorStreet() {
61173 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
61174 var href = select(selector$$1).attr('href') || '#icon-close';
61176 reveal('.entity-editor-pane',
61177 t('intro.navigation.editor_street', {
61178 button: icon(href, 'pre-text'),
61179 field1: onewayField.label(),
61180 field2: maxspeedField.label()
61184 context.on('exit.intro', function() {
61188 context.history().on('change.intro', function() {
61189 // update the close icon in the tooltip if the user edits something.
61190 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
61191 var href = select(selector$$1).attr('href') || '#icon-close';
61193 reveal('.entity-editor-pane',
61194 t('intro.navigation.editor_street', {
61195 button: icon(href, 'pre-text'),
61196 field1: onewayField.label().toLowerCase(),
61197 field2: maxspeedField.label().toLowerCase()
61198 }), { duration: 0 }
61202 function continueTo(nextStep) {
61203 context.on('exit.intro', null);
61204 context.history().on('change.intro', null);
61211 dispatch$$1.call('done');
61212 reveal('#id-container',
61213 t('intro.navigation.play', { next: t('intro.points.title') }), {
61214 tooltipBox: '.intro-nav-wrap .chapter-point',
61215 buttonText: t('intro.ok'),
61216 buttonCallback: function() { reveal('#id-container'); }
61222 chapter.enter = function() {
61227 chapter.exit = function() {
61228 timeouts.forEach(window.clearTimeout);
61229 context.on('enter.intro exit.intro', null);
61230 context.map().on('move.intro drawn.intro', null);
61231 context.history().on('change.intro', null);
61232 select('.inspector-wrap').on('wheel.intro', null);
61233 select('.search-header input').on('keydown.intro keyup.intro', null);
61237 chapter.restart = function() {
61243 return utilRebind(chapter, dispatch$$1, 'on');
61246 function uiIntroPoint(context, reveal) {
61247 var dispatch$$1 = dispatch('done'),
61249 intersection = [-85.63279, 41.94394],
61250 building = [-85.632422, 41.944045],
61251 cafePreset = context.presets().item('amenity/cafe'),
61256 title: 'intro.points.title'
61260 function timeout(f, t$$1) {
61261 timeouts.push(window.setTimeout(f, t$$1));
61265 function revealEditMenu(loc, text$$1, options) {
61266 var rect = context.surfaceRect();
61267 var point = context.curtainProjection(loc);
61269 var width = 250 + (2 * pad);
61271 var startX = rect.left + point[0];
61272 var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad);
61275 top: point[1] + rect.top - 60,
61279 reveal(box, text$$1, options);
61283 function eventCancel() {
61284 event.stopPropagation();
61285 event.preventDefault();
61289 function addPoint() {
61290 context.enter(modeBrowse(context));
61291 context.history().reset('initial');
61293 var msec = transitionTime(intersection, context.map().center());
61294 if (msec) { reveal(null, null, { duration: 0 }); }
61295 context.map().zoom(19).centerEase(intersection, msec);
61297 timeout(function() {
61298 var tooltip = reveal('button.add-point',
61299 t('intro.points.add_point', { button: icon('#icon-point', 'pre-text') }));
61303 tooltip.selectAll('.tooltip-inner')
61304 .insert('svg', 'span')
61305 .attr('class', 'tooltip-illustration')
61307 .attr('xlink:href', '#poi-images');
61309 context.on('enter.intro', function(mode) {
61310 if (mode.id !== 'add-point') return;
61311 continueTo(placePoint);
61315 function continueTo(nextStep) {
61316 context.on('enter.intro', null);
61322 function placePoint() {
61323 if (context.mode().id !== 'add-point') {
61324 return chapter.restart();
61327 var pointBox$$1 = pad$1(building, 150, context);
61328 reveal(pointBox$$1, t('intro.points.place_point'));
61330 context.map().on('move.intro drawn.intro', function() {
61331 pointBox$$1 = pad$1(building, 150, context);
61332 reveal(pointBox$$1, t('intro.points.place_point'), { duration: 0 });
61335 context.on('enter.intro', function(mode) {
61336 if (mode.id !== 'select') return chapter.restart();
61337 pointId = context.mode().selectedIDs()[0];
61338 continueTo(searchPreset);
61341 function continueTo(nextStep) {
61342 context.map().on('move.intro drawn.intro', null);
61343 context.on('enter.intro', null);
61349 function searchPreset() {
61350 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
61354 // disallow scrolling
61355 select('.inspector-wrap').on('wheel.intro', eventCancel);
61357 select('.preset-search-input')
61358 .on('keydown.intro', null)
61359 .on('keyup.intro', checkPresetSearch);
61361 reveal('.preset-search-input',
61362 t('intro.points.search_cafe', { preset: cafePreset.name() })
61365 context.on('enter.intro', function(mode) {
61366 if (!pointId || !context.hasEntity(pointId)) {
61367 return continueTo(addPoint);
61370 var ids = context.selectedIDs();
61371 if (mode.id !== 'select' || !ids.length || ids[0] !== pointId) {
61372 // keep the user's point selected..
61373 context.enter(modeSelect(context, [pointId]));
61375 // disallow scrolling
61376 select('.inspector-wrap').on('wheel.intro', eventCancel);
61378 select('.preset-search-input')
61379 .on('keydown.intro', null)
61380 .on('keyup.intro', checkPresetSearch);
61382 reveal('.preset-search-input',
61383 t('intro.points.search_cafe', { preset: cafePreset.name() })
61386 context.history().on('change.intro', null);
61391 function checkPresetSearch() {
61392 var first = select('.preset-list-item:first-child');
61394 if (first.classed('preset-amenity-cafe')) {
61395 select('.preset-search-input')
61396 .on('keydown.intro', eventCancel, true)
61397 .on('keyup.intro', null);
61399 reveal(first.select('.preset-list-button').node(),
61400 t('intro.points.choose_cafe', { preset: cafePreset.name() }),
61404 context.history().on('change.intro', function() {
61405 continueTo(aboutFeatureEditor);
61410 function continueTo(nextStep) {
61411 context.on('enter.intro', null);
61412 context.history().on('change.intro', null);
61413 select('.inspector-wrap').on('wheel.intro', null);
61414 select('.preset-search-input').on('keydown.intro keyup.intro', null);
61420 function aboutFeatureEditor() {
61421 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
61425 timeout(function() {
61426 reveal('.entity-editor-pane', t('intro.points.feature_editor'), {
61427 tooltipClass: 'intro-points-describe',
61428 buttonText: t('intro.ok'),
61429 buttonCallback: function() { continueTo(addName); }
61433 context.on('exit.intro', function() {
61434 // if user leaves select mode here, just continue with the tutorial.
61435 continueTo(reselectPoint);
61438 function continueTo(nextStep) {
61439 context.on('exit.intro', null);
61445 function addName() {
61446 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
61450 // reset pane, in case user happened to change it..
61451 select('.inspector-wrap .panewrap').style('right', '0%');
61453 timeout(function() {
61454 // It's possible for the user to add a name in a previous step..
61455 // If so, don't tell them to add the name in this step.
61456 // Give them an OK button instead.
61457 var entity = context.entity(pointId);
61458 if (entity.tags.name) {
61459 var tooltip = reveal('.entity-editor-pane', t('intro.points.add_name'), {
61460 tooltipClass: 'intro-points-describe',
61461 buttonText: t('intro.ok'),
61462 buttonCallback: function() { continueTo(addCloseEditor); }
61464 tooltip.select('.instruction').style('display', 'none');
61467 reveal('.entity-editor-pane', t('intro.points.add_name'),
61468 { tooltipClass: 'intro-points-describe' }
61473 context.history().on('change.intro', function() {
61474 continueTo(addCloseEditor);
61477 context.on('exit.intro', function() {
61478 // if user leaves select mode here, just continue with the tutorial.
61479 continueTo(reselectPoint);
61482 function continueTo(nextStep) {
61483 context.on('exit.intro', null);
61484 context.history().on('change.intro', null);
61490 function addCloseEditor() {
61491 // reset pane, in case user happened to change it..
61492 select('.inspector-wrap .panewrap').style('right', '0%');
61494 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
61495 var href = select(selector$$1).attr('href') || '#icon-close';
61497 context.on('exit.intro', function() {
61498 continueTo(reselectPoint);
61501 reveal('.entity-editor-pane',
61502 t('intro.points.add_close', { button: icon(href, 'pre-text') })
61505 function continueTo(nextStep) {
61506 context.on('exit.intro', null);
61512 function reselectPoint() {
61513 if (!pointId) return chapter.restart();
61514 var entity = context.hasEntity(pointId);
61515 if (!entity) return chapter.restart();
61517 // make sure it's still a cafe, in case user somehow changed it..
61518 var oldPreset = context.presets().match(entity, context.graph());
61519 context.replace(actionChangePreset(pointId, oldPreset, cafePreset));
61521 context.enter(modeBrowse(context));
61523 var msec = transitionTime(entity.loc, context.map().center());
61524 if (msec) { reveal(null, null, { duration: 0 }); }
61525 context.map().centerEase(entity.loc, msec);
61527 timeout(function() {
61528 var box = pointBox(entity.loc, context);
61529 reveal(box, t('intro.points.reselect'), { duration: 600 });
61531 timeout(function() {
61532 context.map().on('move.intro drawn.intro', function() {
61533 var entity = context.hasEntity(pointId);
61534 if (!entity) return chapter.restart();
61535 var box = pointBox(entity.loc, context);
61536 reveal(box, t('intro.points.reselect'), { duration: 0 });
61538 }, 600); // after reveal..
61540 context.on('enter.intro', function(mode) {
61541 if (mode.id !== 'select') return;
61542 continueTo(updatePoint);
61547 function continueTo(nextStep) {
61548 context.map().on('move.intro drawn.intro', null);
61549 context.on('enter.intro', null);
61555 function updatePoint() {
61556 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
61557 return continueTo(reselectPoint);
61560 // reset pane, in case user happened to untag the point..
61561 select('.inspector-wrap .panewrap').style('right', '0%');
61563 context.on('exit.intro', function() {
61564 continueTo(reselectPoint);
61567 context.history().on('change.intro', function() {
61568 continueTo(updateCloseEditor);
61571 timeout(function() {
61572 reveal('.entity-editor-pane', t('intro.points.update'),
61573 { tooltipClass: 'intro-points-describe' }
61577 function continueTo(nextStep) {
61578 context.on('exit.intro', null);
61579 context.history().on('change.intro', null);
61585 function updateCloseEditor() {
61586 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
61587 return continueTo(reselectPoint);
61590 // reset pane, in case user happened to change it..
61591 select('.inspector-wrap .panewrap').style('right', '0%');
61593 context.on('exit.intro', function() {
61594 continueTo(rightClickPoint);
61597 timeout(function() {
61598 reveal('.entity-editor-pane',
61599 t('intro.points.update_close', { button: icon('#icon-apply', 'pre-text') })
61603 function continueTo(nextStep) {
61604 context.on('exit.intro', null);
61610 function rightClickPoint() {
61611 if (!pointId) return chapter.restart();
61612 var entity = context.hasEntity(pointId);
61613 if (!entity) return chapter.restart();
61615 context.enter(modeBrowse(context));
61617 var box = pointBox(entity.loc, context);
61618 reveal(box, t('intro.points.rightclick'), { duration: 600 });
61620 timeout(function() {
61621 context.map().on('move.intro drawn.intro', function() {
61622 var entity = context.hasEntity(pointId);
61623 if (!entity) return chapter.restart();
61624 var box = pointBox(entity.loc, context);
61625 reveal(box, t('intro.points.rightclick'), { duration: 0 });
61627 }, 600); // after reveal
61629 context.on('enter.intro', function(mode) {
61630 if (mode.id !== 'select') return;
61631 var ids = context.selectedIDs();
61632 if (ids.length !== 1 || ids[0] !== pointId) return;
61634 timeout(function() {
61635 var node = selectMenuItem('delete').node();
61637 continueTo(enterDelete);
61638 }, 300); // after menu visible
61641 function continueTo(nextStep) {
61642 context.on('enter.intro', null);
61643 context.map().on('move.intro drawn.intro', null);
61649 function enterDelete() {
61650 if (!pointId) return chapter.restart();
61651 var entity = context.hasEntity(pointId);
61652 if (!entity) return chapter.restart();
61654 var node = selectMenuItem('delete').node();
61655 if (!node) { return continueTo(rightClickPoint); }
61657 revealEditMenu(entity.loc,
61658 t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') })
61661 timeout(function() {
61662 context.map().on('move.intro drawn.intro', function() {
61663 revealEditMenu(entity.loc,
61664 t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }),
61668 }, 300); // after menu visible
61670 context.on('exit.intro', function() {
61671 if (!pointId) return chapter.restart();
61672 var entity = context.hasEntity(pointId);
61673 if (entity) return continueTo(rightClickPoint); // point still exists
61676 context.history().on('change.intro', function(changed) {
61677 if (changed.deleted().length) {
61682 function continueTo(nextStep) {
61683 context.map().on('move.intro drawn.intro', null);
61684 context.history().on('change.intro', null);
61685 context.on('exit.intro', null);
61692 context.history().on('change.intro', function() {
61696 var iconName = '#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo');
61697 reveal('#bar button.undo-button',
61698 t('intro.points.undo', { button: icon(iconName, 'pre-text') })
61701 function continueTo(nextStep) {
61702 context.history().on('change.intro', null);
61709 dispatch$$1.call('done');
61710 reveal('#id-container',
61711 t('intro.points.play', { next: t('intro.areas.title') }), {
61712 tooltipBox: '.intro-nav-wrap .chapter-area',
61713 buttonText: t('intro.ok'),
61714 buttonCallback: function() { reveal('#id-container'); }
61720 chapter.enter = function() {
61725 chapter.exit = function() {
61726 timeouts.forEach(window.clearTimeout);
61727 context.on('enter.intro exit.intro', null);
61728 context.map().on('move.intro drawn.intro', null);
61729 context.history().on('change.intro', null);
61730 select('.inspector-wrap').on('wheel.intro', eventCancel);
61731 select('.preset-search-input').on('keydown.intro keyup.intro', null);
61735 chapter.restart = function() {
61741 return utilRebind(chapter, dispatch$$1, 'on');
61744 function uiIntroArea(context, reveal) {
61745 var dispatch$$1 = dispatch('done'),
61746 playground = [-85.63552, 41.94159],
61747 playgroundPreset = context.presets().item('leisure/playground'),
61748 descriptionField = context.presets().field('description'),
61754 title: 'intro.areas.title'
61758 function timeout(f, t$$1) {
61759 timeouts.push(window.setTimeout(f, t$$1));
61763 function eventCancel() {
61764 event.stopPropagation();
61765 event.preventDefault();
61769 function revealPlayground(center, text$$1, options) {
61770 var padding = 180 * Math.pow(2, context.map().zoom() - 19.5);
61771 var box = pad$1(center, padding, context);
61772 reveal(box, text$$1, options);
61776 function addArea() {
61777 context.enter(modeBrowse(context));
61778 context.history().reset('initial');
61781 var msec = transitionTime(playground, context.map().center());
61782 if (msec) { reveal(null, null, { duration: 0 }); }
61783 context.map().zoom(19).centerEase(playground, msec);
61785 timeout(function() {
61786 var tooltip = reveal('button.add-area',
61787 t('intro.areas.add_playground', { button: icon('#icon-area', 'pre-text') }));
61789 tooltip.selectAll('.tooltip-inner')
61790 .insert('svg', 'span')
61791 .attr('class', 'tooltip-illustration')
61793 .attr('xlink:href', '#landuse-images');
61795 context.on('enter.intro', function(mode) {
61796 if (mode.id !== 'add-area') return;
61797 continueTo(startPlayground);
61801 function continueTo(nextStep) {
61802 context.on('enter.intro', null);
61808 function startPlayground() {
61809 if (context.mode().id !== 'add-area') {
61810 return chapter.restart();
61814 context.map().zoomEase(19.5, 500);
61816 timeout(function() {
61817 revealPlayground(playground,
61818 t('intro.areas.start_playground'), { duration: 250 }
61821 timeout(function() {
61822 context.map().on('move.intro drawn.intro', function() {
61823 revealPlayground(playground,
61824 t('intro.areas.start_playground'), { duration: 0 }
61827 context.on('enter.intro', function(mode) {
61828 if (mode.id !== 'draw-area') return chapter.restart();
61829 continueTo(continuePlayground);
61831 }, 250); // after reveal
61833 }, 550); // after easing
61835 function continueTo(nextStep) {
61836 context.map().on('move.intro drawn.intro', null);
61837 context.on('enter.intro', null);
61843 function continuePlayground() {
61844 if (context.mode().id !== 'draw-area') {
61845 return chapter.restart();
61849 revealPlayground(playground,
61850 t('intro.areas.continue_playground', { alt: uiCmd.display('⌥') }),
61854 timeout(function() {
61855 context.map().on('move.intro drawn.intro', function() {
61856 revealPlayground(playground,
61857 t('intro.areas.continue_playground', { alt: uiCmd.display('⌥') }),
61861 }, 250); // after reveal
61863 context.on('enter.intro', function(mode) {
61864 if (mode.id === 'draw-area') {
61865 var entity = context.hasEntity(context.selectedIDs()[0]);
61866 if (entity && entity.nodes.length >= 6) {
61867 return continueTo(finishPlayground);
61871 } else if (mode.id === 'select') {
61872 areaId = context.selectedIDs()[0];
61873 return continueTo(searchPresets);
61875 return chapter.restart();
61879 function continueTo(nextStep) {
61880 context.map().on('move.intro drawn.intro', null);
61881 context.on('enter.intro', null);
61887 function finishPlayground() {
61888 if (context.mode().id !== 'draw-area') {
61889 return chapter.restart();
61893 revealPlayground(playground,
61894 t('intro.areas.finish_playground'), { duration: 250 }
61897 timeout(function() {
61898 context.map().on('move.intro drawn.intro', function() {
61899 revealPlayground(playground,
61900 t('intro.areas.finish_playground'), { duration: 0 }
61903 }, 250); // after reveal
61905 context.on('enter.intro', function(mode) {
61906 if (mode.id === 'draw-area') {
61908 } else if (mode.id === 'select') {
61909 areaId = context.selectedIDs()[0];
61910 return continueTo(searchPresets);
61912 return chapter.restart();
61916 function continueTo(nextStep) {
61917 context.map().on('move.intro drawn.intro', null);
61918 context.on('enter.intro', null);
61924 function searchPresets() {
61925 if (!areaId || !context.hasEntity(areaId)) {
61928 var ids = context.selectedIDs();
61929 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
61930 context.enter(modeSelect(context, [areaId]));
61933 // disallow scrolling
61934 select('.inspector-wrap').on('wheel.intro', eventCancel);
61936 timeout(function() {
61937 // reset pane, in case user somehow happened to change it..
61938 select('.inspector-wrap .panewrap').style('right', '-100%');
61940 select('.preset-search-input')
61941 .on('keydown.intro', null)
61942 .on('keyup.intro', checkPresetSearch);
61944 reveal('.preset-search-input',
61945 t('intro.areas.search_playground', { preset: playgroundPreset.name() })
61947 }, 400); // after preset list pane visible..
61949 context.on('enter.intro', function(mode) {
61950 if (!areaId || !context.hasEntity(areaId)) {
61951 return continueTo(addArea);
61954 var ids = context.selectedIDs();
61955 if (mode.id !== 'select' || !ids.length || ids[0] !== areaId) {
61956 // keep the user's area selected..
61957 context.enter(modeSelect(context, [areaId]));
61959 // reset pane, in case user somehow happened to change it..
61960 select('.inspector-wrap .panewrap').style('right', '-100%');
61961 // disallow scrolling
61962 select('.inspector-wrap').on('wheel.intro', eventCancel);
61964 select('.preset-search-input')
61965 .on('keydown.intro', null)
61966 .on('keyup.intro', checkPresetSearch);
61968 reveal('.preset-search-input',
61969 t('intro.areas.search_playground', { preset: playgroundPreset.name() })
61972 context.history().on('change.intro', null);
61976 function checkPresetSearch() {
61977 var first = select('.preset-list-item:first-child');
61979 if (first.classed('preset-leisure-playground')) {
61980 reveal(first.select('.preset-list-button').node(),
61981 t('intro.areas.choose_playground', { preset: playgroundPreset.name() }),
61985 select('.preset-search-input')
61986 .on('keydown.intro', eventCancel, true)
61987 .on('keyup.intro', null);
61989 context.history().on('change.intro', function() {
61990 continueTo(clickAddField);
61995 function continueTo(nextStep) {
61996 select('.inspector-wrap').on('wheel.intro', null);
61997 context.on('enter.intro', null);
61998 context.history().on('change.intro', null);
61999 select('.preset-search-input').on('keydown.intro keyup.intro', null);
62005 function clickAddField() {
62006 if (!areaId || !context.hasEntity(areaId)) {
62009 var ids = context.selectedIDs();
62010 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
62011 return searchPresets();
62014 if (!select('.form-field-description').empty()) {
62015 return continueTo(describePlayground);
62018 // disallow scrolling
62019 select('.inspector-wrap').on('wheel.intro', eventCancel);
62021 timeout(function() {
62022 // reset pane, in case user somehow happened to change it..
62023 select('.inspector-wrap .panewrap').style('right', '0%');
62025 // It's possible for the user to add a description in a previous step..
62026 // If they did this already, just continue to next step.
62027 var entity = context.entity(areaId);
62028 if (entity.tags.description) {
62029 return continueTo(play);
62032 reveal('.more-fields .combobox-input',
62033 t('intro.areas.add_field'),
62037 select('.more-fields .combobox-input')
62038 .on('click.intro', function() {
62039 continueTo(chooseDescriptionField);
62041 }, 400); // after editor pane visible
62043 context.on('exit.intro', function() {
62044 return continueTo(searchPresets);
62047 function continueTo(nextStep) {
62048 select('.inspector-wrap').on('wheel.intro', null);
62049 select('.more-fields .combobox-input').on('click.intro', null);
62050 context.on('exit.intro', null);
62056 function chooseDescriptionField() {
62057 if (!areaId || !context.hasEntity(areaId)) {
62060 var ids = context.selectedIDs();
62061 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
62062 return searchPresets();
62065 if (!select('.form-field-description').empty()) {
62066 return continueTo(describePlayground);
62069 // Make sure combobox is ready..
62070 if (select('div.combobox').empty()) {
62071 return continueTo(clickAddField);
62073 // Watch for the combobox to go away..
62075 watcher = window.setInterval(function() {
62076 if (select('div.combobox').empty()) {
62077 window.clearInterval(watcher);
62078 timeout(function() {
62079 if (select('.form-field-description').empty()) {
62080 continueTo(retryChooseDescription);
62082 continueTo(describePlayground);
62084 }, 300); // after description field added.
62088 reveal('div.combobox',
62089 t('intro.areas.choose_field', { field: descriptionField.label() }),
62093 context.on('exit.intro', function() {
62094 return continueTo(searchPresets);
62097 function continueTo(nextStep) {
62098 if (watcher) window.clearInterval(watcher);
62099 context.on('exit.intro', null);
62105 function describePlayground() {
62106 if (!areaId || !context.hasEntity(areaId)) {
62109 var ids = context.selectedIDs();
62110 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
62111 return searchPresets();
62114 // reset pane, in case user happened to change it..
62115 select('.inspector-wrap .panewrap').style('right', '0%');
62117 if (select('.form-field-description').empty()) {
62118 return continueTo(retryChooseDescription);
62121 context.on('exit.intro', function() {
62125 reveal('.entity-editor-pane',
62126 t('intro.areas.describe_playground', { button: icon('#icon-apply', 'pre-text') }),
62130 function continueTo(nextStep) {
62131 context.on('exit.intro', null);
62137 function retryChooseDescription() {
62138 if (!areaId || !context.hasEntity(areaId)) {
62141 var ids = context.selectedIDs();
62142 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
62143 return searchPresets();
62146 // reset pane, in case user happened to change it..
62147 select('.inspector-wrap .panewrap').style('right', '0%');
62149 reveal('.entity-editor-pane',
62150 t('intro.areas.retry_add_field', { field: descriptionField.label() }), {
62151 buttonText: t('intro.ok'),
62152 buttonCallback: function() { continueTo(clickAddField); }
62155 context.on('exit.intro', function() {
62156 return continueTo(searchPresets);
62159 function continueTo(nextStep) {
62160 context.on('exit.intro', null);
62167 dispatch$$1.call('done');
62168 reveal('#id-container',
62169 t('intro.areas.play', { next: t('intro.lines.title') }), {
62170 tooltipBox: '.intro-nav-wrap .chapter-line',
62171 buttonText: t('intro.ok'),
62172 buttonCallback: function() { reveal('#id-container'); }
62178 chapter.enter = function() {
62183 chapter.exit = function() {
62184 timeouts.forEach(window.clearTimeout);
62185 context.on('enter.intro exit.intro', null);
62186 context.map().on('move.intro drawn.intro', null);
62187 context.history().on('change.intro', null);
62188 select('.inspector-wrap').on('wheel.intro', null);
62189 select('.preset-search-input').on('keydown.intro keyup.intro', null);
62190 select('.more-fields .combobox-input').on('click.intro', null);
62194 chapter.restart = function() {
62200 return utilRebind(chapter, dispatch$$1, 'on');
62203 function uiIntroLine(context, reveal) {
62204 var dispatch$$1 = dispatch('done'),
62206 tulipRoadId = null,
62207 flowerRoadId = 'w646',
62208 tulipRoadStart = [-85.6297754121684, 41.95805253325314],
62209 tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204],
62210 tulipRoadIntersection = [-85.62974496187628, 41.95742515554585],
62211 roadCategory = context.presets().item('category-road'),
62212 residentialPreset = context.presets().item('highway/residential'),
62213 woodRoadId = 'w525',
62214 woodRoadEndId = 'n2862',
62215 woodRoadAddNode = [-85.62390110349587, 41.95397111462291],
62216 woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487],
62217 woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872],
62218 washingtonStreetId = 'w522',
62219 twelfthAvenueId = 'w1',
62220 eleventhAvenueEndId = 'n3550',
62221 twelfthAvenueEndId = 'n5',
62222 washingtonSegmentId = null,
62223 eleventhAvenueEnd = context.entity(eleventhAvenueEndId).loc,
62224 twelfthAvenueEnd = context.entity(twelfthAvenueEndId).loc,
62225 deleteLinesLoc = [-85.6219395542764, 41.95228033922477],
62226 twelfthAvenue = [-85.62219310052491, 41.952505413152956];
62230 title: 'intro.lines.title'
62234 function timeout(f, t$$1) {
62235 timeouts.push(window.setTimeout(f, t$$1));
62239 function eventCancel() {
62240 event.stopPropagation();
62241 event.preventDefault();
62245 function revealEditMenu(loc, text$$1, options) {
62246 var rect = context.surfaceRect();
62247 var point = context.curtainProjection(loc);
62249 var width = 250 + (2 * pad);
62251 var startX = rect.left + point[0];
62252 var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad);
62255 top: point[1] + rect.top - 60,
62259 reveal(box, text$$1, options);
62263 function addLine() {
62264 context.enter(modeBrowse(context));
62265 context.history().reset('initial');
62267 var msec = transitionTime(tulipRoadStart, context.map().center());
62268 if (msec) { reveal(null, null, { duration: 0 }); }
62269 context.map().zoom(18.5).centerEase(tulipRoadStart, msec);
62271 timeout(function() {
62272 var tooltip = reveal('button.add-line',
62273 t('intro.lines.add_line', { button: icon('#icon-line', 'pre-text') }));
62275 tooltip.selectAll('.tooltip-inner')
62276 .insert('svg', 'span')
62277 .attr('class', 'tooltip-illustration')
62279 .attr('xlink:href', '#feature-images');
62281 context.on('enter.intro', function(mode) {
62282 if (mode.id !== 'add-line') return;
62283 continueTo(startLine);
62287 function continueTo(nextStep) {
62288 context.on('enter.intro', null);
62294 function startLine() {
62295 if (context.mode().id !== 'add-line') {
62296 return chapter.restart();
62299 tulipRoadId = null;
62301 var padding = 70 * Math.pow(2, context.map().zoom() - 18);
62302 var box = pad$1(tulipRoadStart, padding, context);
62303 box.height = box.height + 100;
62304 reveal(box, t('intro.lines.start_line'));
62306 context.map().on('move.intro drawn.intro', function() {
62307 padding = 70 * Math.pow(2, context.map().zoom() - 18);
62308 box = pad$1(tulipRoadStart, padding, context);
62309 box.height = box.height + 100;
62310 reveal(box, t('intro.lines.start_line'), { duration: 0 });
62313 context.on('enter.intro', function(mode) {
62314 if (mode.id !== 'draw-line') return chapter.restart();
62315 continueTo(drawLine);
62318 function continueTo(nextStep) {
62319 context.map().on('move.intro drawn.intro', null);
62320 context.on('enter.intro', null);
62326 function drawLine() {
62327 if (context.mode().id !== 'draw-line') {
62328 return chapter.restart();
62331 tulipRoadId = context.mode().selectedIDs()[0];
62332 context.map().centerEase(tulipRoadMidpoint, 500);
62334 timeout(function() {
62335 var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
62336 var box = pad$1(tulipRoadMidpoint, padding, context);
62337 box.height = box.height * 2;
62339 t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') })
62342 context.map().on('move.intro drawn.intro', function() {
62343 padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
62344 box = pad$1(tulipRoadMidpoint, padding, context);
62345 box.height = box.height * 2;
62347 t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }),
62351 }, 550); // after easing..
62353 context.history().on('change.intro', function() {
62354 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
62355 if (!entity) return chapter.restart();
62357 if (isLineConnected()) {
62358 continueTo(continueLine);
62362 context.on('enter.intro', function(mode) {
62363 if (mode.id === 'draw-line')
62365 else if (mode.id === 'select') {
62366 continueTo(retryIntersect);
62370 return chapter.restart();
62373 function continueTo(nextStep) {
62374 context.map().on('move.intro drawn.intro', null);
62375 context.history().on('change.intro', null);
62376 context.on('enter.intro', null);
62382 function isLineConnected() {
62383 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
62384 if (!entity) return false;
62386 var drawNodes = context.graph().childNodes(entity);
62387 return lodash.some(drawNodes, function(node) {
62388 return lodash.some(context.graph().parentWays(node), function(parent) {
62389 return parent.id === flowerRoadId;
62395 function retryIntersect() {
62396 select(window).on('mousedown.intro', eventCancel, true);
62398 var box = pad$1(tulipRoadIntersection, 80, context);
62400 t('intro.lines.retry_intersect', { name: t('intro.graph.name.flower-street') })
62403 timeout(chapter.restart, 3000);
62407 function continueLine() {
62408 if (context.mode().id !== 'draw-line') return chapter.restart();
62409 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
62410 if (!entity) return chapter.restart();
62412 context.map().centerEase(tulipRoadIntersection, 500);
62414 reveal('#surface', t('intro.lines.continue_line'));
62416 context.on('enter.intro', function(mode) {
62417 if (mode.id === 'draw-line')
62419 else if (mode.id === 'select')
62420 return continueTo(chooseCategoryRoad);
62422 return chapter.restart();
62425 function continueTo(nextStep) {
62426 context.on('enter.intro', null);
62432 function chooseCategoryRoad() {
62433 if (context.mode().id !== 'select') {
62434 return chapter.restart();
62437 context.on('exit.intro', function() {
62438 return chapter.restart();
62441 var button = select('.preset-category-road .preset-list-button');
62442 if (button.empty()) return chapter.restart();
62444 // disallow scrolling
62445 select('.inspector-wrap').on('wheel.intro', eventCancel);
62447 timeout(function() {
62448 // reset pane, in case user somehow happened to change it..
62449 select('.inspector-wrap .panewrap').style('right', '-100%');
62451 reveal(button.node(),
62452 t('intro.lines.choose_category_road', { category: roadCategory.name() })
62455 button.on('click.intro', function() {
62456 continueTo(choosePresetResidential);
62459 }, 400); // after editor pane visible
62461 function continueTo(nextStep) {
62462 select('.inspector-wrap').on('wheel.intro', null);
62463 select('.preset-list-button').on('click.intro', null);
62464 context.on('exit.intro', null);
62470 function choosePresetResidential() {
62471 if (context.mode().id !== 'select') {
62472 return chapter.restart();
62475 context.on('exit.intro', function() {
62476 return chapter.restart();
62479 var subgrid = select('.preset-category-road .subgrid');
62480 if (subgrid.empty()) return chapter.restart();
62482 subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button')
62483 .on('click.intro', function() {
62484 continueTo(retryPresetResidential);
62487 subgrid.selectAll('.preset-highway-residential .preset-list-button')
62488 .on('click.intro', function() {
62489 continueTo(nameRoad);
62492 timeout(function() {
62493 reveal(subgrid.node(),
62494 t('intro.lines.choose_preset_residential', { preset: residentialPreset.name() }),
62495 { tooltipBox: '.preset-highway-residential .preset-list-button', duration: 300 }
62499 function continueTo(nextStep) {
62500 select('.preset-list-button').on('click.intro', null);
62501 context.on('exit.intro', null);
62507 // selected wrong road type
62508 function retryPresetResidential() {
62509 if (context.mode().id !== 'select') {
62510 return chapter.restart();
62513 context.on('exit.intro', function() {
62514 return chapter.restart();
62517 // disallow scrolling
62518 select('.inspector-wrap').on('wheel.intro', eventCancel);
62520 timeout(function() {
62521 var button = select('.entity-editor-pane .preset-list-button');
62523 reveal(button.node(),
62524 t('intro.lines.retry_preset_residential', { preset: residentialPreset.name() })
62527 button.on('click.intro', function() {
62528 continueTo(chooseCategoryRoad);
62533 function continueTo(nextStep) {
62534 select('.inspector-wrap').on('wheel.intro', null);
62535 select('.preset-list-button').on('click.intro', null);
62536 context.on('exit.intro', null);
62542 function nameRoad() {
62543 context.on('exit.intro', function() {
62544 continueTo(didNameRoad);
62547 timeout(function() {
62548 reveal('.entity-editor-pane',
62549 t('intro.lines.name_road', { button: icon('#icon-apply', 'pre-text') }),
62550 { tooltipClass: 'intro-lines-name_road' }
62554 function continueTo(nextStep) {
62555 context.on('exit.intro', null);
62561 function didNameRoad() {
62562 context.history().checkpoint('doneAddLine');
62564 timeout(function() {
62565 reveal('#surface', t('intro.lines.did_name_road'), {
62566 buttonText: t('intro.ok'),
62567 buttonCallback: function() { continueTo(updateLine); }
62571 function continueTo(nextStep) {
62577 function updateLine() {
62578 context.history().reset('doneAddLine');
62579 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62580 return chapter.restart();
62583 var msec = transitionTime(woodRoadDragMidpoint, context.map().center());
62584 if (msec) { reveal(null, null, { duration: 0 }); }
62585 context.map().zoom(19).centerEase(woodRoadDragMidpoint, msec);
62587 timeout(function() {
62588 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
62589 var box = pad$1(woodRoadDragMidpoint, padding, context);
62590 var advance = function() { continueTo(addNode); };
62592 reveal(box, t('intro.lines.update_line'),
62593 { buttonText: t('intro.ok'), buttonCallback: advance }
62596 context.map().on('move.intro drawn.intro', function() {
62597 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
62598 var box = pad$1(woodRoadDragMidpoint, padding, context);
62599 reveal(box, t('intro.lines.update_line'),
62600 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
62605 function continueTo(nextStep) {
62606 context.map().on('move.intro drawn.intro', null);
62612 function addNode() {
62613 context.history().reset('doneAddLine');
62614 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62615 return chapter.restart();
62618 var padding = 40 * Math.pow(2, context.map().zoom() - 19);
62619 var box = pad$1(woodRoadAddNode, padding, context);
62620 reveal(box, t('intro.lines.add_node'));
62622 context.map().on('move.intro drawn.intro', function() {
62623 var padding = 40 * Math.pow(2, context.map().zoom() - 19);
62624 var box = pad$1(woodRoadAddNode, padding, context);
62625 reveal(box, t('intro.lines.add_node'), { duration: 0 });
62628 context.history().on('change.intro', function(changed) {
62629 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62630 return continueTo(updateLine);
62632 if (changed.created().length === 1) {
62633 timeout(function() { continueTo(startDragEndpoint); }, 500);
62637 context.on('enter.intro', function(mode) {
62638 if (mode.id !== 'select') {
62639 continueTo(updateLine);
62643 function continueTo(nextStep) {
62644 context.map().on('move.intro drawn.intro', null);
62645 context.history().on('change.intro', null);
62646 context.on('enter.intro', null);
62652 function startDragEndpoint() {
62653 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62654 return continueTo(updateLine);
62656 if (context.selectedIDs().indexOf(woodRoadId) === -1) {
62657 context.enter(modeSelect(context, [woodRoadId]));
62660 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
62661 var box = pad$1(woodRoadDragEndpoint, padding, context);
62662 reveal(box, t('intro.lines.start_drag_endpoint'));
62664 context.map().on('move.intro drawn.intro', function() {
62665 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62666 return continueTo(updateLine);
62668 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
62669 var box = pad$1(woodRoadDragEndpoint, padding, context);
62670 reveal(box, t('intro.lines.start_drag_endpoint'), { duration: 0 });
62672 var entity = context.entity(woodRoadEndId);
62673 if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) {
62674 continueTo(finishDragEndpoint);
62678 context.on('enter.intro', function(mode) {
62679 if (mode.id !== 'select') {
62680 // keep Wood Road selected so endpoint stays draggable..
62681 context.enter(modeSelect(context, [woodRoadId]));
62685 function continueTo(nextStep) {
62686 context.map().on('move.intro drawn.intro', null);
62687 context.on('enter.intro', null);
62693 function finishDragEndpoint() {
62694 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62695 return continueTo(updateLine);
62698 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
62699 var box = pad$1(woodRoadDragEndpoint, padding, context);
62700 reveal(box, t('intro.lines.finish_drag_endpoint'));
62702 context.map().on('move.intro drawn.intro', function() {
62703 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62704 return continueTo(updateLine);
62706 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
62707 var box = pad$1(woodRoadDragEndpoint, padding, context);
62708 reveal(box, t('intro.lines.finish_drag_endpoint'), { duration: 0 });
62710 var entity = context.entity(woodRoadEndId);
62711 if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) {
62712 continueTo(startDragEndpoint);
62716 context.on('enter.intro', function() {
62717 continueTo(startDragMidpoint);
62720 function continueTo(nextStep) {
62721 context.map().on('move.intro drawn.intro', null);
62722 context.on('enter.intro', null);
62728 function startDragMidpoint() {
62729 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62730 return continueTo(updateLine);
62732 if (context.selectedIDs().indexOf(woodRoadId) === -1) {
62733 context.enter(modeSelect(context, [woodRoadId]));
62736 var padding = 80 * Math.pow(2, context.map().zoom() - 19);
62737 var box = pad$1(woodRoadDragMidpoint, padding, context);
62738 reveal(box, t('intro.lines.start_drag_midpoint'));
62740 context.map().on('move.intro drawn.intro', function() {
62741 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62742 return continueTo(updateLine);
62744 var padding = 80 * Math.pow(2, context.map().zoom() - 19);
62745 var box = pad$1(woodRoadDragMidpoint, padding, context);
62746 reveal(box, t('intro.lines.start_drag_midpoint'), { duration: 0 });
62749 context.history().on('change.intro', function(changed) {
62750 if (changed.created().length === 1) {
62751 continueTo(continueDragMidpoint);
62755 context.on('enter.intro', function(mode) {
62756 if (mode.id !== 'select') {
62757 // keep Wood Road selected so midpoint triangles are drawn..
62758 context.enter(modeSelect(context, [woodRoadId]));
62762 function continueTo(nextStep) {
62763 context.map().on('move.intro drawn.intro', null);
62764 context.history().on('change.intro', null);
62765 context.on('enter.intro', null);
62771 function continueDragMidpoint() {
62772 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62773 return continueTo(updateLine);
62776 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
62777 var box = pad$1(woodRoadDragEndpoint, padding, context);
62780 var advance = function() {
62781 context.history().checkpoint('doneUpdateLine');
62782 continueTo(deleteLines);
62785 reveal(box, t('intro.lines.continue_drag_midpoint'),
62786 { buttonText: t('intro.ok'), buttonCallback: advance }
62789 context.map().on('move.intro drawn.intro', function() {
62790 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
62791 return continueTo(updateLine);
62793 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
62794 var box = pad$1(woodRoadDragEndpoint, padding, context);
62796 reveal(box, t('intro.lines.continue_drag_midpoint'),
62797 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
62801 function continueTo(nextStep) {
62802 context.map().on('move.intro drawn.intro', null);
62808 function deleteLines() {
62809 context.history().reset('doneUpdateLine');
62810 context.enter(modeBrowse(context));
62812 if (!context.hasEntity(washingtonStreetId) ||
62813 !context.hasEntity(twelfthAvenueId) ||
62814 !context.hasEntity(eleventhAvenueEndId)) {
62815 return chapter.restart();
62818 var msec = transitionTime(deleteLinesLoc, context.map().center());
62819 if (msec) { reveal(null, null, { duration: 0 }); }
62820 context.map().zoom(18).centerEase(deleteLinesLoc, msec);
62822 timeout(function() {
62823 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
62824 var box = pad$1(deleteLinesLoc, padding, context);
62827 var advance = function() { continueTo(rightClickIntersection); };
62829 reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }),
62830 { buttonText: t('intro.ok'), buttonCallback: advance }
62833 context.map().on('move.intro drawn.intro', function() {
62834 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
62835 var box = pad$1(deleteLinesLoc, padding, context);
62838 reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }),
62839 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
62843 context.history().on('change.intro', function() {
62844 timeout(function() {
62845 continueTo(deleteLines);
62846 }, 500); // after any transition (e.g. if user deleted intersection)
62851 function continueTo(nextStep) {
62852 context.map().on('move.intro drawn.intro', null);
62853 context.history().on('change.intro', null);
62859 function rightClickIntersection() {
62860 context.history().reset('doneUpdateLine');
62861 context.enter(modeBrowse(context));
62863 context.map().zoom(18).centerEase(eleventhAvenueEnd, 500);
62865 timeout(function() {
62866 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
62867 var box = pad$1(eleventhAvenueEnd, padding, context);
62868 reveal(box, t('intro.lines.rightclick_intersection',
62869 { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') })
62872 context.map().on('move.intro drawn.intro', function() {
62873 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
62874 var box = pad$1(eleventhAvenueEnd, padding, context);
62875 reveal(box, t('intro.lines.rightclick_intersection',
62876 { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') }),
62881 context.on('enter.intro', function(mode) {
62882 if (mode.id !== 'select') return;
62883 var ids = context.selectedIDs();
62884 if (ids.length !== 1 || ids[0] !== eleventhAvenueEndId) return;
62886 timeout(function() {
62887 var node = selectMenuItem('split').node();
62889 continueTo(splitIntersection);
62890 }, 300); // after menu visible
62893 context.history().on('change.intro', function() {
62894 timeout(function() {
62895 continueTo(deleteLines);
62896 }, 300); // after any transition (e.g. if user deleted intersection)
62901 function continueTo(nextStep) {
62902 context.map().on('move.intro drawn.intro', null);
62903 context.on('enter.intro', null);
62904 context.history().on('change.intro', null);
62910 function splitIntersection() {
62911 if (!context.hasEntity(washingtonStreetId) ||
62912 !context.hasEntity(twelfthAvenueId) ||
62913 !context.hasEntity(eleventhAvenueEndId)) {
62914 return continueTo(deleteLines);
62917 var node = selectMenuItem('split').node();
62918 if (!node) { return continueTo(rightClickIntersection); }
62920 var wasChanged = false;
62921 var menuCoords = context.map().mouseCoordinates();
62922 washingtonSegmentId = null;
62924 revealEditMenu(menuCoords, t('intro.lines.split_intersection',
62925 { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') })
62928 context.map().on('move.intro drawn.intro', function() {
62929 var node = selectMenuItem('split').node();
62930 if (!wasChanged && !node) { return continueTo(rightClickIntersection); }
62932 revealEditMenu(menuCoords, t('intro.lines.split_intersection',
62933 { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') }),
62938 context.history().on('change.intro', function(changed) {
62940 timeout(function() {
62941 if (context.history().undoAnnotation() === t('operations.split.annotation.line')) {
62942 washingtonSegmentId = changed.created()[0].id;
62943 continueTo(didSplit);
62945 washingtonSegmentId = null;
62946 continueTo(retrySplit);
62948 }, 300); // after any transition (e.g. if user deleted intersection)
62951 function continueTo(nextStep) {
62952 context.map().on('move.intro drawn.intro', null);
62953 context.history().on('change.intro', null);
62959 function retrySplit() {
62960 context.enter(modeBrowse(context));
62961 context.map().zoom(18).centerEase(eleventhAvenueEnd, 500);
62962 var advance = function() { continueTo(rightClickIntersection); };
62964 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
62965 var box = pad$1(eleventhAvenueEnd, padding, context);
62966 reveal(box, t('intro.lines.retry_split'),
62967 { buttonText: t('intro.ok'), buttonCallback: advance }
62970 context.map().on('move.intro drawn.intro', function() {
62971 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
62972 var box = pad$1(eleventhAvenueEnd, padding, context);
62973 reveal(box, t('intro.lines.retry_split'),
62974 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
62978 function continueTo(nextStep) {
62979 context.map().on('move.intro drawn.intro', null);
62985 function didSplit() {
62986 if (!washingtonSegmentId ||
62987 !context.hasEntity(washingtonSegmentId) ||
62988 !context.hasEntity(washingtonStreetId) ||
62989 !context.hasEntity(twelfthAvenueId) ||
62990 !context.hasEntity(eleventhAvenueEndId)) {
62991 return continueTo(rightClickIntersection);
62994 var ids = context.selectedIDs();
62995 var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single');
62996 var street = t('intro.graph.name.washington-street');
62998 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
62999 var box = pad$1(twelfthAvenue, padding, context);
63000 box.width = box.width / 2;
63001 reveal(box, t(string, { street1: street, street2: street }),
63005 timeout(function() {
63006 context.map().zoom(18).centerEase(twelfthAvenue, 500);
63008 context.map().on('move.intro drawn.intro', function() {
63009 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
63010 var box = pad$1(twelfthAvenue, padding, context);
63011 box.width = box.width / 2;
63012 reveal(box, t(string, { street1: street, street2: street }),
63016 }, 600); // after initial reveal and curtain cut
63018 context.on('enter.intro', function() {
63019 var ids = context.selectedIDs();
63020 if (ids.length === 1 && ids[0] === washingtonSegmentId) {
63021 continueTo(multiSelect);
63025 context.history().on('change.intro', function() {
63026 if (!washingtonSegmentId ||
63027 !context.hasEntity(washingtonSegmentId) ||
63028 !context.hasEntity(washingtonStreetId) ||
63029 !context.hasEntity(twelfthAvenueId) ||
63030 !context.hasEntity(eleventhAvenueEndId)) {
63031 return continueTo(rightClickIntersection);
63035 function continueTo(nextStep) {
63036 context.map().on('move.intro drawn.intro', null);
63037 context.on('enter.intro', null);
63038 context.history().on('change.intro', null);
63044 function multiSelect() {
63045 if (!washingtonSegmentId ||
63046 !context.hasEntity(washingtonSegmentId) ||
63047 !context.hasEntity(washingtonStreetId) ||
63048 !context.hasEntity(twelfthAvenueId) ||
63049 !context.hasEntity(eleventhAvenueEndId)) {
63050 return continueTo(rightClickIntersection);
63053 var ids = context.selectedIDs();
63054 var hasWashington = ids.indexOf(washingtonSegmentId) !== -1;
63055 var hasTwelfth = ids.indexOf(twelfthAvenueId) !== -1;
63057 if (hasWashington && hasTwelfth) {
63058 return continueTo(multiRightClick);
63059 } else if (!hasWashington && !hasTwelfth) {
63060 return continueTo(didSplit);
63063 context.map().zoom(18).centerEase(twelfthAvenue, 500);
63065 timeout(function() {
63066 var selected, other, padding, box;
63067 if (hasWashington) {
63068 selected = t('intro.graph.name.washington-street');
63069 other = t('intro.graph.name.12th-avenue');
63070 padding = 60 * Math.pow(2, context.map().zoom() - 18);
63071 box = pad$1(twelfthAvenueEnd, padding, context);
63074 selected = t('intro.graph.name.12th-avenue');
63075 other = t('intro.graph.name.washington-street');
63076 padding = 200 * Math.pow(2, context.map().zoom() - 18);
63077 box = pad$1(twelfthAvenue, padding, context);
63082 t('intro.lines.multi_select', { selected: selected, other1: other, other2: other })
63085 context.map().on('move.intro drawn.intro', function() {
63086 if (hasWashington) {
63087 selected = t('intro.graph.name.washington-street');
63088 other = t('intro.graph.name.12th-avenue');
63089 padding = 60 * Math.pow(2, context.map().zoom() - 18);
63090 box = pad$1(twelfthAvenueEnd, padding, context);
63093 selected = t('intro.graph.name.12th-avenue');
63094 other = t('intro.graph.name.washington-street');
63095 padding = 200 * Math.pow(2, context.map().zoom() - 18);
63096 box = pad$1(twelfthAvenue, padding, context);
63101 t('intro.lines.multi_select', { selected: selected, other1: other, other2: other }),
63106 context.on('enter.intro', function() {
63107 continueTo(multiSelect);
63110 context.history().on('change.intro', function() {
63111 if (!washingtonSegmentId ||
63112 !context.hasEntity(washingtonSegmentId) ||
63113 !context.hasEntity(washingtonStreetId) ||
63114 !context.hasEntity(twelfthAvenueId) ||
63115 !context.hasEntity(eleventhAvenueEndId)) {
63116 return continueTo(rightClickIntersection);
63121 function continueTo(nextStep) {
63122 context.map().on('move.intro drawn.intro', null);
63123 context.on('enter.intro', null);
63124 context.history().on('change.intro', null);
63130 function multiRightClick() {
63131 if (!washingtonSegmentId ||
63132 !context.hasEntity(washingtonSegmentId) ||
63133 !context.hasEntity(washingtonStreetId) ||
63134 !context.hasEntity(twelfthAvenueId) ||
63135 !context.hasEntity(eleventhAvenueEndId)) {
63136 return continueTo(rightClickIntersection);
63139 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
63140 var box = pad$1(twelfthAvenue, padding, context);
63141 reveal(box, t('intro.lines.multi_rightclick'));
63143 context.map().on('move.intro drawn.intro', function() {
63144 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
63145 var box = pad$1(twelfthAvenue, padding, context);
63146 reveal(box, t('intro.lines.multi_rightclick'), { duration: 0 });
63149 select(window).on('click.intro contextmenu.intro', function() {
63150 timeout(function() {
63151 var ids = context.selectedIDs();
63152 if (ids.length === 2 &&
63153 ids.indexOf(twelfthAvenueId) !== -1 &&
63154 ids.indexOf(washingtonSegmentId) !== -1) {
63155 var node = selectMenuItem('delete').node();
63157 continueTo(multiDelete);
63158 } else if (ids.length === 1 &&
63159 ids.indexOf(washingtonSegmentId) !== -1) {
63160 return continueTo(multiSelect);
63162 return continueTo(didSplit);
63164 }, 300); // after edit menu visible
63167 context.history().on('change.intro', function() {
63168 if (!washingtonSegmentId ||
63169 !context.hasEntity(washingtonSegmentId) ||
63170 !context.hasEntity(washingtonStreetId) ||
63171 !context.hasEntity(twelfthAvenueId) ||
63172 !context.hasEntity(eleventhAvenueEndId)) {
63173 return continueTo(rightClickIntersection);
63177 function continueTo(nextStep) {
63178 context.map().on('move.intro drawn.intro', null);
63179 select(window).on('click.intro contextmenu.intro', null, true);
63180 context.history().on('change.intro', null);
63186 function multiDelete() {
63187 if (!washingtonSegmentId ||
63188 !context.hasEntity(washingtonSegmentId) ||
63189 !context.hasEntity(washingtonStreetId) ||
63190 !context.hasEntity(twelfthAvenueId) ||
63191 !context.hasEntity(eleventhAvenueEndId)) {
63192 return continueTo(rightClickIntersection);
63195 var node = selectMenuItem('delete').node();
63196 if (!node) return continueTo(multiRightClick);
63198 var menuCoords = context.map().mouseCoordinates();
63199 revealEditMenu(menuCoords,
63200 t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') })
63203 context.map().on('move.intro drawn.intro', function() {
63204 revealEditMenu(menuCoords,
63205 t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') }),
63210 context.on('exit.intro', function() {
63211 if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) {
63212 return continueTo(multiSelect); // left select mode but roads still exist
63216 context.history().on('change.intro', function() {
63217 if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) {
63218 continueTo(retryDelete); // changed something but roads still exist
63224 function continueTo(nextStep) {
63225 context.map().on('move.intro drawn.intro', null);
63226 context.on('exit.intro', null);
63227 context.history().on('change.intro', null);
63233 function retryDelete() {
63234 context.enter(modeBrowse(context));
63236 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
63237 var box = pad$1(twelfthAvenue, padding, context);
63238 reveal(box, t('intro.lines.retry_delete'), {
63239 buttonText: t('intro.ok'),
63240 buttonCallback: function() { continueTo(multiSelect); }
63243 function continueTo(nextStep) {
63250 dispatch$$1.call('done');
63251 reveal('#id-container',
63252 t('intro.lines.play', { next: t('intro.buildings.title') }), {
63253 tooltipBox: '.intro-nav-wrap .chapter-building',
63254 buttonText: t('intro.ok'),
63255 buttonCallback: function() { reveal('#id-container'); }
63261 chapter.enter = function() {
63266 chapter.exit = function() {
63267 timeouts.forEach(window.clearTimeout);
63268 select(window).on('mousedown.intro', null, true);
63269 context.on('enter.intro exit.intro', null);
63270 context.map().on('move.intro drawn.intro', null);
63271 context.history().on('change.intro', null);
63272 select('.inspector-wrap').on('wheel.intro', null);
63273 select('.preset-list-button').on('click.intro', null);
63277 chapter.restart = function() {
63283 return utilRebind(chapter, dispatch$$1, 'on');
63286 function uiIntroBuilding(context, reveal) {
63287 var dispatch$$1 = dispatch('done'),
63288 house = [-85.62815, 41.95638],
63289 tank = [-85.62732, 41.95347],
63290 buildingCatetory = context.presets().item('category-building'),
63291 housePreset = context.presets().item('building/house'),
63292 tankPreset = context.presets().item('man_made/storage_tank'),
63299 title: 'intro.buildings.title'
63303 function timeout(f, t$$1) {
63304 timeouts.push(window.setTimeout(f, t$$1));
63308 function eventCancel() {
63309 event.stopPropagation();
63310 event.preventDefault();
63314 function revealHouse(center, text$$1, options) {
63315 var padding = 160 * Math.pow(2, context.map().zoom() - 20);
63316 var box = pad$1(center, padding, context);
63317 reveal(box, text$$1, options);
63321 function revealTank(center, text$$1, options) {
63322 var padding = 190 * Math.pow(2, context.map().zoom() - 19.5);
63323 var box = pad$1(center, padding, context);
63324 reveal(box, text$$1, options);
63328 function revealEditMenu(loc, text$$1, options) {
63329 var rect = context.surfaceRect();
63330 var point = context.curtainProjection(loc);
63332 var width = 250 + (2 * pad);
63334 var startX = rect.left + point[0];
63335 var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad);
63338 top: point[1] + rect.top - 60,
63342 reveal(box, text$$1, options);
63346 function addHouse() {
63347 context.enter(modeBrowse(context));
63348 context.history().reset('initial');
63351 var msec = transitionTime(house, context.map().center());
63352 if (msec) { reveal(null, null, { duration: 0 }); }
63353 context.map().zoom(19).centerEase(house, msec);
63355 timeout(function() {
63356 var tooltip = reveal('button.add-area',
63357 t('intro.buildings.add_building', { button: icon('#icon-area', 'pre-text') }));
63359 tooltip.selectAll('.tooltip-inner')
63360 .insert('svg', 'span')
63361 .attr('class', 'tooltip-illustration')
63363 .attr('xlink:href', '#building-images');
63365 context.on('enter.intro', function(mode) {
63366 if (mode.id !== 'add-area') return;
63367 continueTo(startHouse);
63371 function continueTo(nextStep) {
63372 context.on('enter.intro', null);
63378 function startHouse() {
63379 if (context.mode().id !== 'add-area') {
63380 return continueTo(addHouse);
63384 context.map().zoomEase(20, 500);
63386 timeout(function() {
63387 revealHouse(house, t('intro.buildings.start_building'));
63389 context.map().on('move.intro drawn.intro', function() {
63390 revealHouse(house, t('intro.buildings.start_building'), { duration: 0 });
63393 context.on('enter.intro', function(mode) {
63394 if (mode.id !== 'draw-area') return chapter.restart();
63395 continueTo(continueHouse);
63398 }, 550); // after easing
63400 function continueTo(nextStep) {
63401 context.map().on('move.intro drawn.intro', null);
63402 context.on('enter.intro', null);
63408 function continueHouse() {
63409 if (context.mode().id !== 'draw-area') {
63410 return continueTo(addHouse);
63415 revealHouse(house, t('intro.buildings.continue_building'));
63417 context.map().on('move.intro drawn.intro', function() {
63418 revealHouse(house, t('intro.buildings.continue_building'), { duration: 0 });
63421 context.on('enter.intro', function(mode) {
63422 if (mode.id === 'draw-area') {
63424 } else if (mode.id === 'select') {
63425 var graph = context.graph(),
63426 way = context.entity(context.selectedIDs()[0]),
63427 nodes = graph.childNodes(way),
63428 points = lodash.uniq(nodes).map(function(n) { return context.projection(n.loc); });
63430 if (isMostlySquare(points)) {
63432 return continueTo(chooseCategoryBuilding);
63434 return continueTo(retryHouse);
63438 return chapter.restart();
63442 function continueTo(nextStep) {
63443 context.map().on('move.intro drawn.intro', null);
63444 context.on('enter.intro', null);
63450 function retryHouse() {
63451 var onClick = function() { continueTo(addHouse); };
63453 revealHouse(house, t('intro.buildings.retry_building'),
63454 { buttonText: t('intro.ok'), buttonCallback: onClick }
63457 context.map().on('move.intro drawn.intro', function() {
63458 revealHouse(house, t('intro.buildings.retry_building'),
63459 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
63463 function continueTo(nextStep) {
63464 context.map().on('move.intro drawn.intro', null);
63470 function chooseCategoryBuilding() {
63471 if (!houseId || !context.hasEntity(houseId)) {
63474 var ids = context.selectedIDs();
63475 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
63476 context.enter(modeSelect(context, [houseId]));
63479 // disallow scrolling
63480 select('.inspector-wrap').on('wheel.intro', eventCancel);
63482 timeout(function() {
63483 // reset pane, in case user somehow happened to change it..
63484 select('.inspector-wrap .panewrap').style('right', '-100%');
63486 var button = select('.preset-category-building .preset-list-button');
63488 reveal(button.node(),
63489 t('intro.buildings.choose_category_building', { category: buildingCatetory.name() })
63492 button.on('click.intro', function() {
63493 button.on('click.intro', null);
63494 continueTo(choosePresetHouse);
63497 }, 400); // after preset list pane visible..
63500 context.on('enter.intro', function(mode) {
63501 if (!houseId || !context.hasEntity(houseId)) {
63502 return continueTo(addHouse);
63504 var ids = context.selectedIDs();
63505 if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) {
63506 return continueTo(chooseCategoryBuilding);
63510 function continueTo(nextStep) {
63511 select('.inspector-wrap').on('wheel.intro', null);
63512 select('.preset-list-button').on('click.intro', null);
63513 context.on('enter.intro', null);
63519 function choosePresetHouse() {
63520 if (!houseId || !context.hasEntity(houseId)) {
63523 var ids = context.selectedIDs();
63524 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
63525 context.enter(modeSelect(context, [houseId]));
63528 // disallow scrolling
63529 select('.inspector-wrap').on('wheel.intro', eventCancel);
63531 timeout(function() {
63532 // reset pane, in case user somehow happened to change it..
63533 select('.inspector-wrap .panewrap').style('right', '-100%');
63535 var button = select('.preset-building-house .preset-list-button');
63537 reveal(button.node(),
63538 t('intro.buildings.choose_preset_house', { preset: housePreset.name() }),
63542 button.on('click.intro', function() {
63543 button.on('click.intro', null);
63544 continueTo(closeEditorHouse);
63548 }, 400); // after preset list pane visible..
63550 context.on('enter.intro', function(mode) {
63551 if (!houseId || !context.hasEntity(houseId)) {
63552 return continueTo(addHouse);
63554 var ids = context.selectedIDs();
63555 if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) {
63556 return continueTo(chooseCategoryBuilding);
63560 function continueTo(nextStep) {
63561 select('.inspector-wrap').on('wheel.intro', null);
63562 select('.preset-list-button').on('click.intro', null);
63563 context.on('enter.intro', null);
63569 function closeEditorHouse() {
63570 if (!houseId || !context.hasEntity(houseId)) {
63573 var ids = context.selectedIDs();
63574 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
63575 context.enter(modeSelect(context, [houseId]));
63578 context.history().checkpoint('hasHouse');
63580 context.on('exit.intro', function() {
63581 continueTo(rightClickHouse);
63584 timeout(function() {
63585 reveal('.entity-editor-pane',
63586 t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') })
63590 function continueTo(nextStep) {
63591 context.on('exit.intro', null);
63597 function rightClickHouse() {
63598 if (!houseId) return chapter.restart();
63600 context.enter(modeBrowse(context));
63601 context.history().reset('hasHouse');
63602 context.map().centerEase(house, 500);
63604 timeout(function() {
63605 if (context.map().zoom() < 20) {
63606 context.map().zoomEase(20, 500);
63610 context.on('enter.intro', function(mode) {
63611 if (mode.id !== 'select') return;
63612 var ids = context.selectedIDs();
63613 if (ids.length !== 1 || ids[0] !== houseId) return;
63615 timeout(function() {
63616 var node = selectMenuItem('orthogonalize').node();
63618 continueTo(clickSquare);
63619 }, 300); // after menu visible
63622 context.map().on('move.intro drawn.intro', function() {
63623 revealHouse(house, t('intro.buildings.rightclick_building'), { duration: 0 });
63626 context.history().on('change.intro', function() {
63627 continueTo(rightClickHouse);
63630 function continueTo(nextStep) {
63631 context.on('enter.intro', null);
63632 context.map().on('move.intro drawn.intro', null);
63633 context.history().on('change.intro', null);
63639 function clickSquare() {
63640 if (!houseId) return chapter.restart();
63641 var entity = context.hasEntity(houseId);
63642 if (!entity) return continueTo(rightClickHouse);
63644 var node = selectMenuItem('orthogonalize').node();
63645 if (!node) { return continueTo(rightClickHouse); }
63647 var wasChanged = false;
63648 var menuCoords = context.map().mouseCoordinates();
63650 revealEditMenu(menuCoords,
63651 t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') })
63654 context.on('enter.intro', function(mode) {
63655 if (mode.id === 'browse') {
63656 continueTo(rightClickHouse);
63657 } else if (mode.id === 'move' || mode.id === 'rotate') {
63658 continueTo(retryClickSquare);
63662 context.map().on('move.intro drawn.intro', function() {
63663 var node = selectMenuItem('orthogonalize').node();
63664 if (!wasChanged && !node) { return continueTo(rightClickHouse); }
63666 revealEditMenu(menuCoords,
63667 t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') }),
63672 context.history().on('change.intro', function() {
63674 context.history().on('change.intro', null);
63676 // Something changed. Wait for transition to complete and check undo annotation.
63677 timeout(function() {
63678 if (context.history().undoAnnotation() === t('operations.orthogonalize.annotation.area')) {
63679 continueTo(doneSquare);
63681 continueTo(retryClickSquare);
63683 }, 500); // after transitioned actions
63686 function continueTo(nextStep) {
63687 context.on('enter.intro', null);
63688 context.map().on('move.intro drawn.intro', null);
63689 context.history().on('change.intro', null);
63695 function retryClickSquare() {
63696 context.enter(modeBrowse(context));
63698 revealHouse(house, t('intro.buildings.retry_square'), {
63699 buttonText: t('intro.ok'),
63700 buttonCallback: function() { continueTo(rightClickHouse); }
63703 function continueTo(nextStep) {
63709 function doneSquare() {
63710 context.history().checkpoint('doneSquare');
63712 revealHouse(house, t('intro.buildings.done_square'), {
63713 buttonText: t('intro.ok'),
63714 buttonCallback: function() { continueTo(addTank); }
63717 function continueTo(nextStep) {
63723 function addTank() {
63724 context.enter(modeBrowse(context));
63725 context.history().reset('doneSquare');
63728 var msec = transitionTime(tank, context.map().center());
63729 if (msec) { reveal(null, null, { duration: 0 }); }
63730 context.map().zoom(19.5).centerEase(tank, msec);
63732 timeout(function() {
63733 reveal('button.add-area',
63734 t('intro.buildings.add_tank', { button: icon('#icon-area', 'pre-text') })
63737 context.on('enter.intro', function(mode) {
63738 if (mode.id !== 'add-area') return;
63739 continueTo(startTank);
63743 function continueTo(nextStep) {
63744 context.on('enter.intro', null);
63750 function startTank() {
63751 if (context.mode().id !== 'add-area') {
63752 return continueTo(addTank);
63757 timeout(function() {
63758 revealTank(tank, t('intro.buildings.start_tank'));
63760 context.map().on('move.intro drawn.intro', function() {
63761 revealTank(tank, t('intro.buildings.start_tank'), { duration: 0 });
63764 context.on('enter.intro', function(mode) {
63765 if (mode.id !== 'draw-area') return chapter.restart();
63766 continueTo(continueTank);
63769 }, 550); // after easing
63771 function continueTo(nextStep) {
63772 context.map().on('move.intro drawn.intro', null);
63773 context.on('enter.intro', null);
63779 function continueTank() {
63780 if (context.mode().id !== 'draw-area') {
63781 return continueTo(addTank);
63786 revealTank(tank, t('intro.buildings.continue_tank'));
63788 context.map().on('move.intro drawn.intro', function() {
63789 revealTank(tank, t('intro.buildings.continue_tank'), { duration: 0 });
63792 context.on('enter.intro', function(mode) {
63793 if (mode.id === 'draw-area') {
63795 } else if (mode.id === 'select') {
63796 tankId = context.selectedIDs()[0];
63797 return continueTo(searchPresetTank);
63799 return continueTo(addTank);
63803 function continueTo(nextStep) {
63804 context.map().on('move.intro drawn.intro', null);
63805 context.on('enter.intro', null);
63811 function searchPresetTank() {
63812 if (!tankId || !context.hasEntity(tankId)) {
63815 var ids = context.selectedIDs();
63816 if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) {
63817 context.enter(modeSelect(context, [tankId]));
63820 // disallow scrolling
63821 select('.inspector-wrap').on('wheel.intro', eventCancel);
63823 timeout(function() {
63824 // reset pane, in case user somehow happened to change it..
63825 select('.inspector-wrap .panewrap').style('right', '-100%');
63827 select('.preset-search-input')
63828 .on('keydown.intro', null)
63829 .on('keyup.intro', checkPresetSearch);
63831 reveal('.preset-search-input',
63832 t('intro.buildings.search_tank', { preset: tankPreset.name() })
63834 }, 400); // after preset list pane visible..
63836 context.on('enter.intro', function(mode) {
63837 if (!tankId || !context.hasEntity(tankId)) {
63838 return continueTo(addTank);
63841 var ids = context.selectedIDs();
63842 if (mode.id !== 'select' || !ids.length || ids[0] !== tankId) {
63843 // keep the user's area selected..
63844 context.enter(modeSelect(context, [tankId]));
63846 // reset pane, in case user somehow happened to change it..
63847 select('.inspector-wrap .panewrap').style('right', '-100%');
63848 // disallow scrolling
63849 select('.inspector-wrap').on('wheel.intro', eventCancel);
63851 select('.preset-search-input')
63852 .on('keydown.intro', null)
63853 .on('keyup.intro', checkPresetSearch);
63855 reveal('.preset-search-input',
63856 t('intro.buildings.search_tank', { preset: tankPreset.name() })
63859 context.history().on('change.intro', null);
63863 function checkPresetSearch() {
63864 var first = select('.preset-list-item:first-child');
63866 if (first.classed('preset-man_made-storage_tank')) {
63867 reveal(first.select('.preset-list-button').node(),
63868 t('intro.buildings.choose_tank', { preset: tankPreset.name() }),
63872 select('.preset-search-input')
63873 .on('keydown.intro', eventCancel, true)
63874 .on('keyup.intro', null);
63876 context.history().on('change.intro', function() {
63877 continueTo(closeEditorTank);
63882 function continueTo(nextStep) {
63883 select('.inspector-wrap').on('wheel.intro', null);
63884 context.on('enter.intro', null);
63885 context.history().on('change.intro', null);
63886 select('.preset-search-input').on('keydown.intro keyup.intro', null);
63892 function closeEditorTank() {
63893 if (!tankId || !context.hasEntity(tankId)) {
63896 var ids = context.selectedIDs();
63897 if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) {
63898 context.enter(modeSelect(context, [tankId]));
63901 context.history().checkpoint('hasTank');
63903 context.on('exit.intro', function() {
63904 continueTo(rightClickTank);
63907 timeout(function() {
63908 reveal('.entity-editor-pane',
63909 t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') })
63913 function continueTo(nextStep) {
63914 context.on('exit.intro', null);
63920 function rightClickTank() {
63921 if (!tankId) return continueTo(addTank);
63923 context.enter(modeBrowse(context));
63924 context.history().reset('hasTank');
63925 context.map().centerEase(tank, 500);
63927 timeout(function() {
63928 context.on('enter.intro', function(mode) {
63929 if (mode.id !== 'select') return;
63930 var ids = context.selectedIDs();
63931 if (ids.length !== 1 || ids[0] !== tankId) return;
63933 timeout(function() {
63934 var node = selectMenuItem('circularize').node();
63936 continueTo(clickCircle);
63937 }, 300); // after menu visible
63940 revealTank(tank, t('intro.buildings.rightclick_tank'));
63942 context.map().on('move.intro drawn.intro', function() {
63943 revealTank(tank, t('intro.buildings.rightclick_tank'), { duration: 0 });
63946 context.history().on('change.intro', function() {
63947 continueTo(rightClickTank);
63952 function continueTo(nextStep) {
63953 context.on('enter.intro', null);
63954 context.map().on('move.intro drawn.intro', null);
63955 context.history().on('change.intro', null);
63961 function clickCircle() {
63962 if (!tankId) return chapter.restart();
63963 var entity = context.hasEntity(tankId);
63964 if (!entity) return continueTo(rightClickTank);
63966 var node = selectMenuItem('circularize').node();
63967 if (!node) { return continueTo(rightClickTank); }
63969 var wasChanged = false;
63970 var menuCoords = context.map().mouseCoordinates();
63972 revealEditMenu(menuCoords,
63973 t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') })
63976 context.on('enter.intro', function(mode) {
63977 if (mode.id === 'browse') {
63978 continueTo(rightClickTank);
63979 } else if (mode.id === 'move' || mode.id === 'rotate') {
63980 continueTo(retryClickCircle);
63984 context.map().on('move.intro drawn.intro', function() {
63985 var node = selectMenuItem('circularize').node();
63986 if (!wasChanged && !node) { return continueTo(rightClickTank); }
63988 revealEditMenu(menuCoords,
63989 t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') }),
63994 context.history().on('change.intro', function() {
63996 context.history().on('change.intro', null);
63998 // Something changed. Wait for transition to complete and check undo annotation.
63999 timeout(function() {
64000 if (context.history().undoAnnotation() === t('operations.circularize.annotation.area')) {
64003 continueTo(retryClickCircle);
64005 }, 500); // after transitioned actions
64008 function continueTo(nextStep) {
64009 context.on('enter.intro', null);
64010 context.map().on('move.intro drawn.intro', null);
64011 context.history().on('change.intro', null);
64017 function retryClickCircle() {
64018 context.enter(modeBrowse(context));
64020 revealTank(tank, t('intro.buildings.retry_circle'), {
64021 buttonText: t('intro.ok'),
64022 buttonCallback: function() { continueTo(rightClickTank); }
64025 function continueTo(nextStep) {
64032 dispatch$$1.call('done');
64033 reveal('#id-container',
64034 t('intro.buildings.play', { next: t('intro.startediting.title') }), {
64035 tooltipBox: '.intro-nav-wrap .chapter-startEditing',
64036 buttonText: t('intro.ok'),
64037 buttonCallback: function() { reveal('#id-container'); }
64043 chapter.enter = function() {
64048 chapter.exit = function() {
64049 timeouts.forEach(window.clearTimeout);
64050 context.on('enter.intro exit.intro', null);
64051 context.map().on('move.intro drawn.intro', null);
64052 context.history().on('change.intro', null);
64053 select('.inspector-wrap').on('wheel.intro', null);
64054 select('.preset-search-input').on('keydown.intro keyup.intro', null);
64055 select('.more-fields .combobox-input').on('click.intro', null);
64059 chapter.restart = function() {
64065 return utilRebind(chapter, dispatch$$1, 'on');
64068 function uiIntroStartEditing(context, reveal) {
64069 var dispatch$$1 = dispatch('done', 'startEditing'),
64070 modalSelection = select(null);
64074 title: 'intro.startediting.title'
64077 function showHelp() {
64078 reveal('.map-control.help-control',
64079 t('intro.startediting.help', { button: icon('#icon-help', 'pre-text'), key: t('help.key') }), {
64080 buttonText: t('intro.ok'),
64081 buttonCallback: function() { shortcuts(); }
64086 function shortcuts() {
64087 reveal('.map-control.help-control',
64088 t('intro.startediting.shortcuts', { key: t('shortcuts.toggle.key') }), {
64089 buttonText: t('intro.ok'),
64090 buttonCallback: function() { showSave(); }
64095 function showSave() {
64096 selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
64097 reveal('#bar button.save',
64098 t('intro.startediting.save'), {
64099 buttonText: t('intro.ok'),
64100 buttonCallback: function() { showStart(); }
64105 function showStart() {
64106 selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
64108 modalSelection = uiModal(context.container());
64110 modalSelection.select('.modal')
64111 .attr('class', 'modal-splash modal col6');
64113 modalSelection.selectAll('.close').remove();
64115 var startbutton = modalSelection.select('.content')
64116 .attr('class', 'fillL')
64118 .attr('class', 'modal-section huge-modal-button')
64119 .on('click', function() {
64120 modalSelection.remove();
64125 .attr('class', 'illustration')
64127 .attr('xlink:href', '#logo-walkthrough');
64131 .text(t('intro.startediting.start'));
64133 dispatch$$1.call('startEditing');
64137 chapter.enter = function() {
64142 chapter.exit = function() {
64143 modalSelection.remove();
64144 selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
64148 return utilRebind(chapter, dispatch$$1, 'on');
64152 welcome: uiIntroWelcome,
64153 navigation: uiIntroNavigation,
64154 point: uiIntroPoint,
64157 building: uiIntroBuilding,
64158 startEditing: uiIntroStartEditing
64161 var chapterFlow = [
64172 function uiIntro(context) {
64173 var introGraph = {},
64177 // create entities for intro graph and localize names
64178 for (var id in dataIntroGraph) {
64179 introGraph[id] = osmEntity$$1(localize(dataIntroGraph[id]));
64183 function intro(selection$$1) {
64184 context.enter(modeBrowse(context));
64186 // Save current map state
64187 var history = context.history().toJSON(),
64188 hash = window.location.hash,
64189 center = context.map().center(),
64190 zoom$$1 = context.map().zoom(),
64191 background = context.background().baseLayerSource(),
64192 overlays = context.background().overlayLayerSources(),
64193 opacity = selectAll('#map .layer-background').style('opacity'),
64194 loadedTiles = context.connection().loadedTiles(),
64195 baseEntities = context.history().graph().base().entities,
64196 countryCode = services.geocoder.countryCode;
64199 context.inIntro(true);
64201 // Load semi-real data used in intro
64202 context.connection().toggle(false).reset();
64203 context.history().reset();
64204 context.history().merge(values(coreGraph$$1().load(introGraph).entities));
64205 context.history().checkpoint('initial');
64206 context.background().bing();
64207 overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });
64210 services.geocoder.countryCode = function(location, callback) {
64211 callback(null, t('intro.graph.countrycode'));
64214 selectAll('#map .layer-background').style('opacity', 1);
64216 var curtain = uiCurtain();
64217 selection$$1.call(curtain);
64219 var chapters = chapterFlow.map(function(chapter, i) {
64220 var s = chapterUi[chapter](context, curtain.reveal)
64221 .on('done', function() {
64222 context.presets().init(); // clear away "recent" presets
64224 buttons.filter(function(d) {
64225 return d.title === s.title;
64226 }).classed('finished', true);
64228 if (i < chapterFlow.length - 1) {
64229 var next = chapterFlow[i + 1];
64230 select('button.chapter-' + next)
64231 .classed('next', true);
64237 chapters[chapters.length - 1].on('startEditing', function() {
64240 selectAll('#map .layer-background').style('opacity', opacity);
64241 context.connection().toggle(true).reset().loadedTiles(loadedTiles);
64242 context.history().reset().merge(values(baseEntities));
64243 context.background().baseLayerSource(background);
64244 overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });
64245 if (history) context.history().fromJSON(history, false);
64246 context.map().centerZoom(center, zoom$$1);
64247 window.location.replace(hash);
64248 services.geocoder.countryCode = countryCode;
64249 context.inIntro(false);
64252 var navwrap = selection$$1
64254 .attr('class', 'intro-nav-wrap fillD');
64258 .attr('class', 'intro-nav-wrap-logo')
64260 .attr('xlink:href', '#logo-walkthrough');
64262 var buttonwrap = navwrap
64264 .attr('class', 'joined')
64265 .selectAll('button.chapter');
64267 var buttons = buttonwrap
64271 .attr('class', function(d, i) { return 'chapter chapter-' + chapterFlow[i]; })
64272 .on('click', enterChapter);
64276 .text(function(d) { return t(d.title); });
64280 .attr('class', 'status')
64281 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'));
64283 enterChapter(chapters[0]);
64286 function enterChapter(newChapter) {
64287 if (currChapter) { currChapter.exit(); }
64288 context.enter(modeBrowse(context));
64290 currChapter = newChapter;
64291 currChapter.enter();
64294 .classed('next', false)
64295 .classed('active', function(d) {
64296 return d.title === currChapter.title;
64305 function uiShortcuts() {
64306 var detected = utilDetect();
64308 var modalSelection;
64309 var savedSelection;
64312 var keybinding = d3keybinding('shortcuts')
64313 .on(t('shortcuts.toggle.key'), function () {
64314 if (selectAll('.modal-shortcuts').size()) { // already showing
64315 if (modalSelection) {
64316 modalSelection.close();
64317 modalSelection = null;
64320 modalSelection = uiModal(savedSelection);
64321 shortcutsModal(modalSelection);
64330 function shortcutsModal(modalSelection) {
64331 modalSelection.select('.modal')
64332 .classed('modal-shortcuts', true);
64334 var shortcutsModal = modalSelection.select('.content');
64338 .attr('class', 'modal-section')
64340 .text(t('shortcuts.title'));
64347 function render(selection$$1) {
64348 var wrapper = selection$$1
64349 .selectAll('.wrapper')
64352 var wrapperEnter = wrapper
64355 .attr('class', 'wrapper modal-section');
64357 var tabsBar = wrapperEnter
64359 .attr('class', 'tabs-bar');
64361 var shortcutsList = wrapperEnter
64363 .attr('class', 'shortcuts-list');
64365 wrapper = wrapper.merge(wrapperEnter);
64369 .data(dataShortcuts);
64371 var tabsEnter = tabs
64374 .attr('class', 'tab')
64375 .on('click', function (d, i) {
64377 render(selection$$1);
64382 .text(function (d) { return t(d.text); });
64388 wrapper.selectAll('.tab')
64389 .classed('active', function (d, i) {
64390 return i === activeTab;
64394 var shortcuts = shortcutsList
64395 .selectAll('.shortcut-tab')
64396 .data(dataShortcuts);
64398 var shortcutsEnter = shortcuts
64401 .attr('class', function(d) { return 'shortcut-tab shortcut-tab-' + d.tab; });
64403 var columnsEnter = shortcutsEnter
64404 .selectAll('.shortcut-column')
64405 .data(function (d) { return d.columns; })
64408 .attr('class', 'shortcut-column');
64410 var rowsEnter = columnsEnter
64411 .selectAll('.shortcut-row')
64412 .data(function (d) { return d.rows; })
64415 .attr('class', 'shortcut-row');
64418 var sectionRows = rowsEnter
64419 .filter(function (d) { return !d.shortcuts; });
64426 .attr('class', 'shortcut-section')
64428 .text(function (d) { return t(d.text); });
64431 var shortcutRows = rowsEnter
64432 .filter(function (d) { return d.shortcuts; });
64434 var shortcutKeys = shortcutRows
64436 .attr('class', 'shortcut-keys');
64438 var modifierKeys = shortcutKeys
64439 .filter(function (d) { return d.modifiers; });
64442 .selectAll('kbd.modifier')
64443 .data(function (d) {
64444 if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
64446 } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
64449 return d.modifiers;
64453 .each(function () {
64454 var selection$$1 = select(this);
64458 .attr('class', 'modifier')
64459 .text(function (d) { return uiCmd.display(d); });
64468 .selectAll('kbd.shortcut')
64469 .data(function (d) {
64470 var arr = d.shortcuts;
64471 if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
64473 } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
64477 return arr.map(function(s) {
64480 separator: d.separator
64485 .each(function (d, i, nodes) {
64486 var selection$$1 = select(this);
64487 var click = d.shortcut.toLowerCase().match(/(.*).click/);
64489 if (click && click[1]) {
64491 .call(svgIcon('#walkthrough-mouse', 'mouseclick', click[1]));
64495 .attr('class', 'shortcut')
64496 .text(function (d) {
64497 var key = d.shortcut;
64498 return key.indexOf('.') !== -1 ? uiCmd.display(t(key)) : uiCmd.display(key);
64502 if (i < nodes.length - 1) {
64505 .text(d.separator || '\u00a0' + t('shortcuts.or') + '\u00a0');
64511 .filter(function(d) { return d.gesture; })
64512 .each(function () {
64513 var selection$$1 = select(this);
64521 .attr('class', 'gesture')
64522 .text(function (d) { return t(d.gesture); });
64528 .attr('class', 'shortcut-desc')
64529 .text(function (d) { return d.text ? t(d.text) : '\u00a0'; });
64532 shortcuts = shortcuts
64533 .merge(shortcutsEnter);
64536 wrapper.selectAll('.shortcut-tab')
64537 .style('display', function (d, i) {
64538 return i === activeTab ? 'flex' : 'none';
64543 return function(selection$$1, show) {
64544 savedSelection = selection$$1;
64546 modalSelection = uiModal(selection$$1);
64547 shortcutsModal(modalSelection);
64552 function uiHelp(context) {
64553 var key = t('help.key');
64557 'help.editing_saving',
64566 var docs = docKeys.map(function(key) {
64567 var text$$1 = t(key);
64569 title: text$$1.split('\n')[0].replace('#', '').trim(),
64570 html: marked(text$$1.split('\n').slice(1).join('\n'))
64575 function help(selection$$1) {
64582 function toggle() {
64583 if (event) event.preventDefault();
64584 tooltipBehavior.hide(button);
64585 setVisible(!button.classed('active'));
64589 function setVisible(show) {
64590 if (show !== shown) {
64591 button.classed('active', show);
64595 selection$$1.on('mousedown.help-inside', function() {
64596 return event.stopPropagation();
64598 pane.style('display', 'block')
64599 .style('right', '-500px')
64602 .style('right', '0px');
64604 pane.style('right', '0px')
64607 .style('right', '-500px')
64608 .on('end', function() {
64609 select(this).style('display', 'none');
64611 selection$$1.on('mousedown.help-inside', null);
64617 function clickHelp(d, i) {
64618 var rtl = (textDirection === 'rtl');
64619 pane.property('scrollTop', 0);
64620 doctitle.html(d.title);
64623 body.selectAll('a')
64624 .attr('target', '_blank');
64625 menuItems.classed('selected', function(m) {
64626 return m.title === d.title;
64631 nav.call(drawNext).call(drawPrevious);
64633 nav.call(drawPrevious).call(drawNext);
64637 function drawNext(selection$$1) {
64638 if (i < docs.length - 1) {
64639 var nextLink = selection$$1
64641 .attr('class', 'next')
64642 .on('click', function() {
64643 clickHelp(docs[i + 1], i + 1);
64648 .text(docs[i + 1].title)
64649 .call(svgIcon((rtl ? '#icon-backward' : '#icon-forward'), 'inline'));
64654 function drawPrevious(selection$$1) {
64656 var prevLink = selection$$1
64658 .attr('class', 'previous')
64659 .on('click', function() {
64660 clickHelp(docs[i - 1], i - 1);
64664 .call(svgIcon((rtl ? '#icon-forward' : '#icon-backward'), 'inline'))
64666 .text(docs[i - 1].title);
64672 function clickWalkthrough() {
64673 if (context.inIntro()) return;
64674 context.container().call(uiIntro(context));
64679 function clickShortcuts() {
64680 context.container().call(uiShortcuts(context), true);
64684 var pane = selection$$1.append('div')
64685 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
64686 tooltipBehavior = tooltip()
64687 .placement((textDirection === 'rtl') ? 'right' : 'left')
64689 .title(uiTooltipHtml(t('help.title'), key)),
64690 button = selection$$1.append('button')
64691 .attr('tabindex', -1)
64692 .on('click', toggle)
64693 .call(svgIcon('#icon-help', 'light'))
64694 .call(tooltipBehavior),
64698 var toc = pane.append('ul')
64699 .attr('class', 'toc');
64701 var menuItems = toc.selectAll('li')
64706 .html(function(d) { return d.title; })
64707 .on('click', clickHelp);
64709 var shortcuts = toc
64711 .attr('class', 'shortcuts')
64714 .title(uiTooltipHtml(t('shortcuts.tooltip'), '?'))
64718 .on('click', clickShortcuts);
64722 .text(t('shortcuts.title'));
64724 var walkthrough = toc
64726 .attr('class', 'walkthrough')
64728 .on('click', clickWalkthrough);
64732 .attr('class', 'logo logo-walkthrough')
64734 .attr('xlink:href', '#logo-walkthrough');
64738 .text(t('splash.walkthrough'));
64741 var content = pane.append('div')
64742 .attr('class', 'left-content');
64744 var doctitle = content.append('h2')
64745 .text(t('help.title'));
64747 var body = content.append('div')
64748 .attr('class', 'body');
64750 var nav = content.append('div')
64751 .attr('class', 'nav');
64753 clickHelp(docs[0], 0);
64755 var keybinding = d3keybinding('help')
64757 .on([t('background.key'), t('map_data.key')], hide);
64762 context.surface().on('mousedown.help-outside', hide);
64763 context.container().on('mousedown.help-outside', hide);
64769 function uiPanelBackground(context) {
64770 var background = context.background();
64771 var currSource = null;
64773 var currVintage = '';
64776 function redraw(selection$$1) {
64777 if (currSource !== background.baseLayerSource().name()) {
64778 currSource = background.baseLayerSource().name();
64783 selection$$1.html('');
64785 var list = selection$$1
64787 .attr('class', 'background-info');
64795 .text(t('info_panels.background.zoom') + ': ')
64797 .attr('class', 'zoom')
64802 .text(t('info_panels.background.vintage') + ': ')
64804 .attr('class', 'vintage')
64805 .text(currVintage);
64807 if (!currVintage) {
64808 debouncedGetVintage(selection$$1);
64811 var toggle = context.getDebug('tile') ? 'hide_tiles' : 'show_tiles';
64815 .text(t('info_panels.background.' + toggle))
64817 .attr('class', 'button button-toggle-tiles')
64818 .on('click', function() {
64819 event.preventDefault();
64820 context.setDebug('tile', !context.getDebug('tile'));
64821 selection$$1.call(redraw);
64826 var debouncedGetVintage = lodash.debounce(getVintage, 250);
64827 function getVintage(selection$$1) {
64828 var tile = select('.layer-background img.tile-center'); // tile near viewport center
64829 if (tile.empty()) return;
64831 var d = tile.datum(),
64832 zoom$$1 = (d && d.length >= 3 && d[2]) || Math.floor(context.map().zoom()),
64833 center = context.map().center();
64835 currZoom = String(zoom$$1);
64836 selection$$1.selectAll('.zoom')
64839 if (!d || !d.length >= 3) return;
64840 background.baseLayerSource().getVintage(center, d, function(err, result) {
64841 currVintage = (result && result.range) || t('info_panels.background.unknown');
64842 selection$$1.selectAll('.vintage')
64843 .text(currVintage);
64848 var panel = function(selection$$1) {
64849 selection$$1.call(redraw);
64852 .on('drawn.info-background', function() {
64853 selection$$1.call(redraw);
64855 .on('move.info-background', function() {
64856 selection$$1.call(debouncedGetVintage);
64861 panel.off = function() {
64863 .on('drawn.info-background', null)
64864 .on('move.info-background', null);
64867 panel.id = 'background';
64868 panel.title = t('info_panels.background.title');
64869 panel.key = t('info_panels.background.key');
64875 function uiPanelHistory(context) {
64878 function displayTimestamp(entity) {
64879 if (!entity.timestamp) return t('info_panels.history.unknown');
64881 var d = new Date(entity.timestamp);
64882 if (isNaN(d.getTime())) return t('info_panels.history.unknown');
64884 return d.toLocaleString();
64888 function displayUser(selection, entity) {
64889 if (!entity.user) {
64892 .text(t('info_panels.history.unknown'));
64898 .attr('class', 'user-name')
64899 .text(entity.user);
64901 var links = selection
64903 .attr('class', 'links');
64907 .attr('class', 'user-osm-link')
64908 .attr('href', context.connection().userURL(entity.user))
64909 .attr('target', '_blank')
64910 .attr('tabindex', -1)
64915 .attr('class', 'user-hdyc-link')
64916 .attr('href', 'https://hdyc.neis-one.org/?' + entity.user)
64917 .attr('target', '_blank')
64918 .attr('tabindex', -1)
64923 function displayChangeset(selection, entity) {
64924 if (!entity.changeset) {
64927 .text(t('info_panels.history.unknown'));
64933 .attr('class', 'changeset-id')
64934 .text(entity.changeset);
64936 var links = selection
64938 .attr('class', 'links');
64942 .attr('class', 'changeset-osm-link')
64943 .attr('href', context.connection().changesetURL(entity.changeset))
64944 .attr('target', '_blank')
64945 .attr('tabindex', -1)
64950 .attr('class', 'changeset-osmcha-link')
64951 .attr('href', 'https://osmcha.mapbox.com/changesets/' + entity.changeset)
64952 .attr('target', '_blank')
64953 .attr('tabindex', -1)
64958 function redraw(selection) {
64959 var selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
64960 singular = selected.length === 1 ? selected[0] : null;
64962 selection.html('');
64966 .attr('class', 'history-heading')
64967 .text(singular || t('info_panels.history.selected', { n: selected.length }));
64969 if (!singular) return;
64971 var entity = context.entity(singular);
64973 var list = selection
64978 .text(t('info_panels.history.version') + ': ' + entity.version);
64982 .text(t('info_panels.history.last_edit') + ': ' + displayTimestamp(entity));
64986 .text(t('info_panels.history.edited_by') + ': ')
64987 .call(displayUser, entity);
64991 .text(t('info_panels.history.changeset') + ': ')
64992 .call(displayChangeset, entity);
64996 .attr('class', 'view-history-on-osm')
64997 .attr('target', '_blank')
64998 .attr('tabindex', -1)
64999 .attr('href', context.connection().historyURL(entity))
65000 .call(svgIcon('#icon-out-link', 'inline'))
65002 .text(t('info_panels.history.link_text'));
65006 var panel = function(selection) {
65007 selection.call(redraw);
65010 .on('drawn.info-history', function() {
65011 selection.call(redraw);
65015 panel.off = function() {
65017 .on('drawn.info-history', null);
65020 panel.id = 'history';
65021 panel.title = t('info_panels.history.title');
65022 panel.key = t('info_panels.history.key');
65028 function uiPanelLocation(context) {
65029 var currLocation = '';
65030 var OSM_PRECISION = 7;
65033 function wrap(x, min, max) {
65035 return ((x - min) % d + d) % d + min;
65039 function clamp(x, min, max) {
65040 return Math.max(min, Math.min(x, max));
65044 function redraw(selection) {
65045 selection.html('');
65047 var list = selection
65050 // Mouse coordinates
65051 var coord = context.map().mouseCoordinates();
65052 if (coord.some(isNaN)) {
65053 coord = context.map().center();
65057 clamp(coord[1], -90, 90).toFixed(OSM_PRECISION) + ', ' +
65058 wrap(coord[0], -180, 180).toFixed(OSM_PRECISION);
65067 .attr('class', 'location-info')
65068 .text(currLocation || ' ');
65070 debouncedGetLocation(selection, coord);
65074 var debouncedGetLocation = lodash.debounce(getLocation, 250);
65075 function getLocation(selection, coord) {
65076 if (!services.geocoder) {
65077 currLocation = t('info_panels.location.unknown_location');
65078 selection.selectAll('.location-info')
65079 .text(currLocation);
65081 services.geocoder.reverse(coord, function(err, result) {
65082 currLocation = result ? result.display_name : t('info_panels.location.unknown_location');
65083 selection.selectAll('.location-info')
65084 .text(currLocation);
65090 var panel = function(selection) {
65091 selection.call(redraw);
65094 .on('mousemove.info-location', function() {
65095 selection.call(redraw);
65099 panel.off = function() {
65101 .on('mousemove.info-location', null);
65104 panel.id = 'location';
65105 panel.title = t('info_panels.location.title');
65106 panel.key = t('info_panels.location.key');
65112 function uiPanelMeasurement(context) {
65113 var isImperial = (utilDetect().locale.toLowerCase() === 'en-us');
65114 var OSM_PRECISION = 7;
65117 function radiansToMeters(r) {
65118 // using WGS84 authalic radius (6371007.1809 m)
65119 return r * 6371007.1809;
65122 function steradiansToSqmeters(r) {
65123 // http://gis.stackexchange.com/a/124857/40446
65124 return r / (4 * Math.PI) * 510065621724000;
65128 function toLineString(feature) {
65129 if (feature.type === 'LineString') return feature;
65131 var result = { type: 'LineString', coordinates: [] };
65132 if (feature.type === 'Polygon') {
65133 result.coordinates = feature.coordinates[0];
65134 } else if (feature.type === 'MultiPolygon') {
65135 result.coordinates = feature.coordinates[0][0];
65142 function displayLength(m) {
65143 var d = m * (isImperial ? 3.28084 : 1),
65162 // drop unnecessary precision
65163 p = d > 1000 ? 0 : d > 100 ? 1 : 2;
65165 return String(d.toFixed(p)) + ' ' + unit;
65169 function displayArea(m2) {
65170 var d = m2 * (isImperial ? 10.7639111056 : 1),
65171 d1, d2, p1, p2, unit1, unit2;
65174 if (d >= 6969600) { // > 0.25mi² show mi²
65182 if (d > 4356 && d < 43560000) { // 0.1 - 1000 acres
65188 if (d >= 250000) { // > 0.25km² show km²
65196 if (d > 1000 && d < 10000000) { // 0.1 - 1000 hectares
65202 // drop unnecessary precision
65203 p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
65204 p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
65206 return String(d1.toFixed(p1)) + ' ' + unit1 +
65207 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
65211 function redraw(selection$$1) {
65212 var resolver = context.graph(),
65213 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
65214 singular = selected.length === 1 ? selected[0] : null,
65215 extent$$1 = geoExtent$$1(),
65218 selection$$1.html('');
65222 .attr('class', 'measurement-heading')
65223 .text(singular || t('info_panels.measurement.selected', { n: selected.length }));
65225 if (!selected.length) return;
65228 for (var i = 0; i < selected.length; i++) {
65229 entity = context.entity(selected[i]);
65230 extent$$1._extend(entity.extent(resolver));
65232 center = extent$$1.center();
65235 var list = selection$$1
65238 // multiple features, just display extent center..
65242 .text(t('info_panels.measurement.center') + ': ' +
65243 center[1].toFixed(OSM_PRECISION) + ', ' + center[0].toFixed(OSM_PRECISION)
65248 // single feature, display details..
65249 if (!entity) return;
65250 var geometry = entity.geometry(resolver);
65252 if (geometry === 'line' || geometry === 'area') {
65253 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
65254 feature = entity.asGeoJSON(resolver),
65255 length = radiansToMeters(d3GeoLength(toLineString(feature))),
65256 lengthLabel = t('info_panels.measurement.' + (closed ? 'perimeter' : 'length')),
65257 centroid = d3GeoCentroid(feature);
65261 .text(t('info_panels.measurement.geometry') + ': ' +
65262 (closed ? t('info_panels.measurement.closed') + ' ' : '') + t('geometry.' + geometry) );
65265 var area$$1 = steradiansToSqmeters(entity.area(resolver));
65268 .text(t('info_panels.measurement.area') + ': ' + displayArea(area$$1));
65273 .text(lengthLabel + ': ' + displayLength(length));
65277 .text(t('info_panels.measurement.centroid') + ': ' +
65278 centroid[1].toFixed(OSM_PRECISION) + ', ' + centroid[0].toFixed(OSM_PRECISION)
65282 var toggle = isImperial ? 'imperial' : 'metric';
65286 .text(t('info_panels.measurement.' + toggle))
65288 .attr('class', 'button button-toggle-units')
65289 .on('click', function() {
65290 event.preventDefault();
65291 isImperial = !isImperial;
65292 selection$$1.call(redraw);
65296 var centerLabel = t('info_panels.measurement.' + (entity.type === 'node' ? 'location' : 'center'));
65300 .text(t('info_panels.measurement.geometry') + ': ' + t('geometry.' + geometry));
65304 .text(centerLabel + ': ' +
65305 center[1].toFixed(OSM_PRECISION) + ', ' + center[0].toFixed(OSM_PRECISION)
65311 var panel = function(selection$$1) {
65312 selection$$1.call(redraw);
65315 .on('drawn.info-measurement', function() {
65316 selection$$1.call(redraw);
65320 panel.off = function() {
65322 .on('drawn.info-measurement', null);
65325 panel.id = 'measurement';
65326 panel.title = t('info_panels.measurement.title');
65327 panel.key = t('info_panels.measurement.key');
65333 var uiInfoPanels = {
65334 background: uiPanelBackground,
65335 history: uiPanelHistory,
65336 location: uiPanelLocation,
65337 measurement: uiPanelMeasurement,
65340 function uiInfo(context) {
65341 var ids = Object.keys(uiInfoPanels),
65342 wasActive = ['measurement'],
65347 ids.forEach(function(k) {
65349 panels[k] = uiInfoPanels[k](context);
65350 active$$1[k] = false;
65355 function info(selection$$1) {
65357 function redraw() {
65358 var activeids = ids.filter(function(k) { return active$$1[k]; }).sort();
65360 var containers = infoPanels.selectAll('.panel-container')
65361 .data(activeids, function(k) { return k; });
65364 .style('opacity', 1)
65367 .style('opacity', 0)
65368 .on('end', function(d) {
65370 .call(panels[d].off)
65374 var enter = containers.enter()
65376 .attr('class', function(d) { return 'fillD2 panel-container panel-container-' + d; });
65379 .style('opacity', 0)
65382 .style('opacity', 1);
65386 .attr('class', 'panel-title fillD2');
65390 .text(function(d) { return panels[d].title; });
65394 .attr('class', 'close')
65395 .on('click', function (d) { toggle(d); })
65396 .call(svgIcon('#icon-close'));
65400 .attr('class', function(d) { return 'panel-content panel-content-' + d; });
65403 // redraw the panels
65404 infoPanels.selectAll('.panel-content')
65405 .each(function(d) {
65406 select(this).call(panels[d]);
65411 function toggle(which) {
65412 if (event) event.preventDefault();
65414 var activeids = ids.filter(function(k) { return active$$1[k]; });
65416 if (which) { // toggle one
65417 active$$1[which] = !active$$1[which];
65418 if (activeids.length === 1 && activeids[0] === which) { // none active anymore
65419 wasActive = [which];
65421 } else { // toggle all
65422 if (activeids.length) {
65423 wasActive = activeids;
65424 activeids.forEach(function(k) { active$$1[k] = false; });
65426 wasActive.forEach(function(k) { active$$1[k] = true; });
65434 var infoPanels = selection$$1.selectAll('.info-panels')
65437 infoPanels = infoPanels.enter()
65439 .attr('class', 'info-panels')
65440 .merge(infoPanels);
65444 var keybinding = d3keybinding('info')
65445 .on(uiCmd('⌘' + t('info_panels.key')), toggle);
65447 ids.forEach(function(k) {
65448 var key = t('info_panels.' + k + '.key', { default: null });
65451 .on(uiCmd('⌘⇧' + key), function() { toggle(k); });
65461 function uiMapData(context) {
65462 var key = t('map_data.key'),
65463 features = context.features().keys(),
65464 layers = context.layers(),
65465 fills = ['wireframe', 'partial', 'full'],
65466 fillDefault = context.storage('area-fill') || 'partial',
65467 fillSelected = fillDefault;
65470 function map_data(selection$$1) {
65472 function showsFeature(d) {
65473 return context.features().enabled(d);
65477 function autoHiddenFeature(d) {
65478 return context.features().autoHidden(d);
65482 function clickFeature(d) {
65483 context.features().toggle(d);
65488 function showsFill(d) {
65489 return fillSelected === d;
65493 function setFill(d) {
65494 lodash.each(fills, function(opt) {
65495 context.surface().classed('fill-' + opt, Boolean(opt === d));
65499 if (d !== 'wireframe') {
65501 context.storage('area-fill', d);
65507 function showsLayer(which) {
65508 var layer = layers.layer(which);
65510 return layer.enabled();
65516 function setLayer(which, enabled) {
65517 var layer = layers.layer(which);
65519 layer.enabled(enabled);
65525 function toggleLayer(which) {
65526 setLayer(which, !showsLayer(which));
65530 function clickGpx() {
65531 toggleLayer('gpx');
65535 function clickMapillaryImages() {
65536 toggleLayer('mapillary-images');
65537 if (!showsLayer('mapillary-images')) {
65538 setLayer('mapillary-signs', false);
65543 function clickMapillarySigns() {
65544 toggleLayer('mapillary-signs');
65548 function drawMapillaryItems(selection$$1) {
65549 var mapillaryImages = layers.layer('mapillary-images'),
65550 mapillarySigns = layers.layer('mapillary-signs'),
65551 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
65552 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
65553 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
65554 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
65556 var mapillaryList = selection$$1
65557 .selectAll('.layer-list-mapillary')
65560 mapillaryList = mapillaryList.enter()
65562 .attr('class', 'layer-list layer-list-mapillary')
65563 .merge(mapillaryList);
65566 var mapillaryImageLayerItem = mapillaryList
65567 .selectAll('.list-item-mapillary-images')
65568 .data(supportsMapillaryImages ? [0] : []);
65570 mapillaryImageLayerItem.exit()
65573 var enterImages = mapillaryImageLayerItem.enter()
65575 .attr('class', 'list-item-mapillary-images');
65577 var labelImages = enterImages
65580 .title(t('mapillary_images.tooltip'))
65581 .placement('top'));
65585 .attr('type', 'checkbox')
65586 .on('change', clickMapillaryImages);
65590 .text(t('mapillary_images.title'));
65593 var mapillarySignLayerItem = mapillaryList
65594 .selectAll('.list-item-mapillary-signs')
65595 .data(supportsMapillarySigns ? [0] : []);
65597 mapillarySignLayerItem.exit()
65600 var enterSigns = mapillarySignLayerItem.enter()
65602 .attr('class', 'list-item-mapillary-signs');
65604 var labelSigns = enterSigns
65607 .title(t('mapillary_signs.tooltip'))
65608 .placement('top'));
65612 .attr('type', 'checkbox')
65613 .on('change', clickMapillarySigns);
65617 .text(t('mapillary_signs.title'));
65621 mapillaryImageLayerItem = mapillaryImageLayerItem
65622 .merge(enterImages);
65624 mapillaryImageLayerItem
65625 .classed('active', showsMapillaryImages)
65626 .selectAll('input')
65627 .property('checked', showsMapillaryImages);
65630 mapillarySignLayerItem = mapillarySignLayerItem
65631 .merge(enterSigns);
65633 mapillarySignLayerItem
65634 .classed('active', showsMapillarySigns)
65635 .selectAll('input')
65636 .property('disabled', !showsMapillaryImages)
65637 .property('checked', showsMapillarySigns);
65639 mapillarySignLayerItem
65640 .selectAll('label')
65641 .classed('deemphasize', !showsMapillaryImages);
65645 function drawGpxItem(selection$$1) {
65646 var gpx = layers.layer('gpx'),
65647 hasGpx = gpx && gpx.hasGpx(),
65648 showsGpx = hasGpx && gpx.enabled();
65650 var gpxLayerItem = selection$$1
65651 .selectAll('.layer-list-gpx')
65652 .data(gpx ? [0] : []);
65655 gpxLayerItem.exit()
65659 var enter = gpxLayerItem.enter()
65661 .attr('class', 'layer-list layer-list-gpx')
65663 .classed('list-item-gpx', true);
65667 .attr('class', 'list-item-gpx-extent')
65669 .title(t('gpx.zoom'))
65670 .placement((textDirection === 'rtl') ? 'right' : 'left'))
65671 .on('click', function() {
65672 event.preventDefault();
65673 event.stopPropagation();
65676 .call(svgIcon('#icon-search'));
65680 .attr('class', 'list-item-gpx-browse')
65682 .title(t('gpx.browse'))
65683 .placement((textDirection === 'rtl') ? 'right' : 'left'))
65684 .on('click', function() {
65685 select(document.createElement('input'))
65686 .attr('type', 'file')
65687 .on('change', function() {
65688 gpx.files(event.target.files);
65692 .call(svgIcon('#icon-geolocate'));
65694 var labelGpx = enter
65696 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
65700 .attr('type', 'checkbox')
65701 .on('change', clickGpx);
65705 .text(t('gpx.local_layer'));
65709 gpxLayerItem = gpxLayerItem
65713 .classed('active', showsGpx)
65714 .selectAll('input')
65715 .property('disabled', !hasGpx)
65716 .property('checked', showsGpx);
65719 .selectAll('label')
65720 .classed('deemphasize', !hasGpx);
65724 function drawList(selection$$1, data, type, name, change, active$$1) {
65725 var items = selection$$1.selectAll('li')
65733 var enter = items.enter()
65735 .attr('class', 'layer')
65738 .title(function(d) {
65739 var tip = t(name + '.' + d + '.tooltip'),
65740 key = (d === 'wireframe' ? t('area_fill.wireframe.key') : null);
65742 if (name === 'feature' && autoHiddenFeature(d)) {
65743 tip += '<div>' + t('map_data.autohidden') + '</div>';
65745 return uiTooltipHtml(tip, key);
65755 .attr('type', type)
65756 .attr('name', name)
65757 .on('change', change);
65761 .text(function(d) { return t(name + '.' + d + '.description'); });
65768 .classed('active', active$$1)
65769 .selectAll('input')
65770 .property('checked', active$$1)
65771 .property('indeterminate', function(d) {
65772 return (name === 'feature' && autoHiddenFeature(d));
65777 function update() {
65778 dataLayerContainer.call(drawMapillaryItems);
65779 dataLayerContainer.call(drawGpxItem);
65781 fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
65782 featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
65786 function hidePanel() {
65791 function togglePanel() {
65792 if (event) event.preventDefault();
65793 tooltipBehavior.hide(button);
65794 setVisible(!button.classed('active'));
65798 function toggleWireframe() {
65800 event.preventDefault();
65801 event.stopPropagation();
65803 setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
65804 context.map().pan([0,0]); // trigger a redraw
65808 function setVisible(show) {
65809 if (show !== shown) {
65810 button.classed('active', show);
65815 selection$$1.on('mousedown.map_data-inside', function() {
65816 return event.stopPropagation();
65818 content.style('display', 'block')
65819 .style('right', '-300px')
65822 .style('right', '0px');
65824 content.style('display', 'block')
65825 .style('right', '0px')
65828 .style('right', '-300px')
65829 .on('end', function() {
65830 select(this).style('display', 'none');
65832 selection$$1.on('mousedown.map_data-inside', null);
65838 var content = selection$$1
65840 .attr('class', 'fillL map-overlay col3 content hide'),
65841 tooltipBehavior = tooltip()
65842 .placement((textDirection === 'rtl') ? 'right' : 'left')
65844 .title(uiTooltipHtml(t('map_data.description'), key)),
65845 button = selection$$1
65847 .attr('tabindex', -1)
65848 .on('click', togglePanel)
65849 .call(svgIcon('#icon-data', 'light'))
65850 .call(tooltipBehavior),
65855 .text(t('map_data.title'));
65861 .text(t('map_data.data_layers'))
65863 .classed('hide-toggle', true)
65864 .classed('expanded', true)
65865 .on('click', function() {
65866 var exp = select(this).classed('expanded');
65867 dataLayerContainer.style('display', exp ? 'none' : 'block');
65868 select(this).classed('expanded', !exp);
65869 event.preventDefault();
65872 var dataLayerContainer = content
65874 .attr('class', 'data-data-layers')
65875 .style('display', 'block');
65881 .text(t('map_data.fill_area'))
65883 .classed('hide-toggle', true)
65884 .classed('expanded', false)
65885 .on('click', function() {
65886 var exp = select(this).classed('expanded');
65887 fillContainer.style('display', exp ? 'none' : 'block');
65888 select(this).classed('expanded', !exp);
65889 event.preventDefault();
65892 var fillContainer = content
65894 .attr('class', 'data-area-fills')
65895 .style('display', 'none');
65897 var fillList = fillContainer
65899 .attr('class', 'layer-list layer-fill-list');
65905 .text(t('map_data.map_features'))
65907 .classed('hide-toggle', true)
65908 .classed('expanded', false)
65909 .on('click', function() {
65910 var exp = select(this).classed('expanded');
65911 featureContainer.style('display', exp ? 'none' : 'block');
65912 select(this).classed('expanded', !exp);
65913 event.preventDefault();
65916 var featureContainer = content
65918 .attr('class', 'data-feature-filters')
65919 .style('display', 'none');
65921 var featureList = featureContainer
65923 .attr('class', 'layer-list layer-feature-list');
65927 .on('change.map_data-update', update);
65929 setFill(fillDefault);
65931 var keybinding = d3keybinding('features')
65932 .on(key, togglePanel)
65933 .on(t('area_fill.wireframe.key'), toggleWireframe)
65934 .on([t('background.key'), t('help.key')], hidePanel);
65939 context.surface().on('mousedown.map_data-outside', hidePanel);
65940 context.container().on('mousedown.map_data-outside', hidePanel);
65947 function uiModes(context) {
65949 modeAddPoint$$1(context),
65950 modeAddLine$$1(context),
65951 modeAddArea$$1(context)
65955 function editable() {
65956 return context.editable() && context.mode().id !== 'save';
65960 return function(selection$$1) {
65961 var buttons = selection$$1.selectAll('button.add-button')
65964 buttons = buttons.enter()
65966 .attr('tabindex', -1)
65967 .attr('class', function(mode) { return mode.id + ' add-button col4'; })
65968 .on('click.mode-buttons', function(mode) {
65969 if (mode.id === context.mode().id) {
65970 context.enter(modeBrowse(context));
65972 context.enter(mode);
65976 .placement('bottom')
65978 .title(function(mode) {
65979 return uiTooltipHtml(mode.description, mode.key);
65984 .on('move.modes', lodash.debounce(update, 500));
65987 .on('enter.modes', update);
65990 .each(function(d) {
65992 .call(svgIcon('#icon-' + d.button, 'pre-text'));
65997 .attr('class', 'label')
65998 .text(function(mode) { return mode.title; });
66001 .on('enter.editor', function(entered) {
66002 selection$$1.selectAll('button.add-button')
66003 .classed('active', function(mode) { return entered.button === mode.button; });
66004 context.container()
66005 .classed('mode-' + entered.id, true);
66009 .on('exit.editor', function(exited) {
66010 context.container()
66011 .classed('mode-' + exited.id, false);
66014 var keybinding = d3keybinding('mode-buttons');
66016 modes.forEach(function(mode) {
66017 keybinding.on(mode.key, function() {
66019 if (mode.id === context.mode().id) {
66020 context.enter(modeBrowse(context));
66022 context.enter(mode);
66032 function update() {
66033 selection$$1.selectAll('button.add-button')
66034 .property('disabled', !editable());
66039 function uiRestore(context) {
66041 return function(selection) {
66042 if (!context.history().lock() || !context.history().restorableChanges())
66045 var modalSelection = uiModal(selection, true);
66047 modalSelection.select('.modal')
66048 .attr('class', 'modal fillL col6');
66050 var introModal = modalSelection.select('.content');
66053 .attr('class','cf');
66057 .attr('class', 'modal-section')
66059 .text(t('restore.heading'));
66063 .attr('class','modal-section')
66065 .text(t('restore.description'));
66067 var buttonWrap = introModal
66069 .attr('class', 'modal-actions cf');
66071 var restore = buttonWrap
66073 .attr('class', 'restore col6')
66074 .on('click', function() {
66075 context.history().restore();
66076 modalSelection.remove();
66081 .attr('class', 'logo logo-restore')
66083 .attr('xlink:href', '#logo-restore');
66087 .text(t('restore.restore'));
66089 var reset = buttonWrap
66091 .attr('class', 'reset col6')
66092 .on('click', function() {
66093 context.history().clearSaved();
66094 modalSelection.remove();
66099 .attr('class', 'logo logo-reset')
66101 .attr('xlink:href', '#logo-reset');
66105 .text(t('restore.reset'));
66107 restore.node().focus();
66111 function uiSave(context) {
66112 var history = context.history(),
66116 function saving() {
66117 return context.mode().id === 'save';
66122 event.preventDefault();
66123 if (!context.inIntro() && !saving() && history.hasChanges()) {
66124 context.enter(modeSave$$1(context));
66129 function getBackground(numChanges) {
66131 if (numChanges === 0) {
66133 } else if (numChanges <= 50) {
66134 step$$1 = numChanges / 50;
66135 return interpolateRgb('#fff', '#ff8')(step$$1); // white -> yellow
66137 step$$1 = Math.min((numChanges - 50) / 50, 1.0);
66138 return interpolateRgb('#ff8', '#f88')(step$$1); // yellow -> red
66143 return function(selection$$1) {
66144 var numChanges = 0;
66146 function updateCount() {
66147 var _ = history.difference().summary().length;
66148 if (_ === numChanges) return;
66152 .title(uiTooltipHtml(
66153 t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key)
66156 var background = getBackground(numChanges);
66159 .classed('disabled', numChanges === 0)
66160 .classed('has-count', numChanges > 0)
66161 .style('background', background);
66163 button.select('span.count')
66165 .style('background', background)
66166 .style('border-color', background);
66170 var tooltipBehavior = tooltip()
66171 .placement('bottom')
66173 .title(uiTooltipHtml(t('save.no_changes'), key));
66175 var button = selection$$1
66177 .attr('class', 'save col12 disabled')
66178 .attr('tabindex', -1)
66180 .call(tooltipBehavior);
66183 .call(svgIcon('#icon-save', 'pre-text'))
66185 .attr('class', 'label')
66186 .text(t('save.title'));
66190 .attr('class', 'count')
66196 var keybinding = d3keybinding('save')
66197 .on(key, save, true);
66203 .on('change.save', updateCount);
66206 .on('enter.save', function() {
66207 button.property('disabled', saving());
66208 if (saving()) button.call(tooltipBehavior.hide);
66213 function uiScale(context) {
66214 var projection = context.projection,
66215 isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
66220 function scaleDefs(loc1, loc2) {
66221 var lat = (loc2[1] + loc1[1]) / 2,
66222 conversion = (isImperial ? 3.28084 : 1),
66223 dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
66224 scale = { dist: 0, px: 0, text: '' },
66225 buckets, i, val, dLon;
66228 buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
66230 buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
66233 // determine a user-friendly endpoint for the scale
66234 for (i = 0; i < buckets.length; i++) {
66237 scale.dist = Math.floor(dist / val) * val;
66240 scale.dist = +dist.toFixed(2);
66244 dLon = geoMetersToLon(scale.dist / conversion, lat);
66245 scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
66248 if (scale.dist >= 5280) {
66249 scale.dist /= 5280;
66250 scale.text = String(scale.dist) + ' mi';
66252 scale.text = String(scale.dist) + ' ft';
66255 if (scale.dist >= 1000) {
66256 scale.dist /= 1000;
66257 scale.text = String(scale.dist) + ' km';
66259 scale.text = String(scale.dist) + ' m';
66267 function update(selection) {
66268 // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
66269 var dims = context.map().dimensions(),
66270 loc1 = projection.invert([0, dims[1]]),
66271 loc2 = projection.invert([maxLength, dims[1]]),
66272 scale = scaleDefs(loc1, loc2);
66274 selection.select('#scale-path')
66275 .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
66277 selection.select('#scale-textgroup')
66278 .attr('transform', 'translate(' + (scale.px + 8) + ',' + tickHeight + ')');
66280 selection.select('#scale-text')
66285 return function(selection) {
66286 function switchUnits() {
66287 isImperial = !isImperial;
66288 selection.call(update);
66291 var scalegroup = selection.append('svg')
66292 .attr('id', 'scale')
66293 .on('click', switchUnits)
66295 .attr('transform', 'translate(10,11)');
66299 .attr('id', 'scale-path');
66303 .attr('id', 'scale-textgroup')
66305 .attr('id', 'scale-text');
66307 selection.call(update);
66309 context.map().on('move.scale', function() {
66315 var pair_1 = pair$1;
66316 function search(x, dims, r) {
66317 if (!dims) dims = 'NSEW';
66318 if (typeof x !== 'string') return { val: null, regex: r };
66319 r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
66321 if (!m) return { val: null, regex: r };
66322 else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
66324 val: (((m[1]) ? parseFloat(m[1]) : 0) +
66325 ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
66326 ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
66327 ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
66334 function pair$1(x, dims) {
66336 var one = search(x, dims);
66337 if (one.val === null) return null;
66338 var two = search(x, dims, one.regex);
66339 if (two.val === null) return null;
66340 // null if one/two are not contiguous.
66341 if (one.raw + two.raw !== x) return null;
66343 return swapdim(one.val, two.val, one.dim);
66345 return [one.val, two.val];
66349 function swapdim(a, b, dim) {
66350 if (dim === 'N' || dim === 'S') return [a, b];
66351 if (dim === 'W' || dim === 'E') return [b, a];
66354 function uiFeatureList(context) {
66355 var geocodeResults;
66358 function featureList(selection$$1) {
66359 var header = selection$$1
66361 .attr('class', 'header fillL cf');
66363 header.append('h3')
66364 .text(t('inspector.feature_list'));
66366 var searchWrap = selection$$1
66368 .attr('class', 'search-header');
66370 var search = searchWrap
66372 .attr('placeholder', t('inspector.search'))
66373 .attr('type', 'search')
66375 .on('keypress', keypress)
66376 .on('input', inputevent);
66379 .call(svgIcon('#icon-search', 'pre-text'));
66381 var listWrap = selection$$1
66383 .attr('class', 'inspector-body');
66385 var list = listWrap
66387 .attr('class', 'feature-list cf');
66390 .on('exit.feature-list', clearSearch);
66392 .on('drawn.feature-list', mapDrawn);
66395 function keypress() {
66396 var q = search.property('value'),
66397 items = list.selectAll('.feature-list-item');
66398 if (event.keyCode === 13 && q.length && items.size()) {
66399 click(items.datum());
66404 function inputevent() {
66405 geocodeResults = undefined;
66410 function clearSearch() {
66411 search.property('value', '');
66416 function mapDrawn(e) {
66423 function features() {
66426 graph = context.graph(),
66427 q = search.property('value').toLowerCase();
66429 if (!q) return result;
66431 var idMatch = q.match(/^([nwr])([0-9]+)$/);
66436 geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
66437 type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
66442 var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
66444 if (locationMatch) {
66445 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
66449 type: t('inspector.location'),
66450 name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
66455 function addEntity(entity) {
66456 if (entity.id in entities || result.length > 200)
66459 entities[entity.id] = true;
66461 var name = utilDisplayName(entity) || '';
66462 if (name.toLowerCase().indexOf(q) >= 0) {
66463 var matched = context.presets().match(entity, graph),
66464 type = (matched && matched.name()) || utilDisplayType(entity.id);
66468 geometry: context.geometry(entity.id),
66474 graph.parentRelations(entity).forEach(function(parent) {
66479 var visible = context.surface().selectAll('.point, .line, .area').nodes();
66480 for (var i = 0; i < visible.length && result.length <= 200; i++) {
66481 addEntity(visible[i].__data__);
66484 (geocodeResults || []).forEach(function(d) {
66485 // https://github.com/openstreetmap/iD/issues/1890
66486 if (d.osm_type && d.osm_id) {
66488 id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
66489 geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
66490 type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
66491 : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
66492 name: d.display_name,
66493 extent: new geoExtent$$1(
66494 [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
66495 [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
66504 function drawList() {
66505 var value = search.property('value'),
66506 results = features();
66508 list.classed('filtered', value.length);
66510 var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
66512 var resultsIndicator = list.selectAll('.no-results-item')
66514 .enter().append('button')
66515 .property('disabled', true)
66516 .attr('class', 'no-results-item')
66517 .call(svgIcon('#icon-alert', 'pre-text'));
66519 resultsIndicator.append('span')
66520 .attr('class', 'entity-name');
66522 list.selectAll('.no-results-item .entity-name')
66523 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
66525 if (services.geocoder) {
66526 list.selectAll('.geocode-item')
66528 .enter().append('button')
66529 .attr('class', 'geocode-item')
66530 .on('click', geocoderSearch)
66532 .attr('class', 'label')
66534 .attr('class', 'entity-name')
66535 .text(t('geocoder.search'));
66538 list.selectAll('.no-results-item')
66539 .style('display', (value.length && !results.length) ? 'block' : 'none');
66541 list.selectAll('.geocode-item')
66542 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
66544 list.selectAll('.feature-list-item')
66548 var items = list.selectAll('.feature-list-item')
66549 .data(results, function(d) { return d.id; });
66551 var enter = items.enter()
66552 .insert('button', '.geocode-item')
66553 .attr('class', 'feature-list-item')
66554 .on('mouseover', mouseover)
66555 .on('mouseout', mouseout)
66556 .on('click', click);
66560 .attr('class', 'label');
66562 label.each(function(d) {
66564 .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
66567 label.append('span')
66568 .attr('class', 'entity-type')
66569 .text(function(d) { return d.type; });
66571 label.append('span')
66572 .attr('class', 'entity-name')
66573 .text(function(d) { return d.name; });
66575 enter.style('opacity', 0)
66577 .style('opacity', 1);
66586 function mouseover(d) {
66587 if (d.id === -1) return;
66589 context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
66590 .classed('hover', true);
66594 function mouseout() {
66595 context.surface().selectAll('.hover')
66596 .classed('hover', false);
66600 function click(d) {
66601 event.preventDefault();
66603 context.map().centerZoom([d.location[1], d.location[0]], 20);
66605 else if (d.entity) {
66606 if (d.entity.type === 'node') {
66607 context.map().center(d.entity.loc);
66608 } else if (d.entity.type === 'way') {
66609 var center = context.projection(context.map().center()),
66610 edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
66611 context.map().center(edge.loc);
66613 context.enter(modeSelect(context, [d.entity.id]));
66615 context.zoomToEntity(d.id);
66620 function geocoderSearch() {
66621 services.geocoder.search(search.property('value'), function (err, resp) {
66622 geocodeResults = resp || [];
66629 return featureList;
66632 function uiPresetIcon() {
66633 var preset, geometry;
66636 function presetIcon(selection$$1) {
66637 selection$$1.each(render);
66641 function getIcon(p, geom) {
66644 else if (geom === 'line')
66645 return 'other-line';
66646 else if (geom === 'vertex')
66647 return p.isFallback() ? '' : 'poi-vertex';
66649 return 'marker-stroked';
66653 function render() {
66654 var selection$$1 = select(this),
66655 p = preset.apply(this, arguments),
66656 geom = geometry.apply(this, arguments),
66657 picon = getIcon(p, geom),
66658 isPoi = picon.match(/^poi-/) !== null,
66659 isMaki = dataFeatureIcons.indexOf(picon) !== -1,
66660 isFramed = (geom === 'area' || geom === 'verex');
66663 function tag_classes(p) {
66665 for (var i in p.tags) {
66667 if (p.tags[i] !== '*') {
66668 s += ' tag-' + i + '-' + p.tags[i];
66675 var fill = selection$$1.selectAll('.preset-icon-fill')
66678 fill = fill.enter()
66683 .attr('class', function() {
66684 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
66688 var areaFrame = selection$$1.selectAll('.preset-icon-frame')
66689 .data((geom === 'area') ? [0] : []);
66694 areaFrame = areaFrame.enter()
66696 .attr('class', 'preset-icon-frame')
66697 .call(svgIcon('#preset-icon-frame'));
66700 var icon = selection$$1.selectAll('.preset-icon')
66703 icon = icon.enter()
66705 .attr('class', 'preset-icon')
66710 .attr('class', 'preset-icon preset-icon-' +
66711 ((isMaki || isPoi) ? (isFramed ? '24' : '28') : (isFramed ? '44' : '60'))
66714 icon.selectAll('svg')
66715 .attr('class', function() {
66716 return 'icon ' + picon + (isMaki || isPoi ? '' : tag_classes(p));
66719 icon.selectAll('use')
66720 .attr('href', '#' + picon + (isMaki ? '-15' : ''));
66724 presetIcon.preset = function(_) {
66725 if (!arguments.length) return preset;
66726 preset = utilFunctor(_);
66731 presetIcon.geometry = function(_) {
66732 if (!arguments.length) return geometry;
66733 geometry = utilFunctor(_);
66740 function d3combobox() {
66741 var dispatch$$1 = dispatch('accept'),
66742 container = select(document.body),
66746 caseSensitive = false;
66748 var fetcher = function(val, cb) {
66749 cb(data.filter(function(d) {
66753 .indexOf(val.toLowerCase()) !== -1;
66757 var combobox = function(input, attachTo) {
66759 wrapper = container
66760 .selectAll('div.combobox')
66761 .filter(function(d) { return d === input.node(); }),
66762 shown = !wrapper.empty();
66765 .classed('combobox-input', true)
66766 .on('focus.typeahead', focus)
66767 .on('blur.typeahead', blur)
66768 .on('keydown.typeahead', keydown)
66769 .on('keyup.typeahead', keyup)
66770 .on('input.typeahead', change)
66772 var parent = this.parentNode,
66773 sibling = this.nextSibling;
66775 var caret = select(parent).selectAll('.combobox-caret')
66776 .filter(function(d) { return d === input.node(); })
66777 .data([input.node()]);
66779 caret = caret.enter()
66780 .insert('div', function() { return sibling; })
66781 .attr('class', 'combobox-caret')
66785 .on('mousedown', function () {
66786 // prevent the form element from blurring. it blurs
66788 event.stopPropagation();
66789 event.preventDefault();
66791 input.node().focus();
66800 fetch(value(), render);
66804 window.setTimeout(hide, 150);
66809 wrapper = container
66810 .insert('div', ':first-child')
66811 .datum(input.node())
66812 .attr('class', 'combobox')
66813 .style('position', 'absolute')
66814 .style('display', 'block')
66815 .style('left', '0px')
66816 .on('mousedown', function () {
66817 // prevent moving focus out of the text field
66818 event.preventDefault();
66822 .on('scroll.combobox', render, true);
66834 .on('scroll.combobox', null);
66840 function keydown() {
66841 switch (event.keyCode) {
66842 // backspace, delete
66845 input.on('input.typeahead', function() {
66848 var start = input.property('selectionStart');
66849 input.node().setSelectionRange(start, start);
66850 input.on('input.typeahead', change);
66855 wrapper.selectAll('a.selected').each(function (d) {
66856 dispatch$$1.call('accept', this, d);
66862 event.preventDefault();
66867 event.preventDefault();
66872 event.preventDefault();
66875 event.stopPropagation();
66879 switch (event.keyCode) {
66886 wrapper.selectAll('a.selected').each(function (d) {
66887 dispatch$$1.call('accept', this, d);
66894 function change() {
66895 fetch(value(), function() {
66896 if (input.property('selectionEnd') === input.property('value').length) {
66903 function nav(dir) {
66904 if (!suggestions.length) return;
66905 idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
66906 input.property('value', suggestions[idx].value);
66912 var value = input.property('value'),
66913 start = input.property('selectionStart'),
66914 end = input.property('selectionEnd');
66916 if (start && end) {
66917 value = value.substring(0, start);
66923 function fetch(v, cb) {
66924 fetcher.call(input, v, function(_) {
66930 function autocomplete() {
66931 var v = caseSensitive ? value() : value().toLowerCase();
66935 for (var i = 0; i < suggestions.length; i++) {
66936 var suggestion = suggestions[i].value,
66937 compare = caseSensitive ? suggestion : suggestion.toLowerCase();
66939 if (compare.indexOf(v) === 0) {
66941 input.property('value', suggestion);
66942 input.node().setSelectionRange(v.length, suggestion.length);
66948 function render() {
66949 if (suggestions.length >= minItems && document.activeElement === input.node()) {
66956 var options = wrapper
66957 .selectAll('a.combobox-option')
66958 .data(suggestions, function(d) { return d.value; });
66965 .attr('class', 'combobox-option')
66966 .text(function(d) { return d.value; })
66968 .attr('title', function(d) { return d.title; })
66969 .classed('selected', function(d, i) { return i === idx; })
66970 .on('mouseover', select$$1)
66971 .on('click', accept)
66975 var node = attachTo ? attachTo.node() : input.node(),
66976 rect = node.getBoundingClientRect();
66979 .style('left', rect.left + 'px')
66980 .style('width', rect.width + 'px')
66981 .style('top', rect.height + rect.top + 'px');
66984 function select$$1(d, i) {
66989 function ensureVisible() {
66990 var node = wrapper.selectAll('a.selected').node();
66991 if (node) node.scrollIntoView();
66994 function accept(d) {
66995 if (!shown) return;
66996 input.property('value', d.value);
66997 utilTriggerEvent(input, 'change');
66998 dispatch$$1.call('accept', this, d);
67003 combobox.fetcher = function(_) {
67004 if (!arguments.length) return fetcher;
67009 combobox.data = function(_) {
67010 if (!arguments.length) return data;
67015 combobox.minItems = function(_) {
67016 if (!arguments.length) return minItems;
67021 combobox.caseSensitive = function(_) {
67022 if (!arguments.length) return caseSensitive;
67027 combobox.container = function(_) {
67028 if (!arguments.length) return container;
67033 return utilRebind(combobox, dispatch$$1, 'on');
67037 d3combobox.off = function(input) {
67039 .on('focus.typeahead', null)
67040 .on('blur.typeahead', null)
67041 .on('keydown.typeahead', null)
67042 .on('keyup.typeahead', null)
67043 .on('input.typeahead', null)
67045 select(this.parentNode).selectAll('.combobox-caret')
67046 .filter(function(d) { return d === input.node(); })
67047 .on('mousedown', null);
67051 .on('scroll.combobox', null);
67054 function uiDisclosure() {
67055 var dispatch$$1 = dispatch('toggled'),
67058 content = function () {};
67061 var disclosure = function(selection$$1) {
67062 var hideToggle = selection$$1.selectAll('.hide-toggle')
67065 hideToggle = hideToggle.enter()
67068 .attr('class', 'hide-toggle')
67069 .merge(hideToggle);
67073 .on('click', toggle)
67074 .classed('expanded', expanded);
67077 var wrap = selection$$1.selectAll('div')
67080 wrap = wrap.enter()
67085 .classed('hide', !expanded)
67089 function toggle() {
67090 expanded = !expanded;
67091 hideToggle.classed('expanded', expanded);
67092 wrap.call(uiToggle(expanded));
67093 dispatch$$1.call('toggled', this, expanded);
67098 disclosure.title = function(_) {
67099 if (!arguments.length) return title;
67105 disclosure.expanded = function(_) {
67106 if (!arguments.length) return expanded;
67112 disclosure.content = function(_) {
67113 if (!arguments.length) return content;
67119 return utilRebind(disclosure, dispatch$$1, 'on');
67122 function uiRawMemberEditor(context) {
67124 taginfo = services.taginfo;
67127 function selectMember(d) {
67128 event.preventDefault();
67129 context.enter(modeSelect(context, [d.id]));
67133 function changeRole(d) {
67134 var role = select(this).property('value');
67135 var member = { id: d.id, type: d.type, role: role };
67137 actionChangeMember(d.relation.id, member, d.index),
67138 t('operations.change_role.annotation')
67143 function deleteMember(d) {
67145 actionDeleteMember(d.relation.id, d.index),
67146 t('operations.delete_member.annotation')
67149 if (!context.hasEntity(d.relation.id)) {
67150 context.enter(modeBrowse(context));
67155 function rawMemberEditor(selection$$1) {
67156 var entity = context.entity(id),
67159 entity.members.slice(0, 1000).forEach(function(member, index) {
67166 member: context.hasEntity(member.id)
67170 var gt = entity.members.length > 1000 ? '>' : '';
67171 selection$$1.call(uiDisclosure()
67172 .title(t('inspector.all_members') + ' (' + gt + memberships.length + ')')
67174 .on('toggled', toggled)
67179 function toggled(expanded) {
67181 selection$$1.node().parentNode.scrollTop += 200;
67186 function content(wrap) {
67187 var list = wrap.selectAll('.member-list')
67190 list = list.enter()
67192 .attr('class', 'member-list')
67196 var items = list.selectAll('li')
67197 .data(memberships, function(d) {
67198 return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
67199 (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
67206 var enter = items.enter()
67208 .attr('class', 'member-row form-field')
67209 .classed('member-incomplete', function(d) { return !d.member; });
67212 .each(function(d) {
67214 var label = select(this).append('label')
67215 .attr('class', 'form-label')
67218 .on('click', selectMember);
67220 label.append('span')
67221 .attr('class', 'member-entity-type')
67222 .text(function(d) {
67223 var matched = context.presets().match(d.member, context.graph());
67224 return (matched && matched.name()) || utilDisplayType(d.member.id);
67227 label.append('span')
67228 .attr('class', 'member-entity-name')
67229 .text(function(d) { return utilDisplayName(d.member); });
67232 select(this).append('label')
67233 .attr('class', 'form-label')
67234 .text(t('inspector.incomplete', { id: d.id }));
67240 .attr('class', 'member-role')
67241 .property('type', 'text')
67242 .attr('maxlength', 255)
67243 .attr('placeholder', t('inspector.role'))
67245 .property('value', function(d) { return d.role; })
67246 .on('change', changeRole);
67250 .attr('tabindex', -1)
67251 .attr('class', 'remove button-input-action member-delete minor')
67252 .on('click', deleteMember)
67253 .call(svgIcon('#operation-delete'));
67256 enter.each(bindTypeahead);
67260 function bindTypeahead(d) {
67261 var row = select(this),
67262 role = row.selectAll('input.member-role');
67264 function sort(value, data) {
67265 var sameletter = [],
67267 for (var i = 0; i < data.length; i++) {
67268 if (data[i].value.substring(0, value.length) === value) {
67269 sameletter.push(data[i]);
67271 other.push(data[i]);
67274 return sameletter.concat(other);
67277 role.call(d3combobox()
67278 .container(context.container())
67279 .fetcher(function(role, callback) {
67280 var rtype = entity.tags.type;
67283 rtype: rtype || '',
67284 geometry: context.geometry(d.member.id),
67286 }, function(err, data) {
67287 if (!err) callback(sort(role, data));
67293 function unbind() {
67294 var row = select(this);
67296 row.selectAll('input.member-role')
67297 .call(d3combobox.off);
67303 rawMemberEditor.entityID = function(_) {
67304 if (!arguments.length) return id;
67306 return rawMemberEditor;
67310 return rawMemberEditor;
67313 function uiRawMembershipEditor(context) {
67314 var taginfo = services.taginfo,
67318 function selectRelation(d) {
67319 event.preventDefault();
67320 context.enter(modeSelect(context, [d.relation.id]));
67324 function changeRole(d) {
67325 var role = select(this).property('value');
67327 actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
67328 t('operations.change_role.annotation')
67333 function addMembership(d, role) {
67338 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
67339 t('operations.add_member.annotation')
67343 var relation = osmRelation();
67345 actionAddEntity(relation),
67346 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
67347 t('operations.add.annotation.relation')
67350 context.enter(modeSelect(context, [relation.id]));
67355 function deleteMembership(d) {
67357 actionDeleteMember(d.relation.id, d.index),
67358 t('operations.delete_member.annotation')
67363 function relations(q) {
67364 var newRelation = {
67366 value: t('inspector.new_relation')
67369 graph = context.graph();
67371 context.intersects(context.extent()).forEach(function(entity) {
67372 if (entity.type !== 'relation' || entity.id === id)
67375 var matched = context.presets().match(entity, graph),
67376 presetName = (matched && matched.name()) || t('inspector.relation'),
67377 entityName = utilDisplayName(entity) || '';
67379 var value = presetName + ' ' + entityName;
67380 if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
67389 result.sort(function(a, b) {
67390 return osmRelation.creationOrder(a.relation, b.relation);
67393 // Dedupe identical names by appending relation id - see #2891
67394 var dupeGroups = lodash(result)
67396 .filter(function(v) { return v.length > 1; })
67399 dupeGroups.forEach(function(group) {
67400 group.forEach(function(obj) {
67401 obj.value += ' ' + obj.relation.id;
67405 result.unshift(newRelation);
67410 function rawMembershipEditor(selection$$1) {
67411 var entity = context.entity(id),
67412 parents = context.graph().parentRelations(entity),
67415 parents.slice(0, 1000).forEach(function(relation) {
67416 relation.members.forEach(function(member, index) {
67417 if (member.id === entity.id) {
67418 memberships.push({ relation: relation, member: member, index: index });
67423 var gt = parents.length > 1000 ? '>' : '';
67424 selection$$1.call(uiDisclosure()
67425 .title(t('inspector.all_relations') + ' (' + gt + memberships.length + ')')
67427 .on('toggled', toggled)
67432 function toggled(expanded) {
67434 selection$$1.node().parentNode.scrollTop += 200;
67439 function content(wrap) {
67440 var list = wrap.selectAll('.member-list')
67443 list = list.enter()
67445 .attr('class', 'member-list')
67449 var items = list.selectAll('li.member-row-normal')
67450 .data(memberships, function(d) {
67451 return osmEntity$$1.key(d.relation) + ',' + d.index;
67458 var enter = items.enter()
67460 .attr('class', 'member-row member-row-normal form-field');
67464 .attr('class', 'form-label')
67467 .on('click', selectRelation);
67471 .attr('class', 'member-entity-type')
67472 .text(function(d) {
67473 var matched = context.presets().match(d.relation, context.graph());
67474 return (matched && matched.name()) || t('inspector.relation');
67479 .attr('class', 'member-entity-name')
67480 .text(function(d) { return utilDisplayName(d.relation); });
67484 .attr('class', 'member-role')
67485 .property('type', 'text')
67486 .attr('maxlength', 255)
67487 .attr('placeholder', t('inspector.role'))
67489 .property('value', function(d) { return d.member.role; })
67490 .on('change', changeRole);
67494 .attr('tabindex', -1)
67495 .attr('class', 'remove button-input-action member-delete minor')
67496 .on('click', deleteMembership)
67497 .call(svgIcon('#operation-delete'));
67500 enter.each(bindTypeahead);
67504 var newrow = list.selectAll('.member-row-new')
67505 .data(showBlank ? [0] : []);
67510 enter = newrow.enter()
67512 .attr('class', 'member-row member-row-new form-field');
67516 .attr('type', 'text')
67517 .attr('class', 'member-entity-input')
67522 .attr('class', 'member-role')
67523 .property('type', 'text')
67524 .attr('maxlength', 255)
67525 .attr('placeholder', t('inspector.role'))
67527 .on('change', changeRole);
67531 .attr('tabindex', -1)
67532 .attr('class', 'remove button-input-action member-delete minor')
67533 .on('click', deleteMembership)
67534 .call(svgIcon('#operation-delete'));
67539 newrow.selectAll('.member-entity-input')
67541 .container(context.container())
67543 .fetcher(function(value, callback) { callback(relations(value)); })
67544 .on('accept', onAccept)
67548 var addrel = wrap.selectAll('.add-relation')
67551 addrel = addrel.enter()
67553 .attr('class', 'add-relation')
67557 .call(svgIcon('#icon-plus', 'light'))
67558 .on('click', function() {
67561 list.selectAll('.member-entity-input').node().focus();
67565 function onAccept(d) {
67566 var role = list.selectAll('.member-row-new .member-role').property('value');
67567 addMembership(d, role);
67571 function bindTypeahead(d) {
67572 var row = select(this),
67573 role = row.selectAll('input.member-role');
67575 function sort(value, data) {
67576 var sameletter = [],
67578 for (var i = 0; i < data.length; i++) {
67579 if (data[i].value.substring(0, value.length) === value) {
67580 sameletter.push(data[i]);
67582 other.push(data[i]);
67585 return sameletter.concat(other);
67588 role.call(d3combobox()
67589 .container(context.container())
67590 .fetcher(function(role, callback) {
67591 var rtype = d.relation.tags.type;
67594 rtype: rtype || '',
67595 geometry: context.geometry(id),
67597 }, function(err, data) {
67598 if (!err) callback(sort(role, data));
67604 function unbind() {
67605 var row = select(this);
67607 row.selectAll('input.member-role')
67608 .call(d3combobox.off);
67614 rawMembershipEditor.entityID = function(_) {
67615 if (!arguments.length) return id;
67617 return rawMembershipEditor;
67621 return rawMembershipEditor;
67624 function uiTagReference(tag) {
67625 var taginfo = services.taginfo,
67633 function findLocal(data) {
67634 var locale = utilDetect().locale.toLowerCase(),
67637 if (locale !== 'pt-br') { // see #3776, prefer 'pt' over 'pt-br'
67638 localized = lodash.find(data, function(d) {
67639 return d.lang.toLowerCase() === locale;
67641 if (localized) return localized;
67644 // try the non-regional version of a language, like
67645 // 'en' if the language is 'en-US'
67646 if (locale.indexOf('-') !== -1) {
67647 var first = locale.split('-')[0];
67648 localized = lodash.find(data, function(d) {
67649 return d.lang.toLowerCase() === first;
67651 if (localized) return localized;
67654 // finally fall back to english
67655 return lodash.find(data, function(d) {
67656 return d.lang.toLowerCase() === 'en';
67661 function load(param) {
67662 if (!taginfo) return;
67664 button.classed('tag-reference-loading', true);
67666 taginfo.docs(param, function show(err, data) {
67668 if (!err && data) {
67669 docs = findLocal(data);
67675 if (!docs || !docs.title) {
67676 if (param.hasOwnProperty('value')) {
67677 load(lodash.omit(param, 'value')); // retry with key only
67679 body.append('p').text(t('inspector.no_documentation_key'));
67686 if (docs.image && docs.image.thumb_url_prefix) {
67689 .attr('class', 'wiki-image')
67690 .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
67691 .on('load', function() { done(); })
67692 .on('error', function() { select(this).remove(); done(); });
67699 .text(docs.description || t('inspector.documentation_redirect'));
67703 .attr('target', '_blank')
67704 .attr('tabindex', -1)
67705 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
67706 .call(svgIcon('#icon-out-link', 'inline'))
67708 .text(t('inspector.reference'));
67716 button.classed('tag-reference-loading', false);
67720 .style('max-height', '200px')
67721 .style('opacity', '1');
67727 function hide(selection$$1) {
67728 selection$$1 = selection$$1 || body.transition().duration(200);
67731 .style('max-height', '0px')
67732 .style('opacity', '0');
67738 tagReference.button = function(selection$$1) {
67739 button = selection$$1.selectAll('.tag-reference-button')
67742 button = button.enter()
67744 .attr('class', 'tag-reference-button')
67745 .attr('tabindex', -1)
67746 .call(svgIcon('#icon-inspect'))
67750 .on('click', function () {
67751 event.stopPropagation();
67752 event.preventDefault();
67755 } else if (loaded) {
67764 tagReference.body = function(selection$$1) {
67765 body = selection$$1.selectAll('.tag-reference-body')
67768 body = body.enter()
67770 .attr('class', 'tag-reference-body cf')
67771 .style('max-height', '0')
67772 .style('opacity', '0')
67775 if (showing === false) {
67781 tagReference.showing = function(_) {
67782 if (!arguments.length) return showing;
67784 return tagReference;
67788 return tagReference;
67791 function uiRawTagEditor(context) {
67792 var taginfo = services.taginfo,
67793 dispatch$$1 = dispatch('change'),
67794 expanded = context.storage('raw_tag_editor.expanded') === 'true',
67796 updatePreference = true,
67805 function rawTagEditor(selection$$1) {
67806 var count = Object.keys(tags).filter(function(d) { return d; }).length;
67808 selection$$1.call(uiDisclosure()
67809 .title(t('inspector.all_tags') + ' (' + count + ')')
67810 .expanded(expanded)
67811 .on('toggled', toggled)
67815 function toggled(expanded) {
67816 if (updatePreference) {
67817 context.storage('raw_tag_editor.expanded', expanded);
67820 selection$$1.node().parentNode.scrollTop += 200;
67826 function content(wrap) {
67827 var entries$$1 = entries(tags);
67829 if (!entries$$1.length || showBlank) {
67831 entries$$1.push({key: '', value: ''});
67835 var list = wrap.selectAll('.tag-list')
67838 list = list.enter()
67840 .attr('class', 'tag-list')
67843 var newTag = wrap.selectAll('.add-tag')
67848 .attr('class', 'add-tag')
67849 .on('click', addTag)
67850 .call(svgIcon('#icon-plus', 'light'));
67853 var items = list.selectAll('.tag-row')
67854 .data(entries$$1, function(d) { return d.key; });
67862 var enter = items.enter()
67864 .attr('class', 'tag-row cf')
67865 .classed('readonly', isReadOnly);
67869 .attr('class', 'key-wrap')
67871 .property('type', 'text')
67872 .attr('class', 'key')
67873 .attr('maxlength', 255)
67875 .on('blur', keyChange)
67876 .on('change', keyChange);
67880 .attr('class', 'input-wrap-position')
67882 .property('type', 'text')
67883 .attr('class', 'value')
67884 .attr('maxlength', 255)
67886 .on('blur', valueChange)
67887 .on('change', valueChange)
67888 .on('keydown.push-more', pushMore);
67892 .attr('tabindex', -1)
67893 .attr('class', 'remove minor')
67894 .call(svgIcon('#operation-delete'));
67901 .sort(function(a, b) {
67902 return (a.key === newRow && b.key !== newRow) ? 1
67903 : (a.key !== newRow && b.key === newRow) ? -1
67904 : ascending(a.key, b.key);
67908 .each(function(tag) {
67909 var row = select(this),
67910 key = row.select('input.key'), // propagate bound data to child
67911 value = row.select('input.value'); // propagate bound data to child
67913 if (id && taginfo) {
67914 bindTypeahead(key, value);
67917 var isRelation = (id && context.entity(id).type === 'relation'),
67920 if (isRelation && tag.key === 'type') {
67921 reference = uiTagReference({ rtype: tag.value }, context);
67923 reference = uiTagReference({ key: tag.key, value: tag.value }, context);
67926 if (state === 'hover') {
67927 reference.showing(false);
67931 .call(reference.button)
67932 .call(reference.body);
67935 items.selectAll('input.key')
67936 .attr('title', function(d) { return d.key; })
67937 .call(utilGetSetValue, function(d) { return d.key; })
67938 .property('disabled', isReadOnly);
67940 items.selectAll('input.value')
67941 .attr('title', function(d) { return d.value; })
67942 .call(utilGetSetValue, function(d) { return d.value; })
67943 .property('disabled', isReadOnly);
67945 items.selectAll('button.remove')
67946 .on('click', removeTag);
67950 function isReadOnly(d) {
67951 return readOnlyTags.indexOf(d.key) !== -1;
67955 function pushMore() {
67956 if (event.keyCode === 9 && !event.shiftKey &&
67957 list.selectAll('li:last-child input.value').node() === this) {
67963 function bindTypeahead(key, value) {
67964 if (isReadOnly({ key: key })) return;
67965 var geometry = context.geometry(id);
67967 key.call(d3combobox()
67968 .container(context.container())
67969 .fetcher(function(value, callback) {
67972 geometry: geometry,
67974 }, function(err, data) {
67975 if (!err) callback(sort(value, data));
67979 value.call(d3combobox()
67980 .container(context.container())
67981 .fetcher(function(value, callback) {
67984 key: utilGetSetValue(key),
67985 geometry: geometry,
67987 }, function(err, data) {
67988 if (!err) callback(sort(value, data));
67993 function sort(value, data) {
67994 var sameletter = [],
67996 for (var i = 0; i < data.length; i++) {
67997 if (data[i].value.substring(0, value.length) === value) {
67998 sameletter.push(data[i]);
68000 other.push(data[i]);
68003 return sameletter.concat(other);
68008 function unbind() {
68009 var row = select(this);
68011 row.selectAll('input.key')
68012 .call(d3combobox.off);
68014 row.selectAll('input.value')
68015 .call(d3combobox.off);
68019 function keyChange(d) {
68021 kNew = this.value.trim(),
68025 if (isReadOnly({ key: kNew })) {
68030 if (kNew && kNew !== kOld) {
68031 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
68033 suffix = +(match[2] || 1);
68034 while (tags[kNew]) { // rename key if already in use
68035 kNew = base + '_' + suffix++;
68038 tag[kOld] = undefined;
68039 tag[kNew] = d.value;
68041 d.key = kNew; // Maintain DOM identity through the subsequent update.
68043 if (newRow === kOld) { // see if this row is still a new row
68044 newRow = ((d.value === '' || kNew === '') ? kNew : undefined);
68048 dispatch$$1.call('change', this, tag);
68052 function valueChange(d) {
68053 if (isReadOnly(d)) return;
68055 tag[d.key] = this.value;
68057 if (newRow === d.key && d.key !== '' && d.value !== '') { // not a new row anymore
68058 newRow = undefined;
68061 dispatch$$1.call('change', this, tag);
68065 function removeTag(d) {
68066 if (isReadOnly(d)) return;
68068 tag[d.key] = undefined;
68069 dispatch$$1.call('change', this, tag);
68070 select(this.parentNode).remove();
68074 function addTag() {
68075 // Wrapped in a setTimeout in case it's being called from a blur
68076 // handler. Without the setTimeout, the call to `content` would
68077 // wipe out the pending value change.
68078 setTimeout(function() {
68081 list.selectAll('li:last-child input.key').node().focus();
68087 rawTagEditor.state = function(_) {
68088 if (!arguments.length) return state;
68090 return rawTagEditor;
68094 rawTagEditor.preset = function(_) {
68095 if (!arguments.length) return preset;
68097 if (preset.isFallback()) {
68099 updatePreference = false;
68101 expanded = context.storage('raw_tag_editor.expanded') === 'true';
68102 updatePreference = true;
68104 return rawTagEditor;
68108 rawTagEditor.tags = function(_) {
68109 if (!arguments.length) return tags;
68111 return rawTagEditor;
68115 rawTagEditor.entityID = function(_) {
68116 if (!arguments.length) return id;
68118 return rawTagEditor;
68122 rawTagEditor.expanded = function(_) {
68123 if (!arguments.length) return expanded;
68125 updatePreference = false;
68126 return rawTagEditor;
68130 rawTagEditor.readOnlyTags = function(_) {
68131 if (!arguments.length) return readOnlyTags;
68133 return rawTagEditor;
68137 return utilRebind(rawTagEditor, dispatch$$1, 'on');
68140 function uiFieldCheck(field, context) {
68141 var dispatch$$1 = dispatch('change'),
68142 options = field.strings && field.strings.options,
68145 input = select(null),
68146 text$$1 = select(null),
68147 label = select(null),
68148 reverser = select(null),
68155 for (var k in options) {
68156 values$$1.push(k === 'undefined' ? undefined : k);
68157 texts.push(field.t('options.' + k, { 'default': options[k] }));
68160 values$$1 = [undefined, 'yes'];
68161 texts = [t('inspector.unknown'), t('inspector.check.yes')];
68162 if (field.type !== 'defaultCheck') {
68163 values$$1.push('no');
68164 texts.push(t('inspector.check.no'));
68169 // Checks tags to see whether an undefined value is "Assumed to be Yes"
68170 function checkImpliedYes() {
68171 impliedYes = (field.id === 'oneway_yes');
68173 // hack: pretend `oneway` field is a `oneway_yes` field
68174 // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
68175 if (field.id === 'oneway') {
68176 var entity = context.entity(entityId);
68177 for (var key in entity.tags) {
68178 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
68180 texts[0] = t('presets.fields.oneway_yes.options.undefined');
68188 function reverserHidden() {
68189 if (!select('div.inspector-hover').empty()) return true;
68190 return !(value === 'yes' || (impliedYes && !value));
68194 function reverserSetText(selection$$1) {
68195 var entity = context.hasEntity(entityId);
68196 if (reverserHidden() || !entity) return selection$$1;
68198 var first = entity.first(),
68199 last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last(),
68200 pseudoDirection = first < last,
68201 icon = pseudoDirection ? '#icon-forward' : '#icon-backward';
68203 selection$$1.selectAll('.reverser-span')
68204 .text(t('inspector.check.reverser'))
68205 .call(svgIcon(icon, 'inline'));
68207 return selection$$1;
68211 var check = function(selection$$1) {
68213 selection$$1.classed('checkselect', 'true');
68215 label = selection$$1.selectAll('.preset-input-wrap')
68218 var enter = label.enter()
68220 .attr('class', 'preset-input-wrap');
68224 .property('indeterminate', field.type !== 'defaultCheck')
68225 .attr('type', 'checkbox')
68226 .attr('id', 'preset-input-' + field.id);
68231 .attr('class', 'value');
68233 if (field.type === 'onewayCheck') {
68236 .attr('id', 'preset-input-' + field.id + '-reverser')
68237 .attr('class', 'reverser button' + (reverserHidden() ? ' hide' : ''))
68240 .attr('class', 'reverser-span');
68243 label = label.merge(enter);
68244 input = label.selectAll('input');
68245 text$$1 = label.selectAll('span.value');
68248 .on('click', function() {
68250 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
68251 dispatch$$1.call('change', this, t$$1);
68252 event.stopPropagation();
68255 if (field.type === 'onewayCheck') {
68256 reverser = label.selectAll('.reverser');
68259 .call(reverserSetText)
68260 .on('click', function() {
68261 event.preventDefault();
68262 event.stopPropagation();
68264 actionReverse(entityId),
68265 t('operations.reverse.annotation')
68268 .call(reverserSetText);
68274 check.entity = function(_) {
68275 if (!arguments.length) return context.hasEntity(entityId);
68281 check.tags = function(tags) {
68283 value = tags[field.key] && tags[field.key].toLowerCase();
68285 if (field.type === 'onewayCheck' && (value === '1' || value === '-1')) {
68290 .property('indeterminate', field.type !== 'defaultCheck' && !value)
68291 .property('checked', value === 'yes');
68294 .text(texts[values$$1.indexOf(value)]);
68297 .classed('set', !!value);
68299 if (field.type === 'onewayCheck') {
68301 .classed('hide', reverserHidden())
68302 .call(reverserSetText);
68307 check.focus = function() {
68308 input.node().focus();
68311 return utilRebind(check, dispatch$$1, 'on');
68314 function uiFieldCombo(field, context) {
68315 var dispatch$$1 = dispatch('change'),
68316 nominatim = services.geocoder,
68317 taginfo = services.taginfo,
68318 isMulti = (field.type === 'multiCombo'),
68319 isNetwork = (field.type === 'networkCombo'),
68320 isSemi = (field.type === 'semiCombo'),
68321 optstrings = field.strings && field.strings.options,
68322 optarray = field.options,
68323 snake_case = (field.snake_case || (field.snake_case === undefined)),
68324 combobox = d3combobox()
68325 .container(context.container())
68326 .minItems(isMulti || isSemi ? 1 : 2),
68334 // ensure multiCombo field.key ends with a ':'
68335 if (isMulti && field.key.match(/:$/) === null) {
68340 function snake(s) {
68341 return s.replace(/\s+/g, '_');
68344 function unsnake(s) {
68345 return s.replace(/_+/g, ' ');
68348 function clean(s) {
68349 return s.split(';')
68350 .map(function(s) { return s.trim(); })
68355 // returns the tag value for a display value
68356 // (for multiCombo, dval should be the key suffix, not the entire key)
68357 function tagValue(dval) {
68358 dval = clean(dval || '');
68361 var match = lodash.find(comboData, function(o) {
68362 return o.key && clean(o.value) === dval;
68369 if (field.type === 'typeCombo' && !dval) {
68373 return (snake_case ? snake(dval) : dval) || undefined;
68377 // returns the display value for a tag value
68378 // (for multiCombo, tval should be the key suffix, not the entire key)
68379 function displayValue(tval) {
68383 var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
68385 return match.value;
68389 if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
68393 return snake_case ? unsnake(tval) : tval;
68397 function objectDifference(a, b) {
68398 return lodash.reject(a, function(d1) {
68399 return lodash.some(b, function(d2) { return d1.value === d2.value; });
68404 function initCombo(selection$$1, attachTo) {
68406 selection$$1.attr('readonly', 'readonly');
68407 selection$$1.call(combobox, attachTo);
68408 setStaticValues(setPlaceholder);
68410 } else if (optarray) {
68411 selection$$1.call(combobox, attachTo);
68412 setStaticValues(setPlaceholder);
68414 } else if (taginfo) {
68415 selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
68416 setTaginfoValues('', setPlaceholder);
68421 function setStaticValues(callback) {
68422 if (!(optstrings || optarray)) return;
68425 comboData = Object.keys(optstrings).map(function(k) {
68426 var v = field.t('options.' + k, { 'default': optstrings[k] });
68434 } else if (optarray) {
68435 comboData = optarray.map(function(k) {
68436 var v = snake_case ? unsnake(k) : k;
68445 combobox.data(objectDifference(comboData, multiData));
68446 if (callback) callback(comboData);
68450 function setTaginfoValues(q, callback) {
68451 var fn = isMulti ? 'multikeys' : 'values';
68452 var query = (isMulti ? field.key : '') + q;
68453 var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
68454 if (hasCountryPrefix) {
68455 query = country + ':';
68459 debounce: (q !== ''),
68461 geometry: context.geometry(entity.id),
68463 }, function(err, data) {
68465 if (hasCountryPrefix) {
68466 data = lodash.filter(data, function(d) {
68467 return d.value.toLowerCase().indexOf(country + ':') === 0;
68471 comboData = lodash.map(data, function(d) {
68473 if (isMulti) k = k.replace(field.key, '');
68474 var v = snake_case ? unsnake(k) : k;
68478 title: isMulti ? v : d.title
68482 comboData = objectDifference(comboData, multiData);
68483 if (callback) callback(comboData);
68488 function setPlaceholder(d) {
68491 if (isMulti || isSemi) {
68492 ph = field.placeholder() || t('inspector.add');
68494 var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
68495 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
68496 ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
68499 if (ph.match(/(…|\.\.\.)$/) === null) {
68503 container.selectAll('input')
68504 .attr('placeholder', ph);
68508 function change() {
68509 var val = tagValue(utilGetSetValue(input)),
68512 if (isMulti || isSemi) {
68514 container.classed('active', false);
68515 utilGetSetValue(input, '');
68517 field.keys.push(field.key + val);
68518 t$$1[field.key + val] = 'yes';
68519 } else if (isSemi) {
68520 var arr = multiData.map(function(d) { return d.key; });
68522 t$$1[field.key] = lodash.compact(lodash.uniq(arr)).join(';');
68524 window.setTimeout(function() { input.node().focus(); }, 10);
68527 t$$1[field.key] = val;
68530 dispatch$$1.call('change', this, t$$1);
68534 function removeMultikey(d) {
68535 event.stopPropagation();
68538 t$$1[d.key] = undefined;
68539 } else if (isSemi) {
68540 lodash.remove(multiData, function(md) { return md.key === d.key; });
68541 var arr = multiData.map(function(md) { return md.key; });
68542 arr = lodash.compact(lodash.uniq(arr));
68543 t$$1[field.key] = arr.length ? arr.join(';') : undefined;
68545 dispatch$$1.call('change', this, t$$1);
68549 function combo(selection$$1) {
68550 if (isMulti || isSemi) {
68551 container = selection$$1.selectAll('ul').data([0]);
68553 container = container.enter()
68555 .attr('class', 'form-field-multicombo')
68556 .on('click', function() {
68557 window.setTimeout(function() { input.node().focus(); }, 10);
68562 container = selection$$1;
68565 input = container.selectAll('input')
68568 input = input.enter()
68570 .attr('type', 'text')
68571 .attr('id', 'preset-input-' + field.id)
68573 .call(initCombo, selection$$1)
68576 if (isNetwork && nominatim && entity) {
68577 var center = entity.extent(context.graph()).center();
68578 nominatim.countryCode(center, function (err, code) {
68584 .on('change', change)
68585 .on('blur', change);
68587 if (isMulti || isSemi) {
68589 .on('accept', function() {
68590 input.node().blur();
68591 input.node().focus();
68595 .on('focus', function() { container.classed('active', true); });
68600 combo.tags = function(tags) {
68601 if (isMulti || isSemi) {
68605 // Build multiData array containing keys already set..
68606 Object.keys(tags).forEach(function(key) {
68607 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
68609 var suffix = key.substring(field.key.length);
68612 value: displayValue(suffix)
68616 // Set keys for form-field modified (needed for undo and reset buttons)..
68617 field.keys = lodash.map(multiData, 'key');
68619 } else if (isSemi) {
68620 var arr = lodash.compact(lodash.uniq((tags[field.key] || '').split(';')));
68621 multiData = arr.map(function(key) {
68624 value: displayValue(key)
68629 // Exclude existing multikeys from combo options..
68630 var available = objectDifference(comboData, multiData);
68631 combobox.data(available);
68633 // Hide 'Add' button if this field uses fixed set of
68634 // translateable optstrings and they're all currently used..
68635 container.selectAll('.combobox-input, .combobox-caret')
68636 .classed('hide', optstrings && !available.length);
68640 var chips = container.selectAll('.chips')
68646 var enter = chips.enter()
68647 .insert('li', 'input')
68648 .attr('class', 'chips');
68650 enter.append('span');
68653 chips = chips.merge(enter);
68655 chips.select('span')
68656 .text(function(d) { return d.value; });
68659 .on('click', removeMultikey)
68660 .attr('class', 'remove')
68664 utilGetSetValue(input, displayValue(tags[field.key]));
68669 combo.focus = function() {
68670 input.node().focus();
68674 combo.entity = function(_) {
68675 if (!arguments.length) return entity;
68681 return utilRebind(combo, dispatch$$1, 'on');
68684 function uiFieldText(field, context) {
68685 var dispatch$$1 = dispatch('change'),
68686 nominatim = services.geocoder,
68691 function i(selection$$1) {
68692 var fieldId = 'preset-input-' + field.id;
68694 input = selection$$1.selectAll('input')
68697 input = input.enter()
68699 .attr('type', field.type)
68700 .attr('id', fieldId)
68701 .attr('placeholder', field.placeholder() || t('inspector.unknown'))
68706 .on('input', change(true))
68707 .on('blur', change())
68708 .on('change', change());
68710 if (field.type === 'tel' && nominatim && entity) {
68711 var center = entity.extent(context.graph()).center();
68712 nominatim.countryCode(center, function (err, countryCode) {
68713 if (err || !dataPhoneFormats[countryCode]) return;
68714 selection$$1.selectAll('#' + fieldId)
68715 .attr('placeholder', dataPhoneFormats[countryCode]);
68718 } else if (field.type === 'number') {
68719 input.attr('type', 'text');
68721 var spinControl = selection$$1.selectAll('.spin-control')
68724 var enter = spinControl.enter()
68726 .attr('class', 'spin-control');
68731 .attr('class', 'decrement')
68732 .attr('tabindex', -1);
68737 .attr('class', 'increment')
68738 .attr('tabindex', -1);
68740 spinControl = spinControl
68743 spinControl.selectAll('button')
68744 .on('click', function(d) {
68745 event.preventDefault();
68746 var num = parseInt(input.node().value || 0, 10);
68747 if (!isNaN(num)) input.node().value = num + d;
68754 function change(onInput) {
68755 return function() {
68757 t$$1[field.key] = utilGetSetValue(input) || undefined;
68758 dispatch$$1.call('change', this, t$$1, onInput);
68763 i.entity = function(_) {
68764 if (!arguments.length) return entity;
68770 i.tags = function(tags) {
68771 utilGetSetValue(input, tags[field.key] || '');
68775 i.focus = function() {
68776 var node = input.node();
68777 if (node) node.focus();
68780 return utilRebind(i, dispatch$$1, 'on');
68783 function uiFieldAccess(field, context) {
68784 var dispatch$$1 = dispatch('change'),
68787 function access(selection$$1) {
68788 var wrap = selection$$1.selectAll('.preset-input-wrap')
68791 wrap = wrap.enter()
68793 .attr('class', 'cf preset-input-wrap')
68797 var list = wrap.selectAll('ul')
68800 list = list.enter()
68805 items = list.selectAll('li')
68809 var enter = items.enter()
68811 .attr('class', function(d) { return 'cf preset-access-' + d; });
68815 .attr('class', 'col6 label preset-label-access')
68816 .attr('for', function(d) { return 'preset-input-access-' + d; })
68817 .text(function(d) { return field.t('types.' + d); });
68821 .attr('class', 'col6 preset-input-access-wrap')
68823 .attr('type', 'text')
68824 .attr('class', 'preset-input-access')
68825 .attr('id', function(d) { return 'preset-input-access-' + d; })
68827 .each(function(d) {
68830 .container(context.container())
68831 .data(access.options(d))
68837 items = items.merge(enter);
68839 wrap.selectAll('.preset-input-access')
68840 .on('change', change)
68841 .on('blur', change);
68845 function change(d) {
68847 tag[d] = utilGetSetValue(select(this)) || undefined;
68848 dispatch$$1.call('change', this, tag);
68852 access.options = function(type) {
68853 var options = ['no', 'permissive', 'private', 'destination'];
68855 if (type !== 'access') {
68856 options.unshift('yes');
68857 options.push('designated');
68859 if (type === 'bicycle') {
68860 options.push('dismount');
68864 return options.map(function(option) {
68866 title: field.t('options.' + option + '.description'),
68873 var placeholders = {
68875 foot: 'designated',
68876 motor_vehicle: 'no'
68880 motor_vehicle: 'no',
68886 motor_vehicle: 'no'
68889 motor_vehicle: 'no',
68890 bicycle: 'designated'
68893 motor_vehicle: 'no',
68894 horse: 'designated'
68898 motor_vehicle: 'no',
68904 motor_vehicle: 'yes',
68909 motor_vehicle: 'yes'
68913 motor_vehicle: 'yes',
68919 motor_vehicle: 'yes',
68925 motor_vehicle: 'yes',
68931 motor_vehicle: 'yes',
68937 motor_vehicle: 'yes',
68943 motor_vehicle: 'yes',
68949 motor_vehicle: 'yes',
68954 motor_vehicle: 'yes'
68958 motor_vehicle: 'yes',
68964 motor_vehicle: 'yes',
68970 motor_vehicle: 'yes',
68977 access.tags = function(tags) {
68978 utilGetSetValue(items.selectAll('.preset-input-access'),
68979 function(d) { return tags[d] || ''; })
68980 .attr('placeholder', function() {
68981 return tags.access ? tags.access : field.placeholder();
68984 items.selectAll('#preset-input-access-access')
68985 .attr('placeholder', 'yes');
68987 lodash.forEach(placeholders[tags.highway], function(v, k) {
68988 items.selectAll('#preset-input-access-' + k)
68989 .attr('placeholder', function() { return (tags.access || v); });
68994 access.focus = function() {
68995 items.selectAll('.preset-input-access')
69000 return utilRebind(access, dispatch$$1, 'on');
69003 function uiFieldAddress(field, context) {
69004 var dispatch$$1 = dispatch('init', 'change'),
69005 nominatim = services.geocoder,
69006 wrap = select(null),
69007 isInitialized = false,
69010 function getNearStreets() {
69011 var extent$$1 = entity.extent(context.graph()),
69012 l = extent$$1.center(),
69013 box = geoExtent$$1(l).padByMeters(200);
69015 var streets = context.intersects(box)
69016 .filter(isAddressable)
69018 var loc = context.projection([
69019 (extent$$1[0][0] + extent$$1[1][0]) / 2,
69020 (extent$$1[0][1] + extent$$1[1][1]) / 2]),
69021 choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
69023 title: d.tags.name,
69024 value: d.tags.name,
69025 dist: choice.distance
69028 .sort(function(a, b) {
69029 return a.dist - b.dist;
69032 return lodash.uniqBy(streets, 'value');
69034 function isAddressable(d) {
69035 return d.tags.highway && d.tags.name && d.type === 'way';
69040 function getNearCities() {
69041 var extent$$1 = entity.extent(context.graph()),
69042 l = extent$$1.center(),
69043 box = geoExtent$$1(l).padByMeters(200);
69045 var cities = context.intersects(box)
69046 .filter(isAddressable)
69049 title: d.tags['addr:city'] || d.tags.name,
69050 value: d.tags['addr:city'] || d.tags.name,
69051 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
69054 .sort(function(a, b) {
69055 return a.dist - b.dist;
69058 return lodash.uniqBy(cities, 'value');
69061 function isAddressable(d) {
69063 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
69066 if (d.tags.place && d.tags.name && (
69067 d.tags.place === 'city' ||
69068 d.tags.place === 'town' ||
69069 d.tags.place === 'village'))
69072 if (d.tags['addr:city']) return true;
69078 function getNearValues(key) {
69079 var extent$$1 = entity.extent(context.graph()),
69080 l = extent$$1.center(),
69081 box = geoExtent$$1(l).padByMeters(200);
69083 var results = context.intersects(box)
69084 .filter(function hasTag(d) {
69085 return d.tags[key];
69089 title: d.tags[key],
69090 value: d.tags[key],
69091 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
69094 .sort(function(a, b) {
69095 return a.dist - b.dist;
69098 return lodash.uniqBy(results, 'value');
69102 function initCallback(err, countryCode) {
69105 var addressFormat = lodash.find(dataAddressFormats, function (a) {
69106 return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode.toLowerCase());
69107 }) || lodash.first(dataAddressFormats);
69109 var widths = addressFormat.widths || {
69110 housenumber: 1/3, street: 2/3,
69111 city: 2/3, state: 1/4, postcode: 1/3
69115 // Normalize widths.
69116 var total = lodash.reduce(r, function(sum$$1, field) {
69117 return sum$$1 + (widths[field] || 0.5);
69120 return r.map(function (field) {
69123 width: (widths[field] || 0.5) / total
69128 wrap.selectAll('div.addr-row')
69129 .data(addressFormat.format)
69132 .attr('class', 'addr-row')
69133 .selectAll('input')
69137 .property('type', 'text')
69138 .attr('placeholder', function (d) {
69139 var localkey = d.id + '!' + countryCode.toLowerCase(),
69140 tkey = field.strings.placeholders[localkey] ? localkey : d.id;
69141 return field.t('placeholders.' + tkey);
69143 .attr('class', function (d) { return 'addr-' + d.id; })
69145 .style('width', function (d) { return d.width * 100 + '%'; });
69149 // setup dropdowns for common address tags
69150 var dropdowns = addressFormat.dropdowns || [
69151 'city', 'county', 'country', 'district', 'hamlet',
69152 'neighbourhood', 'place', 'postcode', 'province',
69153 'quarter', 'state', 'street', 'subdistrict', 'suburb'
69156 // If fields exist for any of these tags, create dropdowns to pick nearby values..
69157 dropdowns.forEach(function(tag) {
69158 var nearValues = (tag === 'street') ? getNearStreets
69159 : (tag === 'city') ? getNearCities
69162 wrap.selectAll('input.addr-' + tag)
69164 .container(context.container())
69166 .fetcher(function(value, callback) {
69167 callback(nearValues('addr:' + tag));
69172 wrap.selectAll('input')
69173 .on('blur', change())
69174 .on('change', change());
69176 wrap.selectAll('input:not(.combobox-input)')
69177 .on('input', change(true));
69179 dispatch$$1.call('init');
69180 isInitialized = true;
69184 function address(selection$$1) {
69185 isInitialized = false;
69187 wrap = selection$$1.selectAll('.preset-input-wrap')
69190 wrap = wrap.enter()
69192 .attr('class', 'preset-input-wrap')
69195 if (nominatim && entity) {
69196 var center = entity.extent(context.graph()).center();
69197 nominatim.countryCode(center, initCallback);
69202 function change(onInput) {
69203 return function() {
69206 wrap.selectAll('input')
69207 .each(function (field) {
69208 tags['addr:' + field.id] = this.value || undefined;
69211 dispatch$$1.call('change', this, tags, onInput);
69216 function updateTags(tags) {
69217 utilGetSetValue(wrap.selectAll('input'), function (field) {
69218 return tags['addr:' + field.id] || '';
69223 address.entity = function(_) {
69224 if (!arguments.length) return entity;
69230 address.tags = function(tags) {
69231 if (isInitialized) {
69234 dispatch$$1.on('init', function () {
69235 dispatch$$1.on('init', null);
69242 address.focus = function() {
69243 var node = wrap.selectAll('input').node();
69244 if (node) node.focus();
69248 return utilRebind(address, dispatch$$1, 'on');
69251 function uiFieldCycleway(field, context) {
69252 var dispatch$$1 = dispatch('change'),
69253 items = select(null);
69256 function cycleway(selection$$1) {
69258 function stripcolon(s) {
69259 return s.replace(':', '');
69263 var wrap = selection$$1.selectAll('.preset-input-wrap')
69266 wrap = wrap.enter()
69268 .attr('class', 'cf preset-input-wrap')
69272 var div = wrap.selectAll('ul')
69280 items = div.selectAll('li')
69283 var enter = items.enter()
69285 .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
69289 .attr('class', 'col6 label preset-label-cycleway')
69290 .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
69291 .text(function(d) { return field.t('types.' + d); });
69295 .attr('class', 'col6 preset-input-cycleway-wrap')
69297 .attr('type', 'text')
69298 .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
69300 .each(function(d) {
69303 .container(context.container())
69304 .data(cycleway.options(d))
69310 wrap.selectAll('.preset-input-cycleway')
69311 .on('change', change)
69312 .on('blur', change);
69316 function change() {
69317 var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
69318 right = utilGetSetValue(select('.preset-input-cyclewayright')),
69321 if (left === 'none' || left === '') { left = undefined; }
69322 if (right === 'none' || right === '') { right = undefined; }
69324 // Always set both left and right as changing one can affect the other
69326 cycleway: undefined,
69327 'cycleway:left': left,
69328 'cycleway:right': right
69331 // If the left and right tags match, use the cycleway tag to tag both
69332 // sides the same way
69333 if (left === right) {
69336 'cycleway:left': undefined,
69337 'cycleway:right': undefined
69341 dispatch$$1.call('change', this, tag);
69345 cycleway.options = function() {
69346 return keys(field.strings.options).map(function(option) {
69348 title: field.t('options.' + option + '.description'),
69355 cycleway.tags = function(tags) {
69356 utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
69357 // If cycleway is set, always return that
69358 if (tags.cycleway) {
69359 return tags.cycleway;
69361 return tags[d] || '';
69363 .attr('placeholder', field.placeholder());
69367 cycleway.focus = function() {
69368 items.selectAll('.preset-input-cycleway')
69373 return utilRebind(cycleway, dispatch$$1, 'on');
69376 function uiFieldLanes(field, context) {
69377 var dispatch$$1 = dispatch('change'),
69383 function lanes(selection$$1) {
69384 lanesData = context.entity(wayID).lanes();
69386 if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
69387 selection$$1.call(lanes.off);
69391 var wrap = selection$$1.selectAll('.preset-input-wrap')
69394 wrap = wrap.enter()
69396 .attr('class', 'preset-input-wrap')
69399 var surface = wrap.selectAll('.surface')
69402 var d = utilGetDimensions(wrap);
69403 var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
69405 surface = surface.enter()
69407 .attr('width', d[0])
69408 .attr('height', 300)
69409 .attr('class', 'surface')
69413 var lanesSelection = surface.selectAll('.lanes')
69416 lanesSelection = lanesSelection.enter()
69418 .attr('class', 'lanes')
69419 .merge(lanesSelection);
69422 .attr('transform', function () {
69423 return 'translate(' + (freeSpace / 2) + ', 0)';
69427 var lane = lanesSelection.selectAll('.lane')
69428 .data(lanesData.lanes);
69433 var enter = lane.enter()
69435 .attr('class', 'lane');
69441 .attr('width', LANE_WIDTH)
69442 .attr('height', LANE_HEIGHT);
69446 .attr('class', 'forward')
69454 .attr('class', 'bothways')
69462 .attr('class', 'backward')
69473 .attr('transform', function(d) {
69474 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
69477 lane.select('.forward')
69478 .style('visibility', function(d) {
69479 return d.direction === 'forward' ? 'visible' : 'hidden';
69482 lane.select('.bothways')
69483 .style('visibility', function(d) {
69484 return d.direction === 'bothways' ? 'visible' : 'hidden';
69487 lane.select('.backward')
69488 .style('visibility', function(d) {
69489 return d.direction === 'backward' ? 'visible' : 'hidden';
69494 lanes.entity = function(_) {
69495 if (!wayID || wayID !== _.id) {
69500 lanes.tags = function() {};
69501 lanes.focus = function() {};
69502 lanes.off = function() {};
69504 return utilRebind(lanes, dispatch$$1, 'on');
69507 function uiFieldLocalized(field, context) {
69508 var dispatch$$1 = dispatch('change', 'input'),
69509 wikipedia = services.wikipedia,
69510 input = select(null),
69511 localizedInputs = select(null),
69516 function localized(selection$$1) {
69517 input = selection$$1.selectAll('.localized-main')
69520 input = input.enter()
69522 .attr('type', 'text')
69523 .attr('id', 'preset-input-' + field.id)
69524 .attr('class', 'localized-main')
69525 .attr('placeholder', field.placeholder())
69529 if (field.id === 'name') {
69530 var preset = context.presets().match(entity, context.graph());
69533 .container(context.container())
69534 .fetcher(utilSuggestNames(preset, dataSuggestions))
69539 .on('input', change(true))
69540 .on('blur', change())
69541 .on('change', change());
69544 var translateButton = selection$$1.selectAll('.localized-add')
69547 translateButton = translateButton.enter()
69549 .attr('class', 'button-input-action localized-add minor')
69550 .attr('tabindex', -1)
69551 .call(svgIcon('#icon-plus'))
69553 .title(t('translate.translate'))
69554 .placement('left'))
69555 .merge(translateButton);
69558 .on('click', addNew);
69561 localizedInputs = selection$$1.selectAll('.localized-wrap')
69564 localizedInputs = localizedInputs.enter().append('div')
69565 .attr('class', 'localized-wrap')
69566 .merge(localizedInputs);
69570 function addNew() {
69571 event.preventDefault();
69572 var data$$1 = localizedInputs.selectAll('div.entry').data();
69573 var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
69574 var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
69575 var isLangEn = defaultLang.indexOf('en') > -1;
69576 if (isLangEn || langExists) {
69579 data$$1.push({ lang: defaultLang, value: '' });
69580 localizedInputs.call(render, data$$1);
69584 function change(onInput) {
69585 return function() {
69587 t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
69588 dispatch$$1.call('change', this, t$$1, onInput);
69593 function key(lang) {
69594 return field.key + ':' + lang;
69598 function changeLang(d) {
69599 var lang = utilGetSetValue(select(this)),
69601 language = lodash.find(dataWikipedia, function(d) {
69602 return d[0].toLowerCase() === lang.toLowerCase() ||
69603 d[1].toLowerCase() === lang.toLowerCase();
69606 if (language) lang = language[2];
69608 if (d.lang && d.lang !== lang) {
69609 t$$1[key(d.lang)] = undefined;
69612 var value = utilGetSetValue(select(this.parentNode)
69613 .selectAll('.localized-value'));
69615 if (lang && value) {
69616 t$$1[key(lang)] = value;
69617 } else if (lang && wikiTitles && wikiTitles[d.lang]) {
69618 t$$1[key(lang)] = wikiTitles[d.lang];
69622 dispatch$$1.call('change', this, t$$1);
69626 function changeValue(d) {
69627 if (!d.lang) return;
69629 t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
69630 dispatch$$1.call('change', this, t$$1);
69634 function fetcher(value, cb) {
69635 var v = value.toLowerCase();
69637 cb(dataWikipedia.filter(function(d) {
69638 return d[0].toLowerCase().indexOf(v) >= 0 ||
69639 d[1].toLowerCase().indexOf(v) >= 0 ||
69640 d[2].toLowerCase().indexOf(v) >= 0;
69641 }).map(function(d) {
69642 return { value: d[1] };
69647 function render(selection$$1, data$$1) {
69648 var wraps = selection$$1.selectAll('div.entry').
69649 data(data$$1, function(d) { return d.lang; });
69654 .style('max-height','0px')
69655 .style('opacity', '0')
69656 .style('top','-10px')
69659 var innerWrap = wraps.enter()
69660 .insert('div', ':first-child');
69662 innerWrap.attr('class', 'entry')
69664 var wrap = select(this);
69665 var langcombo = d3combobox()
69666 .container(context.container())
69672 .attr('class','form-label')
69673 .text(t('translate.localized_translation_label'))
69674 .attr('for','localized-lang');
69678 .attr('class', 'minor remove')
69679 .on('click', function(d){
69680 event.preventDefault();
69682 t$$1[key(d.lang)] = undefined;
69683 dispatch$$1.call('change', this, t$$1);
69684 select(this.parentNode.parentNode)
69686 .style('max-height','240px')
69688 .style('opacity', '0')
69689 .style('max-height','0px')
69692 .call(svgIcon('#operation-delete'));
69696 .attr('class', 'localized-lang')
69697 .attr('type', 'text')
69698 .attr('placeholder',t('translate.localized_translation_language'))
69699 .on('blur', changeLang)
69700 .on('change', changeLang)
69705 .on('blur', changeValue)
69706 .on('change', changeValue)
69707 .attr('type', 'text')
69708 .attr('placeholder', t('translate.localized_translation_name'))
69709 .attr('class', 'localized-value');
69713 .style('margin-top', '0px')
69714 .style('max-height', '0px')
69715 .style('opacity', '0')
69718 .style('margin-top', '10px')
69719 .style('max-height', '240px')
69720 .style('opacity', '1')
69721 .on('end', function() {
69723 .style('max-height', '')
69724 .style('overflow', 'visible');
69728 var entry = selection$$1.selectAll('.entry');
69730 utilGetSetValue(entry.select('.localized-lang'), function(d) {
69731 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
69732 return lang ? lang[1] : d.lang;
69735 utilGetSetValue(entry.select('.localized-value'),
69736 function(d) { return d.value; });
69740 localized.tags = function(tags) {
69741 // Fetch translations from wikipedia
69742 if (tags.wikipedia && !wikiTitles) {
69744 var wm = tags.wikipedia.match(/([^:]+):(.+)/);
69745 if (wm && wm[0] && wm[1]) {
69746 wikipedia.translations(wm[1], wm[2], function(d) {
69752 utilGetSetValue(input, tags[field.key] || '');
69754 var postfixed = [], k, m;
69756 m = k.match(/^(.*):([a-zA-Z_-]+)$/);
69757 if (m && m[1] === field.key && m[2]) {
69758 postfixed.push({ lang: m[2], value: tags[k] });
69762 localizedInputs.call(render, postfixed.reverse());
69766 localized.focus = function() {
69767 input.node().focus();
69771 localized.entity = function(_) {
69772 if (!arguments.length) return entity;
69777 return utilRebind(localized, dispatch$$1, 'on');
69780 function uiFieldMaxspeed(field, context) {
69781 var dispatch$$1 = dispatch('change'),
69784 unitInput = select(null),
69785 input = select(null),
69788 var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
69789 imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
69792 function maxspeed(selection$$1) {
69793 combobox = d3combobox()
69794 .container(context.container());
69796 var unitCombobox = d3combobox()
69797 .container(context.container())
69798 .data(['km/h', 'mph'].map(comboValues));
69800 input = selection$$1.selectAll('#preset-input-' + field.id)
69803 input = input.enter()
69805 .attr('type', 'text')
69806 .attr('id', 'preset-input-' + field.id)
69807 .attr('placeholder', field.placeholder())
69813 .on('change', change)
69814 .on('blur', change);
69816 var childNodes = context.graph().childNodes(context.entity(entity.id)),
69817 loc = childNodes[~~(childNodes.length/2)].loc;
69819 isImperial = lodash.some(dataImperial.features, function(f) {
69820 return lodash.some(f.geometry.coordinates, function(d) {
69821 return geoPointInPolygon(loc, d);
69825 unitInput = selection$$1.selectAll('input.maxspeed-unit')
69828 unitInput = unitInput.enter()
69830 .attr('type', 'text')
69831 .attr('class', 'maxspeed-unit')
69832 .call(unitCombobox)
69836 .on('blur', changeUnits)
69837 .on('change', changeUnits);
69840 function changeUnits() {
69841 isImperial = utilGetSetValue(unitInput) === 'mph';
69842 utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
69849 function setSuggestions() {
69850 combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
69851 utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
69855 function comboValues(d) {
69857 value: d.toString(),
69858 title: d.toString()
69863 function change() {
69865 value = utilGetSetValue(input);
69868 tag[field.key] = undefined;
69869 } else if (isNaN(value) || !isImperial) {
69870 tag[field.key] = value;
69872 tag[field.key] = value + ' mph';
69875 dispatch$$1.call('change', this, tag);
69879 maxspeed.tags = function(tags) {
69880 var value = tags[field.key];
69882 if (value && value.indexOf('mph') >= 0) {
69883 value = parseInt(value, 10);
69885 } else if (value) {
69886 isImperial = false;
69890 utilGetSetValue(input, value || '');
69894 maxspeed.focus = function() {
69895 input.node().focus();
69899 maxspeed.entity = function(_) {
69904 return utilRebind(maxspeed, dispatch$$1, 'on');
69907 function uiFieldRadio(field, context) {
69908 var dispatch$$1 = dispatch('change'),
69909 taginfo = services.taginfo,
69910 placeholder = select(null),
69911 wrap = select(null),
69912 labels = select(null),
69913 radios = select(null),
69914 typeInput = select(null),
69915 layerInput = select(null),
69920 function selectedKey() {
69921 var selector$$1 = '.form-field-structure .toggle-list label.active input',
69922 node = selectAll(selector$$1);
69923 return !node.empty() && node.datum();
69926 // returns the tag value for a display value
69927 function tagValue(dispVal) {
69928 dispVal = snake(clean(dispVal || ''));
69929 return dispVal.toLowerCase() || 'yes';
69932 // returns the display value for a tag value
69933 function displayValue(tagVal) {
69934 tagVal = tagVal || '';
69935 return tagVal.toLowerCase() === 'yes' ? '' : unsnake(tagVal);
69938 function snake(s) {
69939 return s.replace(/\s+/g, '_');
69942 function unsnake(s) {
69943 return s.replace(/_+/g, ' ');
69946 function clean(s) {
69947 return s.split(';')
69948 .map(function(s) { return s.trim(); })
69953 function radio(selection$$1) {
69954 selection$$1.classed('preset-radio', true);
69956 wrap = selection$$1.selectAll('.preset-input-wrap')
69959 var enter = wrap.enter()
69961 .attr('class', 'preset-input-wrap toggle-list');
69965 .attr('class', 'placeholder');
69971 placeholder = wrap.selectAll('.placeholder');
69973 labels = wrap.selectAll('label')
69974 .data(field.options || field.keys);
69976 enter = labels.enter()
69981 .attr('type', 'radio')
69982 .attr('name', field.id)
69983 .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
69984 .attr('checked', false);
69988 .text(function(d) { return field.t('options.' + d, { 'default': d }); });
69993 radios = labels.selectAll('input')
69994 .on('change', changeRadio);
69998 function structureExtras(selection$$1) {
69999 var selected = selectedKey();
70001 var extrasWrap = selection$$1.selectAll('.structure-extras-wrap')
70002 .data(selected ? [0] : []);
70007 extrasWrap = extrasWrap.enter()
70009 .attr('class', 'structure-extras-wrap')
70010 .merge(extrasWrap);
70012 var list = extrasWrap.selectAll('ul')
70015 list = list.enter()
70021 var typeItem = list.selectAll('.structure-type-item')
70024 var typeEnter = typeItem.enter()
70026 .attr('class', 'cf structure-type-item');
70030 .attr('class', 'col6 label structure-label-type')
70031 .attr('for', 'structure-input-type')
70032 .text(t('inspector.radio.structure.type'));
70036 .attr('class', 'col6 structure-input-type-wrap')
70038 .attr('type', 'text')
70039 .attr('class', 'structure-input-type')
70040 .attr('placeholder', t('inspector.radio.structure.default'))
70043 typeItem = typeItem
70046 typeInput = typeItem.selectAll('.structure-input-type');
70051 .container(context.container())
70052 .fetcher(typeFetcher)
70057 .on('change', changeType)
70058 .on('blur', changeType);
70062 var showLayer = (selected === 'bridge' || selected === 'tunnel');
70064 var layerItem = list.selectAll('.structure-layer-item')
70065 .data(showLayer ? [0] : []);
70070 var layerEnter = layerItem.enter()
70072 .attr('class', 'cf structure-layer-item');
70076 .attr('class', 'col6 label structure-label-layer')
70077 .attr('for', 'structure-input-layer')
70078 .text(t('inspector.radio.structure.layer'));
70082 .attr('class', 'col6 structure-input-layer-wrap')
70084 .attr('type', 'text')
70085 .attr('class', 'structure-input-layer')
70086 .attr('placeholder', '0')
70089 var spin = layerEnter
70091 .attr('class', 'spin-control');
70096 .attr('class', 'decrement')
70097 .attr('tabindex', -1);
70102 .attr('class', 'increment')
70103 .attr('tabindex', -1);
70105 layerItem = layerItem
70106 .merge(layerEnter);
70108 layerInput = layerItem.selectAll('.structure-input-layer')
70109 .on('change', changeLayer)
70110 .on('blur', changeLayer);
70112 layerItem.selectAll('button')
70113 .on('click', function(d) {
70114 event.preventDefault();
70115 var num = parseInt(layerInput.node().value || 0, 10);
70116 if (!isNaN(num)) layerInput.node().value = num + d;
70123 function typeFetcher(q, callback) {
70126 key: selectedKey(),
70128 }, function(err, data) {
70130 var comboData = data.map(function(d) {
70133 value: unsnake(d.value),
70137 if (callback) callback(comboData);
70142 function changeType() {
70143 var key = selectedKey(),
70147 var val = tagValue(utilGetSetValue(typeInput));
70149 if (val !== 'no') oldType[key] = val;
70150 dispatch$$1.call('change', this, t$$1);
70154 function changeLayer() {
70155 // note: don't use utilGetSetValue here because we want 0 to be falsy.
70156 var t$$1 = { layer: layerInput.node().value || undefined };
70157 dispatch$$1.call('change', this, t$$1);
70161 function changeRadio() {
70166 t$$1[field.key] = undefined;
70169 radios.each(function(d) {
70170 var active$$1 = select(this).property('checked');
70171 if (active$$1) activeKey = d;
70174 if (active$$1) t$$1[field.key] = d;
70176 var val = oldType[activeKey] || 'yes';
70177 t$$1[d] = active$$1 ? val : undefined;
70181 if (field.type === 'structureRadio') {
70182 if (activeKey === 'bridge') {
70184 } else if (activeKey === 'tunnel') {
70187 t$$1.layer = undefined;
70191 dispatch$$1.call('change', this, t$$1);
70195 radio.tags = function(tags) {
70196 function checked(d) {
70198 return tags[field.key] === d;
70200 return !!(tags[d] && tags[d].toLowerCase() !== 'no');
70204 labels.classed('active', checked);
70205 radios.property('checked', checked);
70207 var selection$$1 = radios.filter(function() { return this.checked; });
70210 if (selection$$1.empty()) {
70211 placeholder.text(t('inspector.none'));
70213 placeholder.text(selection$$1.attr('value'));
70214 typeVal = oldType[selection$$1.datum()] = tags[selection$$1.datum()];
70217 if (field.type === 'structureRadio') {
70218 wrap.call(structureExtras);
70219 utilGetSetValue(typeInput, displayValue(typeVal) || '');
70220 utilGetSetValue(layerInput, tags.layer || '');
70225 radio.focus = function() {
70226 radios.node().focus();
70230 radio.entity = function(_) {
70231 if (!arguments.length) return entity;
70238 return utilRebind(radio, dispatch$$1, 'on');
70241 function uiFieldRestrictions(field, context) {
70242 var dispatch$$1 = dispatch('change'),
70243 breathe = behaviorBreathe(context),
70244 hover = behaviorHover(context),
70245 initialized = false,
70250 function restrictions(selection$$1) {
70251 // if form field is hidden or has detached from dom, clean up.
70252 if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
70253 selection$$1.call(restrictions.off);
70257 var wrap = selection$$1.selectAll('.preset-input-wrap')
70260 var enter = wrap.enter()
70262 .attr('class', 'preset-input-wrap');
70266 .attr('class', 'restriction-help');
70269 var intersection = osmIntersection(context.graph(), vertexID),
70270 graph = intersection.graph,
70271 vertex = graph.entity(vertexID),
70272 filter = utilFunctor(true),
70273 extent$$1 = geoExtent$$1(),
70274 projection$$1 = geoRawMercator();
70276 var d = utilGetDimensions(wrap.merge(enter)),
70277 c = [d[0] / 2, d[1] / 2],
70281 .scale(256 * Math.pow(2, z) / (2 * Math.PI));
70283 var s = projection$$1(vertex.loc);
70286 .translate([c[0] - s[0], c[1] - s[1]])
70287 .clipExtent([[0, 0], d]);
70289 var drawLayers = svgLayers(projection$$1, context).only('osm').dimensions(d),
70290 drawVertices = svgVertices$$1(projection$$1, context),
70291 drawLines = svgLines$$1(projection$$1, context),
70292 drawTurns = svgTurns(projection$$1, context);
70300 var surface = wrap.selectAll('.surface');
70302 if (!enter.empty()) {
70303 initialized = true;
70310 .call(utilSetDimensions, d)
70311 .call(drawVertices, graph, [vertex], filter, extent$$1, z)
70312 .call(drawLines, graph, intersection.ways, filter)
70313 .call(drawTurns, graph, intersection.turns(fromNodeID));
70316 .on('click.restrictions', click)
70317 .on('mouseover.restrictions', mouseover)
70318 .on('mouseout.restrictions', mouseout);
70321 .selectAll('.selected')
70322 .classed('selected', false);
70326 .selectAll('.' + intersection.highways[fromNodeID].id)
70327 .classed('selected', true);
70333 .on('change.restrictions', render);
70336 .on('resize.restrictions', function() {
70337 utilSetDimensions(wrap, null);
70347 var datum = event.target.__data__;
70348 if (datum instanceof osmEntity$$1) {
70349 fromNodeID = intersection.adjacentNodeId(datum.id);
70351 } else if (datum instanceof osmTurn) {
70352 if (datum.restriction) {
70354 actionUnrestrictTurn(datum, projection$$1),
70355 t('operations.restriction.annotation.delete')
70359 actionRestrictTurn(datum, projection$$1),
70360 t('operations.restriction.annotation.create')
70367 function mouseover() {
70368 var datum = event.target.__data__;
70369 if (datum instanceof osmTurn) {
70370 var graph = context.graph(),
70371 presets = context.presets(),
70374 if (datum.restriction) {
70375 preset = presets.match(graph.entity(datum.restriction), graph);
70377 preset = presets.item('type/restriction/' +
70378 osmInferRestriction(
70388 wrap.selectAll('.restriction-help')
70389 .text(t('operations.restriction.help.' +
70390 (datum.restriction ? 'toggle_off' : 'toggle_on'),
70391 { restriction: preset.name() })
70397 function mouseout() {
70398 wrap.selectAll('.restriction-help')
70399 .text(t('operations.restriction.help.' +
70400 (fromNodeID ? 'toggle' : 'select'))
70405 function render() {
70406 if (context.hasEntity(vertexID)) {
70407 restrictions(selection$$1);
70413 restrictions.entity = function(_) {
70414 if (!vertexID || vertexID !== _.id) {
70421 restrictions.tags = function() {};
70422 restrictions.focus = function() {};
70425 restrictions.off = function(selection$$1) {
70426 if (!initialized) return;
70428 selection$$1.selectAll('.surface')
70431 .on('click.restrictions', null)
70432 .on('mouseover.restrictions', null)
70433 .on('mouseout.restrictions', null);
70436 .on('change.restrictions', null);
70439 .on('resize.restrictions', null);
70443 return utilRebind(restrictions, dispatch$$1, 'on');
70446 function uiFieldTextarea(field) {
70447 var dispatch$$1 = dispatch('change'),
70448 input = select(null);
70451 function textarea(selection$$1) {
70452 input = selection$$1.selectAll('textarea')
70455 input = input.enter()
70456 .append('textarea')
70457 .attr('id', 'preset-input-' + field.id)
70458 .attr('placeholder', field.placeholder() || t('inspector.unknown'))
70459 .attr('maxlength', 255)
70461 .on('input', change(true))
70462 .on('blur', change())
70463 .on('change', change())
70468 function change(onInput) {
70469 return function() {
70471 t$$1[field.key] = utilGetSetValue(input) || undefined;
70472 dispatch$$1.call('change', this, t$$1, onInput);
70477 textarea.tags = function(tags) {
70478 utilGetSetValue(input, tags[field.key] || '');
70482 textarea.focus = function() {
70483 input.node().focus();
70487 return utilRebind(textarea, dispatch$$1, 'on');
70490 function uiFieldWikipedia(field, context) {
70491 var dispatch$$1 = dispatch('change'),
70492 wikipedia = services.wikipedia,
70493 wikidata = services.wikidata,
70494 link$$1 = select(null),
70495 lang = select(null),
70496 title = select(null),
70501 function wiki(selection$$1) {
70502 var langcombo = d3combobox()
70503 .container(context.container())
70504 .fetcher(function(value, cb) {
70505 var v = value.toLowerCase();
70507 cb(dataWikipedia.filter(function(d) {
70508 return d[0].toLowerCase().indexOf(v) >= 0 ||
70509 d[1].toLowerCase().indexOf(v) >= 0 ||
70510 d[2].toLowerCase().indexOf(v) >= 0;
70511 }).map(function(d) {
70512 return { value: d[1] };
70516 var titlecombo = d3combobox()
70517 .container(context.container())
70518 .fetcher(function(value, cb) {
70520 value = context.entity(entity.id).tags.name || '';
70523 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
70524 searchfn(language()[2], value, function(query, data$$1) {
70525 cb(data$$1.map(function(d) {
70526 return { value: d };
70532 lang = selection$$1.selectAll('input.wiki-lang')
70535 lang = lang.enter()
70537 .attr('type', 'text')
70538 .attr('class', 'wiki-lang')
70539 .attr('placeholder', t('translate.localized_translation_language'))
70543 utilGetSetValue(lang, language()[1]);
70547 .on('blur', changeLang)
70548 .on('change', changeLang);
70551 title = selection$$1.selectAll('input.wiki-title')
70554 title = title.enter()
70556 .attr('type', 'text')
70557 .attr('class', 'wiki-title')
70558 .attr('id', 'preset-input-' + field.id)
70565 .on('change', change);
70568 link$$1 = selection$$1.selectAll('.wiki-link')
70571 link$$1 = link$$1.enter()
70573 .attr('class', 'button-input-action wiki-link minor')
70574 .attr('tabindex', -1)
70575 .call(svgIcon('#icon-out-link'))
70579 .on('click', function() {
70580 event.preventDefault();
70581 if (wikiURL) window.open(wikiURL, '_blank');
70586 function language() {
70587 var value = utilGetSetValue(lang).toLowerCase();
70588 var locale = utilDetect().locale.toLowerCase();
70589 var localeLanguage;
70590 return lodash.find(dataWikipedia, function(d) {
70591 if (d[2] === locale) localeLanguage = d;
70592 return d[0].toLowerCase() === value ||
70593 d[1].toLowerCase() === value ||
70595 }) || localeLanguage || ['English', 'English', 'en'];
70599 function changeLang() {
70600 utilGetSetValue(lang, language()[1]);
70610 function change(skipWikidata) {
70611 var value = utilGetSetValue(title),
70612 m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
70613 l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
70617 // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
70618 value = decodeURIComponent(m[2]).replace(/_/g, ' ');
70622 // Best-effort `anchordecode:` implementation
70623 anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
70625 anchor = decodeURIComponent(m[3]);
70627 value += '#' + anchor.replace(/_/g, ' ');
70629 value = value.slice(0, 1).toUpperCase() + value.slice(1);
70630 utilGetSetValue(lang, l[1]);
70631 utilGetSetValue(title, value);
70635 syncTags.wikipedia = language()[2] + ':' + value;
70637 syncTags.wikipedia = undefined;
70638 syncTags.wikidata = undefined;
70641 dispatch$$1.call('change', this, syncTags);
70644 if (skipWikidata || !value || !language()[2]) return;
70646 // attempt asynchronous update of wikidata tag..
70647 var initGraph = context.graph(),
70648 initEntityId = entity.id;
70650 wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
70651 // If graph has changed, we can't apply this update.
70652 if (context.graph() !== initGraph) return;
70654 if (!data$$1 || !Object.keys(data$$1).length) return;
70656 var qids = Object.keys(data$$1);
70657 var value = qids && lodash.find(qids, function(id) { return id.match(/^Q\d+$/); });
70658 var currTags = lodash.clone(context.entity(initEntityId).tags);
70660 currTags.wikidata = value;
70662 // Coalesce the update of wikidata tag into the previous tag change
70664 actionChangeTags(initEntityId, currTags),
70665 context.history().undoAnnotation()
70668 // do not dispatch.call('change') here, because entity_editor
70669 // changeTags() is not intended to be called asynchronously
70674 wiki.tags = function(tags) {
70675 var value = tags[field.key] || '',
70676 m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
70677 l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
70678 anchor = m && m[3];
70680 // value in correct format
70682 utilGetSetValue(lang, l[1]);
70683 utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
70686 // Best-effort `anchorencode:` implementation
70687 anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
70689 anchor = anchor.replace(/ /g, '_');
70692 wikiURL = 'https://' + m[1] + '.wikipedia.org/wiki/' +
70693 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : '');
70695 // unrecognized value format
70697 utilGetSetValue(title, value);
70698 if (value && value !== '') {
70699 utilGetSetValue(lang, '');
70700 wikiURL = 'https://en.wikipedia.org/wiki/Special:Search?search=' + value;
70708 wiki.entity = function(_) {
70709 if (!arguments.length) return entity;
70715 wiki.focus = function() {
70716 title.node().focus();
70720 return utilRebind(wiki, dispatch$$1, 'on');
70724 access: uiFieldAccess,
70725 address: uiFieldAddress,
70726 check: uiFieldCheck,
70727 combo: uiFieldCombo,
70728 cycleway: uiFieldCycleway,
70729 defaultCheck: uiFieldCheck,
70730 email: uiFieldText,
70731 lanes: uiFieldLanes,
70732 localized: uiFieldLocalized,
70733 maxspeed: uiFieldMaxspeed,
70734 multiCombo: uiFieldCombo,
70735 networkCombo: uiFieldCombo,
70736 number: uiFieldText,
70737 onewayCheck: uiFieldCheck,
70738 radio: uiFieldRadio,
70739 restrictions: uiFieldRestrictions,
70740 semiCombo: uiFieldCombo,
70741 structureRadio: uiFieldRadio,
70744 textarea: uiFieldTextarea,
70745 typeCombo: uiFieldCombo,
70747 wikipedia: uiFieldWikipedia
70750 function uiPreset(context) {
70751 var dispatch$$1 = dispatch('change'),
70759 // Field Constructor
70760 function UIField(field, entity, show) {
70761 field = lodash.clone(field);
70763 field.input = uiFields[field.type](field, context)
70764 .on('change', function(t$$1, onInput) {
70765 dispatch$$1.call('change', field, t$$1, onInput);
70768 if (field.input.entity) field.input.entity(entity);
70770 field.keys = field.keys || [field.key];
70774 field.shown = function() {
70775 return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
70778 field.modified = function() {
70779 var original = context.graph().base().entities[entity.id];
70780 return lodash.some(field.keys, function(key) {
70781 return original ? tags[key] !== original.tags[key] : tags[key];
70785 field.revert = function() {
70786 var original = context.graph().base().entities[entity.id],
70788 field.keys.forEach(function(key) {
70789 t$$1[key] = original ? original.tags[key] : undefined;
70794 field.present = function() {
70795 return lodash.some(field.keys, function(key) {
70800 field.remove = function() {
70802 field.keys.forEach(function(key) {
70803 t$$1[key] = undefined;
70812 function fieldKey(field) {
70817 function presets(selection$$1) {
70818 selection$$1.call(uiDisclosure()
70819 .title(t('inspector.all_fields'))
70820 .expanded(context.storage('preset_fields.expanded') !== 'false')
70821 .on('toggled', toggled)
70825 function toggled(expanded) {
70826 context.storage('preset_fields.expanded', expanded);
70831 function content(selection$$1) {
70833 var entity = context.entity(id),
70834 geometry = context.geometry(id),
70835 presets = context.presets();
70839 if (presets.field('name')) {
70840 fieldsArr.push(UIField(presets.field('name'), entity));
70843 preset.fields.forEach(function(field) {
70844 if (field.matchGeometry(geometry)) {
70845 fieldsArr.push(UIField(field, entity, true));
70849 if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
70850 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
70853 presets.universal().forEach(function(field) {
70854 if (preset.fields.indexOf(field) < 0) {
70855 fieldsArr.push(UIField(field, entity));
70860 var shown = fieldsArr.filter(function(field) { return field.shown(); }),
70861 notShown = fieldsArr.filter(function(field) { return !field.shown(); });
70864 var form = selection$$1.selectAll('.preset-form')
70867 form = form.enter()
70869 .attr('class', 'preset-form inspector-inner fillL3')
70873 var fields = form.selectAll('.form-field')
70874 .data(shown, fieldKey);
70880 var enter = fields.enter()
70882 .attr('class', function(field) {
70883 return 'form-field form-field-' + field.id;
70888 .attr('class', 'form-label')
70889 .attr('for', function(field) { return 'preset-input-' + field.id; })
70890 .text(function(field) { return field.label(); });
70894 .attr('class', 'form-label-button-wrap');
70896 wrap.append('button')
70897 .attr('class', 'remove-icon')
70898 .attr('tabindex', -1)
70899 .call(svgIcon('#operation-delete'));
70901 wrap.append('button')
70902 .attr('class', 'modified-icon')
70903 .attr('tabindex', -1)
70905 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
70913 fields.selectAll('.form-label-button-wrap .remove-icon')
70914 .on('click', remove);
70916 fields.selectAll('.modified-icon')
70917 .on('click', revert);
70921 .classed('modified', function(field) { return field.modified(); })
70922 .classed('present', function(field) { return field.present(); })
70923 .each(function(field) {
70924 var referenceKey = field.key;
70925 if (field.type === 'multiCombo') { // lookup key without the trailing ':'
70926 referenceKey = referenceKey.replace(/:$/, '');
70928 var reference = uiTagReference(field.reference || { key: referenceKey }, context);
70930 if (state === 'hover') {
70931 reference.showing(false);
70936 .selectAll('input')
70937 .on('keydown', function() {
70938 // if user presses enter, and combobox is not active, accept edits..
70939 if (event.keyCode === 13 && select('.combobox').empty()) {
70940 context.enter(modeBrowse(context));
70945 .call(reference.body)
70946 .select('.form-label-button-wrap')
70947 .call(reference.button);
70949 field.input.tags(tags);
70952 notShown = notShown.map(function(field) {
70954 title: field.label(),
70955 value: field.label(),
70961 var more = selection$$1.selectAll('.more-fields')
70962 .data((notShown.length > 0) ? [0] : []);
70967 more = more.enter()
70969 .attr('class', 'more-fields')
70971 .text(t('inspector.add_fields'))
70975 var input = more.selectAll('.value')
70981 input = input.enter()
70983 .attr('class', 'value')
70984 .attr('type', 'text')
70989 .call(utilGetSetValue, '')
70990 .attr('placeholder', function() {
70991 var placeholder = [];
70992 for (var field in notShown) {
70993 placeholder.push(notShown[field].title);
70995 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
70998 .container(context.container())
71001 .on('accept', show)
71005 function show(field) {
71006 field = field.field;
71008 content(selection$$1);
71009 field.input.focus();
71013 function revert(field) {
71014 event.stopPropagation();
71015 event.preventDefault();
71016 dispatch$$1.call('change', field, field.revert());
71020 function remove(field) {
71021 event.stopPropagation();
71022 event.preventDefault();
71023 dispatch$$1.call('change', field, field.remove());
71028 presets.preset = function(_) {
71029 if (!arguments.length) return preset;
71030 if (preset && preset.id === _.id) return presets;
71037 presets.state = function(_) {
71038 if (!arguments.length) return state;
71044 presets.tags = function(_) {
71045 if (!arguments.length) return tags;
71047 // Don't reset fieldsArr here.
71052 presets.entityID = function(_) {
71053 if (!arguments.length) return id;
71054 if (id === _) return presets;
71061 return utilRebind(presets, dispatch$$1, 'on');
71064 function uiEntityEditor(context) {
71065 var dispatch$$1 = dispatch('choose'),
71067 coalesceChanges = false,
71074 var presetEditor = uiPreset(context)
71075 .on('change', changeTags);
71076 var rawTagEditor = uiRawTagEditor(context)
71077 .on('change', changeTags);
71080 function entityEditor(selection$$1) {
71081 var entity = context.entity(id),
71082 tags = lodash.clone(entity.tags);
71085 var header = selection$$1.selectAll('.header')
71089 var enter = header.enter()
71091 .attr('class', 'header fillL cf');
71095 .attr('class', 'fl preset-reset preset-choose')
71096 .call(svgIcon((textDirection === 'rtl') ? '#icon-forward' : '#icon-backward'));
71100 .attr('class', 'fr preset-close')
71101 .on('click', function() { context.enter(modeBrowse(context)); })
71102 .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
71106 .text(t('inspector.edit'));
71112 header.selectAll('.preset-reset')
71113 .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
71117 var body = selection$$1.selectAll('.inspector-body')
71121 enter = body.enter()
71123 .attr('class', 'inspector-body');
71127 .attr('class', 'preset-list-item inspector-inner')
71129 .attr('class', 'preset-list-button-wrap')
71131 .attr('class', 'preset-list-button preset-reset')
71132 .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
71134 .attr('class', 'label');
71138 .attr('class', 'inspector-border inspector-preset');
71142 .attr('class', 'inspector-border raw-tag-editor inspector-inner');
71146 .attr('class', 'inspector-border raw-member-editor inspector-inner');
71150 .attr('class', 'raw-membership-editor inspector-inner');
71156 body.selectAll('.preset-list-button-wrap')
71157 .call(reference.button);
71159 body.selectAll('.preset-list-item')
71160 .call(reference.body);
71162 body.selectAll('.preset-reset')
71163 .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
71165 body.select('.preset-list-item button')
71166 .call(uiPresetIcon()
71167 .geometry(context.geometry(id))
71168 .preset(activePreset));
71170 body.select('.preset-list-item .label')
71171 .text(activePreset.name());
71173 body.select('.inspector-preset')
71175 .preset(activePreset)
71180 body.select('.raw-tag-editor')
71182 .preset(activePreset)
71187 if (entity.type === 'relation') {
71188 body.select('.raw-member-editor')
71189 .style('display', 'block')
71190 .call(uiRawMemberEditor(context)
71193 body.select('.raw-member-editor')
71194 .style('display', 'none');
71197 body.select('.raw-membership-editor')
71198 .call(uiRawMembershipEditor(context)
71203 .on('change.entity-editor', historyChanged);
71206 function historyChanged() {
71207 if (state === 'hide') return;
71209 var entity = context.hasEntity(id),
71210 graph = context.graph();
71211 if (!entity) return;
71213 entityEditor.preset(context.presets().match(entity, graph));
71214 entityEditor.modified(base !== graph);
71215 entityEditor(selection$$1);
71220 function clean(o) {
71222 function cleanVal(k, v) {
71223 function keepSpaces(k) {
71224 return k.match(/_hours|_times/) !== null;
71227 var blacklist = ['description', 'note', 'fixme'];
71228 if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
71230 var cleaned = v.split(';')
71231 .map(function(s) { return s.trim(); })
71232 .join(keepSpaces(k) ? '; ' : ';');
71234 // The code below is not intended to validate websites and emails.
71235 // It is only intended to prevent obvious copy-paste errors. (#2323)
71236 // clean website- and email-like tags
71237 if (k.indexOf('website') !== -1 ||
71238 k.indexOf('email') !== -1 ||
71239 cleaned.indexOf('http') === 0) {
71241 .replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars
71248 var out = {}, k, v;
71250 if (k && (v = o[k]) !== undefined) {
71251 out[k] = cleanVal(k, v);
71258 // Tag changes that fire on input can all get coalesced into a single
71259 // history operation when the user leaves the field. #2342
71260 function changeTags(changed, onInput) {
71261 var entity = context.entity(id),
71262 annotation = t('operations.change_tags.annotation'),
71263 tags = lodash.clone(entity.tags);
71265 lodash.forEach(changed, function(v, k) {
71266 if (v !== undefined || tags.hasOwnProperty(k)) {
71272 tags = clean(tags);
71275 if (!lodash.isEqual(entity.tags, tags)) {
71276 if (coalesceChanges) {
71277 context.overwrite(actionChangeTags(id, tags), annotation);
71279 context.perform(actionChangeTags(id, tags), annotation);
71280 coalesceChanges = !!onInput;
71286 entityEditor.modified = function(_) {
71287 if (!arguments.length) return modified;
71289 selectAll('button.preset-close use')
71290 .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
71294 entityEditor.state = function(_) {
71295 if (!arguments.length) return state;
71297 return entityEditor;
71301 entityEditor.entityID = function(_) {
71302 if (!arguments.length) return id;
71304 base = context.graph();
71305 entityEditor.preset(context.presets().match(context.entity(id), base));
71306 entityEditor.modified(false);
71307 coalesceChanges = false;
71308 return entityEditor;
71312 entityEditor.preset = function(_) {
71313 if (!arguments.length) return activePreset;
71314 if (_ !== activePreset) {
71316 reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
71319 return entityEditor;
71323 return utilRebind(entityEditor, dispatch$$1, 'on');
71326 function uiPresetList(context) {
71327 var dispatch$$1 = dispatch('choose'),
71333 function presetList(selection$$1) {
71334 var entity = context.entity(id),
71335 geometry = context.geometry(id);
71337 // Treat entities on addr:interpolation lines as points, not vertices (#3241)
71338 if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
71339 geometry = 'point';
71342 var presets = context.presets().matchGeometry(geometry);
71344 selection$$1.html('');
71346 var messagewrap = selection$$1
71348 .attr('class', 'header fillL cf');
71350 var message = messagewrap
71352 .text(t('inspector.choose'));
71354 if (context.entity(id).isUsed(context.graph())) {
71357 .attr('class', 'preset-choose')
71358 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
71359 .call(svgIcon((textDirection === 'rtl') ? '#icon-backward' : '#icon-forward'));
71363 .attr('class', 'close')
71364 .on('click', function() {
71365 context.enter(modeBrowse(context));
71367 .call(svgIcon('#icon-close'));
71370 function keydown() {
71371 // hack to let delete shortcut work when search is autofocused
71372 if (search.property('value').length === 0 &&
71373 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
71374 event.keyCode === d3keybinding.keyCodes['⌦'])) {
71375 event.preventDefault();
71376 event.stopPropagation();
71377 operationDelete([id], context)();
71378 } else if (search.property('value').length === 0 &&
71379 (event.ctrlKey || event.metaKey) &&
71380 event.keyCode === d3keybinding.keyCodes.z) {
71381 event.preventDefault();
71382 event.stopPropagation();
71384 } else if (!event.ctrlKey && !event.metaKey) {
71385 select(this).on('keydown', null);
71389 function keypress() {
71391 var value = search.property('value');
71392 if (event.keyCode === 13 && value.length) {
71393 list.selectAll('.preset-list-item:first-child').datum().choose();
71397 function inputevent() {
71398 var value = search.property('value');
71399 list.classed('filtered', value.length);
71400 if (value.length) {
71401 var results = presets.search(value, geometry);
71402 message.text(t('inspector.results', {
71403 n: results.collection.length,
71406 list.call(drawList, results);
71408 list.call(drawList, context.presets().defaults(geometry, 36));
71409 message.text(t('inspector.choose'));
71413 var searchWrap = selection$$1
71415 .attr('class', 'search-header');
71417 var search = searchWrap
71419 .attr('class', 'preset-search-input')
71420 .attr('placeholder', t('inspector.search'))
71421 .attr('type', 'search')
71423 .on('keydown', keydown)
71424 .on('keypress', keypress)
71425 .on('input', inputevent);
71428 .call(svgIcon('#icon-search', 'pre-text'));
71431 search.node().focus();
71434 var listWrap = selection$$1
71436 .attr('class', 'inspector-body');
71438 var list = listWrap
71440 .attr('class', 'preset-list fillL cf')
71441 .call(drawList, context.presets().defaults(geometry, 36));
71445 function drawList(list, presets) {
71446 var collection = presets.collection.map(function(preset) {
71447 return preset.members ? CategoryItem(preset) : PresetItem(preset);
71450 var items = list.selectAll('.preset-list-item')
71451 .data(collection, function(d) { return d.preset.id; });
71460 .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
71461 .classed('current', function(item) { return item.preset === currentPreset; })
71462 .each(function(item) { select(this).call(item); })
71463 .style('opacity', 0)
71465 .style('opacity', 1);
71469 function CategoryItem(preset) {
71470 var box, sublist, shown = false;
71472 function item(selection$$1) {
71473 var wrap = selection$$1.append('div')
71474 .attr('class', 'preset-list-button-wrap category col12');
71478 .attr('class', 'preset-list-button')
71479 .classed('expanded', false)
71480 .call(uiPresetIcon()
71481 .geometry(context.geometry(id))
71483 .on('click', function() {
71484 var isExpanded = select(this).classed('expanded');
71485 var iconName = isExpanded ?
71486 (textDirection === 'rtl' ? '#icon-backward' : '#icon-forward') : '#icon-down';
71488 .classed('expanded', !isExpanded);
71489 select(this).selectAll('div.label svg.icon use')
71490 .attr('href', iconName);
71496 .attr('class', 'label');
71499 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'))
71501 .html(function() { return preset.name() + '…'; });
71503 box = selection$$1.append('div')
71504 .attr('class', 'subgrid col12')
71505 .style('max-height', '0px')
71506 .style('opacity', 0);
71509 .attr('class', 'arrow');
71511 sublist = box.append('div')
71512 .attr('class', 'preset-list fillL3 cf fl');
71516 item.choose = function() {
71517 if (!box || !sublist) return;
71523 .style('opacity', '0')
71524 .style('max-height', '0px')
71525 .style('padding-bottom', '0px');
71528 sublist.call(drawList, preset.members);
71531 .style('opacity', '1')
71532 .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
71533 .style('padding-bottom', '20px');
71537 item.preset = preset;
71543 function PresetItem(preset) {
71544 function item(selection$$1) {
71545 var wrap = selection$$1.append('div')
71546 .attr('class', 'preset-list-button-wrap col12');
71548 wrap.append('button')
71549 .attr('class', 'preset-list-button')
71550 .call(uiPresetIcon()
71551 .geometry(context.geometry(id))
71553 .on('click', item.choose)
71555 .attr('class', 'label')
71556 .text(preset.name());
71558 wrap.call(item.reference.button);
71559 selection$$1.call(item.reference.body);
71562 item.choose = function() {
71563 context.presets().choose(preset);
71566 actionChangePreset(id, currentPreset, preset),
71567 t('operations.change_tags.annotation')
71570 dispatch$$1.call('choose', this, preset);
71573 item.help = function() {
71574 event.stopPropagation();
71575 item.reference.toggle();
71578 item.preset = preset;
71579 item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
71585 presetList.autofocus = function(_) {
71586 if (!arguments.length) return autofocus;
71592 presetList.entityID = function(_) {
71593 if (!arguments.length) return id;
71595 presetList.preset(context.presets().match(context.entity(id), context.graph()));
71600 presetList.preset = function(_) {
71601 if (!arguments.length) return currentPreset;
71607 return utilRebind(presetList, dispatch$$1, 'on');
71610 function uiViewOnOSM(context) {
71613 function viewOnOSM(selection) {
71614 var entity = context.entity(id);
71616 selection.style('display', entity.isNew() ? 'none' : null);
71618 var link = selection.selectAll('.view-on-osm')
71621 var enter = link.enter()
71623 .attr('class', 'view-on-osm')
71624 .attr('target', '_blank')
71625 .call(svgIcon('#icon-out-link', 'inline'));
71629 .text(t('inspector.view_on_osm'));
71633 .attr('href', context.connection().entityURL(entity));
71637 viewOnOSM.entityID = function(_) {
71638 if (!arguments.length) return id;
71646 function uiInspector(context) {
71647 var presetList = uiPresetList(context),
71648 entityEditor = uiEntityEditor(context),
71651 newFeature = false;
71654 function inspector(selection$$1) {
71656 .entityID(entityID)
71657 .autofocus(newFeature)
71658 .on('choose', setPreset);
71662 .entityID(entityID)
71663 .on('choose', showList);
71665 var wrap = selection$$1.selectAll('.panewrap')
71668 var enter = wrap.enter()
71670 .attr('class', 'panewrap');
71674 .attr('class', 'preset-list-pane pane');
71678 .attr('class', 'entity-editor-pane pane');
71680 wrap = wrap.merge(enter);
71681 var presetPane = wrap.selectAll('.preset-list-pane');
71682 var editorPane = wrap.selectAll('.entity-editor-pane');
71684 var graph = context.graph(),
71685 entity = context.entity(entityID),
71686 showEditor = state === 'hover' ||
71687 entity.isUsed(graph) ||
71688 entity.isHighwayIntersection(graph);
71691 wrap.style('right', '0%');
71692 editorPane.call(entityEditor);
71694 wrap.style('right', '-100%');
71695 presetPane.call(presetList);
71698 var footer = selection$$1.selectAll('.footer')
71701 footer = footer.enter()
71703 .attr('class', 'footer')
71707 .call(uiViewOnOSM(context).entityID(entityID));
71710 function showList(preset) {
71712 .styleTween('right', function() { return interpolateValue('0%', '-100%'); });
71715 .call(presetList.preset(preset).autofocus(true));
71719 function setPreset(preset) {
71721 .styleTween('right', function() { return interpolateValue('-100%', '0%'); });
71724 .call(entityEditor.preset(preset));
71729 inspector.state = function(_) {
71730 if (!arguments.length) return state;
71732 entityEditor.state(state);
71737 inspector.entityID = function(_) {
71738 if (!arguments.length) return entityID;
71744 inspector.newFeature = function(_) {
71745 if (!arguments.length) return newFeature;
71754 function uiNotice(context) {
71756 return function(selection) {
71757 var div = selection
71759 .attr('class', 'notice');
71763 .attr('class', 'zoom-to notice')
71764 .on('click', function() { context.map().zoom(context.minEditableZoom()); });
71767 .call(svgIcon('#icon-plus', 'pre-text'))
71769 .attr('class', 'label')
71770 .text(t('zoom_in_edit'));
71773 function disableTooHigh() {
71774 div.style('display', context.editable() ? 'none' : 'block');
71778 .on('move.notice', lodash.debounce(disableTooHigh, 500));
71784 function uiSidebar(context) {
71785 var inspector = uiInspector(context),
71789 function sidebar(selection) {
71790 var featureListWrap = selection
71792 .attr('class', 'feature-list-pane')
71793 .call(uiFeatureList(context));
71796 .call(uiNotice(context));
71798 var inspectorWrap = selection
71800 .attr('class', 'inspector-hidden inspector-wrap fr');
71803 function hover(id) {
71804 if (!current && context.hasEntity(id)) {
71806 .classed('inspector-hidden', true);
71809 .classed('inspector-hidden', false)
71810 .classed('inspector-hover', true);
71812 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
71821 } else if (!current) {
71823 .classed('inspector-hidden', false);
71825 .classed('inspector-hidden', true);
71832 sidebar.hover = lodash.throttle(hover, 200);
71835 sidebar.select = function(id, newFeature) {
71836 if (!current && id) {
71838 .classed('inspector-hidden', true);
71841 .classed('inspector-hidden', false)
71842 .classed('inspector-hover', false);
71844 if (inspector.entityID() !== id || inspector.state() !== 'select') {
71848 .newFeature(newFeature);
71854 } else if (!current) {
71856 .classed('inspector-hidden', false);
71858 .classed('inspector-hidden', true);
71865 sidebar.show = function(component) {
71867 .classed('inspector-hidden', true);
71869 .classed('inspector-hidden', true);
71871 if (current) current.remove();
71872 current = selection
71874 .attr('class', 'sidebar-component')
71879 sidebar.hide = function() {
71881 .classed('inspector-hidden', false);
71883 .classed('inspector-hidden', true);
71885 if (current) current.remove();
71891 sidebar.hover = function() {};
71892 sidebar.hover.cancel = function() {};
71893 sidebar.select = function() {};
71894 sidebar.show = function() {};
71895 sidebar.hide = function() {};
71900 function uiSpinner(context) {
71901 var connection = context.connection();
71904 return function(selection) {
71905 var img = selection
71907 .attr('src', context.imagePath('loader-black.gif'))
71908 .style('opacity', 0);
71911 .on('loading.spinner', function() {
71913 .style('opacity', 1);
71917 .on('loaded.spinner', function() {
71919 .style('opacity', 0);
71924 function uiSplash(context) {
71926 return function(selection) {
71927 if (context.storage('sawSplash'))
71930 context.storage('sawSplash', true);
71932 var modalSelection = uiModal(selection);
71934 modalSelection.select('.modal')
71935 .attr('class', 'modal-splash modal col6');
71937 var introModal = modalSelection.select('.content')
71939 .attr('class', 'fillL');
71943 .attr('class','modal-section cf')
71944 .append('h3').text(t('splash.welcome'));
71948 .attr('class','modal-section')
71950 .html(t('splash.text', {
71951 version: context.version,
71952 website: '<a href="http://ideditor.com/">ideditor.com</a>',
71953 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
71956 var buttonWrap = introModal
71958 .attr('class', 'modal-actions cf');
71960 var walkthrough = buttonWrap
71962 .attr('class', 'walkthrough col6')
71963 .on('click', function() {
71964 context.container().call(uiIntro(context));
71965 modalSelection.close();
71970 .attr('class', 'logo logo-walkthrough')
71972 .attr('xlink:href', '#logo-walkthrough');
71976 .text(t('splash.walkthrough'));
71978 var startEditing = buttonWrap
71980 .attr('class', 'start-editing col6')
71981 .on('click', modalSelection.close);
71985 .attr('class', 'logo logo-features')
71987 .attr('xlink:href', '#logo-features');
71991 .text(t('splash.start'));
71994 modalSelection.select('button.close')
71995 .attr('class','hide');
72000 function uiStatus(context) {
72001 var connection = context.connection();
72003 return function(selection$$1) {
72005 function update() {
72006 connection.status(function(err, apiStatus) {
72007 selection$$1.html('');
72010 if (apiStatus === 'rateLimited') {
72012 .text(t('status.rateLimit'))
72014 .attr('class', 'api-status-login')
72015 .attr('target', '_blank')
72016 .call(svgIcon('#icon-out-link', 'inline'))
72019 .on('click.login', function() {
72020 event.preventDefault();
72021 connection.authenticate();
72024 // TODO: nice messages for different error types
72025 selection$$1.text(t('status.error'));
72028 } else if (apiStatus === 'readonly') {
72029 selection$$1.text(t('status.readonly'));
72030 } else if (apiStatus === 'offline') {
72031 selection$$1.text(t('status.offline'));
72034 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
72039 .on('change', function() { update(selection$$1); });
72041 window.setInterval(update, 90000);
72042 update(selection$$1);
72046 function uiUndoRedo(context) {
72050 action: function() { if (!saving()) context.undo(); },
72051 annotation: function() { return context.history().undoAnnotation(); }
72055 action: function() { if (!saving()) context.redo(); },
72056 annotation: function() { return context.history().redoAnnotation(); }
72060 function saving() {
72061 return context.mode().id === 'save';
72065 return function(selection$$1) {
72066 var tooltipBehavior = tooltip()
72067 .placement('bottom')
72069 .title(function (d) {
72070 return uiTooltipHtml(d.annotation() ?
72071 t(d.id + '.tooltip', {action: d.annotation()}) :
72072 t(d.id + '.nothing'), d.cmd);
72075 var buttons = selection$$1.selectAll('button')
72079 .attr('class', function(d) { return 'col6 disabled ' + d.id + '-button'; })
72080 .on('click', function(d) { return d.action(); })
72081 .call(tooltipBehavior);
72083 buttons.each(function(d) {
72084 var iconName = d.id;
72085 if (textDirection === 'rtl') {
72086 if (iconName === 'undo') {
72088 } else if (iconName === 'redo') {
72093 .call(svgIcon('#icon-' + iconName));
72096 var keybinding = d3keybinding('undo')
72097 .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
72098 .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
72104 .on('change.undo_redo', update);
72107 .on('enter.undo_redo', update);
72109 function update() {
72111 .property('disabled', saving())
72112 .classed('disabled', function(d) { return !d.annotation(); })
72114 var selection$$1 = select(this);
72115 if (selection$$1.property('tooltipVisible')) {
72116 selection$$1.call(tooltipBehavior.show);
72123 // these are module variables so they are preserved through a ui.restart()
72124 var sawVersion = null;
72125 var isNewVersion = false;
72126 var isNewUser = false;
72129 function uiVersion(context) {
72131 var currVersion = context.version,
72132 matchedVersion = currVersion.match(/\d\.\d\.\d.*/);
72134 if (sawVersion === null && matchedVersion !== null) {
72135 isNewVersion = (context.storage('sawVersion') !== currVersion);
72136 isNewUser = !context.storage('sawSplash');
72137 context.storage('sawVersion', currVersion);
72138 sawVersion = currVersion;
72141 return function(selection) {
72144 .attr('target', '_blank')
72145 .attr('tabindex', -1)
72146 .attr('href', 'https://github.com/openstreetmap/iD')
72147 .text(currVersion);
72149 // only show new version indicator to users that have used iD before
72150 if (isNewVersion && !isNewUser) {
72153 .attr('class', 'badge')
72155 .attr('target', '_blank')
72156 .attr('tabindex', -1)
72157 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CHANGELOG.md#whats-new')
72158 .call(svgIcon('#gift-11'))
72160 .title(t('version.whats_new', { version: currVersion }))
72167 function uiZoom(context) {
72171 title: t('zoom.in'),
72172 action: context.zoomIn,
72177 title: t('zoom.out'),
72178 action: context.zoomOut,
72183 function zoomIn() {
72184 event.preventDefault();
72189 function zoomOut() {
72190 event.preventDefault();
72195 function zoomInFurther() {
72196 event.preventDefault();
72197 context.zoomInFurther();
72201 function zoomOutFurther() {
72202 event.preventDefault();
72203 context.zoomOutFurther();
72207 return function(selection$$1) {
72208 var button = selection$$1.selectAll('button')
72212 .attr('tabindex', -1)
72213 .attr('class', function(d) { return d.id; })
72214 .on('click.editor', function(d) { d.action(); })
72216 .placement((textDirection === 'rtl') ? 'right' : 'left')
72218 .title(function(d) {
72219 return uiTooltipHtml(d.title, d.key);
72223 button.each(function(d) {
72225 .call(svgIcon('#icon-' + d.icon, 'light'));
72228 var keybinding = d3keybinding('zoom');
72230 lodash.each(['plus', 'ffplus', '=', 'ffequals'], function(key) {
72231 keybinding.on([key], zoomIn);
72232 keybinding.on([uiCmd('⌘' + key)], zoomInFurther);
72235 lodash.each(['_', '-', 'ffminus', 'dash'], function(key) {
72236 keybinding.on([key], zoomOut);
72237 keybinding.on([uiCmd('⌘' + key)], zoomOutFurther);
72245 function uiInit(context) {
72246 var uiInitCounter = 0;
72249 function render(container) {
72251 .attr('dir', textDirection);
72253 var map = context.map();
72255 var hash = behaviorHash(context);
72258 if (!hash.hadHash) {
72259 map.centerZoom([0, 0], 2);
72264 .attr('id', 'defs')
72265 .call(svgDefs(context));
72269 .attr('id', 'sidebar')
72270 .attr('class', 'col4')
72273 var content = container
72275 .attr('id', 'content')
72276 .attr('class', 'active');
72281 .attr('class', 'fillD');
72286 .attr('dir', 'ltr')
72290 .call(uiMapInMap(context))
72291 .call(uiInfo(context));
72295 .attr('class', 'spacer col4');
72297 var limiter = bar.append('div')
72298 .attr('class', 'limiter');
72302 .attr('class', 'button-wrap joined col3')
72303 .call(uiModes(context), limiter);
72307 .attr('class', 'button-wrap joined col1')
72308 .call(uiUndoRedo(context));
72312 .attr('class', 'button-wrap col1')
72313 .call(uiSave(context));
72317 .attr('class', 'full-screen')
72318 .call(uiFullScreen(context));
72322 .attr('class', 'spinner')
72323 .call(uiSpinner(context));
72328 .attr('class', 'map-controls');
72332 .attr('class', 'map-control zoombuttons')
72333 .call(uiZoom(context));
72337 .attr('class', 'map-control geolocate-control')
72338 .call(uiGeolocate(context));
72342 .attr('class', 'map-control background-control')
72343 .call(uiBackground(context));
72347 .attr('class', 'map-control map-data-control')
72348 .call(uiMapData(context));
72352 .attr('class', 'map-control help-control')
72353 .call(uiHelp(context));
72356 var about = content
72358 .attr('id', 'about');
72362 .attr('id', 'attrib')
72363 .attr('dir', 'ltr')
72364 .call(uiAttribution(context));
72368 .attr('class', 'api-status')
72369 .call(uiStatus(context));
72374 .attr('id', 'footer')
72375 .attr('class', 'fillD');
72379 .attr('id', 'flash-wrap')
72380 .attr('class', 'footer-hide');
72382 var footerWrap = footer
72384 .attr('id', 'footer-wrap')
72385 .attr('class', 'footer-show');
72389 .attr('id', 'scale-block')
72390 .call(uiScale(context));
72392 var aboutList = footerWrap
72394 .attr('id', 'info-block')
72396 .attr('id', 'about-list');
72398 if (!context.embed()) {
72400 .call(uiAccount(context));
72405 .attr('class', 'version')
72406 .call(uiVersion(context));
72408 var issueLinks = aboutList
72413 .attr('target', '_blank')
72414 .attr('tabindex', -1)
72415 .attr('href', 'https://github.com/openstreetmap/iD/issues')
72416 .call(svgIcon('#icon-bug', 'light'))
72417 .call(tooltip().title(t('report_a_bug')).placement('top'));
72421 .attr('target', '_blank')
72422 .attr('tabindex', -1)
72423 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
72424 .call(svgIcon('#icon-translate', 'light'))
72425 .call(tooltip().title(t('help_translate')).placement('top'));
72429 .attr('class', 'feature-warning')
72430 .attr('tabindex', -1)
72431 .call(uiFeatureInfo(context));
72435 .attr('class', 'user-list')
72436 .attr('tabindex', -1)
72437 .call(uiContributors(context));
72440 window.onbeforeunload = function() {
72441 return context.save();
72444 window.onunload = function() {
72445 context.history().unlock();
72448 var mapDimensions = map.dimensions();
72451 function onResize() {
72452 mapDimensions = utilGetDimensions(content, true);
72453 map.dimensions(mapDimensions);
72457 .on('resize.editor', onResize);
72462 return function() {
72463 event.preventDefault();
72464 context.pan(d, 100);
72472 var keybinding = d3keybinding('main')
72473 .on('⌫', function() { event.preventDefault(); })
72474 .on('←', pan([pa, 0]))
72475 .on('↑', pan([0, pa]))
72476 .on('→', pan([-pa, 0]))
72477 .on('↓', pan([0, -pa]))
72478 .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
72479 .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
72480 .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
72481 .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
72486 context.enter(modeBrowse(context));
72488 if (!uiInitCounter++) {
72489 if (!hash.startWalkthrough) {
72490 context.container()
72491 .call(uiSplash(context))
72492 .call(uiRestore(context));
72495 context.container()
72496 .call(uiShortcuts(context));
72499 var authenticating = uiLoading(context)
72500 .message(t('loading_auth'))
72503 context.connection()
72504 .on('authLoading.ui', function() {
72505 context.container()
72506 .call(authenticating);
72508 .on('authDone.ui', function() {
72509 authenticating.close();
72514 if (hash.startWalkthrough) {
72515 hash.startWalkthrough = false;
72516 context.container().call(uiIntro(context));
72521 var renderCallback;
72523 function ui(node, callback) {
72524 renderCallback = callback;
72525 var container = select(node);
72526 context.container(container);
72527 context.loadLocale(function(err) {
72538 ui.restart = function(arg) {
72539 context.locale(arg);
72540 context.loadLocale(function(err) {
72542 context.container().selectAll('*').remove();
72543 render(context.container());
72544 if (renderCallback) renderCallback();
72550 ui.sidebar = uiSidebar(context);
72556 var readOnlyTags = ['created_by', 'imagery_used', 'host', 'locale'];
72559 function uiCommit(context) {
72560 var dispatch$$1 = dispatch('cancel', 'save');
72563 function commit(selection$$1) {
72565 var detected = utilDetect(),
72567 created_by: ('iD ' + context.version).substr(0, 255),
72568 imagery_used: context.history().imageryUsed().join(';').substr(0, 255),
72569 host: detected.host.substr(0, 255),
72570 locale: detected.locale.substr(0, 255)
72573 changeset = new osmChangeset({ tags: tags });
72577 var changes = context.history().changes(),
72578 summary = context.history().difference().summary(),
72579 rawTagEditor = uiRawTagEditor(context).on('change', changeTags),
72580 comment = context.storage('comment') || '',
72581 commentDate = +context.storage('commentDate') || 0,
72582 currDate = Date.now(),
72583 cutoff = 2 * 86400 * 1000; // 2 days
72585 // expire the stored comment if it is too old - #3947
72586 if (commentDate > currDate || currDate - commentDate > cutoff) {
72592 .attr('class', 'header fillL')
72594 .text(t('commit.title'));
72596 var body = selection$$1
72598 .attr('class', 'body');
72600 var commentSection = body
72602 .attr('class', 'modal-section form-field commit-form');
72606 .attr('class', 'form-label')
72607 .text(t('commit.message_label'));
72609 var commentField = commentSection
72610 .append('textarea')
72611 .attr('class', 'commit-form-comment')
72612 .attr('placeholder', t('commit.description_placeholder'))
72613 .attr('maxlength', 255)
72614 .property('value', comment)
72615 .on('input.save', change(true))
72616 .on('change.save', change())
72617 .on('blur.save', function() {
72618 context.storage('comment', this.value);
72619 context.storage('commentDate', Date.now());
72623 commentField.node().select();
72625 context.connection().userChangesets(function (err, changesets) {
72628 var comments = changesets.map(function(changeset) {
72630 title: changeset.tags.comment,
72631 value: changeset.tags.comment
72637 .container(context.container())
72638 .caseSensitive(true)
72639 .data(lodash.uniqBy(comments, 'title'))
72643 var clippyArea = commentSection.append('div')
72644 .attr('class', 'clippy-area');
72646 var changeSetInfo = commentSection.append('div')
72647 .attr('class', 'changeset-info');
72649 changeSetInfo.append('a')
72650 .attr('target', '_blank')
72651 .attr('tabindex', -1)
72652 .call(svgIcon('#icon-out-link', 'inline'))
72653 .attr('href', t('commit.about_changeset_comments_link'))
72655 .text(t('commit.about_changeset_comments'));
72659 var warnings = body.selectAll('div.warning-section')
72660 .data([context.history().validate(changes)]);
72662 warnings = warnings.enter()
72664 .attr('class', 'modal-section warning-section fillL2')
72665 .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
72666 .style('background', '#ffb')
72671 .text(t('commit.warnings'));
72675 .attr('class', 'changeset-list');
72677 var warningLi = warnings.select('ul').selectAll('li')
72678 .data(function(d) { return d; });
72680 warningLi = warningLi.enter()
72682 .on('mouseover', mouseover)
72683 .on('mouseout', mouseout)
72684 .on('click', warningClick)
72688 .call(svgIcon('#icon-alert', 'pre-text'));
72692 .text(function(d) { return d.message; });
72694 warningLi.filter(function(d) { return d.tooltip; })
72696 .title(function(d) { return d.tooltip; })
72701 // Upload Explanation
72702 var saveSection = body
72704 .attr('class','modal-section save-section fillL cf');
72706 var prose = saveSection
72708 .attr('class', 'commit-info')
72709 .html(t('commit.upload_explanation'));
72712 context.connection().userDetails(function(err, user) {
72715 var userLink = select(document.createElement('div'));
72717 if (user.image_url) {
72720 .attr('src', user.image_url)
72721 .attr('class', 'icon pre-text user-icon');
72726 .attr('class','user-info')
72727 .text(user.display_name)
72728 .attr('href', context.connection().userURL(user.display_name))
72729 .attr('tabindex', -1)
72730 .attr('target', '_blank');
72733 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
72738 var buttonSection = saveSection
72740 .attr('class', 'buttons fillL cf');
72742 var cancelButton = buttonSection
72744 .attr('class', 'secondary-action col5 button cancel-button')
72745 .on('click.cancel', function() {
72746 dispatch$$1.call('cancel');
72751 .attr('class', 'label')
72752 .text(t('commit.cancel'));
72754 var saveButton = buttonSection
72756 .attr('class', 'action col5 button save-button')
72757 .attr('disabled', function() {
72758 var n = select('.commit-form textarea').node();
72759 return (n && n.value.length) ? null : true;
72761 .on('click.save', function() {
72762 dispatch$$1.call('save', this, changeset);
72767 .attr('class', 'label')
72768 .text(t('commit.save'));
72772 var tagSection = body
72774 .attr('class', 'modal-section tag-section raw-tag-editor');
72778 var changeSection = body
72780 .attr('class', 'commit-section modal-section fillL2');
72782 changeSection.append('h3')
72783 .text(t('commit.changes', { count: summary.length }));
72785 var li = changeSection
72787 .attr('class', 'changeset-list')
72793 .on('mouseover', mouseover)
72794 .on('mouseout', mouseout)
72795 .on('click', zoomToEntity)
72798 li.each(function(d) {
72800 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
72804 .attr('class', 'change-type')
72805 .text(function(d) { return t('commit.' + d.changeType) + ' '; });
72807 li.append('strong')
72808 .attr('class', 'entity-type')
72809 .text(function(d) {
72810 var matched = context.presets().match(d.entity, d.graph);
72811 return (matched && matched.name()) || utilDisplayType(d.entity.id);
72815 .attr('class', 'entity-name')
72816 .text(function(d) {
72817 var name = utilDisplayName(d.entity) || '',
72819 if (name !== '') string += ':';
72820 return string += ' ' + name;
72823 li.style('opacity', 0)
72825 .style('opacity', 1);
72828 // Call change() off the bat, in case a changeset
72829 // comment is recovered from localStorage
72830 utilTriggerEvent(commentField, 'input');
72833 function mouseover(d) {
72835 context.surface().selectAll(
72836 utilEntityOrMemberSelector([d.entity.id], context.graph())
72837 ).classed('hover', true);
72842 function mouseout() {
72843 context.surface().selectAll('.hover')
72844 .classed('hover', false);
72848 function warningClick(d) {
72850 context.map().zoomTo(d.entity);
72851 context.enter(modeSelect(context, [d.entity.id]));
72856 function zoomToEntity(change) {
72857 var entity = change.entity;
72858 if (change.changeType !== 'deleted' &&
72859 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
72860 context.map().zoomTo(entity);
72861 context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph()))
72862 .classed('hover', true);
72867 function checkComment(comment) {
72868 // Save button disabled if there is no comment..
72869 selectAll('.save-section .save-button')
72870 .attr('disabled', (comment.length ? null : true));
72872 // Warn if comment mentions Google..
72873 var googleWarning = clippyArea
72876 .data(comment.match(/google/i) ? [true] : []);
72878 googleWarning.exit()
72881 googleWarning.enter()
72883 .attr('target', '_blank')
72884 .attr('tabindex', -1)
72885 .call(svgIcon('#icon-alert', 'inline'))
72886 .attr('href', t('commit.google_warning_link'))
72888 .text(t('commit.google_warning'));
72892 function change(onInput) {
72893 return function() {
72894 var comment = commentField.property('value').trim();
72896 commentField.property('value', comment);
72899 checkComment(comment);
72901 var changeset = updateChangeset({ comment: comment });
72902 var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty();
72906 .expanded(expanded)
72907 .readOnlyTags(readOnlyTags)
72908 .tags(lodash.clone(changeset.tags))
72914 function changeTags(changed) {
72915 if (changed.hasOwnProperty('comment')) {
72916 if (changed.comment === undefined) {
72917 changed.comment = '';
72919 changed.comment = changed.comment.trim();
72920 commentField.property('value', changed.comment);
72922 updateChangeset(changed);
72923 utilTriggerEvent(commentField, 'input');
72927 function updateChangeset(changed) {
72928 var tags = lodash.clone(changeset.tags);
72930 lodash.forEach(changed, function(v, k) {
72931 k = k.trim().substr(0, 255);
72932 if (readOnlyTags.indexOf(k) !== -1) return;
72934 if (k !== '' && v !== undefined) {
72935 tags[k] = v.trim().substr(0, 255);
72941 if (!lodash.isEqual(changeset.tags, tags)) {
72942 changeset = changeset.update({ tags: tags });
72951 commit.reset = function() {
72956 return utilRebind(commit, dispatch$$1, 'on');
72959 function uiConfirm(selection) {
72960 var modalSelection = uiModal(selection);
72962 modalSelection.select('.modal')
72963 .classed('modal-alert', true);
72965 var section = modalSelection.select('.content');
72967 section.append('div')
72968 .attr('class', 'modal-section header');
72970 section.append('div')
72971 .attr('class', 'modal-section message-text');
72973 var buttons = section.append('div')
72974 .attr('class', 'modal-section buttons cf');
72977 modalSelection.okButton = function() {
72980 .attr('class', 'action col4')
72981 .on('click.confirm', function() {
72982 modalSelection.remove();
72984 .text(t('confirm.okay'));
72986 return modalSelection;
72990 return modalSelection;
72993 function uiConflicts(context) {
72994 var dispatch$$1 = dispatch('download', 'cancel', 'save'),
72998 function conflicts(selection$$1) {
72999 var header = selection$$1
73001 .attr('class', 'header fillL');
73005 .attr('class', 'fr')
73006 .on('click', function() { dispatch$$1.call('cancel'); })
73007 .call(svgIcon('#icon-close'));
73011 .text(t('save.conflict.header'));
73013 var body = selection$$1
73015 .attr('class', 'body fillL');
73019 .attr('class', 'conflicts-help')
73020 .text(t('save.conflict.help'))
73022 .attr('class', 'conflicts-download')
73023 .text(t('save.conflict.download_changes'))
73024 .on('click.download', function() { dispatch$$1.call('download'); });
73028 .attr('class', 'conflict-container fillL3')
73029 .call(showConflict, 0);
73033 .attr('class', 'conflicts-done')
73034 .attr('opacity', 0)
73035 .style('display', 'none')
73036 .text(t('save.conflict.done'));
73040 .attr('class','buttons col12 joined conflicts-buttons');
73044 .attr('disabled', list.length > 1)
73045 .attr('class', 'action conflicts-button col6')
73046 .text(t('save.title'))
73047 .on('click.try_again', function() { dispatch$$1.call('save'); });
73051 .attr('class', 'secondary-action conflicts-button col6')
73052 .text(t('confirm.cancel'))
73053 .on('click.cancel', function() { dispatch$$1.call('cancel'); });
73057 function showConflict(selection$$1, index) {
73058 if (index < 0 || index >= list.length) return;
73060 var parent = select(selection$$1.node().parentNode);
73062 // enable save button if this is the last conflict being reviewed..
73063 if (index === list.length - 1) {
73064 window.setTimeout(function() {
73065 parent.select('.conflicts-button')
73066 .attr('disabled', null);
73068 parent.select('.conflicts-done')
73070 .attr('opacity', 1)
73071 .style('display', 'block');
73075 var item = selection$$1
73076 .selectAll('.conflict')
73077 .data([list[index]]);
73079 var enter = item.enter()
73081 .attr('class', 'conflict');
73085 .attr('class', 'conflict-count')
73086 .text(t('save.conflict.count', { num: index + 1, total: list.length }));
73090 .attr('class', 'conflict-description')
73092 .text(function(d) { return d.name; })
73093 .on('click', function(d) {
73094 zoomToEntity(d.id);
73095 event.preventDefault();
73098 var details = enter
73100 .attr('class', 'conflict-detail-container');
73104 .attr('class', 'conflict-detail-list')
73106 .data(function(d) { return d.details || []; })
73109 .attr('class', 'conflict-detail-item')
73110 .html(function(d) { return d; });
73114 .attr('class', 'conflict-choices')
73119 .attr('class', 'conflict-nav-buttons joined cf')
73120 .selectAll('button')
73121 .data(['previous', 'next'])
73124 .text(function(d) { return t('save.conflict.' + d); })
73125 .attr('class', 'conflict-nav-button action col6')
73126 .attr('disabled', function(d, i) {
73127 return (i === 0 && index === 0) ||
73128 (i === 1 && index === list.length - 1) || null;
73130 .on('click', function(d, i) {
73131 var container = parent.select('.conflict-container'),
73132 sign = (i === 0 ? -1 : 1);
73135 .selectAll('.conflict')
73139 .call(showConflict, index + sign);
73141 event.preventDefault();
73149 function addChoices(selection$$1) {
73150 var choices = selection$$1
73152 .attr('class', 'layer-list')
73154 .data(function(d) { return d.choices || []; });
73156 var enter = choices.enter()
73158 .attr('class', 'layer');
73165 .attr('type', 'radio')
73166 .attr('name', function(d) { return d.id; })
73167 .on('change', function(d, i) {
73168 var ul = this.parentNode.parentNode.parentNode;
73169 ul.__data__.chosen = i;
73175 .text(function(d) { return d.text; });
73178 .each(function(d, i) {
73179 var ul = this.parentNode;
73180 if (ul.__data__.chosen === i) choose(ul, d);
73185 function choose(ul, datum) {
73186 if (event) event.preventDefault();
73190 .classed('active', function(d) { return d === datum; })
73191 .selectAll('input')
73192 .property('checked', function(d) { return d === datum; });
73194 var extent$$1 = geoExtent$$1(),
73197 entity = context.graph().hasEntity(datum.id);
73198 if (entity) extent$$1._extend(entity.extent(context.graph()));
73202 entity = context.graph().hasEntity(datum.id);
73203 if (entity) extent$$1._extend(entity.extent(context.graph()));
73205 zoomToEntity(datum.id, extent$$1);
73209 function zoomToEntity(id, extent$$1) {
73210 context.surface().selectAll('.hover')
73211 .classed('hover', false);
73213 var entity = context.graph().hasEntity(id);
73216 context.map().trimmedExtent(extent$$1);
73218 context.map().zoomTo(entity);
73220 context.surface().selectAll(
73221 utilEntityOrMemberSelector([entity.id], context.graph()))
73222 .classed('hover', true);
73227 // The conflict list should be an array of objects like:
73230 // name: entityName(local),
73231 // details: merge.conflicts(),
73234 // choice(id, keepMine, forceLocal),
73235 // choice(id, keepTheirs, forceRemote)
73238 conflicts.list = function(_) {
73239 if (!arguments.length) return list;
73245 return utilRebind(conflicts, dispatch$$1, 'on');
73248 function uiEditMenu(context, operations) {
73254 var p = 8, // top padding
73255 m = 4, // top margin
73256 h = 15, // height of icon
73257 vpBottomMargin = 45, // viewport bottom margin
73258 vpSideMargin = 35, // viewport side margin
73260 buttonHeight = (2 * p + h),
73261 menuWidth = buttonWidth,
73262 menuHeight = (2 * m) + operations.length * buttonHeight,
73263 menuSideMargin = 10,
73264 tooltipWidth = 200,
73265 tooltipHeight = 200; // a reasonable guess, real height depends on tooltip contents
73268 var editMenu = function (selection$$1) {
73269 if (!operations.length) return;
73271 selection$$1.node().parentNode.focus();
73273 var isRTL = textDirection === 'rtl',
73274 viewport = context.surfaceRect();
73276 if (!isRTL && (center[0] + menuSideMargin + menuWidth) > (viewport.width - vpSideMargin)) {
73277 // menu is going left-to-right and near right viewport edge, go left instead
73279 } else if (isRTL && (center[0] - menuSideMargin - menuWidth) < vpSideMargin) {
73280 // menu is going right-to-left and near left viewport edge, go right instead
73284 offset[0] = (isRTL ? -1 * (menuSideMargin + menuWidth) : menuSideMargin);
73286 if (center[1] + menuHeight > (viewport.height - vpBottomMargin)) {
73287 // menu is near bottom viewport edge, shift upwards
73288 offset[1] = -1 * (center[1] + menuHeight - viewport.height + vpBottomMargin);
73291 var origin = [ center[0] + offset[0], center[1] + offset[1] ];
73293 menu = selection$$1
73295 .attr('class', 'edit-menu')
73296 .attr('transform', 'translate(' + origin + ')')
73297 .attr('opacity', 0);
73301 .attr('opacity', 1);
73305 .attr('class', 'edit-menu-background')
73309 .attr('width', menuWidth)
73310 .attr('height', menuHeight)
73311 .attr('stroke-linecap', 'round');
73314 var button = menu.selectAll('.edit-menu-item')
73318 .attr('class', function (d) { return 'edit-menu-item edit-menu-item-' + d.id; })
73319 .classed('disabled', function (d) { return d.disabled(); })
73320 .attr('transform', function (d, i) {
73321 return 'translate(' + geoRoundCoords([
73323 m + i * buttonHeight
73324 ]).join(',') + ')';
73330 .attr('width', buttonWidth)
73331 .attr('height', buttonHeight)
73332 .on('click', click)
73333 .on('mousedown', mousedown)
73334 .on('mouseover', mouseover)
73335 .on('mouseout', mouseout);
73339 .attr('width', '20')
73340 .attr('height', '20')
73341 .attr('transform', function () {
73342 return 'translate(' + [2 * p, 5] + ')';
73344 .attr('xlink:href', function (d) { return '#operation-' + d.id; });
73346 tooltip = select(document.body)
73348 .attr('class', 'tooltip-inner edit-menu-tooltip');
73351 function click(operation) {
73352 event.stopPropagation();
73353 if (operation.disabled()) return;
73358 function mousedown() {
73359 event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
73362 function mouseover(d, i) {
73366 tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
73368 tipX = viewport.left + origin[0] - 4 - tooltipWidth;
73371 if (tipX + tooltipWidth > viewport.right) {
73372 // tip is going left-to-right and near right viewport edge, go left instead
73373 tipX = viewport.left + origin[0] - 4 - tooltipWidth;
73374 } else if (tipX < viewport.left) {
73375 // tip is going right-to-left and near left viewport edge, go right instead
73376 tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
73379 tipY = viewport.top + origin[1] + (i * buttonHeight);
73380 if (tipY + tooltipHeight > viewport.bottom) {
73381 // tip is near bottom viewport edge, shift upwards
73382 tipY -= tipY + tooltipHeight - viewport.bottom;
73386 .style('left', tipX + 'px')
73387 .style('top', tipY + 'px')
73388 .style('display', 'block')
73389 .html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title));
73392 function mouseout() {
73393 tooltip.style('display', 'none');
73398 editMenu.close = function () {
73401 .style('pointer-events', 'none')
73403 .attr('opacity', 0)
73413 editMenu.center = function (_) {
73414 if (!arguments.length) return center;
73425 function uiFlash(showDuration) {
73426 showDuration = showDuration || 1500;
73432 select('#footer-wrap')
73433 .attr('class', 'footer-hide');
73434 select('#flash-wrap')
73435 .attr('class', 'footer-show');
73437 var content = select('#flash-wrap').selectAll('.content')
73440 content = content.enter()
73442 .attr('class', 'content')
73445 timer$1 = timeout$1(function() {
73447 select('#footer-wrap')
73448 .attr('class', 'footer-show');
73449 select('#flash-wrap')
73450 .attr('class', 'footer-hide');
73457 function uiLasso(context) {
73458 var group, polygon;
73460 lasso.coordinates = [];
73462 function lasso(selection$$1) {
73463 context.container()
73464 .classed('lasso', true);
73466 group = selection$$1
73468 .attr('class', 'lasso hide');
73472 .attr('class', 'lasso-path');
73475 .call(uiToggle(true));
73481 polygon.data([lasso.coordinates])
73482 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
73487 lasso.extent = function () {
73488 return lasso.coordinates.reduce(function(extent$$1, point) {
73489 return extent$$1.extend(geoExtent$$1(point));
73490 }, geoExtent$$1());
73494 lasso.p = function(_) {
73495 if (!arguments.length) return lasso;
73496 lasso.coordinates.push(_);
73502 lasso.close = function() {
73504 group.call(uiToggle(false, function() {
73505 select(this).remove();
73508 context.container().classed('lasso', false);
73515 function uiRadialMenu(context, operations) {
73521 var radialMenu = function(selection$$1) {
73522 if (!operations.length) return;
73524 selection$$1.node().parentNode.focus();
73526 function click(operation) {
73527 event.stopPropagation();
73528 if (operation.disabled()) return;
73530 radialMenu.close();
73533 menu = selection$$1
73535 .attr('class', 'radial-menu')
73536 .attr('transform', 'translate(' + center + ')')
73537 .attr('opacity', 0);
73541 .attr('opacity', 1);
73546 a1 = a0 + (operations.length - 1) * a;
73550 .attr('class', 'radial-menu-background')
73551 .attr('d', 'M' + r * Math.sin(a0) + ',' +
73553 ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
73554 (r * Math.sin(a1) + 1e-3) + ',' +
73555 (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
73556 .attr('stroke-width', 50)
73557 .attr('stroke-linecap', 'round');
73559 var button = menu.selectAll()
73563 .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
73564 .classed('disabled', function(d) { return d.disabled(); })
73565 .attr('transform', function(d, i) {
73566 return 'translate(' + geoRoundCoords([
73567 r * Math.sin(a0 + i * a),
73568 r * Math.cos(a0 + i * a)]).join(',') + ')';
73574 .on('click', click)
73575 .on('mousedown', mousedown)
73576 .on('mouseover', mouseover)
73577 .on('mouseout', mouseout);
73581 .attr('transform', 'translate(-10,-10)')
73582 .attr('width', '20')
73583 .attr('height', '20')
73584 .attr('xlink:href', function(d) { return '#operation-' + d.id; });
73586 tooltip = select(document.body)
73588 .attr('class', 'tooltip-inner radial-menu-tooltip');
73590 function mousedown() {
73591 event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
73594 function mouseover(d, i) {
73595 var rect = context.surfaceRect(),
73596 angle = a0 + i * a,
73597 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
73598 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
73599 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
73600 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
73603 .style('top', null)
73604 .style('left', null)
73605 .style('bottom', null)
73606 .style('right', null)
73607 .style('display', 'block')
73608 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
73612 .style('right', right)
73613 .style('top', top);
73614 } else if (i >= 4) {
73616 .style('left', left)
73617 .style('bottom', bottom);
73620 .style('left', left)
73621 .style('top', top);
73625 function mouseout() {
73626 tooltip.style('display', 'none');
73631 radialMenu.close = function() {
73634 .style('pointer-events', 'none')
73636 .attr('opacity', 0)
73646 radialMenu.center = function(_) {
73647 if (!arguments.length) return center;
73656 function uiSelectionList(context, selectedIDs) {
73658 function selectEntity(entity) {
73659 context.enter(modeSelect(context, [entity.id]));
73663 function deselectEntity(entity) {
73664 event.stopPropagation();
73665 var index = selectedIDs.indexOf(entity.id);
73667 selectedIDs.splice(index, 1);
73669 context.enter(modeSelect(context, selectedIDs));
73673 function selectionList(selection$$1) {
73674 selection$$1.classed('selection-list-pane', true);
73676 var header = selection$$1
73678 .attr('class', 'header fillL cf');
73682 .text(t('inspector.multiselect'));
73684 var listWrap = selection$$1
73686 .attr('class', 'inspector-body');
73688 var list = listWrap
73690 .attr('class', 'feature-list cf');
73692 context.history().on('change.selection-list', drawList);
73696 function drawList() {
73697 var entities = selectedIDs
73698 .map(function(id) { return context.hasEntity(id); })
73699 .filter(function(entity) { return entity; });
73701 var items = list.selectAll('.feature-list-item')
73702 .data(entities, osmEntity$$1.key);
73708 var enter = items.enter()
73710 .attr('class', 'feature-list-item')
73711 .on('click', selectEntity);
73715 .attr('class', 'label');
73719 .attr('class', 'close')
73720 .on('click', deselectEntity)
73721 .call(svgIcon('#icon-close'));
73725 .attr('class', 'entity-geom-icon')
73726 .call(svgIcon('', 'pre-text'));
73730 .attr('class', 'entity-type');
73734 .attr('class', 'entity-name');
73737 items = items.merge(enter);
73739 items.selectAll('.entity-geom-icon use')
73740 .attr('href', function() {
73741 var entity = this.parentNode.parentNode.__data__;
73742 return '#icon-' + context.geometry(entity.id);
73745 items.selectAll('.entity-type')
73746 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
73748 items.selectAll('.entity-name')
73749 .text(function(entity) { return utilDisplayName(entity); });
73753 return selectionList;
73756 function uiSourceSwitch(context) {
73761 event.preventDefault();
73763 if (context.history().hasChanges() &&
73764 !window.confirm(t('source_switch.lose_changes'))) return;
73766 var live = select(this)
73769 context.connection()
73770 .switch(live ? keys$$1[1] : keys$$1[0]);
73772 context.enter(modeBrowse(context));
73776 .text(live ? t('source_switch.dev') : t('source_switch.live'))
73777 .classed('live', !live);
73780 var sourceSwitch = function(selection$$1) {
73784 .text(t('source_switch.live'))
73785 .classed('live', true)
73786 .attr('tabindex', -1)
73787 .on('click', click);
73791 sourceSwitch.keys = function(_) {
73792 if (!arguments.length) return keys$$1;
73794 return sourceSwitch;
73798 return sourceSwitch;
73801 function uiSuccess(context) {
73802 var dispatch$$1 = dispatch('cancel'),
73806 function success(selection$$1) {
73807 var header = selection$$1
73809 .attr('class', 'header fillL');
73813 .attr('class', 'fr')
73814 .on('click', function() { dispatch$$1.call('cancel'); })
73815 .call(svgIcon('#icon-close'));
73819 .text(t('success.just_edited'));
73821 var body = selection$$1
73823 .attr('class', 'body save-success fillL');
73827 .html(t('success.help_html'));
73831 .attr('class', 'details')
73832 .attr('target', '_blank')
73833 .attr('tabindex', -1)
73834 .call(svgIcon('#icon-out-link', 'inline'))
73835 .attr('href', t('success.help_link_url'))
73837 .text(t('success.help_link_text'));
73839 var changesetURL = context.connection().changesetURL(changeset.id);
73842 var viewOnOsm = body
73844 .attr('class', 'button col12 osm')
73845 .attr('target', '_blank')
73846 .attr('href', changesetURL);
73850 .attr('class', 'logo logo-osm')
73852 .attr('xlink:href', '#logo-osm');
73856 .text(t('success.view_on_osm'));
73859 var message = (changeset.tags.comment || t('success.edited_osm')).substring(0, 130) +
73860 ' ' + context.connection().changesetURL(changeset.id);
73863 facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
73864 twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
73865 google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
73868 body.selectAll('.button.social')
73869 .data(entries(sharing))
73872 .attr('class', 'button social col4')
73873 .attr('target', '_blank')
73874 .attr('href', function(d) { return d.value; })
73876 .title(function(d) { return t('success.' + d.key); })
73877 .placement('bottom'))
73878 .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
73882 success.changeset = function(_) {
73883 if (!arguments.length) return changeset;
73889 return utilRebind(success, dispatch$$1, 'on');
73892 function coreHistory(context) {
73893 var imageryUsed = ['Bing'],
73894 dispatch$$1 = dispatch('change', 'undone', 'redone'),
73895 lock = utilSessionMutex('lock'),
73898 stack$$1, index, tree$$1;
73901 // internal _act, accepts list of actions and eased time
73902 function _act(actions, t) {
73903 actions = Array.prototype.slice.call(actions);
73907 if (!lodash.isFunction(lodash.last(actions))) {
73908 annotation = actions.pop();
73911 stack$$1[index].transform = context.projection.transform();
73912 stack$$1[index].selectedIDs = context.selectedIDs();
73914 var graph = stack$$1[index].graph;
73915 for (var i = 0; i < actions.length; i++) {
73916 graph = actions[i](graph, t);
73921 annotation: annotation,
73922 imageryUsed: imageryUsed
73927 // internal _perform with eased time
73928 function _perform(args, t) {
73929 var previous = stack$$1[index].graph;
73930 stack$$1 = stack$$1.slice(0, index + 1);
73931 stack$$1.push(_act(args, t));
73933 return change(previous);
73937 // internal _replace with eased time
73938 function _replace(args, t) {
73939 var previous = stack$$1[index].graph;
73940 // assert(index == stack.length - 1)
73941 stack$$1[index] = _act(args, t);
73942 return change(previous);
73946 // internal _overwrite with eased time
73947 function _overwrite(args, t) {
73948 var previous = stack$$1[index].graph;
73953 stack$$1 = stack$$1.slice(0, index + 1);
73954 stack$$1.push(_act(args, t));
73956 return change(previous);
73960 // determine diffrence and dispatch a change event
73961 function change(previous) {
73962 var difference = coreDifference(previous, history.graph());
73963 dispatch$$1.call('change', this, difference);
73968 // iD uses namespaced keys so multiple installations do not conflict
73969 function getKey(n) {
73970 return 'iD_' + window.location.origin + '_' + n;
73976 graph: function() {
73977 return stack$$1[index].graph;
73982 return stack$$1[0].graph;
73986 merge: function(entities, extent$$1) {
73987 stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
73988 tree$$1.rebase(entities, false);
73990 dispatch$$1.call('change', this, undefined, extent$$1);
73994 perform: function() {
73995 // complete any transition already in progress
73996 select(document).interrupt('history.perform');
73998 var transitionable = false,
73999 action0 = arguments[0];
74001 if (arguments.length === 1 ||
74002 arguments.length === 2 && !lodash.isFunction(arguments[1])) {
74003 transitionable = !!action0.transitionable;
74006 if (transitionable) {
74007 var origArguments = arguments;
74009 .transition('history.perform')
74010 .duration(duration)
74012 .tween('history.tween', function() {
74013 return function(t) {
74014 if (t < 1) _overwrite([action0], t);
74017 .on('start', function() {
74018 _perform([action0], 0);
74020 .on('end interrupt', function() {
74021 _overwrite(origArguments, 1);
74025 return _perform(arguments);
74030 replace: function() {
74031 select(document).interrupt('history.perform');
74032 return _replace(arguments, 1);
74036 // Same as calling pop and then perform
74037 overwrite: function() {
74038 select(document).interrupt('history.perform');
74039 return _overwrite(arguments, 1);
74044 select(document).interrupt('history.perform');
74046 var previous = stack$$1[index].graph;
74047 if (isNaN(+n) || +n < 0) {
74050 while (n-- > 0 && index > 0) {
74054 return change(previous);
74058 // Back to the previous annotated state or index = 0.
74060 select(document).interrupt('history.perform');
74062 var previous = stack$$1[index].graph;
74063 while (index > 0) {
74065 if (stack$$1[index].annotation) break;
74068 dispatch$$1.call('undone', this, stack$$1[index]);
74069 return change(previous);
74073 // Forward to the next annotated state.
74075 select(document).interrupt('history.perform');
74077 var previous = stack$$1[index].graph;
74078 var tryIndex = index;
74079 while (tryIndex < stack$$1.length - 1) {
74081 if (stack$$1[tryIndex].annotation) {
74083 dispatch$$1.call('redone', this, stack$$1[index]);
74088 return change(previous);
74092 undoAnnotation: function() {
74095 if (stack$$1[i].annotation) return stack$$1[i].annotation;
74101 redoAnnotation: function() {
74103 while (i <= stack$$1.length - 1) {
74104 if (stack$$1[i].annotation) return stack$$1[i].annotation;
74110 intersects: function(extent$$1) {
74111 return tree$$1.intersects(extent$$1, stack$$1[index].graph);
74115 difference: function() {
74116 var base = stack$$1[0].graph,
74117 head = stack$$1[index].graph;
74118 return coreDifference(base, head);
74122 changes: function(action) {
74123 var base = stack$$1[0].graph,
74124 head = stack$$1[index].graph;
74127 head = action(head);
74130 var difference = coreDifference(base, head);
74133 modified: difference.modified(),
74134 created: difference.created(),
74135 deleted: difference.deleted()
74140 validate: function(changes) {
74141 return lodash(Validations)
74142 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
74148 hasChanges: function() {
74149 return this.difference().length() > 0;
74153 imageryUsed: function(sources) {
74155 imageryUsed = sources;
74158 return lodash(stack$$1.slice(1, index + 1))
74159 .map('imageryUsed')
74162 .without(undefined, 'Custom')
74168 // save the current history state
74169 checkpoint: function(key) {
74170 checkpoints[key] = {
74171 stack: lodash.cloneDeep(stack$$1),
74178 // restore history state to a given checkpoint or reset completely
74179 reset: function(key) {
74180 if (key !== undefined && checkpoints.hasOwnProperty(key)) {
74181 stack$$1 = lodash.cloneDeep(checkpoints[key].stack);
74182 index = checkpoints[key].index;
74184 stack$$1 = [{graph: coreGraph$$1()}];
74186 tree$$1 = coreTree(stack$$1[0].graph);
74189 dispatch$$1.call('change');
74194 toIntroGraph: function() {
74195 var nextId = { n: 0, r: 0, w: 0 },
74197 graph = this.graph(),
74200 // clone base entities..
74201 lodash.forEach(graph.base().entities, function(entity) {
74202 var copy = lodash.cloneDeepWith(entity, customizer);
74203 baseEntities[copy.id] = copy;
74206 // replace base entities with head entities..
74207 lodash.forEach(graph.entities, function(entity, id) {
74209 var copy = lodash.cloneDeepWith(entity, customizer);
74210 baseEntities[copy.id] = copy;
74212 delete baseEntities[id];
74216 // swap temporary for permanent ids..
74217 lodash.forEach(baseEntities, function(entity) {
74218 if (Array.isArray(entity.nodes)) {
74219 entity.nodes = entity.nodes.map(function(node) {
74220 return permIds[node] || node;
74223 if (Array.isArray(entity.members)) {
74224 entity.members = entity.members.map(function(member) {
74225 member.id = permIds[member.id] || member.id;
74231 return JSON.stringify({ dataIntroGraph: baseEntities });
74234 function customizer(src) {
74235 var copy = lodash.omit(lodash.cloneDeep(src), ['type', 'user', 'v', 'version', 'visible']);
74236 if (lodash.isEmpty(copy.tags)) {
74240 if (Array.isArray(copy.loc)) {
74241 copy.loc[0] = +copy.loc[0].toFixed(6);
74242 copy.loc[1] = +copy.loc[1].toFixed(6);
74245 var match = src.id.match(/([nrw])-\d*/); // temporary id
74246 if (match !== null) {
74247 var nrw = match[1], permId;
74248 do { permId = nrw + (++nextId[nrw]); }
74249 while (baseEntities.hasOwnProperty(permId));
74251 copy.id = permIds[src.id] = permId;
74258 toJSON: function() {
74259 if (!this.hasChanges()) return;
74261 var allEntities = {},
74263 base = stack$$1[0];
74265 var s = stack$$1.map(function(i) {
74266 var modified = [], deleted = [];
74268 lodash.forEach(i.graph.entities, function(entity, id) {
74270 var key = osmEntity$$1.key(entity);
74271 allEntities[key] = entity;
74272 modified.push(key);
74277 // make sure that the originals of changed or deleted entities get merged
74278 // into the base of the stack after restoring the data from JSON.
74279 if (id in base.graph.entities) {
74280 baseEntities[id] = base.graph.entities[id];
74282 // get originals of parent entities too
74283 lodash.forEach(base.graph._parentWays[id], function(parentId) {
74284 if (parentId in base.graph.entities) {
74285 baseEntities[parentId] = base.graph.entities[parentId];
74292 if (modified.length) x.modified = modified;
74293 if (deleted.length) x.deleted = deleted;
74294 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
74295 if (i.annotation) x.annotation = i.annotation;
74300 return JSON.stringify({
74302 entities: lodash.values(allEntities),
74303 baseEntities: lodash.values(baseEntities),
74305 nextIDs: osmEntity$$1.id.next,
74311 fromJSON: function(json$$1, loadChildNodes) {
74312 var h = JSON.parse(json$$1),
74313 loadComplete = true;
74315 osmEntity$$1.id.next = h.nextIDs;
74318 if (h.version === 2 || h.version === 3) {
74319 var allEntities = {};
74321 h.entities.forEach(function(entity) {
74322 allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
74325 if (h.version === 3) {
74326 // This merges originals for changed entities into the base of
74327 // the stack even if the current stack doesn't have them (for
74328 // example when iD has been restarted in a different region)
74329 var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
74330 stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
74331 tree$$1.rebase(baseEntities, true);
74333 // When we restore a modified way, we also need to fetch any missing
74334 // childnodes that would normally have been downloaded with it.. #2142
74335 if (loadChildNodes) {
74336 var missing = lodash(baseEntities)
74337 .filter({ type: 'way' })
74341 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
74344 if (!lodash.isEmpty(missing)) {
74345 loadComplete = false;
74346 context.redrawEnable(false);
74348 var loading = uiLoading(context).blocking(true);
74349 context.container().call(loading);
74351 var childNodesLoaded = function(err, result) {
74353 var visible = lodash.groupBy(result.data, 'visible');
74354 if (!lodash.isEmpty(visible.true)) {
74355 missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
74356 stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
74357 tree$$1.rebase(visible.true, true);
74360 // fetch older versions of nodes that were deleted..
74361 lodash.each(visible.false, function(entity) {
74362 context.connection()
74363 .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
74367 if (err || lodash.isEmpty(missing)) {
74369 context.redrawEnable(true);
74370 dispatch$$1.call('change');
74374 context.connection().loadMultiple(missing, childNodesLoaded);
74379 stack$$1 = h.stack.map(function(d) {
74380 var entities = {}, entity;
74383 d.modified.forEach(function(key) {
74384 entity = allEntities[key];
74385 entities[entity.id] = entity;
74390 d.deleted.forEach(function(id) {
74391 entities[id] = undefined;
74396 graph: coreGraph$$1(stack$$1[0].graph).load(entities),
74397 annotation: d.annotation,
74398 imageryUsed: d.imageryUsed
74402 } else { // original version
74403 stack$$1 = h.stack.map(function(d) {
74406 for (var i in d.entities) {
74407 var entity = d.entities[i];
74408 entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
74411 d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
74416 if (loadComplete) {
74417 dispatch$$1.call('change');
74425 if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
74430 clearSaved: function() {
74431 context.debouncedSave.cancel();
74432 if (lock.locked()) context.storage(getKey('saved_history'), null);
74438 return lock.lock();
74442 unlock: function() {
74447 // is iD not open in another window and it detects that
74448 // there's a history stored in localStorage that's recoverable?
74449 restorableChanges: function() {
74450 return lock.locked() && !!context.storage(getKey('saved_history'));
74454 // load history from a version stored in localStorage
74455 restore: function() {
74456 if (!lock.locked()) return;
74458 var json$$1 = context.storage(getKey('saved_history'));
74459 if (json$$1) history.fromJSON(json$$1, true);
74470 return utilRebind(history, dispatch$$1, 'on');
74473 function presetCollection(collection) {
74474 var maxSearchResults = 50,
74475 maxSuggestionResults = 10;
74479 collection: collection,
74482 item: function(id) {
74483 return lodash.find(this.collection, function(d) {
74484 return d.id === id;
74489 matchGeometry: function(geometry) {
74490 return presetCollection(this.collection.filter(function(d) {
74491 return d.matchGeometry(geometry);
74496 search: function(value, geometry) {
74497 if (!value) return this;
74499 function leading(a) {
74500 var index = a.indexOf(value);
74501 return index === 0 || a[index - 1] === ' ';
74504 function suggestionName(name) {
74505 var nameArray = name.split(' - ');
74506 if (nameArray.length > 1) {
74507 name = nameArray.slice(0, nameArray.length - 1).join(' - ');
74509 return name.toLowerCase();
74513 value = value.toLowerCase();
74515 var searchable = lodash.filter(this.collection, function(a) {
74516 return a.searchable !== false && a.suggestion !== true;
74518 suggestions = lodash.filter(this.collection, function(a) {
74519 return a.suggestion === true;
74523 // matches value to preset.name
74524 var leading_name = lodash.filter(searchable, function(a) {
74525 return leading(a.name().toLowerCase());
74526 }).sort(function(a, b) {
74528 i = b.originalScore - a.originalScore;
74529 if (i !== 0) return i;
74531 i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
74532 if (i !== 0) return i;
74534 return a.name().length - b.name().length;
74537 // matches value to preset.terms values
74538 var leading_terms = lodash.filter(searchable, function(a) {
74539 return lodash.some(a.terms() || [], leading);
74542 // matches value to preset.tags values
74543 var leading_tag_values = lodash.filter(searchable, function(a) {
74544 return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
74548 // finds close matches to value in preset.name
74549 var similar_name = searchable.map(function(a) {
74552 dist: utilEditDistance(value, a.name())
74554 }).filter(function(a) {
74555 return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
74556 }).sort(function(a, b) {
74557 return a.dist - b.dist;
74558 }).map(function(a) {
74562 // finds close matches to value in preset.terms
74563 var similar_terms = lodash.filter(searchable, function(a) {
74564 return lodash.some(a.terms() || [], function(b) {
74565 return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
74569 var leading_suggestions = lodash.filter(suggestions, function(a) {
74570 return leading(suggestionName(a.name()));
74571 }).sort(function(a, b) {
74572 a = suggestionName(a.name());
74573 b = suggestionName(b.name());
74574 var i = a.indexOf(value) - b.indexOf(value);
74575 if (i === 0) return a.length - b.length;
74579 var similar_suggestions = suggestions.map(function(a) {
74582 dist: utilEditDistance(value, suggestionName(a.name()))
74584 }).filter(function(a) {
74585 return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
74586 }).sort(function(a, b) {
74587 return a.dist - b.dist;
74588 }).map(function(a) {
74592 var other = presets.item(geometry);
74594 var results = leading_name.concat(
74596 leading_tag_values,
74597 leading_suggestions.slice(0, maxSuggestionResults + 5),
74600 similar_suggestions.slice(0, maxSuggestionResults)
74601 ).slice(0, maxSearchResults - 1);
74603 return presetCollection(lodash.uniq(results.concat(other)));
74611 function presetCategory(id, category, all) {
74612 category = lodash.clone(category);
74617 category.members = presetCollection(category.members.map(function(id) {
74618 return all.item(id);
74622 category.matchGeometry = function(geometry) {
74623 return category.geometry.indexOf(geometry) >= 0;
74627 category.matchScore = function() {
74632 category.name = function() {
74633 return t('presets.categories.' + id + '.name', {'default': id});
74637 category.terms = function() {
74645 function presetField(id, field) {
74646 field = lodash.clone(field);
74651 field.matchGeometry = function(geometry) {
74652 return !field.geometry || field.geometry === geometry;
74656 field.t = function(scope, options) {
74657 return t('presets.fields.' + id + '.' + scope, options);
74661 field.label = function() {
74662 return field.t('label', {'default': id});
74666 var placeholder = field.placeholder;
74667 field.placeholder = function() {
74668 return field.t('placeholder', {'default': placeholder});
74675 function presetPreset(id, preset, fields) {
74676 preset = lodash.clone(preset);
74679 preset.fields = (preset.fields || []).map(getFields);
74680 preset.geometry = (preset.geometry || []);
74683 function getFields(f) {
74688 preset.matchGeometry = function(geometry) {
74689 return preset.geometry.indexOf(geometry) >= 0;
74693 preset.originalScore = preset.matchScore || 1;
74696 preset.matchScore = function(entity) {
74697 var tags = preset.tags,
74700 for (var t$$1 in tags) {
74701 if (entity.tags[t$$1] === tags[t$$1]) {
74702 score += preset.originalScore;
74703 } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
74704 score += preset.originalScore / 2;
74714 preset.t = function(scope, options) {
74715 return t('presets.presets.' + id + '.' + scope, options);
74719 var name = preset.name || '';
74720 preset.name = function() {
74721 if (preset.suggestion) {
74722 id = id.split('/');
74723 id = id[0] + '/' + id[1];
74724 return name + ' - ' + t('presets.presets.' + id + '.name');
74726 return preset.t('name', {'default': name});
74730 preset.terms = function() {
74731 return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
74735 preset.isFallback = function() {
74736 var tagCount = Object.keys(preset.tags).length;
74737 return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
74741 var reference = preset.reference || {};
74742 preset.reference = function(geometry) {
74743 var key = reference.key || Object.keys(lodash.omit(preset.tags, 'name'))[0],
74744 value = reference.value || preset.tags[key];
74746 if (geometry === 'relation' && key === 'type') {
74747 if (value in preset.tags) {
74749 value = preset.tags[key];
74751 return { rtype: value };
74755 if (value === '*') {
74756 return { key: key };
74758 return { key: key, value: value };
74763 var removeTags = preset.removeTags || preset.tags;
74764 preset.removeTags = function(tags, geometry) {
74765 tags = lodash.omit(tags, lodash.keys(removeTags));
74767 for (var f in preset.fields) {
74768 var field = preset.fields[f];
74769 if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
74770 delete tags[field.key];
74779 var applyTags = preset.addTags || preset.tags;
74780 preset.applyTags = function(tags, geometry) {
74783 tags = lodash.clone(tags);
74785 for (k in applyTags) {
74786 if (applyTags[k] === '*') {
74789 tags[k] = applyTags[k];
74793 // Add area=yes if necessary.
74794 // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
74795 // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
74796 // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
74798 if (geometry === 'area') {
74799 var needsAreaTag = true;
74800 if (preset.geometry.indexOf('line') === -1) {
74801 for (k in applyTags) {
74802 if (k in areaKeys) {
74803 needsAreaTag = false;
74808 if (needsAreaTag) {
74813 for (var f in preset.fields) {
74814 var field = preset.fields[f];
74815 if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
74816 tags[field.key] = field.default;
74827 function presetIndex() {
74828 // a presetCollection with methods for
74829 // loading new data and returning defaults
74831 var all = presetCollection([]),
74832 defaults = { area: all, line: all, point: all, vertex: all, relation: all },
74835 recent = presetCollection([]);
74837 // Index of presets by (geometry, tag key).
74846 all.match = function(entity, resolver) {
74847 var geometry = entity.geometry(resolver);
74849 // Treat entities on addr:interpolation lines as points, not vertices (#3241)
74850 if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
74851 geometry = 'point';
74854 var geometryMatches = index[geometry],
74858 for (var k in entity.tags) {
74859 var keyMatches = geometryMatches[k];
74860 if (!keyMatches) continue;
74862 for (var i = 0; i < keyMatches.length; i++) {
74863 var score = keyMatches[i].matchScore(entity);
74864 if (score > best) {
74866 match = keyMatches[i];
74871 return match || all.item(geometry);
74875 // Because of the open nature of tagging, iD will never have a complete
74876 // list of tags used in OSM, so we want it to have logic like "assume
74877 // that a closed way with an amenity tag is an area, unless the amenity
74878 // is one of these specific types". This function computes a structure
74879 // that allows testing of such conditions, based on the presets designated
74880 // as as supporting (or not supporting) the area geometry.
74882 // The returned object L is a whitelist/blacklist of tags. A closed way
74883 // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
74884 // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
74885 // and the subkeys form the blacklist.
74886 all.areaKeys = function() {
74888 ignore = ['barrier', 'highway', 'footway', 'railway', 'type'], // probably a line..
74889 presets = lodash.reject(all.collection, 'suggestion');
74892 presets.forEach(function(d) {
74893 for (var key in d.tags) break;
74895 if (ignore.indexOf(key) !== -1) return;
74897 if (d.geometry.indexOf('area') !== -1) { // probably an area..
74898 areaKeys[key] = areaKeys[key] || {};
74903 presets.forEach(function(d) {
74904 for (var key in d.tags) break;
74906 if (ignore.indexOf(key) !== -1) return;
74908 var value = d.tags[key];
74909 if (key in areaKeys && // probably an area...
74910 d.geometry.indexOf('line') !== -1 && // but sometimes a line
74912 areaKeys[key][value] = true;
74920 all.init = function() {
74921 var d = data.presets;
74923 all.collection = [];
74924 recent.collection = [];
74927 index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
74930 lodash.forEach(d.fields, function(d, id) {
74931 fields[id] = presetField(id, d);
74932 if (d.universal) universal.push(fields[id]);
74937 lodash.forEach(d.presets, function(d, id) {
74938 all.collection.push(presetPreset(id, d, fields));
74942 if (d.categories) {
74943 lodash.forEach(d.categories, function(d, id) {
74944 all.collection.push(presetCategory(id, d, all));
74949 var getItem = lodash.bind(all.item, all);
74951 area: presetCollection(d.defaults.area.map(getItem)),
74952 line: presetCollection(d.defaults.line.map(getItem)),
74953 point: presetCollection(d.defaults.point.map(getItem)),
74954 vertex: presetCollection(d.defaults.vertex.map(getItem)),
74955 relation: presetCollection(d.defaults.relation.map(getItem))
74959 for (var i = 0; i < all.collection.length; i++) {
74960 var preset = all.collection[i],
74961 geometry = preset.geometry;
74963 for (var j = 0; j < geometry.length; j++) {
74964 var g = index[geometry[j]];
74965 for (var k in preset.tags) {
74966 (g[k] = g[k] || []).push(preset);
74974 all.field = function(id) {
74978 all.universal = function() {
74982 all.defaults = function(geometry, n) {
74983 var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
74984 def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
74985 return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
74988 all.choose = function(preset) {
74989 if (!preset.isFallback()) {
74990 recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
75000 function setAreaKeys(value) {
75005 function coreContext() {
75007 context.version = '2.3.1';
75009 // create a special translation that contains the keys in place of the strings
75010 var tkeys = lodash.cloneDeep(en);
75013 function traverser(v, k, obj) {
75015 if (lodash.isObject(v)) {
75016 lodash.forOwn(v, traverser);
75017 } else if (lodash.isString(v)) {
75018 obj[k] = parents.join('.');
75023 lodash.forOwn(tkeys, traverser);
75024 addTranslation('_tkeys_', tkeys);
75026 addTranslation('en', en);
75029 var dispatch$$1 = dispatch('enter', 'exit', 'change');
75031 // https://github.com/openstreetmap/iD/issues/772
75032 // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
75034 try { storage = localStorage; } catch (e) {} // eslint-disable-line no-empty
75035 storage = storage || (function() {
75038 getItem: function(k) { return s[k]; },
75039 setItem: function(k, v) { s[k] = v; },
75040 removeItem: function(k) { delete s[k]; }
75044 context.storage = function(k, v) {
75046 if (arguments.length === 1) return storage.getItem(k);
75047 else if (v === null) storage.removeItem(k);
75048 else storage.setItem(k, v);
75050 // localstorage quota exceeded
75051 /* eslint-disable no-console */
75052 if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
75053 /* eslint-enable no-console */
75058 /* Straight accessors. Avoid using these if you can. */
75059 var ui, connection, history;
75060 context.ui = function() { return ui; };
75061 context.connection = function() { return connection; };
75062 context.history = function() { return history; };
75066 function entitiesLoaded(err, result) {
75067 if (!err) history.merge(result.data, result.extent);
75070 context.preauth = function(options) {
75071 connection.switch(options);
75075 context.loadTiles = function(projection$$1, dimensions, callback) {
75076 function done(err, result) {
75077 entitiesLoaded(err, result);
75078 if (callback) callback(err, result);
75080 connection.loadTiles(projection$$1, dimensions, done);
75083 context.loadEntity = function(id, callback) {
75084 function done(err, result) {
75085 entitiesLoaded(err, result);
75086 if (callback) callback(err, result);
75088 connection.loadEntity(id, done);
75091 context.zoomToEntity = function(id, zoomTo) {
75092 if (zoomTo !== false) {
75093 this.loadEntity(id, function(err, result) {
75095 var entity = lodash.find(result.data, function(e) { return e.id === id; });
75096 if (entity) { map.zoomTo(entity); }
75100 map.on('drawn.zoomToEntity', function() {
75101 if (!context.hasEntity(id)) return;
75102 map.on('drawn.zoomToEntity', null);
75103 context.on('enter.zoomToEntity', null);
75104 context.enter(modeSelect(context, [id]));
75107 context.on('enter.zoomToEntity', function() {
75108 if (mode.id !== 'browse') {
75109 map.on('drawn.zoomToEntity', null);
75110 context.on('enter.zoomToEntity', null);
75115 var minEditableZoom = 16;
75116 context.minEditableZoom = function(_) {
75117 if (!arguments.length) return minEditableZoom;
75118 minEditableZoom = _;
75119 connection.tileZoom(_);
75125 var inIntro = false;
75126 context.inIntro = function(_) {
75127 if (!arguments.length) return inIntro;
75132 context.save = function() {
75133 // no history save, no message onbeforeunload
75134 if (inIntro || select('.modal').size()) return;
75137 if (mode && mode.id === 'save') {
75140 canSave = context.selectedIDs().every(function(id) {
75141 var entity = context.hasEntity(id);
75142 return entity && !entity.isDegenerate();
75149 if (history.hasChanges()) {
75150 return t('save.unsaved_changes');
75156 context.hasEntity = function(id) {
75157 return history.graph().hasEntity(id);
75159 context.entity = function(id) {
75160 return history.graph().entity(id);
75162 context.childNodes = function(way) {
75163 return history.graph().childNodes(way);
75165 context.geometry = function(id) {
75166 return context.entity(id).geometry(history.graph());
75172 context.mode = function() {
75175 context.enter = function(newMode) {
75178 dispatch$$1.call('exit', this, mode);
75183 dispatch$$1.call('enter', this, mode);
75186 context.selectedIDs = function() {
75187 if (mode && mode.selectedIDs) {
75188 return mode.selectedIDs();
75196 context.install = function(behavior) {
75197 context.surface().call(behavior);
75199 context.uninstall = function(behavior) {
75200 context.surface().call(behavior.off);
75205 var copyIDs = [], copyGraph;
75206 context.copyGraph = function() { return copyGraph; };
75207 context.copyIDs = function(_) {
75208 if (!arguments.length) return copyIDs;
75210 copyGraph = history.graph();
75217 context.background = function() { return background; };
75222 context.features = function() { return features; };
75223 context.hasHiddenConnections = function(id) {
75224 var graph = history.graph(),
75225 entity = graph.entity(id);
75226 return features.hasHiddenConnections(entity, graph);
75232 context.presets = function() { return presets; };
75237 context.map = function() { return map; };
75238 context.layers = function() { return map.layers; };
75239 context.surface = function() { return map.surface; };
75240 context.editable = function() { return map.editable(); };
75241 context.surfaceRect = function() {
75242 return map.surface.node().getBoundingClientRect();
75254 context.debugFlags = function() {
75257 context.setDebug = function(flag, val) {
75258 if (arguments.length === 1) val = true;
75259 debugFlags[flag] = val;
75260 dispatch$$1.call('change');
75263 context.getDebug = function(flag) {
75264 return flag && debugFlags[flag];
75269 var container = select(document.body);
75270 context.container = function(_) {
75271 if (!arguments.length) return container;
75273 container.classed('id-container', true);
75277 context.embed = function(_) {
75278 if (!arguments.length) return embed;
75285 var assetPath = '';
75286 context.assetPath = function(_) {
75287 if (!arguments.length) return assetPath;
75293 context.assetMap = function(_) {
75294 if (!arguments.length) return assetMap;
75299 context.asset = function(_) {
75300 var filename = assetPath + _;
75301 return assetMap[filename] || filename;
75304 context.imagePath = function(_) {
75305 return context.asset('img/' + _);
75310 // `locale` variable contains a "requested locale".
75311 // It won't become the `currentLocale` until after loadLocale() is called.
75312 var locale, localePath;
75314 context.locale = function(loc, path$$1) {
75315 if (!arguments.length) return currentLocale;
75317 localePath = path$$1;
75321 context.loadLocale = function(callback) {
75322 if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) {
75323 localePath = localePath || context.asset('locales/' + locale + '.json');
75324 json(localePath, function(err, result) {
75326 addTranslation(locale, result[locale]);
75346 /* reset (aka flush) */
75347 context.reset = context.flush = function() {
75348 context.debouncedSave.cancel();
75349 lodash.each(services, function(service) {
75350 if (service && typeof service.reset === 'function') {
75351 service.reset(context);
75362 context.projection = geoRawMercator();
75363 context.curtainProjection = geoRawMercator();
75365 locale = utilDetect().locale;
75366 if (locale && !dataLocales.hasOwnProperty(locale)) {
75367 locale = locale.split('-')[0];
75370 history = coreHistory(context);
75371 context.graph = history.graph;
75372 context.changes = history.changes;
75373 context.intersects = history.intersects;
75375 // Debounce save, since it's a synchronous localStorage write,
75376 // and history changes can happen frequently (e.g. when dragging).
75377 context.debouncedSave = lodash.debounce(context.save, 350);
75378 function withDebouncedSave(fn) {
75379 return function() {
75380 var result = fn.apply(history, arguments);
75381 context.debouncedSave();
75386 context.perform = withDebouncedSave(history.perform);
75387 context.replace = withDebouncedSave(history.replace);
75388 context.pop = withDebouncedSave(history.pop);
75389 context.overwrite = withDebouncedSave(history.overwrite);
75390 context.undo = withDebouncedSave(history.undo);
75391 context.redo = withDebouncedSave(history.redo);
75393 ui = uiInit(context);
75395 connection = services.osm;
75396 background = rendererBackground(context);
75397 features = rendererFeatures(context);
75398 presets = presetIndex();
75400 map = rendererMap(context);
75401 context.mouse = map.mouse;
75402 context.extent = map.extent;
75403 context.pan = map.pan;
75404 context.zoomIn = map.zoomIn;
75405 context.zoomOut = map.zoomOut;
75406 context.zoomInFurther = map.zoomInFurther;
75407 context.zoomOutFurther = map.zoomOutFurther;
75408 context.redrawEnable = map.redrawEnable;
75410 lodash.each(services, function(service) {
75411 if (service && typeof service.init === 'function') {
75412 service.init(context);
75418 areaKeys = presets.areaKeys();
75421 return utilRebind(context, dispatch$$1, 'on');
75424 function osmWay() {
75425 if (!(this instanceof osmWay)) {
75426 return (new osmWay()).initialize(arguments);
75427 } else if (arguments.length) {
75428 this.initialize(arguments);
75433 osmEntity$$1.way = osmWay;
75435 osmWay.prototype = Object.create(osmEntity$$1.prototype);
75438 lodash.extend(osmWay.prototype, {
75443 copy: function(resolver, copies) {
75444 if (copies[this.id])
75445 return copies[this.id];
75447 var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
75449 var nodes = this.nodes.map(function(id) {
75450 return resolver.entity(id).copy(resolver, copies).id;
75453 copy = copy.update({ nodes: nodes });
75454 copies[this.id] = copy;
75460 extent: function(resolver) {
75461 return resolver.transient(this, 'extent', function() {
75462 var extent$$1 = geoExtent$$1();
75463 for (var i = 0; i < this.nodes.length; i++) {
75464 var node = resolver.hasEntity(this.nodes[i]);
75466 extent$$1._extend(node.extent());
75474 first: function() {
75475 return this.nodes[0];
75480 return this.nodes[this.nodes.length - 1];
75484 contains: function(node) {
75485 return this.nodes.indexOf(node) >= 0;
75489 affix: function(node) {
75490 if (this.nodes[0] === node) return 'prefix';
75491 if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
75495 layer: function() {
75496 // explicit layer tag, clamp between -10, 10..
75497 if (isFinite(this.tags.layer)) {
75498 return Math.max(-10, Math.min(+(this.tags.layer), 10));
75501 // implied layer tag..
75502 if (this.tags.location === 'overground') return 1;
75503 if (this.tags.location === 'underground') return -1;
75504 if (this.tags.location === 'underwater') return -10;
75506 if (this.tags.power === 'line') return 10;
75507 if (this.tags.power === 'minor_line') return 10;
75508 if (this.tags.aerialway) return 10;
75509 if (this.tags.bridge) return 1;
75510 if (this.tags.cutting) return -1;
75511 if (this.tags.tunnel) return -1;
75512 if (this.tags.waterway) return -1;
75513 if (this.tags.man_made === 'pipeline') return -10;
75514 if (this.tags.boundary) return -10;
75519 isOneWay: function() {
75520 // explicit oneway tag..
75521 if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
75522 if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
75524 // implied oneway tag..
75525 for (var key in this.tags) {
75526 if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
75533 lanes: function() {
75534 return osmLanes(this);
75538 isClosed: function() {
75539 return this.nodes.length > 1 && this.first() === this.last();
75543 isConvex: function(resolver) {
75544 if (!this.isClosed() || this.isDegenerate()) return null;
75546 var nodes = lodash.uniq(resolver.childNodes(this)),
75547 coords = lodash.map(nodes, 'loc'),
75548 curr = 0, prev = 0;
75550 for (var i = 0; i < coords.length; i++) {
75551 var o = coords[(i+1) % coords.length],
75553 b = coords[(i+2) % coords.length],
75554 res = geoCross(o, a, b);
75556 curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
75559 } else if (prev && curr !== prev) {
75568 isArea: function() {
75569 if (this.tags.area === 'yes')
75571 if (!this.isClosed() || this.tags.area === 'no')
75573 for (var key in this.tags) {
75574 if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
75582 isDegenerate: function() {
75583 return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
75587 areAdjacent: function(n1, n2) {
75588 for (var i = 0; i < this.nodes.length; i++) {
75589 if (this.nodes[i] === n1) {
75590 if (this.nodes[i - 1] === n2) return true;
75591 if (this.nodes[i + 1] === n2) return true;
75598 geometry: function(graph) {
75599 return graph.transient(this, 'geometry', function() {
75600 return this.isArea() ? 'area' : 'line';
75605 // If this way is not closed, append the beginning node to the end of the nodelist to close it.
75606 close: function() {
75607 if (this.isClosed() || !this.nodes.length) return this;
75609 var nodes = this.nodes.slice();
75610 nodes = nodes.filter(noRepeatNodes);
75611 nodes.push(nodes[0]);
75612 return this.update({ nodes: nodes });
75616 // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
75617 unclose: function() {
75618 if (!this.isClosed()) return this;
75620 var nodes = this.nodes.slice(),
75621 connector = this.first(),
75622 i = nodes.length - 1;
75624 // remove trailing connectors..
75625 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
75626 nodes.splice(i, 1);
75627 i = nodes.length - 1;
75630 nodes = nodes.filter(noRepeatNodes);
75631 return this.update({ nodes: nodes });
75635 // Adds a node (id) in front of the node which is currently at position index.
75636 // If index is undefined, the node will be added to the end of the way for linear ways,
75637 // or just before the final connecting node for circular ways.
75638 // Consecutive duplicates are eliminated including existing ones.
75639 // Circularity is always preserved when adding a node.
75640 addNode: function(id, index) {
75641 var nodes = this.nodes.slice(),
75642 isClosed = this.isClosed(),
75643 max$$1 = isClosed ? nodes.length - 1 : nodes.length;
75645 if (index === undefined) {
75649 if (index < 0 || index > max$$1) {
75650 throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
75653 // If this is a closed way, remove all connector nodes except the first one
75654 // (there may be duplicates) and adjust index if necessary..
75656 var connector = this.first();
75658 // leading connectors..
75660 while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
75661 nodes.splice(i, 1);
75662 if (index > i) index--;
75665 // trailing connectors..
75666 i = nodes.length - 1;
75667 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
75668 nodes.splice(i, 1);
75669 if (index > i) index--;
75670 i = nodes.length - 1;
75674 nodes.splice(index, 0, id);
75675 nodes = nodes.filter(noRepeatNodes);
75677 // If the way was closed before, append a connector node to keep it closed..
75678 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
75679 nodes.push(nodes[0]);
75682 return this.update({ nodes: nodes });
75686 // Replaces the node which is currently at position index with the given node (id).
75687 // Consecutive duplicates are eliminated including existing ones.
75688 // Circularity is preserved when updating a node.
75689 updateNode: function(id, index) {
75690 var nodes = this.nodes.slice(),
75691 isClosed = this.isClosed(),
75692 max$$1 = nodes.length - 1;
75694 if (index === undefined || index < 0 || index > max$$1) {
75695 throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
75698 // If this is a closed way, remove all connector nodes except the first one
75699 // (there may be duplicates) and adjust index if necessary..
75701 var connector = this.first();
75703 // leading connectors..
75705 while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
75706 nodes.splice(i, 1);
75707 if (index > i) index--;
75710 // trailing connectors..
75711 i = nodes.length - 1;
75712 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
75713 nodes.splice(i, 1);
75714 if (index === i) index = 0; // update leading connector instead
75715 i = nodes.length - 1;
75719 nodes.splice(index, 1, id);
75720 nodes = nodes.filter(noRepeatNodes);
75722 // If the way was closed before, append a connector node to keep it closed..
75723 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
75724 nodes.push(nodes[0]);
75727 return this.update({nodes: nodes});
75731 // Replaces each occurrence of node id needle with replacement.
75732 // Consecutive duplicates are eliminated including existing ones.
75733 // Circularity is preserved.
75734 replaceNode: function(needle, replacement) {
75735 var nodes = this.nodes.slice(),
75736 isClosed = this.isClosed();
75738 for (var i = 0; i < nodes.length; i++) {
75739 if (nodes[i] === needle) {
75740 nodes[i] = replacement;
75744 nodes = nodes.filter(noRepeatNodes);
75746 // If the way was closed before, append a connector node to keep it closed..
75747 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
75748 nodes.push(nodes[0]);
75751 return this.update({nodes: nodes});
75755 // Removes each occurrence of node id needle with replacement.
75756 // Consecutive duplicates are eliminated including existing ones.
75757 // Circularity is preserved.
75758 removeNode: function(id) {
75759 var nodes = this.nodes.slice(),
75760 isClosed = this.isClosed();
75763 .filter(function(node) { return node !== id; })
75764 .filter(noRepeatNodes);
75766 // If the way was closed before, append a connector node to keep it closed..
75767 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
75768 nodes.push(nodes[0]);
75771 return this.update({nodes: nodes});
75775 asJXON: function(changeset_id) {
75778 '@id': this.osmId(),
75779 '@version': this.version || 0,
75780 nd: lodash.map(this.nodes, function(id) {
75781 return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
75783 tag: lodash.map(this.tags, function(v, k) {
75784 return { keyAttributes: { k: k, v: v } };
75788 if (changeset_id) {
75789 r.way['@changeset'] = changeset_id;
75795 asGeoJSON: function(resolver) {
75796 return resolver.transient(this, 'GeoJSON', function() {
75797 var coordinates = lodash.map(resolver.childNodes(this), 'loc');
75798 if (this.isArea() && this.isClosed()) {
75801 coordinates: [coordinates]
75805 type: 'LineString',
75806 coordinates: coordinates
75813 area: function(resolver) {
75814 return resolver.transient(this, 'area', function() {
75815 var nodes = resolver.childNodes(this);
75819 coordinates: [lodash.map(nodes, 'loc')]
75822 if (!this.isClosed() && nodes.length) {
75823 json$$1.coordinates[0].push(nodes[0].loc);
75826 var area$$1 = area(json$$1);
75828 // Heuristic for detecting counterclockwise winding order. Assumes
75829 // that OpenStreetMap polygons are not hemisphere-spanning.
75830 if (area$$1 > 2 * Math.PI) {
75831 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
75832 area$$1 = area(json$$1);
75835 return isNaN(area$$1) ? 0 : area$$1;
75841 // Filter function to eliminate consecutive duplicates.
75842 function noRepeatNodes(node, i, arr) {
75843 return i === 0 || node !== arr[i - 1];
75846 function osmTurn(turn) {
75847 if (!(this instanceof osmTurn))
75848 return new osmTurn(turn);
75849 lodash.extend(this, turn);
75853 function osmIntersection(graph, vertexId) {
75854 var vertex = graph.entity(vertexId),
75855 parentWays = graph.parentWays(vertex),
75859 function addHighway(way, adjacentNodeId) {
75860 if (highways[adjacentNodeId]) {
75861 coincident.push(adjacentNodeId);
75863 highways[adjacentNodeId] = way;
75867 // Pre-split ways that would need to be split in
75868 // order to add a restriction. The real split will
75869 // happen when the restriction is added.
75870 parentWays.forEach(function(way) {
75871 if (!way.tags.highway || way.isArea() || way.isDegenerate())
75874 var isFirst = (vertexId === way.first()),
75875 isLast = (vertexId === way.last()),
75876 isAffix = (isFirst || isLast),
75877 isClosingNode = (isFirst && isLast);
75879 if (isAffix && !isClosingNode) {
75880 var index = (isFirst ? 1 : way.nodes.length - 2);
75881 addHighway(way, way.nodes[index]);
75884 var splitIndex, wayA, wayB, indexA, indexB;
75885 if (isClosingNode) {
75886 splitIndex = Math.ceil(way.nodes.length / 2); // split at midpoint
75887 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
75888 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
75890 indexB = way.nodes.length - 2;
75892 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1); // split at vertexid
75893 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
75894 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
75895 indexA = splitIndex - 1;
75896 indexB = splitIndex + 1;
75898 graph = graph.replace(wayA).replace(wayB);
75899 addHighway(wayA, way.nodes[indexA]);
75900 addHighway(wayB, way.nodes[indexB]);
75904 // remove any ways from this intersection that are coincident
75905 // (i.e. any adjacent node used by more than one intersecting way)
75906 coincident.forEach(function (n) {
75907 delete highways[n];
75911 var intersection = {
75912 highways: highways,
75913 ways: lodash.values(highways),
75918 intersection.adjacentNodeId = function(fromWayId) {
75919 return lodash.find(lodash.keys(highways), function(k) {
75920 return highways[k].id === fromWayId;
75925 intersection.turns = function(fromNodeId) {
75926 var start = highways[fromNodeId];
75930 if (start.first() === vertex.id && start.tags.oneway === 'yes')
75932 if (start.last() === vertex.id && start.tags.oneway === '-1')
75935 function withRestriction(turn) {
75936 graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
75937 if (relation.tags.type !== 'restriction')
75940 var f = relation.memberByRole('from'),
75941 t = relation.memberByRole('to'),
75942 v = relation.memberByRole('via');
75944 if (f && f.id === turn.from.way &&
75945 v && v.id === turn.via.node &&
75946 t && t.id === turn.to.way) {
75947 turn.restriction = relation.id;
75948 } else if (/^only_/.test(relation.tags.restriction) &&
75949 f && f.id === turn.from.way &&
75950 v && v.id === turn.via.node &&
75951 t && t.id !== turn.to.way) {
75952 turn.restriction = relation.id;
75953 turn.indirect_restriction = true;
75957 return osmTurn(turn);
75963 way: start.id.split(/-(a|b)/)[0]
75965 via = { node: vertex.id },
75968 lodash.each(highways, function(end, adjacentNodeId) {
75973 if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
75974 turns.push(withRestriction({
75978 node: adjacentNodeId,
75979 way: end.id.split(/-(a|b)/)[0]
75985 if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
75986 turns.push(withRestriction({
75990 node: adjacentNodeId,
75991 way: end.id.split(/-(a|b)/)[0]
75999 if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
76000 turns.push(withRestriction({
76011 return intersection;
76015 function osmInferRestriction(graph, from, via, to, projection) {
76016 var fromWay = graph.entity(from.way),
76017 fromNode = graph.entity(from.node),
76018 toWay = graph.entity(to.way),
76019 toNode = graph.entity(to.node),
76020 viaNode = graph.entity(via.node),
76021 fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
76022 (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
76023 toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
76024 (toWay.tags.oneway === '-1' && toWay.last() === via.node),
76025 angle = geoAngle(viaNode, fromNode, projection) -
76026 geoAngle(viaNode, toNode, projection);
76028 angle = angle * 180 / Math.PI;
76033 if (fromNode === toNode)
76034 return 'no_u_turn';
76035 if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
76036 return 'no_u_turn';
76038 return 'no_right_turn';
76040 return 'no_left_turn';
76042 return 'no_straight_on';
76045 function actionAddMember(relationId, member, memberIndex) {
76046 return function(graph) {
76047 var relation = graph.entity(relationId);
76049 if (isNaN(memberIndex) && member.type === 'way') {
76050 var members = relation.indexedMembers();
76051 members.push(member);
76053 var joined = osmJoinWays(members, graph);
76054 for (var i = 0; i < joined.length; i++) {
76055 var segment = joined[i];
76056 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
76057 if (segment[j] !== member)
76061 memberIndex = segment[j + 1].index;
76062 } else if (j === segment.length - 1) {
76063 memberIndex = segment[j - 1].index + 1;
76065 memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
76071 return graph.replace(relation.addMember(member, memberIndex));
76075 function actionAddMidpoint(midpoint, node) {
76076 return function(graph) {
76077 graph = graph.replace(node.move(midpoint.loc));
76079 var parents = lodash.intersection(
76080 graph.parentWays(graph.entity(midpoint.edge[0])),
76081 graph.parentWays(graph.entity(midpoint.edge[1])));
76083 parents.forEach(function(way) {
76084 for (var i = 0; i < way.nodes.length - 1; i++) {
76085 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
76086 graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
76088 // Add only one midpoint on doubled-back segments,
76089 // turning them into self-intersections.
76099 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
76100 function actionAddVertex(wayId, nodeId, index) {
76101 return function(graph) {
76102 return graph.replace(graph.entity(wayId).addNode(nodeId, index));
76106 function actionChangeMember(relationId, member, memberIndex) {
76107 return function(graph) {
76108 return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
76112 function actionChangePreset(entityId, oldPreset, newPreset) {
76113 return function(graph) {
76114 var entity = graph.entity(entityId),
76115 geometry = entity.geometry(graph),
76116 tags = entity.tags;
76118 if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
76119 if (newPreset) tags = newPreset.applyTags(tags, geometry);
76121 return graph.replace(entity.update({tags: tags}));
76125 function actionChangeTags(entityId, tags) {
76126 return function(graph) {
76127 var entity = graph.entity(entityId);
76128 return graph.replace(entity.update({tags: tags}));
76132 function actionCircularize(wayId, projection$$1, maxAngle) {
76133 maxAngle = (maxAngle || 20) * Math.PI / 180;
76136 var action = function(graph, t) {
76137 if (t === null || !isFinite(t)) t = 1;
76138 t = Math.min(Math.max(+t, 0), 1);
76140 var way = graph.entity(wayId),
76143 graph.childNodes(way).forEach(function(node) {
76144 if (!origNodes[node.id]) origNodes[node.id] = node;
76147 if (!way.isConvex(graph)) {
76148 graph = action.makeConvex(graph);
76151 var nodes = lodash.uniq(graph.childNodes(way)),
76152 keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
76153 points = nodes.map(function(n) { return projection$$1(n.loc); }),
76154 keyPoints = keyNodes.map(function(n) { return projection$$1(n.loc); }),
76155 centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
76156 radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
76157 sign = d3polygonArea(points) > 0 ? 1 : -1,
76160 // we need atleast two key nodes for the algorithm to work
76161 if (!keyNodes.length) {
76162 keyNodes = [nodes[0]];
76163 keyPoints = [points[0]];
76166 if (keyNodes.length === 1) {
76167 var index = nodes.indexOf(keyNodes[0]),
76168 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
76170 keyNodes.push(nodes[oppositeIndex]);
76171 keyPoints.push(points[oppositeIndex]);
76174 // key points and nodes are those connected to the ways,
76175 // they are projected onto the circle, inbetween nodes are moved
76176 // to constant intervals between key nodes, extra inbetween nodes are
76177 // added if necessary.
76178 for (var i = 0; i < keyPoints.length; i++) {
76179 var nextKeyNodeIndex = (i + 1) % keyNodes.length,
76180 startNode = keyNodes[i],
76181 endNode = keyNodes[nextKeyNodeIndex],
76182 startNodeIndex = nodes.indexOf(startNode),
76183 endNodeIndex = nodes.indexOf(endNode),
76184 numberNewPoints = -1,
76185 indexRange = endNodeIndex - startNodeIndex,
76187 inBetweenNodes = [],
76188 startAngle, endAngle, totalAngle, eachAngle,
76189 angle, loc, node, origNode, j;
76191 if (indexRange < 0) {
76192 indexRange += nodes.length;
76195 // position this key node
76196 var distance$$1 = geoEuclideanDistance(centroid, keyPoints[i]);
76197 if (distance$$1 === 0) { distance$$1 = 1e-4; }
76199 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance$$1 * radius,
76200 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance$$1 * radius
76202 loc = projection$$1.invert(keyPoints[i]);
76203 node = keyNodes[i];
76204 origNode = origNodes[node.id];
76205 node = node.move(geoInterp(origNode.loc, loc, t));
76206 graph = graph.replace(node);
76208 // figure out the between delta angle we want to match to
76209 startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
76210 endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
76211 totalAngle = endAngle - startAngle;
76213 // detects looping around -pi/pi
76214 if (totalAngle * sign > 0) {
76215 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
76220 eachAngle = totalAngle / (indexRange + numberNewPoints);
76221 } while (Math.abs(eachAngle) > maxAngle);
76224 // move existing nodes
76225 for (j = 1; j < indexRange; j++) {
76226 angle = startAngle + j * eachAngle;
76227 loc = projection$$1.invert([
76228 centroid[0] + Math.cos(angle) * radius,
76229 centroid[1] + Math.sin(angle) * radius
76232 node = nodes[(j + startNodeIndex) % nodes.length];
76233 origNode = origNodes[node.id];
76234 nearNodes[node.id] = angle;
76236 node = node.move(geoInterp(origNode.loc, loc, t));
76237 graph = graph.replace(node);
76240 // add new inbetween nodes if necessary
76241 for (j = 0; j < numberNewPoints; j++) {
76242 angle = startAngle + (indexRange + j) * eachAngle;
76243 loc = projection$$1.invert([
76244 centroid[0] + Math.cos(angle) * radius,
76245 centroid[1] + Math.sin(angle) * radius
76248 // choose a nearnode to use as the original
76249 var min$$1 = Infinity;
76250 for (var nodeId in nearNodes) {
76251 var nearAngle = nearNodes[nodeId],
76252 dist = Math.abs(nearAngle - angle);
76253 if (dist < min$$1) {
76255 origNode = origNodes[nodeId];
76259 node = osmNode({ loc: geoInterp(origNode.loc, loc, t) });
76260 graph = graph.replace(node);
76262 nodes.splice(endNodeIndex + j, 0, node);
76263 inBetweenNodes.push(node.id);
76266 // Check for other ways that share these keyNodes..
76267 // If keyNodes are adjacent in both ways,
76268 // we can add inBetween nodes to that shared way too..
76269 if (indexRange === 1 && inBetweenNodes.length) {
76270 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
76271 endIndex1 = way.nodes.lastIndexOf(endNode.id),
76272 wayDirection1 = (endIndex1 - startIndex1);
76273 if (wayDirection1 < -1) { wayDirection1 = 1; }
76275 /* eslint-disable no-loop-func */
76276 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
76277 if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
76278 var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
76279 endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
76280 wayDirection2 = (endIndex2 - startIndex2),
76281 insertAt = endIndex2;
76282 if (wayDirection2 < -1) { wayDirection2 = 1; }
76284 if (wayDirection1 !== wayDirection2) {
76285 inBetweenNodes.reverse();
76286 insertAt = startIndex2;
76288 for (j = 0; j < inBetweenNodes.length; j++) {
76289 sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
76291 graph = graph.replace(sharedWay);
76294 /* eslint-enable no-loop-func */
76299 // update the way to have all the new nodes
76300 ids = nodes.map(function(n) { return n.id; });
76303 way = way.update({nodes: ids});
76304 graph = graph.replace(way);
76310 action.makeConvex = function(graph) {
76311 var way = graph.entity(wayId),
76312 nodes = lodash.uniq(graph.childNodes(way)),
76313 points = nodes.map(function(n) { return projection$$1(n.loc); }),
76314 sign = d3polygonArea(points) > 0 ? 1 : -1,
76315 hull = d3polygonHull(points);
76317 // D3 convex hulls go counterclockwise..
76323 for (var i = 0; i < hull.length - 1; i++) {
76324 var startIndex = points.indexOf(hull[i]),
76325 endIndex = points.indexOf(hull[i+1]),
76326 indexRange = (endIndex - startIndex);
76328 if (indexRange < 0) {
76329 indexRange += nodes.length;
76332 // move interior nodes to the surface of the convex hull..
76333 for (var j = 1; j < indexRange; j++) {
76334 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
76335 node = nodes[(j + startIndex) % nodes.length].move(projection$$1.invert(point));
76336 graph = graph.replace(node);
76343 action.disabled = function(graph) {
76344 if (!graph.entity(wayId).isClosed())
76345 return 'not_closed';
76349 action.transitionable = true;
76355 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
76356 function actionDeleteWay(wayId) {
76359 function canDeleteNode(node, graph) {
76360 return !graph.parentWays(node).length &&
76361 !graph.parentRelations(node).length &&
76362 !node.hasInterestingTags();
76366 var action = function(graph) {
76367 var way = graph.entity(wayId);
76369 graph.parentRelations(way)
76370 .forEach(function(parent) {
76371 parent = parent.removeMembersWithID(wayId);
76372 graph = graph.replace(parent);
76374 if (parent.isDegenerate()) {
76375 graph = actionDeleteRelation(parent.id)(graph);
76379 lodash.uniq(way.nodes).forEach(function(nodeId) {
76380 graph = graph.replace(way.removeNode(nodeId));
76382 var node = graph.entity(nodeId);
76383 if (canDeleteNode(node, graph)) {
76384 graph = graph.remove(node);
76388 return graph.remove(way);
76395 function actionDeleteMultiple(ids) {
76397 way: actionDeleteWay,
76398 node: actionDeleteNode,
76399 relation: actionDeleteRelation
76403 var action = function(graph) {
76404 ids.forEach(function(id) {
76405 if (graph.hasEntity(id)) { // It may have been deleted aready.
76406 graph = actions[graph.entity(id).type](id)(graph);
76417 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
76418 function actionDeleteRelation(relationId) {
76421 function canDeleteEntity(entity, graph) {
76422 return !graph.parentWays(entity).length &&
76423 !graph.parentRelations(entity).length &&
76424 !entity.hasInterestingTags();
76428 var action = function(graph) {
76429 var relation = graph.entity(relationId);
76431 graph.parentRelations(relation)
76432 .forEach(function(parent) {
76433 parent = parent.removeMembersWithID(relationId);
76434 graph = graph.replace(parent);
76436 if (parent.isDegenerate()) {
76437 graph = actionDeleteRelation(parent.id)(graph);
76441 lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
76442 graph = graph.replace(relation.removeMembersWithID(memberId));
76444 var entity = graph.entity(memberId);
76445 if (canDeleteEntity(entity, graph)) {
76446 graph = actionDeleteMultiple([memberId])(graph);
76450 return graph.remove(relation);
76457 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
76458 function actionDeleteNode(nodeId) {
76459 var action = function(graph) {
76460 var node = graph.entity(nodeId);
76462 graph.parentWays(node)
76463 .forEach(function(parent) {
76464 parent = parent.removeNode(nodeId);
76465 graph = graph.replace(parent);
76467 if (parent.isDegenerate()) {
76468 graph = actionDeleteWay(parent.id)(graph);
76472 graph.parentRelations(node)
76473 .forEach(function(parent) {
76474 parent = parent.removeMembersWithID(nodeId);
76475 graph = graph.replace(parent);
76477 if (parent.isDegenerate()) {
76478 graph = actionDeleteRelation(parent.id)(graph);
76482 return graph.remove(node);
76489 // Connect the ways at the given nodes.
76491 // The last node will survive. All other nodes will be replaced with
76492 // the surviving node in parent ways, and then removed.
76494 // Tags and relation memberships of of non-surviving nodes are merged
76495 // to the survivor.
76497 // This is the inverse of `iD.actionDisconnect`.
76500 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
76501 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
76503 function actionConnect(nodeIds) {
76504 return function(graph) {
76505 var survivor = graph.entity(lodash.last(nodeIds));
76507 for (var i = 0; i < nodeIds.length - 1; i++) {
76508 var node = graph.entity(nodeIds[i]);
76510 /* eslint-disable no-loop-func */
76511 graph.parentWays(node).forEach(function(parent) {
76512 if (!parent.areAdjacent(node.id, survivor.id)) {
76513 graph = graph.replace(parent.replaceNode(node.id, survivor.id));
76517 graph.parentRelations(node).forEach(function(parent) {
76518 graph = graph.replace(parent.replaceMember(node, survivor));
76520 /* eslint-enable no-loop-func */
76522 survivor = survivor.mergeTags(node.tags);
76523 graph = actionDeleteNode(node.id)(graph);
76526 graph = graph.replace(survivor);
76532 function actionCopyEntities(ids, fromGraph) {
76536 var action = function(graph) {
76537 ids.forEach(function(id) {
76538 fromGraph.entity(id).copy(fromGraph, copies);
76541 for (var id in copies) {
76542 graph = graph.replace(copies[id]);
76549 action.copies = function() {
76557 function actionDeleteMember(relationId, memberIndex) {
76558 return function(graph) {
76559 var relation = graph.entity(relationId)
76560 .removeMember(memberIndex);
76562 graph = graph.replace(relation);
76564 if (relation.isDegenerate())
76565 graph = actionDeleteRelation(relation.id)(graph);
76571 function actionDeprecateTags(entityId) {
76573 return function(graph) {
76574 var entity = graph.entity(entityId),
76575 newtags = lodash.clone(entity.tags),
76579 // This handles dataDeprecated tags with a single condition
76580 for (var i = 0; i < dataDeprecated.length; i++) {
76582 rule = dataDeprecated[i];
76583 var match = lodash.toPairs(rule.old)[0],
76584 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
76586 if (entity.tags[match[0]] && match[1] === '*') {
76588 var value = entity.tags[match[0]];
76589 if (replacements && !newtags[replacements[0][0]]) {
76590 newtags[replacements[0][0]] = value;
76592 delete newtags[match[0]];
76595 } else if (entity.tags[match[0]] === match[1]) {
76596 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
76602 return graph.replace(entity.update({tags: newtags}));
76609 function actionDiscardTags(difference) {
76611 return function(graph) {
76612 function discardTags(entity) {
76613 if (!lodash.isEmpty(entity.tags)) {
76615 lodash.each(entity.tags, function(v, k) {
76616 if (v) tags[k] = v;
76619 graph = graph.replace(entity.update({
76620 tags: lodash.omit(tags, dataDiscarded)
76625 difference.modified().forEach(discardTags);
76626 difference.created().forEach(discardTags);
76632 // Disconect the ways at the given node.
76634 // Optionally, disconnect only the given ways.
76636 // For testing convenience, accepts an ID to assign to the (first) new node.
76637 // Normally, this will be undefined and the way will automatically
76638 // be assigned a new ID.
76640 // This is the inverse of `iD.actionConnect`.
76643 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
76644 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
76646 function actionDisconnect(nodeId, newNodeId) {
76650 var action = function(graph) {
76651 var node = graph.entity(nodeId),
76652 connections = action.connections(graph);
76654 connections.forEach(function(connection) {
76655 var way = graph.entity(connection.wayID),
76656 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
76658 graph = graph.replace(newNode);
76659 if (connection.index === 0 && way.isArea()) {
76660 // replace shared node with shared node..
76661 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
76662 } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
76663 // replace closing node with new new node..
76664 graph = graph.replace(way.unclose().addNode(newNode.id));
76666 // replace shared node with multiple new nodes..
76667 graph = graph.replace(way.updateNode(newNode.id, connection.index));
76675 action.connections = function(graph) {
76676 var candidates = [],
76678 parentWays = graph.parentWays(graph.entity(nodeId));
76680 parentWays.forEach(function(way) {
76681 if (wayIds && wayIds.indexOf(way.id) === -1) {
76685 if (way.isArea() && (way.nodes[0] === nodeId)) {
76686 candidates.push({ wayID: way.id, index: 0 });
76688 way.nodes.forEach(function(waynode, index) {
76689 if (waynode === nodeId) {
76690 candidates.push({ wayID: way.id, index: index });
76696 return keeping ? candidates : candidates.slice(1);
76700 action.disabled = function(graph) {
76701 var connections = action.connections(graph);
76702 if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
76703 return 'not_connected';
76705 var parentWays = graph.parentWays(graph.entity(nodeId)),
76706 seenRelationIds = {},
76709 parentWays.forEach(function(way) {
76710 if (wayIds && wayIds.indexOf(way.id) === -1)
76713 var relations = graph.parentRelations(way);
76714 relations.forEach(function(relation) {
76715 if (relation.id in seenRelationIds) {
76716 sharedRelation = relation;
76718 seenRelationIds[relation.id] = true;
76723 if (sharedRelation)
76728 action.limitWays = function(_) {
76729 if (!arguments.length) return wayIds;
76738 // Join ways at the end node they share.
76740 // This is the inverse of `iD.actionSplit`.
76743 // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
76744 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
76746 function actionJoin(ids) {
76748 function groupEntitiesByGeometry(graph) {
76749 var entities = ids.map(function(id) { return graph.entity(id); });
76750 return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
76754 var action = function(graph) {
76755 var ways = ids.map(graph.entity, graph),
76756 survivor = ways[0];
76758 // Prefer to keep an existing way.
76759 for (var i = 0; i < ways.length; i++) {
76760 if (!ways[i].isNew()) {
76761 survivor = ways[i];
76766 var joined = osmJoinWays(ways, graph)[0];
76768 survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
76769 graph = graph.replace(survivor);
76771 joined.forEach(function(way) {
76772 if (way.id === survivor.id)
76775 graph.parentRelations(way).forEach(function(parent) {
76776 graph = graph.replace(parent.replaceMember(way, survivor));
76779 survivor = survivor.mergeTags(way.tags);
76781 graph = graph.replace(survivor);
76782 graph = actionDeleteWay(way.id)(graph);
76789 action.disabled = function(graph) {
76790 var geometries = groupEntitiesByGeometry(graph);
76791 if (ids.length < 2 || ids.length !== geometries.line.length)
76792 return 'not_eligible';
76794 var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
76795 if (joined.length > 1)
76796 return 'not_adjacent';
76798 var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
76801 conflicting = false;
76803 joined[0].forEach(function(way) {
76804 var parents = graph.parentRelations(way);
76805 parents.forEach(function(parent) {
76806 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
76810 for (var k in way.tags) {
76811 if (!(k in tags)) {
76812 tags[k] = way.tags[k];
76813 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
76814 conflicting = true;
76820 return 'restriction';
76823 return 'conflicting_tags';
76830 function actionMerge(ids) {
76832 function groupEntitiesByGeometry(graph) {
76833 var entities = ids.map(function(id) { return graph.entity(id); });
76834 return lodash.extend({point: [], area: [], line: [], relation: []},
76835 lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
76839 var action = function(graph) {
76840 var geometries = groupEntitiesByGeometry(graph),
76841 target = geometries.area[0] || geometries.line[0],
76842 points = geometries.point;
76844 points.forEach(function(point) {
76845 target = target.mergeTags(point.tags);
76846 graph = graph.replace(target);
76848 graph.parentRelations(point).forEach(function(parent) {
76849 graph = graph.replace(parent.replaceMember(point, target));
76852 var nodes = lodash.uniq(graph.childNodes(target)),
76853 removeNode = point;
76855 for (var i = 0; i < nodes.length; i++) {
76856 var node = nodes[i];
76857 if (graph.parentWays(node).length > 1 ||
76858 graph.parentRelations(node).length ||
76859 node.hasInterestingTags()) {
76863 // Found an uninteresting child node on the target way.
76864 // Move orig point into its place to preserve point's history. #3683
76865 graph = graph.replace(point.update({ tags: {}, loc: node.loc }));
76866 target = target.replaceNode(node.id, point.id);
76867 graph = graph.replace(target);
76872 graph = graph.remove(removeNode);
76879 action.disabled = function(graph) {
76880 var geometries = groupEntitiesByGeometry(graph);
76881 if (geometries.point.length === 0 ||
76882 (geometries.area.length + geometries.line.length) !== 1 ||
76883 geometries.relation.length !== 0)
76884 return 'not_eligible';
76891 function actionMergePolygon(ids, newRelationId) {
76893 function groupEntities(graph) {
76894 var entities = ids.map(function (id) { return graph.entity(id); });
76895 return lodash.extend({
76899 }, lodash.groupBy(entities, function(entity) {
76900 if (entity.type === 'way' && entity.isClosed()) {
76901 return 'closedWay';
76902 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
76903 return 'multipolygon';
76911 var action = function(graph) {
76912 var entities = groupEntities(graph);
76914 // An array representing all the polygons that are part of the multipolygon.
76916 // Each element is itself an array of objects with an id property, and has a
76917 // locs property which is an array of the locations forming the polygon.
76918 var polygons = entities.multipolygon.reduce(function(polygons, m) {
76919 return polygons.concat(osmJoinWays(m.members, graph));
76920 }, []).concat(entities.closedWay.map(function(d) {
76921 var member = [{id: d.id}];
76922 member.nodes = graph.childNodes(d);
76926 // contained is an array of arrays of boolean values,
76927 // where contained[j][k] is true iff the jth way is
76928 // contained by the kth way.
76929 var contained = polygons.map(function(w, i) {
76930 return polygons.map(function(d, n) {
76931 if (i === n) return null;
76932 return geoPolygonContainsPolygon(
76933 lodash.map(d.nodes, 'loc'),
76934 lodash.map(w.nodes, 'loc'));
76938 // Sort all polygons as either outer or inner ways
76942 while (polygons.length) {
76943 extractUncontained(polygons);
76944 polygons = polygons.filter(isContained);
76945 contained = contained.filter(isContained).map(filterContained);
76948 function isContained(d, i) {
76949 return lodash.some(contained[i]);
76952 function filterContained(d) {
76953 return d.filter(isContained);
76956 function extractUncontained(polygons) {
76957 polygons.forEach(function(d, i) {
76958 if (!isContained(d, i)) {
76959 d.forEach(function(member) {
76963 role: outer ? 'outer' : 'inner'
76971 // Move all tags to one relation
76972 var relation = entities.multipolygon[0] ||
76973 osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
76975 entities.multipolygon.slice(1).forEach(function(m) {
76976 relation = relation.mergeTags(m.tags);
76977 graph = graph.remove(m);
76980 entities.closedWay.forEach(function(way) {
76981 function isThisOuter(m) {
76982 return m.id === way.id && m.role !== 'inner';
76984 if (members.some(isThisOuter)) {
76985 relation = relation.mergeTags(way.tags);
76986 graph = graph.replace(way.update({ tags: {} }));
76990 return graph.replace(relation.update({
76992 tags: lodash.omit(relation.tags, 'area')
76997 action.disabled = function(graph) {
76998 var entities = groupEntities(graph);
76999 if (entities.other.length > 0 ||
77000 entities.closedWay.length + entities.multipolygon.length < 2)
77001 return 'not_eligible';
77002 if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
77003 return 'incomplete_relation';
77010 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
77011 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
77013 // Permission is hereby granted, free of charge, to any person
77014 // obtaining a copy of this software and associated documentation files
77015 // (the "Software"), to deal in the Software without restriction,
77016 // including without limitation the rights to use, copy, modify, merge,
77017 // publish, distribute, sublicense, and/or sell copies of the Software,
77018 // and to permit persons to whom the Software is furnished to do so,
77019 // subject to the following conditions:
77021 // The above copyright notice and this permission notice shall be
77022 // included in all copies or substantial portions of the Software.
77024 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
77025 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
77026 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
77027 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
77028 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
77029 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
77030 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
77033 // source: https://bitbucket.org/lshift/synchrotron/src
77034 function longest_common_subsequence(file1, file2) {
77035 /* Text diff algorithm following Hunt and McIlroy 1976.
77036 * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
77037 * comparison, Bell Telephone Laboratories CSTR #41 (1976)
77038 * http://www.cs.dartmouth.edu/~doug/
77040 * Expects two arrays of strings.
77042 var equivalenceClasses;
77047 var c, i, j, jX, r, s;
77049 equivalenceClasses = {};
77050 for (j = 0; j < file2.length; j++) {
77052 if (equivalenceClasses[line]) {
77053 equivalenceClasses[line].push(j);
77055 equivalenceClasses[line] = [j];
77059 candidates = [{file1index: -1,
77063 for (i = 0; i < file1.length; i++) {
77065 file2indices = equivalenceClasses[line] || [];
77070 for (jX = 0; jX < file2indices.length; jX++) {
77071 j = file2indices[jX];
77073 for (s = 0; s < candidates.length; s++) {
77074 if ((candidates[s].file2index < j) &&
77075 ((s === candidates.length - 1) ||
77076 (candidates[s + 1].file2index > j)))
77080 if (s < candidates.length) {
77081 newCandidate = {file1index: i,
77083 chain: candidates[s]};
77084 if (r === candidates.length) {
77085 candidates.push(c);
77091 if (r === candidates.length) {
77092 break; // no point in examining further (j)s
77100 // At this point, we know the LCS: it's in the reverse of the
77101 // linked-list through .chain of
77102 // candidates[candidates.length - 1].
77104 return candidates[candidates.length - 1];
77117 function diff_indices(file1, file2) {
77118 // We apply the LCS to give a simple representation of the
77119 // offsets and lengths of mismatched chunks in the input
77120 // files. This is used by diff3_merge_indices below.
77123 var tail1 = file1.length;
77124 var tail2 = file2.length;
77126 for (var candidate = longest_common_subsequence(file1, file2);
77127 candidate !== null;
77128 candidate = candidate.chain)
77130 var mismatchLength1 = tail1 - candidate.file1index - 1;
77131 var mismatchLength2 = tail2 - candidate.file2index - 1;
77132 tail1 = candidate.file1index;
77133 tail2 = candidate.file2index;
77135 if (mismatchLength1 || mismatchLength2) {
77136 result.push({file1: [tail1 + 1, mismatchLength1],
77137 file2: [tail2 + 1, mismatchLength2]});
77145 function diff3_merge_indices (a, o, b) {
77146 // Given three files, A, O, and B, where both A and B are
77147 // independently derived from O, returns a fairly complicated
77148 // internal representation of merge decisions it's taken. The
77149 // interested reader may wish to consult
77151 // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
77152 // Formal Investigation of Diff3." In Arvind and Prasad,
77153 // editors, Foundations of Software Technology and Theoretical
77154 // Computer Science (FSTTCS), December 2007.
77156 // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
77159 var m1 = diff_indices(o, a);
77160 var m2 = diff_indices(o, b);
77163 function addHunk(h, side) {
77164 hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
77166 for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
77167 for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
77171 var commonOffset = 0;
77172 function copyCommon(targetOffset) {
77173 if (targetOffset > commonOffset) {
77174 result.push([1, commonOffset, targetOffset - commonOffset]);
77175 commonOffset = targetOffset;
77179 for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
77180 var firstHunkIndex = hunkIndex;
77181 var hunk = hunks[hunkIndex];
77182 var regionLhs = hunk[0];
77183 var regionRhs = regionLhs + hunk[2];
77184 while (hunkIndex < hunks.length - 1) {
77185 var maybeOverlapping = hunks[hunkIndex + 1];
77186 var maybeLhs = maybeOverlapping[0];
77187 if (maybeLhs > regionRhs) break;
77188 regionRhs = maybeLhs + maybeOverlapping[2];
77192 copyCommon(regionLhs);
77193 if (firstHunkIndex === hunkIndex) {
77194 // The "overlap" was only one hunk long, meaning that
77195 // there's no conflict here. Either a and o were the
77196 // same, or b and o were the same.
77198 result.push([hunk[1], hunk[3], hunk[4]]);
77201 // A proper conflict. Determine the extents of the
77202 // regions involved from a, o and b. Effectively merge
77203 // all the hunks on the left into one giant hunk, and
77204 // do the same for the right; then, correct for skew
77205 // in the regions of o that each side changed, and
77206 // report appropriate spans for the three sides.
77208 0: [a.length, -1, o.length, -1],
77209 2: [b.length, -1, o.length, -1]
77211 for (i = firstHunkIndex; i <= hunkIndex; i++) {
77213 var side = hunk[1];
77214 var r = regions[side];
77215 var oLhs = hunk[0];
77216 var oRhs = oLhs + hunk[2];
77217 var abLhs = hunk[3];
77218 var abRhs = abLhs + hunk[4];
77219 r[0] = Math.min(abLhs, r[0]);
77220 r[1] = Math.max(abRhs, r[1]);
77221 r[2] = Math.min(oLhs, r[2]);
77222 r[3] = Math.max(oRhs, r[3]);
77224 var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
77225 var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
77226 var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
77227 var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
77230 regionLhs, regionRhs - regionLhs,
77231 bLhs, bRhs - bLhs]);
77233 commonOffset = regionRhs;
77236 copyCommon(o.length);
77240 function diff3_merge (a, o, b, excludeFalseConflicts) {
77241 // Applies the output of Diff3.diff3_merge_indices to actually
77242 // construct the merged file; the returned result alternates
77243 // between "ok" and "conflict" blocks.
77246 var files = [a, o, b];
77247 var indices = diff3_merge_indices(a, o, b);
77250 function flushOk() {
77251 if (okLines.length) {
77252 result.push({ok: okLines});
77256 function pushOk(xs) {
77257 for (var j = 0; j < xs.length; j++) {
77258 okLines.push(xs[j]);
77262 function isTrueConflict(rec) {
77263 if (rec[2] !== rec[6]) return true;
77266 for (var j = 0; j < rec[2]; j++) {
77267 if (a[j + aoff] !== b[j + boff]) return true;
77272 for (var i = 0; i < indices.length; i++) {
77273 var x = indices[i];
77276 if (excludeFalseConflicts && !isTrueConflict(x)) {
77277 pushOk(files[0].slice(x[1], x[1] + x[2]));
77280 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
77282 o: o.slice(x[3], x[3] + x[4]),
77284 b: b.slice(x[5], x[5] + x[6]),
77288 pushOk(files[side].slice(x[1], x[1] + x[2]));
77296 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
77297 var option = 'safe', // 'safe', 'force_local', 'force_remote'
77302 return lodash.isFunction(formatUser) ? formatUser(d) : d;
77306 function mergeLocation(remote, target) {
77307 function pointEqual(a, b) {
77308 var epsilon = 1e-6;
77309 return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
77312 if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
77315 if (option === 'force_remote') {
77316 return target.update({loc: remote.loc});
77319 conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
77324 function mergeNodes(base, remote, target) {
77325 if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
77328 if (option === 'force_remote') {
77329 return target.update({nodes: remote.nodes});
77332 var ccount = conflicts.length,
77333 o = base.nodes || [],
77334 a = target.nodes || [],
77335 b = remote.nodes || [],
77337 hunks = diff3_merge(a, o, b, true);
77339 for (var i = 0; i < hunks.length; i++) {
77340 var hunk = hunks[i];
77342 nodes.push.apply(nodes, hunk.ok);
77344 // for all conflicts, we can assume c.a !== c.b
77345 // because `diff3_merge` called with `true` option to exclude false conflicts..
77346 var c = hunk.conflict;
77347 if (lodash.isEqual(c.o, c.a)) { // only changed remotely
77348 nodes.push.apply(nodes, c.b);
77349 } else if (lodash.isEqual(c.o, c.b)) { // only changed locally
77350 nodes.push.apply(nodes, c.a);
77351 } else { // changed both locally and remotely
77352 conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
77358 return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
77362 function mergeChildren(targetWay, children, updates, graph) {
77363 function isUsed(node, targetWay) {
77364 var parentWays = lodash.map(graph.parentWays(node), 'id');
77365 return node.hasInterestingTags() ||
77366 lodash.without(parentWays, targetWay.id).length > 0 ||
77367 graph.parentRelations(node).length > 0;
77370 var ccount = conflicts.length;
77372 for (var i = 0; i < children.length; i++) {
77373 var id = children[i],
77374 node = graph.hasEntity(id);
77376 // remove unused childNodes..
77377 if (targetWay.nodes.indexOf(id) === -1) {
77378 if (node && !isUsed(node, targetWay)) {
77379 updates.removeIds.push(id);
77384 // restore used childNodes..
77385 var local = localGraph.hasEntity(id),
77386 remote = remoteGraph.hasEntity(id),
77389 if (option === 'force_remote' && remote && remote.visible) {
77390 updates.replacements.push(remote);
77392 } else if (option === 'force_local' && local) {
77393 target = osmEntity$$1(local);
77395 target = target.update({ version: remote.version });
77397 updates.replacements.push(target);
77399 } else if (option === 'safe' && local && remote && local.version !== remote.version) {
77400 target = osmEntity$$1(local, { version: remote.version });
77401 if (remote.visible) {
77402 target = mergeLocation(remote, target);
77404 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
77407 if (conflicts.length !== ccount) break;
77408 updates.replacements.push(target);
77416 function updateChildren(updates, graph) {
77417 for (var i = 0; i < updates.replacements.length; i++) {
77418 graph = graph.replace(updates.replacements[i]);
77420 if (updates.removeIds.length) {
77421 graph = actionDeleteMultiple(updates.removeIds)(graph);
77427 function mergeMembers(remote, target) {
77428 if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
77431 if (option === 'force_remote') {
77432 return target.update({members: remote.members});
77435 conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
77440 function mergeTags(base, remote, target) {
77441 function ignoreKey(k) {
77442 return lodash.includes(dataDiscarded, k);
77445 if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
77448 if (option === 'force_remote') {
77449 return target.update({tags: remote.tags});
77452 var ccount = conflicts.length,
77453 o = base.tags || {},
77454 a = target.tags || {},
77455 b = remote.tags || {},
77456 keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
77457 tags = lodash.clone(a),
77460 for (var i = 0; i < keys.length; i++) {
77463 if (o[k] !== b[k] && a[k] !== b[k]) { // changed remotely..
77464 if (o[k] !== a[k]) { // changed locally..
77465 conflicts.push(t('merge_remote_changes.conflict.tags',
77466 { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
77468 } else { // unchanged locally, accept remote change..
77469 if (b.hasOwnProperty(k)) {
77479 return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
77483 // `graph.base()` is the common ancestor of the two graphs.
77484 // `localGraph` contains user's edits up to saving
77485 // `remoteGraph` contains remote edits to modified nodes
77486 // `graph` must be a descendent of `localGraph` and may include
77487 // some conflict resolution actions performed on it.
77489 // --- ... --- `localGraph` -- ... -- `graph`
77491 // `graph.base()` --- ... --- `remoteGraph`
77493 var action = function(graph) {
77494 var updates = { replacements: [], removeIds: [] },
77495 base = graph.base().entities[id],
77496 local = localGraph.entity(id),
77497 remote = remoteGraph.entity(id),
77498 target = osmEntity$$1(local, { version: remote.version });
77501 if (!remote.visible) {
77502 if (option === 'force_remote') {
77503 return actionDeleteMultiple([id])(graph);
77505 } else if (option === 'force_local') {
77506 if (target.type === 'way') {
77507 target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
77508 graph = updateChildren(updates, graph);
77510 return graph.replace(target);
77513 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
77514 return graph; // do nothing
77519 if (target.type === 'node') {
77520 target = mergeLocation(remote, target);
77522 } else if (target.type === 'way') {
77523 // pull in any child nodes that may not be present locally..
77524 graph.rebase(remoteGraph.childNodes(remote), [graph], false);
77525 target = mergeNodes(base, remote, target);
77526 target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
77528 } else if (target.type === 'relation') {
77529 target = mergeMembers(remote, target);
77532 target = mergeTags(base, remote, target);
77534 if (!conflicts.length) {
77535 graph = updateChildren(updates, graph).replace(target);
77542 action.withOption = function(opt) {
77548 action.conflicts = function() {
77556 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
77557 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
77558 function actionMove(moveIds, tryDelta, projection, cache) {
77559 var delta = tryDelta;
77561 function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
77562 function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
77564 function setupCache(graph) {
77565 function canMove(nodeId) {
77566 // Allow movement of any node that is in the selectedIDs list..
77567 if (moveIds.indexOf(nodeId) !== -1) return true;
77569 // Allow movement of a vertex where 2 ways meet..
77570 var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
77571 if (parents.length < 3) return true;
77573 // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
77574 var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
77575 if (!parentsMoving) delete cache.moving[nodeId];
77577 return parentsMoving;
77580 function cacheEntities(ids) {
77581 ids.forEach(function(id) {
77582 if (cache.moving[id]) return;
77583 cache.moving[id] = true;
77585 var entity = graph.hasEntity(id);
77586 if (!entity) return;
77588 if (entity.type === 'node') {
77589 cache.nodes.push(id);
77590 cache.startLoc[id] = entity.loc;
77591 } else if (entity.type === 'way') {
77592 cache.ways.push(id);
77593 cacheEntities(entity.nodes);
77595 cacheEntities(entity.members.map(function(member) {
77602 function cacheIntersections(ids) {
77603 function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
77605 ids.forEach(function(id) {
77606 // consider only intersections with 1 moved and 1 unmoved way.
77607 var childNodes = graph.childNodes(graph.entity(id));
77608 childNodes.forEach(function(node) {
77609 var parents = graph.parentWays(node);
77610 if (parents.length !== 2) return;
77612 var moved = graph.entity(id),
77613 unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
77614 if (!unmoved) return;
77616 // exclude ways that are overly connected..
77617 if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
77619 if (moved.isArea() || unmoved.isArea()) return;
77621 cache.intersection[node.id] = {
77624 unmovedId: unmoved.id,
77625 movedIsEP: isEndpoint(moved, node.id),
77626 unmovedIsEP: isEndpoint(unmoved, node.id)
77638 cache.intersection = {};
77639 cache.replacedVertex = {};
77640 cache.startLoc = {};
77644 cacheEntities(moveIds);
77645 cacheIntersections(cache.ways);
77646 cache.nodes = lodash.filter(cache.nodes, canMove);
77653 // Place a vertex where the moved vertex used to be, to preserve way shape..
77654 function replaceMovedVertex(nodeId, wayId, graph, delta) {
77655 var way = graph.entity(wayId),
77656 moved = graph.entity(nodeId),
77657 movedIndex = way.nodes.indexOf(nodeId),
77658 len, prevIndex, nextIndex;
77660 if (way.isClosed()) {
77661 len = way.nodes.length - 1;
77662 prevIndex = (movedIndex + len - 1) % len;
77663 nextIndex = (movedIndex + len + 1) % len;
77665 len = way.nodes.length;
77666 prevIndex = movedIndex - 1;
77667 nextIndex = movedIndex + 1;
77670 var prev = graph.hasEntity(way.nodes[prevIndex]),
77671 next = graph.hasEntity(way.nodes[nextIndex]);
77673 // Don't add orig vertex at endpoint..
77674 if (!prev || !next) return graph;
77676 var key = wayId + '_' + nodeId,
77677 orig = cache.replacedVertex[key];
77680 cache.replacedVertex[key] = orig;
77681 cache.startLoc[orig.id] = cache.startLoc[nodeId];
77686 start = projection(cache.startLoc[nodeId]);
77687 end = projection.invert(vecAdd(start, delta));
77689 end = cache.startLoc[nodeId];
77691 orig = orig.move(end);
77693 var angle = Math.abs(geoAngle(orig, prev, projection) -
77694 geoAngle(orig, next, projection)) * 180 / Math.PI;
77696 // Don't add orig vertex if it would just make a straight line..
77697 if (angle > 175 && angle < 185) return graph;
77699 // Don't add orig vertex if another point is already nearby (within 10m)
77700 if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
77701 geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
77703 // moving forward or backward along way?
77704 var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
77705 p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
77706 d1 = geoPathLength(p1),
77707 d2 = geoPathLength(p2),
77708 insertAt = (d1 < d2) ? movedIndex : nextIndex;
77710 // moving around closed loop?
77711 if (way.isClosed() && insertAt === 0) insertAt = len;
77713 way = way.addNode(orig.id, insertAt);
77714 return graph.replace(orig).replace(way);
77718 // Reorder nodes around intersections that have moved..
77719 function unZorroIntersection(intersection, graph) {
77720 var vertex = graph.entity(intersection.nodeId),
77721 way1 = graph.entity(intersection.movedId),
77722 way2 = graph.entity(intersection.unmovedId),
77723 isEP1 = intersection.movedIsEP,
77724 isEP2 = intersection.unmovedIsEP;
77726 // don't move the vertex if it is the endpoint of both ways.
77727 if (isEP1 && isEP2) return graph;
77729 var nodes1 = lodash.without(graph.childNodes(way1), vertex),
77730 nodes2 = lodash.without(graph.childNodes(way2), vertex);
77732 if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
77733 if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
77735 var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
77736 edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
77739 // snap vertex to nearest edge (or some point between them)..
77740 if (!isEP1 && !isEP2) {
77741 var epsilon = 1e-4, maxIter = 10;
77742 for (var i = 0; i < maxIter; i++) {
77743 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
77744 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
77745 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
77746 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
77748 } else if (!isEP1) {
77754 graph = graph.replace(vertex.move(loc));
77756 // if zorro happened, reorder nodes..
77757 if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
77758 way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
77759 graph = graph.replace(way1);
77761 if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
77762 way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
77763 graph = graph.replace(way2);
77770 function cleanupIntersections(graph) {
77771 lodash.each(cache.intersection, function(obj) {
77772 graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
77773 graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
77774 graph = unZorroIntersection(obj, graph);
77781 // check if moving way endpoint can cross an unmoved way, if so limit delta..
77782 function limitDelta(graph) {
77783 lodash.each(cache.intersection, function(obj) {
77784 // Don't limit movement if this is vertex joins 2 endpoints..
77785 if (obj.movedIsEP && obj.unmovedIsEP) return;
77786 // Don't limit movement if this vertex is not an endpoint anyway..
77787 if (!obj.movedIsEP) return;
77789 var node = graph.entity(obj.nodeId),
77790 start = projection(node.loc),
77791 end = vecAdd(start, delta),
77792 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
77793 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
77794 function(loc) { return vecAdd(projection(loc), delta); }),
77795 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
77796 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
77797 hits = geoPathIntersections(movedPath, unmovedPath);
77799 for (var i = 0; i < hits.length; i++) {
77800 if (lodash.isEqual(hits[i], end)) continue;
77801 var edge = geoChooseEdge(unmovedNodes, end, projection);
77802 delta = vecSub(projection(edge.loc), start);
77808 var action = function(graph) {
77809 if (delta[0] === 0 && delta[1] === 0) return graph;
77813 if (!lodash.isEmpty(cache.intersection)) {
77817 lodash.each(cache.nodes, function(id) {
77818 var node = graph.entity(id),
77819 start = projection(node.loc),
77820 end = vecAdd(start, delta);
77821 graph = graph.replace(node.move(projection.invert(end)));
77824 if (!lodash.isEmpty(cache.intersection)) {
77825 graph = cleanupIntersections(graph);
77832 action.delta = function() {
77840 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
77841 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
77842 function actionMoveNode(nodeId, loc) {
77843 return function(graph) {
77844 return graph.replace(graph.entity(nodeId).move(loc));
77848 function actionNoop() {
77849 return function(graph) {
77855 * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
77857 function actionOrthogonalize(wayId, projection) {
77858 var threshold = 12, // degrees within right or straight to alter
77859 lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
77860 upperThreshold = Math.cos(threshold * Math.PI / 180);
77863 var action = function(graph, t) {
77864 if (t === null || !isFinite(t)) t = 1;
77865 t = Math.min(Math.max(+t, 0), 1);
77867 var way = graph.entity(wayId),
77868 nodes = graph.childNodes(way),
77869 points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
77870 corner = {i: 0, dotp: 1},
77872 node, loc, score, motions, i, j;
77874 if (points.length === 3) { // move only one vertex for right triangle
77875 for (i = 0; i < 1000; i++) {
77876 motions = points.map(calcMotion);
77877 points[corner.i] = addPoints(points[corner.i], motions[corner.i]);
77878 score = corner.dotp;
77879 if (score < epsilon) {
77884 node = graph.entity(nodes[corner.i].id);
77885 loc = projection.invert(points[corner.i]);
77886 graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
77890 originalPoints = lodash.clone(points);
77893 for (i = 0; i < 1000; i++) {
77894 motions = points.map(calcMotion);
77895 for (j = 0; j < motions.length; j++) {
77896 points[j] = addPoints(points[j],motions[j]);
77898 var newScore = squareness(points);
77899 if (newScore < score) {
77900 best = lodash.clone(points);
77903 if (score < epsilon) {
77910 for (i = 0; i < points.length; i++) {
77911 // only move the points that actually moved
77912 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
77913 loc = projection.invert(points[i]);
77914 node = graph.entity(nodes[i].id);
77915 graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
77919 // remove empty nodes on straight sections
77920 for (i = 0; t === 1 && i < points.length; i++) {
77921 node = graph.entity(nodes[i].id);
77923 if (graph.parentWays(node).length > 1 ||
77924 graph.parentRelations(node).length ||
77925 node.hasInterestingTags()) {
77929 var dotp = normalizedDotProduct(i, points);
77930 if (dotp < -1 + epsilon) {
77931 graph = actionDeleteNode(node.id)(graph);
77939 function calcMotion(b, i, array) {
77940 var a = array[(i - 1 + array.length) % array.length],
77941 c = array[(i + 1) % array.length],
77942 p = subtractPoints(a, b),
77943 q = subtractPoints(c, b),
77946 scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
77947 p = normalizePoint(p, 1.0);
77948 q = normalizePoint(q, 1.0);
77950 dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
77952 // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
77953 if (array.length > 3) {
77954 if (dotp < -0.707106781186547) {
77957 } else if (dotp && Math.abs(dotp) < corner.dotp) {
77959 corner.dotp = Math.abs(dotp);
77962 return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
77967 function squareness(points) {
77968 return points.reduce(function(sum, val, i, array) {
77969 var dotp = normalizedDotProduct(i, array);
77971 dotp = filterDotProduct(dotp);
77972 return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
77977 function normalizedDotProduct(i, points) {
77978 var a = points[(i - 1 + points.length) % points.length],
77980 c = points[(i + 1) % points.length],
77981 p = subtractPoints(a, b),
77982 q = subtractPoints(c, b);
77984 p = normalizePoint(p, 1.0);
77985 q = normalizePoint(q, 1.0);
77987 return p[0] * q[0] + p[1] * q[1];
77991 function subtractPoints(a, b) {
77992 return [a[0] - b[0], a[1] - b[1]];
77996 function addPoints(a, b) {
77997 return [a[0] + b[0], a[1] + b[1]];
78001 function normalizePoint(point, scale) {
78002 var vector = [0, 0];
78003 var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
78004 if (length !== 0) {
78005 vector[0] = point[0] / length;
78006 vector[1] = point[1] / length;
78009 vector[0] *= scale;
78010 vector[1] *= scale;
78016 function filterDotProduct(dotp) {
78017 if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
78025 action.disabled = function(graph) {
78026 var way = graph.entity(wayId),
78027 nodes = graph.childNodes(way),
78028 points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
78030 if (squareness(points)) {
78034 return 'not_squarish';
78038 action.transitionable = true;
78044 // Split a way at the given node.
78046 // Optionally, split only the given ways, if multiple ways share
78049 // This is the inverse of `iD.actionJoin`.
78051 // For testing convenience, accepts an ID to assign to the new way.
78052 // Normally, this will be undefined and the way will automatically
78053 // be assigned a new ID.
78056 // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
78058 function actionSplit(nodeId, newWayIds) {
78061 // if the way is closed, we need to search for a partner node
78062 // to split the way at.
78064 // The following looks for a node that is both far away from
78065 // the initial node in terms of way segment length and nearby
78066 // in terms of beeline-distance. This assures that areas get
78067 // split on the most "natural" points (independent of the number
78069 // For example: bone-shaped areas get split across their waist
78070 // line, circles across the diameter.
78071 function splitArea(nodes, idxA, graph) {
78072 var lengths = new Array(nodes.length),
78078 function wrap(index) {
78079 return utilWrap(index, nodes.length);
78082 function dist(nA, nB) {
78083 return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
78086 // calculate lengths
78088 for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
78089 length += dist(nodes[i], nodes[wrap(i-1)]);
78090 lengths[i] = length;
78094 for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
78095 length += dist(nodes[i], nodes[wrap(i+1)]);
78096 if (length < lengths[i])
78097 lengths[i] = length;
78100 // determine best opposite node to split
78101 for (i = 0; i < nodes.length; i++) {
78102 var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
78113 function split(graph, wayA, newWayId) {
78114 var wayB = osmWay({id: newWayId, tags: wayA.tags}),
78117 isArea = wayA.isArea(),
78118 isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
78120 if (wayA.isClosed()) {
78121 var nodes = wayA.nodes.slice(0, -1),
78122 idxA = lodash.indexOf(nodes, nodeId),
78123 idxB = splitArea(nodes, idxA, graph);
78126 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
78127 nodesB = nodes.slice(idxB, idxA + 1);
78129 nodesA = nodes.slice(idxA, idxB + 1);
78130 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
78133 var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
78134 nodesA = wayA.nodes.slice(0, idx + 1);
78135 nodesB = wayA.nodes.slice(idx);
78138 wayA = wayA.update({nodes: nodesA});
78139 wayB = wayB.update({nodes: nodesB});
78141 graph = graph.replace(wayA);
78142 graph = graph.replace(wayB);
78144 graph.parentRelations(wayA).forEach(function(relation) {
78145 if (relation.isRestriction()) {
78146 var via = relation.memberByRole('via');
78147 if (via && wayB.contains(via.id)) {
78148 relation = relation.replaceMember(wayA, wayB);
78149 graph = graph.replace(relation);
78152 if (relation === isOuter) {
78153 graph = graph.replace(relation.mergeTags(wayA.tags));
78154 graph = graph.replace(wayA.update({tags: {}}));
78155 graph = graph.replace(wayB.update({tags: {}}));
78161 role: relation.memberById(wayA.id).role
78164 graph = actionAddMember(relation.id, member)(graph);
78168 if (!isOuter && isArea) {
78169 var multipolygon = osmRelation({
78170 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
78172 {id: wayA.id, role: 'outer', type: 'way'},
78173 {id: wayB.id, role: 'outer', type: 'way'}
78176 graph = graph.replace(multipolygon);
78177 graph = graph.replace(wayA.update({tags: {}}));
78178 graph = graph.replace(wayB.update({tags: {}}));
78185 var action = function(graph) {
78186 var candidates = action.ways(graph);
78187 for (var i = 0; i < candidates.length; i++) {
78188 graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
78194 action.ways = function(graph) {
78195 var node = graph.entity(nodeId),
78196 parents = graph.parentWays(node),
78197 hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
78199 return parents.filter(function(parent) {
78200 if (wayIds && wayIds.indexOf(parent.id) === -1)
78203 if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
78206 if (parent.isClosed()) {
78210 for (var i = 1; i < parent.nodes.length - 1; i++) {
78211 if (parent.nodes[i] === nodeId) {
78221 action.disabled = function(graph) {
78222 var candidates = action.ways(graph);
78223 if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
78224 return 'not_eligible';
78228 action.limitWays = function(_) {
78229 if (!arguments.length) return wayIds;
78238 // Create a restriction relation for `turn`, which must have the following structure:
78241 // from: { node: <node ID>, way: <way ID> },
78242 // via: { node: <node ID> },
78243 // to: { node: <node ID>, way: <way ID> },
78244 // restriction: <'no_right_turn', 'no_left_turn', etc.>
78247 // This specifies a restriction of type `restriction` when traveling from
78248 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
78249 // (The action does not check that these entities form a valid intersection.)
78251 // If `restriction` is not provided, it is automatically determined by
78252 // osmInferRestriction.
78254 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
78255 // and `to.node` are used to determine which portion of the split ways become
78256 // members of the restriction.
78258 // For testing convenience, accepts an ID to assign to the new relation.
78259 // Normally, this will be undefined and the relation will automatically
78260 // be assigned a new ID.
78262 function actionRestrictTurn(turn, projection, restrictionId) {
78264 return function(graph) {
78265 var from = graph.entity(turn.from.way),
78266 via = graph.entity(turn.via.node),
78267 to = graph.entity(turn.to.way);
78269 function isClosingNode(way, nodeId) {
78270 return nodeId === way.first() && nodeId === way.last();
78273 function split(toOrFrom) {
78274 var newID = toOrFrom.newID || osmWay().id;
78275 graph = actionSplit(via.id, [newID])
78276 .limitWays([toOrFrom.way])(graph);
78278 var a = graph.entity(newID),
78279 b = graph.entity(toOrFrom.way);
78281 if (a.nodes.indexOf(toOrFrom.node) !== -1) {
78288 if (!from.affix(via.id) || isClosingNode(from, via.id)) {
78289 if (turn.from.node === turn.to.node) {
78291 from = to = split(turn.from)[0];
78292 } else if (turn.from.way === turn.to.way) {
78293 // Straight-on or circular
78294 var s = split(turn.from);
78299 from = split(turn.from)[0];
78303 if (!to.affix(via.id) || isClosingNode(to, via.id)) {
78304 to = split(turn.to)[0];
78307 return graph.replace(osmRelation({
78310 type: 'restriction',
78311 restriction: turn.restriction ||
78312 osmInferRestriction(
78320 {id: from.id, type: 'way', role: 'from'},
78321 {id: via.id, type: 'node', role: 'via'},
78322 {id: to.id, type: 'way', role: 'to'}
78328 function actionRevert(id) {
78329 var action = function(graph) {
78330 var entity = graph.hasEntity(id),
78331 base = graph.base().entities[id];
78333 if (entity && !base) { // entity will be removed..
78334 if (entity.type === 'node') {
78335 graph.parentWays(entity)
78336 .forEach(function(parent) {
78337 parent = parent.removeNode(id);
78338 graph = graph.replace(parent);
78340 if (parent.isDegenerate()) {
78341 graph = actionDeleteWay(parent.id)(graph);
78346 graph.parentRelations(entity)
78347 .forEach(function(parent) {
78348 parent = parent.removeMembersWithID(id);
78349 graph = graph.replace(parent);
78351 if (parent.isDegenerate()) {
78352 graph = actionDeleteRelation(parent.id)(graph);
78357 return graph.revert(id);
78363 function actionRotate(rotateIds, pivot, angle, projection) {
78365 var action = function(graph) {
78366 return graph.update(function(graph) {
78367 utilGetAllNodes(rotateIds, graph).forEach(function(node) {
78368 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
78369 graph = graph.replace(node.move(projection.invert(point)));
78378 * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
78380 function actionStraighten(wayId, projection) {
78382 function positionAlongWay(n, s, e) {
78383 return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) /
78384 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
78388 var action = function(graph, t) {
78389 if (t === null || !isFinite(t)) t = 1;
78390 t = Math.min(Math.max(+t, 0), 1);
78392 var way = graph.entity(wayId),
78393 nodes = graph.childNodes(way),
78394 points = nodes.map(function(n) { return projection(n.loc); }),
78395 startPoint = points[0],
78396 endPoint = points[points.length-1],
78400 for (i = 1; i < points.length-1; i++) {
78401 var node = nodes[i],
78404 if (t < 1 || graph.parentWays(node).length > 1 ||
78405 graph.parentRelations(node).length ||
78406 node.hasInterestingTags()) {
78408 var u = positionAlongWay(point, startPoint, endPoint),
78410 startPoint[0] + u * (endPoint[0] - startPoint[0]),
78411 startPoint[1] + u * (endPoint[1] - startPoint[1])
78413 loc2 = projection.invert(p);
78415 graph = graph.replace(node.move(geoInterp(node.loc, loc2, t)));
78419 if (toDelete.indexOf(node) === -1) {
78420 toDelete.push(node);
78425 for (i = 0; i < toDelete.length; i++) {
78426 graph = actionDeleteNode(toDelete[i].id)(graph);
78433 action.disabled = function(graph) {
78434 // check way isn't too bendy
78435 var way = graph.entity(wayId),
78436 nodes = graph.childNodes(way),
78437 points = nodes.map(function(n) { return projection(n.loc); }),
78438 startPoint = points[0],
78439 endPoint = points[points.length-1],
78440 threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
78443 if (threshold === 0) {
78444 return 'too_bendy';
78447 for (i = 1; i < points.length-1; i++) {
78448 var point = points[i],
78449 u = positionAlongWay(point, startPoint, endPoint),
78450 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
78451 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
78452 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
78454 // to bendy if point is off by 20% of total start/end distance in projected space
78455 if (isNaN(dist) || dist > threshold) {
78456 return 'too_bendy';
78462 action.transitionable = true;
78468 // Remove the effects of `turn.restriction` on `turn`, which must have the
78469 // following structure:
78472 // from: { node: <node ID>, way: <way ID> },
78473 // via: { node: <node ID> },
78474 // to: { node: <node ID>, way: <way ID> },
78475 // restriction: <relation ID>
78478 // In the simple case, `restriction` is a reference to a `no_*` restriction
78479 // on the turn itself. In this case, it is simply deleted.
78481 // The more complex case is where `restriction` references an `only_*`
78482 // restriction on a different turn in the same intersection. In that case,
78483 // that restriction is also deleted, but at the same time restrictions on
78484 // the turns other than the first two are created.
78486 function actionUnrestrictTurn(turn) {
78487 return function(graph) {
78488 return actionDeleteRelation(turn.restriction)(graph);
78492 /* Reflect the given area around its axis of symmetry */
78493 function actionReflect(reflectIds, projection$$1) {
78494 var useLongAxis = true;
78497 // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
78498 // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
78499 function getSmallestSurroundingRectangle(graph, nodes) {
78500 var points = nodes.map(function(n) { return projection$$1(n.loc); }),
78501 hull = d3polygonHull(points),
78502 centroid = d3polygonCentroid(hull),
78503 minArea = Infinity,
78508 for (var i = 0; i < hull.length - 1; i++) {
78509 var c2 = hull[i + 1],
78510 angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]),
78511 poly = geoRotate(hull, -angle, centroid),
78512 extent$$1 = poly.reduce(function(extent$$1, point) {
78513 return extent$$1.extend(geoExtent$$1(point));
78514 }, geoExtent$$1()),
78515 area$$1 = extent$$1.area();
78517 if (area$$1 < minArea) {
78519 ssrExtent = extent$$1;
78526 poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
78532 var action = function(graph, t) {
78533 if (t === null || !isFinite(t)) t = 1;
78534 t = Math.min(Math.max(+t, 0), 1);
78536 var nodes = utilGetAllNodes(reflectIds, graph),
78537 ssr = getSmallestSurroundingRectangle(graph, nodes);
78539 // Choose line pq = axis of symmetry.
78540 // The shape's surrounding rectangle has 2 axes of symmetry.
78541 // Reflect across the longer axis by default.
78542 var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2 ],
78543 q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2 ],
78544 p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2 ],
78545 q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ],
78548 var isLong = (geoEuclideanDistance(p1, q1) > geoEuclideanDistance(p2, q2));
78549 if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) {
78557 // reflect c across pq
78558 // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
78559 var dx = q[0] - p[0];
78560 var dy = q[1] - p[1];
78561 var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
78562 var b = 2 * dx * dy / (dx * dx + dy * dy);
78563 for (var i = 0; i < nodes.length; i++) {
78564 var node = nodes[i];
78565 var c = projection$$1(node.loc);
78567 a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0],
78568 b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]
78570 var loc2 = projection$$1.invert(c2);
78571 node = node.move(geoInterp(node.loc, loc2, t));
78572 graph = graph.replace(node);
78579 action.useLongAxis = function(_) {
78580 if (!arguments.length) return useLongAxis;
78586 action.transitionable = true;
78594 var index$17 = Object.freeze({
78595 d3combobox: d3combobox,
78596 d3geoTile: d3geoTile,
78597 d3keybinding: d3keybinding
78600 /* export some legacy symbols: */
78601 var Connection = services.osm;
78607 var iD = Object.freeze({
78608 Connection: Connection,
78613 Context: coreContext,
78614 setAreaKeys: setAreaKeys,
78615 Difference: coreDifference,
78616 Graph: coreGraph$$1,
78617 History: coreHistory,
78619 Entity: osmEntity$$1,
78621 Relation: osmRelation,
78623 BackgroundSource: rendererBackgroundSource,
78624 Background: rendererBackground,
78625 Features: rendererFeatures,
78627 TileLayer: rendererTileLayer,
78628 Detect: utilDetect,
78629 actionAddEntity: actionAddEntity,
78630 actionAddMember: actionAddMember,
78631 actionAddMidpoint: actionAddMidpoint,
78632 actionAddVertex: actionAddVertex,
78633 actionChangeMember: actionChangeMember,
78634 actionChangePreset: actionChangePreset,
78635 actionChangeTags: actionChangeTags,
78636 actionCircularize: actionCircularize,
78637 actionConnect: actionConnect,
78638 actionCopyEntities: actionCopyEntities,
78639 actionDeleteMember: actionDeleteMember,
78640 actionDeleteMultiple: actionDeleteMultiple,
78641 actionDeleteNode: actionDeleteNode,
78642 actionDeleteRelation: actionDeleteRelation,
78643 actionDeleteWay: actionDeleteWay,
78644 actionDeprecateTags: actionDeprecateTags,
78645 actionDiscardTags: actionDiscardTags,
78646 actionDisconnect: actionDisconnect,
78647 actionJoin: actionJoin,
78648 actionMerge: actionMerge,
78649 actionMergePolygon: actionMergePolygon,
78650 actionMergeRemoteChanges: actionMergeRemoteChanges,
78651 actionMove: actionMove,
78652 actionMoveNode: actionMoveNode,
78653 actionNoop: actionNoop,
78654 actionOrthogonalize: actionOrthogonalize,
78655 actionRestrictTurn: actionRestrictTurn,
78656 actionReverse: actionReverse,
78657 actionRevert: actionRevert,
78658 actionRotate: actionRotate,
78659 actionSplit: actionSplit,
78660 actionStraighten: actionStraighten,
78661 actionUnrestrictTurn: actionUnrestrictTurn,
78662 actionReflect: actionReflect,
78663 behaviorAddWay: behaviorAddWay,
78664 behaviorBreathe: behaviorBreathe,
78665 behaviorCopy: behaviorCopy,
78666 behaviorDrag: behaviorDrag,
78667 behaviorDrawWay: behaviorDrawWay,
78668 behaviorDraw: behaviorDraw,
78669 behaviorEdit: behaviorEdit,
78670 behaviorHash: behaviorHash,
78671 behaviorHover: behaviorHover,
78672 behaviorLasso: behaviorLasso,
78673 behaviorOperation: behaviorOperation,
78674 behaviorPaste: behaviorPaste,
78675 behaviorSelect: behaviorSelect,
78676 behaviorTail: behaviorTail,
78677 coreContext: coreContext,
78678 coreDifference: coreDifference,
78679 coreGraph: coreGraph$$1,
78680 coreHistory: coreHistory,
78681 coreTree: coreTree,
78682 dataFeatureIcons: dataFeatureIcons,
78684 dataWikipedia: dataWikipedia,
78685 dataSuggestions: dataSuggestions,
78686 dataAddressFormats: dataAddressFormats,
78687 dataDeprecated: dataDeprecated,
78688 dataDiscarded: dataDiscarded,
78689 dataLocales: dataLocales,
78690 dataPhoneFormats: dataPhoneFormats,
78691 dataShortcuts: dataShortcuts,
78692 dataImperial: dataImperial,
78693 dataDriveLeft: dataDriveLeft,
78695 geoAngle: geoAngle,
78696 geoChooseEdge: geoChooseEdge,
78697 geoCross: geoCross,
78698 geoEdgeEqual: geoEdgeEqual,
78699 geoEuclideanDistance: geoEuclideanDistance,
78700 geoExtent: geoExtent$$1,
78701 geoInterp: geoInterp,
78702 geoRawMercator: geoRawMercator,
78703 geoRoundCoords: geoRoundCoords,
78704 geoRotate: geoRotate,
78705 geoLatToMeters: geoLatToMeters,
78706 geoLineIntersection: geoLineIntersection,
78707 geoLonToMeters: geoLonToMeters,
78708 geoMetersToLat: geoMetersToLat,
78709 geoMetersToLon: geoMetersToLon,
78710 geoMetersToOffset: geoMetersToOffset,
78711 geoOffsetToMeters: geoOffsetToMeters,
78712 geoPathIntersections: geoPathIntersections,
78713 geoPathLength: geoPathLength,
78714 geoPointInPolygon: geoPointInPolygon,
78715 geoPolygonContainsPolygon: geoPolygonContainsPolygon,
78716 geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
78717 geoSphericalDistance: geoSphericalDistance,
78718 modeAddArea: modeAddArea$$1,
78719 modeAddLine: modeAddLine$$1,
78720 modeAddPoint: modeAddPoint$$1,
78721 modeBrowse: modeBrowse,
78722 modeDragNode: modeDragNode$$1,
78723 modeDrawArea: modeDrawArea,
78724 modeDrawLine: modeDrawLine,
78725 modeMove: modeMove$$1,
78726 modeRotate: modeRotate$$1,
78727 modeSave: modeSave$$1,
78728 modeSelect: modeSelect,
78729 operationCircularize: operationCircularize,
78730 operationContinue: operationContinue,
78731 operationDelete: operationDelete,
78732 operationDisconnect: operationDisconnect,
78733 operationMerge: operationMerge,
78734 operationMove: operationMove,
78735 operationOrthogonalize: operationOrthogonalize,
78736 operationReflectShort: operationReflectShort,
78737 operationReflectLong: operationReflectLong,
78738 operationReverse: operationReverse,
78739 operationRotate: operationRotate,
78740 operationSplit: operationSplit,
78741 operationStraighten: operationStraighten,
78742 osmChangeset: osmChangeset,
78743 osmEntity: osmEntity$$1,
78745 osmRelation: osmRelation,
78747 osmIntersection: osmIntersection,
78749 osmInferRestriction: osmInferRestriction,
78750 osmLanes: osmLanes,
78751 osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
78752 osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
78753 osmJoinWays: osmJoinWays,
78754 osmOneWayTags: osmOneWayTags,
78755 osmPavedTags: osmPavedTags,
78756 osmIsInterestingTag: osmIsInterestingTag,
78757 presetCategory: presetCategory,
78758 presetCollection: presetCollection,
78759 presetField: presetField,
78760 presetPreset: presetPreset,
78761 presetIndex: presetIndex,
78762 rendererBackgroundSource: rendererBackgroundSource,
78763 rendererBackground: rendererBackground,
78764 rendererFeatures: rendererFeatures,
78765 rendererMap: rendererMap,
78766 rendererTileLayer: rendererTileLayer,
78767 services: services,
78768 svgAreas: svgAreas$$1,
78769 svgDebug: svgDebug,
78773 svgLabels: svgLabels,
78774 svgLayers: svgLayers,
78775 svgLines: svgLines$$1,
78776 svgMapillaryImages: svgMapillaryImages,
78777 svgMapillarySigns: svgMapillarySigns,
78778 svgMidpoints: svgMidpoints$$1,
78779 svgOneWaySegments: svgOneWaySegments,
78782 svgPointTransform: svgPointTransform,
78783 svgPoints: svgPoints$$1,
78784 svgRelationMemberTags: svgRelationMemberTags,
78785 svgTagClasses: svgTagClasses,
78786 svgTurns: svgTurns,
78787 svgVertices: svgVertices$$1,
78788 uiFields: uiFields,
78789 uiFieldDefaultCheck: uiFieldCheck,
78790 uiFieldOnewayCheck: uiFieldCheck,
78791 uiFieldCheck: uiFieldCheck,
78792 uiFieldMultiCombo: uiFieldCombo,
78793 uiFieldNetworkCombo: uiFieldCombo,
78794 uiFieldSemiCombo: uiFieldCombo,
78795 uiFieldTypeCombo: uiFieldCombo,
78796 uiFieldCombo: uiFieldCombo,
78797 uiFieldUrl: uiFieldText,
78798 uiFieldNumber: uiFieldText,
78799 uiFieldTel: uiFieldText,
78800 uiFieldEmail: uiFieldText,
78801 uiFieldText: uiFieldText,
78802 uiFieldAccess: uiFieldAccess,
78803 uiFieldAddress: uiFieldAddress,
78804 uiFieldCycleway: uiFieldCycleway,
78805 uiFieldLanes: uiFieldLanes,
78806 uiFieldLocalized: uiFieldLocalized,
78807 uiFieldMaxspeed: uiFieldMaxspeed,
78808 uiFieldStructureRadio: uiFieldRadio,
78809 uiFieldRadio: uiFieldRadio,
78810 uiFieldRestrictions: uiFieldRestrictions,
78811 uiFieldTextarea: uiFieldTextarea,
78812 uiFieldWikipedia: uiFieldWikipedia,
78814 uiInfoPanels: uiInfoPanels,
78815 uiPanelBackground: uiPanelBackground,
78816 uiPanelHistory: uiPanelHistory,
78817 uiPanelLocation: uiPanelLocation,
78818 uiPanelMeasurement: uiPanelMeasurement,
78820 uiAccount: uiAccount,
78821 uiAttribution: uiAttribution,
78822 uiBackground: uiBackground,
78824 uiCommit: uiCommit,
78825 uiConfirm: uiConfirm,
78826 uiConflicts: uiConflicts,
78827 uiContributors: uiContributors,
78828 uiCurtain: uiCurtain,
78829 uiDisclosure: uiDisclosure,
78830 uiEditMenu: uiEditMenu,
78831 uiEntityEditor: uiEntityEditor,
78832 uiFeatureInfo: uiFeatureInfo,
78833 uiFeatureList: uiFeatureList,
78835 uiFullScreen: uiFullScreen,
78836 uiGeolocate: uiGeolocate,
78839 uiInspector: uiInspector,
78841 uiLoading: uiLoading,
78842 uiMapData: uiMapData,
78843 uiMapInMap: uiMapInMap,
78846 uiNotice: uiNotice,
78847 uiPreset: uiPreset,
78848 uiPresetIcon: uiPresetIcon,
78849 uiPresetList: uiPresetList,
78850 uiRadialMenu: uiRadialMenu,
78851 uiRawMemberEditor: uiRawMemberEditor,
78852 uiRawMembershipEditor: uiRawMembershipEditor,
78853 uiRawTagEditor: uiRawTagEditor,
78854 uiRestore: uiRestore,
78857 uiSelectionList: uiSelectionList,
78858 uiSidebar: uiSidebar,
78859 uiSourceSwitch: uiSourceSwitch,
78860 uiSpinner: uiSpinner,
78861 uiSplash: uiSplash,
78862 uiStatus: uiStatus,
78863 uiSuccess: uiSuccess,
78864 uiTagReference: uiTagReference,
78865 uiToggle: uiToggle,
78866 uiTooltipHtml: uiTooltipHtml,
78867 uiUndoRedo: uiUndoRedo,
78868 uiVersion: uiVersion,
78869 uiViewOnOSM: uiViewOnOSM,
78871 utilAsyncMap: utilAsyncMap,
78872 utilDisplayName: utilDisplayName,
78873 utilDisplayNameForPath: utilDisplayNameForPath,
78874 utilDisplayType: utilDisplayType,
78875 utilEditDistance: utilEditDistance,
78876 utilEntitySelector: utilEntitySelector,
78877 utilEntityOrMemberSelector: utilEntityOrMemberSelector,
78878 utilFastMouse: utilFastMouse,
78879 utilFunctor: utilFunctor,
78880 utilGetAllNodes: utilGetAllNodes,
78881 utilGetPrototypeOf: utilGetPrototypeOf,
78882 utilGetSetValue: utilGetSetValue,
78883 utilNoAuto: utilNoAuto,
78884 utilPrefixCSSProperty: utilPrefixCSSProperty,
78885 utilPrefixDOMProperty: utilPrefixDOMProperty,
78886 utilQsString: utilQsString,
78887 utilRebind: utilRebind,
78888 utilSetTransform: utilSetTransform,
78889 utilSessionMutex: utilSessionMutex,
78890 utilStringQs: utilStringQs,
78891 utilSuggestNames: utilSuggestNames,
78892 utilTagText: utilTagText,
78893 utilTriggerEvent: utilTriggerEvent,
78894 utilWrap: utilWrap,
78895 d3combobox: d3combobox,
78896 d3geoTile: d3geoTile,
78897 d3keybinding: d3keybinding,
78898 validationDeprecatedTag: validationDeprecatedTag,
78899 validationDisconnectedHighway: validationDisconnectedHighway,
78900 validationManyDeletions: validationManyDeletions,
78901 validationMissingTag: validationMissingTag,
78902 validationOldMultipolygon: validationOldMultipolygon,
78903 validationTagSuggestsArea: validationTagSuggestsArea
78909 //# sourceMappingURL=iD.js.map