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 type = "FeatureCollection";
18610 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]]]}}];
18611 var dataImperial = {
18616 var type$1 = "FeatureCollection";
18617 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]]]}}];
18618 var dataDriveLeft = {
18620 features: features$1
18623 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"},"infobox":{"selected":"{n} selected","geometry":"Geometry","closed":"closed","center":"Center","perimeter":"Perimeter","length":"Length","area":"Area","centroid":"Centroid","location":"Location","metric":"Metric","imperial":"Imperial"},"geometry":{"point":"point","vertex":"vertex","line":"line","area":"area","relation":"relation"},"geocoder":{"search":"Search worldwide...","no_results_visible":"No results in visible map area","no_results_worldwide":"No results found"},"geolocate":{"title":"Show My Location","locating":"Locating, please wait..."},"inspector":{"no_documentation_combination":"There is no documentation available for this tag combination","no_documentation_key":"There is no documentation available for this key","documentation_redirect":"This documentation has been redirected to a new page","show_more":"Show More","view_on_osm":"View on openstreetmap.org","all_fields":"All fields","all_tags":"All tags","all_members":"All members","all_relations":"All relations","new_relation":"New relation...","role":"Role","choose":"Select feature type","results":"{n} results for {search}","reference":"View on OpenStreetMap Wiki","back_tooltip":"Change feature","remove":"Remove","search":"Search","multiselect":"Selected features","unknown":"Unknown","incomplete":"<not downloaded>","feature_list":"Search features","edit":"Edit feature","check":{"yes":"Yes","no":"No","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","percent_brightness":"{opacity}% brightness","none":"None","best_imagery":"Best known imagery source for this location","switch":"Switch back to this background","custom":"Custom","custom_button":"Edit custom background","custom_prompt":"Enter a tile URL template. Valid tokens are {zoom}, {x}, {y} for Z/X/Y scheme and {u} for quadtile scheme.","fix_misalignment":"Adjust imagery offset","imagery_source_faq":"Where does this imagery come from?","reset":"reset","offset":"Drag anywhere in the gray area below to adjust the imagery offset, or enter the offset values in meters.","minimap":{"description":"Minimap","tooltip":"Show a zoomed out map to help locate the area currently displayed."}},"map_data":{"title":"Map Data","description":"Map Data","data_layers":"Data Layers","fill_area":"Fill Areas","map_features":"Map Features","autohidden":"These features have been automatically hidden because too many would be shown on the screen. You can zoom in to edit them."},"feature":{"points":{"description":"Points","tooltip":"Points of Interest"},"traffic_roads":{"description":"Traffic Roads","tooltip":"Highways, Streets, etc."},"service_roads":{"description":"Service Roads","tooltip":"Service Roads, Parking Aisles, Tracks, etc."},"paths":{"description":"Paths","tooltip":"Sidewalks, Foot Paths, Cycle Paths, etc."},"buildings":{"description":"Buildings","tooltip":"Buildings, Shelters, Garages, etc."},"landuse":{"description":"Landuse Features","tooltip":"Forests, Farmland, Parks, Residential, Commercial, etc."},"boundaries":{"description":"Boundaries","tooltip":"Administrative Boundaries"},"water":{"description":"Water Features","tooltip":"Rivers, Lakes, Ponds, Basins, etc."},"rail":{"description":"Rail Features","tooltip":"Railways"},"power":{"description":"Power Features","tooltip":"Power Lines, Power Plants, Substations, etc."},"past_future":{"description":"Past/Future","tooltip":"Proposed, Construction, Abandoned, Demolished, etc."},"others":{"description":"Others","tooltip":"Everything Else"}},"area_fill":{"wireframe":{"description":"No Fill (Wireframe)","tooltip":"Enabling wireframe mode makes it easy to see the background imagery."},"partial":{"description":"Partial Fill","tooltip":"Areas are drawn with fill only around their inner edges. (Recommended for beginner mappers)"},"full":{"description":"Full Fill","tooltip":"Areas are drawn fully filled."}},"restore":{"heading":"You have unsaved changes","description":"Do you wish to restore unsaved changes from a previous editing session?","restore":"Restore","reset":"Reset"},"save":{"title":"Save","help":"Review your changes and upload them to OpenStreetMap, making them visible to other users.","no_changes":"No changes to save.","error":"Errors occurred while trying to save","status_code":"Server returned status code {code}","unknown_error_details":"Please ensure you are connected to the internet.","uploading":"Uploading changes to OpenStreetMap...","unsaved_changes":"You have unsaved changes","conflict":{"header":"Resolve conflicting edits","count":"Conflict {num} of {total}","previous":"< Previous","next":"Next >","keep_local":"Keep mine","keep_remote":"Use theirs","restore":"Restore","delete":"Leave Deleted","download_changes":"Or download your changes.","done":"All conflicts resolved!","help":"Another user changed some of the same map features you changed.\nClick on each feature below for more details about the conflict, and choose whether to keep\nyour changes or the other user's changes.\n"}},"merge_remote_changes":{"conflict":{"deleted":"This feature has been deleted by {user}.","location":"This feature was moved by both you and {user}.","nodelist":"Nodes were changed by both you and {user}.","memberlist":"Relation members were changed by both you and {user}.","tags":"You changed the <b>{tag}</b> tag to \"{local}\" and {user} changed it to \"{remote}\"."}},"success":{"edited_osm":"Edited OSM!","just_edited":"You just edited OpenStreetMap!","view_on_osm":"View on OSM","facebook":"Share on Facebook","twitter":"Share on Twitter","google":"Share on Google+","help_html":"Your changes should appear in the \"Standard\" layer in a few minutes. Other layers, and certain features, may take longer.","help_link_text":"Details","help_link_url":"https://wiki.openstreetmap.org/wiki/FAQ#I_have_just_made_some_changes_to_the_map._How_do_I_get_to_see_my_changes.3F"},"confirm":{"okay":"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","help":"# Help\n\nThis is an editor for [OpenStreetMap](http://www.openstreetmap.org/), the\nfree and editable map of the world. You can use it to add and update\ndata in your area, making an open-source and open-data map of the world\nbetter for everyone.\n\nEdits that you make on this map will be visible to everyone who uses\nOpenStreetMap. In order to make an edit, you'll need to\n[log in](https://www.openstreetmap.org/login).\n\nThe [iD editor](http://ideditor.com/) is a collaborative project with [source\ncode available on GitHub](https://github.com/openstreetmap/iD).\n","editing_saving":"# Editing & Saving\n\nThis editor is designed to work primarily online, and you're accessing\nit through a website right now.\n\n### Selecting Features\n\nTo select a map feature, like a road or point of interest, click\non it on the map. This will highlight the selected feature, open a panel with\ndetails about it, and show a menu of things you can do with the feature.\n\nTo select multiple features, hold down the 'Shift' key. Then either click\non the features you want to select, or drag on the map to draw a rectangle.\nThis will draw a box and select all the points within it.\n\n### Saving Edits\n\nWhen you make changes like editing roads, buildings, and places, these are\nstored locally until you save them to the server. Don't worry if you make\na mistake - you can undo changes by clicking the undo button, and redo\nchanges by clicking the redo button.\n\nClick 'Save' to finish a group of edits - for instance, if you've completed\nan area of town and would like to start on a new area. You'll have a chance\nto review what you've done, and the editor supplies helpful suggestions\nand warnings if something doesn't seem right about the changes.\n\nIf everything looks good, you can enter a short comment explaining the change\nyou made, and click 'Save' again to post the changes\nto [OpenStreetMap.org](http://www.openstreetmap.org/), where they are visible\nto all other users and available for others to build and improve upon.\n\nIf you can't finish your edits in one sitting, you can leave the editor\nwindow and come back (on the same browser and computer), and the\neditor application will offer to restore your work.\n\n### Using the editor\n\nA list of available keyboard shortcuts can be found [here](http://wiki.openstreetmap.org/wiki/ID/Shortcuts).\n","roads":"# Roads\n\nYou can create, fix, and delete roads with this editor. Roads can be all\nkinds: paths, highways, trails, cycleways, and more - any often-crossed\nsegment should be mappable.\n\n### Selecting\n\nClick on a road to select it. An outline should become visible, along\nwith a small tools menu on the map and a sidebar showing more information\nabout the road.\n\n### Modifying\n\nOften you'll see roads that aren't aligned to the imagery behind them\nor to a GPS track. You can adjust these roads so they are in the correct\nplace.\n\nFirst click on the road you want to change. This will highlight it and show\ncontrol points along it that you can drag to better locations. If\nyou want to add new control points for more detail, double-click a part\nof the road without a node, and one will be added.\n\nIf the road connects to another road, but doesn't properly connect on\nthe map, you can drag one of its control points onto the other road in\norder to join them. Having roads connect is important for the map\nand essential for providing driving directions.\n\nYou can also click the 'Move' tool or press the `M` shortcut key to move the entire road at\none time, and then click again to save that movement.\n\n### Deleting\n\nIf a road is entirely incorrect - you can see that it doesn't exist in satellite\nimagery and ideally have confirmed locally that it's not present - you can delete\nit, which removes it from the map. Be cautious when deleting features -\nlike any other edit, the results are seen by everyone and satellite imagery\nis often out of date, so the road could simply be newly built.\n\nYou can delete a road by clicking on it to select it, then clicking the\ntrash can icon or pressing the 'Delete' key.\n\n### Creating\n\nFound somewhere there should be a road but there isn't? Click the 'Line'\nicon in the top-left of the editor or press the shortcut key `2` to start drawing\na line.\n\nClick on the start of the road on the map to start drawing. If the road\nbranches off from an existing road, start by clicking on the place where they connect.\n\nThen click on points along the road so that it follows the right path, according\nto satellite imagery or GPS. If the road you are drawing crosses another road, connect\nit by clicking on the intersection point. When you're done drawing, double-click\nor press 'Return' or 'Enter' on your keyboard.\n","gps":"# GPS\n\nCollected GPS traces are one valuable source of data for OpenStreetMap. This editor\nsupports local traces - `.gpx` files on your local computer. You can collect\nthis kind of GPS trace with a number of smartphone applications as well as\npersonal GPS hardware.\n\nFor information on how to perform a GPS survey, read\n[Mapping with a smartphone, GPS, or paper](http://learnosm.org/en/mobile-mapping/).\n\nTo use a GPX track for mapping, drag and drop the GPX file onto the map\neditor. If it's recognized, it will be added to the map as a bright purple\nline. Click on the 'Map Data' menu on the right side to enable,\ndisable, or zoom to this new GPX-powered layer.\n\nThe GPX track isn't directly uploaded to OpenStreetMap - the best way to\nuse it is to draw on the map, using it as a guide for the new features that\nyou add, and also to [upload it to OpenStreetMap](http://www.openstreetmap.org/trace/create)\nfor other users to use.\n","imagery":"# Imagery\n\nAerial imagery is an important resource for mapping. A combination of\nairplane flyovers, satellite views, and freely-compiled sources are available\nin the editor under the 'Background Settings' menu on the right.\n\nBy default a [Bing Maps](http://www.bing.com/maps/) satellite layer is\npresented in the editor, but as you pan and zoom the map to new geographical\nareas, new sources will become available. Some countries, like the United\nStates, France, and Denmark have very high-quality imagery available for some areas.\n\nImagery is sometimes offset from the map data because of a mistake on the\nimagery provider's side. If you see a lot of roads shifted from the background,\ndon't immediately move them all to match the background. Instead you can adjust\nthe imagery so that it matches the existing data by clicking 'Fix alignment' at\nthe bottom of the Background Settings UI.\n","addresses":"# Addresses\n\nAddresses are some of the most useful information for the map.\n\nAlthough addresses are often represented as parts of streets, in OpenStreetMap\nthey're recorded as attributes of buildings and places along streets.\n\nYou can add address information to places mapped as building outlines\nas well as those mapped as single points. The optimal source of address\ndata is from an on-the-ground survey or personal knowledge - as with any\nother feature, copying from commercial sources like Google Maps is strictly\nforbidden.\n","inspector":"# Using the Inspector\n\nThe inspector is the section on the left side of the page that allows you to\nedit the details of the selected feature.\n\n### Selecting a Feature Type\n\nAfter you add a point, line, or area, you can choose what type of feature it\nis, like whether it's a highway or residential road, supermarket or cafe.\nThe inspector will display buttons for common feature types, and you can\nfind others by typing what you're looking for in the search box.\n\nClick the 'i' in the bottom-right-hand corner of a feature type button to\nlearn more about it. Click a button to choose that type.\n\n### Using Forms and Editing Tags\n\nAfter you choose a feature type, or when you select a feature that already\nhas a type assigned, the inspector will display fields with details about\nthe feature like its name and address.\n\nBelow the fields you see, you can click the 'Add field' dropdown to add\nother details, like a Wikipedia link, wheelchair access, and more.\n\nAt the bottom of the inspector, click 'Additional tags' to add arbitrary\nother tags to the element. [Taginfo](http://taginfo.openstreetmap.org/) is a\ngreat resource for learn more about popular tag combinations.\n\nChanges you make in the inspector are automatically applied to the map.\nYou can undo them at any time by clicking the 'Undo' button.\n","buildings":"# Buildings\n\nOpenStreetMap is the world's largest database of buildings. You can create\nand improve this database.\n\n### Selecting\n\nYou can select a building by clicking on its border. This will highlight the\nbuilding and open a small tools menu and a sidebar showing more information\nabout the building.\n\n### Modifying\n\nSometimes buildings are incorrectly placed or have incorrect tags.\n\nTo move an entire building, select it, then click the 'Move' tool. Move your\nmouse to shift the building, and click when it's correctly placed.\n\nTo fix the specific shape of a building, click and drag the nodes that form\nits border into better places.\n\n### Creating\n\nOne of the main questions around adding buildings to the map is that\nOpenStreetMap records buildings both as shapes and points. The rule of thumb\nis to _map a building as a shape whenever possible_, and map companies, homes,\namenities, and other things that operate out of buildings as points placed\nwithin the building shape.\n\nStart drawing a building as a shape by clicking the 'Area' button in the top\nleft of the interface, and end it either by pressing 'Return' on your keyboard\nor clicking on the first node drawn to close the shape.\n\n### Deleting\n\nIf a building is entirely incorrect - you can see that it doesn't exist in satellite\nimagery and ideally have confirmed locally that it's not present - you can delete\nit, which removes it from the map. Be cautious when deleting features -\nlike any other edit, the results are seen by everyone and satellite imagery\nis often out of date, so the building could simply be newly built.\n\nYou can delete a building by clicking on it to select it, then clicking the\ntrash can icon or pressing the 'Delete' key.\n","relations":"# Relations\n\nA relation is a special type of feature in OpenStreetMap that groups together\nother features. For example, two common types of relations are *route relations*,\nwhich group together sections of road that belong to a specific freeway or\nhighway, and *multipolygons*, which group together several lines that define\na complex area (one with several pieces or holes in it like a donut).\n\nThe group of features in a relation are called *members*. In the sidebar, you can\nsee which relations a feature is a member of, and click on a relation there\nto select the it. When the relation is selected, you can see all of its\nmembers listed in the sidebar and highlighted on the map.\n\nFor the most part, iD will take care of maintaining relations automatically\nwhile you edit. The main thing you should be aware of is that if you delete a\nsection of road to redraw it more accurately, you should make sure that the\nnew section is a member of the same relations as the original.\n\n## Editing Relations\n\nIf you want to edit relations, here are the basics.\n\nTo add a feature to a relation, select the feature, click the \"+\" button in the\n\"All relations\" section of the sidebar, and select or type the name of the relation.\n\nTo create a new relation, select the first feature that should be a member,\nclick the \"+\" button in the \"All relations\" section, and select \"New relation...\".\n\nTo remove a feature from a relation, select the feature and click the trash\nbutton next to the relation you want to remove it from.\n\nYou can create multipolygons with holes using the \"Merge\" tool. Draw two areas (inner\nand outer), hold the Shift key and click on each of them to select them both, and then\nclick the \"Merge\" (+) button.\n"},"intro":{"done":"done","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.","save":"Don't forget to regularly save your changes!","start":"Start mapping!"}},"presets":{"categories":{"category-barrier":{"name":"Barrier Features"},"category-building":{"name":"Building Features"},"category-golf":{"name":"Golf Features"},"category-landuse":{"name":"Land Use Features"},"category-natural-area":{"name":"Natural Features"},"category-natural-line":{"name":"Natural Features"},"category-natural-point":{"name":"Natural Features"},"category-path":{"name":"Path Features"},"category-rail":{"name":"Rail Features"},"category-restriction":{"name":"Restriction Features"},"category-road":{"name":"Road Features"},"category-route":{"name":"Route Features"},"category-water-area":{"name":"Water Features"},"category-water-line":{"name":"Water Features"}},"fields":{"access_simple":{"label":"Allowed Access"},"access_toilets":{"label":"Access"},"access":{"label":"Allowed Access","placeholder":"Not Specified","types":{"access":"All","foot":"Foot","motor_vehicle":"Motor Vehicles","bicycle":"Bicycles","horse":"Horses"},"options":{"yes":{"title":"Allowed","description":"Access permitted by law; a right of way"},"no":{"title":"Prohibited","description":"Access not permitted to the general public"},"permissive":{"title":"Permissive","description":"Access permitted until such time as the owner revokes the permission"},"private":{"title":"Private","description":"Access permitted only with permission of the owner on an individual basis"},"designated":{"title":"Designated","description":"Access permitted according to signs or specific local laws"},"destination":{"title":"Destination","description":"Access permitted only to reach a destination"},"dismount":{"title":"Dismount","description":"Access permitted but rider must dismount"}}},"address":{"label":"Address","placeholders":{"block_number":"Block Number","block_number!jp":"Block No.","city":"City","city!jp":"City/Town/Village/Tokyo Special Ward","city!vn":"City/Town","conscriptionnumber":"123","country":"Country","county":"County","county!jp":"District","district":"District","district!vn":"Arrondissement/Town/District","floor":"Floor","hamlet":"Hamlet","housename":"Housename","housenumber":"123","housenumber!jp":"Building No./Lot No.","neighbourhood":"Neighbourhood","neighbourhood!jp":"Chōme/Aza/Koaza","place":"Place","postcode":"Postcode","province":"Province","province!jp":"Prefecture","quarter":"Quarter","quarter!jp":"Ōaza/Machi","state":"State","street":"Street","subdistrict":"Subdistrict","subdistrict!vn":"Ward/Commune/Townlet","suburb":"Suburb","suburb!jp":"Ward"}},"admin_level":{"label":"Admin Level"},"aerialway":{"label":"Type"},"aerialway/access":{"label":"Access","options":{"entry":"Entry","exit":"Exit","both":"Both"}},"aerialway/bubble":{"label":"Bubble"},"aerialway/capacity":{"label":"Capacity (per hour)","placeholder":"500, 2500, 5000..."},"aerialway/duration":{"label":"Duration (minutes)","placeholder":"1, 2, 3..."},"aerialway/heating":{"label":"Heated"},"aerialway/occupancy":{"label":"Occupancy","placeholder":"2, 4, 8..."},"aerialway/summer/access":{"label":"Access (summer)","options":{"entry":"Entry","exit":"Exit","both":"Both"}},"aeroway":{"label":"Type"},"amenity":{"label":"Type"},"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 Ramp"},"lamp_type":{"label":"Type"},"landuse":{"label":"Type"},"lanes":{"label":"Lanes","placeholder":"1, 2, 3..."},"layer":{"label":"Layer"},"leaf_cycle_singular":{"label":"Leaf Cycle","options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous"}},"leaf_cycle":{"label":"Leaf Cycle","options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous","mixed":"Mixed"}},"leaf_type_singular":{"label":"Leaf Type","options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","leafless":"Leafless"}},"leaf_type":{"label":"Leaf Type","options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","mixed":"Mixed","leafless":"Leafless"}},"leisure":{"label":"Type"},"length":{"label":"Length (Meters)"},"level":{"label":"Level"},"levels":{"label":"Levels","placeholder":"2, 4, 6..."},"lit":{"label":"Lit"},"location":{"label":"Location"},"man_made":{"label":"Type"},"map_size":{"label":"Coverage"},"map_type":{"label":"Type"},"maxheight":{"label":"Max Height","placeholder":"4, 4.5, 5, 14'0\", 14'6\", 15'0\""},"maxspeed":{"label":"Speed Limit","placeholder":"40, 50, 60..."},"maxstay":{"label":"Max Stay"},"mtb/scale":{"label":"Mountain Biking Difficulty","placeholder":"0, 1, 2, 3...","options":{"0":"0: Solid gravel/packed earth, no obstacles, wide curves","1":"1: Some loose surface, small obstacles, wide curves","2":"2: Much loose surface, large obstacles, easy hairpins","3":"3: Slippery surface, large obstacles, tight hairpins","4":"4: Loose surface or boulders, dangerous hairpins","5":"5: Maximum difficulty, boulder fields, landslides","6":"6: Not rideable except by the very best mountain bikers"}},"mtb/scale/imba":{"label":"IMBA Trail Difficulty","placeholder":"Easy, Medium, Difficult...","options":{"0":"Easiest (white circle)","1":"Easy (green circle)","2":"Medium (blue square)","3":"Difficult (black diamond)","4":"Extremely Difficult (double black diamond)"}},"mtb/scale/uphill":{"label":"Mountain Biking Uphill Difficulty","placeholder":"0, 1, 2, 3...","options":{"0":"0: Avg. incline <10%, gravel/packed earth, no obstacles","1":"1: Avg. incline <15%, gravel/packed earth, few small objects","2":"2: Avg. incline <20%, stable surface, fistsize rocks/roots","3":"3: Avg. incline <25%, variable surface, fistsize rocks/branches","4":"4: Avg. incline <30%, poor condition, big rocks/branches","5":"5: Very steep, bike generally needs to be pushed or carried"}},"name":{"label":"Name","placeholder":"Common name (if any)"},"natural":{"label":"Natural"},"network_bicycle":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lcn":"Local","rcn":"Regional","ncn":"National","icn":"International"}},"network_foot":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lwn":"Local","rwn":"Regional","nwn":"National","iwn":"International"}},"network_horse":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lhn":"Local","rhn":"Regional","nhn":"National","ihn":"International"}},"network_road":{"label":"Network"},"network":{"label":"Network"},"note":{"label":"Note"},"office":{"label":"Type"},"oneway_yes":{"label":"One Way","options":{"undefined":"Assumed to be Yes","yes":"Yes","no":"No"}},"oneway":{"label":"One Way","options":{"undefined":"Assumed to be No","yes":"Yes","no":"No"}},"opening_hours":{"label":"Hours"},"operator":{"label":"Operator"},"outdoor_seating":{"label":"Outdoor Seating"},"par":{"label":"Par","placeholder":"3, 4, 5..."},"parallel_direction":{"label":"Direction","options":{"forward":"Forward","backward":"Backward"}},"park_ride":{"label":"Park and Ride"},"parking":{"label":"Type","options":{"surface":"Surface","multi-storey":"Multilevel","underground":"Underground","sheds":"Sheds","carports":"Carports","garage_boxes":"Garage Boxes","lane":"Roadside Lane"}},"payment_multi":{"label":"Payment Types"},"phone":{"label":"Phone","placeholder":"+31 42 123 4567"},"piste/difficulty":{"label":"Difficulty","placeholder":"Easy, Intermediate, Advanced...","options":{"novice":"Novice (instructional)","easy":"Easy (green circle)","intermediate":"Intermediate (blue square)","advanced":"Advanced (black diamond)","expert":"Expert (double black diamond)","freeride":"Freeride (off-piste)","extreme":"Extreme (climbing equipment required)"}},"piste/grooming":{"label":"Grooming","options":{"classic":"Classic","mogul":"Mogul","backcountry":"Backcountry","classic+skating":"Classic and Skating","scooter":"Scooter/Snowmobile","skating":"Skating"}},"piste/type":{"label":"Type","options":{"downhill":"Downhill","nordic":"Nordic","skitour":"Skitour","sled":"Sled","hike":"Hike","sleigh":"Sleigh","ice_skate":"Ice Skate","snow_park":"Snow Park","playground":"Playground"}},"place":{"label":"Type"},"plant":{"label":"Plant"},"population":{"label":"Population"},"power_supply":{"label":"Power Supply"},"power":{"label":"Type"},"produce":{"label":"Produce"},"product":{"label":"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/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":"beer,bier"},"craft/carpenter":{"name":"Carpenter","terms":"woodworker"},"craft/carpet_layer":{"name":"Carpet Layer","terms":""},"craft/caterer":{"name":"Caterer","terms":""},"craft/clockmaker":{"name":"Clockmaker","terms":""},"craft/confectionery":{"name":"Confectionery","terms":"sweets,candy"},"craft/dressmaker":{"name":"Dressmaker","terms":"seamstress"},"craft/electrician":{"name":"Electrician","terms":"power,wire"},"craft/gardener":{"name":"Gardener","terms":"landscaper,grounds keeper"},"craft/glaziery":{"name":"Glaziery","terms":"glass,stained-glass,window"},"craft/handicraft":{"name":"Handicraft","terms":""},"craft/hvac":{"name":"HVAC","terms":"heat*,vent*,air conditioning"},"craft/insulator":{"name":"Insulator","terms":""},"craft/key_cutter":{"name":"Key Cutter","terms":""},"craft/metal_construction":{"name":"Metal Construction","terms":""},"craft/painter":{"name":"Painter","terms":""},"craft/photographer":{"name":"Photographer","terms":""},"craft/photographic_laboratory":{"name":"Photographic Laboratory","terms":"film"},"craft/plasterer":{"name":"Plasterer","terms":""},"craft/plumber":{"name":"Plumber","terms":"pipe"},"craft/pottery":{"name":"Pottery","terms":"ceramic"},"craft/rigger":{"name":"Rigger","terms":""},"craft/roofer":{"name":"Roofer","terms":""},"craft/saddler":{"name":"Saddler","terms":""},"craft/sailmaker":{"name":"Sailmaker","terms":""},"craft/sawmill":{"name":"Sawmill","terms":"lumber"},"craft/scaffolder":{"name":"Scaffolder","terms":""},"craft/sculpter":{"name":"Sculpter","terms":""},"craft/shoemaker":{"name":"Shoemaker","terms":"cobbler"},"craft/stonemason":{"name":"Stonemason","terms":"masonry"},"craft/sweep":{"name":"Chimney Sweep","terms":""},"craft/tiler":{"name":"Tiler","terms":""},"craft/tinsmith":{"name":"Tinsmith","terms":""},"craft/upholsterer":{"name":"Upholsterer","terms":""},"craft/watchmaker":{"name":"Watchmaker","terms":""},"craft/window_construction":{"name":"Window Construction","terms":"glass"},"craft/winery":{"name":"Winery","terms":""},"embankment":{"name":"Embankment","terms":""},"emergency/designated":{"name":"Emergency Access Designated","terms":""},"emergency/destination":{"name":"Emergency Access Destination","terms":""},"emergency/no":{"name":"Emergency Access No","terms":""},"emergency/official":{"name":"Emergency Access Official","terms":""},"emergency/private":{"name":"Emergency Access Private","terms":""},"emergency/yes":{"name":"Emergency Access Yes","terms":""},"emergency/ambulance_station":{"name":"Ambulance Station","terms":"EMS,EMT,rescue"},"emergency/defibrillator":{"name":"Defibrillator","terms":"AED"},"emergency/fire_hydrant":{"name":"Fire Hydrant","terms":"fire plug"},"emergency/phone":{"name":"Emergency Phone","terms":""},"entrance":{"name":"Entrance/Exit","terms":""},"footway/crossing":{"name":"Street Crossing","terms":""},"footway/crosswalk":{"name":"Pedestrian Crosswalk","terms":"zebra crossing"},"footway/sidewalk":{"name":"Sidewalk","terms":""},"ford":{"name":"Ford","terms":""},"golf/bunker":{"name":"Sand Trap","terms":"hazard,bunker"},"golf/fairway":{"name":"Fairway","terms":""},"golf/green":{"name":"Putting Green","terms":""},"golf/hole":{"name":"Golf Hole","terms":""},"golf/lateral_water_hazard_area":{"name":"Lateral Water Hazard","terms":""},"golf/lateral_water_hazard_line":{"name":"Lateral Water Hazard","terms":""},"golf/rough":{"name":"Rough","terms":""},"golf/tee":{"name":"Tee Box","terms":"teeing ground"},"golf/water_hazard_area":{"name":"Water Hazard","terms":""},"golf/water_hazard_line":{"name":"Water Hazard","terms":""},"healthcare/blood_donation":{"name":"Blood Donor Center","terms":"blood bank,blood donation,blood transfusion,apheresis,plasmapheresis,plateletpheresis,stem cell donation"},"highway/bridleway":{"name":"Bridle Path","terms":"bridleway,equestrian,horse"},"highway/bus_stop":{"name":"Bus Stop","terms":""},"highway/corridor":{"name":"Indoor Corridor","terms":"gallery,hall,hallway,indoor,passage,passageway"},"highway/crossing":{"name":"Street Crossing","terms":""},"highway/crosswalk":{"name":"Pedestrian Crosswalk","terms":"zebra crossing"},"highway/cycleway":{"name":"Cycle Path","terms":"bike"},"highway/footway":{"name":"Foot Path","terms":"hike,hiking,trackway,trail,walk"},"highway/give_way":{"name":"Yield Sign","terms":"give way,yield,sign"},"highway/living_street":{"name":"Living Street","terms":""},"highway/mini_roundabout":{"name":"Mini-Roundabout","terms":""},"highway/motorway_junction":{"name":"Motorway Junction / Exit","terms":""},"highway/motorway_link":{"name":"Motorway Link","terms":"ramp,on ramp,off ramp"},"highway/motorway":{"name":"Motorway","terms":"autobahn,expressway,freeway,highway,interstate,parkway,thruway,turnpike"},"highway/path":{"name":"Path","terms":"hike,hiking,trackway,trail,walk"},"highway/pedestrian":{"name":"Pedestrian Street","terms":""},"highway/primary_link":{"name":"Primary Link","terms":"ramp,on ramp,off ramp"},"highway/primary":{"name":"Primary Road","terms":""},"highway/raceway":{"name":"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":""},"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"},"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":""},"power/line":{"name":"Power Line","terms":""},"power/minor_line":{"name":"Minor Power Line","terms":""},"power/plant":{"name":"Power Station Grounds","terms":"coal,gas,generat*,hydro,nuclear,power,station"},"power/pole":{"name":"Power Pole","terms":""},"power/substation":{"name":"Substation","terms":""},"power/tower":{"name":"High-Voltage Tower","terms":""},"power/transformer":{"name":"Transformer","terms":""},"public_transport/platform":{"name":"Platform","terms":""},"public_transport/stop_position":{"name":"Stop Position","terms":""},"railway/abandoned":{"name":"Abandoned Railway","terms":""},"railway/crossing":{"name":"Railway Crossing (Path)","terms":"crossing,pedestrian crossing,railroad crossing,level crossing,grade crossing,path through railroad,train crossing"},"railway/disused":{"name":"Disused Railway","terms":""},"railway/funicular":{"name":"Funicular","terms":"venicular,cliff railway,cable car,cable railway,funicular railway"},"railway/halt":{"name":"Railway Halt","terms":"break,interrupt,rest,wait,interruption"},"railway/level_crossing":{"name":"Railway Crossing (Road)","terms":"crossing,railroad crossing,level crossing,grade crossing,road through railroad,train crossing"},"railway/monorail":{"name":"Monorail","terms":""},"railway/narrow_gauge":{"name":"Narrow Gauge Rail","terms":"narrow gauge railway,narrow gauge railroad"},"railway/platform":{"name":"Railway Platform","terms":""},"railway/rail":{"name":"Rail","terms":""},"railway/station":{"name":"Railway Station","terms":"train station,station"},"railway/subway_entrance":{"name":"Subway Entrance","terms":""},"railway/subway":{"name":"Subway","terms":""},"railway/tram_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/art":{"name":"Art Store","terms":"art*,exhibit*,gallery"},"shop/baby_goods":{"name":"Baby Goods Store","terms":""},"shop/bag":{"name":"Bag/Luggage Store","terms":"handbag,purse"},"shop/bakery":{"name":"Bakery","terms":""},"shop/bathroom_furnishing":{"name":"Bathroom Furnishing Store","terms":""},"shop/beauty":{"name":"Beauty Shop","terms":"spa,salon,tanning"},"shop/beauty/nails":{"name":"Nail Salon","terms":"manicure,pedicure"},"shop/beauty/tanning":{"name":"Tanning Salon","terms":""},"shop/bed":{"name":"Bedding/Mattress Store","terms":""},"shop/beverages":{"name":"Beverage Store","terms":""},"shop/bicycle":{"name":"Bicycle Shop","terms":"bike,repair"},"shop/bookmaker":{"name":"Bookmaker","terms":"betting"},"shop/books":{"name":"Book Store","terms":""},"shop/boutique":{"name":"Boutique","terms":""},"shop/butcher":{"name":"Butcher","terms":"meat"},"shop/candles":{"name":"Candle Shop","terms":""},"shop/car_parts":{"name":"Car Parts Store","terms":"auto"},"shop/car_repair":{"name":"Car Repair Shop","terms":"auto,garage,service"},"shop/car":{"name":"Car Dealership","terms":"auto"},"shop/carpet":{"name":"Carpet Store","terms":"rug"},"shop/charity":{"name":"Charity Store","terms":"thrift,op shop,nonprofit"},"shop/cheese":{"name":"Cheese Store","terms":""},"shop/chemist":{"name":"Drugstore","terms":"med*,drug*,gift"},"shop/chocolate":{"name":"Chocolate Store","terms":""},"shop/clothes":{"name":"Clothing Store","terms":""},"shop/coffee":{"name":"Coffee Store","terms":""},"shop/computer":{"name":"Computer Store","terms":""},"shop/confectionery":{"name":"Candy Store","terms":""},"shop/convenience":{"name":"Convenience Store","terms":""},"shop/copyshop":{"name":"Copy Store","terms":""},"shop/cosmetics":{"name":"Cosmetics Store","terms":""},"shop/craft":{"name":"Arts and Crafts Store","terms":"art*,paint*,frame"},"shop/curtain":{"name":"Curtain Store","terms":"drape*,window"},"shop/dairy":{"name":"Dairy Store","terms":"milk,egg,cheese"},"shop/deli":{"name":"Deli","terms":"lunch,meat,sandwich"},"shop/department_store":{"name":"Department Store","terms":""},"shop/doityourself":{"name":"DIY Store","terms":""},"shop/dry_cleaning":{"name":"Dry Cleaner","terms":""},"shop/e-cigarette":{"name":"E-Cigarette Shop","terms":"electronic,vapor"},"shop/electronics":{"name":"Electronics Store","terms":"appliance,audio,computer,tv"},"shop/erotic":{"name":"Erotic Store","terms":"sex,porn"},"shop/fabric":{"name":"Fabric Store","terms":"sew"},"shop/farm":{"name":"Produce Stand","terms":"farm shop,farm stand"},"shop/fashion":{"name":"Fashion Store","terms":""},"shop/florist":{"name":"Florist","terms":"flower"},"shop/frame":{"name":"Framing Shop","terms":"art*,paint*,photo*,frame"},"shop/funeral_directors":{"name":"Funeral Home","terms":"undertaker,memorial home"},"shop/furnace":{"name":"Furnace Store","terms":"oven,stove"},"shop/furniture":{"name":"Furniture Store","terms":"chair,sofa,table"},"shop/garden_centre":{"name":"Garden Center","terms":"landscape,mulch,shrub,tree"},"shop/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":""}}}};
18625 var dataImagery = [{"id":"sjcgis.org-Aerials_2013_WM","name":"2013 aerial imagery for San Juan County WA","type":"tms","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/Aerials_2013_WM/MapServer/tile/{zoom}/{y}/{x}","description":"Public domain aerial imagery taken in May/June 2013 from San Juan County, WA. Resolution is 9 inch.","scaleExtent":[0,19],"polygon":[[[-123.02167396992,48.44667085335],[-122.9466579482,48.44780949945],[-122.90151100606,48.41306930778],[-122.80263405293,48.40771378918],[-122.79199104756,48.44279926564],[-122.8088138625,48.47865708877],[-122.73911934346,48.49572334021],[-122.78546791524,48.62160819278],[-122.73087959737,48.6361306644],[-122.75559883565,48.71207854113],[-122.95747261494,48.71592956034],[-122.97086220235,48.695765074],[-122.99970131367,48.69780454658],[-123.00347786397,48.73427448605],[-123.04330330342,48.74310484148],[-123.0762622878,48.70528190578],[-123.08484535664,48.66334903433],[-123.12844734639,48.66380254936],[-123.22698097676,48.70301615666],[-123.24655037373,48.68352650341],[-123.17445259541,48.64701977542],[-123.21513634175,48.60106537642],[-123.21393471211,48.57335906966],[-123.18080406636,48.56574853208],[-123.16621284932,48.52006125122],[-123.10235481709,48.47683634964],[-123.02167396992,48.44667085335]],[[-122.98339348286,48.78214357977],[-122.93498497456,48.76653172572],[-122.91181068867,48.73857664785],[-122.80229073018,48.73982194177],[-122.81945686787,48.75498940888],[-122.93429832906,48.79571515892],[-122.98373680562,48.79435816618],[-122.98339348286,48.78214357977]]]},{"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}","description":"Public domain aerial imagery taken in May, June, and July from San Juan County, WA. Resolution is 6 inch countywide.","scaleExtent":[0,19],"polygon":[[[-123.02167396992,48.44667085335],[-122.9466579482,48.44780949945],[-122.90151100606,48.41306930778],[-122.80263405293,48.40771378918],[-122.79199104756,48.44279926564],[-122.8088138625,48.47865708877],[-122.73911934346,48.49572334021],[-122.78546791524,48.62160819278],[-122.73087959737,48.6361306644],[-122.75559883565,48.71207854113],[-122.95747261494,48.71592956034],[-122.97086220235,48.695765074],[-122.99970131367,48.69780454658],[-123.00347786397,48.73427448605],[-123.04330330342,48.74310484148],[-123.0762622878,48.70528190578],[-123.08484535664,48.66334903433],[-123.12844734639,48.66380254936],[-123.22698097676,48.70301615666],[-123.24655037373,48.68352650341],[-123.17445259541,48.64701977542],[-123.21513634175,48.60106537642],[-123.21393471211,48.57335906966],[-123.18080406636,48.56574853208],[-123.16621284932,48.52006125122],[-123.10235481709,48.47683634964],[-123.02167396992,48.44667085335]],[[-122.98339348286,48.78214357977],[-122.93498497456,48.76653172572],[-122.91181068867,48.73857664785],[-122.80229073018,48.73982194177],[-122.81945686787,48.75498940888],[-122.93429832906,48.79571515892],[-122.98373680562,48.79435816618],[-122.98339348286,48.78214357977]]],"best":true},{"id":"OS7","name":"7th Series (OS7)","type":"tms","template":"http://ooc.openstreetmap.org/os7/{zoom}/{x}/{y}.jpg","polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]]},{"id":"AGRI-black_and_white-2.5m","name":"AGRI black-and-white 2.5m","type":"tms","template":"http://agri.openstreetmap.org/{zoom}/{x}/{y}.png","polygon":[[[112.28778,-28.784589],[112.71488,-31.13894],[114.11263,-34.178287],[113.60788,-37.39012],[117.17992,-37.451794],[119.31538,-37.42096],[121.72262,-36.708394],[123.81925,-35.76893],[125.9547,-34.3066],[127.97368,-33.727398],[130.07031,-33.24166],[130.10913,-33.888704],[131.00214,-34.049705],[131.0798,-34.72257],[132.28342,-35.39],[134.18591,-35.61126],[133.8753,-37.1119],[134.8459,-37.6365],[139.7769,-37.82075],[139.93223,-39.4283],[141.6017,-39.8767],[142.3783,-39.368294],[142.3783,-40.64702],[142.49478,-42.074874],[144.009,-44.060127],[147.23161,-44.03222],[149.05645,-42.534313],[149.52237,-40.99959],[149.9494,-40.852921],[150.8036,-38.09627],[151.81313,-38.12682],[156.20052,-22.667706],[156.20052,-20.10109],[156.62761,-17.417627],[155.26869,-17.19521],[154.14272,-19.51662],[153.5215,-18.34139],[153.05558,-16.5636],[152.78379,-15.256768],[152.27905,-13.4135],[151.3472,-12.391767],[149.48354,-12.05024],[146.9598,-9.992408],[135.9719,-9.992408],[130.3032,-10.33636],[128.09016,-12.164136],[125.91588,-12.315912],[124.3239,-11.860326],[122.03323,-11.974295],[118.26706,-16.9353],[115.93747,-19.11357],[114.0738,-21.11863],[113.49141,-22.596033],[112.28778,-28.784589]]],"terms_text":"AGRI"},{"id":"lu.geoportail.opendata.basemap","name":"Basemap geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/basemap/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/carte-de-base-webservices-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"basemap.at","name":"basemap.at","type":"tms","template":"https://maps{switch:1,2,3,4}.wien.gv.at/basemap/geolandbasemap/normal/google3857/{zoom}/{y}/{x}.png","description":"Basemap of Austria, based on goverment data.","scaleExtent":[0,19],"polygon":[[[16.5073284,46.9929304],[16.283417,46.9929304],[16.135839,46.8713046],[15.9831722,46.8190947],[16.0493278,46.655175],[15.8610387,46.7180116],[15.7592608,46.6900933],[15.5607938,46.6796202],[15.5760605,46.6342132],[15.4793715,46.6027553],[15.4335715,46.6516819],[15.2249267,46.6342132],[15.0468154,46.6481886],[14.9908376,46.5887681],[14.9603042,46.6237293],[14.8534374,46.6027553],[14.8330818,46.5012666],[14.7516595,46.4977636],[14.6804149,46.4381781],[14.6142593,46.4381781],[14.578637,46.3785275],[14.4412369,46.4311638],[14.1613476,46.4276563],[14.1257253,46.4767409],[14.0188585,46.4767409],[13.9119917,46.5257813],[13.8254805,46.5047694],[13.4438134,46.560783],[13.3064132,46.5502848],[13.1283019,46.5887681],[12.8433237,46.6132433],[12.7262791,46.6412014],[12.5125455,46.6656529],[12.3598787,46.7040543],[12.3649676,46.7703197],[12.2886341,46.7772902],[12.2733674,46.8852187],[12.2072118,46.8747835],[12.1308784,46.9026062],[12.1156117,46.9998721],[12.2530119,47.0657733],[12.2123007,47.0934969],[11.9833004,47.0449712],[11.7339445,46.9616816],[11.6321666,47.010283],[11.5405665,46.9755722],[11.4998553,47.0068129],[11.418433,46.9651546],[11.2555884,46.9755722],[11.1130993,46.913036],[11.0418548,46.7633482],[10.8891879,46.7598621],[10.7416099,46.7842599],[10.7059877,46.8643462],[10.5787653,46.8399847],[10.4566318,46.8504267],[10.4769874,46.9269392],[10.3853873,46.9894592],[10.2327204,46.8643462],[10.1207647,46.8330223],[9.8663199,46.9408389],[9.9019422,47.0033426],[9.6831197,47.0588402],[9.6118752,47.0380354],[9.6322307,47.128131],[9.5813418,47.1662025],[9.5406306,47.2664422],[9.6067863,47.3492559],[9.6729419,47.369939],[9.6424085,47.4457079],[9.5660751,47.4801122],[9.7136531,47.5282405],[9.7848976,47.5969187],[9.8357866,47.5454185],[9.9477423,47.538548],[10.0902313,47.4491493],[10.1105869,47.3664924],[10.2428982,47.3871688],[10.1869203,47.2698953],[10.3243205,47.2975125],[10.4820763,47.4491493],[10.4311873,47.4869904],[10.4413651,47.5900549],[10.4871652,47.5522881],[10.5482319,47.5351124],[10.5991209,47.5660246],[10.7568766,47.5316766],[10.8891879,47.5454185],[10.9400769,47.4869904],[10.9960547,47.3906141],[11.2352328,47.4422662],[11.2810328,47.3975039],[11.4235219,47.5144941],[11.5761888,47.5076195],[11.6067221,47.5900549],[11.8357224,47.5866227],[12.003656,47.6243647],[12.2072118,47.6037815],[12.1614117,47.6963421],[12.2581008,47.7442718],[12.2530119,47.6792136],[12.4311232,47.7100408],[12.4921899,47.631224],[12.5685234,47.6277944],[12.6295901,47.6894913],[12.7720792,47.6689338],[12.8331459,47.5419833],[12.975635,47.4732332],[13.0417906,47.4938677],[13.0367017,47.5557226],[13.0977685,47.6415112],[13.0316128,47.7100408],[12.9043905,47.7203125],[13.0061684,47.84683],[12.9451016,47.9355501],[12.8636793,47.9594103],[12.8636793,48.0036929],[12.7517236,48.0989418],[12.8738571,48.2109733],[12.9603683,48.2109733],[13.0417906,48.2652035],[13.1842797,48.2990682],[13.2606131,48.2922971],[13.3980133,48.3565867],[13.4438134,48.417418],[13.4387245,48.5523383],[13.509969,48.5860123],[13.6117469,48.5725454],[13.7287915,48.5118999],[13.7847694,48.5725454],[13.8203916,48.6263915],[13.7949471,48.7171267],[13.850925,48.7741724],[14.0595697,48.6633774],[14.0137696,48.6331182],[14.0748364,48.5927444],[14.2173255,48.5961101],[14.3649034,48.5489696],[14.4666813,48.6499311],[14.5582815,48.5961101],[14.5989926,48.6263915],[14.7211261,48.5759124],[14.7211261,48.6868997],[14.822904,48.7271983],[14.8178151,48.777526],[14.9647227,48.7851754],[14.9893637,49.0126611],[15.1485933,48.9950306],[15.1943934,48.9315502],[15.3063491,48.9850128],[15.3928603,48.9850128],[15.4844604,48.9282069],[15.749083,48.8545973],[15.8406831,48.8880697],[16.0086166,48.7808794],[16.2070835,48.7339115],[16.3953727,48.7372678],[16.4920617,48.8110498],[16.6905286,48.7741724],[16.7057953,48.7339115],[16.8991733,48.713769],[16.9755067,48.515271],[16.8482844,48.4511817],[16.8533733,48.3464411],[16.9551512,48.2516513],[16.9907734,48.1498955],[17.0925513,48.1397088],[17.0823736,48.0241182],[17.1739737,48.0207146],[17.0823736,47.8741447],[16.9856845,47.8673174],[17.0823736,47.8092489],[17.0925513,47.7031919],[16.7414176,47.6792136],[16.7057953,47.7511153],[16.5378617,47.7545368],[16.5480395,47.7066164],[16.4208172,47.6689338],[16.573484,47.6175045],[16.670173,47.631224],[16.7108842,47.538548],[16.6599952,47.4491493],[16.5429506,47.3940591],[16.4615283,47.3940591],[16.4920617,47.276801],[16.425906,47.1973317],[16.4717061,47.1489007],[16.5480395,47.1489007],[16.476795,47.0796369],[16.527684,47.0588402],[16.5073284,46.9929304]]],"terms_text":"basemap.at"},{"id":"basemap.at-orthofoto","name":"basemap.at Orthofoto","type":"tms","template":"https://maps{switch:1,2,3,4}.wien.gv.at/basemap/bmaporthofoto30cm/normal/google3857/{zoom}/{y}/{x}.jpeg","description":"Orthofoto layer provided by basemap.at. \"Successor\" of geoimage.at imagery.","scaleExtent":[0,19],"polygon":[[[16.5073284,46.9929304],[16.283417,46.9929304],[16.135839,46.8713046],[15.9831722,46.8190947],[16.0493278,46.655175],[15.8610387,46.7180116],[15.7592608,46.6900933],[15.5607938,46.6796202],[15.5760605,46.6342132],[15.4793715,46.6027553],[15.4335715,46.6516819],[15.2249267,46.6342132],[15.0468154,46.6481886],[14.9908376,46.5887681],[14.9603042,46.6237293],[14.8534374,46.6027553],[14.8330818,46.5012666],[14.7516595,46.4977636],[14.6804149,46.4381781],[14.6142593,46.4381781],[14.578637,46.3785275],[14.4412369,46.4311638],[14.1613476,46.4276563],[14.1257253,46.4767409],[14.0188585,46.4767409],[13.9119917,46.5257813],[13.8254805,46.5047694],[13.4438134,46.560783],[13.3064132,46.5502848],[13.1283019,46.5887681],[12.8433237,46.6132433],[12.7262791,46.6412014],[12.5125455,46.6656529],[12.3598787,46.7040543],[12.3649676,46.7703197],[12.2886341,46.7772902],[12.2733674,46.8852187],[12.2072118,46.8747835],[12.1308784,46.9026062],[12.1156117,46.9998721],[12.2530119,47.0657733],[12.2123007,47.0934969],[11.9833004,47.0449712],[11.7339445,46.9616816],[11.6321666,47.010283],[11.5405665,46.9755722],[11.4998553,47.0068129],[11.418433,46.9651546],[11.2555884,46.9755722],[11.1130993,46.913036],[11.0418548,46.7633482],[10.8891879,46.7598621],[10.7416099,46.7842599],[10.7059877,46.8643462],[10.5787653,46.8399847],[10.4566318,46.8504267],[10.4769874,46.9269392],[10.3853873,46.9894592],[10.2327204,46.8643462],[10.1207647,46.8330223],[9.8663199,46.9408389],[9.9019422,47.0033426],[9.6831197,47.0588402],[9.6118752,47.0380354],[9.6322307,47.128131],[9.5813418,47.1662025],[9.5406306,47.2664422],[9.6067863,47.3492559],[9.6729419,47.369939],[9.6424085,47.4457079],[9.5660751,47.4801122],[9.7136531,47.5282405],[9.7848976,47.5969187],[9.8357866,47.5454185],[9.9477423,47.538548],[10.0902313,47.4491493],[10.1105869,47.3664924],[10.2428982,47.3871688],[10.1869203,47.2698953],[10.3243205,47.2975125],[10.4820763,47.4491493],[10.4311873,47.4869904],[10.4413651,47.5900549],[10.4871652,47.5522881],[10.5482319,47.5351124],[10.5991209,47.5660246],[10.7568766,47.5316766],[10.8891879,47.5454185],[10.9400769,47.4869904],[10.9960547,47.3906141],[11.2352328,47.4422662],[11.2810328,47.3975039],[11.4235219,47.5144941],[11.5761888,47.5076195],[11.6067221,47.5900549],[11.8357224,47.5866227],[12.003656,47.6243647],[12.2072118,47.6037815],[12.1614117,47.6963421],[12.2581008,47.7442718],[12.2530119,47.6792136],[12.4311232,47.7100408],[12.4921899,47.631224],[12.5685234,47.6277944],[12.6295901,47.6894913],[12.7720792,47.6689338],[12.8331459,47.5419833],[12.975635,47.4732332],[13.0417906,47.4938677],[13.0367017,47.5557226],[13.0977685,47.6415112],[13.0316128,47.7100408],[12.9043905,47.7203125],[13.0061684,47.84683],[12.9451016,47.9355501],[12.8636793,47.9594103],[12.8636793,48.0036929],[12.7517236,48.0989418],[12.8738571,48.2109733],[12.9603683,48.2109733],[13.0417906,48.2652035],[13.1842797,48.2990682],[13.2606131,48.2922971],[13.3980133,48.3565867],[13.4438134,48.417418],[13.4387245,48.5523383],[13.509969,48.5860123],[13.6117469,48.5725454],[13.7287915,48.5118999],[13.7847694,48.5725454],[13.8203916,48.6263915],[13.7949471,48.7171267],[13.850925,48.7741724],[14.0595697,48.6633774],[14.0137696,48.6331182],[14.0748364,48.5927444],[14.2173255,48.5961101],[14.3649034,48.5489696],[14.4666813,48.6499311],[14.5582815,48.5961101],[14.5989926,48.6263915],[14.7211261,48.5759124],[14.7211261,48.6868997],[14.822904,48.7271983],[14.8178151,48.777526],[14.9647227,48.7851754],[14.9893637,49.0126611],[15.1485933,48.9950306],[15.1943934,48.9315502],[15.3063491,48.9850128],[15.3928603,48.9850128],[15.4844604,48.9282069],[15.749083,48.8545973],[15.8406831,48.8880697],[16.0086166,48.7808794],[16.2070835,48.7339115],[16.3953727,48.7372678],[16.4920617,48.8110498],[16.6905286,48.7741724],[16.7057953,48.7339115],[16.8991733,48.713769],[16.9755067,48.515271],[16.8482844,48.4511817],[16.8533733,48.3464411],[16.9551512,48.2516513],[16.9907734,48.1498955],[17.0925513,48.1397088],[17.0823736,48.0241182],[17.1739737,48.0207146],[17.0823736,47.8741447],[16.9856845,47.8673174],[17.0823736,47.8092489],[17.0925513,47.7031919],[16.7414176,47.6792136],[16.7057953,47.7511153],[16.5378617,47.7545368],[16.5480395,47.7066164],[16.4208172,47.6689338],[16.573484,47.6175045],[16.670173,47.631224],[16.7108842,47.538548],[16.6599952,47.4491493],[16.5429506,47.3940591],[16.4615283,47.3940591],[16.4920617,47.276801],[16.425906,47.1973317],[16.4717061,47.1489007],[16.5480395,47.1489007],[16.476795,47.0796369],[16.527684,47.0588402],[16.5073284,46.9929304]]],"terms_text":"basemap.at","best":true},{"id":"bavaria-DOP80","name":"Bavaria DOP 80cm","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/BAYERNDOP80/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[0,18],"polygon":[[[10.1235886,50.568462],[10.1428576,50.5507804],[10.2028056,50.5574195],[10.2520485,50.5179575],[10.3269835,50.4934473],[10.4104825,50.4184762],[10.6031724,50.3310874],[10.6224414,50.2271041],[10.7252093,50.2106649],[10.7294913,50.2476451],[10.8515282,50.2435376],[10.7187863,50.3201525],[10.7123633,50.3652428],[10.8558102,50.3966441],[10.9371682,50.3966441],[10.9906932,50.3666085],[11.1277171,50.3666085],[11.1791011,50.3133169],[11.1619731,50.294172],[11.24119,50.2928042],[11.249754,50.3734364],[11.24119,50.479825],[11.358945,50.5234025],[11.4381619,50.5097889],[11.4424439,50.4893611],[11.425316,50.4771001],[11.425316,50.4416618],[11.4895459,50.4225686],[11.4916869,50.3980089],[11.5195199,50.3980089],[11.5259429,50.3761673],[11.5987369,50.4034677],[11.6372748,50.3884544],[11.7935678,50.4212045],[11.8363877,50.3925494],[11.9220277,50.4280246],[11.9862577,50.3870894],[11.9841167,50.3570478],[12.0483466,50.3310874],[12.0933076,50.3297207],[12.1297046,50.2982751],[12.1404096,50.2722826],[12.1061536,50.255859],[12.1125766,50.2353216],[12.1489736,50.236691],[12.1982166,50.2010728],[12.2239086,50.1640565],[12.2046396,50.1434795],[12.2067806,50.1077916],[12.2431775,50.0995522],[12.2774335,50.0720772],[12.4936744,49.985428],[12.4979564,49.9413559],[12.5557634,49.9220616],[12.5493404,49.8682726],[12.4808284,49.7881677],[12.4101755,49.7577484],[12.4615594,49.7065456],[12.5471994,49.6802313],[12.5878784,49.552613],[12.6542493,49.534553],[12.6628133,49.4330153],[12.7527353,49.4107323],[12.7976963,49.3466124],[12.9047462,49.3563752],[12.9968092,49.3368477],[13.0546161,49.2754251],[13.1316921,49.2195199],[13.1916401,49.1439475],[13.236601,49.1215335],[13.296549,49.1229347],[13.371484,49.0808823],[13.414304,49.0289687],[13.414304,48.9798112],[13.5791609,48.9699739],[13.6348268,48.9432629],[13.6776468,48.8869823],[13.7375948,48.8926132],[13.7846968,48.8334571],[13.8403627,48.774231],[13.8168118,48.7064584],[13.8446447,48.7008065],[13.8425037,48.6003807],[13.7654278,48.5422972],[13.7525818,48.5040106],[13.6712238,48.5054291],[13.6433908,48.5437146],[13.4571239,48.5508013],[13.4571239,48.4159838],[13.40574,48.3605338],[13.283703,48.2751083],[13.0931541,48.2694081],[12.9582712,48.1909669],[12.8769132,48.1852574],[12.7720043,48.0938188],[12.8640672,48.0136764],[12.8983232,47.9549216],[12.9454252,47.9563555],[12.9968092,47.8846147],[13.0139372,47.834337],[12.9347202,47.7321953],[13.0588981,47.7249947],[13.1188461,47.6385093],[13.0653211,47.5692178],[13.0567571,47.473792],[13.0032322,47.4520801],[12.7677223,47.5504355],[12.7698633,47.6327385],[12.7398893,47.6731207],[12.6670953,47.6702373],[12.5750324,47.621195],[12.4808284,47.6197519],[12.4144575,47.6702373],[12.2431775,47.6774455],[12.2132036,47.6918589],[12.1917936,47.6817699],[12.2132036,47.6659119],[12.2110626,47.603875],[12.1746656,47.5952129],[12.1382686,47.603875],[11.8920537,47.603875],[11.8513747,47.5793285],[11.6394158,47.5822169],[11.5944549,47.5489905],[11.5901729,47.5128508],[11.5173789,47.498388],[11.4403029,47.5041736],[11.395342,47.4752392],[11.427457,47.4448409],[11.346099,47.4433929],[11.279728,47.3955873],[11.2133571,47.3883402],[11.247613,47.4318076],[11.1020251,47.3926886],[10.9650012,47.3897897],[10.9778472,47.4361524],[10.9178992,47.4752392],[10.8707972,47.4752392],[10.8558102,47.4940484],[10.9007712,47.5142969],[10.8729382,47.5359831],[10.8108493,47.5128508],[10.6438513,47.5489905],[10.5946084,47.5547705],[10.5796214,47.5287553],[10.4618664,47.5403192],[10.4661484,47.4839212],[10.4875584,47.4781333],[10.4875584,47.4129762],[10.4597254,47.4028333],[10.4597254,47.375293],[10.4104825,47.3738431],[10.4083415,47.3433862],[10.3205605,47.2867768],[10.2820225,47.2780622],[10.2841635,47.2620819],[10.1471396,47.2620819],[10.1921006,47.3027497],[10.1942416,47.3738431],[10.1664086,47.3738431],[10.1664086,47.3462876],[10.1000376,47.3433862],[10.0614996,47.3636928],[10.0679226,47.4187712],[10.0936146,47.426014],[10.0957556,47.4419449],[9.9780007,47.485368],[9.9565907,47.5273097],[9.8945017,47.5287553],[9.8559637,47.5085124],[9.8174258,47.544655],[9.8217078,47.5764399],[9.7746058,47.5822169],[9.7382088,47.525864],[9.6739788,47.5345376],[9.5840569,47.564884],[9.6397228,47.6053186],[9.7167988,47.603875],[9.8559637,47.6760039],[9.9780007,47.6558179],[10.0293846,47.6817699],[10.1000376,47.6673537],[10.1321526,47.6760039],[10.1428576,47.7019459],[10.0614996,47.7725005],[10.1128836,47.8098988],[10.0829096,47.8530173],[10.1086016,47.9090177],[10.0764866,47.9649577],[10.1300116,48.020837],[10.1342936,48.1066872],[10.1000376,48.1281274],[10.0550766,48.2622821],[9.9694367,48.3676462],[10.0315256,48.4259299],[10.0293846,48.461436],[10.1235886,48.4770509],[10.1535626,48.4514968],[10.2349205,48.5125212],[10.3162785,48.516776],[10.2991505,48.6187835],[10.2456255,48.6682961],[10.2734585,48.7064584],[10.3698035,48.6838472],[10.4318924,48.6993935],[10.4511614,48.7276471],[10.4019185,48.7460035],[10.4404564,48.8489571],[10.4340334,48.9587289],[10.3376885,49.0205451],[10.2499075,49.0359872],[10.2499075,49.0738701],[10.2006646,49.1033147],[10.2520485,49.1327418],[10.1235886,49.1971401],[10.1193066,49.2628519],[10.1514216,49.2893915],[10.1043196,49.3452175],[10.1407166,49.3940134],[10.1086016,49.445545],[10.1107426,49.5053651],[10.0722046,49.5331635],[10.0165387,49.4761598],[9.9266167,49.478942],[9.9244757,49.5567797],[9.8987837,49.5817727],[9.8559637,49.5387213],[9.8067208,49.5567797],[9.8666687,49.6067529],[9.8538227,49.6441991],[9.8174258,49.6608327],[9.8345537,49.6899277],[9.7960158,49.7203895],[9.7574778,49.7079302],[9.7403498,49.6857723],[9.7060938,49.7162368],[9.6782608,49.7162368],[9.6825428,49.6885426],[9.6204539,49.6913127],[9.6461458,49.78955],[9.5583649,49.7743431],[9.5712109,49.7356133],[9.5069809,49.7522156],[9.4919939,49.7798735],[9.4684429,49.7605146],[9.425623,49.7784909],[9.404213,49.7646636],[9.33356,49.770195],[9.329278,49.7342295],[9.408495,49.725926],[9.427764,49.6982374],[9.414918,49.6441991],[9.380662,49.6386533],[9.359252,49.6497443],[9.339983,49.6372668],[9.31215,49.648358],[9.277894,49.626173],[9.284317,49.6081403],[9.241497,49.5748315],[9.0980501,49.5720547],[9.0659351,49.6081403],[9.1001911,49.6511305],[9.0916271,49.6926978],[9.1301651,49.7120837],[9.1387291,49.7425316],[9.1087551,49.7563653],[9.1365881,49.7909322],[9.1001911,49.78955],[9.0723581,49.8282367],[9.0359611,49.8351418],[9.0166922,50.0267091],[8.9631672,50.0308352],[8.9567442,50.0597083],[9.0017052,50.0707031],[9.0209742,50.1105378],[9.1216011,50.1228936],[9.1558571,50.1132838],[9.1965361,50.1187753],[9.1858311,50.1352462],[9.235074,50.1475956],[9.37638,50.1270115],[9.408495,50.0816953],[9.5219679,50.095432],[9.5048399,50.1421073],[9.5326729,50.1640565],[9.4898529,50.1695422],[9.4941349,50.2435376],[9.6140309,50.221625],[9.6654148,50.2353216],[9.6354408,50.2490142],[9.6675558,50.2722826],[9.7424908,50.3092151],[9.7296448,50.3584137],[9.7703238,50.4293885],[9.8688097,50.4007384],[9.9180527,50.4089259],[10.0358076,50.479825],[10.0379486,50.5111504],[10.1235886,50.568462]]]},{"id":"GRB","name":"Belgium AGIV GRB Flanders","type":"tms","template":"http://tile.informatievlaanderen.be/ws/raadpleegdiensten/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=grb_bsk&STYLE=&FORMAT=image/png&tileMatrixSet=GoogleMapsVL&tileMatrix={zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,21],"polygon":[[[2.522393220658428,51.101723961331],[3.1260610915867457,51.34117672029327],[3.174929443042849,51.382459567439525],[3.3761520666856217,51.38784154353026],[3.410647373595811,51.33040116175589],[3.4020235468682634,51.28547573497245],[3.4911364230529203,51.256700377228974],[3.4825125963253734,51.30345118353617],[3.5773746903283947,51.323216048914524],[3.813092620881357,51.27288873325703],[3.8217164476089045,51.236906864834886],[3.9309515861578386,51.236906864834886],[4.054559769252684,51.27468708752057],[4.20116482362099,51.35194974615148],[4.169544125619984,51.38066543475199],[4.342020660170932,51.395016527087456],[4.3650175314443915,51.46491366130351],[4.5374940659953396,51.50071687469512],[4.571989372905529,51.479238319799464],[4.560490937268798,51.44879304380801],[4.638105377816725,51.45058450468522],[4.750215125274841,51.5239738914927],[4.8364533925503155,51.507874144493115],[5.080795149830825,51.49892738159079],[5.135412719105292,51.447001512638565],[5.106666630013469,51.391429175957505],[5.264770120018504,51.31782647548482],[5.264770120018504,51.28727359653538],[5.4085005654776275,51.292666758936925],[5.486115006025553,51.325012432665545],[5.5809771000285755,51.28367780302667],[5.583851708937758,51.23510703218069],[5.767826679125435,51.20449910348059],[5.8770618176743685,51.161253258857485],[5.704585283123422,50.80292546633848],[5.905807906766195,50.7865720955422],[5.9374286047672005,50.732019528192964],[5.902933297857012,50.70107817444857],[5.8138204216723555,50.69379488717487],[5.615472406938765,50.761122144578216],[5.500488050571466,50.71200098472672],[5.204403332925673,50.70289881954383],[5.164158808197117,50.67558172042608],[5.037676016193088,50.70107817444857],[4.988807664736986,50.750210783384084],[4.916942442007425,50.72656077355532],[4.790459650003396,50.766576871275696],[4.681224511454462,50.77021300246129],[4.6697260758177315,50.73565834458533],[4.287403090896464,50.67922491935501],[3.91082932379356,50.677403355240585],[3.718230526878334,50.752029520237265],[3.6549891308763196,50.71200098472672],[3.5342555566906557,50.710180693059606],[3.514133294326379,50.741116039142966],[3.45664111614273,50.74384464791457],[3.373277457776438,50.69561581502901],[3.310036061774423,50.70745012302645],[3.2899137994101473,50.7365680045137],[3.1648683118607086,50.742935129324266],[3.1318103094051106,50.77203096207303],[3.080067349039826,50.76021296163662],[2.8745328120332805,50.73929687829333],[2.8960923788521487,50.71109084772858],[2.8745328120332805,50.69561581502901],[2.796918371485353,50.70289881954383],[2.699181668573149,50.80020030189157],[2.6201299235706315,50.79747497850781],[2.5698242676599374,50.85830267681076],[2.5669496587507554,50.923581424665855],[2.6028822701155367,50.94984841176044],[2.549702005295661,50.996006093918574],[2.522393220658428,51.101723961331]]],"terms_text":"GRB Flanders (c) AGIV"},{"id":"AGIV","name":"Belgium AGIV Orthophoto Flanders","type":"tms","template":"http://tile.informatievlaanderen.be/ws/raadpleegdiensten/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=omwrgbmrvl&STYLE=&FORMAT=image/png&tileMatrixSet=GoogleMapsVL&tileMatrix={zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,21],"polygon":[[[2.522393220658428,51.101723961331],[3.1260610915867457,51.34117672029327],[3.174929443042849,51.382459567439525],[3.3761520666856217,51.38784154353026],[3.410647373595811,51.33040116175589],[3.4020235468682634,51.28547573497245],[3.4911364230529203,51.256700377228974],[3.4825125963253734,51.30345118353617],[3.5773746903283947,51.323216048914524],[3.813092620881357,51.27288873325703],[3.8217164476089045,51.236906864834886],[3.9309515861578386,51.236906864834886],[4.054559769252684,51.27468708752057],[4.20116482362099,51.35194974615148],[4.169544125619984,51.38066543475199],[4.342020660170932,51.395016527087456],[4.3650175314443915,51.46491366130351],[4.5374940659953396,51.50071687469512],[4.571989372905529,51.479238319799464],[4.560490937268798,51.44879304380801],[4.638105377816725,51.45058450468522],[4.750215125274841,51.5239738914927],[4.8364533925503155,51.507874144493115],[5.080795149830825,51.49892738159079],[5.135412719105292,51.447001512638565],[5.106666630013469,51.391429175957505],[5.264770120018504,51.31782647548482],[5.264770120018504,51.28727359653538],[5.4085005654776275,51.292666758936925],[5.486115006025553,51.325012432665545],[5.5809771000285755,51.28367780302667],[5.583851708937758,51.23510703218069],[5.767826679125435,51.20449910348059],[5.8770618176743685,51.161253258857485],[5.704585283123422,50.80292546633848],[5.905807906766195,50.7865720955422],[5.9374286047672005,50.732019528192964],[5.902933297857012,50.70107817444857],[5.8138204216723555,50.69379488717487],[5.615472406938765,50.761122144578216],[5.500488050571466,50.71200098472672],[5.204403332925673,50.70289881954383],[5.164158808197117,50.67558172042608],[5.037676016193088,50.70107817444857],[4.988807664736986,50.750210783384084],[4.916942442007425,50.72656077355532],[4.790459650003396,50.766576871275696],[4.681224511454462,50.77021300246129],[4.6697260758177315,50.73565834458533],[4.287403090896464,50.67922491935501],[3.91082932379356,50.677403355240585],[3.718230526878334,50.752029520237265],[3.6549891308763196,50.71200098472672],[3.5342555566906557,50.710180693059606],[3.514133294326379,50.741116039142966],[3.45664111614273,50.74384464791457],[3.373277457776438,50.69561581502901],[3.310036061774423,50.70745012302645],[3.2899137994101473,50.7365680045137],[3.1648683118607086,50.742935129324266],[3.1318103094051106,50.77203096207303],[3.080067349039826,50.76021296163662],[2.8745328120332805,50.73929687829333],[2.8960923788521487,50.71109084772858],[2.8745328120332805,50.69561581502901],[2.796918371485353,50.70289881954383],[2.699181668573149,50.80020030189157],[2.6201299235706315,50.79747497850781],[2.5698242676599374,50.85830267681076],[2.5669496587507554,50.923581424665855],[2.6028822701155367,50.94984841176044],[2.549702005295661,50.996006093918574],[2.522393220658428,51.101723961331]]],"terms_text":"Orthophoto Flanders most recent (c) AGIV","best":true},{"id":"Benin_cotonou_pleiade_2016","name":"Benin: Cotonou Pleiade 2016","type":"tms","template":"http://geoxxx.agrocampus-ouest.fr/owsifl/gwc/service/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=Benin:cotonou_pleiade_2016&STYLE=&FORMAT=image/jpeg&tileMatrixSet=EPSG:3857&tileMatrix=EPSG:3857:{zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,21],"polygon":[[[2.31953818544,6.55745092536],[2.33645249928,6.56023631702],[2.36377172444,6.56211241002],[2.36737717181,6.56067658005],[2.37777373205,6.54939665325],[2.3777926612,6.53484752744],[2.36994151563,6.4933195729],[2.37038356708,6.45527010853],[2.36958186167,6.45269435578],[2.36188103586,6.44177160245],[2.35391742884,6.40545220189],[2.3674929737,6.40149524022],[2.39525870424,6.40071623744],[2.40128040262,6.40374371884],[2.40587684694,6.40340733291],[2.42045897749,6.39382909301],[2.42485054154,6.3979366042],[2.42949152505,6.39887495342],[2.43625257397,6.39628121034],[2.43958410532,6.40041525877],[2.44439433776,6.40189359345],[2.45375647532,6.39899446003],[2.47144744127,6.3963166199],[2.48162019208,6.3910582748],[2.49453210303,6.38739776192],[2.50893162289,6.38888498676],[2.50719014059,6.39228876781],[2.50120407357,6.39162040687],[2.4963025358,6.39521449649],[2.49509997769,6.40123077776],[2.49543290813,6.40400928653],[2.49830345887,6.41022131795],[2.50191336015,6.41281720321],[2.5108701911,6.41321333458],[2.52218648559,6.40849403999],[2.53352059576,6.4051656109],[2.53809922441,6.40960941297],[2.5411100736,6.41090182623],[2.54650822333,6.41099034757],[2.54654385468,6.40651114868],[2.57638511144,6.40723702943],[2.57642074279,6.41176933466],[2.58575615684,6.41196408125],[2.58867792765,6.41095493903],[2.60877400982,6.39413560832],[2.62569890171,6.39487921149],[2.64554556441,6.39728706193],[2.65039142819,6.39339200408],[2.6536650586,6.36823275735],[2.6431181786,6.3665949733],[2.61251084779,6.3628944474],[2.56867983171,6.3607044406],[2.54682890549,6.36055393954],[2.54687344468,6.35546343647],[2.50206702036,6.35461353888],[2.47064016846,6.35595920942],[2.46777184468,6.35202842507],[2.46422652522,6.35020467258],[2.45253944198,6.35006302163],[2.4511320036,6.34813302357],[2.44737289603,6.34629155079],[2.43757427441,6.34653944174],[2.43297783009,6.33841209773],[2.43016295333,6.33706638135],[2.42244876576,6.33706638135],[2.39236031651,6.34114999999],[2.39315311407,6.34114999999],[2.3652849434,6.34445228474],[2.35386064137,6.34529777247],[2.34377474198,6.34457844399],[2.34093759563,6.34533982549],[2.31086028117,6.36567095094],[2.28434610184,6.37465215648],[2.28146887022,6.37761782314],[2.27599054995,6.39517244756],[2.27611525968,6.39819996182],[2.31528747657,6.4926104105],[2.31579967725,6.5530659484],[2.31953818544,6.55745092536]],[[1.69563043958,6.25076170066],[1.70009994721,6.24711901182],[1.70417862346,6.24697179839],[1.75874803806,6.25835802546],[1.77079143482,6.25995187823],[1.81712109941,6.27161341959],[1.84456614779,6.27656750346],[1.85767848509,6.27944518918],[1.88843363033,6.28325588467],[1.90481876292,6.28594870029],[1.90617692982,6.29435189983],[1.90083111364,6.29721233234],[1.89880903445,6.29953873942],[1.89404334121,6.30085024405],[1.89047742238,6.29969866569],[1.88747882146,6.29636150888],[1.88344050885,6.29622344016],[1.86969682855,6.29226563906],[1.8564007671,6.29198230539],[1.85206654725,6.28674503171],[1.84991419093,6.28906373821],[1.84691224958,6.29202989661],[1.8435272712,6.29332703219],[1.84040507404,6.29315437611],[1.83626738336,6.29129499924],[1.83409832485,6.28733273348],[1.83416513363,6.2851988527],[1.83229560117,6.28456355663],[1.82785949792,6.28644177291],[1.82182443779,6.2908379014],[1.81562903657,6.28997904337],[1.81211044063,6.29143113241],[1.80757635117,6.29570768815],[1.80471693522,6.29692955475],[1.80073513171,6.29709778253],[1.79775991387,6.29612383144],[1.79625448928,6.29491967121],[1.79490049792,6.28965143736],[1.79641483036,6.28608317469],[1.80097564333,6.28338261222],[1.79566657198,6.28013306439],[1.79156005874,6.28174455931],[1.78498607441,6.28122215216],[1.78092410036,6.27752986974],[1.77588226414,6.27550220232],[1.76744654171,6.27696318619],[1.75653444036,6.27496207997],[1.74833032171,6.27238985028],[1.74761769468,6.27726423691],[1.74572477914,6.27938486862],[1.73948038482,6.27984972411],[1.73680357955,6.27761398678],[1.73572127725,6.27891558552],[1.72901812928,6.27911038233],[1.72435487617,6.27422273126],[1.72449294765,6.2678607472],[1.72555966124,6.26683029328],[1.69933944056,6.26159387355],[1.69572953928,6.25725948175],[1.69563043958,6.25076170066]]],"best":true},{"id":"Bing","name":"Bing aerial imagery","type":"bing","template":"http://www.bing.com/maps/","description":"Satellite and aerial imagery.","scaleExtent":[0,22],"default":true},{"id":"British_Columbia_Mosaic","name":"British Columbia Mosaic","type":"tms","template":"http://{switch:a,b,c,d}.imagery.paulnorman.ca/tiles/bc_mosaic/{zoom}/{x}/{y}.png","scaleExtent":[9,20],"polygon":[[[-123.3176032,49.3272567],[-123.4405258,49.3268222],[-123.440717,49.3384429],[-123.4398375,49.3430357],[-123.4401258,49.3435398],[-123.4401106,49.3439946],[-123.4406265,49.3444493],[-123.4404747,49.3455762],[-123.4397768,49.3460606],[-123.4389726,49.3461298],[-123.4372904,49.3567236],[-123.4374774,49.3710843],[-123.4335292,49.3709446],[-123.4330357,49.373725],[-123.4332717,49.3751221],[-123.4322847,49.3761001],[-123.4317482,49.3791736],[-123.4314264,49.3795927],[-123.4307826,49.3823866],[-123.4313405,49.3827358],[-123.4312118,49.3838533],[-123.4300415,49.3845883],[-123.4189858,49.3847087],[-123.4192235,49.4135198],[-123.3972532,49.4135691],[-123.3972758,49.4243473],[-123.4006929,49.4243314],[-123.4007741,49.5703491],[-123.4000812,49.570345],[-123.4010761,49.5933838],[-123.3760399,49.5932848],[-123.3769811,49.6756063],[-123.3507288,49.6756396],[-123.3507969,49.7086751],[-123.332887,49.708722],[-123.3327888,49.7256288],[-123.3007111,49.7255625],[-123.3009164,49.7375384],[-123.2885986,49.737638],[-123.2887823,49.8249207],[-123.2997955,49.8249207],[-123.3011721,49.8497814],[-123.3218218,49.850669],[-123.3273284,49.8577696],[-123.3276726,49.9758852],[-123.3008279,49.9752212],[-123.3007204,50.0997002],[-123.2501716,50.100735],[-123.25091,50.2754901],[-123.0224338,50.2755598],[-123.0224879,50.3254853],[-123.0009318,50.3254689],[-123.0007778,50.3423899],[-122.9775023,50.3423408],[-122.9774766,50.3504306],[-122.9508137,50.3504961],[-122.950795,50.3711984],[-122.9325221,50.3711521],[-122.9321048,50.399793],[-122.8874234,50.3999748],[-122.8873385,50.4256108],[-122.6620152,50.4256959],[-122.6623083,50.3994506],[-122.5990316,50.3992413],[-122.5988274,50.3755206],[-122.5724832,50.3753706],[-122.5735621,50.2493891],[-122.5990415,50.2494643],[-122.5991504,50.2265663],[-122.6185016,50.2266359],[-122.6185741,50.2244081],[-122.6490609,50.2245126],[-122.6492181,50.1993528],[-122.7308575,50.1993758],[-122.7311583,50.1244287],[-122.7490352,50.1245109],[-122.7490541,50.0903032],[-122.7687806,50.0903435],[-122.7689801,49.9494546],[-122.999047,49.9494706],[-122.9991199,49.8754553],[-122.9775894,49.8754553],[-122.9778145,49.6995098],[-122.9992362,49.6994781],[-122.9992524,49.6516526],[-123.0221525,49.6516526],[-123.0221162,49.5995096],[-123.0491898,49.5994625],[-123.0491898,49.5940523],[-123.0664647,49.5940405],[-123.0663594,49.5451868],[-123.0699906,49.5451202],[-123.0699008,49.5413153],[-123.0706835,49.5392837],[-123.0708888,49.5379931],[-123.0711454,49.5368773],[-123.0711069,49.5358115],[-123.0713764,49.532822],[-123.0716458,49.5321141],[-123.07171,49.5313896],[-123.0720308,49.5304153],[-123.0739554,49.5303486],[-123.0748023,49.5294992],[-123.0748151,49.5288079],[-123.0743403,49.5280584],[-123.073532,49.5274588],[-123.0733652,49.5270423],[-123.0732882,49.5255932],[-123.0737116,49.5249602],[-123.0736218,49.5244938],[-123.0992583,49.5244854],[-123.0991649,49.4754502],[-123.071052,49.4755252],[-123.071088,49.4663034],[-123.0739204,49.4663054],[-123.07422,49.4505028],[-123.0746319,49.4500858],[-123.074651,49.449329],[-123.0745999,49.449018],[-123.0744619,49.4486927],[-123.0743336,49.4479899],[-123.0742427,49.4477688],[-123.0743061,49.4447473],[-123.0747103,49.4447556],[-123.0746384,49.4377306],[-122.9996506,49.4377363],[-122.9996506,49.4369214],[-122.8606163,49.4415314],[-122.8102616,49.4423972],[-122.8098984,49.3766739],[-122.4036093,49.3766617],[-122.4036341,49.3771944],[-122.264739,49.3773028],[-122.263542,49.2360088],[-122.2155742,49.236139],[-122.0580956,49.235878],[-121.9538274,49.2966525],[-121.9400911,49.3045389],[-121.9235761,49.3142257],[-121.8990871,49.3225436],[-121.8883447,49.3259752],[-121.8552982,49.3363575],[-121.832697,49.3441519],[-121.7671336,49.3654361],[-121.6736683,49.3654589],[-121.6404153,49.3743775],[-121.5961976,49.3860493],[-121.5861178,49.3879193],[-121.5213684,49.3994649],[-121.5117375,49.4038378],[-121.4679302,49.4229024],[-121.4416803,49.4345607],[-121.422429,49.4345788],[-121.3462885,49.3932312],[-121.3480144,49.3412388],[-121.5135035,49.320577],[-121.6031683,49.2771727],[-121.6584065,49.1856125],[-121.679953,49.1654109],[-121.7815793,49.0702559],[-121.8076228,49.0622471],[-121.9393997,49.0636219],[-121.9725524,49.0424179],[-121.9921394,49.0332869],[-122.0035289,49.0273413],[-122.0178564,49.0241067],[-122.1108634,48.9992786],[-122.1493067,48.9995305],[-122.1492705,48.9991498],[-122.1991447,48.9996019],[-122.199181,48.9991974],[-122.234365,48.9994829],[-122.234365,49.000173],[-122.3994722,49.0012385],[-122.4521338,49.0016326],[-122.4521338,49.000883],[-122.4584089,49.0009306],[-122.4584814,48.9993124],[-122.4992458,48.9995022],[-122.4992458,48.9992906],[-122.5492618,48.9995107],[-122.5492564,48.9993206],[-122.6580785,48.9994212],[-122.6581061,48.9954007],[-122.7067604,48.9955344],[-122.7519761,48.9956392],[-122.7922063,48.9957204],[-122.7921907,48.9994331],[-123.0350417,48.9995724],[-123.0350437,49.0000958],[-123.0397091,49.0000536],[-123.0397444,49.0001812],[-123.0485506,49.0001348],[-123.0485329,49.0004712],[-123.0557122,49.000448],[-123.0556324,49.0002284],[-123.0641365,49.0001293],[-123.064158,48.9999421],[-123.074899,48.9996928],[-123.0750717,49.0006218],[-123.0899573,49.0003726],[-123.109229,48.9999421],[-123.1271193,49.0003046],[-123.1359953,48.9998741],[-123.1362716,49.0005765],[-123.153851,48.9998061],[-123.1540533,49.0006806],[-123.1710015,49.0001274],[-123.2000916,48.9996849],[-123.2003446,49.0497785],[-123.2108845,49.0497232],[-123.2112218,49.051989],[-123.2070479,49.0520857],[-123.2078911,49.0607884],[-123.2191688,49.0600978],[-123.218958,49.0612719],[-123.2251766,49.0612719],[-123.2253874,49.0622388],[-123.2297088,49.0620316],[-123.2298142,49.068592],[-123.2331869,49.0687301],[-123.2335031,49.0705945],[-123.249313,49.0702493],[-123.2497346,49.0802606],[-123.2751358,49.0803986],[-123.2751358,49.0870947],[-123.299483,49.0873018],[-123.29944,49.080253],[-123.3254508,49.0803944],[-123.3254353,49.1154662],[-123.2750966,49.1503341],[-123.275181,49.1873267],[-123.2788067,49.1871063],[-123.278891,49.1910741],[-123.3004767,49.1910741],[-123.3004186,49.2622933],[-123.3126185,49.2622416],[-123.3125958,49.2714948],[-123.3154251,49.2714727],[-123.3156628,49.2818906],[-123.3174735,49.2818832],[-123.3174961,49.2918488],[-123.3190353,49.2918488],[-123.3190692,49.298602],[-123.3202349,49.2985651],[-123.3202786,49.3019749],[-123.3222679,49.3019605],[-123.3223943,49.3118263],[-123.3254002,49.3118086],[-123.3253898,49.3201721],[-123.3192695,49.3201957],[-123.3192242,49.3246748],[-123.3179437,49.3246596],[-123.3179861,49.3254065],[-123.3176032,49.3272567]]],"terms_url":"http://imagery.paulnorman.ca/tiles/about.html","terms_text":"Copyright Province of British Columbia, City of Surrey"},{"id":"lu.geoportail.opendata.cadastre","name":"Cadastre geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/cadastre/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/plan-cadastral-numerise-pcn-webservices-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"osm-cambodia_laos_thailand_vietnam-bilingual","name":"Cambodia, Laos, Thailand, Vietnam, Myanmar bilingual","type":"tms","template":"http://{switch:a,b,c,d}.tile.osm-tools.org/osm_then/{zoom}/{x}/{y}.png","scaleExtent":[0,19],"polygon":[[[92.1023798,20.8135629],[93.5690546,24.0975527],[94.1733026,23.9269484],[95.1950312,26.707274],[96.7550898,27.5286657],[97.5845575,28.5805966],[98.738122,27.514051],[98.7436151,25.8799151],[97.6779413,24.7577376],[97.9635858,24.042382],[98.8205194,24.1627239],[99.5236444,22.9593356],[100.3695917,21.5051376],[101.7923212,22.4830518],[105.3628778,23.3331079],[106.8185663,22.8480137],[108.1973505,21.3619661],[107.4389505,18.8539792],[117.1453714,7.4656173],[119.6172953,5.2875389],[118.1231546,4.0502277],[117.2552347,4.3624942],[115.8654642,4.3460623],[115.5084085,3.0249771],[114.552598,1.5100953],[113.5418558,1.2574836],[112.9650736,1.5704982],[112.2454691,1.5100953],[111.67418,1.0158321],[110.4546976,0.9004918],[109.4988871,1.9218969],[103.2256937,1.1256762],[100.4626322,3.2388904],[97.6721048,8.0588831],[93.892808,15.9398659],[92.1023798,20.8135629]]],"terms_url":"http://www.osm-tools.org/","terms_text":"© osm-tools.org & OpenStreetMap contributors, CC-BY-SA"},{"id":"South_Africa-CapeTown-Aerial-2013","name":"City of Cape Town 2013 Aerial","type":"tms","template":"http://{switch:a,b,c}.coct.aerial.openstreetmap.org.za/layer/za_coct_aerial_2013/{zoom}/{x}/{y}.jpg","description":"OpenStreetMap use only. City of Cape Town Aerial ortho-photography of the municipal area. 12cm ground sample distance","scaleExtent":[1,21],"polygon":[[[18.4486565,-33.893623],[18.4485868,-33.902644],[18.4702,-33.9027665],[18.4813902,-33.8472383],[18.4492466,-33.801069],[18.4281537,-33.7356408],[18.43914,-33.7177232],[18.4071895,-33.6589917],[18.3322379,-33.5775191],[18.3324525,-33.5504487],[18.353996,-33.5505918],[18.3542535,-33.5236025],[18.3652398,-33.5236561],[18.3650252,-33.5148009],[18.3760115,-33.5147652],[18.3760545,-33.5058017],[18.4296557,-33.5059449],[18.4296986,-33.4878541],[18.4404919,-33.4878899],[18.4405991,-33.4698849],[18.4943721,-33.4700997],[18.4943292,-33.4791564],[18.5158297,-33.4791743],[18.5157439,-33.4881941],[18.5264727,-33.4883015],[18.5263225,-33.5243538],[18.5479304,-33.5244253],[18.5479519,-33.5153913],[18.5693666,-33.5154987],[18.5693666,-33.524479],[18.5801169,-33.5245327],[18.580074,-33.5425978],[18.5907814,-33.5425978],[18.5907385,-33.5606413],[18.5799453,-33.5605341],[18.5798809,-33.569617],[18.5906956,-33.569617],[18.5906526,-33.5786811],[18.6230108,-33.5787347],[18.622925,-33.5877264],[18.6659691,-33.5878872],[18.6659262,-33.614928],[18.6767194,-33.6149726],[18.6765772,-33.6510279],[18.687298,-33.6510167],[18.6873409,-33.6600365],[18.6980697,-33.6600901],[18.6980697,-33.6690733],[18.7520358,-33.6692519],[18.7520787,-33.6421924],[18.7736437,-33.642246],[18.773708,-33.6331886],[18.8274595,-33.6332958],[18.8275239,-33.6603044],[18.8166663,-33.6602866],[18.8166019,-33.6783233],[18.8058087,-33.6783055],[18.8058087,-33.7053892],[18.8273951,-33.7054428],[18.8273308,-33.7234701],[18.838124,-33.7234344],[18.8380381,-33.7413865],[18.8165161,-33.7413687],[18.8163659,-33.7955057],[18.8055941,-33.7955057],[18.8055083,-33.8135675],[18.794758,-33.8135497],[18.7947151,-33.8315364],[18.7731072,-33.8315186],[18.7731287,-33.8405194],[18.7623569,-33.8405194],[18.7622711,-33.903588],[18.7514564,-33.9035167],[18.7510809,-33.9847823],[18.7619063,-33.9848001],[18.7617776,-34.0298785],[18.772603,-34.0298963],[18.7725815,-34.0389073],[18.7940338,-34.0389406],[18.7938756,-34.0406987],[18.7984461,-34.0411855],[18.8032445,-34.0411788],[18.8034055,-34.0389206],[18.8159367,-34.038974],[18.8163444,-34.0299318],[18.8379845,-34.0316479],[18.8380006,-34.030003],[18.8484183,-34.0300074],[18.8484666,-34.0218491],[18.859925,-34.0234675],[18.8598606,-34.0210132],[18.868272,-34.0220803],[18.8681862,-34.0211733],[18.8854596,-34.0234319],[18.8851806,-34.0213156],[18.9025184,-34.021031],[18.9025828,-34.0119958],[18.9134189,-34.0119958],[18.9134833,-33.9939582],[18.9458844,-33.9940294],[18.9458629,-34.003102],[18.9674279,-34.0029953],[18.9674708,-34.0120848],[18.9782211,-34.0120848],[18.9783284,-34.0211377],[18.9891431,-34.0211377],[18.9891645,-34.039134],[19.0000167,-34.0391251],[19.0000221,-34.0571798],[19.0108368,-34.0572509],[19.0107939,-34.0841436],[19.0000007,-34.0841258],[19.0000221,-34.0931977],[18.9891538,-34.0931711],[18.9891753,-34.1021976],[18.9783177,-34.1021798],[18.9783177,-34.111232],[18.967503,-34.1112143],[18.9674923,-34.1292536],[18.9566025,-34.1292358],[18.9565596,-34.1382408],[18.9674172,-34.1383118],[18.9674172,-34.1473157],[18.9891753,-34.147298],[18.9891753,-34.165303],[18.9782748,-34.1652852],[18.9783177,-34.1742863],[18.9674172,-34.1742685],[18.9674601,-34.1833042],[18.9565596,-34.1833219],[18.9565596,-34.1923565],[18.9457449,-34.192321],[18.945702,-34.2013192],[18.9348659,-34.2013725],[18.9348873,-34.2193305],[18.9023575,-34.2193482],[18.9017567,-34.2362557],[18.8878414,-34.2373467],[18.8894185,-34.2554123],[18.8805887,-34.2553414],[18.8792744,-34.2644348],[18.8696882,-34.2644126],[18.8697097,-34.2734386],[18.8371369,-34.2734208],[18.8371155,-34.2643771],[18.848016,-34.2644037],[18.8480267,-34.237391],[18.8154861,-34.210281],[18.8156471,-34.1741265],[18.8548824,-34.1562743],[18.7617561,-34.0840547],[18.6533734,-34.077479],[18.4797433,-34.1101217],[18.4463713,-34.1342269],[18.4444508,-34.1640868],[18.4359965,-34.1640513],[18.435975,-34.1820172],[18.4468111,-34.182106],[18.4467253,-34.1911052],[18.4659299,-34.1912117],[18.4866151,-34.2453911],[18.4788904,-34.2543659],[18.4860036,-34.2543748],[18.4677109,-34.2994116],[18.4892222,-34.3445792],[18.500112,-34.3445837],[18.4999189,-34.3626174],[18.467432,-34.3625111],[18.4673676,-34.3534947],[18.3916005,-34.3170651],[18.3917722,-34.2900161],[18.3701643,-34.2808678],[18.370682,-34.2178866],[18.3492324,-34.1816178],[18.3274743,-34.1814936],[18.3276674,-34.1634565],[18.3118746,-34.1543832],[18.3114025,-34.1435331],[18.3236656,-34.1346886],[18.3499297,-34.1042053],[18.3393189,-34.0882843],[18.3612487,-34.0597219],[18.3550474,-34.0553843],[18.3427522,-34.064326],[18.3199963,-34.0644326],[18.296071,-34.045126],[18.3068213,-34.0252637],[18.3287725,-34.0191992],[18.3289227,-34.001252],[18.3397374,-34.0012698],[18.3398017,-33.9866282],[18.3628687,-33.9735145],[18.3638129,-33.9292474],[18.3726212,-33.9292741],[18.3728358,-33.917763],[18.3977267,-33.8933469],[18.4486565,-33.893623]]],"terms_url":"https://www.capetown.gov.za","terms_text":"City of Cape Town Aerial - OPENSTREETMAP USE ONLY"},{"id":"South_Africa-CapeTown-Aerial","name":"City of Cape Town 2015 Aerial","type":"tms","template":"http://{switch:a,b,c}.coct.aerial.openstreetmap.org.za/layer/za_coct_aerial_2015/{zoom}/{x}/{y}.jpg","description":"OpenStreetMap use only. City of Cape Town Aerial ortho-photography of the municipal area. 8cm ground sample distance","scaleExtent":[1,21],"polygon":[[[18.4486565,-33.893623],[18.4485868,-33.902644],[18.4702,-33.9027665],[18.4813902,-33.8472383],[18.4492466,-33.801069],[18.4281537,-33.7356408],[18.43914,-33.7177232],[18.4071895,-33.6589917],[18.3322379,-33.5775191],[18.3324525,-33.5504487],[18.353996,-33.5505918],[18.3542535,-33.5236025],[18.3652398,-33.5236561],[18.3650252,-33.5148009],[18.3760115,-33.5147652],[18.3760545,-33.5058017],[18.4296557,-33.5059449],[18.4296986,-33.4878541],[18.4404919,-33.4878899],[18.4405991,-33.4698849],[18.4943721,-33.4700997],[18.4943292,-33.4791564],[18.5158297,-33.4791743],[18.5157439,-33.4881941],[18.5264727,-33.4883015],[18.5263225,-33.5243538],[18.5479304,-33.5244253],[18.5479519,-33.5153913],[18.5693666,-33.5154987],[18.5693666,-33.524479],[18.5801169,-33.5245327],[18.580074,-33.5425978],[18.5907814,-33.5425978],[18.5907385,-33.5606413],[18.5799453,-33.5605341],[18.5798809,-33.569617],[18.5906956,-33.569617],[18.5906526,-33.5786811],[18.6230108,-33.5787347],[18.622925,-33.5877264],[18.6659691,-33.5878872],[18.6659262,-33.614928],[18.6767194,-33.6149726],[18.6765772,-33.6510279],[18.687298,-33.6510167],[18.6873409,-33.6600365],[18.6980697,-33.6600901],[18.6980697,-33.6690733],[18.7520358,-33.6692519],[18.7520787,-33.6421924],[18.7736437,-33.642246],[18.773708,-33.6331886],[18.8274595,-33.6332958],[18.8275239,-33.6603044],[18.8166663,-33.6602866],[18.8166019,-33.6783233],[18.8058087,-33.6783055],[18.8058087,-33.7053892],[18.8273951,-33.7054428],[18.8273308,-33.7234701],[18.838124,-33.7234344],[18.8380381,-33.7413865],[18.8165161,-33.7413687],[18.8163659,-33.7955057],[18.8055941,-33.7955057],[18.8055083,-33.8135675],[18.794758,-33.8135497],[18.7947151,-33.8315364],[18.7731072,-33.8315186],[18.7731287,-33.8405194],[18.7623569,-33.8405194],[18.7622711,-33.903588],[18.7514564,-33.9035167],[18.7510809,-33.9847823],[18.7619063,-33.9848001],[18.7617776,-34.0298785],[18.772603,-34.0298963],[18.7725815,-34.0389073],[18.7940338,-34.0389406],[18.7938756,-34.0406987],[18.7984461,-34.0411855],[18.8032445,-34.0411788],[18.8034055,-34.0389206],[18.8159367,-34.038974],[18.8163444,-34.0299318],[18.8379845,-34.0316479],[18.8380006,-34.030003],[18.8484183,-34.0300074],[18.8484666,-34.0218491],[18.859925,-34.0234675],[18.8598606,-34.0210132],[18.868272,-34.0220803],[18.8681862,-34.0211733],[18.8854596,-34.0234319],[18.8851806,-34.0213156],[18.9025184,-34.021031],[18.9025828,-34.0119958],[18.9134189,-34.0119958],[18.9134833,-33.9939582],[18.9458844,-33.9940294],[18.9458629,-34.003102],[18.9674279,-34.0029953],[18.9674708,-34.0120848],[18.9782211,-34.0120848],[18.9783284,-34.0211377],[18.9891431,-34.0211377],[18.9891645,-34.039134],[19.0000167,-34.0391251],[19.0000221,-34.0571798],[19.0108368,-34.0572509],[19.0107939,-34.0841436],[19.0000007,-34.0841258],[19.0000221,-34.0931977],[18.9891538,-34.0931711],[18.9891753,-34.1021976],[18.9783177,-34.1021798],[18.9783177,-34.111232],[18.967503,-34.1112143],[18.9674923,-34.1292536],[18.9566025,-34.1292358],[18.9565596,-34.1382408],[18.9674172,-34.1383118],[18.9674172,-34.1473157],[18.9891753,-34.147298],[18.9891753,-34.165303],[18.9782748,-34.1652852],[18.9783177,-34.1742863],[18.9674172,-34.1742685],[18.9674601,-34.1833042],[18.9565596,-34.1833219],[18.9565596,-34.1923565],[18.9457449,-34.192321],[18.945702,-34.2013192],[18.9348659,-34.2013725],[18.9348873,-34.2193305],[18.9023575,-34.2193482],[18.9017567,-34.2362557],[18.8878414,-34.2373467],[18.8894185,-34.2554123],[18.8805887,-34.2553414],[18.8792744,-34.2644348],[18.8696882,-34.2644126],[18.8697097,-34.2734386],[18.8371369,-34.2734208],[18.8371155,-34.2643771],[18.848016,-34.2644037],[18.8480267,-34.237391],[18.8154861,-34.210281],[18.8156471,-34.1741265],[18.8548824,-34.1562743],[18.7617561,-34.0840547],[18.6533734,-34.077479],[18.4797433,-34.1101217],[18.4463713,-34.1342269],[18.4444508,-34.1640868],[18.4359965,-34.1640513],[18.435975,-34.1820172],[18.4468111,-34.182106],[18.4467253,-34.1911052],[18.4659299,-34.1912117],[18.4866151,-34.2453911],[18.4788904,-34.2543659],[18.4860036,-34.2543748],[18.4677109,-34.2994116],[18.4892222,-34.3445792],[18.500112,-34.3445837],[18.4999189,-34.3626174],[18.467432,-34.3625111],[18.4673676,-34.3534947],[18.3916005,-34.3170651],[18.3917722,-34.2900161],[18.3701643,-34.2808678],[18.370682,-34.2178866],[18.3492324,-34.1816178],[18.3274743,-34.1814936],[18.3276674,-34.1634565],[18.3118746,-34.1543832],[18.3114025,-34.1435331],[18.3236656,-34.1346886],[18.3499297,-34.1042053],[18.3393189,-34.0882843],[18.3612487,-34.0597219],[18.3550474,-34.0553843],[18.3427522,-34.064326],[18.3199963,-34.0644326],[18.296071,-34.045126],[18.3068213,-34.0252637],[18.3287725,-34.0191992],[18.3289227,-34.001252],[18.3397374,-34.0012698],[18.3398017,-33.9866282],[18.3628687,-33.9735145],[18.3638129,-33.9292474],[18.3726212,-33.9292741],[18.3728358,-33.917763],[18.3977267,-33.8933469],[18.4486565,-33.893623]]],"terms_url":"https://www.capetown.gov.za","terms_text":"City of Cape Town Aerial - OPENSTREETMAP USE ONLY","best":true},{"id":"CRAIG-Auvergne-2013","name":"CRAIG - Auvergne 2013 - 25 cm","type":"tms","template":"http://tiles.craig.fr/osm/tms/1.0.0/ortho_2013/webmercator/{zoom-1}/{x}/{-y}.jpeg","polygon":[[[2.9401192,44.6338837],[2.9971896,44.633931],[2.9971676,44.6473385],[3.0159744,44.6473541],[3.0159305,44.6741168],[3.0349486,44.6741326],[3.0349036,44.7015216],[3.0536338,44.7015371],[3.0535675,44.7418954],[3.0723301,44.741911],[3.0722196,44.8091687],[3.0921583,44.8091852],[3.092137,44.8221252],[3.1301398,44.8221567],[3.1300495,44.8770722],[3.1485587,44.8770875],[3.1485807,44.8636964],[3.1682313,44.8637126],[3.1682538,44.8500261],[3.2064,44.8500576],[3.2063789,44.8628393],[3.2439492,44.8628704],[3.2439263,44.8767893],[3.2631452,44.8768052],[3.2630782,44.9175197],[3.3200437,44.9175667],[3.3200227,44.9303336],[3.3390815,44.9303493],[3.3390586,44.9441978],[3.3769989,44.9442292],[3.3770218,44.9302879],[3.396031,44.9303036],[3.39612,44.8762713],[3.4148252,44.8762867],[3.4148923,44.8355255],[3.4333371,44.8355408],[3.4333819,44.8082784],[3.4525549,44.8082943],[3.4525774,44.7946344],[3.5089262,44.7946811],[3.508904,44.8081469],[3.604265,44.8082258],[3.6042213,44.8348239],[3.6236136,44.83484],[3.6235695,44.8616583],[3.6424823,44.8616739],[3.642549,44.821102],[3.6610055,44.8211172],[3.6610275,44.8077696],[3.6992999,44.8078013],[3.6992782,44.820994],[3.7361139,44.8210245],[3.7361819,44.7797075],[3.7751058,44.7797397],[3.775151,44.7522344],[3.8118352,44.7522648],[3.8118567,44.7392021],[3.8311822,44.7392181],[3.8312061,44.7246766],[3.887824,44.7247235],[3.8878019,44.7381833],[3.925626,44.7382146],[3.9256039,44.7516682],[3.9454097,44.7516846],[3.9453656,44.7784691],[3.9643737,44.7784848],[3.9643516,44.7919273],[4.0033183,44.7919596],[4.0032964,44.8052575],[4.0216937,44.8052727],[4.0216718,44.8185687],[4.0596515,44.8186001],[4.0596082,44.8449216],[4.0798132,44.8449383],[4.0797928,44.8573502],[4.173882,44.857428],[4.1738604,44.8705468],[4.1932576,44.8705628],[4.193235,44.8842744],[4.2140385,44.8842916],[4.2139961,44.9100242],[4.2324138,44.9100394],[4.2323689,44.9373093],[4.2715486,44.9373416],[4.2715273,44.9502971],[4.3288672,44.9503445],[4.3287793,45.0036659],[4.3489259,45.0036825],[4.3489038,45.0170656],[4.4060793,45.0171127],[4.4059904,45.0710024],[4.3884707,45.0709879],[4.3884482,45.0845976],[4.407943,45.0846137],[4.4079231,45.09663],[4.4843608,45.0966929],[4.4842941,45.1370472],[4.4663631,45.1370324],[4.4663413,45.1502035],[4.4864469,45.15022],[4.4864022,45.1772415],[4.5065524,45.177258],[4.5064402,45.2450058],[4.4881342,45.2449908],[4.4881106,45.2592077],[4.4698588,45.2591927],[4.469836,45.2729835],[4.4508849,45.2729679],[4.4508626,45.2864203],[4.3936753,45.2863733],[4.3936303,45.3135182],[4.3750893,45.3135029],[4.3750662,45.3274054],[4.3950734,45.3274218],[4.3950283,45.3545849],[4.3767871,45.35457],[4.3767639,45.3685486],[4.3576564,45.3685329],[4.3576335,45.3823359],[4.2814576,45.3822734],[4.2814334,45.3968834],[4.2444556,45.3968531],[4.2444325,45.4107893],[4.1481178,45.4107104],[4.1481388,45.3980659],[4.1291913,45.3980504],[4.1292145,45.3840899],[4.0902138,45.3840579],[4.0902351,45.3712093],[4.0135507,45.3711464],[4.0135259,45.3860975],[3.9170932,45.3860185],[3.9170704,45.3997355],[3.9375703,45.3997523],[3.9375481,45.4131142],[3.975277,45.4131451],[3.9752552,45.4262061],[3.9953725,45.4262226],[3.9956999,45.5209568],[3.9777821,45.5209421],[3.977693,45.5743873],[3.9581755,45.5743714],[3.9581522,45.5883658],[3.9396019,45.5883506],[3.9395781,45.6026212],[3.9202279,45.6026054],[3.9202048,45.6164603],[3.8818916,45.616429],[3.8818468,45.643276],[3.8441329,45.6432453],[3.8441098,45.6570896],[3.8261689,45.657075],[3.8261241,45.6838865],[3.8072175,45.6838711],[3.8071277,45.7375802],[3.7882101,45.7375648],[3.7881863,45.7517966],[3.7688482,45.7517809],[3.7688028,45.7789651],[3.750719,45.7789504],[3.7505822,45.8606554],[3.7696692,45.8606709],[3.7695793,45.914333],[3.751661,45.9143185],[3.7516379,45.9280879],[3.7328974,45.9280727],[3.7328527,45.9547155],[3.8101795,45.9547782],[3.8101569,45.9682278],[3.8495994,45.9682598],[3.8495098,46.0216192],[3.8318849,46.0216049],[3.8317936,46.0759058],[3.8505037,46.0759209],[3.8504583,46.1029545],[3.8324727,46.10294],[3.8323353,46.1845598],[3.8142194,46.1845452],[3.8141522,46.2244234],[3.8336864,46.2244392],[3.8336634,46.2381001],[3.8528929,46.2381156],[3.8528703,46.2514729],[3.8931424,46.2515054],[3.8931205,46.2644677],[3.9130562,46.2644838],[3.9130335,46.2779317],[3.9518926,46.2779631],[3.9518709,46.2908227],[3.971523,46.2908386],[3.9715012,46.3036947],[4.0105021,46.3037261],[4.0104784,46.3177638],[4.0298278,46.3177794],[4.029783,46.3442827],[4.0116018,46.344268],[4.0114647,46.4253437],[4.031532,46.4253598],[4.0314635,46.4657978],[4.0132435,46.4657832],[4.0132204,46.479378],[3.9943703,46.4793629],[3.9943461,46.4936113],[3.9745971,46.4935955],[3.9745735,46.5075278],[3.8775423,46.5074499],[3.8774959,46.5347758],[3.8583577,46.5347605],[3.8583347,46.5483156],[3.8186897,46.5482838],[3.8187114,46.5355316],[3.7992386,46.535516],[3.7992156,46.5490706],[3.7610377,46.5490399],[3.7609226,46.6168059],[3.7423295,46.616791],[3.7422834,46.6439624],[3.7228558,46.6439468],[3.7228098,46.6710357],[3.7038706,46.6710206],[3.7038474,46.6846709],[3.6841096,46.6846551],[3.6840631,46.711998],[3.6648359,46.7119826],[3.6647898,46.7390375],[3.6457623,46.7390222],[3.6457158,46.7663375],[3.6257542,46.7663216],[3.6257314,46.7797093],[3.5672301,46.7796626],[3.5672528,46.7663082],[3.5471462,46.7662922],[3.5471922,46.7392824],[3.5271621,46.7392664],[3.5272308,46.6988967],[3.4877399,46.6988651],[3.4877618,46.685943],[3.4679636,46.6859272],[3.4679407,46.6994059],[3.4679179,46.7127907],[3.4486497,46.7127753],[3.4486258,46.7267878],[3.350433,46.7267092],[3.3504786,46.6999004],[3.3303913,46.6998843],[3.3303448,46.7271984],[3.2327174,46.7271203],[3.2327406,46.7135148],[3.2129042,46.7134989],[3.212927,46.7001302],[3.1735446,46.7000987],[3.173498,46.7275094],[3.1541227,46.7274939],[3.1541002,46.7407271],[3.1147772,46.7406957],[3.114754,46.7542756],[3.0753432,46.7542441],[3.0752971,46.7813548],[3.05597,46.7813394],[3.055924,46.8083069],[2.99704,46.8082598],[2.9970166,46.8219593],[2.9379443,46.8219121],[2.9379675,46.8082604],[2.8986634,46.808229],[2.8986872,46.7942392],[2.878991,46.7942234],[2.8790134,46.7810427],[2.8594188,46.781027],[2.8594415,46.7677056],[2.8400446,46.7676901],[2.8400671,46.754466],[2.7414032,46.7543871],[2.741382,46.7668245],[2.7023351,46.7667932],[2.7023571,46.7538869],[2.6826621,46.7538711],[2.6826849,46.7404752],[2.6634875,46.7404599],[2.6635123,46.7258966],[2.6434164,46.7258805],[2.6434382,46.7130938],[2.6241432,46.7130784],[2.6241658,46.6998093],[2.6039699,46.6997931],[2.6039936,46.6858433],[2.5651245,46.6858122],[2.5651469,46.6726126],[2.5459278,46.6725972],[2.5459966,46.6321534],[2.5659222,46.6321694],[2.565946,46.6181104],[2.5456397,46.6180941],[2.5456862,46.5907192],[2.5664225,46.5907358],[2.5664449,46.5775417],[2.5854963,46.577557],[2.5855181,46.5647199],[2.5661318,46.5647044],[2.5661557,46.5506246],[2.468279,46.5505461],[2.4683039,46.5358205],[2.3321246,46.5357112],[2.3321701,46.5088566],[2.3126474,46.5088409],[2.3126703,46.4953444],[2.2928767,46.4953285],[2.2928996,46.4818182],[2.2748687,46.4818037],[2.2749151,46.4544154],[2.2553921,46.4543997],[2.255529,46.3734888],[2.275948,46.3735052],[2.276037,46.3208741],[2.3145615,46.3209052],[2.3145849,46.3070421],[2.3537075,46.3070737],[2.3537313,46.2929669],[2.3938428,46.2929992],[2.3938862,46.2672854],[2.4515727,46.267332],[2.451596,46.2534921],[2.4709353,46.2535077],[2.4709807,46.2265552],[2.4915062,46.2265718],[2.4915521,46.199329],[2.5108806,46.1993446],[2.5109254,46.1727799],[2.5311728,46.1727963],[2.5313772,46.051352],[2.5516349,46.0513684],[2.5516577,46.0377665],[2.5705635,46.0377818],[2.5706774,45.9699434],[2.5514356,45.9699278],[2.551458,45.9566151],[2.5322621,45.9565995],[2.5322849,45.9430066],[2.5130653,45.942991],[2.513134,45.9020279],[2.4749412,45.9019969],[2.4749633,45.8888235],[2.4361947,45.888792],[2.4362172,45.8753288],[2.417209,45.8753133],[2.4172548,45.8479368],[2.3784736,45.8479053],[2.378497,45.8339746],[2.3595157,45.8339592],[2.3595606,45.8070849],[2.3787254,45.8071005],[2.3787481,45.7935783],[2.3986981,45.7935945],[2.3987203,45.7803477],[2.4182486,45.7803636],[2.4183161,45.7400007],[2.4572171,45.7400324],[2.4572394,45.7266956],[2.4758919,45.7267107],[2.4759144,45.7132391],[2.49533,45.7132549],[2.4954204,45.6591268],[2.4576942,45.659096],[2.4577622,45.618343],[2.4391188,45.6183278],[2.4391866,45.5776619],[2.4585044,45.5776777],[2.4585496,45.5505348],[2.4780887,45.5505508],[2.4781108,45.5372464],[2.4975506,45.5372623],[2.4975949,45.5106757],[2.4785536,45.5106601],[2.4786444,45.4561337],[2.4597798,45.4561183],[2.4598701,45.401757],[2.4224876,45.4017264],[2.4224651,45.4152816],[2.4023154,45.4152651],[2.4022929,45.4288193],[2.3256006,45.4287565],[2.3256684,45.3879609],[2.3456182,45.3879773],[2.3456629,45.3611091],[2.326256,45.3610932],[2.326279,45.3472146],[2.3073819,45.3471991],[2.3074045,45.3335972],[2.2881095,45.3335813],[2.2881307,45.3208191],[2.2696332,45.3208039],[2.2696574,45.306212],[2.2506602,45.3061964],[2.2506828,45.2925147],[2.2316866,45.2924992],[2.2317086,45.2792355],[2.2130009,45.2792202],[2.213046,45.2520355],[2.1937387,45.2520197],[2.1937617,45.2381134],[2.1756091,45.2380985],[2.1757423,45.1576822],[2.1573543,45.157667],[2.1574448,45.1029478],[2.1202408,45.1029172],[2.1202629,45.0895468],[2.1006669,45.0895306],[2.1006902,45.0754441],[2.0824591,45.0754291],[2.082548,45.0215961],[2.1025534,45.0216126],[2.1025982,44.994453],[2.0457406,44.9944061],[2.0458508,44.9275321],[2.0657794,44.9275486],[2.0658912,44.8596881],[2.0856964,44.8597044],[2.0857193,44.8458126],[2.1055593,44.8458291],[2.1056029,44.8193264],[2.124743,44.8193422],[2.1247657,44.805512],[2.1435067,44.8055275],[2.143551,44.778597],[2.1256091,44.7785822],[2.1256984,44.7242739],[2.1066459,44.7242581],[2.1067116,44.6842263],[2.1263414,44.6842426],[2.1263635,44.670735],[2.14598,44.6707513],[2.146069,44.6164441],[2.1839622,44.6164756],[2.183983,44.6037819],[2.2404173,44.6038288],[2.2403728,44.6309515],[2.25948,44.6309674],[2.2594571,44.644934],[2.316678,44.6449815],[2.3167011,44.6308801],[2.3361516,44.6308963],[2.3361734,44.6175824],[2.3724238,44.6176125],[2.3724009,44.6315823],[2.4110495,44.6316144],[2.4110701,44.6190741],[2.4492173,44.6191058],[2.4491956,44.6323197],[2.5048575,44.6323659],[2.5048126,44.6597555],[2.5246119,44.6597719],[2.524567,44.6871739],[2.5422544,44.6871886],[2.5422313,44.70122],[2.5807101,44.701252],[2.5805999,44.7683374],[2.61769,44.7683681],[2.6176235,44.808838],[2.6367564,44.8088539],[2.6366899,44.8492948],[2.6733105,44.8493251],[2.6732888,44.8625164],[2.6933766,44.862533],[2.6933323,44.8894303],[2.7305201,44.8894611],[2.7304757,44.9164461],[2.7499202,44.9164622],[2.7500519,44.8364688],[2.8073346,44.8365162],[2.8073139,44.8491017],[2.8263796,44.8491175],[2.8264007,44.8362845],[2.8457039,44.8363004],[2.8457707,44.7957107],[2.8642166,44.795726],[2.8642611,44.7686452],[2.8839885,44.7686615],[2.8840323,44.7419697],[2.9020315,44.7419846],[2.9021426,44.6743192],[2.9219777,44.6743357],[2.9220221,44.6472986],[2.9400972,44.6473136],[2.9401192,44.6338837]]],"terms_url":"http://wiki.openstreetmap.org/wiki/WikiProject_France/CRAIG","terms_text":"Orthophotographie CRAIG/Sintegra/IGN 2013"},{"id":"Czech_CUZK-KM-tms","name":"Czech CUZK:KM tiles proxy","type":"tms","template":"http://osm-{switch:a,b,c}.zby.cz/tiles_cuzk.php/{zoom}/{x}/{y}.png","scaleExtent":[13,18],"polygon":[[[15.0063684,49.0177392],[15.1559854,49.0013828],[15.190896,48.9424551],[15.3105895,48.9882938],[15.4053469,48.9752013],[15.5400022,48.9162426],[15.7145553,48.8670572],[15.8342488,48.880178],[15.968904,48.8178233],[16.0885976,48.7455261],[16.3978059,48.7455261],[16.4875761,48.8145394],[16.6721036,48.7784014],[16.6820781,48.7356594],[16.9015163,48.7126294],[16.9464014,48.6237005],[17.1159672,48.8375227],[17.2107246,48.880178],[17.4052266,48.8178233],[17.4800351,48.8539329],[17.5299074,48.8178233],[17.7044605,48.8670572],[17.8141796,48.9359033],[17.8840008,48.9359033],[17.9438476,49.0210099],[18.0635412,49.0340903],[18.1184007,49.0994409],[18.1981964,49.3047337],[18.3877112,49.3339917],[18.577226,49.5091747],[18.7567663,49.4994587],[18.8465365,49.5253637],[18.8764598,49.5706645],[18.7966641,49.693412],[18.64206,49.7095399],[18.5872004,49.8351543],[18.6121366,49.8833809],[18.5622643,49.9347695],[18.512392,49.9058702],[18.362775,49.9540261],[18.3278644,49.9219275],[18.2630304,49.9732751],[18.1184007,50.0053395],[18.0635412,50.075806],[17.9139242,49.9796897],[17.779269,50.0309757],[17.714435,50.1237921],[17.6047159,50.1653411],[17.7593201,50.21962],[17.7343839,50.3439092],[17.6396265,50.2802117],[17.3802905,50.2802117],[17.3503671,50.3439092],[17.2805459,50.3375433],[17.1857885,50.4075214],[16.9015163,50.4615247],[16.8666057,50.4138779],[16.9663503,50.3184404],[17.0361715,50.2323826],[16.8366823,50.21962],[16.7120015,50.1046034],[16.5823335,50.1589513],[16.5623846,50.2387626],[16.4327166,50.3375433],[16.3529209,50.3916263],[16.2781124,50.3916263],[16.2082911,50.4456477],[16.3978059,50.5344899],[16.4476782,50.5978464],[16.3529209,50.670601],[16.2382145,50.6769221],[16.2182656,50.6326561],[16.1284954,50.6832425],[16.0486997,50.6073425],[15.988853,50.7021983],[15.8741467,50.6832425],[15.8292616,50.7653291],[15.729517,50.743243],[15.450232,50.8157725],[15.3903852,50.7747914],[15.3804108,50.8598659],[15.2956278,50.8850434],[15.2956278,50.9887568],[15.1709471,51.0201394],[14.9914067,51.0013124],[15.0063684,50.8881896],[14.8417898,50.8756034],[14.7969047,50.8252246],[14.6323261,50.8567177],[14.6622495,50.9353576],[14.5724793,50.9227841],[14.6123772,50.9856174],[14.4976708,51.0483657],[14.4178751,51.0232765],[14.3081561,51.0671736],[14.2532965,51.0044508],[14.4029134,50.9322145],[14.3729901,50.897627],[14.2433221,50.9070625],[14.2084114,50.844123],[14.0338583,50.8126214],[13.9789988,50.8252246],[13.9041903,50.7968626],[13.8742669,50.740087],[13.5351352,50.7243038],[13.530148,50.6579561],[13.4703012,50.6136722],[13.3905055,50.664279],[13.3256715,50.5883483],[13.250863,50.6105074],[13.1960035,50.5059517],[13.0513738,50.5218084],[12.9665909,50.4106997],[12.8269484,50.4710483],[12.7022676,50.4138779],[12.5077656,50.401164],[12.343187,50.2547088],[12.323238,50.1845054],[12.2484296,50.2738373],[12.1736211,50.3311765],[12.0988126,50.33436],[12.1187616,50.25152],[12.2234934,50.1653411],[12.2035445,50.1237921],[12.5027784,49.9732751],[12.4778422,49.9379795],[12.5476634,49.9155052],[12.4678677,49.8029766],[12.408021,49.7611134],[12.4828294,49.6869593],[12.5327017,49.6869593],[12.5177401,49.6288466],[12.6075102,49.5415474],[12.6723442,49.4378793],[12.8119867,49.3469896],[12.9466419,49.3437405],[13.2309141,49.1288206],[13.3256715,49.1059712],[13.4353906,49.0438984],[13.4154417,48.9948387],[13.5002246,48.949006],[13.5650586,48.9882938],[13.6847522,48.8834577],[13.7445989,48.9031312],[13.8243946,48.7751149],[13.8992031,48.7751149],[14.0587945,48.676418],[14.0438328,48.6302932],[14.1435774,48.5907241],[14.3729901,48.5610269],[14.4827091,48.6500662],[14.5774665,48.607215],[14.6273389,48.6335892],[14.7071346,48.5808269],[14.7470324,48.7027561],[14.8118664,48.7389485],[14.8168536,48.794831],[14.9864195,48.7652539],[15.0063684,49.0177392]]],"overlay":true},{"id":"Czech_RUIAN-budovy","name":"Czech RUIAN budovy","type":"tms","template":"http://tile.poloha.net/budovy/{zoom}/{x}/{y}.png","scaleExtent":[12,20],"polygon":[[[15.0063684,49.0177392],[15.1559854,49.0013828],[15.190896,48.9424551],[15.3105895,48.9882938],[15.4053469,48.9752013],[15.5400022,48.9162426],[15.7145553,48.8670572],[15.8342488,48.880178],[15.968904,48.8178233],[16.0885976,48.7455261],[16.3978059,48.7455261],[16.4875761,48.8145394],[16.6721036,48.7784014],[16.6820781,48.7356594],[16.9015163,48.7126294],[16.9464014,48.6237005],[17.1159672,48.8375227],[17.2107246,48.880178],[17.4052266,48.8178233],[17.4800351,48.8539329],[17.5299074,48.8178233],[17.7044605,48.8670572],[17.8141796,48.9359033],[17.8840008,48.9359033],[17.9438476,49.0210099],[18.0635412,49.0340903],[18.1184007,49.0994409],[18.1981964,49.3047337],[18.3877112,49.3339917],[18.577226,49.5091747],[18.7567663,49.4994587],[18.8465365,49.5253637],[18.8764598,49.5706645],[18.7966641,49.693412],[18.64206,49.7095399],[18.5872004,49.8351543],[18.6121366,49.8833809],[18.5622643,49.9347695],[18.512392,49.9058702],[18.362775,49.9540261],[18.3278644,49.9219275],[18.2630304,49.9732751],[18.1184007,50.0053395],[18.0635412,50.075806],[17.9139242,49.9796897],[17.779269,50.0309757],[17.714435,50.1237921],[17.6047159,50.1653411],[17.7593201,50.21962],[17.7343839,50.3439092],[17.6396265,50.2802117],[17.3802905,50.2802117],[17.3503671,50.3439092],[17.2805459,50.3375433],[17.1857885,50.4075214],[16.9015163,50.4615247],[16.8666057,50.4138779],[16.9663503,50.3184404],[17.0361715,50.2323826],[16.8366823,50.21962],[16.7120015,50.1046034],[16.5823335,50.1589513],[16.5623846,50.2387626],[16.4327166,50.3375433],[16.3529209,50.3916263],[16.2781124,50.3916263],[16.2082911,50.4456477],[16.3978059,50.5344899],[16.4476782,50.5978464],[16.3529209,50.670601],[16.2382145,50.6769221],[16.2182656,50.6326561],[16.1284954,50.6832425],[16.0486997,50.6073425],[15.988853,50.7021983],[15.8741467,50.6832425],[15.8292616,50.7653291],[15.729517,50.743243],[15.450232,50.8157725],[15.3903852,50.7747914],[15.3804108,50.8598659],[15.2956278,50.8850434],[15.2956278,50.9887568],[15.1709471,51.0201394],[14.9914067,51.0013124],[15.0063684,50.8881896],[14.8417898,50.8756034],[14.7969047,50.8252246],[14.6323261,50.8567177],[14.6622495,50.9353576],[14.5724793,50.9227841],[14.6123772,50.9856174],[14.4976708,51.0483657],[14.4178751,51.0232765],[14.3081561,51.0671736],[14.2532965,51.0044508],[14.4029134,50.9322145],[14.3729901,50.897627],[14.2433221,50.9070625],[14.2084114,50.844123],[14.0338583,50.8126214],[13.9789988,50.8252246],[13.9041903,50.7968626],[13.8742669,50.740087],[13.5351352,50.7243038],[13.530148,50.6579561],[13.4703012,50.6136722],[13.3905055,50.664279],[13.3256715,50.5883483],[13.250863,50.6105074],[13.1960035,50.5059517],[13.0513738,50.5218084],[12.9665909,50.4106997],[12.8269484,50.4710483],[12.7022676,50.4138779],[12.5077656,50.401164],[12.343187,50.2547088],[12.323238,50.1845054],[12.2484296,50.2738373],[12.1736211,50.3311765],[12.0988126,50.33436],[12.1187616,50.25152],[12.2234934,50.1653411],[12.2035445,50.1237921],[12.5027784,49.9732751],[12.4778422,49.9379795],[12.5476634,49.9155052],[12.4678677,49.8029766],[12.408021,49.7611134],[12.4828294,49.6869593],[12.5327017,49.6869593],[12.5177401,49.6288466],[12.6075102,49.5415474],[12.6723442,49.4378793],[12.8119867,49.3469896],[12.9466419,49.3437405],[13.2309141,49.1288206],[13.3256715,49.1059712],[13.4353906,49.0438984],[13.4154417,48.9948387],[13.5002246,48.949006],[13.5650586,48.9882938],[13.6847522,48.8834577],[13.7445989,48.9031312],[13.8243946,48.7751149],[13.8992031,48.7751149],[14.0587945,48.676418],[14.0438328,48.6302932],[14.1435774,48.5907241],[14.3729901,48.5610269],[14.4827091,48.6500662],[14.5774665,48.607215],[14.6273389,48.6335892],[14.7071346,48.5808269],[14.7470324,48.7027561],[14.8118664,48.7389485],[14.8168536,48.794831],[14.9864195,48.7652539],[15.0063684,49.0177392]]],"terms_url":"http://poloha.net/"},{"id":"Czech_RUIAN-parcely","name":"Czech RUIAN parcely","type":"tms","template":"http://tile.poloha.net/parcely/{zoom}/{x}/{y}.png","scaleExtent":[12,20],"polygon":[[[15.0063684,49.0177392],[15.1559854,49.0013828],[15.190896,48.9424551],[15.3105895,48.9882938],[15.4053469,48.9752013],[15.5400022,48.9162426],[15.7145553,48.8670572],[15.8342488,48.880178],[15.968904,48.8178233],[16.0885976,48.7455261],[16.3978059,48.7455261],[16.4875761,48.8145394],[16.6721036,48.7784014],[16.6820781,48.7356594],[16.9015163,48.7126294],[16.9464014,48.6237005],[17.1159672,48.8375227],[17.2107246,48.880178],[17.4052266,48.8178233],[17.4800351,48.8539329],[17.5299074,48.8178233],[17.7044605,48.8670572],[17.8141796,48.9359033],[17.8840008,48.9359033],[17.9438476,49.0210099],[18.0635412,49.0340903],[18.1184007,49.0994409],[18.1981964,49.3047337],[18.3877112,49.3339917],[18.577226,49.5091747],[18.7567663,49.4994587],[18.8465365,49.5253637],[18.8764598,49.5706645],[18.7966641,49.693412],[18.64206,49.7095399],[18.5872004,49.8351543],[18.6121366,49.8833809],[18.5622643,49.9347695],[18.512392,49.9058702],[18.362775,49.9540261],[18.3278644,49.9219275],[18.2630304,49.9732751],[18.1184007,50.0053395],[18.0635412,50.075806],[17.9139242,49.9796897],[17.779269,50.0309757],[17.714435,50.1237921],[17.6047159,50.1653411],[17.7593201,50.21962],[17.7343839,50.3439092],[17.6396265,50.2802117],[17.3802905,50.2802117],[17.3503671,50.3439092],[17.2805459,50.3375433],[17.1857885,50.4075214],[16.9015163,50.4615247],[16.8666057,50.4138779],[16.9663503,50.3184404],[17.0361715,50.2323826],[16.8366823,50.21962],[16.7120015,50.1046034],[16.5823335,50.1589513],[16.5623846,50.2387626],[16.4327166,50.3375433],[16.3529209,50.3916263],[16.2781124,50.3916263],[16.2082911,50.4456477],[16.3978059,50.5344899],[16.4476782,50.5978464],[16.3529209,50.670601],[16.2382145,50.6769221],[16.2182656,50.6326561],[16.1284954,50.6832425],[16.0486997,50.6073425],[15.988853,50.7021983],[15.8741467,50.6832425],[15.8292616,50.7653291],[15.729517,50.743243],[15.450232,50.8157725],[15.3903852,50.7747914],[15.3804108,50.8598659],[15.2956278,50.8850434],[15.2956278,50.9887568],[15.1709471,51.0201394],[14.9914067,51.0013124],[15.0063684,50.8881896],[14.8417898,50.8756034],[14.7969047,50.8252246],[14.6323261,50.8567177],[14.6622495,50.9353576],[14.5724793,50.9227841],[14.6123772,50.9856174],[14.4976708,51.0483657],[14.4178751,51.0232765],[14.3081561,51.0671736],[14.2532965,51.0044508],[14.4029134,50.9322145],[14.3729901,50.897627],[14.2433221,50.9070625],[14.2084114,50.844123],[14.0338583,50.8126214],[13.9789988,50.8252246],[13.9041903,50.7968626],[13.8742669,50.740087],[13.5351352,50.7243038],[13.530148,50.6579561],[13.4703012,50.6136722],[13.3905055,50.664279],[13.3256715,50.5883483],[13.250863,50.6105074],[13.1960035,50.5059517],[13.0513738,50.5218084],[12.9665909,50.4106997],[12.8269484,50.4710483],[12.7022676,50.4138779],[12.5077656,50.401164],[12.343187,50.2547088],[12.323238,50.1845054],[12.2484296,50.2738373],[12.1736211,50.3311765],[12.0988126,50.33436],[12.1187616,50.25152],[12.2234934,50.1653411],[12.2035445,50.1237921],[12.5027784,49.9732751],[12.4778422,49.9379795],[12.5476634,49.9155052],[12.4678677,49.8029766],[12.408021,49.7611134],[12.4828294,49.6869593],[12.5327017,49.6869593],[12.5177401,49.6288466],[12.6075102,49.5415474],[12.6723442,49.4378793],[12.8119867,49.3469896],[12.9466419,49.3437405],[13.2309141,49.1288206],[13.3256715,49.1059712],[13.4353906,49.0438984],[13.4154417,48.9948387],[13.5002246,48.949006],[13.5650586,48.9882938],[13.6847522,48.8834577],[13.7445989,48.9031312],[13.8243946,48.7751149],[13.8992031,48.7751149],[14.0587945,48.676418],[14.0438328,48.6302932],[14.1435774,48.5907241],[14.3729901,48.5610269],[14.4827091,48.6500662],[14.5774665,48.607215],[14.6273389,48.6335892],[14.7071346,48.5808269],[14.7470324,48.7027561],[14.8118664,48.7389485],[14.8168536,48.794831],[14.9864195,48.7652539],[15.0063684,49.0177392]]],"terms_url":"http://poloha.net/"},{"id":"Duna_2013","name":"Danube flood 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","description":"This data set consists of 0.3-meter pixel resolution (approximately 1-foot), 4-band true color and near infrared (R, G, B, IR) orthoimages covering New Castle, Kent and Sussex Counties in Delaware.","polygon":[[[-75.01770587603,38.45188674427],[-75.74173524589,38.4499581145],[-75.80699639658,39.73907123636],[-75.75558784863,39.80106251053],[-75.64692187603,39.8563815616],[-75.47114773904,39.84645578141],[-75.37725787603,39.81477822231],[-75.48746302671,39.6718115509],[-75.50901151986,39.43446011595],[-75.39326532808,39.27784018498],[-75.30707135548,39.01666513594],[-75.1931721774,38.82218696272],[-75.05341480753,38.80875503297],[-75.01770587603,38.45188674427]]],"terms_url":"https://firstmap.delaware.gov/arcgis/rest/services/DE_Imagery/DE_Imagery_2012/ImageServer","terms_text":"Digital Aerial Solutions, LLC"},{"id":"DigitalGlobe-Premium","name":"DigitalGlobe Premium Imagery","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/digitalglobe.316c9a2e/{zoom}/{x}/{y}.png?access_token=pk.eyJ1IjoiZGlnaXRhbGdsb2JlIiwiYSI6ImNqMmFxdGp5aTAwOWIzM3M1NDZ2eGU1a2QifQ.JN5adNxCwK_oprEwFEtjjg","scaleExtent":[0,19],"terms_url":"https://wiki.openstreetmap.org/wiki/DigitalGlobe","terms_text":"Terms & Feedback","default":true},{"id":"DigitalGlobe-Standard","name":"DigitalGlobe Standard Imagery","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/digitalglobe.0a8e44ba/{zoom}/{x}/{y}.png?access_token=pk.eyJ1IjoiZGlnaXRhbGdsb2JlIiwiYSI6ImNqMmFxcGJ2MjAwOHEzMm9nZmF2c3luZWkifQ.HsF19zOlj8PeOxo5BhNqyQ","scaleExtent":[0,19],"terms_url":"https://wiki.openstreetmap.org/wiki/DigitalGlobe","terms_text":"Terms & Feedback","default":true},{"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","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","scaleExtent":[0,17],"polygon":[[[16.1139147,46.8691038],[16.1789749,46.90662],[16.2000429,46.9415079],[16.2217547,46.9355441],[16.2462784,46.9463851],[16.2553226,46.9642125],[16.2764694,46.9626082],[16.290583,47.0139849],[16.3016199,46.9992329],[16.3414618,46.9965225],[16.3505162,47.0106313],[16.3734016,46.9985929],[16.412765,47.00475],[16.4332705,46.9927417],[16.4478119,47.003893],[16.479997,46.9941169],[16.5121988,47.0011695],[16.4635584,47.0322699],[16.4478586,47.0227481],[16.439123,47.029663],[16.445673,47.038872],[16.520323,47.056103],[16.473213,47.0736169],[16.4637199,47.09392],[16.500798,47.110058],[16.500035,47.123295],[16.5295349,47.1287419],[16.5171609,47.1496938],[16.454951,47.1425878],[16.4648728,47.1683349],[16.4555643,47.1875584],[16.4305559,47.1847022],[16.4195013,47.1949147],[16.4189215,47.2107114],[16.4371293,47.2097043],[16.4426335,47.2337117],[16.4313127,47.2527554],[16.4671512,47.2531652],[16.4892319,47.2798885],[16.4646338,47.3338455],[16.4337002,47.3528101],[16.458513,47.3670496],[16.4454619,47.4070195],[16.4831657,47.4093628],[16.4963821,47.3892659],[16.5170941,47.4100218],[16.5749054,47.4054243],[16.5807291,47.4191699],[16.661847,47.455595],[16.6706419,47.47422],[16.6523395,47.500342],[16.6895619,47.510161],[16.7147797,47.540199],[16.663545,47.567733],[16.673199,47.6049544],[16.6595343,47.6061018],[16.652758,47.622852],[16.6314207,47.6283176],[16.5739108,47.619667],[16.5147382,47.6461964],[16.4967504,47.6393149],[16.425464,47.6621679],[16.4437449,47.674205],[16.4480507,47.6964725],[16.4746984,47.6811576],[16.4872245,47.6979767],[16.5521729,47.7225519],[16.5363779,47.736785],[16.5479799,47.751544],[16.6095193,47.7603722],[16.6344148,47.7590843],[16.65729,47.7414879],[16.7209405,47.7353565],[16.7534062,47.6828165],[16.8301587,47.681058],[16.8394284,47.7045139],[16.8668943,47.7211462],[16.876679,47.6876452],[17.0937421,47.7077706],[17.0706562,47.7285366],[17.0516019,47.7938499],[17.0749479,47.8084997],[17.047139,47.8285635],[17.0519452,47.8377691],[17.0105513,47.8581765],[17.0163878,47.8673325],[17.0857537,47.8746239],[17.113171,47.9271605],[17.0917133,47.9342916],[17.1183782,47.9601083],[17.094657,47.9708775],[17.2010289,48.019992],[17.241769,48.0224651],[17.257955,47.998655],[17.334651,47.993125],[17.4029929,47.947849],[17.4539199,47.8852579],[17.5267369,47.865509],[17.5675779,47.8151289],[17.608402,47.8218859],[17.7085789,47.756678],[17.7798739,47.739487],[17.8660959,47.74575],[17.9001292,47.7392633],[17.946867,47.744668],[17.9708709,47.7578392],[18.0044103,47.7463402],[18.0380583,47.7576812],[18.2958774,47.7314616],[18.4540681,47.7651226],[18.4931553,47.7527552],[18.5590761,47.7659963],[18.6460866,47.7590921],[18.7260691,47.7890411],[18.7411784,47.8138245],[18.7920013,47.8230869],[18.8485417,47.8167221],[18.855876,47.826077],[18.828014,47.834291],[18.8135749,47.85555],[18.76353,47.8716049],[18.756858,47.896838],[18.776746,47.955092],[18.7552499,47.9763469],[18.8157429,47.993442],[18.819998,48.039676],[18.833268,48.048239],[18.8749364,48.0470707],[18.886674,48.058682],[18.9089819,48.051139],[18.9439039,48.058865],[18.9816099,48.0536009],[19.0148639,48.078179],[19.0585249,48.0573529],[19.0843619,48.072781],[19.107402,48.065596],[19.1352889,48.074146],[19.2413679,48.0536529],[19.2557819,48.0715559],[19.3031119,48.088711],[19.3865969,48.091914],[19.400018,48.082304],[19.454053,48.101436],[19.467354,48.083933],[19.4944199,48.109906],[19.492377,48.1396639],[19.5128219,48.154663],[19.504518,48.173443],[19.528967,48.190358],[19.526044,48.20313],[19.577502,48.2160149],[19.6308263,48.2500725],[19.6445239,48.2391719],[19.669857,48.239212],[19.691219,48.203894],[19.721125,48.201473],[19.74618,48.2165119],[19.7871629,48.19253],[19.7987329,48.19482],[19.8052829,48.183733],[19.782415,48.165039],[19.794812,48.153529],[19.821331,48.169081],[19.8452819,48.162742],[19.8551729,48.178431],[19.8601309,48.169409],[19.898745,48.1663119],[19.9145359,48.146863],[19.898298,48.1249019],[19.937383,48.131118],[19.9743939,48.1660049],[19.988706,48.1621679],[20.029038,48.1776849],[20.049449,48.1671999],[20.0729859,48.179606],[20.0700369,48.1917019],[20.1340909,48.225182],[20.1331879,48.253982],[20.206162,48.250979],[20.2038299,48.261906],[20.228466,48.262779],[20.2349469,48.279933],[20.286858,48.26164],[20.3257109,48.272794],[20.3374649,48.301667],[20.3656579,48.316606],[20.384077,48.3511809],[20.4098349,48.365857],[20.402532,48.382565],[20.4205349,48.403858],[20.416228,48.418536],[20.507929,48.489363],[20.5065069,48.534415],[20.537471,48.527878],[20.5464939,48.544292],[20.586595,48.535759],[20.6538739,48.561413],[20.836359,48.58284],[20.8378,48.57421],[20.8504359,48.5816329],[20.8453301,48.5665046],[20.8681549,48.551818],[20.922323,48.559453],[20.9346349,48.538341],[20.955882,48.533963],[20.9561979,48.521666],[20.9815849,48.5177669],[21.0151139,48.532313],[21.0663209,48.525894],[21.1174479,48.4910549],[21.1608749,48.521499],[21.179634,48.518232],[21.221061,48.537497],[21.305488,48.5222489],[21.313377,48.550841],[21.326875,48.554129],[21.319384,48.561201],[21.4154499,48.558951],[21.4226649,48.578821],[21.4406099,48.585104],[21.514091,48.551065],[21.5420199,48.508395],[21.6139329,48.509416],[21.6201879,48.469826],[21.663549,48.417961],[21.6645609,48.392164],[21.7017409,48.380695],[21.711871,48.357617],[21.8174139,48.332787],[21.8352029,48.3346409],[21.837213,48.363253],[21.8842979,48.356047],[21.8848429,48.367539],[21.897883,48.36256],[21.8997959,48.3702229],[21.9281859,48.3615969],[21.9268059,48.370899],[21.949198,48.378728],[21.994463,48.377323],[22.0213259,48.392749],[22.0546049,48.377528],[22.0764859,48.387241],[22.086743,48.371564],[22.1359089,48.380519],[22.131056,48.3912329],[22.152768,48.3962409],[22.1561913,48.4093076],[22.2125722,48.4256468],[22.2371405,48.4100396],[22.2654858,48.4098675],[22.2398761,48.3870055],[22.2675722,48.3611612],[22.3178106,48.3545437],[22.3132861,48.3250712],[22.3372944,48.3079113],[22.3384267,48.2792074],[22.3847547,48.2339632],[22.4006407,48.249198],[22.4328384,48.2525166],[22.456386,48.2423109],[22.4899029,48.2534237],[22.4972201,48.2395546],[22.5161491,48.237965],[22.5311088,48.2094282],[22.5711442,48.1961428],[22.5616362,48.1816066],[22.5982449,48.144756],[22.5902763,48.1073414],[22.6754492,48.091997],[22.7347192,48.119848],[22.7576242,48.1200599],[22.7703914,48.1090162],[22.772319,48.1218742],[22.8027688,48.1221112],[22.8025285,48.1070813],[22.8254256,48.1175119],[22.8364365,48.080249],[22.8611284,48.0750312],[22.8677955,48.0524256],[22.8820424,48.0548053],[22.8659692,48.0113165],[22.835562,47.9905988],[22.8407599,47.9813636],[22.8725729,47.9752683],[22.8697274,47.9659593],[22.8915652,47.9672446],[22.897435,47.9540629],[22.8473299,47.9077579],[22.7928135,47.8908586],[22.7586924,47.8941446],[22.77775,47.8422508],[22.7136344,47.8360928],[22.6801938,47.7877527],[22.6111171,47.7717455],[22.5490018,47.7722246],[22.4812121,47.8108886],[22.4513078,47.803389],[22.4313319,47.7398119],[22.3566167,47.7486206],[22.3177714,47.7660887],[22.3176236,47.7433657],[22.2851369,47.7292757],[22.264325,47.7310675],[22.2589955,47.6979057],[22.2306796,47.693196],[22.1796501,47.5916115],[22.1289245,47.5978984],[22.0942787,47.5583628],[22.0782587,47.5621299],[22.0534529,47.5474795],[22.0712176,47.5380742],[22.0617872,47.5288029],[22.0451278,47.5398919],[22.0367222,47.5326653],[22.0071886,47.48362],[22.0327909,47.4508372],[22.0238835,47.3908631],[22.0119849,47.3758016],[21.9627373,47.381053],[21.9382461,47.3725317],[21.8777922,47.2857763],[21.8872845,47.2730473],[21.8534909,47.2397622],[21.8580662,47.1873597],[21.8124804,47.1667511],[21.7924092,47.1059751],[21.7268258,47.0983882],[21.6976037,47.057915],[21.6504151,47.0408303],[21.6888701,47.0019977],[21.6678744,46.9712337],[21.6814917,46.9652089],[21.6381964,46.9330487],[21.5984455,46.9274708],[21.6142857,46.8867275],[21.6016694,46.8668202],[21.520328,46.8373749],[21.5186086,46.8000703],[21.4831761,46.7650246],[21.5263389,46.7393249],[21.529369,46.7209721],[21.4923253,46.6859652],[21.4728438,46.6959075],[21.4299047,46.693937],[21.4309553,46.6781367],[21.4546661,46.660863],[21.4162375,46.6426231],[21.4097959,46.6218052],[21.3657038,46.6379501],[21.3300499,46.6318155],[21.3139733,46.617666],[21.3012351,46.5908672],[21.3207905,46.5828562],[21.2743045,46.5407362],[21.2600254,46.5021583],[21.2744188,46.4767333],[21.2964506,46.4762973],[21.3174343,46.4507288],[21.2895176,46.4154784],[21.2963256,46.4069601],[21.2250116,46.4136899],[21.2064214,46.4033825],[21.1992563,46.3479034],[21.1762269,46.3357664],[21.180497,46.3044494],[21.1155437,46.3018529],[21.1030549,46.2624637],[21.0708792,46.2539014],[21.0660827,46.2429394],[21.0366237,46.2480392],[21.0246723,46.2665329],[20.960817,46.2623039],[20.9465849,46.2793024],[20.9250701,46.2766191],[20.9218133,46.2618129],[20.8732713,46.2877555],[20.7756538,46.2759602],[20.7490474,46.2508489],[20.7618619,46.204563],[20.727401,46.2077485],[20.7341052,46.1939355],[20.7140487,46.1660531],[20.6843592,46.1447802],[20.6549178,46.1497739],[20.6394471,46.1267602],[20.5450486,46.1790935],[20.5014839,46.190334],[20.4949436,46.1709908],[20.4592293,46.1428837],[20.3975133,46.1574709],[20.3685325,46.1528554],[20.3557074,46.1696256],[20.2968136,46.1521542],[20.2549024,46.1158522],[20.2484757,46.1300956],[20.2330132,46.1241668],[20.1817362,46.1601137],[20.1364966,46.1449476],[20.1009667,46.1772756],[20.0636156,46.1437275],[20.0346142,46.1458888],[20.0158072,46.1768354],[19.9354075,46.1764243],[19.8533469,46.1500005],[19.8179747,46.1281652],[19.7585403,46.1479754],[19.6982054,46.1879317],[19.6827672,46.1800388],[19.661508,46.1904394],[19.6317396,46.1692993],[19.5676482,46.179106],[19.5604013,46.1665762],[19.5026585,46.1424492],[19.5271208,46.1210269],[19.4645033,46.0953827],[19.4665828,46.0820437],[19.4160037,46.0460453],[19.3803957,46.0358749],[19.3640923,46.0522965],[19.2819012,46.0148048],[19.2965348,45.9881173],[19.2856472,45.9968981],[19.1479857,45.9963445],[19.1338422,46.0370993],[19.104873,46.0401673],[19.0660427,46.0001999],[19.0796791,45.9636376],[19.0059803,45.9590674],[19.0092745,45.9236559],[18.9061334,45.9353801],[18.8794572,45.9166827],[18.8647137,45.9208493],[18.8685629,45.9113361],[18.8276792,45.9051714],[18.8220041,45.9145893],[18.8075092,45.9036055],[18.809247,45.8796189],[18.7956242,45.8784488],[18.7048857,45.9181883],[18.6700246,45.9108439],[18.6596602,45.9168934],[18.6651348,45.899279],[18.6412808,45.8890396],[18.6550179,45.8742393],[18.6277704,45.8733782],[18.6148449,45.8531438],[18.6236656,45.8398531],[18.5732391,45.8137578],[18.5749849,45.8004344],[18.559716,45.8037961],[18.5223504,45.7826858],[18.4906706,45.7947167],[18.4821905,45.7655032],[18.4562828,45.7695229],[18.4450763,45.7605195],[18.446853,45.737128],[18.40763,45.7397119],[18.3918949,45.7616983],[18.3642257,45.7729364],[18.3394214,45.7471605],[18.2968157,45.7612196],[18.2440473,45.7612305],[18.2307311,45.7790328],[18.1908702,45.7878759],[18.1681939,45.7762712],[18.1246514,45.7896277],[18.1068067,45.7708256],[18.0818922,45.7645205],[17.9958808,45.7957311],[17.9302095,45.7863301],[17.9066757,45.7925692],[17.8653145,45.7670064],[17.8262748,45.8099957],[17.8089784,45.8040989],[17.7809054,45.8174884],[17.7603399,45.811923],[17.7408624,45.8295975],[17.6632915,45.8381849],[17.6276211,45.8979446],[17.5700676,45.9358204],[17.4378254,45.9503823],[17.4258964,45.9272681],[17.4108059,45.9399665],[17.392149,45.9302149],[17.3828713,45.9475733],[17.3476208,45.9423413],[17.3438769,45.9605329],[17.3537711,45.9525011],[17.3905375,45.9581914],[17.387423,45.9661823],[17.3583539,45.9642737],[17.3754852,45.9686921],[17.3751895,45.9881054],[17.3635685,45.9915442],[17.3567202,45.9735836],[17.3339583,45.9960781],[17.3319847,45.9728948],[17.3129974,45.9665347],[17.323647,45.9887776],[17.2987653,45.9838652],[17.3041996,46.0021128],[17.2579726,46.0110256],[17.29632,46.0285169],[17.2541514,46.030005],[17.270955,46.0567055],[17.2324767,46.0592034],[17.2525145,46.0664725],[17.2313144,46.0790345],[17.2019916,46.0765488],[17.2331299,46.0989644],[17.2104017,46.1001693],[17.2129734,46.113855],[17.175927,46.1084583],[17.1743424,46.1287608],[17.1865197,46.1332308],[17.1810983,46.1505485],[17.1562307,46.1585819],[17.1592857,46.1696818],[17.1261012,46.1684495],[17.1227409,46.1789791],[17.0752482,46.1889531],[17.0661614,46.2022984],[16.9735401,46.2251982],[16.973954,46.2431113],[16.9504085,46.2415285],[16.8862356,46.2814598],[16.8713682,46.3252767],[16.8802109,46.3356966],[16.8615374,46.3452401],[16.8656232,46.3556489],[16.8521959,46.3517189],[16.8498589,46.3626245],[16.8352859,46.3638195],[16.8376499,46.3748032],[16.8261732,46.3670994],[16.7933444,46.387385],[16.7592072,46.3776563],[16.7298672,46.40149],[16.7182119,46.3898704],[16.6772872,46.4494536],[16.6631785,46.4486958],[16.6663732,46.4582995],[16.6187915,46.4619875],[16.604468,46.4760773],[16.5235997,46.5053761],[16.5325768,46.5314027],[16.5176728,46.5363516],[16.5084107,46.5652692],[16.4829969,46.5660383],[16.4834008,46.5786011],[16.4455713,46.610952],[16.4248583,46.6131645],[16.385941,46.6442485],[16.3915424,46.6637257],[16.4198454,46.6584771],[16.4286335,46.6939737],[16.3689211,46.7040082],[16.3798266,46.7153869],[16.3710856,46.7222945],[16.3570587,46.7142387],[16.3185954,46.7541449],[16.3305417,46.7752119],[16.3121626,46.7780033],[16.3127666,46.797314],[16.3406373,46.8051851],[16.3508404,46.8300552],[16.3403309,46.8468762],[16.3015007,46.8595142],[16.2913867,46.8728341],[16.2332296,46.8766702],[16.1560866,46.8537074],[16.126571,46.8569079],[16.1139147,46.8691038]]],"terms_url":"http://www.fomi.hu/","terms_text":"Földmérési és Távérzékelési Intézet"},{"id":"FR-BAN","name":"FR-BAN","type":"tms","template":"http://{switch:a,b,c}.layers.openstreetmap.fr/bano/{zoom}/{x}/{y}.png","description":"French address registry or Base Adresses Nationale","scaleExtent":[12,20],"polygon":[[[8.3247852,49.0891892],[6.1566882,49.6167369],[4.8666714,50.2126152],[2.4937064,51.1761675],[1.3121526,50.9324682],[1.2659981,50.1877492],[0.1121369,49.8258592],[-0.3494075,49.4312336],[-1.0232625,49.4852345],[-1.3278818,49.7901162],[-2.1032765,49.7901162],[-1.6232703,48.7420657],[-3.1002126,48.9728514],[-5.1125465,48.6811558],[-5.3525496,48.4367783],[-4.5984193,47.7194959],[-2.555398,47.0232784],[-2.4738077,46.6638823],[-1.6676954,46.1055717],[-1.334807,45.5141125],[-1.4914604,44.1627003],[-1.9940567,43.3708146],[-0.956228,42.7364747],[2.2029487,42.2841894],[3.2342502,42.5444129],[3.2407774,43.1140543],[4.0436261,43.3280964],[6.4325902,42.808345],[7.6270723,43.5934102],[7.8163619,44.1720643],[7.0396221,44.41967],[7.268075,45.4958141],[7.1244761,46.2140775],[6.5631347,46.771283],[7.6571492,47.59128],[7.6527839,47.5941813],[7.6224698,47.5776739],[7.6047297,47.578221],[7.5877054,47.5901532],[7.521558,47.65161],[7.503992,47.70235],[7.520958,47.77685],[7.557124,47.84839],[7.549463,47.879205],[7.574615,47.93028],[7.613179,47.96804],[7.611904,47.9871],[7.5612401,48.0383618],[7.574915,48.1258],[7.595338,48.15977],[7.633047,48.19717],[7.662748,48.22473],[7.684659,48.30305],[7.763463,48.49158],[7.8004602,48.5125977],[7.799582,48.5878],[7.834088,48.64439],[7.9121073,48.6889897],[7.9672295,48.7571585],[8.020692,48.78879],[8.043024,48.7956],[8.0864658,48.8130551],[8.1364418,48.8978239],[8.1970586,48.96021],[8.2816129,48.9948995],[8.2996723,49.025966],[8.3124269,49.0599642],[8.3247852,49.0891892]],[[9.3609615,43.1345098],[8.4393174,42.48439],[8.4836272,41.8175373],[8.8469677,41.3768281],[9.2058772,41.3136241],[9.48946,41.5461776],[9.6356823,42.1994563],[9.6046655,42.901254],[9.3609615,43.1345098]]],"terms_url":"https://wiki.openstreetmap.org/wiki/WikiProject_France/WikiProject_Base_Adresses_Nationale_Ouverte_(BANO)","terms_text":"Tiles © cquest@Openstreetmap France, data © OpenStreetMap contributors, ODBL"},{"id":"FR-Cadastre","name":"FR-Cadastre","type":"tms","template":"http://tms.cadastre.openstreetmap.fr/*/tout/{zoom}/{x}/{y}.png","description":"French land registry","scaleExtent":[12,20],"polygon":[[[8.3247852,49.0891892],[6.1566882,49.6167369],[4.8666714,50.2126152],[2.4937064,51.1761675],[1.3121526,50.9324682],[1.2659981,50.1877492],[0.1121369,49.8258592],[-0.3494075,49.4312336],[-1.0232625,49.4852345],[-1.3278818,49.7901162],[-2.1032765,49.7901162],[-1.6232703,48.7420657],[-3.1002126,48.9728514],[-5.1125465,48.6811558],[-5.3525496,48.4367783],[-4.5984193,47.7194959],[-2.555398,47.0232784],[-2.4738077,46.6638823],[-1.6676954,46.1055717],[-1.334807,45.5141125],[-1.4914604,44.1627003],[-1.9940567,43.3708146],[-0.956228,42.7364747],[2.2029487,42.2841894],[3.2342502,42.5444129],[3.2407774,43.1140543],[4.0436261,43.3280964],[6.4325902,42.808345],[7.6270723,43.5934102],[7.8163619,44.1720643],[7.0396221,44.41967],[7.268075,45.4958141],[7.1244761,46.2140775],[6.5631347,46.771283],[7.6571492,47.59128],[7.6527839,47.5941813],[7.6224698,47.5776739],[7.6047297,47.578221],[7.5877054,47.5901532],[7.521558,47.65161],[7.503992,47.70235],[7.520958,47.77685],[7.557124,47.84839],[7.549463,47.879205],[7.574615,47.93028],[7.613179,47.96804],[7.611904,47.9871],[7.5612401,48.0383618],[7.574915,48.1258],[7.595338,48.15977],[7.633047,48.19717],[7.662748,48.22473],[7.684659,48.30305],[7.763463,48.49158],[7.8004602,48.5125977],[7.799582,48.5878],[7.834088,48.64439],[7.9121073,48.6889897],[7.9672295,48.7571585],[8.020692,48.78879],[8.043024,48.7956],[8.0864658,48.8130551],[8.1364418,48.8978239],[8.1970586,48.96021],[8.2816129,48.9948995],[8.2996723,49.025966],[8.3124269,49.0599642],[8.3247852,49.0891892]],[[9.3609615,43.1345098],[8.4393174,42.48439],[8.4836272,41.8175373],[8.8469677,41.3768281],[9.2058772,41.3136241],[9.48946,41.5461776],[9.6356823,42.1994563],[9.6046655,42.901254],[9.3609615,43.1345098]]],"terms_url":"http://wiki.openstreetmap.org/wiki/WikiProject_Cadastre_Fran%C3%A7ais/Conditions_d%27utilisation","terms_text":"cadastre-dgi-fr source : Direction Générale des Impôts - Cadastre. Mise à jour : 2015"},{"id":"Freemap.sk-Car","name":"Freemap.sk Car","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/A/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"id":"Freemap.sk-Cyclo","name":"Freemap.sk Cyclo","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/C/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"id":"Freemap.sk-Hiking","name":"Freemap.sk Hiking","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/T/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"id":"Freemap.sk-Ski","name":"Freemap.sk Ski","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/K/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"id":"Geodatastyrelsen_Denmark","name":"Geodatastyrelsen (Denmark)","type":"tms","template":"http://osmtools.septima.dk/mapproxy/tiles/1.0.0/kortforsyningen_ortoforaar/EPSG3857/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,21],"polygon":[[[8.3743941,54.9551655],[8.3683809,55.4042149],[8.2103997,55.4039795],[8.2087314,55.4937345],[8.0502655,55.4924731],[8.0185123,56.7501399],[8.1819161,56.7509948],[8.1763274,57.0208898],[8.3413329,57.0219872],[8.3392467,57.1119574],[8.5054433,57.1123212],[8.5033923,57.2020499],[9.3316304,57.2027636],[9.3319079,57.2924835],[9.4978864,57.2919578],[9.4988593,57.3820608],[9.6649749,57.3811615],[9.6687295,57.5605591],[9.8351961,57.5596265],[9.8374896,57.6493322],[10.1725726,57.6462818],[10.1754245,57.7367768],[10.5118282,57.7330269],[10.5152095,57.8228945],[10.6834853,57.8207722],[10.6751613,57.6412021],[10.5077045,57.6433097],[10.5039992,57.5535088],[10.671038,57.5514113],[10.6507805,57.1024538],[10.4857673,57.1045138],[10.4786236,56.9249051],[10.3143981,56.9267573],[10.3112341,56.8369269],[10.4750295,56.83509],[10.4649016,56.5656681],[10.9524239,56.5589761],[10.9479249,56.4692243],[11.1099335,56.4664675],[11.1052639,56.376833],[10.9429901,56.3795284],[10.9341235,56.1994768],[10.7719685,56.2020244],[10.7694751,56.1120103],[10.6079695,56.1150259],[10.4466742,56.116717],[10.2865948,56.118675],[10.2831527,56.0281851],[10.4439274,56.0270388],[10.4417713,55.7579243],[10.4334961,55.6693533],[10.743814,55.6646861],[10.743814,55.5712253],[10.8969041,55.5712253],[10.9051793,55.3953852],[11.0613726,55.3812841],[11.0593038,55.1124061],[11.0458567,55.0318621],[11.2030844,55.0247474],[11.2030844,55.117139],[11.0593038,55.1124061],[11.0613726,55.3812841],[11.0789572,55.5712253],[10.8969041,55.5712253],[10.9258671,55.6670198],[10.743814,55.6646861],[10.7562267,55.7579243],[10.4417713,55.7579243],[10.4439274,56.0270388],[10.4466742,56.116717],[10.6079695,56.1150259],[10.6052053,56.0247462],[10.9258671,56.0201215],[10.9197132,55.9309388],[11.0802782,55.92792],[11.0858066,56.0178284],[11.7265047,56.005058],[11.7319981,56.0952142],[12.0540333,56.0871256],[12.0608477,56.1762576],[12.7023469,56.1594405],[12.6611131,55.7114318],[12.9792318,55.7014026],[12.9612912,55.5217294],[12.3268659,55.5412096],[12.3206071,55.4513655],[12.4778226,55.447067],[12.4702432,55.3570479],[12.6269738,55.3523837],[12.6200898,55.2632576],[12.4627339,55.26722],[12.4552949,55.1778223],[12.2987046,55.1822303],[12.2897344,55.0923641],[12.6048608,55.0832904],[12.5872011,54.9036285],[12.2766618,54.9119031],[12.2610181,54.7331602],[12.1070691,54.7378161],[12.0858621,54.4681655],[11.7794953,54.4753579],[11.7837381,54.5654783],[11.1658525,54.5782155],[11.1706443,54.6686508],[10.8617173,54.6733956],[10.8651245,54.7634667],[10.7713646,54.7643888],[10.7707276,54.7372807],[10.7551428,54.7375776],[10.7544039,54.7195666],[10.7389074,54.7197588],[10.7384368,54.7108482],[10.7074486,54.7113045],[10.7041094,54.6756741],[10.5510973,54.6781698],[10.5547184,54.7670245],[10.2423994,54.7705935],[10.2459845,54.8604673],[10.0902268,54.8622134],[10.0873731,54.7723851],[9.1555798,54.7769557],[9.1562752,54.8675369],[8.5321973,54.8663765],[8.531432,54.95516],[8.3743941,54.9551655]],[[11.4577738,56.819554],[11.7849181,56.8127385],[11.7716715,56.6332796],[11.4459621,56.6401087],[11.4577738,56.819554]],[[11.3274736,57.3612962],[11.3161808,57.1818004],[11.1508692,57.1847276],[11.1456628,57.094962],[10.8157703,57.1001693],[10.8290599,57.3695272],[11.3274736,57.3612962]],[[11.5843266,56.2777928],[11.5782882,56.1880397],[11.7392309,56.1845765],[11.7456428,56.2743186],[11.5843266,56.2777928]],[[14.6825922,55.3639405],[14.8395247,55.3565231],[14.8263755,55.2671261],[15.1393406,55.2517359],[15.1532015,55.3410836],[15.309925,55.3330556],[15.295719,55.2437356],[15.1393406,55.2517359],[15.1255631,55.1623802],[15.2815819,55.1544167],[15.2535578,54.9757646],[14.6317464,55.0062496],[14.6825922,55.3639405]]],"terms_url":"http://download.kortforsyningen.dk/content/vilkaar-og-betingelser","terms_text":"Geodatastyrelsen og Danske Kommuner","best":true},{"id":"Geoportal-PL-aerial_image","name":"Geoportal.gov.pl (Orthophotomap)","type":"tms","template":"http://wms.misek.pl/geoportal.orto/tms/{zoom}/{x}/{y}","scaleExtent":[6,24],"polygon":[[[15.9751041,54.3709213],[16.311164,54.5561775],[17.1391878,54.7845723],[18.3448458,54.9022727],[19.6613689,54.4737213],[20.2815206,54.4213456],[21.4663914,54.3406369],[22.7759855,54.3769755],[22.8625989,54.4233613],[23.2956657,54.2678633],[23.5347186,54.0955258],[23.5208604,53.9775182],[23.7183389,53.4629603],[23.9296755,53.1856735],[23.9296755,52.6887269],[23.732197,52.6067497],[23.5658994,52.5878101],[23.2090523,52.3302642],[23.1951942,52.2370089],[23.5035377,52.1860596],[23.6906226,52.0030113],[23.5970802,51.739903],[23.6629063,51.3888562],[23.9366046,50.9827781],[24.1687284,50.8604752],[24.0197534,50.8035823],[24.1098313,50.6610467],[24.0578633,50.4188439],[23.6178674,50.3083403],[22.6824431,49.5163532],[22.7378756,49.2094935],[22.9041733,49.0780441],[22.8625989,48.9940062],[22.6096878,49.0371785],[22.0761495,49.2004392],[21.8474902,49.3721872],[21.3763135,49.4488281],[21.1026153,49.3721872],[20.9120659,49.3022043],[20.6452967,49.3902311],[20.1845136,49.3315641],[20.1186875,49.2004392],[19.9419962,49.1302123],[19.765305,49.2117568],[19.7479823,49.3992506],[19.6024718,49.4150307],[19.5089294,49.5815389],[19.4292451,49.5905232],[19.2317666,49.4150307],[18.9961783,49.387976],[18.9338167,49.4916048],[18.8368097,49.4938552],[18.8021643,49.6623381],[18.6427958,49.7094091],[18.521537,49.8994693],[18.0815412,50.0109209],[17.8875272,49.9886512],[17.7385522,50.0687739],[17.6068999,50.1709584],[17.7454813,50.2153184],[17.710836,50.3017019],[17.4163505,50.2640668],[16.9486384,50.4453265],[16.8932058,50.4033889],[17.0006064,50.3105529],[17.017929,50.2241854],[16.8135215,50.186489],[16.6402948,50.0976742],[16.4324227,50.2862087],[16.1968344,50.4276731],[16.4220291,50.5885165],[16.3388803,50.6632429],[16.2280152,50.6368824],[16.0547884,50.6127057],[15.5732181,50.7641544],[15.2683391,50.8976368],[15.2440873,50.980597],[15.0292862,51.0133036],[15.0015699,50.8582883],[14.8110205,50.8735944],[14.956531,51.0721176],[15.0188926,51.2914636],[14.9392083,51.4601459],[14.7209426,51.5571799],[14.7521234,51.6260562],[14.5996839,51.8427626],[14.70362,52.0733396],[14.5581095,52.2497371],[14.5165351,52.425436],[14.6031485,52.5878101],[14.1146491,52.8208272],[14.152759,52.9733951],[14.3502374,53.0734212],[14.4229927,53.2665624],[14.1977979,53.8734759],[14.2220497,53.9958517],[15.9751041,54.3709213]]],"terms_text":"Copyright © Główny Urząd Geodezji i Kartografii.","best":true},{"id":"IBGE_DF_Addresses","name":"IBGE Distrito Federal","type":"tms","template":"https://api.mapbox.com/styles/v1/wille/cirnnxni1000jg8nfppc8g7pm/tiles/256/{zoom}/{x}/{y}?access_token=pk.eyJ1Ijoid2lsbGUiLCJhIjoicFNVWk5VWSJ9.hluCd0YGvYHNlFi_utWe2g","description":"Addresses data from IBGE","scaleExtent":[0,19],"polygon":[[[-48.2444,-16.0508],[-48.2444,-15.5005],[-47.5695,-15.5005],[-47.5695,-16.0508],[-48.2444,-16.0508]]],"overlay":true},{"id":"IBGE_Setores_Rurais","name":"IBGE Mapa de Setores Rurais","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/tmpsantos.i00mo1kj/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,14],"polygon":[[[-29.3325,2.335959],[-28.72472,2.031551],[-27.76041,-8.937033],[-27.67249,-22.20839],[-51.11495,-35.46552],[-53.39394,-33.85064],[-53.62553,-33.72493],[-53.62503,-33.15428],[-53.24498,-32.73392],[-53.65747,-32.51873],[-53.8329,-32.16592],[-54.64174,-31.55507],[-55.29638,-31.3429],[-55.57371,-30.99691],[-56.06384,-31.16749],[-56.10468,-30.86436],[-56.86862,-30.20752],[-57.39671,-30.40464],[-57.74384,-30.22142],[-55.83724,-28.16598],[-54.86969,-27.44994],[-53.9016,-27.02998],[-53.74972,-26.25781],[-53.97158,-25.74513],[-54.44723,-25.79609],[-54.67802,-25.64668],[-54.36097,-24.35145],[-54.41679,-24.06527],[-54.64355,-23.94107],[-55.22163,-24.11355],[-55.49138,-24.02797],[-55.71734,-22.68488],[-55.90555,-22.39886],[-56.45255,-22.21731],[-56.8256,-22.4002],[-57.34109,-22.34351],[-58.08472,-22.13075],[-57.95766,-20.99818],[-58.26551,-20.24147],[-58.03577,-19.95871],[-58.23083,-19.75211],[-57.64739,-18.19828],[-57.89356,-17.57377],[-58.16997,-17.53519],[-58.48825,-17.21961],[-58.57691,-16.81466],[-58.45563,-16.42158],[-60.2541,-16.32571],[-60.33481,-15.51483],[-60.67423,-15.1122],[-60.34999,-14.99707],[-60.63603,-13.84119],[-61.07283,-13.62569],[-61.9025,-13.62647],[-62.21395,-13.25048],[-62.80185,-13.10905],[-63.17194,-12.76568],[-63.74229,-12.54071],[-64.32845,-12.59578],[-65.10261,-12.0682],[-65.45781,-11.27865],[-65.41641,-9.838943],[-66.52331,-9.985873],[-67.66452,-10.80093],[-67.99778,-10.75991],[-68.52286,-11.20807],[-69.88988,-11.02776],[-70.30957,-11.1699],[-70.71896,-11.02003],[-70.68128,-9.669083],[-71.27536,-10.08971],[-72.18053,-10.09967],[-72.41623,-9.587397],[-73.29207,-9.454149],[-73.0625,-9.017267],[-73.61432,-8.40982],[-74.09056,-7.527548],[-74.03652,-7.27885],[-73.84718,-7.238285],[-73.78618,-6.774872],[-73.22362,-6.430106],[-73.33719,-6.029736],[-72.93016,-5.038711],[-71.93973,-4.425027],[-70.96802,-4.248294],[-70.79598,-4.064931],[-70.02393,-4.167345],[-69.51025,-1.134089],[-69.70776,-0.567619],[-70.13645,-0.226161],[-70.14083,0.5844],[-69.26594,0.806502],[-69.34226,0.968924],[-69.92481,1.015705],[-69.92343,1.773851],[-68.38511,1.82943],[-68.24848,2.119808],[-67.94571,1.948424],[-67.37696,2.327468],[-67.05751,1.858336],[-67.00579,1.291603],[-66.79967,1.314684],[-66.28683,0.857709],[-65.67671,1.111146],[-65.42494,0.966549],[-65.15671,1.24203],[-64.27483,1.601591],[-64.0486,2.065137],[-63.47236,2.279358],[-64.13446,2.433909],[-64.10005,2.723778],[-64.32628,3.118275],[-64.28142,3.541983],[-64.88451,4.117671],[-64.88064,4.342461],[-64.13653,4.223152],[-63.95465,4.021316],[-63.17706,4.048301],[-62.96093,3.763658],[-62.82024,4.106019],[-62.49922,4.270815],[-61.91181,4.26284],[-61.35393,4.630097],[-61.04904,4.623115],[-60.70452,4.969851],[-60.78709,5.296764],[-60.22457,5.371207],[-59.89857,5.107541],[-59.97549,4.603025],[-59.59676,4.439875],[-59.41942,3.96994],[-59.71017,3.542008],[-59.88955,2.72301],[-59.63006,2.316332],[-59.63382,1.966581],[-59.18812,1.478079],[-58.80545,1.320732],[-58.35933,1.689932],[-57.6,1.803907],[-57.39854,2.065119],[-57.12392,2.128758],[-56.02925,1.949445],[-56.23884,2.263348],[-55.98195,2.628657],[-55.64816,2.519953],[-54.93958,2.682515],[-54.24988,2.25056],[-53.73937,2.473731],[-52.98578,2.280494],[-52.65712,2.564069],[-52.41739,3.22121],[-51.73983,4.119158],[-51.7246,4.556867],[-51.0112,5.522895],[-43.48209,5.335832],[-29.3325,2.335959]]]},{"id":"IBGE_Setores_Urbanos","name":"IBGE Mapa de Setores Urbanos","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/tmpsantos.hgda0m6h/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,19],"polygon":[[[-29.3325,2.335959],[-28.72472,2.031551],[-27.76041,-8.937033],[-27.67249,-22.20839],[-51.11495,-35.46552],[-53.39394,-33.85064],[-53.62553,-33.72493],[-53.62503,-33.15428],[-53.24498,-32.73392],[-53.65747,-32.51873],[-53.8329,-32.16592],[-54.64174,-31.55507],[-55.29638,-31.3429],[-55.57371,-30.99691],[-56.06384,-31.16749],[-56.10468,-30.86436],[-56.86862,-30.20752],[-57.39671,-30.40464],[-57.74384,-30.22142],[-55.83724,-28.16598],[-54.86969,-27.44994],[-53.9016,-27.02998],[-53.74972,-26.25781],[-53.97158,-25.74513],[-54.44723,-25.79609],[-54.67802,-25.64668],[-54.36097,-24.35145],[-54.41679,-24.06527],[-54.64355,-23.94107],[-55.22163,-24.11355],[-55.49138,-24.02797],[-55.71734,-22.68488],[-55.90555,-22.39886],[-56.45255,-22.21731],[-56.8256,-22.4002],[-57.34109,-22.34351],[-58.08472,-22.13075],[-57.95766,-20.99818],[-58.26551,-20.24147],[-58.03577,-19.95871],[-58.23083,-19.75211],[-57.64739,-18.19828],[-57.89356,-17.57377],[-58.16997,-17.53519],[-58.48825,-17.21961],[-58.57691,-16.81466],[-58.45563,-16.42158],[-60.2541,-16.32571],[-60.33481,-15.51483],[-60.67423,-15.1122],[-60.34999,-14.99707],[-60.63603,-13.84119],[-61.07283,-13.62569],[-61.9025,-13.62647],[-62.21395,-13.25048],[-62.80185,-13.10905],[-63.17194,-12.76568],[-63.74229,-12.54071],[-64.32845,-12.59578],[-65.10261,-12.0682],[-65.45781,-11.27865],[-65.41641,-9.838943],[-66.52331,-9.985873],[-67.66452,-10.80093],[-67.99778,-10.75991],[-68.52286,-11.20807],[-69.88988,-11.02776],[-70.30957,-11.1699],[-70.71896,-11.02003],[-70.68128,-9.669083],[-71.27536,-10.08971],[-72.18053,-10.09967],[-72.41623,-9.587397],[-73.29207,-9.454149],[-73.0625,-9.017267],[-73.61432,-8.40982],[-74.09056,-7.527548],[-74.03652,-7.27885],[-73.84718,-7.238285],[-73.78618,-6.774872],[-73.22362,-6.430106],[-73.33719,-6.029736],[-72.93016,-5.038711],[-71.93973,-4.425027],[-70.96802,-4.248294],[-70.79598,-4.064931],[-70.02393,-4.167345],[-69.51025,-1.134089],[-69.70776,-0.567619],[-70.13645,-0.226161],[-70.14083,0.5844],[-69.26594,0.806502],[-69.34226,0.968924],[-69.92481,1.015705],[-69.92343,1.773851],[-68.38511,1.82943],[-68.24848,2.119808],[-67.94571,1.948424],[-67.37696,2.327468],[-67.05751,1.858336],[-67.00579,1.291603],[-66.79967,1.314684],[-66.28683,0.857709],[-65.67671,1.111146],[-65.42494,0.966549],[-65.15671,1.24203],[-64.27483,1.601591],[-64.0486,2.065137],[-63.47236,2.279358],[-64.13446,2.433909],[-64.10005,2.723778],[-64.32628,3.118275],[-64.28142,3.541983],[-64.88451,4.117671],[-64.88064,4.342461],[-64.13653,4.223152],[-63.95465,4.021316],[-63.17706,4.048301],[-62.96093,3.763658],[-62.82024,4.106019],[-62.49922,4.270815],[-61.91181,4.26284],[-61.35393,4.630097],[-61.04904,4.623115],[-60.70452,4.969851],[-60.78709,5.296764],[-60.22457,5.371207],[-59.89857,5.107541],[-59.97549,4.603025],[-59.59676,4.439875],[-59.41942,3.96994],[-59.71017,3.542008],[-59.88955,2.72301],[-59.63006,2.316332],[-59.63382,1.966581],[-59.18812,1.478079],[-58.80545,1.320732],[-58.35933,1.689932],[-57.6,1.803907],[-57.39854,2.065119],[-57.12392,2.128758],[-56.02925,1.949445],[-56.23884,2.263348],[-55.98195,2.628657],[-55.64816,2.519953],[-54.93958,2.682515],[-54.24988,2.25056],[-53.73937,2.473731],[-52.98578,2.280494],[-52.65712,2.564069],[-52.41739,3.22121],[-51.73983,4.119158],[-51.7246,4.556867],[-51.0112,5.522895],[-43.48209,5.335832],[-29.3325,2.335959]]]},{"id":"Haiti-Drone","name":"Imagerie Drone (Haiti)","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/iomhaiti/{zoom}/{x}/{y}","polygon":[[[-72.1547401,19.6878969],[-72.162234,19.689011],[-72.164995,19.6932445],[-72.1657838,19.6979977],[-72.161603,19.7035677],[-72.1487449,19.7028993],[-72.1477194,19.7026765],[-72.1485082,19.7001514],[-72.1436963,19.7011169],[-72.1410143,19.7000029],[-72.139476,19.6973664],[-72.1382533,19.6927617],[-72.1386872,19.6923161],[-72.1380561,19.6896423],[-72.1385294,19.6894938],[-72.1388055,19.6901251],[-72.1388844,19.6876741],[-72.1378195,19.6872656],[-72.13778,19.6850003],[-72.1369517,19.6855945],[-72.136794,19.6840719],[-72.135729,19.6835148],[-72.1355713,19.6740817],[-72.1366362,19.6708133],[-72.1487843,19.6710733],[-72.1534779,19.6763843],[-72.1530835,19.6769414],[-72.1533251,19.6769768],[-72.1532807,19.6796525],[-72.1523834,19.6797175],[-72.1522749,19.6803488],[-72.1519101,19.6803395],[-72.1518608,19.6805067],[-72.1528173,19.6806552],[-72.1522299,19.6833011],[-72.1507801,19.6831499],[-72.1504457,19.6847862],[-72.1508591,19.6843492],[-72.1530087,19.6849898],[-72.1546258,19.6854354],[-72.1543103,19.6870694],[-72.1547244,19.6868466],[-72.1548501,19.6877564],[-72.1545814,19.6877982],[-72.1547401,19.6878969]],[[-72.1310601,19.6718929],[-72.1259842,19.6772765],[-72.1255379,19.6776179],[-72.1216891,19.6776442],[-72.1149677,19.672602],[-72.1152745,19.6687152],[-72.1198205,19.6627535],[-72.1227768,19.6625696],[-72.1248965,19.662701],[-72.1285779,19.6645394],[-72.1308091,19.6661677],[-72.1316737,19.668794],[-72.1315621,19.671],[-72.1310601,19.6718929]],[[-71.845795,19.6709758],[-71.8429354,19.6759525],[-71.8410027,19.6759525],[-71.8380249,19.6755254],[-71.8378671,19.6745041],[-71.8390504,19.6743927],[-71.8390109,19.6741141],[-71.8398392,19.673947],[-71.8389123,19.6736127],[-71.8380249,19.67209],[-71.8380052,19.6726285],[-71.8376699,19.6727214],[-71.8376305,19.672545],[-71.8354414,19.6732135],[-71.835333,19.6729999],[-71.8331242,19.6734642],[-71.8326706,19.6716815],[-71.8321579,19.67209],[-71.8307183,19.6694902],[-71.8306009,19.6697594],[-71.8302174,19.6698907],[-71.8291833,19.6672095],[-71.8290749,19.6672095],[-71.8289122,19.6667916],[-71.8289516,19.6666199],[-71.8288333,19.6663506],[-71.8285572,19.6664759],[-71.8288678,19.6672466],[-71.8287593,19.6674138],[-71.8277979,19.6678177],[-71.8277112,19.6678586],[-71.8278263,19.6679637],[-71.8271831,19.6681212],[-71.8271761,19.6680917],[-71.8264405,19.6683921],[-71.8264074,19.6683231],[-71.8261954,19.6684253],[-71.8261806,19.6683556],[-71.8258946,19.6684206],[-71.8258897,19.6686574],[-71.8251551,19.6687549],[-71.8254509,19.6691588],[-71.8229332,19.6695739],[-71.822713,19.6696658],[-71.8227688,19.6697577],[-71.8201751,19.6709855],[-71.8198474,19.6704537],[-71.8197985,19.6706014],[-71.8194674,19.6707557],[-71.8182472,19.6713433],[-71.8181426,19.6711431],[-71.8175813,19.6714254],[-71.816959,19.6707672],[-71.8176388,19.6718965],[-71.8171403,19.6720376],[-71.8158225,19.6718045],[-71.8138354,19.6711874],[-71.8123259,19.6706982],[-71.8121759,19.6704258],[-71.8124304,19.6701467],[-71.8119184,19.6700141],[-71.8118765,19.6705828],[-71.811169,19.6703483],[-71.8095938,19.6698516],[-71.8077992,19.6692829],[-71.8056028,19.668612],[-71.8051443,19.6668942],[-71.8051196,19.6652322],[-71.8052315,19.661979],[-71.8065603,19.6523921],[-71.8073412,19.6482946],[-71.8099686,19.6468292],[-71.8147517,19.6454502],[-71.8147726,19.6455619],[-71.8150027,19.6455093],[-71.8149469,19.6453846],[-71.8159928,19.6450234],[-71.8158882,19.6448855],[-71.8165854,19.6446097],[-71.8190119,19.643802],[-71.8211524,19.643454],[-71.8221564,19.6433292],[-71.8269046,19.643211],[-71.8280481,19.6432241],[-71.8304466,19.6440778],[-71.8306419,19.6448592],[-71.8295263,19.6450365],[-71.8296064,19.6456111],[-71.8299411,19.6455651],[-71.8303699,19.6451744],[-71.830471,19.6453452],[-71.8308092,19.6451974],[-71.8310184,19.6451088],[-71.8312519,19.6458541],[-71.8311125,19.6458245],[-71.831367,19.6465862],[-71.8328939,19.646189],[-71.8344566,19.6457062],[-71.8344664,19.6463052],[-71.834215,19.6461938],[-71.8342002,19.6465513],[-71.8346702,19.6463],[-71.8349118,19.6463905],[-71.8347984,19.6462187],[-71.8354393,19.6458496],[-71.8355034,19.6458032],[-71.8364747,19.6461328],[-71.8376382,19.6472658],[-71.8379143,19.647888],[-71.8390483,19.6508039],[-71.8456942,19.6696203],[-71.845795,19.6709758]],[[-72.098878,18.54843],[-72.096993,18.5501994],[-72.0972888,18.5503209],[-72.0968451,18.5503489],[-72.0955632,18.551854],[-72.0956428,18.5526742],[-72.0959914,18.5533748],[-72.0962145,18.553203],[-72.0962842,18.5535665],[-72.0964446,18.5535533],[-72.0965352,18.5539764],[-72.0965056,18.554173],[-72.0966085,18.5541747],[-72.0965178,18.5542127],[-72.0968769,18.5546588],[-72.0979018,18.5552141],[-72.1006211,18.5555875],[-72.1014926,18.5556206],[-72.1024339,18.5555016],[-72.103417,18.5543515],[-72.1034798,18.5516215],[-72.1030789,18.5516149],[-72.1033752,18.5515224],[-72.1035042,18.5515224],[-72.1035239,18.5502417],[-72.1028701,18.5503062],[-72.1029015,18.55025],[-72.1028457,18.5501773],[-72.1035081,18.5500252],[-72.103491,18.5497396],[-72.1035181,18.5497361],[-72.1035398,18.5489039],[-72.1034317,18.5487056],[-72.102717,18.5481437],[-72.1025601,18.5481536],[-72.10229,18.5482751],[-72.1022891,18.5482569],[-72.1025201,18.5481396],[-72.1023388,18.5481321],[-72.0999082,18.5480901],[-72.09907,18.5483799],[-72.098878,18.54843]],[[-72.2542503,18.568262],[-72.2560252,18.5717765],[-72.2557886,18.5748049],[-72.2535009,18.5755526],[-72.2522782,18.5755526],[-72.2499906,18.5740945],[-72.2473874,18.5698323],[-72.2460069,18.566729],[-72.2458492,18.5629527],[-72.2479396,18.5625414],[-72.2501483,18.5628031],[-72.2519232,18.5650839],[-72.2542503,18.568262]],[[-72.303145,18.5332749],[-72.3031275,18.5331799],[-72.3048311,18.5311081],[-72.3097397,18.5311081],[-72.3164332,18.5324302],[-72.3234056,18.5366083],[-72.3261388,18.5387765],[-72.3261946,18.5426371],[-72.3170468,18.5540596],[-72.3130864,18.5540596],[-72.2987511,18.5453342],[-72.2988627,18.5407333],[-72.2962969,18.5404689],[-72.2954602,18.5395169],[-72.2961853,18.5338582],[-72.2971893,18.5332235],[-72.3007034,18.5332764],[-72.3022652,18.5342284],[-72.3028486,18.5335189],[-72.303104,18.5333361],[-72.303181,18.5334007],[-72.3035793,18.5335614],[-72.3030793,18.5346463],[-72.303715,18.5339873],[-72.3045286,18.5344052],[-72.3044015,18.5345097],[-72.3062747,18.5352571],[-72.3063107,18.5352741],[-72.3061219,18.5357628],[-72.3061219,18.5358196],[-72.30637,18.5358928],[-72.3062726,18.5354869],[-72.3066688,18.5350891],[-72.3061963,18.5349706],[-72.3058869,18.5349385],[-72.3055373,18.5346833],[-72.3054864,18.534613],[-72.3055585,18.5345065],[-72.3046749,18.5342293],[-72.3047617,18.5338817],[-72.3043252,18.5337511],[-72.3042595,18.5336346],[-72.303145,18.5332749]],[[-72.2981405,18.477502],[-72.2935652,18.4948587],[-72.2922242,18.4964297],[-72.2931708,18.4972526],[-72.2892266,18.5057058],[-72.2878067,18.5080996],[-72.2850458,18.5119893],[-72.2840203,18.5113161],[-72.2808649,18.515879],[-72.2773151,18.5175994],[-72.2723454,18.5175246],[-72.2662714,18.5144578],[-72.2665869,18.5066783],[-72.2692643,18.5046154],[-72.2661965,18.5029756],[-72.2688181,18.4965222],[-72.2691528,18.4959403],[-72.2702684,18.4961519],[-72.2702684,18.4955964],[-72.2690691,18.49557],[-72.2692922,18.4937714],[-72.2736988,18.4859951],[-72.2746749,18.4850429],[-72.2751769,18.483403],[-72.2765435,18.4813398],[-72.2773523,18.4814985],[-72.2783006,18.4809694],[-72.2778544,18.4807049],[-72.2771013,18.480123],[-72.2789978,18.4775836],[-72.279723,18.4772927],[-72.2806433,18.4776365],[-72.2813685,18.4771604],[-72.2808386,18.4769752],[-72.2812848,18.4758378],[-72.2823167,18.4751765],[-72.2851615,18.4750971],[-72.2849941,18.4763668],[-72.2854404,18.4769752],[-72.286277,18.4756262],[-72.2869325,18.4754675],[-72.2865978,18.4751897],[-72.2865978,18.4750046],[-72.2909765,18.4747268],[-72.2946579,18.4749384],[-72.2973911,18.476843],[-72.2981405,18.477502]],[[-72.3466657,18.5222375],[-72.346833,18.5244325],[-72.3475303,18.5277645],[-72.3455501,18.5291131],[-72.3403069,18.5292189],[-72.3383267,18.5280289],[-72.3369043,18.530118],[-72.3338086,18.5296684],[-72.3289279,18.5270769],[-72.328649,18.5253316],[-72.3292068,18.5232689],[-72.330406,18.5220524],[-72.3321631,18.5221847],[-72.3322467,18.5191963],[-72.3369183,18.5183633],[-72.3382012,18.5184691],[-72.3381454,18.5181782],[-72.3411993,18.5177947],[-72.3454943,18.5171997],[-72.3492595,18.517279],[-72.3504308,18.5188922],[-72.3503472,18.5206112],[-72.3496778,18.5220392],[-72.3466657,18.5222375]],[[-72.3303078,18.5486462],[-72.3429687,18.5508149],[-72.3433236,18.5530585],[-72.3413121,18.5614341],[-72.3390639,18.5613593],[-72.3384723,18.5638271],[-72.3375257,18.5654348],[-72.3348436,18.5650609],[-72.3311755,18.5638271],[-72.3312149,18.5616211],[-72.3232082,18.5606863],[-72.3212361,18.559602],[-72.3208023,18.5587046],[-72.3208811,18.557882],[-72.3259493,18.5580274],[-72.3266186,18.5581993],[-72.3259214,18.5577498],[-72.3250986,18.5573797],[-72.3233767,18.552263],[-72.3245994,18.5478507],[-72.3288986,18.5483742],[-72.329979,18.5489548],[-72.3303078,18.5486462]],[[-72.3231383,18.5269828],[-72.3223434,18.528067],[-72.3209629,18.5279745],[-72.3207816,18.5271282],[-72.3208513,18.5253697],[-72.3214649,18.5249598],[-72.3225666,18.5248937],[-72.3228454,18.52533],[-72.3232359,18.5264804],[-72.3231383,18.5269828]],[[-72.2160832,18.6457752],[-72.2159649,18.6553795],[-72.2030279,18.6558279],[-72.1947057,18.6553421],[-72.1922208,18.6545573],[-72.1920631,18.6521283],[-72.193483,18.6477559],[-72.201253,18.6385249],[-72.2069327,18.6388239],[-72.2120996,18.6424117],[-72.2118068,18.6430591],[-72.2121693,18.6426892],[-72.2127968,18.6427552],[-72.2134662,18.6431252],[-72.2135638,18.6437462],[-72.2154176,18.6443947],[-72.2158909,18.6450301],[-72.2160832,18.6457752]],[[-72.2867654,18.6482017],[-72.2900977,18.6527446],[-72.28981,18.6536532],[-72.2900738,18.6542664],[-72.290721,18.6537667],[-72.2910327,18.6544709],[-72.2912485,18.654221],[-72.29168,18.6558905],[-72.2912245,18.656606],[-72.2922673,18.65597],[-72.2926869,18.6567536],[-72.2930705,18.6567309],[-72.2941253,18.6581846],[-72.2960192,18.6608421],[-72.2959713,18.6619096],[-72.2932862,18.664567],[-72.2906731,18.6659979],[-72.2895943,18.6661342],[-72.2895943,18.6665657],[-72.2877004,18.6664749],[-72.2875805,18.6676559],[-72.2831214,18.6697227],[-72.2796453,18.6696546],[-72.2784311,18.6690787],[-72.2783972,18.6687736],[-72.277736,18.6691671],[-72.2774394,18.669143],[-72.2770071,18.6683159],[-72.2765575,18.6681125],[-72.2765385,18.6680583],[-72.2752319,18.6685239],[-72.2749292,18.6674649],[-72.2746416,18.6674309],[-72.2734668,18.6682145],[-72.2732271,18.6682712],[-72.2726757,18.6671583],[-72.2719147,18.6674288],[-72.2718808,18.6673405],[-72.2688149,18.6681868],[-72.2688269,18.6671761],[-72.2690786,18.6668241],[-72.2688149,18.66679],[-72.2681077,18.6670739],[-72.2676282,18.6673805],[-72.2675563,18.6666878],[-72.266861,18.666949],[-72.2655904,18.6673578],[-72.2654466,18.6670058],[-72.2647514,18.6674146],[-72.2629893,18.6681868],[-72.2628455,18.6681754],[-72.2626537,18.6676076],[-72.2623001,18.6677098],[-72.2624799,18.6679199],[-72.2624799,18.6682322],[-72.262306,18.6682606],[-72.2620963,18.6679654],[-72.2622761,18.6689193],[-72.2601484,18.6688966],[-72.2542749,18.6687944],[-72.2505388,18.6683476],[-72.2504371,18.669536],[-72.2477926,18.6698893],[-72.2415204,18.669793],[-72.2414187,18.6741933],[-72.2389167,18.6739759],[-72.2387249,18.6734649],[-72.2383653,18.6733059],[-72.2387009,18.6739532],[-72.2375502,18.6738964],[-72.2374183,18.6735103],[-72.237742,18.67334],[-72.2375142,18.6732605],[-72.236843,18.6734876],[-72.2364354,18.6724088],[-72.2355124,18.6726019],[-72.2354045,18.6724202],[-72.2353027,18.6729028],[-72.2345475,18.6726871],[-72.2343077,18.6724599],[-72.2342358,18.6734706],[-72.2334087,18.6734592],[-72.2332889,18.6733003],[-72.2327375,18.6732889],[-72.2327135,18.6735047],[-72.227703,18.6725281],[-72.2265283,18.6716537],[-72.226804,18.6715742],[-72.2274993,18.6715855],[-72.2274873,18.6714493],[-72.2272899,18.6714623],[-72.2272814,18.6712977],[-72.2272094,18.671358],[-72.2261785,18.6713693],[-72.2256032,18.670881],[-72.2255073,18.6694502],[-72.2261066,18.6696886],[-72.2261785,18.6695949],[-72.2259837,18.6695495],[-72.225777,18.6691379],[-72.2253335,18.6694643],[-72.2249739,18.66947],[-72.2245783,18.6678802],[-72.2235525,18.6677046],[-72.2235907,18.6675921],[-72.2224634,18.6676283],[-72.2223659,18.667022],[-72.2223277,18.6670943],[-72.2219209,18.667026],[-72.2208105,18.6669015],[-72.220809,18.6665325],[-72.2208705,18.6663593],[-72.2206023,18.6668107],[-72.2203895,18.6666361],[-72.2184341,18.6650535],[-72.21829,18.6640979],[-72.2183493,18.6608376],[-72.2187223,18.6606541],[-72.2186894,18.660603],[-72.2187253,18.6604525],[-72.2189771,18.6603247],[-72.2187823,18.6601998],[-72.2186984,18.6602367],[-72.2185815,18.6600352],[-72.2186085,18.6600039],[-72.2187823,18.6601345],[-72.218995,18.6600181],[-72.2189111,18.6599131],[-72.2189681,18.6597938],[-72.2183807,18.6595837],[-72.2184728,18.6539662],[-72.2201001,18.6511554],[-72.225796,18.6469472],[-72.2283048,18.6457265],[-72.2379335,18.645855],[-72.237764,18.6446985],[-72.2400355,18.6432529],[-72.2455958,18.6433493],[-72.2482742,18.6450358],[-72.2487488,18.6436705],[-72.2511067,18.6429775],[-72.2512385,18.6433409],[-72.2512625,18.6431592],[-72.2514843,18.6431365],[-72.2513284,18.6429718],[-72.2533602,18.6423471],[-72.253516,18.6426765],[-72.2539535,18.6425402],[-72.2541453,18.642932],[-72.2543851,18.6428696],[-72.2543791,18.6427503],[-72.2564168,18.6423244],[-72.2566925,18.6431365],[-72.2568783,18.6428582],[-72.2568184,18.6425288],[-72.258843,18.6420991],[-72.258885,18.6422467],[-72.2592626,18.6422297],[-72.2596461,18.6424057],[-72.2592206,18.6406907],[-72.2599545,18.6404815],[-72.2601156,18.6406341],[-72.2601156,18.6399393],[-72.2615268,18.6394669],[-72.2626056,18.6391034],[-72.2654465,18.6387286],[-72.2719433,18.6386832],[-72.272201,18.6388649],[-72.2730341,18.6394158],[-72.273166,18.6412558],[-72.2738732,18.6410286],[-72.2742208,18.6416079],[-72.2752187,18.6416987],[-72.2754524,18.6415738],[-72.2755513,18.6416874],[-72.2755394,18.6417527],[-72.2764713,18.6418634],[-72.276753,18.6418975],[-72.2762953,18.6426002],[-72.2774226,18.6429978],[-72.277982,18.6427247],[-72.2785796,18.6431303],[-72.2785669,18.6432307],[-72.2789017,18.6433471],[-72.279851,18.6439655],[-72.2858703,18.6469651],[-72.2867654,18.6482017]],[[-72.5557247,18.5305893],[-72.5555866,18.5367036],[-72.554995,18.537975],[-72.5488026,18.537919],[-72.5486646,18.5372832],[-72.548842,18.5306267],[-72.5493745,18.5301031],[-72.555133,18.5301218],[-72.5557247,18.5305893]],[[-72.6235278,18.5079877],[-72.6234441,18.5095217],[-72.6226074,18.5104341],[-72.6204878,18.511849],[-72.6183403,18.5107514],[-72.6162207,18.5083183],[-72.6162625,18.506467],[-72.618661,18.5044438],[-72.6204041,18.5044967],[-72.6228305,18.506996],[-72.6235278,18.5079877]]]},{"id":"osmim-imagicode-S2A_R119_N09_20160327T050917","name":"imagico.de OSM images for mapping: Adams Bridge","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R119_N09_20160327T050917&z={zoom}&x={x}&y={-y}","description":"Supplementing incomplete coverage in other sources (true color)","scaleExtent":[0,14],"polygon":[[[79.01779174804685,8.827572266651268],[79.01401519775389,9.64678471986339],[80.17642021179198,9.650423231331946],[80.17727851867674,8.831304063493132],[79.01779174804685,8.827572266651268]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC80700162014211LGN00","name":"imagico.de OSM images for mapping: Alaska Range","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80700162014211LGN00&z={zoom}&x={x}&y={-y}","description":"Recent summer image of the Alaska Range for mapping natural features (true color)","scaleExtent":[0,12],"polygon":[[[-152.70872943147867,62.30357443926811],[-152.70838610872474,62.58153176976553],[-152.00835101350992,63.54645538851267],[-148.99432055696695,63.53329945446586],[-148.99432055696695,62.30357443926811],[-152.70872943147867,62.30357443926811]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81190582014075LGN00","name":"imagico.de OSM images for mapping: Bakun Reservoir","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81190582014075LGN00&z={zoom}&x={x}&y={-y}","description":"Missing in older pre-2011 images (true color)","scaleExtent":[0,13],"polygon":[[[114.35999506049737,2.028456548619032],[113.5344754987298,2.030000532161949],[113.53619211249934,3.070767124420059],[114.76511591010677,3.067510236472651],[114.76254098945248,2.088156161702156],[114.35999506049737,2.028456548619032]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81250592016107LGN00","name":"imagico.de OSM images for mapping: Batam","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81250592016107LGN00&z={zoom}&x={x}&y={-y}","description":"Missing Islands in OSM (true color)","scaleExtent":[0,13],"polygon":[[[104.00154570197358,-0.000078769115171],[104.00137404059662,1.45099139170518],[104.91014937018647,1.451162998032411],[104.91014937018647,-0.000078769115171],[104.00154570197358,-0.000078769115171]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81800982013291LGN00","name":"imagico.de OSM images for mapping: Bouvet Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81800982013291LGN00&z={zoom}&x={x}&y={-y}","description":"For more accurate coastline and glacier mapping (true color)","scaleExtent":[0,13],"polygon":[[[3.246529403113632,-54.47046993167111],[3.246529403113632,-54.375391687979096],[3.463852706336288,-54.375391687979096],[3.463852706336288,-54.47046993167111],[3.246529403113632,-54.47046993167111]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","best":true},{"id":"osmim-imagicode-S2A_R065_N47_20160929T102022","name":"imagico.de OSM images for mapping: Cental Alps in late September 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R065_N47_20160929T102022&z={zoom}&x={x}&y={-y}","description":"Up-to-date image for glacier mapping - beware of some fresh snow at higher altitudes (true color)","scaleExtent":[0,13],"polygon":[[[10.559062957763668,45.95484945195885],[7.473964691162107,45.95532682303484],[7.555847167968747,46.27080015119853],[8.05469512939453,47.66469371011084],[11.752452850341793,47.664809318453564],[11.752452850341793,46.813336457338615],[11.38423919677734,45.955088138010865],[10.559062957763668,45.95484945195885]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC82050982015344LGN00","name":"imagico.de OSM images for mapping: Clerke Rocks","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82050982015344LGN00&z={zoom}&x={x}&y={-y}","description":"Missing in other image sources (true color)","scaleExtent":[0,13],"polygon":[[[-34.17701089820909,-55.29692751183208],[-35.19599283180284,-55.282851769908206],[-35.16663873634385,-54.7209735214882],[-34.12516916236925,-54.73465315976587],[-34.14010370216417,-55.29692751183208],[-34.17701089820909,-55.29692751183208]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-EO1A0040712016264110KF","name":"imagico.de OSM images for mapping: Coropuna","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=EO1A0040712016264110KF&z={zoom}&x={x}&y={-y}","description":"Up-to-date image for glacier mapping (true color)","scaleExtent":[0,14],"polygon":[[[-72.7594470977783,-15.68684010813036],[-72.7594470977783,-15.49570157136026],[-72.74434089660643,-15.426295586903299],[-72.41286277770995,-15.426295586903299],[-72.41286277770995,-15.652957427428944],[-72.42410659790038,-15.686674840407827],[-72.7594470977783,-15.68684010813036]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R022_N06_20151221T103009","name":"imagico.de OSM images for mapping: Cotonou","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R022_N06_20151221T103009&z={zoom}&x={x}&y={-y}","description":"Patchy and partly cloudy coverage in usual sources (true color)","scaleExtent":[0,14],"polygon":[[[1.839749701876779,6.257803795151386],[1.839749701876779,7.114271792431897],[2.549397834200998,7.114271792431897],[2.549397834200998,6.489052510574106],[2.497813590426584,6.258059752887941],[1.839749701876779,6.257803795151386]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R040_N01_20160311T164128","name":"imagico.de OSM images for mapping: Darwin and Wolf islands, Galapagos","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R040_N01_20160311T164128&z={zoom}&x={x}&y={-y}","description":"Recent image, only old and poor images in other sources currently (true color)","scaleExtent":[0,14],"polygon":[[[-92.05216379429558,1.321295617717369],[-92.05216379429558,1.72181118585353],[-91.74849481846549,1.72181118585353],[-91.74849481846549,1.321295617717369],[-92.05216379429558,1.321295617717369]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC80360072014245LGN00","name":"imagico.de OSM images for mapping: Eastern Devon Island coast","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80360072014245LGN00&z={zoom}&x={x}&y={-y}","description":"Coastline mostly mapped meanwhile (false color IR)","scaleExtent":[0,11],"polygon":[[[-84.34798733886554,74.38945823827667],[-84.34798733886554,75.89030323920836],[-79.14870755370929,75.89030323920836],[-79.14870755370929,74.38945823827667],[-84.34798733886554,74.38945823827667]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC82160152013239LGN00","name":"imagico.de OSM images for mapping: Eastern Iceland","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82160152013239LGN00&z={zoom}&x={x}&y={-y}","description":"Missing islets and inaccurate coast (true color)","scaleExtent":[0,12],"polygon":[[[-13.047005598725303,64.2110895294821],[-15.164963667572959,64.22408122727819],[-15.168053572358117,64.81572800422087],[-13.043572371186242,64.80359943673454],[-13.047005598725303,64.2110895294821]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-AST_L1T_00302052007154424_20150518041444_91492","name":"imagico.de OSM images for mapping: El Altar","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=AST_L1T_00302052007154424_20150518041444_91492&z={zoom}&x={x}&y={-y}","description":"2007 ASTER image offering better glacier coverage than common sources (true color with estimated blue)","scaleExtent":[0,14],"polygon":[[[-78.531997745432,-1.805085317123331],[-78.531997745432,-1.608105565001241],[-78.33561713019762,-1.608105565001241],[-78.33561713019762,-1.805085317123331],[-78.531997745432,-1.805085317123331]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R009_S61_20160109","name":"imagico.de OSM images for mapping: Elephant Island/Clarence Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R009_S61_20160109&z={zoom}&x={x}&y={-y}","description":"Fairly clear up-to-date image for updating glacier edges (true color)","scaleExtent":[0,13],"polygon":[[[-56.13476090727487,-61.63471600102006],[-56.13476090727487,-61.199363166283845],[-55.83263688383738,-60.84015069906498],[-53.72343354521433,-60.83981613078141],[-53.72343354521433,-61.63471600102006],[-56.13476090727487,-61.63471600102006]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-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}","description":"Sentinel-2 images of Enderby Land and Kemp Coast (true color)","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"},{"id":"osmim-imagicode-LC82100502015347LGN00","name":"imagico.de OSM images for mapping: Fogo, Cape Verde","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82100502015347LGN00&z={zoom}&x={x}&y={-y}","description":"Image from after the 2014/2015 eruption (true color)","scaleExtent":[0,14],"polygon":[[[-24.758781955967567,14.748140156641956],[-24.758781955967567,15.092493544965103],[-24.267057941685337,15.092493544965103],[-24.267057941685337,14.748140156641956],[-24.758781955967567,14.748140156641956]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-greenland","name":"imagico.de OSM images for mapping: Greenland mosaic","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=greenland&z={zoom}&x={x}&y={-y}","description":"Landsat mosaic of Greenland (true color)","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"},{"id":"osmim-imagicode-S2A_R047_S54_20160411T044330","name":"imagico.de OSM images for mapping: Heard Island coast","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R047_S54_20160411T044330&z={zoom}&x={x}&y={-y}","description":"Recent image of Heard island with interior mostly cloud covered but mostly well visible coast (true color)","scaleExtent":[0,13],"polygon":[[[73.06896521028185,-53.270590689700434],[73.06896521028185,-52.875489636268725],[73.67338491853381,-52.87673289134188],[74.08863378938341,-52.94950473139763],[74.08863378938341,-53.270590689700434],[73.06896521028185,-53.270590689700434]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC82280982013259LGN00","name":"imagico.de OSM images for mapping: Isla Londonderry","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82280982013259LGN00&z={zoom}&x={x}&y={-y}","description":"A lot of very coarse coastlines could be improved here, much snow cover though so no use for glacier mapping (false color IR)","scaleExtent":[0,12],"polygon":[[[-69.85679747431641,-55.55949231551995],[-72.26520659296875,-55.149427383391455],[-72.26520659296875,-54.51089432315929],[-72.08530546992188,-54.17909103768387],[-69.49115874140625,-54.17889010631196],[-69.49150206416016,-55.28378528847367],[-69.62230803339844,-55.55910398108892],[-69.85679747431641,-55.55949231551995]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R021_N44_20160807T083013","name":"imagico.de OSM images for mapping: Kerch Strait","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R021_N44_20160807T083013&z={zoom}&x={x}&y={-y}","description":"State of bridge construction in August 2016 (true color)","scaleExtent":[0,14],"polygon":[[[35.932588577270494,44.96236872935039],[35.932588577270494,45.559256426515695],[37.369909286499016,45.559256426515695],[37.369909286499016,44.96236872935039],[35.932588577270494,44.96236872935039]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-ls_polar2","name":"imagico.de OSM images for mapping: Landsat off-nadir July 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=ls_polar2&z={zoom}&x={x}&y={-y}","description":"Latest images north of the regular Landsat limit (true color)","scaleExtent":[0,10],"polygon":[[[-79.05174500251786,81.91484289044183],[-79.05174500251786,83.43338556749623],[-73.60389956385866,83.80224987787145],[-26.424486898081835,83.80224987787145],[-21.492998879371186,83.50352415480617],[-16.888354121159868,83.15094632775453],[-16.888354121159868,81.91484289044183],[-79.05174500251786,81.91484289044183]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-AST_L1T_00311162013112731_20150618142416_109190","name":"imagico.de OSM images for mapping: Leskov Island ASTER","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=AST_L1T_00311162013112731_20150618142416_109190&z={zoom}&x={x}&y={-y}","description":"Missing in other image sources (true color with estimated blue)","scaleExtent":[0,13],"polygon":[[[-28.210747081406492,-56.72108048139938],[-28.210747081406492,-56.624975043089115],[-27.96956284678735,-56.624975043089115],[-27.96956284678735,-56.72108048139938],[-28.210747081406492,-56.72108048139938]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81991002015286LGN00","name":"imagico.de OSM images for mapping: Leskov Island Landsat","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81991002015286LGN00&z={zoom}&x={x}&y={-y}","description":"Missing in other image sources (true color)","scaleExtent":[0,13],"polygon":[[[-27.992928409215843,-56.73479060902333],[-28.227761172887714,-56.732624892496354],[-28.2241562839717,-56.600752537318456],[-27.969754123327167,-56.60283135691063],[-27.97318735086623,-56.73479060902333],[-27.992928409215843,-56.73479060902333]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-ls_polar","name":"imagico.de OSM images for mapping: May 2013 off-nadir Landsat","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=ls_polar&z={zoom}&x={x}&y={-y}","description":"First available image north of the regular Landsat limit, mostly with seasonal snow cover so difficult to interpret (true color)","scaleExtent":[0,10],"polygon":[[[-85.76109385682587,81.39333391115835],[-89.83015512094161,82.14951616258433],[-89.83152841195212,82.24404688557661],[-84.99342418195555,82.73098798225534],[-79.95207288240479,83.13107965605444],[-74.55641250214465,83.46266728201661],[-69.35850602739671,83.70450775086888],[-28.207840897721187,83.70450775086888],[-23.06623935440381,83.46532469372944],[-17.96583654140148,83.15518123848051],[-17.96720983241198,82.72386035102944],[-22.781968115230015,81.44190408358111],[-85.76109385682587,81.39333391115835]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R092_S02_20160613T075613","name":"imagico.de OSM images for mapping: Mount Kenya 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R092_S02_20160613T075613&z={zoom}&x={x}&y={-y}","description":"Up-to-date image for glacier mapping (true color)","scaleExtent":[0,14],"polygon":[[[37.20665931701659,-0.266846645776291],[37.20665931701659,-0.011930465612033],[37.5655174255371,-0.011930465612033],[37.5655174255371,-0.266846645776291],[37.20665931701659,-0.266846645776291]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R092_S05_20160802T075556","name":"imagico.de OSM images for mapping: Mount Kilimanjaro 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R092_S05_20160802T075556&z={zoom}&x={x}&y={-y}","description":"Up-to-date image for glacier mapping (true color)","scaleExtent":[0,14],"polygon":[[[37.24768638610839,-3.229213650135676],[37.24768638610839,-2.968155849006605],[37.61581420898436,-2.968155849006605],[37.61581420898436,-3.229213650135676],[37.24768638610839,-3.229213650135676]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC80940622015159LGN00","name":"imagico.de OSM images for mapping: New Ireland","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80940622015159LGN00&z={zoom}&x={x}&y={-y}","description":"Many missing islands in OSM (mostly mapped meanwhile) (true color)","scaleExtent":[0,14],"polygon":[[[150.38853376619625,-2.800534349432724],[150.38853376619625,-2.383396178206425],[150.83348005525875,-2.383396178206425],[150.83348005525875,-2.800534349432724],[150.38853376619625,-2.800534349432724]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-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}","description":"Up-to-date low tide imagery of the coast for updating mapping of tidalflats and shoals (true color)","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"},{"id":"osmim-imagicode-ural_s2_2016","name":"imagico.de OSM images for mapping: Northern and Polar Ural mountains August 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=ural_s2_2016&z={zoom}&x={x}&y={-y}","description":"Up-to-date late summer imagery with few clouds - caution: not all visible snow is glaciers (true color)","scaleExtent":[0,13],"polygon":[[[59.198977223476454,64.8920468958533],[59.198977223476454,66.91656046303187],[60.733286610683486,68.44289182710118],[67.7329509173241,68.44327026354412],[67.7329509173241,67.748828729217],[64.21646761043934,64.9195663902952],[59.198977223476454,64.8920468958533]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-nellesmere_ast","name":"imagico.de OSM images for mapping: Northern Ellesmere Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=nellesmere_ast&z={zoom}&x={x}&y={-y}","description":"Assembled from July 2012 ASTER imagery (true color with estimated blue)","scaleExtent":[0,10],"polygon":[[[-81.62923243782096,82.45969864814401],[-83.03136255954291,82.47985512217643],[-83.03136255954291,83.05876272004272],[-72.80309111332822,83.09567468670448],[-65.65785798568925,83.03232446260982],[-65.8116665788654,82.45969864814401],[-81.62923243782096,82.45969864814401]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-nellesmere_ast_2016","name":"imagico.de OSM images for mapping: Northern Ellesmere Island July 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=nellesmere_ast_2016&z={zoom}&x={x}&y={-y}","description":"Assembled from July 2016 ASTER imagery (true color with estimated blue)","scaleExtent":[0,10],"polygon":[[[-78.89729497133754,82.17577067162792],[-82.64500613899595,82.19425721404356],[-82.64500613899595,83.08067098163464],[-66.58986093522367,83.08497116318647],[-63.78010752773773,82.98907949583335],[-63.78010752773773,82.72198178031782],[-65.0092029821365,82.17577067162792],[-78.89729497133754,82.17577067162792]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81960222015233LGN00vis","name":"imagico.de OSM images for mapping: Northern German west coast tidalflats","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81960222015233LGN00vis&z={zoom}&x={x}&y={-y}","description":"Up-to-date low tide imagery of the coast for updating mapping of tidalflats and shoals (true color)","scaleExtent":[0,12],"polygon":[[[7.63567991501593,53.28027339774928],[7.63567991501593,53.66770140276793],[8.49433012253546,55.502457780526],[9.207754805152648,55.48106268908912],[9.207754805152648,53.28027339774928],[7.63567991501593,53.28027339774928]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81960222015233LGN00ir","name":"imagico.de OSM images for mapping: Northern German west coast tidalflats (infrared)","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81960222015233LGN00ir&z={zoom}&x={x}&y={-y}","description":"Up-to-date low tide imagery of the coast for updating mapping of tidalflats and shoals (false color IR)","scaleExtent":[0,12],"polygon":[[[7.63567991501593,53.28027339774928],[7.63567991501593,53.66810821588294],[8.49433012253546,55.502457780526],[9.207754805152648,55.48106268908912],[9.207754805152648,53.28027339774928],[7.63567991501593,53.28027339774928]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-ngreenland_ast","name":"imagico.de OSM images for mapping: Northern Greenland ASTER","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=ngreenland_ast&z={zoom}&x={x}&y={-y}","description":"Assembled from mostly 2012 ASTER imagery, some 2005 images mainly in the northeast (true color with estimated blue)","scaleExtent":[0,10],"polygon":[[[-52.49221819430999,82.48971755550389],[-52.49221819430999,82.94294978186194],[-49.28695697579964,83.47311821807558],[-44.52850362441216,83.7321400994933],[-29.525299334683975,83.7321400994933],[-25.263977329098022,83.58271128961059],[-21.183929736898254,83.39775984253468],[-21.183929736898254,82.74312310369845],[-23.404541300879075,82.48971755550389],[-52.49221819430999,82.48971755550389]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-EO1A1350972013086110KF","name":"imagico.de OSM images for mapping: Northwest Heard Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=EO1A1350972013086110KF&z={zoom}&x={x}&y={-y}","description":"Glaciers of Northwest Heard Island (mapped meanwhile) (false color IR)","scaleExtent":[0,13],"polygon":[[[73.22790413350113,-53.20333324999222],[73.22790413350113,-53.01072925838941],[73.2594898268605,-52.94943913810479],[73.78992348164566,-52.94943913810479],[73.78992348164566,-53.06048282358537],[73.71782570332533,-53.20333324999222],[73.22790413350113,-53.20333324999222]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R111_N09_20160604T154554","name":"imagico.de OSM images for mapping: Panama Canal","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R111_N09_20160604T154554&z={zoom}&x={x}&y={-y}","description":"Images of the new locks (but partly cloudy) (true color)","scaleExtent":[0,14],"polygon":[[[-80.01653561766223,8.848981570244637],[-80.01653561766223,9.41480707574399],[-79.46859250242785,9.41480707574399],[-79.46859250242785,8.848981570244637],[-80.01653561766223,8.848981570244637]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-EO1A0120532016364110KF","name":"imagico.de OSM images for mapping: Panama Canal - Pacific side","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=EO1A0120532016364110KF&z={zoom}&x={x}&y={-y}","description":"New locks with less clouds than in the Sentinel-2 image - make sure to check image alignment (true color)","scaleExtent":[0,14],"polygon":[[[-79.62538719177245,8.770827350748924],[-79.68684196472167,8.821974500616129],[-79.6866703033447,8.93705081902936],[-79.65362548828124,9.0929436313527],[-79.268159866333,9.0929436313527],[-79.32832717895505,8.770827350748924],[-79.62538719177245,8.770827350748924]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-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}","description":"Sentinel-2 image of the Pechora Sea coast in autumn 2016 (true color)","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"},{"id":"osmim-imagicode-LC81511242016033LGN00","name":"imagico.de OSM images for mapping: Pensacola Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81511242016033LGN00&z={zoom}&x={x}&y={-y}","description":"Outside regular Landsat coverage and therefore not in LIMA and Bing/Mapbox (true color)","scaleExtent":[0,10],"polygon":[[[-53.20921946177197,-84.12524693598144],[-60.615377881406225,-83.78609327915953],[-60.615377881406225,-82.29968785439104],[-48.72405102147429,-82.29987186164387],[-44.52178052933989,-82.43683433550413],[-44.51354078327688,-84.12524693598144],[-53.20921946177197,-84.12524693598144]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R136_N41_20150831T093006","name":"imagico.de OSM images for mapping: Prokletije Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R136_N41_20150831T093006&z={zoom}&x={x}&y={-y}","description":"Late summer imagery where usual sources are severely limited by clouds and snow (true color)","scaleExtent":[0,14],"polygon":[[[19.112325688609005,42.1531576323006],[19.08425905347717,43.08073531915633],[20.63298799634826,43.09602978090892],[20.637880345591427,42.167791043253985],[19.112325688609005,42.1531576323006]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-DMS_1142622_03746_20110415_17533956","name":"imagico.de OSM images for mapping: Qasigiannguit","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=DMS_1142622_03746_20110415_17533956&z={zoom}&x={x}&y={-y}","description":"Icebridge DMS image of the settlement - alignment might be poor","scaleExtent":[0,15],"polygon":[[[-51.238571767352376,68.79971882076842],[-51.243335370562825,68.85302612951142],[-51.151668195269856,68.85302612951142],[-51.14038145973519,68.80116208175376],[-51.238571767352376,68.79971882076842]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81510432015030LGN00","name":"imagico.de OSM images for mapping: Rann of Kutch","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81510432015030LGN00&z={zoom}&x={x}&y={-y}","description":"Land/water distinction difficult to properly map based on Bing/Mapbox images (false color IR)","scaleExtent":[0,12],"polygon":[[[67.96839858817646,22.36264542957619],[67.86231185721942,22.38391650007107],[67.86231185721942,24.886930816927297],[71.48986007499286,24.886930816927297],[71.48986007499286,22.36264542957619],[67.96839858817646,22.36264542957619]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R093_N41_20150828T092005","name":"imagico.de OSM images for mapping: Rila and Pirin Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R093_N41_20150828T092005&z={zoom}&x={x}&y={-y}","description":"Late summer imagery where usual sources are severely limited by clouds and snow (true color)","scaleExtent":[0,14],"polygon":[[[23.808114560320394,41.584878805945024],[22.992379697039144,41.6019534981177],[23.011863263323328,42.29983747360261],[23.99402383156063,42.283393175568236],[23.965613873674886,41.584878805945024],[23.808114560320394,41.584878805945024]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81730602015040LGN00","name":"imagico.de OSM images for mapping: Rwenzori Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81730602015040LGN00&z={zoom}&x={x}&y={-y}","description":"Recent image of most of the remaining Rwenzori Mountains glaciers (false color IR)","scaleExtent":[0,13],"polygon":[[[29.766296776846374,0.206886934953159],[29.766296776846374,0.509176367154027],[30.034603509024116,0.509176367154027],[30.034603509024116,0.206886934953159],[29.766296776846374,0.206886934953159]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R078_N01_20160702T082522","name":"imagico.de OSM images for mapping: Rwenzori Mountains 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R078_N01_20160702T082522&z={zoom}&x={x}&y={-y}","description":"Up-to-date image for glacier mapping (true color)","scaleExtent":[0,14],"polygon":[[[29.8051357269287,0.235862065771959],[29.8051357269287,0.467085433008179],[30.02503395080565,0.467085433008179],[30.02503395080565,0.235862065771959],[29.8051357269287,0.235862065771959]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC80611072014036LGN00","name":"imagico.de OSM images for mapping: Scott Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80611072014036LGN00&z={zoom}&x={x}&y={-y}","description":"Missing in other image sources (true color)","scaleExtent":[0,13],"polygon":[[[-180,-67.4263452007858],[-180,-67.32544337276457],[-179.8247337341308,-67.3253771978419],[-179.8247337341308,-67.4263452007858],[-180,-67.4263452007858]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC82100972015347LGN00","name":"imagico.de OSM images for mapping: Shag Rocks","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82100972015347LGN00&z={zoom}&x={x}&y={-y}","description":"Missing in other image sources (true color)","scaleExtent":[0,13],"polygon":[[[-42.12874872458635,-53.72050213468143],[-42.14625818503558,-53.45782244664258],[-41.67573435080706,-53.445862233424414],[-41.6558216310805,-53.70871763480476],[-42.12874872458635,-53.72050213468143]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81130622013270LGN00","name":"imagico.de OSM images for mapping: Southeastern Sulawesi","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81130622013270LGN00&z={zoom}&x={x}&y={-y}","description":"Missing islands and coarse coastline due to cloud cover in Bing, lakes could also use additional detail (true color)","scaleExtent":[0,13],"polygon":[[[120.84382442048364,-3.595452324350203],[120.84382442048364,-3.159848173206955],[120.98184016755395,-2.514681686347053],[122.62618449738794,-2.514681686347053],[122.62618449738794,-3.002148034113534],[122.5007000308352,-3.595452324350203],[120.84382442048364,-3.595452324350203]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC80281222016035LGN00","name":"imagico.de OSM images for mapping: Southern Transantarctic Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80281222016035LGN00&z={zoom}&x={x}&y={-y}","description":"Outside regular Landsat coverage and therefore not in LIMA and Bing/Mapbox (true color)","scaleExtent":[0,10],"polygon":[[[156.96951345925345,-84.50097988272655],[154.50857596843485,-84.46255082580927],[154.50857596843485,-82.60681485793681],[175.46774337070775,-82.58504749645738],[177.00582930246938,-83.52806548607914],[177.00582930246938,-84.19262083779002],[171.93838547371908,-84.34632646581997],[166.83798266071676,-84.44370142483508],[161.67028858819987,-84.50045345467909],[156.96951345925345,-84.50097988272655]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-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}","description":"Sentinel-2 mosaic of Svalbard (true color)","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"},{"id":"osmim-imagicode-DMS_1142636_160xx_20110507_1822xxxx","name":"imagico.de OSM images for mapping: Thule Air Base","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=DMS_1142636_160xx_20110507_1822xxxx&z={zoom}&x={x}&y={-y}","description":"Icebridge DMS image - alignment might be poor","scaleExtent":[0,15],"polygon":[[[-68.93976917529807,76.51132557714853],[-68.93976917529807,76.54990046497333],[-68.76634826923117,76.55175699880375],[-68.50992908740743,76.55175699880375],[-68.50743999744161,76.51611959755911],[-68.67897262836203,76.51193618208278],[-68.93976917529807,76.51132557714853]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-dms_thule2_2015.09.25","name":"imagico.de OSM images for mapping: Thule Airbase DMS low altitude overflight September 2015","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=dms_thule2_2015.09.25&z={zoom}&x={x}&y={-y}","description":"Icebridge DMS aerial images from Thule Airbase - alignment might be poor","scaleExtent":[0,17],"polygon":[[[-68.74291885235837,76.52635852412212],[-68.74446380475094,76.52840070669755],[-68.74806869366695,76.54938731810256],[-68.7461482320123,76.56016657973251],[-68.72275936940244,76.56022393334496],[-68.72017371991207,76.5577475347327],[-68.71853220799495,76.5292079974043],[-68.71977675297786,76.52636602351234],[-68.74291885235837,76.52635852412212]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-dms_thule_2015.10.06","name":"imagico.de OSM images for mapping: Thule Airbase DMS overflight October 2015","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=dms_thule_2015.10.06&z={zoom}&x={x}&y={-y}","description":"Icebridge DMS aerial images from Thule Airbase - alignment might be poor","scaleExtent":[0,16],"polygon":[[[-68.81923965911197,76.52510098413808],[-68.82651380996036,76.54176603738404],[-68.77344898680974,76.5439032956252],[-68.7021022270136,76.54544610909097],[-68.59176687697696,76.54560088014632],[-68.59183124999333,76.52793072237704],[-68.65970186690618,76.52510098413808],[-68.81923965911197,76.52510098413808]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-dms_thule_2015.09.25","name":"imagico.de OSM images for mapping: Thule Airbase DMS overflight September 2015","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=dms_thule_2015.09.25&z={zoom}&x={x}&y={-y}","description":"Icebridge DMS aerial images from Thule Airbase - alignment might be poor","scaleExtent":[0,16],"polygon":[[[-68.7777130980429,76.50687742381471],[-68.77661875676482,76.57064446843503],[-68.68115357350676,76.57065443536027],[-68.67630413960784,76.55384487076157],[-68.67619685124725,76.5307435998188],[-68.6852305312094,76.50688243050337],[-68.7777130980429,76.50687742381471]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R094_N79_20160812T105622","name":"imagico.de OSM images for mapping: Ushakov Island August 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R094_N79_20160812T105622&z={zoom}&x={x}&y={-y}","description":"Up-to-date late summer imagery with few clouds (true color)","scaleExtent":[0,12],"polygon":[[[78.45885691499899,80.72643412860921],[78.45885691499899,80.9098976404357],[80.48892435884663,80.9098976404357],[80.48892435884663,80.72643412860921],[78.45885691499899,80.72643412860921]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC80910682014358LGN00","name":"imagico.de OSM images for mapping: Vanatinai","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80910682014358LGN00&z={zoom}&x={x}&y={-y}","description":"Coarse coastline due to cloud cover in Bing/Mapbox (true color)","scaleExtent":[0,13],"polygon":[[[153.0613810625655,-11.789228234021259],[153.0613810625655,-11.288690822294749],[153.10927458673538,-11.072292520575749],[154.41201277643268,-11.072292520575749],[154.41201277643268,-11.789228234021259],[153.0613810625655,-11.789228234021259]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC82330892016031LGN00","name":"imagico.de OSM images for mapping: Volcán Calbuco","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82330892016031LGN00&z={zoom}&x={x}&y={-y}","description":"Image from after the 2015 eruption (true color)","scaleExtent":[0,13],"polygon":[[[-72.8669610523419,-41.51741123877955],[-72.8669610523419,-41.045274923011036],[-72.23181395761533,-41.045274923011036],[-71.87510161630674,-41.10829439141359],[-72.00007109872861,-41.51741123877955],[-72.8669610523419,-41.51741123877955]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R089_N52_20160623T024048","name":"imagico.de OSM images for mapping: Vostochny Cosmodrome","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R089_N52_20160623T024048&z={zoom}&x={x}&y={-y}","description":"Recent image showing newest features (true color)","scaleExtent":[0,13],"polygon":[[[126.36143429881301,51.375528375017275],[126.34804471141064,52.33932231282816],[128.60762341624462,52.340895519845674],[128.6117432892915,51.375528375017275],[126.36143429881301,51.375528375017275]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC81490352013282LGN00","name":"imagico.de OSM images for mapping: Western Karakoram","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81490352013282LGN00&z={zoom}&x={x}&y={-y}","description":"Represents approximately minimum snow cover so can be well used for glacier mapping (true color)","scaleExtent":[0,13],"polygon":[[[75.98364343730569,34.97850982318471],[73.96164407817483,35.36957188964085],[74.44281091777444,37.09391400468158],[76.50600900737405,36.7026732100855],[75.98364343730569,34.97850982318471]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R039_S15_20160510T145731","name":"imagico.de OSM images for mapping: Willkanuta Mountains and Quelccaya Ice Cap","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R039_S15_20160510T145731&z={zoom}&x={x}&y={-y}","description":"Poor and outdated imagery in other sources (true color)","scaleExtent":[0,14],"polygon":[[[-71.18070648306262,-14.4978507264954],[-71.17976234548938,-13.710292880050797],[-70.5563740550841,-13.71262765059222],[-70.5563740550841,-14.4978507264954],[-71.18070648306262,-14.4978507264954]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"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"},{"id":"GSGS3906","name":"Ireland British War Office 1:25k GSGS 3906","type":"tms","template":"http://mapwarper.net/layers/tile/101/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"polygon":[[[-10.71,51.32],[-10.71,55.46],[-5.37,55.46],[-5.37,51.32],[-10.71,51.32]]],"terms_url":"http://wiki.openstreetmap.org/wiki/WikiProject_Ireland#Trinity_College_Dublin","terms_text":"Glucksman Map Library, Trinity College Dublin"},{"id":"GSGS4136","name":"Ireland British War Office One-Inch 1941-43 GSGS 4136","type":"tms","template":"http://geo.nls.uk/maps/ireland/gsgs4136/{zoom}/{x}/{-y}.png","scaleExtent":[5,15],"polygon":[[[-10.0847426,51.4147902],[-10.0906535,51.5064103],[-10.4564222,51.5003961],[-10.5005905,52.3043019],[-10.0837522,52.312741],[-10.0840973,52.3404698],[-10.055802,52.3408915],[-10.0768509,52.7628238],[-9.7780248,52.7684611],[-9.7818205,52.8577261],[-9.6337877,52.8596012],[-9.6449626,53.1294502],[-10.0919663,53.1227152],[-10.1051422,53.3912913],[-10.4052593,53.3866349],[-10.4530828,54.193502],[-10.2998523,54.1974988],[-10.3149801,54.4669592],[-8.9276095,54.4853897],[-8.9339534,54.7546562],[-8.7773069,54.755501],[-8.7826749,55.0252208],[-8.9402974,55.0238221],[-8.9451773,55.2934155],[-7.528039,55.2970274],[-7.525599,55.3874955],[-7.0541955,55.3841691],[-7.0556595,55.2939712],[-6.3241545,55.2859128],[-6.3217146,55.3253556],[-6.1035807,55.3223016],[-6.1045566,55.2828557],[-5.7985836,55.2772968],[-5.8117595,55.0087135],[-5.656577,55.0056351],[-5.6721928,54.7355021],[-5.3618278,54.729585],[-5.3964755,54.1917889],[-5.855679,54.2017807],[-5.9220464,52.8524504],[-6.070885,52.8551025],[-6.1030927,52.1373337],[-6.8331336,52.1463183],[-6.8355736,52.0578908],[-7.5641506,52.0617913],[-7.5661026,51.7921593],[-8.147305,51.792763],[-8.146329,51.7033331],[-8.2912636,51.7027283],[-8.2897996,51.5227274],[-9.1174397,51.516958],[-9.1179277,51.4625685],[-9.3692452,51.4616564],[-9.3672933,51.4254613],[-10.0847426,51.4147902]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"gsi.go.jp","name":"Japan GSI ortho Imagery","type":"tms","template":"http://cyberjapandata.gsi.go.jp/xyz/ort/{zoom}/{x}/{y}.jpg","scaleExtent":[12,19],"polygon":[[[141.85546875,44.64911632343077],[140.2294921875,43.96909818325174],[138.955078125,41.80407814427237],[139.482421875,40.17887331434696],[138.8671875,38.30718056188316],[136.31835937499997,37.19533058280065],[132.1435546875,35.137879119634185],[128.935546875,33.35806161277885],[129.5068359375,32.47269502206151],[129.77050781249997,31.690781806136822],[130.2099609375,30.90222470517144],[131.220703125,30.78903675126116],[131.66015625,32.32427558887655],[132.71484375,32.879587173066305],[133.76953125,33.17434155100208],[136.7578125,33.87041555094183],[139.306640625,35.06597313798418],[140.888671875,35.17380831799959],[141.15234374999997,36.56260003738548],[142.11914062499997,39.9434364619742],[141.767578125,42.68243539838623],[141.85546875,44.64911632343077]]]},{"id":"Aargau-AGIS-2011","name":"Kanton Aargau 25cm (AGIS 2011)","type":"tms","template":"http://tiles.poole.ch/AGIS/OF2011/{zoom}/{x}/{y}.png","scaleExtent":[14,19],"polygon":[[[7.7,47.12],[7.7,47.63],[8.5,47.63],[8.5,47.12],[7.7,47.12]]],"terms_text":"AGIS OF2011"},{"id":"Aargau-AGIS-2014","name":"Kanton Aargau 25cm (AGIS 2014)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/AGIS2014/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[8,20],"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","scaleExtent":[8,20],"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},{"id":"KTZUERICH2015","name":"Kanton Zürich 2015 10cm","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/KTZUERICH2015/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[8,21],"polygon":[[[8.807601928710938,47.66608099332474],[8.808631896972656,47.65475043477393],[8.830604553222656,47.648506014952225],[8.805885314941406,47.597597727711346],[8.749580383300781,47.61565270219988],[8.751983642578125,47.59505101193038],[8.807945251464844,47.585789182379905],[8.811721801757812,47.57467282332527],[8.840904235839844,47.57467282332527],[8.854637145996094,47.56216409801383],[8.8330078125,47.55382328811835],[8.845024108886719,47.53458802782819],[8.899612426757812,47.52786561031842],[8.895835876464844,47.491224888201955],[8.902702331542969,47.48588897929538],[8.887252807617188,47.475911695481756],[8.911285400390625,47.43969913094723],[8.934288024902344,47.43807362350206],[8.935317993164062,47.43017758727173],[8.917121887207031,47.42808726171425],[8.909912109375,47.404855836246135],[8.944587707519531,47.38905261221537],[8.945274353027344,47.379521907289295],[8.963127136230469,47.357664518690434],[8.973083496093748,47.35580389715929],[8.989906311035156,47.31857768821123],[8.973426818847656,47.30367985581531],[8.9593505859375,47.300653220457775],[8.941154479980469,47.2873805430142],[8.950080871582031,47.28458587064588],[8.940467834472656,47.259194168186234],[8.876266479492188,47.24847474828181],[8.876609802246092,47.243114224640834],[8.850173950195312,47.23961793870555],[8.849830627441406,47.247076403108416],[8.825111389160156,47.24824169331652],[8.800048828125,47.24031721435106],[8.804855346679688,47.23425651880584],[8.815155029296875,47.217702626593784],[8.793525695800781,47.21886856286133],[8.71490478515625,47.20021050593422],[8.685722351074219,47.18154588528182],[8.697395324707031,47.163108130899104],[8.660659790039062,47.15633823511178],[8.6572265625,47.16684287656919],[8.618087768554688,47.172444502751944],[8.622550964355469,47.17991241867412],[8.607101440429688,47.201376826785406],[8.595085144042969,47.19834433924206],[8.575859069824219,47.21513747655813],[8.541183471679688,47.2186353776589],[8.471488952636719,47.2053421258966],[8.441619873046875,47.22120035848172],[8.417243957519531,47.22120035848172],[8.383941650390625,47.292270864380086],[8.422050476074219,47.302282968719936],[8.442306518554688,47.32439601339355],[8.413810729980469,47.32299967378833],[8.408660888671875,47.33067908487908],[8.378448486328125,47.39718721653071],[8.360939025878906,47.39695481668995],[8.359222412109375,47.4053205652024],[8.379135131835938,47.40764414848437],[8.377418518066406,47.41624051540972],[8.384284973144531,47.42274494145051],[8.372611999511719,47.42808726171425],[8.372955322265625,47.437376962080776],[8.379478454589844,47.45037978769006],[8.36402893066406,47.46198673754625],[8.352012634277344,47.5079250985124],[8.373985290527344,47.517200697839414],[8.392181396484375,47.5366741201253],[8.417587280273436,47.56610235225701],[8.430290222167967,47.5693453981427],[8.491744995117188,47.581620824334166],[8.487625122070312,47.58648387645128],[8.463935852050781,47.58301031389572],[8.453292846679688,47.60315376826432],[8.479385375976562,47.617504142079596],[8.505821228027344,47.61958693358351],[8.513717651367188,47.635783590864854],[8.542213439941406,47.632776019724375],[8.545646667480469,47.627685889602006],[8.564186096191406,47.6256034207548],[8.566932678222656,47.61935551640258],[8.576202392578125,47.613569753973955],[8.564872741699219,47.60037582174319],[8.535346984863281,47.586715439092906],[8.550109863281248,47.5714301073211],[8.555259704589844,47.55498181333744],[8.581008911132812,47.59551406038282],[8.598861694335936,47.61449551898437],[8.59130859375,47.64642437575518],[8.609848022460938,47.65521295468833],[8.620834350585938,47.646886969413],[8.618431091308594,47.65660048985082],[8.602981567382812,47.666312203609145],[8.610877990722656,47.67856488312544],[8.62323760986328,47.67856488312544],[8.621864318847656,47.69312564683551],[8.64898681640625,47.697516190510555],[8.667526245117188,47.68665469810477],[8.671646118164062,47.67602211074509],[8.692245483398438,47.65197522925437],[8.734817504882812,47.64526787368664],[8.777389526367188,47.65313158281113],[8.785629272460938,47.667930646923494],[8.807601928710938,47.66608099332474]]],"terms_text":"Kanton Zürich OF 2015","best":true},{"id":"kelowna_2012","name":"Kelowna 2012","type":"tms","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/kelowna2012/{zoom}/{x}/{y}.png","description":"High quality aerial imagery taken for the City of Kelowna","scaleExtent":[9,20],"polygon":[[[-119.5867318,49.7928087],[-119.5465655,49.7928097],[-119.5465661,49.8013837],[-119.5343374,49.8013841],[-119.5343376,49.8047321],[-119.5296211,49.8047322],[-119.5296216,49.8119555],[-119.5104463,49.811956],[-119.5115683,49.8744325],[-119.5108946,49.8744904],[-119.5114111,49.8843312],[-119.5114115,49.9221763],[-119.49386,49.9223477],[-119.4940505,49.9313031],[-119.4803936,49.9317529],[-119.4804572,49.9407474],[-119.4666732,49.9409927],[-119.4692775,49.9913717],[-119.4551337,49.9916078],[-119.4556736,50.0121242],[-119.4416673,50.0123895],[-119.4417308,50.0136345],[-119.4221492,50.0140377],[-119.4221042,50.0119306],[-119.4121303,50.012165],[-119.4126082,50.0216913],[-119.4123387,50.0216913],[-119.4124772,50.0250773],[-119.4120917,50.0250821],[-119.4121954,50.0270769],[-119.4126083,50.0270718],[-119.4128328,50.0321946],[-119.3936313,50.0326418],[-119.393529,50.0307781],[-119.3795727,50.0310116],[-119.3795377,50.0287584],[-119.3735764,50.0288621],[-119.371544,49.9793618],[-119.3573506,49.9793618],[-119.3548353,49.9256081],[-119.3268079,49.9257238],[-119.3256573,49.8804068],[-119.3138893,49.8806528],[-119.3137097,49.8771651],[-119.3132156,49.877223],[-119.3131482,49.8749652],[-119.312452,49.8749073],[-119.3122275,49.87236],[-119.3117558,49.872331],[-119.3115986,49.8696098],[-119.3112169,49.8694217],[-119.3109199,49.8632417],[-119.3103721,49.8632724],[-119.3095139,49.8512388],[-119.3106368,49.8512316],[-119.3103859,49.8462564],[-119.3245344,49.8459957],[-119.3246018,49.8450689],[-119.3367018,49.844875],[-119.3367467,49.8435136],[-119.337937,49.8434702],[-119.3378023,49.8382055],[-119.3383637,49.8381041],[-119.3383749,49.8351202],[-119.3390936,49.8351058],[-119.3388016,49.8321217],[-119.3391497,49.8320565],[-119.3391722,49.8293331],[-119.3394641,49.8293331],[-119.3395879,49.8267878],[-119.3500053,49.8265829],[-119.3493701,49.8180588],[-119.4046964,49.8163785],[-119.4045694,49.8099022],[-119.4101592,49.8099022],[-119.4102862,49.8072787],[-119.4319467,49.8069098],[-119.4322643,49.7907965],[-119.4459847,49.7905504],[-119.445286,49.7820201],[-119.4967376,49.7811587],[-119.4966105,49.7784927],[-119.5418371,49.7775082],[-119.5415892,49.7718277],[-119.5560296,49.7714941],[-119.5561194,49.7718422],[-119.5715704,49.7715086],[-119.5716153,49.7717262],[-119.5819235,49.7714941],[-119.5820133,49.7717697],[-119.5922991,49.7715231],[-119.592344,49.7718132],[-119.6003839,49.7715957],[-119.6011924,49.7839081],[-119.5864365,49.7843863],[-119.5867318,49.7928087]]]},{"id":"kelowna_roads","name":"Kelowna Roads overlay","type":"tms","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/kelowna_overlay/{zoom}/{x}/{y}.png","scaleExtent":[9,20],"polygon":[[[-119.5867318,49.7928087],[-119.5465655,49.7928097],[-119.5465661,49.8013837],[-119.5343374,49.8013841],[-119.5343376,49.8047321],[-119.5296211,49.8047322],[-119.5296216,49.8119555],[-119.5104463,49.811956],[-119.5115683,49.8744325],[-119.5108946,49.8744904],[-119.5114111,49.8843312],[-119.5114115,49.9221763],[-119.49386,49.9223477],[-119.4940505,49.9313031],[-119.4803936,49.9317529],[-119.4804572,49.9407474],[-119.4666732,49.9409927],[-119.4692775,49.9913717],[-119.4551337,49.9916078],[-119.4556736,50.0121242],[-119.4416673,50.0123895],[-119.4417308,50.0136345],[-119.4221492,50.0140377],[-119.4221042,50.0119306],[-119.4121303,50.012165],[-119.4126082,50.0216913],[-119.4123387,50.0216913],[-119.4124772,50.0250773],[-119.4120917,50.0250821],[-119.4121954,50.0270769],[-119.4126083,50.0270718],[-119.4128328,50.0321946],[-119.3936313,50.0326418],[-119.393529,50.0307781],[-119.3795727,50.0310116],[-119.3795377,50.0287584],[-119.3735764,50.0288621],[-119.371544,49.9793618],[-119.3573506,49.9793618],[-119.3548353,49.9256081],[-119.3268079,49.9257238],[-119.3256573,49.8804068],[-119.3138893,49.8806528],[-119.3137097,49.8771651],[-119.3132156,49.877223],[-119.3131482,49.8749652],[-119.312452,49.8749073],[-119.3122275,49.87236],[-119.3117558,49.872331],[-119.3115986,49.8696098],[-119.3112169,49.8694217],[-119.3109199,49.8632417],[-119.3103721,49.8632724],[-119.3095139,49.8512388],[-119.3106368,49.8512316],[-119.3103859,49.8462564],[-119.3245344,49.8459957],[-119.3246018,49.8450689],[-119.3367018,49.844875],[-119.3367467,49.8435136],[-119.337937,49.8434702],[-119.3378023,49.8382055],[-119.3383637,49.8381041],[-119.3383749,49.8351202],[-119.3390936,49.8351058],[-119.3388016,49.8321217],[-119.3391497,49.8320565],[-119.3391722,49.8293331],[-119.3394641,49.8293331],[-119.3395879,49.8267878],[-119.3500053,49.8265829],[-119.3493701,49.8180588],[-119.4046964,49.8163785],[-119.4045694,49.8099022],[-119.4101592,49.8099022],[-119.4102862,49.8072787],[-119.4319467,49.8069098],[-119.4322643,49.7907965],[-119.4459847,49.7905504],[-119.445286,49.7820201],[-119.4967376,49.7811587],[-119.4966105,49.7784927],[-119.5418371,49.7775082],[-119.5415892,49.7718277],[-119.5560296,49.7714941],[-119.5561194,49.7718422],[-119.5715704,49.7715086],[-119.5716153,49.7717262],[-119.5819235,49.7714941],[-119.5820133,49.7717697],[-119.5922991,49.7715231],[-119.592344,49.7718132],[-119.6003839,49.7715957],[-119.6011924,49.7839081],[-119.5864365,49.7843863],[-119.5867318,49.7928087]]],"overlay":true},{"id":"landsat_233055","name":"Landsat 233055","type":"tms","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/landsat_233055/{zoom}/{x}/{y}.png","description":"Recent Landsat imagery","scaleExtent":[5,14],"polygon":[[[-60.8550011,6.1765004],[-60.4762612,7.9188291],[-62.161689,8.2778675],[-62.5322549,6.5375488],[-60.8550011,6.1765004]]]},{"id":"landsat_047026","name":"Latest southwest British Columbia Landsat","type":"tms","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/landsat_047026/{zoom}/{x}/{y}.png","description":"Recent lower-resolution landsat imagery for southwest British Columbia","scaleExtent":[5,13],"polygon":[[[-121.9355512,47.7820648],[-121.5720582,48.6410125],[-121.2015461,49.4846247],[-121.8375516,49.6023246],[-122.4767046,49.7161735],[-123.118912,49.8268824],[-123.760228,49.9335836],[-124.0887706,49.0870469],[-124.4128889,48.2252567],[-123.792772,48.1197334],[-123.1727942,48.0109592],[-122.553553,47.8982299],[-121.9355512,47.7820648]]]},{"id":"ORT10LT","name":"Lithuania - NŽT ORT10LT","type":"tms","template":"http://mapproxy.openmap.lt/ort10lt/g/{zoom}/{x}/{y}.jpeg","scaleExtent":[4,18],"polygon":[[[26.2138385,55.850748],[26.3858298,55.7045315],[26.6303618,55.6806692],[26.6205349,55.5689227],[26.5242191,55.5099228],[26.5541476,55.388833],[26.4399286,55.3479351],[26.7919694,55.3212027],[26.8291304,55.2763488],[26.7434625,55.2539863],[26.6764846,55.158828],[26.4611191,55.1285624],[26.3577434,55.1505399],[26.2296342,55.1073177],[26.2713814,55.0775905],[26.2085126,54.997414],[26.0619117,54.9416094],[25.8578176,54.9276001],[25.7429827,54.8150641],[25.7626083,54.5769013],[25.5319352,54.3418175],[25.6771618,54.3238109],[25.7857293,54.2336242],[25.7858844,54.1550594],[25.5550843,54.1461918],[25.5109462,54.1750267],[25.5896725,54.2285838],[25.5136246,54.3078472],[25.2689287,54.2744706],[25.0705963,54.1336282],[24.9573726,54.1720575],[24.8133801,54.144862],[24.7790172,54.0999054],[24.8712786,54.034904],[24.819568,53.9977218],[24.6845912,53.9621091],[24.697865,54.0171421],[24.6259068,54.0105048],[24.4342619,53.9014424],[24.3520594,53.8967893],[24.2016059,53.9700069],[23.9683341,53.9266977],[23.9130177,53.9696842],[23.7781192,53.8989169],[23.7097655,53.9394502],[23.5370435,53.9430702],[23.4822428,53.9893848],[23.5273356,54.0473482],[23.4858579,54.1532339],[23.3867851,54.224838],[23.0421216,54.3159745],[23.0102115,54.3827959],[22.8546899,54.4104029],[22.7919963,54.3633227],[22.7023421,54.4528985],[22.6838586,54.585972],[22.7489713,54.6319792],[22.7429727,54.7268221],[22.8866837,54.8135001],[22.8204005,54.9119829],[22.6424041,54.9713362],[22.5892361,55.070243],[22.080597,55.0244812],[22.0324081,55.084098],[21.9130671,55.0816838],[21.6491949,55.1808113],[21.5015124,55.1868198],[21.3843708,55.2936996],[21.2709829,55.2450059],[21.0983616,55.2563884],[20.9421741,55.282453],[21.0863466,55.5618266],[21.0399547,55.8363584],[21.0640261,56.0699542],[21.2047804,56.0811668],[21.2307958,56.1623302],[21.5021038,56.2954952],[21.7235874,56.3138211],[21.8356623,56.37162],[21.9695397,56.3766515],[22.0153001,56.4242811],[22.4372717,56.406405],[22.6800028,56.3515884],[22.9191739,56.3790184],[22.9466759,56.4146477],[23.0932498,56.3046383],[23.1703443,56.3667721],[23.3064522,56.3830535],[23.5571715,56.3338187],[23.7647953,56.3733238],[23.7666897,56.3238079],[24.0189971,56.3297615],[24.1214631,56.2488984],[24.2857421,56.3006367],[24.4541496,56.2581579],[24.5794651,56.2882389],[24.6284061,56.3753322],[24.9023767,56.4805317],[25.1277405,56.2059091],[25.5771398,56.182414],[25.6731232,56.1493667],[26.2138385,55.850748]]],"terms_url":"http://www.geoportal.lt","terms_text":"NŽT ORT10LT","best":true},{"id":"mapbox_locator_overlay","name":"Locator Overlay","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/openstreetmap.map-inh76ba2/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","description":"Shows major features to help orient you.","scaleExtent":[0,16],"overzoom":false,"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","default":true,"overlay":true},{"id":"londrina2011","name":"Londrina Ortofoto 2011","type":"tms","template":"https://siglon.londrina.pr.gov.br/arcgis/rest/services/Imagens/Ortofotos_2011_Paranacidade/MapServer/WMTS/tile/1.0.0/Imagens_Ortofotos_2011_Paranacidade/default/GoogleMapsCompatible/{zoom}/{y}/{x}","polygon":[[[-51.10903142008701,-23.392750890870328],[-51.110147219037096,-23.39111628244602],[-51.111981850003126,-23.389599820448623],[-51.11358044657587,-23.38976722295012],[-51.120999436701226,-23.38592675938185],[-51.12224934611127,-23.385109415587607],[-51.12483499560139,-23.383504255873166],[-51.12538216624037,-23.38186953335707],[-51.12482426676533,-23.37770385409619],[-51.12445948633935,-23.375054689723584],[-51.124373655650885,-23.372297138974446],[-51.12244246516032,-23.37032742475139],[-51.12302182230749,-23.366427304263887],[-51.128557901713755,-23.36548180323493],[-51.12832186732048,-23.358843408308623],[-51.12477062258506,-23.35475580404945],[-51.12703440699343,-23.35091432623551],[-51.12411616358548,-23.34679692655685],[-51.12025378260435,-23.347811512977742],[-51.1176466754421,-23.33969460448754],[-51.11264703783877,-23.341290443649072],[-51.109396200513004,-23.33488726938344],[-51.10756156954697,-23.334089313725826],[-51.10485790286019,-23.333980949007543],[-51.10252974543546,-23.334187827029368],[-51.09986899409291,-23.331015661953632],[-51.09801290545476,-23.329360589233605],[-51.09998701128955,-23.32830645478855],[-51.10322711977927,-23.325321337105603],[-51.10472915682748,-23.323193291476684],[-51.104664783811145,-23.321291814470847],[-51.10514758143378,-23.318444474199904],[-51.1063599399084,-23.3157547161216],[-51.10660670313775,-23.31467091543279],[-51.11050127062705,-23.311665785493048],[-51.111584883068964,-23.30842411016493],[-51.099504213666904,-23.309468549142686],[-51.09740136179941,-23.308631027972474],[-51.09511611971892,-23.307448636164267],[-51.09201548609798,-23.3049360186679],[-51.09036324534495,-23.3037141796735],[-51.09204767260616,-23.29874787986134],[-51.09269140276969,-23.297496421894902],[-51.09407542262125,-23.292953629109174],[-51.10073802981369,-23.293318240761657],[-51.10101697955121,-23.28870632248831],[-51.10068438563339,-23.28837126237015],[-51.10084531817427,-23.28777997775132],[-51.09937546763423,-23.28663682004102],[-51.09631774935752,-23.277914991984613],[-51.10285161051725,-23.273016720553397],[-51.10835550341534,-23.27033590016574],[-51.11309764895328,-23.268404099092194],[-51.13160489115448,-23.265338785827712],[-51.13188384089201,-23.262007272160396],[-51.1317336371872,-23.255058136908826],[-51.13290308031759,-23.254683563301587],[-51.132956724497895,-23.250750476893938],[-51.13473771128364,-23.2512729236245],[-51.13533852610292,-23.25133206840842],[-51.13516686472599,-23.24359373640034],[-51.13534925493897,-23.24117849627157],[-51.137516479822814,-23.24219388826517],[-51.13884685549409,-23.243495156026544],[-51.14108918223035,-23.24521044413634],[-51.1471724322756,-23.243179698340864],[-51.14761231455401,-23.23828015040167],[-51.149082165094036,-23.235884531292832],[-51.14976881060179,-23.236811236789336],[-51.15138886484666,-23.23853646924079],[-51.15289090189487,-23.238842079520833],[-51.15383503946804,-23.238950521710013],[-51.15820167574391,-23.238142132361276],[-51.16045473131624,-23.238161849232945],[-51.160347442955654,-23.24658068718069],[-51.15912435564498,-23.2478326235554],[-51.16131303820094,-23.247773477219496],[-51.166591625541805,-23.245939927797],[-51.17193458589902,-23.245821633420345],[-51.17205260309565,-23.249557713480034],[-51.174241285651625,-23.248404370116877],[-51.17514250788055,-23.2493211310392],[-51.176859121649926,-23.248157927934038],[-51.179466228812196,-23.251686936561047],[-51.18135450395853,-23.253806268366073],[-51.18273852381009,-23.253628837227893],[-51.18378994974384,-23.253264116924615],[-51.18495939287424,-23.253303546194683],[-51.18626831087339,-23.252150235227905],[-51.18665454897149,-23.247477745146526],[-51.191182117788244,-23.249143693933142],[-51.19141815218154,-23.252859966234126],[-51.19369266542598,-23.252781107419985],[-51.1938428691308,-23.26073575534214],[-51.20096681627374,-23.26054847664639],[-51.20126722368338,-23.24259807127726],[-51.209936123218775,-23.242775517090898],[-51.21090171846407,-23.26988252079656],[-51.21968863519614,-23.27221839365197],[-51.225965004290465,-23.2745345140599],[-51.22934458764894,-23.27860487489667],[-51.234515886629225,-23.28160089636689],[-51.23497722657975,-23.283246708422755],[-51.235073786104266,-23.285444377831148],[-51.23371122392482,-23.285897704227196],[-51.232155542696304,-23.28801649191402],[-51.22870085748543,-23.292293383844925],[-51.227402668322334,-23.294599300809004],[-51.22679112466699,-23.295476327114592],[-51.225600223864475,-23.29657013833941],[-51.22392652543933,-23.297210654251764],[-51.220482569064515,-23.30072850975029],[-51.21863720926242,-23.301300029310937],[-51.21668456109974,-23.30211788923888],[-51.21423838647836,-23.30441378240661],[-51.210966091480465,-23.306965823153238],[-51.22328279527583,-23.318296686707587],[-51.224387865389886,-23.31459209321986],[-51.22521398576639,-23.312887551432937],[-51.22511742624187,-23.312582111000477],[-51.22521398576639,-23.312513140483127],[-51.2255251220121,-23.312532846348883],[-51.22595427545445,-23.312385052284572],[-51.22616885217561,-23.31183328632629],[-51.22935531648505,-23.314887676277397],[-51.22802494081377,-23.31661189768144],[-51.227885465945,-23.31901591762422],[-51.22767088922384,-23.320227763653186],[-51.22723100694544,-23.321508564518947],[-51.2273919394863,-23.322227778055023],[-51.22725246461755,-23.322848466059934],[-51.230331640566384,-23.325577488448165],[-51.23046038659909,-23.326710459617892],[-51.229537706698046,-23.32789268010374],[-51.229162197436,-23.330503379743732],[-51.229290943468705,-23.33178408156439],[-51.22681258233914,-23.334473515196468],[-51.2260186484708,-23.336571826694826],[-51.22473118814376,-23.33839427691611],[-51.22210262330938,-23.340226553005806],[-51.22257469209598,-23.34196029634743],[-51.22380850824271,-23.343388647432523],[-51.22384069475089,-23.345309509145306],[-51.22440932306201,-23.347003784611864],[-51.2245380690947,-23.348294177581966],[-51.22404454263601,-23.34968305981433],[-51.22350810083308,-23.35010661675208],[-51.22381923707877,-23.35076657486812],[-51.22304676088255,-23.35174173085325],[-51.22259614976809,-23.35296312824164],[-51.22586844476598,-23.35480505304304],[-51.22650144609346,-23.36705763453823],[-51.22354028734128,-23.369145582171885],[-51.22366903337377,-23.37968330666716],[-51.220375280703756,-23.381633186264455],[-51.216469984378406,-23.38170212087667],[-51.21416328462579,-23.379949201028825],[-51.2092816642191,-23.37395167630701],[-51.20738266023672,-23.368141007697016],[-51.20628831895872,-23.36723491438801],[-51.20472190889416,-23.366269721227162],[-51.198230963078665,-23.366683376299132],[-51.19297383340994,-23.366506095711998],[-51.18986247095292,-23.3654424072124],[-51.18806002649507,-23.36464463523902],[-51.18718026193825,-23.3645264463904],[-51.18579624208668,-23.363738518041337],[-51.183038931219606,-23.36359078095478],[-51.18071077379488,-23.3637582163071],[-51.179069261877906,-23.361581540240305],[-51.177642326682125,-23.35836078207346],[-51.16683838877106,-23.356262814974126],[-51.166141014427254,-23.358538073547532],[-51.16475699457568,-23.360389770338585],[-51.16076586756186,-23.359217688669915],[-51.15983245882475,-23.36660458495632],[-51.162042599052846,-23.36861374957437],[-51.16276143106877,-23.374158492021696],[-51.158448438973174,-23.37580315788644],[-51.155047397942575,-23.376305417047273],[-51.15396378550066,-23.37903334042617],[-51.15298746141932,-23.381052164536694],[-51.15118501696147,-23.382076336717283],[-51.149167995782435,-23.382509637949354],[-51.14721534761976,-23.382155118864866],[-51.14517686876862,-23.382588419839323],[-51.14410398516276,-23.38376029492248],[-51.14512322458833,-23.388083341091015],[-51.141797285410156,-23.389402876058366],[-51.14030597719799,-23.38880219385971],[-51.14068148646006,-23.391608636504017],[-51.14127157244328,-23.393538646762796],[-51.14093897852546,-23.394434713394368],[-51.140456180902824,-23.39536031431835],[-51.13939402613302,-23.395104297688697],[-51.13738773379004,-23.393154616350518],[-51.13608954462695,-23.389796764546077],[-51.13428710016909,-23.389757375749994],[-51.132162790629465,-23.390072485790583],[-51.13172290835106,-23.39285920758337],[-51.12259266886514,-23.38864463742227],[-51.12228153261944,-23.391657871809155],[-51.11882684740854,-23.393174310244916],[-51.115683298443365,-23.393351555162592],[-51.10903142008701,-23.392750890870328]],[[-51.13829432042955,-23.41600741009485],[-51.133310776080314,-23.418665600378624],[-51.132087688769644,-23.416440600302334],[-51.13002238782791,-23.418291487939495],[-51.12868664773901,-23.419010176689888],[-51.12824140104259,-23.42102839134528],[-51.12696466955051,-23.421860280620358],[-51.12532852205271,-23.422692164660027],[-51.1244541219139,-23.420969322085504],[-51.1215144208339,-23.424109801147612],[-51.12063465627703,-23.423268081315832],[-51.11970661195797,-23.423120410617486],[-51.11977098497433,-23.42156985833077],[-51.1188000253111,-23.421545246243184],[-51.11643431696008,-23.420836416154565],[-51.11942766222045,-23.419167696990424],[-51.11787198099193,-23.416775337218567],[-51.116546969738685,-23.41730697646229],[-51.115699391690086,-23.415702207051474],[-51.115120034542905,-23.413088261827834],[-51.119078975048524,-23.411114231305813],[-51.119599323597356,-23.41169512115064],[-51.12052200349841,-23.41489489238112],[-51.12147686990764,-23.417139608782644],[-51.12308619531643,-23.418626220171642],[-51.12754939111684,-23.41653905242448],[-51.12803218873949,-23.417395582795194],[-51.13119719537679,-23.415574218468866],[-51.13080022844262,-23.414766903017576],[-51.13278506311348,-23.41264029239725],[-51.13521514448077,-23.411055157619415],[-51.13585887464424,-23.410956701416854],[-51.13682446988958,-23.411188073376714],[-51.137205343569626,-23.411576974270133],[-51.13730190309418,-23.41324086645236],[-51.137430649126884,-23.414707830961888],[-51.13829432042955,-23.41600741009485]],[[-51.18929065852,-23.61469318354],[-51.18868716149,-23.61385268133],[-51.18817754178,-23.61338573333],[-51.18731118826,-23.61301708899],[-51.18628926663,-23.61314488581],[-51.18401743559,-23.61395590119],[-51.18348904042,-23.61396573165],[-51.18183143525,-23.61283522407],[-51.18140496401,-23.61344471632],[-51.18062980561,-23.61313505529],[-51.18001021533,-23.61409352754],[-51.17865838198,-23.61328742827],[-51.18064589886,-23.61060367181],[-51.17972321896,-23.61018095058],[-51.18061639456,-23.60849005203],[-51.1821157494,-23.60850479833],[-51.18260927586,-23.60775273479],[-51.18319936184,-23.60804274673],[-51.18415154605,-23.60627808786],[-51.18511177687,-23.60666149766],[-51.18649043231,-23.60469528171],[-51.18902243762,-23.60610112912],[-51.18821241049,-23.60741848294],[-51.18918873458,-23.60801816947],[-51.188899056,-23.60953211999],[-51.18962325244,-23.60992535103],[-51.1911896625,-23.6111935131],[-51.1901489654,-23.61244691705],[-51.19054056792,-23.6127565797],[-51.19029380469,-23.61377895281],[-51.18929065852,-23.61469318354]],[[-51.08005769639,-23.52984412096],[-51.07962317853,-23.52205317842],[-51.08468182473,-23.52194496764],[-51.08581908135,-23.52404030606],[-51.0858941832,-23.52703569673],[-51.08579494147,-23.52777346722],[-51.08530141501,-23.52806365581],[-51.08513511805,-23.52856533627],[-51.08512438922,-23.52981952906],[-51.08470864682,-23.53023759067],[-51.08343459754,-23.53023759067],[-51.08329512267,-23.52978018202],[-51.08005769639,-23.52984412096]]],"terms_url":"http://siglon.londrina.pr.gov.br/","terms_text":"Prefeitura do Londrinas, PR"},{"id":"NSW_LPI_BaseMap","name":"LPI NSW Base Map","type":"tms","template":"https://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Base_Map/MapServer/tile/{zoom}/{y}/{x}","scaleExtent":[0,19],"polygon":[[[140.9948644,-28.952966],[148.9611382,-28.8997729],[148.9870097,-28.4862285],[151.013609,-28.4786485],[151.1084711,-28.7032909],[151.8759917,-28.683118],[151.9334839,-28.4078753],[152.25544,-28.2332683],[153.0660798,-28.2104723],[153.1408196,-28.1090981],[153.4735137,-28.1164808],[153.3576523,-27.693606],[159.4938303,-27.699252],[159.4856997,-37.8474137],[149.5256879,-37.8281502],[149.9159578,-37.4869999],[148.0485886,-36.8131741],[147.9680996,-36.1567945],[146.7147701,-36.2866613],[145.3004625,-36.1567945],[144.5300673,-36.1475101],[142.8397973,-35.0254303],[142.356863,-34.7802471],[141.9774146,-34.4016159],[140.9950258,-34.1371824],[140.9948644,-28.952966]]],"terms_url":"http://spatialservices.finance.nsw.gov.au/mapping_and_imagery/lpi_web_services","terms_text":"© Land and Property Information 2016"},{"id":"NSW_LPI_Imagery","name":"LPI NSW Imagery","type":"tms","template":"https://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Imagery/MapServer/tile/{zoom}/{y}/{x}","scaleExtent":[0,21],"polygon":[[[140.9868688,-28.9887829],[148.9951472,-28.9727491],[148.9966717,-28.4915066],[151.0029027,-28.4930697],[151.0029027,-28.7261663],[151.4915093,-28.7323921],[151.4918687,-28.7155337],[151.9228213,-28.719635],[151.9251607,-28.4897139],[151.9955886,-28.4898718],[151.9989947,-28.1192742],[152.4967606,-28.122091],[152.4968241,-28.1146398],[153.0044563,-28.1154389],[153.0044563,-28.120397],[153.5038629,-28.119345],[153.5039264,-28.1227063],[153.5919395,-28.1223619],[153.5926582,-28.1776872],[153.6111186,-28.1757867],[153.6113881,-28.1825173],[153.7426846,-28.2162084],[153.7787253,-28.710911],[152.6237954,-32.5877239],[152.3123961,-32.6328837],[151.4141942,-33.5790388],[150.8929925,-35.2648721],[150.4620695,-35.7777256],[150.0156501,-37.5103569],[149.9918121,-37.5126787],[149.519778,-37.5130704],[149.5199577,-37.5216919],[149.4462958,-37.5353701],[149.063344,-37.5357975],[148.9836635,-37.5217631],[148.9816872,-37.5191982],[148.9863847,-37.2584972],[148.4875376,-37.265846],[148.4824774,-37.0092669],[147.994386,-37.014339],[147.988288,-36.5332184],[147.9529707,-36.5260725],[147.9486513,-36.0685992],[147.5034997,-36.0716798],[147.5047701,-36.2651047],[146.4919996,-36.266129],[146.4922536,-36.2565],[145.9929826,-36.2534267],[145.9965866,-36.0188147],[145.9831568,-36.0187058],[145.9624506,-36.0219026],[145.946236,-36.0120936],[145.9454275,-36.0060259],[145.5041534,-36.0013564],[145.5037941,-36.0109125],[145.0072008,-36.0036213],[145.0035404,-36.1520424],[144.4860806,-36.1423149],[144.4874127,-36.0137522],[143.9874676,-36.0024134],[143.9932853,-35.5723753],[143.4971691,-35.5837101],[143.4917967,-35.4065648],[143.4613438,-35.3674934],[143.4585591,-35.3555888],[143.4897755,-35.3396522],[143.4895509,-35.332214],[143.4316994,-35.2570613],[143.2505542,-35.2606556],[143.2438356,-35.0132729],[142.9933305,-35.0177207],[142.9919767,-34.7961882],[142.4971375,-34.8032323],[142.4973172,-34.8007613],[142.4211401,-34.8017571],[142.4209155,-34.7838306],[142.2330892,-34.7859191],[142.2307707,-34.7807542],[142.2269959,-34.5061271],[141.9975302,-34.5083733],[141.9945959,-34.2526687],[141.4982345,-34.2556921],[141.498171,-34.2522794],[140.9945397,-34.2528411],[140.9868688,-28.9887829]]],"terms_url":"http://spatialservices.finance.nsw.gov.au/mapping_and_imagery/lpi_web_services","terms_text":"© Land and Property Information 2016","best":true},{"id":"NSW_LPI_TopographicMap","name":"LPI NSW Topographic Map","type":"tms","template":"https://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Topo_Map/MapServer/tile/{zoom}/{y}/{x}","scaleExtent":[0,16],"polygon":[[[140.9988422,-28.9992444],[148.9502438,-28.9993736],[148.9498845,-28.9665265],[148.9998308,-28.9665265],[149.0000917,-28.8165829],[149.1000729,-28.8165829],[149.0997046,-28.7488533],[148.9998504,-28.7497444],[148.9998169,-28.5000304],[151.0000514,-28.5005192],[151.0005904,-28.7325849],[151.0239466,-28.7327424],[151.0241262,-28.7418794],[151.0329297,-28.7418794],[151.033828,-28.7505431],[151.999984,-28.7495314],[151.999984,-28.7164478],[152.0334014,-28.7166053],[152.0332217,-28.683196],[152.0000739,-28.6833537],[151.9998769,-28.6416273],[151.9829886,-28.6413908],[151.9831683,-28.624912],[151.9331321,-28.6247543],[151.9334122,-28.500071],[151.9998875,-28.5002289],[151.9998556,-28.3749591],[152.2499739,-28.3750718],[152.2499356,-28.2500066],[152.9997192,-28.2498563],[152.9998989,-28.2832447],[153.1165002,-28.2834029],[153.11659,-28.2498563],[153.1666262,-28.2500146],[153.166716,-28.2331582],[153.2499898,-28.2332373],[153.2500265,-28.1249689],[153.6249628,-28.1250833],[153.6248398,-28.4999134],[153.7497955,-28.4999924],[153.7495877,-28.7497976],[153.6248117,-28.7501127],[153.6249745,-28.9999333],[153.4997672,-29.0000612],[153.4998417,-29.4995077],[153.3747962,-29.500055],[153.3754111,-29.8750302],[153.4999113,-29.8751403],[153.4999113,-30.0000922],[153.2498947,-29.9997621],[153.250025,-30.1917704],[153.2748185,-30.1916151],[153.2748185,-30.2168467],[153.2166077,-30.2166139],[153.2166077,-30.250065],[153.250025,-30.250065],[153.2497502,-30.3751935],[153.1243608,-30.3749743],[153.1246457,-30.6250359],[153.0331676,-30.6250482],[153.0333884,-30.8750837],[153.1249214,-30.8750291],[153.1249344,-31.1250505],[153.0082433,-31.1249736],[153.0082914,-31.2499759],[153.0000019,-31.250003],[152.9999392,-31.6249919],[152.8749386,-31.6250491],[152.8749572,-31.749954],[152.7832899,-31.7500034],[152.7831966,-31.8748579],[152.749914,-31.8750105],[152.7500397,-32.0000207],[152.6249044,-31.9999446],[152.6249078,-32.5000047],[152.4999757,-32.4999569],[152.5000336,-32.5666443],[152.4166699,-32.5663415],[152.4167598,-32.6249954],[152.3498477,-32.624991],[152.3498477,-32.6332294],[152.2830786,-32.6332218],[152.2832583,-32.6249755],[152.2494816,-32.6249755],[152.2498101,-32.874906],[151.8745693,-32.8750443],[151.8748535,-33.0000091],[151.7497706,-33.0001533],[151.7504669,-33.2500398],[151.6252418,-33.2497393],[151.6250828,-33.3751621],[151.499585,-33.3751442],[151.5003127,-33.6249385],[151.3741466,-33.6243658],[151.3727902,-34.001962],[151.2477819,-34.0011194],[151.2477819,-34.2493114],[150.9957327,-34.2501515],[151.0008143,-34.62483],[150.8717407,-34.6265026],[150.872757,-35.1242738],[150.7670589,-35.1234425],[150.7690916,-35.2463774],[150.6257894,-35.2496974],[150.6280314,-35.3751485],[150.4999742,-35.3751485],[150.4959088,-35.6275034],[150.3719169,-35.6250251],[150.3749658,-35.7537957],[150.2672351,-35.7513213],[150.2652024,-35.8741232],[150.2479249,-35.870829],[150.2458922,-36.374885],[150.1229166,-36.374885],[150.1259656,-36.6224345],[150.0253491,-36.6240658],[150.0283981,-36.7471337],[149.9928266,-36.7495768],[150.0040062,-37.1224477],[150.0588879,-37.1273097],[150.0568553,-37.37809],[149.9979083,-37.3732441],[149.9999409,-37.4830073],[149.987745,-37.4846202],[149.9857123,-37.5080043],[148.0684571,-36.80624],[147.9930603,-36.1379955],[147.8148345,-36.0055567],[147.3893924,-36.0113701],[147.3822059,-36.1310306],[146.9972549,-36.1275479],[146.9886311,-36.2528271],[146.4956356,-36.2447132],[146.5042595,-36.126387],[145.0011817,-36.0079505],[145.0154103,-36.2542074],[144.5072465,-36.2476506],[144.4991158,-36.0211037],[143.9965422,-35.9810531],[143.3382568,-35.2331794],[142.4097581,-34.7669434],[142.0361436,-34.3758837],[140.9965216,-34.1385805],[140.9988422,-28.9992444]]],"terms_url":"http://spatialservices.finance.nsw.gov.au/mapping_and_imagery/lpi_web_services","terms_text":"© Land and Property Information 2016"},{"id":"Mapbox","name":"Mapbox Satellite","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/openstreetmap.map-inh7ifmo/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","description":"Satellite and aerial imagery.","scaleExtent":[0,19],"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","default":true},{"id":"geodata.md.gov-MD_SixInchImagery","name":"MD 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","description":"Six Inch resolution aerial imagery for the State of Maryland","scaleExtent":[0,20],"polygon":[[[-76.234131,37.920368],[-76.598053,38.158317],[-76.940002,38.270532],[-77.038193,38.413786],[-77.23526,38.33627],[-77.312164,38.410558],[-77.262726,38.566422],[-77.042999,38.713376],[-77.049866,38.793697],[-76.92627,38.892503],[-77.040939,38.984499],[-77.12162,38.925229],[-77.150116,38.955137],[-77.252426,38.975425],[-77.259293,39.024252],[-77.34581,39.054918],[-77.461853,39.070379],[-77.537384,39.139647],[-77.474213,39.224807],[-77.572746,39.304284],[-77.723465,39.328986],[-77.777023,39.463234],[-77.861481,39.516225],[-77.840881,39.608862],[-77.956238,39.59299],[-78.166351,39.695564],[-78.270035,39.621557],[-78.338699,39.640066],[-78.466415,39.523641],[-78.662796,39.540058],[-78.798752,39.606217],[-78.9814,39.446799],[-79.06723,39.476486],[-79.485054,39.199536],[-79.485569,39.72158],[-75.788359,39.721811],[-75.690994,38.460579],[-75.049238,38.458159],[-75.049839,38.402218],[-75.081511,38.323208],[-75.097733,38.309066],[-75.186996,38.097551],[-75.23798,38.022402],[-75.61821,37.989669],[-75.863686,37.909534],[-76.234131,37.920368]]],"terms_url":"http://imap.maryland.gov/Pages/imagery-products.aspx","terms_text":"DoIT, MD iMap, MDP"},{"id":"geodata.md.gov-MD_ColorBasemap","name":"MD Transportation Basemap","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/MD_ColorBasemap/http://geodata.md.gov/imap/services/Transportation/MD_ColorBasemap/MapServer/WmsServer","description":"Maryland State Highway Administration road features and additional Maryland focused landmarks","polygon":[[[-76.234131,37.920368],[-76.598053,38.158317],[-76.940002,38.270532],[-77.038193,38.413786],[-77.23526,38.33627],[-77.312164,38.410558],[-77.262726,38.566422],[-77.042999,38.713376],[-77.049866,38.793697],[-76.92627,38.892503],[-77.040939,38.984499],[-77.12162,38.925229],[-77.150116,38.955137],[-77.252426,38.975425],[-77.259293,39.024252],[-77.34581,39.054918],[-77.461853,39.070379],[-77.537384,39.139647],[-77.474213,39.224807],[-77.572746,39.304284],[-77.723465,39.328986],[-77.777023,39.463234],[-77.861481,39.516225],[-77.840881,39.608862],[-77.956238,39.59299],[-78.166351,39.695564],[-78.270035,39.621557],[-78.338699,39.640066],[-78.466415,39.523641],[-78.662796,39.540058],[-78.798752,39.606217],[-78.9814,39.446799],[-79.06723,39.476486],[-79.485054,39.199536],[-79.485569,39.72158],[-75.788359,39.721811],[-75.690994,38.460579],[-75.049238,38.458159],[-75.049839,38.402218],[-75.081511,38.323208],[-75.097733,38.309066],[-75.186996,38.097551],[-75.23798,38.022402],[-75.61821,37.989669],[-75.863686,37.909534],[-76.234131,37.920368]]],"terms_url":"http://imap.maryland.gov/Pages/imagery-products.aspx","terms_text":"DoIT, MD iMap, MDP"},{"id":"New_and_Misaligned_TIGER_Roads-2013","name":"New & Misaligned TIGER Roads","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/enf.e0b8291e/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJhNVlHd29ZIn0.ti6wATGDWOmCnCYen-Ip7Q","description":"At zoom level 16+, public domain map data from the US Census. At lower zooms, only changes since 2006 minus changes already incorporated into OpenStreetMap","scaleExtent":[0,22],"polygon":[[[-124.7617886,48.4130148],[-124.6059492,45.90245],[-124.9934269,40.0557614],[-122.5369737,36.8566086],[-119.9775867,33.0064099],[-117.675935,32.4630223],[-114.8612307,32.4799891],[-111.0089311,31.336015],[-108.1992687,31.3260016],[-108.1871123,31.7755116],[-106.5307225,31.7820947],[-106.4842052,31.7464455],[-106.429317,31.7520583],[-106.2868855,31.5613291],[-106.205248,31.446704],[-105.0205259,30.5360988],[-104.5881916,29.6997856],[-103.2518856,28.8908685],[-102.7173632,29.3920567],[-102.1513983,29.7475702],[-101.2552871,29.4810523],[-100.0062436,28.0082173],[-99.2351068,26.4475962],[-98.0109067,25.9928035],[-97.435024,25.8266009],[-96.9555259,25.9821589],[-96.8061741,27.7978168],[-95.5563349,28.5876066],[-93.7405308,29.4742093],[-90.9028456,28.8564513],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-84.0187909,28.9961781],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-79.8901116,26.8550713],[-80.0245309,32.0161282],[-75.4147385,35.0531894],[-74.0211163,39.5727927],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8489304,43.2619916],[-66.9452845,44.7104937],[-67.7596632,47.0990024],[-69.2505131,47.5122328],[-70.4614886,46.2176574],[-71.412273,45.254878],[-72.0222508,45.0059846],[-75.0798841,44.9802854],[-76.9023061,43.8024568],[-78.7623935,43.6249578],[-79.15798,43.4462589],[-79.0060087,42.8005317],[-82.662475,41.6889458],[-82.1761642,43.588535],[-83.2813977,46.138853],[-87.5064535,48.0142702],[-88.3492194,48.2963271],[-89.4353148,47.9837822],[-93.9981078,49.0067142],[-95.1105379,49.412004],[-96.0131199,49.0060547],[-123.3228926,49.0042878],[-123.2275233,48.1849927],[-124.7617886,48.4130148]],[[-160.5787616,22.5062947],[-160.5782192,21.4984647],[-158.7470604,21.2439843],[-157.5083185,20.995803],[-155.9961942,18.7790194],[-154.6217803,18.7586966],[-154.6890176,19.8805722],[-156.2927622,21.2225888],[-157.5047384,21.9984962],[-159.0093692,22.5070181],[-160.5787616,22.5062947]],[[-167.1571546,68.721974],[-164.8553982,67.0255078],[-168.002195,66.0017503],[-169.0087448,66.001546],[-169.0075381,64.9987675],[-172.5143281,63.8767267],[-173.8197023,59.74014],[-162.5018149,58.0005815],[-160.0159024,58.0012389],[-160.0149725,57.000035],[-160.5054788,56.9999017],[-165.8092575,54.824847],[-178.000097,52.2446469],[-177.9992996,51.2554252],[-171.4689067,51.8215329],[-162.40251,53.956664],[-159.0075717,55.002502],[-158.0190709,55.0027849],[-151.9963213,55.9991902],[-151.500341,57.9987853],[-151.5012894,58.9919816],[-138.5159989,58.9953194],[-138.5150471,57.9986434],[-133.9948193,54.0031685],[-130.0044418,54.0043387],[-130.0070826,57.0000507],[-131.975877,56.9995156],[-135.1229873,59.756601],[-138.0071813,59.991805],[-139.1715881,60.4127229],[-140.9874011,61.0118551],[-140.9683975,69.9535069],[-156.176891,71.5633329],[-160.413634,70.7397728],[-163.0218273,69.9707435],[-164.9717003,68.994689],[-167.1571546,68.721974]]],"overlay":true},{"id":"geodata.state.nj.us-Infrared2015","name":"NJ 2015 Aerial Imagery (Infrared)","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/Infrared2015/http://geodata.state.nj.us/imagerywms/Infrared2015","description":"Digital orthophotography of New Jersey, Near Infrared, 1 foot resolution","scaleExtent":[0,20],"polygon":[[[-74.86599,40.085427],[-74.840927,40.107225],[-74.822903,40.130329],[-74.788055,40.124685],[-74.726086,40.149488],[-74.729176,40.16392],[-74.763336,40.191725],[-74.775524,40.214276],[-74.844017,40.247957],[-74.868393,40.291573],[-74.944611,40.33817],[-74.967098,40.395195],[-75.002632,40.406046],[-75.026836,40.402516],[-75.06134,40.416502],[-75.074215,40.455046],[-75.069065,40.536503],[-75.102367,40.567024],[-75.135927,40.573609],[-75.16777,40.559069],[-75.197639,40.573674],[-75.203733,40.618318],[-75.205064,40.691312],[-75.198326,40.753889],[-75.172405,40.780671],[-75.1367,40.777292],[-75.090179,40.822383],[-75.100994,40.839269],[-75.096874,40.850956],[-75.068464,40.850372],[-75.057049,40.867574],[-75.13773,40.973094],[-75.135155,40.994411],[-75.039024,41.03819],[-74.981518,41.112598],[-74.905472,41.170384],[-74.84024,41.278645],[-74.798012,41.322685],[-74.757156,41.347691],[-74.695702,41.360576],[-74.041054,41.059088],[-74.041051,41.059087],[-74.04105,41.059087],[-74.04105,41.059086],[-74.041049,41.059086],[-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)"},{"id":"geodata.state.nj.us-Natural2015","name":"NJ 2015 Aerial Imagery (Natural Color)","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/Natural2015/http://geodata.state.nj.us/imagerywms/Natural2015","description":"Digital orthophotography of New Jersey, Natural Color, 1 foot resolution","scaleExtent":[0,20],"polygon":[[[-74.86599,40.085427],[-74.840927,40.107225],[-74.822903,40.130329],[-74.788055,40.124685],[-74.726086,40.149488],[-74.729176,40.16392],[-74.763336,40.191725],[-74.775524,40.214276],[-74.844017,40.247957],[-74.868393,40.291573],[-74.944611,40.33817],[-74.967098,40.395195],[-75.002632,40.406046],[-75.026836,40.402516],[-75.06134,40.416502],[-75.074215,40.455046],[-75.069065,40.536503],[-75.102367,40.567024],[-75.135927,40.573609],[-75.16777,40.559069],[-75.197639,40.573674],[-75.203733,40.618318],[-75.205064,40.691312],[-75.198326,40.753889],[-75.172405,40.780671],[-75.1367,40.777292],[-75.090179,40.822383],[-75.100994,40.839269],[-75.096874,40.850956],[-75.068464,40.850372],[-75.057049,40.867574],[-75.13773,40.973094],[-75.135155,40.994411],[-75.039024,41.03819],[-74.981518,41.112598],[-74.905472,41.170384],[-74.84024,41.278645],[-74.798012,41.322685],[-74.757156,41.347691],[-74.695702,41.360576],[-74.041054,41.059088],[-74.041051,41.059087],[-74.04105,41.059087],[-74.04105,41.059086],[-74.041049,41.059086],[-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)"},{"id":"NLS-Bartholomew-hfinch-hist","name":"NLS - Bartholomew Half Inch, 1897-1907","type":"tms","template":"http://geo.nls.uk/mapdata2/bartholomew/great_britain/{zoom}/{x}/{-y}.png","scaleExtent":[0,15],"polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-7th_Series","name":"NLS - OS 1-inch 7th Series 1955-61","type":"tms","template":"http://geo.nls.uk/mapdata2/os/seventh/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-1st_Series","name":"NLS - OS 1:25k 1st Series 1937-61","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25000/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-4.7157244,54.6796556],[-4.6850662,54.6800268],[-4.6835779,54.6623245],[-4.7148782,54.6615818],[-4.7157244,54.6796556]],[[-3.7085748,58.3371151],[-3.5405937,58.3380684],[-3.5315137,58.1608002],[-3.3608086,58.1622372],[-3.3653486,58.252173],[-3.1610473,58.2536063],[-3.1610473,58.3261509],[-3.0275704,58.3271045],[-3.0366505,58.6139001],[-3.0021463,58.614373],[-3.0030543,58.7036341],[-3.4180129,58.7003322],[-3.4171049,58.6290293],[-3.7240109,58.6266658],[-3.7231029,58.606806],[-4.2361262,58.5992374],[-4.2334022,58.5092347],[-3.88836,58.5144516],[-3.8829119,58.4261327],[-3.7158389,58.4270836],[-3.7085748,58.3371151]],[[-6.46676,49.9943621],[-6.1889102,50.004868],[-6.1789222,49.8967815],[-6.3169391,49.8915171],[-6.312399,49.8200979],[-6.4504159,49.8159968],[-6.46676,49.9943621]],[[-5.6453263,50.2029809],[-5.7801329,50.2014076],[-5.7637888,50.0197267],[-5.3479221,50.0290604],[-5.3388421,49.9414854],[-5.024672,49.9473287],[-5.0355681,50.0383923],[-5.0010639,50.0453901],[-4.9974319,50.1304478],[-4.855783,50.13394],[-4.861231,50.206057],[-4.6546085,50.2140172],[-4.6558926,50.3018616],[-4.5184924,50.3026818],[-4.51464,50.325642],[-4.2488284,50.3264618],[-4.2488284,50.3100631],[-4.10886,50.3141633],[-4.1062917,50.2411267],[-3.9648088,50.2432047],[-3.9640778,50.2254158],[-3.8522287,50.2273626],[-3.8503757,50.1552563],[-3.6921809,50.1572487],[-3.5414602,50.1602198],[-3.5465781,50.3226814],[-3.4068012,50.3241013],[-3.4165761,50.5892711],[-3.2746691,50.5962721],[-3.2749172,50.6106323],[-2.9971742,50.613972],[-2.9896008,50.688537],[-2.7120266,50.690565],[-2.710908,50.6195964],[-2.5695473,50.6157538],[-2.5651019,50.5134083],[-2.4014463,50.513379],[-2.3940583,50.6160348],[-2.2894123,50.6147436],[-2.2876184,50.6008549],[-2.1477855,50.6048506],[-2.1451013,50.5325437],[-1.9335117,50.5347477],[-1.9362139,50.6170445],[-1.8573025,50.6228094],[-1.8554865,50.709139],[-1.6066929,50.709139],[-1.6085089,50.6239615],[-1.4450678,50.6228094],[-1.4432518,50.5317039],[-1.1545059,50.5293951],[-1.1472419,50.6170485],[-1.011041,50.6205051],[-1.011041,50.7056889],[-0.704135,50.7045388],[-0.700503,50.7769401],[-0.5860943,50.7723465],[-0.5879103,50.7907181],[-0.0149586,50.7798108],[-0.0185906,50.7625836],[0.0967261,50.7620093],[0.0921861,50.6913106],[0.3046595,50.6890096],[0.3101075,50.7757917],[0.5511831,50.7726336],[0.5529991,50.8432096],[0.695556,50.8403428],[0.696464,50.8592608],[0.9852099,50.8523824],[0.9906579,50.9417226],[1.0160821,50.9411504],[1.0215301,51.0303204],[1.2812198,51.0240383],[1.2848518,51.0948044],[1.4277848,51.0948044],[1.4386809,51.2882859],[1.4713691,51.2871502],[1.4804492,51.3994534],[1.1590151,51.4073836],[1.1590151,51.3869889],[1.0191822,51.3903886],[1.0228142,51.4798247],[0.8793493,51.4843484],[0.8829813,51.5566675],[1.0264462,51.5544092],[1.0373423,51.7493319],[1.2607117,51.7482076],[1.2661598,51.8279642],[1.3351682,51.8335756],[1.3478803,51.9199021],[1.4840812,51.9199021],[1.4986093,52.0038271],[1.6438902,52.0027092],[1.6656823,52.270221],[1.7310588,52.270221],[1.7528509,52.4465637],[1.8254914,52.4476705],[1.8345714,52.624408],[1.7690346,52.6291402],[1.7741711,52.717904],[1.6996925,52.721793],[1.706113,52.8103687],[1.559724,52.8165777],[1.5648605,52.9034116],[1.4184715,52.9103818],[1.4223238,52.9281894],[1.3439928,52.9289635],[1.3491293,53.0001194],[0.4515789,53.022589],[0.4497629,52.9351139],[0.3789384,52.9351139],[0.3716744,52.846365],[0.2227614,52.8496552],[0.2336575,52.9329248],[0.3062979,52.9351139],[0.308114,53.022589],[0.3807544,53.0236813],[0.3993708,53.2933729],[0.3248922,53.2987454],[0.3274604,53.3853782],[0.2504136,53.38691],[0.2581183,53.4748924],[0.1862079,53.4779494],[0.1913443,53.6548777],[0.1502527,53.6594436],[0.1528209,53.7666003],[0.0012954,53.7734308],[0.0025796,53.8424326],[-0.0282392,53.841675],[-0.0226575,53.9311501],[-0.1406983,53.9322193],[-0.1416063,54.0219323],[-0.1706625,54.0235326],[-0.1679384,54.0949482],[-0.0126694,54.0912206],[-0.0099454,54.1811226],[-0.1615824,54.1837795],[-0.1606744,54.2029038],[-0.2405789,54.2034349],[-0.2378549,54.2936234],[-0.3894919,54.2941533],[-0.3857497,54.3837321],[-0.461638,54.3856364],[-0.4571122,54.4939066],[-0.6105651,54.4965434],[-0.6096571,54.5676704],[-0.7667421,54.569776],[-0.7640181,54.5887213],[-0.9192871,54.5908258],[-0.9148116,54.6608348],[-1.1485204,54.6634343],[-1.1472363,54.7528316],[-1.2268514,54.7532021],[-1.2265398,54.8429879],[-1.2991803,54.8435107],[-1.2991803,54.9333391],[-1.3454886,54.9354258],[-1.3436726,55.0234878],[-1.3772688,55.0255698],[-1.3754528,55.1310877],[-1.4997441,55.1315727],[-1.4969272,55.2928323],[-1.5296721,55.2942946],[-1.5258198,55.6523803],[-1.7659492,55.6545537],[-1.7620968,55.7435626],[-1.9688392,55.7435626],[-1.9698023,55.8334505],[-2.0019051,55.8336308],[-2.0015841,55.9235526],[-2.1604851,55.9240613],[-2.1613931,55.9413549],[-2.3202942,55.9408463],[-2.3212022,56.0145126],[-2.5627317,56.0124824],[-2.5645477,56.1022207],[-2.9658863,56.0991822],[-2.9667943,56.1710304],[-2.4828272,56.1755797],[-2.4882752,56.2856078],[-2.5645477,56.2835918],[-2.5681798,56.3742075],[-2.7261728,56.3732019],[-2.7316208,56.4425301],[-2.6190281,56.4425301],[-2.6153961,56.5317671],[-2.453771,56.5347715],[-2.4534686,56.6420248],[-2.4062523,56.6440218],[-2.3953562,56.7297964],[-2.2936596,56.7337811],[-2.2972916,56.807423],[-2.1629067,56.8113995],[-2.1592747,56.9958425],[-1.9922016,57.0017771],[-2.0067297,57.2737477],[-1.9195612,57.2757112],[-1.9304572,57.3482876],[-1.8106005,57.3443682],[-1.7997044,57.4402728],[-1.6616875,57.4285429],[-1.6689516,57.5398256],[-1.7452241,57.5398256],[-1.7524881,57.6313302],[-1.8287606,57.6332746],[-1.8287606,57.7187255],[-3.1768526,57.7171219],[-3.1794208,57.734264],[-3.5134082,57.7292105],[-3.5129542,57.7112683],[-3.7635638,57.7076303],[-3.7598539,57.635713],[-3.8420372,57.6343382],[-3.8458895,57.6178365],[-3.9794374,57.6157733],[-3.9794374,57.686544],[-3.8150708,57.689976],[-3.817639,57.7968899],[-3.6853753,57.7989429],[-3.6892276,57.8891567],[-3.9383458,57.8877915],[-3.9421981,57.9750592],[-3.6943641,57.9784638],[-3.6969323,58.0695865],[-4.0372226,58.0641528],[-4.0346543,57.9730163],[-4.2003051,57.9702923],[-4.1832772,57.7012869],[-4.518752,57.6951111],[-4.5122925,57.6050682],[-4.6789116,57.6016628],[-4.666022,57.4218334],[-3.6677696,57.4394729],[-3.671282,57.5295384],[-3.3384979,57.5331943],[-3.3330498,57.4438859],[-2.8336466,57.4485275],[-2.8236396,56.9992706],[-2.3305398,57.0006693],[-2.3298977,56.9113932],[-2.6579889,56.9092901],[-2.6559637,56.8198406],[-2.8216747,56.8188467],[-2.8184967,56.7295397],[-3.1449248,56.7265508],[-3.1435628,56.6362749],[-3.4679089,56.6350265],[-3.474265,56.7238108],[-3.8011471,56.7188284],[-3.785711,56.4493026],[-3.946428,56.4457896],[-3.9428873,56.2659777],[-4.423146,56.2588459],[-4.4141572,56.0815506],[-4.8944159,56.0708008],[-4.8791072,55.8896994],[-5.1994158,55.8821374],[-5.1852906,55.7023791],[-5.0273445,55.7067203],[-5.0222081,55.6879046],[-4.897649,55.6907999],[-4.8880181,55.6002822],[-4.7339244,55.6046348],[-4.7275038,55.5342082],[-4.773732,55.5334815],[-4.7685955,55.4447227],[-4.8494947,55.4418092],[-4.8405059,55.3506535],[-4.8700405,55.3513836],[-4.8649041,55.2629462],[-4.9920314,55.2592875],[-4.9907473,55.1691779],[-5.0600894,55.1655105],[-5.0575212,55.0751884],[-5.2141831,55.0722477],[-5.1991766,54.8020337],[-5.0466316,54.8062205],[-5.0502636,54.7244996],[-4.9703591,54.7203043],[-4.9776232,54.6215905],[-4.796022,54.6342056],[-4.796022,54.7307917],[-4.8977186,54.7265971],[-4.9086147,54.8145928],[-4.8069181,54.8166856],[-4.8105501,54.7915648],[-4.6943253,54.7978465],[-4.6761652,54.7244996],[-4.5744686,54.7244996],[-4.5599405,54.6426135],[-4.3093309,54.6384098],[-4.3333262,54.8229889],[-4.2626999,54.8274274],[-4.2549952,54.7348587],[-3.8338058,54.7400481],[-3.836374,54.8141105],[-3.7118149,54.8133706],[-3.7143831,54.8318654],[-3.5346072,54.8355633],[-3.5271039,54.9066228],[-3.4808758,54.9084684],[-3.4776655,54.7457328],[-3.5874573,54.744621],[-3.5836049,54.6546166],[-3.7107322,54.6531308],[-3.6991752,54.4550407],[-3.5746161,54.4572801],[-3.5759002,54.3863042],[-3.539945,54.3855564],[-3.5386609,54.297224],[-3.46033,54.2957252],[-3.4590458,54.2079507],[-3.3807149,54.2102037],[-3.381999,54.1169788],[-3.302878,54.1160656],[-3.300154,54.0276224],[-3.1013007,54.0292224],[-3.093596,53.6062158],[-3.2065981,53.6016441],[-3.2091663,53.4917753],[-3.2451215,53.4887193],[-3.2348486,53.4045934],[-3.5276266,53.3999999],[-3.5343966,53.328481],[-3.6488053,53.3252272],[-3.6527308,53.3057716],[-3.7271873,53.3046865],[-3.7315003,53.3945257],[-3.9108315,53.3912769],[-3.9071995,53.3023804],[-3.9521457,53.3015665],[-3.9566724,53.3912183],[-4.1081979,53.3889209],[-4.1081979,53.4072967],[-4.2622916,53.4065312],[-4.2635757,53.4753707],[-4.638537,53.4677274],[-4.6346847,53.3812621],[-4.7091633,53.3774321],[-4.7001745,53.1954965],[-4.5499332,53.1962658],[-4.5435126,53.1092488],[-4.3919871,53.1100196],[-4.3855666,53.0236002],[-4.6115707,53.0205105],[-4.603866,52.9284932],[-4.7566756,52.9261709],[-4.7476868,52.8370555],[-4.8208813,52.8331768],[-4.8208813,52.7446476],[-4.3701572,52.7539749],[-4.3765778,52.8401583],[-4.2314728,52.8455875],[-4.2237682,52.7586379],[-4.1056297,52.7570836],[-4.1015192,52.6714874],[-4.1487355,52.6703862],[-4.1305754,52.4008596],[-4.1995838,52.3986435],[-4.2050319,52.3110195],[-4.3466808,52.303247],[-4.3484968,52.2365693],[-4.4901457,52.2332328],[-4.4883297,52.2098702],[-4.6572188,52.2098702],[-4.6590348,52.1385939],[-4.7788916,52.13525],[-4.7807076,52.1162967],[-4.9259885,52.1140663],[-4.9187245,52.0392855],[-5.2365265,52.0314653],[-5.2347105,51.9442339],[-5.3473032,51.9408755],[-5.3473032,51.9195995],[-5.4925842,51.9162392],[-5.4853201,51.8265386],[-5.1983903,51.8321501],[-5.1893102,51.7625177],[-5.335825,51.7589528],[-5.3281204,51.6686495],[-5.1836575,51.6730296],[-5.1836575,51.6539134],[-5.0674452,51.6578966],[-5.0603825,51.5677905],[-4.5974594,51.5809588],[-4.60388,51.6726314],[-4.345773,51.6726314],[-4.3355001,51.4962964],[-3.9528341,51.5106841],[-3.9425611,51.5905333],[-3.8809237,51.5953198],[-3.8706508,51.5074872],[-3.7679216,51.4978952],[-3.7550805,51.4242895],[-3.5855774,51.41468],[-3.5778727,51.3329177],[-3.0796364,51.3329177],[-3.0770682,51.2494018],[-3.7216935,51.2381477],[-3.7216935,51.2558315],[-3.8706508,51.2558315],[-3.8680825,51.2365398],[-4.2944084,51.2252825],[-4.289272,51.0496352],[-4.5692089,51.0431767],[-4.5624122,50.9497388],[-4.5905604,50.9520269],[-4.5896524,50.8627065],[-4.6296046,50.8592677],[-4.6226411,50.7691513],[-4.6952816,50.7680028],[-4.6934655,50.6967379],[-4.8342064,50.6938621],[-4.8296664,50.6046231],[-4.9676833,50.6000126],[-4.9685913,50.5821427],[-5.1084242,50.5786832],[-5.1029762,50.4892254],[-5.1311244,50.48807],[-5.1274923,50.4163798],[-5.2664172,50.4117509],[-5.2609692,50.3034214],[-5.5124868,50.2976214],[-5.5061308,50.2256428],[-5.6468717,50.2209953],[-5.6453263,50.2029809]],[[-5.1336607,55.2630226],[-5.1021999,55.2639372],[-5.0999527,55.2458239],[-5.1322161,55.2446343],[-5.1336607,55.2630226]],[[-5.6431878,55.5095745],[-5.4861028,55.5126594],[-5.4715747,55.3348829],[-5.6277517,55.3302345],[-5.6431878,55.5095745]],[[-4.7213517,51.2180246],[-4.5804201,51.2212417],[-4.5746416,51.1306736],[-4.7174993,51.1280545],[-4.7213517,51.2180246]],[[-5.1608796,55.4153626],[-5.0045387,55.4190069],[-5.0184798,55.6153521],[-5.1755648,55.6138137],[-5.1608796,55.4153626]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-25inch-hist","name":"NLS - OS 25-inch (Scotland), 1892-1905","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25_inch/scotland_1/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"polygon":[[[-5.2112173,54.8018593],[-5.0642752,54.8026508],[-5.0560354,54.6305176],[-4.3158316,54.6297227],[-4.3117117,54.7448258],[-3.8530325,54.7464112],[-3.8530325,54.8034424],[-3.5522818,54.8034424],[-3.5522818,54.8374644],[-3.468511,54.8406277],[-3.4657644,54.8983158],[-3.3847403,54.8991055],[-3.3888601,54.9559214],[-3.0920786,54.9539468],[-3.0392359,54.9923274],[-3.0212713,55.0493881],[-2.9591232,55.0463283],[-2.9202807,55.0666294],[-2.7857081,55.068652],[-2.7852225,55.0914426],[-2.7337562,55.0922761],[-2.737616,55.151204],[-2.7648395,55.1510672],[-2.7013114,55.1722505],[-2.6635459,55.2192808],[-2.6460364,55.2188891],[-2.629042,55.2233933],[-2.6317886,55.2287781],[-2.6235488,55.2446345],[-2.6197723,55.2454663],[-2.6099017,55.2454174],[-2.6099876,55.2486466],[-2.6408121,55.2590039],[-2.6247896,55.2615631],[-2.6045186,55.2823081],[-2.5693176,55.296132],[-2.5479542,55.3121617],[-2.5091116,55.3234891],[-2.4780376,55.3494471],[-2.4421083,55.3533118],[-2.4052079,55.3439256],[-2.3726772,55.3447539],[-2.3221819,55.3687665],[-2.3241241,55.3999337],[-2.2576062,55.425015],[-2.1985547,55.4273529],[-2.1484296,55.4717466],[-2.1944348,55.484199],[-2.2040479,55.529306],[-2.2960584,55.6379722],[-2.2177808,55.6379722],[-2.1059266,55.7452498],[-1.9716874,55.7462161],[-1.9697453,55.9190951],[-2.1201694,55.9207115],[-2.1242893,55.9776133],[-2.3440159,55.9783817],[-2.3440159,56.0390349],[-2.5046909,56.0413363],[-2.500571,56.1003588],[-2.8823459,56.0957629],[-2.8823459,56.1722898],[-2.4126804,56.1692316],[-2.4181736,56.2334017],[-2.5857151,56.2303484],[-2.5719822,56.3416356],[-2.7257908,56.3462022],[-2.7312839,56.4343808],[-2.6928318,56.4343808],[-2.6928318,56.4859769],[-2.5307834,56.4935587],[-2.5307834,56.570806],[-2.5302878,56.6047947],[-2.3732428,56.6044452],[-2.3684363,56.7398824],[-2.3292975,56.7398824],[-2.3292975,56.7888065],[-2.3145346,56.7891826],[-2.3148779,56.7967036],[-2.171369,56.7967036],[-2.1703979,56.9710595],[-2.0101725,56.9694716],[-2.0101725,57.0846832],[-2.0817687,57.085349],[-2.0488097,57.1259963],[-2.0409133,57.126369],[-2.0383434,57.2411129],[-1.878118,57.2421638],[-1.8771469,57.2978175],[-1.9868771,57.2983422],[-1.9082209,57.3560063],[-1.8752048,57.3560063],[-1.8761758,57.3769527],[-1.8120857,57.4120111],[-1.7120661,57.4120111],[-1.7034646,57.6441388],[-1.8666032,57.6451781],[-1.8646611,57.7033351],[-3.1204292,57.7064705],[-3.1218025,57.7504652],[-3.4445259,57.7526635],[-3.4472724,57.7138067],[-3.5145637,57.7094052],[-3.5118171,57.6939956],[-3.7645027,57.6917938],[-3.7672492,57.6344975],[-3.842378,57.6288312],[-3.8438346,57.5965825],[-3.9414265,57.5916386],[-3.9404554,57.6537782],[-3.8894746,57.6529989],[-3.8826772,57.7676408],[-3.7224517,57.766087],[-3.7195385,57.8819201],[-3.9146888,57.8853352],[-3.916062,57.9546243],[-3.745774,57.9538956],[-3.7471473,58.0688409],[-3.5837256,58.0695672],[-3.5837256,58.1116689],[-3.4560096,58.1138452],[-3.4544646,58.228503],[-3.4379851,58.2283222],[-3.4243233,58.2427725],[-3.412307,58.2438567],[-3.3735115,58.2695057],[-3.3063919,58.2862038],[-3.1229154,58.2859395],[-3.123602,58.3443661],[-2.9574338,58.3447264],[-2.951254,58.6422011],[-2.8812162,58.6429157],[-2.8851004,58.8112825],[-2.7180775,58.8142997],[-2.7161354,58.8715749],[-2.556881,58.8775984],[-2.5544533,58.9923453],[-2.5567617,59.0483775],[-2.391893,59.0485996],[-2.3918002,59.1106996],[-2.4733695,59.1106996],[-2.5591563,59.1783028],[-2.5630406,59.2210646],[-2.3921334,59.224046],[-2.3911409,59.2740075],[-2.3639512,59.2745036],[-2.3658933,59.285417],[-2.3911409,59.284921],[-2.3911409,59.3379505],[-2.2221759,59.3381981],[-2.2233897,59.395965],[-2.3758467,59.396583],[-2.3899271,59.4026383],[-2.4008516,59.3962122],[-2.5637882,59.3952604],[-2.5637882,59.3385811],[-2.7320164,59.3375306],[-2.7333896,59.3952604],[-3.0726511,59.3931174],[-3.0703404,59.3354759],[-3.0753186,59.3355634],[-3.0749753,59.3292593],[-3.0698254,59.3289091],[-3.069801,59.2196159],[-3.2363384,59.2166341],[-3.2336751,59.1606496],[-3.4032766,59.1588895],[-3.394086,58.9279316],[-3.5664497,58.9259268],[-3.5611089,58.8679885],[-3.392508,58.8699339],[-3.3894734,58.8698711],[-3.3891093,58.8684905],[-3.3912942,58.868616],[-3.3884161,58.7543084],[-3.2238208,58.7555677],[-3.2189655,58.691289],[-3.4634113,58.6905753],[-3.4551716,58.6341518],[-3.787508,58.6341518],[-3.7861347,58.5769211],[-3.9028645,58.5733411],[-3.9028645,58.6477304],[-4.0690327,58.6491594],[-4.0690327,58.5912376],[-4.7364521,58.5933845],[-4.7364521,58.6505884],[-5.0715351,58.6520173],[-5.0654779,58.5325854],[-5.2332047,58.5316087],[-5.2283494,58.4719947],[-5.2424298,58.4719947],[-5.2366034,58.4089731],[-5.2283494,58.4094818],[-5.2210664,58.3005859],[-5.5657939,58.2959933],[-5.5580254,58.2372573],[-5.4146722,58.2401326],[-5.4141866,58.2267768],[-5.3885749,58.2272242],[-5.382714,58.1198615],[-5.51043,58.1191362],[-5.5114011,58.006214],[-5.6745397,58.0041559],[-5.6716266,57.9449366],[-5.6716266,57.8887166],[-5.8347652,57.8856193],[-5.8277052,57.5988958],[-6.0384259,57.5986357],[-6.0389115,57.6459559],[-6.1981658,57.6456961],[-6.2076123,57.7600132],[-6.537067,57.7544033],[-6.5312406,57.6402392],[-6.7002056,57.6360809],[-6.6807844,57.5236293],[-6.8516915,57.5152857],[-6.8361545,57.3385811],[-6.6730158,57.3438213],[-6.674958,57.2850883],[-6.5098772,57.2850883],[-6.4982244,57.1757637],[-6.3506228,57.1820797],[-6.3312015,57.1251969],[-6.1797156,57.1230884],[-6.1719471,57.0682265],[-6.4593819,57.059779],[-6.4564687,57.1093806],[-6.6671895,57.1062165],[-6.6730158,57.002708],[-6.5021087,57.0048233],[-6.4836097,56.8917522],[-6.3266104,56.8894062],[-6.3156645,56.7799312],[-6.2146739,56.775675],[-6.2146739,56.7234965],[-6.6866107,56.7224309],[-6.6769001,56.6114413],[-6.8419809,56.607166],[-6.8400387,56.5483307],[-7.1546633,56.5461895],[-7.1488369,56.4872592],[-6.9915246,56.490476],[-6.9876404,56.4325329],[-6.6827265,56.4314591],[-6.6769001,56.5472601],[-6.5292985,56.5504717],[-6.5234721,56.4379018],[-6.3661598,56.4368281],[-6.3642177,56.3766524],[-6.5273563,56.3712749],[-6.5171745,56.2428427],[-6.4869621,56.247421],[-6.4869621,56.1893882],[-6.3001945,56.1985572],[-6.3029411,56.2581017],[-5.9019401,56.256576],[-5.8964469,56.0960466],[-6.0282829,56.0883855],[-6.0392692,56.1557502],[-6.3853385,56.1542205],[-6.3606193,55.96099],[-6.2123039,55.9640647],[-6.2047508,55.9202269],[-6.5185478,55.9129158],[-6.5061881,55.7501763],[-6.6764762,55.7409005],[-6.6599967,55.6263176],[-6.3551261,55.6232161],[-6.3578727,55.5689002],[-6.0392692,55.5720059],[-6.0310294,55.6247669],[-5.7398917,55.6309694],[-5.7371452,55.4569279],[-5.8964469,55.4600426],[-5.8964469,55.2789864],[-5.4350211,55.2821151],[-5.4405143,55.4506979],[-5.2867057,55.4569279],[-5.3086784,55.4070602],[-4.9735954,55.4008223],[-4.9845817,55.2038242],[-5.1493766,55.2038242],[-5.1411369,55.037337],[-5.2152946,55.0341891],[-5.2112173,54.8018593]],[[-2.1646559,60.1622059],[-1.9930299,60.1609801],[-1.9946862,60.1035151],[-2.1663122,60.104743],[-2.1646559,60.1622059]],[[-1.5360658,59.8570831],[-1.3653566,59.8559841],[-1.366847,59.7975565],[-1.190628,59.7964199],[-1.1862046,59.9695391],[-1.0078652,59.9683948],[-1.0041233,60.114145],[-0.8360832,60.1130715],[-0.834574,60.1716772],[-1.0074262,60.1727795],[-1.0052165,60.2583924],[-0.8299659,60.2572778],[-0.826979,60.3726551],[-0.6507514,60.3715381],[-0.6477198,60.4882292],[-0.9984896,60.4904445],[-0.9970279,60.546555],[-0.6425288,60.5443201],[-0.6394896,60.6606792],[-0.8148133,60.6617806],[-0.8132987,60.7196112],[-0.6383298,60.7185141],[-0.635467,60.8275393],[-0.797568,60.8285523],[-0.9941426,60.8297807],[-0.9954966,60.7782667],[-1.1670282,60.7793403],[-1.1700357,60.6646181],[-1.5222599,60.6668304],[-1.5237866,60.6084426],[-1.6975673,60.609536],[-1.7021271,60.4345249],[-1.5260578,60.4334111],[-1.5275203,60.3770719],[-1.8751127,60.3792746],[-1.8781372,60.2624647],[-1.7019645,60.2613443],[-1.7049134,60.1470532],[-1.528659,60.1459283],[-1.5360658,59.8570831]],[[-0.9847667,60.8943762],[-0.9860347,60.8361105],[-0.8078362,60.8351904],[-0.8065683,60.8934578],[-0.9847667,60.8943762]],[[-7.7696901,56.8788231],[-7.7614504,56.7608274],[-7.6009049,56.7641903],[-7.5972473,56.819332],[-7.4479894,56.8203948],[-7.4489319,56.8794098],[-7.2841369,56.8794098],[-7.2813904,57.0471152],[-7.1303283,57.0515969],[-7.1330749,57.511801],[-6.96828,57.5147514],[-6.9765198,57.6854668],[-6.8062317,57.6913392],[-6.8089782,57.8041985],[-6.6496765,57.8071252],[-6.6441833,57.8612267],[-6.3200866,57.8626878],[-6.3200866,58.1551617],[-6.1607849,58.1522633],[-6.1552917,58.20874],[-5.9850036,58.2101869],[-5.9904968,58.2680163],[-6.1497986,58.2665717],[-6.1415588,58.5557514],[-6.3173401,58.5557514],[-6.3091003,58.4983923],[-6.4876282,58.4955218],[-6.4876282,58.4423768],[-6.6606628,58.4395018],[-6.6469299,58.3819525],[-6.8117248,58.3805125],[-6.8117248,58.3286357],[-6.9792663,58.3286357],[-6.9710266,58.2694608],[-7.1413147,58.2680163],[-7.1403816,58.0358742],[-7.3020636,58.0351031],[-7.3030347,57.9774797],[-7.1379539,57.9777372],[-7.1413526,57.9202792],[-7.1398961,57.8640206],[-7.3020636,57.862471],[-7.298484,57.7442293],[-7.4509193,57.7456951],[-7.4550392,57.6899522],[-7.6186131,57.6906048],[-7.6198341,57.7456951],[-7.7901222,57.7442293],[-7.7873756,57.6855477],[-7.6222332,57.6853817],[-7.6173779,57.5712602],[-7.788285,57.5709998],[-7.7892561,57.512109],[-7.7038025,57.5115874],[-7.6999183,57.4546902],[-7.5367796,57.4552126],[-7.5348375,57.5126306],[-7.4581235,57.5131521],[-7.4552103,57.2824165],[-7.6115515,57.2845158],[-7.6144647,57.2272651],[-7.451326,57.2256881],[-7.451326,57.1103873],[-7.6164068,57.1088053],[-7.603783,56.8792358],[-7.7696901,56.8788231]],[[-1.7106618,59.5626284],[-1.5417509,59.562215],[-1.5423082,59.5037224],[-1.7112191,59.5041365],[-1.7106618,59.5626284]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-6inch-Scotland-hist","name":"NLS - OS 6-inch Scotland 1842-82","type":"tms","template":"http://geo.nls.uk/maps/os/six_inch/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-5.2112173,54.8018593],[-5.0642752,54.8026508],[-5.0560354,54.6305176],[-4.3158316,54.6297227],[-4.3117117,54.7448258],[-3.8530325,54.7464112],[-3.8530325,54.8034424],[-3.5522818,54.8034424],[-3.5522818,54.8374644],[-3.468511,54.8406277],[-3.4657644,54.8983158],[-3.3847403,54.8991055],[-3.3888601,54.9559214],[-3.0920786,54.9539468],[-3.0392359,54.9923274],[-3.0212713,55.0493881],[-2.9591232,55.0463283],[-2.9202807,55.0666294],[-2.7857081,55.068652],[-2.7852225,55.0914426],[-2.7337562,55.0922761],[-2.737616,55.151204],[-2.7648395,55.1510672],[-2.7013114,55.1722505],[-2.6635459,55.2192808],[-2.6460364,55.2188891],[-2.629042,55.2233933],[-2.6317886,55.2287781],[-2.6235488,55.2446345],[-2.6197723,55.2454663],[-2.6099017,55.2454174],[-2.6099876,55.2486466],[-2.6408121,55.2590039],[-2.6247896,55.2615631],[-2.6045186,55.2823081],[-2.5693176,55.296132],[-2.5479542,55.3121617],[-2.5091116,55.3234891],[-2.4780376,55.3494471],[-2.4421083,55.3533118],[-2.4052079,55.3439256],[-2.3726772,55.3447539],[-2.3221819,55.3687665],[-2.3241241,55.3999337],[-2.2576062,55.425015],[-2.1985547,55.4273529],[-2.1484296,55.4717466],[-2.1944348,55.484199],[-2.2040479,55.529306],[-2.2960584,55.6379722],[-2.2177808,55.6379722],[-2.1059266,55.7452498],[-1.9716874,55.7462161],[-1.9697453,55.9190951],[-2.1201694,55.9207115],[-2.1242893,55.9776133],[-2.3440159,55.9783817],[-2.3440159,56.0390349],[-2.5046909,56.0413363],[-2.500571,56.1003588],[-2.8823459,56.0957629],[-2.8823459,56.1722898],[-2.4126804,56.1692316],[-2.4181736,56.2334017],[-2.5857151,56.2303484],[-2.5719822,56.3416356],[-2.7257908,56.3462022],[-2.7312839,56.4343808],[-2.6928318,56.4343808],[-2.6928318,56.4859769],[-2.5307834,56.4935587],[-2.5307834,56.570806],[-2.5302878,56.6047947],[-2.3732428,56.6044452],[-2.3684363,56.7398824],[-2.3292975,56.7398824],[-2.3292975,56.7888065],[-2.3145346,56.7891826],[-2.3148779,56.7967036],[-2.171369,56.7967036],[-2.1703979,56.9710595],[-2.0101725,56.9694716],[-2.0101725,57.0846832],[-2.0817687,57.085349],[-2.0488097,57.1259963],[-2.0409133,57.126369],[-2.0383434,57.2411129],[-1.878118,57.2421638],[-1.8771469,57.2978175],[-1.9868771,57.2983422],[-1.9082209,57.3560063],[-1.8752048,57.3560063],[-1.8761758,57.3769527],[-1.8120857,57.4120111],[-1.7120661,57.4120111],[-1.7034646,57.6441388],[-1.8666032,57.6451781],[-1.8646611,57.7033351],[-3.1204292,57.7064705],[-3.1218025,57.7504652],[-3.4445259,57.7526635],[-3.4472724,57.7138067],[-3.5145637,57.7094052],[-3.5118171,57.6939956],[-3.7645027,57.6917938],[-3.7672492,57.6344975],[-3.842378,57.6288312],[-3.8438346,57.5965825],[-3.9414265,57.5916386],[-3.9404554,57.6537782],[-3.8894746,57.6529989],[-3.8826772,57.7676408],[-3.7224517,57.766087],[-3.7195385,57.8819201],[-3.9146888,57.8853352],[-3.916062,57.9546243],[-3.745774,57.9538956],[-3.7471473,58.0688409],[-3.5837256,58.0695672],[-3.5837256,58.1116689],[-3.4560096,58.1138452],[-3.4544646,58.228503],[-3.4379851,58.2283222],[-3.4243233,58.2427725],[-3.412307,58.2438567],[-3.3735115,58.2695057],[-3.3063919,58.2862038],[-3.1229154,58.2859395],[-3.123602,58.3443661],[-2.9574338,58.3447264],[-2.951254,58.6422011],[-2.8812162,58.6429157],[-2.8851004,58.8112825],[-2.7180775,58.8142997],[-2.7161354,58.8715749],[-2.556881,58.8775984],[-2.5544533,58.9923453],[-2.5567617,59.0483775],[-2.391893,59.0485996],[-2.3918002,59.1106996],[-2.4733695,59.1106996],[-2.5591563,59.1783028],[-2.5630406,59.2210646],[-2.3921334,59.224046],[-2.3911409,59.2740075],[-2.3639512,59.2745036],[-2.3658933,59.285417],[-2.3911409,59.284921],[-2.3911409,59.3379505],[-2.2221759,59.3381981],[-2.2233897,59.395965],[-2.3758467,59.396583],[-2.3899271,59.4026383],[-2.4008516,59.3962122],[-2.5637882,59.3952604],[-2.5637882,59.3385811],[-2.7320164,59.3375306],[-2.7333896,59.3952604],[-3.0726511,59.3931174],[-3.0703404,59.3354759],[-3.0753186,59.3355634],[-3.0749753,59.3292593],[-3.0698254,59.3289091],[-3.069801,59.2196159],[-3.2363384,59.2166341],[-3.2336751,59.1606496],[-3.4032766,59.1588895],[-3.394086,58.9279316],[-3.5664497,58.9259268],[-3.5611089,58.8679885],[-3.392508,58.8699339],[-3.3894734,58.8698711],[-3.3891093,58.8684905],[-3.3912942,58.868616],[-3.3884161,58.7543084],[-3.2238208,58.7555677],[-3.2189655,58.691289],[-3.4634113,58.6905753],[-3.4551716,58.6341518],[-3.787508,58.6341518],[-3.7861347,58.5769211],[-3.9028645,58.5733411],[-3.9028645,58.6477304],[-4.0690327,58.6491594],[-4.0690327,58.5912376],[-4.7364521,58.5933845],[-4.7364521,58.6505884],[-5.0715351,58.6520173],[-5.0654779,58.5325854],[-5.2332047,58.5316087],[-5.2283494,58.4719947],[-5.2424298,58.4719947],[-5.2366034,58.4089731],[-5.2283494,58.4094818],[-5.2210664,58.3005859],[-5.5657939,58.2959933],[-5.5580254,58.2372573],[-5.4146722,58.2401326],[-5.4141866,58.2267768],[-5.3885749,58.2272242],[-5.382714,58.1198615],[-5.51043,58.1191362],[-5.5114011,58.006214],[-5.6745397,58.0041559],[-5.6716266,57.9449366],[-5.6716266,57.8887166],[-5.8347652,57.8856193],[-5.8277052,57.5988958],[-6.0384259,57.5986357],[-6.0389115,57.6459559],[-6.1981658,57.6456961],[-6.2076123,57.7600132],[-6.537067,57.7544033],[-6.5312406,57.6402392],[-6.7002056,57.6360809],[-6.6807844,57.5236293],[-6.8516915,57.5152857],[-6.8361545,57.3385811],[-6.6730158,57.3438213],[-6.674958,57.2850883],[-6.5098772,57.2850883],[-6.4982244,57.1757637],[-6.3506228,57.1820797],[-6.3312015,57.1251969],[-6.1797156,57.1230884],[-6.1719471,57.0682265],[-6.4593819,57.059779],[-6.4564687,57.1093806],[-6.6671895,57.1062165],[-6.6730158,57.002708],[-6.5021087,57.0048233],[-6.4836097,56.8917522],[-6.3266104,56.8894062],[-6.3156645,56.7799312],[-6.2146739,56.775675],[-6.2146739,56.7234965],[-6.6866107,56.7224309],[-6.6769001,56.6114413],[-6.8419809,56.607166],[-6.8400387,56.5483307],[-7.1546633,56.5461895],[-7.1488369,56.4872592],[-6.9915246,56.490476],[-6.9876404,56.4325329],[-6.6827265,56.4314591],[-6.6769001,56.5472601],[-6.5292985,56.5504717],[-6.5234721,56.4379018],[-6.3661598,56.4368281],[-6.3642177,56.3766524],[-6.5273563,56.3712749],[-6.5171745,56.2428427],[-6.4869621,56.247421],[-6.4869621,56.1893882],[-6.3001945,56.1985572],[-6.3029411,56.2581017],[-5.9019401,56.256576],[-5.8964469,56.0960466],[-6.0282829,56.0883855],[-6.0392692,56.1557502],[-6.3853385,56.1542205],[-6.3606193,55.96099],[-6.2123039,55.9640647],[-6.2047508,55.9202269],[-6.5185478,55.9129158],[-6.5061881,55.7501763],[-6.6764762,55.7409005],[-6.6599967,55.6263176],[-6.3551261,55.6232161],[-6.3578727,55.5689002],[-6.0392692,55.5720059],[-6.0310294,55.6247669],[-5.7398917,55.6309694],[-5.7371452,55.4569279],[-5.8964469,55.4600426],[-5.8964469,55.2789864],[-5.4350211,55.2821151],[-5.4405143,55.4506979],[-5.2867057,55.4569279],[-5.3086784,55.4070602],[-4.9735954,55.4008223],[-4.9845817,55.2038242],[-5.1493766,55.2038242],[-5.1411369,55.037337],[-5.2152946,55.0341891],[-5.2112173,54.8018593]],[[-2.1646559,60.1622059],[-1.9930299,60.1609801],[-1.9946862,60.1035151],[-2.1663122,60.104743],[-2.1646559,60.1622059]],[[-1.5360658,59.8570831],[-1.3653566,59.8559841],[-1.366847,59.7975565],[-1.190628,59.7964199],[-1.1862046,59.9695391],[-1.0078652,59.9683948],[-1.0041233,60.114145],[-0.8360832,60.1130715],[-0.834574,60.1716772],[-1.0074262,60.1727795],[-1.0052165,60.2583924],[-0.8299659,60.2572778],[-0.826979,60.3726551],[-0.6507514,60.3715381],[-0.6477198,60.4882292],[-0.9984896,60.4904445],[-0.9970279,60.546555],[-0.6425288,60.5443201],[-0.6394896,60.6606792],[-0.8148133,60.6617806],[-0.8132987,60.7196112],[-0.6383298,60.7185141],[-0.635467,60.8275393],[-0.797568,60.8285523],[-0.9941426,60.8297807],[-0.9954966,60.7782667],[-1.1670282,60.7793403],[-1.1700357,60.6646181],[-1.5222599,60.6668304],[-1.5237866,60.6084426],[-1.6975673,60.609536],[-1.7021271,60.4345249],[-1.5260578,60.4334111],[-1.5275203,60.3770719],[-1.8751127,60.3792746],[-1.8781372,60.2624647],[-1.7019645,60.2613443],[-1.7049134,60.1470532],[-1.528659,60.1459283],[-1.5360658,59.8570831]],[[-0.9847667,60.8943762],[-0.9860347,60.8361105],[-0.8078362,60.8351904],[-0.8065683,60.8934578],[-0.9847667,60.8943762]],[[-7.7696901,56.8788231],[-7.7614504,56.7608274],[-7.6009049,56.7641903],[-7.5972473,56.819332],[-7.4479894,56.8203948],[-7.4489319,56.8794098],[-7.2841369,56.8794098],[-7.2813904,57.0471152],[-7.1303283,57.0515969],[-7.1330749,57.511801],[-6.96828,57.5147514],[-6.9765198,57.6854668],[-6.8062317,57.6913392],[-6.8089782,57.8041985],[-6.6496765,57.8071252],[-6.6441833,57.8612267],[-6.3200866,57.8626878],[-6.3200866,58.1551617],[-6.1607849,58.1522633],[-6.1552917,58.20874],[-5.9850036,58.2101869],[-5.9904968,58.2680163],[-6.1497986,58.2665717],[-6.1415588,58.5557514],[-6.3173401,58.5557514],[-6.3091003,58.4983923],[-6.4876282,58.4955218],[-6.4876282,58.4423768],[-6.6606628,58.4395018],[-6.6469299,58.3819525],[-6.8117248,58.3805125],[-6.8117248,58.3286357],[-6.9792663,58.3286357],[-6.9710266,58.2694608],[-7.1413147,58.2680163],[-7.1403816,58.0358742],[-7.3020636,58.0351031],[-7.3030347,57.9774797],[-7.1379539,57.9777372],[-7.1413526,57.9202792],[-7.1398961,57.8640206],[-7.3020636,57.862471],[-7.298484,57.7442293],[-7.4509193,57.7456951],[-7.4550392,57.6899522],[-7.6186131,57.6906048],[-7.6198341,57.7456951],[-7.7901222,57.7442293],[-7.7873756,57.6855477],[-7.6222332,57.6853817],[-7.6173779,57.5712602],[-7.788285,57.5709998],[-7.7892561,57.512109],[-7.7038025,57.5115874],[-7.6999183,57.4546902],[-7.5367796,57.4552126],[-7.5348375,57.5126306],[-7.4581235,57.5131521],[-7.4552103,57.2824165],[-7.6115515,57.2845158],[-7.6144647,57.2272651],[-7.451326,57.2256881],[-7.451326,57.1103873],[-7.6164068,57.1088053],[-7.603783,56.8792358],[-7.7696901,56.8788231]],[[-1.7106618,59.5626284],[-1.5417509,59.562215],[-1.5423082,59.5037224],[-1.7112191,59.5041365],[-1.7106618,59.5626284]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLSC-EMAP5","name":"NLSC General Map with Contour line","type":"tms","template":"http://maps.nlsc.gov.tw/S_Maps/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=EMAP5_OPENDATA&STYLE=_null&TILEMATRIXSET=EPSG:3857&TILEMATRIX=EPSG:3857:{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image/png","description":"The emap from Taiwan National Land Surveying and Mapping Center","scaleExtent":[0,15],"polygon":[[[120.4570579,26.3970586],[120.44256,26.3708009],[120.44713,26.3531513],[120.4673009,26.3405831],[120.4978723,26.3340866],[120.5141036,26.3401594],[120.5341168,26.3641649],[120.5297045,26.3842128],[120.4956661,26.4015754],[120.4570579,26.3970586]],[[119.9007221,25.9858609],[119.8960071,25.9648902],[119.9131301,25.9470399],[119.9503542,25.9278478],[119.9905563,25.9260623],[120.0198392,25.9363284],[120.0277804,25.9557423],[120.0275322,25.9845224],[119.9989937,26.0010288],[119.9404278,26.0028131],[119.9007221,25.9858609]],[[122.089,24.5485],[121.709,23.4541],[121.717,22.698],[121.818,21.95],[121.803,21.8735],[121.759,21.8087],[121.694,21.7653],[120.861,21.5631],[120.815,21.5576],[120.739,21.5728],[120.661,21.6296],[120.202,22.1809],[119.27,23.0542],[119.153,23.2049],[119.128,23.2485],[119.103,23.4],[119.118,23.4765],[119.137,23.512],[119.361,23.8885],[119.406,23.9407],[120.968,25.2284],[121.408,25.4687],[121.989,25.8147],[122.065,25.8299],[122.141,25.8147],[122.216,25.7663],[122.26,25.7015],[122.297,25.48],[122.196,24.9696],[122.089,24.5485]],[[116.6855033,20.8547596],[116.6309071,20.8149565],[116.5941695,20.7600846],[116.5797214,20.6967501],[116.5893056,20.6325865],[116.621766,20.5753367],[116.6731874,20.5319171],[116.7373678,20.5075783],[116.8065659,20.5052653],[116.8724354,20.5252581],[116.9270316,20.5651373],[116.9637692,20.6200797],[116.9782173,20.6834462],[116.9686331,20.7475883],[116.9361727,20.8047732],[116.8847512,20.8481147],[116.8205709,20.872399],[116.7513728,20.8747063],[116.6855033,20.8547596]],[[118.2261504,24.4563345],[118.2936439,24.4538527],[118.2851467,24.4751026],[118.3097372,24.4916821],[118.3767709,24.4729348],[118.4100947,24.5332285],[118.4479031,24.5284069],[118.4746394,24.4599272],[118.512992,24.4315479],[118.5065839,24.4202318],[118.4811625,24.4332439],[118.4610567,24.4089192],[118.426145,24.3970385],[118.3970055,24.4284184],[118.3765564,24.4258395],[118.3397565,24.3814628],[118.3031926,24.3705764],[118.2574234,24.4139213],[118.1381276,24.3724838],[118.1617342,24.4022433],[118.2094226,24.4139604],[118.1895784,24.4352201],[118.2176338,24.430205],[118.2261504,24.4563345]],[[120.2234496,26.30045],[120.2550843,26.3100412],[120.269888,26.3368716],[120.2591889,26.3652192],[120.2292544,26.3784823],[120.1976197,26.3688968],[120.182816,26.3420738],[120.1935151,26.3137205],[120.2234496,26.30045]],[[119.4374461,25.0047541],[119.4342024,24.9886249],[119.4541901,24.9722553],[119.4827444,24.9718376],[119.4898402,24.9937882],[119.4715877,25.0069239],[119.4374461,25.0047541]],[[119.8869914,26.180381],[119.893227,26.1203128],[119.9285109,26.1080224],[119.9779388,26.1223611],[120.0366775,26.151728],[120.1098054,26.2134921],[120.119269,26.2713663],[120.0629175,26.3172592],[119.9923706,26.3164881],[119.9467732,26.2898799],[119.9020362,26.2439761],[119.8869914,26.180381]]],"terms_url":"http://maps.nlsc.gov.tw/","terms_text":"NLSC EMAP 2015"},{"id":"MAPNIK","name":"OpenStreetMap (Standard)","type":"tms","template":"https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png","description":"The default OpenStreetMap layer.","scaleExtent":[0,19],"terms_url":"https://openstreetmap.org/","terms_text":"© OpenStreetMap contributors, CC-BY-SA","default":true},{"id":"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":"http://openstreetmap.hu/","terms_text":"OpenStreetMap.hu"},{"id":"osm-gps","name":"OpenStreetMap GPS traces","type":"tms","template":"http://{switch:a,b,c}.gps-tile.openstreetmap.org/lines/{zoom}/{x}/{y}.png","description":"Public GPS traces uploaded to OpenStreetMap.","scaleExtent":[0,20],"terms_url":"http://www.openstreetmap.org/copyright","terms_text":"© OpenStreetMap contributors","terms_html":"<span style='display: inline-block; padding: 0 8px; background-color: rgba(0,0,0,0.5);'><span style='color: #eee;'>GPS Direction:</span> <span style='font-size: 15px; padding-left: 2px; font-weight: bold;'> <span style='color: #0ee;'>←</span> <span style='color: #96f;'>↓</span> <span style='color: #6e0;'>↑</span> <span style='color: #f63;'>→</span> </span></span> © <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap contributors</a>.","overlay":true},{"id":"lu.geoportail.opendata.ortho2010","name":"Ortho 2010 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2010/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"lu.geoportail.opendata.ortho2013","name":"Ortho 2013 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2013/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"lu.geoportail.opendata.ortho2016","name":"Ortho 2016 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2016/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie","best":true},{"id":"OS-historic-25k-OSM_Limited","name":"OS 1:25k historic (OSM)","type":"tms","template":"http://ooc.openstreetmap.org/os1/{zoom}/{x}/{y}.jpg","scaleExtent":[6,17],"polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]]},{"id":"OS-New_Popular_Edition-historic","name":"OS New Popular Edition historic","type":"tms","template":"http://ooc.openstreetmap.org/npe/{zoom}/{x}/{y}.png","polygon":[[[-5.8,49.8],[-5.8,55.8],[1.9,55.8],[1.9,49.8],[-5.8,49.8]]]},{"id":"OS-OpenData_Locator","name":"OS OpenData Locator","type":"tms","template":"http://tiles.itoworld.com/os_locator/{zoom}/{x}/{y}.png","polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"overlay":true},{"id":"OS-OpenData_StreetView","name":"OS OpenData StreetView","type":"tms","template":"http://os.openstreetmap.org/sv/{zoom}/{x}/{y}.png","scaleExtent":[1,18],"polygon":[[[-5.8292886,50.0229734],[-5.8292886,50.254819],[-5.373356,50.254819],[-5.373356,50.3530588],[-5.1756021,50.3530588],[-5.1756021,50.5925406],[-4.9970743,50.5925406],[-4.9970743,50.6935617],[-4.7965738,50.6935617],[-4.7965738,50.7822112],[-4.6949503,50.7822112],[-4.6949503,50.9607371],[-4.6043131,50.9607371],[-4.6043131,51.0692066],[-4.3792215,51.0692066],[-4.3792215,51.2521782],[-3.9039346,51.2521782],[-3.9039346,51.2916998],[-3.7171671,51.2916998],[-3.7171671,51.2453014],[-3.1486246,51.2453014],[-3.1486246,51.362067],[-3.7446329,51.362067],[-3.7446329,51.4340386],[-3.8297769,51.4340386],[-3.8297769,51.5298246],[-4.0852091,51.5298246],[-4.0852091,51.4939284],[-4.3792215,51.4939284],[-4.3792215,51.5427168],[-5.1444195,51.5427168],[-5.1444195,51.6296003],[-5.7387103,51.6296003],[-5.7387103,51.774037],[-5.5095393,51.774037],[-5.5095393,51.9802596],[-5.198799,51.9802596],[-5.198799,52.0973358],[-4.8880588,52.0973358],[-4.8880588,52.1831557],[-4.4957492,52.1831557],[-4.4957492,52.2925739],[-4.3015365,52.2925739],[-4.3015365,52.3685318],[-4.1811246,52.3685318],[-4.1811246,52.7933685],[-4.4413696,52.7933685],[-4.4413696,52.7369614],[-4.8569847,52.7369614],[-4.8569847,52.9317255],[-4.7288044,52.9317255],[-4.7288044,53.5038599],[-4.1578191,53.5038599],[-4.1578191,53.4113498],[-3.3110518,53.4113498],[-3.3110518,53.5038599],[-3.2333667,53.5038599],[-3.2333667,54.0159169],[-3.3926211,54.0159169],[-3.3926211,54.1980953],[-3.559644,54.1980953],[-3.559644,54.433732],[-3.7188984,54.433732],[-3.7188984,54.721897],[-4.3015365,54.721897],[-4.3015365,54.6140739],[-5.0473132,54.6140739],[-5.0473132,54.7532915],[-5.2298731,54.7532915],[-5.2298731,55.2190799],[-5.6532567,55.2190799],[-5.6532567,55.250088],[-5.8979647,55.250088],[-5.8979647,55.4822462],[-6.5933212,55.4822462],[-6.5933212,56.3013441],[-7.1727691,56.3013441],[-7.1727691,56.5601822],[-6.8171722,56.5601822],[-6.8171722,56.6991713],[-6.5315276,56.6991713],[-6.5315276,56.9066964],[-6.811679,56.9066964],[-6.811679,57.3716613],[-6.8721038,57.3716613],[-6.8721038,57.5518893],[-7.0973235,57.5518893],[-7.0973235,57.2411085],[-7.1742278,57.2411085],[-7.1742278,56.9066964],[-7.3719817,56.9066964],[-7.3719817,56.8075885],[-7.5202972,56.8075885],[-7.5202972,56.7142479],[-7.8306806,56.7142479],[-7.8306806,56.8994605],[-7.6494061,56.8994605],[-7.6494061,57.4739617],[-7.8306806,57.4739617],[-7.8306806,57.7915584],[-7.4736249,57.7915584],[-7.4736249,58.086063],[-7.1879804,58.086063],[-7.1879804,58.367197],[-6.8034589,58.367197],[-6.8034589,58.4155786],[-6.638664,58.4155786],[-6.638664,58.4673277],[-6.5178143,58.4673277],[-6.5178143,58.5625632],[-6.0536224,58.5625632],[-6.0536224,58.1568843],[-6.1470062,58.1568843],[-6.1470062,58.1105865],[-6.2799798,58.1105865],[-6.2799798,57.7122664],[-6.1591302,57.7122664],[-6.1591302,57.6667563],[-5.9339104,57.6667563],[-5.9339104,57.8892524],[-5.80643,57.8892524],[-5.80643,57.9621767],[-5.6141692,57.9621767],[-5.6141692,58.0911236],[-5.490819,58.0911236],[-5.490819,58.3733281],[-5.3199118,58.3733281],[-5.3199118,58.75015],[-3.5719977,58.75015],[-3.5719977,59.2091788],[-3.1944501,59.2091788],[-3.1944501,59.4759216],[-2.243583,59.4759216],[-2.243583,59.1388749],[-2.4611012,59.1388749],[-2.4611012,58.8185938],[-2.7407675,58.8185938],[-2.7407675,58.5804743],[-2.9116746,58.5804743],[-2.9116746,58.1157523],[-3.4865441,58.1157523],[-3.4865441,57.740386],[-1.7153245,57.740386],[-1.7153245,57.2225558],[-1.9794538,57.2225558],[-1.9794538,56.8760742],[-2.1658979,56.8760742],[-2.1658979,56.6333186],[-2.3601106,56.6333186],[-2.3601106,56.0477521],[-1.9794538,56.0477521],[-1.9794538,55.8650949],[-1.4745008,55.8650949],[-1.4745008,55.2499926],[-1.3221997,55.2499926],[-1.3221997,54.8221737],[-1.0550014,54.8221737],[-1.0550014,54.6746628],[-0.6618765,54.6746628],[-0.6618765,54.5527463],[-0.3247617,54.5527463],[-0.3247617,54.2865195],[0.0092841,54.2865195],[0.0092841,53.7938518],[0.2081962,53.7938518],[0.2081962,53.5217726],[0.4163548,53.5217726],[0.4163548,53.0298851],[1.4273388,53.0298851],[1.4273388,52.92021],[1.8333912,52.92021],[1.8333912,52.042488],[1.5235504,52.042488],[1.5235504,51.8261335],[1.2697049,51.8261335],[1.2697049,51.6967453],[1.116651,51.6967453],[1.116651,51.440346],[1.5235504,51.440346],[1.5235504,51.3331831],[1.4507565,51.3331831],[1.4507565,51.0207553],[1.0699883,51.0207553],[1.0699883,50.9008416],[0.7788126,50.9008416],[0.7788126,50.729843],[-0.7255952,50.729843],[-0.7255952,50.7038437],[-1.0074383,50.7038437],[-1.0074383,50.5736307],[-2.3625252,50.5736307],[-2.3625252,50.4846421],[-2.4987805,50.4846421],[-2.4987805,50.5736307],[-3.4096378,50.5736307],[-3.4096378,50.2057837],[-3.6922446,50.2057837],[-3.6922446,50.1347737],[-5.005468,50.1347737],[-5.005468,49.9474456],[-5.2839506,49.9474456],[-5.2839506,50.0229734],[-5.8292886,50.0229734]],[[-6.4580707,49.8673563],[-6.4580707,49.9499935],[-6.3978807,49.9499935],[-6.3978807,50.0053797],[-6.1799606,50.0053797],[-6.1799606,49.9168614],[-6.2540201,49.9168614],[-6.2540201,49.8673563],[-6.4580707,49.8673563]],[[-5.8343165,49.932156],[-5.8343165,49.9754641],[-5.7683254,49.9754641],[-5.7683254,49.932156],[-5.8343165,49.932156]],[[-1.9483797,60.6885737],[-1.9483797,60.3058841],[-1.7543149,60.3058841],[-1.7543149,60.1284428],[-1.5754914,60.1284428],[-1.5754914,59.797917],[-1.0316959,59.797917],[-1.0316959,60.0354518],[-0.6626918,60.0354518],[-0.6626918,60.9103862],[-1.1034395,60.9103862],[-1.1034395,60.8040022],[-1.3506319,60.8040022],[-1.3506319,60.6885737],[-1.9483797,60.6885737]],[[-2.203381,60.1968568],[-2.203381,60.0929443],[-1.9864011,60.0929443],[-1.9864011,60.1968568],[-2.203381,60.1968568]],[[-1.7543149,59.5698289],[-1.7543149,59.4639383],[-1.5373349,59.4639383],[-1.5373349,59.5698289],[-1.7543149,59.5698289]],[[-4.5585981,59.1370518],[-4.5585981,58.9569099],[-4.2867004,58.9569099],[-4.2867004,59.1370518],[-4.5585981,59.1370518]],[[-6.2787732,59.2025744],[-6.2787732,59.0227769],[-5.6650612,59.0227769],[-5.6650612,59.2025744],[-6.2787732,59.2025744]],[[-8.7163482,57.9440556],[-8.7163482,57.7305936],[-8.3592926,57.7305936],[-8.3592926,57.9440556],[-8.7163482,57.9440556]],[[-7.6077005,50.4021026],[-7.6077005,50.2688657],[-7.3907205,50.2688657],[-7.3907205,50.4021026],[-7.6077005,50.4021026]],[[-7.7304303,58.3579902],[-7.7304303,58.248313],[-7.5134503,58.248313],[-7.5134503,58.3579902],[-7.7304303,58.3579902]]]},{"id":"OS-Scottish_Popular-historic","name":"OS Scottish Popular historic","type":"tms","template":"http://ooc.openstreetmap.org/npescotland/tiles/{zoom}/{x}/{y}.jpg","scaleExtent":[6,15],"polygon":[[[-7.8,54.5],[-7.8,61.1],[-1.1,61.1],[-1.1,54.5],[-7.8,54.5]]]},{"id":"Pangasinan_Bulacan_HiRes","name":"Pangasinán/Bulacan (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}","description":"Landsdekkende dataset 25cm resolutie kleuren luchtfotos van de meest recente jaargang.","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_text":"Nationaal Georegister, CC BY 4.0","best":true},{"id":"PNOA-Spain-TMS","name":"PNOA Spain","type":"tms","template":"http://www.ign.es/wmts/pnoa-ma?request=GetTile&service=WMTS&VERSION=1.0.0&Layer=OI.OrthoimageCoverage&Style=default&Format=image/png&TileMatrixSet=GoogleMapsCompatible&TileMatrix={zoom}&TileRow={y}&TileCol={x}","polygon":[[[-17.8846298,28.4460601],[-17.8939535,28.5225529],[-18.0212548,28.7481927],[-18.0224091,28.8038375],[-17.9424017,28.8726124],[-17.8911792,28.8737099],[-17.8903302,28.8515102],[-17.7675902,28.8537764],[-17.7669837,28.8312183],[-17.7412714,28.8319975],[-17.7394926,28.7642235],[-17.7139824,28.7649677],[-17.7129312,28.7303731],[-17.7574427,28.6931782],[-17.7570788,28.6741254],[-17.7457913,28.6743524],[-17.7457266,28.6165627],[-17.7519687,28.5833675],[-17.7622536,28.5591958],[-17.7833086,28.541667],[-17.7831575,28.4936643],[-17.808611,28.4925024],[-17.8060072,28.4468974],[-17.8846298,28.4460601]],[[-18.1661033,27.7851643],[-18.163494,27.6949247],[-18.0889827,27.6963366],[-18.0873398,27.6738724],[-18.0364092,27.6753701],[-18.0350079,27.6302571],[-17.9589987,27.6323976],[-17.8603269,27.7926025],[-17.8630328,27.8368793],[-17.8884015,27.8364947],[-17.8891263,27.8590536],[-17.9906491,27.8567467],[-18.0386803,27.7655831],[-18.1146412,27.7637873],[-18.1154627,27.7863613],[-18.1661033,27.7851643]],[[-17.36038,28.0639801],[-17.3629657,28.1757247],[-17.3375583,28.1763688],[-17.3384577,28.2213012],[-17.1857883,28.2238767],[-17.0820788,28.1351849],[-17.0808422,28.0679977],[-17.1315446,28.0668073],[-17.1563337,28.0214628],[-17.2321063,28.0203711],[-17.2319938,27.9980388],[-17.2576823,27.9978403],[-17.257851,28.0199741],[-17.3086658,28.0192298],[-17.36038,28.0639801]],[[-16.9278171,28.3275779],[-16.9286591,28.3721879],[-16.8776666,28.3729288],[-16.8780707,28.3954191],[-16.5214259,28.4226146],[-16.4457117,28.491135],[-16.4462506,28.535972],[-16.4205859,28.5362679],[-16.4209227,28.5588419],[-16.3443329,28.5597589],[-16.3446023,28.5822095],[-16.1912541,28.5837179],[-16.1916246,28.6068435],[-16.1279344,28.6078193],[-16.1277997,28.5921762],[-16.0995079,28.5925015],[-16.0993395,28.5163822],[-16.1648148,28.5161158],[-16.1647474,28.4938583],[-16.2385755,28.4484704],[-16.2653516,28.4476116],[-16.2658569,28.4030038],[-16.3167484,28.4017594],[-16.3163105,28.380189],[-16.3420763,28.3795075],[-16.3408301,28.2892963],[-16.415837,28.1976134],[-16.415096,28.1311312],[-16.5153297,28.0164796],[-16.6168433,28.01532],[-16.6168096,27.9930469],[-16.7184243,27.9919168],[-16.7190979,28.0371426],[-16.7446952,28.0367859],[-16.7453351,28.0818146],[-16.7706967,28.0816065],[-16.8223966,28.1259036],[-16.8231712,28.1708652],[-16.8487012,28.1707464],[-16.8502842,28.260791],[-16.8756457,28.2605537],[-16.8760836,28.2832162],[-16.9015125,28.2827713],[-16.9023882,28.3279337],[-16.9278171,28.3275779]],[[-15.8537427,27.9008901],[-15.8542032,27.9901812],[-15.828953,27.9906555],[-15.8291065,28.035578],[-15.7782992,28.0363232],[-15.7532793,28.0814298],[-15.7278756,28.0815652],[-15.7282593,28.1718567],[-15.4989741,28.1728039],[-15.4987438,28.1504075],[-15.4497785,28.1507459],[-15.4501622,28.1961425],[-15.3972827,28.1961425],[-15.3964385,28.0383554],[-15.3710348,28.0380167],[-15.3706511,28.0153212],[-15.3457847,28.0153212],[-15.3454777,27.9254406],[-15.3708046,27.9252372],[-15.3705743,27.8352137],[-15.395978,27.8347387],[-15.4209979,27.7879673],[-15.4718052,27.7893932],[-15.471882,27.7666454],[-15.522766,27.7667813],[-15.5477092,27.7216112],[-15.6236132,27.7213395],[-15.6241504,27.741991],[-15.7007451,27.7433495],[-15.801669,27.8110501],[-15.8537427,27.9008901]],[[-14.5215621,28.0467778],[-14.5224358,28.1184131],[-14.4157526,28.1156076],[-14.2168794,28.2278805],[-14.2153651,28.33903],[-14.1641672,28.4528287],[-14.1115132,28.4747955],[-14.0335806,28.7226671],[-13.9565217,28.7449351],[-13.9561722,28.7665857],[-13.8290221,28.7664325],[-13.8289639,28.7879765],[-13.8000741,28.7879255],[-13.8012972,28.7189894],[-13.827566,28.719347],[-13.8278572,28.6517968],[-13.8025786,28.651899],[-13.8033941,28.5384172],[-13.8288474,28.5384684],[-13.8315061,28.3970177],[-13.9158189,28.2241438],[-13.9856445,28.2235696],[-14.0369588,28.1795787],[-14.1387139,28.1799894],[-14.1386556,28.1579103],[-14.2153651,28.1578076],[-14.2147244,28.1118888],[-14.2913173,28.0452356],[-14.3319673,28.0368713],[-14.4457846,28.0469834],[-14.4466583,28.0657961],[-14.4962835,28.0682631],[-14.495934,28.0458525],[-14.5215621,28.0467778]],[[-13.800662,28.8456579],[-13.8009273,28.8231121],[-13.775688,28.8230539],[-13.69729,28.8898184],[-13.69729,28.9127744],[-13.6072498,28.9117991],[-13.4388551,29.0002417],[-13.4374559,29.1351289],[-13.4117005,29.1349931],[-13.4105556,29.2229789],[-13.4592801,29.255586],[-13.4597392,29.2942023],[-13.5091254,29.2945638],[-13.5100581,29.3163453],[-13.5635382,29.3172941],[-13.5640564,29.2713764],[-13.5389228,29.2711956],[-13.5389747,29.2500375],[-13.5661293,29.2501279],[-13.5665956,29.2030039],[-13.5156549,29.2022349],[-13.5156549,29.1820579],[-13.5398038,29.1827819],[-13.5408921,29.137528],[-13.65782,29.1368528],[-13.713222,29.0935079],[-13.7663353,29.0934533],[-13.8502463,29.0165937],[-13.8518224,28.983425],[-13.8524443,28.914861],[-13.9013122,28.89245],[-13.9024005,28.8469779],[-13.800662,28.8456579]],[[1.6479916,38.9990693],[1.7321668,38.9993635],[1.7314703,39.0441733],[1.6489512,39.0431944],[1.6481552,39.1276358],[1.3948608,39.1265691],[1.3954412,39.0864199],[1.2281145,39.0852615],[1.2291095,39.0028958],[1.1448657,39.0018003],[1.1452803,38.8319988],[1.3113632,38.8331615],[1.3121924,38.7906483],[1.3946949,38.7916178],[1.3951924,38.7529597],[1.3112803,38.7519251],[1.3125919,38.6238804],[1.6489036,38.6251112],[1.6480745,38.7111504],[1.58456,38.7101152],[1.5811604,38.7005387],[1.5491544,38.7002798],[1.5197188,38.7092094],[1.50355,38.7253185],[1.4813282,38.9155064],[1.5518906,38.9254411],[1.5667328,38.9566554],[1.6487378,38.9583318],[1.6479916,38.9990693]],[[2.5450749,39.4166673],[2.43933,39.4161122],[2.438714,39.4846853],[2.439022,39.4993424],[2.3122308,39.4993424],[2.3119228,39.5417911],[2.2290722,39.5409994],[2.2283536,39.6260571],[2.3460076,39.6270851],[2.9270445,39.9601558],[3.1456647,39.9600498],[3.1460753,40.0019797],[3.2313899,40.0019797],[3.2312872,39.8329231],[3.1482313,39.8331596],[3.1484366,39.7935717],[3.4814817,39.7931773],[3.4803472,39.5959027],[3.3150618,39.4784606],[3.3146179,39.3785504],[3.0830178,39.2499355],[2.9798608,39.2501482],[2.9790395,39.3334971],[2.7287424,39.3334177],[2.7288451,39.4581361],[2.6456865,39.4577397],[2.6453785,39.4996593],[2.5452802,39.4994216],[2.5450749,39.4166673]],[[3.8120402,40.0434431],[3.729082,40.0437979],[3.7286185,39.9584155],[3.8126633,39.9576011],[3.8122771,39.9164393],[3.9608975,39.9159813],[4.1938142,39.791308],[4.3150279,39.7905799],[4.3159934,39.8329294],[4.3987393,39.8320396],[4.3973664,39.9185834],[4.3158003,39.9193274],[4.3161865,40.0433985],[4.2318959,40.0443594],[4.2324752,40.0847793],[4.1491501,40.086109],[4.1490623,40.1255157],[4.0627981,40.1272166],[4.0624217,40.0849941],[3.8128687,40.085294],[3.8120402,40.0434431]],[[-8.8910646,41.8228891],[-9.1092038,42.5751065],[-9.0365469,42.730656],[-9.0883419,42.7269569],[-9.1466113,42.7750272],[-9.2185488,42.9016271],[-9.2760988,42.8605106],[-9.3099094,42.9311297],[-9.2789763,42.9821991],[-9.3099094,43.0600377],[-9.2523594,43.1041725],[-9.2314975,43.1703151],[-9.1473307,43.210176],[-9.06748,43.1991644],[-9.0336694,43.2426748],[-8.99842,43.2447709],[-8.9998588,43.2955793],[-8.9372732,43.3055265],[-8.92936,43.326986],[-8.8638969,43.3290792],[-8.8761263,43.3740655],[-8.8221732,43.3735426],[-8.785485,43.3191358],[-8.7063538,43.305003],[-8.6099575,43.3296025],[-8.5509688,43.3233227],[-8.5243519,43.3364048],[-8.5250713,43.3646525],[-8.45745,43.3918416],[-8.3610538,43.4111803],[-8.3603344,43.4634161],[-8.3344369,43.5797394],[-8.2776063,43.5708796],[-8.0646713,43.7239184],[-7.9992081,43.7233986],[-7.9171994,43.7826357],[-7.8560525,43.7914643],[-7.83591,43.7374337],[-7.6628443,43.809819],[-7.3188932,43.6782695],[-7.1997467,43.5830817],[-6.2488228,43.6075032],[-6.1229322,43.5790105],[-5.8520425,43.6798953],[-5.6036334,43.5708672],[-5.2855347,43.5619084],[-5.1787525,43.4991591],[-4.9089869,43.4836655],[-4.6156167,43.4192021],[-4.1839917,43.4249168],[-3.8029478,43.5195394],[-3.7400025,43.4869277],[-3.5612827,43.5423572],[-3.1083013,43.3816347],[-2.9385737,43.4624573],[-2.7452417,43.4755094],[-2.3046245,43.3170625],[-1.9854018,43.3563045],[-1.8552841,43.3972545],[-1.769802,43.3964383],[-1.7700492,43.3760501],[-1.7100474,43.3756908],[-1.7113451,43.3312527],[-1.7225915,43.3131806],[-1.6890375,43.3129108],[-1.6881106,43.3341294],[-1.6446695,43.3337248],[-1.6449785,43.3133155],[-1.6029903,43.3129528],[-1.6034352,43.2926624],[-1.5635905,43.2921227],[-1.5630468,43.3133844],[-1.4779905,43.3128355],[-1.3667723,43.2761368],[-1.3568809,43.2381533],[-1.3703692,43.1712972],[-1.4423067,43.0833554],[-1.4198262,43.0603647],[-1.3730668,43.051166],[-1.3640746,43.1115893],[-1.3020285,43.135217],[-1.2354864,43.1332484],[-1.2795481,43.0774443],[-1.1923239,43.0649635],[-1.0061856,43.0077821],[-0.942341,42.9748951],[-0.7562028,42.9821318],[-0.7148387,42.9610774],[-0.6968543,42.9031405],[-0.5511809,42.8220693],[-0.5044215,42.8484456],[-0.4288871,42.8200906],[-0.3164848,42.8655842],[-0.1456332,42.810856],[-0.0314324,42.7124874],[0.1861785,42.7540985],[0.3021777,42.7177729],[0.3642238,42.7428729],[0.4487504,42.7144695],[0.6276949,42.7223973],[0.6411832,42.8576747],[0.7149192,42.882718],[0.9675996,42.8181119],[1.108777,42.7989808],[1.1753192,42.7342872],[1.3632559,42.7415521],[1.4113736,42.7093914],[1.4806054,42.7103407],[1.4813006,42.5010664],[1.6443591,42.5020345],[1.6432777,42.5424539],[1.730407,42.5434214],[1.7316429,42.5011803],[2.0638621,42.5016359],[2.0645572,42.4590247],[2.3969309,42.4599364],[2.3976786,42.4178363],[2.4804823,42.4179732],[2.4809767,42.3759441],[2.6447922,42.3762636],[2.6444832,42.4592447],[2.8113266,42.4596094],[2.8112648,42.5010358],[3.063878,42.5008535],[3.063878,42.4591535],[3.2307832,42.4593359],[3.2304935,42.3764363],[3.3141469,42.3760369],[3.3141243,42.3339864],[3.397855,42.3340435],[3.3973912,42.290094],[3.3138923,42.2908368],[3.3139695,42.2070151],[3.1475896,42.2073012],[3.1475896,42.1260612],[3.2305478,42.1260039],[3.2466753,41.9529359],[3.1945206,41.8558943],[3.060537,41.7647419],[2.7835777,41.6371796],[2.26293,41.4271601],[2.1649151,41.2989297],[1.86008,41.2232228],[1.3763003,41.116273],[1.1793714,41.0464585],[1.0858526,41.048493],[0.758537,40.8195599],[0.9114042,40.733761],[0.8781331,40.6751363],[0.6650182,40.5358666],[0.5580112,40.5502166],[0.433919,40.3757589],[0.2675635,40.1919192],[0.1641534,40.0647234],[0.0751307,40.0144671],[0.010387,39.8952188],[-0.0939224,39.8116904],[-0.1847435,39.6311716],[-0.2908513,39.5036254],[-0.2863552,39.333431],[-0.1856427,39.1774612],[-0.2135185,39.1558487],[-0.1110076,38.9722246],[0.0094878,38.8826835],[0.1218901,38.872183],[0.2342925,38.798636],[0.2558737,38.7264162],[0.0958128,38.6133825],[-0.0022021,38.6070586],[-0.0570544,38.5269073],[-0.2719677,38.4762395],[-0.379874,38.3931234],[-0.3834708,38.3381297],[-0.4509122,38.3310763],[-0.5048654,38.2830943],[-0.4823849,38.1948095],[-0.429331,38.1658287],[-0.4545091,38.148859],[-0.5839966,38.1721913],[-0.6136708,38.1198599],[-0.6370505,37.9612228],[-0.6811123,37.9456238],[-0.7323677,37.8810656],[-0.7215771,37.7830562],[-0.688306,37.7340026],[-0.6641461,37.6231485],[-0.7193941,37.5878413],[-0.9196258,37.5375806],[-1.1107098,37.5164093],[-1.3383246,37.5286671],[-1.4408917,37.3903714],[-1.6766966,37.2765189],[-1.8540816,36.9122889],[-2.0683486,36.6929117],[-2.2158766,36.6619233],[-2.3721861,36.7801753],[-2.6812926,36.6591056],[-2.9201476,36.6675585],[-3.09402,36.712625],[-3.4610839,36.6548788],[-3.7280395,36.6929117],[-4.3743529,36.6633322],[-4.6571151,36.4404171],[-4.9188018,36.4531321],[-5.1699508,36.3513541],[-5.2841094,36.1970201],[-5.2680911,36.1241812],[-5.3524784,36.1224654],[-5.3516094,36.0401413],[-5.4365759,36.0388921],[-5.4353207,36.0034384],[-5.6888562,36.0036518],[-5.6899635,36.0405317],[-5.85506,36.0385595],[-5.8566821,36.1242077],[-5.9384817,36.1221487],[-5.9400265,36.1655625],[-5.9983445,36.1645024],[-6.0357297,36.1780957],[-6.0775178,36.2224132],[-6.1506113,36.2864561],[-6.231541,36.3770075],[-6.3358504,36.5310643],[-6.3214629,36.5816265],[-6.404191,36.6234958],[-6.4743301,36.7489673],[-6.4158808,36.7993866],[-6.490516,36.9173818],[-6.6298949,37.0194012],[-6.8744824,37.1083766],[-7.0426363,37.1850699],[-7.2647434,37.1843535],[-7.3753473,37.1535419],[-7.408316,37.1682196],[-7.4202886,37.2118318],[-7.4249231,37.2350505],[-7.4380543,37.2451969],[-7.4459717,37.3326142],[-7.4480958,37.3909382],[-7.4696271,37.4075829],[-7.4647029,37.4530494],[-7.5019723,37.516411],[-7.5191587,37.5229203],[-7.5219588,37.5723727],[-7.4501271,37.6695835],[-7.4249019,37.7599222],[-7.316662,37.839974],[-7.268329,37.988952],[-7.1536786,38.0155235],[-7.1177098,38.0553626],[-7.0142997,38.0243785],[-6.9963153,38.1075633],[-6.9614706,38.201254],[-7.080617,38.1570753],[-7.3402665,38.4402363],[-7.2638329,38.7380741],[-7.0435243,38.8729667],[-7.0615086,38.907962],[-6.9693387,39.0198308],[-7.0008114,39.0887867],[-7.1536786,39.0957658],[-7.1525545,39.1602899],[-7.2447245,39.1968854],[-7.2559647,39.2813308],[-7.3368944,39.3535074],[-7.3279022,39.4559917],[-7.5144901,39.5886496],[-7.5527069,39.6795427],[-7.0502684,39.6752171],[-6.9951913,39.8195433],[-6.9221297,39.8790868],[-6.886161,40.0229854],[-7.0412762,40.1347927],[-7.0176717,40.266146],[-6.8086034,40.3450071],[-6.8681766,40.4451649],[-6.8535643,40.6066433],[-6.837828,40.8757589],[-6.9536024,41.0370445],[-6.8018592,41.0395879],[-6.7681385,41.138706],[-6.6411239,41.2655616],[-6.5624422,41.2630269],[-6.217367,41.5791017],[-6.3162811,41.644652],[-6.5152332,41.6412921],[-6.5871707,41.6883151],[-6.5478299,41.8559743],[-6.6298836,41.9112057],[-7.1334461,41.9404756],[-7.1682909,41.8718791],[-7.4256922,41.7847727],[-7.9539833,41.8459271],[-8.130455,41.7805819],[-8.2518495,41.9078597],[-8.1293309,42.0348842],[-8.2484774,42.1008034],[-8.3676239,42.0557521],[-8.6070409,42.0340493],[-8.8910646,41.8228891]]],"terms_text":"PNOA","best":true},{"id":"Slovakia-Historic-Maps","name":"Slovakia Historic Maps","type":"tms","template":"http://tms.freemap.sk/historicke/{zoom}/{x}/{y}.png","scaleExtent":[0,12],"polygon":[[[16.8196949,47.4927236],[16.8196949,49.5030322],[22.8388318,49.5030322],[22.8388318,47.4927236],[16.8196949,47.4927236]]]},{"id":"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","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-Orthofoto2014","name":"South Tyrol Orthofoto 2014","type":"tms","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_OF_2014_EPSG3857&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","scaleExtent":[0,18],"polygon":[[[12.23442,46.84254],[12.24913,46.82785],[12.24913,46.81945],[12.25753,46.81735],[12.26173,46.80686],[12.26594,46.80686],[12.26804,46.79637],[12.26173,46.79427],[12.27014,46.78587],[12.27224,46.76908],[12.28485,46.76698],[12.29745,46.7439],[12.30166,46.7439],[12.30166,46.7376],[12.28695,46.7376],[12.23652,46.72081],[12.18819,46.71451],[12.16298,46.70192],[12.10835,46.69353],[12.08944,46.68303],[12.05792,46.68093],[12.04531,46.67464],[12.03481,46.67464],[12.03061,46.68303],[12.0096,46.68303],[11.98438,46.66834],[11.94866,46.66414],[11.93816,46.65575],[11.90874,46.64525],[11.89193,46.64525],[11.8457,46.62846],[11.82049,46.62636],[11.80998,46.60748],[11.79528,46.60328],[11.78897,46.59069],[11.78057,46.58859],[11.76586,46.55501],[11.75325,46.54871],[11.73855,46.52982],[11.73224,46.52982],[11.72384,46.51513],[11.71543,46.51513],[11.71333,46.50254],[11.70913,46.50254],[11.70913,46.49624],[11.69652,46.48575],[11.69442,46.47735],[11.66711,46.47525],[11.66711,46.44587],[11.6608,46.44587],[11.64399,46.45846],[11.63769,46.45846],[11.63349,46.44587],[11.62508,46.44797],[11.62508,46.43957],[11.61878,46.43957],[11.61458,46.42278],[11.61037,46.42278],[11.61037,46.41649],[11.62508,46.41229],[11.62508,46.3934],[11.61458,46.38291],[11.60617,46.38291],[11.60407,46.37241],[11.58306,46.37241],[11.58306,46.34932],[11.55995,46.32414],[11.53894,46.32834],[11.53894,46.34513],[11.52423,46.34723],[11.50111,46.34723],[11.49901,46.32834],[11.48851,46.33044],[11.49271,46.32204],[11.41917,46.32414],[11.41707,46.25278],[11.35613,46.24858],[11.34773,46.25698],[11.34563,46.26747],[11.34143,46.26747],[11.33722,46.25068],[11.31201,46.24858],[11.30991,46.25278],[11.3015,46.25278],[11.2889,46.24019],[11.2889,46.2234],[11.25108,46.2234],[11.24898,46.2129],[11.16283,46.215],[11.16283,46.24858],[11.12711,46.24858],[11.13131,46.25278],[11.12291,46.25488],[11.12501,46.29895],[11.16283,46.29895],[11.16283,46.36821],[11.16703,46.36821],[11.16703,46.38081],[11.17543,46.3871],[11.17754,46.3997],[11.20485,46.3997],[11.20695,46.42068],[11.19014,46.42068],[11.19014,46.42698],[11.19435,46.42698],[11.19855,46.44167],[11.20485,46.44587],[11.20695,46.47315],[11.19014,46.47525],[11.18804,46.48365],[11.15232,46.47525],[11.08298,46.47525],[11.08088,46.43537],[11.04096,46.42068],[11.01154,46.42068],[10.99894,46.44587],[10.98843,46.44587],[10.98423,46.45217],[10.96952,46.45217],[10.96112,46.48365],[10.95691,46.48365],[10.95481,46.49414],[10.94851,46.49624],[10.94431,46.50673],[10.91069,46.49624],[10.90018,46.49624],[10.89808,46.51093],[10.85606,46.50254],[10.84135,46.54241],[10.86446,46.54661],[10.86236,46.55081],[10.76571,46.54031],[10.72158,46.55081],[10.59762,46.55291],[10.5619,46.54871],[10.53668,46.55291],[10.50096,46.54871],[10.48415,46.55501],[10.46314,46.55501],[10.47155,46.5676],[10.47365,46.59069],[10.47785,46.59069],[10.47785,46.61797],[10.46944,46.62636],[10.44843,46.63476],[10.42532,46.62846],[10.3938,46.63056],[10.3896,46.64525],[10.3812,46.64735],[10.3833,46.66414],[10.3791,46.66834],[10.3791,46.69353],[10.3854,46.72081],[10.3896,46.72081],[10.3938,46.7376],[10.41692,46.75229],[10.41692,46.78587],[10.42112,46.79847],[10.42532,46.79847],[10.42532,46.80686],[10.43373,46.81106],[10.43793,46.79007],[10.44423,46.78377],[10.44843,46.7439],[10.45264,46.7439],[10.45684,46.72711],[10.46104,46.72711],[10.46524,46.71032],[10.46944,46.71032],[10.47365,46.67254],[10.47995,46.67044],[10.48415,46.65575],[10.48836,46.65575],[10.48415,46.62846],[10.48836,46.62846],[10.48836,46.62217],[10.49886,46.62007],[10.52828,46.62427],[10.49886,46.63056],[10.49886,46.64525],[10.50516,46.64316],[10.49886,46.66204],[10.51777,46.65785],[10.58921,46.66204],[10.63123,46.65365],[10.79302,46.65575],[10.79723,46.65155],[10.88127,46.65155],[10.89178,46.65785],[10.9275,46.66414],[10.94431,46.67464],[10.98003,46.67464],[11.00104,46.68303],[11.02415,46.68303],[11.05147,46.69772],[11.12711,46.70822],[11.13971,46.71242],[11.14392,46.71871],[11.17543,46.72081],[11.19855,46.7334],[11.24898,46.7355],[11.25318,46.72291],[11.2952,46.72921],[11.30571,46.70822],[11.31831,46.70822],[11.33722,46.71871],[11.38555,46.72081],[11.43178,46.7376],[11.50952,46.7439],[11.54734,46.75649],[11.56835,46.75649],[11.58306,46.76698],[11.60617,46.76908],[11.61037,46.77538],[11.69862,46.79427],[11.71753,46.79427],[11.72174,46.79007],[11.73855,46.75859],[11.74905,46.75019],[11.76166,46.70192],[11.76586,46.70192],[11.78687,46.71661],[11.8331,46.72291],[11.86041,46.7376],[11.90874,46.7439],[11.92135,46.75229],[11.95286,46.75859],[11.95917,46.76488],[11.99489,46.77538],[12.00749,46.77538],[12.0096,46.77958],[12.03061,46.78168],[12.05792,46.79427],[12.09995,46.79847],[12.13566,46.81316],[12.15878,46.81316],[12.18609,46.82785],[12.21551,46.83205],[12.23442,46.84254]],[[11.97388,46.96637],[11.99489,46.96007],[11.99489,46.95587],[12.0096,46.95797],[12.0117,46.94748],[12.0159,46.94748],[12.0117,46.94118],[12.018,46.93908],[12.02851,46.92229],[12.00749,46.9118],[11.97388,46.9055],[11.95707,46.89501],[11.91714,46.88871],[11.85831,46.86982],[11.8394,46.86982],[11.80158,46.85303],[11.76166,46.84464],[11.74905,46.83415],[11.68181,46.81945],[11.67971,46.81526],[11.6545,46.81106],[11.64399,46.80476],[11.63769,46.80686],[11.63139,46.82155],[11.62508,46.82155],[11.62298,46.83205],[11.61037,46.84464],[11.61668,46.84884],[11.61458,46.85723],[11.61037,46.85723],[11.61668,46.86563],[11.64609,46.86563],[11.68602,46.88242],[11.69022,46.88871],[11.74905,46.89711],[11.75325,46.90341],[11.78057,46.9076],[11.80158,46.9202],[11.8457,46.92649],[11.87722,46.94118],[11.89613,46.94328],[11.92135,46.95797],[11.96757,46.96217],[11.97388,46.96637]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano CC-BY 3.0","best":true},{"id":"South-Tyrol-Topomap","name":"South Tyrol Topomap","type":"tms","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_BASEMAP_TOPO&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","description":"Topographical basemap of South Tyrol","scaleExtent":[0,20],"polygon":[[[10.38615,46.68821],[10.39201,46.69016],[10.40215,46.70624],[10.41274,46.70821],[10.41622,46.71479],[10.4168,46.71847],[10.39934,46.73435],[10.43464,46.75356],[10.44107,46.75413],[10.44011,46.77149],[10.42123,46.78861],[10.42845,46.79755],[10.43851,46.79869],[10.44925,46.80462],[10.45602,46.81635],[10.45438,46.82221],[10.4583,46.82478],[10.45513,46.83059],[10.45906,46.83548],[10.46483,46.83624],[10.46229,46.8413],[10.46987,46.84933],[10.46819,46.8553],[10.47838,46.86013],[10.48372,46.85543],[10.49628,46.85305],[10.49931,46.84857],[10.52124,46.84653],[10.5527,46.8511],[10.55795,46.84695],[10.55264,46.8408],[10.55536,46.84087],[10.58883,46.85125],[10.59502,46.85829],[10.60936,46.8597],[10.62441,46.86558],[10.64858,46.86655],[10.66787,46.87651],[10.67297,46.87138],[10.69112,46.86861],[10.69786,46.86339],[10.69508,46.85308],[10.70594,46.84786],[10.71763,46.84795],[10.72333,46.83892],[10.75621,46.83383],[10.76481,46.82409],[10.76387,46.81971],[10.75239,46.81387],[10.74506,46.80223],[10.7276,46.79709],[10.73122,46.78925],[10.75722,46.78624],[10.77744,46.79149],[10.78678,46.79735],[10.81439,46.77662],[10.82479,46.77472],[10.83129,46.78138],[10.84112,46.78282],[10.85354,46.77506],[10.86845,46.77313],[10.86993,46.7669],[10.88294,46.76393],[10.88962,46.76529],[10.8951,46.77092],[10.90527,46.76911],[10.92299,46.7764],[10.92821,46.77408],[10.94388,46.77648],[10.97522,46.77361],[10.97932,46.77014],[10.99475,46.76804],[11.01397,46.77317],[11.02328,46.76715],[11.0346,46.79428],[11.04234,46.801],[11.03792,46.80562],[11.05633,46.80928],[11.07279,46.82092],[11.08171,46.82252],[11.0762,46.83384],[11.06887,46.83793],[11.07303,46.84345],[11.06988,46.85348],[11.08742,46.87927],[11.09961,46.88922],[11.09538,46.89178],[11.09795,46.89844],[11.0946,46.91247],[11.10792,46.91706],[11.10804,46.92632],[11.11418,46.93234],[11.13851,46.92865],[11.16322,46.94091],[11.16642,46.94479],[11.16114,46.94979],[11.1637,46.96677],[11.17598,46.96367],[11.18658,46.97062],[11.19527,46.97152],[11.20418,46.96877],[11.20688,46.96403],[11.22047,46.97025],[11.24139,46.9708],[11.24865,46.97517],[11.25582,46.97535],[11.26272,46.98169],[11.27662,46.98168],[11.28762,46.98699],[11.30709,46.98525],[11.3205,46.99345],[11.33765,46.98606],[11.34516,46.99169],[11.35932,46.99154],[11.37697,46.98025],[11.38324,46.97168],[11.40465,46.96609],[11.43929,46.97601],[11.45134,46.99294],[11.46803,46.99582],[11.46859,47.003],[11.47831,47.01201],[11.50238,47.01073],[11.50313,47.00808],[11.51366,47.00595],[11.51679,47.00091],[11.53381,46.99233],[11.53846,46.98519],[11.55297,46.99149],[11.57663,46.99657],[11.58,47.00277],[11.58879,47.00641],[11.59901,47.00657],[11.60944,47.01207],[11.62697,47.01437],[11.63629,47.00383],[11.66542,46.99304],[11.6885,46.99658],[11.71226,46.99416],[11.72897,46.97322],[11.74698,46.97013],[11.76411,46.97412],[11.78106,46.99342],[11.81526,46.991],[11.83564,46.99417],[11.84396,47.0025],[11.85192,47.0014],[11.86722,47.01252],[11.87393,47.01136],[11.8794,47.01714],[11.89137,47.01728],[11.91627,47.03422],[11.9329,47.03864],[11.94688,47.03464],[11.95457,47.04374],[11.96773,47.04158],[11.97912,47.0511],[11.98587,47.04815],[11.99534,47.05064],[12.02037,47.04821],[12.02968,47.05127],[12.03353,47.0583],[12.04276,47.06228],[12.07543,47.0605],[12.08035,47.06951],[12.09308,47.07791],[12.10329,47.07931],[12.11867,47.07445],[12.13561,47.08171],[12.15125,47.08049],[12.15997,47.08267],[12.18589,47.09322],[12.2278,47.08302],[12.24228,47.06892],[12.23786,47.0644],[12.21821,47.05795],[12.2182,47.04483],[12.20552,47.02595],[12.18048,47.02414],[12.16423,47.01782],[12.14786,47.02357],[12.12723,47.01218],[12.12285,47.00662],[12.1322,46.99339],[12.12974,46.98593],[12.13977,46.982],[12.13808,46.96514],[12.13328,46.96292],[12.13882,46.95764],[12.15927,46.95133],[12.1702,46.93758],[12.15414,46.91654],[12.14675,46.91413],[12.16205,46.908],[12.16959,46.91121],[12.19154,46.90682],[12.20106,46.8965],[12.2022,46.88806],[12.21663,46.87517],[12.22147,46.88084],[12.23125,46.88146],[12.2345,46.88919],[12.24162,46.89192],[12.27486,46.88512],[12.27979,46.87921],[12.27736,46.87319],[12.29326,46.86566],[12.2912,46.85704],[12.29733,46.84455],[12.30833,46.84137],[12.30726,46.83271],[12.285,46.81503],[12.29383,46.8027],[12.28905,46.79948],[12.28889,46.79427],[12.28232,46.79153],[12.28539,46.7839],[12.30943,46.78603],[12.35837,46.77583],[12.37036,46.74163],[12.38475,46.71745],[12.40283,46.70811],[12.41103,46.70701],[12.41522,46.70163],[12.42862,46.6997],[12.42943,46.69567],[12.44268,46.68979],[12.47501,46.68756],[12.4795,46.67969],[12.43473,46.66714],[12.40648,46.64167],[12.38115,46.64183],[12.37944,46.63733],[12.3915,46.62765],[12.38577,46.62154],[12.35939,46.61829],[12.34465,46.62376],[12.34034,46.63022],[12.33578,46.62732],[12.3172,46.62876],[12.31785,46.62355],[12.30802,46.61811],[12.28413,46.61623],[12.26982,46.62003],[12.25931,46.62809],[12.24502,46.62326],[12.24198,46.61586],[12.21241,46.60918],[12.20444,46.59836],[12.19228,46.59321],[12.19261,46.62059],[12.1818,46.6192],[12.17117,46.63275],[12.16062,46.63574],[12.1511,46.63215],[12.1436,46.6327],[12.13739,46.64122],[12.12342,46.64475],[12.10949,46.65204],[12.10609,46.65783],[12.09345,46.66123],[12.08826,46.66638],[12.07985,46.66686],[12.07038,46.67386],[12.07173,46.66064],[12.06686,46.65364],[12.07479,46.64329],[12.06837,46.63997],[12.06495,46.62121],[12.05448,46.61778],[12.05318,46.60989],[12.04613,46.60716],[12.05043,46.60016],[12.04763,46.58357],[12.03665,46.57668],[12.0266,46.55871],[12.02189,46.55791],[11.99941,46.53208],[11.99411,46.53345],[11.98704,46.54417],[11.96633,46.54363],[11.95094,46.53869],[11.94719,46.52879],[11.94147,46.52689],[11.93294,46.52631],[11.9121,46.532],[11.8904,46.52175],[11.85192,46.51682],[11.82849,46.50783],[11.82334,46.51315],[11.82391,46.52141],[11.81086,46.53146],[11.79385,46.52023],[11.79189,46.51322],[11.76157,46.50503],[11.74317,46.50391],[11.73202,46.50877],[11.71935,46.50916],[11.71524,46.51245],[11.69889,46.50218],[11.6672,46.49647],[11.64515,46.49743],[11.63849,46.50051],[11.63495,46.49486],[11.64297,46.49346],[11.65174,46.48271],[11.64536,46.47189],[11.64179,46.47439],[11.62679,46.4708],[11.62987,46.46377],[11.61882,46.44325],[11.62143,46.42539],[11.60161,46.39731],[11.60307,46.38924],[11.5932,46.38265],[11.56489,46.38018],[11.55878,46.35076],[11.55249,46.34418],[11.54423,46.34483],[11.53837,46.35015],[11.52445,46.35502],[11.47969,46.36277],[11.48052,46.3551],[11.46322,46.34922],[11.45556,46.33396],[11.42105,46.32441],[11.40517,46.32387],[11.39865,46.31426],[11.39994,46.30709],[11.39569,46.3083],[11.38188,46.30052],[11.36088,46.29906],[11.36078,46.29682],[11.38256,46.29177],[11.3871,46.28143],[11.39609,46.27423],[11.39862,46.264],[11.38756,46.26029],[11.37347,46.2629],[11.36836,46.26135],[11.35783,46.26481],[11.35495,46.27564],[11.33912,46.28306],[11.33379,46.29049],[11.33471,46.2962],[11.3129,46.28256],[11.31737,46.27303],[11.30645,46.25786],[11.29124,46.2604],[11.24743,46.22933],[11.20622,46.2187],[11.18267,46.22496],[11.17077,46.23806],[11.17994,46.24434],[11.18351,46.25269],[11.18935,46.25354],[11.19448,46.2461],[11.20029,46.25566],[11.16604,46.26129],[11.14885,46.27904],[11.13725,46.28336],[11.14293,46.28934],[11.15847,46.29059],[11.16439,46.2986],[11.1761,46.30346],[11.1847,46.32104],[11.18894,46.32151],[11.18696,46.32673],[11.1942,46.33016],[11.20204,46.34212],[11.19001,46.35984],[11.19263,46.36578],[11.20393,46.36765],[11.19792,46.37232],[11.21275,46.39804],[11.21345,46.40675],[11.20565,46.4166],[11.21026,46.4206],[11.20347,46.42682],[11.21416,46.43556],[11.21634,46.44255],[11.20903,46.45293],[11.21419,46.45807],[11.21736,46.45731],[11.21886,46.46199],[11.21626,46.47277],[11.20939,46.481],[11.20876,46.49346],[11.19608,46.50241],[11.1924,46.501],[11.18686,46.50734],[11.18002,46.49823],[11.17014,46.49635],[11.16095,46.4878],[11.12934,46.48058],[11.1103,46.49643],[11.10449,46.4948],[11.08812,46.50128],[11.08173,46.53021],[11.05915,46.51508],[11.03795,46.51357],[11.05006,46.50784],[11.05773,46.49235],[11.06278,46.4894],[11.06894,46.46619],[11.07625,46.45487],[11.0778,46.44569],[11.07301,46.44042],[11.05394,46.44849],[11.0414,46.44569],[11.02817,46.46116],[11.00952,46.46917],[11.00462,46.47607],[10.98695,46.48289],[10.96543,46.48103],[10.95791,46.46983],[10.93819,46.46578],[10.9325,46.45831],[10.93332,46.4528],[10.91305,46.44284],[10.89161,46.44366],[10.88324,46.44995],[10.88093,46.44579],[10.87162,46.4438],[10.86174,46.43509],[10.85113,46.43817],[10.80034,46.44185],[10.78906,46.45164],[10.77835,46.47112],[10.76934,46.47609],[10.76463,46.4848],[10.75906,46.48547],[10.74422,46.48333],[10.71753,46.46022],[10.69667,46.4573],[10.68293,46.44846],[10.66821,46.45122],[10.63303,46.44309],[10.61439,46.45098],[10.60128,46.46139],[10.59995,46.46766],[10.57672,46.47237],[10.55875,46.48187],[10.54986,46.49123],[10.53685,46.49062],[10.52657,46.49425],[10.49366,46.49719],[10.48141,46.49337],[10.45714,46.5096],[10.45124,46.53083],[10.45814,46.54215],[10.47056,46.54377],[10.46954,46.54856],[10.47617,46.55749],[10.47321,46.56701],[10.48305,46.5777],[10.48575,46.58921],[10.48221,46.59199],[10.48576,46.59805],[10.48291,46.60512],[10.49055,46.61394],[10.44632,46.63989],[10.40935,46.63389],[10.40011,46.63648],[10.39873,46.6455],[10.38946,46.65862],[10.39057,46.67089],[10.3803,46.68399],[10.38615,46.68821]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano"},{"id":"Bern-bern2016-tms","name":"Stadt Bern 10cm (2016)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/bern2016/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[8,21],"polygon":[[[7.2943145,46.9237564],[7.2982665,46.9274715],[7.3061586,46.9309487],[7.3043338,46.9362344],[7.3068603,46.9403709],[7.3246431,46.9432765],[7.3284525,46.946409],[7.3414051,46.9460797],[7.3438454,46.9473713],[7.3434554,46.9487937],[7.3513567,46.9485481],[7.3505628,46.950213],[7.3530901,46.9519266],[7.3582028,46.9511773],[7.3685031,46.9566244],[7.3715097,46.9607339],[7.37503,46.959835],[7.3785111,46.9614686],[7.3806232,46.9654741],[7.3832097,46.9663014],[7.3937998,46.9669268],[7.4000528,46.9691779],[7.4082922,46.9686857],[7.4281713,46.9738041],[7.4327053,46.972689],[7.4353602,46.9684345],[7.4378522,46.9684302],[7.4412474,46.9767865],[7.4456893,46.9747939],[7.4483835,46.9756393],[7.4477006,46.9790125],[7.4440468,46.9780682],[7.4412738,46.9798224],[7.4506732,46.9901527],[7.4522112,46.9896803],[7.454649,46.9778182],[7.4680382,46.9758258],[7.4707923,46.969998],[7.4701907,46.9674116],[7.4781618,46.9711823],[7.4845237,46.9701571],[7.4861275,46.9679018],[7.4857945,46.9646828],[7.4784708,46.9629043],[7.4802865,46.9606768],[7.4789304,46.9587841],[7.4797786,46.9566019],[7.4770135,46.9544586],[7.4840504,46.9499938],[7.4833925,46.9451977],[7.4955563,46.9396169],[7.4935119,46.9376594],[7.4908036,46.9387617],[7.4894997,46.9368667],[7.4766667,46.9369496],[7.4781093,46.9362489],[7.4746986,46.9339187],[7.4753537,46.9329898],[7.4691047,46.9292427],[7.4707683,46.9255044],[7.4585674,46.934836],[7.4476373,46.9304297],[7.435418,46.9349668],[7.4338022,46.9331237],[7.4376403,46.9307415],[7.4146941,46.9368183],[7.413844,46.9315682],[7.4070798,46.9303824],[7.408065,46.9256296],[7.4021268,46.9241992],[7.4014835,46.9211927],[7.3875736,46.9304506],[7.3823129,46.927282],[7.3800187,46.9298929],[7.3808694,46.9324085],[7.3748669,46.9314306],[7.3748901,46.9327104],[7.368066,46.9323929],[7.3683058,46.930426],[7.3604074,46.9285884],[7.3605592,46.9272018],[7.338783,46.9245357],[7.3393683,46.9196675],[7.3274574,46.9190326],[7.3269178,46.9235974],[7.324374,46.9251891],[7.3082264,46.9222857],[7.2943145,46.9237564]]],"terms_text":"Orthophoto 2016, Vermessungsamt Stadt Bern ","best":true},{"id":"Uster-2008","name":"Stadt Uster Orthophoto 2008 10cm","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/uster/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.6,47.31],[8.6,47.39],[8.77,47.39],[8.77,47.31],[8.6,47.31]]],"terms_text":"Stadt Uster Vermessung Orthophoto 2008"},{"id":"Zuerich-zh_luftbild2011-tms","name":"Stadt Zürich Luftbild 2011","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_luftbild2011/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.4441,47.3141],[8.4441,47.4411],[8.6284,47.4411],[8.6284,47.3141],[8.4441,47.3141]]],"terms_text":"Stadt Zürich Luftbild 2011"},{"id":"Zuerich-city_map","name":"Stadtplan Zürich","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_stadtplan/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.4482,47.321],[8.4482,47.4339],[8.6248,47.4339],[8.6248,47.321],[8.4482,47.321]]],"terms_text":"Stadt Zürich Open Government Data"},{"id":"stamen-terrain-background","name":"Stamen Terrain","type":"tms","template":"http://{switch:a,b,c,d}.tile.stamen.com/terrain-background/{zoom}/{x}/{y}.jpg","scaleExtent":[4,18],"terms_url":"http://maps.stamen.com/#terrain","terms_text":"Map tiles by Stamen Design, under CC BY 3.0"},{"id":"Stevns_Denmark","name":"Stevns (Denmark)","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.dk/stevns/2009/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[12.0913942,55.3491574],[12.0943104,55.3842256],[12.1573875,55.3833103],[12.1587287,55.4013326],[12.1903468,55.400558],[12.1931411,55.4364665],[12.2564251,55.4347995],[12.2547073,55.4168882],[12.3822489,55.4134349],[12.3795942,55.3954143],[12.4109213,55.3946958],[12.409403,55.3766417],[12.4407807,55.375779],[12.4394142,55.3578314],[12.4707413,55.3569971],[12.4629475,55.2672214],[12.4315633,55.2681491],[12.430045,55.2502103],[12.3672011,55.2519673],[12.3656858,55.2340267],[12.2714604,55.2366031],[12.2744467,55.272476],[12.2115654,55.2741475],[12.2130078,55.2920322],[12.1815665,55.2928638],[12.183141,55.3107091],[12.2144897,55.3100981],[12.2159927,55.3279764],[12.1214458,55.3303379],[12.1229489,55.3483291],[12.0913942,55.3491574]]],"terms_text":"Stevns Kommune"},{"id":"Surrey-Air_Survey","name":"Surrey Air Survey","type":"tms","template":"http://gravitystorm.dev.openstreetmap.org/surrey/{zoom}/{x}/{y}.png","scaleExtent":[8,19],"polygon":[[[-0.752478,51.0821941],[-0.7595183,51.0856254],[-0.8014342,51.1457917],[-0.8398864,51.1440686],[-0.8357665,51.1802397],[-0.8529549,51.2011266],[-0.8522683,51.2096231],[-0.8495217,51.217903],[-0.8266907,51.2403696],[-0.8120995,51.2469248],[-0.7736474,51.2459577],[-0.7544213,51.2381127],[-0.754078,51.233921],[-0.7446366,51.2333836],[-0.7430693,51.2847178],[-0.751503,51.3069524],[-0.7664376,51.3121032],[-0.7820588,51.3270157],[-0.7815438,51.3388135],[-0.7374268,51.3720456],[-0.7192307,51.3769748],[-0.6795769,51.3847961],[-0.6807786,51.3901523],[-0.6531411,51.3917591],[-0.6301385,51.3905808],[-0.6291085,51.3970074],[-0.6234437,51.3977572],[-0.613144,51.4295552],[-0.6002471,51.4459121],[-0.5867081,51.4445365],[-0.5762368,51.453202],[-0.5626755,51.4523462],[-0.547741,51.4469972],[-0.5372697,51.4448575],[-0.537098,51.4526671],[-0.5439644,51.4545926],[-0.5405312,51.4698865],[-0.5309182,51.4760881],[-0.5091172,51.4744843],[-0.5086022,51.4695657],[-0.4900628,51.4682825],[-0.4526406,51.4606894],[-0.4486924,51.4429316],[-0.4414826,51.4418616],[-0.4418259,51.4369394],[-0.4112702,51.4380095],[-0.4014855,51.4279498],[-0.3807145,51.4262372],[-0.3805428,51.4161749],[-0.3491288,51.4138195],[-0.3274994,51.4037544],[-0.3039818,51.3990424],[-0.3019219,51.3754747],[-0.309475,51.369688],[-0.3111916,51.3529669],[-0.2955704,51.3541462],[-0.2923089,51.3673303],[-0.2850991,51.3680805],[-0.2787476,51.3771891],[-0.2655297,51.3837247],[-0.2411538,51.3847961],[-0.2123147,51.3628288],[-0.2107697,51.3498578],[-0.190857,51.3502867],[-0.1542931,51.3338802],[-0.1496583,51.3057719],[-0.1074296,51.2966491],[-0.0887185,51.3099571],[-0.0878602,51.3220811],[-0.0652009,51.3215448],[-0.0641709,51.3264793],[-0.0519829,51.3263721],[-0.0528412,51.334631],[-0.0330779,51.3430876],[0.0019187,51.3376339],[0.0118751,51.3281956],[0.013935,51.2994398],[0.0202865,51.2994398],[0.0240631,51.3072743],[0.0331611,51.3086694],[0.0455207,51.30545],[0.0523872,51.2877392],[0.0616569,51.2577764],[0.0640602,51.2415518],[0.0462074,51.2126342],[0.0407142,51.2109136],[0.0448341,51.1989753],[0.0494689,51.1997283],[0.0558204,51.1944573],[0.0611419,51.1790713],[0.0623435,51.1542061],[0.0577087,51.1417146],[0.0204582,51.1365447],[-0.0446015,51.1336364],[-0.1566964,51.1352522],[-0.1572114,51.1290043],[-0.2287942,51.1183379],[-0.2473336,51.1183379],[-0.2500802,51.1211394],[-0.299347,51.1137042],[-0.3221779,51.1119799],[-0.3223496,51.1058367],[-0.3596001,51.1019563],[-0.3589135,51.1113333],[-0.3863793,51.1117644],[-0.3869014,51.1062516],[-0.4281001,51.0947174],[-0.4856784,51.0951554],[-0.487135,51.0872266],[-0.5297404,51.0865404],[-0.5302259,51.0789914],[-0.61046,51.076551],[-0.6099745,51.080669],[-0.6577994,51.0792202],[-0.6582849,51.0743394],[-0.6836539,51.0707547],[-0.6997979,51.070831],[-0.7296581,51.0744919],[-0.752478,51.0821941]]]},{"id":"Szeged_2011","name":"Szeged 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}","scaleExtent":[0,20],"polygon":[[[-99.9985439,34.5601834],[-95.55654502453,33.99257450647],[-93.89679027134,33.61039304449],[-93.98468089634,32.04103124103],[-93.41613841587,31.02505269211],[-93.74531484297,29.57268254375],[-96.50492070332,28.23158511753],[-97.36942054453,26.95467452634],[-97.04866958924,25.80530249434],[-99.0734177889,26.32559221139],[-100.76599193149,29.02531904433],[-102.3315436893,29.8433892263],[-103.13354564242,28.88112103669],[-104.2887874222,29.28831477845],[-104.7269783935,29.94815782859],[-104.72696778796,30.23535241761],[-106.53450082091,31.78456647831],[-106.75767043939,31.78457253947],[-106.75766067978,32.04385536686],[-106.61848436611,32.04385159755],[-103.11949492759,32.04375683439],[-103.09544343487,36.50045758762],[-103.05798056071,36.54268645422],[-100.00042146824,36.54222227302],[-99.9985439,34.5601834]]],"terms_url":"https://tnris.org/maps-and-data/online-mapping-services/"},{"id":"tf-landscape","name":"Thunderforest Landscape","type":"tms","template":"https://{switch:a,b,c}.tile.thunderforest.com/landscape/{zoom}/{x}/{y}.png","scaleExtent":[0,22],"terms_url":"http://www.thunderforest.com/terms/","terms_text":"Maps © Thunderforest, Data © OpenStreetMap contributors"},{"id":"lu.geoportail.opendata.topo","name":"Topographical Map geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/topo/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/cartes-topographiques-services-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"Toulouse-Orthophotoplan-2007","name":"Toulouse - Orthophotoplan 2007","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_ortho2007/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1919978,43.6328791],[1.2015377,43.6329729],[1.2011107,43.6554932],[1.2227985,43.6557029],[1.2226231,43.6653353],[1.2275341,43.6653849],[1.2275417,43.6656387],[1.2337568,43.6656883],[1.2337644,43.6650153],[1.2351218,43.6650319],[1.2350913,43.6670729],[1.2443566,43.6671556],[1.2441584,43.6743925],[1.2493973,43.6744256],[1.2493973,43.6746628],[1.2555666,43.6747234],[1.2555742,43.6744532],[1.2569545,43.6744697],[1.2568782,43.678529],[1.2874873,43.6788257],[1.2870803,43.7013229],[1.3088219,43.7014632],[1.3086493,43.7127673],[1.3303262,43.7129544],[1.3300242,43.7305221],[1.3367106,43.7305845],[1.3367322,43.7312235],[1.3734338,43.7310456],[1.3735848,43.7245772],[1.4604504,43.7252947],[1.4607783,43.7028034],[1.4824875,43.7029516],[1.4829828,43.6692071],[1.5046832,43.6693616],[1.5048383,43.6581174],[1.5265475,43.6582656],[1.5266945,43.6470298],[1.548368,43.6471633],[1.5485357,43.6359385],[1.5702172,43.636082],[1.5705123,43.6135777],[1.5488166,43.6134276],[1.549097,43.5909479],[1.5707695,43.5910694],[1.5709373,43.5798341],[1.5793714,43.5798894],[1.5794782,43.5737682],[1.5809119,43.5737792],[1.5810859,43.5573794],[1.5712334,43.5573131],[1.5716504,43.5235497],[1.3984804,43.5222618],[1.3986509,43.5110113],[1.3120959,43.5102543],[1.3118968,43.5215192],[1.2902569,43.5213126],[1.2898637,43.5438168],[1.311517,43.5440133],[1.3113271,43.5552596],[1.3036924,43.5551924],[1.3036117,43.5595099],[1.2955449,43.5594317],[1.2955449,43.5595489],[1.2895595,43.5594473],[1.2892899,43.5775366],[1.2675698,43.5773647],[1.2673973,43.5886141],[1.25355,43.5885047],[1.2533774,43.5956282],[1.2518029,43.5956282],[1.2518029,43.5949409],[1.2350437,43.5947847],[1.2350437,43.5945972],[1.2239572,43.5945972],[1.2239357,43.5994708],[1.2139708,43.599299],[1.2138845,43.6046408],[1.2020647,43.6044846],[1.2019464,43.61048],[1.1924294,43.6103695],[1.1919978,43.6328791]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"id":"Toulouse-Orthophotoplan-2011","name":"Toulouse - Orthophotoplan 2011","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_ortho2011/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"id":"Toulouse-Orthophotoplan-2013","name":"Toulouse - Orthophotoplan 2013","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_2013/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"id":"Toulouse-Orthophotoplan-2015","name":"Toulouse - Orthophotoplan 2015","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_2015/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"id":"Tours-Orthophoto-2008_2010","name":"Tours - Orthophotos 2008-2010","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/tours/{zoom}/{x}/{y}","scaleExtent":[0,20],"polygon":[[[0.5457462,47.465264],[0.54585,47.4608163],[0.5392188,47.4606983],[0.5393484,47.456243],[0.5327959,47.4561003],[0.5329011,47.451565],[0.52619,47.4514013],[0.5265854,47.4424884],[0.5000941,47.4420739],[0.5002357,47.4375835],[0.4936014,47.4374324],[0.4937,47.4329285],[0.4606141,47.4324593],[0.4607248,47.4279827],[0.4541016,47.4278125],[0.454932,47.4053921],[0.4615431,47.4054476],[0.4619097,47.3964924],[0.4684346,47.3966005],[0.4691319,47.3786415],[0.4757125,47.3787609],[0.4762116,47.3652018],[0.4828297,47.3653499],[0.4829611,47.3608321],[0.4763543,47.360743],[0.476654,47.3517263],[0.4700497,47.3516186],[0.4701971,47.3471313],[0.4637503,47.3470104],[0.4571425,47.3424146],[0.4572922,47.3379061],[0.4506741,47.3378081],[0.4508379,47.3333051],[0.4442212,47.3332032],[0.4443809,47.328711],[0.4311392,47.3284977],[0.4316262,47.3150004],[0.4382432,47.3151136],[0.4383815,47.3106174],[0.4714487,47.3111374],[0.4713096,47.3156565],[0.477888,47.3157542],[0.4780733,47.3112802],[0.4846826,47.3113639],[0.4848576,47.3068686],[0.4914359,47.3069803],[0.491745,47.2979733],[0.4851578,47.2978722],[0.4854269,47.2888744],[0.4788485,47.2887697],[0.4791574,47.2797818],[0.4857769,47.2799005],[0.4859107,47.2753885],[0.492539,47.2755029],[0.4926669,47.2710127],[0.4992986,47.2711066],[0.4994296,47.2666116],[0.5192658,47.2669245],[0.5194225,47.2624231],[0.5260186,47.2625205],[0.5258735,47.2670183],[0.5456972,47.2673383],[0.5455537,47.2718283],[0.5587737,47.2720366],[0.5586259,47.2765185],[0.5652252,47.2766278],[0.5650848,47.2811206],[0.5716753,47.2812285],[0.5715223,47.2857217],[0.5781436,47.2858299],[0.5779914,47.2903294],[0.5846023,47.2904263],[0.5843076,47.2994231],[0.597499,47.2996094],[0.5976637,47.2951375],[0.6571596,47.2960036],[0.6572988,47.2915091],[0.6705019,47.2917186],[0.6703475,47.2962082],[0.6836175,47.2963688],[0.6834322,47.3008929],[0.690062,47.3009558],[0.6899241,47.3054703],[0.7362019,47.3061157],[0.7360848,47.3106063],[0.7559022,47.3108935],[0.7557718,47.315392],[0.7623755,47.3154716],[0.7622314,47.3199941],[0.7754911,47.3201546],[0.77497,47.3388218],[0.7745786,47.351628],[0.7680363,47.3515901],[0.767589,47.3605298],[0.7742443,47.3606238],[0.7733465,47.3921266],[0.7667434,47.3920195],[0.7664411,47.4010837],[0.7730647,47.4011115],[0.7728868,47.4101297],[0.7661849,47.4100226],[0.7660267,47.4145044],[0.7527613,47.4143038],[0.7529788,47.4098086],[0.7462373,47.4097016],[0.7459424,47.4232208],[0.7392324,47.4231451],[0.738869,47.4366116],[0.7323267,47.4365171],[0.7321869,47.4410556],[0.7255048,47.44098],[0.7254209,47.4453479],[0.7318793,47.4454803],[0.7318514,47.4501126],[0.7384496,47.450226],[0.7383098,47.454631],[0.7449359,47.4547444],[0.7443209,47.4771985],[0.7310685,47.4769717],[0.7309008,47.4815445],[0.7176205,47.4812611],[0.7177883,47.4768394],[0.69777,47.4764993],[0.6980496,47.4719827],[0.6914514,47.4718882],[0.6917309,47.4630241],[0.6851048,47.4629295],[0.684937,47.4673524],[0.678255,47.4673335],[0.6779754,47.4762158],[0.6714051,47.4761592],[0.6710417,47.4881952],[0.6577334,47.4879685],[0.6578173,47.48504],[0.6511911,47.4848322],[0.6514707,47.4758568],[0.6448166,47.4757245],[0.6449284,47.4712646],[0.6117976,47.4707543],[0.6118815,47.4663129],[0.6052833,47.4661239],[0.6054231,47.4616631],[0.5988808,47.4615497],[0.5990206,47.4570886],[0.572488,47.4566916],[0.5721805,47.4656513],[0.5457462,47.465264]]],"terms_url":"http://wiki.openstreetmap.org/wiki/Tours/Orthophoto","terms_text":"Orthophoto Tour(s) Plus 2008"},{"id":"Tours-Orthophoto-2013","name":"Tours - Orthophotos 2013","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/tours_2013/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[0.427093505859375,47.26199018174824],[0.427093505859375,47.50096732311069],[0.814361572265625,47.50096732311069],[0.814361572265625,47.26199018174824],[0.427093505859375,47.26199018174824]]],"terms_url":"http://wiki.openstreetmap.org/wiki/Tours/Orthophoto","terms_text":"Orthophoto Tour(s)plus 2013"},{"id":"US_Forest_Service_roads","name":"U.S. Forest Service roads","type":"tms","template":"http://osm.cycle.travel/forest/{zoom}/{x}/{y}.png","scaleExtent":[0,19],"polygon":[[[-124.7617886,48.4130148],[-124.6059492,45.90245],[-124.9934269,40.0557614],[-122.5369737,36.8566086],[-119.9775867,33.0064099],[-117.675935,32.4630223],[-114.8612307,32.4799891],[-111.0089311,31.336015],[-108.1992687,31.3260016],[-108.1871123,31.7755116],[-106.5307225,31.7820947],[-106.4842052,31.7464455],[-106.429317,31.7520583],[-106.2868855,31.5613291],[-106.205248,31.446704],[-105.0205259,30.5360988],[-104.5881916,29.6997856],[-103.2518856,28.8908685],[-102.7173632,29.3920567],[-102.1513983,29.7475702],[-101.2552871,29.4810523],[-100.0062436,28.0082173],[-99.2351068,26.4475962],[-98.0109067,25.9928035],[-97.435024,25.8266009],[-96.9555259,25.9821589],[-96.8061741,27.7978168],[-95.5563349,28.5876066],[-93.7405308,29.4742093],[-90.9028456,28.8564513],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-84.0187909,28.9961781],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-79.8901116,26.8550713],[-80.0245309,32.0161282],[-75.4147385,35.0531894],[-74.0211163,39.5727927],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8489304,43.2619916],[-66.9452845,44.7104937],[-67.7596632,47.0990024],[-69.2505131,47.5122328],[-70.4614886,46.2176574],[-71.412273,45.254878],[-72.0222508,45.0059846],[-75.0798841,44.9802854],[-76.9023061,43.8024568],[-78.7623935,43.6249578],[-79.15798,43.4462589],[-79.0060087,42.8005317],[-82.662475,41.6889458],[-82.1761642,43.588535],[-83.2813977,46.138853],[-87.5064535,48.0142702],[-88.3492194,48.2963271],[-89.4353148,47.9837822],[-93.9981078,49.0067142],[-95.1105379,49.412004],[-96.0131199,49.0060547],[-123.3228926,49.0042878],[-123.2275233,48.1849927],[-124.7617886,48.4130148]],[[-160.5787616,22.5062947],[-160.5782192,21.4984647],[-158.7470604,21.2439843],[-157.5083185,20.995803],[-155.9961942,18.7790194],[-154.6217803,18.7586966],[-154.6890176,19.8805722],[-156.2927622,21.2225888],[-157.5047384,21.9984962],[-159.0093692,22.5070181],[-160.5787616,22.5062947]],[[-167.1571546,68.721974],[-164.8553982,67.0255078],[-168.002195,66.0017503],[-169.0087448,66.001546],[-169.0075381,64.9987675],[-172.5143281,63.8767267],[-173.8197023,59.74014],[-162.5018149,58.0005815],[-160.0159024,58.0012389],[-160.0149725,57.000035],[-160.5054788,56.9999017],[-165.8092575,54.824847],[-178.000097,52.2446469],[-177.9992996,51.2554252],[-171.4689067,51.8215329],[-162.40251,53.956664],[-159.0075717,55.002502],[-158.0190709,55.0027849],[-151.9963213,55.9991902],[-151.500341,57.9987853],[-151.5012894,58.9919816],[-138.5159989,58.9953194],[-138.5150471,57.9986434],[-133.9948193,54.0031685],[-130.0044418,54.0043387],[-130.0070826,57.0000507],[-131.975877,56.9995156],[-135.1229873,59.756601],[-138.0071813,59.991805],[-139.1715881,60.4127229],[-140.9874011,61.0118551],[-140.9683975,69.9535069],[-156.176891,71.5633329],[-160.413634,70.7397728],[-163.0218273,69.9707435],[-164.9717003,68.994689],[-167.1571546,68.721974]]]},{"id":"Zuerich-zh_uebersichtsplan-tms","name":"Übersichtsplan Zürich","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_uebersichtsplan/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[0,21],"polygon":[[[8.4482,47.321],[8.4482,47.4339],[8.6248,47.4339],[8.6248,47.321],[8.4482,47.321]]],"terms_text":"Stadt Zürich Open Government Data"},{"id":"USGS-Large_Scale","name":"USGS Large Scale Imagery","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.us/usgs_large_scale/{zoom}/{x}/{y}.jpg","scaleExtent":[12,20],"polygon":[[[-123.2549305,48.7529029],[-123.2549305,48.5592263],[-123.192224,48.5592263],[-123.192224,48.4348366],[-122.9419646,48.4348366],[-122.9419646,48.3720812],[-122.8806229,48.3720812],[-122.8806229,48.3094763],[-122.8167566,48.3094763],[-122.8167566,48.1904587],[-123.0041133,48.1904587],[-123.0041133,48.1275918],[-123.058416,48.1275918],[-123.058416,48.190514],[-123.254113,48.190514],[-123.254113,48.1274982],[-123.3706593,48.1274982],[-123.3706593,48.1908403],[-124.0582632,48.1908403],[-124.0582632,48.253442],[-124.1815163,48.253442],[-124.1815163,48.3164666],[-124.4319117,48.3164666],[-124.4319117,48.3782613],[-124.5564618,48.3782613],[-124.5564618,48.4408305],[-124.7555107,48.4408305],[-124.7555107,48.1914986],[-124.8185282,48.1914986],[-124.8185282,48.1228381],[-124.7552951,48.1228381],[-124.7552951,47.5535253],[-124.3812108,47.5535253],[-124.3812108,47.1218696],[-124.1928897,47.1218696],[-124.1928897,43.7569431],[-124.4443382,43.7569431],[-124.4443382,43.1425556],[-124.6398855,43.1425556],[-124.6398855,42.6194503],[-124.4438525,42.6194503],[-124.4438525,39.8080662],[-123.8815685,39.8080662],[-123.8815685,39.1102825],[-123.75805,39.1102825],[-123.75805,38.4968799],[-123.2702803,38.4968799],[-123.2702803,37.9331905],[-122.8148084,37.9331905],[-122.8148084,37.8019606],[-122.5664316,37.8019606],[-122.5664316,36.9319611],[-121.8784026,36.9319611],[-121.8784026,36.6897596],[-122.0034748,36.6897596],[-122.0034748,36.4341056],[-121.9414159,36.4341056],[-121.9414159,35.9297636],[-121.5040977,35.9297636],[-121.5040977,35.8100273],[-121.3790276,35.8100273],[-121.3790276,35.4239164],[-120.9426515,35.4239164],[-120.9426515,35.1849683],[-120.8171978,35.1849683],[-120.8171978,35.1219894],[-120.6918447,35.1219894],[-120.6918447,34.4966794],[-120.5045898,34.4966794],[-120.5045898,34.4339651],[-120.0078775,34.4339651],[-120.0078775,34.3682626],[-119.5283517,34.3682626],[-119.5283517,34.0576434],[-119.0060985,34.0576434],[-119.0060985,33.9975267],[-118.5046259,33.9975267],[-118.5046259,33.8694631],[-118.4413209,33.8694631],[-118.4413209,33.6865253],[-118.066912,33.6865253],[-118.066912,33.3063832],[-117.5030045,33.3063832],[-117.5030045,33.0500337],[-117.3188195,33.0500337],[-117.3188195,32.6205888],[-117.1917023,32.6205888],[-117.1917023,32.4974566],[-116.746496,32.4974566],[-116.746496,32.5609161],[-115.9970138,32.5609161],[-115.9970138,32.6264942],[-114.8808125,32.6264942],[-114.8808125,32.4340796],[-114.6294474,32.4340796],[-114.6294474,32.3731636],[-114.4447437,32.3731636],[-114.4447437,32.3075418],[-114.2557628,32.3075418],[-114.2557628,32.2444561],[-114.0680274,32.2444561],[-114.0680274,32.1829113],[-113.8166499,32.1829113],[-113.8166499,32.1207622],[-113.6307421,32.1207622],[-113.6307421,32.0565099],[-113.4417495,32.0565099],[-113.4417495,31.9984372],[-113.2546027,31.9984372],[-113.2546027,31.9325434],[-113.068072,31.9325434],[-113.068072,31.8718062],[-112.8161105,31.8718062],[-112.8161105,31.8104171],[-112.6308756,31.8104171],[-112.6308756,31.7464723],[-112.4418918,31.7464723],[-112.4418918,31.6856001],[-112.257192,31.6856001],[-112.257192,31.6210352],[-112.0033787,31.6210352],[-112.0033787,31.559584],[-111.815619,31.559584],[-111.815619,31.4970238],[-111.6278586,31.4970238],[-111.6278586,31.4339867],[-111.4418978,31.4339867],[-111.4418978,31.3733859],[-111.2559708,31.3733859],[-111.2559708,31.3113225],[-108.1845822,31.3113225],[-108.1845822,31.7459502],[-106.5065055,31.7459502],[-106.5065055,31.6842308],[-106.3797265,31.6842308],[-106.3797265,31.621752],[-106.317434,31.621752],[-106.317434,31.4968167],[-106.2551769,31.4968167],[-106.2551769,31.4344889],[-106.1924698,31.4344889],[-106.1924698,31.3721296],[-106.0039212,31.3721296],[-106.0039212,31.309328],[-105.9416582,31.309328],[-105.9416582,31.2457547],[-105.8798174,31.2457547],[-105.8798174,31.1836194],[-105.8162349,31.1836194],[-105.8162349,31.1207155],[-105.6921198,31.1207155],[-105.6921198,31.0584835],[-105.6302881,31.0584835],[-105.6302881,30.9328271],[-105.5044418,30.9328271],[-105.5044418,30.8715864],[-105.4412973,30.8715864],[-105.4412973,30.808463],[-105.3781497,30.808463],[-105.3781497,30.7471828],[-105.1904658,30.7471828],[-105.1904658,30.6843231],[-105.1286244,30.6843231],[-105.1286244,30.6199737],[-105.0036504,30.6199737],[-105.0036504,30.5589058],[-104.9417962,30.5589058],[-104.9417962,30.4963236],[-104.8782018,30.4963236],[-104.8782018,30.3098261],[-104.8155257,30.3098261],[-104.8155257,30.2478305],[-104.7536079,30.2478305],[-104.7536079,29.9353916],[-104.690949,29.9353916],[-104.690949,29.8090156],[-104.6291301,29.8090156],[-104.6291301,29.6843577],[-104.5659869,29.6843577],[-104.5659869,29.6223459],[-104.5037188,29.6223459],[-104.5037188,29.5595436],[-104.4410072,29.5595436],[-104.4410072,29.4974832],[-104.2537551,29.4974832],[-104.2537551,29.3716718],[-104.1291984,29.3716718],[-104.1291984,29.3091621],[-104.0688737,29.3091621],[-104.0688737,29.2467276],[-103.8187309,29.2467276],[-103.8187309,29.1843076],[-103.755736,29.1843076],[-103.755736,29.1223174],[-103.5667542,29.1223174],[-103.5667542,29.0598119],[-103.5049819,29.0598119],[-103.5049819,28.9967506],[-103.3165753,28.9967506],[-103.3165753,28.9346923],[-103.0597572,28.9346923],[-103.0597572,29.0592965],[-102.9979694,29.0592965],[-102.9979694,29.1212855],[-102.9331397,29.1212855],[-102.9331397,29.1848575],[-102.8095989,29.1848575],[-102.8095989,29.2526154],[-102.8701345,29.2526154],[-102.8701345,29.308096],[-102.8096681,29.308096],[-102.8096681,29.3715484],[-102.7475655,29.3715484],[-102.7475655,29.5581899],[-102.684554,29.5581899],[-102.684554,29.6847655],[-102.4967764,29.6847655],[-102.4967764,29.7457694],[-102.3086647,29.7457694],[-102.3086647,29.8086627],[-102.1909323,29.8086627],[-102.1909323,29.7460097],[-101.5049914,29.7460097],[-101.5049914,29.6846777],[-101.3805796,29.6846777],[-101.3805796,29.5594459],[-101.3175057,29.5594459],[-101.3175057,29.4958934],[-101.1910075,29.4958934],[-101.1910075,29.4326115],[-101.067501,29.4326115],[-101.067501,29.308808],[-100.9418897,29.308808],[-100.9418897,29.2456231],[-100.8167271,29.2456231],[-100.8167271,29.1190449],[-100.7522672,29.1190449],[-100.7522672,29.0578214],[-100.6925358,29.0578214],[-100.6925358,28.8720431],[-100.6290158,28.8720431],[-100.6290158,28.8095363],[-100.5679901,28.8095363],[-100.5679901,28.622554],[-100.5040411,28.622554],[-100.5040411,28.5583804],[-100.4421832,28.5583804],[-100.4421832,28.4968266],[-100.379434,28.4968266],[-100.379434,28.3092865],[-100.3171942,28.3092865],[-100.3171942,28.1835681],[-100.254483,28.1835681],[-100.254483,28.1213885],[-100.1282282,28.1213885],[-100.1282282,28.059215],[-100.0659537,28.059215],[-100.0659537,27.9966087],[-100.0023855,27.9966087],[-100.0023855,27.9332152],[-99.9426497,27.9332152],[-99.9426497,27.7454658],[-99.816851,27.7454658],[-99.816851,27.6834301],[-99.7541346,27.6834301],[-99.7541346,27.6221543],[-99.6291629,27.6221543],[-99.6291629,27.5588977],[-99.5672838,27.5588977],[-99.5672838,27.4353752],[-99.5041798,27.4353752],[-99.5041798,27.3774021],[-99.5671796,27.3774021],[-99.5671796,27.2463726],[-99.504975,27.2463726],[-99.504975,26.9965649],[-99.4427427,26.9965649],[-99.4427427,26.872803],[-99.3800633,26.872803],[-99.3800633,26.8068179],[-99.3190684,26.8068179],[-99.3190684,26.7473614],[-99.2537541,26.7473614],[-99.2537541,26.6210068],[-99.1910617,26.6210068],[-99.1910617,26.4956737],[-99.1300639,26.4956737],[-99.1300639,26.3713808],[-99.0029473,26.3713808],[-99.0029473,26.3093836],[-98.816572,26.3093836],[-98.816572,26.2457762],[-98.6920082,26.2457762],[-98.6920082,26.1837096],[-98.4440896,26.1837096],[-98.4440896,26.1217217],[-98.3823181,26.1217217],[-98.3823181,26.0596488],[-98.2532707,26.0596488],[-98.2532707,25.9986871],[-98.0109084,25.9986871],[-98.0109084,25.9932255],[-97.6932319,25.9932255],[-97.6932319,25.9334103],[-97.6313904,25.9334103],[-97.6313904,25.8695893],[-97.5046779,25.8695893],[-97.5046779,25.8073488],[-97.3083401,25.8073488],[-97.3083401,25.8731159],[-97.2456326,25.8731159],[-97.2456326,25.9353731],[-97.1138939,25.9353731],[-97.1138939,27.6809179],[-97.0571035,27.6809179],[-97.0571035,27.8108242],[-95.5810766,27.8108242],[-95.5810766,28.7468827],[-94.271041,28.7468827],[-94.271041,29.5594076],[-92.5029947,29.5594076],[-92.5029947,29.4974754],[-91.8776216,29.4974754],[-91.8776216,29.3727013],[-91.378418,29.3727013],[-91.378418,29.2468326],[-91.3153953,29.2468326],[-91.3153953,29.1844301],[-91.1294702,29.1844301],[-91.1294702,29.1232559],[-91.0052632,29.1232559],[-91.0052632,28.9968437],[-89.4500159,28.9968437],[-89.4500159,28.8677422],[-88.8104309,28.8677422],[-88.8104309,30.1841864],[-85.8791527,30.1841864],[-85.8791527,29.5455038],[-84.8368083,29.5455038],[-84.8368083,29.6225158],[-84.7482786,29.6225158],[-84.7482786,29.683624],[-84.685894,29.683624],[-84.685894,29.7468386],[-83.6296975,29.7468386],[-83.6296975,29.4324361],[-83.3174937,29.4324361],[-83.3174937,29.0579442],[-82.879659,29.0579442],[-82.879659,27.7453529],[-82.8182822,27.7453529],[-82.8182822,26.9290868],[-82.3796782,26.9290868],[-82.3796782,26.3694183],[-81.8777106,26.3694183],[-81.8777106,25.805971],[-81.5036862,25.805971],[-81.5036862,25.7474753],[-81.4405462,25.7474753],[-81.4405462,25.6851489],[-81.3155883,25.6851489],[-81.3155883,25.5600985],[-81.2538534,25.5600985],[-81.2538534,25.4342361],[-81.1902012,25.4342361],[-81.1902012,25.1234341],[-81.1288133,25.1234341],[-81.1288133,25.0619389],[-81.0649231,25.0619389],[-81.0649231,24.8157807],[-81.6289469,24.8157807],[-81.6289469,24.7538367],[-81.6907173,24.7538367],[-81.6907173,24.6899374],[-81.8173189,24.6899374],[-81.8173189,24.6279161],[-82.1910041,24.6279161],[-82.1910041,24.496294],[-81.6216596,24.496294],[-81.6216596,24.559484],[-81.372006,24.559484],[-81.372006,24.6220687],[-81.0593278,24.6220687],[-81.0593278,24.684826],[-80.9347147,24.684826],[-80.9347147,24.7474828],[-80.7471081,24.7474828],[-80.7471081,24.8100618],[-80.3629898,24.8100618],[-80.3629898,25.1175858],[-80.122344,25.1175858],[-80.122344,25.7472357],[-80.0588458,25.7472357],[-80.0588458,26.3708251],[-79.995837,26.3708251],[-79.995837,26.9398003],[-80.0587265,26.9398003],[-80.0587265,27.1277466],[-80.1226251,27.1277466],[-80.1226251,27.2534279],[-80.1846956,27.2534279],[-80.1846956,27.3781229],[-80.246175,27.3781229],[-80.246175,27.5658729],[-80.3094768,27.5658729],[-80.3094768,27.7530311],[-80.3721485,27.7530311],[-80.3721485,27.8774451],[-80.4351457,27.8774451],[-80.4351457,28.0033366],[-80.4966078,28.0033366],[-80.4966078,28.1277326],[-80.5587159,28.1277326],[-80.5587159,28.3723509],[-80.4966335,28.3723509],[-80.4966335,29.5160326],[-81.1213644,29.5160326],[-81.1213644,31.6846966],[-80.6018723,31.6846966],[-80.6018723,32.2475309],[-79.4921024,32.2475309],[-79.4921024,32.9970261],[-79.1116488,32.9970261],[-79.1116488,33.3729457],[-78.6153621,33.3729457],[-78.6153621,33.8097638],[-77.9316963,33.8097638],[-77.9316963,33.8718243],[-77.8692252,33.8718243],[-77.8692252,34.0552454],[-77.6826392,34.0552454],[-77.6826392,34.2974598],[-77.2453509,34.2974598],[-77.2453509,34.5598585],[-76.4973277,34.5598585],[-76.4973277,34.622796],[-76.4337602,34.622796],[-76.4337602,34.6849285],[-76.373212,34.6849285],[-76.373212,34.7467674],[-76.3059364,34.7467674],[-76.3059364,34.808551],[-76.2468017,34.808551],[-76.2468017,34.8728418],[-76.1825922,34.8728418],[-76.1825922,34.9335332],[-76.120814,34.9335332],[-76.120814,34.9952359],[-75.9979015,34.9952359],[-75.9979015,35.0578182],[-75.870338,35.0578182],[-75.870338,35.1219097],[-75.7462194,35.1219097],[-75.7462194,35.1818911],[-75.4929694,35.1818911],[-75.4929694,35.3082988],[-75.4325662,35.3082988],[-75.4325662,35.7542495],[-75.4969907,35.7542495],[-75.4969907,37.8105602],[-75.3082972,37.8105602],[-75.3082972,37.8720088],[-75.245601,37.8720088],[-75.245601,37.9954849],[-75.1828751,37.9954849],[-75.1828751,38.0585079],[-75.1184793,38.0585079],[-75.1184793,38.2469091],[-75.0592098,38.2469091],[-75.0592098,38.3704316],[-74.9948111,38.3704316],[-74.9948111,38.8718417],[-74.4878252,38.8718417],[-74.4878252,39.3089428],[-74.1766317,39.3089428],[-74.1766317,39.6224653],[-74.0567045,39.6224653],[-74.0567045,39.933178],[-73.9959035,39.933178],[-73.9959035,40.1854852],[-73.9341593,40.1854852],[-73.9341593,40.4959486],[-73.8723024,40.4959486],[-73.8723024,40.5527135],[-71.8074506,40.5527135],[-71.8074506,41.3088005],[-70.882512,41.3088005],[-70.882512,41.184978],[-70.7461947,41.184978],[-70.7461947,41.3091865],[-70.4337553,41.3091865],[-70.4337553,41.4963885],[-69.9334281,41.4963885],[-69.9334281,41.6230802],[-69.869857,41.6230802],[-69.869857,41.8776895],[-69.935791,41.8776895],[-69.935791,42.0032342],[-69.9975823,42.0032342],[-69.9975823,42.0650191],[-70.0606103,42.0650191],[-70.0606103,42.1294348],[-70.5572884,42.1294348],[-70.5572884,43.2487079],[-70.4974097,43.2487079],[-70.4974097,43.3092194],[-70.3704249,43.3092194],[-70.3704249,43.371963],[-70.3085701,43.371963],[-70.3085701,43.4969879],[-70.183921,43.4969879],[-70.183921,43.6223531],[-70.057583,43.6223531],[-70.057583,43.6850173],[-69.7455247,43.6850173],[-69.7455247,43.7476571],[-69.2472845,43.7476571],[-69.2472845,43.8107035],[-69.0560701,43.8107035],[-69.0560701,43.8717247],[-68.9950522,43.8717247],[-68.9950522,43.9982022],[-68.4963672,43.9982022],[-68.4963672,44.0597368],[-68.3081038,44.0597368],[-68.3081038,44.122137],[-68.1851802,44.122137],[-68.1851802,44.3081382],[-67.9956019,44.3081382],[-67.9956019,44.3727489],[-67.8103041,44.3727489],[-67.8103041,44.435178],[-67.4965289,44.435178],[-67.4965289,44.4968776],[-67.37102,44.4968776],[-67.37102,44.5600642],[-67.1848753,44.5600642],[-67.1848753,44.6213345],[-67.1221208,44.6213345],[-67.1221208,44.6867918],[-67.059365,44.6867918],[-67.059365,44.7473657],[-66.9311098,44.7473657],[-66.9311098,44.9406566],[-66.994683,44.9406566],[-66.994683,45.0024514],[-67.0595847,45.0024514],[-67.0595847,45.1273377],[-67.1201974,45.1273377],[-67.1201974,45.1910115],[-67.2469811,45.1910115],[-67.2469811,45.253442],[-67.3177546,45.253442],[-67.3177546,45.1898369],[-67.370749,45.1898369],[-67.370749,45.2534001],[-67.4326888,45.2534001],[-67.4326888,45.3083409],[-67.3708571,45.3083409],[-67.3708571,45.4396986],[-67.4305573,45.4396986],[-67.4305573,45.4950095],[-67.37099,45.4950095],[-67.37099,45.6264543],[-67.6214982,45.6264543],[-67.6214982,45.6896133],[-67.683828,45.6896133],[-67.683828,45.753259],[-67.7462097,45.753259],[-67.7462097,47.1268165],[-67.8700141,47.1268165],[-67.8700141,47.1900278],[-67.9323803,47.1900278],[-67.9323803,47.2539678],[-67.9959387,47.2539678],[-67.9959387,47.3149737],[-68.1206676,47.3149737],[-68.1206676,47.3780823],[-68.4423175,47.3780823],[-68.4423175,47.3166082],[-68.6314305,47.3166082],[-68.6314305,47.2544676],[-68.9978037,47.2544676],[-68.9978037,47.439895],[-69.0607223,47.439895],[-69.0607223,47.5047558],[-69.2538122,47.5047558],[-69.2538122,47.4398084],[-69.3179284,47.4398084],[-69.3179284,47.378601],[-69.4438546,47.378601],[-69.4438546,47.3156274],[-69.5038204,47.3156274],[-69.5038204,47.2525839],[-69.5667838,47.2525839],[-69.5667838,47.1910884],[-69.6303478,47.1910884],[-69.6303478,47.128701],[-69.6933103,47.128701],[-69.6933103,47.0654307],[-69.7557063,47.0654307],[-69.7557063,47.0042751],[-69.8180391,47.0042751],[-69.8180391,46.9415344],[-69.8804023,46.9415344],[-69.8804023,46.8792519],[-69.9421674,46.8792519],[-69.9421674,46.8177399],[-70.0063088,46.8177399],[-70.0063088,46.6920295],[-70.0704265,46.6920295],[-70.0704265,46.4425926],[-70.1945902,46.4425926],[-70.1945902,46.3785887],[-70.2562047,46.3785887],[-70.2562047,46.3152628],[-70.3203651,46.3152628],[-70.3203651,46.0651209],[-70.3814988,46.0651209],[-70.3814988,45.93552],[-70.3201618,45.93552],[-70.3201618,45.879479],[-70.4493131,45.879479],[-70.4493131,45.7538713],[-70.5070021,45.7538713],[-70.5070021,45.6916912],[-70.6316642,45.6916912],[-70.6316642,45.6291619],[-70.7575538,45.6291619],[-70.7575538,45.4414685],[-70.8809878,45.4414685],[-70.8809878,45.3780612],[-71.13328,45.3780612],[-71.13328,45.3151452],[-71.3830282,45.3151452],[-71.3830282,45.253416],[-71.5076448,45.253416],[-71.5076448,45.0655726],[-73.9418929,45.0655726],[-73.9418929,45.0031242],[-74.7469725,45.0031242],[-74.7469725,45.0649003],[-74.8800964,45.0649003],[-74.8800964,45.0029023],[-75.0662455,45.0029023],[-75.0662455,44.9415167],[-75.2539363,44.9415167],[-75.2539363,44.8776043],[-75.3789648,44.8776043],[-75.3789648,44.8153462],[-75.4431283,44.8153462],[-75.4431283,44.7536053],[-75.5666566,44.7536053],[-75.5666566,44.6909879],[-75.6290205,44.6909879],[-75.6290205,44.6284958],[-75.7540484,44.6284958],[-75.7540484,44.566385],[-75.817312,44.566385],[-75.817312,44.5028932],[-75.8799549,44.5028932],[-75.8799549,44.3784946],[-76.1300319,44.3784946],[-76.1300319,44.3159227],[-76.1926961,44.3159227],[-76.1926961,44.2534378],[-76.3182619,44.2534378],[-76.3182619,44.1916726],[-76.3792975,44.1916726],[-76.3792975,44.0653733],[-76.4427584,44.0653733],[-76.4427584,43.9963825],[-76.317027,43.9963825],[-76.317027,43.9414581],[-76.5076611,43.9414581],[-76.5076611,43.8723335],[-76.3829974,43.8723335],[-76.3829974,43.8091872],[-76.2534102,43.8091872],[-76.2534102,43.5665222],[-76.5064833,43.5665222],[-76.5064833,43.5033881],[-76.6331208,43.5033881],[-76.6331208,43.4432252],[-76.6951085,43.4432252],[-76.6951085,43.3786858],[-76.8177798,43.3786858],[-76.8177798,43.318066],[-77.682,43.318066],[-77.682,43.3789376],[-78.0565883,43.3789376],[-78.0565883,43.4396918],[-78.4389748,43.4396918],[-78.4389748,43.3794382],[-78.8803396,43.3794382],[-78.8803396,43.3149724],[-79.1298858,43.3149724],[-79.1298858,43.2429286],[-79.0669615,43.2429286],[-79.0669615,43.1299931],[-79.1298858,43.1299931],[-79.1298858,43.0577305],[-79.071264,43.0577305],[-79.071264,42.9294906],[-78.943264,42.9294906],[-78.943264,42.7542165],[-79.069439,42.7542165],[-79.069439,42.6941622],[-79.133439,42.6941622],[-79.133439,42.6296973],[-79.1947499,42.6296973],[-79.1947499,42.5663538],[-79.3786827,42.5663538],[-79.3786827,42.5033425],[-79.4442961,42.5033425],[-79.4442961,42.4410614],[-79.5679936,42.4410614],[-79.5679936,42.3775264],[-79.6906154,42.3775264],[-79.6906154,42.3171086],[-79.8164642,42.3171086],[-79.8164642,42.2534481],[-80.0052373,42.2534481],[-80.0052373,42.1909188],[-80.1916829,42.1909188],[-80.1916829,42.1272555],[-80.3167992,42.1272555],[-80.3167992,42.0669857],[-80.5063234,42.0669857],[-80.5063234,42.0034331],[-80.6930471,42.0034331],[-80.6930471,41.9415141],[-80.9440403,41.9415141],[-80.9440403,41.8781193],[-81.1942729,41.8781193],[-81.1942729,41.8166455],[-81.3190089,41.8166455],[-81.3190089,41.7545453],[-81.4418435,41.7545453],[-81.4418435,41.690965],[-81.5053523,41.690965],[-81.5053523,41.6301643],[-82.7470081,41.6301643],[-82.7470081,41.7536942],[-82.8839135,41.7536942],[-82.8839135,41.5656075],[-82.9957195,41.5656075],[-82.9957195,41.6270375],[-83.1257796,41.6270375],[-83.1257796,41.6878411],[-83.2474733,41.6878411],[-83.2474733,41.7536942],[-83.3737305,41.7536942],[-83.3737305,41.809276],[-83.3106019,41.809276],[-83.3106019,41.8716064],[-83.2474733,41.8716064],[-83.2474733,41.9361393],[-83.1843447,41.9361393],[-83.1843447,41.9960851],[-83.1207681,41.9960851],[-83.1207681,42.2464812],[-83.0589194,42.2464812],[-83.0589194,42.3089555],[-82.8685328,42.3089555],[-82.8685328,42.3717652],[-82.8072219,42.3717652],[-82.8072219,42.558553],[-82.7553745,42.558553],[-82.7553745,42.4954945],[-82.5599041,42.4954945],[-82.5599041,42.558553],[-82.4967755,42.558553],[-82.4967755,42.6833607],[-82.4328863,42.6833607],[-82.4328863,42.9342196],[-82.3700552,42.9342196],[-82.3700552,43.0648071],[-82.4328863,43.0648071],[-82.4328863,43.1917566],[-82.4947464,43.1917566],[-82.4947464,43.5034627],[-82.557133,43.5034627],[-82.557133,43.8160901],[-82.6197884,43.8160901],[-82.6197884,43.9422098],[-82.6839499,43.9422098],[-82.6839499,44.0022641],[-82.7465346,44.0022641],[-82.7465346,44.0670545],[-82.8708696,44.0670545],[-82.8708696,44.1291935],[-83.008517,44.1291935],[-83.008517,44.0664786],[-83.1336086,44.0664786],[-83.1336086,44.0053949],[-83.2414522,44.0053949],[-83.2414522,44.9962034],[-83.1806112,44.9962034],[-83.1806112,45.067302],[-83.2455172,45.067302],[-83.2455172,45.1287382],[-83.3065878,45.1287382],[-83.3065878,45.2551509],[-83.3706087,45.2551509],[-83.3706087,45.3165923],[-83.4325644,45.3165923],[-83.4325644,45.3792105],[-83.6178415,45.3792105],[-83.6178415,45.4419665],[-83.8084291,45.4419665],[-83.8084291,45.5036189],[-84.0550718,45.5036189],[-84.0550718,45.5647907],[-84.1235181,45.5647907],[-84.1235181,45.6287845],[-84.1807534,45.6287845],[-84.1807534,45.6914688],[-84.3111554,45.6914688],[-84.3111554,45.9337076],[-83.8209974,45.9337076],[-83.8209974,45.8725113],[-83.4968086,45.8725113],[-83.4968086,45.9337076],[-83.4338066,45.9337076],[-83.4338066,46.0016863],[-83.4962697,46.0016863],[-83.4962697,46.0668178],[-83.5599956,46.0668178],[-83.5599956,46.1261576],[-83.9954558,46.1261576],[-83.9954558,46.1931747],[-84.0591816,46.1931747],[-84.0591816,46.3814972],[-84.1152614,46.3814972],[-84.1152614,46.4953584],[-84.0591816,46.4953584],[-84.0591816,46.5682653],[-84.2579545,46.5682653],[-84.2579545,46.5051232],[-84.3071879,46.5051232],[-84.3071879,46.5682653],[-84.4415364,46.5682653],[-84.4415364,46.504525],[-84.9965729,46.504525],[-84.9965729,46.6842882],[-84.9298158,46.6842882],[-84.9298158,46.818077],[-85.3165894,46.818077],[-85.3165894,46.7535825],[-87.5562645,46.7535825],[-87.5562645,47.4407371],[-87.6825361,47.4407371],[-87.6825361,47.5035554],[-88.2560738,47.5035554],[-88.2560738,47.4433716],[-88.4417419,47.4433716],[-88.4417419,47.3789949],[-88.50683,47.3789949],[-88.50683,47.3153881],[-88.6312821,47.3153881],[-88.6312821,47.2539782],[-88.7569636,47.2539782],[-88.7569636,47.1934682],[-88.8838253,47.1934682],[-88.8838253,47.1284735],[-88.9434208,47.1284735],[-88.9434208,47.0662127],[-89.0708726,47.0662127],[-89.0708726,47.0026826],[-89.2565553,47.0026826],[-89.2565553,46.9410806],[-90.3677669,46.9410806],[-90.3677669,47.6844827],[-90.3069978,47.6844827],[-90.3069978,47.7460174],[-89.994859,47.7460174],[-89.994859,47.8082719],[-89.8048615,47.8082719],[-89.8048615,47.8700562],[-89.6797699,47.8700562],[-89.6797699,47.9339637],[-89.4933757,47.9339637],[-89.4933757,47.9957956],[-89.4284697,47.9957956],[-89.4284697,48.0656377],[-89.9932739,48.0656377],[-89.9932739,48.1282966],[-90.7455933,48.1282966],[-90.7455933,48.1893056],[-90.8087291,48.1893056],[-90.8087291,48.2522065],[-91.067763,48.2522065],[-91.067763,48.1916658],[-91.1946247,48.1916658],[-91.1946247,48.1279027],[-91.6814196,48.1279027],[-91.6814196,48.2525994],[-91.9321927,48.2525994],[-91.9321927,48.3142454],[-91.9929683,48.3142454],[-91.9929683,48.3780845],[-92.3189383,48.3780845],[-92.3189383,48.2529081],[-92.3732233,48.2529081],[-92.3732233,48.3153385],[-92.4322288,48.3153385],[-92.4322288,48.4411448],[-92.4977248,48.4411448],[-92.4977248,48.501781],[-92.5679413,48.501781],[-92.5679413,48.439579],[-92.6210462,48.439579],[-92.6210462,48.5650783],[-92.8086835,48.5650783],[-92.8086835,48.6286865],[-92.8086835,48.6267365],[-92.933185,48.6267365],[-92.933185,48.6922145],[-93.0051716,48.6922145],[-93.0051716,48.6282965],[-93.1225924,48.6282965],[-93.1225924,48.6922145],[-93.3190806,48.6922145],[-93.3190806,48.6267365],[-93.5049477,48.6267365],[-93.5049477,48.5635164],[-93.7474601,48.5635164],[-93.7474601,48.6267365],[-93.8135461,48.6267365],[-93.8135461,48.6898775],[-94.2453121,48.6898775],[-94.2453121,48.7554327],[-94.6183171,48.7554327],[-94.6183171,48.941036],[-94.6809018,48.941036],[-94.6809018,49.0029737],[-94.7441532,49.0029737],[-94.7441532,49.2536079],[-94.8084069,49.2536079],[-94.8084069,49.3784134],[-95.1192391,49.3784134],[-95.1192391,49.4425264],[-95.1934341,49.4425264],[-95.1934341,49.0035292],[-96.87069,49.0035292],[-96.87069,49.0656063],[-99.0049312,49.0656063],[-99.0049312,49.0050714],[-109.3699257,49.0050714],[-109.3699257,49.0668231],[-109.5058746,49.0668231],[-109.5058746,49.0050714],[-114.1830014,49.0050714],[-114.1830014,49.0687317],[-114.7578709,49.0687317],[-114.7578709,49.0050714],[-115.433731,49.0050714],[-115.433731,49.0671412],[-116.5062706,49.0671412],[-116.5062706,49.0050714],[-117.3089504,49.0050714],[-117.3089504,49.0659803],[-119.882945,49.0659803],[-119.882945,49.0050714],[-120.1208555,49.0050714],[-120.1208555,49.0678367],[-121.4451636,49.0678367],[-121.4451636,49.0050714],[-121.9311808,49.0050714],[-121.9311808,49.0656099],[-122.817484,49.0656099],[-122.817484,49.0029143],[-122.8795155,49.0029143],[-122.8795155,48.9347018],[-122.8174629,48.9347018],[-122.8174629,48.8101998],[-122.7538859,48.8101998],[-122.7538859,48.7533758],[-122.8712937,48.7533758],[-122.8712937,48.8153948],[-123.0055391,48.8153948],[-123.0055391,48.7529529],[-123.1296926,48.7529529],[-123.1296926,48.6902201],[-123.1838197,48.6902201],[-123.1838197,48.7529029],[-123.2549305,48.7529029]],[[-122.9341743,37.7521547],[-122.9347457,37.6842013],[-123.0679013,37.6849023],[-123.0673747,37.7475251],[-123.1292603,37.7478506],[-123.1286894,37.815685],[-123.0590687,37.8153192],[-123.0595947,37.7528143],[-122.9341743,37.7521547]],[[-71.6299464,41.2540893],[-71.4966465,41.2541393],[-71.4965596,41.122965],[-71.6298594,41.1229149],[-71.6299464,41.2540893]],[[-70.3184265,41.3775196],[-70.3183384,41.2448243],[-70.1906612,41.2448722],[-70.1906239,41.1886019],[-69.9336025,41.1886984],[-69.933729,41.3791941],[-69.9950664,41.3791712],[-69.995109,41.443159],[-70.0707828,41.4431307],[-70.0706972,41.3144915],[-70.2461667,41.3144258],[-70.2462087,41.3775467],[-70.3184265,41.3775196]],[[-68.9403374,43.9404062],[-68.6856948,43.9404977],[-68.6856475,43.8721797],[-68.7465405,43.8721577],[-68.7464976,43.8102529],[-68.8090782,43.8102304],[-68.8090343,43.746728],[-68.8773094,43.7467034],[-68.8773544,43.8117826],[-68.9402483,43.8117599],[-68.9403374,43.9404062]],[[-123.1291466,49.0645144],[-122.9954224,49.0645144],[-122.9954224,48.9343243],[-123.1291466,48.9343243],[-123.1291466,49.0645144]],[[-82.9407144,24.7535913],[-82.8719398,24.7535913],[-82.8719398,24.6905653],[-82.7446233,24.6905653],[-82.7446233,24.6214593],[-82.8088038,24.6214593],[-82.8088038,24.5594908],[-82.9407144,24.5594908],[-82.9407144,24.7535913]]]},{"id":"USGS-Scanned_Topographic","name":"USGS Topographic Maps","type":"tms","template":"http://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"},{"id":"sjcgis.org-General_Basemap_WM","name":"Vector Streetmap for San Juan County WA","type":"tms","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/General_Basemap_WM/MapServer/tile/{zoom}/{y}/{x}","description":"Public domain street and address data from the San Juan County, WA. Updated at least quarterly.","scaleExtent":[0,19],"polygon":[[[-123.274024,48.692975],[-123.007726,48.767256],[-123.007619,48.831577],[-122.783495,48.758416],[-122.693402,48.658522],[-122.767451,48.603606],[-122.744842,48.387083],[-123.248221,48.283531],[-123.114524,48.422614],[-123.219035,48.548575],[-123.274024,48.692975]]],"best":true},{"id":"Vejmidte_Denmark","name":"Vejmidte (Denmark)","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.dk/danmark/vejmidte/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[8.3743941,54.9551655],[8.3683809,55.4042149],[8.2103997,55.4039795],[8.2087314,55.4937345],[8.0502655,55.4924731],[8.0185123,56.7501399],[8.1819161,56.7509948],[8.1763274,57.0208898],[8.3413329,57.0219872],[8.3392467,57.1119574],[8.5054433,57.1123212],[8.5033923,57.2020499],[9.3316304,57.2027636],[9.3319079,57.2924835],[9.4978864,57.2919578],[9.4988593,57.3820608],[9.6649749,57.3811615],[9.6687295,57.5605591],[9.8351961,57.5596265],[9.8374896,57.6493322],[10.1725726,57.6462818],[10.1754245,57.7367768],[10.5118282,57.7330269],[10.5152095,57.8228945],[10.6834853,57.8207722],[10.6751613,57.6412021],[10.5077045,57.6433097],[10.5039992,57.5535088],[10.671038,57.5514113],[10.6507805,57.1024538],[10.4857673,57.1045138],[10.4786236,56.9249051],[10.3143981,56.9267573],[10.3112341,56.8369269],[10.4750295,56.83509],[10.4649016,56.5656681],[10.9524239,56.5589761],[10.9479249,56.4692243],[11.1099335,56.4664675],[11.1052639,56.376833],[10.9429901,56.3795284],[10.9341235,56.1994768],[10.7719685,56.2020244],[10.7694751,56.1120103],[10.6079695,56.1150259],[10.4466742,56.116717],[10.2865948,56.118675],[10.2831527,56.0281851],[10.4439274,56.0270388],[10.4417713,55.7579243],[10.4334961,55.6693533],[10.743814,55.6646861],[10.743814,55.5712253],[10.8969041,55.5712253],[10.9051793,55.3953852],[11.0613726,55.3812841],[11.0593038,55.1124061],[11.0458567,55.0318621],[11.2030844,55.0247474],[11.2030844,55.117139],[11.0593038,55.1124061],[11.0613726,55.3812841],[11.0789572,55.5712253],[10.8969041,55.5712253],[10.9258671,55.6670198],[10.743814,55.6646861],[10.7562267,55.7579243],[10.4417713,55.7579243],[10.4439274,56.0270388],[10.4466742,56.116717],[10.6079695,56.1150259],[10.6052053,56.0247462],[10.9258671,56.0201215],[10.9197132,55.9309388],[11.0802782,55.92792],[11.0858066,56.0178284],[11.7265047,56.005058],[11.7319981,56.0952142],[12.0540333,56.0871256],[12.0608477,56.1762576],[12.7023469,56.1594405],[12.6611131,55.7114318],[12.9792318,55.7014026],[12.9612912,55.5217294],[12.3268659,55.5412096],[12.3206071,55.4513655],[12.4778226,55.447067],[12.4702432,55.3570479],[12.6269738,55.3523837],[12.6200898,55.2632576],[12.4627339,55.26722],[12.4552949,55.1778223],[12.2987046,55.1822303],[12.2897344,55.0923641],[12.6048608,55.0832904],[12.5872011,54.9036285],[12.2766618,54.9119031],[12.2610181,54.7331602],[12.1070691,54.7378161],[12.0858621,54.4681655],[11.7794953,54.4753579],[11.7837381,54.5654783],[11.1658525,54.5782155],[11.1706443,54.6686508],[10.8617173,54.6733956],[10.8651245,54.7634667],[10.7713646,54.7643888],[10.7707276,54.7372807],[10.7551428,54.7375776],[10.7544039,54.7195666],[10.7389074,54.7197588],[10.7384368,54.7108482],[10.7074486,54.7113045],[10.7041094,54.6756741],[10.5510973,54.6781698],[10.5547184,54.7670245],[10.2423994,54.7705935],[10.2459845,54.8604673],[10.0902268,54.8622134],[10.0873731,54.7723851],[9.1555798,54.7769557],[9.1562752,54.8675369],[8.5321973,54.8663765],[8.531432,54.95516],[8.3743941,54.9551655]],[[11.4577738,56.819554],[11.7849181,56.8127385],[11.7716715,56.6332796],[11.4459621,56.6401087],[11.4577738,56.819554]],[[11.3274736,57.3612962],[11.3161808,57.1818004],[11.1508692,57.1847276],[11.1456628,57.094962],[10.8157703,57.1001693],[10.8290599,57.3695272],[11.3274736,57.3612962]],[[11.5843266,56.2777928],[11.5782882,56.1880397],[11.7392309,56.1845765],[11.7456428,56.2743186],[11.5843266,56.2777928]],[[14.6825922,55.3639405],[14.8395247,55.3565231],[14.8263755,55.2671261],[15.1393406,55.2517359],[15.1532015,55.3410836],[15.309925,55.3330556],[15.295719,55.2437356],[15.1393406,55.2517359],[15.1255631,55.1623802],[15.2815819,55.1544167],[15.2535578,54.9757646],[14.6317464,55.0062496],[14.6825922,55.3639405]]],"terms_url":"http://wiki.openstreetmap.org/wiki/Vejmidte","terms_text":"Danish municipalities"},{"id":"wien.gv.at-labels","name":"Vienna: Beschriftungen (annotations)","type":"tms","template":"https://maps.wien.gv.at/wmts/beschriftung/normal/google3857/{zoom}/{y}/{x}.png","scaleExtent":[12,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"https://data.wien.gv.at/","terms_text":"Stadt Wien"},{"id":"wien.gv.at-gp","name":"Vienna: Mehrzweckkarte (general purpose)","type":"tms","template":"https://maps.wien.gv.at/wmts/fmzk/pastell/google3857/{zoom}/{y}/{x}.jpeg","scaleExtent":[10,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"https://data.wien.gv.at/","terms_text":"Stadt Wien"},{"id":"wien.gv.at-aerial_image","name":"Vienna: Orthofoto (aerial image)","type":"tms","template":"https://maps.wien.gv.at/wmts/lb/farbe/google3857/{zoom}/{y}/{x}.jpeg","scaleExtent":[10,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"https://data.wien.gv.at/","terms_text":"Stadt Wien"}];
18627 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/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":"beer","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["beer","bier"],"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/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/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/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":[],"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"},"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"],"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"],"tags":{"railway":"subway_entrance"},"terms":[],"name":"Subway Entrance"},"railway/subway":{"icon":"railway-subway","geometry":["line"],"tags":{"railway":"subway"},"fields":["structure","gauge","electrified","service_rail"],"terms":[],"name":"Subway"},"railway/tram_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/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","computer","tv"],"tags":{"shop":"electronics"},"name":"Electronics Store"},"shop/erotic":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["sex","porn"],"tags":{"shop":"erotic"},"name":"Erotic Store"},"shop/fabric":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["sew"],"tags":{"shop":"fabric"},"name":"Fabric Store"},"shop/farm":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["farm shop","farm stand"],"tags":{"shop":"farm"},"name":"Produce Stand"},"shop/fashion":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"fashion"},"name":"Fashion Store"},"shop/florist":{"icon":"florist","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["flower"],"tags":{"shop":"florist"},"name":"Florist"},"shop/frame":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"frame"},"terms":["art*","paint*","photo*","frame"],"name":"Framing Shop"},"shop/funeral_directors":{"icon":"cemetery","fields":["operator","address","building_area","religion","denomination"],"geometry":["point","area"],"terms":["undertaker","memorial home"],"tags":{"shop":"funeral_directors"},"name":"Funeral Home"},"shop/furnace":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["oven","stove"],"tags":{"shop":"furnace"},"name":"Furnace Store"},"shop/furniture":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["chair","sofa","table"],"tags":{"shop":"furniture"},"name":"Furniture Store"},"shop/garden_centre":{"icon":"garden-center","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["landscape","mulch","shrub","tree"],"tags":{"shop":"garden_centre"},"name":"Garden Center"},"shop/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}};
18629 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"]};
18631 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"]}};
18633 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 Ramp"},"lamp_type":{"key":"lamp_type","type":"combo","label":"Type"},"landuse":{"key":"landuse","type":"typeCombo","label":"Type"},"lanes":{"key":"lanes","type":"number","label":"Lanes","placeholder":"1, 2, 3..."},"layer":{"key":"layer","type":"combo","label":"Layer"},"leaf_cycle_singular":{"key":"leaf_cycle","type":"combo","label":"Leaf Cycle","strings":{"options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous"}}},"leaf_cycle":{"key":"leaf_cycle","type":"combo","label":"Leaf Cycle","strings":{"options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous","mixed":"Mixed"}}},"leaf_type_singular":{"key":"leaf_type","type":"combo","label":"Leaf Type","strings":{"options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","leafless":"Leafless"}}},"leaf_type":{"key":"leaf_type","type":"combo","label":"Leaf Type","strings":{"options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","mixed":"Mixed","leafless":"Leafless"}}},"leisure":{"key":"leisure","type":"typeCombo","label":"Type"},"length":{"key":"length","type":"number","label":"Length (Meters)"},"level":{"key":"level","type":"combo","label":"Level","universal":true},"levels":{"key":"building:levels","type":"number","label":"Levels","placeholder":"2, 4, 6..."},"lit":{"key":"lit","type":"check","label":"Lit"},"location":{"key":"location","type":"combo","label":"Location"},"man_made":{"key":"man_made","type":"typeCombo","label":"Type"},"map_size":{"key":"map_size","type":"typeCombo","label":"Coverage"},"map_type":{"key":"map_type","type":"typeCombo","label":"Type"},"maxheight":{"key":"maxheight","type":"combo","label":"Max Height","placeholder":"4, 4.5, 5, 14'0\", 14'6\", 15'0\"","snake_case":false},"maxspeed":{"key":"maxspeed","type":"maxspeed","label":"Speed Limit","placeholder":"40, 50, 60..."},"maxstay":{"key":"maxstay","type":"combo","label":"Max Stay","options":["15 min","30 min","45 min","1 hr","1.5 hr","2 hr","2.5 hr","3 hr","4 hr","1 day","2 day"],"snake_case":false},"mtb/scale":{"key":"mtb:scale","type":"combo","label":"Mountain Biking Difficulty","placeholder":"0, 1, 2, 3...","strings":{"options":{"0":"0: Solid gravel/packed earth, no obstacles, wide curves","1":"1: Some loose surface, small obstacles, wide curves","2":"2: Much loose surface, large obstacles, easy hairpins","3":"3: Slippery surface, large obstacles, tight hairpins","4":"4: Loose surface or boulders, dangerous hairpins","5":"5: Maximum difficulty, boulder fields, landslides","6":"6: Not rideable except by the very best mountain bikers"}}},"mtb/scale/imba":{"key":"mtb:scale:imba","type":"combo","label":"IMBA Trail Difficulty","placeholder":"Easy, Medium, Difficult...","strings":{"options":{"0":"Easiest (white circle)","1":"Easy (green circle)","2":"Medium (blue square)","3":"Difficult (black diamond)","4":"Extremely Difficult (double black diamond)"}}},"mtb/scale/uphill":{"key":"mtb:scale:uphill","type":"combo","label":"Mountain Biking Uphill Difficulty","placeholder":"0, 1, 2, 3...","strings":{"options":{"0":"0: Avg. incline <10%, gravel/packed earth, no obstacles","1":"1: Avg. incline <15%, gravel/packed earth, few small objects","2":"2: Avg. incline <20%, stable surface, fistsize rocks/roots","3":"3: Avg. incline <25%, variable surface, fistsize rocks/branches","4":"4: Avg. incline <30%, poor condition, big rocks/branches","5":"5: Very steep, bike generally needs to be pushed or carried"}}},"name":{"key":"name","type":"localized","label":"Name","placeholder":"Common name (if any)"},"natural":{"key":"natural","type":"typeCombo","label":"Natural"},"network_bicycle":{"key":"network","type":"combo","label":"Network Type","placeholder":"Local, Regional, National, International","strings":{"options":{"lcn":"Local","rcn":"Regional","ncn":"National","icn":"International"}}},"network_foot":{"key":"network","type":"combo","label":"Network Type","placeholder":"Local, Regional, National, International","strings":{"options":{"lwn":"Local","rwn":"Regional","nwn":"National","iwn":"International"}}},"network_horse":{"key":"network","type":"combo","label":"Network Type","placeholder":"Local, Regional, National, International","strings":{"options":{"lhn":"Local","rhn":"Regional","nhn":"National","ihn":"International"}}},"network_road":{"key":"network","type":"networkCombo","label":"Network"},"network":{"key":"network","type":"text","label":"Network"},"note":{"key":"note","type":"textarea","universal":true,"icon":"note","label":"Note"},"office":{"key":"office","type":"typeCombo","label":"Type"},"oneway_yes":{"key":"oneway","type":"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"}};
18635 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"];
18640 var all$2 = Object.freeze({
18645 var Airport = ["airfield","airport","heliport","rocket"];
18646 var Dining = ["bakery","bar","beer","cafe","fast-food","ice-cream","restaurant"];
18647 var Education = ["college","school"];
18648 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"];
18649 var Health = ["dentist","doctor","hospital","pharmacy"];
18650 var Outdoors = ["campsite","cemetery","dog-park","garden","golf","park","picnic-site","playground","zoo"];
18651 var Transit = ["bus","ferry"];
18655 Education: Education,
18658 Outdoors: Outdoors,
18660 "Mountain peak": ["mountain","volcano"],
18661 "Rail station": ["entrance","rail","rail-light","rail-metro"]
18664 var streets$1 = Object.freeze({
18667 Education: Education,
18670 Outdoors: Outdoors,
18675 var require$$0 = ( all$2 && all$1 ) || all$2;
18677 var require$$1 = ( streets$1 && streets ) || streets$1;
18682 streets: require$$1
18686 var dataFeatureIcons = index$1.layouts.all.all;
18689 imagery: dataImagery,
18692 defaults: defaults,
18693 categories: categories,
18698 function osmEntity$$1(attrs) {
18699 // For prototypal inheritance.
18700 if (this instanceof osmEntity$$1) return;
18702 // Create the appropriate subtype.
18703 if (attrs && attrs.type) {
18704 return osmEntity$$1[attrs.type].apply(this, arguments);
18705 } else if (attrs && attrs.id) {
18706 return osmEntity$$1[osmEntity$$1.id.type(attrs.id)].apply(this, arguments);
18709 // Initialize a generic Entity (used only in tests).
18710 return (new osmEntity$$1()).initialize(arguments);
18714 osmEntity$$1.id = function(type) {
18715 return osmEntity$$1.id.fromOSM(type, osmEntity$$1.id.next[type]--);
18719 osmEntity$$1.id.next = {
18720 changeset: -1, node: -1, way: -1, relation: -1
18724 osmEntity$$1.id.fromOSM = function(type, id) {
18725 return type[0] + id;
18729 osmEntity$$1.id.toOSM = function(id) {
18730 return id.slice(1);
18734 osmEntity$$1.id.type = function(id) {
18735 return { 'c': 'changeset', 'n': 'node', 'w': 'way', 'r': 'relation' }[id[0]];
18739 // A function suitable for use as the second argument to d3.selection#data().
18740 osmEntity$$1.key = function(entity) {
18741 return entity.id + 'v' + (entity.v || 0);
18745 osmEntity$$1.prototype = {
18750 initialize: function(sources) {
18751 for (var i = 0; i < sources.length; ++i) {
18752 var source = sources[i];
18753 for (var prop in source) {
18754 if (Object.prototype.hasOwnProperty.call(source, prop)) {
18755 if (source[prop] === undefined) {
18758 this[prop] = source[prop];
18764 if (!this.id && this.type) {
18765 this.id = osmEntity$$1.id(this.type);
18767 if (!this.hasOwnProperty('visible')) {
18768 this.visible = true;
18772 Object.freeze(this);
18773 Object.freeze(this.tags);
18775 if (this.loc) Object.freeze(this.loc);
18776 if (this.nodes) Object.freeze(this.nodes);
18777 if (this.members) Object.freeze(this.members);
18784 copy: function(resolver, copies) {
18785 if (copies[this.id])
18786 return copies[this.id];
18788 var copy = osmEntity$$1(this, {id: undefined, user: undefined, version: undefined});
18789 copies[this.id] = copy;
18795 osmId: function() {
18796 return osmEntity$$1.id.toOSM(this.id);
18800 isNew: function() {
18801 return this.osmId() < 0;
18805 update: function(attrs) {
18806 return osmEntity$$1(this, attrs, {v: 1 + (this.v || 0)});
18810 mergeTags: function(tags) {
18811 var merged = lodash.clone(this.tags), changed = false;
18812 for (var k in tags) {
18813 var t1 = merged[k],
18818 } else if (t1 !== t2) {
18820 merged[k] = lodash.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
18823 return changed ? this.update({tags: merged}) : this;
18827 intersects: function(extent, resolver) {
18828 return this.extent(resolver).intersects(extent);
18832 isUsed: function(resolver) {
18833 return lodash.without(Object.keys(this.tags), 'area').length > 0 ||
18834 resolver.parentRelations(this).length > 0;
18838 hasInterestingTags: function() {
18839 return lodash.keys(this.tags).some(osmIsInterestingTag);
18843 isHighwayIntersection: function() {
18847 isDegenerate: function() {
18851 deprecatedTags: function() {
18852 var tags = lodash.toPairs(this.tags);
18853 var deprecated = {};
18855 dataDeprecated.forEach(function(d) {
18856 var match = lodash.toPairs(d.old)[0];
18857 tags.forEach(function(t) {
18858 if (t[0] === match[0] &&
18859 (t[1] === match[1] || match[1] === '*')) {
18860 deprecated[t[0]] = t[1];
18869 function geoRoundCoords(c) {
18870 return [Math.floor(c[0]), Math.floor(c[1])];
18874 function geoInterp(p1, p2, t) {
18875 return [p1[0] + (p2[0] - p1[0]) * t,
18876 p1[1] + (p2[1] - p1[1]) * t];
18880 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
18881 // Returns a positive value, if OAB makes a counter-clockwise turn,
18882 // negative for clockwise turn, and zero if the points are collinear.
18883 function geoCross(o, a, b) {
18884 return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
18888 // http://jsperf.com/id-dist-optimization
18889 function geoEuclideanDistance(a, b) {
18890 var x = a[0] - b[0], y = a[1] - b[1];
18891 return Math.sqrt((x * x) + (y * y));
18895 // using WGS84 polar radius (6356752.314245179 m)
18896 // const = 2 * PI * r / 360
18897 function geoLatToMeters(dLat) {
18898 return dLat * 110946.257617;
18902 // using WGS84 equatorial radius (6378137.0 m)
18903 // const = 2 * PI * r / 360
18904 function geoLonToMeters(dLon, atLat) {
18905 return Math.abs(atLat) >= 90 ? 0 :
18906 dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
18910 // using WGS84 polar radius (6356752.314245179 m)
18911 // const = 2 * PI * r / 360
18912 function geoMetersToLat(m) {
18913 return m / 110946.257617;
18917 // using WGS84 equatorial radius (6378137.0 m)
18918 // const = 2 * PI * r / 360
18919 function geoMetersToLon(m, atLat) {
18920 return Math.abs(atLat) >= 90 ? 0 :
18921 m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
18925 function geoOffsetToMeters(offset) {
18926 var equatRadius = 6356752.314245179,
18927 polarRadius = 6378137.0,
18931 offset[0] * 2 * Math.PI * equatRadius / tileSize,
18932 -offset[1] * 2 * Math.PI * polarRadius / tileSize
18937 function geoMetersToOffset(meters) {
18938 var equatRadius = 6356752.314245179,
18939 polarRadius = 6378137.0,
18943 meters[0] * tileSize / (2 * Math.PI * equatRadius),
18944 -meters[1] * tileSize / (2 * Math.PI * polarRadius)
18949 // Equirectangular approximation of spherical distances on Earth
18950 function geoSphericalDistance(a, b) {
18951 var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
18952 y = geoLatToMeters(a[1] - b[1]);
18953 return Math.sqrt((x * x) + (y * y));
18957 function geoEdgeEqual(a, b) {
18958 return (a[0] === b[0] && a[1] === b[1]) ||
18959 (a[0] === b[1] && a[1] === b[0]);
18963 // Return the counterclockwise angle in the range (-pi, pi)
18964 // between the positive X axis and the line intersecting a and b.
18965 function geoAngle(a, b, projection) {
18966 a = projection(a.loc);
18967 b = projection(b.loc);
18968 return Math.atan2(b[1] - a[1], b[0] - a[0]);
18972 // Rotate all points counterclockwise around a pivot point by given angle
18973 function geoRotate(points, angle, around) {
18974 return points.map(function(point) {
18975 var radial = [point[0] - around[0], point[1] - around[1]];
18977 radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + around[0],
18978 radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + around[1]
18984 // Choose the edge with the minimal distance from `point` to its orthogonal
18985 // projection onto that edge, if such a projection exists, or the distance to
18986 // the closest vertex on that edge. Returns an object with the `index` of the
18987 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
18988 function geoChooseEdge(nodes, point, projection) {
18989 var dist = geoEuclideanDistance,
18990 points = nodes.map(function(n) { return projection(n.loc); }),
18994 function dot(p, q) {
18995 return p[0] * q[0] + p[1] * q[1];
18998 for (var i = 0; i < points.length - 1; i++) {
19000 s = [points[i + 1][0] - o[0],
19001 points[i + 1][1] - o[1]],
19002 v = [point[0] - o[0],
19004 proj = dot(v, s) / dot(s, s),
19009 } else if (proj > 1) {
19012 p = [o[0] + proj * s[0], o[1] + proj * s[1]];
19015 var d = dist(p, point);
19019 loc = projection.invert(p);
19031 // Return the intersection point of 2 line segments.
19032 // From https://github.com/pgkelley4/line-segments-intersect
19033 // This uses the vector cross product approach described below:
19034 // http://stackoverflow.com/a/565282/786339
19035 function geoLineIntersection(a, b) {
19036 function subtractPoints(point1, point2) {
19037 return [point1[0] - point2[0], point1[1] - point2[1]];
19039 function crossProduct(point1, point2) {
19040 return point1[0] * point2[1] - point1[1] * point2[0];
19043 var p = [a[0][0], a[0][1]],
19044 p2 = [a[1][0], a[1][1]],
19045 q = [b[0][0], b[0][1]],
19046 q2 = [b[1][0], b[1][1]],
19047 r = subtractPoints(p2, p),
19048 s = subtractPoints(q2, q),
19049 uNumerator = crossProduct(subtractPoints(q, p), r),
19050 denominator = crossProduct(r, s);
19052 if (uNumerator && denominator) {
19053 var u = uNumerator / denominator,
19054 t = crossProduct(subtractPoints(q, p), s) / denominator;
19056 if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
19057 return geoInterp(p, p2, t);
19065 function geoPathIntersections(path1, path2) {
19066 var intersections = [];
19067 for (var i = 0; i < path1.length - 1; i++) {
19068 for (var j = 0; j < path2.length - 1; j++) {
19069 var a = [ path1[i], path1[i+1] ],
19070 b = [ path2[j], path2[j+1] ],
19071 hit = geoLineIntersection(a, b);
19072 if (hit) intersections.push(hit);
19075 return intersections;
19079 // Return whether point is contained in polygon.
19081 // `point` should be a 2-item array of coordinates.
19082 // `polygon` should be an array of 2-item arrays of coordinates.
19084 // From https://github.com/substack/point-in-polygon.
19085 // ray-casting algorithm based on
19086 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
19088 function geoPointInPolygon(point, polygon) {
19093 for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
19094 var xi = polygon[i][0], yi = polygon[i][1];
19095 var xj = polygon[j][0], yj = polygon[j][1];
19097 var intersect = ((yi > y) !== (yj > y)) &&
19098 (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
19099 if (intersect) inside = !inside;
19106 function geoPolygonContainsPolygon(outer, inner) {
19107 return lodash.every(inner, function(point) {
19108 return geoPointInPolygon(point, outer);
19113 function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
19114 function testSegments(outer, inner) {
19115 for (var i = 0; i < outer.length - 1; i++) {
19116 for (var j = 0; j < inner.length - 1; j++) {
19117 var a = [ outer[i], outer[i+1] ],
19118 b = [ inner[j], inner[j+1] ];
19119 if (geoLineIntersection(a, b)) return true;
19125 function testPoints(outer, inner) {
19126 return lodash.some(inner, function(point) {
19127 return geoPointInPolygon(point, outer);
19131 return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
19135 function geoPathLength(path) {
19137 for (var i = 0; i < path.length - 1; i++) {
19138 length += geoEuclideanDistance(path[i], path[i + 1]);
19143 function geoExtent$$1(min, max) {
19144 if (!(this instanceof geoExtent$$1)) return new geoExtent$$1(min, max);
19145 if (min instanceof geoExtent$$1) {
19147 } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
19151 this[0] = min || [ Infinity, Infinity];
19152 this[1] = max || min || [-Infinity, -Infinity];
19156 geoExtent$$1.prototype = new Array(2);
19158 lodash.extend(geoExtent$$1.prototype, {
19160 equals: function (obj) {
19161 return this[0][0] === obj[0][0] &&
19162 this[0][1] === obj[0][1] &&
19163 this[1][0] === obj[1][0] &&
19164 this[1][1] === obj[1][1];
19168 extend: function(obj) {
19169 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19170 return geoExtent$$1(
19171 [Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])],
19172 [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]
19177 _extend: function(extent) {
19178 this[0][0] = Math.min(extent[0][0], this[0][0]);
19179 this[0][1] = Math.min(extent[0][1], this[0][1]);
19180 this[1][0] = Math.max(extent[1][0], this[1][0]);
19181 this[1][1] = Math.max(extent[1][1], this[1][1]);
19186 return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
19190 center: function() {
19191 return [(this[0][0] + this[1][0]) / 2,
19192 (this[0][1] + this[1][1]) / 2];
19196 rectangle: function() {
19197 return [this[0][0], this[0][1], this[1][0], this[1][1]];
19202 return { minX: this[0][0], minY: this[0][1], maxX: this[1][0], maxY: this[1][1] };
19206 polygon: function() {
19208 [this[0][0], this[0][1]],
19209 [this[0][0], this[1][1]],
19210 [this[1][0], this[1][1]],
19211 [this[1][0], this[0][1]],
19212 [this[0][0], this[0][1]]
19217 contains: function(obj) {
19218 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19219 return obj[0][0] >= this[0][0] &&
19220 obj[0][1] >= this[0][1] &&
19221 obj[1][0] <= this[1][0] &&
19222 obj[1][1] <= this[1][1];
19226 intersects: function(obj) {
19227 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19228 return obj[0][0] <= this[1][0] &&
19229 obj[0][1] <= this[1][1] &&
19230 obj[1][0] >= this[0][0] &&
19231 obj[1][1] >= this[0][1];
19235 intersection: function(obj) {
19236 if (!this.intersects(obj)) return new geoExtent$$1();
19237 return new geoExtent$$1(
19238 [Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])],
19239 [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]
19244 percentContainedIn: function(obj) {
19245 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19246 var a1 = this.intersection(obj).area(),
19249 if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
19257 padByMeters: function(meters) {
19258 var dLat = geoMetersToLat(meters),
19259 dLon = geoMetersToLon(meters, this.center()[1]);
19260 return geoExtent$$1(
19261 [this[0][0] - dLon, this[0][1] - dLat],
19262 [this[1][0] + dLon, this[1][1] + dLat]
19267 toParam: function() {
19268 return this.rectangle().join(',');
19273 var version = "4.8.0";
19275 var ascending = function(a, b) {
19276 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
19279 var bisector = function(compare) {
19280 if (compare.length === 1) compare = ascendingComparator(compare);
19282 left: function(a, x, lo, hi) {
19283 if (lo == null) lo = 0;
19284 if (hi == null) hi = a.length;
19286 var mid = lo + hi >>> 1;
19287 if (compare(a[mid], x) < 0) lo = mid + 1;
19292 right: function(a, x, lo, hi) {
19293 if (lo == null) lo = 0;
19294 if (hi == null) hi = a.length;
19296 var mid = lo + hi >>> 1;
19297 if (compare(a[mid], x) > 0) hi = mid;
19305 function ascendingComparator(f) {
19306 return function(d, x) {
19307 return ascending(f(d), x);
19311 var ascendingBisect = bisector(ascending);
19312 var bisectRight = ascendingBisect.right;
19313 var bisectLeft = ascendingBisect.left;
19315 var pairs = function(array, f) {
19316 if (f == null) f = pair;
19317 var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);
19318 while (i < n) pairs[i] = f(p, p = array[++i]);
19322 function pair(a, b) {
19326 var cross = function(values0, values1, reduce) {
19327 var n0 = values0.length,
19328 n1 = values1.length,
19329 values = new Array(n0 * n1),
19335 if (reduce == null) reduce = pair;
19337 for (i0 = i = 0; i0 < n0; ++i0) {
19338 for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) {
19339 values[i] = reduce(value0, values1[i1]);
19346 var descending = function(a, b) {
19347 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
19350 var number = function(x) {
19351 return x === null ? NaN : +x;
19354 var variance = function(values, valueof) {
19355 var n = values.length,
19363 if (valueof == null) {
19365 if (!isNaN(value = number(values[i]))) {
19366 delta = value - mean;
19367 mean += delta / ++m;
19368 sum += delta * (value - mean);
19375 if (!isNaN(value = number(valueof(values[i], i, values)))) {
19376 delta = value - mean;
19377 mean += delta / ++m;
19378 sum += delta * (value - mean);
19383 if (m > 1) return sum / (m - 1);
19386 var deviation = function(array, f) {
19387 var v = variance(array, f);
19388 return v ? Math.sqrt(v) : v;
19391 var extent = function(values, valueof) {
19392 var n = values.length,
19398 if (valueof == null) {
19399 while (++i < n) { // Find the first comparable value.
19400 if ((value = values[i]) != null && value >= value) {
19402 while (++i < n) { // Compare the remaining values.
19403 if ((value = values[i]) != null) {
19404 if (min > value) min = value;
19405 if (max < value) max = value;
19413 while (++i < n) { // Find the first comparable value.
19414 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19416 while (++i < n) { // Compare the remaining values.
19417 if ((value = valueof(values[i], i, values)) != null) {
19418 if (min > value) min = value;
19419 if (max < value) max = value;
19429 var array = Array.prototype;
19431 var slice = array.slice;
19432 var map = array.map;
19434 var constant = function(x) {
19435 return function() {
19440 var identity = function(x) {
19444 var sequence = function(start, stop, step) {
19445 start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
19448 n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
19449 range = new Array(n);
19452 range[i] = start + i * step;
19458 var e10 = Math.sqrt(50);
19459 var e5 = Math.sqrt(10);
19460 var e2 = Math.sqrt(2);
19462 var ticks = function(start, stop, count) {
19463 var reverse = stop < start,
19469 if (reverse) n = start, start = stop, stop = n;
19471 if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
19474 start = Math.ceil(start / step);
19475 stop = Math.floor(stop / step);
19476 ticks = new Array(n = Math.ceil(stop - start + 1));
19477 while (++i < n) ticks[i] = (start + i) * step;
19479 start = Math.floor(start * step);
19480 stop = Math.ceil(stop * step);
19481 ticks = new Array(n = Math.ceil(start - stop + 1));
19482 while (++i < n) ticks[i] = (start - i) / step;
19485 if (reverse) ticks.reverse();
19490 function tickIncrement(start, stop, count) {
19491 var step = (stop - start) / Math.max(0, count),
19492 power = Math.floor(Math.log(step) / Math.LN10),
19493 error = step / Math.pow(10, power);
19495 ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power)
19496 : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
19499 function tickStep(start, stop, count) {
19500 var step0 = Math.abs(stop - start) / Math.max(0, count),
19501 step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
19502 error = step0 / step1;
19503 if (error >= e10) step1 *= 10;
19504 else if (error >= e5) step1 *= 5;
19505 else if (error >= e2) step1 *= 2;
19506 return stop < start ? -step1 : step1;
19509 var sturges = function(values) {
19510 return Math.ceil(Math.log(values.length) / Math.LN2) + 1;
19513 var histogram = function() {
19514 var value = identity,
19516 threshold = sturges;
19518 function histogram(data) {
19522 values = new Array(n);
19524 for (i = 0; i < n; ++i) {
19525 values[i] = value(data[i], i, data);
19528 var xz = domain(values),
19531 tz = threshold(values, x0, x1);
19533 // Convert number of thresholds into uniform thresholds.
19534 if (!Array.isArray(tz)) {
19535 tz = tickStep(x0, x1, tz);
19536 tz = sequence(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive
19539 // Remove any thresholds outside the domain.
19541 while (tz[0] <= x0) tz.shift(), --m;
19542 while (tz[m - 1] > x1) tz.pop(), --m;
19544 var bins = new Array(m + 1),
19547 // Initialize bins.
19548 for (i = 0; i <= m; ++i) {
19549 bin = bins[i] = [];
19550 bin.x0 = i > 0 ? tz[i - 1] : x0;
19551 bin.x1 = i < m ? tz[i] : x1;
19554 // Assign data to bins by value, ignoring any outside the domain.
19555 for (i = 0; i < n; ++i) {
19557 if (x0 <= x && x <= x1) {
19558 bins[bisectRight(tz, x, 0, m)].push(data[i]);
19565 histogram.value = function(_) {
19566 return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value;
19569 histogram.domain = function(_) {
19570 return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain;
19573 histogram.thresholds = function(_) {
19574 return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold;
19580 var threshold = function(values, p, valueof) {
19581 if (valueof == null) valueof = number;
19582 if (!(n = values.length)) return;
19583 if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values);
19584 if (p >= 1) return +valueof(values[n - 1], n - 1, values);
19587 i0 = Math.floor(i),
19588 value0 = +valueof(values[i0], i0, values),
19589 value1 = +valueof(values[i0 + 1], i0 + 1, values);
19590 return value0 + (value1 - value0) * (i - i0);
19593 var freedmanDiaconis = function(values, min, max) {
19594 values = map.call(values, number).sort(ascending);
19595 return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3)));
19598 var scott = function(values, min, max) {
19599 return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));
19602 var max = function(values, valueof) {
19603 var n = values.length,
19608 if (valueof == null) {
19609 while (++i < n) { // Find the first comparable value.
19610 if ((value = values[i]) != null && value >= value) {
19612 while (++i < n) { // Compare the remaining values.
19613 if ((value = values[i]) != null && value > max) {
19622 while (++i < n) { // Find the first comparable value.
19623 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19625 while (++i < n) { // Compare the remaining values.
19626 if ((value = valueof(values[i], i, values)) != null && value > max) {
19637 var mean = function(values, valueof) {
19638 var n = values.length,
19644 if (valueof == null) {
19646 if (!isNaN(value = number(values[i]))) sum += value;
19653 if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value;
19658 if (m) return sum / m;
19661 var median = function(values, valueof) {
19662 var n = values.length,
19667 if (valueof == null) {
19669 if (!isNaN(value = number(values[i]))) {
19670 numbers.push(value);
19677 if (!isNaN(value = number(valueof(values[i], i, values)))) {
19678 numbers.push(value);
19683 return threshold(numbers.sort(ascending), 0.5);
19686 var merge = function(arrays) {
19687 var n = arrays.length,
19694 while (++i < n) j += arrays[i].length;
19695 merged = new Array(j);
19701 merged[--j] = array[m];
19708 var min = function(values, valueof) {
19709 var n = values.length,
19714 if (valueof == null) {
19715 while (++i < n) { // Find the first comparable value.
19716 if ((value = values[i]) != null && value >= value) {
19718 while (++i < n) { // Compare the remaining values.
19719 if ((value = values[i]) != null && min > value) {
19728 while (++i < n) { // Find the first comparable value.
19729 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19731 while (++i < n) { // Compare the remaining values.
19732 if ((value = valueof(values[i], i, values)) != null && min > value) {
19743 var permute = function(array, indexes) {
19744 var i = indexes.length, permutes = new Array(i);
19745 while (i--) permutes[i] = array[indexes[i]];
19749 var scan = function(values, compare) {
19750 if (!(n = values.length)) return;
19757 if (compare == null) compare = ascending;
19760 if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) {
19765 if (compare(xj, xj) === 0) return j;
19768 var shuffle = function(array, i0, i1) {
19769 var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),
19774 i = Math.random() * m-- | 0;
19776 array[m + i0] = array[i + i0];
19783 var sum = function(values, valueof) {
19784 var n = values.length,
19789 if (valueof == null) {
19791 if (value = +values[i]) sum += value; // Note: zero and null are equivalent.
19797 if (value = +valueof(values[i], i, values)) sum += value;
19804 var transpose = function(matrix) {
19805 if (!(n = matrix.length)) return [];
19806 for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
19807 for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
19808 row[j] = matrix[j][i];
19814 function length(d) {
19818 var zip = function() {
19819 return transpose(arguments);
19822 var slice$1 = Array.prototype.slice;
19824 var identity$1 = function(x) {
19832 var epsilon = 1e-6;
19834 function translateX(x) {
19835 return "translate(" + x + ",0)";
19838 function translateY(y) {
19839 return "translate(0," + y + ")";
19842 function center(scale) {
19843 var offset = scale.bandwidth() / 2;
19844 if (scale.round()) offset = Math.round(offset);
19845 return function(d) {
19846 return scale(d) + offset;
19850 function entering() {
19851 return !this.__axis;
19854 function axis(orient, scale) {
19855 var tickArguments = [],
19861 k = orient === top || orient === left ? -1 : 1,
19862 x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x"),
19863 transform = orient === top || orient === bottom ? translateX : translateY;
19865 function axis(context) {
19866 var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
19867 format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$1) : tickFormat,
19868 spacing = Math.max(tickSizeInner, 0) + tickPadding,
19869 range = scale.range(),
19870 range0 = range[0] + 0.5,
19871 range1 = range[range.length - 1] + 0.5,
19872 position = (scale.bandwidth ? center : identity$1)(scale.copy()),
19873 selection = context.selection ? context.selection() : context,
19874 path = selection.selectAll(".domain").data([null]),
19875 tick = selection.selectAll(".tick").data(values, scale).order(),
19876 tickExit = tick.exit(),
19877 tickEnter = tick.enter().append("g").attr("class", "tick"),
19878 line = tick.select("line"),
19879 text = tick.select("text");
19881 path = path.merge(path.enter().insert("path", ".tick")
19882 .attr("class", "domain")
19883 .attr("stroke", "#000"));
19885 tick = tick.merge(tickEnter);
19887 line = line.merge(tickEnter.append("line")
19888 .attr("stroke", "#000")
19889 .attr(x + "2", k * tickSizeInner)
19890 .attr(y + "1", 0.5)
19891 .attr(y + "2", 0.5));
19893 text = text.merge(tickEnter.append("text")
19894 .attr("fill", "#000")
19895 .attr(x, k * spacing)
19897 .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em"));
19899 if (context !== selection) {
19900 path = path.transition(context);
19901 tick = tick.transition(context);
19902 line = line.transition(context);
19903 text = text.transition(context);
19905 tickExit = tickExit.transition(context)
19906 .attr("opacity", epsilon)
19907 .attr("transform", function(d) { return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); });
19910 .attr("opacity", epsilon)
19911 .attr("transform", function(d) { var p = this.parentNode.__axis; return transform(p && isFinite(p = p(d)) ? p : position(d)); });
19917 .attr("d", orient === left || orient == right
19918 ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter
19919 : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter);
19922 .attr("opacity", 1)
19923 .attr("transform", function(d) { return transform(position(d)); });
19926 .attr(x + "2", k * tickSizeInner);
19929 .attr(x, k * spacing)
19932 selection.filter(entering)
19933 .attr("fill", "none")
19934 .attr("font-size", 10)
19935 .attr("font-family", "sans-serif")
19936 .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle");
19939 .each(function() { this.__axis = position; });
19942 axis.scale = function(_) {
19943 return arguments.length ? (scale = _, axis) : scale;
19946 axis.ticks = function() {
19947 return tickArguments = slice$1.call(arguments), axis;
19950 axis.tickArguments = function(_) {
19951 return arguments.length ? (tickArguments = _ == null ? [] : slice$1.call(_), axis) : tickArguments.slice();
19954 axis.tickValues = function(_) {
19955 return arguments.length ? (tickValues = _ == null ? null : slice$1.call(_), axis) : tickValues && tickValues.slice();
19958 axis.tickFormat = function(_) {
19959 return arguments.length ? (tickFormat = _, axis) : tickFormat;
19962 axis.tickSize = function(_) {
19963 return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
19966 axis.tickSizeInner = function(_) {
19967 return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
19970 axis.tickSizeOuter = function(_) {
19971 return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
19974 axis.tickPadding = function(_) {
19975 return arguments.length ? (tickPadding = +_, axis) : tickPadding;
19981 function axisTop(scale) {
19982 return axis(top, scale);
19985 function axisRight(scale) {
19986 return axis(right, scale);
19989 function axisBottom(scale) {
19990 return axis(bottom, scale);
19993 function axisLeft(scale) {
19994 return axis(left, scale);
19997 var noop = {value: function() {}};
19999 function dispatch() {
20000 for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
20001 if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t);
20004 return new Dispatch(_);
20007 function Dispatch(_) {
20011 function parseTypenames(typenames, types) {
20012 return typenames.trim().split(/^|\s+/).map(function(t) {
20013 var name = "", i = t.indexOf(".");
20014 if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
20015 if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
20016 return {type: t, name: name};
20020 Dispatch.prototype = dispatch.prototype = {
20021 constructor: Dispatch,
20022 on: function(typename, callback) {
20024 T = parseTypenames(typename + "", _),
20029 // If no callback was specified, return the callback of the given type and name.
20030 if (arguments.length < 2) {
20031 while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
20035 // If a type was specified, set the callback for the given type and name.
20036 // Otherwise, if a null callback was specified, remove callbacks of the given name.
20037 if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
20039 if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);
20040 else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);
20046 var copy = {}, _ = this._;
20047 for (var t in _) copy[t] = _[t].slice();
20048 return new Dispatch(copy);
20050 call: function(type, that) {
20051 if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
20052 if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
20053 for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
20055 apply: function(type, that, args) {
20056 if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
20057 for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
20061 function get(type, name) {
20062 for (var i = 0, n = type.length, c; i < n; ++i) {
20063 if ((c = type[i]).name === name) {
20069 function set(type, name, callback) {
20070 for (var i = 0, n = type.length; i < n; ++i) {
20071 if (type[i].name === name) {
20072 type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
20076 if (callback != null) type.push({name: name, value: callback});
20080 var xhtml = "http://www.w3.org/1999/xhtml";
20083 svg: "http://www.w3.org/2000/svg",
20085 xlink: "http://www.w3.org/1999/xlink",
20086 xml: "http://www.w3.org/XML/1998/namespace",
20087 xmlns: "http://www.w3.org/2000/xmlns/"
20090 var namespace = function(name) {
20091 var prefix = name += "", i = prefix.indexOf(":");
20092 if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
20093 return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
20096 function creatorInherit(name) {
20097 return function() {
20098 var document = this.ownerDocument,
20099 uri = this.namespaceURI;
20100 return uri === xhtml && document.documentElement.namespaceURI === xhtml
20101 ? document.createElement(name)
20102 : document.createElementNS(uri, name);
20106 function creatorFixed(fullname) {
20107 return function() {
20108 return this.ownerDocument.createElementNS(fullname.space, fullname.local);
20112 var creator = function(name) {
20113 var fullname = namespace(name);
20114 return (fullname.local
20116 : creatorInherit)(fullname);
20121 function local$1() {
20126 this._ = "@" + (++nextId).toString(36);
20129 Local.prototype = local$1.prototype = {
20130 constructor: Local,
20131 get: function(node) {
20133 while (!(id in node)) if (!(node = node.parentNode)) return;
20136 set: function(node, value) {
20137 return node[this._] = value;
20139 remove: function(node) {
20140 return this._ in node && delete node[this._];
20142 toString: function() {
20147 var matcher = function(selector) {
20148 return function() {
20149 return this.matches(selector);
20153 if (typeof document !== "undefined") {
20154 var element = document.documentElement;
20155 if (!element.matches) {
20156 var vendorMatches = element.webkitMatchesSelector
20157 || element.msMatchesSelector
20158 || element.mozMatchesSelector
20159 || element.oMatchesSelector;
20160 matcher = function(selector) {
20161 return function() {
20162 return vendorMatches.call(this, selector);
20168 var matcher$1 = matcher;
20170 var filterEvents = {};
20174 if (typeof document !== "undefined") {
20175 var element$1 = document.documentElement;
20176 if (!("onmouseenter" in element$1)) {
20177 filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
20181 function filterContextListener(listener, index, group) {
20182 listener = contextListener(listener, index, group);
20183 return function(event) {
20184 var related = event.relatedTarget;
20185 if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
20186 listener.call(this, event);
20191 function contextListener(listener, index, group) {
20192 return function(event1) {
20193 var event0 = event; // Events can be reentrant (e.g., focus).
20196 listener.call(this, this.__data__, index, group);
20203 function parseTypenames$1(typenames) {
20204 return typenames.trim().split(/^|\s+/).map(function(t) {
20205 var name = "", i = t.indexOf(".");
20206 if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
20207 return {type: t, name: name};
20211 function onRemove(typename) {
20212 return function() {
20213 var on = this.__on;
20215 for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
20216 if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
20217 this.removeEventListener(o.type, o.listener, o.capture);
20222 if (++i) on.length = i;
20223 else delete this.__on;
20227 function onAdd(typename, value, capture) {
20228 var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
20229 return function(d, i, group) {
20230 var on = this.__on, o, listener = wrap(value, i, group);
20231 if (on) for (var j = 0, m = on.length; j < m; ++j) {
20232 if ((o = on[j]).type === typename.type && o.name === typename.name) {
20233 this.removeEventListener(o.type, o.listener, o.capture);
20234 this.addEventListener(o.type, o.listener = listener, o.capture = capture);
20239 this.addEventListener(typename.type, listener, capture);
20240 o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
20241 if (!on) this.__on = [o];
20246 var selection_on = function(typename, value, capture) {
20247 var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t;
20249 if (arguments.length < 2) {
20250 var on = this.node().__on;
20251 if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
20252 for (i = 0, o = on[j]; i < n; ++i) {
20253 if ((t = typenames[i]).type === o.type && t.name === o.name) {
20261 on = value ? onAdd : onRemove;
20262 if (capture == null) capture = false;
20263 for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
20267 function customEvent(event1, listener, that, args) {
20268 var event0 = event;
20269 event1.sourceEvent = event;
20272 return listener.apply(that, args);
20278 var sourceEvent = function() {
20279 var current = event, source;
20280 while (source = current.sourceEvent) current = source;
20284 var point = function(node, event) {
20285 var svg = node.ownerSVGElement || node;
20287 if (svg.createSVGPoint) {
20288 var point = svg.createSVGPoint();
20289 point.x = event.clientX, point.y = event.clientY;
20290 point = point.matrixTransform(node.getScreenCTM().inverse());
20291 return [point.x, point.y];
20294 var rect = node.getBoundingClientRect();
20295 return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
20298 var mouse = function(node) {
20299 var event = sourceEvent();
20300 if (event.changedTouches) event = event.changedTouches[0];
20301 return point(node, event);
20306 var selector = function(selector) {
20307 return selector == null ? none : function() {
20308 return this.querySelector(selector);
20312 var selection_select = function(select) {
20313 if (typeof select !== "function") select = selector(select);
20315 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
20316 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
20317 if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
20318 if ("__data__" in node) subnode.__data__ = node.__data__;
20319 subgroup[i] = subnode;
20324 return new Selection(subgroups, this._parents);
20327 function empty$1() {
20331 var selectorAll = function(selector) {
20332 return selector == null ? empty$1 : function() {
20333 return this.querySelectorAll(selector);
20337 var selection_selectAll = function(select) {
20338 if (typeof select !== "function") select = selectorAll(select);
20340 for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
20341 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
20342 if (node = group[i]) {
20343 subgroups.push(select.call(node, node.__data__, i, group));
20344 parents.push(node);
20349 return new Selection(subgroups, parents);
20352 var selection_filter = function(match) {
20353 if (typeof match !== "function") match = matcher$1(match);
20355 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
20356 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
20357 if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
20358 subgroup.push(node);
20363 return new Selection(subgroups, this._parents);
20366 var sparse = function(update) {
20367 return new Array(update.length);
20370 var selection_enter = function() {
20371 return new Selection(this._enter || this._groups.map(sparse), this._parents);
20374 function EnterNode(parent, datum) {
20375 this.ownerDocument = parent.ownerDocument;
20376 this.namespaceURI = parent.namespaceURI;
20378 this._parent = parent;
20379 this.__data__ = datum;
20382 EnterNode.prototype = {
20383 constructor: EnterNode,
20384 appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
20385 insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
20386 querySelector: function(selector) { return this._parent.querySelector(selector); },
20387 querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
20390 var constant$1 = function(x) {
20391 return function() {
20396 var keyPrefix = "$"; // Protect against keys like “__proto__”.
20398 function bindIndex(parent, group, enter, update, exit, data) {
20401 groupLength = group.length,
20402 dataLength = data.length;
20404 // Put any non-null nodes that fit into update.
20405 // Put any null nodes into enter.
20406 // Put any remaining data into enter.
20407 for (; i < dataLength; ++i) {
20408 if (node = group[i]) {
20409 node.__data__ = data[i];
20412 enter[i] = new EnterNode(parent, data[i]);
20416 // Put any non-null nodes that don’t fit into exit.
20417 for (; i < groupLength; ++i) {
20418 if (node = group[i]) {
20424 function bindKey(parent, group, enter, update, exit, data, key) {
20427 nodeByKeyValue = {},
20428 groupLength = group.length,
20429 dataLength = data.length,
20430 keyValues = new Array(groupLength),
20433 // Compute the key for each node.
20434 // If multiple nodes have the same key, the duplicates are added to exit.
20435 for (i = 0; i < groupLength; ++i) {
20436 if (node = group[i]) {
20437 keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
20438 if (keyValue in nodeByKeyValue) {
20441 nodeByKeyValue[keyValue] = node;
20446 // Compute the key for each datum.
20447 // If there a node associated with this key, join and add it to update.
20448 // If there is not (or the key is a duplicate), add it to enter.
20449 for (i = 0; i < dataLength; ++i) {
20450 keyValue = keyPrefix + key.call(parent, data[i], i, data);
20451 if (node = nodeByKeyValue[keyValue]) {
20453 node.__data__ = data[i];
20454 nodeByKeyValue[keyValue] = null;
20456 enter[i] = new EnterNode(parent, data[i]);
20460 // Add any remaining nodes that were not bound to data to exit.
20461 for (i = 0; i < groupLength; ++i) {
20462 if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
20468 var selection_data = function(value, key) {
20470 data = new Array(this.size()), j = -1;
20471 this.each(function(d) { data[++j] = d; });
20475 var bind = key ? bindKey : bindIndex,
20476 parents = this._parents,
20477 groups = this._groups;
20479 if (typeof value !== "function") value = constant$1(value);
20481 for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
20482 var parent = parents[j],
20484 groupLength = group.length,
20485 data = value.call(parent, parent && parent.__data__, j, parents),
20486 dataLength = data.length,
20487 enterGroup = enter[j] = new Array(dataLength),
20488 updateGroup = update[j] = new Array(dataLength),
20489 exitGroup = exit[j] = new Array(groupLength);
20491 bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
20493 // Now connect the enter nodes to their following update node, such that
20494 // appendChild can insert the materialized enter node before this node,
20495 // rather than at the end of the parent node.
20496 for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
20497 if (previous = enterGroup[i0]) {
20498 if (i0 >= i1) i1 = i0 + 1;
20499 while (!(next = updateGroup[i1]) && ++i1 < dataLength);
20500 previous._next = next || null;
20505 update = new Selection(update, parents);
20506 update._enter = enter;
20507 update._exit = exit;
20511 var selection_exit = function() {
20512 return new Selection(this._exit || this._groups.map(sparse), this._parents);
20515 var selection_merge = function(selection) {
20517 for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
20518 for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
20519 if (node = group0[i] || group1[i]) {
20525 for (; j < m0; ++j) {
20526 merges[j] = groups0[j];
20529 return new Selection(merges, this._parents);
20532 var selection_order = function() {
20534 for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
20535 for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
20536 if (node = group[i]) {
20537 if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
20546 var selection_sort = function(compare) {
20547 if (!compare) compare = ascending$1;
20549 function compareNode(a, b) {
20550 return a && b ? compare(a.__data__, b.__data__) : !a - !b;
20553 for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
20554 for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
20555 if (node = group[i]) {
20556 sortgroup[i] = node;
20559 sortgroup.sort(compareNode);
20562 return new Selection(sortgroups, this._parents).order();
20565 function ascending$1(a, b) {
20566 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
20569 var selection_call = function() {
20570 var callback = arguments[0];
20571 arguments[0] = this;
20572 callback.apply(null, arguments);
20576 var selection_nodes = function() {
20577 var nodes = new Array(this.size()), i = -1;
20578 this.each(function() { nodes[++i] = this; });
20582 var selection_node = function() {
20584 for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
20585 for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
20586 var node = group[i];
20587 if (node) return node;
20594 var selection_size = function() {
20596 this.each(function() { ++size; });
20600 var selection_empty = function() {
20601 return !this.node();
20604 var selection_each = function(callback) {
20606 for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
20607 for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
20608 if (node = group[i]) callback.call(node, node.__data__, i, group);
20615 function attrRemove(name) {
20616 return function() {
20617 this.removeAttribute(name);
20621 function attrRemoveNS(fullname) {
20622 return function() {
20623 this.removeAttributeNS(fullname.space, fullname.local);
20627 function attrConstant(name, value) {
20628 return function() {
20629 this.setAttribute(name, value);
20633 function attrConstantNS(fullname, value) {
20634 return function() {
20635 this.setAttributeNS(fullname.space, fullname.local, value);
20639 function attrFunction(name, value) {
20640 return function() {
20641 var v = value.apply(this, arguments);
20642 if (v == null) this.removeAttribute(name);
20643 else this.setAttribute(name, v);
20647 function attrFunctionNS(fullname, value) {
20648 return function() {
20649 var v = value.apply(this, arguments);
20650 if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
20651 else this.setAttributeNS(fullname.space, fullname.local, v);
20655 var selection_attr = function(name, value) {
20656 var fullname = namespace(name);
20658 if (arguments.length < 2) {
20659 var node = this.node();
20660 return fullname.local
20661 ? node.getAttributeNS(fullname.space, fullname.local)
20662 : node.getAttribute(fullname);
20665 return this.each((value == null
20666 ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
20667 ? (fullname.local ? attrFunctionNS : attrFunction)
20668 : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
20671 var window$1 = function(node) {
20672 return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
20673 || (node.document && node) // node is a Window
20674 || node.defaultView; // node is a Document
20677 function styleRemove(name) {
20678 return function() {
20679 this.style.removeProperty(name);
20683 function styleConstant(name, value, priority) {
20684 return function() {
20685 this.style.setProperty(name, value, priority);
20689 function styleFunction(name, value, priority) {
20690 return function() {
20691 var v = value.apply(this, arguments);
20692 if (v == null) this.style.removeProperty(name);
20693 else this.style.setProperty(name, v, priority);
20697 var selection_style = function(name, value, priority) {
20699 return arguments.length > 1
20700 ? this.each((value == null
20701 ? styleRemove : typeof value === "function"
20703 : styleConstant)(name, value, priority == null ? "" : priority))
20704 : window$1(node = this.node())
20705 .getComputedStyle(node, null)
20706 .getPropertyValue(name);
20709 function propertyRemove(name) {
20710 return function() {
20715 function propertyConstant(name, value) {
20716 return function() {
20717 this[name] = value;
20721 function propertyFunction(name, value) {
20722 return function() {
20723 var v = value.apply(this, arguments);
20724 if (v == null) delete this[name];
20725 else this[name] = v;
20729 var selection_property = function(name, value) {
20730 return arguments.length > 1
20731 ? this.each((value == null
20732 ? propertyRemove : typeof value === "function"
20734 : propertyConstant)(name, value))
20735 : this.node()[name];
20738 function classArray(string) {
20739 return string.trim().split(/^|\s+/);
20742 function classList(node) {
20743 return node.classList || new ClassList(node);
20746 function ClassList(node) {
20748 this._names = classArray(node.getAttribute("class") || "");
20751 ClassList.prototype = {
20752 add: function(name) {
20753 var i = this._names.indexOf(name);
20755 this._names.push(name);
20756 this._node.setAttribute("class", this._names.join(" "));
20759 remove: function(name) {
20760 var i = this._names.indexOf(name);
20762 this._names.splice(i, 1);
20763 this._node.setAttribute("class", this._names.join(" "));
20766 contains: function(name) {
20767 return this._names.indexOf(name) >= 0;
20771 function classedAdd(node, names) {
20772 var list = classList(node), i = -1, n = names.length;
20773 while (++i < n) list.add(names[i]);
20776 function classedRemove(node, names) {
20777 var list = classList(node), i = -1, n = names.length;
20778 while (++i < n) list.remove(names[i]);
20781 function classedTrue(names) {
20782 return function() {
20783 classedAdd(this, names);
20787 function classedFalse(names) {
20788 return function() {
20789 classedRemove(this, names);
20793 function classedFunction(names, value) {
20794 return function() {
20795 (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
20799 var selection_classed = function(name, value) {
20800 var names = classArray(name + "");
20802 if (arguments.length < 2) {
20803 var list = classList(this.node()), i = -1, n = names.length;
20804 while (++i < n) if (!list.contains(names[i])) return false;
20808 return this.each((typeof value === "function"
20809 ? classedFunction : value
20811 : classedFalse)(names, value));
20814 function textRemove() {
20815 this.textContent = "";
20818 function textConstant(value) {
20819 return function() {
20820 this.textContent = value;
20824 function textFunction(value) {
20825 return function() {
20826 var v = value.apply(this, arguments);
20827 this.textContent = v == null ? "" : v;
20831 var selection_text = function(value) {
20832 return arguments.length
20833 ? this.each(value == null
20834 ? textRemove : (typeof value === "function"
20836 : textConstant)(value))
20837 : this.node().textContent;
20840 function htmlRemove() {
20841 this.innerHTML = "";
20844 function htmlConstant(value) {
20845 return function() {
20846 this.innerHTML = value;
20850 function htmlFunction(value) {
20851 return function() {
20852 var v = value.apply(this, arguments);
20853 this.innerHTML = v == null ? "" : v;
20857 var selection_html = function(value) {
20858 return arguments.length
20859 ? this.each(value == null
20860 ? htmlRemove : (typeof value === "function"
20862 : htmlConstant)(value))
20863 : this.node().innerHTML;
20867 if (this.nextSibling) this.parentNode.appendChild(this);
20870 var selection_raise = function() {
20871 return this.each(raise);
20875 if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
20878 var selection_lower = function() {
20879 return this.each(lower);
20882 var selection_append = function(name) {
20883 var create = typeof name === "function" ? name : creator(name);
20884 return this.select(function() {
20885 return this.appendChild(create.apply(this, arguments));
20889 function constantNull() {
20893 var selection_insert = function(name, before) {
20894 var create = typeof name === "function" ? name : creator(name),
20895 select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
20896 return this.select(function() {
20897 return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
20901 function remove() {
20902 var parent = this.parentNode;
20903 if (parent) parent.removeChild(this);
20906 var selection_remove = function() {
20907 return this.each(remove);
20910 var selection_datum = function(value) {
20911 return arguments.length
20912 ? this.property("__data__", value)
20913 : this.node().__data__;
20916 function dispatchEvent(node, type, params) {
20917 var window = window$1(node),
20918 event = window.CustomEvent;
20921 event = new event(type, params);
20923 event = window.document.createEvent("Event");
20924 if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
20925 else event.initEvent(type, false, false);
20928 node.dispatchEvent(event);
20931 function dispatchConstant(type, params) {
20932 return function() {
20933 return dispatchEvent(this, type, params);
20937 function dispatchFunction(type, params) {
20938 return function() {
20939 return dispatchEvent(this, type, params.apply(this, arguments));
20943 var selection_dispatch = function(type, params) {
20944 return this.each((typeof params === "function"
20946 : dispatchConstant)(type, params));
20951 function Selection(groups, parents) {
20952 this._groups = groups;
20953 this._parents = parents;
20956 function selection() {
20957 return new Selection([[document.documentElement]], root);
20960 Selection.prototype = selection.prototype = {
20961 constructor: Selection,
20962 select: selection_select,
20963 selectAll: selection_selectAll,
20964 filter: selection_filter,
20965 data: selection_data,
20966 enter: selection_enter,
20967 exit: selection_exit,
20968 merge: selection_merge,
20969 order: selection_order,
20970 sort: selection_sort,
20971 call: selection_call,
20972 nodes: selection_nodes,
20973 node: selection_node,
20974 size: selection_size,
20975 empty: selection_empty,
20976 each: selection_each,
20977 attr: selection_attr,
20978 style: selection_style,
20979 property: selection_property,
20980 classed: selection_classed,
20981 text: selection_text,
20982 html: selection_html,
20983 raise: selection_raise,
20984 lower: selection_lower,
20985 append: selection_append,
20986 insert: selection_insert,
20987 remove: selection_remove,
20988 datum: selection_datum,
20990 dispatch: selection_dispatch
20993 var select = function(selector) {
20994 return typeof selector === "string"
20995 ? new Selection([[document.querySelector(selector)]], [document.documentElement])
20996 : new Selection([[selector]], root);
20999 var selectAll = function(selector) {
21000 return typeof selector === "string"
21001 ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
21002 : new Selection([selector == null ? [] : selector], root);
21005 var touch = function(node, touches, identifier) {
21006 if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
21008 for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
21009 if ((touch = touches[i]).identifier === identifier) {
21010 return point(node, touch);
21017 var touches = function(node, touches) {
21018 if (touches == null) touches = sourceEvent().touches;
21020 for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) {
21021 points[i] = point(node, touches[i]);
21027 function nopropagation() {
21028 event.stopImmediatePropagation();
21031 var noevent = function() {
21032 event.preventDefault();
21033 event.stopImmediatePropagation();
21036 var dragDisable = function(view) {
21037 var root = view.document.documentElement,
21038 selection$$1 = select(view).on("dragstart.drag", noevent, true);
21039 if ("onselectstart" in root) {
21040 selection$$1.on("selectstart.drag", noevent, true);
21042 root.__noselect = root.style.MozUserSelect;
21043 root.style.MozUserSelect = "none";
21047 function yesdrag(view, noclick) {
21048 var root = view.document.documentElement,
21049 selection$$1 = select(view).on("dragstart.drag", null);
21051 selection$$1.on("click.drag", noevent, true);
21052 setTimeout(function() { selection$$1.on("click.drag", null); }, 0);
21054 if ("onselectstart" in root) {
21055 selection$$1.on("selectstart.drag", null);
21057 root.style.MozUserSelect = root.__noselect;
21058 delete root.__noselect;
21062 var constant$2 = function(x) {
21063 return function() {
21068 function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) {
21069 this.target = target;
21071 this.subject = subject;
21072 this.identifier = id;
21073 this.active = active;
21081 DragEvent.prototype.on = function() {
21082 var value = this._.on.apply(this._, arguments);
21083 return value === this._ ? this : value;
21086 // Ignore right-click, since that should open the context menu.
21087 function defaultFilter$1() {
21088 return !event.button;
21091 function defaultContainer() {
21092 return this.parentNode;
21095 function defaultSubject(d) {
21096 return d == null ? {x: event.x, y: event.y} : d;
21099 var drag = function() {
21100 var filter = defaultFilter$1,
21101 container = defaultContainer,
21102 subject = defaultSubject,
21104 listeners = dispatch("start", "drag", "end"),
21109 function drag(selection$$1) {
21111 .on("mousedown.drag", mousedowned)
21112 .on("touchstart.drag", touchstarted)
21113 .on("touchmove.drag", touchmoved)
21114 .on("touchend.drag touchcancel.drag", touchended)
21115 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
21118 function mousedowned() {
21119 if (touchending || !filter.apply(this, arguments)) return;
21120 var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments);
21121 if (!gesture) return;
21122 select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
21123 dragDisable(event.view);
21125 mousemoving = false;
21129 function mousemoved() {
21131 mousemoving = true;
21132 gestures.mouse("drag");
21135 function mouseupped() {
21136 select(event.view).on("mousemove.drag mouseup.drag", null);
21137 yesdrag(event.view, mousemoving);
21139 gestures.mouse("end");
21142 function touchstarted() {
21143 if (!filter.apply(this, arguments)) return;
21144 var touches$$1 = event.changedTouches,
21145 c = container.apply(this, arguments),
21146 n = touches$$1.length, i, gesture;
21148 for (i = 0; i < n; ++i) {
21149 if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) {
21156 function touchmoved() {
21157 var touches$$1 = event.changedTouches,
21158 n = touches$$1.length, i, gesture;
21160 for (i = 0; i < n; ++i) {
21161 if (gesture = gestures[touches$$1[i].identifier]) {
21168 function touchended() {
21169 var touches$$1 = event.changedTouches,
21170 n = touches$$1.length, i, gesture;
21172 if (touchending) clearTimeout(touchending);
21173 touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
21174 for (i = 0; i < n; ++i) {
21175 if (gesture = gestures[touches$$1[i].identifier]) {
21182 function beforestart(id, container, point, that, args) {
21183 var p = point(container, id), s, dx, dy,
21184 sublisteners = listeners.copy();
21186 if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() {
21187 if ((event.subject = s = subject.apply(that, args)) == null) return false;
21188 dx = s.x - p[0] || 0;
21189 dy = s.y - p[1] || 0;
21193 return function gesture(type) {
21196 case "start": gestures[id] = gesture, n = active++; break;
21197 case "end": delete gestures[id], --active; // nobreak
21198 case "drag": p = point(container, id), n = active; break;
21200 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]);
21204 drag.filter = function(_) {
21205 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter;
21208 drag.container = function(_) {
21209 return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container;
21212 drag.subject = function(_) {
21213 return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject;
21216 drag.on = function() {
21217 var value = listeners.on.apply(listeners, arguments);
21218 return value === listeners ? drag : value;
21224 var define = function(constructor, factory, prototype) {
21225 constructor.prototype = factory.prototype = prototype;
21226 prototype.constructor = constructor;
21229 function extend(parent, definition) {
21230 var prototype = Object.create(parent.prototype);
21231 for (var key in definition) prototype[key] = definition[key];
21235 function Color() {}
21238 var brighter = 1 / darker;
21240 var reI = "\\s*([+-]?\\d+)\\s*";
21241 var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*";
21242 var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*";
21243 var reHex3 = /^#([0-9a-f]{3})$/;
21244 var reHex6 = /^#([0-9a-f]{6})$/;
21245 var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$");
21246 var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$");
21247 var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$");
21248 var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$");
21249 var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$");
21250 var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
21253 aliceblue: 0xf0f8ff,
21254 antiquewhite: 0xfaebd7,
21256 aquamarine: 0x7fffd4,
21261 blanchedalmond: 0xffebcd,
21263 blueviolet: 0x8a2be2,
21265 burlywood: 0xdeb887,
21266 cadetblue: 0x5f9ea0,
21267 chartreuse: 0x7fff00,
21268 chocolate: 0xd2691e,
21270 cornflowerblue: 0x6495ed,
21271 cornsilk: 0xfff8dc,
21274 darkblue: 0x00008b,
21275 darkcyan: 0x008b8b,
21276 darkgoldenrod: 0xb8860b,
21277 darkgray: 0xa9a9a9,
21278 darkgreen: 0x006400,
21279 darkgrey: 0xa9a9a9,
21280 darkkhaki: 0xbdb76b,
21281 darkmagenta: 0x8b008b,
21282 darkolivegreen: 0x556b2f,
21283 darkorange: 0xff8c00,
21284 darkorchid: 0x9932cc,
21286 darksalmon: 0xe9967a,
21287 darkseagreen: 0x8fbc8f,
21288 darkslateblue: 0x483d8b,
21289 darkslategray: 0x2f4f4f,
21290 darkslategrey: 0x2f4f4f,
21291 darkturquoise: 0x00ced1,
21292 darkviolet: 0x9400d3,
21293 deeppink: 0xff1493,
21294 deepskyblue: 0x00bfff,
21297 dodgerblue: 0x1e90ff,
21298 firebrick: 0xb22222,
21299 floralwhite: 0xfffaf0,
21300 forestgreen: 0x228b22,
21302 gainsboro: 0xdcdcdc,
21303 ghostwhite: 0xf8f8ff,
21305 goldenrod: 0xdaa520,
21308 greenyellow: 0xadff2f,
21310 honeydew: 0xf0fff0,
21312 indianred: 0xcd5c5c,
21316 lavender: 0xe6e6fa,
21317 lavenderblush: 0xfff0f5,
21318 lawngreen: 0x7cfc00,
21319 lemonchiffon: 0xfffacd,
21320 lightblue: 0xadd8e6,
21321 lightcoral: 0xf08080,
21322 lightcyan: 0xe0ffff,
21323 lightgoldenrodyellow: 0xfafad2,
21324 lightgray: 0xd3d3d3,
21325 lightgreen: 0x90ee90,
21326 lightgrey: 0xd3d3d3,
21327 lightpink: 0xffb6c1,
21328 lightsalmon: 0xffa07a,
21329 lightseagreen: 0x20b2aa,
21330 lightskyblue: 0x87cefa,
21331 lightslategray: 0x778899,
21332 lightslategrey: 0x778899,
21333 lightsteelblue: 0xb0c4de,
21334 lightyellow: 0xffffe0,
21336 limegreen: 0x32cd32,
21340 mediumaquamarine: 0x66cdaa,
21341 mediumblue: 0x0000cd,
21342 mediumorchid: 0xba55d3,
21343 mediumpurple: 0x9370db,
21344 mediumseagreen: 0x3cb371,
21345 mediumslateblue: 0x7b68ee,
21346 mediumspringgreen: 0x00fa9a,
21347 mediumturquoise: 0x48d1cc,
21348 mediumvioletred: 0xc71585,
21349 midnightblue: 0x191970,
21350 mintcream: 0xf5fffa,
21351 mistyrose: 0xffe4e1,
21352 moccasin: 0xffe4b5,
21353 navajowhite: 0xffdead,
21357 olivedrab: 0x6b8e23,
21359 orangered: 0xff4500,
21361 palegoldenrod: 0xeee8aa,
21362 palegreen: 0x98fb98,
21363 paleturquoise: 0xafeeee,
21364 palevioletred: 0xdb7093,
21365 papayawhip: 0xffefd5,
21366 peachpuff: 0xffdab9,
21370 powderblue: 0xb0e0e6,
21372 rebeccapurple: 0x663399,
21374 rosybrown: 0xbc8f8f,
21375 royalblue: 0x4169e1,
21376 saddlebrown: 0x8b4513,
21378 sandybrown: 0xf4a460,
21379 seagreen: 0x2e8b57,
21380 seashell: 0xfff5ee,
21384 slateblue: 0x6a5acd,
21385 slategray: 0x708090,
21386 slategrey: 0x708090,
21388 springgreen: 0x00ff7f,
21389 steelblue: 0x4682b4,
21394 turquoise: 0x40e0d0,
21398 whitesmoke: 0xf5f5f5,
21400 yellowgreen: 0x9acd32
21403 define(Color, color, {
21404 displayable: function() {
21405 return this.rgb().displayable();
21407 toString: function() {
21408 return this.rgb() + "";
21412 function color(format) {
21414 format = (format + "").trim().toLowerCase();
21415 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
21416 : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
21417 : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
21418 : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
21419 : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
21420 : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
21421 : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
21422 : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
21423 : named.hasOwnProperty(format) ? rgbn(named[format])
21424 : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
21429 return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
21432 function rgba(r, g, b, a) {
21433 if (a <= 0) r = g = b = NaN;
21434 return new Rgb(r, g, b, a);
21437 function rgbConvert(o) {
21438 if (!(o instanceof Color)) o = color(o);
21439 if (!o) return new Rgb;
21441 return new Rgb(o.r, o.g, o.b, o.opacity);
21444 function rgb(r, g, b, opacity) {
21445 return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
21448 function Rgb(r, g, b, opacity) {
21452 this.opacity = +opacity;
21455 define(Rgb, rgb, extend(Color, {
21456 brighter: function(k) {
21457 k = k == null ? brighter : Math.pow(brighter, k);
21458 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
21460 darker: function(k) {
21461 k = k == null ? darker : Math.pow(darker, k);
21462 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
21467 displayable: function() {
21468 return (0 <= this.r && this.r <= 255)
21469 && (0 <= this.g && this.g <= 255)
21470 && (0 <= this.b && this.b <= 255)
21471 && (0 <= this.opacity && this.opacity <= 1);
21473 toString: function() {
21474 var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
21475 return (a === 1 ? "rgb(" : "rgba(")
21476 + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
21477 + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
21478 + Math.max(0, Math.min(255, Math.round(this.b) || 0))
21479 + (a === 1 ? ")" : ", " + a + ")");
21483 function hsla(h, s, l, a) {
21484 if (a <= 0) h = s = l = NaN;
21485 else if (l <= 0 || l >= 1) h = s = NaN;
21486 else if (s <= 0) h = NaN;
21487 return new Hsl(h, s, l, a);
21490 function hslConvert(o) {
21491 if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
21492 if (!(o instanceof Color)) o = color(o);
21493 if (!o) return new Hsl;
21494 if (o instanceof Hsl) return o;
21499 min = Math.min(r, g, b),
21500 max = Math.max(r, g, b),
21503 l = (max + min) / 2;
21505 if (r === max) h = (g - b) / s + (g < b) * 6;
21506 else if (g === max) h = (b - r) / s + 2;
21507 else h = (r - g) / s + 4;
21508 s /= l < 0.5 ? max + min : 2 - max - min;
21511 s = l > 0 && l < 1 ? 0 : h;
21513 return new Hsl(h, s, l, o.opacity);
21516 function hsl(h, s, l, opacity) {
21517 return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
21520 function Hsl(h, s, l, opacity) {
21524 this.opacity = +opacity;
21527 define(Hsl, hsl, extend(Color, {
21528 brighter: function(k) {
21529 k = k == null ? brighter : Math.pow(brighter, k);
21530 return new Hsl(this.h, this.s, this.l * k, this.opacity);
21532 darker: function(k) {
21533 k = k == null ? darker : Math.pow(darker, k);
21534 return new Hsl(this.h, this.s, this.l * k, this.opacity);
21537 var h = this.h % 360 + (this.h < 0) * 360,
21538 s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
21540 m2 = l + (l < 0.5 ? l : 1 - l) * s,
21543 hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
21544 hsl2rgb(h, m1, m2),
21545 hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
21549 displayable: function() {
21550 return (0 <= this.s && this.s <= 1 || isNaN(this.s))
21551 && (0 <= this.l && this.l <= 1)
21552 && (0 <= this.opacity && this.opacity <= 1);
21556 /* From FvD 13.37, CSS Color Module Level 3 */
21557 function hsl2rgb(h, m1, m2) {
21558 return (h < 60 ? m1 + (m2 - m1) * h / 60
21560 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
21564 var deg2rad = Math.PI / 180;
21565 var rad2deg = 180 / Math.PI;
21573 var t2 = 3 * t1 * t1;
21574 var t3 = t1 * t1 * t1;
21576 function labConvert(o) {
21577 if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
21578 if (o instanceof Hcl) {
21579 var h = o.h * deg2rad;
21580 return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
21582 if (!(o instanceof Rgb)) o = rgbConvert(o);
21583 var b = rgb2xyz(o.r),
21586 x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
21587 y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
21588 z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
21589 return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
21592 function lab(l, a, b, opacity) {
21593 return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
21596 function Lab(l, a, b, opacity) {
21600 this.opacity = +opacity;
21603 define(Lab, lab, extend(Color, {
21604 brighter: function(k) {
21605 return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
21607 darker: function(k) {
21608 return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
21611 var y = (this.l + 16) / 116,
21612 x = isNaN(this.a) ? y : y + this.a / 500,
21613 z = isNaN(this.b) ? y : y - this.b / 200;
21614 y = Yn * lab2xyz(y);
21615 x = Xn * lab2xyz(x);
21616 z = Zn * lab2xyz(z);
21618 xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
21619 xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
21620 xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
21626 function xyz2lab(t) {
21627 return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
21630 function lab2xyz(t) {
21631 return t > t1 ? t * t * t : t2 * (t - t0);
21634 function xyz2rgb(x) {
21635 return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
21638 function rgb2xyz(x) {
21639 return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
21642 function hclConvert(o) {
21643 if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
21644 if (!(o instanceof Lab)) o = labConvert(o);
21645 var h = Math.atan2(o.b, o.a) * rad2deg;
21646 return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
21649 function hcl(h, c, l, opacity) {
21650 return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
21653 function Hcl(h, c, l, opacity) {
21657 this.opacity = +opacity;
21660 define(Hcl, hcl, extend(Color, {
21661 brighter: function(k) {
21662 return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
21664 darker: function(k) {
21665 return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
21668 return labConvert(this).rgb();
21679 var BC_DA = B * C - D * A;
21681 function cubehelixConvert(o) {
21682 if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
21683 if (!(o instanceof Rgb)) o = rgbConvert(o);
21687 l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
21689 k = (E * (g - l) - C * bl) / D,
21690 s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
21691 h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
21692 return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
21695 function cubehelix(h, s, l, opacity) {
21696 return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
21699 function Cubehelix(h, s, l, opacity) {
21703 this.opacity = +opacity;
21706 define(Cubehelix, cubehelix, extend(Color, {
21707 brighter: function(k) {
21708 k = k == null ? brighter : Math.pow(brighter, k);
21709 return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
21711 darker: function(k) {
21712 k = k == null ? darker : Math.pow(darker, k);
21713 return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
21716 var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
21718 a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
21719 cosh = Math.cos(h),
21720 sinh = Math.sin(h);
21722 255 * (l + a * (A * cosh + B * sinh)),
21723 255 * (l + a * (C * cosh + D * sinh)),
21724 255 * (l + a * (E * cosh)),
21730 function basis(t1, v0, v1, v2, v3) {
21731 var t2 = t1 * t1, t3 = t2 * t1;
21732 return ((1 - 3 * t1 + 3 * t2 - t3) * v0
21733 + (4 - 6 * t2 + 3 * t3) * v1
21734 + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
21738 var basis$1 = function(values) {
21739 var n = values.length - 1;
21740 return function(t) {
21741 var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
21743 v2 = values[i + 1],
21744 v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
21745 v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
21746 return basis((t - i / n) * n, v0, v1, v2, v3);
21750 var basisClosed = function(values) {
21751 var n = values.length;
21752 return function(t) {
21753 var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),
21754 v0 = values[(i + n - 1) % n],
21755 v1 = values[i % n],
21756 v2 = values[(i + 1) % n],
21757 v3 = values[(i + 2) % n];
21758 return basis((t - i / n) * n, v0, v1, v2, v3);
21762 var constant$3 = function(x) {
21763 return function() {
21768 function linear(a, d) {
21769 return function(t) {
21774 function exponential(a, b, y) {
21775 return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
21776 return Math.pow(a + t * b, y);
21780 function hue(a, b) {
21782 return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a);
21785 function gamma(y) {
21786 return (y = +y) === 1 ? nogamma : function(a, b) {
21787 return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a);
21791 function nogamma(a, b) {
21793 return d ? linear(a, d) : constant$3(isNaN(a) ? b : a);
21796 var interpolateRgb = ((function rgbGamma(y) {
21797 var color$$1 = gamma(y);
21799 function rgb$$1(start, end) {
21800 var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r),
21801 g = color$$1(start.g, end.g),
21802 b = color$$1(start.b, end.b),
21803 opacity = nogamma(start.opacity, end.opacity);
21804 return function(t) {
21808 start.opacity = opacity(t);
21813 rgb$$1.gamma = rgbGamma;
21818 function rgbSpline(spline) {
21819 return function(colors) {
21820 var n = colors.length,
21825 for (i = 0; i < n; ++i) {
21826 color$$1 = rgb(colors[i]);
21827 r[i] = color$$1.r || 0;
21828 g[i] = color$$1.g || 0;
21829 b[i] = color$$1.b || 0;
21834 color$$1.opacity = 1;
21835 return function(t) {
21839 return color$$1 + "";
21844 var rgbBasis = rgbSpline(basis$1);
21845 var rgbBasisClosed = rgbSpline(basisClosed);
21847 var array$1 = function(a, b) {
21848 var nb = b ? b.length : 0,
21849 na = a ? Math.min(nb, a.length) : 0,
21854 for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]);
21855 for (; i < nb; ++i) c[i] = b[i];
21857 return function(t) {
21858 for (i = 0; i < na; ++i) c[i] = x[i](t);
21863 var date = function(a, b) {
21865 return a = +a, b -= a, function(t) {
21866 return d.setTime(a + b * t), d;
21870 var reinterpolate = function(a, b) {
21871 return a = +a, b -= a, function(t) {
21876 var object = function(a, b) {
21881 if (a === null || typeof a !== "object") a = {};
21882 if (b === null || typeof b !== "object") b = {};
21886 i[k] = interpolateValue(a[k], b[k]);
21892 return function(t) {
21893 for (k in i) c[k] = i[k](t);
21898 var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
21899 var reB = new RegExp(reA.source, "g");
21902 return function() {
21908 return function(t) {
21913 var interpolateString = function(a, b) {
21914 var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
21915 am, // current match in a
21916 bm, // current match in b
21917 bs, // string preceding current number in b, if any
21918 i = -1, // index in s
21919 s = [], // string constants and placeholders
21920 q = []; // number interpolators
21922 // Coerce inputs to strings.
21923 a = a + "", b = b + "";
21925 // Interpolate pairs of numbers in a & b.
21926 while ((am = reA.exec(a))
21927 && (bm = reB.exec(b))) {
21928 if ((bs = bm.index) > bi) { // a string precedes the next number in b
21929 bs = b.slice(bi, bs);
21930 if (s[i]) s[i] += bs; // coalesce with previous string
21933 if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
21934 if (s[i]) s[i] += bm; // coalesce with previous string
21936 } else { // interpolate non-matching numbers
21938 q.push({i: i, x: reinterpolate(am, bm)});
21940 bi = reB.lastIndex;
21943 // Add remains of b.
21944 if (bi < b.length) {
21946 if (s[i]) s[i] += bs; // coalesce with previous string
21950 // Special optimization for only a single match.
21951 // Otherwise, interpolate each of the numbers and rejoin the string.
21952 return s.length < 2 ? (q[0]
21955 : (b = q.length, function(t) {
21956 for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
21961 var interpolateValue = function(a, b) {
21962 var t = typeof b, c;
21963 return b == null || t === "boolean" ? constant$3(b)
21964 : (t === "number" ? reinterpolate
21965 : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString)
21966 : b instanceof color ? interpolateRgb
21967 : b instanceof Date ? date
21968 : Array.isArray(b) ? array$1
21969 : isNaN(b) ? object
21970 : reinterpolate)(a, b);
21973 var interpolateRound = function(a, b) {
21974 return a = +a, b -= a, function(t) {
21975 return Math.round(a + b * t);
21979 var degrees = 180 / Math.PI;
21990 var decompose = function(a, b, c, d, e, f) {
21991 var scaleX, scaleY, skewX;
21992 if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
21993 if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
21994 if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
21995 if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
21999 rotate: Math.atan2(b, a) * degrees,
22000 skewX: Math.atan(skewX) * degrees,
22011 function parseCss(value) {
22012 if (value === "none") return identity$2;
22013 if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView;
22014 cssNode.style.transform = value;
22015 value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform");
22016 cssRoot.removeChild(cssNode);
22017 value = value.slice(7, -1).split(",");
22018 return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
22021 function parseSvg(value) {
22022 if (value == null) return identity$2;
22023 if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
22024 svgNode.setAttribute("transform", value);
22025 if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2;
22026 value = value.matrix;
22027 return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
22030 function interpolateTransform(parse, pxComma, pxParen, degParen) {
22033 return s.length ? s.pop() + " " : "";
22036 function translate(xa, ya, xb, yb, s, q) {
22037 if (xa !== xb || ya !== yb) {
22038 var i = s.push("translate(", null, pxComma, null, pxParen);
22039 q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)});
22040 } else if (xb || yb) {
22041 s.push("translate(" + xb + pxComma + yb + pxParen);
22045 function rotate(a, b, s, q) {
22047 if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
22048 q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: reinterpolate(a, b)});
22050 s.push(pop(s) + "rotate(" + b + degParen);
22054 function skewX(a, b, s, q) {
22056 q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: reinterpolate(a, b)});
22058 s.push(pop(s) + "skewX(" + b + degParen);
22062 function scale(xa, ya, xb, yb, s, q) {
22063 if (xa !== xb || ya !== yb) {
22064 var i = s.push(pop(s) + "scale(", null, ",", null, ")");
22065 q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)});
22066 } else if (xb !== 1 || yb !== 1) {
22067 s.push(pop(s) + "scale(" + xb + "," + yb + ")");
22071 return function(a, b) {
22072 var s = [], // string constants and placeholders
22073 q = []; // number interpolators
22074 a = parse(a), b = parse(b);
22075 translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
22076 rotate(a.rotate, b.rotate, s, q);
22077 skewX(a.skewX, b.skewX, s, q);
22078 scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
22079 a = b = null; // gc
22080 return function(t) {
22081 var i = -1, n = q.length, o;
22082 while (++i < n) s[(o = q[i]).i] = o.x(t);
22088 var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
22089 var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
22091 var rho = Math.SQRT2;
22094 var epsilon2 = 1e-12;
22097 return ((x = Math.exp(x)) + 1 / x) / 2;
22101 return ((x = Math.exp(x)) - 1 / x) / 2;
22105 return ((x = Math.exp(2 * x)) - 1) / (x + 1);
22108 // p0 = [ux0, uy0, w0]
22109 // p1 = [ux1, uy1, w1]
22110 var interpolateZoom = function(p0, p1) {
22111 var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
22112 ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
22115 d2 = dx * dx + dy * dy,
22119 // Special case for u0 ≅ u1.
22120 if (d2 < epsilon2) {
22121 S = Math.log(w1 / w0) / rho;
22126 w0 * Math.exp(rho * t * S)
22133 var d1 = Math.sqrt(d2),
22134 b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
22135 b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
22136 r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
22137 r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
22138 S = (r1 - r0) / rho;
22142 u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
22146 w0 * coshr0 / cosh(rho * s + r0)
22151 i.duration = S * 1000;
22156 function hsl$1(hue$$1) {
22157 return function(start, end) {
22158 var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h),
22159 s = nogamma(start.s, end.s),
22160 l = nogamma(start.l, end.l),
22161 opacity = nogamma(start.opacity, end.opacity);
22162 return function(t) {
22166 start.opacity = opacity(t);
22172 var hsl$2 = hsl$1(hue);
22173 var hslLong = hsl$1(nogamma);
22175 function lab$1(start, end) {
22176 var l = nogamma((start = lab(start)).l, (end = lab(end)).l),
22177 a = nogamma(start.a, end.a),
22178 b = nogamma(start.b, end.b),
22179 opacity = nogamma(start.opacity, end.opacity);
22180 return function(t) {
22184 start.opacity = opacity(t);
22189 function hcl$1(hue$$1) {
22190 return function(start, end) {
22191 var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h),
22192 c = nogamma(start.c, end.c),
22193 l = nogamma(start.l, end.l),
22194 opacity = nogamma(start.opacity, end.opacity);
22195 return function(t) {
22199 start.opacity = opacity(t);
22205 var hcl$2 = hcl$1(hue);
22206 var hclLong = hcl$1(nogamma);
22208 function cubehelix$1(hue$$1) {
22209 return (function cubehelixGamma(y) {
22212 function cubehelix$$1(start, end) {
22213 var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h),
22214 s = nogamma(start.s, end.s),
22215 l = nogamma(start.l, end.l),
22216 opacity = nogamma(start.opacity, end.opacity);
22217 return function(t) {
22220 start.l = l(Math.pow(t, y));
22221 start.opacity = opacity(t);
22226 cubehelix$$1.gamma = cubehelixGamma;
22228 return cubehelix$$1;
22232 var cubehelix$2 = cubehelix$1(hue);
22233 var cubehelixLong = cubehelix$1(nogamma);
22235 var quantize = function(interpolator, n) {
22236 var samples = new Array(n);
22237 for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));
22244 var pokeDelay = 1000;
22250 var clock = typeof performance === "object" && performance.now ? performance : Date;
22251 var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); };
22254 return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
22257 function clearNow() {
22267 Timer.prototype = timer.prototype = {
22268 constructor: Timer,
22269 restart: function(callback, delay, time) {
22270 if (typeof callback !== "function") throw new TypeError("callback is not a function");
22271 time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
22272 if (!this._next && taskTail !== this) {
22273 if (taskTail) taskTail._next = this;
22274 else taskHead = this;
22277 this._call = callback;
22284 this._time = Infinity;
22290 function timer(callback, delay, time) {
22292 t.restart(callback, delay, time);
22296 function timerFlush() {
22297 now(); // Get the current time, if not already set.
22298 ++frame; // Pretend we’ve set an alarm, if we haven’t already.
22299 var t = taskHead, e;
22301 if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
22308 clockNow = (clockLast = clock.now()) + clockSkew;
22309 frame = timeout = 0;
22320 var now = clock.now(), delay = now - clockLast;
22321 if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
22325 var t0, t1 = taskHead, t2, time = Infinity;
22328 if (time > t1._time) time = t1._time;
22329 t0 = t1, t1 = t1._next;
22331 t2 = t1._next, t1._next = null;
22332 t1 = t0 ? t0._next = t2 : taskHead = t2;
22339 function sleep(time) {
22340 if (frame) return; // Soonest alarm already set, or will be.
22341 if (timeout) timeout = clearTimeout(timeout);
22342 var delay = time - clockNow;
22344 if (time < Infinity) timeout = setTimeout(wake, delay);
22345 if (interval) interval = clearInterval(interval);
22347 if (!interval) clockLast = clockNow, interval = setInterval(poke, pokeDelay);
22348 frame = 1, setFrame(wake);
22352 var timeout$1 = function(callback, delay, time) {
22354 delay = delay == null ? 0 : +delay;
22355 t.restart(function(elapsed) {
22357 callback(elapsed + delay);
22362 var interval$1 = function(callback, delay, time) {
22363 var t = new Timer, total = delay;
22364 if (delay == null) return t.restart(callback, delay, time), t;
22365 delay = +delay, time = time == null ? now() : +time;
22366 t.restart(function tick(elapsed) {
22368 t.restart(tick, total += delay, time);
22374 var emptyOn = dispatch("start", "end", "interrupt");
22375 var emptyTween = [];
22385 var schedule = function(node, name, id, index, group, timing) {
22386 var schedules = node.__transition;
22387 if (!schedules) node.__transition = {};
22388 else if (id in schedules) return;
22391 index: index, // For context during callback.
22392 group: group, // For context during callback.
22396 delay: timing.delay,
22397 duration: timing.duration,
22404 function init(node, id) {
22405 var schedule = node.__transition;
22406 if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late");
22410 function set$1(node, id) {
22411 var schedule = node.__transition;
22412 if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late");
22416 function get$1(node, id) {
22417 var schedule = node.__transition;
22418 if (!schedule || !(schedule = schedule[id])) throw new Error("too late");
22422 function create(node, id, self) {
22423 var schedules = node.__transition,
22426 // Initialize the self timer when the transition is created.
22427 // Note the actual delay is not known until the first callback!
22428 schedules[id] = self;
22429 self.timer = timer(schedule, 0, self.time);
22431 function schedule(elapsed) {
22432 self.state = SCHEDULED;
22433 self.timer.restart(start, self.delay, self.time);
22435 // If the elapsed delay is less than our first sleep, start immediately.
22436 if (self.delay <= elapsed) start(elapsed - self.delay);
22439 function start(elapsed) {
22442 // If the state is not SCHEDULED, then we previously errored on start.
22443 if (self.state !== SCHEDULED) return stop();
22445 for (i in schedules) {
22447 if (o.name !== self.name) continue;
22449 // While this element already has a starting transition during this frame,
22450 // defer starting an interrupting transition until that transition has a
22451 // chance to tick (and possibly end); see d3/d3-transition#54!
22452 if (o.state === STARTED) return timeout$1(start);
22454 // Interrupt the active transition, if any.
22455 // Dispatch the interrupt event.
22456 if (o.state === RUNNING) {
22459 o.on.call("interrupt", node, node.__data__, o.index, o.group);
22460 delete schedules[i];
22463 // Cancel any pre-empted transitions. No interrupt event is dispatched
22464 // because the cancelled transitions never started. Note that this also
22465 // removes this transition from the pending list!
22466 else if (+i < id) {
22469 delete schedules[i];
22473 // Defer the first tick to end of the current frame; see d3/d3#1576.
22474 // Note the transition may be canceled after start and before the first tick!
22475 // Note this must be scheduled before the start event; see d3/d3-transition#16!
22476 // Assuming this is successful, subsequent callbacks go straight to tick.
22477 timeout$1(function() {
22478 if (self.state === STARTED) {
22479 self.state = RUNNING;
22480 self.timer.restart(tick, self.delay, self.time);
22485 // Dispatch the start event.
22486 // Note this must be done before the tween are initialized.
22487 self.state = STARTING;
22488 self.on.call("start", node, node.__data__, self.index, self.group);
22489 if (self.state !== STARTING) return; // interrupted
22490 self.state = STARTED;
22492 // Initialize the tween, deleting null tween.
22493 tween = new Array(n = self.tween.length);
22494 for (i = 0, j = -1; i < n; ++i) {
22495 if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
22499 tween.length = j + 1;
22502 function tick(elapsed) {
22503 var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
22508 tween[i].call(null, t);
22511 // Dispatch the end event.
22512 if (self.state === ENDING) {
22513 self.on.call("end", node, node.__data__, self.index, self.group);
22519 self.state = ENDED;
22521 delete schedules[id];
22522 for (var i in schedules) return; // eslint-disable-line no-unused-vars
22523 delete node.__transition;
22527 var interrupt = function(node, name) {
22528 var schedules = node.__transition,
22534 if (!schedules) return;
22536 name = name == null ? null : name + "";
22538 for (i in schedules) {
22539 if ((schedule = schedules[i]).name !== name) { empty = false; continue; }
22540 active = schedule.state > STARTING && schedule.state < ENDING;
22541 schedule.state = ENDED;
22542 schedule.timer.stop();
22543 if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group);
22544 delete schedules[i];
22547 if (empty) delete node.__transition;
22550 var selection_interrupt = function(name) {
22551 return this.each(function() {
22552 interrupt(this, name);
22556 function tweenRemove(id, name) {
22557 var tween0, tween1;
22558 return function() {
22559 var schedule = set$1(this, id),
22560 tween = schedule.tween;
22562 // If this node shared tween with the previous node,
22563 // just assign the updated shared tween and we’re done!
22564 // Otherwise, copy-on-write.
22565 if (tween !== tween0) {
22566 tween1 = tween0 = tween;
22567 for (var i = 0, n = tween1.length; i < n; ++i) {
22568 if (tween1[i].name === name) {
22569 tween1 = tween1.slice();
22570 tween1.splice(i, 1);
22576 schedule.tween = tween1;
22580 function tweenFunction(id, name, value) {
22581 var tween0, tween1;
22582 if (typeof value !== "function") throw new Error;
22583 return function() {
22584 var schedule = set$1(this, id),
22585 tween = schedule.tween;
22587 // If this node shared tween with the previous node,
22588 // just assign the updated shared tween and we’re done!
22589 // Otherwise, copy-on-write.
22590 if (tween !== tween0) {
22591 tween1 = (tween0 = tween).slice();
22592 for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) {
22593 if (tween1[i].name === name) {
22598 if (i === n) tween1.push(t);
22601 schedule.tween = tween1;
22605 var transition_tween = function(name, value) {
22610 if (arguments.length < 2) {
22611 var tween = get$1(this.node(), id).tween;
22612 for (var i = 0, n = tween.length, t; i < n; ++i) {
22613 if ((t = tween[i]).name === name) {
22620 return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
22623 function tweenValue(transition, name, value) {
22624 var id = transition._id;
22626 transition.each(function() {
22627 var schedule = set$1(this, id);
22628 (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
22631 return function(node) {
22632 return get$1(node, id).value[name];
22636 var interpolate$$1 = function(a, b) {
22638 return (typeof b === "number" ? reinterpolate
22639 : b instanceof color ? interpolateRgb
22640 : (c = color(b)) ? (b = c, interpolateRgb)
22641 : interpolateString)(a, b);
22644 function attrRemove$1(name) {
22645 return function() {
22646 this.removeAttribute(name);
22650 function attrRemoveNS$1(fullname) {
22651 return function() {
22652 this.removeAttributeNS(fullname.space, fullname.local);
22656 function attrConstant$1(name, interpolate$$1, value1) {
22659 return function() {
22660 var value0 = this.getAttribute(name);
22661 return value0 === value1 ? null
22662 : value0 === value00 ? interpolate0
22663 : interpolate0 = interpolate$$1(value00 = value0, value1);
22667 function attrConstantNS$1(fullname, interpolate$$1, value1) {
22670 return function() {
22671 var value0 = this.getAttributeNS(fullname.space, fullname.local);
22672 return value0 === value1 ? null
22673 : value0 === value00 ? interpolate0
22674 : interpolate0 = interpolate$$1(value00 = value0, value1);
22678 function attrFunction$1(name, interpolate$$1, value) {
22682 return function() {
22683 var value0, value1 = value(this);
22684 if (value1 == null) return void this.removeAttribute(name);
22685 value0 = this.getAttribute(name);
22686 return value0 === value1 ? null
22687 : value0 === value00 && value1 === value10 ? interpolate0
22688 : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22692 function attrFunctionNS$1(fullname, interpolate$$1, value) {
22696 return function() {
22697 var value0, value1 = value(this);
22698 if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
22699 value0 = this.getAttributeNS(fullname.space, fullname.local);
22700 return value0 === value1 ? null
22701 : value0 === value00 && value1 === value10 ? interpolate0
22702 : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22706 var transition_attr = function(name, value) {
22707 var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$$1;
22708 return this.attrTween(name, typeof value === "function"
22709 ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value))
22710 : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname)
22711 : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value + ""));
22714 function attrTweenNS(fullname, value) {
22716 var node = this, i = value.apply(node, arguments);
22717 return i && function(t) {
22718 node.setAttributeNS(fullname.space, fullname.local, i(t));
22721 tween._value = value;
22725 function attrTween(name, value) {
22727 var node = this, i = value.apply(node, arguments);
22728 return i && function(t) {
22729 node.setAttribute(name, i(t));
22732 tween._value = value;
22736 var transition_attrTween = function(name, value) {
22737 var key = "attr." + name;
22738 if (arguments.length < 2) return (key = this.tween(key)) && key._value;
22739 if (value == null) return this.tween(key, null);
22740 if (typeof value !== "function") throw new Error;
22741 var fullname = namespace(name);
22742 return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
22745 function delayFunction(id, value) {
22746 return function() {
22747 init(this, id).delay = +value.apply(this, arguments);
22751 function delayConstant(id, value) {
22752 return value = +value, function() {
22753 init(this, id).delay = value;
22757 var transition_delay = function(value) {
22760 return arguments.length
22761 ? this.each((typeof value === "function"
22763 : delayConstant)(id, value))
22764 : get$1(this.node(), id).delay;
22767 function durationFunction(id, value) {
22768 return function() {
22769 set$1(this, id).duration = +value.apply(this, arguments);
22773 function durationConstant(id, value) {
22774 return value = +value, function() {
22775 set$1(this, id).duration = value;
22779 var transition_duration = function(value) {
22782 return arguments.length
22783 ? this.each((typeof value === "function"
22785 : durationConstant)(id, value))
22786 : get$1(this.node(), id).duration;
22789 function easeConstant(id, value) {
22790 if (typeof value !== "function") throw new Error;
22791 return function() {
22792 set$1(this, id).ease = value;
22796 var transition_ease = function(value) {
22799 return arguments.length
22800 ? this.each(easeConstant(id, value))
22801 : get$1(this.node(), id).ease;
22804 var transition_filter = function(match) {
22805 if (typeof match !== "function") match = matcher$1(match);
22807 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
22808 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
22809 if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
22810 subgroup.push(node);
22815 return new Transition(subgroups, this._parents, this._name, this._id);
22818 var transition_merge = function(transition) {
22819 if (transition._id !== this._id) throw new Error;
22821 for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
22822 for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
22823 if (node = group0[i] || group1[i]) {
22829 for (; j < m0; ++j) {
22830 merges[j] = groups0[j];
22833 return new Transition(merges, this._parents, this._name, this._id);
22836 function start(name) {
22837 return (name + "").trim().split(/^|\s+/).every(function(t) {
22838 var i = t.indexOf(".");
22839 if (i >= 0) t = t.slice(0, i);
22840 return !t || t === "start";
22844 function onFunction(id, name, listener) {
22845 var on0, on1, sit = start(name) ? init : set$1;
22846 return function() {
22847 var schedule = sit(this, id),
22850 // If this node shared a dispatch with the previous node,
22851 // just assign the updated shared dispatch and we’re done!
22852 // Otherwise, copy-on-write.
22853 if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
22859 var transition_on = function(name, listener) {
22862 return arguments.length < 2
22863 ? get$1(this.node(), id).on.on(name)
22864 : this.each(onFunction(id, name, listener));
22867 function removeFunction(id) {
22868 return function() {
22869 var parent = this.parentNode;
22870 for (var i in this.__transition) if (+i !== id) return;
22871 if (parent) parent.removeChild(this);
22875 var transition_remove = function() {
22876 return this.on("end.remove", removeFunction(this._id));
22879 var transition_select = function(select$$1) {
22880 var name = this._name,
22883 if (typeof select$$1 !== "function") select$$1 = selector(select$$1);
22885 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
22886 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
22887 if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) {
22888 if ("__data__" in node) subnode.__data__ = node.__data__;
22889 subgroup[i] = subnode;
22890 schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
22895 return new Transition(subgroups, this._parents, name, id);
22898 var transition_selectAll = function(select$$1) {
22899 var name = this._name,
22902 if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1);
22904 for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
22905 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
22906 if (node = group[i]) {
22907 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) {
22908 if (child = children[k]) {
22909 schedule(child, name, id, k, children, inherit);
22912 subgroups.push(children);
22913 parents.push(node);
22918 return new Transition(subgroups, parents, name, id);
22921 var Selection$1 = selection.prototype.constructor;
22923 var transition_selection = function() {
22924 return new Selection$1(this._groups, this._parents);
22927 function styleRemove$1(name, interpolate$$2) {
22931 return function() {
22932 var style = window$1(this).getComputedStyle(this, null),
22933 value0 = style.getPropertyValue(name),
22934 value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
22935 return value0 === value1 ? null
22936 : value0 === value00 && value1 === value10 ? interpolate0
22937 : interpolate0 = interpolate$$2(value00 = value0, value10 = value1);
22941 function styleRemoveEnd(name) {
22942 return function() {
22943 this.style.removeProperty(name);
22947 function styleConstant$1(name, interpolate$$2, value1) {
22950 return function() {
22951 var value0 = window$1(this).getComputedStyle(this, null).getPropertyValue(name);
22952 return value0 === value1 ? null
22953 : value0 === value00 ? interpolate0
22954 : interpolate0 = interpolate$$2(value00 = value0, value1);
22958 function styleFunction$1(name, interpolate$$2, value) {
22962 return function() {
22963 var style = window$1(this).getComputedStyle(this, null),
22964 value0 = style.getPropertyValue(name),
22965 value1 = value(this);
22966 if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
22967 return value0 === value1 ? null
22968 : value0 === value00 && value1 === value10 ? interpolate0
22969 : interpolate0 = interpolate$$2(value00 = value0, value10 = value1);
22973 var transition_style = function(name, value, priority) {
22974 var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$$1;
22975 return value == null ? this
22976 .styleTween(name, styleRemove$1(name, i))
22977 .on("end.style." + name, styleRemoveEnd(name))
22978 : this.styleTween(name, typeof value === "function"
22979 ? styleFunction$1(name, i, tweenValue(this, "style." + name, value))
22980 : styleConstant$1(name, i, value + ""), priority);
22983 function styleTween(name, value, priority) {
22985 var node = this, i = value.apply(node, arguments);
22986 return i && function(t) {
22987 node.style.setProperty(name, i(t), priority);
22990 tween._value = value;
22994 var transition_styleTween = function(name, value, priority) {
22995 var key = "style." + (name += "");
22996 if (arguments.length < 2) return (key = this.tween(key)) && key._value;
22997 if (value == null) return this.tween(key, null);
22998 if (typeof value !== "function") throw new Error;
22999 return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
23002 function textConstant$1(value) {
23003 return function() {
23004 this.textContent = value;
23008 function textFunction$1(value) {
23009 return function() {
23010 var value1 = value(this);
23011 this.textContent = value1 == null ? "" : value1;
23015 var transition_text = function(value) {
23016 return this.tween("text", typeof value === "function"
23017 ? textFunction$1(tweenValue(this, "text", value))
23018 : textConstant$1(value == null ? "" : value + ""));
23021 var transition_transition = function() {
23022 var name = this._name,
23026 for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
23027 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
23028 if (node = group[i]) {
23029 var inherit = get$1(node, id0);
23030 schedule(node, name, id1, i, group, {
23031 time: inherit.time + inherit.delay + inherit.duration,
23033 duration: inherit.duration,
23040 return new Transition(groups, this._parents, name, id1);
23045 function Transition(groups, parents, name, id) {
23046 this._groups = groups;
23047 this._parents = parents;
23052 function transition(name) {
23053 return selection().transition(name);
23060 var selection_prototype = selection.prototype;
23062 Transition.prototype = transition.prototype = {
23063 constructor: Transition,
23064 select: transition_select,
23065 selectAll: transition_selectAll,
23066 filter: transition_filter,
23067 merge: transition_merge,
23068 selection: transition_selection,
23069 transition: transition_transition,
23070 call: selection_prototype.call,
23071 nodes: selection_prototype.nodes,
23072 node: selection_prototype.node,
23073 size: selection_prototype.size,
23074 empty: selection_prototype.empty,
23075 each: selection_prototype.each,
23077 attr: transition_attr,
23078 attrTween: transition_attrTween,
23079 style: transition_style,
23080 styleTween: transition_styleTween,
23081 text: transition_text,
23082 remove: transition_remove,
23083 tween: transition_tween,
23084 delay: transition_delay,
23085 duration: transition_duration,
23086 ease: transition_ease
23089 function linear$1(t) {
23093 function quadIn(t) {
23097 function quadOut(t) {
23098 return t * (2 - t);
23101 function quadInOut(t) {
23102 return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
23105 function cubicIn(t) {
23109 function cubicOut(t) {
23110 return --t * t * t + 1;
23113 function cubicInOut(t) {
23114 return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
23119 var polyIn = (function custom(e) {
23122 function polyIn(t) {
23123 return Math.pow(t, e);
23126 polyIn.exponent = custom;
23131 var polyOut = (function custom(e) {
23134 function polyOut(t) {
23135 return 1 - Math.pow(1 - t, e);
23138 polyOut.exponent = custom;
23143 var polyInOut = (function custom(e) {
23146 function polyInOut(t) {
23147 return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2;
23150 polyInOut.exponent = custom;
23156 var halfPi = pi / 2;
23158 function sinIn(t) {
23159 return 1 - Math.cos(t * halfPi);
23162 function sinOut(t) {
23163 return Math.sin(t * halfPi);
23166 function sinInOut(t) {
23167 return (1 - Math.cos(pi * t)) / 2;
23170 function expIn(t) {
23171 return Math.pow(2, 10 * t - 10);
23174 function expOut(t) {
23175 return 1 - Math.pow(2, -10 * t);
23178 function expInOut(t) {
23179 return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2;
23182 function circleIn(t) {
23183 return 1 - Math.sqrt(1 - t * t);
23186 function circleOut(t) {
23187 return Math.sqrt(1 - --t * t);
23190 function circleInOut(t) {
23191 return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2;
23203 var b0 = 1 / b1 / b1;
23205 function bounceIn(t) {
23206 return 1 - bounceOut(1 - t);
23209 function bounceOut(t) {
23210 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;
23213 function bounceInOut(t) {
23214 return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2;
23217 var overshoot = 1.70158;
23219 var backIn = (function custom(s) {
23222 function backIn(t) {
23223 return t * t * ((s + 1) * t - s);
23226 backIn.overshoot = custom;
23231 var backOut = (function custom(s) {
23234 function backOut(t) {
23235 return --t * t * ((s + 1) * t + s) + 1;
23238 backOut.overshoot = custom;
23243 var backInOut = (function custom(s) {
23246 function backInOut(t) {
23247 return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2;
23250 backInOut.overshoot = custom;
23255 var tau = 2 * Math.PI;
23259 var elasticIn = (function custom(a, p) {
23260 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23262 function elasticIn(t) {
23263 return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p);
23266 elasticIn.amplitude = function(a) { return custom(a, p * tau); };
23267 elasticIn.period = function(p) { return custom(a, p); };
23270 })(amplitude, period);
23272 var elasticOut = (function custom(a, p) {
23273 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23275 function elasticOut(t) {
23276 return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p);
23279 elasticOut.amplitude = function(a) { return custom(a, p * tau); };
23280 elasticOut.period = function(p) { return custom(a, p); };
23283 })(amplitude, period);
23285 var elasticInOut = (function custom(a, p) {
23286 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23288 function elasticInOut(t) {
23289 return ((t = t * 2 - 1) < 0
23290 ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p)
23291 : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2;
23294 elasticInOut.amplitude = function(a) { return custom(a, p * tau); };
23295 elasticInOut.period = function(p) { return custom(a, p); };
23297 return elasticInOut;
23298 })(amplitude, period);
23300 var defaultTiming = {
23301 time: null, // Set on use.
23307 function inherit(node, id) {
23309 while (!(timing = node.__transition) || !(timing = timing[id])) {
23310 if (!(node = node.parentNode)) {
23311 return defaultTiming.time = now(), defaultTiming;
23317 var selection_transition = function(name) {
23321 if (name instanceof Transition) {
23322 id = name._id, name = name._name;
23324 id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "";
23327 for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
23328 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
23329 if (node = group[i]) {
23330 schedule(node, name, id, i, group, timing || inherit(node, id));
23335 return new Transition(groups, this._parents, name, id);
23338 selection.prototype.interrupt = selection_interrupt;
23339 selection.prototype.transition = selection_transition;
23341 var root$1 = [null];
23343 var active = function(node, name) {
23344 var schedules = node.__transition,
23349 name = name == null ? null : name + "";
23350 for (i in schedules) {
23351 if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) {
23352 return new Transition([[node]], root$1, name, +i);
23360 var constant$4 = function(x) {
23361 return function() {
23366 var BrushEvent = function(target, type, selection) {
23367 this.target = target;
23369 this.selection = selection;
23372 function nopropagation$1() {
23373 event.stopImmediatePropagation();
23376 var noevent$1 = function() {
23377 event.preventDefault();
23378 event.stopImmediatePropagation();
23381 var MODE_DRAG = {name: "drag"};
23382 var MODE_SPACE = {name: "space"};
23383 var MODE_HANDLE = {name: "handle"};
23384 var MODE_CENTER = {name: "center"};
23388 handles: ["e", "w"].map(type$2),
23389 input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
23390 output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
23395 handles: ["n", "s"].map(type$2),
23396 input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
23397 output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
23402 handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$2),
23403 input: function(xy) { return xy; },
23404 output: function(xy) { return xy; }
23408 overlay: "crosshair",
23464 function type$2(t) {
23468 // Ignore right-click, since that should open the context menu.
23469 function defaultFilter() {
23470 return !event.button;
23473 function defaultExtent() {
23474 var svg = this.ownerSVGElement || this;
23475 return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
23478 // Like d3.local, but with the name “__brush” rather than auto-generated.
23479 function local$$1(node) {
23480 while (!node.__brush) if (!(node = node.parentNode)) return;
23481 return node.__brush;
23484 function empty(extent) {
23485 return extent[0][0] === extent[1][0]
23486 || extent[0][1] === extent[1][1];
23489 function brushSelection(node) {
23490 var state = node.__brush;
23491 return state ? state.dim.output(state.selection) : null;
23494 function brushX() {
23498 function brushY() {
23502 var brush = function() {
23503 return brush$1(XY);
23506 function brush$1(dim) {
23507 var extent = defaultExtent,
23508 filter = defaultFilter,
23509 listeners = dispatch(brush, "start", "brush", "end"),
23513 function brush(group) {
23514 var overlay = group
23515 .property("__brush", initialize)
23516 .selectAll(".overlay")
23517 .data([type$2("overlay")]);
23519 overlay.enter().append("rect")
23520 .attr("class", "overlay")
23521 .attr("pointer-events", "all")
23522 .attr("cursor", cursors.overlay)
23525 var extent = local$$1(this).extent;
23527 .attr("x", extent[0][0])
23528 .attr("y", extent[0][1])
23529 .attr("width", extent[1][0] - extent[0][0])
23530 .attr("height", extent[1][1] - extent[0][1]);
23533 group.selectAll(".selection")
23534 .data([type$2("selection")])
23535 .enter().append("rect")
23536 .attr("class", "selection")
23537 .attr("cursor", cursors.selection)
23538 .attr("fill", "#777")
23539 .attr("fill-opacity", 0.3)
23540 .attr("stroke", "#fff")
23541 .attr("shape-rendering", "crispEdges");
23543 var handle = group.selectAll(".handle")
23544 .data(dim.handles, function(d) { return d.type; });
23546 handle.exit().remove();
23548 handle.enter().append("rect")
23549 .attr("class", function(d) { return "handle handle--" + d.type; })
23550 .attr("cursor", function(d) { return cursors[d.type]; });
23554 .attr("fill", "none")
23555 .attr("pointer-events", "all")
23556 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
23557 .on("mousedown.brush touchstart.brush", started);
23560 brush.move = function(group, selection$$1) {
23561 if (group.selection) {
23563 .on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
23564 .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
23565 .tween("brush", function() {
23567 state = that.__brush,
23568 emit = emitter(that, arguments),
23569 selection0 = state.selection,
23570 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent),
23571 i = interpolateValue(selection0, selection1);
23573 function tween(t) {
23574 state.selection = t === 1 && empty(selection1) ? null : i(t);
23579 return selection0 && selection1 ? tween : tween(1);
23586 state = that.__brush,
23587 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent),
23588 emit = emitter(that, args).beforestart();
23591 state.selection = selection1 == null || empty(selection1) ? null : selection1;
23593 emit.start().brush().end();
23598 function redraw() {
23599 var group = select(this),
23600 selection$$1 = local$$1(this).selection;
23602 if (selection$$1) {
23603 group.selectAll(".selection")
23604 .style("display", null)
23605 .attr("x", selection$$1[0][0])
23606 .attr("y", selection$$1[0][1])
23607 .attr("width", selection$$1[1][0] - selection$$1[0][0])
23608 .attr("height", selection$$1[1][1] - selection$$1[0][1]);
23610 group.selectAll(".handle")
23611 .style("display", null)
23612 .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; })
23613 .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; })
23614 .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; })
23615 .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; });
23619 group.selectAll(".selection,.handle")
23620 .style("display", "none")
23623 .attr("width", null)
23624 .attr("height", null);
23628 function emitter(that, args) {
23629 return that.__brush.emitter || new Emitter(that, args);
23632 function Emitter(that, args) {
23635 this.state = that.__brush;
23639 Emitter.prototype = {
23640 beforestart: function() {
23641 if (++this.active === 1) this.state.emitter = this, this.starting = true;
23644 start: function() {
23645 if (this.starting) this.starting = false, this.emit("start");
23648 brush: function() {
23649 this.emit("brush");
23653 if (--this.active === 0) delete this.state.emitter, this.emit("end");
23656 emit: function(type) {
23657 customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
23661 function started() {
23662 if (event.touches) { if (event.changedTouches.length < event.touches.length) return noevent$1(); }
23663 else if (touchending) return;
23664 if (!filter.apply(this, arguments)) return;
23667 type = event.target.__data__.type,
23668 mode = (event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (event.altKey ? MODE_CENTER : MODE_HANDLE),
23669 signX = dim === Y ? null : signsX[type],
23670 signY = dim === X ? null : signsY[type],
23671 state = local$$1(that),
23672 extent = state.extent,
23673 selection$$1 = state.selection,
23674 W = extent[0][0], w0, w1,
23675 N = extent[0][1], n0, n1,
23676 E = extent[1][0], e0, e1,
23677 S = extent[1][1], s0, s1,
23681 shifting = signX && signY && event.shiftKey,
23684 point0 = mouse(that),
23686 emit = emitter(that, arguments).beforestart();
23688 if (type === "overlay") {
23689 state.selection = selection$$1 = [
23690 [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
23691 [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
23694 w0 = selection$$1[0][0];
23695 n0 = selection$$1[0][1];
23696 e0 = selection$$1[1][0];
23697 s0 = selection$$1[1][1];
23705 var group = select(that)
23706 .attr("pointer-events", "none");
23708 var overlay = group.selectAll(".overlay")
23709 .attr("cursor", cursors[type]);
23711 if (event.touches) {
23713 .on("touchmove.brush", moved, true)
23714 .on("touchend.brush touchcancel.brush", ended, true);
23716 var view = select(event.view)
23717 .on("keydown.brush", keydowned, true)
23718 .on("keyup.brush", keyupped, true)
23719 .on("mousemove.brush", moved, true)
23720 .on("mouseup.brush", ended, true);
23722 dragDisable(event.view);
23731 var point1 = mouse(that);
23732 if (shifting && !lockX && !lockY) {
23733 if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
23745 dx = point[0] - point0[0];
23746 dy = point[1] - point0[1];
23751 if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
23752 if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
23755 case MODE_HANDLE: {
23756 if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
23757 else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
23758 if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
23759 else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
23762 case MODE_CENTER: {
23763 if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
23764 if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
23771 t = w0, w0 = e0, e0 = t;
23772 t = w1, w1 = e1, e1 = t;
23773 if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
23778 t = n0, n0 = s0, s0 = t;
23779 t = n1, n1 = s1, s1 = t;
23780 if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
23783 if (state.selection) selection$$1 = state.selection; // May be set by brush.move!
23784 if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0];
23785 if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1];
23787 if (selection$$1[0][0] !== w1
23788 || selection$$1[0][1] !== n1
23789 || selection$$1[1][0] !== e1
23790 || selection$$1[1][1] !== s1) {
23791 state.selection = [[w1, n1], [e1, s1]];
23799 if (event.touches) {
23800 if (event.touches.length) return;
23801 if (touchending) clearTimeout(touchending);
23802 touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
23803 group.on("touchmove.brush touchend.brush touchcancel.brush", null);
23805 yesdrag(event.view, moving);
23806 view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
23808 group.attr("pointer-events", "all");
23809 overlay.attr("cursor", cursors.overlay);
23810 if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)!
23811 if (empty(selection$$1)) state.selection = null, redraw.call(that);
23815 function keydowned() {
23816 switch (event.keyCode) {
23817 case 16: { // SHIFT
23818 shifting = signX && signY;
23822 if (mode === MODE_HANDLE) {
23823 if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
23824 if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
23825 mode = MODE_CENTER;
23830 case 32: { // SPACE; takes priority over ALT
23831 if (mode === MODE_HANDLE || mode === MODE_CENTER) {
23832 if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
23833 if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
23835 overlay.attr("cursor", cursors.selection);
23845 function keyupped() {
23846 switch (event.keyCode) {
23847 case 16: { // SHIFT
23849 lockX = lockY = shifting = false;
23855 if (mode === MODE_CENTER) {
23856 if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
23857 if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
23858 mode = MODE_HANDLE;
23863 case 32: { // SPACE
23864 if (mode === MODE_SPACE) {
23865 if (event.altKey) {
23866 if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
23867 if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
23868 mode = MODE_CENTER;
23870 if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
23871 if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
23872 mode = MODE_HANDLE;
23874 overlay.attr("cursor", cursors[type]);
23885 function initialize() {
23886 var state = this.__brush || {selection: null};
23887 state.extent = extent.apply(this, arguments);
23892 brush.extent = function(_) {
23893 return arguments.length ? (extent = typeof _ === "function" ? _ : constant$4([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent;
23896 brush.filter = function(_) {
23897 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$4(!!_), brush) : filter;
23900 brush.handleSize = function(_) {
23901 return arguments.length ? (handleSize = +_, brush) : handleSize;
23904 brush.on = function() {
23905 var value = listeners.on.apply(listeners, arguments);
23906 return value === listeners ? brush : value;
23912 var cos = Math.cos;
23913 var sin = Math.sin;
23914 var pi$1 = Math.PI;
23915 var halfPi$1 = pi$1 / 2;
23916 var tau$1 = pi$1 * 2;
23917 var max$1 = Math.max;
23919 function compareValue(compare) {
23920 return function(a, b) {
23922 a.source.value + a.target.value,
23923 b.source.value + b.target.value
23928 var chord = function() {
23931 sortSubgroups = null,
23934 function chord(matrix) {
23935 var n = matrix.length,
23937 groupIndex = sequence(n),
23938 subgroupIndex = [],
23940 groups = chords.groups = new Array(n),
23941 subgroups = new Array(n * n),
23949 // Compute the sum.
23950 k = 0, i = -1; while (++i < n) {
23951 x = 0, j = -1; while (++j < n) {
23955 subgroupIndex.push(sequence(n));
23960 if (sortGroups) groupIndex.sort(function(a, b) {
23961 return sortGroups(groupSums[a], groupSums[b]);
23965 if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
23966 d.sort(function(a, b) {
23967 return sortSubgroups(matrix[i][a], matrix[i][b]);
23971 // Convert the sum to scaling factor for [0, 2pi].
23972 // TODO Allow start and end angle to be specified?
23973 // TODO Allow padding to be specified as percentage?
23974 k = max$1(0, tau$1 - padAngle * n) / k;
23975 dx = k ? padAngle : tau$1 / n;
23977 // Compute the start and end angle for each group and subgroup.
23978 // Note: Opera has a bug reordering object literal properties!
23979 x = 0, i = -1; while (++i < n) {
23980 x0 = x, j = -1; while (++j < n) {
23981 var di = groupIndex[i],
23982 dj = subgroupIndex[di][j],
23983 v = matrix[di][dj],
23986 subgroups[dj * n + di] = {
23998 value: groupSums[di]
24003 // Generate chords for each (non-empty) subgroup-subgroup link.
24004 i = -1; while (++i < n) {
24005 j = i - 1; while (++j < n) {
24006 var source = subgroups[j * n + i],
24007 target = subgroups[i * n + j];
24008 if (source.value || target.value) {
24009 chords.push(source.value < target.value
24010 ? {source: target, target: source}
24011 : {source: source, target: target});
24016 return sortChords ? chords.sort(sortChords) : chords;
24019 chord.padAngle = function(_) {
24020 return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle;
24023 chord.sortGroups = function(_) {
24024 return arguments.length ? (sortGroups = _, chord) : sortGroups;
24027 chord.sortSubgroups = function(_) {
24028 return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
24031 chord.sortChords = function(_) {
24032 return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
24038 var slice$2 = Array.prototype.slice;
24040 var constant$5 = function(x) {
24041 return function() {
24046 var pi$2 = Math.PI;
24047 var tau$2 = 2 * pi$2;
24048 var epsilon$1 = 1e-6;
24049 var tauEpsilon = tau$2 - epsilon$1;
24052 this._x0 = this._y0 = // start of current subpath
24053 this._x1 = this._y1 = null; // end of current subpath
24061 Path.prototype = path.prototype = {
24063 moveTo: function(x, y) {
24064 this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
24066 closePath: function() {
24067 if (this._x1 !== null) {
24068 this._x1 = this._x0, this._y1 = this._y0;
24072 lineTo: function(x, y) {
24073 this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
24075 quadraticCurveTo: function(x1, y1, x, y) {
24076 this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
24078 bezierCurveTo: function(x1, y1, x2, y2, x, y) {
24079 this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
24081 arcTo: function(x1, y1, x2, y2, r) {
24082 x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
24089 l01_2 = x01 * x01 + y01 * y01;
24091 // Is the radius negative? Error.
24092 if (r < 0) throw new Error("negative radius: " + r);
24094 // Is this path empty? Move to (x1,y1).
24095 if (this._x1 === null) {
24096 this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1);
24099 // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
24100 else if (!(l01_2 > epsilon$1)) {}
24102 // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
24103 // Equivalently, is (x1,y1) coincident with (x2,y2)?
24104 // Or, is the radius zero? Line to (x1,y1).
24105 else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon$1) || !r) {
24106 this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1);
24109 // Otherwise, draw an arc!
24113 l21_2 = x21 * x21 + y21 * y21,
24114 l20_2 = x20 * x20 + y20 * y20,
24115 l21 = Math.sqrt(l21_2),
24116 l01 = Math.sqrt(l01_2),
24117 l = r * Math.tan((pi$2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
24121 // If the start tangent is not coincident with (x0,y0), line to.
24122 if (Math.abs(t01 - 1) > epsilon$1) {
24123 this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01);
24126 this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21);
24129 arc: function(x, y, r, a0, a1, ccw) {
24130 x = +x, y = +y, r = +r;
24131 var dx = r * Math.cos(a0),
24132 dy = r * Math.sin(a0),
24136 da = ccw ? a0 - a1 : a1 - a0;
24138 // Is the radius negative? Error.
24139 if (r < 0) throw new Error("negative radius: " + r);
24141 // Is this path empty? Move to (x0,y0).
24142 if (this._x1 === null) {
24143 this._ += "M" + x0 + "," + y0;
24146 // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
24147 else if (Math.abs(this._x1 - x0) > epsilon$1 || Math.abs(this._y1 - y0) > epsilon$1) {
24148 this._ += "L" + x0 + "," + y0;
24151 // Is this arc empty? We’re done.
24154 // Does the angle go the wrong way? Flip the direction.
24155 if (da < 0) da = da % tau$2 + tau$2;
24157 // Is this a complete circle? Draw two arcs to complete the circle.
24158 if (da > tauEpsilon) {
24159 this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0);
24162 // Is this arc non-empty? Draw an arc!
24163 else if (da > epsilon$1) {
24164 this._ += "A" + r + "," + r + ",0," + (+(da >= pi$2)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1));
24167 rect: function(x, y, w, h) {
24168 this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z";
24170 toString: function() {
24175 function defaultSource(d) {
24179 function defaultTarget(d) {
24183 function defaultRadius(d) {
24187 function defaultStartAngle(d) {
24188 return d.startAngle;
24191 function defaultEndAngle(d) {
24195 var ribbon = function() {
24196 var source = defaultSource,
24197 target = defaultTarget,
24198 radius = defaultRadius,
24199 startAngle = defaultStartAngle,
24200 endAngle = defaultEndAngle,
24203 function ribbon() {
24205 argv = slice$2.call(arguments),
24206 s = source.apply(this, argv),
24207 t = target.apply(this, argv),
24208 sr = +radius.apply(this, (argv[0] = s, argv)),
24209 sa0 = startAngle.apply(this, argv) - halfPi$1,
24210 sa1 = endAngle.apply(this, argv) - halfPi$1,
24211 sx0 = sr * cos(sa0),
24212 sy0 = sr * sin(sa0),
24213 tr = +radius.apply(this, (argv[0] = t, argv)),
24214 ta0 = startAngle.apply(this, argv) - halfPi$1,
24215 ta1 = endAngle.apply(this, argv) - halfPi$1;
24217 if (!context) context = buffer = path();
24219 context.moveTo(sx0, sy0);
24220 context.arc(0, 0, sr, sa0, sa1);
24221 if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr?
24222 context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0));
24223 context.arc(0, 0, tr, ta0, ta1);
24225 context.quadraticCurveTo(0, 0, sx0, sy0);
24226 context.closePath();
24228 if (buffer) return context = null, buffer + "" || null;
24231 ribbon.radius = function(_) {
24232 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$5(+_), ribbon) : radius;
24235 ribbon.startAngle = function(_) {
24236 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : startAngle;
24239 ribbon.endAngle = function(_) {
24240 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : endAngle;
24243 ribbon.source = function(_) {
24244 return arguments.length ? (source = _, ribbon) : source;
24247 ribbon.target = function(_) {
24248 return arguments.length ? (target = _, ribbon) : target;
24251 ribbon.context = function(_) {
24252 return arguments.length ? ((context = _ == null ? null : _), ribbon) : context;
24262 Map.prototype = map$1.prototype = {
24264 has: function(key) {
24265 return (prefix + key) in this;
24267 get: function(key) {
24268 return this[prefix + key];
24270 set: function(key, value) {
24271 this[prefix + key] = value;
24274 remove: function(key) {
24275 var property = prefix + key;
24276 return property in this && delete this[property];
24278 clear: function() {
24279 for (var property in this) if (property[0] === prefix) delete this[property];
24283 for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
24286 values: function() {
24288 for (var property in this) if (property[0] === prefix) values.push(this[property]);
24291 entries: function() {
24293 for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
24298 for (var property in this) if (property[0] === prefix) ++size;
24301 empty: function() {
24302 for (var property in this) if (property[0] === prefix) return false;
24305 each: function(f) {
24306 for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
24310 function map$1(object, f) {
24313 // Copy constructor.
24314 if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
24316 // Index array by numeric index or specified key function.
24317 else if (Array.isArray(object)) {
24322 if (f == null) while (++i < n) map.set(i, object[i]);
24323 else while (++i < n) map.set(f(o = object[i], i, object), o);
24326 // Convert object to map.
24327 else if (object) for (var key in object) map.set(key, object[key]);
24332 var nest = function() {
24339 function apply(array, depth, createResult, setResult) {
24340 if (depth >= keys.length) return rollup != null
24341 ? rollup(array) : (sortValues != null
24342 ? array.sort(sortValues)
24347 key = keys[depth++],
24350 valuesByKey = map$1(),
24352 result = createResult();
24355 if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
24356 values.push(value);
24358 valuesByKey.set(keyValue, [value]);
24362 valuesByKey.each(function(values, key) {
24363 setResult(result, key, apply(values, depth, createResult, setResult));
24369 function entries(map, depth) {
24370 if (++depth > keys.length) return map;
24371 var array, sortKey = sortKeys[depth - 1];
24372 if (rollup != null && depth >= keys.length) array = map.entries();
24373 else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); });
24374 return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array;
24378 object: function(array) { return apply(array, 0, createObject, setObject); },
24379 map: function(array) { return apply(array, 0, createMap, setMap); },
24380 entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
24381 key: function(d) { keys.push(d); return nest; },
24382 sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
24383 sortValues: function(order) { sortValues = order; return nest; },
24384 rollup: function(f) { rollup = f; return nest; }
24388 function createObject() {
24392 function setObject(object, key, value) {
24393 object[key] = value;
24396 function createMap() {
24400 function setMap(map, key, value) {
24401 map.set(key, value);
24406 var proto = map$1.prototype;
24408 Set.prototype = set$2.prototype = {
24411 add: function(value) {
24413 this[prefix + value] = value;
24416 remove: proto.remove,
24417 clear: proto.clear,
24418 values: proto.keys,
24420 empty: proto.empty,
24424 function set$2(object, f) {
24427 // Copy constructor.
24428 if (object instanceof Set) object.each(function(value) { set.add(value); });
24430 // Otherwise, assume it’s an array.
24432 var i = -1, n = object.length;
24433 if (f == null) while (++i < n) set.add(object[i]);
24434 else while (++i < n) set.add(f(object[i], i, object));
24440 var keys = function(map) {
24442 for (var key in map) keys.push(key);
24446 var values = function(map) {
24448 for (var key in map) values.push(map[key]);
24452 var entries = function(map) {
24454 for (var key in map) entries.push({key: key, value: map[key]});
24458 function objectConverter(columns) {
24459 return new Function("d", "return {" + columns.map(function(name, i) {
24460 return JSON.stringify(name) + ": d[" + i + "]";
24461 }).join(",") + "}");
24464 function customConverter(columns, f) {
24465 var object = objectConverter(columns);
24466 return function(row, i) {
24467 return f(object(row), i, columns);
24471 // Compute unique columns in order of discovery.
24472 function inferColumns(rows) {
24473 var columnSet = Object.create(null),
24476 rows.forEach(function(row) {
24477 for (var column in row) {
24478 if (!(column in columnSet)) {
24479 columns.push(columnSet[column] = column);
24487 var dsv = function(delimiter) {
24488 var reFormat = new RegExp("[\"" + delimiter + "\n\r]"),
24489 delimiterCode = delimiter.charCodeAt(0);
24491 function parse(text, f) {
24492 var convert, columns, rows = parseRows(text, function(row, i) {
24493 if (convert) return convert(row, i - 1);
24494 columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
24496 rows.columns = columns;
24500 function parseRows(text, f) {
24501 var EOL = {}, // sentinel value for end-of-line
24502 EOF = {}, // sentinel value for end-of-file
24503 rows = [], // output rows
24505 I = 0, // current character index
24506 n = 0, // the current line number
24507 t, // the current token
24508 eol; // is the current token followed by EOL?
24511 if (I >= N) return EOF; // special case: end of file
24512 if (eol) return eol = false, EOL; // special case: end of line
24514 // special case: quotes
24516 if (text.charCodeAt(j) === 34) {
24519 if (text.charCodeAt(i) === 34) {
24520 if (text.charCodeAt(i + 1) !== 34) break;
24525 c = text.charCodeAt(i + 1);
24528 if (text.charCodeAt(i + 2) === 10) ++I;
24529 } else if (c === 10) {
24532 return text.slice(j + 1, i).replace(/""/g, "\"");
24535 // common case: find next delimiter or newline
24538 c = text.charCodeAt(I++);
24539 if (c === 10) eol = true; // \n
24540 else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
24541 else if (c !== delimiterCode) continue;
24542 return text.slice(j, I - k);
24545 // special case: last token before EOF
24546 return text.slice(j);
24549 while ((t = token()) !== EOF) {
24551 while (t !== EOL && t !== EOF) {
24555 if (f && (a = f(a, n++)) == null) continue;
24562 function format(rows, columns) {
24563 if (columns == null) columns = inferColumns(rows);
24564 return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
24565 return columns.map(function(column) {
24566 return formatValue(row[column]);
24567 }).join(delimiter);
24571 function formatRows(rows) {
24572 return rows.map(formatRow).join("\n");
24575 function formatRow(row) {
24576 return row.map(formatValue).join(delimiter);
24579 function formatValue(text) {
24580 return text == null ? ""
24581 : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\""
24587 parseRows: parseRows,
24589 formatRows: formatRows
24593 var csv = dsv(",");
24595 var csvParse = csv.parse;
24596 var csvParseRows = csv.parseRows;
24597 var csvFormat = csv.format;
24598 var csvFormatRows = csv.formatRows;
24600 var tsv = dsv("\t");
24602 var tsvParse = tsv.parse;
24603 var tsvParseRows = tsv.parseRows;
24604 var tsvFormat = tsv.format;
24605 var tsvFormatRows = tsv.formatRows;
24607 var center$1 = function(x, y) {
24610 if (x == null) x = 0;
24611 if (y == null) y = 0;
24620 for (i = 0; i < n; ++i) {
24621 node = nodes[i], sx += node.x, sy += node.y;
24624 for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) {
24625 node = nodes[i], node.x -= sx, node.y -= sy;
24629 force.initialize = function(_) {
24633 force.x = function(_) {
24634 return arguments.length ? (x = +_, force) : x;
24637 force.y = function(_) {
24638 return arguments.length ? (y = +_, force) : y;
24644 var constant$6 = function(x) {
24645 return function() {
24650 var jiggle = function() {
24651 return (Math.random() - 0.5) * 1e-6;
24654 var tree_add = function(d) {
24655 var x = +this._x.call(null, d),
24656 y = +this._y.call(null, d);
24657 return add(this.cover(x, y), x, y, d);
24660 function add(tree, x, y, d) {
24661 if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
24679 // If the tree is empty, initialize the root as a leaf.
24680 if (!node) return tree._root = leaf, tree;
24682 // Find the existing leaf for the new point, or add it.
24683 while (node.length) {
24684 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24685 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24686 if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
24689 // Is the new point is exactly coincident with the existing point?
24690 xp = +tree._x.call(null, node.data);
24691 yp = +tree._y.call(null, node.data);
24692 if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
24694 // Otherwise, split the leaf node until the old and new point are separated.
24696 parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
24697 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24698 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24699 } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
24700 return parent[j] = node, parent[i] = leaf, tree;
24703 function addAll(data) {
24704 var d, i, n = data.length,
24714 // Compute the points and their extent.
24715 for (i = 0; i < n; ++i) {
24716 if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
24719 if (x < x0) x0 = x;
24720 if (x > x1) x1 = x;
24721 if (y < y0) y0 = y;
24722 if (y > y1) y1 = y;
24725 // If there were no (valid) points, inherit the existing extent.
24726 if (x1 < x0) x0 = this._x0, x1 = this._x1;
24727 if (y1 < y0) y0 = this._y0, y1 = this._y1;
24729 // Expand the tree to cover the new points.
24730 this.cover(x0, y0).cover(x1, y1);
24732 // Add the new points.
24733 for (i = 0; i < n; ++i) {
24734 add(this, xz[i], yz[i], data[i]);
24740 var tree_cover = function(x, y) {
24741 if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
24748 // If the quadtree has no extent, initialize them.
24749 // Integer extent are necessary so that if we later double the extent,
24750 // the existing quadrant boundaries don’t change due to floating point error!
24752 x1 = (x0 = Math.floor(x)) + 1;
24753 y1 = (y0 = Math.floor(y)) + 1;
24756 // Otherwise, double repeatedly to cover.
24757 else if (x0 > x || x > x1 || y0 > y || y > y1) {
24763 switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
24765 do parent = new Array(4), parent[i] = node, node = parent;
24766 while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
24770 do parent = new Array(4), parent[i] = node, node = parent;
24771 while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
24775 do parent = new Array(4), parent[i] = node, node = parent;
24776 while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
24780 do parent = new Array(4), parent[i] = node, node = parent;
24781 while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
24786 if (this._root && this._root.length) this._root = node;
24789 // If the quadtree covers the point already, just return.
24799 var tree_data = function() {
24801 this.visit(function(node) {
24802 if (!node.length) do data.push(node.data); while (node = node.next)
24807 var tree_extent = function(_) {
24808 return arguments.length
24809 ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
24810 : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
24813 var Quad = function(node, x0, y0, x1, y1) {
24821 var tree_find = function(x, y, radius) {
24836 if (node) quads.push(new Quad(node, x0, y0, x3, y3));
24837 if (radius == null) radius = Infinity;
24839 x0 = x - radius, y0 = y - radius;
24840 x3 = x + radius, y3 = y + radius;
24844 while (q = quads.pop()) {
24846 // Stop searching if this quadrant can’t contain a closer node.
24847 if (!(node = q.node)
24848 || (x1 = q.x0) > x3
24849 || (y1 = q.y0) > y3
24850 || (x2 = q.x1) < x0
24851 || (y2 = q.y1) < y0) continue;
24853 // Bisect the current quadrant.
24855 var xm = (x1 + x2) / 2,
24856 ym = (y1 + y2) / 2;
24859 new Quad(node[3], xm, ym, x2, y2),
24860 new Quad(node[2], x1, ym, xm, y2),
24861 new Quad(node[1], xm, y1, x2, ym),
24862 new Quad(node[0], x1, y1, xm, ym)
24865 // Visit the closest quadrant first.
24866 if (i = (y >= ym) << 1 | (x >= xm)) {
24867 q = quads[quads.length - 1];
24868 quads[quads.length - 1] = quads[quads.length - 1 - i];
24869 quads[quads.length - 1 - i] = q;
24873 // Visit this point. (Visiting coincident points isn’t necessary!)
24875 var dx = x - +this._x.call(null, node.data),
24876 dy = y - +this._y.call(null, node.data),
24877 d2 = dx * dx + dy * dy;
24879 var d = Math.sqrt(radius = d2);
24880 x0 = x - d, y0 = y - d;
24881 x3 = x + d, y3 = y + d;
24890 var tree_remove = function(d) {
24891 if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
24911 // If the tree is empty, initialize the root as a leaf.
24912 if (!node) return this;
24914 // Find the leaf node for the point.
24915 // While descending, also retain the deepest parent with a non-removed sibling.
24916 if (node.length) while (true) {
24917 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24918 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24919 if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
24920 if (!node.length) break;
24921 if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
24924 // Find the point to remove.
24925 while (node.data !== d) if (!(previous = node, node = node.next)) return this;
24926 if (next = node.next) delete node.next;
24928 // If there are multiple coincident points, remove just the point.
24929 if (previous) return (next ? previous.next = next : delete previous.next), this;
24931 // If this is the root point, remove it.
24932 if (!parent) return this._root = next, this;
24934 // Remove this leaf.
24935 next ? parent[i] = next : delete parent[i];
24937 // If the parent now contains exactly one leaf, collapse superfluous parents.
24938 if ((node = parent[0] || parent[1] || parent[2] || parent[3])
24939 && node === (parent[3] || parent[2] || parent[1] || parent[0])
24941 if (retainer) retainer[j] = node;
24942 else this._root = node;
24948 function removeAll(data) {
24949 for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
24953 var tree_root = function() {
24957 var tree_size = function() {
24959 this.visit(function(node) {
24960 if (!node.length) do ++size; while (node = node.next)
24965 var tree_visit = function(callback) {
24966 var quads = [], q, node = this._root, child, x0, y0, x1, y1;
24967 if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
24968 while (q = quads.pop()) {
24969 if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
24970 var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
24971 if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
24972 if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
24973 if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
24974 if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
24980 var tree_visitAfter = function(callback) {
24981 var quads = [], next = [], q;
24982 if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
24983 while (q = quads.pop()) {
24986 var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
24987 if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
24988 if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
24989 if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
24990 if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
24994 while (q = next.pop()) {
24995 callback(q.node, q.x0, q.y0, q.x1, q.y1);
25000 function defaultX(d) {
25004 var tree_x = function(_) {
25005 return arguments.length ? (this._x = _, this) : this._x;
25008 function defaultY(d) {
25012 var tree_y = function(_) {
25013 return arguments.length ? (this._y = _, this) : this._y;
25016 function quadtree(nodes, x, y) {
25017 var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
25018 return nodes == null ? tree : tree.addAll(nodes);
25021 function Quadtree(x, y, x0, y0, x1, y1) {
25028 this._root = undefined;
25031 function leaf_copy(leaf) {
25032 var copy = {data: leaf.data}, next = copy;
25033 while (leaf = leaf.next) next = next.next = {data: leaf.data};
25037 var treeProto = quadtree.prototype = Quadtree.prototype;
25039 treeProto.copy = function() {
25040 var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
25045 if (!node) return copy;
25047 if (!node.length) return copy._root = leaf_copy(node), copy;
25049 nodes = [{source: node, target: copy._root = new Array(4)}];
25050 while (node = nodes.pop()) {
25051 for (var i = 0; i < 4; ++i) {
25052 if (child = node.source[i]) {
25053 if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
25054 else node.target[i] = leaf_copy(child);
25062 treeProto.add = tree_add;
25063 treeProto.addAll = addAll;
25064 treeProto.cover = tree_cover;
25065 treeProto.data = tree_data;
25066 treeProto.extent = tree_extent;
25067 treeProto.find = tree_find;
25068 treeProto.remove = tree_remove;
25069 treeProto.removeAll = removeAll;
25070 treeProto.root = tree_root;
25071 treeProto.size = tree_size;
25072 treeProto.visit = tree_visit;
25073 treeProto.visitAfter = tree_visitAfter;
25074 treeProto.x = tree_x;
25075 treeProto.y = tree_y;
25085 var collide = function(radius) {
25091 if (typeof radius !== "function") radius = constant$6(radius == null ? 1 : +radius);
25094 var i, n = nodes.length,
25102 for (var k = 0; k < iterations; ++k) {
25103 tree = quadtree(nodes, x, y).visitAfter(prepare);
25104 for (i = 0; i < n; ++i) {
25106 ri = radii[node.index], ri2 = ri * ri;
25107 xi = node.x + node.vx;
25108 yi = node.y + node.vy;
25113 function apply(quad, x0, y0, x1, y1) {
25114 var data = quad.data, rj = quad.r, r = ri + rj;
25116 if (data.index > node.index) {
25117 var x = xi - data.x - data.vx,
25118 y = yi - data.y - data.vy,
25121 if (x === 0) x = jiggle(), l += x * x;
25122 if (y === 0) y = jiggle(), l += y * y;
25123 l = (r - (l = Math.sqrt(l))) / l * strength;
25124 node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
25125 node.vy += (y *= l) * r;
25126 data.vx -= x * (r = 1 - r);
25132 return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
25136 function prepare(quad) {
25137 if (quad.data) return quad.r = radii[quad.data.index];
25138 for (var i = quad.r = 0; i < 4; ++i) {
25139 if (quad[i] && quad[i].r > quad.r) {
25140 quad.r = quad[i].r;
25145 function initialize() {
25146 if (!nodes) return;
25147 var i, n = nodes.length, node;
25148 radii = new Array(n);
25149 for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);
25152 force.initialize = function(_) {
25157 force.iterations = function(_) {
25158 return arguments.length ? (iterations = +_, force) : iterations;
25161 force.strength = function(_) {
25162 return arguments.length ? (strength = +_, force) : strength;
25165 force.radius = function(_) {
25166 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : radius;
25172 function index$3(d) {
25176 function find(nodeById, nodeId) {
25177 var node = nodeById.get(nodeId);
25178 if (!node) throw new Error("missing: " + nodeId);
25182 var link = function(links) {
25184 strength = defaultStrength,
25186 distance = constant$6(30),
25193 if (links == null) links = [];
25195 function defaultStrength(link) {
25196 return 1 / Math.min(count[link.source.index], count[link.target.index]);
25199 function force(alpha) {
25200 for (var k = 0, n = links.length; k < iterations; ++k) {
25201 for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
25202 link = links[i], source = link.source, target = link.target;
25203 x = target.x + target.vx - source.x - source.vx || jiggle();
25204 y = target.y + target.vy - source.y - source.vy || jiggle();
25205 l = Math.sqrt(x * x + y * y);
25206 l = (l - distances[i]) / l * alpha * strengths[i];
25208 target.vx -= x * (b = bias[i]);
25209 target.vy -= y * b;
25210 source.vx += x * (b = 1 - b);
25211 source.vy += y * b;
25216 function initialize() {
25217 if (!nodes) return;
25222 nodeById = map$1(nodes, id),
25225 for (i = 0, count = new Array(n); i < m; ++i) {
25226 link = links[i], link.index = i;
25227 if (typeof link.source !== "object") link.source = find(nodeById, link.source);
25228 if (typeof link.target !== "object") link.target = find(nodeById, link.target);
25229 count[link.source.index] = (count[link.source.index] || 0) + 1;
25230 count[link.target.index] = (count[link.target.index] || 0) + 1;
25233 for (i = 0, bias = new Array(m); i < m; ++i) {
25234 link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
25237 strengths = new Array(m), initializeStrength();
25238 distances = new Array(m), initializeDistance();
25241 function initializeStrength() {
25242 if (!nodes) return;
25244 for (var i = 0, n = links.length; i < n; ++i) {
25245 strengths[i] = +strength(links[i], i, links);
25249 function initializeDistance() {
25250 if (!nodes) return;
25252 for (var i = 0, n = links.length; i < n; ++i) {
25253 distances[i] = +distance(links[i], i, links);
25257 force.initialize = function(_) {
25262 force.links = function(_) {
25263 return arguments.length ? (links = _, initialize(), force) : links;
25266 force.id = function(_) {
25267 return arguments.length ? (id = _, force) : id;
25270 force.iterations = function(_) {
25271 return arguments.length ? (iterations = +_, force) : iterations;
25274 force.strength = function(_) {
25275 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initializeStrength(), force) : strength;
25278 force.distance = function(_) {
25279 return arguments.length ? (distance = typeof _ === "function" ? _ : constant$6(+_), initializeDistance(), force) : distance;
25293 var initialRadius = 10;
25294 var initialAngle = Math.PI * (3 - Math.sqrt(5));
25296 var simulation = function(nodes) {
25300 alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
25302 velocityDecay = 0.6,
25304 stepper = timer(step),
25305 event = dispatch("tick", "end");
25307 if (nodes == null) nodes = [];
25311 event.call("tick", simulation);
25312 if (alpha < alphaMin) {
25314 event.call("end", simulation);
25319 var i, n = nodes.length, node;
25321 alpha += (alphaTarget - alpha) * alphaDecay;
25323 forces.each(function(force) {
25327 for (i = 0; i < n; ++i) {
25329 if (node.fx == null) node.x += node.vx *= velocityDecay;
25330 else node.x = node.fx, node.vx = 0;
25331 if (node.fy == null) node.y += node.vy *= velocityDecay;
25332 else node.y = node.fy, node.vy = 0;
25336 function initializeNodes() {
25337 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25338 node = nodes[i], node.index = i;
25339 if (isNaN(node.x) || isNaN(node.y)) {
25340 var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle;
25341 node.x = radius * Math.cos(angle);
25342 node.y = radius * Math.sin(angle);
25344 if (isNaN(node.vx) || isNaN(node.vy)) {
25345 node.vx = node.vy = 0;
25350 function initializeForce(force) {
25351 if (force.initialize) force.initialize(nodes);
25357 return simulation = {
25360 restart: function() {
25361 return stepper.restart(step), simulation;
25365 return stepper.stop(), simulation;
25368 nodes: function(_) {
25369 return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes;
25372 alpha: function(_) {
25373 return arguments.length ? (alpha = +_, simulation) : alpha;
25376 alphaMin: function(_) {
25377 return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
25380 alphaDecay: function(_) {
25381 return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
25384 alphaTarget: function(_) {
25385 return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
25388 velocityDecay: function(_) {
25389 return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
25392 force: function(name, _) {
25393 return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
25396 find: function(x, y, radius) {
25405 if (radius == null) radius = Infinity;
25406 else radius *= radius;
25408 for (i = 0; i < n; ++i) {
25412 d2 = dx * dx + dy * dy;
25413 if (d2 < radius) closest = node, radius = d2;
25419 on: function(name, _) {
25420 return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
25425 var manyBody = function() {
25429 strength = constant$6(-30),
25432 distanceMax2 = Infinity,
25435 function force(_) {
25436 var i, n = nodes.length, tree = quadtree(nodes, x$1, y$1).visitAfter(accumulate);
25437 for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
25440 function initialize() {
25441 if (!nodes) return;
25442 var i, n = nodes.length, node;
25443 strengths = new Array(n);
25444 for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
25447 function accumulate(quad) {
25448 var strength = 0, q, c, x$$1, y$$1, i;
25450 // For internal nodes, accumulate forces from child quadrants.
25452 for (x$$1 = y$$1 = i = 0; i < 4; ++i) {
25453 if ((q = quad[i]) && (c = q.value)) {
25454 strength += c, x$$1 += c * q.x, y$$1 += c * q.y;
25457 quad.x = x$$1 / strength;
25458 quad.y = y$$1 / strength;
25461 // For leaf nodes, accumulate forces from coincident quadrants.
25466 do strength += strengths[q.data.index];
25467 while (q = q.next);
25470 quad.value = strength;
25473 function apply(quad, x1, _, x2) {
25474 if (!quad.value) return true;
25476 var x$$1 = quad.x - node.x,
25477 y$$1 = quad.y - node.y,
25479 l = x$$1 * x$$1 + y$$1 * y$$1;
25481 // Apply the Barnes-Hut approximation if possible.
25482 // Limit forces for very close nodes; randomize direction if coincident.
25483 if (w * w / theta2 < l) {
25484 if (l < distanceMax2) {
25485 if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
25486 if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
25487 if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
25488 node.vx += x$$1 * quad.value * alpha / l;
25489 node.vy += y$$1 * quad.value * alpha / l;
25494 // Otherwise, process points directly.
25495 else if (quad.length || l >= distanceMax2) return;
25497 // Limit forces for very close nodes; randomize direction if coincident.
25498 if (quad.data !== node || quad.next) {
25499 if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
25500 if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
25501 if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
25504 do if (quad.data !== node) {
25505 w = strengths[quad.data.index] * alpha / l;
25506 node.vx += x$$1 * w;
25507 node.vy += y$$1 * w;
25508 } while (quad = quad.next);
25511 force.initialize = function(_) {
25516 force.strength = function(_) {
25517 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25520 force.distanceMin = function(_) {
25521 return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
25524 force.distanceMax = function(_) {
25525 return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
25528 force.theta = function(_) {
25529 return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
25535 var x$2 = function(x) {
25536 var strength = constant$6(0.1),
25541 if (typeof x !== "function") x = constant$6(x == null ? 0 : +x);
25543 function force(alpha) {
25544 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25545 node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
25549 function initialize() {
25550 if (!nodes) return;
25551 var i, n = nodes.length;
25552 strengths = new Array(n);
25554 for (i = 0; i < n; ++i) {
25555 strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
25559 force.initialize = function(_) {
25564 force.strength = function(_) {
25565 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25568 force.x = function(_) {
25569 return arguments.length ? (x = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : x;
25575 var y$2 = function(y) {
25576 var strength = constant$6(0.1),
25581 if (typeof y !== "function") y = constant$6(y == null ? 0 : +y);
25583 function force(alpha) {
25584 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25585 node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
25589 function initialize() {
25590 if (!nodes) return;
25591 var i, n = nodes.length;
25592 strengths = new Array(n);
25594 for (i = 0; i < n; ++i) {
25595 strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
25599 force.initialize = function(_) {
25604 force.strength = function(_) {
25605 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25608 force.y = function(_) {
25609 return arguments.length ? (y = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : y;
25615 // Computes the decimal coefficient and exponent of the specified number x with
25616 // significant digits p, where x is positive and p is in [1, 21] or undefined.
25617 // For example, formatDecimal(1.23) returns ["123", 0].
25618 var formatDecimal = function(x, p) {
25619 if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
25620 var i, coefficient = x.slice(0, i);
25622 // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
25623 // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
25625 coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
25630 var exponent$1 = function(x) {
25631 return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
25634 var formatGroup = function(grouping, thousands) {
25635 return function(value, width) {
25636 var i = value.length,
25642 while (i > 0 && g > 0) {
25643 if (length + g + 1 > width) g = Math.max(1, width - length);
25644 t.push(value.substring(i -= g, i + g));
25645 if ((length += g + 1) > width) break;
25646 g = grouping[j = (j + 1) % grouping.length];
25649 return t.reverse().join(thousands);
25653 var formatNumerals = function(numerals) {
25654 return function(value) {
25655 return value.replace(/[0-9]/g, function(i) {
25656 return numerals[+i];
25661 var formatDefault = function(x, p) {
25662 x = x.toPrecision(p);
25664 out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
25666 case ".": i0 = i1 = i; break;
25667 case "0": if (i0 === 0) i0 = i; i1 = i; break;
25668 case "e": break out;
25669 default: if (i0 > 0) i0 = 0; break;
25673 return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
25676 var prefixExponent;
25678 var formatPrefixAuto = function(x, p) {
25679 var d = formatDecimal(x, p);
25680 if (!d) return x + "";
25681 var coefficient = d[0],
25683 i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
25684 n = coefficient.length;
25685 return i === n ? coefficient
25686 : i > n ? coefficient + new Array(i - n + 1).join("0")
25687 : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
25688 : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
25691 var formatRounded = function(x, p) {
25692 var d = formatDecimal(x, p);
25693 if (!d) return x + "";
25694 var coefficient = d[0],
25696 return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
25697 : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
25698 : coefficient + new Array(exponent - coefficient.length + 2).join("0");
25701 var formatTypes = {
25703 "%": function(x, p) { return (x * 100).toFixed(p); },
25704 "b": function(x) { return Math.round(x).toString(2); },
25705 "c": function(x) { return x + ""; },
25706 "d": function(x) { return Math.round(x).toString(10); },
25707 "e": function(x, p) { return x.toExponential(p); },
25708 "f": function(x, p) { return x.toFixed(p); },
25709 "g": function(x, p) { return x.toPrecision(p); },
25710 "o": function(x) { return Math.round(x).toString(8); },
25711 "p": function(x, p) { return formatRounded(x * 100, p); },
25712 "r": formatRounded,
25713 "s": formatPrefixAuto,
25714 "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
25715 "x": function(x) { return Math.round(x).toString(16); }
25718 // [[fill]align][sign][symbol][0][width][,][.precision][type]
25719 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
25721 function formatSpecifier(specifier) {
25722 return new FormatSpecifier(specifier);
25725 formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
25727 function FormatSpecifier(specifier) {
25728 if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
25731 fill = match[1] || " ",
25732 align = match[2] || ">",
25733 sign = match[3] || "-",
25734 symbol = match[4] || "",
25736 width = match[6] && +match[6],
25737 comma = !!match[7],
25738 precision = match[8] && +match[8].slice(1),
25739 type = match[9] || "";
25741 // The "n" type is an alias for ",g".
25742 if (type === "n") comma = true, type = "g";
25744 // Map invalid types to the default format.
25745 else if (!formatTypes[type]) type = "";
25747 // If zero fill is specified, padding goes after sign and before digits.
25748 if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
25751 this.align = align;
25753 this.symbol = symbol;
25755 this.width = width;
25756 this.comma = comma;
25757 this.precision = precision;
25761 FormatSpecifier.prototype.toString = function() {
25766 + (this.zero ? "0" : "")
25767 + (this.width == null ? "" : Math.max(1, this.width | 0))
25768 + (this.comma ? "," : "")
25769 + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
25773 var identity$3 = function(x) {
25777 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
25779 var formatLocale = function(locale) {
25780 var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3,
25781 currency = locale.currency,
25782 decimal = locale.decimal,
25783 numerals = locale.numerals ? formatNumerals(locale.numerals) : identity$3,
25784 percent = locale.percent || "%";
25786 function newFormat(specifier) {
25787 specifier = formatSpecifier(specifier);
25789 var fill = specifier.fill,
25790 align = specifier.align,
25791 sign = specifier.sign,
25792 symbol = specifier.symbol,
25793 zero = specifier.zero,
25794 width = specifier.width,
25795 comma = specifier.comma,
25796 precision = specifier.precision,
25797 type = specifier.type;
25799 // Compute the prefix and suffix.
25800 // For SI-prefix, the suffix is lazily computed.
25801 var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
25802 suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : "";
25804 // What format function should we use?
25805 // Is this an integer type?
25806 // Can this type generate exponential notation?
25807 var formatType = formatTypes[type],
25808 maybeSuffix = !type || /[defgprs%]/.test(type);
25810 // Set the default precision if not specified,
25811 // or clamp the specified precision to the supported range.
25812 // For significant precision, it must be in [1, 21].
25813 // For fixed precision, it must be in [0, 20].
25814 precision = precision == null ? (type ? 6 : 12)
25815 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
25816 : Math.max(0, Math.min(20, precision));
25818 function format(value) {
25819 var valuePrefix = prefix,
25820 valueSuffix = suffix,
25823 if (type === "c") {
25824 valueSuffix = formatType(value) + valueSuffix;
25829 // Perform the initial formatting.
25830 var valueNegative = value < 0;
25831 value = formatType(Math.abs(value), precision);
25833 // If a negative value rounds to zero during formatting, treat as positive.
25834 if (valueNegative && +value === 0) valueNegative = false;
25836 // Compute the prefix and suffix.
25837 valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
25838 valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
25840 // Break the formatted value into the integer “value” part that can be
25841 // grouped, and fractional or exponential “suffix” part that is not.
25843 i = -1, n = value.length;
25845 if (c = value.charCodeAt(i), 48 > c || c > 57) {
25846 valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
25847 value = value.slice(0, i);
25854 // If the fill character is not "0", grouping is applied before padding.
25855 if (comma && !zero) value = group(value, Infinity);
25857 // Compute the padding.
25858 var length = valuePrefix.length + value.length + valueSuffix.length,
25859 padding = length < width ? new Array(width - length + 1).join(fill) : "";
25861 // If the fill character is "0", grouping is applied after padding.
25862 if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
25864 // Reconstruct the final output based on the desired alignment.
25866 case "<": value = valuePrefix + value + valueSuffix + padding; break;
25867 case "=": value = valuePrefix + padding + value + valueSuffix; break;
25868 case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
25869 default: value = padding + valuePrefix + value + valueSuffix; break;
25872 return numerals(value);
25875 format.toString = function() {
25876 return specifier + "";
25882 function formatPrefix(specifier, value) {
25883 var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
25884 e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
25885 k = Math.pow(10, -e),
25886 prefix = prefixes[8 + e / 3];
25887 return function(value) {
25888 return f(k * value) + prefix;
25894 formatPrefix: formatPrefix
25906 currency: ["$", ""]
25909 function defaultLocale(definition) {
25910 locale$1 = formatLocale(definition);
25911 format = locale$1.format;
25912 formatPrefix = locale$1.formatPrefix;
25916 var precisionFixed = function(step) {
25917 return Math.max(0, -exponent$1(Math.abs(step)));
25920 var precisionPrefix = function(step, value) {
25921 return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step)));
25924 var precisionRound = function(step, max) {
25925 step = Math.abs(step), max = Math.abs(max) - step;
25926 return Math.max(0, exponent$1(max) - exponent$1(step)) + 1;
25929 // Adds floating point numbers with twice the normal precision.
25930 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
25931 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
25933 // Code adapted from GeographicLib by Charles F. F. Karney,
25934 // http://geographiclib.sourceforge.net/
25936 var adder = function() {
25944 Adder.prototype = {
25945 constructor: Adder,
25946 reset: function() {
25947 this.s = // rounded value
25948 this.t = 0; // exact error
25951 add$1(temp, y, this.t);
25952 add$1(this, temp.s, this.s);
25953 if (this.s) this.t += temp.t;
25954 else this.s = temp.t;
25956 valueOf: function() {
25961 var temp = new Adder;
25963 function add$1(adder, a, b) {
25964 var x = adder.s = a + b,
25967 adder.t = (a - av) + (b - bv);
25970 var epsilon$2 = 1e-6;
25971 var epsilon2$1 = 1e-12;
25972 var pi$3 = Math.PI;
25973 var halfPi$2 = pi$3 / 2;
25974 var quarterPi = pi$3 / 4;
25975 var tau$3 = pi$3 * 2;
25977 var degrees$1 = 180 / pi$3;
25978 var radians = pi$3 / 180;
25980 var abs = Math.abs;
25981 var atan = Math.atan;
25982 var atan2 = Math.atan2;
25983 var cos$1 = Math.cos;
25984 var ceil = Math.ceil;
25985 var exp = Math.exp;
25987 var log = Math.log;
25988 var pow = Math.pow;
25989 var sin$1 = Math.sin;
25990 var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
25991 var sqrt = Math.sqrt;
25992 var tan = Math.tan;
25995 return x > 1 ? 0 : x < -1 ? pi$3 : Math.acos(x);
25999 return x > 1 ? halfPi$2 : x < -1 ? -halfPi$2 : Math.asin(x);
26002 function haversin(x) {
26003 return (x = sin$1(x / 2)) * x;
26006 function noop$1() {}
26008 function streamGeometry(geometry, stream) {
26009 if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
26010 streamGeometryType[geometry.type](geometry, stream);
26014 var streamObjectType = {
26015 Feature: function(object, stream) {
26016 streamGeometry(object.geometry, stream);
26018 FeatureCollection: function(object, stream) {
26019 var features = object.features, i = -1, n = features.length;
26020 while (++i < n) streamGeometry(features[i].geometry, stream);
26024 var streamGeometryType = {
26025 Sphere: function(object, stream) {
26028 Point: function(object, stream) {
26029 object = object.coordinates;
26030 stream.point(object[0], object[1], object[2]);
26032 MultiPoint: function(object, stream) {
26033 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26034 while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
26036 LineString: function(object, stream) {
26037 streamLine(object.coordinates, stream, 0);
26039 MultiLineString: function(object, stream) {
26040 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26041 while (++i < n) streamLine(coordinates[i], stream, 0);
26043 Polygon: function(object, stream) {
26044 streamPolygon(object.coordinates, stream);
26046 MultiPolygon: function(object, stream) {
26047 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26048 while (++i < n) streamPolygon(coordinates[i], stream);
26050 GeometryCollection: function(object, stream) {
26051 var geometries = object.geometries, i = -1, n = geometries.length;
26052 while (++i < n) streamGeometry(geometries[i], stream);
26056 function streamLine(coordinates, stream, closed) {
26057 var i = -1, n = coordinates.length - closed, coordinate;
26058 stream.lineStart();
26059 while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
26063 function streamPolygon(coordinates, stream) {
26064 var i = -1, n = coordinates.length;
26065 stream.polygonStart();
26066 while (++i < n) streamLine(coordinates[i], stream, 1);
26067 stream.polygonEnd();
26070 var geoStream = function(object, stream) {
26071 if (object && streamObjectType.hasOwnProperty(object.type)) {
26072 streamObjectType[object.type](object, stream);
26074 streamGeometry(object, stream);
26078 var areaRingSum = adder();
26080 var areaSum = adder();
26091 polygonStart: function() {
26092 areaRingSum.reset();
26093 areaStream.lineStart = areaRingStart;
26094 areaStream.lineEnd = areaRingEnd;
26096 polygonEnd: function() {
26097 var areaRing = +areaRingSum;
26098 areaSum.add(areaRing < 0 ? tau$3 + areaRing : areaRing);
26099 this.lineStart = this.lineEnd = this.point = noop$1;
26101 sphere: function() {
26102 areaSum.add(tau$3);
26106 function areaRingStart() {
26107 areaStream.point = areaPointFirst;
26110 function areaRingEnd() {
26111 areaPoint(lambda00, phi00);
26114 function areaPointFirst(lambda, phi) {
26115 areaStream.point = areaPoint;
26116 lambda00 = lambda, phi00 = phi;
26117 lambda *= radians, phi *= radians;
26118 lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi);
26121 function areaPoint(lambda, phi) {
26122 lambda *= radians, phi *= radians;
26123 phi = phi / 2 + quarterPi; // half the angular distance from south pole
26125 // Spherical excess E for a spherical triangle with vertices: south pole,
26126 // previous point, current point. Uses a formula derived from Cagnoli’s
26127 // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
26128 var dLambda = lambda - lambda0,
26129 sdLambda = dLambda >= 0 ? 1 : -1,
26130 adLambda = sdLambda * dLambda,
26131 cosPhi = cos$1(phi),
26132 sinPhi = sin$1(phi),
26133 k = sinPhi0 * sinPhi,
26134 u = cosPhi0 * cosPhi + k * cos$1(adLambda),
26135 v = k * sdLambda * sin$1(adLambda);
26136 areaRingSum.add(atan2(v, u));
26138 // Advance the previous points.
26139 lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
26142 var area = function(object) {
26144 geoStream(object, areaStream);
26145 return areaSum * 2;
26148 function spherical(cartesian) {
26149 return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
26152 function cartesian(spherical) {
26153 var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi);
26154 return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)];
26157 function cartesianDot(a, b) {
26158 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
26161 function cartesianCross(a, b) {
26162 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]];
26166 function cartesianAddInPlace(a, b) {
26167 a[0] += b[0], a[1] += b[1], a[2] += b[2];
26170 function cartesianScale(vector, k) {
26171 return [vector[0] * k, vector[1] * k, vector[2] * k];
26175 function cartesianNormalizeInPlace(d) {
26176 var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
26177 d[0] /= l, d[1] /= l, d[2] /= l;
26188 var deltaSum = adder();
26192 var boundsStream = {
26193 point: boundsPoint,
26194 lineStart: boundsLineStart,
26195 lineEnd: boundsLineEnd,
26196 polygonStart: function() {
26197 boundsStream.point = boundsRingPoint;
26198 boundsStream.lineStart = boundsRingStart;
26199 boundsStream.lineEnd = boundsRingEnd;
26201 areaStream.polygonStart();
26203 polygonEnd: function() {
26204 areaStream.polygonEnd();
26205 boundsStream.point = boundsPoint;
26206 boundsStream.lineStart = boundsLineStart;
26207 boundsStream.lineEnd = boundsLineEnd;
26208 if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
26209 else if (deltaSum > epsilon$2) phi1 = 90;
26210 else if (deltaSum < -epsilon$2) phi0 = -90;
26211 range[0] = lambda0$1, range[1] = lambda1;
26215 function boundsPoint(lambda, phi) {
26216 ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
26217 if (phi < phi0) phi0 = phi;
26218 if (phi > phi1) phi1 = phi;
26221 function linePoint(lambda, phi) {
26222 var p = cartesian([lambda * radians, phi * radians]);
26224 var normal = cartesianCross(p0, p),
26225 equatorial = [normal[1], -normal[0], 0],
26226 inflection = cartesianCross(equatorial, normal);
26227 cartesianNormalizeInPlace(inflection);
26228 inflection = spherical(inflection);
26229 var delta = lambda - lambda2,
26230 sign$$1 = delta > 0 ? 1 : -1,
26231 lambdai = inflection[0] * degrees$1 * sign$$1,
26233 antimeridian = abs(delta) > 180;
26234 if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
26235 phii = inflection[1] * degrees$1;
26236 if (phii > phi1) phi1 = phii;
26237 } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
26238 phii = -inflection[1] * degrees$1;
26239 if (phii < phi0) phi0 = phii;
26241 if (phi < phi0) phi0 = phi;
26242 if (phi > phi1) phi1 = phi;
26244 if (antimeridian) {
26245 if (lambda < lambda2) {
26246 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
26248 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
26251 if (lambda1 >= lambda0$1) {
26252 if (lambda < lambda0$1) lambda0$1 = lambda;
26253 if (lambda > lambda1) lambda1 = lambda;
26255 if (lambda > lambda2) {
26256 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
26258 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
26263 ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
26265 if (phi < phi0) phi0 = phi;
26266 if (phi > phi1) phi1 = phi;
26267 p0 = p, lambda2 = lambda;
26270 function boundsLineStart() {
26271 boundsStream.point = linePoint;
26274 function boundsLineEnd() {
26275 range[0] = lambda0$1, range[1] = lambda1;
26276 boundsStream.point = boundsPoint;
26280 function boundsRingPoint(lambda, phi) {
26282 var delta = lambda - lambda2;
26283 deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
26285 lambda00$1 = lambda, phi00$1 = phi;
26287 areaStream.point(lambda, phi);
26288 linePoint(lambda, phi);
26291 function boundsRingStart() {
26292 areaStream.lineStart();
26295 function boundsRingEnd() {
26296 boundsRingPoint(lambda00$1, phi00$1);
26297 areaStream.lineEnd();
26298 if (abs(deltaSum) > epsilon$2) lambda0$1 = -(lambda1 = 180);
26299 range[0] = lambda0$1, range[1] = lambda1;
26303 // Finds the left-right distance between two longitudes.
26304 // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
26305 // the distance between ±180° to be 360°.
26306 function angle(lambda0, lambda1) {
26307 return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
26310 function rangeCompare(a, b) {
26311 return a[0] - b[0];
26314 function rangeContains(range, x) {
26315 return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
26318 var bounds = function(feature) {
26319 var i, n, a, b, merged, deltaMax, delta;
26321 phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
26323 geoStream(feature, boundsStream);
26325 // First, sort ranges by their minimum longitudes.
26326 if (n = ranges.length) {
26327 ranges.sort(rangeCompare);
26329 // Then, merge any ranges that overlap.
26330 for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
26332 if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
26333 if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
26334 if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
26336 merged.push(a = b);
26340 // Finally, find the largest gap between the merged ranges.
26341 // The final bounding box will be the inverse of this gap.
26342 for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
26344 if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
26348 ranges = range = null;
26350 return lambda0$1 === Infinity || phi0 === Infinity
26351 ? [[NaN, NaN], [NaN, NaN]]
26352 : [[lambda0$1, phi0], [lambda1, phi1]];
26370 var z0; // previous point
26372 var centroidStream = {
26374 point: centroidPoint,
26375 lineStart: centroidLineStart,
26376 lineEnd: centroidLineEnd,
26377 polygonStart: function() {
26378 centroidStream.lineStart = centroidRingStart;
26379 centroidStream.lineEnd = centroidRingEnd;
26381 polygonEnd: function() {
26382 centroidStream.lineStart = centroidLineStart;
26383 centroidStream.lineEnd = centroidLineEnd;
26387 // Arithmetic mean of Cartesian vectors.
26388 function centroidPoint(lambda, phi) {
26389 lambda *= radians, phi *= radians;
26390 var cosPhi = cos$1(phi);
26391 centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi));
26394 function centroidPointCartesian(x, y, z) {
26396 X0 += (x - X0) / W0;
26397 Y0 += (y - Y0) / W0;
26398 Z0 += (z - Z0) / W0;
26401 function centroidLineStart() {
26402 centroidStream.point = centroidLinePointFirst;
26405 function centroidLinePointFirst(lambda, phi) {
26406 lambda *= radians, phi *= radians;
26407 var cosPhi = cos$1(phi);
26408 x0 = cosPhi * cos$1(lambda);
26409 y0 = cosPhi * sin$1(lambda);
26411 centroidStream.point = centroidLinePoint;
26412 centroidPointCartesian(x0, y0, z0);
26415 function centroidLinePoint(lambda, phi) {
26416 lambda *= radians, phi *= radians;
26417 var cosPhi = cos$1(phi),
26418 x = cosPhi * cos$1(lambda),
26419 y = cosPhi * sin$1(lambda),
26421 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);
26423 X1 += w * (x0 + (x0 = x));
26424 Y1 += w * (y0 + (y0 = y));
26425 Z1 += w * (z0 + (z0 = z));
26426 centroidPointCartesian(x0, y0, z0);
26429 function centroidLineEnd() {
26430 centroidStream.point = centroidPoint;
26433 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
26434 // J. Applied Mechanics 42, 239 (1975).
26435 function centroidRingStart() {
26436 centroidStream.point = centroidRingPointFirst;
26439 function centroidRingEnd() {
26440 centroidRingPoint(lambda00$2, phi00$2);
26441 centroidStream.point = centroidPoint;
26444 function centroidRingPointFirst(lambda, phi) {
26445 lambda00$2 = lambda, phi00$2 = phi;
26446 lambda *= radians, phi *= radians;
26447 centroidStream.point = centroidRingPoint;
26448 var cosPhi = cos$1(phi);
26449 x0 = cosPhi * cos$1(lambda);
26450 y0 = cosPhi * sin$1(lambda);
26452 centroidPointCartesian(x0, y0, z0);
26455 function centroidRingPoint(lambda, phi) {
26456 lambda *= radians, phi *= radians;
26457 var cosPhi = cos$1(phi),
26458 x = cosPhi * cos$1(lambda),
26459 y = cosPhi * sin$1(lambda),
26461 cx = y0 * z - z0 * y,
26462 cy = z0 * x - x0 * z,
26463 cz = x0 * y - y0 * x,
26464 m = sqrt(cx * cx + cy * cy + cz * cz),
26465 w = asin(m), // line weight = angle
26466 v = m && -w / m; // area weight multiplier
26471 X1 += w * (x0 + (x0 = x));
26472 Y1 += w * (y0 + (y0 = y));
26473 Z1 += w * (z0 + (z0 = z));
26474 centroidPointCartesian(x0, y0, z0);
26477 var d3GeoCentroid = function(object) {
26482 geoStream(object, centroidStream);
26487 m = x * x + y * y + z * z;
26489 // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
26490 if (m < epsilon2$1) {
26491 x = X1, y = Y1, z = Z1;
26492 // If the feature has zero length, fall back to arithmetic mean of point vectors.
26493 if (W1 < epsilon$2) x = X0, y = Y0, z = Z0;
26494 m = x * x + y * y + z * z;
26495 // If the feature still has an undefined ccentroid, then return.
26496 if (m < epsilon2$1) return [NaN, NaN];
26499 return [atan2(y, x) * degrees$1, asin(z / sqrt(m)) * degrees$1];
26502 var constant$7 = function(x) {
26503 return function() {
26508 var compose = function(a, b) {
26510 function compose(x, y) {
26511 return x = a(x, y), b(x[0], x[1]);
26514 if (a.invert && b.invert) compose.invert = function(x, y) {
26515 return x = b.invert(x, y), x && a.invert(x[0], x[1]);
26521 function rotationIdentity(lambda, phi) {
26522 return [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi];
26525 rotationIdentity.invert = rotationIdentity;
26527 function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
26528 return (deltaLambda %= tau$3) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
26529 : rotationLambda(deltaLambda))
26530 : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
26531 : rotationIdentity);
26534 function forwardRotationLambda(deltaLambda) {
26535 return function(lambda, phi) {
26536 return lambda += deltaLambda, [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi];
26540 function rotationLambda(deltaLambda) {
26541 var rotation = forwardRotationLambda(deltaLambda);
26542 rotation.invert = forwardRotationLambda(-deltaLambda);
26546 function rotationPhiGamma(deltaPhi, deltaGamma) {
26547 var cosDeltaPhi = cos$1(deltaPhi),
26548 sinDeltaPhi = sin$1(deltaPhi),
26549 cosDeltaGamma = cos$1(deltaGamma),
26550 sinDeltaGamma = sin$1(deltaGamma);
26552 function rotation(lambda, phi) {
26553 var cosPhi = cos$1(phi),
26554 x = cos$1(lambda) * cosPhi,
26555 y = sin$1(lambda) * cosPhi,
26557 k = z * cosDeltaPhi + x * sinDeltaPhi;
26559 atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
26560 asin(k * cosDeltaGamma + y * sinDeltaGamma)
26564 rotation.invert = function(lambda, phi) {
26565 var cosPhi = cos$1(phi),
26566 x = cos$1(lambda) * cosPhi,
26567 y = sin$1(lambda) * cosPhi,
26569 k = z * cosDeltaGamma - y * sinDeltaGamma;
26571 atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
26572 asin(k * cosDeltaPhi - x * sinDeltaPhi)
26579 var rotation = function(rotate) {
26580 rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
26582 function forward(coordinates) {
26583 coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
26584 return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
26587 forward.invert = function(coordinates) {
26588 coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
26589 return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
26595 // Generates a circle centered at [0°, 0°], with a given radius and precision.
26596 function circleStream(stream, radius, delta, direction, t0, t1) {
26597 if (!delta) return;
26598 var cosRadius = cos$1(radius),
26599 sinRadius = sin$1(radius),
26600 step = direction * delta;
26602 t0 = radius + direction * tau$3;
26603 t1 = radius - step / 2;
26605 t0 = circleRadius(cosRadius, t0);
26606 t1 = circleRadius(cosRadius, t1);
26607 if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$3;
26609 for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
26610 point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]);
26611 stream.point(point[0], point[1]);
26615 // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
26616 function circleRadius(cosRadius, point) {
26617 point = cartesian(point), point[0] -= cosRadius;
26618 cartesianNormalizeInPlace(point);
26619 var radius = acos(-point[1]);
26620 return ((-point[2] < 0 ? -radius : radius) + tau$3 - epsilon$2) % tau$3;
26623 var circle = function() {
26624 var center = constant$7([0, 0]),
26625 radius = constant$7(90),
26626 precision = constant$7(6),
26629 stream = {point: point};
26631 function point(x, y) {
26632 ring.push(x = rotate(x, y));
26633 x[0] *= degrees$1, x[1] *= degrees$1;
26636 function circle() {
26637 var c = center.apply(this, arguments),
26638 r = radius.apply(this, arguments) * radians,
26639 p = precision.apply(this, arguments) * radians;
26641 rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
26642 circleStream(stream, r, p, 1);
26643 c = {type: "Polygon", coordinates: [ring]};
26644 ring = rotate = null;
26648 circle.center = function(_) {
26649 return arguments.length ? (center = typeof _ === "function" ? _ : constant$7([+_[0], +_[1]]), circle) : center;
26652 circle.radius = function(_) {
26653 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), circle) : radius;
26656 circle.precision = function(_) {
26657 return arguments.length ? (precision = typeof _ === "function" ? _ : constant$7(+_), circle) : precision;
26663 var clipBuffer = function() {
26667 point: function(x, y) {
26670 lineStart: function() {
26671 lines.push(line = []);
26674 rejoin: function() {
26675 if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
26677 result: function() {
26678 var result = lines;
26686 var clipLine = function(a, b, x0, y0, x1, y1) {
26698 if (!dx && r > 0) return;
26701 if (r < t0) return;
26702 if (r < t1) t1 = r;
26703 } else if (dx > 0) {
26704 if (r > t1) return;
26705 if (r > t0) t0 = r;
26709 if (!dx && r < 0) return;
26712 if (r > t1) return;
26713 if (r > t0) t0 = r;
26714 } else if (dx > 0) {
26715 if (r < t0) return;
26716 if (r < t1) t1 = r;
26720 if (!dy && r > 0) return;
26723 if (r < t0) return;
26724 if (r < t1) t1 = r;
26725 } else if (dy > 0) {
26726 if (r > t1) return;
26727 if (r > t0) t0 = r;
26731 if (!dy && r < 0) return;
26734 if (r > t1) return;
26735 if (r > t0) t0 = r;
26736 } else if (dy > 0) {
26737 if (r < t0) return;
26738 if (r < t1) t1 = r;
26741 if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
26742 if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
26746 var pointEqual = function(a, b) {
26747 return abs(a[0] - b[0]) < epsilon$2 && abs(a[1] - b[1]) < epsilon$2;
26750 function Intersection(point, points, other, entry) {
26753 this.o = other; // another intersection
26754 this.e = entry; // is an entry?
26755 this.v = false; // visited
26756 this.n = this.p = null; // next & previous
26759 // A generalized polygon clipping algorithm: given a polygon that has been cut
26760 // into its visible line segments, and rejoins the segments by interpolating
26761 // along the clip edge.
26762 var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) {
26768 segments.forEach(function(segment) {
26769 if ((n = segment.length - 1) <= 0) return;
26770 var n, p0 = segment[0], p1 = segment[n], x;
26772 // If the first and last points of a segment are coincident, then treat as a
26773 // closed ring. TODO if all rings are closed, then the winding order of the
26774 // exterior ring should be checked.
26775 if (pointEqual(p0, p1)) {
26776 stream.lineStart();
26777 for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
26782 subject.push(x = new Intersection(p0, segment, null, true));
26783 clip.push(x.o = new Intersection(p0, null, x, false));
26784 subject.push(x = new Intersection(p1, segment, null, false));
26785 clip.push(x.o = new Intersection(p1, null, x, true));
26788 if (!subject.length) return;
26790 clip.sort(compareIntersection);
26794 for (i = 0, n = clip.length; i < n; ++i) {
26795 clip[i].e = startInside = !startInside;
26798 var start = subject[0],
26803 // Find first unvisited intersection.
26804 var current = start,
26806 while (current.v) if ((current = current.n) === start) return;
26807 points = current.z;
26808 stream.lineStart();
26810 current.v = current.o.v = true;
26813 for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
26815 interpolate(current.x, current.n.x, 1, stream);
26817 current = current.n;
26820 points = current.p.z;
26821 for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
26823 interpolate(current.x, current.p.x, -1, stream);
26825 current = current.p;
26827 current = current.o;
26828 points = current.z;
26829 isSubject = !isSubject;
26830 } while (!current.v);
26835 function link$1(array) {
26836 if (!(n = array.length)) return;
26842 a.n = b = array[i];
26846 a.n = b = array[0];
26851 var clipMin = -clipMax;
26853 // TODO Use d3-polygon’s polygonContains here for the ring check?
26854 // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
26856 function clipExtent(x0, y0, x1, y1) {
26858 function visible(x, y) {
26859 return x0 <= x && x <= x1 && y0 <= y && y <= y1;
26862 function interpolate(from, to, direction, stream) {
26865 || (a = corner(from, direction)) !== (a1 = corner(to, direction))
26866 || comparePoint(from, to) < 0 ^ direction > 0) {
26867 do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
26868 while ((a = (a + direction + 4) % 4) !== a1);
26870 stream.point(to[0], to[1]);
26874 function corner(p, direction) {
26875 return abs(p[0] - x0) < epsilon$2 ? direction > 0 ? 0 : 3
26876 : abs(p[0] - x1) < epsilon$2 ? direction > 0 ? 2 : 1
26877 : abs(p[1] - y0) < epsilon$2 ? direction > 0 ? 1 : 0
26878 : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
26881 function compareIntersection(a, b) {
26882 return comparePoint(a.x, b.x);
26885 function comparePoint(a, b) {
26886 var ca = corner(a, 1),
26888 return ca !== cb ? ca - cb
26889 : ca === 0 ? b[1] - a[1]
26890 : ca === 1 ? a[0] - b[0]
26891 : ca === 2 ? a[1] - b[1]
26895 return function(stream) {
26896 var activeStream = stream,
26897 bufferStream = clipBuffer(),
26901 x__, y__, v__, // first point
26902 x_, y_, v_, // previous point
26908 lineStart: lineStart,
26910 polygonStart: polygonStart,
26911 polygonEnd: polygonEnd
26914 function point(x, y) {
26915 if (visible(x, y)) activeStream.point(x, y);
26918 function polygonInside() {
26921 for (var i = 0, n = polygon.length; i < n; ++i) {
26922 for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
26923 a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
26924 if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
26925 else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
26932 // Buffer geometry within a polygon and then clip it en masse.
26933 function polygonStart() {
26934 activeStream = bufferStream, segments = [], polygon = [], clean = true;
26937 function polygonEnd() {
26938 var startInside = polygonInside(),
26939 cleanInside = clean && startInside,
26940 visible = (segments = merge(segments)).length;
26941 if (cleanInside || visible) {
26942 stream.polygonStart();
26944 stream.lineStart();
26945 interpolate(null, null, 1, stream);
26949 clipPolygon(segments, compareIntersection, startInside, interpolate, stream);
26951 stream.polygonEnd();
26953 activeStream = stream, segments = polygon = ring = null;
26956 function lineStart() {
26957 clipStream.point = linePoint;
26958 if (polygon) polygon.push(ring = []);
26964 // TODO rather than special-case polygons, simply handle them separately.
26965 // Ideally, coincident intersection points should be jittered to avoid
26966 // clipping issues.
26967 function lineEnd() {
26969 linePoint(x__, y__);
26970 if (v__ && v_) bufferStream.rejoin();
26971 segments.push(bufferStream.result());
26973 clipStream.point = point;
26974 if (v_) activeStream.lineEnd();
26977 function linePoint(x, y) {
26978 var v = visible(x, y);
26979 if (polygon) ring.push([x, y]);
26981 x__ = x, y__ = y, v__ = v;
26984 activeStream.lineStart();
26985 activeStream.point(x, y);
26988 if (v && v_) activeStream.point(x, y);
26990 var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
26991 b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
26992 if (clipLine(a, b, x0, y0, x1, y1)) {
26994 activeStream.lineStart();
26995 activeStream.point(a[0], a[1]);
26997 activeStream.point(b[0], b[1]);
26998 if (!v) activeStream.lineEnd();
27001 activeStream.lineStart();
27002 activeStream.point(x, y);
27007 x_ = x, y_ = y, v_ = v;
27014 var extent$1 = function() {
27024 stream: function(stream) {
27025 return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream);
27027 extent: function(_) {
27028 return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]];
27033 var sum$1 = adder();
27035 var polygonContains = function(polygon, point) {
27036 var lambda = point[0],
27038 normal = [sin$1(lambda), -cos$1(lambda), 0],
27044 for (var i = 0, n = polygon.length; i < n; ++i) {
27045 if (!(m = (ring = polygon[i]).length)) continue;
27048 point0 = ring[m - 1],
27049 lambda0 = point0[0],
27050 phi0 = point0[1] / 2 + quarterPi,
27051 sinPhi0 = sin$1(phi0),
27052 cosPhi0 = cos$1(phi0);
27054 for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
27055 var point1 = ring[j],
27056 lambda1 = point1[0],
27057 phi1 = point1[1] / 2 + quarterPi,
27058 sinPhi1 = sin$1(phi1),
27059 cosPhi1 = cos$1(phi1),
27060 delta = lambda1 - lambda0,
27061 sign$$1 = delta >= 0 ? 1 : -1,
27062 absDelta = sign$$1 * delta,
27063 antimeridian = absDelta > pi$3,
27064 k = sinPhi0 * sinPhi1;
27066 sum$1.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta)));
27067 angle += antimeridian ? delta + sign$$1 * tau$3 : delta;
27069 // Are the longitudes either side of the point’s meridian (lambda),
27070 // and are the latitudes smaller than the parallel (phi)?
27071 if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
27072 var arc = cartesianCross(cartesian(point0), cartesian(point1));
27073 cartesianNormalizeInPlace(arc);
27074 var intersection = cartesianCross(normal, arc);
27075 cartesianNormalizeInPlace(intersection);
27076 var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
27077 if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
27078 winding += antimeridian ^ delta >= 0 ? 1 : -1;
27084 // First, determine whether the South pole is inside or outside:
27086 // It is inside if:
27087 // * the polygon winds around it in a clockwise direction.
27088 // * the polygon does not (cumulatively) wind around it, but has a negative
27089 // (counter-clockwise) area.
27091 // Second, count the (signed) number of times a segment crosses a lambda
27092 // from the point to the South pole. If it is zero, then the point is the
27093 // same side as the South pole.
27095 return (angle < -epsilon$2 || angle < epsilon$2 && sum$1 < -epsilon$2) ^ (winding & 1);
27098 var lengthSum = adder();
27103 var lengthStream = {
27106 lineStart: lengthLineStart,
27108 polygonStart: noop$1,
27112 function lengthLineStart() {
27113 lengthStream.point = lengthPointFirst;
27114 lengthStream.lineEnd = lengthLineEnd;
27117 function lengthLineEnd() {
27118 lengthStream.point = lengthStream.lineEnd = noop$1;
27121 function lengthPointFirst(lambda, phi) {
27122 lambda *= radians, phi *= radians;
27123 lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi);
27124 lengthStream.point = lengthPoint;
27127 function lengthPoint(lambda, phi) {
27128 lambda *= radians, phi *= radians;
27129 var sinPhi = sin$1(phi),
27130 cosPhi = cos$1(phi),
27131 delta = abs(lambda - lambda0$2),
27132 cosDelta = cos$1(delta),
27133 sinDelta = sin$1(delta),
27134 x = cosPhi * sinDelta,
27135 y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta,
27136 z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta;
27137 lengthSum.add(atan2(sqrt(x * x + y * y), z));
27138 lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi;
27141 var d3GeoLength = function(object) {
27143 geoStream(object, lengthStream);
27147 var coordinates = [null, null];
27148 var object$1 = {type: "LineString", coordinates: coordinates};
27150 var distance = function(a, b) {
27151 coordinates[0] = a;
27152 coordinates[1] = b;
27153 return d3GeoLength(object$1);
27156 var containsObjectType = {
27157 Feature: function(object, point) {
27158 return containsGeometry(object.geometry, point);
27160 FeatureCollection: function(object, point) {
27161 var features = object.features, i = -1, n = features.length;
27162 while (++i < n) if (containsGeometry(features[i].geometry, point)) return true;
27167 var containsGeometryType = {
27168 Sphere: function() {
27171 Point: function(object, point) {
27172 return containsPoint(object.coordinates, point);
27174 MultiPoint: function(object, point) {
27175 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27176 while (++i < n) if (containsPoint(coordinates[i], point)) return true;
27179 LineString: function(object, point) {
27180 return containsLine(object.coordinates, point);
27182 MultiLineString: function(object, point) {
27183 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27184 while (++i < n) if (containsLine(coordinates[i], point)) return true;
27187 Polygon: function(object, point) {
27188 return containsPolygon(object.coordinates, point);
27190 MultiPolygon: function(object, point) {
27191 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27192 while (++i < n) if (containsPolygon(coordinates[i], point)) return true;
27195 GeometryCollection: function(object, point) {
27196 var geometries = object.geometries, i = -1, n = geometries.length;
27197 while (++i < n) if (containsGeometry(geometries[i], point)) return true;
27202 function containsGeometry(geometry, point) {
27203 return geometry && containsGeometryType.hasOwnProperty(geometry.type)
27204 ? containsGeometryType[geometry.type](geometry, point)
27208 function containsPoint(coordinates, point) {
27209 return distance(coordinates, point) === 0;
27212 function containsLine(coordinates, point) {
27213 var ab = distance(coordinates[0], coordinates[1]),
27214 ao = distance(coordinates[0], point),
27215 ob = distance(point, coordinates[1]);
27216 return ao + ob <= ab + epsilon$2;
27219 function containsPolygon(coordinates, point) {
27220 return !!polygonContains(coordinates.map(ringRadians), pointRadians(point));
27223 function ringRadians(ring) {
27224 return ring = ring.map(pointRadians), ring.pop(), ring;
27227 function pointRadians(point) {
27228 return [point[0] * radians, point[1] * radians];
27231 var contains = function(object, point) {
27232 return (object && containsObjectType.hasOwnProperty(object.type)
27233 ? containsObjectType[object.type]
27234 : containsGeometry)(object, point);
27237 function graticuleX(y0, y1, dy) {
27238 var y = sequence(y0, y1 - epsilon$2, dy).concat(y1);
27239 return function(x) { return y.map(function(y) { return [x, y]; }); };
27242 function graticuleY(x0, x1, dx) {
27243 var x = sequence(x0, x1 - epsilon$2, dx).concat(x1);
27244 return function(y) { return x.map(function(x) { return [x, y]; }); };
27247 function graticule() {
27248 var x1, x0, X1, X0,
27250 dx = 10, dy = dx, DX = 90, DY = 360,
27254 function graticule() {
27255 return {type: "MultiLineString", coordinates: lines()};
27259 return sequence(ceil(X0 / DX) * DX, X1, DX).map(X)
27260 .concat(sequence(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
27261 .concat(sequence(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$2; }).map(x))
27262 .concat(sequence(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$2; }).map(y));
27265 graticule.lines = function() {
27266 return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
27269 graticule.outline = function() {
27275 X(X1).reverse().slice(1),
27276 Y(Y0).reverse().slice(1))
27281 graticule.extent = function(_) {
27282 if (!arguments.length) return graticule.extentMinor();
27283 return graticule.extentMajor(_).extentMinor(_);
27286 graticule.extentMajor = function(_) {
27287 if (!arguments.length) return [[X0, Y0], [X1, Y1]];
27288 X0 = +_[0][0], X1 = +_[1][0];
27289 Y0 = +_[0][1], Y1 = +_[1][1];
27290 if (X0 > X1) _ = X0, X0 = X1, X1 = _;
27291 if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
27292 return graticule.precision(precision);
27295 graticule.extentMinor = function(_) {
27296 if (!arguments.length) return [[x0, y0], [x1, y1]];
27297 x0 = +_[0][0], x1 = +_[1][0];
27298 y0 = +_[0][1], y1 = +_[1][1];
27299 if (x0 > x1) _ = x0, x0 = x1, x1 = _;
27300 if (y0 > y1) _ = y0, y0 = y1, y1 = _;
27301 return graticule.precision(precision);
27304 graticule.step = function(_) {
27305 if (!arguments.length) return graticule.stepMinor();
27306 return graticule.stepMajor(_).stepMinor(_);
27309 graticule.stepMajor = function(_) {
27310 if (!arguments.length) return [DX, DY];
27311 DX = +_[0], DY = +_[1];
27315 graticule.stepMinor = function(_) {
27316 if (!arguments.length) return [dx, dy];
27317 dx = +_[0], dy = +_[1];
27321 graticule.precision = function(_) {
27322 if (!arguments.length) return precision;
27324 x = graticuleX(y0, y1, 90);
27325 y = graticuleY(x0, x1, precision);
27326 X = graticuleX(Y0, Y1, 90);
27327 Y = graticuleY(X0, X1, precision);
27332 .extentMajor([[-180, -90 + epsilon$2], [180, 90 - epsilon$2]])
27333 .extentMinor([[-180, -80 - epsilon$2], [180, 80 + epsilon$2]]);
27336 function graticule10() {
27337 return graticule()();
27340 var interpolate$1 = function(a, b) {
27341 var x0 = a[0] * radians,
27342 y0 = a[1] * radians,
27343 x1 = b[0] * radians,
27344 y1 = b[1] * radians,
27349 kx0 = cy0 * cos$1(x0),
27350 ky0 = cy0 * sin$1(x0),
27351 kx1 = cy1 * cos$1(x1),
27352 ky1 = cy1 * sin$1(x1),
27353 d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))),
27356 var interpolate = d ? function(t) {
27357 var B = sin$1(t *= d) / k,
27358 A = sin$1(d - t) / k,
27359 x = A * kx0 + B * kx1,
27360 y = A * ky0 + B * ky1,
27361 z = A * sy0 + B * sy1;
27363 atan2(y, x) * degrees$1,
27364 atan2(z, sqrt(x * x + y * y)) * degrees$1
27367 return [x0 * degrees$1, y0 * degrees$1];
27370 interpolate.distance = d;
27372 return interpolate;
27375 var identity$4 = function(x) {
27379 var areaSum$1 = adder();
27380 var areaRingSum$1 = adder();
27386 var areaStream$1 = {
27390 polygonStart: function() {
27391 areaStream$1.lineStart = areaRingStart$1;
27392 areaStream$1.lineEnd = areaRingEnd$1;
27394 polygonEnd: function() {
27395 areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$1;
27396 areaSum$1.add(abs(areaRingSum$1));
27397 areaRingSum$1.reset();
27399 result: function() {
27400 var area = areaSum$1 / 2;
27406 function areaRingStart$1() {
27407 areaStream$1.point = areaPointFirst$1;
27410 function areaPointFirst$1(x, y) {
27411 areaStream$1.point = areaPoint$1;
27412 x00 = x0$1 = x, y00 = y0$1 = y;
27415 function areaPoint$1(x, y) {
27416 areaRingSum$1.add(y0$1 * x - x0$1 * y);
27417 x0$1 = x, y0$1 = y;
27420 function areaRingEnd$1() {
27421 areaPoint$1(x00, y00);
27424 var x0$2 = Infinity;
27429 var boundsStream$1 = {
27430 point: boundsPoint$1,
27433 polygonStart: noop$1,
27434 polygonEnd: noop$1,
27435 result: function() {
27436 var bounds = [[x0$2, y0$2], [x1, y1]];
27437 x1 = y1 = -(y0$2 = x0$2 = Infinity);
27442 function boundsPoint$1(x, y) {
27443 if (x < x0$2) x0$2 = x;
27444 if (x > x1) x1 = x;
27445 if (y < y0$2) y0$2 = y;
27446 if (y > y1) y1 = y;
27449 // TODO Enforce positive area for exterior, negative area for interior?
27465 var centroidStream$1 = {
27466 point: centroidPoint$1,
27467 lineStart: centroidLineStart$1,
27468 lineEnd: centroidLineEnd$1,
27469 polygonStart: function() {
27470 centroidStream$1.lineStart = centroidRingStart$1;
27471 centroidStream$1.lineEnd = centroidRingEnd$1;
27473 polygonEnd: function() {
27474 centroidStream$1.point = centroidPoint$1;
27475 centroidStream$1.lineStart = centroidLineStart$1;
27476 centroidStream$1.lineEnd = centroidLineEnd$1;
27478 result: function() {
27479 var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1]
27480 : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1]
27481 : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1]
27483 X0$1 = Y0$1 = Z0$1 =
27484 X1$1 = Y1$1 = Z1$1 =
27485 X2$1 = Y2$1 = Z2$1 = 0;
27490 function centroidPoint$1(x, y) {
27496 function centroidLineStart$1() {
27497 centroidStream$1.point = centroidPointFirstLine;
27500 function centroidPointFirstLine(x, y) {
27501 centroidStream$1.point = centroidPointLine;
27502 centroidPoint$1(x0$3 = x, y0$3 = y);
27505 function centroidPointLine(x, y) {
27506 var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy);
27507 X1$1 += z * (x0$3 + x) / 2;
27508 Y1$1 += z * (y0$3 + y) / 2;
27510 centroidPoint$1(x0$3 = x, y0$3 = y);
27513 function centroidLineEnd$1() {
27514 centroidStream$1.point = centroidPoint$1;
27517 function centroidRingStart$1() {
27518 centroidStream$1.point = centroidPointFirstRing;
27521 function centroidRingEnd$1() {
27522 centroidPointRing(x00$1, y00$1);
27525 function centroidPointFirstRing(x, y) {
27526 centroidStream$1.point = centroidPointRing;
27527 centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y);
27530 function centroidPointRing(x, y) {
27533 z = sqrt(dx * dx + dy * dy);
27535 X1$1 += z * (x0$3 + x) / 2;
27536 Y1$1 += z * (y0$3 + y) / 2;
27539 z = y0$3 * x - x0$3 * y;
27540 X2$1 += z * (x0$3 + x);
27541 Y2$1 += z * (y0$3 + y);
27543 centroidPoint$1(x0$3 = x, y0$3 = y);
27546 function PathContext(context) {
27547 this._context = context;
27550 PathContext.prototype = {
27552 pointRadius: function(_) {
27553 return this._radius = _, this;
27555 polygonStart: function() {
27558 polygonEnd: function() {
27561 lineStart: function() {
27564 lineEnd: function() {
27565 if (this._line === 0) this._context.closePath();
27568 point: function(x, y) {
27569 switch (this._point) {
27571 this._context.moveTo(x, y);
27576 this._context.lineTo(x, y);
27580 this._context.moveTo(x + this._radius, y);
27581 this._context.arc(x, y, this._radius, 0, tau$3);
27589 var lengthSum$1 = adder();
27596 var lengthStream$1 = {
27598 lineStart: function() {
27599 lengthStream$1.point = lengthPointFirst$1;
27601 lineEnd: function() {
27602 if (lengthRing) lengthPoint$1(x00$2, y00$2);
27603 lengthStream$1.point = noop$1;
27605 polygonStart: function() {
27608 polygonEnd: function() {
27611 result: function() {
27612 var length = +lengthSum$1;
27613 lengthSum$1.reset();
27618 function lengthPointFirst$1(x, y) {
27619 lengthStream$1.point = lengthPoint$1;
27620 x00$2 = x0$4 = x, y00$2 = y0$4 = y;
27623 function lengthPoint$1(x, y) {
27624 x0$4 -= x, y0$4 -= y;
27625 lengthSum$1.add(sqrt(x0$4 * x0$4 + y0$4 * y0$4));
27626 x0$4 = x, y0$4 = y;
27629 function PathString() {
27633 PathString.prototype = {
27634 _circle: circle$1(4.5),
27635 pointRadius: function(_) {
27636 return this._circle = circle$1(_), this;
27638 polygonStart: function() {
27641 polygonEnd: function() {
27644 lineStart: function() {
27647 lineEnd: function() {
27648 if (this._line === 0) this._string.push("Z");
27651 point: function(x, y) {
27652 switch (this._point) {
27654 this._string.push("M", x, ",", y);
27659 this._string.push("L", x, ",", y);
27663 this._string.push("M", x, ",", y, this._circle);
27668 result: function() {
27669 if (this._string.length) {
27670 var result = this._string.join("");
27677 function circle$1(radius) {
27678 return "m0," + radius
27679 + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
27680 + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
27684 var index$4 = function(projection, context) {
27685 var pointRadius = 4.5,
27689 function path(object) {
27691 if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
27692 geoStream(object, projectionStream(contextStream));
27694 return contextStream.result();
27697 path.area = function(object) {
27698 geoStream(object, projectionStream(areaStream$1));
27699 return areaStream$1.result();
27702 path.measure = function(object) {
27703 geoStream(object, projectionStream(lengthStream$1));
27704 return lengthStream$1.result();
27707 path.bounds = function(object) {
27708 geoStream(object, projectionStream(boundsStream$1));
27709 return boundsStream$1.result();
27712 path.centroid = function(object) {
27713 geoStream(object, projectionStream(centroidStream$1));
27714 return centroidStream$1.result();
27717 path.projection = function(_) {
27718 return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection;
27721 path.context = function(_) {
27722 if (!arguments.length) return context;
27723 contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _);
27724 if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
27728 path.pointRadius = function(_) {
27729 if (!arguments.length) return pointRadius;
27730 pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
27734 return path.projection(projection).context(context);
27737 var clip = function(pointVisible, clipLine, interpolate, start) {
27738 return function(rotate, sink) {
27739 var line = clipLine(sink),
27740 rotatedStart = rotate.invert(start[0], start[1]),
27741 ringBuffer = clipBuffer(),
27742 ringSink = clipLine(ringBuffer),
27743 polygonStarted = false,
27750 lineStart: lineStart,
27752 polygonStart: function() {
27753 clip.point = pointRing;
27754 clip.lineStart = ringStart;
27755 clip.lineEnd = ringEnd;
27759 polygonEnd: function() {
27760 clip.point = point;
27761 clip.lineStart = lineStart;
27762 clip.lineEnd = lineEnd;
27763 segments = merge(segments);
27764 var startInside = polygonContains(polygon, rotatedStart);
27765 if (segments.length) {
27766 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27767 clipPolygon(segments, compareIntersection, startInside, interpolate, sink);
27768 } else if (startInside) {
27769 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27771 interpolate(null, null, 1, sink);
27774 if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
27775 segments = polygon = null;
27777 sphere: function() {
27778 sink.polygonStart();
27780 interpolate(null, null, 1, sink);
27786 function point(lambda, phi) {
27787 var point = rotate(lambda, phi);
27788 if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi);
27791 function pointLine(lambda, phi) {
27792 var point = rotate(lambda, phi);
27793 line.point(point[0], point[1]);
27796 function lineStart() {
27797 clip.point = pointLine;
27801 function lineEnd() {
27802 clip.point = point;
27806 function pointRing(lambda, phi) {
27807 ring.push([lambda, phi]);
27808 var point = rotate(lambda, phi);
27809 ringSink.point(point[0], point[1]);
27812 function ringStart() {
27813 ringSink.lineStart();
27817 function ringEnd() {
27818 pointRing(ring[0][0], ring[0][1]);
27819 ringSink.lineEnd();
27821 var clean = ringSink.clean(),
27822 ringSegments = ringBuffer.result(),
27823 i, n = ringSegments.length, m,
27828 polygon.push(ring);
27833 // No intersections.
27835 segment = ringSegments[0];
27836 if ((m = segment.length - 1) > 0) {
27837 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27839 for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
27845 // Rejoin connected segments.
27846 // TODO reuse ringBuffer.rejoin()?
27847 if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
27849 segments.push(ringSegments.filter(validSegment));
27856 function validSegment(segment) {
27857 return segment.length > 1;
27860 // Intersections are sorted along the clip edge. For both antimeridian cutting
27861 // and circle clipping, the same comparison is used.
27862 function compareIntersection(a, b) {
27863 return ((a = a.x)[0] < 0 ? a[1] - halfPi$2 - epsilon$2 : halfPi$2 - a[1])
27864 - ((b = b.x)[0] < 0 ? b[1] - halfPi$2 - epsilon$2 : halfPi$2 - b[1]);
27867 var clipAntimeridian = clip(
27868 function() { return true; },
27869 clipAntimeridianLine,
27870 clipAntimeridianInterpolate,
27874 // Takes a line and cuts into visible segments. Return values: 0 - there were
27875 // intersections or the line was empty; 1 - no intersections; 2 - there were
27876 // intersections, and the first and last segments should be rejoined.
27877 function clipAntimeridianLine(stream) {
27881 clean; // no intersections
27884 lineStart: function() {
27885 stream.lineStart();
27888 point: function(lambda1, phi1) {
27889 var sign1 = lambda1 > 0 ? pi$3 : -pi$3,
27890 delta = abs(lambda1 - lambda0);
27891 if (abs(delta - pi$3) < epsilon$2) { // line crosses a pole
27892 stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$2 : -halfPi$2);
27893 stream.point(sign0, phi0);
27895 stream.lineStart();
27896 stream.point(sign1, phi0);
27897 stream.point(lambda1, phi0);
27899 } else if (sign0 !== sign1 && delta >= pi$3) { // line crosses antimeridian
27900 if (abs(lambda0 - sign0) < epsilon$2) lambda0 -= sign0 * epsilon$2; // handle degeneracies
27901 if (abs(lambda1 - sign1) < epsilon$2) lambda1 -= sign1 * epsilon$2;
27902 phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
27903 stream.point(sign0, phi0);
27905 stream.lineStart();
27906 stream.point(sign1, phi0);
27909 stream.point(lambda0 = lambda1, phi0 = phi1);
27912 lineEnd: function() {
27914 lambda0 = phi0 = NaN;
27916 clean: function() {
27917 return 2 - clean; // if intersections, rejoin first and last segments
27922 function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
27925 sinLambda0Lambda1 = sin$1(lambda0 - lambda1);
27926 return abs(sinLambda0Lambda1) > epsilon$2
27927 ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1)
27928 - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0))
27929 / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
27930 : (phi0 + phi1) / 2;
27933 function clipAntimeridianInterpolate(from, to, direction, stream) {
27935 if (from == null) {
27936 phi = direction * halfPi$2;
27937 stream.point(-pi$3, phi);
27938 stream.point(0, phi);
27939 stream.point(pi$3, phi);
27940 stream.point(pi$3, 0);
27941 stream.point(pi$3, -phi);
27942 stream.point(0, -phi);
27943 stream.point(-pi$3, -phi);
27944 stream.point(-pi$3, 0);
27945 stream.point(-pi$3, phi);
27946 } else if (abs(from[0] - to[0]) > epsilon$2) {
27947 var lambda = from[0] < to[0] ? pi$3 : -pi$3;
27948 phi = direction * lambda / 2;
27949 stream.point(-lambda, phi);
27950 stream.point(0, phi);
27951 stream.point(lambda, phi);
27953 stream.point(to[0], to[1]);
27957 var clipCircle = function(radius, delta) {
27958 var cr = cos$1(radius),
27959 smallRadius = cr > 0,
27960 notHemisphere = abs(cr) > epsilon$2; // TODO optimise for this common case
27962 function interpolate(from, to, direction, stream) {
27963 circleStream(stream, radius, delta, direction, from, to);
27966 function visible(lambda, phi) {
27967 return cos$1(lambda) * cos$1(phi) > cr;
27970 // Takes a line and cuts into visible segments. Return values used for polygon
27971 // clipping: 0 - there were intersections or the line was empty; 1 - no
27972 // intersections 2 - there were intersections, and the first and last segments
27973 // should be rejoined.
27974 function clipLine(stream) {
27975 var point0, // previous point
27976 c0, // code for previous point
27977 v0, // visibility of previous point
27978 v00, // visibility of first point
27979 clean; // no intersections
27981 lineStart: function() {
27985 point: function(lambda, phi) {
27986 var point1 = [lambda, phi],
27988 v = visible(lambda, phi),
27990 ? v ? 0 : code(lambda, phi)
27991 : v ? code(lambda + (lambda < 0 ? pi$3 : -pi$3), phi) : 0;
27992 if (!point0 && (v00 = v0 = v)) stream.lineStart();
27993 // Handle degeneracies.
27994 // TODO ignore if not clipping polygons.
27996 point2 = intersect(point0, point1);
27997 if (pointEqual(point0, point2) || pointEqual(point1, point2)) {
27998 point1[0] += epsilon$2;
27999 point1[1] += epsilon$2;
28000 v = visible(point1[0], point1[1]);
28006 // outside going in
28007 stream.lineStart();
28008 point2 = intersect(point1, point0);
28009 stream.point(point2[0], point2[1]);
28011 // inside going out
28012 point2 = intersect(point0, point1);
28013 stream.point(point2[0], point2[1]);
28017 } else if (notHemisphere && point0 && smallRadius ^ v) {
28019 // If the codes for two points are different, or are both zero,
28020 // and there this segment intersects with the small circle.
28021 if (!(c & c0) && (t = intersect(point1, point0, true))) {
28024 stream.lineStart();
28025 stream.point(t[0][0], t[0][1]);
28026 stream.point(t[1][0], t[1][1]);
28029 stream.point(t[1][0], t[1][1]);
28031 stream.lineStart();
28032 stream.point(t[0][0], t[0][1]);
28036 if (v && (!point0 || !pointEqual(point0, point1))) {
28037 stream.point(point1[0], point1[1]);
28039 point0 = point1, v0 = v, c0 = c;
28041 lineEnd: function() {
28042 if (v0) stream.lineEnd();
28045 // Rejoin first and last segments if there were intersections and the first
28046 // and last points were visible.
28047 clean: function() {
28048 return clean | ((v00 && v0) << 1);
28053 // Intersects the great circle between a and b with the clip circle.
28054 function intersect(a, b, two) {
28055 var pa = cartesian(a),
28058 // We have two planes, n1.p = d1 and n2.p = d2.
28059 // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
28060 var n1 = [1, 0, 0], // normal
28061 n2 = cartesianCross(pa, pb),
28062 n2n2 = cartesianDot(n2, n2),
28063 n1n2 = n2[0], // cartesianDot(n1, n2),
28064 determinant = n2n2 - n1n2 * n1n2;
28066 // Two polar points.
28067 if (!determinant) return !two && a;
28069 var c1 = cr * n2n2 / determinant,
28070 c2 = -cr * n1n2 / determinant,
28071 n1xn2 = cartesianCross(n1, n2),
28072 A = cartesianScale(n1, c1),
28073 B = cartesianScale(n2, c2);
28074 cartesianAddInPlace(A, B);
28076 // Solve |p(t)|^2 = 1.
28078 w = cartesianDot(A, u),
28079 uu = cartesianDot(u, u),
28080 t2 = w * w - uu * (cartesianDot(A, A) - 1);
28082 if (t2 < 0) return;
28085 q = cartesianScale(u, (-w - t) / uu);
28086 cartesianAddInPlace(q, A);
28089 if (!two) return q;
28091 // Two intersection points.
28092 var lambda0 = a[0],
28098 if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
28100 var delta = lambda1 - lambda0,
28101 polar = abs(delta - pi$3) < epsilon$2,
28102 meridian = polar || delta < epsilon$2;
28104 if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
28106 // Check that the first point is between a and b.
28109 ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$2 ? phi0 : phi1)
28110 : phi0 <= q[1] && q[1] <= phi1
28111 : delta > pi$3 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
28112 var q1 = cartesianScale(u, (-w + t) / uu);
28113 cartesianAddInPlace(q1, A);
28114 return [q, spherical(q1)];
28118 // Generates a 4-bit vector representing the location of a point relative to
28119 // the small circle's bounding box.
28120 function code(lambda, phi) {
28121 var r = smallRadius ? radius : pi$3 - radius,
28123 if (lambda < -r) code |= 1; // left
28124 else if (lambda > r) code |= 2; // right
28125 if (phi < -r) code |= 4; // below
28126 else if (phi > r) code |= 8; // above
28130 return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$3, radius - pi$3]);
28133 var transform = function(methods) {
28135 stream: transformer(methods)
28139 function transformer(methods) {
28140 return function(stream) {
28141 var s = new TransformStream;
28142 for (var key in methods) s[key] = methods[key];
28148 function TransformStream() {}
28150 TransformStream.prototype = {
28151 constructor: TransformStream,
28152 point: function(x, y) { this.stream.point(x, y); },
28153 sphere: function() { this.stream.sphere(); },
28154 lineStart: function() { this.stream.lineStart(); },
28155 lineEnd: function() { this.stream.lineEnd(); },
28156 polygonStart: function() { this.stream.polygonStart(); },
28157 polygonEnd: function() { this.stream.polygonEnd(); }
28160 function fitExtent(projection, extent, object) {
28161 var w = extent[1][0] - extent[0][0],
28162 h = extent[1][1] - extent[0][1],
28163 clip = projection.clipExtent && projection.clipExtent();
28167 .translate([0, 0]);
28169 if (clip != null) projection.clipExtent(null);
28171 geoStream(object, projection.stream(boundsStream$1));
28173 var b = boundsStream$1.result(),
28174 k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
28175 x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
28176 y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
28178 if (clip != null) projection.clipExtent(clip);
28182 .translate([x, y]);
28185 function fitSize(projection, size, object) {
28186 return fitExtent(projection, [[0, 0], size], object);
28190 var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance)
28192 var resample = function(project, delta2) {
28193 return +delta2 ? resample$1(project, delta2) : resampleNone(project);
28196 function resampleNone(project) {
28197 return transformer({
28198 point: function(x, y) {
28200 this.stream.point(x[0], x[1]);
28205 function resample$1(project, delta2) {
28207 function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
28210 d2 = dx * dx + dy * dy;
28211 if (d2 > 4 * delta2 && depth--) {
28215 m = sqrt(a * a + b * b + c * c),
28216 phi2 = asin(c /= m),
28217 lambda2 = abs(abs(c) - 1) < epsilon$2 || abs(lambda0 - lambda1) < epsilon$2 ? (lambda0 + lambda1) / 2 : atan2(b, a),
28218 p = project(lambda2, phi2),
28223 dz = dy * dx2 - dx * dy2;
28224 if (dz * dz / d2 > delta2 // perpendicular projected distance
28225 || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
28226 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
28227 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
28228 stream.point(x2, y2);
28229 resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
28233 return function(stream) {
28234 var lambda00, x00, y00, a00, b00, c00, // first point
28235 lambda0, x0, y0, a0, b0, c0; // previous point
28237 var resampleStream = {
28239 lineStart: lineStart,
28241 polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
28242 polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
28245 function point(x, y) {
28247 stream.point(x[0], x[1]);
28250 function lineStart() {
28252 resampleStream.point = linePoint;
28253 stream.lineStart();
28256 function linePoint(lambda, phi) {
28257 var c = cartesian([lambda, phi]), p = project(lambda, phi);
28258 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);
28259 stream.point(x0, y0);
28262 function lineEnd() {
28263 resampleStream.point = point;
28267 function ringStart() {
28269 resampleStream.point = ringPoint;
28270 resampleStream.lineEnd = ringEnd;
28273 function ringPoint(lambda, phi) {
28274 linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
28275 resampleStream.point = linePoint;
28278 function ringEnd() {
28279 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
28280 resampleStream.lineEnd = lineEnd;
28284 return resampleStream;
28288 var transformRadians = transformer({
28289 point: function(x, y) {
28290 this.stream.point(x * radians, y * radians);
28294 function projection(project) {
28295 return projectionMutator(function() { return project; })();
28298 function projectionMutator(projectAt) {
28301 x = 480, y = 250, // translate
28302 dx, dy, lambda = 0, phi = 0, // center
28303 deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate
28304 theta = null, preclip = clipAntimeridian, // clip angle
28305 x0 = null, y0, x1, y1, postclip = identity$4, // clip extent
28306 delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision
28310 function projection(point) {
28311 point = projectRotate(point[0] * radians, point[1] * radians);
28312 return [point[0] * k + dx, dy - point[1] * k];
28315 function invert(point) {
28316 point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k);
28317 return point && [point[0] * degrees$1, point[1] * degrees$1];
28320 function projectTransform(x, y) {
28321 return x = project(x, y), [x[0] * k + dx, dy - x[1] * k];
28324 projection.stream = function(stream) {
28325 return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream))));
28328 projection.clipAngle = function(_) {
28329 return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
28332 projection.clipExtent = function(_) {
28333 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]];
28336 projection.scale = function(_) {
28337 return arguments.length ? (k = +_, recenter()) : k;
28340 projection.translate = function(_) {
28341 return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
28344 projection.center = function(_) {
28345 return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
28348 projection.rotate = function(_) {
28349 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];
28352 projection.precision = function(_) {
28353 return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
28356 projection.fitExtent = function(extent, object) {
28357 return fitExtent(projection, extent, object);
28360 projection.fitSize = function(size, object) {
28361 return fitSize(projection, size, object);
28364 function recenter() {
28365 projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project);
28366 var center = project(lambda, phi);
28367 dx = x - center[0] * k;
28368 dy = y + center[1] * k;
28373 cache = cacheStream = null;
28377 return function() {
28378 project = projectAt.apply(this, arguments);
28379 projection.invert = project.invert && invert;
28384 function conicProjection(projectAt) {
28387 m = projectionMutator(projectAt),
28390 p.parallels = function(_) {
28391 return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1];
28397 function cylindricalEqualAreaRaw(phi0) {
28398 var cosPhi0 = cos$1(phi0);
28400 function forward(lambda, phi) {
28401 return [lambda * cosPhi0, sin$1(phi) / cosPhi0];
28404 forward.invert = function(x, y) {
28405 return [x / cosPhi0, asin(y * cosPhi0)];
28411 function conicEqualAreaRaw(y0, y1) {
28412 var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2;
28414 // Are the parallels symmetrical around the Equator?
28415 if (abs(n) < epsilon$2) return cylindricalEqualAreaRaw(y0);
28417 var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n;
28419 function project(x, y) {
28420 var r = sqrt(c - 2 * n * sin$1(y)) / n;
28421 return [r * sin$1(x *= n), r0 - r * cos$1(x)];
28424 project.invert = function(x, y) {
28426 return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
28432 var conicEqualArea = function() {
28433 return conicProjection(conicEqualAreaRaw)
28435 .center([0, 33.6442]);
28438 var albers = function() {
28439 return conicEqualArea()
28440 .parallels([29.5, 45.5])
28442 .translate([480, 250])
28444 .center([-0.6, 38.7]);
28447 // The projections must have mutually exclusive clip regions on the sphere,
28448 // as this will avoid emitting interleaving lines and polygons.
28449 function multiplex(streams) {
28450 var n = streams.length;
28452 point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
28453 sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
28454 lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
28455 lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
28456 polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
28457 polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
28461 // A composite projection for the United States, configured by default for
28462 // 960×500. The projection also works quite well at 960×600 if you change the
28463 // scale to 1285 and adjust the translate accordingly. The set of standard
28464 // parallels for each region comes from USGS, which is published here:
28465 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
28466 var albersUsa = function() {
28469 lower48 = albers(), lower48Point,
28470 alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
28471 hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
28472 point, pointStream = {point: function(x, y) { point = [x, y]; }};
28474 function albersUsa(coordinates) {
28475 var x = coordinates[0], y = coordinates[1];
28476 return point = null,
28477 (lower48Point.point(x, y), point)
28478 || (alaskaPoint.point(x, y), point)
28479 || (hawaiiPoint.point(x, y), point);
28482 albersUsa.invert = function(coordinates) {
28483 var k = lower48.scale(),
28484 t = lower48.translate(),
28485 x = (coordinates[0] - t[0]) / k,
28486 y = (coordinates[1] - t[1]) / k;
28487 return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
28488 : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
28489 : lower48).invert(coordinates);
28492 albersUsa.stream = function(stream) {
28493 return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
28496 albersUsa.precision = function(_) {
28497 if (!arguments.length) return lower48.precision();
28498 lower48.precision(_), alaska.precision(_), hawaii.precision(_);
28502 albersUsa.scale = function(_) {
28503 if (!arguments.length) return lower48.scale();
28504 lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
28505 return albersUsa.translate(lower48.translate());
28508 albersUsa.translate = function(_) {
28509 if (!arguments.length) return lower48.translate();
28510 var k = lower48.scale(), x = +_[0], y = +_[1];
28512 lower48Point = lower48
28514 .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
28515 .stream(pointStream);
28517 alaskaPoint = alaska
28518 .translate([x - 0.307 * k, y + 0.201 * k])
28519 .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]])
28520 .stream(pointStream);
28522 hawaiiPoint = hawaii
28523 .translate([x - 0.205 * k, y + 0.212 * k])
28524 .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]])
28525 .stream(pointStream);
28530 albersUsa.fitExtent = function(extent, object) {
28531 return fitExtent(albersUsa, extent, object);
28534 albersUsa.fitSize = function(size, object) {
28535 return fitSize(albersUsa, size, object);
28539 cache = cacheStream = null;
28543 return albersUsa.scale(1070);
28546 function azimuthalRaw(scale) {
28547 return function(x, y) {
28550 k = scale(cx * cy);
28558 function azimuthalInvert(angle) {
28559 return function(x, y) {
28560 var z = sqrt(x * x + y * y),
28565 atan2(x * sc, z * cc),
28566 asin(z && y * sc / z)
28571 var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
28572 return sqrt(2 / (1 + cxcy));
28575 azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
28576 return 2 * asin(z / 2);
28579 var azimuthalEqualArea = function() {
28580 return projection(azimuthalEqualAreaRaw)
28582 .clipAngle(180 - 1e-3);
28585 var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
28586 return (c = acos(c)) && c / sin$1(c);
28589 azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
28593 var azimuthalEquidistant = function() {
28594 return projection(azimuthalEquidistantRaw)
28596 .clipAngle(180 - 1e-3);
28599 function mercatorRaw(lambda, phi) {
28600 return [lambda, log(tan((halfPi$2 + phi) / 2))];
28603 mercatorRaw.invert = function(x, y) {
28604 return [x, 2 * atan(exp(y)) - halfPi$2];
28607 var mercator = function() {
28608 return mercatorProjection(mercatorRaw)
28609 .scale(961 / tau$3);
28612 function mercatorProjection(project) {
28613 var m = projection(project),
28616 translate = m.translate,
28617 clipExtent = m.clipExtent,
28618 x0 = null, y0, x1, y1; // clip extent
28620 m.scale = function(_) {
28621 return arguments.length ? (scale(_), reclip()) : scale();
28624 m.translate = function(_) {
28625 return arguments.length ? (translate(_), reclip()) : translate();
28628 m.center = function(_) {
28629 return arguments.length ? (center(_), reclip()) : center();
28632 m.clipExtent = function(_) {
28633 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]];
28636 function reclip() {
28637 var k = pi$3 * scale(),
28638 t = m(rotation(m.rotate()).invert([0, 0]));
28639 return clipExtent(x0 == null
28640 ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw
28641 ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]]
28642 : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]);
28649 return tan((halfPi$2 + y) / 2);
28652 function conicConformalRaw(y0, y1) {
28653 var cy0 = cos$1(y0),
28654 n = y0 === y1 ? sin$1(y0) : log(cy0 / cos$1(y1)) / log(tany(y1) / tany(y0)),
28655 f = cy0 * pow(tany(y0), n) / n;
28657 if (!n) return mercatorRaw;
28659 function project(x, y) {
28660 if (f > 0) { if (y < -halfPi$2 + epsilon$2) y = -halfPi$2 + epsilon$2; }
28661 else { if (y > halfPi$2 - epsilon$2) y = halfPi$2 - epsilon$2; }
28662 var r = f / pow(tany(y), n);
28663 return [r * sin$1(n * x), f - r * cos$1(n * x)];
28666 project.invert = function(x, y) {
28667 var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy);
28668 return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi$2];
28674 var conicConformal = function() {
28675 return conicProjection(conicConformalRaw)
28677 .parallels([30, 30]);
28680 function equirectangularRaw(lambda, phi) {
28681 return [lambda, phi];
28684 equirectangularRaw.invert = equirectangularRaw;
28686 var equirectangular = function() {
28687 return projection(equirectangularRaw)
28691 function conicEquidistantRaw(y0, y1) {
28692 var cy0 = cos$1(y0),
28693 n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0),
28696 if (abs(n) < epsilon$2) return equirectangularRaw;
28698 function project(x, y) {
28699 var gy = g - y, nx = n * x;
28700 return [gy * sin$1(nx), g - gy * cos$1(nx)];
28703 project.invert = function(x, y) {
28705 return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)];
28711 var conicEquidistant = function() {
28712 return conicProjection(conicEquidistantRaw)
28714 .center([0, 13.9389]);
28717 function gnomonicRaw(x, y) {
28718 var cy = cos$1(y), k = cos$1(x) * cy;
28719 return [cy * sin$1(x) / k, sin$1(y) / k];
28722 gnomonicRaw.invert = azimuthalInvert(atan);
28724 var gnomonic = function() {
28725 return projection(gnomonicRaw)
28730 function scaleTranslate(kx, ky, tx, ty) {
28731 return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity$4 : transformer({
28732 point: function(x, y) {
28733 this.stream.point(x * kx + tx, y * ky + ty);
28738 var identity$5 = function() {
28739 var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform = identity$4, // scale, translate and reflect
28740 x0 = null, y0, x1, y1, clip = identity$4, // clip extent
28746 cache = cacheStream = null;
28750 return projection = {
28751 stream: function(stream) {
28752 return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream));
28754 clipExtent: function(_) {
28755 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]];
28757 scale: function(_) {
28758 return arguments.length ? (transform = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k;
28760 translate: function(_) {
28761 return arguments.length ? (transform = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty];
28763 reflectX: function(_) {
28764 return arguments.length ? (transform = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0;
28766 reflectY: function(_) {
28767 return arguments.length ? (transform = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0;
28769 fitExtent: function(extent, object) {
28770 return fitExtent(projection, extent, object);
28772 fitSize: function(size, object) {
28773 return fitSize(projection, size, object);
28778 function orthographicRaw(x, y) {
28779 return [cos$1(y) * sin$1(x), sin$1(y)];
28782 orthographicRaw.invert = azimuthalInvert(asin);
28784 var orthographic = function() {
28785 return projection(orthographicRaw)
28787 .clipAngle(90 + epsilon$2);
28790 function stereographicRaw(x, y) {
28791 var cy = cos$1(y), k = 1 + cos$1(x) * cy;
28792 return [cy * sin$1(x) / k, sin$1(y) / k];
28795 stereographicRaw.invert = azimuthalInvert(function(z) {
28796 return 2 * atan(z);
28799 var stereographic = function() {
28800 return projection(stereographicRaw)
28805 function transverseMercatorRaw(lambda, phi) {
28806 return [log(tan((halfPi$2 + phi) / 2)), -lambda];
28809 transverseMercatorRaw.invert = function(x, y) {
28810 return [-y, 2 * atan(exp(x)) - halfPi$2];
28813 var transverseMercator = function() {
28814 var m = mercatorProjection(transverseMercatorRaw),
28818 m.center = function(_) {
28819 return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
28822 m.rotate = function(_) {
28823 return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
28826 return rotate([0, 0, 90])
28830 function defaultSeparation(a, b) {
28831 return a.parent === b.parent ? 1 : 2;
28834 function meanX(children) {
28835 return children.reduce(meanXReduce, 0) / children.length;
28838 function meanXReduce(x, c) {
28842 function maxY(children) {
28843 return 1 + children.reduce(maxYReduce, 0);
28846 function maxYReduce(y, c) {
28847 return Math.max(y, c.y);
28850 function leafLeft(node) {
28852 while (children = node.children) node = children[0];
28856 function leafRight(node) {
28858 while (children = node.children) node = children[children.length - 1];
28862 var cluster = function() {
28863 var separation = defaultSeparation,
28868 function cluster(root) {
28872 // First walk, computing the initial x & y values.
28873 root.eachAfter(function(node) {
28874 var children = node.children;
28876 node.x = meanX(children);
28877 node.y = maxY(children);
28879 node.x = previousNode ? x += separation(node, previousNode) : 0;
28881 previousNode = node;
28885 var left = leafLeft(root),
28886 right = leafRight(root),
28887 x0 = left.x - separation(left, right) / 2,
28888 x1 = right.x + separation(right, left) / 2;
28890 // Second walk, normalizing x & y to the desired size.
28891 return root.eachAfter(nodeSize ? function(node) {
28892 node.x = (node.x - root.x) * dx;
28893 node.y = (root.y - node.y) * dy;
28894 } : function(node) {
28895 node.x = (node.x - x0) / (x1 - x0) * dx;
28896 node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
28900 cluster.separation = function(x) {
28901 return arguments.length ? (separation = x, cluster) : separation;
28904 cluster.size = function(x) {
28905 return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
28908 cluster.nodeSize = function(x) {
28909 return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
28915 function count(node) {
28917 children = node.children,
28918 i = children && children.length;
28920 else while (--i >= 0) sum += children[i].value;
28924 var node_count = function() {
28925 return this.eachAfter(count);
28928 var node_each = function(callback) {
28929 var node = this, current, next = [node], children, i, n;
28931 current = next.reverse(), next = [];
28932 while (node = current.pop()) {
28933 callback(node), children = node.children;
28934 if (children) for (i = 0, n = children.length; i < n; ++i) {
28935 next.push(children[i]);
28938 } while (next.length);
28942 var node_eachBefore = function(callback) {
28943 var node = this, nodes = [node], children, i;
28944 while (node = nodes.pop()) {
28945 callback(node), children = node.children;
28946 if (children) for (i = children.length - 1; i >= 0; --i) {
28947 nodes.push(children[i]);
28953 var node_eachAfter = function(callback) {
28954 var node = this, nodes = [node], next = [], children, i, n;
28955 while (node = nodes.pop()) {
28956 next.push(node), children = node.children;
28957 if (children) for (i = 0, n = children.length; i < n; ++i) {
28958 nodes.push(children[i]);
28961 while (node = next.pop()) {
28967 var node_sum = function(value) {
28968 return this.eachAfter(function(node) {
28969 var sum = +value(node.data) || 0,
28970 children = node.children,
28971 i = children && children.length;
28972 while (--i >= 0) sum += children[i].value;
28977 var node_sort = function(compare) {
28978 return this.eachBefore(function(node) {
28979 if (node.children) {
28980 node.children.sort(compare);
28985 var node_path = function(end) {
28987 ancestor = leastCommonAncestor(start, end),
28989 while (start !== ancestor) {
28990 start = start.parent;
28993 var k = nodes.length;
28994 while (end !== ancestor) {
28995 nodes.splice(k, 0, end);
29001 function leastCommonAncestor(a, b) {
29002 if (a === b) return a;
29003 var aNodes = a.ancestors(),
29004 bNodes = b.ancestors(),
29016 var node_ancestors = function() {
29017 var node = this, nodes = [node];
29018 while (node = node.parent) {
29024 var node_descendants = function() {
29026 this.each(function(node) {
29032 var node_leaves = function() {
29034 this.eachBefore(function(node) {
29035 if (!node.children) {
29042 var node_links = function() {
29043 var root = this, links = [];
29044 root.each(function(node) {
29045 if (node !== root) { // Don’t include the root’s parent, if any.
29046 links.push({source: node.parent, target: node});
29052 function hierarchy(data, children) {
29053 var root = new Node(data),
29054 valued = +data.value && (root.value = data.value),
29062 if (children == null) children = defaultChildren;
29064 while (node = nodes.pop()) {
29065 if (valued) node.value = +node.data.value;
29066 if ((childs = children(node.data)) && (n = childs.length)) {
29067 node.children = new Array(n);
29068 for (i = n - 1; i >= 0; --i) {
29069 nodes.push(child = node.children[i] = new Node(childs[i]));
29070 child.parent = node;
29071 child.depth = node.depth + 1;
29076 return root.eachBefore(computeHeight);
29079 function node_copy() {
29080 return hierarchy(this).eachBefore(copyData);
29083 function defaultChildren(d) {
29087 function copyData(node) {
29088 node.data = node.data.data;
29091 function computeHeight(node) {
29093 do node.height = height;
29094 while ((node = node.parent) && (node.height < ++height));
29097 function Node(data) {
29101 this.parent = null;
29104 Node.prototype = hierarchy.prototype = {
29108 eachAfter: node_eachAfter,
29109 eachBefore: node_eachBefore,
29113 ancestors: node_ancestors,
29114 descendants: node_descendants,
29115 leaves: node_leaves,
29120 function Node$2(value) {
29125 var shuffle$1 = function(array) {
29127 n = (array = array.slice()).length,
29132 var next = new Node$2(array[n - 1]);
29133 if (node) node = node.next = next;
29134 else node = head = next;
29135 array[i] = array[--n];
29144 var enclose = function(circles) {
29145 return encloseN(shuffle$1(circles), []);
29148 function encloses(a, b) {
29149 var dx = b.x - a.x,
29152 return dr * dr + 1e-6 > dx * dx + dy * dy;
29155 // Returns the smallest circle that contains circles L and intersects circles B.
29156 function encloseN(L, B) {
29163 switch (B.length) {
29164 case 1: circle = enclose1(B[0]); break;
29165 case 2: circle = enclose2(B[0], B[1]); break;
29166 case 3: circle = enclose3(B[0], B[1], B[2]); break;
29170 p1 = l1._, l2 = l1.next;
29171 if (!circle || !encloses(circle, p1)) {
29173 // Temporarily truncate L before l1.
29174 if (l0) L.tail = l0, l0.next = null;
29175 else L.head = L.tail = null;
29178 circle = encloseN(L, B); // Note: reorders L!
29181 // Move l1 to the front of L and reconnect the truncated list L.
29182 if (L.head) l1.next = L.head, L.head = l1;
29183 else l1.next = null, L.head = L.tail = l1;
29184 l0 = L.tail, l0.next = l2;
29196 function enclose1(a) {
29204 function enclose2(a, b) {
29205 var x1 = a.x, y1 = a.y, r1 = a.r,
29206 x2 = b.x, y2 = b.y, r2 = b.r,
29207 x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
29208 l = Math.sqrt(x21 * x21 + y21 * y21);
29210 x: (x1 + x2 + x21 / l * r21) / 2,
29211 y: (y1 + y2 + y21 / l * r21) / 2,
29212 r: (l + r1 + r2) / 2
29216 function enclose3(a, b, c) {
29217 var x1 = a.x, y1 = a.y, r1 = a.r,
29218 x2 = b.x, y2 = b.y, r2 = b.r,
29219 x3 = c.x, y3 = c.y, r3 = c.r,
29220 a2 = 2 * (x1 - x2),
29221 b2 = 2 * (y1 - y2),
29222 c2 = 2 * (r2 - r1),
29223 d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2,
29224 a3 = 2 * (x1 - x3),
29225 b3 = 2 * (y1 - y3),
29226 c3 = 2 * (r3 - r1),
29227 d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3,
29228 ab = a3 * b2 - a2 * b3,
29229 xa = (b2 * d3 - b3 * d2) / ab - x1,
29230 xb = (b3 * c2 - b2 * c3) / ab,
29231 ya = (a3 * d2 - a2 * d3) / ab - y1,
29232 yb = (a2 * c3 - a3 * c2) / ab,
29233 A = xb * xb + yb * yb - 1,
29234 B = 2 * (xa * xb + ya * yb + r1),
29235 C = xa * xa + ya * ya - r1 * r1,
29236 r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
29238 x: xa + xb * r + x1,
29239 y: ya + yb * r + y1,
29244 function place(a, b, c) {
29251 dc = dx * dx + dy * dy;
29253 var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc),
29254 y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
29255 c.x = ax + x * dx + y * dy;
29256 c.y = ay + x * dy - y * dx;
29263 function intersects(a, b) {
29264 var dx = b.x - a.x,
29267 return dr * dr - 1e-6 > dx * dx + dy * dy;
29270 function distance2(node, x, y) {
29274 dx = (a.x * b.r + b.x * a.r) / ab - x,
29275 dy = (a.y * b.r + b.y * a.r) / ab - y;
29276 return dx * dx + dy * dy;
29279 function Node$1(circle) {
29282 this.previous = null;
29285 function packEnclose(circles) {
29286 if (!(n = circles.length)) return 0;
29290 // Place the first circle.
29291 a = circles[0], a.x = 0, a.y = 0;
29292 if (!(n > 1)) return a.r;
29294 // Place the second circle.
29295 b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
29296 if (!(n > 2)) return a.r + b.r;
29298 // Place the third circle.
29299 place(b, a, c = circles[2]);
29301 // Initialize the weighted centroid.
29302 var aa = a.r * a.r,
29306 ox = aa * a.x + ba * b.x + ca * c.x,
29307 oy = aa * a.y + ba * b.y + ca * c.y,
29308 cx, cy, i, j, k, sj, sk;
29310 // Initialize the front-chain using the first three circles a, b and c.
29311 a = new Node$1(a), b = new Node$1(b), c = new Node$1(c);
29312 a.next = c.previous = b;
29313 b.next = a.previous = c;
29314 c.next = b.previous = a;
29316 // Attempt to place each remaining circle…
29317 pack: for (i = 3; i < n; ++i) {
29318 place(a._, b._, c = circles[i]), c = new Node$1(c);
29320 // Find the closest intersecting circle on the front-chain, if any.
29321 // “Closeness” is determined by linear distance along the front-chain.
29322 // “Ahead” or “behind” is likewise determined by linear distance.
29323 j = b.next, k = a.previous, sj = b._.r, sk = a._.r;
29326 if (intersects(j._, c._)) {
29327 b = j, a.next = b, b.previous = a, --i;
29330 sj += j._.r, j = j.next;
29332 if (intersects(k._, c._)) {
29333 a = k, a.next = b, b.previous = a, --i;
29336 sk += k._.r, k = k.previous;
29338 } while (j !== k.next);
29340 // Success! Insert the new circle c between a and b.
29341 c.previous = a, c.next = b, a.next = b.previous = b = c;
29343 // Update the weighted centroid.
29344 oa += ca = c._.r * c._.r;
29348 // Compute the new closest circle pair to the centroid.
29349 aa = distance2(a, cx = ox / oa, cy = oy / oa);
29350 while ((c = c.next) !== b) {
29351 if ((ca = distance2(c, cx, cy)) < aa) {
29358 // Compute the enclosing circle of the front chain.
29359 a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);
29361 // Translate the circles to put the enclosing circle around the origin.
29362 for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
29367 var siblings = function(circles) {
29368 packEnclose(circles);
29372 function optional(f) {
29373 return f == null ? null : required(f);
29376 function required(f) {
29377 if (typeof f !== "function") throw new Error;
29381 function constantZero() {
29385 var constant$8 = function(x) {
29386 return function() {
29391 function defaultRadius$1(d) {
29392 return Math.sqrt(d.value);
29395 var index$5 = function() {
29399 padding = constantZero;
29401 function pack(root) {
29402 root.x = dx / 2, root.y = dy / 2;
29404 root.eachBefore(radiusLeaf(radius))
29405 .eachAfter(packChildren(padding, 0.5))
29406 .eachBefore(translateChild(1));
29408 root.eachBefore(radiusLeaf(defaultRadius$1))
29409 .eachAfter(packChildren(constantZero, 1))
29410 .eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))
29411 .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
29416 pack.radius = function(x) {
29417 return arguments.length ? (radius = optional(x), pack) : radius;
29420 pack.size = function(x) {
29421 return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
29424 pack.padding = function(x) {
29425 return arguments.length ? (padding = typeof x === "function" ? x : constant$8(+x), pack) : padding;
29431 function radiusLeaf(radius) {
29432 return function(node) {
29433 if (!node.children) {
29434 node.r = Math.max(0, +radius(node) || 0);
29439 function packChildren(padding, k) {
29440 return function(node) {
29441 if (children = node.children) {
29444 n = children.length,
29445 r = padding(node) * k || 0,
29448 if (r) for (i = 0; i < n; ++i) children[i].r += r;
29449 e = packEnclose(children);
29450 if (r) for (i = 0; i < n; ++i) children[i].r -= r;
29456 function translateChild(k) {
29457 return function(node) {
29458 var parent = node.parent;
29461 node.x = parent.x + k * node.x;
29462 node.y = parent.y + k * node.y;
29467 var roundNode = function(node) {
29468 node.x0 = Math.round(node.x0);
29469 node.y0 = Math.round(node.y0);
29470 node.x1 = Math.round(node.x1);
29471 node.y1 = Math.round(node.y1);
29474 var treemapDice = function(parent, x0, y0, x1, y1) {
29475 var nodes = parent.children,
29479 k = parent.value && (x1 - x0) / parent.value;
29482 node = nodes[i], node.y0 = y0, node.y1 = y1;
29483 node.x0 = x0, node.x1 = x0 += node.value * k;
29487 var partition = function() {
29493 function partition(root) {
29494 var n = root.height + 1;
29499 root.eachBefore(positionNode(dy, n));
29500 if (round) root.eachBefore(roundNode);
29504 function positionNode(dy, n) {
29505 return function(node) {
29506 if (node.children) {
29507 treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
29511 x1 = node.x1 - padding,
29512 y1 = node.y1 - padding;
29513 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29514 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29522 partition.round = function(x) {
29523 return arguments.length ? (round = !!x, partition) : round;
29526 partition.size = function(x) {
29527 return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
29530 partition.padding = function(x) {
29531 return arguments.length ? (padding = +x, partition) : padding;
29537 var keyPrefix$1 = "$";
29538 var preroot = {depth: -1};
29539 var ambiguous = {};
29541 function defaultId(d) {
29545 function defaultParentId(d) {
29549 var stratify = function() {
29550 var id = defaultId,
29551 parentId = defaultParentId;
29553 function stratify(data) {
29560 nodes = new Array(n),
29565 for (i = 0; i < n; ++i) {
29566 d = data[i], node = nodes[i] = new Node(d);
29567 if ((nodeId = id(d, i, data)) != null && (nodeId += "")) {
29568 nodeKey = keyPrefix$1 + (node.id = nodeId);
29569 nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node;
29573 for (i = 0; i < n; ++i) {
29574 node = nodes[i], nodeId = parentId(data[i], i, data);
29575 if (nodeId == null || !(nodeId += "")) {
29576 if (root) throw new Error("multiple roots");
29579 parent = nodeByKey[keyPrefix$1 + nodeId];
29580 if (!parent) throw new Error("missing: " + nodeId);
29581 if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
29582 if (parent.children) parent.children.push(node);
29583 else parent.children = [node];
29584 node.parent = parent;
29588 if (!root) throw new Error("no root");
29589 root.parent = preroot;
29590 root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
29591 root.parent = null;
29592 if (n > 0) throw new Error("cycle");
29597 stratify.id = function(x) {
29598 return arguments.length ? (id = required(x), stratify) : id;
29601 stratify.parentId = function(x) {
29602 return arguments.length ? (parentId = required(x), stratify) : parentId;
29608 function defaultSeparation$1(a, b) {
29609 return a.parent === b.parent ? 1 : 2;
29612 // function radialSeparation(a, b) {
29613 // return (a.parent === b.parent ? 1 : 2) / a.depth;
29616 // This function is used to traverse the left contour of a subtree (or
29617 // subforest). It returns the successor of v on this contour. This successor is
29618 // either given by the leftmost child of v or by the thread of v. The function
29619 // returns null if and only if v is on the highest level of its subtree.
29620 function nextLeft(v) {
29621 var children = v.children;
29622 return children ? children[0] : v.t;
29625 // This function works analogously to nextLeft.
29626 function nextRight(v) {
29627 var children = v.children;
29628 return children ? children[children.length - 1] : v.t;
29631 // Shifts the current subtree rooted at w+. This is done by increasing
29632 // prelim(w+) and mod(w+) by shift.
29633 function moveSubtree(wm, wp, shift) {
29634 var change = shift / (wp.i - wm.i);
29642 // All other shifts, applied to the smaller subtrees between w- and w+, are
29643 // performed by this function. To prepare the shifts, we have to adjust
29644 // change(w+), shift(w+), and change(w-).
29645 function executeShifts(v) {
29648 children = v.children,
29649 i = children.length,
29655 shift += w.s + (change += w.c);
29659 // If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
29660 // returns the specified (default) ancestor.
29661 function nextAncestor(vim, v, ancestor) {
29662 return vim.a.parent === v.parent ? vim.a : ancestor;
29665 function TreeNode(node, i) {
29667 this.parent = null;
29668 this.children = null;
29669 this.A = null; // default ancestor
29670 this.a = this; // ancestor
29671 this.z = 0; // prelim
29673 this.c = 0; // change
29674 this.s = 0; // shift
29675 this.t = null; // thread
29676 this.i = i; // number
29679 TreeNode.prototype = Object.create(Node.prototype);
29681 function treeRoot(root) {
29682 var tree = new TreeNode(root, 0),
29690 while (node = nodes.pop()) {
29691 if (children = node._.children) {
29692 node.children = new Array(n = children.length);
29693 for (i = n - 1; i >= 0; --i) {
29694 nodes.push(child = node.children[i] = new TreeNode(children[i], i));
29695 child.parent = node;
29700 (tree.parent = new TreeNode(null, 0)).children = [tree];
29704 // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
29705 var tree = function() {
29706 var separation = defaultSeparation$1,
29711 function tree(root) {
29712 var t = treeRoot(root);
29714 // Compute the layout using Buchheim et al.’s algorithm.
29715 t.eachAfter(firstWalk), t.parent.m = -t.z;
29716 t.eachBefore(secondWalk);
29718 // If a fixed node size is specified, scale x and y.
29719 if (nodeSize) root.eachBefore(sizeNode);
29721 // If a fixed tree size is specified, scale x and y based on the extent.
29722 // Compute the left-most, right-most, and depth-most nodes for extents.
29727 root.eachBefore(function(node) {
29728 if (node.x < left.x) left = node;
29729 if (node.x > right.x) right = node;
29730 if (node.depth > bottom.depth) bottom = node;
29732 var s = left === right ? 1 : separation(left, right) / 2,
29734 kx = dx / (right.x + s + tx),
29735 ky = dy / (bottom.depth || 1);
29736 root.eachBefore(function(node) {
29737 node.x = (node.x + tx) * kx;
29738 node.y = node.depth * ky;
29745 // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
29746 // applied recursively to the children of v, as well as the function
29747 // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
29748 // node v is placed to the midpoint of its outermost children.
29749 function firstWalk(v) {
29750 var children = v.children,
29751 siblings = v.parent.children,
29752 w = v.i ? siblings[v.i - 1] : null;
29755 var midpoint = (children[0].z + children[children.length - 1].z) / 2;
29757 v.z = w.z + separation(v._, w._);
29758 v.m = v.z - midpoint;
29763 v.z = w.z + separation(v._, w._);
29765 v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
29768 // Computes all real x-coordinates by summing up the modifiers recursively.
29769 function secondWalk(v) {
29770 v._.x = v.z + v.parent.m;
29774 // The core of the algorithm. Here, a new subtree is combined with the
29775 // previous subtrees. Threads are used to traverse the inside and outside
29776 // contours of the left and right subtree up to the highest common level. The
29777 // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
29778 // superscript o means outside and i means inside, the subscript - means left
29779 // subtree and + means right subtree. For summing up the modifiers along the
29780 // contour, we use respective variables si+, si-, so-, and so+. Whenever two
29781 // nodes of the inside contours conflict, we compute the left one of the
29782 // greatest uncommon ancestors using the function ANCESTOR and call MOVE
29783 // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
29784 // Finally, we add a new thread (if necessary).
29785 function apportion(v, w, ancestor) {
29790 vom = vip.parent.children[0],
29796 while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
29797 vom = nextLeft(vom);
29798 vop = nextRight(vop);
29800 shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
29802 moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
29811 if (vim && !nextRight(vop)) {
29813 vop.m += sim - sop;
29815 if (vip && !nextLeft(vom)) {
29817 vom.m += sip - som;
29824 function sizeNode(node) {
29826 node.y = node.depth * dy;
29829 tree.separation = function(x) {
29830 return arguments.length ? (separation = x, tree) : separation;
29833 tree.size = function(x) {
29834 return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
29837 tree.nodeSize = function(x) {
29838 return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
29844 var treemapSlice = function(parent, x0, y0, x1, y1) {
29845 var nodes = parent.children,
29849 k = parent.value && (y1 - y0) / parent.value;
29852 node = nodes[i], node.x0 = x0, node.x1 = x1;
29853 node.y0 = y0, node.y1 = y0 += node.value * k;
29857 var phi = (1 + Math.sqrt(5)) / 2;
29859 function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
29861 nodes = parent.children,
29868 value = parent.value,
29878 dx = x1 - x0, dy = y1 - y0;
29880 // Find the next non-empty node.
29881 do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
29882 minValue = maxValue = sumValue;
29883 alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
29884 beta = sumValue * sumValue * alpha;
29885 minRatio = Math.max(maxValue / beta, beta / minValue);
29887 // Keep adding nodes while the aspect ratio maintains or improves.
29888 for (; i1 < n; ++i1) {
29889 sumValue += nodeValue = nodes[i1].value;
29890 if (nodeValue < minValue) minValue = nodeValue;
29891 if (nodeValue > maxValue) maxValue = nodeValue;
29892 beta = sumValue * sumValue * alpha;
29893 newRatio = Math.max(maxValue / beta, beta / minValue);
29894 if (newRatio > minRatio) { sumValue -= nodeValue; break; }
29895 minRatio = newRatio;
29898 // Position and record the row orientation.
29899 rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
29900 if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
29901 else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
29902 value -= sumValue, i0 = i1;
29908 var squarify = ((function custom(ratio) {
29910 function squarify(parent, x0, y0, x1, y1) {
29911 squarifyRatio(ratio, parent, x0, y0, x1, y1);
29914 squarify.ratio = function(x) {
29915 return custom((x = +x) > 1 ? x : 1);
29921 var index$6 = function() {
29922 var tile = squarify,
29926 paddingStack = [0],
29927 paddingInner = constantZero,
29928 paddingTop = constantZero,
29929 paddingRight = constantZero,
29930 paddingBottom = constantZero,
29931 paddingLeft = constantZero;
29933 function treemap(root) {
29938 root.eachBefore(positionNode);
29939 paddingStack = [0];
29940 if (round) root.eachBefore(roundNode);
29944 function positionNode(node) {
29945 var p = paddingStack[node.depth],
29950 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29951 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29956 if (node.children) {
29957 p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
29958 x0 += paddingLeft(node) - p;
29959 y0 += paddingTop(node) - p;
29960 x1 -= paddingRight(node) - p;
29961 y1 -= paddingBottom(node) - p;
29962 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29963 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29964 tile(node, x0, y0, x1, y1);
29968 treemap.round = function(x) {
29969 return arguments.length ? (round = !!x, treemap) : round;
29972 treemap.size = function(x) {
29973 return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
29976 treemap.tile = function(x) {
29977 return arguments.length ? (tile = required(x), treemap) : tile;
29980 treemap.padding = function(x) {
29981 return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
29984 treemap.paddingInner = function(x) {
29985 return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$8(+x), treemap) : paddingInner;
29988 treemap.paddingOuter = function(x) {
29989 return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
29992 treemap.paddingTop = function(x) {
29993 return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$8(+x), treemap) : paddingTop;
29996 treemap.paddingRight = function(x) {
29997 return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$8(+x), treemap) : paddingRight;
30000 treemap.paddingBottom = function(x) {
30001 return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$8(+x), treemap) : paddingBottom;
30004 treemap.paddingLeft = function(x) {
30005 return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$8(+x), treemap) : paddingLeft;
30011 var binary = function(parent, x0, y0, x1, y1) {
30012 var nodes = parent.children,
30013 i, n = nodes.length,
30014 sum, sums = new Array(n + 1);
30016 for (sums[0] = sum = i = 0; i < n; ++i) {
30017 sums[i + 1] = sum += nodes[i].value;
30020 partition(0, n, parent.value, x0, y0, x1, y1);
30022 function partition(i, j, value, x0, y0, x1, y1) {
30024 var node = nodes[i];
30025 node.x0 = x0, node.y0 = y0;
30026 node.x1 = x1, node.y1 = y1;
30030 var valueOffset = sums[i],
30031 valueTarget = (value / 2) + valueOffset,
30036 var mid = k + hi >>> 1;
30037 if (sums[mid] < valueTarget) k = mid + 1;
30041 if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k;
30043 var valueLeft = sums[k] - valueOffset,
30044 valueRight = value - valueLeft;
30046 if ((x1 - x0) > (y1 - y0)) {
30047 var xk = (x0 * valueRight + x1 * valueLeft) / value;
30048 partition(i, k, valueLeft, x0, y0, xk, y1);
30049 partition(k, j, valueRight, xk, y0, x1, y1);
30051 var yk = (y0 * valueRight + y1 * valueLeft) / value;
30052 partition(i, k, valueLeft, x0, y0, x1, yk);
30053 partition(k, j, valueRight, x0, yk, x1, y1);
30058 var sliceDice = function(parent, x0, y0, x1, y1) {
30059 (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
30062 var resquarify = ((function custom(ratio) {
30064 function resquarify(parent, x0, y0, x1, y1) {
30065 if ((rows = parent._squarify) && (rows.ratio === ratio)) {
30073 value = parent.value;
30076 row = rows[j], nodes = row.children;
30077 for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
30078 if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
30079 else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
30080 value -= row.value;
30083 parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
30084 rows.ratio = ratio;
30088 resquarify.ratio = function(x) {
30089 return custom((x = +x) > 1 ? x : 1);
30095 var d3polygonArea = function(polygon) {
30097 n = polygon.length,
30099 b = polygon[n - 1],
30105 area += a[1] * b[0] - a[0] * b[1];
30111 var d3polygonCentroid = function(polygon) {
30113 n = polygon.length,
30117 b = polygon[n - 1],
30124 k += c = a[0] * b[1] - b[0] * a[1];
30125 x += (a[0] + b[0]) * c;
30126 y += (a[1] + b[1]) * c;
30129 return k *= 3, [x / k, y / k];
30132 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
30133 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
30134 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
30135 // negative if clockwise, and zero if the points are collinear.
30136 var cross$1 = function(a, b, c) {
30137 return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
30140 function lexicographicOrder(a, b) {
30141 return a[0] - b[0] || a[1] - b[1];
30144 // Computes the upper convex hull per the monotone chain algorithm.
30145 // Assumes points.length >= 3, is sorted by x, unique in y.
30146 // Returns an array of indices into points in left-to-right order.
30147 function computeUpperHullIndexes(points) {
30148 var n = points.length,
30152 for (var i = 2; i < n; ++i) {
30153 while (size > 1 && cross$1(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size;
30154 indexes[size++] = i;
30157 return indexes.slice(0, size); // remove popped points
30160 var d3polygonHull = function(points) {
30161 if ((n = points.length) < 3) return null;
30165 sortedPoints = new Array(n),
30166 flippedPoints = new Array(n);
30168 for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i];
30169 sortedPoints.sort(lexicographicOrder);
30170 for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
30172 var upperIndexes = computeUpperHullIndexes(sortedPoints),
30173 lowerIndexes = computeUpperHullIndexes(flippedPoints);
30175 // Construct the hull polygon, removing possible duplicate endpoints.
30176 var skipLeft = lowerIndexes[0] === upperIndexes[0],
30177 skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
30180 // Add upper hull in right-to-l order.
30181 // Then add lower hull in left-to-right order.
30182 for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]);
30183 for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
30188 var contains$1 = function(polygon, point) {
30189 var n = polygon.length,
30190 p = polygon[n - 1],
30191 x = point[0], y = point[1],
30192 x0 = p[0], y0 = p[1],
30196 for (var i = 0; i < n; ++i) {
30197 p = polygon[i], x1 = p[0], y1 = p[1];
30198 if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside;
30205 var length$1 = function(polygon) {
30207 n = polygon.length,
30208 b = polygon[n - 1],
30223 perimeter += Math.sqrt(xa * xa + ya * ya);
30229 var slice$3 = [].slice;
30233 function Queue(size) {
30234 if (!(size >= 1)) throw new Error;
30237 this._error = null;
30243 this._start = 0; // inside a synchronous task callback?
30246 Queue.prototype = queue.prototype = {
30247 constructor: Queue,
30248 defer: function(callback) {
30249 if (typeof callback !== "function" || this._call) throw new Error;
30250 if (this._error != null) return this;
30251 var t = slice$3.call(arguments, 1);
30253 ++this._waiting, this._tasks.push(t);
30257 abort: function() {
30258 if (this._error == null) abort(this, new Error("abort"));
30261 await: function(callback) {
30262 if (typeof callback !== "function" || this._call) throw new Error;
30263 this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
30267 awaitAll: function(callback) {
30268 if (typeof callback !== "function" || this._call) throw new Error;
30269 this._call = callback;
30275 function poke$1(q) {
30277 try { start$1(q); } // let the current task complete
30279 if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously
30280 else if (!q._data) throw e; // await callback errored synchronously
30285 function start$1(q) {
30286 while (q._start = q._waiting && q._active < q._size) {
30287 var i = q._ended + q._active,
30292 --q._waiting, ++q._active;
30293 t = c.apply(null, t);
30294 if (!q._tasks[i]) continue; // task finished synchronously
30295 q._tasks[i] = t || noabort;
30299 function end(q, i) {
30300 return function(e, r) {
30301 if (!q._tasks[i]) return; // ignore multiple callbacks
30302 --q._active, ++q._ended;
30303 q._tasks[i] = null;
30304 if (q._error != null) return; // ignore secondary errors
30309 if (q._waiting) poke$1(q);
30310 else maybeNotify(q);
30315 function abort(q, e) {
30316 var i = q._tasks.length, t;
30317 q._error = e; // ignore active callbacks
30318 q._data = undefined; // allow gc
30319 q._waiting = NaN; // prevent starting
30322 if (t = q._tasks[i]) {
30323 q._tasks[i] = null;
30326 catch (e) { /* ignore */ }
30331 q._active = NaN; // allow notification
30335 function maybeNotify(q) {
30336 if (!q._active && q._call) {
30338 q._data = undefined; // allow gc
30339 q._call(q._error, d);
30343 function queue(concurrency) {
30344 return new Queue(arguments.length ? +concurrency : Infinity);
30347 var uniform = function(min, max) {
30348 min = min == null ? 0 : +min;
30349 max = max == null ? 1 : +max;
30350 if (arguments.length === 1) max = min, min = 0;
30352 return function() {
30353 return Math.random() * max + min;
30357 var normal = function(mu, sigma) {
30359 mu = mu == null ? 0 : +mu;
30360 sigma = sigma == null ? 1 : +sigma;
30361 return function() {
30364 // If available, use the second previously-generated uniform random.
30365 if (x != null) y = x, x = null;
30367 // Otherwise, generate a new x and y.
30369 x = Math.random() * 2 - 1;
30370 y = Math.random() * 2 - 1;
30372 } while (!r || r > 1);
30374 return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r);
30378 var logNormal = function() {
30379 var randomNormal = normal.apply(this, arguments);
30380 return function() {
30381 return Math.exp(randomNormal());
30385 var irwinHall = function(n) {
30386 return function() {
30387 for (var sum = 0, i = 0; i < n; ++i) sum += Math.random();
30392 var bates = function(n) {
30393 var randomIrwinHall = irwinHall(n);
30394 return function() {
30395 return randomIrwinHall() / n;
30399 var exponential$1 = function(lambda) {
30400 return function() {
30401 return -Math.log(1 - Math.random()) / lambda;
30405 var request = function(url, callback) {
30407 event = dispatch("beforesend", "progress", "load", "error"),
30410 xhr = new XMLHttpRequest,
30417 // If IE does not support CORS, use XDomainRequest.
30418 if (typeof XDomainRequest !== "undefined"
30419 && !("withCredentials" in xhr)
30420 && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest;
30423 ? xhr.onload = xhr.onerror = xhr.ontimeout = respond
30424 : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); };
30426 function respond(o) {
30427 var status = xhr.status, result;
30428 if (!status && hasResponse(xhr)
30429 || status >= 200 && status < 300
30430 || status === 304) {
30433 result = response.call(request, xhr);
30435 event.call("error", request, e);
30441 event.call("load", request, result);
30443 event.call("error", request, o);
30447 xhr.onprogress = function(e) {
30448 event.call("progress", request, e);
30452 header: function(name, value) {
30453 name = (name + "").toLowerCase();
30454 if (arguments.length < 2) return headers.get(name);
30455 if (value == null) headers.remove(name);
30456 else headers.set(name, value + "");
30460 // If mimeType is non-null and no Accept header is set, a default is used.
30461 mimeType: function(value) {
30462 if (!arguments.length) return mimeType;
30463 mimeType = value == null ? null : value + "";
30467 // Specifies what type the response value should take;
30468 // for instance, arraybuffer, blob, document, or text.
30469 responseType: function(value) {
30470 if (!arguments.length) return responseType;
30471 responseType = value;
30475 timeout: function(value) {
30476 if (!arguments.length) return timeout;
30481 user: function(value) {
30482 return arguments.length < 1 ? user : (user = value == null ? null : value + "", request);
30485 password: function(value) {
30486 return arguments.length < 1 ? password : (password = value == null ? null : value + "", request);
30489 // Specify how to convert the response content to a specific type;
30490 // changes the callback value on "load" events.
30491 response: function(value) {
30496 // Alias for send("GET", …).
30497 get: function(data, callback) {
30498 return request.send("GET", data, callback);
30501 // Alias for send("POST", …).
30502 post: function(data, callback) {
30503 return request.send("POST", data, callback);
30506 // If callback is non-null, it will be used for error and load events.
30507 send: function(method, data, callback) {
30508 xhr.open(method, url, true, user, password);
30509 if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*");
30510 if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); });
30511 if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType);
30512 if (responseType != null) xhr.responseType = responseType;
30513 if (timeout > 0) xhr.timeout = timeout;
30514 if (callback == null && typeof data === "function") callback = data, data = null;
30515 if (callback != null && callback.length === 1) callback = fixCallback(callback);
30516 if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); });
30517 event.call("beforesend", request, xhr);
30518 xhr.send(data == null ? null : data);
30522 abort: function() {
30528 var value = event.on.apply(event, arguments);
30529 return value === event ? request : value;
30533 if (callback != null) {
30534 if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
30535 return request.get(callback);
30541 function fixCallback(callback) {
30542 return function(error, xhr) {
30543 callback(error == null ? xhr : null);
30547 function hasResponse(xhr) {
30548 var type = xhr.responseType;
30549 return type && type !== "text"
30550 ? xhr.response // null on error
30551 : xhr.responseText; // "" on error
30554 var type$3 = function(defaultMimeType, response) {
30555 return function(url, callback) {
30556 var r = request(url).mimeType(defaultMimeType).response(response);
30557 if (callback != null) {
30558 if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
30559 return r.get(callback);
30565 var html = type$3("text/html", function(xhr) {
30566 return document.createRange().createContextualFragment(xhr.responseText);
30569 var json = type$3("application/json", function(xhr) {
30570 return JSON.parse(xhr.responseText);
30573 var text = type$3("text/plain", function(xhr) {
30574 return xhr.responseText;
30577 var xml = type$3("application/xml", function(xhr) {
30578 var xml = xhr.responseXML;
30579 if (!xml) throw new Error("parse error");
30583 var dsv$1 = function(defaultMimeType, parse) {
30584 return function(url, row, callback) {
30585 if (arguments.length < 3) callback = row, row = null;
30586 var r = request(url).mimeType(defaultMimeType);
30587 r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; };
30589 return callback ? r.get(callback) : r;
30593 function responseOf(parse, row) {
30594 return function(request$$1) {
30595 return parse(request$$1.responseText, row);
30599 var csv$1 = dsv$1("text/csv", csvParse);
30601 var tsv$1 = dsv$1("text/tab-separated-values", tsvParse);
30603 var array$2 = Array.prototype;
30605 var map$3 = array$2.map;
30606 var slice$4 = array$2.slice;
30608 var implicit = {name: "implicit"};
30610 function ordinal(range) {
30611 var index = map$1(),
30613 unknown = implicit;
30615 range = range == null ? [] : slice$4.call(range);
30617 function scale(d) {
30618 var key = d + "", i = index.get(key);
30620 if (unknown !== implicit) return unknown;
30621 index.set(key, i = domain.push(d));
30623 return range[(i - 1) % range.length];
30626 scale.domain = function(_) {
30627 if (!arguments.length) return domain.slice();
30628 domain = [], index = map$1();
30629 var i = -1, n = _.length, d, key;
30630 while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
30634 scale.range = function(_) {
30635 return arguments.length ? (range = slice$4.call(_), scale) : range.slice();
30638 scale.unknown = function(_) {
30639 return arguments.length ? (unknown = _, scale) : unknown;
30642 scale.copy = function() {
30653 var scale = ordinal().unknown(undefined),
30654 domain = scale.domain,
30655 ordinalRange = scale.range,
30664 delete scale.unknown;
30666 function rescale() {
30667 var n = domain().length,
30668 reverse = range$$1[1] < range$$1[0],
30669 start = range$$1[reverse - 0],
30670 stop = range$$1[1 - reverse];
30671 step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
30672 if (round) step = Math.floor(step);
30673 start += (stop - start - step * (n - paddingInner)) * align;
30674 bandwidth = step * (1 - paddingInner);
30675 if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
30676 var values = sequence(n).map(function(i) { return start + step * i; });
30677 return ordinalRange(reverse ? values.reverse() : values);
30680 scale.domain = function(_) {
30681 return arguments.length ? (domain(_), rescale()) : domain();
30684 scale.range = function(_) {
30685 return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice();
30688 scale.rangeRound = function(_) {
30689 return range$$1 = [+_[0], +_[1]], round = true, rescale();
30692 scale.bandwidth = function() {
30696 scale.step = function() {
30700 scale.round = function(_) {
30701 return arguments.length ? (round = !!_, rescale()) : round;
30704 scale.padding = function(_) {
30705 return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
30708 scale.paddingInner = function(_) {
30709 return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
30712 scale.paddingOuter = function(_) {
30713 return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter;
30716 scale.align = function(_) {
30717 return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
30720 scale.copy = function() {
30725 .paddingInner(paddingInner)
30726 .paddingOuter(paddingOuter)
30733 function pointish(scale) {
30734 var copy = scale.copy;
30736 scale.padding = scale.paddingOuter;
30737 delete scale.paddingInner;
30738 delete scale.paddingOuter;
30740 scale.copy = function() {
30741 return pointish(copy());
30747 function point$1() {
30748 return pointish(band().paddingInner(1));
30751 var constant$9 = function(x) {
30752 return function() {
30757 var number$1 = function(x) {
30763 function deinterpolateLinear(a, b) {
30764 return (b -= (a = +a))
30765 ? function(x) { return (x - a) / b; }
30769 function deinterpolateClamp(deinterpolate) {
30770 return function(a, b) {
30771 var d = deinterpolate(a = +a, b = +b);
30772 return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
30776 function reinterpolateClamp(reinterpolate) {
30777 return function(a, b) {
30778 var r = reinterpolate(a = +a, b = +b);
30779 return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
30783 function bimap(domain, range$$1, deinterpolate, reinterpolate) {
30784 var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1];
30785 if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
30786 else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
30787 return function(x) { return r0(d0(x)); };
30790 function polymap(domain, range$$1, deinterpolate, reinterpolate) {
30791 var j = Math.min(domain.length, range$$1.length) - 1,
30796 // Reverse descending domains.
30797 if (domain[j] < domain[0]) {
30798 domain = domain.slice().reverse();
30799 range$$1 = range$$1.slice().reverse();
30803 d[i] = deinterpolate(domain[i], domain[i + 1]);
30804 r[i] = reinterpolate(range$$1[i], range$$1[i + 1]);
30807 return function(x) {
30808 var i = bisectRight(domain, x, 1, j) - 1;
30809 return r[i](d[i](x));
30813 function copy(source, target) {
30815 .domain(source.domain())
30816 .range(source.range())
30817 .interpolate(source.interpolate())
30818 .clamp(source.clamp());
30821 // deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
30822 // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
30823 function continuous(deinterpolate, reinterpolate) {
30826 interpolate$$1 = interpolateValue,
30832 function rescale() {
30833 piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap;
30834 output = input = null;
30838 function scale(x) {
30839 return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x);
30842 scale.invert = function(y) {
30843 return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y);
30846 scale.domain = function(_) {
30847 return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice();
30850 scale.range = function(_) {
30851 return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice();
30854 scale.rangeRound = function(_) {
30855 return range$$1 = slice$4.call(_), interpolate$$1 = interpolateRound, rescale();
30858 scale.clamp = function(_) {
30859 return arguments.length ? (clamp = !!_, rescale()) : clamp;
30862 scale.interpolate = function(_) {
30863 return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1;
30869 var tickFormat = function(domain, count, specifier) {
30870 var start = domain[0],
30871 stop = domain[domain.length - 1],
30872 step = tickStep(start, stop, count == null ? 10 : count),
30874 specifier = formatSpecifier(specifier == null ? ",f" : specifier);
30875 switch (specifier.type) {
30877 var value = Math.max(Math.abs(start), Math.abs(stop));
30878 if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
30879 return formatPrefix(specifier, value);
30886 if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
30891 if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
30895 return format(specifier);
30898 function linearish(scale) {
30899 var domain = scale.domain;
30901 scale.ticks = function(count) {
30903 return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
30906 scale.tickFormat = function(count, specifier) {
30907 return tickFormat(domain(), count, specifier);
30910 scale.nice = function(count) {
30913 n = count == null ? 10 : count,
30916 step = tickStep(start, stop, n);
30919 step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n);
30920 d[0] = Math.floor(start / step) * step;
30921 d[i] = Math.ceil(stop / step) * step;
30931 function linear$2() {
30932 var scale = continuous(deinterpolateLinear, reinterpolate);
30934 scale.copy = function() {
30935 return copy(scale, linear$2());
30938 return linearish(scale);
30941 function identity$6() {
30942 var domain = [0, 1];
30944 function scale(x) {
30948 scale.invert = scale;
30950 scale.domain = scale.range = function(_) {
30951 return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice();
30954 scale.copy = function() {
30955 return identity$6().domain(domain);
30958 return linearish(scale);
30961 var nice = function(domain, interval) {
30962 domain = domain.slice();
30965 i1 = domain.length - 1,
30971 t = i0, i0 = i1, i1 = t;
30972 t = x0, x0 = x1, x1 = t;
30975 domain[i0] = interval.floor(x0);
30976 domain[i1] = interval.ceil(x1);
30980 function deinterpolate(a, b) {
30981 return (b = Math.log(b / a))
30982 ? function(x) { return Math.log(x / a) / b; }
30986 function reinterpolate$1(a, b) {
30988 ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
30989 : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
30992 function pow10(x) {
30993 return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
30996 function powp(base) {
30997 return base === 10 ? pow10
30998 : base === Math.E ? Math.exp
30999 : function(x) { return Math.pow(base, x); };
31002 function logp(base) {
31003 return base === Math.E ? Math.log
31004 : base === 10 && Math.log10
31005 || base === 2 && Math.log2
31006 || (base = Math.log(base), function(x) { return Math.log(x) / base; });
31009 function reflect(f) {
31010 return function(x) {
31016 var scale = continuous(deinterpolate, reinterpolate$1).domain([1, 10]),
31017 domain = scale.domain,
31022 function rescale() {
31023 logs = logp(base), pows = powp(base);
31024 if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
31028 scale.base = function(_) {
31029 return arguments.length ? (base = +_, rescale()) : base;
31032 scale.domain = function(_) {
31033 return arguments.length ? (domain(_), rescale()) : domain();
31036 scale.ticks = function(count) {
31039 v = d[d.length - 1],
31042 if (r = v < u) i = u, u = v, v = i;
31049 n = count == null ? 10 : +count,
31052 if (!(base % 1) && j - i < n) {
31053 i = Math.round(i) - 1, j = Math.round(j) + 1;
31054 if (u > 0) for (; i < j; ++i) {
31055 for (k = 1, p = pows(i); k < base; ++k) {
31057 if (t < u) continue;
31061 } else for (; i < j; ++i) {
31062 for (k = base - 1, p = pows(i); k >= 1; --k) {
31064 if (t < u) continue;
31070 z = ticks(i, j, Math.min(j - i, n)).map(pows);
31073 return r ? z.reverse() : z;
31076 scale.tickFormat = function(count, specifier) {
31077 if (specifier == null) specifier = base === 10 ? ".0e" : ",";
31078 if (typeof specifier !== "function") specifier = format(specifier);
31079 if (count === Infinity) return specifier;
31080 if (count == null) count = 10;
31081 var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
31082 return function(d) {
31083 var i = d / pows(Math.round(logs(d)));
31084 if (i * base < base - 0.5) i *= base;
31085 return i <= k ? specifier(d) : "";
31089 scale.nice = function() {
31090 return domain(nice(domain(), {
31091 floor: function(x) { return pows(Math.floor(logs(x))); },
31092 ceil: function(x) { return pows(Math.ceil(logs(x))); }
31096 scale.copy = function() {
31097 return copy(scale, log$1().base(base));
31103 function raise$1(x, exponent) {
31104 return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
31109 scale = continuous(deinterpolate, reinterpolate),
31110 domain = scale.domain;
31112 function deinterpolate(a, b) {
31113 return (b = raise$1(b, exponent) - (a = raise$1(a, exponent)))
31114 ? function(x) { return (raise$1(x, exponent) - a) / b; }
31118 function reinterpolate(a, b) {
31119 b = raise$1(b, exponent) - (a = raise$1(a, exponent));
31120 return function(t) { return raise$1(a + b * t, 1 / exponent); };
31123 scale.exponent = function(_) {
31124 return arguments.length ? (exponent = +_, domain(domain())) : exponent;
31127 scale.copy = function() {
31128 return copy(scale, pow$1().exponent(exponent));
31131 return linearish(scale);
31134 function sqrt$1() {
31135 return pow$1().exponent(0.5);
31138 function quantile$$1() {
31143 function rescale() {
31144 var i = 0, n = Math.max(1, range$$1.length);
31145 thresholds = new Array(n - 1);
31146 while (++i < n) thresholds[i - 1] = threshold(domain, i / n);
31150 function scale(x) {
31151 if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)];
31154 scale.invertExtent = function(y) {
31155 var i = range$$1.indexOf(y);
31156 return i < 0 ? [NaN, NaN] : [
31157 i > 0 ? thresholds[i - 1] : domain[0],
31158 i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
31162 scale.domain = function(_) {
31163 if (!arguments.length) return domain.slice();
31165 for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
31166 domain.sort(ascending);
31170 scale.range = function(_) {
31171 return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice();
31174 scale.quantiles = function() {
31175 return thresholds.slice();
31178 scale.copy = function() {
31179 return quantile$$1()
31187 function quantize$1() {
31194 function scale(x) {
31195 if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
31198 function rescale() {
31200 domain = new Array(n);
31201 while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
31205 scale.domain = function(_) {
31206 return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
31209 scale.range = function(_) {
31210 return arguments.length ? (n = (range$$1 = slice$4.call(_)).length - 1, rescale()) : range$$1.slice();
31213 scale.invertExtent = function(y) {
31214 var i = range$$1.indexOf(y);
31215 return i < 0 ? [NaN, NaN]
31216 : i < 1 ? [x0, domain[0]]
31217 : i >= n ? [domain[n - 1], x1]
31218 : [domain[i - 1], domain[i]];
31221 scale.copy = function() {
31222 return quantize$1()
31227 return linearish(scale);
31230 function threshold$1() {
31231 var domain = [0.5],
31235 function scale(x) {
31236 if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
31239 scale.domain = function(_) {
31240 return arguments.length ? (domain = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice();
31243 scale.range = function(_) {
31244 return arguments.length ? (range$$1 = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice();
31247 scale.invertExtent = function(y) {
31248 var i = range$$1.indexOf(y);
31249 return [domain[i - 1], domain[i]];
31252 scale.copy = function() {
31253 return threshold$1()
31261 var t0$1 = new Date;
31262 var t1$1 = new Date;
31264 function newInterval(floori, offseti, count, field) {
31266 function interval(date) {
31267 return floori(date = new Date(+date)), date;
31270 interval.floor = interval;
31272 interval.ceil = function(date) {
31273 return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
31276 interval.round = function(date) {
31277 var d0 = interval(date),
31278 d1 = interval.ceil(date);
31279 return date - d0 < d1 - date ? d0 : d1;
31282 interval.offset = function(date, step) {
31283 return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
31286 interval.range = function(start, stop, step) {
31288 start = interval.ceil(start);
31289 step = step == null ? 1 : Math.floor(step);
31290 if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
31291 do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop)
31295 interval.filter = function(test) {
31296 return newInterval(function(date) {
31297 if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
31298 }, function(date, step) {
31299 if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty
31304 interval.count = function(start, end) {
31305 t0$1.setTime(+start), t1$1.setTime(+end);
31306 floori(t0$1), floori(t1$1);
31307 return Math.floor(count(t0$1, t1$1));
31310 interval.every = function(step) {
31311 step = Math.floor(step);
31312 return !isFinite(step) || !(step > 0) ? null
31313 : !(step > 1) ? interval
31314 : interval.filter(field
31315 ? function(d) { return field(d) % step === 0; }
31316 : function(d) { return interval.count(0, d) % step === 0; });
31323 var millisecond = newInterval(function() {
31325 }, function(date, step) {
31326 date.setTime(+date + step);
31327 }, function(start, end) {
31328 return end - start;
31331 // An optimized implementation for this simple case.
31332 millisecond.every = function(k) {
31334 if (!isFinite(k) || !(k > 0)) return null;
31335 if (!(k > 1)) return millisecond;
31336 return newInterval(function(date) {
31337 date.setTime(Math.floor(date / k) * k);
31338 }, function(date, step) {
31339 date.setTime(+date + step * k);
31340 }, function(start, end) {
31341 return (end - start) / k;
31345 var milliseconds = millisecond.range;
31347 var durationSecond$1 = 1e3;
31348 var durationMinute$1 = 6e4;
31349 var durationHour$1 = 36e5;
31350 var durationDay$1 = 864e5;
31351 var durationWeek$1 = 6048e5;
31353 var second = newInterval(function(date) {
31354 date.setTime(Math.floor(date / durationSecond$1) * durationSecond$1);
31355 }, function(date, step) {
31356 date.setTime(+date + step * durationSecond$1);
31357 }, function(start, end) {
31358 return (end - start) / durationSecond$1;
31359 }, function(date) {
31360 return date.getUTCSeconds();
31363 var seconds = second.range;
31365 var minute = newInterval(function(date) {
31366 date.setTime(Math.floor(date / durationMinute$1) * durationMinute$1);
31367 }, function(date, step) {
31368 date.setTime(+date + step * durationMinute$1);
31369 }, function(start, end) {
31370 return (end - start) / durationMinute$1;
31371 }, function(date) {
31372 return date.getMinutes();
31375 var minutes = minute.range;
31377 var hour = newInterval(function(date) {
31378 var offset = date.getTimezoneOffset() * durationMinute$1 % durationHour$1;
31379 if (offset < 0) offset += durationHour$1;
31380 date.setTime(Math.floor((+date - offset) / durationHour$1) * durationHour$1 + offset);
31381 }, function(date, step) {
31382 date.setTime(+date + step * durationHour$1);
31383 }, function(start, end) {
31384 return (end - start) / durationHour$1;
31385 }, function(date) {
31386 return date.getHours();
31389 var hours = hour.range;
31391 var day = newInterval(function(date) {
31392 date.setHours(0, 0, 0, 0);
31393 }, function(date, step) {
31394 date.setDate(date.getDate() + step);
31395 }, function(start, end) {
31396 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationDay$1;
31397 }, function(date) {
31398 return date.getDate() - 1;
31401 var days = day.range;
31403 function weekday(i) {
31404 return newInterval(function(date) {
31405 date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
31406 date.setHours(0, 0, 0, 0);
31407 }, function(date, step) {
31408 date.setDate(date.getDate() + step * 7);
31409 }, function(start, end) {
31410 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationWeek$1;
31414 var sunday = weekday(0);
31415 var monday = weekday(1);
31416 var tuesday = weekday(2);
31417 var wednesday = weekday(3);
31418 var thursday = weekday(4);
31419 var friday = weekday(5);
31420 var saturday = weekday(6);
31422 var sundays = sunday.range;
31423 var mondays = monday.range;
31424 var tuesdays = tuesday.range;
31425 var wednesdays = wednesday.range;
31426 var thursdays = thursday.range;
31427 var fridays = friday.range;
31428 var saturdays = saturday.range;
31430 var month = newInterval(function(date) {
31432 date.setHours(0, 0, 0, 0);
31433 }, function(date, step) {
31434 date.setMonth(date.getMonth() + step);
31435 }, function(start, end) {
31436 return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
31437 }, function(date) {
31438 return date.getMonth();
31441 var months = month.range;
31443 var year = newInterval(function(date) {
31444 date.setMonth(0, 1);
31445 date.setHours(0, 0, 0, 0);
31446 }, function(date, step) {
31447 date.setFullYear(date.getFullYear() + step);
31448 }, function(start, end) {
31449 return end.getFullYear() - start.getFullYear();
31450 }, function(date) {
31451 return date.getFullYear();
31454 // An optimized implementation for this simple case.
31455 year.every = function(k) {
31456 return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
31457 date.setFullYear(Math.floor(date.getFullYear() / k) * k);
31458 date.setMonth(0, 1);
31459 date.setHours(0, 0, 0, 0);
31460 }, function(date, step) {
31461 date.setFullYear(date.getFullYear() + step * k);
31465 var years = year.range;
31467 var utcMinute = newInterval(function(date) {
31468 date.setUTCSeconds(0, 0);
31469 }, function(date, step) {
31470 date.setTime(+date + step * durationMinute$1);
31471 }, function(start, end) {
31472 return (end - start) / durationMinute$1;
31473 }, function(date) {
31474 return date.getUTCMinutes();
31477 var utcMinutes = utcMinute.range;
31479 var utcHour = newInterval(function(date) {
31480 date.setUTCMinutes(0, 0, 0);
31481 }, function(date, step) {
31482 date.setTime(+date + step * durationHour$1);
31483 }, function(start, end) {
31484 return (end - start) / durationHour$1;
31485 }, function(date) {
31486 return date.getUTCHours();
31489 var utcHours = utcHour.range;
31491 var utcDay = newInterval(function(date) {
31492 date.setUTCHours(0, 0, 0, 0);
31493 }, function(date, step) {
31494 date.setUTCDate(date.getUTCDate() + step);
31495 }, function(start, end) {
31496 return (end - start) / durationDay$1;
31497 }, function(date) {
31498 return date.getUTCDate() - 1;
31501 var utcDays = utcDay.range;
31503 function utcWeekday(i) {
31504 return newInterval(function(date) {
31505 date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
31506 date.setUTCHours(0, 0, 0, 0);
31507 }, function(date, step) {
31508 date.setUTCDate(date.getUTCDate() + step * 7);
31509 }, function(start, end) {
31510 return (end - start) / durationWeek$1;
31514 var utcSunday = utcWeekday(0);
31515 var utcMonday = utcWeekday(1);
31516 var utcTuesday = utcWeekday(2);
31517 var utcWednesday = utcWeekday(3);
31518 var utcThursday = utcWeekday(4);
31519 var utcFriday = utcWeekday(5);
31520 var utcSaturday = utcWeekday(6);
31522 var utcSundays = utcSunday.range;
31523 var utcMondays = utcMonday.range;
31524 var utcTuesdays = utcTuesday.range;
31525 var utcWednesdays = utcWednesday.range;
31526 var utcThursdays = utcThursday.range;
31527 var utcFridays = utcFriday.range;
31528 var utcSaturdays = utcSaturday.range;
31530 var utcMonth = newInterval(function(date) {
31531 date.setUTCDate(1);
31532 date.setUTCHours(0, 0, 0, 0);
31533 }, function(date, step) {
31534 date.setUTCMonth(date.getUTCMonth() + step);
31535 }, function(start, end) {
31536 return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
31537 }, function(date) {
31538 return date.getUTCMonth();
31541 var utcMonths = utcMonth.range;
31543 var utcYear = newInterval(function(date) {
31544 date.setUTCMonth(0, 1);
31545 date.setUTCHours(0, 0, 0, 0);
31546 }, function(date, step) {
31547 date.setUTCFullYear(date.getUTCFullYear() + step);
31548 }, function(start, end) {
31549 return end.getUTCFullYear() - start.getUTCFullYear();
31550 }, function(date) {
31551 return date.getUTCFullYear();
31554 // An optimized implementation for this simple case.
31555 utcYear.every = function(k) {
31556 return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
31557 date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
31558 date.setUTCMonth(0, 1);
31559 date.setUTCHours(0, 0, 0, 0);
31560 }, function(date, step) {
31561 date.setUTCFullYear(date.getUTCFullYear() + step * k);
31565 var utcYears = utcYear.range;
31567 function localDate(d) {
31568 if (0 <= d.y && d.y < 100) {
31569 var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
31570 date.setFullYear(d.y);
31573 return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
31576 function utcDate(d) {
31577 if (0 <= d.y && d.y < 100) {
31578 var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
31579 date.setUTCFullYear(d.y);
31582 return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
31585 function newYear(y) {
31586 return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
31589 function formatLocale$1(locale) {
31590 var locale_dateTime = locale.dateTime,
31591 locale_date = locale.date,
31592 locale_time = locale.time,
31593 locale_periods = locale.periods,
31594 locale_weekdays = locale.days,
31595 locale_shortWeekdays = locale.shortDays,
31596 locale_months = locale.months,
31597 locale_shortMonths = locale.shortMonths;
31599 var periodRe = formatRe(locale_periods),
31600 periodLookup = formatLookup(locale_periods),
31601 weekdayRe = formatRe(locale_weekdays),
31602 weekdayLookup = formatLookup(locale_weekdays),
31603 shortWeekdayRe = formatRe(locale_shortWeekdays),
31604 shortWeekdayLookup = formatLookup(locale_shortWeekdays),
31605 monthRe = formatRe(locale_months),
31606 monthLookup = formatLookup(locale_months),
31607 shortMonthRe = formatRe(locale_shortMonths),
31608 shortMonthLookup = formatLookup(locale_shortMonths);
31611 "a": formatShortWeekday,
31612 "A": formatWeekday,
31613 "b": formatShortMonth,
31616 "d": formatDayOfMonth,
31617 "e": formatDayOfMonth,
31620 "j": formatDayOfYear,
31621 "L": formatMilliseconds,
31622 "m": formatMonthNumber,
31623 "M": formatMinutes,
31625 "S": formatSeconds,
31626 "U": formatWeekNumberSunday,
31627 "w": formatWeekdayNumber,
31628 "W": formatWeekNumberMonday,
31632 "Y": formatFullYear,
31634 "%": formatLiteralPercent
31638 "a": formatUTCShortWeekday,
31639 "A": formatUTCWeekday,
31640 "b": formatUTCShortMonth,
31641 "B": formatUTCMonth,
31643 "d": formatUTCDayOfMonth,
31644 "e": formatUTCDayOfMonth,
31645 "H": formatUTCHour24,
31646 "I": formatUTCHour12,
31647 "j": formatUTCDayOfYear,
31648 "L": formatUTCMilliseconds,
31649 "m": formatUTCMonthNumber,
31650 "M": formatUTCMinutes,
31651 "p": formatUTCPeriod,
31652 "S": formatUTCSeconds,
31653 "U": formatUTCWeekNumberSunday,
31654 "w": formatUTCWeekdayNumber,
31655 "W": formatUTCWeekNumberMonday,
31658 "y": formatUTCYear,
31659 "Y": formatUTCFullYear,
31660 "Z": formatUTCZone,
31661 "%": formatLiteralPercent
31665 "a": parseShortWeekday,
31667 "b": parseShortMonth,
31669 "c": parseLocaleDateTime,
31670 "d": parseDayOfMonth,
31671 "e": parseDayOfMonth,
31674 "j": parseDayOfYear,
31675 "L": parseMilliseconds,
31676 "m": parseMonthNumber,
31680 "U": parseWeekNumberSunday,
31681 "w": parseWeekdayNumber,
31682 "W": parseWeekNumberMonday,
31683 "x": parseLocaleDate,
31684 "X": parseLocaleTime,
31686 "Y": parseFullYear,
31688 "%": parseLiteralPercent
31691 // These recursive directive definitions must be deferred.
31692 formats.x = newFormat(locale_date, formats);
31693 formats.X = newFormat(locale_time, formats);
31694 formats.c = newFormat(locale_dateTime, formats);
31695 utcFormats.x = newFormat(locale_date, utcFormats);
31696 utcFormats.X = newFormat(locale_time, utcFormats);
31697 utcFormats.c = newFormat(locale_dateTime, utcFormats);
31699 function newFormat(specifier, formats) {
31700 return function(date) {
31704 n = specifier.length,
31709 if (!(date instanceof Date)) date = new Date(+date);
31712 if (specifier.charCodeAt(i) === 37) {
31713 string.push(specifier.slice(j, i));
31714 if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
31715 else pad = c === "e" ? " " : "0";
31716 if (format = formats[c]) c = format(date, pad);
31722 string.push(specifier.slice(j, i));
31723 return string.join("");
31727 function newParse(specifier, newDate) {
31728 return function(string) {
31729 var d = newYear(1900),
31730 i = parseSpecifier(d, specifier, string += "", 0);
31731 if (i != string.length) return null;
31733 // The am-pm flag is 0 for AM, and 1 for PM.
31734 if ("p" in d) d.H = d.H % 12 + d.p * 12;
31736 // Convert day-of-week and week-of-year to day-of-year.
31737 if ("W" in d || "U" in d) {
31738 if (!("w" in d)) d.w = "W" in d ? 1 : 0;
31739 var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
31741 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;
31744 // If a time zone is specified, all fields are interpreted as UTC and then
31745 // offset according to the specified time zone.
31747 d.H += d.Z / 100 | 0;
31752 // Otherwise, all fields are in local time.
31757 function parseSpecifier(d, specifier, string, j) {
31759 n = specifier.length,
31765 if (j >= m) return -1;
31766 c = specifier.charCodeAt(i++);
31768 c = specifier.charAt(i++);
31769 parse = parses[c in pads ? specifier.charAt(i++) : c];
31770 if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
31771 } else if (c != string.charCodeAt(j++)) {
31779 function parsePeriod(d, string, i) {
31780 var n = periodRe.exec(string.slice(i));
31781 return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31784 function parseShortWeekday(d, string, i) {
31785 var n = shortWeekdayRe.exec(string.slice(i));
31786 return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31789 function parseWeekday(d, string, i) {
31790 var n = weekdayRe.exec(string.slice(i));
31791 return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31794 function parseShortMonth(d, string, i) {
31795 var n = shortMonthRe.exec(string.slice(i));
31796 return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31799 function parseMonth(d, string, i) {
31800 var n = monthRe.exec(string.slice(i));
31801 return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31804 function parseLocaleDateTime(d, string, i) {
31805 return parseSpecifier(d, locale_dateTime, string, i);
31808 function parseLocaleDate(d, string, i) {
31809 return parseSpecifier(d, locale_date, string, i);
31812 function parseLocaleTime(d, string, i) {
31813 return parseSpecifier(d, locale_time, string, i);
31816 function formatShortWeekday(d) {
31817 return locale_shortWeekdays[d.getDay()];
31820 function formatWeekday(d) {
31821 return locale_weekdays[d.getDay()];
31824 function formatShortMonth(d) {
31825 return locale_shortMonths[d.getMonth()];
31828 function formatMonth(d) {
31829 return locale_months[d.getMonth()];
31832 function formatPeriod(d) {
31833 return locale_periods[+(d.getHours() >= 12)];
31836 function formatUTCShortWeekday(d) {
31837 return locale_shortWeekdays[d.getUTCDay()];
31840 function formatUTCWeekday(d) {
31841 return locale_weekdays[d.getUTCDay()];
31844 function formatUTCShortMonth(d) {
31845 return locale_shortMonths[d.getUTCMonth()];
31848 function formatUTCMonth(d) {
31849 return locale_months[d.getUTCMonth()];
31852 function formatUTCPeriod(d) {
31853 return locale_periods[+(d.getUTCHours() >= 12)];
31857 format: function(specifier) {
31858 var f = newFormat(specifier += "", formats);
31859 f.toString = function() { return specifier; };
31862 parse: function(specifier) {
31863 var p = newParse(specifier += "", localDate);
31864 p.toString = function() { return specifier; };
31867 utcFormat: function(specifier) {
31868 var f = newFormat(specifier += "", utcFormats);
31869 f.toString = function() { return specifier; };
31872 utcParse: function(specifier) {
31873 var p = newParse(specifier, utcDate);
31874 p.toString = function() { return specifier; };
31880 var pads = {"-": "", "_": " ", "0": "0"};
31881 var numberRe = /^\s*\d+/;
31882 var percentRe = /^%/;
31883 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
31885 function pad(value, fill, width) {
31886 var sign = value < 0 ? "-" : "",
31887 string = (sign ? -value : value) + "",
31888 length = string.length;
31889 return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
31892 function requote(s) {
31893 return s.replace(requoteRe, "\\$&");
31896 function formatRe(names) {
31897 return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
31900 function formatLookup(names) {
31901 var map = {}, i = -1, n = names.length;
31902 while (++i < n) map[names[i].toLowerCase()] = i;
31906 function parseWeekdayNumber(d, string, i) {
31907 var n = numberRe.exec(string.slice(i, i + 1));
31908 return n ? (d.w = +n[0], i + n[0].length) : -1;
31911 function parseWeekNumberSunday(d, string, i) {
31912 var n = numberRe.exec(string.slice(i));
31913 return n ? (d.U = +n[0], i + n[0].length) : -1;
31916 function parseWeekNumberMonday(d, string, i) {
31917 var n = numberRe.exec(string.slice(i));
31918 return n ? (d.W = +n[0], i + n[0].length) : -1;
31921 function parseFullYear(d, string, i) {
31922 var n = numberRe.exec(string.slice(i, i + 4));
31923 return n ? (d.y = +n[0], i + n[0].length) : -1;
31926 function parseYear(d, string, i) {
31927 var n = numberRe.exec(string.slice(i, i + 2));
31928 return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
31931 function parseZone(d, string, i) {
31932 var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
31933 return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
31936 function parseMonthNumber(d, string, i) {
31937 var n = numberRe.exec(string.slice(i, i + 2));
31938 return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
31941 function parseDayOfMonth(d, string, i) {
31942 var n = numberRe.exec(string.slice(i, i + 2));
31943 return n ? (d.d = +n[0], i + n[0].length) : -1;
31946 function parseDayOfYear(d, string, i) {
31947 var n = numberRe.exec(string.slice(i, i + 3));
31948 return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
31951 function parseHour24(d, string, i) {
31952 var n = numberRe.exec(string.slice(i, i + 2));
31953 return n ? (d.H = +n[0], i + n[0].length) : -1;
31956 function parseMinutes(d, string, i) {
31957 var n = numberRe.exec(string.slice(i, i + 2));
31958 return n ? (d.M = +n[0], i + n[0].length) : -1;
31961 function parseSeconds(d, string, i) {
31962 var n = numberRe.exec(string.slice(i, i + 2));
31963 return n ? (d.S = +n[0], i + n[0].length) : -1;
31966 function parseMilliseconds(d, string, i) {
31967 var n = numberRe.exec(string.slice(i, i + 3));
31968 return n ? (d.L = +n[0], i + n[0].length) : -1;
31971 function parseLiteralPercent(d, string, i) {
31972 var n = percentRe.exec(string.slice(i, i + 1));
31973 return n ? i + n[0].length : -1;
31976 function formatDayOfMonth(d, p) {
31977 return pad(d.getDate(), p, 2);
31980 function formatHour24(d, p) {
31981 return pad(d.getHours(), p, 2);
31984 function formatHour12(d, p) {
31985 return pad(d.getHours() % 12 || 12, p, 2);
31988 function formatDayOfYear(d, p) {
31989 return pad(1 + day.count(year(d), d), p, 3);
31992 function formatMilliseconds(d, p) {
31993 return pad(d.getMilliseconds(), p, 3);
31996 function formatMonthNumber(d, p) {
31997 return pad(d.getMonth() + 1, p, 2);
32000 function formatMinutes(d, p) {
32001 return pad(d.getMinutes(), p, 2);
32004 function formatSeconds(d, p) {
32005 return pad(d.getSeconds(), p, 2);
32008 function formatWeekNumberSunday(d, p) {
32009 return pad(sunday.count(year(d), d), p, 2);
32012 function formatWeekdayNumber(d) {
32016 function formatWeekNumberMonday(d, p) {
32017 return pad(monday.count(year(d), d), p, 2);
32020 function formatYear(d, p) {
32021 return pad(d.getFullYear() % 100, p, 2);
32024 function formatFullYear(d, p) {
32025 return pad(d.getFullYear() % 10000, p, 4);
32028 function formatZone(d) {
32029 var z = d.getTimezoneOffset();
32030 return (z > 0 ? "-" : (z *= -1, "+"))
32031 + pad(z / 60 | 0, "0", 2)
32032 + pad(z % 60, "0", 2);
32035 function formatUTCDayOfMonth(d, p) {
32036 return pad(d.getUTCDate(), p, 2);
32039 function formatUTCHour24(d, p) {
32040 return pad(d.getUTCHours(), p, 2);
32043 function formatUTCHour12(d, p) {
32044 return pad(d.getUTCHours() % 12 || 12, p, 2);
32047 function formatUTCDayOfYear(d, p) {
32048 return pad(1 + utcDay.count(utcYear(d), d), p, 3);
32051 function formatUTCMilliseconds(d, p) {
32052 return pad(d.getUTCMilliseconds(), p, 3);
32055 function formatUTCMonthNumber(d, p) {
32056 return pad(d.getUTCMonth() + 1, p, 2);
32059 function formatUTCMinutes(d, p) {
32060 return pad(d.getUTCMinutes(), p, 2);
32063 function formatUTCSeconds(d, p) {
32064 return pad(d.getUTCSeconds(), p, 2);
32067 function formatUTCWeekNumberSunday(d, p) {
32068 return pad(utcSunday.count(utcYear(d), d), p, 2);
32071 function formatUTCWeekdayNumber(d) {
32072 return d.getUTCDay();
32075 function formatUTCWeekNumberMonday(d, p) {
32076 return pad(utcMonday.count(utcYear(d), d), p, 2);
32079 function formatUTCYear(d, p) {
32080 return pad(d.getUTCFullYear() % 100, p, 2);
32083 function formatUTCFullYear(d, p) {
32084 return pad(d.getUTCFullYear() % 10000, p, 4);
32087 function formatUTCZone() {
32091 function formatLiteralPercent() {
32102 dateTime: "%x, %X",
32103 date: "%-m/%-d/%Y",
32104 time: "%-I:%M:%S %p",
32105 periods: ["AM", "PM"],
32106 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
32107 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
32108 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
32109 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
32112 function defaultLocale$1(definition) {
32113 locale$2 = formatLocale$1(definition);
32114 timeFormat = locale$2.format;
32115 timeParse = locale$2.parse;
32116 utcFormat = locale$2.utcFormat;
32117 utcParse = locale$2.utcParse;
32121 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
32123 function formatIsoNative(date) {
32124 return date.toISOString();
32127 var formatIso = Date.prototype.toISOString
32129 : utcFormat(isoSpecifier);
32131 function parseIsoNative(string) {
32132 var date = new Date(string);
32133 return isNaN(date) ? null : date;
32136 var parseIso = +new Date("2000-01-01T00:00:00.000Z")
32138 : utcParse(isoSpecifier);
32140 var durationSecond = 1000;
32141 var durationMinute = durationSecond * 60;
32142 var durationHour = durationMinute * 60;
32143 var durationDay = durationHour * 24;
32144 var durationWeek = durationDay * 7;
32145 var durationMonth = durationDay * 30;
32146 var durationYear = durationDay * 365;
32148 function date$1(t) {
32149 return new Date(t);
32152 function number$2(t) {
32153 return t instanceof Date ? +t : +new Date(+t);
32156 function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) {
32157 var scale = continuous(deinterpolateLinear, reinterpolate),
32158 invert = scale.invert,
32159 domain = scale.domain;
32161 var formatMillisecond = format(".%L"),
32162 formatSecond = format(":%S"),
32163 formatMinute = format("%I:%M"),
32164 formatHour = format("%I %p"),
32165 formatDay = format("%a %d"),
32166 formatWeek = format("%b %d"),
32167 formatMonth = format("%B"),
32168 formatYear = format("%Y");
32170 var tickIntervals = [
32171 [second$$1, 1, durationSecond],
32172 [second$$1, 5, 5 * durationSecond],
32173 [second$$1, 15, 15 * durationSecond],
32174 [second$$1, 30, 30 * durationSecond],
32175 [minute$$1, 1, durationMinute],
32176 [minute$$1, 5, 5 * durationMinute],
32177 [minute$$1, 15, 15 * durationMinute],
32178 [minute$$1, 30, 30 * durationMinute],
32179 [ hour$$1, 1, durationHour ],
32180 [ hour$$1, 3, 3 * durationHour ],
32181 [ hour$$1, 6, 6 * durationHour ],
32182 [ hour$$1, 12, 12 * durationHour ],
32183 [ day$$1, 1, durationDay ],
32184 [ day$$1, 2, 2 * durationDay ],
32185 [ week, 1, durationWeek ],
32186 [ month$$1, 1, durationMonth ],
32187 [ month$$1, 3, 3 * durationMonth ],
32188 [ year$$1, 1, durationYear ]
32191 function tickFormat(date) {
32192 return (second$$1(date) < date ? formatMillisecond
32193 : minute$$1(date) < date ? formatSecond
32194 : hour$$1(date) < date ? formatMinute
32195 : day$$1(date) < date ? formatHour
32196 : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek)
32197 : year$$1(date) < date ? formatMonth
32198 : formatYear)(date);
32201 function tickInterval(interval, start, stop, step) {
32202 if (interval == null) interval = 10;
32204 // If a desired tick count is specified, pick a reasonable tick interval
32205 // based on the extent of the domain and a rough estimate of tick size.
32206 // Otherwise, assume interval is already a time interval and use it.
32207 if (typeof interval === "number") {
32208 var target = Math.abs(stop - start) / interval,
32209 i = bisector(function(i) { return i[2]; }).right(tickIntervals, target);
32210 if (i === tickIntervals.length) {
32211 step = tickStep(start / durationYear, stop / durationYear, interval);
32212 interval = year$$1;
32214 i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
32218 step = tickStep(start, stop, interval);
32219 interval = millisecond$$1;
32223 return step == null ? interval : interval.every(step);
32226 scale.invert = function(y) {
32227 return new Date(invert(y));
32230 scale.domain = function(_) {
32231 return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1);
32234 scale.ticks = function(interval, step) {
32237 t1 = d[d.length - 1],
32240 if (r) t = t0, t0 = t1, t1 = t;
32241 t = tickInterval(interval, t0, t1, step);
32242 t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
32243 return r ? t.reverse() : t;
32246 scale.tickFormat = function(count, specifier) {
32247 return specifier == null ? tickFormat : format(specifier);
32250 scale.nice = function(interval, step) {
32252 return (interval = tickInterval(interval, d[0], d[d.length - 1], step))
32253 ? domain(nice(d, interval))
32257 scale.copy = function() {
32258 return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format));
32264 var time = function() {
32265 return calendar(year, month, sunday, day, hour, minute, second, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]);
32268 var utcTime = function() {
32269 return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]);
32272 var colors = function(s) {
32273 return s.match(/.{6}/g).map(function(x) {
32278 var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf");
32280 var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6");
32282 var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9");
32284 var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5");
32286 var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0));
32288 var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
32290 var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
32292 var rainbow = cubehelix();
32294 var rainbow$1 = function(t) {
32295 if (t < 0 || t > 1) t -= Math.floor(t);
32296 var ts = Math.abs(t - 0.5);
32297 rainbow.h = 360 * t - 100;
32298 rainbow.s = 1.5 - 1.5 * ts;
32299 rainbow.l = 0.8 - 0.9 * ts;
32300 return rainbow + "";
32303 function ramp(range) {
32304 var n = range.length;
32305 return function(t) {
32306 return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];
32310 var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));
32312 var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf"));
32314 var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4"));
32316 var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));
32318 function sequential(interpolator) {
32323 function scale(x) {
32324 var t = (x - x0) / (x1 - x0);
32325 return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t);
32328 scale.domain = function(_) {
32329 return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1];
32332 scale.clamp = function(_) {
32333 return arguments.length ? (clamp = !!_, scale) : clamp;
32336 scale.interpolator = function(_) {
32337 return arguments.length ? (interpolator = _, scale) : interpolator;
32340 scale.copy = function() {
32341 return sequential(interpolator).domain([x0, x1]).clamp(clamp);
32344 return linearish(scale);
32347 var constant$10 = function(x) {
32348 return function constant() {
32353 var abs$1 = Math.abs;
32354 var atan2$1 = Math.atan2;
32355 var cos$2 = Math.cos;
32356 var max$2 = Math.max;
32357 var min$1 = Math.min;
32358 var sin$2 = Math.sin;
32359 var sqrt$2 = Math.sqrt;
32361 var epsilon$3 = 1e-12;
32362 var pi$4 = Math.PI;
32363 var halfPi$3 = pi$4 / 2;
32364 var tau$4 = 2 * pi$4;
32366 function acos$1(x) {
32367 return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x);
32370 function asin$1(x) {
32371 return x >= 1 ? halfPi$3 : x <= -1 ? -halfPi$3 : Math.asin(x);
32374 function arcInnerRadius(d) {
32375 return d.innerRadius;
32378 function arcOuterRadius(d) {
32379 return d.outerRadius;
32382 function arcStartAngle(d) {
32383 return d.startAngle;
32386 function arcEndAngle(d) {
32390 function arcPadAngle(d) {
32391 return d && d.padAngle; // Note: optional!
32394 function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
32395 var x10 = x1 - x0, y10 = y1 - y0,
32396 x32 = x3 - x2, y32 = y3 - y2,
32397 t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10);
32398 return [x0 + t * x10, y0 + t * y10];
32401 // Compute perpendicular offset line of length rc.
32402 // http://mathworld.wolfram.com/Circle-LineIntersection.html
32403 function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
32406 lo = (cw ? rc : -rc) / sqrt$2(x01 * x01 + y01 * y01),
32413 x00 = (x11 + x10) / 2,
32414 y00 = (y11 + y10) / 2,
32417 d2 = dx * dx + dy * dy,
32419 D = x11 * y10 - x10 * y11,
32420 d = (dy < 0 ? -1 : 1) * sqrt$2(max$2(0, r * r * d2 - D * D)),
32421 cx0 = (D * dy - dx * d) / d2,
32422 cy0 = (-D * dx - dy * d) / d2,
32423 cx1 = (D * dy + dx * d) / d2,
32424 cy1 = (-D * dx + dy * d) / d2,
32430 // Pick the closer of the two intersection points.
32431 // TODO Is there a faster way to determine which intersection to use?
32432 if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
32439 x11: cx0 * (r1 / r - 1),
32440 y11: cy0 * (r1 / r - 1)
32444 var arc = function() {
32445 var innerRadius = arcInnerRadius,
32446 outerRadius = arcOuterRadius,
32447 cornerRadius = constant$10(0),
32449 startAngle = arcStartAngle,
32450 endAngle = arcEndAngle,
32451 padAngle = arcPadAngle,
32457 r0 = +innerRadius.apply(this, arguments),
32458 r1 = +outerRadius.apply(this, arguments),
32459 a0 = startAngle.apply(this, arguments) - halfPi$3,
32460 a1 = endAngle.apply(this, arguments) - halfPi$3,
32461 da = abs$1(a1 - a0),
32464 if (!context) context = buffer = path();
32466 // Ensure that the outer radius is always larger than the inner radius.
32467 if (r1 < r0) r = r1, r1 = r0, r0 = r;
32470 if (!(r1 > epsilon$3)) context.moveTo(0, 0);
32472 // Or is it a circle or annulus?
32473 else if (da > tau$4 - epsilon$3) {
32474 context.moveTo(r1 * cos$2(a0), r1 * sin$2(a0));
32475 context.arc(0, 0, r1, a0, a1, !cw);
32476 if (r0 > epsilon$3) {
32477 context.moveTo(r0 * cos$2(a1), r0 * sin$2(a1));
32478 context.arc(0, 0, r0, a1, a0, cw);
32482 // Or is it a circular or annular sector?
32490 ap = padAngle.apply(this, arguments) / 2,
32491 rp = (ap > epsilon$3) && (padRadius ? +padRadius.apply(this, arguments) : sqrt$2(r0 * r0 + r1 * r1)),
32492 rc = min$1(abs$1(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
32498 // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
32499 if (rp > epsilon$3) {
32500 var p0 = asin$1(rp / r0 * sin$2(ap)),
32501 p1 = asin$1(rp / r1 * sin$2(ap));
32502 if ((da0 -= p0 * 2) > epsilon$3) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
32503 else da0 = 0, a00 = a10 = (a0 + a1) / 2;
32504 if ((da1 -= p1 * 2) > epsilon$3) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
32505 else da1 = 0, a01 = a11 = (a0 + a1) / 2;
32508 var x01 = r1 * cos$2(a01),
32509 y01 = r1 * sin$2(a01),
32510 x10 = r0 * cos$2(a10),
32511 y10 = r0 * sin$2(a10);
32513 // Apply rounded corners?
32514 if (rc > epsilon$3) {
32515 var x11 = r1 * cos$2(a11),
32516 y11 = r1 * sin$2(a11),
32517 x00 = r0 * cos$2(a00),
32518 y00 = r0 * sin$2(a00);
32520 // Restrict the corner radius according to the sector angle.
32522 var oc = da0 > epsilon$3 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10],
32527 kc = 1 / sin$2(acos$1((ax * bx + ay * by) / (sqrt$2(ax * ax + ay * ay) * sqrt$2(bx * bx + by * by))) / 2),
32528 lc = sqrt$2(oc[0] * oc[0] + oc[1] * oc[1]);
32529 rc0 = min$1(rc, (r0 - lc) / (kc - 1));
32530 rc1 = min$1(rc, (r1 - lc) / (kc + 1));
32534 // Is the sector collapsed to a line?
32535 if (!(da1 > epsilon$3)) context.moveTo(x01, y01);
32537 // Does the sector’s outer ring have rounded corners?
32538 else if (rc1 > epsilon$3) {
32539 t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
32540 t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
32542 context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
32544 // Have the corners merged?
32545 if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw);
32547 // Otherwise, draw the two corners and the ring.
32549 context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw);
32550 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);
32551 context.arc(t1.cx, t1.cy, rc1, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw);
32555 // Or is the outer ring just a circular arc?
32556 else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
32558 // Is there no inner ring, and it’s a circular sector?
32559 // Or perhaps it’s an annular sector collapsed due to padding?
32560 if (!(r0 > epsilon$3) || !(da0 > epsilon$3)) context.lineTo(x10, y10);
32562 // Does the sector’s inner ring (or point) have rounded corners?
32563 else if (rc0 > epsilon$3) {
32564 t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
32565 t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
32567 context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
32569 // Have the corners merged?
32570 if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw);
32572 // Otherwise, draw the two corners and the ring.
32574 context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw);
32575 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);
32576 context.arc(t1.cx, t1.cy, rc0, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw);
32580 // Or is the inner ring just a circular arc?
32581 else context.arc(0, 0, r0, a10, a00, cw);
32584 context.closePath();
32586 if (buffer) return context = null, buffer + "" || null;
32589 arc.centroid = function() {
32590 var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
32591 a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$4 / 2;
32592 return [cos$2(a) * r, sin$2(a) * r];
32595 arc.innerRadius = function(_) {
32596 return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : innerRadius;
32599 arc.outerRadius = function(_) {
32600 return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : outerRadius;
32603 arc.cornerRadius = function(_) {
32604 return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : cornerRadius;
32607 arc.padRadius = function(_) {
32608 return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), arc) : padRadius;
32611 arc.startAngle = function(_) {
32612 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : startAngle;
32615 arc.endAngle = function(_) {
32616 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : endAngle;
32619 arc.padAngle = function(_) {
32620 return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : padAngle;
32623 arc.context = function(_) {
32624 return arguments.length ? ((context = _ == null ? null : _), arc) : context;
32630 function Linear(context) {
32631 this._context = context;
32634 Linear.prototype = {
32635 areaStart: function() {
32638 areaEnd: function() {
32641 lineStart: function() {
32644 lineEnd: function() {
32645 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
32646 this._line = 1 - this._line;
32648 point: function(x, y) {
32650 switch (this._point) {
32651 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
32652 case 1: this._point = 2; // proceed
32653 default: this._context.lineTo(x, y); break;
32658 var curveLinear = function(context) {
32659 return new Linear(context);
32670 var line = function() {
32673 defined = constant$10(true),
32675 curve = curveLinear,
32678 function line(data) {
32685 if (context == null) output = curve(buffer = path());
32687 for (i = 0; i <= n; ++i) {
32688 if (!(i < n && defined(d = data[i], i, data)) === defined0) {
32689 if (defined0 = !defined0) output.lineStart();
32690 else output.lineEnd();
32692 if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data));
32695 if (buffer) return output = null, buffer + "" || null;
32698 line.x = function(_) {
32699 return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : x$$1;
32702 line.y = function(_) {
32703 return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : y$$1;
32706 line.defined = function(_) {
32707 return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), line) : defined;
32710 line.curve = function(_) {
32711 return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
32714 line.context = function(_) {
32715 return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
32721 var area$1 = function() {
32724 y0 = constant$10(0),
32726 defined = constant$10(true),
32728 curve = curveLinear,
32731 function area(data) {
32739 x0z = new Array(n),
32740 y0z = new Array(n);
32742 if (context == null) output = curve(buffer = path());
32744 for (i = 0; i <= n; ++i) {
32745 if (!(i < n && defined(d = data[i], i, data)) === defined0) {
32746 if (defined0 = !defined0) {
32748 output.areaStart();
32749 output.lineStart();
32752 output.lineStart();
32753 for (k = i - 1; k >= j; --k) {
32754 output.point(x0z[k], y0z[k]);
32761 x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
32762 output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
32766 if (buffer) return output = null, buffer + "" || null;
32769 function arealine() {
32770 return line().defined(defined).curve(curve).context(context);
32773 area.x = function(_) {
32774 return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), x1 = null, area) : x0;
32777 area.x0 = function(_) {
32778 return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), area) : x0;
32781 area.x1 = function(_) {
32782 return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : x1;
32785 area.y = function(_) {
32786 return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), y1 = null, area) : y0;
32789 area.y0 = function(_) {
32790 return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), area) : y0;
32793 area.y1 = function(_) {
32794 return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : y1;
32798 area.lineY0 = function() {
32799 return arealine().x(x0).y(y0);
32802 area.lineY1 = function() {
32803 return arealine().x(x0).y(y1);
32806 area.lineX1 = function() {
32807 return arealine().x(x1).y(y0);
32810 area.defined = function(_) {
32811 return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), area) : defined;
32814 area.curve = function(_) {
32815 return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
32818 area.context = function(_) {
32819 return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
32825 var descending$1 = function(a, b) {
32826 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
32829 var identity$7 = function(d) {
32833 var pie = function() {
32834 var value = identity$7,
32835 sortValues = descending$1,
32837 startAngle = constant$10(0),
32838 endAngle = constant$10(tau$4),
32839 padAngle = constant$10(0);
32841 function pie(data) {
32847 index = new Array(n),
32848 arcs = new Array(n),
32849 a0 = +startAngle.apply(this, arguments),
32850 da = Math.min(tau$4, Math.max(-tau$4, endAngle.apply(this, arguments) - a0)),
32852 p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
32853 pa = p * (da < 0 ? -1 : 1),
32856 for (i = 0; i < n; ++i) {
32857 if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
32862 // Optionally sort the arcs by previously-computed values or by data.
32863 if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
32864 else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); });
32866 // Compute the arcs! They are stored in the original data's order.
32867 for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
32868 j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
32881 pie.value = function(_) {
32882 return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), pie) : value;
32885 pie.sortValues = function(_) {
32886 return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
32889 pie.sort = function(_) {
32890 return arguments.length ? (sort = _, sortValues = null, pie) : sort;
32893 pie.startAngle = function(_) {
32894 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : startAngle;
32897 pie.endAngle = function(_) {
32898 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : endAngle;
32901 pie.padAngle = function(_) {
32902 return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : padAngle;
32908 var curveRadialLinear = curveRadial(curveLinear);
32910 function Radial(curve) {
32911 this._curve = curve;
32914 Radial.prototype = {
32915 areaStart: function() {
32916 this._curve.areaStart();
32918 areaEnd: function() {
32919 this._curve.areaEnd();
32921 lineStart: function() {
32922 this._curve.lineStart();
32924 lineEnd: function() {
32925 this._curve.lineEnd();
32927 point: function(a, r) {
32928 this._curve.point(r * Math.sin(a), r * -Math.cos(a));
32932 function curveRadial(curve) {
32934 function radial(context) {
32935 return new Radial(curve(context));
32938 radial._curve = curve;
32943 function radialLine(l) {
32946 l.angle = l.x, delete l.x;
32947 l.radius = l.y, delete l.y;
32949 l.curve = function(_) {
32950 return arguments.length ? c(curveRadial(_)) : c()._curve;
32956 var radialLine$1 = function() {
32957 return radialLine(line().curve(curveRadialLinear));
32960 var radialArea = function() {
32961 var a = area$1().curve(curveRadialLinear),
32968 a.angle = a.x, delete a.x;
32969 a.startAngle = a.x0, delete a.x0;
32970 a.endAngle = a.x1, delete a.x1;
32971 a.radius = a.y, delete a.y;
32972 a.innerRadius = a.y0, delete a.y0;
32973 a.outerRadius = a.y1, delete a.y1;
32974 a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0;
32975 a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1;
32976 a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0;
32977 a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1;
32979 a.curve = function(_) {
32980 return arguments.length ? c(curveRadial(_)) : c()._curve;
32987 draw: function(context, size) {
32988 var r = Math.sqrt(size / pi$4);
32989 context.moveTo(r, 0);
32990 context.arc(0, 0, r, 0, tau$4);
32995 draw: function(context, size) {
32996 var r = Math.sqrt(size / 5) / 2;
32997 context.moveTo(-3 * r, -r);
32998 context.lineTo(-r, -r);
32999 context.lineTo(-r, -3 * r);
33000 context.lineTo(r, -3 * r);
33001 context.lineTo(r, -r);
33002 context.lineTo(3 * r, -r);
33003 context.lineTo(3 * r, r);
33004 context.lineTo(r, r);
33005 context.lineTo(r, 3 * r);
33006 context.lineTo(-r, 3 * r);
33007 context.lineTo(-r, r);
33008 context.lineTo(-3 * r, r);
33009 context.closePath();
33013 var tan30 = Math.sqrt(1 / 3);
33014 var tan30_2 = tan30 * 2;
33017 draw: function(context, size) {
33018 var y = Math.sqrt(size / tan30_2),
33020 context.moveTo(0, -y);
33021 context.lineTo(x, 0);
33022 context.lineTo(0, y);
33023 context.lineTo(-x, 0);
33024 context.closePath();
33028 var ka = 0.89081309152928522810;
33029 var kr = Math.sin(pi$4 / 10) / Math.sin(7 * pi$4 / 10);
33030 var kx = Math.sin(tau$4 / 10) * kr;
33031 var ky = -Math.cos(tau$4 / 10) * kr;
33034 draw: function(context, size) {
33035 var r = Math.sqrt(size * ka),
33038 context.moveTo(0, -r);
33039 context.lineTo(x, y);
33040 for (var i = 1; i < 5; ++i) {
33041 var a = tau$4 * i / 5,
33044 context.lineTo(s * r, -c * r);
33045 context.lineTo(c * x - s * y, s * x + c * y);
33047 context.closePath();
33052 draw: function(context, size) {
33053 var w = Math.sqrt(size),
33055 context.rect(x, x, w, w);
33059 var sqrt3 = Math.sqrt(3);
33062 draw: function(context, size) {
33063 var y = -Math.sqrt(size / (sqrt3 * 3));
33064 context.moveTo(0, y * 2);
33065 context.lineTo(-sqrt3 * y, -y);
33066 context.lineTo(sqrt3 * y, -y);
33067 context.closePath();
33072 var s = Math.sqrt(3) / 2;
33073 var k = 1 / Math.sqrt(12);
33074 var a = (k / 2 + 1) * 3;
33077 draw: function(context, size) {
33078 var r = Math.sqrt(size / a),
33085 context.moveTo(x0, y0);
33086 context.lineTo(x1, y1);
33087 context.lineTo(x2, y2);
33088 context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
33089 context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
33090 context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
33091 context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
33092 context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
33093 context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
33094 context.closePath();
33108 var symbol = function() {
33109 var type = constant$10(circle$2),
33110 size = constant$10(64),
33113 function symbol() {
33115 if (!context) context = buffer = path();
33116 type.apply(this, arguments).draw(context, +size.apply(this, arguments));
33117 if (buffer) return context = null, buffer + "" || null;
33120 symbol.type = function(_) {
33121 return arguments.length ? (type = typeof _ === "function" ? _ : constant$10(_), symbol) : type;
33124 symbol.size = function(_) {
33125 return arguments.length ? (size = typeof _ === "function" ? _ : constant$10(+_), symbol) : size;
33128 symbol.context = function(_) {
33129 return arguments.length ? (context = _ == null ? null : _, symbol) : context;
33135 var noop$2 = function() {};
33137 function point$2(that, x, y) {
33138 that._context.bezierCurveTo(
33139 (2 * that._x0 + that._x1) / 3,
33140 (2 * that._y0 + that._y1) / 3,
33141 (that._x0 + 2 * that._x1) / 3,
33142 (that._y0 + 2 * that._y1) / 3,
33143 (that._x0 + 4 * that._x1 + x) / 6,
33144 (that._y0 + 4 * that._y1 + y) / 6
33148 function Basis(context) {
33149 this._context = context;
33152 Basis.prototype = {
33153 areaStart: function() {
33156 areaEnd: function() {
33159 lineStart: function() {
33160 this._x0 = this._x1 =
33161 this._y0 = this._y1 = NaN;
33164 lineEnd: function() {
33165 switch (this._point) {
33166 case 3: point$2(this, this._x1, this._y1); // proceed
33167 case 2: this._context.lineTo(this._x1, this._y1); break;
33169 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33170 this._line = 1 - this._line;
33172 point: function(x, y) {
33174 switch (this._point) {
33175 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33176 case 1: this._point = 2; break;
33177 case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed
33178 default: point$2(this, x, y); break;
33180 this._x0 = this._x1, this._x1 = x;
33181 this._y0 = this._y1, this._y1 = y;
33185 var basis$2 = function(context) {
33186 return new Basis(context);
33189 function BasisClosed(context) {
33190 this._context = context;
33193 BasisClosed.prototype = {
33196 lineStart: function() {
33197 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
33198 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
33201 lineEnd: function() {
33202 switch (this._point) {
33204 this._context.moveTo(this._x2, this._y2);
33205 this._context.closePath();
33209 this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
33210 this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
33211 this._context.closePath();
33215 this.point(this._x2, this._y2);
33216 this.point(this._x3, this._y3);
33217 this.point(this._x4, this._y4);
33222 point: function(x, y) {
33224 switch (this._point) {
33225 case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
33226 case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
33227 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;
33228 default: point$2(this, x, y); break;
33230 this._x0 = this._x1, this._x1 = x;
33231 this._y0 = this._y1, this._y1 = y;
33235 var basisClosed$1 = function(context) {
33236 return new BasisClosed(context);
33239 function BasisOpen(context) {
33240 this._context = context;
33243 BasisOpen.prototype = {
33244 areaStart: function() {
33247 areaEnd: function() {
33250 lineStart: function() {
33251 this._x0 = this._x1 =
33252 this._y0 = this._y1 = NaN;
33255 lineEnd: function() {
33256 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33257 this._line = 1 - this._line;
33259 point: function(x, y) {
33261 switch (this._point) {
33262 case 0: this._point = 1; break;
33263 case 1: this._point = 2; break;
33264 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;
33265 case 3: this._point = 4; // proceed
33266 default: point$2(this, x, y); break;
33268 this._x0 = this._x1, this._x1 = x;
33269 this._y0 = this._y1, this._y1 = y;
33273 var basisOpen = function(context) {
33274 return new BasisOpen(context);
33277 function Bundle(context, beta) {
33278 this._basis = new Basis(context);
33282 Bundle.prototype = {
33283 lineStart: function() {
33286 this._basis.lineStart();
33288 lineEnd: function() {
33304 this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
33305 this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
33310 this._x = this._y = null;
33311 this._basis.lineEnd();
33313 point: function(x, y) {
33319 var bundle = ((function custom(beta) {
33321 function bundle(context) {
33322 return beta === 1 ? new Basis(context) : new Bundle(context, beta);
33325 bundle.beta = function(beta) {
33326 return custom(+beta);
33332 function point$3(that, x, y) {
33333 that._context.bezierCurveTo(
33334 that._x1 + that._k * (that._x2 - that._x0),
33335 that._y1 + that._k * (that._y2 - that._y0),
33336 that._x2 + that._k * (that._x1 - x),
33337 that._y2 + that._k * (that._y1 - y),
33343 function Cardinal(context, tension) {
33344 this._context = context;
33345 this._k = (1 - tension) / 6;
33348 Cardinal.prototype = {
33349 areaStart: function() {
33352 areaEnd: function() {
33355 lineStart: function() {
33356 this._x0 = this._x1 = this._x2 =
33357 this._y0 = this._y1 = this._y2 = NaN;
33360 lineEnd: function() {
33361 switch (this._point) {
33362 case 2: this._context.lineTo(this._x2, this._y2); break;
33363 case 3: point$3(this, this._x1, this._y1); break;
33365 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33366 this._line = 1 - this._line;
33368 point: function(x, y) {
33370 switch (this._point) {
33371 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33372 case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
33373 case 2: this._point = 3; // proceed
33374 default: point$3(this, x, y); break;
33376 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33377 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33381 var cardinal = ((function custom(tension) {
33383 function cardinal(context) {
33384 return new Cardinal(context, tension);
33387 cardinal.tension = function(tension) {
33388 return custom(+tension);
33394 function CardinalClosed(context, tension) {
33395 this._context = context;
33396 this._k = (1 - tension) / 6;
33399 CardinalClosed.prototype = {
33402 lineStart: function() {
33403 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
33404 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
33407 lineEnd: function() {
33408 switch (this._point) {
33410 this._context.moveTo(this._x3, this._y3);
33411 this._context.closePath();
33415 this._context.lineTo(this._x3, this._y3);
33416 this._context.closePath();
33420 this.point(this._x3, this._y3);
33421 this.point(this._x4, this._y4);
33422 this.point(this._x5, this._y5);
33427 point: function(x, y) {
33429 switch (this._point) {
33430 case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
33431 case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
33432 case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
33433 default: point$3(this, x, y); break;
33435 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33436 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33440 var cardinalClosed = ((function custom(tension) {
33442 function cardinal(context) {
33443 return new CardinalClosed(context, tension);
33446 cardinal.tension = function(tension) {
33447 return custom(+tension);
33453 function CardinalOpen(context, tension) {
33454 this._context = context;
33455 this._k = (1 - tension) / 6;
33458 CardinalOpen.prototype = {
33459 areaStart: function() {
33462 areaEnd: function() {
33465 lineStart: function() {
33466 this._x0 = this._x1 = this._x2 =
33467 this._y0 = this._y1 = this._y2 = NaN;
33470 lineEnd: function() {
33471 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33472 this._line = 1 - this._line;
33474 point: function(x, y) {
33476 switch (this._point) {
33477 case 0: this._point = 1; break;
33478 case 1: this._point = 2; break;
33479 case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
33480 case 3: this._point = 4; // proceed
33481 default: point$3(this, x, y); break;
33483 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33484 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33488 var cardinalOpen = ((function custom(tension) {
33490 function cardinal(context) {
33491 return new CardinalOpen(context, tension);
33494 cardinal.tension = function(tension) {
33495 return custom(+tension);
33501 function point$4(that, x, y) {
33507 if (that._l01_a > epsilon$3) {
33508 var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
33509 n = 3 * that._l01_a * (that._l01_a + that._l12_a);
33510 x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
33511 y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
33514 if (that._l23_a > epsilon$3) {
33515 var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
33516 m = 3 * that._l23_a * (that._l23_a + that._l12_a);
33517 x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
33518 y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
33521 that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
33524 function CatmullRom(context, alpha) {
33525 this._context = context;
33526 this._alpha = alpha;
33529 CatmullRom.prototype = {
33530 areaStart: function() {
33533 areaEnd: function() {
33536 lineStart: function() {
33537 this._x0 = this._x1 = this._x2 =
33538 this._y0 = this._y1 = this._y2 = NaN;
33539 this._l01_a = this._l12_a = this._l23_a =
33540 this._l01_2a = this._l12_2a = this._l23_2a =
33543 lineEnd: function() {
33544 switch (this._point) {
33545 case 2: this._context.lineTo(this._x2, this._y2); break;
33546 case 3: this.point(this._x2, this._y2); break;
33548 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33549 this._line = 1 - this._line;
33551 point: function(x, y) {
33555 var x23 = this._x2 - x,
33556 y23 = this._y2 - y;
33557 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33560 switch (this._point) {
33561 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33562 case 1: this._point = 2; break;
33563 case 2: this._point = 3; // proceed
33564 default: point$4(this, x, y); break;
33567 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33568 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33569 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33570 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33574 var catmullRom = ((function custom(alpha) {
33576 function catmullRom(context) {
33577 return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
33580 catmullRom.alpha = function(alpha) {
33581 return custom(+alpha);
33587 function CatmullRomClosed(context, alpha) {
33588 this._context = context;
33589 this._alpha = alpha;
33592 CatmullRomClosed.prototype = {
33595 lineStart: function() {
33596 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
33597 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
33598 this._l01_a = this._l12_a = this._l23_a =
33599 this._l01_2a = this._l12_2a = this._l23_2a =
33602 lineEnd: function() {
33603 switch (this._point) {
33605 this._context.moveTo(this._x3, this._y3);
33606 this._context.closePath();
33610 this._context.lineTo(this._x3, this._y3);
33611 this._context.closePath();
33615 this.point(this._x3, this._y3);
33616 this.point(this._x4, this._y4);
33617 this.point(this._x5, this._y5);
33622 point: function(x, y) {
33626 var x23 = this._x2 - x,
33627 y23 = this._y2 - y;
33628 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33631 switch (this._point) {
33632 case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
33633 case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
33634 case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
33635 default: point$4(this, x, y); break;
33638 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33639 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33640 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33641 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33645 var catmullRomClosed = ((function custom(alpha) {
33647 function catmullRom(context) {
33648 return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
33651 catmullRom.alpha = function(alpha) {
33652 return custom(+alpha);
33658 function CatmullRomOpen(context, alpha) {
33659 this._context = context;
33660 this._alpha = alpha;
33663 CatmullRomOpen.prototype = {
33664 areaStart: function() {
33667 areaEnd: function() {
33670 lineStart: function() {
33671 this._x0 = this._x1 = this._x2 =
33672 this._y0 = this._y1 = this._y2 = NaN;
33673 this._l01_a = this._l12_a = this._l23_a =
33674 this._l01_2a = this._l12_2a = this._l23_2a =
33677 lineEnd: function() {
33678 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33679 this._line = 1 - this._line;
33681 point: function(x, y) {
33685 var x23 = this._x2 - x,
33686 y23 = this._y2 - y;
33687 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33690 switch (this._point) {
33691 case 0: this._point = 1; break;
33692 case 1: this._point = 2; break;
33693 case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
33694 case 3: this._point = 4; // proceed
33695 default: point$4(this, x, y); break;
33698 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33699 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33700 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33701 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33705 var catmullRomOpen = ((function custom(alpha) {
33707 function catmullRom(context) {
33708 return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
33711 catmullRom.alpha = function(alpha) {
33712 return custom(+alpha);
33718 function LinearClosed(context) {
33719 this._context = context;
33722 LinearClosed.prototype = {
33725 lineStart: function() {
33728 lineEnd: function() {
33729 if (this._point) this._context.closePath();
33731 point: function(x, y) {
33733 if (this._point) this._context.lineTo(x, y);
33734 else this._point = 1, this._context.moveTo(x, y);
33738 var linearClosed = function(context) {
33739 return new LinearClosed(context);
33742 function sign$1(x) {
33743 return x < 0 ? -1 : 1;
33746 // Calculate the slopes of the tangents (Hermite-type interpolation) based on
33747 // the following paper: Steffen, M. 1990. A Simple Method for Monotonic
33748 // Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
33749 // NOV(II), P. 443, 1990.
33750 function slope3(that, x2, y2) {
33751 var h0 = that._x1 - that._x0,
33752 h1 = x2 - that._x1,
33753 s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
33754 s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
33755 p = (s0 * h1 + s1 * h0) / (h0 + h1);
33756 return (sign$1(s0) + sign$1(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
33759 // Calculate a one-sided slope.
33760 function slope2(that, t) {
33761 var h = that._x1 - that._x0;
33762 return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
33765 // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
33766 // "you can express cubic Hermite interpolation in terms of cubic Bézier curves
33767 // with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
33768 function point$5(that, t0, t1) {
33773 dx = (x1 - x0) / 3;
33774 that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
33777 function MonotoneX(context) {
33778 this._context = context;
33781 MonotoneX.prototype = {
33782 areaStart: function() {
33785 areaEnd: function() {
33788 lineStart: function() {
33789 this._x0 = this._x1 =
33790 this._y0 = this._y1 =
33794 lineEnd: function() {
33795 switch (this._point) {
33796 case 2: this._context.lineTo(this._x1, this._y1); break;
33797 case 3: point$5(this, this._t0, slope2(this, this._t0)); break;
33799 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33800 this._line = 1 - this._line;
33802 point: function(x, y) {
33806 if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
33807 switch (this._point) {
33808 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33809 case 1: this._point = 2; break;
33810 case 2: this._point = 3; point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
33811 default: point$5(this, this._t0, t1 = slope3(this, x, y)); break;
33814 this._x0 = this._x1, this._x1 = x;
33815 this._y0 = this._y1, this._y1 = y;
33820 function MonotoneY(context) {
33821 this._context = new ReflectContext(context);
33824 (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
33825 MonotoneX.prototype.point.call(this, y, x);
33828 function ReflectContext(context) {
33829 this._context = context;
33832 ReflectContext.prototype = {
33833 moveTo: function(x, y) { this._context.moveTo(y, x); },
33834 closePath: function() { this._context.closePath(); },
33835 lineTo: function(x, y) { this._context.lineTo(y, x); },
33836 bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
33839 function monotoneX(context) {
33840 return new MonotoneX(context);
33843 function monotoneY(context) {
33844 return new MonotoneY(context);
33847 function Natural(context) {
33848 this._context = context;
33851 Natural.prototype = {
33852 areaStart: function() {
33855 areaEnd: function() {
33858 lineStart: function() {
33862 lineEnd: function() {
33868 this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
33870 this._context.lineTo(x[1], y[1]);
33872 var px = controlPoints(x),
33873 py = controlPoints(y);
33874 for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
33875 this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
33880 if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
33881 this._line = 1 - this._line;
33882 this._x = this._y = null;
33884 point: function(x, y) {
33890 // See https://www.particleincell.com/2012/bezier-splines/ for derivation.
33891 function controlPoints(x) {
33898 a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
33899 for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
33900 a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
33901 for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
33902 a[n - 1] = r[n - 1] / b[n - 1];
33903 for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
33904 b[n - 1] = (x[n] + a[n - 1]) / 2;
33905 for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
33909 var natural = function(context) {
33910 return new Natural(context);
33913 function Step(context, t) {
33914 this._context = context;
33919 areaStart: function() {
33922 areaEnd: function() {
33925 lineStart: function() {
33926 this._x = this._y = NaN;
33929 lineEnd: function() {
33930 if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
33931 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33932 if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
33934 point: function(x, y) {
33936 switch (this._point) {
33937 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33938 case 1: this._point = 2; // proceed
33940 if (this._t <= 0) {
33941 this._context.lineTo(this._x, y);
33942 this._context.lineTo(x, y);
33944 var x1 = this._x * (1 - this._t) + x * this._t;
33945 this._context.lineTo(x1, this._y);
33946 this._context.lineTo(x1, y);
33951 this._x = x, this._y = y;
33955 var step = function(context) {
33956 return new Step(context, 0.5);
33959 function stepBefore(context) {
33960 return new Step(context, 0);
33963 function stepAfter(context) {
33964 return new Step(context, 1);
33967 var slice$5 = Array.prototype.slice;
33969 var none$1 = function(series, order) {
33970 if (!((n = series.length) > 1)) return;
33971 for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
33972 s0 = s1, s1 = series[order[i]];
33973 for (var j = 0; j < m; ++j) {
33974 s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
33979 var none$2 = function(series) {
33980 var n = series.length, o = new Array(n);
33981 while (--n >= 0) o[n] = n;
33985 function stackValue(d, key) {
33989 var stack = function() {
33990 var keys = constant$10([]),
33993 value = stackValue;
33995 function stack(data) {
33996 var kz = keys.apply(this, arguments),
34003 for (i = 0; i < n; ++i) {
34004 for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
34005 si[j] = sij = [0, +value(data[j], ki, j, data)];
34006 sij.data = data[j];
34011 for (i = 0, oz = order(sz); i < n; ++i) {
34012 sz[oz[i]].index = i;
34019 stack.keys = function(_) {
34020 return arguments.length ? (keys = typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : keys;
34023 stack.value = function(_) {
34024 return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), stack) : value;
34027 stack.order = function(_) {
34028 return arguments.length ? (order = _ == null ? none$2 : typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : order;
34031 stack.offset = function(_) {
34032 return arguments.length ? (offset = _ == null ? none$1 : _, stack) : offset;
34038 var expand = function(series, order) {
34039 if (!((n = series.length) > 0)) return;
34040 for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
34041 for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0;
34042 if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y;
34044 none$1(series, order);
34047 var silhouette = function(series, order) {
34048 if (!((n = series.length) > 0)) return;
34049 for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
34050 for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0;
34051 s0[j][1] += s0[j][0] = -y / 2;
34053 none$1(series, order);
34056 var wiggle = function(series, order) {
34057 if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
34058 for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
34059 for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
34060 var si = series[order[i]],
34061 sij0 = si[j][1] || 0,
34062 sij1 = si[j - 1][1] || 0,
34063 s3 = (sij0 - sij1) / 2;
34064 for (var k = 0; k < i; ++k) {
34065 var sk = series[order[k]],
34066 skj0 = sk[j][1] || 0,
34067 skj1 = sk[j - 1][1] || 0;
34070 s1 += sij0, s2 += s3 * sij0;
34072 s0[j - 1][1] += s0[j - 1][0] = y;
34073 if (s1) y -= s2 / s1;
34075 s0[j - 1][1] += s0[j - 1][0] = y;
34076 none$1(series, order);
34079 var ascending$2 = function(series) {
34080 var sums = series.map(sum$2);
34081 return none$2(series).sort(function(a, b) { return sums[a] - sums[b]; });
34084 function sum$2(series) {
34085 var s = 0, i = -1, n = series.length, v;
34086 while (++i < n) if (v = +series[i][1]) s += v;
34090 var descending$2 = function(series) {
34091 return ascending$2(series).reverse();
34094 var insideOut = function(series) {
34095 var n = series.length,
34098 sums = series.map(sum$2),
34099 order = none$2(series).sort(function(a, b) { return sums[b] - sums[a]; }),
34105 for (i = 0; i < n; ++i) {
34107 if (top < bottom) {
34116 return bottoms.reverse().concat(tops);
34119 var reverse = function(series) {
34120 return none$2(series).reverse();
34123 var constant$11 = function(x) {
34124 return function() {
34137 function RedBlackTree() {
34138 this._ = null; // root node
34141 function RedBlackNode(node) {
34142 node.U = // parent node
34143 node.C = // color - true for red, false for black
34144 node.L = // left node
34145 node.R = // right node
34146 node.P = // previous node
34147 node.N = null; // next node
34150 RedBlackTree.prototype = {
34151 constructor: RedBlackTree,
34153 insert: function(after, node) {
34154 var parent, grandpa, uncle;
34159 if (after.N) after.N.P = node;
34163 while (after.L) after = after.L;
34169 } else if (this._) {
34170 after = RedBlackFirst(this._);
34173 after.P = after.L = node;
34176 node.P = node.N = null;
34180 node.L = node.R = null;
34185 while (parent && parent.C) {
34186 grandpa = parent.U;
34187 if (parent === grandpa.L) {
34189 if (uncle && uncle.C) {
34190 parent.C = uncle.C = false;
34194 if (after === parent.R) {
34195 RedBlackRotateLeft(this, parent);
34201 RedBlackRotateRight(this, grandpa);
34205 if (uncle && uncle.C) {
34206 parent.C = uncle.C = false;
34210 if (after === parent.L) {
34211 RedBlackRotateRight(this, parent);
34217 RedBlackRotateLeft(this, grandpa);
34225 remove: function(node) {
34226 if (node.N) node.N.P = node.P;
34227 if (node.P) node.P.N = node.N;
34228 node.N = node.P = null;
34230 var parent = node.U,
34237 if (!left) next = right;
34238 else if (!right) next = left;
34239 else next = RedBlackFirst(right);
34242 if (parent.L === node) parent.L = next;
34243 else parent.R = next;
34248 if (left && right) {
34253 if (next !== right) {
34270 if (node) node.U = parent;
34272 if (node && node.C) { node.C = false; return; }
34275 if (node === this._) break;
34276 if (node === parent.L) {
34277 sibling = parent.R;
34281 RedBlackRotateLeft(this, parent);
34282 sibling = parent.R;
34284 if ((sibling.L && sibling.L.C)
34285 || (sibling.R && sibling.R.C)) {
34286 if (!sibling.R || !sibling.R.C) {
34287 sibling.L.C = false;
34289 RedBlackRotateRight(this, sibling);
34290 sibling = parent.R;
34292 sibling.C = parent.C;
34293 parent.C = sibling.R.C = false;
34294 RedBlackRotateLeft(this, parent);
34299 sibling = parent.L;
34303 RedBlackRotateRight(this, parent);
34304 sibling = parent.L;
34306 if ((sibling.L && sibling.L.C)
34307 || (sibling.R && sibling.R.C)) {
34308 if (!sibling.L || !sibling.L.C) {
34309 sibling.R.C = false;
34311 RedBlackRotateLeft(this, sibling);
34312 sibling = parent.L;
34314 sibling.C = parent.C;
34315 parent.C = sibling.L.C = false;
34316 RedBlackRotateRight(this, parent);
34326 if (node) node.C = false;
34330 function RedBlackRotateLeft(tree, node) {
34336 if (parent.L === p) parent.L = q;
34345 if (p.R) p.R.U = p;
34349 function RedBlackRotateRight(tree, node) {
34355 if (parent.L === p) parent.L = q;
34364 if (p.L) p.L.U = p;
34368 function RedBlackFirst(node) {
34369 while (node.L) node = node.L;
34373 function createEdge(left, right, v0, v1) {
34374 var edge = [null, null],
34375 index = edges.push(edge) - 1;
34377 edge.right = right;
34378 if (v0) setEdgeEnd(edge, left, right, v0);
34379 if (v1) setEdgeEnd(edge, right, left, v1);
34380 cells[left.index].halfedges.push(index);
34381 cells[right.index].halfedges.push(index);
34385 function createBorderEdge(left, v0, v1) {
34386 var edge = [v0, v1];
34391 function setEdgeEnd(edge, left, right, vertex) {
34392 if (!edge[0] && !edge[1]) {
34395 edge.right = right;
34396 } else if (edge.left === right) {
34403 // Liang–Barsky line clipping.
34404 function clipEdge(edge, x0, y0, x1, y1) {
34418 if (!dx && r > 0) return;
34421 if (r < t0) return;
34422 if (r < t1) t1 = r;
34423 } else if (dx > 0) {
34424 if (r > t1) return;
34425 if (r > t0) t0 = r;
34429 if (!dx && r < 0) return;
34432 if (r > t1) return;
34433 if (r > t0) t0 = r;
34434 } else if (dx > 0) {
34435 if (r < t0) return;
34436 if (r < t1) t1 = r;
34440 if (!dy && r > 0) return;
34443 if (r < t0) return;
34444 if (r < t1) t1 = r;
34445 } else if (dy > 0) {
34446 if (r > t1) return;
34447 if (r > t0) t0 = r;
34451 if (!dy && r < 0) return;
34454 if (r > t1) return;
34455 if (r > t0) t0 = r;
34456 } else if (dy > 0) {
34457 if (r < t0) return;
34458 if (r < t1) t1 = r;
34461 if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
34463 if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
34464 if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
34468 function connectEdge(edge, x0, y0, x1, y1) {
34470 if (v1) return true;
34474 right = edge.right,
34479 fx = (lx + rx) / 2,
34480 fy = (ly + ry) / 2,
34485 if (fx < x0 || fx >= x1) return;
34487 if (!v0) v0 = [fx, y0];
34488 else if (v0[1] >= y1) return;
34491 if (!v0) v0 = [fx, y1];
34492 else if (v0[1] < y0) return;
34496 fm = (lx - rx) / (ry - ly);
34498 if (fm < -1 || fm > 1) {
34500 if (!v0) v0 = [(y0 - fb) / fm, y0];
34501 else if (v0[1] >= y1) return;
34502 v1 = [(y1 - fb) / fm, y1];
34504 if (!v0) v0 = [(y1 - fb) / fm, y1];
34505 else if (v0[1] < y0) return;
34506 v1 = [(y0 - fb) / fm, y0];
34510 if (!v0) v0 = [x0, fm * x0 + fb];
34511 else if (v0[0] >= x1) return;
34512 v1 = [x1, fm * x1 + fb];
34514 if (!v0) v0 = [x1, fm * x1 + fb];
34515 else if (v0[0] < x0) return;
34516 v1 = [x0, fm * x0 + fb];
34526 function clipEdges(x0, y0, x1, y1) {
34527 var i = edges.length,
34531 if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
34532 || !clipEdge(edge, x0, y0, x1, y1)
34533 || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$4
34534 || Math.abs(edge[0][1] - edge[1][1]) > epsilon$4)) {
34540 function createCell(site) {
34541 return cells[site.index] = {
34547 function cellHalfedgeAngle(cell, edge) {
34548 var site = cell.site,
34551 if (site === vb) vb = va, va = site;
34552 if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
34553 if (site === va) va = edge[1], vb = edge[0];
34554 else va = edge[0], vb = edge[1];
34555 return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
34558 function cellHalfedgeStart(cell, edge) {
34559 return edge[+(edge.left !== cell.site)];
34562 function cellHalfedgeEnd(cell, edge) {
34563 return edge[+(edge.left === cell.site)];
34566 function sortCellHalfedges() {
34567 for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
34568 if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
34569 var index = new Array(m),
34570 array = new Array(m);
34571 for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
34572 index.sort(function(i, j) { return array[j] - array[i]; });
34573 for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
34574 for (j = 0; j < m; ++j) halfedges[j] = array[j];
34579 function clipCells(x0, y0, x1, y1) {
34580 var nCells = cells.length,
34595 for (iCell = 0; iCell < nCells; ++iCell) {
34596 if (cell = cells[iCell]) {
34598 halfedges = cell.halfedges;
34599 iHalfedge = halfedges.length;
34601 // Remove any dangling clipped edges.
34602 while (iHalfedge--) {
34603 if (!edges[halfedges[iHalfedge]]) {
34604 halfedges.splice(iHalfedge, 1);
34608 // Insert any border edges as necessary.
34609 iHalfedge = 0, nHalfedges = halfedges.length;
34610 while (iHalfedge < nHalfedges) {
34611 end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
34612 start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
34613 if (Math.abs(endX - startX) > epsilon$4 || Math.abs(endY - startY) > epsilon$4) {
34614 halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
34615 Math.abs(endX - x0) < epsilon$4 && y1 - endY > epsilon$4 ? [x0, Math.abs(startX - x0) < epsilon$4 ? startY : y1]
34616 : Math.abs(endY - y1) < epsilon$4 && x1 - endX > epsilon$4 ? [Math.abs(startY - y1) < epsilon$4 ? startX : x1, y1]
34617 : Math.abs(endX - x1) < epsilon$4 && endY - y0 > epsilon$4 ? [x1, Math.abs(startX - x1) < epsilon$4 ? startY : y0]
34618 : Math.abs(endY - y0) < epsilon$4 && endX - x0 > epsilon$4 ? [Math.abs(startY - y0) < epsilon$4 ? startX : x0, y0]
34624 if (nHalfedges) cover = false;
34628 // If there weren’t any edges, have the closest site cover the extent.
34629 // It doesn’t matter which corner of the extent we measure!
34631 var dx, dy, d2, dc = Infinity;
34633 for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
34634 if (cell = cells[iCell]) {
34638 d2 = dx * dx + dy * dy;
34639 if (d2 < dc) dc = d2, cover = cell;
34644 var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
34645 cover.halfedges.push(
34646 edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
34647 edges.push(createBorderEdge(site, v01, v11)) - 1,
34648 edges.push(createBorderEdge(site, v11, v10)) - 1,
34649 edges.push(createBorderEdge(site, v10, v00)) - 1
34654 // Lastly delete any cells with no edges; these were entirely clipped.
34655 for (iCell = 0; iCell < nCells; ++iCell) {
34656 if (cell = cells[iCell]) {
34657 if (!cell.halfedges.length) {
34658 delete cells[iCell];
34664 var circlePool = [];
34668 function Circle() {
34669 RedBlackNode(this);
34677 function attachCircle(arc) {
34681 if (!lArc || !rArc) return;
34683 var lSite = lArc.site,
34687 if (lSite === rSite) return;
34691 ax = lSite[0] - bx,
34692 ay = lSite[1] - by,
34693 cx = rSite[0] - bx,
34694 cy = rSite[1] - by;
34696 var d = 2 * (ax * cy - ay * cx);
34697 if (d >= -epsilon2$2) return;
34699 var ha = ax * ax + ay * ay,
34700 hc = cx * cx + cy * cy,
34701 x = (cy * ha - ay * hc) / d,
34702 y = (ax * hc - cx * ha) / d;
34704 var circle = circlePool.pop() || new Circle;
34706 circle.site = cSite;
34708 circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
34710 arc.circle = circle;
34716 if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
34717 if (node.L) node = node.L;
34718 else { before = node.P; break; }
34720 if (node.R) node = node.R;
34721 else { before = node; break; }
34725 circles.insert(before, circle);
34726 if (!before) firstCircle = circle;
34729 function detachCircle(arc) {
34730 var circle = arc.circle;
34732 if (!circle.P) firstCircle = circle.N;
34733 circles.remove(circle);
34734 circlePool.push(circle);
34735 RedBlackNode(circle);
34740 var beachPool = [];
34743 RedBlackNode(this);
34746 this.circle = null;
34749 function createBeach(site) {
34750 var beach = beachPool.pop() || new Beach;
34755 function detachBeach(beach) {
34756 detachCircle(beach);
34757 beaches.remove(beach);
34758 beachPool.push(beach);
34759 RedBlackNode(beach);
34762 function removeBeach(beach) {
34763 var circle = beach.circle,
34767 previous = beach.P,
34769 disappearing = [beach];
34771 detachBeach(beach);
34773 var lArc = previous;
34775 && Math.abs(x - lArc.circle.x) < epsilon$4
34776 && Math.abs(y - lArc.circle.cy) < epsilon$4) {
34778 disappearing.unshift(lArc);
34783 disappearing.unshift(lArc);
34784 detachCircle(lArc);
34788 && Math.abs(x - rArc.circle.x) < epsilon$4
34789 && Math.abs(y - rArc.circle.cy) < epsilon$4) {
34791 disappearing.push(rArc);
34796 disappearing.push(rArc);
34797 detachCircle(rArc);
34799 var nArcs = disappearing.length,
34801 for (iArc = 1; iArc < nArcs; ++iArc) {
34802 rArc = disappearing[iArc];
34803 lArc = disappearing[iArc - 1];
34804 setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
34807 lArc = disappearing[0];
34808 rArc = disappearing[nArcs - 1];
34809 rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
34811 attachCircle(lArc);
34812 attachCircle(rArc);
34815 function addBeach(site) {
34817 directrix = site[1],
34825 dxl = leftBreakPoint(node, directrix) - x;
34826 if (dxl > epsilon$4) node = node.L; else {
34827 dxr = x - rightBreakPoint(node, directrix);
34828 if (dxr > epsilon$4) {
34835 if (dxl > -epsilon$4) {
34838 } else if (dxr > -epsilon$4) {
34842 lArc = rArc = node;
34850 var newArc = createBeach(site);
34851 beaches.insert(lArc, newArc);
34853 if (!lArc && !rArc) return;
34855 if (lArc === rArc) {
34856 detachCircle(lArc);
34857 rArc = createBeach(lArc.site);
34858 beaches.insert(newArc, rArc);
34859 newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
34860 attachCircle(lArc);
34861 attachCircle(rArc);
34865 if (!rArc) { // && lArc
34866 newArc.edge = createEdge(lArc.site, newArc.site);
34870 // else lArc !== rArc
34871 detachCircle(lArc);
34872 detachCircle(rArc);
34874 var lSite = lArc.site,
34880 cx = rSite[0] - ax,
34881 cy = rSite[1] - ay,
34882 d = 2 * (bx * cy - by * cx),
34883 hb = bx * bx + by * by,
34884 hc = cx * cx + cy * cy,
34885 vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
34887 setEdgeEnd(rArc.edge, lSite, rSite, vertex);
34888 newArc.edge = createEdge(lSite, site, null, vertex);
34889 rArc.edge = createEdge(site, rSite, null, vertex);
34890 attachCircle(lArc);
34891 attachCircle(rArc);
34894 function leftBreakPoint(arc, directrix) {
34895 var site = arc.site,
34898 pby2 = rfocy - directrix;
34900 if (!pby2) return rfocx;
34903 if (!lArc) return -Infinity;
34906 var lfocx = site[0],
34908 plby2 = lfocy - directrix;
34910 if (!plby2) return lfocx;
34912 var hl = lfocx - rfocx,
34913 aby2 = 1 / pby2 - 1 / plby2,
34916 if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
34918 return (rfocx + lfocx) / 2;
34921 function rightBreakPoint(arc, directrix) {
34923 if (rArc) return leftBreakPoint(rArc, directrix);
34924 var site = arc.site;
34925 return site[1] === directrix ? site[0] : Infinity;
34928 var epsilon$4 = 1e-6;
34929 var epsilon2$2 = 1e-12;
34935 function triangleArea(a, b, c) {
34936 return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
34939 function lexicographic(a, b) {
34944 function Diagram(sites, extent) {
34945 var site = sites.sort(lexicographic).pop(),
34951 cells = new Array(sites.length);
34952 beaches = new RedBlackTree;
34953 circles = new RedBlackTree;
34956 circle = firstCircle;
34957 if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
34958 if (site[0] !== x || site[1] !== y) {
34960 x = site[0], y = site[1];
34962 site = sites.pop();
34963 } else if (circle) {
34964 removeBeach(circle.arc);
34970 sortCellHalfedges();
34973 var x0 = +extent[0][0],
34974 y0 = +extent[0][1],
34975 x1 = +extent[1][0],
34976 y1 = +extent[1][1];
34977 clipEdges(x0, y0, x1, y1);
34978 clipCells(x0, y0, x1, y1);
34981 this.edges = edges;
34982 this.cells = cells;
34990 Diagram.prototype = {
34991 constructor: Diagram,
34993 polygons: function() {
34994 var edges = this.edges;
34996 return this.cells.map(function(cell) {
34997 var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); });
34998 polygon.data = cell.site.data;
35003 triangles: function() {
35004 var triangles = [],
35005 edges = this.edges;
35007 this.cells.forEach(function(cell, i) {
35008 if (!(m = (halfedges = cell.halfedges).length)) return;
35009 var site = cell.site,
35014 e1 = edges[halfedges[m - 1]],
35015 s1 = e1.left === site ? e1.right : e1.left;
35019 e1 = edges[halfedges[j]];
35020 s1 = e1.left === site ? e1.right : e1.left;
35021 if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
35022 triangles.push([site.data, s0.data, s1.data]);
35030 links: function() {
35031 return this.edges.filter(function(edge) {
35033 }).map(function(edge) {
35035 source: edge.left.data,
35036 target: edge.right.data
35041 find: function(x, y, radius) {
35042 var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell;
35044 // Use the previously-found cell, or start with an arbitrary one.
35045 while (!(cell = that.cells[i1])) if (++i1 >= n) return null;
35046 var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy;
35048 // Traverse the half-edges to find a closer cell, if any.
35050 cell = that.cells[i0 = i1], i1 = null;
35051 cell.halfedges.forEach(function(e) {
35052 var edge = that.edges[e], v = edge.left;
35053 if ((v === cell.site || !v) && !(v = edge.right)) return;
35054 var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy;
35055 if (v2 < d2) d2 = v2, i1 = v.index;
35057 } while (i1 !== null);
35061 return radius == null || d2 <= radius * radius ? cell.site : null;
35065 var voronoi = function() {
35070 function voronoi(data) {
35071 return new Diagram(data.map(function(d, i) {
35072 var s = [Math.round(x$$1(d, i, data) / epsilon$4) * epsilon$4, Math.round(y$$1(d, i, data) / epsilon$4) * epsilon$4];
35079 voronoi.polygons = function(data) {
35080 return voronoi(data).polygons();
35083 voronoi.links = function(data) {
35084 return voronoi(data).links();
35087 voronoi.triangles = function(data) {
35088 return voronoi(data).triangles();
35091 voronoi.x = function(_) {
35092 return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : x$$1;
35095 voronoi.y = function(_) {
35096 return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : y$$1;
35099 voronoi.extent = function(_) {
35100 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]]];
35103 voronoi.size = function(_) {
35104 return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]];
35110 var constant$12 = function(x) {
35111 return function() {
35116 function ZoomEvent(target, type, transform) {
35117 this.target = target;
35119 this.transform = transform;
35122 function Transform(k, x, y) {
35128 Transform.prototype = {
35129 constructor: Transform,
35130 scale: function(k) {
35131 return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
35133 translate: function(x, y) {
35134 return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
35136 apply: function(point) {
35137 return [point[0] * this.k + this.x, point[1] * this.k + this.y];
35139 applyX: function(x) {
35140 return x * this.k + this.x;
35142 applyY: function(y) {
35143 return y * this.k + this.y;
35145 invert: function(location) {
35146 return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
35148 invertX: function(x) {
35149 return (x - this.x) / this.k;
35151 invertY: function(y) {
35152 return (y - this.y) / this.k;
35154 rescaleX: function(x) {
35155 return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
35157 rescaleY: function(y) {
35158 return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
35160 toString: function() {
35161 return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
35165 var identity$8 = new Transform(1, 0, 0);
35167 transform$1.prototype = Transform.prototype;
35169 function transform$1(node) {
35170 return node.__zoom || identity$8;
35173 function nopropagation$2() {
35174 event.stopImmediatePropagation();
35177 var noevent$2 = function() {
35178 event.preventDefault();
35179 event.stopImmediatePropagation();
35182 // Ignore right-click, since that should open the context menu.
35183 function defaultFilter$2() {
35184 return !event.button;
35187 function defaultExtent$1() {
35188 var e = this, w, h;
35189 if (e instanceof SVGElement) {
35190 e = e.ownerSVGElement || e;
35191 w = e.width.baseVal.value;
35192 h = e.height.baseVal.value;
35195 h = e.clientHeight;
35197 return [[0, 0], [w, h]];
35200 function defaultTransform() {
35201 return this.__zoom || identity$8;
35204 var zoom = function() {
35205 var filter = defaultFilter$2,
35206 extent = defaultExtent$1,
35214 interpolate$$1 = interpolateZoom,
35216 listeners = dispatch("start", "zoom", "end"),
35222 function zoom(selection$$1) {
35224 .on("wheel.zoom", wheeled)
35225 .on("mousedown.zoom", mousedowned)
35226 .on("dblclick.zoom", dblclicked)
35227 .on("touchstart.zoom", touchstarted)
35228 .on("touchmove.zoom", touchmoved)
35229 .on("touchend.zoom touchcancel.zoom", touchended)
35230 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
35231 .property("__zoom", defaultTransform);
35234 zoom.transform = function(collection, transform) {
35235 var selection$$1 = collection.selection ? collection.selection() : collection;
35236 selection$$1.property("__zoom", defaultTransform);
35237 if (collection !== selection$$1) {
35238 schedule(collection, transform);
35240 selection$$1.interrupt().each(function() {
35241 gesture(this, arguments)
35243 .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform)
35249 zoom.scaleBy = function(selection$$1, k) {
35250 zoom.scaleTo(selection$$1, function() {
35251 var k0 = this.__zoom.k,
35252 k1 = typeof k === "function" ? k.apply(this, arguments) : k;
35257 zoom.scaleTo = function(selection$$1, k) {
35258 zoom.transform(selection$$1, function() {
35259 var e = extent.apply(this, arguments),
35262 p1 = t0.invert(p0),
35263 k1 = typeof k === "function" ? k.apply(this, arguments) : k;
35264 return constrain(translate(scale(t0, k1), p0, p1), e);
35268 zoom.translateBy = function(selection$$1, x, y) {
35269 zoom.transform(selection$$1, function() {
35270 return constrain(this.__zoom.translate(
35271 typeof x === "function" ? x.apply(this, arguments) : x,
35272 typeof y === "function" ? y.apply(this, arguments) : y
35273 ), extent.apply(this, arguments));
35277 function scale(transform, k) {
35278 k = Math.max(k0, Math.min(k1, k));
35279 return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
35282 function translate(transform, p0, p1) {
35283 var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k;
35284 return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
35287 function constrain(transform, extent) {
35288 var dx0 = transform.invertX(extent[0][0]) - x0,
35289 dx1 = transform.invertX(extent[1][0]) - x1,
35290 dy0 = transform.invertY(extent[0][1]) - y0,
35291 dy1 = transform.invertY(extent[1][1]) - y1;
35292 return transform.translate(
35293 dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1),
35294 dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)
35298 function centroid(extent) {
35299 return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
35302 function schedule(transition$$1, transform, center) {
35304 .on("start.zoom", function() { gesture(this, arguments).start(); })
35305 .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
35306 .tween("zoom", function() {
35309 g = gesture(that, args),
35310 e = extent.apply(that, args),
35311 p = center || centroid(e),
35312 w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
35314 b = typeof transform === "function" ? transform.apply(that, args) : transform,
35315 i = interpolate$$1(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
35316 return function(t) {
35317 if (t === 1) t = b; // Avoid rounding error on end.
35318 else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
35324 function gesture(that, args) {
35325 for (var i = 0, n = gestures.length, g; i < n; ++i) {
35326 if ((g = gestures[i]).that === that) {
35330 return new Gesture(that, args);
35333 function Gesture(that, args) {
35338 this.extent = extent.apply(that, args);
35341 Gesture.prototype = {
35342 start: function() {
35343 if (++this.active === 1) {
35344 this.index = gestures.push(this) - 1;
35345 this.emit("start");
35349 zoom: function(key, transform) {
35350 if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
35351 if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
35352 if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
35353 this.that.__zoom = transform;
35358 if (--this.active === 0) {
35359 gestures.splice(this.index, 1);
35365 emit: function(type) {
35366 customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
35370 function wheeled() {
35371 if (!filter.apply(this, arguments)) return;
35372 var g = gesture(this, arguments),
35374 k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500))),
35377 // If the mouse is in the same location as before, reuse it.
35378 // If there were recent wheel events, reset the wheel idle timeout.
35380 if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
35381 g.mouse[1] = t.invert(g.mouse[0] = p);
35383 clearTimeout(g.wheel);
35386 // If this wheel event won’t trigger a transform change, ignore it.
35387 else if (t.k === k) return;
35389 // Otherwise, capture the mouse point and location at the start.
35391 g.mouse = [p, t.invert(p)];
35397 g.wheel = setTimeout(wheelidled, wheelDelay);
35398 g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent));
35400 function wheelidled() {
35406 function mousedowned() {
35407 if (touchending || !filter.apply(this, arguments)) return;
35408 var g = gesture(this, arguments),
35409 v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
35412 dragDisable(event.view);
35414 g.mouse = [p, this.__zoom.invert(p)];
35418 function mousemoved() {
35421 g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent));
35424 function mouseupped() {
35425 v.on("mousemove.zoom mouseup.zoom", null);
35426 yesdrag(event.view, g.moved);
35432 function dblclicked() {
35433 if (!filter.apply(this, arguments)) return;
35434 var t0 = this.__zoom,
35436 p1 = t0.invert(p0),
35437 k1 = t0.k * (event.shiftKey ? 0.5 : 2),
35438 t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments));
35441 if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
35442 else select(this).call(zoom.transform, t1);
35445 function touchstarted() {
35446 if (!filter.apply(this, arguments)) return;
35447 var g = gesture(this, arguments),
35448 touches$$1 = event.changedTouches,
35450 n = touches$$1.length, i, t, p;
35453 for (i = 0; i < n; ++i) {
35454 t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
35455 p = [p, this.__zoom.invert(p), t.identifier];
35456 if (!g.touch0) g.touch0 = p, started = true;
35457 else if (!g.touch1) g.touch1 = p;
35460 // If this is a dbltap, reroute to the (optional) dblclick.zoom handler.
35461 if (touchstarting) {
35462 touchstarting = clearTimeout(touchstarting);
35465 p = select(this).on("dblclick.zoom");
35466 if (p) p.apply(this, arguments);
35472 touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay);
35478 function touchmoved() {
35479 var g = gesture(this, arguments),
35480 touches$$1 = event.changedTouches,
35481 n = touches$$1.length, i, t, p, l;
35484 if (touchstarting) touchstarting = clearTimeout(touchstarting);
35485 for (i = 0; i < n; ++i) {
35486 t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
35487 if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;
35488 else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
35492 var p0 = g.touch0[0], l0 = g.touch0[1],
35493 p1 = g.touch1[0], l1 = g.touch1[1],
35494 dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
35495 dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
35496 t = scale(t, Math.sqrt(dp / dl));
35497 p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
35498 l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
35500 else if (g.touch0) p = g.touch0[0], l = g.touch0[1];
35502 g.zoom("touch", constrain(translate(t, p, l), g.extent));
35505 function touchended() {
35506 var g = gesture(this, arguments),
35507 touches$$1 = event.changedTouches,
35508 n = touches$$1.length, i, t;
35511 if (touchending) clearTimeout(touchending);
35512 touchending = setTimeout(function() { touchending = null; }, touchDelay);
35513 for (i = 0; i < n; ++i) {
35515 if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;
35516 else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
35518 if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
35519 if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);
35523 zoom.filter = function(_) {
35524 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$12(!!_), zoom) : filter;
35527 zoom.extent = function(_) {
35528 return arguments.length ? (extent = typeof _ === "function" ? _ : constant$12([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
35531 zoom.scaleExtent = function(_) {
35532 return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1];
35535 zoom.translateExtent = function(_) {
35536 return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]];
35539 zoom.duration = function(_) {
35540 return arguments.length ? (duration = +_, zoom) : duration;
35543 zoom.interpolate = function(_) {
35544 return arguments.length ? (interpolate$$1 = _, zoom) : interpolate$$1;
35547 zoom.on = function() {
35548 var value = listeners.on.apply(listeners, arguments);
35549 return value === listeners ? zoom : value;
35557 var index$2 = Object.freeze({
35559 bisect: bisectRight,
35560 bisectRight: bisectRight,
35561 bisectLeft: bisectLeft,
35562 ascending: ascending,
35563 bisector: bisector,
35565 descending: descending,
35566 deviation: deviation,
35568 histogram: histogram,
35569 thresholdFreedmanDiaconis: freedmanDiaconis,
35570 thresholdScott: scott,
35571 thresholdSturges: sturges,
35579 quantile: threshold,
35585 tickIncrement: tickIncrement,
35586 tickStep: tickStep,
35587 transpose: transpose,
35588 variance: variance,
35591 axisRight: axisRight,
35592 axisBottom: axisBottom,
35593 axisLeft: axisLeft,
35597 brushSelection: brushSelection,
35611 cubehelix: cubehelix,
35612 dispatch: dispatch,
35614 dragDisable: dragDisable,
35615 dragEnable: yesdrag,
35617 csvParse: csvParse,
35618 csvParseRows: csvParseRows,
35619 csvFormat: csvFormat,
35620 csvFormatRows: csvFormatRows,
35621 tsvParse: tsvParse,
35622 tsvParseRows: tsvParseRows,
35623 tsvFormat: tsvFormat,
35624 tsvFormatRows: tsvFormatRows,
35625 easeLinear: linear$1,
35626 easeQuad: quadInOut,
35627 easeQuadIn: quadIn,
35628 easeQuadOut: quadOut,
35629 easeQuadInOut: quadInOut,
35630 easeCubic: cubicInOut,
35631 easeCubicIn: cubicIn,
35632 easeCubicOut: cubicOut,
35633 easeCubicInOut: cubicInOut,
35634 easePoly: polyInOut,
35635 easePolyIn: polyIn,
35636 easePolyOut: polyOut,
35637 easePolyInOut: polyInOut,
35640 easeSinOut: sinOut,
35641 easeSinInOut: sinInOut,
35644 easeExpOut: expOut,
35645 easeExpInOut: expInOut,
35646 easeCircle: circleInOut,
35647 easeCircleIn: circleIn,
35648 easeCircleOut: circleOut,
35649 easeCircleInOut: circleInOut,
35650 easeBounce: bounceOut,
35651 easeBounceIn: bounceIn,
35652 easeBounceOut: bounceOut,
35653 easeBounceInOut: bounceInOut,
35654 easeBack: backInOut,
35655 easeBackIn: backIn,
35656 easeBackOut: backOut,
35657 easeBackInOut: backInOut,
35658 easeElastic: elasticOut,
35659 easeElasticIn: elasticIn,
35660 easeElasticOut: elasticOut,
35661 easeElasticInOut: elasticInOut,
35662 forceCenter: center$1,
35663 forceCollide: collide,
35665 forceManyBody: manyBody,
35666 forceSimulation: simulation,
35669 formatDefaultLocale: defaultLocale,
35670 get format () { return format; },
35671 get formatPrefix () { return formatPrefix; },
35672 formatLocale: formatLocale,
35673 formatSpecifier: formatSpecifier,
35674 precisionFixed: precisionFixed,
35675 precisionPrefix: precisionPrefix,
35676 precisionRound: precisionRound,
35679 geoCentroid: d3GeoCentroid,
35681 geoClipExtent: extent$1,
35682 geoContains: contains,
35683 geoDistance: distance,
35684 geoGraticule: graticule,
35685 geoGraticule10: graticule10,
35686 geoInterpolate: interpolate$1,
35687 geoLength: d3GeoLength,
35690 geoAlbersUsa: albersUsa,
35691 geoAzimuthalEqualArea: azimuthalEqualArea,
35692 geoAzimuthalEqualAreaRaw: azimuthalEqualAreaRaw,
35693 geoAzimuthalEquidistant: azimuthalEquidistant,
35694 geoAzimuthalEquidistantRaw: azimuthalEquidistantRaw,
35695 geoConicConformal: conicConformal,
35696 geoConicConformalRaw: conicConformalRaw,
35697 geoConicEqualArea: conicEqualArea,
35698 geoConicEqualAreaRaw: conicEqualAreaRaw,
35699 geoConicEquidistant: conicEquidistant,
35700 geoConicEquidistantRaw: conicEquidistantRaw,
35701 geoEquirectangular: equirectangular,
35702 geoEquirectangularRaw: equirectangularRaw,
35703 geoGnomonic: gnomonic,
35704 geoGnomonicRaw: gnomonicRaw,
35705 geoIdentity: identity$5,
35706 geoProjection: projection,
35707 geoProjectionMutator: projectionMutator,
35708 geoMercator: mercator,
35709 geoMercatorRaw: mercatorRaw,
35710 geoOrthographic: orthographic,
35711 geoOrthographicRaw: orthographicRaw,
35712 geoStereographic: stereographic,
35713 geoStereographicRaw: stereographicRaw,
35714 geoTransverseMercator: transverseMercator,
35715 geoTransverseMercatorRaw: transverseMercatorRaw,
35716 geoRotation: rotation,
35717 geoStream: geoStream,
35718 geoTransform: transform,
35720 hierarchy: hierarchy,
35722 packSiblings: siblings,
35723 packEnclose: enclose,
35724 partition: partition,
35725 stratify: stratify,
35728 treemapBinary: binary,
35729 treemapDice: treemapDice,
35730 treemapSlice: treemapSlice,
35731 treemapSliceDice: sliceDice,
35732 treemapSquarify: squarify,
35733 treemapResquarify: resquarify,
35734 interpolate: interpolateValue,
35735 interpolateArray: array$1,
35736 interpolateBasis: basis$1,
35737 interpolateBasisClosed: basisClosed,
35738 interpolateDate: date,
35739 interpolateNumber: reinterpolate,
35740 interpolateObject: object,
35741 interpolateRound: interpolateRound,
35742 interpolateString: interpolateString,
35743 interpolateTransformCss: interpolateTransformCss,
35744 interpolateTransformSvg: interpolateTransformSvg,
35745 interpolateZoom: interpolateZoom,
35746 interpolateRgb: interpolateRgb,
35747 interpolateRgbBasis: rgbBasis,
35748 interpolateRgbBasisClosed: rgbBasisClosed,
35749 interpolateHsl: hsl$2,
35750 interpolateHslLong: hslLong,
35751 interpolateLab: lab$1,
35752 interpolateHcl: hcl$2,
35753 interpolateHclLong: hclLong,
35754 interpolateCubehelix: cubehelix$2,
35755 interpolateCubehelixLong: cubehelixLong,
35756 quantize: quantize,
35758 polygonArea: d3polygonArea,
35759 polygonCentroid: d3polygonCentroid,
35760 polygonHull: d3polygonHull,
35761 polygonContains: contains$1,
35762 polygonLength: length$1,
35763 quadtree: quadtree,
35765 randomUniform: uniform,
35766 randomNormal: normal,
35767 randomLogNormal: logNormal,
35768 randomBates: bates,
35769 randomIrwinHall: irwinHall,
35770 randomExponential: exponential$1,
35779 scalePoint: point$1,
35780 scaleIdentity: identity$6,
35781 scaleLinear: linear$2,
35783 scaleOrdinal: ordinal,
35784 scaleImplicit: implicit,
35787 scaleQuantile: quantile$$1,
35788 scaleQuantize: quantize$1,
35789 scaleThreshold: threshold$1,
35792 schemeCategory10: category10,
35793 schemeCategory20b: category20b,
35794 schemeCategory20c: category20c,
35795 schemeCategory20: category20,
35796 interpolateCubehelixDefault: cubehelix$3,
35797 interpolateRainbow: rainbow$1,
35798 interpolateWarm: warm,
35799 interpolateCool: cool,
35800 interpolateViridis: viridis,
35801 interpolateMagma: magma,
35802 interpolateInferno: inferno,
35803 interpolatePlasma: plasma,
35804 scaleSequential: sequential,
35807 matcher: matcher$1,
35809 namespace: namespace,
35810 namespaces: namespaces,
35812 selectAll: selectAll,
35813 selection: selection,
35814 selector: selector,
35815 selectorAll: selectorAll,
35819 get event () { return event; },
35820 customEvent: customEvent,
35825 radialArea: radialArea,
35826 radialLine: radialLine$1,
35829 symbolCircle: circle$2,
35830 symbolCross: cross$2,
35831 symbolDiamond: diamond,
35832 symbolSquare: square,
35834 symbolTriangle: triangle,
35836 curveBasisClosed: basisClosed$1,
35837 curveBasisOpen: basisOpen,
35838 curveBasis: basis$2,
35839 curveBundle: bundle,
35840 curveCardinalClosed: cardinalClosed,
35841 curveCardinalOpen: cardinalOpen,
35842 curveCardinal: cardinal,
35843 curveCatmullRomClosed: catmullRomClosed,
35844 curveCatmullRomOpen: catmullRomOpen,
35845 curveCatmullRom: catmullRom,
35846 curveLinearClosed: linearClosed,
35847 curveLinear: curveLinear,
35848 curveMonotoneX: monotoneX,
35849 curveMonotoneY: monotoneY,
35850 curveNatural: natural,
35852 curveStepAfter: stepAfter,
35853 curveStepBefore: stepBefore,
35855 stackOffsetExpand: expand,
35856 stackOffsetNone: none$1,
35857 stackOffsetSilhouette: silhouette,
35858 stackOffsetWiggle: wiggle,
35859 stackOrderAscending: ascending$2,
35860 stackOrderDescending: descending$2,
35861 stackOrderInsideOut: insideOut,
35862 stackOrderNone: none$2,
35863 stackOrderReverse: reverse,
35864 timeInterval: newInterval,
35865 timeMillisecond: millisecond,
35866 timeMilliseconds: milliseconds,
35867 utcMillisecond: millisecond,
35868 utcMilliseconds: milliseconds,
35869 timeSecond: second,
35870 timeSeconds: seconds,
35872 utcSeconds: seconds,
35873 timeMinute: minute,
35874 timeMinutes: minutes,
35880 timeWeeks: sundays,
35881 timeSunday: sunday,
35882 timeSundays: sundays,
35883 timeMonday: monday,
35884 timeMondays: mondays,
35885 timeTuesday: tuesday,
35886 timeTuesdays: tuesdays,
35887 timeWednesday: wednesday,
35888 timeWednesdays: wednesdays,
35889 timeThursday: thursday,
35890 timeThursdays: thursdays,
35891 timeFriday: friday,
35892 timeFridays: fridays,
35893 timeSaturday: saturday,
35894 timeSaturdays: saturdays,
35896 timeMonths: months,
35899 utcMinute: utcMinute,
35900 utcMinutes: utcMinutes,
35902 utcHours: utcHours,
35905 utcWeek: utcSunday,
35906 utcWeeks: utcSundays,
35907 utcSunday: utcSunday,
35908 utcSundays: utcSundays,
35909 utcMonday: utcMonday,
35910 utcMondays: utcMondays,
35911 utcTuesday: utcTuesday,
35912 utcTuesdays: utcTuesdays,
35913 utcWednesday: utcWednesday,
35914 utcWednesdays: utcWednesdays,
35915 utcThursday: utcThursday,
35916 utcThursdays: utcThursdays,
35917 utcFriday: utcFriday,
35918 utcFridays: utcFridays,
35919 utcSaturday: utcSaturday,
35920 utcSaturdays: utcSaturdays,
35921 utcMonth: utcMonth,
35922 utcMonths: utcMonths,
35924 utcYears: utcYears,
35925 timeFormatDefaultLocale: defaultLocale$1,
35926 get timeFormat () { return timeFormat; },
35927 get timeParse () { return timeParse; },
35928 get utcFormat () { return utcFormat; },
35929 get utcParse () { return utcParse; },
35930 timeFormatLocale: formatLocale$1,
35931 isoFormat: formatIso,
35932 isoParse: parseIso,
35935 timerFlush: timerFlush,
35936 timeout: timeout$1,
35937 interval: interval$1,
35938 transition: transition,
35940 interrupt: interrupt,
35943 zoomTransform: transform$1,
35944 zoomIdentity: identity$8
35948 Bypasses features of D3's default projection stream pipeline that are unnecessary:
35949 * Antimeridian clipping
35950 * Spherical rotation
35953 function geoRawMercator() {
35954 var project = mercatorRaw,
35955 k = 512 / Math.PI, // scale
35956 x = 0, y = 0, // translate
35957 clipExtent = [[0, 0], [0, 0]];
35960 function projection(point) {
35961 point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
35962 return [point[0] * k + x, y - point[1] * k];
35966 projection.invert = function(point) {
35967 point = project.invert((point[0] - x) / k, (y - point[1]) / k);
35968 return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
35972 projection.scale = function(_) {
35973 if (!arguments.length) return k;
35979 projection.translate = function(_) {
35980 if (!arguments.length) return [x, y];
35987 projection.clipExtent = function(_) {
35988 if (!arguments.length) return clipExtent;
35994 projection.transform = function(_) {
35995 if (!arguments.length) return identity$8.translate(x, y).scale(k);
36003 projection.stream = transform({
36004 point: function(x, y) {
36005 x = projection([x, y]);
36006 this.stream.point(x[0], x[1]);
36014 function osmChangeset() {
36015 if (!(this instanceof osmChangeset)) {
36016 return (new osmChangeset()).initialize(arguments);
36017 } else if (arguments.length) {
36018 this.initialize(arguments);
36023 osmEntity$$1.changeset = osmChangeset;
36025 osmChangeset.prototype = Object.create(osmEntity$$1.prototype);
36027 lodash.extend(osmChangeset.prototype, {
36032 extent: function() {
36033 return new geoExtent$$1();
36037 geometry: function() {
36038 return 'changeset';
36042 asJXON: function() {
36046 tag: lodash.map(this.tags, function(value, key) {
36047 return { '@k': key, '@v': value };
36057 // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
36058 // XML. Returns a string.
36059 osmChangeJXON: function(changes) {
36060 var changeset_id = this.id;
36062 function nest(x, order) {
36064 for (var i = 0; i < x.length; i++) {
36065 var tagName = Object.keys(x[i])[0];
36066 if (!groups[tagName]) groups[tagName] = [];
36067 groups[tagName].push(x[i][tagName]);
36070 order.forEach(function(o) {
36071 if (groups[o]) ordered[o] = groups[o];
36077 // sort relations in a changeset by dependencies
36078 function sort(changes) {
36080 // find a referenced relation in the current changeset
36081 function resolve(item) {
36082 return lodash.find(relations, function(relation) {
36083 return item.keyAttributes.type === 'relation'
36084 && item.keyAttributes.ref === relation['@id'];
36088 // a new item is an item that has not been already processed
36089 function isNew(item) {
36090 return !sorted[ item['@id'] ] && !lodash.find(processing, function(proc) {
36091 return proc['@id'] === item['@id'];
36095 var processing = [],
36097 relations = changes.relation;
36099 if (!relations) return changes;
36101 for (var i = 0; i < relations.length; i++) {
36102 var relation = relations[i];
36104 // skip relation if already sorted
36105 if (!sorted[relation['@id']]) {
36106 processing.push(relation);
36109 while (processing.length > 0) {
36110 var next = processing[0],
36111 deps = lodash.filter(lodash.compact(next.member.map(resolve)), isNew);
36112 if (deps.length === 0) {
36113 sorted[next['@id']] = next;
36114 processing.shift();
36116 processing = deps.concat(processing);
36121 changes.relation = lodash.values(sorted);
36125 function rep(entity) {
36126 return entity.asJXON(changeset_id);
36132 '@generator': 'iD',
36133 'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])),
36134 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
36135 'delete': lodash.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), { '@if-unused': true })
36141 asGeoJSON: function() {
36147 function osmNode() {
36148 if (!(this instanceof osmNode)) {
36149 return (new osmNode()).initialize(arguments);
36150 } else if (arguments.length) {
36151 this.initialize(arguments);
36155 osmEntity$$1.node = osmNode;
36157 osmNode.prototype = Object.create(osmEntity$$1.prototype);
36159 lodash.extend(osmNode.prototype, {
36164 extent: function() {
36165 return new geoExtent$$1(this.loc);
36169 geometry: function(graph) {
36170 return graph.transient(this, 'geometry', function() {
36171 return graph.isPoi(this) ? 'point' : 'vertex';
36176 move: function(loc) {
36177 return this.update({loc: loc});
36181 isDegenerate: function() {
36183 Array.isArray(this.loc) && this.loc.length === 2 &&
36184 this.loc[0] >= -180 && this.loc[0] <= 180 &&
36185 this.loc[1] >= -90 && this.loc[1] <= 90
36190 isEndpoint: function(resolver) {
36191 return resolver.transient(this, 'isEndpoint', function() {
36193 return resolver.parentWays(this).filter(function(parent) {
36194 return !parent.isClosed() && !!parent.affix(id);
36200 isConnected: function(resolver) {
36201 return resolver.transient(this, 'isConnected', function() {
36202 var parents = resolver.parentWays(this);
36204 function isLine(entity) {
36205 return entity.geometry(resolver) === 'line' &&
36206 entity.hasInterestingTags();
36209 // vertex is connected to multiple parent lines
36210 if (parents.length > 1 && lodash.some(parents, isLine)) {
36213 } else if (parents.length === 1) {
36214 var way = parents[0],
36215 nodes = way.nodes.slice();
36216 if (way.isClosed()) { nodes.pop(); } // ignore connecting node if closed
36218 // return true if vertex appears multiple times (way is self intersecting)
36219 return nodes.indexOf(this.id) !== nodes.lastIndexOf(this.id);
36227 isIntersection: function(resolver) {
36228 return resolver.transient(this, 'isIntersection', function() {
36229 return resolver.parentWays(this).filter(function(parent) {
36230 return (parent.tags.highway ||
36231 parent.tags.waterway ||
36232 parent.tags.railway ||
36233 parent.tags.aeroway) &&
36234 parent.geometry(resolver) === 'line';
36240 isHighwayIntersection: function(resolver) {
36241 return resolver.transient(this, 'isHighwayIntersection', function() {
36242 return resolver.parentWays(this).filter(function(parent) {
36243 return parent.tags.highway && parent.geometry(resolver) === 'line';
36249 isOnAddressLine: function(resolver) {
36250 return resolver.transient(this, 'isOnAddressLine', function() {
36251 return resolver.parentWays(this).filter(function(parent) {
36252 return parent.tags.hasOwnProperty('addr:interpolation') &&
36253 parent.geometry(resolver) === 'line';
36259 asJXON: function(changeset_id) {
36262 '@id': this.osmId(),
36263 '@lon': this.loc[0],
36264 '@lat': this.loc[1],
36265 '@version': (this.version || 0),
36266 tag: lodash.map(this.tags, function(v, k) {
36267 return { keyAttributes: { k: k, v: v } };
36271 if (changeset_id) r.node['@changeset'] = changeset_id;
36276 asGeoJSON: function() {
36279 coordinates: this.loc
36285 Order the nodes of a way in reverse order and reverse any direction dependent tags
36286 other than `oneway`. (We assume that correcting a backwards oneway is the primary
36287 reason for reversing a way.)
36289 The following transforms are performed:
36292 *:right=* ⟺ *:left=*
36293 *:forward=* ⟺ *:backward=*
36294 direction=up ⟺ direction=down
36295 incline=up ⟺ incline=down
36299 role=forward ⟺ role=backward
36300 role=north ⟺ role=south
36301 role=east ⟺ role=west
36303 In addition, numeric-valued `incline` tags are negated.
36305 The JOSM implementation was used as a guide, but transformations that were of unclear benefit
36306 or adjusted tags that don't seem to be used in practice were omitted.
36308 Also, each node on the way is examined for its own tags and the following transformations are performed
36309 in order to ensure associated nodes (eg a Stop Sign) is also reversed
36312 direction=forward ⟺ direction=backward
36313 direction=left ⟺ direction=right
36314 *:forward=* ⟺ *:backward=*
36315 *:left=* ⟺ *:right=*
36318 http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
36319 http://wiki.openstreetmap.org/wiki/Key:direction#Steps
36320 http://wiki.openstreetmap.org/wiki/Key:incline
36321 http://wiki.openstreetmap.org/wiki/Route#Members
36322 http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
36323 http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
36324 http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
36326 function actionReverse(wayId, options) {
36327 var replacements = [
36328 [/:right$/, ':left'], [/:left$/, ':right'],
36329 [/:forward$/, ':backward'], [/:backward$/, ':forward']
36331 numeric = /^([+\-]?)(?=[\d.])/,
36333 forward: 'backward',
36334 backward: 'forward',
36342 function reverseKey(key) {
36343 for (var i = 0; i < replacements.length; ++i) {
36344 var replacement = replacements[i];
36345 if (replacement[0].test(key)) {
36346 return key.replace(replacement[0], replacement[1]);
36353 function reverseValue(key, value) {
36354 if (key === 'incline' && numeric.test(value)) {
36355 return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
36356 } else if (key === 'incline' || key === 'direction') {
36357 return {up: 'down', down: 'up'}[value] || value;
36358 } else if (options && options.reverseOneway && key === 'oneway') {
36359 return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
36361 return {left: 'right', right: 'left'}[value] || value;
36366 function reverseDirectionTags(node) {
36367 // Update the direction based tags as appropriate then return an updated node
36368 return node.update({tags: lodash.transform(node.tags, function(acc, tagValue, tagKey) {
36369 // See if this is a direction tag and reverse (or use existing value if not recognised)
36370 if (tagKey === 'direction') {
36371 acc[tagKey] = {forward: 'backward', backward: 'forward', left: 'right', right: 'left'}[tagValue] || tagValue;
36373 // Use the reverseKey method to cater for situations such as traffic_sign:forward=stop
36374 // This will pass through other tags unchanged
36375 acc[reverseKey(tagKey)] = tagValue;
36382 function reverseTagsOnNodes(graph, nodeIds) {
36383 // Reverse the direction of appropriate tags attached to the nodes (#3076)
36384 return lodash(nodeIds)
36385 // Get each node from the graph
36386 .map(function(nodeId) { return graph.entity(nodeId);})
36387 // Check tags on the node, if there aren't any, we can skip
36388 .filter(function(existingNode) { return existingNode.tags !== undefined;})
36389 // Get a new version of each node with the appropriate tags reversed
36390 .map(function(existingNode) { return reverseDirectionTags(existingNode);})
36391 // Chain together consecutive updates to the graph for each updated node and return
36392 .reduce(function (accGraph, value) { return accGraph.replace(value); }, graph);
36396 return function(graph) {
36397 var way = graph.entity(wayId),
36398 nodes = way.nodes.slice().reverse(),
36399 tags = {}, key, role;
36401 for (key in way.tags) {
36402 tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
36405 graph.parentRelations(way).forEach(function(relation) {
36406 relation.members.forEach(function(member, index) {
36407 if (member.id === way.id && (role = roleReversals[member.role])) {
36408 relation = relation.updateMember({role: role}, index);
36409 graph = graph.replace(relation);
36414 // Reverse any associated directions on nodes on the way and then replace
36415 // the way itself with the reversed node ids and updated way tags
36416 return reverseTagsOnNodes(graph, nodes).replace(way.update({nodes: nodes, tags: tags}));
36420 // For fixing up rendering of multipolygons with tags on the outer member.
36421 // https://github.com/openstreetmap/iD/issues/613
36422 function osmIsSimpleMultipolygonOuterMember(entity, graph) {
36423 if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0)
36426 var parents = graph.parentRelations(entity);
36427 if (parents.length !== 1)
36430 var parent = parents[0];
36431 if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
36434 var members = parent.members, member;
36435 for (var i = 0; i < members.length; i++) {
36436 member = members[i];
36437 if (member.id === entity.id && member.role && member.role !== 'outer')
36438 return false; // Not outer member
36439 if (member.id !== entity.id && (!member.role || member.role === 'outer'))
36440 return false; // Not a simple multipolygon
36447 function osmSimpleMultipolygonOuterMember(entity, graph) {
36448 if (entity.type !== 'way')
36451 var parents = graph.parentRelations(entity);
36452 if (parents.length !== 1)
36455 var parent = parents[0];
36456 if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
36459 var members = parent.members, member, outerMember;
36460 for (var i = 0; i < members.length; i++) {
36461 member = members[i];
36462 if (!member.role || member.role === 'outer') {
36464 return false; // Not a simple multipolygon
36465 outerMember = member;
36472 var outerEntity = graph.hasEntity(outerMember.id);
36473 if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length)
36476 return outerEntity;
36480 // Join `array` into sequences of connecting ways.
36482 // Segments which share identical start/end nodes will, as much as possible,
36483 // be connected with each other.
36485 // The return value is a nested array. Each constituent array contains elements
36486 // of `array` which have been determined to connect. Each consitituent array
36487 // also has a `nodes` property whose value is an ordered array of member nodes,
36488 // with appropriate order reversal and start/end coordinate de-duplication.
36490 // Members of `array` must have, at minimum, `type` and `id` properties.
36491 // Thus either an array of `osmWay`s or a relation member array may be
36494 // If an member has a `tags` property, its tags will be reversed via
36495 // `actionReverse` in the output.
36497 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
36498 // false) and non-way members are ignored.
36500 function osmJoinWays(array, graph) {
36501 var joined = [], member, current, nodes, first, last, i, how, what;
36503 array = array.filter(function(member) {
36504 return member.type === 'way' && graph.hasEntity(member.id);
36507 function resolve(member) {
36508 return graph.childNodes(graph.entity(member.id));
36511 function reverse(member) {
36512 return member.tags ? actionReverse(member.id, { reverseOneway: true })(graph).entity(member.id) : member;
36515 while (array.length) {
36516 member = array.shift();
36517 current = [member];
36518 current.nodes = nodes = resolve(member).slice();
36519 joined.push(current);
36521 while (array.length && lodash.first(nodes) !== lodash.last(nodes)) {
36522 first = lodash.first(nodes);
36523 last = lodash.last(nodes);
36525 for (i = 0; i < array.length; i++) {
36527 what = resolve(member);
36529 if (last === lodash.first(what)) {
36531 what = what.slice(1);
36533 } else if (last === lodash.last(what)) {
36535 what = what.slice(0, -1).reverse();
36536 member = reverse(member);
36538 } else if (first === lodash.last(what)) {
36539 how = nodes.unshift;
36540 what = what.slice(0, -1);
36542 } else if (first === lodash.first(what)) {
36543 how = nodes.unshift;
36544 what = what.slice(1).reverse();
36545 member = reverse(member);
36553 break; // No more joinable ways.
36555 how.apply(current, [member]);
36556 how.apply(nodes, what);
36558 array.splice(i, 1);
36565 function osmRelation() {
36566 if (!(this instanceof osmRelation)) {
36567 return (new osmRelation()).initialize(arguments);
36568 } else if (arguments.length) {
36569 this.initialize(arguments);
36574 osmEntity$$1.relation = osmRelation;
36576 osmRelation.prototype = Object.create(osmEntity$$1.prototype);
36579 osmRelation.creationOrder = function(a, b) {
36580 var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10);
36581 var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10);
36583 if (aId < 0 || bId < 0) return aId - bId;
36588 lodash.extend(osmRelation.prototype, {
36593 copy: function(resolver, copies) {
36594 if (copies[this.id])
36595 return copies[this.id];
36597 var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
36599 var members = this.members.map(function(member) {
36600 return lodash.extend({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id });
36603 copy = copy.update({members: members});
36604 copies[this.id] = copy;
36610 extent: function(resolver, memo) {
36611 return resolver.transient(this, 'extent', function() {
36612 if (memo && memo[this.id]) return geoExtent$$1();
36614 memo[this.id] = true;
36616 var extent$$1 = geoExtent$$1();
36617 for (var i = 0; i < this.members.length; i++) {
36618 var member = resolver.hasEntity(this.members[i].id);
36620 extent$$1._extend(member.extent(resolver, memo));
36628 geometry: function(graph) {
36629 return graph.transient(this, 'geometry', function() {
36630 return this.isMultipolygon() ? 'area' : 'relation';
36635 isDegenerate: function() {
36636 return this.members.length === 0;
36640 // Return an array of members, each extended with an 'index' property whose value
36641 // is the member index.
36642 indexedMembers: function() {
36643 var result = new Array(this.members.length);
36644 for (var i = 0; i < this.members.length; i++) {
36645 result[i] = lodash.extend({}, this.members[i], {index: i});
36651 // Return the first member with the given role. A copy of the member object
36652 // is returned, extended with an 'index' property whose value is the member index.
36653 memberByRole: function(role) {
36654 for (var i = 0; i < this.members.length; i++) {
36655 if (this.members[i].role === role) {
36656 return lodash.extend({}, this.members[i], {index: i});
36662 // Return the first member with the given id. A copy of the member object
36663 // is returned, extended with an 'index' property whose value is the member index.
36664 memberById: function(id) {
36665 for (var i = 0; i < this.members.length; i++) {
36666 if (this.members[i].id === id) {
36667 return lodash.extend({}, this.members[i], {index: i});
36673 // Return the first member with the given id and role. A copy of the member object
36674 // is returned, extended with an 'index' property whose value is the member index.
36675 memberByIdAndRole: function(id, role) {
36676 for (var i = 0; i < this.members.length; i++) {
36677 if (this.members[i].id === id && this.members[i].role === role) {
36678 return lodash.extend({}, this.members[i], {index: i});
36684 addMember: function(member, index) {
36685 var members = this.members.slice();
36686 members.splice(index === undefined ? members.length : index, 0, member);
36687 return this.update({members: members});
36691 updateMember: function(member, index) {
36692 var members = this.members.slice();
36693 members.splice(index, 1, lodash.extend({}, members[index], member));
36694 return this.update({members: members});
36698 removeMember: function(index) {
36699 var members = this.members.slice();
36700 members.splice(index, 1);
36701 return this.update({members: members});
36705 removeMembersWithID: function(id) {
36706 var members = lodash.reject(this.members, function(m) { return m.id === id; });
36707 return this.update({members: members});
36711 // Wherever a member appears with id `needle.id`, replace it with a member
36712 // with id `replacement.id`, type `replacement.type`, and the original role,
36713 // unless a member already exists with that id and role. Return an updated
36715 replaceMember: function(needle, replacement) {
36716 if (!this.memberById(needle.id))
36721 for (var i = 0; i < this.members.length; i++) {
36722 var member = this.members[i];
36723 if (member.id !== needle.id) {
36724 members.push(member);
36725 } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
36726 members.push({id: replacement.id, type: replacement.type, role: member.role});
36730 return this.update({members: members});
36734 asJXON: function(changeset_id) {
36737 '@id': this.osmId(),
36738 '@version': this.version || 0,
36739 member: lodash.map(this.members, function(member) {
36744 ref: osmEntity$$1.id.toOSM(member.id)
36748 tag: lodash.map(this.tags, function(v, k) {
36749 return { keyAttributes: { k: k, v: v } };
36753 if (changeset_id) r.relation['@changeset'] = changeset_id;
36758 asGeoJSON: function(resolver) {
36759 return resolver.transient(this, 'GeoJSON', function () {
36760 if (this.isMultipolygon()) {
36762 type: 'MultiPolygon',
36763 coordinates: this.multipolygon(resolver)
36767 type: 'FeatureCollection',
36768 properties: this.tags,
36769 features: this.members.map(function (member) {
36770 return lodash.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
36778 area: function(resolver) {
36779 return resolver.transient(this, 'area', function() {
36780 return area(this.asGeoJSON(resolver));
36785 isMultipolygon: function() {
36786 return this.tags.type === 'multipolygon';
36790 isComplete: function(resolver) {
36791 for (var i = 0; i < this.members.length; i++) {
36792 if (!resolver.hasEntity(this.members[i].id)) {
36800 isRestriction: function() {
36801 return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
36805 // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
36806 // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
36808 // This corresponds to the structure needed for rendering a multipolygon path using a
36809 // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
36811 // In the case of invalid geometries, this function will still return a result which
36812 // includes the nodes of all way members, but some Nds may be unclosed and some inner
36813 // rings not matched with the intended outer ring.
36815 multipolygon: function(resolver) {
36816 var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
36817 inners = this.members.filter(function(m) { return 'inner' === m.role; });
36819 outers = osmJoinWays(outers, resolver);
36820 inners = osmJoinWays(inners, resolver);
36822 outers = outers.map(function(outer) { return lodash.map(outer.nodes, 'loc'); });
36823 inners = inners.map(function(inner) { return lodash.map(inner.nodes, 'loc'); });
36825 var result = outers.map(function(o) {
36826 // Heuristic for detecting counterclockwise winding order. Assumes
36827 // that OpenStreetMap polygons are not hemisphere-spanning.
36828 return [area({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o];
36831 function findOuter(inner) {
36834 for (o = 0; o < outers.length; o++) {
36836 if (geoPolygonContainsPolygon(outer, inner))
36840 for (o = 0; o < outers.length; o++) {
36842 if (geoPolygonIntersectsPolygon(outer, inner, false))
36847 for (var i = 0; i < inners.length; i++) {
36848 var inner = inners[i];
36850 if (area({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) {
36851 inner = inner.reverse();
36854 var o = findOuter(inners[i]);
36855 if (o !== undefined)
36856 result[o].push(inners[i]);
36858 result.push([inners[i]]); // Invalid geometry
36865 function osmLanes(entity) {
36866 if (entity.type !== 'way') return null;
36867 if (!entity.tags.highway) return null;
36869 var tags = entity.tags;
36870 var isOneWay = entity.isOneWay();
36871 var laneCount = getLaneCount(tags, isOneWay);
36872 var maxspeed = parseMaxspeed(tags);
36874 var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
36875 var forward = laneDirections.forward;
36876 var backward = laneDirections.backward;
36877 var bothways = laneDirections.bothways;
36879 // parse the piped string 'x|y|z' format
36880 var turnLanes = {};
36881 turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
36882 turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
36883 turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
36885 var maxspeedLanes = {};
36886 maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
36887 maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
36888 maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
36891 psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
36892 psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
36893 psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
36896 busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
36897 busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
36898 busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
36900 var taxiLanes = {};
36901 taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
36902 taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
36903 taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
36906 hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
36907 hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
36908 hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
36911 hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
36912 hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
36913 hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
36915 var bicyclewayLanes = {};
36916 bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
36917 bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
36918 bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
36926 // map forward/backward/unspecified of each lane type to lanesObj
36927 mapToLanesObj(lanesObj, turnLanes, 'turnLane');
36928 mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
36929 mapToLanesObj(lanesObj, psvLanes, 'psv');
36930 mapToLanesObj(lanesObj, busLanes, 'bus');
36931 mapToLanesObj(lanesObj, taxiLanes, 'taxi');
36932 mapToLanesObj(lanesObj, hovLanes, 'hov');
36933 mapToLanesObj(lanesObj, hgvLanes, 'hgv');
36934 mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
36941 backward: backward,
36942 bothways: bothways,
36943 turnLanes: turnLanes,
36944 maxspeed: maxspeed,
36945 maxspeedLanes: maxspeedLanes,
36946 psvLanes: psvLanes,
36947 busLanes: busLanes,
36948 taxiLanes: taxiLanes,
36949 hovLanes: hovLanes,
36950 hgvLanes: hgvLanes,
36951 bicyclewayLanes: bicyclewayLanes
36958 function getLaneCount(tags, isOneWay) {
36961 count = parseInt(tags.lanes, 10);
36968 switch (tags.highway) {
36971 count = isOneWay ? 2 : 4;
36974 count = isOneWay ? 1 : 2;
36982 function parseMaxspeed(tags) {
36983 var maxspeed = tags.maxspeed;
36984 if (lodash.isNumber(maxspeed)) return maxspeed;
36985 if (lodash.isString(maxspeed)) {
36986 maxspeed = maxspeed.match(/^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/g);
36987 if (!maxspeed) return;
36988 return parseInt(maxspeed, 10);
36993 function parseLaneDirections(tags, isOneWay, laneCount) {
36994 var forward = parseInt(tags['lanes:forward'], 10);
36995 var backward = parseInt(tags['lanes:backward'], 10);
36996 var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
36998 if (parseInt(tags.oneway, 10) === -1) {
37001 backward = laneCount;
37003 else if (isOneWay) {
37004 forward = laneCount;
37008 else if (lodash.isNaN(forward) && lodash.isNaN(backward)) {
37009 backward = Math.floor((laneCount - bothways) / 2);
37010 forward = laneCount - bothways - backward;
37012 else if (lodash.isNaN(forward)) {
37013 if (backward > laneCount - bothways) {
37014 backward = laneCount - bothways;
37016 forward = laneCount - bothways - backward;
37018 else if (lodash.isNaN(backward)) {
37019 if (forward > laneCount - bothways) {
37020 forward = laneCount - bothways;
37022 backward = laneCount - bothways - forward;
37026 backward: backward,
37032 function parseTurnLanes(tag){
37035 var validValues = [
37036 'left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right',
37037 'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'
37040 return tag.split('|')
37041 .map(function (s) {
37042 if (s === '') s = 'none';
37043 return s.split(';')
37044 .map(function (d) {
37045 return validValues.indexOf(d) === -1 ? 'unknown': d;
37051 function parseMaxspeedLanes(tag, maxspeed) {
37054 return tag.split('|')
37055 .map(function (s) {
37056 if (s === 'none') return s;
37057 var m = parseInt(s, 10);
37058 if (s === '' || m === maxspeed) return null;
37059 return lodash.isNaN(m) ? 'unknown': m;
37064 function parseMiscLanes(tag) {
37067 var validValues = [
37068 'yes', 'no', 'designated'
37071 return tag.split('|')
37072 .map(function (s) {
37073 if (s === '') s = 'no';
37074 return validValues.indexOf(s) === -1 ? 'unknown': s;
37079 function parseBicycleWay(tag) {
37082 var validValues = [
37083 'yes', 'no', 'designated', 'lane'
37086 return tag.split('|')
37087 .map(function (s) {
37088 if (s === '') s = 'no';
37089 return validValues.indexOf(s) === -1 ? 'unknown': s;
37094 function mapToLanesObj(lanesObj, data, key) {
37095 if (data.forward) data.forward.forEach(function(l, i) {
37096 if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
37097 lanesObj.forward[i][key] = l;
37099 if (data.backward) data.backward.forEach(function(l, i) {
37100 if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
37101 lanesObj.backward[i][key] = l;
37103 if (data.unspecified) data.unspecified.forEach(function(l, i) {
37104 if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
37105 lanesObj.unspecified[i][key] = l;
37109 var translations = Object.create(null);
37111 var currentLocale = 'en';
37112 var textDirection = 'ltr';
37114 function setLocale(_) {
37115 if (translations[_] !== undefined) {
37117 } else if (translations[_.split('-')[0]]) {
37118 currentLocale = _.split('-')[0];
37122 function addTranslation(id, value) {
37123 translations[id] = value;
37127 * Given a string identifier, try to find that string in the current
37128 * language, and return it.
37130 * @param {string} s string identifier
37131 * @returns {string?} locale string
37133 function t(s, o, loc) {
37134 loc = loc || currentLocale;
37136 var path = s.split('.').reverse();
37137 var rep = translations[loc];
37139 while (rep !== undefined && path.length) rep = rep[path.pop()];
37141 if (rep !== undefined) {
37142 if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
37146 if (loc !== 'en') {
37147 return t(s, o, 'en');
37150 if (o && 'default' in o) {
37154 var missing = 'Missing ' + loc + ' translation: ' + s;
37155 if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
37161 * Given string 'ltr' or 'rtl', save that setting
37163 * @param {string} s ltr or rtl
37166 function setTextDirection(dir) {
37167 textDirection = dir;
37172 function utilDetect(force) {
37173 if (detected && !force) return detected;
37176 var ua = navigator.userAgent,
37179 m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i); // Edge
37181 detected.browser = m[1];
37182 detected.version = m[2];
37184 if (!detected.browser) {
37185 m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11
37187 detected.browser = 'msie';
37188 detected.version = m[1];
37191 if (!detected.browser) {
37192 m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i); // Opera 15+
37194 detected.browser = 'Opera';
37195 detected.version = m[2];
37198 if (!detected.browser) {
37199 m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
37201 detected.browser = m[1];
37202 detected.version = m[2];
37203 m = ua.match(/version\/([\.\d]+)/i);
37204 if (m !== null) detected.version = m[1];
37207 if (!detected.browser) {
37208 detected.browser = navigator.appName;
37209 detected.version = navigator.appVersion;
37212 // keep major.minor version only..
37213 detected.version = detected.version.split(/\W/).slice(0,2).join('.');
37215 if (detected.browser.toLowerCase() === 'msie') {
37216 detected.ie = true;
37217 detected.browser = 'Internet Explorer';
37218 detected.support = parseFloat(detected.version) >= 11;
37220 detected.ie = false;
37221 detected.support = true;
37224 // Added due to incomplete svg style support. See #715
37225 detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
37227 detected.locale = (navigator.language || navigator.userLanguage || 'en-US');
37228 detected.language = detected.locale.split('-')[0];
37230 // Search `navigator.languages` for a better locale.. Prefer the first language,
37231 // unless the second language is a culture-specific version of the first one, see #3842
37232 if (navigator.languages && navigator.languages.length > 0) {
37233 var code0 = navigator.languages[0],
37234 parts0 = code0.split('-');
37236 detected.locale = code0;
37237 detected.language = parts0[0];
37239 if (navigator.languages.length > 1 && parts0.length === 1) {
37240 var code1 = navigator.languages[1],
37241 parts1 = code1.split('-');
37243 if (parts1[0] === parts0[0]) {
37244 detected.locale = code1;
37249 // Loaded locale is stored in currentLocale
37250 // return that instead (except in the situation where 'en' might override 'en-US')
37251 var loadedLocale = currentLocale || 'en';
37252 if (loadedLocale !== 'en') {
37253 detected.locale = loadedLocale;
37254 detected.language = detected.locale.split('-')[0];
37257 // detect text direction
37258 var q = utilStringQs(window.location.hash.substring(1));
37259 var lang = dataLocales[detected.locale];
37260 if ((lang && lang.rtl) || q.hasOwnProperty('rtl')) {
37261 detected.textDirection = 'rtl';
37263 detected.textDirection = 'ltr';
37265 setTextDirection(detected.textDirection);
37268 var loc = window.top.location;
37269 var origin = loc.origin;
37270 if (!origin) { // for unpatched IE11
37271 origin = loc.protocol + '//' + loc.hostname + (loc.port ? ':' + loc.port: '');
37274 detected.host = origin + loc.pathname;
37276 detected.filedrop = (window.FileReader && 'ondrop' in window);
37279 return navigator.userAgent.indexOf(x) !== -1;
37283 detected.os = 'win';
37284 detected.platform = 'Windows';
37286 else if (nav('Mac')) {
37287 detected.os = 'mac';
37288 detected.platform = 'Macintosh';
37290 else if (nav('X11') || nav('Linux')) {
37291 detected.os = 'linux';
37292 detected.platform = 'Linux';
37295 detected.os = 'win';
37296 detected.platform = 'Unknown';
37302 var remove$1 = removeDiacritics;
37304 var replacementList = [
37313 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",
37319 chars: "\u00C6\u01FC\u01E2",
37328 chars: "\uA738\uA73A",
37334 chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181",
37337 chars: "\u24b8\uff23\uA73E\u1E08\u0106\u0043\u0108\u010A\u010C\u00C7\u0187\u023B",
37340 chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779",
37346 chars: "\u01F1\u01C4",
37349 chars: "\u01F2\u01C5",
37352 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",
37355 chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B",
37358 chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262",
37361 chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D",
37364 chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197",
37367 chars: "\u24BF\uFF2A\u0134\u0248\u0237",
37370 chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2",
37373 chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780",
37382 chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB",
37385 chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E",
37394 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",
37409 chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754",
37412 chars: "\u24C6\uFF31\uA756\uA758\u024A",
37415 chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782",
37418 chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784",
37421 chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786",
37430 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",
37433 chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245",
37439 chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72",
37442 chars: "\u24CD\uFF38\u1E8A\u1E8C",
37445 chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE",
37448 chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762",
37451 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",
37457 chars: "\u00E6\u01FD\u01E3",
37466 chars: "\uA739\uA73B",
37472 chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182",
37475 chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184",
37478 chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA",
37484 chars: "\u01F3\u01C6",
37487 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",
37490 chars: "\u24D5\uFF46\u1E1F\u0192",
37508 chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79",
37511 chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265",
37517 chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131",
37520 chars: "\u24D9\uFF4A\u0135\u01F0\u0249",
37523 chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3",
37526 chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D",
37532 chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F",
37535 chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509",
37541 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",
37556 chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1",
37559 chars: "\u24E0\uFF51\u024B\uA757\uA759",
37562 chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783",
37565 chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282",
37571 chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787",
37580 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",
37583 chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C",
37589 chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73",
37592 chars: "\u24E7\uFF58\u1E8B\u1E8D",
37595 chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF",
37598 chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763",
37602 var diacriticsMap = {};
37603 for (var i = 0; i < replacementList.length; i += 1) {
37604 var chars = replacementList[i].chars;
37605 for (var j = 0; j < chars.length; j += 1) {
37606 diacriticsMap[chars[j]] = replacementList[i].base;
37610 function removeDiacritics(str) {
37611 return str.replace(/[^\u0000-\u007e]/g, function(c) {
37612 return diacriticsMap[c] || c;
37616 // see https://github.com/openstreetmap/iD/pull/3707
37617 // https://gist.github.com/mapmeld/556b09ddec07a2044c76e1ef45f01c60
37620 // madda above alef
37621 1570: { initial: 'آ', isolated: 'ﺁ', medial: 'ﺁ', final: 'ﺂ' },
37623 // hamza above and below alef
37624 1571: { initial: 'أ', isolated: 'ﺃ', medial: '', final: 'ﺄ' },
37626 1573: { initial: 'إ', isolated: 'ﺇ', medial: '', final: 'ﺈ' },
37628 1575: { initial: 'ا', isolated: 'ا', medial: '', final: 'ﺎ' },
37629 1576: { initial: 'ﺑ', isolated: 'ﺏ', medial: 'ﺒ', final: 'ﺐ' },
37632 1577: { initial: '', isolated: 'ة', medial: '', final: 'ﺔ' },
37634 1578: { initial: 'ﺗ', isolated: 'ﺕ', medial: 'ﺘ', final: 'ﺖ' },
37635 1579: { initial: 'ﺛ', isolated: 'ﺙ', medial: 'ﺜ', final: 'ﺚ' },
37636 1580: { initial: 'ﺟ', isolated: 'ﺝ', medial: 'ﺠ', final: 'ﺞ' },
37637 1581: { initial: 'ﺣ', isolated: 'ﺡ', medial: 'ﺤ', final: 'ﺢ' },
37638 1582: { initial: 'ﺧ', isolated: 'ﺥ', medial: 'ﺨ', final: 'ﺦ' },
37639 1583: { initial: 'ﺩ', isolated: 'ﺩ', medial: '', final: 'ﺪ' },
37640 1584: { initial: 'ﺫ', isolated: 'ﺫ', medial: '', final: 'ﺬ' },
37641 1585: { initial: 'ﺭ', isolated: 'ﺭ', medial: '', final: 'ﺮ' },
37642 1586: { initial: 'ﺯ', isolated: 'ﺯ', medial: '', final: 'ﺰ' },
37643 1688: { initial: 'ﮊ', isolated: 'ﮊ', medial: '', final: 'ﮋ' },
37644 1587: { initial: 'ﺳ', isolated: 'ﺱ', medial: 'ﺴ', final: 'ﺲ' },
37645 1588: { initial: 'ﺷ', isolated: 'ﺵ', medial: 'ﺸ', final: 'ﺶ' },
37646 1589: { initial: 'ﺻ', isolated: 'ﺹ', medial: 'ﺼ', final: 'ﺺ' },
37647 1590: { initial: 'ﺿ', isolated: 'ﺽ', medial: 'ﻀ', final: 'ﺾ' },
37648 1591: { initial: 'ﻃ', isolated: 'ﻁ', medial: 'ﻄ', final: 'ﻂ' },
37649 1592: { initial: 'ﻇ', isolated: 'ﻅ', medial: 'ﻈ', final: 'ﻆ' },
37650 1593: { initial: 'ﻋ', isolated: 'ﻉ', medial: 'ﻌ', final: 'ﻊ' },
37651 1594: { initial: 'ﻏ', isolated: 'ﻍ', medial: 'ﻐ', final: 'ﻎ' },
37653 // 1595 ػ - may be very rare
37655 1601: { initial: 'ﻓ', isolated: 'ﻑ', medial: 'ﻔ', final: 'ﻒ' },
37656 1602: { initial: 'ﻗ', isolated: 'ﻕ', medial: 'ﻘ', final: 'ﻖ' },
37657 1604: { initial: 'ﻟ', isolated: 'ﻝ', medial: 'ﻠ', final: 'ﻞ' },
37658 1605: { initial: 'ﻣ', isolated: 'ﻡ', medial: 'ﻤ', final: 'ﻢ' },
37659 1606: { initial: 'ﻧ', isolated: 'ﻥ', medial: 'ﻨ', final: 'ﻦ' },
37660 1607: { initial: 'ﻫ', isolated: 'ﻩ', medial: 'ﻬ', final: 'ﻪ' },
37661 1608: { initial: 'ﻭ', isolated: 'ﻭ', medial: '', final: 'ﻮ' },
37664 1609: { initial: 'ﯨ', isolated: 'ﻯ', medial: 'ﯩ', final: 'ﻰ' },
37666 1610: { initial: 'ﻳ', isolated: 'ﻱ', medial: 'ﻴ', final: 'ﻲ' },
37668 // short vowel sounds / tashkil markings
37670 1662: { initial: 'ﭘ', isolated: 'ﭖ', medial: 'ﭙ', final: 'ﭗ' },
37672 1670: { initial: 'ﭼ', isolated: 'ﭺ', medial: 'ﭽ', final: 'ﭻ' },
37673 1603: { initial: 'ﻛ', isolated: 'ﻙ', medial: 'ﻜ', final: 'ﻚ' },
37674 1705: { initial: 'ﻛ', isolated: 'ﮎ', medial: 'ﻜ', final: 'ﮏ' },
37675 1711: { initial: 'ﮔ', isolated: 'ﮒ', medial: 'ﮕ', final: 'ﮓ' },
37676 1740: { initial: 'ﻳ', isolated: 'ﻯ', medial: 'ﻴ', final: 'ﻰ' },
37677 5000: { initial: 'ﻻ', isolated: 'ﻻ', medial: '', final: 'ﻼ' }
37680 var rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0780-\u07BF]/;
37682 function fixRTLTextForSvg(inputText) {
37683 var context = true;
37685 var rtlBuffer = [];
37686 var arabicRegex = /[\u0600-\u06FF]/g;
37687 var arabicTashkil = /[\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED]/;
37688 var thaanaVowel = /[\u07A6-\u07B0]/;
37689 var hebrewSign = /[\u0591-\u05bd\u05bf\u05c1-\u05c5\u05c7]/;
37691 if (!arabicRegex.test(inputText)) {
37692 // Hebrew or Thaana RTL script
37693 for (var n = 0; n < inputText.length; n++) {
37694 var c = inputText[n];
37695 if ((thaanaVowel.test(c) || hebrewSign.test(c)) && rtlBuffer.length) {
37696 rtlBuffer[rtlBuffer.length - 1] += c;
37697 } else if (rtlRegex.test(c)) {
37699 } else if (c === ' ' && rtlBuffer.length) {
37700 // whitespace within RTL text
37701 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
37703 // non-RTL character
37704 ret += rtlBuffer.reverse().join('') + c;
37709 for (var i = 0, l = inputText.length; i < l; i++) {
37710 var code = inputText[i].charCodeAt(0);
37711 var nextCode = inputText[i + 1] ? inputText[i + 1].charCodeAt(0) : 0;
37713 if (!chars$1[code]) {
37714 if (code === 32 && rtlBuffer.length) {
37716 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
37717 } else if (arabicTashkil.test(inputText[i]) && rtlBuffer.length) {
37719 rtlBuffer[rtlBuffer.length - 1] += inputText[i];
37721 // non-RTL character
37722 ret += rtlBuffer.reverse().join('') + inputText[i];
37728 if (i === l - 1 || nextCode === 32) {
37729 rtlBuffer.push(chars$1[code].isolated);
37731 // special case for لا
37732 if (code === 1604 && nextCode === 1575) {
37733 rtlBuffer.push(chars$1[5000].initial);
37738 rtlBuffer.push(chars$1[code].initial);
37741 if (i === l - 1 || nextCode === 32){
37742 rtlBuffer.push(chars$1[code].final);
37744 // special case for ﻼ
37745 if (code === 1604 && nextCode === 1575){
37746 rtlBuffer.push(chars$1[5000].final);
37751 if (chars$1[code].medial === ''){
37752 rtlBuffer.push(chars$1[code].final);
37754 rtlBuffer.push(chars$1[code].medial);
37758 context = (chars$1[code].medial === '') || nextCode === 32;
37761 ret += rtlBuffer.reverse().join('');
37765 function utilTagText(entity) {
37766 return entries(entity.tags).map(function(e) {
37767 return e.key + '=' + e.value;
37772 function utilEntitySelector(ids) {
37773 return ids.length ? '.' + ids.join(',.') : 'nothing';
37777 function utilEntityOrMemberSelector(ids, graph) {
37778 var s = utilEntitySelector(ids);
37780 ids.forEach(function(id) {
37781 var entity = graph.hasEntity(id);
37782 if (entity && entity.type === 'relation') {
37783 entity.members.forEach(function(member) {
37784 s += ',.' + member.id;
37793 function utilGetAllNodes(ids, graph) {
37796 ids.forEach(getNodes);
37799 function getNodes(id) {
37800 if (seen[id]) return;
37803 var entity = graph.hasEntity(id);
37804 if (!entity) return;
37806 if (entity.type === 'node') {
37807 nodes.push(entity);
37808 } else if (entity.type === 'way') {
37809 entity.nodes.forEach(getNodes);
37811 entity.members.map(function(member) { return member.id; }).forEach(getNodes);
37817 function utilDisplayName(entity) {
37818 var localizedNameKey = 'name:' + utilDetect().locale.toLowerCase().split('-')[0],
37819 name = entity.tags[localizedNameKey] || entity.tags.name || '',
37820 network = entity.tags.cycle_network || entity.tags.network;
37822 if (!name && entity.tags.ref) {
37823 name = entity.tags.ref;
37825 name = network + ' ' + name;
37833 function utilDisplayNameForPath(entity) {
37834 var name = utilDisplayName(entity);
37835 var isFirefox = utilDetect().browser.toLowerCase().indexOf('firefox') > -1;
37837 if (!isFirefox && name && rtlRegex.test(name)) {
37838 name = fixRTLTextForSvg(name);
37845 function utilDisplayType(id) {
37847 n: t('inspector.node'),
37848 w: t('inspector.way'),
37849 r: t('inspector.relation')
37854 function utilStringQs(str) {
37855 return str.split('&').reduce(function(obj, pair){
37856 var parts = pair.split('=');
37857 if (parts.length === 2) {
37858 obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
37865 function utilQsString(obj, noencode) {
37866 function softEncode(s) {
37867 // encode everything except special characters used in certain hash parameters:
37868 // "/" in map states, ":", ",", {" and "}" in background
37869 return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
37871 return Object.keys(obj).sort().map(function(key) {
37872 return encodeURIComponent(key) + '=' + (
37873 noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
37878 function utilPrefixDOMProperty(property) {
37879 var prefixes = ['webkit', 'ms', 'moz', 'o'],
37881 n = prefixes.length,
37887 property = property.substr(0, 1).toUpperCase() + property.substr(1);
37890 if (prefixes[i] + property in s)
37891 return prefixes[i] + property;
37897 function utilPrefixCSSProperty(property) {
37898 var prefixes = ['webkit', 'ms', 'Moz', 'O'],
37900 n = prefixes.length,
37901 s = document.body.style;
37903 if (property.toLowerCase() in s)
37904 return property.toLowerCase();
37907 if (prefixes[i] + property in s)
37908 return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
37914 var transformProperty;
37915 function utilSetTransform(el, x, y, scale) {
37916 var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform'),
37917 translate = utilDetect().opera ?
37918 'translate(' + x + 'px,' + y + 'px)' :
37919 'translate3d(' + x + 'px,' + y + 'px,0)';
37920 return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
37924 // Calculates Levenshtein distance between two strings
37925 // see: https://en.wikipedia.org/wiki/Levenshtein_distance
37926 // first converts the strings to lowercase and replaces diacritic marks with ascii equivalents.
37927 function utilEditDistance(a, b) {
37928 a = remove$1(a.toLowerCase());
37929 b = remove$1(b.toLowerCase());
37930 if (a.length === 0) return b.length;
37931 if (b.length === 0) return a.length;
37933 for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
37934 for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
37935 for (i = 1; i <= b.length; i++) {
37936 for (j = 1; j <= a.length; j++) {
37937 if (b.charAt(i-1) === a.charAt(j-1)) {
37938 matrix[i][j] = matrix[i-1][j-1];
37940 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
37941 Math.min(matrix[i][j-1] + 1, // insertion
37942 matrix[i-1][j] + 1)); // deletion
37946 return matrix[b.length][a.length];
37950 // a d3.mouse-alike which
37951 // 1. Only works on HTML elements, not SVG
37952 // 2. Does not cause style recalculation
37953 function utilFastMouse(container) {
37954 var rect = container.getBoundingClientRect(),
37955 rectLeft = rect.left,
37956 rectTop = rect.top,
37957 clientLeft = +container.clientLeft,
37958 clientTop = +container.clientTop;
37959 if (textDirection === 'rtl') {
37962 return function(e) {
37964 e.clientX - rectLeft - clientLeft,
37965 e.clientY - rectTop - clientTop];
37970 /* eslint-disable no-proto */
37971 var utilGetPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
37972 /* eslint-enable no-proto */
37975 function utilAsyncMap(inputs, func, callback) {
37976 var remaining = inputs.length,
37980 inputs.forEach(function(d, i) {
37981 func(d, function done(err, data) {
37985 if (!remaining) callback(errors, results);
37991 // wraps an index to an interval [0..length-1]
37992 function utilWrap(index, length) {
37994 index += Math.ceil(-index/length)*length;
37995 return index % length;
38000 * a replacement for functor
38002 * @param {*} value any value
38003 * @returns {Function} a function that returns that value or the value if it's a function
38005 function utilFunctor(value) {
38006 if (typeof value === 'function') return value;
38007 return function() {
38013 function utilNoAuto(selection$$1) {
38014 return selection$$1
38015 .attr('autocomplete', 'off')
38016 .attr('autocorrect', 'off')
38017 .attr('autocapitalize', 'off')
38018 .attr('spellcheck', 'false');
38021 // Like selection.property('value', ...), but avoids no-op value sets,
38022 // which can result in layout/repaint thrashing in some situations.
38023 function utilGetSetValue(selection, value) {
38024 function d3_selection_value(value) {
38025 function valueNull() {
38029 function valueConstant() {
38030 if (this.value !== value) {
38031 this.value = value;
38035 function valueFunction() {
38036 var x = value.apply(this, arguments);
38039 } else if (this.value !== x) {
38044 return value == null
38045 ? valueNull : (typeof value === 'function'
38046 ? valueFunction : valueConstant);
38049 if (arguments.length === 1) {
38050 return selection.property('value');
38053 return selection.each(d3_selection_value(value));
38056 // Copies a variable number of methods from source to target.
38057 function utilRebind(target, source) {
38058 var i = 1, n = arguments.length, method;
38060 target[method = arguments[i]] = d3_rebind(target, source, source[method]);
38065 // Method is assumed to be a standard D3 getter-setter:
38066 // If passed with no arguments, gets the value.
38067 // If passed with arguments, sets the value and returns the target.
38068 function d3_rebind(target, source, method) {
38069 return function() {
38070 var value = method.apply(source, arguments);
38071 return value === source ? target : value;
38075 // A per-domain session mutex backed by a cookie and dead man's
38076 // switch. If the session crashes, the mutex will auto-release
38077 // after 5 seconds.
38079 function utilSessionMutex(name) {
38084 var expires = new Date();
38085 expires.setSeconds(expires.getSeconds() + 5);
38086 document.cookie = name + '=1; expires=' + expires.toUTCString();
38089 mutex.lock = function() {
38090 if (intervalID) return true;
38091 var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
38092 if (cookie) return false;
38094 intervalID = window.setInterval(renew, 4000);
38098 mutex.unlock = function() {
38099 if (!intervalID) return;
38100 document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
38101 clearInterval(intervalID);
38105 mutex.locked = function() {
38106 return !!intervalID;
38112 function utilSuggestNames(preset, suggestions) {
38113 preset = preset.id.split('/', 2);
38117 return function(value, callback) {
38119 if (value && value.length > 2) {
38120 if (suggestions[k] && suggestions[k][v]) {
38121 for (var sugg in suggestions[k][v]) {
38122 var dist = utilEditDistance(value, sugg.substring(0, value.length));
38132 result.sort(function(a, b) {
38133 return a.dist - b.dist;
38136 result = result.slice(0,3);
38141 function utilTriggerEvent(target, type) {
38142 target.each(function() {
38143 var evt = document.createEvent('HTMLEvents');
38144 evt.initEvent(type, true, true);
38145 this.dispatchEvent(evt);
38149 function validationDeprecatedTag() {
38151 var validation = function(changes) {
38153 for (var i = 0; i < changes.created.length; i++) {
38154 var change = changes.created[i],
38155 deprecatedTags = change.deprecatedTags();
38157 if (!lodash.isEmpty(deprecatedTags)) {
38158 var tags = utilTagText({ tags: deprecatedTags });
38160 id: 'deprecated_tags',
38161 message: t('validations.deprecated_tags', { tags: tags }),
38174 function validationDisconnectedHighway() {
38177 function isDisconnectedHighway(entity, graph) {
38178 if (!entity.tags.highway) return false;
38179 if (entity.geometry(graph) !== 'line') return false;
38181 return graph.childNodes(entity)
38182 .every(function(vertex) {
38183 var parents = graph.parentWays(vertex);
38184 if (parents.length === 1) { // standalone vertex
38186 } else { // shared vertex
38187 return !vertex.tags.entrance &&
38188 parents.filter(function(parent) {
38189 return parent.tags.highway && parent !== entity;
38196 var validation = function(changes, graph) {
38198 for (var i = 0; i < changes.created.length; i++) {
38199 var entity = changes.created[i];
38201 if (isDisconnectedHighway(entity, graph)) {
38203 id: 'disconnected_highway',
38204 message: t('validations.disconnected_highway'),
38205 tooltip: t('validations.disconnected_highway_tooltip'),
38218 function validationManyDeletions() {
38219 var threshold = 100;
38221 var validation = function(changes) {
38223 if (changes.deleted.length > threshold) {
38225 id: 'many_deletions',
38226 message: t('validations.many_deletions', { n: changes.deleted.length })
38237 function validationMissingTag() {
38239 // Slightly stricter check than Entity#isUsed (#3091)
38240 function hasTags(entity, graph) {
38241 return lodash.without(Object.keys(entity.tags), 'area', 'name').length > 0 ||
38242 graph.parentRelations(entity).length > 0;
38245 var validation = function(changes, graph) {
38246 var types = ['point', 'line', 'area', 'relation'],
38249 for (var i = 0; i < changes.created.length; i++) {
38250 var change = changes.created[i],
38251 geometry = change.geometry(graph);
38253 if (types.indexOf(geometry) !== -1 && !hasTags(change, graph)) {
38256 message: t('validations.untagged_' + geometry),
38257 tooltip: t('validations.untagged_' + geometry + '_tooltip'),
38270 function validationOldMultipolygon() {
38273 return function validation(changes, graph) {
38275 for (var i = 0; i < changes.created.length; i++) {
38276 var entity = changes.created[i];
38277 var parent = osmIsSimpleMultipolygonOuterMember(entity, graph);
38280 id: 'old_multipolygon',
38281 message: t('validations.old_multipolygon'),
38282 tooltip: t('validations.old_multipolygon_tooltip'),
38291 // https://github.com/openstreetmap/josm/blob/mirror/src/org/
38292 // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
38293 function validationTagSuggestsArea() {
38295 function tagSuggestsArea(tags) {
38296 if (lodash.isEmpty(tags)) return false;
38298 var presence = ['landuse', 'amenities', 'tourism', 'shop'];
38299 for (var i = 0; i < presence.length; i++) {
38300 if (tags[presence[i]] !== undefined) {
38301 return presence[i] + '=' + tags[presence[i]];
38305 if (tags.building && tags.building === 'yes') return 'building=yes';
38309 var validation = function(changes, graph) {
38311 for (var i = 0; i < changes.created.length; i++) {
38312 var change = changes.created[i],
38313 geometry = change.geometry(graph),
38314 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
38318 id: 'tag_suggests_area',
38319 message: t('validations.tag_suggests_area', { tag: suggestion }),
38334 var Validations = Object.freeze({
38335 validationDeprecatedTag: validationDeprecatedTag,
38336 validationDisconnectedHighway: validationDisconnectedHighway,
38337 validationManyDeletions: validationManyDeletions,
38338 validationMissingTag: validationMissingTag,
38339 validationOldMultipolygon: validationOldMultipolygon,
38340 validationTagSuggestsArea: validationTagSuggestsArea
38344 iD.Difference represents the difference between two graphs.
38345 It knows how to calculate the set of entities that were
38346 created, modified, or deleted, and also contains the logic
38347 for recursively extending a difference to the complete set
38348 of entities that will require a redraw, taking into account
38349 child and parent relationships.
38351 function coreDifference(base, head) {
38357 function changed(h, b) {
38358 return h !== b && !lodash.isEqual(lodash.omit(h, 'v'), lodash.omit(b, 'v'));
38362 lodash.each(head.entities, function(h, id) {
38363 var b = base.entities[id];
38364 if (changed(h, b)) {
38365 changes[id] = {base: b, head: h};
38371 lodash.each(base.entities, function(b, id) {
38372 var h = head.entities[id];
38373 if (!changes[id] && changed(h, b)) {
38374 changes[id] = {base: b, head: h};
38380 function addParents(parents, result) {
38381 for (var i = 0; i < parents.length; i++) {
38382 var parent = parents[i];
38384 if (parent.id in result)
38387 result[parent.id] = parent;
38388 addParents(head.parentRelations(parent), result);
38393 difference.length = function() {
38398 difference.changes = function() {
38403 difference.extantIDs = function() {
38405 lodash.each(changes, function(change, id) {
38406 if (change.head) result.push(id);
38412 difference.modified = function() {
38414 lodash.each(changes, function(change) {
38415 if (change.base && change.head) result.push(change.head);
38421 difference.created = function() {
38423 lodash.each(changes, function(change) {
38424 if (!change.base && change.head) result.push(change.head);
38430 difference.deleted = function() {
38432 lodash.each(changes, function(change) {
38433 if (change.base && !change.head) result.push(change.base);
38439 difference.summary = function() {
38442 function addEntity(entity, graph, changeType) {
38443 relevant[entity.id] = {
38446 changeType: changeType
38450 function addParents(entity) {
38451 var parents = head.parentWays(entity);
38452 for (var j = parents.length - 1; j >= 0; j--) {
38453 var parent = parents[j];
38454 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
38458 lodash.each(changes, function(change) {
38459 if (change.head && change.head.geometry(head) !== 'vertex') {
38460 addEntity(change.head, head, change.base ? 'modified' : 'created');
38462 } else if (change.base && change.base.geometry(base) !== 'vertex') {
38463 addEntity(change.base, base, 'deleted');
38465 } else if (change.base && change.head) { // modified vertex
38466 var moved = !lodash.isEqual(change.base.loc, change.head.loc),
38467 retagged = !lodash.isEqual(change.base.tags, change.head.tags);
38470 addParents(change.head);
38473 if (retagged || (moved && change.head.hasInterestingTags())) {
38474 addEntity(change.head, head, 'modified');
38477 } else if (change.head && change.head.hasInterestingTags()) { // created vertex
38478 addEntity(change.head, head, 'created');
38480 } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
38481 addEntity(change.base, base, 'deleted');
38485 return values(relevant);
38489 difference.complete = function(extent$$1) {
38490 var result = {}, id, change;
38492 for (id in changes) {
38493 change = changes[id];
38495 var h = change.head,
38500 (!h || !h.intersects(extent$$1, head)) &&
38501 (!b || !b.intersects(extent$$1, base)))
38506 if (entity.type === 'way') {
38507 var nh = h ? h.nodes : [],
38508 nb = b ? b.nodes : [],
38511 diff = lodash.difference(nh, nb);
38512 for (i = 0; i < diff.length; i++) {
38513 result[diff[i]] = head.hasEntity(diff[i]);
38516 diff = lodash.difference(nb, nh);
38517 for (i = 0; i < diff.length; i++) {
38518 result[diff[i]] = head.hasEntity(diff[i]);
38522 addParents(head.parentWays(entity), result);
38523 addParents(head.parentRelations(entity), result);
38533 function coreGraph$$1(other, mutable) {
38534 if (!(this instanceof coreGraph$$1)) return new coreGraph$$1(other, mutable);
38536 if (other instanceof coreGraph$$1) {
38537 var base = other.base();
38538 this.entities = lodash.assign(Object.create(base.entities), other.entities);
38539 this._parentWays = lodash.assign(Object.create(base.parentWays), other._parentWays);
38540 this._parentRels = lodash.assign(Object.create(base.parentRels), other._parentRels);
38543 this.entities = Object.create({});
38544 this._parentWays = Object.create({});
38545 this._parentRels = Object.create({});
38546 this.rebase(other || [], [this]);
38549 this.transients = {};
38550 this._childNodes = {};
38551 this.frozen = !mutable;
38555 coreGraph$$1.prototype = {
38557 hasEntity: function(id) {
38558 return this.entities[id];
38562 entity: function(id) {
38563 var entity = this.entities[id];
38565 throw new Error('entity ' + id + ' not found');
38571 transient: function(entity, key, fn) {
38572 var id = entity.id,
38573 transients = this.transients[id] ||
38574 (this.transients[id] = {});
38576 if (transients[key] !== undefined) {
38577 return transients[key];
38580 transients[key] = fn.call(entity);
38582 return transients[key];
38586 parentWays: function(entity) {
38587 var parents = this._parentWays[entity.id],
38591 for (var i = 0; i < parents.length; i++) {
38592 result.push(this.entity(parents[i]));
38599 isPoi: function(entity) {
38600 var parentWays = this._parentWays[entity.id];
38601 return !parentWays || parentWays.length === 0;
38605 isShared: function(entity) {
38606 var parentWays = this._parentWays[entity.id];
38607 return parentWays && parentWays.length > 1;
38611 parentRelations: function(entity) {
38612 var parents = this._parentRels[entity.id],
38616 for (var i = 0; i < parents.length; i++) {
38617 result.push(this.entity(parents[i]));
38624 childNodes: function(entity) {
38625 if (this._childNodes[entity.id]) return this._childNodes[entity.id];
38626 if (!entity.nodes) return [];
38629 for (var i = 0; i < entity.nodes.length; i++) {
38630 nodes[i] = this.entity(entity.nodes[i]);
38633 if (debug) Object.freeze(nodes);
38635 this._childNodes[entity.id] = nodes;
38636 return this._childNodes[entity.id];
38642 'entities': utilGetPrototypeOf(this.entities),
38643 'parentWays': utilGetPrototypeOf(this._parentWays),
38644 'parentRels': utilGetPrototypeOf(this._parentRels)
38649 // Unlike other graph methods, rebase mutates in place. This is because it
38650 // is used only during the history operation that merges newly downloaded
38651 // data into each state. To external consumers, it should appear as if the
38652 // graph always contained the newly downloaded data.
38653 rebase: function(entities, stack, force) {
38654 var base = this.base(),
38657 for (i = 0; i < entities.length; i++) {
38658 var entity = entities[i];
38660 if (!entity.visible || (!force && base.entities[entity.id]))
38663 // Merging data into the base graph
38664 base.entities[entity.id] = entity;
38665 this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
38667 // Restore provisionally-deleted nodes that are discovered to have an extant parent
38668 if (entity.type === 'way') {
38669 for (j = 0; j < entity.nodes.length; j++) {
38670 id = entity.nodes[j];
38671 for (k = 1; k < stack.length; k++) {
38672 var ents = stack[k].entities;
38673 if (ents.hasOwnProperty(id) && ents[id] === undefined) {
38681 for (i = 0; i < stack.length; i++) {
38682 stack[i]._updateRebased();
38687 _updateRebased: function() {
38688 var base = this.base(),
38689 i, k, child, id, keys;
38691 keys = Object.keys(this._parentWays);
38692 for (i = 0; i < keys.length; i++) {
38694 if (base.parentWays[child]) {
38695 for (k = 0; k < base.parentWays[child].length; k++) {
38696 id = base.parentWays[child][k];
38697 if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentWays[child], id)) {
38698 this._parentWays[child].push(id);
38704 keys = Object.keys(this._parentRels);
38705 for (i = 0; i < keys.length; i++) {
38707 if (base.parentRels[child]) {
38708 for (k = 0; k < base.parentRels[child].length; k++) {
38709 id = base.parentRels[child][k];
38710 if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentRels[child], id)) {
38711 this._parentRels[child].push(id);
38717 this.transients = {};
38719 // this._childNodes is not updated, under the assumption that
38720 // ways are always downloaded with their child nodes.
38724 // Updates calculated properties (parentWays, parentRels) for the specified change
38725 _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
38727 parentWays = parentWays || this._parentWays;
38728 parentRels = parentRels || this._parentRels;
38730 var type = entity && entity.type || oldentity && oldentity.type,
38731 removed, added, ways, rels, i;
38734 if (type === 'way') {
38736 // Update parentWays
38737 if (oldentity && entity) {
38738 removed = lodash.difference(oldentity.nodes, entity.nodes);
38739 added = lodash.difference(entity.nodes, oldentity.nodes);
38740 } else if (oldentity) {
38741 removed = oldentity.nodes;
38743 } else if (entity) {
38745 added = entity.nodes;
38747 for (i = 0; i < removed.length; i++) {
38748 parentWays[removed[i]] = lodash.without(parentWays[removed[i]], oldentity.id);
38750 for (i = 0; i < added.length; i++) {
38751 ways = lodash.without(parentWays[added[i]], entity.id);
38752 ways.push(entity.id);
38753 parentWays[added[i]] = ways;
38756 } else if (type === 'relation') {
38758 // Update parentRels
38759 if (oldentity && entity) {
38760 removed = lodash.difference(oldentity.members, entity.members);
38761 added = lodash.difference(entity.members, oldentity);
38762 } else if (oldentity) {
38763 removed = oldentity.members;
38765 } else if (entity) {
38767 added = entity.members;
38769 for (i = 0; i < removed.length; i++) {
38770 parentRels[removed[i].id] = lodash.without(parentRels[removed[i].id], oldentity.id);
38772 for (i = 0; i < added.length; i++) {
38773 rels = lodash.without(parentRels[added[i].id], entity.id);
38774 rels.push(entity.id);
38775 parentRels[added[i].id] = rels;
38781 replace: function(entity) {
38782 if (this.entities[entity.id] === entity)
38785 return this.update(function() {
38786 this._updateCalculated(this.entities[entity.id], entity);
38787 this.entities[entity.id] = entity;
38792 remove: function(entity) {
38793 return this.update(function() {
38794 this._updateCalculated(entity, undefined);
38795 this.entities[entity.id] = undefined;
38800 revert: function(id) {
38801 var baseEntity = this.base().entities[id],
38802 headEntity = this.entities[id];
38804 if (headEntity === baseEntity)
38807 return this.update(function() {
38808 this._updateCalculated(headEntity, baseEntity);
38809 delete this.entities[id];
38814 update: function() {
38815 var graph = this.frozen ? coreGraph$$1(this, true) : this;
38817 for (var i = 0; i < arguments.length; i++) {
38818 arguments[i].call(graph, graph);
38821 if (this.frozen) graph.frozen = true;
38827 // Obliterates any existing entities
38828 load: function(entities) {
38829 var base = this.base();
38830 this.entities = Object.create(base.entities);
38832 for (var i in entities) {
38833 this.entities[i] = entities[i];
38834 this._updateCalculated(base.entities[i], this.entities[i]);
38841 var index$10 = partialSort;
38843 // Floyd-Rivest selection algorithm:
38844 // Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
38845 // The k-th element will have the (k - left + 1)th smallest value in [left, right]
38847 function partialSort(arr, k, left, right, compare) {
38849 right = right || (arr.length - 1);
38850 compare = compare || defaultCompare;
38852 while (right > left) {
38853 if (right - left > 600) {
38854 var n = right - left + 1;
38855 var m = k - left + 1;
38856 var z = Math.log(n);
38857 var s = 0.5 * Math.exp(2 * z / 3);
38858 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
38859 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
38860 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
38861 partialSort(arr, k, newLeft, newRight, compare);
38868 swap(arr, left, k);
38869 if (compare(arr[right], t) > 0) swap(arr, left, right);
38875 while (compare(arr[i], t) < 0) i++;
38876 while (compare(arr[j], t) > 0) j--;
38879 if (compare(arr[left], t) === 0) swap(arr, left, j);
38882 swap(arr, j, right);
38885 if (j <= k) left = j + 1;
38886 if (k <= j) right = j - 1;
38890 function swap(arr, i, j) {
38896 function defaultCompare(a, b) {
38897 return a < b ? -1 : a > b ? 1 : 0;
38900 var index$9 = rbush;
38904 function rbush(maxEntries, format) {
38905 if (!(this instanceof rbush)) return new rbush(maxEntries, format);
38907 // max entries in a node is 9 by default; min node fill is 40% for best performance
38908 this._maxEntries = Math.max(4, maxEntries || 9);
38909 this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
38912 this._initFormat(format);
38918 rbush.prototype = {
38921 return this._all(this.data, []);
38924 search: function (bbox) {
38926 var node = this.data,
38928 toBBox = this.toBBox;
38930 if (!intersects$1(bbox, node)) return result;
38932 var nodesToSearch = [],
38933 i, len, child, childBBox;
38936 for (i = 0, len = node.children.length; i < len; i++) {
38938 child = node.children[i];
38939 childBBox = node.leaf ? toBBox(child) : child;
38941 if (intersects$1(bbox, childBBox)) {
38942 if (node.leaf) result.push(child);
38943 else if (contains$2(bbox, childBBox)) this._all(child, result);
38944 else nodesToSearch.push(child);
38947 node = nodesToSearch.pop();
38953 collides: function (bbox) {
38955 var node = this.data,
38956 toBBox = this.toBBox;
38958 if (!intersects$1(bbox, node)) return false;
38960 var nodesToSearch = [],
38961 i, len, child, childBBox;
38964 for (i = 0, len = node.children.length; i < len; i++) {
38966 child = node.children[i];
38967 childBBox = node.leaf ? toBBox(child) : child;
38969 if (intersects$1(bbox, childBBox)) {
38970 if (node.leaf || contains$2(bbox, childBBox)) return true;
38971 nodesToSearch.push(child);
38974 node = nodesToSearch.pop();
38980 load: function (data) {
38981 if (!(data && data.length)) return this;
38983 if (data.length < this._minEntries) {
38984 for (var i = 0, len = data.length; i < len; i++) {
38985 this.insert(data[i]);
38990 // recursively build the tree with the given data from stratch using OMT algorithm
38991 var node = this._build(data.slice(), 0, data.length - 1, 0);
38993 if (!this.data.children.length) {
38994 // save as is if tree is empty
38997 } else if (this.data.height === node.height) {
38998 // split root if trees have the same height
38999 this._splitRoot(this.data, node);
39002 if (this.data.height < node.height) {
39003 // swap trees if inserted one is bigger
39004 var tmpNode = this.data;
39009 // insert the small tree into the large tree at appropriate level
39010 this._insert(node, this.data.height - node.height - 1, true);
39016 insert: function (item) {
39017 if (item) this._insert(item, this.data.height - 1);
39021 clear: function () {
39022 this.data = createNode([]);
39026 remove: function (item, equalsFn) {
39027 if (!item) return this;
39029 var node = this.data,
39030 bbox = this.toBBox(item),
39033 i, parent, index, goingUp;
39035 // depth-first iterative tree traversal
39036 while (node || path.length) {
39038 if (!node) { // go up
39040 parent = path[path.length - 1];
39045 if (node.leaf) { // check current node
39046 index = findItem(item, node.children, equalsFn);
39048 if (index !== -1) {
39049 // item found, remove the item and condense tree upwards
39050 node.children.splice(index, 1);
39052 this._condense(path);
39057 if (!goingUp && !node.leaf && contains$2(node, bbox)) { // go down
39062 node = node.children[0];
39064 } else if (parent) { // go right
39066 node = parent.children[i];
39069 } else node = null; // nothing found
39075 toBBox: function (item) { return item; },
39077 compareMinX: compareNodeMinX,
39078 compareMinY: compareNodeMinY,
39080 toJSON: function () { return this.data; },
39082 fromJSON: function (data) {
39087 _all: function (node, result) {
39088 var nodesToSearch = [];
39090 if (node.leaf) result.push.apply(result, node.children);
39091 else nodesToSearch.push.apply(nodesToSearch, node.children);
39093 node = nodesToSearch.pop();
39098 _build: function (items, left, right, height) {
39100 var N = right - left + 1,
39101 M = this._maxEntries,
39105 // reached leaf level; return leaf
39106 node = createNode(items.slice(left, right + 1));
39107 calcBBox(node, this.toBBox);
39112 // target height of the bulk-loaded tree
39113 height = Math.ceil(Math.log(N) / Math.log(M));
39115 // target number of root entries to maximize storage utilization
39116 M = Math.ceil(N / Math.pow(M, height - 1));
39119 node = createNode([]);
39121 node.height = height;
39123 // split the items into M mostly square tiles
39125 var N2 = Math.ceil(N / M),
39126 N1 = N2 * Math.ceil(Math.sqrt(M)),
39127 i, j, right2, right3;
39129 multiSelect(items, left, right, N1, this.compareMinX);
39131 for (i = left; i <= right; i += N1) {
39133 right2 = Math.min(i + N1 - 1, right);
39135 multiSelect(items, i, right2, N2, this.compareMinY);
39137 for (j = i; j <= right2; j += N2) {
39139 right3 = Math.min(j + N2 - 1, right2);
39141 // pack each entry recursively
39142 node.children.push(this._build(items, j, right3, height - 1));
39146 calcBBox(node, this.toBBox);
39151 _chooseSubtree: function (bbox, node, level, path) {
39153 var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
39158 if (node.leaf || path.length - 1 === level) break;
39160 minArea = minEnlargement = Infinity;
39162 for (i = 0, len = node.children.length; i < len; i++) {
39163 child = node.children[i];
39164 area = bboxArea(child);
39165 enlargement = enlargedArea(bbox, child) - area;
39167 // choose entry with the least area enlargement
39168 if (enlargement < minEnlargement) {
39169 minEnlargement = enlargement;
39170 minArea = area < minArea ? area : minArea;
39171 targetNode = child;
39173 } else if (enlargement === minEnlargement) {
39174 // otherwise choose one with the smallest area
39175 if (area < minArea) {
39177 targetNode = child;
39182 node = targetNode || node.children[0];
39188 _insert: function (item, level, isNode) {
39190 var toBBox = this.toBBox,
39191 bbox = isNode ? item : toBBox(item),
39194 // find the best node for accommodating the item, saving all nodes along the path too
39195 var node = this._chooseSubtree(bbox, this.data, level, insertPath);
39197 // put the item into the node
39198 node.children.push(item);
39199 extend$1(node, bbox);
39201 // split on node overflow; propagate upwards if necessary
39202 while (level >= 0) {
39203 if (insertPath[level].children.length > this._maxEntries) {
39204 this._split(insertPath, level);
39209 // adjust bboxes along the insertion path
39210 this._adjustParentBBoxes(bbox, insertPath, level);
39213 // split overflowed node into two
39214 _split: function (insertPath, level) {
39216 var node = insertPath[level],
39217 M = node.children.length,
39218 m = this._minEntries;
39220 this._chooseSplitAxis(node, m, M);
39222 var splitIndex = this._chooseSplitIndex(node, m, M);
39224 var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
39225 newNode.height = node.height;
39226 newNode.leaf = node.leaf;
39228 calcBBox(node, this.toBBox);
39229 calcBBox(newNode, this.toBBox);
39231 if (level) insertPath[level - 1].children.push(newNode);
39232 else this._splitRoot(node, newNode);
39235 _splitRoot: function (node, newNode) {
39237 this.data = createNode([node, newNode]);
39238 this.data.height = node.height + 1;
39239 this.data.leaf = false;
39240 calcBBox(this.data, this.toBBox);
39243 _chooseSplitIndex: function (node, m, M) {
39245 var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
39247 minOverlap = minArea = Infinity;
39249 for (i = m; i <= M - m; i++) {
39250 bbox1 = distBBox(node, 0, i, this.toBBox);
39251 bbox2 = distBBox(node, i, M, this.toBBox);
39253 overlap = intersectionArea(bbox1, bbox2);
39254 area = bboxArea(bbox1) + bboxArea(bbox2);
39256 // choose distribution with minimum overlap
39257 if (overlap < minOverlap) {
39258 minOverlap = overlap;
39261 minArea = area < minArea ? area : minArea;
39263 } else if (overlap === minOverlap) {
39264 // otherwise choose distribution with minimum area
39265 if (area < minArea) {
39275 // sorts node children by the best axis for split
39276 _chooseSplitAxis: function (node, m, M) {
39278 var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
39279 compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
39280 xMargin = this._allDistMargin(node, m, M, compareMinX),
39281 yMargin = this._allDistMargin(node, m, M, compareMinY);
39283 // if total distributions margin value is minimal for x, sort by minX,
39284 // otherwise it's already sorted by minY
39285 if (xMargin < yMargin) node.children.sort(compareMinX);
39288 // total margin of all possible split distributions where each node is at least m full
39289 _allDistMargin: function (node, m, M, compare) {
39291 node.children.sort(compare);
39293 var toBBox = this.toBBox,
39294 leftBBox = distBBox(node, 0, m, toBBox),
39295 rightBBox = distBBox(node, M - m, M, toBBox),
39296 margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
39299 for (i = m; i < M - m; i++) {
39300 child = node.children[i];
39301 extend$1(leftBBox, node.leaf ? toBBox(child) : child);
39302 margin += bboxMargin(leftBBox);
39305 for (i = M - m - 1; i >= m; i--) {
39306 child = node.children[i];
39307 extend$1(rightBBox, node.leaf ? toBBox(child) : child);
39308 margin += bboxMargin(rightBBox);
39314 _adjustParentBBoxes: function (bbox, path, level) {
39315 // adjust bboxes along the given tree path
39316 for (var i = level; i >= 0; i--) {
39317 extend$1(path[i], bbox);
39321 _condense: function (path) {
39322 // go through the path, removing empty nodes and updating bboxes
39323 for (var i = path.length - 1, siblings; i >= 0; i--) {
39324 if (path[i].children.length === 0) {
39326 siblings = path[i - 1].children;
39327 siblings.splice(siblings.indexOf(path[i]), 1);
39329 } else this.clear();
39331 } else calcBBox(path[i], this.toBBox);
39335 _initFormat: function (format) {
39336 // data format (minX, minY, maxX, maxY accessors)
39338 // uses eval-type function compilation instead of just accepting a toBBox function
39339 // because the algorithms are very sensitive to sorting functions performance,
39340 // so they should be dead simple and without inner calls
39342 var compareArr = ['return a', ' - b', ';'];
39344 this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
39345 this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
39347 this.toBBox = new Function('a',
39348 'return {minX: a' + format[0] +
39349 ', minY: a' + format[1] +
39350 ', maxX: a' + format[2] +
39351 ', maxY: a' + format[3] + '};');
39355 function findItem(item, items, equalsFn) {
39356 if (!equalsFn) return items.indexOf(item);
39358 for (var i = 0; i < items.length; i++) {
39359 if (equalsFn(item, items[i])) return i;
39364 // calculate node's bbox from bboxes of its children
39365 function calcBBox(node, toBBox) {
39366 distBBox(node, 0, node.children.length, toBBox, node);
39369 // min bounding rectangle of node children from k to p-1
39370 function distBBox(node, k, p, toBBox, destNode) {
39371 if (!destNode) destNode = createNode(null);
39372 destNode.minX = Infinity;
39373 destNode.minY = Infinity;
39374 destNode.maxX = -Infinity;
39375 destNode.maxY = -Infinity;
39377 for (var i = k, child; i < p; i++) {
39378 child = node.children[i];
39379 extend$1(destNode, node.leaf ? toBBox(child) : child);
39385 function extend$1(a, b) {
39386 a.minX = Math.min(a.minX, b.minX);
39387 a.minY = Math.min(a.minY, b.minY);
39388 a.maxX = Math.max(a.maxX, b.maxX);
39389 a.maxY = Math.max(a.maxY, b.maxY);
39393 function compareNodeMinX(a, b) { return a.minX - b.minX; }
39394 function compareNodeMinY(a, b) { return a.minY - b.minY; }
39396 function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
39397 function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
39399 function enlargedArea(a, b) {
39400 return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
39401 (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
39404 function intersectionArea(a, b) {
39405 var minX = Math.max(a.minX, b.minX),
39406 minY = Math.max(a.minY, b.minY),
39407 maxX = Math.min(a.maxX, b.maxX),
39408 maxY = Math.min(a.maxY, b.maxY);
39410 return Math.max(0, maxX - minX) *
39411 Math.max(0, maxY - minY);
39414 function contains$2(a, b) {
39415 return a.minX <= b.minX &&
39416 a.minY <= b.minY &&
39417 b.maxX <= a.maxX &&
39421 function intersects$1(a, b) {
39422 return b.minX <= a.maxX &&
39423 b.minY <= a.maxY &&
39424 b.maxX >= a.minX &&
39428 function createNode(children) {
39430 children: children,
39440 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
39441 // combines selection algorithm with binary divide & conquer approach
39443 function multiSelect(arr, left, right, n, compare) {
39444 var stack = [left, right],
39447 while (stack.length) {
39448 right = stack.pop();
39449 left = stack.pop();
39451 if (right - left <= n) continue;
39453 mid = left + Math.ceil((right - left) / n / 2) * n;
39454 index$10(arr, mid, left, right, compare);
39456 stack.push(left, mid, mid, right);
39460 function coreTree(head) {
39461 var rtree = index$9(),
39466 function entityBBox(entity) {
39467 var bbox = entity.extent(head).bbox();
39468 bbox.id = entity.id;
39469 bboxes[entity.id] = bbox;
39474 function updateParents(entity, insertions, memo) {
39475 head.parentWays(entity).forEach(function(way) {
39476 if (bboxes[way.id]) {
39477 rtree.remove(bboxes[way.id]);
39478 insertions[way.id] = way;
39480 updateParents(way, insertions, memo);
39483 head.parentRelations(entity).forEach(function(relation) {
39484 if (memo[entity.id]) return;
39485 memo[entity.id] = true;
39486 if (bboxes[relation.id]) {
39487 rtree.remove(bboxes[relation.id]);
39488 insertions[relation.id] = relation;
39490 updateParents(relation, insertions, memo);
39495 tree.rebase = function(entities, force) {
39496 var insertions = {};
39498 for (var i = 0; i < entities.length; i++) {
39499 var entity = entities[i];
39501 if (!entity.visible)
39504 if (head.entities.hasOwnProperty(entity.id) || bboxes[entity.id]) {
39507 } else if (bboxes[entity.id]) {
39508 rtree.remove(bboxes[entity.id]);
39512 insertions[entity.id] = entity;
39513 updateParents(entity, insertions, {});
39516 rtree.load(lodash.map(insertions, entityBBox));
39522 tree.intersects = function(extent, graph) {
39523 if (graph !== head) {
39524 var diff = coreDifference(head, graph),
39529 diff.deleted().forEach(function(entity) {
39530 rtree.remove(bboxes[entity.id]);
39531 delete bboxes[entity.id];
39534 diff.modified().forEach(function(entity) {
39535 rtree.remove(bboxes[entity.id]);
39536 insertions[entity.id] = entity;
39537 updateParents(entity, insertions, {});
39540 diff.created().forEach(function(entity) {
39541 insertions[entity.id] = entity;
39544 rtree.load(lodash.map(insertions, entityBBox));
39547 return rtree.search(extent.bbox()).map(function(bbox) {
39548 return head.entity(bbox.id);
39557 * This code is licensed under the MIT license.
39559 * Copyright © 2013, iD authors.
39561 * Portions copyright © 2011, Keith Cirkel
39562 * See https://github.com/keithamus/jwerty
39565 function d3keybinding(namespace$$1) {
39568 function matches(binding, event$$1) {
39569 for (var p in binding.event) {
39570 if (event$$1[p] !== binding.event[p])
39576 function testBindings(isCapturing) {
39577 for (var i = 0; i < bindings.length; i++) {
39578 var binding = bindings[i];
39580 if (!!binding.capture === isCapturing && matches(binding, event)) {
39581 binding.callback();
39586 function capture() {
39587 testBindings(true);
39590 function bubble() {
39591 var tagName = select(event.target).node().tagName;
39592 if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
39595 testBindings(false);
39598 function keybinding(selection$$1) {
39599 selection$$1 = selection$$1 || select(document);
39600 selection$$1.on('keydown.capture' + namespace$$1, capture, true);
39601 selection$$1.on('keydown.bubble' + namespace$$1, bubble, false);
39605 keybinding.off = function(selection$$1) {
39607 selection$$1 = selection$$1 || select(document);
39608 selection$$1.on('keydown.capture' + namespace$$1, null);
39609 selection$$1.on('keydown.bubble' + namespace$$1, null);
39613 keybinding.on = function(codes, callback, capture) {
39614 var arr = [].concat(codes);
39615 for (var i = 0; i < arr.length; i++) {
39629 code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
39631 for (var j = 0; j < code.length; j++) {
39632 // Normalise matching errors
39633 if (code[j] === '++') code[i] = '+';
39635 if (code[j] in d3keybinding.modifierCodes) {
39636 binding.event[d3keybinding.modifierProperties[d3keybinding.modifierCodes[code[j]]]] = true;
39637 } else if (code[j] in d3keybinding.keyCodes) {
39638 binding.event.keyCode = d3keybinding.keyCodes[code[j]];
39642 bindings.push(binding);
39652 d3keybinding.modifierCodes = {
39654 '⇧': 16, shift: 16,
39655 // CTRL key, on Mac: ⌃
39657 // ALT key, on Mac: ⌥ (Alt)
39658 '⌥': 18, alt: 18, option: 18,
39659 // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
39660 '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
39663 d3keybinding.modifierProperties = {
39670 d3keybinding.keyCodes = {
39671 // Backspace key, on Mac: ⌫ (Backspace)
39672 '⌫': 8, backspace: 8,
39673 // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
39674 '⇥': 9, '⇆': 9, tab: 9,
39676 '↩': 13, 'return': 13, enter: 13, '⌅': 13,
39678 'pause': 19, 'pause-break': 19,
39679 // Caps Lock key, ⇪
39680 '⇪': 20, caps: 20, 'caps-lock': 20,
39681 // Escape key, on Mac: ⎋, on Windows: Esc
39682 '⎋': 27, escape: 27, esc: 27,
39685 // Page-Up key, or pgup, on Mac: ↖
39686 '↖': 33, pgup: 33, 'page-up': 33,
39687 // Page-Down key, or pgdown, on Mac: ↘
39688 '↘': 34, pgdown: 34, 'page-down': 34,
39689 // END key, on Mac: ⇟
39691 // HOME key, on Mac: ⇞
39693 // Insert key, or ins
39694 ins: 45, insert: 45,
39695 // Delete key, on Mac: ⌦ (Delete)
39696 '⌦': 46, del: 46, 'delete': 46,
39697 // Left Arrow Key, or ←
39698 '←': 37, left: 37, 'arrow-left': 37,
39699 // Up Arrow Key, or ↑
39700 '↑': 38, up: 38, 'arrow-up': 38,
39701 // Right Arrow Key, or →
39702 '→': 39, right: 39, 'arrow-right': 39,
39703 // Up Arrow Key, or ↓
39704 '↓': 40, down: 40, 'arrow-down': 40,
39705 // odities, printing characters that come out wrong:
39708 // Num-Multiply, or *
39709 '*': 106, star: 106, asterisk: 106, multiply: 106,
39711 '+': 107, 'plus': 107,
39712 // Num-Subtract, or -
39713 '-': 109, subtract: 109,
39719 ';': 186, semicolon: 186,
39721 '=': 187, 'equals': 187,
39723 ',': 188, comma: 188,
39724 // Dash / Underscore key
39726 // Period, or ., or full-stop
39727 '.': 190, period: 190, 'full-stop': 190,
39728 // Slash, or /, or forward-slash
39729 '/': 191, slash: 191, 'forward-slash': 191,
39730 // Tick, or `, or back-quote
39731 '`': 192, tick: 192, 'back-quote': 192,
39732 // Open bracket, or [
39733 '[': 219, 'open-bracket': 219,
39734 // Back slash, or \
39735 '\\': 220, 'back-slash': 220,
39736 // Close backet, or ]
39737 ']': 221, 'close-bracket': 221,
39738 // Apostrophe, or Quote, or '
39739 '\'': 222, quote: 222, apostrophe: 222
39745 while (++i$1 < 106) {
39746 d3keybinding.keyCodes['num-' + n] = i$1;
39752 while (++i$1 < 58) {
39753 d3keybinding.keyCodes[n] = i$1;
39759 while (++i$1 < 136) {
39760 d3keybinding.keyCodes['f' + n] = i$1;
39766 while (++i$1 < 91) {
39767 d3keybinding.keyCodes[String.fromCharCode(i$1).toLowerCase()] = i$1;
39770 function tooltip() {
39771 var tooltip = function(selection$$1) {
39772 selection$$1.each(setup);
39774 animation = utilFunctor(false),
39775 html$$1 = utilFunctor(false),
39776 title = function() {
39777 var title = this.getAttribute('data-original-title');
39781 title = this.getAttribute('title');
39782 this.removeAttribute('title');
39783 this.setAttribute('data-original-title', title);
39787 over = 'mouseenter.tooltip',
39788 out = 'mouseleave.tooltip',
39789 placement = utilFunctor('top');
39792 tooltip.title = function(_) {
39793 if (arguments.length) {
39794 title = utilFunctor(_);
39802 tooltip.html = function(_) {
39803 if (arguments.length) {
39804 html$$1 = utilFunctor(_);
39812 tooltip.placement = function(_) {
39813 if (arguments.length) {
39814 placement = utilFunctor(_);
39822 tooltip.show = function(selection$$1) {
39823 selection$$1.each(show);
39827 tooltip.hide = function(selection$$1) {
39828 selection$$1.each(hide);
39832 tooltip.toggle = function(selection$$1) {
39833 selection$$1.each(toggle);
39837 tooltip.destroy = function(selection$$1) {
39841 .attr('title', function() {
39842 return this.getAttribute('data-original-title') || this.getAttribute('title');
39844 .attr('data-original-title', null)
39845 .selectAll('.tooltip')
39851 var root = select(this),
39852 animate = animation.apply(this, arguments),
39853 tip = root.selectAll('.tooltip').data([0]);
39855 var enter = tip.enter()
39857 .attr('class', 'tooltip');
39861 .attr('class', 'tooltip-arrow');
39865 .attr('class', 'tooltip-inner');
39871 tip.classed('fade', true);
39874 var place = placement.apply(this, arguments);
39875 tip.classed(place, true);
39877 root.on(over, show);
39878 root.on(out, hide);
39883 var root = select(this),
39884 content = title.apply(this, arguments),
39885 tip = root.selectAll('.tooltip')
39886 .classed('in', true),
39887 markup = html$$1.apply(this, arguments);
39889 tip.selectAll('.tooltip-inner')[markup ? 'html' : 'text'](content);
39890 var place = placement.apply(this, arguments),
39891 outer = getPosition(root.node()),
39892 inner = getPosition(tip.node()),
39897 pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
39900 pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
39903 pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
39906 pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
39911 tip.style('left', ~~pos.x + 'px').style('top', ~~pos.y + 'px');
39913 tip.style('left', null).style('top', null);
39916 this.tooltipVisible = true;
39921 select(this).selectAll('.tooltip')
39922 .classed('in', false);
39924 this.tooltipVisible = false;
39928 function toggle() {
39929 if (this.tooltipVisible) {
39930 hide.apply(this, arguments);
39932 show.apply(this, arguments);
39940 function getPosition(node) {
39941 var mode = select(node).style('position');
39942 if (mode === 'absolute' || mode === 'static') {
39944 x: node.offsetLeft,
39946 w: node.offsetWidth,
39947 h: node.offsetHeight
39953 w: node.offsetWidth,
39954 h: node.offsetHeight
39959 function svgAreas$$1(projection, context) {
39960 // Patterns only work in Firefox when set directly on element.
39961 // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
39964 cemetery: 'cemetery',
39965 construction: 'construction',
39967 farmland: 'farmland',
39968 grave_yard: 'cemetery',
39970 military: 'construction',
39971 orchard: 'orchard',
39974 wetland: 'wetland',
39977 var patternKeys = ['landuse', 'natural', 'amenity'];
39980 function setPattern(d) {
39981 for (var i = 0; i < patternKeys.length; i++) {
39982 if (d.tags.building && d.tags.building !== 'no') continue;
39984 if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
39985 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
39989 this.style.fill = this.style.stroke = '';
39993 return function drawAreas(selection$$1, graph, entities, filter) {
39994 var path$$1 = svgPath(projection, graph, true),
39998 for (var i = 0; i < entities.length; i++) {
39999 var entity = entities[i];
40000 if (entity.geometry(graph) !== 'area') continue;
40002 multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph);
40003 if (multipolygon) {
40004 areas[multipolygon.id] = {
40005 entity: multipolygon.mergeTags(entity.tags),
40006 area: Math.abs(entity.area(graph))
40008 } else if (!areas[entity.id]) {
40009 areas[entity.id] = {
40011 area: Math.abs(entity.area(graph))
40016 areas = values(areas).filter(function hasPath(a) { return path$$1(a.entity); });
40017 areas.sort(function areaSort(a, b) { return b.area - a.area; });
40018 areas = lodash.map(areas, 'entity');
40020 var strokes = areas.filter(function(area$$1) {
40021 return area$$1.type === 'way';
40031 var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath')
40033 .data(data.clip, osmEntity$$1.key);
40038 var clipPathsEnter = clipPaths.enter()
40039 .append('clipPath')
40040 .attr('class', 'clipPath')
40041 .attr('id', function(entity) { return entity.id + '-clippath'; });
40046 clipPaths.merge(clipPathsEnter)
40048 .attr('d', path$$1);
40051 var layer = selection$$1.selectAll('.layer-areas');
40053 var areagroup = layer
40054 .selectAll('g.areagroup')
40055 .data(['fill', 'shadow', 'stroke']);
40057 areagroup = areagroup.enter()
40059 .attr('class', function(d) { return 'areagroup area-' + d; })
40062 var paths = areagroup
40065 .data(function(layer) { return data[layer]; }, osmEntity$$1.key);
40070 var fills = selection$$1.selectAll('.area-fill path.area').nodes();
40072 var bisect$$1 = bisector(function(node) {
40073 return -node.__data__.area(graph);
40076 function sortedByArea(entity) {
40077 if (this._parent.__data__ === 'fill') {
40078 return fills[bisect$$1(fills, -entity.area(graph))];
40082 paths = paths.enter()
40083 .insert('path', sortedByArea)
40085 .each(function(entity) {
40086 var layer = this.parentNode.__data__;
40088 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
40090 if (layer === 'fill') {
40091 this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
40092 setPattern.apply(this, arguments);
40095 .call(svgTagClasses())
40096 .attr('d', path$$1);
40100 function svgDebug(projection, context) {
40102 function multipolygons(imagery) {
40103 return imagery.map(function(data$$1) {
40105 type: 'MultiPolygon',
40106 coordinates: [ data$$1.polygon ]
40111 function drawDebug(selection$$1) {
40112 var showsTile = context.getDebug('tile'),
40113 showsCollision = context.getDebug('collision'),
40114 showsImagery = context.getDebug('imagery'),
40115 showsImperial = context.getDebug('imperial'),
40116 showsDriveLeft = context.getDebug('driveLeft'),
40117 path$$1 = index$4(projection);
40120 var debugData = [];
40122 debugData.push({ class: 'red', label: 'tile' });
40124 if (showsCollision) {
40125 debugData.push({ class: 'yellow', label: 'collision' });
40127 if (showsImagery) {
40128 debugData.push({ class: 'orange', label: 'imagery' });
40130 if (showsImperial) {
40131 debugData.push({ class: 'cyan', label: 'imperial' });
40133 if (showsDriveLeft) {
40134 debugData.push({ class: 'green', label: 'driveLeft' });
40138 var legend = select('#content')
40139 .selectAll('.debug-legend')
40140 .data(debugData.length ? [0] : []);
40145 legend = legend.enter()
40147 .attr('class', 'fillD debug-legend')
40151 var legendItems = legend.selectAll('.debug-legend-item')
40152 .data(debugData, function(d) { return d.label; });
40157 legendItems.enter()
40159 .attr('class', function(d) { return 'debug-legend-item ' + d.class; })
40160 .text(function(d) { return d.label; });
40163 var layer = selection$$1.selectAll('.layer-debug')
40164 .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
40169 layer = layer.enter()
40171 .attr('class', 'layer-debug')
40175 var extent$$1 = context.map().extent(),
40176 dataImagery = data.imagery || [],
40177 availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) {
40178 if (!source.polygon) return false;
40179 return source.polygon.some(function(polygon) {
40180 return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
40184 var imagery = layer.selectAll('path.debug-imagery')
40185 .data(showsImagery ? availableImagery : []);
40192 .attr('class', 'debug-imagery debug orange');
40195 var imperial = layer
40196 .selectAll('path.debug-imperial')
40197 .data(showsImperial ? [dataImperial] : []);
40204 .attr('class', 'debug-imperial debug cyan');
40207 var driveLeft = layer
40208 .selectAll('path.debug-drive-left')
40209 .data(showsDriveLeft ? [dataDriveLeft] : []);
40216 .attr('class', 'debug-drive-left debug green');
40220 layer.selectAll('path')
40221 .attr('d', path$$1);
40225 // This looks strange because `enabled` methods on other layers are
40226 // chainable getter/setters, and this one is just a getter.
40227 drawDebug.enabled = function() {
40228 if (!arguments.length) {
40229 return context.getDebug('tile') ||
40230 context.getDebug('collision') ||
40231 context.getDebug('imagery') ||
40232 context.getDebug('imperial') ||
40233 context.getDebug('driveLeft');
40244 A standalone SVG element that contains only a `defs` sub-element. To be
40245 used once globally, since defs IDs must be unique within a document.
40247 function svgDefs(context) {
40249 function SVGSpriteDefinition(id, href) {
40250 return function(defs) {
40252 .mimeType('image/svg+xml')
40253 .response(function(xhr) { return xhr.responseXML; })
40254 .get(function(err, svg) {
40256 defs.node().appendChild(
40257 select(svg.documentElement).attr('id', id).node()
40264 return function drawDefs(selection$$1) {
40265 var defs = selection$$1.append('defs');
40268 defs.append('marker')
40269 .attr('id', 'oneway-marker')
40270 .attr('viewBox', '0 0 10 10')
40273 .attr('markerWidth', 2)
40274 .attr('markerHeight', 2)
40275 .attr('markerUnits', 'strokeWidth')
40276 .attr('orient', 'auto')
40279 .attr('class', 'oneway')
40280 .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')
40281 .attr('stroke', 'none')
40282 .attr('fill', '#000')
40283 .attr('opacity', '0.75');
40286 var patterns = defs.selectAll('pattern')
40288 // pattern name, pattern image name
40289 ['wetland', 'wetland'],
40290 ['construction', 'construction'],
40291 ['cemetery', 'cemetery'],
40292 ['orchard', 'orchard'],
40293 ['farmland', 'farmland'],
40300 .attr('id', function (d) {
40301 return 'pattern-' + d[0];
40304 .attr('height', 32)
40305 .attr('patternUnits', 'userSpaceOnUse');
40307 patterns.append('rect')
40311 .attr('height', 32)
40312 .attr('class', function (d) {
40313 return 'pattern-color-' + d[0];
40316 patterns.append('image')
40320 .attr('height', 32)
40321 .attr('xlink:href', function (d) {
40322 return context.imagePath('pattern/' + d[1] + '.png');
40327 .data([12, 18, 20, 32, 45])
40329 .append('clipPath')
40330 .attr('id', function (d) {
40331 return 'clip-square-' + d;
40336 .attr('width', function (d) {
40339 .attr('height', function (d) {
40343 defs.call(SVGSpriteDefinition(
40345 context.imagePath('iD-sprite.svg')));
40347 defs.call(SVGSpriteDefinition(
40349 context.imagePath('maki-sprite.svg')));
40353 //[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]
40354 //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
40355 //[5] Name ::= NameStartChar (NameChar)*
40356 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
40357 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
40358 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
40359 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
40360 //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(',')
40362 //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
40363 //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
40364 var S_TAG = 0;//tag name offerring
40365 var S_ATTR = 1;//attr name offerring
40366 var S_ATTR_SPACE=2;//attr name end and space offer
40367 var S_EQ = 3;//=space?
40368 var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
40369 var S_ATTR_END = 5;//attr value end and no space(quot end)
40370 var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
40371 var S_TAG_CLOSE = 7;//closed el<el />
40373 function XMLReader(){
40377 XMLReader.prototype = {
40378 parse:function(source,defaultNSMap,entityMap){
40379 var domBuilder = this.domBuilder;
40380 domBuilder.startDocument();
40381 _copy(defaultNSMap ,defaultNSMap = {});
40382 parse(source,defaultNSMap,entityMap,
40383 domBuilder,this.errorHandler);
40384 domBuilder.endDocument();
40387 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
40388 function fixedFromCharCode(code) {
40389 // String.prototype.fromCharCode does not supports
40390 // > 2 bytes unicode chars directly
40391 if (code > 0xffff) {
40393 var surrogate1 = 0xd800 + (code >> 10)
40394 , surrogate2 = 0xdc00 + (code & 0x3ff);
40396 return String.fromCharCode(surrogate1, surrogate2);
40398 return String.fromCharCode(code);
40401 function entityReplacer(a){
40402 var k = a.slice(1,-1);
40403 if(k in entityMap){
40404 return entityMap[k];
40405 }else if(k.charAt(0) === '#'){
40406 return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
40408 errorHandler.error('entity not found:'+a);
40412 function appendText(end){//has some bugs
40414 var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
40415 locator&&position(start);
40416 domBuilder.characters(xt,0,end-start);
40420 function position(p,m){
40421 while(p>=lineEnd && (m = linePattern.exec(source))){
40422 lineStart = m.index;
40423 lineEnd = lineStart + m[0].length;
40424 locator.lineNumber++;
40425 //console.log('line++:',locator,startPos,endPos)
40427 locator.columnNumber = p-lineStart+1;
40431 var linePattern = /.*(?:\r\n?|\n)|.*$/g;
40432 var locator = domBuilder.locator;
40434 var parseStack = [{currentNSMap:defaultNSMapCopy}];
40439 var tagStart = source.indexOf('<',start);
40441 if(!source.substr(start).match(/^\s*$/)){
40442 var doc = domBuilder.doc;
40443 var text = doc.createTextNode(source.substr(start));
40444 doc.appendChild(text);
40445 domBuilder.currentElement = text;
40449 if(tagStart>start){
40450 appendText(tagStart);
40452 switch(source.charAt(tagStart+1)){
40454 var end = source.indexOf('>',tagStart+3);
40455 var tagName = source.substring(tagStart+2,end);
40456 var config = parseStack.pop();
40459 tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
40460 //console.error('#@@@@@@'+tagName)
40461 errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
40462 end = tagStart+1+tagName.length;
40463 }else if(tagName.match(/\s</)){
40464 tagName = tagName.replace(/[\s<].*/,'');
40465 errorHandler.error("end tag name: "+tagName+' maybe not complete');
40466 end = tagStart+1+tagName.length;
40468 //console.error(parseStack.length,parseStack)
40469 //console.error(config);
40470 var localNSMap = config.localNSMap;
40471 var endMatch = config.tagName == tagName;
40472 var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase();
40473 if(endIgnoreCaseMach){
40474 domBuilder.endElement(config.uri,config.localName,tagName);
40476 for(var prefix in localNSMap){
40477 domBuilder.endPrefixMapping(prefix) ;
40481 errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
40484 parseStack.push(config);
40490 case '?':// <?...?>
40491 locator&&position(tagStart);
40492 end = parseInstruction(source,tagStart,domBuilder);
40494 case '!':// <!doctype,<![CDATA,<!--
40495 locator&&position(tagStart);
40496 end = parseDCC(source,tagStart,domBuilder,errorHandler);
40499 locator&&position(tagStart);
40500 var el = new ElementAttributes();
40501 var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
40503 var end = parseElementStartPart(source,tagStart,el,currentNSMap,entityReplacer,errorHandler);
40504 var len = el.length;
40507 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
40509 if(!entityMap.nbsp){
40510 errorHandler.warning('unclosed xml attribute');
40513 if(locator && len){
40514 var locator2 = copyLocator(locator,{});
40515 //try{//attribute position fixed
40516 for(var i = 0;i<len;i++){
40518 position(a.offset);
40519 a.locator = copyLocator(locator,{});
40521 //}catch(e){console.error('@@@@@'+e)}
40522 domBuilder.locator = locator2;
40523 if(appendElement(el,domBuilder,currentNSMap)){
40524 parseStack.push(el);
40526 domBuilder.locator = locator;
40528 if(appendElement(el,domBuilder,currentNSMap)){
40529 parseStack.push(el);
40535 if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
40536 end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder);
40542 errorHandler.error('element parse error: '+e);
40543 //errorHandler.error('element parse error: '+e);
40550 //TODO: 这里有可能sax回退,有位置错误风险
40551 appendText(Math.max(tagStart,start)+1);
40555 function copyLocator(f,t){
40556 t.lineNumber = f.lineNumber;
40557 t.columnNumber = f.columnNumber;
40562 * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
40563 * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40565 function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
40569 var s = S_TAG;//status
40571 var c = source.charAt(p);
40574 if(s === S_ATTR){//attrName
40575 attrName = source.slice(start,p);
40577 }else if(s === S_ATTR_SPACE){
40580 //fatalError: equal must after attrName or space after attrName
40581 throw new Error('attribute equal must after attrName');
40586 if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
40589 errorHandler.warning('attribute value must after "="');
40590 attrName = source.slice(start,p);
40593 p = source.indexOf(c,start);
40595 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40596 el.add(attrName,value,start-1);
40599 //fatalError: no end quot match
40600 throw new Error('attribute value no end \''+c+'\' match');
40602 }else if(s == S_ATTR_NOQUOT_VALUE){
40603 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40604 //console.log(attrName,value,start,p)
40605 el.add(attrName,value,start);
40607 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
40611 //fatalError: no equal before
40612 throw new Error('attribute value must after "="');
40618 el.setTagName(source.slice(start,p));
40624 case S_ATTR_NOQUOT_VALUE:
40630 throw new Error("attribute invalid close char('/')")
40633 case ''://end document
40634 //throw new Error('unexpected end of input')
40635 errorHandler.error('unexpected end of input');
40637 el.setTagName(source.slice(start,p));
40643 el.setTagName(source.slice(start,p));
40648 case S_ATTR_NOQUOT_VALUE://Compatible state
40650 value = source.slice(start,p);
40651 if(value.slice(-1) === '/'){
40653 value = value.slice(0,-1);
40656 if(s === S_ATTR_SPACE){
40659 if(s == S_ATTR_NOQUOT_VALUE){
40660 errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40661 el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start);
40663 if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){
40664 errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!');
40666 el.add(value,value,start);
40670 throw new Error('attribute value missed!!');
40672 // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
40674 /*xml space '\x20' | #x9 | #xD | #xA; */
40678 if(c<= ' '){//space
40681 el.setTagName(source.slice(start,p));//tagName
40685 attrName = source.slice(start,p);
40688 case S_ATTR_NOQUOT_VALUE:
40689 var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40690 errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40691 el.add(attrName,value,start);
40695 //case S_TAG_SPACE:
40697 //case S_ATTR_SPACE:
40699 //case S_TAG_CLOSE:
40703 //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
40704 //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
40706 //case S_TAG:void();break;
40707 //case S_ATTR:void();break;
40708 //case S_ATTR_NOQUOT_VALUE:void();break;
40710 var tagName = el.tagName;
40711 if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){
40712 errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!');
40714 el.add(attrName,attrName,start);
40719 errorHandler.warning('attribute space is required"'+attrName+'"!!');
40725 s = S_ATTR_NOQUOT_VALUE;
40729 throw new Error("elements closed character '/' and '>' must be connected to");
40732 }//end outer switch
40733 //console.log('p++',p)
40738 * @return true if has new namespace define
40740 function appendElement(el,domBuilder,currentNSMap){
40741 var tagName = el.tagName;
40742 var localNSMap = null;
40743 //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
40747 var qName = a.qName;
40748 var value = a.value;
40749 var nsp = qName.indexOf(':');
40751 var prefix = a.prefix = qName.slice(0,nsp);
40752 var localName = qName.slice(nsp+1);
40753 var nsPrefix = prefix === 'xmlns' && localName;
40757 nsPrefix = qName === 'xmlns' && '';
40759 //can not set prefix,because prefix !== ''
40760 a.localName = localName ;
40761 //prefix == null for no ns prefix attribute
40762 if(nsPrefix !== false){//hack!!
40763 if(localNSMap == null){
40765 //console.log(currentNSMap,0)
40766 _copy(currentNSMap,currentNSMap={});
40767 //console.log(currentNSMap,1)
40769 currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
40770 a.uri = 'http://www.w3.org/2000/xmlns/';
40771 domBuilder.startPrefixMapping(nsPrefix, value);
40777 var prefix = a.prefix;
40778 if(prefix){//no prefix attribute has no namespace
40779 if(prefix === 'xml'){
40780 a.uri = 'http://www.w3.org/XML/1998/namespace';
40781 }if(prefix !== 'xmlns'){
40782 a.uri = currentNSMap[prefix || ''];
40784 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
40788 var nsp = tagName.indexOf(':');
40790 prefix = el.prefix = tagName.slice(0,nsp);
40791 localName = el.localName = tagName.slice(nsp+1);
40793 prefix = null;//important!!
40794 localName = el.localName = tagName;
40796 //no prefix element has default namespace
40797 var ns = el.uri = currentNSMap[prefix || ''];
40798 domBuilder.startElement(ns,localName,tagName,el);
40799 //endPrefixMapping and startPrefixMapping have not any help for dom builder
40800 //localNSMap = null
40802 domBuilder.endElement(ns,localName,tagName);
40804 for(prefix in localNSMap){
40805 domBuilder.endPrefixMapping(prefix);
40809 el.currentNSMap = currentNSMap;
40810 el.localNSMap = localNSMap;
40811 //parseStack.push(el);
40815 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
40816 if(/^(?:script|textarea)$/i.test(tagName)){
40817 var elEndStart = source.indexOf('</'+tagName+'>',elStartEnd);
40818 var text = source.substring(elStartEnd+1,elEndStart);
40819 if(/[&<]/.test(text)){
40820 if(/^script$/i.test(tagName)){
40821 //if(!/\]\]>/.test(text)){
40822 //lexHandler.startCDATA();
40823 domBuilder.characters(text,0,text.length);
40824 //lexHandler.endCDATA();
40827 }//}else{//text area
40828 text = text.replace(/&#?\w+;/g,entityReplacer);
40829 domBuilder.characters(text,0,text.length);
40835 return elStartEnd+1;
40837 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
40838 //if(tagName in closeMap){
40839 var pos = closeMap[tagName];
40841 //console.log(tagName)
40842 pos = source.lastIndexOf('</'+tagName+'>');
40843 if(pos<elStartEnd){//忘记闭合
40844 pos = source.lastIndexOf('</'+tagName);
40846 closeMap[tagName] =pos;
40848 return pos<elStartEnd;
40851 function _copy(source,target){
40852 for(var n in source){target[n] = source[n];}
40854 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
40855 var next= source.charAt(start+2);
40858 if(source.charAt(start + 3) === '-'){
40859 var end = source.indexOf('-->',start+4);
40860 //append comment source.substring(4,end)//<!--
40862 domBuilder.comment(source,start+4,end-start-4);
40865 errorHandler.error("Unclosed comment");
40873 if(source.substr(start+3,6) == 'CDATA['){
40874 var end = source.indexOf(']]>',start+9);
40875 domBuilder.startCDATA();
40876 domBuilder.characters(source,start+9,end-start-9);
40877 domBuilder.endCDATA();
40881 //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
40882 var matchs = split(source,start);
40883 var len = matchs.length;
40884 if(len>1 && /!doctype/i.test(matchs[0][0])){
40885 var name = matchs[1][0];
40886 var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
40887 var sysid = len>4 && matchs[4][0];
40888 var lastMatch = matchs[len-1];
40889 domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
40890 sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
40891 domBuilder.endDTD();
40893 return lastMatch.index+lastMatch[0].length
40901 function parseInstruction(source,start,domBuilder){
40902 var end = source.indexOf('?>',start);
40904 var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
40906 var len = match[0].length;
40907 domBuilder.processingInstruction(match[1], match[2]) ;
40919 function ElementAttributes(source){
40922 ElementAttributes.prototype = {
40923 setTagName:function(tagName){
40924 if(!tagNamePattern.test(tagName)){
40925 throw new Error('invalid tagName:'+tagName)
40927 this.tagName = tagName;
40929 add:function(qName,value,offset){
40930 if(!tagNamePattern.test(qName)){
40931 throw new Error('invalid attribute:'+qName)
40933 this[this.length++] = {qName:qName,value:value,offset:offset};
40936 getLocalName:function(i){return this[i].localName},
40937 getLocator:function(i){return this[i].locator},
40938 getQName:function(i){return this[i].qName},
40939 getURI:function(i){return this[i].uri},
40940 getValue:function(i){return this[i].value}
40941 // ,getIndex:function(uri, localName)){
40948 // getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
40949 // getType:function(uri,localName){}
40950 // getType:function(i){},
40956 function _set_proto_(thiz,parent){
40957 thiz.__proto__ = parent;
40960 if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
40961 _set_proto_ = function(thiz,parent){
40963 p.prototype = parent;
40965 for(parent in thiz){
40966 p[parent] = thiz[parent];
40972 function split(source,start){
40975 var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
40976 reg.lastIndex = start;
40977 reg.exec(source);//skip <
40978 while(match = reg.exec(source)){
40980 if(match[1])return buf;
40984 var XMLReader_1 = XMLReader;
40987 XMLReader: XMLReader_1
40992 * Object DOMException
40993 * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
40994 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
40997 function copy$1(src,dest){
41003 ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
41004 ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
41006 function _extends(Class,Super){
41007 var pt = Class.prototype;
41009 var ppt = Object.create(Super.prototype);
41010 pt.__proto__ = ppt;
41012 if(!(pt instanceof Super)){
41014 t.prototype = Super.prototype;
41017 Class.prototype = pt = t;
41019 if(pt.constructor != Class){
41020 if(typeof Class != 'function'){
41021 console.error("unknow Class:"+Class);
41023 pt.constructor = Class;
41026 var htmlns = 'http://www.w3.org/1999/xhtml';
41029 var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
41030 var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
41031 var TEXT_NODE = NodeType.TEXT_NODE = 3;
41032 var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4;
41033 var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5;
41034 var ENTITY_NODE = NodeType.ENTITY_NODE = 6;
41035 var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
41036 var COMMENT_NODE = NodeType.COMMENT_NODE = 8;
41037 var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9;
41038 var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10;
41039 var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
41040 var NOTATION_NODE = NodeType.NOTATION_NODE = 12;
41043 var ExceptionCode = {};
41044 var ExceptionMessage = {};
41045 var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1);
41046 var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2);
41047 var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3]="Hierarchy request error"),3);
41048 var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4]="Wrong document"),4);
41049 var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5]="Invalid character"),5);
41050 var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6]="No data allowed"),6);
41051 var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
41052 var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8]="Not found"),8);
41053 var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9]="Not supported"),9);
41054 var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10]="Attribute in use"),10);
41056 var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11]="Invalid state"),11);
41057 var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12]="Syntax error"),12);
41058 var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13]="Invalid modification"),13);
41059 var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14);
41060 var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15]="Invalid access"),15);
41063 function DOMException(code, message) {
41064 if(message instanceof Error){
41065 var error = message;
41068 Error.call(this, ExceptionMessage[code]);
41069 this.message = ExceptionMessage[code];
41070 if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
41073 if(message) this.message = this.message + ": " + message;
41076 DOMException.prototype = Error.prototype;
41077 copy$1(ExceptionCode,DOMException);
41079 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
41080 * 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.
41081 * The items in the NodeList are accessible via an integral index, starting from 0.
41083 function NodeList() {
41085 NodeList.prototype = {
41087 * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
41092 * 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.
41094 * @param index unsigned long
41095 * Index into the collection.
41097 * The node at the indexth position in the NodeList, or null if that is not a valid index.
41099 item: function(index) {
41100 return this[index] || null;
41102 toString:function(isHTML,nodeFilter){
41103 for(var buf = [], i = 0;i<this.length;i++){
41104 serializeToString(this[i],buf,isHTML,nodeFilter);
41106 return buf.join('');
41109 function LiveNodeList(node,refresh){
41111 this._refresh = refresh;
41112 _updateLiveList(this);
41114 function _updateLiveList(list){
41115 var inc = list._node._inc || list._node.ownerDocument._inc;
41116 if(list._inc != inc){
41117 var ls = list._refresh(list._node);
41118 //console.log(ls.length)
41119 __set__(list,'length',ls.length);
41124 LiveNodeList.prototype.item = function(i){
41125 _updateLiveList(this);
41129 _extends(LiveNodeList,NodeList);
41132 * 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.
41133 * NamedNodeMap objects in the DOM are live.
41134 * used for attributes or DocumentType entities
41136 function NamedNodeMap() {
41139 function _findNodeIndex(list,node){
41140 var i = list.length;
41142 if(list[i] === node){return i}
41146 function _addNamedNode(el,list,newAttr,oldAttr){
41148 list[_findNodeIndex(list,oldAttr)] = newAttr;
41150 list[list.length++] = newAttr;
41153 newAttr.ownerElement = el;
41154 var doc = el.ownerDocument;
41156 oldAttr && _onRemoveAttribute(doc,el,oldAttr);
41157 _onAddAttribute(doc,el,newAttr);
41161 function _removeNamedNode(el,list,attr){
41162 //console.log('remove attr:'+attr)
41163 var i = _findNodeIndex(list,attr);
41165 var lastIndex = list.length-1;
41166 while(i<lastIndex){
41167 list[i] = list[++i];
41169 list.length = lastIndex;
41171 var doc = el.ownerDocument;
41173 _onRemoveAttribute(doc,el,attr);
41174 attr.ownerElement = null;
41178 throw DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr))
41181 NamedNodeMap.prototype = {
41183 item:NodeList.prototype.item,
41184 getNamedItem: function(key) {
41185 // if(key.indexOf(':')>0 || key == 'xmlns'){
41189 var i = this.length;
41191 var attr = this[i];
41192 //console.log(attr.nodeName,key)
41193 if(attr.nodeName == key){
41198 setNamedItem: function(attr) {
41199 var el = attr.ownerElement;
41200 if(el && el!=this._ownerElement){
41201 throw new DOMException(INUSE_ATTRIBUTE_ERR);
41203 var oldAttr = this.getNamedItem(attr.nodeName);
41204 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41208 setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
41209 var el = attr.ownerElement, oldAttr;
41210 if(el && el!=this._ownerElement){
41211 throw new DOMException(INUSE_ATTRIBUTE_ERR);
41213 oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
41214 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41219 removeNamedItem: function(key) {
41220 var attr = this.getNamedItem(key);
41221 _removeNamedNode(this._ownerElement,this,attr);
41225 },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
41228 removeNamedItemNS:function(namespaceURI,localName){
41229 var attr = this.getNamedItemNS(namespaceURI,localName);
41230 _removeNamedNode(this._ownerElement,this,attr);
41233 getNamedItemNS: function(namespaceURI, localName) {
41234 var i = this.length;
41236 var node = this[i];
41237 if(node.localName == localName && node.namespaceURI == namespaceURI){
41245 * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
41247 function DOMImplementation(/* Object */ features) {
41248 this._features = {};
41250 for (var feature in features) {
41251 this._features = features[feature];
41256 DOMImplementation.prototype = {
41257 hasFeature: function(/* string */ feature, /* string */ version) {
41258 var versions = this._features[feature.toLowerCase()];
41259 if (versions && (!version || version in versions)) {
41265 // Introduced in DOM Level 2:
41266 createDocument:function(namespaceURI, qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
41267 var doc = new Document();
41268 doc.implementation = this;
41269 doc.childNodes = new NodeList();
41270 doc.doctype = doctype;
41272 doc.appendChild(doctype);
41275 var root = doc.createElementNS(namespaceURI,qualifiedName);
41276 doc.appendChild(root);
41280 // Introduced in DOM Level 2:
41281 createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
41282 var node = new DocumentType();
41283 node.name = qualifiedName;
41284 node.nodeName = qualifiedName;
41285 node.publicId = publicId;
41286 node.systemId = systemId;
41287 // Introduced in DOM Level 2:
41288 //readonly attribute DOMString internalSubset;
41291 // readonly attribute NamedNodeMap entities;
41292 // readonly attribute NamedNodeMap notations;
41299 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
41302 function Node$3() {
41305 Node$3.prototype = {
41308 previousSibling : null,
41309 nextSibling : null,
41313 ownerDocument : null,
41315 namespaceURI : null,
41318 // Modified in DOM Level 2:
41319 insertBefore:function(newChild, refChild){//raises
41320 return _insertBefore(this,newChild,refChild);
41322 replaceChild:function(newChild, oldChild){//raises
41323 this.insertBefore(newChild,oldChild);
41325 this.removeChild(oldChild);
41328 removeChild:function(oldChild){
41329 return _removeChild(this,oldChild);
41331 appendChild:function(newChild){
41332 return this.insertBefore(newChild,null);
41334 hasChildNodes:function(){
41335 return this.firstChild != null;
41337 cloneNode:function(deep){
41338 return cloneNode(this.ownerDocument||this,this,deep);
41340 // Modified in DOM Level 2:
41341 normalize:function(){
41342 var child = this.firstChild;
41344 var next = child.nextSibling;
41345 if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
41346 this.removeChild(next);
41347 child.appendData(next.data);
41354 // Introduced in DOM Level 2:
41355 isSupported:function(feature, version){
41356 return this.ownerDocument.implementation.hasFeature(feature,version);
41358 // Introduced in DOM Level 2:
41359 hasAttributes:function(){
41360 return this.attributes.length>0;
41362 lookupPrefix:function(namespaceURI){
41365 var map = el._nsMap;
41369 if(map[n] == namespaceURI){
41374 el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
41378 // Introduced in DOM Level 3:
41379 lookupNamespaceURI:function(prefix){
41382 var map = el._nsMap;
41386 return map[prefix] ;
41389 el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
41393 // Introduced in DOM Level 3:
41394 isDefaultNamespace:function(namespaceURI){
41395 var prefix = this.lookupPrefix(namespaceURI);
41396 return prefix == null;
41401 function _xmlEncoder(c){
41402 return c == '<' && '<' ||
41403 c == '>' && '>' ||
41404 c == '&' && '&' ||
41405 c == '"' && '"' ||
41406 '&#'+c.charCodeAt()+';'
41410 copy$1(NodeType,Node$3);
41411 copy$1(NodeType,Node$3.prototype);
41414 * @param callback return true for continue,false for break
41415 * @return boolean true: break visit;
41417 function _visitNode(node,callback){
41418 if(callback(node)){
41421 if(node = node.firstChild){
41423 if(_visitNode(node,callback)){return true}
41424 }while(node=node.nextSibling)
41430 function Document(){
41432 function _onAddAttribute(doc,el,newAttr){
41434 var ns = newAttr.namespaceURI;
41435 if(ns == 'http://www.w3.org/2000/xmlns/'){
41437 el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value;
41440 function _onRemoveAttribute(doc,el,newAttr,remove){
41442 var ns = newAttr.namespaceURI;
41443 if(ns == 'http://www.w3.org/2000/xmlns/'){
41445 delete el._nsMap[newAttr.prefix?newAttr.localName:''];
41448 function _onUpdateChild(doc,el,newChild){
41449 if(doc && doc._inc){
41451 //update childNodes
41452 var cs = el.childNodes;
41454 cs[cs.length++] = newChild;
41457 var child = el.firstChild;
41461 child =child.nextSibling;
41472 * writeable properties:
41473 * nodeValue,Attr:value,CharacterData:data
41476 function _removeChild(parentNode,child){
41477 var previous = child.previousSibling;
41478 var next = child.nextSibling;
41480 previous.nextSibling = next;
41482 parentNode.firstChild = next;
41485 next.previousSibling = previous;
41487 parentNode.lastChild = previous;
41489 _onUpdateChild(parentNode.ownerDocument,parentNode);
41493 * preformance key(refChild == null)
41495 function _insertBefore(parentNode,newChild,nextChild){
41496 var cp = newChild.parentNode;
41498 cp.removeChild(newChild);//remove and update
41500 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41501 var newFirst = newChild.firstChild;
41502 if (newFirst == null) {
41505 var newLast = newChild.lastChild;
41507 newFirst = newLast = newChild;
41509 var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
41511 newFirst.previousSibling = pre;
41512 newLast.nextSibling = nextChild;
41516 pre.nextSibling = newFirst;
41518 parentNode.firstChild = newFirst;
41520 if(nextChild == null){
41521 parentNode.lastChild = newLast;
41523 nextChild.previousSibling = newLast;
41526 newFirst.parentNode = parentNode;
41527 }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
41528 _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
41529 //console.log(parentNode.lastChild.nextSibling == null)
41530 if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
41531 newChild.firstChild = newChild.lastChild = null;
41535 function _appendSingleChild(parentNode,newChild){
41536 var cp = newChild.parentNode;
41538 var pre = parentNode.lastChild;
41539 cp.removeChild(newChild);//remove and update
41540 var pre = parentNode.lastChild;
41542 var pre = parentNode.lastChild;
41543 newChild.parentNode = parentNode;
41544 newChild.previousSibling = pre;
41545 newChild.nextSibling = null;
41547 pre.nextSibling = newChild;
41549 parentNode.firstChild = newChild;
41551 parentNode.lastChild = newChild;
41552 _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
41554 //console.log("__aa",parentNode.lastChild.nextSibling == null)
41556 Document.prototype = {
41557 //implementation : null,
41558 nodeName : '#document',
41559 nodeType : DOCUMENT_NODE,
41561 documentElement : null,
41564 insertBefore : function(newChild, refChild){//raises
41565 if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
41566 var child = newChild.firstChild;
41568 var next = child.nextSibling;
41569 this.insertBefore(child,refChild);
41574 if(this.documentElement == null && newChild.nodeType == ELEMENT_NODE){
41575 this.documentElement = newChild;
41578 return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
41580 removeChild : function(oldChild){
41581 if(this.documentElement == oldChild){
41582 this.documentElement = null;
41584 return _removeChild(this,oldChild);
41586 // Introduced in DOM Level 2:
41587 importNode : function(importedNode,deep){
41588 return importNode(this,importedNode,deep);
41590 // Introduced in DOM Level 2:
41591 getElementById : function(id){
41593 _visitNode(this.documentElement,function(node){
41594 if(node.nodeType == ELEMENT_NODE){
41595 if(node.getAttribute('id') == id){
41604 //document factory method:
41605 createElement : function(tagName){
41606 var node = new Element();
41607 node.ownerDocument = this;
41608 node.nodeName = tagName;
41609 node.tagName = tagName;
41610 node.childNodes = new NodeList();
41611 var attrs = node.attributes = new NamedNodeMap();
41612 attrs._ownerElement = node;
41615 createDocumentFragment : function(){
41616 var node = new DocumentFragment();
41617 node.ownerDocument = this;
41618 node.childNodes = new NodeList();
41621 createTextNode : function(data){
41622 var node = new Text();
41623 node.ownerDocument = this;
41624 node.appendData(data);
41627 createComment : function(data){
41628 var node = new Comment();
41629 node.ownerDocument = this;
41630 node.appendData(data);
41633 createCDATASection : function(data){
41634 var node = new CDATASection();
41635 node.ownerDocument = this;
41636 node.appendData(data);
41639 createProcessingInstruction : function(target,data){
41640 var node = new ProcessingInstruction();
41641 node.ownerDocument = this;
41642 node.tagName = node.target = target;
41643 node.nodeValue= node.data = data;
41646 createAttribute : function(name){
41647 var node = new Attr();
41648 node.ownerDocument = this;
41650 node.nodeName = name;
41651 node.localName = name;
41652 node.specified = true;
41655 createEntityReference : function(name){
41656 var node = new EntityReference();
41657 node.ownerDocument = this;
41658 node.nodeName = name;
41661 // Introduced in DOM Level 2:
41662 createElementNS : function(namespaceURI,qualifiedName){
41663 var node = new Element();
41664 var pl = qualifiedName.split(':');
41665 var attrs = node.attributes = new NamedNodeMap();
41666 node.childNodes = new NodeList();
41667 node.ownerDocument = this;
41668 node.nodeName = qualifiedName;
41669 node.tagName = qualifiedName;
41670 node.namespaceURI = namespaceURI;
41671 if(pl.length == 2){
41672 node.prefix = pl[0];
41673 node.localName = pl[1];
41675 //el.prefix = null;
41676 node.localName = qualifiedName;
41678 attrs._ownerElement = node;
41681 // Introduced in DOM Level 2:
41682 createAttributeNS : function(namespaceURI,qualifiedName){
41683 var node = new Attr();
41684 var pl = qualifiedName.split(':');
41685 node.ownerDocument = this;
41686 node.nodeName = qualifiedName;
41687 node.name = qualifiedName;
41688 node.namespaceURI = namespaceURI;
41689 node.specified = true;
41690 if(pl.length == 2){
41691 node.prefix = pl[0];
41692 node.localName = pl[1];
41694 //el.prefix = null;
41695 node.localName = qualifiedName;
41700 _extends(Document,Node$3);
41703 function Element() {
41706 Element.prototype = {
41707 nodeType : ELEMENT_NODE,
41708 hasAttribute : function(name){
41709 return this.getAttributeNode(name)!=null;
41711 getAttribute : function(name){
41712 var attr = this.getAttributeNode(name);
41713 return attr && attr.value || '';
41715 getAttributeNode : function(name){
41716 return this.attributes.getNamedItem(name);
41718 setAttribute : function(name, value){
41719 var attr = this.ownerDocument.createAttribute(name);
41720 attr.value = attr.nodeValue = "" + value;
41721 this.setAttributeNode(attr);
41723 removeAttribute : function(name){
41724 var attr = this.getAttributeNode(name);
41725 attr && this.removeAttributeNode(attr);
41728 //four real opeartion method
41729 appendChild:function(newChild){
41730 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41731 return this.insertBefore(newChild,null);
41733 return _appendSingleChild(this,newChild);
41736 setAttributeNode : function(newAttr){
41737 return this.attributes.setNamedItem(newAttr);
41739 setAttributeNodeNS : function(newAttr){
41740 return this.attributes.setNamedItemNS(newAttr);
41742 removeAttributeNode : function(oldAttr){
41743 //console.log(this == oldAttr.ownerElement)
41744 return this.attributes.removeNamedItem(oldAttr.nodeName);
41746 //get real attribute name,and remove it by removeAttributeNode
41747 removeAttributeNS : function(namespaceURI, localName){
41748 var old = this.getAttributeNodeNS(namespaceURI, localName);
41749 old && this.removeAttributeNode(old);
41752 hasAttributeNS : function(namespaceURI, localName){
41753 return this.getAttributeNodeNS(namespaceURI, localName)!=null;
41755 getAttributeNS : function(namespaceURI, localName){
41756 var attr = this.getAttributeNodeNS(namespaceURI, localName);
41757 return attr && attr.value || '';
41759 setAttributeNS : function(namespaceURI, qualifiedName, value){
41760 var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
41761 attr.value = attr.nodeValue = "" + value;
41762 this.setAttributeNode(attr);
41764 getAttributeNodeNS : function(namespaceURI, localName){
41765 return this.attributes.getNamedItemNS(namespaceURI, localName);
41768 getElementsByTagName : function(tagName){
41769 return new LiveNodeList(this,function(base){
41771 _visitNode(base,function(node){
41772 if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
41779 getElementsByTagNameNS : function(namespaceURI, localName){
41780 return new LiveNodeList(this,function(base){
41782 _visitNode(base,function(node){
41783 if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
41792 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
41793 Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
41796 _extends(Element,Node$3);
41799 Attr.prototype.nodeType = ATTRIBUTE_NODE;
41800 _extends(Attr,Node$3);
41803 function CharacterData() {
41805 CharacterData.prototype = {
41807 substringData : function(offset, count) {
41808 return this.data.substring(offset, offset+count);
41810 appendData: function(text) {
41811 text = this.data+text;
41812 this.nodeValue = this.data = text;
41813 this.length = text.length;
41815 insertData: function(offset,text) {
41816 this.replaceData(offset,0,text);
41819 appendChild:function(newChild){
41820 throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR])
41822 deleteData: function(offset, count) {
41823 this.replaceData(offset,count,"");
41825 replaceData: function(offset, count, text) {
41826 var start = this.data.substring(0,offset);
41827 var end = this.data.substring(offset+count);
41828 text = start + text + end;
41829 this.nodeValue = this.data = text;
41830 this.length = text.length;
41833 _extends(CharacterData,Node$3);
41837 nodeName : "#text",
41838 nodeType : TEXT_NODE,
41839 splitText : function(offset) {
41840 var text = this.data;
41841 var newText = text.substring(offset);
41842 text = text.substring(0, offset);
41843 this.data = this.nodeValue = text;
41844 this.length = text.length;
41845 var newNode = this.ownerDocument.createTextNode(newText);
41846 if(this.parentNode){
41847 this.parentNode.insertBefore(newNode, this.nextSibling);
41852 _extends(Text,CharacterData);
41853 function Comment() {
41855 Comment.prototype = {
41856 nodeName : "#comment",
41857 nodeType : COMMENT_NODE
41859 _extends(Comment,CharacterData);
41861 function CDATASection() {
41863 CDATASection.prototype = {
41864 nodeName : "#cdata-section",
41865 nodeType : CDATA_SECTION_NODE
41867 _extends(CDATASection,CharacterData);
41870 function DocumentType() {
41872 DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
41873 _extends(DocumentType,Node$3);
41875 function Notation() {
41877 Notation.prototype.nodeType = NOTATION_NODE;
41878 _extends(Notation,Node$3);
41880 function Entity() {
41882 Entity.prototype.nodeType = ENTITY_NODE;
41883 _extends(Entity,Node$3);
41885 function EntityReference() {
41887 EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
41888 _extends(EntityReference,Node$3);
41890 function DocumentFragment() {
41892 DocumentFragment.prototype.nodeName = "#document-fragment";
41893 DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
41894 _extends(DocumentFragment,Node$3);
41897 function ProcessingInstruction() {
41899 ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
41900 _extends(ProcessingInstruction,Node$3);
41901 function XMLSerializer$1(){}
41902 XMLSerializer$1.prototype.serializeToString = function(node,isHtml,nodeFilter){
41903 return nodeSerializeToString.call(node,isHtml,nodeFilter);
41905 Node$3.prototype.toString = nodeSerializeToString;
41906 function nodeSerializeToString(isHtml,nodeFilter){
41908 var refNode = this.nodeType == 9?this.documentElement:this;
41909 var prefix = refNode.prefix;
41910 var uri = refNode.namespaceURI;
41912 if(uri && prefix == null){
41913 //console.log(prefix)
41914 var prefix = refNode.lookupPrefix(uri);
41915 if(prefix == null){
41917 var visibleNamespaces=[
41918 {namespace:uri,prefix:null}
41919 //{namespace:uri,prefix:''}
41923 serializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces);
41924 //console.log('###',this.nodeType,uri,prefix,buf.join(''))
41925 return buf.join('');
41927 function needNamespaceDefine(node,isHTML, visibleNamespaces) {
41928 var prefix = node.prefix||'';
41929 var uri = node.namespaceURI;
41930 if (!prefix && !uri){
41933 if (prefix === "xml" && uri === "http://www.w3.org/XML/1998/namespace"
41934 || uri == 'http://www.w3.org/2000/xmlns/'){
41938 var i = visibleNamespaces.length;
41939 //console.log('@@@@',node.tagName,prefix,uri,visibleNamespaces)
41941 var ns = visibleNamespaces[i];
41942 // get namespace prefix
41943 //console.log(node.nodeType,node.tagName,ns.prefix,prefix)
41944 if (ns.prefix == prefix){
41945 return ns.namespace != uri;
41948 //console.log(isHTML,uri,prefix=='')
41949 //if(isHTML && prefix ==null && uri == 'http://www.w3.org/1999/xhtml'){
41952 //node.flag = '11111'
41953 //console.error(3,true,node.flag,node.prefix,node.namespaceURI)
41956 function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
41958 node = nodeFilter(node);
41960 if(typeof node == 'string'){
41967 //buf.sort.apply(attrs, attributeSorter);
41969 switch(node.nodeType){
41971 if (!visibleNamespaces) visibleNamespaces = [];
41972 var startVisibleNamespaces = visibleNamespaces.length;
41973 var attrs = node.attributes;
41974 var len = attrs.length;
41975 var child = node.firstChild;
41976 var nodeName = node.tagName;
41978 isHTML = (htmlns === node.namespaceURI) ||isHTML;
41979 buf.push('<',nodeName);
41983 for(var i=0;i<len;i++){
41984 // add namespaces for attributes
41985 var attr = attrs.item(i);
41986 if (attr.prefix == 'xmlns') {
41987 visibleNamespaces.push({ prefix: attr.localName, namespace: attr.value });
41988 }else if(attr.nodeName == 'xmlns'){
41989 visibleNamespaces.push({ prefix: '', namespace: attr.value });
41992 for(var i=0;i<len;i++){
41993 var attr = attrs.item(i);
41994 if (needNamespaceDefine(attr,isHTML, visibleNamespaces)) {
41995 var prefix = attr.prefix||'';
41996 var uri = attr.namespaceURI;
41997 var ns = prefix ? ' xmlns:' + prefix : " xmlns";
41998 buf.push(ns, '="' , uri , '"');
41999 visibleNamespaces.push({ prefix: prefix, namespace:uri });
42001 serializeToString(attr,buf,isHTML,nodeFilter,visibleNamespaces);
42003 // add namespace for current node
42004 if (needNamespaceDefine(node,isHTML, visibleNamespaces)) {
42005 var prefix = node.prefix||'';
42006 var uri = node.namespaceURI;
42007 var ns = prefix ? ' xmlns:' + prefix : " xmlns";
42008 buf.push(ns, '="' , uri , '"');
42009 visibleNamespaces.push({ prefix: prefix, namespace:uri });
42012 if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){
42014 //if is cdata child node
42015 if(isHTML && /^script$/i.test(nodeName)){
42018 buf.push(child.data);
42020 serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
42022 child = child.nextSibling;
42027 serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
42028 child = child.nextSibling;
42031 buf.push('</',nodeName,'>');
42035 // remove added visible namespaces
42036 //visibleNamespaces.length = startVisibleNamespaces;
42038 case DOCUMENT_NODE:
42039 case DOCUMENT_FRAGMENT_NODE:
42040 var child = node.firstChild;
42042 serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
42043 child = child.nextSibling;
42046 case ATTRIBUTE_NODE:
42047 return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
42049 return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
42050 case CDATA_SECTION_NODE:
42051 return buf.push( '<![CDATA[',node.data,']]>');
42053 return buf.push( "<!--",node.data,"-->");
42054 case DOCUMENT_TYPE_NODE:
42055 var pubid = node.publicId;
42056 var sysid = node.systemId;
42057 buf.push('<!DOCTYPE ',node.name);
42059 buf.push(' PUBLIC "',pubid);
42060 if (sysid && sysid!='.') {
42061 buf.push( '" "',sysid);
42064 }else if(sysid && sysid!='.'){
42065 buf.push(' SYSTEM "',sysid,'">');
42067 var sub = node.internalSubset;
42069 buf.push(" [",sub,"]");
42074 case PROCESSING_INSTRUCTION_NODE:
42075 return buf.push( "<?",node.target," ",node.data,"?>");
42076 case ENTITY_REFERENCE_NODE:
42077 return buf.push( '&',node.nodeName,';');
42078 //case ENTITY_NODE:
42079 //case NOTATION_NODE:
42081 buf.push('??',node.nodeName);
42084 function importNode(doc,node,deep){
42086 switch (node.nodeType) {
42088 node2 = node.cloneNode(false);
42089 node2.ownerDocument = doc;
42090 //var attrs = node2.attributes;
42091 //var len = attrs.length;
42092 //for(var i=0;i<len;i++){
42093 //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
42095 case DOCUMENT_FRAGMENT_NODE:
42097 case ATTRIBUTE_NODE:
42100 //case ENTITY_REFERENCE_NODE:
42101 //case PROCESSING_INSTRUCTION_NODE:
42102 ////case TEXT_NODE:
42103 //case CDATA_SECTION_NODE:
42104 //case COMMENT_NODE:
42107 //case DOCUMENT_NODE:
42108 //case DOCUMENT_TYPE_NODE:
42109 //cannot be imported.
42110 //case ENTITY_NODE:
42111 //case NOTATION_NODE:
42112 //can not hit in level3
42116 node2 = node.cloneNode(false);//false
42118 node2.ownerDocument = doc;
42119 node2.parentNode = null;
42121 var child = node.firstChild;
42123 node2.appendChild(importNode(doc,child,deep));
42124 child = child.nextSibling;
42130 //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
42131 // attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
42132 function cloneNode(doc,node,deep){
42133 var node2 = new node.constructor();
42134 for(var n in node){
42136 if(typeof v != 'object' ){
42142 if(node.childNodes){
42143 node2.childNodes = new NodeList();
42145 node2.ownerDocument = doc;
42146 switch (node2.nodeType) {
42148 var attrs = node.attributes;
42149 var attrs2 = node2.attributes = new NamedNodeMap();
42150 var len = attrs.length;
42151 attrs2._ownerElement = node2;
42152 for(var i=0;i<len;i++){
42153 node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
42156 case ATTRIBUTE_NODE:
42160 var child = node.firstChild;
42162 node2.appendChild(cloneNode(doc,child,deep));
42163 child = child.nextSibling;
42169 function __set__(object,key,value){
42170 object[key] = value;
42174 if(Object.defineProperty){
42175 Object.defineProperty(LiveNodeList.prototype,'length',{
42177 _updateLiveList(this);
42178 return this.$$length;
42181 Object.defineProperty(Node$3.prototype,'textContent',{
42183 return getTextContent(this);
42185 set:function(data){
42186 switch(this.nodeType){
42188 case DOCUMENT_FRAGMENT_NODE:
42189 while(this.firstChild){
42190 this.removeChild(this.firstChild);
42192 if(data || String(data)){
42193 this.appendChild(this.ownerDocument.createTextNode(data));
42200 this.nodeValue = data;
42205 function getTextContent(node){
42206 switch(node.nodeType){
42208 case DOCUMENT_FRAGMENT_NODE:
42210 node = node.firstChild;
42212 if(node.nodeType!==7 && node.nodeType !==8){
42213 buf.push(getTextContent(node));
42215 node = node.nextSibling;
42217 return buf.join('');
42219 return node.nodeValue;
42222 __set__ = function(object,key,value){
42223 //console.log(value)
42224 object['$$'+key] = value;
42230 //if(typeof require == 'function'){
42231 var DOMImplementation_1 = DOMImplementation;
42232 var XMLSerializer_1 = XMLSerializer$1;
42236 DOMImplementation: DOMImplementation_1,
42237 XMLSerializer: XMLSerializer_1
42240 var domParser = createCommonjsModule(function (module, exports) {
42241 function DOMParser(options){
42242 this.options = options ||{locator:{}};
42245 DOMParser.prototype.parseFromString = function(source,mimeType){
42246 var options = this.options;
42247 var sax$$1 = new XMLReader();
42248 var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
42249 var errorHandler = options.errorHandler;
42250 var locator = options.locator;
42251 var defaultNSMap = options.xmlns||{};
42252 var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
42254 domBuilder.setDocumentLocator(locator);
42257 sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
42258 sax$$1.domBuilder = options.domBuilder || domBuilder;
42259 if(/\/x?html?$/.test(mimeType)){
42260 entityMap.nbsp = '\xa0';
42261 entityMap.copy = '\xa9';
42262 defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
42264 defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
42266 sax$$1.parse(source,defaultNSMap,entityMap);
42268 sax$$1.errorHandler.error("invalid doc source");
42270 return domBuilder.doc;
42272 function buildErrorHandler(errorImpl,domBuilder,locator){
42274 if(domBuilder instanceof DOMHandler){
42277 errorImpl = domBuilder ;
42279 var errorHandler = {};
42280 var isCallback = errorImpl instanceof Function;
42281 locator = locator||{};
42282 function build(key){
42283 var fn = errorImpl[key];
42284 if(!fn && isCallback){
42285 fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl;
42287 errorHandler[key] = fn && function(msg){
42288 fn('[xmldom '+key+']\t'+msg+_locator(locator));
42293 build('fatalError');
42294 return errorHandler;
42297 //console.log('#\n\n\n\n\n\n\n####')
42299 * +ContentHandler+ErrorHandler
42300 * +LexicalHandler+EntityResolver2
42301 * -DeclHandler-DTDHandler
42303 * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
42304 * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
42305 * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
42307 function DOMHandler() {
42308 this.cdata = false;
42310 function position(locator,node){
42311 node.lineNumber = locator.lineNumber;
42312 node.columnNumber = locator.columnNumber;
42315 * @see org.xml.sax.ContentHandler#startDocument
42316 * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
42318 DOMHandler.prototype = {
42319 startDocument : function() {
42320 this.doc = new DOMImplementation().createDocument(null, null, null);
42321 if (this.locator) {
42322 this.doc.documentURI = this.locator.systemId;
42325 startElement:function(namespaceURI, localName, qName, attrs) {
42326 var doc = this.doc;
42327 var el = doc.createElementNS(namespaceURI, qName||localName);
42328 var len = attrs.length;
42329 appendElement(this, el);
42330 this.currentElement = el;
42332 this.locator && position(this.locator,el);
42333 for (var i = 0 ; i < len; i++) {
42334 var namespaceURI = attrs.getURI(i);
42335 var value = attrs.getValue(i);
42336 var qName = attrs.getQName(i);
42337 var attr = doc.createAttributeNS(namespaceURI, qName);
42338 this.locator &&position(attrs.getLocator(i),attr);
42339 attr.value = attr.nodeValue = value;
42340 el.setAttributeNode(attr);
42343 endElement:function(namespaceURI, localName, qName) {
42344 var current = this.currentElement;
42345 var tagName = current.tagName;
42346 this.currentElement = current.parentNode;
42348 startPrefixMapping:function(prefix, uri) {
42350 endPrefixMapping:function(prefix) {
42352 processingInstruction:function(target, data) {
42353 var ins = this.doc.createProcessingInstruction(target, data);
42354 this.locator && position(this.locator,ins);
42355 appendElement(this, ins);
42357 ignorableWhitespace:function(ch, start, length) {
42359 characters:function(chars, start, length) {
42360 chars = _toString.apply(this,arguments);
42361 //console.log(chars)
42364 var charNode = this.doc.createCDATASection(chars);
42366 var charNode = this.doc.createTextNode(chars);
42368 if(this.currentElement){
42369 this.currentElement.appendChild(charNode);
42370 }else if(/^\s*$/.test(chars)){
42371 this.doc.appendChild(charNode);
42374 this.locator && position(this.locator,charNode);
42377 skippedEntity:function(name) {
42379 endDocument:function() {
42380 this.doc.normalize();
42382 setDocumentLocator:function (locator) {
42383 if(this.locator = locator){// && !('lineNumber' in locator)){
42384 locator.lineNumber = 0;
42388 comment:function(chars, start, length) {
42389 chars = _toString.apply(this,arguments);
42390 var comm = this.doc.createComment(chars);
42391 this.locator && position(this.locator,comm);
42392 appendElement(this, comm);
42395 startCDATA:function() {
42396 //used in characters() methods
42399 endCDATA:function() {
42400 this.cdata = false;
42403 startDTD:function(name, publicId, systemId) {
42404 var impl = this.doc.implementation;
42405 if (impl && impl.createDocumentType) {
42406 var dt = impl.createDocumentType(name, publicId, systemId);
42407 this.locator && position(this.locator,dt);
42408 appendElement(this, dt);
42412 * @see org.xml.sax.ErrorHandler
42413 * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
42415 warning:function(error) {
42416 console.warn('[xmldom warning]\t'+error,_locator(this.locator));
42418 error:function(error) {
42419 console.error('[xmldom error]\t'+error,_locator(this.locator));
42421 fatalError:function(error) {
42422 console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
42426 function _locator(l){
42428 return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
42431 function _toString(chars,start,length){
42432 if(typeof chars == 'string'){
42433 return chars.substr(start,length)
42434 }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
42435 if(chars.length >= start+length || start){
42436 return new java.lang.String(chars,start,length)+'';
42443 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
42444 * used method of org.xml.sax.ext.LexicalHandler:
42445 * #comment(chars, start, length)
42448 * #startDTD(name, publicId, systemId)
42451 * IGNORED method of org.xml.sax.ext.LexicalHandler:
42453 * #startEntity(name)
42457 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
42458 * IGNORED method of org.xml.sax.ext.DeclHandler
42459 * #attributeDecl(eName, aName, type, mode, value)
42460 * #elementDecl(name, model)
42461 * #externalEntityDecl(name, publicId, systemId)
42462 * #internalEntityDecl(name, value)
42463 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
42464 * IGNORED method of org.xml.sax.EntityResolver2
42465 * #resolveEntity(String name,String publicId,String baseURI,String systemId)
42466 * #resolveEntity(publicId, systemId)
42467 * #getExternalSubset(name, baseURI)
42468 * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
42469 * IGNORED method of org.xml.sax.DTDHandler
42470 * #notationDecl(name, publicId, systemId) {};
42471 * #unparsedEntityDecl(name, publicId, systemId, notationName) {};
42473 "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
42474 DOMHandler.prototype[key] = function(){return null};
42477 /* 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 */
42478 function appendElement (hander,node) {
42479 if (!hander.currentElement) {
42480 hander.doc.appendChild(node);
42482 hander.currentElement.appendChild(node);
42484 }//appendChild and setAttributeNS are preformance key
42486 //if(typeof require == 'function'){
42487 var XMLReader = sax.XMLReader;
42488 var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation;
42489 exports.XMLSerializer = dom.XMLSerializer ;
42490 exports.DOMParser = DOMParser;
42494 var togeojson = createCommonjsModule(function (module, exports) {
42495 var toGeoJSON = (function() {
42498 var removeSpace = /\s*/g,
42499 trimSpace = /^\s*|\s*$/g,
42500 splitSpace = /\s+/;
42501 // generate a short, numeric hash of a string
42502 function okhash(x) {
42503 if (!x || !x.length) return 0;
42504 for (var i = 0, h = 0; i < x.length; i++) {
42505 h = ((h << 5) - h) + x.charCodeAt(i) | 0;
42508 // all Y children of X
42509 function get(x, y) { return x.getElementsByTagName(y); }
42510 function attr(x, y) { return x.getAttribute(y); }
42511 function attrf(x, y) { return parseFloat(attr(x, y)); }
42512 // one Y child of X, if any, otherwise null
42513 function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
42514 // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
42515 function norm(el) { if (el.normalize) { el.normalize(); } return el; }
42516 // cast array x into numbers
42517 function numarray(x) {
42518 for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); }
42521 // get the content of a text node, if any
42522 function nodeVal(x) {
42523 if (x) { norm(x); }
42524 return (x && x.textContent) || '';
42526 // get the contents of multiple text nodes, if present
42527 function getMulti(x, ys) {
42529 for (k = 0; k < ys.length; k++) {
42530 n = get1(x, ys[k]);
42531 if (n) o[ys[k]] = nodeVal(n);
42535 // add properties of Y to X, overwriting if present in both
42536 function extend(x, y) { for (var k in y) x[k] = y[k]; }
42537 // get one coordinate from a coordinate array, if any
42538 function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
42539 // get all coordinates from a coordinate array as [[],[]]
42540 function coord(v) {
42541 var coords = v.replace(trimSpace, '').split(splitSpace),
42543 for (var i = 0; i < coords.length; i++) {
42544 o.push(coord1(coords[i]));
42548 function coordPair(x) {
42549 var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
42550 ele = get1(x, 'ele'),
42551 // handle namespaced attribute in browser
42552 heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'),
42553 time = get1(x, 'time'),
42556 e = parseFloat(nodeVal(ele));
42563 time: time ? nodeVal(time) : null,
42564 heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null
42568 // create a new feature collection parent object
42571 type: 'FeatureCollection',
42577 if (typeof XMLSerializer !== 'undefined') {
42578 /* istanbul ignore next */
42579 serializer = new XMLSerializer();
42580 // only require xmldom in a node environment
42581 } else if ('object' === 'object' && typeof process === 'object' && !process.browser) {
42582 serializer = new (domParser.XMLSerializer)();
42584 function xml2str(str) {
42585 // IE9 will create a new XMLSerializer but it'll crash immediately.
42586 // This line is ignored because we don't run coverage tests in IE9
42587 /* istanbul ignore next */
42588 if (str.xml !== undefined) return str.xml;
42589 return serializer.serializeToString(str);
42593 kml: function(doc) {
42596 // styleindex keeps track of hashed styles in order to match features
42597 styleIndex = {}, styleByHash = {},
42598 // stylemapindex keeps track of style maps to expose in properties
42599 styleMapIndex = {},
42600 // atomic geospatial types supported by KML - MultiGeometry is
42601 // handled separately
42602 geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'],
42603 // all root placemarks in the file
42604 placemarks = get(doc, 'Placemark'),
42605 styles = get(doc, 'Style'),
42606 styleMaps = get(doc, 'StyleMap');
42608 for (var k = 0; k < styles.length; k++) {
42609 var hash = okhash(xml2str(styles[k])).toString(16);
42610 styleIndex['#' + attr(styles[k], 'id')] = hash;
42611 styleByHash[hash] = styles[k];
42613 for (var l = 0; l < styleMaps.length; l++) {
42614 styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16);
42615 var pairs = get(styleMaps[l], 'Pair');
42617 for (var m = 0; m < pairs.length; m++) {
42618 pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl'));
42620 styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap;
42623 for (var j = 0; j < placemarks.length; j++) {
42624 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
42626 function kmlColor(v) {
42627 var color, opacity;
42629 if (v.substr(0, 1) === '#') { v = v.substr(1); }
42630 if (v.length === 6 || v.length === 3) { color = v; }
42631 if (v.length === 8) {
42632 opacity = parseInt(v.substr(0, 2), 16) / 255;
42633 color = '#' + v.substr(6, 2) +
42637 return [color, isNaN(opacity) ? undefined : opacity];
42639 function gxCoord(v) { return numarray(v.split(' ')); }
42640 function gxCoords(root) {
42641 var elems = get(root, 'coord', 'gx'), coords = [], times = [];
42642 if (elems.length === 0) elems = get(root, 'gx:coord');
42643 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
42644 var timeElems = get(root, 'when');
42645 for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j]));
42651 function getGeometry(root) {
42652 var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = [];
42653 if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); }
42654 if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); }
42655 if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); }
42656 for (i = 0; i < geotypes.length; i++) {
42657 geomNodes = get(root, geotypes[i]);
42659 for (j = 0; j < geomNodes.length; j++) {
42660 geomNode = geomNodes[j];
42661 if (geotypes[i] === 'Point') {
42664 coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
42666 } else if (geotypes[i] === 'LineString') {
42668 type: 'LineString',
42669 coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
42671 } else if (geotypes[i] === 'Polygon') {
42672 var rings = get(geomNode, 'LinearRing'),
42674 for (k = 0; k < rings.length; k++) {
42675 coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
42679 coordinates: coords
42681 } else if (geotypes[i] === 'Track' ||
42682 geotypes[i] === 'gx:Track') {
42683 var track = gxCoords(geomNode);
42685 type: 'LineString',
42686 coordinates: track.coords
42688 if (track.times.length) coordTimes.push(track.times);
42695 coordTimes: coordTimes
42698 function getPlacemark(root) {
42699 var geomsAndTimes = getGeometry(root), i, properties = {},
42700 name = nodeVal(get1(root, 'name')),
42701 address = nodeVal(get1(root, 'address')),
42702 styleUrl = nodeVal(get1(root, 'styleUrl')),
42703 description = nodeVal(get1(root, 'description')),
42704 timeSpan = get1(root, 'TimeSpan'),
42705 timeStamp = get1(root, 'TimeStamp'),
42706 extendedData = get1(root, 'ExtendedData'),
42707 lineStyle = get1(root, 'LineStyle'),
42708 polyStyle = get1(root, 'PolyStyle'),
42709 visibility = get1(root, 'visibility');
42711 if (!geomsAndTimes.geoms.length) return [];
42712 if (name) properties.name = name;
42713 if (address) properties.address = address;
42715 if (styleUrl[0] !== '#') {
42716 styleUrl = '#' + styleUrl;
42719 properties.styleUrl = styleUrl;
42720 if (styleIndex[styleUrl]) {
42721 properties.styleHash = styleIndex[styleUrl];
42723 if (styleMapIndex[styleUrl]) {
42724 properties.styleMapHash = styleMapIndex[styleUrl];
42725 properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
42727 // Try to populate the lineStyle or polyStyle since we got the style hash
42728 var style = styleByHash[properties.styleHash];
42730 if (!lineStyle) lineStyle = get1(style, 'LineStyle');
42731 if (!polyStyle) polyStyle = get1(style, 'PolyStyle');
42734 if (description) properties.description = description;
42736 var begin = nodeVal(get1(timeSpan, 'begin'));
42737 var end = nodeVal(get1(timeSpan, 'end'));
42738 properties.timespan = { begin: begin, end: end };
42741 properties.timestamp = nodeVal(get1(timeStamp, 'when'));
42744 var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))),
42745 color = linestyles[0],
42746 opacity = linestyles[1],
42747 width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42748 if (color) properties.stroke = color;
42749 if (!isNaN(opacity)) properties['stroke-opacity'] = opacity;
42750 if (!isNaN(width)) properties['stroke-width'] = width;
42753 var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))),
42754 pcolor = polystyles[0],
42755 popacity = polystyles[1],
42756 fill = nodeVal(get1(polyStyle, 'fill')),
42757 outline = nodeVal(get1(polyStyle, 'outline'));
42758 if (pcolor) properties.fill = pcolor;
42759 if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
42760 if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0;
42761 if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0;
42763 if (extendedData) {
42764 var datas = get(extendedData, 'Data'),
42765 simpleDatas = get(extendedData, 'SimpleData');
42767 for (i = 0; i < datas.length; i++) {
42768 properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
42770 for (i = 0; i < simpleDatas.length; i++) {
42771 properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
42775 properties.visibility = nodeVal(visibility);
42777 if (geomsAndTimes.coordTimes.length) {
42778 properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
42779 geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
42783 geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : {
42784 type: 'GeometryCollection',
42785 geometries: geomsAndTimes.geoms
42787 properties: properties
42789 if (attr(root, 'id')) feature.id = attr(root, 'id');
42794 gpx: function(doc) {
42796 tracks = get(doc, 'trk'),
42797 routes = get(doc, 'rte'),
42798 waypoints = get(doc, 'wpt'),
42799 // a feature collection
42802 for (i = 0; i < tracks.length; i++) {
42803 feature = getTrack(tracks[i]);
42804 if (feature) gj.features.push(feature);
42806 for (i = 0; i < routes.length; i++) {
42807 feature = getRoute(routes[i]);
42808 if (feature) gj.features.push(feature);
42810 for (i = 0; i < waypoints.length; i++) {
42811 gj.features.push(getPoint(waypoints[i]));
42813 function getPoints(node, pointname) {
42814 var pts = get(node, pointname),
42819 if (l < 2) return {}; // Invalid line in GeoJSON
42820 for (var i = 0; i < l; i++) {
42821 var c = coordPair(pts[i]);
42822 line.push(c.coordinates);
42823 if (c.time) times.push(c.time);
42824 if (c.heartRate) heartRates.push(c.heartRate);
42829 heartRates: heartRates
42832 function getTrack(node) {
42833 var segments = get(node, 'trkseg'),
42838 for (var i = 0; i < segments.length; i++) {
42839 line = getPoints(segments[i], 'trkpt');
42841 if (line.line) track.push(line.line);
42842 if (line.times && line.times.length) times.push(line.times);
42843 if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates);
42846 if (track.length === 0) return;
42847 var properties = getProperties(node);
42848 extend(properties, getLineStyle(get1(node, 'extensions')));
42849 if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times;
42850 if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates;
42853 properties: properties,
42855 type: track.length === 1 ? 'LineString' : 'MultiLineString',
42856 coordinates: track.length === 1 ? track[0] : track
42860 function getRoute(node) {
42861 var line = getPoints(node, 'rtept');
42862 if (!line.line) return;
42863 var prop = getProperties(node);
42864 extend(prop, getLineStyle(get1(node, 'extensions')));
42869 type: 'LineString',
42870 coordinates: line.line
42875 function getPoint(node) {
42876 var prop = getProperties(node);
42877 extend(prop, getMulti(node, ['sym']));
42883 coordinates: coordPair(node).coordinates
42887 function getLineStyle(extensions) {
42890 var lineStyle = get1(extensions, 'line');
42892 var color = nodeVal(get1(lineStyle, 'color')),
42893 opacity = parseFloat(nodeVal(get1(lineStyle, 'opacity'))),
42894 width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42895 if (color) style.stroke = color;
42896 if (!isNaN(opacity)) style['stroke-opacity'] = opacity;
42897 // GPX width is in mm, convert to px with 96 px per inch
42898 if (!isNaN(width)) style['stroke-width'] = width * 96 / 25.4;
42903 function getProperties(node) {
42904 var prop = getMulti(node, ['name', 'cmt', 'desc', 'type', 'time', 'keywords']),
42905 links = get(node, 'link');
42906 if (links.length) prop.links = [];
42907 for (var i = 0, link; i < links.length; i++) {
42908 link = { href: attr(links[i], 'href') };
42909 extend(link, getMulti(links[i], ['text', 'type']));
42910 prop.links.push(link);
42920 module.exports = toGeoJSON;
42923 function svgGpx(projection, context, dispatch$$1) {
42924 var showLabels = true,
42925 detected = utilDetect(),
42930 if (svgGpx.initialized) return; // run once
42932 svgGpx.geojson = {};
42933 svgGpx.enabled = true;
42936 event.stopPropagation();
42937 event.preventDefault();
42938 event.dataTransfer.dropEffect = 'copy';
42942 .attr('dropzone', 'copy')
42943 .on('drop.localgpx', function() {
42944 event.stopPropagation();
42945 event.preventDefault();
42946 if (!detected.filedrop) return;
42947 drawGpx.files(event.dataTransfer.files);
42949 .on('dragenter.localgpx', over)
42950 .on('dragexit.localgpx', over)
42951 .on('dragover.localgpx', over);
42953 svgGpx.initialized = true;
42957 function drawGpx(selection$$1) {
42958 var geojson = svgGpx.geojson,
42959 enabled = svgGpx.enabled;
42961 layer = selection$$1.selectAll('.layer-gpx')
42962 .data(enabled ? [0] : []);
42967 layer = layer.enter()
42969 .attr('class', 'layer-gpx')
42980 paths = paths.enter()
42982 .attr('class', 'gpx')
42986 var path$$1 = index$4(projection);
42989 .attr('d', path$$1);
42992 var labels = layer.selectAll('text')
42993 .data(showLabels && geojson.features ? geojson.features : []);
42998 labels = labels.enter()
43000 .attr('class', 'gpx')
43004 .text(function(d) {
43005 return d.properties.desc || d.properties.name;
43007 .attr('x', function(d) {
43008 var centroid = path$$1.centroid(d);
43009 return centroid[0] + 7;
43011 .attr('y', function(d) {
43012 var centroid = path$$1.centroid(d);
43013 return centroid[1];
43019 function toDom(x) {
43020 return (new DOMParser()).parseFromString(x, 'text/xml');
43024 function getExtension(fileName) {
43025 if (lodash.isUndefined(fileName)) {
43029 var lastDotIndex = fileName.lastIndexOf('.');
43030 if (lastDotIndex < 0) {
43034 return fileName.substr(lastDotIndex);
43038 function parseSaveAndZoom(extension, data) {
43039 switch (extension) {
43041 drawGpx.geojson(togeojson.gpx(toDom(data))).fitZoom();
43044 drawGpx.geojson(togeojson.kml(toDom(data))).fitZoom();
43048 drawGpx.geojson(JSON.parse(data)).fitZoom();
43054 drawGpx.showLabels = function(_) {
43055 if (!arguments.length) return showLabels;
43061 drawGpx.enabled = function(_) {
43062 if (!arguments.length) return svgGpx.enabled;
43063 svgGpx.enabled = _;
43064 dispatch$$1.call('change');
43069 drawGpx.hasGpx = function() {
43070 var geojson = svgGpx.geojson;
43071 return (!(lodash.isEmpty(geojson) || lodash.isEmpty(geojson.features)));
43075 drawGpx.geojson = function(gj) {
43076 if (!arguments.length) return svgGpx.geojson;
43077 if (lodash.isEmpty(gj) || lodash.isEmpty(gj.features)) return this;
43078 svgGpx.geojson = gj;
43079 dispatch$$1.call('change');
43084 drawGpx.url = function(url) {
43085 text(url, function(err, data) {
43087 var extension = getExtension(url);
43088 parseSaveAndZoom(extension, data);
43095 drawGpx.files = function(fileList) {
43096 if (!fileList.length) return this;
43097 var f = fileList[0],
43098 reader = new FileReader();
43100 reader.onload = (function(file) {
43101 var extension = getExtension(file.name);
43103 return function (e) {
43104 parseSaveAndZoom(extension, e.target.result);
43108 reader.readAsText(f);
43113 drawGpx.fitZoom = function() {
43114 if (!this.hasGpx()) return this;
43115 var geojson = svgGpx.geojson;
43117 var map$$1 = context.map(),
43118 viewport = map$$1.trimmedExtent().polygon(),
43119 coords = lodash.reduce(geojson.features, function(coords, feature) {
43120 var c = feature.geometry.coordinates;
43122 /* eslint-disable no-fallthrough */
43123 switch (feature.geometry.type) {
43130 case 'MultiPolygon':
43131 c = lodash.flatten(c);
43133 case 'MultiLineString':
43134 c = lodash.flatten(c);
43137 /* eslint-enable no-fallthrough */
43139 return lodash.union(coords, c);
43142 if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
43143 var extent$$1 = geoExtent$$1(bounds({ type: 'LineString', coordinates: coords }));
43144 map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
43155 function svgIcon(name, svgklass, useklass) {
43156 return function drawIcon(selection) {
43157 selection.selectAll('svg')
43161 .attr('class', 'icon ' + (svgklass || ''))
43163 .attr('xlink:href', name)
43164 .attr('class', useklass);
43168 function svgLabels(projection, context) {
43169 var path$$1 = index$4(projection),
43170 detected = utilDetect(),
43171 baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'),
43172 rdrawn = index$9(),
43173 rskipped = index$9(),
43174 textWidthCache = {},
43177 // Listed from highest to lowest priority
43179 ['line', 'aeroway', '*', 12],
43180 ['line', 'highway', 'motorway', 12],
43181 ['line', 'highway', 'trunk', 12],
43182 ['line', 'highway', 'primary', 12],
43183 ['line', 'highway', 'secondary', 12],
43184 ['line', 'highway', 'tertiary', 12],
43185 ['line', 'highway', '*', 12],
43186 ['line', 'railway', '*', 12],
43187 ['line', 'waterway', '*', 12],
43188 ['area', 'aeroway', '*', 12],
43189 ['area', 'amenity', '*', 12],
43190 ['area', 'building', '*', 12],
43191 ['area', 'historic', '*', 12],
43192 ['area', 'leisure', '*', 12],
43193 ['area', 'man_made', '*', 12],
43194 ['area', 'natural', '*', 12],
43195 ['area', 'shop', '*', 12],
43196 ['area', 'tourism', '*', 12],
43197 ['area', 'camp_site', '*', 12],
43198 ['point', 'aeroway', '*', 10],
43199 ['point', 'amenity', '*', 10],
43200 ['point', 'building', '*', 10],
43201 ['point', 'historic', '*', 10],
43202 ['point', 'leisure', '*', 10],
43203 ['point', 'man_made', '*', 10],
43204 ['point', 'natural', '*', 10],
43205 ['point', 'shop', '*', 10],
43206 ['point', 'tourism', '*', 10],
43207 ['point', 'camp_site', '*', 10],
43208 ['line', 'name', '*', 12],
43209 ['area', 'name', '*', 12],
43210 ['point', 'name', '*', 10]
43214 function blacklisted(preset) {
43215 var noIcons = ['building', 'landuse', 'natural'];
43216 return lodash.some(noIcons, function(s) {
43217 return preset.id.indexOf(s) >= 0;
43222 function get(array, prop) {
43223 return function(d, i) { return array[i][prop]; };
43227 function textWidth(text$$1, size, elem) {
43228 var c = textWidthCache[size];
43229 if (!c) c = textWidthCache[size] = {};
43235 c[text$$1] = elem.getComputedTextLength();
43239 var str = encodeURIComponent(text$$1).match(/%[CDEFcdef]/g);
43240 if (str === null) {
43241 return size / 3 * 2 * text$$1.length;
43243 return size / 3 * (2 * text$$1.length + str.length);
43249 function drawLinePaths(selection$$1, entities, filter, classes, labels) {
43250 var paths = selection$$1.selectAll('path')
43252 .data(entities, osmEntity$$1.key);
43259 .style('stroke-width', get(labels, 'font-size'))
43260 .attr('id', function(d) { return 'labelpath-' + d.id; })
43261 .attr('class', classes)
43263 .attr('d', get(labels, 'lineString'));
43267 function drawLineLabels(selection$$1, entities, filter, classes, labels) {
43268 var texts = selection$$1.selectAll('text.' + classes)
43270 .data(entities, osmEntity$$1.key);
43277 .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
43278 .attr('dy', baselineHack ? '0.35em' : null)
43279 .append('textPath')
43280 .attr('class', 'textpath');
43282 texts = selection$$1.selectAll('text.' + classes);
43284 texts.selectAll('.textpath')
43286 .data(entities, osmEntity$$1.key)
43287 .attr('startOffset', '50%')
43288 .attr('xlink:href', function(d) { return '#labelpath-' + d.id; })
43289 .text(utilDisplayNameForPath);
43293 function drawPointLabels(selection$$1, entities, filter, classes, labels) {
43294 var texts = selection$$1.selectAll('text.' + classes)
43296 .data(entities, osmEntity$$1.key);
43301 texts = texts.enter()
43303 .attr('class', function(d, i) {
43304 return classes + ' ' + labels[i].classes + ' ' + d.id;
43309 .attr('x', get(labels, 'x'))
43310 .attr('y', get(labels, 'y'))
43311 .style('text-anchor', get(labels, 'textAnchor'))
43312 .text(utilDisplayName)
43313 .each(function(d, i) {
43314 textWidth(utilDisplayName(d), labels[i].height, this);
43319 function drawAreaLabels(selection$$1, entities, filter, classes, labels) {
43320 entities = entities.filter(hasText);
43321 labels = labels.filter(hasText);
43322 drawPointLabels(selection$$1, entities, filter, classes, labels);
43324 function hasText(d, i) {
43325 return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
43330 function drawAreaIcons(selection$$1, entities, filter, classes, labels) {
43331 var icons = selection$$1.selectAll('use.' + classes)
43333 .data(entities, osmEntity$$1.key);
43338 icons = icons.enter()
43340 .attr('class', 'icon ' + classes)
43341 .attr('width', '17px')
43342 .attr('height', '17px')
43346 .attr('transform', get(labels, 'transform'))
43347 .attr('xlink:href', function(d) {
43348 var preset = context.presets().match(d, context.graph()),
43349 picon = preset && preset.icon;
43354 var isMaki = dataFeatureIcons.indexOf(picon) !== -1;
43355 return '#' + picon + (isMaki ? '-15' : '');
43361 function drawCollisionBoxes(selection$$1, rtree, which) {
43362 var showDebug = context.getDebug('collision'),
43363 classes = 'debug ' + which + ' ' +
43364 (which === 'debug-skipped' ? 'orange' : 'yellow');
43366 var debug = selection$$1.selectAll('.layer-label-debug')
43367 .data(showDebug ? [true] : []);
43372 debug = debug.enter()
43374 .attr('class', 'layer-label-debug')
43378 var gj = rtree.all().map(function(d) {
43379 return { type: 'Polygon', coordinates: [[
43388 var debugboxes = debug.selectAll('.' + which)
43394 debugboxes = debugboxes.enter()
43396 .attr('class', classes)
43397 .merge(debugboxes);
43400 .attr('d', index$4());
43405 function drawLabels(selection$$1, graph, entities, filter, dimensions, fullRedraw) {
43406 var lowZoom = context.surface().classed('low-zoom');
43408 var labelable = [], i, j, k, entity, geometry;
43409 for (i = 0; i < labelStack.length; i++) {
43410 labelable.push([]);
43418 for (i = 0; i < entities.length; i++) {
43419 entity = entities[i];
43421 .concat(entitybboxes[entity.id] || [])
43422 .concat(entitybboxes[entity.id + 'I'] || []);
43424 for (j = 0; j < toRemove.length; j++) {
43425 rdrawn.remove(toRemove[j]);
43426 rskipped.remove(toRemove[j]);
43431 // Split entities into groups specified by labelStack
43432 for (i = 0; i < entities.length; i++) {
43433 entity = entities[i];
43434 geometry = entity.geometry(graph);
43435 if (geometry === 'vertex') { geometry = 'point'; } // treat vertex like point
43437 var preset = geometry === 'area' && context.presets().match(entity, graph),
43438 icon = preset && !blacklisted(preset) && preset.icon;
43440 if (!icon && !utilDisplayName(entity))
43443 for (k = 0; k < labelStack.length; k++) {
43444 var matchGeom = labelStack[k][0],
43445 matchKey = labelStack[k][1],
43446 matchVal = labelStack[k][2],
43447 hasVal = entity.tags[matchKey];
43449 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
43450 labelable[k].push(entity);
43468 // Try and find a valid label for labellable entities
43469 for (k = 0; k < labelable.length; k++) {
43470 var fontSize = labelStack[k][3];
43471 for (i = 0; i < labelable[k].length; i++) {
43472 entity = labelable[k][i];
43473 geometry = entity.geometry(graph);
43475 var getName = (geometry === 'line') ? utilDisplayNameForPath : utilDisplayName,
43476 name = getName(entity),
43477 width = name && textWidth(name, fontSize),
43480 if (geometry === 'point') {
43481 p = getPointLabel(entity, width, fontSize, geometry);
43482 } else if (geometry === 'vertex' && !lowZoom) {
43483 // don't label vertices at low zoom because they don't have icons
43484 p = getPointLabel(entity, width, fontSize, geometry);
43485 } else if (geometry === 'line') {
43486 p = getLineLabel(entity, width, fontSize);
43487 } else if (geometry === 'area') {
43488 p = getAreaLabel(entity, width, fontSize);
43492 if (geometry === 'vertex') { geometry = 'point'; } // treat vertex like point
43493 p.classes = geometry + ' tag-' + labelStack[k][1];
43494 positions[geometry].push(p);
43495 labelled[geometry].push(entity);
43501 function getPointLabel(entity, width, height, geometry) {
43502 var y = (geometry === 'point' ? -12 : 0),
43504 ltr: [15, y, 'start'],
43505 rtl: [-15, y, 'end']
43508 var coord = projection(entity.loc),
43510 offset = pointOffsets[textDirection],
43514 x: coord[0] + offset[0],
43515 y: coord[1] + offset[1],
43516 textAnchor: offset[2]
43520 if (textDirection === 'rtl') {
43522 minX: p.x - width - margin,
43523 minY: p.y - (height / 2) - margin,
43524 maxX: p.x + margin,
43525 maxY: p.y + (height / 2) + margin
43529 minX: p.x - margin,
43530 minY: p.y - (height / 2) - margin,
43531 maxX: p.x + width + margin,
43532 maxY: p.y + (height / 2) + margin
43536 if (tryInsert([bbox], entity.id, true)) {
43542 function getLineLabel(entity, width, height) {
43543 var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
43544 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection),
43545 length = geoPathLength(nodes);
43547 if (length < width + 20) return;
43549 // % along the line to attempt to place the label
43550 var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
43551 25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
43554 for (var i = 0; i < lineOffsets.length; i++) {
43555 var offset = lineOffsets[i],
43556 middle = offset / 100 * length,
43557 start = middle - width / 2;
43559 if (start < 0 || start + width > length) continue;
43561 // generate subpath and ignore paths that are invalid or don't cross viewport.
43562 var sub = subpath(nodes, start, start + width);
43563 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
43567 var isReverse = reverse(sub);
43569 sub = sub.reverse();
43573 boxsize = (height + 2) / 2;
43575 for (var j = 0; j < sub.length - 1; j++) {
43577 var b = sub[j + 1];
43578 var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
43580 for (var box = 0; box < num; box++) {
43581 var p = geoInterp(a, b, box / num);
43582 var x0 = p[0] - boxsize - margin;
43583 var y0 = p[1] - boxsize - margin;
43584 var x1 = p[0] + boxsize + margin;
43585 var y1 = p[1] + boxsize + margin;
43588 minX: Math.min(x0, x1),
43589 minY: Math.min(y0, y1),
43590 maxX: Math.max(x0, x1),
43591 maxY: Math.max(y0, y1)
43596 if (tryInsert(bboxes, entity.id, false)) {
43598 'font-size': height + 2,
43599 lineString: lineString(sub),
43600 startOffset: offset + '%'
43605 function reverse(p) {
43606 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
43607 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
43610 function lineString(nodes) {
43611 return 'M' + nodes.join('L');
43614 function subpath(nodes, from, to) {
43616 start, end, i0, i1;
43618 for (var i = 0; i < nodes.length - 1; i++) {
43621 var current = geoEuclideanDistance(a, b);
43623 if (!start && sofar + current >= from) {
43624 portion = (from - sofar) / current;
43626 a[0] + portion * (b[0] - a[0]),
43627 a[1] + portion * (b[1] - a[1])
43631 if (!end && sofar + current >= to) {
43632 portion = (to - sofar) / current;
43634 a[0] + portion * (b[0] - a[0]),
43635 a[1] + portion * (b[1] - a[1])
43642 var ret = nodes.slice(i0, i1);
43643 ret.unshift(start);
43650 function getAreaLabel(entity, width, height) {
43651 var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
43652 extent$$1 = entity.extent(graph),
43653 entitywidth = projection(extent$$1[1])[0] - projection(extent$$1[0])[0];
43655 if (isNaN(centroid[0]) || entitywidth < 20) return;
43658 iconX = centroid[0] - (iconSize / 2),
43659 iconY = centroid[1] - (iconSize / 2),
43661 textOffset = iconSize + margin,
43662 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
43667 maxX: iconX + iconSize,
43668 maxY: iconY + iconSize
43672 if (tryInsert([bbox], entity.id + 'I', true)) {
43673 if (width && entitywidth >= width + 20) {
43674 var labelX = centroid[0],
43675 labelY = centroid[1] + textOffset;
43678 minX: labelX - (width / 2) - margin,
43679 minY: labelY - (height / 2) - margin,
43680 maxX: labelX + (width / 2) + margin,
43681 maxY: labelY + (height / 2) + margin
43684 // try to add label
43685 if (tryInsert([bbox], entity.id, true)) {
43688 p.textAnchor = 'middle';
43698 function tryInsert(bboxes, id, saveSkipped) {
43699 var skipped = false,
43702 for (var i = 0; i < bboxes.length; i++) {
43706 // Check that label is visible
43707 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
43711 if (rdrawn.collides(bbox)) {
43717 entitybboxes[id] = bboxes;
43721 rskipped.load(bboxes);
43724 rdrawn.load(bboxes);
43731 var label = selection$$1.selectAll('.layer-label'),
43732 halo = selection$$1.selectAll('.layer-halo');
43735 drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
43736 drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
43739 drawLinePaths(halo, labelled.line, filter, '', positions.line);
43740 drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
43741 drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
43744 drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
43745 drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
43746 drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
43747 drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area);
43750 drawCollisionBoxes(label, rskipped, 'debug-skipped');
43751 drawCollisionBoxes(label, rdrawn, 'debug-drawn');
43753 selection$$1.call(filterLabels);
43757 function filterLabels(selection$$1) {
43758 var layers = selection$$1
43759 .selectAll('.layer-label, .layer-halo');
43761 layers.selectAll('.proximate')
43762 .classed('proximate', false);
43764 var mouse$$1 = context.mouse(),
43765 graph = context.graph(),
43766 selectedIDs = context.selectedIDs(),
43770 // hide labels near the mouse
43773 bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad };
43774 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43777 // hide labels along selected ways, or near selected vertices
43778 for (var i = 0; i < selectedIDs.length; i++) {
43779 var entity = graph.hasEntity(selectedIDs[i]);
43780 if (!entity) continue;
43781 var geometry = entity.geometry(graph);
43783 if (geometry === 'line') {
43784 ids.push(selectedIDs[i]);
43785 } else if (geometry === 'vertex') {
43786 var point = context.projection(entity.loc);
43788 bbox = { minX: point[0] - pad, minY: point[1] - pad, maxX: point[0] + pad, maxY: point[1] + pad };
43789 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43793 layers.selectAll(utilEntitySelector(ids))
43794 .classed('proximate', true);
43798 var throttleFilterLabels = lodash.throttle(filterLabels, 100);
43801 drawLabels.observe = function(selection$$1) {
43802 var listener = function() { throttleFilterLabels(selection$$1); };
43803 selection$$1.on('mousemove.hidelabels', listener);
43804 context.on('enter.hidelabels', listener);
43808 drawLabels.off = function(selection$$1) {
43809 throttleFilterLabels.cancel();
43810 selection$$1.on('mousemove.hidelabels', null);
43811 context.on('enter.hidelabels', null);
43818 function refresh(selection, node) {
43819 var cr = node.getBoundingClientRect();
43820 var prop = [cr.width, cr.height];
43821 selection.property('__dimensions__', prop);
43825 function utilGetDimensions(selection, force) {
43826 if (!selection || selection.empty()) {
43829 var node = selection.node(),
43830 cached = selection.property('__dimensions__');
43831 return (!cached || force) ? refresh(selection, node) : cached;
43835 function utilSetDimensions(selection, dimensions) {
43836 if (!selection || selection.empty()) {
43839 var node = selection.node();
43840 if (dimensions === null) {
43841 refresh(selection, node);
43845 .property('__dimensions__', [dimensions[0], dimensions[1]])
43846 .attr('width', dimensions[0])
43847 .attr('height', dimensions[1]);
43850 function svgPointTransform(projection) {
43851 return function(entity) {
43852 // http://jsperf.com/short-array-join
43853 var pt = projection(entity.loc);
43854 return 'translate(' + pt[0] + ',' + pt[1] + ')';
43858 function d3geoTile() {
43859 var size = [960, 500],
43861 scaleExtent = [0, 20],
43862 translate = [size[0] / 2, size[1] / 2],
43865 function bound(_) {
43866 return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
43870 var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
43871 z0 = bound(Math.round(z + zoomDelta)),
43872 k = Math.pow(2, z - z0 + 8),
43873 origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
43875 cols = sequence(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
43876 rows = sequence(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
43878 rows.forEach(function(y) {
43879 cols.forEach(function(x) {
43880 tiles.push([x, y, z0]);
43884 tiles.translate = origin;
43890 tile.scaleExtent = function(_) {
43891 if (!arguments.length) return scaleExtent;
43896 tile.size = function(_) {
43897 if (!arguments.length) return size;
43902 tile.scale = function(_) {
43903 if (!arguments.length) return scale;
43908 tile.translate = function(_) {
43909 if (!arguments.length) return translate;
43914 tile.zoomDelta = function(_) {
43915 if (!arguments.length) return zoomDelta;
43923 /* global Mapillary:false */
43924 var apibase = 'https://a.mapillary.com/v2/';
43925 var viewercss = 'mapillary-js/mapillary.min.css';
43926 var viewerjs = 'mapillary-js/mapillary.min.js';
43927 var trafficocss = 'traffico/stylesheets/traffico.css';
43928 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
43929 var maxResults = 1000;
43931 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
43932 var mapillaryCache;
43933 var mapillaryClicks;
43934 var mapillaryImage;
43935 var mapillarySignDefs;
43936 var mapillaryViewer;
43939 function abortRequest(i) {
43944 function nearNullIsland(x, y, z) {
43946 var center = Math.pow(2, z - 1),
43947 width = Math.pow(2, z - 6),
43948 min$$1 = center - (width / 2),
43949 max$$1 = center + (width / 2) - 1;
43950 return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
43956 function maxPageAtZoom(z) {
43957 if (z < 15) return 2;
43958 if (z === 15) return 5;
43959 if (z === 16) return 10;
43960 if (z === 17) return 20;
43961 if (z === 18) return 40;
43962 if (z > 18) return 80;
43966 function getTiles(projection) {
43967 var s = projection.scale() * 2 * Math.PI,
43968 z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
43969 ts = 256 * Math.pow(2, z - tileZoom),
43971 s / 2 - projection.translate()[0],
43972 s / 2 - projection.translate()[1]];
43975 .scaleExtent([tileZoom, tileZoom])
43977 .size(projection.clipExtent()[1])
43978 .translate(projection.translate())()
43979 .map(function(tile) {
43980 var x = tile[0] * ts - origin[0],
43981 y = tile[1] * ts - origin[1];
43984 id: tile.toString(),
43986 extent: geoExtent$$1(
43987 projection.invert([x, y + ts]),
43988 projection.invert([x + ts, y])
43995 function loadTiles(which, url, projection) {
43996 var s = projection.scale() * 2 * Math.PI,
43997 currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0));
43999 var tiles = getTiles(projection).filter(function(t) {
44000 return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
44003 lodash.filter(which.inflight, function(v, k) {
44004 var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
44005 if (!wanted) delete which.inflight[k];
44007 }).map(abortRequest);
44009 tiles.forEach(function(tile) {
44010 loadNextTilePage(which, currZoom, url, tile);
44015 function loadNextTilePage(which, currZoom, url, tile) {
44016 var cache = mapillaryCache[which],
44017 rect = tile.extent.rectangle(),
44018 maxPages = maxPageAtZoom(currZoom),
44019 nextPage = cache.nextPage[tile.id] || 0;
44021 if (nextPage > maxPages) return;
44023 var id = tile.id + ',' + String(nextPage);
44024 if (cache.loaded[id] || cache.inflight[id]) return;
44026 cache.inflight[id] = json(url +
44031 client_id: clientId,
44036 }), function(err, data) {
44037 cache.loaded[id] = true;
44038 delete cache.inflight[id];
44039 if (err || !data.features || !data.features.length) return;
44044 for (var i = 0; i < data.features.length; i++) {
44045 feature = data.features[i];
44046 loc = feature.geometry.coordinates;
44047 d = { key: feature.properties.key, loc: loc };
44048 if (which === 'images') d.ca = feature.properties.ca;
44049 if (which === 'signs') d.signs = feature.properties.rects;
44051 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
44054 cache.rtree.load(features);
44056 if (which === 'images') dispatch$2.call('loadedImages');
44057 if (which === 'signs') dispatch$2.call('loadedSigns');
44059 if (data.features.length === maxResults) { // more pages to load
44060 cache.nextPage[tile.id] = nextPage + 1;
44061 loadNextTilePage(which, currZoom, url, tile);
44063 cache.nextPage[tile.id] = Infinity; // no more pages to load
44070 // partition viewport into `psize` x `psize` regions
44071 function partitionViewport(psize, projection) {
44072 var dimensions = projection.clipExtent()[1];
44073 psize = psize || 16;
44074 var cols = sequence(0, dimensions[0], psize),
44075 rows = sequence(0, dimensions[1], psize),
44078 rows.forEach(function(y) {
44079 cols.forEach(function(x) {
44080 var min$$1 = [x, y + psize],
44081 max$$1 = [x + psize, y];
44083 geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)));
44091 // no more than `limit` results per partition.
44092 function searchLimited(psize, limit, projection, rtree) {
44093 limit = limit || 3;
44095 var partitions = partitionViewport(psize, projection);
44096 return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
44097 return rtree.search(extent$$1.bbox())
44099 .map(function(d) { return d.data; });
44105 var serviceMapillary = {
44108 if (!mapillaryCache) {
44112 this.event = utilRebind(this, dispatch$2, 'on');
44115 reset: function() {
44116 var cache = mapillaryCache;
44119 if (cache.images && cache.images.inflight) {
44120 lodash.forEach(cache.images.inflight, abortRequest);
44122 if (cache.signs && cache.signs.inflight) {
44123 lodash.forEach(cache.signs.inflight, abortRequest);
44128 images: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() },
44129 signs: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() }
44132 mapillaryImage = null;
44133 mapillaryClicks = [];
44137 images: function(projection) {
44138 var psize = 16, limit = 3;
44139 return searchLimited(psize, limit, projection, mapillaryCache.images.rtree);
44143 signs: function(projection) {
44144 var psize = 32, limit = 3;
44145 return searchLimited(psize, limit, projection, mapillaryCache.signs.rtree);
44149 signsSupported: function() {
44150 var detected = utilDetect();
44151 if (detected.ie) return false;
44152 if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
44157 signHTML: function(d) {
44158 if (!mapillarySignDefs) return;
44160 var detectionPackage = d.signs[0].package,
44161 type = d.signs[0].type,
44162 country = detectionPackage.split('_')[1];
44164 return mapillarySignDefs[country][type];
44168 loadImages: function(projection) {
44169 var url = apibase + 'search/im/geojson?';
44170 loadTiles('images', url, projection);
44174 loadSigns: function(context, projection) {
44175 var url = apibase + 'search/im/geojson/or?';
44176 loadTiles('signs', url, projection);
44178 // load traffico css
44179 select('head').selectAll('#traffico')
44183 .attr('id', 'traffico')
44184 .attr('rel', 'stylesheet')
44185 .attr('href', context.asset(trafficocss));
44187 // load traffico sign defs
44188 if (!mapillarySignDefs) {
44189 mapillarySignDefs = {};
44190 lodash.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
44191 json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
44193 if (region === 'de') region = 'eu';
44194 mapillarySignDefs[region] = data;
44201 loadViewer: function(context) {
44203 var wrap = select('#content').selectAll('.mapillary-wrap')
44206 var enter = wrap.enter()
44208 .attr('class', 'mapillary-wrap')
44209 .classed('al', true) // 'al'=left, 'ar'=right
44210 .classed('hidden', true);
44214 .attr('class', 'thumb-hide')
44215 .on('click', function () { that.hideViewer(); })
44217 .call(svgIcon('#icon-close'));
44222 .attr('class', 'mly-wrapper')
44223 .classed('active', false);
44225 // load mapillary-viewercss
44226 select('head').selectAll('#mapillary-viewercss')
44230 .attr('id', 'mapillary-viewercss')
44231 .attr('rel', 'stylesheet')
44232 .attr('href', context.asset(viewercss));
44234 // load mapillary-viewerjs
44235 select('head').selectAll('#mapillary-viewerjs')
44239 .attr('id', 'mapillary-viewerjs')
44240 .attr('src', context.asset(viewerjs));
44244 showViewer: function() {
44246 .selectAll('.mapillary-wrap')
44247 .classed('hidden', false)
44248 .selectAll('.mly-wrapper')
44249 .classed('active', true);
44255 hideViewer: function() {
44257 .selectAll('.mapillary-wrap')
44258 .classed('hidden', true)
44259 .selectAll('.mly-wrapper')
44260 .classed('active', false);
44262 selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44263 .classed('selected', false);
44265 mapillaryImage = null;
44270 updateViewer: function(imageKey, context) {
44271 if (!imageKey) return;
44273 if (!mapillaryViewer) {
44274 this.initViewer(imageKey, context);
44276 mapillaryViewer.moveToKey(imageKey);
44283 initViewer: function(imageKey, context) {
44285 if (Mapillary && imageKey) {
44287 baseImageSize: 320,
44294 mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
44295 mapillaryViewer.on('nodechanged', nodeChanged);
44298 function nodeChanged(node) {
44299 var clicks = mapillaryClicks;
44300 var index = clicks.indexOf(node.key);
44301 if (index > -1) { // nodechange initiated from clicking on a marker..
44302 clicks.splice(index, 1);
44303 } else { // nodechange initiated from the Mapillary viewer controls..
44304 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
44305 context.map().centerEase(loc);
44306 that.selectedImage(node.key, false);
44312 selectedImage: function(imageKey, fromClick) {
44313 if (!arguments.length) return mapillaryImage;
44315 mapillaryImage = imageKey;
44317 mapillaryClicks.push(imageKey);
44320 selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44321 .classed('selected', function(d) { return d.key === imageKey; });
44327 cache: function(_) {
44328 if (!arguments.length) return mapillaryCache;
44329 mapillaryCache = _;
44334 signDefs: function(_) {
44335 if (!arguments.length) return mapillarySignDefs;
44336 mapillarySignDefs = _;
44342 var apibase$1 = 'https://nominatim.openstreetmap.org/';
44344 var nominatimCache;
44347 var serviceNominatim = {
44351 nominatimCache = index$9();
44354 reset: function() {
44355 lodash.forEach(inflight, function(req) { req.abort(); });
44357 nominatimCache = index$9();
44361 countryCode: function (location, callback) {
44362 var countryCodes = nominatimCache.search(
44363 { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
44366 if (countryCodes.length > 0) {
44367 return callback(null, countryCodes[0].data);
44370 var params = { format: 'json', addressdetails: 1, lat: location[1], lon: location[0] };
44371 var url = apibase$1 + 'reverse?' + utilQsString(params);
44372 if (inflight[url]) return;
44374 inflight[url] = json(url, function(err, result) {
44375 delete inflight[url];
44378 return callback(err);
44379 else if (result && result.error)
44380 return callback(result.error);
44382 var extent$$1 = geoExtent$$1(location).padByMeters(1000);
44383 nominatimCache.insert(lodash.assign(extent$$1.bbox(),
44384 { data: result.address.country_code }
44387 callback(null, result.address.country_code);
44392 search: function (val, callback) {
44393 var searchVal = encodeURIComponent(val);
44394 var url = apibase$1 + 'search/' + searchVal + '?limit=10&format=json';
44395 if (inflight[url]) return;
44397 inflight[url] = json(url, function(err, result) {
44398 delete inflight[url];
44399 callback(err, result);
44405 var hashes = createCommonjsModule(function (module, exports) {
44407 * jshashes - https://github.com/h2non/jshashes
44408 * Released under the "New BSD" license
44410 * Algorithms specification:
44412 * MD5 - http://www.ietf.org/rfc/rfc1321.txt
44413 * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
44414 * SHA1 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44415 * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44416 * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44417 * HMAC - http://www.ietf.org/rfc/rfc2104.txt
44422 function utf8Encode(str) {
44423 var x, y, output = '',
44427 if (str && str.length) {
44429 while ((i += 1) < l) {
44430 /* Decode utf-16 surrogate pairs */
44431 x = str.charCodeAt(i);
44432 y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
44433 if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
44434 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
44437 /* Encode output as utf-8 */
44439 output += String.fromCharCode(x);
44440 } else if (x <= 0x7FF) {
44441 output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
44442 0x80 | (x & 0x3F));
44443 } else if (x <= 0xFFFF) {
44444 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
44445 0x80 | ((x >>> 6) & 0x3F),
44446 0x80 | (x & 0x3F));
44447 } else if (x <= 0x1FFFFF) {
44448 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
44449 0x80 | ((x >>> 12) & 0x3F),
44450 0x80 | ((x >>> 6) & 0x3F),
44451 0x80 | (x & 0x3F));
44458 function utf8Decode(str) {
44459 var i, ac, c1, c2, c3, arr = [],
44461 i = ac = c1 = c2 = c3 = 0;
44463 if (str && str.length) {
44468 c1 = str.charCodeAt(i);
44471 arr[ac] = String.fromCharCode(c1);
44473 } else if (c1 > 191 && c1 < 224) {
44474 c2 = str.charCodeAt(i + 1);
44475 arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
44478 c2 = str.charCodeAt(i + 1);
44479 c3 = str.charCodeAt(i + 2);
44480 arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
44485 return arr.join('');
44489 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
44490 * to work around bugs in some JS interpreters.
44493 function safe_add(x, y) {
44494 var lsw = (x & 0xFFFF) + (y & 0xFFFF),
44495 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
44496 return (msw << 16) | (lsw & 0xFFFF);
44500 * Bitwise rotate a 32-bit number to the left.
44503 function bit_rol(num, cnt) {
44504 return (num << cnt) | (num >>> (32 - cnt));
44508 * Convert a raw string to a hex string
44511 function rstr2hex(input, hexcase) {
44512 var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
44516 for (; i < l; i += 1) {
44517 x = input.charCodeAt(i);
44518 output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
44524 * Encode a string as utf-16
44527 function binb2rstr(input) {
44528 var i, l = input.length * 32,
44530 for (i = 0; i < l; i += 8) {
44531 output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
44537 * Convert an array of little-endian words to a string
44540 function binl2rstr(input) {
44541 var i, l = input.length * 32,
44543 for (i = 0; i < l; i += 8) {
44544 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
44550 * Convert a raw string to an array of little-endian words
44551 * Characters >255 have their high-byte silently ignored.
44554 function rstr2binl(input) {
44555 var i, l = input.length * 8,
44556 output = Array(input.length >> 2),
44557 lo = output.length;
44558 for (i = 0; i < lo; i += 1) {
44561 for (i = 0; i < l; i += 8) {
44562 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
44568 * Convert a raw string to an array of big-endian words
44569 * Characters >255 have their high-byte silently ignored.
44572 function rstr2binb(input) {
44573 var i, l = input.length * 8,
44574 output = Array(input.length >> 2),
44575 lo = output.length;
44576 for (i = 0; i < lo; i += 1) {
44579 for (i = 0; i < l; i += 8) {
44580 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
44586 * Convert a raw string to an arbitrary string encoding
44589 function rstr2any(input, encoding) {
44590 var divisor = encoding.length,
44591 remainders = Array(),
44592 i, q, x, ld, quotient, dividend, output, full_length;
44594 /* Convert to an array of 16-bit big-endian values, forming the dividend */
44595 dividend = Array(Math.ceil(input.length / 2));
44596 ld = dividend.length;
44597 for (i = 0; i < ld; i += 1) {
44598 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
44602 * Repeatedly perform a long division. The binary array forms the dividend,
44603 * the length of the encoding is the divisor. Once computed, the quotient
44604 * forms the dividend for the next step. We stop when the dividend is zerHashes.
44605 * All remainders are stored for later use.
44607 while (dividend.length > 0) {
44608 quotient = Array();
44610 for (i = 0; i < dividend.length; i += 1) {
44611 x = (x << 16) + dividend[i];
44612 q = Math.floor(x / divisor);
44614 if (quotient.length > 0 || q > 0) {
44615 quotient[quotient.length] = q;
44618 remainders[remainders.length] = x;
44619 dividend = quotient;
44622 /* Convert the remainders to the output string */
44624 for (i = remainders.length - 1; i >= 0; i--) {
44625 output += encoding.charAt(remainders[i]);
44628 /* Append leading zero equivalents */
44629 full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
44630 for (i = output.length; i < full_length; i += 1) {
44631 output = encoding[0] + output;
44637 * Convert a raw string to a base-64 string
44640 function rstr2b64(input, b64pad) {
44641 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44643 len = input.length,
44645 b64pad = b64pad || '=';
44646 for (i = 0; i < len; i += 3) {
44647 triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44648 for (j = 0; j < 4; j += 1) {
44649 if (i * 8 + j * 6 > input.length * 8) {
44652 output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44661 * @property {String} version
44670 Base64: function() {
44671 // private properties
44672 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44673 pad = '=', // default pad according with the RFC standard
44674 url = false, // URL encoding support @todo
44675 utf8 = true; // by default enable UTF-8 support encoding
44677 // public method for encoding
44678 this.encode = function(input) {
44681 len = input.length;
44684 input = (utf8) ? utf8Encode(input) : input;
44686 for (i = 0; i < len; i += 3) {
44687 triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44688 for (j = 0; j < 4; j += 1) {
44689 if (i * 8 + j * 6 > len * 8) {
44692 output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44699 // public method for decoding
44700 this.decode = function(input) {
44701 // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
44702 var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
44710 input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
44713 do { // unpack four hexets into three octets using index points in b64
44714 h1 = tab.indexOf(input.charAt(i += 1));
44715 h2 = tab.indexOf(input.charAt(i += 1));
44716 h3 = tab.indexOf(input.charAt(i += 1));
44717 h4 = tab.indexOf(input.charAt(i += 1));
44719 bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
44721 o1 = bits >> 16 & 0xff;
44722 o2 = bits >> 8 & 0xff;
44727 arr[ac] = String.fromCharCode(o1);
44728 } else if (h4 === 64) {
44729 arr[ac] = String.fromCharCode(o1, o2);
44731 arr[ac] = String.fromCharCode(o1, o2, o3);
44733 } while (i < input.length);
44735 dec = arr.join('');
44736 dec = (utf8) ? utf8Decode(dec) : dec;
44741 // set custom pad string
44742 this.setPad = function(str) {
44746 // set custom tab string characters
44747 this.setTab = function(str) {
44751 this.setUTF8 = function(bool) {
44752 if (typeof bool === 'boolean') {
44760 * CRC-32 calculation
44764 * @param {String} str Input String
44767 CRC32: function(str) {
44772 str = utf8Encode(str);
44775 '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
44776 '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
44777 '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
44778 '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
44779 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
44780 '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
44781 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
44782 '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
44783 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
44784 '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
44785 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
44786 '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
44787 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
44788 '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
44789 '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
44790 '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
44791 '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
44792 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
44793 '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
44794 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
44795 '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
44796 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
44797 '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
44798 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
44799 '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
44800 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
44804 for (i = 0, iTop = str.length; i < iTop; i += 1) {
44805 y = (crc ^ str.charCodeAt(i)) & 0xFF;
44806 x = '0x' + table.substr(y * 9, 8);
44807 crc = (crc >>> 8) ^ x;
44809 // always return a positive number (that's what >>> 0 does)
44810 return (crc ^ (-1)) >>> 0;
44816 * @param {Object} [config]
44818 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44819 * Digest Algorithm, as defined in RFC 1321.
44820 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44821 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44822 * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
44824 MD5: function(options) {
44826 * Private config properties. You may need to tweak these to be compatible with
44827 * the server-side, but the defaults work in most cases.
44828 * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44830 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44831 b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44832 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44834 // privileged (public) methods
44835 this.hex = function(s) {
44836 return rstr2hex(rstr(s, utf8), hexcase);
44838 this.b64 = function(s) {
44839 return rstr2b64(rstr(s), b64pad);
44841 this.any = function(s, e) {
44842 return rstr2any(rstr(s, utf8), e);
44844 this.raw = function(s) {
44845 return rstr(s, utf8);
44847 this.hex_hmac = function(k, d) {
44848 return rstr2hex(rstr_hmac(k, d), hexcase);
44850 this.b64_hmac = function(k, d) {
44851 return rstr2b64(rstr_hmac(k, d), b64pad);
44853 this.any_hmac = function(k, d, e) {
44854 return rstr2any(rstr_hmac(k, d), e);
44857 * Perform a simple self-test to see if the VM is working
44858 * @return {String} Hexadecimal hash sample
44860 this.vm_test = function() {
44861 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44864 * Enable/disable uppercase hexadecimal returned string
44866 * @return {Object} this
44868 this.setUpperCase = function(a) {
44869 if (typeof a === 'boolean') {
44875 * Defines a base64 pad string
44876 * @param {String} Pad
44877 * @return {Object} this
44879 this.setPad = function(a) {
44880 b64pad = a || b64pad;
44884 * Defines a base64 pad string
44886 * @return {Object} [this]
44888 this.setUTF8 = function(a) {
44889 if (typeof a === 'boolean') {
44898 * Calculate the MD5 of a raw string
44902 s = (utf8) ? utf8Encode(s) : s;
44903 return binl2rstr(binl(rstr2binl(s), s.length * 8));
44907 * Calculate the HMAC-MD5, of a key and some data (raw strings)
44910 function rstr_hmac(key, data) {
44911 var bkey, ipad, opad, hash, i;
44913 key = (utf8) ? utf8Encode(key) : key;
44914 data = (utf8) ? utf8Encode(data) : data;
44915 bkey = rstr2binl(key);
44916 if (bkey.length > 16) {
44917 bkey = binl(bkey, key.length * 8);
44920 ipad = Array(16), opad = Array(16);
44921 for (i = 0; i < 16; i += 1) {
44922 ipad[i] = bkey[i] ^ 0x36363636;
44923 opad[i] = bkey[i] ^ 0x5C5C5C5C;
44925 hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44926 return binl2rstr(binl(opad.concat(hash), 512 + 128));
44930 * Calculate the MD5 of an array of little-endian words, and a bit length.
44933 function binl(x, len) {
44934 var i, olda, oldb, oldc, oldd,
44940 /* append padding */
44941 x[len >> 5] |= 0x80 << ((len) % 32);
44942 x[(((len + 64) >>> 9) << 4) + 14] = len;
44944 for (i = 0; i < x.length; i += 16) {
44950 a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
44951 d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
44952 c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
44953 b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
44954 a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
44955 d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
44956 c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
44957 b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
44958 a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
44959 d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
44960 c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
44961 b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
44962 a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
44963 d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
44964 c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
44965 b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
44967 a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
44968 d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
44969 c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
44970 b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
44971 a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
44972 d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
44973 c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
44974 b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
44975 a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
44976 d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
44977 c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
44978 b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
44979 a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
44980 d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
44981 c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
44982 b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
44984 a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
44985 d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
44986 c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
44987 b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
44988 a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
44989 d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
44990 c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
44991 b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
44992 a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
44993 d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
44994 c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
44995 b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
44996 a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
44997 d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
44998 c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
44999 b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
45001 a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
45002 d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
45003 c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
45004 b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
45005 a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
45006 d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
45007 c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
45008 b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
45009 a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
45010 d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
45011 c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
45012 b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
45013 a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
45014 d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
45015 c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
45016 b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
45018 a = safe_add(a, olda);
45019 b = safe_add(b, oldb);
45020 c = safe_add(c, oldc);
45021 d = safe_add(d, oldd);
45023 return Array(a, b, c, d);
45027 * These functions implement the four basic operations the algorithm uses.
45030 function md5_cmn(q, a, b, x, s, t) {
45031 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
45034 function md5_ff(a, b, c, d, x, s, t) {
45035 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
45038 function md5_gg(a, b, c, d, x, s, t) {
45039 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
45042 function md5_hh(a, b, c, d, x, s, t) {
45043 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
45046 function md5_ii(a, b, c, d, x, s, t) {
45047 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
45052 * @class Hashes.SHA1
45053 * @param {Object} [config]
45056 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
45057 * Version 2.2 Copyright Paul Johnston 2000 - 2009.
45058 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45059 * See http://pajhome.org.uk/crypt/md5 for details.
45061 SHA1: function(options) {
45063 * Private config properties. You may need to tweak these to be compatible with
45064 * the server-side, but the defaults work in most cases.
45065 * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
45067 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
45068 b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
45069 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
45072 this.hex = function(s) {
45073 return rstr2hex(rstr(s, utf8), hexcase);
45075 this.b64 = function(s) {
45076 return rstr2b64(rstr(s, utf8), b64pad);
45078 this.any = function(s, e) {
45079 return rstr2any(rstr(s, utf8), e);
45081 this.raw = function(s) {
45082 return rstr(s, utf8);
45084 this.hex_hmac = function(k, d) {
45085 return rstr2hex(rstr_hmac(k, d));
45087 this.b64_hmac = function(k, d) {
45088 return rstr2b64(rstr_hmac(k, d), b64pad);
45090 this.any_hmac = function(k, d, e) {
45091 return rstr2any(rstr_hmac(k, d), e);
45094 * Perform a simple self-test to see if the VM is working
45095 * @return {String} Hexadecimal hash sample
45098 this.vm_test = function() {
45099 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45102 * @description Enable/disable uppercase hexadecimal returned string
45104 * @return {Object} this
45107 this.setUpperCase = function(a) {
45108 if (typeof a === 'boolean') {
45114 * @description Defines a base64 pad string
45115 * @param {string} Pad
45116 * @return {Object} this
45119 this.setPad = function(a) {
45120 b64pad = a || b64pad;
45124 * @description Defines a base64 pad string
45126 * @return {Object} this
45129 this.setUTF8 = function(a) {
45130 if (typeof a === 'boolean') {
45139 * Calculate the SHA-512 of a raw string
45143 s = (utf8) ? utf8Encode(s) : s;
45144 return binb2rstr(binb(rstr2binb(s), s.length * 8));
45148 * Calculate the HMAC-SHA1 of a key and some data (raw strings)
45151 function rstr_hmac(key, data) {
45152 var bkey, ipad, opad, i, hash;
45153 key = (utf8) ? utf8Encode(key) : key;
45154 data = (utf8) ? utf8Encode(data) : data;
45155 bkey = rstr2binb(key);
45157 if (bkey.length > 16) {
45158 bkey = binb(bkey, key.length * 8);
45160 ipad = Array(16), opad = Array(16);
45161 for (i = 0; i < 16; i += 1) {
45162 ipad[i] = bkey[i] ^ 0x36363636;
45163 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45165 hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45166 return binb2rstr(binb(opad.concat(hash), 512 + 160));
45170 * Calculate the SHA-1 of an array of big-endian words, and a bit length
45173 function binb(x, len) {
45174 var i, j, t, olda, oldb, oldc, oldd, olde,
45182 /* append padding */
45183 x[len >> 5] |= 0x80 << (24 - len % 32);
45184 x[((len + 64 >> 9) << 4) + 15] = len;
45186 for (i = 0; i < x.length; i += 16) {
45193 for (j = 0; j < 80; j += 1) {
45197 w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
45199 t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
45200 safe_add(safe_add(e, w[j]), sha1_kt(j)));
45203 c = bit_rol(b, 30);
45208 a = safe_add(a, olda);
45209 b = safe_add(b, oldb);
45210 c = safe_add(c, oldc);
45211 d = safe_add(d, oldd);
45212 e = safe_add(e, olde);
45214 return Array(a, b, c, d, e);
45218 * Perform the appropriate triplet combination function for the current
45222 function sha1_ft(t, b, c, d) {
45224 return (b & c) | ((~b) & d);
45230 return (b & c) | (b & d) | (c & d);
45236 * Determine the appropriate additive constant for the current iteration
45239 function sha1_kt(t) {
45240 return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
45241 (t < 60) ? -1894007588 : -899497514;
45245 * @class Hashes.SHA256
45248 * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
45249 * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
45250 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45251 * See http://pajhome.org.uk/crypt/md5 for details.
45252 * Also http://anmar.eu.org/projects/jssha2/
45254 SHA256: function(options) {
45256 * Private properties configuration variables. You may need to tweak these to be compatible with
45257 * the server-side, but the defaults work in most cases.
45258 * @see this.setUpperCase() method
45259 * @see this.setPad() method
45261 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */
45262 b64pad = (options && typeof options.pad === 'string') ? options.pad : '=',
45263 /* base-64 pad character. Default '=' for strict RFC compliance */
45264 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45265 /* enable/disable utf8 encoding */
45268 /* privileged (public) methods */
45269 this.hex = function(s) {
45270 return rstr2hex(rstr(s, utf8));
45272 this.b64 = function(s) {
45273 return rstr2b64(rstr(s, utf8), b64pad);
45275 this.any = function(s, e) {
45276 return rstr2any(rstr(s, utf8), e);
45278 this.raw = function(s) {
45279 return rstr(s, utf8);
45281 this.hex_hmac = function(k, d) {
45282 return rstr2hex(rstr_hmac(k, d));
45284 this.b64_hmac = function(k, d) {
45285 return rstr2b64(rstr_hmac(k, d), b64pad);
45287 this.any_hmac = function(k, d, e) {
45288 return rstr2any(rstr_hmac(k, d), e);
45291 * Perform a simple self-test to see if the VM is working
45292 * @return {String} Hexadecimal hash sample
45295 this.vm_test = function() {
45296 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45299 * Enable/disable uppercase hexadecimal returned string
45301 * @return {Object} this
45304 this.setUpperCase = function(a) {
45305 if (typeof a === 'boolean') {
45311 * @description Defines a base64 pad string
45312 * @param {string} Pad
45313 * @return {Object} this
45316 this.setPad = function(a) {
45317 b64pad = a || b64pad;
45321 * Defines a base64 pad string
45323 * @return {Object} this
45326 this.setUTF8 = function(a) {
45327 if (typeof a === 'boolean') {
45336 * Calculate the SHA-512 of a raw string
45339 function rstr(s, utf8) {
45340 s = (utf8) ? utf8Encode(s) : s;
45341 return binb2rstr(binb(rstr2binb(s), s.length * 8));
45345 * Calculate the HMAC-sha256 of a key and some data (raw strings)
45348 function rstr_hmac(key, data) {
45349 key = (utf8) ? utf8Encode(key) : key;
45350 data = (utf8) ? utf8Encode(data) : data;
45352 bkey = rstr2binb(key),
45356 if (bkey.length > 16) {
45357 bkey = binb(bkey, key.length * 8);
45360 for (; i < 16; i += 1) {
45361 ipad[i] = bkey[i] ^ 0x36363636;
45362 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45365 hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45366 return binb2rstr(binb(opad.concat(hash), 512 + 256));
45370 * Main sha256 function, with its support functions
45373 function sha256_S(X, n) {
45374 return (X >>> n) | (X << (32 - n));
45377 function sha256_R(X, n) {
45381 function sha256_Ch(x, y, z) {
45382 return ((x & y) ^ ((~x) & z));
45385 function sha256_Maj(x, y, z) {
45386 return ((x & y) ^ (x & z) ^ (y & z));
45389 function sha256_Sigma0256(x) {
45390 return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
45393 function sha256_Sigma1256(x) {
45394 return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
45397 function sha256_Gamma0256(x) {
45398 return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
45401 function sha256_Gamma1256(x) {
45402 return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
45406 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
45407 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
45408 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
45409 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
45410 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
45411 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
45412 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
45415 function binb(m, l) {
45416 var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
45417 1359893119, -1694144372, 528734635, 1541459225
45419 var W = new Array(64);
45420 var a, b, c, d, e, f, g, h;
45423 /* append padding */
45424 m[l >> 5] |= 0x80 << (24 - l % 32);
45425 m[((l + 64 >> 9) << 4) + 15] = l;
45427 for (i = 0; i < m.length; i += 16) {
45437 for (j = 0; j < 64; j += 1) {
45441 W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
45442 sha256_Gamma0256(W[j - 15])), W[j - 16]);
45445 T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
45446 sha256_K[j]), W[j]);
45447 T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
45451 e = safe_add(d, T1);
45455 a = safe_add(T1, T2);
45458 HASH[0] = safe_add(a, HASH[0]);
45459 HASH[1] = safe_add(b, HASH[1]);
45460 HASH[2] = safe_add(c, HASH[2]);
45461 HASH[3] = safe_add(d, HASH[3]);
45462 HASH[4] = safe_add(e, HASH[4]);
45463 HASH[5] = safe_add(f, HASH[5]);
45464 HASH[6] = safe_add(g, HASH[6]);
45465 HASH[7] = safe_add(h, HASH[7]);
45473 * @class Hashes.SHA512
45476 * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
45477 * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
45478 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45479 * See http://pajhome.org.uk/crypt/md5 for details.
45481 SHA512: function(options) {
45483 * Private properties configuration variables. You may need to tweak these to be compatible with
45484 * the server-side, but the defaults work in most cases.
45485 * @see this.setUpperCase() method
45486 * @see this.setPad() method
45488 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45489 /* hexadecimal output case format. false - lowercase; true - uppercase */
45490 b64pad = (options && typeof options.pad === 'string') ? options.pad : '=',
45491 /* base-64 pad character. Default '=' for strict RFC compliance */
45492 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45493 /* enable/disable utf8 encoding */
45496 /* privileged (public) methods */
45497 this.hex = function(s) {
45498 return rstr2hex(rstr(s));
45500 this.b64 = function(s) {
45501 return rstr2b64(rstr(s), b64pad);
45503 this.any = function(s, e) {
45504 return rstr2any(rstr(s), e);
45506 this.raw = function(s) {
45507 return rstr(s, utf8);
45509 this.hex_hmac = function(k, d) {
45510 return rstr2hex(rstr_hmac(k, d));
45512 this.b64_hmac = function(k, d) {
45513 return rstr2b64(rstr_hmac(k, d), b64pad);
45515 this.any_hmac = function(k, d, e) {
45516 return rstr2any(rstr_hmac(k, d), e);
45519 * Perform a simple self-test to see if the VM is working
45520 * @return {String} Hexadecimal hash sample
45523 this.vm_test = function() {
45524 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45527 * @description Enable/disable uppercase hexadecimal returned string
45529 * @return {Object} this
45532 this.setUpperCase = function(a) {
45533 if (typeof a === 'boolean') {
45539 * @description Defines a base64 pad string
45540 * @param {string} Pad
45541 * @return {Object} this
45544 this.setPad = function(a) {
45545 b64pad = a || b64pad;
45549 * @description Defines a base64 pad string
45551 * @return {Object} this
45554 this.setUTF8 = function(a) {
45555 if (typeof a === 'boolean') {
45561 /* private methods */
45564 * Calculate the SHA-512 of a raw string
45568 s = (utf8) ? utf8Encode(s) : s;
45569 return binb2rstr(binb(rstr2binb(s), s.length * 8));
45572 * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
45575 function rstr_hmac(key, data) {
45576 key = (utf8) ? utf8Encode(key) : key;
45577 data = (utf8) ? utf8Encode(data) : data;
45580 bkey = rstr2binb(key),
45584 if (bkey.length > 32) {
45585 bkey = binb(bkey, key.length * 8);
45588 for (; i < 32; i += 1) {
45589 ipad[i] = bkey[i] ^ 0x36363636;
45590 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45593 hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
45594 return binb2rstr(binb(opad.concat(hash), 1024 + 512));
45598 * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
45601 function binb(x, len) {
45604 hash = new Array(16),
45605 //Initial hash values
45607 new int64(0x6a09e667, -205731576),
45608 new int64(-1150833019, -2067093701),
45609 new int64(0x3c6ef372, -23791573),
45610 new int64(-1521486534, 0x5f1d36f1),
45611 new int64(0x510e527f, -1377402159),
45612 new int64(-1694144372, 0x2b3e6c1f),
45613 new int64(0x1f83d9ab, -79577749),
45614 new int64(0x5be0cd19, 0x137e2179)
45616 T1 = new int64(0, 0),
45617 T2 = new int64(0, 0),
45618 a = new int64(0, 0),
45619 b = new int64(0, 0),
45620 c = new int64(0, 0),
45621 d = new int64(0, 0),
45622 e = new int64(0, 0),
45623 f = new int64(0, 0),
45624 g = new int64(0, 0),
45625 h = new int64(0, 0),
45626 //Temporary variables not specified by the document
45627 s0 = new int64(0, 0),
45628 s1 = new int64(0, 0),
45629 Ch = new int64(0, 0),
45630 Maj = new int64(0, 0),
45631 r1 = new int64(0, 0),
45632 r2 = new int64(0, 0),
45633 r3 = new int64(0, 0);
45635 if (sha512_k === undefined) {
45638 new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
45639 new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
45640 new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
45641 new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
45642 new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
45643 new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
45644 new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
45645 new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
45646 new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
45647 new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
45648 new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
45649 new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
45650 new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
45651 new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
45652 new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
45653 new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
45654 new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
45655 new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
45656 new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
45657 new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
45658 new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
45659 new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
45660 new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
45661 new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
45662 new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
45663 new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
45664 new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
45665 new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
45666 new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
45667 new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
45668 new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
45669 new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
45670 new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
45671 new int64(-354779690, -840897762), new int64(-176337025, -294727304),
45672 new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
45673 new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
45674 new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
45675 new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
45676 new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
45677 new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
45681 for (i = 0; i < 80; i += 1) {
45682 W[i] = new int64(0, 0);
45685 // append padding to the source string. The format is described in the FIPS.
45686 x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
45687 x[((len + 128 >> 10) << 5) + 31] = len;
45689 for (i = 0; i < l; i += 32) { //32 dwords is the block size
45690 int64copy(a, H[0]);
45691 int64copy(b, H[1]);
45692 int64copy(c, H[2]);
45693 int64copy(d, H[3]);
45694 int64copy(e, H[4]);
45695 int64copy(f, H[5]);
45696 int64copy(g, H[6]);
45697 int64copy(h, H[7]);
45699 for (j = 0; j < 16; j += 1) {
45700 W[j].h = x[i + 2 * j];
45701 W[j].l = x[i + 2 * j + 1];
45704 for (j = 16; j < 80; j += 1) {
45706 int64rrot(r1, W[j - 2], 19);
45707 int64revrrot(r2, W[j - 2], 29);
45708 int64shr(r3, W[j - 2], 6);
45709 s1.l = r1.l ^ r2.l ^ r3.l;
45710 s1.h = r1.h ^ r2.h ^ r3.h;
45712 int64rrot(r1, W[j - 15], 1);
45713 int64rrot(r2, W[j - 15], 8);
45714 int64shr(r3, W[j - 15], 7);
45715 s0.l = r1.l ^ r2.l ^ r3.l;
45716 s0.h = r1.h ^ r2.h ^ r3.h;
45718 int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
45721 for (j = 0; j < 80; j += 1) {
45723 Ch.l = (e.l & f.l) ^ (~e.l & g.l);
45724 Ch.h = (e.h & f.h) ^ (~e.h & g.h);
45727 int64rrot(r1, e, 14);
45728 int64rrot(r2, e, 18);
45729 int64revrrot(r3, e, 9);
45730 s1.l = r1.l ^ r2.l ^ r3.l;
45731 s1.h = r1.h ^ r2.h ^ r3.h;
45734 int64rrot(r1, a, 28);
45735 int64revrrot(r2, a, 2);
45736 int64revrrot(r3, a, 7);
45737 s0.l = r1.l ^ r2.l ^ r3.l;
45738 s0.h = r1.h ^ r2.h ^ r3.h;
45741 Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
45742 Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
45744 int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
45745 int64add(T2, s0, Maj);
45750 int64add(e, d, T1);
45754 int64add(a, T1, T2);
45756 int64add(H[0], H[0], a);
45757 int64add(H[1], H[1], b);
45758 int64add(H[2], H[2], c);
45759 int64add(H[3], H[3], d);
45760 int64add(H[4], H[4], e);
45761 int64add(H[5], H[5], f);
45762 int64add(H[6], H[6], g);
45763 int64add(H[7], H[7], h);
45766 //represent the hash as an array of 32-bit dwords
45767 for (i = 0; i < 8; i += 1) {
45768 hash[2 * i] = H[i].h;
45769 hash[2 * i + 1] = H[i].l;
45774 //A constructor for 64-bit numbers
45776 function int64(h, l) {
45779 //this.toString = int64toString;
45782 //Copies src into dst, assuming both are 64-bit numbers
45784 function int64copy(dst, src) {
45789 //Right-rotates a 64-bit number by shift
45790 //Won't handle cases of shift>=32
45791 //The function revrrot() is for that
45793 function int64rrot(dst, x, shift) {
45794 dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45795 dst.h = (x.h >>> shift) | (x.l << (32 - shift));
45798 //Reverses the dwords of the source and then rotates right by shift.
45799 //This is equivalent to rotation by 32+shift
45801 function int64revrrot(dst, x, shift) {
45802 dst.l = (x.h >>> shift) | (x.l << (32 - shift));
45803 dst.h = (x.l >>> shift) | (x.h << (32 - shift));
45806 //Bitwise-shifts right a 64-bit number by shift
45807 //Won't handle shift>=32, but it's never needed in SHA512
45809 function int64shr(dst, x, shift) {
45810 dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45811 dst.h = (x.h >>> shift);
45814 //Adds two 64-bit numbers
45815 //Like the original implementation, does not rely on 32-bit operations
45817 function int64add(dst, x, y) {
45818 var w0 = (x.l & 0xffff) + (y.l & 0xffff);
45819 var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
45820 var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
45821 var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
45822 dst.l = (w0 & 0xffff) | (w1 << 16);
45823 dst.h = (w2 & 0xffff) | (w3 << 16);
45826 //Same, except with 4 addends. Works faster than adding them one by one.
45828 function int64add4(dst, a, b, c, d) {
45829 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
45830 var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
45831 var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
45832 var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
45833 dst.l = (w0 & 0xffff) | (w1 << 16);
45834 dst.h = (w2 & 0xffff) | (w3 << 16);
45837 //Same, except with 5 addends
45839 function int64add5(dst, a, b, c, d, e) {
45840 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
45841 w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
45842 w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
45843 w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
45844 dst.l = (w0 & 0xffff) | (w1 << 16);
45845 dst.h = (w2 & 0xffff) | (w3 << 16);
45849 * @class Hashes.RMD160
45851 * @param {Object} [config]
45853 * A JavaScript implementation of the RIPEMD-160 Algorithm
45854 * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
45855 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45856 * See http://pajhome.org.uk/crypt/md5 for details.
45857 * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
45859 RMD160: function(options) {
45861 * Private properties configuration variables. You may need to tweak these to be compatible with
45862 * the server-side, but the defaults work in most cases.
45863 * @see this.setUpperCase() method
45864 * @see this.setPad() method
45866 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45867 /* hexadecimal output case format. false - lowercase; true - uppercase */
45868 b64pad = (options && typeof options.pad === 'string') ? options.pa : '=',
45869 /* base-64 pad character. Default '=' for strict RFC compliance */
45870 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45871 /* enable/disable utf8 encoding */
45873 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45874 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
45875 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
45876 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
45877 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
45880 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
45881 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
45882 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
45883 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
45884 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
45887 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
45888 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
45889 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
45890 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
45891 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
45894 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
45895 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
45896 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
45897 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
45898 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
45901 /* privileged (public) methods */
45902 this.hex = function(s) {
45903 return rstr2hex(rstr(s, utf8));
45905 this.b64 = function(s) {
45906 return rstr2b64(rstr(s, utf8), b64pad);
45908 this.any = function(s, e) {
45909 return rstr2any(rstr(s, utf8), e);
45911 this.raw = function(s) {
45912 return rstr(s, utf8);
45914 this.hex_hmac = function(k, d) {
45915 return rstr2hex(rstr_hmac(k, d));
45917 this.b64_hmac = function(k, d) {
45918 return rstr2b64(rstr_hmac(k, d), b64pad);
45920 this.any_hmac = function(k, d, e) {
45921 return rstr2any(rstr_hmac(k, d), e);
45924 * Perform a simple self-test to see if the VM is working
45925 * @return {String} Hexadecimal hash sample
45928 this.vm_test = function() {
45929 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45932 * @description Enable/disable uppercase hexadecimal returned string
45934 * @return {Object} this
45937 this.setUpperCase = function(a) {
45938 if (typeof a === 'boolean') {
45944 * @description Defines a base64 pad string
45945 * @param {string} Pad
45946 * @return {Object} this
45949 this.setPad = function(a) {
45950 if (typeof a !== 'undefined') {
45956 * @description Defines a base64 pad string
45958 * @return {Object} this
45961 this.setUTF8 = function(a) {
45962 if (typeof a === 'boolean') {
45968 /* private methods */
45971 * Calculate the rmd160 of a raw string
45975 s = (utf8) ? utf8Encode(s) : s;
45976 return binl2rstr(binl(rstr2binl(s), s.length * 8));
45980 * Calculate the HMAC-rmd160 of a key and some data (raw strings)
45983 function rstr_hmac(key, data) {
45984 key = (utf8) ? utf8Encode(key) : key;
45985 data = (utf8) ? utf8Encode(data) : data;
45987 bkey = rstr2binl(key),
45991 if (bkey.length > 16) {
45992 bkey = binl(bkey, key.length * 8);
45995 for (i = 0; i < 16; i += 1) {
45996 ipad[i] = bkey[i] ^ 0x36363636;
45997 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45999 hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
46000 return binl2rstr(binl(opad.concat(hash), 512 + 160));
46004 * Convert an array of little-endian words to a string
46007 function binl2rstr(input) {
46008 var i, output = '',
46009 l = input.length * 32;
46010 for (i = 0; i < l; i += 8) {
46011 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
46017 * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
46020 function binl(x, len) {
46027 A1, B1, C1, D1, E1,
46028 A2, B2, C2, D2, E2;
46030 /* append padding */
46031 x[len >> 5] |= 0x80 << (len % 32);
46032 x[(((len + 64) >>> 9) << 4) + 14] = len;
46035 for (i = 0; i < l; i += 16) {
46041 for (j = 0; j <= 79; j += 1) {
46042 T = safe_add(A1, rmd160_f(j, B1, C1, D1));
46043 T = safe_add(T, x[i + rmd160_r1[j]]);
46044 T = safe_add(T, rmd160_K1(j));
46045 T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
46048 D1 = bit_rol(C1, 10);
46051 T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
46052 T = safe_add(T, x[i + rmd160_r2[j]]);
46053 T = safe_add(T, rmd160_K2(j));
46054 T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
46057 D2 = bit_rol(C2, 10);
46062 T = safe_add(h1, safe_add(C1, D2));
46063 h1 = safe_add(h2, safe_add(D1, E2));
46064 h2 = safe_add(h3, safe_add(E1, A2));
46065 h3 = safe_add(h4, safe_add(A1, B2));
46066 h4 = safe_add(h0, safe_add(B1, C2));
46069 return [h0, h1, h2, h3, h4];
46072 // specific algorithm methods
46074 function rmd160_f(j, x, y, z) {
46075 return (0 <= j && j <= 15) ? (x ^ y ^ z) :
46076 (16 <= j && j <= 31) ? (x & y) | (~x & z) :
46077 (32 <= j && j <= 47) ? (x | ~y) ^ z :
46078 (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
46079 (64 <= j && j <= 79) ? x ^ (y | ~z) :
46080 'rmd160_f: j out of range';
46083 function rmd160_K1(j) {
46084 return (0 <= j && j <= 15) ? 0x00000000 :
46085 (16 <= j && j <= 31) ? 0x5a827999 :
46086 (32 <= j && j <= 47) ? 0x6ed9eba1 :
46087 (48 <= j && j <= 63) ? 0x8f1bbcdc :
46088 (64 <= j && j <= 79) ? 0xa953fd4e :
46089 'rmd160_K1: j out of range';
46092 function rmd160_K2(j) {
46093 return (0 <= j && j <= 15) ? 0x50a28be6 :
46094 (16 <= j && j <= 31) ? 0x5c4dd124 :
46095 (32 <= j && j <= 47) ? 0x6d703ef3 :
46096 (48 <= j && j <= 63) ? 0x7a6d76e9 :
46097 (64 <= j && j <= 79) ? 0x00000000 :
46098 'rmd160_K2: j out of range';
46104 (function(window, undefined) {
46105 var freeExports = false;
46107 freeExports = exports;
46108 if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
46109 window = commonjsGlobal;
46113 if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) {
46114 // define as an anonymous module, so, through path mapping, it can be aliased
46115 undefined(function() {
46118 } else if (freeExports) {
46119 // in Node.js or RingoJS v0.8.0+
46120 if ('object' === 'object' && module && module.exports === freeExports) {
46121 module.exports = Hashes;
46123 // in Narwhal or RingoJS v0.7.0-
46125 freeExports.Hashes = Hashes;
46128 // in a browser or Rhino
46129 window.Hashes = Hashes;
46135 var immutable = extend$2;
46137 var hasOwnProperty = Object.prototype.hasOwnProperty;
46139 function extend$2() {
46142 for (var i = 0; i < arguments.length; i++) {
46143 var source = arguments[i];
46145 for (var key in source) {
46146 if (hasOwnProperty.call(source, key)) {
46147 target[key] = source[key];
46155 var sha1 = new hashes.SHA1();
46159 ohauth.qsString = function(obj) {
46160 return Object.keys(obj).sort().map(function(key) {
46161 return ohauth.percentEncode(key) + '=' +
46162 ohauth.percentEncode(obj[key]);
46166 ohauth.stringQs = function(str) {
46167 return str.split('&').filter(function (pair) {
46168 return pair !== '';
46169 }).reduce(function(obj, pair){
46170 var parts = pair.split('=');
46171 obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
46172 '' : decodeURIComponent(parts[1]);
46177 ohauth.rawxhr = function(method, url, data, headers, callback) {
46178 var xhr = new XMLHttpRequest(),
46179 twoHundred = /^20\d$/;
46180 xhr.onreadystatechange = function() {
46181 if (4 === xhr.readyState && 0 !== xhr.status) {
46182 if (twoHundred.test(xhr.status)) callback(null, xhr);
46183 else return callback(xhr, null);
46186 xhr.onerror = function(e) { return callback(e, null); };
46187 xhr.open(method, url, true);
46188 for (var h in headers) xhr.setRequestHeader(h, headers[h]);
46193 ohauth.xhr = function(method, url, auth, data, options, callback) {
46194 var headers = (options && options.header) || {
46195 'Content-Type': 'application/x-www-form-urlencoded'
46197 headers.Authorization = 'OAuth ' + ohauth.authHeader(auth);
46198 return ohauth.rawxhr(method, url, data, headers, callback);
46201 ohauth.nonce = function() {
46202 for (var o = ''; o.length < 6;) {
46203 o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
46208 ohauth.authHeader = function(obj) {
46209 return Object.keys(obj).sort().map(function(key) {
46210 return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
46214 ohauth.timestamp = function() { return ~~((+new Date()) / 1000); };
46216 ohauth.percentEncode = function(s) {
46217 return encodeURIComponent(s)
46218 .replace(/\!/g, '%21').replace(/\'/g, '%27')
46219 .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
46222 ohauth.baseString = function(method, url, params) {
46223 if (params.oauth_signature) delete params.oauth_signature;
46226 ohauth.percentEncode(url),
46227 ohauth.percentEncode(ohauth.qsString(params))].join('&');
46230 ohauth.signature = function(oauth_secret, token_secret, baseString) {
46231 return sha1.b64_hmac(
46232 ohauth.percentEncode(oauth_secret) + '&' +
46233 ohauth.percentEncode(token_secret),
46238 * Takes an options object for configuration (consumer_key,
46239 * consumer_secret, version, signature_method, token, token_secret)
46240 * and returns a function that generates the Authorization header
46243 * The returned function takes these parameters:
46244 * - method: GET/POST/...
46245 * - uri: full URI with protocol, port, path and query string
46246 * - extra_params: any extra parameters (that are passed in the POST data),
46247 * can be an object or a from-urlencoded string.
46249 * Returned function returns full OAuth header with "OAuth" string in it.
46252 ohauth.headerGenerator = function(options) {
46253 options = options || {};
46254 var consumer_key = options.consumer_key || '',
46255 consumer_secret = options.consumer_secret || '',
46256 signature_method = options.signature_method || 'HMAC-SHA1',
46257 version = options.version || '1.0',
46258 token = options.token || '',
46259 token_secret = options.token_secret || '';
46261 return function(method, uri, extra_params) {
46262 method = method.toUpperCase();
46263 if (typeof extra_params === 'string' && extra_params.length > 0) {
46264 extra_params = ohauth.stringQs(extra_params);
46267 var uri_parts = uri.split('?', 2),
46268 base_uri = uri_parts[0];
46270 var query_params = uri_parts.length === 2 ?
46271 ohauth.stringQs(uri_parts[1]) : {};
46273 var oauth_params = {
46274 oauth_consumer_key: consumer_key,
46275 oauth_signature_method: signature_method,
46276 oauth_version: version,
46277 oauth_timestamp: ohauth.timestamp(),
46278 oauth_nonce: ohauth.nonce()
46281 if (token) oauth_params.oauth_token = token;
46283 var all_params = immutable({}, oauth_params, query_params, extra_params),
46284 base_str = ohauth.baseString(method, base_uri, all_params);
46286 oauth_params.oauth_signature = ohauth.signature(consumer_secret, token_secret, base_str);
46288 return 'OAuth ' + ohauth.authHeader(oauth_params);
46292 var index$13 = ohauth;
46294 var store = createCommonjsModule(function (module, exports) {
46296 // Module export pattern from
46297 // https://github.com/umdjs/umd/blob/master/returnExports.js
46298 ;(function (root, factory) {
46299 if (typeof undefined === 'function' && undefined.amd) {
46300 // AMD. Register as an anonymous module.
46301 undefined([], factory);
46303 // Node. Does not work with strict CommonJS, but
46304 // only CommonJS-like environments that support module.exports,
46306 module.exports = factory();
46308 }(commonjsGlobal, function () {
46312 win = (typeof window != 'undefined' ? window : commonjsGlobal),
46313 doc = win.document,
46314 localStorageName = 'localStorage',
46315 scriptTag = 'script',
46318 store.disabled = false;
46319 store.version = '1.3.20';
46320 store.set = function(key, value) {};
46321 store.get = function(key, defaultVal) {};
46322 store.has = function(key) { return store.get(key) !== undefined };
46323 store.remove = function(key) {};
46324 store.clear = function() {};
46325 store.transact = function(key, defaultVal, transactionFn) {
46326 if (transactionFn == null) {
46327 transactionFn = defaultVal;
46330 if (defaultVal == null) {
46333 var val = store.get(key, defaultVal);
46334 transactionFn(val);
46335 store.set(key, val);
46337 store.getAll = function() {};
46338 store.forEach = function() {};
46340 store.serialize = function(value) {
46341 return JSON.stringify(value)
46343 store.deserialize = function(value) {
46344 if (typeof value != 'string') { return undefined }
46345 try { return JSON.parse(value) }
46346 catch(e) { return value || undefined }
46349 // Functions to encapsulate questionable FireFox 3.6.13 behavior
46350 // when about.config::dom.storage.enabled === false
46351 // See https://github.com/marcuswestin/store.js/issues#issue/13
46352 function isLocalStorageNameSupported() {
46353 try { return (localStorageName in win && win[localStorageName]) }
46354 catch(err) { return false }
46357 if (isLocalStorageNameSupported()) {
46358 storage = win[localStorageName];
46359 store.set = function(key, val) {
46360 if (val === undefined) { return store.remove(key) }
46361 storage.setItem(key, store.serialize(val));
46364 store.get = function(key, defaultVal) {
46365 var val = store.deserialize(storage.getItem(key));
46366 return (val === undefined ? defaultVal : val)
46368 store.remove = function(key) { storage.removeItem(key); };
46369 store.clear = function() { storage.clear(); };
46370 store.getAll = function() {
46372 store.forEach(function(key, val) {
46377 store.forEach = function(callback) {
46378 for (var i=0; i<storage.length; i++) {
46379 var key = storage.key(i);
46380 callback(key, store.get(key));
46383 } else if (doc && doc.documentElement.addBehavior) {
46386 // Since #userData storage applies only to specific paths, we need to
46387 // somehow link our data to a specific path. We choose /favicon.ico
46388 // as a pretty safe option, since all browsers already make a request to
46389 // this URL anyway and being a 404 will not hurt us here. We wrap an
46390 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
46391 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
46392 // since the iframe access rules appear to allow direct access and
46393 // manipulation of the document element, even for a 404 page. This
46394 // document can be used instead of the current document (which would
46395 // have been limited to the current path) to perform #userData storage.
46397 storageContainer = new ActiveXObject('htmlfile');
46398 storageContainer.open();
46399 storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
46400 storageContainer.close();
46401 storageOwner = storageContainer.w.frames[0].document;
46402 storage = storageOwner.createElement('div');
46404 // somehow ActiveXObject instantiation failed (perhaps some special
46405 // security settings or otherwse), fall back to per-path storage
46406 storage = doc.createElement('div');
46407 storageOwner = doc.body;
46409 var withIEStorage = function(storeFunction) {
46410 return function() {
46411 var args = Array.prototype.slice.call(arguments, 0);
46412 args.unshift(storage);
46413 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
46414 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
46415 storageOwner.appendChild(storage);
46416 storage.addBehavior('#default#userData');
46417 storage.load(localStorageName);
46418 var result = storeFunction.apply(store, args);
46419 storageOwner.removeChild(storage);
46424 // In IE7, keys cannot start with a digit or contain certain chars.
46425 // See https://github.com/marcuswestin/store.js/issues/40
46426 // See https://github.com/marcuswestin/store.js/issues/83
46427 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
46428 var ieKeyFix = function(key) {
46429 return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
46431 store.set = withIEStorage(function(storage, key, val) {
46432 key = ieKeyFix(key);
46433 if (val === undefined) { return store.remove(key) }
46434 storage.setAttribute(key, store.serialize(val));
46435 storage.save(localStorageName);
46438 store.get = withIEStorage(function(storage, key, defaultVal) {
46439 key = ieKeyFix(key);
46440 var val = store.deserialize(storage.getAttribute(key));
46441 return (val === undefined ? defaultVal : val)
46443 store.remove = withIEStorage(function(storage, key) {
46444 key = ieKeyFix(key);
46445 storage.removeAttribute(key);
46446 storage.save(localStorageName);
46448 store.clear = withIEStorage(function(storage) {
46449 var attributes = storage.XMLDocument.documentElement.attributes;
46450 storage.load(localStorageName);
46451 for (var i=attributes.length-1; i>=0; i--) {
46452 storage.removeAttribute(attributes[i].name);
46454 storage.save(localStorageName);
46456 store.getAll = function(storage) {
46458 store.forEach(function(key, val) {
46463 store.forEach = withIEStorage(function(storage, callback) {
46464 var attributes = storage.XMLDocument.documentElement.attributes;
46465 for (var i=0, attr; attr=attributes[i]; ++i) {
46466 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
46472 var testKey = '__storejs__';
46473 store.set(testKey, testKey);
46474 if (store.get(testKey) != testKey) { store.disabled = true; }
46475 store.remove(testKey);
46477 store.disabled = true;
46479 store.enabled = !store.disabled;
46487 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
46488 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
46489 // does not support custom headers, which this uses everywhere.
46490 var index$12 = function(o) {
46494 // authenticated users will also have a request token secret, but it's
46495 // not used in transactions with the server
46496 oauth.authenticated = function() {
46497 return !!(token('oauth_token') && token('oauth_token_secret'));
46500 oauth.logout = function() {
46501 token('oauth_token', '');
46502 token('oauth_token_secret', '');
46503 token('oauth_request_token_secret', '');
46507 // TODO: detect lack of click event
46508 oauth.authenticate = function(callback) {
46509 if (oauth.authenticated()) return callback();
46513 // ## Getting a request token
46514 var params = timenonce(getAuth(o)),
46515 url = o.url + '/oauth/request_token';
46517 params.oauth_signature = index$13.signature(
46518 o.oauth_secret, '',
46519 index$13.baseString('POST', url, params));
46521 if (!o.singlepage) {
46522 // Create a 600x550 popup window in the center of the screen
46523 var w = 600, h = 550,
46525 ['width', w], ['height', h],
46526 ['left', screen.width / 2 - w / 2],
46527 ['top', screen.height / 2 - h / 2]].map(function(x) {
46528 return x.join('=');
46530 popup = window.open('about:blank', 'oauth_window', settings);
46533 // Request a request token. When this is complete, the popup
46534 // window is redirected to OSM's authorization page.
46535 index$13.xhr('POST', url, params, null, {}, reqTokenDone);
46538 function reqTokenDone(err, xhr) {
46540 if (err) return callback(err);
46541 var resp = index$13.stringQs(xhr.response);
46542 token('oauth_request_token_secret', resp.oauth_token_secret);
46543 var authorize_url = o.url + '/oauth/authorize?' + index$13.qsString({
46544 oauth_token: resp.oauth_token,
46545 oauth_callback: location.href.replace('index.html', '')
46546 .replace(/#.*/, '').replace(location.search, '') + o.landing
46549 if (o.singlepage) {
46550 location.href = authorize_url;
46552 popup.location = authorize_url;
46556 // Called by a function in a landing page, in the popup window. The
46557 // window closes itself.
46558 window.authComplete = function(token) {
46559 var oauth_token = index$13.stringQs(token.split('?')[1]);
46560 get_access_token(oauth_token.oauth_token);
46561 delete window.authComplete;
46564 // ## Getting an request token
46566 // At this point we have an `oauth_token`, brought in from a function
46567 // call on a landing page popup.
46568 function get_access_token(oauth_token) {
46569 var url = o.url + '/oauth/access_token',
46570 params = timenonce(getAuth(o)),
46571 request_token_secret = token('oauth_request_token_secret');
46572 params.oauth_token = oauth_token;
46573 params.oauth_signature = index$13.signature(
46575 request_token_secret,
46576 index$13.baseString('POST', url, params));
46578 // ## Getting an access token
46580 // The final token required for authentication. At this point
46581 // we have a `request token secret`
46582 index$13.xhr('POST', url, params, null, {}, accessTokenDone);
46586 function accessTokenDone(err, xhr) {
46588 if (err) return callback(err);
46589 var access_token = index$13.stringQs(xhr.response);
46590 token('oauth_token', access_token.oauth_token);
46591 token('oauth_token_secret', access_token.oauth_token_secret);
46592 callback(null, oauth);
46596 oauth.bootstrapToken = function(oauth_token, callback) {
46597 // ## Getting an request token
46598 // At this point we have an `oauth_token`, brought in from a function
46599 // call on a landing page popup.
46600 function get_access_token(oauth_token) {
46601 var url = o.url + '/oauth/access_token',
46602 params = timenonce(getAuth(o)),
46603 request_token_secret = token('oauth_request_token_secret');
46604 params.oauth_token = oauth_token;
46605 params.oauth_signature = index$13.signature(
46607 request_token_secret,
46608 index$13.baseString('POST', url, params));
46610 // ## Getting an access token
46611 // The final token required for authentication. At this point
46612 // we have a `request token secret`
46613 index$13.xhr('POST', url, params, null, {}, accessTokenDone);
46617 function accessTokenDone(err, xhr) {
46619 if (err) return callback(err);
46620 var access_token = index$13.stringQs(xhr.response);
46621 token('oauth_token', access_token.oauth_token);
46622 token('oauth_token_secret', access_token.oauth_token_secret);
46623 callback(null, oauth);
46626 get_access_token(oauth_token);
46631 // A single XMLHttpRequest wrapper that does authenticated calls if the
46632 // user has logged in.
46633 oauth.xhr = function(options, callback) {
46634 if (!oauth.authenticated()) {
46636 return oauth.authenticate(run);
46638 callback('not authenticated', null);
46646 var params = timenonce(getAuth(o)),
46647 oauth_token_secret = token('oauth_token_secret'),
46648 url = (options.prefix !== false) ? o.url + options.path : options.path,
46649 url_parts = url.replace(/#.*$/, '').split('?', 2),
46650 base_url = url_parts[0],
46651 query = (url_parts.length === 2) ? url_parts[1] : '';
46653 // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
46654 if ((!options.options || !options.options.header ||
46655 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
46657 params = immutable(params, index$13.stringQs(options.content));
46660 params.oauth_token = token('oauth_token');
46661 params.oauth_signature = index$13.signature(
46663 oauth_token_secret,
46664 index$13.baseString(options.method, base_url, immutable(params, index$13.stringQs(query)))
46667 return index$13.xhr(options.method, url, params, options.content, options.options, done);
46670 function done(err, xhr) {
46671 if (err) return callback(err);
46672 else if (xhr.responseXML) return callback(err, xhr.responseXML);
46673 else return callback(err, xhr.response);
46677 // pre-authorize this object, if we can just get a token and token_secret
46679 oauth.preauth = function(c) {
46681 if (c.oauth_token) token('oauth_token', c.oauth_token);
46682 if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
46686 oauth.options = function(_) {
46687 if (!arguments.length) return o;
46690 o.url = o.url || 'http://www.openstreetmap.org';
46691 o.landing = o.landing || 'land.html';
46692 o.singlepage = o.singlepage || false;
46694 // Optional loading and loading-done functions for nice UI feedback.
46695 // by default, no-ops
46696 o.loading = o.loading || function() {};
46697 o.done = o.done || function() {};
46699 return oauth.preauth(o);
46702 // 'stamp' an authentication object from `getAuth()`
46703 // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
46705 function timenonce(o) {
46706 o.oauth_timestamp = index$13.timestamp();
46707 o.oauth_nonce = index$13.nonce();
46711 // get/set tokens. These are prefixed with the base URL so that `osm-auth`
46712 // can be used with multiple APIs and the keys in `localStorage`
46716 if (store.enabled) {
46717 token = function (x, y) {
46718 if (arguments.length === 1) return store.get(o.url + x);
46719 else if (arguments.length === 2) return store.set(o.url + x, y);
46723 token = function (x, y) {
46724 if (arguments.length === 1) return storage[o.url + x];
46725 else if (arguments.length === 2) return storage[o.url + x] = y;
46729 // Get an authentication object. If you just add and remove properties
46730 // from a single object, you'll need to use `delete` to make sure that
46731 // it doesn't contain undesired properties for authentication
46732 function getAuth(o) {
46734 oauth_consumer_key: o.oauth_consumer_key,
46735 oauth_signature_method: 'HMAC-SHA1'
46739 // potentially pre-authorize
46745 var JXON = new (function () {
46747 sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
46748 aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
46750 function parseText (sValue) {
46751 if (rIsNull.test(sValue)) { return null; }
46752 if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
46753 if (isFinite(sValue)) { return parseFloat(sValue); }
46754 if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
46758 function EmptyTree () { }
46759 EmptyTree.prototype.toString = function () { return 'null'; };
46760 EmptyTree.prototype.valueOf = function () { return null; };
46762 function objectify (vValue) {
46763 return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
46766 function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
46768 nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
46769 bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
46772 sProp, vContent, nLength = 0, sCollectedTxt = '',
46773 vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
46776 for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
46777 oNode = oParentNode.childNodes.item(nItem);
46778 if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
46779 else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
46780 else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
46784 var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
46786 if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
46788 for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
46789 sProp = aCache[nElId].nodeName.toLowerCase();
46790 vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
46791 if (vResult.hasOwnProperty(sProp)) {
46792 if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
46793 vResult[sProp].push(vContent);
46795 vResult[sProp] = vContent;
46802 nAttrLen = oParentNode.attributes.length,
46803 sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
46805 for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
46806 oAttrib = oParentNode.attributes.item(nAttrib);
46807 oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
46811 if (bFreeze) { Object.freeze(oAttrParent); }
46812 vResult[sAttributesProp] = oAttrParent;
46813 nLength -= nAttrLen - 1;
46817 if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
46818 vResult[sValueProp] = vBuiltVal;
46819 } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
46820 vResult = vBuiltVal;
46823 if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
46825 aCache.length = nLevelStart;
46830 function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
46831 var vValue, oChild;
46833 if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
46834 oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
46835 } else if (oParentObj.constructor === Date) {
46836 oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));
46839 for (var sName in oParentObj) {
46840 vValue = oParentObj[sName];
46841 if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
46842 if (sName === sValueProp) {
46843 if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
46844 } else if (sName === sAttributesProp) { /* verbosity level is 3 */
46845 for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
46846 } else if (sName.charAt(0) === sAttrPref) {
46847 oParentEl.setAttribute(sName.slice(1), vValue);
46848 } else if (vValue.constructor === Array) {
46849 for (var nItem = 0; nItem < vValue.length; nItem++) {
46850 oChild = oXMLDoc.createElement(sName);
46851 loadObjTree(oXMLDoc, oChild, vValue[nItem]);
46852 oParentEl.appendChild(oChild);
46855 oChild = oXMLDoc.createElement(sName);
46856 if (vValue instanceof Object) {
46857 loadObjTree(oXMLDoc, oChild, vValue);
46858 } else if (vValue !== null && vValue !== true) {
46859 oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
46861 oParentEl.appendChild(oChild);
46866 this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
46867 var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
46868 return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);
46871 this.unbuild = function (oObjTree) {
46872 var oNewDoc = document.implementation.createDocument('', '', null);
46873 loadObjTree(oNewDoc, oNewDoc, oObjTree);
46877 this.stringify = function (oObjTree) {
46878 return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
46882 // var myObject = JXON.build(doc);
46883 // we got our javascript object! try: alert(JSON.stringify(myObject));
46885 // var newDoc = JXON.unbuild(myObject);
46886 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
46888 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
46889 var urlroot = 'https://www.openstreetmap.org';
46890 var blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'];
46891 var inflight$1 = {};
46892 var loadedTiles = {};
46893 var tileZoom$1 = 16;
46894 var oauth = index$12({
46896 oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
46897 oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
46898 loading: authLoading,
46901 var rateLimitError;
46902 var userChangesets;
46907 function authLoading() {
46908 dispatch$3.call('authLoading');
46912 function authDone() {
46913 dispatch$3.call('authDone');
46917 function abortRequest$1(i) {
46924 function getLoc(attrs) {
46925 var lon = attrs.lon && attrs.lon.value,
46926 lat = attrs.lat && attrs.lat.value;
46927 return [parseFloat(lon), parseFloat(lat)];
46931 function getNodes(obj) {
46932 var elems = obj.getElementsByTagName('nd'),
46933 nodes = new Array(elems.length);
46934 for (var i = 0, l = elems.length; i < l; i++) {
46935 nodes[i] = 'n' + elems[i].attributes.ref.value;
46941 function getTags(obj) {
46942 var elems = obj.getElementsByTagName('tag'),
46944 for (var i = 0, l = elems.length; i < l; i++) {
46945 var attrs = elems[i].attributes;
46946 tags[attrs.k.value] = attrs.v.value;
46953 function getMembers(obj) {
46954 var elems = obj.getElementsByTagName('member'),
46955 members = new Array(elems.length);
46956 for (var i = 0, l = elems.length; i < l; i++) {
46957 var attrs = elems[i].attributes;
46959 id: attrs.type.value[0] + attrs.ref.value,
46960 type: attrs.type.value,
46961 role: attrs.role.value
46968 function getVisible(attrs) {
46969 return (!attrs.visible || attrs.visible.value !== 'false');
46974 node: function nodeData(obj) {
46975 var attrs = obj.attributes;
46976 return new osmNode({
46977 id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
46978 loc: getLoc(attrs),
46979 version: attrs.version.value,
46980 user: attrs.user && attrs.user.value,
46981 tags: getTags(obj),
46982 visible: getVisible(attrs)
46986 way: function wayData(obj) {
46987 var attrs = obj.attributes;
46988 return new osmWay({
46989 id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
46990 version: attrs.version.value,
46991 user: attrs.user && attrs.user.value,
46992 tags: getTags(obj),
46993 nodes: getNodes(obj),
46994 visible: getVisible(attrs)
46998 relation: function relationData(obj) {
46999 var attrs = obj.attributes;
47000 return new osmRelation({
47001 id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
47002 version: attrs.version.value,
47003 user: attrs.user && attrs.user.value,
47004 tags: getTags(obj),
47005 members: getMembers(obj),
47006 visible: getVisible(attrs)
47012 function parse$1(xml$$1) {
47013 if (!xml$$1 || !xml$$1.childNodes) return;
47015 var root = xml$$1.childNodes[0],
47016 children = root.childNodes,
47019 for (var i = 0, l = children.length; i < l; i++) {
47020 var child = children[i],
47021 parser = parsers[child.nodeName];
47023 entities.push(parser(child));
47034 utilRebind(this, dispatch$3, 'on');
47038 reset: function() {
47039 userChangesets = undefined;
47040 userDetails = undefined;
47041 rateLimitError = undefined;
47042 lodash.forEach(inflight$1, abortRequest$1);
47049 changesetURL: function(changesetId) {
47050 return urlroot + '/changeset/' + changesetId;
47054 changesetsURL: function(center, zoom$$1) {
47055 var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
47056 return urlroot + '/history#map=' +
47057 Math.floor(zoom$$1) + '/' +
47058 center[1].toFixed(precision) + '/' +
47059 center[0].toFixed(precision);
47063 entityURL: function(entity) {
47064 return urlroot + '/' + entity.type + '/' + entity.osmId();
47068 userURL: function(username) {
47069 return urlroot + '/user/' + username;
47073 loadFromAPI: function(path$$1, callback) {
47076 function done(err, xml$$1) {
47077 var isAuthenticated = that.authenticated();
47079 // 400 Bad Request, 401 Unauthorized, 403 Forbidden
47080 // Logout and retry the request..
47081 if (isAuthenticated && err &&
47082 (err.status === 400 || err.status === 401 || err.status === 403)) {
47084 that.loadFromAPI(path$$1, callback);
47086 // else, no retry..
47088 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
47089 // Set the rateLimitError flag and trigger a warning..
47090 if (!isAuthenticated && !rateLimitError && err &&
47091 (err.status === 509 || err.status === 429)) {
47092 rateLimitError = err;
47093 dispatch$3.call('change');
47097 callback(err, parse$1(xml$$1));
47102 if (this.authenticated()) {
47103 return oauth.xhr({ method: 'GET', path: path$$1 }, done);
47105 var url = urlroot + path$$1;
47106 return xml(url).get(done);
47111 loadEntity: function(id, callback) {
47112 var type = osmEntity$$1.id.type(id),
47113 osmID = osmEntity$$1.id.toOSM(id);
47116 '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
47117 function(err, entities) {
47118 if (callback) callback(err, { data: entities });
47124 loadEntityVersion: function(id, version$$1, callback) {
47125 var type = osmEntity$$1.id.type(id),
47126 osmID = osmEntity$$1.id.toOSM(id);
47129 '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
47130 function(err, entities) {
47131 if (callback) callback(err, { data: entities });
47137 loadMultiple: function(ids, callback) {
47139 lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
47140 var type = k + 's',
47141 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
47143 lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
47145 '/api/0.6/' + type + '?' + type + '=' + arr.join(),
47146 function(err, entities) {
47147 if (callback) callback(err, { data: entities });
47155 authenticated: function() {
47156 return oauth.authenticated();
47160 putChangeset: function(changeset, changes, callback) {
47162 // Create the changeset..
47165 path: '/api/0.6/changeset/create',
47166 options: { header: { 'Content-Type': 'text/xml' } },
47167 content: JXON.stringify(changeset.asJXON())
47168 }, createdChangeset);
47171 function createdChangeset(err, changeset_id) {
47172 if (err) return callback(err);
47173 changeset = changeset.update({ id: changeset_id });
47175 // Upload the changeset..
47178 path: '/api/0.6/changeset/' + changeset_id + '/upload',
47179 options: { header: { 'Content-Type': 'text/xml' } },
47180 content: JXON.stringify(changeset.osmChangeJXON(changes))
47181 }, uploadedChangeset);
47185 function uploadedChangeset(err) {
47186 if (err) return callback(err);
47188 // Upload was successful, safe to call the callback.
47189 // Add delay to allow for postgres replication #1646 #2678
47190 window.setTimeout(function() {
47191 callback(null, changeset);
47194 // Still attempt to close changeset, but ignore response because #2667
47197 path: '/api/0.6/changeset/' + changeset.id + '/close',
47198 options: { header: { 'Content-Type': 'text/xml' } }
47199 }, function() { return true; });
47204 userDetails: function(callback) {
47206 callback(undefined, userDetails);
47210 function done(err, user_details) {
47211 if (err) return callback(err);
47213 var u = user_details.getElementsByTagName('user')[0],
47214 img = u.getElementsByTagName('img'),
47217 if (img && img[0] && img[0].getAttribute('href')) {
47218 image_url = img[0].getAttribute('href');
47222 display_name: u.attributes.display_name.value,
47223 image_url: image_url,
47224 id: u.attributes.id.value
47227 callback(undefined, userDetails);
47230 oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
47234 userChangesets: function(callback) {
47235 if (userChangesets) {
47236 callback(undefined, userChangesets);
47240 this.userDetails(function(err, user) {
47246 function done(err, changesets) {
47250 userChangesets = Array.prototype.map.call(
47251 changesets.getElementsByTagName('changeset'),
47252 function (changeset) {
47253 return { tags: getTags(changeset) };
47255 ).filter(function (changeset) {
47256 var comment = changeset.tags.comment;
47257 return comment && comment !== '';
47259 callback(undefined, userChangesets);
47263 oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
47268 status: function(callback) {
47269 function done(xml$$1) {
47270 // update blacklists
47271 var elements = xml$$1.getElementsByTagName('blacklist'),
47273 for (var i = 0; i < elements.length; i++) {
47274 var regex = elements[i].getAttribute('regex'); // needs unencode?
47276 regexes.push(regex);
47279 if (regexes.length) {
47280 blacklists = regexes;
47284 if (rateLimitError) {
47285 callback(rateLimitError, 'rateLimited');
47287 var apiStatus = xml$$1.getElementsByTagName('status'),
47288 val = apiStatus[0].getAttribute('api');
47290 callback(undefined, val);
47294 xml(urlroot + '/api/capabilities').get()
47296 .on('error', callback);
47300 imageryBlacklists: function() {
47305 tileZoom: function(_) {
47306 if (!arguments.length) return tileZoom$1;
47312 loadTiles: function(projection, dimensions, callback) {
47316 s = projection.scale() * 2 * Math.PI,
47317 z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
47318 ts = 256 * Math.pow(2, z - tileZoom$1),
47320 s / 2 - projection.translate()[0],
47321 s / 2 - projection.translate()[1]
47324 var tiles = d3geoTile()
47325 .scaleExtent([tileZoom$1, tileZoom$1])
47328 .translate(projection.translate())()
47329 .map(function(tile) {
47330 var x = tile[0] * ts - origin[0],
47331 y = tile[1] * ts - origin[1];
47334 id: tile.toString(),
47335 extent: geoExtent$$1(
47336 projection.invert([x, y + ts]),
47337 projection.invert([x + ts, y]))
47341 lodash.filter(inflight$1, function(v, i) {
47342 var wanted = lodash.find(tiles, function(tile) {
47343 return i === tile.id;
47345 if (!wanted) delete inflight$1[i];
47347 }).map(abortRequest$1);
47349 tiles.forEach(function(tile) {
47352 if (loadedTiles[id] || inflight$1[id]) return;
47354 if (lodash.isEmpty(inflight$1)) {
47355 dispatch$3.call('loading');
47358 inflight$1[id] = that.loadFromAPI(
47359 '/api/0.6/map?bbox=' + tile.extent.toParam(),
47360 function(err, parsed) {
47361 delete inflight$1[id];
47363 loadedTiles[id] = true;
47367 callback(err, lodash.extend({ data: parsed }, tile));
47370 if (lodash.isEmpty(inflight$1)) {
47371 dispatch$3.call('loaded');
47379 switch: function(options) {
47380 urlroot = options.urlroot;
47382 oauth.options(lodash.extend({
47384 loading: authLoading,
47388 dispatch$3.call('change');
47390 this.userChangesets(function() {}); // eagerly load user details/changesets
47395 toggle: function(_) {
47401 loadedTiles: function(_) {
47402 if (!arguments.length) return loadedTiles;
47408 logout: function() {
47409 userChangesets = undefined;
47410 userDetails = undefined;
47412 dispatch$3.call('change');
47417 authenticate: function(callback) {
47419 userChangesets = undefined;
47420 userDetails = undefined;
47422 function done(err, res) {
47423 rateLimitError = undefined;
47424 dispatch$3.call('change');
47425 if (callback) callback(err, res);
47426 that.userChangesets(function() {}); // eagerly load user details/changesets
47429 return oauth.authenticate(done);
47433 var apibase$2 = 'https://taginfo.openstreetmap.org/api/4/';
47434 var inflight$2 = {};
47435 var popularKeys = {};
47436 var taginfoCache = {};
47438 point: 'count_nodes',
47439 vertex: 'count_nodes',
47440 area: 'count_ways',
47443 var tag_sort_members = {
47444 point: 'count_node_members',
47445 vertex: 'count_node_members',
47446 area: 'count_way_members',
47447 line: 'count_way_members',
47448 relation: 'count_relation_members'
47450 var tag_filters = {
47456 var tag_members_fractions = {
47457 point: 'count_node_members_fraction',
47458 vertex: 'count_node_members_fraction',
47459 area: 'count_way_members_fraction',
47460 line: 'count_way_members_fraction',
47461 relation: 'count_relation_members_fraction'
47465 function sets(params, n, o) {
47466 if (params.geometry && o[params.geometry]) {
47467 params[n] = o[params.geometry];
47473 function setFilter(params) {
47474 return sets(params, 'filter', tag_filters);
47478 function setSort(params) {
47479 return sets(params, 'sortname', tag_sorts);
47483 function setSortMembers(params) {
47484 return sets(params, 'sortname', tag_sort_members);
47488 function clean(params) {
47489 return lodash.omit(params, ['geometry', 'debounce']);
47493 function filterKeys(type) {
47494 var count_type = type ? 'count_' + type : 'count_all';
47495 return function(d) {
47496 return parseFloat(d[count_type]) > 2500 || d.in_wiki;
47501 function filterMultikeys(prefix) {
47502 return function(d) {
47503 // d.key begins with prefix, and d.key contains no additional ':'s
47504 var re = new RegExp('^' + prefix + '(.*)$');
47505 var matches = d.key.match(re) || [];
47506 return (matches.length === 2 && matches[1].indexOf(':') === -1);
47511 function filterValues(allowUpperCase) {
47512 return function(d) {
47513 if (d.value.match(/[;,]/) !== null) return false; // exclude some punctuation
47514 if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false; // exclude uppercase letters
47515 return parseFloat(d.fraction) > 0.0 || d.in_wiki;
47520 function filterRoles(geometry) {
47521 return function(d) {
47522 if (d.role === '') return false; // exclude empty role
47523 if (d.role.match(/[A-Z*;,]/) !== null) return false; // exclude uppercase letters and some punctuation
47524 return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
47529 function valKey(d) {
47537 function valKeyDescription(d) {
47540 title: d.description || d.value
47545 function roleKey(d) {
47553 // sort keys with ':' lower than keys without ':'
47554 function sortKeys(a, b) {
47555 return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
47556 : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
47561 var debouncedRequest = lodash.debounce(request$1, 500, { leading: false });
47563 function request$1(url, params, exactMatch, callback, loaded) {
47564 if (inflight$2[url]) return;
47566 if (checkCache(url, params, exactMatch, callback)) return;
47568 inflight$2[url] = json(url, function (err, data) {
47569 delete inflight$2[url];
47575 function checkCache(url, params, exactMatch, callback) {
47576 var rp = params.rp || 25,
47577 testQuery = params.query || '',
47581 var hit = taginfoCache[testUrl];
47583 // exact match, or shorter match yielding fewer than max results (rp)
47584 if (hit && (url === testUrl || hit.length < rp)) {
47585 callback(null, hit);
47589 // don't try to shorten the query
47590 if (exactMatch || !testQuery.length) return false;
47592 // do shorten the query to see if we already have a cached result
47593 // that has returned fewer than max results (rp)
47594 testQuery = testQuery.slice(0, -1);
47595 testUrl = url.replace(/&query=(.*?)&/, '&query=' + testQuery + '&');
47596 } while (testQuery.length >= 0);
47602 var serviceTaginfo = {
47609 // Fetch popular keys. We'll exclude these from `values`
47610 // lookups because they stress taginfo, and they aren't likely
47611 // to yield meaningful autocomplete results.. see #3955
47612 var params = { rp: 100, sortname: 'values_all', sortorder: 'desc', page: 1, debounce: false };
47613 this.keys(params, function(err, data) {
47615 data.forEach(function(d) {
47616 if (d.value === 'opening_hours') return; // exception
47617 popularKeys[d.value] = true;
47623 reset: function() {
47624 lodash.forEach(inflight$2, function(req) { req.abort(); });
47629 keys: function(params, callback) {
47630 var doRequest = params.debounce ? debouncedRequest : request$1;
47631 params = clean(setSort(params));
47632 params = lodash.extend({ rp: 10, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
47634 var url = apibase$2 + 'keys/all?' + utilQsString(params);
47635 doRequest(url, params, false, callback, function(err, d) {
47639 var f = filterKeys(params.filter);
47640 var result = d.data.filter(f).sort(sortKeys).map(valKey);
47641 taginfoCache[url] = result;
47642 callback(null, result);
47648 multikeys: function(params, callback) {
47649 var doRequest = params.debounce ? debouncedRequest : request$1;
47650 params = clean(setSort(params));
47651 params = lodash.extend({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
47652 var prefix = params.query;
47654 var url = apibase$2 + 'keys/all?' + utilQsString(params);
47655 doRequest(url, params, true, callback, function(err, d) {
47659 var f = filterMultikeys(prefix);
47660 var result = d.data.filter(f).map(valKey);
47661 taginfoCache[url] = result;
47662 callback(null, result);
47668 values: function(params, callback) {
47669 // Exclude popular keys from values lookups.. see #3955
47670 var key = params.key;
47671 if (key && popularKeys[key]) {
47672 callback(null, []);
47676 var doRequest = params.debounce ? debouncedRequest : request$1;
47677 params = clean(setSort(setFilter(params)));
47678 params = lodash.extend({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
47680 var url = apibase$2 + 'key/values?' + utilQsString(params);
47681 doRequest(url, params, false, callback, function(err, d) {
47685 // In most cases we prefer taginfo value results with lowercase letters.
47686 // A few OSM keys expect values to contain uppercase values (see #3377).
47687 // This is not an exhaustive list (e.g. `name` also has uppercase values)
47688 // but these are the fields where taginfo value lookup is most useful.
47689 var re = /network|taxon|genus|species|brand|grape_variety|_hours|_times/;
47690 var allowUpperCase = (params.key.match(re) !== null);
47691 var f = filterValues(allowUpperCase);
47693 var result = d.data.filter(f).map(valKeyDescription);
47694 taginfoCache[url] = result;
47695 callback(null, result);
47701 roles: function(params, callback) {
47702 var doRequest = params.debounce ? debouncedRequest : request$1;
47703 var geometry = params.geometry;
47704 params = clean(setSortMembers(params));
47705 params = lodash.extend({ rp: 25, sortname: 'count_all_members', sortorder: 'desc', page: 1 }, params);
47707 var url = apibase$2 + 'relation/roles?' + utilQsString(params);
47708 doRequest(url, params, true, callback, function(err, d) {
47712 var f = filterRoles(geometry);
47713 var result = d.data.filter(f).map(roleKey);
47714 taginfoCache[url] = result;
47715 callback(null, result);
47721 docs: function(params, callback) {
47722 var doRequest = params.debounce ? debouncedRequest : request$1;
47723 params = clean(setSort(params));
47725 var path$$1 = 'key/wiki_pages?';
47726 if (params.value) path$$1 = 'tag/wiki_pages?';
47727 else if (params.rtype) path$$1 = 'relation/wiki_pages?';
47729 var url = apibase$2 + path$$1 + utilQsString(params);
47730 doRequest(url, params, true, callback, function(err, d) {
47734 taginfoCache[url] = d.data;
47735 callback(null, d.data);
47741 apibase: function(_) {
47742 if (!arguments.length) return apibase$2;
47749 var jsonpCache = {};
47750 window.jsonpCache = jsonpCache;
47752 function jsonpRequest(url, callback) {
47754 if (window.JSONP_FIX) {
47755 if (window.JSONP_DELAY === 0) {
47756 callback(window.JSONP_FIX);
47758 setTimeout(function() {
47759 callback(window.JSONP_FIX);
47760 }, window.JSONP_DELAY || 0);
47766 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
47768 while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
47772 function create(url) {
47773 var e = url.match(/callback=(\w+)/),
47774 c = e ? e[1] : rand();
47775 jsonpCache[c] = function(data) {
47777 delete jsonpCache[c];
47780 return 'jsonpCache.' + c;
47783 var cb = create(url),
47784 script = select('head')
47786 .attr('type', 'text/javascript')
47787 .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
47790 var endpoint = 'https://www.wikidata.org/w/api.php?';
47792 var serviceWikidata = {
47794 init: function() {},
47795 reset: function() {},
47798 // Given a Wikipedia language and article title, return an array of
47799 // corresponding Wikidata entities.
47800 itemsByTitle: function(lang, title, callback) {
47806 lang = lang || 'en';
47807 jsonpRequest(endpoint + utilQsString({
47808 action: 'wbgetentities',
47810 sites: lang.replace(/-/g, '_') + 'wiki',
47812 languages: 'en', // shrink response by filtering to one language
47813 callback: '{callback}'
47814 }), function(data) {
47815 if (!data || data.error) {
47818 callback(title, data.entities || {});
47825 var endpoint$1 = 'https://en.wikipedia.org/w/api.php?';
47827 var serviceWikipedia = {
47829 init: function() {},
47830 reset: function() {},
47833 search: function(lang, query, callback) {
47839 lang = lang || 'en';
47840 jsonpRequest(endpoint$1.replace('en', lang) +
47845 srinfo: 'suggestion',
47847 callback: '{callback}',
47849 }), function(data) {
47850 if (!data || !data.query || !data.query.search || data.error) {
47853 var results = data.query.search.map(function(d) { return d.title; });
47854 callback(query, results);
47861 suggestions: function(lang, query, callback) {
47867 lang = lang || 'en';
47868 jsonpRequest(endpoint$1.replace('en', lang) +
47870 action: 'opensearch',
47874 callback: '{callback}',
47876 }), function(data) {
47877 if (!data || data.error) {
47880 callback(data[0], data[1] || []);
47887 translations: function(lang, title, callback) {
47893 jsonpRequest(endpoint$1.replace('en', lang) +
47898 callback: '{callback}',
47901 }), function(data) {
47902 if (!data || !data.query || !data.query.pages || data.error) {
47905 var list = data.query.pages[Object.keys(data.query.pages)[0]],
47907 if (list && list.langlinks) {
47908 list.langlinks.forEach(function(d) {
47909 translations[d.lang] = d['*'];
47912 callback(translations);
47921 mapillary: serviceMapillary,
47922 geocoder: serviceNominatim,
47924 taginfo: serviceTaginfo,
47925 wikidata: serviceWikidata,
47926 wikipedia: serviceWikipedia
47929 function svgMapillaryImages(projection, context, dispatch$$1) {
47930 var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47932 minViewfieldZoom = 17,
47933 layer = select(null),
47938 if (svgMapillaryImages.initialized) return; // run once
47939 svgMapillaryImages.enabled = false;
47940 svgMapillaryImages.initialized = true;
47944 function getMapillary() {
47945 if (services.mapillary && !_mapillary) {
47946 _mapillary = services.mapillary;
47947 _mapillary.event.on('loadedImages', throttledRedraw);
47948 } else if (!services.mapillary && _mapillary) {
47956 function showLayer() {
47957 var mapillary = getMapillary();
47958 if (!mapillary) return;
47960 mapillary.loadViewer(context);
47964 .style('opacity', 0)
47967 .style('opacity', 1)
47968 .on('end', function () { dispatch$$1.call('change'); });
47972 function hideLayer() {
47973 var mapillary = getMapillary();
47975 mapillary.hideViewer();
47978 throttledRedraw.cancel();
47983 .style('opacity', 0)
47984 .on('end', editOff);
47988 function editOn() {
47989 layer.style('display', 'block');
47993 function editOff() {
47994 layer.selectAll('.viewfield-group').remove();
47995 layer.style('display', 'none');
47999 function click(d) {
48000 var mapillary = getMapillary();
48001 if (!mapillary) return;
48003 context.map().centerEase(d.loc);
48006 .selectedImage(d.key, true)
48007 .updateViewer(d.key, context)
48012 function transform(d) {
48013 var t = svgPointTransform(projection)(d);
48014 if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
48019 function update() {
48020 var mapillary = getMapillary(),
48021 data = (mapillary ? mapillary.images(projection) : []),
48022 imageKey = mapillary ? mapillary.selectedImage() : null;
48024 var markers = layer.selectAll('.viewfield-group')
48025 .data(data, function(d) { return d.key; });
48030 var enter = markers.enter()
48032 .attr('class', 'viewfield-group')
48033 .classed('selected', function(d) { return d.key === imageKey; })
48034 .on('click', click);
48038 .attr('transform', transform);
48041 var viewfields = markers.selectAll('.viewfield')
48042 .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
48049 .attr('class', 'viewfield')
48050 .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
48051 .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');
48053 markers.selectAll('circle')
48063 function drawImages(selection$$1) {
48064 var enabled = svgMapillaryImages.enabled,
48065 mapillary = getMapillary();
48067 layer = selection$$1.selectAll('.layer-mapillary-images')
48068 .data(mapillary ? [0] : []);
48073 layer = layer.enter()
48075 .attr('class', 'layer-mapillary-images')
48076 .style('display', enabled ? 'block' : 'none')
48080 if (mapillary && ~~context.map().zoom() >= minZoom) {
48083 mapillary.loadImages(projection);
48091 drawImages.enabled = function(_) {
48092 if (!arguments.length) return svgMapillaryImages.enabled;
48093 svgMapillaryImages.enabled = _;
48094 if (svgMapillaryImages.enabled) {
48099 dispatch$$1.call('change');
48104 drawImages.supported = function() {
48105 return !!getMapillary();
48113 function svgMapillarySigns(projection, context, dispatch$$1) {
48114 var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
48116 layer = select(null),
48121 if (svgMapillarySigns.initialized) return; // run once
48122 svgMapillarySigns.enabled = false;
48123 svgMapillarySigns.initialized = true;
48127 function getMapillary() {
48128 if (services.mapillary && !_mapillary) {
48129 _mapillary = services.mapillary;
48130 _mapillary.event.on('loadedSigns', throttledRedraw);
48131 } else if (!services.mapillary && _mapillary) {
48138 function showLayer() {
48143 function hideLayer() {
48144 throttledRedraw.cancel();
48149 function editOn() {
48150 layer.style('display', 'block');
48154 function editOff() {
48155 layer.selectAll('.icon-sign').remove();
48156 layer.style('display', 'none');
48160 function click(d) {
48161 var mapillary = getMapillary();
48162 if (!mapillary) return;
48164 context.map().centerEase(d.loc);
48167 .selectedImage(d.key, true)
48168 .updateViewer(d.key, context)
48173 function update() {
48174 var mapillary = getMapillary(),
48175 data = (mapillary ? mapillary.signs(projection) : []),
48176 imageKey = mapillary ? mapillary.selectedImage() : null;
48178 var signs = layer.selectAll('.icon-sign')
48179 .data(data, function(d) { return d.key; });
48184 var enter = signs.enter()
48185 .append('foreignObject')
48186 .attr('class', 'icon-sign')
48187 .attr('width', '32px') // for Firefox
48188 .attr('height', '32px') // for Firefox
48189 .classed('selected', function(d) { return d.key === imageKey; })
48190 .on('click', click);
48193 .append('xhtml:body')
48194 .attr('class', 'icon-sign-body')
48195 .html(mapillary.signHTML);
48199 .attr('x', function(d) { return projection(d.loc)[0] - 16; }) // offset by -16px to
48200 .attr('y', function(d) { return projection(d.loc)[1] - 16; }); // center signs on loc
48204 function drawSigns(selection$$1) {
48205 var enabled = svgMapillarySigns.enabled,
48206 mapillary = getMapillary();
48208 layer = selection$$1.selectAll('.layer-mapillary-signs')
48209 .data(mapillary ? [0] : []);
48214 layer = layer.enter()
48216 .attr('class', 'layer-mapillary-signs')
48217 .style('display', enabled ? 'block' : 'none')
48221 if (mapillary && ~~context.map().zoom() >= minZoom) {
48224 mapillary.loadSigns(context, projection);
48232 drawSigns.enabled = function(_) {
48233 if (!arguments.length) return svgMapillarySigns.enabled;
48234 svgMapillarySigns.enabled = _;
48235 if (svgMapillarySigns.enabled) {
48240 dispatch$$1.call('change');
48245 drawSigns.supported = function() {
48246 var mapillary = getMapillary();
48247 return (mapillary && mapillary.signsSupported());
48255 function svgOsm() {
48256 return function drawOsm(selection) {
48257 var layers = selection.selectAll('.layer-osm')
48258 .data(['areas', 'lines', 'hit', 'halo', 'label']);
48262 .attr('class', function(d) { return 'layer-osm layer-' + d; });
48266 function svgLayers(projection, context) {
48267 var dispatch$$1 = dispatch('change'),
48268 svg = select(null),
48270 { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) },
48271 { id: 'gpx', layer: svgGpx(projection, context, dispatch$$1) },
48272 { id: 'mapillary-images', layer: svgMapillaryImages(projection, context, dispatch$$1) },
48273 { id: 'mapillary-signs', layer: svgMapillarySigns(projection, context, dispatch$$1) },
48274 { id: 'debug', layer: svgDebug(projection, context, dispatch$$1) }
48278 function drawLayers(selection$$1) {
48279 svg = selection$$1.selectAll('.surface')
48284 .attr('class', 'surface')
48287 var defs = svg.selectAll('.surface-defs')
48292 .attr('class', 'surface-defs');
48294 var groups = svg.selectAll('.data-layer')
48302 .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
48304 .each(function(d) { select(this).call(d.layer); });
48308 drawLayers.all = function() {
48313 drawLayers.layer = function(id) {
48314 var obj = lodash.find(layers, function(o) {return o.id === id;});
48315 return obj && obj.layer;
48319 drawLayers.only = function(what) {
48320 var arr = [].concat(what);
48321 drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
48326 drawLayers.remove = function(what) {
48327 var arr = [].concat(what);
48328 arr.forEach(function(id) {
48329 layers = lodash.reject(layers, function(o) {return o.id === id;});
48331 dispatch$$1.call('change');
48336 drawLayers.add = function(what) {
48337 var arr = [].concat(what);
48338 arr.forEach(function(obj) {
48339 if ('id' in obj && 'layer' in obj) {
48343 dispatch$$1.call('change');
48348 drawLayers.dimensions = function(_) {
48349 if (!arguments.length) return utilGetDimensions(svg);
48350 utilSetDimensions(svg, _);
48355 return utilRebind(drawLayers, dispatch$$1, 'on');
48358 function svgLines$$1(projection, context) {
48359 var detected = utilDetect();
48361 var highway_stack = {
48377 function drawLines(selection$$1, graph, entities, filter) {
48380 function waystack(a, b) {
48381 var selected = context.selectedIDs(),
48382 scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0,
48383 scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0;
48385 if (a.tags.highway) { scoreA -= highway_stack[a.tags.highway]; }
48386 if (b.tags.highway) { scoreB -= highway_stack[b.tags.highway]; }
48387 return scoreA - scoreB;
48391 function drawLineGroup(selection$$1, klass, isSelected) {
48392 var lines = selection$$1
48395 .data(getPathData(isSelected), osmEntity$$1.key);
48400 // Optimization: call simple TagClasses only on enter selection. This
48401 // works because osmEntity.key is defined to include the entity v attribute.
48404 .attr('class', function(d) {
48405 return 'way line ' + klass + ' ' + d.id + (isSelected ? ' selected' : '') +
48406 (oldMultiPolygonOuters[d.id] ? ' old-multipolygon' : '');
48408 .call(svgTagClasses())
48411 .attr('d', getPath)
48412 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
48414 return selection$$1;
48418 function getPathData(isSelected) {
48419 return function() {
48420 var layer = this.parentNode.__data__;
48421 var data = pathdata[layer] || [];
48422 return data.filter(function(d) {
48424 return context.selectedIDs().indexOf(d.id) !== -1;
48426 return context.selectedIDs().indexOf(d.id) === -1;
48432 var getPath = svgPath(projection, graph),
48436 oldMultiPolygonOuters = {};
48438 for (var i = 0; i < entities.length; i++) {
48439 var entity = entities[i],
48440 outer = osmSimpleMultipolygonOuterMember(entity, graph);
48442 ways.push(entity.mergeTags(outer.tags));
48443 oldMultiPolygonOuters[outer.id] = true;
48444 } else if (entity.geometry(graph) === 'line') {
48449 ways = ways.filter(getPath);
48450 pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
48452 lodash.forOwn(pathdata, function(v, k) {
48453 onewaydata[k] = lodash(v)
48454 .filter(function(d) { return d.isOneWay(); })
48455 .map(svgOneWaySegments(projection, graph, 35))
48461 var layer = selection$$1.selectAll('.layer-lines');
48463 var layergroup = layer
48464 .selectAll('g.layergroup')
48465 .data(sequence(-10, 11));
48467 layergroup = layergroup.enter()
48469 .attr('class', function(d) { return 'layergroup layer' + String(d); })
48470 .merge(layergroup);
48473 .selectAll('g.linegroup')
48474 .data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted'])
48477 .attr('class', function(d) { return 'linegroup line-' + d; });
48480 layergroup.selectAll('g.line-shadow')
48481 .call(drawLineGroup, 'shadow', false);
48482 layergroup.selectAll('g.line-casing')
48483 .call(drawLineGroup, 'casing', false);
48484 layergroup.selectAll('g.line-stroke')
48485 .call(drawLineGroup, 'stroke', false);
48487 layergroup.selectAll('g.line-shadow-highlighted')
48488 .call(drawLineGroup, 'shadow', true);
48489 layergroup.selectAll('g.line-casing-highlighted')
48490 .call(drawLineGroup, 'casing', true);
48491 layergroup.selectAll('g.line-stroke-highlighted')
48492 .call(drawLineGroup, 'stroke', true);
48495 var onewaygroup = layergroup
48496 .selectAll('g.onewaygroup')
48499 onewaygroup = onewaygroup.enter()
48501 .attr('class', 'onewaygroup')
48502 .merge(onewaygroup);
48504 var oneways = onewaygroup
48508 function() { return onewaydata[this.parentNode.__data__] || []; },
48509 function(d) { return [d.id, d.index]; }
48515 oneways = oneways.enter()
48517 .attr('class', 'oneway')
48518 .attr('marker-mid', 'url(#oneway-marker)')
48520 .attr('d', function(d) { return d.d; });
48523 oneways.each(function() { this.parentNode.insertBefore(this, this); });
48531 function svgMidpoints$$1(projection, context) {
48533 return function drawMidpoints(selection, graph, entities, filter, extent) {
48534 var layer = selection.selectAll('.layer-hit');
48536 var mode = context.mode();
48537 if (mode && mode.id !== 'select') {
48538 layer.selectAll('g.midpoint').remove();
48542 var poly = extent.polygon(),
48545 for (var i = 0; i < entities.length; i++) {
48546 var entity = entities[i];
48548 if (entity.type !== 'way')
48550 if (!filter(entity))
48552 if (context.selectedIDs().indexOf(entity.id) < 0)
48555 var nodes = graph.childNodes(entity);
48556 for (var j = 0; j < nodes.length - 1; j++) {
48560 id = [a.id, b.id].sort().join('-');
48562 if (midpoints[id]) {
48563 midpoints[id].parents.push(entity);
48565 if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
48566 var point = geoInterp(a.loc, b.loc, 0.5),
48569 if (extent.intersects(point)) {
48572 for (var k = 0; k < 4; k++) {
48573 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
48575 geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
48576 geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
48589 edge: [a.id, b.id],
48599 function midpointFilter(d) {
48600 if (midpoints[d.id])
48603 for (var i = 0; i < d.parents.length; i++) {
48604 if (filter(d.parents[i])) {
48614 .selectAll('g.midpoint')
48615 .filter(midpointFilter)
48616 .data(lodash.values(midpoints), function(d) { return d.id; });
48621 var enter = groups.enter()
48622 .insert('g', ':first-child')
48623 .attr('class', 'midpoint');
48625 enter.append('polygon')
48626 .attr('points', '-6,8 10,0 -6,-8')
48627 .attr('class', 'shadow');
48629 enter.append('polygon')
48630 .attr('points', '-3,4 5,0 -3,-4')
48631 .attr('class', 'fill');
48635 .attr('transform', function(d) {
48636 var translate = svgPointTransform(projection),
48637 a = graph.entity(d.edge[0]),
48638 b = graph.entity(d.edge[1]),
48639 angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
48640 return translate(d) + ' rotate(' + angleVal + ')';
48642 .call(svgTagClasses().tags(
48643 function(d) { return d.parents[0].tags; }
48646 // Propagate data bindings.
48647 groups.select('polygon.shadow');
48648 groups.select('polygon.fill');
48653 function svgOneWaySegments(projection, graph, dt) {
48654 return function(entity) {
48660 clip = identity$5().clipExtent(projection.clipExtent()).stream,
48661 coordinates = graph.childNodes(entity).map(function(n) {
48665 if (entity.tags.oneway === '-1') coordinates.reverse();
48668 type: 'LineString',
48669 coordinates: coordinates
48670 }, projection.stream(clip({
48671 lineStart: function() {},
48672 lineEnd: function() {
48675 point: function(x, y) {
48679 var span = geoEuclideanDistance(a, b) - offset;
48682 var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
48683 dx = dt * Math.cos(angle),
48684 dy = dt * Math.sin(angle),
48685 p = [a[0] + offset * Math.cos(angle),
48686 a[1] + offset * Math.sin(angle)];
48688 var segment = 'M' + a[0] + ',' + a[1] +
48689 'L' + p[0] + ',' + p[1];
48691 for (span -= dt; span >= 0; span -= dt) {
48694 segment += 'L' + p[0] + ',' + p[1];
48697 segment += 'L' + b[0] + ',' + b[1];
48698 segments.push({id: entity.id, index: i, d: segment});
48713 function svgPath(projection, graph, isArea) {
48715 // Explanation of magic numbers:
48716 // "padding" here allows space for strokes to extend beyond the viewport,
48717 // so that the stroke isn't drawn along the edge of the viewport when
48718 // the shape is clipped.
48720 // When drawing lines, pad viewport by 5px.
48721 // When drawing areas, pad viewport by 65px in each direction to allow
48722 // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
48725 padding = isArea ? 65 : 5,
48726 viewport = projection.clipExtent(),
48728 [viewport[0][0] - padding, viewport[0][1] - padding],
48729 [viewport[1][0] + padding, viewport[1][1] + padding]
48731 clip = identity$5().clipExtent(paddedExtent).stream,
48732 project = projection.stream,
48733 path$$1 = index$4()
48734 .projection({stream: function(output) { return project(clip(output)); }});
48736 return function(entity) {
48737 if (entity.id in cache) {
48738 return cache[entity.id];
48740 return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
48745 function svgPoints$$1(projection, context) {
48747 function markerPath(selection, klass) {
48749 .attr('class', klass)
48750 .attr('transform', 'translate(-8, -23)')
48751 .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');
48754 function sortY(a, b) {
48755 return b.loc[1] - a.loc[1];
48759 return function drawPoints(selection, graph, entities, filter) {
48760 var wireframe = context.surface().classed('fill-wireframe'),
48761 points = wireframe ? [] : lodash.filter(entities, function(e) {
48762 return e.geometry(graph) === 'point';
48765 points.sort(sortY);
48767 var layer = selection.selectAll('.layer-hit');
48769 var groups = layer.selectAll('g.point')
48771 .data(points, osmEntity$$1.key);
48776 var enter = groups.enter()
48778 .attr('class', function(d) { return 'node point ' + d.id; })
48781 enter.append('path')
48782 .call(markerPath, 'shadow');
48784 enter.append('ellipse')
48789 .attr('class', 'stroke');
48791 enter.append('path')
48792 .call(markerPath, 'stroke');
48794 enter.append('use')
48795 .attr('transform', 'translate(-5, -19)')
48796 .attr('class', 'icon')
48797 .attr('width', '11px')
48798 .attr('height', '11px');
48802 .attr('transform', svgPointTransform(projection))
48803 .call(svgTagClasses());
48805 // Selecting the following implicitly
48806 // sets the data (point entity) on the element
48807 groups.select('.shadow');
48808 groups.select('.stroke');
48809 groups.select('.icon')
48810 .attr('xlink:href', function(entity) {
48811 var preset = context.presets().match(entity, graph),
48812 picon = preset && preset.icon;
48817 var isMaki = dataFeatureIcons.indexOf(picon) !== -1;
48818 return '#' + picon + (isMaki ? '-11' : '');
48824 function svgRelationMemberTags(graph) {
48825 return function(entity) {
48826 var tags = entity.tags;
48827 graph.parentRelations(entity).forEach(function(relation) {
48828 var type = relation.tags.type;
48829 if (type === 'multipolygon' || type === 'boundary') {
48830 tags = lodash.extend({}, relation.tags, tags);
48837 function svgTagClasses() {
48839 'building', 'highway', 'railway', 'waterway', 'aeroway',
48840 'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
48841 'leisure', 'military', 'place'
48844 'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
48845 'razed', 'demolished', 'obliterated'
48848 'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
48849 'surface', 'tracktype', 'crossing'
48851 tagClassRe = /^tag-/,
48852 tags = function(entity) { return entity.tags; };
48855 var tagClasses = function(selection$$1) {
48856 selection$$1.each(function tagClassesEach(entity) {
48857 var value = this.className,
48858 classes, primary, status;
48860 if (value.baseVal !== undefined) value = value.baseVal;
48862 classes = value.trim().split(/\s+/).filter(function(name) {
48863 return name.length && !tagClassRe.test(name);
48866 var t = tags(entity), i, k, v;
48868 // pick at most one primary classification tag..
48869 for (i = 0; i < primaries.length; i++) {
48872 if (!v || v === 'no') continue;
48875 if (statuses.indexOf(v) !== -1) { // e.g. `railway=abandoned`
48877 classes += ' tag-' + k;
48879 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48885 // add at most one status tag, only if relates to primary tag..
48887 for (i = 0; i < statuses.length; i++) {
48890 if (!v || v === 'no') continue;
48892 if (v === 'yes') { // e.g. `railway=rail + abandoned=yes`
48895 else if (primary && primary === v) { // e.g. `railway=rail + abandoned=railway`
48897 } else if (!primary && primaries.indexOf(v) !== -1) { // e.g. `abandoned=railway`
48900 classes += ' tag-' + v;
48901 } // else ignore e.g. `highway=path + abandoned=railway`
48908 classes += ' tag-status tag-status-' + status;
48911 // add any secondary (structure) tags
48912 for (i = 0; i < secondaries.length; i++) {
48913 k = secondaries[i];
48915 if (!v || v === 'no') continue;
48916 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48919 // For highways, look for surface tagging..
48920 if (primary === 'highway') {
48921 var paved = (t.highway !== 'track');
48924 if (k in osmPavedTags) {
48925 paved = !!osmPavedTags[k][v];
48930 classes += ' tag-unpaved';
48934 classes = classes.trim();
48936 if (classes !== value) {
48937 select(this).attr('class', classes);
48943 tagClasses.tags = function(_) {
48944 if (!arguments.length) return tags;
48952 function svgTurns(projection) {
48954 return function drawTurns(selection, graph, turns) {
48956 function key(turn) {
48957 return [turn.from.node + turn.via.node + turn.to.node].join('-');
48960 function icon(turn) {
48961 var u = turn.u ? '-u' : '';
48962 if (!turn.restriction)
48963 return '#turn-yes' + u;
48964 var restriction = graph.entity(turn.restriction).tags.restriction;
48966 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
48969 var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
48976 var enter = groups.enter()
48978 .attr('class', 'turn');
48981 .filter(function (turn) { return !turn.u; });
48983 nEnter.append('rect')
48984 .attr('transform', 'translate(-22, -12)')
48985 .attr('width', '44')
48986 .attr('height', '24');
48988 nEnter.append('use')
48989 .attr('transform', 'translate(-22, -12)')
48990 .attr('width', '44')
48991 .attr('height', '24');
48995 .filter(function (turn) { return turn.u; });
48997 uEnter.append('circle')
49000 uEnter.append('use')
49001 .attr('transform', 'translate(-16, -16)')
49002 .attr('width', '32')
49003 .attr('height', '32');
49010 .attr('transform', function (turn) {
49011 var v = graph.entity(turn.via.node),
49012 t = graph.entity(turn.to.node),
49013 a = geoAngle(v, t, projection),
49014 p = projection(v.loc),
49015 r = turn.u ? 0 : 60;
49017 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
49018 'rotate(' + a * 180 / Math.PI + ')';
49021 groups.select('use')
49022 .attr('xlink:href', icon);
49024 groups.select('rect');
49025 groups.select('circle');
49031 function svgVertices$$1(projection, context) {
49033 // z16-, z17, z18+, tagged
49034 shadow: [6, 7.5, 7.5, 11.5],
49035 stroke: [2.5, 3.5, 3.5, 7],
49036 fill: [1, 1.5, 1.5, 1.5]
49042 function siblingAndChildVertices(ids, graph, extent$$1) {
49045 function addChildVertices(entity) {
49046 if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
49048 if (entity.type === 'way') {
49049 for (i = 0; i < entity.nodes.length; i++) {
49050 addChildVertices(graph.entity(entity.nodes[i]));
49052 } else if (entity.type === 'relation') {
49053 for (i = 0; i < entity.members.length; i++) {
49054 var member = context.hasEntity(entity.members[i].id);
49056 addChildVertices(member);
49059 } else if (entity.intersects(extent$$1, graph)) {
49060 vertices[entity.id] = entity;
49065 ids.forEach(function(id) {
49066 var entity = context.hasEntity(id);
49067 if (entity && entity.type === 'node') {
49068 vertices[entity.id] = entity;
49069 context.graph().parentWays(entity).forEach(function(entity) {
49070 addChildVertices(entity);
49072 } else if (entity) {
49073 addChildVertices(entity);
49081 function draw(selection$$1, vertices, klass, graph, zoom$$1, siblings) {
49083 function icon(entity) {
49084 if (entity.id in icons) return icons[entity.id];
49086 entity.hasInterestingTags() &&
49087 context.presets().match(entity, graph).icon;
49088 return icons[entity.id];
49091 function setClass(klass) {
49092 return function(entity) {
49093 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
49097 function setAttributes(selection$$1) {
49098 ['shadow','stroke','fill'].forEach(function(klass) {
49099 var rads = radiuses[klass];
49100 selection$$1.selectAll('.' + klass)
49101 .each(function(entity) {
49102 var i = z && icon(entity),
49104 r = rads[i ? 3 : z];
49106 // slightly increase the size of unconnected endpoints #3775
49107 if (entity.isEndpoint(graph) && !entity.isConnected(graph)) {
49111 this.setAttribute('cx', c);
49112 this.setAttribute('cy', -c);
49113 this.setAttribute('r', r);
49114 if (i && klass === 'fill') {
49115 this.setAttribute('visibility', 'hidden');
49117 this.removeAttribute('visibility');
49122 selection$$1.selectAll('use')
49125 this.removeAttribute('visibility');
49127 this.setAttribute('visibility', 'hidden');
49133 siblings = siblings || {};
49136 z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
49138 var groups = selection$$1
49139 .data(vertices, osmEntity$$1.key);
49144 var enter = groups.enter()
49146 .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
49148 enter.append('circle')
49149 .each(setClass('shadow'));
49151 enter.append('circle')
49152 .each(setClass('stroke'));
49154 // Vertices with icons get a `use`.
49155 enter.filter(function(d) { return icon(d); })
49157 .attr('transform', 'translate(-5, -6)')
49158 .attr('xlink:href', function(d) {
49159 var picon = icon(d),
49160 isMaki = dataFeatureIcons.indexOf(picon) !== -1;
49161 return '#' + picon + (isMaki ? '-11' : '');
49163 .attr('width', '11px')
49164 .attr('height', '11px')
49165 .each(setClass('icon'));
49167 // Vertices with tags get a fill.
49168 enter.filter(function(d) { return d.hasInterestingTags(); })
49170 .each(setClass('fill'));
49174 .attr('transform', svgPointTransform(projection))
49175 .classed('sibling', function(entity) { return entity.id in siblings; })
49176 .classed('shared', function(entity) { return graph.isShared(entity); })
49177 .classed('endpoint', function(entity) { return entity.isEndpoint(graph); })
49178 .call(setAttributes);
49182 function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
49183 var siblings = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
49184 wireframe = context.surface().classed('fill-wireframe'),
49187 for (var i = 0; i < entities.length; i++) {
49188 var entity = entities[i],
49189 geometry = entity.geometry(graph);
49191 if (wireframe && geometry === 'point') {
49192 vertices.push(entity);
49196 if (geometry !== 'vertex')
49199 if (entity.id in siblings ||
49200 entity.hasInterestingTags() ||
49201 entity.isEndpoint(graph) ||
49202 entity.isConnected(graph)) {
49203 vertices.push(entity);
49207 var layer = selection$$1.selectAll('.layer-hit');
49208 layer.selectAll('g.vertex.vertex-persistent')
49210 .call(draw, vertices, 'vertex-persistent', graph, zoom$$1, siblings);
49212 drawHover(selection$$1, graph, extent$$1, zoom$$1);
49216 function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
49217 var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
49218 var layer = selection$$1.selectAll('.layer-hit');
49220 layer.selectAll('g.vertex.vertex-hover')
49221 .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
49225 drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
49226 if (target === hover) return;
49228 drawHover(selection$$1, graph, extent$$1, zoom$$1);
49231 return drawVertices;
49234 function behaviorEdit(context) {
49238 .minzoom(context.minEditableZoom());
49242 edit.off = function() {
49252 The hover behavior adds the `.hover` class on mouseover to all elements to which
49253 the identical datum is bound, and removes it on mouseout.
49255 The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
49256 representation may consist of several elements scattered throughout the DOM hierarchy.
49257 Only one of these elements can have the :hover pseudo-class, but all of them will
49258 have the .hover class.
49260 function behaviorHover(context) {
49261 var dispatch$$1 = dispatch('hover'),
49262 _selection = select(null),
49269 function keydown() {
49270 if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
49271 _selection.selectAll('.hover')
49272 .classed('hover-suppressed', true)
49273 .classed('hover', false);
49276 .classed('hover-disabled', true);
49278 dispatch$$1.call('hover', this, null);
49284 if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
49285 _selection.selectAll('.hover-suppressed')
49286 .classed('hover-suppressed', false)
49287 .classed('hover', true);
49290 .classed('hover-disabled', false);
49292 dispatch$$1.call('hover', this, target ? target.id : null);
49297 var hover = function(selection$$1) {
49298 _selection = selection$$1;
49302 .on('mouseover.hover', mouseover)
49303 .on('mouseout.hover', mouseout)
49304 .on('mousedown.hover', mousedown);
49307 .on('keydown.hover', keydown)
49308 .on('keyup.hover', keyup);
49311 function mouseover() {
49312 if (buttonDown) return;
49313 var target = event.target;
49314 enter(target ? target.__data__ : null);
49318 function mouseout() {
49319 if (buttonDown) return;
49320 var target = event.relatedTarget;
49321 enter(target ? target.__data__ : null);
49325 function mousedown() {
49328 .on('mouseup.hover', mouseup, true);
49332 function mouseup() {
49333 buttonDown = false;
49335 .on('mouseup.hover', null, true);
49339 function enter(d) {
49340 if (d === target) return;
49343 _selection.selectAll('.hover')
49344 .classed('hover', false);
49345 _selection.selectAll('.hover-suppressed')
49346 .classed('hover-suppressed', false);
49348 if (target instanceof osmEntity$$1 && target.id !== newId) {
49350 // If drawing a way, don't hover on a node that was just placed. #3974
49351 var mode = context.mode() && context.mode().id;
49352 if ((mode === 'draw-line' || mode === 'draw-area') && !newId && target.type === 'node') {
49357 var selector$$1 = '.' + target.id;
49359 if (target.type === 'relation') {
49360 target.members.forEach(function(member) {
49361 selector$$1 += ', .' + member.id;
49365 var suppressed = altDisables && event && event.altKey;
49367 _selection.selectAll(selector$$1)
49368 .classed(suppressed ? 'hover-suppressed' : 'hover', true);
49370 dispatch$$1.call('hover', this, !suppressed && target.id);
49373 dispatch$$1.call('hover', this, null);
49380 hover.off = function(selection$$1) {
49381 selection$$1.selectAll('.hover')
49382 .classed('hover', false);
49383 selection$$1.selectAll('.hover-suppressed')
49384 .classed('hover-suppressed', false);
49386 .classed('hover-disabled', false);
49390 .on('mouseover.hover', null)
49391 .on('mouseout.hover', null)
49392 .on('mousedown.hover', null);
49395 .on('keydown.hover', null)
49396 .on('keyup.hover', null);
49400 hover.altDisables = function(_) {
49401 if (!arguments.length) return altDisables;
49407 return utilRebind(hover, dispatch$$1, 'on');
49410 function behaviorTail() {
49414 tooltipSize = [0, 0],
49415 selectionSize = [0, 0];
49418 function tail(selection$$1) {
49419 if (!text$$1) return;
49422 .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
49424 container = select(document.body)
49426 .style('display', 'none')
49427 .attr('class', 'tail tooltip-inner');
49429 container.append('div')
49433 .on('mousemove.tail', mousemove)
49434 .on('mouseenter.tail', mouseenter)
49435 .on('mouseleave.tail', mouseleave);
49438 .on('mousemove.tail', mousemove);
49440 tooltipSize = utilGetDimensions(container);
49441 selectionSize = utilGetDimensions(selection$$1);
49445 container.style('display', 'block');
49446 tooltipSize = utilGetDimensions(container);
49450 function mousemove() {
49451 if (container.style('display') === 'none') show();
49452 var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
49453 -tooltipSize[0] - xmargin : xmargin;
49454 container.classed('left', xoffset > 0);
49455 utilSetTransform(container, event.clientX + xoffset, event.clientY);
49459 function mouseleave() {
49460 if (event.relatedTarget !== container.node()) {
49461 container.style('display', 'none');
49466 function mouseenter() {
49467 if (event.relatedTarget !== container.node()) {
49474 tail.off = function(selection$$1) {
49475 if (!text$$1) return;
49478 .on('mousemove.tail', null)
49482 .on('mousemove.tail', null)
49483 .on('mouseenter.tail', null)
49484 .on('mouseleave.tail', null);
49487 .on('resize.tail', null);
49491 tail.text = function(_) {
49492 if (!arguments.length) return text$$1;
49501 var usedTails = {};
49502 var disableSpace = false;
49503 var lastSpace = null;
49506 function behaviorDraw(context) {
49507 var dispatch$$1 = dispatch('move', 'click', 'clickWay',
49508 'clickNode', 'undo', 'cancel', 'finish'),
49509 keybinding = d3keybinding('draw'),
49510 hover = behaviorHover(context)
49512 .on('hover', context.ui().sidebar.hover),
49513 tail = behaviorTail(),
49514 edit = behaviorEdit(context),
49515 closeTolerance = 4,
49517 mouseLeave = false,
49522 if (event.altKey) return {};
49524 if (event.type === 'keydown') {
49525 return (lastMouse && lastMouse.target.__data__) || {};
49527 return event.target.__data__ || {};
49532 function mousedown() {
49535 var p = context.container().node();
49536 return touchId !== null ? touches(p).filter(function(p) {
49537 return p.identifier === touchId;
49541 var element = select(this),
49542 touchId = event.touches ? event.changedTouches[0].identifier : null,
49546 element.on('mousemove.draw', null);
49548 select(window).on('mouseup.draw', function() {
49549 var t2 = +new Date(),
49551 dist = geoEuclideanDistance(p1, p2);
49553 element.on('mousemove.draw', mousemove);
49554 select(window).on('mouseup.draw', null);
49556 if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
49557 // Prevent a quick second click
49558 select(window).on('click.draw-block', function() {
49559 event.stopPropagation();
49562 context.map().dblclickEnable(false);
49564 window.setTimeout(function() {
49565 context.map().dblclickEnable(true);
49566 select(window).on('click.draw-block', null);
49575 function mousemove() {
49577 dispatch$$1.call('move', this, datum());
49581 function mouseenter() {
49582 mouseLeave = false;
49586 function mouseleave() {
49593 if (d.type === 'way') {
49594 var dims = context.map().dimensions(),
49595 mouse$$1 = context.mouse(),
49597 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
49598 mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
49601 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
49602 edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
49603 dispatch$$1.call('clickWay', this, choice.loc, edge);
49605 dispatch$$1.call('click', this, context.map().mouseCoordinates());
49608 } else if (d.type === 'node') {
49609 dispatch$$1.call('clickNode', this, d);
49612 dispatch$$1.call('click', this, context.map().mouseCoordinates());
49618 event.preventDefault();
49619 event.stopPropagation();
49621 var currSpace = context.mouse();
49622 if (disableSpace && lastSpace) {
49623 var dist = geoEuclideanDistance(lastSpace, currSpace);
49624 if (dist > tolerance) {
49625 disableSpace = false;
49629 if (disableSpace || mouseLeave || !lastMouse) return;
49631 // user must move mouse or release space bar to allow another click
49632 lastSpace = currSpace;
49633 disableSpace = true;
49635 select(window).on('keyup.space-block', function() {
49636 event.preventDefault();
49637 event.stopPropagation();
49638 disableSpace = false;
49639 select(window).on('keyup.space-block', null);
49646 function backspace() {
49647 event.preventDefault();
49648 dispatch$$1.call('undo');
49653 event.preventDefault();
49654 dispatch$$1.call('cancel');
49659 event.preventDefault();
49660 dispatch$$1.call('finish');
49664 function draw(selection$$1) {
49665 context.install(hover);
49666 context.install(edit);
49668 if (!context.inIntro() && !usedTails[tail.text()]) {
49669 context.install(tail);
49673 .on('⌫', backspace)
49677 .on('space', space)
49678 .on('⌥space', space);
49681 .on('mouseenter.draw', mouseenter)
49682 .on('mouseleave.draw', mouseleave)
49683 .on('mousedown.draw', mousedown)
49684 .on('mousemove.draw', mousemove);
49693 draw.off = function(selection$$1) {
49694 context.ui().sidebar.hover.cancel();
49695 context.uninstall(hover);
49696 context.uninstall(edit);
49698 if (!context.inIntro() && !usedTails[tail.text()]) {
49699 context.uninstall(tail);
49700 usedTails[tail.text()] = true;
49704 .on('mouseenter.draw', null)
49705 .on('mouseleave.draw', null)
49706 .on('mousedown.draw', null)
49707 .on('mousemove.draw', null);
49710 .on('mouseup.draw', null);
49711 // note: keyup.space-block, click.draw-block should remain
49714 .call(keybinding.off);
49718 draw.tail = function(_) {
49724 return utilRebind(draw, dispatch$$1, 'on');
49727 function behaviorAddWay(context) {
49728 var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
49729 draw = behaviorDraw(context);
49731 var addWay = function(surface) {
49732 draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
49733 .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
49734 .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
49735 .on('cancel', addWay.cancel)
49736 .on('finish', addWay.cancel);
49739 .dblclickEnable(false);
49741 surface.call(draw);
49745 addWay.off = function(surface) {
49746 surface.call(draw.off);
49750 addWay.cancel = function() {
49751 window.setTimeout(function() {
49752 context.map().dblclickEnable(true);
49755 context.enter(modeBrowse(context));
49759 addWay.tail = function(text$$1) {
49760 draw.tail(text$$1);
49765 return utilRebind(addWay, dispatch$$1, 'on');
49768 function behaviorBreathe() {
49769 var duration = 800,
49771 selector$$1 = '.selected.shadow, .selected .shadow',
49772 selected = select(null),
49779 function ratchetyInterpolator(a, b, steps, units) {
49782 var sample = quantize$1()
49784 .range(quantize(reinterpolate(a, b), steps));
49786 return function(t) {
49787 return String(sample(t)) + (units || '');
49792 function reset(selection$$1) {
49794 .style('stroke-opacity', null)
49795 .style('stroke-width', null)
49796 .style('fill-opacity', null)
49801 function setAnimationParams(transition$$1, fromTo) {
49802 var toFrom = (fromTo === 'from' ? 'to' : 'from');
49805 .styleTween('stroke-opacity', function(d) {
49806 return ratchetyInterpolator(
49807 params[d.id][toFrom].opacity,
49808 params[d.id][fromTo].opacity,
49812 .styleTween('stroke-width', function(d) {
49813 return ratchetyInterpolator(
49814 params[d.id][toFrom].width,
49815 params[d.id][fromTo].width,
49820 .styleTween('fill-opacity', function(d) {
49821 return ratchetyInterpolator(
49822 params[d.id][toFrom].opacity,
49823 params[d.id][fromTo].opacity,
49827 .styleTween('r', function(d) {
49828 return ratchetyInterpolator(
49829 params[d.id][toFrom].width,
49830 params[d.id][fromTo].width,
49838 function calcAnimationParams(selection$$1) {
49841 .each(function(d) {
49842 var s = select(this),
49843 tag = s.node().tagName,
49844 p = {'from': {}, 'to': {}},
49847 // determine base opacity and width
49848 if (tag === 'circle') {
49849 opacity = parseFloat(s.style('fill-opacity') || 0.5);
49850 width = parseFloat(s.style('r') || 15.5);
49852 opacity = parseFloat(s.style('stroke-opacity') || 0.7);
49853 width = parseFloat(s.style('stroke-width') || 10);
49856 // calculate from/to interpolation params..
49858 p.from.opacity = opacity * 0.6;
49859 p.to.opacity = opacity * 1.25;
49860 p.from.width = width * 0.7;
49861 p.to.width = width * (tag === 'circle' ? 1.5 : 1);
49867 function run(surface, fromTo) {
49868 var toFrom = (fromTo === 'from' ? 'to' : 'from'),
49869 currSelected = surface.selectAll(selector$$1),
49870 currClassed = surface.attr('class');
49872 if (done || currSelected.empty()) {
49873 selected.call(reset);
49877 if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
49878 selected.call(reset);
49879 classed = currClassed;
49880 selected = currSelected.call(calcAnimationParams);
49885 .duration(duration)
49886 .call(setAnimationParams, fromTo)
49887 .on('end', function() {
49888 surface.call(run, toFrom);
49893 var breathe = function(surface) {
49895 timer$$1 = timer(function() {
49896 // wait for elements to actually become selected
49897 if (surface.selectAll(selector$$1).empty()) {
49901 surface.call(run, 'from');
49908 breathe.off = function() {
49922 function behaviorCopy(context) {
49923 var keybinding = d3keybinding('copy');
49926 function groupEntities(ids, graph) {
49927 var entities = ids.map(function (id) { return graph.entity(id); });
49928 return lodash.extend({relation: [], way: [], node: []},
49929 lodash.groupBy(entities, function(entity) { return entity.type; }));
49933 function getDescendants(id, graph, descendants) {
49934 var entity = graph.entity(id),
49937 descendants = descendants || {};
49939 if (entity.type === 'relation') {
49940 children = lodash.map(entity.members, 'id');
49941 } else if (entity.type === 'way') {
49942 children = entity.nodes;
49947 for (i = 0; i < children.length; i++) {
49948 if (!descendants[children[i]]) {
49949 descendants[children[i]] = true;
49950 descendants = getDescendants(children[i], graph, descendants);
49954 return descendants;
49958 function doCopy() {
49959 event.preventDefault();
49961 var graph = context.graph(),
49962 selected = groupEntities(context.selectedIDs(), graph),
49967 for (i = 0; i < selected.relation.length; i++) {
49968 entity = selected.relation[i];
49969 if (!skip[entity.id] && entity.isComplete(graph)) {
49970 canCopy.push(entity.id);
49971 skip = getDescendants(entity.id, graph, skip);
49974 for (i = 0; i < selected.way.length; i++) {
49975 entity = selected.way[i];
49976 if (!skip[entity.id]) {
49977 canCopy.push(entity.id);
49978 skip = getDescendants(entity.id, graph, skip);
49981 for (i = 0; i < selected.node.length; i++) {
49982 entity = selected.node[i];
49983 if (!skip[entity.id]) {
49984 canCopy.push(entity.id);
49988 context.copyIDs(canCopy);
49993 keybinding.on(uiCmd('⌘C'), doCopy);
49994 select(document).call(keybinding);
49999 copy.off = function() {
50000 select(document).call(keybinding.off);
50008 `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
50010 * The `origin` function is expected to return an [x, y] tuple rather than an
50012 * The events are `start`, `move`, and `end`.
50013 (https://github.com/mbostock/d3/issues/563)
50014 * The `start` event is not dispatched until the first cursor movement occurs.
50015 (https://github.com/mbostock/d3/pull/368)
50016 * The `move` event has a `point` and `delta` [x, y] tuple properties rather
50017 than `x`, `y`, `dx`, and `dy` properties.
50018 * The `end` event is not dispatched if no movement occurs.
50019 * An `off` function is available that unbinds the drag's internal event handlers.
50022 function behaviorDrag() {
50023 var event$$1 = dispatch('start', 'move', 'end'),
50027 event_, target, surface;
50030 var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
50031 d3_event_userSelectSuppress = function() {
50032 var selection$$1 = selection(),
50033 select$$1 = selection$$1.style(d3_event_userSelectProperty);
50034 selection$$1.style(d3_event_userSelectProperty, 'none');
50035 return function() {
50036 selection$$1.style(d3_event_userSelectProperty, select$$1);
50041 function d3_eventCancel() {
50042 event.stopPropagation();
50043 event.preventDefault();
50047 function eventOf(thiz, argumentz) {
50048 return function(e1) {
50049 e1.target = drag$$1;
50050 customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
50055 function dragstart() {
50057 event_ = eventOf(target, arguments);
50059 var eventTarget = event.target,
50060 touchId = event.touches ? event.changedTouches[0].identifier : null,
50064 selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
50067 .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
50068 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
50071 offset = origin.apply(target, arguments);
50072 offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
50077 if (touchId === null) {
50078 event.stopPropagation();
50083 var p = surface || target.parentNode;
50084 return touchId !== null ? touches(p).filter(function(p) {
50085 return p.identifier === touchId;
50090 function dragmove() {
50092 dx = p[0] - origin_[0],
50093 dy = p[1] - origin_[1];
50095 if (dx === 0 && dy === 0)
50100 event_({ type: 'start' });
50108 point: [p[0] + offset[0], p[1] + offset[1]],
50114 function dragend() {
50116 event_({ type: 'end' });
50119 if (event.target === eventTarget) {
50121 .on('click.drag', click, true);
50126 .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
50127 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
50136 .on('click.drag', null);
50141 function drag$$1(selection$$1) {
50142 var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
50143 delegate = dragstart;
50146 delegate = function() {
50148 target = event.target;
50149 for (; target && target !== root; target = target.parentNode) {
50150 if (target[matchesSelector](selector$$1) &&
50151 (!filter || filter(target.__data__))) {
50152 return dragstart.call(target, target.__data__);
50159 .on('mousedown.drag' + selector$$1, delegate)
50160 .on('touchstart.drag' + selector$$1, delegate);
50164 drag$$1.off = function(selection$$1) {
50166 .on('mousedown.drag' + selector$$1, null)
50167 .on('touchstart.drag' + selector$$1, null);
50171 drag$$1.selector = function(_) {
50172 if (!arguments.length) return selector$$1;
50178 drag$$1.filter = function(_) {
50179 if (!arguments.length) return origin;
50185 drag$$1.origin = function (_) {
50186 if (!arguments.length) return origin;
50192 drag$$1.cancel = function() {
50194 .on('mousemove.drag', null)
50195 .on('mouseup.drag', null);
50200 drag$$1.target = function() {
50201 if (!arguments.length) return target;
50202 target = arguments[0];
50203 event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
50208 drag$$1.surface = function() {
50209 if (!arguments.length) return surface;
50210 surface = arguments[0];
50215 return utilRebind(drag$$1, event$$1, 'on');
50218 function behaviorDrawWay(context, wayId, index, mode, startGraph) {
50220 var origWay = context.entity(wayId),
50221 isArea = context.geometry(wayId) === 'area',
50223 annotation = t((origWay.isDegenerate() ?
50224 'operations.start.annotation.' :
50225 'operations.continue.annotation.') + context.geometry(wayId)),
50226 draw = behaviorDraw(context),
50233 // initialize the temporary drawing entities
50235 startIndex = typeof index === 'undefined' ? origWay.nodes.length - 1 : 0;
50236 start = osmNode({ id: 'nStart', loc: context.entity(origWay.nodes[startIndex]).loc });
50237 end = osmNode({ id: 'nEnd', loc: context.map().mouseCoordinates() });
50238 segment = osmWay({ id: 'wTemp',
50239 nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
50240 tags: lodash.clone(origWay.tags)
50243 end = osmNode({ loc: context.map().mouseCoordinates() });
50246 // Push an annotated state for undo to return back to.
50247 // We must make sure to remove this edit later.
50248 context.perform(actionNoop(), annotation);
50251 // Add the temporary drawing entities to the graph.
50252 // We must make sure to remove this edit later.
50253 context.perform(AddDrawEntities());
50257 function move(datum) {
50260 if (datum.type === 'node' && datum.id !== end.id) {
50263 } else if (datum.type === 'way') {
50264 var dims = context.map().dimensions(),
50265 mouse = context.mouse(),
50267 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
50268 mouse[1] > pad && mouse[1] < dims[1] - pad;
50271 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
50276 loc = context.map().mouseCoordinates();
50279 context.replace(actionMoveNode(end.id, loc));
50280 end = context.entity(end.id);
50284 function undone() {
50285 // Undo popped the history back to the initial annotated no-op edit.
50286 // Remove initial no-op edit and whatever edit happened immediately before it.
50290 if (context.hasEntity(wayId)) {
50291 context.enter(mode);
50293 context.enter(modeBrowse(context));
50298 function setActiveElements() {
50299 var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
50300 context.surface().selectAll(utilEntitySelector(active))
50301 .classed('active', true);
50305 var drawWay = function(surface) {
50306 draw.on('move', move)
50307 .on('click', drawWay.add)
50308 .on('clickWay', drawWay.addWay)
50309 .on('clickNode', drawWay.addNode)
50310 .on('undo', context.undo)
50311 .on('cancel', drawWay.cancel)
50312 .on('finish', drawWay.finish);
50315 .dblclickEnable(false)
50316 .on('drawn.draw', setActiveElements);
50318 setActiveElements();
50320 surface.call(draw);
50323 .on('undone.draw', undone);
50327 drawWay.off = function(surface) {
50328 // Drawing was interrupted unexpectedly.
50329 // This can happen if the user changes modes,
50330 // clicks geolocate button, a hashchange event occurs, etc.
50332 context.pop(tempEdits);
50333 while (context.graph() !== startGraph) {
50339 .on('drawn.draw', null);
50341 surface.call(draw.off)
50342 .selectAll('.active')
50343 .classed('active', false);
50346 .on('undone.draw', null);
50350 function AddDrawEntities() {
50351 return function(graph) {
50353 // For area drawing, there is no need for a temporary node.
50354 // `end` gets inserted into the way as the penultimate node.
50357 .replace(origWay.addNode(end.id));
50359 // For line drawing, add a temporary start, end, and segment to the graph.
50360 // This allows us to class the new segment as `active`, but still
50361 // connect it back to parts of the way that have already been drawn.
50371 function ReplaceDrawEntities(newNode) {
50372 return function(graph) {
50374 // For area drawing, we didn't create a temporary node.
50375 // `newNode` gets inserted into the _original_ way as the penultimate node.
50377 .replace(origWay.addNode(newNode.id))
50380 // For line drawing, add the `newNode` to the way at specified index,
50381 // and remove the temporary start, end, and segment.
50383 .replace(origWay.addNode(newNode.id, index))
50392 // Accept the current position of the temporary node and continue drawing.
50393 drawWay.add = function(loc) {
50394 // prevent duplicate nodes
50395 var last = context.hasEntity(origWay.nodes[origWay.nodes.length - (isArea ? 2 : 1)]);
50396 if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
50398 context.pop(tempEdits);
50406 var newNode = osmNode({loc: loc});
50408 actionAddEntity(newNode),
50409 ReplaceDrawEntities(newNode),
50415 context.enter(mode);
50419 // Connect the way to an existing way.
50420 drawWay.addWay = function(loc, edge) {
50422 context.pop(tempEdits);
50426 actionAddMidpoint({ loc: loc, edge: edge}, end),
50430 var previousEdge = startIndex ?
50431 [origWay.nodes[startIndex], origWay.nodes[startIndex - 1]] :
50432 [origWay.nodes[0], origWay.nodes[1]];
50434 // Avoid creating duplicate segments
50435 if (geoEdgeEqual(edge, previousEdge))
50438 context.pop(tempEdits);
50440 var newNode = osmNode({ loc: loc });
50442 actionAddMidpoint({ loc: loc, edge: edge}, newNode),
50443 ReplaceDrawEntities(newNode),
50449 context.enter(mode);
50453 // Connect the way to an existing node and continue drawing.
50454 drawWay.addNode = function(node) {
50455 // Avoid creating duplicate segments
50456 if (origWay.areAdjacent(node.id, origWay.nodes[origWay.nodes.length - 1])) return;
50458 // Clicks should not occur on the drawing node, however a space keypress can
50459 // sometimes grab that node's datum (before it gets classed as `active`?) #4016
50460 if (node.id === end.id) {
50461 drawWay.add(node.loc);
50465 context.pop(tempEdits);
50468 ReplaceDrawEntities(node),
50473 context.enter(mode);
50477 // Finish the draw operation, removing the temporary edits.
50478 // If the way has enough nodes to be valid, it's selected.
50479 // Otherwise, delete everything and return to browse mode.
50480 drawWay.finish = function() {
50481 context.pop(tempEdits);
50484 var way = context.hasEntity(wayId);
50485 if (!way || way.isDegenerate()) {
50490 window.setTimeout(function() {
50491 context.map().dblclickEnable(true);
50494 context.enter(modeSelect(context, [wayId]).newFeature(true));
50498 // Cancel the draw operation, delete everything, and return to browse mode.
50499 drawWay.cancel = function() {
50500 context.pop(tempEdits);
50503 while (context.graph() !== startGraph) {
50507 window.setTimeout(function() {
50508 context.map().dblclickEnable(true);
50511 context.enter(modeBrowse(context));
50515 drawWay.tail = function(text) {
50524 function behaviorHash(context) {
50525 var s0 = null, // cached window.location.hash
50526 lat = 90 - 1e-8; // allowable latitude range
50529 var parser = function(map$$1, s) {
50530 var q = utilStringQs(s);
50531 var args = (q.map || '').split('/').map(Number);
50532 if (args.length < 3 || args.some(isNaN)) {
50533 return true; // replace bogus hash
50534 } else if (s !== formatter(map$$1).slice(1)) {
50535 var mode = context.mode();
50536 if (mode && mode.id.match(/^draw/) !== null) {
50537 context.enter(modeBrowse(context));
50539 map$$1.centerZoom([args[2], Math.min(lat, Math.max(-lat, args[1]))], args[0]);
50544 var formatter = function(map$$1) {
50545 var center = map$$1.center(),
50546 zoom$$1 = map$$1.zoom(),
50547 precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
50548 q = lodash.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
50552 var selected = context.selectedIDs().filter(function(id) {
50553 return !context.entity(id).isNew();
50555 if (selected.length) {
50556 newParams.id = selected.join(',');
50559 newParams.map = zoom$$1.toFixed(2) +
50560 '/' + center[1].toFixed(precision) +
50561 '/' + center[0].toFixed(precision);
50563 return '#' + utilQsString(lodash.assign(q, newParams), true);
50567 function update() {
50568 if (context.inIntro()) return;
50569 var s1 = formatter(context.map());
50571 window.location.replace(s0 = s1); // don't recenter the map!
50576 var throttledUpdate = lodash.throttle(update, 500);
50579 function hashchange() {
50580 if (window.location.hash === s0) return; // ignore spurious hashchange events
50581 if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
50582 update(); // replace bogus hash
50589 .on('move.hash', throttledUpdate);
50592 .on('enter.hash', throttledUpdate);
50595 .on('hashchange.hash', hashchange);
50597 if (window.location.hash) {
50598 var q = utilStringQs(window.location.hash.substring(1));
50600 context.zoomToEntity(q.id.split(',')[0], !q.map);
50603 context.storage('comment', q.comment);
50604 context.storage('commentDate', Date.now());
50607 if (q.map) hash.hadHash = true;
50612 hash.off = function() {
50613 throttledUpdate.cancel();
50616 .on('move.hash', null);
50619 .on('enter.hash', null);
50622 .on('hashchange.hash', null);
50624 window.location.hash = '';
50631 function behaviorLasso(context) {
50633 var behavior = function(selection$$1) {
50637 function mousedown() {
50638 var button = 0; // left
50639 if (event.button === button && event.shiftKey === true) {
50643 .on('mousemove.lasso', mousemove)
50644 .on('mouseup.lasso', mouseup);
50646 event.stopPropagation();
50651 function mousemove() {
50653 lasso = uiLasso(context);
50654 context.surface().call(lasso);
50657 lasso.p(context.mouse());
50661 function normalize(a, b) {
50663 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
50664 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
50668 function lassoed() {
50669 if (!lasso) return [];
50671 var graph = context.graph(),
50672 bounds = lasso.extent().map(context.projection.invert),
50673 extent$$1 = geoExtent$$1(normalize(bounds[0], bounds[1]));
50675 return lodash.map(context.intersects(extent$$1).filter(function(entity) {
50676 return entity.type === 'node' &&
50677 geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
50678 !context.features().isHidden(entity, graph, entity.geometry(graph));
50683 function mouseup() {
50685 .on('mousemove.lasso', null)
50686 .on('mouseup.lasso', null);
50688 if (!lasso) return;
50690 var ids = lassoed();
50694 context.enter(modeSelect(context, ids));
50699 .on('mousedown.lasso', mousedown);
50703 behavior.off = function(selection$$1) {
50704 selection$$1.on('mousedown.lasso', null);
50711 /* Creates a keybinding behavior for an operation */
50712 function behaviorOperation() {
50713 var which, keybinding;
50716 function drawIcon(selection$$1) {
50717 var button = selection$$1
50719 .attr('class', 'operation-icon')
50721 .attr('class', 'radial-menu-item radial-menu-item-' + which.id)
50722 .attr('transform', 'translate(10,10)')
50723 .classed('disabled', which.disabled());
50731 .attr('transform', 'translate(-7,-7)')
50732 .attr('width', '14')
50733 .attr('height', '14')
50734 .attr('xlink:href', '#operation-' + which.id);
50736 return selection$$1;
50740 var behavior = function () {
50741 if (which && which.available()) {
50742 keybinding = d3keybinding('behavior.key.' + which.id);
50743 keybinding.on(which.keys, function() {
50744 event.preventDefault();
50745 var disabled = which.disabled();
50752 .attr('class', 'operation-tip')
50753 .text(which.tooltip);
50760 .attr('class', 'operation-tip')
50761 .text(which.annotation() || which.title);
50766 select(document).call(keybinding);
50772 behavior.off = function() {
50774 select(document).call(keybinding.off);
50779 behavior.which = function (_) {
50780 if (!arguments.length) return which;
50789 function behaviorPaste(context) {
50790 var keybinding = d3keybinding('paste');
50792 function omitTag(v, k) {
50800 k === 'description' ||
50801 k.indexOf('name') !== -1 ||
50802 k.indexOf('wiki') === 0 ||
50803 k.indexOf('addr:') === 0 ||
50804 k.indexOf('contact:') === 0
50809 function doPaste() {
50810 event.preventDefault();
50812 var baseGraph = context.graph(),
50813 mouse$$1 = context.mouse(),
50814 projection = context.projection,
50815 viewport = geoExtent$$1(projection.clipExtent()).polygon();
50817 if (!geoPointInPolygon(mouse$$1, viewport)) return;
50819 var extent$$1 = geoExtent$$1(),
50820 oldIDs = context.copyIDs(),
50821 oldGraph = context.copyGraph(),
50824 if (!oldIDs.length) return;
50826 var action = actionCopyEntities(oldIDs, oldGraph);
50827 context.perform(action);
50829 var copies = action.copies();
50830 var originals = lodash.invert(lodash.mapValues(copies, 'id'));
50831 for (var id in copies) {
50832 var oldEntity = oldGraph.entity(id),
50833 newEntity = copies[id];
50835 extent$$1._extend(oldEntity.extent(oldGraph));
50837 actionChangeTags(newEntity.id, lodash.omitBy(newEntity.tags, omitTag))
50840 // Exclude child nodes from newIDs if their parent way was also copied.
50841 var parents = context.graph().parentWays(newEntity),
50842 parentCopied = false;
50843 for (var i = 0; i < parents.length; i++) {
50844 if (originals[parents[i].id]) {
50845 parentCopied = true;
50850 if (!parentCopied) {
50851 newIDs.push(newEntity.id);
50855 // Put pasted objects where mouse pointer is..
50856 var center = projection(extent$$1.center()),
50857 delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
50859 context.perform(actionMove(newIDs, delta, projection));
50860 context.enter(modeMove$$1(context, newIDs, baseGraph));
50865 keybinding.on(uiCmd('⌘V'), doPaste);
50866 select(document).call(keybinding);
50871 paste.off = function() {
50872 select(document).call(keybinding.off);
50879 function behaviorSelect(context) {
50880 var lastMouse = null,
50881 suppressMenu = true,
50887 return mouse(context.container().node());
50891 function keydown() {
50893 if (e && e.shiftKey) {
50895 .classed('behavior-multiselect', true);
50898 if (e && e.keyCode === 93) { // context menu
50899 e.preventDefault();
50900 e.stopPropagation();
50907 if (!e || !e.shiftKey) {
50909 .classed('behavior-multiselect', false);
50913 if (e && e.keyCode === 93) { // context menu
50914 e.preventDefault();
50915 e.stopPropagation();
50921 function mousedown() {
50922 if (!p1) p1 = point();
50924 .on('mouseup.select', mouseup, true);
50926 var isShowAlways = +context.storage('edit-menu-show-always') === 1;
50927 suppressMenu = !isShowAlways;
50931 function mousemove() {
50932 if (event) lastMouse = event;
50936 function mouseup() {
50941 function contextmenu() {
50943 e.preventDefault();
50944 e.stopPropagation();
50946 if (!+e.clientX && !+e.clientY) {
50948 e.sourceEvent = lastMouse;
50954 if (!p1) p1 = point();
50955 suppressMenu = false;
50962 .on('mouseup.select', null, true);
50966 dist = geoEuclideanDistance(p1, p2);
50969 if (dist > tolerance) {
50973 var isMultiselect = event.shiftKey || select('#surface .lasso').node(),
50974 isShowAlways = +context.storage('edit-menu-show-always') === 1,
50975 datum = event.target.__data__ || (lastMouse && lastMouse.target.__data__),
50976 mode = context.mode();
50979 if (datum && datum.type === 'midpoint') {
50980 datum = datum.parents[0];
50983 if (!(datum instanceof osmEntity$$1)) {
50984 // clicked nothing..
50985 if (!isMultiselect && mode.id !== 'browse') {
50986 context.enter(modeBrowse(context));
50990 // clicked an entity..
50991 var selectedIDs = context.selectedIDs();
50993 if (!isMultiselect) {
50994 if (selectedIDs.length > 1 && (!suppressMenu && !isShowAlways)) {
50995 // multiple things already selected, just show the menu...
50996 mode.suppressMenu(false).reselect();
50998 // select a single thing..
50999 context.enter(modeSelect(context, [datum.id]).suppressMenu(suppressMenu));
51003 if (selectedIDs.indexOf(datum.id) !== -1) {
51004 // clicked entity is already in the selectedIDs list..
51005 if (!suppressMenu && !isShowAlways) {
51006 // don't deselect clicked entity, just show the menu.
51007 mode.suppressMenu(false).reselect();
51009 // deselect clicked entity, then reenter select mode or return to browse mode..
51010 selectedIDs = lodash.without(selectedIDs, datum.id);
51011 context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse(context));
51014 // clicked entity is not in the selected list, add it..
51015 selectedIDs = selectedIDs.concat([datum.id]);
51016 context.enter(modeSelect(context, selectedIDs).suppressMenu(suppressMenu));
51021 // reset for next time..
51022 suppressMenu = true;
51026 var behavior = function(selection$$1) {
51028 suppressMenu = true;
51032 .on('keydown.select', keydown)
51033 .on('keyup.select', keyup)
51034 .on('contextmenu.select-window', function() {
51035 // Edge and IE really like to show the contextmenu on the
51036 // menubar when user presses a keyboard menu button
51037 // even after we've already preventdefaulted the key event.
51039 if (+e.clientX === 0 && +e.clientY === 0) {
51040 event.preventDefault();
51041 event.stopPropagation();
51046 .on('mousedown.select', mousedown)
51047 .on('mousemove.select', mousemove)
51048 .on('contextmenu.select', contextmenu);
51050 if (event && event.shiftKey) {
51052 .classed('behavior-multiselect', true);
51057 behavior.off = function(selection$$1) {
51059 .on('keydown.select', null)
51060 .on('keyup.select', null)
51061 .on('contextmenu.select-window', null)
51062 .on('mouseup.select', null, true);
51065 .on('mousedown.select', null)
51066 .on('mousemove.select', null)
51067 .on('contextmenu.select', null);
51070 .classed('behavior-multiselect', false);
51077 function modeAddArea$$1(context) {
51081 title: t('modes.add_area.title'),
51082 description: t('modes.add_area.description'),
51086 var behavior = behaviorAddWay(context)
51087 .tail(t('modes.add_area.tail'))
51088 .on('start', start)
51089 .on('startFromWay', startFromWay)
51090 .on('startFromNode', startFromNode),
51091 defaultTags = { area: 'yes' };
51094 function actionClose(wayId) {
51095 return function (graph) {
51096 return graph.replace(graph.entity(wayId).close());
51101 function start(loc) {
51102 var startGraph = context.graph(),
51103 node = osmNode({ loc: loc }),
51104 way = osmWay({ tags: defaultTags });
51107 actionAddEntity(node),
51108 actionAddEntity(way),
51109 actionAddVertex(way.id, node.id),
51110 actionClose(way.id)
51113 context.enter(modeDrawArea(context, way.id, startGraph));
51117 function startFromWay(loc, edge) {
51118 var startGraph = context.graph(),
51119 node = osmNode({ loc: loc }),
51120 way = osmWay({ tags: defaultTags });
51123 actionAddEntity(node),
51124 actionAddEntity(way),
51125 actionAddVertex(way.id, node.id),
51126 actionClose(way.id),
51127 actionAddMidpoint({ loc: loc, edge: edge }, node)
51130 context.enter(modeDrawArea(context, way.id, startGraph));
51134 function startFromNode(node) {
51135 var startGraph = context.graph(),
51136 way = osmWay({ tags: defaultTags });
51139 actionAddEntity(way),
51140 actionAddVertex(way.id, node.id),
51141 actionClose(way.id)
51144 context.enter(modeDrawArea(context, way.id, startGraph));
51148 mode.enter = function() {
51149 context.install(behavior);
51153 mode.exit = function() {
51154 context.uninstall(behavior);
51161 function modeAddLine$$1(context) {
51165 title: t('modes.add_line.title'),
51166 description: t('modes.add_line.description'),
51170 var behavior = behaviorAddWay(context)
51171 .tail(t('modes.add_line.tail'))
51172 .on('start', start)
51173 .on('startFromWay', startFromWay)
51174 .on('startFromNode', startFromNode);
51177 function start(loc) {
51178 var startGraph = context.graph(),
51179 node = osmNode({ loc: loc }),
51183 actionAddEntity(node),
51184 actionAddEntity(way),
51185 actionAddVertex(way.id, node.id)
51188 context.enter(modeDrawLine(context, way.id, startGraph));
51192 function startFromWay(loc, edge) {
51193 var startGraph = context.graph(),
51194 node = osmNode({ loc: loc }),
51198 actionAddEntity(node),
51199 actionAddEntity(way),
51200 actionAddVertex(way.id, node.id),
51201 actionAddMidpoint({ loc: loc, edge: edge }, node)
51204 context.enter(modeDrawLine(context, way.id, startGraph));
51208 function startFromNode(node) {
51209 var startGraph = context.graph(),
51213 actionAddEntity(way),
51214 actionAddVertex(way.id, node.id)
51217 context.enter(modeDrawLine(context, way.id, startGraph));
51221 mode.enter = function() {
51222 context.install(behavior);
51226 mode.exit = function() {
51227 context.uninstall(behavior);
51233 function modeAddPoint$$1(context) {
51237 title: t('modes.add_point.title'),
51238 description: t('modes.add_point.description'),
51242 var behavior = behaviorDraw(context)
51243 .tail(t('modes.add_point.tail'))
51245 .on('clickWay', addWay)
51246 .on('clickNode', addNode)
51247 .on('cancel', cancel)
51248 .on('finish', cancel);
51251 function add(loc) {
51252 var node = osmNode({ loc: loc });
51255 actionAddEntity(node),
51256 t('operations.add.annotation.point')
51260 modeSelect(context, [node.id]).newFeature(true)
51265 function addWay(loc) {
51270 function addNode(node) {
51275 function cancel() {
51276 context.enter(modeBrowse(context));
51280 mode.enter = function() {
51281 context.install(behavior);
51285 mode.exit = function() {
51286 context.uninstall(behavior);
51293 function modeDragNode$$1(context) {
51305 hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
51306 edit = behaviorEdit(context);
51309 function vecSub(a, b) {
51310 return [a[0] - b[0], a[1] - b[1]];
51313 function edge(point, size) {
51314 var pad = [80, 20, 50, 20], // top, right, bottom, left
51318 if (point[0] > size[0] - pad[1])
51320 if (point[0] < pad[3])
51322 if (point[1] > size[1] - pad[2])
51324 if (point[1] < pad[0])
51335 function startNudge(entity, nudge) {
51336 if (nudgeInterval) window.clearInterval(nudgeInterval);
51337 nudgeInterval = window.setInterval(function() {
51338 context.pan(nudge);
51339 doMove(entity, nudge);
51344 function stopNudge() {
51345 if (nudgeInterval) {
51346 window.clearInterval(nudgeInterval);
51347 nudgeInterval = null;
51352 function moveAnnotation(entity) {
51353 return t('operations.move.annotation.' + entity.geometry(context.graph()));
51357 function connectAnnotation(entity) {
51358 return t('operations.connect.annotation.' + entity.geometry(context.graph()));
51362 function origin(entity) {
51363 return context.projection(entity.loc);
51367 function start(entity) {
51368 wasMidpoint = entity.type === 'midpoint';
51370 isCancelled = event.sourceEvent.shiftKey ||
51371 context.features().hasHiddenConnections(entity, context.graph());
51374 return behavior.cancel();
51378 var midpoint = entity;
51379 entity = osmNode();
51380 context.perform(actionAddMidpoint(midpoint, entity));
51382 var vertex = context.surface().selectAll('.' + entity.id);
51383 behavior.target(vertex.node(), entity);
51386 context.perform(actionNoop());
51389 // activeIDs generate no pointer events. This prevents the node or vertex
51390 // being dragged from trying to connect to itself or its parent element.
51391 activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
51392 activeIDs.push(entity.id);
51393 setActiveElements();
51395 context.enter(mode);
51400 var event$$1 = event && event.sourceEvent;
51401 if (!event$$1 || event$$1.altKey) {
51404 return event$$1.target.__data__ || {};
51409 function doMove(entity, nudge) {
51410 nudge = nudge || [0, 0];
51412 var currPoint = (event && event.point) || context.projection(lastLoc),
51413 currMouse = vecSub(currPoint, nudge),
51414 loc = context.projection.invert(currMouse),
51417 if (!nudgeInterval) {
51418 if (d.type === 'node' && d.id !== entity.id) {
51420 } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
51421 loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
51426 actionMoveNode(entity.id, loc),
51427 moveAnnotation(entity)
51434 function move(entity) {
51435 if (isCancelled) return;
51436 event.sourceEvent.stopPropagation();
51437 lastLoc = context.projection.invert(event.point);
51440 var nudge = edge(event.point, context.map().dimensions());
51442 startNudge(entity, nudge);
51449 function end(entity) {
51450 if (isCancelled) return;
51454 if (d.type === 'way') {
51455 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
51457 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
51458 connectAnnotation(d)
51461 } else if (d.type === 'node' && d.id !== entity.id) {
51463 actionConnect([d.id, entity.id]),
51464 connectAnnotation(d)
51467 } else if (wasMidpoint) {
51470 t('operations.add.annotation.vertex')
51476 moveAnnotation(entity)
51480 var reselection = selectedIDs.filter(function(id) {
51481 return context.graph().hasEntity(id);
51484 if (reselection.length) {
51485 context.enter(modeSelect(context, reselection));
51487 context.enter(modeBrowse(context));
51492 function cancel() {
51494 context.enter(modeBrowse(context));
51498 function setActiveElements() {
51499 context.surface().selectAll(utilEntitySelector(activeIDs))
51500 .classed('active', true);
51504 var behavior = behaviorDrag()
51505 .selector('g.node, g.point, g.midpoint')
51506 .surface(select('#map').node())
51508 .on('start', start)
51513 mode.enter = function() {
51514 context.install(hover);
51515 context.install(edit);
51518 .on('undone.drag-node', cancel);
51521 .on('drawn.drag-node', setActiveElements);
51523 setActiveElements();
51527 mode.exit = function() {
51528 context.ui().sidebar.hover.cancel();
51529 context.uninstall(hover);
51530 context.uninstall(edit);
51533 .on('undone.drag-node', null);
51536 .on('drawn.drag-node', null);
51539 .selectAll('.active')
51540 .classed('active', false);
51546 mode.selectedIDs = function(_) {
51547 if (!arguments.length) return selectedIDs;
51553 mode.behavior = behavior;
51559 function modeBrowse(context) {
51563 title: t('modes.browse.title'),
51564 description: t('modes.browse.description')
51568 behaviorPaste(context),
51569 behaviorHover(context).on('hover', context.ui().sidebar.hover),
51570 behaviorSelect(context),
51571 behaviorLasso(context),
51572 modeDragNode$$1(context).behavior
51576 mode.enter = function() {
51577 behaviors.forEach(function(behavior) {
51578 context.install(behavior);
51581 // Get focus on the body.
51582 if (document.activeElement && document.activeElement.blur) {
51583 document.activeElement.blur();
51587 context.ui().sidebar.show(sidebar);
51589 context.ui().sidebar.select(null);
51594 mode.exit = function() {
51595 context.ui().sidebar.hover.cancel();
51596 behaviors.forEach(function(behavior) {
51597 context.uninstall(behavior);
51601 context.ui().sidebar.hide();
51606 mode.sidebar = function(_) {
51607 if (!arguments.length) return sidebar;
51616 function modeDrawArea(context, wayId, startGraph) {
51625 mode.enter = function() {
51626 var way = context.entity(wayId);
51628 behavior = behaviorDrawWay(context, wayId, undefined, mode, startGraph)
51629 .tail(t('modes.draw_area.tail'));
51631 var addNode = behavior.addNode;
51633 behavior.addNode = function(node) {
51634 var length = way.nodes.length,
51635 penultimate = length > 2 ? way.nodes[length - 2] : null;
51637 if (node.id === way.first() || node.id === penultimate) {
51644 context.install(behavior);
51648 mode.exit = function() {
51649 context.uninstall(behavior);
51653 mode.selectedIDs = function() {
51661 function modeDrawLine(context, wayId, startGraph, affix) {
51670 mode.enter = function() {
51671 var way = context.entity(wayId),
51672 index = (affix === 'prefix') ? 0 : undefined,
51673 headId = (affix === 'prefix') ? way.first() : way.last();
51675 behavior = behaviorDrawWay(context, wayId, index, mode, startGraph)
51676 .tail(t('modes.draw_line.tail'));
51678 var addNode = behavior.addNode;
51680 behavior.addNode = function(node) {
51681 if (node.id === headId) {
51688 context.install(behavior);
51692 mode.exit = function() {
51693 context.uninstall(behavior);
51697 mode.selectedIDs = function() {
51705 function operationCircularize(selectedIDs, context) {
51706 var entityId = selectedIDs[0],
51707 entity = context.entity(entityId),
51708 extent = entity.extent(context.graph()),
51709 geometry = context.geometry(entityId),
51710 action = actionCircularize(entityId, context.projection);
51713 var operation = function() {
51714 context.perform(action, operation.annotation());
51718 operation.available = function() {
51719 return selectedIDs.length === 1 &&
51720 entity.type === 'way' &&
51721 lodash.uniq(entity.nodes).length > 1;
51725 operation.disabled = function() {
51727 if (extent.percentContainedIn(context.extent()) < 0.8) {
51728 reason = 'too_large';
51729 } else if (context.hasHiddenConnections(entityId)) {
51730 reason = 'connected_to_hidden';
51732 return action.disabled(context.graph()) || reason;
51736 operation.tooltip = function() {
51737 var disable = operation.disabled();
51739 t('operations.circularize.' + disable) :
51740 t('operations.circularize.description.' + geometry);
51744 operation.annotation = function() {
51745 return t('operations.circularize.annotation.' + geometry);
51749 operation.id = 'circularize';
51750 operation.keys = [t('operations.circularize.key')];
51751 operation.title = t('operations.circularize.title');
51752 operation.behavior = behaviorOperation(context).which(operation);
51757 function operationContinue(selectedIDs, context) {
51758 var graph = context.graph(),
51759 entities = selectedIDs.map(function(id) { return graph.entity(id); }),
51760 geometries = lodash.extend({ line: [], vertex: [] },
51761 lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
51762 vertex = geometries.vertex[0];
51765 function candidateWays() {
51766 return graph.parentWays(vertex).filter(function(parent) {
51767 return parent.geometry(graph) === 'line' &&
51768 !parent.isClosed() &&
51769 parent.affix(vertex.id) &&
51770 (geometries.line.length === 0 || geometries.line[0] === parent);
51775 var operation = function() {
51776 var candidate = candidateWays()[0];
51778 modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
51783 operation.available = function() {
51784 return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
51785 !context.features().hasHiddenConnections(vertex, context.graph());
51789 operation.disabled = function() {
51790 var candidates = candidateWays();
51791 if (candidates.length === 0)
51792 return 'not_eligible';
51793 if (candidates.length > 1)
51798 operation.tooltip = function() {
51799 var disable = operation.disabled();
51801 t('operations.continue.' + disable) :
51802 t('operations.continue.description');
51806 operation.annotation = function() {
51807 return t('operations.continue.annotation.line');
51811 operation.id = 'continue';
51812 operation.keys = [t('operations.continue.key')];
51813 operation.title = t('operations.continue.title');
51814 operation.behavior = behaviorOperation(context).which(operation);
51819 function operationDelete(selectedIDs, context) {
51820 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51821 action = actionDeleteMultiple(selectedIDs),
51822 extent = selectedIDs.reduce(function(extent, id) {
51823 return extent.extend(context.entity(id).extent(context.graph()));
51824 }, geoExtent$$1());
51827 var operation = function() {
51828 var nextSelectedID;
51830 if (selectedIDs.length === 1) {
51831 var id = selectedIDs[0],
51832 entity = context.entity(id),
51833 geometry = context.geometry(id),
51834 parents = context.graph().parentWays(entity),
51835 parent = parents[0];
51837 // Select the next closest node in the way.
51838 if (geometry === 'vertex' && parent.nodes.length > 2) {
51839 var nodes = parent.nodes,
51840 i = nodes.indexOf(id);
51844 } else if (i === nodes.length - 1) {
51847 var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
51848 b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
51849 i = a < b ? i - 1 : i + 1;
51852 nextSelectedID = nodes[i];
51856 context.perform(action, operation.annotation());
51858 if (nextSelectedID && context.hasEntity(nextSelectedID)) {
51859 context.enter(modeSelect(context, [nextSelectedID]).follow(true));
51861 context.enter(modeBrowse(context));
51867 operation.available = function() {
51872 operation.disabled = function() {
51874 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51875 reason = 'too_large';
51876 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51877 reason = 'connected_to_hidden';
51878 } else if (lodash.some(selectedIDs, protectedMember)) {
51879 reason = 'part_of_relation';
51880 } else if (lodash.some(selectedIDs, incompleteRelation)) {
51881 reason = 'incomplete_relation';
51885 function incompleteRelation(id) {
51886 var entity = context.entity(id);
51887 return entity.type === 'relation' && !entity.isComplete(context.graph());
51890 function protectedMember(id) {
51891 var entity = context.entity(id);
51892 if (entity.type !== 'way') return false;
51894 var parents = context.graph().parentRelations(entity);
51895 for (var i = 0; i < parents.length; i++) {
51896 var parent = parents[i],
51897 type = parent.tags.type,
51898 role = parent.memberById(id).role || 'outer';
51899 if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
51909 operation.tooltip = function() {
51910 var disable = operation.disabled();
51912 t('operations.delete.' + disable + '.' + multi) :
51913 t('operations.delete.description' + '.' + multi);
51917 operation.annotation = function() {
51918 return selectedIDs.length === 1 ?
51919 t('operations.delete.annotation.' + context.geometry(selectedIDs[0])) :
51920 t('operations.delete.annotation.multiple', { n: selectedIDs.length });
51924 operation.id = 'delete';
51925 operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
51926 operation.title = t('operations.delete.title');
51927 operation.behavior = behaviorOperation(context).which(operation);
51932 function operationDisconnect(selectedIDs, context) {
51933 var vertices = lodash.filter(selectedIDs, function(entityId) {
51934 return context.geometry(entityId) === 'vertex';
51937 var entityId = vertices[0],
51938 action = actionDisconnect(entityId);
51940 if (selectedIDs.length > 1) {
51941 action.limitWays(lodash.without(selectedIDs, entityId));
51945 var operation = function() {
51946 context.perform(action, operation.annotation());
51950 operation.available = function() {
51951 return vertices.length === 1;
51955 operation.disabled = function() {
51957 if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51958 reason = 'connected_to_hidden';
51960 return action.disabled(context.graph()) || reason;
51964 operation.tooltip = function() {
51965 var disable = operation.disabled();
51967 t('operations.disconnect.' + disable) :
51968 t('operations.disconnect.description');
51972 operation.annotation = function() {
51973 return t('operations.disconnect.annotation');
51977 operation.id = 'disconnect';
51978 operation.keys = [t('operations.disconnect.key')];
51979 operation.title = t('operations.disconnect.title');
51980 operation.behavior = behaviorOperation(context).which(operation);
51985 function operationMerge(selectedIDs, context) {
51987 function updatePresetTags(oldGraph, newGraph, ids) {
51989 oldEntity = oldGraph.hasEntity(id),
51990 newEntity = newGraph.hasEntity(id);
51992 if (!oldEntity || !newEntity) return;
51994 var oldPreset = context.presets().match(oldEntity, oldGraph),
51995 newPreset = context.presets().match(newEntity, newGraph);
51997 context.replace(actionChangePreset(id, oldPreset, newPreset));
52001 var join = actionJoin(selectedIDs),
52002 merge = actionMerge(selectedIDs),
52003 mergePolygon = actionMergePolygon(selectedIDs);
52006 var operation = function() {
52007 var origGraph = context.graph(),
52010 if (!join.disabled(origGraph)) {
52012 } else if (!merge.disabled(origGraph)) {
52015 action = mergePolygon;
52018 context.perform(action, operation.annotation());
52020 var ids = selectedIDs.filter(function(id) {
52021 var entity = context.hasEntity(id);
52022 return entity && entity.type !== 'node';
52025 // if we merged tags, rematch preset and update tags if necessary (#3851)
52026 if (action === merge) {
52027 updatePresetTags(origGraph, context.graph(), ids);
52030 context.enter(modeSelect(context, ids));
52034 operation.available = function() {
52035 return selectedIDs.length >= 2;
52039 operation.disabled = function() {
52040 return join.disabled(context.graph()) &&
52041 merge.disabled(context.graph()) &&
52042 mergePolygon.disabled(context.graph());
52046 operation.tooltip = function() {
52047 var j = join.disabled(context.graph()),
52048 m = merge.disabled(context.graph()),
52049 p = mergePolygon.disabled(context.graph());
52051 if (j === 'restriction' && m && p) {
52052 return t('operations.merge.restriction',
52053 { relation: context.presets().item('type/restriction').name() });
52056 if (p === 'incomplete_relation' && j && m) {
52057 return t('operations.merge.incomplete_relation');
52061 return t('operations.merge.' + j);
52064 return t('operations.merge.description');
52068 operation.annotation = function() {
52069 return t('operations.merge.annotation', { n: selectedIDs.length });
52073 operation.id = 'merge';
52074 operation.keys = [t('operations.merge.key')];
52075 operation.title = t('operations.merge.title');
52076 operation.behavior = behaviorOperation(context).which(operation);
52081 function operationMove(selectedIDs, context) {
52082 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
52083 extent = selectedIDs.reduce(function(extent, id) {
52084 return extent.extend(context.entity(id).extent(context.graph()));
52085 }, geoExtent$$1());
52088 var operation = function() {
52089 context.enter(modeMove$$1(context, selectedIDs));
52093 operation.available = function() {
52094 return selectedIDs.length > 1 ||
52095 context.entity(selectedIDs[0]).type !== 'node';
52099 operation.disabled = function() {
52101 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
52102 reason = 'too_large';
52103 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
52104 reason = 'connected_to_hidden';
52105 } else if (lodash.some(selectedIDs, incompleteRelation)) {
52106 reason = 'incomplete_relation';
52110 function incompleteRelation(id) {
52111 var entity = context.entity(id);
52112 return entity.type === 'relation' && !entity.isComplete(context.graph());
52117 operation.tooltip = function() {
52118 var disable = operation.disabled();
52120 t('operations.move.' + disable + '.' + multi) :
52121 t('operations.move.description.' + multi);
52125 operation.annotation = function() {
52126 return selectedIDs.length === 1 ?
52127 t('operations.move.annotation.' + context.geometry(selectedIDs[0])) :
52128 t('operations.move.annotation.multiple');
52132 operation.id = 'move';
52133 operation.keys = [t('operations.move.key')];
52134 operation.title = t('operations.move.title');
52135 operation.behavior = behaviorOperation(context).which(operation);
52140 function operationOrthogonalize(selectedIDs, context) {
52141 var entityId = selectedIDs[0],
52142 entity = context.entity(entityId),
52143 extent = entity.extent(context.graph()),
52144 geometry = context.geometry(entityId),
52145 action = actionOrthogonalize(entityId, context.projection);
52148 var operation = function() {
52149 context.perform(action, operation.annotation());
52153 operation.available = function() {
52154 return selectedIDs.length === 1 &&
52155 entity.type === 'way' &&
52156 entity.isClosed() &&
52157 lodash.uniq(entity.nodes).length > 2;
52161 operation.disabled = function() {
52163 if (extent.percentContainedIn(context.extent()) < 0.8) {
52164 reason = 'too_large';
52165 } else if (context.hasHiddenConnections(entityId)) {
52166 reason = 'connected_to_hidden';
52168 return action.disabled(context.graph()) || reason;
52172 operation.tooltip = function() {
52173 var disable = operation.disabled();
52175 t('operations.orthogonalize.' + disable) :
52176 t('operations.orthogonalize.description.' + geometry);
52180 operation.annotation = function() {
52181 return t('operations.orthogonalize.annotation.' + geometry);
52185 operation.id = 'orthogonalize';
52186 operation.keys = [t('operations.orthogonalize.key')];
52187 operation.title = t('operations.orthogonalize.title');
52188 operation.behavior = behaviorOperation(context).which(operation);
52193 function operationReflectShort(selectedIDs, context) {
52194 return operationReflect(selectedIDs, context, 'short');
52198 function operationReflectLong(selectedIDs, context) {
52199 return operationReflect(selectedIDs, context, 'long');
52203 function operationReflect(selectedIDs, context, axis) {
52204 axis = axis || 'long';
52205 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
52206 extent = selectedIDs.reduce(function(extent, id) {
52207 return extent.extend(context.entity(id).extent(context.graph()));
52208 }, geoExtent$$1());
52211 var operation = function() {
52212 var action = actionReflect(selectedIDs, context.projection)
52213 .useLongAxis(Boolean(axis === 'long'));
52214 context.perform(action, operation.annotation());
52218 operation.available = function() {
52219 return lodash.some(selectedIDs, hasArea);
52221 function hasArea(id) {
52222 var entity = context.entity(id);
52223 return (entity.type === 'way' && entity.isClosed()) ||
52224 (entity.type ==='relation' && entity.isMultipolygon());
52229 operation.disabled = function() {
52231 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
52232 reason = 'too_large';
52233 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
52234 reason = 'connected_to_hidden';
52235 } else if (lodash.some(selectedIDs, incompleteRelation)) {
52236 reason = 'incomplete_relation';
52240 function incompleteRelation(id) {
52241 var entity = context.entity(id);
52242 return entity.type === 'relation' && !entity.isComplete(context.graph());
52247 operation.tooltip = function() {
52248 var disable = operation.disabled();
52250 t('operations.reflect.' + disable + '.' + multi) :
52251 t('operations.reflect.description.' + axis + '.' + multi);
52255 operation.annotation = function() {
52256 return t('operations.reflect.annotation.' + axis + '.' + multi);
52260 operation.id = 'reflect-' + axis;
52261 operation.keys = [t('operations.reflect.key.' + axis)];
52262 operation.title = t('operations.reflect.title.' + axis);
52263 operation.behavior = behaviorOperation(context).which(operation);
52268 function operationReverse(selectedIDs, context) {
52269 var entityId = selectedIDs[0];
52271 var operation = function() {
52272 context.perform(actionReverse(entityId), operation.annotation());
52276 operation.available = function() {
52277 return selectedIDs.length === 1 && context.geometry(entityId) === 'line';
52281 operation.disabled = function() {
52286 operation.tooltip = function() {
52287 return t('operations.reverse.description');
52291 operation.annotation = function() {
52292 return t('operations.reverse.annotation');
52296 operation.id = 'reverse';
52297 operation.keys = [t('operations.reverse.key')];
52298 operation.title = t('operations.reverse.title');
52299 operation.behavior = behaviorOperation(context).which(operation);
52304 function operationRotate(selectedIDs, context) {
52305 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
52306 extent = selectedIDs.reduce(function(extent, id) {
52307 return extent.extend(context.entity(id).extent(context.graph()));
52308 }, geoExtent$$1());
52311 var operation = function() {
52312 context.enter(modeRotate$$1(context, selectedIDs));
52316 operation.available = function() {
52317 return lodash.some(selectedIDs, hasArea);
52319 function hasArea(id) {
52320 var entity = context.entity(id);
52321 return (entity.type === 'way' && entity.isClosed()) ||
52322 (entity.type ==='relation' && entity.isMultipolygon());
52327 operation.disabled = function() {
52329 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
52330 reason = 'too_large';
52331 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
52332 reason = 'connected_to_hidden';
52333 } else if (lodash.some(selectedIDs, incompleteRelation)) {
52334 reason = 'incomplete_relation';
52338 function incompleteRelation(id) {
52339 var entity = context.entity(id);
52340 return entity.type === 'relation' && !entity.isComplete(context.graph());
52345 operation.tooltip = function() {
52346 var disable = operation.disabled();
52348 t('operations.rotate.' + disable + '.' + multi) :
52349 t('operations.rotate.description.' + multi);
52353 operation.annotation = function() {
52354 return selectedIDs.length === 1 ?
52355 t('operations.rotate.annotation.' + context.geometry(selectedIDs[0])) :
52356 t('operations.rotate.annotation.multiple');
52360 operation.id = 'rotate';
52361 operation.keys = [t('operations.rotate.key')];
52362 operation.title = t('operations.rotate.title');
52363 operation.behavior = behaviorOperation(context).which(operation);
52368 function operationSplit(selectedIDs, context) {
52369 var vertices = lodash.filter(selectedIDs, function(entityId) {
52370 return context.geometry(entityId) === 'vertex';
52373 var entityId = vertices[0],
52374 action = actionSplit(entityId),
52377 if (vertices.length === 1) {
52378 if (selectedIDs.length > 1) {
52379 action.limitWays(lodash.without(selectedIDs, entityId));
52381 ways = action.ways(context.graph());
52385 var operation = function() {
52386 var difference = context.perform(action, operation.annotation());
52387 context.enter(modeSelect(context, difference.extantIDs()));
52391 operation.available = function() {
52392 return vertices.length === 1;
52396 operation.disabled = function() {
52398 if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
52399 reason = 'connected_to_hidden';
52401 return action.disabled(context.graph()) || reason;
52405 operation.tooltip = function() {
52406 var disable = operation.disabled();
52408 return t('operations.split.' + disable);
52410 if (ways.length === 1) {
52411 return t('operations.split.description.' + context.geometry(ways[0].id));
52413 return t('operations.split.description.multiple');
52418 operation.annotation = function() {
52419 return ways.length === 1 ?
52420 t('operations.split.annotation.' + context.geometry(ways[0].id)) :
52421 t('operations.split.annotation.multiple', { n: ways.length });
52425 operation.id = 'split';
52426 operation.keys = [t('operations.split.key')];
52427 operation.title = t('operations.split.title');
52428 operation.behavior = behaviorOperation(context).which(operation);
52433 function operationStraighten(selectedIDs, context) {
52434 var entityId = selectedIDs[0],
52435 action = actionStraighten(entityId, context.projection);
52438 function operation() {
52439 context.perform(action, operation.annotation());
52443 operation.available = function() {
52444 var entity = context.entity(entityId);
52445 return selectedIDs.length === 1 &&
52446 entity.type === 'way' &&
52447 !entity.isClosed() &&
52448 lodash.uniq(entity.nodes).length > 2;
52452 operation.disabled = function() {
52454 if (context.hasHiddenConnections(entityId)) {
52455 reason = 'connected_to_hidden';
52457 return action.disabled(context.graph()) || reason;
52461 operation.tooltip = function() {
52462 var disable = operation.disabled();
52464 t('operations.straighten.' + disable) :
52465 t('operations.straighten.description');
52469 operation.annotation = function() {
52470 return t('operations.straighten.annotation');
52474 operation.id = 'straighten';
52475 operation.keys = [t('operations.straighten.key')];
52476 operation.title = t('operations.straighten.title');
52477 operation.behavior = behaviorOperation(context).which(operation);
52484 var Operations = Object.freeze({
52485 operationCircularize: operationCircularize,
52486 operationContinue: operationContinue,
52487 operationDelete: operationDelete,
52488 operationDisconnect: operationDisconnect,
52489 operationMerge: operationMerge,
52490 operationMove: operationMove,
52491 operationOrthogonalize: operationOrthogonalize,
52492 operationReflectShort: operationReflectShort,
52493 operationReflectLong: operationReflectLong,
52494 operationReverse: operationReverse,
52495 operationRotate: operationRotate,
52496 operationSplit: operationSplit,
52497 operationStraighten: operationStraighten
52500 function modeMove$$1(context, entityIDs, baseGraph) {
52506 var keybinding = d3keybinding('move'),
52508 behaviorEdit(context),
52509 operationCircularize(entityIDs, context).behavior,
52510 operationDelete(entityIDs, context).behavior,
52511 operationOrthogonalize(entityIDs, context).behavior,
52512 operationReflectLong(entityIDs, context).behavior,
52513 operationReflectShort(entityIDs, context).behavior,
52514 operationRotate(entityIDs, context).behavior
52516 annotation = entityIDs.length === 1 ?
52517 t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
52518 t('operations.move.annotation.multiple'),
52525 function vecSub(a, b) {
52526 return [a[0] - b[0], a[1] - b[1]];
52530 function edge(point, size) {
52531 var pad = [80, 20, 50, 20], // top, right, bottom, left
52535 if (point[0] > size[0] - pad[1])
52537 if (point[0] < pad[3])
52539 if (point[1] > size[1] - pad[2])
52541 if (point[1] < pad[0])
52552 function doMove(nudge) {
52553 nudge = nudge || [0, 0];
52556 if (prevGraph !== context.graph()) {
52558 origin = context.map().mouseCoordinates();
52559 fn = context.perform;
52561 fn = context.overwrite;
52564 var currMouse = context.mouse(),
52565 origMouse = context.projection(origin),
52566 delta = vecSub(vecSub(currMouse, origMouse), nudge);
52568 fn(actionMove(entityIDs, delta, context.projection, cache), annotation);
52569 prevGraph = context.graph();
52573 function startNudge(nudge) {
52574 if (nudgeInterval) window.clearInterval(nudgeInterval);
52575 nudgeInterval = window.setInterval(function() {
52576 context.pan(nudge);
52582 function stopNudge() {
52583 if (nudgeInterval) {
52584 window.clearInterval(nudgeInterval);
52585 nudgeInterval = null;
52592 var nudge = edge(context.mouse(), context.map().dimensions());
52601 function finish() {
52602 event.stopPropagation();
52603 context.enter(modeSelect(context, entityIDs));
52608 function cancel() {
52610 while (context.graph() !== baseGraph) context.pop();
52611 context.enter(modeBrowse(context));
52614 context.enter(modeSelect(context, entityIDs));
52620 function undone() {
52621 context.enter(modeBrowse(context));
52625 mode.enter = function() {
52626 origin = context.map().mouseCoordinates();
52630 behaviors.forEach(function(behavior) {
52631 context.install(behavior);
52635 .on('mousemove.move', move)
52636 .on('click.move', finish);
52639 .on('undone.move', undone);
52650 mode.exit = function() {
52653 behaviors.forEach(function(behavior) {
52654 context.uninstall(behavior);
52658 .on('mousemove.move', null)
52659 .on('click.move', null);
52662 .on('undone.move', null);
52671 function modeRotate$$1(context, entityIDs) {
52677 var keybinding = d3keybinding('rotate'),
52679 behaviorEdit(context),
52680 operationCircularize(entityIDs, context).behavior,
52681 operationDelete(entityIDs, context).behavior,
52682 operationMove(entityIDs, context).behavior,
52683 operationOrthogonalize(entityIDs, context).behavior,
52684 operationReflectLong(entityIDs, context).behavior,
52685 operationReflectShort(entityIDs, context).behavior
52687 annotation = entityIDs.length === 1 ?
52688 t('operations.rotate.annotation.' + context.geometry(entityIDs[0])) :
52689 t('operations.rotate.annotation.multiple'),
52696 function doRotate() {
52698 if (context.graph() !== prevGraph) {
52699 fn = context.perform;
52701 fn = context.replace;
52704 // projection changed, recalculate pivot
52705 var projection = context.projection;
52706 var currTransform = projection.transform();
52707 if (!prevTransform ||
52708 currTransform.k !== prevTransform.k ||
52709 currTransform.x !== prevTransform.x ||
52710 currTransform.y !== prevTransform.y) {
52712 var nodes = utilGetAllNodes(entityIDs, context.graph()),
52713 points = nodes.map(function(n) { return projection(n.loc); });
52715 pivot = d3polygonCentroid(d3polygonHull(points));
52716 prevAngle = undefined;
52720 var currMouse = context.mouse(),
52721 currAngle = Math.atan2(currMouse[1] - pivot[1], currMouse[0] - pivot[0]);
52723 if (typeof prevAngle === 'undefined') prevAngle = currAngle;
52724 var delta = currAngle - prevAngle;
52726 fn(actionRotate(entityIDs, pivot, delta, projection), annotation);
52728 prevTransform = currTransform;
52729 prevAngle = currAngle;
52730 prevGraph = context.graph();
52734 function finish() {
52735 event.stopPropagation();
52736 context.enter(modeSelect(context, entityIDs));
52740 function cancel() {
52742 context.enter(modeSelect(context, entityIDs));
52746 function undone() {
52747 context.enter(modeBrowse(context));
52751 mode.enter = function() {
52752 behaviors.forEach(function(behavior) {
52753 context.install(behavior);
52757 .on('mousemove.rotate', doRotate)
52758 .on('click.rotate', finish);
52761 .on('undone.rotate', undone);
52772 mode.exit = function() {
52773 behaviors.forEach(function(behavior) {
52774 context.uninstall(behavior);
52778 .on('mousemove.rotate', null)
52779 .on('click.rotate', null);
52782 .on('undone.rotate', null);
52791 function modeSave$$1(context) {
52796 var commit = uiCommit(context)
52797 .on('cancel', cancel)
52801 function cancel() {
52802 context.enter(modeBrowse(context));
52806 function save(changeset, tryAgain) {
52808 var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
52809 history = context.history(),
52810 origChanges = history.changes(actionDiscardTags(history.difference())),
52811 localGraph = context.graph(),
52812 remoteGraph = coreGraph$$1(history.base(), true),
52813 modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
52814 toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
52815 toLoad = withChildNodes(toCheck, localGraph),
52820 history.perform(actionNoop()); // checkpoint
52823 context.container().call(loading);
52825 if (toCheck.length) {
52826 context.connection().loadMultiple(toLoad, loaded);
52832 function withChildNodes(ids, graph) {
52833 return lodash.uniq(lodash.reduce(ids, function(result, id) {
52834 var entity = graph.entity(id);
52835 if (entity.type === 'way') {
52837 var cn = graph.childNodes(entity);
52838 result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
52840 /* eslint-disable no-console */
52841 if (typeof console !== 'undefined') console.error(err);
52842 /* eslint-enable no-console */
52846 }, lodash.clone(ids)));
52850 // Reload modified entities into an alternate graph and check for conflicts..
52851 function loaded(err, result) {
52852 if (errors.length) return;
52856 msg: err.responseText,
52857 details: [ t('save.status_code', { code: err.status }) ]
52863 lodash.each(result.data, function(entity) {
52864 remoteGraph.replace(entity);
52865 toLoad = lodash.without(toLoad, entity.id);
52867 // Because loadMultiple doesn't download /full like loadEntity,
52868 // need to also load children that aren't already being checked..
52869 if (!entity.visible) return;
52870 if (entity.type === 'way') {
52871 loadMore.push.apply(loadMore,
52872 lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
52873 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
52874 loadMore.push.apply(loadMore,
52875 lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
52879 if (loadMore.length) {
52880 toLoad.push.apply(toLoad, loadMore);
52881 context.connection().loadMultiple(loadMore, loaded);
52884 if (!toLoad.length) {
52891 function checkConflicts() {
52892 function choice(id, text$$1, action) {
52893 return { id: id, text: text$$1, action: function() { history.replace(action); } };
52895 function formatUser(d) {
52896 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
52898 function entityName(entity) {
52899 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
52902 function compareVersions(local$$1, remote) {
52903 if (local$$1.version !== remote.version) return false;
52905 if (local$$1.type === 'way') {
52906 var children = lodash.union(local$$1.nodes, remote.nodes);
52908 for (var i = 0; i < children.length; i++) {
52909 var a = localGraph.hasEntity(children[i]),
52910 b = remoteGraph.hasEntity(children[i]);
52912 if (a && b && a.version !== b.version) return false;
52919 lodash.each(toCheck, function(id) {
52920 var local$$1 = localGraph.entity(id),
52921 remote = remoteGraph.entity(id);
52923 if (compareVersions(local$$1, remote)) return;
52925 var action = actionMergeRemoteChanges,
52926 merge$$1 = action(id, localGraph, remoteGraph, formatUser);
52928 history.replace(merge$$1);
52930 var mergeConflicts = merge$$1.conflicts();
52931 if (!mergeConflicts.length) return; // merged safely
52933 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
52934 forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
52935 keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
52936 keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
52940 name: entityName(local$$1),
52941 details: mergeConflicts,
52944 choice(id, keepMine, forceLocal),
52945 choice(id, keepTheirs, forceRemote)
52954 function upload() {
52955 if (conflicts.length) {
52956 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
52958 } else if (errors.length) {
52961 var changes = history.changes(actionDiscardTags(history.difference()));
52962 if (changes.modified.length || changes.created.length || changes.deleted.length) {
52963 context.connection().putChangeset(changeset, changes, uploadCallback);
52964 } else { // changes were insignificant or reverted by user
52965 select('.inspector-wrap *').remove();
52974 function uploadCallback(err, changeset) {
52977 msg: err.responseText,
52978 details: [ t('save.status_code', { code: err.status }) ]
52982 history.clearSaved();
52983 success(changeset);
52984 // Add delay to allow for postgres replication #1646 #2678
52985 window.setTimeout(function() {
52986 select('.inspector-wrap *').remove();
52994 function showConflicts() {
52995 var selection$$1 = context.container()
52996 .select('#sidebar')
52998 .attr('class','sidebar-component');
53002 selection$$1.call(uiConflicts(context)
53004 .on('download', function() {
53005 var data = JXON.stringify(changeset.update({ id: 'CHANGEME' }).osmChangeJXON(origChanges)),
53006 win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
53009 .on('cancel', function() {
53011 selection$$1.remove();
53013 .on('save', function() {
53014 for (var i = 0; i < conflicts.length; i++) {
53015 if (conflicts[i].chosen === 1) { // user chose "keep theirs"
53016 var entity = context.hasEntity(conflicts[i].id);
53017 if (entity && entity.type === 'way') {
53018 var children = lodash.uniq(entity.nodes);
53019 for (var j = 0; j < children.length; j++) {
53020 history.replace(actionRevert(children[j]));
53023 history.replace(actionRevert(conflicts[i].id));
53027 selection$$1.remove();
53028 save(changeset, true);
53034 function showErrors() {
53035 var selection$$1 = uiConfirm(context.container());
53041 .select('.modal-section.header')
53043 .text(t('save.error'));
53045 addErrors(selection$$1, errors);
53046 selection$$1.okButton();
53050 function addErrors(selection$$1, data) {
53051 var message = selection$$1
53052 .select('.modal-section.message-text');
53054 var items = message
53055 .selectAll('.error-container')
53058 var enter = items.enter()
53060 .attr('class', 'error-container');
53064 .attr('class', 'error-description')
53066 .classed('hide-toggle', true)
53067 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
53068 .on('click', function() {
53069 var error = select(this),
53070 detail = select(this.nextElementSibling),
53071 exp = error.classed('expanded');
53073 detail.style('display', exp ? 'none' : 'block');
53074 error.classed('expanded', !exp);
53076 event.preventDefault();
53079 var details = enter
53081 .attr('class', 'error-detail-container')
53082 .style('display', 'none');
53086 .attr('class', 'error-detail-list')
53088 .data(function(d) { return d.details || []; })
53091 .attr('class', 'error-detail-item')
53092 .text(function(d) { return d; });
53101 function success(changeset) {
53103 context.enter(modeBrowse(context)
53104 .sidebar(uiSuccess(context)
53105 .changeset(changeset)
53106 .on('cancel', function() {
53107 context.ui().sidebar.hide();
53114 mode.enter = function() {
53116 context.ui().sidebar.show(commit);
53119 context.container().selectAll('#content')
53120 .attr('class', 'inactive');
53122 if (context.connection().authenticated()) {
53125 context.connection().authenticate(function(err) {
53136 mode.exit = function() {
53137 context.container().selectAll('#content')
53138 .attr('class', 'active');
53140 context.ui().sidebar.hide();
53146 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
53147 // For example, ⌘Z -> Ctrl+Z
53148 function uiCmd(code) {
53149 var detected = utilDetect();
53151 if (detected.os === 'mac') {
53155 if (detected.os === 'win') {
53156 if (code === '⌘⇧Z') return 'Ctrl+Y';
53168 for (var i = 0; i < code.length; i++) {
53169 if (code[i] in replacements) {
53170 result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
53179 // deprecation warning - Radial Menu to be removed in iD v3
53183 function modeSelect(context, selectedIDs) {
53189 var keybinding = d3keybinding('select'),
53192 behaviorCopy(context),
53193 behaviorPaste(context),
53194 behaviorBreathe(context),
53195 behaviorHover(context),
53196 behaviorSelect(context),
53197 behaviorLasso(context),
53198 modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
53202 newFeature = false,
53203 suppressMenu = true,
53207 var wrap = context.container()
53208 .select('.inspector-wrap');
53211 function singular() {
53212 if (selectedIDs.length === 1) {
53213 return context.hasEntity(selectedIDs[0]);
53218 function checkSelectedIDs() {
53220 if (Array.isArray(selectedIDs)) {
53221 ids = selectedIDs.filter(function(id) {
53222 return context.hasEntity(id);
53229 context.enter(modeBrowse(context));
53231 return !!ids.length;
53235 // find the common parent ways for nextVertex, previousVertex
53236 function commonParents() {
53237 var graph = context.graph(),
53238 commonParents = [];
53240 for (var i = 0; i < selectedIDs.length; i++) {
53241 var entity = context.hasEntity(selectedIDs[i]);
53242 if (!entity || entity.geometry(graph) !== 'vertex') {
53243 return []; // selection includes some not vertexes
53246 var currParents = lodash.map(graph.parentWays(entity), 'id');
53247 if (!commonParents.length) {
53248 commonParents = currParents;
53252 commonParents = lodash.intersection(commonParents, currParents);
53253 if (!commonParents.length) {
53258 return commonParents;
53262 function singularParent() {
53263 var parents = commonParents();
53264 if (!parents || parents.length === 0) {
53265 relatedParent = null;
53269 // relatedParent is used when we visit a vertex with multiple
53270 // parents, and we want to remember which parent line we started on.
53272 if (parents.length === 1) {
53273 relatedParent = parents[0]; // remember this parent for later
53274 return relatedParent;
53277 if (parents.indexOf(relatedParent) !== -1) {
53278 return relatedParent; // prefer the previously seen parent
53285 function closeMenu() {
53287 context.surface().call(editMenu.close);
53292 function positionMenu() {
53293 if (!editMenu) { return; }
53295 var entity = singular();
53296 if (entity && context.geometry(entity.id) === 'relation') {
53297 suppressMenu = true;
53299 var point = context.mouse(),
53300 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
53302 if (point && geoPointInPolygon(point, viewport)) {
53303 editMenu.center(point);
53305 suppressMenu = true;
53311 function showMenu() {
53314 context.surface().call(editMenu);
53319 function toggleMenu() {
53320 // deprecation warning - Radial Menu to be removed in iD v3
53321 if (select('.edit-menu, .radial-menu').empty()) {
53330 mode.selectedIDs = function() {
53331 return selectedIDs;
53335 mode.reselect = function() {
53336 if (!checkSelectedIDs()) return;
53338 var surfaceNode = context.surface().node();
53339 if (surfaceNode.focus) { // FF doesn't support it
53340 surfaceNode.focus();
53344 if (!suppressMenu) {
53350 mode.newFeature = function(_) {
53351 if (!arguments.length) return newFeature;
53357 mode.suppressMenu = function(_) {
53358 if (!arguments.length) return suppressMenu;
53364 mode.follow = function(_) {
53365 if (!arguments.length) return follow;
53371 mode.enter = function() {
53373 function update() {
53375 checkSelectedIDs();
53379 function dblclick() {
53380 var target = select(event.target),
53381 datum = target.datum();
53383 if (datum instanceof osmWay && !target.classed('fill')) {
53384 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
53385 prev = datum.nodes[choice.index - 1],
53386 next = datum.nodes[choice.index];
53389 actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, osmNode()),
53390 t('operations.add.annotation.vertex')
53393 event.preventDefault();
53394 event.stopPropagation();
53396 } else if (datum.type === 'midpoint') {
53398 actionAddMidpoint({loc: datum.loc, edge: datum.edge}, osmNode()),
53399 t('operations.add.annotation.vertex'));
53401 event.preventDefault();
53402 event.stopPropagation();
53407 function selectElements(drawn) {
53408 if (!checkSelectedIDs()) return;
53410 var surface = context.surface(),
53411 entity = singular();
53413 if (entity && context.geometry(entity.id) === 'relation') {
53414 suppressMenu = true;
53418 surface.selectAll('.related')
53419 .classed('related', false);
53422 if (relatedParent) {
53423 surface.selectAll(utilEntitySelector([relatedParent]))
53424 .classed('related', true);
53427 var selection$$1 = context.surface()
53428 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
53430 if (selection$$1.empty()) {
53431 // Return to browse mode if selected DOM elements have
53432 // disappeared because the user moved them out of view..
53433 var source = event && event.type === 'zoom' && event.sourceEvent;
53434 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
53435 context.enter(modeBrowse(context));
53439 .classed('selected', true);
53445 context.enter(modeBrowse(context));
53449 function firstVertex() {
53450 event.preventDefault();
53451 var parent = singularParent();
53453 var way = context.entity(parent);
53455 modeSelect(context, [way.first()]).follow(true)
53461 function lastVertex() {
53462 event.preventDefault();
53463 var parent = singularParent();
53465 var way = context.entity(parent);
53467 modeSelect(context, [way.last()]).follow(true)
53473 function previousVertex() {
53474 event.preventDefault();
53475 var parent = singularParent();
53476 if (!parent) return;
53478 var way = context.entity(parent),
53479 length = way.nodes.length,
53480 curr = way.nodes.indexOf(selectedIDs[0]),
53485 } else if (way.isClosed()) {
53486 index = length - 2;
53489 if (index !== -1) {
53491 modeSelect(context, [way.nodes[index]]).follow(true)
53497 function nextVertex() {
53498 event.preventDefault();
53499 var parent = singularParent();
53500 if (!parent) return;
53502 var way = context.entity(parent),
53503 length = way.nodes.length,
53504 curr = way.nodes.indexOf(selectedIDs[0]),
53507 if (curr < length - 1) {
53509 } else if (way.isClosed()) {
53513 if (index !== -1) {
53515 modeSelect(context, [way.nodes[index]]).follow(true)
53521 function nextParent() {
53522 event.preventDefault();
53523 var parents = lodash.uniq(commonParents());
53524 if (!parents || parents.length < 2) return;
53526 var index = parents.indexOf(relatedParent);
53527 if (index < 0 || index > parents.length - 2) {
53528 relatedParent = parents[0];
53530 relatedParent = parents[index + 1];
53533 var surface = context.surface();
53534 surface.selectAll('.related')
53535 .classed('related', false);
53537 if (relatedParent) {
53538 surface.selectAll(utilEntitySelector([relatedParent]))
53539 .classed('related', true);
53544 if (!checkSelectedIDs()) return;
53546 var operations = lodash.without(values(Operations), operationDelete)
53547 .map(function(o) { return o(selectedIDs, context); })
53548 .filter(function(o) { return o.available(); });
53550 // deprecation warning - Radial Menu to be removed in iD v3
53551 var isRadialMenu = context.storage('edit-menu-style') === 'radial';
53552 if (isRadialMenu) {
53553 operations = operations.slice(0,7);
53554 operations.unshift(operationDelete(selectedIDs, context));
53556 operations.push(operationDelete(selectedIDs, context));
53559 operations.forEach(function(operation) {
53560 if (operation.behavior) {
53561 behaviors.push(operation.behavior);
53565 behaviors.forEach(function(behavior) {
53566 context.install(behavior);
53570 .on(['[','pgup'], previousVertex)
53571 .on([']', 'pgdown'], nextVertex)
53572 .on([uiCmd('⌘['), 'home'], firstVertex)
53573 .on([uiCmd('⌘]'), 'end'], lastVertex)
53574 .on(['\\', 'pause'], nextParent)
53575 .on('⎋', esc, true)
53576 .on('space', toggleMenu);
53582 // deprecation warning - Radial Menu to be removed in iD v3
53583 editMenu = isRadialMenu
53584 ? uiRadialMenu(context, operations)
53585 : uiEditMenu(context, operations);
53587 context.ui().sidebar
53588 .select(singular() ? singular().id : null, newFeature);
53591 .on('undone.select', update)
53592 .on('redone.select', update);
53595 .on('move.select', closeMenu)
53596 .on('drawn.select', selectElements);
53599 .on('dblclick.select', dblclick);
53604 if (selectedIDs.length > 1) {
53605 var entities = uiSelectionList(context, selectedIDs);
53606 context.ui().sidebar.show(entities);
53610 var extent$$1 = geoExtent$$1(),
53611 graph = context.graph();
53612 selectedIDs.forEach(function(id) {
53613 var entity = context.entity(id);
53614 extent$$1._extend(entity.extent(graph));
53617 var loc = extent$$1.center();
53618 context.map().centerEase(loc);
53619 } else if (singular() && singular().type === 'way') {
53620 context.map().pan([0,0]); // full redraw, to adjust z-sorting #2914
53623 timeout$$1 = window.setTimeout(function() {
53625 if (!suppressMenu) {
53628 }, 270); /* after any centerEase completes */
53633 mode.exit = function() {
53634 if (timeout$$1) window.clearTimeout(timeout$$1);
53636 if (inspector) wrap.call(inspector.close);
53638 behaviors.forEach(function(behavior) {
53639 context.uninstall(behavior);
53644 editMenu = undefined;
53647 .on('undone.select', null)
53648 .on('redone.select', null);
53650 var surface = context.surface();
53653 .on('dblclick.select', null);
53656 .selectAll('.selected')
53657 .classed('selected', false);
53660 .selectAll('.related')
53661 .classed('related', false);
53663 context.map().on('drawn.select', null);
53664 context.ui().sidebar.hide();
53671 function uiAccount(context) {
53672 var connection = context.connection();
53675 function update(selection$$1) {
53676 if (!connection.authenticated()) {
53677 selection$$1.selectAll('#userLink, #logoutLink')
53678 .classed('hide', true);
53682 connection.userDetails(function(err, details) {
53683 var userLink = selection$$1.select('#userLink'),
53684 logoutLink = selection$$1.select('#logoutLink');
53687 logoutLink.html('');
53691 selection$$1.selectAll('#userLink, #logoutLink')
53692 .classed('hide', false);
53695 userLink.append('a')
53696 .attr('href', connection.userURL(details.display_name))
53697 .attr('target', '_blank');
53699 // Add thumbnail or dont
53700 if (details.image_url) {
53701 userLink.append('img')
53702 .attr('class', 'icon pre-text user-icon')
53703 .attr('src', details.image_url);
53706 .call(svgIcon('#icon-avatar', 'pre-text light'));
53710 userLink.append('span')
53711 .attr('class', 'label')
53712 .text(details.display_name);
53714 logoutLink.append('a')
53715 .attr('class', 'logout')
53718 .on('click.logout', function() {
53719 event.preventDefault();
53720 connection.logout();
53726 return function(selection$$1) {
53727 selection$$1.append('li')
53728 .attr('id', 'logoutLink')
53729 .classed('hide', true);
53731 selection$$1.append('li')
53732 .attr('id', 'userLink')
53733 .classed('hide', true);
53736 .on('change.account', function() { update(selection$$1); });
53738 update(selection$$1);
53742 function uiAttribution(context) {
53746 function attribution(data, klass) {
53747 var div = selection$$1.selectAll('.' + klass)
53752 .attr('class', klass)
53756 var background = div.selectAll('.attribution')
53757 .data(data, function(d) { return d.name(); });
53762 background = background.enter()
53764 .attr('class', 'attribution')
53765 .each(function(d) {
53766 if (d.terms_html) {
53768 .html(d.terms_html);
53772 var source = d.terms_text || d.id || d.name();
53775 source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
53781 .attr('href', d.terms_url)
53782 .attr('target', '_blank')
53789 .merge(background);
53792 var copyright = background.selectAll('.copyright-notice')
53793 .data(function(d) {
53794 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
53795 return notice ? [notice] : [];
53801 copyright = copyright.enter()
53803 .attr('class', 'copyright-notice')
53811 function update() {
53812 attribution([context.background().baseLayerSource()], 'base-layer-attribution');
53813 attribution(context.background().overlayLayerSources().filter(function (s) {
53814 return s.validZoom(context.map().zoom());
53815 }), 'overlay-layer-attribution');
53819 return function(select$$1) {
53820 selection$$1 = select$$1;
53822 context.background()
53823 .on('change.attribution', update);
53826 .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
53832 function rendererBackgroundSource(data) {
53833 var source = lodash.clone(data),
53835 name = source.name,
53836 best = !!source.best;
53838 source.scaleExtent = data.scaleExtent || [0, 20];
53839 source.overzoom = data.overzoom !== false;
53842 source.offset = function(_) {
53843 if (!arguments.length) return offset;
53849 source.nudge = function(_, zoomlevel) {
53850 offset[0] += _[0] / Math.pow(2, zoomlevel);
53851 offset[1] += _[1] / Math.pow(2, zoomlevel);
53856 source.name = function() {
53861 source.best = function() {
53866 source.area = function() {
53867 if (!data.polygon) return Number.MAX_VALUE; // worldwide
53868 var area$$1 = area({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
53869 return isNaN(area$$1) ? 0 : area$$1;
53873 source.imageryUsed = function() {
53874 return name || source.id;
53878 source.url = function(coord) {
53879 return data.template
53880 .replace('{x}', coord[0])
53881 .replace('{y}', coord[1])
53882 // TMS-flipped y coordinate
53883 .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
53884 .replace(/\{z(oom)?\}/, coord[2])
53885 .replace(/\{switch:([^}]+)\}/, function(s, r) {
53886 var subdomains = r.split(',');
53887 return subdomains[(coord[0] + coord[1]) % subdomains.length];
53889 .replace('{u}', function() {
53891 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
53893 var mask = 1 << (zoom$$1 - 1);
53894 if ((coord[0] & mask) !== 0) b++;
53895 if ((coord[1] & mask) !== 0) b += 2;
53903 source.intersects = function(extent$$1) {
53904 extent$$1 = extent$$1.polygon();
53905 return !data.polygon || data.polygon.some(function(polygon) {
53906 return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
53911 source.validZoom = function(z) {
53912 return source.scaleExtent[0] <= z &&
53913 (source.overzoom || source.scaleExtent[1] > z);
53917 source.isLocatorOverlay = function() {
53918 return source.id === 'mapbox_locator_overlay';
53922 source.copyrightNotices = function() {};
53929 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
53930 // http://msdn.microsoft.com/en-us/library/ff701716.aspx
53931 // http://msdn.microsoft.com/en-us/library/ff701701.aspx
53933 data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
53935 var bing = rendererBackgroundSource(data),
53936 key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
53937 url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
53938 key + '&jsonp={callback}',
53941 jsonpRequest(url, function(json$$1) {
53942 providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
53944 attribution: provider.attribution,
53945 areas: provider.coverageAreas.map(function(area$$1) {
53947 zoom: [area$$1.zoomMin, area$$1.zoomMax],
53948 extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
53953 dispatch$$1.call('change');
53956 bing.copyrightNotices = function(zoom$$1, extent$$1) {
53957 zoom$$1 = Math.min(zoom$$1, 21);
53958 return providers.filter(function(provider) {
53959 return lodash.some(provider.areas, function(area$$1) {
53960 return extent$$1.intersects(area$$1.extent) &&
53961 area$$1.zoom[0] <= zoom$$1 &&
53962 area$$1.zoom[1] >= zoom$$1;
53964 }).map(function(provider) {
53965 return provider.attribution;
53969 bing.logo = 'bing_maps.png';
53970 bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
53976 rendererBackgroundSource.None = function() {
53977 var source = rendererBackgroundSource({ id: 'none', template: '' });
53979 source.name = function() {
53980 return t('background.none');
53983 source.imageryUsed = function() {
53987 source.area = function() {
53988 return -1; // sources in background pane are sorted by area
53995 rendererBackgroundSource.Custom = function(template) {
53996 var source = rendererBackgroundSource({ id: 'custom', template: template });
53998 source.name = function() {
53999 return t('background.custom');
54002 source.imageryUsed = function() {
54003 return 'Custom (' + template + ')';
54006 source.area = function() {
54007 return -2; // sources in background pane are sorted by area
54013 function rendererTileLayer(context) {
54014 var tileSize = 256,
54015 tile = d3geoTile(),
54020 transformProp = utilPrefixCSSProperty('Transform'),
54021 source = rendererBackgroundSource.None();
54024 // blacklist overlay tiles around Null Island..
54025 function nearNullIsland(x, y, z) {
54027 var center = Math.pow(2, z - 1),
54028 width = Math.pow(2, z - 6),
54029 min$$1 = center - (width / 2),
54030 max$$1 = center + (width / 2) - 1;
54031 return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
54037 function tileSizeAtZoom(d, z) {
54038 var epsilon = 0.002;
54039 return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
54043 function atZoom(t, distance) {
54044 var power = Math.pow(2, distance);
54046 Math.floor(t[0] * power),
54047 Math.floor(t[1] * power),
54052 function lookUp(d) {
54053 for (var up = -1; up > -d[2]; up--) {
54054 var tile = atZoom(d, up);
54055 if (cache[source.url(tile)] !== false) {
54062 function uniqueBy(a, n) {
54063 var o = [], seen = {};
54064 for (var i = 0; i < a.length; i++) {
54065 if (seen[a[i][n]] === undefined) {
54067 seen[a[i][n]] = true;
54074 function addSource(d) {
54075 d.push(source.url(d));
54080 // Update tiles based on current state of `projection`.
54081 function background(selection$$1) {
54082 tile.scale(projection.scale() * 2 * Math.PI)
54083 .translate(projection.translate());
54086 projection.scale() * Math.PI - projection.translate()[0],
54087 projection.scale() * Math.PI - projection.translate()[1]];
54089 z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
54091 render(selection$$1);
54095 // Derive the tiles onscreen, remove those offscreen and position them.
54096 // Important that this part not depend on `projection` because it's
54097 // rentered when tiles load/error (see #644).
54098 function render(selection$$1) {
54100 var showDebug = context.getDebug('tile') && !source.overlay;
54102 if (source.validZoom(z)) {
54103 tile().forEach(function(d) {
54105 if (d[3] === '') return;
54106 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
54108 if (cache[d[3]] === false && lookUp(d)) {
54109 requests.push(addSource(lookUp(d)));
54113 requests = uniqueBy(requests, 3).filter(function(r) {
54114 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
54117 // don't re-request tiles which have failed in the past
54118 return cache[r[3]] !== false;
54122 var pixelOffset = [
54123 source.offset()[0] * Math.pow(2, z),
54124 source.offset()[1] * Math.pow(2, z)
54128 cache[d[3]] = true;
54132 .classed('tile-loaded', true);
54133 render(selection$$1);
54136 function error(d) {
54137 cache[d[3]] = false;
54142 render(selection$$1);
54145 function imageTransform(d) {
54146 var _ts = tileSize * Math.pow(2, z - d[2]);
54147 var scale = tileSizeAtZoom(d, z);
54148 return 'translate(' +
54149 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
54150 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
54151 'scale(' + scale + ',' + scale + ')';
54154 function debugTransform(d) {
54155 var _ts = tileSize * Math.pow(2, z - d[2]);
54156 var scale = tileSizeAtZoom(d, z);
54157 return 'translate(' +
54158 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
54159 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
54163 var image = selection$$1.selectAll('img')
54164 .data(requests, function(d) { return d[3]; });
54167 .style(transformProp, imageTransform)
54168 .classed('tile-removing', true)
54170 var tile = select(this);
54171 window.setTimeout(function() {
54172 if (tile.classed('tile-removing')) {
54180 .attr('class', 'tile')
54181 .attr('src', function(d) { return d[3]; })
54182 .on('error', error)
54185 .style(transformProp, imageTransform)
54186 .classed('tile-debug', showDebug)
54187 .classed('tile-removing', false);
54190 var debug = selection$$1.selectAll('.tile-label-debug')
54191 .data(showDebug ? requests : [], function(d) { return d[3]; });
54198 .attr('class', 'tile-label-debug')
54200 .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
54201 .style(transformProp, debugTransform);
54205 background.projection = function(_) {
54206 if (!arguments.length) return projection;
54212 background.dimensions = function(_) {
54213 if (!arguments.length) return tile.size();
54219 background.source = function(_) {
54220 if (!arguments.length) return source;
54223 tile.scaleExtent(source.scaleExtent);
54231 function rendererBackground(context) {
54232 var dispatch$$1 = dispatch('change'),
54233 baseLayer = rendererTileLayer(context).projection(context.projection),
54234 overlayLayers = [],
54238 function findSource(id) {
54239 return lodash.find(backgroundSources, function(d) {
54240 return d.id && d.id === id;
54245 function background(selection$$1) {
54246 var base = selection$$1.selectAll('.layer-background')
54250 .insert('div', '.layer-data')
54251 .attr('class', 'layer layer-background')
54255 var overlays = selection$$1.selectAll('.layer-overlay')
54256 .data(overlayLayers, function(d) { return d.source().name(); });
54262 .insert('div', '.layer-data')
54263 .attr('class', 'layer layer-overlay')
54265 .each(function(layer) { select(this).call(layer); });
54269 background.updateImagery = function() {
54270 if (context.inIntro()) return;
54272 var b = background.baseLayerSource(),
54274 .filter(function (d) { return !d.source().isLocatorOverlay(); })
54275 .map(function (d) { return d.source().id; })
54277 meters = geoOffsetToMeters(b.offset()),
54279 x = +meters[0].toFixed(2),
54280 y = +meters[1].toFixed(2),
54281 q = utilStringQs(window.location.hash.substring(1));
54284 if (id === 'custom') {
54285 id = 'custom:' + b.template;
54291 delete q.background;
54300 if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
54301 q.offset = x + ',' + y;
54306 window.location.replace('#' + utilQsString(q, true));
54308 var imageryUsed = [b.imageryUsed()];
54311 .filter(function (d) { return !d.source().isLocatorOverlay(); })
54312 .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); });
54314 var gpx = context.layers().layer('gpx');
54315 if (gpx && gpx.enabled() && gpx.hasGpx()) {
54316 imageryUsed.push('Local GPX');
54319 var mapillary_images = context.layers().layer('mapillary-images');
54320 if (mapillary_images && mapillary_images.enabled()) {
54321 imageryUsed.push('Mapillary Images');
54324 var mapillary_signs = context.layers().layer('mapillary-signs');
54325 if (mapillary_signs && mapillary_signs.enabled()) {
54326 imageryUsed.push('Mapillary Signs');
54329 context.history().imageryUsed(imageryUsed);
54333 background.sources = function(extent$$1) {
54334 return backgroundSources.filter(function(source) {
54335 return source.intersects(extent$$1);
54340 background.dimensions = function(_) {
54342 baseLayer.dimensions(_);
54344 overlayLayers.forEach(function(layer) {
54345 layer.dimensions(_);
54350 background.baseLayerSource = function(d) {
54351 if (!arguments.length) return baseLayer.source();
54353 // test source against OSM imagery blacklists..
54354 var blacklists = context.connection().imageryBlacklists();
54360 for (i = 0; i < blacklists.length; i++) {
54362 regex = new RegExp(blacklists[i]);
54363 fail = regex.test(d.template);
54371 // ensure at least one test was run.
54373 regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*');
54374 fail = regex.test(d.template);
54377 baseLayer.source(!fail ? d : rendererBackgroundSource.None());
54378 dispatch$$1.call('change');
54379 background.updateImagery();
54384 background.bing = function() {
54385 background.baseLayerSource(findSource('Bing'));
54389 background.showsLayer = function(d) {
54390 return d.id === baseLayer.source().id ||
54391 overlayLayers.some(function(layer) { return d.id === layer.source().id; });
54395 background.overlayLayerSources = function() {
54396 return overlayLayers.map(function (l) { return l.source(); });
54400 background.toggleOverlayLayer = function(d) {
54403 for (var i = 0; i < overlayLayers.length; i++) {
54404 layer = overlayLayers[i];
54405 if (layer.source() === d) {
54406 overlayLayers.splice(i, 1);
54407 dispatch$$1.call('change');
54408 background.updateImagery();
54413 layer = rendererTileLayer(context)
54415 .projection(context.projection)
54416 .dimensions(baseLayer.dimensions());
54418 overlayLayers.push(layer);
54419 dispatch$$1.call('change');
54420 background.updateImagery();
54424 background.nudge = function(d, zoom$$1) {
54425 baseLayer.source().nudge(d, zoom$$1);
54426 dispatch$$1.call('change');
54427 background.updateImagery();
54432 background.offset = function(d) {
54433 if (!arguments.length) return baseLayer.source().offset();
54434 baseLayer.source().offset(d);
54435 dispatch$$1.call('change');
54436 background.updateImagery();
54441 background.init = function() {
54442 function parseMap(qmap) {
54443 if (!qmap) return false;
54444 var args = qmap.split('/').map(Number);
54445 if (args.length < 3 || args.some(isNaN)) return false;
54446 return geoExtent$$1([args[2], args[1]]);
54449 var dataImagery = data.imagery || [],
54450 q = utilStringQs(window.location.hash.substring(1)),
54451 chosen = q.background || q.layer,
54452 extent$$1 = parseMap(q.map),
54455 backgroundSources = dataImagery.map(function(source) {
54456 if (source.type === 'bing') {
54457 return rendererBackgroundSource.Bing(source, dispatch$$1);
54459 return rendererBackgroundSource(source);
54463 backgroundSources.unshift(rendererBackgroundSource.None());
54465 if (!chosen && extent$$1) {
54466 best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
54469 if (chosen && chosen.indexOf('custom:') === 0) {
54470 background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
54472 background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
54475 var locator = lodash.find(backgroundSources, function(d) {
54476 return d.overlay && d.default;
54480 background.toggleOverlayLayer(locator);
54483 var overlays = (q.overlays || '').split(',');
54484 overlays.forEach(function(overlay) {
54485 overlay = findSource(overlay);
54487 background.toggleOverlayLayer(overlay);
54492 var gpx = context.layers().layer('gpx');
54499 var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
54500 return !isNaN(n) && n;
54503 if (offset.length === 2) {
54504 background.offset(geoMetersToOffset(offset));
54510 return utilRebind(background, dispatch$$1, 'on');
54513 function rendererFeatures(context) {
54514 var traffic_roads = {
54516 'motorway_link': true,
54518 'trunk_link': true,
54520 'primary_link': true,
54522 'secondary_link': true,
54524 'tertiary_link': true,
54525 'residential': true,
54526 'unclassified': true,
54527 'living_street': true
54530 var service_roads = {
54542 'pedestrian': true,
54546 var past_futures = {
54548 'construction': true,
54550 'dismantled': true,
54553 'demolished': true,
54554 'obliterated': true
54557 var dispatch$$1 = dispatch('change', 'redraw'),
54566 function update() {
54567 _hidden = features.hidden();
54568 dispatch$$1.call('change');
54569 dispatch$$1.call('redraw');
54573 function defineFeature(k, filter, max$$1) {
54577 enabled: true, // whether the user wants it enabled..
54579 currentMax: (max$$1 || Infinity),
54580 defaultMax: (max$$1 || Infinity),
54581 enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
54582 disable: function() { this.enabled = false; this.currentMax = 0; },
54583 hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
54584 autoHidden: function() { return this.hidden() && this.currentMax > 0; }
54589 defineFeature('points', function isPoint(entity, resolver, geometry) {
54590 return geometry === 'point';
54593 defineFeature('traffic_roads', function isTrafficRoad(entity) {
54594 return traffic_roads[entity.tags.highway];
54597 defineFeature('service_roads', function isServiceRoad(entity) {
54598 return service_roads[entity.tags.highway];
54601 defineFeature('paths', function isPath(entity) {
54602 return paths[entity.tags.highway];
54605 defineFeature('buildings', function isBuilding(entity) {
54607 !!entity.tags['building:part'] ||
54608 (!!entity.tags.building && entity.tags.building !== 'no') ||
54609 entity.tags.amenity === 'shelter' ||
54610 entity.tags.parking === 'multi-storey' ||
54611 entity.tags.parking === 'sheds' ||
54612 entity.tags.parking === 'carports' ||
54613 entity.tags.parking === 'garage_boxes'
54617 defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
54618 return geometry === 'area' &&
54619 !_features.buildings.filter(entity) &&
54620 !_features.water.filter(entity);
54623 defineFeature('boundaries', function isBoundary(entity) {
54624 return !!entity.tags.boundary;
54627 defineFeature('water', function isWater(entity) {
54629 !!entity.tags.waterway ||
54630 entity.tags.natural === 'water' ||
54631 entity.tags.natural === 'coastline' ||
54632 entity.tags.natural === 'bay' ||
54633 entity.tags.landuse === 'pond' ||
54634 entity.tags.landuse === 'basin' ||
54635 entity.tags.landuse === 'reservoir' ||
54636 entity.tags.landuse === 'salt_pond'
54640 defineFeature('rail', function isRail(entity) {
54642 !!entity.tags.railway ||
54643 entity.tags.landuse === 'railway'
54645 traffic_roads[entity.tags.highway] ||
54646 service_roads[entity.tags.highway] ||
54647 paths[entity.tags.highway]
54651 defineFeature('power', function isPower(entity) {
54652 return !!entity.tags.power;
54655 // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
54656 defineFeature('past_future', function isPastFuture(entity) {
54658 traffic_roads[entity.tags.highway] ||
54659 service_roads[entity.tags.highway] ||
54660 paths[entity.tags.highway]
54661 ) { return false; }
54663 var strings = Object.keys(entity.tags);
54665 for (var i = 0; i < strings.length; i++) {
54666 var s = strings[i];
54667 if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
54672 // Lines or areas that don't match another feature filter.
54673 // IMPORTANT: The 'others' feature must be the last one defined,
54674 // so that code in getMatches can skip this test if `hasMatch = true`
54675 defineFeature('others', function isOther(entity, resolver, geometry) {
54676 return (geometry === 'line' || geometry === 'area');
54680 function features() {}
54683 features.features = function() {
54688 features.keys = function() {
54693 features.enabled = function(k) {
54694 if (!arguments.length) {
54695 return _keys.filter(function(k) { return _features[k].enabled; });
54697 return _features[k] && _features[k].enabled;
54701 features.disabled = function(k) {
54702 if (!arguments.length) {
54703 return _keys.filter(function(k) { return !_features[k].enabled; });
54705 return _features[k] && !_features[k].enabled;
54709 features.hidden = function(k) {
54710 if (!arguments.length) {
54711 return _keys.filter(function(k) { return _features[k].hidden(); });
54713 return _features[k] && _features[k].hidden();
54717 features.autoHidden = function(k) {
54718 if (!arguments.length) {
54719 return _keys.filter(function(k) { return _features[k].autoHidden(); });
54721 return _features[k] && _features[k].autoHidden();
54725 features.enable = function(k) {
54726 if (_features[k] && !_features[k].enabled) {
54727 _features[k].enable();
54733 features.disable = function(k) {
54734 if (_features[k] && _features[k].enabled) {
54735 _features[k].disable();
54741 features.toggle = function(k) {
54742 if (_features[k]) {
54743 (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
54749 features.resetStats = function() {
54750 for (var i = 0; i < _keys.length; i++) {
54751 _features[_keys[i]].count = 0;
54753 dispatch$$1.call('change');
54757 features.gatherStats = function(d, resolver, dimensions) {
54758 var needsRedraw = false,
54759 type = lodash.groupBy(d, function(ent) { return ent.type; }),
54760 entities = [].concat(type.relation || [], type.way || [], type.node || []),
54761 currHidden, geometry, matches, i, j;
54763 for (i = 0; i < _keys.length; i++) {
54764 _features[_keys[i]].count = 0;
54767 // adjust the threshold for point/building culling based on viewport size..
54768 // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
54769 _cullFactor = dimensions[0] * dimensions[1] / 1000000;
54771 for (i = 0; i < entities.length; i++) {
54772 geometry = entities[i].geometry(resolver);
54773 if (!(geometry === 'vertex' || geometry === 'relation')) {
54774 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
54775 for (j = 0; j < matches.length; j++) {
54776 _features[matches[j]].count++;
54781 currHidden = features.hidden();
54782 if (currHidden !== _hidden) {
54783 _hidden = currHidden;
54784 needsRedraw = true;
54785 dispatch$$1.call('change');
54788 return needsRedraw;
54792 features.stats = function() {
54793 for (var i = 0; i < _keys.length; i++) {
54794 _stats[_keys[i]] = _features[_keys[i]].count;
54801 features.clear = function(d) {
54802 for (var i = 0; i < d.length; i++) {
54803 features.clearEntity(d[i]);
54808 features.clearEntity = function(entity) {
54809 delete _cache[osmEntity$$1.key(entity)];
54813 features.reset = function() {
54818 features.getMatches = function(entity, resolver, geometry) {
54819 if (geometry === 'vertex' || geometry === 'relation') return {};
54821 var ent = osmEntity$$1.key(entity);
54822 if (!_cache[ent]) {
54826 if (!_cache[ent].matches) {
54830 for (var i = 0; i < _keys.length; i++) {
54831 if (_keys[i] === 'others') {
54832 if (hasMatch) continue;
54834 // Multipolygon members:
54836 // 1. is a way that hasn't matched other 'interesting' feature rules,
54837 // 2. and it belongs to a single parent multipolygon relation
54838 // ...then match whatever feature rules the parent multipolygon has matched.
54839 // see #2548, #2887
54842 // For this to work, getMatches must be called on relations before ways.
54844 if (entity.type === 'way') {
54845 var parents = features.getParents(entity, resolver, geometry);
54846 if (parents.length === 1 && parents[0].isMultipolygon()) {
54847 var pkey = osmEntity$$1.key(parents[0]);
54848 if (_cache[pkey] && _cache[pkey].matches) {
54849 matches = lodash.clone(_cache[pkey].matches);
54856 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
54857 matches[_keys[i]] = hasMatch = true;
54860 _cache[ent].matches = matches;
54863 return _cache[ent].matches;
54867 features.getParents = function(entity, resolver, geometry) {
54868 if (geometry === 'point') return [];
54870 var ent = osmEntity$$1.key(entity);
54871 if (!_cache[ent]) {
54875 if (!_cache[ent].parents) {
54877 if (geometry === 'vertex') {
54878 parents = resolver.parentWays(entity);
54879 } else { // 'line', 'area', 'relation'
54880 parents = resolver.parentRelations(entity);
54882 _cache[ent].parents = parents;
54884 return _cache[ent].parents;
54888 features.isHiddenFeature = function(entity, resolver, geometry) {
54889 if (!_hidden.length) return false;
54890 if (!entity.version) return false;
54892 var matches = features.getMatches(entity, resolver, geometry);
54894 for (var i = 0; i < _hidden.length; i++) {
54895 if (matches[_hidden[i]]) return true;
54901 features.isHiddenChild = function(entity, resolver, geometry) {
54902 if (!_hidden.length) return false;
54903 if (!entity.version || geometry === 'point') return false;
54905 var parents = features.getParents(entity, resolver, geometry);
54906 if (!parents.length) return false;
54908 for (var i = 0; i < parents.length; i++) {
54909 if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
54917 features.hasHiddenConnections = function(entity, resolver) {
54918 if (!_hidden.length) return false;
54919 var childNodes, connections;
54921 if (entity.type === 'midpoint') {
54922 childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
54925 childNodes = entity.nodes ? resolver.childNodes(entity) : [];
54926 connections = features.getParents(entity, resolver, entity.geometry(resolver));
54929 // gather ways connected to child nodes..
54930 connections = lodash.reduce(childNodes, function(result, e) {
54931 return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
54934 return connections.length ? lodash.some(connections, function(e) {
54935 return features.isHidden(e, resolver, e.geometry(resolver));
54940 features.isHidden = function(entity, resolver, geometry) {
54941 if (!_hidden.length) return false;
54942 if (!entity.version) return false;
54944 var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
54945 return fn(entity, resolver, geometry);
54949 features.filter = function(d, resolver) {
54950 if (!_hidden.length) return d;
54953 for (var i = 0; i < d.length; i++) {
54955 if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
54956 result.push(entity);
54963 return utilRebind(features, dispatch$$1, 'on');
54966 function utilBindOnce(target, type, listener, capture) {
54967 var typeOnce = type + '.once';
54969 target.on(typeOnce, null);
54970 listener.apply(this, arguments);
54972 target.on(typeOnce, one, capture);
54976 function rendererMap(context) {
54978 var dimensions = [1, 1],
54979 dispatch$$1 = dispatch('move', 'drawn'),
54980 projection = context.projection,
54981 curtainProjection = context.curtainProjection,
54982 dblclickEnabled = true,
54983 redrawEnabled = true,
54984 transformStart = projection.transform(),
54986 transformed = false,
54988 drawLayers = svgLayers(projection, context),
54989 drawPoints = svgPoints$$1(projection, context),
54990 drawVertices = svgVertices$$1(projection, context),
54991 drawLines = svgLines$$1(projection, context),
54992 drawAreas = svgAreas$$1(projection, context),
54993 drawMidpoints = svgMidpoints$$1(projection, context),
54994 drawLabels = svgLabels(projection, context),
54995 supersurface = select(null),
54996 wrapper = select(null),
54997 surface = select(null),
55001 var zoom$$1 = zoom()
55002 .scaleExtent([ztok(2), ztok(24)])
55003 .interpolate(interpolateValue)
55004 .filter(zoomEventFilter)
55005 .on('zoom', zoomPan);
55007 var _selection = select(null);
55010 function map$$1(selection$$1) {
55012 _selection = selection$$1;
55015 .on('change.map', immediateRedraw);
55017 context.connection()
55018 .on('change.map', immediateRedraw);
55021 .on('change.map', immediateRedraw)
55022 .on('undone.map redone.map', function(stack$$1) {
55023 var mode = context.mode().id;
55024 if (mode !== 'browse' && mode !== 'select') return;
55026 var followSelected = false;
55027 if (Array.isArray(stack$$1.selectedIDs)) {
55028 followSelected = (stack$$1.selectedIDs.length === 1 && stack$$1.selectedIDs[0][0] === 'n');
55030 modeSelect(context, stack$$1.selectedIDs).follow(followSelected)
55033 if (!followSelected && stack$$1.transform) {
55034 map$$1.transformEase(stack$$1.transform);
55038 context.background()
55039 .on('change.map', immediateRedraw);
55042 .on('redraw.map', immediateRedraw);
55045 .on('change.map', function() {
55046 context.background().updateImagery();
55051 .on('dblclick.map', dblClick)
55053 .call(zoom$$1.transform, projection.transform());
55055 supersurface = selection$$1.append('div')
55056 .attr('id', 'supersurface')
55057 .call(utilSetTransform, 0, 0);
55059 // Need a wrapper div because Opera can't cope with an absolutely positioned
55060 // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
55061 wrapper = supersurface
55063 .attr('class', 'layer layer-data');
55065 map$$1.surface = surface = wrapper
55067 .selectAll('.surface')
55068 .attr('id', 'surface');
55071 .call(drawLabels.observe)
55072 .on('mousedown.zoom', function() {
55073 if (event.button === 2) {
55074 event.stopPropagation();
55077 .on('mouseup.zoom', function() {
55078 if (resetTransform()) immediateRedraw();
55080 .on('mousemove.map', function() {
55083 .on('mouseover.vertices', function() {
55084 if (map$$1.editable() && !transformed) {
55085 var hover = event.target.__data__;
55086 surface.selectAll('.data-layer-osm')
55087 .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
55088 dispatch$$1.call('drawn', this, {full: false});
55091 .on('mouseout.vertices', function() {
55092 if (map$$1.editable() && !transformed) {
55093 var hover = event.relatedTarget && event.relatedTarget.__data__;
55094 surface.selectAll('.data-layer-osm')
55095 .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
55096 dispatch$$1.call('drawn', this, {full: false});
55101 .call(context.background());
55103 context.on('enter.map', function() {
55104 if (map$$1.editable() && !transformed) {
55105 var all = context.intersects(map$$1.extent()),
55106 filter = utilFunctor(true),
55107 graph = context.graph();
55109 all = context.features().filter(all, graph);
55110 surface.selectAll('.data-layer-osm')
55111 .call(drawVertices, graph, all, filter, map$$1.extent(), map$$1.zoom())
55112 .call(drawMidpoints, graph, all, filter, map$$1.trimmedExtent());
55113 dispatch$$1.call('drawn', this, {full: false});
55117 map$$1.dimensions(utilGetDimensions(selection$$1));
55121 function zoomEventFilter() {
55122 // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
55123 // Intercept `mousedown` and check if there is an orphaned zoom gesture.
55124 // This can happen if a previous `mousedown` occurred without a `mouseup`.
55125 // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
55126 // so that d3-zoom won't stop propagation of new `mousedown` events.
55127 if (event.type === 'mousedown') {
55128 var hasOrphan = false;
55129 var listeners = window.__on;
55130 for (var i = 0; i < listeners.length; i++) {
55131 var listener = listeners[i];
55132 if (listener.name === 'zoom' && listener.type === 'mouseup') {
55138 var event$$1 = window.CustomEvent;
55140 event$$1 = new event$$1('mouseup');
55142 event$$1 = window.document.createEvent('Event');
55143 event$$1.initEvent('mouseup', false, false);
55145 // Event needs to be dispatched with an event.view property.
55146 event$$1.view = window;
55147 window.dispatchEvent(event$$1);
55151 return event.button !== 2; // ignore right clicks
55156 return 256 * Math.pow(2, z);
55160 return Math.max(Math.log(k) / Math.LN2 - 8, 0);
55163 function pxCenter() {
55164 return [dimensions[0] / 2, dimensions[1] / 2];
55168 function drawVector(difference, extent$$1) {
55169 var graph = context.graph(),
55170 features = context.features(),
55171 all = context.intersects(map$$1.extent()),
55175 var complete = difference.complete(map$$1.extent());
55176 data = lodash.compact(lodash.values(complete));
55177 filter = function(d) { return d.id in complete; };
55178 features.clear(data);
55181 // force a full redraw if gatherStats detects that a feature
55182 // should be auto-hidden (e.g. points or buildings)..
55183 if (features.gatherStats(all, graph, dimensions)) {
55184 extent$$1 = undefined;
55188 data = context.intersects(map$$1.extent().intersection(extent$$1));
55189 var set$$1 = set$2(lodash.map(data, 'id'));
55190 filter = function(d) { return set$$1.has(d.id); };
55194 filter = utilFunctor(true);
55198 data = features.filter(data, graph);
55200 surface.selectAll('.data-layer-osm')
55201 .call(drawVertices, graph, data, filter, map$$1.extent(), map$$1.zoom())
55202 .call(drawLines, graph, data, filter)
55203 .call(drawAreas, graph, data, filter)
55204 .call(drawMidpoints, graph, data, filter, map$$1.trimmedExtent())
55205 .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
55206 .call(drawPoints, graph, data, filter);
55208 dispatch$$1.call('drawn', this, {full: true});
55212 function editOff() {
55213 context.features().resetStats();
55214 surface.selectAll('.layer-osm *').remove();
55215 dispatch$$1.call('drawn', this, {full: true});
55219 function dblClick() {
55220 if (!dblclickEnabled) {
55221 event.preventDefault();
55222 event.stopImmediatePropagation();
55227 function zoomPan(manualEvent) {
55228 var event$$1 = (manualEvent || event),
55229 source = event$$1.sourceEvent,
55230 eventTransform = event$$1.transform;
55232 if (transformStart.x === eventTransform.x &&
55233 transformStart.y === eventTransform.y &&
55234 transformStart.k === eventTransform.k) {
55235 return; // no change
55238 // Normalize mousewheel - #3029
55239 // If wheel delta is provided in LINE units, recalculate it in PIXEL units
55240 // We are essentially redoing the calculations that occur here:
55241 // https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203
55242 // See this for more info:
55243 // https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js
55244 if (source && source.type === 'wheel' && source.deltaMode === 1 /* LINE */) {
55245 // pick sensible scroll amount if user scrolling fast or slow..
55246 var lines = Math.abs(source.deltaY),
55247 scroll = lines > 2 ? 40 : lines * 10;
55249 var t0 = transformed ? transformLast : transformStart,
55250 p0 = mouse$$1(source),
55251 p1 = t0.invert(p0),
55252 k2 = t0.k * Math.pow(2, -source.deltaY * scroll / 500),
55253 x2 = p0[0] - p1[0] * k2,
55254 y2 = p0[1] - p1[1] * k2;
55256 eventTransform = identity$8.translate(x2,y2).scale(k2);
55257 _selection.node().__zoom = eventTransform;
55260 if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
55261 surface.interrupt();
55262 uiFlash().text(t('cannot_zoom'));
55263 setZoom(context.minEditableZoom(), true);
55265 dispatch$$1.call('move', this, map$$1);
55269 projection.transform(eventTransform);
55271 var scale = eventTransform.k / transformStart.k,
55272 tX = (eventTransform.x / scale - transformStart.x) * scale,
55273 tY = (eventTransform.y / scale - transformStart.y) * scale;
55275 if (context.inIntro()) {
55276 curtainProjection.transform({
55277 x: eventTransform.x - tX,
55278 y: eventTransform.y - tY,
55279 k: eventTransform.k
55283 transformed = true;
55284 transformLast = eventTransform;
55285 utilSetTransform(supersurface, tX, tY, scale);
55288 dispatch$$1.call('move', this, map$$1);
55292 function resetTransform() {
55293 if (!transformed) return false;
55295 // deprecation warning - Radial Menu to be removed in iD v3
55296 surface.selectAll('.edit-menu, .radial-menu').interrupt().remove();
55297 utilSetTransform(supersurface, 0, 0);
55298 transformed = false;
55299 if (context.inIntro()) {
55300 curtainProjection.transform(projection.transform());
55306 function redraw(difference, extent$$1) {
55307 if (surface.empty() || !redrawEnabled) return;
55309 // If we are in the middle of a zoom/pan, we can't do differenced redraws.
55310 // It would result in artifacts where differenced entities are redrawn with
55311 // one transform and unchanged entities with another.
55312 if (resetTransform()) {
55313 difference = extent$$1 = undefined;
55316 var z = String(~~map$$1.zoom());
55317 if (surface.attr('data-zoom') !== z) {
55318 surface.attr('data-zoom', z)
55319 .classed('low-zoom', z <= 16);
55323 supersurface.call(context.background());
55330 if (map$$1.editable()) {
55331 context.loadTiles(projection, dimensions);
55332 drawVector(difference, extent$$1);
55337 transformStart = projection.transform();
55343 var queueRedraw = lodash.throttle(redraw, 750);
55346 var immediateRedraw = function(difference, extent$$1) {
55347 if (!difference && !extent$$1) queueRedraw.cancel();
55348 redraw(difference, extent$$1);
55352 function pointLocation(p) {
55353 var translate = projection.translate(),
55354 scale = projection.scale() * 2 * Math.PI;
55355 return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
55359 function locationPoint(l) {
55360 var translate = projection.translate(),
55361 scale = projection.scale() * 2 * Math.PI;
55362 return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
55366 map$$1.mouse = function() {
55367 var event$$1 = mousemove || event;
55370 while ((s = event$$1.sourceEvent)) { event$$1 = s; }
55371 return mouse$$1(event$$1);
55377 map$$1.mouseCoordinates = function() {
55378 return projection.invert(map$$1.mouse());
55382 map$$1.dblclickEnable = function(_) {
55383 if (!arguments.length) return dblclickEnabled;
55384 dblclickEnabled = _;
55389 map$$1.redrawEnable = function(_) {
55390 if (!arguments.length) return redrawEnabled;
55396 function setTransform(t2, duration, force) {
55397 var t$$1 = projection.transform();
55398 if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) {
55405 .duration(duration)
55406 .on('start', function() { map$$1.startEase(); })
55407 .call(zoom$$1.transform, identity$8.translate(t2.x, t2.y).scale(t2.k));
55409 projection.transform(t2);
55410 transformStart = t2;
55411 _selection.call(zoom$$1.transform, transformStart);
55416 function setZoom(z2, force, duration) {
55417 if (z2 === map$$1.zoom() && !force) {
55421 var k = projection.scale(),
55422 k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
55423 center = pxCenter(),
55424 l = pointLocation(center);
55426 projection.scale(k2);
55428 var t$$1 = projection.translate();
55429 l = locationPoint(l);
55431 t$$1[0] += center[0] - l[0];
55432 t$$1[1] += center[1] - l[1];
55435 projection.scale(k); // reset scale
55438 .duration(duration)
55439 .on('start', function() { map$$1.startEase(); })
55440 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k2));
55442 projection.translate(t$$1);
55443 transformStart = projection.transform();
55444 _selection.call(zoom$$1.transform, transformStart);
55451 function setCenter(loc2, duration) {
55452 var c = map$$1.center();
55453 if (loc2[0] === c[0] && loc2[1] === c[1]) {
55457 var t$$1 = projection.translate(),
55458 k = projection.scale(),
55460 ll = projection(loc2);
55462 t$$1[0] = t$$1[0] - ll[0] + pxC[0];
55463 t$$1[1] = t$$1[1] - ll[1] + pxC[1];
55468 .duration(duration)
55469 .on('start', function() { map$$1.startEase(); })
55470 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k));
55472 projection.translate(t$$1);
55473 transformStart = projection.transform();
55474 _selection.call(zoom$$1.transform, transformStart);
55481 map$$1.pan = function(delta, duration) {
55482 var t$$1 = projection.translate(),
55483 k = projection.scale();
55485 t$$1[0] += delta[0];
55486 t$$1[1] += delta[1];
55491 .duration(duration)
55492 .on('start', function() { map$$1.startEase(); })
55493 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k));
55495 projection.translate(t$$1);
55496 transformStart = projection.transform();
55497 _selection.call(zoom$$1.transform, transformStart);
55498 dispatch$$1.call('move', this, map$$1);
55506 map$$1.dimensions = function(_) {
55507 if (!arguments.length) return dimensions;
55508 var center = map$$1.center();
55510 drawLayers.dimensions(dimensions);
55511 context.background().dimensions(dimensions);
55512 projection.clipExtent([[0, 0], dimensions]);
55513 mouse$$1 = utilFastMouse(supersurface.node());
55521 function zoomIn(delta) {
55522 setZoom(~~map$$1.zoom() + delta, true, 250);
55525 function zoomOut(delta) {
55526 setZoom(~~map$$1.zoom() - delta, true, 250);
55529 map$$1.zoomIn = function() { zoomIn(1); };
55530 map$$1.zoomInFurther = function() { zoomIn(4); };
55532 map$$1.zoomOut = function() { zoomOut(1); };
55533 map$$1.zoomOutFurther = function() { zoomOut(4); };
55536 map$$1.center = function(loc2) {
55537 if (!arguments.length) {
55538 return projection.invert(pxCenter());
55541 if (setCenter(loc2)) {
55542 dispatch$$1.call('move', this, map$$1);
55550 map$$1.zoom = function(z2) {
55551 if (!arguments.length) {
55552 return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0);
55555 if (z2 < minzoom) {
55556 surface.interrupt();
55557 uiFlash().text(t('cannot_zoom'));
55558 z2 = context.minEditableZoom();
55562 dispatch$$1.call('move', this, map$$1);
55570 map$$1.zoomTo = function(entity, zoomLimits) {
55571 var extent$$1 = entity.extent(context.graph());
55572 if (!isFinite(extent$$1.area())) return;
55574 var z2 = map$$1.trimmedExtentZoom(extent$$1);
55575 zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
55576 map$$1.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
55580 map$$1.centerZoom = function(loc2, z2) {
55581 var centered = setCenter(loc2),
55582 zoomed = setZoom(z2);
55584 if (centered || zoomed) {
55585 dispatch$$1.call('move', this, map$$1);
55593 map$$1.centerEase = function(loc2, duration) {
55594 duration = duration || 250;
55595 setCenter(loc2, duration);
55600 map$$1.zoomEase = function(z2, duration) {
55601 duration = duration || 250;
55602 setZoom(z2, false, duration);
55607 map$$1.transformEase = function(t2, duration) {
55608 duration = duration || 250;
55609 setTransform(t2, duration, false);
55614 map$$1.startEase = function() {
55615 utilBindOnce(surface, 'mousedown.ease', function() {
55616 map$$1.cancelEase();
55622 map$$1.cancelEase = function() {
55623 _selection.interrupt();
55628 map$$1.extent = function(_) {
55629 if (!arguments.length) {
55630 return new geoExtent$$1(projection.invert([0, dimensions[1]]),
55631 projection.invert([dimensions[0], 0]));
55633 var extent$$1 = geoExtent$$1(_);
55634 map$$1.centerZoom(extent$$1.center(), map$$1.extentZoom(extent$$1));
55639 map$$1.trimmedExtent = function(_) {
55640 if (!arguments.length) {
55641 var headerY = 60, footerY = 30, pad = 10;
55642 return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]),
55643 projection.invert([dimensions[0] - pad, headerY + pad]));
55645 var extent$$1 = geoExtent$$1(_);
55646 map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
55651 function calcZoom(extent$$1, dim) {
55652 var tl = projection([extent$$1[0][0], extent$$1[1][1]]),
55653 br = projection([extent$$1[1][0], extent$$1[0][1]]);
55655 // Calculate maximum zoom that fits extent
55656 var hFactor = (br[0] - tl[0]) / dim[0],
55657 vFactor = (br[1] - tl[1]) / dim[1],
55658 hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
55659 vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
55660 newZoom = map$$1.zoom() - Math.max(hZoomDiff, vZoomDiff);
55666 map$$1.extentZoom = function(_) {
55667 return calcZoom(geoExtent$$1(_), dimensions);
55671 map$$1.trimmedExtentZoom = function(_) {
55672 var trimY = 120, trimX = 40,
55673 trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
55674 return calcZoom(geoExtent$$1(_), trimmed);
55678 map$$1.editable = function() {
55679 return map$$1.zoom() >= context.minEditableZoom();
55683 map$$1.minzoom = function(_) {
55684 if (!arguments.length) return minzoom;
55690 map$$1.layers = drawLayers;
55693 return utilRebind(map$$1, dispatch$$1, 'on');
55696 var TAU = 2 * Math.PI;
55697 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
55698 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
55699 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
55700 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
55703 function uiMapInMap(context) {
55707 function map_in_map(selection$$1) {
55708 var backgroundLayer = rendererTileLayer(context),
55709 overlayLayers = {},
55710 projection = geoRawMercator(),
55711 gpxLayer = svgGpx(projection, context).showLabels(false),
55712 debugLayer = svgDebug(projection, context),
55714 .scaleExtent([ztok(0.5), ztok(24)])
55715 .on('start', zoomStarted)
55716 .on('zoom', zoomed)
55717 .on('end', zoomEnded),
55718 isTransformed = false,
55720 skipEvents = false,
55722 zDiff = 6, // by default, minimap renders at (main zoom - 6)
55723 wrap = select(null),
55724 tiles = select(null),
55725 viewport = select(null),
55726 tStart, // transform at start of gesture
55727 tCurr, // transform at most recent event
55731 function zoomStarted() {
55732 if (skipEvents) return;
55733 tStart = tCurr = projection.transform();
55738 function zoomed() {
55739 if (skipEvents) return;
55741 var x = event.transform.x,
55742 y = event.transform.y,
55743 k = event.transform.k,
55744 isZooming = (k !== tStart.k),
55745 isPanning = (x !== tStart.x || y !== tStart.y);
55747 if (!isZooming && !isPanning) {
55748 return; // no change
55751 // lock in either zooming or panning, don't allow both in minimap.
55753 gesture = isZooming ? 'zoom' : 'pan';
55756 var tMini = projection.transform(),
55759 if (gesture === 'zoom') {
55760 var dMini = utilGetDimensions(wrap),
55761 cMini = vecScale(dMini, 0.5);
55762 scale = k / tMini.k;
55763 tX = (cMini[0] / scale - cMini[0]) * scale;
55764 tY = (cMini[1] / scale - cMini[1]) * scale;
55772 utilSetTransform(tiles, tX, tY, scale);
55773 utilSetTransform(viewport, 0, 0, scale);
55774 isTransformed = true;
55775 tCurr = identity$8.translate(x, y).scale(k);
55777 var zMain = ktoz(context.projection.scale()),
55780 zDiff = zMain - zMini;
55786 function zoomEnded() {
55787 if (skipEvents) return;
55788 if (gesture !== 'pan') return;
55790 updateProjection();
55792 var dMini = utilGetDimensions(wrap),
55793 cMini = vecScale(dMini, 0.5);
55794 context.map().center(projection.invert(cMini)); // recenter main map..
55798 function updateProjection() {
55799 var loc = context.map().center(),
55800 dMini = utilGetDimensions(wrap),
55801 cMini = vecScale(dMini, 0.5),
55802 tMain = context.projection.transform(),
55803 zMain = ktoz(tMain.k),
55804 zMini = Math.max(zMain - zDiff, 0.5),
55805 kMini = ztok(zMini);
55808 .translate([tMain.x, tMain.y])
55811 var point = projection(loc),
55812 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
55813 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
55814 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
55817 .translate([xMini, yMini])
55818 .clipExtent([[0, 0], dMini]);
55820 tCurr = projection.transform();
55822 if (isTransformed) {
55823 utilSetTransform(tiles, 0, 0);
55824 utilSetTransform(viewport, 0, 0);
55825 isTransformed = false;
55829 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
55832 wrap.call(zoom$$1.transform, tCurr);
55833 skipEvents = false;
55837 function redraw() {
55838 clearTimeout(timeoutId);
55839 if (isHidden) return;
55841 updateProjection();
55843 var dMini = utilGetDimensions(wrap),
55844 zMini = ktoz(projection.scale());
55846 // setup tile container
55848 .selectAll('.map-in-map-tiles')
55851 tiles = tiles.enter()
55853 .attr('class', 'map-in-map-tiles')
55856 // redraw background
55858 .source(context.background().baseLayerSource())
55859 .projection(projection)
55860 .dimensions(dMini);
55862 var background = tiles
55863 .selectAll('.map-in-map-background')
55868 .attr('class', 'map-in-map-background')
55870 .call(backgroundLayer);
55874 var overlaySources = context.background().overlayLayerSources();
55875 var activeOverlayLayers = [];
55876 for (var i = 0; i < overlaySources.length; i++) {
55877 if (overlaySources[i].validZoom(zMini)) {
55878 if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
55879 activeOverlayLayers.push(overlayLayers[i]
55880 .source(overlaySources[i])
55881 .projection(projection)
55882 .dimensions(dMini));
55886 var overlay = tiles
55887 .selectAll('.map-in-map-overlay')
55890 overlay = overlay.enter()
55892 .attr('class', 'map-in-map-overlay')
55896 var overlays = overlay
55898 .data(activeOverlayLayers, function(d) { return d.source().name(); });
55903 overlays = overlays.enter()
55906 .each(function(layer) { select(this).call(layer); });
55909 var dataLayers = tiles
55910 .selectAll('.map-in-map-data')
55916 dataLayers = dataLayers.enter()
55918 .attr('class', 'map-in-map-data')
55924 // redraw viewport bounding box
55925 if (gesture !== 'pan') {
55926 var getPath = index$4(projection),
55927 bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
55929 viewport = wrap.selectAll('.map-in-map-viewport')
55932 viewport = viewport.enter()
55934 .attr('class', 'map-in-map-viewport')
55938 var path$$1 = viewport.selectAll('.map-in-map-bbox')
55943 .attr('class', 'map-in-map-bbox')
55945 .attr('d', getPath)
55946 .classed('thick', function(d) { return getPath.area(d) < 30; });
55951 function queueRedraw() {
55952 clearTimeout(timeoutId);
55953 timeoutId = setTimeout(function() { redraw(); }, 750);
55957 function toggle() {
55958 if (event) event.preventDefault();
55960 isHidden = !isHidden;
55962 var label = select('.minimap-toggle');
55963 label.classed('active', !isHidden)
55964 .select('input').property('checked', !isHidden);
55968 .style('display', 'block')
55969 .style('opacity', '1')
55972 .style('opacity', '0')
55973 .on('end', function() {
55974 selection$$1.selectAll('.map-in-map')
55975 .style('display', 'none');
55979 .style('display', 'block')
55980 .style('opacity', '0')
55983 .style('opacity', '1')
55984 .on('end', function() {
55991 uiMapInMap.toggle = toggle;
55993 wrap = selection$$1.selectAll('.map-in-map')
55996 wrap = wrap.enter()
55998 .attr('class', 'map-in-map')
55999 .style('display', (isHidden ? 'none' : 'block'))
56001 .on('dblclick.zoom', null)
56005 .on('drawn.map-in-map', function(drawn) {
56006 if (drawn.full === true) {
56013 var keybinding = d3keybinding('map-in-map')
56023 function uiTooltipHtml(text, key, heading) {
56027 s += '<div class="tooltip-heading"><span>' + heading + '</span></div>';
56030 s += '<div class="tooltip-text"><span>' + text + '</span></div>';
56033 s += '<div class="keyhint-wrap"><span>' + t('tooltip_keyhint') + '</span>' +
56034 '<span class="keyhint">' + key + '</span></div>';
56040 function uiBackground(context) {
56042 detected = utilDetect(),
56043 opacities = [1, 0.75, 0.5, 0.25],
56045 ['right', [0.5, 0]],
56046 ['top', [0, -0.5]],
56047 ['left', [-0.5, 0]],
56048 ['bottom', [0, 0.5]]],
56049 opacityDefault = (context.storage('background-opacity') !== null) ?
56050 (+context.storage('background-opacity')) : 1.0,
56051 customTemplate = context.storage('background-custom-template') || '',
56054 // Can be 0 from <1.3.0 use or due to issue #1923.
56055 if (opacityDefault === 0) opacityDefault = 1.0;
56058 function background(selection$$1) {
56060 function sortSources(a, b) {
56061 return a.best() && !b.best() ? -1
56062 : b.best() && !a.best() ? 1
56063 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
56067 function setOpacity(d) {
56068 var bg = context.container().selectAll('.layer-background')
56070 .style('opacity', d)
56071 .attr('data-opacity', d);
56073 if (!detected.opera) {
56074 utilSetTransform(bg, 0, 0);
56077 opacityList.selectAll('li')
56078 .classed('active', function(_) { return _ === d; });
56080 context.storage('background-opacity', d);
56084 function setTooltips(selection$$1) {
56085 selection$$1.each(function(d, i, nodes) {
56086 var item = select(this).select('label'),
56087 span = item.select('span'),
56088 placement = (i < nodes.length / 2) ? 'bottom' : 'top',
56089 isOverflowing = (span.property('clientWidth') !== span.property('scrollWidth'));
56091 if (d === previous) {
56092 item.call(tooltip()
56093 .placement(placement)
56095 .title(function() {
56096 var tip = '<div>' + t('background.switch') + '</div>';
56097 return uiTooltipHtml(tip, uiCmd('⌘B'));
56100 } else if (d.description || isOverflowing) {
56101 item.call(tooltip()
56102 .placement(placement)
56103 .title(d.description || d.name())
56106 item.call(tooltip().destroy);
56112 function selectLayer() {
56113 function active$$1(d) {
56114 return context.background().showsLayer(d);
56117 content.selectAll('.layer, .custom_layer')
56118 .classed('active', active$$1)
56119 .classed('switch', function(d) { return d === previous; })
56121 .selectAll('input')
56122 .property('checked', active$$1);
56126 function clickSetSource(d) {
56127 event.preventDefault();
56128 previous = context.background().baseLayerSource();
56129 context.background().baseLayerSource(d);
56131 document.activeElement.blur();
56135 function editCustom() {
56136 event.preventDefault();
56137 var template = window.prompt(t('background.custom_prompt'), customTemplate);
56139 setCustom(template);
56146 function setCustom(template) {
56147 context.storage('background-custom-template', template);
56148 var d = rendererBackgroundSource.Custom(template);
56149 content.selectAll('.custom_layer').datum(d);
56154 function clickSetOverlay(d) {
56155 event.preventDefault();
56156 context.background().toggleOverlayLayer(d);
56158 document.activeElement.blur();
56162 function drawList(layerList, type, change, filter) {
56163 var sources = context.background()
56164 .sources(context.map().extent())
56167 var layerLinks = layerList.selectAll('li.layer')
56168 .data(sources, function(d) { return d.name(); });
56173 var enter = layerLinks.enter()
56174 .insert('li', '.custom_layer')
56175 .attr('class', 'layer')
56176 .classed('best', function(d) { return d.best(); });
56178 enter.filter(function(d) { return d.best(); })
56180 .attr('class', 'best')
56182 .title(t('background.best_imagery'))
56183 .placement((textDirection === 'rtl') ? 'right' : 'left'))
56192 .attr('type', type)
56193 .attr('name', 'layers')
56194 .on('change', change);
56198 .text(function(d) { return d.name(); });
56201 layerList.selectAll('li.layer')
56203 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
56207 function update() {
56208 backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
56209 overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
56213 var source = context.background().baseLayerSource();
56214 if (source.id === 'custom') {
56215 customTemplate = source.template;
56222 function updateOffsetVal() {
56223 var meters = geoOffsetToMeters(context.background().offset()),
56224 x = +meters[0].toFixed(2),
56225 y = +meters[1].toFixed(2);
56227 selectAll('.nudge-inner-rect')
56229 .classed('error', false)
56230 .property('value', x + ', ' + y);
56232 selectAll('.nudge-reset')
56233 .classed('disabled', function() {
56234 return (x === 0 && y === 0);
56239 function resetOffset() {
56240 if (event.button !== 0) return;
56241 context.background().offset([0, 0]);
56246 function nudge(d) {
56247 context.background().nudge(d, context.map().zoom());
56252 function buttonOffset(d) {
56253 if (event.button !== 0) return;
56254 var timeout$$1 = window.setTimeout(function() {
56255 interval$$1 = window.setInterval(nudge.bind(null, d), 100);
56259 function doneNudge() {
56260 window.clearTimeout(timeout$$1);
56261 window.clearInterval(interval$$1);
56263 .on('mouseup.buttonoffset', null, true)
56264 .on('mousedown.buttonoffset', null, true);
56268 .on('mouseup.buttonoffset', doneNudge, true)
56269 .on('mousedown.buttonoffset', doneNudge, true);
56275 function inputOffset() {
56276 if (event.button !== 0) return;
56277 var input = select(this);
56278 var d = input.node().value;
56280 if (d === '') return resetOffset();
56282 d = d.replace(/;/g, ',').split(',').map(function(n) {
56283 // if n is NaN, it will always get mapped to false.
56284 return !isNaN(n) && n;
56287 if (d.length !== 2 || !d[0] || !d[1]) {
56288 input.classed('error', true);
56292 context.background().offset(geoMetersToOffset(d));
56297 function dragOffset() {
56298 if (event.button !== 0) return;
56299 var origin = [event.clientX, event.clientY];
56301 context.container()
56303 .attr('class', 'nudge-surface');
56306 .on('mousemove.offset', function() {
56307 var latest = [event.clientX, event.clientY];
56309 -(origin[0] - latest[0]) / 4,
56310 -(origin[1] - latest[1]) / 4
56316 .on('mouseup.offset', function() {
56317 if (event.button !== 0) return;
56318 selectAll('.nudge-surface')
56322 .on('mousemove.offset', null)
56323 .on('mouseup.offset', null);
56326 event.preventDefault();
56335 function toggle() {
56336 if (event) event.preventDefault();
56337 tooltipBehavior.hide(button);
56338 setVisible(!button.classed('active'));
56342 function quickSwitch() {
56344 clickSetSource(previous);
56349 function setVisible(show) {
56350 if (show !== shown) {
56351 button.classed('active', show);
56356 .on('mousedown.background-inside', function() {
56357 event.stopPropagation();
56361 .style('display', 'block')
56362 .style('right', '-300px')
56365 .style('right', '0px');
56367 content.selectAll('.layer, .custom_layer')
56368 .call(setTooltips);
56372 .style('display', 'block')
56373 .style('right', '0px')
56376 .style('right', '-300px')
56377 .on('end', function() {
56378 select(this).style('display', 'none');
56382 .on('mousedown.background-inside', null);
56388 var content = selection$$1
56390 .attr('class', 'fillL map-overlay col3 content hide'),
56391 tooltipBehavior = tooltip()
56392 .placement((textDirection === 'rtl') ? 'right' : 'left')
56394 .title(uiTooltipHtml(t('background.description'), key)),
56395 button = selection$$1
56397 .attr('tabindex', -1)
56398 .on('click', toggle)
56399 .call(svgIcon('#icon-layers', 'light'))
56400 .call(tooltipBehavior),
56404 /* opacity switcher */
56406 var opawrap = content
56408 .attr('class', 'opacity-options-wrapper');
56412 .text(t('background.title'));
56414 var opacityList = opawrap
56416 .attr('class', 'opacity-options');
56418 opacityList.selectAll('div.opacity')
56422 .attr('data-original-title', function(d) {
56423 return t('background.percent_brightness', { opacity: (d * 100) });
56425 .on('click.set-opacity', setOpacity)
56426 .html('<div class="select-box"></div>')
56428 .placement((textDirection === 'rtl') ? 'right' : 'left'))
56430 .attr('class', 'opacity')
56431 .style('opacity', function(d) { return 1.25 - d; });
56434 /* background switcher */
56436 var backgroundList = content
56438 .attr('class', 'layer-list')
56439 .attr('dir', 'auto');
56441 var custom = backgroundList
56443 .attr('class', 'custom_layer')
56444 .datum(rendererBackgroundSource.Custom());
56448 .attr('class', 'layer-browse')
56450 .title(t('background.custom_button'))
56451 .placement((textDirection === 'rtl') ? 'right' : 'left'))
56452 .on('click', editCustom)
56453 .call(svgIcon('#icon-search'));
56460 .attr('type', 'radio')
56461 .attr('name', 'layers')
56462 .on('change', function () {
56463 if (customTemplate) {
56464 setCustom(customTemplate);
56472 .text(t('background.custom'));
56476 .attr('class', 'imagery-faq')
56478 .attr('target', '_blank')
56479 .attr('tabindex', -1)
56480 .call(svgIcon('#icon-out-link', 'inline'))
56481 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
56483 .text(t('background.imagery_source_faq'));
56485 var overlayList = content
56487 .attr('class', 'layer-list');
56489 var controls = content
56491 .attr('class', 'controls-list');
56494 /* minimap toggle */
56496 var minimapLabel = controls
56500 .title(uiTooltipHtml(t('background.minimap.tooltip'), '/'))
56505 .classed('minimap-toggle', true)
56507 .attr('type', 'checkbox')
56508 .on('change', function() {
56509 uiMapInMap.toggle();
56510 event.preventDefault();
56515 .text(t('background.minimap.description'));
56518 /* imagery offset controls */
56520 var adjustments = content
56522 .attr('class', 'adjustments');
56526 .text(t('background.fix_misalignment'))
56528 .classed('hide-toggle', true)
56529 .classed('expanded', false)
56530 .on('click', function() {
56531 if (event.button !== 0) return;
56532 var exp = select(this).classed('expanded');
56533 nudgeContainer.style('display', exp ? 'none' : 'block');
56534 select(this).classed('expanded', !exp);
56535 event.preventDefault();
56538 var nudgeContainer = adjustments
56540 .attr('class', 'nudge-container cf')
56541 .style('display', 'none');
56545 .attr('class', 'nudge-instructions')
56546 .text(t('background.offset'));
56548 var nudgeRect = nudgeContainer
56550 .attr('class', 'nudge-outer-rect')
56551 .on('mousedown', dragOffset);
56555 .attr('class', 'nudge-inner-rect')
56557 .on('change', inputOffset)
56558 .on('mousedown', function() {
56559 if (event.button !== 0) return;
56560 event.stopPropagation();
56565 .selectAll('button')
56566 .data(directions).enter()
56568 .attr('class', function(d) { return d[0] + ' nudge'; })
56569 .on('mousedown', function(d) {
56570 if (event.button !== 0) return;
56571 buttonOffset(d[1]);
56576 .attr('title', t('background.reset'))
56577 .attr('class', 'nudge-reset disabled')
56578 .on('click', resetOffset)
56580 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
56584 .on('move.background-update', lodash.debounce(update, 1000));
56586 context.background()
56587 .on('change.background-update', update);
56591 setOpacity(opacityDefault);
56593 var keybinding = d3keybinding('background')
56595 .on(uiCmd('⌘B'), quickSwitch)
56602 context.surface().on('mousedown.background-outside', hide);
56603 context.container().on('mousedown.background-outside', hide);
56609 function uiContributors(context) {
56610 var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
56613 wrap = select(null);
56616 function update() {
56618 entities = context.intersects(context.map().extent());
56620 entities.forEach(function(entity) {
56621 if (entity && entity.user) users[entity.user] = true;
56624 var u = Object.keys(users),
56625 subset = u.slice(0, u.length > limit ? limit - 1 : limit);
56628 .call(svgIcon('#icon-nearby', 'pre-text light'));
56630 var userList = select(document.createElement('span'));
56632 userList.selectAll()
56636 .attr('class', 'user-link')
56637 .attr('href', function(d) { return context.connection().userURL(d); })
56638 .attr('target', '_blank')
56639 .attr('tabindex', -1)
56642 if (u.length > limit) {
56643 var count = select(document.createElement('span'));
56646 .attr('target', '_blank')
56647 .attr('tabindex', -1)
56648 .attr('href', function() {
56649 return context.connection().changesetsURL(context.map().center(), context.map().zoom());
56651 .text(u.length - limit + 1);
56653 wrap.append('span')
56654 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
56657 wrap.append('span')
56658 .html(t('contributors.list', { users: userList.html() }));
56665 .style('opacity', 0);
56667 } else if (hidden) {
56670 .style('opacity', 1);
56675 return function(selection$$1) {
56676 wrap = selection$$1;
56679 context.connection().on('loaded.contributors', debouncedUpdate);
56680 context.map().on('move.contributors', debouncedUpdate);
56684 function uiFeatureInfo(context) {
56685 function update(selection$$1) {
56686 var features = context.features(),
56687 stats = features.stats(),
56689 hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
56692 return String(stats[k]) + ' ' + t('feature.' + k + '.description');
56696 selection$$1.html('');
56698 if (hiddenList.length) {
56699 var tooltipBehavior = tooltip()
56702 .title(function() {
56703 return uiTooltipHtml(hiddenList.join('<br/>'));
56706 var warning = selection$$1.append('a')
56708 .attr('tabindex', -1)
56709 .html(t('feature_info.hidden_warning', { count: count }))
56710 .call(tooltipBehavior)
56711 .on('click', function() {
56712 tooltipBehavior.hide(warning);
56713 // open map data panel?
56714 event.preventDefault();
56719 .classed('hide', !hiddenList.length);
56723 return function(selection$$1) {
56724 update(selection$$1);
56726 context.features().on('change.feature_info', function() {
56727 update(selection$$1);
56732 function uiFullScreen(context) {
56733 var element = context.container().node(),
56734 keybinding = d3keybinding('full-screen');
56738 function getFullScreenFn() {
56739 if (element.requestFullscreen) {
56740 return element.requestFullscreen;
56741 } else if (element.msRequestFullscreen) {
56742 return element.msRequestFullscreen;
56743 } else if (element.mozRequestFullScreen) {
56744 return element.mozRequestFullScreen;
56745 } else if (element.webkitRequestFullscreen) {
56746 return element.webkitRequestFullscreen;
56751 function getExitFullScreenFn() {
56752 if (document.exitFullscreen) {
56753 return document.exitFullscreen;
56754 } else if (document.msExitFullscreen) {
56755 return document.msExitFullscreen;
56756 } else if (document.mozCancelFullScreen) {
56757 return document.mozCancelFullScreen;
56758 } else if (document.webkitExitFullscreen) {
56759 return document.webkitExitFullscreen;
56764 function isFullScreen() {
56765 return document.fullscreenElement ||
56766 document.mozFullScreenElement ||
56767 document.webkitFullscreenElement ||
56768 document.msFullscreenElement;
56772 function isSupported() {
56773 return !!getFullScreenFn();
56777 function fullScreen() {
56778 event.preventDefault();
56779 if (!isFullScreen()) {
56780 // button.classed('active', true);
56781 getFullScreenFn().apply(element);
56783 // button.classed('active', false);
56784 getExitFullScreenFn().apply(document);
56789 return function() { // selection) {
56790 if (!isSupported())
56793 // button = selection.append('button')
56794 // .attr('title', t('full_screen'))
56795 // .attr('tabindex', -1)
56796 // .on('click', fullScreen)
56799 // button.append('span')
56800 // .attr('class', 'icon full-screen');
56803 .on('f11', fullScreen)
56804 .on(uiCmd('⌘⇧F'), fullScreen);
56811 function uiModal(selection$$1, blocking) {
56812 var keybinding = d3keybinding('modal');
56813 var previous = selection$$1.select('div.modal');
56814 var animate = previous.empty();
56816 previous.transition()
56818 .style('opacity', 0)
56821 var shaded = selection$$1
56823 .attr('class', 'shaded')
56824 .style('opacity', 0);
56826 shaded.close = function() {
56830 .style('opacity',0)
56836 .style('top','0px');
56844 .attr('class', 'modal fillL col6');
56847 shaded.on('click.remove-modal', function() {
56848 if (event.target === this) {
56853 modal.append('button')
56854 .attr('class', 'close')
56855 .on('click', shaded.close)
56856 .call(svgIcon('#icon-close'));
56859 .on('⌫', shaded.close)
56860 .on('⎋', shaded.close);
56868 .attr('class', 'content');
56871 shaded.transition().style('opacity', 1);
56873 shaded.style('opacity', 1);
56880 function uiLoading(context) {
56886 var loading = function(selection) {
56887 modalSelection = uiModal(selection, blocking);
56889 var loadertext = modalSelection.select('.content')
56890 .classed('loading-modal', true)
56892 .attr('class', 'modal-section fillL');
56896 .attr('class', 'loader')
56897 .attr('src', context.imagePath('loader-white.gif'));
56903 modalSelection.select('button.close')
56904 .attr('class', 'hide');
56910 loading.message = function(_) {
56911 if (!arguments.length) return message;
56917 loading.blocking = function(_) {
56918 if (!arguments.length) return blocking;
56924 loading.close = function() {
56925 modalSelection.remove();
56932 function uiGeolocate(context) {
56933 var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
56934 locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
56939 if (context.inIntro()) return;
56940 context.enter(modeBrowse(context));
56941 context.container().call(locating);
56942 navigator.geolocation.getCurrentPosition(success, error, geoOptions);
56944 // This timeout ensures that we still call finish() even if
56945 // the user declines to share their location in Firefox
56946 timeoutId = setTimeout(finish, 10000 /* 10sec */ );
56950 function success(position) {
56951 var map = context.map(),
56952 extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
56953 .padByMeters(position.coords.accuracy);
56955 map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
56965 function finish() {
56966 locating.close(); // unblock ui
56967 if (timeoutId) { clearTimeout(timeoutId); }
56968 timeoutId = undefined;
56972 return function(selection) {
56973 if (!navigator.geolocation) return;
56977 .attr('tabindex', -1)
56978 .attr('title', t('geolocate.title'))
56979 .on('click', click)
56980 .call(svgIcon('#icon-geolocate', 'light'))
56982 .placement((textDirection === 'rtl') ? 'right' : 'left'));
56986 var marked = createCommonjsModule(function (module, exports) {
56988 * marked - a markdown parser
56989 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
56990 * https://github.com/chjj/marked
56996 * Block-Level Grammar
57001 code: /^( {4}[^\n]+\n*)+/,
57003 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
57004 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
57006 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
57007 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
57008 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
57009 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
57010 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
57012 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
57016 block.bullet = /(?:[*+-]|\d+\.)/;
57017 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
57018 block.item = replace(block.item, 'gm')
57019 (/bull/g, block.bullet)
57022 block.list = replace(block.list)
57023 (/bull/g, block.bullet)
57024 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
57025 ('def', '\\n+(?=' + block.def.source + ')')
57028 block.blockquote = replace(block.blockquote)
57032 block._tag = '(?!(?:'
57033 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
57034 + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
57035 + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
57037 block.html = replace(block.html)
57038 ('comment', /<!--[\s\S]*?-->/)
57039 ('closed', /<(tag)[\s\S]+?<\/\1>/)
57040 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
57041 (/tag/g, block._tag)
57044 block.paragraph = replace(block.paragraph)
57046 ('heading', block.heading)
57047 ('lheading', block.lheading)
57048 ('blockquote', block.blockquote)
57049 ('tag', '<' + block._tag)
57054 * Normal Block Grammar
57057 block.normal = merge({}, block);
57060 * GFM Block Grammar
57063 block.gfm = merge({}, block.normal, {
57064 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
57066 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
57069 block.gfm.paragraph = replace(block.paragraph)
57071 + block.gfm.fences.source.replace('\\1', '\\2') + '|'
57072 + block.list.source.replace('\\1', '\\3') + '|')
57076 * GFM + Tables Block Grammar
57079 block.tables = merge({}, block.gfm, {
57080 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
57081 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
57088 function Lexer(options) {
57090 this.tokens.links = {};
57091 this.options = options || marked.defaults;
57092 this.rules = block.normal;
57094 if (this.options.gfm) {
57095 if (this.options.tables) {
57096 this.rules = block.tables;
57098 this.rules = block.gfm;
57104 * Expose Block Rules
57107 Lexer.rules = block;
57110 * Static Lex Method
57113 Lexer.lex = function(src, options) {
57114 var lexer = new Lexer(options);
57115 return lexer.lex(src);
57122 Lexer.prototype.lex = function(src) {
57124 .replace(/\r\n|\r/g, '\n')
57125 .replace(/\t/g, ' ')
57126 .replace(/\u00a0/g, ' ')
57127 .replace(/\u2424/g, '\n');
57129 return this.token(src, true);
57136 Lexer.prototype.token = function(src, top, bq) {
57137 var src = src.replace(/^ +$/gm, '')
57150 if (cap = this.rules.newline.exec(src)) {
57151 src = src.substring(cap[0].length);
57152 if (cap[0].length > 1) {
57160 if (cap = this.rules.code.exec(src)) {
57161 src = src.substring(cap[0].length);
57162 cap = cap[0].replace(/^ {4}/gm, '');
57165 text: !this.options.pedantic
57166 ? cap.replace(/\n+$/, '')
57173 if (cap = this.rules.fences.exec(src)) {
57174 src = src.substring(cap[0].length);
57184 if (cap = this.rules.heading.exec(src)) {
57185 src = src.substring(cap[0].length);
57188 depth: cap[1].length,
57194 // table no leading pipe (gfm)
57195 if (top && (cap = this.rules.nptable.exec(src))) {
57196 src = src.substring(cap[0].length);
57200 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
57201 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
57202 cells: cap[3].replace(/\n$/, '').split('\n')
57205 for (i = 0; i < item.align.length; i++) {
57206 if (/^ *-+: *$/.test(item.align[i])) {
57207 item.align[i] = 'right';
57208 } else if (/^ *:-+: *$/.test(item.align[i])) {
57209 item.align[i] = 'center';
57210 } else if (/^ *:-+ *$/.test(item.align[i])) {
57211 item.align[i] = 'left';
57213 item.align[i] = null;
57217 for (i = 0; i < item.cells.length; i++) {
57218 item.cells[i] = item.cells[i].split(/ *\| */);
57221 this.tokens.push(item);
57227 if (cap = this.rules.lheading.exec(src)) {
57228 src = src.substring(cap[0].length);
57231 depth: cap[2] === '=' ? 1 : 2,
57238 if (cap = this.rules.hr.exec(src)) {
57239 src = src.substring(cap[0].length);
57247 if (cap = this.rules.blockquote.exec(src)) {
57248 src = src.substring(cap[0].length);
57251 type: 'blockquote_start'
57254 cap = cap[0].replace(/^ *> ?/gm, '');
57256 // Pass `top` to keep the current
57257 // "toplevel" state. This is exactly
57258 // how markdown.pl works.
57259 this.token(cap, top, true);
57262 type: 'blockquote_end'
57269 if (cap = this.rules.list.exec(src)) {
57270 src = src.substring(cap[0].length);
57274 type: 'list_start',
57275 ordered: bull.length > 1
57278 // Get each top-level item.
57279 cap = cap[0].match(this.rules.item);
57285 for (; i < l; i++) {
57288 // Remove the list item's bullet
57289 // so it is seen as the next token.
57290 space = item.length;
57291 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
57293 // Outdent whatever the
57294 // list item contains. Hacky.
57295 if (~item.indexOf('\n ')) {
57296 space -= item.length;
57297 item = !this.options.pedantic
57298 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
57299 : item.replace(/^ {1,4}/gm, '');
57302 // Determine whether the next list item belongs here.
57303 // Backpedal if it does not belong in this list.
57304 if (this.options.smartLists && i !== l - 1) {
57305 b = block.bullet.exec(cap[i + 1])[0];
57306 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
57307 src = cap.slice(i + 1).join('\n') + src;
57312 // Determine whether item is loose or not.
57313 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
57314 // for discount behavior.
57315 loose = next || /\n\n(?!\s*$)/.test(item);
57317 next = item.charAt(item.length - 1) === '\n';
57318 if (!loose) loose = next;
57323 ? 'loose_item_start'
57324 : 'list_item_start'
57328 this.token(item, false, bq);
57331 type: 'list_item_end'
57343 if (cap = this.rules.html.exec(src)) {
57344 src = src.substring(cap[0].length);
57346 type: this.options.sanitize
57349 pre: !this.options.sanitizer
57350 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
57357 if ((!bq && top) && (cap = this.rules.def.exec(src))) {
57358 src = src.substring(cap[0].length);
57359 this.tokens.links[cap[1].toLowerCase()] = {
57367 if (top && (cap = this.rules.table.exec(src))) {
57368 src = src.substring(cap[0].length);
57372 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
57373 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
57374 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
57377 for (i = 0; i < item.align.length; i++) {
57378 if (/^ *-+: *$/.test(item.align[i])) {
57379 item.align[i] = 'right';
57380 } else if (/^ *:-+: *$/.test(item.align[i])) {
57381 item.align[i] = 'center';
57382 } else if (/^ *:-+ *$/.test(item.align[i])) {
57383 item.align[i] = 'left';
57385 item.align[i] = null;
57389 for (i = 0; i < item.cells.length; i++) {
57390 item.cells[i] = item.cells[i]
57391 .replace(/^ *\| *| *\| *$/g, '')
57395 this.tokens.push(item);
57400 // top-level paragraph
57401 if (top && (cap = this.rules.paragraph.exec(src))) {
57402 src = src.substring(cap[0].length);
57405 text: cap[1].charAt(cap[1].length - 1) === '\n'
57406 ? cap[1].slice(0, -1)
57413 if (cap = this.rules.text.exec(src)) {
57414 // Top-level should never reach here.
57415 src = src.substring(cap[0].length);
57425 Error('Infinite loop on byte: ' + src.charCodeAt(0));
57429 return this.tokens;
57433 * Inline-Level Grammar
57437 escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
57438 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
57440 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
57441 link: /^!?\[(inside)\]\(href\)/,
57442 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
57443 nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
57444 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
57445 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
57446 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
57447 br: /^ {2,}\n(?!\s*$)/,
57449 text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
57452 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
57453 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
57455 inline.link = replace(inline.link)
57456 ('inside', inline._inside)
57457 ('href', inline._href)
57460 inline.reflink = replace(inline.reflink)
57461 ('inside', inline._inside)
57465 * Normal Inline Grammar
57468 inline.normal = merge({}, inline);
57471 * Pedantic Inline Grammar
57474 inline.pedantic = merge({}, inline.normal, {
57475 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
57476 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
57480 * GFM Inline Grammar
57483 inline.gfm = merge({}, inline.normal, {
57484 escape: replace(inline.escape)('])', '~|])')(),
57485 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
57486 del: /^~~(?=\S)([\s\S]*?\S)~~/,
57487 text: replace(inline.text)
57489 ('|', '|https?://|')
57494 * GFM + Line Breaks Inline Grammar
57497 inline.breaks = merge({}, inline.gfm, {
57498 br: replace(inline.br)('{2,}', '*')(),
57499 text: replace(inline.gfm.text)('{2,}', '*')()
57503 * Inline Lexer & Compiler
57506 function InlineLexer(links, options) {
57507 this.options = options || marked.defaults;
57508 this.links = links;
57509 this.rules = inline.normal;
57510 this.renderer = this.options.renderer || new Renderer;
57511 this.renderer.options = this.options;
57515 Error('Tokens array requires a `links` property.');
57518 if (this.options.gfm) {
57519 if (this.options.breaks) {
57520 this.rules = inline.breaks;
57522 this.rules = inline.gfm;
57524 } else if (this.options.pedantic) {
57525 this.rules = inline.pedantic;
57530 * Expose Inline Rules
57533 InlineLexer.rules = inline;
57536 * Static Lexing/Compiling Method
57539 InlineLexer.output = function(src, links, options) {
57540 var inline = new InlineLexer(links, options);
57541 return inline.output(src);
57548 InlineLexer.prototype.output = function(src) {
57557 if (cap = this.rules.escape.exec(src)) {
57558 src = src.substring(cap[0].length);
57564 if (cap = this.rules.autolink.exec(src)) {
57565 src = src.substring(cap[0].length);
57566 if (cap[2] === '@') {
57567 text = cap[1].charAt(6) === ':'
57568 ? this.mangle(cap[1].substring(7))
57569 : this.mangle(cap[1]);
57570 href = this.mangle('mailto:') + text;
57572 text = escape(cap[1]);
57575 out += this.renderer.link(href, null, text);
57580 if (!this.inLink && (cap = this.rules.url.exec(src))) {
57581 src = src.substring(cap[0].length);
57582 text = escape(cap[1]);
57584 out += this.renderer.link(href, null, text);
57589 if (cap = this.rules.tag.exec(src)) {
57590 if (!this.inLink && /^<a /i.test(cap[0])) {
57591 this.inLink = true;
57592 } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
57593 this.inLink = false;
57595 src = src.substring(cap[0].length);
57596 out += this.options.sanitize
57597 ? this.options.sanitizer
57598 ? this.options.sanitizer(cap[0])
57605 if (cap = this.rules.link.exec(src)) {
57606 src = src.substring(cap[0].length);
57607 this.inLink = true;
57608 out += this.outputLink(cap, {
57612 this.inLink = false;
57617 if ((cap = this.rules.reflink.exec(src))
57618 || (cap = this.rules.nolink.exec(src))) {
57619 src = src.substring(cap[0].length);
57620 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
57621 link = this.links[link.toLowerCase()];
57622 if (!link || !link.href) {
57623 out += cap[0].charAt(0);
57624 src = cap[0].substring(1) + src;
57627 this.inLink = true;
57628 out += this.outputLink(cap, link);
57629 this.inLink = false;
57634 if (cap = this.rules.strong.exec(src)) {
57635 src = src.substring(cap[0].length);
57636 out += this.renderer.strong(this.output(cap[2] || cap[1]));
57641 if (cap = this.rules.em.exec(src)) {
57642 src = src.substring(cap[0].length);
57643 out += this.renderer.em(this.output(cap[2] || cap[1]));
57648 if (cap = this.rules.code.exec(src)) {
57649 src = src.substring(cap[0].length);
57650 out += this.renderer.codespan(escape(cap[2], true));
57655 if (cap = this.rules.br.exec(src)) {
57656 src = src.substring(cap[0].length);
57657 out += this.renderer.br();
57662 if (cap = this.rules.del.exec(src)) {
57663 src = src.substring(cap[0].length);
57664 out += this.renderer.del(this.output(cap[1]));
57669 if (cap = this.rules.text.exec(src)) {
57670 src = src.substring(cap[0].length);
57671 out += this.renderer.text(escape(this.smartypants(cap[0])));
57677 Error('Infinite loop on byte: ' + src.charCodeAt(0));
57688 InlineLexer.prototype.outputLink = function(cap, link) {
57689 var href = escape(link.href)
57690 , title = link.title ? escape(link.title) : null;
57692 return cap[0].charAt(0) !== '!'
57693 ? this.renderer.link(href, title, this.output(cap[1]))
57694 : this.renderer.image(href, title, escape(cap[1]));
57698 * Smartypants Transformations
57701 InlineLexer.prototype.smartypants = function(text) {
57702 if (!this.options.smartypants) return text;
57705 .replace(/---/g, '\u2014')
57707 .replace(/--/g, '\u2013')
57709 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
57710 // closing singles & apostrophes
57711 .replace(/'/g, '\u2019')
57713 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
57715 .replace(/"/g, '\u201d')
57717 .replace(/\.{3}/g, '\u2026');
57724 InlineLexer.prototype.mangle = function(text) {
57725 if (!this.options.mangle) return text;
57731 for (; i < l; i++) {
57732 ch = text.charCodeAt(i);
57733 if (Math.random() > 0.5) {
57734 ch = 'x' + ch.toString(16);
57736 out += '&#' + ch + ';';
57746 function Renderer(options) {
57747 this.options = options || {};
57750 Renderer.prototype.code = function(code, lang, escaped) {
57751 if (this.options.highlight) {
57752 var out = this.options.highlight(code, lang);
57753 if (out != null && out !== code) {
57760 return '<pre><code>'
57761 + (escaped ? code : escape(code, true))
57762 + '\n</code></pre>';
57765 return '<pre><code class="'
57766 + this.options.langPrefix
57767 + escape(lang, true)
57769 + (escaped ? code : escape(code, true))
57770 + '\n</code></pre>\n';
57773 Renderer.prototype.blockquote = function(quote) {
57774 return '<blockquote>\n' + quote + '</blockquote>\n';
57777 Renderer.prototype.html = function(html) {
57781 Renderer.prototype.heading = function(text, level, raw) {
57785 + this.options.headerPrefix
57786 + raw.toLowerCase().replace(/[^\w]+/g, '-')
57794 Renderer.prototype.hr = function() {
57795 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
57798 Renderer.prototype.list = function(body, ordered) {
57799 var type = ordered ? 'ol' : 'ul';
57800 return '<' + type + '>\n' + body + '</' + type + '>\n';
57803 Renderer.prototype.listitem = function(text) {
57804 return '<li>' + text + '</li>\n';
57807 Renderer.prototype.paragraph = function(text) {
57808 return '<p>' + text + '</p>\n';
57811 Renderer.prototype.table = function(header, body) {
57822 Renderer.prototype.tablerow = function(content) {
57823 return '<tr>\n' + content + '</tr>\n';
57826 Renderer.prototype.tablecell = function(content, flags) {
57827 var type = flags.header ? 'th' : 'td';
57828 var tag = flags.align
57829 ? '<' + type + ' style="text-align:' + flags.align + '">'
57830 : '<' + type + '>';
57831 return tag + content + '</' + type + '>\n';
57834 // span level renderer
57835 Renderer.prototype.strong = function(text) {
57836 return '<strong>' + text + '</strong>';
57839 Renderer.prototype.em = function(text) {
57840 return '<em>' + text + '</em>';
57843 Renderer.prototype.codespan = function(text) {
57844 return '<code>' + text + '</code>';
57847 Renderer.prototype.br = function() {
57848 return this.options.xhtml ? '<br/>' : '<br>';
57851 Renderer.prototype.del = function(text) {
57852 return '<del>' + text + '</del>';
57855 Renderer.prototype.link = function(href, title, text) {
57856 if (this.options.sanitize) {
57858 var prot = decodeURIComponent(unescape(href))
57859 .replace(/[^\w:]/g, '')
57864 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
57868 var out = '<a href="' + href + '"';
57870 out += ' title="' + title + '"';
57872 out += '>' + text + '</a>';
57876 Renderer.prototype.image = function(href, title, text) {
57877 var out = '<img src="' + href + '" alt="' + text + '"';
57879 out += ' title="' + title + '"';
57881 out += this.options.xhtml ? '/>' : '>';
57885 Renderer.prototype.text = function(text) {
57890 * Parsing & Compiling
57893 function Parser(options) {
57896 this.options = options || marked.defaults;
57897 this.options.renderer = this.options.renderer || new Renderer;
57898 this.renderer = this.options.renderer;
57899 this.renderer.options = this.options;
57903 * Static Parse Method
57906 Parser.parse = function(src, options, renderer) {
57907 var parser = new Parser(options, renderer);
57908 return parser.parse(src);
57915 Parser.prototype.parse = function(src) {
57916 this.inline = new InlineLexer(src.links, this.options, this.renderer);
57917 this.tokens = src.reverse();
57920 while (this.next()) {
57931 Parser.prototype.next = function() {
57932 return this.token = this.tokens.pop();
57936 * Preview Next Token
57939 Parser.prototype.peek = function() {
57940 return this.tokens[this.tokens.length - 1] || 0;
57944 * Parse Text Tokens
57947 Parser.prototype.parseText = function() {
57948 var body = this.token.text;
57950 while (this.peek().type === 'text') {
57951 body += '\n' + this.next().text;
57954 return this.inline.output(body);
57958 * Parse Current Token
57961 Parser.prototype.tok = function() {
57962 switch (this.token.type) {
57967 return this.renderer.hr();
57970 return this.renderer.heading(
57971 this.inline.output(this.token.text),
57976 return this.renderer.code(this.token.text,
57978 this.token.escaped);
57991 for (i = 0; i < this.token.header.length; i++) {
57992 flags = { header: true, align: this.token.align[i] };
57993 cell += this.renderer.tablecell(
57994 this.inline.output(this.token.header[i]),
57995 { header: true, align: this.token.align[i] }
57998 header += this.renderer.tablerow(cell);
58000 for (i = 0; i < this.token.cells.length; i++) {
58001 row = this.token.cells[i];
58004 for (j = 0; j < row.length; j++) {
58005 cell += this.renderer.tablecell(
58006 this.inline.output(row[j]),
58007 { header: false, align: this.token.align[j] }
58011 body += this.renderer.tablerow(cell);
58013 return this.renderer.table(header, body);
58015 case 'blockquote_start': {
58018 while (this.next().type !== 'blockquote_end') {
58019 body += this.tok();
58022 return this.renderer.blockquote(body);
58024 case 'list_start': {
58026 , ordered = this.token.ordered;
58028 while (this.next().type !== 'list_end') {
58029 body += this.tok();
58032 return this.renderer.list(body, ordered);
58034 case 'list_item_start': {
58037 while (this.next().type !== 'list_item_end') {
58038 body += this.token.type === 'text'
58043 return this.renderer.listitem(body);
58045 case 'loose_item_start': {
58048 while (this.next().type !== 'list_item_end') {
58049 body += this.tok();
58052 return this.renderer.listitem(body);
58055 var html = !this.token.pre && !this.options.pedantic
58056 ? this.inline.output(this.token.text)
58058 return this.renderer.html(html);
58060 case 'paragraph': {
58061 return this.renderer.paragraph(this.inline.output(this.token.text));
58064 return this.renderer.paragraph(this.parseText());
58073 function escape(html, encode) {
58075 .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
58076 .replace(/</g, '<')
58077 .replace(/>/g, '>')
58078 .replace(/"/g, '"')
58079 .replace(/'/g, ''');
58082 function unescape(html) {
58083 // explicitly match decimal, hex, and named HTML entities
58084 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
58085 n = n.toLowerCase();
58086 if (n === 'colon') return ':';
58087 if (n.charAt(0) === '#') {
58088 return n.charAt(1) === 'x'
58089 ? String.fromCharCode(parseInt(n.substring(2), 16))
58090 : String.fromCharCode(+n.substring(1));
58096 function replace(regex, opt) {
58097 regex = regex.source;
58099 return function self(name, val) {
58100 if (!name) return new RegExp(regex, opt);
58101 val = val.source || val;
58102 val = val.replace(/(^|[^\[])\^/g, '$1');
58103 regex = regex.replace(name, val);
58111 function merge(obj) {
58116 for (; i < arguments.length; i++) {
58117 target = arguments[i];
58118 for (key in target) {
58119 if (Object.prototype.hasOwnProperty.call(target, key)) {
58120 obj[key] = target[key];
58133 function marked(src, opt, callback) {
58134 if (callback || typeof opt === 'function') {
58140 opt = merge({}, marked.defaults, opt || {});
58142 var highlight = opt.highlight
58148 tokens = Lexer.lex(src, opt);
58150 return callback(e);
58153 pending = tokens.length;
58155 var done = function(err) {
58157 opt.highlight = highlight;
58158 return callback(err);
58164 out = Parser.parse(tokens, opt);
58169 opt.highlight = highlight;
58173 : callback(null, out);
58176 if (!highlight || highlight.length < 3) {
58180 delete opt.highlight;
58182 if (!pending) return done();
58184 for (; i < tokens.length; i++) {
58186 if (token.type !== 'code') {
58187 return --pending || done();
58189 return highlight(token.text, token.lang, function(err, code) {
58190 if (err) return done(err);
58191 if (code == null || code === token.text) {
58192 return --pending || done();
58195 token.escaped = true;
58196 --pending || done();
58204 if (opt) opt = merge({}, marked.defaults, opt);
58205 return Parser.parse(Lexer.lex(src, opt), opt);
58207 e.message += '\nPlease report this to https://github.com/chjj/marked.';
58208 if ((opt || marked.defaults).silent) {
58209 return '<p>An error occured:</p><pre>'
58210 + escape(e.message + '', true)
58222 marked.setOptions = function(opt) {
58223 merge(marked.defaults, opt);
58227 marked.defaults = {
58238 langPrefix: 'lang-',
58239 smartypants: false,
58241 renderer: new Renderer,
58249 marked.Parser = Parser;
58250 marked.parser = Parser.parse;
58252 marked.Renderer = Renderer;
58254 marked.Lexer = Lexer;
58255 marked.lexer = Lexer.lex;
58257 marked.InlineLexer = InlineLexer;
58258 marked.inlineLexer = InlineLexer.output;
58260 marked.parse = marked;
58263 module.exports = marked;
58266 }).call(function() {
58267 return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
58271 function pointBox(loc, context) {
58272 var rect = context.surfaceRect();
58273 var point = context.curtainProjection(loc);
58275 left: point[0] + rect.left - 40,
58276 top: point[1] + rect.top - 60,
58283 function pad$1(locOrBox, padding, context) {
58285 if (locOrBox instanceof Array) {
58286 var rect = context.surfaceRect();
58287 var point = context.curtainProjection(locOrBox);
58289 left: point[0] + rect.left,
58290 top: point[1] + rect.top
58297 left: box.left - padding,
58298 top: box.top - padding,
58299 width: (box.width || 0) + 2 * padding,
58300 height: (box.width || 0) + 2 * padding
58305 function icon(name, svgklass) {
58306 return '<svg class="icon ' + (svgklass || '') + '">' +
58307 '<use xlink:href="' + name + '"></use></svg>';
58311 function slugify(text$$1) {
58312 return text$$1.toString().toLowerCase()
58313 .replace(/\s+/g, '-') // Replace spaces with -
58314 .replace(/[^\w\-]+/g, '') // Remove all non-word chars
58315 .replace(/\-\-+/g, '-') // Replace multiple - with single -
58316 .replace(/^-+/, '') // Trim - from start of text
58317 .replace(/-+$/, ''); // Trim - from end of text
58321 // console warning for missing walkthrough names
58322 var missingStrings = {};
58323 function checkKey(key, text$$1) {
58324 if (t(key, { default: undefined}) === undefined) {
58325 if (missingStrings.hasOwnProperty(key)) return; // warn once
58326 missingStrings[key] = text$$1;
58327 var missing = key + ': ' + text$$1;
58328 if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line
58333 function localize(obj) {
58336 // Assign name if entity has one..
58337 var name = obj.tags && obj.tags.name;
58339 key = 'intro.graph.name.' + slugify(name);
58340 obj.tags.name = t(key, { default: name });
58341 checkKey(key, name);
58344 // Assign street name if entity has one..
58345 var street = obj.tags && obj.tags['addr:street'];
58347 key = 'intro.graph.name.' + slugify(street);
58348 obj.tags['addr:street'] = t(key, { default: street });
58349 checkKey(key, street);
58351 // Add address details common across walkthrough..
58353 'block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood',
58354 'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb'
58356 addrTags.forEach(function(k) {
58357 var key = 'intro.graph.' + k,
58359 val = obj.tags && obj.tags[tag],
58360 str = t(key, { default: val });
58363 if (str.match(/^<.*>$/) !== null) {
58364 delete obj.tags[tag];
58366 obj.tags[tag] = str;
58376 // Used to detect squareness.. some duplicataion of code from actionOrthogonalize.
58377 function isMostlySquare(points) {
58378 // note: uses 15 here instead of the 12 from actionOrthogonalize because
58379 // actionOrthogonalize can actually straighten some larger angles as it iterates
58380 var threshold = 15, // degrees within right or straight
58381 lowerBound = Math.cos((90 - threshold) * Math.PI / 180), // near right
58382 upperBound = Math.cos(threshold * Math.PI / 180), // near straight
58385 for (var i = 0; i < points.length; i++) {
58386 mag = Math.abs(normalizedDotProduct(i, points));
58387 if (mag > lowerBound && mag < upperBound) {
58395 function normalizedDotProduct(i, points) {
58396 var a = points[(i - 1 + points.length) % points.length],
58398 c = points[(i + 1) % points.length],
58399 p = subtractPoints(a, b),
58400 q = subtractPoints(c, b);
58402 p = normalizePoint(p);
58403 q = normalizePoint(q);
58405 return p[0] * q[0] + p[1] * q[1];
58408 function subtractPoints(a, b) {
58409 return [a[0] - b[0], a[1] - b[1]];
58412 function normalizePoint(point) {
58413 var vector = [0, 0];
58414 var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
58415 if (length !== 0) {
58416 vector[0] = point[0] / length;
58417 vector[1] = point[1] / length;
58425 function selectMenuItem(operation) {
58426 var selector$$1 = '.edit-menu .edit-menu-item-' + operation +
58427 ', .radial-menu .radial-menu-item-' + operation;
58428 return select(selector$$1);
58432 function transitionTime(point1, point2) {
58433 var distance = geoSphericalDistance(point1, point2);
58434 if (distance === 0)
58436 else if (distance < 80)
58442 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"}}};
58444 // toggles the visibility of ui elements, using a combination of the
58445 // hide class, which sets display=none, and a d3 transition for opacity.
58446 // this will cause blinking when called repeatedly, so check that the
58447 // value actually changes between calls.
58448 function uiToggle(show, callback) {
58449 return function(selection$$1) {
58451 .style('opacity', show ? 0 : 1)
58452 .classed('hide', false)
58454 .style('opacity', show ? 1 : 0)
58455 .on('end', function() {
58457 .classed('hide', !show)
58458 .style('opacity', null);
58459 if (callback) callback.apply(this);
58464 // Tooltips and svg mask used to highlight certain features
58465 function uiCurtain() {
58467 var surface = select(null),
58468 tooltip = select(null),
58469 darkness = select(null);
58471 function curtain(selection$$1) {
58472 surface = selection$$1
58474 .attr('id', 'curtain')
58475 .style('z-index', 1000)
58476 .style('pointer-events', 'none')
58477 .style('position', 'absolute')
58481 darkness = surface.append('path')
58484 .attr('class', 'curtain-darkness');
58486 select(window).on('resize.curtain', resize);
58488 tooltip = selection$$1.append('div')
58489 .attr('class', 'tooltip')
58490 .style('z-index', 1002);
58494 .attr('class', 'tooltip-arrow');
58498 .attr('class', 'tooltip-inner');
58503 function resize() {
58505 .attr('width', window.innerWidth)
58506 .attr('height', window.innerHeight);
58507 curtain.cut(darkness.datum());
58513 * Reveal cuts the curtain to highlight the given box,
58514 * and shows a tooltip with instructions next to the box.
58516 * @param {String|ClientRect} [box] box used to cut the curtain
58517 * @param {String} [text] text for a tooltip
58518 * @param {Object} [options]
58519 * @param {string} [options.tooltipClass] optional class to add to the tooltip
58520 * @param {integer} [options.duration] transition time in milliseconds
58521 * @param {string} [options.buttonText] if set, create a button with this text label
58522 * @param {function} [options.buttonCallback] if set, the callback for the button
58523 * @param {String|ClientRect} [options.tooltipBox] box for tooltip position, if different from box for the curtain
58525 curtain.reveal = function(box, text$$1, options) {
58526 if (typeof box === 'string') {
58527 box = select(box).node();
58529 if (box && box.getBoundingClientRect) {
58530 box = copyBox(box.getBoundingClientRect());
58533 options = options || {};
58536 if (options.tooltipBox) {
58537 tooltipBox = options.tooltipBox;
58538 if (typeof tooltipBox === 'string') {
58539 tooltipBox = select(tooltipBox).node();
58541 if (tooltipBox && tooltipBox.getBoundingClientRect) {
58542 tooltipBox = copyBox(tooltipBox.getBoundingClientRect());
58548 if (tooltipBox && text$$1) {
58549 // pseudo markdown bold text for the instruction section..
58550 var parts = text$$1.split('**');
58551 var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
58553 html$$1 += '<span class="instruction">' + parts[1] + '</span>';
58556 html$$1 = html$$1.replace(/\*(.*?)\*/g, '<em>$1</em>'); // emphasis
58557 html$$1 = html$$1.replace(/\{br\}/g, '<br/><br/>'); // linebreak
58559 if (options.buttonText && options.buttonCallback) {
58560 html$$1 += '<div class="button-section">' +
58561 '<button href="#" class="button action col8">' + options.buttonText + '</button></div>';
58564 var classes = 'curtain-tooltip tooltip in ' + (options.tooltipClass || '');
58566 .classed(classes, true)
58567 .selectAll('.tooltip-inner')
58570 if (options.buttonText && options.buttonCallback) {
58571 var button = tooltip.selectAll('.button-section .button.action');
58573 .on('click', function() {
58574 event.preventDefault();
58575 options.buttonCallback();
58579 var tip = copyBox(tooltip.node().getBoundingClientRect()),
58580 w = window.innerWidth,
58581 h = window.innerHeight,
58582 tooltipWidth = 200,
58587 // hack: this will have bottom placement,
58588 // so need to reserve extra space for the tooltip illustration.
58589 if (options.tooltipClass === 'intro-mouse') {
58593 // trim box dimensions to just the portion that fits in the window..
58594 if (tooltipBox.top + tooltipBox.height > h) {
58595 tooltipBox.height -= (tooltipBox.top + tooltipBox.height - h);
58597 if (tooltipBox.left + tooltipBox.width > w) {
58598 tooltipBox.width -= (tooltipBox.left + tooltipBox.width - w);
58601 // determine tooltip placement..
58603 if (tooltipBox.top + tooltipBox.height < 100) {
58604 // tooltip below box..
58607 tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
58608 tooltipBox.top + tooltipBox.height
58611 } else if (tooltipBox.top > h - 140) {
58612 // tooltip above box..
58615 tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
58616 tooltipBox.top - tip.height
58620 // tooltip to the side of the tooltipBox..
58621 var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2;
58623 if (textDirection === 'rtl') {
58624 if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) {
58626 pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
58630 pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
58634 if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
58636 pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
58640 pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
58645 if (options.duration !== 0 || !tooltip.classed(side)) {
58646 tooltip.call(uiToggle(true));
58650 .style('top', pos[1] + 'px')
58651 .style('left', pos[0] + 'px')
58652 .attr('class', classes + ' ' + side);
58655 // shift tooltip-inner if it is very close to the top or bottom edge
58656 // (doesn't affect the placement of the tooltip-arrow)
58658 if (side === 'left' || side === 'right') {
58660 shiftY = 60 - pos[1];
58662 else if (pos[1] + tip.height > h - 100) {
58663 shiftY = h - pos[1] - tip.height - 100;
58666 tooltip.selectAll('.tooltip-inner')
58667 .style('top', shiftY + 'px');
58671 .classed('in', false)
58672 .call(uiToggle(false));
58675 curtain.cut(box, options.duration);
58681 curtain.cut = function(datum, duration) {
58682 darkness.datum(datum)
58686 if (duration === 0) {
58687 selection$$1 = darkness;
58689 selection$$1 = darkness
58691 .duration(duration || 600)
58696 .attr('d', function(d) {
58697 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
58698 window.innerWidth + ',' + window.innerHeight + 'L' +
58699 window.innerWidth + ',0 Z';
58701 if (!d) return string;
58702 return string + 'M' +
58703 d.left + ',' + d.top + 'L' +
58704 d.left + ',' + (d.top + d.height) + 'L' +
58705 (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
58706 (d.left + d.width) + ',' + (d.top) + 'Z';
58712 curtain.remove = function() {
58715 select(window).on('resize.curtain', null);
58719 // ClientRects are immutable, so copy them to an object,
58720 // in case we need to trim the height/width.
58721 function copyBox(src) {
58725 bottom: src.bottom,
58736 function uiIntroWelcome(context, reveal) {
58737 var dispatch$$1 = dispatch('done'),
58738 listener = clickListener();
58741 title: 'intro.welcome.title'
58745 function welcome() {
58746 context.map().centerZoom([-85.63591, 41.94285], 19);
58747 reveal('.intro-nav-wrap .chapter-welcome',
58748 t('intro.welcome.welcome'),
58749 { buttonText: t('intro.ok'), buttonCallback: practice }
58753 function practice() {
58754 reveal('.intro-nav-wrap .chapter-welcome',
58755 t('intro.welcome.practice'),
58756 { buttonText: t('intro.ok'), buttonCallback: words }
58761 reveal('.intro-nav-wrap .chapter-welcome',
58762 t('intro.welcome.words'),
58763 { buttonText: t('intro.ok'), buttonCallback: mouse$$1 }
58768 function mouse$$1() {
58769 reveal('.intro-nav-wrap .chapter-welcome',
58770 t('intro.welcome.mouse'),
58771 { buttonText: t('intro.ok'), buttonCallback: leftClick }
58776 function leftClick() {
58780 var tooltip = reveal('.intro-nav-wrap .chapter-welcome',
58781 t('intro.welcome.leftclick', { num: times }),
58782 { tooltipClass: 'intro-mouse' }
58785 tooltip.selectAll('.tooltip-inner')
58786 .insert('svg', 'span')
58787 .attr('class', 'tooltip-illustration')
58789 .attr('xlink:href', '#walkthrough-mouse');
58793 .attr('class', 'counter');
58795 tooltip.call(listener);
58797 listener.on('click', function(which) {
58798 if (which === 'left') {
58799 select('.curtain-tooltip.intro-mouse .counter')
58800 .text(String(++counter));
58802 if (counter === times) {
58803 window.setTimeout(function() { continueTo(rightClick); }, 1000);
58808 function continueTo(nextStep) {
58809 listener.on('click', null);
58810 tooltip.call(listener.off);
58811 tooltip.select('.counter').remove();
58817 function rightClick() {
58821 var tooltip = reveal('.intro-nav-wrap .chapter-welcome',
58822 t('intro.welcome.rightclick', { num: times }),
58823 { tooltipClass: 'intro-mouse' }
58826 tooltip.selectAll('.tooltip-inner')
58827 .insert('svg', 'span')
58828 .attr('class', 'tooltip-illustration')
58830 .attr('xlink:href', '#walkthrough-mouse');
58834 .attr('class', 'counter');
58836 tooltip.call(listener);
58838 listener.on('click', function(which) {
58839 if (which === 'right') {
58840 select('.curtain-tooltip.intro-mouse .counter')
58841 .text(String(++counter));
58843 if (counter === times) {
58844 window.setTimeout(function() { continueTo(chapters); }, 1000);
58849 function continueTo(nextStep) {
58850 listener.on('click', null);
58851 tooltip.call(listener.off);
58852 tooltip.select('.counter').remove();
58858 function chapters() {
58859 dispatch$$1.call('done');
58860 reveal('.intro-nav-wrap .chapter-navigation',
58861 t('intro.welcome.chapters', { next: t('intro.navigation.title') })
58866 chapter.enter = function() {
58871 chapter.exit = function() {
58876 chapter.restart = function() {
58882 return utilRebind(chapter, dispatch$$1, 'on');
58887 function clickListener() {
58888 var dispatch$$1 = dispatch('click'),
58890 tooltip = select(null),
58893 // `down` keeps track of which buttons/keys are down.
58894 // Setting a property in `down` happens immediately.
58895 // Unsetting a property in `down` is delayed because
58896 // on Windows a contextmenu event happens after keyup/mouseup
58898 function keydown() {
58899 if (event.keyCode === 93) { // context menu
58900 event.preventDefault();
58901 event.stopPropagation();
58902 down.menu = event.timeStamp;
58903 tooltip.classed('rightclick', true);
58909 if (event.keyCode === 93) { // context menu
58910 event.preventDefault();
58911 event.stopPropagation();
58912 var endTime = event.timeStamp,
58913 startTime = down.menu || endTime,
58914 delay = (endTime - startTime < minTime) ? minTime : 0;
58916 window.setTimeout(function() {
58917 tooltip.classed('rightclick', false);
58918 down.menu = undefined; // delayed, for Windows
58921 dispatch$$1.call('click', this, 'right');
58926 function mousedown() {
58927 var button = event.button;
58928 if (button === 0 && !event.ctrlKey) {
58929 tooltip.classed('leftclick', true);
58930 } else if (button === 2) {
58931 tooltip.classed('rightclick', true);
58933 down[button] = event.timeStamp;
58937 function mouseup() {
58938 var button = event.button,
58939 endTime = event.timeStamp,
58940 startTime = down[button] || endTime,
58941 delay = (endTime - startTime < minTime) ? minTime : 0;
58943 if (button === 0 && !event.ctrlKey) {
58944 window.setTimeout(function() {
58945 tooltip.classed('leftclick', false);
58946 down[button] = undefined; // delayed, for Windows
58949 dispatch$$1.call('click', this, 'left');
58951 } else if (button === 2) {
58952 window.setTimeout(function() {
58953 tooltip.classed('rightclick', false);
58954 down[button] = undefined; // delayed, for Windows
58957 dispatch$$1.call('click', this, 'right');
58960 window.setTimeout(function() {
58961 down[button] = undefined; // delayed, for Windows
58967 function contextmenu() {
58968 event.preventDefault();
58969 event.stopPropagation();
58970 if (!down[2] && !down.menu) {
58971 tooltip.classed('rightclick', true);
58972 window.setTimeout(function() {
58973 tooltip.classed('rightclick', false);
58975 dispatch$$1.call('click', this, 'right');
58980 var behavior = function(selection$$1) {
58981 tooltip = selection$$1;
58985 .on('keydown.intro', keydown)
58986 .on('keyup.intro', keyup)
58987 .on('mousedown.intro', mousedown)
58988 .on('mouseup.intro', mouseup)
58989 .on('contextmenu.intro', contextmenu);
58993 behavior.off = function() {
58995 .on('keydown.intro', null)
58996 .on('keyup.intro', null)
58997 .on('mousedown.intro', null)
58998 .on('mouseup.intro', null)
58999 .on('contextmenu.intro', null);
59002 .classed('leftclick', false)
59003 .classed('rightclick', false);
59006 return utilRebind(behavior, dispatch$$1, 'on');
59009 function uiIntroNavigation(context, reveal) {
59010 var dispatch$$1 = dispatch('done'),
59013 townHall = [-85.63591, 41.94285],
59014 springStreetId = 'w397',
59015 springStreetEndId = 'n1834',
59016 springStreet = [-85.63582, 41.94255],
59017 onewayField = context.presets().field('oneway'),
59018 maxspeedField = context.presets().field('maxspeed');
59022 title: 'intro.navigation.title'
59026 function timeout$$1(f, t$$1) {
59027 timeouts.push(window.setTimeout(f, t$$1));
59031 function eventCancel() {
59032 event.stopPropagation();
59033 event.preventDefault();
59037 function isTownHallSelected() {
59038 var ids = context.selectedIDs();
59039 return ids.length === 1 && ids[0] === hallId;
59043 function dragMap() {
59044 context.enter(modeBrowse(context));
59045 context.history().reset('initial');
59047 var msec = transitionTime(townHall, context.map().center());
59048 if (msec) { reveal(null, null, { duration: 0 }); }
59049 context.map().zoom(19).centerEase(townHall, msec);
59051 timeout$$1(function() {
59052 var centerStart = context.map().center();
59054 reveal('#surface', t('intro.navigation.drag'));
59055 context.map().on('drawn.intro', function() {
59056 reveal('#surface', t('intro.navigation.drag'), { duration: 0 });
59059 context.map().on('move.intro', function() {
59060 var centerNow = context.map().center();
59061 if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) {
59062 context.map().on('move.intro', null);
59063 timeout$$1(function() { continueTo(zoomMap); }, 3000);
59069 function continueTo(nextStep) {
59070 context.map().on('move.intro drawn.intro', null);
59076 function zoomMap() {
59077 var zoomStart = context.map().zoom();
59080 t('intro.navigation.zoom', {
59081 plus: icon('#icon-plus', 'pre-text'),
59082 minus: icon('#icon-minus', 'pre-text')
59086 context.map().on('drawn.intro', function() {
59088 t('intro.navigation.zoom', {
59089 plus: icon('#icon-plus', 'pre-text'),
59090 minus: icon('#icon-minus', 'pre-text')
59091 }), { duration: 0 }
59095 context.map().on('move.intro', function() {
59096 if (context.map().zoom() !== zoomStart) {
59097 context.map().on('move.intro', null);
59098 timeout$$1(function() { continueTo(features); }, 3000);
59102 function continueTo(nextStep) {
59103 context.map().on('move.intro drawn.intro', null);
59109 function features() {
59110 var onClick = function() { continueTo(pointsLinesAreas); };
59112 reveal('#surface', t('intro.navigation.features'),
59113 { buttonText: t('intro.ok'), buttonCallback: onClick }
59116 context.map().on('drawn.intro', function() {
59117 reveal('#surface', t('intro.navigation.features'),
59118 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
59122 function continueTo(nextStep) {
59123 context.map().on('drawn.intro', null);
59128 function pointsLinesAreas() {
59129 var onClick = function() { continueTo(nodesWays); };
59131 reveal('#surface', t('intro.navigation.points_lines_areas'),
59132 { buttonText: t('intro.ok'), buttonCallback: onClick }
59135 context.map().on('drawn.intro', function() {
59136 reveal('#surface', t('intro.navigation.points_lines_areas'),
59137 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
59141 function continueTo(nextStep) {
59142 context.map().on('drawn.intro', null);
59147 function nodesWays() {
59148 var onClick = function() { continueTo(clickTownHall); };
59150 reveal('#surface', t('intro.navigation.nodes_ways'),
59151 { buttonText: t('intro.ok'), buttonCallback: onClick }
59154 context.map().on('drawn.intro', function() {
59155 reveal('#surface', t('intro.navigation.nodes_ways'),
59156 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
59160 function continueTo(nextStep) {
59161 context.map().on('drawn.intro', null);
59166 function clickTownHall() {
59167 context.enter(modeBrowse(context));
59168 context.history().reset('initial');
59170 reveal(null, null, { duration: 0 });
59171 context.map().zoomEase(19, 500);
59173 timeout$$1(function() {
59174 var entity = context.hasEntity(hallId);
59175 if (!entity) return;
59176 context.map().centerEase(entity.loc, 500);
59178 timeout$$1(function() {
59179 var entity = context.hasEntity(hallId);
59180 if (!entity) return;
59181 var box = pointBox(entity.loc, context);
59182 reveal(box, t('intro.navigation.click_townhall'));
59184 context.map().on('move.intro drawn.intro', function() {
59185 var entity = context.hasEntity(hallId);
59186 if (!entity) return;
59187 var box = pointBox(entity.loc, context);
59188 reveal(box, t('intro.navigation.click_townhall'), { duration: 0 });
59191 context.on('enter.intro', function() {
59192 if (isTownHallSelected()) continueTo(selectedTownHall);
59195 }, 550); // after centerEase
59197 }, 550); // after zoomEase
59199 context.history().on('change.intro', function() {
59200 if (!context.hasEntity(hallId)) {
59201 continueTo(clickTownHall);
59205 function continueTo(nextStep) {
59206 context.on('enter.intro', null);
59207 context.map().on('move.intro drawn.intro', null);
59208 context.history().on('change.intro', null);
59214 function selectedTownHall() {
59215 if (!isTownHallSelected()) return clickTownHall();
59217 var entity = context.hasEntity(hallId);
59218 if (!entity) return clickTownHall();
59220 var box = pointBox(entity.loc, context);
59221 var onClick = function() { continueTo(editorTownHall); };
59223 reveal(box, t('intro.navigation.selected_townhall'),
59224 { buttonText: t('intro.ok'), buttonCallback: onClick }
59227 context.map().on('move.intro drawn.intro', function() {
59228 var entity = context.hasEntity(hallId);
59229 if (!entity) return;
59230 var box = pointBox(entity.loc, context);
59231 reveal(box, t('intro.navigation.selected_townhall'),
59232 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
59236 context.history().on('change.intro', function() {
59237 if (!context.hasEntity(hallId)) {
59238 continueTo(clickTownHall);
59242 function continueTo(nextStep) {
59243 context.map().on('move.intro drawn.intro', null);
59244 context.history().on('change.intro', null);
59250 function editorTownHall() {
59251 if (!isTownHallSelected()) return clickTownHall();
59253 // disallow scrolling
59254 select('.inspector-wrap').on('wheel.intro', eventCancel);
59256 var onClick = function() { continueTo(presetTownHall); };
59258 reveal('.entity-editor-pane',
59259 t('intro.navigation.editor_townhall'),
59260 { buttonText: t('intro.ok'), buttonCallback: onClick }
59263 context.on('exit.intro', function() {
59264 continueTo(clickTownHall);
59267 context.history().on('change.intro', function() {
59268 if (!context.hasEntity(hallId)) {
59269 continueTo(clickTownHall);
59273 function continueTo(nextStep) {
59274 context.on('exit.intro', null);
59275 context.history().on('change.intro', null);
59276 select('.inspector-wrap').on('wheel.intro', null);
59282 function presetTownHall() {
59283 if (!isTownHallSelected()) return clickTownHall();
59285 // reset pane, in case user happened to change it..
59286 select('.inspector-wrap .panewrap').style('right', '0%');
59287 // disallow scrolling
59288 select('.inspector-wrap').on('wheel.intro', eventCancel);
59290 // preset match, in case the user happened to change it.
59291 var entity = context.entity(context.selectedIDs()[0]);
59292 var preset = context.presets().match(entity, context.graph());
59294 var onClick = function() { continueTo(fieldsTownHall); };
59296 context.on('exit.intro', function() {
59297 continueTo(clickTownHall);
59300 context.history().on('change.intro', function() {
59301 if (!context.hasEntity(hallId)) {
59302 continueTo(clickTownHall);
59306 reveal('.inspector-body .preset-list-item.inspector-inner',
59307 t('intro.navigation.preset_townhall', { preset: preset.name() }),
59308 { buttonText: t('intro.ok'), buttonCallback: onClick }
59311 function continueTo(nextStep) {
59312 context.on('exit.intro', null);
59313 context.history().on('change.intro', null);
59314 select('.inspector-wrap').on('wheel.intro', null);
59320 function fieldsTownHall() {
59321 if (!isTownHallSelected()) return clickTownHall();
59323 // reset pane, in case user happened to change it..
59324 select('.inspector-wrap .panewrap').style('right', '0%');
59325 // disallow scrolling
59326 select('.inspector-wrap').on('wheel.intro', eventCancel);
59328 var onClick = function() { continueTo(closeTownHall); };
59330 reveal('.inspector-body .inspector-preset',
59331 t('intro.navigation.fields_townhall'),
59332 { buttonText: t('intro.ok'), buttonCallback: onClick }
59335 context.on('exit.intro', function() {
59336 continueTo(clickTownHall);
59339 context.history().on('change.intro', function() {
59340 if (!context.hasEntity(hallId)) {
59341 continueTo(clickTownHall);
59345 function continueTo(nextStep) {
59346 context.on('exit.intro', null);
59347 context.history().on('change.intro', null);
59348 select('.inspector-wrap').on('wheel.intro', null);
59354 function closeTownHall() {
59355 if (!isTownHallSelected()) return clickTownHall();
59357 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59358 var href = select(selector$$1).attr('href') || '#icon-close';
59360 reveal('.entity-editor-pane',
59361 t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') })
59364 context.on('exit.intro', function() {
59365 continueTo(searchStreet);
59368 context.history().on('change.intro', function() {
59369 // update the close icon in the tooltip if the user edits something.
59370 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59371 var href = select(selector$$1).attr('href') || '#icon-close';
59373 reveal('.entity-editor-pane',
59374 t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }),
59379 function continueTo(nextStep) {
59380 context.on('exit.intro', null);
59381 context.history().on('change.intro', null);
59387 function searchStreet() {
59388 context.enter(modeBrowse(context));
59389 context.history().reset('initial'); // ensure spring street exists
59391 var msec = transitionTime(springStreet, context.map().center());
59392 if (msec) { reveal(null, null, { duration: 0 }); }
59393 context.map().zoom(19).centerEase(springStreet, msec); // ..and user can see it
59395 timeout$$1(function() {
59396 reveal('.search-header input',
59397 t('intro.navigation.search_street', { name: t('intro.graph.name.spring-street') })
59400 select('.search-header input')
59401 .on('keyup.intro', checkSearchResult);
59406 function checkSearchResult() {
59407 var first = select('.feature-list-item:nth-child(0n+2)'), // skip "No Results" item
59408 firstName = first.select('.entity-name'),
59409 name = t('intro.graph.name.spring-street');
59411 if (!firstName.empty() && firstName.text() === name) {
59412 reveal(first.node(),
59413 t('intro.navigation.choose_street', { name: name }),
59417 context.on('exit.intro', function() {
59418 continueTo(selectedStreet);
59421 select('.search-header input')
59422 .on('keydown.intro', eventCancel, true)
59423 .on('keyup.intro', null);
59426 function continueTo(nextStep) {
59427 context.on('exit.intro', null);
59428 select('.search-header input')
59429 .on('keydown.intro', null)
59430 .on('keyup.intro', null);
59436 function selectedStreet() {
59437 if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
59438 return searchStreet();
59441 var onClick = function() { continueTo(editorStreet); };
59442 var entity = context.entity(springStreetEndId);
59443 var box = pointBox(entity.loc, context);
59447 t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }),
59448 { duration: 600, buttonText: t('intro.ok'), buttonCallback: onClick }
59451 timeout$$1(function() {
59452 context.map().on('move.intro drawn.intro', function() {
59453 var entity = context.hasEntity(springStreetEndId);
59454 if (!entity) return;
59455 var box = pointBox(entity.loc, context);
59458 t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }),
59459 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
59462 }, 600); // after reveal.
59464 context.on('enter.intro', function(mode) {
59465 if (!context.hasEntity(springStreetId)) {
59466 return continueTo(searchStreet);
59468 var ids = context.selectedIDs();
59469 if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) {
59470 // keep Spring Street selected..
59471 context.enter(modeSelect(context, [springStreetId]));
59475 context.history().on('change.intro', function() {
59476 if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
59477 timeout$$1(function() {
59478 continueTo(searchStreet);
59479 }, 300); // after any transition (e.g. if user deleted intersection)
59483 function continueTo(nextStep) {
59484 context.map().on('move.intro drawn.intro', null);
59485 context.on('enter.intro', null);
59486 context.history().on('change.intro', null);
59492 function editorStreet() {
59493 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59494 var href = select(selector$$1).attr('href') || '#icon-close';
59496 reveal('.entity-editor-pane',
59497 t('intro.navigation.editor_street', {
59498 button: icon(href, 'pre-text'),
59499 field1: onewayField.label(),
59500 field2: maxspeedField.label()
59504 context.on('exit.intro', function() {
59508 context.history().on('change.intro', function() {
59509 // update the close icon in the tooltip if the user edits something.
59510 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59511 var href = select(selector$$1).attr('href') || '#icon-close';
59513 reveal('.entity-editor-pane',
59514 t('intro.navigation.editor_street', {
59515 button: icon(href, 'pre-text'),
59516 field1: onewayField.label().toLowerCase(),
59517 field2: maxspeedField.label().toLowerCase()
59518 }), { duration: 0 }
59522 function continueTo(nextStep) {
59523 context.on('exit.intro', null);
59524 context.history().on('change.intro', null);
59531 dispatch$$1.call('done');
59532 reveal('#id-container',
59533 t('intro.navigation.play', { next: t('intro.points.title') }), {
59534 tooltipBox: '.intro-nav-wrap .chapter-point',
59535 buttonText: t('intro.ok'),
59536 buttonCallback: function() { reveal('#id-container'); }
59542 chapter.enter = function() {
59547 chapter.exit = function() {
59548 timeouts.forEach(window.clearTimeout);
59549 context.on('enter.intro exit.intro', null);
59550 context.map().on('move.intro drawn.intro', null);
59551 context.history().on('change.intro', null);
59552 select('.inspector-wrap').on('wheel.intro', null);
59553 select('.search-header input').on('keydown.intro keyup.intro', null);
59557 chapter.restart = function() {
59563 return utilRebind(chapter, dispatch$$1, 'on');
59566 function uiIntroPoint(context, reveal) {
59567 var dispatch$$1 = dispatch('done'),
59569 intersection = [-85.63279, 41.94394],
59570 building = [-85.632422, 41.944045],
59571 cafePreset = context.presets().item('amenity/cafe'),
59576 title: 'intro.points.title'
59580 function timeout$$1(f, t$$1) {
59581 timeouts.push(window.setTimeout(f, t$$1));
59585 function revealEditMenu(loc, text$$1, options) {
59586 var rect = context.surfaceRect();
59587 var point = context.curtainProjection(loc);
59589 var width = 250 + (2 * pad$$1);
59591 var startX = rect.left + point[0];
59592 var left = (textDirection === 'rtl') ? (startX - width + pad$$1) : (startX - pad$$1);
59595 top: point[1] + rect.top - 60,
59599 reveal(box, text$$1, options);
59603 function eventCancel() {
59604 event.stopPropagation();
59605 event.preventDefault();
59609 function addPoint() {
59610 context.enter(modeBrowse(context));
59611 context.history().reset('initial');
59613 var msec = transitionTime(intersection, context.map().center());
59614 if (msec) { reveal(null, null, { duration: 0 }); }
59615 context.map().zoom(19).centerEase(intersection, msec);
59617 timeout$$1(function() {
59618 var tooltip = reveal('button.add-point',
59619 t('intro.points.add_point', { button: icon('#icon-point', 'pre-text') }));
59623 tooltip.selectAll('.tooltip-inner')
59624 .insert('svg', 'span')
59625 .attr('class', 'tooltip-illustration')
59627 .attr('xlink:href', '#poi-images');
59629 context.on('enter.intro', function(mode) {
59630 if (mode.id !== 'add-point') return;
59631 continueTo(placePoint);
59635 function continueTo(nextStep) {
59636 context.on('enter.intro', null);
59642 function placePoint() {
59643 if (context.mode().id !== 'add-point') {
59644 return chapter.restart();
59647 var pointBox$$1 = pad$1(building, 150, context);
59648 reveal(pointBox$$1, t('intro.points.place_point'));
59650 context.map().on('move.intro drawn.intro', function() {
59651 pointBox$$1 = pad$1(building, 150, context);
59652 reveal(pointBox$$1, t('intro.points.place_point'), { duration: 0 });
59655 context.on('enter.intro', function(mode) {
59656 if (mode.id !== 'select') return chapter.restart();
59657 pointId = context.mode().selectedIDs()[0];
59658 continueTo(searchPreset);
59661 function continueTo(nextStep) {
59662 context.map().on('move.intro drawn.intro', null);
59663 context.on('enter.intro', null);
59669 function searchPreset() {
59670 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59674 // disallow scrolling
59675 select('.inspector-wrap').on('wheel.intro', eventCancel);
59677 select('.preset-search-input')
59678 .on('keydown.intro', null)
59679 .on('keyup.intro', checkPresetSearch);
59681 reveal('.preset-search-input',
59682 t('intro.points.search_cafe', { preset: cafePreset.name() })
59685 context.on('enter.intro', function(mode) {
59686 if (!pointId || !context.hasEntity(pointId)) {
59687 return continueTo(addPoint);
59690 var ids = context.selectedIDs();
59691 if (mode.id !== 'select' || !ids.length || ids[0] !== pointId) {
59692 // keep the user's point selected..
59693 context.enter(modeSelect(context, [pointId]));
59695 // disallow scrolling
59696 select('.inspector-wrap').on('wheel.intro', eventCancel);
59698 select('.preset-search-input')
59699 .on('keydown.intro', null)
59700 .on('keyup.intro', checkPresetSearch);
59702 reveal('.preset-search-input',
59703 t('intro.points.search_cafe', { preset: cafePreset.name() })
59706 context.history().on('change.intro', null);
59711 function checkPresetSearch() {
59712 var first = select('.preset-list-item:first-child');
59714 if (first.classed('preset-amenity-cafe')) {
59715 select('.preset-search-input')
59716 .on('keydown.intro', eventCancel, true)
59717 .on('keyup.intro', null);
59719 reveal(first.select('.preset-list-button').node(),
59720 t('intro.points.choose_cafe', { preset: cafePreset.name() }),
59724 context.history().on('change.intro', function() {
59725 continueTo(aboutFeatureEditor);
59730 function continueTo(nextStep) {
59731 context.on('enter.intro', null);
59732 context.history().on('change.intro', null);
59733 select('.inspector-wrap').on('wheel.intro', null);
59734 select('.preset-search-input').on('keydown.intro keyup.intro', null);
59740 function aboutFeatureEditor() {
59741 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59745 timeout$$1(function() {
59746 reveal('.entity-editor-pane', t('intro.points.feature_editor'), {
59747 tooltipClass: 'intro-points-describe',
59748 buttonText: t('intro.ok'),
59749 buttonCallback: function() { continueTo(addName); }
59753 context.on('exit.intro', function() {
59754 // if user leaves select mode here, just continue with the tutorial.
59755 continueTo(reselectPoint);
59758 function continueTo(nextStep) {
59759 context.on('exit.intro', null);
59765 function addName() {
59766 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59770 // reset pane, in case user happened to change it..
59771 select('.inspector-wrap .panewrap').style('right', '0%');
59773 timeout$$1(function() {
59774 // It's possible for the user to add a name in a previous step..
59775 // If so, don't tell them to add the name in this step.
59776 // Give them an OK button instead.
59777 var entity = context.entity(pointId);
59778 if (entity.tags.name) {
59779 var tooltip = reveal('.entity-editor-pane', t('intro.points.add_name'), {
59780 tooltipClass: 'intro-points-describe',
59781 buttonText: t('intro.ok'),
59782 buttonCallback: function() { continueTo(addCloseEditor); }
59784 tooltip.select('.instruction').style('display', 'none');
59787 reveal('.entity-editor-pane', t('intro.points.add_name'),
59788 { tooltipClass: 'intro-points-describe' }
59793 context.history().on('change.intro', function() {
59794 continueTo(addCloseEditor);
59797 context.on('exit.intro', function() {
59798 // if user leaves select mode here, just continue with the tutorial.
59799 continueTo(reselectPoint);
59802 function continueTo(nextStep) {
59803 context.on('exit.intro', null);
59804 context.history().on('change.intro', null);
59810 function addCloseEditor() {
59811 // reset pane, in case user happened to change it..
59812 select('.inspector-wrap .panewrap').style('right', '0%');
59814 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59815 var href = select(selector$$1).attr('href') || '#icon-close';
59817 context.on('exit.intro', function() {
59818 continueTo(reselectPoint);
59821 reveal('.entity-editor-pane',
59822 t('intro.points.add_close', { button: icon(href, 'pre-text') })
59825 function continueTo(nextStep) {
59826 context.on('exit.intro', null);
59832 function reselectPoint() {
59833 if (!pointId) return chapter.restart();
59834 var entity = context.hasEntity(pointId);
59835 if (!entity) return chapter.restart();
59837 // make sure it's still a cafe, in case user somehow changed it..
59838 var oldPreset = context.presets().match(entity, context.graph());
59839 context.replace(actionChangePreset(pointId, oldPreset, cafePreset));
59841 context.enter(modeBrowse(context));
59843 var msec = transitionTime(entity.loc, context.map().center());
59844 if (msec) { reveal(null, null, { duration: 0 }); }
59845 context.map().centerEase(entity.loc, msec);
59847 timeout$$1(function() {
59848 var box = pointBox(entity.loc, context);
59849 reveal(box, t('intro.points.reselect'), { duration: 600 });
59851 timeout$$1(function() {
59852 context.map().on('move.intro drawn.intro', function() {
59853 var entity = context.hasEntity(pointId);
59854 if (!entity) return chapter.restart();
59855 var box = pointBox(entity.loc, context);
59856 reveal(box, t('intro.points.reselect'), { duration: 0 });
59858 }, 600); // after reveal..
59860 context.on('enter.intro', function(mode) {
59861 if (mode.id !== 'select') return;
59862 continueTo(updatePoint);
59867 function continueTo(nextStep) {
59868 context.map().on('move.intro drawn.intro', null);
59869 context.on('enter.intro', null);
59875 function updatePoint() {
59876 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59877 return continueTo(reselectPoint);
59880 // reset pane, in case user happened to untag the point..
59881 select('.inspector-wrap .panewrap').style('right', '0%');
59883 context.on('exit.intro', function() {
59884 continueTo(reselectPoint);
59887 context.history().on('change.intro', function() {
59888 continueTo(updateCloseEditor);
59891 timeout$$1(function() {
59892 reveal('.entity-editor-pane', t('intro.points.update'),
59893 { tooltipClass: 'intro-points-describe' }
59897 function continueTo(nextStep) {
59898 context.on('exit.intro', null);
59899 context.history().on('change.intro', null);
59905 function updateCloseEditor() {
59906 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59907 return continueTo(reselectPoint);
59910 // reset pane, in case user happened to change it..
59911 select('.inspector-wrap .panewrap').style('right', '0%');
59913 context.on('exit.intro', function() {
59914 continueTo(rightClickPoint);
59917 timeout$$1(function() {
59918 reveal('.entity-editor-pane',
59919 t('intro.points.update_close', { button: icon('#icon-apply', 'pre-text') })
59923 function continueTo(nextStep) {
59924 context.on('exit.intro', null);
59930 function rightClickPoint() {
59931 if (!pointId) return chapter.restart();
59932 var entity = context.hasEntity(pointId);
59933 if (!entity) return chapter.restart();
59935 context.enter(modeBrowse(context));
59937 var box = pointBox(entity.loc, context);
59938 reveal(box, t('intro.points.rightclick'), { duration: 600 });
59940 timeout$$1(function() {
59941 context.map().on('move.intro drawn.intro', function() {
59942 var entity = context.hasEntity(pointId);
59943 if (!entity) return chapter.restart();
59944 var box = pointBox(entity.loc, context);
59945 reveal(box, t('intro.points.rightclick'), { duration: 0 });
59947 }, 600); // after reveal
59949 context.on('enter.intro', function(mode) {
59950 if (mode.id !== 'select') return;
59951 var ids = context.selectedIDs();
59952 if (ids.length !== 1 || ids[0] !== pointId) return;
59954 timeout$$1(function() {
59955 var node = selectMenuItem('delete').node();
59957 continueTo(enterDelete);
59958 }, 300); // after menu visible
59961 function continueTo(nextStep) {
59962 context.on('enter.intro', null);
59963 context.map().on('move.intro drawn.intro', null);
59969 function enterDelete() {
59970 if (!pointId) return chapter.restart();
59971 var entity = context.hasEntity(pointId);
59972 if (!entity) return chapter.restart();
59974 var node = selectMenuItem('delete').node();
59975 if (!node) { return continueTo(rightClickPoint); }
59977 revealEditMenu(entity.loc,
59978 t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') })
59981 timeout$$1(function() {
59982 context.map().on('move.intro drawn.intro', function() {
59983 revealEditMenu(entity.loc,
59984 t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }),
59988 }, 300); // after menu visible
59990 context.on('exit.intro', function() {
59991 if (!pointId) return chapter.restart();
59992 var entity = context.hasEntity(pointId);
59993 if (entity) return continueTo(rightClickPoint); // point still exists
59996 context.history().on('change.intro', function(changed) {
59997 if (changed.deleted().length) {
60002 function continueTo(nextStep) {
60003 context.map().on('move.intro drawn.intro', null);
60004 context.history().on('change.intro', null);
60005 context.on('exit.intro', null);
60012 context.history().on('change.intro', function() {
60016 var iconName = '#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo');
60017 reveal('#bar button.undo-button',
60018 t('intro.points.undo', { button: icon(iconName, 'pre-text') })
60021 function continueTo(nextStep) {
60022 context.history().on('change.intro', null);
60029 dispatch$$1.call('done');
60030 reveal('#id-container',
60031 t('intro.points.play', { next: t('intro.areas.title') }), {
60032 tooltipBox: '.intro-nav-wrap .chapter-area',
60033 buttonText: t('intro.ok'),
60034 buttonCallback: function() { reveal('#id-container'); }
60040 chapter.enter = function() {
60045 chapter.exit = function() {
60046 timeouts.forEach(window.clearTimeout);
60047 context.on('enter.intro exit.intro', null);
60048 context.map().on('move.intro drawn.intro', null);
60049 context.history().on('change.intro', null);
60050 select('.inspector-wrap').on('wheel.intro', eventCancel);
60051 select('.preset-search-input').on('keydown.intro keyup.intro', null);
60055 chapter.restart = function() {
60061 return utilRebind(chapter, dispatch$$1, 'on');
60064 function uiIntroArea(context, reveal) {
60065 var dispatch$$1 = dispatch('done'),
60066 playground = [-85.63552, 41.94159],
60067 playgroundPreset = context.presets().item('leisure/playground'),
60068 descriptionField = context.presets().field('description'),
60074 title: 'intro.areas.title'
60078 function timeout$$1(f, t$$1) {
60079 timeouts.push(window.setTimeout(f, t$$1));
60083 function eventCancel() {
60084 event.stopPropagation();
60085 event.preventDefault();
60089 function revealPlayground(center, text$$1, options) {
60090 var padding = 180 * Math.pow(2, context.map().zoom() - 19.5);
60091 var box = pad$1(center, padding, context);
60092 reveal(box, text$$1, options);
60096 function addArea() {
60097 context.enter(modeBrowse(context));
60098 context.history().reset('initial');
60101 var msec = transitionTime(playground, context.map().center());
60102 if (msec) { reveal(null, null, { duration: 0 }); }
60103 context.map().zoom(19).centerEase(playground, msec);
60105 timeout$$1(function() {
60106 var tooltip = reveal('button.add-area',
60107 t('intro.areas.add_playground', { button: icon('#icon-area', 'pre-text') }));
60109 tooltip.selectAll('.tooltip-inner')
60110 .insert('svg', 'span')
60111 .attr('class', 'tooltip-illustration')
60113 .attr('xlink:href', '#landuse-images');
60115 context.on('enter.intro', function(mode) {
60116 if (mode.id !== 'add-area') return;
60117 continueTo(startPlayground);
60121 function continueTo(nextStep) {
60122 context.on('enter.intro', null);
60128 function startPlayground() {
60129 if (context.mode().id !== 'add-area') {
60130 return chapter.restart();
60134 context.map().zoomEase(19.5, 500);
60136 timeout$$1(function() {
60137 revealPlayground(playground,
60138 t('intro.areas.start_playground'), { duration: 250 }
60141 timeout$$1(function() {
60142 context.map().on('move.intro drawn.intro', function() {
60143 revealPlayground(playground,
60144 t('intro.areas.start_playground'), { duration: 0 }
60147 context.on('enter.intro', function(mode) {
60148 if (mode.id !== 'draw-area') return chapter.restart();
60149 continueTo(continuePlayground);
60151 }, 250); // after reveal
60153 }, 550); // after easing
60155 function continueTo(nextStep) {
60156 context.map().on('move.intro drawn.intro', null);
60157 context.on('enter.intro', null);
60163 function continuePlayground() {
60164 if (context.mode().id !== 'draw-area') {
60165 return chapter.restart();
60169 revealPlayground(playground,
60170 t('intro.areas.continue_playground'), { duration: 250 }
60173 timeout$$1(function() {
60174 context.map().on('move.intro drawn.intro', function() {
60175 revealPlayground(playground,
60176 t('intro.areas.continue_playground'), { duration: 0 }
60179 }, 250); // after reveal
60181 context.on('enter.intro', function(mode) {
60182 if (mode.id === 'draw-area') {
60183 var entity = context.hasEntity(context.selectedIDs()[0]);
60184 if (entity && entity.nodes.length >= 6) {
60185 return continueTo(finishPlayground);
60189 } else if (mode.id === 'select') {
60190 areaId = context.selectedIDs()[0];
60191 return continueTo(searchPresets);
60193 return chapter.restart();
60197 function continueTo(nextStep) {
60198 context.map().on('move.intro drawn.intro', null);
60199 context.on('enter.intro', null);
60205 function finishPlayground() {
60206 if (context.mode().id !== 'draw-area') {
60207 return chapter.restart();
60211 revealPlayground(playground,
60212 t('intro.areas.finish_playground'), { duration: 250 }
60215 timeout$$1(function() {
60216 context.map().on('move.intro drawn.intro', function() {
60217 revealPlayground(playground,
60218 t('intro.areas.finish_playground'), { duration: 0 }
60221 }, 250); // after reveal
60223 context.on('enter.intro', function(mode) {
60224 if (mode.id === 'draw-area') {
60226 } else if (mode.id === 'select') {
60227 areaId = context.selectedIDs()[0];
60228 return continueTo(searchPresets);
60230 return chapter.restart();
60234 function continueTo(nextStep) {
60235 context.map().on('move.intro drawn.intro', null);
60236 context.on('enter.intro', null);
60242 function searchPresets() {
60243 if (!areaId || !context.hasEntity(areaId)) {
60246 var ids = context.selectedIDs();
60247 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60248 context.enter(modeSelect(context, [areaId]));
60251 // disallow scrolling
60252 select('.inspector-wrap').on('wheel.intro', eventCancel);
60254 timeout$$1(function() {
60255 // reset pane, in case user somehow happened to change it..
60256 select('.inspector-wrap .panewrap').style('right', '-100%');
60258 select('.preset-search-input')
60259 .on('keydown.intro', null)
60260 .on('keyup.intro', checkPresetSearch);
60262 reveal('.preset-search-input',
60263 t('intro.areas.search_playground', { preset: playgroundPreset.name() })
60265 }, 400); // after preset list pane visible..
60267 context.on('enter.intro', function(mode) {
60268 if (!areaId || !context.hasEntity(areaId)) {
60269 return continueTo(addArea);
60272 var ids = context.selectedIDs();
60273 if (mode.id !== 'select' || !ids.length || ids[0] !== areaId) {
60274 // keep the user's area selected..
60275 context.enter(modeSelect(context, [areaId]));
60277 // reset pane, in case user somehow happened to change it..
60278 select('.inspector-wrap .panewrap').style('right', '-100%');
60279 // disallow scrolling
60280 select('.inspector-wrap').on('wheel.intro', eventCancel);
60282 select('.preset-search-input')
60283 .on('keydown.intro', null)
60284 .on('keyup.intro', checkPresetSearch);
60286 reveal('.preset-search-input',
60287 t('intro.areas.search_playground', { preset: playgroundPreset.name() })
60290 context.history().on('change.intro', null);
60294 function checkPresetSearch() {
60295 var first = select('.preset-list-item:first-child');
60297 if (first.classed('preset-leisure-playground')) {
60298 reveal(first.select('.preset-list-button').node(),
60299 t('intro.areas.choose_playground', { preset: playgroundPreset.name() }),
60303 select('.preset-search-input')
60304 .on('keydown.intro', eventCancel, true)
60305 .on('keyup.intro', null);
60307 context.history().on('change.intro', function() {
60308 continueTo(clickAddField);
60313 function continueTo(nextStep) {
60314 select('.inspector-wrap').on('wheel.intro', null);
60315 context.on('enter.intro', null);
60316 context.history().on('change.intro', null);
60317 select('.preset-search-input').on('keydown.intro keyup.intro', null);
60323 function clickAddField() {
60324 if (!areaId || !context.hasEntity(areaId)) {
60327 var ids = context.selectedIDs();
60328 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60329 return searchPresets();
60332 if (!select('.form-field-description').empty()) {
60333 return continueTo(describePlayground);
60336 // disallow scrolling
60337 select('.inspector-wrap').on('wheel.intro', eventCancel);
60339 timeout$$1(function() {
60340 // reset pane, in case user somehow happened to change it..
60341 select('.inspector-wrap .panewrap').style('right', '0%');
60343 // It's possible for the user to add a description in a previous step..
60344 // If they did this already, just continue to next step.
60345 var entity = context.entity(areaId);
60346 if (entity.tags.description) {
60347 return continueTo(play);
60350 reveal('.more-fields .combobox-input',
60351 t('intro.areas.add_field'),
60355 select('.more-fields .combobox-input')
60356 .on('click.intro', function() {
60357 continueTo(chooseDescriptionField);
60359 }, 400); // after editor pane visible
60361 context.on('exit.intro', function() {
60362 return continueTo(searchPresets);
60365 function continueTo(nextStep) {
60366 select('.inspector-wrap').on('wheel.intro', null);
60367 select('.more-fields .combobox-input').on('click.intro', null);
60368 context.on('exit.intro', null);
60374 function chooseDescriptionField() {
60375 if (!areaId || !context.hasEntity(areaId)) {
60378 var ids = context.selectedIDs();
60379 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60380 return searchPresets();
60383 if (!select('.form-field-description').empty()) {
60384 return continueTo(describePlayground);
60387 // Make sure combobox is ready..
60388 if (select('div.combobox').empty()) {
60389 return continueTo(clickAddField);
60391 // Watch for the combobox to go away..
60393 watcher = window.setInterval(function() {
60394 if (select('div.combobox').empty()) {
60395 window.clearInterval(watcher);
60396 timeout$$1(function() {
60397 if (select('.form-field-description').empty()) {
60398 continueTo(retryChooseDescription);
60400 continueTo(describePlayground);
60402 }, 300); // after description field added.
60406 reveal('div.combobox',
60407 t('intro.areas.choose_field', { field: descriptionField.label() }),
60411 context.on('exit.intro', function() {
60412 return continueTo(searchPresets);
60415 function continueTo(nextStep) {
60416 if (watcher) window.clearInterval(watcher);
60417 context.on('exit.intro', null);
60423 function describePlayground() {
60424 if (!areaId || !context.hasEntity(areaId)) {
60427 var ids = context.selectedIDs();
60428 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60429 return searchPresets();
60432 // reset pane, in case user happened to change it..
60433 select('.inspector-wrap .panewrap').style('right', '0%');
60435 if (select('.form-field-description').empty()) {
60436 return continueTo(retryChooseDescription);
60439 context.on('exit.intro', function() {
60443 reveal('.entity-editor-pane',
60444 t('intro.areas.describe_playground', { button: icon('#icon-apply', 'pre-text') }),
60448 function continueTo(nextStep) {
60449 context.on('exit.intro', null);
60455 function retryChooseDescription() {
60456 if (!areaId || !context.hasEntity(areaId)) {
60459 var ids = context.selectedIDs();
60460 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60461 return searchPresets();
60464 // reset pane, in case user happened to change it..
60465 select('.inspector-wrap .panewrap').style('right', '0%');
60467 reveal('.entity-editor-pane',
60468 t('intro.areas.retry_add_field', { field: descriptionField.label() }), {
60469 buttonText: t('intro.ok'),
60470 buttonCallback: function() { continueTo(clickAddField); }
60473 context.on('exit.intro', function() {
60474 return continueTo(searchPresets);
60477 function continueTo(nextStep) {
60478 context.on('exit.intro', null);
60485 dispatch$$1.call('done');
60486 reveal('#id-container',
60487 t('intro.areas.play', { next: t('intro.lines.title') }), {
60488 tooltipBox: '.intro-nav-wrap .chapter-line',
60489 buttonText: t('intro.ok'),
60490 buttonCallback: function() { reveal('#id-container'); }
60496 chapter.enter = function() {
60501 chapter.exit = function() {
60502 timeouts.forEach(window.clearTimeout);
60503 context.on('enter.intro exit.intro', null);
60504 context.map().on('move.intro drawn.intro', null);
60505 context.history().on('change.intro', null);
60506 select('.inspector-wrap').on('wheel.intro', null);
60507 select('.preset-search-input').on('keydown.intro keyup.intro', null);
60508 select('.more-fields .combobox-input').on('click.intro', null);
60512 chapter.restart = function() {
60518 return utilRebind(chapter, dispatch$$1, 'on');
60521 function uiIntroLine(context, reveal) {
60522 var dispatch$$1 = dispatch('done'),
60524 tulipRoadId = null,
60525 flowerRoadId = 'w646',
60526 tulipRoadStart = [-85.6297754121684, 41.95805253325314],
60527 tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204],
60528 tulipRoadIntersection = [-85.62974496187628, 41.95742515554585],
60529 roadCategory = context.presets().item('category-road'),
60530 residentialPreset = context.presets().item('highway/residential'),
60531 woodRoadId = 'w525',
60532 woodRoadEndId = 'n2862',
60533 woodRoadAddNode = [-85.62390110349587, 41.95397111462291],
60534 woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487],
60535 woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872],
60536 washingtonStreetId = 'w522',
60537 twelfthAvenueId = 'w1',
60538 eleventhAvenueEndId = 'n3550',
60539 twelfthAvenueEndId = 'n5',
60540 washingtonSegmentId = null,
60541 eleventhAvenueEnd = context.entity(eleventhAvenueEndId).loc,
60542 twelfthAvenueEnd = context.entity(twelfthAvenueEndId).loc,
60543 deleteLinesLoc = [-85.6219395542764, 41.95228033922477],
60544 twelfthAvenue = [-85.62219310052491, 41.952505413152956];
60548 title: 'intro.lines.title'
60552 function timeout$$1(f, t$$1) {
60553 timeouts.push(window.setTimeout(f, t$$1));
60557 function eventCancel() {
60558 event.stopPropagation();
60559 event.preventDefault();
60563 function revealEditMenu(loc, text$$1, options) {
60564 var rect = context.surfaceRect();
60565 var point = context.curtainProjection(loc);
60567 var width = 250 + (2 * pad$$1);
60569 var startX = rect.left + point[0];
60570 var left = (textDirection === 'rtl') ? (startX - width + pad$$1) : (startX - pad$$1);
60573 top: point[1] + rect.top - 60,
60577 reveal(box, text$$1, options);
60581 function addLine() {
60582 context.enter(modeBrowse(context));
60583 context.history().reset('initial');
60585 var msec = transitionTime(tulipRoadStart, context.map().center());
60586 if (msec) { reveal(null, null, { duration: 0 }); }
60587 context.map().zoom(18.5).centerEase(tulipRoadStart, msec);
60589 timeout$$1(function() {
60590 var tooltip = reveal('button.add-line',
60591 t('intro.lines.add_line', { button: icon('#icon-line', 'pre-text') }));
60593 tooltip.selectAll('.tooltip-inner')
60594 .insert('svg', 'span')
60595 .attr('class', 'tooltip-illustration')
60597 .attr('xlink:href', '#feature-images');
60599 context.on('enter.intro', function(mode) {
60600 if (mode.id !== 'add-line') return;
60601 continueTo(startLine);
60605 function continueTo(nextStep) {
60606 context.on('enter.intro', null);
60612 function startLine() {
60613 if (context.mode().id !== 'add-line') {
60614 return chapter.restart();
60617 tulipRoadId = null;
60619 var padding = 70 * Math.pow(2, context.map().zoom() - 18);
60620 var box = pad$1(tulipRoadStart, padding, context);
60621 box.height = box.height + 100;
60622 reveal(box, t('intro.lines.start_line'));
60624 context.map().on('move.intro drawn.intro', function() {
60625 padding = 70 * Math.pow(2, context.map().zoom() - 18);
60626 box = pad$1(tulipRoadStart, padding, context);
60627 box.height = box.height + 100;
60628 reveal(box, t('intro.lines.start_line'), { duration: 0 });
60631 context.on('enter.intro', function(mode) {
60632 if (mode.id !== 'draw-line') return chapter.restart();
60633 continueTo(drawLine);
60636 function continueTo(nextStep) {
60637 context.map().on('move.intro drawn.intro', null);
60638 context.on('enter.intro', null);
60644 function drawLine() {
60645 if (context.mode().id !== 'draw-line') {
60646 return chapter.restart();
60649 tulipRoadId = context.mode().selectedIDs()[0];
60650 context.map().centerEase(tulipRoadMidpoint, 500);
60652 timeout$$1(function() {
60653 var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
60654 var box = pad$1(tulipRoadMidpoint, padding, context);
60655 box.height = box.height * 2;
60657 t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') })
60660 context.map().on('move.intro drawn.intro', function() {
60661 padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
60662 box = pad$1(tulipRoadMidpoint, padding, context);
60663 box.height = box.height * 2;
60665 t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }),
60669 }, 550); // after easing..
60671 context.history().on('change.intro', function() {
60672 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
60673 if (!entity) return chapter.restart();
60675 if (isLineConnected()) {
60676 continueTo(continueLine);
60680 context.on('enter.intro', function(mode) {
60681 if (mode.id === 'draw-line')
60683 else if (mode.id === 'select') {
60684 continueTo(retryIntersect);
60688 return chapter.restart();
60691 function continueTo(nextStep) {
60692 context.map().on('move.intro drawn.intro', null);
60693 context.history().on('change.intro', null);
60694 context.on('enter.intro', null);
60700 function isLineConnected() {
60701 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
60702 if (!entity) return false;
60704 var drawNodes = context.graph().childNodes(entity);
60705 return lodash.some(drawNodes, function(node) {
60706 return lodash.some(context.graph().parentWays(node), function(parent) {
60707 return parent.id === flowerRoadId;
60713 function retryIntersect() {
60714 select(window).on('mousedown.intro', eventCancel, true);
60716 var box = pad$1(tulipRoadIntersection, 80, context);
60718 t('intro.lines.retry_intersect', { name: t('intro.graph.name.flower-street') })
60721 timeout$$1(chapter.restart, 3000);
60725 function continueLine() {
60726 if (context.mode().id !== 'draw-line') return chapter.restart();
60727 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
60728 if (!entity) return chapter.restart();
60730 context.map().centerEase(tulipRoadIntersection, 500);
60732 reveal('#surface', t('intro.lines.continue_line'));
60734 context.on('enter.intro', function(mode) {
60735 if (mode.id === 'draw-line')
60737 else if (mode.id === 'select')
60738 return continueTo(chooseCategoryRoad);
60740 return chapter.restart();
60743 function continueTo(nextStep) {
60744 context.on('enter.intro', null);
60750 function chooseCategoryRoad() {
60751 if (context.mode().id !== 'select') {
60752 return chapter.restart();
60755 context.on('exit.intro', function() {
60756 return chapter.restart();
60759 var button = select('.preset-category-road .preset-list-button');
60760 if (button.empty()) return chapter.restart();
60762 // disallow scrolling
60763 select('.inspector-wrap').on('wheel.intro', eventCancel);
60765 timeout$$1(function() {
60766 // reset pane, in case user somehow happened to change it..
60767 select('.inspector-wrap .panewrap').style('right', '-100%');
60769 reveal(button.node(),
60770 t('intro.lines.choose_category_road', { category: roadCategory.name() })
60773 button.on('click.intro', function() {
60774 continueTo(choosePresetResidential);
60777 }, 400); // after editor pane visible
60779 function continueTo(nextStep) {
60780 select('.inspector-wrap').on('wheel.intro', null);
60781 select('.preset-list-button').on('click.intro', null);
60782 context.on('exit.intro', null);
60788 function choosePresetResidential() {
60789 if (context.mode().id !== 'select') {
60790 return chapter.restart();
60793 context.on('exit.intro', function() {
60794 return chapter.restart();
60797 var subgrid = select('.preset-category-road .subgrid');
60798 if (subgrid.empty()) return chapter.restart();
60800 subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button')
60801 .on('click.intro', function() {
60802 continueTo(retryPresetResidential);
60805 subgrid.selectAll('.preset-highway-residential .preset-list-button')
60806 .on('click.intro', function() {
60807 continueTo(nameRoad);
60810 timeout$$1(function() {
60811 reveal(subgrid.node(),
60812 t('intro.lines.choose_preset_residential', { preset: residentialPreset.name() }),
60813 { tooltipBox: '.preset-highway-residential .preset-list-button', duration: 300 }
60817 function continueTo(nextStep) {
60818 select('.preset-list-button').on('click.intro', null);
60819 context.on('exit.intro', null);
60825 // selected wrong road type
60826 function retryPresetResidential() {
60827 if (context.mode().id !== 'select') {
60828 return chapter.restart();
60831 context.on('exit.intro', function() {
60832 return chapter.restart();
60835 // disallow scrolling
60836 select('.inspector-wrap').on('wheel.intro', eventCancel);
60838 timeout$$1(function() {
60839 var button = select('.entity-editor-pane .preset-list-button');
60841 reveal(button.node(),
60842 t('intro.lines.retry_preset_residential', { preset: residentialPreset.name() })
60845 button.on('click.intro', function() {
60846 continueTo(chooseCategoryRoad);
60851 function continueTo(nextStep) {
60852 select('.inspector-wrap').on('wheel.intro', null);
60853 select('.preset-list-button').on('click.intro', null);
60854 context.on('exit.intro', null);
60860 function nameRoad() {
60861 context.on('exit.intro', function() {
60862 continueTo(didNameRoad);
60865 timeout$$1(function() {
60866 reveal('.entity-editor-pane',
60867 t('intro.lines.name_road', { button: icon('#icon-apply', 'pre-text') }),
60868 { tooltipClass: 'intro-lines-name_road' }
60872 function continueTo(nextStep) {
60873 context.on('exit.intro', null);
60879 function didNameRoad() {
60880 context.history().checkpoint('doneAddLine');
60882 timeout$$1(function() {
60883 reveal('#surface', t('intro.lines.did_name_road'), {
60884 buttonText: t('intro.ok'),
60885 buttonCallback: function() { continueTo(updateLine); }
60889 function continueTo(nextStep) {
60895 function updateLine() {
60896 context.history().reset('doneAddLine');
60897 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60898 return chapter.restart();
60901 var msec = transitionTime(woodRoadDragMidpoint, context.map().center());
60902 if (msec) { reveal(null, null, { duration: 0 }); }
60903 context.map().zoom(19).centerEase(woodRoadDragMidpoint, msec);
60905 timeout$$1(function() {
60906 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
60907 var box = pad$1(woodRoadDragMidpoint, padding, context);
60908 var advance = function() { continueTo(addNode); };
60910 reveal(box, t('intro.lines.update_line'),
60911 { buttonText: t('intro.ok'), buttonCallback: advance }
60914 context.map().on('move.intro drawn.intro', function() {
60915 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
60916 var box = pad$1(woodRoadDragMidpoint, padding, context);
60917 reveal(box, t('intro.lines.update_line'),
60918 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
60923 function continueTo(nextStep) {
60924 context.map().on('move.intro drawn.intro', null);
60930 function addNode() {
60931 context.history().reset('doneAddLine');
60932 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60933 return chapter.restart();
60936 var padding = 40 * Math.pow(2, context.map().zoom() - 19);
60937 var box = pad$1(woodRoadAddNode, padding, context);
60938 reveal(box, t('intro.lines.add_node'));
60940 context.map().on('move.intro drawn.intro', function() {
60941 var padding = 40 * Math.pow(2, context.map().zoom() - 19);
60942 var box = pad$1(woodRoadAddNode, padding, context);
60943 reveal(box, t('intro.lines.add_node'), { duration: 0 });
60946 context.history().on('change.intro', function(changed) {
60947 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60948 return continueTo(updateLine);
60950 if (changed.created().length === 1) {
60951 timeout$$1(function() { continueTo(startDragEndpoint); }, 500);
60955 context.on('enter.intro', function(mode) {
60956 if (mode.id !== 'select') {
60957 continueTo(updateLine);
60961 function continueTo(nextStep) {
60962 context.map().on('move.intro drawn.intro', null);
60963 context.history().on('change.intro', null);
60964 context.on('enter.intro', null);
60970 function startDragEndpoint() {
60971 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60972 return continueTo(updateLine);
60974 if (context.selectedIDs().indexOf(woodRoadId) === -1) {
60975 context.enter(modeSelect(context, [woodRoadId]));
60978 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
60979 var box = pad$1(woodRoadDragEndpoint, padding, context);
60980 reveal(box, t('intro.lines.start_drag_endpoint'));
60982 context.map().on('move.intro drawn.intro', function() {
60983 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60984 return continueTo(updateLine);
60986 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
60987 var box = pad$1(woodRoadDragEndpoint, padding, context);
60988 reveal(box, t('intro.lines.start_drag_endpoint'), { duration: 0 });
60990 var entity = context.entity(woodRoadEndId);
60991 if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) {
60992 continueTo(finishDragEndpoint);
60996 context.on('enter.intro', function(mode) {
60997 if (mode.id !== 'select') {
60998 // keep Wood Road selected so endpoint stays draggable..
60999 context.enter(modeSelect(context, [woodRoadId]));
61003 function continueTo(nextStep) {
61004 context.map().on('move.intro drawn.intro', null);
61005 context.on('enter.intro', null);
61011 function finishDragEndpoint() {
61012 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
61013 return continueTo(updateLine);
61016 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
61017 var box = pad$1(woodRoadDragEndpoint, padding, context);
61018 reveal(box, t('intro.lines.finish_drag_endpoint'));
61020 context.map().on('move.intro drawn.intro', function() {
61021 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
61022 return continueTo(updateLine);
61024 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
61025 var box = pad$1(woodRoadDragEndpoint, padding, context);
61026 reveal(box, t('intro.lines.finish_drag_endpoint'), { duration: 0 });
61028 var entity = context.entity(woodRoadEndId);
61029 if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) {
61030 continueTo(startDragEndpoint);
61034 context.on('enter.intro', function() {
61035 continueTo(startDragMidpoint);
61038 function continueTo(nextStep) {
61039 context.map().on('move.intro drawn.intro', null);
61040 context.on('enter.intro', null);
61046 function startDragMidpoint() {
61047 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
61048 return continueTo(updateLine);
61050 if (context.selectedIDs().indexOf(woodRoadId) === -1) {
61051 context.enter(modeSelect(context, [woodRoadId]));
61054 var padding = 80 * Math.pow(2, context.map().zoom() - 19);
61055 var box = pad$1(woodRoadDragMidpoint, padding, context);
61056 reveal(box, t('intro.lines.start_drag_midpoint'));
61058 context.map().on('move.intro drawn.intro', function() {
61059 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
61060 return continueTo(updateLine);
61062 var padding = 80 * Math.pow(2, context.map().zoom() - 19);
61063 var box = pad$1(woodRoadDragMidpoint, padding, context);
61064 reveal(box, t('intro.lines.start_drag_midpoint'), { duration: 0 });
61067 context.history().on('change.intro', function(changed) {
61068 if (changed.created().length === 1) {
61069 continueTo(continueDragMidpoint);
61073 context.on('enter.intro', function(mode) {
61074 if (mode.id !== 'select') {
61075 // keep Wood Road selected so midpoint triangles are drawn..
61076 context.enter(modeSelect(context, [woodRoadId]));
61080 function continueTo(nextStep) {
61081 context.map().on('move.intro drawn.intro', null);
61082 context.history().on('change.intro', null);
61083 context.on('enter.intro', null);
61089 function continueDragMidpoint() {
61090 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
61091 return continueTo(updateLine);
61094 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
61095 var box = pad$1(woodRoadDragEndpoint, padding, context);
61098 var advance = function() {
61099 context.history().checkpoint('doneUpdateLine');
61100 continueTo(deleteLines);
61103 reveal(box, t('intro.lines.continue_drag_midpoint'),
61104 { buttonText: t('intro.ok'), buttonCallback: advance }
61107 context.map().on('move.intro drawn.intro', function() {
61108 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
61109 return continueTo(updateLine);
61111 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
61112 var box = pad$1(woodRoadDragEndpoint, padding, context);
61114 reveal(box, t('intro.lines.continue_drag_midpoint'),
61115 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
61119 function continueTo(nextStep) {
61120 context.map().on('move.intro drawn.intro', null);
61126 function deleteLines() {
61127 context.history().reset('doneUpdateLine');
61128 context.enter(modeBrowse(context));
61130 if (!context.hasEntity(washingtonStreetId) ||
61131 !context.hasEntity(twelfthAvenueId) ||
61132 !context.hasEntity(eleventhAvenueEndId)) {
61133 return chapter.restart();
61136 var msec = transitionTime(deleteLinesLoc, context.map().center());
61137 if (msec) { reveal(null, null, { duration: 0 }); }
61138 context.map().zoom(18).centerEase(deleteLinesLoc, msec);
61140 timeout$$1(function() {
61141 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61142 var box = pad$1(deleteLinesLoc, padding, context);
61145 var advance = function() { continueTo(rightClickIntersection); };
61147 reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }),
61148 { buttonText: t('intro.ok'), buttonCallback: advance }
61151 context.map().on('move.intro drawn.intro', function() {
61152 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61153 var box = pad$1(deleteLinesLoc, padding, context);
61156 reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }),
61157 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
61161 context.history().on('change.intro', function() {
61162 timeout$$1(function() {
61163 continueTo(deleteLines);
61164 }, 500); // after any transition (e.g. if user deleted intersection)
61169 function continueTo(nextStep) {
61170 context.map().on('move.intro drawn.intro', null);
61171 context.history().on('change.intro', null);
61177 function rightClickIntersection() {
61178 context.history().reset('doneUpdateLine');
61179 context.enter(modeBrowse(context));
61181 context.map().zoom(18).centerEase(eleventhAvenueEnd, 500);
61183 timeout$$1(function() {
61184 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
61185 var box = pad$1(eleventhAvenueEnd, padding, context);
61186 reveal(box, t('intro.lines.rightclick_intersection',
61187 { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') })
61190 context.map().on('move.intro drawn.intro', function() {
61191 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
61192 var box = pad$1(eleventhAvenueEnd, padding, context);
61193 reveal(box, t('intro.lines.rightclick_intersection',
61194 { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') }),
61199 context.on('enter.intro', function(mode) {
61200 if (mode.id !== 'select') return;
61201 var ids = context.selectedIDs();
61202 if (ids.length !== 1 || ids[0] !== eleventhAvenueEndId) return;
61204 timeout$$1(function() {
61205 var node = selectMenuItem('split').node();
61207 continueTo(splitIntersection);
61208 }, 300); // after menu visible
61211 context.history().on('change.intro', function() {
61212 timeout$$1(function() {
61213 continueTo(deleteLines);
61214 }, 300); // after any transition (e.g. if user deleted intersection)
61219 function continueTo(nextStep) {
61220 context.map().on('move.intro drawn.intro', null);
61221 context.on('enter.intro', null);
61222 context.history().on('change.intro', null);
61228 function splitIntersection() {
61229 if (!context.hasEntity(washingtonStreetId) ||
61230 !context.hasEntity(twelfthAvenueId) ||
61231 !context.hasEntity(eleventhAvenueEndId)) {
61232 return continueTo(deleteLines);
61235 var node = selectMenuItem('split').node();
61236 if (!node) { return continueTo(rightClickIntersection); }
61238 var wasChanged = false;
61239 var menuCoords = context.map().mouseCoordinates();
61240 washingtonSegmentId = null;
61242 revealEditMenu(menuCoords, t('intro.lines.split_intersection',
61243 { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') })
61246 context.map().on('move.intro drawn.intro', function() {
61247 var node = selectMenuItem('split').node();
61248 if (!wasChanged && !node) { return continueTo(rightClickIntersection); }
61250 revealEditMenu(menuCoords, t('intro.lines.split_intersection',
61251 { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') }),
61256 context.history().on('change.intro', function(changed) {
61258 timeout$$1(function() {
61259 if (context.history().undoAnnotation() === t('operations.split.annotation.line')) {
61260 washingtonSegmentId = changed.created()[0].id;
61261 continueTo(didSplit);
61263 washingtonSegmentId = null;
61264 continueTo(retrySplit);
61266 }, 300); // after any transition (e.g. if user deleted intersection)
61269 function continueTo(nextStep) {
61270 context.map().on('move.intro drawn.intro', null);
61271 context.history().on('change.intro', null);
61277 function retrySplit() {
61278 context.enter(modeBrowse(context));
61279 context.map().zoom(18).centerEase(eleventhAvenueEnd, 500);
61280 var advance = function() { continueTo(rightClickIntersection); };
61282 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
61283 var box = pad$1(eleventhAvenueEnd, padding, context);
61284 reveal(box, t('intro.lines.retry_split'),
61285 { buttonText: t('intro.ok'), buttonCallback: advance }
61288 context.map().on('move.intro drawn.intro', function() {
61289 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
61290 var box = pad$1(eleventhAvenueEnd, padding, context);
61291 reveal(box, t('intro.lines.retry_split'),
61292 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
61296 function continueTo(nextStep) {
61297 context.map().on('move.intro drawn.intro', null);
61303 function didSplit() {
61304 if (!washingtonSegmentId ||
61305 !context.hasEntity(washingtonSegmentId) ||
61306 !context.hasEntity(washingtonStreetId) ||
61307 !context.hasEntity(twelfthAvenueId) ||
61308 !context.hasEntity(eleventhAvenueEndId)) {
61309 return continueTo(rightClickIntersection);
61312 var ids = context.selectedIDs();
61313 var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single');
61314 var street = t('intro.graph.name.washington-street');
61316 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61317 var box = pad$1(twelfthAvenue, padding, context);
61318 box.width = box.width / 2;
61319 reveal(box, t(string, { street1: street, street2: street }),
61323 timeout$$1(function() {
61324 context.map().zoom(18).centerEase(twelfthAvenue, 500);
61326 context.map().on('move.intro drawn.intro', function() {
61327 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61328 var box = pad$1(twelfthAvenue, padding, context);
61329 box.width = box.width / 2;
61330 reveal(box, t(string, { street1: street, street2: street }),
61334 }, 600); // after initial reveal and curtain cut
61336 context.on('enter.intro', function() {
61337 var ids = context.selectedIDs();
61338 if (ids.length === 1 && ids[0] === washingtonSegmentId) {
61339 continueTo(multiSelect);
61343 context.history().on('change.intro', function() {
61344 if (!washingtonSegmentId ||
61345 !context.hasEntity(washingtonSegmentId) ||
61346 !context.hasEntity(washingtonStreetId) ||
61347 !context.hasEntity(twelfthAvenueId) ||
61348 !context.hasEntity(eleventhAvenueEndId)) {
61349 return continueTo(rightClickIntersection);
61353 function continueTo(nextStep) {
61354 context.map().on('move.intro drawn.intro', null);
61355 context.on('enter.intro', null);
61356 context.history().on('change.intro', null);
61362 function multiSelect() {
61363 if (!washingtonSegmentId ||
61364 !context.hasEntity(washingtonSegmentId) ||
61365 !context.hasEntity(washingtonStreetId) ||
61366 !context.hasEntity(twelfthAvenueId) ||
61367 !context.hasEntity(eleventhAvenueEndId)) {
61368 return continueTo(rightClickIntersection);
61371 var ids = context.selectedIDs();
61372 var hasWashington = ids.indexOf(washingtonSegmentId) !== -1;
61373 var hasTwelfth = ids.indexOf(twelfthAvenueId) !== -1;
61375 if (hasWashington && hasTwelfth) {
61376 return continueTo(multiRightClick);
61377 } else if (!hasWashington && !hasTwelfth) {
61378 return continueTo(didSplit);
61381 context.map().zoom(18).centerEase(twelfthAvenue, 500);
61383 timeout$$1(function() {
61384 var selected, other, padding, box;
61385 if (hasWashington) {
61386 selected = t('intro.graph.name.washington-street');
61387 other = t('intro.graph.name.12th-avenue');
61388 padding = 60 * Math.pow(2, context.map().zoom() - 18);
61389 box = pad$1(twelfthAvenueEnd, padding, context);
61392 selected = t('intro.graph.name.12th-avenue');
61393 other = t('intro.graph.name.washington-street');
61394 padding = 200 * Math.pow(2, context.map().zoom() - 18);
61395 box = pad$1(twelfthAvenue, padding, context);
61400 t('intro.lines.multi_select', { selected: selected, other1: other, other2: other })
61403 context.map().on('move.intro drawn.intro', function() {
61404 if (hasWashington) {
61405 selected = t('intro.graph.name.washington-street');
61406 other = t('intro.graph.name.12th-avenue');
61407 padding = 60 * Math.pow(2, context.map().zoom() - 18);
61408 box = pad$1(twelfthAvenueEnd, padding, context);
61411 selected = t('intro.graph.name.12th-avenue');
61412 other = t('intro.graph.name.washington-street');
61413 padding = 200 * Math.pow(2, context.map().zoom() - 18);
61414 box = pad$1(twelfthAvenue, padding, context);
61419 t('intro.lines.multi_select', { selected: selected, other1: other, other2: other }),
61424 context.on('enter.intro', function() {
61425 continueTo(multiSelect);
61428 context.history().on('change.intro', function() {
61429 if (!washingtonSegmentId ||
61430 !context.hasEntity(washingtonSegmentId) ||
61431 !context.hasEntity(washingtonStreetId) ||
61432 !context.hasEntity(twelfthAvenueId) ||
61433 !context.hasEntity(eleventhAvenueEndId)) {
61434 return continueTo(rightClickIntersection);
61439 function continueTo(nextStep) {
61440 context.map().on('move.intro drawn.intro', null);
61441 context.on('enter.intro', null);
61442 context.history().on('change.intro', null);
61448 function multiRightClick() {
61449 if (!washingtonSegmentId ||
61450 !context.hasEntity(washingtonSegmentId) ||
61451 !context.hasEntity(washingtonStreetId) ||
61452 !context.hasEntity(twelfthAvenueId) ||
61453 !context.hasEntity(eleventhAvenueEndId)) {
61454 return continueTo(rightClickIntersection);
61457 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61458 var box = pad$1(twelfthAvenue, padding, context);
61459 reveal(box, t('intro.lines.multi_rightclick'));
61461 context.map().on('move.intro drawn.intro', function() {
61462 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61463 var box = pad$1(twelfthAvenue, padding, context);
61464 reveal(box, t('intro.lines.multi_rightclick'), { duration: 0 });
61467 select(window).on('click.intro contextmenu.intro', function() {
61468 timeout$$1(function() {
61469 var ids = context.selectedIDs();
61470 if (ids.length === 2 &&
61471 ids.indexOf(twelfthAvenueId) !== -1 &&
61472 ids.indexOf(washingtonSegmentId) !== -1) {
61473 var node = selectMenuItem('delete').node();
61475 continueTo(multiDelete);
61476 } else if (ids.length === 1 &&
61477 ids.indexOf(washingtonSegmentId) !== -1) {
61478 return continueTo(multiSelect);
61480 return continueTo(didSplit);
61482 }, 300); // after edit menu visible
61485 context.history().on('change.intro', function() {
61486 if (!washingtonSegmentId ||
61487 !context.hasEntity(washingtonSegmentId) ||
61488 !context.hasEntity(washingtonStreetId) ||
61489 !context.hasEntity(twelfthAvenueId) ||
61490 !context.hasEntity(eleventhAvenueEndId)) {
61491 return continueTo(rightClickIntersection);
61495 function continueTo(nextStep) {
61496 context.map().on('move.intro drawn.intro', null);
61497 select(window).on('click.intro contextmenu.intro', null, true);
61498 context.history().on('change.intro', null);
61504 function multiDelete() {
61505 if (!washingtonSegmentId ||
61506 !context.hasEntity(washingtonSegmentId) ||
61507 !context.hasEntity(washingtonStreetId) ||
61508 !context.hasEntity(twelfthAvenueId) ||
61509 !context.hasEntity(eleventhAvenueEndId)) {
61510 return continueTo(rightClickIntersection);
61513 var node = selectMenuItem('delete').node();
61514 if (!node) return continueTo(multiRightClick);
61516 var menuCoords = context.map().mouseCoordinates();
61517 revealEditMenu(menuCoords,
61518 t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') })
61521 context.map().on('move.intro drawn.intro', function() {
61522 revealEditMenu(menuCoords,
61523 t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') }),
61528 context.on('exit.intro', function() {
61529 if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) {
61530 return continueTo(multiSelect); // left select mode but roads still exist
61534 context.history().on('change.intro', function() {
61535 if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) {
61536 continueTo(retryDelete); // changed something but roads still exist
61542 function continueTo(nextStep) {
61543 context.map().on('move.intro drawn.intro', null);
61544 context.on('exit.intro', null);
61545 context.history().on('change.intro', null);
61551 function retryDelete() {
61552 context.enter(modeBrowse(context));
61554 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61555 var box = pad$1(twelfthAvenue, padding, context);
61556 reveal(box, t('intro.lines.retry_delete'), {
61557 buttonText: t('intro.ok'),
61558 buttonCallback: function() { continueTo(multiSelect); }
61561 function continueTo(nextStep) {
61568 dispatch$$1.call('done');
61569 reveal('#id-container',
61570 t('intro.lines.play', { next: t('intro.buildings.title') }), {
61571 tooltipBox: '.intro-nav-wrap .chapter-building',
61572 buttonText: t('intro.ok'),
61573 buttonCallback: function() { reveal('#id-container'); }
61579 chapter.enter = function() {
61584 chapter.exit = function() {
61585 timeouts.forEach(window.clearTimeout);
61586 select(window).on('mousedown.intro', null, true);
61587 context.on('enter.intro exit.intro', null);
61588 context.map().on('move.intro drawn.intro', null);
61589 context.history().on('change.intro', null);
61590 select('.inspector-wrap').on('wheel.intro', null);
61591 select('.preset-list-button').on('click.intro', null);
61595 chapter.restart = function() {
61601 return utilRebind(chapter, dispatch$$1, 'on');
61604 function uiIntroBuilding(context, reveal) {
61605 var dispatch$$1 = dispatch('done'),
61606 house = [-85.62815, 41.95638],
61607 tank = [-85.62732, 41.95347],
61608 buildingCatetory = context.presets().item('category-building'),
61609 housePreset = context.presets().item('building/house'),
61610 tankPreset = context.presets().item('man_made/storage_tank'),
61617 title: 'intro.buildings.title'
61621 function timeout$$1(f, t$$1) {
61622 timeouts.push(window.setTimeout(f, t$$1));
61626 function eventCancel() {
61627 event.stopPropagation();
61628 event.preventDefault();
61632 function revealHouse(center, text$$1, options) {
61633 var padding = 160 * Math.pow(2, context.map().zoom() - 20);
61634 var box = pad$1(center, padding, context);
61635 reveal(box, text$$1, options);
61639 function revealTank(center, text$$1, options) {
61640 var padding = 190 * Math.pow(2, context.map().zoom() - 19.5);
61641 var box = pad$1(center, padding, context);
61642 reveal(box, text$$1, options);
61646 function revealEditMenu(loc, text$$1, options) {
61647 var rect = context.surfaceRect();
61648 var point = context.curtainProjection(loc);
61650 var width = 250 + (2 * pad$$1);
61652 var startX = rect.left + point[0];
61653 var left = (textDirection === 'rtl') ? (startX - width + pad$$1) : (startX - pad$$1);
61656 top: point[1] + rect.top - 60,
61660 reveal(box, text$$1, options);
61664 function addHouse() {
61665 context.enter(modeBrowse(context));
61666 context.history().reset('initial');
61669 var msec = transitionTime(house, context.map().center());
61670 if (msec) { reveal(null, null, { duration: 0 }); }
61671 context.map().zoom(19).centerEase(house, msec);
61673 timeout$$1(function() {
61674 var tooltip = reveal('button.add-area',
61675 t('intro.buildings.add_building', { button: icon('#icon-area', 'pre-text') }));
61677 tooltip.selectAll('.tooltip-inner')
61678 .insert('svg', 'span')
61679 .attr('class', 'tooltip-illustration')
61681 .attr('xlink:href', '#building-images');
61683 context.on('enter.intro', function(mode) {
61684 if (mode.id !== 'add-area') return;
61685 continueTo(startHouse);
61689 function continueTo(nextStep) {
61690 context.on('enter.intro', null);
61696 function startHouse() {
61697 if (context.mode().id !== 'add-area') {
61698 return continueTo(addHouse);
61702 context.map().zoomEase(20, 500);
61704 timeout$$1(function() {
61705 revealHouse(house, t('intro.buildings.start_building'));
61707 context.map().on('move.intro drawn.intro', function() {
61708 revealHouse(house, t('intro.buildings.start_building'), { duration: 0 });
61711 context.on('enter.intro', function(mode) {
61712 if (mode.id !== 'draw-area') return chapter.restart();
61713 continueTo(continueHouse);
61716 }, 550); // after easing
61718 function continueTo(nextStep) {
61719 context.map().on('move.intro drawn.intro', null);
61720 context.on('enter.intro', null);
61726 function continueHouse() {
61727 if (context.mode().id !== 'draw-area') {
61728 return continueTo(addHouse);
61733 revealHouse(house, t('intro.buildings.continue_building'));
61735 context.map().on('move.intro drawn.intro', function() {
61736 revealHouse(house, t('intro.buildings.continue_building'), { duration: 0 });
61739 context.on('enter.intro', function(mode) {
61740 if (mode.id === 'draw-area') {
61742 } else if (mode.id === 'select') {
61743 var graph = context.graph(),
61744 way = context.entity(context.selectedIDs()[0]),
61745 nodes = graph.childNodes(way),
61746 points = lodash.uniq(nodes).map(function(n) { return context.projection(n.loc); });
61748 if (isMostlySquare(points)) {
61750 return continueTo(chooseCategoryBuilding);
61752 return continueTo(retryHouse);
61756 return chapter.restart();
61760 function continueTo(nextStep) {
61761 context.map().on('move.intro drawn.intro', null);
61762 context.on('enter.intro', null);
61768 function retryHouse() {
61769 var onClick = function() { continueTo(addHouse); };
61771 revealHouse(house, t('intro.buildings.retry_building'),
61772 { buttonText: t('intro.ok'), buttonCallback: onClick }
61775 context.map().on('move.intro drawn.intro', function() {
61776 revealHouse(house, t('intro.buildings.retry_building'),
61777 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
61781 function continueTo(nextStep) {
61782 context.map().on('move.intro drawn.intro', null);
61788 function chooseCategoryBuilding() {
61789 if (!houseId || !context.hasEntity(houseId)) {
61792 var ids = context.selectedIDs();
61793 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
61794 context.enter(modeSelect(context, [houseId]));
61797 // disallow scrolling
61798 select('.inspector-wrap').on('wheel.intro', eventCancel);
61800 timeout$$1(function() {
61801 // reset pane, in case user somehow happened to change it..
61802 select('.inspector-wrap .panewrap').style('right', '-100%');
61804 var button = select('.preset-category-building .preset-list-button');
61806 reveal(button.node(),
61807 t('intro.buildings.choose_category_building', { category: buildingCatetory.name() })
61810 button.on('click.intro', function() {
61811 button.on('click.intro', null);
61812 continueTo(choosePresetHouse);
61815 }, 400); // after preset list pane visible..
61818 context.on('enter.intro', function(mode) {
61819 if (!houseId || !context.hasEntity(houseId)) {
61820 return continueTo(addHouse);
61822 var ids = context.selectedIDs();
61823 if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) {
61824 return continueTo(chooseCategoryBuilding);
61828 function continueTo(nextStep) {
61829 select('.inspector-wrap').on('wheel.intro', null);
61830 select('.preset-list-button').on('click.intro', null);
61831 context.on('enter.intro', null);
61837 function choosePresetHouse() {
61838 if (!houseId || !context.hasEntity(houseId)) {
61841 var ids = context.selectedIDs();
61842 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
61843 context.enter(modeSelect(context, [houseId]));
61846 // disallow scrolling
61847 select('.inspector-wrap').on('wheel.intro', eventCancel);
61849 timeout$$1(function() {
61850 // reset pane, in case user somehow happened to change it..
61851 select('.inspector-wrap .panewrap').style('right', '-100%');
61853 var button = select('.preset-building-house .preset-list-button');
61855 reveal(button.node(),
61856 t('intro.buildings.choose_preset_house', { preset: housePreset.name() }),
61860 button.on('click.intro', function() {
61861 button.on('click.intro', null);
61862 continueTo(closeEditorHouse);
61866 }, 400); // after preset list pane visible..
61868 context.on('enter.intro', function(mode) {
61869 if (!houseId || !context.hasEntity(houseId)) {
61870 return continueTo(addHouse);
61872 var ids = context.selectedIDs();
61873 if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) {
61874 return continueTo(chooseCategoryBuilding);
61878 function continueTo(nextStep) {
61879 select('.inspector-wrap').on('wheel.intro', null);
61880 select('.preset-list-button').on('click.intro', null);
61881 context.on('enter.intro', null);
61887 function closeEditorHouse() {
61888 if (!houseId || !context.hasEntity(houseId)) {
61891 var ids = context.selectedIDs();
61892 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
61893 context.enter(modeSelect(context, [houseId]));
61896 context.history().checkpoint('hasHouse');
61898 context.on('exit.intro', function() {
61899 continueTo(rightClickHouse);
61902 timeout$$1(function() {
61903 reveal('.entity-editor-pane',
61904 t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') })
61908 function continueTo(nextStep) {
61909 context.on('exit.intro', null);
61915 function rightClickHouse() {
61916 if (!houseId) return chapter.restart();
61918 context.enter(modeBrowse(context));
61919 context.history().reset('hasHouse');
61920 context.map().centerEase(house, 500);
61922 timeout$$1(function() {
61923 if (context.map().zoom() < 20) {
61924 context.map().zoomEase(20, 500);
61928 context.on('enter.intro', function(mode) {
61929 if (mode.id !== 'select') return;
61930 var ids = context.selectedIDs();
61931 if (ids.length !== 1 || ids[0] !== houseId) return;
61933 timeout$$1(function() {
61934 var node = selectMenuItem('orthogonalize').node();
61936 continueTo(clickSquare);
61937 }, 300); // after menu visible
61940 context.map().on('move.intro drawn.intro', function() {
61941 revealHouse(house, t('intro.buildings.rightclick_building'), { duration: 0 });
61944 context.history().on('change.intro', function() {
61945 continueTo(rightClickHouse);
61948 function continueTo(nextStep) {
61949 context.on('enter.intro', null);
61950 context.map().on('move.intro drawn.intro', null);
61951 context.history().on('change.intro', null);
61957 function clickSquare() {
61958 if (!houseId) return chapter.restart();
61959 var entity = context.hasEntity(houseId);
61960 if (!entity) return continueTo(rightClickHouse);
61962 var node = selectMenuItem('orthogonalize').node();
61963 if (!node) { return continueTo(rightClickHouse); }
61965 var wasChanged = false;
61966 var menuCoords = context.map().mouseCoordinates();
61968 revealEditMenu(menuCoords,
61969 t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') })
61972 context.on('enter.intro', function(mode) {
61973 if (mode.id === 'browse') {
61974 continueTo(rightClickHouse);
61975 } else if (mode.id === 'move' || mode.id === 'rotate') {
61976 continueTo(retryClickSquare);
61980 context.map().on('move.intro drawn.intro', function() {
61981 var node = selectMenuItem('orthogonalize').node();
61982 if (!wasChanged && !node) { return continueTo(rightClickHouse); }
61984 revealEditMenu(menuCoords,
61985 t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') }),
61990 context.history().on('change.intro', function() {
61992 context.history().on('change.intro', null);
61994 // Something changed. Wait for transition to complete and check undo annotation.
61995 timeout$$1(function() {
61996 if (context.history().undoAnnotation() === t('operations.orthogonalize.annotation.area')) {
61997 continueTo(doneSquare);
61999 continueTo(retryClickSquare);
62001 }, 500); // after transitioned actions
62004 function continueTo(nextStep) {
62005 context.on('enter.intro', null);
62006 context.map().on('move.intro drawn.intro', null);
62007 context.history().on('change.intro', null);
62013 function retryClickSquare() {
62014 context.enter(modeBrowse(context));
62016 revealHouse(house, t('intro.buildings.retry_square'), {
62017 buttonText: t('intro.ok'),
62018 buttonCallback: function() { continueTo(rightClickHouse); }
62021 function continueTo(nextStep) {
62027 function doneSquare() {
62028 context.history().checkpoint('doneSquare');
62030 revealHouse(house, t('intro.buildings.done_square'), {
62031 buttonText: t('intro.ok'),
62032 buttonCallback: function() { continueTo(addTank); }
62035 function continueTo(nextStep) {
62041 function addTank() {
62042 context.enter(modeBrowse(context));
62043 context.history().reset('doneSquare');
62046 var msec = transitionTime(tank, context.map().center());
62047 if (msec) { reveal(null, null, { duration: 0 }); }
62048 context.map().zoom(19.5).centerEase(tank, msec);
62050 timeout$$1(function() {
62051 reveal('button.add-area',
62052 t('intro.buildings.add_tank', { button: icon('#icon-area', 'pre-text') })
62055 context.on('enter.intro', function(mode) {
62056 if (mode.id !== 'add-area') return;
62057 continueTo(startTank);
62061 function continueTo(nextStep) {
62062 context.on('enter.intro', null);
62068 function startTank() {
62069 if (context.mode().id !== 'add-area') {
62070 return continueTo(addTank);
62075 timeout$$1(function() {
62076 revealTank(tank, t('intro.buildings.start_tank'));
62078 context.map().on('move.intro drawn.intro', function() {
62079 revealTank(tank, t('intro.buildings.start_tank'), { duration: 0 });
62082 context.on('enter.intro', function(mode) {
62083 if (mode.id !== 'draw-area') return chapter.restart();
62084 continueTo(continueTank);
62087 }, 550); // after easing
62089 function continueTo(nextStep) {
62090 context.map().on('move.intro drawn.intro', null);
62091 context.on('enter.intro', null);
62097 function continueTank() {
62098 if (context.mode().id !== 'draw-area') {
62099 return continueTo(addTank);
62104 revealTank(tank, t('intro.buildings.continue_tank'));
62106 context.map().on('move.intro drawn.intro', function() {
62107 revealTank(tank, t('intro.buildings.continue_tank'), { duration: 0 });
62110 context.on('enter.intro', function(mode) {
62111 if (mode.id === 'draw-area') {
62113 } else if (mode.id === 'select') {
62114 tankId = context.selectedIDs()[0];
62115 return continueTo(searchPresetTank);
62117 return continueTo(addTank);
62121 function continueTo(nextStep) {
62122 context.map().on('move.intro drawn.intro', null);
62123 context.on('enter.intro', null);
62129 function searchPresetTank() {
62130 if (!tankId || !context.hasEntity(tankId)) {
62133 var ids = context.selectedIDs();
62134 if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) {
62135 context.enter(modeSelect(context, [tankId]));
62138 // disallow scrolling
62139 select('.inspector-wrap').on('wheel.intro', eventCancel);
62141 timeout$$1(function() {
62142 // reset pane, in case user somehow happened to change it..
62143 select('.inspector-wrap .panewrap').style('right', '-100%');
62145 select('.preset-search-input')
62146 .on('keydown.intro', null)
62147 .on('keyup.intro', checkPresetSearch);
62149 reveal('.preset-search-input',
62150 t('intro.buildings.search_tank', { preset: tankPreset.name() })
62152 }, 400); // after preset list pane visible..
62154 context.on('enter.intro', function(mode) {
62155 if (!tankId || !context.hasEntity(tankId)) {
62156 return continueTo(addTank);
62159 var ids = context.selectedIDs();
62160 if (mode.id !== 'select' || !ids.length || ids[0] !== tankId) {
62161 // keep the user's area selected..
62162 context.enter(modeSelect(context, [tankId]));
62164 // reset pane, in case user somehow happened to change it..
62165 select('.inspector-wrap .panewrap').style('right', '-100%');
62166 // disallow scrolling
62167 select('.inspector-wrap').on('wheel.intro', eventCancel);
62169 select('.preset-search-input')
62170 .on('keydown.intro', null)
62171 .on('keyup.intro', checkPresetSearch);
62173 reveal('.preset-search-input',
62174 t('intro.buildings.search_tank', { preset: tankPreset.name() })
62177 context.history().on('change.intro', null);
62181 function checkPresetSearch() {
62182 var first = select('.preset-list-item:first-child');
62184 if (first.classed('preset-man_made-storage_tank')) {
62185 reveal(first.select('.preset-list-button').node(),
62186 t('intro.buildings.choose_tank', { preset: tankPreset.name() }),
62190 select('.preset-search-input')
62191 .on('keydown.intro', eventCancel, true)
62192 .on('keyup.intro', null);
62194 context.history().on('change.intro', function() {
62195 continueTo(closeEditorTank);
62200 function continueTo(nextStep) {
62201 select('.inspector-wrap').on('wheel.intro', null);
62202 context.on('enter.intro', null);
62203 context.history().on('change.intro', null);
62204 select('.preset-search-input').on('keydown.intro keyup.intro', null);
62210 function closeEditorTank() {
62211 if (!tankId || !context.hasEntity(tankId)) {
62214 var ids = context.selectedIDs();
62215 if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) {
62216 context.enter(modeSelect(context, [tankId]));
62219 context.history().checkpoint('hasTank');
62221 context.on('exit.intro', function() {
62222 continueTo(rightClickTank);
62225 timeout$$1(function() {
62226 reveal('.entity-editor-pane',
62227 t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') })
62231 function continueTo(nextStep) {
62232 context.on('exit.intro', null);
62238 function rightClickTank() {
62239 if (!tankId) return continueTo(addTank);
62241 context.enter(modeBrowse(context));
62242 context.history().reset('hasTank');
62243 context.map().centerEase(tank, 500);
62245 timeout$$1(function() {
62246 context.on('enter.intro', function(mode) {
62247 if (mode.id !== 'select') return;
62248 var ids = context.selectedIDs();
62249 if (ids.length !== 1 || ids[0] !== tankId) return;
62251 timeout$$1(function() {
62252 var node = selectMenuItem('circularize').node();
62254 continueTo(clickCircle);
62255 }, 300); // after menu visible
62258 revealTank(tank, t('intro.buildings.rightclick_tank'));
62260 context.map().on('move.intro drawn.intro', function() {
62261 revealTank(tank, t('intro.buildings.rightclick_tank'), { duration: 0 });
62264 context.history().on('change.intro', function() {
62265 continueTo(rightClickTank);
62270 function continueTo(nextStep) {
62271 context.on('enter.intro', null);
62272 context.map().on('move.intro drawn.intro', null);
62273 context.history().on('change.intro', null);
62279 function clickCircle() {
62280 if (!tankId) return chapter.restart();
62281 var entity = context.hasEntity(tankId);
62282 if (!entity) return continueTo(rightClickTank);
62284 var node = selectMenuItem('circularize').node();
62285 if (!node) { return continueTo(rightClickTank); }
62287 var wasChanged = false;
62288 var menuCoords = context.map().mouseCoordinates();
62290 revealEditMenu(menuCoords,
62291 t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') })
62294 context.on('enter.intro', function(mode) {
62295 if (mode.id === 'browse') {
62296 continueTo(rightClickTank);
62297 } else if (mode.id === 'move' || mode.id === 'rotate') {
62298 continueTo(retryClickCircle);
62302 context.map().on('move.intro drawn.intro', function() {
62303 var node = selectMenuItem('circularize').node();
62304 if (!wasChanged && !node) { return continueTo(rightClickTank); }
62306 revealEditMenu(menuCoords,
62307 t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') }),
62312 context.history().on('change.intro', function() {
62314 context.history().on('change.intro', null);
62316 // Something changed. Wait for transition to complete and check undo annotation.
62317 timeout$$1(function() {
62318 if (context.history().undoAnnotation() === t('operations.circularize.annotation.area')) {
62321 continueTo(retryClickCircle);
62323 }, 500); // after transitioned actions
62326 function continueTo(nextStep) {
62327 context.on('enter.intro', null);
62328 context.map().on('move.intro drawn.intro', null);
62329 context.history().on('change.intro', null);
62335 function retryClickCircle() {
62336 context.enter(modeBrowse(context));
62338 revealTank(tank, t('intro.buildings.retry_circle'), {
62339 buttonText: t('intro.ok'),
62340 buttonCallback: function() { continueTo(rightClickTank); }
62343 function continueTo(nextStep) {
62350 dispatch$$1.call('done');
62351 reveal('#id-container',
62352 t('intro.buildings.play', { next: t('intro.startediting.title') }), {
62353 tooltipBox: '.intro-nav-wrap .chapter-startEditing',
62354 buttonText: t('intro.ok'),
62355 buttonCallback: function() { reveal('#id-container'); }
62361 chapter.enter = function() {
62366 chapter.exit = function() {
62367 timeouts.forEach(window.clearTimeout);
62368 context.on('enter.intro exit.intro', null);
62369 context.map().on('move.intro drawn.intro', null);
62370 context.history().on('change.intro', null);
62371 select('.inspector-wrap').on('wheel.intro', null);
62372 select('.preset-search-input').on('keydown.intro keyup.intro', null);
62373 select('.more-fields .combobox-input').on('click.intro', null);
62377 chapter.restart = function() {
62383 return utilRebind(chapter, dispatch$$1, 'on');
62386 function uiIntroStartEditing(context, reveal) {
62387 var dispatch$$1 = dispatch('done', 'startEditing'),
62388 modalSelection = select(null);
62392 title: 'intro.startediting.title'
62396 function showHelp() {
62397 reveal('.map-control.help-control',
62398 t('intro.startediting.help', { button: icon('#icon-help', 'pre-text') }), {
62399 buttonText: t('intro.ok'),
62400 buttonCallback: function() { showSave(); }
62405 function showSave() {
62406 reveal('#bar button.save',
62407 t('intro.startediting.save'), {
62408 buttonText: t('intro.ok'),
62409 buttonCallback: function() { showStart(); }
62414 function showStart() {
62415 modalSelection = uiModal(context.container());
62417 modalSelection.select('.modal')
62418 .attr('class', 'modal-splash modal col6');
62420 modalSelection.selectAll('.close').remove();
62422 var startbutton = modalSelection.select('.content')
62423 .attr('class', 'fillL')
62425 .attr('class', 'modal-section huge-modal-button')
62426 .on('click', function() {
62427 modalSelection.remove();
62432 .attr('class', 'illustration')
62434 .attr('xlink:href', '#logo-walkthrough');
62438 .text(t('intro.startediting.start'));
62440 dispatch$$1.call('startEditing');
62444 chapter.enter = function() {
62449 chapter.exit = function() {
62450 modalSelection.remove();
62454 return utilRebind(chapter, dispatch$$1, 'on');
62458 welcome: uiIntroWelcome,
62459 navigation: uiIntroNavigation,
62460 point: uiIntroPoint,
62463 building: uiIntroBuilding,
62464 startEditing: uiIntroStartEditing
62467 var chapterFlow = [
62478 function uiIntro(context) {
62479 var introGraph = {},
62483 // create entities for intro graph and localize names
62484 for (var id in dataIntroGraph) {
62485 introGraph[id] = osmEntity$$1(localize(dataIntroGraph[id]));
62489 function intro(selection$$1) {
62490 context.enter(modeBrowse(context));
62492 // Save current map state
62493 var history = context.history().toJSON(),
62494 hash = window.location.hash,
62495 center = context.map().center(),
62496 zoom$$1 = context.map().zoom(),
62497 background = context.background().baseLayerSource(),
62498 overlays = context.background().overlayLayerSources(),
62499 opacity = selectAll('#map .layer-background').style('opacity'),
62500 loadedTiles = context.connection().loadedTiles(),
62501 baseEntities = context.history().graph().base().entities,
62502 countryCode = services.geocoder.countryCode;
62505 context.inIntro(true);
62507 // Load semi-real data used in intro
62508 context.connection().toggle(false).reset();
62509 context.history().reset();
62510 context.history().merge(values(coreGraph$$1().load(introGraph).entities));
62511 context.history().checkpoint('initial');
62512 context.background().bing();
62513 overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });
62516 services.geocoder.countryCode = function(location, callback) {
62517 callback(null, t('intro.graph.countrycode'));
62520 selectAll('#map .layer-background').style('opacity', 1);
62522 var curtain = uiCurtain();
62523 selection$$1.call(curtain);
62525 var chapters = chapterFlow.map(function(chapter, i) {
62526 var s = chapterUi[chapter](context, curtain.reveal)
62527 .on('done', function() {
62528 context.presets().init(); // clear away "recent" presets
62530 buttons.filter(function(d) {
62531 return d.title === s.title;
62532 }).classed('finished', true);
62534 if (i < chapterFlow.length - 1) {
62535 var next = chapterFlow[i + 1];
62536 select('button.chapter-' + next)
62537 .classed('next', true);
62543 chapters[chapters.length - 1].on('startEditing', function() {
62546 selectAll('#map .layer-background').style('opacity', opacity);
62547 context.connection().toggle(true).reset().loadedTiles(loadedTiles);
62548 context.history().reset().merge(values(baseEntities));
62549 context.background().baseLayerSource(background);
62550 overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });
62551 if (history) context.history().fromJSON(history, false);
62552 context.map().centerZoom(center, zoom$$1);
62553 window.location.replace(hash);
62554 services.geocoder.countryCode = countryCode;
62555 context.inIntro(false);
62558 var navwrap = selection$$1
62560 .attr('class', 'intro-nav-wrap fillD');
62564 .attr('class', 'intro-nav-wrap-logo')
62566 .attr('xlink:href', '#logo-walkthrough');
62568 var buttonwrap = navwrap
62570 .attr('class', 'joined')
62571 .selectAll('button.chapter');
62573 var buttons = buttonwrap
62577 .attr('class', function(d, i) { return 'chapter chapter-' + chapterFlow[i]; })
62578 .on('click', enterChapter);
62582 .text(function(d) { return t(d.title); });
62586 .attr('class', 'status')
62587 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'));
62589 enterChapter(chapters[0]);
62592 function enterChapter(newChapter) {
62593 if (currChapter) { currChapter.exit(); }
62594 context.enter(modeBrowse(context));
62596 currChapter = newChapter;
62597 currChapter.enter();
62600 .classed('next', false)
62601 .classed('active', function(d) {
62602 return d.title === currChapter.title;
62611 function uiHelp(context) {
62616 'help.editing_saving',
62625 var docs = docKeys.map(function(key) {
62626 var text$$1 = t(key);
62628 title: text$$1.split('\n')[0].replace('#', '').trim(),
62629 html: marked(text$$1.split('\n').slice(1).join('\n'))
62634 function help(selection$$1) {
62641 function toggle() {
62642 if (event) event.preventDefault();
62643 tooltipBehavior.hide(button);
62644 setVisible(!button.classed('active'));
62648 function setVisible(show) {
62649 if (show !== shown) {
62650 button.classed('active', show);
62654 selection$$1.on('mousedown.help-inside', function() {
62655 return event.stopPropagation();
62657 pane.style('display', 'block')
62658 .style('right', '-500px')
62661 .style('right', '0px');
62663 pane.style('right', '0px')
62666 .style('right', '-500px')
62667 .on('end', function() {
62668 select(this).style('display', 'none');
62670 selection$$1.on('mousedown.help-inside', null);
62676 function clickHelp(d, i) {
62677 var rtl = (textDirection === 'rtl');
62678 pane.property('scrollTop', 0);
62679 doctitle.html(d.title);
62682 body.selectAll('a')
62683 .attr('target', '_blank');
62684 menuItems.classed('selected', function(m) {
62685 return m.title === d.title;
62690 nav.call(drawNext).call(drawPrevious);
62692 nav.call(drawPrevious).call(drawNext);
62696 function drawNext(selection$$1) {
62697 if (i < docs.length - 1) {
62698 var nextLink = selection$$1
62700 .attr('class', 'next')
62701 .on('click', function() {
62702 clickHelp(docs[i + 1], i + 1);
62707 .text(docs[i + 1].title)
62708 .call(svgIcon((rtl ? '#icon-backward' : '#icon-forward'), 'inline'));
62713 function drawPrevious(selection$$1) {
62715 var prevLink = selection$$1
62717 .attr('class', 'previous')
62718 .on('click', function() {
62719 clickHelp(docs[i - 1], i - 1);
62723 .call(svgIcon((rtl ? '#icon-forward' : '#icon-backward'), 'inline'))
62725 .text(docs[i - 1].title);
62731 function clickWalkthrough() {
62732 if (context.inIntro()) return;
62733 context.container().call(uiIntro(context));
62738 var pane = selection$$1.append('div')
62739 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
62740 tooltipBehavior = tooltip()
62741 .placement((textDirection === 'rtl') ? 'right' : 'left')
62743 .title(uiTooltipHtml(t('help.title'), key)),
62744 button = selection$$1.append('button')
62745 .attr('tabindex', -1)
62746 .on('click', toggle)
62747 .call(svgIcon('#icon-help', 'light'))
62748 .call(tooltipBehavior),
62752 var toc = pane.append('ul')
62753 .attr('class', 'toc');
62755 var menuItems = toc.selectAll('li')
62760 .html(function(d) { return d.title; })
62761 .on('click', clickHelp);
62763 var walkthrough = toc
62765 .attr('class', 'walkthrough')
62767 .on('click', clickWalkthrough);
62771 .attr('class', 'logo logo-walkthrough')
62773 .attr('xlink:href', '#logo-walkthrough');
62777 .text(t('splash.walkthrough'));
62780 var content = pane.append('div')
62781 .attr('class', 'left-content');
62783 var doctitle = content.append('h2')
62784 .text(t('help.title'));
62786 var body = content.append('div')
62787 .attr('class', 'body');
62789 var nav = content.append('div')
62790 .attr('class', 'nav');
62792 clickHelp(docs[0], 0);
62794 var keybinding = d3keybinding('help')
62802 context.surface().on('mousedown.help-outside', hide);
62803 context.container().on('mousedown.help-outside', hide);
62809 function uiInfo(context) {
62810 var key = uiCmd('⌘I'),
62811 isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
62815 function info(selection$$1) {
62817 function radiansToMeters(r) {
62818 // using WGS84 authalic radius (6371007.1809 m)
62819 return r * 6371007.1809;
62822 function steradiansToSqmeters(r) {
62823 // http://gis.stackexchange.com/a/124857/40446
62824 return r / (4 * Math.PI) * 510065621724000;
62828 function toLineString(feature) {
62829 if (feature.type === 'LineString') return feature;
62831 var result = { type: 'LineString', coordinates: [] };
62832 if (feature.type === 'Polygon') {
62833 result.coordinates = feature.coordinates[0];
62834 } else if (feature.type === 'MultiPolygon') {
62835 result.coordinates = feature.coordinates[0][0];
62842 function displayLength(m) {
62843 var d = m * (isImperial ? 3.28084 : 1),
62862 // drop unnecessary precision
62863 p = d > 1000 ? 0 : d > 100 ? 1 : 2;
62865 return String(d.toFixed(p)) + ' ' + unit;
62869 function displayArea(m2) {
62870 var d = m2 * (isImperial ? 10.7639111056 : 1),
62871 d1, d2, p1, p2, unit1, unit2;
62874 if (d >= 6969600) { // > 0.25mi² show mi²
62882 if (d > 4356 && d < 43560000) { // 0.1 - 1000 acres
62888 if (d >= 250000) { // > 0.25km² show km²
62896 if (d > 1000 && d < 10000000) { // 0.1 - 1000 hectares
62902 // drop unnecessary precision
62903 p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
62904 p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
62906 return String(d1.toFixed(p1)) + ' ' + unit1 +
62907 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
62911 function redraw() {
62912 if (isHidden) return;
62914 var resolver = context.graph(),
62915 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
62916 singular = selected.length === 1 ? selected[0] : null,
62917 extent$$1 = geoExtent$$1(),
62922 .attr('class', 'infobox-heading fillD')
62923 .text(singular || t('infobox.selected', { n: selected.length }));
62925 if (!selected.length) return;
62928 for (var i = 0; i < selected.length; i++) {
62929 entity = context.entity(selected[i]);
62930 extent$$1._extend(entity.extent(resolver));
62932 center = extent$$1.center();
62935 var list = wrap.append('ul');
62937 // multiple features, just display extent center..
62940 .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
62944 // single feature, display details..
62945 if (!entity) return;
62946 var geometry = entity.geometry(resolver);
62948 if (geometry === 'line' || geometry === 'area') {
62949 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
62950 feature = entity.asGeoJSON(resolver),
62951 length = radiansToMeters(d3GeoLength(toLineString(feature))),
62952 lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
62953 centroid = d3GeoCentroid(feature);
62956 .text(t('infobox.geometry') + ': ' +
62957 (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
62960 var area$$1 = steradiansToSqmeters(entity.area(resolver));
62962 .text(t('infobox.area') + ': ' + displayArea(area$$1));
62966 .text(lengthLabel + ': ' + displayLength(length));
62969 .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
62972 var toggle = isImperial ? 'imperial' : 'metric';
62974 .text(t('infobox.' + toggle))
62976 .attr('class', 'button')
62977 .on('click', function() {
62978 event.preventDefault();
62979 isImperial = !isImperial;
62984 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
62987 .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
62990 .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
62995 function toggle() {
62997 event.preventDefault();
63000 isHidden = !isHidden;
63004 .style('display', 'block')
63005 .style('opacity', 1)
63008 .style('opacity', 0)
63009 .on('end', function() {
63010 select(this).style('display', 'none');
63014 .style('display', 'block')
63015 .style('opacity', 0)
63018 .style('opacity', 1)
63019 .on('end', function() {
63026 var wrap = selection$$1.selectAll('.infobox')
63029 wrap = wrap.enter()
63031 .attr('class', 'infobox fillD2')
63032 .style('display', (isHidden ? 'none' : 'block'))
63036 .on('drawn.info', redraw);
63040 var keybinding = d3keybinding('info')
63050 function uiMapData(context) {
63052 features = context.features().keys(),
63053 layers = context.layers(),
63054 fills = ['wireframe', 'partial', 'full'],
63055 fillDefault = context.storage('area-fill') || 'partial',
63056 fillSelected = fillDefault;
63059 function map_data(selection$$1) {
63061 function showsFeature(d) {
63062 return context.features().enabled(d);
63066 function autoHiddenFeature(d) {
63067 return context.features().autoHidden(d);
63071 function clickFeature(d) {
63072 context.features().toggle(d);
63077 function showsFill(d) {
63078 return fillSelected === d;
63082 function setFill(d) {
63083 lodash.each(fills, function(opt) {
63084 context.surface().classed('fill-' + opt, Boolean(opt === d));
63088 if (d !== 'wireframe') {
63090 context.storage('area-fill', d);
63096 function showsLayer(which) {
63097 var layer = layers.layer(which);
63099 return layer.enabled();
63105 function setLayer(which, enabled) {
63106 var layer = layers.layer(which);
63108 layer.enabled(enabled);
63114 function toggleLayer(which) {
63115 setLayer(which, !showsLayer(which));
63119 function clickGpx() {
63120 toggleLayer('gpx');
63124 function clickMapillaryImages() {
63125 toggleLayer('mapillary-images');
63126 if (!showsLayer('mapillary-images')) {
63127 setLayer('mapillary-signs', false);
63132 function clickMapillarySigns() {
63133 toggleLayer('mapillary-signs');
63137 function drawMapillaryItems(selection$$1) {
63138 var mapillaryImages = layers.layer('mapillary-images'),
63139 mapillarySigns = layers.layer('mapillary-signs'),
63140 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
63141 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
63142 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
63143 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
63145 var mapillaryList = selection$$1
63146 .selectAll('.layer-list-mapillary')
63149 mapillaryList = mapillaryList.enter()
63151 .attr('class', 'layer-list layer-list-mapillary')
63152 .merge(mapillaryList);
63155 var mapillaryImageLayerItem = mapillaryList
63156 .selectAll('.list-item-mapillary-images')
63157 .data(supportsMapillaryImages ? [0] : []);
63159 mapillaryImageLayerItem.exit()
63162 var enterImages = mapillaryImageLayerItem.enter()
63164 .attr('class', 'list-item-mapillary-images');
63166 var labelImages = enterImages
63169 .title(t('mapillary_images.tooltip'))
63170 .placement('top'));
63174 .attr('type', 'checkbox')
63175 .on('change', clickMapillaryImages);
63179 .text(t('mapillary_images.title'));
63182 var mapillarySignLayerItem = mapillaryList
63183 .selectAll('.list-item-mapillary-signs')
63184 .data(supportsMapillarySigns ? [0] : []);
63186 mapillarySignLayerItem.exit()
63189 var enterSigns = mapillarySignLayerItem.enter()
63191 .attr('class', 'list-item-mapillary-signs');
63193 var labelSigns = enterSigns
63196 .title(t('mapillary_signs.tooltip'))
63197 .placement('top'));
63201 .attr('type', 'checkbox')
63202 .on('change', clickMapillarySigns);
63206 .text(t('mapillary_signs.title'));
63210 mapillaryImageLayerItem = mapillaryImageLayerItem
63211 .merge(enterImages);
63213 mapillaryImageLayerItem
63214 .classed('active', showsMapillaryImages)
63215 .selectAll('input')
63216 .property('checked', showsMapillaryImages);
63219 mapillarySignLayerItem = mapillarySignLayerItem
63220 .merge(enterSigns);
63222 mapillarySignLayerItem
63223 .classed('active', showsMapillarySigns)
63224 .selectAll('input')
63225 .property('disabled', !showsMapillaryImages)
63226 .property('checked', showsMapillarySigns);
63228 mapillarySignLayerItem
63229 .selectAll('label')
63230 .classed('deemphasize', !showsMapillaryImages);
63234 function drawGpxItem(selection$$1) {
63235 var gpx = layers.layer('gpx'),
63236 hasGpx = gpx && gpx.hasGpx(),
63237 showsGpx = hasGpx && gpx.enabled();
63239 var gpxLayerItem = selection$$1
63240 .selectAll('.layer-list-gpx')
63241 .data(gpx ? [0] : []);
63244 gpxLayerItem.exit()
63248 var enter = gpxLayerItem.enter()
63250 .attr('class', 'layer-list layer-list-gpx')
63252 .classed('list-item-gpx', true);
63256 .attr('class', 'list-item-gpx-extent')
63258 .title(t('gpx.zoom'))
63259 .placement((textDirection === 'rtl') ? 'right' : 'left'))
63260 .on('click', function() {
63261 event.preventDefault();
63262 event.stopPropagation();
63265 .call(svgIcon('#icon-search'));
63269 .attr('class', 'list-item-gpx-browse')
63271 .title(t('gpx.browse'))
63272 .placement((textDirection === 'rtl') ? 'right' : 'left'))
63273 .on('click', function() {
63274 select(document.createElement('input'))
63275 .attr('type', 'file')
63276 .on('change', function() {
63277 gpx.files(event.target.files);
63281 .call(svgIcon('#icon-geolocate'));
63283 var labelGpx = enter
63285 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
63289 .attr('type', 'checkbox')
63290 .on('change', clickGpx);
63294 .text(t('gpx.local_layer'));
63298 gpxLayerItem = gpxLayerItem
63302 .classed('active', showsGpx)
63303 .selectAll('input')
63304 .property('disabled', !hasGpx)
63305 .property('checked', showsGpx);
63308 .selectAll('label')
63309 .classed('deemphasize', !hasGpx);
63313 function drawList(selection$$1, data, type, name, change, active$$1) {
63314 var items = selection$$1.selectAll('li')
63322 var enter = items.enter()
63324 .attr('class', 'layer')
63327 .title(function(d) {
63328 var tip = t(name + '.' + d + '.tooltip'),
63329 key = (d === 'wireframe' ? 'W' : null);
63331 if (name === 'feature' && autoHiddenFeature(d)) {
63332 tip += '<div>' + t('map_data.autohidden') + '</div>';
63334 return uiTooltipHtml(tip, key);
63344 .attr('type', type)
63345 .attr('name', name)
63346 .on('change', change);
63350 .text(function(d) { return t(name + '.' + d + '.description'); });
63357 .classed('active', active$$1)
63358 .selectAll('input')
63359 .property('checked', active$$1)
63360 .property('indeterminate', function(d) {
63361 return (name === 'feature' && autoHiddenFeature(d));
63366 function update() {
63367 dataLayerContainer.call(drawMapillaryItems);
63368 dataLayerContainer.call(drawGpxItem);
63370 fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
63371 featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
63375 function hidePanel() {
63380 function togglePanel() {
63381 if (event) event.preventDefault();
63382 tooltipBehavior.hide(button);
63383 setVisible(!button.classed('active'));
63387 function toggleWireframe() {
63389 event.preventDefault();
63390 event.stopPropagation();
63392 setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
63393 context.map().pan([0,0]); // trigger a redraw
63397 function setVisible(show) {
63398 if (show !== shown) {
63399 button.classed('active', show);
63404 selection$$1.on('mousedown.map_data-inside', function() {
63405 return event.stopPropagation();
63407 content.style('display', 'block')
63408 .style('right', '-300px')
63411 .style('right', '0px');
63413 content.style('display', 'block')
63414 .style('right', '0px')
63417 .style('right', '-300px')
63418 .on('end', function() {
63419 select(this).style('display', 'none');
63421 selection$$1.on('mousedown.map_data-inside', null);
63427 var content = selection$$1
63429 .attr('class', 'fillL map-overlay col3 content hide'),
63430 tooltipBehavior = tooltip()
63431 .placement((textDirection === 'rtl') ? 'right' : 'left')
63433 .title(uiTooltipHtml(t('map_data.description'), key)),
63434 button = selection$$1
63436 .attr('tabindex', -1)
63437 .on('click', togglePanel)
63438 .call(svgIcon('#icon-data', 'light'))
63439 .call(tooltipBehavior),
63444 .text(t('map_data.title'));
63450 .text(t('map_data.data_layers'))
63452 .classed('hide-toggle', true)
63453 .classed('expanded', true)
63454 .on('click', function() {
63455 var exp = select(this).classed('expanded');
63456 dataLayerContainer.style('display', exp ? 'none' : 'block');
63457 select(this).classed('expanded', !exp);
63458 event.preventDefault();
63461 var dataLayerContainer = content
63463 .attr('class', 'data-data-layers')
63464 .style('display', 'block');
63470 .text(t('map_data.fill_area'))
63472 .classed('hide-toggle', true)
63473 .classed('expanded', false)
63474 .on('click', function() {
63475 var exp = select(this).classed('expanded');
63476 fillContainer.style('display', exp ? 'none' : 'block');
63477 select(this).classed('expanded', !exp);
63478 event.preventDefault();
63481 var fillContainer = content
63483 .attr('class', 'data-area-fills')
63484 .style('display', 'none');
63486 var fillList = fillContainer
63488 .attr('class', 'layer-list layer-fill-list');
63494 .text(t('map_data.map_features'))
63496 .classed('hide-toggle', true)
63497 .classed('expanded', false)
63498 .on('click', function() {
63499 var exp = select(this).classed('expanded');
63500 featureContainer.style('display', exp ? 'none' : 'block');
63501 select(this).classed('expanded', !exp);
63502 event.preventDefault();
63505 var featureContainer = content
63507 .attr('class', 'data-feature-filters')
63508 .style('display', 'none');
63510 var featureList = featureContainer
63512 .attr('class', 'layer-list layer-feature-list');
63516 .on('change.map_data-update', update);
63518 setFill(fillDefault);
63520 var keybinding = d3keybinding('features')
63521 .on(key, togglePanel)
63522 .on('W', toggleWireframe)
63523 .on('B', hidePanel)
63524 .on('H', hidePanel);
63529 context.surface().on('mousedown.map_data-outside', hidePanel);
63530 context.container().on('mousedown.map_data-outside', hidePanel);
63537 function uiModes(context) {
63539 modeAddPoint$$1(context),
63540 modeAddLine$$1(context),
63541 modeAddArea$$1(context)
63545 function editable() {
63546 return context.editable() && context.mode().id !== 'save';
63550 return function(selection$$1) {
63551 var buttons = selection$$1.selectAll('button.add-button')
63554 buttons = buttons.enter()
63556 .attr('tabindex', -1)
63557 .attr('class', function(mode) { return mode.id + ' add-button col4'; })
63558 .on('click.mode-buttons', function(mode) {
63559 if (mode.id === context.mode().id) {
63560 context.enter(modeBrowse(context));
63562 context.enter(mode);
63566 .placement('bottom')
63568 .title(function(mode) {
63569 return uiTooltipHtml(mode.description, mode.key);
63574 .on('move.modes', lodash.debounce(update, 500));
63577 .on('enter.modes', update);
63580 .each(function(d) {
63582 .call(svgIcon('#icon-' + d.button, 'pre-text'));
63587 .attr('class', 'label')
63588 .text(function(mode) { return mode.title; });
63591 .on('enter.editor', function(entered) {
63592 selection$$1.selectAll('button.add-button')
63593 .classed('active', function(mode) { return entered.button === mode.button; });
63594 context.container()
63595 .classed('mode-' + entered.id, true);
63599 .on('exit.editor', function(exited) {
63600 context.container()
63601 .classed('mode-' + exited.id, false);
63604 var keybinding = d3keybinding('mode-buttons');
63606 modes.forEach(function(mode) {
63607 keybinding.on(mode.key, function() {
63609 if (mode.id === context.mode().id) {
63610 context.enter(modeBrowse(context));
63612 context.enter(mode);
63622 function update() {
63623 selection$$1.selectAll('button.add-button')
63624 .property('disabled', !editable());
63629 function uiRestore(context) {
63631 return function(selection) {
63632 if (!context.history().lock() || !context.history().restorableChanges())
63635 var modalSelection = uiModal(selection, true);
63637 modalSelection.select('.modal')
63638 .attr('class', 'modal fillL col6');
63640 var introModal = modalSelection.select('.content');
63643 .attr('class','cf');
63647 .attr('class', 'modal-section')
63649 .text(t('restore.heading'));
63653 .attr('class','modal-section')
63655 .text(t('restore.description'));
63657 var buttonWrap = introModal
63659 .attr('class', 'modal-actions cf');
63661 var restore = buttonWrap
63663 .attr('class', 'restore col6')
63664 .on('click', function() {
63665 context.history().restore();
63666 modalSelection.remove();
63671 .attr('class', 'logo logo-restore')
63673 .attr('xlink:href', '#logo-restore');
63677 .text(t('restore.restore'));
63679 var reset = buttonWrap
63681 .attr('class', 'reset col6')
63682 .on('click', function() {
63683 context.history().clearSaved();
63684 modalSelection.remove();
63689 .attr('class', 'logo logo-reset')
63691 .attr('xlink:href', '#logo-reset');
63695 .text(t('restore.reset'));
63697 restore.node().focus();
63701 function uiSave(context) {
63702 var history = context.history(),
63706 function saving() {
63707 return context.mode().id === 'save';
63712 event.preventDefault();
63713 if (!context.inIntro() && !saving() && history.hasChanges()) {
63714 context.enter(modeSave$$1(context));
63719 function getBackground(numChanges) {
63721 if (numChanges === 0) {
63723 } else if (numChanges <= 50) {
63724 step = numChanges / 50;
63725 return interpolateRgb('#fff', '#ff8')(step); // white -> yellow
63727 step = Math.min((numChanges - 50) / 50, 1.0);
63728 return interpolateRgb('#ff8', '#f88')(step); // yellow -> red
63733 return function(selection$$1) {
63734 var numChanges = 0;
63736 function updateCount() {
63737 var _ = history.difference().summary().length;
63738 if (_ === numChanges) return;
63742 .title(uiTooltipHtml(
63743 t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key)
63746 var background = getBackground(numChanges);
63749 .classed('disabled', numChanges === 0)
63750 .classed('has-count', numChanges > 0)
63751 .style('background', background);
63753 button.select('span.count')
63755 .style('background', background)
63756 .style('border-color', background);
63760 var tooltipBehavior = tooltip()
63761 .placement('bottom')
63763 .title(uiTooltipHtml(t('save.no_changes'), key));
63765 var button = selection$$1
63767 .attr('class', 'save col12 disabled')
63768 .attr('tabindex', -1)
63770 .call(tooltipBehavior);
63773 .call(svgIcon('#icon-save', 'pre-text'))
63775 .attr('class', 'label')
63776 .text(t('save.title'));
63780 .attr('class', 'count')
63786 var keybinding = d3keybinding('save')
63787 .on(key, save, true);
63793 .on('change.save', updateCount);
63796 .on('enter.save', function() {
63797 button.property('disabled', saving());
63798 if (saving()) button.call(tooltipBehavior.hide);
63803 function uiScale(context) {
63804 var projection = context.projection,
63805 isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
63810 function scaleDefs(loc1, loc2) {
63811 var lat = (loc2[1] + loc1[1]) / 2,
63812 conversion = (isImperial ? 3.28084 : 1),
63813 dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
63814 scale = { dist: 0, px: 0, text: '' },
63815 buckets, i, val, dLon;
63818 buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
63820 buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
63823 // determine a user-friendly endpoint for the scale
63824 for (i = 0; i < buckets.length; i++) {
63827 scale.dist = Math.floor(dist / val) * val;
63830 scale.dist = +dist.toFixed(2);
63834 dLon = geoMetersToLon(scale.dist / conversion, lat);
63835 scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
63838 if (scale.dist >= 5280) {
63839 scale.dist /= 5280;
63840 scale.text = String(scale.dist) + ' mi';
63842 scale.text = String(scale.dist) + ' ft';
63845 if (scale.dist >= 1000) {
63846 scale.dist /= 1000;
63847 scale.text = String(scale.dist) + ' km';
63849 scale.text = String(scale.dist) + ' m';
63857 function update(selection) {
63858 // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
63859 var dims = context.map().dimensions(),
63860 loc1 = projection.invert([0, dims[1]]),
63861 loc2 = projection.invert([maxLength, dims[1]]),
63862 scale = scaleDefs(loc1, loc2);
63864 selection.select('#scale-path')
63865 .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
63867 selection.select('#scale-textgroup')
63868 .attr('transform', 'translate(' + (scale.px + 8) + ',' + tickHeight + ')');
63870 selection.select('#scale-text')
63875 return function(selection) {
63876 function switchUnits() {
63877 isImperial = !isImperial;
63878 selection.call(update);
63881 var scalegroup = selection.append('svg')
63882 .attr('id', 'scale')
63883 .on('click', switchUnits)
63885 .attr('transform', 'translate(10,11)');
63889 .attr('id', 'scale-path');
63893 .attr('id', 'scale-textgroup')
63895 .attr('id', 'scale-text');
63897 selection.call(update);
63899 context.map().on('move.scale', function() {
63905 var pair_1 = pair$1;
63906 function search(x, dims, r) {
63907 if (!dims) dims = 'NSEW';
63908 if (typeof x !== 'string') return { val: null, regex: r };
63909 r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
63911 if (!m) return { val: null, regex: r };
63912 else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
63914 val: (((m[1]) ? parseFloat(m[1]) : 0) +
63915 ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
63916 ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
63917 ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
63924 function pair$1(x, dims) {
63926 var one = search(x, dims);
63927 if (one.val === null) return null;
63928 var two = search(x, dims, one.regex);
63929 if (two.val === null) return null;
63930 // null if one/two are not contiguous.
63931 if (one.raw + two.raw !== x) return null;
63933 return swapdim(one.val, two.val, one.dim);
63935 return [one.val, two.val];
63939 function swapdim(a, b, dim) {
63940 if (dim === 'N' || dim === 'S') return [a, b];
63941 if (dim === 'W' || dim === 'E') return [b, a];
63944 function uiFeatureList(context) {
63945 var geocodeResults;
63948 function featureList(selection$$1) {
63949 var header = selection$$1
63951 .attr('class', 'header fillL cf');
63953 header.append('h3')
63954 .text(t('inspector.feature_list'));
63956 var searchWrap = selection$$1
63958 .attr('class', 'search-header');
63960 var search = searchWrap
63962 .attr('placeholder', t('inspector.search'))
63963 .attr('type', 'search')
63965 .on('keypress', keypress)
63966 .on('input', inputevent);
63969 .call(svgIcon('#icon-search', 'pre-text'));
63971 var listWrap = selection$$1
63973 .attr('class', 'inspector-body');
63975 var list = listWrap
63977 .attr('class', 'feature-list cf');
63980 .on('exit.feature-list', clearSearch);
63982 .on('drawn.feature-list', mapDrawn);
63985 function keypress() {
63986 var q = search.property('value'),
63987 items = list.selectAll('.feature-list-item');
63988 if (event.keyCode === 13 && q.length && items.size()) {
63989 click(items.datum());
63994 function inputevent() {
63995 geocodeResults = undefined;
64000 function clearSearch() {
64001 search.property('value', '');
64006 function mapDrawn(e) {
64013 function features() {
64016 graph = context.graph(),
64017 q = search.property('value').toLowerCase();
64019 if (!q) return result;
64021 var idMatch = q.match(/^([nwr])([0-9]+)$/);
64026 geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
64027 type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
64032 var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
64034 if (locationMatch) {
64035 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
64039 type: t('inspector.location'),
64040 name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
64045 function addEntity(entity) {
64046 if (entity.id in entities || result.length > 200)
64049 entities[entity.id] = true;
64051 var name = utilDisplayName(entity) || '';
64052 if (name.toLowerCase().indexOf(q) >= 0) {
64053 var matched = context.presets().match(entity, graph),
64054 type = (matched && matched.name()) || utilDisplayType(entity.id);
64058 geometry: context.geometry(entity.id),
64064 graph.parentRelations(entity).forEach(function(parent) {
64069 var visible = context.surface().selectAll('.point, .line, .area').nodes();
64070 for (var i = 0; i < visible.length && result.length <= 200; i++) {
64071 addEntity(visible[i].__data__);
64074 (geocodeResults || []).forEach(function(d) {
64075 // https://github.com/openstreetmap/iD/issues/1890
64076 if (d.osm_type && d.osm_id) {
64078 id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
64079 geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
64080 type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
64081 : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
64082 name: d.display_name,
64083 extent: new geoExtent$$1(
64084 [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
64085 [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
64094 function drawList() {
64095 var value = search.property('value'),
64096 results = features();
64098 list.classed('filtered', value.length);
64100 var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
64102 var resultsIndicator = list.selectAll('.no-results-item')
64104 .enter().append('button')
64105 .property('disabled', true)
64106 .attr('class', 'no-results-item')
64107 .call(svgIcon('#icon-alert', 'pre-text'));
64109 resultsIndicator.append('span')
64110 .attr('class', 'entity-name');
64112 list.selectAll('.no-results-item .entity-name')
64113 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
64115 if (services.geocoder) {
64116 list.selectAll('.geocode-item')
64118 .enter().append('button')
64119 .attr('class', 'geocode-item')
64120 .on('click', geocoderSearch)
64122 .attr('class', 'label')
64124 .attr('class', 'entity-name')
64125 .text(t('geocoder.search'));
64128 list.selectAll('.no-results-item')
64129 .style('display', (value.length && !results.length) ? 'block' : 'none');
64131 list.selectAll('.geocode-item')
64132 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
64134 list.selectAll('.feature-list-item')
64138 var items = list.selectAll('.feature-list-item')
64139 .data(results, function(d) { return d.id; });
64141 var enter = items.enter()
64142 .insert('button', '.geocode-item')
64143 .attr('class', 'feature-list-item')
64144 .on('mouseover', mouseover)
64145 .on('mouseout', mouseout)
64146 .on('click', click);
64150 .attr('class', 'label');
64152 label.each(function(d) {
64154 .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
64157 label.append('span')
64158 .attr('class', 'entity-type')
64159 .text(function(d) { return d.type; });
64161 label.append('span')
64162 .attr('class', 'entity-name')
64163 .text(function(d) { return d.name; });
64165 enter.style('opacity', 0)
64167 .style('opacity', 1);
64176 function mouseover(d) {
64177 if (d.id === -1) return;
64179 context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
64180 .classed('hover', true);
64184 function mouseout() {
64185 context.surface().selectAll('.hover')
64186 .classed('hover', false);
64190 function click(d) {
64191 event.preventDefault();
64193 context.map().centerZoom([d.location[1], d.location[0]], 20);
64195 else if (d.entity) {
64196 if (d.entity.type === 'node') {
64197 context.map().center(d.entity.loc);
64198 } else if (d.entity.type === 'way') {
64199 var center = context.projection(context.map().center()),
64200 edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
64201 context.map().center(edge.loc);
64203 context.enter(modeSelect(context, [d.entity.id]));
64205 context.zoomToEntity(d.id);
64210 function geocoderSearch() {
64211 services.geocoder.search(search.property('value'), function (err, resp) {
64212 geocodeResults = resp || [];
64219 return featureList;
64222 function uiPresetIcon() {
64223 var preset, geometry;
64226 function presetIcon(selection$$1) {
64227 selection$$1.each(render);
64231 function getIcon(p, geom) {
64234 else if (geom === 'line')
64235 return 'other-line';
64236 else if (geom === 'vertex')
64237 return p.isFallback() ? '' : 'poi-vertex';
64239 return 'marker-stroked';
64243 function render() {
64244 var selection$$1 = select(this),
64245 p = preset.apply(this, arguments),
64246 geom = geometry.apply(this, arguments),
64247 picon = getIcon(p, geom),
64248 isPoi = picon.match(/^poi-/) !== null,
64249 isMaki = dataFeatureIcons.indexOf(picon) !== -1,
64250 isFramed = (geom === 'area' || geom === 'verex');
64253 function tag_classes(p) {
64255 for (var i in p.tags) {
64257 if (p.tags[i] !== '*') {
64258 s += ' tag-' + i + '-' + p.tags[i];
64265 var fill = selection$$1.selectAll('.preset-icon-fill')
64268 fill = fill.enter()
64273 .attr('class', function() {
64274 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
64278 var areaFrame = selection$$1.selectAll('.preset-icon-frame')
64279 .data((geom === 'area') ? [0] : []);
64284 areaFrame = areaFrame.enter()
64286 .attr('class', 'preset-icon-frame')
64287 .call(svgIcon('#preset-icon-frame'));
64290 var icon = selection$$1.selectAll('.preset-icon')
64293 icon = icon.enter()
64295 .attr('class', 'preset-icon')
64300 .attr('class', 'preset-icon preset-icon-' +
64301 ((isMaki || isPoi) ? (isFramed ? '24' : '28') : (isFramed ? '44' : '60'))
64304 icon.selectAll('svg')
64305 .attr('class', function() {
64306 return 'icon ' + picon + (isMaki || isPoi ? '' : tag_classes(p));
64309 icon.selectAll('use')
64310 .attr('href', '#' + picon + (isMaki ? '-15' : ''));
64314 presetIcon.preset = function(_) {
64315 if (!arguments.length) return preset;
64316 preset = utilFunctor(_);
64321 presetIcon.geometry = function(_) {
64322 if (!arguments.length) return geometry;
64323 geometry = utilFunctor(_);
64330 function d3combobox() {
64331 var dispatch$$1 = dispatch('accept'),
64332 container = select(document.body),
64336 caseSensitive = false;
64338 var fetcher = function(val, cb) {
64339 cb(data.filter(function(d) {
64343 .indexOf(val.toLowerCase()) !== -1;
64347 var combobox = function(input, attachTo) {
64349 wrapper = container
64350 .selectAll('div.combobox')
64351 .filter(function(d) { return d === input.node(); }),
64352 shown = !wrapper.empty();
64355 .classed('combobox-input', true)
64356 .on('focus.typeahead', focus)
64357 .on('blur.typeahead', blur)
64358 .on('keydown.typeahead', keydown)
64359 .on('keyup.typeahead', keyup)
64360 .on('input.typeahead', change)
64362 var parent = this.parentNode,
64363 sibling = this.nextSibling;
64365 var caret = select(parent).selectAll('.combobox-caret')
64366 .filter(function(d) { return d === input.node(); })
64367 .data([input.node()]);
64369 caret = caret.enter()
64370 .insert('div', function() { return sibling; })
64371 .attr('class', 'combobox-caret')
64375 .on('mousedown', function () {
64376 // prevent the form element from blurring. it blurs
64378 event.stopPropagation();
64379 event.preventDefault();
64381 input.node().focus();
64390 fetch(value(), render);
64394 window.setTimeout(hide, 150);
64399 wrapper = container
64400 .insert('div', ':first-child')
64401 .datum(input.node())
64402 .attr('class', 'combobox')
64403 .style('position', 'absolute')
64404 .style('display', 'block')
64405 .style('left', '0px')
64406 .on('mousedown', function () {
64407 // prevent moving focus out of the text field
64408 event.preventDefault();
64412 .on('scroll.combobox', render, true);
64424 .on('scroll.combobox', null);
64430 function keydown() {
64431 switch (event.keyCode) {
64432 // backspace, delete
64435 input.on('input.typeahead', function() {
64438 var start = input.property('selectionStart');
64439 input.node().setSelectionRange(start, start);
64440 input.on('input.typeahead', change);
64445 wrapper.selectAll('a.selected').each(function (d) {
64446 dispatch$$1.call('accept', this, d);
64452 event.preventDefault();
64457 event.preventDefault();
64462 event.preventDefault();
64465 event.stopPropagation();
64469 switch (event.keyCode) {
64476 wrapper.selectAll('a.selected').each(function (d) {
64477 dispatch$$1.call('accept', this, d);
64484 function change() {
64485 fetch(value(), function() {
64486 if (input.property('selectionEnd') === input.property('value').length) {
64493 function nav(dir) {
64494 if (!suggestions.length) return;
64495 idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
64496 input.property('value', suggestions[idx].value);
64502 var value = input.property('value'),
64503 start = input.property('selectionStart'),
64504 end = input.property('selectionEnd');
64506 if (start && end) {
64507 value = value.substring(0, start);
64513 function fetch(v, cb) {
64514 fetcher.call(input, v, function(_) {
64520 function autocomplete() {
64521 var v = caseSensitive ? value() : value().toLowerCase();
64525 for (var i = 0; i < suggestions.length; i++) {
64526 var suggestion = suggestions[i].value,
64527 compare = caseSensitive ? suggestion : suggestion.toLowerCase();
64529 if (compare.indexOf(v) === 0) {
64531 input.property('value', suggestion);
64532 input.node().setSelectionRange(v.length, suggestion.length);
64538 function render() {
64539 if (suggestions.length >= minItems && document.activeElement === input.node()) {
64546 var options = wrapper
64547 .selectAll('a.combobox-option')
64548 .data(suggestions, function(d) { return d.value; });
64555 .attr('class', 'combobox-option')
64556 .text(function(d) { return d.value; })
64558 .attr('title', function(d) { return d.title; })
64559 .classed('selected', function(d, i) { return i === idx; })
64560 .on('mouseover', select$$1)
64561 .on('click', accept)
64565 var node = attachTo ? attachTo.node() : input.node(),
64566 rect = node.getBoundingClientRect();
64569 .style('left', rect.left + 'px')
64570 .style('width', rect.width + 'px')
64571 .style('top', rect.height + rect.top + 'px');
64574 function select$$1(d, i) {
64579 function ensureVisible() {
64580 var node = wrapper.selectAll('a.selected').node();
64581 if (node) node.scrollIntoView();
64584 function accept(d) {
64585 if (!shown) return;
64586 input.property('value', d.value);
64587 utilTriggerEvent(input, 'change');
64588 dispatch$$1.call('accept', this, d);
64593 combobox.fetcher = function(_) {
64594 if (!arguments.length) return fetcher;
64599 combobox.data = function(_) {
64600 if (!arguments.length) return data;
64605 combobox.minItems = function(_) {
64606 if (!arguments.length) return minItems;
64611 combobox.caseSensitive = function(_) {
64612 if (!arguments.length) return caseSensitive;
64617 combobox.container = function(_) {
64618 if (!arguments.length) return container;
64623 return utilRebind(combobox, dispatch$$1, 'on');
64627 d3combobox.off = function(input) {
64629 .on('focus.typeahead', null)
64630 .on('blur.typeahead', null)
64631 .on('keydown.typeahead', null)
64632 .on('keyup.typeahead', null)
64633 .on('input.typeahead', null)
64635 select(this.parentNode).selectAll('.combobox-caret')
64636 .filter(function(d) { return d === input.node(); })
64637 .on('mousedown', null);
64641 .on('scroll.combobox', null);
64644 function uiDisclosure() {
64645 var dispatch$$1 = dispatch('toggled'),
64648 content = function () {};
64651 var disclosure = function(selection$$1) {
64652 var hideToggle = selection$$1.selectAll('.hide-toggle')
64655 hideToggle = hideToggle.enter()
64658 .attr('class', 'hide-toggle')
64659 .merge(hideToggle);
64663 .on('click', toggle)
64664 .classed('expanded', expanded);
64667 var wrap = selection$$1.selectAll('div')
64670 wrap = wrap.enter()
64675 .classed('hide', !expanded)
64679 function toggle() {
64680 expanded = !expanded;
64681 hideToggle.classed('expanded', expanded);
64682 wrap.call(uiToggle(expanded));
64683 dispatch$$1.call('toggled', this, expanded);
64688 disclosure.title = function(_) {
64689 if (!arguments.length) return title;
64695 disclosure.expanded = function(_) {
64696 if (!arguments.length) return expanded;
64702 disclosure.content = function(_) {
64703 if (!arguments.length) return content;
64709 return utilRebind(disclosure, dispatch$$1, 'on');
64712 function uiRawMemberEditor(context) {
64714 taginfo = services.taginfo;
64717 function selectMember(d) {
64718 event.preventDefault();
64719 context.enter(modeSelect(context, [d.id]));
64723 function changeRole(d) {
64724 var role = select(this).property('value');
64725 var member = { id: d.id, type: d.type, role: role };
64727 actionChangeMember(d.relation.id, member, d.index),
64728 t('operations.change_role.annotation')
64733 function deleteMember(d) {
64735 actionDeleteMember(d.relation.id, d.index),
64736 t('operations.delete_member.annotation')
64739 if (!context.hasEntity(d.relation.id)) {
64740 context.enter(modeBrowse(context));
64745 function rawMemberEditor(selection$$1) {
64746 var entity = context.entity(id),
64749 entity.members.slice(0, 1000).forEach(function(member, index) {
64756 member: context.hasEntity(member.id)
64760 var gt = entity.members.length > 1000 ? '>' : '';
64761 selection$$1.call(uiDisclosure()
64762 .title(t('inspector.all_members') + ' (' + gt + memberships.length + ')')
64764 .on('toggled', toggled)
64769 function toggled(expanded) {
64771 selection$$1.node().parentNode.scrollTop += 200;
64776 function content(wrap) {
64777 var list = wrap.selectAll('.member-list')
64780 list = list.enter()
64782 .attr('class', 'member-list')
64786 var items = list.selectAll('li')
64787 .data(memberships, function(d) {
64788 return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
64789 (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
64796 var enter = items.enter()
64798 .attr('class', 'member-row form-field')
64799 .classed('member-incomplete', function(d) { return !d.member; });
64802 .each(function(d) {
64804 var label = select(this).append('label')
64805 .attr('class', 'form-label')
64808 .on('click', selectMember);
64810 label.append('span')
64811 .attr('class', 'member-entity-type')
64812 .text(function(d) {
64813 var matched = context.presets().match(d.member, context.graph());
64814 return (matched && matched.name()) || utilDisplayType(d.member.id);
64817 label.append('span')
64818 .attr('class', 'member-entity-name')
64819 .text(function(d) { return utilDisplayName(d.member); });
64822 select(this).append('label')
64823 .attr('class', 'form-label')
64824 .text(t('inspector.incomplete', { id: d.id }));
64830 .attr('class', 'member-role')
64831 .property('type', 'text')
64832 .attr('maxlength', 255)
64833 .attr('placeholder', t('inspector.role'))
64835 .property('value', function(d) { return d.role; })
64836 .on('change', changeRole);
64840 .attr('tabindex', -1)
64841 .attr('class', 'remove button-input-action member-delete minor')
64842 .on('click', deleteMember)
64843 .call(svgIcon('#operation-delete'));
64846 enter.each(bindTypeahead);
64850 function bindTypeahead(d) {
64851 var row = select(this),
64852 role = row.selectAll('input.member-role');
64854 function sort(value, data) {
64855 var sameletter = [],
64857 for (var i = 0; i < data.length; i++) {
64858 if (data[i].value.substring(0, value.length) === value) {
64859 sameletter.push(data[i]);
64861 other.push(data[i]);
64864 return sameletter.concat(other);
64867 role.call(d3combobox()
64868 .container(context.container())
64869 .fetcher(function(role, callback) {
64870 var rtype = entity.tags.type;
64873 rtype: rtype || '',
64874 geometry: context.geometry(d.member.id),
64876 }, function(err, data) {
64877 if (!err) callback(sort(role, data));
64883 function unbind() {
64884 var row = select(this);
64886 row.selectAll('input.member-role')
64887 .call(d3combobox.off);
64893 rawMemberEditor.entityID = function(_) {
64894 if (!arguments.length) return id;
64896 return rawMemberEditor;
64900 return rawMemberEditor;
64903 function uiRawMembershipEditor(context) {
64904 var taginfo = services.taginfo,
64908 function selectRelation(d) {
64909 event.preventDefault();
64910 context.enter(modeSelect(context, [d.relation.id]));
64914 function changeRole(d) {
64915 var role = select(this).property('value');
64917 actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
64918 t('operations.change_role.annotation')
64923 function addMembership(d, role) {
64928 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
64929 t('operations.add_member.annotation')
64933 var relation = osmRelation();
64935 actionAddEntity(relation),
64936 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
64937 t('operations.add.annotation.relation')
64940 context.enter(modeSelect(context, [relation.id]));
64945 function deleteMembership(d) {
64947 actionDeleteMember(d.relation.id, d.index),
64948 t('operations.delete_member.annotation')
64953 function relations(q) {
64954 var newRelation = {
64956 value: t('inspector.new_relation')
64959 graph = context.graph();
64961 context.intersects(context.extent()).forEach(function(entity) {
64962 if (entity.type !== 'relation' || entity.id === id)
64965 var matched = context.presets().match(entity, graph),
64966 presetName = (matched && matched.name()) || t('inspector.relation'),
64967 entityName = utilDisplayName(entity) || '';
64969 var value = presetName + ' ' + entityName;
64970 if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
64979 result.sort(function(a, b) {
64980 return osmRelation.creationOrder(a.relation, b.relation);
64983 // Dedupe identical names by appending relation id - see #2891
64984 var dupeGroups = lodash(result)
64986 .filter(function(v) { return v.length > 1; })
64989 dupeGroups.forEach(function(group) {
64990 group.forEach(function(obj) {
64991 obj.value += ' ' + obj.relation.id;
64995 result.unshift(newRelation);
65000 function rawMembershipEditor(selection$$1) {
65001 var entity = context.entity(id),
65002 parents = context.graph().parentRelations(entity),
65005 parents.slice(0, 1000).forEach(function(relation) {
65006 relation.members.forEach(function(member, index) {
65007 if (member.id === entity.id) {
65008 memberships.push({ relation: relation, member: member, index: index });
65013 var gt = parents.length > 1000 ? '>' : '';
65014 selection$$1.call(uiDisclosure()
65015 .title(t('inspector.all_relations') + ' (' + gt + memberships.length + ')')
65017 .on('toggled', toggled)
65022 function toggled(expanded) {
65024 selection$$1.node().parentNode.scrollTop += 200;
65029 function content(wrap) {
65030 var list = wrap.selectAll('.member-list')
65033 list = list.enter()
65035 .attr('class', 'member-list')
65039 var items = list.selectAll('li.member-row-normal')
65040 .data(memberships, function(d) {
65041 return osmEntity$$1.key(d.relation) + ',' + d.index;
65048 var enter = items.enter()
65050 .attr('class', 'member-row member-row-normal form-field');
65054 .attr('class', 'form-label')
65057 .on('click', selectRelation);
65061 .attr('class', 'member-entity-type')
65062 .text(function(d) {
65063 var matched = context.presets().match(d.relation, context.graph());
65064 return (matched && matched.name()) || t('inspector.relation');
65069 .attr('class', 'member-entity-name')
65070 .text(function(d) { return utilDisplayName(d.relation); });
65074 .attr('class', 'member-role')
65075 .property('type', 'text')
65076 .attr('maxlength', 255)
65077 .attr('placeholder', t('inspector.role'))
65079 .property('value', function(d) { return d.member.role; })
65080 .on('change', changeRole);
65084 .attr('tabindex', -1)
65085 .attr('class', 'remove button-input-action member-delete minor')
65086 .on('click', deleteMembership)
65087 .call(svgIcon('#operation-delete'));
65090 enter.each(bindTypeahead);
65094 var newrow = list.selectAll('.member-row-new')
65095 .data(showBlank ? [0] : []);
65100 enter = newrow.enter()
65102 .attr('class', 'member-row member-row-new form-field');
65106 .attr('type', 'text')
65107 .attr('class', 'member-entity-input')
65112 .attr('class', 'member-role')
65113 .property('type', 'text')
65114 .attr('maxlength', 255)
65115 .attr('placeholder', t('inspector.role'))
65117 .on('change', changeRole);
65121 .attr('tabindex', -1)
65122 .attr('class', 'remove button-input-action member-delete minor')
65123 .on('click', deleteMembership)
65124 .call(svgIcon('#operation-delete'));
65129 newrow.selectAll('.member-entity-input')
65131 .container(context.container())
65133 .fetcher(function(value, callback) { callback(relations(value)); })
65134 .on('accept', onAccept)
65138 var addrel = wrap.selectAll('.add-relation')
65141 addrel = addrel.enter()
65143 .attr('class', 'add-relation')
65147 .call(svgIcon('#icon-plus', 'light'))
65148 .on('click', function() {
65151 list.selectAll('.member-entity-input').node().focus();
65155 function onAccept(d) {
65156 var role = list.selectAll('.member-row-new .member-role').property('value');
65157 addMembership(d, role);
65161 function bindTypeahead(d) {
65162 var row = select(this),
65163 role = row.selectAll('input.member-role');
65165 function sort(value, data) {
65166 var sameletter = [],
65168 for (var i = 0; i < data.length; i++) {
65169 if (data[i].value.substring(0, value.length) === value) {
65170 sameletter.push(data[i]);
65172 other.push(data[i]);
65175 return sameletter.concat(other);
65178 role.call(d3combobox()
65179 .container(context.container())
65180 .fetcher(function(role, callback) {
65181 var rtype = d.relation.tags.type;
65184 rtype: rtype || '',
65185 geometry: context.geometry(id),
65187 }, function(err, data) {
65188 if (!err) callback(sort(role, data));
65194 function unbind() {
65195 var row = select(this);
65197 row.selectAll('input.member-role')
65198 .call(d3combobox.off);
65204 rawMembershipEditor.entityID = function(_) {
65205 if (!arguments.length) return id;
65207 return rawMembershipEditor;
65211 return rawMembershipEditor;
65214 function uiTagReference(tag) {
65215 var taginfo = services.taginfo,
65223 function findLocal(data) {
65224 var locale = utilDetect().locale.toLowerCase(),
65227 if (locale !== 'pt-br') { // see #3776, prefer 'pt' over 'pt-br'
65228 localized = lodash.find(data, function(d) {
65229 return d.lang.toLowerCase() === locale;
65231 if (localized) return localized;
65234 // try the non-regional version of a language, like
65235 // 'en' if the language is 'en-US'
65236 if (locale.indexOf('-') !== -1) {
65237 var first = locale.split('-')[0];
65238 localized = lodash.find(data, function(d) {
65239 return d.lang.toLowerCase() === first;
65241 if (localized) return localized;
65244 // finally fall back to english
65245 return lodash.find(data, function(d) {
65246 return d.lang.toLowerCase() === 'en';
65251 function load(param) {
65252 if (!taginfo) return;
65254 button.classed('tag-reference-loading', true);
65256 taginfo.docs(param, function show(err, data) {
65258 if (!err && data) {
65259 docs = findLocal(data);
65265 if (!docs || !docs.title) {
65266 if (param.hasOwnProperty('value')) {
65267 load(lodash.omit(param, 'value')); // retry with key only
65269 body.append('p').text(t('inspector.no_documentation_key'));
65276 if (docs.image && docs.image.thumb_url_prefix) {
65279 .attr('class', 'wiki-image')
65280 .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
65281 .on('load', function() { done(); })
65282 .on('error', function() { select(this).remove(); done(); });
65289 .text(docs.description || t('inspector.documentation_redirect'));
65293 .attr('target', '_blank')
65294 .attr('tabindex', -1)
65295 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
65296 .call(svgIcon('#icon-out-link', 'inline'))
65298 .text(t('inspector.reference'));
65306 button.classed('tag-reference-loading', false);
65310 .style('max-height', '200px')
65311 .style('opacity', '1');
65317 function hide(selection$$1) {
65318 selection$$1 = selection$$1 || body.transition().duration(200);
65321 .style('max-height', '0px')
65322 .style('opacity', '0');
65328 tagReference.button = function(selection$$1) {
65329 button = selection$$1.selectAll('.tag-reference-button')
65332 button = button.enter()
65334 .attr('class', 'tag-reference-button')
65335 .attr('tabindex', -1)
65336 .call(svgIcon('#icon-inspect'))
65340 .on('click', function () {
65341 event.stopPropagation();
65342 event.preventDefault();
65345 } else if (loaded) {
65354 tagReference.body = function(selection$$1) {
65355 body = selection$$1.selectAll('.tag-reference-body')
65358 body = body.enter()
65360 .attr('class', 'tag-reference-body cf')
65361 .style('max-height', '0')
65362 .style('opacity', '0')
65365 if (showing === false) {
65371 tagReference.showing = function(_) {
65372 if (!arguments.length) return showing;
65374 return tagReference;
65378 return tagReference;
65381 function uiRawTagEditor(context) {
65382 var taginfo = services.taginfo,
65383 dispatch$$1 = dispatch('change'),
65384 expanded = context.storage('raw_tag_editor.expanded') === 'true',
65386 updatePreference = true,
65395 function rawTagEditor(selection$$1) {
65396 var count = Object.keys(tags).filter(function(d) { return d; }).length;
65398 selection$$1.call(uiDisclosure()
65399 .title(t('inspector.all_tags') + ' (' + count + ')')
65400 .expanded(expanded)
65401 .on('toggled', toggled)
65405 function toggled(expanded) {
65406 if (updatePreference) {
65407 context.storage('raw_tag_editor.expanded', expanded);
65410 selection$$1.node().parentNode.scrollTop += 200;
65416 function content(wrap) {
65417 var entries$$1 = entries(tags);
65419 if (!entries$$1.length || showBlank) {
65421 entries$$1.push({key: '', value: ''});
65425 var list = wrap.selectAll('.tag-list')
65428 list = list.enter()
65430 .attr('class', 'tag-list')
65433 var newTag = wrap.selectAll('.add-tag')
65438 .attr('class', 'add-tag')
65439 .on('click', addTag)
65440 .call(svgIcon('#icon-plus', 'light'));
65443 var items = list.selectAll('.tag-row')
65444 .data(entries$$1, function(d) { return d.key; });
65452 var enter = items.enter()
65454 .attr('class', 'tag-row cf')
65455 .classed('readonly', isReadOnly);
65459 .attr('class', 'key-wrap')
65461 .property('type', 'text')
65462 .attr('class', 'key')
65463 .attr('maxlength', 255)
65465 .on('blur', keyChange)
65466 .on('change', keyChange);
65470 .attr('class', 'input-wrap-position')
65472 .property('type', 'text')
65473 .attr('class', 'value')
65474 .attr('maxlength', 255)
65476 .on('blur', valueChange)
65477 .on('change', valueChange)
65478 .on('keydown.push-more', pushMore);
65482 .attr('tabindex', -1)
65483 .attr('class', 'remove minor')
65484 .call(svgIcon('#operation-delete'));
65491 .sort(function(a, b) {
65492 return (a.key === newRow && b.key !== newRow) ? 1
65493 : (a.key !== newRow && b.key === newRow) ? -1
65494 : ascending(a.key, b.key);
65498 .each(function(tag) {
65499 var row = select(this),
65500 key = row.select('input.key'), // propagate bound data to child
65501 value = row.select('input.value'); // propagate bound data to child
65503 if (id && taginfo) {
65504 bindTypeahead(key, value);
65507 var isRelation = (id && context.entity(id).type === 'relation'),
65510 if (isRelation && tag.key === 'type') {
65511 reference = uiTagReference({ rtype: tag.value }, context);
65513 reference = uiTagReference({ key: tag.key, value: tag.value }, context);
65516 if (state === 'hover') {
65517 reference.showing(false);
65521 .call(reference.button)
65522 .call(reference.body);
65525 items.selectAll('input.key')
65526 .attr('title', function(d) { return d.key; })
65527 .call(utilGetSetValue, function(d) { return d.key; })
65528 .property('disabled', isReadOnly);
65530 items.selectAll('input.value')
65531 .attr('title', function(d) { return d.value; })
65532 .call(utilGetSetValue, function(d) { return d.value; })
65533 .property('disabled', isReadOnly);
65535 items.selectAll('button.remove')
65536 .on('click', removeTag);
65540 function isReadOnly(d) {
65541 return readOnlyTags.indexOf(d.key) !== -1;
65545 function pushMore() {
65546 if (event.keyCode === 9 && !event.shiftKey &&
65547 list.selectAll('li:last-child input.value').node() === this) {
65553 function bindTypeahead(key, value) {
65554 if (isReadOnly({ key: key })) return;
65555 var geometry = context.geometry(id);
65557 key.call(d3combobox()
65558 .container(context.container())
65559 .fetcher(function(value, callback) {
65562 geometry: geometry,
65564 }, function(err, data) {
65565 if (!err) callback(sort(value, data));
65569 value.call(d3combobox()
65570 .container(context.container())
65571 .fetcher(function(value, callback) {
65574 key: utilGetSetValue(key),
65575 geometry: geometry,
65577 }, function(err, data) {
65578 if (!err) callback(sort(value, data));
65583 function sort(value, data) {
65584 var sameletter = [],
65586 for (var i = 0; i < data.length; i++) {
65587 if (data[i].value.substring(0, value.length) === value) {
65588 sameletter.push(data[i]);
65590 other.push(data[i]);
65593 return sameletter.concat(other);
65598 function unbind() {
65599 var row = select(this);
65601 row.selectAll('input.key')
65602 .call(d3combobox.off);
65604 row.selectAll('input.value')
65605 .call(d3combobox.off);
65609 function keyChange(d) {
65611 kNew = this.value.trim(),
65615 if (isReadOnly({ key: kNew })) {
65620 if (kNew && kNew !== kOld) {
65621 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
65623 suffix = +(match[2] || 1);
65624 while (tags[kNew]) { // rename key if already in use
65625 kNew = base + '_' + suffix++;
65628 tag[kOld] = undefined;
65629 tag[kNew] = d.value;
65631 d.key = kNew; // Maintain DOM identity through the subsequent update.
65633 if (newRow === kOld) { // see if this row is still a new row
65634 newRow = ((d.value === '' || kNew === '') ? kNew : undefined);
65638 dispatch$$1.call('change', this, tag);
65642 function valueChange(d) {
65643 if (isReadOnly(d)) return;
65645 tag[d.key] = this.value;
65647 if (newRow === d.key && d.key !== '' && d.value !== '') { // not a new row anymore
65648 newRow = undefined;
65651 dispatch$$1.call('change', this, tag);
65655 function removeTag(d) {
65656 if (isReadOnly(d)) return;
65658 tag[d.key] = undefined;
65659 dispatch$$1.call('change', this, tag);
65660 select(this.parentNode).remove();
65664 function addTag() {
65665 // Wrapped in a setTimeout in case it's being called from a blur
65666 // handler. Without the setTimeout, the call to `content` would
65667 // wipe out the pending value change.
65668 setTimeout(function() {
65671 list.selectAll('li:last-child input.key').node().focus();
65677 rawTagEditor.state = function(_) {
65678 if (!arguments.length) return state;
65680 return rawTagEditor;
65684 rawTagEditor.preset = function(_) {
65685 if (!arguments.length) return preset;
65687 if (preset.isFallback()) {
65689 updatePreference = false;
65691 expanded = context.storage('raw_tag_editor.expanded') === 'true';
65692 updatePreference = true;
65694 return rawTagEditor;
65698 rawTagEditor.tags = function(_) {
65699 if (!arguments.length) return tags;
65701 return rawTagEditor;
65705 rawTagEditor.entityID = function(_) {
65706 if (!arguments.length) return id;
65708 return rawTagEditor;
65712 rawTagEditor.expanded = function(_) {
65713 if (!arguments.length) return expanded;
65715 updatePreference = false;
65716 return rawTagEditor;
65720 rawTagEditor.readOnlyTags = function(_) {
65721 if (!arguments.length) return readOnlyTags;
65723 return rawTagEditor;
65727 return utilRebind(rawTagEditor, dispatch$$1, 'on');
65730 function uiFieldCheck(field, context) {
65731 var dispatch$$1 = dispatch('change'),
65732 options = field.strings && field.strings.options,
65735 input = select(null),
65736 text$$1 = select(null),
65737 label = select(null),
65738 reverser = select(null),
65745 for (var k in options) {
65746 values$$1.push(k === 'undefined' ? undefined : k);
65747 texts.push(field.t('options.' + k, { 'default': options[k] }));
65750 values$$1 = [undefined, 'yes'];
65751 texts = [t('inspector.unknown'), t('inspector.check.yes')];
65752 if (field.type !== 'defaultCheck') {
65753 values$$1.push('no');
65754 texts.push(t('inspector.check.no'));
65759 // Checks tags to see whether an undefined value is "Assumed to be Yes"
65760 function checkImpliedYes() {
65761 impliedYes = (field.id === 'oneway_yes');
65763 // hack: pretend `oneway` field is a `oneway_yes` field
65764 // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
65765 if (field.id === 'oneway') {
65766 var entity = context.entity(entityId);
65767 for (var key in entity.tags) {
65768 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
65770 texts[0] = t('presets.fields.oneway_yes.options.undefined');
65778 function reverserHidden() {
65779 if (!select('div.inspector-hover').empty()) return true;
65780 return !(value === 'yes' || (impliedYes && !value));
65784 function reverserSetText(selection$$1) {
65785 var entity = context.hasEntity(entityId);
65786 if (reverserHidden() || !entity) return selection$$1;
65788 var first = entity.first(),
65789 last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last(),
65790 pseudoDirection = first < last,
65791 icon = pseudoDirection ? '#icon-forward' : '#icon-backward';
65793 selection$$1.selectAll('.reverser-span')
65794 .text(t('inspector.check.reverser'))
65795 .call(svgIcon(icon, 'inline'));
65797 return selection$$1;
65801 var check = function(selection$$1) {
65803 selection$$1.classed('checkselect', 'true');
65805 label = selection$$1.selectAll('.preset-input-wrap')
65808 var enter = label.enter()
65810 .attr('class', 'preset-input-wrap');
65814 .property('indeterminate', field.type !== 'defaultCheck')
65815 .attr('type', 'checkbox')
65816 .attr('id', 'preset-input-' + field.id);
65821 .attr('class', 'value');
65823 if (field.type === 'onewayCheck') {
65826 .attr('id', 'preset-input-' + field.id + '-reverser')
65827 .attr('class', 'reverser button' + (reverserHidden() ? ' hide' : ''))
65830 .attr('class', 'reverser-span');
65833 label = label.merge(enter);
65834 input = label.selectAll('input');
65835 text$$1 = label.selectAll('span.value');
65838 .on('click', function() {
65840 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
65841 dispatch$$1.call('change', this, t$$1);
65842 event.stopPropagation();
65845 if (field.type === 'onewayCheck') {
65846 reverser = label.selectAll('.reverser');
65849 .call(reverserSetText)
65850 .on('click', function() {
65851 event.preventDefault();
65852 event.stopPropagation();
65854 actionReverse(entityId),
65855 t('operations.reverse.annotation')
65858 .call(reverserSetText);
65864 check.entity = function(_) {
65865 if (!arguments.length) return context.hasEntity(entityId);
65871 check.tags = function(tags) {
65873 value = tags[field.key] && tags[field.key].toLowerCase();
65875 if (field.type === 'onewayCheck' && (value === '1' || value === '-1')) {
65880 .property('indeterminate', field.type !== 'defaultCheck' && !value)
65881 .property('checked', value === 'yes');
65884 .text(texts[values$$1.indexOf(value)]);
65887 .classed('set', !!value);
65889 if (field.type === 'onewayCheck') {
65891 .classed('hide', reverserHidden())
65892 .call(reverserSetText);
65897 check.focus = function() {
65898 input.node().focus();
65901 return utilRebind(check, dispatch$$1, 'on');
65904 function uiFieldCombo(field, context) {
65905 var dispatch$$1 = dispatch('change'),
65906 nominatim = services.geocoder,
65907 taginfo = services.taginfo,
65908 isMulti = (field.type === 'multiCombo'),
65909 isNetwork = (field.type === 'networkCombo'),
65910 isSemi = (field.type === 'semiCombo'),
65911 optstrings = field.strings && field.strings.options,
65912 optarray = field.options,
65913 snake_case = (field.snake_case || (field.snake_case === undefined)),
65914 combobox = d3combobox()
65915 .container(context.container())
65916 .minItems(isMulti || isSemi ? 1 : 2),
65924 // ensure multiCombo field.key ends with a ':'
65925 if (isMulti && field.key.match(/:$/) === null) {
65930 function snake(s) {
65931 return s.replace(/\s+/g, '_');
65934 function unsnake(s) {
65935 return s.replace(/_+/g, ' ');
65938 function clean(s) {
65939 return s.split(';')
65940 .map(function(s) { return s.trim(); })
65945 // returns the tag value for a display value
65946 // (for multiCombo, dval should be the key suffix, not the entire key)
65947 function tagValue(dval) {
65948 dval = clean(dval || '');
65951 var match = lodash.find(comboData, function(o) {
65952 return o.key && clean(o.value) === dval;
65959 if (field.type === 'typeCombo' && !dval) {
65963 return (snake_case ? snake(dval) : dval) || undefined;
65967 // returns the display value for a tag value
65968 // (for multiCombo, tval should be the key suffix, not the entire key)
65969 function displayValue(tval) {
65973 var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
65975 return match.value;
65979 if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
65983 return snake_case ? unsnake(tval) : tval;
65987 function objectDifference(a, b) {
65988 return lodash.reject(a, function(d1) {
65989 return lodash.some(b, function(d2) { return d1.value === d2.value; });
65994 function initCombo(selection$$1, attachTo) {
65996 selection$$1.attr('readonly', 'readonly');
65997 selection$$1.call(combobox, attachTo);
65998 setStaticValues(setPlaceholder);
66000 } else if (optarray) {
66001 selection$$1.call(combobox, attachTo);
66002 setStaticValues(setPlaceholder);
66004 } else if (taginfo) {
66005 selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
66006 setTaginfoValues('', setPlaceholder);
66011 function setStaticValues(callback) {
66012 if (!(optstrings || optarray)) return;
66015 comboData = Object.keys(optstrings).map(function(k) {
66016 var v = field.t('options.' + k, { 'default': optstrings[k] });
66024 } else if (optarray) {
66025 comboData = optarray.map(function(k) {
66026 var v = snake_case ? unsnake(k) : k;
66035 combobox.data(objectDifference(comboData, multiData));
66036 if (callback) callback(comboData);
66040 function setTaginfoValues(q, callback) {
66041 var fn = isMulti ? 'multikeys' : 'values';
66042 var query = (isMulti ? field.key : '') + q;
66043 var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
66044 if (hasCountryPrefix) {
66045 query = country + ':';
66049 debounce: (q !== ''),
66051 geometry: context.geometry(entity.id),
66053 }, function(err, data) {
66055 if (hasCountryPrefix) {
66056 data = lodash.filter(data, function(d) {
66057 return d.value.toLowerCase().indexOf(country + ':') === 0;
66061 comboData = lodash.map(data, function(d) {
66063 if (isMulti) k = k.replace(field.key, '');
66064 var v = snake_case ? unsnake(k) : k;
66068 title: isMulti ? v : d.title
66072 comboData = objectDifference(comboData, multiData);
66073 if (callback) callback(comboData);
66078 function setPlaceholder(d) {
66081 if (isMulti || isSemi) {
66082 ph = field.placeholder() || t('inspector.add');
66084 var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
66085 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
66086 ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
66089 if (ph.match(/(…|\.\.\.)$/) === null) {
66093 container.selectAll('input')
66094 .attr('placeholder', ph);
66098 function change() {
66099 var val = tagValue(utilGetSetValue(input)),
66102 if (isMulti || isSemi) {
66104 container.classed('active', false);
66105 utilGetSetValue(input, '');
66107 field.keys.push(field.key + val);
66108 t$$1[field.key + val] = 'yes';
66109 } else if (isSemi) {
66110 var arr = multiData.map(function(d) { return d.key; });
66112 t$$1[field.key] = lodash.compact(lodash.uniq(arr)).join(';');
66114 window.setTimeout(function() { input.node().focus(); }, 10);
66117 t$$1[field.key] = val;
66120 dispatch$$1.call('change', this, t$$1);
66124 function removeMultikey(d) {
66125 event.stopPropagation();
66128 t$$1[d.key] = undefined;
66129 } else if (isSemi) {
66130 lodash.remove(multiData, function(md) { return md.key === d.key; });
66131 var arr = multiData.map(function(md) { return md.key; });
66132 arr = lodash.compact(lodash.uniq(arr));
66133 t$$1[field.key] = arr.length ? arr.join(';') : undefined;
66135 dispatch$$1.call('change', this, t$$1);
66139 function combo(selection$$1) {
66140 if (isMulti || isSemi) {
66141 container = selection$$1.selectAll('ul').data([0]);
66143 container = container.enter()
66145 .attr('class', 'form-field-multicombo')
66146 .on('click', function() {
66147 window.setTimeout(function() { input.node().focus(); }, 10);
66152 container = selection$$1;
66155 input = container.selectAll('input')
66158 input = input.enter()
66160 .attr('type', 'text')
66161 .attr('id', 'preset-input-' + field.id)
66163 .call(initCombo, selection$$1)
66166 if (isNetwork && nominatim && entity) {
66167 var center = entity.extent(context.graph()).center();
66168 nominatim.countryCode(center, function (err, code) {
66174 .on('change', change)
66175 .on('blur', change);
66177 if (isMulti || isSemi) {
66179 .on('accept', function() {
66180 input.node().blur();
66181 input.node().focus();
66185 .on('focus', function() { container.classed('active', true); });
66190 combo.tags = function(tags) {
66191 if (isMulti || isSemi) {
66195 // Build multiData array containing keys already set..
66196 Object.keys(tags).forEach(function(key) {
66197 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
66199 var suffix = key.substring(field.key.length);
66202 value: displayValue(suffix)
66206 // Set keys for form-field modified (needed for undo and reset buttons)..
66207 field.keys = lodash.map(multiData, 'key');
66209 } else if (isSemi) {
66210 var arr = lodash.compact(lodash.uniq((tags[field.key] || '').split(';')));
66211 multiData = arr.map(function(key) {
66214 value: displayValue(key)
66219 // Exclude existing multikeys from combo options..
66220 var available = objectDifference(comboData, multiData);
66221 combobox.data(available);
66223 // Hide 'Add' button if this field uses fixed set of
66224 // translateable optstrings and they're all currently used..
66225 container.selectAll('.combobox-input, .combobox-caret')
66226 .classed('hide', optstrings && !available.length);
66230 var chips = container.selectAll('.chips')
66236 var enter = chips.enter()
66237 .insert('li', 'input')
66238 .attr('class', 'chips');
66240 enter.append('span');
66243 chips = chips.merge(enter);
66245 chips.select('span')
66246 .text(function(d) { return d.value; });
66249 .on('click', removeMultikey)
66250 .attr('class', 'remove')
66254 utilGetSetValue(input, displayValue(tags[field.key]));
66259 combo.focus = function() {
66260 input.node().focus();
66264 combo.entity = function(_) {
66265 if (!arguments.length) return entity;
66271 return utilRebind(combo, dispatch$$1, 'on');
66274 function uiFieldText(field, context) {
66275 var dispatch$$1 = dispatch('change'),
66276 nominatim = services.geocoder,
66281 function i(selection$$1) {
66282 var fieldId = 'preset-input-' + field.id;
66284 input = selection$$1.selectAll('input')
66287 input = input.enter()
66289 .attr('type', field.type)
66290 .attr('id', fieldId)
66291 .attr('placeholder', field.placeholder() || t('inspector.unknown'))
66296 .on('input', change(true))
66297 .on('blur', change())
66298 .on('change', change());
66300 if (field.type === 'tel' && nominatim && entity) {
66301 var center = entity.extent(context.graph()).center();
66302 nominatim.countryCode(center, function (err, countryCode) {
66303 if (err || !dataPhoneFormats[countryCode]) return;
66304 selection$$1.selectAll('#' + fieldId)
66305 .attr('placeholder', dataPhoneFormats[countryCode]);
66308 } else if (field.type === 'number') {
66309 input.attr('type', 'text');
66311 var spinControl = selection$$1.selectAll('.spin-control')
66314 var enter = spinControl.enter()
66316 .attr('class', 'spin-control');
66321 .attr('class', 'decrement')
66322 .attr('tabindex', -1);
66327 .attr('class', 'increment')
66328 .attr('tabindex', -1);
66330 spinControl = spinControl
66333 spinControl.selectAll('button')
66334 .on('click', function(d) {
66335 event.preventDefault();
66336 var num = parseInt(input.node().value || 0, 10);
66337 if (!isNaN(num)) input.node().value = num + d;
66344 function change(onInput) {
66345 return function() {
66347 t$$1[field.key] = utilGetSetValue(input) || undefined;
66348 dispatch$$1.call('change', this, t$$1, onInput);
66353 i.entity = function(_) {
66354 if (!arguments.length) return entity;
66360 i.tags = function(tags) {
66361 utilGetSetValue(input, tags[field.key] || '');
66365 i.focus = function() {
66366 var node = input.node();
66367 if (node) node.focus();
66370 return utilRebind(i, dispatch$$1, 'on');
66373 function uiFieldAccess(field, context) {
66374 var dispatch$$1 = dispatch('change'),
66377 function access(selection$$1) {
66378 var wrap = selection$$1.selectAll('.preset-input-wrap')
66381 wrap = wrap.enter()
66383 .attr('class', 'cf preset-input-wrap')
66387 var list = wrap.selectAll('ul')
66390 list = list.enter()
66395 items = list.selectAll('li')
66399 var enter = items.enter()
66401 .attr('class', function(d) { return 'cf preset-access-' + d; });
66405 .attr('class', 'col6 label preset-label-access')
66406 .attr('for', function(d) { return 'preset-input-access-' + d; })
66407 .text(function(d) { return field.t('types.' + d); });
66411 .attr('class', 'col6 preset-input-access-wrap')
66413 .attr('type', 'text')
66414 .attr('class', 'preset-input-access')
66415 .attr('id', function(d) { return 'preset-input-access-' + d; })
66417 .each(function(d) {
66420 .container(context.container())
66421 .data(access.options(d))
66427 items = items.merge(enter);
66429 wrap.selectAll('.preset-input-access')
66430 .on('change', change)
66431 .on('blur', change);
66435 function change(d) {
66437 tag[d] = utilGetSetValue(select(this)) || undefined;
66438 dispatch$$1.call('change', this, tag);
66442 access.options = function(type) {
66443 var options = ['no', 'permissive', 'private', 'destination'];
66445 if (type !== 'access') {
66446 options.unshift('yes');
66447 options.push('designated');
66449 if (type === 'bicycle') {
66450 options.push('dismount');
66454 return options.map(function(option) {
66456 title: field.t('options.' + option + '.description'),
66463 var placeholders = {
66465 foot: 'designated',
66466 motor_vehicle: 'no'
66470 motor_vehicle: 'no',
66476 motor_vehicle: 'no'
66479 motor_vehicle: 'no',
66480 bicycle: 'designated'
66483 motor_vehicle: 'no',
66484 horse: 'designated'
66488 motor_vehicle: 'no',
66494 motor_vehicle: 'yes',
66499 motor_vehicle: 'yes'
66503 motor_vehicle: 'yes',
66509 motor_vehicle: 'yes',
66515 motor_vehicle: 'yes',
66521 motor_vehicle: 'yes',
66527 motor_vehicle: 'yes',
66533 motor_vehicle: 'yes',
66539 motor_vehicle: 'yes',
66544 motor_vehicle: 'yes'
66548 motor_vehicle: 'yes',
66554 motor_vehicle: 'yes',
66560 motor_vehicle: 'yes',
66567 access.tags = function(tags) {
66568 utilGetSetValue(items.selectAll('.preset-input-access'),
66569 function(d) { return tags[d] || ''; })
66570 .attr('placeholder', function() {
66571 return tags.access ? tags.access : field.placeholder();
66574 items.selectAll('#preset-input-access-access')
66575 .attr('placeholder', 'yes');
66577 lodash.forEach(placeholders[tags.highway], function(v, k) {
66578 items.selectAll('#preset-input-access-' + k)
66579 .attr('placeholder', function() { return (tags.access || v); });
66584 access.focus = function() {
66585 items.selectAll('.preset-input-access')
66590 return utilRebind(access, dispatch$$1, 'on');
66593 function uiFieldAddress(field, context) {
66594 var dispatch$$1 = dispatch('init', 'change'),
66595 nominatim = services.geocoder,
66596 wrap = select(null),
66597 isInitialized = false,
66600 function getNearStreets() {
66601 var extent$$1 = entity.extent(context.graph()),
66602 l = extent$$1.center(),
66603 box = geoExtent$$1(l).padByMeters(200);
66605 var streets = context.intersects(box)
66606 .filter(isAddressable)
66608 var loc = context.projection([
66609 (extent$$1[0][0] + extent$$1[1][0]) / 2,
66610 (extent$$1[0][1] + extent$$1[1][1]) / 2]),
66611 choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
66613 title: d.tags.name,
66614 value: d.tags.name,
66615 dist: choice.distance
66618 .sort(function(a, b) {
66619 return a.dist - b.dist;
66622 return lodash.uniqBy(streets, 'value');
66624 function isAddressable(d) {
66625 return d.tags.highway && d.tags.name && d.type === 'way';
66630 function getNearCities() {
66631 var extent$$1 = entity.extent(context.graph()),
66632 l = extent$$1.center(),
66633 box = geoExtent$$1(l).padByMeters(200);
66635 var cities = context.intersects(box)
66636 .filter(isAddressable)
66639 title: d.tags['addr:city'] || d.tags.name,
66640 value: d.tags['addr:city'] || d.tags.name,
66641 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
66644 .sort(function(a, b) {
66645 return a.dist - b.dist;
66648 return lodash.uniqBy(cities, 'value');
66651 function isAddressable(d) {
66653 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
66656 if (d.tags.place && d.tags.name && (
66657 d.tags.place === 'city' ||
66658 d.tags.place === 'town' ||
66659 d.tags.place === 'village'))
66662 if (d.tags['addr:city']) return true;
66668 function getNearValues(key) {
66669 var extent$$1 = entity.extent(context.graph()),
66670 l = extent$$1.center(),
66671 box = geoExtent$$1(l).padByMeters(200);
66673 var results = context.intersects(box)
66674 .filter(function hasTag(d) {
66675 return d.tags[key];
66679 title: d.tags[key],
66680 value: d.tags[key],
66681 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
66684 .sort(function(a, b) {
66685 return a.dist - b.dist;
66688 return lodash.uniqBy(results, 'value');
66692 function initCallback(err, countryCode) {
66695 var addressFormat = lodash.find(dataAddressFormats, function (a) {
66696 return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode.toLowerCase());
66697 }) || lodash.first(dataAddressFormats);
66699 var widths = addressFormat.widths || {
66700 housenumber: 1/3, street: 2/3,
66701 city: 2/3, state: 1/4, postcode: 1/3
66705 // Normalize widths.
66706 var total = lodash.reduce(r, function(sum$$1, field) {
66707 return sum$$1 + (widths[field] || 0.5);
66710 return r.map(function (field) {
66713 width: (widths[field] || 0.5) / total
66718 wrap.selectAll('div.addr-row')
66719 .data(addressFormat.format)
66722 .attr('class', 'addr-row')
66723 .selectAll('input')
66727 .property('type', 'text')
66728 .attr('placeholder', function (d) {
66729 var localkey = d.id + '!' + countryCode.toLowerCase(),
66730 tkey = field.strings.placeholders[localkey] ? localkey : d.id;
66731 return field.t('placeholders.' + tkey);
66733 .attr('class', function (d) { return 'addr-' + d.id; })
66735 .style('width', function (d) { return d.width * 100 + '%'; });
66739 // setup dropdowns for common address tags
66740 var dropdowns = addressFormat.dropdowns || [
66741 'city', 'county', 'country', 'district', 'hamlet',
66742 'neighbourhood', 'place', 'postcode', 'province',
66743 'quarter', 'state', 'street', 'subdistrict', 'suburb'
66746 // If fields exist for any of these tags, create dropdowns to pick nearby values..
66747 dropdowns.forEach(function(tag) {
66748 var nearValues = (tag === 'street') ? getNearStreets
66749 : (tag === 'city') ? getNearCities
66752 wrap.selectAll('input.addr-' + tag)
66754 .container(context.container())
66756 .fetcher(function(value, callback) {
66757 callback(nearValues('addr:' + tag));
66762 wrap.selectAll('input')
66763 .on('blur', change())
66764 .on('change', change());
66766 wrap.selectAll('input:not(.combobox-input)')
66767 .on('input', change(true));
66769 dispatch$$1.call('init');
66770 isInitialized = true;
66774 function address(selection$$1) {
66775 isInitialized = false;
66777 wrap = selection$$1.selectAll('.preset-input-wrap')
66780 wrap = wrap.enter()
66782 .attr('class', 'preset-input-wrap')
66785 if (nominatim && entity) {
66786 var center = entity.extent(context.graph()).center();
66787 nominatim.countryCode(center, initCallback);
66792 function change(onInput) {
66793 return function() {
66796 wrap.selectAll('input')
66797 .each(function (field) {
66798 tags['addr:' + field.id] = this.value || undefined;
66801 dispatch$$1.call('change', this, tags, onInput);
66806 function updateTags(tags) {
66807 utilGetSetValue(wrap.selectAll('input'), function (field) {
66808 return tags['addr:' + field.id] || '';
66813 address.entity = function(_) {
66814 if (!arguments.length) return entity;
66820 address.tags = function(tags) {
66821 if (isInitialized) {
66824 dispatch$$1.on('init', function () {
66825 dispatch$$1.on('init', null);
66832 address.focus = function() {
66833 var node = wrap.selectAll('input').node();
66834 if (node) node.focus();
66838 return utilRebind(address, dispatch$$1, 'on');
66841 function uiFieldCycleway(field, context) {
66842 var dispatch$$1 = dispatch('change'),
66843 items = select(null);
66846 function cycleway(selection$$1) {
66848 function stripcolon(s) {
66849 return s.replace(':', '');
66853 var wrap = selection$$1.selectAll('.preset-input-wrap')
66856 wrap = wrap.enter()
66858 .attr('class', 'cf preset-input-wrap')
66862 var div = wrap.selectAll('ul')
66870 items = div.selectAll('li')
66873 var enter = items.enter()
66875 .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
66879 .attr('class', 'col6 label preset-label-cycleway')
66880 .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
66881 .text(function(d) { return field.t('types.' + d); });
66885 .attr('class', 'col6 preset-input-cycleway-wrap')
66887 .attr('type', 'text')
66888 .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
66890 .each(function(d) {
66893 .container(context.container())
66894 .data(cycleway.options(d))
66900 wrap.selectAll('.preset-input-cycleway')
66901 .on('change', change)
66902 .on('blur', change);
66906 function change() {
66907 var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
66908 right = utilGetSetValue(select('.preset-input-cyclewayright')),
66911 if (left === 'none' || left === '') { left = undefined; }
66912 if (right === 'none' || right === '') { right = undefined; }
66914 // Always set both left and right as changing one can affect the other
66916 cycleway: undefined,
66917 'cycleway:left': left,
66918 'cycleway:right': right
66921 // If the left and right tags match, use the cycleway tag to tag both
66922 // sides the same way
66923 if (left === right) {
66926 'cycleway:left': undefined,
66927 'cycleway:right': undefined
66931 dispatch$$1.call('change', this, tag);
66935 cycleway.options = function() {
66936 return keys(field.strings.options).map(function(option) {
66938 title: field.t('options.' + option + '.description'),
66945 cycleway.tags = function(tags) {
66946 utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
66947 // If cycleway is set, always return that
66948 if (tags.cycleway) {
66949 return tags.cycleway;
66951 return tags[d] || '';
66953 .attr('placeholder', field.placeholder());
66957 cycleway.focus = function() {
66958 items.selectAll('.preset-input-cycleway')
66963 return utilRebind(cycleway, dispatch$$1, 'on');
66966 function uiFieldLanes(field, context) {
66967 var dispatch$$1 = dispatch('change'),
66973 function lanes(selection$$1) {
66974 lanesData = context.entity(wayID).lanes();
66976 if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
66977 selection$$1.call(lanes.off);
66981 var wrap = selection$$1.selectAll('.preset-input-wrap')
66984 wrap = wrap.enter()
66986 .attr('class', 'preset-input-wrap')
66989 var surface = wrap.selectAll('.surface')
66992 var d = utilGetDimensions(wrap);
66993 var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
66995 surface = surface.enter()
66997 .attr('width', d[0])
66998 .attr('height', 300)
66999 .attr('class', 'surface')
67003 var lanesSelection = surface.selectAll('.lanes')
67006 lanesSelection = lanesSelection.enter()
67008 .attr('class', 'lanes')
67009 .merge(lanesSelection);
67012 .attr('transform', function () {
67013 return 'translate(' + (freeSpace / 2) + ', 0)';
67017 var lane = lanesSelection.selectAll('.lane')
67018 .data(lanesData.lanes);
67023 var enter = lane.enter()
67025 .attr('class', 'lane');
67031 .attr('width', LANE_WIDTH)
67032 .attr('height', LANE_HEIGHT);
67036 .attr('class', 'forward')
67044 .attr('class', 'bothways')
67052 .attr('class', 'backward')
67063 .attr('transform', function(d) {
67064 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
67067 lane.select('.forward')
67068 .style('visibility', function(d) {
67069 return d.direction === 'forward' ? 'visible' : 'hidden';
67072 lane.select('.bothways')
67073 .style('visibility', function(d) {
67074 return d.direction === 'bothways' ? 'visible' : 'hidden';
67077 lane.select('.backward')
67078 .style('visibility', function(d) {
67079 return d.direction === 'backward' ? 'visible' : 'hidden';
67084 lanes.entity = function(_) {
67085 if (!wayID || wayID !== _.id) {
67090 lanes.tags = function() {};
67091 lanes.focus = function() {};
67092 lanes.off = function() {};
67094 return utilRebind(lanes, dispatch$$1, 'on');
67097 function uiFieldLocalized(field, context) {
67098 var dispatch$$1 = dispatch('change', 'input'),
67099 wikipedia = services.wikipedia,
67100 input = select(null),
67101 localizedInputs = select(null),
67106 function localized(selection$$1) {
67107 input = selection$$1.selectAll('.localized-main')
67110 input = input.enter()
67112 .attr('type', 'text')
67113 .attr('id', 'preset-input-' + field.id)
67114 .attr('class', 'localized-main')
67115 .attr('placeholder', field.placeholder())
67119 if (field.id === 'name') {
67120 var preset = context.presets().match(entity, context.graph());
67123 .container(context.container())
67124 .fetcher(utilSuggestNames(preset, dataSuggestions))
67129 .on('input', change(true))
67130 .on('blur', change())
67131 .on('change', change());
67134 var translateButton = selection$$1.selectAll('.localized-add')
67137 translateButton = translateButton.enter()
67139 .attr('class', 'button-input-action localized-add minor')
67140 .attr('tabindex', -1)
67141 .call(svgIcon('#icon-plus'))
67143 .title(t('translate.translate'))
67144 .placement('left'))
67145 .merge(translateButton);
67148 .on('click', addNew);
67151 localizedInputs = selection$$1.selectAll('.localized-wrap')
67154 localizedInputs = localizedInputs.enter().append('div')
67155 .attr('class', 'localized-wrap')
67156 .merge(localizedInputs);
67160 function addNew() {
67161 event.preventDefault();
67162 var data$$1 = localizedInputs.selectAll('div.entry').data();
67163 var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
67164 var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
67165 var isLangEn = defaultLang.indexOf('en') > -1;
67166 if (isLangEn || langExists) {
67169 data$$1.push({ lang: defaultLang, value: '' });
67170 localizedInputs.call(render, data$$1);
67174 function change(onInput) {
67175 return function() {
67177 t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
67178 dispatch$$1.call('change', this, t$$1, onInput);
67183 function key(lang) {
67184 return field.key + ':' + lang;
67188 function changeLang(d) {
67189 var lang = utilGetSetValue(select(this)),
67191 language = lodash.find(dataWikipedia, function(d) {
67192 return d[0].toLowerCase() === lang.toLowerCase() ||
67193 d[1].toLowerCase() === lang.toLowerCase();
67196 if (language) lang = language[2];
67198 if (d.lang && d.lang !== lang) {
67199 t$$1[key(d.lang)] = undefined;
67202 var value = utilGetSetValue(select(this.parentNode)
67203 .selectAll('.localized-value'));
67205 if (lang && value) {
67206 t$$1[key(lang)] = value;
67207 } else if (lang && wikiTitles && wikiTitles[d.lang]) {
67208 t$$1[key(lang)] = wikiTitles[d.lang];
67212 dispatch$$1.call('change', this, t$$1);
67216 function changeValue(d) {
67217 if (!d.lang) return;
67219 t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
67220 dispatch$$1.call('change', this, t$$1);
67224 function fetcher(value, cb) {
67225 var v = value.toLowerCase();
67227 cb(dataWikipedia.filter(function(d) {
67228 return d[0].toLowerCase().indexOf(v) >= 0 ||
67229 d[1].toLowerCase().indexOf(v) >= 0 ||
67230 d[2].toLowerCase().indexOf(v) >= 0;
67231 }).map(function(d) {
67232 return { value: d[1] };
67237 function render(selection$$1, data$$1) {
67238 var wraps = selection$$1.selectAll('div.entry').
67239 data(data$$1, function(d) { return d.lang; });
67244 .style('max-height','0px')
67245 .style('opacity', '0')
67246 .style('top','-10px')
67249 var innerWrap = wraps.enter()
67250 .insert('div', ':first-child');
67252 innerWrap.attr('class', 'entry')
67254 var wrap = select(this);
67255 var langcombo = d3combobox()
67256 .container(context.container())
67262 .attr('class','form-label')
67263 .text(t('translate.localized_translation_label'))
67264 .attr('for','localized-lang');
67268 .attr('class', 'minor remove')
67269 .on('click', function(d){
67270 event.preventDefault();
67272 t$$1[key(d.lang)] = undefined;
67273 dispatch$$1.call('change', this, t$$1);
67274 select(this.parentNode.parentNode)
67276 .style('max-height','240px')
67278 .style('opacity', '0')
67279 .style('max-height','0px')
67282 .call(svgIcon('#operation-delete'));
67286 .attr('class', 'localized-lang')
67287 .attr('type', 'text')
67288 .attr('placeholder',t('translate.localized_translation_language'))
67289 .on('blur', changeLang)
67290 .on('change', changeLang)
67295 .on('blur', changeValue)
67296 .on('change', changeValue)
67297 .attr('type', 'text')
67298 .attr('placeholder', t('translate.localized_translation_name'))
67299 .attr('class', 'localized-value');
67303 .style('margin-top', '0px')
67304 .style('max-height', '0px')
67305 .style('opacity', '0')
67308 .style('margin-top', '10px')
67309 .style('max-height', '240px')
67310 .style('opacity', '1')
67311 .on('end', function() {
67313 .style('max-height', '')
67314 .style('overflow', 'visible');
67318 var entry = selection$$1.selectAll('.entry');
67320 utilGetSetValue(entry.select('.localized-lang'), function(d) {
67321 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
67322 return lang ? lang[1] : d.lang;
67325 utilGetSetValue(entry.select('.localized-value'),
67326 function(d) { return d.value; });
67330 localized.tags = function(tags) {
67331 // Fetch translations from wikipedia
67332 if (tags.wikipedia && !wikiTitles) {
67334 var wm = tags.wikipedia.match(/([^:]+):(.+)/);
67335 if (wm && wm[0] && wm[1]) {
67336 wikipedia.translations(wm[1], wm[2], function(d) {
67342 utilGetSetValue(input, tags[field.key] || '');
67344 var postfixed = [], k, m;
67346 m = k.match(/^(.*):([a-zA-Z_-]+)$/);
67347 if (m && m[1] === field.key && m[2]) {
67348 postfixed.push({ lang: m[2], value: tags[k] });
67352 localizedInputs.call(render, postfixed.reverse());
67356 localized.focus = function() {
67357 input.node().focus();
67361 localized.entity = function(_) {
67362 if (!arguments.length) return entity;
67367 return utilRebind(localized, dispatch$$1, 'on');
67370 function uiFieldMaxspeed(field, context) {
67371 var dispatch$$1 = dispatch('change'),
67374 unitInput = select(null),
67375 input = select(null),
67378 var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
67379 imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
67382 function maxspeed(selection$$1) {
67383 combobox = d3combobox()
67384 .container(context.container());
67386 var unitCombobox = d3combobox()
67387 .container(context.container())
67388 .data(['km/h', 'mph'].map(comboValues));
67390 input = selection$$1.selectAll('#preset-input-' + field.id)
67393 input = input.enter()
67395 .attr('type', 'text')
67396 .attr('id', 'preset-input-' + field.id)
67397 .attr('placeholder', field.placeholder())
67403 .on('change', change)
67404 .on('blur', change);
67406 var childNodes = context.graph().childNodes(context.entity(entity.id)),
67407 loc = childNodes[~~(childNodes.length/2)].loc;
67409 isImperial = lodash.some(dataImperial.features, function(f) {
67410 return lodash.some(f.geometry.coordinates, function(d) {
67411 return geoPointInPolygon(loc, d);
67415 unitInput = selection$$1.selectAll('input.maxspeed-unit')
67418 unitInput = unitInput.enter()
67420 .attr('type', 'text')
67421 .attr('class', 'maxspeed-unit')
67422 .call(unitCombobox)
67426 .on('blur', changeUnits)
67427 .on('change', changeUnits);
67430 function changeUnits() {
67431 isImperial = utilGetSetValue(unitInput) === 'mph';
67432 utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
67439 function setSuggestions() {
67440 combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
67441 utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
67445 function comboValues(d) {
67447 value: d.toString(),
67448 title: d.toString()
67453 function change() {
67455 value = utilGetSetValue(input);
67458 tag[field.key] = undefined;
67459 } else if (isNaN(value) || !isImperial) {
67460 tag[field.key] = value;
67462 tag[field.key] = value + ' mph';
67465 dispatch$$1.call('change', this, tag);
67469 maxspeed.tags = function(tags) {
67470 var value = tags[field.key];
67472 if (value && value.indexOf('mph') >= 0) {
67473 value = parseInt(value, 10);
67475 } else if (value) {
67476 isImperial = false;
67480 utilGetSetValue(input, value || '');
67484 maxspeed.focus = function() {
67485 input.node().focus();
67489 maxspeed.entity = function(_) {
67494 return utilRebind(maxspeed, dispatch$$1, 'on');
67497 function uiFieldRadio(field, context) {
67498 var dispatch$$1 = dispatch('change'),
67499 taginfo = services.taginfo,
67500 placeholder = select(null),
67501 wrap = select(null),
67502 labels = select(null),
67503 radios = select(null),
67504 typeInput = select(null),
67505 layerInput = select(null),
67510 function selectedKey() {
67511 var selector$$1 = '.form-field-structure .toggle-list label.active input',
67512 node = selectAll(selector$$1);
67513 return !node.empty() && node.datum();
67516 // returns the tag value for a display value
67517 function tagValue(dispVal) {
67518 dispVal = snake(clean(dispVal || ''));
67519 return dispVal.toLowerCase() || 'yes';
67522 // returns the display value for a tag value
67523 function displayValue(tagVal) {
67524 tagVal = tagVal || '';
67525 return tagVal.toLowerCase() === 'yes' ? '' : unsnake(tagVal);
67528 function snake(s) {
67529 return s.replace(/\s+/g, '_');
67532 function unsnake(s) {
67533 return s.replace(/_+/g, ' ');
67536 function clean(s) {
67537 return s.split(';')
67538 .map(function(s) { return s.trim(); })
67543 function radio(selection$$1) {
67544 selection$$1.classed('preset-radio', true);
67546 wrap = selection$$1.selectAll('.preset-input-wrap')
67549 var enter = wrap.enter()
67551 .attr('class', 'preset-input-wrap toggle-list');
67555 .attr('class', 'placeholder');
67561 placeholder = wrap.selectAll('.placeholder');
67563 labels = wrap.selectAll('label')
67564 .data(field.options || field.keys);
67566 enter = labels.enter()
67571 .attr('type', 'radio')
67572 .attr('name', field.id)
67573 .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
67574 .attr('checked', false);
67578 .text(function(d) { return field.t('options.' + d, { 'default': d }); });
67583 radios = labels.selectAll('input')
67584 .on('change', changeRadio);
67588 function structureExtras(selection$$1) {
67589 var selected = selectedKey();
67591 var extrasWrap = selection$$1.selectAll('.structure-extras-wrap')
67592 .data(selected ? [0] : []);
67597 extrasWrap = extrasWrap.enter()
67599 .attr('class', 'structure-extras-wrap')
67600 .merge(extrasWrap);
67602 var list = extrasWrap.selectAll('ul')
67605 list = list.enter()
67611 var typeItem = list.selectAll('.structure-type-item')
67614 var typeEnter = typeItem.enter()
67616 .attr('class', 'cf structure-type-item');
67620 .attr('class', 'col6 label structure-label-type')
67621 .attr('for', 'structure-input-type')
67622 .text(t('inspector.radio.structure.type'));
67626 .attr('class', 'col6 structure-input-type-wrap')
67628 .attr('type', 'text')
67629 .attr('class', 'structure-input-type')
67630 .attr('placeholder', t('inspector.radio.structure.default'))
67633 typeItem = typeItem
67636 typeInput = typeItem.selectAll('.structure-input-type');
67641 .container(context.container())
67642 .fetcher(typeFetcher)
67647 .on('change', changeType)
67648 .on('blur', changeType);
67652 var showLayer = (selected === 'bridge' || selected === 'tunnel');
67654 var layerItem = list.selectAll('.structure-layer-item')
67655 .data(showLayer ? [0] : []);
67660 var layerEnter = layerItem.enter()
67662 .attr('class', 'cf structure-layer-item');
67666 .attr('class', 'col6 label structure-label-layer')
67667 .attr('for', 'structure-input-layer')
67668 .text(t('inspector.radio.structure.layer'));
67672 .attr('class', 'col6 structure-input-layer-wrap')
67674 .attr('type', 'text')
67675 .attr('class', 'structure-input-layer')
67676 .attr('placeholder', '0')
67679 var spin = layerEnter
67681 .attr('class', 'spin-control');
67686 .attr('class', 'decrement')
67687 .attr('tabindex', -1);
67692 .attr('class', 'increment')
67693 .attr('tabindex', -1);
67695 layerItem = layerItem
67696 .merge(layerEnter);
67698 layerInput = layerItem.selectAll('.structure-input-layer')
67699 .on('change', changeLayer)
67700 .on('blur', changeLayer);
67702 layerItem.selectAll('button')
67703 .on('click', function(d) {
67704 event.preventDefault();
67705 var num = parseInt(layerInput.node().value || 0, 10);
67706 if (!isNaN(num)) layerInput.node().value = num + d;
67713 function typeFetcher(q, callback) {
67716 key: selectedKey(),
67718 }, function(err, data) {
67720 var comboData = data.map(function(d) {
67723 value: unsnake(d.value),
67727 if (callback) callback(comboData);
67732 function changeType() {
67733 var key = selectedKey(),
67737 var val = tagValue(utilGetSetValue(typeInput));
67739 if (val !== 'no') oldType[key] = val;
67740 dispatch$$1.call('change', this, t$$1);
67744 function changeLayer() {
67745 // note: don't use utilGetSetValue here because we want 0 to be falsy.
67746 var t$$1 = { layer: layerInput.node().value || undefined };
67747 dispatch$$1.call('change', this, t$$1);
67751 function changeRadio() {
67756 t$$1[field.key] = undefined;
67759 radios.each(function(d) {
67760 var active$$1 = select(this).property('checked');
67761 if (active$$1) activeKey = d;
67764 if (active$$1) t$$1[field.key] = d;
67766 var val = oldType[activeKey] || 'yes';
67767 t$$1[d] = active$$1 ? val : undefined;
67771 if (field.type === 'structureRadio') {
67772 if (activeKey === 'bridge') {
67774 } else if (activeKey === 'tunnel') {
67777 t$$1.layer = undefined;
67781 dispatch$$1.call('change', this, t$$1);
67785 radio.tags = function(tags) {
67786 function checked(d) {
67788 return tags[field.key] === d;
67790 return !!(tags[d] && tags[d].toLowerCase() !== 'no');
67794 labels.classed('active', checked);
67795 radios.property('checked', checked);
67797 var selection$$1 = radios.filter(function() { return this.checked; });
67800 if (selection$$1.empty()) {
67801 placeholder.text(t('inspector.none'));
67803 placeholder.text(selection$$1.attr('value'));
67804 typeVal = oldType[selection$$1.datum()] = tags[selection$$1.datum()];
67807 if (field.type === 'structureRadio') {
67808 wrap.call(structureExtras);
67809 utilGetSetValue(typeInput, displayValue(typeVal) || '');
67810 utilGetSetValue(layerInput, tags.layer || '');
67815 radio.focus = function() {
67816 radios.node().focus();
67820 radio.entity = function(_) {
67821 if (!arguments.length) return entity;
67828 return utilRebind(radio, dispatch$$1, 'on');
67831 function uiFieldRestrictions(field, context) {
67832 var dispatch$$1 = dispatch('change'),
67833 breathe = behaviorBreathe(context),
67834 hover = behaviorHover(context),
67835 initialized = false,
67840 function restrictions(selection$$1) {
67841 // if form field is hidden or has detached from dom, clean up.
67842 if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
67843 selection$$1.call(restrictions.off);
67847 var wrap = selection$$1.selectAll('.preset-input-wrap')
67850 var enter = wrap.enter()
67852 .attr('class', 'preset-input-wrap');
67856 .attr('class', 'restriction-help');
67859 var intersection = osmIntersection(context.graph(), vertexID),
67860 graph = intersection.graph,
67861 vertex = graph.entity(vertexID),
67862 filter = utilFunctor(true),
67863 extent$$1 = geoExtent$$1(),
67864 projection = geoRawMercator();
67866 var d = utilGetDimensions(wrap.merge(enter)),
67867 c = [d[0] / 2, d[1] / 2],
67871 .scale(256 * Math.pow(2, z) / (2 * Math.PI));
67873 var s = projection(vertex.loc);
67876 .translate([c[0] - s[0], c[1] - s[1]])
67877 .clipExtent([[0, 0], d]);
67879 var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
67880 drawVertices = svgVertices$$1(projection, context),
67881 drawLines = svgLines$$1(projection, context),
67882 drawTurns = svgTurns(projection, context);
67890 var surface = wrap.selectAll('.surface');
67892 if (!enter.empty()) {
67893 initialized = true;
67900 .call(utilSetDimensions, d)
67901 .call(drawVertices, graph, [vertex], filter, extent$$1, z)
67902 .call(drawLines, graph, intersection.ways, filter)
67903 .call(drawTurns, graph, intersection.turns(fromNodeID));
67906 .on('click.restrictions', click)
67907 .on('mouseover.restrictions', mouseover)
67908 .on('mouseout.restrictions', mouseout);
67911 .selectAll('.selected')
67912 .classed('selected', false);
67916 .selectAll('.' + intersection.highways[fromNodeID].id)
67917 .classed('selected', true);
67923 .on('change.restrictions', render);
67926 .on('resize.restrictions', function() {
67927 utilSetDimensions(wrap, null);
67937 var datum = event.target.__data__;
67938 if (datum instanceof osmEntity$$1) {
67939 fromNodeID = intersection.adjacentNodeId(datum.id);
67941 } else if (datum instanceof osmTurn) {
67942 if (datum.restriction) {
67944 actionUnrestrictTurn(datum, projection),
67945 t('operations.restriction.annotation.delete')
67949 actionRestrictTurn(datum, projection),
67950 t('operations.restriction.annotation.create')
67957 function mouseover() {
67958 var datum = event.target.__data__;
67959 if (datum instanceof osmTurn) {
67960 var graph = context.graph(),
67961 presets = context.presets(),
67964 if (datum.restriction) {
67965 preset = presets.match(graph.entity(datum.restriction), graph);
67967 preset = presets.item('type/restriction/' +
67968 osmInferRestriction(
67978 wrap.selectAll('.restriction-help')
67979 .text(t('operations.restriction.help.' +
67980 (datum.restriction ? 'toggle_off' : 'toggle_on'),
67981 { restriction: preset.name() })
67987 function mouseout() {
67988 wrap.selectAll('.restriction-help')
67989 .text(t('operations.restriction.help.' +
67990 (fromNodeID ? 'toggle' : 'select'))
67995 function render() {
67996 if (context.hasEntity(vertexID)) {
67997 restrictions(selection$$1);
68003 restrictions.entity = function(_) {
68004 if (!vertexID || vertexID !== _.id) {
68011 restrictions.tags = function() {};
68012 restrictions.focus = function() {};
68015 restrictions.off = function(selection$$1) {
68016 if (!initialized) return;
68018 selection$$1.selectAll('.surface')
68021 .on('click.restrictions', null)
68022 .on('mouseover.restrictions', null)
68023 .on('mouseout.restrictions', null);
68026 .on('change.restrictions', null);
68029 .on('resize.restrictions', null);
68033 return utilRebind(restrictions, dispatch$$1, 'on');
68036 function uiFieldTextarea(field) {
68037 var dispatch$$1 = dispatch('change'),
68038 input = select(null);
68041 function textarea(selection$$1) {
68042 input = selection$$1.selectAll('textarea')
68045 input = input.enter()
68046 .append('textarea')
68047 .attr('id', 'preset-input-' + field.id)
68048 .attr('placeholder', field.placeholder() || t('inspector.unknown'))
68049 .attr('maxlength', 255)
68051 .on('input', change(true))
68052 .on('blur', change())
68053 .on('change', change())
68058 function change(onInput) {
68059 return function() {
68061 t$$1[field.key] = utilGetSetValue(input) || undefined;
68062 dispatch$$1.call('change', this, t$$1, onInput);
68067 textarea.tags = function(tags) {
68068 utilGetSetValue(input, tags[field.key] || '');
68072 textarea.focus = function() {
68073 input.node().focus();
68077 return utilRebind(textarea, dispatch$$1, 'on');
68080 function uiFieldWikipedia(field, context) {
68081 var dispatch$$1 = dispatch('change'),
68082 wikipedia = services.wikipedia,
68083 wikidata = services.wikidata,
68084 link = select(null),
68085 lang = select(null),
68086 title = select(null),
68091 function wiki(selection$$1) {
68092 var langcombo = d3combobox()
68093 .container(context.container())
68094 .fetcher(function(value, cb) {
68095 var v = value.toLowerCase();
68097 cb(dataWikipedia.filter(function(d) {
68098 return d[0].toLowerCase().indexOf(v) >= 0 ||
68099 d[1].toLowerCase().indexOf(v) >= 0 ||
68100 d[2].toLowerCase().indexOf(v) >= 0;
68101 }).map(function(d) {
68102 return { value: d[1] };
68106 var titlecombo = d3combobox()
68107 .container(context.container())
68108 .fetcher(function(value, cb) {
68110 value = context.entity(entity.id).tags.name || '';
68113 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
68114 searchfn(language()[2], value, function(query, data$$1) {
68115 cb(data$$1.map(function(d) {
68116 return { value: d };
68122 lang = selection$$1.selectAll('input.wiki-lang')
68125 lang = lang.enter()
68127 .attr('type', 'text')
68128 .attr('class', 'wiki-lang')
68129 .attr('placeholder', t('translate.localized_translation_language'))
68133 utilGetSetValue(lang, language()[1]);
68137 .on('blur', changeLang)
68138 .on('change', changeLang);
68141 title = selection$$1.selectAll('input.wiki-title')
68144 title = title.enter()
68146 .attr('type', 'text')
68147 .attr('class', 'wiki-title')
68148 .attr('id', 'preset-input-' + field.id)
68155 .on('change', change);
68158 link = selection$$1.selectAll('.wiki-link')
68161 link = link.enter()
68163 .attr('class', 'button-input-action wiki-link minor')
68164 .attr('tabindex', -1)
68165 .call(svgIcon('#icon-out-link'))
68169 .on('click', function() {
68170 event.preventDefault();
68171 if (wikiURL) window.open(wikiURL, '_blank');
68176 function language() {
68177 var value = utilGetSetValue(lang).toLowerCase();
68178 var locale = utilDetect().locale.toLowerCase();
68179 var localeLanguage;
68180 return lodash.find(dataWikipedia, function(d) {
68181 if (d[2] === locale) localeLanguage = d;
68182 return d[0].toLowerCase() === value ||
68183 d[1].toLowerCase() === value ||
68185 }) || localeLanguage || ['English', 'English', 'en'];
68189 function changeLang() {
68190 utilGetSetValue(lang, language()[1]);
68200 function change(skipWikidata) {
68201 var value = utilGetSetValue(title),
68202 m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
68203 l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
68208 // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
68209 value = decodeURIComponent(m[2]).replace(/_/g, ' ');
68212 // Best-effort `anchordecode:` implementation
68213 anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
68215 anchor = decodeURIComponent(m[3]);
68217 value += '#' + anchor.replace(/_/g, ' ');
68219 value = value.slice(0, 1).toUpperCase() + value.slice(1);
68220 utilGetSetValue(lang, l[1]);
68221 utilGetSetValue(title, value);
68224 syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
68225 if (!skipWikidata) {
68226 syncTags.wikidata = undefined;
68229 dispatch$$1.call('change', this, syncTags);
68232 if (skipWikidata || !value || !language()[2]) return;
68234 // attempt asynchronous update of wikidata tag..
68235 var initEntityId = entity.id,
68236 initWikipedia = context.entity(initEntityId).tags.wikipedia;
68238 wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
68239 if (!data$$1 || !Object.keys(data$$1).length) return;
68240 var qids = Object.keys(data$$1);
68242 // 1. most recent change was a tag change
68243 var annotation = t('operations.change_tags.annotation'),
68244 currAnnotation = context.history().undoAnnotation();
68245 if (currAnnotation !== annotation) return;
68247 // 2. same entity exists and still selected
68248 var selectedIds = context.selectedIDs(),
68249 currEntityId = selectedIds.length > 0 && selectedIds[0];
68250 if (currEntityId !== initEntityId) return;
68252 // 3. wikipedia value has not changed
68253 var currTags = lodash.clone(context.entity(currEntityId).tags);
68254 if (initWikipedia !== currTags.wikipedia) return;
68256 // ok to coalesce the update of wikidata tag into the previous tag change
68257 currTags.wikidata = qids && lodash.find(qids, function(id) {
68258 return id.match(/^Q\d+$/);
68261 context.overwrite(actionChangeTags(currEntityId, currTags), annotation);
68262 dispatch$$1.call('change', this, currTags);
68267 wiki.tags = function(tags) {
68268 var value = tags[field.key] || '',
68269 m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
68270 l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
68271 anchor = m && m[3];
68273 // value in correct format
68275 utilGetSetValue(lang, l[1]);
68276 utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
68279 // Best-effort `anchorencode:` implementation
68280 anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
68282 anchor = anchor.replace(/ /g, '_');
68285 wikiURL = 'https://' + m[1] + '.wikipedia.org/wiki/' +
68286 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : '');
68288 // unrecognized value format
68290 utilGetSetValue(title, value);
68291 if (value && value !== '') {
68292 utilGetSetValue(lang, '');
68293 wikiURL = 'https://en.wikipedia.org/wiki/Special:Search?search=' + value;
68301 wiki.entity = function(_) {
68302 if (!arguments.length) return entity;
68308 wiki.focus = function() {
68309 title.node().focus();
68313 return utilRebind(wiki, dispatch$$1, 'on');
68317 access: uiFieldAccess,
68318 address: uiFieldAddress,
68319 check: uiFieldCheck,
68320 combo: uiFieldCombo,
68321 cycleway: uiFieldCycleway,
68322 defaultCheck: uiFieldCheck,
68323 email: uiFieldText,
68324 lanes: uiFieldLanes,
68325 localized: uiFieldLocalized,
68326 maxspeed: uiFieldMaxspeed,
68327 multiCombo: uiFieldCombo,
68328 networkCombo: uiFieldCombo,
68329 number: uiFieldText,
68330 onewayCheck: uiFieldCheck,
68331 radio: uiFieldRadio,
68332 restrictions: uiFieldRestrictions,
68333 semiCombo: uiFieldCombo,
68334 structureRadio: uiFieldRadio,
68337 textarea: uiFieldTextarea,
68338 typeCombo: uiFieldCombo,
68340 wikipedia: uiFieldWikipedia
68343 function uiPreset(context) {
68344 var dispatch$$1 = dispatch('change'),
68352 // Field Constructor
68353 function UIField(field, entity, show) {
68354 field = lodash.clone(field);
68356 field.input = uiFields[field.type](field, context)
68357 .on('change', function(t$$1, onInput) {
68358 dispatch$$1.call('change', field, t$$1, onInput);
68361 if (field.input.entity) field.input.entity(entity);
68363 field.keys = field.keys || [field.key];
68367 field.shown = function() {
68368 return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
68371 field.modified = function() {
68372 var original = context.graph().base().entities[entity.id];
68373 return lodash.some(field.keys, function(key) {
68374 return original ? tags[key] !== original.tags[key] : tags[key];
68378 field.revert = function() {
68379 var original = context.graph().base().entities[entity.id],
68381 field.keys.forEach(function(key) {
68382 t$$1[key] = original ? original.tags[key] : undefined;
68387 field.present = function() {
68388 return lodash.some(field.keys, function(key) {
68393 field.remove = function() {
68395 field.keys.forEach(function(key) {
68396 t$$1[key] = undefined;
68405 function fieldKey(field) {
68410 function presets(selection$$1) {
68411 selection$$1.call(uiDisclosure()
68412 .title(t('inspector.all_fields'))
68413 .expanded(context.storage('preset_fields.expanded') !== 'false')
68414 .on('toggled', toggled)
68418 function toggled(expanded) {
68419 context.storage('preset_fields.expanded', expanded);
68424 function content(selection$$1) {
68426 var entity = context.entity(id),
68427 geometry = context.geometry(id),
68428 presets = context.presets();
68432 if (presets.field('name')) {
68433 fieldsArr.push(UIField(presets.field('name'), entity));
68436 preset.fields.forEach(function(field) {
68437 if (field.matchGeometry(geometry)) {
68438 fieldsArr.push(UIField(field, entity, true));
68442 if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
68443 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
68446 presets.universal().forEach(function(field) {
68447 if (preset.fields.indexOf(field) < 0) {
68448 fieldsArr.push(UIField(field, entity));
68453 var shown = fieldsArr.filter(function(field) { return field.shown(); }),
68454 notShown = fieldsArr.filter(function(field) { return !field.shown(); });
68457 var form = selection$$1.selectAll('.preset-form')
68460 form = form.enter()
68462 .attr('class', 'preset-form inspector-inner fillL3')
68466 var fields = form.selectAll('.form-field')
68467 .data(shown, fieldKey);
68473 var enter = fields.enter()
68475 .attr('class', function(field) {
68476 return 'form-field form-field-' + field.id;
68481 .attr('class', 'form-label')
68482 .attr('for', function(field) { return 'preset-input-' + field.id; })
68483 .text(function(field) { return field.label(); });
68487 .attr('class', 'form-label-button-wrap');
68489 wrap.append('button')
68490 .attr('class', 'remove-icon')
68491 .attr('tabindex', -1)
68492 .call(svgIcon('#operation-delete'));
68494 wrap.append('button')
68495 .attr('class', 'modified-icon')
68496 .attr('tabindex', -1)
68498 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
68506 fields.selectAll('.form-label-button-wrap .remove-icon')
68507 .on('click', remove);
68509 fields.selectAll('.modified-icon')
68510 .on('click', revert);
68514 .classed('modified', function(field) { return field.modified(); })
68515 .classed('present', function(field) { return field.present(); })
68516 .each(function(field) {
68517 var reference = uiTagReference(field.reference || { key: field.key }, context);
68519 if (state === 'hover') {
68520 reference.showing(false);
68525 .selectAll('input')
68526 .on('keydown', function() {
68527 // if user presses enter, and combobox is not active, accept edits..
68528 if (event.keyCode === 13 && select('.combobox').empty()) {
68529 context.enter(modeBrowse(context));
68534 .call(reference.body)
68535 .select('.form-label-button-wrap')
68536 .call(reference.button);
68538 field.input.tags(tags);
68541 notShown = notShown.map(function(field) {
68543 title: field.label(),
68544 value: field.label(),
68550 var more = selection$$1.selectAll('.more-fields')
68551 .data((notShown.length > 0) ? [0] : []);
68556 more = more.enter()
68558 .attr('class', 'more-fields')
68560 .text(t('inspector.add_fields'))
68564 var input = more.selectAll('.value')
68570 input = input.enter()
68572 .attr('class', 'value')
68573 .attr('type', 'text')
68578 .call(utilGetSetValue, '')
68579 .attr('placeholder', function() {
68580 var placeholder = [];
68581 for (var field in notShown) {
68582 placeholder.push(notShown[field].title);
68584 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
68587 .container(context.container())
68590 .on('accept', show)
68594 function show(field) {
68595 field = field.field;
68597 content(selection$$1);
68598 field.input.focus();
68602 function revert(field) {
68603 event.stopPropagation();
68604 event.preventDefault();
68605 dispatch$$1.call('change', field, field.revert());
68609 function remove(field) {
68610 event.stopPropagation();
68611 event.preventDefault();
68612 dispatch$$1.call('change', field, field.remove());
68617 presets.preset = function(_) {
68618 if (!arguments.length) return preset;
68619 if (preset && preset.id === _.id) return presets;
68626 presets.state = function(_) {
68627 if (!arguments.length) return state;
68633 presets.tags = function(_) {
68634 if (!arguments.length) return tags;
68636 // Don't reset fieldsArr here.
68641 presets.entityID = function(_) {
68642 if (!arguments.length) return id;
68643 if (id === _) return presets;
68650 return utilRebind(presets, dispatch$$1, 'on');
68653 function uiEntityEditor(context) {
68654 var dispatch$$1 = dispatch('choose'),
68656 coalesceChanges = false,
68663 var presetEditor = uiPreset(context)
68664 .on('change', changeTags);
68665 var rawTagEditor = uiRawTagEditor(context)
68666 .on('change', changeTags);
68669 function entityEditor(selection$$1) {
68670 var entity = context.entity(id),
68671 tags = lodash.clone(entity.tags);
68674 var header = selection$$1.selectAll('.header')
68678 var enter = header.enter()
68680 .attr('class', 'header fillL cf');
68684 .attr('class', 'fl preset-reset preset-choose')
68685 .call(svgIcon((textDirection === 'rtl') ? '#icon-forward' : '#icon-backward'));
68689 .attr('class', 'fr preset-close')
68690 .on('click', function() { context.enter(modeBrowse(context)); })
68691 .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
68695 .text(t('inspector.edit'));
68701 header.selectAll('.preset-reset')
68702 .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
68706 var body = selection$$1.selectAll('.inspector-body')
68710 enter = body.enter()
68712 .attr('class', 'inspector-body');
68716 .attr('class', 'preset-list-item inspector-inner')
68718 .attr('class', 'preset-list-button-wrap')
68720 .attr('class', 'preset-list-button preset-reset')
68721 .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
68723 .attr('class', 'label');
68727 .attr('class', 'inspector-border inspector-preset');
68731 .attr('class', 'inspector-border raw-tag-editor inspector-inner');
68735 .attr('class', 'inspector-border raw-member-editor inspector-inner');
68739 .attr('class', 'raw-membership-editor inspector-inner');
68745 body.selectAll('.preset-list-button-wrap')
68746 .call(reference.button);
68748 body.selectAll('.preset-list-item')
68749 .call(reference.body);
68751 body.selectAll('.preset-reset')
68752 .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
68754 body.select('.preset-list-item button')
68755 .call(uiPresetIcon()
68756 .geometry(context.geometry(id))
68757 .preset(activePreset));
68759 body.select('.preset-list-item .label')
68760 .text(activePreset.name());
68762 body.select('.inspector-preset')
68764 .preset(activePreset)
68769 body.select('.raw-tag-editor')
68771 .preset(activePreset)
68776 if (entity.type === 'relation') {
68777 body.select('.raw-member-editor')
68778 .style('display', 'block')
68779 .call(uiRawMemberEditor(context)
68782 body.select('.raw-member-editor')
68783 .style('display', 'none');
68786 body.select('.raw-membership-editor')
68787 .call(uiRawMembershipEditor(context)
68792 .on('change.entity-editor', historyChanged);
68795 function historyChanged() {
68796 if (state === 'hide') return;
68798 var entity = context.hasEntity(id),
68799 graph = context.graph();
68800 if (!entity) return;
68802 entityEditor.preset(context.presets().match(entity, graph));
68803 entityEditor.modified(base !== graph);
68804 entityEditor(selection$$1);
68809 function clean(o) {
68811 function cleanVal(k, v) {
68812 function keepSpaces(k) {
68813 return k.match(/_hours|_times/) !== null;
68816 var blacklist = ['description', 'note', 'fixme'];
68817 if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
68819 var cleaned = v.split(';')
68820 .map(function(s) { return s.trim(); })
68821 .join(keepSpaces(k) ? '; ' : ';');
68823 // The code below is not intended to validate websites and emails.
68824 // It is only intended to prevent obvious copy-paste errors. (#2323)
68825 // clean website- and email-like tags
68826 if (k.indexOf('website') !== -1 ||
68827 k.indexOf('email') !== -1 ||
68828 cleaned.indexOf('http') === 0) {
68830 .replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars
68837 var out = {}, k, v;
68839 if (k && (v = o[k]) !== undefined) {
68840 out[k] = cleanVal(k, v);
68847 // Tag changes that fire on input can all get coalesced into a single
68848 // history operation when the user leaves the field. #2342
68849 function changeTags(changed, onInput) {
68850 var entity = context.entity(id),
68851 annotation = t('operations.change_tags.annotation'),
68852 tags = lodash.clone(entity.tags);
68854 lodash.forEach(changed, function(v, k) {
68855 if (v !== undefined || tags.hasOwnProperty(k)) {
68861 tags = clean(tags);
68864 if (!lodash.isEqual(entity.tags, tags)) {
68865 if (coalesceChanges) {
68866 context.overwrite(actionChangeTags(id, tags), annotation);
68868 context.perform(actionChangeTags(id, tags), annotation);
68869 coalesceChanges = !!onInput;
68875 entityEditor.modified = function(_) {
68876 if (!arguments.length) return modified;
68878 selectAll('button.preset-close use')
68879 .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
68883 entityEditor.state = function(_) {
68884 if (!arguments.length) return state;
68886 return entityEditor;
68890 entityEditor.entityID = function(_) {
68891 if (!arguments.length) return id;
68893 base = context.graph();
68894 entityEditor.preset(context.presets().match(context.entity(id), base));
68895 entityEditor.modified(false);
68896 coalesceChanges = false;
68897 return entityEditor;
68901 entityEditor.preset = function(_) {
68902 if (!arguments.length) return activePreset;
68903 if (_ !== activePreset) {
68905 reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
68908 return entityEditor;
68912 return utilRebind(entityEditor, dispatch$$1, 'on');
68915 function uiPresetList(context) {
68916 var dispatch$$1 = dispatch('choose'),
68922 function presetList(selection$$1) {
68923 var entity = context.entity(id),
68924 geometry = context.geometry(id);
68926 // Treat entities on addr:interpolation lines as points, not vertices (#3241)
68927 if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
68928 geometry = 'point';
68931 var presets = context.presets().matchGeometry(geometry);
68933 selection$$1.html('');
68935 var messagewrap = selection$$1
68937 .attr('class', 'header fillL cf');
68939 var message = messagewrap
68941 .text(t('inspector.choose'));
68943 if (context.entity(id).isUsed(context.graph())) {
68946 .attr('class', 'preset-choose')
68947 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
68948 .call(svgIcon((textDirection === 'rtl') ? '#icon-backward' : '#icon-forward'));
68952 .attr('class', 'close')
68953 .on('click', function() {
68954 context.enter(modeBrowse(context));
68956 .call(svgIcon('#icon-close'));
68959 function keydown() {
68960 // hack to let delete shortcut work when search is autofocused
68961 if (search.property('value').length === 0 &&
68962 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
68963 event.keyCode === d3keybinding.keyCodes['⌦'])) {
68964 event.preventDefault();
68965 event.stopPropagation();
68966 operationDelete([id], context)();
68967 } else if (search.property('value').length === 0 &&
68968 (event.ctrlKey || event.metaKey) &&
68969 event.keyCode === d3keybinding.keyCodes.z) {
68970 event.preventDefault();
68971 event.stopPropagation();
68973 } else if (!event.ctrlKey && !event.metaKey) {
68974 select(this).on('keydown', null);
68978 function keypress() {
68980 var value = search.property('value');
68981 if (event.keyCode === 13 && value.length) {
68982 list.selectAll('.preset-list-item:first-child').datum().choose();
68986 function inputevent() {
68987 var value = search.property('value');
68988 list.classed('filtered', value.length);
68989 if (value.length) {
68990 var results = presets.search(value, geometry);
68991 message.text(t('inspector.results', {
68992 n: results.collection.length,
68995 list.call(drawList, results);
68997 list.call(drawList, context.presets().defaults(geometry, 36));
68998 message.text(t('inspector.choose'));
69002 var searchWrap = selection$$1
69004 .attr('class', 'search-header');
69006 var search = searchWrap
69008 .attr('class', 'preset-search-input')
69009 .attr('placeholder', t('inspector.search'))
69010 .attr('type', 'search')
69012 .on('keydown', keydown)
69013 .on('keypress', keypress)
69014 .on('input', inputevent);
69017 .call(svgIcon('#icon-search', 'pre-text'));
69020 search.node().focus();
69023 var listWrap = selection$$1
69025 .attr('class', 'inspector-body');
69027 var list = listWrap
69029 .attr('class', 'preset-list fillL cf')
69030 .call(drawList, context.presets().defaults(geometry, 36));
69034 function drawList(list, presets) {
69035 var collection = presets.collection.map(function(preset) {
69036 return preset.members ? CategoryItem(preset) : PresetItem(preset);
69039 var items = list.selectAll('.preset-list-item')
69040 .data(collection, function(d) { return d.preset.id; });
69049 .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
69050 .classed('current', function(item) { return item.preset === currentPreset; })
69051 .each(function(item) { select(this).call(item); })
69052 .style('opacity', 0)
69054 .style('opacity', 1);
69058 function CategoryItem(preset) {
69059 var box, sublist, shown = false;
69061 function item(selection$$1) {
69062 var wrap = selection$$1.append('div')
69063 .attr('class', 'preset-list-button-wrap category col12');
69067 .attr('class', 'preset-list-button')
69068 .classed('expanded', false)
69069 .call(uiPresetIcon()
69070 .geometry(context.geometry(id))
69072 .on('click', function() {
69073 var isExpanded = select(this).classed('expanded');
69074 var iconName = isExpanded ?
69075 (textDirection === 'rtl' ? '#icon-backward' : '#icon-forward') : '#icon-down';
69077 .classed('expanded', !isExpanded);
69078 select(this).selectAll('div.label svg.icon use')
69079 .attr('href', iconName);
69085 .attr('class', 'label');
69088 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'))
69090 .html(function() { return preset.name() + '…'; });
69092 box = selection$$1.append('div')
69093 .attr('class', 'subgrid col12')
69094 .style('max-height', '0px')
69095 .style('opacity', 0);
69098 .attr('class', 'arrow');
69100 sublist = box.append('div')
69101 .attr('class', 'preset-list fillL3 cf fl');
69105 item.choose = function() {
69106 if (!box || !sublist) return;
69112 .style('opacity', '0')
69113 .style('max-height', '0px')
69114 .style('padding-bottom', '0px');
69117 sublist.call(drawList, preset.members);
69120 .style('opacity', '1')
69121 .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
69122 .style('padding-bottom', '20px');
69126 item.preset = preset;
69132 function PresetItem(preset) {
69133 function item(selection$$1) {
69134 var wrap = selection$$1.append('div')
69135 .attr('class', 'preset-list-button-wrap col12');
69137 wrap.append('button')
69138 .attr('class', 'preset-list-button')
69139 .call(uiPresetIcon()
69140 .geometry(context.geometry(id))
69142 .on('click', item.choose)
69144 .attr('class', 'label')
69145 .text(preset.name());
69147 wrap.call(item.reference.button);
69148 selection$$1.call(item.reference.body);
69151 item.choose = function() {
69152 context.presets().choose(preset);
69155 actionChangePreset(id, currentPreset, preset),
69156 t('operations.change_tags.annotation')
69159 dispatch$$1.call('choose', this, preset);
69162 item.help = function() {
69163 event.stopPropagation();
69164 item.reference.toggle();
69167 item.preset = preset;
69168 item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
69174 presetList.autofocus = function(_) {
69175 if (!arguments.length) return autofocus;
69181 presetList.entityID = function(_) {
69182 if (!arguments.length) return id;
69184 presetList.preset(context.presets().match(context.entity(id), context.graph()));
69189 presetList.preset = function(_) {
69190 if (!arguments.length) return currentPreset;
69196 return utilRebind(presetList, dispatch$$1, 'on');
69199 function uiViewOnOSM(context) {
69202 function viewOnOSM(selection) {
69203 var entity = context.entity(id);
69205 selection.style('display', entity.isNew() ? 'none' : null);
69207 var link = selection.selectAll('.view-on-osm')
69210 var enter = link.enter()
69212 .attr('class', 'view-on-osm')
69213 .attr('target', '_blank')
69214 .call(svgIcon('#icon-out-link', 'inline'));
69218 .text(t('inspector.view_on_osm'));
69222 .attr('href', context.connection().entityURL(entity));
69226 viewOnOSM.entityID = function(_) {
69227 if (!arguments.length) return id;
69235 function uiInspector(context) {
69236 var presetList = uiPresetList(context),
69237 entityEditor = uiEntityEditor(context),
69240 newFeature = false;
69243 function inspector(selection$$1) {
69245 .entityID(entityID)
69246 .autofocus(newFeature)
69247 .on('choose', setPreset);
69251 .entityID(entityID)
69252 .on('choose', showList);
69254 var wrap = selection$$1.selectAll('.panewrap')
69257 var enter = wrap.enter()
69259 .attr('class', 'panewrap');
69263 .attr('class', 'preset-list-pane pane');
69267 .attr('class', 'entity-editor-pane pane');
69269 wrap = wrap.merge(enter);
69270 var presetPane = wrap.selectAll('.preset-list-pane');
69271 var editorPane = wrap.selectAll('.entity-editor-pane');
69273 var graph = context.graph(),
69274 entity = context.entity(entityID),
69275 showEditor = state === 'hover' ||
69276 entity.isUsed(graph) ||
69277 entity.isHighwayIntersection(graph);
69280 wrap.style('right', '0%');
69281 editorPane.call(entityEditor);
69283 wrap.style('right', '-100%');
69284 presetPane.call(presetList);
69287 var footer = selection$$1.selectAll('.footer')
69290 footer = footer.enter()
69292 .attr('class', 'footer')
69296 .call(uiViewOnOSM(context).entityID(entityID));
69299 function showList(preset) {
69301 .styleTween('right', function() { return interpolateValue('0%', '-100%'); });
69304 .call(presetList.preset(preset).autofocus(true));
69308 function setPreset(preset) {
69310 .styleTween('right', function() { return interpolateValue('-100%', '0%'); });
69313 .call(entityEditor.preset(preset));
69318 inspector.state = function(_) {
69319 if (!arguments.length) return state;
69321 entityEditor.state(state);
69326 inspector.entityID = function(_) {
69327 if (!arguments.length) return entityID;
69333 inspector.newFeature = function(_) {
69334 if (!arguments.length) return newFeature;
69343 function uiNotice(context) {
69345 return function(selection) {
69346 var div = selection
69348 .attr('class', 'notice');
69352 .attr('class', 'zoom-to notice')
69353 .on('click', function() { context.map().zoom(context.minEditableZoom()); });
69356 .call(svgIcon('#icon-plus', 'pre-text'))
69358 .attr('class', 'label')
69359 .text(t('zoom_in_edit'));
69362 function disableTooHigh() {
69363 div.style('display', context.editable() ? 'none' : 'block');
69367 .on('move.notice', lodash.debounce(disableTooHigh, 500));
69373 function uiSidebar(context) {
69374 var inspector = uiInspector(context),
69378 function sidebar(selection) {
69379 var featureListWrap = selection
69381 .attr('class', 'feature-list-pane')
69382 .call(uiFeatureList(context));
69385 .call(uiNotice(context));
69387 var inspectorWrap = selection
69389 .attr('class', 'inspector-hidden inspector-wrap fr');
69392 function hover(id) {
69393 if (!current && context.hasEntity(id)) {
69395 .classed('inspector-hidden', true);
69398 .classed('inspector-hidden', false)
69399 .classed('inspector-hover', true);
69401 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
69410 } else if (!current) {
69412 .classed('inspector-hidden', false);
69414 .classed('inspector-hidden', true);
69421 sidebar.hover = lodash.throttle(hover, 200);
69424 sidebar.select = function(id, newFeature) {
69425 if (!current && id) {
69427 .classed('inspector-hidden', true);
69430 .classed('inspector-hidden', false)
69431 .classed('inspector-hover', false);
69433 if (inspector.entityID() !== id || inspector.state() !== 'select') {
69437 .newFeature(newFeature);
69443 } else if (!current) {
69445 .classed('inspector-hidden', false);
69447 .classed('inspector-hidden', true);
69454 sidebar.show = function(component) {
69456 .classed('inspector-hidden', true);
69458 .classed('inspector-hidden', true);
69460 if (current) current.remove();
69461 current = selection
69463 .attr('class', 'sidebar-component')
69468 sidebar.hide = function() {
69470 .classed('inspector-hidden', false);
69472 .classed('inspector-hidden', true);
69474 if (current) current.remove();
69480 sidebar.hover = function() {};
69481 sidebar.hover.cancel = function() {};
69482 sidebar.select = function() {};
69483 sidebar.show = function() {};
69484 sidebar.hide = function() {};
69489 function uiSpinner(context) {
69490 var connection = context.connection();
69493 return function(selection) {
69494 var img = selection
69496 .attr('src', context.imagePath('loader-black.gif'))
69497 .style('opacity', 0);
69500 .on('loading.spinner', function() {
69502 .style('opacity', 1);
69506 .on('loaded.spinner', function() {
69508 .style('opacity', 0);
69513 function uiSplash(context) {
69515 return function(selection) {
69516 if (context.storage('sawSplash'))
69519 context.storage('sawSplash', true);
69521 var modalSelection = uiModal(selection);
69523 modalSelection.select('.modal')
69524 .attr('class', 'modal-splash modal col6');
69526 var introModal = modalSelection.select('.content')
69528 .attr('class', 'fillL');
69532 .attr('class','modal-section cf')
69533 .append('h3').text(t('splash.welcome'));
69537 .attr('class','modal-section')
69539 .html(t('splash.text', {
69540 version: context.version,
69541 website: '<a href="http://ideditor.com/">ideditor.com</a>',
69542 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
69545 var buttonWrap = introModal
69547 .attr('class', 'modal-actions cf');
69549 var walkthrough = buttonWrap
69551 .attr('class', 'walkthrough col6')
69552 .on('click', function() {
69553 context.container().call(uiIntro(context));
69554 modalSelection.close();
69559 .attr('class', 'logo logo-walkthrough')
69561 .attr('xlink:href', '#logo-walkthrough');
69565 .text(t('splash.walkthrough'));
69567 var startEditing = buttonWrap
69569 .attr('class', 'start-editing col6')
69570 .on('click', modalSelection.close);
69574 .attr('class', 'logo logo-features')
69576 .attr('xlink:href', '#logo-features');
69580 .text(t('splash.start'));
69583 modalSelection.select('button.close')
69584 .attr('class','hide');
69589 function uiStatus(context) {
69590 var connection = context.connection();
69592 return function(selection$$1) {
69594 function update() {
69595 connection.status(function(err, apiStatus) {
69596 selection$$1.html('');
69599 if (apiStatus === 'rateLimited') {
69601 .text(t('status.rateLimit'))
69603 .attr('class', 'api-status-login')
69604 .attr('target', '_blank')
69605 .call(svgIcon('#icon-out-link', 'inline'))
69608 .on('click.login', function() {
69609 event.preventDefault();
69610 connection.authenticate();
69613 // TODO: nice messages for different error types
69614 selection$$1.text(t('status.error'));
69617 } else if (apiStatus === 'readonly') {
69618 selection$$1.text(t('status.readonly'));
69619 } else if (apiStatus === 'offline') {
69620 selection$$1.text(t('status.offline'));
69623 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
69628 .on('change', function() { update(selection$$1); });
69630 window.setInterval(update, 90000);
69631 update(selection$$1);
69635 function uiUndoRedo(context) {
69639 action: function() { if (!saving()) context.undo(); },
69640 annotation: function() { return context.history().undoAnnotation(); }
69644 action: function() { if (!saving()) context.redo(); },
69645 annotation: function() { return context.history().redoAnnotation(); }
69649 function saving() {
69650 return context.mode().id === 'save';
69654 return function(selection$$1) {
69655 var tooltipBehavior = tooltip()
69656 .placement('bottom')
69658 .title(function (d) {
69659 return uiTooltipHtml(d.annotation() ?
69660 t(d.id + '.tooltip', {action: d.annotation()}) :
69661 t(d.id + '.nothing'), d.cmd);
69664 var buttons = selection$$1.selectAll('button')
69668 .attr('class', function(d) { return 'col6 disabled ' + d.id + '-button'; })
69669 .on('click', function(d) { return d.action(); })
69670 .call(tooltipBehavior);
69672 buttons.each(function(d) {
69673 var iconName = d.id;
69674 if (textDirection === 'rtl') {
69675 if (iconName === 'undo') {
69677 } else if (iconName === 'redo') {
69682 .call(svgIcon('#icon-' + iconName));
69685 var keybinding = d3keybinding('undo')
69686 .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
69687 .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
69693 .on('change.undo_redo', update);
69696 .on('enter.undo_redo', update);
69698 function update() {
69700 .property('disabled', saving())
69701 .classed('disabled', function(d) { return !d.annotation(); })
69703 var selection$$1 = select(this);
69704 if (selection$$1.property('tooltipVisible')) {
69705 selection$$1.call(tooltipBehavior.show);
69712 // these are module variables so they are preserved through a ui.restart()
69713 var sawVersion = null;
69714 var isNewVersion = false;
69715 var isNewUser = false;
69718 function uiVersion(context) {
69720 var currVersion = context.version,
69721 matchedVersion = currVersion.match(/\d\.\d\.\d.*/);
69723 if (sawVersion === null && matchedVersion !== null) {
69724 isNewVersion = (context.storage('sawVersion') !== currVersion);
69725 isNewUser = !context.storage('sawSplash');
69726 context.storage('sawVersion', currVersion);
69727 sawVersion = currVersion;
69730 return function(selection) {
69733 .attr('target', '_blank')
69734 .attr('tabindex', -1)
69735 .attr('href', 'https://github.com/openstreetmap/iD')
69736 .text(currVersion);
69738 // only show new version indicator to users that have used iD before
69739 if (isNewVersion && !isNewUser) {
69742 .attr('class', 'badge')
69744 .attr('target', '_blank')
69745 .attr('tabindex', -1)
69746 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CHANGELOG.md#whats-new')
69747 .call(svgIcon('#gift-11'))
69749 .title(t('version.whats_new', { version: currVersion }))
69756 function uiZoom(context) {
69760 title: t('zoom.in'),
69761 action: context.zoomIn,
69766 title: t('zoom.out'),
69767 action: context.zoomOut,
69772 function zoomIn() {
69773 event.preventDefault();
69778 function zoomOut() {
69779 event.preventDefault();
69784 function zoomInFurther() {
69785 event.preventDefault();
69786 context.zoomInFurther();
69790 function zoomOutFurther() {
69791 event.preventDefault();
69792 context.zoomOutFurther();
69796 return function(selection$$1) {
69797 var button = selection$$1.selectAll('button')
69801 .attr('tabindex', -1)
69802 .attr('class', function(d) { return d.id; })
69803 .on('click.editor', function(d) { d.action(); })
69805 .placement((textDirection === 'rtl') ? 'right' : 'left')
69807 .title(function(d) {
69808 return uiTooltipHtml(d.title, d.key);
69812 button.each(function(d) {
69814 .call(svgIcon('#icon-' + d.icon, 'light'));
69817 var keybinding = d3keybinding('zoom');
69819 lodash.each(['=','ffequals','plus','ffplus'], function(key) {
69820 keybinding.on([key, '⇧' + key], zoomIn);
69821 keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomInFurther);
69823 lodash.each(['-','ffminus','dash'], function(key) {
69824 keybinding.on([key, '⇧' + key], zoomOut);
69825 keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomOutFurther);
69833 function uiInit(context) {
69834 var uiInitCounter = 0;
69837 function render(container) {
69839 .attr('dir', textDirection);
69841 var map$$1 = context.map();
69843 var hash = behaviorHash(context);
69846 if (!hash.hadHash) {
69847 map$$1.centerZoom([0, 0], 2);
69852 .attr('id', 'defs')
69853 .call(svgDefs(context));
69857 .attr('id', 'sidebar')
69858 .attr('class', 'col4')
69861 var content = container
69863 .attr('id', 'content')
69864 .attr('class', 'active');
69869 .attr('class', 'fillD');
69874 .attr('dir', 'ltr')
69878 .call(uiMapInMap(context));
69882 .call(uiInfo(context));
69886 .attr('class', 'spacer col4');
69888 var limiter = bar.append('div')
69889 .attr('class', 'limiter');
69893 .attr('class', 'button-wrap joined col3')
69894 .call(uiModes(context), limiter);
69898 .attr('class', 'button-wrap joined col1')
69899 .call(uiUndoRedo(context));
69903 .attr('class', 'button-wrap col1')
69904 .call(uiSave(context));
69908 .attr('class', 'full-screen')
69909 .call(uiFullScreen(context));
69913 .attr('class', 'spinner')
69914 .call(uiSpinner(context));
69919 .attr('class', 'map-controls');
69923 .attr('class', 'map-control zoombuttons')
69924 .call(uiZoom(context));
69928 .attr('class', 'map-control geolocate-control')
69929 .call(uiGeolocate(context));
69933 .attr('class', 'map-control background-control')
69934 .call(uiBackground(context));
69938 .attr('class', 'map-control map-data-control')
69939 .call(uiMapData(context));
69943 .attr('class', 'map-control help-control')
69944 .call(uiHelp(context));
69947 var about = content
69949 .attr('id', 'about');
69953 .attr('id', 'attrib')
69954 .attr('dir', 'ltr')
69955 .call(uiAttribution(context));
69959 .attr('class', 'api-status')
69960 .call(uiStatus(context));
69965 .attr('id', 'footer')
69966 .attr('class', 'fillD');
69970 .attr('id', 'flash-wrap')
69971 .attr('class', 'footer-hide');
69973 var footerWrap = footer
69975 .attr('id', 'footer-wrap')
69976 .attr('class', 'footer-show');
69980 .attr('id', 'scale-block')
69981 .call(uiScale(context));
69983 var aboutList = footerWrap
69985 .attr('id', 'info-block')
69987 .attr('id', 'about-list');
69989 if (!context.embed()) {
69991 .call(uiAccount(context));
69996 .attr('class', 'version')
69997 .call(uiVersion(context));
69999 var issueLinks = aboutList
70004 .attr('target', '_blank')
70005 .attr('tabindex', -1)
70006 .attr('href', 'https://github.com/openstreetmap/iD/issues')
70007 .call(svgIcon('#icon-bug', 'light'))
70008 .call(tooltip().title(t('report_a_bug')).placement('top'));
70012 .attr('target', '_blank')
70013 .attr('tabindex', -1)
70014 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
70015 .call(svgIcon('#icon-translate', 'light'))
70016 .call(tooltip().title(t('help_translate')).placement('top'));
70020 .attr('class', 'feature-warning')
70021 .attr('tabindex', -1)
70022 .call(uiFeatureInfo(context));
70026 .attr('class', 'user-list')
70027 .attr('tabindex', -1)
70028 .call(uiContributors(context));
70031 window.onbeforeunload = function() {
70032 return context.save();
70035 window.onunload = function() {
70036 context.history().unlock();
70039 var mapDimensions = map$$1.dimensions();
70042 function onResize() {
70043 mapDimensions = utilGetDimensions(content, true);
70044 map$$1.dimensions(mapDimensions);
70048 .on('resize.editor', onResize);
70053 return function() {
70054 event.preventDefault();
70055 context.pan(d, 100);
70063 var keybinding = d3keybinding('main')
70064 .on('⌫', function() { event.preventDefault(); })
70065 .on('←', pan([pa, 0]))
70066 .on('↑', pan([0, pa]))
70067 .on('→', pan([-pa, 0]))
70068 .on('↓', pan([0, -pa]))
70069 .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
70070 .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
70071 .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
70072 .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
70077 context.enter(modeBrowse(context));
70079 if (!uiInitCounter++) {
70080 context.container()
70081 .call(uiSplash(context))
70082 .call(uiRestore(context));
70085 var authenticating = uiLoading(context)
70086 .message(t('loading_auth'))
70089 context.connection()
70090 .on('authLoading.ui', function() {
70091 context.container()
70092 .call(authenticating);
70094 .on('authDone.ui', function() {
70095 authenticating.close();
70102 var renderCallback;
70104 function ui(node, callback) {
70105 renderCallback = callback;
70106 var container = select(node);
70107 context.container(container);
70108 context.loadLocale(function(err) {
70119 ui.restart = function(arg) {
70120 context.locale(arg);
70121 context.loadLocale(function(err) {
70123 context.container().selectAll('*').remove();
70124 render(context.container());
70125 if (renderCallback) renderCallback();
70131 ui.sidebar = uiSidebar(context);
70137 var readOnlyTags = ['created_by', 'imagery_used', 'host', 'locale'];
70140 function uiCommit(context) {
70141 var dispatch$$1 = dispatch('cancel', 'save');
70144 function commit(selection$$1) {
70146 var detected = utilDetect(),
70148 created_by: ('iD ' + context.version).substr(0, 255),
70149 imagery_used: context.history().imageryUsed().join(';').substr(0, 255),
70150 host: detected.host.substr(0, 255),
70151 locale: detected.locale.substr(0, 255)
70154 changeset = new osmChangeset({ tags: tags });
70158 var changes = context.history().changes(),
70159 summary = context.history().difference().summary(),
70160 rawTagEditor = uiRawTagEditor(context).on('change', changeTags),
70161 comment = context.storage('comment') || '',
70162 commentDate = +context.storage('commentDate') || 0,
70163 currDate = Date.now(),
70164 cutoff = 2 * 86400 * 1000; // 2 days
70166 // expire the stored comment if it is too old - #3947
70167 if (commentDate > currDate || currDate - commentDate > cutoff) {
70173 .attr('class', 'header fillL')
70175 .text(t('commit.title'));
70177 var body = selection$$1
70179 .attr('class', 'body');
70181 var commentSection = body
70183 .attr('class', 'modal-section form-field commit-form');
70187 .attr('class', 'form-label')
70188 .text(t('commit.message_label'));
70190 var commentField = commentSection
70191 .append('textarea')
70192 .attr('class', 'commit-form-comment')
70193 .attr('placeholder', t('commit.description_placeholder'))
70194 .attr('maxlength', 255)
70195 .property('value', comment)
70196 .on('input.save', change(true))
70197 .on('change.save', change())
70198 .on('blur.save', function() {
70199 context.storage('comment', this.value);
70200 context.storage('commentDate', Date.now());
70204 commentField.node().select();
70206 context.connection().userChangesets(function (err, changesets) {
70209 var comments = changesets.map(function(changeset) {
70211 title: changeset.tags.comment,
70212 value: changeset.tags.comment
70218 .container(context.container())
70219 .caseSensitive(true)
70220 .data(lodash.uniqBy(comments, 'title'))
70224 var clippyArea = commentSection.append('div')
70225 .attr('class', 'clippy-area');
70227 var changeSetInfo = commentSection.append('div')
70228 .attr('class', 'changeset-info');
70230 changeSetInfo.append('a')
70231 .attr('target', '_blank')
70232 .attr('tabindex', -1)
70233 .call(svgIcon('#icon-out-link', 'inline'))
70234 .attr('href', t('commit.about_changeset_comments_link'))
70236 .text(t('commit.about_changeset_comments'));
70240 var warnings = body.selectAll('div.warning-section')
70241 .data([context.history().validate(changes)]);
70243 warnings = warnings.enter()
70245 .attr('class', 'modal-section warning-section fillL2')
70246 .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
70247 .style('background', '#ffb')
70252 .text(t('commit.warnings'));
70256 .attr('class', 'changeset-list');
70258 var warningLi = warnings.select('ul').selectAll('li')
70259 .data(function(d) { return d; });
70261 warningLi = warningLi.enter()
70263 .on('mouseover', mouseover)
70264 .on('mouseout', mouseout)
70265 .on('click', warningClick)
70269 .call(svgIcon('#icon-alert', 'pre-text'));
70273 .text(function(d) { return d.message; });
70275 warningLi.filter(function(d) { return d.tooltip; })
70277 .title(function(d) { return d.tooltip; })
70282 // Upload Explanation
70283 var saveSection = body
70285 .attr('class','modal-section save-section fillL cf');
70287 var prose = saveSection
70289 .attr('class', 'commit-info')
70290 .html(t('commit.upload_explanation'));
70293 context.connection().userDetails(function(err, user) {
70296 var userLink = select(document.createElement('div'));
70298 if (user.image_url) {
70301 .attr('src', user.image_url)
70302 .attr('class', 'icon pre-text user-icon');
70307 .attr('class','user-info')
70308 .text(user.display_name)
70309 .attr('href', context.connection().userURL(user.display_name))
70310 .attr('tabindex', -1)
70311 .attr('target', '_blank');
70314 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
70319 var buttonSection = saveSection
70321 .attr('class', 'buttons fillL cf');
70323 var cancelButton = buttonSection
70325 .attr('class', 'secondary-action col5 button cancel-button')
70326 .on('click.cancel', function() {
70327 dispatch$$1.call('cancel');
70332 .attr('class', 'label')
70333 .text(t('commit.cancel'));
70335 var saveButton = buttonSection
70337 .attr('class', 'action col5 button save-button')
70338 .attr('disabled', function() {
70339 var n = select('.commit-form textarea').node();
70340 return (n && n.value.length) ? null : true;
70342 .on('click.save', function() {
70343 dispatch$$1.call('save', this, changeset);
70348 .attr('class', 'label')
70349 .text(t('commit.save'));
70353 var tagSection = body
70355 .attr('class', 'modal-section tag-section raw-tag-editor');
70359 var changeSection = body
70361 .attr('class', 'commit-section modal-section fillL2');
70363 changeSection.append('h3')
70364 .text(t('commit.changes', { count: summary.length }));
70366 var li = changeSection
70368 .attr('class', 'changeset-list')
70374 .on('mouseover', mouseover)
70375 .on('mouseout', mouseout)
70376 .on('click', zoomToEntity)
70379 li.each(function(d) {
70381 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
70385 .attr('class', 'change-type')
70386 .text(function(d) { return t('commit.' + d.changeType) + ' '; });
70388 li.append('strong')
70389 .attr('class', 'entity-type')
70390 .text(function(d) {
70391 var matched = context.presets().match(d.entity, d.graph);
70392 return (matched && matched.name()) || utilDisplayType(d.entity.id);
70396 .attr('class', 'entity-name')
70397 .text(function(d) {
70398 var name = utilDisplayName(d.entity) || '',
70400 if (name !== '') string += ':';
70401 return string += ' ' + name;
70404 li.style('opacity', 0)
70406 .style('opacity', 1);
70409 // Call change() off the bat, in case a changeset
70410 // comment is recovered from localStorage
70411 utilTriggerEvent(commentField, 'input');
70414 function mouseover(d) {
70416 context.surface().selectAll(
70417 utilEntityOrMemberSelector([d.entity.id], context.graph())
70418 ).classed('hover', true);
70423 function mouseout() {
70424 context.surface().selectAll('.hover')
70425 .classed('hover', false);
70429 function warningClick(d) {
70431 context.map().zoomTo(d.entity);
70432 context.enter(modeSelect(context, [d.entity.id]));
70437 function zoomToEntity(change) {
70438 var entity = change.entity;
70439 if (change.changeType !== 'deleted' &&
70440 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
70441 context.map().zoomTo(entity);
70442 context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph()))
70443 .classed('hover', true);
70448 function checkComment(comment) {
70449 // Save button disabled if there is no comment..
70450 selectAll('.save-section .save-button')
70451 .attr('disabled', (comment.length ? null : true));
70453 // Warn if comment mentions Google..
70454 var googleWarning = clippyArea
70457 .data(comment.match(/google/i) ? [true] : []);
70459 googleWarning.exit()
70462 googleWarning.enter()
70464 .attr('target', '_blank')
70465 .attr('tabindex', -1)
70466 .call(svgIcon('#icon-alert', 'inline'))
70467 .attr('href', t('commit.google_warning_link'))
70469 .text(t('commit.google_warning'));
70473 function change(onInput) {
70474 return function() {
70475 var comment = commentField.property('value').trim();
70477 commentField.property('value', comment);
70480 checkComment(comment);
70482 var changeset = updateChangeset({ comment: comment });
70483 var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty();
70487 .expanded(expanded)
70488 .readOnlyTags(readOnlyTags)
70489 .tags(lodash.clone(changeset.tags))
70495 function changeTags(changed) {
70496 if (changed.hasOwnProperty('comment')) {
70497 if (changed.comment === undefined) {
70498 changed.comment = '';
70500 changed.comment = changed.comment.trim();
70501 commentField.property('value', changed.comment);
70503 updateChangeset(changed);
70504 utilTriggerEvent(commentField, 'input');
70508 function updateChangeset(changed) {
70509 var tags = lodash.clone(changeset.tags);
70511 lodash.forEach(changed, function(v, k) {
70512 k = k.trim().substr(0, 255);
70513 if (readOnlyTags.indexOf(k) !== -1) return;
70515 if (k !== '' && v !== undefined) {
70516 tags[k] = v.trim().substr(0, 255);
70522 if (!lodash.isEqual(changeset.tags, tags)) {
70523 changeset = changeset.update({ tags: tags });
70532 commit.reset = function() {
70537 return utilRebind(commit, dispatch$$1, 'on');
70540 function uiConfirm(selection) {
70541 var modalSelection = uiModal(selection);
70543 modalSelection.select('.modal')
70544 .classed('modal-alert', true);
70546 var section = modalSelection.select('.content');
70548 section.append('div')
70549 .attr('class', 'modal-section header');
70551 section.append('div')
70552 .attr('class', 'modal-section message-text');
70554 var buttons = section.append('div')
70555 .attr('class', 'modal-section buttons cf');
70558 modalSelection.okButton = function() {
70561 .attr('class', 'action col4')
70562 .on('click.confirm', function() {
70563 modalSelection.remove();
70565 .text(t('confirm.okay'));
70567 return modalSelection;
70571 return modalSelection;
70574 function uiConflicts(context) {
70575 var dispatch$$1 = dispatch('download', 'cancel', 'save'),
70579 function conflicts(selection$$1) {
70580 var header = selection$$1
70582 .attr('class', 'header fillL');
70586 .attr('class', 'fr')
70587 .on('click', function() { dispatch$$1.call('cancel'); })
70588 .call(svgIcon('#icon-close'));
70592 .text(t('save.conflict.header'));
70594 var body = selection$$1
70596 .attr('class', 'body fillL');
70600 .attr('class', 'conflicts-help')
70601 .text(t('save.conflict.help'))
70603 .attr('class', 'conflicts-download')
70604 .text(t('save.conflict.download_changes'))
70605 .on('click.download', function() { dispatch$$1.call('download'); });
70609 .attr('class', 'conflict-container fillL3')
70610 .call(showConflict, 0);
70614 .attr('class', 'conflicts-done')
70615 .attr('opacity', 0)
70616 .style('display', 'none')
70617 .text(t('save.conflict.done'));
70621 .attr('class','buttons col12 joined conflicts-buttons');
70625 .attr('disabled', list.length > 1)
70626 .attr('class', 'action conflicts-button col6')
70627 .text(t('save.title'))
70628 .on('click.try_again', function() { dispatch$$1.call('save'); });
70632 .attr('class', 'secondary-action conflicts-button col6')
70633 .text(t('confirm.cancel'))
70634 .on('click.cancel', function() { dispatch$$1.call('cancel'); });
70638 function showConflict(selection$$1, index) {
70639 if (index < 0 || index >= list.length) return;
70641 var parent = select(selection$$1.node().parentNode);
70643 // enable save button if this is the last conflict being reviewed..
70644 if (index === list.length - 1) {
70645 window.setTimeout(function() {
70646 parent.select('.conflicts-button')
70647 .attr('disabled', null);
70649 parent.select('.conflicts-done')
70651 .attr('opacity', 1)
70652 .style('display', 'block');
70656 var item = selection$$1
70657 .selectAll('.conflict')
70658 .data([list[index]]);
70660 var enter = item.enter()
70662 .attr('class', 'conflict');
70666 .attr('class', 'conflict-count')
70667 .text(t('save.conflict.count', { num: index + 1, total: list.length }));
70671 .attr('class', 'conflict-description')
70673 .text(function(d) { return d.name; })
70674 .on('click', function(d) {
70675 zoomToEntity(d.id);
70676 event.preventDefault();
70679 var details = enter
70681 .attr('class', 'conflict-detail-container');
70685 .attr('class', 'conflict-detail-list')
70687 .data(function(d) { return d.details || []; })
70690 .attr('class', 'conflict-detail-item')
70691 .html(function(d) { return d; });
70695 .attr('class', 'conflict-choices')
70700 .attr('class', 'conflict-nav-buttons joined cf')
70701 .selectAll('button')
70702 .data(['previous', 'next'])
70705 .text(function(d) { return t('save.conflict.' + d); })
70706 .attr('class', 'conflict-nav-button action col6')
70707 .attr('disabled', function(d, i) {
70708 return (i === 0 && index === 0) ||
70709 (i === 1 && index === list.length - 1) || null;
70711 .on('click', function(d, i) {
70712 var container = parent.select('.conflict-container'),
70713 sign = (i === 0 ? -1 : 1);
70716 .selectAll('.conflict')
70720 .call(showConflict, index + sign);
70722 event.preventDefault();
70730 function addChoices(selection$$1) {
70731 var choices = selection$$1
70733 .attr('class', 'layer-list')
70735 .data(function(d) { return d.choices || []; });
70737 var enter = choices.enter()
70739 .attr('class', 'layer');
70746 .attr('type', 'radio')
70747 .attr('name', function(d) { return d.id; })
70748 .on('change', function(d, i) {
70749 var ul = this.parentNode.parentNode.parentNode;
70750 ul.__data__.chosen = i;
70756 .text(function(d) { return d.text; });
70759 .each(function(d, i) {
70760 var ul = this.parentNode;
70761 if (ul.__data__.chosen === i) choose(ul, d);
70766 function choose(ul, datum) {
70767 if (event) event.preventDefault();
70771 .classed('active', function(d) { return d === datum; })
70772 .selectAll('input')
70773 .property('checked', function(d) { return d === datum; });
70775 var extent$$1 = geoExtent$$1(),
70778 entity = context.graph().hasEntity(datum.id);
70779 if (entity) extent$$1._extend(entity.extent(context.graph()));
70783 entity = context.graph().hasEntity(datum.id);
70784 if (entity) extent$$1._extend(entity.extent(context.graph()));
70786 zoomToEntity(datum.id, extent$$1);
70790 function zoomToEntity(id, extent$$1) {
70791 context.surface().selectAll('.hover')
70792 .classed('hover', false);
70794 var entity = context.graph().hasEntity(id);
70797 context.map().trimmedExtent(extent$$1);
70799 context.map().zoomTo(entity);
70801 context.surface().selectAll(
70802 utilEntityOrMemberSelector([entity.id], context.graph()))
70803 .classed('hover', true);
70808 // The conflict list should be an array of objects like:
70811 // name: entityName(local),
70812 // details: merge.conflicts(),
70815 // choice(id, keepMine, forceLocal),
70816 // choice(id, keepTheirs, forceRemote)
70819 conflicts.list = function(_) {
70820 if (!arguments.length) return list;
70826 return utilRebind(conflicts, dispatch$$1, 'on');
70829 function uiEditMenu(context, operations) {
70835 var p = 8, // top padding
70836 m = 4, // top margin
70837 h = 15, // height of icon
70838 vpBottomMargin = 45, // viewport bottom margin
70839 vpSideMargin = 35, // viewport side margin
70841 buttonHeight = (2 * p + h),
70842 menuWidth = buttonWidth,
70843 menuHeight = (2 * m) + operations.length * buttonHeight,
70844 menuSideMargin = 10,
70845 tooltipWidth = 200,
70846 tooltipHeight = 200; // a reasonable guess, real height depends on tooltip contents
70849 var editMenu = function (selection$$1) {
70850 if (!operations.length) return;
70852 selection$$1.node().parentNode.focus();
70854 var isRTL = textDirection === 'rtl',
70855 viewport = context.surfaceRect();
70857 if (!isRTL && (center[0] + menuSideMargin + menuWidth) > (viewport.width - vpSideMargin)) {
70858 // menu is going left-to-right and near right viewport edge, go left instead
70860 } else if (isRTL && (center[0] - menuSideMargin - menuWidth) < vpSideMargin) {
70861 // menu is going right-to-left and near left viewport edge, go right instead
70865 offset[0] = (isRTL ? -1 * (menuSideMargin + menuWidth) : menuSideMargin);
70867 if (center[1] + menuHeight > (viewport.height - vpBottomMargin)) {
70868 // menu is near bottom viewport edge, shift upwards
70869 offset[1] = -1 * (center[1] + menuHeight - viewport.height + vpBottomMargin);
70872 var origin = [ center[0] + offset[0], center[1] + offset[1] ];
70874 menu = selection$$1
70876 .attr('class', 'edit-menu')
70877 .attr('transform', 'translate(' + origin + ')')
70878 .attr('opacity', 0);
70882 .attr('opacity', 1);
70886 .attr('class', 'edit-menu-background')
70890 .attr('width', menuWidth)
70891 .attr('height', menuHeight)
70892 .attr('stroke-linecap', 'round');
70895 var button = menu.selectAll('.edit-menu-item')
70899 .attr('class', function (d) { return 'edit-menu-item edit-menu-item-' + d.id; })
70900 .classed('disabled', function (d) { return d.disabled(); })
70901 .attr('transform', function (d, i) {
70902 return 'translate(' + geoRoundCoords([
70904 m + i * buttonHeight
70905 ]).join(',') + ')';
70911 .attr('width', buttonWidth)
70912 .attr('height', buttonHeight)
70913 .on('click', click)
70914 .on('mousedown', mousedown)
70915 .on('mouseover', mouseover)
70916 .on('mouseout', mouseout);
70920 .attr('width', '20')
70921 .attr('height', '20')
70922 .attr('transform', function () {
70923 return 'translate(' + [2 * p, 5] + ')';
70925 .attr('xlink:href', function (d) { return '#operation-' + d.id; });
70927 tooltip = select(document.body)
70929 .attr('class', 'tooltip-inner edit-menu-tooltip');
70932 function click(operation) {
70933 event.stopPropagation();
70934 if (operation.disabled()) return;
70939 function mousedown() {
70940 event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
70943 function mouseover(d, i) {
70947 tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
70949 tipX = viewport.left + origin[0] - 4 - tooltipWidth;
70952 if (tipX + tooltipWidth > viewport.right) {
70953 // tip is going left-to-right and near right viewport edge, go left instead
70954 tipX = viewport.left + origin[0] - 4 - tooltipWidth;
70955 } else if (tipX < viewport.left) {
70956 // tip is going right-to-left and near left viewport edge, go right instead
70957 tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
70960 tipY = viewport.top + origin[1] + (i * buttonHeight);
70961 if (tipY + tooltipHeight > viewport.bottom) {
70962 // tip is near bottom viewport edge, shift upwards
70963 tipY -= tipY + tooltipHeight - viewport.bottom;
70967 .style('left', tipX + 'px')
70968 .style('top', tipY + 'px')
70969 .style('display', 'block')
70970 .html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title));
70973 function mouseout() {
70974 tooltip.style('display', 'none');
70979 editMenu.close = function () {
70982 .style('pointer-events', 'none')
70984 .attr('opacity', 0)
70994 editMenu.center = function (_) {
70995 if (!arguments.length) return center;
71006 function uiFlash(showDuration) {
71007 showDuration = showDuration || 1500;
71013 select('#footer-wrap')
71014 .attr('class', 'footer-hide');
71015 select('#flash-wrap')
71016 .attr('class', 'footer-show');
71018 var content = select('#flash-wrap').selectAll('.content')
71021 content = content.enter()
71023 .attr('class', 'content')
71026 timer$1 = timeout$1(function() {
71028 select('#footer-wrap')
71029 .attr('class', 'footer-show');
71030 select('#flash-wrap')
71031 .attr('class', 'footer-hide');
71038 function uiLasso(context) {
71039 var group, polygon;
71041 lasso.coordinates = [];
71043 function lasso(selection$$1) {
71044 context.container()
71045 .classed('lasso', true);
71047 group = selection$$1
71049 .attr('class', 'lasso hide');
71053 .attr('class', 'lasso-path');
71056 .call(uiToggle(true));
71062 polygon.data([lasso.coordinates])
71063 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
71068 lasso.extent = function () {
71069 return lasso.coordinates.reduce(function(extent$$1, point) {
71070 return extent$$1.extend(geoExtent$$1(point));
71071 }, geoExtent$$1());
71075 lasso.p = function(_) {
71076 if (!arguments.length) return lasso;
71077 lasso.coordinates.push(_);
71083 lasso.close = function() {
71085 group.call(uiToggle(false, function() {
71086 select(this).remove();
71089 context.container().classed('lasso', false);
71096 function uiRadialMenu(context, operations) {
71102 var radialMenu = function(selection$$1) {
71103 if (!operations.length) return;
71105 selection$$1.node().parentNode.focus();
71107 function click(operation) {
71108 event.stopPropagation();
71109 if (operation.disabled()) return;
71111 radialMenu.close();
71114 menu = selection$$1
71116 .attr('class', 'radial-menu')
71117 .attr('transform', 'translate(' + center + ')')
71118 .attr('opacity', 0);
71122 .attr('opacity', 1);
71127 a1 = a0 + (operations.length - 1) * a;
71131 .attr('class', 'radial-menu-background')
71132 .attr('d', 'M' + r * Math.sin(a0) + ',' +
71134 ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
71135 (r * Math.sin(a1) + 1e-3) + ',' +
71136 (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
71137 .attr('stroke-width', 50)
71138 .attr('stroke-linecap', 'round');
71140 var button = menu.selectAll()
71144 .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
71145 .classed('disabled', function(d) { return d.disabled(); })
71146 .attr('transform', function(d, i) {
71147 return 'translate(' + geoRoundCoords([
71148 r * Math.sin(a0 + i * a),
71149 r * Math.cos(a0 + i * a)]).join(',') + ')';
71155 .on('click', click)
71156 .on('mousedown', mousedown)
71157 .on('mouseover', mouseover)
71158 .on('mouseout', mouseout);
71162 .attr('transform', 'translate(-10,-10)')
71163 .attr('width', '20')
71164 .attr('height', '20')
71165 .attr('xlink:href', function(d) { return '#operation-' + d.id; });
71167 tooltip = select(document.body)
71169 .attr('class', 'tooltip-inner radial-menu-tooltip');
71171 function mousedown() {
71172 event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
71175 function mouseover(d, i) {
71176 var rect = context.surfaceRect(),
71177 angle = a0 + i * a,
71178 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
71179 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
71180 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
71181 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
71184 .style('top', null)
71185 .style('left', null)
71186 .style('bottom', null)
71187 .style('right', null)
71188 .style('display', 'block')
71189 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
71193 .style('right', right)
71194 .style('top', top);
71195 } else if (i >= 4) {
71197 .style('left', left)
71198 .style('bottom', bottom);
71201 .style('left', left)
71202 .style('top', top);
71206 function mouseout() {
71207 tooltip.style('display', 'none');
71212 radialMenu.close = function() {
71215 .style('pointer-events', 'none')
71217 .attr('opacity', 0)
71227 radialMenu.center = function(_) {
71228 if (!arguments.length) return center;
71237 function uiSelectionList(context, selectedIDs) {
71239 function selectEntity(entity) {
71240 context.enter(modeSelect(context, [entity.id]));
71244 function deselectEntity(entity) {
71245 event.stopPropagation();
71246 var index = selectedIDs.indexOf(entity.id);
71248 selectedIDs.splice(index, 1);
71250 context.enter(modeSelect(context, selectedIDs));
71254 function selectionList(selection$$1) {
71255 selection$$1.classed('selection-list-pane', true);
71257 var header = selection$$1
71259 .attr('class', 'header fillL cf');
71263 .text(t('inspector.multiselect'));
71265 var listWrap = selection$$1
71267 .attr('class', 'inspector-body');
71269 var list = listWrap
71271 .attr('class', 'feature-list cf');
71273 context.history().on('change.selection-list', drawList);
71277 function drawList() {
71278 var entities = selectedIDs
71279 .map(function(id) { return context.hasEntity(id); })
71280 .filter(function(entity) { return entity; });
71282 var items = list.selectAll('.feature-list-item')
71283 .data(entities, osmEntity$$1.key);
71289 var enter = items.enter()
71291 .attr('class', 'feature-list-item')
71292 .on('click', selectEntity);
71296 .attr('class', 'label');
71300 .attr('class', 'close')
71301 .on('click', deselectEntity)
71302 .call(svgIcon('#icon-close'));
71306 .attr('class', 'entity-geom-icon')
71307 .call(svgIcon('', 'pre-text'));
71311 .attr('class', 'entity-type');
71315 .attr('class', 'entity-name');
71318 items = items.merge(enter);
71320 items.selectAll('.entity-geom-icon use')
71321 .attr('href', function() {
71322 var entity = this.parentNode.parentNode.__data__;
71323 return '#icon-' + context.geometry(entity.id);
71326 items.selectAll('.entity-type')
71327 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
71329 items.selectAll('.entity-name')
71330 .text(function(entity) { return utilDisplayName(entity); });
71334 return selectionList;
71337 function uiSourceSwitch(context) {
71342 event.preventDefault();
71344 if (context.history().hasChanges() &&
71345 !window.confirm(t('source_switch.lose_changes'))) return;
71347 var live = select(this)
71350 context.connection()
71351 .switch(live ? keys$$1[1] : keys$$1[0]);
71353 context.enter(modeBrowse(context));
71357 .text(live ? t('source_switch.dev') : t('source_switch.live'))
71358 .classed('live', !live);
71361 var sourceSwitch = function(selection$$1) {
71365 .text(t('source_switch.live'))
71366 .classed('live', true)
71367 .attr('tabindex', -1)
71368 .on('click', click);
71372 sourceSwitch.keys = function(_) {
71373 if (!arguments.length) return keys$$1;
71375 return sourceSwitch;
71379 return sourceSwitch;
71382 function uiSuccess(context) {
71383 var dispatch$$1 = dispatch('cancel'),
71387 function success(selection$$1) {
71388 var header = selection$$1
71390 .attr('class', 'header fillL');
71394 .attr('class', 'fr')
71395 .on('click', function() { dispatch$$1.call('cancel'); })
71396 .call(svgIcon('#icon-close'));
71400 .text(t('success.just_edited'));
71402 var body = selection$$1
71404 .attr('class', 'body save-success fillL');
71408 .html(t('success.help_html'));
71412 .attr('class', 'details')
71413 .attr('target', '_blank')
71414 .attr('tabindex', -1)
71415 .call(svgIcon('#icon-out-link', 'inline'))
71416 .attr('href', t('success.help_link_url'))
71418 .text(t('success.help_link_text'));
71420 var changesetURL = context.connection().changesetURL(changeset.id);
71423 var viewOnOsm = body
71425 .attr('class', 'button col12 osm')
71426 .attr('target', '_blank')
71427 .attr('href', changesetURL);
71431 .attr('class', 'logo logo-osm')
71433 .attr('xlink:href', '#logo-osm');
71437 .text(t('success.view_on_osm'));
71440 var message = (changeset.tags.comment || t('success.edited_osm')).substring(0, 130) +
71441 ' ' + context.connection().changesetURL(changeset.id);
71444 facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
71445 twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
71446 google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
71449 body.selectAll('.button.social')
71450 .data(entries(sharing))
71453 .attr('class', 'button social col4')
71454 .attr('target', '_blank')
71455 .attr('href', function(d) { return d.value; })
71457 .title(function(d) { return t('success.' + d.key); })
71458 .placement('bottom'))
71459 .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
71463 success.changeset = function(_) {
71464 if (!arguments.length) return changeset;
71470 return utilRebind(success, dispatch$$1, 'on');
71473 function coreHistory(context) {
71474 var imageryUsed = ['Bing'],
71475 dispatch$$1 = dispatch('change', 'undone', 'redone'),
71476 lock = utilSessionMutex('lock'),
71479 stack$$1, index, tree$$1;
71482 // internal _act, accepts list of actions and eased time
71483 function _act(actions, t) {
71484 actions = Array.prototype.slice.call(actions);
71488 if (!lodash.isFunction(lodash.last(actions))) {
71489 annotation = actions.pop();
71492 stack$$1[index].transform = context.projection.transform();
71493 stack$$1[index].selectedIDs = context.selectedIDs();
71495 var graph = stack$$1[index].graph;
71496 for (var i = 0; i < actions.length; i++) {
71497 graph = actions[i](graph, t);
71502 annotation: annotation,
71503 imageryUsed: imageryUsed
71508 // internal _perform with eased time
71509 function _perform(args, t) {
71510 var previous = stack$$1[index].graph;
71511 stack$$1 = stack$$1.slice(0, index + 1);
71512 stack$$1.push(_act(args, t));
71514 return change(previous);
71518 // internal _replace with eased time
71519 function _replace(args, t) {
71520 var previous = stack$$1[index].graph;
71521 // assert(index == stack.length - 1)
71522 stack$$1[index] = _act(args, t);
71523 return change(previous);
71527 // internal _overwrite with eased time
71528 function _overwrite(args, t) {
71529 var previous = stack$$1[index].graph;
71534 stack$$1 = stack$$1.slice(0, index + 1);
71535 stack$$1.push(_act(args, t));
71537 return change(previous);
71541 // determine diffrence and dispatch a change event
71542 function change(previous) {
71543 var difference = coreDifference(previous, history.graph());
71544 dispatch$$1.call('change', this, difference);
71549 // iD uses namespaced keys so multiple installations do not conflict
71550 function getKey(n) {
71551 return 'iD_' + window.location.origin + '_' + n;
71557 graph: function() {
71558 return stack$$1[index].graph;
71563 return stack$$1[0].graph;
71567 merge: function(entities, extent$$1) {
71568 stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
71569 tree$$1.rebase(entities, false);
71571 dispatch$$1.call('change', this, undefined, extent$$1);
71575 perform: function() {
71576 // complete any transition already in progress
71577 select(document).interrupt('history.perform');
71579 var transitionable = false,
71580 action0 = arguments[0];
71582 if (arguments.length === 1 ||
71583 arguments.length === 2 && !lodash.isFunction(arguments[1])) {
71584 transitionable = !!action0.transitionable;
71587 if (transitionable) {
71588 var origArguments = arguments;
71590 .transition('history.perform')
71591 .duration(duration)
71593 .tween('history.tween', function() {
71594 return function(t) {
71595 if (t < 1) _overwrite([action0], t);
71598 .on('start', function() {
71599 _perform([action0], 0);
71601 .on('end interrupt', function() {
71602 _overwrite(origArguments, 1);
71606 return _perform(arguments);
71611 replace: function() {
71612 select(document).interrupt('history.perform');
71613 return _replace(arguments, 1);
71617 // Same as calling pop and then perform
71618 overwrite: function() {
71619 select(document).interrupt('history.perform');
71620 return _overwrite(arguments, 1);
71625 select(document).interrupt('history.perform');
71627 var previous = stack$$1[index].graph;
71628 if (isNaN(+n) || +n < 0) {
71631 while (n-- > 0 && index > 0) {
71635 return change(previous);
71639 // Back to the previous annotated state or index = 0.
71641 select(document).interrupt('history.perform');
71643 var previous = stack$$1[index].graph;
71644 while (index > 0) {
71646 if (stack$$1[index].annotation) break;
71649 dispatch$$1.call('undone', this, stack$$1[index]);
71650 return change(previous);
71654 // Forward to the next annotated state.
71656 select(document).interrupt('history.perform');
71658 var previous = stack$$1[index].graph;
71659 var tryIndex = index;
71660 while (tryIndex < stack$$1.length - 1) {
71662 if (stack$$1[tryIndex].annotation) {
71664 dispatch$$1.call('redone', this, stack$$1[index]);
71669 return change(previous);
71673 undoAnnotation: function() {
71676 if (stack$$1[i].annotation) return stack$$1[i].annotation;
71682 redoAnnotation: function() {
71684 while (i <= stack$$1.length - 1) {
71685 if (stack$$1[i].annotation) return stack$$1[i].annotation;
71691 intersects: function(extent$$1) {
71692 return tree$$1.intersects(extent$$1, stack$$1[index].graph);
71696 difference: function() {
71697 var base = stack$$1[0].graph,
71698 head = stack$$1[index].graph;
71699 return coreDifference(base, head);
71703 changes: function(action) {
71704 var base = stack$$1[0].graph,
71705 head = stack$$1[index].graph;
71708 head = action(head);
71711 var difference = coreDifference(base, head);
71714 modified: difference.modified(),
71715 created: difference.created(),
71716 deleted: difference.deleted()
71721 validate: function(changes) {
71722 return lodash(Validations)
71723 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
71729 hasChanges: function() {
71730 return this.difference().length() > 0;
71734 imageryUsed: function(sources) {
71736 imageryUsed = sources;
71739 return lodash(stack$$1.slice(1, index + 1))
71740 .map('imageryUsed')
71743 .without(undefined, 'Custom')
71749 // save the current history state
71750 checkpoint: function(key) {
71751 checkpoints[key] = {
71752 stack: lodash.cloneDeep(stack$$1),
71759 // restore history state to a given checkpoint or reset completely
71760 reset: function(key) {
71761 if (key !== undefined && checkpoints.hasOwnProperty(key)) {
71762 stack$$1 = lodash.cloneDeep(checkpoints[key].stack);
71763 index = checkpoints[key].index;
71765 stack$$1 = [{graph: coreGraph$$1()}];
71767 tree$$1 = coreTree(stack$$1[0].graph);
71770 dispatch$$1.call('change');
71775 toIntroGraph: function() {
71776 var nextId = { n: 0, r: 0, w: 0 },
71778 graph = this.graph(),
71781 // clone base entities..
71782 lodash.forEach(graph.base().entities, function(entity) {
71783 var copy = lodash.cloneDeepWith(entity, customizer);
71784 baseEntities[copy.id] = copy;
71787 // replace base entities with head entities..
71788 lodash.forEach(graph.entities, function(entity, id) {
71790 var copy = lodash.cloneDeepWith(entity, customizer);
71791 baseEntities[copy.id] = copy;
71793 delete baseEntities[id];
71797 // swap temporary for permanent ids..
71798 lodash.forEach(baseEntities, function(entity) {
71799 if (Array.isArray(entity.nodes)) {
71800 entity.nodes = entity.nodes.map(function(node) {
71801 return permIds[node] || node;
71804 if (Array.isArray(entity.members)) {
71805 entity.members = entity.members.map(function(member) {
71806 member.id = permIds[member.id] || member.id;
71812 return JSON.stringify({ dataIntroGraph: baseEntities });
71815 function customizer(src) {
71816 var copy = lodash.omit(lodash.cloneDeep(src), ['type', 'user', 'v', 'version', 'visible']);
71817 if (lodash.isEmpty(copy.tags)) {
71821 if (Array.isArray(copy.loc)) {
71822 copy.loc[0] = +copy.loc[0].toFixed(6);
71823 copy.loc[1] = +copy.loc[1].toFixed(6);
71826 var match = src.id.match(/([nrw])-\d*/); // temporary id
71827 if (match !== null) {
71828 var nrw = match[1], permId;
71829 do { permId = nrw + (++nextId[nrw]); }
71830 while (baseEntities.hasOwnProperty(permId));
71832 copy.id = permIds[src.id] = permId;
71839 toJSON: function() {
71840 if (!this.hasChanges()) return;
71842 var allEntities = {},
71844 base = stack$$1[0];
71846 var s = stack$$1.map(function(i) {
71847 var modified = [], deleted = [];
71849 lodash.forEach(i.graph.entities, function(entity, id) {
71851 var key = osmEntity$$1.key(entity);
71852 allEntities[key] = entity;
71853 modified.push(key);
71858 // make sure that the originals of changed or deleted entities get merged
71859 // into the base of the stack after restoring the data from JSON.
71860 if (id in base.graph.entities) {
71861 baseEntities[id] = base.graph.entities[id];
71863 // get originals of parent entities too
71864 lodash.forEach(base.graph._parentWays[id], function(parentId) {
71865 if (parentId in base.graph.entities) {
71866 baseEntities[parentId] = base.graph.entities[parentId];
71873 if (modified.length) x.modified = modified;
71874 if (deleted.length) x.deleted = deleted;
71875 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
71876 if (i.annotation) x.annotation = i.annotation;
71881 return JSON.stringify({
71883 entities: lodash.values(allEntities),
71884 baseEntities: lodash.values(baseEntities),
71886 nextIDs: osmEntity$$1.id.next,
71892 fromJSON: function(json$$1, loadChildNodes) {
71893 var h = JSON.parse(json$$1),
71894 loadComplete = true;
71896 osmEntity$$1.id.next = h.nextIDs;
71899 if (h.version === 2 || h.version === 3) {
71900 var allEntities = {};
71902 h.entities.forEach(function(entity) {
71903 allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
71906 if (h.version === 3) {
71907 // This merges originals for changed entities into the base of
71908 // the stack even if the current stack doesn't have them (for
71909 // example when iD has been restarted in a different region)
71910 var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
71911 stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
71912 tree$$1.rebase(baseEntities, true);
71914 // When we restore a modified way, we also need to fetch any missing
71915 // childnodes that would normally have been downloaded with it.. #2142
71916 if (loadChildNodes) {
71917 var missing = lodash(baseEntities)
71918 .filter({ type: 'way' })
71922 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
71925 if (!lodash.isEmpty(missing)) {
71926 loadComplete = false;
71927 context.redrawEnable(false);
71929 var loading = uiLoading(context).blocking(true);
71930 context.container().call(loading);
71932 var childNodesLoaded = function(err, result) {
71934 var visible = lodash.groupBy(result.data, 'visible');
71935 if (!lodash.isEmpty(visible.true)) {
71936 missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
71937 stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
71938 tree$$1.rebase(visible.true, true);
71941 // fetch older versions of nodes that were deleted..
71942 lodash.each(visible.false, function(entity) {
71943 context.connection()
71944 .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
71948 if (err || lodash.isEmpty(missing)) {
71950 context.redrawEnable(true);
71951 dispatch$$1.call('change');
71955 context.connection().loadMultiple(missing, childNodesLoaded);
71960 stack$$1 = h.stack.map(function(d) {
71961 var entities = {}, entity;
71964 d.modified.forEach(function(key) {
71965 entity = allEntities[key];
71966 entities[entity.id] = entity;
71971 d.deleted.forEach(function(id) {
71972 entities[id] = undefined;
71977 graph: coreGraph$$1(stack$$1[0].graph).load(entities),
71978 annotation: d.annotation,
71979 imageryUsed: d.imageryUsed
71983 } else { // original version
71984 stack$$1 = h.stack.map(function(d) {
71987 for (var i in d.entities) {
71988 var entity = d.entities[i];
71989 entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
71992 d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
71997 if (loadComplete) {
71998 dispatch$$1.call('change');
72006 if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
72011 clearSaved: function() {
72012 context.debouncedSave.cancel();
72013 if (lock.locked()) context.storage(getKey('saved_history'), null);
72019 return lock.lock();
72023 unlock: function() {
72028 // is iD not open in another window and it detects that
72029 // there's a history stored in localStorage that's recoverable?
72030 restorableChanges: function() {
72031 return lock.locked() && !!context.storage(getKey('saved_history'));
72035 // load history from a version stored in localStorage
72036 restore: function() {
72037 if (!lock.locked()) return;
72039 var json$$1 = context.storage(getKey('saved_history'));
72040 if (json$$1) history.fromJSON(json$$1, true);
72051 return utilRebind(history, dispatch$$1, 'on');
72054 function presetCollection(collection) {
72055 var maxSearchResults = 50,
72056 maxSuggestionResults = 10;
72060 collection: collection,
72063 item: function(id) {
72064 return lodash.find(this.collection, function(d) {
72065 return d.id === id;
72070 matchGeometry: function(geometry) {
72071 return presetCollection(this.collection.filter(function(d) {
72072 return d.matchGeometry(geometry);
72077 search: function(value, geometry) {
72078 if (!value) return this;
72080 function leading(a) {
72081 var index = a.indexOf(value);
72082 return index === 0 || a[index - 1] === ' ';
72085 function suggestionName(name) {
72086 var nameArray = name.split(' - ');
72087 if (nameArray.length > 1) {
72088 name = nameArray.slice(0, nameArray.length - 1).join(' - ');
72090 return name.toLowerCase();
72094 value = value.toLowerCase();
72096 var searchable = lodash.filter(this.collection, function(a) {
72097 return a.searchable !== false && a.suggestion !== true;
72099 suggestions = lodash.filter(this.collection, function(a) {
72100 return a.suggestion === true;
72104 // matches value to preset.name
72105 var leading_name = lodash.filter(searchable, function(a) {
72106 return leading(a.name().toLowerCase());
72107 }).sort(function(a, b) {
72109 i = b.originalScore - a.originalScore;
72110 if (i !== 0) return i;
72112 i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
72113 if (i !== 0) return i;
72115 return a.name().length - b.name().length;
72118 // matches value to preset.terms values
72119 var leading_terms = lodash.filter(searchable, function(a) {
72120 return lodash.some(a.terms() || [], leading);
72123 // matches value to preset.tags values
72124 var leading_tag_values = lodash.filter(searchable, function(a) {
72125 return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
72129 // finds close matches to value in preset.name
72130 var similar_name = searchable.map(function(a) {
72133 dist: utilEditDistance(value, a.name())
72135 }).filter(function(a) {
72136 return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
72137 }).sort(function(a, b) {
72138 return a.dist - b.dist;
72139 }).map(function(a) {
72143 // finds close matches to value in preset.terms
72144 var similar_terms = lodash.filter(searchable, function(a) {
72145 return lodash.some(a.terms() || [], function(b) {
72146 return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
72150 var leading_suggestions = lodash.filter(suggestions, function(a) {
72151 return leading(suggestionName(a.name()));
72152 }).sort(function(a, b) {
72153 a = suggestionName(a.name());
72154 b = suggestionName(b.name());
72155 var i = a.indexOf(value) - b.indexOf(value);
72156 if (i === 0) return a.length - b.length;
72160 var similar_suggestions = suggestions.map(function(a) {
72163 dist: utilEditDistance(value, suggestionName(a.name()))
72165 }).filter(function(a) {
72166 return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
72167 }).sort(function(a, b) {
72168 return a.dist - b.dist;
72169 }).map(function(a) {
72173 var other = presets.item(geometry);
72175 var results = leading_name.concat(
72177 leading_tag_values,
72178 leading_suggestions.slice(0, maxSuggestionResults + 5),
72181 similar_suggestions.slice(0, maxSuggestionResults)
72182 ).slice(0, maxSearchResults - 1);
72184 return presetCollection(lodash.uniq(results.concat(other)));
72192 function presetCategory(id, category, all) {
72193 category = lodash.clone(category);
72198 category.members = presetCollection(category.members.map(function(id) {
72199 return all.item(id);
72203 category.matchGeometry = function(geometry) {
72204 return category.geometry.indexOf(geometry) >= 0;
72208 category.matchScore = function() {
72213 category.name = function() {
72214 return t('presets.categories.' + id + '.name', {'default': id});
72218 category.terms = function() {
72226 function presetField(id, field) {
72227 field = lodash.clone(field);
72232 field.matchGeometry = function(geometry) {
72233 return !field.geometry || field.geometry === geometry;
72237 field.t = function(scope, options) {
72238 return t('presets.fields.' + id + '.' + scope, options);
72242 field.label = function() {
72243 return field.t('label', {'default': id});
72247 var placeholder = field.placeholder;
72248 field.placeholder = function() {
72249 return field.t('placeholder', {'default': placeholder});
72256 function presetPreset(id, preset, fields) {
72257 preset = lodash.clone(preset);
72260 preset.fields = (preset.fields || []).map(getFields);
72261 preset.geometry = (preset.geometry || []);
72264 function getFields(f) {
72269 preset.matchGeometry = function(geometry) {
72270 return preset.geometry.indexOf(geometry) >= 0;
72274 preset.originalScore = preset.matchScore || 1;
72277 preset.matchScore = function(entity) {
72278 var tags = preset.tags,
72281 for (var t$$1 in tags) {
72282 if (entity.tags[t$$1] === tags[t$$1]) {
72283 score += preset.originalScore;
72284 } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
72285 score += preset.originalScore / 2;
72295 preset.t = function(scope, options) {
72296 return t('presets.presets.' + id + '.' + scope, options);
72300 var name = preset.name || '';
72301 preset.name = function() {
72302 if (preset.suggestion) {
72303 id = id.split('/');
72304 id = id[0] + '/' + id[1];
72305 return name + ' - ' + t('presets.presets.' + id + '.name');
72307 return preset.t('name', {'default': name});
72311 preset.terms = function() {
72312 return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
72316 preset.isFallback = function() {
72317 var tagCount = Object.keys(preset.tags).length;
72318 return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
72322 var reference = preset.reference || {};
72323 preset.reference = function(geometry) {
72324 var key = reference.key || Object.keys(preset.tags)[0],
72325 value = reference.value || preset.tags[key];
72327 if (geometry === 'relation' && key === 'type') {
72328 if (value in preset.tags) {
72330 value = preset.tags[key];
72332 return { rtype: value };
72336 if (value === '*') {
72337 return { key: key };
72339 return { key: key, value: value };
72344 var removeTags = preset.removeTags || preset.tags;
72345 preset.removeTags = function(tags, geometry) {
72346 tags = lodash.omit(tags, lodash.keys(removeTags));
72348 for (var f in preset.fields) {
72349 var field = preset.fields[f];
72350 if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
72351 delete tags[field.key];
72360 var applyTags = preset.addTags || preset.tags;
72361 preset.applyTags = function(tags, geometry) {
72364 tags = lodash.clone(tags);
72366 for (k in applyTags) {
72367 if (applyTags[k] === '*') {
72370 tags[k] = applyTags[k];
72374 // Add area=yes if necessary.
72375 // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
72376 // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
72377 // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
72378 if (geometry === 'area') {
72379 var needsAreaTag = true;
72380 if (preset.geometry.indexOf('line') === -1) {
72381 for (k in applyTags) {
72382 if (k in areaKeys) {
72383 needsAreaTag = false;
72388 if (needsAreaTag) {
72393 for (var f in preset.fields) {
72394 var field = preset.fields[f];
72395 if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
72396 tags[field.key] = field.default;
72407 function presetIndex() {
72408 // a presetCollection with methods for
72409 // loading new data and returning defaults
72411 var all = presetCollection([]),
72412 defaults = { area: all, line: all, point: all, vertex: all, relation: all },
72415 recent = presetCollection([]);
72417 // Index of presets by (geometry, tag key).
72426 all.match = function(entity, resolver) {
72427 var geometry = entity.geometry(resolver);
72429 // Treat entities on addr:interpolation lines as points, not vertices (#3241)
72430 if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
72431 geometry = 'point';
72434 var geometryMatches = index[geometry],
72438 for (var k in entity.tags) {
72439 var keyMatches = geometryMatches[k];
72440 if (!keyMatches) continue;
72442 for (var i = 0; i < keyMatches.length; i++) {
72443 var score = keyMatches[i].matchScore(entity);
72444 if (score > best) {
72446 match = keyMatches[i];
72451 return match || all.item(geometry);
72455 // Because of the open nature of tagging, iD will never have a complete
72456 // list of tags used in OSM, so we want it to have logic like "assume
72457 // that a closed way with an amenity tag is an area, unless the amenity
72458 // is one of these specific types". This function computes a structure
72459 // that allows testing of such conditions, based on the presets designated
72460 // as as supporting (or not supporting) the area geometry.
72462 // The returned object L is a whitelist/blacklist of tags. A closed way
72463 // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
72464 // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
72465 // and the subkeys form the blacklist.
72466 all.areaKeys = function() {
72468 ignore = ['barrier', 'highway', 'footway', 'railway', 'type'], // probably a line..
72469 presets = lodash.reject(all.collection, 'suggestion');
72472 presets.forEach(function(d) {
72473 for (var key in d.tags) break;
72475 if (ignore.indexOf(key) !== -1) return;
72477 if (d.geometry.indexOf('area') !== -1) { // probably an area..
72478 areaKeys[key] = areaKeys[key] || {};
72483 presets.forEach(function(d) {
72484 for (var key in d.tags) break;
72486 if (ignore.indexOf(key) !== -1) return;
72488 var value = d.tags[key];
72489 if (key in areaKeys && // probably an area...
72490 d.geometry.indexOf('line') !== -1 && // but sometimes a line
72492 areaKeys[key][value] = true;
72500 all.init = function() {
72501 var d = data.presets;
72503 all.collection = [];
72504 recent.collection = [];
72507 index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
72510 lodash.forEach(d.fields, function(d, id) {
72511 fields[id] = presetField(id, d);
72512 if (d.universal) universal.push(fields[id]);
72517 lodash.forEach(d.presets, function(d, id) {
72518 all.collection.push(presetPreset(id, d, fields));
72522 if (d.categories) {
72523 lodash.forEach(d.categories, function(d, id) {
72524 all.collection.push(presetCategory(id, d, all));
72529 var getItem = lodash.bind(all.item, all);
72531 area: presetCollection(d.defaults.area.map(getItem)),
72532 line: presetCollection(d.defaults.line.map(getItem)),
72533 point: presetCollection(d.defaults.point.map(getItem)),
72534 vertex: presetCollection(d.defaults.vertex.map(getItem)),
72535 relation: presetCollection(d.defaults.relation.map(getItem))
72539 for (var i = 0; i < all.collection.length; i++) {
72540 var preset = all.collection[i],
72541 geometry = preset.geometry;
72543 for (var j = 0; j < geometry.length; j++) {
72544 var g = index[geometry[j]];
72545 for (var k in preset.tags) {
72546 (g[k] = g[k] || []).push(preset);
72554 all.field = function(id) {
72558 all.universal = function() {
72562 all.defaults = function(geometry, n) {
72563 var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
72564 def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
72565 return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
72568 all.choose = function(preset) {
72569 if (!preset.isFallback()) {
72570 recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
72580 function setAreaKeys(value) {
72585 function coreContext() {
72587 // create a special translation that contains the keys in place of the strings
72588 var tkeys = lodash.cloneDeep(en);
72591 function traverser(v, k, obj) {
72593 if (lodash.isObject(v)) {
72594 lodash.forOwn(v, traverser);
72595 } else if (lodash.isString(v)) {
72596 obj[k] = parents.join('.');
72601 lodash.forOwn(tkeys, traverser);
72602 addTranslation('_tkeys_', tkeys);
72604 addTranslation('en', en);
72607 var dispatch$$1 = dispatch('enter', 'exit', 'change'),
72610 // https://github.com/openstreetmap/iD/issues/772
72611 // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
72613 try { storage = localStorage; } catch (e) {} // eslint-disable-line no-empty
72614 storage = storage || (function() {
72617 getItem: function(k) { return s[k]; },
72618 setItem: function(k, v) { s[k] = v; },
72619 removeItem: function(k) { delete s[k]; }
72623 context.storage = function(k, v) {
72625 if (arguments.length === 1) return storage.getItem(k);
72626 else if (v === null) storage.removeItem(k);
72627 else storage.setItem(k, v);
72629 // localstorage quota exceeded
72630 /* eslint-disable no-console */
72631 if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
72632 /* eslint-enable no-console */
72637 /* Straight accessors. Avoid using these if you can. */
72638 var ui, connection, history;
72639 context.ui = function() { return ui; };
72640 context.connection = function() { return connection; };
72641 context.history = function() { return history; };
72645 function entitiesLoaded(err, result) {
72646 if (!err) history.merge(result.data, result.extent);
72649 context.preauth = function(options) {
72650 connection.switch(options);
72654 context.loadTiles = function(projection, dimensions, callback) {
72655 function done(err, result) {
72656 entitiesLoaded(err, result);
72657 if (callback) callback(err, result);
72659 connection.loadTiles(projection, dimensions, done);
72662 context.loadEntity = function(id, callback) {
72663 function done(err, result) {
72664 entitiesLoaded(err, result);
72665 if (callback) callback(err, result);
72667 connection.loadEntity(id, done);
72670 context.zoomToEntity = function(id, zoomTo) {
72671 if (zoomTo !== false) {
72672 this.loadEntity(id, function(err, result) {
72674 var entity = lodash.find(result.data, function(e) { return e.id === id; });
72675 if (entity) { map$$1.zoomTo(entity); }
72679 map$$1.on('drawn.zoomToEntity', function() {
72680 if (!context.hasEntity(id)) return;
72681 map$$1.on('drawn.zoomToEntity', null);
72682 context.on('enter.zoomToEntity', null);
72683 context.enter(modeSelect(context, [id]));
72686 context.on('enter.zoomToEntity', function() {
72687 if (mode.id !== 'browse') {
72688 map$$1.on('drawn.zoomToEntity', null);
72689 context.on('enter.zoomToEntity', null);
72694 var minEditableZoom = 16;
72695 context.minEditableZoom = function(_) {
72696 if (!arguments.length) return minEditableZoom;
72697 minEditableZoom = _;
72698 connection.tileZoom(_);
72704 var inIntro = false;
72705 context.inIntro = function(_) {
72706 if (!arguments.length) return inIntro;
72711 context.save = function() {
72712 // no history save, no message onbeforeunload
72713 if (inIntro || select('.modal').size()) return;
72716 if (mode && mode.id === 'save') {
72719 canSave = context.selectedIDs().every(function(id) {
72720 var entity = context.hasEntity(id);
72721 return entity && !entity.isDegenerate();
72728 if (history.hasChanges()) {
72729 return t('save.unsaved_changes');
72735 context.hasEntity = function(id) {
72736 return history.graph().hasEntity(id);
72738 context.entity = function(id) {
72739 return history.graph().entity(id);
72741 context.childNodes = function(way) {
72742 return history.graph().childNodes(way);
72744 context.geometry = function(id) {
72745 return context.entity(id).geometry(history.graph());
72751 context.mode = function() {
72754 context.enter = function(newMode) {
72757 dispatch$$1.call('exit', this, mode);
72762 dispatch$$1.call('enter', this, mode);
72765 context.selectedIDs = function() {
72766 if (mode && mode.selectedIDs) {
72767 return mode.selectedIDs();
72775 context.install = function(behavior) {
72776 context.surface().call(behavior);
72778 context.uninstall = function(behavior) {
72779 context.surface().call(behavior.off);
72784 var copyIDs = [], copyGraph;
72785 context.copyGraph = function() { return copyGraph; };
72786 context.copyIDs = function(_) {
72787 if (!arguments.length) return copyIDs;
72789 copyGraph = history.graph();
72796 context.background = function() { return background; };
72801 context.features = function() { return features; };
72802 context.hasHiddenConnections = function(id) {
72803 var graph = history.graph(),
72804 entity = graph.entity(id);
72805 return features.hasHiddenConnections(entity, graph);
72811 context.presets = function() { return presets; };
72816 context.map = function() { return map$$1; };
72817 context.layers = function() { return map$$1.layers; };
72818 context.surface = function() { return map$$1.surface; };
72819 context.editable = function() { return map$$1.editable(); };
72820 context.surfaceRect = function() {
72821 return map$$1.surface.node().getBoundingClientRect();
72833 context.debugFlags = function() {
72836 context.setDebug = function(flag, val) {
72837 if (arguments.length === 1) val = true;
72838 debugFlags[flag] = val;
72839 dispatch$$1.call('change');
72842 context.getDebug = function(flag) {
72843 return flag && debugFlags[flag];
72848 var container = select(document.body);
72849 context.container = function(_) {
72850 if (!arguments.length) return container;
72852 container.classed('id-container', true);
72856 context.embed = function(_) {
72857 if (!arguments.length) return embed;
72864 var assetPath = '';
72865 context.assetPath = function(_) {
72866 if (!arguments.length) return assetPath;
72872 context.assetMap = function(_) {
72873 if (!arguments.length) return assetMap;
72878 context.asset = function(_) {
72879 var filename = assetPath + _;
72880 return assetMap[filename] || filename;
72883 context.imagePath = function(_) {
72884 return context.asset('img/' + _);
72889 // `locale` variable contains a "requested locale".
72890 // It won't become the `currentLocale` until after loadLocale() is called.
72891 var locale, localePath;
72893 context.locale = function(loc, path$$1) {
72894 if (!arguments.length) return currentLocale;
72896 localePath = path$$1;
72900 context.loadLocale = function(callback) {
72901 if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) {
72902 localePath = localePath || context.asset('locales/' + locale + '.json');
72903 json(localePath, function(err, result) {
72905 addTranslation(locale, result[locale]);
72925 /* reset (aka flush) */
72926 context.reset = context.flush = function() {
72927 context.debouncedSave.cancel();
72928 lodash.each(services, function(service) {
72929 if (service && typeof service.reset === 'function') {
72930 service.reset(context);
72940 context.version = '2.2.1';
72942 context.projection = geoRawMercator();
72943 context.curtainProjection = geoRawMercator();
72945 locale = utilDetect().locale;
72946 if (locale && !dataLocales.hasOwnProperty(locale)) {
72947 locale = locale.split('-')[0];
72950 history = coreHistory(context);
72951 context.graph = history.graph;
72952 context.changes = history.changes;
72953 context.intersects = history.intersects;
72955 // Debounce save, since it's a synchronous localStorage write,
72956 // and history changes can happen frequently (e.g. when dragging).
72957 context.debouncedSave = lodash.debounce(context.save, 350);
72958 function withDebouncedSave(fn) {
72959 return function() {
72960 var result = fn.apply(history, arguments);
72961 context.debouncedSave();
72966 context.perform = withDebouncedSave(history.perform);
72967 context.replace = withDebouncedSave(history.replace);
72968 context.pop = withDebouncedSave(history.pop);
72969 context.overwrite = withDebouncedSave(history.overwrite);
72970 context.undo = withDebouncedSave(history.undo);
72971 context.redo = withDebouncedSave(history.redo);
72973 ui = uiInit(context);
72975 connection = services.osm;
72976 background = rendererBackground(context);
72977 features = rendererFeatures(context);
72978 presets = presetIndex();
72980 map$$1 = rendererMap(context);
72981 context.mouse = map$$1.mouse;
72982 context.extent = map$$1.extent;
72983 context.pan = map$$1.pan;
72984 context.zoomIn = map$$1.zoomIn;
72985 context.zoomOut = map$$1.zoomOut;
72986 context.zoomInFurther = map$$1.zoomInFurther;
72987 context.zoomOutFurther = map$$1.zoomOutFurther;
72988 context.redrawEnable = map$$1.redrawEnable;
72990 lodash.each(services, function(service) {
72991 if (service && typeof service.init === 'function') {
72992 service.init(context);
72998 areaKeys = presets.areaKeys();
73001 return utilRebind(context, dispatch$$1, 'on');
73004 function osmWay() {
73005 if (!(this instanceof osmWay)) {
73006 return (new osmWay()).initialize(arguments);
73007 } else if (arguments.length) {
73008 this.initialize(arguments);
73013 osmEntity$$1.way = osmWay;
73015 osmWay.prototype = Object.create(osmEntity$$1.prototype);
73018 lodash.extend(osmWay.prototype, {
73023 copy: function(resolver, copies) {
73024 if (copies[this.id])
73025 return copies[this.id];
73027 var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
73029 var nodes = this.nodes.map(function(id) {
73030 return resolver.entity(id).copy(resolver, copies).id;
73033 copy = copy.update({ nodes: nodes });
73034 copies[this.id] = copy;
73040 extent: function(resolver) {
73041 return resolver.transient(this, 'extent', function() {
73042 var extent$$1 = geoExtent$$1();
73043 for (var i = 0; i < this.nodes.length; i++) {
73044 var node = resolver.hasEntity(this.nodes[i]);
73046 extent$$1._extend(node.extent());
73054 first: function() {
73055 return this.nodes[0];
73060 return this.nodes[this.nodes.length - 1];
73064 contains: function(node) {
73065 return this.nodes.indexOf(node) >= 0;
73069 affix: function(node) {
73070 if (this.nodes[0] === node) return 'prefix';
73071 if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
73075 layer: function() {
73076 // explicit layer tag, clamp between -10, 10..
73077 if (isFinite(this.tags.layer)) {
73078 return Math.max(-10, Math.min(+(this.tags.layer), 10));
73081 // implied layer tag..
73082 if (this.tags.location === 'overground') return 1;
73083 if (this.tags.location === 'underground') return -1;
73084 if (this.tags.location === 'underwater') return -10;
73086 if (this.tags.power === 'line') return 10;
73087 if (this.tags.power === 'minor_line') return 10;
73088 if (this.tags.aerialway) return 10;
73089 if (this.tags.bridge) return 1;
73090 if (this.tags.cutting) return -1;
73091 if (this.tags.tunnel) return -1;
73092 if (this.tags.waterway) return -1;
73093 if (this.tags.man_made === 'pipeline') return -10;
73094 if (this.tags.boundary) return -10;
73099 isOneWay: function() {
73100 // explicit oneway tag..
73101 if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
73102 if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
73104 // implied oneway tag..
73105 for (var key in this.tags) {
73106 if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
73113 lanes: function() {
73114 return osmLanes(this);
73118 isClosed: function() {
73119 return this.nodes.length > 1 && this.first() === this.last();
73123 isConvex: function(resolver) {
73124 if (!this.isClosed() || this.isDegenerate()) return null;
73126 var nodes = lodash.uniq(resolver.childNodes(this)),
73127 coords = lodash.map(nodes, 'loc'),
73128 curr = 0, prev = 0;
73130 for (var i = 0; i < coords.length; i++) {
73131 var o = coords[(i+1) % coords.length],
73133 b = coords[(i+2) % coords.length],
73134 res = geoCross(o, a, b);
73136 curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
73139 } else if (prev && curr !== prev) {
73148 isArea: function() {
73149 if (this.tags.area === 'yes')
73151 if (!this.isClosed() || this.tags.area === 'no')
73153 for (var key in this.tags) {
73154 if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
73162 isDegenerate: function() {
73163 return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
73167 areAdjacent: function(n1, n2) {
73168 for (var i = 0; i < this.nodes.length; i++) {
73169 if (this.nodes[i] === n1) {
73170 if (this.nodes[i - 1] === n2) return true;
73171 if (this.nodes[i + 1] === n2) return true;
73178 geometry: function(graph) {
73179 return graph.transient(this, 'geometry', function() {
73180 return this.isArea() ? 'area' : 'line';
73185 // If this way is not closed, append the beginning node to the end of the nodelist to close it.
73186 close: function() {
73187 if (this.isClosed() || !this.nodes.length) return this;
73189 var nodes = this.nodes.slice();
73190 nodes = nodes.filter(noRepeatNodes);
73191 nodes.push(nodes[0]);
73192 return this.update({ nodes: nodes });
73196 // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
73197 unclose: function() {
73198 if (!this.isClosed()) return this;
73200 var nodes = this.nodes.slice(),
73201 connector = this.first(),
73202 i = nodes.length - 1;
73204 // remove trailing connectors..
73205 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
73206 nodes.splice(i, 1);
73207 i = nodes.length - 1;
73210 nodes = nodes.filter(noRepeatNodes);
73211 return this.update({ nodes: nodes });
73215 // Adds a node (id) in front of the node which is currently at position index.
73216 // If index is undefined, the node will be added to the end of the way for linear ways,
73217 // or just before the final connecting node for circular ways.
73218 // Consecutive duplicates are eliminated including existing ones.
73219 // Circularity is always preserved when adding a node.
73220 addNode: function(id, index) {
73221 var nodes = this.nodes.slice(),
73222 isClosed = this.isClosed(),
73223 max$$1 = isClosed ? nodes.length - 1 : nodes.length;
73225 if (index === undefined) {
73229 if (index < 0 || index > max$$1) {
73230 throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
73233 // If this is a closed way, remove all connector nodes except the first one
73234 // (there may be duplicates) and adjust index if necessary..
73236 var connector = this.first();
73238 // leading connectors..
73240 while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
73241 nodes.splice(i, 1);
73242 if (index > i) index--;
73245 // trailing connectors..
73246 i = nodes.length - 1;
73247 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
73248 nodes.splice(i, 1);
73249 if (index > i) index--;
73250 i = nodes.length - 1;
73254 nodes.splice(index, 0, id);
73255 nodes = nodes.filter(noRepeatNodes);
73257 // If the way was closed before, append a connector node to keep it closed..
73258 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
73259 nodes.push(nodes[0]);
73262 return this.update({ nodes: nodes });
73266 // Replaces the node which is currently at position index with the given node (id).
73267 // Consecutive duplicates are eliminated including existing ones.
73268 // Circularity is preserved when updating a node.
73269 updateNode: function(id, index) {
73270 var nodes = this.nodes.slice(),
73271 isClosed = this.isClosed(),
73272 max$$1 = nodes.length - 1;
73274 if (index === undefined || index < 0 || index > max$$1) {
73275 throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
73278 // If this is a closed way, remove all connector nodes except the first one
73279 // (there may be duplicates) and adjust index if necessary..
73281 var connector = this.first();
73283 // leading connectors..
73285 while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
73286 nodes.splice(i, 1);
73287 if (index > i) index--;
73290 // trailing connectors..
73291 i = nodes.length - 1;
73292 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
73293 nodes.splice(i, 1);
73294 if (index === i) index = 0; // update leading connector instead
73295 i = nodes.length - 1;
73299 nodes.splice(index, 1, id);
73300 nodes = nodes.filter(noRepeatNodes);
73302 // If the way was closed before, append a connector node to keep it closed..
73303 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
73304 nodes.push(nodes[0]);
73307 return this.update({nodes: nodes});
73311 // Replaces each occurrence of node id needle with replacement.
73312 // Consecutive duplicates are eliminated including existing ones.
73313 // Circularity is preserved.
73314 replaceNode: function(needle, replacement) {
73315 var nodes = this.nodes.slice(),
73316 isClosed = this.isClosed();
73318 for (var i = 0; i < nodes.length; i++) {
73319 if (nodes[i] === needle) {
73320 nodes[i] = replacement;
73324 nodes = nodes.filter(noRepeatNodes);
73326 // If the way was closed before, append a connector node to keep it closed..
73327 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
73328 nodes.push(nodes[0]);
73331 return this.update({nodes: nodes});
73335 // Removes each occurrence of node id needle with replacement.
73336 // Consecutive duplicates are eliminated including existing ones.
73337 // Circularity is preserved.
73338 removeNode: function(id) {
73339 var nodes = this.nodes.slice(),
73340 isClosed = this.isClosed();
73343 .filter(function(node) { return node !== id; })
73344 .filter(noRepeatNodes);
73346 // If the way was closed before, append a connector node to keep it closed..
73347 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
73348 nodes.push(nodes[0]);
73351 return this.update({nodes: nodes});
73355 asJXON: function(changeset_id) {
73358 '@id': this.osmId(),
73359 '@version': this.version || 0,
73360 nd: lodash.map(this.nodes, function(id) {
73361 return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
73363 tag: lodash.map(this.tags, function(v, k) {
73364 return { keyAttributes: { k: k, v: v } };
73368 if (changeset_id) {
73369 r.way['@changeset'] = changeset_id;
73375 asGeoJSON: function(resolver) {
73376 return resolver.transient(this, 'GeoJSON', function() {
73377 var coordinates = lodash.map(resolver.childNodes(this), 'loc');
73378 if (this.isArea() && this.isClosed()) {
73381 coordinates: [coordinates]
73385 type: 'LineString',
73386 coordinates: coordinates
73393 area: function(resolver) {
73394 return resolver.transient(this, 'area', function() {
73395 var nodes = resolver.childNodes(this);
73399 coordinates: [lodash.map(nodes, 'loc')]
73402 if (!this.isClosed() && nodes.length) {
73403 json$$1.coordinates[0].push(nodes[0].loc);
73406 var area$$1 = area(json$$1);
73408 // Heuristic for detecting counterclockwise winding order. Assumes
73409 // that OpenStreetMap polygons are not hemisphere-spanning.
73410 if (area$$1 > 2 * Math.PI) {
73411 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
73412 area$$1 = area(json$$1);
73415 return isNaN(area$$1) ? 0 : area$$1;
73421 // Filter function to eliminate consecutive duplicates.
73422 function noRepeatNodes(node, i, arr) {
73423 return i === 0 || node !== arr[i - 1];
73426 function osmTurn(turn) {
73427 if (!(this instanceof osmTurn))
73428 return new osmTurn(turn);
73429 lodash.extend(this, turn);
73433 function osmIntersection(graph, vertexId) {
73434 var vertex = graph.entity(vertexId),
73435 parentWays = graph.parentWays(vertex),
73439 function addHighway(way, adjacentNodeId) {
73440 if (highways[adjacentNodeId]) {
73441 coincident.push(adjacentNodeId);
73443 highways[adjacentNodeId] = way;
73447 // Pre-split ways that would need to be split in
73448 // order to add a restriction. The real split will
73449 // happen when the restriction is added.
73450 parentWays.forEach(function(way) {
73451 if (!way.tags.highway || way.isArea() || way.isDegenerate())
73454 var isFirst = (vertexId === way.first()),
73455 isLast = (vertexId === way.last()),
73456 isAffix = (isFirst || isLast),
73457 isClosingNode = (isFirst && isLast);
73459 if (isAffix && !isClosingNode) {
73460 var index = (isFirst ? 1 : way.nodes.length - 2);
73461 addHighway(way, way.nodes[index]);
73464 var splitIndex, wayA, wayB, indexA, indexB;
73465 if (isClosingNode) {
73466 splitIndex = Math.ceil(way.nodes.length / 2); // split at midpoint
73467 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
73468 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
73470 indexB = way.nodes.length - 2;
73472 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1); // split at vertexid
73473 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
73474 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
73475 indexA = splitIndex - 1;
73476 indexB = splitIndex + 1;
73478 graph = graph.replace(wayA).replace(wayB);
73479 addHighway(wayA, way.nodes[indexA]);
73480 addHighway(wayB, way.nodes[indexB]);
73484 // remove any ways from this intersection that are coincident
73485 // (i.e. any adjacent node used by more than one intersecting way)
73486 coincident.forEach(function (n) {
73487 delete highways[n];
73491 var intersection = {
73492 highways: highways,
73493 ways: lodash.values(highways),
73498 intersection.adjacentNodeId = function(fromWayId) {
73499 return lodash.find(lodash.keys(highways), function(k) {
73500 return highways[k].id === fromWayId;
73505 intersection.turns = function(fromNodeId) {
73506 var start = highways[fromNodeId];
73510 if (start.first() === vertex.id && start.tags.oneway === 'yes')
73512 if (start.last() === vertex.id && start.tags.oneway === '-1')
73515 function withRestriction(turn) {
73516 graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
73517 if (relation.tags.type !== 'restriction')
73520 var f = relation.memberByRole('from'),
73521 t = relation.memberByRole('to'),
73522 v = relation.memberByRole('via');
73524 if (f && f.id === turn.from.way &&
73525 v && v.id === turn.via.node &&
73526 t && t.id === turn.to.way) {
73527 turn.restriction = relation.id;
73528 } else if (/^only_/.test(relation.tags.restriction) &&
73529 f && f.id === turn.from.way &&
73530 v && v.id === turn.via.node &&
73531 t && t.id !== turn.to.way) {
73532 turn.restriction = relation.id;
73533 turn.indirect_restriction = true;
73537 return osmTurn(turn);
73543 way: start.id.split(/-(a|b)/)[0]
73545 via = { node: vertex.id },
73548 lodash.each(highways, function(end, adjacentNodeId) {
73553 if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
73554 turns.push(withRestriction({
73558 node: adjacentNodeId,
73559 way: end.id.split(/-(a|b)/)[0]
73565 if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
73566 turns.push(withRestriction({
73570 node: adjacentNodeId,
73571 way: end.id.split(/-(a|b)/)[0]
73579 if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
73580 turns.push(withRestriction({
73591 return intersection;
73595 function osmInferRestriction(graph, from, via, to, projection) {
73596 var fromWay = graph.entity(from.way),
73597 fromNode = graph.entity(from.node),
73598 toWay = graph.entity(to.way),
73599 toNode = graph.entity(to.node),
73600 viaNode = graph.entity(via.node),
73601 fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
73602 (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
73603 toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
73604 (toWay.tags.oneway === '-1' && toWay.last() === via.node),
73605 angle = geoAngle(viaNode, fromNode, projection) -
73606 geoAngle(viaNode, toNode, projection);
73608 angle = angle * 180 / Math.PI;
73613 if (fromNode === toNode)
73614 return 'no_u_turn';
73615 if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
73616 return 'no_u_turn';
73618 return 'no_right_turn';
73620 return 'no_left_turn';
73622 return 'no_straight_on';
73625 function actionAddMember(relationId, member, memberIndex) {
73626 return function(graph) {
73627 var relation = graph.entity(relationId);
73629 if (isNaN(memberIndex) && member.type === 'way') {
73630 var members = relation.indexedMembers();
73631 members.push(member);
73633 var joined = osmJoinWays(members, graph);
73634 for (var i = 0; i < joined.length; i++) {
73635 var segment = joined[i];
73636 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
73637 if (segment[j] !== member)
73641 memberIndex = segment[j + 1].index;
73642 } else if (j === segment.length - 1) {
73643 memberIndex = segment[j - 1].index + 1;
73645 memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
73651 return graph.replace(relation.addMember(member, memberIndex));
73655 function actionAddMidpoint(midpoint, node) {
73656 return function(graph) {
73657 graph = graph.replace(node.move(midpoint.loc));
73659 var parents = lodash.intersection(
73660 graph.parentWays(graph.entity(midpoint.edge[0])),
73661 graph.parentWays(graph.entity(midpoint.edge[1])));
73663 parents.forEach(function(way) {
73664 for (var i = 0; i < way.nodes.length - 1; i++) {
73665 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
73666 graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
73668 // Add only one midpoint on doubled-back segments,
73669 // turning them into self-intersections.
73679 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
73680 function actionAddVertex(wayId, nodeId, index) {
73681 return function(graph) {
73682 return graph.replace(graph.entity(wayId).addNode(nodeId, index));
73686 function actionChangeMember(relationId, member, memberIndex) {
73687 return function(graph) {
73688 return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
73692 function actionChangePreset(entityId, oldPreset, newPreset) {
73693 return function(graph) {
73694 var entity = graph.entity(entityId),
73695 geometry = entity.geometry(graph),
73696 tags = entity.tags;
73698 if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
73699 if (newPreset) tags = newPreset.applyTags(tags, geometry);
73701 return graph.replace(entity.update({tags: tags}));
73705 function actionChangeTags(entityId, tags) {
73706 return function(graph) {
73707 var entity = graph.entity(entityId);
73708 return graph.replace(entity.update({tags: tags}));
73712 function actionCircularize(wayId, projection, maxAngle) {
73713 maxAngle = (maxAngle || 20) * Math.PI / 180;
73716 var action = function(graph, t) {
73717 if (t === null || !isFinite(t)) t = 1;
73718 t = Math.min(Math.max(+t, 0), 1);
73720 var way = graph.entity(wayId),
73723 graph.childNodes(way).forEach(function(node) {
73724 if (!origNodes[node.id]) origNodes[node.id] = node;
73727 if (!way.isConvex(graph)) {
73728 graph = action.makeConvex(graph);
73731 var nodes = lodash.uniq(graph.childNodes(way)),
73732 keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
73733 points = nodes.map(function(n) { return projection(n.loc); }),
73734 keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
73735 centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
73736 radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
73737 sign = d3polygonArea(points) > 0 ? 1 : -1,
73740 // we need atleast two key nodes for the algorithm to work
73741 if (!keyNodes.length) {
73742 keyNodes = [nodes[0]];
73743 keyPoints = [points[0]];
73746 if (keyNodes.length === 1) {
73747 var index = nodes.indexOf(keyNodes[0]),
73748 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
73750 keyNodes.push(nodes[oppositeIndex]);
73751 keyPoints.push(points[oppositeIndex]);
73754 // key points and nodes are those connected to the ways,
73755 // they are projected onto the circle, inbetween nodes are moved
73756 // to constant intervals between key nodes, extra inbetween nodes are
73757 // added if necessary.
73758 for (var i = 0; i < keyPoints.length; i++) {
73759 var nextKeyNodeIndex = (i + 1) % keyNodes.length,
73760 startNode = keyNodes[i],
73761 endNode = keyNodes[nextKeyNodeIndex],
73762 startNodeIndex = nodes.indexOf(startNode),
73763 endNodeIndex = nodes.indexOf(endNode),
73764 numberNewPoints = -1,
73765 indexRange = endNodeIndex - startNodeIndex,
73767 inBetweenNodes = [],
73768 startAngle, endAngle, totalAngle, eachAngle,
73769 angle, loc, node, origNode, j;
73771 if (indexRange < 0) {
73772 indexRange += nodes.length;
73775 // position this key node
73776 var distance = geoEuclideanDistance(centroid, keyPoints[i]);
73777 if (distance === 0) { distance = 1e-4; }
73779 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
73780 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius
73782 loc = projection.invert(keyPoints[i]);
73783 node = keyNodes[i];
73784 origNode = origNodes[node.id];
73785 node = node.move(geoInterp(origNode.loc, loc, t));
73786 graph = graph.replace(node);
73788 // figure out the between delta angle we want to match to
73789 startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
73790 endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
73791 totalAngle = endAngle - startAngle;
73793 // detects looping around -pi/pi
73794 if (totalAngle * sign > 0) {
73795 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
73800 eachAngle = totalAngle / (indexRange + numberNewPoints);
73801 } while (Math.abs(eachAngle) > maxAngle);
73804 // move existing nodes
73805 for (j = 1; j < indexRange; j++) {
73806 angle = startAngle + j * eachAngle;
73807 loc = projection.invert([
73808 centroid[0] + Math.cos(angle) * radius,
73809 centroid[1] + Math.sin(angle) * radius
73812 node = nodes[(j + startNodeIndex) % nodes.length];
73813 origNode = origNodes[node.id];
73814 nearNodes[node.id] = angle;
73816 node = node.move(geoInterp(origNode.loc, loc, t));
73817 graph = graph.replace(node);
73820 // add new inbetween nodes if necessary
73821 for (j = 0; j < numberNewPoints; j++) {
73822 angle = startAngle + (indexRange + j) * eachAngle;
73823 loc = projection.invert([
73824 centroid[0] + Math.cos(angle) * radius,
73825 centroid[1] + Math.sin(angle) * radius
73828 // choose a nearnode to use as the original
73829 var min$$1 = Infinity;
73830 for (var nodeId in nearNodes) {
73831 var nearAngle = nearNodes[nodeId],
73832 dist = Math.abs(nearAngle - angle);
73833 if (dist < min$$1) {
73835 origNode = origNodes[nodeId];
73839 node = osmNode({ loc: geoInterp(origNode.loc, loc, t) });
73840 graph = graph.replace(node);
73842 nodes.splice(endNodeIndex + j, 0, node);
73843 inBetweenNodes.push(node.id);
73846 // Check for other ways that share these keyNodes..
73847 // If keyNodes are adjacent in both ways,
73848 // we can add inBetween nodes to that shared way too..
73849 if (indexRange === 1 && inBetweenNodes.length) {
73850 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
73851 endIndex1 = way.nodes.lastIndexOf(endNode.id),
73852 wayDirection1 = (endIndex1 - startIndex1);
73853 if (wayDirection1 < -1) { wayDirection1 = 1; }
73855 /* eslint-disable no-loop-func */
73856 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
73857 if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
73858 var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
73859 endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
73860 wayDirection2 = (endIndex2 - startIndex2),
73861 insertAt = endIndex2;
73862 if (wayDirection2 < -1) { wayDirection2 = 1; }
73864 if (wayDirection1 !== wayDirection2) {
73865 inBetweenNodes.reverse();
73866 insertAt = startIndex2;
73868 for (j = 0; j < inBetweenNodes.length; j++) {
73869 sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
73871 graph = graph.replace(sharedWay);
73874 /* eslint-enable no-loop-func */
73879 // update the way to have all the new nodes
73880 ids = nodes.map(function(n) { return n.id; });
73883 way = way.update({nodes: ids});
73884 graph = graph.replace(way);
73890 action.makeConvex = function(graph) {
73891 var way = graph.entity(wayId),
73892 nodes = lodash.uniq(graph.childNodes(way)),
73893 points = nodes.map(function(n) { return projection(n.loc); }),
73894 sign = d3polygonArea(points) > 0 ? 1 : -1,
73895 hull = d3polygonHull(points);
73897 // D3 convex hulls go counterclockwise..
73903 for (var i = 0; i < hull.length - 1; i++) {
73904 var startIndex = points.indexOf(hull[i]),
73905 endIndex = points.indexOf(hull[i+1]),
73906 indexRange = (endIndex - startIndex);
73908 if (indexRange < 0) {
73909 indexRange += nodes.length;
73912 // move interior nodes to the surface of the convex hull..
73913 for (var j = 1; j < indexRange; j++) {
73914 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
73915 node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
73916 graph = graph.replace(node);
73923 action.disabled = function(graph) {
73924 if (!graph.entity(wayId).isClosed())
73925 return 'not_closed';
73929 action.transitionable = true;
73935 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
73936 function actionDeleteWay(wayId) {
73939 function canDeleteNode(node, graph) {
73940 return !graph.parentWays(node).length &&
73941 !graph.parentRelations(node).length &&
73942 !node.hasInterestingTags();
73946 var action = function(graph) {
73947 var way = graph.entity(wayId);
73949 graph.parentRelations(way)
73950 .forEach(function(parent) {
73951 parent = parent.removeMembersWithID(wayId);
73952 graph = graph.replace(parent);
73954 if (parent.isDegenerate()) {
73955 graph = actionDeleteRelation(parent.id)(graph);
73959 lodash.uniq(way.nodes).forEach(function(nodeId) {
73960 graph = graph.replace(way.removeNode(nodeId));
73962 var node = graph.entity(nodeId);
73963 if (canDeleteNode(node, graph)) {
73964 graph = graph.remove(node);
73968 return graph.remove(way);
73975 function actionDeleteMultiple(ids) {
73977 way: actionDeleteWay,
73978 node: actionDeleteNode,
73979 relation: actionDeleteRelation
73983 var action = function(graph) {
73984 ids.forEach(function(id) {
73985 if (graph.hasEntity(id)) { // It may have been deleted aready.
73986 graph = actions[graph.entity(id).type](id)(graph);
73997 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
73998 function actionDeleteRelation(relationId) {
74001 function canDeleteEntity(entity, graph) {
74002 return !graph.parentWays(entity).length &&
74003 !graph.parentRelations(entity).length &&
74004 !entity.hasInterestingTags();
74008 var action = function(graph) {
74009 var relation = graph.entity(relationId);
74011 graph.parentRelations(relation)
74012 .forEach(function(parent) {
74013 parent = parent.removeMembersWithID(relationId);
74014 graph = graph.replace(parent);
74016 if (parent.isDegenerate()) {
74017 graph = actionDeleteRelation(parent.id)(graph);
74021 lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
74022 graph = graph.replace(relation.removeMembersWithID(memberId));
74024 var entity = graph.entity(memberId);
74025 if (canDeleteEntity(entity, graph)) {
74026 graph = actionDeleteMultiple([memberId])(graph);
74030 return graph.remove(relation);
74037 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
74038 function actionDeleteNode(nodeId) {
74039 var action = function(graph) {
74040 var node = graph.entity(nodeId);
74042 graph.parentWays(node)
74043 .forEach(function(parent) {
74044 parent = parent.removeNode(nodeId);
74045 graph = graph.replace(parent);
74047 if (parent.isDegenerate()) {
74048 graph = actionDeleteWay(parent.id)(graph);
74052 graph.parentRelations(node)
74053 .forEach(function(parent) {
74054 parent = parent.removeMembersWithID(nodeId);
74055 graph = graph.replace(parent);
74057 if (parent.isDegenerate()) {
74058 graph = actionDeleteRelation(parent.id)(graph);
74062 return graph.remove(node);
74069 // Connect the ways at the given nodes.
74071 // The last node will survive. All other nodes will be replaced with
74072 // the surviving node in parent ways, and then removed.
74074 // Tags and relation memberships of of non-surviving nodes are merged
74075 // to the survivor.
74077 // This is the inverse of `iD.actionDisconnect`.
74080 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
74081 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
74083 function actionConnect(nodeIds) {
74084 return function(graph) {
74085 var survivor = graph.entity(lodash.last(nodeIds));
74087 for (var i = 0; i < nodeIds.length - 1; i++) {
74088 var node = graph.entity(nodeIds[i]);
74090 /* eslint-disable no-loop-func */
74091 graph.parentWays(node).forEach(function(parent) {
74092 if (!parent.areAdjacent(node.id, survivor.id)) {
74093 graph = graph.replace(parent.replaceNode(node.id, survivor.id));
74097 graph.parentRelations(node).forEach(function(parent) {
74098 graph = graph.replace(parent.replaceMember(node, survivor));
74100 /* eslint-enable no-loop-func */
74102 survivor = survivor.mergeTags(node.tags);
74103 graph = actionDeleteNode(node.id)(graph);
74106 graph = graph.replace(survivor);
74112 function actionCopyEntities(ids, fromGraph) {
74116 var action = function(graph) {
74117 ids.forEach(function(id) {
74118 fromGraph.entity(id).copy(fromGraph, copies);
74121 for (var id in copies) {
74122 graph = graph.replace(copies[id]);
74129 action.copies = function() {
74137 function actionDeleteMember(relationId, memberIndex) {
74138 return function(graph) {
74139 var relation = graph.entity(relationId)
74140 .removeMember(memberIndex);
74142 graph = graph.replace(relation);
74144 if (relation.isDegenerate())
74145 graph = actionDeleteRelation(relation.id)(graph);
74151 function actionDeprecateTags(entityId) {
74153 return function(graph) {
74154 var entity = graph.entity(entityId),
74155 newtags = lodash.clone(entity.tags),
74159 // This handles dataDeprecated tags with a single condition
74160 for (var i = 0; i < dataDeprecated.length; i++) {
74162 rule = dataDeprecated[i];
74163 var match = lodash.toPairs(rule.old)[0],
74164 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
74166 if (entity.tags[match[0]] && match[1] === '*') {
74168 var value = entity.tags[match[0]];
74169 if (replacements && !newtags[replacements[0][0]]) {
74170 newtags[replacements[0][0]] = value;
74172 delete newtags[match[0]];
74175 } else if (entity.tags[match[0]] === match[1]) {
74176 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
74182 return graph.replace(entity.update({tags: newtags}));
74189 function actionDiscardTags(difference) {
74191 return function(graph) {
74192 function discardTags(entity) {
74193 if (!lodash.isEmpty(entity.tags)) {
74195 lodash.each(entity.tags, function(v, k) {
74196 if (v) tags[k] = v;
74199 graph = graph.replace(entity.update({
74200 tags: lodash.omit(tags, dataDiscarded)
74205 difference.modified().forEach(discardTags);
74206 difference.created().forEach(discardTags);
74212 // Disconect the ways at the given node.
74214 // Optionally, disconnect only the given ways.
74216 // For testing convenience, accepts an ID to assign to the (first) new node.
74217 // Normally, this will be undefined and the way will automatically
74218 // be assigned a new ID.
74220 // This is the inverse of `iD.actionConnect`.
74223 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
74224 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
74226 function actionDisconnect(nodeId, newNodeId) {
74230 var action = function(graph) {
74231 var node = graph.entity(nodeId),
74232 connections = action.connections(graph);
74234 connections.forEach(function(connection) {
74235 var way = graph.entity(connection.wayID),
74236 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
74238 graph = graph.replace(newNode);
74239 if (connection.index === 0 && way.isArea()) {
74240 // replace shared node with shared node..
74241 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
74242 } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
74243 // replace closing node with new new node..
74244 graph = graph.replace(way.unclose().addNode(newNode.id));
74246 // replace shared node with multiple new nodes..
74247 graph = graph.replace(way.updateNode(newNode.id, connection.index));
74255 action.connections = function(graph) {
74256 var candidates = [],
74258 parentWays = graph.parentWays(graph.entity(nodeId));
74260 parentWays.forEach(function(way) {
74261 if (wayIds && wayIds.indexOf(way.id) === -1) {
74265 if (way.isArea() && (way.nodes[0] === nodeId)) {
74266 candidates.push({ wayID: way.id, index: 0 });
74268 way.nodes.forEach(function(waynode, index) {
74269 if (waynode === nodeId) {
74270 candidates.push({ wayID: way.id, index: index });
74276 return keeping ? candidates : candidates.slice(1);
74280 action.disabled = function(graph) {
74281 var connections = action.connections(graph);
74282 if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
74283 return 'not_connected';
74285 var parentWays = graph.parentWays(graph.entity(nodeId)),
74286 seenRelationIds = {},
74289 parentWays.forEach(function(way) {
74290 if (wayIds && wayIds.indexOf(way.id) === -1)
74293 var relations = graph.parentRelations(way);
74294 relations.forEach(function(relation) {
74295 if (relation.id in seenRelationIds) {
74296 sharedRelation = relation;
74298 seenRelationIds[relation.id] = true;
74303 if (sharedRelation)
74308 action.limitWays = function(_) {
74309 if (!arguments.length) return wayIds;
74318 // Join ways at the end node they share.
74320 // This is the inverse of `iD.actionSplit`.
74323 // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
74324 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
74326 function actionJoin(ids) {
74328 function groupEntitiesByGeometry(graph) {
74329 var entities = ids.map(function(id) { return graph.entity(id); });
74330 return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
74334 var action = function(graph) {
74335 var ways = ids.map(graph.entity, graph),
74336 survivor = ways[0];
74338 // Prefer to keep an existing way.
74339 for (var i = 0; i < ways.length; i++) {
74340 if (!ways[i].isNew()) {
74341 survivor = ways[i];
74346 var joined = osmJoinWays(ways, graph)[0];
74348 survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
74349 graph = graph.replace(survivor);
74351 joined.forEach(function(way) {
74352 if (way.id === survivor.id)
74355 graph.parentRelations(way).forEach(function(parent) {
74356 graph = graph.replace(parent.replaceMember(way, survivor));
74359 survivor = survivor.mergeTags(way.tags);
74361 graph = graph.replace(survivor);
74362 graph = actionDeleteWay(way.id)(graph);
74369 action.disabled = function(graph) {
74370 var geometries = groupEntitiesByGeometry(graph);
74371 if (ids.length < 2 || ids.length !== geometries.line.length)
74372 return 'not_eligible';
74374 var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
74375 if (joined.length > 1)
74376 return 'not_adjacent';
74378 var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
74381 conflicting = false;
74383 joined[0].forEach(function(way) {
74384 var parents = graph.parentRelations(way);
74385 parents.forEach(function(parent) {
74386 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
74390 for (var k in way.tags) {
74391 if (!(k in tags)) {
74392 tags[k] = way.tags[k];
74393 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
74394 conflicting = true;
74400 return 'restriction';
74403 return 'conflicting_tags';
74410 function actionMerge(ids) {
74412 function groupEntitiesByGeometry(graph) {
74413 var entities = ids.map(function(id) { return graph.entity(id); });
74414 return lodash.extend({point: [], area: [], line: [], relation: []},
74415 lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
74419 var action = function(graph) {
74420 var geometries = groupEntitiesByGeometry(graph),
74421 target = geometries.area[0] || geometries.line[0],
74422 points = geometries.point;
74424 points.forEach(function(point) {
74425 target = target.mergeTags(point.tags);
74426 graph = graph.replace(target);
74428 graph.parentRelations(point).forEach(function(parent) {
74429 graph = graph.replace(parent.replaceMember(point, target));
74432 var nodes = lodash.uniq(graph.childNodes(target)),
74433 removeNode = point;
74435 for (var i = 0; i < nodes.length; i++) {
74436 var node = nodes[i];
74437 if (graph.parentWays(node).length > 1 ||
74438 graph.parentRelations(node).length ||
74439 node.hasInterestingTags()) {
74443 // Found an uninteresting child node on the target way.
74444 // Move orig point into its place to preserve point's history. #3683
74445 graph = graph.replace(point.update({ tags: {}, loc: node.loc }));
74446 target = target.replaceNode(node.id, point.id);
74447 graph = graph.replace(target);
74452 graph = graph.remove(removeNode);
74459 action.disabled = function(graph) {
74460 var geometries = groupEntitiesByGeometry(graph);
74461 if (geometries.point.length === 0 ||
74462 (geometries.area.length + geometries.line.length) !== 1 ||
74463 geometries.relation.length !== 0)
74464 return 'not_eligible';
74471 function actionMergePolygon(ids, newRelationId) {
74473 function groupEntities(graph) {
74474 var entities = ids.map(function (id) { return graph.entity(id); });
74475 return lodash.extend({
74479 }, lodash.groupBy(entities, function(entity) {
74480 if (entity.type === 'way' && entity.isClosed()) {
74481 return 'closedWay';
74482 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
74483 return 'multipolygon';
74491 var action = function(graph) {
74492 var entities = groupEntities(graph);
74494 // An array representing all the polygons that are part of the multipolygon.
74496 // Each element is itself an array of objects with an id property, and has a
74497 // locs property which is an array of the locations forming the polygon.
74498 var polygons = entities.multipolygon.reduce(function(polygons, m) {
74499 return polygons.concat(osmJoinWays(m.members, graph));
74500 }, []).concat(entities.closedWay.map(function(d) {
74501 var member = [{id: d.id}];
74502 member.nodes = graph.childNodes(d);
74506 // contained is an array of arrays of boolean values,
74507 // where contained[j][k] is true iff the jth way is
74508 // contained by the kth way.
74509 var contained = polygons.map(function(w, i) {
74510 return polygons.map(function(d, n) {
74511 if (i === n) return null;
74512 return geoPolygonContainsPolygon(
74513 lodash.map(d.nodes, 'loc'),
74514 lodash.map(w.nodes, 'loc'));
74518 // Sort all polygons as either outer or inner ways
74522 while (polygons.length) {
74523 extractUncontained(polygons);
74524 polygons = polygons.filter(isContained);
74525 contained = contained.filter(isContained).map(filterContained);
74528 function isContained(d, i) {
74529 return lodash.some(contained[i]);
74532 function filterContained(d) {
74533 return d.filter(isContained);
74536 function extractUncontained(polygons) {
74537 polygons.forEach(function(d, i) {
74538 if (!isContained(d, i)) {
74539 d.forEach(function(member) {
74543 role: outer ? 'outer' : 'inner'
74551 // Move all tags to one relation
74552 var relation = entities.multipolygon[0] ||
74553 osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
74555 entities.multipolygon.slice(1).forEach(function(m) {
74556 relation = relation.mergeTags(m.tags);
74557 graph = graph.remove(m);
74560 entities.closedWay.forEach(function(way) {
74561 function isThisOuter(m) {
74562 return m.id === way.id && m.role !== 'inner';
74564 if (members.some(isThisOuter)) {
74565 relation = relation.mergeTags(way.tags);
74566 graph = graph.replace(way.update({ tags: {} }));
74570 return graph.replace(relation.update({
74572 tags: lodash.omit(relation.tags, 'area')
74577 action.disabled = function(graph) {
74578 var entities = groupEntities(graph);
74579 if (entities.other.length > 0 ||
74580 entities.closedWay.length + entities.multipolygon.length < 2)
74581 return 'not_eligible';
74582 if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
74583 return 'incomplete_relation';
74590 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
74591 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
74593 // Permission is hereby granted, free of charge, to any person
74594 // obtaining a copy of this software and associated documentation files
74595 // (the "Software"), to deal in the Software without restriction,
74596 // including without limitation the rights to use, copy, modify, merge,
74597 // publish, distribute, sublicense, and/or sell copies of the Software,
74598 // and to permit persons to whom the Software is furnished to do so,
74599 // subject to the following conditions:
74601 // The above copyright notice and this permission notice shall be
74602 // included in all copies or substantial portions of the Software.
74604 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
74605 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
74606 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
74607 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
74608 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
74609 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
74610 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
74613 // source: https://bitbucket.org/lshift/synchrotron/src
74614 function longest_common_subsequence(file1, file2) {
74615 /* Text diff algorithm following Hunt and McIlroy 1976.
74616 * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
74617 * comparison, Bell Telephone Laboratories CSTR #41 (1976)
74618 * http://www.cs.dartmouth.edu/~doug/
74620 * Expects two arrays of strings.
74622 var equivalenceClasses;
74627 var c, i, j, jX, r, s;
74629 equivalenceClasses = {};
74630 for (j = 0; j < file2.length; j++) {
74632 if (equivalenceClasses[line]) {
74633 equivalenceClasses[line].push(j);
74635 equivalenceClasses[line] = [j];
74639 candidates = [{file1index: -1,
74643 for (i = 0; i < file1.length; i++) {
74645 file2indices = equivalenceClasses[line] || [];
74650 for (jX = 0; jX < file2indices.length; jX++) {
74651 j = file2indices[jX];
74653 for (s = 0; s < candidates.length; s++) {
74654 if ((candidates[s].file2index < j) &&
74655 ((s === candidates.length - 1) ||
74656 (candidates[s + 1].file2index > j)))
74660 if (s < candidates.length) {
74661 newCandidate = {file1index: i,
74663 chain: candidates[s]};
74664 if (r === candidates.length) {
74665 candidates.push(c);
74671 if (r === candidates.length) {
74672 break; // no point in examining further (j)s
74680 // At this point, we know the LCS: it's in the reverse of the
74681 // linked-list through .chain of
74682 // candidates[candidates.length - 1].
74684 return candidates[candidates.length - 1];
74697 function diff_indices(file1, file2) {
74698 // We apply the LCS to give a simple representation of the
74699 // offsets and lengths of mismatched chunks in the input
74700 // files. This is used by diff3_merge_indices below.
74703 var tail1 = file1.length;
74704 var tail2 = file2.length;
74706 for (var candidate = longest_common_subsequence(file1, file2);
74707 candidate !== null;
74708 candidate = candidate.chain)
74710 var mismatchLength1 = tail1 - candidate.file1index - 1;
74711 var mismatchLength2 = tail2 - candidate.file2index - 1;
74712 tail1 = candidate.file1index;
74713 tail2 = candidate.file2index;
74715 if (mismatchLength1 || mismatchLength2) {
74716 result.push({file1: [tail1 + 1, mismatchLength1],
74717 file2: [tail2 + 1, mismatchLength2]});
74725 function diff3_merge_indices (a, o, b) {
74726 // Given three files, A, O, and B, where both A and B are
74727 // independently derived from O, returns a fairly complicated
74728 // internal representation of merge decisions it's taken. The
74729 // interested reader may wish to consult
74731 // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
74732 // Formal Investigation of Diff3." In Arvind and Prasad,
74733 // editors, Foundations of Software Technology and Theoretical
74734 // Computer Science (FSTTCS), December 2007.
74736 // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
74739 var m1 = diff_indices(o, a);
74740 var m2 = diff_indices(o, b);
74743 function addHunk(h, side) {
74744 hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
74746 for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
74747 for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
74751 var commonOffset = 0;
74752 function copyCommon(targetOffset) {
74753 if (targetOffset > commonOffset) {
74754 result.push([1, commonOffset, targetOffset - commonOffset]);
74755 commonOffset = targetOffset;
74759 for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
74760 var firstHunkIndex = hunkIndex;
74761 var hunk = hunks[hunkIndex];
74762 var regionLhs = hunk[0];
74763 var regionRhs = regionLhs + hunk[2];
74764 while (hunkIndex < hunks.length - 1) {
74765 var maybeOverlapping = hunks[hunkIndex + 1];
74766 var maybeLhs = maybeOverlapping[0];
74767 if (maybeLhs > regionRhs) break;
74768 regionRhs = maybeLhs + maybeOverlapping[2];
74772 copyCommon(regionLhs);
74773 if (firstHunkIndex === hunkIndex) {
74774 // The "overlap" was only one hunk long, meaning that
74775 // there's no conflict here. Either a and o were the
74776 // same, or b and o were the same.
74778 result.push([hunk[1], hunk[3], hunk[4]]);
74781 // A proper conflict. Determine the extents of the
74782 // regions involved from a, o and b. Effectively merge
74783 // all the hunks on the left into one giant hunk, and
74784 // do the same for the right; then, correct for skew
74785 // in the regions of o that each side changed, and
74786 // report appropriate spans for the three sides.
74788 0: [a.length, -1, o.length, -1],
74789 2: [b.length, -1, o.length, -1]
74791 for (i = firstHunkIndex; i <= hunkIndex; i++) {
74793 var side = hunk[1];
74794 var r = regions[side];
74795 var oLhs = hunk[0];
74796 var oRhs = oLhs + hunk[2];
74797 var abLhs = hunk[3];
74798 var abRhs = abLhs + hunk[4];
74799 r[0] = Math.min(abLhs, r[0]);
74800 r[1] = Math.max(abRhs, r[1]);
74801 r[2] = Math.min(oLhs, r[2]);
74802 r[3] = Math.max(oRhs, r[3]);
74804 var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
74805 var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
74806 var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
74807 var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
74810 regionLhs, regionRhs - regionLhs,
74811 bLhs, bRhs - bLhs]);
74813 commonOffset = regionRhs;
74816 copyCommon(o.length);
74820 function diff3_merge (a, o, b, excludeFalseConflicts) {
74821 // Applies the output of Diff3.diff3_merge_indices to actually
74822 // construct the merged file; the returned result alternates
74823 // between "ok" and "conflict" blocks.
74826 var files = [a, o, b];
74827 var indices = diff3_merge_indices(a, o, b);
74830 function flushOk() {
74831 if (okLines.length) {
74832 result.push({ok: okLines});
74836 function pushOk(xs) {
74837 for (var j = 0; j < xs.length; j++) {
74838 okLines.push(xs[j]);
74842 function isTrueConflict(rec) {
74843 if (rec[2] !== rec[6]) return true;
74846 for (var j = 0; j < rec[2]; j++) {
74847 if (a[j + aoff] !== b[j + boff]) return true;
74852 for (var i = 0; i < indices.length; i++) {
74853 var x = indices[i];
74856 if (excludeFalseConflicts && !isTrueConflict(x)) {
74857 pushOk(files[0].slice(x[1], x[1] + x[2]));
74860 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
74862 o: o.slice(x[3], x[3] + x[4]),
74864 b: b.slice(x[5], x[5] + x[6]),
74868 pushOk(files[side].slice(x[1], x[1] + x[2]));
74876 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
74877 var option = 'safe', // 'safe', 'force_local', 'force_remote'
74882 return lodash.isFunction(formatUser) ? formatUser(d) : d;
74886 function mergeLocation(remote, target) {
74887 function pointEqual(a, b) {
74888 var epsilon = 1e-6;
74889 return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
74892 if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
74895 if (option === 'force_remote') {
74896 return target.update({loc: remote.loc});
74899 conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
74904 function mergeNodes(base, remote, target) {
74905 if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
74908 if (option === 'force_remote') {
74909 return target.update({nodes: remote.nodes});
74912 var ccount = conflicts.length,
74913 o = base.nodes || [],
74914 a = target.nodes || [],
74915 b = remote.nodes || [],
74917 hunks = diff3_merge(a, o, b, true);
74919 for (var i = 0; i < hunks.length; i++) {
74920 var hunk = hunks[i];
74922 nodes.push.apply(nodes, hunk.ok);
74924 // for all conflicts, we can assume c.a !== c.b
74925 // because `diff3_merge` called with `true` option to exclude false conflicts..
74926 var c = hunk.conflict;
74927 if (lodash.isEqual(c.o, c.a)) { // only changed remotely
74928 nodes.push.apply(nodes, c.b);
74929 } else if (lodash.isEqual(c.o, c.b)) { // only changed locally
74930 nodes.push.apply(nodes, c.a);
74931 } else { // changed both locally and remotely
74932 conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
74938 return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
74942 function mergeChildren(targetWay, children, updates, graph) {
74943 function isUsed(node, targetWay) {
74944 var parentWays = lodash.map(graph.parentWays(node), 'id');
74945 return node.hasInterestingTags() ||
74946 lodash.without(parentWays, targetWay.id).length > 0 ||
74947 graph.parentRelations(node).length > 0;
74950 var ccount = conflicts.length;
74952 for (var i = 0; i < children.length; i++) {
74953 var id = children[i],
74954 node = graph.hasEntity(id);
74956 // remove unused childNodes..
74957 if (targetWay.nodes.indexOf(id) === -1) {
74958 if (node && !isUsed(node, targetWay)) {
74959 updates.removeIds.push(id);
74964 // restore used childNodes..
74965 var local = localGraph.hasEntity(id),
74966 remote = remoteGraph.hasEntity(id),
74969 if (option === 'force_remote' && remote && remote.visible) {
74970 updates.replacements.push(remote);
74972 } else if (option === 'force_local' && local) {
74973 target = osmEntity$$1(local);
74975 target = target.update({ version: remote.version });
74977 updates.replacements.push(target);
74979 } else if (option === 'safe' && local && remote && local.version !== remote.version) {
74980 target = osmEntity$$1(local, { version: remote.version });
74981 if (remote.visible) {
74982 target = mergeLocation(remote, target);
74984 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
74987 if (conflicts.length !== ccount) break;
74988 updates.replacements.push(target);
74996 function updateChildren(updates, graph) {
74997 for (var i = 0; i < updates.replacements.length; i++) {
74998 graph = graph.replace(updates.replacements[i]);
75000 if (updates.removeIds.length) {
75001 graph = actionDeleteMultiple(updates.removeIds)(graph);
75007 function mergeMembers(remote, target) {
75008 if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
75011 if (option === 'force_remote') {
75012 return target.update({members: remote.members});
75015 conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
75020 function mergeTags(base, remote, target) {
75021 function ignoreKey(k) {
75022 return lodash.includes(dataDiscarded, k);
75025 if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
75028 if (option === 'force_remote') {
75029 return target.update({tags: remote.tags});
75032 var ccount = conflicts.length,
75033 o = base.tags || {},
75034 a = target.tags || {},
75035 b = remote.tags || {},
75036 keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
75037 tags = lodash.clone(a),
75040 for (var i = 0; i < keys.length; i++) {
75043 if (o[k] !== b[k] && a[k] !== b[k]) { // changed remotely..
75044 if (o[k] !== a[k]) { // changed locally..
75045 conflicts.push(t('merge_remote_changes.conflict.tags',
75046 { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
75048 } else { // unchanged locally, accept remote change..
75049 if (b.hasOwnProperty(k)) {
75059 return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
75063 // `graph.base()` is the common ancestor of the two graphs.
75064 // `localGraph` contains user's edits up to saving
75065 // `remoteGraph` contains remote edits to modified nodes
75066 // `graph` must be a descendent of `localGraph` and may include
75067 // some conflict resolution actions performed on it.
75069 // --- ... --- `localGraph` -- ... -- `graph`
75071 // `graph.base()` --- ... --- `remoteGraph`
75073 var action = function(graph) {
75074 var updates = { replacements: [], removeIds: [] },
75075 base = graph.base().entities[id],
75076 local = localGraph.entity(id),
75077 remote = remoteGraph.entity(id),
75078 target = osmEntity$$1(local, { version: remote.version });
75081 if (!remote.visible) {
75082 if (option === 'force_remote') {
75083 return actionDeleteMultiple([id])(graph);
75085 } else if (option === 'force_local') {
75086 if (target.type === 'way') {
75087 target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
75088 graph = updateChildren(updates, graph);
75090 return graph.replace(target);
75093 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
75094 return graph; // do nothing
75099 if (target.type === 'node') {
75100 target = mergeLocation(remote, target);
75102 } else if (target.type === 'way') {
75103 // pull in any child nodes that may not be present locally..
75104 graph.rebase(remoteGraph.childNodes(remote), [graph], false);
75105 target = mergeNodes(base, remote, target);
75106 target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
75108 } else if (target.type === 'relation') {
75109 target = mergeMembers(remote, target);
75112 target = mergeTags(base, remote, target);
75114 if (!conflicts.length) {
75115 graph = updateChildren(updates, graph).replace(target);
75122 action.withOption = function(opt) {
75128 action.conflicts = function() {
75136 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
75137 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
75138 function actionMove(moveIds, tryDelta, projection, cache) {
75139 var delta = tryDelta;
75141 function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
75142 function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
75144 function setupCache(graph) {
75145 function canMove(nodeId) {
75146 // Allow movement of any node that is in the selectedIDs list..
75147 if (moveIds.indexOf(nodeId) !== -1) return true;
75149 // Allow movement of a vertex where 2 ways meet..
75150 var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
75151 if (parents.length < 3) return true;
75153 // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
75154 var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
75155 if (!parentsMoving) delete cache.moving[nodeId];
75157 return parentsMoving;
75160 function cacheEntities(ids) {
75161 ids.forEach(function(id) {
75162 if (cache.moving[id]) return;
75163 cache.moving[id] = true;
75165 var entity = graph.hasEntity(id);
75166 if (!entity) return;
75168 if (entity.type === 'node') {
75169 cache.nodes.push(id);
75170 cache.startLoc[id] = entity.loc;
75171 } else if (entity.type === 'way') {
75172 cache.ways.push(id);
75173 cacheEntities(entity.nodes);
75175 cacheEntities(entity.members.map(function(member) {
75182 function cacheIntersections(ids) {
75183 function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
75185 ids.forEach(function(id) {
75186 // consider only intersections with 1 moved and 1 unmoved way.
75187 var childNodes = graph.childNodes(graph.entity(id));
75188 childNodes.forEach(function(node) {
75189 var parents = graph.parentWays(node);
75190 if (parents.length !== 2) return;
75192 var moved = graph.entity(id),
75193 unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
75194 if (!unmoved) return;
75196 // exclude ways that are overly connected..
75197 if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
75199 if (moved.isArea() || unmoved.isArea()) return;
75201 cache.intersection[node.id] = {
75204 unmovedId: unmoved.id,
75205 movedIsEP: isEndpoint(moved, node.id),
75206 unmovedIsEP: isEndpoint(unmoved, node.id)
75218 cache.intersection = {};
75219 cache.replacedVertex = {};
75220 cache.startLoc = {};
75224 cacheEntities(moveIds);
75225 cacheIntersections(cache.ways);
75226 cache.nodes = lodash.filter(cache.nodes, canMove);
75233 // Place a vertex where the moved vertex used to be, to preserve way shape..
75234 function replaceMovedVertex(nodeId, wayId, graph, delta) {
75235 var way = graph.entity(wayId),
75236 moved = graph.entity(nodeId),
75237 movedIndex = way.nodes.indexOf(nodeId),
75238 len, prevIndex, nextIndex;
75240 if (way.isClosed()) {
75241 len = way.nodes.length - 1;
75242 prevIndex = (movedIndex + len - 1) % len;
75243 nextIndex = (movedIndex + len + 1) % len;
75245 len = way.nodes.length;
75246 prevIndex = movedIndex - 1;
75247 nextIndex = movedIndex + 1;
75250 var prev = graph.hasEntity(way.nodes[prevIndex]),
75251 next = graph.hasEntity(way.nodes[nextIndex]);
75253 // Don't add orig vertex at endpoint..
75254 if (!prev || !next) return graph;
75256 var key = wayId + '_' + nodeId,
75257 orig = cache.replacedVertex[key];
75260 cache.replacedVertex[key] = orig;
75261 cache.startLoc[orig.id] = cache.startLoc[nodeId];
75266 start = projection(cache.startLoc[nodeId]);
75267 end = projection.invert(vecAdd(start, delta));
75269 end = cache.startLoc[nodeId];
75271 orig = orig.move(end);
75273 var angle = Math.abs(geoAngle(orig, prev, projection) -
75274 geoAngle(orig, next, projection)) * 180 / Math.PI;
75276 // Don't add orig vertex if it would just make a straight line..
75277 if (angle > 175 && angle < 185) return graph;
75279 // Don't add orig vertex if another point is already nearby (within 10m)
75280 if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
75281 geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
75283 // moving forward or backward along way?
75284 var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
75285 p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
75286 d1 = geoPathLength(p1),
75287 d2 = geoPathLength(p2),
75288 insertAt = (d1 < d2) ? movedIndex : nextIndex;
75290 // moving around closed loop?
75291 if (way.isClosed() && insertAt === 0) insertAt = len;
75293 way = way.addNode(orig.id, insertAt);
75294 return graph.replace(orig).replace(way);
75298 // Reorder nodes around intersections that have moved..
75299 function unZorroIntersection(intersection, graph) {
75300 var vertex = graph.entity(intersection.nodeId),
75301 way1 = graph.entity(intersection.movedId),
75302 way2 = graph.entity(intersection.unmovedId),
75303 isEP1 = intersection.movedIsEP,
75304 isEP2 = intersection.unmovedIsEP;
75306 // don't move the vertex if it is the endpoint of both ways.
75307 if (isEP1 && isEP2) return graph;
75309 var nodes1 = lodash.without(graph.childNodes(way1), vertex),
75310 nodes2 = lodash.without(graph.childNodes(way2), vertex);
75312 if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
75313 if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
75315 var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
75316 edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
75319 // snap vertex to nearest edge (or some point between them)..
75320 if (!isEP1 && !isEP2) {
75321 var epsilon = 1e-4, maxIter = 10;
75322 for (var i = 0; i < maxIter; i++) {
75323 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
75324 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
75325 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
75326 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
75328 } else if (!isEP1) {
75334 graph = graph.replace(vertex.move(loc));
75336 // if zorro happened, reorder nodes..
75337 if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
75338 way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
75339 graph = graph.replace(way1);
75341 if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
75342 way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
75343 graph = graph.replace(way2);
75350 function cleanupIntersections(graph) {
75351 lodash.each(cache.intersection, function(obj) {
75352 graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
75353 graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
75354 graph = unZorroIntersection(obj, graph);
75361 // check if moving way endpoint can cross an unmoved way, if so limit delta..
75362 function limitDelta(graph) {
75363 lodash.each(cache.intersection, function(obj) {
75364 // Don't limit movement if this is vertex joins 2 endpoints..
75365 if (obj.movedIsEP && obj.unmovedIsEP) return;
75366 // Don't limit movement if this vertex is not an endpoint anyway..
75367 if (!obj.movedIsEP) return;
75369 var node = graph.entity(obj.nodeId),
75370 start = projection(node.loc),
75371 end = vecAdd(start, delta),
75372 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
75373 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
75374 function(loc) { return vecAdd(projection(loc), delta); }),
75375 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
75376 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
75377 hits = geoPathIntersections(movedPath, unmovedPath);
75379 for (var i = 0; i < hits.length; i++) {
75380 if (lodash.isEqual(hits[i], end)) continue;
75381 var edge = geoChooseEdge(unmovedNodes, end, projection);
75382 delta = vecSub(projection(edge.loc), start);
75388 var action = function(graph) {
75389 if (delta[0] === 0 && delta[1] === 0) return graph;
75393 if (!lodash.isEmpty(cache.intersection)) {
75397 lodash.each(cache.nodes, function(id) {
75398 var node = graph.entity(id),
75399 start = projection(node.loc),
75400 end = vecAdd(start, delta);
75401 graph = graph.replace(node.move(projection.invert(end)));
75404 if (!lodash.isEmpty(cache.intersection)) {
75405 graph = cleanupIntersections(graph);
75412 action.delta = function() {
75420 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
75421 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
75422 function actionMoveNode(nodeId, loc) {
75423 return function(graph) {
75424 return graph.replace(graph.entity(nodeId).move(loc));
75428 function actionNoop() {
75429 return function(graph) {
75435 * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
75437 function actionOrthogonalize(wayId, projection) {
75438 var threshold = 12, // degrees within right or straight to alter
75439 lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
75440 upperThreshold = Math.cos(threshold * Math.PI / 180);
75443 var action = function(graph, t) {
75444 if (t === null || !isFinite(t)) t = 1;
75445 t = Math.min(Math.max(+t, 0), 1);
75447 var way = graph.entity(wayId),
75448 nodes = graph.childNodes(way),
75449 points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
75450 corner = {i: 0, dotp: 1},
75452 node, loc, score, motions, i, j;
75454 if (points.length === 3) { // move only one vertex for right triangle
75455 for (i = 0; i < 1000; i++) {
75456 motions = points.map(calcMotion);
75457 points[corner.i] = addPoints(points[corner.i], motions[corner.i]);
75458 score = corner.dotp;
75459 if (score < epsilon) {
75464 node = graph.entity(nodes[corner.i].id);
75465 loc = projection.invert(points[corner.i]);
75466 graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
75470 originalPoints = lodash.clone(points);
75473 for (i = 0; i < 1000; i++) {
75474 motions = points.map(calcMotion);
75475 for (j = 0; j < motions.length; j++) {
75476 points[j] = addPoints(points[j],motions[j]);
75478 var newScore = squareness(points);
75479 if (newScore < score) {
75480 best = lodash.clone(points);
75483 if (score < epsilon) {
75490 for (i = 0; i < points.length; i++) {
75491 // only move the points that actually moved
75492 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
75493 loc = projection.invert(points[i]);
75494 node = graph.entity(nodes[i].id);
75495 graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
75499 // remove empty nodes on straight sections
75500 for (i = 0; t === 1 && i < points.length; i++) {
75501 node = graph.entity(nodes[i].id);
75503 if (graph.parentWays(node).length > 1 ||
75504 graph.parentRelations(node).length ||
75505 node.hasInterestingTags()) {
75509 var dotp = normalizedDotProduct(i, points);
75510 if (dotp < -1 + epsilon) {
75511 graph = actionDeleteNode(node.id)(graph);
75519 function calcMotion(b, i, array) {
75520 var a = array[(i - 1 + array.length) % array.length],
75521 c = array[(i + 1) % array.length],
75522 p = subtractPoints(a, b),
75523 q = subtractPoints(c, b),
75526 scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
75527 p = normalizePoint(p, 1.0);
75528 q = normalizePoint(q, 1.0);
75530 dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
75532 // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
75533 if (array.length > 3) {
75534 if (dotp < -0.707106781186547) {
75537 } else if (dotp && Math.abs(dotp) < corner.dotp) {
75539 corner.dotp = Math.abs(dotp);
75542 return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
75547 function squareness(points) {
75548 return points.reduce(function(sum, val, i, array) {
75549 var dotp = normalizedDotProduct(i, array);
75551 dotp = filterDotProduct(dotp);
75552 return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
75557 function normalizedDotProduct(i, points) {
75558 var a = points[(i - 1 + points.length) % points.length],
75560 c = points[(i + 1) % points.length],
75561 p = subtractPoints(a, b),
75562 q = subtractPoints(c, b);
75564 p = normalizePoint(p, 1.0);
75565 q = normalizePoint(q, 1.0);
75567 return p[0] * q[0] + p[1] * q[1];
75571 function subtractPoints(a, b) {
75572 return [a[0] - b[0], a[1] - b[1]];
75576 function addPoints(a, b) {
75577 return [a[0] + b[0], a[1] + b[1]];
75581 function normalizePoint(point, scale) {
75582 var vector = [0, 0];
75583 var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
75584 if (length !== 0) {
75585 vector[0] = point[0] / length;
75586 vector[1] = point[1] / length;
75589 vector[0] *= scale;
75590 vector[1] *= scale;
75596 function filterDotProduct(dotp) {
75597 if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
75605 action.disabled = function(graph) {
75606 var way = graph.entity(wayId),
75607 nodes = graph.childNodes(way),
75608 points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
75610 if (squareness(points)) {
75614 return 'not_squarish';
75618 action.transitionable = true;
75624 // Split a way at the given node.
75626 // Optionally, split only the given ways, if multiple ways share
75629 // This is the inverse of `iD.actionJoin`.
75631 // For testing convenience, accepts an ID to assign to the new way.
75632 // Normally, this will be undefined and the way will automatically
75633 // be assigned a new ID.
75636 // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
75638 function actionSplit(nodeId, newWayIds) {
75641 // if the way is closed, we need to search for a partner node
75642 // to split the way at.
75644 // The following looks for a node that is both far away from
75645 // the initial node in terms of way segment length and nearby
75646 // in terms of beeline-distance. This assures that areas get
75647 // split on the most "natural" points (independent of the number
75649 // For example: bone-shaped areas get split across their waist
75650 // line, circles across the diameter.
75651 function splitArea(nodes, idxA, graph) {
75652 var lengths = new Array(nodes.length),
75658 function wrap(index) {
75659 return utilWrap(index, nodes.length);
75662 function dist(nA, nB) {
75663 return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
75666 // calculate lengths
75668 for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
75669 length += dist(nodes[i], nodes[wrap(i-1)]);
75670 lengths[i] = length;
75674 for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
75675 length += dist(nodes[i], nodes[wrap(i+1)]);
75676 if (length < lengths[i])
75677 lengths[i] = length;
75680 // determine best opposite node to split
75681 for (i = 0; i < nodes.length; i++) {
75682 var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
75693 function split(graph, wayA, newWayId) {
75694 var wayB = osmWay({id: newWayId, tags: wayA.tags}),
75697 isArea = wayA.isArea(),
75698 isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
75700 if (wayA.isClosed()) {
75701 var nodes = wayA.nodes.slice(0, -1),
75702 idxA = lodash.indexOf(nodes, nodeId),
75703 idxB = splitArea(nodes, idxA, graph);
75706 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
75707 nodesB = nodes.slice(idxB, idxA + 1);
75709 nodesA = nodes.slice(idxA, idxB + 1);
75710 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
75713 var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
75714 nodesA = wayA.nodes.slice(0, idx + 1);
75715 nodesB = wayA.nodes.slice(idx);
75718 wayA = wayA.update({nodes: nodesA});
75719 wayB = wayB.update({nodes: nodesB});
75721 graph = graph.replace(wayA);
75722 graph = graph.replace(wayB);
75724 graph.parentRelations(wayA).forEach(function(relation) {
75725 if (relation.isRestriction()) {
75726 var via = relation.memberByRole('via');
75727 if (via && wayB.contains(via.id)) {
75728 relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
75729 graph = graph.replace(relation);
75732 if (relation === isOuter) {
75733 graph = graph.replace(relation.mergeTags(wayA.tags));
75734 graph = graph.replace(wayA.update({tags: {}}));
75735 graph = graph.replace(wayB.update({tags: {}}));
75741 role: relation.memberById(wayA.id).role
75744 graph = actionAddMember(relation.id, member)(graph);
75748 if (!isOuter && isArea) {
75749 var multipolygon = osmRelation({
75750 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
75752 {id: wayA.id, role: 'outer', type: 'way'},
75753 {id: wayB.id, role: 'outer', type: 'way'}
75756 graph = graph.replace(multipolygon);
75757 graph = graph.replace(wayA.update({tags: {}}));
75758 graph = graph.replace(wayB.update({tags: {}}));
75765 var action = function(graph) {
75766 var candidates = action.ways(graph);
75767 for (var i = 0; i < candidates.length; i++) {
75768 graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
75774 action.ways = function(graph) {
75775 var node = graph.entity(nodeId),
75776 parents = graph.parentWays(node),
75777 hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
75779 return parents.filter(function(parent) {
75780 if (wayIds && wayIds.indexOf(parent.id) === -1)
75783 if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
75786 if (parent.isClosed()) {
75790 for (var i = 1; i < parent.nodes.length - 1; i++) {
75791 if (parent.nodes[i] === nodeId) {
75801 action.disabled = function(graph) {
75802 var candidates = action.ways(graph);
75803 if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
75804 return 'not_eligible';
75808 action.limitWays = function(_) {
75809 if (!arguments.length) return wayIds;
75818 // Create a restriction relation for `turn`, which must have the following structure:
75821 // from: { node: <node ID>, way: <way ID> },
75822 // via: { node: <node ID> },
75823 // to: { node: <node ID>, way: <way ID> },
75824 // restriction: <'no_right_turn', 'no_left_turn', etc.>
75827 // This specifies a restriction of type `restriction` when traveling from
75828 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
75829 // (The action does not check that these entities form a valid intersection.)
75831 // If `restriction` is not provided, it is automatically determined by
75832 // osmInferRestriction.
75834 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
75835 // and `to.node` are used to determine which portion of the split ways become
75836 // members of the restriction.
75838 // For testing convenience, accepts an ID to assign to the new relation.
75839 // Normally, this will be undefined and the relation will automatically
75840 // be assigned a new ID.
75842 function actionRestrictTurn(turn, projection, restrictionId) {
75844 return function(graph) {
75845 var from = graph.entity(turn.from.way),
75846 via = graph.entity(turn.via.node),
75847 to = graph.entity(turn.to.way);
75849 function isClosingNode(way, nodeId) {
75850 return nodeId === way.first() && nodeId === way.last();
75853 function split(toOrFrom) {
75854 var newID = toOrFrom.newID || osmWay().id;
75855 graph = actionSplit(via.id, [newID])
75856 .limitWays([toOrFrom.way])(graph);
75858 var a = graph.entity(newID),
75859 b = graph.entity(toOrFrom.way);
75861 if (a.nodes.indexOf(toOrFrom.node) !== -1) {
75868 if (!from.affix(via.id) || isClosingNode(from, via.id)) {
75869 if (turn.from.node === turn.to.node) {
75871 from = to = split(turn.from)[0];
75872 } else if (turn.from.way === turn.to.way) {
75873 // Straight-on or circular
75874 var s = split(turn.from);
75879 from = split(turn.from)[0];
75883 if (!to.affix(via.id) || isClosingNode(to, via.id)) {
75884 to = split(turn.to)[0];
75887 return graph.replace(osmRelation({
75890 type: 'restriction',
75891 restriction: turn.restriction ||
75892 osmInferRestriction(
75900 {id: from.id, type: 'way', role: 'from'},
75901 {id: via.id, type: 'node', role: 'via'},
75902 {id: to.id, type: 'way', role: 'to'}
75908 function actionRevert(id) {
75909 var action = function(graph) {
75910 var entity = graph.hasEntity(id),
75911 base = graph.base().entities[id];
75913 if (entity && !base) { // entity will be removed..
75914 if (entity.type === 'node') {
75915 graph.parentWays(entity)
75916 .forEach(function(parent) {
75917 parent = parent.removeNode(id);
75918 graph = graph.replace(parent);
75920 if (parent.isDegenerate()) {
75921 graph = actionDeleteWay(parent.id)(graph);
75926 graph.parentRelations(entity)
75927 .forEach(function(parent) {
75928 parent = parent.removeMembersWithID(id);
75929 graph = graph.replace(parent);
75931 if (parent.isDegenerate()) {
75932 graph = actionDeleteRelation(parent.id)(graph);
75937 return graph.revert(id);
75943 function actionRotate(rotateIds, pivot, angle, projection) {
75945 var action = function(graph) {
75946 return graph.update(function(graph) {
75947 utilGetAllNodes(rotateIds, graph).forEach(function(node) {
75948 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
75949 graph = graph.replace(node.move(projection.invert(point)));
75958 * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
75960 function actionStraighten(wayId, projection) {
75962 function positionAlongWay(n, s, e) {
75963 return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) /
75964 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
75968 var action = function(graph, t) {
75969 if (t === null || !isFinite(t)) t = 1;
75970 t = Math.min(Math.max(+t, 0), 1);
75972 var way = graph.entity(wayId),
75973 nodes = graph.childNodes(way),
75974 points = nodes.map(function(n) { return projection(n.loc); }),
75975 startPoint = points[0],
75976 endPoint = points[points.length-1],
75980 for (i = 1; i < points.length-1; i++) {
75981 var node = nodes[i],
75984 if (t < 1 || graph.parentWays(node).length > 1 ||
75985 graph.parentRelations(node).length ||
75986 node.hasInterestingTags()) {
75988 var u = positionAlongWay(point, startPoint, endPoint),
75990 startPoint[0] + u * (endPoint[0] - startPoint[0]),
75991 startPoint[1] + u * (endPoint[1] - startPoint[1])
75993 loc2 = projection.invert(p);
75995 graph = graph.replace(node.move(geoInterp(node.loc, loc2, t)));
75999 if (toDelete.indexOf(node) === -1) {
76000 toDelete.push(node);
76005 for (i = 0; i < toDelete.length; i++) {
76006 graph = actionDeleteNode(toDelete[i].id)(graph);
76013 action.disabled = function(graph) {
76014 // check way isn't too bendy
76015 var way = graph.entity(wayId),
76016 nodes = graph.childNodes(way),
76017 points = nodes.map(function(n) { return projection(n.loc); }),
76018 startPoint = points[0],
76019 endPoint = points[points.length-1],
76020 threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
76023 if (threshold === 0) {
76024 return 'too_bendy';
76027 for (i = 1; i < points.length-1; i++) {
76028 var point = points[i],
76029 u = positionAlongWay(point, startPoint, endPoint),
76030 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
76031 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
76032 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
76034 // to bendy if point is off by 20% of total start/end distance in projected space
76035 if (isNaN(dist) || dist > threshold) {
76036 return 'too_bendy';
76042 action.transitionable = true;
76048 // Remove the effects of `turn.restriction` on `turn`, which must have the
76049 // following structure:
76052 // from: { node: <node ID>, way: <way ID> },
76053 // via: { node: <node ID> },
76054 // to: { node: <node ID>, way: <way ID> },
76055 // restriction: <relation ID>
76058 // In the simple case, `restriction` is a reference to a `no_*` restriction
76059 // on the turn itself. In this case, it is simply deleted.
76061 // The more complex case is where `restriction` references an `only_*`
76062 // restriction on a different turn in the same intersection. In that case,
76063 // that restriction is also deleted, but at the same time restrictions on
76064 // the turns other than the first two are created.
76066 function actionUnrestrictTurn(turn) {
76067 return function(graph) {
76068 return actionDeleteRelation(turn.restriction)(graph);
76072 /* Reflect the given area around its axis of symmetry */
76073 function actionReflect(reflectIds, projection) {
76074 var useLongAxis = true;
76077 // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
76078 // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
76079 function getSmallestSurroundingRectangle(graph, nodes) {
76080 var points = nodes.map(function(n) { return projection(n.loc); }),
76081 hull = d3polygonHull(points),
76082 centroid = d3polygonCentroid(hull),
76083 minArea = Infinity,
76088 for (var i = 0; i < hull.length - 1; i++) {
76089 var c2 = hull[i + 1],
76090 angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]),
76091 poly = geoRotate(hull, -angle, centroid),
76092 extent$$1 = poly.reduce(function(extent$$1, point) {
76093 return extent$$1.extend(geoExtent$$1(point));
76094 }, geoExtent$$1()),
76095 area$$1 = extent$$1.area();
76097 if (area$$1 < minArea) {
76099 ssrExtent = extent$$1;
76106 poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
76112 var action = function(graph, t) {
76113 if (t === null || !isFinite(t)) t = 1;
76114 t = Math.min(Math.max(+t, 0), 1);
76116 var nodes = utilGetAllNodes(reflectIds, graph),
76117 ssr = getSmallestSurroundingRectangle(graph, nodes);
76119 // Choose line pq = axis of symmetry.
76120 // The shape's surrounding rectangle has 2 axes of symmetry.
76121 // Reflect across the longer axis by default.
76122 var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2 ],
76123 q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2 ],
76124 p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2 ],
76125 q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ],
76128 var isLong = (geoEuclideanDistance(p1, q1) > geoEuclideanDistance(p2, q2));
76129 if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) {
76137 // reflect c across pq
76138 // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
76139 var dx = q[0] - p[0];
76140 var dy = q[1] - p[1];
76141 var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
76142 var b = 2 * dx * dy / (dx * dx + dy * dy);
76143 for (var i = 0; i < nodes.length; i++) {
76144 var node = nodes[i];
76145 var c = projection(node.loc);
76147 a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0],
76148 b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]
76150 var loc2 = projection.invert(c2);
76151 node = node.move(geoInterp(node.loc, loc2, t));
76152 graph = graph.replace(node);
76159 action.useLongAxis = function(_) {
76160 if (!arguments.length) return useLongAxis;
76166 action.transitionable = true;
76174 var index$17 = Object.freeze({
76175 d3combobox: d3combobox,
76176 d3geoTile: d3geoTile,
76177 d3keybinding: d3keybinding
76180 /* export some legacy symbols: */
76181 var Connection = services.osm;
76187 var iD = Object.freeze({
76188 Connection: Connection,
76193 Context: coreContext,
76194 setAreaKeys: setAreaKeys,
76195 Difference: coreDifference,
76196 Graph: coreGraph$$1,
76197 History: coreHistory,
76199 Entity: osmEntity$$1,
76201 Relation: osmRelation,
76203 BackgroundSource: rendererBackgroundSource,
76204 Background: rendererBackground,
76205 Features: rendererFeatures,
76207 TileLayer: rendererTileLayer,
76208 Detect: utilDetect,
76209 actionAddEntity: actionAddEntity,
76210 actionAddMember: actionAddMember,
76211 actionAddMidpoint: actionAddMidpoint,
76212 actionAddVertex: actionAddVertex,
76213 actionChangeMember: actionChangeMember,
76214 actionChangePreset: actionChangePreset,
76215 actionChangeTags: actionChangeTags,
76216 actionCircularize: actionCircularize,
76217 actionConnect: actionConnect,
76218 actionCopyEntities: actionCopyEntities,
76219 actionDeleteMember: actionDeleteMember,
76220 actionDeleteMultiple: actionDeleteMultiple,
76221 actionDeleteNode: actionDeleteNode,
76222 actionDeleteRelation: actionDeleteRelation,
76223 actionDeleteWay: actionDeleteWay,
76224 actionDeprecateTags: actionDeprecateTags,
76225 actionDiscardTags: actionDiscardTags,
76226 actionDisconnect: actionDisconnect,
76227 actionJoin: actionJoin,
76228 actionMerge: actionMerge,
76229 actionMergePolygon: actionMergePolygon,
76230 actionMergeRemoteChanges: actionMergeRemoteChanges,
76231 actionMove: actionMove,
76232 actionMoveNode: actionMoveNode,
76233 actionNoop: actionNoop,
76234 actionOrthogonalize: actionOrthogonalize,
76235 actionRestrictTurn: actionRestrictTurn,
76236 actionReverse: actionReverse,
76237 actionRevert: actionRevert,
76238 actionRotate: actionRotate,
76239 actionSplit: actionSplit,
76240 actionStraighten: actionStraighten,
76241 actionUnrestrictTurn: actionUnrestrictTurn,
76242 actionReflect: actionReflect,
76243 behaviorAddWay: behaviorAddWay,
76244 behaviorBreathe: behaviorBreathe,
76245 behaviorCopy: behaviorCopy,
76246 behaviorDrag: behaviorDrag,
76247 behaviorDrawWay: behaviorDrawWay,
76248 behaviorDraw: behaviorDraw,
76249 behaviorEdit: behaviorEdit,
76250 behaviorHash: behaviorHash,
76251 behaviorHover: behaviorHover,
76252 behaviorLasso: behaviorLasso,
76253 behaviorOperation: behaviorOperation,
76254 behaviorPaste: behaviorPaste,
76255 behaviorSelect: behaviorSelect,
76256 behaviorTail: behaviorTail,
76257 coreContext: coreContext,
76258 coreDifference: coreDifference,
76259 coreGraph: coreGraph$$1,
76260 coreHistory: coreHistory,
76261 coreTree: coreTree,
76262 dataFeatureIcons: dataFeatureIcons,
76264 dataWikipedia: dataWikipedia,
76265 dataSuggestions: dataSuggestions,
76266 dataAddressFormats: dataAddressFormats,
76267 dataDeprecated: dataDeprecated,
76268 dataDiscarded: dataDiscarded,
76269 dataLocales: dataLocales,
76270 dataPhoneFormats: dataPhoneFormats,
76271 dataImperial: dataImperial,
76272 dataDriveLeft: dataDriveLeft,
76274 geoAngle: geoAngle,
76275 geoChooseEdge: geoChooseEdge,
76276 geoCross: geoCross,
76277 geoEdgeEqual: geoEdgeEqual,
76278 geoEuclideanDistance: geoEuclideanDistance,
76279 geoExtent: geoExtent$$1,
76280 geoInterp: geoInterp,
76281 geoRawMercator: geoRawMercator,
76282 geoRoundCoords: geoRoundCoords,
76283 geoRotate: geoRotate,
76284 geoLatToMeters: geoLatToMeters,
76285 geoLineIntersection: geoLineIntersection,
76286 geoLonToMeters: geoLonToMeters,
76287 geoMetersToLat: geoMetersToLat,
76288 geoMetersToLon: geoMetersToLon,
76289 geoMetersToOffset: geoMetersToOffset,
76290 geoOffsetToMeters: geoOffsetToMeters,
76291 geoPathIntersections: geoPathIntersections,
76292 geoPathLength: geoPathLength,
76293 geoPointInPolygon: geoPointInPolygon,
76294 geoPolygonContainsPolygon: geoPolygonContainsPolygon,
76295 geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
76296 geoSphericalDistance: geoSphericalDistance,
76297 modeAddArea: modeAddArea$$1,
76298 modeAddLine: modeAddLine$$1,
76299 modeAddPoint: modeAddPoint$$1,
76300 modeBrowse: modeBrowse,
76301 modeDragNode: modeDragNode$$1,
76302 modeDrawArea: modeDrawArea,
76303 modeDrawLine: modeDrawLine,
76304 modeMove: modeMove$$1,
76305 modeRotate: modeRotate$$1,
76306 modeSave: modeSave$$1,
76307 modeSelect: modeSelect,
76308 operationCircularize: operationCircularize,
76309 operationContinue: operationContinue,
76310 operationDelete: operationDelete,
76311 operationDisconnect: operationDisconnect,
76312 operationMerge: operationMerge,
76313 operationMove: operationMove,
76314 operationOrthogonalize: operationOrthogonalize,
76315 operationReflectShort: operationReflectShort,
76316 operationReflectLong: operationReflectLong,
76317 operationReverse: operationReverse,
76318 operationRotate: operationRotate,
76319 operationSplit: operationSplit,
76320 operationStraighten: operationStraighten,
76321 osmChangeset: osmChangeset,
76322 osmEntity: osmEntity$$1,
76324 osmRelation: osmRelation,
76326 osmIntersection: osmIntersection,
76328 osmInferRestriction: osmInferRestriction,
76329 osmLanes: osmLanes,
76330 osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
76331 osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
76332 osmJoinWays: osmJoinWays,
76333 osmOneWayTags: osmOneWayTags,
76334 osmPavedTags: osmPavedTags,
76335 osmIsInterestingTag: osmIsInterestingTag,
76336 presetCategory: presetCategory,
76337 presetCollection: presetCollection,
76338 presetField: presetField,
76339 presetPreset: presetPreset,
76340 presetIndex: presetIndex,
76341 rendererBackgroundSource: rendererBackgroundSource,
76342 rendererBackground: rendererBackground,
76343 rendererFeatures: rendererFeatures,
76344 rendererMap: rendererMap,
76345 rendererTileLayer: rendererTileLayer,
76346 services: services,
76347 svgAreas: svgAreas$$1,
76348 svgDebug: svgDebug,
76352 svgLabels: svgLabels,
76353 svgLayers: svgLayers,
76354 svgLines: svgLines$$1,
76355 svgMapillaryImages: svgMapillaryImages,
76356 svgMapillarySigns: svgMapillarySigns,
76357 svgMidpoints: svgMidpoints$$1,
76358 svgOneWaySegments: svgOneWaySegments,
76361 svgPointTransform: svgPointTransform,
76362 svgPoints: svgPoints$$1,
76363 svgRelationMemberTags: svgRelationMemberTags,
76364 svgTagClasses: svgTagClasses,
76365 svgTurns: svgTurns,
76366 svgVertices: svgVertices$$1,
76367 uiFields: uiFields,
76368 uiFieldDefaultCheck: uiFieldCheck,
76369 uiFieldOnewayCheck: uiFieldCheck,
76370 uiFieldCheck: uiFieldCheck,
76371 uiFieldMultiCombo: uiFieldCombo,
76372 uiFieldNetworkCombo: uiFieldCombo,
76373 uiFieldSemiCombo: uiFieldCombo,
76374 uiFieldTypeCombo: uiFieldCombo,
76375 uiFieldCombo: uiFieldCombo,
76376 uiFieldUrl: uiFieldText,
76377 uiFieldNumber: uiFieldText,
76378 uiFieldTel: uiFieldText,
76379 uiFieldEmail: uiFieldText,
76380 uiFieldText: uiFieldText,
76381 uiFieldAccess: uiFieldAccess,
76382 uiFieldAddress: uiFieldAddress,
76383 uiFieldCycleway: uiFieldCycleway,
76384 uiFieldLanes: uiFieldLanes,
76385 uiFieldLocalized: uiFieldLocalized,
76386 uiFieldMaxspeed: uiFieldMaxspeed,
76387 uiFieldStructureRadio: uiFieldRadio,
76388 uiFieldRadio: uiFieldRadio,
76389 uiFieldRestrictions: uiFieldRestrictions,
76390 uiFieldTextarea: uiFieldTextarea,
76391 uiFieldWikipedia: uiFieldWikipedia,
76394 uiAccount: uiAccount,
76395 uiAttribution: uiAttribution,
76396 uiBackground: uiBackground,
76398 uiCommit: uiCommit,
76399 uiConfirm: uiConfirm,
76400 uiConflicts: uiConflicts,
76401 uiContributors: uiContributors,
76402 uiCurtain: uiCurtain,
76403 uiDisclosure: uiDisclosure,
76404 uiEditMenu: uiEditMenu,
76405 uiEntityEditor: uiEntityEditor,
76406 uiFeatureInfo: uiFeatureInfo,
76407 uiFeatureList: uiFeatureList,
76409 uiFullScreen: uiFullScreen,
76410 uiGeolocate: uiGeolocate,
76413 uiInspector: uiInspector,
76415 uiLoading: uiLoading,
76416 uiMapData: uiMapData,
76417 uiMapInMap: uiMapInMap,
76420 uiNotice: uiNotice,
76421 uiPreset: uiPreset,
76422 uiPresetIcon: uiPresetIcon,
76423 uiPresetList: uiPresetList,
76424 uiRadialMenu: uiRadialMenu,
76425 uiRawMemberEditor: uiRawMemberEditor,
76426 uiRawMembershipEditor: uiRawMembershipEditor,
76427 uiRawTagEditor: uiRawTagEditor,
76428 uiRestore: uiRestore,
76431 uiSelectionList: uiSelectionList,
76432 uiSidebar: uiSidebar,
76433 uiSourceSwitch: uiSourceSwitch,
76434 uiSpinner: uiSpinner,
76435 uiSplash: uiSplash,
76436 uiStatus: uiStatus,
76437 uiSuccess: uiSuccess,
76438 uiTagReference: uiTagReference,
76439 uiToggle: uiToggle,
76440 uiTooltipHtml: uiTooltipHtml,
76441 uiUndoRedo: uiUndoRedo,
76442 uiVersion: uiVersion,
76443 uiViewOnOSM: uiViewOnOSM,
76445 utilAsyncMap: utilAsyncMap,
76446 utilDisplayName: utilDisplayName,
76447 utilDisplayNameForPath: utilDisplayNameForPath,
76448 utilDisplayType: utilDisplayType,
76449 utilEditDistance: utilEditDistance,
76450 utilEntitySelector: utilEntitySelector,
76451 utilEntityOrMemberSelector: utilEntityOrMemberSelector,
76452 utilFastMouse: utilFastMouse,
76453 utilFunctor: utilFunctor,
76454 utilGetAllNodes: utilGetAllNodes,
76455 utilGetPrototypeOf: utilGetPrototypeOf,
76456 utilGetSetValue: utilGetSetValue,
76457 utilNoAuto: utilNoAuto,
76458 utilPrefixCSSProperty: utilPrefixCSSProperty,
76459 utilPrefixDOMProperty: utilPrefixDOMProperty,
76460 utilQsString: utilQsString,
76461 utilRebind: utilRebind,
76462 utilSetTransform: utilSetTransform,
76463 utilSessionMutex: utilSessionMutex,
76464 utilStringQs: utilStringQs,
76465 utilSuggestNames: utilSuggestNames,
76466 utilTagText: utilTagText,
76467 utilTriggerEvent: utilTriggerEvent,
76468 utilWrap: utilWrap,
76469 d3combobox: d3combobox,
76470 d3geoTile: d3geoTile,
76471 d3keybinding: d3keybinding,
76472 validationDeprecatedTag: validationDeprecatedTag,
76473 validationDisconnectedHighway: validationDisconnectedHighway,
76474 validationManyDeletions: validationManyDeletions,
76475 validationMissingTag: validationMissingTag,
76476 validationOldMultipolygon: validationOldMultipolygon,
76477 validationTagSuggestsArea: validationTagSuggestsArea
76483 //# sourceMappingURL=iD.js.map