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 : {};
10 function commonjsRequire () {
11 throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
16 function createCommonjsModule(fn, module) {
17 return module = { exports: {} }, fn(module, module.exports), module.exports;
20 var lodash = createCommonjsModule(function (module, exports) {
23 * Lodash <https://lodash.com/>
24 * Copyright JS Foundation and other contributors <https://js.foundation/>
25 * Released under MIT license <https://lodash.com/license>
26 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
27 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
31 /** Used as a safe reference for `undefined` in pre-ES5 environments. */
34 /** Used as the semantic version number. */
35 var VERSION = '4.17.4';
37 /** Used as the size to enable large array optimizations. */
38 var LARGE_ARRAY_SIZE = 200;
40 /** Error message constants. */
41 var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
42 FUNC_ERROR_TEXT = 'Expected a function';
44 /** Used to stand-in for `undefined` hash values. */
45 var HASH_UNDEFINED = '__lodash_hash_undefined__';
47 /** Used as the maximum memoize cache size. */
48 var MAX_MEMOIZE_SIZE = 500;
50 /** Used as the internal argument placeholder. */
51 var PLACEHOLDER = '__lodash_placeholder__';
53 /** Used to compose bitmasks for cloning. */
54 var CLONE_DEEP_FLAG = 1,
56 CLONE_SYMBOLS_FLAG = 4;
58 /** Used to compose bitmasks for value comparisons. */
59 var COMPARE_PARTIAL_FLAG = 1,
60 COMPARE_UNORDERED_FLAG = 2;
62 /** Used to compose bitmasks for function metadata. */
63 var WRAP_BIND_FLAG = 1,
64 WRAP_BIND_KEY_FLAG = 2,
65 WRAP_CURRY_BOUND_FLAG = 4,
67 WRAP_CURRY_RIGHT_FLAG = 16,
68 WRAP_PARTIAL_FLAG = 32,
69 WRAP_PARTIAL_RIGHT_FLAG = 64,
71 WRAP_REARG_FLAG = 256,
74 /** Used as default options for `_.truncate`. */
75 var DEFAULT_TRUNC_LENGTH = 30,
76 DEFAULT_TRUNC_OMISSION = '...';
78 /** Used to detect hot functions by number of calls within a span of milliseconds. */
82 /** Used to indicate the type of lazy iteratees. */
83 var LAZY_FILTER_FLAG = 1,
87 /** Used as references for various `Number` constants. */
89 MAX_SAFE_INTEGER = 9007199254740991,
90 MAX_INTEGER = 1.7976931348623157e+308,
93 /** Used as references for the maximum length and index of an array. */
94 var MAX_ARRAY_LENGTH = 4294967295,
95 MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
96 HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
98 /** Used to associate wrap methods with their bit flags. */
100 ['ary', WRAP_ARY_FLAG],
101 ['bind', WRAP_BIND_FLAG],
102 ['bindKey', WRAP_BIND_KEY_FLAG],
103 ['curry', WRAP_CURRY_FLAG],
104 ['curryRight', WRAP_CURRY_RIGHT_FLAG],
105 ['flip', WRAP_FLIP_FLAG],
106 ['partial', WRAP_PARTIAL_FLAG],
107 ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
108 ['rearg', WRAP_REARG_FLAG]
111 /** `Object#toString` result references. */
112 var argsTag = '[object Arguments]',
113 arrayTag = '[object Array]',
114 asyncTag = '[object AsyncFunction]',
115 boolTag = '[object Boolean]',
116 dateTag = '[object Date]',
117 domExcTag = '[object DOMException]',
118 errorTag = '[object Error]',
119 funcTag = '[object Function]',
120 genTag = '[object GeneratorFunction]',
121 mapTag = '[object Map]',
122 numberTag = '[object Number]',
123 nullTag = '[object Null]',
124 objectTag = '[object Object]',
125 promiseTag = '[object Promise]',
126 proxyTag = '[object Proxy]',
127 regexpTag = '[object RegExp]',
128 setTag = '[object Set]',
129 stringTag = '[object String]',
130 symbolTag = '[object Symbol]',
131 undefinedTag = '[object Undefined]',
132 weakMapTag = '[object WeakMap]',
133 weakSetTag = '[object WeakSet]';
135 var arrayBufferTag = '[object ArrayBuffer]',
136 dataViewTag = '[object DataView]',
137 float32Tag = '[object Float32Array]',
138 float64Tag = '[object Float64Array]',
139 int8Tag = '[object Int8Array]',
140 int16Tag = '[object Int16Array]',
141 int32Tag = '[object Int32Array]',
142 uint8Tag = '[object Uint8Array]',
143 uint8ClampedTag = '[object Uint8ClampedArray]',
144 uint16Tag = '[object Uint16Array]',
145 uint32Tag = '[object Uint32Array]';
147 /** Used to match empty string literals in compiled template source. */
148 var reEmptyStringLeading = /\b__p \+= '';/g,
149 reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
150 reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
152 /** Used to match HTML entities and HTML characters. */
153 var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
154 reUnescapedHtml = /[&<>"']/g,
155 reHasEscapedHtml = RegExp(reEscapedHtml.source),
156 reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
158 /** Used to match template delimiters. */
159 var reEscape = /<%-([\s\S]+?)%>/g,
160 reEvaluate = /<%([\s\S]+?)%>/g,
161 reInterpolate = /<%=([\s\S]+?)%>/g;
163 /** Used to match property names within property paths. */
164 var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
165 reIsPlainProp = /^\w*$/,
166 reLeadingDot = /^\./,
167 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
170 * Used to match `RegExp`
171 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
173 var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
174 reHasRegExpChar = RegExp(reRegExpChar.source);
176 /** Used to match leading and trailing whitespace. */
177 var reTrim = /^\s+|\s+$/g,
178 reTrimStart = /^\s+/,
181 /** Used to match wrap detail comments. */
182 var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
183 reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
184 reSplitDetails = /,? & /;
186 /** Used to match words composed of alphanumeric characters. */
187 var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
189 /** Used to match backslashes in property paths. */
190 var reEscapeChar = /\\(\\)?/g;
194 * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
196 var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
198 /** Used to match `RegExp` flags from their coerced string values. */
199 var reFlags = /\w*$/;
201 /** Used to detect bad signed hexadecimal string values. */
202 var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
204 /** Used to detect binary string values. */
205 var reIsBinary = /^0b[01]+$/i;
207 /** Used to detect host constructors (Safari). */
208 var reIsHostCtor = /^\[object .+?Constructor\]$/;
210 /** Used to detect octal string values. */
211 var reIsOctal = /^0o[0-7]+$/i;
213 /** Used to detect unsigned integer values. */
214 var reIsUint = /^(?:0|[1-9]\d*)$/;
216 /** Used to match Latin Unicode letters (excluding mathematical operators). */
217 var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
219 /** Used to ensure capturing order of template delimiters. */
220 var reNoMatch = /($^)/;
222 /** Used to match unescaped characters in compiled string literals. */
223 var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
225 /** Used to compose unicode character classes. */
226 var rsAstralRange = '\\ud800-\\udfff',
227 rsComboMarksRange = '\\u0300-\\u036f',
228 reComboHalfMarksRange = '\\ufe20-\\ufe2f',
229 rsComboSymbolsRange = '\\u20d0-\\u20ff',
230 rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
231 rsDingbatRange = '\\u2700-\\u27bf',
232 rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
233 rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
234 rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
235 rsPunctuationRange = '\\u2000-\\u206f',
236 rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
237 rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
238 rsVarRange = '\\ufe0e\\ufe0f',
239 rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
241 /** Used to compose unicode capture groups. */
242 var rsApos = "['\u2019]",
243 rsAstral = '[' + rsAstralRange + ']',
244 rsBreak = '[' + rsBreakRange + ']',
245 rsCombo = '[' + rsComboRange + ']',
247 rsDingbat = '[' + rsDingbatRange + ']',
248 rsLower = '[' + rsLowerRange + ']',
249 rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
250 rsFitz = '\\ud83c[\\udffb-\\udfff]',
251 rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
252 rsNonAstral = '[^' + rsAstralRange + ']',
253 rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
254 rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
255 rsUpper = '[' + rsUpperRange + ']',
258 /** Used to compose unicode regexes. */
259 var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
260 rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
261 rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
262 rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
263 reOptMod = rsModifier + '?',
264 rsOptVar = '[' + rsVarRange + ']?',
265 rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
266 rsOrdLower = '\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)',
267 rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)',
268 rsSeq = rsOptVar + reOptMod + rsOptJoin,
269 rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
270 rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
272 /** Used to match apostrophes. */
273 var reApos = RegExp(rsApos, 'g');
276 * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
277 * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
279 var reComboMark = RegExp(rsCombo, 'g');
281 /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
282 var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
284 /** Used to match complex or compound words. */
285 var reUnicodeWord = RegExp([
286 rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
287 rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
288 rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
289 rsUpper + '+' + rsOptContrUpper,
296 /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
297 var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
299 /** Used to detect strings that need a more robust regexp to match words. */
300 var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
302 /** Used to assign default `context` object properties. */
304 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
305 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
306 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
307 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
308 '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
311 /** Used to make template sourceURLs easier to identify. */
312 var templateCounter = -1;
314 /** Used to identify `toStringTag` values of typed arrays. */
315 var typedArrayTags = {};
316 typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
317 typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
318 typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
319 typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
320 typedArrayTags[uint32Tag] = true;
321 typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
322 typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
323 typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
324 typedArrayTags[errorTag] = typedArrayTags[funcTag] =
325 typedArrayTags[mapTag] = typedArrayTags[numberTag] =
326 typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
327 typedArrayTags[setTag] = typedArrayTags[stringTag] =
328 typedArrayTags[weakMapTag] = false;
330 /** Used to identify `toStringTag` values supported by `_.clone`. */
331 var cloneableTags = {};
332 cloneableTags[argsTag] = cloneableTags[arrayTag] =
333 cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
334 cloneableTags[boolTag] = cloneableTags[dateTag] =
335 cloneableTags[float32Tag] = cloneableTags[float64Tag] =
336 cloneableTags[int8Tag] = cloneableTags[int16Tag] =
337 cloneableTags[int32Tag] = cloneableTags[mapTag] =
338 cloneableTags[numberTag] = cloneableTags[objectTag] =
339 cloneableTags[regexpTag] = cloneableTags[setTag] =
340 cloneableTags[stringTag] = cloneableTags[symbolTag] =
341 cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
342 cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
343 cloneableTags[errorTag] = cloneableTags[funcTag] =
344 cloneableTags[weakMapTag] = false;
346 /** Used to map Latin Unicode letters to basic Latin letters. */
347 var deburredLetters = {
348 // Latin-1 Supplement block.
349 '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
350 '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
351 '\xc7': 'C', '\xe7': 'c',
352 '\xd0': 'D', '\xf0': 'd',
353 '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
354 '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
355 '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
356 '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
357 '\xd1': 'N', '\xf1': 'n',
358 '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
359 '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
360 '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
361 '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
362 '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
363 '\xc6': 'Ae', '\xe6': 'ae',
364 '\xde': 'Th', '\xfe': 'th',
366 // Latin Extended-A block.
367 '\u0100': 'A', '\u0102': 'A', '\u0104': 'A',
368 '\u0101': 'a', '\u0103': 'a', '\u0105': 'a',
369 '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
370 '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
371 '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
372 '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
373 '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
374 '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
375 '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
376 '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
377 '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
378 '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
379 '\u0134': 'J', '\u0135': 'j',
380 '\u0136': 'K', '\u0137': 'k', '\u0138': 'k',
381 '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
382 '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
383 '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
384 '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
385 '\u014c': 'O', '\u014e': 'O', '\u0150': 'O',
386 '\u014d': 'o', '\u014f': 'o', '\u0151': 'o',
387 '\u0154': 'R', '\u0156': 'R', '\u0158': 'R',
388 '\u0155': 'r', '\u0157': 'r', '\u0159': 'r',
389 '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
390 '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's',
391 '\u0162': 'T', '\u0164': 'T', '\u0166': 'T',
392 '\u0163': 't', '\u0165': 't', '\u0167': 't',
393 '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
394 '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
395 '\u0174': 'W', '\u0175': 'w',
396 '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y',
397 '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z',
398 '\u017a': 'z', '\u017c': 'z', '\u017e': 'z',
399 '\u0132': 'IJ', '\u0133': 'ij',
400 '\u0152': 'Oe', '\u0153': 'oe',
401 '\u0149': "'n", '\u017f': 's'
404 /** Used to map characters to HTML entities. */
413 /** Used to map HTML entities to characters. */
414 var htmlUnescapes = {
422 /** Used to escape characters for inclusion in compiled string literals. */
423 var stringEscapes = {
432 /** Built-in method references without a dependency on `root`. */
433 var freeParseFloat = parseFloat,
434 freeParseInt = parseInt;
436 /** Detect free variable `global` from Node.js. */
437 var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
439 /** Detect free variable `self`. */
440 var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
442 /** Used as a reference to the global object. */
443 var root = freeGlobal || freeSelf || Function('return this')();
445 /** Detect free variable `exports`. */
446 var freeExports = 'object' == 'object' && exports && !exports.nodeType && exports;
448 /** Detect free variable `module`. */
449 var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
451 /** Detect the popular CommonJS extension `module.exports`. */
452 var moduleExports = freeModule && freeModule.exports === freeExports;
454 /** Detect free variable `process` from Node.js. */
455 var freeProcess = moduleExports && freeGlobal.process;
457 /** Used to access faster Node.js helpers. */
458 var nodeUtil = (function() {
460 return freeProcess && freeProcess.binding && freeProcess.binding('util');
464 /* Node.js helper references. */
465 var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
466 nodeIsDate = nodeUtil && nodeUtil.isDate,
467 nodeIsMap = nodeUtil && nodeUtil.isMap,
468 nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
469 nodeIsSet = nodeUtil && nodeUtil.isSet,
470 nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
472 /*--------------------------------------------------------------------------*/
475 * Adds the key-value `pair` to `map`.
478 * @param {Object} map The map to modify.
479 * @param {Array} pair The key-value pair to add.
480 * @returns {Object} Returns `map`.
482 function addMapEntry(map, pair) {
483 // Don't return `map.set` because it's not chainable in IE 11.
484 map.set(pair[0], pair[1]);
489 * Adds `value` to `set`.
492 * @param {Object} set The set to modify.
493 * @param {*} value The value to add.
494 * @returns {Object} Returns `set`.
496 function addSetEntry(set, value) {
497 // Don't return `set.add` because it's not chainable in IE 11.
503 * A faster alternative to `Function#apply`, this function invokes `func`
504 * with the `this` binding of `thisArg` and the arguments of `args`.
507 * @param {Function} func The function to invoke.
508 * @param {*} thisArg The `this` binding of `func`.
509 * @param {Array} args The arguments to invoke `func` with.
510 * @returns {*} Returns the result of `func`.
512 function apply(func, thisArg, args) {
513 switch (args.length) {
514 case 0: return func.call(thisArg);
515 case 1: return func.call(thisArg, args[0]);
516 case 2: return func.call(thisArg, args[0], args[1]);
517 case 3: return func.call(thisArg, args[0], args[1], args[2]);
519 return func.apply(thisArg, args);
523 * A specialized version of `baseAggregator` for arrays.
526 * @param {Array} [array] The array to iterate over.
527 * @param {Function} setter The function to set `accumulator` values.
528 * @param {Function} iteratee The iteratee to transform keys.
529 * @param {Object} accumulator The initial aggregated object.
530 * @returns {Function} Returns `accumulator`.
532 function arrayAggregator(array, setter, iteratee, accumulator) {
534 length = array == null ? 0 : array.length;
536 while (++index < length) {
537 var value = array[index];
538 setter(accumulator, value, iteratee(value), array);
544 * A specialized version of `_.forEach` for arrays without support for
545 * iteratee shorthands.
548 * @param {Array} [array] The array to iterate over.
549 * @param {Function} iteratee The function invoked per iteration.
550 * @returns {Array} Returns `array`.
552 function arrayEach(array, iteratee) {
554 length = array == null ? 0 : array.length;
556 while (++index < length) {
557 if (iteratee(array[index], index, array) === false) {
565 * A specialized version of `_.forEachRight` for arrays without support for
566 * iteratee shorthands.
569 * @param {Array} [array] The array to iterate over.
570 * @param {Function} iteratee The function invoked per iteration.
571 * @returns {Array} Returns `array`.
573 function arrayEachRight(array, iteratee) {
574 var length = array == null ? 0 : array.length;
577 if (iteratee(array[length], length, array) === false) {
585 * A specialized version of `_.every` for arrays without support for
586 * iteratee shorthands.
589 * @param {Array} [array] The array to iterate over.
590 * @param {Function} predicate The function invoked per iteration.
591 * @returns {boolean} Returns `true` if all elements pass the predicate check,
594 function arrayEvery(array, predicate) {
596 length = array == null ? 0 : array.length;
598 while (++index < length) {
599 if (!predicate(array[index], index, array)) {
607 * A specialized version of `_.filter` for arrays without support for
608 * iteratee shorthands.
611 * @param {Array} [array] The array to iterate over.
612 * @param {Function} predicate The function invoked per iteration.
613 * @returns {Array} Returns the new filtered array.
615 function arrayFilter(array, predicate) {
617 length = array == null ? 0 : array.length,
621 while (++index < length) {
622 var value = array[index];
623 if (predicate(value, index, array)) {
624 result[resIndex++] = value;
631 * A specialized version of `_.includes` for arrays without support for
632 * specifying an index to search from.
635 * @param {Array} [array] The array to inspect.
636 * @param {*} target The value to search for.
637 * @returns {boolean} Returns `true` if `target` is found, else `false`.
639 function arrayIncludes(array, value) {
640 var length = array == null ? 0 : array.length;
641 return !!length && baseIndexOf(array, value, 0) > -1;
645 * This function is like `arrayIncludes` except that it accepts a comparator.
648 * @param {Array} [array] The array to inspect.
649 * @param {*} target The value to search for.
650 * @param {Function} comparator The comparator invoked per element.
651 * @returns {boolean} Returns `true` if `target` is found, else `false`.
653 function arrayIncludesWith(array, value, comparator) {
655 length = array == null ? 0 : array.length;
657 while (++index < length) {
658 if (comparator(value, array[index])) {
666 * A specialized version of `_.map` for arrays without support for iteratee
670 * @param {Array} [array] The array to iterate over.
671 * @param {Function} iteratee The function invoked per iteration.
672 * @returns {Array} Returns the new mapped array.
674 function arrayMap(array, iteratee) {
676 length = array == null ? 0 : array.length,
677 result = Array(length);
679 while (++index < length) {
680 result[index] = iteratee(array[index], index, array);
686 * Appends the elements of `values` to `array`.
689 * @param {Array} array The array to modify.
690 * @param {Array} values The values to append.
691 * @returns {Array} Returns `array`.
693 function arrayPush(array, values) {
695 length = values.length,
696 offset = array.length;
698 while (++index < length) {
699 array[offset + index] = values[index];
705 * A specialized version of `_.reduce` for arrays without support for
706 * iteratee shorthands.
709 * @param {Array} [array] The array to iterate over.
710 * @param {Function} iteratee The function invoked per iteration.
711 * @param {*} [accumulator] The initial value.
712 * @param {boolean} [initAccum] Specify using the first element of `array` as
714 * @returns {*} Returns the accumulated value.
716 function arrayReduce(array, iteratee, accumulator, initAccum) {
718 length = array == null ? 0 : array.length;
720 if (initAccum && length) {
721 accumulator = array[++index];
723 while (++index < length) {
724 accumulator = iteratee(accumulator, array[index], index, array);
730 * A specialized version of `_.reduceRight` for arrays without support for
731 * iteratee shorthands.
734 * @param {Array} [array] The array to iterate over.
735 * @param {Function} iteratee The function invoked per iteration.
736 * @param {*} [accumulator] The initial value.
737 * @param {boolean} [initAccum] Specify using the last element of `array` as
739 * @returns {*} Returns the accumulated value.
741 function arrayReduceRight(array, iteratee, accumulator, initAccum) {
742 var length = array == null ? 0 : array.length;
743 if (initAccum && length) {
744 accumulator = array[--length];
747 accumulator = iteratee(accumulator, array[length], length, array);
753 * A specialized version of `_.some` for arrays without support for iteratee
757 * @param {Array} [array] The array to iterate over.
758 * @param {Function} predicate The function invoked per iteration.
759 * @returns {boolean} Returns `true` if any element passes the predicate check,
762 function arraySome(array, predicate) {
764 length = array == null ? 0 : array.length;
766 while (++index < length) {
767 if (predicate(array[index], index, array)) {
775 * Gets the size of an ASCII `string`.
778 * @param {string} string The string inspect.
779 * @returns {number} Returns the string size.
781 var asciiSize = baseProperty('length');
784 * Converts an ASCII `string` to an array.
787 * @param {string} string The string to convert.
788 * @returns {Array} Returns the converted array.
790 function asciiToArray(string) {
791 return string.split('');
795 * Splits an ASCII `string` into an array of its words.
798 * @param {string} The string to inspect.
799 * @returns {Array} Returns the words of `string`.
801 function asciiWords(string) {
802 return string.match(reAsciiWord) || [];
806 * The base implementation of methods like `_.findKey` and `_.findLastKey`,
807 * without support for iteratee shorthands, which iterates over `collection`
811 * @param {Array|Object} collection The collection to inspect.
812 * @param {Function} predicate The function invoked per iteration.
813 * @param {Function} eachFunc The function to iterate over `collection`.
814 * @returns {*} Returns the found element or its key, else `undefined`.
816 function baseFindKey(collection, predicate, eachFunc) {
818 eachFunc(collection, function(value, key, collection) {
819 if (predicate(value, key, collection)) {
828 * The base implementation of `_.findIndex` and `_.findLastIndex` without
829 * support for iteratee shorthands.
832 * @param {Array} array The array to inspect.
833 * @param {Function} predicate The function invoked per iteration.
834 * @param {number} fromIndex The index to search from.
835 * @param {boolean} [fromRight] Specify iterating from right to left.
836 * @returns {number} Returns the index of the matched value, else `-1`.
838 function baseFindIndex(array, predicate, fromIndex, fromRight) {
839 var length = array.length,
840 index = fromIndex + (fromRight ? 1 : -1);
842 while ((fromRight ? index-- : ++index < length)) {
843 if (predicate(array[index], index, array)) {
851 * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
854 * @param {Array} array The array to inspect.
855 * @param {*} value The value to search for.
856 * @param {number} fromIndex The index to search from.
857 * @returns {number} Returns the index of the matched value, else `-1`.
859 function baseIndexOf(array, value, fromIndex) {
860 return value === value
861 ? strictIndexOf(array, value, fromIndex)
862 : baseFindIndex(array, baseIsNaN, fromIndex);
866 * This function is like `baseIndexOf` except that it accepts a comparator.
869 * @param {Array} array The array to inspect.
870 * @param {*} value The value to search for.
871 * @param {number} fromIndex The index to search from.
872 * @param {Function} comparator The comparator invoked per element.
873 * @returns {number} Returns the index of the matched value, else `-1`.
875 function baseIndexOfWith(array, value, fromIndex, comparator) {
876 var index = fromIndex - 1,
877 length = array.length;
879 while (++index < length) {
880 if (comparator(array[index], value)) {
888 * The base implementation of `_.isNaN` without support for number objects.
891 * @param {*} value The value to check.
892 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
894 function baseIsNaN(value) {
895 return value !== value;
899 * The base implementation of `_.mean` and `_.meanBy` without support for
900 * iteratee shorthands.
903 * @param {Array} array The array to iterate over.
904 * @param {Function} iteratee The function invoked per iteration.
905 * @returns {number} Returns the mean.
907 function baseMean(array, iteratee) {
908 var length = array == null ? 0 : array.length;
909 return length ? (baseSum(array, iteratee) / length) : NAN;
913 * The base implementation of `_.property` without support for deep paths.
916 * @param {string} key The key of the property to get.
917 * @returns {Function} Returns the new accessor function.
919 function baseProperty(key) {
920 return function(object) {
921 return object == null ? undefined : object[key];
926 * The base implementation of `_.propertyOf` without support for deep paths.
929 * @param {Object} object The object to query.
930 * @returns {Function} Returns the new accessor function.
932 function basePropertyOf(object) {
933 return function(key) {
934 return object == null ? undefined : object[key];
939 * The base implementation of `_.reduce` and `_.reduceRight`, without support
940 * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
943 * @param {Array|Object} collection The collection to iterate over.
944 * @param {Function} iteratee The function invoked per iteration.
945 * @param {*} accumulator The initial value.
946 * @param {boolean} initAccum Specify using the first or last element of
947 * `collection` as the initial value.
948 * @param {Function} eachFunc The function to iterate over `collection`.
949 * @returns {*} Returns the accumulated value.
951 function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
952 eachFunc(collection, function(value, index, collection) {
953 accumulator = initAccum
954 ? (initAccum = false, value)
955 : iteratee(accumulator, value, index, collection);
961 * The base implementation of `_.sortBy` which uses `comparer` to define the
962 * sort order of `array` and replaces criteria objects with their corresponding
966 * @param {Array} array The array to sort.
967 * @param {Function} comparer The function to define sort order.
968 * @returns {Array} Returns `array`.
970 function baseSortBy(array, comparer) {
971 var length = array.length;
973 array.sort(comparer);
975 array[length] = array[length].value;
981 * The base implementation of `_.sum` and `_.sumBy` without support for
982 * iteratee shorthands.
985 * @param {Array} array The array to iterate over.
986 * @param {Function} iteratee The function invoked per iteration.
987 * @returns {number} Returns the sum.
989 function baseSum(array, iteratee) {
992 length = array.length;
994 while (++index < length) {
995 var current = iteratee(array[index]);
996 if (current !== undefined) {
997 result = result === undefined ? current : (result + current);
1004 * The base implementation of `_.times` without support for iteratee shorthands
1005 * or max array length checks.
1008 * @param {number} n The number of times to invoke `iteratee`.
1009 * @param {Function} iteratee The function invoked per iteration.
1010 * @returns {Array} Returns the array of results.
1012 function baseTimes(n, iteratee) {
1016 while (++index < n) {
1017 result[index] = iteratee(index);
1023 * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
1024 * of key-value pairs for `object` corresponding to the property names of `props`.
1027 * @param {Object} object The object to query.
1028 * @param {Array} props The property names to get values for.
1029 * @returns {Object} Returns the key-value pairs.
1031 function baseToPairs(object, props) {
1032 return arrayMap(props, function(key) {
1033 return [key, object[key]];
1038 * The base implementation of `_.unary` without support for storing metadata.
1041 * @param {Function} func The function to cap arguments for.
1042 * @returns {Function} Returns the new capped function.
1044 function baseUnary(func) {
1045 return function(value) {
1051 * The base implementation of `_.values` and `_.valuesIn` which creates an
1052 * array of `object` property values corresponding to the property names
1056 * @param {Object} object The object to query.
1057 * @param {Array} props The property names to get values for.
1058 * @returns {Object} Returns the array of property values.
1060 function baseValues(object, props) {
1061 return arrayMap(props, function(key) {
1067 * Checks if a `cache` value for `key` exists.
1070 * @param {Object} cache The cache to query.
1071 * @param {string} key The key of the entry to check.
1072 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
1074 function cacheHas(cache, key) {
1075 return cache.has(key);
1079 * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
1080 * that is not found in the character symbols.
1083 * @param {Array} strSymbols The string symbols to inspect.
1084 * @param {Array} chrSymbols The character symbols to find.
1085 * @returns {number} Returns the index of the first unmatched string symbol.
1087 function charsStartIndex(strSymbols, chrSymbols) {
1089 length = strSymbols.length;
1091 while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
1096 * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
1097 * that is not found in the character symbols.
1100 * @param {Array} strSymbols The string symbols to inspect.
1101 * @param {Array} chrSymbols The character symbols to find.
1102 * @returns {number} Returns the index of the last unmatched string symbol.
1104 function charsEndIndex(strSymbols, chrSymbols) {
1105 var index = strSymbols.length;
1107 while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
1112 * Gets the number of `placeholder` occurrences in `array`.
1115 * @param {Array} array The array to inspect.
1116 * @param {*} placeholder The placeholder to search for.
1117 * @returns {number} Returns the placeholder count.
1119 function countHolders(array, placeholder) {
1120 var length = array.length,
1124 if (array[length] === placeholder) {
1132 * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
1133 * letters to basic Latin letters.
1136 * @param {string} letter The matched letter to deburr.
1137 * @returns {string} Returns the deburred letter.
1139 var deburrLetter = basePropertyOf(deburredLetters);
1142 * Used by `_.escape` to convert characters to HTML entities.
1145 * @param {string} chr The matched character to escape.
1146 * @returns {string} Returns the escaped character.
1148 var escapeHtmlChar = basePropertyOf(htmlEscapes);
1151 * Used by `_.template` to escape characters for inclusion in compiled string literals.
1154 * @param {string} chr The matched character to escape.
1155 * @returns {string} Returns the escaped character.
1157 function escapeStringChar(chr) {
1158 return '\\' + stringEscapes[chr];
1162 * Gets the value at `key` of `object`.
1165 * @param {Object} [object] The object to query.
1166 * @param {string} key The key of the property to get.
1167 * @returns {*} Returns the property value.
1169 function getValue(object, key) {
1170 return object == null ? undefined : object[key];
1174 * Checks if `string` contains Unicode symbols.
1177 * @param {string} string The string to inspect.
1178 * @returns {boolean} Returns `true` if a symbol is found, else `false`.
1180 function hasUnicode(string) {
1181 return reHasUnicode.test(string);
1185 * Checks if `string` contains a word composed of Unicode symbols.
1188 * @param {string} string The string to inspect.
1189 * @returns {boolean} Returns `true` if a word is found, else `false`.
1191 function hasUnicodeWord(string) {
1192 return reHasUnicodeWord.test(string);
1196 * Converts `iterator` to an array.
1199 * @param {Object} iterator The iterator to convert.
1200 * @returns {Array} Returns the converted array.
1202 function iteratorToArray(iterator) {
1206 while (!(data = iterator.next()).done) {
1207 result.push(data.value);
1213 * Converts `map` to its key-value pairs.
1216 * @param {Object} map The map to convert.
1217 * @returns {Array} Returns the key-value pairs.
1219 function mapToArray(map) {
1221 result = Array(map.size);
1223 map.forEach(function(value, key) {
1224 result[++index] = [key, value];
1230 * Creates a unary function that invokes `func` with its argument transformed.
1233 * @param {Function} func The function to wrap.
1234 * @param {Function} transform The argument transform.
1235 * @returns {Function} Returns the new function.
1237 function overArg(func, transform) {
1238 return function(arg) {
1239 return func(transform(arg));
1244 * Replaces all `placeholder` elements in `array` with an internal placeholder
1245 * and returns an array of their indexes.
1248 * @param {Array} array The array to modify.
1249 * @param {*} placeholder The placeholder to replace.
1250 * @returns {Array} Returns the new array of placeholder indexes.
1252 function replaceHolders(array, placeholder) {
1254 length = array.length,
1258 while (++index < length) {
1259 var value = array[index];
1260 if (value === placeholder || value === PLACEHOLDER) {
1261 array[index] = PLACEHOLDER;
1262 result[resIndex++] = index;
1269 * Converts `set` to an array of its values.
1272 * @param {Object} set The set to convert.
1273 * @returns {Array} Returns the values.
1275 function setToArray(set) {
1277 result = Array(set.size);
1279 set.forEach(function(value) {
1280 result[++index] = value;
1286 * Converts `set` to its value-value pairs.
1289 * @param {Object} set The set to convert.
1290 * @returns {Array} Returns the value-value pairs.
1292 function setToPairs(set) {
1294 result = Array(set.size);
1296 set.forEach(function(value) {
1297 result[++index] = [value, value];
1303 * A specialized version of `_.indexOf` which performs strict equality
1304 * comparisons of values, i.e. `===`.
1307 * @param {Array} array The array to inspect.
1308 * @param {*} value The value to search for.
1309 * @param {number} fromIndex The index to search from.
1310 * @returns {number} Returns the index of the matched value, else `-1`.
1312 function strictIndexOf(array, value, fromIndex) {
1313 var index = fromIndex - 1,
1314 length = array.length;
1316 while (++index < length) {
1317 if (array[index] === value) {
1325 * A specialized version of `_.lastIndexOf` which performs strict equality
1326 * comparisons of values, i.e. `===`.
1329 * @param {Array} array The array to inspect.
1330 * @param {*} value The value to search for.
1331 * @param {number} fromIndex The index to search from.
1332 * @returns {number} Returns the index of the matched value, else `-1`.
1334 function strictLastIndexOf(array, value, fromIndex) {
1335 var index = fromIndex + 1;
1337 if (array[index] === value) {
1345 * Gets the number of symbols in `string`.
1348 * @param {string} string The string to inspect.
1349 * @returns {number} Returns the string size.
1351 function stringSize(string) {
1352 return hasUnicode(string)
1353 ? unicodeSize(string)
1354 : asciiSize(string);
1358 * Converts `string` to an array.
1361 * @param {string} string The string to convert.
1362 * @returns {Array} Returns the converted array.
1364 function stringToArray(string) {
1365 return hasUnicode(string)
1366 ? unicodeToArray(string)
1367 : asciiToArray(string);
1371 * Used by `_.unescape` to convert HTML entities to characters.
1374 * @param {string} chr The matched character to unescape.
1375 * @returns {string} Returns the unescaped character.
1377 var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
1380 * Gets the size of a Unicode `string`.
1383 * @param {string} string The string inspect.
1384 * @returns {number} Returns the string size.
1386 function unicodeSize(string) {
1387 var result = reUnicode.lastIndex = 0;
1388 while (reUnicode.test(string)) {
1395 * Converts a Unicode `string` to an array.
1398 * @param {string} string The string to convert.
1399 * @returns {Array} Returns the converted array.
1401 function unicodeToArray(string) {
1402 return string.match(reUnicode) || [];
1406 * Splits a Unicode `string` into an array of its words.
1409 * @param {string} The string to inspect.
1410 * @returns {Array} Returns the words of `string`.
1412 function unicodeWords(string) {
1413 return string.match(reUnicodeWord) || [];
1416 /*--------------------------------------------------------------------------*/
1419 * Create a new pristine `lodash` function using the `context` object.
1425 * @param {Object} [context=root] The context object.
1426 * @returns {Function} Returns a new `lodash` function.
1429 * _.mixin({ 'foo': _.constant('foo') });
1431 * var lodash = _.runInContext();
1432 * lodash.mixin({ 'bar': lodash.constant('bar') });
1434 * _.isFunction(_.foo);
1436 * _.isFunction(_.bar);
1439 * lodash.isFunction(lodash.foo);
1441 * lodash.isFunction(lodash.bar);
1444 * // Create a suped-up `defer` in Node.js.
1445 * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
1447 var runInContext = (function runInContext(context) {
1448 context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
1450 /** Built-in constructor references. */
1451 var Array = context.Array,
1452 Date = context.Date,
1453 Error = context.Error,
1454 Function = context.Function,
1455 Math = context.Math,
1456 Object = context.Object,
1457 RegExp = context.RegExp,
1458 String = context.String,
1459 TypeError = context.TypeError;
1461 /** Used for built-in method references. */
1462 var arrayProto = Array.prototype,
1463 funcProto = Function.prototype,
1464 objectProto = Object.prototype;
1466 /** Used to detect overreaching core-js shims. */
1467 var coreJsData = context['__core-js_shared__'];
1469 /** Used to resolve the decompiled source of functions. */
1470 var funcToString = funcProto.toString;
1472 /** Used to check objects for own properties. */
1473 var hasOwnProperty = objectProto.hasOwnProperty;
1475 /** Used to generate unique IDs. */
1478 /** Used to detect methods masquerading as native. */
1479 var maskSrcKey = (function() {
1480 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
1481 return uid ? ('Symbol(src)_1.' + uid) : '';
1485 * Used to resolve the
1486 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
1489 var nativeObjectToString = objectProto.toString;
1491 /** Used to infer the `Object` constructor. */
1492 var objectCtorString = funcToString.call(Object);
1494 /** Used to restore the original `_` reference in `_.noConflict`. */
1495 var oldDash = root._;
1497 /** Used to detect if a method is native. */
1498 var reIsNative = RegExp('^' +
1499 funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
1500 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
1503 /** Built-in value references. */
1504 var Buffer = moduleExports ? context.Buffer : undefined,
1505 Symbol = context.Symbol,
1506 Uint8Array = context.Uint8Array,
1507 allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,
1508 getPrototype = overArg(Object.getPrototypeOf, Object),
1509 objectCreate = Object.create,
1510 propertyIsEnumerable = objectProto.propertyIsEnumerable,
1511 splice = arrayProto.splice,
1512 spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,
1513 symIterator = Symbol ? Symbol.iterator : undefined,
1514 symToStringTag = Symbol ? Symbol.toStringTag : undefined;
1516 var defineProperty = (function() {
1518 var func = getNative(Object, 'defineProperty');
1524 /** Mocked built-ins. */
1525 var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
1526 ctxNow = Date && Date.now !== root.Date.now && Date.now,
1527 ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
1529 /* Built-in method references for those with the same name as other `lodash` methods. */
1530 var nativeCeil = Math.ceil,
1531 nativeFloor = Math.floor,
1532 nativeGetSymbols = Object.getOwnPropertySymbols,
1533 nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
1534 nativeIsFinite = context.isFinite,
1535 nativeJoin = arrayProto.join,
1536 nativeKeys = overArg(Object.keys, Object),
1537 nativeMax = Math.max,
1538 nativeMin = Math.min,
1539 nativeNow = Date.now,
1540 nativeParseInt = context.parseInt,
1541 nativeRandom = Math.random,
1542 nativeReverse = arrayProto.reverse;
1544 /* Built-in method references that are verified to be native. */
1545 var DataView = getNative(context, 'DataView'),
1546 Map = getNative(context, 'Map'),
1547 Promise = getNative(context, 'Promise'),
1548 Set = getNative(context, 'Set'),
1549 WeakMap = getNative(context, 'WeakMap'),
1550 nativeCreate = getNative(Object, 'create');
1552 /** Used to store function metadata. */
1553 var metaMap = WeakMap && new WeakMap;
1555 /** Used to lookup unminified function names. */
1558 /** Used to detect maps, sets, and weakmaps. */
1559 var dataViewCtorString = toSource(DataView),
1560 mapCtorString = toSource(Map),
1561 promiseCtorString = toSource(Promise),
1562 setCtorString = toSource(Set),
1563 weakMapCtorString = toSource(WeakMap);
1565 /** Used to convert symbols to primitives and strings. */
1566 var symbolProto = Symbol ? Symbol.prototype : undefined,
1567 symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
1568 symbolToString = symbolProto ? symbolProto.toString : undefined;
1570 /*------------------------------------------------------------------------*/
1573 * Creates a `lodash` object which wraps `value` to enable implicit method
1574 * chain sequences. Methods that operate on and return arrays, collections,
1575 * and functions can be chained together. Methods that retrieve a single value
1576 * or may return a primitive value will automatically end the chain sequence
1577 * and return the unwrapped value. Otherwise, the value must be unwrapped
1580 * Explicit chain sequences, which must be unwrapped with `_#value`, may be
1581 * enabled using `_.chain`.
1583 * The execution of chained methods is lazy, that is, it's deferred until
1584 * `_#value` is implicitly or explicitly called.
1586 * Lazy evaluation allows several methods to support shortcut fusion.
1587 * Shortcut fusion is an optimization to merge iteratee calls; this avoids
1588 * the creation of intermediate arrays and can greatly reduce the number of
1589 * iteratee executions. Sections of a chain sequence qualify for shortcut
1590 * fusion if the section is applied to an array and iteratees accept only
1591 * one argument. The heuristic for whether a section qualifies for shortcut
1592 * fusion is subject to change.
1594 * Chaining is supported in custom builds as long as the `_#value` method is
1595 * directly or indirectly included in the build.
1597 * In addition to lodash methods, wrappers have `Array` and `String` methods.
1599 * The wrapper `Array` methods are:
1600 * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
1602 * The wrapper `String` methods are:
1603 * `replace` and `split`
1605 * The wrapper methods that support shortcut fusion are:
1606 * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
1607 * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
1608 * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
1610 * The chainable wrapper methods are:
1611 * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
1612 * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
1613 * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
1614 * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
1615 * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
1616 * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
1617 * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
1618 * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
1619 * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
1620 * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
1621 * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
1622 * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
1623 * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
1624 * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
1625 * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
1626 * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
1627 * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
1628 * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
1629 * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
1630 * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
1631 * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
1632 * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
1633 * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
1634 * `zipObject`, `zipObjectDeep`, and `zipWith`
1636 * The wrapper methods that are **not** chainable by default are:
1637 * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
1638 * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
1639 * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
1640 * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
1641 * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
1642 * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
1643 * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
1644 * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
1645 * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
1646 * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
1647 * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
1648 * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
1649 * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
1650 * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
1651 * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
1652 * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
1653 * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
1654 * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
1655 * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
1656 * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
1657 * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
1658 * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
1659 * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
1660 * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
1661 * `upperFirst`, `value`, and `words`
1666 * @param {*} value The value to wrap in a `lodash` instance.
1667 * @returns {Object} Returns the new `lodash` wrapper instance.
1670 * function square(n) {
1674 * var wrapped = _([1, 2, 3]);
1676 * // Returns an unwrapped value.
1677 * wrapped.reduce(_.add);
1680 * // Returns a wrapped value.
1681 * var squares = wrapped.map(square);
1683 * _.isArray(squares);
1686 * _.isArray(squares.value());
1689 function lodash(value) {
1690 if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
1691 if (value instanceof LodashWrapper) {
1694 if (hasOwnProperty.call(value, '__wrapped__')) {
1695 return wrapperClone(value);
1698 return new LodashWrapper(value);
1702 * The base implementation of `_.create` without support for assigning
1703 * properties to the created object.
1706 * @param {Object} proto The object to inherit from.
1707 * @returns {Object} Returns the new object.
1709 var baseCreate = (function() {
1710 function object() {}
1711 return function(proto) {
1712 if (!isObject(proto)) {
1716 return objectCreate(proto);
1718 object.prototype = proto;
1719 var result = new object;
1720 object.prototype = undefined;
1726 * The function whose prototype chain sequence wrappers inherit from.
1730 function baseLodash() {
1731 // No operation performed.
1735 * The base constructor for creating `lodash` wrapper objects.
1738 * @param {*} value The value to wrap.
1739 * @param {boolean} [chainAll] Enable explicit method chain sequences.
1741 function LodashWrapper(value, chainAll) {
1742 this.__wrapped__ = value;
1743 this.__actions__ = [];
1744 this.__chain__ = !!chainAll;
1746 this.__values__ = undefined;
1750 * By default, the template delimiters used by lodash are like those in
1751 * embedded Ruby (ERB) as well as ES2015 template strings. Change the
1752 * following template settings to use alternative delimiters.
1758 lodash.templateSettings = {
1761 * Used to detect `data` property values to be HTML-escaped.
1763 * @memberOf _.templateSettings
1769 * Used to detect code to be evaluated.
1771 * @memberOf _.templateSettings
1774 'evaluate': reEvaluate,
1777 * Used to detect `data` property values to inject.
1779 * @memberOf _.templateSettings
1782 'interpolate': reInterpolate,
1785 * Used to reference the data object in the template text.
1787 * @memberOf _.templateSettings
1793 * Used to import variables into the compiled template.
1795 * @memberOf _.templateSettings
1801 * A reference to the `lodash` function.
1803 * @memberOf _.templateSettings.imports
1810 // Ensure wrappers are instances of `baseLodash`.
1811 lodash.prototype = baseLodash.prototype;
1812 lodash.prototype.constructor = lodash;
1814 LodashWrapper.prototype = baseCreate(baseLodash.prototype);
1815 LodashWrapper.prototype.constructor = LodashWrapper;
1817 /*------------------------------------------------------------------------*/
1820 * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
1824 * @param {*} value The value to wrap.
1826 function LazyWrapper(value) {
1827 this.__wrapped__ = value;
1828 this.__actions__ = [];
1830 this.__filtered__ = false;
1831 this.__iteratees__ = [];
1832 this.__takeCount__ = MAX_ARRAY_LENGTH;
1833 this.__views__ = [];
1837 * Creates a clone of the lazy wrapper object.
1841 * @memberOf LazyWrapper
1842 * @returns {Object} Returns the cloned `LazyWrapper` object.
1844 function lazyClone() {
1845 var result = new LazyWrapper(this.__wrapped__);
1846 result.__actions__ = copyArray(this.__actions__);
1847 result.__dir__ = this.__dir__;
1848 result.__filtered__ = this.__filtered__;
1849 result.__iteratees__ = copyArray(this.__iteratees__);
1850 result.__takeCount__ = this.__takeCount__;
1851 result.__views__ = copyArray(this.__views__);
1856 * Reverses the direction of lazy iteration.
1860 * @memberOf LazyWrapper
1861 * @returns {Object} Returns the new reversed `LazyWrapper` object.
1863 function lazyReverse() {
1864 if (this.__filtered__) {
1865 var result = new LazyWrapper(this);
1866 result.__dir__ = -1;
1867 result.__filtered__ = true;
1869 result = this.clone();
1870 result.__dir__ *= -1;
1876 * Extracts the unwrapped value from its lazy wrapper.
1880 * @memberOf LazyWrapper
1881 * @returns {*} Returns the unwrapped value.
1883 function lazyValue() {
1884 var array = this.__wrapped__.value(),
1886 isArr = isArray(array),
1888 arrLength = isArr ? array.length : 0,
1889 view = getView(0, arrLength, this.__views__),
1892 length = end - start,
1893 index = isRight ? end : (start - 1),
1894 iteratees = this.__iteratees__,
1895 iterLength = iteratees.length,
1897 takeCount = nativeMin(length, this.__takeCount__);
1899 if (!isArr || (!isRight && arrLength == length && takeCount == length)) {
1900 return baseWrapperValue(array, this.__actions__);
1905 while (length-- && resIndex < takeCount) {
1909 value = array[index];
1911 while (++iterIndex < iterLength) {
1912 var data = iteratees[iterIndex],
1913 iteratee = data.iteratee,
1915 computed = iteratee(value);
1917 if (type == LAZY_MAP_FLAG) {
1919 } else if (!computed) {
1920 if (type == LAZY_FILTER_FLAG) {
1927 result[resIndex++] = value;
1932 // Ensure `LazyWrapper` is an instance of `baseLodash`.
1933 LazyWrapper.prototype = baseCreate(baseLodash.prototype);
1934 LazyWrapper.prototype.constructor = LazyWrapper;
1936 /*------------------------------------------------------------------------*/
1939 * Creates a hash object.
1943 * @param {Array} [entries] The key-value pairs to cache.
1945 function Hash(entries) {
1947 length = entries == null ? 0 : entries.length;
1950 while (++index < length) {
1951 var entry = entries[index];
1952 this.set(entry[0], entry[1]);
1957 * Removes all key-value entries from the hash.
1963 function hashClear() {
1964 this.__data__ = nativeCreate ? nativeCreate(null) : {};
1969 * Removes `key` and its value from the hash.
1974 * @param {Object} hash The hash to modify.
1975 * @param {string} key The key of the value to remove.
1976 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
1978 function hashDelete(key) {
1979 var result = this.has(key) && delete this.__data__[key];
1980 this.size -= result ? 1 : 0;
1985 * Gets the hash value for `key`.
1990 * @param {string} key The key of the value to get.
1991 * @returns {*} Returns the entry value.
1993 function hashGet(key) {
1994 var data = this.__data__;
1996 var result = data[key];
1997 return result === HASH_UNDEFINED ? undefined : result;
1999 return hasOwnProperty.call(data, key) ? data[key] : undefined;
2003 * Checks if a hash value for `key` exists.
2008 * @param {string} key The key of the entry to check.
2009 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2011 function hashHas(key) {
2012 var data = this.__data__;
2013 return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
2017 * Sets the hash `key` to `value`.
2022 * @param {string} key The key of the value to set.
2023 * @param {*} value The value to set.
2024 * @returns {Object} Returns the hash instance.
2026 function hashSet(key, value) {
2027 var data = this.__data__;
2028 this.size += this.has(key) ? 0 : 1;
2029 data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
2033 // Add methods to `Hash`.
2034 Hash.prototype.clear = hashClear;
2035 Hash.prototype['delete'] = hashDelete;
2036 Hash.prototype.get = hashGet;
2037 Hash.prototype.has = hashHas;
2038 Hash.prototype.set = hashSet;
2040 /*------------------------------------------------------------------------*/
2043 * Creates an list cache object.
2047 * @param {Array} [entries] The key-value pairs to cache.
2049 function ListCache(entries) {
2051 length = entries == null ? 0 : entries.length;
2054 while (++index < length) {
2055 var entry = entries[index];
2056 this.set(entry[0], entry[1]);
2061 * Removes all key-value entries from the list cache.
2065 * @memberOf ListCache
2067 function listCacheClear() {
2073 * Removes `key` and its value from the list cache.
2077 * @memberOf ListCache
2078 * @param {string} key The key of the value to remove.
2079 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2081 function listCacheDelete(key) {
2082 var data = this.__data__,
2083 index = assocIndexOf(data, key);
2088 var lastIndex = data.length - 1;
2089 if (index == lastIndex) {
2092 splice.call(data, index, 1);
2099 * Gets the list cache value for `key`.
2103 * @memberOf ListCache
2104 * @param {string} key The key of the value to get.
2105 * @returns {*} Returns the entry value.
2107 function listCacheGet(key) {
2108 var data = this.__data__,
2109 index = assocIndexOf(data, key);
2111 return index < 0 ? undefined : data[index][1];
2115 * Checks if a list cache value for `key` exists.
2119 * @memberOf ListCache
2120 * @param {string} key The key of the entry to check.
2121 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2123 function listCacheHas(key) {
2124 return assocIndexOf(this.__data__, key) > -1;
2128 * Sets the list cache `key` to `value`.
2132 * @memberOf ListCache
2133 * @param {string} key The key of the value to set.
2134 * @param {*} value The value to set.
2135 * @returns {Object} Returns the list cache instance.
2137 function listCacheSet(key, value) {
2138 var data = this.__data__,
2139 index = assocIndexOf(data, key);
2143 data.push([key, value]);
2145 data[index][1] = value;
2150 // Add methods to `ListCache`.
2151 ListCache.prototype.clear = listCacheClear;
2152 ListCache.prototype['delete'] = listCacheDelete;
2153 ListCache.prototype.get = listCacheGet;
2154 ListCache.prototype.has = listCacheHas;
2155 ListCache.prototype.set = listCacheSet;
2157 /*------------------------------------------------------------------------*/
2160 * Creates a map cache object to store key-value pairs.
2164 * @param {Array} [entries] The key-value pairs to cache.
2166 function MapCache(entries) {
2168 length = entries == null ? 0 : entries.length;
2171 while (++index < length) {
2172 var entry = entries[index];
2173 this.set(entry[0], entry[1]);
2178 * Removes all key-value entries from the map.
2182 * @memberOf MapCache
2184 function mapCacheClear() {
2188 'map': new (Map || ListCache),
2194 * Removes `key` and its value from the map.
2198 * @memberOf MapCache
2199 * @param {string} key The key of the value to remove.
2200 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2202 function mapCacheDelete(key) {
2203 var result = getMapData(this, key)['delete'](key);
2204 this.size -= result ? 1 : 0;
2209 * Gets the map value for `key`.
2213 * @memberOf MapCache
2214 * @param {string} key The key of the value to get.
2215 * @returns {*} Returns the entry value.
2217 function mapCacheGet(key) {
2218 return getMapData(this, key).get(key);
2222 * Checks if a map value for `key` exists.
2226 * @memberOf MapCache
2227 * @param {string} key The key of the entry to check.
2228 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2230 function mapCacheHas(key) {
2231 return getMapData(this, key).has(key);
2235 * Sets the map `key` to `value`.
2239 * @memberOf MapCache
2240 * @param {string} key The key of the value to set.
2241 * @param {*} value The value to set.
2242 * @returns {Object} Returns the map cache instance.
2244 function mapCacheSet(key, value) {
2245 var data = getMapData(this, key),
2248 data.set(key, value);
2249 this.size += data.size == size ? 0 : 1;
2253 // Add methods to `MapCache`.
2254 MapCache.prototype.clear = mapCacheClear;
2255 MapCache.prototype['delete'] = mapCacheDelete;
2256 MapCache.prototype.get = mapCacheGet;
2257 MapCache.prototype.has = mapCacheHas;
2258 MapCache.prototype.set = mapCacheSet;
2260 /*------------------------------------------------------------------------*/
2264 * Creates an array cache object to store unique values.
2268 * @param {Array} [values] The values to cache.
2270 function SetCache(values) {
2272 length = values == null ? 0 : values.length;
2274 this.__data__ = new MapCache;
2275 while (++index < length) {
2276 this.add(values[index]);
2281 * Adds `value` to the array cache.
2285 * @memberOf SetCache
2287 * @param {*} value The value to cache.
2288 * @returns {Object} Returns the cache instance.
2290 function setCacheAdd(value) {
2291 this.__data__.set(value, HASH_UNDEFINED);
2296 * Checks if `value` is in the array cache.
2300 * @memberOf SetCache
2301 * @param {*} value The value to search for.
2302 * @returns {number} Returns `true` if `value` is found, else `false`.
2304 function setCacheHas(value) {
2305 return this.__data__.has(value);
2308 // Add methods to `SetCache`.
2309 SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
2310 SetCache.prototype.has = setCacheHas;
2312 /*------------------------------------------------------------------------*/
2315 * Creates a stack cache object to store key-value pairs.
2319 * @param {Array} [entries] The key-value pairs to cache.
2321 function Stack(entries) {
2322 var data = this.__data__ = new ListCache(entries);
2323 this.size = data.size;
2327 * Removes all key-value entries from the stack.
2333 function stackClear() {
2334 this.__data__ = new ListCache;
2339 * Removes `key` and its value from the stack.
2344 * @param {string} key The key of the value to remove.
2345 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2347 function stackDelete(key) {
2348 var data = this.__data__,
2349 result = data['delete'](key);
2351 this.size = data.size;
2356 * Gets the stack value for `key`.
2361 * @param {string} key The key of the value to get.
2362 * @returns {*} Returns the entry value.
2364 function stackGet(key) {
2365 return this.__data__.get(key);
2369 * Checks if a stack value for `key` exists.
2374 * @param {string} key The key of the entry to check.
2375 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2377 function stackHas(key) {
2378 return this.__data__.has(key);
2382 * Sets the stack `key` to `value`.
2387 * @param {string} key The key of the value to set.
2388 * @param {*} value The value to set.
2389 * @returns {Object} Returns the stack cache instance.
2391 function stackSet(key, value) {
2392 var data = this.__data__;
2393 if (data instanceof ListCache) {
2394 var pairs = data.__data__;
2395 if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2396 pairs.push([key, value]);
2397 this.size = ++data.size;
2400 data = this.__data__ = new MapCache(pairs);
2402 data.set(key, value);
2403 this.size = data.size;
2407 // Add methods to `Stack`.
2408 Stack.prototype.clear = stackClear;
2409 Stack.prototype['delete'] = stackDelete;
2410 Stack.prototype.get = stackGet;
2411 Stack.prototype.has = stackHas;
2412 Stack.prototype.set = stackSet;
2414 /*------------------------------------------------------------------------*/
2417 * Creates an array of the enumerable property names of the array-like `value`.
2420 * @param {*} value The value to query.
2421 * @param {boolean} inherited Specify returning inherited property names.
2422 * @returns {Array} Returns the array of property names.
2424 function arrayLikeKeys(value, inherited) {
2425 var isArr = isArray(value),
2426 isArg = !isArr && isArguments(value),
2427 isBuff = !isArr && !isArg && isBuffer(value),
2428 isType = !isArr && !isArg && !isBuff && isTypedArray(value),
2429 skipIndexes = isArr || isArg || isBuff || isType,
2430 result = skipIndexes ? baseTimes(value.length, String) : [],
2431 length = result.length;
2433 for (var key in value) {
2434 if ((inherited || hasOwnProperty.call(value, key)) &&
2436 // Safari 9 has enumerable `arguments.length` in strict mode.
2438 // Node.js 0.10 has enumerable non-index properties on buffers.
2439 (isBuff && (key == 'offset' || key == 'parent')) ||
2440 // PhantomJS 2 has enumerable non-index properties on typed arrays.
2441 (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
2442 // Skip index properties.
2443 isIndex(key, length)
2452 * A specialized version of `_.sample` for arrays.
2455 * @param {Array} array The array to sample.
2456 * @returns {*} Returns the random element.
2458 function arraySample(array) {
2459 var length = array.length;
2460 return length ? array[baseRandom(0, length - 1)] : undefined;
2464 * A specialized version of `_.sampleSize` for arrays.
2467 * @param {Array} array The array to sample.
2468 * @param {number} n The number of elements to sample.
2469 * @returns {Array} Returns the random elements.
2471 function arraySampleSize(array, n) {
2472 return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
2476 * A specialized version of `_.shuffle` for arrays.
2479 * @param {Array} array The array to shuffle.
2480 * @returns {Array} Returns the new shuffled array.
2482 function arrayShuffle(array) {
2483 return shuffleSelf(copyArray(array));
2487 * This function is like `assignValue` except that it doesn't assign
2488 * `undefined` values.
2491 * @param {Object} object The object to modify.
2492 * @param {string} key The key of the property to assign.
2493 * @param {*} value The value to assign.
2495 function assignMergeValue(object, key, value) {
2496 if ((value !== undefined && !eq(object[key], value)) ||
2497 (value === undefined && !(key in object))) {
2498 baseAssignValue(object, key, value);
2503 * Assigns `value` to `key` of `object` if the existing value is not equivalent
2504 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
2505 * for equality comparisons.
2508 * @param {Object} object The object to modify.
2509 * @param {string} key The key of the property to assign.
2510 * @param {*} value The value to assign.
2512 function assignValue(object, key, value) {
2513 var objValue = object[key];
2514 if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
2515 (value === undefined && !(key in object))) {
2516 baseAssignValue(object, key, value);
2521 * Gets the index at which the `key` is found in `array` of key-value pairs.
2524 * @param {Array} array The array to inspect.
2525 * @param {*} key The key to search for.
2526 * @returns {number} Returns the index of the matched value, else `-1`.
2528 function assocIndexOf(array, key) {
2529 var length = array.length;
2531 if (eq(array[length][0], key)) {
2539 * Aggregates elements of `collection` on `accumulator` with keys transformed
2540 * by `iteratee` and values set by `setter`.
2543 * @param {Array|Object} collection The collection to iterate over.
2544 * @param {Function} setter The function to set `accumulator` values.
2545 * @param {Function} iteratee The iteratee to transform keys.
2546 * @param {Object} accumulator The initial aggregated object.
2547 * @returns {Function} Returns `accumulator`.
2549 function baseAggregator(collection, setter, iteratee, accumulator) {
2550 baseEach(collection, function(value, key, collection) {
2551 setter(accumulator, value, iteratee(value), collection);
2557 * The base implementation of `_.assign` without support for multiple sources
2558 * or `customizer` functions.
2561 * @param {Object} object The destination object.
2562 * @param {Object} source The source object.
2563 * @returns {Object} Returns `object`.
2565 function baseAssign(object, source) {
2566 return object && copyObject(source, keys(source), object);
2570 * The base implementation of `_.assignIn` without support for multiple sources
2571 * or `customizer` functions.
2574 * @param {Object} object The destination object.
2575 * @param {Object} source The source object.
2576 * @returns {Object} Returns `object`.
2578 function baseAssignIn(object, source) {
2579 return object && copyObject(source, keysIn(source), object);
2583 * The base implementation of `assignValue` and `assignMergeValue` without
2587 * @param {Object} object The object to modify.
2588 * @param {string} key The key of the property to assign.
2589 * @param {*} value The value to assign.
2591 function baseAssignValue(object, key, value) {
2592 if (key == '__proto__' && defineProperty) {
2593 defineProperty(object, key, {
2594 'configurable': true,
2600 object[key] = value;
2605 * The base implementation of `_.at` without support for individual paths.
2608 * @param {Object} object The object to iterate over.
2609 * @param {string[]} paths The property paths to pick.
2610 * @returns {Array} Returns the picked elements.
2612 function baseAt(object, paths) {
2614 length = paths.length,
2615 result = Array(length),
2616 skip = object == null;
2618 while (++index < length) {
2619 result[index] = skip ? undefined : get(object, paths[index]);
2625 * The base implementation of `_.clamp` which doesn't coerce arguments.
2628 * @param {number} number The number to clamp.
2629 * @param {number} [lower] The lower bound.
2630 * @param {number} upper The upper bound.
2631 * @returns {number} Returns the clamped number.
2633 function baseClamp(number, lower, upper) {
2634 if (number === number) {
2635 if (upper !== undefined) {
2636 number = number <= upper ? number : upper;
2638 if (lower !== undefined) {
2639 number = number >= lower ? number : lower;
2646 * The base implementation of `_.clone` and `_.cloneDeep` which tracks
2647 * traversed objects.
2650 * @param {*} value The value to clone.
2651 * @param {boolean} bitmask The bitmask flags.
2653 * 2 - Flatten inherited properties
2655 * @param {Function} [customizer] The function to customize cloning.
2656 * @param {string} [key] The key of `value`.
2657 * @param {Object} [object] The parent object of `value`.
2658 * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
2659 * @returns {*} Returns the cloned value.
2661 function baseClone(value, bitmask, customizer, key, object, stack) {
2663 isDeep = bitmask & CLONE_DEEP_FLAG,
2664 isFlat = bitmask & CLONE_FLAT_FLAG,
2665 isFull = bitmask & CLONE_SYMBOLS_FLAG;
2668 result = object ? customizer(value, key, object, stack) : customizer(value);
2670 if (result !== undefined) {
2673 if (!isObject(value)) {
2676 var isArr = isArray(value);
2678 result = initCloneArray(value);
2680 return copyArray(value, result);
2683 var tag = getTag(value),
2684 isFunc = tag == funcTag || tag == genTag;
2686 if (isBuffer(value)) {
2687 return cloneBuffer(value, isDeep);
2689 if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
2690 result = (isFlat || isFunc) ? {} : initCloneObject(value);
2693 ? copySymbolsIn(value, baseAssignIn(result, value))
2694 : copySymbols(value, baseAssign(result, value));
2697 if (!cloneableTags[tag]) {
2698 return object ? value : {};
2700 result = initCloneByTag(value, tag, baseClone, isDeep);
2703 // Check for circular references and return its corresponding clone.
2704 stack || (stack = new Stack);
2705 var stacked = stack.get(value);
2709 stack.set(value, result);
2711 var keysFunc = isFull
2712 ? (isFlat ? getAllKeysIn : getAllKeys)
2713 : (isFlat ? keysIn : keys);
2715 var props = isArr ? undefined : keysFunc(value);
2716 arrayEach(props || value, function(subValue, key) {
2719 subValue = value[key];
2721 // Recursively populate clone (susceptible to call stack limits).
2722 assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
2728 * The base implementation of `_.conforms` which doesn't clone `source`.
2731 * @param {Object} source The object of property predicates to conform to.
2732 * @returns {Function} Returns the new spec function.
2734 function baseConforms(source) {
2735 var props = keys(source);
2736 return function(object) {
2737 return baseConformsTo(object, source, props);
2742 * The base implementation of `_.conformsTo` which accepts `props` to check.
2745 * @param {Object} object The object to inspect.
2746 * @param {Object} source The object of property predicates to conform to.
2747 * @returns {boolean} Returns `true` if `object` conforms, else `false`.
2749 function baseConformsTo(object, source, props) {
2750 var length = props.length;
2751 if (object == null) {
2754 object = Object(object);
2756 var key = props[length],
2757 predicate = source[key],
2758 value = object[key];
2760 if ((value === undefined && !(key in object)) || !predicate(value)) {
2768 * The base implementation of `_.delay` and `_.defer` which accepts `args`
2769 * to provide to `func`.
2772 * @param {Function} func The function to delay.
2773 * @param {number} wait The number of milliseconds to delay invocation.
2774 * @param {Array} args The arguments to provide to `func`.
2775 * @returns {number|Object} Returns the timer id or timeout object.
2777 function baseDelay(func, wait, args) {
2778 if (typeof func != 'function') {
2779 throw new TypeError(FUNC_ERROR_TEXT);
2781 return setTimeout(function() { func.apply(undefined, args); }, wait);
2785 * The base implementation of methods like `_.difference` without support
2786 * for excluding multiple arrays or iteratee shorthands.
2789 * @param {Array} array The array to inspect.
2790 * @param {Array} values The values to exclude.
2791 * @param {Function} [iteratee] The iteratee invoked per element.
2792 * @param {Function} [comparator] The comparator invoked per element.
2793 * @returns {Array} Returns the new array of filtered values.
2795 function baseDifference(array, values, iteratee, comparator) {
2797 includes = arrayIncludes,
2799 length = array.length,
2801 valuesLength = values.length;
2807 values = arrayMap(values, baseUnary(iteratee));
2810 includes = arrayIncludesWith;
2813 else if (values.length >= LARGE_ARRAY_SIZE) {
2814 includes = cacheHas;
2816 values = new SetCache(values);
2819 while (++index < length) {
2820 var value = array[index],
2821 computed = iteratee == null ? value : iteratee(value);
2823 value = (comparator || value !== 0) ? value : 0;
2824 if (isCommon && computed === computed) {
2825 var valuesIndex = valuesLength;
2826 while (valuesIndex--) {
2827 if (values[valuesIndex] === computed) {
2833 else if (!includes(values, computed, comparator)) {
2841 * The base implementation of `_.forEach` without support for iteratee shorthands.
2844 * @param {Array|Object} collection The collection to iterate over.
2845 * @param {Function} iteratee The function invoked per iteration.
2846 * @returns {Array|Object} Returns `collection`.
2848 var baseEach = createBaseEach(baseForOwn);
2851 * The base implementation of `_.forEachRight` without support for iteratee shorthands.
2854 * @param {Array|Object} collection The collection to iterate over.
2855 * @param {Function} iteratee The function invoked per iteration.
2856 * @returns {Array|Object} Returns `collection`.
2858 var baseEachRight = createBaseEach(baseForOwnRight, true);
2861 * The base implementation of `_.every` without support for iteratee shorthands.
2864 * @param {Array|Object} collection The collection to iterate over.
2865 * @param {Function} predicate The function invoked per iteration.
2866 * @returns {boolean} Returns `true` if all elements pass the predicate check,
2869 function baseEvery(collection, predicate) {
2871 baseEach(collection, function(value, index, collection) {
2872 result = !!predicate(value, index, collection);
2879 * The base implementation of methods like `_.max` and `_.min` which accepts a
2880 * `comparator` to determine the extremum value.
2883 * @param {Array} array The array to iterate over.
2884 * @param {Function} iteratee The iteratee invoked per iteration.
2885 * @param {Function} comparator The comparator used to compare values.
2886 * @returns {*} Returns the extremum value.
2888 function baseExtremum(array, iteratee, comparator) {
2890 length = array.length;
2892 while (++index < length) {
2893 var value = array[index],
2894 current = iteratee(value);
2896 if (current != null && (computed === undefined
2897 ? (current === current && !isSymbol(current))
2898 : comparator(current, computed)
2900 var computed = current,
2908 * The base implementation of `_.fill` without an iteratee call guard.
2911 * @param {Array} array The array to fill.
2912 * @param {*} value The value to fill `array` with.
2913 * @param {number} [start=0] The start position.
2914 * @param {number} [end=array.length] The end position.
2915 * @returns {Array} Returns `array`.
2917 function baseFill(array, value, start, end) {
2918 var length = array.length;
2920 start = toInteger(start);
2922 start = -start > length ? 0 : (length + start);
2924 end = (end === undefined || end > length) ? length : toInteger(end);
2928 end = start > end ? 0 : toLength(end);
2929 while (start < end) {
2930 array[start++] = value;
2936 * The base implementation of `_.filter` without support for iteratee shorthands.
2939 * @param {Array|Object} collection The collection to iterate over.
2940 * @param {Function} predicate The function invoked per iteration.
2941 * @returns {Array} Returns the new filtered array.
2943 function baseFilter(collection, predicate) {
2945 baseEach(collection, function(value, index, collection) {
2946 if (predicate(value, index, collection)) {
2954 * The base implementation of `_.flatten` with support for restricting flattening.
2957 * @param {Array} array The array to flatten.
2958 * @param {number} depth The maximum recursion depth.
2959 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
2960 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
2961 * @param {Array} [result=[]] The initial result value.
2962 * @returns {Array} Returns the new flattened array.
2964 function baseFlatten(array, depth, predicate, isStrict, result) {
2966 length = array.length;
2968 predicate || (predicate = isFlattenable);
2969 result || (result = []);
2971 while (++index < length) {
2972 var value = array[index];
2973 if (depth > 0 && predicate(value)) {
2975 // Recursively flatten arrays (susceptible to call stack limits).
2976 baseFlatten(value, depth - 1, predicate, isStrict, result);
2978 arrayPush(result, value);
2980 } else if (!isStrict) {
2981 result[result.length] = value;
2988 * The base implementation of `baseForOwn` which iterates over `object`
2989 * properties returned by `keysFunc` and invokes `iteratee` for each property.
2990 * Iteratee functions may exit iteration early by explicitly returning `false`.
2993 * @param {Object} object The object to iterate over.
2994 * @param {Function} iteratee The function invoked per iteration.
2995 * @param {Function} keysFunc The function to get the keys of `object`.
2996 * @returns {Object} Returns `object`.
2998 var baseFor = createBaseFor();
3001 * This function is like `baseFor` except that it iterates over properties
3002 * in the opposite order.
3005 * @param {Object} object The object to iterate over.
3006 * @param {Function} iteratee The function invoked per iteration.
3007 * @param {Function} keysFunc The function to get the keys of `object`.
3008 * @returns {Object} Returns `object`.
3010 var baseForRight = createBaseFor(true);
3013 * The base implementation of `_.forOwn` without support for iteratee shorthands.
3016 * @param {Object} object The object to iterate over.
3017 * @param {Function} iteratee The function invoked per iteration.
3018 * @returns {Object} Returns `object`.
3020 function baseForOwn(object, iteratee) {
3021 return object && baseFor(object, iteratee, keys);
3025 * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
3028 * @param {Object} object The object to iterate over.
3029 * @param {Function} iteratee The function invoked per iteration.
3030 * @returns {Object} Returns `object`.
3032 function baseForOwnRight(object, iteratee) {
3033 return object && baseForRight(object, iteratee, keys);
3037 * The base implementation of `_.functions` which creates an array of
3038 * `object` function property names filtered from `props`.
3041 * @param {Object} object The object to inspect.
3042 * @param {Array} props The property names to filter.
3043 * @returns {Array} Returns the function names.
3045 function baseFunctions(object, props) {
3046 return arrayFilter(props, function(key) {
3047 return isFunction(object[key]);
3052 * The base implementation of `_.get` without support for default values.
3055 * @param {Object} object The object to query.
3056 * @param {Array|string} path The path of the property to get.
3057 * @returns {*} Returns the resolved value.
3059 function baseGet(object, path) {
3060 path = castPath(path, object);
3063 length = path.length;
3065 while (object != null && index < length) {
3066 object = object[toKey(path[index++])];
3068 return (index && index == length) ? object : undefined;
3072 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
3073 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
3074 * symbols of `object`.
3077 * @param {Object} object The object to query.
3078 * @param {Function} keysFunc The function to get the keys of `object`.
3079 * @param {Function} symbolsFunc The function to get the symbols of `object`.
3080 * @returns {Array} Returns the array of property names and symbols.
3082 function baseGetAllKeys(object, keysFunc, symbolsFunc) {
3083 var result = keysFunc(object);
3084 return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
3088 * The base implementation of `getTag` without fallbacks for buggy environments.
3091 * @param {*} value The value to query.
3092 * @returns {string} Returns the `toStringTag`.
3094 function baseGetTag(value) {
3095 if (value == null) {
3096 return value === undefined ? undefinedTag : nullTag;
3098 return (symToStringTag && symToStringTag in Object(value))
3100 : objectToString(value);
3104 * The base implementation of `_.gt` which doesn't coerce arguments.
3107 * @param {*} value The value to compare.
3108 * @param {*} other The other value to compare.
3109 * @returns {boolean} Returns `true` if `value` is greater than `other`,
3112 function baseGt(value, other) {
3113 return value > other;
3117 * The base implementation of `_.has` without support for deep paths.
3120 * @param {Object} [object] The object to query.
3121 * @param {Array|string} key The key to check.
3122 * @returns {boolean} Returns `true` if `key` exists, else `false`.
3124 function baseHas(object, key) {
3125 return object != null && hasOwnProperty.call(object, key);
3129 * The base implementation of `_.hasIn` without support for deep paths.
3132 * @param {Object} [object] The object to query.
3133 * @param {Array|string} key The key to check.
3134 * @returns {boolean} Returns `true` if `key` exists, else `false`.
3136 function baseHasIn(object, key) {
3137 return object != null && key in Object(object);
3141 * The base implementation of `_.inRange` which doesn't coerce arguments.
3144 * @param {number} number The number to check.
3145 * @param {number} start The start of the range.
3146 * @param {number} end The end of the range.
3147 * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
3149 function baseInRange(number, start, end) {
3150 return number >= nativeMin(start, end) && number < nativeMax(start, end);
3154 * The base implementation of methods like `_.intersection`, without support
3155 * for iteratee shorthands, that accepts an array of arrays to inspect.
3158 * @param {Array} arrays The arrays to inspect.
3159 * @param {Function} [iteratee] The iteratee invoked per element.
3160 * @param {Function} [comparator] The comparator invoked per element.
3161 * @returns {Array} Returns the new array of shared values.
3163 function baseIntersection(arrays, iteratee, comparator) {
3164 var includes = comparator ? arrayIncludesWith : arrayIncludes,
3165 length = arrays[0].length,
3166 othLength = arrays.length,
3167 othIndex = othLength,
3168 caches = Array(othLength),
3169 maxLength = Infinity,
3172 while (othIndex--) {
3173 var array = arrays[othIndex];
3174 if (othIndex && iteratee) {
3175 array = arrayMap(array, baseUnary(iteratee));
3177 maxLength = nativeMin(array.length, maxLength);
3178 caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
3179 ? new SetCache(othIndex && array)
3188 while (++index < length && result.length < maxLength) {
3189 var value = array[index],
3190 computed = iteratee ? iteratee(value) : value;
3192 value = (comparator || value !== 0) ? value : 0;
3194 ? cacheHas(seen, computed)
3195 : includes(result, computed, comparator)
3197 othIndex = othLength;
3198 while (--othIndex) {
3199 var cache = caches[othIndex];
3201 ? cacheHas(cache, computed)
3202 : includes(arrays[othIndex], computed, comparator))
3208 seen.push(computed);
3217 * The base implementation of `_.invert` and `_.invertBy` which inverts
3218 * `object` with values transformed by `iteratee` and set by `setter`.
3221 * @param {Object} object The object to iterate over.
3222 * @param {Function} setter The function to set `accumulator` values.
3223 * @param {Function} iteratee The iteratee to transform values.
3224 * @param {Object} accumulator The initial inverted object.
3225 * @returns {Function} Returns `accumulator`.
3227 function baseInverter(object, setter, iteratee, accumulator) {
3228 baseForOwn(object, function(value, key, object) {
3229 setter(accumulator, iteratee(value), key, object);
3235 * The base implementation of `_.invoke` without support for individual
3239 * @param {Object} object The object to query.
3240 * @param {Array|string} path The path of the method to invoke.
3241 * @param {Array} args The arguments to invoke the method with.
3242 * @returns {*} Returns the result of the invoked method.
3244 function baseInvoke(object, path, args) {
3245 path = castPath(path, object);
3246 object = parent(object, path);
3247 var func = object == null ? object : object[toKey(last(path))];
3248 return func == null ? undefined : apply(func, object, args);
3252 * The base implementation of `_.isArguments`.
3255 * @param {*} value The value to check.
3256 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3258 function baseIsArguments(value) {
3259 return isObjectLike(value) && baseGetTag(value) == argsTag;
3263 * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
3266 * @param {*} value The value to check.
3267 * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
3269 function baseIsArrayBuffer(value) {
3270 return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
3274 * The base implementation of `_.isDate` without Node.js optimizations.
3277 * @param {*} value The value to check.
3278 * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
3280 function baseIsDate(value) {
3281 return isObjectLike(value) && baseGetTag(value) == dateTag;
3285 * The base implementation of `_.isEqual` which supports partial comparisons
3286 * and tracks traversed objects.
3289 * @param {*} value The value to compare.
3290 * @param {*} other The other value to compare.
3291 * @param {boolean} bitmask The bitmask flags.
3292 * 1 - Unordered comparison
3293 * 2 - Partial comparison
3294 * @param {Function} [customizer] The function to customize comparisons.
3295 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
3296 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3298 function baseIsEqual(value, other, bitmask, customizer, stack) {
3299 if (value === other) {
3302 if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
3303 return value !== value && other !== other;
3305 return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
3309 * A specialized version of `baseIsEqual` for arrays and objects which performs
3310 * deep comparisons and tracks traversed objects enabling objects with circular
3311 * references to be compared.
3314 * @param {Object} object The object to compare.
3315 * @param {Object} other The other object to compare.
3316 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3317 * @param {Function} customizer The function to customize comparisons.
3318 * @param {Function} equalFunc The function to determine equivalents of values.
3319 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
3320 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
3322 function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
3323 var objIsArr = isArray(object),
3324 othIsArr = isArray(other),
3325 objTag = objIsArr ? arrayTag : getTag(object),
3326 othTag = othIsArr ? arrayTag : getTag(other);
3328 objTag = objTag == argsTag ? objectTag : objTag;
3329 othTag = othTag == argsTag ? objectTag : othTag;
3331 var objIsObj = objTag == objectTag,
3332 othIsObj = othTag == objectTag,
3333 isSameTag = objTag == othTag;
3335 if (isSameTag && isBuffer(object)) {
3336 if (!isBuffer(other)) {
3342 if (isSameTag && !objIsObj) {
3343 stack || (stack = new Stack);
3344 return (objIsArr || isTypedArray(object))
3345 ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
3346 : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
3348 if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
3349 var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
3350 othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
3352 if (objIsWrapped || othIsWrapped) {
3353 var objUnwrapped = objIsWrapped ? object.value() : object,
3354 othUnwrapped = othIsWrapped ? other.value() : other;
3356 stack || (stack = new Stack);
3357 return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
3363 stack || (stack = new Stack);
3364 return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
3368 * The base implementation of `_.isMap` without Node.js optimizations.
3371 * @param {*} value The value to check.
3372 * @returns {boolean} Returns `true` if `value` is a map, else `false`.
3374 function baseIsMap(value) {
3375 return isObjectLike(value) && getTag(value) == mapTag;
3379 * The base implementation of `_.isMatch` without support for iteratee shorthands.
3382 * @param {Object} object The object to inspect.
3383 * @param {Object} source The object of property values to match.
3384 * @param {Array} matchData The property names, values, and compare flags to match.
3385 * @param {Function} [customizer] The function to customize comparisons.
3386 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
3388 function baseIsMatch(object, source, matchData, customizer) {
3389 var index = matchData.length,
3391 noCustomizer = !customizer;
3393 if (object == null) {
3396 object = Object(object);
3398 var data = matchData[index];
3399 if ((noCustomizer && data[2])
3400 ? data[1] !== object[data[0]]
3401 : !(data[0] in object)
3406 while (++index < length) {
3407 data = matchData[index];
3409 objValue = object[key],
3412 if (noCustomizer && data[2]) {
3413 if (objValue === undefined && !(key in object)) {
3417 var stack = new Stack;
3419 var result = customizer(objValue, srcValue, key, object, source, stack);
3421 if (!(result === undefined
3422 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
3433 * The base implementation of `_.isNative` without bad shim checks.
3436 * @param {*} value The value to check.
3437 * @returns {boolean} Returns `true` if `value` is a native function,
3440 function baseIsNative(value) {
3441 if (!isObject(value) || isMasked(value)) {
3444 var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
3445 return pattern.test(toSource(value));
3449 * The base implementation of `_.isRegExp` without Node.js optimizations.
3452 * @param {*} value The value to check.
3453 * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
3455 function baseIsRegExp(value) {
3456 return isObjectLike(value) && baseGetTag(value) == regexpTag;
3460 * The base implementation of `_.isSet` without Node.js optimizations.
3463 * @param {*} value The value to check.
3464 * @returns {boolean} Returns `true` if `value` is a set, else `false`.
3466 function baseIsSet(value) {
3467 return isObjectLike(value) && getTag(value) == setTag;
3471 * The base implementation of `_.isTypedArray` without Node.js optimizations.
3474 * @param {*} value The value to check.
3475 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3477 function baseIsTypedArray(value) {
3478 return isObjectLike(value) &&
3479 isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
3483 * The base implementation of `_.iteratee`.
3486 * @param {*} [value=_.identity] The value to convert to an iteratee.
3487 * @returns {Function} Returns the iteratee.
3489 function baseIteratee(value) {
3490 // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
3491 // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
3492 if (typeof value == 'function') {
3495 if (value == null) {
3498 if (typeof value == 'object') {
3499 return isArray(value)
3500 ? baseMatchesProperty(value[0], value[1])
3501 : baseMatches(value);
3503 return property(value);
3507 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
3510 * @param {Object} object The object to query.
3511 * @returns {Array} Returns the array of property names.
3513 function baseKeys(object) {
3514 if (!isPrototype(object)) {
3515 return nativeKeys(object);
3518 for (var key in Object(object)) {
3519 if (hasOwnProperty.call(object, key) && key != 'constructor') {
3527 * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
3530 * @param {Object} object The object to query.
3531 * @returns {Array} Returns the array of property names.
3533 function baseKeysIn(object) {
3534 if (!isObject(object)) {
3535 return nativeKeysIn(object);
3537 var isProto = isPrototype(object),
3540 for (var key in object) {
3541 if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
3549 * The base implementation of `_.lt` which doesn't coerce arguments.
3552 * @param {*} value The value to compare.
3553 * @param {*} other The other value to compare.
3554 * @returns {boolean} Returns `true` if `value` is less than `other`,
3557 function baseLt(value, other) {
3558 return value < other;
3562 * The base implementation of `_.map` without support for iteratee shorthands.
3565 * @param {Array|Object} collection The collection to iterate over.
3566 * @param {Function} iteratee The function invoked per iteration.
3567 * @returns {Array} Returns the new mapped array.
3569 function baseMap(collection, iteratee) {
3571 result = isArrayLike(collection) ? Array(collection.length) : [];
3573 baseEach(collection, function(value, key, collection) {
3574 result[++index] = iteratee(value, key, collection);
3580 * The base implementation of `_.matches` which doesn't clone `source`.
3583 * @param {Object} source The object of property values to match.
3584 * @returns {Function} Returns the new spec function.
3586 function baseMatches(source) {
3587 var matchData = getMatchData(source);
3588 if (matchData.length == 1 && matchData[0][2]) {
3589 return matchesStrictComparable(matchData[0][0], matchData[0][1]);
3591 return function(object) {
3592 return object === source || baseIsMatch(object, source, matchData);
3597 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
3600 * @param {string} path The path of the property to get.
3601 * @param {*} srcValue The value to match.
3602 * @returns {Function} Returns the new spec function.
3604 function baseMatchesProperty(path, srcValue) {
3605 if (isKey(path) && isStrictComparable(srcValue)) {
3606 return matchesStrictComparable(toKey(path), srcValue);
3608 return function(object) {
3609 var objValue = get(object, path);
3610 return (objValue === undefined && objValue === srcValue)
3611 ? hasIn(object, path)
3612 : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
3617 * The base implementation of `_.merge` without support for multiple sources.
3620 * @param {Object} object The destination object.
3621 * @param {Object} source The source object.
3622 * @param {number} srcIndex The index of `source`.
3623 * @param {Function} [customizer] The function to customize merged values.
3624 * @param {Object} [stack] Tracks traversed source values and their merged
3627 function baseMerge(object, source, srcIndex, customizer, stack) {
3628 if (object === source) {
3631 baseFor(source, function(srcValue, key) {
3632 if (isObject(srcValue)) {
3633 stack || (stack = new Stack);
3634 baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
3637 var newValue = customizer
3638 ? customizer(object[key], srcValue, (key + ''), object, source, stack)
3641 if (newValue === undefined) {
3642 newValue = srcValue;
3644 assignMergeValue(object, key, newValue);
3650 * A specialized version of `baseMerge` for arrays and objects which performs
3651 * deep merges and tracks traversed objects enabling objects with circular
3652 * references to be merged.
3655 * @param {Object} object The destination object.
3656 * @param {Object} source The source object.
3657 * @param {string} key The key of the value to merge.
3658 * @param {number} srcIndex The index of `source`.
3659 * @param {Function} mergeFunc The function to merge values.
3660 * @param {Function} [customizer] The function to customize assigned values.
3661 * @param {Object} [stack] Tracks traversed source values and their merged
3664 function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
3665 var objValue = object[key],
3666 srcValue = source[key],
3667 stacked = stack.get(srcValue);
3670 assignMergeValue(object, key, stacked);
3673 var newValue = customizer
3674 ? customizer(objValue, srcValue, (key + ''), object, source, stack)
3677 var isCommon = newValue === undefined;
3680 var isArr = isArray(srcValue),
3681 isBuff = !isArr && isBuffer(srcValue),
3682 isTyped = !isArr && !isBuff && isTypedArray(srcValue);
3684 newValue = srcValue;
3685 if (isArr || isBuff || isTyped) {
3686 if (isArray(objValue)) {
3687 newValue = objValue;
3689 else if (isArrayLikeObject(objValue)) {
3690 newValue = copyArray(objValue);
3694 newValue = cloneBuffer(srcValue, true);
3698 newValue = cloneTypedArray(srcValue, true);
3704 else if (isPlainObject(srcValue) || isArguments(srcValue)) {
3705 newValue = objValue;
3706 if (isArguments(objValue)) {
3707 newValue = toPlainObject(objValue);
3709 else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
3710 newValue = initCloneObject(srcValue);
3718 // Recursively merge objects and arrays (susceptible to call stack limits).
3719 stack.set(srcValue, newValue);
3720 mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
3721 stack['delete'](srcValue);
3723 assignMergeValue(object, key, newValue);
3727 * The base implementation of `_.nth` which doesn't coerce arguments.
3730 * @param {Array} array The array to query.
3731 * @param {number} n The index of the element to return.
3732 * @returns {*} Returns the nth element of `array`.
3734 function baseNth(array, n) {
3735 var length = array.length;
3739 n += n < 0 ? length : 0;
3740 return isIndex(n, length) ? array[n] : undefined;
3744 * The base implementation of `_.orderBy` without param guards.
3747 * @param {Array|Object} collection The collection to iterate over.
3748 * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
3749 * @param {string[]} orders The sort orders of `iteratees`.
3750 * @returns {Array} Returns the new sorted array.
3752 function baseOrderBy(collection, iteratees, orders) {
3754 iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));
3756 var result = baseMap(collection, function(value, key, collection) {
3757 var criteria = arrayMap(iteratees, function(iteratee) {
3758 return iteratee(value);
3760 return { 'criteria': criteria, 'index': ++index, 'value': value };
3763 return baseSortBy(result, function(object, other) {
3764 return compareMultiple(object, other, orders);
3769 * The base implementation of `_.pick` without support for individual
3770 * property identifiers.
3773 * @param {Object} object The source object.
3774 * @param {string[]} paths The property paths to pick.
3775 * @returns {Object} Returns the new object.
3777 function basePick(object, paths) {
3778 return basePickBy(object, paths, function(value, path) {
3779 return hasIn(object, path);
3784 * The base implementation of `_.pickBy` without support for iteratee shorthands.
3787 * @param {Object} object The source object.
3788 * @param {string[]} paths The property paths to pick.
3789 * @param {Function} predicate The function invoked per property.
3790 * @returns {Object} Returns the new object.
3792 function basePickBy(object, paths, predicate) {
3794 length = paths.length,
3797 while (++index < length) {
3798 var path = paths[index],
3799 value = baseGet(object, path);
3801 if (predicate(value, path)) {
3802 baseSet(result, castPath(path, object), value);
3809 * A specialized version of `baseProperty` which supports deep paths.
3812 * @param {Array|string} path The path of the property to get.
3813 * @returns {Function} Returns the new accessor function.
3815 function basePropertyDeep(path) {
3816 return function(object) {
3817 return baseGet(object, path);
3822 * The base implementation of `_.pullAllBy` without support for iteratee
3826 * @param {Array} array The array to modify.
3827 * @param {Array} values The values to remove.
3828 * @param {Function} [iteratee] The iteratee invoked per element.
3829 * @param {Function} [comparator] The comparator invoked per element.
3830 * @returns {Array} Returns `array`.
3832 function basePullAll(array, values, iteratee, comparator) {
3833 var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
3835 length = values.length,
3838 if (array === values) {
3839 values = copyArray(values);
3842 seen = arrayMap(array, baseUnary(iteratee));
3844 while (++index < length) {
3846 value = values[index],
3847 computed = iteratee ? iteratee(value) : value;
3849 while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
3850 if (seen !== array) {
3851 splice.call(seen, fromIndex, 1);
3853 splice.call(array, fromIndex, 1);
3860 * The base implementation of `_.pullAt` without support for individual
3861 * indexes or capturing the removed elements.
3864 * @param {Array} array The array to modify.
3865 * @param {number[]} indexes The indexes of elements to remove.
3866 * @returns {Array} Returns `array`.
3868 function basePullAt(array, indexes) {
3869 var length = array ? indexes.length : 0,
3870 lastIndex = length - 1;
3873 var index = indexes[length];
3874 if (length == lastIndex || index !== previous) {
3875 var previous = index;
3876 if (isIndex(index)) {
3877 splice.call(array, index, 1);
3879 baseUnset(array, index);
3887 * The base implementation of `_.random` without support for returning
3888 * floating-point numbers.
3891 * @param {number} lower The lower bound.
3892 * @param {number} upper The upper bound.
3893 * @returns {number} Returns the random number.
3895 function baseRandom(lower, upper) {
3896 return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
3900 * The base implementation of `_.range` and `_.rangeRight` which doesn't
3904 * @param {number} start The start of the range.
3905 * @param {number} end The end of the range.
3906 * @param {number} step The value to increment or decrement by.
3907 * @param {boolean} [fromRight] Specify iterating from right to left.
3908 * @returns {Array} Returns the range of numbers.
3910 function baseRange(start, end, step, fromRight) {
3912 length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
3913 result = Array(length);
3916 result[fromRight ? length : ++index] = start;
3923 * The base implementation of `_.repeat` which doesn't coerce arguments.
3926 * @param {string} string The string to repeat.
3927 * @param {number} n The number of times to repeat the string.
3928 * @returns {string} Returns the repeated string.
3930 function baseRepeat(string, n) {
3932 if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
3935 // Leverage the exponentiation by squaring algorithm for a faster repeat.
3936 // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
3941 n = nativeFloor(n / 2);
3951 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
3954 * @param {Function} func The function to apply a rest parameter to.
3955 * @param {number} [start=func.length-1] The start position of the rest parameter.
3956 * @returns {Function} Returns the new function.
3958 function baseRest(func, start) {
3959 return setToString(overRest(func, start, identity), func + '');
3963 * The base implementation of `_.sample`.
3966 * @param {Array|Object} collection The collection to sample.
3967 * @returns {*} Returns the random element.
3969 function baseSample(collection) {
3970 return arraySample(values(collection));
3974 * The base implementation of `_.sampleSize` without param guards.
3977 * @param {Array|Object} collection The collection to sample.
3978 * @param {number} n The number of elements to sample.
3979 * @returns {Array} Returns the random elements.
3981 function baseSampleSize(collection, n) {
3982 var array = values(collection);
3983 return shuffleSelf(array, baseClamp(n, 0, array.length));
3987 * The base implementation of `_.set`.
3990 * @param {Object} object The object to modify.
3991 * @param {Array|string} path The path of the property to set.
3992 * @param {*} value The value to set.
3993 * @param {Function} [customizer] The function to customize path creation.
3994 * @returns {Object} Returns `object`.
3996 function baseSet(object, path, value, customizer) {
3997 if (!isObject(object)) {
4000 path = castPath(path, object);
4003 length = path.length,
4004 lastIndex = length - 1,
4007 while (nested != null && ++index < length) {
4008 var key = toKey(path[index]),
4011 if (index != lastIndex) {
4012 var objValue = nested[key];
4013 newValue = customizer ? customizer(objValue, key, nested) : undefined;
4014 if (newValue === undefined) {
4015 newValue = isObject(objValue)
4017 : (isIndex(path[index + 1]) ? [] : {});
4020 assignValue(nested, key, newValue);
4021 nested = nested[key];
4027 * The base implementation of `setData` without support for hot loop shorting.
4030 * @param {Function} func The function to associate metadata with.
4031 * @param {*} data The metadata.
4032 * @returns {Function} Returns `func`.
4034 var baseSetData = !metaMap ? identity : function(func, data) {
4035 metaMap.set(func, data);
4040 * The base implementation of `setToString` without support for hot loop shorting.
4043 * @param {Function} func The function to modify.
4044 * @param {Function} string The `toString` result.
4045 * @returns {Function} Returns `func`.
4047 var baseSetToString = !defineProperty ? identity : function(func, string) {
4048 return defineProperty(func, 'toString', {
4049 'configurable': true,
4050 'enumerable': false,
4051 'value': constant(string),
4057 * The base implementation of `_.shuffle`.
4060 * @param {Array|Object} collection The collection to shuffle.
4061 * @returns {Array} Returns the new shuffled array.
4063 function baseShuffle(collection) {
4064 return shuffleSelf(values(collection));
4068 * The base implementation of `_.slice` without an iteratee call guard.
4071 * @param {Array} array The array to slice.
4072 * @param {number} [start=0] The start position.
4073 * @param {number} [end=array.length] The end position.
4074 * @returns {Array} Returns the slice of `array`.
4076 function baseSlice(array, start, end) {
4078 length = array.length;
4081 start = -start > length ? 0 : (length + start);
4083 end = end > length ? length : end;
4087 length = start > end ? 0 : ((end - start) >>> 0);
4090 var result = Array(length);
4091 while (++index < length) {
4092 result[index] = array[index + start];
4098 * The base implementation of `_.some` without support for iteratee shorthands.
4101 * @param {Array|Object} collection The collection to iterate over.
4102 * @param {Function} predicate The function invoked per iteration.
4103 * @returns {boolean} Returns `true` if any element passes the predicate check,
4106 function baseSome(collection, predicate) {
4109 baseEach(collection, function(value, index, collection) {
4110 result = predicate(value, index, collection);
4117 * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
4118 * performs a binary search of `array` to determine the index at which `value`
4119 * should be inserted into `array` in order to maintain its sort order.
4122 * @param {Array} array The sorted array to inspect.
4123 * @param {*} value The value to evaluate.
4124 * @param {boolean} [retHighest] Specify returning the highest qualified index.
4125 * @returns {number} Returns the index at which `value` should be inserted
4128 function baseSortedIndex(array, value, retHighest) {
4130 high = array == null ? low : array.length;
4132 if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
4133 while (low < high) {
4134 var mid = (low + high) >>> 1,
4135 computed = array[mid];
4137 if (computed !== null && !isSymbol(computed) &&
4138 (retHighest ? (computed <= value) : (computed < value))) {
4146 return baseSortedIndexBy(array, value, identity, retHighest);
4150 * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
4151 * which invokes `iteratee` for `value` and each element of `array` to compute
4152 * their sort ranking. The iteratee is invoked with one argument; (value).
4155 * @param {Array} array The sorted array to inspect.
4156 * @param {*} value The value to evaluate.
4157 * @param {Function} iteratee The iteratee invoked per element.
4158 * @param {boolean} [retHighest] Specify returning the highest qualified index.
4159 * @returns {number} Returns the index at which `value` should be inserted
4162 function baseSortedIndexBy(array, value, iteratee, retHighest) {
4163 value = iteratee(value);
4166 high = array == null ? 0 : array.length,
4167 valIsNaN = value !== value,
4168 valIsNull = value === null,
4169 valIsSymbol = isSymbol(value),
4170 valIsUndefined = value === undefined;
4172 while (low < high) {
4173 var mid = nativeFloor((low + high) / 2),
4174 computed = iteratee(array[mid]),
4175 othIsDefined = computed !== undefined,
4176 othIsNull = computed === null,
4177 othIsReflexive = computed === computed,
4178 othIsSymbol = isSymbol(computed);
4181 var setLow = retHighest || othIsReflexive;
4182 } else if (valIsUndefined) {
4183 setLow = othIsReflexive && (retHighest || othIsDefined);
4184 } else if (valIsNull) {
4185 setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
4186 } else if (valIsSymbol) {
4187 setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
4188 } else if (othIsNull || othIsSymbol) {
4191 setLow = retHighest ? (computed <= value) : (computed < value);
4199 return nativeMin(high, MAX_ARRAY_INDEX);
4203 * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
4204 * support for iteratee shorthands.
4207 * @param {Array} array The array to inspect.
4208 * @param {Function} [iteratee] The iteratee invoked per element.
4209 * @returns {Array} Returns the new duplicate free array.
4211 function baseSortedUniq(array, iteratee) {
4213 length = array.length,
4217 while (++index < length) {
4218 var value = array[index],
4219 computed = iteratee ? iteratee(value) : value;
4221 if (!index || !eq(computed, seen)) {
4222 var seen = computed;
4223 result[resIndex++] = value === 0 ? 0 : value;
4230 * The base implementation of `_.toNumber` which doesn't ensure correct
4231 * conversions of binary, hexadecimal, or octal string values.
4234 * @param {*} value The value to process.
4235 * @returns {number} Returns the number.
4237 function baseToNumber(value) {
4238 if (typeof value == 'number') {
4241 if (isSymbol(value)) {
4248 * The base implementation of `_.toString` which doesn't convert nullish
4249 * values to empty strings.
4252 * @param {*} value The value to process.
4253 * @returns {string} Returns the string.
4255 function baseToString(value) {
4256 // Exit early for strings to avoid a performance hit in some environments.
4257 if (typeof value == 'string') {
4260 if (isArray(value)) {
4261 // Recursively convert values (susceptible to call stack limits).
4262 return arrayMap(value, baseToString) + '';
4264 if (isSymbol(value)) {
4265 return symbolToString ? symbolToString.call(value) : '';
4267 var result = (value + '');
4268 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
4272 * The base implementation of `_.uniqBy` without support for iteratee shorthands.
4275 * @param {Array} array The array to inspect.
4276 * @param {Function} [iteratee] The iteratee invoked per element.
4277 * @param {Function} [comparator] The comparator invoked per element.
4278 * @returns {Array} Returns the new duplicate free array.
4280 function baseUniq(array, iteratee, comparator) {
4282 includes = arrayIncludes,
4283 length = array.length,
4290 includes = arrayIncludesWith;
4292 else if (length >= LARGE_ARRAY_SIZE) {
4293 var set = iteratee ? null : createSet(array);
4295 return setToArray(set);
4298 includes = cacheHas;
4299 seen = new SetCache;
4302 seen = iteratee ? [] : result;
4305 while (++index < length) {
4306 var value = array[index],
4307 computed = iteratee ? iteratee(value) : value;
4309 value = (comparator || value !== 0) ? value : 0;
4310 if (isCommon && computed === computed) {
4311 var seenIndex = seen.length;
4312 while (seenIndex--) {
4313 if (seen[seenIndex] === computed) {
4318 seen.push(computed);
4322 else if (!includes(seen, computed, comparator)) {
4323 if (seen !== result) {
4324 seen.push(computed);
4333 * The base implementation of `_.unset`.
4336 * @param {Object} object The object to modify.
4337 * @param {Array|string} path The property path to unset.
4338 * @returns {boolean} Returns `true` if the property is deleted, else `false`.
4340 function baseUnset(object, path) {
4341 path = castPath(path, object);
4342 object = parent(object, path);
4343 return object == null || delete object[toKey(last(path))];
4347 * The base implementation of `_.update`.
4350 * @param {Object} object The object to modify.
4351 * @param {Array|string} path The path of the property to update.
4352 * @param {Function} updater The function to produce the updated value.
4353 * @param {Function} [customizer] The function to customize path creation.
4354 * @returns {Object} Returns `object`.
4356 function baseUpdate(object, path, updater, customizer) {
4357 return baseSet(object, path, updater(baseGet(object, path)), customizer);
4361 * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
4362 * without support for iteratee shorthands.
4365 * @param {Array} array The array to query.
4366 * @param {Function} predicate The function invoked per iteration.
4367 * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
4368 * @param {boolean} [fromRight] Specify iterating from right to left.
4369 * @returns {Array} Returns the slice of `array`.
4371 function baseWhile(array, predicate, isDrop, fromRight) {
4372 var length = array.length,
4373 index = fromRight ? length : -1;
4375 while ((fromRight ? index-- : ++index < length) &&
4376 predicate(array[index], index, array)) {}
4379 ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
4380 : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
4384 * The base implementation of `wrapperValue` which returns the result of
4385 * performing a sequence of actions on the unwrapped `value`, where each
4386 * successive action is supplied the return value of the previous.
4389 * @param {*} value The unwrapped value.
4390 * @param {Array} actions Actions to perform to resolve the unwrapped value.
4391 * @returns {*} Returns the resolved value.
4393 function baseWrapperValue(value, actions) {
4395 if (result instanceof LazyWrapper) {
4396 result = result.value();
4398 return arrayReduce(actions, function(result, action) {
4399 return action.func.apply(action.thisArg, arrayPush([result], action.args));
4404 * The base implementation of methods like `_.xor`, without support for
4405 * iteratee shorthands, that accepts an array of arrays to inspect.
4408 * @param {Array} arrays The arrays to inspect.
4409 * @param {Function} [iteratee] The iteratee invoked per element.
4410 * @param {Function} [comparator] The comparator invoked per element.
4411 * @returns {Array} Returns the new array of values.
4413 function baseXor(arrays, iteratee, comparator) {
4414 var length = arrays.length;
4416 return length ? baseUniq(arrays[0]) : [];
4419 result = Array(length);
4421 while (++index < length) {
4422 var array = arrays[index],
4425 while (++othIndex < length) {
4426 if (othIndex != index) {
4427 result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
4431 return baseUniq(baseFlatten(result, 1), iteratee, comparator);
4435 * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
4438 * @param {Array} props The property identifiers.
4439 * @param {Array} values The property values.
4440 * @param {Function} assignFunc The function to assign values.
4441 * @returns {Object} Returns the new object.
4443 function baseZipObject(props, values, assignFunc) {
4445 length = props.length,
4446 valsLength = values.length,
4449 while (++index < length) {
4450 var value = index < valsLength ? values[index] : undefined;
4451 assignFunc(result, props[index], value);
4457 * Casts `value` to an empty array if it's not an array like object.
4460 * @param {*} value The value to inspect.
4461 * @returns {Array|Object} Returns the cast array-like object.
4463 function castArrayLikeObject(value) {
4464 return isArrayLikeObject(value) ? value : [];
4468 * Casts `value` to `identity` if it's not a function.
4471 * @param {*} value The value to inspect.
4472 * @returns {Function} Returns cast function.
4474 function castFunction(value) {
4475 return typeof value == 'function' ? value : identity;
4479 * Casts `value` to a path array if it's not one.
4482 * @param {*} value The value to inspect.
4483 * @param {Object} [object] The object to query keys on.
4484 * @returns {Array} Returns the cast property path array.
4486 function castPath(value, object) {
4487 if (isArray(value)) {
4490 return isKey(value, object) ? [value] : stringToPath(toString(value));
4494 * A `baseRest` alias which can be replaced with `identity` by module
4495 * replacement plugins.
4499 * @param {Function} func The function to apply a rest parameter to.
4500 * @returns {Function} Returns the new function.
4502 var castRest = baseRest;
4505 * Casts `array` to a slice if it's needed.
4508 * @param {Array} array The array to inspect.
4509 * @param {number} start The start position.
4510 * @param {number} [end=array.length] The end position.
4511 * @returns {Array} Returns the cast slice.
4513 function castSlice(array, start, end) {
4514 var length = array.length;
4515 end = end === undefined ? length : end;
4516 return (!start && end >= length) ? array : baseSlice(array, start, end);
4520 * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
4523 * @param {number|Object} id The timer id or timeout object of the timer to clear.
4525 var clearTimeout = ctxClearTimeout || function(id) {
4526 return root.clearTimeout(id);
4530 * Creates a clone of `buffer`.
4533 * @param {Buffer} buffer The buffer to clone.
4534 * @param {boolean} [isDeep] Specify a deep clone.
4535 * @returns {Buffer} Returns the cloned buffer.
4537 function cloneBuffer(buffer, isDeep) {
4539 return buffer.slice();
4541 var length = buffer.length,
4542 result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
4544 buffer.copy(result);
4549 * Creates a clone of `arrayBuffer`.
4552 * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
4553 * @returns {ArrayBuffer} Returns the cloned array buffer.
4555 function cloneArrayBuffer(arrayBuffer) {
4556 var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
4557 new Uint8Array(result).set(new Uint8Array(arrayBuffer));
4562 * Creates a clone of `dataView`.
4565 * @param {Object} dataView The data view to clone.
4566 * @param {boolean} [isDeep] Specify a deep clone.
4567 * @returns {Object} Returns the cloned data view.
4569 function cloneDataView(dataView, isDeep) {
4570 var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
4571 return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
4575 * Creates a clone of `map`.
4578 * @param {Object} map The map to clone.
4579 * @param {Function} cloneFunc The function to clone values.
4580 * @param {boolean} [isDeep] Specify a deep clone.
4581 * @returns {Object} Returns the cloned map.
4583 function cloneMap(map, isDeep, cloneFunc) {
4584 var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
4585 return arrayReduce(array, addMapEntry, new map.constructor);
4589 * Creates a clone of `regexp`.
4592 * @param {Object} regexp The regexp to clone.
4593 * @returns {Object} Returns the cloned regexp.
4595 function cloneRegExp(regexp) {
4596 var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
4597 result.lastIndex = regexp.lastIndex;
4602 * Creates a clone of `set`.
4605 * @param {Object} set The set to clone.
4606 * @param {Function} cloneFunc The function to clone values.
4607 * @param {boolean} [isDeep] Specify a deep clone.
4608 * @returns {Object} Returns the cloned set.
4610 function cloneSet(set, isDeep, cloneFunc) {
4611 var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
4612 return arrayReduce(array, addSetEntry, new set.constructor);
4616 * Creates a clone of the `symbol` object.
4619 * @param {Object} symbol The symbol object to clone.
4620 * @returns {Object} Returns the cloned symbol object.
4622 function cloneSymbol(symbol) {
4623 return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
4627 * Creates a clone of `typedArray`.
4630 * @param {Object} typedArray The typed array to clone.
4631 * @param {boolean} [isDeep] Specify a deep clone.
4632 * @returns {Object} Returns the cloned typed array.
4634 function cloneTypedArray(typedArray, isDeep) {
4635 var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
4636 return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
4640 * Compares values to sort them in ascending order.
4643 * @param {*} value The value to compare.
4644 * @param {*} other The other value to compare.
4645 * @returns {number} Returns the sort order indicator for `value`.
4647 function compareAscending(value, other) {
4648 if (value !== other) {
4649 var valIsDefined = value !== undefined,
4650 valIsNull = value === null,
4651 valIsReflexive = value === value,
4652 valIsSymbol = isSymbol(value);
4654 var othIsDefined = other !== undefined,
4655 othIsNull = other === null,
4656 othIsReflexive = other === other,
4657 othIsSymbol = isSymbol(other);
4659 if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
4660 (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
4661 (valIsNull && othIsDefined && othIsReflexive) ||
4662 (!valIsDefined && othIsReflexive) ||
4666 if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
4667 (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
4668 (othIsNull && valIsDefined && valIsReflexive) ||
4669 (!othIsDefined && valIsReflexive) ||
4678 * Used by `_.orderBy` to compare multiple properties of a value to another
4679 * and stable sort them.
4681 * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
4682 * specify an order of "desc" for descending or "asc" for ascending sort order
4683 * of corresponding values.
4686 * @param {Object} object The object to compare.
4687 * @param {Object} other The other object to compare.
4688 * @param {boolean[]|string[]} orders The order to sort by for each property.
4689 * @returns {number} Returns the sort order indicator for `object`.
4691 function compareMultiple(object, other, orders) {
4693 objCriteria = object.criteria,
4694 othCriteria = other.criteria,
4695 length = objCriteria.length,
4696 ordersLength = orders.length;
4698 while (++index < length) {
4699 var result = compareAscending(objCriteria[index], othCriteria[index]);
4701 if (index >= ordersLength) {
4704 var order = orders[index];
4705 return result * (order == 'desc' ? -1 : 1);
4708 // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
4709 // that causes it, under certain circumstances, to provide the same value for
4710 // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
4711 // for more details.
4713 // This also ensures a stable sort in V8 and other engines.
4714 // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
4715 return object.index - other.index;
4719 * Creates an array that is the composition of partially applied arguments,
4720 * placeholders, and provided arguments into a single array of arguments.
4723 * @param {Array} args The provided arguments.
4724 * @param {Array} partials The arguments to prepend to those provided.
4725 * @param {Array} holders The `partials` placeholder indexes.
4726 * @params {boolean} [isCurried] Specify composing for a curried function.
4727 * @returns {Array} Returns the new array of composed arguments.
4729 function composeArgs(args, partials, holders, isCurried) {
4731 argsLength = args.length,
4732 holdersLength = holders.length,
4734 leftLength = partials.length,
4735 rangeLength = nativeMax(argsLength - holdersLength, 0),
4736 result = Array(leftLength + rangeLength),
4737 isUncurried = !isCurried;
4739 while (++leftIndex < leftLength) {
4740 result[leftIndex] = partials[leftIndex];
4742 while (++argsIndex < holdersLength) {
4743 if (isUncurried || argsIndex < argsLength) {
4744 result[holders[argsIndex]] = args[argsIndex];
4747 while (rangeLength--) {
4748 result[leftIndex++] = args[argsIndex++];
4754 * This function is like `composeArgs` except that the arguments composition
4755 * is tailored for `_.partialRight`.
4758 * @param {Array} args The provided arguments.
4759 * @param {Array} partials The arguments to append to those provided.
4760 * @param {Array} holders The `partials` placeholder indexes.
4761 * @params {boolean} [isCurried] Specify composing for a curried function.
4762 * @returns {Array} Returns the new array of composed arguments.
4764 function composeArgsRight(args, partials, holders, isCurried) {
4766 argsLength = args.length,
4768 holdersLength = holders.length,
4770 rightLength = partials.length,
4771 rangeLength = nativeMax(argsLength - holdersLength, 0),
4772 result = Array(rangeLength + rightLength),
4773 isUncurried = !isCurried;
4775 while (++argsIndex < rangeLength) {
4776 result[argsIndex] = args[argsIndex];
4778 var offset = argsIndex;
4779 while (++rightIndex < rightLength) {
4780 result[offset + rightIndex] = partials[rightIndex];
4782 while (++holdersIndex < holdersLength) {
4783 if (isUncurried || argsIndex < argsLength) {
4784 result[offset + holders[holdersIndex]] = args[argsIndex++];
4791 * Copies the values of `source` to `array`.
4794 * @param {Array} source The array to copy values from.
4795 * @param {Array} [array=[]] The array to copy values to.
4796 * @returns {Array} Returns `array`.
4798 function copyArray(source, array) {
4800 length = source.length;
4802 array || (array = Array(length));
4803 while (++index < length) {
4804 array[index] = source[index];
4810 * Copies properties of `source` to `object`.
4813 * @param {Object} source The object to copy properties from.
4814 * @param {Array} props The property identifiers to copy.
4815 * @param {Object} [object={}] The object to copy properties to.
4816 * @param {Function} [customizer] The function to customize copied values.
4817 * @returns {Object} Returns `object`.
4819 function copyObject(source, props, object, customizer) {
4820 var isNew = !object;
4821 object || (object = {});
4824 length = props.length;
4826 while (++index < length) {
4827 var key = props[index];
4829 var newValue = customizer
4830 ? customizer(object[key], source[key], key, object, source)
4833 if (newValue === undefined) {
4834 newValue = source[key];
4837 baseAssignValue(object, key, newValue);
4839 assignValue(object, key, newValue);
4846 * Copies own symbols of `source` to `object`.
4849 * @param {Object} source The object to copy symbols from.
4850 * @param {Object} [object={}] The object to copy symbols to.
4851 * @returns {Object} Returns `object`.
4853 function copySymbols(source, object) {
4854 return copyObject(source, getSymbols(source), object);
4858 * Copies own and inherited symbols of `source` to `object`.
4861 * @param {Object} source The object to copy symbols from.
4862 * @param {Object} [object={}] The object to copy symbols to.
4863 * @returns {Object} Returns `object`.
4865 function copySymbolsIn(source, object) {
4866 return copyObject(source, getSymbolsIn(source), object);
4870 * Creates a function like `_.groupBy`.
4873 * @param {Function} setter The function to set accumulator values.
4874 * @param {Function} [initializer] The accumulator object initializer.
4875 * @returns {Function} Returns the new aggregator function.
4877 function createAggregator(setter, initializer) {
4878 return function(collection, iteratee) {
4879 var func = isArray(collection) ? arrayAggregator : baseAggregator,
4880 accumulator = initializer ? initializer() : {};
4882 return func(collection, setter, getIteratee(iteratee, 2), accumulator);
4887 * Creates a function like `_.assign`.
4890 * @param {Function} assigner The function to assign values.
4891 * @returns {Function} Returns the new assigner function.
4893 function createAssigner(assigner) {
4894 return baseRest(function(object, sources) {
4896 length = sources.length,
4897 customizer = length > 1 ? sources[length - 1] : undefined,
4898 guard = length > 2 ? sources[2] : undefined;
4900 customizer = (assigner.length > 3 && typeof customizer == 'function')
4901 ? (length--, customizer)
4904 if (guard && isIterateeCall(sources[0], sources[1], guard)) {
4905 customizer = length < 3 ? undefined : customizer;
4908 object = Object(object);
4909 while (++index < length) {
4910 var source = sources[index];
4912 assigner(object, source, index, customizer);
4920 * Creates a `baseEach` or `baseEachRight` function.
4923 * @param {Function} eachFunc The function to iterate over a collection.
4924 * @param {boolean} [fromRight] Specify iterating from right to left.
4925 * @returns {Function} Returns the new base function.
4927 function createBaseEach(eachFunc, fromRight) {
4928 return function(collection, iteratee) {
4929 if (collection == null) {
4932 if (!isArrayLike(collection)) {
4933 return eachFunc(collection, iteratee);
4935 var length = collection.length,
4936 index = fromRight ? length : -1,
4937 iterable = Object(collection);
4939 while ((fromRight ? index-- : ++index < length)) {
4940 if (iteratee(iterable[index], index, iterable) === false) {
4949 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
4952 * @param {boolean} [fromRight] Specify iterating from right to left.
4953 * @returns {Function} Returns the new base function.
4955 function createBaseFor(fromRight) {
4956 return function(object, iteratee, keysFunc) {
4958 iterable = Object(object),
4959 props = keysFunc(object),
4960 length = props.length;
4963 var key = props[fromRight ? length : ++index];
4964 if (iteratee(iterable[key], key, iterable) === false) {
4973 * Creates a function that wraps `func` to invoke it with the optional `this`
4974 * binding of `thisArg`.
4977 * @param {Function} func The function to wrap.
4978 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
4979 * @param {*} [thisArg] The `this` binding of `func`.
4980 * @returns {Function} Returns the new wrapped function.
4982 function createBind(func, bitmask, thisArg) {
4983 var isBind = bitmask & WRAP_BIND_FLAG,
4984 Ctor = createCtor(func);
4986 function wrapper() {
4987 var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
4988 return fn.apply(isBind ? thisArg : this, arguments);
4994 * Creates a function like `_.lowerFirst`.
4997 * @param {string} methodName The name of the `String` case method to use.
4998 * @returns {Function} Returns the new case function.
5000 function createCaseFirst(methodName) {
5001 return function(string) {
5002 string = toString(string);
5004 var strSymbols = hasUnicode(string)
5005 ? stringToArray(string)
5008 var chr = strSymbols
5012 var trailing = strSymbols
5013 ? castSlice(strSymbols, 1).join('')
5016 return chr[methodName]() + trailing;
5021 * Creates a function like `_.camelCase`.
5024 * @param {Function} callback The function to combine each word.
5025 * @returns {Function} Returns the new compounder function.
5027 function createCompounder(callback) {
5028 return function(string) {
5029 return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
5034 * Creates a function that produces an instance of `Ctor` regardless of
5035 * whether it was invoked as part of a `new` expression or by `call` or `apply`.
5038 * @param {Function} Ctor The constructor to wrap.
5039 * @returns {Function} Returns the new wrapped function.
5041 function createCtor(Ctor) {
5043 // Use a `switch` statement to work with class constructors. See
5044 // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
5045 // for more details.
5046 var args = arguments;
5047 switch (args.length) {
5048 case 0: return new Ctor;
5049 case 1: return new Ctor(args[0]);
5050 case 2: return new Ctor(args[0], args[1]);
5051 case 3: return new Ctor(args[0], args[1], args[2]);
5052 case 4: return new Ctor(args[0], args[1], args[2], args[3]);
5053 case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
5054 case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
5055 case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
5057 var thisBinding = baseCreate(Ctor.prototype),
5058 result = Ctor.apply(thisBinding, args);
5060 // Mimic the constructor's `return` behavior.
5061 // See https://es5.github.io/#x13.2.2 for more details.
5062 return isObject(result) ? result : thisBinding;
5067 * Creates a function that wraps `func` to enable currying.
5070 * @param {Function} func The function to wrap.
5071 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5072 * @param {number} arity The arity of `func`.
5073 * @returns {Function} Returns the new wrapped function.
5075 function createCurry(func, bitmask, arity) {
5076 var Ctor = createCtor(func);
5078 function wrapper() {
5079 var length = arguments.length,
5080 args = Array(length),
5082 placeholder = getHolder(wrapper);
5085 args[index] = arguments[index];
5087 var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
5089 : replaceHolders(args, placeholder);
5091 length -= holders.length;
5092 if (length < arity) {
5093 return createRecurry(
5094 func, bitmask, createHybrid, wrapper.placeholder, undefined,
5095 args, holders, undefined, undefined, arity - length);
5097 var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5098 return apply(fn, this, args);
5104 * Creates a `_.find` or `_.findLast` function.
5107 * @param {Function} findIndexFunc The function to find the collection index.
5108 * @returns {Function} Returns the new find function.
5110 function createFind(findIndexFunc) {
5111 return function(collection, predicate, fromIndex) {
5112 var iterable = Object(collection);
5113 if (!isArrayLike(collection)) {
5114 var iteratee = getIteratee(predicate, 3);
5115 collection = keys(collection);
5116 predicate = function(key) { return iteratee(iterable[key], key, iterable); };
5118 var index = findIndexFunc(collection, predicate, fromIndex);
5119 return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
5124 * Creates a `_.flow` or `_.flowRight` function.
5127 * @param {boolean} [fromRight] Specify iterating from right to left.
5128 * @returns {Function} Returns the new flow function.
5130 function createFlow(fromRight) {
5131 return flatRest(function(funcs) {
5132 var length = funcs.length,
5134 prereq = LodashWrapper.prototype.thru;
5140 var func = funcs[index];
5141 if (typeof func != 'function') {
5142 throw new TypeError(FUNC_ERROR_TEXT);
5144 if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
5145 var wrapper = new LodashWrapper([], true);
5148 index = wrapper ? index : length;
5149 while (++index < length) {
5150 func = funcs[index];
5152 var funcName = getFuncName(func),
5153 data = funcName == 'wrapper' ? getData(func) : undefined;
5155 if (data && isLaziable(data[0]) &&
5156 data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
5157 !data[4].length && data[9] == 1
5159 wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
5161 wrapper = (func.length == 1 && isLaziable(func))
5162 ? wrapper[funcName]()
5163 : wrapper.thru(func);
5167 var args = arguments,
5170 if (wrapper && args.length == 1 && isArray(value)) {
5171 return wrapper.plant(value).value();
5174 result = length ? funcs[index].apply(this, args) : value;
5176 while (++index < length) {
5177 result = funcs[index].call(this, result);
5185 * Creates a function that wraps `func` to invoke it with optional `this`
5186 * binding of `thisArg`, partial application, and currying.
5189 * @param {Function|string} func The function or method name to wrap.
5190 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5191 * @param {*} [thisArg] The `this` binding of `func`.
5192 * @param {Array} [partials] The arguments to prepend to those provided to
5194 * @param {Array} [holders] The `partials` placeholder indexes.
5195 * @param {Array} [partialsRight] The arguments to append to those provided
5196 * to the new function.
5197 * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
5198 * @param {Array} [argPos] The argument positions of the new function.
5199 * @param {number} [ary] The arity cap of `func`.
5200 * @param {number} [arity] The arity of `func`.
5201 * @returns {Function} Returns the new wrapped function.
5203 function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
5204 var isAry = bitmask & WRAP_ARY_FLAG,
5205 isBind = bitmask & WRAP_BIND_FLAG,
5206 isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
5207 isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
5208 isFlip = bitmask & WRAP_FLIP_FLAG,
5209 Ctor = isBindKey ? undefined : createCtor(func);
5211 function wrapper() {
5212 var length = arguments.length,
5213 args = Array(length),
5217 args[index] = arguments[index];
5220 var placeholder = getHolder(wrapper),
5221 holdersCount = countHolders(args, placeholder);
5224 args = composeArgs(args, partials, holders, isCurried);
5226 if (partialsRight) {
5227 args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
5229 length -= holdersCount;
5230 if (isCurried && length < arity) {
5231 var newHolders = replaceHolders(args, placeholder);
5232 return createRecurry(
5233 func, bitmask, createHybrid, wrapper.placeholder, thisArg,
5234 args, newHolders, argPos, ary, arity - length
5237 var thisBinding = isBind ? thisArg : this,
5238 fn = isBindKey ? thisBinding[func] : func;
5240 length = args.length;
5242 args = reorder(args, argPos);
5243 } else if (isFlip && length > 1) {
5246 if (isAry && ary < length) {
5249 if (this && this !== root && this instanceof wrapper) {
5250 fn = Ctor || createCtor(fn);
5252 return fn.apply(thisBinding, args);
5258 * Creates a function like `_.invertBy`.
5261 * @param {Function} setter The function to set accumulator values.
5262 * @param {Function} toIteratee The function to resolve iteratees.
5263 * @returns {Function} Returns the new inverter function.
5265 function createInverter(setter, toIteratee) {
5266 return function(object, iteratee) {
5267 return baseInverter(object, setter, toIteratee(iteratee), {});
5272 * Creates a function that performs a mathematical operation on two values.
5275 * @param {Function} operator The function to perform the operation.
5276 * @param {number} [defaultValue] The value used for `undefined` arguments.
5277 * @returns {Function} Returns the new mathematical operation function.
5279 function createMathOperation(operator, defaultValue) {
5280 return function(value, other) {
5282 if (value === undefined && other === undefined) {
5283 return defaultValue;
5285 if (value !== undefined) {
5288 if (other !== undefined) {
5289 if (result === undefined) {
5292 if (typeof value == 'string' || typeof other == 'string') {
5293 value = baseToString(value);
5294 other = baseToString(other);
5296 value = baseToNumber(value);
5297 other = baseToNumber(other);
5299 result = operator(value, other);
5306 * Creates a function like `_.over`.
5309 * @param {Function} arrayFunc The function to iterate over iteratees.
5310 * @returns {Function} Returns the new over function.
5312 function createOver(arrayFunc) {
5313 return flatRest(function(iteratees) {
5314 iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
5315 return baseRest(function(args) {
5317 return arrayFunc(iteratees, function(iteratee) {
5318 return apply(iteratee, thisArg, args);
5325 * Creates the padding for `string` based on `length`. The `chars` string
5326 * is truncated if the number of characters exceeds `length`.
5329 * @param {number} length The padding length.
5330 * @param {string} [chars=' '] The string used as padding.
5331 * @returns {string} Returns the padding for `string`.
5333 function createPadding(length, chars) {
5334 chars = chars === undefined ? ' ' : baseToString(chars);
5336 var charsLength = chars.length;
5337 if (charsLength < 2) {
5338 return charsLength ? baseRepeat(chars, length) : chars;
5340 var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
5341 return hasUnicode(chars)
5342 ? castSlice(stringToArray(result), 0, length).join('')
5343 : result.slice(0, length);
5347 * Creates a function that wraps `func` to invoke it with the `this` binding
5348 * of `thisArg` and `partials` prepended to the arguments it receives.
5351 * @param {Function} func The function to wrap.
5352 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5353 * @param {*} thisArg The `this` binding of `func`.
5354 * @param {Array} partials The arguments to prepend to those provided to
5356 * @returns {Function} Returns the new wrapped function.
5358 function createPartial(func, bitmask, thisArg, partials) {
5359 var isBind = bitmask & WRAP_BIND_FLAG,
5360 Ctor = createCtor(func);
5362 function wrapper() {
5364 argsLength = arguments.length,
5366 leftLength = partials.length,
5367 args = Array(leftLength + argsLength),
5368 fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5370 while (++leftIndex < leftLength) {
5371 args[leftIndex] = partials[leftIndex];
5373 while (argsLength--) {
5374 args[leftIndex++] = arguments[++argsIndex];
5376 return apply(fn, isBind ? thisArg : this, args);
5382 * Creates a `_.range` or `_.rangeRight` function.
5385 * @param {boolean} [fromRight] Specify iterating from right to left.
5386 * @returns {Function} Returns the new range function.
5388 function createRange(fromRight) {
5389 return function(start, end, step) {
5390 if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
5391 end = step = undefined;
5393 // Ensure the sign of `-0` is preserved.
5394 start = toFinite(start);
5395 if (end === undefined) {
5399 end = toFinite(end);
5401 step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
5402 return baseRange(start, end, step, fromRight);
5407 * Creates a function that performs a relational operation on two values.
5410 * @param {Function} operator The function to perform the operation.
5411 * @returns {Function} Returns the new relational operation function.
5413 function createRelationalOperation(operator) {
5414 return function(value, other) {
5415 if (!(typeof value == 'string' && typeof other == 'string')) {
5416 value = toNumber(value);
5417 other = toNumber(other);
5419 return operator(value, other);
5424 * Creates a function that wraps `func` to continue currying.
5427 * @param {Function} func The function to wrap.
5428 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5429 * @param {Function} wrapFunc The function to create the `func` wrapper.
5430 * @param {*} placeholder The placeholder value.
5431 * @param {*} [thisArg] The `this` binding of `func`.
5432 * @param {Array} [partials] The arguments to prepend to those provided to
5434 * @param {Array} [holders] The `partials` placeholder indexes.
5435 * @param {Array} [argPos] The argument positions of the new function.
5436 * @param {number} [ary] The arity cap of `func`.
5437 * @param {number} [arity] The arity of `func`.
5438 * @returns {Function} Returns the new wrapped function.
5440 function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
5441 var isCurry = bitmask & WRAP_CURRY_FLAG,
5442 newHolders = isCurry ? holders : undefined,
5443 newHoldersRight = isCurry ? undefined : holders,
5444 newPartials = isCurry ? partials : undefined,
5445 newPartialsRight = isCurry ? undefined : partials;
5447 bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
5448 bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
5450 if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
5451 bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
5454 func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
5455 newHoldersRight, argPos, ary, arity
5458 var result = wrapFunc.apply(undefined, newData);
5459 if (isLaziable(func)) {
5460 setData(result, newData);
5462 result.placeholder = placeholder;
5463 return setWrapToString(result, func, bitmask);
5467 * Creates a function like `_.round`.
5470 * @param {string} methodName The name of the `Math` method to use when rounding.
5471 * @returns {Function} Returns the new round function.
5473 function createRound(methodName) {
5474 var func = Math[methodName];
5475 return function(number, precision) {
5476 number = toNumber(number);
5477 precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
5479 // Shift with exponential notation to avoid floating-point issues.
5480 // See [MDN](https://mdn.io/round#Examples) for more details.
5481 var pair = (toString(number) + 'e').split('e'),
5482 value = func(pair[0] + 'e' + (+pair[1] + precision));
5484 pair = (toString(value) + 'e').split('e');
5485 return +(pair[0] + 'e' + (+pair[1] - precision));
5487 return func(number);
5492 * Creates a set object of `values`.
5495 * @param {Array} values The values to add to the set.
5496 * @returns {Object} Returns the new set.
5498 var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
5499 return new Set(values);
5503 * Creates a `_.toPairs` or `_.toPairsIn` function.
5506 * @param {Function} keysFunc The function to get the keys of a given object.
5507 * @returns {Function} Returns the new pairs function.
5509 function createToPairs(keysFunc) {
5510 return function(object) {
5511 var tag = getTag(object);
5512 if (tag == mapTag) {
5513 return mapToArray(object);
5515 if (tag == setTag) {
5516 return setToPairs(object);
5518 return baseToPairs(object, keysFunc(object));
5523 * Creates a function that either curries or invokes `func` with optional
5524 * `this` binding and partially applied arguments.
5527 * @param {Function|string} func The function or method name to wrap.
5528 * @param {number} bitmask The bitmask flags.
5531 * 4 - `_.curry` or `_.curryRight` of a bound function
5533 * 16 - `_.curryRight`
5535 * 64 - `_.partialRight`
5539 * @param {*} [thisArg] The `this` binding of `func`.
5540 * @param {Array} [partials] The arguments to be partially applied.
5541 * @param {Array} [holders] The `partials` placeholder indexes.
5542 * @param {Array} [argPos] The argument positions of the new function.
5543 * @param {number} [ary] The arity cap of `func`.
5544 * @param {number} [arity] The arity of `func`.
5545 * @returns {Function} Returns the new wrapped function.
5547 function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
5548 var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
5549 if (!isBindKey && typeof func != 'function') {
5550 throw new TypeError(FUNC_ERROR_TEXT);
5552 var length = partials ? partials.length : 0;
5554 bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
5555 partials = holders = undefined;
5557 ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
5558 arity = arity === undefined ? arity : toInteger(arity);
5559 length -= holders ? holders.length : 0;
5561 if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
5562 var partialsRight = partials,
5563 holdersRight = holders;
5565 partials = holders = undefined;
5567 var data = isBindKey ? undefined : getData(func);
5570 func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
5575 mergeData(newData, data);
5578 bitmask = newData[1];
5579 thisArg = newData[2];
5580 partials = newData[3];
5581 holders = newData[4];
5582 arity = newData[9] = newData[9] === undefined
5583 ? (isBindKey ? 0 : func.length)
5584 : nativeMax(newData[9] - length, 0);
5586 if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
5587 bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
5589 if (!bitmask || bitmask == WRAP_BIND_FLAG) {
5590 var result = createBind(func, bitmask, thisArg);
5591 } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
5592 result = createCurry(func, bitmask, arity);
5593 } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
5594 result = createPartial(func, bitmask, thisArg, partials);
5596 result = createHybrid.apply(undefined, newData);
5598 var setter = data ? baseSetData : setData;
5599 return setWrapToString(setter(result, newData), func, bitmask);
5603 * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
5604 * of source objects to the destination object for all destination properties
5605 * that resolve to `undefined`.
5608 * @param {*} objValue The destination value.
5609 * @param {*} srcValue The source value.
5610 * @param {string} key The key of the property to assign.
5611 * @param {Object} object The parent object of `objValue`.
5612 * @returns {*} Returns the value to assign.
5614 function customDefaultsAssignIn(objValue, srcValue, key, object) {
5615 if (objValue === undefined ||
5616 (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
5623 * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
5624 * objects into destination objects that are passed thru.
5627 * @param {*} objValue The destination value.
5628 * @param {*} srcValue The source value.
5629 * @param {string} key The key of the property to merge.
5630 * @param {Object} object The parent object of `objValue`.
5631 * @param {Object} source The parent object of `srcValue`.
5632 * @param {Object} [stack] Tracks traversed source values and their merged
5634 * @returns {*} Returns the value to assign.
5636 function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
5637 if (isObject(objValue) && isObject(srcValue)) {
5638 // Recursively merge objects and arrays (susceptible to call stack limits).
5639 stack.set(srcValue, objValue);
5640 baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);
5641 stack['delete'](srcValue);
5647 * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
5651 * @param {*} value The value to inspect.
5652 * @param {string} key The key of the property to inspect.
5653 * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
5655 function customOmitClone(value) {
5656 return isPlainObject(value) ? undefined : value;
5660 * A specialized version of `baseIsEqualDeep` for arrays with support for
5661 * partial deep comparisons.
5664 * @param {Array} array The array to compare.
5665 * @param {Array} other The other array to compare.
5666 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5667 * @param {Function} customizer The function to customize comparisons.
5668 * @param {Function} equalFunc The function to determine equivalents of values.
5669 * @param {Object} stack Tracks traversed `array` and `other` objects.
5670 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
5672 function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
5673 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5674 arrLength = array.length,
5675 othLength = other.length;
5677 if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
5680 // Assume cyclic values are equal.
5681 var stacked = stack.get(array);
5682 if (stacked && stack.get(other)) {
5683 return stacked == other;
5687 seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
5689 stack.set(array, other);
5690 stack.set(other, array);
5692 // Ignore non-index properties.
5693 while (++index < arrLength) {
5694 var arrValue = array[index],
5695 othValue = other[index];
5698 var compared = isPartial
5699 ? customizer(othValue, arrValue, index, other, array, stack)
5700 : customizer(arrValue, othValue, index, array, other, stack);
5702 if (compared !== undefined) {
5709 // Recursively compare arrays (susceptible to call stack limits).
5711 if (!arraySome(other, function(othValue, othIndex) {
5712 if (!cacheHas(seen, othIndex) &&
5713 (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
5714 return seen.push(othIndex);
5721 arrValue === othValue ||
5722 equalFunc(arrValue, othValue, bitmask, customizer, stack)
5728 stack['delete'](array);
5729 stack['delete'](other);
5734 * A specialized version of `baseIsEqualDeep` for comparing objects of
5735 * the same `toStringTag`.
5737 * **Note:** This function only supports comparing values with tags of
5738 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
5741 * @param {Object} object The object to compare.
5742 * @param {Object} other The other object to compare.
5743 * @param {string} tag The `toStringTag` of the objects to compare.
5744 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5745 * @param {Function} customizer The function to customize comparisons.
5746 * @param {Function} equalFunc The function to determine equivalents of values.
5747 * @param {Object} stack Tracks traversed `object` and `other` objects.
5748 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5750 function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
5753 if ((object.byteLength != other.byteLength) ||
5754 (object.byteOffset != other.byteOffset)) {
5757 object = object.buffer;
5758 other = other.buffer;
5760 case arrayBufferTag:
5761 if ((object.byteLength != other.byteLength) ||
5762 !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
5770 // Coerce booleans to `1` or `0` and dates to milliseconds.
5771 // Invalid dates are coerced to `NaN`.
5772 return eq(+object, +other);
5775 return object.name == other.name && object.message == other.message;
5779 // Coerce regexes to strings and treat strings, primitives and objects,
5780 // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
5781 // for more details.
5782 return object == (other + '');
5785 var convert = mapToArray;
5788 var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
5789 convert || (convert = setToArray);
5791 if (object.size != other.size && !isPartial) {
5794 // Assume cyclic values are equal.
5795 var stacked = stack.get(object);
5797 return stacked == other;
5799 bitmask |= COMPARE_UNORDERED_FLAG;
5801 // Recursively compare objects (susceptible to call stack limits).
5802 stack.set(object, other);
5803 var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
5804 stack['delete'](object);
5808 if (symbolValueOf) {
5809 return symbolValueOf.call(object) == symbolValueOf.call(other);
5816 * A specialized version of `baseIsEqualDeep` for objects with support for
5817 * partial deep comparisons.
5820 * @param {Object} object The object to compare.
5821 * @param {Object} other The other object to compare.
5822 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5823 * @param {Function} customizer The function to customize comparisons.
5824 * @param {Function} equalFunc The function to determine equivalents of values.
5825 * @param {Object} stack Tracks traversed `object` and `other` objects.
5826 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5828 function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
5829 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5830 objProps = getAllKeys(object),
5831 objLength = objProps.length,
5832 othProps = getAllKeys(other),
5833 othLength = othProps.length;
5835 if (objLength != othLength && !isPartial) {
5838 var index = objLength;
5840 var key = objProps[index];
5841 if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
5845 // Assume cyclic values are equal.
5846 var stacked = stack.get(object);
5847 if (stacked && stack.get(other)) {
5848 return stacked == other;
5851 stack.set(object, other);
5852 stack.set(other, object);
5854 var skipCtor = isPartial;
5855 while (++index < objLength) {
5856 key = objProps[index];
5857 var objValue = object[key],
5858 othValue = other[key];
5861 var compared = isPartial
5862 ? customizer(othValue, objValue, key, other, object, stack)
5863 : customizer(objValue, othValue, key, object, other, stack);
5865 // Recursively compare objects (susceptible to call stack limits).
5866 if (!(compared === undefined
5867 ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
5873 skipCtor || (skipCtor = key == 'constructor');
5875 if (result && !skipCtor) {
5876 var objCtor = object.constructor,
5877 othCtor = other.constructor;
5879 // Non `Object` object instances with different constructors are not equal.
5880 if (objCtor != othCtor &&
5881 ('constructor' in object && 'constructor' in other) &&
5882 !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
5883 typeof othCtor == 'function' && othCtor instanceof othCtor)) {
5887 stack['delete'](object);
5888 stack['delete'](other);
5893 * A specialized version of `baseRest` which flattens the rest array.
5896 * @param {Function} func The function to apply a rest parameter to.
5897 * @returns {Function} Returns the new function.
5899 function flatRest(func) {
5900 return setToString(overRest(func, undefined, flatten), func + '');
5904 * Creates an array of own enumerable property names and symbols of `object`.
5907 * @param {Object} object The object to query.
5908 * @returns {Array} Returns the array of property names and symbols.
5910 function getAllKeys(object) {
5911 return baseGetAllKeys(object, keys, getSymbols);
5915 * Creates an array of own and inherited enumerable property names and
5916 * symbols of `object`.
5919 * @param {Object} object The object to query.
5920 * @returns {Array} Returns the array of property names and symbols.
5922 function getAllKeysIn(object) {
5923 return baseGetAllKeys(object, keysIn, getSymbolsIn);
5927 * Gets metadata for `func`.
5930 * @param {Function} func The function to query.
5931 * @returns {*} Returns the metadata for `func`.
5933 var getData = !metaMap ? noop : function(func) {
5934 return metaMap.get(func);
5938 * Gets the name of `func`.
5941 * @param {Function} func The function to query.
5942 * @returns {string} Returns the function name.
5944 function getFuncName(func) {
5945 var result = (func.name + ''),
5946 array = realNames[result],
5947 length = hasOwnProperty.call(realNames, result) ? array.length : 0;
5950 var data = array[length],
5951 otherFunc = data.func;
5952 if (otherFunc == null || otherFunc == func) {
5960 * Gets the argument placeholder value for `func`.
5963 * @param {Function} func The function to inspect.
5964 * @returns {*} Returns the placeholder value.
5966 function getHolder(func) {
5967 var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
5968 return object.placeholder;
5972 * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
5973 * this function returns the custom method, otherwise it returns `baseIteratee`.
5974 * If arguments are provided, the chosen function is invoked with them and
5975 * its result is returned.
5978 * @param {*} [value] The value to convert to an iteratee.
5979 * @param {number} [arity] The arity of the created iteratee.
5980 * @returns {Function} Returns the chosen function or its result.
5982 function getIteratee() {
5983 var result = lodash.iteratee || iteratee;
5984 result = result === iteratee ? baseIteratee : result;
5985 return arguments.length ? result(arguments[0], arguments[1]) : result;
5989 * Gets the data for `map`.
5992 * @param {Object} map The map to query.
5993 * @param {string} key The reference key.
5994 * @returns {*} Returns the map data.
5996 function getMapData(map, key) {
5997 var data = map.__data__;
5998 return isKeyable(key)
5999 ? data[typeof key == 'string' ? 'string' : 'hash']
6004 * Gets the property names, values, and compare flags of `object`.
6007 * @param {Object} object The object to query.
6008 * @returns {Array} Returns the match data of `object`.
6010 function getMatchData(object) {
6011 var result = keys(object),
6012 length = result.length;
6015 var key = result[length],
6016 value = object[key];
6018 result[length] = [key, value, isStrictComparable(value)];
6024 * Gets the native function at `key` of `object`.
6027 * @param {Object} object The object to query.
6028 * @param {string} key The key of the method to get.
6029 * @returns {*} Returns the function if it's native, else `undefined`.
6031 function getNative(object, key) {
6032 var value = getValue(object, key);
6033 return baseIsNative(value) ? value : undefined;
6037 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
6040 * @param {*} value The value to query.
6041 * @returns {string} Returns the raw `toStringTag`.
6043 function getRawTag(value) {
6044 var isOwn = hasOwnProperty.call(value, symToStringTag),
6045 tag = value[symToStringTag];
6048 value[symToStringTag] = undefined;
6049 var unmasked = true;
6052 var result = nativeObjectToString.call(value);
6055 value[symToStringTag] = tag;
6057 delete value[symToStringTag];
6064 * Creates an array of the own enumerable symbols of `object`.
6067 * @param {Object} object The object to query.
6068 * @returns {Array} Returns the array of symbols.
6070 var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
6071 if (object == null) {
6074 object = Object(object);
6075 return arrayFilter(nativeGetSymbols(object), function(symbol) {
6076 return propertyIsEnumerable.call(object, symbol);
6081 * Creates an array of the own and inherited enumerable symbols of `object`.
6084 * @param {Object} object The object to query.
6085 * @returns {Array} Returns the array of symbols.
6087 var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
6090 arrayPush(result, getSymbols(object));
6091 object = getPrototype(object);
6097 * Gets the `toStringTag` of `value`.
6100 * @param {*} value The value to query.
6101 * @returns {string} Returns the `toStringTag`.
6103 var getTag = baseGetTag;
6105 // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
6106 if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
6107 (Map && getTag(new Map) != mapTag) ||
6108 (Promise && getTag(Promise.resolve()) != promiseTag) ||
6109 (Set && getTag(new Set) != setTag) ||
6110 (WeakMap && getTag(new WeakMap) != weakMapTag)) {
6111 getTag = function(value) {
6112 var result = baseGetTag(value),
6113 Ctor = result == objectTag ? value.constructor : undefined,
6114 ctorString = Ctor ? toSource(Ctor) : '';
6117 switch (ctorString) {
6118 case dataViewCtorString: return dataViewTag;
6119 case mapCtorString: return mapTag;
6120 case promiseCtorString: return promiseTag;
6121 case setCtorString: return setTag;
6122 case weakMapCtorString: return weakMapTag;
6130 * Gets the view, applying any `transforms` to the `start` and `end` positions.
6133 * @param {number} start The start of the view.
6134 * @param {number} end The end of the view.
6135 * @param {Array} transforms The transformations to apply to the view.
6136 * @returns {Object} Returns an object containing the `start` and `end`
6137 * positions of the view.
6139 function getView(start, end, transforms) {
6141 length = transforms.length;
6143 while (++index < length) {
6144 var data = transforms[index],
6147 switch (data.type) {
6148 case 'drop': start += size; break;
6149 case 'dropRight': end -= size; break;
6150 case 'take': end = nativeMin(end, start + size); break;
6151 case 'takeRight': start = nativeMax(start, end - size); break;
6154 return { 'start': start, 'end': end };
6158 * Extracts wrapper details from the `source` body comment.
6161 * @param {string} source The source to inspect.
6162 * @returns {Array} Returns the wrapper details.
6164 function getWrapDetails(source) {
6165 var match = source.match(reWrapDetails);
6166 return match ? match[1].split(reSplitDetails) : [];
6170 * Checks if `path` exists on `object`.
6173 * @param {Object} object The object to query.
6174 * @param {Array|string} path The path to check.
6175 * @param {Function} hasFunc The function to check properties.
6176 * @returns {boolean} Returns `true` if `path` exists, else `false`.
6178 function hasPath(object, path, hasFunc) {
6179 path = castPath(path, object);
6182 length = path.length,
6185 while (++index < length) {
6186 var key = toKey(path[index]);
6187 if (!(result = object != null && hasFunc(object, key))) {
6190 object = object[key];
6192 if (result || ++index != length) {
6195 length = object == null ? 0 : object.length;
6196 return !!length && isLength(length) && isIndex(key, length) &&
6197 (isArray(object) || isArguments(object));
6201 * Initializes an array clone.
6204 * @param {Array} array The array to clone.
6205 * @returns {Array} Returns the initialized clone.
6207 function initCloneArray(array) {
6208 var length = array.length,
6209 result = array.constructor(length);
6211 // Add properties assigned by `RegExp#exec`.
6212 if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
6213 result.index = array.index;
6214 result.input = array.input;
6220 * Initializes an object clone.
6223 * @param {Object} object The object to clone.
6224 * @returns {Object} Returns the initialized clone.
6226 function initCloneObject(object) {
6227 return (typeof object.constructor == 'function' && !isPrototype(object))
6228 ? baseCreate(getPrototype(object))
6233 * Initializes an object clone based on its `toStringTag`.
6235 * **Note:** This function only supports cloning values with tags of
6236 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
6239 * @param {Object} object The object to clone.
6240 * @param {string} tag The `toStringTag` of the object to clone.
6241 * @param {Function} cloneFunc The function to clone values.
6242 * @param {boolean} [isDeep] Specify a deep clone.
6243 * @returns {Object} Returns the initialized clone.
6245 function initCloneByTag(object, tag, cloneFunc, isDeep) {
6246 var Ctor = object.constructor;
6248 case arrayBufferTag:
6249 return cloneArrayBuffer(object);
6253 return new Ctor(+object);
6256 return cloneDataView(object, isDeep);
6258 case float32Tag: case float64Tag:
6259 case int8Tag: case int16Tag: case int32Tag:
6260 case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
6261 return cloneTypedArray(object, isDeep);
6264 return cloneMap(object, isDeep, cloneFunc);
6268 return new Ctor(object);
6271 return cloneRegExp(object);
6274 return cloneSet(object, isDeep, cloneFunc);
6277 return cloneSymbol(object);
6282 * Inserts wrapper `details` in a comment at the top of the `source` body.
6285 * @param {string} source The source to modify.
6286 * @returns {Array} details The details to insert.
6287 * @returns {string} Returns the modified source.
6289 function insertWrapDetails(source, details) {
6290 var length = details.length;
6294 var lastIndex = length - 1;
6295 details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
6296 details = details.join(length > 2 ? ', ' : ' ');
6297 return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
6301 * Checks if `value` is a flattenable `arguments` object or array.
6304 * @param {*} value The value to check.
6305 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
6307 function isFlattenable(value) {
6308 return isArray(value) || isArguments(value) ||
6309 !!(spreadableSymbol && value && value[spreadableSymbol]);
6313 * Checks if `value` is a valid array-like index.
6316 * @param {*} value The value to check.
6317 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
6318 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
6320 function isIndex(value, length) {
6321 length = length == null ? MAX_SAFE_INTEGER : length;
6323 (typeof value == 'number' || reIsUint.test(value)) &&
6324 (value > -1 && value % 1 == 0 && value < length);
6328 * Checks if the given arguments are from an iteratee call.
6331 * @param {*} value The potential iteratee value argument.
6332 * @param {*} index The potential iteratee index or key argument.
6333 * @param {*} object The potential iteratee object argument.
6334 * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
6337 function isIterateeCall(value, index, object) {
6338 if (!isObject(object)) {
6341 var type = typeof index;
6342 if (type == 'number'
6343 ? (isArrayLike(object) && isIndex(index, object.length))
6344 : (type == 'string' && index in object)
6346 return eq(object[index], value);
6352 * Checks if `value` is a property name and not a property path.
6355 * @param {*} value The value to check.
6356 * @param {Object} [object] The object to query keys on.
6357 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
6359 function isKey(value, object) {
6360 if (isArray(value)) {
6363 var type = typeof value;
6364 if (type == 'number' || type == 'symbol' || type == 'boolean' ||
6365 value == null || isSymbol(value)) {
6368 return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
6369 (object != null && value in Object(object));
6373 * Checks if `value` is suitable for use as unique object key.
6376 * @param {*} value The value to check.
6377 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
6379 function isKeyable(value) {
6380 var type = typeof value;
6381 return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
6382 ? (value !== '__proto__')
6387 * Checks if `func` has a lazy counterpart.
6390 * @param {Function} func The function to check.
6391 * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
6394 function isLaziable(func) {
6395 var funcName = getFuncName(func),
6396 other = lodash[funcName];
6398 if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
6401 if (func === other) {
6404 var data = getData(other);
6405 return !!data && func === data[0];
6409 * Checks if `func` has its source masked.
6412 * @param {Function} func The function to check.
6413 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
6415 function isMasked(func) {
6416 return !!maskSrcKey && (maskSrcKey in func);
6420 * Checks if `func` is capable of being masked.
6423 * @param {*} value The value to check.
6424 * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
6426 var isMaskable = coreJsData ? isFunction : stubFalse;
6429 * Checks if `value` is likely a prototype object.
6432 * @param {*} value The value to check.
6433 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
6435 function isPrototype(value) {
6436 var Ctor = value && value.constructor,
6437 proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
6439 return value === proto;
6443 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
6446 * @param {*} value The value to check.
6447 * @returns {boolean} Returns `true` if `value` if suitable for strict
6448 * equality comparisons, else `false`.
6450 function isStrictComparable(value) {
6451 return value === value && !isObject(value);
6455 * A specialized version of `matchesProperty` for source values suitable
6456 * for strict equality comparisons, i.e. `===`.
6459 * @param {string} key The key of the property to get.
6460 * @param {*} srcValue The value to match.
6461 * @returns {Function} Returns the new spec function.
6463 function matchesStrictComparable(key, srcValue) {
6464 return function(object) {
6465 if (object == null) {
6468 return object[key] === srcValue &&
6469 (srcValue !== undefined || (key in Object(object)));
6474 * A specialized version of `_.memoize` which clears the memoized function's
6475 * cache when it exceeds `MAX_MEMOIZE_SIZE`.
6478 * @param {Function} func The function to have its output memoized.
6479 * @returns {Function} Returns the new memoized function.
6481 function memoizeCapped(func) {
6482 var result = memoize(func, function(key) {
6483 if (cache.size === MAX_MEMOIZE_SIZE) {
6489 var cache = result.cache;
6494 * Merges the function metadata of `source` into `data`.
6496 * Merging metadata reduces the number of wrappers used to invoke a function.
6497 * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
6498 * may be applied regardless of execution order. Methods like `_.ary` and
6499 * `_.rearg` modify function arguments, making the order in which they are
6500 * executed important, preventing the merging of metadata. However, we make
6501 * an exception for a safe combined case where curried functions have `_.ary`
6502 * and or `_.rearg` applied.
6505 * @param {Array} data The destination metadata.
6506 * @param {Array} source The source metadata.
6507 * @returns {Array} Returns `data`.
6509 function mergeData(data, source) {
6510 var bitmask = data[1],
6511 srcBitmask = source[1],
6512 newBitmask = bitmask | srcBitmask,
6513 isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
6516 ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
6517 ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
6518 ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
6520 // Exit early if metadata can't be merged.
6521 if (!(isCommon || isCombo)) {
6524 // Use source `thisArg` if available.
6525 if (srcBitmask & WRAP_BIND_FLAG) {
6526 data[2] = source[2];
6527 // Set when currying a bound function.
6528 newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
6530 // Compose partial arguments.
6531 var value = source[3];
6533 var partials = data[3];
6534 data[3] = partials ? composeArgs(partials, value, source[4]) : value;
6535 data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
6537 // Compose partial right arguments.
6541 data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
6542 data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
6544 // Use source `argPos` if available.
6549 // Use source `ary` if it's smaller.
6550 if (srcBitmask & WRAP_ARY_FLAG) {
6551 data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
6553 // Use source `arity` if one is not provided.
6554 if (data[9] == null) {
6555 data[9] = source[9];
6557 // Use source `func` and merge bitmasks.
6558 data[0] = source[0];
6559 data[1] = newBitmask;
6565 * This function is like
6566 * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
6567 * except that it includes inherited enumerable properties.
6570 * @param {Object} object The object to query.
6571 * @returns {Array} Returns the array of property names.
6573 function nativeKeysIn(object) {
6575 if (object != null) {
6576 for (var key in Object(object)) {
6584 * Converts `value` to a string using `Object.prototype.toString`.
6587 * @param {*} value The value to convert.
6588 * @returns {string} Returns the converted string.
6590 function objectToString(value) {
6591 return nativeObjectToString.call(value);
6595 * A specialized version of `baseRest` which transforms the rest array.
6598 * @param {Function} func The function to apply a rest parameter to.
6599 * @param {number} [start=func.length-1] The start position of the rest parameter.
6600 * @param {Function} transform The rest array transform.
6601 * @returns {Function} Returns the new function.
6603 function overRest(func, start, transform) {
6604 start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
6606 var args = arguments,
6608 length = nativeMax(args.length - start, 0),
6609 array = Array(length);
6611 while (++index < length) {
6612 array[index] = args[start + index];
6615 var otherArgs = Array(start + 1);
6616 while (++index < start) {
6617 otherArgs[index] = args[index];
6619 otherArgs[start] = transform(array);
6620 return apply(func, this, otherArgs);
6625 * Gets the parent value at `path` of `object`.
6628 * @param {Object} object The object to query.
6629 * @param {Array} path The path to get the parent value of.
6630 * @returns {*} Returns the parent value.
6632 function parent(object, path) {
6633 return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
6637 * Reorder `array` according to the specified indexes where the element at
6638 * the first index is assigned as the first element, the element at
6639 * the second index is assigned as the second element, and so on.
6642 * @param {Array} array The array to reorder.
6643 * @param {Array} indexes The arranged array indexes.
6644 * @returns {Array} Returns `array`.
6646 function reorder(array, indexes) {
6647 var arrLength = array.length,
6648 length = nativeMin(indexes.length, arrLength),
6649 oldArray = copyArray(array);
6652 var index = indexes[length];
6653 array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
6659 * Sets metadata for `func`.
6661 * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
6662 * period of time, it will trip its breaker and transition to an identity
6663 * function to avoid garbage collection pauses in V8. See
6664 * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
6668 * @param {Function} func The function to associate metadata with.
6669 * @param {*} data The metadata.
6670 * @returns {Function} Returns `func`.
6672 var setData = shortOut(baseSetData);
6675 * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
6678 * @param {Function} func The function to delay.
6679 * @param {number} wait The number of milliseconds to delay invocation.
6680 * @returns {number|Object} Returns the timer id or timeout object.
6682 var setTimeout = ctxSetTimeout || function(func, wait) {
6683 return root.setTimeout(func, wait);
6687 * Sets the `toString` method of `func` to return `string`.
6690 * @param {Function} func The function to modify.
6691 * @param {Function} string The `toString` result.
6692 * @returns {Function} Returns `func`.
6694 var setToString = shortOut(baseSetToString);
6697 * Sets the `toString` method of `wrapper` to mimic the source of `reference`
6698 * with wrapper details in a comment at the top of the source body.
6701 * @param {Function} wrapper The function to modify.
6702 * @param {Function} reference The reference function.
6703 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6704 * @returns {Function} Returns `wrapper`.
6706 function setWrapToString(wrapper, reference, bitmask) {
6707 var source = (reference + '');
6708 return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
6712 * Creates a function that'll short out and invoke `identity` instead
6713 * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
6717 * @param {Function} func The function to restrict.
6718 * @returns {Function} Returns the new shortable function.
6720 function shortOut(func) {
6725 var stamp = nativeNow(),
6726 remaining = HOT_SPAN - (stamp - lastCalled);
6729 if (remaining > 0) {
6730 if (++count >= HOT_COUNT) {
6731 return arguments[0];
6736 return func.apply(undefined, arguments);
6741 * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
6744 * @param {Array} array The array to shuffle.
6745 * @param {number} [size=array.length] The size of `array`.
6746 * @returns {Array} Returns `array`.
6748 function shuffleSelf(array, size) {
6750 length = array.length,
6751 lastIndex = length - 1;
6753 size = size === undefined ? length : size;
6754 while (++index < size) {
6755 var rand = baseRandom(index, lastIndex),
6756 value = array[rand];
6758 array[rand] = array[index];
6759 array[index] = value;
6761 array.length = size;
6766 * Converts `string` to a property path array.
6769 * @param {string} string The string to convert.
6770 * @returns {Array} Returns the property path array.
6772 var stringToPath = memoizeCapped(function(string) {
6774 if (reLeadingDot.test(string)) {
6777 string.replace(rePropName, function(match, number, quote, string) {
6778 result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
6784 * Converts `value` to a string key if it's not a string or symbol.
6787 * @param {*} value The value to inspect.
6788 * @returns {string|symbol} Returns the key.
6790 function toKey(value) {
6791 if (typeof value == 'string' || isSymbol(value)) {
6794 var result = (value + '');
6795 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
6799 * Converts `func` to its source code.
6802 * @param {Function} func The function to convert.
6803 * @returns {string} Returns the source code.
6805 function toSource(func) {
6808 return funcToString.call(func);
6818 * Updates wrapper `details` based on `bitmask` flags.
6821 * @returns {Array} details The details to modify.
6822 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6823 * @returns {Array} Returns `details`.
6825 function updateWrapDetails(details, bitmask) {
6826 arrayEach(wrapFlags, function(pair) {
6827 var value = '_.' + pair[0];
6828 if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
6829 details.push(value);
6832 return details.sort();
6836 * Creates a clone of `wrapper`.
6839 * @param {Object} wrapper The wrapper to clone.
6840 * @returns {Object} Returns the cloned wrapper.
6842 function wrapperClone(wrapper) {
6843 if (wrapper instanceof LazyWrapper) {
6844 return wrapper.clone();
6846 var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
6847 result.__actions__ = copyArray(wrapper.__actions__);
6848 result.__index__ = wrapper.__index__;
6849 result.__values__ = wrapper.__values__;
6853 /*------------------------------------------------------------------------*/
6856 * Creates an array of elements split into groups the length of `size`.
6857 * If `array` can't be split evenly, the final chunk will be the remaining
6864 * @param {Array} array The array to process.
6865 * @param {number} [size=1] The length of each chunk
6866 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
6867 * @returns {Array} Returns the new array of chunks.
6870 * _.chunk(['a', 'b', 'c', 'd'], 2);
6871 * // => [['a', 'b'], ['c', 'd']]
6873 * _.chunk(['a', 'b', 'c', 'd'], 3);
6874 * // => [['a', 'b', 'c'], ['d']]
6876 function chunk(array, size, guard) {
6877 if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
6880 size = nativeMax(toInteger(size), 0);
6882 var length = array == null ? 0 : array.length;
6883 if (!length || size < 1) {
6888 result = Array(nativeCeil(length / size));
6890 while (index < length) {
6891 result[resIndex++] = baseSlice(array, index, (index += size));
6897 * Creates an array with all falsey values removed. The values `false`, `null`,
6898 * `0`, `""`, `undefined`, and `NaN` are falsey.
6904 * @param {Array} array The array to compact.
6905 * @returns {Array} Returns the new array of filtered values.
6908 * _.compact([0, 1, false, 2, '', 3]);
6911 function compact(array) {
6913 length = array == null ? 0 : array.length,
6917 while (++index < length) {
6918 var value = array[index];
6920 result[resIndex++] = value;
6927 * Creates a new array concatenating `array` with any additional arrays
6934 * @param {Array} array The array to concatenate.
6935 * @param {...*} [values] The values to concatenate.
6936 * @returns {Array} Returns the new concatenated array.
6940 * var other = _.concat(array, 2, [3], [[4]]);
6942 * console.log(other);
6943 * // => [1, 2, 3, [4]]
6945 * console.log(array);
6949 var length = arguments.length;
6953 var args = Array(length - 1),
6954 array = arguments[0],
6958 args[index - 1] = arguments[index];
6960 return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
6964 * Creates an array of `array` values not included in the other given arrays
6965 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
6966 * for equality comparisons. The order and references of result values are
6967 * determined by the first array.
6969 * **Note:** Unlike `_.pullAll`, this method returns a new array.
6975 * @param {Array} array The array to inspect.
6976 * @param {...Array} [values] The values to exclude.
6977 * @returns {Array} Returns the new array of filtered values.
6978 * @see _.without, _.xor
6981 * _.difference([2, 1], [2, 3]);
6984 var difference = baseRest(function(array, values) {
6985 return isArrayLikeObject(array)
6986 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
6991 * This method is like `_.difference` except that it accepts `iteratee` which
6992 * is invoked for each element of `array` and `values` to generate the criterion
6993 * by which they're compared. The order and references of result values are
6994 * determined by the first array. The iteratee is invoked with one argument:
6997 * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
7003 * @param {Array} array The array to inspect.
7004 * @param {...Array} [values] The values to exclude.
7005 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7006 * @returns {Array} Returns the new array of filtered values.
7009 * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7012 * // The `_.property` iteratee shorthand.
7013 * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
7014 * // => [{ 'x': 2 }]
7016 var differenceBy = baseRest(function(array, values) {
7017 var iteratee = last(values);
7018 if (isArrayLikeObject(iteratee)) {
7019 iteratee = undefined;
7021 return isArrayLikeObject(array)
7022 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
7027 * This method is like `_.difference` except that it accepts `comparator`
7028 * which is invoked to compare elements of `array` to `values`. The order and
7029 * references of result values are determined by the first array. The comparator
7030 * is invoked with two arguments: (arrVal, othVal).
7032 * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
7038 * @param {Array} array The array to inspect.
7039 * @param {...Array} [values] The values to exclude.
7040 * @param {Function} [comparator] The comparator invoked per element.
7041 * @returns {Array} Returns the new array of filtered values.
7044 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7046 * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
7047 * // => [{ 'x': 2, 'y': 1 }]
7049 var differenceWith = baseRest(function(array, values) {
7050 var comparator = last(values);
7051 if (isArrayLikeObject(comparator)) {
7052 comparator = undefined;
7054 return isArrayLikeObject(array)
7055 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
7060 * Creates a slice of `array` with `n` elements dropped from the beginning.
7066 * @param {Array} array The array to query.
7067 * @param {number} [n=1] The number of elements to drop.
7068 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7069 * @returns {Array} Returns the slice of `array`.
7072 * _.drop([1, 2, 3]);
7075 * _.drop([1, 2, 3], 2);
7078 * _.drop([1, 2, 3], 5);
7081 * _.drop([1, 2, 3], 0);
7084 function drop(array, n, guard) {
7085 var length = array == null ? 0 : array.length;
7089 n = (guard || n === undefined) ? 1 : toInteger(n);
7090 return baseSlice(array, n < 0 ? 0 : n, length);
7094 * Creates a slice of `array` with `n` elements dropped from the end.
7100 * @param {Array} array The array to query.
7101 * @param {number} [n=1] The number of elements to drop.
7102 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7103 * @returns {Array} Returns the slice of `array`.
7106 * _.dropRight([1, 2, 3]);
7109 * _.dropRight([1, 2, 3], 2);
7112 * _.dropRight([1, 2, 3], 5);
7115 * _.dropRight([1, 2, 3], 0);
7118 function dropRight(array, n, guard) {
7119 var length = array == null ? 0 : array.length;
7123 n = (guard || n === undefined) ? 1 : toInteger(n);
7125 return baseSlice(array, 0, n < 0 ? 0 : n);
7129 * Creates a slice of `array` excluding elements dropped from the end.
7130 * Elements are dropped until `predicate` returns falsey. The predicate is
7131 * invoked with three arguments: (value, index, array).
7137 * @param {Array} array The array to query.
7138 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7139 * @returns {Array} Returns the slice of `array`.
7143 * { 'user': 'barney', 'active': true },
7144 * { 'user': 'fred', 'active': false },
7145 * { 'user': 'pebbles', 'active': false }
7148 * _.dropRightWhile(users, function(o) { return !o.active; });
7149 * // => objects for ['barney']
7151 * // The `_.matches` iteratee shorthand.
7152 * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
7153 * // => objects for ['barney', 'fred']
7155 * // The `_.matchesProperty` iteratee shorthand.
7156 * _.dropRightWhile(users, ['active', false]);
7157 * // => objects for ['barney']
7159 * // The `_.property` iteratee shorthand.
7160 * _.dropRightWhile(users, 'active');
7161 * // => objects for ['barney', 'fred', 'pebbles']
7163 function dropRightWhile(array, predicate) {
7164 return (array && array.length)
7165 ? baseWhile(array, getIteratee(predicate, 3), true, true)
7170 * Creates a slice of `array` excluding elements dropped from the beginning.
7171 * Elements are dropped until `predicate` returns falsey. The predicate is
7172 * invoked with three arguments: (value, index, array).
7178 * @param {Array} array The array to query.
7179 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7180 * @returns {Array} Returns the slice of `array`.
7184 * { 'user': 'barney', 'active': false },
7185 * { 'user': 'fred', 'active': false },
7186 * { 'user': 'pebbles', 'active': true }
7189 * _.dropWhile(users, function(o) { return !o.active; });
7190 * // => objects for ['pebbles']
7192 * // The `_.matches` iteratee shorthand.
7193 * _.dropWhile(users, { 'user': 'barney', 'active': false });
7194 * // => objects for ['fred', 'pebbles']
7196 * // The `_.matchesProperty` iteratee shorthand.
7197 * _.dropWhile(users, ['active', false]);
7198 * // => objects for ['pebbles']
7200 * // The `_.property` iteratee shorthand.
7201 * _.dropWhile(users, 'active');
7202 * // => objects for ['barney', 'fred', 'pebbles']
7204 function dropWhile(array, predicate) {
7205 return (array && array.length)
7206 ? baseWhile(array, getIteratee(predicate, 3), true)
7211 * Fills elements of `array` with `value` from `start` up to, but not
7214 * **Note:** This method mutates `array`.
7220 * @param {Array} array The array to fill.
7221 * @param {*} value The value to fill `array` with.
7222 * @param {number} [start=0] The start position.
7223 * @param {number} [end=array.length] The end position.
7224 * @returns {Array} Returns `array`.
7227 * var array = [1, 2, 3];
7229 * _.fill(array, 'a');
7230 * console.log(array);
7231 * // => ['a', 'a', 'a']
7233 * _.fill(Array(3), 2);
7236 * _.fill([4, 6, 8, 10], '*', 1, 3);
7237 * // => [4, '*', '*', 10]
7239 function fill(array, value, start, end) {
7240 var length = array == null ? 0 : array.length;
7244 if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
7248 return baseFill(array, value, start, end);
7252 * This method is like `_.find` except that it returns the index of the first
7253 * element `predicate` returns truthy for instead of the element itself.
7259 * @param {Array} array The array to inspect.
7260 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7261 * @param {number} [fromIndex=0] The index to search from.
7262 * @returns {number} Returns the index of the found element, else `-1`.
7266 * { 'user': 'barney', 'active': false },
7267 * { 'user': 'fred', 'active': false },
7268 * { 'user': 'pebbles', 'active': true }
7271 * _.findIndex(users, function(o) { return o.user == 'barney'; });
7274 * // The `_.matches` iteratee shorthand.
7275 * _.findIndex(users, { 'user': 'fred', 'active': false });
7278 * // The `_.matchesProperty` iteratee shorthand.
7279 * _.findIndex(users, ['active', false]);
7282 * // The `_.property` iteratee shorthand.
7283 * _.findIndex(users, 'active');
7286 function findIndex(array, predicate, fromIndex) {
7287 var length = array == null ? 0 : array.length;
7291 var index = fromIndex == null ? 0 : toInteger(fromIndex);
7293 index = nativeMax(length + index, 0);
7295 return baseFindIndex(array, getIteratee(predicate, 3), index);
7299 * This method is like `_.findIndex` except that it iterates over elements
7300 * of `collection` from right to left.
7306 * @param {Array} array The array to inspect.
7307 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7308 * @param {number} [fromIndex=array.length-1] The index to search from.
7309 * @returns {number} Returns the index of the found element, else `-1`.
7313 * { 'user': 'barney', 'active': true },
7314 * { 'user': 'fred', 'active': false },
7315 * { 'user': 'pebbles', 'active': false }
7318 * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
7321 * // The `_.matches` iteratee shorthand.
7322 * _.findLastIndex(users, { 'user': 'barney', 'active': true });
7325 * // The `_.matchesProperty` iteratee shorthand.
7326 * _.findLastIndex(users, ['active', false]);
7329 * // The `_.property` iteratee shorthand.
7330 * _.findLastIndex(users, 'active');
7333 function findLastIndex(array, predicate, fromIndex) {
7334 var length = array == null ? 0 : array.length;
7338 var index = length - 1;
7339 if (fromIndex !== undefined) {
7340 index = toInteger(fromIndex);
7341 index = fromIndex < 0
7342 ? nativeMax(length + index, 0)
7343 : nativeMin(index, length - 1);
7345 return baseFindIndex(array, getIteratee(predicate, 3), index, true);
7349 * Flattens `array` a single level deep.
7355 * @param {Array} array The array to flatten.
7356 * @returns {Array} Returns the new flattened array.
7359 * _.flatten([1, [2, [3, [4]], 5]]);
7360 * // => [1, 2, [3, [4]], 5]
7362 function flatten(array) {
7363 var length = array == null ? 0 : array.length;
7364 return length ? baseFlatten(array, 1) : [];
7368 * Recursively flattens `array`.
7374 * @param {Array} array The array to flatten.
7375 * @returns {Array} Returns the new flattened array.
7378 * _.flattenDeep([1, [2, [3, [4]], 5]]);
7379 * // => [1, 2, 3, 4, 5]
7381 function flattenDeep(array) {
7382 var length = array == null ? 0 : array.length;
7383 return length ? baseFlatten(array, INFINITY) : [];
7387 * Recursively flatten `array` up to `depth` times.
7393 * @param {Array} array The array to flatten.
7394 * @param {number} [depth=1] The maximum recursion depth.
7395 * @returns {Array} Returns the new flattened array.
7398 * var array = [1, [2, [3, [4]], 5]];
7400 * _.flattenDepth(array, 1);
7401 * // => [1, 2, [3, [4]], 5]
7403 * _.flattenDepth(array, 2);
7404 * // => [1, 2, 3, [4], 5]
7406 function flattenDepth(array, depth) {
7407 var length = array == null ? 0 : array.length;
7411 depth = depth === undefined ? 1 : toInteger(depth);
7412 return baseFlatten(array, depth);
7416 * The inverse of `_.toPairs`; this method returns an object composed
7417 * from key-value `pairs`.
7423 * @param {Array} pairs The key-value pairs.
7424 * @returns {Object} Returns the new object.
7427 * _.fromPairs([['a', 1], ['b', 2]]);
7428 * // => { 'a': 1, 'b': 2 }
7430 function fromPairs(pairs) {
7432 length = pairs == null ? 0 : pairs.length,
7435 while (++index < length) {
7436 var pair = pairs[index];
7437 result[pair[0]] = pair[1];
7443 * Gets the first element of `array`.
7450 * @param {Array} array The array to query.
7451 * @returns {*} Returns the first element of `array`.
7454 * _.head([1, 2, 3]);
7460 function head(array) {
7461 return (array && array.length) ? array[0] : undefined;
7465 * Gets the index at which the first occurrence of `value` is found in `array`
7466 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7467 * for equality comparisons. If `fromIndex` is negative, it's used as the
7468 * offset from the end of `array`.
7474 * @param {Array} array The array to inspect.
7475 * @param {*} value The value to search for.
7476 * @param {number} [fromIndex=0] The index to search from.
7477 * @returns {number} Returns the index of the matched value, else `-1`.
7480 * _.indexOf([1, 2, 1, 2], 2);
7483 * // Search from the `fromIndex`.
7484 * _.indexOf([1, 2, 1, 2], 2, 2);
7487 function indexOf(array, value, fromIndex) {
7488 var length = array == null ? 0 : array.length;
7492 var index = fromIndex == null ? 0 : toInteger(fromIndex);
7494 index = nativeMax(length + index, 0);
7496 return baseIndexOf(array, value, index);
7500 * Gets all but the last element of `array`.
7506 * @param {Array} array The array to query.
7507 * @returns {Array} Returns the slice of `array`.
7510 * _.initial([1, 2, 3]);
7513 function initial(array) {
7514 var length = array == null ? 0 : array.length;
7515 return length ? baseSlice(array, 0, -1) : [];
7519 * Creates an array of unique values that are included in all given arrays
7520 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7521 * for equality comparisons. The order and references of result values are
7522 * determined by the first array.
7528 * @param {...Array} [arrays] The arrays to inspect.
7529 * @returns {Array} Returns the new array of intersecting values.
7532 * _.intersection([2, 1], [2, 3]);
7535 var intersection = baseRest(function(arrays) {
7536 var mapped = arrayMap(arrays, castArrayLikeObject);
7537 return (mapped.length && mapped[0] === arrays[0])
7538 ? baseIntersection(mapped)
7543 * This method is like `_.intersection` except that it accepts `iteratee`
7544 * which is invoked for each element of each `arrays` to generate the criterion
7545 * by which they're compared. The order and references of result values are
7546 * determined by the first array. The iteratee is invoked with one argument:
7553 * @param {...Array} [arrays] The arrays to inspect.
7554 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7555 * @returns {Array} Returns the new array of intersecting values.
7558 * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7561 * // The `_.property` iteratee shorthand.
7562 * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
7563 * // => [{ 'x': 1 }]
7565 var intersectionBy = baseRest(function(arrays) {
7566 var iteratee = last(arrays),
7567 mapped = arrayMap(arrays, castArrayLikeObject);
7569 if (iteratee === last(mapped)) {
7570 iteratee = undefined;
7574 return (mapped.length && mapped[0] === arrays[0])
7575 ? baseIntersection(mapped, getIteratee(iteratee, 2))
7580 * This method is like `_.intersection` except that it accepts `comparator`
7581 * which is invoked to compare elements of `arrays`. The order and references
7582 * of result values are determined by the first array. The comparator is
7583 * invoked with two arguments: (arrVal, othVal).
7589 * @param {...Array} [arrays] The arrays to inspect.
7590 * @param {Function} [comparator] The comparator invoked per element.
7591 * @returns {Array} Returns the new array of intersecting values.
7594 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7595 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
7597 * _.intersectionWith(objects, others, _.isEqual);
7598 * // => [{ 'x': 1, 'y': 2 }]
7600 var intersectionWith = baseRest(function(arrays) {
7601 var comparator = last(arrays),
7602 mapped = arrayMap(arrays, castArrayLikeObject);
7604 comparator = typeof comparator == 'function' ? comparator : undefined;
7608 return (mapped.length && mapped[0] === arrays[0])
7609 ? baseIntersection(mapped, undefined, comparator)
7614 * Converts all elements in `array` into a string separated by `separator`.
7620 * @param {Array} array The array to convert.
7621 * @param {string} [separator=','] The element separator.
7622 * @returns {string} Returns the joined string.
7625 * _.join(['a', 'b', 'c'], '~');
7628 function join(array, separator) {
7629 return array == null ? '' : nativeJoin.call(array, separator);
7633 * Gets the last element of `array`.
7639 * @param {Array} array The array to query.
7640 * @returns {*} Returns the last element of `array`.
7643 * _.last([1, 2, 3]);
7646 function last(array) {
7647 var length = array == null ? 0 : array.length;
7648 return length ? array[length - 1] : undefined;
7652 * This method is like `_.indexOf` except that it iterates over elements of
7653 * `array` from right to left.
7659 * @param {Array} array The array to inspect.
7660 * @param {*} value The value to search for.
7661 * @param {number} [fromIndex=array.length-1] The index to search from.
7662 * @returns {number} Returns the index of the matched value, else `-1`.
7665 * _.lastIndexOf([1, 2, 1, 2], 2);
7668 * // Search from the `fromIndex`.
7669 * _.lastIndexOf([1, 2, 1, 2], 2, 2);
7672 function lastIndexOf(array, value, fromIndex) {
7673 var length = array == null ? 0 : array.length;
7678 if (fromIndex !== undefined) {
7679 index = toInteger(fromIndex);
7680 index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
7682 return value === value
7683 ? strictLastIndexOf(array, value, index)
7684 : baseFindIndex(array, baseIsNaN, index, true);
7688 * Gets the element at index `n` of `array`. If `n` is negative, the nth
7689 * element from the end is returned.
7695 * @param {Array} array The array to query.
7696 * @param {number} [n=0] The index of the element to return.
7697 * @returns {*} Returns the nth element of `array`.
7700 * var array = ['a', 'b', 'c', 'd'];
7708 function nth(array, n) {
7709 return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
7713 * Removes all given values from `array` using
7714 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7715 * for equality comparisons.
7717 * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
7718 * to remove elements from an array by predicate.
7724 * @param {Array} array The array to modify.
7725 * @param {...*} [values] The values to remove.
7726 * @returns {Array} Returns `array`.
7729 * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7731 * _.pull(array, 'a', 'c');
7732 * console.log(array);
7735 var pull = baseRest(pullAll);
7738 * This method is like `_.pull` except that it accepts an array of values to remove.
7740 * **Note:** Unlike `_.difference`, this method mutates `array`.
7746 * @param {Array} array The array to modify.
7747 * @param {Array} values The values to remove.
7748 * @returns {Array} Returns `array`.
7751 * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7753 * _.pullAll(array, ['a', 'c']);
7754 * console.log(array);
7757 function pullAll(array, values) {
7758 return (array && array.length && values && values.length)
7759 ? basePullAll(array, values)
7764 * This method is like `_.pullAll` except that it accepts `iteratee` which is
7765 * invoked for each element of `array` and `values` to generate the criterion
7766 * by which they're compared. The iteratee is invoked with one argument: (value).
7768 * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
7774 * @param {Array} array The array to modify.
7775 * @param {Array} values The values to remove.
7776 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7777 * @returns {Array} Returns `array`.
7780 * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
7782 * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
7783 * console.log(array);
7784 * // => [{ 'x': 2 }]
7786 function pullAllBy(array, values, iteratee) {
7787 return (array && array.length && values && values.length)
7788 ? basePullAll(array, values, getIteratee(iteratee, 2))
7793 * This method is like `_.pullAll` except that it accepts `comparator` which
7794 * is invoked to compare elements of `array` to `values`. The comparator is
7795 * invoked with two arguments: (arrVal, othVal).
7797 * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
7803 * @param {Array} array The array to modify.
7804 * @param {Array} values The values to remove.
7805 * @param {Function} [comparator] The comparator invoked per element.
7806 * @returns {Array} Returns `array`.
7809 * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
7811 * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
7812 * console.log(array);
7813 * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
7815 function pullAllWith(array, values, comparator) {
7816 return (array && array.length && values && values.length)
7817 ? basePullAll(array, values, undefined, comparator)
7822 * Removes elements from `array` corresponding to `indexes` and returns an
7823 * array of removed elements.
7825 * **Note:** Unlike `_.at`, this method mutates `array`.
7831 * @param {Array} array The array to modify.
7832 * @param {...(number|number[])} [indexes] The indexes of elements to remove.
7833 * @returns {Array} Returns the new array of removed elements.
7836 * var array = ['a', 'b', 'c', 'd'];
7837 * var pulled = _.pullAt(array, [1, 3]);
7839 * console.log(array);
7842 * console.log(pulled);
7845 var pullAt = flatRest(function(array, indexes) {
7846 var length = array == null ? 0 : array.length,
7847 result = baseAt(array, indexes);
7849 basePullAt(array, arrayMap(indexes, function(index) {
7850 return isIndex(index, length) ? +index : index;
7851 }).sort(compareAscending));
7857 * Removes all elements from `array` that `predicate` returns truthy for
7858 * and returns an array of the removed elements. The predicate is invoked
7859 * with three arguments: (value, index, array).
7861 * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
7862 * to pull elements from an array by value.
7868 * @param {Array} array The array to modify.
7869 * @param {Function} [predicate=_.identity] The function invoked per iteration.
7870 * @returns {Array} Returns the new array of removed elements.
7873 * var array = [1, 2, 3, 4];
7874 * var evens = _.remove(array, function(n) {
7875 * return n % 2 == 0;
7878 * console.log(array);
7881 * console.log(evens);
7884 function remove(array, predicate) {
7886 if (!(array && array.length)) {
7891 length = array.length;
7893 predicate = getIteratee(predicate, 3);
7894 while (++index < length) {
7895 var value = array[index];
7896 if (predicate(value, index, array)) {
7898 indexes.push(index);
7901 basePullAt(array, indexes);
7906 * Reverses `array` so that the first element becomes the last, the second
7907 * element becomes the second to last, and so on.
7909 * **Note:** This method mutates `array` and is based on
7910 * [`Array#reverse`](https://mdn.io/Array/reverse).
7916 * @param {Array} array The array to modify.
7917 * @returns {Array} Returns `array`.
7920 * var array = [1, 2, 3];
7925 * console.log(array);
7928 function reverse(array) {
7929 return array == null ? array : nativeReverse.call(array);
7933 * Creates a slice of `array` from `start` up to, but not including, `end`.
7935 * **Note:** This method is used instead of
7936 * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
7943 * @param {Array} array The array to slice.
7944 * @param {number} [start=0] The start position.
7945 * @param {number} [end=array.length] The end position.
7946 * @returns {Array} Returns the slice of `array`.
7948 function slice(array, start, end) {
7949 var length = array == null ? 0 : array.length;
7953 if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
7958 start = start == null ? 0 : toInteger(start);
7959 end = end === undefined ? length : toInteger(end);
7961 return baseSlice(array, start, end);
7965 * Uses a binary search to determine the lowest index at which `value`
7966 * should be inserted into `array` in order to maintain its sort order.
7972 * @param {Array} array The sorted array to inspect.
7973 * @param {*} value The value to evaluate.
7974 * @returns {number} Returns the index at which `value` should be inserted
7978 * _.sortedIndex([30, 50], 40);
7981 function sortedIndex(array, value) {
7982 return baseSortedIndex(array, value);
7986 * This method is like `_.sortedIndex` except that it accepts `iteratee`
7987 * which is invoked for `value` and each element of `array` to compute their
7988 * sort ranking. The iteratee is invoked with one argument: (value).
7994 * @param {Array} array The sorted array to inspect.
7995 * @param {*} value The value to evaluate.
7996 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7997 * @returns {number} Returns the index at which `value` should be inserted
8001 * var objects = [{ 'x': 4 }, { 'x': 5 }];
8003 * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8006 * // The `_.property` iteratee shorthand.
8007 * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
8010 function sortedIndexBy(array, value, iteratee) {
8011 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
8015 * This method is like `_.indexOf` except that it performs a binary
8016 * search on a sorted `array`.
8022 * @param {Array} array The array to inspect.
8023 * @param {*} value The value to search for.
8024 * @returns {number} Returns the index of the matched value, else `-1`.
8027 * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
8030 function sortedIndexOf(array, value) {
8031 var length = array == null ? 0 : array.length;
8033 var index = baseSortedIndex(array, value);
8034 if (index < length && eq(array[index], value)) {
8042 * This method is like `_.sortedIndex` except that it returns the highest
8043 * index at which `value` should be inserted into `array` in order to
8044 * maintain its sort order.
8050 * @param {Array} array The sorted array to inspect.
8051 * @param {*} value The value to evaluate.
8052 * @returns {number} Returns the index at which `value` should be inserted
8056 * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
8059 function sortedLastIndex(array, value) {
8060 return baseSortedIndex(array, value, true);
8064 * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
8065 * which is invoked for `value` and each element of `array` to compute their
8066 * sort ranking. The iteratee is invoked with one argument: (value).
8072 * @param {Array} array The sorted array to inspect.
8073 * @param {*} value The value to evaluate.
8074 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8075 * @returns {number} Returns the index at which `value` should be inserted
8079 * var objects = [{ 'x': 4 }, { 'x': 5 }];
8081 * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8084 * // The `_.property` iteratee shorthand.
8085 * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
8088 function sortedLastIndexBy(array, value, iteratee) {
8089 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
8093 * This method is like `_.lastIndexOf` except that it performs a binary
8094 * search on a sorted `array`.
8100 * @param {Array} array The array to inspect.
8101 * @param {*} value The value to search for.
8102 * @returns {number} Returns the index of the matched value, else `-1`.
8105 * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
8108 function sortedLastIndexOf(array, value) {
8109 var length = array == null ? 0 : array.length;
8111 var index = baseSortedIndex(array, value, true) - 1;
8112 if (eq(array[index], value)) {
8120 * This method is like `_.uniq` except that it's designed and optimized
8121 * for sorted arrays.
8127 * @param {Array} array The array to inspect.
8128 * @returns {Array} Returns the new duplicate free array.
8131 * _.sortedUniq([1, 1, 2]);
8134 function sortedUniq(array) {
8135 return (array && array.length)
8136 ? baseSortedUniq(array)
8141 * This method is like `_.uniqBy` except that it's designed and optimized
8142 * for sorted arrays.
8148 * @param {Array} array The array to inspect.
8149 * @param {Function} [iteratee] The iteratee invoked per element.
8150 * @returns {Array} Returns the new duplicate free array.
8153 * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
8156 function sortedUniqBy(array, iteratee) {
8157 return (array && array.length)
8158 ? baseSortedUniq(array, getIteratee(iteratee, 2))
8163 * Gets all but the first element of `array`.
8169 * @param {Array} array The array to query.
8170 * @returns {Array} Returns the slice of `array`.
8173 * _.tail([1, 2, 3]);
8176 function tail(array) {
8177 var length = array == null ? 0 : array.length;
8178 return length ? baseSlice(array, 1, length) : [];
8182 * Creates a slice of `array` with `n` elements taken from the beginning.
8188 * @param {Array} array The array to query.
8189 * @param {number} [n=1] The number of elements to take.
8190 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8191 * @returns {Array} Returns the slice of `array`.
8194 * _.take([1, 2, 3]);
8197 * _.take([1, 2, 3], 2);
8200 * _.take([1, 2, 3], 5);
8203 * _.take([1, 2, 3], 0);
8206 function take(array, n, guard) {
8207 if (!(array && array.length)) {
8210 n = (guard || n === undefined) ? 1 : toInteger(n);
8211 return baseSlice(array, 0, n < 0 ? 0 : n);
8215 * Creates a slice of `array` with `n` elements taken from the end.
8221 * @param {Array} array The array to query.
8222 * @param {number} [n=1] The number of elements to take.
8223 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8224 * @returns {Array} Returns the slice of `array`.
8227 * _.takeRight([1, 2, 3]);
8230 * _.takeRight([1, 2, 3], 2);
8233 * _.takeRight([1, 2, 3], 5);
8236 * _.takeRight([1, 2, 3], 0);
8239 function takeRight(array, n, guard) {
8240 var length = array == null ? 0 : array.length;
8244 n = (guard || n === undefined) ? 1 : toInteger(n);
8246 return baseSlice(array, n < 0 ? 0 : n, length);
8250 * Creates a slice of `array` with elements taken from the end. Elements are
8251 * taken until `predicate` returns falsey. The predicate is invoked with
8252 * three arguments: (value, index, array).
8258 * @param {Array} array The array to query.
8259 * @param {Function} [predicate=_.identity] The function invoked per iteration.
8260 * @returns {Array} Returns the slice of `array`.
8264 * { 'user': 'barney', 'active': true },
8265 * { 'user': 'fred', 'active': false },
8266 * { 'user': 'pebbles', 'active': false }
8269 * _.takeRightWhile(users, function(o) { return !o.active; });
8270 * // => objects for ['fred', 'pebbles']
8272 * // The `_.matches` iteratee shorthand.
8273 * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
8274 * // => objects for ['pebbles']
8276 * // The `_.matchesProperty` iteratee shorthand.
8277 * _.takeRightWhile(users, ['active', false]);
8278 * // => objects for ['fred', 'pebbles']
8280 * // The `_.property` iteratee shorthand.
8281 * _.takeRightWhile(users, 'active');
8284 function takeRightWhile(array, predicate) {
8285 return (array && array.length)
8286 ? baseWhile(array, getIteratee(predicate, 3), false, true)
8291 * Creates a slice of `array` with elements taken from the beginning. Elements
8292 * are taken until `predicate` returns falsey. The predicate is invoked with
8293 * three arguments: (value, index, array).
8299 * @param {Array} array The array to query.
8300 * @param {Function} [predicate=_.identity] The function invoked per iteration.
8301 * @returns {Array} Returns the slice of `array`.
8305 * { 'user': 'barney', 'active': false },
8306 * { 'user': 'fred', 'active': false },
8307 * { 'user': 'pebbles', 'active': true }
8310 * _.takeWhile(users, function(o) { return !o.active; });
8311 * // => objects for ['barney', 'fred']
8313 * // The `_.matches` iteratee shorthand.
8314 * _.takeWhile(users, { 'user': 'barney', 'active': false });
8315 * // => objects for ['barney']
8317 * // The `_.matchesProperty` iteratee shorthand.
8318 * _.takeWhile(users, ['active', false]);
8319 * // => objects for ['barney', 'fred']
8321 * // The `_.property` iteratee shorthand.
8322 * _.takeWhile(users, 'active');
8325 function takeWhile(array, predicate) {
8326 return (array && array.length)
8327 ? baseWhile(array, getIteratee(predicate, 3))
8332 * Creates an array of unique values, in order, from all given arrays using
8333 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8334 * for equality comparisons.
8340 * @param {...Array} [arrays] The arrays to inspect.
8341 * @returns {Array} Returns the new array of combined values.
8344 * _.union([2], [1, 2]);
8347 var union = baseRest(function(arrays) {
8348 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
8352 * This method is like `_.union` except that it accepts `iteratee` which is
8353 * invoked for each element of each `arrays` to generate the criterion by
8354 * which uniqueness is computed. Result values are chosen from the first
8355 * array in which the value occurs. The iteratee is invoked with one argument:
8362 * @param {...Array} [arrays] The arrays to inspect.
8363 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8364 * @returns {Array} Returns the new array of combined values.
8367 * _.unionBy([2.1], [1.2, 2.3], Math.floor);
8370 * // The `_.property` iteratee shorthand.
8371 * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8372 * // => [{ 'x': 1 }, { 'x': 2 }]
8374 var unionBy = baseRest(function(arrays) {
8375 var iteratee = last(arrays);
8376 if (isArrayLikeObject(iteratee)) {
8377 iteratee = undefined;
8379 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
8383 * This method is like `_.union` except that it accepts `comparator` which
8384 * is invoked to compare elements of `arrays`. Result values are chosen from
8385 * the first array in which the value occurs. The comparator is invoked
8386 * with two arguments: (arrVal, othVal).
8392 * @param {...Array} [arrays] The arrays to inspect.
8393 * @param {Function} [comparator] The comparator invoked per element.
8394 * @returns {Array} Returns the new array of combined values.
8397 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8398 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8400 * _.unionWith(objects, others, _.isEqual);
8401 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8403 var unionWith = baseRest(function(arrays) {
8404 var comparator = last(arrays);
8405 comparator = typeof comparator == 'function' ? comparator : undefined;
8406 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
8410 * Creates a duplicate-free version of an array, using
8411 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8412 * for equality comparisons, in which only the first occurrence of each element
8413 * is kept. The order of result values is determined by the order they occur
8420 * @param {Array} array The array to inspect.
8421 * @returns {Array} Returns the new duplicate free array.
8424 * _.uniq([2, 1, 2]);
8427 function uniq(array) {
8428 return (array && array.length) ? baseUniq(array) : [];
8432 * This method is like `_.uniq` except that it accepts `iteratee` which is
8433 * invoked for each element in `array` to generate the criterion by which
8434 * uniqueness is computed. The order of result values is determined by the
8435 * order they occur in the array. The iteratee is invoked with one argument:
8442 * @param {Array} array The array to inspect.
8443 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8444 * @returns {Array} Returns the new duplicate free array.
8447 * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
8450 * // The `_.property` iteratee shorthand.
8451 * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
8452 * // => [{ 'x': 1 }, { 'x': 2 }]
8454 function uniqBy(array, iteratee) {
8455 return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
8459 * This method is like `_.uniq` except that it accepts `comparator` which
8460 * is invoked to compare elements of `array`. The order of result values is
8461 * determined by the order they occur in the array.The comparator is invoked
8462 * with two arguments: (arrVal, othVal).
8468 * @param {Array} array The array to inspect.
8469 * @param {Function} [comparator] The comparator invoked per element.
8470 * @returns {Array} Returns the new duplicate free array.
8473 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
8475 * _.uniqWith(objects, _.isEqual);
8476 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
8478 function uniqWith(array, comparator) {
8479 comparator = typeof comparator == 'function' ? comparator : undefined;
8480 return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
8484 * This method is like `_.zip` except that it accepts an array of grouped
8485 * elements and creates an array regrouping the elements to their pre-zip
8492 * @param {Array} array The array of grouped elements to process.
8493 * @returns {Array} Returns the new array of regrouped elements.
8496 * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
8497 * // => [['a', 1, true], ['b', 2, false]]
8500 * // => [['a', 'b'], [1, 2], [true, false]]
8502 function unzip(array) {
8503 if (!(array && array.length)) {
8507 array = arrayFilter(array, function(group) {
8508 if (isArrayLikeObject(group)) {
8509 length = nativeMax(group.length, length);
8513 return baseTimes(length, function(index) {
8514 return arrayMap(array, baseProperty(index));
8519 * This method is like `_.unzip` except that it accepts `iteratee` to specify
8520 * how regrouped values should be combined. The iteratee is invoked with the
8521 * elements of each group: (...group).
8527 * @param {Array} array The array of grouped elements to process.
8528 * @param {Function} [iteratee=_.identity] The function to combine
8530 * @returns {Array} Returns the new array of regrouped elements.
8533 * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
8534 * // => [[1, 10, 100], [2, 20, 200]]
8536 * _.unzipWith(zipped, _.add);
8537 * // => [3, 30, 300]
8539 function unzipWith(array, iteratee) {
8540 if (!(array && array.length)) {
8543 var result = unzip(array);
8544 if (iteratee == null) {
8547 return arrayMap(result, function(group) {
8548 return apply(iteratee, undefined, group);
8553 * Creates an array excluding all given values using
8554 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8555 * for equality comparisons.
8557 * **Note:** Unlike `_.pull`, this method returns a new array.
8563 * @param {Array} array The array to inspect.
8564 * @param {...*} [values] The values to exclude.
8565 * @returns {Array} Returns the new array of filtered values.
8566 * @see _.difference, _.xor
8569 * _.without([2, 1, 2, 3], 1, 2);
8572 var without = baseRest(function(array, values) {
8573 return isArrayLikeObject(array)
8574 ? baseDifference(array, values)
8579 * Creates an array of unique values that is the
8580 * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
8581 * of the given arrays. The order of result values is determined by the order
8582 * they occur in the arrays.
8588 * @param {...Array} [arrays] The arrays to inspect.
8589 * @returns {Array} Returns the new array of filtered values.
8590 * @see _.difference, _.without
8593 * _.xor([2, 1], [2, 3]);
8596 var xor = baseRest(function(arrays) {
8597 return baseXor(arrayFilter(arrays, isArrayLikeObject));
8601 * This method is like `_.xor` except that it accepts `iteratee` which is
8602 * invoked for each element of each `arrays` to generate the criterion by
8603 * which by which they're compared. The order of result values is determined
8604 * by the order they occur in the arrays. The iteratee is invoked with one
8605 * argument: (value).
8611 * @param {...Array} [arrays] The arrays to inspect.
8612 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8613 * @returns {Array} Returns the new array of filtered values.
8616 * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
8619 * // The `_.property` iteratee shorthand.
8620 * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8621 * // => [{ 'x': 2 }]
8623 var xorBy = baseRest(function(arrays) {
8624 var iteratee = last(arrays);
8625 if (isArrayLikeObject(iteratee)) {
8626 iteratee = undefined;
8628 return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
8632 * This method is like `_.xor` except that it accepts `comparator` which is
8633 * invoked to compare elements of `arrays`. The order of result values is
8634 * determined by the order they occur in the arrays. The comparator is invoked
8635 * with two arguments: (arrVal, othVal).
8641 * @param {...Array} [arrays] The arrays to inspect.
8642 * @param {Function} [comparator] The comparator invoked per element.
8643 * @returns {Array} Returns the new array of filtered values.
8646 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8647 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8649 * _.xorWith(objects, others, _.isEqual);
8650 * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8652 var xorWith = baseRest(function(arrays) {
8653 var comparator = last(arrays);
8654 comparator = typeof comparator == 'function' ? comparator : undefined;
8655 return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
8659 * Creates an array of grouped elements, the first of which contains the
8660 * first elements of the given arrays, the second of which contains the
8661 * second elements of the given arrays, and so on.
8667 * @param {...Array} [arrays] The arrays to process.
8668 * @returns {Array} Returns the new array of grouped elements.
8671 * _.zip(['a', 'b'], [1, 2], [true, false]);
8672 * // => [['a', 1, true], ['b', 2, false]]
8674 var zip = baseRest(unzip);
8677 * This method is like `_.fromPairs` except that it accepts two arrays,
8678 * one of property identifiers and one of corresponding values.
8684 * @param {Array} [props=[]] The property identifiers.
8685 * @param {Array} [values=[]] The property values.
8686 * @returns {Object} Returns the new object.
8689 * _.zipObject(['a', 'b'], [1, 2]);
8690 * // => { 'a': 1, 'b': 2 }
8692 function zipObject(props, values) {
8693 return baseZipObject(props || [], values || [], assignValue);
8697 * This method is like `_.zipObject` except that it supports property paths.
8703 * @param {Array} [props=[]] The property identifiers.
8704 * @param {Array} [values=[]] The property values.
8705 * @returns {Object} Returns the new object.
8708 * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
8709 * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
8711 function zipObjectDeep(props, values) {
8712 return baseZipObject(props || [], values || [], baseSet);
8716 * This method is like `_.zip` except that it accepts `iteratee` to specify
8717 * how grouped values should be combined. The iteratee is invoked with the
8718 * elements of each group: (...group).
8724 * @param {...Array} [arrays] The arrays to process.
8725 * @param {Function} [iteratee=_.identity] The function to combine
8727 * @returns {Array} Returns the new array of grouped elements.
8730 * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
8735 var zipWith = baseRest(function(arrays) {
8736 var length = arrays.length,
8737 iteratee = length > 1 ? arrays[length - 1] : undefined;
8739 iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
8740 return unzipWith(arrays, iteratee);
8743 /*------------------------------------------------------------------------*/
8746 * Creates a `lodash` wrapper instance that wraps `value` with explicit method
8747 * chain sequences enabled. The result of such sequences must be unwrapped
8754 * @param {*} value The value to wrap.
8755 * @returns {Object} Returns the new `lodash` wrapper instance.
8759 * { 'user': 'barney', 'age': 36 },
8760 * { 'user': 'fred', 'age': 40 },
8761 * { 'user': 'pebbles', 'age': 1 }
8767 * .map(function(o) {
8768 * return o.user + ' is ' + o.age;
8772 * // => 'pebbles is 1'
8774 function chain(value) {
8775 var result = lodash(value);
8776 result.__chain__ = true;
8781 * This method invokes `interceptor` and returns `value`. The interceptor
8782 * is invoked with one argument; (value). The purpose of this method is to
8783 * "tap into" a method chain sequence in order to modify intermediate results.
8789 * @param {*} value The value to provide to `interceptor`.
8790 * @param {Function} interceptor The function to invoke.
8791 * @returns {*} Returns `value`.
8795 * .tap(function(array) {
8796 * // Mutate input array.
8803 function tap(value, interceptor) {
8809 * This method is like `_.tap` except that it returns the result of `interceptor`.
8810 * The purpose of this method is to "pass thru" values replacing intermediate
8811 * results in a method chain sequence.
8817 * @param {*} value The value to provide to `interceptor`.
8818 * @param {Function} interceptor The function to invoke.
8819 * @returns {*} Returns the result of `interceptor`.
8825 * .thru(function(value) {
8831 function thru(value, interceptor) {
8832 return interceptor(value);
8836 * This method is the wrapper version of `_.at`.
8842 * @param {...(string|string[])} [paths] The property paths to pick.
8843 * @returns {Object} Returns the new `lodash` wrapper instance.
8846 * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
8848 * _(object).at(['a[0].b.c', 'a[1]']).value();
8851 var wrapperAt = flatRest(function(paths) {
8852 var length = paths.length,
8853 start = length ? paths[0] : 0,
8854 value = this.__wrapped__,
8855 interceptor = function(object) { return baseAt(object, paths); };
8857 if (length > 1 || this.__actions__.length ||
8858 !(value instanceof LazyWrapper) || !isIndex(start)) {
8859 return this.thru(interceptor);
8861 value = value.slice(start, +start + (length ? 1 : 0));
8862 value.__actions__.push({
8864 'args': [interceptor],
8865 'thisArg': undefined
8867 return new LodashWrapper(value, this.__chain__).thru(function(array) {
8868 if (length && !array.length) {
8869 array.push(undefined);
8876 * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
8882 * @returns {Object} Returns the new `lodash` wrapper instance.
8886 * { 'user': 'barney', 'age': 36 },
8887 * { 'user': 'fred', 'age': 40 }
8890 * // A sequence without explicit chaining.
8892 * // => { 'user': 'barney', 'age': 36 }
8894 * // A sequence with explicit chaining.
8900 * // => { 'user': 'barney' }
8902 function wrapperChain() {
8907 * Executes the chain sequence and returns the wrapped result.
8913 * @returns {Object} Returns the new `lodash` wrapper instance.
8916 * var array = [1, 2];
8917 * var wrapped = _(array).push(3);
8919 * console.log(array);
8922 * wrapped = wrapped.commit();
8923 * console.log(array);
8929 * console.log(array);
8932 function wrapperCommit() {
8933 return new LodashWrapper(this.value(), this.__chain__);
8937 * Gets the next value on a wrapped object following the
8938 * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
8944 * @returns {Object} Returns the next iterator value.
8947 * var wrapped = _([1, 2]);
8950 * // => { 'done': false, 'value': 1 }
8953 * // => { 'done': false, 'value': 2 }
8956 * // => { 'done': true, 'value': undefined }
8958 function wrapperNext() {
8959 if (this.__values__ === undefined) {
8960 this.__values__ = toArray(this.value());
8962 var done = this.__index__ >= this.__values__.length,
8963 value = done ? undefined : this.__values__[this.__index__++];
8965 return { 'done': done, 'value': value };
8969 * Enables the wrapper to be iterable.
8971 * @name Symbol.iterator
8975 * @returns {Object} Returns the wrapper object.
8978 * var wrapped = _([1, 2]);
8980 * wrapped[Symbol.iterator]() === wrapped;
8983 * Array.from(wrapped);
8986 function wrapperToIterator() {
8991 * Creates a clone of the chain sequence planting `value` as the wrapped value.
8997 * @param {*} value The value to plant.
8998 * @returns {Object} Returns the new `lodash` wrapper instance.
9001 * function square(n) {
9005 * var wrapped = _([1, 2]).map(square);
9006 * var other = wrapped.plant([3, 4]);
9014 function wrapperPlant(value) {
9018 while (parent instanceof baseLodash) {
9019 var clone = wrapperClone(parent);
9020 clone.__index__ = 0;
9021 clone.__values__ = undefined;
9023 previous.__wrapped__ = clone;
9027 var previous = clone;
9028 parent = parent.__wrapped__;
9030 previous.__wrapped__ = value;
9035 * This method is the wrapper version of `_.reverse`.
9037 * **Note:** This method mutates the wrapped array.
9043 * @returns {Object} Returns the new `lodash` wrapper instance.
9046 * var array = [1, 2, 3];
9048 * _(array).reverse().value()
9051 * console.log(array);
9054 function wrapperReverse() {
9055 var value = this.__wrapped__;
9056 if (value instanceof LazyWrapper) {
9057 var wrapped = value;
9058 if (this.__actions__.length) {
9059 wrapped = new LazyWrapper(this);
9061 wrapped = wrapped.reverse();
9062 wrapped.__actions__.push({
9065 'thisArg': undefined
9067 return new LodashWrapper(wrapped, this.__chain__);
9069 return this.thru(reverse);
9073 * Executes the chain sequence to resolve the unwrapped value.
9078 * @alias toJSON, valueOf
9080 * @returns {*} Returns the resolved unwrapped value.
9083 * _([1, 2, 3]).value();
9086 function wrapperValue() {
9087 return baseWrapperValue(this.__wrapped__, this.__actions__);
9090 /*------------------------------------------------------------------------*/
9093 * Creates an object composed of keys generated from the results of running
9094 * each element of `collection` thru `iteratee`. The corresponding value of
9095 * each key is the number of times the key was returned by `iteratee`. The
9096 * iteratee is invoked with one argument: (value).
9101 * @category Collection
9102 * @param {Array|Object} collection The collection to iterate over.
9103 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9104 * @returns {Object} Returns the composed aggregate object.
9107 * _.countBy([6.1, 4.2, 6.3], Math.floor);
9108 * // => { '4': 1, '6': 2 }
9110 * // The `_.property` iteratee shorthand.
9111 * _.countBy(['one', 'two', 'three'], 'length');
9112 * // => { '3': 2, '5': 1 }
9114 var countBy = createAggregator(function(result, value, key) {
9115 if (hasOwnProperty.call(result, key)) {
9118 baseAssignValue(result, key, 1);
9123 * Checks if `predicate` returns truthy for **all** elements of `collection`.
9124 * Iteration is stopped once `predicate` returns falsey. The predicate is
9125 * invoked with three arguments: (value, index|key, collection).
9127 * **Note:** This method returns `true` for
9128 * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
9129 * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
9130 * elements of empty collections.
9135 * @category Collection
9136 * @param {Array|Object} collection The collection to iterate over.
9137 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9138 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9139 * @returns {boolean} Returns `true` if all elements pass the predicate check,
9143 * _.every([true, 1, null, 'yes'], Boolean);
9147 * { 'user': 'barney', 'age': 36, 'active': false },
9148 * { 'user': 'fred', 'age': 40, 'active': false }
9151 * // The `_.matches` iteratee shorthand.
9152 * _.every(users, { 'user': 'barney', 'active': false });
9155 * // The `_.matchesProperty` iteratee shorthand.
9156 * _.every(users, ['active', false]);
9159 * // The `_.property` iteratee shorthand.
9160 * _.every(users, 'active');
9163 function every(collection, predicate, guard) {
9164 var func = isArray(collection) ? arrayEvery : baseEvery;
9165 if (guard && isIterateeCall(collection, predicate, guard)) {
9166 predicate = undefined;
9168 return func(collection, getIteratee(predicate, 3));
9172 * Iterates over elements of `collection`, returning an array of all elements
9173 * `predicate` returns truthy for. The predicate is invoked with three
9174 * arguments: (value, index|key, collection).
9176 * **Note:** Unlike `_.remove`, this method returns a new array.
9181 * @category Collection
9182 * @param {Array|Object} collection The collection to iterate over.
9183 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9184 * @returns {Array} Returns the new filtered array.
9189 * { 'user': 'barney', 'age': 36, 'active': true },
9190 * { 'user': 'fred', 'age': 40, 'active': false }
9193 * _.filter(users, function(o) { return !o.active; });
9194 * // => objects for ['fred']
9196 * // The `_.matches` iteratee shorthand.
9197 * _.filter(users, { 'age': 36, 'active': true });
9198 * // => objects for ['barney']
9200 * // The `_.matchesProperty` iteratee shorthand.
9201 * _.filter(users, ['active', false]);
9202 * // => objects for ['fred']
9204 * // The `_.property` iteratee shorthand.
9205 * _.filter(users, 'active');
9206 * // => objects for ['barney']
9208 function filter(collection, predicate) {
9209 var func = isArray(collection) ? arrayFilter : baseFilter;
9210 return func(collection, getIteratee(predicate, 3));
9214 * Iterates over elements of `collection`, returning the first element
9215 * `predicate` returns truthy for. The predicate is invoked with three
9216 * arguments: (value, index|key, collection).
9221 * @category Collection
9222 * @param {Array|Object} collection The collection to inspect.
9223 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9224 * @param {number} [fromIndex=0] The index to search from.
9225 * @returns {*} Returns the matched element, else `undefined`.
9229 * { 'user': 'barney', 'age': 36, 'active': true },
9230 * { 'user': 'fred', 'age': 40, 'active': false },
9231 * { 'user': 'pebbles', 'age': 1, 'active': true }
9234 * _.find(users, function(o) { return o.age < 40; });
9235 * // => object for 'barney'
9237 * // The `_.matches` iteratee shorthand.
9238 * _.find(users, { 'age': 1, 'active': true });
9239 * // => object for 'pebbles'
9241 * // The `_.matchesProperty` iteratee shorthand.
9242 * _.find(users, ['active', false]);
9243 * // => object for 'fred'
9245 * // The `_.property` iteratee shorthand.
9246 * _.find(users, 'active');
9247 * // => object for 'barney'
9249 var find = createFind(findIndex);
9252 * This method is like `_.find` except that it iterates over elements of
9253 * `collection` from right to left.
9258 * @category Collection
9259 * @param {Array|Object} collection The collection to inspect.
9260 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9261 * @param {number} [fromIndex=collection.length-1] The index to search from.
9262 * @returns {*} Returns the matched element, else `undefined`.
9265 * _.findLast([1, 2, 3, 4], function(n) {
9266 * return n % 2 == 1;
9270 var findLast = createFind(findLastIndex);
9273 * Creates a flattened array of values by running each element in `collection`
9274 * thru `iteratee` and flattening the mapped results. The iteratee is invoked
9275 * with three arguments: (value, index|key, collection).
9280 * @category Collection
9281 * @param {Array|Object} collection The collection to iterate over.
9282 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9283 * @returns {Array} Returns the new flattened array.
9286 * function duplicate(n) {
9290 * _.flatMap([1, 2], duplicate);
9291 * // => [1, 1, 2, 2]
9293 function flatMap(collection, iteratee) {
9294 return baseFlatten(map(collection, iteratee), 1);
9298 * This method is like `_.flatMap` except that it recursively flattens the
9304 * @category Collection
9305 * @param {Array|Object} collection The collection to iterate over.
9306 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9307 * @returns {Array} Returns the new flattened array.
9310 * function duplicate(n) {
9311 * return [[[n, n]]];
9314 * _.flatMapDeep([1, 2], duplicate);
9315 * // => [1, 1, 2, 2]
9317 function flatMapDeep(collection, iteratee) {
9318 return baseFlatten(map(collection, iteratee), INFINITY);
9322 * This method is like `_.flatMap` except that it recursively flattens the
9323 * mapped results up to `depth` times.
9328 * @category Collection
9329 * @param {Array|Object} collection The collection to iterate over.
9330 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9331 * @param {number} [depth=1] The maximum recursion depth.
9332 * @returns {Array} Returns the new flattened array.
9335 * function duplicate(n) {
9336 * return [[[n, n]]];
9339 * _.flatMapDepth([1, 2], duplicate, 2);
9340 * // => [[1, 1], [2, 2]]
9342 function flatMapDepth(collection, iteratee, depth) {
9343 depth = depth === undefined ? 1 : toInteger(depth);
9344 return baseFlatten(map(collection, iteratee), depth);
9348 * Iterates over elements of `collection` and invokes `iteratee` for each element.
9349 * The iteratee is invoked with three arguments: (value, index|key, collection).
9350 * Iteratee functions may exit iteration early by explicitly returning `false`.
9352 * **Note:** As with other "Collections" methods, objects with a "length"
9353 * property are iterated like arrays. To avoid this behavior use `_.forIn`
9354 * or `_.forOwn` for object iteration.
9360 * @category Collection
9361 * @param {Array|Object} collection The collection to iterate over.
9362 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9363 * @returns {Array|Object} Returns `collection`.
9364 * @see _.forEachRight
9367 * _.forEach([1, 2], function(value) {
9368 * console.log(value);
9370 * // => Logs `1` then `2`.
9372 * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
9375 * // => Logs 'a' then 'b' (iteration order is not guaranteed).
9377 function forEach(collection, iteratee) {
9378 var func = isArray(collection) ? arrayEach : baseEach;
9379 return func(collection, getIteratee(iteratee, 3));
9383 * This method is like `_.forEach` except that it iterates over elements of
9384 * `collection` from right to left.
9390 * @category Collection
9391 * @param {Array|Object} collection The collection to iterate over.
9392 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9393 * @returns {Array|Object} Returns `collection`.
9397 * _.forEachRight([1, 2], function(value) {
9398 * console.log(value);
9400 * // => Logs `2` then `1`.
9402 function forEachRight(collection, iteratee) {
9403 var func = isArray(collection) ? arrayEachRight : baseEachRight;
9404 return func(collection, getIteratee(iteratee, 3));
9408 * Creates an object composed of keys generated from the results of running
9409 * each element of `collection` thru `iteratee`. The order of grouped values
9410 * is determined by the order they occur in `collection`. The corresponding
9411 * value of each key is an array of elements responsible for generating the
9412 * key. The iteratee is invoked with one argument: (value).
9417 * @category Collection
9418 * @param {Array|Object} collection The collection to iterate over.
9419 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9420 * @returns {Object} Returns the composed aggregate object.
9423 * _.groupBy([6.1, 4.2, 6.3], Math.floor);
9424 * // => { '4': [4.2], '6': [6.1, 6.3] }
9426 * // The `_.property` iteratee shorthand.
9427 * _.groupBy(['one', 'two', 'three'], 'length');
9428 * // => { '3': ['one', 'two'], '5': ['three'] }
9430 var groupBy = createAggregator(function(result, value, key) {
9431 if (hasOwnProperty.call(result, key)) {
9432 result[key].push(value);
9434 baseAssignValue(result, key, [value]);
9439 * Checks if `value` is in `collection`. If `collection` is a string, it's
9440 * checked for a substring of `value`, otherwise
9441 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
9442 * is used for equality comparisons. If `fromIndex` is negative, it's used as
9443 * the offset from the end of `collection`.
9448 * @category Collection
9449 * @param {Array|Object|string} collection The collection to inspect.
9450 * @param {*} value The value to search for.
9451 * @param {number} [fromIndex=0] The index to search from.
9452 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9453 * @returns {boolean} Returns `true` if `value` is found, else `false`.
9456 * _.includes([1, 2, 3], 1);
9459 * _.includes([1, 2, 3], 1, 2);
9462 * _.includes({ 'a': 1, 'b': 2 }, 1);
9465 * _.includes('abcd', 'bc');
9468 function includes(collection, value, fromIndex, guard) {
9469 collection = isArrayLike(collection) ? collection : values(collection);
9470 fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
9472 var length = collection.length;
9473 if (fromIndex < 0) {
9474 fromIndex = nativeMax(length + fromIndex, 0);
9476 return isString(collection)
9477 ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
9478 : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
9482 * Invokes the method at `path` of each element in `collection`, returning
9483 * an array of the results of each invoked method. Any additional arguments
9484 * are provided to each invoked method. If `path` is a function, it's invoked
9485 * for, and `this` bound to, each element in `collection`.
9490 * @category Collection
9491 * @param {Array|Object} collection The collection to iterate over.
9492 * @param {Array|Function|string} path The path of the method to invoke or
9493 * the function invoked per iteration.
9494 * @param {...*} [args] The arguments to invoke each method with.
9495 * @returns {Array} Returns the array of results.
9498 * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
9499 * // => [[1, 5, 7], [1, 2, 3]]
9501 * _.invokeMap([123, 456], String.prototype.split, '');
9502 * // => [['1', '2', '3'], ['4', '5', '6']]
9504 var invokeMap = baseRest(function(collection, path, args) {
9506 isFunc = typeof path == 'function',
9507 result = isArrayLike(collection) ? Array(collection.length) : [];
9509 baseEach(collection, function(value) {
9510 result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
9516 * Creates an object composed of keys generated from the results of running
9517 * each element of `collection` thru `iteratee`. The corresponding value of
9518 * each key is the last element responsible for generating the key. The
9519 * iteratee is invoked with one argument: (value).
9524 * @category Collection
9525 * @param {Array|Object} collection The collection to iterate over.
9526 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9527 * @returns {Object} Returns the composed aggregate object.
9531 * { 'dir': 'left', 'code': 97 },
9532 * { 'dir': 'right', 'code': 100 }
9535 * _.keyBy(array, function(o) {
9536 * return String.fromCharCode(o.code);
9538 * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
9540 * _.keyBy(array, 'dir');
9541 * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
9543 var keyBy = createAggregator(function(result, value, key) {
9544 baseAssignValue(result, key, value);
9548 * Creates an array of values by running each element in `collection` thru
9549 * `iteratee`. The iteratee is invoked with three arguments:
9550 * (value, index|key, collection).
9552 * Many lodash methods are guarded to work as iteratees for methods like
9553 * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
9555 * The guarded methods are:
9556 * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
9557 * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
9558 * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
9559 * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
9564 * @category Collection
9565 * @param {Array|Object} collection The collection to iterate over.
9566 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9567 * @returns {Array} Returns the new mapped array.
9570 * function square(n) {
9574 * _.map([4, 8], square);
9577 * _.map({ 'a': 4, 'b': 8 }, square);
9578 * // => [16, 64] (iteration order is not guaranteed)
9581 * { 'user': 'barney' },
9582 * { 'user': 'fred' }
9585 * // The `_.property` iteratee shorthand.
9586 * _.map(users, 'user');
9587 * // => ['barney', 'fred']
9589 function map(collection, iteratee) {
9590 var func = isArray(collection) ? arrayMap : baseMap;
9591 return func(collection, getIteratee(iteratee, 3));
9595 * This method is like `_.sortBy` except that it allows specifying the sort
9596 * orders of the iteratees to sort by. If `orders` is unspecified, all values
9597 * are sorted in ascending order. Otherwise, specify an order of "desc" for
9598 * descending or "asc" for ascending sort order of corresponding values.
9603 * @category Collection
9604 * @param {Array|Object} collection The collection to iterate over.
9605 * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
9606 * The iteratees to sort by.
9607 * @param {string[]} [orders] The sort orders of `iteratees`.
9608 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9609 * @returns {Array} Returns the new sorted array.
9613 * { 'user': 'fred', 'age': 48 },
9614 * { 'user': 'barney', 'age': 34 },
9615 * { 'user': 'fred', 'age': 40 },
9616 * { 'user': 'barney', 'age': 36 }
9619 * // Sort by `user` in ascending order and by `age` in descending order.
9620 * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
9621 * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9623 function orderBy(collection, iteratees, orders, guard) {
9624 if (collection == null) {
9627 if (!isArray(iteratees)) {
9628 iteratees = iteratees == null ? [] : [iteratees];
9630 orders = guard ? undefined : orders;
9631 if (!isArray(orders)) {
9632 orders = orders == null ? [] : [orders];
9634 return baseOrderBy(collection, iteratees, orders);
9638 * Creates an array of elements split into two groups, the first of which
9639 * contains elements `predicate` returns truthy for, the second of which
9640 * contains elements `predicate` returns falsey for. The predicate is
9641 * invoked with one argument: (value).
9646 * @category Collection
9647 * @param {Array|Object} collection The collection to iterate over.
9648 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9649 * @returns {Array} Returns the array of grouped elements.
9653 * { 'user': 'barney', 'age': 36, 'active': false },
9654 * { 'user': 'fred', 'age': 40, 'active': true },
9655 * { 'user': 'pebbles', 'age': 1, 'active': false }
9658 * _.partition(users, function(o) { return o.active; });
9659 * // => objects for [['fred'], ['barney', 'pebbles']]
9661 * // The `_.matches` iteratee shorthand.
9662 * _.partition(users, { 'age': 1, 'active': false });
9663 * // => objects for [['pebbles'], ['barney', 'fred']]
9665 * // The `_.matchesProperty` iteratee shorthand.
9666 * _.partition(users, ['active', false]);
9667 * // => objects for [['barney', 'pebbles'], ['fred']]
9669 * // The `_.property` iteratee shorthand.
9670 * _.partition(users, 'active');
9671 * // => objects for [['fred'], ['barney', 'pebbles']]
9673 var partition = createAggregator(function(result, value, key) {
9674 result[key ? 0 : 1].push(value);
9675 }, function() { return [[], []]; });
9678 * Reduces `collection` to a value which is the accumulated result of running
9679 * each element in `collection` thru `iteratee`, where each successive
9680 * invocation is supplied the return value of the previous. If `accumulator`
9681 * is not given, the first element of `collection` is used as the initial
9682 * value. The iteratee is invoked with four arguments:
9683 * (accumulator, value, index|key, collection).
9685 * Many lodash methods are guarded to work as iteratees for methods like
9686 * `_.reduce`, `_.reduceRight`, and `_.transform`.
9688 * The guarded methods are:
9689 * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
9695 * @category Collection
9696 * @param {Array|Object} collection The collection to iterate over.
9697 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9698 * @param {*} [accumulator] The initial value.
9699 * @returns {*} Returns the accumulated value.
9700 * @see _.reduceRight
9703 * _.reduce([1, 2], function(sum, n) {
9708 * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
9709 * (result[value] || (result[value] = [])).push(key);
9712 * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
9714 function reduce(collection, iteratee, accumulator) {
9715 var func = isArray(collection) ? arrayReduce : baseReduce,
9716 initAccum = arguments.length < 3;
9718 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
9722 * This method is like `_.reduce` except that it iterates over elements of
9723 * `collection` from right to left.
9728 * @category Collection
9729 * @param {Array|Object} collection The collection to iterate over.
9730 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9731 * @param {*} [accumulator] The initial value.
9732 * @returns {*} Returns the accumulated value.
9736 * var array = [[0, 1], [2, 3], [4, 5]];
9738 * _.reduceRight(array, function(flattened, other) {
9739 * return flattened.concat(other);
9741 * // => [4, 5, 2, 3, 0, 1]
9743 function reduceRight(collection, iteratee, accumulator) {
9744 var func = isArray(collection) ? arrayReduceRight : baseReduce,
9745 initAccum = arguments.length < 3;
9747 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
9751 * The opposite of `_.filter`; this method returns the elements of `collection`
9752 * that `predicate` does **not** return truthy for.
9757 * @category Collection
9758 * @param {Array|Object} collection The collection to iterate over.
9759 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9760 * @returns {Array} Returns the new filtered array.
9765 * { 'user': 'barney', 'age': 36, 'active': false },
9766 * { 'user': 'fred', 'age': 40, 'active': true }
9769 * _.reject(users, function(o) { return !o.active; });
9770 * // => objects for ['fred']
9772 * // The `_.matches` iteratee shorthand.
9773 * _.reject(users, { 'age': 40, 'active': true });
9774 * // => objects for ['barney']
9776 * // The `_.matchesProperty` iteratee shorthand.
9777 * _.reject(users, ['active', false]);
9778 * // => objects for ['fred']
9780 * // The `_.property` iteratee shorthand.
9781 * _.reject(users, 'active');
9782 * // => objects for ['barney']
9784 function reject(collection, predicate) {
9785 var func = isArray(collection) ? arrayFilter : baseFilter;
9786 return func(collection, negate(getIteratee(predicate, 3)));
9790 * Gets a random element from `collection`.
9795 * @category Collection
9796 * @param {Array|Object} collection The collection to sample.
9797 * @returns {*} Returns the random element.
9800 * _.sample([1, 2, 3, 4]);
9803 function sample(collection) {
9804 var func = isArray(collection) ? arraySample : baseSample;
9805 return func(collection);
9809 * Gets `n` random elements at unique keys from `collection` up to the
9810 * size of `collection`.
9815 * @category Collection
9816 * @param {Array|Object} collection The collection to sample.
9817 * @param {number} [n=1] The number of elements to sample.
9818 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9819 * @returns {Array} Returns the random elements.
9822 * _.sampleSize([1, 2, 3], 2);
9825 * _.sampleSize([1, 2, 3], 4);
9828 function sampleSize(collection, n, guard) {
9829 if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
9834 var func = isArray(collection) ? arraySampleSize : baseSampleSize;
9835 return func(collection, n);
9839 * Creates an array of shuffled values, using a version of the
9840 * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
9845 * @category Collection
9846 * @param {Array|Object} collection The collection to shuffle.
9847 * @returns {Array} Returns the new shuffled array.
9850 * _.shuffle([1, 2, 3, 4]);
9851 * // => [4, 1, 3, 2]
9853 function shuffle(collection) {
9854 var func = isArray(collection) ? arrayShuffle : baseShuffle;
9855 return func(collection);
9859 * Gets the size of `collection` by returning its length for array-like
9860 * values or the number of own enumerable string keyed properties for objects.
9865 * @category Collection
9866 * @param {Array|Object|string} collection The collection to inspect.
9867 * @returns {number} Returns the collection size.
9870 * _.size([1, 2, 3]);
9873 * _.size({ 'a': 1, 'b': 2 });
9876 * _.size('pebbles');
9879 function size(collection) {
9880 if (collection == null) {
9883 if (isArrayLike(collection)) {
9884 return isString(collection) ? stringSize(collection) : collection.length;
9886 var tag = getTag(collection);
9887 if (tag == mapTag || tag == setTag) {
9888 return collection.size;
9890 return baseKeys(collection).length;
9894 * Checks if `predicate` returns truthy for **any** element of `collection`.
9895 * Iteration is stopped once `predicate` returns truthy. The predicate is
9896 * invoked with three arguments: (value, index|key, collection).
9901 * @category Collection
9902 * @param {Array|Object} collection The collection to iterate over.
9903 * @param {Function} [predicate=_.identity] The function invoked per iteration.
9904 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9905 * @returns {boolean} Returns `true` if any element passes the predicate check,
9909 * _.some([null, 0, 'yes', false], Boolean);
9913 * { 'user': 'barney', 'active': true },
9914 * { 'user': 'fred', 'active': false }
9917 * // The `_.matches` iteratee shorthand.
9918 * _.some(users, { 'user': 'barney', 'active': false });
9921 * // The `_.matchesProperty` iteratee shorthand.
9922 * _.some(users, ['active', false]);
9925 * // The `_.property` iteratee shorthand.
9926 * _.some(users, 'active');
9929 function some(collection, predicate, guard) {
9930 var func = isArray(collection) ? arraySome : baseSome;
9931 if (guard && isIterateeCall(collection, predicate, guard)) {
9932 predicate = undefined;
9934 return func(collection, getIteratee(predicate, 3));
9938 * Creates an array of elements, sorted in ascending order by the results of
9939 * running each element in a collection thru each iteratee. This method
9940 * performs a stable sort, that is, it preserves the original sort order of
9941 * equal elements. The iteratees are invoked with one argument: (value).
9946 * @category Collection
9947 * @param {Array|Object} collection The collection to iterate over.
9948 * @param {...(Function|Function[])} [iteratees=[_.identity]]
9949 * The iteratees to sort by.
9950 * @returns {Array} Returns the new sorted array.
9954 * { 'user': 'fred', 'age': 48 },
9955 * { 'user': 'barney', 'age': 36 },
9956 * { 'user': 'fred', 'age': 40 },
9957 * { 'user': 'barney', 'age': 34 }
9960 * _.sortBy(users, [function(o) { return o.user; }]);
9961 * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9963 * _.sortBy(users, ['user', 'age']);
9964 * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
9966 var sortBy = baseRest(function(collection, iteratees) {
9967 if (collection == null) {
9970 var length = iteratees.length;
9971 if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
9973 } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
9974 iteratees = [iteratees[0]];
9976 return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
9979 /*------------------------------------------------------------------------*/
9982 * Gets the timestamp of the number of milliseconds that have elapsed since
9983 * the Unix epoch (1 January 1970 00:00:00 UTC).
9989 * @returns {number} Returns the timestamp.
9992 * _.defer(function(stamp) {
9993 * console.log(_.now() - stamp);
9995 * // => Logs the number of milliseconds it took for the deferred invocation.
9997 var now = ctxNow || function() {
9998 return root.Date.now();
10001 /*------------------------------------------------------------------------*/
10004 * The opposite of `_.before`; this method creates a function that invokes
10005 * `func` once it's called `n` or more times.
10010 * @category Function
10011 * @param {number} n The number of calls before `func` is invoked.
10012 * @param {Function} func The function to restrict.
10013 * @returns {Function} Returns the new restricted function.
10016 * var saves = ['profile', 'settings'];
10018 * var done = _.after(saves.length, function() {
10019 * console.log('done saving!');
10022 * _.forEach(saves, function(type) {
10023 * asyncSave({ 'type': type, 'complete': done });
10025 * // => Logs 'done saving!' after the two async saves have completed.
10027 function after(n, func) {
10028 if (typeof func != 'function') {
10029 throw new TypeError(FUNC_ERROR_TEXT);
10032 return function() {
10034 return func.apply(this, arguments);
10040 * Creates a function that invokes `func`, with up to `n` arguments,
10041 * ignoring any additional arguments.
10046 * @category Function
10047 * @param {Function} func The function to cap arguments for.
10048 * @param {number} [n=func.length] The arity cap.
10049 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10050 * @returns {Function} Returns the new capped function.
10053 * _.map(['6', '8', '10'], _.ary(parseInt, 1));
10056 function ary(func, n, guard) {
10057 n = guard ? undefined : n;
10058 n = (func && n == null) ? func.length : n;
10059 return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
10063 * Creates a function that invokes `func`, with the `this` binding and arguments
10064 * of the created function, while it's called less than `n` times. Subsequent
10065 * calls to the created function return the result of the last `func` invocation.
10070 * @category Function
10071 * @param {number} n The number of calls at which `func` is no longer invoked.
10072 * @param {Function} func The function to restrict.
10073 * @returns {Function} Returns the new restricted function.
10076 * jQuery(element).on('click', _.before(5, addContactToList));
10077 * // => Allows adding up to 4 contacts to the list.
10079 function before(n, func) {
10081 if (typeof func != 'function') {
10082 throw new TypeError(FUNC_ERROR_TEXT);
10085 return function() {
10087 result = func.apply(this, arguments);
10097 * Creates a function that invokes `func` with the `this` binding of `thisArg`
10098 * and `partials` prepended to the arguments it receives.
10100 * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
10101 * may be used as a placeholder for partially applied arguments.
10103 * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
10104 * property of bound functions.
10109 * @category Function
10110 * @param {Function} func The function to bind.
10111 * @param {*} thisArg The `this` binding of `func`.
10112 * @param {...*} [partials] The arguments to be partially applied.
10113 * @returns {Function} Returns the new bound function.
10116 * function greet(greeting, punctuation) {
10117 * return greeting + ' ' + this.user + punctuation;
10120 * var object = { 'user': 'fred' };
10122 * var bound = _.bind(greet, object, 'hi');
10126 * // Bound with placeholders.
10127 * var bound = _.bind(greet, object, _, '!');
10131 var bind = baseRest(function(func, thisArg, partials) {
10132 var bitmask = WRAP_BIND_FLAG;
10133 if (partials.length) {
10134 var holders = replaceHolders(partials, getHolder(bind));
10135 bitmask |= WRAP_PARTIAL_FLAG;
10137 return createWrap(func, bitmask, thisArg, partials, holders);
10141 * Creates a function that invokes the method at `object[key]` with `partials`
10142 * prepended to the arguments it receives.
10144 * This method differs from `_.bind` by allowing bound functions to reference
10145 * methods that may be redefined or don't yet exist. See
10146 * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
10147 * for more details.
10149 * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
10150 * builds, may be used as a placeholder for partially applied arguments.
10155 * @category Function
10156 * @param {Object} object The object to invoke the method on.
10157 * @param {string} key The key of the method.
10158 * @param {...*} [partials] The arguments to be partially applied.
10159 * @returns {Function} Returns the new bound function.
10164 * 'greet': function(greeting, punctuation) {
10165 * return greeting + ' ' + this.user + punctuation;
10169 * var bound = _.bindKey(object, 'greet', 'hi');
10173 * object.greet = function(greeting, punctuation) {
10174 * return greeting + 'ya ' + this.user + punctuation;
10178 * // => 'hiya fred!'
10180 * // Bound with placeholders.
10181 * var bound = _.bindKey(object, 'greet', _, '!');
10183 * // => 'hiya fred!'
10185 var bindKey = baseRest(function(object, key, partials) {
10186 var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
10187 if (partials.length) {
10188 var holders = replaceHolders(partials, getHolder(bindKey));
10189 bitmask |= WRAP_PARTIAL_FLAG;
10191 return createWrap(key, bitmask, object, partials, holders);
10195 * Creates a function that accepts arguments of `func` and either invokes
10196 * `func` returning its result, if at least `arity` number of arguments have
10197 * been provided, or returns a function that accepts the remaining `func`
10198 * arguments, and so on. The arity of `func` may be specified if `func.length`
10199 * is not sufficient.
10201 * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
10202 * may be used as a placeholder for provided arguments.
10204 * **Note:** This method doesn't set the "length" property of curried functions.
10209 * @category Function
10210 * @param {Function} func The function to curry.
10211 * @param {number} [arity=func.length] The arity of `func`.
10212 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10213 * @returns {Function} Returns the new curried function.
10216 * var abc = function(a, b, c) {
10217 * return [a, b, c];
10220 * var curried = _.curry(abc);
10222 * curried(1)(2)(3);
10225 * curried(1, 2)(3);
10228 * curried(1, 2, 3);
10231 * // Curried with placeholders.
10232 * curried(1)(_, 3)(2);
10235 function curry(func, arity, guard) {
10236 arity = guard ? undefined : arity;
10237 var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10238 result.placeholder = curry.placeholder;
10243 * This method is like `_.curry` except that arguments are applied to `func`
10244 * in the manner of `_.partialRight` instead of `_.partial`.
10246 * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
10247 * builds, may be used as a placeholder for provided arguments.
10249 * **Note:** This method doesn't set the "length" property of curried functions.
10254 * @category Function
10255 * @param {Function} func The function to curry.
10256 * @param {number} [arity=func.length] The arity of `func`.
10257 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10258 * @returns {Function} Returns the new curried function.
10261 * var abc = function(a, b, c) {
10262 * return [a, b, c];
10265 * var curried = _.curryRight(abc);
10267 * curried(3)(2)(1);
10270 * curried(2, 3)(1);
10273 * curried(1, 2, 3);
10276 * // Curried with placeholders.
10277 * curried(3)(1, _)(2);
10280 function curryRight(func, arity, guard) {
10281 arity = guard ? undefined : arity;
10282 var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10283 result.placeholder = curryRight.placeholder;
10288 * Creates a debounced function that delays invoking `func` until after `wait`
10289 * milliseconds have elapsed since the last time the debounced function was
10290 * invoked. The debounced function comes with a `cancel` method to cancel
10291 * delayed `func` invocations and a `flush` method to immediately invoke them.
10292 * Provide `options` to indicate whether `func` should be invoked on the
10293 * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
10294 * with the last arguments provided to the debounced function. Subsequent
10295 * calls to the debounced function return the result of the last `func`
10298 * **Note:** If `leading` and `trailing` options are `true`, `func` is
10299 * invoked on the trailing edge of the timeout only if the debounced function
10300 * is invoked more than once during the `wait` timeout.
10302 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10303 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10305 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10306 * for details over the differences between `_.debounce` and `_.throttle`.
10311 * @category Function
10312 * @param {Function} func The function to debounce.
10313 * @param {number} [wait=0] The number of milliseconds to delay.
10314 * @param {Object} [options={}] The options object.
10315 * @param {boolean} [options.leading=false]
10316 * Specify invoking on the leading edge of the timeout.
10317 * @param {number} [options.maxWait]
10318 * The maximum time `func` is allowed to be delayed before it's invoked.
10319 * @param {boolean} [options.trailing=true]
10320 * Specify invoking on the trailing edge of the timeout.
10321 * @returns {Function} Returns the new debounced function.
10324 * // Avoid costly calculations while the window size is in flux.
10325 * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
10327 * // Invoke `sendMail` when clicked, debouncing subsequent calls.
10328 * jQuery(element).on('click', _.debounce(sendMail, 300, {
10330 * 'trailing': false
10333 * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
10334 * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
10335 * var source = new EventSource('/stream');
10336 * jQuery(source).on('message', debounced);
10338 * // Cancel the trailing debounced invocation.
10339 * jQuery(window).on('popstate', debounced.cancel);
10341 function debounce(func, wait, options) {
10348 lastInvokeTime = 0,
10353 if (typeof func != 'function') {
10354 throw new TypeError(FUNC_ERROR_TEXT);
10356 wait = toNumber(wait) || 0;
10357 if (isObject(options)) {
10358 leading = !!options.leading;
10359 maxing = 'maxWait' in options;
10360 maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
10361 trailing = 'trailing' in options ? !!options.trailing : trailing;
10364 function invokeFunc(time) {
10365 var args = lastArgs,
10366 thisArg = lastThis;
10368 lastArgs = lastThis = undefined;
10369 lastInvokeTime = time;
10370 result = func.apply(thisArg, args);
10374 function leadingEdge(time) {
10375 // Reset any `maxWait` timer.
10376 lastInvokeTime = time;
10377 // Start the timer for the trailing edge.
10378 timerId = setTimeout(timerExpired, wait);
10379 // Invoke the leading edge.
10380 return leading ? invokeFunc(time) : result;
10383 function remainingWait(time) {
10384 var timeSinceLastCall = time - lastCallTime,
10385 timeSinceLastInvoke = time - lastInvokeTime,
10386 result = wait - timeSinceLastCall;
10388 return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
10391 function shouldInvoke(time) {
10392 var timeSinceLastCall = time - lastCallTime,
10393 timeSinceLastInvoke = time - lastInvokeTime;
10395 // Either this is the first call, activity has stopped and we're at the
10396 // trailing edge, the system time has gone backwards and we're treating
10397 // it as the trailing edge, or we've hit the `maxWait` limit.
10398 return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
10399 (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
10402 function timerExpired() {
10404 if (shouldInvoke(time)) {
10405 return trailingEdge(time);
10407 // Restart the timer.
10408 timerId = setTimeout(timerExpired, remainingWait(time));
10411 function trailingEdge(time) {
10412 timerId = undefined;
10414 // Only invoke if we have `lastArgs` which means `func` has been
10415 // debounced at least once.
10416 if (trailing && lastArgs) {
10417 return invokeFunc(time);
10419 lastArgs = lastThis = undefined;
10423 function cancel() {
10424 if (timerId !== undefined) {
10425 clearTimeout(timerId);
10427 lastInvokeTime = 0;
10428 lastArgs = lastCallTime = lastThis = timerId = undefined;
10432 return timerId === undefined ? result : trailingEdge(now());
10435 function debounced() {
10437 isInvoking = shouldInvoke(time);
10439 lastArgs = arguments;
10441 lastCallTime = time;
10444 if (timerId === undefined) {
10445 return leadingEdge(lastCallTime);
10448 // Handle invocations in a tight loop.
10449 timerId = setTimeout(timerExpired, wait);
10450 return invokeFunc(lastCallTime);
10453 if (timerId === undefined) {
10454 timerId = setTimeout(timerExpired, wait);
10458 debounced.cancel = cancel;
10459 debounced.flush = flush;
10464 * Defers invoking the `func` until the current call stack has cleared. Any
10465 * additional arguments are provided to `func` when it's invoked.
10470 * @category Function
10471 * @param {Function} func The function to defer.
10472 * @param {...*} [args] The arguments to invoke `func` with.
10473 * @returns {number} Returns the timer id.
10476 * _.defer(function(text) {
10477 * console.log(text);
10479 * // => Logs 'deferred' after one millisecond.
10481 var defer = baseRest(function(func, args) {
10482 return baseDelay(func, 1, args);
10486 * Invokes `func` after `wait` milliseconds. Any additional arguments are
10487 * provided to `func` when it's invoked.
10492 * @category Function
10493 * @param {Function} func The function to delay.
10494 * @param {number} wait The number of milliseconds to delay invocation.
10495 * @param {...*} [args] The arguments to invoke `func` with.
10496 * @returns {number} Returns the timer id.
10499 * _.delay(function(text) {
10500 * console.log(text);
10501 * }, 1000, 'later');
10502 * // => Logs 'later' after one second.
10504 var delay = baseRest(function(func, wait, args) {
10505 return baseDelay(func, toNumber(wait) || 0, args);
10509 * Creates a function that invokes `func` with arguments reversed.
10514 * @category Function
10515 * @param {Function} func The function to flip arguments for.
10516 * @returns {Function} Returns the new flipped function.
10519 * var flipped = _.flip(function() {
10520 * return _.toArray(arguments);
10523 * flipped('a', 'b', 'c', 'd');
10524 * // => ['d', 'c', 'b', 'a']
10526 function flip(func) {
10527 return createWrap(func, WRAP_FLIP_FLAG);
10531 * Creates a function that memoizes the result of `func`. If `resolver` is
10532 * provided, it determines the cache key for storing the result based on the
10533 * arguments provided to the memoized function. By default, the first argument
10534 * provided to the memoized function is used as the map cache key. The `func`
10535 * is invoked with the `this` binding of the memoized function.
10537 * **Note:** The cache is exposed as the `cache` property on the memoized
10538 * function. Its creation may be customized by replacing the `_.memoize.Cache`
10539 * constructor with one whose instances implement the
10540 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
10541 * method interface of `clear`, `delete`, `get`, `has`, and `set`.
10546 * @category Function
10547 * @param {Function} func The function to have its output memoized.
10548 * @param {Function} [resolver] The function to resolve the cache key.
10549 * @returns {Function} Returns the new memoized function.
10552 * var object = { 'a': 1, 'b': 2 };
10553 * var other = { 'c': 3, 'd': 4 };
10555 * var values = _.memoize(_.values);
10566 * // Modify the result cache.
10567 * values.cache.set(object, ['a', 'b']);
10571 * // Replace `_.memoize.Cache`.
10572 * _.memoize.Cache = WeakMap;
10574 function memoize(func, resolver) {
10575 if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
10576 throw new TypeError(FUNC_ERROR_TEXT);
10578 var memoized = function() {
10579 var args = arguments,
10580 key = resolver ? resolver.apply(this, args) : args[0],
10581 cache = memoized.cache;
10583 if (cache.has(key)) {
10584 return cache.get(key);
10586 var result = func.apply(this, args);
10587 memoized.cache = cache.set(key, result) || cache;
10590 memoized.cache = new (memoize.Cache || MapCache);
10594 // Expose `MapCache`.
10595 memoize.Cache = MapCache;
10598 * Creates a function that negates the result of the predicate `func`. The
10599 * `func` predicate is invoked with the `this` binding and arguments of the
10600 * created function.
10605 * @category Function
10606 * @param {Function} predicate The predicate to negate.
10607 * @returns {Function} Returns the new negated function.
10610 * function isEven(n) {
10611 * return n % 2 == 0;
10614 * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
10617 function negate(predicate) {
10618 if (typeof predicate != 'function') {
10619 throw new TypeError(FUNC_ERROR_TEXT);
10621 return function() {
10622 var args = arguments;
10623 switch (args.length) {
10624 case 0: return !predicate.call(this);
10625 case 1: return !predicate.call(this, args[0]);
10626 case 2: return !predicate.call(this, args[0], args[1]);
10627 case 3: return !predicate.call(this, args[0], args[1], args[2]);
10629 return !predicate.apply(this, args);
10634 * Creates a function that is restricted to invoking `func` once. Repeat calls
10635 * to the function return the value of the first invocation. The `func` is
10636 * invoked with the `this` binding and arguments of the created function.
10641 * @category Function
10642 * @param {Function} func The function to restrict.
10643 * @returns {Function} Returns the new restricted function.
10646 * var initialize = _.once(createApplication);
10649 * // => `createApplication` is invoked once
10651 function once(func) {
10652 return before(2, func);
10656 * Creates a function that invokes `func` with its arguments transformed.
10661 * @category Function
10662 * @param {Function} func The function to wrap.
10663 * @param {...(Function|Function[])} [transforms=[_.identity]]
10664 * The argument transforms.
10665 * @returns {Function} Returns the new function.
10668 * function doubled(n) {
10672 * function square(n) {
10676 * var func = _.overArgs(function(x, y) {
10678 * }, [square, doubled]);
10686 var overArgs = castRest(function(func, transforms) {
10687 transforms = (transforms.length == 1 && isArray(transforms[0]))
10688 ? arrayMap(transforms[0], baseUnary(getIteratee()))
10689 : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
10691 var funcsLength = transforms.length;
10692 return baseRest(function(args) {
10694 length = nativeMin(args.length, funcsLength);
10696 while (++index < length) {
10697 args[index] = transforms[index].call(this, args[index]);
10699 return apply(func, this, args);
10704 * Creates a function that invokes `func` with `partials` prepended to the
10705 * arguments it receives. This method is like `_.bind` except it does **not**
10706 * alter the `this` binding.
10708 * The `_.partial.placeholder` value, which defaults to `_` in monolithic
10709 * builds, may be used as a placeholder for partially applied arguments.
10711 * **Note:** This method doesn't set the "length" property of partially
10712 * applied functions.
10717 * @category Function
10718 * @param {Function} func The function to partially apply arguments to.
10719 * @param {...*} [partials] The arguments to be partially applied.
10720 * @returns {Function} Returns the new partially applied function.
10723 * function greet(greeting, name) {
10724 * return greeting + ' ' + name;
10727 * var sayHelloTo = _.partial(greet, 'hello');
10728 * sayHelloTo('fred');
10729 * // => 'hello fred'
10731 * // Partially applied with placeholders.
10732 * var greetFred = _.partial(greet, _, 'fred');
10736 var partial = baseRest(function(func, partials) {
10737 var holders = replaceHolders(partials, getHolder(partial));
10738 return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
10742 * This method is like `_.partial` except that partially applied arguments
10743 * are appended to the arguments it receives.
10745 * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
10746 * builds, may be used as a placeholder for partially applied arguments.
10748 * **Note:** This method doesn't set the "length" property of partially
10749 * applied functions.
10754 * @category Function
10755 * @param {Function} func The function to partially apply arguments to.
10756 * @param {...*} [partials] The arguments to be partially applied.
10757 * @returns {Function} Returns the new partially applied function.
10760 * function greet(greeting, name) {
10761 * return greeting + ' ' + name;
10764 * var greetFred = _.partialRight(greet, 'fred');
10768 * // Partially applied with placeholders.
10769 * var sayHelloTo = _.partialRight(greet, 'hello', _);
10770 * sayHelloTo('fred');
10771 * // => 'hello fred'
10773 var partialRight = baseRest(function(func, partials) {
10774 var holders = replaceHolders(partials, getHolder(partialRight));
10775 return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
10779 * Creates a function that invokes `func` with arguments arranged according
10780 * to the specified `indexes` where the argument value at the first index is
10781 * provided as the first argument, the argument value at the second index is
10782 * provided as the second argument, and so on.
10787 * @category Function
10788 * @param {Function} func The function to rearrange arguments for.
10789 * @param {...(number|number[])} indexes The arranged argument indexes.
10790 * @returns {Function} Returns the new function.
10793 * var rearged = _.rearg(function(a, b, c) {
10794 * return [a, b, c];
10797 * rearged('b', 'c', 'a')
10798 * // => ['a', 'b', 'c']
10800 var rearg = flatRest(function(func, indexes) {
10801 return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
10805 * Creates a function that invokes `func` with the `this` binding of the
10806 * created function and arguments from `start` and beyond provided as
10809 * **Note:** This method is based on the
10810 * [rest parameter](https://mdn.io/rest_parameters).
10815 * @category Function
10816 * @param {Function} func The function to apply a rest parameter to.
10817 * @param {number} [start=func.length-1] The start position of the rest parameter.
10818 * @returns {Function} Returns the new function.
10821 * var say = _.rest(function(what, names) {
10822 * return what + ' ' + _.initial(names).join(', ') +
10823 * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
10826 * say('hello', 'fred', 'barney', 'pebbles');
10827 * // => 'hello fred, barney, & pebbles'
10829 function rest(func, start) {
10830 if (typeof func != 'function') {
10831 throw new TypeError(FUNC_ERROR_TEXT);
10833 start = start === undefined ? start : toInteger(start);
10834 return baseRest(func, start);
10838 * Creates a function that invokes `func` with the `this` binding of the
10839 * create function and an array of arguments much like
10840 * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
10842 * **Note:** This method is based on the
10843 * [spread operator](https://mdn.io/spread_operator).
10848 * @category Function
10849 * @param {Function} func The function to spread arguments over.
10850 * @param {number} [start=0] The start position of the spread.
10851 * @returns {Function} Returns the new function.
10854 * var say = _.spread(function(who, what) {
10855 * return who + ' says ' + what;
10858 * say(['fred', 'hello']);
10859 * // => 'fred says hello'
10861 * var numbers = Promise.all([
10862 * Promise.resolve(40),
10863 * Promise.resolve(36)
10866 * numbers.then(_.spread(function(x, y) {
10869 * // => a Promise of 76
10871 function spread(func, start) {
10872 if (typeof func != 'function') {
10873 throw new TypeError(FUNC_ERROR_TEXT);
10875 start = start == null ? 0 : nativeMax(toInteger(start), 0);
10876 return baseRest(function(args) {
10877 var array = args[start],
10878 otherArgs = castSlice(args, 0, start);
10881 arrayPush(otherArgs, array);
10883 return apply(func, this, otherArgs);
10888 * Creates a throttled function that only invokes `func` at most once per
10889 * every `wait` milliseconds. The throttled function comes with a `cancel`
10890 * method to cancel delayed `func` invocations and a `flush` method to
10891 * immediately invoke them. Provide `options` to indicate whether `func`
10892 * should be invoked on the leading and/or trailing edge of the `wait`
10893 * timeout. The `func` is invoked with the last arguments provided to the
10894 * throttled function. Subsequent calls to the throttled function return the
10895 * result of the last `func` invocation.
10897 * **Note:** If `leading` and `trailing` options are `true`, `func` is
10898 * invoked on the trailing edge of the timeout only if the throttled function
10899 * is invoked more than once during the `wait` timeout.
10901 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10902 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10904 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10905 * for details over the differences between `_.throttle` and `_.debounce`.
10910 * @category Function
10911 * @param {Function} func The function to throttle.
10912 * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
10913 * @param {Object} [options={}] The options object.
10914 * @param {boolean} [options.leading=true]
10915 * Specify invoking on the leading edge of the timeout.
10916 * @param {boolean} [options.trailing=true]
10917 * Specify invoking on the trailing edge of the timeout.
10918 * @returns {Function} Returns the new throttled function.
10921 * // Avoid excessively updating the position while scrolling.
10922 * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
10924 * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
10925 * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
10926 * jQuery(element).on('click', throttled);
10928 * // Cancel the trailing throttled invocation.
10929 * jQuery(window).on('popstate', throttled.cancel);
10931 function throttle(func, wait, options) {
10932 var leading = true,
10935 if (typeof func != 'function') {
10936 throw new TypeError(FUNC_ERROR_TEXT);
10938 if (isObject(options)) {
10939 leading = 'leading' in options ? !!options.leading : leading;
10940 trailing = 'trailing' in options ? !!options.trailing : trailing;
10942 return debounce(func, wait, {
10943 'leading': leading,
10945 'trailing': trailing
10950 * Creates a function that accepts up to one argument, ignoring any
10951 * additional arguments.
10956 * @category Function
10957 * @param {Function} func The function to cap arguments for.
10958 * @returns {Function} Returns the new capped function.
10961 * _.map(['6', '8', '10'], _.unary(parseInt));
10964 function unary(func) {
10965 return ary(func, 1);
10969 * Creates a function that provides `value` to `wrapper` as its first
10970 * argument. Any additional arguments provided to the function are appended
10971 * to those provided to the `wrapper`. The wrapper is invoked with the `this`
10972 * binding of the created function.
10977 * @category Function
10978 * @param {*} value The value to wrap.
10979 * @param {Function} [wrapper=identity] The wrapper function.
10980 * @returns {Function} Returns the new function.
10983 * var p = _.wrap(_.escape, function(func, text) {
10984 * return '<p>' + func(text) + '</p>';
10987 * p('fred, barney, & pebbles');
10988 * // => '<p>fred, barney, & pebbles</p>'
10990 function wrap(value, wrapper) {
10991 return partial(castFunction(wrapper), value);
10994 /*------------------------------------------------------------------------*/
10997 * Casts `value` as an array if it's not one.
11003 * @param {*} value The value to inspect.
11004 * @returns {Array} Returns the cast array.
11010 * _.castArray({ 'a': 1 });
11011 * // => [{ 'a': 1 }]
11013 * _.castArray('abc');
11016 * _.castArray(null);
11019 * _.castArray(undefined);
11020 * // => [undefined]
11025 * var array = [1, 2, 3];
11026 * console.log(_.castArray(array) === array);
11029 function castArray() {
11030 if (!arguments.length) {
11033 var value = arguments[0];
11034 return isArray(value) ? value : [value];
11038 * Creates a shallow clone of `value`.
11040 * **Note:** This method is loosely based on the
11041 * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
11042 * and supports cloning arrays, array buffers, booleans, date objects, maps,
11043 * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
11044 * arrays. The own enumerable properties of `arguments` objects are cloned
11045 * as plain objects. An empty object is returned for uncloneable values such
11046 * as error objects, functions, DOM nodes, and WeakMaps.
11052 * @param {*} value The value to clone.
11053 * @returns {*} Returns the cloned value.
11057 * var objects = [{ 'a': 1 }, { 'b': 2 }];
11059 * var shallow = _.clone(objects);
11060 * console.log(shallow[0] === objects[0]);
11063 function clone(value) {
11064 return baseClone(value, CLONE_SYMBOLS_FLAG);
11068 * This method is like `_.clone` except that it accepts `customizer` which
11069 * is invoked to produce the cloned value. If `customizer` returns `undefined`,
11070 * cloning is handled by the method instead. The `customizer` is invoked with
11071 * up to four arguments; (value [, index|key, object, stack]).
11077 * @param {*} value The value to clone.
11078 * @param {Function} [customizer] The function to customize cloning.
11079 * @returns {*} Returns the cloned value.
11080 * @see _.cloneDeepWith
11083 * function customizer(value) {
11084 * if (_.isElement(value)) {
11085 * return value.cloneNode(false);
11089 * var el = _.cloneWith(document.body, customizer);
11091 * console.log(el === document.body);
11093 * console.log(el.nodeName);
11095 * console.log(el.childNodes.length);
11098 function cloneWith(value, customizer) {
11099 customizer = typeof customizer == 'function' ? customizer : undefined;
11100 return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
11104 * This method is like `_.clone` except that it recursively clones `value`.
11110 * @param {*} value The value to recursively clone.
11111 * @returns {*} Returns the deep cloned value.
11115 * var objects = [{ 'a': 1 }, { 'b': 2 }];
11117 * var deep = _.cloneDeep(objects);
11118 * console.log(deep[0] === objects[0]);
11121 function cloneDeep(value) {
11122 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
11126 * This method is like `_.cloneWith` except that it recursively clones `value`.
11132 * @param {*} value The value to recursively clone.
11133 * @param {Function} [customizer] The function to customize cloning.
11134 * @returns {*} Returns the deep cloned value.
11138 * function customizer(value) {
11139 * if (_.isElement(value)) {
11140 * return value.cloneNode(true);
11144 * var el = _.cloneDeepWith(document.body, customizer);
11146 * console.log(el === document.body);
11148 * console.log(el.nodeName);
11150 * console.log(el.childNodes.length);
11153 function cloneDeepWith(value, customizer) {
11154 customizer = typeof customizer == 'function' ? customizer : undefined;
11155 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
11159 * Checks if `object` conforms to `source` by invoking the predicate
11160 * properties of `source` with the corresponding property values of `object`.
11162 * **Note:** This method is equivalent to `_.conforms` when `source` is
11163 * partially applied.
11169 * @param {Object} object The object to inspect.
11170 * @param {Object} source The object of property predicates to conform to.
11171 * @returns {boolean} Returns `true` if `object` conforms, else `false`.
11174 * var object = { 'a': 1, 'b': 2 };
11176 * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
11179 * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
11182 function conformsTo(object, source) {
11183 return source == null || baseConformsTo(object, source, keys(source));
11188 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
11189 * comparison between two values to determine if they are equivalent.
11195 * @param {*} value The value to compare.
11196 * @param {*} other The other value to compare.
11197 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11200 * var object = { 'a': 1 };
11201 * var other = { 'a': 1 };
11203 * _.eq(object, object);
11206 * _.eq(object, other);
11212 * _.eq('a', Object('a'));
11218 function eq(value, other) {
11219 return value === other || (value !== value && other !== other);
11223 * Checks if `value` is greater than `other`.
11229 * @param {*} value The value to compare.
11230 * @param {*} other The other value to compare.
11231 * @returns {boolean} Returns `true` if `value` is greater than `other`,
11245 var gt = createRelationalOperation(baseGt);
11248 * Checks if `value` is greater than or equal to `other`.
11254 * @param {*} value The value to compare.
11255 * @param {*} other The other value to compare.
11256 * @returns {boolean} Returns `true` if `value` is greater than or equal to
11257 * `other`, else `false`.
11270 var gte = createRelationalOperation(function(value, other) {
11271 return value >= other;
11275 * Checks if `value` is likely an `arguments` object.
11281 * @param {*} value The value to check.
11282 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
11286 * _.isArguments(function() { return arguments; }());
11289 * _.isArguments([1, 2, 3]);
11292 var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
11293 return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
11294 !propertyIsEnumerable.call(value, 'callee');
11298 * Checks if `value` is classified as an `Array` object.
11304 * @param {*} value The value to check.
11305 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
11308 * _.isArray([1, 2, 3]);
11311 * _.isArray(document.body.children);
11314 * _.isArray('abc');
11317 * _.isArray(_.noop);
11320 var isArray = Array.isArray;
11323 * Checks if `value` is classified as an `ArrayBuffer` object.
11329 * @param {*} value The value to check.
11330 * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
11333 * _.isArrayBuffer(new ArrayBuffer(2));
11336 * _.isArrayBuffer(new Array(2));
11339 var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
11342 * Checks if `value` is array-like. A value is considered array-like if it's
11343 * not a function and has a `value.length` that's an integer greater than or
11344 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
11350 * @param {*} value The value to check.
11351 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
11354 * _.isArrayLike([1, 2, 3]);
11357 * _.isArrayLike(document.body.children);
11360 * _.isArrayLike('abc');
11363 * _.isArrayLike(_.noop);
11366 function isArrayLike(value) {
11367 return value != null && isLength(value.length) && !isFunction(value);
11371 * This method is like `_.isArrayLike` except that it also checks if `value`
11378 * @param {*} value The value to check.
11379 * @returns {boolean} Returns `true` if `value` is an array-like object,
11383 * _.isArrayLikeObject([1, 2, 3]);
11386 * _.isArrayLikeObject(document.body.children);
11389 * _.isArrayLikeObject('abc');
11392 * _.isArrayLikeObject(_.noop);
11395 function isArrayLikeObject(value) {
11396 return isObjectLike(value) && isArrayLike(value);
11400 * Checks if `value` is classified as a boolean primitive or object.
11406 * @param {*} value The value to check.
11407 * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
11410 * _.isBoolean(false);
11413 * _.isBoolean(null);
11416 function isBoolean(value) {
11417 return value === true || value === false ||
11418 (isObjectLike(value) && baseGetTag(value) == boolTag);
11422 * Checks if `value` is a buffer.
11428 * @param {*} value The value to check.
11429 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
11432 * _.isBuffer(new Buffer(2));
11435 * _.isBuffer(new Uint8Array(2));
11438 var isBuffer = nativeIsBuffer || stubFalse;
11441 * Checks if `value` is classified as a `Date` object.
11447 * @param {*} value The value to check.
11448 * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
11451 * _.isDate(new Date);
11454 * _.isDate('Mon April 23 2012');
11457 var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
11460 * Checks if `value` is likely a DOM element.
11466 * @param {*} value The value to check.
11467 * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
11470 * _.isElement(document.body);
11473 * _.isElement('<body>');
11476 function isElement(value) {
11477 return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
11481 * Checks if `value` is an empty object, collection, map, or set.
11483 * Objects are considered empty if they have no own enumerable string keyed
11486 * Array-like values such as `arguments` objects, arrays, buffers, strings, or
11487 * jQuery-like collections are considered empty if they have a `length` of `0`.
11488 * Similarly, maps and sets are considered empty if they have a `size` of `0`.
11494 * @param {*} value The value to check.
11495 * @returns {boolean} Returns `true` if `value` is empty, else `false`.
11507 * _.isEmpty([1, 2, 3]);
11510 * _.isEmpty({ 'a': 1 });
11513 function isEmpty(value) {
11514 if (value == null) {
11517 if (isArrayLike(value) &&
11518 (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
11519 isBuffer(value) || isTypedArray(value) || isArguments(value))) {
11520 return !value.length;
11522 var tag = getTag(value);
11523 if (tag == mapTag || tag == setTag) {
11524 return !value.size;
11526 if (isPrototype(value)) {
11527 return !baseKeys(value).length;
11529 for (var key in value) {
11530 if (hasOwnProperty.call(value, key)) {
11538 * Performs a deep comparison between two values to determine if they are
11541 * **Note:** This method supports comparing arrays, array buffers, booleans,
11542 * date objects, error objects, maps, numbers, `Object` objects, regexes,
11543 * sets, strings, symbols, and typed arrays. `Object` objects are compared
11544 * by their own, not inherited, enumerable properties. Functions and DOM
11545 * nodes are compared by strict equality, i.e. `===`.
11551 * @param {*} value The value to compare.
11552 * @param {*} other The other value to compare.
11553 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11556 * var object = { 'a': 1 };
11557 * var other = { 'a': 1 };
11559 * _.isEqual(object, other);
11562 * object === other;
11565 function isEqual(value, other) {
11566 return baseIsEqual(value, other);
11570 * This method is like `_.isEqual` except that it accepts `customizer` which
11571 * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11572 * are handled by the method instead. The `customizer` is invoked with up to
11573 * six arguments: (objValue, othValue [, index|key, object, other, stack]).
11579 * @param {*} value The value to compare.
11580 * @param {*} other The other value to compare.
11581 * @param {Function} [customizer] The function to customize comparisons.
11582 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11585 * function isGreeting(value) {
11586 * return /^h(?:i|ello)$/.test(value);
11589 * function customizer(objValue, othValue) {
11590 * if (isGreeting(objValue) && isGreeting(othValue)) {
11595 * var array = ['hello', 'goodbye'];
11596 * var other = ['hi', 'goodbye'];
11598 * _.isEqualWith(array, other, customizer);
11601 function isEqualWith(value, other, customizer) {
11602 customizer = typeof customizer == 'function' ? customizer : undefined;
11603 var result = customizer ? customizer(value, other) : undefined;
11604 return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
11608 * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
11609 * `SyntaxError`, `TypeError`, or `URIError` object.
11615 * @param {*} value The value to check.
11616 * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
11619 * _.isError(new Error);
11622 * _.isError(Error);
11625 function isError(value) {
11626 if (!isObjectLike(value)) {
11629 var tag = baseGetTag(value);
11630 return tag == errorTag || tag == domExcTag ||
11631 (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
11635 * Checks if `value` is a finite primitive number.
11637 * **Note:** This method is based on
11638 * [`Number.isFinite`](https://mdn.io/Number/isFinite).
11644 * @param {*} value The value to check.
11645 * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
11651 * _.isFinite(Number.MIN_VALUE);
11654 * _.isFinite(Infinity);
11660 function isFinite(value) {
11661 return typeof value == 'number' && nativeIsFinite(value);
11665 * Checks if `value` is classified as a `Function` object.
11671 * @param {*} value The value to check.
11672 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
11678 * _.isFunction(/abc/);
11681 function isFunction(value) {
11682 if (!isObject(value)) {
11685 // The use of `Object#toString` avoids issues with the `typeof` operator
11686 // in Safari 9 which returns 'object' for typed arrays and other constructors.
11687 var tag = baseGetTag(value);
11688 return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
11692 * Checks if `value` is an integer.
11694 * **Note:** This method is based on
11695 * [`Number.isInteger`](https://mdn.io/Number/isInteger).
11701 * @param {*} value The value to check.
11702 * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
11708 * _.isInteger(Number.MIN_VALUE);
11711 * _.isInteger(Infinity);
11714 * _.isInteger('3');
11717 function isInteger(value) {
11718 return typeof value == 'number' && value == toInteger(value);
11722 * Checks if `value` is a valid array-like length.
11724 * **Note:** This method is loosely based on
11725 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
11731 * @param {*} value The value to check.
11732 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
11738 * _.isLength(Number.MIN_VALUE);
11741 * _.isLength(Infinity);
11747 function isLength(value) {
11748 return typeof value == 'number' &&
11749 value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
11753 * Checks if `value` is the
11754 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
11755 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
11761 * @param {*} value The value to check.
11762 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
11768 * _.isObject([1, 2, 3]);
11771 * _.isObject(_.noop);
11774 * _.isObject(null);
11777 function isObject(value) {
11778 var type = typeof value;
11779 return value != null && (type == 'object' || type == 'function');
11783 * Checks if `value` is object-like. A value is object-like if it's not `null`
11784 * and has a `typeof` result of "object".
11790 * @param {*} value The value to check.
11791 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
11794 * _.isObjectLike({});
11797 * _.isObjectLike([1, 2, 3]);
11800 * _.isObjectLike(_.noop);
11803 * _.isObjectLike(null);
11806 function isObjectLike(value) {
11807 return value != null && typeof value == 'object';
11811 * Checks if `value` is classified as a `Map` object.
11817 * @param {*} value The value to check.
11818 * @returns {boolean} Returns `true` if `value` is a map, else `false`.
11821 * _.isMap(new Map);
11824 * _.isMap(new WeakMap);
11827 var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
11830 * Performs a partial deep comparison between `object` and `source` to
11831 * determine if `object` contains equivalent property values.
11833 * **Note:** This method is equivalent to `_.matches` when `source` is
11834 * partially applied.
11836 * Partial comparisons will match empty array and empty object `source`
11837 * values against any array or object value, respectively. See `_.isEqual`
11838 * for a list of supported value comparisons.
11844 * @param {Object} object The object to inspect.
11845 * @param {Object} source The object of property values to match.
11846 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11849 * var object = { 'a': 1, 'b': 2 };
11851 * _.isMatch(object, { 'b': 2 });
11854 * _.isMatch(object, { 'b': 1 });
11857 function isMatch(object, source) {
11858 return object === source || baseIsMatch(object, source, getMatchData(source));
11862 * This method is like `_.isMatch` except that it accepts `customizer` which
11863 * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11864 * are handled by the method instead. The `customizer` is invoked with five
11865 * arguments: (objValue, srcValue, index|key, object, source).
11871 * @param {Object} object The object to inspect.
11872 * @param {Object} source The object of property values to match.
11873 * @param {Function} [customizer] The function to customize comparisons.
11874 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11877 * function isGreeting(value) {
11878 * return /^h(?:i|ello)$/.test(value);
11881 * function customizer(objValue, srcValue) {
11882 * if (isGreeting(objValue) && isGreeting(srcValue)) {
11887 * var object = { 'greeting': 'hello' };
11888 * var source = { 'greeting': 'hi' };
11890 * _.isMatchWith(object, source, customizer);
11893 function isMatchWith(object, source, customizer) {
11894 customizer = typeof customizer == 'function' ? customizer : undefined;
11895 return baseIsMatch(object, source, getMatchData(source), customizer);
11899 * Checks if `value` is `NaN`.
11901 * **Note:** This method is based on
11902 * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
11903 * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
11904 * `undefined` and other non-number values.
11910 * @param {*} value The value to check.
11911 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
11917 * _.isNaN(new Number(NaN));
11920 * isNaN(undefined);
11923 * _.isNaN(undefined);
11926 function isNaN(value) {
11927 // An `NaN` primitive is the only value that is not equal to itself.
11928 // Perform the `toStringTag` check first to avoid errors with some
11929 // ActiveX objects in IE.
11930 return isNumber(value) && value != +value;
11934 * Checks if `value` is a pristine native function.
11936 * **Note:** This method can't reliably detect native functions in the presence
11937 * of the core-js package because core-js circumvents this kind of detection.
11938 * Despite multiple requests, the core-js maintainer has made it clear: any
11939 * attempt to fix the detection will be obstructed. As a result, we're left
11940 * with little choice but to throw an error. Unfortunately, this also affects
11941 * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
11942 * which rely on core-js.
11948 * @param {*} value The value to check.
11949 * @returns {boolean} Returns `true` if `value` is a native function,
11953 * _.isNative(Array.prototype.push);
11959 function isNative(value) {
11960 if (isMaskable(value)) {
11961 throw new Error(CORE_ERROR_TEXT);
11963 return baseIsNative(value);
11967 * Checks if `value` is `null`.
11973 * @param {*} value The value to check.
11974 * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
11980 * _.isNull(void 0);
11983 function isNull(value) {
11984 return value === null;
11988 * Checks if `value` is `null` or `undefined`.
11994 * @param {*} value The value to check.
11995 * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
12007 function isNil(value) {
12008 return value == null;
12012 * Checks if `value` is classified as a `Number` primitive or object.
12014 * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
12015 * classified as numbers, use the `_.isFinite` method.
12021 * @param {*} value The value to check.
12022 * @returns {boolean} Returns `true` if `value` is a number, else `false`.
12028 * _.isNumber(Number.MIN_VALUE);
12031 * _.isNumber(Infinity);
12037 function isNumber(value) {
12038 return typeof value == 'number' ||
12039 (isObjectLike(value) && baseGetTag(value) == numberTag);
12043 * Checks if `value` is a plain object, that is, an object created by the
12044 * `Object` constructor or one with a `[[Prototype]]` of `null`.
12050 * @param {*} value The value to check.
12051 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
12058 * _.isPlainObject(new Foo);
12061 * _.isPlainObject([1, 2, 3]);
12064 * _.isPlainObject({ 'x': 0, 'y': 0 });
12067 * _.isPlainObject(Object.create(null));
12070 function isPlainObject(value) {
12071 if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
12074 var proto = getPrototype(value);
12075 if (proto === null) {
12078 var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
12079 return typeof Ctor == 'function' && Ctor instanceof Ctor &&
12080 funcToString.call(Ctor) == objectCtorString;
12084 * Checks if `value` is classified as a `RegExp` object.
12090 * @param {*} value The value to check.
12091 * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
12094 * _.isRegExp(/abc/);
12097 * _.isRegExp('/abc/');
12100 var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
12103 * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
12104 * double precision number which isn't the result of a rounded unsafe integer.
12106 * **Note:** This method is based on
12107 * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
12113 * @param {*} value The value to check.
12114 * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
12117 * _.isSafeInteger(3);
12120 * _.isSafeInteger(Number.MIN_VALUE);
12123 * _.isSafeInteger(Infinity);
12126 * _.isSafeInteger('3');
12129 function isSafeInteger(value) {
12130 return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
12134 * Checks if `value` is classified as a `Set` object.
12140 * @param {*} value The value to check.
12141 * @returns {boolean} Returns `true` if `value` is a set, else `false`.
12144 * _.isSet(new Set);
12147 * _.isSet(new WeakSet);
12150 var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
12153 * Checks if `value` is classified as a `String` primitive or object.
12159 * @param {*} value The value to check.
12160 * @returns {boolean} Returns `true` if `value` is a string, else `false`.
12163 * _.isString('abc');
12169 function isString(value) {
12170 return typeof value == 'string' ||
12171 (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
12175 * Checks if `value` is classified as a `Symbol` primitive or object.
12181 * @param {*} value The value to check.
12182 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
12185 * _.isSymbol(Symbol.iterator);
12188 * _.isSymbol('abc');
12191 function isSymbol(value) {
12192 return typeof value == 'symbol' ||
12193 (isObjectLike(value) && baseGetTag(value) == symbolTag);
12197 * Checks if `value` is classified as a typed array.
12203 * @param {*} value The value to check.
12204 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
12207 * _.isTypedArray(new Uint8Array);
12210 * _.isTypedArray([]);
12213 var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
12216 * Checks if `value` is `undefined`.
12222 * @param {*} value The value to check.
12223 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
12226 * _.isUndefined(void 0);
12229 * _.isUndefined(null);
12232 function isUndefined(value) {
12233 return value === undefined;
12237 * Checks if `value` is classified as a `WeakMap` object.
12243 * @param {*} value The value to check.
12244 * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
12247 * _.isWeakMap(new WeakMap);
12250 * _.isWeakMap(new Map);
12253 function isWeakMap(value) {
12254 return isObjectLike(value) && getTag(value) == weakMapTag;
12258 * Checks if `value` is classified as a `WeakSet` object.
12264 * @param {*} value The value to check.
12265 * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
12268 * _.isWeakSet(new WeakSet);
12271 * _.isWeakSet(new Set);
12274 function isWeakSet(value) {
12275 return isObjectLike(value) && baseGetTag(value) == weakSetTag;
12279 * Checks if `value` is less than `other`.
12285 * @param {*} value The value to compare.
12286 * @param {*} other The other value to compare.
12287 * @returns {boolean} Returns `true` if `value` is less than `other`,
12301 var lt = createRelationalOperation(baseLt);
12304 * Checks if `value` is less than or equal to `other`.
12310 * @param {*} value The value to compare.
12311 * @param {*} other The other value to compare.
12312 * @returns {boolean} Returns `true` if `value` is less than or equal to
12313 * `other`, else `false`.
12326 var lte = createRelationalOperation(function(value, other) {
12327 return value <= other;
12331 * Converts `value` to an array.
12337 * @param {*} value The value to convert.
12338 * @returns {Array} Returns the converted array.
12341 * _.toArray({ 'a': 1, 'b': 2 });
12344 * _.toArray('abc');
12345 * // => ['a', 'b', 'c']
12353 function toArray(value) {
12357 if (isArrayLike(value)) {
12358 return isString(value) ? stringToArray(value) : copyArray(value);
12360 if (symIterator && value[symIterator]) {
12361 return iteratorToArray(value[symIterator]());
12363 var tag = getTag(value),
12364 func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
12366 return func(value);
12370 * Converts `value` to a finite number.
12376 * @param {*} value The value to convert.
12377 * @returns {number} Returns the converted number.
12383 * _.toFinite(Number.MIN_VALUE);
12386 * _.toFinite(Infinity);
12387 * // => 1.7976931348623157e+308
12389 * _.toFinite('3.2');
12392 function toFinite(value) {
12394 return value === 0 ? value : 0;
12396 value = toNumber(value);
12397 if (value === INFINITY || value === -INFINITY) {
12398 var sign = (value < 0 ? -1 : 1);
12399 return sign * MAX_INTEGER;
12401 return value === value ? value : 0;
12405 * Converts `value` to an integer.
12407 * **Note:** This method is loosely based on
12408 * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
12414 * @param {*} value The value to convert.
12415 * @returns {number} Returns the converted integer.
12418 * _.toInteger(3.2);
12421 * _.toInteger(Number.MIN_VALUE);
12424 * _.toInteger(Infinity);
12425 * // => 1.7976931348623157e+308
12427 * _.toInteger('3.2');
12430 function toInteger(value) {
12431 var result = toFinite(value),
12432 remainder = result % 1;
12434 return result === result ? (remainder ? result - remainder : result) : 0;
12438 * Converts `value` to an integer suitable for use as the length of an
12439 * array-like object.
12441 * **Note:** This method is based on
12442 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
12448 * @param {*} value The value to convert.
12449 * @returns {number} Returns the converted integer.
12455 * _.toLength(Number.MIN_VALUE);
12458 * _.toLength(Infinity);
12461 * _.toLength('3.2');
12464 function toLength(value) {
12465 return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
12469 * Converts `value` to a number.
12475 * @param {*} value The value to process.
12476 * @returns {number} Returns the number.
12482 * _.toNumber(Number.MIN_VALUE);
12485 * _.toNumber(Infinity);
12488 * _.toNumber('3.2');
12491 function toNumber(value) {
12492 if (typeof value == 'number') {
12495 if (isSymbol(value)) {
12498 if (isObject(value)) {
12499 var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
12500 value = isObject(other) ? (other + '') : other;
12502 if (typeof value != 'string') {
12503 return value === 0 ? value : +value;
12505 value = value.replace(reTrim, '');
12506 var isBinary = reIsBinary.test(value);
12507 return (isBinary || reIsOctal.test(value))
12508 ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
12509 : (reIsBadHex.test(value) ? NAN : +value);
12513 * Converts `value` to a plain object flattening inherited enumerable string
12514 * keyed properties of `value` to own properties of the plain object.
12520 * @param {*} value The value to convert.
12521 * @returns {Object} Returns the converted plain object.
12528 * Foo.prototype.c = 3;
12530 * _.assign({ 'a': 1 }, new Foo);
12531 * // => { 'a': 1, 'b': 2 }
12533 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
12534 * // => { 'a': 1, 'b': 2, 'c': 3 }
12536 function toPlainObject(value) {
12537 return copyObject(value, keysIn(value));
12541 * Converts `value` to a safe integer. A safe integer can be compared and
12542 * represented correctly.
12548 * @param {*} value The value to convert.
12549 * @returns {number} Returns the converted integer.
12552 * _.toSafeInteger(3.2);
12555 * _.toSafeInteger(Number.MIN_VALUE);
12558 * _.toSafeInteger(Infinity);
12559 * // => 9007199254740991
12561 * _.toSafeInteger('3.2');
12564 function toSafeInteger(value) {
12566 ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
12567 : (value === 0 ? value : 0);
12571 * Converts `value` to a string. An empty string is returned for `null`
12572 * and `undefined` values. The sign of `-0` is preserved.
12578 * @param {*} value The value to convert.
12579 * @returns {string} Returns the converted string.
12582 * _.toString(null);
12588 * _.toString([1, 2, 3]);
12591 function toString(value) {
12592 return value == null ? '' : baseToString(value);
12595 /*------------------------------------------------------------------------*/
12598 * Assigns own enumerable string keyed properties of source objects to the
12599 * destination object. Source objects are applied from left to right.
12600 * Subsequent sources overwrite property assignments of previous sources.
12602 * **Note:** This method mutates `object` and is loosely based on
12603 * [`Object.assign`](https://mdn.io/Object/assign).
12609 * @param {Object} object The destination object.
12610 * @param {...Object} [sources] The source objects.
12611 * @returns {Object} Returns `object`.
12623 * Foo.prototype.b = 2;
12624 * Bar.prototype.d = 4;
12626 * _.assign({ 'a': 0 }, new Foo, new Bar);
12627 * // => { 'a': 1, 'c': 3 }
12629 var assign = createAssigner(function(object, source) {
12630 if (isPrototype(source) || isArrayLike(source)) {
12631 copyObject(source, keys(source), object);
12634 for (var key in source) {
12635 if (hasOwnProperty.call(source, key)) {
12636 assignValue(object, key, source[key]);
12642 * This method is like `_.assign` except that it iterates over own and
12643 * inherited source properties.
12645 * **Note:** This method mutates `object`.
12652 * @param {Object} object The destination object.
12653 * @param {...Object} [sources] The source objects.
12654 * @returns {Object} Returns `object`.
12666 * Foo.prototype.b = 2;
12667 * Bar.prototype.d = 4;
12669 * _.assignIn({ 'a': 0 }, new Foo, new Bar);
12670 * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
12672 var assignIn = createAssigner(function(object, source) {
12673 copyObject(source, keysIn(source), object);
12677 * This method is like `_.assignIn` except that it accepts `customizer`
12678 * which is invoked to produce the assigned values. If `customizer` returns
12679 * `undefined`, assignment is handled by the method instead. The `customizer`
12680 * is invoked with five arguments: (objValue, srcValue, key, object, source).
12682 * **Note:** This method mutates `object`.
12687 * @alias extendWith
12689 * @param {Object} object The destination object.
12690 * @param {...Object} sources The source objects.
12691 * @param {Function} [customizer] The function to customize assigned values.
12692 * @returns {Object} Returns `object`.
12693 * @see _.assignWith
12696 * function customizer(objValue, srcValue) {
12697 * return _.isUndefined(objValue) ? srcValue : objValue;
12700 * var defaults = _.partialRight(_.assignInWith, customizer);
12702 * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12703 * // => { 'a': 1, 'b': 2 }
12705 var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
12706 copyObject(source, keysIn(source), object, customizer);
12710 * This method is like `_.assign` except that it accepts `customizer`
12711 * which is invoked to produce the assigned values. If `customizer` returns
12712 * `undefined`, assignment is handled by the method instead. The `customizer`
12713 * is invoked with five arguments: (objValue, srcValue, key, object, source).
12715 * **Note:** This method mutates `object`.
12721 * @param {Object} object The destination object.
12722 * @param {...Object} sources The source objects.
12723 * @param {Function} [customizer] The function to customize assigned values.
12724 * @returns {Object} Returns `object`.
12725 * @see _.assignInWith
12728 * function customizer(objValue, srcValue) {
12729 * return _.isUndefined(objValue) ? srcValue : objValue;
12732 * var defaults = _.partialRight(_.assignWith, customizer);
12734 * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12735 * // => { 'a': 1, 'b': 2 }
12737 var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
12738 copyObject(source, keys(source), object, customizer);
12742 * Creates an array of values corresponding to `paths` of `object`.
12748 * @param {Object} object The object to iterate over.
12749 * @param {...(string|string[])} [paths] The property paths to pick.
12750 * @returns {Array} Returns the picked values.
12753 * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
12755 * _.at(object, ['a[0].b.c', 'a[1]']);
12758 var at = flatRest(baseAt);
12761 * Creates an object that inherits from the `prototype` object. If a
12762 * `properties` object is given, its own enumerable string keyed properties
12763 * are assigned to the created object.
12769 * @param {Object} prototype The object to inherit from.
12770 * @param {Object} [properties] The properties to assign to the object.
12771 * @returns {Object} Returns the new object.
12774 * function Shape() {
12779 * function Circle() {
12780 * Shape.call(this);
12783 * Circle.prototype = _.create(Shape.prototype, {
12784 * 'constructor': Circle
12787 * var circle = new Circle;
12788 * circle instanceof Circle;
12791 * circle instanceof Shape;
12794 function create(prototype, properties) {
12795 var result = baseCreate(prototype);
12796 return properties == null ? result : baseAssign(result, properties);
12800 * Assigns own and inherited enumerable string keyed properties of source
12801 * objects to the destination object for all destination properties that
12802 * resolve to `undefined`. Source objects are applied from left to right.
12803 * Once a property is set, additional values of the same property are ignored.
12805 * **Note:** This method mutates `object`.
12811 * @param {Object} object The destination object.
12812 * @param {...Object} [sources] The source objects.
12813 * @returns {Object} Returns `object`.
12814 * @see _.defaultsDeep
12817 * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12818 * // => { 'a': 1, 'b': 2 }
12820 var defaults = baseRest(function(args) {
12821 args.push(undefined, customDefaultsAssignIn);
12822 return apply(assignInWith, undefined, args);
12826 * This method is like `_.defaults` except that it recursively assigns
12827 * default properties.
12829 * **Note:** This method mutates `object`.
12835 * @param {Object} object The destination object.
12836 * @param {...Object} [sources] The source objects.
12837 * @returns {Object} Returns `object`.
12841 * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
12842 * // => { 'a': { 'b': 2, 'c': 3 } }
12844 var defaultsDeep = baseRest(function(args) {
12845 args.push(undefined, customDefaultsMerge);
12846 return apply(mergeWith, undefined, args);
12850 * This method is like `_.find` except that it returns the key of the first
12851 * element `predicate` returns truthy for instead of the element itself.
12857 * @param {Object} object The object to inspect.
12858 * @param {Function} [predicate=_.identity] The function invoked per iteration.
12859 * @returns {string|undefined} Returns the key of the matched element,
12860 * else `undefined`.
12864 * 'barney': { 'age': 36, 'active': true },
12865 * 'fred': { 'age': 40, 'active': false },
12866 * 'pebbles': { 'age': 1, 'active': true }
12869 * _.findKey(users, function(o) { return o.age < 40; });
12870 * // => 'barney' (iteration order is not guaranteed)
12872 * // The `_.matches` iteratee shorthand.
12873 * _.findKey(users, { 'age': 1, 'active': true });
12876 * // The `_.matchesProperty` iteratee shorthand.
12877 * _.findKey(users, ['active', false]);
12880 * // The `_.property` iteratee shorthand.
12881 * _.findKey(users, 'active');
12884 function findKey(object, predicate) {
12885 return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
12889 * This method is like `_.findKey` except that it iterates over elements of
12890 * a collection in the opposite order.
12896 * @param {Object} object The object to inspect.
12897 * @param {Function} [predicate=_.identity] The function invoked per iteration.
12898 * @returns {string|undefined} Returns the key of the matched element,
12899 * else `undefined`.
12903 * 'barney': { 'age': 36, 'active': true },
12904 * 'fred': { 'age': 40, 'active': false },
12905 * 'pebbles': { 'age': 1, 'active': true }
12908 * _.findLastKey(users, function(o) { return o.age < 40; });
12909 * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
12911 * // The `_.matches` iteratee shorthand.
12912 * _.findLastKey(users, { 'age': 36, 'active': true });
12915 * // The `_.matchesProperty` iteratee shorthand.
12916 * _.findLastKey(users, ['active', false]);
12919 * // The `_.property` iteratee shorthand.
12920 * _.findLastKey(users, 'active');
12923 function findLastKey(object, predicate) {
12924 return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
12928 * Iterates over own and inherited enumerable string keyed properties of an
12929 * object and invokes `iteratee` for each property. The iteratee is invoked
12930 * with three arguments: (value, key, object). Iteratee functions may exit
12931 * iteration early by explicitly returning `false`.
12937 * @param {Object} object The object to iterate over.
12938 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12939 * @returns {Object} Returns `object`.
12940 * @see _.forInRight
12948 * Foo.prototype.c = 3;
12950 * _.forIn(new Foo, function(value, key) {
12951 * console.log(key);
12953 * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
12955 function forIn(object, iteratee) {
12956 return object == null
12958 : baseFor(object, getIteratee(iteratee, 3), keysIn);
12962 * This method is like `_.forIn` except that it iterates over properties of
12963 * `object` in the opposite order.
12969 * @param {Object} object The object to iterate over.
12970 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12971 * @returns {Object} Returns `object`.
12980 * Foo.prototype.c = 3;
12982 * _.forInRight(new Foo, function(value, key) {
12983 * console.log(key);
12985 * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
12987 function forInRight(object, iteratee) {
12988 return object == null
12990 : baseForRight(object, getIteratee(iteratee, 3), keysIn);
12994 * Iterates over own enumerable string keyed properties of an object and
12995 * invokes `iteratee` for each property. The iteratee is invoked with three
12996 * arguments: (value, key, object). Iteratee functions may exit iteration
12997 * early by explicitly returning `false`.
13003 * @param {Object} object The object to iterate over.
13004 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13005 * @returns {Object} Returns `object`.
13006 * @see _.forOwnRight
13014 * Foo.prototype.c = 3;
13016 * _.forOwn(new Foo, function(value, key) {
13017 * console.log(key);
13019 * // => Logs 'a' then 'b' (iteration order is not guaranteed).
13021 function forOwn(object, iteratee) {
13022 return object && baseForOwn(object, getIteratee(iteratee, 3));
13026 * This method is like `_.forOwn` except that it iterates over properties of
13027 * `object` in the opposite order.
13033 * @param {Object} object The object to iterate over.
13034 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13035 * @returns {Object} Returns `object`.
13044 * Foo.prototype.c = 3;
13046 * _.forOwnRight(new Foo, function(value, key) {
13047 * console.log(key);
13049 * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
13051 function forOwnRight(object, iteratee) {
13052 return object && baseForOwnRight(object, getIteratee(iteratee, 3));
13056 * Creates an array of function property names from own enumerable properties
13063 * @param {Object} object The object to inspect.
13064 * @returns {Array} Returns the function names.
13065 * @see _.functionsIn
13069 * this.a = _.constant('a');
13070 * this.b = _.constant('b');
13073 * Foo.prototype.c = _.constant('c');
13075 * _.functions(new Foo);
13078 function functions(object) {
13079 return object == null ? [] : baseFunctions(object, keys(object));
13083 * Creates an array of function property names from own and inherited
13084 * enumerable properties of `object`.
13090 * @param {Object} object The object to inspect.
13091 * @returns {Array} Returns the function names.
13096 * this.a = _.constant('a');
13097 * this.b = _.constant('b');
13100 * Foo.prototype.c = _.constant('c');
13102 * _.functionsIn(new Foo);
13103 * // => ['a', 'b', 'c']
13105 function functionsIn(object) {
13106 return object == null ? [] : baseFunctions(object, keysIn(object));
13110 * Gets the value at `path` of `object`. If the resolved value is
13111 * `undefined`, the `defaultValue` is returned in its place.
13117 * @param {Object} object The object to query.
13118 * @param {Array|string} path The path of the property to get.
13119 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13120 * @returns {*} Returns the resolved value.
13123 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13125 * _.get(object, 'a[0].b.c');
13128 * _.get(object, ['a', '0', 'b', 'c']);
13131 * _.get(object, 'a.b.c', 'default');
13134 function get(object, path, defaultValue) {
13135 var result = object == null ? undefined : baseGet(object, path);
13136 return result === undefined ? defaultValue : result;
13140 * Checks if `path` is a direct property of `object`.
13146 * @param {Object} object The object to query.
13147 * @param {Array|string} path The path to check.
13148 * @returns {boolean} Returns `true` if `path` exists, else `false`.
13151 * var object = { 'a': { 'b': 2 } };
13152 * var other = _.create({ 'a': _.create({ 'b': 2 }) });
13154 * _.has(object, 'a');
13157 * _.has(object, 'a.b');
13160 * _.has(object, ['a', 'b']);
13163 * _.has(other, 'a');
13166 function has(object, path) {
13167 return object != null && hasPath(object, path, baseHas);
13171 * Checks if `path` is a direct or inherited property of `object`.
13177 * @param {Object} object The object to query.
13178 * @param {Array|string} path The path to check.
13179 * @returns {boolean} Returns `true` if `path` exists, else `false`.
13182 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
13184 * _.hasIn(object, 'a');
13187 * _.hasIn(object, 'a.b');
13190 * _.hasIn(object, ['a', 'b']);
13193 * _.hasIn(object, 'b');
13196 function hasIn(object, path) {
13197 return object != null && hasPath(object, path, baseHasIn);
13201 * Creates an object composed of the inverted keys and values of `object`.
13202 * If `object` contains duplicate values, subsequent values overwrite
13203 * property assignments of previous values.
13209 * @param {Object} object The object to invert.
13210 * @returns {Object} Returns the new inverted object.
13213 * var object = { 'a': 1, 'b': 2, 'c': 1 };
13215 * _.invert(object);
13216 * // => { '1': 'c', '2': 'b' }
13218 var invert = createInverter(function(result, value, key) {
13219 result[value] = key;
13220 }, constant(identity));
13223 * This method is like `_.invert` except that the inverted object is generated
13224 * from the results of running each element of `object` thru `iteratee`. The
13225 * corresponding inverted value of each inverted key is an array of keys
13226 * responsible for generating the inverted value. The iteratee is invoked
13227 * with one argument: (value).
13233 * @param {Object} object The object to invert.
13234 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
13235 * @returns {Object} Returns the new inverted object.
13238 * var object = { 'a': 1, 'b': 2, 'c': 1 };
13240 * _.invertBy(object);
13241 * // => { '1': ['a', 'c'], '2': ['b'] }
13243 * _.invertBy(object, function(value) {
13244 * return 'group' + value;
13246 * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
13248 var invertBy = createInverter(function(result, value, key) {
13249 if (hasOwnProperty.call(result, value)) {
13250 result[value].push(key);
13252 result[value] = [key];
13257 * Invokes the method at `path` of `object`.
13263 * @param {Object} object The object to query.
13264 * @param {Array|string} path The path of the method to invoke.
13265 * @param {...*} [args] The arguments to invoke the method with.
13266 * @returns {*} Returns the result of the invoked method.
13269 * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
13271 * _.invoke(object, 'a[0].b.c.slice', 1, 3);
13274 var invoke = baseRest(baseInvoke);
13277 * Creates an array of the own enumerable property names of `object`.
13279 * **Note:** Non-object values are coerced to objects. See the
13280 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
13281 * for more details.
13287 * @param {Object} object The object to query.
13288 * @returns {Array} Returns the array of property names.
13296 * Foo.prototype.c = 3;
13299 * // => ['a', 'b'] (iteration order is not guaranteed)
13304 function keys(object) {
13305 return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
13309 * Creates an array of the own and inherited enumerable property names of `object`.
13311 * **Note:** Non-object values are coerced to objects.
13317 * @param {Object} object The object to query.
13318 * @returns {Array} Returns the array of property names.
13326 * Foo.prototype.c = 3;
13328 * _.keysIn(new Foo);
13329 * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
13331 function keysIn(object) {
13332 return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
13336 * The opposite of `_.mapValues`; this method creates an object with the
13337 * same values as `object` and keys generated by running each own enumerable
13338 * string keyed property of `object` thru `iteratee`. The iteratee is invoked
13339 * with three arguments: (value, key, object).
13345 * @param {Object} object The object to iterate over.
13346 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13347 * @returns {Object} Returns the new mapped object.
13351 * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
13352 * return key + value;
13354 * // => { 'a1': 1, 'b2': 2 }
13356 function mapKeys(object, iteratee) {
13358 iteratee = getIteratee(iteratee, 3);
13360 baseForOwn(object, function(value, key, object) {
13361 baseAssignValue(result, iteratee(value, key, object), value);
13367 * Creates an object with the same keys as `object` and values generated
13368 * by running each own enumerable string keyed property of `object` thru
13369 * `iteratee`. The iteratee is invoked with three arguments:
13370 * (value, key, object).
13376 * @param {Object} object The object to iterate over.
13377 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13378 * @returns {Object} Returns the new mapped object.
13383 * 'fred': { 'user': 'fred', 'age': 40 },
13384 * 'pebbles': { 'user': 'pebbles', 'age': 1 }
13387 * _.mapValues(users, function(o) { return o.age; });
13388 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13390 * // The `_.property` iteratee shorthand.
13391 * _.mapValues(users, 'age');
13392 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13394 function mapValues(object, iteratee) {
13396 iteratee = getIteratee(iteratee, 3);
13398 baseForOwn(object, function(value, key, object) {
13399 baseAssignValue(result, key, iteratee(value, key, object));
13405 * This method is like `_.assign` except that it recursively merges own and
13406 * inherited enumerable string keyed properties of source objects into the
13407 * destination object. Source properties that resolve to `undefined` are
13408 * skipped if a destination value exists. Array and plain object properties
13409 * are merged recursively. Other objects and value types are overridden by
13410 * assignment. Source objects are applied from left to right. Subsequent
13411 * sources overwrite property assignments of previous sources.
13413 * **Note:** This method mutates `object`.
13419 * @param {Object} object The destination object.
13420 * @param {...Object} [sources] The source objects.
13421 * @returns {Object} Returns `object`.
13425 * 'a': [{ 'b': 2 }, { 'd': 4 }]
13429 * 'a': [{ 'c': 3 }, { 'e': 5 }]
13432 * _.merge(object, other);
13433 * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
13435 var merge = createAssigner(function(object, source, srcIndex) {
13436 baseMerge(object, source, srcIndex);
13440 * This method is like `_.merge` except that it accepts `customizer` which
13441 * is invoked to produce the merged values of the destination and source
13442 * properties. If `customizer` returns `undefined`, merging is handled by the
13443 * method instead. The `customizer` is invoked with six arguments:
13444 * (objValue, srcValue, key, object, source, stack).
13446 * **Note:** This method mutates `object`.
13452 * @param {Object} object The destination object.
13453 * @param {...Object} sources The source objects.
13454 * @param {Function} customizer The function to customize assigned values.
13455 * @returns {Object} Returns `object`.
13458 * function customizer(objValue, srcValue) {
13459 * if (_.isArray(objValue)) {
13460 * return objValue.concat(srcValue);
13464 * var object = { 'a': [1], 'b': [2] };
13465 * var other = { 'a': [3], 'b': [4] };
13467 * _.mergeWith(object, other, customizer);
13468 * // => { 'a': [1, 3], 'b': [2, 4] }
13470 var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
13471 baseMerge(object, source, srcIndex, customizer);
13475 * The opposite of `_.pick`; this method creates an object composed of the
13476 * own and inherited enumerable property paths of `object` that are not omitted.
13478 * **Note:** This method is considerably slower than `_.pick`.
13484 * @param {Object} object The source object.
13485 * @param {...(string|string[])} [paths] The property paths to omit.
13486 * @returns {Object} Returns the new object.
13489 * var object = { 'a': 1, 'b': '2', 'c': 3 };
13491 * _.omit(object, ['a', 'c']);
13492 * // => { 'b': '2' }
13494 var omit = flatRest(function(object, paths) {
13496 if (object == null) {
13499 var isDeep = false;
13500 paths = arrayMap(paths, function(path) {
13501 path = castPath(path, object);
13502 isDeep || (isDeep = path.length > 1);
13505 copyObject(object, getAllKeysIn(object), result);
13507 result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
13509 var length = paths.length;
13511 baseUnset(result, paths[length]);
13517 * The opposite of `_.pickBy`; this method creates an object composed of
13518 * the own and inherited enumerable string keyed properties of `object` that
13519 * `predicate` doesn't return truthy for. The predicate is invoked with two
13520 * arguments: (value, key).
13526 * @param {Object} object The source object.
13527 * @param {Function} [predicate=_.identity] The function invoked per property.
13528 * @returns {Object} Returns the new object.
13531 * var object = { 'a': 1, 'b': '2', 'c': 3 };
13533 * _.omitBy(object, _.isNumber);
13534 * // => { 'b': '2' }
13536 function omitBy(object, predicate) {
13537 return pickBy(object, negate(getIteratee(predicate)));
13541 * Creates an object composed of the picked `object` properties.
13547 * @param {Object} object The source object.
13548 * @param {...(string|string[])} [paths] The property paths to pick.
13549 * @returns {Object} Returns the new object.
13552 * var object = { 'a': 1, 'b': '2', 'c': 3 };
13554 * _.pick(object, ['a', 'c']);
13555 * // => { 'a': 1, 'c': 3 }
13557 var pick = flatRest(function(object, paths) {
13558 return object == null ? {} : basePick(object, paths);
13562 * Creates an object composed of the `object` properties `predicate` returns
13563 * truthy for. The predicate is invoked with two arguments: (value, key).
13569 * @param {Object} object The source object.
13570 * @param {Function} [predicate=_.identity] The function invoked per property.
13571 * @returns {Object} Returns the new object.
13574 * var object = { 'a': 1, 'b': '2', 'c': 3 };
13576 * _.pickBy(object, _.isNumber);
13577 * // => { 'a': 1, 'c': 3 }
13579 function pickBy(object, predicate) {
13580 if (object == null) {
13583 var props = arrayMap(getAllKeysIn(object), function(prop) {
13586 predicate = getIteratee(predicate);
13587 return basePickBy(object, props, function(value, path) {
13588 return predicate(value, path[0]);
13593 * This method is like `_.get` except that if the resolved value is a
13594 * function it's invoked with the `this` binding of its parent object and
13595 * its result is returned.
13601 * @param {Object} object The object to query.
13602 * @param {Array|string} path The path of the property to resolve.
13603 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13604 * @returns {*} Returns the resolved value.
13607 * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
13609 * _.result(object, 'a[0].b.c1');
13612 * _.result(object, 'a[0].b.c2');
13615 * _.result(object, 'a[0].b.c3', 'default');
13618 * _.result(object, 'a[0].b.c3', _.constant('default'));
13621 function result(object, path, defaultValue) {
13622 path = castPath(path, object);
13625 length = path.length;
13627 // Ensure the loop is entered when path is empty.
13630 object = undefined;
13632 while (++index < length) {
13633 var value = object == null ? undefined : object[toKey(path[index])];
13634 if (value === undefined) {
13636 value = defaultValue;
13638 object = isFunction(value) ? value.call(object) : value;
13644 * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
13645 * it's created. Arrays are created for missing index properties while objects
13646 * are created for all other missing properties. Use `_.setWith` to customize
13649 * **Note:** This method mutates `object`.
13655 * @param {Object} object The object to modify.
13656 * @param {Array|string} path The path of the property to set.
13657 * @param {*} value The value to set.
13658 * @returns {Object} Returns `object`.
13661 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13663 * _.set(object, 'a[0].b.c', 4);
13664 * console.log(object.a[0].b.c);
13667 * _.set(object, ['x', '0', 'y', 'z'], 5);
13668 * console.log(object.x[0].y.z);
13671 function set(object, path, value) {
13672 return object == null ? object : baseSet(object, path, value);
13676 * This method is like `_.set` except that it accepts `customizer` which is
13677 * invoked to produce the objects of `path`. If `customizer` returns `undefined`
13678 * path creation is handled by the method instead. The `customizer` is invoked
13679 * with three arguments: (nsValue, key, nsObject).
13681 * **Note:** This method mutates `object`.
13687 * @param {Object} object The object to modify.
13688 * @param {Array|string} path The path of the property to set.
13689 * @param {*} value The value to set.
13690 * @param {Function} [customizer] The function to customize assigned values.
13691 * @returns {Object} Returns `object`.
13696 * _.setWith(object, '[0][1]', 'a', Object);
13697 * // => { '0': { '1': 'a' } }
13699 function setWith(object, path, value, customizer) {
13700 customizer = typeof customizer == 'function' ? customizer : undefined;
13701 return object == null ? object : baseSet(object, path, value, customizer);
13705 * Creates an array of own enumerable string keyed-value pairs for `object`
13706 * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
13707 * entries are returned.
13714 * @param {Object} object The object to query.
13715 * @returns {Array} Returns the key-value pairs.
13723 * Foo.prototype.c = 3;
13725 * _.toPairs(new Foo);
13726 * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
13728 var toPairs = createToPairs(keys);
13731 * Creates an array of own and inherited enumerable string keyed-value pairs
13732 * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
13733 * or set, its entries are returned.
13740 * @param {Object} object The object to query.
13741 * @returns {Array} Returns the key-value pairs.
13749 * Foo.prototype.c = 3;
13751 * _.toPairsIn(new Foo);
13752 * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
13754 var toPairsIn = createToPairs(keysIn);
13757 * An alternative to `_.reduce`; this method transforms `object` to a new
13758 * `accumulator` object which is the result of running each of its own
13759 * enumerable string keyed properties thru `iteratee`, with each invocation
13760 * potentially mutating the `accumulator` object. If `accumulator` is not
13761 * provided, a new object with the same `[[Prototype]]` will be used. The
13762 * iteratee is invoked with four arguments: (accumulator, value, key, object).
13763 * Iteratee functions may exit iteration early by explicitly returning `false`.
13769 * @param {Object} object The object to iterate over.
13770 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13771 * @param {*} [accumulator] The custom accumulator value.
13772 * @returns {*} Returns the accumulated value.
13775 * _.transform([2, 3, 4], function(result, n) {
13776 * result.push(n *= n);
13777 * return n % 2 == 0;
13781 * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
13782 * (result[value] || (result[value] = [])).push(key);
13784 * // => { '1': ['a', 'c'], '2': ['b'] }
13786 function transform(object, iteratee, accumulator) {
13787 var isArr = isArray(object),
13788 isArrLike = isArr || isBuffer(object) || isTypedArray(object);
13790 iteratee = getIteratee(iteratee, 4);
13791 if (accumulator == null) {
13792 var Ctor = object && object.constructor;
13794 accumulator = isArr ? new Ctor : [];
13796 else if (isObject(object)) {
13797 accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
13803 (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
13804 return iteratee(accumulator, value, index, object);
13806 return accumulator;
13810 * Removes the property at `path` of `object`.
13812 * **Note:** This method mutates `object`.
13818 * @param {Object} object The object to modify.
13819 * @param {Array|string} path The path of the property to unset.
13820 * @returns {boolean} Returns `true` if the property is deleted, else `false`.
13823 * var object = { 'a': [{ 'b': { 'c': 7 } }] };
13824 * _.unset(object, 'a[0].b.c');
13827 * console.log(object);
13828 * // => { 'a': [{ 'b': {} }] };
13830 * _.unset(object, ['a', '0', 'b', 'c']);
13833 * console.log(object);
13834 * // => { 'a': [{ 'b': {} }] };
13836 function unset(object, path) {
13837 return object == null ? true : baseUnset(object, path);
13841 * This method is like `_.set` except that accepts `updater` to produce the
13842 * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
13843 * is invoked with one argument: (value).
13845 * **Note:** This method mutates `object`.
13851 * @param {Object} object The object to modify.
13852 * @param {Array|string} path The path of the property to set.
13853 * @param {Function} updater The function to produce the updated value.
13854 * @returns {Object} Returns `object`.
13857 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13859 * _.update(object, 'a[0].b.c', function(n) { return n * n; });
13860 * console.log(object.a[0].b.c);
13863 * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
13864 * console.log(object.x[0].y.z);
13867 function update(object, path, updater) {
13868 return object == null ? object : baseUpdate(object, path, castFunction(updater));
13872 * This method is like `_.update` except that it accepts `customizer` which is
13873 * invoked to produce the objects of `path`. If `customizer` returns `undefined`
13874 * path creation is handled by the method instead. The `customizer` is invoked
13875 * with three arguments: (nsValue, key, nsObject).
13877 * **Note:** This method mutates `object`.
13883 * @param {Object} object The object to modify.
13884 * @param {Array|string} path The path of the property to set.
13885 * @param {Function} updater The function to produce the updated value.
13886 * @param {Function} [customizer] The function to customize assigned values.
13887 * @returns {Object} Returns `object`.
13892 * _.updateWith(object, '[0][1]', _.constant('a'), Object);
13893 * // => { '0': { '1': 'a' } }
13895 function updateWith(object, path, updater, customizer) {
13896 customizer = typeof customizer == 'function' ? customizer : undefined;
13897 return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
13901 * Creates an array of the own enumerable string keyed property values of `object`.
13903 * **Note:** Non-object values are coerced to objects.
13909 * @param {Object} object The object to query.
13910 * @returns {Array} Returns the array of property values.
13918 * Foo.prototype.c = 3;
13920 * _.values(new Foo);
13921 * // => [1, 2] (iteration order is not guaranteed)
13926 function values(object) {
13927 return object == null ? [] : baseValues(object, keys(object));
13931 * Creates an array of the own and inherited enumerable string keyed property
13932 * values of `object`.
13934 * **Note:** Non-object values are coerced to objects.
13940 * @param {Object} object The object to query.
13941 * @returns {Array} Returns the array of property values.
13949 * Foo.prototype.c = 3;
13951 * _.valuesIn(new Foo);
13952 * // => [1, 2, 3] (iteration order is not guaranteed)
13954 function valuesIn(object) {
13955 return object == null ? [] : baseValues(object, keysIn(object));
13958 /*------------------------------------------------------------------------*/
13961 * Clamps `number` within the inclusive `lower` and `upper` bounds.
13967 * @param {number} number The number to clamp.
13968 * @param {number} [lower] The lower bound.
13969 * @param {number} upper The upper bound.
13970 * @returns {number} Returns the clamped number.
13973 * _.clamp(-10, -5, 5);
13976 * _.clamp(10, -5, 5);
13979 function clamp(number, lower, upper) {
13980 if (upper === undefined) {
13984 if (upper !== undefined) {
13985 upper = toNumber(upper);
13986 upper = upper === upper ? upper : 0;
13988 if (lower !== undefined) {
13989 lower = toNumber(lower);
13990 lower = lower === lower ? lower : 0;
13992 return baseClamp(toNumber(number), lower, upper);
13996 * Checks if `n` is between `start` and up to, but not including, `end`. If
13997 * `end` is not specified, it's set to `start` with `start` then set to `0`.
13998 * If `start` is greater than `end` the params are swapped to support
14005 * @param {number} number The number to check.
14006 * @param {number} [start=0] The start of the range.
14007 * @param {number} end The end of the range.
14008 * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
14009 * @see _.range, _.rangeRight
14012 * _.inRange(3, 2, 4);
14024 * _.inRange(1.2, 2);
14027 * _.inRange(5.2, 4);
14030 * _.inRange(-3, -2, -6);
14033 function inRange(number, start, end) {
14034 start = toFinite(start);
14035 if (end === undefined) {
14039 end = toFinite(end);
14041 number = toNumber(number);
14042 return baseInRange(number, start, end);
14046 * Produces a random number between the inclusive `lower` and `upper` bounds.
14047 * If only one argument is provided a number between `0` and the given number
14048 * is returned. If `floating` is `true`, or either `lower` or `upper` are
14049 * floats, a floating-point number is returned instead of an integer.
14051 * **Note:** JavaScript follows the IEEE-754 standard for resolving
14052 * floating-point values which can produce unexpected results.
14058 * @param {number} [lower=0] The lower bound.
14059 * @param {number} [upper=1] The upper bound.
14060 * @param {boolean} [floating] Specify returning a floating-point number.
14061 * @returns {number} Returns the random number.
14065 * // => an integer between 0 and 5
14068 * // => also an integer between 0 and 5
14070 * _.random(5, true);
14071 * // => a floating-point number between 0 and 5
14073 * _.random(1.2, 5.2);
14074 * // => a floating-point number between 1.2 and 5.2
14076 function random(lower, upper, floating) {
14077 if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
14078 upper = floating = undefined;
14080 if (floating === undefined) {
14081 if (typeof upper == 'boolean') {
14085 else if (typeof lower == 'boolean') {
14090 if (lower === undefined && upper === undefined) {
14095 lower = toFinite(lower);
14096 if (upper === undefined) {
14100 upper = toFinite(upper);
14103 if (lower > upper) {
14108 if (floating || lower % 1 || upper % 1) {
14109 var rand = nativeRandom();
14110 return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
14112 return baseRandom(lower, upper);
14115 /*------------------------------------------------------------------------*/
14118 * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
14124 * @param {string} [string=''] The string to convert.
14125 * @returns {string} Returns the camel cased string.
14128 * _.camelCase('Foo Bar');
14131 * _.camelCase('--foo-bar--');
14134 * _.camelCase('__FOO_BAR__');
14137 var camelCase = createCompounder(function(result, word, index) {
14138 word = word.toLowerCase();
14139 return result + (index ? capitalize(word) : word);
14143 * Converts the first character of `string` to upper case and the remaining
14150 * @param {string} [string=''] The string to capitalize.
14151 * @returns {string} Returns the capitalized string.
14154 * _.capitalize('FRED');
14157 function capitalize(string) {
14158 return upperFirst(toString(string).toLowerCase());
14162 * Deburrs `string` by converting
14163 * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
14164 * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
14165 * letters to basic Latin letters and removing
14166 * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
14172 * @param {string} [string=''] The string to deburr.
14173 * @returns {string} Returns the deburred string.
14176 * _.deburr('déjà vu');
14179 function deburr(string) {
14180 string = toString(string);
14181 return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
14185 * Checks if `string` ends with the given target string.
14191 * @param {string} [string=''] The string to inspect.
14192 * @param {string} [target] The string to search for.
14193 * @param {number} [position=string.length] The position to search up to.
14194 * @returns {boolean} Returns `true` if `string` ends with `target`,
14198 * _.endsWith('abc', 'c');
14201 * _.endsWith('abc', 'b');
14204 * _.endsWith('abc', 'b', 2);
14207 function endsWith(string, target, position) {
14208 string = toString(string);
14209 target = baseToString(target);
14211 var length = string.length;
14212 position = position === undefined
14214 : baseClamp(toInteger(position), 0, length);
14216 var end = position;
14217 position -= target.length;
14218 return position >= 0 && string.slice(position, end) == target;
14222 * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
14223 * corresponding HTML entities.
14225 * **Note:** No other characters are escaped. To escape additional
14226 * characters use a third-party library like [_he_](https://mths.be/he).
14228 * Though the ">" character is escaped for symmetry, characters like
14229 * ">" and "/" don't need escaping in HTML and have no special meaning
14230 * unless they're part of a tag or unquoted attribute value. See
14231 * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
14232 * (under "semi-related fun fact") for more details.
14234 * When working with HTML you should always
14235 * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
14242 * @param {string} [string=''] The string to escape.
14243 * @returns {string} Returns the escaped string.
14246 * _.escape('fred, barney, & pebbles');
14247 * // => 'fred, barney, & pebbles'
14249 function escape(string) {
14250 string = toString(string);
14251 return (string && reHasUnescapedHtml.test(string))
14252 ? string.replace(reUnescapedHtml, escapeHtmlChar)
14257 * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
14258 * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
14264 * @param {string} [string=''] The string to escape.
14265 * @returns {string} Returns the escaped string.
14268 * _.escapeRegExp('[lodash](https://lodash.com/)');
14269 * // => '\[lodash\]\(https://lodash\.com/\)'
14271 function escapeRegExp(string) {
14272 string = toString(string);
14273 return (string && reHasRegExpChar.test(string))
14274 ? string.replace(reRegExpChar, '\\$&')
14279 * Converts `string` to
14280 * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
14286 * @param {string} [string=''] The string to convert.
14287 * @returns {string} Returns the kebab cased string.
14290 * _.kebabCase('Foo Bar');
14293 * _.kebabCase('fooBar');
14296 * _.kebabCase('__FOO_BAR__');
14299 var kebabCase = createCompounder(function(result, word, index) {
14300 return result + (index ? '-' : '') + word.toLowerCase();
14304 * Converts `string`, as space separated words, to lower case.
14310 * @param {string} [string=''] The string to convert.
14311 * @returns {string} Returns the lower cased string.
14314 * _.lowerCase('--Foo-Bar--');
14317 * _.lowerCase('fooBar');
14320 * _.lowerCase('__FOO_BAR__');
14323 var lowerCase = createCompounder(function(result, word, index) {
14324 return result + (index ? ' ' : '') + word.toLowerCase();
14328 * Converts the first character of `string` to lower case.
14334 * @param {string} [string=''] The string to convert.
14335 * @returns {string} Returns the converted string.
14338 * _.lowerFirst('Fred');
14341 * _.lowerFirst('FRED');
14344 var lowerFirst = createCaseFirst('toLowerCase');
14347 * Pads `string` on the left and right sides if it's shorter than `length`.
14348 * Padding characters are truncated if they can't be evenly divided by `length`.
14354 * @param {string} [string=''] The string to pad.
14355 * @param {number} [length=0] The padding length.
14356 * @param {string} [chars=' '] The string used as padding.
14357 * @returns {string} Returns the padded string.
14363 * _.pad('abc', 8, '_-');
14369 function pad(string, length, chars) {
14370 string = toString(string);
14371 length = toInteger(length);
14373 var strLength = length ? stringSize(string) : 0;
14374 if (!length || strLength >= length) {
14377 var mid = (length - strLength) / 2;
14379 createPadding(nativeFloor(mid), chars) +
14381 createPadding(nativeCeil(mid), chars)
14386 * Pads `string` on the right side if it's shorter than `length`. Padding
14387 * characters are truncated if they exceed `length`.
14393 * @param {string} [string=''] The string to pad.
14394 * @param {number} [length=0] The padding length.
14395 * @param {string} [chars=' '] The string used as padding.
14396 * @returns {string} Returns the padded string.
14399 * _.padEnd('abc', 6);
14402 * _.padEnd('abc', 6, '_-');
14405 * _.padEnd('abc', 3);
14408 function padEnd(string, length, chars) {
14409 string = toString(string);
14410 length = toInteger(length);
14412 var strLength = length ? stringSize(string) : 0;
14413 return (length && strLength < length)
14414 ? (string + createPadding(length - strLength, chars))
14419 * Pads `string` on the left side if it's shorter than `length`. Padding
14420 * characters are truncated if they exceed `length`.
14426 * @param {string} [string=''] The string to pad.
14427 * @param {number} [length=0] The padding length.
14428 * @param {string} [chars=' '] The string used as padding.
14429 * @returns {string} Returns the padded string.
14432 * _.padStart('abc', 6);
14435 * _.padStart('abc', 6, '_-');
14438 * _.padStart('abc', 3);
14441 function padStart(string, length, chars) {
14442 string = toString(string);
14443 length = toInteger(length);
14445 var strLength = length ? stringSize(string) : 0;
14446 return (length && strLength < length)
14447 ? (createPadding(length - strLength, chars) + string)
14452 * Converts `string` to an integer of the specified radix. If `radix` is
14453 * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
14454 * hexadecimal, in which case a `radix` of `16` is used.
14456 * **Note:** This method aligns with the
14457 * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
14463 * @param {string} string The string to convert.
14464 * @param {number} [radix=10] The radix to interpret `value` by.
14465 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14466 * @returns {number} Returns the converted integer.
14469 * _.parseInt('08');
14472 * _.map(['6', '08', '10'], _.parseInt);
14475 function parseInt(string, radix, guard) {
14476 if (guard || radix == null) {
14478 } else if (radix) {
14481 return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
14485 * Repeats the given string `n` times.
14491 * @param {string} [string=''] The string to repeat.
14492 * @param {number} [n=1] The number of times to repeat the string.
14493 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14494 * @returns {string} Returns the repeated string.
14497 * _.repeat('*', 3);
14500 * _.repeat('abc', 2);
14503 * _.repeat('abc', 0);
14506 function repeat(string, n, guard) {
14507 if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
14512 return baseRepeat(toString(string), n);
14516 * Replaces matches for `pattern` in `string` with `replacement`.
14518 * **Note:** This method is based on
14519 * [`String#replace`](https://mdn.io/String/replace).
14525 * @param {string} [string=''] The string to modify.
14526 * @param {RegExp|string} pattern The pattern to replace.
14527 * @param {Function|string} replacement The match replacement.
14528 * @returns {string} Returns the modified string.
14531 * _.replace('Hi Fred', 'Fred', 'Barney');
14532 * // => 'Hi Barney'
14534 function replace() {
14535 var args = arguments,
14536 string = toString(args[0]);
14538 return args.length < 3 ? string : string.replace(args[1], args[2]);
14542 * Converts `string` to
14543 * [snake case](https://en.wikipedia.org/wiki/Snake_case).
14549 * @param {string} [string=''] The string to convert.
14550 * @returns {string} Returns the snake cased string.
14553 * _.snakeCase('Foo Bar');
14556 * _.snakeCase('fooBar');
14559 * _.snakeCase('--FOO-BAR--');
14562 var snakeCase = createCompounder(function(result, word, index) {
14563 return result + (index ? '_' : '') + word.toLowerCase();
14567 * Splits `string` by `separator`.
14569 * **Note:** This method is based on
14570 * [`String#split`](https://mdn.io/String/split).
14576 * @param {string} [string=''] The string to split.
14577 * @param {RegExp|string} separator The separator pattern to split by.
14578 * @param {number} [limit] The length to truncate results to.
14579 * @returns {Array} Returns the string segments.
14582 * _.split('a-b-c', '-', 2);
14585 function split(string, separator, limit) {
14586 if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
14587 separator = limit = undefined;
14589 limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
14593 string = toString(string);
14595 typeof separator == 'string' ||
14596 (separator != null && !isRegExp(separator))
14598 separator = baseToString(separator);
14599 if (!separator && hasUnicode(string)) {
14600 return castSlice(stringToArray(string), 0, limit);
14603 return string.split(separator, limit);
14607 * Converts `string` to
14608 * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
14614 * @param {string} [string=''] The string to convert.
14615 * @returns {string} Returns the start cased string.
14618 * _.startCase('--foo-bar--');
14621 * _.startCase('fooBar');
14624 * _.startCase('__FOO_BAR__');
14627 var startCase = createCompounder(function(result, word, index) {
14628 return result + (index ? ' ' : '') + upperFirst(word);
14632 * Checks if `string` starts with the given target string.
14638 * @param {string} [string=''] The string to inspect.
14639 * @param {string} [target] The string to search for.
14640 * @param {number} [position=0] The position to search from.
14641 * @returns {boolean} Returns `true` if `string` starts with `target`,
14645 * _.startsWith('abc', 'a');
14648 * _.startsWith('abc', 'b');
14651 * _.startsWith('abc', 'b', 1);
14654 function startsWith(string, target, position) {
14655 string = toString(string);
14656 position = position == null
14658 : baseClamp(toInteger(position), 0, string.length);
14660 target = baseToString(target);
14661 return string.slice(position, position + target.length) == target;
14665 * Creates a compiled template function that can interpolate data properties
14666 * in "interpolate" delimiters, HTML-escape interpolated data properties in
14667 * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
14668 * properties may be accessed as free variables in the template. If a setting
14669 * object is given, it takes precedence over `_.templateSettings` values.
14671 * **Note:** In the development build `_.template` utilizes
14672 * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
14673 * for easier debugging.
14675 * For more information on precompiling templates see
14676 * [lodash's custom builds documentation](https://lodash.com/custom-builds).
14678 * For more information on Chrome extension sandboxes see
14679 * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
14685 * @param {string} [string=''] The template string.
14686 * @param {Object} [options={}] The options object.
14687 * @param {RegExp} [options.escape=_.templateSettings.escape]
14688 * The HTML "escape" delimiter.
14689 * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
14690 * The "evaluate" delimiter.
14691 * @param {Object} [options.imports=_.templateSettings.imports]
14692 * An object to import into the template as free variables.
14693 * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
14694 * The "interpolate" delimiter.
14695 * @param {string} [options.sourceURL='lodash.templateSources[n]']
14696 * The sourceURL of the compiled template.
14697 * @param {string} [options.variable='obj']
14698 * The data object variable name.
14699 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14700 * @returns {Function} Returns the compiled template function.
14703 * // Use the "interpolate" delimiter to create a compiled template.
14704 * var compiled = _.template('hello <%= user %>!');
14705 * compiled({ 'user': 'fred' });
14706 * // => 'hello fred!'
14708 * // Use the HTML "escape" delimiter to escape data property values.
14709 * var compiled = _.template('<b><%- value %></b>');
14710 * compiled({ 'value': '<script>' });
14711 * // => '<b><script></b>'
14713 * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
14714 * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
14715 * compiled({ 'users': ['fred', 'barney'] });
14716 * // => '<li>fred</li><li>barney</li>'
14718 * // Use the internal `print` function in "evaluate" delimiters.
14719 * var compiled = _.template('<% print("hello " + user); %>!');
14720 * compiled({ 'user': 'barney' });
14721 * // => 'hello barney!'
14723 * // Use the ES template literal delimiter as an "interpolate" delimiter.
14724 * // Disable support by replacing the "interpolate" delimiter.
14725 * var compiled = _.template('hello ${ user }!');
14726 * compiled({ 'user': 'pebbles' });
14727 * // => 'hello pebbles!'
14729 * // Use backslashes to treat delimiters as plain text.
14730 * var compiled = _.template('<%= "\\<%- value %\\>" %>');
14731 * compiled({ 'value': 'ignored' });
14732 * // => '<%- value %>'
14734 * // Use the `imports` option to import `jQuery` as `jq`.
14735 * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
14736 * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
14737 * compiled({ 'users': ['fred', 'barney'] });
14738 * // => '<li>fred</li><li>barney</li>'
14740 * // Use the `sourceURL` option to specify a custom sourceURL for the template.
14741 * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
14743 * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
14745 * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
14746 * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
14748 * // => function(data) {
14749 * // var __t, __p = '';
14750 * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
14754 * // Use custom template delimiters.
14755 * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
14756 * var compiled = _.template('hello {{ user }}!');
14757 * compiled({ 'user': 'mustache' });
14758 * // => 'hello mustache!'
14760 * // Use the `source` property to inline compiled templates for meaningful
14761 * // line numbers in error messages and stack traces.
14762 * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
14764 * "main": ' + _.template(mainText).source + '\
14768 function template(string, options, guard) {
14769 // Based on John Resig's `tmpl` implementation
14770 // (http://ejohn.org/blog/javascript-micro-templating/)
14771 // and Laura Doktorova's doT.js (https://github.com/olado/doT).
14772 var settings = lodash.templateSettings;
14774 if (guard && isIterateeCall(string, options, guard)) {
14775 options = undefined;
14777 string = toString(string);
14778 options = assignInWith({}, options, settings, customDefaultsAssignIn);
14780 var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
14781 importsKeys = keys(imports),
14782 importsValues = baseValues(imports, importsKeys);
14787 interpolate = options.interpolate || reNoMatch,
14788 source = "__p += '";
14790 // Compile the regexp to match each delimiter.
14791 var reDelimiters = RegExp(
14792 (options.escape || reNoMatch).source + '|' +
14793 interpolate.source + '|' +
14794 (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
14795 (options.evaluate || reNoMatch).source + '|$'
14798 // Use a sourceURL for easier debugging.
14799 var sourceURL = '//# sourceURL=' +
14800 ('sourceURL' in options
14801 ? options.sourceURL
14802 : ('lodash.templateSources[' + (++templateCounter) + ']')
14805 string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
14806 interpolateValue || (interpolateValue = esTemplateValue);
14808 // Escape characters that can't be included in string literals.
14809 source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
14811 // Replace delimiters with snippets.
14814 source += "' +\n__e(" + escapeValue + ") +\n'";
14816 if (evaluateValue) {
14817 isEvaluating = true;
14818 source += "';\n" + evaluateValue + ";\n__p += '";
14820 if (interpolateValue) {
14821 source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
14823 index = offset + match.length;
14825 // The JS engine embedded in Adobe products needs `match` returned in
14826 // order to produce the correct `offset` value.
14832 // If `variable` is not specified wrap a with-statement around the generated
14833 // code to add the data object to the top of the scope chain.
14834 var variable = options.variable;
14836 source = 'with (obj) {\n' + source + '\n}\n';
14838 // Cleanup code by stripping empty strings.
14839 source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
14840 .replace(reEmptyStringMiddle, '$1')
14841 .replace(reEmptyStringTrailing, '$1;');
14843 // Frame code as the function body.
14844 source = 'function(' + (variable || 'obj') + ') {\n' +
14847 : 'obj || (obj = {});\n'
14849 "var __t, __p = ''" +
14851 ? ', __e = _.escape'
14855 ? ', __j = Array.prototype.join;\n' +
14856 "function print() { __p += __j.call(arguments, '') }\n"
14862 var result = attempt(function() {
14863 return Function(importsKeys, sourceURL + 'return ' + source)
14864 .apply(undefined, importsValues);
14867 // Provide the compiled function's source by its `toString` method or
14868 // the `source` property as a convenience for inlining compiled templates.
14869 result.source = source;
14870 if (isError(result)) {
14877 * Converts `string`, as a whole, to lower case just like
14878 * [String#toLowerCase](https://mdn.io/toLowerCase).
14884 * @param {string} [string=''] The string to convert.
14885 * @returns {string} Returns the lower cased string.
14888 * _.toLower('--Foo-Bar--');
14889 * // => '--foo-bar--'
14891 * _.toLower('fooBar');
14894 * _.toLower('__FOO_BAR__');
14895 * // => '__foo_bar__'
14897 function toLower(value) {
14898 return toString(value).toLowerCase();
14902 * Converts `string`, as a whole, to upper case just like
14903 * [String#toUpperCase](https://mdn.io/toUpperCase).
14909 * @param {string} [string=''] The string to convert.
14910 * @returns {string} Returns the upper cased string.
14913 * _.toUpper('--foo-bar--');
14914 * // => '--FOO-BAR--'
14916 * _.toUpper('fooBar');
14919 * _.toUpper('__foo_bar__');
14920 * // => '__FOO_BAR__'
14922 function toUpper(value) {
14923 return toString(value).toUpperCase();
14927 * Removes leading and trailing whitespace or specified characters from `string`.
14933 * @param {string} [string=''] The string to trim.
14934 * @param {string} [chars=whitespace] The characters to trim.
14935 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14936 * @returns {string} Returns the trimmed string.
14942 * _.trim('-_-abc-_-', '_-');
14945 * _.map([' foo ', ' bar '], _.trim);
14946 * // => ['foo', 'bar']
14948 function trim(string, chars, guard) {
14949 string = toString(string);
14950 if (string && (guard || chars === undefined)) {
14951 return string.replace(reTrim, '');
14953 if (!string || !(chars = baseToString(chars))) {
14956 var strSymbols = stringToArray(string),
14957 chrSymbols = stringToArray(chars),
14958 start = charsStartIndex(strSymbols, chrSymbols),
14959 end = charsEndIndex(strSymbols, chrSymbols) + 1;
14961 return castSlice(strSymbols, start, end).join('');
14965 * Removes trailing whitespace or specified characters from `string`.
14971 * @param {string} [string=''] The string to trim.
14972 * @param {string} [chars=whitespace] The characters to trim.
14973 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14974 * @returns {string} Returns the trimmed string.
14977 * _.trimEnd(' abc ');
14980 * _.trimEnd('-_-abc-_-', '_-');
14983 function trimEnd(string, chars, guard) {
14984 string = toString(string);
14985 if (string && (guard || chars === undefined)) {
14986 return string.replace(reTrimEnd, '');
14988 if (!string || !(chars = baseToString(chars))) {
14991 var strSymbols = stringToArray(string),
14992 end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
14994 return castSlice(strSymbols, 0, end).join('');
14998 * Removes leading whitespace or specified characters from `string`.
15004 * @param {string} [string=''] The string to trim.
15005 * @param {string} [chars=whitespace] The characters to trim.
15006 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15007 * @returns {string} Returns the trimmed string.
15010 * _.trimStart(' abc ');
15013 * _.trimStart('-_-abc-_-', '_-');
15016 function trimStart(string, chars, guard) {
15017 string = toString(string);
15018 if (string && (guard || chars === undefined)) {
15019 return string.replace(reTrimStart, '');
15021 if (!string || !(chars = baseToString(chars))) {
15024 var strSymbols = stringToArray(string),
15025 start = charsStartIndex(strSymbols, stringToArray(chars));
15027 return castSlice(strSymbols, start).join('');
15031 * Truncates `string` if it's longer than the given maximum string length.
15032 * The last characters of the truncated string are replaced with the omission
15033 * string which defaults to "...".
15039 * @param {string} [string=''] The string to truncate.
15040 * @param {Object} [options={}] The options object.
15041 * @param {number} [options.length=30] The maximum string length.
15042 * @param {string} [options.omission='...'] The string to indicate text is omitted.
15043 * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
15044 * @returns {string} Returns the truncated string.
15047 * _.truncate('hi-diddly-ho there, neighborino');
15048 * // => 'hi-diddly-ho there, neighbo...'
15050 * _.truncate('hi-diddly-ho there, neighborino', {
15054 * // => 'hi-diddly-ho there,...'
15056 * _.truncate('hi-diddly-ho there, neighborino', {
15058 * 'separator': /,? +/
15060 * // => 'hi-diddly-ho there...'
15062 * _.truncate('hi-diddly-ho there, neighborino', {
15063 * 'omission': ' [...]'
15065 * // => 'hi-diddly-ho there, neig [...]'
15067 function truncate(string, options) {
15068 var length = DEFAULT_TRUNC_LENGTH,
15069 omission = DEFAULT_TRUNC_OMISSION;
15071 if (isObject(options)) {
15072 var separator = 'separator' in options ? options.separator : separator;
15073 length = 'length' in options ? toInteger(options.length) : length;
15074 omission = 'omission' in options ? baseToString(options.omission) : omission;
15076 string = toString(string);
15078 var strLength = string.length;
15079 if (hasUnicode(string)) {
15080 var strSymbols = stringToArray(string);
15081 strLength = strSymbols.length;
15083 if (length >= strLength) {
15086 var end = length - stringSize(omission);
15090 var result = strSymbols
15091 ? castSlice(strSymbols, 0, end).join('')
15092 : string.slice(0, end);
15094 if (separator === undefined) {
15095 return result + omission;
15098 end += (result.length - end);
15100 if (isRegExp(separator)) {
15101 if (string.slice(end).search(separator)) {
15103 substring = result;
15105 if (!separator.global) {
15106 separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
15108 separator.lastIndex = 0;
15109 while ((match = separator.exec(substring))) {
15110 var newEnd = match.index;
15112 result = result.slice(0, newEnd === undefined ? end : newEnd);
15114 } else if (string.indexOf(baseToString(separator), end) != end) {
15115 var index = result.lastIndexOf(separator);
15117 result = result.slice(0, index);
15120 return result + omission;
15124 * The inverse of `_.escape`; this method converts the HTML entities
15125 * `&`, `<`, `>`, `"`, and `'` in `string` to
15126 * their corresponding characters.
15128 * **Note:** No other HTML entities are unescaped. To unescape additional
15129 * HTML entities use a third-party library like [_he_](https://mths.be/he).
15135 * @param {string} [string=''] The string to unescape.
15136 * @returns {string} Returns the unescaped string.
15139 * _.unescape('fred, barney, & pebbles');
15140 * // => 'fred, barney, & pebbles'
15142 function unescape(string) {
15143 string = toString(string);
15144 return (string && reHasEscapedHtml.test(string))
15145 ? string.replace(reEscapedHtml, unescapeHtmlChar)
15150 * Converts `string`, as space separated words, to upper case.
15156 * @param {string} [string=''] The string to convert.
15157 * @returns {string} Returns the upper cased string.
15160 * _.upperCase('--foo-bar');
15163 * _.upperCase('fooBar');
15166 * _.upperCase('__foo_bar__');
15169 var upperCase = createCompounder(function(result, word, index) {
15170 return result + (index ? ' ' : '') + word.toUpperCase();
15174 * Converts the first character of `string` to upper case.
15180 * @param {string} [string=''] The string to convert.
15181 * @returns {string} Returns the converted string.
15184 * _.upperFirst('fred');
15187 * _.upperFirst('FRED');
15190 var upperFirst = createCaseFirst('toUpperCase');
15193 * Splits `string` into an array of its words.
15199 * @param {string} [string=''] The string to inspect.
15200 * @param {RegExp|string} [pattern] The pattern to match words.
15201 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15202 * @returns {Array} Returns the words of `string`.
15205 * _.words('fred, barney, & pebbles');
15206 * // => ['fred', 'barney', 'pebbles']
15208 * _.words('fred, barney, & pebbles', /[^, ]+/g);
15209 * // => ['fred', 'barney', '&', 'pebbles']
15211 function words(string, pattern, guard) {
15212 string = toString(string);
15213 pattern = guard ? undefined : pattern;
15215 if (pattern === undefined) {
15216 return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
15218 return string.match(pattern) || [];
15221 /*------------------------------------------------------------------------*/
15224 * Attempts to invoke `func`, returning either the result or the caught error
15225 * object. Any additional arguments are provided to `func` when it's invoked.
15231 * @param {Function} func The function to attempt.
15232 * @param {...*} [args] The arguments to invoke `func` with.
15233 * @returns {*} Returns the `func` result or error object.
15236 * // Avoid throwing errors for invalid selectors.
15237 * var elements = _.attempt(function(selector) {
15238 * return document.querySelectorAll(selector);
15241 * if (_.isError(elements)) {
15245 var attempt = baseRest(function(func, args) {
15247 return apply(func, undefined, args);
15249 return isError(e) ? e : new Error(e);
15254 * Binds methods of an object to the object itself, overwriting the existing
15257 * **Note:** This method doesn't set the "length" property of bound functions.
15263 * @param {Object} object The object to bind and assign the bound methods to.
15264 * @param {...(string|string[])} methodNames The object method names to bind.
15265 * @returns {Object} Returns `object`.
15270 * 'click': function() {
15271 * console.log('clicked ' + this.label);
15275 * _.bindAll(view, ['click']);
15276 * jQuery(element).on('click', view.click);
15277 * // => Logs 'clicked docs' when clicked.
15279 var bindAll = flatRest(function(object, methodNames) {
15280 arrayEach(methodNames, function(key) {
15282 baseAssignValue(object, key, bind(object[key], object));
15288 * Creates a function that iterates over `pairs` and invokes the corresponding
15289 * function of the first predicate to return truthy. The predicate-function
15290 * pairs are invoked with the `this` binding and arguments of the created
15297 * @param {Array} pairs The predicate-function pairs.
15298 * @returns {Function} Returns the new composite function.
15301 * var func = _.cond([
15302 * [_.matches({ 'a': 1 }), _.constant('matches A')],
15303 * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
15304 * [_.stubTrue, _.constant('no match')]
15307 * func({ 'a': 1, 'b': 2 });
15308 * // => 'matches A'
15310 * func({ 'a': 0, 'b': 1 });
15311 * // => 'matches B'
15313 * func({ 'a': '1', 'b': '2' });
15316 function cond(pairs) {
15317 var length = pairs == null ? 0 : pairs.length,
15318 toIteratee = getIteratee();
15320 pairs = !length ? [] : arrayMap(pairs, function(pair) {
15321 if (typeof pair[1] != 'function') {
15322 throw new TypeError(FUNC_ERROR_TEXT);
15324 return [toIteratee(pair[0]), pair[1]];
15327 return baseRest(function(args) {
15329 while (++index < length) {
15330 var pair = pairs[index];
15331 if (apply(pair[0], this, args)) {
15332 return apply(pair[1], this, args);
15339 * Creates a function that invokes the predicate properties of `source` with
15340 * the corresponding property values of a given object, returning `true` if
15341 * all predicates return truthy, else `false`.
15343 * **Note:** The created function is equivalent to `_.conformsTo` with
15344 * `source` partially applied.
15350 * @param {Object} source The object of property predicates to conform to.
15351 * @returns {Function} Returns the new spec function.
15355 * { 'a': 2, 'b': 1 },
15356 * { 'a': 1, 'b': 2 }
15359 * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
15360 * // => [{ 'a': 1, 'b': 2 }]
15362 function conforms(source) {
15363 return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
15367 * Creates a function that returns `value`.
15373 * @param {*} value The value to return from the new function.
15374 * @returns {Function} Returns the new constant function.
15377 * var objects = _.times(2, _.constant({ 'a': 1 }));
15379 * console.log(objects);
15380 * // => [{ 'a': 1 }, { 'a': 1 }]
15382 * console.log(objects[0] === objects[1]);
15385 function constant(value) {
15386 return function() {
15392 * Checks `value` to determine whether a default value should be returned in
15393 * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
15400 * @param {*} value The value to check.
15401 * @param {*} defaultValue The default value.
15402 * @returns {*} Returns the resolved value.
15405 * _.defaultTo(1, 10);
15408 * _.defaultTo(undefined, 10);
15411 function defaultTo(value, defaultValue) {
15412 return (value == null || value !== value) ? defaultValue : value;
15416 * Creates a function that returns the result of invoking the given functions
15417 * with the `this` binding of the created function, where each successive
15418 * invocation is supplied the return value of the previous.
15424 * @param {...(Function|Function[])} [funcs] The functions to invoke.
15425 * @returns {Function} Returns the new composite function.
15429 * function square(n) {
15433 * var addSquare = _.flow([_.add, square]);
15437 var flow = createFlow();
15440 * This method is like `_.flow` except that it creates a function that
15441 * invokes the given functions from right to left.
15447 * @param {...(Function|Function[])} [funcs] The functions to invoke.
15448 * @returns {Function} Returns the new composite function.
15452 * function square(n) {
15456 * var addSquare = _.flowRight([square, _.add]);
15460 var flowRight = createFlow(true);
15463 * This method returns the first argument it receives.
15469 * @param {*} value Any value.
15470 * @returns {*} Returns `value`.
15473 * var object = { 'a': 1 };
15475 * console.log(_.identity(object) === object);
15478 function identity(value) {
15483 * Creates a function that invokes `func` with the arguments of the created
15484 * function. If `func` is a property name, the created function returns the
15485 * property value for a given element. If `func` is an array or object, the
15486 * created function returns `true` for elements that contain the equivalent
15487 * source properties, otherwise it returns `false`.
15493 * @param {*} [func=_.identity] The value to convert to a callback.
15494 * @returns {Function} Returns the callback.
15498 * { 'user': 'barney', 'age': 36, 'active': true },
15499 * { 'user': 'fred', 'age': 40, 'active': false }
15502 * // The `_.matches` iteratee shorthand.
15503 * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
15504 * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
15506 * // The `_.matchesProperty` iteratee shorthand.
15507 * _.filter(users, _.iteratee(['user', 'fred']));
15508 * // => [{ 'user': 'fred', 'age': 40 }]
15510 * // The `_.property` iteratee shorthand.
15511 * _.map(users, _.iteratee('user'));
15512 * // => ['barney', 'fred']
15514 * // Create custom iteratee shorthands.
15515 * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
15516 * return !_.isRegExp(func) ? iteratee(func) : function(string) {
15517 * return func.test(string);
15521 * _.filter(['abc', 'def'], /ef/);
15524 function iteratee(func) {
15525 return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
15529 * Creates a function that performs a partial deep comparison between a given
15530 * object and `source`, returning `true` if the given object has equivalent
15531 * property values, else `false`.
15533 * **Note:** The created function is equivalent to `_.isMatch` with `source`
15534 * partially applied.
15536 * Partial comparisons will match empty array and empty object `source`
15537 * values against any array or object value, respectively. See `_.isEqual`
15538 * for a list of supported value comparisons.
15544 * @param {Object} source The object of property values to match.
15545 * @returns {Function} Returns the new spec function.
15549 * { 'a': 1, 'b': 2, 'c': 3 },
15550 * { 'a': 4, 'b': 5, 'c': 6 }
15553 * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
15554 * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
15556 function matches(source) {
15557 return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
15561 * Creates a function that performs a partial deep comparison between the
15562 * value at `path` of a given object to `srcValue`, returning `true` if the
15563 * object value is equivalent, else `false`.
15565 * **Note:** Partial comparisons will match empty array and empty object
15566 * `srcValue` values against any array or object value, respectively. See
15567 * `_.isEqual` for a list of supported value comparisons.
15573 * @param {Array|string} path The path of the property to get.
15574 * @param {*} srcValue The value to match.
15575 * @returns {Function} Returns the new spec function.
15579 * { 'a': 1, 'b': 2, 'c': 3 },
15580 * { 'a': 4, 'b': 5, 'c': 6 }
15583 * _.find(objects, _.matchesProperty('a', 4));
15584 * // => { 'a': 4, 'b': 5, 'c': 6 }
15586 function matchesProperty(path, srcValue) {
15587 return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
15591 * Creates a function that invokes the method at `path` of a given object.
15592 * Any additional arguments are provided to the invoked method.
15598 * @param {Array|string} path The path of the method to invoke.
15599 * @param {...*} [args] The arguments to invoke the method with.
15600 * @returns {Function} Returns the new invoker function.
15604 * { 'a': { 'b': _.constant(2) } },
15605 * { 'a': { 'b': _.constant(1) } }
15608 * _.map(objects, _.method('a.b'));
15611 * _.map(objects, _.method(['a', 'b']));
15614 var method = baseRest(function(path, args) {
15615 return function(object) {
15616 return baseInvoke(object, path, args);
15621 * The opposite of `_.method`; this method creates a function that invokes
15622 * the method at a given path of `object`. Any additional arguments are
15623 * provided to the invoked method.
15629 * @param {Object} object The object to query.
15630 * @param {...*} [args] The arguments to invoke the method with.
15631 * @returns {Function} Returns the new invoker function.
15634 * var array = _.times(3, _.constant),
15635 * object = { 'a': array, 'b': array, 'c': array };
15637 * _.map(['a[2]', 'c[0]'], _.methodOf(object));
15640 * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
15643 var methodOf = baseRest(function(object, args) {
15644 return function(path) {
15645 return baseInvoke(object, path, args);
15650 * Adds all own enumerable string keyed function properties of a source
15651 * object to the destination object. If `object` is a function, then methods
15652 * are added to its prototype as well.
15654 * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
15655 * avoid conflicts caused by modifying the original.
15661 * @param {Function|Object} [object=lodash] The destination object.
15662 * @param {Object} source The object of functions to add.
15663 * @param {Object} [options={}] The options object.
15664 * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
15665 * @returns {Function|Object} Returns `object`.
15668 * function vowels(string) {
15669 * return _.filter(string, function(v) {
15670 * return /[aeiou]/i.test(v);
15674 * _.mixin({ 'vowels': vowels });
15675 * _.vowels('fred');
15678 * _('fred').vowels().value();
15681 * _.mixin({ 'vowels': vowels }, { 'chain': false });
15682 * _('fred').vowels();
15685 function mixin(object, source, options) {
15686 var props = keys(source),
15687 methodNames = baseFunctions(source, props);
15689 if (options == null &&
15690 !(isObject(source) && (methodNames.length || !props.length))) {
15694 methodNames = baseFunctions(source, keys(source));
15696 var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
15697 isFunc = isFunction(object);
15699 arrayEach(methodNames, function(methodName) {
15700 var func = source[methodName];
15701 object[methodName] = func;
15703 object.prototype[methodName] = function() {
15704 var chainAll = this.__chain__;
15705 if (chain || chainAll) {
15706 var result = object(this.__wrapped__),
15707 actions = result.__actions__ = copyArray(this.__actions__);
15709 actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
15710 result.__chain__ = chainAll;
15713 return func.apply(object, arrayPush([this.value()], arguments));
15722 * Reverts the `_` variable to its previous value and returns a reference to
15723 * the `lodash` function.
15729 * @returns {Function} Returns the `lodash` function.
15732 * var lodash = _.noConflict();
15734 function noConflict() {
15735 if (root._ === this) {
15742 * This method returns `undefined`.
15750 * _.times(2, _.noop);
15751 * // => [undefined, undefined]
15754 // No operation performed.
15758 * Creates a function that gets the argument at index `n`. If `n` is negative,
15759 * the nth argument from the end is returned.
15765 * @param {number} [n=0] The index of the argument to return.
15766 * @returns {Function} Returns the new pass-thru function.
15769 * var func = _.nthArg(1);
15770 * func('a', 'b', 'c', 'd');
15773 * var func = _.nthArg(-2);
15774 * func('a', 'b', 'c', 'd');
15777 function nthArg(n) {
15779 return baseRest(function(args) {
15780 return baseNth(args, n);
15785 * Creates a function that invokes `iteratees` with the arguments it receives
15786 * and returns their results.
15792 * @param {...(Function|Function[])} [iteratees=[_.identity]]
15793 * The iteratees to invoke.
15794 * @returns {Function} Returns the new function.
15797 * var func = _.over([Math.max, Math.min]);
15799 * func(1, 2, 3, 4);
15802 var over = createOver(arrayMap);
15805 * Creates a function that checks if **all** of the `predicates` return
15806 * truthy when invoked with the arguments it receives.
15812 * @param {...(Function|Function[])} [predicates=[_.identity]]
15813 * The predicates to check.
15814 * @returns {Function} Returns the new function.
15817 * var func = _.overEvery([Boolean, isFinite]);
15828 var overEvery = createOver(arrayEvery);
15831 * Creates a function that checks if **any** of the `predicates` return
15832 * truthy when invoked with the arguments it receives.
15838 * @param {...(Function|Function[])} [predicates=[_.identity]]
15839 * The predicates to check.
15840 * @returns {Function} Returns the new function.
15843 * var func = _.overSome([Boolean, isFinite]);
15854 var overSome = createOver(arraySome);
15857 * Creates a function that returns the value at `path` of a given object.
15863 * @param {Array|string} path The path of the property to get.
15864 * @returns {Function} Returns the new accessor function.
15868 * { 'a': { 'b': 2 } },
15869 * { 'a': { 'b': 1 } }
15872 * _.map(objects, _.property('a.b'));
15875 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
15878 function property(path) {
15879 return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
15883 * The opposite of `_.property`; this method creates a function that returns
15884 * the value at a given path of `object`.
15890 * @param {Object} object The object to query.
15891 * @returns {Function} Returns the new accessor function.
15894 * var array = [0, 1, 2],
15895 * object = { 'a': array, 'b': array, 'c': array };
15897 * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
15900 * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
15903 function propertyOf(object) {
15904 return function(path) {
15905 return object == null ? undefined : baseGet(object, path);
15910 * Creates an array of numbers (positive and/or negative) progressing from
15911 * `start` up to, but not including, `end`. A step of `-1` is used if a negative
15912 * `start` is specified without an `end` or `step`. If `end` is not specified,
15913 * it's set to `start` with `start` then set to `0`.
15915 * **Note:** JavaScript follows the IEEE-754 standard for resolving
15916 * floating-point values which can produce unexpected results.
15922 * @param {number} [start=0] The start of the range.
15923 * @param {number} end The end of the range.
15924 * @param {number} [step=1] The value to increment or decrement by.
15925 * @returns {Array} Returns the range of numbers.
15926 * @see _.inRange, _.rangeRight
15930 * // => [0, 1, 2, 3]
15933 * // => [0, -1, -2, -3]
15936 * // => [1, 2, 3, 4]
15938 * _.range(0, 20, 5);
15939 * // => [0, 5, 10, 15]
15941 * _.range(0, -4, -1);
15942 * // => [0, -1, -2, -3]
15944 * _.range(1, 4, 0);
15950 var range = createRange();
15953 * This method is like `_.range` except that it populates values in
15954 * descending order.
15960 * @param {number} [start=0] The start of the range.
15961 * @param {number} end The end of the range.
15962 * @param {number} [step=1] The value to increment or decrement by.
15963 * @returns {Array} Returns the range of numbers.
15964 * @see _.inRange, _.range
15968 * // => [3, 2, 1, 0]
15970 * _.rangeRight(-4);
15971 * // => [-3, -2, -1, 0]
15973 * _.rangeRight(1, 5);
15974 * // => [4, 3, 2, 1]
15976 * _.rangeRight(0, 20, 5);
15977 * // => [15, 10, 5, 0]
15979 * _.rangeRight(0, -4, -1);
15980 * // => [-3, -2, -1, 0]
15982 * _.rangeRight(1, 4, 0);
15988 var rangeRight = createRange(true);
15991 * This method returns a new empty array.
15997 * @returns {Array} Returns the new empty array.
16000 * var arrays = _.times(2, _.stubArray);
16002 * console.log(arrays);
16005 * console.log(arrays[0] === arrays[1]);
16008 function stubArray() {
16013 * This method returns `false`.
16019 * @returns {boolean} Returns `false`.
16022 * _.times(2, _.stubFalse);
16023 * // => [false, false]
16025 function stubFalse() {
16030 * This method returns a new empty object.
16036 * @returns {Object} Returns the new empty object.
16039 * var objects = _.times(2, _.stubObject);
16041 * console.log(objects);
16044 * console.log(objects[0] === objects[1]);
16047 function stubObject() {
16052 * This method returns an empty string.
16058 * @returns {string} Returns the empty string.
16061 * _.times(2, _.stubString);
16064 function stubString() {
16069 * This method returns `true`.
16075 * @returns {boolean} Returns `true`.
16078 * _.times(2, _.stubTrue);
16079 * // => [true, true]
16081 function stubTrue() {
16086 * Invokes the iteratee `n` times, returning an array of the results of
16087 * each invocation. The iteratee is invoked with one argument; (index).
16093 * @param {number} n The number of times to invoke `iteratee`.
16094 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
16095 * @returns {Array} Returns the array of results.
16098 * _.times(3, String);
16099 * // => ['0', '1', '2']
16101 * _.times(4, _.constant(0));
16102 * // => [0, 0, 0, 0]
16104 function times(n, iteratee) {
16106 if (n < 1 || n > MAX_SAFE_INTEGER) {
16109 var index = MAX_ARRAY_LENGTH,
16110 length = nativeMin(n, MAX_ARRAY_LENGTH);
16112 iteratee = getIteratee(iteratee);
16113 n -= MAX_ARRAY_LENGTH;
16115 var result = baseTimes(length, iteratee);
16116 while (++index < n) {
16123 * Converts `value` to a property path array.
16129 * @param {*} value The value to convert.
16130 * @returns {Array} Returns the new property path array.
16133 * _.toPath('a.b.c');
16134 * // => ['a', 'b', 'c']
16136 * _.toPath('a[0].b.c');
16137 * // => ['a', '0', 'b', 'c']
16139 function toPath(value) {
16140 if (isArray(value)) {
16141 return arrayMap(value, toKey);
16143 return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
16147 * Generates a unique ID. If `prefix` is given, the ID is appended to it.
16153 * @param {string} [prefix=''] The value to prefix the ID with.
16154 * @returns {string} Returns the unique ID.
16157 * _.uniqueId('contact_');
16158 * // => 'contact_104'
16163 function uniqueId(prefix) {
16164 var id = ++idCounter;
16165 return toString(prefix) + id;
16168 /*------------------------------------------------------------------------*/
16171 * Adds two numbers.
16177 * @param {number} augend The first number in an addition.
16178 * @param {number} addend The second number in an addition.
16179 * @returns {number} Returns the total.
16185 var add = createMathOperation(function(augend, addend) {
16186 return augend + addend;
16190 * Computes `number` rounded up to `precision`.
16196 * @param {number} number The number to round up.
16197 * @param {number} [precision=0] The precision to round up to.
16198 * @returns {number} Returns the rounded up number.
16204 * _.ceil(6.004, 2);
16207 * _.ceil(6040, -2);
16210 var ceil = createRound('ceil');
16213 * Divide two numbers.
16219 * @param {number} dividend The first number in a division.
16220 * @param {number} divisor The second number in a division.
16221 * @returns {number} Returns the quotient.
16227 var divide = createMathOperation(function(dividend, divisor) {
16228 return dividend / divisor;
16232 * Computes `number` rounded down to `precision`.
16238 * @param {number} number The number to round down.
16239 * @param {number} [precision=0] The precision to round down to.
16240 * @returns {number} Returns the rounded down number.
16246 * _.floor(0.046, 2);
16249 * _.floor(4060, -2);
16252 var floor = createRound('floor');
16255 * Computes the maximum value of `array`. If `array` is empty or falsey,
16256 * `undefined` is returned.
16262 * @param {Array} array The array to iterate over.
16263 * @returns {*} Returns the maximum value.
16266 * _.max([4, 2, 8, 6]);
16272 function max(array) {
16273 return (array && array.length)
16274 ? baseExtremum(array, identity, baseGt)
16279 * This method is like `_.max` except that it accepts `iteratee` which is
16280 * invoked for each element in `array` to generate the criterion by which
16281 * the value is ranked. The iteratee is invoked with one argument: (value).
16287 * @param {Array} array The array to iterate over.
16288 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16289 * @returns {*} Returns the maximum value.
16292 * var objects = [{ 'n': 1 }, { 'n': 2 }];
16294 * _.maxBy(objects, function(o) { return o.n; });
16297 * // The `_.property` iteratee shorthand.
16298 * _.maxBy(objects, 'n');
16301 function maxBy(array, iteratee) {
16302 return (array && array.length)
16303 ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
16308 * Computes the mean of the values in `array`.
16314 * @param {Array} array The array to iterate over.
16315 * @returns {number} Returns the mean.
16318 * _.mean([4, 2, 8, 6]);
16321 function mean(array) {
16322 return baseMean(array, identity);
16326 * This method is like `_.mean` except that it accepts `iteratee` which is
16327 * invoked for each element in `array` to generate the value to be averaged.
16328 * The iteratee is invoked with one argument: (value).
16334 * @param {Array} array The array to iterate over.
16335 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16336 * @returns {number} Returns the mean.
16339 * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16341 * _.meanBy(objects, function(o) { return o.n; });
16344 * // The `_.property` iteratee shorthand.
16345 * _.meanBy(objects, 'n');
16348 function meanBy(array, iteratee) {
16349 return baseMean(array, getIteratee(iteratee, 2));
16353 * Computes the minimum value of `array`. If `array` is empty or falsey,
16354 * `undefined` is returned.
16360 * @param {Array} array The array to iterate over.
16361 * @returns {*} Returns the minimum value.
16364 * _.min([4, 2, 8, 6]);
16370 function min(array) {
16371 return (array && array.length)
16372 ? baseExtremum(array, identity, baseLt)
16377 * This method is like `_.min` except that it accepts `iteratee` which is
16378 * invoked for each element in `array` to generate the criterion by which
16379 * the value is ranked. The iteratee is invoked with one argument: (value).
16385 * @param {Array} array The array to iterate over.
16386 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16387 * @returns {*} Returns the minimum value.
16390 * var objects = [{ 'n': 1 }, { 'n': 2 }];
16392 * _.minBy(objects, function(o) { return o.n; });
16395 * // The `_.property` iteratee shorthand.
16396 * _.minBy(objects, 'n');
16399 function minBy(array, iteratee) {
16400 return (array && array.length)
16401 ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
16406 * Multiply two numbers.
16412 * @param {number} multiplier The first number in a multiplication.
16413 * @param {number} multiplicand The second number in a multiplication.
16414 * @returns {number} Returns the product.
16417 * _.multiply(6, 4);
16420 var multiply = createMathOperation(function(multiplier, multiplicand) {
16421 return multiplier * multiplicand;
16425 * Computes `number` rounded to `precision`.
16431 * @param {number} number The number to round.
16432 * @param {number} [precision=0] The precision to round to.
16433 * @returns {number} Returns the rounded number.
16439 * _.round(4.006, 2);
16442 * _.round(4060, -2);
16445 var round = createRound('round');
16448 * Subtract two numbers.
16454 * @param {number} minuend The first number in a subtraction.
16455 * @param {number} subtrahend The second number in a subtraction.
16456 * @returns {number} Returns the difference.
16459 * _.subtract(6, 4);
16462 var subtract = createMathOperation(function(minuend, subtrahend) {
16463 return minuend - subtrahend;
16467 * Computes the sum of the values in `array`.
16473 * @param {Array} array The array to iterate over.
16474 * @returns {number} Returns the sum.
16477 * _.sum([4, 2, 8, 6]);
16480 function sum(array) {
16481 return (array && array.length)
16482 ? baseSum(array, identity)
16487 * This method is like `_.sum` except that it accepts `iteratee` which is
16488 * invoked for each element in `array` to generate the value to be summed.
16489 * The iteratee is invoked with one argument: (value).
16495 * @param {Array} array The array to iterate over.
16496 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16497 * @returns {number} Returns the sum.
16500 * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16502 * _.sumBy(objects, function(o) { return o.n; });
16505 * // The `_.property` iteratee shorthand.
16506 * _.sumBy(objects, 'n');
16509 function sumBy(array, iteratee) {
16510 return (array && array.length)
16511 ? baseSum(array, getIteratee(iteratee, 2))
16515 /*------------------------------------------------------------------------*/
16517 // Add methods that return wrapped values in chain sequences.
16518 lodash.after = after;
16520 lodash.assign = assign;
16521 lodash.assignIn = assignIn;
16522 lodash.assignInWith = assignInWith;
16523 lodash.assignWith = assignWith;
16525 lodash.before = before;
16526 lodash.bind = bind;
16527 lodash.bindAll = bindAll;
16528 lodash.bindKey = bindKey;
16529 lodash.castArray = castArray;
16530 lodash.chain = chain;
16531 lodash.chunk = chunk;
16532 lodash.compact = compact;
16533 lodash.concat = concat;
16534 lodash.cond = cond;
16535 lodash.conforms = conforms;
16536 lodash.constant = constant;
16537 lodash.countBy = countBy;
16538 lodash.create = create;
16539 lodash.curry = curry;
16540 lodash.curryRight = curryRight;
16541 lodash.debounce = debounce;
16542 lodash.defaults = defaults;
16543 lodash.defaultsDeep = defaultsDeep;
16544 lodash.defer = defer;
16545 lodash.delay = delay;
16546 lodash.difference = difference;
16547 lodash.differenceBy = differenceBy;
16548 lodash.differenceWith = differenceWith;
16549 lodash.drop = drop;
16550 lodash.dropRight = dropRight;
16551 lodash.dropRightWhile = dropRightWhile;
16552 lodash.dropWhile = dropWhile;
16553 lodash.fill = fill;
16554 lodash.filter = filter;
16555 lodash.flatMap = flatMap;
16556 lodash.flatMapDeep = flatMapDeep;
16557 lodash.flatMapDepth = flatMapDepth;
16558 lodash.flatten = flatten;
16559 lodash.flattenDeep = flattenDeep;
16560 lodash.flattenDepth = flattenDepth;
16561 lodash.flip = flip;
16562 lodash.flow = flow;
16563 lodash.flowRight = flowRight;
16564 lodash.fromPairs = fromPairs;
16565 lodash.functions = functions;
16566 lodash.functionsIn = functionsIn;
16567 lodash.groupBy = groupBy;
16568 lodash.initial = initial;
16569 lodash.intersection = intersection;
16570 lodash.intersectionBy = intersectionBy;
16571 lodash.intersectionWith = intersectionWith;
16572 lodash.invert = invert;
16573 lodash.invertBy = invertBy;
16574 lodash.invokeMap = invokeMap;
16575 lodash.iteratee = iteratee;
16576 lodash.keyBy = keyBy;
16577 lodash.keys = keys;
16578 lodash.keysIn = keysIn;
16580 lodash.mapKeys = mapKeys;
16581 lodash.mapValues = mapValues;
16582 lodash.matches = matches;
16583 lodash.matchesProperty = matchesProperty;
16584 lodash.memoize = memoize;
16585 lodash.merge = merge;
16586 lodash.mergeWith = mergeWith;
16587 lodash.method = method;
16588 lodash.methodOf = methodOf;
16589 lodash.mixin = mixin;
16590 lodash.negate = negate;
16591 lodash.nthArg = nthArg;
16592 lodash.omit = omit;
16593 lodash.omitBy = omitBy;
16594 lodash.once = once;
16595 lodash.orderBy = orderBy;
16596 lodash.over = over;
16597 lodash.overArgs = overArgs;
16598 lodash.overEvery = overEvery;
16599 lodash.overSome = overSome;
16600 lodash.partial = partial;
16601 lodash.partialRight = partialRight;
16602 lodash.partition = partition;
16603 lodash.pick = pick;
16604 lodash.pickBy = pickBy;
16605 lodash.property = property;
16606 lodash.propertyOf = propertyOf;
16607 lodash.pull = pull;
16608 lodash.pullAll = pullAll;
16609 lodash.pullAllBy = pullAllBy;
16610 lodash.pullAllWith = pullAllWith;
16611 lodash.pullAt = pullAt;
16612 lodash.range = range;
16613 lodash.rangeRight = rangeRight;
16614 lodash.rearg = rearg;
16615 lodash.reject = reject;
16616 lodash.remove = remove;
16617 lodash.rest = rest;
16618 lodash.reverse = reverse;
16619 lodash.sampleSize = sampleSize;
16621 lodash.setWith = setWith;
16622 lodash.shuffle = shuffle;
16623 lodash.slice = slice;
16624 lodash.sortBy = sortBy;
16625 lodash.sortedUniq = sortedUniq;
16626 lodash.sortedUniqBy = sortedUniqBy;
16627 lodash.split = split;
16628 lodash.spread = spread;
16629 lodash.tail = tail;
16630 lodash.take = take;
16631 lodash.takeRight = takeRight;
16632 lodash.takeRightWhile = takeRightWhile;
16633 lodash.takeWhile = takeWhile;
16635 lodash.throttle = throttle;
16636 lodash.thru = thru;
16637 lodash.toArray = toArray;
16638 lodash.toPairs = toPairs;
16639 lodash.toPairsIn = toPairsIn;
16640 lodash.toPath = toPath;
16641 lodash.toPlainObject = toPlainObject;
16642 lodash.transform = transform;
16643 lodash.unary = unary;
16644 lodash.union = union;
16645 lodash.unionBy = unionBy;
16646 lodash.unionWith = unionWith;
16647 lodash.uniq = uniq;
16648 lodash.uniqBy = uniqBy;
16649 lodash.uniqWith = uniqWith;
16650 lodash.unset = unset;
16651 lodash.unzip = unzip;
16652 lodash.unzipWith = unzipWith;
16653 lodash.update = update;
16654 lodash.updateWith = updateWith;
16655 lodash.values = values;
16656 lodash.valuesIn = valuesIn;
16657 lodash.without = without;
16658 lodash.words = words;
16659 lodash.wrap = wrap;
16661 lodash.xorBy = xorBy;
16662 lodash.xorWith = xorWith;
16664 lodash.zipObject = zipObject;
16665 lodash.zipObjectDeep = zipObjectDeep;
16666 lodash.zipWith = zipWith;
16669 lodash.entries = toPairs;
16670 lodash.entriesIn = toPairsIn;
16671 lodash.extend = assignIn;
16672 lodash.extendWith = assignInWith;
16674 // Add methods to `lodash.prototype`.
16675 mixin(lodash, lodash);
16677 /*------------------------------------------------------------------------*/
16679 // Add methods that return unwrapped values in chain sequences.
16681 lodash.attempt = attempt;
16682 lodash.camelCase = camelCase;
16683 lodash.capitalize = capitalize;
16684 lodash.ceil = ceil;
16685 lodash.clamp = clamp;
16686 lodash.clone = clone;
16687 lodash.cloneDeep = cloneDeep;
16688 lodash.cloneDeepWith = cloneDeepWith;
16689 lodash.cloneWith = cloneWith;
16690 lodash.conformsTo = conformsTo;
16691 lodash.deburr = deburr;
16692 lodash.defaultTo = defaultTo;
16693 lodash.divide = divide;
16694 lodash.endsWith = endsWith;
16696 lodash.escape = escape;
16697 lodash.escapeRegExp = escapeRegExp;
16698 lodash.every = every;
16699 lodash.find = find;
16700 lodash.findIndex = findIndex;
16701 lodash.findKey = findKey;
16702 lodash.findLast = findLast;
16703 lodash.findLastIndex = findLastIndex;
16704 lodash.findLastKey = findLastKey;
16705 lodash.floor = floor;
16706 lodash.forEach = forEach;
16707 lodash.forEachRight = forEachRight;
16708 lodash.forIn = forIn;
16709 lodash.forInRight = forInRight;
16710 lodash.forOwn = forOwn;
16711 lodash.forOwnRight = forOwnRight;
16716 lodash.hasIn = hasIn;
16717 lodash.head = head;
16718 lodash.identity = identity;
16719 lodash.includes = includes;
16720 lodash.indexOf = indexOf;
16721 lodash.inRange = inRange;
16722 lodash.invoke = invoke;
16723 lodash.isArguments = isArguments;
16724 lodash.isArray = isArray;
16725 lodash.isArrayBuffer = isArrayBuffer;
16726 lodash.isArrayLike = isArrayLike;
16727 lodash.isArrayLikeObject = isArrayLikeObject;
16728 lodash.isBoolean = isBoolean;
16729 lodash.isBuffer = isBuffer;
16730 lodash.isDate = isDate;
16731 lodash.isElement = isElement;
16732 lodash.isEmpty = isEmpty;
16733 lodash.isEqual = isEqual;
16734 lodash.isEqualWith = isEqualWith;
16735 lodash.isError = isError;
16736 lodash.isFinite = isFinite;
16737 lodash.isFunction = isFunction;
16738 lodash.isInteger = isInteger;
16739 lodash.isLength = isLength;
16740 lodash.isMap = isMap;
16741 lodash.isMatch = isMatch;
16742 lodash.isMatchWith = isMatchWith;
16743 lodash.isNaN = isNaN;
16744 lodash.isNative = isNative;
16745 lodash.isNil = isNil;
16746 lodash.isNull = isNull;
16747 lodash.isNumber = isNumber;
16748 lodash.isObject = isObject;
16749 lodash.isObjectLike = isObjectLike;
16750 lodash.isPlainObject = isPlainObject;
16751 lodash.isRegExp = isRegExp;
16752 lodash.isSafeInteger = isSafeInteger;
16753 lodash.isSet = isSet;
16754 lodash.isString = isString;
16755 lodash.isSymbol = isSymbol;
16756 lodash.isTypedArray = isTypedArray;
16757 lodash.isUndefined = isUndefined;
16758 lodash.isWeakMap = isWeakMap;
16759 lodash.isWeakSet = isWeakSet;
16760 lodash.join = join;
16761 lodash.kebabCase = kebabCase;
16762 lodash.last = last;
16763 lodash.lastIndexOf = lastIndexOf;
16764 lodash.lowerCase = lowerCase;
16765 lodash.lowerFirst = lowerFirst;
16769 lodash.maxBy = maxBy;
16770 lodash.mean = mean;
16771 lodash.meanBy = meanBy;
16773 lodash.minBy = minBy;
16774 lodash.stubArray = stubArray;
16775 lodash.stubFalse = stubFalse;
16776 lodash.stubObject = stubObject;
16777 lodash.stubString = stubString;
16778 lodash.stubTrue = stubTrue;
16779 lodash.multiply = multiply;
16781 lodash.noConflict = noConflict;
16782 lodash.noop = noop;
16785 lodash.padEnd = padEnd;
16786 lodash.padStart = padStart;
16787 lodash.parseInt = parseInt;
16788 lodash.random = random;
16789 lodash.reduce = reduce;
16790 lodash.reduceRight = reduceRight;
16791 lodash.repeat = repeat;
16792 lodash.replace = replace;
16793 lodash.result = result;
16794 lodash.round = round;
16795 lodash.runInContext = runInContext;
16796 lodash.sample = sample;
16797 lodash.size = size;
16798 lodash.snakeCase = snakeCase;
16799 lodash.some = some;
16800 lodash.sortedIndex = sortedIndex;
16801 lodash.sortedIndexBy = sortedIndexBy;
16802 lodash.sortedIndexOf = sortedIndexOf;
16803 lodash.sortedLastIndex = sortedLastIndex;
16804 lodash.sortedLastIndexBy = sortedLastIndexBy;
16805 lodash.sortedLastIndexOf = sortedLastIndexOf;
16806 lodash.startCase = startCase;
16807 lodash.startsWith = startsWith;
16808 lodash.subtract = subtract;
16810 lodash.sumBy = sumBy;
16811 lodash.template = template;
16812 lodash.times = times;
16813 lodash.toFinite = toFinite;
16814 lodash.toInteger = toInteger;
16815 lodash.toLength = toLength;
16816 lodash.toLower = toLower;
16817 lodash.toNumber = toNumber;
16818 lodash.toSafeInteger = toSafeInteger;
16819 lodash.toString = toString;
16820 lodash.toUpper = toUpper;
16821 lodash.trim = trim;
16822 lodash.trimEnd = trimEnd;
16823 lodash.trimStart = trimStart;
16824 lodash.truncate = truncate;
16825 lodash.unescape = unescape;
16826 lodash.uniqueId = uniqueId;
16827 lodash.upperCase = upperCase;
16828 lodash.upperFirst = upperFirst;
16831 lodash.each = forEach;
16832 lodash.eachRight = forEachRight;
16833 lodash.first = head;
16835 mixin(lodash, (function() {
16837 baseForOwn(lodash, function(func, methodName) {
16838 if (!hasOwnProperty.call(lodash.prototype, methodName)) {
16839 source[methodName] = func;
16843 }()), { 'chain': false });
16845 /*------------------------------------------------------------------------*/
16848 * The semantic version number.
16854 lodash.VERSION = VERSION;
16856 // Assign default placeholders.
16857 arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
16858 lodash[methodName].placeholder = lodash;
16861 // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
16862 arrayEach(['drop', 'take'], function(methodName, index) {
16863 LazyWrapper.prototype[methodName] = function(n) {
16864 n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
16866 var result = (this.__filtered__ && !index)
16867 ? new LazyWrapper(this)
16870 if (result.__filtered__) {
16871 result.__takeCount__ = nativeMin(n, result.__takeCount__);
16873 result.__views__.push({
16874 'size': nativeMin(n, MAX_ARRAY_LENGTH),
16875 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
16881 LazyWrapper.prototype[methodName + 'Right'] = function(n) {
16882 return this.reverse()[methodName](n).reverse();
16886 // Add `LazyWrapper` methods that accept an `iteratee` value.
16887 arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
16888 var type = index + 1,
16889 isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
16891 LazyWrapper.prototype[methodName] = function(iteratee) {
16892 var result = this.clone();
16893 result.__iteratees__.push({
16894 'iteratee': getIteratee(iteratee, 3),
16897 result.__filtered__ = result.__filtered__ || isFilter;
16902 // Add `LazyWrapper` methods for `_.head` and `_.last`.
16903 arrayEach(['head', 'last'], function(methodName, index) {
16904 var takeName = 'take' + (index ? 'Right' : '');
16906 LazyWrapper.prototype[methodName] = function() {
16907 return this[takeName](1).value()[0];
16911 // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
16912 arrayEach(['initial', 'tail'], function(methodName, index) {
16913 var dropName = 'drop' + (index ? '' : 'Right');
16915 LazyWrapper.prototype[methodName] = function() {
16916 return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
16920 LazyWrapper.prototype.compact = function() {
16921 return this.filter(identity);
16924 LazyWrapper.prototype.find = function(predicate) {
16925 return this.filter(predicate).head();
16928 LazyWrapper.prototype.findLast = function(predicate) {
16929 return this.reverse().find(predicate);
16932 LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
16933 if (typeof path == 'function') {
16934 return new LazyWrapper(this);
16936 return this.map(function(value) {
16937 return baseInvoke(value, path, args);
16941 LazyWrapper.prototype.reject = function(predicate) {
16942 return this.filter(negate(getIteratee(predicate)));
16945 LazyWrapper.prototype.slice = function(start, end) {
16946 start = toInteger(start);
16949 if (result.__filtered__ && (start > 0 || end < 0)) {
16950 return new LazyWrapper(result);
16953 result = result.takeRight(-start);
16954 } else if (start) {
16955 result = result.drop(start);
16957 if (end !== undefined) {
16958 end = toInteger(end);
16959 result = end < 0 ? result.dropRight(-end) : result.take(end - start);
16964 LazyWrapper.prototype.takeRightWhile = function(predicate) {
16965 return this.reverse().takeWhile(predicate).reverse();
16968 LazyWrapper.prototype.toArray = function() {
16969 return this.take(MAX_ARRAY_LENGTH);
16972 // Add `LazyWrapper` methods to `lodash.prototype`.
16973 baseForOwn(LazyWrapper.prototype, function(func, methodName) {
16974 var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
16975 isTaker = /^(?:head|last)$/.test(methodName),
16976 lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
16977 retUnwrapped = isTaker || /^find/.test(methodName);
16982 lodash.prototype[methodName] = function() {
16983 var value = this.__wrapped__,
16984 args = isTaker ? [1] : arguments,
16985 isLazy = value instanceof LazyWrapper,
16986 iteratee = args[0],
16987 useLazy = isLazy || isArray(value);
16989 var interceptor = function(value) {
16990 var result = lodashFunc.apply(lodash, arrayPush([value], args));
16991 return (isTaker && chainAll) ? result[0] : result;
16994 if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
16995 // Avoid lazy use if the iteratee has a "length" value other than `1`.
16996 isLazy = useLazy = false;
16998 var chainAll = this.__chain__,
16999 isHybrid = !!this.__actions__.length,
17000 isUnwrapped = retUnwrapped && !chainAll,
17001 onlyLazy = isLazy && !isHybrid;
17003 if (!retUnwrapped && useLazy) {
17004 value = onlyLazy ? value : new LazyWrapper(this);
17005 var result = func.apply(value, args);
17006 result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
17007 return new LodashWrapper(result, chainAll);
17009 if (isUnwrapped && onlyLazy) {
17010 return func.apply(this, args);
17012 result = this.thru(interceptor);
17013 return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
17017 // Add `Array` methods to `lodash.prototype`.
17018 arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
17019 var func = arrayProto[methodName],
17020 chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
17021 retUnwrapped = /^(?:pop|shift)$/.test(methodName);
17023 lodash.prototype[methodName] = function() {
17024 var args = arguments;
17025 if (retUnwrapped && !this.__chain__) {
17026 var value = this.value();
17027 return func.apply(isArray(value) ? value : [], args);
17029 return this[chainName](function(value) {
17030 return func.apply(isArray(value) ? value : [], args);
17035 // Map minified method names to their real names.
17036 baseForOwn(LazyWrapper.prototype, function(func, methodName) {
17037 var lodashFunc = lodash[methodName];
17039 var key = (lodashFunc.name + ''),
17040 names = realNames[key] || (realNames[key] = []);
17042 names.push({ 'name': methodName, 'func': lodashFunc });
17046 realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
17051 // Add methods to `LazyWrapper`.
17052 LazyWrapper.prototype.clone = lazyClone;
17053 LazyWrapper.prototype.reverse = lazyReverse;
17054 LazyWrapper.prototype.value = lazyValue;
17056 // Add chain sequence methods to the `lodash` wrapper.
17057 lodash.prototype.at = wrapperAt;
17058 lodash.prototype.chain = wrapperChain;
17059 lodash.prototype.commit = wrapperCommit;
17060 lodash.prototype.next = wrapperNext;
17061 lodash.prototype.plant = wrapperPlant;
17062 lodash.prototype.reverse = wrapperReverse;
17063 lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
17065 // Add lazy aliases.
17066 lodash.prototype.first = lodash.prototype.head;
17069 lodash.prototype[symIterator] = wrapperToIterator;
17074 /*--------------------------------------------------------------------------*/
17077 var _ = runInContext();
17079 // Some AMD build optimizers, like r.js, check for condition patterns like:
17080 if (typeof undefined == 'function' && typeof undefined.amd == 'object' && undefined.amd) {
17081 // Expose Lodash on the global object to prevent errors when Lodash is
17082 // loaded by a script tag in the presence of an AMD loader.
17083 // See http://requirejs.org/docs/errors.html#mismatch for more details.
17084 // Use `_.noConflict` to remove Lodash from the global object.
17087 // Define as an anonymous module so, through path mapping, it can be
17088 // referenced as the "underscore" module.
17089 undefined(function() {
17093 // Check for `exports` after `define` in case a build optimizer adds it.
17094 else if (freeModule) {
17095 // Export for Node.js.
17096 (freeModule.exports = _)._ = _;
17097 // Export for CommonJS support.
17101 // Export to the global object.
17104 }.call(commonjsGlobal));
17109 var lodash$1 = Object.freeze({
17111 __moduleExports: lodash
17114 function osmIsInterestingTag(key) {
17115 return key !== 'attribution' &&
17116 key !== 'created_by' &&
17117 key !== 'source' &&
17119 key.indexOf('tiger:') !== 0;
17124 var osmOneWayTags = {
17126 'chair_lift': true,
17127 'mixed_lift': true,
17132 'magic_carpet': true,
17137 'motorway_link': true
17143 'piste:halfpipe': true
17160 var osmPavedTags = {
17171 var dataWikipedia = [
17288 "беларуская (тарашкевіца)",
17289 "беларуская (тарашкевіца)",
17329 "বিষ্ণুপ্রিয়া মণিপুরী",
17358 "Chavacano de Zamboanga",
17359 "Chavacano de Zamboanga",
17363 "Min Dong Chinese",
17404 "Nēhiyawēwin / ᓀᐦᐃᔭᐍᐏᐣ",
17424 "словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ",
17478 "Emiliano-Romagnolo",
17479 "emiliàn e rumagnòl",
17534 "Na Vosa Vakaviti",
17553 "Northern Frisian",
17604 "गोंयची कोंकणी / Gõychi Konknni",
17684 "Bahasa Indonesia",
17724 "ᐃᓄᒃᑎᑐᑦ/inuktitut",
17733 "Jamaican Creole English",
17809 "къарачай-малкъар",
17949 "Baso Minangkabau",
18048 "Norwegian Nynorsk",
18069 "Sesotho sa Leboa",
18133 "Pennsylvania German",
18148 "Norfuk / Pitkern",
18149 "Norfuk / Pitkern",
18274 "srpskohrvatski / српскохрватски",
18338 "Saterland Frisian",
18464 "ئۇيغۇرچە / Uyghurche",
18479 "oʻzbekcha/ўзбекча",
18573 "Classical Chinese",
18578 "Chinese (Min Nan)",
18594 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}}};
18595 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}}};
18596 var dataSuggestions = {
18601 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"]]}];
18603 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"}}];
18605 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"];
18607 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}};
18609 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"};
18611 var type = "FeatureCollection";
18612 var features = [{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[1.97754,51.13111],[1.8457,63.45051],[-10.45898,57.01681],[-6.82251,55.26503],[-7.25583,55.06525],[-7.26546,55.0665],[-7.26992,55.06419],[-7.2725,55.06346],[-7.27818,55.05362],[-7.2893,55.04735],[-7.29939,55.0561],[-7.31835,55.04475],[-7.3447,55.05079],[-7.38831,55.02389],[-7.40547,55.00292],[-7.39157,54.99507],[-7.40075,54.98892],[-7.40706,54.98291],[-7.40363,54.97963],[-7.40633,54.97813],[-7.39835,54.97013],[-7.40745,54.96357],[-7.40178,54.95961],[-7.40727,54.95515],[-7.3944,54.94376],[-7.44444,54.93858],[-7.45216,54.89793],[-7.44204,54.87532],[-7.4713,54.83431],[-7.48092,54.83093],[-7.49216,54.82185],[-7.55121,54.79054],[-7.5443,54.78609],[-7.54958,54.75653],[-7.5349,54.74917],[-7.54881,54.74068],[-7.55941,54.74556],[-7.57894,54.74221],[-7.57507,54.7494],[-7.58606,54.75039],[-7.58872,54.74377],[-7.60031,54.74603],[-7.60632,54.74405],[-7.61662,54.74459],[-7.63593,54.75108],[-7.68854,54.72968],[-7.72064,54.72155],[-7.75094,54.70469],[-7.79094,54.71942],[-7.8051,54.71932],[-7.83497,54.73632],[-7.85419,54.72745],[-7.91496,54.67582],[-7.90174,54.66182],[-7.83832,54.63401],[-7.7433,54.6188],[-7.70863,54.63485],[-7.70682,54.6189],[-7.69386,54.6188],[-7.69631,54.61125],[-7.75845,54.59509],[-7.78708,54.58],[-7.79446,54.58141],[-7.79969,54.57704],[-7.79673,54.56915],[-7.8184,54.56315],[-7.83334,54.55227],[-7.82737,54.54299],[-7.85007,54.53363],[-7.90741,54.53722],[-7.93213,54.53388],[-8.00487,54.54568],[-8.03727,54.51162],[-8.04285,54.48759],[-8.08027,54.48829],[-8.09988,54.48395],[-8.09126,54.4765],[-8.111,54.47807],[-8.11512,54.46904],[-8.16542,54.46914],[-8.1776,54.46485],[-8.14293,54.45003],[-8.16284,54.4413],[-8.08731,54.4002],[-8.06062,54.37051],[-8.03289,54.35711],[-8.00054,54.34835],[-7.93333,54.30561],[-7.85849,54.29151],[-7.87067,54.28794],[-7.87265,54.26648],[-7.86123,54.25931],[-7.85917,54.21256],[-7.71043,54.20307],[-7.70193,54.20776],[-7.68828,54.202],[-7.67644,54.18906],[-7.66082,54.1871],[-7.62554,54.16545],[-7.62541,54.15319],[-7.61026,54.14353],[-7.57421,54.14142],[-7.57181,54.13287],[-7.56228,54.12704],[-7.51379,54.12998],[-7.47944,54.122],[-7.47169,54.12665],[-7.47075,54.13318],[-7.44684,54.15168],[-7.40792,54.156],[-7.42579,54.14092],[-7.41903,54.13629],[-7.3744,54.14172],[-7.37234,54.13881],[-7.39509,54.12624],[-7.39182,54.12017],[-7.36341,54.13157],[-7.34518,54.11577],[-7.32471,54.12123],[-7.32003,54.11379],[-7.3078,54.11718],[-7.30548,54.12347],[-7.31591,54.12697],[-7.31213,54.13162],[-7.3187,54.13411],[-7.31857,54.13745],[-7.32222,54.13836],[-7.32737,54.13544],[-7.3399,54.14585],[-7.30827,54.16716],[-7.30024,54.16625],[-7.29029,54.1715],[-7.28158,54.16839],[-7.2863,54.14919],[-7.29874,54.14904],[-7.30162,54.14411],[-7.28411,54.13971],[-7.29192,54.13071],[-7.29737,54.133],[-7.30883,54.13242],[-7.30333,54.12251],[-7.29218,54.11929],[-7.27844,54.12282],[-7.27707,54.12986],[-7.26613,54.13624],[-7.2566,54.16354],[-7.24015,54.17125],[-7.2575,54.17678],[-7.2581,54.19257],[-7.25179,54.19403],[-7.23608,54.1935],[-7.23338,54.19792],[-7.24317,54.20076],[-7.24892,54.1977],[-7.25183,54.20201],[-7.24119,54.20623],[-7.23094,54.20578],[-7.23269,54.20912],[-7.22188,54.21607],[-7.20643,54.2117],[-7.18506,54.22485],[-7.17055,54.21742],[-7.14721,54.22488],[-7.14633,54.23008],[-7.15051,54.23165],[-7.14613,54.23983],[-7.15802,54.24434],[-7.13985,54.25298],[-7.15255,54.26235],[-7.16064,54.27405],[-7.17991,54.27144],[-7.17201,54.28627],[-7.21252,54.2985],[-7.19888,54.31117],[-7.17918,54.30946],[-7.1812,54.3397],[-7.15339,54.33514],[-7.10253,54.35811],[-7.10811,54.36677],[-7.06927,54.3899],[-7.05593,54.41056],[-7.02898,54.42135],[-7.00198,54.40832],[-6.98683,54.40829],[-6.97562,54.40014],[-6.96774,54.40145],[-6.90682,54.36966],[-6.89772,54.35075],[-6.87527,54.33853],[-6.86512,54.32568],[-6.85163,54.29137],[-6.87452,54.28677],[-6.87791,54.27918],[-6.86673,54.27522],[-6.85177,54.26489],[-6.83693,54.26658],[-6.82165,54.24346],[-6.81633,54.22299],[-6.80045,54.22108],[-6.80122,54.21338],[-6.77599,54.19965],[-6.75573,54.1987],[-6.74316,54.18258],[-6.73406,54.18566],[-6.72445,54.18127],[-6.70295,54.20036],[-6.69166,54.20018],[-6.68673,54.19398],[-6.669,54.19584],[-6.65248,54.18102],[-6.6433,54.17801],[-6.63467,54.16449],[-6.63179,54.14766],[-6.64081,54.14238],[-6.63935,54.13599],[-6.66149,54.1205],[-6.6481,54.10153],[-6.66119,54.0934],[-6.66458,54.06629],[-6.64681,54.05873],[-6.62501,54.03737],[-6.59291,54.04755],[-6.58905,54.05808],[-6.5597,54.0481],[-6.52897,54.05888],[-6.50442,54.05566],[-6.47824,54.07004],[-6.47919,54.07762],[-6.43601,54.05959],[-6.36314,54.07057],[-6.36589,54.09338],[-6.36293,54.09758],[-6.37104,54.11497],[-6.3522,54.11084],[-6.34242,54.1114],[-6.33589,54.10833],[-6.33636,54.09469],[-6.31808,54.09096],[-6.30903,54.10463],[-6.29165,54.11235],[-6.28246,54.11145],[-6.26272,54.09786],[-5.35583,53.72597],[-7.0752,49.23912],[-1.83472,49.02346],[-2.12036,49.94415],[1.97754,51.13111]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-65.2,18.7],[-65,16.3],[-63.7,19.2],[-65.2,18.7]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-63,-50.5],[-55,-51],[-60,-54],[-63,-50.5]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-139.19952,60.08402],[-141,60.30621],[-141,76],[-169,68.63655],[-169,65.20147],[-180,61],[-180,-4],[-154,9],[-133.76404,54.54021],[-130.73868,54.71986],[-129.96277,55.29163],[-130.15228,55.7758],[-130.01787,55.90688],[-130.00362,56.00798],[-130.10284,56.12336],[-130.24498,56.09656],[-130.42625,56.14249],[-131.87439,56.79787],[-135.02884,59.56285],[-135.11759,59.62306],[-135.15827,59.6261],[-135.47928,59.79822],[-136.28677,59.57955],[-136.30531,59.46462],[-136.36836,59.44898],[-136.47697,59.46558],[-137.19727,59.01935],[-139.19952,60.08402]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-111.96064,48.99841],[-121.22623,49.00049],[-122.26513,49.00246],[-122.7565,49.00208],[-123.32218,49.00218],[-122.97821,48.76524],[-123.2666,48.69821],[-123.21991,48.21186],[-125.80444,48.60749],[-124.32129,31.54109],[-117.125,32.53429],[-116.82417,32.55996],[-115.88036,32.63735],[-115.49738,32.66486],[-114.71984,32.71877],[-114.7649,32.64602],[-114.80885,32.60959],[-114.81481,32.49451],[-112.81743,31.88004],[-111.07481,31.33224],[-109.56051,31.33402],[-108.20847,31.33384],[-108.20838,31.78363],[-106.52847,31.78391],[-106.52781,31.78086],[-106.52249,31.77501],[-106.51249,31.76933],[-106.50988,31.7612],[-106.50709,31.76123],[-106.48896,31.74806],[-106.48473,31.74769],[-106.4719,31.75101],[-106.46816,31.75897],[-106.45434,31.76466],[-106.45035,31.76426],[-106.43516,31.75492],[-106.41484,31.75101],[-106.37864,31.73021],[-106.37225,31.71174],[-106.34924,31.69633],[-106.33289,31.66178],[-106.3068,31.62459],[-106.28079,31.56179],[-106.24775,31.54226],[-106.2329,31.49982],[-106.2105,31.46857],[-106.08201,31.39863],[-106.00554,31.39233],[-105.76401,31.17051],[-105.58548,31.06117],[-105.56419,30.98526],[-104.99153,30.6639],[-104.97162,30.60896],[-104.90639,30.57822],[-104.83772,30.38117],[-104.70177,30.20567],[-104.68048,29.92399],[-104.57611,29.77838],[-104.51157,29.63674],[-104.39758,29.57047],[-104.39278,29.55293],[-104.05769,29.32173],[-103.79883,29.2581],[-103.78196,29.26555],[-103.76759,29.22799],[-103.14102,28.93666],[-102.86087,29.2217],[-102.65076,29.79418],[-101.41068,29.73457],[-101.26511,29.51372],[-101.05997,29.452],[-101.04083,29.38038],[-100.96303,29.34735],[-100.94406,29.34369],[-100.94071,29.33351],[-100.92775,29.32663],[-100.89814,29.30957],[-100.87818,29.28086],[-100.80076,29.2238],[-100.76437,29.15981],[-100.67047,29.08663],[-100.6412,28.91299],[-100.63236,28.90255],[-100.61296,28.89939],[-100.534,28.75622],[-100.51495,28.74531],[-100.50705,28.7143],[-100.51203,28.70666],[-100.51014,28.69127],[-100.50048,28.66186],[-100.45547,28.6381],[-100.44697,28.60743],[-100.35599,28.45239],[-100.34946,28.39653],[-100.29488,28.31315],[-100.29591,28.27324],[-100.17197,28.17493],[-99.93645,27.9568],[-99.87722,27.80173],[-99.79671,27.73338],[-99.772,27.72532],[-99.74556,27.69979],[-99.71947,27.65981],[-99.5957,27.59974],[-99.54094,27.60537],[-99.53055,27.57973],[-99.52034,27.55782],[-99.52802,27.49773],[-99.50141,27.49986],[-99.48755,27.49518],[-99.47897,27.48421],[-99.48661,27.46453],[-99.49534,27.44861],[-99.48927,27.40941],[-99.53957,27.31565],[-99.43588,27.19678],[-99.46404,27.01968],[-99.16698,26.56039],[-99.17474,26.53939],[-99.12698,26.51958],[-99.1135,26.42954],[-99.08355,26.39625],[-99.06007,26.39737],[-99.03634,26.41255],[-99.02042,26.40598],[-99.01291,26.39364],[-98.95686,26.38641],[-98.9566,26.37365],[-98.94523,26.36949],[-98.90013,26.36419],[-98.89905,26.35454],[-98.80305,26.36626],[-98.78254,26.30511],[-98.66667,26.23457],[-98.58496,26.24647],[-98.57951,26.23434],[-98.56519,26.23987],[-98.56294,26.22464],[-98.50599,26.20858],[-98.44806,26.21236],[-98.38617,26.15721],[-98.34176,26.15278],[-98.33579,26.1388],[-98.30626,26.10003],[-98.28841,26.10512],[-98.26524,26.0914],[-98.19898,26.06411],[-98.09577,26.05698],[-98.07568,26.06667],[-98.08302,26.03396],[-97.9771,26.04136],[-97.9532,26.06179],[-97.81643,26.04475],[-97.77017,26.02439],[-97.73884,26.02902],[-97.5289,25.90648],[-97.52151,25.88625],[-97.50615,25.89031],[-97.49851,25.89903],[-97.49637,25.89641],[-97.49748,25.88008],[-97.49422,25.87981],[-97.48847,25.88564],[-97.46409,25.88174],[-97.42607,25.842],[-97.36856,25.8396],[-97.26231,25.94724],[-80.81543,24.00633],[-66.87378,44.77794],[-67.16148,45.16715],[-67.2286,45.16739],[-67.26246,45.18797],[-67.28311,45.19175],[-67.28959,45.18784],[-67.29332,45.17568],[-67.29049,45.17317],[-67.3001,45.16776],[-67.3025,45.16122],[-67.29761,45.14766],[-67.33975,45.1255],[-67.40524,45.16122],[-67.40387,45.17139],[-67.4818,45.27682],[-67.42172,45.38543],[-67.45262,45.41008],[-67.50498,45.4889],[-67.41623,45.50105],[-67.42219,45.55661],[-67.42902,45.56833],[-67.42331,45.57154],[-67.42498,45.57836],[-67.45193,45.60323],[-67.77981,45.6738],[-67.79019,47.06776],[-67.88006,47.1067],[-67.91319,47.14793],[-67.92598,47.15418],[-67.95181,47.1875],[-68.02374,47.23915],[-68.13017,47.29309],[-68.17669,47.32893],[-68.24046,47.35354],[-68.32809,47.36005],[-68.36363,47.35476],[-68.38054,47.34167],[-68.38509,47.30321],[-68.37367,47.28796],[-68.4377,47.28232],[-68.47916,47.29623],[-68.51074,47.29885],[-68.54593,47.28441],[-68.58408,47.28482],[-68.59777,47.27134],[-68.59271,47.25762],[-68.61889,47.24148],[-68.68936,47.24125],[-68.71768,47.23676],[-68.80128,47.21423],[-68.89629,47.17676],[-69.05354,47.24847],[-69.04924,47.41798],[-69.22425,47.45961],[-69.99729,46.69558],[-70.0569,46.4149],[-70.25551,46.10871],[-70.29001,46.09431],[-70.39919,45.80667],[-70.83229,45.40062],[-70.80794,45.37878],[-70.82663,45.2367],[-70.87538,45.23453],[-70.92138,45.28099],[-70.90645,45.30918],[-71.0109,45.34798],[-71.08429,45.30556],[-71.1454,45.24226],[-71.20525,45.25278],[-71.28925,45.30097],[-71.41405,45.23513],[-71.43044,45.12381],[-71.49692,45.06991],[-71.50623,45.04878],[-71.49284,45.03629],[-71.50027,45.01372],[-71.79359,45.01075],[-72.08774,45.00581],[-72.14155,45.00568],[-72.15282,45.00609],[-72.17142,45.00584],[-72.25847,45.00436],[-72.38795,45.00626],[-72.4496,45.00863],[-72.5356,45.00936],[-72.66257,45.01523],[-72.82537,45.01642],[-73.08466,45.01561],[-73.45219,45.00875],[-74.14699,44.99145],[-74.33753,44.9923],[-74.50786,44.99798],[-74.66158,44.99949],[-74.71244,44.99734],[-74.75887,44.98708],[-74.76368,45.00632],[-74.78977,45.00365],[-74.82376,45.01773],[-74.94186,44.98229],[-75.30098,44.83883],[-75.30304,44.82836],[-75.59418,44.6457],[-75.97269,44.33502],[-75.97295,44.34595],[-76.00059,44.34797],[-76.17645,44.2865],[-76.18744,44.22158],[-76.88782,43.82759],[-79.16851,43.32168],[-79.05487,43.25371],[-79.05092,43.169],[-79.04603,43.16093],[-79.04208,43.13942],[-79.07002,43.12038],[-79.06015,43.114],[-79.0568,43.10474],[-79.0774,43.07861],[-78.9996,43.05484],[-79.02311,43.02071],[-79.02552,42.99473],[-78.96235,42.9573],[-78.91188,42.9426],[-78.90398,42.89181],[-82.42767,41.47978],[-83.14316,42.03807],[-83.12805,42.23843],[-83.09715,42.29052],[-83.07252,42.31515],[-82.94575,42.34332],[-82.59676,42.5479],[-82.51368,42.61785],[-82.5108,42.66464],[-82.4675,42.76415],[-82.48055,42.80573],[-82.45497,42.9284],[-82.41334,42.97099],[-82.42596,42.99536],[-82.15851,43.39507],[-83.53729,46.098],[-83.96301,46.05036],[-84.11021,46.23851],[-84.09794,46.25656],[-84.11613,46.26878],[-84.11905,46.31516],[-84.10721,46.3218],[-84.14394,46.41076],[-84.11682,46.51576],[-84.13536,46.53218],[-84.16162,46.5284],[-84.21621,46.53891],[-84.26994,46.49189],[-84.36092,46.50997],[-84.55284,46.4407],[-84.95178,46.77185],[-89.59179,48.00307],[-89.67547,48.00371],[-90.87204,48.25943],[-91.41312,48.06753],[-92.99377,48.62474],[-93.34877,48.62604],[-93.35529,48.61124],[-93.37074,48.60584],[-93.39812,48.60369],[-93.40542,48.61089],[-93.43846,48.59478],[-93.46859,48.59205],[-93.45735,48.56667],[-93.46533,48.54593],[-93.64763,48.51751],[-93.80625,48.51888],[-93.80642,48.58047],[-93.83328,48.62582],[-93.84865,48.63064],[-93.93388,48.6326],[-94.01327,48.64471],[-94.16176,48.64697],[-94.25025,48.65463],[-94.24931,48.67827],[-94.26046,48.69816],[-94.30578,48.71073],[-94.32758,48.70433],[-94.36123,48.70478],[-94.38406,48.71135],[-94.41629,48.71067],[-94.44294,48.69266],[-94.53615,48.7024],[-94.55031,48.71419],[-94.58894,48.71928],[-94.69425,48.77938],[-94.70129,48.83376],[-94.68996,48.83953],[-94.68395,48.99914],[-111.96064,48.99841]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[180,55],[170,53],[180,49],[180,55]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[143,22],[147,22],[147,12],[143,12],[143,22]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-171.5,-10],[-171,-15],[-167,-15],[-171.5,-10]]]}}];
18613 var dataImperial = {
18618 var type$1 = "FeatureCollection";
18619 var features$1 = [{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[113.573,22.186],[114,22.5],[114.05534,22.503],[114.0595,22.51422],[114.07345,22.51934],[114.0786,22.53012],[114.08512,22.53228],[114.09034,22.53717],[114.09611,22.53486],[114.10602,22.53472],[114.1115,22.52929],[114.11522,22.5308],[114.11649,22.53418],[114.11979,22.53511],[114.1244,22.5393],[114.12729,22.53947],[114.13018,22.54132],[114.13807,22.5432],[114.14429,22.54176],[114.14441,22.54114],[114.14846,22.54179],[114.14855,22.54397],[114.15042,22.54593],[114.14964,22.54954],[114.15166,22.55168],[114.15192,22.55438],[114.15642,22.55495],[114.15841,22.55909],[114.16032,22.56153],[114.16162,22.56187],[114.1634,22.55931],[114.16553,22.5593],[114.16733,22.56119],[114.16934,22.56093],[114.17061,22.5597],[114.17702,22.56],[114.17798,22.55546],[114.18401,22.5552],[114.18673,22.55468],[114.1878,22.55545],[114.18979,22.55446],[114.1955,22.55564],[114.19674,22.55691],[114.20005,22.55717],[114.20376,22.55623],[114.20884,22.55672],[114.22438,22.55055],[114.2264,22.5476],[114.22545,22.54528],[114.22661,22.54339],[114.32,22.576],[114.45,22.43],[114.45,22.14],[113.9,22.14],[113.75,22.22],[113.553,22.095],[113.54678,22.1207],[113.5456,22.1207],[113.54076,22.12373],[113.54016,22.13618],[113.54701,22.13651],[113.5475,22.14583],[113.52456,22.17978],[113.53623,22.20191],[113.53299,22.21232],[113.53497,22.21351],[113.53735,22.21377],[113.54156,22.21315],[113.54385,22.21709],[113.55849,22.21565],[113.573,22.186]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-75,18],[-80,20.5],[-83,19],[-77,16],[-75,18]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-64.33594,32.86113],[-79.39819,27.21067],[-80.63965,23.71998],[-73.39966,20.40642],[-65.1709,19.20743],[-65.09399,16.23577],[-59.13391,16.80454],[-62.64404,15.16228],[-59.43054,14.85985],[-62.83081,13.64599],[-61.80359,10.73752],[-62.08649,10.04729],[-61.06201,9.85522],[-59.81369,8.31274],[-59.8027,8.27469],[-59.83498,8.22712],[-59.94141,8.21149],[-59.99771,8.15576],[-59.97986,8.13265],[-59.99771,8.12041],[-60.00183,8.07147],[-60.05127,8.02524],[-60.09933,8.03747],[-60.12268,8.02388],[-60.14053,7.98988],[-60.36163,7.83345],[-60.53467,7.81713],[-60.5896,7.6375],[-60.72144,7.54493],[-60.5896,7.31888],[-60.63904,7.24532],[-60.54703,7.12542],[-60.46875,7.20309],[-60.37262,7.18401],[-60.29984,7.1445],[-60.2916,7.06819],[-60.39871,6.95097],[-60.66513,6.83235],[-60.71869,6.75053],[-60.91232,6.81735],[-60.94254,6.72053],[-61.14441,6.72326],[-61.23093,6.5773],[-61.1554,6.45314],[-61.14441,6.20199],[-61.39709,5.95619],[-60.71045,5.20036],[-60.21606,5.23319],[-59.99634,5.06906],[-60.13916,4.51071],[-59.69971,4.40118],[-59.5459,3.93002],[-59.87549,3.56825],[-59.7876,3.37086],[-60.01831,2.83332],[-59.90845,2.38335],[-59.69971,2.2626],[-59.77661,1.87833],[-59.65302,1.85087],[-59.69147,1.75754],[-59.61456,1.71361],[-59.55139,1.73283],[-59.36188,1.49123],[-59.26575,1.39238],[-58.92242,1.30726],[-58.83728,1.17271],[-58.71918,1.23037],[-58.71094,1.29902],[-58.49121,1.26058],[-58.461,1.37591],[-58.50494,1.38689],[-58.51044,1.46102],[-58.38135,1.4775],[-58.32642,1.57359],[-58.00507,1.49946],[-57.99133,1.65321],[-57.79907,1.69165],[-57.70844,1.71087],[-57.54364,1.68341],[-57.41455,1.94421],[-57.10693,1.97715],[-56.8103,1.85636],[-56.48071,1.92225],[-55.90942,1.81244],[-55.90942,2.04302],[-56.14014,2.26534],[-55.94788,2.53701],[-55.70892,2.39981],[-55.37933,2.43274],[-55.19257,2.53976],[-54.98108,2.57268],[-54.88495,2.43548],[-54.71191,2.46293],[-54.69543,2.34767],[-54.58832,2.32846],[-54.43451,2.43548],[-54.20654,2.76748],[-54.17358,3.12955],[-53.96484,3.57921],[-54.33838,4.00674],[-54.44412,4.52577],[-54.46884,4.91036],[-54.36653,5.13061],[-54.27727,5.26191],[-54.19968,5.3084],[-54.01222,5.54457],[-54.0239,5.64605],[-53.86322,5.94936],[-64.33594,32.86113]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-14.5,-6],[11.79657,-17.27197],[12.03415,-17.14866],[12.38159,-17.22213],[12.58484,-17.22476],[13.01193,-16.97405],[13.24951,-17.00098],[13.38135,-16.98522],[13.93341,-17.38734],[18.42476,-17.38996],[18.47763,-17.46857],[18.62663,-17.64599],[18.79211,-17.76177],[18.92944,-17.82061],[19.33044,-17.84806],[19.66278,-17.8644],[19.74792,-17.90557],[19.85161,-17.87486],[20.10361,-17.90296],[20.18394,-17.88401],[20.34737,-17.88466],[20.44693,-17.91733],[20.51697,-17.96698],[20.83008,-18.03032],[20.95711,-17.97285],[21.16997,-17.93497],[21.42677,-18.0264],[23.45032,-17.63879],[22.00012,-16.38866],[21.99944,-13.00523],[24.03809,-12.99118],[24.03809,-10.91962],[24.43359,-11.09217],[24.45557,-11.48002],[25.37842,-11.19996],[25.42236,-11.60919],[26.96045,-11.97484],[27.18018,-11.60919],[28.125,-12.42048],[29.11377,-13.36824],[29.1687,-13.43771],[29.55872,-13.19716],[29.68506,-13.2239],[29.62463,-13.41099],[29.80591,-13.44305],[29.81415,-12.14809],[29.31152,-12.55456],[28.41064,-11.78133],[28.63037,-10.70379],[28.65234,-9.73071],[28.37219,-9.24309],[28.89748,-8.47916],[30.78644,-8.26857],[29.39941,-6.05316],[29.4873,-4.45595],[29.75922,-4.46759],[29.81415,-4.36421],[29.88007,-4.36832],[30.04074,-4.26699],[30.07919,-4.1629],[30.18356,-4.08311],[30.1918,-4.05126],[30.21566,-4.04595],[30.22923,-4.01136],[30.21326,-3.99612],[30.25978,-3.88755],[30.29274,-3.86288],[30.34424,-3.77245],[30.39848,-3.79095],[30.40878,-3.76765],[30.39548,-3.7304],[30.39054,-3.72821],[30.3896,-3.71918],[30.39093,-3.7101],[30.39514,-3.70444],[30.42028,-3.64963],[30.46886,-3.53501],[30.67108,-3.41335],[30.63297,-3.34892],[30.84206,-3.25535],[30.84549,-3.16108],[30.83485,-3.09698],[30.7933,-3.06235],[30.82111,-3.02258],[30.84515,-2.9739],[30.74764,-2.99618],[30.7037,-2.97013],[30.66422,-2.98967],[30.57632,-2.90738],[30.49393,-2.94441],[30.41016,-2.87172],[30.52002,-2.39432],[30.77545,-2.38883],[30.8606,-2.31199],[30.84961,-2.19398],[30.89081,-2.07322],[30.81116,-1.96068],[30.83862,-1.6587],[30.73425,-1.4418],[30.56259,-1.33884],[30.4541,-1.05737],[30.35797,-1.06287],[30.34149,-1.13152],[30.16571,-1.34296],[29.91852,-1.48024],[29.83887,-1.31824],[29.58344,-1.39238],[29.729,0.05493],[29.96796,0.5136],[29.9707,0.8569],[30.22339,0.92281],[30.24536,1.15349],[30.47745,1.20772],[31.30966,2.15693],[31.20255,2.22211],[31.20255,2.29278],[31.16409,2.27906],[31.13937,2.28318],[31.13113,2.26534],[31.07826,2.30033],[31.0714,2.34767],[31.00479,2.4005],[30.97183,2.40461],[30.94711,2.38746],[30.94849,2.36276],[30.9375,2.33532],[30.88531,2.34012],[30.83038,2.42176],[30.74112,2.43274],[30.76035,2.5864],[30.90179,2.88132],[30.76447,3.04178],[30.93613,3.40239],[30.94059,3.50588],[30.85236,3.48601],[30.90866,3.5936],[30.95055,3.63918],[30.94677,3.65391],[30.9866,3.70187],[31.00582,3.70701],[31.02058,3.69708],[31.16547,3.7954],[31.28838,3.79643],[31.52699,3.66282],[31.7038,3.72449],[31.82671,3.82794],[31.96198,3.65596],[31.95854,3.57099],[32.04987,3.59155],[32.07733,3.57099],[32.0842,3.53672],[32.20093,3.50657],[32.21672,3.56448],[32.19578,3.59977],[32.41516,3.74504],[32.72055,3.76782],[32.89307,3.81219],[33.02782,3.89371],[33.18146,3.7793],[33.51173,3.75258],[33.98758,4.23309],[34.05762,4.28342],[34.38721,4.61065],[35.94452,4.62023],[35.95688,4.53467],[36.04134,4.44568],[36.89621,4.4491],[38.14728,3.62992],[38.55927,3.62033],[38.92181,3.51068],[39.56039,3.43392],[39.87076,3.87522],[40.76752,4.28753],[41.16371,3.94372],[41.89774,3.97797],[41.31271,3.14463],[40.98896,2.82869],[40.99548,-0.84042],[41.7,-1.8],[41.7,-49],[-27,-60],[-65.7,-52.5],[-14.5,-6]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[31.33301,35.47856],[33.0249,33.75175],[35.44189,36.02245],[31.33301,35.47856]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[14,36.5],[15,36],[14,35],[14,36.5]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[0,62],[2.5,51.3],[-2,50],[-1.9,49],[-20,53],[0,62]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[180,-35],[161,-19],[167,-12],[180,-22],[180,4],[170,3.7],[127,5.7],[118,2.7],[119.5,5.4],[117.2,7.5],[102.6,8],[102.9158,11.74099],[102.76268,12.07357],[102.70226,12.17158],[102.74139,12.46474],[102.53128,12.68857],[102.49557,12.9256],[102.49763,13.0064],[102.4597,13.08199],[102.43412,13.09026],[102.39155,13.16407],[102.35481,13.29341],[102.35893,13.30945],[102.34503,13.34837],[102.35928,13.39797],[102.3567,13.48095],[102.36168,13.50582],[102.33559,13.53787],[102.33971,13.56023],[102.35498,13.5649],[102.36511,13.5785],[102.40047,13.5679],[102.42537,13.56891],[102.44614,13.56123],[102.48047,13.57091],[102.53849,13.56757],[102.5699,13.58526],[102.57806,13.60486],[102.62501,13.60845],[102.62132,13.61295],[102.60767,13.61562],[102.57231,13.63331],[102.56922,13.64082],[102.54879,13.658],[102.56252,13.68552],[102.5972,13.70803],[102.67084,13.74472],[102.68818,13.75172],[102.7014,13.7684],[102.73161,13.77082],[102.76543,13.85541],[102.78397,13.93207],[102.80388,13.94406],[102.81607,13.96639],[102.90705,14.02119],[102.89726,14.0535],[102.90095,14.0838],[102.92421,14.10744],[102.92378,14.12838],[102.94147,14.15035],[102.92953,14.17952],[103.17535,14.33774],[103.19939,14.32992],[103.68553,14.44],[103.94508,14.34157],[104.05756,14.34589],[104.06636,14.3419],[104.26025,14.37749],[104.50058,14.36984],[104.57817,14.36019],[104.6422,14.42387],[104.66632,14.40234],[104.68357,14.39877],[104.71138,14.43169],[104.72305,14.42188],[104.71687,14.40043],[104.75344,14.40459],[104.80408,14.43867],[104.83429,14.41573],[104.99239,14.3838],[105.05402,14.19783],[105.47905,14.49186],[105.60883,15.0005],[105.46703,15.13005],[105.48866,15.20237],[105.59269,15.2716],[105.58617,15.32823],[105.50308,15.31912],[105.46703,15.33948],[105.49175,15.37921],[105.59372,15.42869],[105.59372,15.50927],[105.60986,15.54871],[105.62616,15.56492],[105.62702,15.59129],[105.63518,15.62742],[105.63612,15.66056],[105.5975,15.72088],[105.49965,15.76681],[105.46291,15.74517],[105.43819,15.75459],[105.40489,15.79424],[105.34241,15.92039],[105.37811,15.98344],[105.39167,15.99136],[105.41931,15.98608],[105.42652,15.99764],[105.41468,16.01661],[105.21263,16.05076],[105.04955,16.10552],[105.01316,16.24401],[104.88235,16.37812],[104.8391,16.45782],[104.77936,16.49041],[104.73919,16.53287],[104.74228,16.62205],[104.76391,16.70953],[104.73953,16.80323],[104.76425,16.85088],[104.73782,16.90968],[104.744,17.0128],[104.81266,17.21853],[104.79841,17.39274],[104.70348,17.52833],[104.46384,17.65515],[104.34368,17.83564],[104.27776,17.8559],[104.22661,17.98069],[104.1116,18.10735],[104.06525,18.21174],[103.97392,18.33823],[103.9286,18.33237],[103.88809,18.29456],[103.85582,18.28673],[103.83659,18.32715],[103.79128,18.3467],[103.70201,18.34214],[103.60931,18.40405],[103.57292,18.40437],[103.51593,18.42978],[103.45963,18.42587],[103.41568,18.44802],[103.30479,18.43206],[103.24265,18.37082],[103.24333,18.34133],[103.29123,18.32357],[103.28899,18.29521],[103.23595,18.28299],[103.16608,18.25511],[103.02429,17.98135],[102.6535,17.83237],[102.40631,17.99963],[102.10968,18.22413],[101.548,17.81538],[101.30493,17.64991],[101.14563,17.46595],[100.95886,17.61654],[101.01757,17.88858],[101.18752,18.05121],[101.16863,18.10409],[101.18134,18.33595],[101.08727,18.38287],[101.05499,18.43988],[101.23215,18.73015],[101.35265,19.04524],[101.25927,19.12733],[101.2373,19.32637],[101.25824,19.58438],[101.11954,19.56836],[101.08898,19.58777],[101.08624,19.59715],[101.03165,19.6185],[100.89844,19.62125],[100.77827,19.49249],[100.63751,19.56432],[100.58258,19.49313],[100.47478,19.5944],[100.42929,19.67152],[100.43341,19.7024],[100.4147,19.7255],[100.40525,19.7646],[100.43907,19.80345],[100.45555,19.84843],[100.50636,19.87264],[100.51709,19.93027],[100.58653,20.1599],[100.56576,20.1757],[100.54945,20.17473],[100.52731,20.14379],[100.51065,20.14895],[100.48697,20.17956],[100.46774,20.196],[100.45246,20.20147],[100.45521,20.22129],[100.44783,20.23546],[100.41607,20.25286],[100.40594,20.28184],[100.38397,20.31082],[100.37556,20.35187],[100.36165,20.35638],[100.35736,20.37408],[100.33195,20.39902],[100.27805,20.40224],[100.25917,20.39677],[100.2475,20.37263],[100.22535,20.35509],[100.22346,20.31839],[100.16579,20.29988],[100.17162,20.24545],[100.10845,20.25221],[100.09266,20.2696],[100.09798,20.31485],[100.07961,20.3678],[99.9567,20.46417],[99.91636,20.44925],[99.90765,20.44977],[99.89121,20.44511],[99.87276,20.44406],[99.86212,20.44326],[99.80186,20.33948],[99.46472,20.3884],[99.56085,20.20035],[99.43691,20.08882],[99.27727,20.11623],[99.06921,20.1101],[98.97789,19.74538],[98.24387,19.68656],[97.85934,19.57014],[97.76733,18.57336],[97.39655,18.47179],[97.62451,18.30238],[97.73849,17.97743],[97.66502,17.87943],[97.90947,17.56745],[98.52951,16.82557],[98.51303,16.69276],[98.69293,16.26873],[98.87421,16.43609],[98.93394,16.3353],[98.84743,16.13356],[98.74512,16.12037],[98.58307,16.07287],[98.5762,15.79754],[98.54736,15.37557],[98.17383,15.15167],[98.3606,14.63674],[99.08295,13.89208],[99.16534,13.72204],[99.18182,13.00723],[99.39331,12.56797],[99.64153,11.78973],[99.32156,11.30266],[98.77859,10.67849],[98.80597,10.47642],[98.76657,10.40459],[98.74924,10.34194],[96.85547,6.40265],[92.42523,20.54794],[92.2728,20.96272],[92.187,21.16],[92.26,21.36],[92.27,21.4328],[92.62,21.43],[92.6,22],[93.22,22.25],[93.4,23.7],[93.34,23.95],[94.155,23.847],[94.17,23.92],[94.25171,24.07405],[94.28,24.23],[94.30175,24.2371],[94.3256,24.2731],[94.6,24.7],[94.78,25.47],[95.2,26],[95.1,26.6],[97.3,27.9],[96.14,29.38],[95.4,29.1],[94.8,29.2],[92.5,27.8],[91.64,27.76],[91.4,28],[89.58,28.18],[88.9,27.32],[88.74,27.47],[88.9,27.86],[88.7,28.1],[88.1,27.87],[85.93,27.942],[81.6,30.5],[81.2,30],[78.73,31.5],[78.77,31.99],[78.4,32.5],[79.3,32.5],[79,34.3],[78.3,34.6],[78,35.5],[76.1,35.8],[76,36.55],[75.15,37],[72.5,36.9],[71.1,36.1],[71.65,35.44],[71.45,35],[70.985,34.54],[71.18,34.36],[71.092,34.118],[70.88,33.97],[70.5,33.94],[69.908,34.04],[69.869,33.96],[70,33.75],[70.13,33.73],[70.34,33.34],[70.013,33.14],[69.57,33.09],[69.24,32.45],[69.3,31.9],[68.1,31.6],[66.393,30.934],[66.2,29.8],[62.5,29.4],[60.87,29.86],[61.53,29.0165],[61.66,28.77],[61.96,28.54],[62.43,28.42],[62.6,28.25],[62.795,28.28],[62.86,27.25],[63.24,27.25],[63.327,27.13],[63.25,27.1],[63.25,26.84],[63.18,26.83],[63.18,26.65],[62.3,26.5],[62.2,26.28],[61.85,26.22],[61.84,25.75],[61.68,25.67],[56.5,-21],[180,-65],[180,-35]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[138.7,46.7],[145.5,44.5],[145.2,43.7],[146,43.3],[142,18],[122,24.3],[138.7,46.7]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-180,7],[-148,7],[-151,-12],[-171.5,-10.75],[-171,-16],[-152,-19],[-180,-55],[-180,7]]]}}];
18620 var dataDriveLeft = {
18622 features: features$1
18625 var en = {"modes":{"add_area":{"title":"Area","description":"Add parks, buildings, lakes or other areas to the map.","tail":"Click on the map to start drawing an area, like a park, lake, or building."},"add_line":{"title":"Line","description":"Add highways, streets, pedestrian paths, canals or other lines to the map.","tail":"Click on the map to start drawing a road, path, or route."},"add_point":{"title":"Point","description":"Add restaurants, monuments, postal boxes or other points to the map.","tail":"Click on the map to add a point."},"browse":{"title":"Browse","description":"Pan and zoom the map."},"draw_area":{"tail":"Click to add nodes to your area. Click the first node to finish the area."},"draw_line":{"tail":"Click to add more nodes to the line. Click on other lines to connect to them, and double-click to end the line."}},"operations":{"add":{"annotation":{"point":"Added a point.","vertex":"Added a node to a way.","relation":"Added a relation."}},"start":{"annotation":{"line":"Started a line.","area":"Started an area."}},"continue":{"key":"A","title":"Continue","description":"Continue this line.","not_eligible":"No line can be continued here.","multiple":"Several lines can be continued here. To choose a line, press the Shift key and click on it to select it.","annotation":{"line":"Continued a line.","area":"Continued an area."}},"cancel_draw":{"annotation":"Canceled drawing."},"change_role":{"annotation":"Changed the role of a relation member."},"change_tags":{"annotation":"Changed tags."},"circularize":{"title":"Circularize","description":{"line":"Make this line circular.","area":"Make this area circular."},"key":"O","annotation":{"line":"Made a line circular.","area":"Made an area circular."},"not_closed":"This can't be made circular because it's not a loop.","too_large":"This can't be made circular because not enough of it is currently visible.","connected_to_hidden":"This can't be made circular because it is connected to a hidden feature."},"orthogonalize":{"title":"Square","description":{"line":"Square the corners of this line.","area":"Square the corners of this area."},"key":"S","annotation":{"line":"Squared the corners of a line.","area":"Squared the corners of an area."},"not_squarish":"This can't be made square because it is not squarish.","too_large":"This can't be made square because not enough of it is currently visible.","connected_to_hidden":"This can't be made square because it is connected to a hidden feature."},"straighten":{"title":"Straighten","description":"Straighten this line.","key":"S","annotation":"Straightened a line.","too_bendy":"This can't be straightened because it bends too much.","connected_to_hidden":"This line can't be straightened because it is connected to a hidden feature."},"delete":{"title":"Delete","description":{"single":"Delete this feature permanently.","multiple":"Delete these features permanently."},"annotation":{"point":"Deleted a point.","vertex":"Deleted a node from a way.","line":"Deleted a line.","area":"Deleted an area.","relation":"Deleted a relation.","multiple":"Deleted {n} features."},"too_large":{"single":"This feature can't be deleted because not enough of it is currently visible.","multiple":"These features can't be deleted because not enough of them are currently visible."},"incomplete_relation":{"single":"This feature can't be deleted because it hasn't been fully downloaded.","multiple":"These features can't be deleted because they haven't been fully downloaded."},"part_of_relation":{"single":"This feature can't be deleted because it is part of a larger relation. You must remove it from the relation first.","multiple":"These features can't be deleted because they are part of larger relations. You must remove them from the relations first."},"connected_to_hidden":{"single":"This feature can't be deleted because it is connected to a hidden feature.","multiple":"These features can't be deleted because some are connected to hidden features."}},"add_member":{"annotation":"Added a member to a relation."},"delete_member":{"annotation":"Removed a member from a relation."},"connect":{"annotation":{"point":"Connected a way to a point.","vertex":"Connected a way to another.","line":"Connected a way to a line.","area":"Connected a way to an area."}},"disconnect":{"title":"Disconnect","description":"Disconnect these lines/areas from each other.","key":"D","annotation":"Disconnected lines/areas.","not_connected":"There aren't enough lines/areas here to disconnect.","connected_to_hidden":"This can't be disconnected because it is connected to a hidden feature.","relation":"This can't be disconnected because it connects members of a relation."},"merge":{"title":"Merge","description":"Merge these features.","key":"C","annotation":"Merged {n} features.","not_eligible":"These features can't be merged.","not_adjacent":"These features can't be merged because their endpoints aren't connected.","restriction":"These features can't be merged because at least one is a member of a \"{relation}\" relation.","incomplete_relation":"These features can't be merged because at least one hasn't been fully downloaded.","conflicting_tags":"These features can't be merged because some of their tags have conflicting values."},"move":{"title":"Move","description":{"single":"Move this feature to a different location.","multiple":"Move these features to a different location."},"key":"M","annotation":{"point":"Moved a point.","vertex":"Moved a node in a way.","line":"Moved a line.","area":"Moved an area.","multiple":"Moved multiple features."},"incomplete_relation":{"single":"This feature can't be moved because it hasn't been fully downloaded.","multiple":"These features can't be moved because they haven't been fully downloaded."},"too_large":{"single":"This feature can't be moved because not enough of it is currently visible.","multiple":"These features can't be moved because not enough of them are currently visible."},"connected_to_hidden":{"single":"This feature can't be moved because it is connected to a hidden feature.","multiple":"These features can't be moved because some are connected to hidden features."}},"reflect":{"title":{"long":"Reflect Long","short":"Reflect Short"},"description":{"long":{"single":"Reflect this feature across its long axis.","multiple":"Reflect these features across their long axis."},"short":{"single":"Reflect this feature across its short axis.","multiple":"Reflect these features across their short axis."}},"key":{"long":"T","short":"Y"},"annotation":{"long":{"single":"Reflected a feature across its long axis.","multiple":"Reflected multiple features across their long axis."},"short":{"single":"Reflected a feature across its short axis.","multiple":"Reflected multiple features across their short axis."}},"incomplete_relation":{"single":"This feature can't be reflected because it hasn't been fully downloaded.","multiple":"These features can't be reflected because they haven't been fully downloaded."},"too_large":{"single":"This feature can't be reflected because not enough of it is currently visible.","multiple":"These features can't be reflected because not enough of them are currently visible."},"connected_to_hidden":{"single":"This feature can't be reflected because it is connected to a hidden feature.","multiple":"These features can't be reflected because some are connected to hidden features."}},"rotate":{"title":"Rotate","description":{"single":"Rotate this feature around its center point.","multiple":"Rotate these features around their center point."},"key":"R","annotation":{"line":"Rotated a line.","area":"Rotated an area.","multiple":"Rotated multiple features."},"incomplete_relation":{"single":"This feature can't be rotated because it hasn't been fully downloaded.","multiple":"These features can't be rotated because they haven't been fully downloaded."},"too_large":{"single":"This feature can't be rotated because not enough of it is currently visible.","multiple":"These features can't be rotated because not enough of them are currently visible."},"connected_to_hidden":{"single":"This feature can't be rotated because it is connected to a hidden feature.","multiple":"These features can't be rotated because some are connected to hidden features."}},"reverse":{"title":"Reverse","description":"Make this line go in the opposite direction.","key":"V","annotation":"Reversed a line."},"split":{"title":"Split","description":{"line":"Split this line into two at this node.","area":"Split the boundary of this area into two.","multiple":"Split the lines/area boundaries at this node into two."},"key":"X","annotation":{"line":"Split a line.","area":"Split an area boundary.","multiple":"Split {n} lines/area boundaries."},"not_eligible":"Lines can't be split at their beginning or end.","multiple_ways":"There are too many lines here to split.","connected_to_hidden":"This can't be split because it is connected to a hidden feature."},"restriction":{"help":{"select":"Click to select a road segment.","toggle":"Click to toggle turn restrictions.","toggle_on":"Click to add a \"{restriction}\" restriction.","toggle_off":"Click to remove the \"{restriction}\" restriction."},"annotation":{"create":"Added a turn restriction","delete":"Deleted a turn restriction"}}},"undo":{"tooltip":"Undo: {action}","nothing":"Nothing to undo."},"redo":{"tooltip":"Redo: {action}","nothing":"Nothing to redo."},"tooltip_keyhint":"Shortcut:","browser_notice":"This editor is supported in Firefox, Chrome, Safari, Opera, and Internet Explorer 11 and above. Please upgrade your browser or use Potlatch 2 to edit the map.","translate":{"translate":"Translate","localized_translation_label":"Multilingual name","localized_translation_language":"Choose language","localized_translation_name":"Name"},"zoom_in_edit":"Zoom in to Edit","login":"login","logout":"logout","loading_auth":"Connecting to OpenStreetMap...","report_a_bug":"Report a bug","help_translate":"Help translate","feature_info":{"hidden_warning":"{count} hidden features","hidden_details":"These features are currently hidden: {details}"},"status":{"error":"Unable to connect to API.","offline":"The API is offline. Please try editing later.","readonly":"The API is read-only. You will need to wait to save your changes.","rateLimit":"The API is limiting anonymous connections. You can fix this by logging in."},"commit":{"title":"Upload to OpenStreetMap","description_placeholder":"Brief description of your contributions (required)","message_label":"Changeset Comment","upload_explanation":"The changes you upload will be visible on all maps that use OpenStreetMap data.","upload_explanation_with_user":"The changes you upload as {user} will be visible on all maps that use OpenStreetMap data.","save":"Upload","cancel":"Cancel","changes":"{count} Changes","warnings":"Warnings","modified":"Modified","deleted":"Deleted","created":"Created","about_changeset_comments":"About changeset comments","about_changeset_comments_link":"//wiki.openstreetmap.org/wiki/Good_changeset_comments","google_warning":"You mentioned Google in this comment: remember that copying from Google Maps is strictly forbidden.","google_warning_link":"http://www.openstreetmap.org/copyright"},"contributors":{"list":"Edits by {users}","truncated_list":"Edits by {users} and {count} others"},"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, return, 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, return, 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 return, 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, return, 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 return, 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 return, 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":""}}}};
18627 var dataImagery = [{"id":"sjcgis.org-Aerials_2013_WM","name":"2013 aerial imagery for San Juan County WA","type":"tms","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/Aerials_2013_WM/MapServer/tile/{zoom}/{y}/{x}","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","description":"Hungary","scaleExtent":[0,17],"polygon":[[[16.1139147,46.8691038],[16.1789749,46.90662],[16.2000429,46.9415079],[16.2217547,46.9355441],[16.2462784,46.9463851],[16.2553226,46.9642125],[16.2764694,46.9626082],[16.290583,47.0139849],[16.3016199,46.9992329],[16.3414618,46.9965225],[16.3505162,47.0106313],[16.3734016,46.9985929],[16.412765,47.00475],[16.4332705,46.9927417],[16.4478119,47.003893],[16.479997,46.9941169],[16.5121988,47.0011695],[16.4635584,47.0322699],[16.4478586,47.0227481],[16.439123,47.029663],[16.445673,47.038872],[16.520323,47.056103],[16.473213,47.0736169],[16.4637199,47.09392],[16.500798,47.110058],[16.500035,47.123295],[16.5295349,47.1287419],[16.5171609,47.1496938],[16.454951,47.1425878],[16.4648728,47.1683349],[16.4555643,47.1875584],[16.4305559,47.1847022],[16.4195013,47.1949147],[16.4189215,47.2107114],[16.4371293,47.2097043],[16.4426335,47.2337117],[16.4313127,47.2527554],[16.4671512,47.2531652],[16.4892319,47.2798885],[16.4646338,47.3338455],[16.4337002,47.3528101],[16.458513,47.3670496],[16.4454619,47.4070195],[16.4831657,47.4093628],[16.4963821,47.3892659],[16.5170941,47.4100218],[16.5749054,47.4054243],[16.5807291,47.4191699],[16.661847,47.455595],[16.6706419,47.47422],[16.6523395,47.500342],[16.6895619,47.510161],[16.7147797,47.540199],[16.663545,47.567733],[16.673199,47.6049544],[16.6595343,47.6061018],[16.652758,47.622852],[16.6314207,47.6283176],[16.5739108,47.619667],[16.5147382,47.6461964],[16.4967504,47.6393149],[16.425464,47.6621679],[16.4437449,47.674205],[16.4480507,47.6964725],[16.4746984,47.6811576],[16.4872245,47.6979767],[16.5521729,47.7225519],[16.5363779,47.736785],[16.5479799,47.751544],[16.6095193,47.7603722],[16.6344148,47.7590843],[16.65729,47.7414879],[16.7209405,47.7353565],[16.7534062,47.6828165],[16.8301587,47.681058],[16.8394284,47.7045139],[16.8668943,47.7211462],[16.876679,47.6876452],[17.0937421,47.7077706],[17.0706562,47.7285366],[17.0516019,47.7938499],[17.0749479,47.8084997],[17.047139,47.8285635],[17.0519452,47.8377691],[17.0105513,47.8581765],[17.0163878,47.8673325],[17.0857537,47.8746239],[17.113171,47.9271605],[17.0917133,47.9342916],[17.1183782,47.9601083],[17.094657,47.9708775],[17.2010289,48.019992],[17.241769,48.0224651],[17.257955,47.998655],[17.334651,47.993125],[17.4029929,47.947849],[17.4539199,47.8852579],[17.5267369,47.865509],[17.5675779,47.8151289],[17.608402,47.8218859],[17.7085789,47.756678],[17.7798739,47.739487],[17.8660959,47.74575],[17.9001292,47.7392633],[17.946867,47.744668],[17.9708709,47.7578392],[18.0044103,47.7463402],[18.0380583,47.7576812],[18.2958774,47.7314616],[18.4540681,47.7651226],[18.4931553,47.7527552],[18.5590761,47.7659963],[18.6460866,47.7590921],[18.7260691,47.7890411],[18.7411784,47.8138245],[18.7920013,47.8230869],[18.8485417,47.8167221],[18.855876,47.826077],[18.828014,47.834291],[18.8135749,47.85555],[18.76353,47.8716049],[18.756858,47.896838],[18.776746,47.955092],[18.7552499,47.9763469],[18.8157429,47.993442],[18.819998,48.039676],[18.833268,48.048239],[18.8749364,48.0470707],[18.886674,48.058682],[18.9089819,48.051139],[18.9439039,48.058865],[18.9816099,48.0536009],[19.0148639,48.078179],[19.0585249,48.0573529],[19.0843619,48.072781],[19.107402,48.065596],[19.1352889,48.074146],[19.2413679,48.0536529],[19.2557819,48.0715559],[19.3031119,48.088711],[19.3865969,48.091914],[19.400018,48.082304],[19.454053,48.101436],[19.467354,48.083933],[19.4944199,48.109906],[19.492377,48.1396639],[19.5128219,48.154663],[19.504518,48.173443],[19.528967,48.190358],[19.526044,48.20313],[19.577502,48.2160149],[19.6308263,48.2500725],[19.6445239,48.2391719],[19.669857,48.239212],[19.691219,48.203894],[19.721125,48.201473],[19.74618,48.2165119],[19.7871629,48.19253],[19.7987329,48.19482],[19.8052829,48.183733],[19.782415,48.165039],[19.794812,48.153529],[19.821331,48.169081],[19.8452819,48.162742],[19.8551729,48.178431],[19.8601309,48.169409],[19.898745,48.1663119],[19.9145359,48.146863],[19.898298,48.1249019],[19.937383,48.131118],[19.9743939,48.1660049],[19.988706,48.1621679],[20.029038,48.1776849],[20.049449,48.1671999],[20.0729859,48.179606],[20.0700369,48.1917019],[20.1340909,48.225182],[20.1331879,48.253982],[20.206162,48.250979],[20.2038299,48.261906],[20.228466,48.262779],[20.2349469,48.279933],[20.286858,48.26164],[20.3257109,48.272794],[20.3374649,48.301667],[20.3656579,48.316606],[20.384077,48.3511809],[20.4098349,48.365857],[20.402532,48.382565],[20.4205349,48.403858],[20.416228,48.418536],[20.507929,48.489363],[20.5065069,48.534415],[20.537471,48.527878],[20.5464939,48.544292],[20.586595,48.535759],[20.6538739,48.561413],[20.836359,48.58284],[20.8378,48.57421],[20.8504359,48.5816329],[20.8453301,48.5665046],[20.8681549,48.551818],[20.922323,48.559453],[20.9346349,48.538341],[20.955882,48.533963],[20.9561979,48.521666],[20.9815849,48.5177669],[21.0151139,48.532313],[21.0663209,48.525894],[21.1174479,48.4910549],[21.1608749,48.521499],[21.179634,48.518232],[21.221061,48.537497],[21.305488,48.5222489],[21.313377,48.550841],[21.326875,48.554129],[21.319384,48.561201],[21.4154499,48.558951],[21.4226649,48.578821],[21.4406099,48.585104],[21.514091,48.551065],[21.5420199,48.508395],[21.6139329,48.509416],[21.6201879,48.469826],[21.663549,48.417961],[21.6645609,48.392164],[21.7017409,48.380695],[21.711871,48.357617],[21.8174139,48.332787],[21.8352029,48.3346409],[21.837213,48.363253],[21.8842979,48.356047],[21.8848429,48.367539],[21.897883,48.36256],[21.8997959,48.3702229],[21.9281859,48.3615969],[21.9268059,48.370899],[21.949198,48.378728],[21.994463,48.377323],[22.0213259,48.392749],[22.0546049,48.377528],[22.0764859,48.387241],[22.086743,48.371564],[22.1359089,48.380519],[22.131056,48.3912329],[22.152768,48.3962409],[22.1561913,48.4093076],[22.2125722,48.4256468],[22.2371405,48.4100396],[22.2654858,48.4098675],[22.2398761,48.3870055],[22.2675722,48.3611612],[22.3178106,48.3545437],[22.3132861,48.3250712],[22.3372944,48.3079113],[22.3384267,48.2792074],[22.3847547,48.2339632],[22.4006407,48.249198],[22.4328384,48.2525166],[22.456386,48.2423109],[22.4899029,48.2534237],[22.4972201,48.2395546],[22.5161491,48.237965],[22.5311088,48.2094282],[22.5711442,48.1961428],[22.5616362,48.1816066],[22.5982449,48.144756],[22.5902763,48.1073414],[22.6754492,48.091997],[22.7347192,48.119848],[22.7576242,48.1200599],[22.7703914,48.1090162],[22.772319,48.1218742],[22.8027688,48.1221112],[22.8025285,48.1070813],[22.8254256,48.1175119],[22.8364365,48.080249],[22.8611284,48.0750312],[22.8677955,48.0524256],[22.8820424,48.0548053],[22.8659692,48.0113165],[22.835562,47.9905988],[22.8407599,47.9813636],[22.8725729,47.9752683],[22.8697274,47.9659593],[22.8915652,47.9672446],[22.897435,47.9540629],[22.8473299,47.9077579],[22.7928135,47.8908586],[22.7586924,47.8941446],[22.77775,47.8422508],[22.7136344,47.8360928],[22.6801938,47.7877527],[22.6111171,47.7717455],[22.5490018,47.7722246],[22.4812121,47.8108886],[22.4513078,47.803389],[22.4313319,47.7398119],[22.3566167,47.7486206],[22.3177714,47.7660887],[22.3176236,47.7433657],[22.2851369,47.7292757],[22.264325,47.7310675],[22.2589955,47.6979057],[22.2306796,47.693196],[22.1796501,47.5916115],[22.1289245,47.5978984],[22.0942787,47.5583628],[22.0782587,47.5621299],[22.0534529,47.5474795],[22.0712176,47.5380742],[22.0617872,47.5288029],[22.0451278,47.5398919],[22.0367222,47.5326653],[22.0071886,47.48362],[22.0327909,47.4508372],[22.0238835,47.3908631],[22.0119849,47.3758016],[21.9627373,47.381053],[21.9382461,47.3725317],[21.8777922,47.2857763],[21.8872845,47.2730473],[21.8534909,47.2397622],[21.8580662,47.1873597],[21.8124804,47.1667511],[21.7924092,47.1059751],[21.7268258,47.0983882],[21.6976037,47.057915],[21.6504151,47.0408303],[21.6888701,47.0019977],[21.6678744,46.9712337],[21.6814917,46.9652089],[21.6381964,46.9330487],[21.5984455,46.9274708],[21.6142857,46.8867275],[21.6016694,46.8668202],[21.520328,46.8373749],[21.5186086,46.8000703],[21.4831761,46.7650246],[21.5263389,46.7393249],[21.529369,46.7209721],[21.4923253,46.6859652],[21.4728438,46.6959075],[21.4299047,46.693937],[21.4309553,46.6781367],[21.4546661,46.660863],[21.4162375,46.6426231],[21.4097959,46.6218052],[21.3657038,46.6379501],[21.3300499,46.6318155],[21.3139733,46.617666],[21.3012351,46.5908672],[21.3207905,46.5828562],[21.2743045,46.5407362],[21.2600254,46.5021583],[21.2744188,46.4767333],[21.2964506,46.4762973],[21.3174343,46.4507288],[21.2895176,46.4154784],[21.2963256,46.4069601],[21.2250116,46.4136899],[21.2064214,46.4033825],[21.1992563,46.3479034],[21.1762269,46.3357664],[21.180497,46.3044494],[21.1155437,46.3018529],[21.1030549,46.2624637],[21.0708792,46.2539014],[21.0660827,46.2429394],[21.0366237,46.2480392],[21.0246723,46.2665329],[20.960817,46.2623039],[20.9465849,46.2793024],[20.9250701,46.2766191],[20.9218133,46.2618129],[20.8732713,46.2877555],[20.7756538,46.2759602],[20.7490474,46.2508489],[20.7618619,46.204563],[20.727401,46.2077485],[20.7341052,46.1939355],[20.7140487,46.1660531],[20.6843592,46.1447802],[20.6549178,46.1497739],[20.6394471,46.1267602],[20.5450486,46.1790935],[20.5014839,46.190334],[20.4949436,46.1709908],[20.4592293,46.1428837],[20.3975133,46.1574709],[20.3685325,46.1528554],[20.3557074,46.1696256],[20.2968136,46.1521542],[20.2549024,46.1158522],[20.2484757,46.1300956],[20.2330132,46.1241668],[20.1817362,46.1601137],[20.1364966,46.1449476],[20.1009667,46.1772756],[20.0636156,46.1437275],[20.0346142,46.1458888],[20.0158072,46.1768354],[19.9354075,46.1764243],[19.8533469,46.1500005],[19.8179747,46.1281652],[19.7585403,46.1479754],[19.6982054,46.1879317],[19.6827672,46.1800388],[19.661508,46.1904394],[19.6317396,46.1692993],[19.5676482,46.179106],[19.5604013,46.1665762],[19.5026585,46.1424492],[19.5271208,46.1210269],[19.4645033,46.0953827],[19.4665828,46.0820437],[19.4160037,46.0460453],[19.3803957,46.0358749],[19.3640923,46.0522965],[19.2819012,46.0148048],[19.2965348,45.9881173],[19.2856472,45.9968981],[19.1479857,45.9963445],[19.1338422,46.0370993],[19.104873,46.0401673],[19.0660427,46.0001999],[19.0796791,45.9636376],[19.0059803,45.9590674],[19.0092745,45.9236559],[18.9061334,45.9353801],[18.8794572,45.9166827],[18.8647137,45.9208493],[18.8685629,45.9113361],[18.8276792,45.9051714],[18.8220041,45.9145893],[18.8075092,45.9036055],[18.809247,45.8796189],[18.7956242,45.8784488],[18.7048857,45.9181883],[18.6700246,45.9108439],[18.6596602,45.9168934],[18.6651348,45.899279],[18.6412808,45.8890396],[18.6550179,45.8742393],[18.6277704,45.8733782],[18.6148449,45.8531438],[18.6236656,45.8398531],[18.5732391,45.8137578],[18.5749849,45.8004344],[18.559716,45.8037961],[18.5223504,45.7826858],[18.4906706,45.7947167],[18.4821905,45.7655032],[18.4562828,45.7695229],[18.4450763,45.7605195],[18.446853,45.737128],[18.40763,45.7397119],[18.3918949,45.7616983],[18.3642257,45.7729364],[18.3394214,45.7471605],[18.2968157,45.7612196],[18.2440473,45.7612305],[18.2307311,45.7790328],[18.1908702,45.7878759],[18.1681939,45.7762712],[18.1246514,45.7896277],[18.1068067,45.7708256],[18.0818922,45.7645205],[17.9958808,45.7957311],[17.9302095,45.7863301],[17.9066757,45.7925692],[17.8653145,45.7670064],[17.8262748,45.8099957],[17.8089784,45.8040989],[17.7809054,45.8174884],[17.7603399,45.811923],[17.7408624,45.8295975],[17.6632915,45.8381849],[17.6276211,45.8979446],[17.5700676,45.9358204],[17.4378254,45.9503823],[17.4258964,45.9272681],[17.4108059,45.9399665],[17.392149,45.9302149],[17.3828713,45.9475733],[17.3476208,45.9423413],[17.3438769,45.9605329],[17.3537711,45.9525011],[17.3905375,45.9581914],[17.387423,45.9661823],[17.3583539,45.9642737],[17.3754852,45.9686921],[17.3751895,45.9881054],[17.3635685,45.9915442],[17.3567202,45.9735836],[17.3339583,45.9960781],[17.3319847,45.9728948],[17.3129974,45.9665347],[17.323647,45.9887776],[17.2987653,45.9838652],[17.3041996,46.0021128],[17.2579726,46.0110256],[17.29632,46.0285169],[17.2541514,46.030005],[17.270955,46.0567055],[17.2324767,46.0592034],[17.2525145,46.0664725],[17.2313144,46.0790345],[17.2019916,46.0765488],[17.2331299,46.0989644],[17.2104017,46.1001693],[17.2129734,46.113855],[17.175927,46.1084583],[17.1743424,46.1287608],[17.1865197,46.1332308],[17.1810983,46.1505485],[17.1562307,46.1585819],[17.1592857,46.1696818],[17.1261012,46.1684495],[17.1227409,46.1789791],[17.0752482,46.1889531],[17.0661614,46.2022984],[16.9735401,46.2251982],[16.973954,46.2431113],[16.9504085,46.2415285],[16.8862356,46.2814598],[16.8713682,46.3252767],[16.8802109,46.3356966],[16.8615374,46.3452401],[16.8656232,46.3556489],[16.8521959,46.3517189],[16.8498589,46.3626245],[16.8352859,46.3638195],[16.8376499,46.3748032],[16.8261732,46.3670994],[16.7933444,46.387385],[16.7592072,46.3776563],[16.7298672,46.40149],[16.7182119,46.3898704],[16.6772872,46.4494536],[16.6631785,46.4486958],[16.6663732,46.4582995],[16.6187915,46.4619875],[16.604468,46.4760773],[16.5235997,46.5053761],[16.5325768,46.5314027],[16.5176728,46.5363516],[16.5084107,46.5652692],[16.4829969,46.5660383],[16.4834008,46.5786011],[16.4455713,46.610952],[16.4248583,46.6131645],[16.385941,46.6442485],[16.3915424,46.6637257],[16.4198454,46.6584771],[16.4286335,46.6939737],[16.3689211,46.7040082],[16.3798266,46.7153869],[16.3710856,46.7222945],[16.3570587,46.7142387],[16.3185954,46.7541449],[16.3305417,46.7752119],[16.3121626,46.7780033],[16.3127666,46.797314],[16.3406373,46.8051851],[16.3508404,46.8300552],[16.3403309,46.8468762],[16.3015007,46.8595142],[16.2913867,46.8728341],[16.2332296,46.8766702],[16.1560866,46.8537074],[16.126571,46.8569079],[16.1139147,46.8691038]]],"terms_url":"http://www.fomi.hu/","terms_text":"Földmérési és Távérzékelési Intézet"},{"id":"FOMI_2005","name":"FÖMI orthophoto 2005","type":"tms","template":"http://e.tile.openstreetmap.hu/ortofoto2005/{zoom}/{x}/{y}.jpg","description":"Hungary","scaleExtent":[0,17],"polygon":[[[16.1139147,46.8691038],[16.1789749,46.90662],[16.2000429,46.9415079],[16.2217547,46.9355441],[16.2462784,46.9463851],[16.2553226,46.9642125],[16.2764694,46.9626082],[16.290583,47.0139849],[16.3016199,46.9992329],[16.3414618,46.9965225],[16.3505162,47.0106313],[16.3734016,46.9985929],[16.412765,47.00475],[16.4332705,46.9927417],[16.4478119,47.003893],[16.479997,46.9941169],[16.5121988,47.0011695],[16.4635584,47.0322699],[16.4478586,47.0227481],[16.439123,47.029663],[16.445673,47.038872],[16.520323,47.056103],[16.473213,47.0736169],[16.4637199,47.09392],[16.500798,47.110058],[16.500035,47.123295],[16.5295349,47.1287419],[16.5171609,47.1496938],[16.454951,47.1425878],[16.4648728,47.1683349],[16.4555643,47.1875584],[16.4305559,47.1847022],[16.4195013,47.1949147],[16.4189215,47.2107114],[16.4371293,47.2097043],[16.4426335,47.2337117],[16.4313127,47.2527554],[16.4671512,47.2531652],[16.4892319,47.2798885],[16.4646338,47.3338455],[16.4337002,47.3528101],[16.458513,47.3670496],[16.4454619,47.4070195],[16.4831657,47.4093628],[16.4963821,47.3892659],[16.5170941,47.4100218],[16.5749054,47.4054243],[16.5807291,47.4191699],[16.661847,47.455595],[16.6706419,47.47422],[16.6523395,47.500342],[16.6895619,47.510161],[16.7147797,47.540199],[16.663545,47.567733],[16.673199,47.6049544],[16.6595343,47.6061018],[16.652758,47.622852],[16.6314207,47.6283176],[16.5739108,47.619667],[16.5147382,47.6461964],[16.4967504,47.6393149],[16.425464,47.6621679],[16.4437449,47.674205],[16.4480507,47.6964725],[16.4746984,47.6811576],[16.4872245,47.6979767],[16.5521729,47.7225519],[16.5363779,47.736785],[16.5479799,47.751544],[16.6095193,47.7603722],[16.6344148,47.7590843],[16.65729,47.7414879],[16.7209405,47.7353565],[16.7534062,47.6828165],[16.8301587,47.681058],[16.8394284,47.7045139],[16.8668943,47.7211462],[16.876679,47.6876452],[17.0937421,47.7077706],[17.0706562,47.7285366],[17.0516019,47.7938499],[17.0749479,47.8084997],[17.047139,47.8285635],[17.0519452,47.8377691],[17.0105513,47.8581765],[17.0163878,47.8673325],[17.0857537,47.8746239],[17.113171,47.9271605],[17.0917133,47.9342916],[17.1183782,47.9601083],[17.094657,47.9708775],[17.2010289,48.019992],[17.241769,48.0224651],[17.257955,47.998655],[17.334651,47.993125],[17.4029929,47.947849],[17.4539199,47.8852579],[17.5267369,47.865509],[17.5675779,47.8151289],[17.608402,47.8218859],[17.7085789,47.756678],[17.7798739,47.739487],[17.8660959,47.74575],[17.9001292,47.7392633],[17.946867,47.744668],[17.9708709,47.7578392],[18.0044103,47.7463402],[18.0380583,47.7576812],[18.2958774,47.7314616],[18.4540681,47.7651226],[18.4931553,47.7527552],[18.5590761,47.7659963],[18.6460866,47.7590921],[18.7260691,47.7890411],[18.7411784,47.8138245],[18.7920013,47.8230869],[18.8485417,47.8167221],[18.855876,47.826077],[18.828014,47.834291],[18.8135749,47.85555],[18.76353,47.8716049],[18.756858,47.896838],[18.776746,47.955092],[18.7552499,47.9763469],[18.8157429,47.993442],[18.819998,48.039676],[18.833268,48.048239],[18.8749364,48.0470707],[18.886674,48.058682],[18.9089819,48.051139],[18.9439039,48.058865],[18.9816099,48.0536009],[19.0148639,48.078179],[19.0585249,48.0573529],[19.0843619,48.072781],[19.107402,48.065596],[19.1352889,48.074146],[19.2413679,48.0536529],[19.2557819,48.0715559],[19.3031119,48.088711],[19.3865969,48.091914],[19.400018,48.082304],[19.454053,48.101436],[19.467354,48.083933],[19.4944199,48.109906],[19.492377,48.1396639],[19.5128219,48.154663],[19.504518,48.173443],[19.528967,48.190358],[19.526044,48.20313],[19.577502,48.2160149],[19.6308263,48.2500725],[19.6445239,48.2391719],[19.669857,48.239212],[19.691219,48.203894],[19.721125,48.201473],[19.74618,48.2165119],[19.7871629,48.19253],[19.7987329,48.19482],[19.8052829,48.183733],[19.782415,48.165039],[19.794812,48.153529],[19.821331,48.169081],[19.8452819,48.162742],[19.8551729,48.178431],[19.8601309,48.169409],[19.898745,48.1663119],[19.9145359,48.146863],[19.898298,48.1249019],[19.937383,48.131118],[19.9743939,48.1660049],[19.988706,48.1621679],[20.029038,48.1776849],[20.049449,48.1671999],[20.0729859,48.179606],[20.0700369,48.1917019],[20.1340909,48.225182],[20.1331879,48.253982],[20.206162,48.250979],[20.2038299,48.261906],[20.228466,48.262779],[20.2349469,48.279933],[20.286858,48.26164],[20.3257109,48.272794],[20.3374649,48.301667],[20.3656579,48.316606],[20.384077,48.3511809],[20.4098349,48.365857],[20.402532,48.382565],[20.4205349,48.403858],[20.416228,48.418536],[20.507929,48.489363],[20.5065069,48.534415],[20.537471,48.527878],[20.5464939,48.544292],[20.586595,48.535759],[20.6538739,48.561413],[20.836359,48.58284],[20.8378,48.57421],[20.8504359,48.5816329],[20.8453301,48.5665046],[20.8681549,48.551818],[20.922323,48.559453],[20.9346349,48.538341],[20.955882,48.533963],[20.9561979,48.521666],[20.9815849,48.5177669],[21.0151139,48.532313],[21.0663209,48.525894],[21.1174479,48.4910549],[21.1608749,48.521499],[21.179634,48.518232],[21.221061,48.537497],[21.305488,48.5222489],[21.313377,48.550841],[21.326875,48.554129],[21.319384,48.561201],[21.4154499,48.558951],[21.4226649,48.578821],[21.4406099,48.585104],[21.514091,48.551065],[21.5420199,48.508395],[21.6139329,48.509416],[21.6201879,48.469826],[21.663549,48.417961],[21.6645609,48.392164],[21.7017409,48.380695],[21.711871,48.357617],[21.8174139,48.332787],[21.8352029,48.3346409],[21.837213,48.363253],[21.8842979,48.356047],[21.8848429,48.367539],[21.897883,48.36256],[21.8997959,48.3702229],[21.9281859,48.3615969],[21.9268059,48.370899],[21.949198,48.378728],[21.994463,48.377323],[22.0213259,48.392749],[22.0546049,48.377528],[22.0764859,48.387241],[22.086743,48.371564],[22.1359089,48.380519],[22.131056,48.3912329],[22.152768,48.3962409],[22.1561913,48.4093076],[22.2125722,48.4256468],[22.2371405,48.4100396],[22.2654858,48.4098675],[22.2398761,48.3870055],[22.2675722,48.3611612],[22.3178106,48.3545437],[22.3132861,48.3250712],[22.3372944,48.3079113],[22.3384267,48.2792074],[22.3847547,48.2339632],[22.4006407,48.249198],[22.4328384,48.2525166],[22.456386,48.2423109],[22.4899029,48.2534237],[22.4972201,48.2395546],[22.5161491,48.237965],[22.5311088,48.2094282],[22.5711442,48.1961428],[22.5616362,48.1816066],[22.5982449,48.144756],[22.5902763,48.1073414],[22.6754492,48.091997],[22.7347192,48.119848],[22.7576242,48.1200599],[22.7703914,48.1090162],[22.772319,48.1218742],[22.8027688,48.1221112],[22.8025285,48.1070813],[22.8254256,48.1175119],[22.8364365,48.080249],[22.8611284,48.0750312],[22.8677955,48.0524256],[22.8820424,48.0548053],[22.8659692,48.0113165],[22.835562,47.9905988],[22.8407599,47.9813636],[22.8725729,47.9752683],[22.8697274,47.9659593],[22.8915652,47.9672446],[22.897435,47.9540629],[22.8473299,47.9077579],[22.7928135,47.8908586],[22.7586924,47.8941446],[22.77775,47.8422508],[22.7136344,47.8360928],[22.6801938,47.7877527],[22.6111171,47.7717455],[22.5490018,47.7722246],[22.4812121,47.8108886],[22.4513078,47.803389],[22.4313319,47.7398119],[22.3566167,47.7486206],[22.3177714,47.7660887],[22.3176236,47.7433657],[22.2851369,47.7292757],[22.264325,47.7310675],[22.2589955,47.6979057],[22.2306796,47.693196],[22.1796501,47.5916115],[22.1289245,47.5978984],[22.0942787,47.5583628],[22.0782587,47.5621299],[22.0534529,47.5474795],[22.0712176,47.5380742],[22.0617872,47.5288029],[22.0451278,47.5398919],[22.0367222,47.5326653],[22.0071886,47.48362],[22.0327909,47.4508372],[22.0238835,47.3908631],[22.0119849,47.3758016],[21.9627373,47.381053],[21.9382461,47.3725317],[21.8777922,47.2857763],[21.8872845,47.2730473],[21.8534909,47.2397622],[21.8580662,47.1873597],[21.8124804,47.1667511],[21.7924092,47.1059751],[21.7268258,47.0983882],[21.6976037,47.057915],[21.6504151,47.0408303],[21.6888701,47.0019977],[21.6678744,46.9712337],[21.6814917,46.9652089],[21.6381964,46.9330487],[21.5984455,46.9274708],[21.6142857,46.8867275],[21.6016694,46.8668202],[21.520328,46.8373749],[21.5186086,46.8000703],[21.4831761,46.7650246],[21.5263389,46.7393249],[21.529369,46.7209721],[21.4923253,46.6859652],[21.4728438,46.6959075],[21.4299047,46.693937],[21.4309553,46.6781367],[21.4546661,46.660863],[21.4162375,46.6426231],[21.4097959,46.6218052],[21.3657038,46.6379501],[21.3300499,46.6318155],[21.3139733,46.617666],[21.3012351,46.5908672],[21.3207905,46.5828562],[21.2743045,46.5407362],[21.2600254,46.5021583],[21.2744188,46.4767333],[21.2964506,46.4762973],[21.3174343,46.4507288],[21.2895176,46.4154784],[21.2963256,46.4069601],[21.2250116,46.4136899],[21.2064214,46.4033825],[21.1992563,46.3479034],[21.1762269,46.3357664],[21.180497,46.3044494],[21.1155437,46.3018529],[21.1030549,46.2624637],[21.0708792,46.2539014],[21.0660827,46.2429394],[21.0366237,46.2480392],[21.0246723,46.2665329],[20.960817,46.2623039],[20.9465849,46.2793024],[20.9250701,46.2766191],[20.9218133,46.2618129],[20.8732713,46.2877555],[20.7756538,46.2759602],[20.7490474,46.2508489],[20.7618619,46.204563],[20.727401,46.2077485],[20.7341052,46.1939355],[20.7140487,46.1660531],[20.6843592,46.1447802],[20.6549178,46.1497739],[20.6394471,46.1267602],[20.5450486,46.1790935],[20.5014839,46.190334],[20.4949436,46.1709908],[20.4592293,46.1428837],[20.3975133,46.1574709],[20.3685325,46.1528554],[20.3557074,46.1696256],[20.2968136,46.1521542],[20.2549024,46.1158522],[20.2484757,46.1300956],[20.2330132,46.1241668],[20.1817362,46.1601137],[20.1364966,46.1449476],[20.1009667,46.1772756],[20.0636156,46.1437275],[20.0346142,46.1458888],[20.0158072,46.1768354],[19.9354075,46.1764243],[19.8533469,46.1500005],[19.8179747,46.1281652],[19.7585403,46.1479754],[19.6982054,46.1879317],[19.6827672,46.1800388],[19.661508,46.1904394],[19.6317396,46.1692993],[19.5676482,46.179106],[19.5604013,46.1665762],[19.5026585,46.1424492],[19.5271208,46.1210269],[19.4645033,46.0953827],[19.4665828,46.0820437],[19.4160037,46.0460453],[19.3803957,46.0358749],[19.3640923,46.0522965],[19.2819012,46.0148048],[19.2965348,45.9881173],[19.2856472,45.9968981],[19.1479857,45.9963445],[19.1338422,46.0370993],[19.104873,46.0401673],[19.0660427,46.0001999],[19.0796791,45.9636376],[19.0059803,45.9590674],[19.0092745,45.9236559],[18.9061334,45.9353801],[18.8794572,45.9166827],[18.8647137,45.9208493],[18.8685629,45.9113361],[18.8276792,45.9051714],[18.8220041,45.9145893],[18.8075092,45.9036055],[18.809247,45.8796189],[18.7956242,45.8784488],[18.7048857,45.9181883],[18.6700246,45.9108439],[18.6596602,45.9168934],[18.6651348,45.899279],[18.6412808,45.8890396],[18.6550179,45.8742393],[18.6277704,45.8733782],[18.6148449,45.8531438],[18.6236656,45.8398531],[18.5732391,45.8137578],[18.5749849,45.8004344],[18.559716,45.8037961],[18.5223504,45.7826858],[18.4906706,45.7947167],[18.4821905,45.7655032],[18.4562828,45.7695229],[18.4450763,45.7605195],[18.446853,45.737128],[18.40763,45.7397119],[18.3918949,45.7616983],[18.3642257,45.7729364],[18.3394214,45.7471605],[18.2968157,45.7612196],[18.2440473,45.7612305],[18.2307311,45.7790328],[18.1908702,45.7878759],[18.1681939,45.7762712],[18.1246514,45.7896277],[18.1068067,45.7708256],[18.0818922,45.7645205],[17.9958808,45.7957311],[17.9302095,45.7863301],[17.9066757,45.7925692],[17.8653145,45.7670064],[17.8262748,45.8099957],[17.8089784,45.8040989],[17.7809054,45.8174884],[17.7603399,45.811923],[17.7408624,45.8295975],[17.6632915,45.8381849],[17.6276211,45.8979446],[17.5700676,45.9358204],[17.4378254,45.9503823],[17.4258964,45.9272681],[17.4108059,45.9399665],[17.392149,45.9302149],[17.3828713,45.9475733],[17.3476208,45.9423413],[17.3438769,45.9605329],[17.3537711,45.9525011],[17.3905375,45.9581914],[17.387423,45.9661823],[17.3583539,45.9642737],[17.3754852,45.9686921],[17.3751895,45.9881054],[17.3635685,45.9915442],[17.3567202,45.9735836],[17.3339583,45.9960781],[17.3319847,45.9728948],[17.3129974,45.9665347],[17.323647,45.9887776],[17.2987653,45.9838652],[17.3041996,46.0021128],[17.2579726,46.0110256],[17.29632,46.0285169],[17.2541514,46.030005],[17.270955,46.0567055],[17.2324767,46.0592034],[17.2525145,46.0664725],[17.2313144,46.0790345],[17.2019916,46.0765488],[17.2331299,46.0989644],[17.2104017,46.1001693],[17.2129734,46.113855],[17.175927,46.1084583],[17.1743424,46.1287608],[17.1865197,46.1332308],[17.1810983,46.1505485],[17.1562307,46.1585819],[17.1592857,46.1696818],[17.1261012,46.1684495],[17.1227409,46.1789791],[17.0752482,46.1889531],[17.0661614,46.2022984],[16.9735401,46.2251982],[16.973954,46.2431113],[16.9504085,46.2415285],[16.8862356,46.2814598],[16.8713682,46.3252767],[16.8802109,46.3356966],[16.8615374,46.3452401],[16.8656232,46.3556489],[16.8521959,46.3517189],[16.8498589,46.3626245],[16.8352859,46.3638195],[16.8376499,46.3748032],[16.8261732,46.3670994],[16.7933444,46.387385],[16.7592072,46.3776563],[16.7298672,46.40149],[16.7182119,46.3898704],[16.6772872,46.4494536],[16.6631785,46.4486958],[16.6663732,46.4582995],[16.6187915,46.4619875],[16.604468,46.4760773],[16.5235997,46.5053761],[16.5325768,46.5314027],[16.5176728,46.5363516],[16.5084107,46.5652692],[16.4829969,46.5660383],[16.4834008,46.5786011],[16.4455713,46.610952],[16.4248583,46.6131645],[16.385941,46.6442485],[16.3915424,46.6637257],[16.4198454,46.6584771],[16.4286335,46.6939737],[16.3689211,46.7040082],[16.3798266,46.7153869],[16.3710856,46.7222945],[16.3570587,46.7142387],[16.3185954,46.7541449],[16.3305417,46.7752119],[16.3121626,46.7780033],[16.3127666,46.797314],[16.3406373,46.8051851],[16.3508404,46.8300552],[16.3403309,46.8468762],[16.3015007,46.8595142],[16.2913867,46.8728341],[16.2332296,46.8766702],[16.1560866,46.8537074],[16.126571,46.8569079],[16.1139147,46.8691038]]],"terms_url":"http://www.fomi.hu/","terms_text":"Földmérési és Távérzékelési Intézet"},{"id":"FR-BAN","name":"FR-BAN","type":"tms","template":"http://{switch:a,b,c}.layers.openstreetmap.fr/bano/{zoom}/{x}/{y}.png","description":"French address registry or Base Adresses Nationale","scaleExtent":[12,20],"polygon":[[[8.3247852,49.0891892],[6.1566882,49.6167369],[4.8666714,50.2126152],[2.4937064,51.1761675],[1.3121526,50.9324682],[1.2659981,50.1877492],[0.1121369,49.8258592],[-0.3494075,49.4312336],[-1.0232625,49.4852345],[-1.3278818,49.7901162],[-2.1032765,49.7901162],[-1.6232703,48.7420657],[-3.1002126,48.9728514],[-5.1125465,48.6811558],[-5.3525496,48.4367783],[-4.5984193,47.7194959],[-2.555398,47.0232784],[-2.4738077,46.6638823],[-1.6676954,46.1055717],[-1.334807,45.5141125],[-1.4914604,44.1627003],[-1.9940567,43.3708146],[-0.956228,42.7364747],[2.2029487,42.2841894],[3.2342502,42.5444129],[3.2407774,43.1140543],[4.0436261,43.3280964],[6.4325902,42.808345],[7.6270723,43.5934102],[7.8163619,44.1720643],[7.0396221,44.41967],[7.268075,45.4958141],[7.1244761,46.2140775],[6.5631347,46.771283],[7.6571492,47.59128],[7.6527839,47.5941813],[7.6224698,47.5776739],[7.6047297,47.578221],[7.5877054,47.5901532],[7.521558,47.65161],[7.503992,47.70235],[7.520958,47.77685],[7.557124,47.84839],[7.549463,47.879205],[7.574615,47.93028],[7.613179,47.96804],[7.611904,47.9871],[7.5612401,48.0383618],[7.574915,48.1258],[7.595338,48.15977],[7.633047,48.19717],[7.662748,48.22473],[7.684659,48.30305],[7.763463,48.49158],[7.8004602,48.5125977],[7.799582,48.5878],[7.834088,48.64439],[7.9121073,48.6889897],[7.9672295,48.7571585],[8.020692,48.78879],[8.043024,48.7956],[8.0864658,48.8130551],[8.1364418,48.8978239],[8.1970586,48.96021],[8.2816129,48.9948995],[8.2996723,49.025966],[8.3124269,49.0599642],[8.3247852,49.0891892]],[[9.3609615,43.1345098],[8.4393174,42.48439],[8.4836272,41.8175373],[8.8469677,41.3768281],[9.2058772,41.3136241],[9.48946,41.5461776],[9.6356823,42.1994563],[9.6046655,42.901254],[9.3609615,43.1345098]]],"terms_url":"https://wiki.openstreetmap.org/wiki/WikiProject_France/WikiProject_Base_Adresses_Nationale_Ouverte_(BANO)","terms_text":"Tiles © cquest@Openstreetmap France, data © OpenStreetMap contributors, ODBL"},{"id":"FR-Cadastre","name":"FR-Cadastre","type":"tms","template":"http://tms.cadastre.openstreetmap.fr/*/tout/{zoom}/{x}/{y}.png","description":"French land registry","scaleExtent":[12,20],"polygon":[[[8.3247852,49.0891892],[6.1566882,49.6167369],[4.8666714,50.2126152],[2.4937064,51.1761675],[1.3121526,50.9324682],[1.2659981,50.1877492],[0.1121369,49.8258592],[-0.3494075,49.4312336],[-1.0232625,49.4852345],[-1.3278818,49.7901162],[-2.1032765,49.7901162],[-1.6232703,48.7420657],[-3.1002126,48.9728514],[-5.1125465,48.6811558],[-5.3525496,48.4367783],[-4.5984193,47.7194959],[-2.555398,47.0232784],[-2.4738077,46.6638823],[-1.6676954,46.1055717],[-1.334807,45.5141125],[-1.4914604,44.1627003],[-1.9940567,43.3708146],[-0.956228,42.7364747],[2.2029487,42.2841894],[3.2342502,42.5444129],[3.2407774,43.1140543],[4.0436261,43.3280964],[6.4325902,42.808345],[7.6270723,43.5934102],[7.8163619,44.1720643],[7.0396221,44.41967],[7.268075,45.4958141],[7.1244761,46.2140775],[6.5631347,46.771283],[7.6571492,47.59128],[7.6527839,47.5941813],[7.6224698,47.5776739],[7.6047297,47.578221],[7.5877054,47.5901532],[7.521558,47.65161],[7.503992,47.70235],[7.520958,47.77685],[7.557124,47.84839],[7.549463,47.879205],[7.574615,47.93028],[7.613179,47.96804],[7.611904,47.9871],[7.5612401,48.0383618],[7.574915,48.1258],[7.595338,48.15977],[7.633047,48.19717],[7.662748,48.22473],[7.684659,48.30305],[7.763463,48.49158],[7.8004602,48.5125977],[7.799582,48.5878],[7.834088,48.64439],[7.9121073,48.6889897],[7.9672295,48.7571585],[8.020692,48.78879],[8.043024,48.7956],[8.0864658,48.8130551],[8.1364418,48.8978239],[8.1970586,48.96021],[8.2816129,48.9948995],[8.2996723,49.025966],[8.3124269,49.0599642],[8.3247852,49.0891892]],[[9.3609615,43.1345098],[8.4393174,42.48439],[8.4836272,41.8175373],[8.8469677,41.3768281],[9.2058772,41.3136241],[9.48946,41.5461776],[9.6356823,42.1994563],[9.6046655,42.901254],[9.3609615,43.1345098]]],"terms_url":"http://wiki.openstreetmap.org/wiki/WikiProject_Cadastre_Fran%C3%A7ais/Conditions_d%27utilisation","terms_text":"cadastre-dgi-fr source : Direction Générale des Impôts - Cadastre. Mise à jour : 2015"},{"id":"Freemap.sk-Car","name":"Freemap.sk Car","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/A/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"id":"Freemap.sk-Cyclo","name":"Freemap.sk Cyclo","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/C/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"id":"Freemap.sk-Hiking","name":"Freemap.sk Hiking","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/T/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"id":"Freemap.sk-Ski","name":"Freemap.sk Ski","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/K/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"id":"Geodatastyrelsen_Denmark","name":"Geodatastyrelsen (Denmark)","type":"tms","template":"http://osmtools.septima.dk/mapproxy/tiles/1.0.0/kortforsyningen_ortoforaar/EPSG3857/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,21],"polygon":[[[8.3743941,54.9551655],[8.3683809,55.4042149],[8.2103997,55.4039795],[8.2087314,55.4937345],[8.0502655,55.4924731],[8.0185123,56.7501399],[8.1819161,56.7509948],[8.1763274,57.0208898],[8.3413329,57.0219872],[8.3392467,57.1119574],[8.5054433,57.1123212],[8.5033923,57.2020499],[9.3316304,57.2027636],[9.3319079,57.2924835],[9.4978864,57.2919578],[9.4988593,57.3820608],[9.6649749,57.3811615],[9.6687295,57.5605591],[9.8351961,57.5596265],[9.8374896,57.6493322],[10.1725726,57.6462818],[10.1754245,57.7367768],[10.5118282,57.7330269],[10.5152095,57.8228945],[10.6834853,57.8207722],[10.6751613,57.6412021],[10.5077045,57.6433097],[10.5039992,57.5535088],[10.671038,57.5514113],[10.6507805,57.1024538],[10.4857673,57.1045138],[10.4786236,56.9249051],[10.3143981,56.9267573],[10.3112341,56.8369269],[10.4750295,56.83509],[10.4649016,56.5656681],[10.9524239,56.5589761],[10.9479249,56.4692243],[11.1099335,56.4664675],[11.1052639,56.376833],[10.9429901,56.3795284],[10.9341235,56.1994768],[10.7719685,56.2020244],[10.7694751,56.1120103],[10.6079695,56.1150259],[10.4466742,56.116717],[10.2865948,56.118675],[10.2831527,56.0281851],[10.4439274,56.0270388],[10.4417713,55.7579243],[10.4334961,55.6693533],[10.743814,55.6646861],[10.743814,55.5712253],[10.8969041,55.5712253],[10.9051793,55.3953852],[11.0613726,55.3812841],[11.0593038,55.1124061],[11.0458567,55.0318621],[11.2030844,55.0247474],[11.2030844,55.117139],[11.0593038,55.1124061],[11.0613726,55.3812841],[11.0789572,55.5712253],[10.8969041,55.5712253],[10.9258671,55.6670198],[10.743814,55.6646861],[10.7562267,55.7579243],[10.4417713,55.7579243],[10.4439274,56.0270388],[10.4466742,56.116717],[10.6079695,56.1150259],[10.6052053,56.0247462],[10.9258671,56.0201215],[10.9197132,55.9309388],[11.0802782,55.92792],[11.0858066,56.0178284],[11.7265047,56.005058],[11.7319981,56.0952142],[12.0540333,56.0871256],[12.0608477,56.1762576],[12.7023469,56.1594405],[12.6611131,55.7114318],[12.9792318,55.7014026],[12.9612912,55.5217294],[12.3268659,55.5412096],[12.3206071,55.4513655],[12.4778226,55.447067],[12.4702432,55.3570479],[12.6269738,55.3523837],[12.6200898,55.2632576],[12.4627339,55.26722],[12.4552949,55.1778223],[12.2987046,55.1822303],[12.2897344,55.0923641],[12.6048608,55.0832904],[12.5872011,54.9036285],[12.2766618,54.9119031],[12.2610181,54.7331602],[12.1070691,54.7378161],[12.0858621,54.4681655],[11.7794953,54.4753579],[11.7837381,54.5654783],[11.1658525,54.5782155],[11.1706443,54.6686508],[10.8617173,54.6733956],[10.8651245,54.7634667],[10.7713646,54.7643888],[10.7707276,54.7372807],[10.7551428,54.7375776],[10.7544039,54.7195666],[10.7389074,54.7197588],[10.7384368,54.7108482],[10.7074486,54.7113045],[10.7041094,54.6756741],[10.5510973,54.6781698],[10.5547184,54.7670245],[10.2423994,54.7705935],[10.2459845,54.8604673],[10.0902268,54.8622134],[10.0873731,54.7723851],[9.1555798,54.7769557],[9.1562752,54.8675369],[8.5321973,54.8663765],[8.531432,54.95516],[8.3743941,54.9551655]],[[11.4577738,56.819554],[11.7849181,56.8127385],[11.7716715,56.6332796],[11.4459621,56.6401087],[11.4577738,56.819554]],[[11.3274736,57.3612962],[11.3161808,57.1818004],[11.1508692,57.1847276],[11.1456628,57.094962],[10.8157703,57.1001693],[10.8290599,57.3695272],[11.3274736,57.3612962]],[[11.5843266,56.2777928],[11.5782882,56.1880397],[11.7392309,56.1845765],[11.7456428,56.2743186],[11.5843266,56.2777928]],[[14.6825922,55.3639405],[14.8395247,55.3565231],[14.8263755,55.2671261],[15.1393406,55.2517359],[15.1532015,55.3410836],[15.309925,55.3330556],[15.295719,55.2437356],[15.1393406,55.2517359],[15.1255631,55.1623802],[15.2815819,55.1544167],[15.2535578,54.9757646],[14.6317464,55.0062496],[14.6825922,55.3639405]]],"terms_url":"http://download.kortforsyningen.dk/content/vilkaar-og-betingelser","terms_text":"Geodatastyrelsen og Danske Kommuner","best":true},{"id":"Geoportal-PL-aerial_image","name":"Geoportal.gov.pl (Orthophotomap)","type":"tms","template":"http://wms.misek.pl/geoportal.orto/tms/{zoom}/{x}/{y}","scaleExtent":[6,24],"polygon":[[[15.9751041,54.3709213],[16.311164,54.5561775],[17.1391878,54.7845723],[18.3448458,54.9022727],[19.6613689,54.4737213],[20.2815206,54.4213456],[21.4663914,54.3406369],[22.7759855,54.3769755],[22.8625989,54.4233613],[23.2956657,54.2678633],[23.5347186,54.0955258],[23.5208604,53.9775182],[23.7183389,53.4629603],[23.9296755,53.1856735],[23.9296755,52.6887269],[23.732197,52.6067497],[23.5658994,52.5878101],[23.2090523,52.3302642],[23.1951942,52.2370089],[23.5035377,52.1860596],[23.6906226,52.0030113],[23.5970802,51.739903],[23.6629063,51.3888562],[23.9366046,50.9827781],[24.1687284,50.8604752],[24.0197534,50.8035823],[24.1098313,50.6610467],[24.0578633,50.4188439],[23.6178674,50.3083403],[22.6824431,49.5163532],[22.7378756,49.2094935],[22.9041733,49.0780441],[22.8625989,48.9940062],[22.6096878,49.0371785],[22.0761495,49.2004392],[21.8474902,49.3721872],[21.3763135,49.4488281],[21.1026153,49.3721872],[20.9120659,49.3022043],[20.6452967,49.3902311],[20.1845136,49.3315641],[20.1186875,49.2004392],[19.9419962,49.1302123],[19.765305,49.2117568],[19.7479823,49.3992506],[19.6024718,49.4150307],[19.5089294,49.5815389],[19.4292451,49.5905232],[19.2317666,49.4150307],[18.9961783,49.387976],[18.9338167,49.4916048],[18.8368097,49.4938552],[18.8021643,49.6623381],[18.6427958,49.7094091],[18.521537,49.8994693],[18.0815412,50.0109209],[17.8875272,49.9886512],[17.7385522,50.0687739],[17.6068999,50.1709584],[17.7454813,50.2153184],[17.710836,50.3017019],[17.4163505,50.2640668],[16.9486384,50.4453265],[16.8932058,50.4033889],[17.0006064,50.3105529],[17.017929,50.2241854],[16.8135215,50.186489],[16.6402948,50.0976742],[16.4324227,50.2862087],[16.1968344,50.4276731],[16.4220291,50.5885165],[16.3388803,50.6632429],[16.2280152,50.6368824],[16.0547884,50.6127057],[15.5732181,50.7641544],[15.2683391,50.8976368],[15.2440873,50.980597],[15.0292862,51.0133036],[15.0015699,50.8582883],[14.8110205,50.8735944],[14.956531,51.0721176],[15.0188926,51.2914636],[14.9392083,51.4601459],[14.7209426,51.5571799],[14.7521234,51.6260562],[14.5996839,51.8427626],[14.70362,52.0733396],[14.5581095,52.2497371],[14.5165351,52.425436],[14.6031485,52.5878101],[14.1146491,52.8208272],[14.152759,52.9733951],[14.3502374,53.0734212],[14.4229927,53.2665624],[14.1977979,53.8734759],[14.2220497,53.9958517],[15.9751041,54.3709213]]],"terms_text":"Copyright © Główny Urząd Geodezji i Kartografii.","best":true},{"id":"IBGE_DF_Addresses","name":"IBGE Distrito Federal","type":"tms","template":"https://api.mapbox.com/styles/v1/wille/cirnnxni1000jg8nfppc8g7pm/tiles/256/{zoom}/{x}/{y}?access_token=pk.eyJ1Ijoid2lsbGUiLCJhIjoicFNVWk5VWSJ9.hluCd0YGvYHNlFi_utWe2g","description":"Addresses data from IBGE","scaleExtent":[0,19],"polygon":[[[-48.2444,-16.0508],[-48.2444,-15.5005],[-47.5695,-15.5005],[-47.5695,-16.0508],[-48.2444,-16.0508]]],"overlay":true},{"id":"IBGE_Setores_Rurais","name":"IBGE Mapa de Setores Rurais","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/tmpsantos.i00mo1kj/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,14],"polygon":[[[-29.3325,2.335959],[-28.72472,2.031551],[-27.76041,-8.937033],[-27.67249,-22.20839],[-51.11495,-35.46552],[-53.39394,-33.85064],[-53.62553,-33.72493],[-53.62503,-33.15428],[-53.24498,-32.73392],[-53.65747,-32.51873],[-53.8329,-32.16592],[-54.64174,-31.55507],[-55.29638,-31.3429],[-55.57371,-30.99691],[-56.06384,-31.16749],[-56.10468,-30.86436],[-56.86862,-30.20752],[-57.39671,-30.40464],[-57.74384,-30.22142],[-55.83724,-28.16598],[-54.86969,-27.44994],[-53.9016,-27.02998],[-53.74972,-26.25781],[-53.97158,-25.74513],[-54.44723,-25.79609],[-54.67802,-25.64668],[-54.36097,-24.35145],[-54.41679,-24.06527],[-54.64355,-23.94107],[-55.22163,-24.11355],[-55.49138,-24.02797],[-55.71734,-22.68488],[-55.90555,-22.39886],[-56.45255,-22.21731],[-56.8256,-22.4002],[-57.34109,-22.34351],[-58.08472,-22.13075],[-57.95766,-20.99818],[-58.26551,-20.24147],[-58.03577,-19.95871],[-58.23083,-19.75211],[-57.64739,-18.19828],[-57.89356,-17.57377],[-58.16997,-17.53519],[-58.48825,-17.21961],[-58.57691,-16.81466],[-58.45563,-16.42158],[-60.2541,-16.32571],[-60.33481,-15.51483],[-60.67423,-15.1122],[-60.34999,-14.99707],[-60.63603,-13.84119],[-61.07283,-13.62569],[-61.9025,-13.62647],[-62.21395,-13.25048],[-62.80185,-13.10905],[-63.17194,-12.76568],[-63.74229,-12.54071],[-64.32845,-12.59578],[-65.10261,-12.0682],[-65.45781,-11.27865],[-65.41641,-9.838943],[-66.52331,-9.985873],[-67.66452,-10.80093],[-67.99778,-10.75991],[-68.52286,-11.20807],[-69.88988,-11.02776],[-70.30957,-11.1699],[-70.71896,-11.02003],[-70.68128,-9.669083],[-71.27536,-10.08971],[-72.18053,-10.09967],[-72.41623,-9.587397],[-73.29207,-9.454149],[-73.0625,-9.017267],[-73.61432,-8.40982],[-74.09056,-7.527548],[-74.03652,-7.27885],[-73.84718,-7.238285],[-73.78618,-6.774872],[-73.22362,-6.430106],[-73.33719,-6.029736],[-72.93016,-5.038711],[-71.93973,-4.425027],[-70.96802,-4.248294],[-70.79598,-4.064931],[-70.02393,-4.167345],[-69.51025,-1.134089],[-69.70776,-0.567619],[-70.13645,-0.226161],[-70.14083,0.5844],[-69.26594,0.806502],[-69.34226,0.968924],[-69.92481,1.015705],[-69.92343,1.773851],[-68.38511,1.82943],[-68.24848,2.119808],[-67.94571,1.948424],[-67.37696,2.327468],[-67.05751,1.858336],[-67.00579,1.291603],[-66.79967,1.314684],[-66.28683,0.857709],[-65.67671,1.111146],[-65.42494,0.966549],[-65.15671,1.24203],[-64.27483,1.601591],[-64.0486,2.065137],[-63.47236,2.279358],[-64.13446,2.433909],[-64.10005,2.723778],[-64.32628,3.118275],[-64.28142,3.541983],[-64.88451,4.117671],[-64.88064,4.342461],[-64.13653,4.223152],[-63.95465,4.021316],[-63.17706,4.048301],[-62.96093,3.763658],[-62.82024,4.106019],[-62.49922,4.270815],[-61.91181,4.26284],[-61.35393,4.630097],[-61.04904,4.623115],[-60.70452,4.969851],[-60.78709,5.296764],[-60.22457,5.371207],[-59.89857,5.107541],[-59.97549,4.603025],[-59.59676,4.439875],[-59.41942,3.96994],[-59.71017,3.542008],[-59.88955,2.72301],[-59.63006,2.316332],[-59.63382,1.966581],[-59.18812,1.478079],[-58.80545,1.320732],[-58.35933,1.689932],[-57.6,1.803907],[-57.39854,2.065119],[-57.12392,2.128758],[-56.02925,1.949445],[-56.23884,2.263348],[-55.98195,2.628657],[-55.64816,2.519953],[-54.93958,2.682515],[-54.24988,2.25056],[-53.73937,2.473731],[-52.98578,2.280494],[-52.65712,2.564069],[-52.41739,3.22121],[-51.73983,4.119158],[-51.7246,4.556867],[-51.0112,5.522895],[-43.48209,5.335832],[-29.3325,2.335959]]]},{"id":"IBGE_Setores_Urbanos","name":"IBGE Mapa de Setores Urbanos","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/tmpsantos.hgda0m6h/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,19],"polygon":[[[-29.3325,2.335959],[-28.72472,2.031551],[-27.76041,-8.937033],[-27.67249,-22.20839],[-51.11495,-35.46552],[-53.39394,-33.85064],[-53.62553,-33.72493],[-53.62503,-33.15428],[-53.24498,-32.73392],[-53.65747,-32.51873],[-53.8329,-32.16592],[-54.64174,-31.55507],[-55.29638,-31.3429],[-55.57371,-30.99691],[-56.06384,-31.16749],[-56.10468,-30.86436],[-56.86862,-30.20752],[-57.39671,-30.40464],[-57.74384,-30.22142],[-55.83724,-28.16598],[-54.86969,-27.44994],[-53.9016,-27.02998],[-53.74972,-26.25781],[-53.97158,-25.74513],[-54.44723,-25.79609],[-54.67802,-25.64668],[-54.36097,-24.35145],[-54.41679,-24.06527],[-54.64355,-23.94107],[-55.22163,-24.11355],[-55.49138,-24.02797],[-55.71734,-22.68488],[-55.90555,-22.39886],[-56.45255,-22.21731],[-56.8256,-22.4002],[-57.34109,-22.34351],[-58.08472,-22.13075],[-57.95766,-20.99818],[-58.26551,-20.24147],[-58.03577,-19.95871],[-58.23083,-19.75211],[-57.64739,-18.19828],[-57.89356,-17.57377],[-58.16997,-17.53519],[-58.48825,-17.21961],[-58.57691,-16.81466],[-58.45563,-16.42158],[-60.2541,-16.32571],[-60.33481,-15.51483],[-60.67423,-15.1122],[-60.34999,-14.99707],[-60.63603,-13.84119],[-61.07283,-13.62569],[-61.9025,-13.62647],[-62.21395,-13.25048],[-62.80185,-13.10905],[-63.17194,-12.76568],[-63.74229,-12.54071],[-64.32845,-12.59578],[-65.10261,-12.0682],[-65.45781,-11.27865],[-65.41641,-9.838943],[-66.52331,-9.985873],[-67.66452,-10.80093],[-67.99778,-10.75991],[-68.52286,-11.20807],[-69.88988,-11.02776],[-70.30957,-11.1699],[-70.71896,-11.02003],[-70.68128,-9.669083],[-71.27536,-10.08971],[-72.18053,-10.09967],[-72.41623,-9.587397],[-73.29207,-9.454149],[-73.0625,-9.017267],[-73.61432,-8.40982],[-74.09056,-7.527548],[-74.03652,-7.27885],[-73.84718,-7.238285],[-73.78618,-6.774872],[-73.22362,-6.430106],[-73.33719,-6.029736],[-72.93016,-5.038711],[-71.93973,-4.425027],[-70.96802,-4.248294],[-70.79598,-4.064931],[-70.02393,-4.167345],[-69.51025,-1.134089],[-69.70776,-0.567619],[-70.13645,-0.226161],[-70.14083,0.5844],[-69.26594,0.806502],[-69.34226,0.968924],[-69.92481,1.015705],[-69.92343,1.773851],[-68.38511,1.82943],[-68.24848,2.119808],[-67.94571,1.948424],[-67.37696,2.327468],[-67.05751,1.858336],[-67.00579,1.291603],[-66.79967,1.314684],[-66.28683,0.857709],[-65.67671,1.111146],[-65.42494,0.966549],[-65.15671,1.24203],[-64.27483,1.601591],[-64.0486,2.065137],[-63.47236,2.279358],[-64.13446,2.433909],[-64.10005,2.723778],[-64.32628,3.118275],[-64.28142,3.541983],[-64.88451,4.117671],[-64.88064,4.342461],[-64.13653,4.223152],[-63.95465,4.021316],[-63.17706,4.048301],[-62.96093,3.763658],[-62.82024,4.106019],[-62.49922,4.270815],[-61.91181,4.26284],[-61.35393,4.630097],[-61.04904,4.623115],[-60.70452,4.969851],[-60.78709,5.296764],[-60.22457,5.371207],[-59.89857,5.107541],[-59.97549,4.603025],[-59.59676,4.439875],[-59.41942,3.96994],[-59.71017,3.542008],[-59.88955,2.72301],[-59.63006,2.316332],[-59.63382,1.966581],[-59.18812,1.478079],[-58.80545,1.320732],[-58.35933,1.689932],[-57.6,1.803907],[-57.39854,2.065119],[-57.12392,2.128758],[-56.02925,1.949445],[-56.23884,2.263348],[-55.98195,2.628657],[-55.64816,2.519953],[-54.93958,2.682515],[-54.24988,2.25056],[-53.73937,2.473731],[-52.98578,2.280494],[-52.65712,2.564069],[-52.41739,3.22121],[-51.73983,4.119158],[-51.7246,4.556867],[-51.0112,5.522895],[-43.48209,5.335832],[-29.3325,2.335959]]]},{"id":"Haiti-Drone","name":"Imagerie Drone (Haiti)","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/iomhaiti/{zoom}/{x}/{y}","polygon":[[[-72.1547401,19.6878969],[-72.162234,19.689011],[-72.164995,19.6932445],[-72.1657838,19.6979977],[-72.161603,19.7035677],[-72.1487449,19.7028993],[-72.1477194,19.7026765],[-72.1485082,19.7001514],[-72.1436963,19.7011169],[-72.1410143,19.7000029],[-72.139476,19.6973664],[-72.1382533,19.6927617],[-72.1386872,19.6923161],[-72.1380561,19.6896423],[-72.1385294,19.6894938],[-72.1388055,19.6901251],[-72.1388844,19.6876741],[-72.1378195,19.6872656],[-72.13778,19.6850003],[-72.1369517,19.6855945],[-72.136794,19.6840719],[-72.135729,19.6835148],[-72.1355713,19.6740817],[-72.1366362,19.6708133],[-72.1487843,19.6710733],[-72.1534779,19.6763843],[-72.1530835,19.6769414],[-72.1533251,19.6769768],[-72.1532807,19.6796525],[-72.1523834,19.6797175],[-72.1522749,19.6803488],[-72.1519101,19.6803395],[-72.1518608,19.6805067],[-72.1528173,19.6806552],[-72.1522299,19.6833011],[-72.1507801,19.6831499],[-72.1504457,19.6847862],[-72.1508591,19.6843492],[-72.1530087,19.6849898],[-72.1546258,19.6854354],[-72.1543103,19.6870694],[-72.1547244,19.6868466],[-72.1548501,19.6877564],[-72.1545814,19.6877982],[-72.1547401,19.6878969]],[[-72.1310601,19.6718929],[-72.1259842,19.6772765],[-72.1255379,19.6776179],[-72.1216891,19.6776442],[-72.1149677,19.672602],[-72.1152745,19.6687152],[-72.1198205,19.6627535],[-72.1227768,19.6625696],[-72.1248965,19.662701],[-72.1285779,19.6645394],[-72.1308091,19.6661677],[-72.1316737,19.668794],[-72.1315621,19.671],[-72.1310601,19.6718929]],[[-71.845795,19.6709758],[-71.8429354,19.6759525],[-71.8410027,19.6759525],[-71.8380249,19.6755254],[-71.8378671,19.6745041],[-71.8390504,19.6743927],[-71.8390109,19.6741141],[-71.8398392,19.673947],[-71.8389123,19.6736127],[-71.8380249,19.67209],[-71.8380052,19.6726285],[-71.8376699,19.6727214],[-71.8376305,19.672545],[-71.8354414,19.6732135],[-71.835333,19.6729999],[-71.8331242,19.6734642],[-71.8326706,19.6716815],[-71.8321579,19.67209],[-71.8307183,19.6694902],[-71.8306009,19.6697594],[-71.8302174,19.6698907],[-71.8291833,19.6672095],[-71.8290749,19.6672095],[-71.8289122,19.6667916],[-71.8289516,19.6666199],[-71.8288333,19.6663506],[-71.8285572,19.6664759],[-71.8288678,19.6672466],[-71.8287593,19.6674138],[-71.8277979,19.6678177],[-71.8277112,19.6678586],[-71.8278263,19.6679637],[-71.8271831,19.6681212],[-71.8271761,19.6680917],[-71.8264405,19.6683921],[-71.8264074,19.6683231],[-71.8261954,19.6684253],[-71.8261806,19.6683556],[-71.8258946,19.6684206],[-71.8258897,19.6686574],[-71.8251551,19.6687549],[-71.8254509,19.6691588],[-71.8229332,19.6695739],[-71.822713,19.6696658],[-71.8227688,19.6697577],[-71.8201751,19.6709855],[-71.8198474,19.6704537],[-71.8197985,19.6706014],[-71.8194674,19.6707557],[-71.8182472,19.6713433],[-71.8181426,19.6711431],[-71.8175813,19.6714254],[-71.816959,19.6707672],[-71.8176388,19.6718965],[-71.8171403,19.6720376],[-71.8158225,19.6718045],[-71.8138354,19.6711874],[-71.8123259,19.6706982],[-71.8121759,19.6704258],[-71.8124304,19.6701467],[-71.8119184,19.6700141],[-71.8118765,19.6705828],[-71.811169,19.6703483],[-71.8095938,19.6698516],[-71.8077992,19.6692829],[-71.8056028,19.668612],[-71.8051443,19.6668942],[-71.8051196,19.6652322],[-71.8052315,19.661979],[-71.8065603,19.6523921],[-71.8073412,19.6482946],[-71.8099686,19.6468292],[-71.8147517,19.6454502],[-71.8147726,19.6455619],[-71.8150027,19.6455093],[-71.8149469,19.6453846],[-71.8159928,19.6450234],[-71.8158882,19.6448855],[-71.8165854,19.6446097],[-71.8190119,19.643802],[-71.8211524,19.643454],[-71.8221564,19.6433292],[-71.8269046,19.643211],[-71.8280481,19.6432241],[-71.8304466,19.6440778],[-71.8306419,19.6448592],[-71.8295263,19.6450365],[-71.8296064,19.6456111],[-71.8299411,19.6455651],[-71.8303699,19.6451744],[-71.830471,19.6453452],[-71.8308092,19.6451974],[-71.8310184,19.6451088],[-71.8312519,19.6458541],[-71.8311125,19.6458245],[-71.831367,19.6465862],[-71.8328939,19.646189],[-71.8344566,19.6457062],[-71.8344664,19.6463052],[-71.834215,19.6461938],[-71.8342002,19.6465513],[-71.8346702,19.6463],[-71.8349118,19.6463905],[-71.8347984,19.6462187],[-71.8354393,19.6458496],[-71.8355034,19.6458032],[-71.8364747,19.6461328],[-71.8376382,19.6472658],[-71.8379143,19.647888],[-71.8390483,19.6508039],[-71.8456942,19.6696203],[-71.845795,19.6709758]],[[-72.098878,18.54843],[-72.096993,18.5501994],[-72.0972888,18.5503209],[-72.0968451,18.5503489],[-72.0955632,18.551854],[-72.0956428,18.5526742],[-72.0959914,18.5533748],[-72.0962145,18.553203],[-72.0962842,18.5535665],[-72.0964446,18.5535533],[-72.0965352,18.5539764],[-72.0965056,18.554173],[-72.0966085,18.5541747],[-72.0965178,18.5542127],[-72.0968769,18.5546588],[-72.0979018,18.5552141],[-72.1006211,18.5555875],[-72.1014926,18.5556206],[-72.1024339,18.5555016],[-72.103417,18.5543515],[-72.1034798,18.5516215],[-72.1030789,18.5516149],[-72.1033752,18.5515224],[-72.1035042,18.5515224],[-72.1035239,18.5502417],[-72.1028701,18.5503062],[-72.1029015,18.55025],[-72.1028457,18.5501773],[-72.1035081,18.5500252],[-72.103491,18.5497396],[-72.1035181,18.5497361],[-72.1035398,18.5489039],[-72.1034317,18.5487056],[-72.102717,18.5481437],[-72.1025601,18.5481536],[-72.10229,18.5482751],[-72.1022891,18.5482569],[-72.1025201,18.5481396],[-72.1023388,18.5481321],[-72.0999082,18.5480901],[-72.09907,18.5483799],[-72.098878,18.54843]],[[-72.2542503,18.568262],[-72.2560252,18.5717765],[-72.2557886,18.5748049],[-72.2535009,18.5755526],[-72.2522782,18.5755526],[-72.2499906,18.5740945],[-72.2473874,18.5698323],[-72.2460069,18.566729],[-72.2458492,18.5629527],[-72.2479396,18.5625414],[-72.2501483,18.5628031],[-72.2519232,18.5650839],[-72.2542503,18.568262]],[[-72.303145,18.5332749],[-72.3031275,18.5331799],[-72.3048311,18.5311081],[-72.3097397,18.5311081],[-72.3164332,18.5324302],[-72.3234056,18.5366083],[-72.3261388,18.5387765],[-72.3261946,18.5426371],[-72.3170468,18.5540596],[-72.3130864,18.5540596],[-72.2987511,18.5453342],[-72.2988627,18.5407333],[-72.2962969,18.5404689],[-72.2954602,18.5395169],[-72.2961853,18.5338582],[-72.2971893,18.5332235],[-72.3007034,18.5332764],[-72.3022652,18.5342284],[-72.3028486,18.5335189],[-72.303104,18.5333361],[-72.303181,18.5334007],[-72.3035793,18.5335614],[-72.3030793,18.5346463],[-72.303715,18.5339873],[-72.3045286,18.5344052],[-72.3044015,18.5345097],[-72.3062747,18.5352571],[-72.3063107,18.5352741],[-72.3061219,18.5357628],[-72.3061219,18.5358196],[-72.30637,18.5358928],[-72.3062726,18.5354869],[-72.3066688,18.5350891],[-72.3061963,18.5349706],[-72.3058869,18.5349385],[-72.3055373,18.5346833],[-72.3054864,18.534613],[-72.3055585,18.5345065],[-72.3046749,18.5342293],[-72.3047617,18.5338817],[-72.3043252,18.5337511],[-72.3042595,18.5336346],[-72.303145,18.5332749]],[[-72.2981405,18.477502],[-72.2935652,18.4948587],[-72.2922242,18.4964297],[-72.2931708,18.4972526],[-72.2892266,18.5057058],[-72.2878067,18.5080996],[-72.2850458,18.5119893],[-72.2840203,18.5113161],[-72.2808649,18.515879],[-72.2773151,18.5175994],[-72.2723454,18.5175246],[-72.2662714,18.5144578],[-72.2665869,18.5066783],[-72.2692643,18.5046154],[-72.2661965,18.5029756],[-72.2688181,18.4965222],[-72.2691528,18.4959403],[-72.2702684,18.4961519],[-72.2702684,18.4955964],[-72.2690691,18.49557],[-72.2692922,18.4937714],[-72.2736988,18.4859951],[-72.2746749,18.4850429],[-72.2751769,18.483403],[-72.2765435,18.4813398],[-72.2773523,18.4814985],[-72.2783006,18.4809694],[-72.2778544,18.4807049],[-72.2771013,18.480123],[-72.2789978,18.4775836],[-72.279723,18.4772927],[-72.2806433,18.4776365],[-72.2813685,18.4771604],[-72.2808386,18.4769752],[-72.2812848,18.4758378],[-72.2823167,18.4751765],[-72.2851615,18.4750971],[-72.2849941,18.4763668],[-72.2854404,18.4769752],[-72.286277,18.4756262],[-72.2869325,18.4754675],[-72.2865978,18.4751897],[-72.2865978,18.4750046],[-72.2909765,18.4747268],[-72.2946579,18.4749384],[-72.2973911,18.476843],[-72.2981405,18.477502]],[[-72.3466657,18.5222375],[-72.346833,18.5244325],[-72.3475303,18.5277645],[-72.3455501,18.5291131],[-72.3403069,18.5292189],[-72.3383267,18.5280289],[-72.3369043,18.530118],[-72.3338086,18.5296684],[-72.3289279,18.5270769],[-72.328649,18.5253316],[-72.3292068,18.5232689],[-72.330406,18.5220524],[-72.3321631,18.5221847],[-72.3322467,18.5191963],[-72.3369183,18.5183633],[-72.3382012,18.5184691],[-72.3381454,18.5181782],[-72.3411993,18.5177947],[-72.3454943,18.5171997],[-72.3492595,18.517279],[-72.3504308,18.5188922],[-72.3503472,18.5206112],[-72.3496778,18.5220392],[-72.3466657,18.5222375]],[[-72.3303078,18.5486462],[-72.3429687,18.5508149],[-72.3433236,18.5530585],[-72.3413121,18.5614341],[-72.3390639,18.5613593],[-72.3384723,18.5638271],[-72.3375257,18.5654348],[-72.3348436,18.5650609],[-72.3311755,18.5638271],[-72.3312149,18.5616211],[-72.3232082,18.5606863],[-72.3212361,18.559602],[-72.3208023,18.5587046],[-72.3208811,18.557882],[-72.3259493,18.5580274],[-72.3266186,18.5581993],[-72.3259214,18.5577498],[-72.3250986,18.5573797],[-72.3233767,18.552263],[-72.3245994,18.5478507],[-72.3288986,18.5483742],[-72.329979,18.5489548],[-72.3303078,18.5486462]],[[-72.3231383,18.5269828],[-72.3223434,18.528067],[-72.3209629,18.5279745],[-72.3207816,18.5271282],[-72.3208513,18.5253697],[-72.3214649,18.5249598],[-72.3225666,18.5248937],[-72.3228454,18.52533],[-72.3232359,18.5264804],[-72.3231383,18.5269828]],[[-72.2160832,18.6457752],[-72.2159649,18.6553795],[-72.2030279,18.6558279],[-72.1947057,18.6553421],[-72.1922208,18.6545573],[-72.1920631,18.6521283],[-72.193483,18.6477559],[-72.201253,18.6385249],[-72.2069327,18.6388239],[-72.2120996,18.6424117],[-72.2118068,18.6430591],[-72.2121693,18.6426892],[-72.2127968,18.6427552],[-72.2134662,18.6431252],[-72.2135638,18.6437462],[-72.2154176,18.6443947],[-72.2158909,18.6450301],[-72.2160832,18.6457752]],[[-72.2867654,18.6482017],[-72.2900977,18.6527446],[-72.28981,18.6536532],[-72.2900738,18.6542664],[-72.290721,18.6537667],[-72.2910327,18.6544709],[-72.2912485,18.654221],[-72.29168,18.6558905],[-72.2912245,18.656606],[-72.2922673,18.65597],[-72.2926869,18.6567536],[-72.2930705,18.6567309],[-72.2941253,18.6581846],[-72.2960192,18.6608421],[-72.2959713,18.6619096],[-72.2932862,18.664567],[-72.2906731,18.6659979],[-72.2895943,18.6661342],[-72.2895943,18.6665657],[-72.2877004,18.6664749],[-72.2875805,18.6676559],[-72.2831214,18.6697227],[-72.2796453,18.6696546],[-72.2784311,18.6690787],[-72.2783972,18.6687736],[-72.277736,18.6691671],[-72.2774394,18.669143],[-72.2770071,18.6683159],[-72.2765575,18.6681125],[-72.2765385,18.6680583],[-72.2752319,18.6685239],[-72.2749292,18.6674649],[-72.2746416,18.6674309],[-72.2734668,18.6682145],[-72.2732271,18.6682712],[-72.2726757,18.6671583],[-72.2719147,18.6674288],[-72.2718808,18.6673405],[-72.2688149,18.6681868],[-72.2688269,18.6671761],[-72.2690786,18.6668241],[-72.2688149,18.66679],[-72.2681077,18.6670739],[-72.2676282,18.6673805],[-72.2675563,18.6666878],[-72.266861,18.666949],[-72.2655904,18.6673578],[-72.2654466,18.6670058],[-72.2647514,18.6674146],[-72.2629893,18.6681868],[-72.2628455,18.6681754],[-72.2626537,18.6676076],[-72.2623001,18.6677098],[-72.2624799,18.6679199],[-72.2624799,18.6682322],[-72.262306,18.6682606],[-72.2620963,18.6679654],[-72.2622761,18.6689193],[-72.2601484,18.6688966],[-72.2542749,18.6687944],[-72.2505388,18.6683476],[-72.2504371,18.669536],[-72.2477926,18.6698893],[-72.2415204,18.669793],[-72.2414187,18.6741933],[-72.2389167,18.6739759],[-72.2387249,18.6734649],[-72.2383653,18.6733059],[-72.2387009,18.6739532],[-72.2375502,18.6738964],[-72.2374183,18.6735103],[-72.237742,18.67334],[-72.2375142,18.6732605],[-72.236843,18.6734876],[-72.2364354,18.6724088],[-72.2355124,18.6726019],[-72.2354045,18.6724202],[-72.2353027,18.6729028],[-72.2345475,18.6726871],[-72.2343077,18.6724599],[-72.2342358,18.6734706],[-72.2334087,18.6734592],[-72.2332889,18.6733003],[-72.2327375,18.6732889],[-72.2327135,18.6735047],[-72.227703,18.6725281],[-72.2265283,18.6716537],[-72.226804,18.6715742],[-72.2274993,18.6715855],[-72.2274873,18.6714493],[-72.2272899,18.6714623],[-72.2272814,18.6712977],[-72.2272094,18.671358],[-72.2261785,18.6713693],[-72.2256032,18.670881],[-72.2255073,18.6694502],[-72.2261066,18.6696886],[-72.2261785,18.6695949],[-72.2259837,18.6695495],[-72.225777,18.6691379],[-72.2253335,18.6694643],[-72.2249739,18.66947],[-72.2245783,18.6678802],[-72.2235525,18.6677046],[-72.2235907,18.6675921],[-72.2224634,18.6676283],[-72.2223659,18.667022],[-72.2223277,18.6670943],[-72.2219209,18.667026],[-72.2208105,18.6669015],[-72.220809,18.6665325],[-72.2208705,18.6663593],[-72.2206023,18.6668107],[-72.2203895,18.6666361],[-72.2184341,18.6650535],[-72.21829,18.6640979],[-72.2183493,18.6608376],[-72.2187223,18.6606541],[-72.2186894,18.660603],[-72.2187253,18.6604525],[-72.2189771,18.6603247],[-72.2187823,18.6601998],[-72.2186984,18.6602367],[-72.2185815,18.6600352],[-72.2186085,18.6600039],[-72.2187823,18.6601345],[-72.218995,18.6600181],[-72.2189111,18.6599131],[-72.2189681,18.6597938],[-72.2183807,18.6595837],[-72.2184728,18.6539662],[-72.2201001,18.6511554],[-72.225796,18.6469472],[-72.2283048,18.6457265],[-72.2379335,18.645855],[-72.237764,18.6446985],[-72.2400355,18.6432529],[-72.2455958,18.6433493],[-72.2482742,18.6450358],[-72.2487488,18.6436705],[-72.2511067,18.6429775],[-72.2512385,18.6433409],[-72.2512625,18.6431592],[-72.2514843,18.6431365],[-72.2513284,18.6429718],[-72.2533602,18.6423471],[-72.253516,18.6426765],[-72.2539535,18.6425402],[-72.2541453,18.642932],[-72.2543851,18.6428696],[-72.2543791,18.6427503],[-72.2564168,18.6423244],[-72.2566925,18.6431365],[-72.2568783,18.6428582],[-72.2568184,18.6425288],[-72.258843,18.6420991],[-72.258885,18.6422467],[-72.2592626,18.6422297],[-72.2596461,18.6424057],[-72.2592206,18.6406907],[-72.2599545,18.6404815],[-72.2601156,18.6406341],[-72.2601156,18.6399393],[-72.2615268,18.6394669],[-72.2626056,18.6391034],[-72.2654465,18.6387286],[-72.2719433,18.6386832],[-72.272201,18.6388649],[-72.2730341,18.6394158],[-72.273166,18.6412558],[-72.2738732,18.6410286],[-72.2742208,18.6416079],[-72.2752187,18.6416987],[-72.2754524,18.6415738],[-72.2755513,18.6416874],[-72.2755394,18.6417527],[-72.2764713,18.6418634],[-72.276753,18.6418975],[-72.2762953,18.6426002],[-72.2774226,18.6429978],[-72.277982,18.6427247],[-72.2785796,18.6431303],[-72.2785669,18.6432307],[-72.2789017,18.6433471],[-72.279851,18.6439655],[-72.2858703,18.6469651],[-72.2867654,18.6482017]],[[-72.5557247,18.5305893],[-72.5555866,18.5367036],[-72.554995,18.537975],[-72.5488026,18.537919],[-72.5486646,18.5372832],[-72.548842,18.5306267],[-72.5493745,18.5301031],[-72.555133,18.5301218],[-72.5557247,18.5305893]],[[-72.6235278,18.5079877],[-72.6234441,18.5095217],[-72.6226074,18.5104341],[-72.6204878,18.511849],[-72.6183403,18.5107514],[-72.6162207,18.5083183],[-72.6162625,18.506467],[-72.618661,18.5044438],[-72.6204041,18.5044967],[-72.6228305,18.506996],[-72.6235278,18.5079877]]]},{"id":"osmim-imagicode-S2A_R119_N09_20160327T050917","name":"imagico.de OSM images for mapping: Adams Bridge","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R119_N09_20160327T050917&z={zoom}&x={x}&y={-y}","description":"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":"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"}];
18629 var presets = {"aerialway":{"fields":["aerialway"],"geometry":["point","vertex","line"],"tags":{"aerialway":"*"},"terms":["ski lift","funifor","funitel"],"searchable":false,"name":"Aerialway"},"aeroway":{"icon":"airport","fields":["aeroway"],"geometry":["point","vertex","line","area"],"tags":{"aeroway":"*"},"searchable":false,"name":"Aeroway"},"amenity":{"fields":["amenity"],"geometry":["point","vertex","area"],"tags":{"amenity":"*"},"searchable":false,"name":"Amenity"},"highway":{"fields":["highway"],"geometry":["point","vertex","line","area"],"tags":{"highway":"*"},"searchable":false,"name":"Highway"},"place":{"fields":["place"],"geometry":["point","vertex","area"],"tags":{"place":"*"},"searchable":false,"name":"Place"},"power":{"geometry":["point","vertex","line","area"],"tags":{"power":"*"},"fields":["power"],"searchable":false,"name":"Power"},"railway":{"fields":["railway"],"geometry":["point","vertex","line","area"],"tags":{"railway":"*"},"searchable":false,"name":"Railway"},"roundabout":{"geometry":["vertex","line"],"tags":{"junction":"roundabout"},"name":"Roundabout","searchable":false},"waterway":{"fields":["waterway"],"geometry":["point","vertex","line","area"],"tags":{"waterway":"*"},"searchable":false,"name":"Waterway"},"address":{"fields":["address"],"geometry":["point"],"tags":{"addr:housenumber":"*"},"addTags":{},"removeTags":{},"matchScore":0.2,"name":"Address"},"advertising/billboard":{"fields":["parallel_direction","lit"],"geometry":["point","vertex","line"],"tags":{"advertising":"billboard"},"name":"Billboard"},"aerialway/cable_car":{"geometry":["line"],"terms":["tramway","ropeway"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/heating"],"tags":{"aerialway":"cable_car"},"name":"Cable Car"},"aerialway/chair_lift":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"chair_lift"},"name":"Chair Lift"},"aerialway/drag_lift":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"drag_lift"},"name":"Drag Lift"},"aerialway/gondola":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"gondola"},"name":"Gondola"},"aerialway/goods":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"goods"},"name":"Goods Aerialway"},"aerialway/magic_carpet":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration","aerialway/heating"],"tags":{"aerialway":"magic_carpet"},"name":"Magic Carpet Lift"},"aerialway/mixed_lift":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"mixed_lift"},"name":"Mixed Lift"},"aerialway/platter":{"geometry":["line"],"terms":["button lift","poma lift"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"platter"},"name":"Platter Lift"},"aerialway/pylon":{"geometry":["point","vertex"],"fields":["ref"],"tags":{"aerialway":"pylon"},"name":"Aerialway Pylon"},"aerialway/rope_tow":{"geometry":["line"],"terms":["handle tow","bugel lift"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"rope_tow"},"name":"Rope Tow Lift"},"aerialway/station":{"icon":"aerialway","geometry":["point","vertex"],"fields":["aerialway/access","aerialway/summer/access","elevation"],"tags":{"aerialway":"station"},"name":"Aerialway Station"},"aerialway/t-bar":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"t-bar"},"name":"T-bar Lift"},"aeroway/aerodrome":{"icon":"airport","geometry":["point","area"],"fields":["ref","iata","icao","operator","internet_access","internet_access/fee","internet_access/ssid"],"terms":["airplane","airport","aerodrome"],"tags":{"aeroway":"aerodrome"},"name":"Airport"},"aeroway/apron":{"icon":"airport","geometry":["area"],"terms":["ramp"],"fields":["ref","surface"],"tags":{"aeroway":"apron"},"name":"Apron"},"aeroway/gate":{"icon":"airport","geometry":["point"],"fields":["ref"],"tags":{"aeroway":"gate"},"name":"Airport Gate"},"aeroway/hangar":{"geometry":["area"],"fields":["building_area"],"tags":{"aeroway":"hangar"},"name":"Hangar"},"aeroway/helipad":{"icon":"heliport","geometry":["point","area"],"fields":["ref"],"terms":["helicopter","helipad","heliport"],"tags":{"aeroway":"helipad"},"name":"Helipad"},"aeroway/runway":{"geometry":["line","area"],"terms":["landing strip"],"fields":["ref","surface","length","width"],"tags":{"aeroway":"runway"},"name":"Runway"},"aeroway/taxiway":{"geometry":["line"],"fields":["ref","surface"],"tags":{"aeroway":"taxiway"},"name":"Taxiway"},"aeroway/terminal":{"icon":"airport","geometry":["point","area"],"terms":["airport","aerodrome"],"fields":["operator","building_area"],"tags":{"aeroway":"terminal"},"name":"Airport Terminal"},"amenity/coworking_space":{"icon":"commercial","fields":["address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"geometry":["point","area"],"tags":{"amenity":"coworking_space"},"name":"Coworking Space","searchable":false},"amenity/nursing_home":{"icon":"wheelchair","fields":["operator","address","building_area","social_facility","social_facility_for","opening_hours","wheelchair"],"geometry":["point","area"],"tags":{"amenity":"nursing_home"},"reference":{"key":"social_facility","value":"nursing_home"},"name":"Nursing Home","searchable":false},"amenity/register_office":{"icon":"town-hall","fields":["address","building_area","opening_hours","operator"],"geometry":["point","area"],"tags":{"amenity":"register_office"},"reference":{"key":"government","value":"register_office"},"name":"Register Office","searchable":false},"amenity/swimming_pool":{"icon":"swimming","geometry":["point","vertex","area"],"tags":{"amenity":"swimming_pool"},"reference":{"key":"leisure","value":"swimming_pool"},"name":"Swimming Pool","searchable":false},"amenity/animal_boarding":{"icon":"veterinary","fields":["operator","address","building_area","opening_hours","animal_boarding"],"geometry":["point","area"],"terms":["boarding","cat","dog","horse","kitten","pet boarding","pet care","pet hotel","puppy","reptile"],"tags":{"amenity":"animal_boarding"},"name":"Animal Boarding Facility"},"amenity/animal_breeding":{"icon":"veterinary","fields":["operator","address","building_area","opening_hours","animal_breeding"],"geometry":["point","area"],"terms":["breeding","bull","cat","cow","dog","horse","husbandry","kitten","livestock","pet breeding","puppy","reptile"],"tags":{"amenity":"animal_breeding"},"name":"Animal Breeding Facility"},"amenity/animal_shelter":{"icon":"veterinary","fields":["operator","address","building_area","opening_hours","animal_shelter"],"geometry":["point","area"],"terms":["adoption","aspca","cat","dog","horse","kitten","pet care","pet rescue","puppy","raptor","reptile","rescue","spca"],"tags":{"amenity":"animal_shelter"},"name":"Animal Shelter"},"amenity/arts_centre":{"icon":"theatre","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"arts_centre"},"name":"Arts Center"},"amenity/atm":{"icon":"bank","fields":["operator","currency_multi","drive_through"],"geometry":["point","vertex"],"terms":["money","cash","machine"],"tags":{"amenity":"atm"},"name":"ATM"},"amenity/bank":{"icon":"bank","fields":["atm","operator","address","building_area","opening_hours","drive_through"],"geometry":["point","area"],"terms":["credit union","check","deposit","fund","investment","repository","reserve","safe","savings","stock","treasury","trust","vault"],"tags":{"amenity":"bank"},"name":"Bank"},"amenity/bar":{"icon":"bar","fields":["operator","address","building_area","opening_hours","smoking","outdoor_seating"],"geometry":["point","area"],"terms":["dive","beer","bier","booze"],"tags":{"amenity":"bar"},"name":"Bar"},"amenity/bbq":{"icon":"bbq","fields":["covered","fuel"],"geometry":["point"],"terms":["bbq","grill"],"tags":{"amenity":"bbq"},"name":"Barbecue/Grill"},"amenity/bench":{"icon":"poi-bench","fields":["backrest"],"geometry":["point","vertex","line"],"terms":["seat"],"tags":{"amenity":"bench"},"name":"Bench"},"amenity/bicycle_parking":{"icon":"bicycle","fields":["bicycle_parking","capacity","operator","covered","access_simple"],"geometry":["point","vertex","area"],"terms":["bike"],"tags":{"amenity":"bicycle_parking"},"name":"Bicycle Parking"},"amenity/bicycle_rental":{"icon":"bicycle","fields":["capacity","network","operator"],"geometry":["point","vertex","area"],"terms":["bike"],"tags":{"amenity":"bicycle_rental"},"name":"Bicycle Rental"},"amenity/bicycle_repair_station":{"icon":"bicycle","fields":["operator","brand","opening_hours","fee","service/bicycle"],"geometry":["point","vertex","area"],"terms":["bike","repair","chain","pump"],"tags":{"amenity":"bicycle_repair_station"},"name":"Bicycle Repair Tool Stand"},"amenity/biergarten":{"icon":"beer","fields":["address","building_area","opening_hours","smoking","outdoor_seating"],"geometry":["point","area"],"tags":{"amenity":"biergarten"},"terms":["beer","bier","booze"],"name":"Beer Garden"},"amenity/boat_rental":{"fields":["operator"],"geometry":["point","area"],"tags":{"amenity":"boat_rental"},"name":"Boat Rental"},"amenity/bureau_de_change":{"icon":"bank","fields":["operator","currency_multi"],"geometry":["point","vertex"],"terms":["bureau de change","money changer"],"tags":{"amenity":"bureau_de_change"},"name":"Currency Exchange"},"amenity/bus_station":{"icon":"bus","fields":["building_area","operator","internet_access","internet_access/fee","internet_access/ssid"],"geometry":["point","area"],"tags":{"amenity":"bus_station"},"name":"Bus Station"},"amenity/cafe":{"icon":"cafe","fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"geometry":["point","area"],"terms":["bistro","coffee","tea"],"tags":{"amenity":"cafe"},"name":"Cafe"},"amenity/car_rental":{"icon":"car","fields":["operator"],"geometry":["point","area"],"tags":{"amenity":"car_rental"},"name":"Car Rental"},"amenity/car_sharing":{"icon":"car","fields":["operator","capacity"],"geometry":["point","area"],"tags":{"amenity":"car_sharing"},"name":"Car Sharing"},"amenity/car_wash":{"icon":"car","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"amenity":"car_wash"},"name":"Car Wash"},"amenity/casino":{"icon":"poi-dice","fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"terms":["gambling","roulette","craps","poker","blackjack"],"tags":{"amenity":"casino"},"name":"Casino"},"amenity/charging_station":{"icon":"car","fields":["operator","capacity"],"geometry":["point","area"],"tags":{"amenity":"charging_station"},"terms":["EV","Electric Vehicle","Supercharger"],"name":"Charging Station"},"amenity/childcare":{"icon":"school","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["daycare","orphanage","playgroup"],"tags":{"amenity":"childcare"},"name":"Nursery/Childcare"},"amenity/cinema":{"icon":"cinema","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["drive-in","film","flick","movie","theater","picture","show","screen"],"tags":{"amenity":"cinema"},"name":"Cinema"},"amenity/clinic":{"icon":"hospital","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["medical","urgentcare"],"tags":{"amenity":"clinic"},"name":"Clinic"},"amenity/clock":{"icon":"poi-clock","fields":["support","display","visibility","date"],"geometry":["point","vertex"],"tags":{"amenity":"clock"},"name":"Clock"},"amenity/college":{"icon":"college","fields":["operator","address","internet_access","internet_access/ssid"],"geometry":["point","area"],"terms":["university"],"tags":{"amenity":"college"},"name":"College Grounds"},"amenity/community_centre":{"icon":"town-hall","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":["event","hall"],"tags":{"amenity":"community_centre"},"name":"Community Center"},"amenity/compressed_air":{"icon":"car","geometry":["point","area"],"tags":{"amenity":"compressed_air"},"name":"Compressed Air"},"amenity/courthouse":{"icon":"town-hall","fields":["operator","address","building_area"],"geometry":["point","area"],"tags":{"amenity":"courthouse"},"name":"Courthouse"},"amenity/crematorium":{"icon":"cemetery","fields":["website","phone","opening_hours","wheelchair"],"geometry":["area","point"],"tags":{"amenity":"crematorium"},"terms":["cemetery","funeral"],"name":"Crematorium"},"amenity/dentist":{"icon":"dentist","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["tooth","teeth"],"tags":{"amenity":"dentist"},"name":"Dentist"},"amenity/doctors":{"icon":"hospital","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["medic*"],"tags":{"amenity":"doctors"},"name":"Doctor"},"amenity/dojo":{"icon":"pitch","fields":["sport","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["martial arts","dojang"],"tags":{"amenity":"dojo"},"name":"Dojo / Martial Arts Academy"},"amenity/drinking_water":{"icon":"drinking-water","geometry":["point"],"tags":{"amenity":"drinking_water"},"terms":["fountain","potable"],"name":"Drinking Water"},"amenity/driving_school":{"icon":"car","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"amenity":"driving_school"},"name":"Driving School"},"amenity/embassy":{"icon":"embassy","fields":["country","address","building_area"],"geometry":["point","area"],"tags":{"amenity":"embassy"},"name":"Embassy"},"amenity/fast_food":{"icon":"fast-food","fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking","outdoor_seating"],"geometry":["point","area"],"tags":{"amenity":"fast_food"},"terms":["restaurant","takeaway"],"name":"Fast Food"},"amenity/ferry_terminal":{"icon":"ferry","fields":["network","operator","address","building_area"],"geometry":["point","vertex","area"],"terms":[],"tags":{"amenity":"ferry_terminal"},"name":"Ferry Terminal"},"amenity/fire_station":{"icon":"fire-station","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"fire_station"},"name":"Fire Station"},"amenity/food_court":{"icon":"restaurant","fields":["operator","address","building_area","opening_hours","smoking","outdoor_seating"],"geometry":["point","area"],"terms":["fast food","restaurant","food"],"tags":{"amenity":"food_court"},"name":"Food Court"},"amenity/fountain":{"icon":"poi-fountain","geometry":["point","area"],"tags":{"amenity":"fountain"},"name":"Fountain"},"amenity/fuel":{"icon":"fuel","fields":["operator","address","opening_hours","fuel_multi"],"geometry":["point","area"],"terms":["petrol","fuel","gasoline","propane","diesel","lng","cng","biodiesel"],"tags":{"amenity":"fuel"},"name":"Gas Station"},"amenity/grave_yard":{"icon":"cemetery","fields":["religion","denomination"],"geometry":["point","area"],"tags":{"amenity":"grave_yard"},"name":"Graveyard"},"amenity/grit_bin":{"fields":["access_simple"],"geometry":["point","vertex"],"tags":{"amenity":"grit_bin"},"terms":["salt","sand"],"name":"Grit Bin"},"amenity/hospital":{"icon":"hospital","fields":["operator","address","emergency"],"geometry":["point","area"],"terms":["clinic","doctor","emergency room","health","infirmary","institution","sanatorium","sanitarium","sick","surgery","ward"],"tags":{"amenity":"hospital"},"name":"Hospital Grounds"},"amenity/hunting_stand":{"icon":"poi-binoculars","geometry":["point","vertex","area"],"terms":["game","gun","lookout","rifle","shoot*","wild","watch"],"tags":{"amenity":"hunting_stand"},"name":"Hunting Stand"},"amenity/ice_cream":{"icon":"ice-cream","fields":["address","building_area","opening_hours","takeaway","delivery","outdoor_seating"],"geometry":["point","area"],"terms":["gelato","sorbet","sherbet","frozen","yogurt"],"tags":{"amenity":"ice_cream"},"name":"Ice Cream Shop"},"amenity/internet_cafe":{"icon":"poi-mast","fields":["operator","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"geometry":["point","area"],"terms":["cybercafe","taxiphone","teleboutique","coffee","cafe","net","lanhouse"],"tags":{"amenity":"internet_cafe"},"name":"Internet Cafe"},"amenity/kindergarten":{"icon":"school","fields":["operator","address"],"geometry":["point","area"],"terms":["kindergarden","pre-school"],"tags":{"amenity":"kindergarten"},"name":"Preschool/Kindergarten Grounds"},"amenity/library":{"icon":"library","fields":["operator","building_area","address","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"geometry":["point","area"],"terms":["book"],"tags":{"amenity":"library"},"name":"Library"},"amenity/marketplace":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"amenity":"marketplace"},"name":"Marketplace"},"amenity/motorcycle_parking":{"icon":"scooter","fields":["capacity","operator","covered","access_simple"],"geometry":["point","vertex","area"],"tags":{"amenity":"motorcycle_parking"},"name":"Motorcycle Parking"},"amenity/nightclub":{"icon":"bar","fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"tags":{"amenity":"nightclub"},"terms":["disco*","night club","dancing","dance club"],"name":"Nightclub"},"amenity/parking_entrance":{"icon":"entrance-alt1","fields":["access_simple","ref"],"geometry":["vertex"],"tags":{"amenity":"parking_entrance"},"name":"Parking Garage Entrance/Exit"},"amenity/parking_space":{"fields":["capacity"],"geometry":["point","vertex","area"],"terms":[],"tags":{"amenity":"parking_space"},"matchScore":0.95,"name":"Parking Space"},"amenity/parking":{"icon":"parking","fields":["operator","parking","capacity","fee","access_simple","supervised","park_ride","surface","maxstay","address"],"geometry":["point","vertex","area"],"tags":{"amenity":"parking"},"terms":[],"name":"Car Parking"},"amenity/pavilion":{"icon":"shelter","fields":["bin","bench"],"geometry":["point","vertex","area"],"tags":{"amenity":"shelter","shelter_type":"pavilion"},"name":"Pavilion"},"amenity/pharmacy":{"icon":"pharmacy","fields":["operator","address","building_area","opening_hours","drive_through"],"geometry":["point","area"],"tags":{"amenity":"pharmacy"},"terms":["drug*","med*","prescription"],"name":"Pharmacy"},"amenity/place_of_worship":{"icon":"place-of-worship","fields":["religion","denomination","address","building_area","service_times"],"geometry":["point","area"],"terms":["abbey","basilica","bethel","cathedral","chancel","chantry","chapel","church","fold","house of God","house of prayer","house of worship","minster","mission","mosque","oratory","parish","sacellum","sanctuary","shrine","synagogue","tabernacle","temple"],"tags":{"amenity":"place_of_worship"},"name":"Place of Worship"},"amenity/place_of_worship/buddhist":{"icon":"buddhism","fields":["denomination","building_area","address","service_times"],"geometry":["point","area"],"terms":["stupa","vihara","monastery","temple","pagoda","zendo","dojo"],"tags":{"amenity":"place_of_worship","religion":"buddhist"},"reference":{"key":"amenity","value":"place_of_worship"},"name":"Buddhist Temple"},"amenity/place_of_worship/christian":{"icon":"religious-christian","fields":["denomination","building_area","address","service_times"],"geometry":["point","area"],"terms":["christian","abbey","basilica","bethel","cathedral","chancel","chantry","chapel","fold","house of God","house of prayer","house of worship","minster","mission","oratory","parish","sacellum","sanctuary","shrine","tabernacle","temple"],"tags":{"amenity":"place_of_worship","religion":"christian"},"reference":{"key":"amenity","value":"place_of_worship"},"name":"Church"},"amenity/place_of_worship/jewish":{"icon":"religious-jewish","fields":["denomination","building_area","address","service_times"],"geometry":["point","area"],"terms":["jewish"],"tags":{"amenity":"place_of_worship","religion":"jewish"},"reference":{"key":"amenity","value":"place_of_worship"},"name":"Synagogue"},"amenity/place_of_worship/muslim":{"icon":"religious-muslim","fields":["denomination","building_area","address","service_times"],"geometry":["point","area"],"terms":["muslim"],"tags":{"amenity":"place_of_worship","religion":"muslim"},"reference":{"key":"amenity","value":"place_of_worship"},"name":"Mosque"},"amenity/planetarium":{"icon":"museum","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["museum","astronomy","observatory"],"tags":{"amenity":"planetarium"},"name":"Planetarium"},"amenity/police":{"icon":"police","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":["badge","constable","constabulary","cop","detective","fed","law","enforcement","officer","patrol"],"tags":{"amenity":"police"},"name":"Police"},"amenity/post_box":{"icon":"post","fields":["operator","collection_times","drive_through","ref"],"geometry":["point","vertex"],"tags":{"amenity":"post_box"},"terms":["letter","post"],"name":"Mailbox"},"amenity/post_office":{"icon":"post","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["letter","mail"],"tags":{"amenity":"post_office"},"name":"Post Office"},"amenity/prison":{"icon":"prison","fields":["operator","address"],"geometry":["point","area"],"terms":["cell","jail"],"tags":{"amenity":"prison"},"name":"Prison Grounds"},"amenity/pub":{"icon":"beer","fields":["address","building_area","opening_hours","smoking","outdoor_seating"],"geometry":["point","area"],"tags":{"amenity":"pub"},"terms":["alcohol","drink","dive","beer","bier","booze"],"name":"Pub"},"amenity/public_bath":{"icon":"water","fields":["bath/type","bath/open_air","bath/sand_bath","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"amenity":"public_bath"},"terms":["onsen","foot bath","hot springs"],"name":"Public Bath"},"amenity/public_bookcase":{"icon":"library","fields":["name","operator","capacity","website"],"geometry":["point","area"],"terms":["library","bookcrossing"],"tags":{"amenity":"public_bookcase"},"name":"Public Bookcase"},"amenity/ranger_station":{"fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["visitor center","visitor centre","permit center","permit centre","backcountry office","warden office","warden center"],"tags":{"amenity":"ranger_station"},"name":"Ranger Station"},"amenity/recycling_centre":{"icon":"waste-basket","fields":["operator","address","opening_hours","recycling_accepts"],"geometry":["point","area"],"terms":["bottle","can","dump","glass","garbage","rubbish","scrap","trash"],"tags":{"amenity":"recycling","recycling_type":"centre"},"name":"Recycling Center"},"amenity/recycling":{"icon":"recycling","fields":["recycling_type","recycling_accepts","collection_times"],"geometry":["point","area"],"terms":["bin","can","bottle","glass","garbage","rubbish","scrap","trash"],"tags":{"amenity":"recycling"},"name":"Recycling"},"amenity/restaurant":{"icon":"restaurant","fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking","outdoor_seating"],"geometry":["point","area"],"terms":["bar","breakfast","cafe","café","canteen","coffee","dine","dining","dinner","drive-in","eat","grill","lunch","table"],"tags":{"amenity":"restaurant"},"name":"Restaurant"},"amenity/sanitary_dump_station":{"icon":"poi-storage-tank","fields":["operator","access_toilets","fee","water_point"],"geometry":["point","vertex","area"],"terms":["Motor Home","Camper","Sanitary","Dump Station","Elsan","CDP","CTDP","Chemical Toilet"],"tags":{"amenity":"sanitary_dump_station"},"name":"RV Toilet Disposal"},"amenity/school":{"icon":"school","fields":["operator","address"],"geometry":["point","area"],"terms":["academy","elementary school","middle school","high school"],"tags":{"amenity":"school"},"name":"School Grounds"},"amenity/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}};
18631 var defaults = {"area":["category-landuse","category-building","category-water-area","category-natural-area","leisure/park","amenity/hospital","amenity/place_of_worship","amenity/cafe","amenity/restaurant","area"],"line":["category-road","category-rail","category-path","category-water-line","category-barrier","category-natural-line","power/line","line"],"point":["category-natural-point","leisure/park","amenity/hospital","amenity/place_of_worship","amenity/cafe","amenity/restaurant","amenity/fast_food","amenity/bar","amenity/bank","shop/supermarket","point"],"vertex":["highway/crosswalk","highway/crossing","railway/level_crossing","highway/traffic_signals","highway/turning_circle","highway/turning_loop","traffic_calming","highway/mini_roundabout","highway/motorway_junction","vertex"],"relation":["category-route","category-restriction","type/boundary","type/multipolygon","type/site","relation"]};
18633 var categories = {"category-barrier":{"icon":"roadblock","geometry":"line","name":"Barrier Features","members":["barrier/fence","barrier/wall","barrier/ditch","barrier/gate","barrier"]},"category-building":{"icon":"building","geometry":"area","name":"Building Features","members":["building","building/house","building/apartments","building/commercial","building/industrial","building/residential"]},"category-golf":{"icon":"golf","geometry":"area","name":"Golf Features","members":["golf/fairway","golf/green","golf/lateral_water_hazard_area","golf/rough","golf/bunker","golf/tee","golf/water_hazard_area"]},"category-landuse":{"icon":"landuse","geometry":"area","name":"Land Use Features","members":["landuse/residential","landuse/industrial","landuse/commercial","landuse/retail","landuse/farmland","landuse/farmyard","landuse/forest","landuse/meadow","landuse/aquaculture","landuse/cemetery","landuse/military"]},"category-natural-area":{"icon":"natural","geometry":"area","name":"Natural Features","members":["natural/water","natural/wood","natural/scrub","natural/wetland","natural/grassland","natural/heath","natural/bare_rock","natural/beach","natural/cave_entrance","natural/glacier"]},"category-natural-line":{"icon":"natural","geometry":"line","name":"Natural Features","members":["natural/coastline","natural/tree_row"]},"category-natural-point":{"icon":"natural","geometry":"point","name":"Natural Features","members":["natural/peak","natural/cliff","natural/beach","natural/cave_entrance"]},"category-path":{"icon":"category-path","geometry":"line","name":"Path Features","members":["footway/crosswalk","footway/sidewalk","highway/steps","highway/path","highway/footway","highway/cycleway","highway/bridleway","highway/pedestrian"]},"category-rail":{"icon":"category-rail","geometry":"line","name":"Rail Features","members":["railway/rail","railway/subway","railway/tram","railway/monorail","railway/disused","railway/abandoned"]},"category-restriction":{"icon":"restriction","geometry":"relation","name":"Restriction Features","members":["type/restriction/no_left_turn","type/restriction/no_right_turn","type/restriction/no_straight_on","type/restriction/no_u_turn","type/restriction/only_left_turn","type/restriction/only_right_turn","type/restriction/only_straight_on","type/restriction"]},"category-road":{"icon":"category-roads","geometry":"line","name":"Road Features","members":["highway/residential","highway/motorway","highway/trunk","highway/primary","highway/secondary","highway/tertiary","highway/living_street","highway/unclassified","highway/service","highway/track","highway/motorway_link","highway/trunk_link","highway/primary_link","highway/secondary_link","highway/tertiary_link","highway/road"]},"category-route":{"icon":"route","geometry":"relation","name":"Route Features","members":["type/route/road","type/route/bicycle","type/route/foot","type/route/hiking","type/route/horse","type/route/bus","type/route/train","type/route/tram","type/route/ferry","type/route/power","type/route/pipeline","type/route/detour","type/route_master","type/route"]},"category-water-area":{"icon":"water","geometry":"area","name":"Water Features","members":["natural/water/lake","natural/water/pond","natural/water/reservoir","natural/water"]},"category-water-line":{"icon":"category-water","geometry":"line","name":"Water Features","members":["waterway/river","waterway/stream","waterway/canal","waterway/ditch","waterway/drain"]}};
18635 var fields = {"access_simple":{"key":"access","type":"combo","label":"Allowed Access","options":["permissive","private","customers","no"]},"access_toilets":{"key":"access","type":"combo","label":"Access","options":["yes","permissive","private","customers"]},"access":{"keys":["access","foot","motor_vehicle","bicycle","horse"],"reference":{"key":"access"},"type":"access","label":"Allowed Access","placeholder":"Not Specified","strings":{"types":{"access":"All","foot":"Foot","motor_vehicle":"Motor Vehicles","bicycle":"Bicycles","horse":"Horses"},"options":{"yes":{"title":"Allowed","description":"Access permitted by law; a right of way"},"no":{"title":"Prohibited","description":"Access not permitted to the general public"},"permissive":{"title":"Permissive","description":"Access permitted until such time as the owner revokes the permission"},"private":{"title":"Private","description":"Access permitted only with permission of the owner on an individual basis"},"designated":{"title":"Designated","description":"Access permitted according to signs or specific local laws"},"destination":{"title":"Destination","description":"Access permitted only to reach a destination"},"dismount":{"title":"Dismount","description":"Access permitted but rider must dismount"}}}},"address":{"type":"address","keys":["addr:block_number","addr:city","addr:block_number","addr:conscriptionnumber","addr:county","addr:country","addr:county","addr:district","addr:floor","addr:hamlet","addr:housename","addr:housenumber","addr:neighbourhood","addr:place","addr:postcode","addr:province","addr:quarter","addr:state","addr:street","addr:subdistrict","addr:suburb"],"reference":{"key":"addr"},"icon":"address","universal":true,"label":"Address","strings":{"placeholders":{"block_number":"Block Number","block_number!jp":"Block No.","city":"City","city!jp":"City/Town/Village/Tokyo Special Ward","city!vn":"City/Town","conscriptionnumber":"123","country":"Country","county":"County","county!jp":"District","district":"District","district!vn":"Arrondissement/Town/District","floor":"Floor","hamlet":"Hamlet","housename":"Housename","housenumber":"123","housenumber!jp":"Building No./Lot No.","neighbourhood":"Neighbourhood","neighbourhood!jp":"Chōme/Aza/Koaza","place":"Place","postcode":"Postcode","province":"Province","province!jp":"Prefecture","quarter":"Quarter","quarter!jp":"Ōaza/Machi","state":"State","street":"Street","subdistrict":"Subdistrict","subdistrict!vn":"Ward/Commune/Townlet","suburb":"Suburb","suburb!jp":"Ward"}}},"admin_level":{"key":"admin_level","type":"number","label":"Admin Level"},"aerialway":{"key":"aerialway","type":"typeCombo","label":"Type"},"aerialway/access":{"key":"aerialway:access","type":"combo","label":"Access","strings":{"options":{"entry":"Entry","exit":"Exit","both":"Both"}}},"aerialway/bubble":{"key":"aerialway:bubble","type":"check","label":"Bubble"},"aerialway/capacity":{"key":"aerialway:capacity","type":"number","label":"Capacity (per hour)","placeholder":"500, 2500, 5000..."},"aerialway/duration":{"key":"aerialway:duration","type":"number","label":"Duration (minutes)","placeholder":"1, 2, 3..."},"aerialway/heating":{"key":"aerialway:heating","type":"check","label":"Heated"},"aerialway/occupancy":{"key":"aerialway:occupancy","type":"number","label":"Occupancy","placeholder":"2, 4, 8..."},"aerialway/summer/access":{"key":"aerialway:summer:access","type":"combo","label":"Access (summer)","strings":{"options":{"entry":"Entry","exit":"Exit","both":"Both"}}},"aeroway":{"key":"aeroway","type":"typeCombo","label":"Type"},"amenity":{"key":"amenity","type":"typeCombo","label":"Type"},"animal_boarding":{"key":"animal_boarding","type":"semiCombo","label":"For Animals"},"animal_breeding":{"key":"animal_breeding","type":"semiCombo","label":"For Animals"},"animal_shelter":{"key":"animal_shelter","type":"semiCombo","label":"For Animals"},"area/highway":{"key":"area:highway","type":"typeCombo","label":"Type"},"artist":{"key":"artist_name","type":"text","label":"Artist"},"artwork_type":{"key":"artwork_type","type":"combo","label":"Type"},"atm":{"key":"atm","type":"check","label":"ATM"},"backrest":{"key":"backrest","type":"check","label":"Backrest"},"barrier":{"key":"barrier","type":"typeCombo","label":"Type"},"bath/open_air":{"key":"bath:open_air","label":"Open Air","type":"check"},"bath/sand_bath":{"key":"bath:sand_bath","label":"Sand Bath","type":"check"},"bath/type":{"key":"bath:type","type":"combo","label":"Specialty","strings":{"options":{"onsen":"Japanese Onsen","foot_bath":"Foot Bath","hot_spring":"Hot Spring"}}},"beauty":{"key":"beauty","type":"combo","label":"Shop Type"},"bench":{"key":"bench","type":"check","label":"Bench"},"bicycle_parking":{"key":"bicycle_parking","type":"combo","label":"Type"},"bin":{"key":"bin","type":"check","label":"Waste Bin"},"blood_components":{"key":"blood:","type":"multiCombo","label":"Blood Components","strings":{"options":{"whole":"whole blood","plasma":"plasma","platelets":"platelets","stemcells":"stem cell samples"}}},"board_type":{"key":"board_type","type":"typeCombo","label":"Type"},"boundary":{"key":"boundary","type":"combo","label":"Type"},"brand":{"key":"brand","type":"text","label":"Brand"},"building_area":{"key":"building","type":"combo","default":"yes","geometry":"area","label":"Building"},"building":{"key":"building","type":"combo","label":"Building"},"bunker_type":{"key":"bunker_type","type":"combo","label":"Type"},"camera/direction":{"key":"camera:direction","type":"number","label":"Direction (Degrees Clockwise)","placeholder":"45, 90, 180, 270"},"camera/mount":{"key":"camera:mount","type":"combo","label":"Camera Mount"},"camera/type":{"key":"camera:type","type":"combo","label":"Camera Type","strings":{"options":{"fixed":"Fixed","panning":"Panning","dome":"Dome"}}},"capacity":{"key":"capacity","type":"number","label":"Capacity","placeholder":"50, 100, 200..."},"cardinal_direction":{"key":"direction","type":"combo","label":"Direction","strings":{"options":{"N":"North","E":"East","S":"South","W":"West","NE":"Northeast","SE":"Southeast","SW":"Southwest","NW":"Northwest","NNE":"North-northeast","ENE":"East-northeast","ESE":"East-southeast","SSE":"South-southeast","SSW":"South-southwest","WSW":"West-southwest","WNW":"West-northwest","NNW":"North-northwest"}}},"castle_type":{"key":"castle_type","type":"combo","label":"Type"},"clock_direction":{"key":"direction","type":"combo","label":"Direction","strings":{"options":{"clockwise":"Clockwise","anticlockwise":"Counterclockwise"}}},"club":{"key":"club","type":"typeCombo","label":"Type"},"collection_times":{"key":"collection_times","type":"text","label":"Collection Times"},"communication_multi":{"key":"communication:","type":"multiCombo","label":"Communication Types"},"construction":{"key":"construction","type":"combo","label":"Type"},"contact/webcam":{"key":"contact:webcam","type":"url","icon":"website","label":"Webcam URL","placeholder":"http://example.com/"},"content":{"key":"content","type":"combo","label":"Contents"},"country":{"key":"country","type":"combo","label":"Country"},"covered":{"key":"covered","type":"check","label":"Covered"},"craft":{"key":"craft","type":"typeCombo","label":"Type"},"crop":{"key":"crop","type":"semiCombo","label":"Crops"},"crossing":{"key":"crossing","type":"combo","label":"Type"},"cuisine":{"key":"cuisine","type":"semiCombo","label":"Cuisines"},"currency_multi":{"key":"currency:","type":"multiCombo","label":"Currency Types"},"cycle_network":{"key":"cycle_network","type":"networkCombo","label":"Network"},"cycleway":{"keys":["cycleway:left","cycleway:right"],"reference":{"key":"cycleway"},"type":"cycleway","label":"Bike Lanes","placeholder":"none","strings":{"types":{"cycleway:left":"Left side","cycleway:right":"Right side"},"options":{"none":{"title":"None","description":"No bike lane"},"lane":{"title":"Standard bike lane","description":"A bike lane separated from auto traffic by a painted line"},"shared_lane":{"title":"Shared bike lane","description":"A bike lane with no separation from auto traffic"},"track":{"title":"Bike track","description":"A bike lane separated from traffic by a physical barrier"},"share_busway":{"title":"Bike lane shared with bus","description":"A bike lane shared with a bus lane"},"opposite_lane":{"title":"Opposite bike lane","description":"A bike lane that travels in the opposite direction of traffic"},"opposite":{"title":"Contraflow bike lane","description":"A bike lane that travels in both directions on a one-way street"}}}},"date":{"key":"date","type":"check","label":"Date"},"delivery":{"key":"delivery","type":"check","label":"Delivery"},"denomination":{"key":"denomination","type":"combo","label":"Denomination"},"denotation":{"key":"denotation","type":"combo","label":"Denotation"},"description":{"key":"description","type":"textarea","label":"Description","universal":true},"diaper":{"key":"diaper","type":"combo","label":"Diaper Changing Available","options":["yes","no","room","1","2","3","4","5"]},"display":{"key":"display","type":"combo","label":"Display","options":["analog","digital","sundial","unorthodox"]},"dock":{"key":"dock","type":"combo","label":"Type"},"drive_through":{"key":"drive_through","type":"check","label":"Drive-Through"},"electrified":{"key":"electrified","type":"combo","label":"Electrification","placeholder":"Contact Line, Electrified Rail...","strings":{"options":{"contact_line":"Contact Line","rail":"Electrified Rail","yes":"Yes (unspecified)","no":"No"}}},"elevation":{"key":"ele","type":"number","icon":"elevation","universal":true,"label":"Elevation"},"email":{"key":"email","type":"email","placeholder":"example@example.com","universal":true,"label":"Email"},"emergency":{"key":"emergency","type":"check","label":"Emergency"},"entrance":{"key":"entrance","type":"typeCombo","label":"Type"},"except":{"key":"except","type":"combo","label":"Exceptions"},"fax":{"key":"fax","type":"tel","label":"Fax","universal":true,"placeholder":"+31 42 123 4567"},"fee":{"key":"fee","type":"check","label":"Fee"},"fence_type":{"key":"fence_type","type":"combo","label":"Type"},"fire_hydrant/position":{"key":"fire_hydrant:position","type":"combo","label":"Position","strings":{"options":{"lane":"Lane","parking_lot":"Parking Lot","sidewalk":"Sidewalk","green":"Green"}}},"fire_hydrant/type":{"key":"fire_hydrant:type","type":"combo","label":"Type","strings":{"options":{"pillar":"Pillar/Aboveground","underground":"Underground","wall":"Wall","pond":"Pond"}}},"fixme":{"key":"fixme","type":"textarea","label":"Fix Me","universal":true},"fuel_multi":{"key":"fuel:","type":"multiCombo","label":"Fuel Types"},"fuel":{"key":"fuel","type":"combo","label":"Fuel"},"gauge":{"key":"gauge","type":"combo","label":"Gauge"},"gender":{"type":"radio","keys":["male","female","unisex"],"label":"Gender","placeholder":"Unknown","strings":{"options":{"male":"Male","female":"Female","unisex":"Unisex"}}},"generator/method":{"key":"generator:method","type":"combo","label":"Method"},"generator/source":{"key":"generator:source","type":"combo","label":"Source"},"generator/type":{"key":"generator:type","type":"combo","label":"Type"},"golf_hole":{"key":"ref","type":"text","label":"Reference","placeholder":"Hole number (1-18)"},"grape_variety":{"key":"grape_variety","type":"semiCombo","label":"Grape Varieties"},"handicap":{"key":"handicap","type":"number","label":"Handicap","placeholder":"1-18"},"handrail":{"key":"handrail","type":"check","label":"Handrail"},"height":{"key":"height","type":"number","label":"Height (Meters)"},"highway":{"key":"highway","type":"typeCombo","label":"Type"},"historic":{"key":"historic","type":"typeCombo","label":"Type"},"historic/civilization":{"key":"historic:civilization","type":"combo","label":"Historic Civilization"},"hoops":{"key":"hoops","type":"number","label":"Hoops","placeholder":"1, 2, 4..."},"iata":{"key":"iata","type":"text","label":"IATA"},"icao":{"key":"icao","type":"text","label":"ICAO"},"incline_steps":{"key":"incline","type":"combo","label":"Incline","strings":{"options":{"up":"Up","down":"Down"}}},"incline":{"key":"incline","type":"combo","label":"Incline"},"indoor":{"key":"indoor","type":"check","label":"Indoor"},"information":{"key":"information","type":"typeCombo","label":"Type"},"inscription":{"key":"inscription","type":"textarea","label":"Inscription"},"internet_access":{"key":"internet_access","type":"combo","label":"Internet Access","strings":{"options":{"yes":"Yes","no":"No","wlan":"Wifi","wired":"Wired","terminal":"Terminal"}}},"internet_access/fee":{"key":"internet_access:fee","type":"check","label":"Internet Access Fee"},"internet_access/ssid":{"key":"internet_access:ssid","type":"text","label":"SSID (Network Name)"},"kerb":{"key":"kerb","type":"combo","label":"Curb 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"},"operator":{"key":"operator","type":"text","label":"Operator"},"outdoor_seating":{"key":"outdoor_seating","type":"check","label":"Outdoor Seating"},"par":{"key":"par","type":"number","label":"Par","placeholder":"3, 4, 5..."},"parallel_direction":{"key":"direction","type":"combo","label":"Direction","strings":{"options":{"forward":"Forward","backward":"Backward"}}},"park_ride":{"key":"park_ride","type":"check","label":"Park and Ride"},"parking":{"key":"parking","type":"combo","label":"Type","strings":{"options":{"surface":"Surface","multi-storey":"Multilevel","underground":"Underground","sheds":"Sheds","carports":"Carports","garage_boxes":"Garage Boxes","lane":"Roadside Lane"}}},"payment_multi":{"key":"payment:","type":"multiCombo","label":"Payment Types"},"phone":{"key":"phone","type":"tel","icon":"telephone","universal":true,"label":"Phone","placeholder":"+31 42 123 4567"},"piste/difficulty":{"key":"piste:difficulty","type":"combo","label":"Difficulty","placeholder":"Easy, Intermediate, Advanced...","strings":{"options":{"novice":"Novice (instructional)","easy":"Easy (green circle)","intermediate":"Intermediate (blue square)","advanced":"Advanced (black diamond)","expert":"Expert (double black diamond)","freeride":"Freeride (off-piste)","extreme":"Extreme (climbing equipment required)"}}},"piste/grooming":{"key":"piste:grooming","type":"combo","label":"Grooming","strings":{"options":{"classic":"Classic","mogul":"Mogul","backcountry":"Backcountry","classic+skating":"Classic and Skating","scooter":"Scooter/Snowmobile","skating":"Skating"}}},"piste/type":{"key":"piste:type","type":"typeCombo","label":"Type","strings":{"options":{"downhill":"Downhill","nordic":"Nordic","skitour":"Skitour","sled":"Sled","hike":"Hike","sleigh":"Sleigh","ice_skate":"Ice Skate","snow_park":"Snow Park","playground":"Playground"}}},"place":{"key":"place","type":"typeCombo","label":"Type"},"plant":{"key":"plant","type":"combo","label":"Plant"},"population":{"key":"population","type":"text","label":"Population"},"power_supply":{"key":"power_supply","type":"check","label":"Power Supply"},"power":{"key":"power","type":"typeCombo","label":"Type"},"produce":{"key":"produce","type":"semiCombo","label":"Produce"},"product":{"key":"product","type":"semiCombo","label":"Products"},"railway":{"key":"railway","type":"typeCombo","label":"Type"},"recycling_accepts":{"key":"recycling:","type":"multiCombo","label":"Accepts"},"recycling_type":{"key":"recycling_type","default":"container","type":"combo","label":"Recycling Type","strings":{"options":{"container":"Container","centre":"Recycling Center"}}},"ref":{"key":"ref","type":"text","label":"Reference"},"relation":{"key":"type","type":"combo","label":"Type"},"religion":{"key":"religion","type":"combo","label":"Religion"},"restriction":{"key":"restriction","type":"combo","label":"Type"},"restrictions":{"type":"restrictions","geometry":"vertex","icon":"restrictions","reference":{"rtype":"restriction"},"label":"Turn Restrictions"},"rooms":{"key":"rooms","type":"number","label":"Rooms"},"route_master":{"key":"route_master","type":"combo","label":"Type"},"route":{"key":"route","type":"combo","label":"Type"},"sac_scale":{"key":"sac_scale","type":"combo","label":"Hiking Difficulty","placeholder":"Mountain Hiking, Alpine Hiking...","strings":{"options":{"hiking":"T1: Hiking","mountain_hiking":"T2: Mountain Hiking","demanding_mountain_hiking":"T3: Demanding Mountain Hiking","alpine_hiking":"T4: Alpine Hiking","demanding_alpine_hiking":"T5: Demanding Alpine Hiking","difficult_alpine_hiking":"T6: Difficult Alpine Hiking"}}},"sanitary_dump_station":{"key":"sanitary_dump_station","type":"check","label":"Toilet Disposal"},"seasonal":{"key":"seasonal","type":"check","label":"Seasonal"},"second_hand":{"key":"second_hand","type":"combo","label":"Sells Used","placeholder":"Yes, No, Only","strings":{"options":{"yes":"Yes","no":"No","only":"Only"}}},"service_rail":{"key":"service","type":"combo","label":"Service Type","strings":{"options":{"spur":"Spur","yard":"Yard","siding":"Siding","crossover":"Crossover"}}},"service_times":{"key":"service_times","type":"text","label":"Service Times"},"service":{"key":"service","type":"combo","label":"Type","options":["parking_aisle","driveway","alley","emergency_access","drive-through"]},"service/bicycle":{"key":"service:bicycle:","type":"multiCombo","label":"Services"},"service/vehicle":{"key":"service:vehicle:","type":"multiCombo","label":"Services"},"shelter_type":{"key":"shelter_type","type":"combo","label":"Type"},"shelter":{"key":"shelter","type":"check","label":"Shelter"},"shop":{"key":"shop","type":"typeCombo","label":"Type"},"site":{"key":"site","type":"combo","label":"Type"},"smoking":{"key":"smoking","type":"combo","label":"Smoking","placeholder":"No, Separated, Yes...","strings":{"options":{"no":"No smoking anywhere","separated":"In smoking areas, not physically isolated","isolated":"In smoking areas, physically isolated","outside":"Allowed outside","yes":"Allowed everywhere","dedicated":"Dedicated to smokers (e.g. smokers' club)"}}},"smoothness":{"key":"smoothness","type":"combo","label":"Smoothness","placeholder":"Thin Rollers, Wheels, Off-Road...","strings":{"options":{"excellent":"Thin Rollers: rollerblade, skateboard","good":"Thin Wheels: racing bike","intermediate":"Wheels: city bike, wheelchair, scooter","bad":"Robust Wheels: trekking bike, car, rickshaw","very_bad":"High Clearance: light duty off-road vehicle","horrible":"Off-Road: heavy duty off-road vehicle","very_horrible":"Specialized off-road: tractor, ATV","impassable":"Impassable / No wheeled vehicle"}}},"social_facility_for":{"key":"social_facility:for","type":"combo","label":"People Served"},"social_facility":{"key":"social_facility","type":"combo","label":"Type"},"source":{"key":"source","type":"text","icon":"source","universal":true,"label":"Source"},"sport_ice":{"key":"sport","type":"semiCombo","label":"Sports","options":["skating","hockey","multi","curling","ice_stock"]},"sport_racing_motor":{"key":"sport","type":"semiCombo","label":"Sports","options":["motor","karting","motocross"]},"sport_racing_nonmotor":{"key":"sport","type":"semiCombo","label":"Sports","options":["bmx","cycling","dog_racing","horse_racing","running"]},"sport":{"key":"sport","type":"semiCombo","label":"Sports"},"stars":{"key":"stars","type":"number","label":"Stars"},"start_date":{"key":"start_date","type":"text","universal":true,"label":"Start Date"},"step_count":{"key":"step_count","type":"number","label":"Number of Steps"},"stop":{"key":"stop","type":"combo","label":"Stop Type","strings":{"options":{"all":"All Ways","minor":"Minor Road"}}},"structure":{"type":"structureRadio","keys":["bridge","tunnel","embankment","cutting","ford"],"label":"Structure","placeholder":"Unknown","strings":{"options":{"bridge":"Bridge","tunnel":"Tunnel","embankment":"Embankment","cutting":"Cutting","ford":"Ford"}}},"studio":{"key":"studio","type":"combo","label":"Type"},"substation":{"key":"substation","type":"typeCombo","label":"Type"},"supervised":{"key":"supervised","type":"check","label":"Supervised"},"support":{"key":"support","type":"combo","label":"Support"},"surface":{"key":"surface","type":"combo","label":"Surface"},"surveillance":{"key":"surveillance","type":"combo","label":"Surveillance Kind"},"surveillance/type":{"key":"surveillance:type","type":"combo","label":"Surveillance Type","strings":{"options":{"camera":"Camera","guard":"Guard","ALPR":"Automatic License Plate Reader"}}},"surveillance/zone":{"key":"surveillance:zone","type":"combo","label":"Surveillance Zone"},"tactile_paving":{"key":"tactile_paving","type":"check","label":"Tactile Paving"},"takeaway":{"key":"takeaway","type":"combo","label":"Takeaway","placeholder":"Yes, No, Takeaway Only...","strings":{"options":{"yes":"Yes","no":"No","only":"Takeaway Only"}}},"toilets/disposal":{"key":"toilets:disposal","type":"combo","label":"Disposal","strings":{"options":{"flush":"Flush","pitlatrine":"Pit/Latrine","chemical":"Chemical","bucket":"Bucket"}}},"toll":{"key":"toll","type":"check","label":"Toll"},"tomb":{"key":"tomb","type":"typeCombo","label":"Type"},"tourism":{"key":"tourism","type":"typeCombo","label":"Type"},"tower/construction":{"key":"tower:construction","type":"combo","label":"Construction","placeholder":"Guyed, Lattice, Concealed, ..."},"tower/type":{"key":"tower:type","type":"combo","label":"Type"},"tracktype":{"key":"tracktype","type":"combo","label":"Track Type","placeholder":"Solid, Mostly Solid, Soft...","strings":{"options":{"grade1":"Solid: paved or heavily compacted hardcore surface","grade2":"Mostly Solid: gravel/rock with some soft material mixed in","grade3":"Even mixture of hard and soft materials","grade4":"Mostly Soft: soil/sand/grass with some hard material mixed in","grade5":"Soft: soil/sand/grass"}}},"traffic_calming":{"key":"traffic_calming","type":"typeCombo","label":"Type"},"traffic_signals":{"key":"traffic_signals","type":"combo","label":"Type","default":"signal"},"trail_visibility":{"key":"trail_visibility","type":"combo","label":"Trail Visibility","placeholder":"Excellent, Good, Bad...","strings":{"options":{"excellent":"Excellent: unambiguous path or markers everywhere","good":"Good: markers visible, sometimes require searching","intermediate":"Intermediate: few markers, path mostly visible","bad":"Bad: no markers, path sometimes invisible/pathless","horrible":"Horrible: often pathless, some orientation skills required","no":"No: pathless, excellent orientation skills required"}}},"trees":{"key":"trees","type":"semiCombo","label":"Trees"},"tunnel":{"key":"tunnel","type":"combo","label":"Tunnel"},"vending":{"key":"vending","type":"combo","label":"Type of Goods"},"visibility":{"key":"visibility","type":"combo","label":"Visibility","strings":{"options":{"house":"Up to 5m (16ft)","street":"5 to 20m (16 to 65ft)","area":"Over 20m (65ft)"}}},"wall":{"key":"wall","type":"combo","label":"Type"},"water_point":{"key":"water_point","type":"check","label":"Water Point"},"water":{"key":"water","type":"combo","label":"Type"},"waterway":{"key":"waterway","type":"typeCombo","label":"Type"},"website":{"key":"website","type":"url","icon":"website","placeholder":"http://example.com/","universal":true,"label":"Website"},"wetland":{"key":"wetland","type":"combo","label":"Type"},"wheelchair":{"key":"wheelchair","type":"radio","options":["yes","limited","no"],"icon":"wheelchair","universal":true,"label":"Wheelchair Access"},"width":{"key":"width","type":"number","label":"Width (Meters)"},"wikipedia":{"key":"wikipedia","keys":["wikipedia","wikidata"],"type":"wikipedia","icon":"wikipedia","universal":true,"label":"Wikipedia"}};
18637 var all = ["aerialway","airfield","airport","alcohol-shop","america-football","amusement-park","aquarium","art-gallery","attraction","bakery","bank","bar","barrier","baseball","basketball","bbq","beer","bicycle","bicycle-share","blood-bank","buddhism","building","building-alt1","bus","cafe","campsite","car","castle","cemetery","cinema","circle","circle-stroked","city","clothing-store","college","commercial","cricket","cross","dam","danger","defibrillator","dentist","doctor","dog-park","drinking-water","embassy","emergency-phone","entrance","entrance-alt1","farm","fast-food","fence","ferry","fire-station","florist","fuel","gaming","garden","garden-center","gift","golf","grocery","hairdresser","harbor","heart","heliport","home","horse-riding","hospital","ice-cream","industry","information","karaoke","landmark","landuse","laundry","library","lighthouse","lodging","logging","marker","marker-stroked","mobile-phone","monument","mountain","museum","music","natural","park","park-alt1","parking","parking-garage","pharmacy","picnic-site","pitch","place-of-worship","playground","police","post","prison","rail","rail-light","rail-metro","ranger-station","recycling","religious-christian","religious-jewish","religious-muslim","residential-community","restaurant","roadblock","rocket","school","scooter","shelter","shop","skiing","slaughterhouse","snowmobile","soccer","square","square-stroked","stadium","star","star-stroked","suitcase","sushi","swimming","teahouse","telephone","tennis","theatre","toilet","town","town-hall","triangle","triangle-stroked","veterinary","village","volcano","warehouse","waste-basket","water","wetland","wheelchair","zoo"];
18642 var all$2 = Object.freeze({
18647 var Airport = ["airfield","airport","heliport","rocket"];
18648 var Dining = ["bakery","bar","beer","cafe","fast-food","ice-cream","restaurant"];
18649 var Education = ["college","school"];
18650 var General = ["alcohol-shop","amusement-park","aquarium","art-gallery","attraction","bank","bicycle","bicycle-share","car","castle","cinema","circle","circle-stroked","clothing-store","drinking-water","embassy","fire-station","fuel","grocery","harbor","information","laundry","library","lodging","marker","monument","museum","music","place-of-worship","police","post","prison","religious-christian","religious-jewish","religious-muslim","shop","stadium","star","suitcase","swimming","theatre","toilet","town-hall","triangle","triangle-stroked","veterinary"];
18651 var Health = ["dentist","doctor","hospital","pharmacy"];
18652 var Outdoors = ["campsite","cemetery","dog-park","garden","golf","park","picnic-site","playground","zoo"];
18653 var Transit = ["bus","ferry"];
18657 Education: Education,
18660 Outdoors: Outdoors,
18662 "Mountain peak": ["mountain","volcano"],
18663 "Rail station": ["entrance","rail","rail-light","rail-metro"]
18666 var streets$1 = Object.freeze({
18669 Education: Education,
18672 Outdoors: Outdoors,
18677 var require$$0 = ( all$2 && all$1 ) || all$2;
18679 var require$$1 = ( streets$1 && streets ) || streets$1;
18684 streets: require$$1
18688 var dataFeatureIcons = index$1.layouts.all.all;
18691 imagery: dataImagery,
18694 defaults: defaults,
18695 categories: categories,
18700 function osmEntity$$1(attrs) {
18701 // For prototypal inheritance.
18702 if (this instanceof osmEntity$$1) return;
18704 // Create the appropriate subtype.
18705 if (attrs && attrs.type) {
18706 return osmEntity$$1[attrs.type].apply(this, arguments);
18707 } else if (attrs && attrs.id) {
18708 return osmEntity$$1[osmEntity$$1.id.type(attrs.id)].apply(this, arguments);
18711 // Initialize a generic Entity (used only in tests).
18712 return (new osmEntity$$1()).initialize(arguments);
18716 osmEntity$$1.id = function(type) {
18717 return osmEntity$$1.id.fromOSM(type, osmEntity$$1.id.next[type]--);
18721 osmEntity$$1.id.next = {
18722 changeset: -1, node: -1, way: -1, relation: -1
18726 osmEntity$$1.id.fromOSM = function(type, id) {
18727 return type[0] + id;
18731 osmEntity$$1.id.toOSM = function(id) {
18732 return id.slice(1);
18736 osmEntity$$1.id.type = function(id) {
18737 return { 'c': 'changeset', 'n': 'node', 'w': 'way', 'r': 'relation' }[id[0]];
18741 // A function suitable for use as the second argument to d3.selection#data().
18742 osmEntity$$1.key = function(entity) {
18743 return entity.id + 'v' + (entity.v || 0);
18747 osmEntity$$1.prototype = {
18752 initialize: function(sources) {
18753 for (var i = 0; i < sources.length; ++i) {
18754 var source = sources[i];
18755 for (var prop in source) {
18756 if (Object.prototype.hasOwnProperty.call(source, prop)) {
18757 if (source[prop] === undefined) {
18760 this[prop] = source[prop];
18766 if (!this.id && this.type) {
18767 this.id = osmEntity$$1.id(this.type);
18769 if (!this.hasOwnProperty('visible')) {
18770 this.visible = true;
18774 Object.freeze(this);
18775 Object.freeze(this.tags);
18777 if (this.loc) Object.freeze(this.loc);
18778 if (this.nodes) Object.freeze(this.nodes);
18779 if (this.members) Object.freeze(this.members);
18786 copy: function(resolver, copies) {
18787 if (copies[this.id])
18788 return copies[this.id];
18790 var copy = osmEntity$$1(this, {id: undefined, user: undefined, version: undefined});
18791 copies[this.id] = copy;
18797 osmId: function() {
18798 return osmEntity$$1.id.toOSM(this.id);
18802 isNew: function() {
18803 return this.osmId() < 0;
18807 update: function(attrs) {
18808 return osmEntity$$1(this, attrs, {v: 1 + (this.v || 0)});
18812 mergeTags: function(tags) {
18813 var merged = lodash.clone(this.tags), changed = false;
18814 for (var k in tags) {
18815 var t1 = merged[k],
18820 } else if (t1 !== t2) {
18822 merged[k] = lodash.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
18825 return changed ? this.update({tags: merged}) : this;
18829 intersects: function(extent, resolver) {
18830 return this.extent(resolver).intersects(extent);
18834 isUsed: function(resolver) {
18835 return lodash.without(Object.keys(this.tags), 'area').length > 0 ||
18836 resolver.parentRelations(this).length > 0;
18840 hasInterestingTags: function() {
18841 return lodash.keys(this.tags).some(osmIsInterestingTag);
18845 isHighwayIntersection: function() {
18849 isDegenerate: function() {
18853 deprecatedTags: function() {
18854 var tags = lodash.toPairs(this.tags);
18855 var deprecated = {};
18857 dataDeprecated.forEach(function(d) {
18858 var match = lodash.toPairs(d.old)[0];
18859 tags.forEach(function(t) {
18860 if (t[0] === match[0] &&
18861 (t[1] === match[1] || match[1] === '*')) {
18862 deprecated[t[0]] = t[1];
18871 function geoRoundCoords(c) {
18872 return [Math.floor(c[0]), Math.floor(c[1])];
18876 function geoInterp(p1, p2, t) {
18877 return [p1[0] + (p2[0] - p1[0]) * t,
18878 p1[1] + (p2[1] - p1[1]) * t];
18882 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
18883 // Returns a positive value, if OAB makes a counter-clockwise turn,
18884 // negative for clockwise turn, and zero if the points are collinear.
18885 function geoCross(o, a, b) {
18886 return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
18890 // http://jsperf.com/id-dist-optimization
18891 function geoEuclideanDistance(a, b) {
18892 var x = a[0] - b[0], y = a[1] - b[1];
18893 return Math.sqrt((x * x) + (y * y));
18897 // using WGS84 polar radius (6356752.314245179 m)
18898 // const = 2 * PI * r / 360
18899 function geoLatToMeters(dLat) {
18900 return dLat * 110946.257617;
18904 // using WGS84 equatorial radius (6378137.0 m)
18905 // const = 2 * PI * r / 360
18906 function geoLonToMeters(dLon, atLat) {
18907 return Math.abs(atLat) >= 90 ? 0 :
18908 dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
18912 // using WGS84 polar radius (6356752.314245179 m)
18913 // const = 2 * PI * r / 360
18914 function geoMetersToLat(m) {
18915 return m / 110946.257617;
18919 // using WGS84 equatorial radius (6378137.0 m)
18920 // const = 2 * PI * r / 360
18921 function geoMetersToLon(m, atLat) {
18922 return Math.abs(atLat) >= 90 ? 0 :
18923 m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
18927 function geoOffsetToMeters(offset) {
18928 var equatRadius = 6356752.314245179,
18929 polarRadius = 6378137.0,
18933 offset[0] * 2 * Math.PI * equatRadius / tileSize,
18934 -offset[1] * 2 * Math.PI * polarRadius / tileSize
18939 function geoMetersToOffset(meters) {
18940 var equatRadius = 6356752.314245179,
18941 polarRadius = 6378137.0,
18945 meters[0] * tileSize / (2 * Math.PI * equatRadius),
18946 -meters[1] * tileSize / (2 * Math.PI * polarRadius)
18951 // Equirectangular approximation of spherical distances on Earth
18952 function geoSphericalDistance(a, b) {
18953 var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
18954 y = geoLatToMeters(a[1] - b[1]);
18955 return Math.sqrt((x * x) + (y * y));
18959 function geoEdgeEqual(a, b) {
18960 return (a[0] === b[0] && a[1] === b[1]) ||
18961 (a[0] === b[1] && a[1] === b[0]);
18965 // Return the counterclockwise angle in the range (-pi, pi)
18966 // between the positive X axis and the line intersecting a and b.
18967 function geoAngle(a, b, projection) {
18968 a = projection(a.loc);
18969 b = projection(b.loc);
18970 return Math.atan2(b[1] - a[1], b[0] - a[0]);
18974 // Rotate all points counterclockwise around a pivot point by given angle
18975 function geoRotate(points, angle, around) {
18976 return points.map(function(point) {
18977 var radial = [point[0] - around[0], point[1] - around[1]];
18979 radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + around[0],
18980 radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + around[1]
18986 // Choose the edge with the minimal distance from `point` to its orthogonal
18987 // projection onto that edge, if such a projection exists, or the distance to
18988 // the closest vertex on that edge. Returns an object with the `index` of the
18989 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
18990 function geoChooseEdge(nodes, point, projection) {
18991 var dist = geoEuclideanDistance,
18992 points = nodes.map(function(n) { return projection(n.loc); }),
18996 function dot(p, q) {
18997 return p[0] * q[0] + p[1] * q[1];
19000 for (var i = 0; i < points.length - 1; i++) {
19002 s = [points[i + 1][0] - o[0],
19003 points[i + 1][1] - o[1]],
19004 v = [point[0] - o[0],
19006 proj = dot(v, s) / dot(s, s),
19011 } else if (proj > 1) {
19014 p = [o[0] + proj * s[0], o[1] + proj * s[1]];
19017 var d = dist(p, point);
19021 loc = projection.invert(p);
19033 // Return the intersection point of 2 line segments.
19034 // From https://github.com/pgkelley4/line-segments-intersect
19035 // This uses the vector cross product approach described below:
19036 // http://stackoverflow.com/a/565282/786339
19037 function geoLineIntersection(a, b) {
19038 function subtractPoints(point1, point2) {
19039 return [point1[0] - point2[0], point1[1] - point2[1]];
19041 function crossProduct(point1, point2) {
19042 return point1[0] * point2[1] - point1[1] * point2[0];
19045 var p = [a[0][0], a[0][1]],
19046 p2 = [a[1][0], a[1][1]],
19047 q = [b[0][0], b[0][1]],
19048 q2 = [b[1][0], b[1][1]],
19049 r = subtractPoints(p2, p),
19050 s = subtractPoints(q2, q),
19051 uNumerator = crossProduct(subtractPoints(q, p), r),
19052 denominator = crossProduct(r, s);
19054 if (uNumerator && denominator) {
19055 var u = uNumerator / denominator,
19056 t = crossProduct(subtractPoints(q, p), s) / denominator;
19058 if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
19059 return geoInterp(p, p2, t);
19067 function geoPathIntersections(path1, path2) {
19068 var intersections = [];
19069 for (var i = 0; i < path1.length - 1; i++) {
19070 for (var j = 0; j < path2.length - 1; j++) {
19071 var a = [ path1[i], path1[i+1] ],
19072 b = [ path2[j], path2[j+1] ],
19073 hit = geoLineIntersection(a, b);
19074 if (hit) intersections.push(hit);
19077 return intersections;
19081 // Return whether point is contained in polygon.
19083 // `point` should be a 2-item array of coordinates.
19084 // `polygon` should be an array of 2-item arrays of coordinates.
19086 // From https://github.com/substack/point-in-polygon.
19087 // ray-casting algorithm based on
19088 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
19090 function geoPointInPolygon(point, polygon) {
19095 for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
19096 var xi = polygon[i][0], yi = polygon[i][1];
19097 var xj = polygon[j][0], yj = polygon[j][1];
19099 var intersect = ((yi > y) !== (yj > y)) &&
19100 (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
19101 if (intersect) inside = !inside;
19108 function geoPolygonContainsPolygon(outer, inner) {
19109 return lodash.every(inner, function(point) {
19110 return geoPointInPolygon(point, outer);
19115 function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
19116 function testSegments(outer, inner) {
19117 for (var i = 0; i < outer.length - 1; i++) {
19118 for (var j = 0; j < inner.length - 1; j++) {
19119 var a = [ outer[i], outer[i+1] ],
19120 b = [ inner[j], inner[j+1] ];
19121 if (geoLineIntersection(a, b)) return true;
19127 function testPoints(outer, inner) {
19128 return lodash.some(inner, function(point) {
19129 return geoPointInPolygon(point, outer);
19133 return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
19137 function geoPathLength(path) {
19139 for (var i = 0; i < path.length - 1; i++) {
19140 length += geoEuclideanDistance(path[i], path[i + 1]);
19145 function geoExtent$$1(min, max) {
19146 if (!(this instanceof geoExtent$$1)) return new geoExtent$$1(min, max);
19147 if (min instanceof geoExtent$$1) {
19149 } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
19153 this[0] = min || [ Infinity, Infinity];
19154 this[1] = max || min || [-Infinity, -Infinity];
19158 geoExtent$$1.prototype = new Array(2);
19160 lodash.extend(geoExtent$$1.prototype, {
19162 equals: function (obj) {
19163 return this[0][0] === obj[0][0] &&
19164 this[0][1] === obj[0][1] &&
19165 this[1][0] === obj[1][0] &&
19166 this[1][1] === obj[1][1];
19170 extend: function(obj) {
19171 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19172 return geoExtent$$1(
19173 [Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])],
19174 [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]
19179 _extend: function(extent) {
19180 this[0][0] = Math.min(extent[0][0], this[0][0]);
19181 this[0][1] = Math.min(extent[0][1], this[0][1]);
19182 this[1][0] = Math.max(extent[1][0], this[1][0]);
19183 this[1][1] = Math.max(extent[1][1], this[1][1]);
19188 return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
19192 center: function() {
19193 return [(this[0][0] + this[1][0]) / 2,
19194 (this[0][1] + this[1][1]) / 2];
19198 rectangle: function() {
19199 return [this[0][0], this[0][1], this[1][0], this[1][1]];
19204 return { minX: this[0][0], minY: this[0][1], maxX: this[1][0], maxY: this[1][1] };
19208 polygon: function() {
19210 [this[0][0], this[0][1]],
19211 [this[0][0], this[1][1]],
19212 [this[1][0], this[1][1]],
19213 [this[1][0], this[0][1]],
19214 [this[0][0], this[0][1]]
19219 contains: function(obj) {
19220 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19221 return obj[0][0] >= this[0][0] &&
19222 obj[0][1] >= this[0][1] &&
19223 obj[1][0] <= this[1][0] &&
19224 obj[1][1] <= this[1][1];
19228 intersects: function(obj) {
19229 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19230 return obj[0][0] <= this[1][0] &&
19231 obj[0][1] <= this[1][1] &&
19232 obj[1][0] >= this[0][0] &&
19233 obj[1][1] >= this[0][1];
19237 intersection: function(obj) {
19238 if (!this.intersects(obj)) return new geoExtent$$1();
19239 return new geoExtent$$1(
19240 [Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])],
19241 [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]
19246 percentContainedIn: function(obj) {
19247 if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19248 var a1 = this.intersection(obj).area(),
19251 if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
19259 padByMeters: function(meters) {
19260 var dLat = geoMetersToLat(meters),
19261 dLon = geoMetersToLon(meters, this.center()[1]);
19262 return geoExtent$$1(
19263 [this[0][0] - dLon, this[0][1] - dLat],
19264 [this[1][0] + dLon, this[1][1] + dLat]
19269 toParam: function() {
19270 return this.rectangle().join(',');
19275 var version = "4.8.0";
19277 var ascending = function(a, b) {
19278 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
19281 var bisector = function(compare) {
19282 if (compare.length === 1) compare = ascendingComparator(compare);
19284 left: function(a, x, lo, hi) {
19285 if (lo == null) lo = 0;
19286 if (hi == null) hi = a.length;
19288 var mid = lo + hi >>> 1;
19289 if (compare(a[mid], x) < 0) lo = mid + 1;
19294 right: function(a, x, lo, hi) {
19295 if (lo == null) lo = 0;
19296 if (hi == null) hi = a.length;
19298 var mid = lo + hi >>> 1;
19299 if (compare(a[mid], x) > 0) hi = mid;
19307 function ascendingComparator(f) {
19308 return function(d, x) {
19309 return ascending(f(d), x);
19313 var ascendingBisect = bisector(ascending);
19314 var bisectRight = ascendingBisect.right;
19315 var bisectLeft = ascendingBisect.left;
19317 var pairs = function(array, f) {
19318 if (f == null) f = pair;
19319 var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);
19320 while (i < n) pairs[i] = f(p, p = array[++i]);
19324 function pair(a, b) {
19328 var cross = function(values0, values1, reduce) {
19329 var n0 = values0.length,
19330 n1 = values1.length,
19331 values = new Array(n0 * n1),
19337 if (reduce == null) reduce = pair;
19339 for (i0 = i = 0; i0 < n0; ++i0) {
19340 for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) {
19341 values[i] = reduce(value0, values1[i1]);
19348 var descending = function(a, b) {
19349 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
19352 var number = function(x) {
19353 return x === null ? NaN : +x;
19356 var variance = function(values, valueof) {
19357 var n = values.length,
19365 if (valueof == null) {
19367 if (!isNaN(value = number(values[i]))) {
19368 delta = value - mean;
19369 mean += delta / ++m;
19370 sum += delta * (value - mean);
19377 if (!isNaN(value = number(valueof(values[i], i, values)))) {
19378 delta = value - mean;
19379 mean += delta / ++m;
19380 sum += delta * (value - mean);
19385 if (m > 1) return sum / (m - 1);
19388 var deviation = function(array, f) {
19389 var v = variance(array, f);
19390 return v ? Math.sqrt(v) : v;
19393 var extent = function(values, valueof) {
19394 var n = values.length,
19400 if (valueof == null) {
19401 while (++i < n) { // Find the first comparable value.
19402 if ((value = values[i]) != null && value >= value) {
19404 while (++i < n) { // Compare the remaining values.
19405 if ((value = values[i]) != null) {
19406 if (min > value) min = value;
19407 if (max < value) max = value;
19415 while (++i < n) { // Find the first comparable value.
19416 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19418 while (++i < n) { // Compare the remaining values.
19419 if ((value = valueof(values[i], i, values)) != null) {
19420 if (min > value) min = value;
19421 if (max < value) max = value;
19431 var array = Array.prototype;
19433 var slice = array.slice;
19434 var map = array.map;
19436 var constant = function(x) {
19437 return function() {
19442 var identity = function(x) {
19446 var sequence = function(start, stop, step) {
19447 start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
19450 n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
19451 range = new Array(n);
19454 range[i] = start + i * step;
19460 var e10 = Math.sqrt(50);
19461 var e5 = Math.sqrt(10);
19462 var e2 = Math.sqrt(2);
19464 var ticks = function(start, stop, count) {
19465 var reverse = stop < start,
19471 if (reverse) n = start, start = stop, stop = n;
19473 if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
19476 start = Math.ceil(start / step);
19477 stop = Math.floor(stop / step);
19478 ticks = new Array(n = Math.ceil(stop - start + 1));
19479 while (++i < n) ticks[i] = (start + i) * step;
19481 start = Math.floor(start * step);
19482 stop = Math.ceil(stop * step);
19483 ticks = new Array(n = Math.ceil(start - stop + 1));
19484 while (++i < n) ticks[i] = (start - i) / step;
19487 if (reverse) ticks.reverse();
19492 function tickIncrement(start, stop, count) {
19493 var step = (stop - start) / Math.max(0, count),
19494 power = Math.floor(Math.log(step) / Math.LN10),
19495 error = step / Math.pow(10, power);
19497 ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power)
19498 : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
19501 function tickStep(start, stop, count) {
19502 var step0 = Math.abs(stop - start) / Math.max(0, count),
19503 step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
19504 error = step0 / step1;
19505 if (error >= e10) step1 *= 10;
19506 else if (error >= e5) step1 *= 5;
19507 else if (error >= e2) step1 *= 2;
19508 return stop < start ? -step1 : step1;
19511 var sturges = function(values) {
19512 return Math.ceil(Math.log(values.length) / Math.LN2) + 1;
19515 var histogram = function() {
19516 var value = identity,
19518 threshold = sturges;
19520 function histogram(data) {
19524 values = new Array(n);
19526 for (i = 0; i < n; ++i) {
19527 values[i] = value(data[i], i, data);
19530 var xz = domain(values),
19533 tz = threshold(values, x0, x1);
19535 // Convert number of thresholds into uniform thresholds.
19536 if (!Array.isArray(tz)) {
19537 tz = tickStep(x0, x1, tz);
19538 tz = sequence(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive
19541 // Remove any thresholds outside the domain.
19543 while (tz[0] <= x0) tz.shift(), --m;
19544 while (tz[m - 1] > x1) tz.pop(), --m;
19546 var bins = new Array(m + 1),
19549 // Initialize bins.
19550 for (i = 0; i <= m; ++i) {
19551 bin = bins[i] = [];
19552 bin.x0 = i > 0 ? tz[i - 1] : x0;
19553 bin.x1 = i < m ? tz[i] : x1;
19556 // Assign data to bins by value, ignoring any outside the domain.
19557 for (i = 0; i < n; ++i) {
19559 if (x0 <= x && x <= x1) {
19560 bins[bisectRight(tz, x, 0, m)].push(data[i]);
19567 histogram.value = function(_) {
19568 return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value;
19571 histogram.domain = function(_) {
19572 return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain;
19575 histogram.thresholds = function(_) {
19576 return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold;
19582 var threshold = function(values, p, valueof) {
19583 if (valueof == null) valueof = number;
19584 if (!(n = values.length)) return;
19585 if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values);
19586 if (p >= 1) return +valueof(values[n - 1], n - 1, values);
19589 i0 = Math.floor(i),
19590 value0 = +valueof(values[i0], i0, values),
19591 value1 = +valueof(values[i0 + 1], i0 + 1, values);
19592 return value0 + (value1 - value0) * (i - i0);
19595 var freedmanDiaconis = function(values, min, max) {
19596 values = map.call(values, number).sort(ascending);
19597 return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3)));
19600 var scott = function(values, min, max) {
19601 return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));
19604 var max = function(values, valueof) {
19605 var n = values.length,
19610 if (valueof == null) {
19611 while (++i < n) { // Find the first comparable value.
19612 if ((value = values[i]) != null && value >= value) {
19614 while (++i < n) { // Compare the remaining values.
19615 if ((value = values[i]) != null && value > max) {
19624 while (++i < n) { // Find the first comparable value.
19625 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19627 while (++i < n) { // Compare the remaining values.
19628 if ((value = valueof(values[i], i, values)) != null && value > max) {
19639 var mean = function(values, valueof) {
19640 var n = values.length,
19646 if (valueof == null) {
19648 if (!isNaN(value = number(values[i]))) sum += value;
19655 if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value;
19660 if (m) return sum / m;
19663 var median = function(values, valueof) {
19664 var n = values.length,
19669 if (valueof == null) {
19671 if (!isNaN(value = number(values[i]))) {
19672 numbers.push(value);
19679 if (!isNaN(value = number(valueof(values[i], i, values)))) {
19680 numbers.push(value);
19685 return threshold(numbers.sort(ascending), 0.5);
19688 var merge = function(arrays) {
19689 var n = arrays.length,
19696 while (++i < n) j += arrays[i].length;
19697 merged = new Array(j);
19703 merged[--j] = array[m];
19710 var min = function(values, valueof) {
19711 var n = values.length,
19716 if (valueof == null) {
19717 while (++i < n) { // Find the first comparable value.
19718 if ((value = values[i]) != null && value >= value) {
19720 while (++i < n) { // Compare the remaining values.
19721 if ((value = values[i]) != null && min > value) {
19730 while (++i < n) { // Find the first comparable value.
19731 if ((value = valueof(values[i], i, values)) != null && value >= value) {
19733 while (++i < n) { // Compare the remaining values.
19734 if ((value = valueof(values[i], i, values)) != null && min > value) {
19745 var permute = function(array, indexes) {
19746 var i = indexes.length, permutes = new Array(i);
19747 while (i--) permutes[i] = array[indexes[i]];
19751 var scan = function(values, compare) {
19752 if (!(n = values.length)) return;
19759 if (compare == null) compare = ascending;
19762 if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) {
19767 if (compare(xj, xj) === 0) return j;
19770 var shuffle = function(array, i0, i1) {
19771 var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),
19776 i = Math.random() * m-- | 0;
19778 array[m + i0] = array[i + i0];
19785 var sum = function(values, valueof) {
19786 var n = values.length,
19791 if (valueof == null) {
19793 if (value = +values[i]) sum += value; // Note: zero and null are equivalent.
19799 if (value = +valueof(values[i], i, values)) sum += value;
19806 var transpose = function(matrix) {
19807 if (!(n = matrix.length)) return [];
19808 for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
19809 for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
19810 row[j] = matrix[j][i];
19816 function length(d) {
19820 var zip = function() {
19821 return transpose(arguments);
19824 var slice$1 = Array.prototype.slice;
19826 var identity$1 = function(x) {
19834 var epsilon = 1e-6;
19836 function translateX(x) {
19837 return "translate(" + x + ",0)";
19840 function translateY(y) {
19841 return "translate(0," + y + ")";
19844 function center(scale) {
19845 var offset = scale.bandwidth() / 2;
19846 if (scale.round()) offset = Math.round(offset);
19847 return function(d) {
19848 return scale(d) + offset;
19852 function entering() {
19853 return !this.__axis;
19856 function axis(orient, scale) {
19857 var tickArguments = [],
19863 k = orient === top || orient === left ? -1 : 1,
19864 x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x"),
19865 transform = orient === top || orient === bottom ? translateX : translateY;
19867 function axis(context) {
19868 var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
19869 format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$1) : tickFormat,
19870 spacing = Math.max(tickSizeInner, 0) + tickPadding,
19871 range = scale.range(),
19872 range0 = range[0] + 0.5,
19873 range1 = range[range.length - 1] + 0.5,
19874 position = (scale.bandwidth ? center : identity$1)(scale.copy()),
19875 selection = context.selection ? context.selection() : context,
19876 path = selection.selectAll(".domain").data([null]),
19877 tick = selection.selectAll(".tick").data(values, scale).order(),
19878 tickExit = tick.exit(),
19879 tickEnter = tick.enter().append("g").attr("class", "tick"),
19880 line = tick.select("line"),
19881 text = tick.select("text");
19883 path = path.merge(path.enter().insert("path", ".tick")
19884 .attr("class", "domain")
19885 .attr("stroke", "#000"));
19887 tick = tick.merge(tickEnter);
19889 line = line.merge(tickEnter.append("line")
19890 .attr("stroke", "#000")
19891 .attr(x + "2", k * tickSizeInner)
19892 .attr(y + "1", 0.5)
19893 .attr(y + "2", 0.5));
19895 text = text.merge(tickEnter.append("text")
19896 .attr("fill", "#000")
19897 .attr(x, k * spacing)
19899 .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em"));
19901 if (context !== selection) {
19902 path = path.transition(context);
19903 tick = tick.transition(context);
19904 line = line.transition(context);
19905 text = text.transition(context);
19907 tickExit = tickExit.transition(context)
19908 .attr("opacity", epsilon)
19909 .attr("transform", function(d) { return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); });
19912 .attr("opacity", epsilon)
19913 .attr("transform", function(d) { var p = this.parentNode.__axis; return transform(p && isFinite(p = p(d)) ? p : position(d)); });
19919 .attr("d", orient === left || orient == right
19920 ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter
19921 : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter);
19924 .attr("opacity", 1)
19925 .attr("transform", function(d) { return transform(position(d)); });
19928 .attr(x + "2", k * tickSizeInner);
19931 .attr(x, k * spacing)
19934 selection.filter(entering)
19935 .attr("fill", "none")
19936 .attr("font-size", 10)
19937 .attr("font-family", "sans-serif")
19938 .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle");
19941 .each(function() { this.__axis = position; });
19944 axis.scale = function(_) {
19945 return arguments.length ? (scale = _, axis) : scale;
19948 axis.ticks = function() {
19949 return tickArguments = slice$1.call(arguments), axis;
19952 axis.tickArguments = function(_) {
19953 return arguments.length ? (tickArguments = _ == null ? [] : slice$1.call(_), axis) : tickArguments.slice();
19956 axis.tickValues = function(_) {
19957 return arguments.length ? (tickValues = _ == null ? null : slice$1.call(_), axis) : tickValues && tickValues.slice();
19960 axis.tickFormat = function(_) {
19961 return arguments.length ? (tickFormat = _, axis) : tickFormat;
19964 axis.tickSize = function(_) {
19965 return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
19968 axis.tickSizeInner = function(_) {
19969 return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
19972 axis.tickSizeOuter = function(_) {
19973 return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
19976 axis.tickPadding = function(_) {
19977 return arguments.length ? (tickPadding = +_, axis) : tickPadding;
19983 function axisTop(scale) {
19984 return axis(top, scale);
19987 function axisRight(scale) {
19988 return axis(right, scale);
19991 function axisBottom(scale) {
19992 return axis(bottom, scale);
19995 function axisLeft(scale) {
19996 return axis(left, scale);
19999 var noop = {value: function() {}};
20001 function dispatch() {
20002 for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
20003 if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t);
20006 return new Dispatch(_);
20009 function Dispatch(_) {
20013 function parseTypenames(typenames, types) {
20014 return typenames.trim().split(/^|\s+/).map(function(t) {
20015 var name = "", i = t.indexOf(".");
20016 if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
20017 if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
20018 return {type: t, name: name};
20022 Dispatch.prototype = dispatch.prototype = {
20023 constructor: Dispatch,
20024 on: function(typename, callback) {
20026 T = parseTypenames(typename + "", _),
20031 // If no callback was specified, return the callback of the given type and name.
20032 if (arguments.length < 2) {
20033 while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
20037 // If a type was specified, set the callback for the given type and name.
20038 // Otherwise, if a null callback was specified, remove callbacks of the given name.
20039 if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
20041 if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);
20042 else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);
20048 var copy = {}, _ = this._;
20049 for (var t in _) copy[t] = _[t].slice();
20050 return new Dispatch(copy);
20052 call: function(type, that) {
20053 if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
20054 if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
20055 for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
20057 apply: function(type, that, args) {
20058 if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
20059 for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
20063 function get(type, name) {
20064 for (var i = 0, n = type.length, c; i < n; ++i) {
20065 if ((c = type[i]).name === name) {
20071 function set(type, name, callback) {
20072 for (var i = 0, n = type.length; i < n; ++i) {
20073 if (type[i].name === name) {
20074 type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
20078 if (callback != null) type.push({name: name, value: callback});
20082 var xhtml = "http://www.w3.org/1999/xhtml";
20085 svg: "http://www.w3.org/2000/svg",
20087 xlink: "http://www.w3.org/1999/xlink",
20088 xml: "http://www.w3.org/XML/1998/namespace",
20089 xmlns: "http://www.w3.org/2000/xmlns/"
20092 var namespace = function(name) {
20093 var prefix = name += "", i = prefix.indexOf(":");
20094 if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
20095 return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
20098 function creatorInherit(name) {
20099 return function() {
20100 var document = this.ownerDocument,
20101 uri = this.namespaceURI;
20102 return uri === xhtml && document.documentElement.namespaceURI === xhtml
20103 ? document.createElement(name)
20104 : document.createElementNS(uri, name);
20108 function creatorFixed(fullname) {
20109 return function() {
20110 return this.ownerDocument.createElementNS(fullname.space, fullname.local);
20114 var creator = function(name) {
20115 var fullname = namespace(name);
20116 return (fullname.local
20118 : creatorInherit)(fullname);
20123 function local$1() {
20128 this._ = "@" + (++nextId).toString(36);
20131 Local.prototype = local$1.prototype = {
20132 constructor: Local,
20133 get: function(node) {
20135 while (!(id in node)) if (!(node = node.parentNode)) return;
20138 set: function(node, value) {
20139 return node[this._] = value;
20141 remove: function(node) {
20142 return this._ in node && delete node[this._];
20144 toString: function() {
20149 var matcher = function(selector) {
20150 return function() {
20151 return this.matches(selector);
20155 if (typeof document !== "undefined") {
20156 var element = document.documentElement;
20157 if (!element.matches) {
20158 var vendorMatches = element.webkitMatchesSelector
20159 || element.msMatchesSelector
20160 || element.mozMatchesSelector
20161 || element.oMatchesSelector;
20162 matcher = function(selector) {
20163 return function() {
20164 return vendorMatches.call(this, selector);
20170 var matcher$1 = matcher;
20172 var filterEvents = {};
20176 if (typeof document !== "undefined") {
20177 var element$1 = document.documentElement;
20178 if (!("onmouseenter" in element$1)) {
20179 filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
20183 function filterContextListener(listener, index, group) {
20184 listener = contextListener(listener, index, group);
20185 return function(event) {
20186 var related = event.relatedTarget;
20187 if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
20188 listener.call(this, event);
20193 function contextListener(listener, index, group) {
20194 return function(event1) {
20195 var event0 = event; // Events can be reentrant (e.g., focus).
20198 listener.call(this, this.__data__, index, group);
20205 function parseTypenames$1(typenames) {
20206 return typenames.trim().split(/^|\s+/).map(function(t) {
20207 var name = "", i = t.indexOf(".");
20208 if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
20209 return {type: t, name: name};
20213 function onRemove(typename) {
20214 return function() {
20215 var on = this.__on;
20217 for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
20218 if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
20219 this.removeEventListener(o.type, o.listener, o.capture);
20224 if (++i) on.length = i;
20225 else delete this.__on;
20229 function onAdd(typename, value, capture) {
20230 var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
20231 return function(d, i, group) {
20232 var on = this.__on, o, listener = wrap(value, i, group);
20233 if (on) for (var j = 0, m = on.length; j < m; ++j) {
20234 if ((o = on[j]).type === typename.type && o.name === typename.name) {
20235 this.removeEventListener(o.type, o.listener, o.capture);
20236 this.addEventListener(o.type, o.listener = listener, o.capture = capture);
20241 this.addEventListener(typename.type, listener, capture);
20242 o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
20243 if (!on) this.__on = [o];
20248 var selection_on = function(typename, value, capture) {
20249 var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t;
20251 if (arguments.length < 2) {
20252 var on = this.node().__on;
20253 if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
20254 for (i = 0, o = on[j]; i < n; ++i) {
20255 if ((t = typenames[i]).type === o.type && t.name === o.name) {
20263 on = value ? onAdd : onRemove;
20264 if (capture == null) capture = false;
20265 for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
20269 function customEvent(event1, listener, that, args) {
20270 var event0 = event;
20271 event1.sourceEvent = event;
20274 return listener.apply(that, args);
20280 var sourceEvent = function() {
20281 var current = event, source;
20282 while (source = current.sourceEvent) current = source;
20286 var point = function(node, event) {
20287 var svg = node.ownerSVGElement || node;
20289 if (svg.createSVGPoint) {
20290 var point = svg.createSVGPoint();
20291 point.x = event.clientX, point.y = event.clientY;
20292 point = point.matrixTransform(node.getScreenCTM().inverse());
20293 return [point.x, point.y];
20296 var rect = node.getBoundingClientRect();
20297 return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
20300 var mouse = function(node) {
20301 var event = sourceEvent();
20302 if (event.changedTouches) event = event.changedTouches[0];
20303 return point(node, event);
20308 var selector = function(selector) {
20309 return selector == null ? none : function() {
20310 return this.querySelector(selector);
20314 var selection_select = function(select) {
20315 if (typeof select !== "function") select = selector(select);
20317 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
20318 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
20319 if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
20320 if ("__data__" in node) subnode.__data__ = node.__data__;
20321 subgroup[i] = subnode;
20326 return new Selection(subgroups, this._parents);
20329 function empty$1() {
20333 var selectorAll = function(selector) {
20334 return selector == null ? empty$1 : function() {
20335 return this.querySelectorAll(selector);
20339 var selection_selectAll = function(select) {
20340 if (typeof select !== "function") select = selectorAll(select);
20342 for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
20343 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
20344 if (node = group[i]) {
20345 subgroups.push(select.call(node, node.__data__, i, group));
20346 parents.push(node);
20351 return new Selection(subgroups, parents);
20354 var selection_filter = function(match) {
20355 if (typeof match !== "function") match = matcher$1(match);
20357 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
20358 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
20359 if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
20360 subgroup.push(node);
20365 return new Selection(subgroups, this._parents);
20368 var sparse = function(update) {
20369 return new Array(update.length);
20372 var selection_enter = function() {
20373 return new Selection(this._enter || this._groups.map(sparse), this._parents);
20376 function EnterNode(parent, datum) {
20377 this.ownerDocument = parent.ownerDocument;
20378 this.namespaceURI = parent.namespaceURI;
20380 this._parent = parent;
20381 this.__data__ = datum;
20384 EnterNode.prototype = {
20385 constructor: EnterNode,
20386 appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
20387 insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
20388 querySelector: function(selector) { return this._parent.querySelector(selector); },
20389 querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
20392 var constant$1 = function(x) {
20393 return function() {
20398 var keyPrefix = "$"; // Protect against keys like “__proto__”.
20400 function bindIndex(parent, group, enter, update, exit, data) {
20403 groupLength = group.length,
20404 dataLength = data.length;
20406 // Put any non-null nodes that fit into update.
20407 // Put any null nodes into enter.
20408 // Put any remaining data into enter.
20409 for (; i < dataLength; ++i) {
20410 if (node = group[i]) {
20411 node.__data__ = data[i];
20414 enter[i] = new EnterNode(parent, data[i]);
20418 // Put any non-null nodes that don’t fit into exit.
20419 for (; i < groupLength; ++i) {
20420 if (node = group[i]) {
20426 function bindKey(parent, group, enter, update, exit, data, key) {
20429 nodeByKeyValue = {},
20430 groupLength = group.length,
20431 dataLength = data.length,
20432 keyValues = new Array(groupLength),
20435 // Compute the key for each node.
20436 // If multiple nodes have the same key, the duplicates are added to exit.
20437 for (i = 0; i < groupLength; ++i) {
20438 if (node = group[i]) {
20439 keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
20440 if (keyValue in nodeByKeyValue) {
20443 nodeByKeyValue[keyValue] = node;
20448 // Compute the key for each datum.
20449 // If there a node associated with this key, join and add it to update.
20450 // If there is not (or the key is a duplicate), add it to enter.
20451 for (i = 0; i < dataLength; ++i) {
20452 keyValue = keyPrefix + key.call(parent, data[i], i, data);
20453 if (node = nodeByKeyValue[keyValue]) {
20455 node.__data__ = data[i];
20456 nodeByKeyValue[keyValue] = null;
20458 enter[i] = new EnterNode(parent, data[i]);
20462 // Add any remaining nodes that were not bound to data to exit.
20463 for (i = 0; i < groupLength; ++i) {
20464 if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
20470 var selection_data = function(value, key) {
20472 data = new Array(this.size()), j = -1;
20473 this.each(function(d) { data[++j] = d; });
20477 var bind = key ? bindKey : bindIndex,
20478 parents = this._parents,
20479 groups = this._groups;
20481 if (typeof value !== "function") value = constant$1(value);
20483 for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
20484 var parent = parents[j],
20486 groupLength = group.length,
20487 data = value.call(parent, parent && parent.__data__, j, parents),
20488 dataLength = data.length,
20489 enterGroup = enter[j] = new Array(dataLength),
20490 updateGroup = update[j] = new Array(dataLength),
20491 exitGroup = exit[j] = new Array(groupLength);
20493 bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
20495 // Now connect the enter nodes to their following update node, such that
20496 // appendChild can insert the materialized enter node before this node,
20497 // rather than at the end of the parent node.
20498 for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
20499 if (previous = enterGroup[i0]) {
20500 if (i0 >= i1) i1 = i0 + 1;
20501 while (!(next = updateGroup[i1]) && ++i1 < dataLength);
20502 previous._next = next || null;
20507 update = new Selection(update, parents);
20508 update._enter = enter;
20509 update._exit = exit;
20513 var selection_exit = function() {
20514 return new Selection(this._exit || this._groups.map(sparse), this._parents);
20517 var selection_merge = function(selection) {
20519 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) {
20520 for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
20521 if (node = group0[i] || group1[i]) {
20527 for (; j < m0; ++j) {
20528 merges[j] = groups0[j];
20531 return new Selection(merges, this._parents);
20534 var selection_order = function() {
20536 for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
20537 for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
20538 if (node = group[i]) {
20539 if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
20548 var selection_sort = function(compare) {
20549 if (!compare) compare = ascending$1;
20551 function compareNode(a, b) {
20552 return a && b ? compare(a.__data__, b.__data__) : !a - !b;
20555 for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
20556 for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
20557 if (node = group[i]) {
20558 sortgroup[i] = node;
20561 sortgroup.sort(compareNode);
20564 return new Selection(sortgroups, this._parents).order();
20567 function ascending$1(a, b) {
20568 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
20571 var selection_call = function() {
20572 var callback = arguments[0];
20573 arguments[0] = this;
20574 callback.apply(null, arguments);
20578 var selection_nodes = function() {
20579 var nodes = new Array(this.size()), i = -1;
20580 this.each(function() { nodes[++i] = this; });
20584 var selection_node = function() {
20586 for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
20587 for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
20588 var node = group[i];
20589 if (node) return node;
20596 var selection_size = function() {
20598 this.each(function() { ++size; });
20602 var selection_empty = function() {
20603 return !this.node();
20606 var selection_each = function(callback) {
20608 for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
20609 for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
20610 if (node = group[i]) callback.call(node, node.__data__, i, group);
20617 function attrRemove(name) {
20618 return function() {
20619 this.removeAttribute(name);
20623 function attrRemoveNS(fullname) {
20624 return function() {
20625 this.removeAttributeNS(fullname.space, fullname.local);
20629 function attrConstant(name, value) {
20630 return function() {
20631 this.setAttribute(name, value);
20635 function attrConstantNS(fullname, value) {
20636 return function() {
20637 this.setAttributeNS(fullname.space, fullname.local, value);
20641 function attrFunction(name, value) {
20642 return function() {
20643 var v = value.apply(this, arguments);
20644 if (v == null) this.removeAttribute(name);
20645 else this.setAttribute(name, v);
20649 function attrFunctionNS(fullname, value) {
20650 return function() {
20651 var v = value.apply(this, arguments);
20652 if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
20653 else this.setAttributeNS(fullname.space, fullname.local, v);
20657 var selection_attr = function(name, value) {
20658 var fullname = namespace(name);
20660 if (arguments.length < 2) {
20661 var node = this.node();
20662 return fullname.local
20663 ? node.getAttributeNS(fullname.space, fullname.local)
20664 : node.getAttribute(fullname);
20667 return this.each((value == null
20668 ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
20669 ? (fullname.local ? attrFunctionNS : attrFunction)
20670 : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
20673 var window$1 = function(node) {
20674 return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
20675 || (node.document && node) // node is a Window
20676 || node.defaultView; // node is a Document
20679 function styleRemove(name) {
20680 return function() {
20681 this.style.removeProperty(name);
20685 function styleConstant(name, value, priority) {
20686 return function() {
20687 this.style.setProperty(name, value, priority);
20691 function styleFunction(name, value, priority) {
20692 return function() {
20693 var v = value.apply(this, arguments);
20694 if (v == null) this.style.removeProperty(name);
20695 else this.style.setProperty(name, v, priority);
20699 var selection_style = function(name, value, priority) {
20701 return arguments.length > 1
20702 ? this.each((value == null
20703 ? styleRemove : typeof value === "function"
20705 : styleConstant)(name, value, priority == null ? "" : priority))
20706 : window$1(node = this.node())
20707 .getComputedStyle(node, null)
20708 .getPropertyValue(name);
20711 function propertyRemove(name) {
20712 return function() {
20717 function propertyConstant(name, value) {
20718 return function() {
20719 this[name] = value;
20723 function propertyFunction(name, value) {
20724 return function() {
20725 var v = value.apply(this, arguments);
20726 if (v == null) delete this[name];
20727 else this[name] = v;
20731 var selection_property = function(name, value) {
20732 return arguments.length > 1
20733 ? this.each((value == null
20734 ? propertyRemove : typeof value === "function"
20736 : propertyConstant)(name, value))
20737 : this.node()[name];
20740 function classArray(string) {
20741 return string.trim().split(/^|\s+/);
20744 function classList(node) {
20745 return node.classList || new ClassList(node);
20748 function ClassList(node) {
20750 this._names = classArray(node.getAttribute("class") || "");
20753 ClassList.prototype = {
20754 add: function(name) {
20755 var i = this._names.indexOf(name);
20757 this._names.push(name);
20758 this._node.setAttribute("class", this._names.join(" "));
20761 remove: function(name) {
20762 var i = this._names.indexOf(name);
20764 this._names.splice(i, 1);
20765 this._node.setAttribute("class", this._names.join(" "));
20768 contains: function(name) {
20769 return this._names.indexOf(name) >= 0;
20773 function classedAdd(node, names) {
20774 var list = classList(node), i = -1, n = names.length;
20775 while (++i < n) list.add(names[i]);
20778 function classedRemove(node, names) {
20779 var list = classList(node), i = -1, n = names.length;
20780 while (++i < n) list.remove(names[i]);
20783 function classedTrue(names) {
20784 return function() {
20785 classedAdd(this, names);
20789 function classedFalse(names) {
20790 return function() {
20791 classedRemove(this, names);
20795 function classedFunction(names, value) {
20796 return function() {
20797 (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
20801 var selection_classed = function(name, value) {
20802 var names = classArray(name + "");
20804 if (arguments.length < 2) {
20805 var list = classList(this.node()), i = -1, n = names.length;
20806 while (++i < n) if (!list.contains(names[i])) return false;
20810 return this.each((typeof value === "function"
20811 ? classedFunction : value
20813 : classedFalse)(names, value));
20816 function textRemove() {
20817 this.textContent = "";
20820 function textConstant(value) {
20821 return function() {
20822 this.textContent = value;
20826 function textFunction(value) {
20827 return function() {
20828 var v = value.apply(this, arguments);
20829 this.textContent = v == null ? "" : v;
20833 var selection_text = function(value) {
20834 return arguments.length
20835 ? this.each(value == null
20836 ? textRemove : (typeof value === "function"
20838 : textConstant)(value))
20839 : this.node().textContent;
20842 function htmlRemove() {
20843 this.innerHTML = "";
20846 function htmlConstant(value) {
20847 return function() {
20848 this.innerHTML = value;
20852 function htmlFunction(value) {
20853 return function() {
20854 var v = value.apply(this, arguments);
20855 this.innerHTML = v == null ? "" : v;
20859 var selection_html = function(value) {
20860 return arguments.length
20861 ? this.each(value == null
20862 ? htmlRemove : (typeof value === "function"
20864 : htmlConstant)(value))
20865 : this.node().innerHTML;
20869 if (this.nextSibling) this.parentNode.appendChild(this);
20872 var selection_raise = function() {
20873 return this.each(raise);
20877 if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
20880 var selection_lower = function() {
20881 return this.each(lower);
20884 var selection_append = function(name) {
20885 var create = typeof name === "function" ? name : creator(name);
20886 return this.select(function() {
20887 return this.appendChild(create.apply(this, arguments));
20891 function constantNull() {
20895 var selection_insert = function(name, before) {
20896 var create = typeof name === "function" ? name : creator(name),
20897 select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
20898 return this.select(function() {
20899 return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
20903 function remove() {
20904 var parent = this.parentNode;
20905 if (parent) parent.removeChild(this);
20908 var selection_remove = function() {
20909 return this.each(remove);
20912 var selection_datum = function(value) {
20913 return arguments.length
20914 ? this.property("__data__", value)
20915 : this.node().__data__;
20918 function dispatchEvent(node, type, params) {
20919 var window = window$1(node),
20920 event = window.CustomEvent;
20923 event = new event(type, params);
20925 event = window.document.createEvent("Event");
20926 if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
20927 else event.initEvent(type, false, false);
20930 node.dispatchEvent(event);
20933 function dispatchConstant(type, params) {
20934 return function() {
20935 return dispatchEvent(this, type, params);
20939 function dispatchFunction(type, params) {
20940 return function() {
20941 return dispatchEvent(this, type, params.apply(this, arguments));
20945 var selection_dispatch = function(type, params) {
20946 return this.each((typeof params === "function"
20948 : dispatchConstant)(type, params));
20953 function Selection(groups, parents) {
20954 this._groups = groups;
20955 this._parents = parents;
20958 function selection() {
20959 return new Selection([[document.documentElement]], root);
20962 Selection.prototype = selection.prototype = {
20963 constructor: Selection,
20964 select: selection_select,
20965 selectAll: selection_selectAll,
20966 filter: selection_filter,
20967 data: selection_data,
20968 enter: selection_enter,
20969 exit: selection_exit,
20970 merge: selection_merge,
20971 order: selection_order,
20972 sort: selection_sort,
20973 call: selection_call,
20974 nodes: selection_nodes,
20975 node: selection_node,
20976 size: selection_size,
20977 empty: selection_empty,
20978 each: selection_each,
20979 attr: selection_attr,
20980 style: selection_style,
20981 property: selection_property,
20982 classed: selection_classed,
20983 text: selection_text,
20984 html: selection_html,
20985 raise: selection_raise,
20986 lower: selection_lower,
20987 append: selection_append,
20988 insert: selection_insert,
20989 remove: selection_remove,
20990 datum: selection_datum,
20992 dispatch: selection_dispatch
20995 var select = function(selector) {
20996 return typeof selector === "string"
20997 ? new Selection([[document.querySelector(selector)]], [document.documentElement])
20998 : new Selection([[selector]], root);
21001 var selectAll = function(selector) {
21002 return typeof selector === "string"
21003 ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
21004 : new Selection([selector == null ? [] : selector], root);
21007 var touch = function(node, touches, identifier) {
21008 if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
21010 for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
21011 if ((touch = touches[i]).identifier === identifier) {
21012 return point(node, touch);
21019 var touches = function(node, touches) {
21020 if (touches == null) touches = sourceEvent().touches;
21022 for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) {
21023 points[i] = point(node, touches[i]);
21029 function nopropagation() {
21030 event.stopImmediatePropagation();
21033 var noevent = function() {
21034 event.preventDefault();
21035 event.stopImmediatePropagation();
21038 var dragDisable = function(view) {
21039 var root = view.document.documentElement,
21040 selection$$1 = select(view).on("dragstart.drag", noevent, true);
21041 if ("onselectstart" in root) {
21042 selection$$1.on("selectstart.drag", noevent, true);
21044 root.__noselect = root.style.MozUserSelect;
21045 root.style.MozUserSelect = "none";
21049 function yesdrag(view, noclick) {
21050 var root = view.document.documentElement,
21051 selection$$1 = select(view).on("dragstart.drag", null);
21053 selection$$1.on("click.drag", noevent, true);
21054 setTimeout(function() { selection$$1.on("click.drag", null); }, 0);
21056 if ("onselectstart" in root) {
21057 selection$$1.on("selectstart.drag", null);
21059 root.style.MozUserSelect = root.__noselect;
21060 delete root.__noselect;
21064 var constant$2 = function(x) {
21065 return function() {
21070 function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) {
21071 this.target = target;
21073 this.subject = subject;
21074 this.identifier = id;
21075 this.active = active;
21083 DragEvent.prototype.on = function() {
21084 var value = this._.on.apply(this._, arguments);
21085 return value === this._ ? this : value;
21088 // Ignore right-click, since that should open the context menu.
21089 function defaultFilter$1() {
21090 return !event.button;
21093 function defaultContainer() {
21094 return this.parentNode;
21097 function defaultSubject(d) {
21098 return d == null ? {x: event.x, y: event.y} : d;
21101 var drag = function() {
21102 var filter = defaultFilter$1,
21103 container = defaultContainer,
21104 subject = defaultSubject,
21106 listeners = dispatch("start", "drag", "end"),
21111 function drag(selection$$1) {
21113 .on("mousedown.drag", mousedowned)
21114 .on("touchstart.drag", touchstarted)
21115 .on("touchmove.drag", touchmoved)
21116 .on("touchend.drag touchcancel.drag", touchended)
21117 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
21120 function mousedowned() {
21121 if (touchending || !filter.apply(this, arguments)) return;
21122 var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments);
21123 if (!gesture) return;
21124 select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
21125 dragDisable(event.view);
21127 mousemoving = false;
21131 function mousemoved() {
21133 mousemoving = true;
21134 gestures.mouse("drag");
21137 function mouseupped() {
21138 select(event.view).on("mousemove.drag mouseup.drag", null);
21139 yesdrag(event.view, mousemoving);
21141 gestures.mouse("end");
21144 function touchstarted() {
21145 if (!filter.apply(this, arguments)) return;
21146 var touches$$1 = event.changedTouches,
21147 c = container.apply(this, arguments),
21148 n = touches$$1.length, i, gesture;
21150 for (i = 0; i < n; ++i) {
21151 if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) {
21158 function touchmoved() {
21159 var touches$$1 = event.changedTouches,
21160 n = touches$$1.length, i, gesture;
21162 for (i = 0; i < n; ++i) {
21163 if (gesture = gestures[touches$$1[i].identifier]) {
21170 function touchended() {
21171 var touches$$1 = event.changedTouches,
21172 n = touches$$1.length, i, gesture;
21174 if (touchending) clearTimeout(touchending);
21175 touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
21176 for (i = 0; i < n; ++i) {
21177 if (gesture = gestures[touches$$1[i].identifier]) {
21184 function beforestart(id, container, point, that, args) {
21185 var p = point(container, id), s, dx, dy,
21186 sublisteners = listeners.copy();
21188 if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() {
21189 if ((event.subject = s = subject.apply(that, args)) == null) return false;
21190 dx = s.x - p[0] || 0;
21191 dy = s.y - p[1] || 0;
21195 return function gesture(type) {
21198 case "start": gestures[id] = gesture, n = active++; break;
21199 case "end": delete gestures[id], --active; // nobreak
21200 case "drag": p = point(container, id), n = active; break;
21202 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]);
21206 drag.filter = function(_) {
21207 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter;
21210 drag.container = function(_) {
21211 return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container;
21214 drag.subject = function(_) {
21215 return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject;
21218 drag.on = function() {
21219 var value = listeners.on.apply(listeners, arguments);
21220 return value === listeners ? drag : value;
21226 var define = function(constructor, factory, prototype) {
21227 constructor.prototype = factory.prototype = prototype;
21228 prototype.constructor = constructor;
21231 function extend(parent, definition) {
21232 var prototype = Object.create(parent.prototype);
21233 for (var key in definition) prototype[key] = definition[key];
21237 function Color() {}
21240 var brighter = 1 / darker;
21242 var reI = "\\s*([+-]?\\d+)\\s*";
21243 var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*";
21244 var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*";
21245 var reHex3 = /^#([0-9a-f]{3})$/;
21246 var reHex6 = /^#([0-9a-f]{6})$/;
21247 var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$");
21248 var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$");
21249 var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$");
21250 var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$");
21251 var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$");
21252 var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
21255 aliceblue: 0xf0f8ff,
21256 antiquewhite: 0xfaebd7,
21258 aquamarine: 0x7fffd4,
21263 blanchedalmond: 0xffebcd,
21265 blueviolet: 0x8a2be2,
21267 burlywood: 0xdeb887,
21268 cadetblue: 0x5f9ea0,
21269 chartreuse: 0x7fff00,
21270 chocolate: 0xd2691e,
21272 cornflowerblue: 0x6495ed,
21273 cornsilk: 0xfff8dc,
21276 darkblue: 0x00008b,
21277 darkcyan: 0x008b8b,
21278 darkgoldenrod: 0xb8860b,
21279 darkgray: 0xa9a9a9,
21280 darkgreen: 0x006400,
21281 darkgrey: 0xa9a9a9,
21282 darkkhaki: 0xbdb76b,
21283 darkmagenta: 0x8b008b,
21284 darkolivegreen: 0x556b2f,
21285 darkorange: 0xff8c00,
21286 darkorchid: 0x9932cc,
21288 darksalmon: 0xe9967a,
21289 darkseagreen: 0x8fbc8f,
21290 darkslateblue: 0x483d8b,
21291 darkslategray: 0x2f4f4f,
21292 darkslategrey: 0x2f4f4f,
21293 darkturquoise: 0x00ced1,
21294 darkviolet: 0x9400d3,
21295 deeppink: 0xff1493,
21296 deepskyblue: 0x00bfff,
21299 dodgerblue: 0x1e90ff,
21300 firebrick: 0xb22222,
21301 floralwhite: 0xfffaf0,
21302 forestgreen: 0x228b22,
21304 gainsboro: 0xdcdcdc,
21305 ghostwhite: 0xf8f8ff,
21307 goldenrod: 0xdaa520,
21310 greenyellow: 0xadff2f,
21312 honeydew: 0xf0fff0,
21314 indianred: 0xcd5c5c,
21318 lavender: 0xe6e6fa,
21319 lavenderblush: 0xfff0f5,
21320 lawngreen: 0x7cfc00,
21321 lemonchiffon: 0xfffacd,
21322 lightblue: 0xadd8e6,
21323 lightcoral: 0xf08080,
21324 lightcyan: 0xe0ffff,
21325 lightgoldenrodyellow: 0xfafad2,
21326 lightgray: 0xd3d3d3,
21327 lightgreen: 0x90ee90,
21328 lightgrey: 0xd3d3d3,
21329 lightpink: 0xffb6c1,
21330 lightsalmon: 0xffa07a,
21331 lightseagreen: 0x20b2aa,
21332 lightskyblue: 0x87cefa,
21333 lightslategray: 0x778899,
21334 lightslategrey: 0x778899,
21335 lightsteelblue: 0xb0c4de,
21336 lightyellow: 0xffffe0,
21338 limegreen: 0x32cd32,
21342 mediumaquamarine: 0x66cdaa,
21343 mediumblue: 0x0000cd,
21344 mediumorchid: 0xba55d3,
21345 mediumpurple: 0x9370db,
21346 mediumseagreen: 0x3cb371,
21347 mediumslateblue: 0x7b68ee,
21348 mediumspringgreen: 0x00fa9a,
21349 mediumturquoise: 0x48d1cc,
21350 mediumvioletred: 0xc71585,
21351 midnightblue: 0x191970,
21352 mintcream: 0xf5fffa,
21353 mistyrose: 0xffe4e1,
21354 moccasin: 0xffe4b5,
21355 navajowhite: 0xffdead,
21359 olivedrab: 0x6b8e23,
21361 orangered: 0xff4500,
21363 palegoldenrod: 0xeee8aa,
21364 palegreen: 0x98fb98,
21365 paleturquoise: 0xafeeee,
21366 palevioletred: 0xdb7093,
21367 papayawhip: 0xffefd5,
21368 peachpuff: 0xffdab9,
21372 powderblue: 0xb0e0e6,
21374 rebeccapurple: 0x663399,
21376 rosybrown: 0xbc8f8f,
21377 royalblue: 0x4169e1,
21378 saddlebrown: 0x8b4513,
21380 sandybrown: 0xf4a460,
21381 seagreen: 0x2e8b57,
21382 seashell: 0xfff5ee,
21386 slateblue: 0x6a5acd,
21387 slategray: 0x708090,
21388 slategrey: 0x708090,
21390 springgreen: 0x00ff7f,
21391 steelblue: 0x4682b4,
21396 turquoise: 0x40e0d0,
21400 whitesmoke: 0xf5f5f5,
21402 yellowgreen: 0x9acd32
21405 define(Color, color, {
21406 displayable: function() {
21407 return this.rgb().displayable();
21409 toString: function() {
21410 return this.rgb() + "";
21414 function color(format) {
21416 format = (format + "").trim().toLowerCase();
21417 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
21418 : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
21419 : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
21420 : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
21421 : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
21422 : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
21423 : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
21424 : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
21425 : named.hasOwnProperty(format) ? rgbn(named[format])
21426 : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
21431 return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
21434 function rgba(r, g, b, a) {
21435 if (a <= 0) r = g = b = NaN;
21436 return new Rgb(r, g, b, a);
21439 function rgbConvert(o) {
21440 if (!(o instanceof Color)) o = color(o);
21441 if (!o) return new Rgb;
21443 return new Rgb(o.r, o.g, o.b, o.opacity);
21446 function rgb(r, g, b, opacity) {
21447 return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
21450 function Rgb(r, g, b, opacity) {
21454 this.opacity = +opacity;
21457 define(Rgb, rgb, extend(Color, {
21458 brighter: function(k) {
21459 k = k == null ? brighter : Math.pow(brighter, k);
21460 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
21462 darker: function(k) {
21463 k = k == null ? darker : Math.pow(darker, k);
21464 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
21469 displayable: function() {
21470 return (0 <= this.r && this.r <= 255)
21471 && (0 <= this.g && this.g <= 255)
21472 && (0 <= this.b && this.b <= 255)
21473 && (0 <= this.opacity && this.opacity <= 1);
21475 toString: function() {
21476 var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
21477 return (a === 1 ? "rgb(" : "rgba(")
21478 + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
21479 + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
21480 + Math.max(0, Math.min(255, Math.round(this.b) || 0))
21481 + (a === 1 ? ")" : ", " + a + ")");
21485 function hsla(h, s, l, a) {
21486 if (a <= 0) h = s = l = NaN;
21487 else if (l <= 0 || l >= 1) h = s = NaN;
21488 else if (s <= 0) h = NaN;
21489 return new Hsl(h, s, l, a);
21492 function hslConvert(o) {
21493 if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
21494 if (!(o instanceof Color)) o = color(o);
21495 if (!o) return new Hsl;
21496 if (o instanceof Hsl) return o;
21501 min = Math.min(r, g, b),
21502 max = Math.max(r, g, b),
21505 l = (max + min) / 2;
21507 if (r === max) h = (g - b) / s + (g < b) * 6;
21508 else if (g === max) h = (b - r) / s + 2;
21509 else h = (r - g) / s + 4;
21510 s /= l < 0.5 ? max + min : 2 - max - min;
21513 s = l > 0 && l < 1 ? 0 : h;
21515 return new Hsl(h, s, l, o.opacity);
21518 function hsl(h, s, l, opacity) {
21519 return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
21522 function Hsl(h, s, l, opacity) {
21526 this.opacity = +opacity;
21529 define(Hsl, hsl, extend(Color, {
21530 brighter: function(k) {
21531 k = k == null ? brighter : Math.pow(brighter, k);
21532 return new Hsl(this.h, this.s, this.l * k, this.opacity);
21534 darker: function(k) {
21535 k = k == null ? darker : Math.pow(darker, k);
21536 return new Hsl(this.h, this.s, this.l * k, this.opacity);
21539 var h = this.h % 360 + (this.h < 0) * 360,
21540 s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
21542 m2 = l + (l < 0.5 ? l : 1 - l) * s,
21545 hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
21546 hsl2rgb(h, m1, m2),
21547 hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
21551 displayable: function() {
21552 return (0 <= this.s && this.s <= 1 || isNaN(this.s))
21553 && (0 <= this.l && this.l <= 1)
21554 && (0 <= this.opacity && this.opacity <= 1);
21558 /* From FvD 13.37, CSS Color Module Level 3 */
21559 function hsl2rgb(h, m1, m2) {
21560 return (h < 60 ? m1 + (m2 - m1) * h / 60
21562 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
21566 var deg2rad = Math.PI / 180;
21567 var rad2deg = 180 / Math.PI;
21575 var t2 = 3 * t1 * t1;
21576 var t3 = t1 * t1 * t1;
21578 function labConvert(o) {
21579 if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
21580 if (o instanceof Hcl) {
21581 var h = o.h * deg2rad;
21582 return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
21584 if (!(o instanceof Rgb)) o = rgbConvert(o);
21585 var b = rgb2xyz(o.r),
21588 x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
21589 y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
21590 z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
21591 return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
21594 function lab(l, a, b, opacity) {
21595 return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
21598 function Lab(l, a, b, opacity) {
21602 this.opacity = +opacity;
21605 define(Lab, lab, extend(Color, {
21606 brighter: function(k) {
21607 return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
21609 darker: function(k) {
21610 return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
21613 var y = (this.l + 16) / 116,
21614 x = isNaN(this.a) ? y : y + this.a / 500,
21615 z = isNaN(this.b) ? y : y - this.b / 200;
21616 y = Yn * lab2xyz(y);
21617 x = Xn * lab2xyz(x);
21618 z = Zn * lab2xyz(z);
21620 xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
21621 xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
21622 xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
21628 function xyz2lab(t) {
21629 return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
21632 function lab2xyz(t) {
21633 return t > t1 ? t * t * t : t2 * (t - t0);
21636 function xyz2rgb(x) {
21637 return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
21640 function rgb2xyz(x) {
21641 return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
21644 function hclConvert(o) {
21645 if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
21646 if (!(o instanceof Lab)) o = labConvert(o);
21647 var h = Math.atan2(o.b, o.a) * rad2deg;
21648 return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
21651 function hcl(h, c, l, opacity) {
21652 return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
21655 function Hcl(h, c, l, opacity) {
21659 this.opacity = +opacity;
21662 define(Hcl, hcl, extend(Color, {
21663 brighter: function(k) {
21664 return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
21666 darker: function(k) {
21667 return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
21670 return labConvert(this).rgb();
21681 var BC_DA = B * C - D * A;
21683 function cubehelixConvert(o) {
21684 if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
21685 if (!(o instanceof Rgb)) o = rgbConvert(o);
21689 l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
21691 k = (E * (g - l) - C * bl) / D,
21692 s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
21693 h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
21694 return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
21697 function cubehelix(h, s, l, opacity) {
21698 return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
21701 function Cubehelix(h, s, l, opacity) {
21705 this.opacity = +opacity;
21708 define(Cubehelix, cubehelix, extend(Color, {
21709 brighter: function(k) {
21710 k = k == null ? brighter : Math.pow(brighter, k);
21711 return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
21713 darker: function(k) {
21714 k = k == null ? darker : Math.pow(darker, k);
21715 return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
21718 var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
21720 a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
21721 cosh = Math.cos(h),
21722 sinh = Math.sin(h);
21724 255 * (l + a * (A * cosh + B * sinh)),
21725 255 * (l + a * (C * cosh + D * sinh)),
21726 255 * (l + a * (E * cosh)),
21732 function basis(t1, v0, v1, v2, v3) {
21733 var t2 = t1 * t1, t3 = t2 * t1;
21734 return ((1 - 3 * t1 + 3 * t2 - t3) * v0
21735 + (4 - 6 * t2 + 3 * t3) * v1
21736 + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
21740 var basis$1 = function(values) {
21741 var n = values.length - 1;
21742 return function(t) {
21743 var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
21745 v2 = values[i + 1],
21746 v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
21747 v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
21748 return basis((t - i / n) * n, v0, v1, v2, v3);
21752 var basisClosed = function(values) {
21753 var n = values.length;
21754 return function(t) {
21755 var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),
21756 v0 = values[(i + n - 1) % n],
21757 v1 = values[i % n],
21758 v2 = values[(i + 1) % n],
21759 v3 = values[(i + 2) % n];
21760 return basis((t - i / n) * n, v0, v1, v2, v3);
21764 var constant$3 = function(x) {
21765 return function() {
21770 function linear(a, d) {
21771 return function(t) {
21776 function exponential(a, b, y) {
21777 return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
21778 return Math.pow(a + t * b, y);
21782 function hue(a, b) {
21784 return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a);
21787 function gamma(y) {
21788 return (y = +y) === 1 ? nogamma : function(a, b) {
21789 return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a);
21793 function nogamma(a, b) {
21795 return d ? linear(a, d) : constant$3(isNaN(a) ? b : a);
21798 var interpolateRgb = ((function rgbGamma(y) {
21799 var color$$1 = gamma(y);
21801 function rgb$$1(start, end) {
21802 var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r),
21803 g = color$$1(start.g, end.g),
21804 b = color$$1(start.b, end.b),
21805 opacity = nogamma(start.opacity, end.opacity);
21806 return function(t) {
21810 start.opacity = opacity(t);
21815 rgb$$1.gamma = rgbGamma;
21820 function rgbSpline(spline) {
21821 return function(colors) {
21822 var n = colors.length,
21827 for (i = 0; i < n; ++i) {
21828 color$$1 = rgb(colors[i]);
21829 r[i] = color$$1.r || 0;
21830 g[i] = color$$1.g || 0;
21831 b[i] = color$$1.b || 0;
21836 color$$1.opacity = 1;
21837 return function(t) {
21841 return color$$1 + "";
21846 var rgbBasis = rgbSpline(basis$1);
21847 var rgbBasisClosed = rgbSpline(basisClosed);
21849 var array$1 = function(a, b) {
21850 var nb = b ? b.length : 0,
21851 na = a ? Math.min(nb, a.length) : 0,
21856 for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]);
21857 for (; i < nb; ++i) c[i] = b[i];
21859 return function(t) {
21860 for (i = 0; i < na; ++i) c[i] = x[i](t);
21865 var date = function(a, b) {
21867 return a = +a, b -= a, function(t) {
21868 return d.setTime(a + b * t), d;
21872 var reinterpolate = function(a, b) {
21873 return a = +a, b -= a, function(t) {
21878 var object = function(a, b) {
21883 if (a === null || typeof a !== "object") a = {};
21884 if (b === null || typeof b !== "object") b = {};
21888 i[k] = interpolateValue(a[k], b[k]);
21894 return function(t) {
21895 for (k in i) c[k] = i[k](t);
21900 var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
21901 var reB = new RegExp(reA.source, "g");
21904 return function() {
21910 return function(t) {
21915 var interpolateString = function(a, b) {
21916 var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
21917 am, // current match in a
21918 bm, // current match in b
21919 bs, // string preceding current number in b, if any
21920 i = -1, // index in s
21921 s = [], // string constants and placeholders
21922 q = []; // number interpolators
21924 // Coerce inputs to strings.
21925 a = a + "", b = b + "";
21927 // Interpolate pairs of numbers in a & b.
21928 while ((am = reA.exec(a))
21929 && (bm = reB.exec(b))) {
21930 if ((bs = bm.index) > bi) { // a string precedes the next number in b
21931 bs = b.slice(bi, bs);
21932 if (s[i]) s[i] += bs; // coalesce with previous string
21935 if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
21936 if (s[i]) s[i] += bm; // coalesce with previous string
21938 } else { // interpolate non-matching numbers
21940 q.push({i: i, x: reinterpolate(am, bm)});
21942 bi = reB.lastIndex;
21945 // Add remains of b.
21946 if (bi < b.length) {
21948 if (s[i]) s[i] += bs; // coalesce with previous string
21952 // Special optimization for only a single match.
21953 // Otherwise, interpolate each of the numbers and rejoin the string.
21954 return s.length < 2 ? (q[0]
21957 : (b = q.length, function(t) {
21958 for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
21963 var interpolateValue = function(a, b) {
21964 var t = typeof b, c;
21965 return b == null || t === "boolean" ? constant$3(b)
21966 : (t === "number" ? reinterpolate
21967 : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString)
21968 : b instanceof color ? interpolateRgb
21969 : b instanceof Date ? date
21970 : Array.isArray(b) ? array$1
21971 : isNaN(b) ? object
21972 : reinterpolate)(a, b);
21975 var interpolateRound = function(a, b) {
21976 return a = +a, b -= a, function(t) {
21977 return Math.round(a + b * t);
21981 var degrees = 180 / Math.PI;
21992 var decompose = function(a, b, c, d, e, f) {
21993 var scaleX, scaleY, skewX;
21994 if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
21995 if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
21996 if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
21997 if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
22001 rotate: Math.atan2(b, a) * degrees,
22002 skewX: Math.atan(skewX) * degrees,
22013 function parseCss(value) {
22014 if (value === "none") return identity$2;
22015 if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView;
22016 cssNode.style.transform = value;
22017 value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform");
22018 cssRoot.removeChild(cssNode);
22019 value = value.slice(7, -1).split(",");
22020 return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
22023 function parseSvg(value) {
22024 if (value == null) return identity$2;
22025 if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
22026 svgNode.setAttribute("transform", value);
22027 if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2;
22028 value = value.matrix;
22029 return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
22032 function interpolateTransform(parse, pxComma, pxParen, degParen) {
22035 return s.length ? s.pop() + " " : "";
22038 function translate(xa, ya, xb, yb, s, q) {
22039 if (xa !== xb || ya !== yb) {
22040 var i = s.push("translate(", null, pxComma, null, pxParen);
22041 q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)});
22042 } else if (xb || yb) {
22043 s.push("translate(" + xb + pxComma + yb + pxParen);
22047 function rotate(a, b, s, q) {
22049 if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
22050 q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: reinterpolate(a, b)});
22052 s.push(pop(s) + "rotate(" + b + degParen);
22056 function skewX(a, b, s, q) {
22058 q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: reinterpolate(a, b)});
22060 s.push(pop(s) + "skewX(" + b + degParen);
22064 function scale(xa, ya, xb, yb, s, q) {
22065 if (xa !== xb || ya !== yb) {
22066 var i = s.push(pop(s) + "scale(", null, ",", null, ")");
22067 q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)});
22068 } else if (xb !== 1 || yb !== 1) {
22069 s.push(pop(s) + "scale(" + xb + "," + yb + ")");
22073 return function(a, b) {
22074 var s = [], // string constants and placeholders
22075 q = []; // number interpolators
22076 a = parse(a), b = parse(b);
22077 translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
22078 rotate(a.rotate, b.rotate, s, q);
22079 skewX(a.skewX, b.skewX, s, q);
22080 scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
22081 a = b = null; // gc
22082 return function(t) {
22083 var i = -1, n = q.length, o;
22084 while (++i < n) s[(o = q[i]).i] = o.x(t);
22090 var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
22091 var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
22093 var rho = Math.SQRT2;
22096 var epsilon2 = 1e-12;
22099 return ((x = Math.exp(x)) + 1 / x) / 2;
22103 return ((x = Math.exp(x)) - 1 / x) / 2;
22107 return ((x = Math.exp(2 * x)) - 1) / (x + 1);
22110 // p0 = [ux0, uy0, w0]
22111 // p1 = [ux1, uy1, w1]
22112 var interpolateZoom = function(p0, p1) {
22113 var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
22114 ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
22117 d2 = dx * dx + dy * dy,
22121 // Special case for u0 ≅ u1.
22122 if (d2 < epsilon2) {
22123 S = Math.log(w1 / w0) / rho;
22128 w0 * Math.exp(rho * t * S)
22135 var d1 = Math.sqrt(d2),
22136 b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
22137 b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
22138 r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
22139 r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
22140 S = (r1 - r0) / rho;
22144 u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
22148 w0 * coshr0 / cosh(rho * s + r0)
22153 i.duration = S * 1000;
22158 function hsl$1(hue$$1) {
22159 return function(start, end) {
22160 var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h),
22161 s = nogamma(start.s, end.s),
22162 l = nogamma(start.l, end.l),
22163 opacity = nogamma(start.opacity, end.opacity);
22164 return function(t) {
22168 start.opacity = opacity(t);
22174 var hsl$2 = hsl$1(hue);
22175 var hslLong = hsl$1(nogamma);
22177 function lab$1(start, end) {
22178 var l = nogamma((start = lab(start)).l, (end = lab(end)).l),
22179 a = nogamma(start.a, end.a),
22180 b = nogamma(start.b, end.b),
22181 opacity = nogamma(start.opacity, end.opacity);
22182 return function(t) {
22186 start.opacity = opacity(t);
22191 function hcl$1(hue$$1) {
22192 return function(start, end) {
22193 var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h),
22194 c = nogamma(start.c, end.c),
22195 l = nogamma(start.l, end.l),
22196 opacity = nogamma(start.opacity, end.opacity);
22197 return function(t) {
22201 start.opacity = opacity(t);
22207 var hcl$2 = hcl$1(hue);
22208 var hclLong = hcl$1(nogamma);
22210 function cubehelix$1(hue$$1) {
22211 return (function cubehelixGamma(y) {
22214 function cubehelix$$1(start, end) {
22215 var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h),
22216 s = nogamma(start.s, end.s),
22217 l = nogamma(start.l, end.l),
22218 opacity = nogamma(start.opacity, end.opacity);
22219 return function(t) {
22222 start.l = l(Math.pow(t, y));
22223 start.opacity = opacity(t);
22228 cubehelix$$1.gamma = cubehelixGamma;
22230 return cubehelix$$1;
22234 var cubehelix$2 = cubehelix$1(hue);
22235 var cubehelixLong = cubehelix$1(nogamma);
22237 var quantize = function(interpolator, n) {
22238 var samples = new Array(n);
22239 for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));
22246 var pokeDelay = 1000;
22252 var clock = typeof performance === "object" && performance.now ? performance : Date;
22253 var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); };
22256 return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
22259 function clearNow() {
22269 Timer.prototype = timer.prototype = {
22270 constructor: Timer,
22271 restart: function(callback, delay, time) {
22272 if (typeof callback !== "function") throw new TypeError("callback is not a function");
22273 time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
22274 if (!this._next && taskTail !== this) {
22275 if (taskTail) taskTail._next = this;
22276 else taskHead = this;
22279 this._call = callback;
22286 this._time = Infinity;
22292 function timer(callback, delay, time) {
22294 t.restart(callback, delay, time);
22298 function timerFlush() {
22299 now(); // Get the current time, if not already set.
22300 ++frame; // Pretend we’ve set an alarm, if we haven’t already.
22301 var t = taskHead, e;
22303 if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
22310 clockNow = (clockLast = clock.now()) + clockSkew;
22311 frame = timeout = 0;
22322 var now = clock.now(), delay = now - clockLast;
22323 if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
22327 var t0, t1 = taskHead, t2, time = Infinity;
22330 if (time > t1._time) time = t1._time;
22331 t0 = t1, t1 = t1._next;
22333 t2 = t1._next, t1._next = null;
22334 t1 = t0 ? t0._next = t2 : taskHead = t2;
22341 function sleep(time) {
22342 if (frame) return; // Soonest alarm already set, or will be.
22343 if (timeout) timeout = clearTimeout(timeout);
22344 var delay = time - clockNow;
22346 if (time < Infinity) timeout = setTimeout(wake, delay);
22347 if (interval) interval = clearInterval(interval);
22349 if (!interval) clockLast = clockNow, interval = setInterval(poke, pokeDelay);
22350 frame = 1, setFrame(wake);
22354 var timeout$1 = function(callback, delay, time) {
22356 delay = delay == null ? 0 : +delay;
22357 t.restart(function(elapsed) {
22359 callback(elapsed + delay);
22364 var interval$1 = function(callback, delay, time) {
22365 var t = new Timer, total = delay;
22366 if (delay == null) return t.restart(callback, delay, time), t;
22367 delay = +delay, time = time == null ? now() : +time;
22368 t.restart(function tick(elapsed) {
22370 t.restart(tick, total += delay, time);
22376 var emptyOn = dispatch("start", "end", "interrupt");
22377 var emptyTween = [];
22387 var schedule = function(node, name, id, index, group, timing) {
22388 var schedules = node.__transition;
22389 if (!schedules) node.__transition = {};
22390 else if (id in schedules) return;
22393 index: index, // For context during callback.
22394 group: group, // For context during callback.
22398 delay: timing.delay,
22399 duration: timing.duration,
22406 function init(node, id) {
22407 var schedule = node.__transition;
22408 if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late");
22412 function set$1(node, id) {
22413 var schedule = node.__transition;
22414 if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late");
22418 function get$1(node, id) {
22419 var schedule = node.__transition;
22420 if (!schedule || !(schedule = schedule[id])) throw new Error("too late");
22424 function create(node, id, self) {
22425 var schedules = node.__transition,
22428 // Initialize the self timer when the transition is created.
22429 // Note the actual delay is not known until the first callback!
22430 schedules[id] = self;
22431 self.timer = timer(schedule, 0, self.time);
22433 function schedule(elapsed) {
22434 self.state = SCHEDULED;
22435 self.timer.restart(start, self.delay, self.time);
22437 // If the elapsed delay is less than our first sleep, start immediately.
22438 if (self.delay <= elapsed) start(elapsed - self.delay);
22441 function start(elapsed) {
22444 // If the state is not SCHEDULED, then we previously errored on start.
22445 if (self.state !== SCHEDULED) return stop();
22447 for (i in schedules) {
22449 if (o.name !== self.name) continue;
22451 // While this element already has a starting transition during this frame,
22452 // defer starting an interrupting transition until that transition has a
22453 // chance to tick (and possibly end); see d3/d3-transition#54!
22454 if (o.state === STARTED) return timeout$1(start);
22456 // Interrupt the active transition, if any.
22457 // Dispatch the interrupt event.
22458 if (o.state === RUNNING) {
22461 o.on.call("interrupt", node, node.__data__, o.index, o.group);
22462 delete schedules[i];
22465 // Cancel any pre-empted transitions. No interrupt event is dispatched
22466 // because the cancelled transitions never started. Note that this also
22467 // removes this transition from the pending list!
22468 else if (+i < id) {
22471 delete schedules[i];
22475 // Defer the first tick to end of the current frame; see d3/d3#1576.
22476 // Note the transition may be canceled after start and before the first tick!
22477 // Note this must be scheduled before the start event; see d3/d3-transition#16!
22478 // Assuming this is successful, subsequent callbacks go straight to tick.
22479 timeout$1(function() {
22480 if (self.state === STARTED) {
22481 self.state = RUNNING;
22482 self.timer.restart(tick, self.delay, self.time);
22487 // Dispatch the start event.
22488 // Note this must be done before the tween are initialized.
22489 self.state = STARTING;
22490 self.on.call("start", node, node.__data__, self.index, self.group);
22491 if (self.state !== STARTING) return; // interrupted
22492 self.state = STARTED;
22494 // Initialize the tween, deleting null tween.
22495 tween = new Array(n = self.tween.length);
22496 for (i = 0, j = -1; i < n; ++i) {
22497 if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
22501 tween.length = j + 1;
22504 function tick(elapsed) {
22505 var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
22510 tween[i].call(null, t);
22513 // Dispatch the end event.
22514 if (self.state === ENDING) {
22515 self.on.call("end", node, node.__data__, self.index, self.group);
22521 self.state = ENDED;
22523 delete schedules[id];
22524 for (var i in schedules) return; // eslint-disable-line no-unused-vars
22525 delete node.__transition;
22529 var interrupt = function(node, name) {
22530 var schedules = node.__transition,
22536 if (!schedules) return;
22538 name = name == null ? null : name + "";
22540 for (i in schedules) {
22541 if ((schedule = schedules[i]).name !== name) { empty = false; continue; }
22542 active = schedule.state > STARTING && schedule.state < ENDING;
22543 schedule.state = ENDED;
22544 schedule.timer.stop();
22545 if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group);
22546 delete schedules[i];
22549 if (empty) delete node.__transition;
22552 var selection_interrupt = function(name) {
22553 return this.each(function() {
22554 interrupt(this, name);
22558 function tweenRemove(id, name) {
22559 var tween0, tween1;
22560 return function() {
22561 var schedule = set$1(this, id),
22562 tween = schedule.tween;
22564 // If this node shared tween with the previous node,
22565 // just assign the updated shared tween and we’re done!
22566 // Otherwise, copy-on-write.
22567 if (tween !== tween0) {
22568 tween1 = tween0 = tween;
22569 for (var i = 0, n = tween1.length; i < n; ++i) {
22570 if (tween1[i].name === name) {
22571 tween1 = tween1.slice();
22572 tween1.splice(i, 1);
22578 schedule.tween = tween1;
22582 function tweenFunction(id, name, value) {
22583 var tween0, tween1;
22584 if (typeof value !== "function") throw new Error;
22585 return function() {
22586 var schedule = set$1(this, id),
22587 tween = schedule.tween;
22589 // If this node shared tween with the previous node,
22590 // just assign the updated shared tween and we’re done!
22591 // Otherwise, copy-on-write.
22592 if (tween !== tween0) {
22593 tween1 = (tween0 = tween).slice();
22594 for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) {
22595 if (tween1[i].name === name) {
22600 if (i === n) tween1.push(t);
22603 schedule.tween = tween1;
22607 var transition_tween = function(name, value) {
22612 if (arguments.length < 2) {
22613 var tween = get$1(this.node(), id).tween;
22614 for (var i = 0, n = tween.length, t; i < n; ++i) {
22615 if ((t = tween[i]).name === name) {
22622 return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
22625 function tweenValue(transition, name, value) {
22626 var id = transition._id;
22628 transition.each(function() {
22629 var schedule = set$1(this, id);
22630 (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
22633 return function(node) {
22634 return get$1(node, id).value[name];
22638 var interpolate$$1 = function(a, b) {
22640 return (typeof b === "number" ? reinterpolate
22641 : b instanceof color ? interpolateRgb
22642 : (c = color(b)) ? (b = c, interpolateRgb)
22643 : interpolateString)(a, b);
22646 function attrRemove$1(name) {
22647 return function() {
22648 this.removeAttribute(name);
22652 function attrRemoveNS$1(fullname) {
22653 return function() {
22654 this.removeAttributeNS(fullname.space, fullname.local);
22658 function attrConstant$1(name, interpolate$$1, value1) {
22661 return function() {
22662 var value0 = this.getAttribute(name);
22663 return value0 === value1 ? null
22664 : value0 === value00 ? interpolate0
22665 : interpolate0 = interpolate$$1(value00 = value0, value1);
22669 function attrConstantNS$1(fullname, interpolate$$1, value1) {
22672 return function() {
22673 var value0 = this.getAttributeNS(fullname.space, fullname.local);
22674 return value0 === value1 ? null
22675 : value0 === value00 ? interpolate0
22676 : interpolate0 = interpolate$$1(value00 = value0, value1);
22680 function attrFunction$1(name, interpolate$$1, value) {
22684 return function() {
22685 var value0, value1 = value(this);
22686 if (value1 == null) return void this.removeAttribute(name);
22687 value0 = this.getAttribute(name);
22688 return value0 === value1 ? null
22689 : value0 === value00 && value1 === value10 ? interpolate0
22690 : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22694 function attrFunctionNS$1(fullname, interpolate$$1, value) {
22698 return function() {
22699 var value0, value1 = value(this);
22700 if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
22701 value0 = this.getAttributeNS(fullname.space, fullname.local);
22702 return value0 === value1 ? null
22703 : value0 === value00 && value1 === value10 ? interpolate0
22704 : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22708 var transition_attr = function(name, value) {
22709 var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$$1;
22710 return this.attrTween(name, typeof value === "function"
22711 ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value))
22712 : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname)
22713 : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value + ""));
22716 function attrTweenNS(fullname, value) {
22718 var node = this, i = value.apply(node, arguments);
22719 return i && function(t) {
22720 node.setAttributeNS(fullname.space, fullname.local, i(t));
22723 tween._value = value;
22727 function attrTween(name, value) {
22729 var node = this, i = value.apply(node, arguments);
22730 return i && function(t) {
22731 node.setAttribute(name, i(t));
22734 tween._value = value;
22738 var transition_attrTween = function(name, value) {
22739 var key = "attr." + name;
22740 if (arguments.length < 2) return (key = this.tween(key)) && key._value;
22741 if (value == null) return this.tween(key, null);
22742 if (typeof value !== "function") throw new Error;
22743 var fullname = namespace(name);
22744 return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
22747 function delayFunction(id, value) {
22748 return function() {
22749 init(this, id).delay = +value.apply(this, arguments);
22753 function delayConstant(id, value) {
22754 return value = +value, function() {
22755 init(this, id).delay = value;
22759 var transition_delay = function(value) {
22762 return arguments.length
22763 ? this.each((typeof value === "function"
22765 : delayConstant)(id, value))
22766 : get$1(this.node(), id).delay;
22769 function durationFunction(id, value) {
22770 return function() {
22771 set$1(this, id).duration = +value.apply(this, arguments);
22775 function durationConstant(id, value) {
22776 return value = +value, function() {
22777 set$1(this, id).duration = value;
22781 var transition_duration = function(value) {
22784 return arguments.length
22785 ? this.each((typeof value === "function"
22787 : durationConstant)(id, value))
22788 : get$1(this.node(), id).duration;
22791 function easeConstant(id, value) {
22792 if (typeof value !== "function") throw new Error;
22793 return function() {
22794 set$1(this, id).ease = value;
22798 var transition_ease = function(value) {
22801 return arguments.length
22802 ? this.each(easeConstant(id, value))
22803 : get$1(this.node(), id).ease;
22806 var transition_filter = function(match) {
22807 if (typeof match !== "function") match = matcher$1(match);
22809 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
22810 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
22811 if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
22812 subgroup.push(node);
22817 return new Transition(subgroups, this._parents, this._name, this._id);
22820 var transition_merge = function(transition) {
22821 if (transition._id !== this._id) throw new Error;
22823 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) {
22824 for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
22825 if (node = group0[i] || group1[i]) {
22831 for (; j < m0; ++j) {
22832 merges[j] = groups0[j];
22835 return new Transition(merges, this._parents, this._name, this._id);
22838 function start(name) {
22839 return (name + "").trim().split(/^|\s+/).every(function(t) {
22840 var i = t.indexOf(".");
22841 if (i >= 0) t = t.slice(0, i);
22842 return !t || t === "start";
22846 function onFunction(id, name, listener) {
22847 var on0, on1, sit = start(name) ? init : set$1;
22848 return function() {
22849 var schedule = sit(this, id),
22852 // If this node shared a dispatch with the previous node,
22853 // just assign the updated shared dispatch and we’re done!
22854 // Otherwise, copy-on-write.
22855 if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
22861 var transition_on = function(name, listener) {
22864 return arguments.length < 2
22865 ? get$1(this.node(), id).on.on(name)
22866 : this.each(onFunction(id, name, listener));
22869 function removeFunction(id) {
22870 return function() {
22871 var parent = this.parentNode;
22872 for (var i in this.__transition) if (+i !== id) return;
22873 if (parent) parent.removeChild(this);
22877 var transition_remove = function() {
22878 return this.on("end.remove", removeFunction(this._id));
22881 var transition_select = function(select$$1) {
22882 var name = this._name,
22885 if (typeof select$$1 !== "function") select$$1 = selector(select$$1);
22887 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
22888 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
22889 if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) {
22890 if ("__data__" in node) subnode.__data__ = node.__data__;
22891 subgroup[i] = subnode;
22892 schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
22897 return new Transition(subgroups, this._parents, name, id);
22900 var transition_selectAll = function(select$$1) {
22901 var name = this._name,
22904 if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1);
22906 for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
22907 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
22908 if (node = group[i]) {
22909 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) {
22910 if (child = children[k]) {
22911 schedule(child, name, id, k, children, inherit);
22914 subgroups.push(children);
22915 parents.push(node);
22920 return new Transition(subgroups, parents, name, id);
22923 var Selection$1 = selection.prototype.constructor;
22925 var transition_selection = function() {
22926 return new Selection$1(this._groups, this._parents);
22929 function styleRemove$1(name, interpolate$$2) {
22933 return function() {
22934 var style = window$1(this).getComputedStyle(this, null),
22935 value0 = style.getPropertyValue(name),
22936 value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
22937 return value0 === value1 ? null
22938 : value0 === value00 && value1 === value10 ? interpolate0
22939 : interpolate0 = interpolate$$2(value00 = value0, value10 = value1);
22943 function styleRemoveEnd(name) {
22944 return function() {
22945 this.style.removeProperty(name);
22949 function styleConstant$1(name, interpolate$$2, value1) {
22952 return function() {
22953 var value0 = window$1(this).getComputedStyle(this, null).getPropertyValue(name);
22954 return value0 === value1 ? null
22955 : value0 === value00 ? interpolate0
22956 : interpolate0 = interpolate$$2(value00 = value0, value1);
22960 function styleFunction$1(name, interpolate$$2, value) {
22964 return function() {
22965 var style = window$1(this).getComputedStyle(this, null),
22966 value0 = style.getPropertyValue(name),
22967 value1 = value(this);
22968 if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
22969 return value0 === value1 ? null
22970 : value0 === value00 && value1 === value10 ? interpolate0
22971 : interpolate0 = interpolate$$2(value00 = value0, value10 = value1);
22975 var transition_style = function(name, value, priority) {
22976 var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$$1;
22977 return value == null ? this
22978 .styleTween(name, styleRemove$1(name, i))
22979 .on("end.style." + name, styleRemoveEnd(name))
22980 : this.styleTween(name, typeof value === "function"
22981 ? styleFunction$1(name, i, tweenValue(this, "style." + name, value))
22982 : styleConstant$1(name, i, value + ""), priority);
22985 function styleTween(name, value, priority) {
22987 var node = this, i = value.apply(node, arguments);
22988 return i && function(t) {
22989 node.style.setProperty(name, i(t), priority);
22992 tween._value = value;
22996 var transition_styleTween = function(name, value, priority) {
22997 var key = "style." + (name += "");
22998 if (arguments.length < 2) return (key = this.tween(key)) && key._value;
22999 if (value == null) return this.tween(key, null);
23000 if (typeof value !== "function") throw new Error;
23001 return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
23004 function textConstant$1(value) {
23005 return function() {
23006 this.textContent = value;
23010 function textFunction$1(value) {
23011 return function() {
23012 var value1 = value(this);
23013 this.textContent = value1 == null ? "" : value1;
23017 var transition_text = function(value) {
23018 return this.tween("text", typeof value === "function"
23019 ? textFunction$1(tweenValue(this, "text", value))
23020 : textConstant$1(value == null ? "" : value + ""));
23023 var transition_transition = function() {
23024 var name = this._name,
23028 for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
23029 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
23030 if (node = group[i]) {
23031 var inherit = get$1(node, id0);
23032 schedule(node, name, id1, i, group, {
23033 time: inherit.time + inherit.delay + inherit.duration,
23035 duration: inherit.duration,
23042 return new Transition(groups, this._parents, name, id1);
23047 function Transition(groups, parents, name, id) {
23048 this._groups = groups;
23049 this._parents = parents;
23054 function transition(name) {
23055 return selection().transition(name);
23062 var selection_prototype = selection.prototype;
23064 Transition.prototype = transition.prototype = {
23065 constructor: Transition,
23066 select: transition_select,
23067 selectAll: transition_selectAll,
23068 filter: transition_filter,
23069 merge: transition_merge,
23070 selection: transition_selection,
23071 transition: transition_transition,
23072 call: selection_prototype.call,
23073 nodes: selection_prototype.nodes,
23074 node: selection_prototype.node,
23075 size: selection_prototype.size,
23076 empty: selection_prototype.empty,
23077 each: selection_prototype.each,
23079 attr: transition_attr,
23080 attrTween: transition_attrTween,
23081 style: transition_style,
23082 styleTween: transition_styleTween,
23083 text: transition_text,
23084 remove: transition_remove,
23085 tween: transition_tween,
23086 delay: transition_delay,
23087 duration: transition_duration,
23088 ease: transition_ease
23091 function linear$1(t) {
23095 function quadIn(t) {
23099 function quadOut(t) {
23100 return t * (2 - t);
23103 function quadInOut(t) {
23104 return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
23107 function cubicIn(t) {
23111 function cubicOut(t) {
23112 return --t * t * t + 1;
23115 function cubicInOut(t) {
23116 return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
23121 var polyIn = (function custom(e) {
23124 function polyIn(t) {
23125 return Math.pow(t, e);
23128 polyIn.exponent = custom;
23133 var polyOut = (function custom(e) {
23136 function polyOut(t) {
23137 return 1 - Math.pow(1 - t, e);
23140 polyOut.exponent = custom;
23145 var polyInOut = (function custom(e) {
23148 function polyInOut(t) {
23149 return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2;
23152 polyInOut.exponent = custom;
23158 var halfPi = pi / 2;
23160 function sinIn(t) {
23161 return 1 - Math.cos(t * halfPi);
23164 function sinOut(t) {
23165 return Math.sin(t * halfPi);
23168 function sinInOut(t) {
23169 return (1 - Math.cos(pi * t)) / 2;
23172 function expIn(t) {
23173 return Math.pow(2, 10 * t - 10);
23176 function expOut(t) {
23177 return 1 - Math.pow(2, -10 * t);
23180 function expInOut(t) {
23181 return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2;
23184 function circleIn(t) {
23185 return 1 - Math.sqrt(1 - t * t);
23188 function circleOut(t) {
23189 return Math.sqrt(1 - --t * t);
23192 function circleInOut(t) {
23193 return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2;
23205 var b0 = 1 / b1 / b1;
23207 function bounceIn(t) {
23208 return 1 - bounceOut(1 - t);
23211 function bounceOut(t) {
23212 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;
23215 function bounceInOut(t) {
23216 return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2;
23219 var overshoot = 1.70158;
23221 var backIn = (function custom(s) {
23224 function backIn(t) {
23225 return t * t * ((s + 1) * t - s);
23228 backIn.overshoot = custom;
23233 var backOut = (function custom(s) {
23236 function backOut(t) {
23237 return --t * t * ((s + 1) * t + s) + 1;
23240 backOut.overshoot = custom;
23245 var backInOut = (function custom(s) {
23248 function backInOut(t) {
23249 return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2;
23252 backInOut.overshoot = custom;
23257 var tau = 2 * Math.PI;
23261 var elasticIn = (function custom(a, p) {
23262 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23264 function elasticIn(t) {
23265 return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p);
23268 elasticIn.amplitude = function(a) { return custom(a, p * tau); };
23269 elasticIn.period = function(p) { return custom(a, p); };
23272 })(amplitude, period);
23274 var elasticOut = (function custom(a, p) {
23275 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23277 function elasticOut(t) {
23278 return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p);
23281 elasticOut.amplitude = function(a) { return custom(a, p * tau); };
23282 elasticOut.period = function(p) { return custom(a, p); };
23285 })(amplitude, period);
23287 var elasticInOut = (function custom(a, p) {
23288 var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
23290 function elasticInOut(t) {
23291 return ((t = t * 2 - 1) < 0
23292 ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p)
23293 : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2;
23296 elasticInOut.amplitude = function(a) { return custom(a, p * tau); };
23297 elasticInOut.period = function(p) { return custom(a, p); };
23299 return elasticInOut;
23300 })(amplitude, period);
23302 var defaultTiming = {
23303 time: null, // Set on use.
23309 function inherit(node, id) {
23311 while (!(timing = node.__transition) || !(timing = timing[id])) {
23312 if (!(node = node.parentNode)) {
23313 return defaultTiming.time = now(), defaultTiming;
23319 var selection_transition = function(name) {
23323 if (name instanceof Transition) {
23324 id = name._id, name = name._name;
23326 id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "";
23329 for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
23330 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
23331 if (node = group[i]) {
23332 schedule(node, name, id, i, group, timing || inherit(node, id));
23337 return new Transition(groups, this._parents, name, id);
23340 selection.prototype.interrupt = selection_interrupt;
23341 selection.prototype.transition = selection_transition;
23343 var root$1 = [null];
23345 var active = function(node, name) {
23346 var schedules = node.__transition,
23351 name = name == null ? null : name + "";
23352 for (i in schedules) {
23353 if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) {
23354 return new Transition([[node]], root$1, name, +i);
23362 var constant$4 = function(x) {
23363 return function() {
23368 var BrushEvent = function(target, type, selection) {
23369 this.target = target;
23371 this.selection = selection;
23374 function nopropagation$1() {
23375 event.stopImmediatePropagation();
23378 var noevent$1 = function() {
23379 event.preventDefault();
23380 event.stopImmediatePropagation();
23383 var MODE_DRAG = {name: "drag"};
23384 var MODE_SPACE = {name: "space"};
23385 var MODE_HANDLE = {name: "handle"};
23386 var MODE_CENTER = {name: "center"};
23390 handles: ["e", "w"].map(type$2),
23391 input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
23392 output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
23397 handles: ["n", "s"].map(type$2),
23398 input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
23399 output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
23404 handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$2),
23405 input: function(xy) { return xy; },
23406 output: function(xy) { return xy; }
23410 overlay: "crosshair",
23466 function type$2(t) {
23470 // Ignore right-click, since that should open the context menu.
23471 function defaultFilter() {
23472 return !event.button;
23475 function defaultExtent() {
23476 var svg = this.ownerSVGElement || this;
23477 return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
23480 // Like d3.local, but with the name “__brush” rather than auto-generated.
23481 function local$$1(node) {
23482 while (!node.__brush) if (!(node = node.parentNode)) return;
23483 return node.__brush;
23486 function empty(extent) {
23487 return extent[0][0] === extent[1][0]
23488 || extent[0][1] === extent[1][1];
23491 function brushSelection(node) {
23492 var state = node.__brush;
23493 return state ? state.dim.output(state.selection) : null;
23496 function brushX() {
23500 function brushY() {
23504 var brush = function() {
23505 return brush$1(XY);
23508 function brush$1(dim) {
23509 var extent = defaultExtent,
23510 filter = defaultFilter,
23511 listeners = dispatch(brush, "start", "brush", "end"),
23515 function brush(group) {
23516 var overlay = group
23517 .property("__brush", initialize)
23518 .selectAll(".overlay")
23519 .data([type$2("overlay")]);
23521 overlay.enter().append("rect")
23522 .attr("class", "overlay")
23523 .attr("pointer-events", "all")
23524 .attr("cursor", cursors.overlay)
23527 var extent = local$$1(this).extent;
23529 .attr("x", extent[0][0])
23530 .attr("y", extent[0][1])
23531 .attr("width", extent[1][0] - extent[0][0])
23532 .attr("height", extent[1][1] - extent[0][1]);
23535 group.selectAll(".selection")
23536 .data([type$2("selection")])
23537 .enter().append("rect")
23538 .attr("class", "selection")
23539 .attr("cursor", cursors.selection)
23540 .attr("fill", "#777")
23541 .attr("fill-opacity", 0.3)
23542 .attr("stroke", "#fff")
23543 .attr("shape-rendering", "crispEdges");
23545 var handle = group.selectAll(".handle")
23546 .data(dim.handles, function(d) { return d.type; });
23548 handle.exit().remove();
23550 handle.enter().append("rect")
23551 .attr("class", function(d) { return "handle handle--" + d.type; })
23552 .attr("cursor", function(d) { return cursors[d.type]; });
23556 .attr("fill", "none")
23557 .attr("pointer-events", "all")
23558 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
23559 .on("mousedown.brush touchstart.brush", started);
23562 brush.move = function(group, selection$$1) {
23563 if (group.selection) {
23565 .on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
23566 .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
23567 .tween("brush", function() {
23569 state = that.__brush,
23570 emit = emitter(that, arguments),
23571 selection0 = state.selection,
23572 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent),
23573 i = interpolateValue(selection0, selection1);
23575 function tween(t) {
23576 state.selection = t === 1 && empty(selection1) ? null : i(t);
23581 return selection0 && selection1 ? tween : tween(1);
23588 state = that.__brush,
23589 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent),
23590 emit = emitter(that, args).beforestart();
23593 state.selection = selection1 == null || empty(selection1) ? null : selection1;
23595 emit.start().brush().end();
23600 function redraw() {
23601 var group = select(this),
23602 selection$$1 = local$$1(this).selection;
23604 if (selection$$1) {
23605 group.selectAll(".selection")
23606 .style("display", null)
23607 .attr("x", selection$$1[0][0])
23608 .attr("y", selection$$1[0][1])
23609 .attr("width", selection$$1[1][0] - selection$$1[0][0])
23610 .attr("height", selection$$1[1][1] - selection$$1[0][1]);
23612 group.selectAll(".handle")
23613 .style("display", null)
23614 .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; })
23615 .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; })
23616 .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; })
23617 .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; });
23621 group.selectAll(".selection,.handle")
23622 .style("display", "none")
23625 .attr("width", null)
23626 .attr("height", null);
23630 function emitter(that, args) {
23631 return that.__brush.emitter || new Emitter(that, args);
23634 function Emitter(that, args) {
23637 this.state = that.__brush;
23641 Emitter.prototype = {
23642 beforestart: function() {
23643 if (++this.active === 1) this.state.emitter = this, this.starting = true;
23646 start: function() {
23647 if (this.starting) this.starting = false, this.emit("start");
23650 brush: function() {
23651 this.emit("brush");
23655 if (--this.active === 0) delete this.state.emitter, this.emit("end");
23658 emit: function(type) {
23659 customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
23663 function started() {
23664 if (event.touches) { if (event.changedTouches.length < event.touches.length) return noevent$1(); }
23665 else if (touchending) return;
23666 if (!filter.apply(this, arguments)) return;
23669 type = event.target.__data__.type,
23670 mode = (event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (event.altKey ? MODE_CENTER : MODE_HANDLE),
23671 signX = dim === Y ? null : signsX[type],
23672 signY = dim === X ? null : signsY[type],
23673 state = local$$1(that),
23674 extent = state.extent,
23675 selection$$1 = state.selection,
23676 W = extent[0][0], w0, w1,
23677 N = extent[0][1], n0, n1,
23678 E = extent[1][0], e0, e1,
23679 S = extent[1][1], s0, s1,
23683 shifting = signX && signY && event.shiftKey,
23686 point0 = mouse(that),
23688 emit = emitter(that, arguments).beforestart();
23690 if (type === "overlay") {
23691 state.selection = selection$$1 = [
23692 [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
23693 [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
23696 w0 = selection$$1[0][0];
23697 n0 = selection$$1[0][1];
23698 e0 = selection$$1[1][0];
23699 s0 = selection$$1[1][1];
23707 var group = select(that)
23708 .attr("pointer-events", "none");
23710 var overlay = group.selectAll(".overlay")
23711 .attr("cursor", cursors[type]);
23713 if (event.touches) {
23715 .on("touchmove.brush", moved, true)
23716 .on("touchend.brush touchcancel.brush", ended, true);
23718 var view = select(event.view)
23719 .on("keydown.brush", keydowned, true)
23720 .on("keyup.brush", keyupped, true)
23721 .on("mousemove.brush", moved, true)
23722 .on("mouseup.brush", ended, true);
23724 dragDisable(event.view);
23733 var point1 = mouse(that);
23734 if (shifting && !lockX && !lockY) {
23735 if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
23747 dx = point[0] - point0[0];
23748 dy = point[1] - point0[1];
23753 if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
23754 if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
23757 case MODE_HANDLE: {
23758 if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
23759 else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
23760 if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
23761 else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
23764 case MODE_CENTER: {
23765 if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
23766 if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
23773 t = w0, w0 = e0, e0 = t;
23774 t = w1, w1 = e1, e1 = t;
23775 if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
23780 t = n0, n0 = s0, s0 = t;
23781 t = n1, n1 = s1, s1 = t;
23782 if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
23785 if (state.selection) selection$$1 = state.selection; // May be set by brush.move!
23786 if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0];
23787 if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1];
23789 if (selection$$1[0][0] !== w1
23790 || selection$$1[0][1] !== n1
23791 || selection$$1[1][0] !== e1
23792 || selection$$1[1][1] !== s1) {
23793 state.selection = [[w1, n1], [e1, s1]];
23801 if (event.touches) {
23802 if (event.touches.length) return;
23803 if (touchending) clearTimeout(touchending);
23804 touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
23805 group.on("touchmove.brush touchend.brush touchcancel.brush", null);
23807 yesdrag(event.view, moving);
23808 view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
23810 group.attr("pointer-events", "all");
23811 overlay.attr("cursor", cursors.overlay);
23812 if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)!
23813 if (empty(selection$$1)) state.selection = null, redraw.call(that);
23817 function keydowned() {
23818 switch (event.keyCode) {
23819 case 16: { // SHIFT
23820 shifting = signX && signY;
23824 if (mode === MODE_HANDLE) {
23825 if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
23826 if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
23827 mode = MODE_CENTER;
23832 case 32: { // SPACE; takes priority over ALT
23833 if (mode === MODE_HANDLE || mode === MODE_CENTER) {
23834 if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
23835 if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
23837 overlay.attr("cursor", cursors.selection);
23847 function keyupped() {
23848 switch (event.keyCode) {
23849 case 16: { // SHIFT
23851 lockX = lockY = shifting = false;
23857 if (mode === MODE_CENTER) {
23858 if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
23859 if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
23860 mode = MODE_HANDLE;
23865 case 32: { // SPACE
23866 if (mode === MODE_SPACE) {
23867 if (event.altKey) {
23868 if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
23869 if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
23870 mode = MODE_CENTER;
23872 if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
23873 if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
23874 mode = MODE_HANDLE;
23876 overlay.attr("cursor", cursors[type]);
23887 function initialize() {
23888 var state = this.__brush || {selection: null};
23889 state.extent = extent.apply(this, arguments);
23894 brush.extent = function(_) {
23895 return arguments.length ? (extent = typeof _ === "function" ? _ : constant$4([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent;
23898 brush.filter = function(_) {
23899 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$4(!!_), brush) : filter;
23902 brush.handleSize = function(_) {
23903 return arguments.length ? (handleSize = +_, brush) : handleSize;
23906 brush.on = function() {
23907 var value = listeners.on.apply(listeners, arguments);
23908 return value === listeners ? brush : value;
23914 var cos = Math.cos;
23915 var sin = Math.sin;
23916 var pi$1 = Math.PI;
23917 var halfPi$1 = pi$1 / 2;
23918 var tau$1 = pi$1 * 2;
23919 var max$1 = Math.max;
23921 function compareValue(compare) {
23922 return function(a, b) {
23924 a.source.value + a.target.value,
23925 b.source.value + b.target.value
23930 var chord = function() {
23933 sortSubgroups = null,
23936 function chord(matrix) {
23937 var n = matrix.length,
23939 groupIndex = sequence(n),
23940 subgroupIndex = [],
23942 groups = chords.groups = new Array(n),
23943 subgroups = new Array(n * n),
23951 // Compute the sum.
23952 k = 0, i = -1; while (++i < n) {
23953 x = 0, j = -1; while (++j < n) {
23957 subgroupIndex.push(sequence(n));
23962 if (sortGroups) groupIndex.sort(function(a, b) {
23963 return sortGroups(groupSums[a], groupSums[b]);
23967 if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
23968 d.sort(function(a, b) {
23969 return sortSubgroups(matrix[i][a], matrix[i][b]);
23973 // Convert the sum to scaling factor for [0, 2pi].
23974 // TODO Allow start and end angle to be specified?
23975 // TODO Allow padding to be specified as percentage?
23976 k = max$1(0, tau$1 - padAngle * n) / k;
23977 dx = k ? padAngle : tau$1 / n;
23979 // Compute the start and end angle for each group and subgroup.
23980 // Note: Opera has a bug reordering object literal properties!
23981 x = 0, i = -1; while (++i < n) {
23982 x0 = x, j = -1; while (++j < n) {
23983 var di = groupIndex[i],
23984 dj = subgroupIndex[di][j],
23985 v = matrix[di][dj],
23988 subgroups[dj * n + di] = {
24000 value: groupSums[di]
24005 // Generate chords for each (non-empty) subgroup-subgroup link.
24006 i = -1; while (++i < n) {
24007 j = i - 1; while (++j < n) {
24008 var source = subgroups[j * n + i],
24009 target = subgroups[i * n + j];
24010 if (source.value || target.value) {
24011 chords.push(source.value < target.value
24012 ? {source: target, target: source}
24013 : {source: source, target: target});
24018 return sortChords ? chords.sort(sortChords) : chords;
24021 chord.padAngle = function(_) {
24022 return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle;
24025 chord.sortGroups = function(_) {
24026 return arguments.length ? (sortGroups = _, chord) : sortGroups;
24029 chord.sortSubgroups = function(_) {
24030 return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
24033 chord.sortChords = function(_) {
24034 return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
24040 var slice$2 = Array.prototype.slice;
24042 var constant$5 = function(x) {
24043 return function() {
24048 var pi$2 = Math.PI;
24049 var tau$2 = 2 * pi$2;
24050 var epsilon$1 = 1e-6;
24051 var tauEpsilon = tau$2 - epsilon$1;
24054 this._x0 = this._y0 = // start of current subpath
24055 this._x1 = this._y1 = null; // end of current subpath
24063 Path.prototype = path.prototype = {
24065 moveTo: function(x, y) {
24066 this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
24068 closePath: function() {
24069 if (this._x1 !== null) {
24070 this._x1 = this._x0, this._y1 = this._y0;
24074 lineTo: function(x, y) {
24075 this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
24077 quadraticCurveTo: function(x1, y1, x, y) {
24078 this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
24080 bezierCurveTo: function(x1, y1, x2, y2, x, y) {
24081 this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
24083 arcTo: function(x1, y1, x2, y2, r) {
24084 x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
24091 l01_2 = x01 * x01 + y01 * y01;
24093 // Is the radius negative? Error.
24094 if (r < 0) throw new Error("negative radius: " + r);
24096 // Is this path empty? Move to (x1,y1).
24097 if (this._x1 === null) {
24098 this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1);
24101 // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
24102 else if (!(l01_2 > epsilon$1)) {}
24104 // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
24105 // Equivalently, is (x1,y1) coincident with (x2,y2)?
24106 // Or, is the radius zero? Line to (x1,y1).
24107 else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon$1) || !r) {
24108 this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1);
24111 // Otherwise, draw an arc!
24115 l21_2 = x21 * x21 + y21 * y21,
24116 l20_2 = x20 * x20 + y20 * y20,
24117 l21 = Math.sqrt(l21_2),
24118 l01 = Math.sqrt(l01_2),
24119 l = r * Math.tan((pi$2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
24123 // If the start tangent is not coincident with (x0,y0), line to.
24124 if (Math.abs(t01 - 1) > epsilon$1) {
24125 this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01);
24128 this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21);
24131 arc: function(x, y, r, a0, a1, ccw) {
24132 x = +x, y = +y, r = +r;
24133 var dx = r * Math.cos(a0),
24134 dy = r * Math.sin(a0),
24138 da = ccw ? a0 - a1 : a1 - a0;
24140 // Is the radius negative? Error.
24141 if (r < 0) throw new Error("negative radius: " + r);
24143 // Is this path empty? Move to (x0,y0).
24144 if (this._x1 === null) {
24145 this._ += "M" + x0 + "," + y0;
24148 // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
24149 else if (Math.abs(this._x1 - x0) > epsilon$1 || Math.abs(this._y1 - y0) > epsilon$1) {
24150 this._ += "L" + x0 + "," + y0;
24153 // Is this arc empty? We’re done.
24156 // Does the angle go the wrong way? Flip the direction.
24157 if (da < 0) da = da % tau$2 + tau$2;
24159 // Is this a complete circle? Draw two arcs to complete the circle.
24160 if (da > tauEpsilon) {
24161 this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0);
24164 // Is this arc non-empty? Draw an arc!
24165 else if (da > epsilon$1) {
24166 this._ += "A" + r + "," + r + ",0," + (+(da >= pi$2)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1));
24169 rect: function(x, y, w, h) {
24170 this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z";
24172 toString: function() {
24177 function defaultSource(d) {
24181 function defaultTarget(d) {
24185 function defaultRadius(d) {
24189 function defaultStartAngle(d) {
24190 return d.startAngle;
24193 function defaultEndAngle(d) {
24197 var ribbon = function() {
24198 var source = defaultSource,
24199 target = defaultTarget,
24200 radius = defaultRadius,
24201 startAngle = defaultStartAngle,
24202 endAngle = defaultEndAngle,
24205 function ribbon() {
24207 argv = slice$2.call(arguments),
24208 s = source.apply(this, argv),
24209 t = target.apply(this, argv),
24210 sr = +radius.apply(this, (argv[0] = s, argv)),
24211 sa0 = startAngle.apply(this, argv) - halfPi$1,
24212 sa1 = endAngle.apply(this, argv) - halfPi$1,
24213 sx0 = sr * cos(sa0),
24214 sy0 = sr * sin(sa0),
24215 tr = +radius.apply(this, (argv[0] = t, argv)),
24216 ta0 = startAngle.apply(this, argv) - halfPi$1,
24217 ta1 = endAngle.apply(this, argv) - halfPi$1;
24219 if (!context) context = buffer = path();
24221 context.moveTo(sx0, sy0);
24222 context.arc(0, 0, sr, sa0, sa1);
24223 if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr?
24224 context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0));
24225 context.arc(0, 0, tr, ta0, ta1);
24227 context.quadraticCurveTo(0, 0, sx0, sy0);
24228 context.closePath();
24230 if (buffer) return context = null, buffer + "" || null;
24233 ribbon.radius = function(_) {
24234 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$5(+_), ribbon) : radius;
24237 ribbon.startAngle = function(_) {
24238 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : startAngle;
24241 ribbon.endAngle = function(_) {
24242 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : endAngle;
24245 ribbon.source = function(_) {
24246 return arguments.length ? (source = _, ribbon) : source;
24249 ribbon.target = function(_) {
24250 return arguments.length ? (target = _, ribbon) : target;
24253 ribbon.context = function(_) {
24254 return arguments.length ? ((context = _ == null ? null : _), ribbon) : context;
24264 Map.prototype = map$1.prototype = {
24266 has: function(key) {
24267 return (prefix + key) in this;
24269 get: function(key) {
24270 return this[prefix + key];
24272 set: function(key, value) {
24273 this[prefix + key] = value;
24276 remove: function(key) {
24277 var property = prefix + key;
24278 return property in this && delete this[property];
24280 clear: function() {
24281 for (var property in this) if (property[0] === prefix) delete this[property];
24285 for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
24288 values: function() {
24290 for (var property in this) if (property[0] === prefix) values.push(this[property]);
24293 entries: function() {
24295 for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
24300 for (var property in this) if (property[0] === prefix) ++size;
24303 empty: function() {
24304 for (var property in this) if (property[0] === prefix) return false;
24307 each: function(f) {
24308 for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
24312 function map$1(object, f) {
24315 // Copy constructor.
24316 if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
24318 // Index array by numeric index or specified key function.
24319 else if (Array.isArray(object)) {
24324 if (f == null) while (++i < n) map.set(i, object[i]);
24325 else while (++i < n) map.set(f(o = object[i], i, object), o);
24328 // Convert object to map.
24329 else if (object) for (var key in object) map.set(key, object[key]);
24334 var nest = function() {
24341 function apply(array, depth, createResult, setResult) {
24342 if (depth >= keys.length) return rollup != null
24343 ? rollup(array) : (sortValues != null
24344 ? array.sort(sortValues)
24349 key = keys[depth++],
24352 valuesByKey = map$1(),
24354 result = createResult();
24357 if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
24358 values.push(value);
24360 valuesByKey.set(keyValue, [value]);
24364 valuesByKey.each(function(values, key) {
24365 setResult(result, key, apply(values, depth, createResult, setResult));
24371 function entries(map, depth) {
24372 if (++depth > keys.length) return map;
24373 var array, sortKey = sortKeys[depth - 1];
24374 if (rollup != null && depth >= keys.length) array = map.entries();
24375 else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); });
24376 return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array;
24380 object: function(array) { return apply(array, 0, createObject, setObject); },
24381 map: function(array) { return apply(array, 0, createMap, setMap); },
24382 entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
24383 key: function(d) { keys.push(d); return nest; },
24384 sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
24385 sortValues: function(order) { sortValues = order; return nest; },
24386 rollup: function(f) { rollup = f; return nest; }
24390 function createObject() {
24394 function setObject(object, key, value) {
24395 object[key] = value;
24398 function createMap() {
24402 function setMap(map, key, value) {
24403 map.set(key, value);
24408 var proto = map$1.prototype;
24410 Set.prototype = set$2.prototype = {
24413 add: function(value) {
24415 this[prefix + value] = value;
24418 remove: proto.remove,
24419 clear: proto.clear,
24420 values: proto.keys,
24422 empty: proto.empty,
24426 function set$2(object, f) {
24429 // Copy constructor.
24430 if (object instanceof Set) object.each(function(value) { set.add(value); });
24432 // Otherwise, assume it’s an array.
24434 var i = -1, n = object.length;
24435 if (f == null) while (++i < n) set.add(object[i]);
24436 else while (++i < n) set.add(f(object[i], i, object));
24442 var keys = function(map) {
24444 for (var key in map) keys.push(key);
24448 var values = function(map) {
24450 for (var key in map) values.push(map[key]);
24454 var entries = function(map) {
24456 for (var key in map) entries.push({key: key, value: map[key]});
24460 function objectConverter(columns) {
24461 return new Function("d", "return {" + columns.map(function(name, i) {
24462 return JSON.stringify(name) + ": d[" + i + "]";
24463 }).join(",") + "}");
24466 function customConverter(columns, f) {
24467 var object = objectConverter(columns);
24468 return function(row, i) {
24469 return f(object(row), i, columns);
24473 // Compute unique columns in order of discovery.
24474 function inferColumns(rows) {
24475 var columnSet = Object.create(null),
24478 rows.forEach(function(row) {
24479 for (var column in row) {
24480 if (!(column in columnSet)) {
24481 columns.push(columnSet[column] = column);
24489 var dsv = function(delimiter) {
24490 var reFormat = new RegExp("[\"" + delimiter + "\n\r]"),
24491 delimiterCode = delimiter.charCodeAt(0);
24493 function parse(text, f) {
24494 var convert, columns, rows = parseRows(text, function(row, i) {
24495 if (convert) return convert(row, i - 1);
24496 columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
24498 rows.columns = columns;
24502 function parseRows(text, f) {
24503 var EOL = {}, // sentinel value for end-of-line
24504 EOF = {}, // sentinel value for end-of-file
24505 rows = [], // output rows
24507 I = 0, // current character index
24508 n = 0, // the current line number
24509 t, // the current token
24510 eol; // is the current token followed by EOL?
24513 if (I >= N) return EOF; // special case: end of file
24514 if (eol) return eol = false, EOL; // special case: end of line
24516 // special case: quotes
24518 if (text.charCodeAt(j) === 34) {
24521 if (text.charCodeAt(i) === 34) {
24522 if (text.charCodeAt(i + 1) !== 34) break;
24527 c = text.charCodeAt(i + 1);
24530 if (text.charCodeAt(i + 2) === 10) ++I;
24531 } else if (c === 10) {
24534 return text.slice(j + 1, i).replace(/""/g, "\"");
24537 // common case: find next delimiter or newline
24540 c = text.charCodeAt(I++);
24541 if (c === 10) eol = true; // \n
24542 else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
24543 else if (c !== delimiterCode) continue;
24544 return text.slice(j, I - k);
24547 // special case: last token before EOF
24548 return text.slice(j);
24551 while ((t = token()) !== EOF) {
24553 while (t !== EOL && t !== EOF) {
24557 if (f && (a = f(a, n++)) == null) continue;
24564 function format(rows, columns) {
24565 if (columns == null) columns = inferColumns(rows);
24566 return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
24567 return columns.map(function(column) {
24568 return formatValue(row[column]);
24569 }).join(delimiter);
24573 function formatRows(rows) {
24574 return rows.map(formatRow).join("\n");
24577 function formatRow(row) {
24578 return row.map(formatValue).join(delimiter);
24581 function formatValue(text) {
24582 return text == null ? ""
24583 : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\""
24589 parseRows: parseRows,
24591 formatRows: formatRows
24595 var csv = dsv(",");
24597 var csvParse = csv.parse;
24598 var csvParseRows = csv.parseRows;
24599 var csvFormat = csv.format;
24600 var csvFormatRows = csv.formatRows;
24602 var tsv = dsv("\t");
24604 var tsvParse = tsv.parse;
24605 var tsvParseRows = tsv.parseRows;
24606 var tsvFormat = tsv.format;
24607 var tsvFormatRows = tsv.formatRows;
24609 var center$1 = function(x, y) {
24612 if (x == null) x = 0;
24613 if (y == null) y = 0;
24622 for (i = 0; i < n; ++i) {
24623 node = nodes[i], sx += node.x, sy += node.y;
24626 for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) {
24627 node = nodes[i], node.x -= sx, node.y -= sy;
24631 force.initialize = function(_) {
24635 force.x = function(_) {
24636 return arguments.length ? (x = +_, force) : x;
24639 force.y = function(_) {
24640 return arguments.length ? (y = +_, force) : y;
24646 var constant$6 = function(x) {
24647 return function() {
24652 var jiggle = function() {
24653 return (Math.random() - 0.5) * 1e-6;
24656 var tree_add = function(d) {
24657 var x = +this._x.call(null, d),
24658 y = +this._y.call(null, d);
24659 return add(this.cover(x, y), x, y, d);
24662 function add(tree, x, y, d) {
24663 if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
24681 // If the tree is empty, initialize the root as a leaf.
24682 if (!node) return tree._root = leaf, tree;
24684 // Find the existing leaf for the new point, or add it.
24685 while (node.length) {
24686 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24687 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24688 if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
24691 // Is the new point is exactly coincident with the existing point?
24692 xp = +tree._x.call(null, node.data);
24693 yp = +tree._y.call(null, node.data);
24694 if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
24696 // Otherwise, split the leaf node until the old and new point are separated.
24698 parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
24699 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24700 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24701 } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
24702 return parent[j] = node, parent[i] = leaf, tree;
24705 function addAll(data) {
24706 var d, i, n = data.length,
24716 // Compute the points and their extent.
24717 for (i = 0; i < n; ++i) {
24718 if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
24721 if (x < x0) x0 = x;
24722 if (x > x1) x1 = x;
24723 if (y < y0) y0 = y;
24724 if (y > y1) y1 = y;
24727 // If there were no (valid) points, inherit the existing extent.
24728 if (x1 < x0) x0 = this._x0, x1 = this._x1;
24729 if (y1 < y0) y0 = this._y0, y1 = this._y1;
24731 // Expand the tree to cover the new points.
24732 this.cover(x0, y0).cover(x1, y1);
24734 // Add the new points.
24735 for (i = 0; i < n; ++i) {
24736 add(this, xz[i], yz[i], data[i]);
24742 var tree_cover = function(x, y) {
24743 if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
24750 // If the quadtree has no extent, initialize them.
24751 // Integer extent are necessary so that if we later double the extent,
24752 // the existing quadrant boundaries don’t change due to floating point error!
24754 x1 = (x0 = Math.floor(x)) + 1;
24755 y1 = (y0 = Math.floor(y)) + 1;
24758 // Otherwise, double repeatedly to cover.
24759 else if (x0 > x || x > x1 || y0 > y || y > y1) {
24765 switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
24767 do parent = new Array(4), parent[i] = node, node = parent;
24768 while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
24772 do parent = new Array(4), parent[i] = node, node = parent;
24773 while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
24777 do parent = new Array(4), parent[i] = node, node = parent;
24778 while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
24782 do parent = new Array(4), parent[i] = node, node = parent;
24783 while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
24788 if (this._root && this._root.length) this._root = node;
24791 // If the quadtree covers the point already, just return.
24801 var tree_data = function() {
24803 this.visit(function(node) {
24804 if (!node.length) do data.push(node.data); while (node = node.next)
24809 var tree_extent = function(_) {
24810 return arguments.length
24811 ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
24812 : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
24815 var Quad = function(node, x0, y0, x1, y1) {
24823 var tree_find = function(x, y, radius) {
24838 if (node) quads.push(new Quad(node, x0, y0, x3, y3));
24839 if (radius == null) radius = Infinity;
24841 x0 = x - radius, y0 = y - radius;
24842 x3 = x + radius, y3 = y + radius;
24846 while (q = quads.pop()) {
24848 // Stop searching if this quadrant can’t contain a closer node.
24849 if (!(node = q.node)
24850 || (x1 = q.x0) > x3
24851 || (y1 = q.y0) > y3
24852 || (x2 = q.x1) < x0
24853 || (y2 = q.y1) < y0) continue;
24855 // Bisect the current quadrant.
24857 var xm = (x1 + x2) / 2,
24858 ym = (y1 + y2) / 2;
24861 new Quad(node[3], xm, ym, x2, y2),
24862 new Quad(node[2], x1, ym, xm, y2),
24863 new Quad(node[1], xm, y1, x2, ym),
24864 new Quad(node[0], x1, y1, xm, ym)
24867 // Visit the closest quadrant first.
24868 if (i = (y >= ym) << 1 | (x >= xm)) {
24869 q = quads[quads.length - 1];
24870 quads[quads.length - 1] = quads[quads.length - 1 - i];
24871 quads[quads.length - 1 - i] = q;
24875 // Visit this point. (Visiting coincident points isn’t necessary!)
24877 var dx = x - +this._x.call(null, node.data),
24878 dy = y - +this._y.call(null, node.data),
24879 d2 = dx * dx + dy * dy;
24881 var d = Math.sqrt(radius = d2);
24882 x0 = x - d, y0 = y - d;
24883 x3 = x + d, y3 = y + d;
24892 var tree_remove = function(d) {
24893 if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
24913 // If the tree is empty, initialize the root as a leaf.
24914 if (!node) return this;
24916 // Find the leaf node for the point.
24917 // While descending, also retain the deepest parent with a non-removed sibling.
24918 if (node.length) while (true) {
24919 if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24920 if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24921 if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
24922 if (!node.length) break;
24923 if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
24926 // Find the point to remove.
24927 while (node.data !== d) if (!(previous = node, node = node.next)) return this;
24928 if (next = node.next) delete node.next;
24930 // If there are multiple coincident points, remove just the point.
24931 if (previous) return (next ? previous.next = next : delete previous.next), this;
24933 // If this is the root point, remove it.
24934 if (!parent) return this._root = next, this;
24936 // Remove this leaf.
24937 next ? parent[i] = next : delete parent[i];
24939 // If the parent now contains exactly one leaf, collapse superfluous parents.
24940 if ((node = parent[0] || parent[1] || parent[2] || parent[3])
24941 && node === (parent[3] || parent[2] || parent[1] || parent[0])
24943 if (retainer) retainer[j] = node;
24944 else this._root = node;
24950 function removeAll(data) {
24951 for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
24955 var tree_root = function() {
24959 var tree_size = function() {
24961 this.visit(function(node) {
24962 if (!node.length) do ++size; while (node = node.next)
24967 var tree_visit = function(callback) {
24968 var quads = [], q, node = this._root, child, x0, y0, x1, y1;
24969 if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
24970 while (q = quads.pop()) {
24971 if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
24972 var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
24973 if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
24974 if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
24975 if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
24976 if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
24982 var tree_visitAfter = function(callback) {
24983 var quads = [], next = [], q;
24984 if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
24985 while (q = quads.pop()) {
24988 var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
24989 if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
24990 if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
24991 if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
24992 if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
24996 while (q = next.pop()) {
24997 callback(q.node, q.x0, q.y0, q.x1, q.y1);
25002 function defaultX(d) {
25006 var tree_x = function(_) {
25007 return arguments.length ? (this._x = _, this) : this._x;
25010 function defaultY(d) {
25014 var tree_y = function(_) {
25015 return arguments.length ? (this._y = _, this) : this._y;
25018 function quadtree(nodes, x, y) {
25019 var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
25020 return nodes == null ? tree : tree.addAll(nodes);
25023 function Quadtree(x, y, x0, y0, x1, y1) {
25030 this._root = undefined;
25033 function leaf_copy(leaf) {
25034 var copy = {data: leaf.data}, next = copy;
25035 while (leaf = leaf.next) next = next.next = {data: leaf.data};
25039 var treeProto = quadtree.prototype = Quadtree.prototype;
25041 treeProto.copy = function() {
25042 var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
25047 if (!node) return copy;
25049 if (!node.length) return copy._root = leaf_copy(node), copy;
25051 nodes = [{source: node, target: copy._root = new Array(4)}];
25052 while (node = nodes.pop()) {
25053 for (var i = 0; i < 4; ++i) {
25054 if (child = node.source[i]) {
25055 if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
25056 else node.target[i] = leaf_copy(child);
25064 treeProto.add = tree_add;
25065 treeProto.addAll = addAll;
25066 treeProto.cover = tree_cover;
25067 treeProto.data = tree_data;
25068 treeProto.extent = tree_extent;
25069 treeProto.find = tree_find;
25070 treeProto.remove = tree_remove;
25071 treeProto.removeAll = removeAll;
25072 treeProto.root = tree_root;
25073 treeProto.size = tree_size;
25074 treeProto.visit = tree_visit;
25075 treeProto.visitAfter = tree_visitAfter;
25076 treeProto.x = tree_x;
25077 treeProto.y = tree_y;
25087 var collide = function(radius) {
25093 if (typeof radius !== "function") radius = constant$6(radius == null ? 1 : +radius);
25096 var i, n = nodes.length,
25104 for (var k = 0; k < iterations; ++k) {
25105 tree = quadtree(nodes, x, y).visitAfter(prepare);
25106 for (i = 0; i < n; ++i) {
25108 ri = radii[node.index], ri2 = ri * ri;
25109 xi = node.x + node.vx;
25110 yi = node.y + node.vy;
25115 function apply(quad, x0, y0, x1, y1) {
25116 var data = quad.data, rj = quad.r, r = ri + rj;
25118 if (data.index > node.index) {
25119 var x = xi - data.x - data.vx,
25120 y = yi - data.y - data.vy,
25123 if (x === 0) x = jiggle(), l += x * x;
25124 if (y === 0) y = jiggle(), l += y * y;
25125 l = (r - (l = Math.sqrt(l))) / l * strength;
25126 node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
25127 node.vy += (y *= l) * r;
25128 data.vx -= x * (r = 1 - r);
25134 return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
25138 function prepare(quad) {
25139 if (quad.data) return quad.r = radii[quad.data.index];
25140 for (var i = quad.r = 0; i < 4; ++i) {
25141 if (quad[i] && quad[i].r > quad.r) {
25142 quad.r = quad[i].r;
25147 function initialize() {
25148 if (!nodes) return;
25149 var i, n = nodes.length, node;
25150 radii = new Array(n);
25151 for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);
25154 force.initialize = function(_) {
25159 force.iterations = function(_) {
25160 return arguments.length ? (iterations = +_, force) : iterations;
25163 force.strength = function(_) {
25164 return arguments.length ? (strength = +_, force) : strength;
25167 force.radius = function(_) {
25168 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : radius;
25174 function index$3(d) {
25178 function find(nodeById, nodeId) {
25179 var node = nodeById.get(nodeId);
25180 if (!node) throw new Error("missing: " + nodeId);
25184 var link = function(links) {
25186 strength = defaultStrength,
25188 distance = constant$6(30),
25195 if (links == null) links = [];
25197 function defaultStrength(link) {
25198 return 1 / Math.min(count[link.source.index], count[link.target.index]);
25201 function force(alpha) {
25202 for (var k = 0, n = links.length; k < iterations; ++k) {
25203 for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
25204 link = links[i], source = link.source, target = link.target;
25205 x = target.x + target.vx - source.x - source.vx || jiggle();
25206 y = target.y + target.vy - source.y - source.vy || jiggle();
25207 l = Math.sqrt(x * x + y * y);
25208 l = (l - distances[i]) / l * alpha * strengths[i];
25210 target.vx -= x * (b = bias[i]);
25211 target.vy -= y * b;
25212 source.vx += x * (b = 1 - b);
25213 source.vy += y * b;
25218 function initialize() {
25219 if (!nodes) return;
25224 nodeById = map$1(nodes, id),
25227 for (i = 0, count = new Array(n); i < m; ++i) {
25228 link = links[i], link.index = i;
25229 if (typeof link.source !== "object") link.source = find(nodeById, link.source);
25230 if (typeof link.target !== "object") link.target = find(nodeById, link.target);
25231 count[link.source.index] = (count[link.source.index] || 0) + 1;
25232 count[link.target.index] = (count[link.target.index] || 0) + 1;
25235 for (i = 0, bias = new Array(m); i < m; ++i) {
25236 link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
25239 strengths = new Array(m), initializeStrength();
25240 distances = new Array(m), initializeDistance();
25243 function initializeStrength() {
25244 if (!nodes) return;
25246 for (var i = 0, n = links.length; i < n; ++i) {
25247 strengths[i] = +strength(links[i], i, links);
25251 function initializeDistance() {
25252 if (!nodes) return;
25254 for (var i = 0, n = links.length; i < n; ++i) {
25255 distances[i] = +distance(links[i], i, links);
25259 force.initialize = function(_) {
25264 force.links = function(_) {
25265 return arguments.length ? (links = _, initialize(), force) : links;
25268 force.id = function(_) {
25269 return arguments.length ? (id = _, force) : id;
25272 force.iterations = function(_) {
25273 return arguments.length ? (iterations = +_, force) : iterations;
25276 force.strength = function(_) {
25277 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initializeStrength(), force) : strength;
25280 force.distance = function(_) {
25281 return arguments.length ? (distance = typeof _ === "function" ? _ : constant$6(+_), initializeDistance(), force) : distance;
25295 var initialRadius = 10;
25296 var initialAngle = Math.PI * (3 - Math.sqrt(5));
25298 var simulation = function(nodes) {
25302 alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
25304 velocityDecay = 0.6,
25306 stepper = timer(step),
25307 event = dispatch("tick", "end");
25309 if (nodes == null) nodes = [];
25313 event.call("tick", simulation);
25314 if (alpha < alphaMin) {
25316 event.call("end", simulation);
25321 var i, n = nodes.length, node;
25323 alpha += (alphaTarget - alpha) * alphaDecay;
25325 forces.each(function(force) {
25329 for (i = 0; i < n; ++i) {
25331 if (node.fx == null) node.x += node.vx *= velocityDecay;
25332 else node.x = node.fx, node.vx = 0;
25333 if (node.fy == null) node.y += node.vy *= velocityDecay;
25334 else node.y = node.fy, node.vy = 0;
25338 function initializeNodes() {
25339 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25340 node = nodes[i], node.index = i;
25341 if (isNaN(node.x) || isNaN(node.y)) {
25342 var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle;
25343 node.x = radius * Math.cos(angle);
25344 node.y = radius * Math.sin(angle);
25346 if (isNaN(node.vx) || isNaN(node.vy)) {
25347 node.vx = node.vy = 0;
25352 function initializeForce(force) {
25353 if (force.initialize) force.initialize(nodes);
25359 return simulation = {
25362 restart: function() {
25363 return stepper.restart(step), simulation;
25367 return stepper.stop(), simulation;
25370 nodes: function(_) {
25371 return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes;
25374 alpha: function(_) {
25375 return arguments.length ? (alpha = +_, simulation) : alpha;
25378 alphaMin: function(_) {
25379 return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
25382 alphaDecay: function(_) {
25383 return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
25386 alphaTarget: function(_) {
25387 return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
25390 velocityDecay: function(_) {
25391 return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
25394 force: function(name, _) {
25395 return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
25398 find: function(x, y, radius) {
25407 if (radius == null) radius = Infinity;
25408 else radius *= radius;
25410 for (i = 0; i < n; ++i) {
25414 d2 = dx * dx + dy * dy;
25415 if (d2 < radius) closest = node, radius = d2;
25421 on: function(name, _) {
25422 return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
25427 var manyBody = function() {
25431 strength = constant$6(-30),
25434 distanceMax2 = Infinity,
25437 function force(_) {
25438 var i, n = nodes.length, tree = quadtree(nodes, x$1, y$1).visitAfter(accumulate);
25439 for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
25442 function initialize() {
25443 if (!nodes) return;
25444 var i, n = nodes.length, node;
25445 strengths = new Array(n);
25446 for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
25449 function accumulate(quad) {
25450 var strength = 0, q, c, x$$1, y$$1, i;
25452 // For internal nodes, accumulate forces from child quadrants.
25454 for (x$$1 = y$$1 = i = 0; i < 4; ++i) {
25455 if ((q = quad[i]) && (c = q.value)) {
25456 strength += c, x$$1 += c * q.x, y$$1 += c * q.y;
25459 quad.x = x$$1 / strength;
25460 quad.y = y$$1 / strength;
25463 // For leaf nodes, accumulate forces from coincident quadrants.
25468 do strength += strengths[q.data.index];
25469 while (q = q.next);
25472 quad.value = strength;
25475 function apply(quad, x1, _, x2) {
25476 if (!quad.value) return true;
25478 var x$$1 = quad.x - node.x,
25479 y$$1 = quad.y - node.y,
25481 l = x$$1 * x$$1 + y$$1 * y$$1;
25483 // Apply the Barnes-Hut approximation if possible.
25484 // Limit forces for very close nodes; randomize direction if coincident.
25485 if (w * w / theta2 < l) {
25486 if (l < distanceMax2) {
25487 if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
25488 if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
25489 if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
25490 node.vx += x$$1 * quad.value * alpha / l;
25491 node.vy += y$$1 * quad.value * alpha / l;
25496 // Otherwise, process points directly.
25497 else if (quad.length || l >= distanceMax2) return;
25499 // Limit forces for very close nodes; randomize direction if coincident.
25500 if (quad.data !== node || quad.next) {
25501 if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
25502 if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
25503 if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
25506 do if (quad.data !== node) {
25507 w = strengths[quad.data.index] * alpha / l;
25508 node.vx += x$$1 * w;
25509 node.vy += y$$1 * w;
25510 } while (quad = quad.next);
25513 force.initialize = function(_) {
25518 force.strength = function(_) {
25519 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25522 force.distanceMin = function(_) {
25523 return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
25526 force.distanceMax = function(_) {
25527 return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
25530 force.theta = function(_) {
25531 return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
25537 var x$2 = function(x) {
25538 var strength = constant$6(0.1),
25543 if (typeof x !== "function") x = constant$6(x == null ? 0 : +x);
25545 function force(alpha) {
25546 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25547 node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
25551 function initialize() {
25552 if (!nodes) return;
25553 var i, n = nodes.length;
25554 strengths = new Array(n);
25556 for (i = 0; i < n; ++i) {
25557 strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
25561 force.initialize = function(_) {
25566 force.strength = function(_) {
25567 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25570 force.x = function(_) {
25571 return arguments.length ? (x = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : x;
25577 var y$2 = function(y) {
25578 var strength = constant$6(0.1),
25583 if (typeof y !== "function") y = constant$6(y == null ? 0 : +y);
25585 function force(alpha) {
25586 for (var i = 0, n = nodes.length, node; i < n; ++i) {
25587 node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
25591 function initialize() {
25592 if (!nodes) return;
25593 var i, n = nodes.length;
25594 strengths = new Array(n);
25596 for (i = 0; i < n; ++i) {
25597 strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
25601 force.initialize = function(_) {
25606 force.strength = function(_) {
25607 return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25610 force.y = function(_) {
25611 return arguments.length ? (y = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : y;
25617 // Computes the decimal coefficient and exponent of the specified number x with
25618 // significant digits p, where x is positive and p is in [1, 21] or undefined.
25619 // For example, formatDecimal(1.23) returns ["123", 0].
25620 var formatDecimal = function(x, p) {
25621 if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
25622 var i, coefficient = x.slice(0, i);
25624 // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
25625 // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
25627 coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
25632 var exponent$1 = function(x) {
25633 return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
25636 var formatGroup = function(grouping, thousands) {
25637 return function(value, width) {
25638 var i = value.length,
25644 while (i > 0 && g > 0) {
25645 if (length + g + 1 > width) g = Math.max(1, width - length);
25646 t.push(value.substring(i -= g, i + g));
25647 if ((length += g + 1) > width) break;
25648 g = grouping[j = (j + 1) % grouping.length];
25651 return t.reverse().join(thousands);
25655 var formatNumerals = function(numerals) {
25656 return function(value) {
25657 return value.replace(/[0-9]/g, function(i) {
25658 return numerals[+i];
25663 var formatDefault = function(x, p) {
25664 x = x.toPrecision(p);
25666 out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
25668 case ".": i0 = i1 = i; break;
25669 case "0": if (i0 === 0) i0 = i; i1 = i; break;
25670 case "e": break out;
25671 default: if (i0 > 0) i0 = 0; break;
25675 return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
25678 var prefixExponent;
25680 var formatPrefixAuto = function(x, p) {
25681 var d = formatDecimal(x, p);
25682 if (!d) return x + "";
25683 var coefficient = d[0],
25685 i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
25686 n = coefficient.length;
25687 return i === n ? coefficient
25688 : i > n ? coefficient + new Array(i - n + 1).join("0")
25689 : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
25690 : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
25693 var formatRounded = function(x, p) {
25694 var d = formatDecimal(x, p);
25695 if (!d) return x + "";
25696 var coefficient = d[0],
25698 return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
25699 : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
25700 : coefficient + new Array(exponent - coefficient.length + 2).join("0");
25703 var formatTypes = {
25705 "%": function(x, p) { return (x * 100).toFixed(p); },
25706 "b": function(x) { return Math.round(x).toString(2); },
25707 "c": function(x) { return x + ""; },
25708 "d": function(x) { return Math.round(x).toString(10); },
25709 "e": function(x, p) { return x.toExponential(p); },
25710 "f": function(x, p) { return x.toFixed(p); },
25711 "g": function(x, p) { return x.toPrecision(p); },
25712 "o": function(x) { return Math.round(x).toString(8); },
25713 "p": function(x, p) { return formatRounded(x * 100, p); },
25714 "r": formatRounded,
25715 "s": formatPrefixAuto,
25716 "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
25717 "x": function(x) { return Math.round(x).toString(16); }
25720 // [[fill]align][sign][symbol][0][width][,][.precision][type]
25721 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
25723 function formatSpecifier(specifier) {
25724 return new FormatSpecifier(specifier);
25727 formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
25729 function FormatSpecifier(specifier) {
25730 if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
25733 fill = match[1] || " ",
25734 align = match[2] || ">",
25735 sign = match[3] || "-",
25736 symbol = match[4] || "",
25738 width = match[6] && +match[6],
25739 comma = !!match[7],
25740 precision = match[8] && +match[8].slice(1),
25741 type = match[9] || "";
25743 // The "n" type is an alias for ",g".
25744 if (type === "n") comma = true, type = "g";
25746 // Map invalid types to the default format.
25747 else if (!formatTypes[type]) type = "";
25749 // If zero fill is specified, padding goes after sign and before digits.
25750 if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
25753 this.align = align;
25755 this.symbol = symbol;
25757 this.width = width;
25758 this.comma = comma;
25759 this.precision = precision;
25763 FormatSpecifier.prototype.toString = function() {
25768 + (this.zero ? "0" : "")
25769 + (this.width == null ? "" : Math.max(1, this.width | 0))
25770 + (this.comma ? "," : "")
25771 + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
25775 var identity$3 = function(x) {
25779 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
25781 var formatLocale = function(locale) {
25782 var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3,
25783 currency = locale.currency,
25784 decimal = locale.decimal,
25785 numerals = locale.numerals ? formatNumerals(locale.numerals) : identity$3,
25786 percent = locale.percent || "%";
25788 function newFormat(specifier) {
25789 specifier = formatSpecifier(specifier);
25791 var fill = specifier.fill,
25792 align = specifier.align,
25793 sign = specifier.sign,
25794 symbol = specifier.symbol,
25795 zero = specifier.zero,
25796 width = specifier.width,
25797 comma = specifier.comma,
25798 precision = specifier.precision,
25799 type = specifier.type;
25801 // Compute the prefix and suffix.
25802 // For SI-prefix, the suffix is lazily computed.
25803 var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
25804 suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : "";
25806 // What format function should we use?
25807 // Is this an integer type?
25808 // Can this type generate exponential notation?
25809 var formatType = formatTypes[type],
25810 maybeSuffix = !type || /[defgprs%]/.test(type);
25812 // Set the default precision if not specified,
25813 // or clamp the specified precision to the supported range.
25814 // For significant precision, it must be in [1, 21].
25815 // For fixed precision, it must be in [0, 20].
25816 precision = precision == null ? (type ? 6 : 12)
25817 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
25818 : Math.max(0, Math.min(20, precision));
25820 function format(value) {
25821 var valuePrefix = prefix,
25822 valueSuffix = suffix,
25825 if (type === "c") {
25826 valueSuffix = formatType(value) + valueSuffix;
25831 // Perform the initial formatting.
25832 var valueNegative = value < 0;
25833 value = formatType(Math.abs(value), precision);
25835 // If a negative value rounds to zero during formatting, treat as positive.
25836 if (valueNegative && +value === 0) valueNegative = false;
25838 // Compute the prefix and suffix.
25839 valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
25840 valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
25842 // Break the formatted value into the integer “value” part that can be
25843 // grouped, and fractional or exponential “suffix” part that is not.
25845 i = -1, n = value.length;
25847 if (c = value.charCodeAt(i), 48 > c || c > 57) {
25848 valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
25849 value = value.slice(0, i);
25856 // If the fill character is not "0", grouping is applied before padding.
25857 if (comma && !zero) value = group(value, Infinity);
25859 // Compute the padding.
25860 var length = valuePrefix.length + value.length + valueSuffix.length,
25861 padding = length < width ? new Array(width - length + 1).join(fill) : "";
25863 // If the fill character is "0", grouping is applied after padding.
25864 if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
25866 // Reconstruct the final output based on the desired alignment.
25868 case "<": value = valuePrefix + value + valueSuffix + padding; break;
25869 case "=": value = valuePrefix + padding + value + valueSuffix; break;
25870 case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
25871 default: value = padding + valuePrefix + value + valueSuffix; break;
25874 return numerals(value);
25877 format.toString = function() {
25878 return specifier + "";
25884 function formatPrefix(specifier, value) {
25885 var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
25886 e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
25887 k = Math.pow(10, -e),
25888 prefix = prefixes[8 + e / 3];
25889 return function(value) {
25890 return f(k * value) + prefix;
25896 formatPrefix: formatPrefix
25908 currency: ["$", ""]
25911 function defaultLocale(definition) {
25912 locale$1 = formatLocale(definition);
25913 format = locale$1.format;
25914 formatPrefix = locale$1.formatPrefix;
25918 var precisionFixed = function(step) {
25919 return Math.max(0, -exponent$1(Math.abs(step)));
25922 var precisionPrefix = function(step, value) {
25923 return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step)));
25926 var precisionRound = function(step, max) {
25927 step = Math.abs(step), max = Math.abs(max) - step;
25928 return Math.max(0, exponent$1(max) - exponent$1(step)) + 1;
25931 // Adds floating point numbers with twice the normal precision.
25932 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
25933 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
25935 // Code adapted from GeographicLib by Charles F. F. Karney,
25936 // http://geographiclib.sourceforge.net/
25938 var adder = function() {
25946 Adder.prototype = {
25947 constructor: Adder,
25948 reset: function() {
25949 this.s = // rounded value
25950 this.t = 0; // exact error
25953 add$1(temp, y, this.t);
25954 add$1(this, temp.s, this.s);
25955 if (this.s) this.t += temp.t;
25956 else this.s = temp.t;
25958 valueOf: function() {
25963 var temp = new Adder;
25965 function add$1(adder, a, b) {
25966 var x = adder.s = a + b,
25969 adder.t = (a - av) + (b - bv);
25972 var epsilon$2 = 1e-6;
25973 var epsilon2$1 = 1e-12;
25974 var pi$3 = Math.PI;
25975 var halfPi$2 = pi$3 / 2;
25976 var quarterPi = pi$3 / 4;
25977 var tau$3 = pi$3 * 2;
25979 var degrees$1 = 180 / pi$3;
25980 var radians = pi$3 / 180;
25982 var abs = Math.abs;
25983 var atan = Math.atan;
25984 var atan2 = Math.atan2;
25985 var cos$1 = Math.cos;
25986 var ceil = Math.ceil;
25987 var exp = Math.exp;
25989 var log = Math.log;
25990 var pow = Math.pow;
25991 var sin$1 = Math.sin;
25992 var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
25993 var sqrt = Math.sqrt;
25994 var tan = Math.tan;
25997 return x > 1 ? 0 : x < -1 ? pi$3 : Math.acos(x);
26001 return x > 1 ? halfPi$2 : x < -1 ? -halfPi$2 : Math.asin(x);
26004 function haversin(x) {
26005 return (x = sin$1(x / 2)) * x;
26008 function noop$1() {}
26010 function streamGeometry(geometry, stream) {
26011 if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
26012 streamGeometryType[geometry.type](geometry, stream);
26016 var streamObjectType = {
26017 Feature: function(object, stream) {
26018 streamGeometry(object.geometry, stream);
26020 FeatureCollection: function(object, stream) {
26021 var features = object.features, i = -1, n = features.length;
26022 while (++i < n) streamGeometry(features[i].geometry, stream);
26026 var streamGeometryType = {
26027 Sphere: function(object, stream) {
26030 Point: function(object, stream) {
26031 object = object.coordinates;
26032 stream.point(object[0], object[1], object[2]);
26034 MultiPoint: function(object, stream) {
26035 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26036 while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
26038 LineString: function(object, stream) {
26039 streamLine(object.coordinates, stream, 0);
26041 MultiLineString: function(object, stream) {
26042 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26043 while (++i < n) streamLine(coordinates[i], stream, 0);
26045 Polygon: function(object, stream) {
26046 streamPolygon(object.coordinates, stream);
26048 MultiPolygon: function(object, stream) {
26049 var coordinates = object.coordinates, i = -1, n = coordinates.length;
26050 while (++i < n) streamPolygon(coordinates[i], stream);
26052 GeometryCollection: function(object, stream) {
26053 var geometries = object.geometries, i = -1, n = geometries.length;
26054 while (++i < n) streamGeometry(geometries[i], stream);
26058 function streamLine(coordinates, stream, closed) {
26059 var i = -1, n = coordinates.length - closed, coordinate;
26060 stream.lineStart();
26061 while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
26065 function streamPolygon(coordinates, stream) {
26066 var i = -1, n = coordinates.length;
26067 stream.polygonStart();
26068 while (++i < n) streamLine(coordinates[i], stream, 1);
26069 stream.polygonEnd();
26072 var geoStream = function(object, stream) {
26073 if (object && streamObjectType.hasOwnProperty(object.type)) {
26074 streamObjectType[object.type](object, stream);
26076 streamGeometry(object, stream);
26080 var areaRingSum = adder();
26082 var areaSum = adder();
26093 polygonStart: function() {
26094 areaRingSum.reset();
26095 areaStream.lineStart = areaRingStart;
26096 areaStream.lineEnd = areaRingEnd;
26098 polygonEnd: function() {
26099 var areaRing = +areaRingSum;
26100 areaSum.add(areaRing < 0 ? tau$3 + areaRing : areaRing);
26101 this.lineStart = this.lineEnd = this.point = noop$1;
26103 sphere: function() {
26104 areaSum.add(tau$3);
26108 function areaRingStart() {
26109 areaStream.point = areaPointFirst;
26112 function areaRingEnd() {
26113 areaPoint(lambda00, phi00);
26116 function areaPointFirst(lambda, phi) {
26117 areaStream.point = areaPoint;
26118 lambda00 = lambda, phi00 = phi;
26119 lambda *= radians, phi *= radians;
26120 lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi);
26123 function areaPoint(lambda, phi) {
26124 lambda *= radians, phi *= radians;
26125 phi = phi / 2 + quarterPi; // half the angular distance from south pole
26127 // Spherical excess E for a spherical triangle with vertices: south pole,
26128 // previous point, current point. Uses a formula derived from Cagnoli’s
26129 // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
26130 var dLambda = lambda - lambda0,
26131 sdLambda = dLambda >= 0 ? 1 : -1,
26132 adLambda = sdLambda * dLambda,
26133 cosPhi = cos$1(phi),
26134 sinPhi = sin$1(phi),
26135 k = sinPhi0 * sinPhi,
26136 u = cosPhi0 * cosPhi + k * cos$1(adLambda),
26137 v = k * sdLambda * sin$1(adLambda);
26138 areaRingSum.add(atan2(v, u));
26140 // Advance the previous points.
26141 lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
26144 var area = function(object) {
26146 geoStream(object, areaStream);
26147 return areaSum * 2;
26150 function spherical(cartesian) {
26151 return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
26154 function cartesian(spherical) {
26155 var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi);
26156 return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)];
26159 function cartesianDot(a, b) {
26160 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
26163 function cartesianCross(a, b) {
26164 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]];
26168 function cartesianAddInPlace(a, b) {
26169 a[0] += b[0], a[1] += b[1], a[2] += b[2];
26172 function cartesianScale(vector, k) {
26173 return [vector[0] * k, vector[1] * k, vector[2] * k];
26177 function cartesianNormalizeInPlace(d) {
26178 var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
26179 d[0] /= l, d[1] /= l, d[2] /= l;
26190 var deltaSum = adder();
26194 var boundsStream = {
26195 point: boundsPoint,
26196 lineStart: boundsLineStart,
26197 lineEnd: boundsLineEnd,
26198 polygonStart: function() {
26199 boundsStream.point = boundsRingPoint;
26200 boundsStream.lineStart = boundsRingStart;
26201 boundsStream.lineEnd = boundsRingEnd;
26203 areaStream.polygonStart();
26205 polygonEnd: function() {
26206 areaStream.polygonEnd();
26207 boundsStream.point = boundsPoint;
26208 boundsStream.lineStart = boundsLineStart;
26209 boundsStream.lineEnd = boundsLineEnd;
26210 if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
26211 else if (deltaSum > epsilon$2) phi1 = 90;
26212 else if (deltaSum < -epsilon$2) phi0 = -90;
26213 range[0] = lambda0$1, range[1] = lambda1;
26217 function boundsPoint(lambda, phi) {
26218 ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
26219 if (phi < phi0) phi0 = phi;
26220 if (phi > phi1) phi1 = phi;
26223 function linePoint(lambda, phi) {
26224 var p = cartesian([lambda * radians, phi * radians]);
26226 var normal = cartesianCross(p0, p),
26227 equatorial = [normal[1], -normal[0], 0],
26228 inflection = cartesianCross(equatorial, normal);
26229 cartesianNormalizeInPlace(inflection);
26230 inflection = spherical(inflection);
26231 var delta = lambda - lambda2,
26232 sign$$1 = delta > 0 ? 1 : -1,
26233 lambdai = inflection[0] * degrees$1 * sign$$1,
26235 antimeridian = abs(delta) > 180;
26236 if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
26237 phii = inflection[1] * degrees$1;
26238 if (phii > phi1) phi1 = phii;
26239 } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
26240 phii = -inflection[1] * degrees$1;
26241 if (phii < phi0) phi0 = phii;
26243 if (phi < phi0) phi0 = phi;
26244 if (phi > phi1) phi1 = phi;
26246 if (antimeridian) {
26247 if (lambda < lambda2) {
26248 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
26250 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
26253 if (lambda1 >= lambda0$1) {
26254 if (lambda < lambda0$1) lambda0$1 = lambda;
26255 if (lambda > lambda1) lambda1 = lambda;
26257 if (lambda > lambda2) {
26258 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
26260 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
26265 ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
26267 if (phi < phi0) phi0 = phi;
26268 if (phi > phi1) phi1 = phi;
26269 p0 = p, lambda2 = lambda;
26272 function boundsLineStart() {
26273 boundsStream.point = linePoint;
26276 function boundsLineEnd() {
26277 range[0] = lambda0$1, range[1] = lambda1;
26278 boundsStream.point = boundsPoint;
26282 function boundsRingPoint(lambda, phi) {
26284 var delta = lambda - lambda2;
26285 deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
26287 lambda00$1 = lambda, phi00$1 = phi;
26289 areaStream.point(lambda, phi);
26290 linePoint(lambda, phi);
26293 function boundsRingStart() {
26294 areaStream.lineStart();
26297 function boundsRingEnd() {
26298 boundsRingPoint(lambda00$1, phi00$1);
26299 areaStream.lineEnd();
26300 if (abs(deltaSum) > epsilon$2) lambda0$1 = -(lambda1 = 180);
26301 range[0] = lambda0$1, range[1] = lambda1;
26305 // Finds the left-right distance between two longitudes.
26306 // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
26307 // the distance between ±180° to be 360°.
26308 function angle(lambda0, lambda1) {
26309 return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
26312 function rangeCompare(a, b) {
26313 return a[0] - b[0];
26316 function rangeContains(range, x) {
26317 return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
26320 var bounds = function(feature) {
26321 var i, n, a, b, merged, deltaMax, delta;
26323 phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
26325 geoStream(feature, boundsStream);
26327 // First, sort ranges by their minimum longitudes.
26328 if (n = ranges.length) {
26329 ranges.sort(rangeCompare);
26331 // Then, merge any ranges that overlap.
26332 for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
26334 if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
26335 if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
26336 if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
26338 merged.push(a = b);
26342 // Finally, find the largest gap between the merged ranges.
26343 // The final bounding box will be the inverse of this gap.
26344 for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
26346 if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
26350 ranges = range = null;
26352 return lambda0$1 === Infinity || phi0 === Infinity
26353 ? [[NaN, NaN], [NaN, NaN]]
26354 : [[lambda0$1, phi0], [lambda1, phi1]];
26372 var z0; // previous point
26374 var centroidStream = {
26376 point: centroidPoint,
26377 lineStart: centroidLineStart,
26378 lineEnd: centroidLineEnd,
26379 polygonStart: function() {
26380 centroidStream.lineStart = centroidRingStart;
26381 centroidStream.lineEnd = centroidRingEnd;
26383 polygonEnd: function() {
26384 centroidStream.lineStart = centroidLineStart;
26385 centroidStream.lineEnd = centroidLineEnd;
26389 // Arithmetic mean of Cartesian vectors.
26390 function centroidPoint(lambda, phi) {
26391 lambda *= radians, phi *= radians;
26392 var cosPhi = cos$1(phi);
26393 centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi));
26396 function centroidPointCartesian(x, y, z) {
26398 X0 += (x - X0) / W0;
26399 Y0 += (y - Y0) / W0;
26400 Z0 += (z - Z0) / W0;
26403 function centroidLineStart() {
26404 centroidStream.point = centroidLinePointFirst;
26407 function centroidLinePointFirst(lambda, phi) {
26408 lambda *= radians, phi *= radians;
26409 var cosPhi = cos$1(phi);
26410 x0 = cosPhi * cos$1(lambda);
26411 y0 = cosPhi * sin$1(lambda);
26413 centroidStream.point = centroidLinePoint;
26414 centroidPointCartesian(x0, y0, z0);
26417 function centroidLinePoint(lambda, phi) {
26418 lambda *= radians, phi *= radians;
26419 var cosPhi = cos$1(phi),
26420 x = cosPhi * cos$1(lambda),
26421 y = cosPhi * sin$1(lambda),
26423 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);
26425 X1 += w * (x0 + (x0 = x));
26426 Y1 += w * (y0 + (y0 = y));
26427 Z1 += w * (z0 + (z0 = z));
26428 centroidPointCartesian(x0, y0, z0);
26431 function centroidLineEnd() {
26432 centroidStream.point = centroidPoint;
26435 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
26436 // J. Applied Mechanics 42, 239 (1975).
26437 function centroidRingStart() {
26438 centroidStream.point = centroidRingPointFirst;
26441 function centroidRingEnd() {
26442 centroidRingPoint(lambda00$2, phi00$2);
26443 centroidStream.point = centroidPoint;
26446 function centroidRingPointFirst(lambda, phi) {
26447 lambda00$2 = lambda, phi00$2 = phi;
26448 lambda *= radians, phi *= radians;
26449 centroidStream.point = centroidRingPoint;
26450 var cosPhi = cos$1(phi);
26451 x0 = cosPhi * cos$1(lambda);
26452 y0 = cosPhi * sin$1(lambda);
26454 centroidPointCartesian(x0, y0, z0);
26457 function centroidRingPoint(lambda, phi) {
26458 lambda *= radians, phi *= radians;
26459 var cosPhi = cos$1(phi),
26460 x = cosPhi * cos$1(lambda),
26461 y = cosPhi * sin$1(lambda),
26463 cx = y0 * z - z0 * y,
26464 cy = z0 * x - x0 * z,
26465 cz = x0 * y - y0 * x,
26466 m = sqrt(cx * cx + cy * cy + cz * cz),
26467 w = asin(m), // line weight = angle
26468 v = m && -w / m; // area weight multiplier
26473 X1 += w * (x0 + (x0 = x));
26474 Y1 += w * (y0 + (y0 = y));
26475 Z1 += w * (z0 + (z0 = z));
26476 centroidPointCartesian(x0, y0, z0);
26479 var d3GeoCentroid = function(object) {
26484 geoStream(object, centroidStream);
26489 m = x * x + y * y + z * z;
26491 // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
26492 if (m < epsilon2$1) {
26493 x = X1, y = Y1, z = Z1;
26494 // If the feature has zero length, fall back to arithmetic mean of point vectors.
26495 if (W1 < epsilon$2) x = X0, y = Y0, z = Z0;
26496 m = x * x + y * y + z * z;
26497 // If the feature still has an undefined ccentroid, then return.
26498 if (m < epsilon2$1) return [NaN, NaN];
26501 return [atan2(y, x) * degrees$1, asin(z / sqrt(m)) * degrees$1];
26504 var constant$7 = function(x) {
26505 return function() {
26510 var compose = function(a, b) {
26512 function compose(x, y) {
26513 return x = a(x, y), b(x[0], x[1]);
26516 if (a.invert && b.invert) compose.invert = function(x, y) {
26517 return x = b.invert(x, y), x && a.invert(x[0], x[1]);
26523 function rotationIdentity(lambda, phi) {
26524 return [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi];
26527 rotationIdentity.invert = rotationIdentity;
26529 function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
26530 return (deltaLambda %= tau$3) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
26531 : rotationLambda(deltaLambda))
26532 : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
26533 : rotationIdentity);
26536 function forwardRotationLambda(deltaLambda) {
26537 return function(lambda, phi) {
26538 return lambda += deltaLambda, [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi];
26542 function rotationLambda(deltaLambda) {
26543 var rotation = forwardRotationLambda(deltaLambda);
26544 rotation.invert = forwardRotationLambda(-deltaLambda);
26548 function rotationPhiGamma(deltaPhi, deltaGamma) {
26549 var cosDeltaPhi = cos$1(deltaPhi),
26550 sinDeltaPhi = sin$1(deltaPhi),
26551 cosDeltaGamma = cos$1(deltaGamma),
26552 sinDeltaGamma = sin$1(deltaGamma);
26554 function rotation(lambda, phi) {
26555 var cosPhi = cos$1(phi),
26556 x = cos$1(lambda) * cosPhi,
26557 y = sin$1(lambda) * cosPhi,
26559 k = z * cosDeltaPhi + x * sinDeltaPhi;
26561 atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
26562 asin(k * cosDeltaGamma + y * sinDeltaGamma)
26566 rotation.invert = function(lambda, phi) {
26567 var cosPhi = cos$1(phi),
26568 x = cos$1(lambda) * cosPhi,
26569 y = sin$1(lambda) * cosPhi,
26571 k = z * cosDeltaGamma - y * sinDeltaGamma;
26573 atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
26574 asin(k * cosDeltaPhi - x * sinDeltaPhi)
26581 var rotation = function(rotate) {
26582 rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
26584 function forward(coordinates) {
26585 coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
26586 return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
26589 forward.invert = function(coordinates) {
26590 coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
26591 return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
26597 // Generates a circle centered at [0°, 0°], with a given radius and precision.
26598 function circleStream(stream, radius, delta, direction, t0, t1) {
26599 if (!delta) return;
26600 var cosRadius = cos$1(radius),
26601 sinRadius = sin$1(radius),
26602 step = direction * delta;
26604 t0 = radius + direction * tau$3;
26605 t1 = radius - step / 2;
26607 t0 = circleRadius(cosRadius, t0);
26608 t1 = circleRadius(cosRadius, t1);
26609 if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$3;
26611 for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
26612 point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]);
26613 stream.point(point[0], point[1]);
26617 // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
26618 function circleRadius(cosRadius, point) {
26619 point = cartesian(point), point[0] -= cosRadius;
26620 cartesianNormalizeInPlace(point);
26621 var radius = acos(-point[1]);
26622 return ((-point[2] < 0 ? -radius : radius) + tau$3 - epsilon$2) % tau$3;
26625 var circle = function() {
26626 var center = constant$7([0, 0]),
26627 radius = constant$7(90),
26628 precision = constant$7(6),
26631 stream = {point: point};
26633 function point(x, y) {
26634 ring.push(x = rotate(x, y));
26635 x[0] *= degrees$1, x[1] *= degrees$1;
26638 function circle() {
26639 var c = center.apply(this, arguments),
26640 r = radius.apply(this, arguments) * radians,
26641 p = precision.apply(this, arguments) * radians;
26643 rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
26644 circleStream(stream, r, p, 1);
26645 c = {type: "Polygon", coordinates: [ring]};
26646 ring = rotate = null;
26650 circle.center = function(_) {
26651 return arguments.length ? (center = typeof _ === "function" ? _ : constant$7([+_[0], +_[1]]), circle) : center;
26654 circle.radius = function(_) {
26655 return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), circle) : radius;
26658 circle.precision = function(_) {
26659 return arguments.length ? (precision = typeof _ === "function" ? _ : constant$7(+_), circle) : precision;
26665 var clipBuffer = function() {
26669 point: function(x, y) {
26672 lineStart: function() {
26673 lines.push(line = []);
26676 rejoin: function() {
26677 if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
26679 result: function() {
26680 var result = lines;
26688 var clipLine = function(a, b, x0, y0, x1, y1) {
26700 if (!dx && r > 0) return;
26703 if (r < t0) return;
26704 if (r < t1) t1 = r;
26705 } else if (dx > 0) {
26706 if (r > t1) return;
26707 if (r > t0) t0 = r;
26711 if (!dx && r < 0) return;
26714 if (r > t1) return;
26715 if (r > t0) t0 = r;
26716 } else if (dx > 0) {
26717 if (r < t0) return;
26718 if (r < t1) t1 = r;
26722 if (!dy && r > 0) return;
26725 if (r < t0) return;
26726 if (r < t1) t1 = r;
26727 } else if (dy > 0) {
26728 if (r > t1) return;
26729 if (r > t0) t0 = r;
26733 if (!dy && r < 0) return;
26736 if (r > t1) return;
26737 if (r > t0) t0 = r;
26738 } else if (dy > 0) {
26739 if (r < t0) return;
26740 if (r < t1) t1 = r;
26743 if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
26744 if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
26748 var pointEqual = function(a, b) {
26749 return abs(a[0] - b[0]) < epsilon$2 && abs(a[1] - b[1]) < epsilon$2;
26752 function Intersection(point, points, other, entry) {
26755 this.o = other; // another intersection
26756 this.e = entry; // is an entry?
26757 this.v = false; // visited
26758 this.n = this.p = null; // next & previous
26761 // A generalized polygon clipping algorithm: given a polygon that has been cut
26762 // into its visible line segments, and rejoins the segments by interpolating
26763 // along the clip edge.
26764 var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) {
26770 segments.forEach(function(segment) {
26771 if ((n = segment.length - 1) <= 0) return;
26772 var n, p0 = segment[0], p1 = segment[n], x;
26774 // If the first and last points of a segment are coincident, then treat as a
26775 // closed ring. TODO if all rings are closed, then the winding order of the
26776 // exterior ring should be checked.
26777 if (pointEqual(p0, p1)) {
26778 stream.lineStart();
26779 for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
26784 subject.push(x = new Intersection(p0, segment, null, true));
26785 clip.push(x.o = new Intersection(p0, null, x, false));
26786 subject.push(x = new Intersection(p1, segment, null, false));
26787 clip.push(x.o = new Intersection(p1, null, x, true));
26790 if (!subject.length) return;
26792 clip.sort(compareIntersection);
26796 for (i = 0, n = clip.length; i < n; ++i) {
26797 clip[i].e = startInside = !startInside;
26800 var start = subject[0],
26805 // Find first unvisited intersection.
26806 var current = start,
26808 while (current.v) if ((current = current.n) === start) return;
26809 points = current.z;
26810 stream.lineStart();
26812 current.v = current.o.v = true;
26815 for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
26817 interpolate(current.x, current.n.x, 1, stream);
26819 current = current.n;
26822 points = current.p.z;
26823 for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
26825 interpolate(current.x, current.p.x, -1, stream);
26827 current = current.p;
26829 current = current.o;
26830 points = current.z;
26831 isSubject = !isSubject;
26832 } while (!current.v);
26837 function link$1(array) {
26838 if (!(n = array.length)) return;
26844 a.n = b = array[i];
26848 a.n = b = array[0];
26853 var clipMin = -clipMax;
26855 // TODO Use d3-polygon’s polygonContains here for the ring check?
26856 // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
26858 function clipExtent(x0, y0, x1, y1) {
26860 function visible(x, y) {
26861 return x0 <= x && x <= x1 && y0 <= y && y <= y1;
26864 function interpolate(from, to, direction, stream) {
26867 || (a = corner(from, direction)) !== (a1 = corner(to, direction))
26868 || comparePoint(from, to) < 0 ^ direction > 0) {
26869 do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
26870 while ((a = (a + direction + 4) % 4) !== a1);
26872 stream.point(to[0], to[1]);
26876 function corner(p, direction) {
26877 return abs(p[0] - x0) < epsilon$2 ? direction > 0 ? 0 : 3
26878 : abs(p[0] - x1) < epsilon$2 ? direction > 0 ? 2 : 1
26879 : abs(p[1] - y0) < epsilon$2 ? direction > 0 ? 1 : 0
26880 : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
26883 function compareIntersection(a, b) {
26884 return comparePoint(a.x, b.x);
26887 function comparePoint(a, b) {
26888 var ca = corner(a, 1),
26890 return ca !== cb ? ca - cb
26891 : ca === 0 ? b[1] - a[1]
26892 : ca === 1 ? a[0] - b[0]
26893 : ca === 2 ? a[1] - b[1]
26897 return function(stream) {
26898 var activeStream = stream,
26899 bufferStream = clipBuffer(),
26903 x__, y__, v__, // first point
26904 x_, y_, v_, // previous point
26910 lineStart: lineStart,
26912 polygonStart: polygonStart,
26913 polygonEnd: polygonEnd
26916 function point(x, y) {
26917 if (visible(x, y)) activeStream.point(x, y);
26920 function polygonInside() {
26923 for (var i = 0, n = polygon.length; i < n; ++i) {
26924 for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
26925 a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
26926 if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
26927 else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
26934 // Buffer geometry within a polygon and then clip it en masse.
26935 function polygonStart() {
26936 activeStream = bufferStream, segments = [], polygon = [], clean = true;
26939 function polygonEnd() {
26940 var startInside = polygonInside(),
26941 cleanInside = clean && startInside,
26942 visible = (segments = merge(segments)).length;
26943 if (cleanInside || visible) {
26944 stream.polygonStart();
26946 stream.lineStart();
26947 interpolate(null, null, 1, stream);
26951 clipPolygon(segments, compareIntersection, startInside, interpolate, stream);
26953 stream.polygonEnd();
26955 activeStream = stream, segments = polygon = ring = null;
26958 function lineStart() {
26959 clipStream.point = linePoint;
26960 if (polygon) polygon.push(ring = []);
26966 // TODO rather than special-case polygons, simply handle them separately.
26967 // Ideally, coincident intersection points should be jittered to avoid
26968 // clipping issues.
26969 function lineEnd() {
26971 linePoint(x__, y__);
26972 if (v__ && v_) bufferStream.rejoin();
26973 segments.push(bufferStream.result());
26975 clipStream.point = point;
26976 if (v_) activeStream.lineEnd();
26979 function linePoint(x, y) {
26980 var v = visible(x, y);
26981 if (polygon) ring.push([x, y]);
26983 x__ = x, y__ = y, v__ = v;
26986 activeStream.lineStart();
26987 activeStream.point(x, y);
26990 if (v && v_) activeStream.point(x, y);
26992 var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
26993 b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
26994 if (clipLine(a, b, x0, y0, x1, y1)) {
26996 activeStream.lineStart();
26997 activeStream.point(a[0], a[1]);
26999 activeStream.point(b[0], b[1]);
27000 if (!v) activeStream.lineEnd();
27003 activeStream.lineStart();
27004 activeStream.point(x, y);
27009 x_ = x, y_ = y, v_ = v;
27016 var extent$1 = function() {
27026 stream: function(stream) {
27027 return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream);
27029 extent: function(_) {
27030 return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]];
27035 var sum$1 = adder();
27037 var polygonContains = function(polygon, point) {
27038 var lambda = point[0],
27040 normal = [sin$1(lambda), -cos$1(lambda), 0],
27046 for (var i = 0, n = polygon.length; i < n; ++i) {
27047 if (!(m = (ring = polygon[i]).length)) continue;
27050 point0 = ring[m - 1],
27051 lambda0 = point0[0],
27052 phi0 = point0[1] / 2 + quarterPi,
27053 sinPhi0 = sin$1(phi0),
27054 cosPhi0 = cos$1(phi0);
27056 for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
27057 var point1 = ring[j],
27058 lambda1 = point1[0],
27059 phi1 = point1[1] / 2 + quarterPi,
27060 sinPhi1 = sin$1(phi1),
27061 cosPhi1 = cos$1(phi1),
27062 delta = lambda1 - lambda0,
27063 sign$$1 = delta >= 0 ? 1 : -1,
27064 absDelta = sign$$1 * delta,
27065 antimeridian = absDelta > pi$3,
27066 k = sinPhi0 * sinPhi1;
27068 sum$1.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta)));
27069 angle += antimeridian ? delta + sign$$1 * tau$3 : delta;
27071 // Are the longitudes either side of the point’s meridian (lambda),
27072 // and are the latitudes smaller than the parallel (phi)?
27073 if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
27074 var arc = cartesianCross(cartesian(point0), cartesian(point1));
27075 cartesianNormalizeInPlace(arc);
27076 var intersection = cartesianCross(normal, arc);
27077 cartesianNormalizeInPlace(intersection);
27078 var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
27079 if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
27080 winding += antimeridian ^ delta >= 0 ? 1 : -1;
27086 // First, determine whether the South pole is inside or outside:
27088 // It is inside if:
27089 // * the polygon winds around it in a clockwise direction.
27090 // * the polygon does not (cumulatively) wind around it, but has a negative
27091 // (counter-clockwise) area.
27093 // Second, count the (signed) number of times a segment crosses a lambda
27094 // from the point to the South pole. If it is zero, then the point is the
27095 // same side as the South pole.
27097 return (angle < -epsilon$2 || angle < epsilon$2 && sum$1 < -epsilon$2) ^ (winding & 1);
27100 var lengthSum = adder();
27105 var lengthStream = {
27108 lineStart: lengthLineStart,
27110 polygonStart: noop$1,
27114 function lengthLineStart() {
27115 lengthStream.point = lengthPointFirst;
27116 lengthStream.lineEnd = lengthLineEnd;
27119 function lengthLineEnd() {
27120 lengthStream.point = lengthStream.lineEnd = noop$1;
27123 function lengthPointFirst(lambda, phi) {
27124 lambda *= radians, phi *= radians;
27125 lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi);
27126 lengthStream.point = lengthPoint;
27129 function lengthPoint(lambda, phi) {
27130 lambda *= radians, phi *= radians;
27131 var sinPhi = sin$1(phi),
27132 cosPhi = cos$1(phi),
27133 delta = abs(lambda - lambda0$2),
27134 cosDelta = cos$1(delta),
27135 sinDelta = sin$1(delta),
27136 x = cosPhi * sinDelta,
27137 y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta,
27138 z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta;
27139 lengthSum.add(atan2(sqrt(x * x + y * y), z));
27140 lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi;
27143 var d3GeoLength = function(object) {
27145 geoStream(object, lengthStream);
27149 var coordinates = [null, null];
27150 var object$1 = {type: "LineString", coordinates: coordinates};
27152 var distance = function(a, b) {
27153 coordinates[0] = a;
27154 coordinates[1] = b;
27155 return d3GeoLength(object$1);
27158 var containsObjectType = {
27159 Feature: function(object, point) {
27160 return containsGeometry(object.geometry, point);
27162 FeatureCollection: function(object, point) {
27163 var features = object.features, i = -1, n = features.length;
27164 while (++i < n) if (containsGeometry(features[i].geometry, point)) return true;
27169 var containsGeometryType = {
27170 Sphere: function() {
27173 Point: function(object, point) {
27174 return containsPoint(object.coordinates, point);
27176 MultiPoint: function(object, point) {
27177 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27178 while (++i < n) if (containsPoint(coordinates[i], point)) return true;
27181 LineString: function(object, point) {
27182 return containsLine(object.coordinates, point);
27184 MultiLineString: function(object, point) {
27185 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27186 while (++i < n) if (containsLine(coordinates[i], point)) return true;
27189 Polygon: function(object, point) {
27190 return containsPolygon(object.coordinates, point);
27192 MultiPolygon: function(object, point) {
27193 var coordinates = object.coordinates, i = -1, n = coordinates.length;
27194 while (++i < n) if (containsPolygon(coordinates[i], point)) return true;
27197 GeometryCollection: function(object, point) {
27198 var geometries = object.geometries, i = -1, n = geometries.length;
27199 while (++i < n) if (containsGeometry(geometries[i], point)) return true;
27204 function containsGeometry(geometry, point) {
27205 return geometry && containsGeometryType.hasOwnProperty(geometry.type)
27206 ? containsGeometryType[geometry.type](geometry, point)
27210 function containsPoint(coordinates, point) {
27211 return distance(coordinates, point) === 0;
27214 function containsLine(coordinates, point) {
27215 var ab = distance(coordinates[0], coordinates[1]),
27216 ao = distance(coordinates[0], point),
27217 ob = distance(point, coordinates[1]);
27218 return ao + ob <= ab + epsilon$2;
27221 function containsPolygon(coordinates, point) {
27222 return !!polygonContains(coordinates.map(ringRadians), pointRadians(point));
27225 function ringRadians(ring) {
27226 return ring = ring.map(pointRadians), ring.pop(), ring;
27229 function pointRadians(point) {
27230 return [point[0] * radians, point[1] * radians];
27233 var contains = function(object, point) {
27234 return (object && containsObjectType.hasOwnProperty(object.type)
27235 ? containsObjectType[object.type]
27236 : containsGeometry)(object, point);
27239 function graticuleX(y0, y1, dy) {
27240 var y = sequence(y0, y1 - epsilon$2, dy).concat(y1);
27241 return function(x) { return y.map(function(y) { return [x, y]; }); };
27244 function graticuleY(x0, x1, dx) {
27245 var x = sequence(x0, x1 - epsilon$2, dx).concat(x1);
27246 return function(y) { return x.map(function(x) { return [x, y]; }); };
27249 function graticule() {
27250 var x1, x0, X1, X0,
27252 dx = 10, dy = dx, DX = 90, DY = 360,
27256 function graticule() {
27257 return {type: "MultiLineString", coordinates: lines()};
27261 return sequence(ceil(X0 / DX) * DX, X1, DX).map(X)
27262 .concat(sequence(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
27263 .concat(sequence(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$2; }).map(x))
27264 .concat(sequence(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$2; }).map(y));
27267 graticule.lines = function() {
27268 return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
27271 graticule.outline = function() {
27277 X(X1).reverse().slice(1),
27278 Y(Y0).reverse().slice(1))
27283 graticule.extent = function(_) {
27284 if (!arguments.length) return graticule.extentMinor();
27285 return graticule.extentMajor(_).extentMinor(_);
27288 graticule.extentMajor = function(_) {
27289 if (!arguments.length) return [[X0, Y0], [X1, Y1]];
27290 X0 = +_[0][0], X1 = +_[1][0];
27291 Y0 = +_[0][1], Y1 = +_[1][1];
27292 if (X0 > X1) _ = X0, X0 = X1, X1 = _;
27293 if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
27294 return graticule.precision(precision);
27297 graticule.extentMinor = function(_) {
27298 if (!arguments.length) return [[x0, y0], [x1, y1]];
27299 x0 = +_[0][0], x1 = +_[1][0];
27300 y0 = +_[0][1], y1 = +_[1][1];
27301 if (x0 > x1) _ = x0, x0 = x1, x1 = _;
27302 if (y0 > y1) _ = y0, y0 = y1, y1 = _;
27303 return graticule.precision(precision);
27306 graticule.step = function(_) {
27307 if (!arguments.length) return graticule.stepMinor();
27308 return graticule.stepMajor(_).stepMinor(_);
27311 graticule.stepMajor = function(_) {
27312 if (!arguments.length) return [DX, DY];
27313 DX = +_[0], DY = +_[1];
27317 graticule.stepMinor = function(_) {
27318 if (!arguments.length) return [dx, dy];
27319 dx = +_[0], dy = +_[1];
27323 graticule.precision = function(_) {
27324 if (!arguments.length) return precision;
27326 x = graticuleX(y0, y1, 90);
27327 y = graticuleY(x0, x1, precision);
27328 X = graticuleX(Y0, Y1, 90);
27329 Y = graticuleY(X0, X1, precision);
27334 .extentMajor([[-180, -90 + epsilon$2], [180, 90 - epsilon$2]])
27335 .extentMinor([[-180, -80 - epsilon$2], [180, 80 + epsilon$2]]);
27338 function graticule10() {
27339 return graticule()();
27342 var interpolate$1 = function(a, b) {
27343 var x0 = a[0] * radians,
27344 y0 = a[1] * radians,
27345 x1 = b[0] * radians,
27346 y1 = b[1] * radians,
27351 kx0 = cy0 * cos$1(x0),
27352 ky0 = cy0 * sin$1(x0),
27353 kx1 = cy1 * cos$1(x1),
27354 ky1 = cy1 * sin$1(x1),
27355 d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))),
27358 var interpolate = d ? function(t) {
27359 var B = sin$1(t *= d) / k,
27360 A = sin$1(d - t) / k,
27361 x = A * kx0 + B * kx1,
27362 y = A * ky0 + B * ky1,
27363 z = A * sy0 + B * sy1;
27365 atan2(y, x) * degrees$1,
27366 atan2(z, sqrt(x * x + y * y)) * degrees$1
27369 return [x0 * degrees$1, y0 * degrees$1];
27372 interpolate.distance = d;
27374 return interpolate;
27377 var identity$4 = function(x) {
27381 var areaSum$1 = adder();
27382 var areaRingSum$1 = adder();
27388 var areaStream$1 = {
27392 polygonStart: function() {
27393 areaStream$1.lineStart = areaRingStart$1;
27394 areaStream$1.lineEnd = areaRingEnd$1;
27396 polygonEnd: function() {
27397 areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$1;
27398 areaSum$1.add(abs(areaRingSum$1));
27399 areaRingSum$1.reset();
27401 result: function() {
27402 var area = areaSum$1 / 2;
27408 function areaRingStart$1() {
27409 areaStream$1.point = areaPointFirst$1;
27412 function areaPointFirst$1(x, y) {
27413 areaStream$1.point = areaPoint$1;
27414 x00 = x0$1 = x, y00 = y0$1 = y;
27417 function areaPoint$1(x, y) {
27418 areaRingSum$1.add(y0$1 * x - x0$1 * y);
27419 x0$1 = x, y0$1 = y;
27422 function areaRingEnd$1() {
27423 areaPoint$1(x00, y00);
27426 var x0$2 = Infinity;
27431 var boundsStream$1 = {
27432 point: boundsPoint$1,
27435 polygonStart: noop$1,
27436 polygonEnd: noop$1,
27437 result: function() {
27438 var bounds = [[x0$2, y0$2], [x1, y1]];
27439 x1 = y1 = -(y0$2 = x0$2 = Infinity);
27444 function boundsPoint$1(x, y) {
27445 if (x < x0$2) x0$2 = x;
27446 if (x > x1) x1 = x;
27447 if (y < y0$2) y0$2 = y;
27448 if (y > y1) y1 = y;
27451 // TODO Enforce positive area for exterior, negative area for interior?
27467 var centroidStream$1 = {
27468 point: centroidPoint$1,
27469 lineStart: centroidLineStart$1,
27470 lineEnd: centroidLineEnd$1,
27471 polygonStart: function() {
27472 centroidStream$1.lineStart = centroidRingStart$1;
27473 centroidStream$1.lineEnd = centroidRingEnd$1;
27475 polygonEnd: function() {
27476 centroidStream$1.point = centroidPoint$1;
27477 centroidStream$1.lineStart = centroidLineStart$1;
27478 centroidStream$1.lineEnd = centroidLineEnd$1;
27480 result: function() {
27481 var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1]
27482 : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1]
27483 : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1]
27485 X0$1 = Y0$1 = Z0$1 =
27486 X1$1 = Y1$1 = Z1$1 =
27487 X2$1 = Y2$1 = Z2$1 = 0;
27492 function centroidPoint$1(x, y) {
27498 function centroidLineStart$1() {
27499 centroidStream$1.point = centroidPointFirstLine;
27502 function centroidPointFirstLine(x, y) {
27503 centroidStream$1.point = centroidPointLine;
27504 centroidPoint$1(x0$3 = x, y0$3 = y);
27507 function centroidPointLine(x, y) {
27508 var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy);
27509 X1$1 += z * (x0$3 + x) / 2;
27510 Y1$1 += z * (y0$3 + y) / 2;
27512 centroidPoint$1(x0$3 = x, y0$3 = y);
27515 function centroidLineEnd$1() {
27516 centroidStream$1.point = centroidPoint$1;
27519 function centroidRingStart$1() {
27520 centroidStream$1.point = centroidPointFirstRing;
27523 function centroidRingEnd$1() {
27524 centroidPointRing(x00$1, y00$1);
27527 function centroidPointFirstRing(x, y) {
27528 centroidStream$1.point = centroidPointRing;
27529 centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y);
27532 function centroidPointRing(x, y) {
27535 z = sqrt(dx * dx + dy * dy);
27537 X1$1 += z * (x0$3 + x) / 2;
27538 Y1$1 += z * (y0$3 + y) / 2;
27541 z = y0$3 * x - x0$3 * y;
27542 X2$1 += z * (x0$3 + x);
27543 Y2$1 += z * (y0$3 + y);
27545 centroidPoint$1(x0$3 = x, y0$3 = y);
27548 function PathContext(context) {
27549 this._context = context;
27552 PathContext.prototype = {
27554 pointRadius: function(_) {
27555 return this._radius = _, this;
27557 polygonStart: function() {
27560 polygonEnd: function() {
27563 lineStart: function() {
27566 lineEnd: function() {
27567 if (this._line === 0) this._context.closePath();
27570 point: function(x, y) {
27571 switch (this._point) {
27573 this._context.moveTo(x, y);
27578 this._context.lineTo(x, y);
27582 this._context.moveTo(x + this._radius, y);
27583 this._context.arc(x, y, this._radius, 0, tau$3);
27591 var lengthSum$1 = adder();
27598 var lengthStream$1 = {
27600 lineStart: function() {
27601 lengthStream$1.point = lengthPointFirst$1;
27603 lineEnd: function() {
27604 if (lengthRing) lengthPoint$1(x00$2, y00$2);
27605 lengthStream$1.point = noop$1;
27607 polygonStart: function() {
27610 polygonEnd: function() {
27613 result: function() {
27614 var length = +lengthSum$1;
27615 lengthSum$1.reset();
27620 function lengthPointFirst$1(x, y) {
27621 lengthStream$1.point = lengthPoint$1;
27622 x00$2 = x0$4 = x, y00$2 = y0$4 = y;
27625 function lengthPoint$1(x, y) {
27626 x0$4 -= x, y0$4 -= y;
27627 lengthSum$1.add(sqrt(x0$4 * x0$4 + y0$4 * y0$4));
27628 x0$4 = x, y0$4 = y;
27631 function PathString() {
27635 PathString.prototype = {
27636 _circle: circle$1(4.5),
27637 pointRadius: function(_) {
27638 return this._circle = circle$1(_), this;
27640 polygonStart: function() {
27643 polygonEnd: function() {
27646 lineStart: function() {
27649 lineEnd: function() {
27650 if (this._line === 0) this._string.push("Z");
27653 point: function(x, y) {
27654 switch (this._point) {
27656 this._string.push("M", x, ",", y);
27661 this._string.push("L", x, ",", y);
27665 this._string.push("M", x, ",", y, this._circle);
27670 result: function() {
27671 if (this._string.length) {
27672 var result = this._string.join("");
27679 function circle$1(radius) {
27680 return "m0," + radius
27681 + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
27682 + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
27686 var index$4 = function(projection, context) {
27687 var pointRadius = 4.5,
27691 function path(object) {
27693 if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
27694 geoStream(object, projectionStream(contextStream));
27696 return contextStream.result();
27699 path.area = function(object) {
27700 geoStream(object, projectionStream(areaStream$1));
27701 return areaStream$1.result();
27704 path.measure = function(object) {
27705 geoStream(object, projectionStream(lengthStream$1));
27706 return lengthStream$1.result();
27709 path.bounds = function(object) {
27710 geoStream(object, projectionStream(boundsStream$1));
27711 return boundsStream$1.result();
27714 path.centroid = function(object) {
27715 geoStream(object, projectionStream(centroidStream$1));
27716 return centroidStream$1.result();
27719 path.projection = function(_) {
27720 return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection;
27723 path.context = function(_) {
27724 if (!arguments.length) return context;
27725 contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _);
27726 if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
27730 path.pointRadius = function(_) {
27731 if (!arguments.length) return pointRadius;
27732 pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
27736 return path.projection(projection).context(context);
27739 var clip = function(pointVisible, clipLine, interpolate, start) {
27740 return function(rotate, sink) {
27741 var line = clipLine(sink),
27742 rotatedStart = rotate.invert(start[0], start[1]),
27743 ringBuffer = clipBuffer(),
27744 ringSink = clipLine(ringBuffer),
27745 polygonStarted = false,
27752 lineStart: lineStart,
27754 polygonStart: function() {
27755 clip.point = pointRing;
27756 clip.lineStart = ringStart;
27757 clip.lineEnd = ringEnd;
27761 polygonEnd: function() {
27762 clip.point = point;
27763 clip.lineStart = lineStart;
27764 clip.lineEnd = lineEnd;
27765 segments = merge(segments);
27766 var startInside = polygonContains(polygon, rotatedStart);
27767 if (segments.length) {
27768 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27769 clipPolygon(segments, compareIntersection, startInside, interpolate, sink);
27770 } else if (startInside) {
27771 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27773 interpolate(null, null, 1, sink);
27776 if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
27777 segments = polygon = null;
27779 sphere: function() {
27780 sink.polygonStart();
27782 interpolate(null, null, 1, sink);
27788 function point(lambda, phi) {
27789 var point = rotate(lambda, phi);
27790 if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi);
27793 function pointLine(lambda, phi) {
27794 var point = rotate(lambda, phi);
27795 line.point(point[0], point[1]);
27798 function lineStart() {
27799 clip.point = pointLine;
27803 function lineEnd() {
27804 clip.point = point;
27808 function pointRing(lambda, phi) {
27809 ring.push([lambda, phi]);
27810 var point = rotate(lambda, phi);
27811 ringSink.point(point[0], point[1]);
27814 function ringStart() {
27815 ringSink.lineStart();
27819 function ringEnd() {
27820 pointRing(ring[0][0], ring[0][1]);
27821 ringSink.lineEnd();
27823 var clean = ringSink.clean(),
27824 ringSegments = ringBuffer.result(),
27825 i, n = ringSegments.length, m,
27830 polygon.push(ring);
27835 // No intersections.
27837 segment = ringSegments[0];
27838 if ((m = segment.length - 1) > 0) {
27839 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27841 for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
27847 // Rejoin connected segments.
27848 // TODO reuse ringBuffer.rejoin()?
27849 if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
27851 segments.push(ringSegments.filter(validSegment));
27858 function validSegment(segment) {
27859 return segment.length > 1;
27862 // Intersections are sorted along the clip edge. For both antimeridian cutting
27863 // and circle clipping, the same comparison is used.
27864 function compareIntersection(a, b) {
27865 return ((a = a.x)[0] < 0 ? a[1] - halfPi$2 - epsilon$2 : halfPi$2 - a[1])
27866 - ((b = b.x)[0] < 0 ? b[1] - halfPi$2 - epsilon$2 : halfPi$2 - b[1]);
27869 var clipAntimeridian = clip(
27870 function() { return true; },
27871 clipAntimeridianLine,
27872 clipAntimeridianInterpolate,
27876 // Takes a line and cuts into visible segments. Return values: 0 - there were
27877 // intersections or the line was empty; 1 - no intersections; 2 - there were
27878 // intersections, and the first and last segments should be rejoined.
27879 function clipAntimeridianLine(stream) {
27883 clean; // no intersections
27886 lineStart: function() {
27887 stream.lineStart();
27890 point: function(lambda1, phi1) {
27891 var sign1 = lambda1 > 0 ? pi$3 : -pi$3,
27892 delta = abs(lambda1 - lambda0);
27893 if (abs(delta - pi$3) < epsilon$2) { // line crosses a pole
27894 stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$2 : -halfPi$2);
27895 stream.point(sign0, phi0);
27897 stream.lineStart();
27898 stream.point(sign1, phi0);
27899 stream.point(lambda1, phi0);
27901 } else if (sign0 !== sign1 && delta >= pi$3) { // line crosses antimeridian
27902 if (abs(lambda0 - sign0) < epsilon$2) lambda0 -= sign0 * epsilon$2; // handle degeneracies
27903 if (abs(lambda1 - sign1) < epsilon$2) lambda1 -= sign1 * epsilon$2;
27904 phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
27905 stream.point(sign0, phi0);
27907 stream.lineStart();
27908 stream.point(sign1, phi0);
27911 stream.point(lambda0 = lambda1, phi0 = phi1);
27914 lineEnd: function() {
27916 lambda0 = phi0 = NaN;
27918 clean: function() {
27919 return 2 - clean; // if intersections, rejoin first and last segments
27924 function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
27927 sinLambda0Lambda1 = sin$1(lambda0 - lambda1);
27928 return abs(sinLambda0Lambda1) > epsilon$2
27929 ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1)
27930 - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0))
27931 / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
27932 : (phi0 + phi1) / 2;
27935 function clipAntimeridianInterpolate(from, to, direction, stream) {
27937 if (from == null) {
27938 phi = direction * halfPi$2;
27939 stream.point(-pi$3, phi);
27940 stream.point(0, phi);
27941 stream.point(pi$3, phi);
27942 stream.point(pi$3, 0);
27943 stream.point(pi$3, -phi);
27944 stream.point(0, -phi);
27945 stream.point(-pi$3, -phi);
27946 stream.point(-pi$3, 0);
27947 stream.point(-pi$3, phi);
27948 } else if (abs(from[0] - to[0]) > epsilon$2) {
27949 var lambda = from[0] < to[0] ? pi$3 : -pi$3;
27950 phi = direction * lambda / 2;
27951 stream.point(-lambda, phi);
27952 stream.point(0, phi);
27953 stream.point(lambda, phi);
27955 stream.point(to[0], to[1]);
27959 var clipCircle = function(radius, delta) {
27960 var cr = cos$1(radius),
27961 smallRadius = cr > 0,
27962 notHemisphere = abs(cr) > epsilon$2; // TODO optimise for this common case
27964 function interpolate(from, to, direction, stream) {
27965 circleStream(stream, radius, delta, direction, from, to);
27968 function visible(lambda, phi) {
27969 return cos$1(lambda) * cos$1(phi) > cr;
27972 // Takes a line and cuts into visible segments. Return values used for polygon
27973 // clipping: 0 - there were intersections or the line was empty; 1 - no
27974 // intersections 2 - there were intersections, and the first and last segments
27975 // should be rejoined.
27976 function clipLine(stream) {
27977 var point0, // previous point
27978 c0, // code for previous point
27979 v0, // visibility of previous point
27980 v00, // visibility of first point
27981 clean; // no intersections
27983 lineStart: function() {
27987 point: function(lambda, phi) {
27988 var point1 = [lambda, phi],
27990 v = visible(lambda, phi),
27992 ? v ? 0 : code(lambda, phi)
27993 : v ? code(lambda + (lambda < 0 ? pi$3 : -pi$3), phi) : 0;
27994 if (!point0 && (v00 = v0 = v)) stream.lineStart();
27995 // Handle degeneracies.
27996 // TODO ignore if not clipping polygons.
27998 point2 = intersect(point0, point1);
27999 if (pointEqual(point0, point2) || pointEqual(point1, point2)) {
28000 point1[0] += epsilon$2;
28001 point1[1] += epsilon$2;
28002 v = visible(point1[0], point1[1]);
28008 // outside going in
28009 stream.lineStart();
28010 point2 = intersect(point1, point0);
28011 stream.point(point2[0], point2[1]);
28013 // inside going out
28014 point2 = intersect(point0, point1);
28015 stream.point(point2[0], point2[1]);
28019 } else if (notHemisphere && point0 && smallRadius ^ v) {
28021 // If the codes for two points are different, or are both zero,
28022 // and there this segment intersects with the small circle.
28023 if (!(c & c0) && (t = intersect(point1, point0, true))) {
28026 stream.lineStart();
28027 stream.point(t[0][0], t[0][1]);
28028 stream.point(t[1][0], t[1][1]);
28031 stream.point(t[1][0], t[1][1]);
28033 stream.lineStart();
28034 stream.point(t[0][0], t[0][1]);
28038 if (v && (!point0 || !pointEqual(point0, point1))) {
28039 stream.point(point1[0], point1[1]);
28041 point0 = point1, v0 = v, c0 = c;
28043 lineEnd: function() {
28044 if (v0) stream.lineEnd();
28047 // Rejoin first and last segments if there were intersections and the first
28048 // and last points were visible.
28049 clean: function() {
28050 return clean | ((v00 && v0) << 1);
28055 // Intersects the great circle between a and b with the clip circle.
28056 function intersect(a, b, two) {
28057 var pa = cartesian(a),
28060 // We have two planes, n1.p = d1 and n2.p = d2.
28061 // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
28062 var n1 = [1, 0, 0], // normal
28063 n2 = cartesianCross(pa, pb),
28064 n2n2 = cartesianDot(n2, n2),
28065 n1n2 = n2[0], // cartesianDot(n1, n2),
28066 determinant = n2n2 - n1n2 * n1n2;
28068 // Two polar points.
28069 if (!determinant) return !two && a;
28071 var c1 = cr * n2n2 / determinant,
28072 c2 = -cr * n1n2 / determinant,
28073 n1xn2 = cartesianCross(n1, n2),
28074 A = cartesianScale(n1, c1),
28075 B = cartesianScale(n2, c2);
28076 cartesianAddInPlace(A, B);
28078 // Solve |p(t)|^2 = 1.
28080 w = cartesianDot(A, u),
28081 uu = cartesianDot(u, u),
28082 t2 = w * w - uu * (cartesianDot(A, A) - 1);
28084 if (t2 < 0) return;
28087 q = cartesianScale(u, (-w - t) / uu);
28088 cartesianAddInPlace(q, A);
28091 if (!two) return q;
28093 // Two intersection points.
28094 var lambda0 = a[0],
28100 if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
28102 var delta = lambda1 - lambda0,
28103 polar = abs(delta - pi$3) < epsilon$2,
28104 meridian = polar || delta < epsilon$2;
28106 if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
28108 // Check that the first point is between a and b.
28111 ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$2 ? phi0 : phi1)
28112 : phi0 <= q[1] && q[1] <= phi1
28113 : delta > pi$3 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
28114 var q1 = cartesianScale(u, (-w + t) / uu);
28115 cartesianAddInPlace(q1, A);
28116 return [q, spherical(q1)];
28120 // Generates a 4-bit vector representing the location of a point relative to
28121 // the small circle's bounding box.
28122 function code(lambda, phi) {
28123 var r = smallRadius ? radius : pi$3 - radius,
28125 if (lambda < -r) code |= 1; // left
28126 else if (lambda > r) code |= 2; // right
28127 if (phi < -r) code |= 4; // below
28128 else if (phi > r) code |= 8; // above
28132 return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$3, radius - pi$3]);
28135 var transform = function(methods) {
28137 stream: transformer(methods)
28141 function transformer(methods) {
28142 return function(stream) {
28143 var s = new TransformStream;
28144 for (var key in methods) s[key] = methods[key];
28150 function TransformStream() {}
28152 TransformStream.prototype = {
28153 constructor: TransformStream,
28154 point: function(x, y) { this.stream.point(x, y); },
28155 sphere: function() { this.stream.sphere(); },
28156 lineStart: function() { this.stream.lineStart(); },
28157 lineEnd: function() { this.stream.lineEnd(); },
28158 polygonStart: function() { this.stream.polygonStart(); },
28159 polygonEnd: function() { this.stream.polygonEnd(); }
28162 function fitExtent(projection, extent, object) {
28163 var w = extent[1][0] - extent[0][0],
28164 h = extent[1][1] - extent[0][1],
28165 clip = projection.clipExtent && projection.clipExtent();
28169 .translate([0, 0]);
28171 if (clip != null) projection.clipExtent(null);
28173 geoStream(object, projection.stream(boundsStream$1));
28175 var b = boundsStream$1.result(),
28176 k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
28177 x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
28178 y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
28180 if (clip != null) projection.clipExtent(clip);
28184 .translate([x, y]);
28187 function fitSize(projection, size, object) {
28188 return fitExtent(projection, [[0, 0], size], object);
28192 var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance)
28194 var resample = function(project, delta2) {
28195 return +delta2 ? resample$1(project, delta2) : resampleNone(project);
28198 function resampleNone(project) {
28199 return transformer({
28200 point: function(x, y) {
28202 this.stream.point(x[0], x[1]);
28207 function resample$1(project, delta2) {
28209 function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
28212 d2 = dx * dx + dy * dy;
28213 if (d2 > 4 * delta2 && depth--) {
28217 m = sqrt(a * a + b * b + c * c),
28218 phi2 = asin(c /= m),
28219 lambda2 = abs(abs(c) - 1) < epsilon$2 || abs(lambda0 - lambda1) < epsilon$2 ? (lambda0 + lambda1) / 2 : atan2(b, a),
28220 p = project(lambda2, phi2),
28225 dz = dy * dx2 - dx * dy2;
28226 if (dz * dz / d2 > delta2 // perpendicular projected distance
28227 || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
28228 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
28229 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
28230 stream.point(x2, y2);
28231 resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
28235 return function(stream) {
28236 var lambda00, x00, y00, a00, b00, c00, // first point
28237 lambda0, x0, y0, a0, b0, c0; // previous point
28239 var resampleStream = {
28241 lineStart: lineStart,
28243 polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
28244 polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
28247 function point(x, y) {
28249 stream.point(x[0], x[1]);
28252 function lineStart() {
28254 resampleStream.point = linePoint;
28255 stream.lineStart();
28258 function linePoint(lambda, phi) {
28259 var c = cartesian([lambda, phi]), p = project(lambda, phi);
28260 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);
28261 stream.point(x0, y0);
28264 function lineEnd() {
28265 resampleStream.point = point;
28269 function ringStart() {
28271 resampleStream.point = ringPoint;
28272 resampleStream.lineEnd = ringEnd;
28275 function ringPoint(lambda, phi) {
28276 linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
28277 resampleStream.point = linePoint;
28280 function ringEnd() {
28281 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
28282 resampleStream.lineEnd = lineEnd;
28286 return resampleStream;
28290 var transformRadians = transformer({
28291 point: function(x, y) {
28292 this.stream.point(x * radians, y * radians);
28296 function projection(project) {
28297 return projectionMutator(function() { return project; })();
28300 function projectionMutator(projectAt) {
28303 x = 480, y = 250, // translate
28304 dx, dy, lambda = 0, phi = 0, // center
28305 deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate
28306 theta = null, preclip = clipAntimeridian, // clip angle
28307 x0 = null, y0, x1, y1, postclip = identity$4, // clip extent
28308 delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision
28312 function projection(point) {
28313 point = projectRotate(point[0] * radians, point[1] * radians);
28314 return [point[0] * k + dx, dy - point[1] * k];
28317 function invert(point) {
28318 point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k);
28319 return point && [point[0] * degrees$1, point[1] * degrees$1];
28322 function projectTransform(x, y) {
28323 return x = project(x, y), [x[0] * k + dx, dy - x[1] * k];
28326 projection.stream = function(stream) {
28327 return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream))));
28330 projection.clipAngle = function(_) {
28331 return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
28334 projection.clipExtent = function(_) {
28335 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]];
28338 projection.scale = function(_) {
28339 return arguments.length ? (k = +_, recenter()) : k;
28342 projection.translate = function(_) {
28343 return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
28346 projection.center = function(_) {
28347 return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
28350 projection.rotate = function(_) {
28351 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];
28354 projection.precision = function(_) {
28355 return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
28358 projection.fitExtent = function(extent, object) {
28359 return fitExtent(projection, extent, object);
28362 projection.fitSize = function(size, object) {
28363 return fitSize(projection, size, object);
28366 function recenter() {
28367 projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project);
28368 var center = project(lambda, phi);
28369 dx = x - center[0] * k;
28370 dy = y + center[1] * k;
28375 cache = cacheStream = null;
28379 return function() {
28380 project = projectAt.apply(this, arguments);
28381 projection.invert = project.invert && invert;
28386 function conicProjection(projectAt) {
28389 m = projectionMutator(projectAt),
28392 p.parallels = function(_) {
28393 return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1];
28399 function cylindricalEqualAreaRaw(phi0) {
28400 var cosPhi0 = cos$1(phi0);
28402 function forward(lambda, phi) {
28403 return [lambda * cosPhi0, sin$1(phi) / cosPhi0];
28406 forward.invert = function(x, y) {
28407 return [x / cosPhi0, asin(y * cosPhi0)];
28413 function conicEqualAreaRaw(y0, y1) {
28414 var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2;
28416 // Are the parallels symmetrical around the Equator?
28417 if (abs(n) < epsilon$2) return cylindricalEqualAreaRaw(y0);
28419 var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n;
28421 function project(x, y) {
28422 var r = sqrt(c - 2 * n * sin$1(y)) / n;
28423 return [r * sin$1(x *= n), r0 - r * cos$1(x)];
28426 project.invert = function(x, y) {
28428 return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
28434 var conicEqualArea = function() {
28435 return conicProjection(conicEqualAreaRaw)
28437 .center([0, 33.6442]);
28440 var albers = function() {
28441 return conicEqualArea()
28442 .parallels([29.5, 45.5])
28444 .translate([480, 250])
28446 .center([-0.6, 38.7]);
28449 // The projections must have mutually exclusive clip regions on the sphere,
28450 // as this will avoid emitting interleaving lines and polygons.
28451 function multiplex(streams) {
28452 var n = streams.length;
28454 point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
28455 sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
28456 lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
28457 lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
28458 polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
28459 polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
28463 // A composite projection for the United States, configured by default for
28464 // 960×500. The projection also works quite well at 960×600 if you change the
28465 // scale to 1285 and adjust the translate accordingly. The set of standard
28466 // parallels for each region comes from USGS, which is published here:
28467 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
28468 var albersUsa = function() {
28471 lower48 = albers(), lower48Point,
28472 alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
28473 hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
28474 point, pointStream = {point: function(x, y) { point = [x, y]; }};
28476 function albersUsa(coordinates) {
28477 var x = coordinates[0], y = coordinates[1];
28478 return point = null,
28479 (lower48Point.point(x, y), point)
28480 || (alaskaPoint.point(x, y), point)
28481 || (hawaiiPoint.point(x, y), point);
28484 albersUsa.invert = function(coordinates) {
28485 var k = lower48.scale(),
28486 t = lower48.translate(),
28487 x = (coordinates[0] - t[0]) / k,
28488 y = (coordinates[1] - t[1]) / k;
28489 return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
28490 : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
28491 : lower48).invert(coordinates);
28494 albersUsa.stream = function(stream) {
28495 return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
28498 albersUsa.precision = function(_) {
28499 if (!arguments.length) return lower48.precision();
28500 lower48.precision(_), alaska.precision(_), hawaii.precision(_);
28504 albersUsa.scale = function(_) {
28505 if (!arguments.length) return lower48.scale();
28506 lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
28507 return albersUsa.translate(lower48.translate());
28510 albersUsa.translate = function(_) {
28511 if (!arguments.length) return lower48.translate();
28512 var k = lower48.scale(), x = +_[0], y = +_[1];
28514 lower48Point = lower48
28516 .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
28517 .stream(pointStream);
28519 alaskaPoint = alaska
28520 .translate([x - 0.307 * k, y + 0.201 * k])
28521 .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]])
28522 .stream(pointStream);
28524 hawaiiPoint = hawaii
28525 .translate([x - 0.205 * k, y + 0.212 * k])
28526 .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]])
28527 .stream(pointStream);
28532 albersUsa.fitExtent = function(extent, object) {
28533 return fitExtent(albersUsa, extent, object);
28536 albersUsa.fitSize = function(size, object) {
28537 return fitSize(albersUsa, size, object);
28541 cache = cacheStream = null;
28545 return albersUsa.scale(1070);
28548 function azimuthalRaw(scale) {
28549 return function(x, y) {
28552 k = scale(cx * cy);
28560 function azimuthalInvert(angle) {
28561 return function(x, y) {
28562 var z = sqrt(x * x + y * y),
28567 atan2(x * sc, z * cc),
28568 asin(z && y * sc / z)
28573 var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
28574 return sqrt(2 / (1 + cxcy));
28577 azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
28578 return 2 * asin(z / 2);
28581 var azimuthalEqualArea = function() {
28582 return projection(azimuthalEqualAreaRaw)
28584 .clipAngle(180 - 1e-3);
28587 var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
28588 return (c = acos(c)) && c / sin$1(c);
28591 azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
28595 var azimuthalEquidistant = function() {
28596 return projection(azimuthalEquidistantRaw)
28598 .clipAngle(180 - 1e-3);
28601 function mercatorRaw(lambda, phi) {
28602 return [lambda, log(tan((halfPi$2 + phi) / 2))];
28605 mercatorRaw.invert = function(x, y) {
28606 return [x, 2 * atan(exp(y)) - halfPi$2];
28609 var mercator = function() {
28610 return mercatorProjection(mercatorRaw)
28611 .scale(961 / tau$3);
28614 function mercatorProjection(project) {
28615 var m = projection(project),
28618 translate = m.translate,
28619 clipExtent = m.clipExtent,
28620 x0 = null, y0, x1, y1; // clip extent
28622 m.scale = function(_) {
28623 return arguments.length ? (scale(_), reclip()) : scale();
28626 m.translate = function(_) {
28627 return arguments.length ? (translate(_), reclip()) : translate();
28630 m.center = function(_) {
28631 return arguments.length ? (center(_), reclip()) : center();
28634 m.clipExtent = function(_) {
28635 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]];
28638 function reclip() {
28639 var k = pi$3 * scale(),
28640 t = m(rotation(m.rotate()).invert([0, 0]));
28641 return clipExtent(x0 == null
28642 ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw
28643 ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]]
28644 : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]);
28651 return tan((halfPi$2 + y) / 2);
28654 function conicConformalRaw(y0, y1) {
28655 var cy0 = cos$1(y0),
28656 n = y0 === y1 ? sin$1(y0) : log(cy0 / cos$1(y1)) / log(tany(y1) / tany(y0)),
28657 f = cy0 * pow(tany(y0), n) / n;
28659 if (!n) return mercatorRaw;
28661 function project(x, y) {
28662 if (f > 0) { if (y < -halfPi$2 + epsilon$2) y = -halfPi$2 + epsilon$2; }
28663 else { if (y > halfPi$2 - epsilon$2) y = halfPi$2 - epsilon$2; }
28664 var r = f / pow(tany(y), n);
28665 return [r * sin$1(n * x), f - r * cos$1(n * x)];
28668 project.invert = function(x, y) {
28669 var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy);
28670 return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi$2];
28676 var conicConformal = function() {
28677 return conicProjection(conicConformalRaw)
28679 .parallels([30, 30]);
28682 function equirectangularRaw(lambda, phi) {
28683 return [lambda, phi];
28686 equirectangularRaw.invert = equirectangularRaw;
28688 var equirectangular = function() {
28689 return projection(equirectangularRaw)
28693 function conicEquidistantRaw(y0, y1) {
28694 var cy0 = cos$1(y0),
28695 n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0),
28698 if (abs(n) < epsilon$2) return equirectangularRaw;
28700 function project(x, y) {
28701 var gy = g - y, nx = n * x;
28702 return [gy * sin$1(nx), g - gy * cos$1(nx)];
28705 project.invert = function(x, y) {
28707 return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)];
28713 var conicEquidistant = function() {
28714 return conicProjection(conicEquidistantRaw)
28716 .center([0, 13.9389]);
28719 function gnomonicRaw(x, y) {
28720 var cy = cos$1(y), k = cos$1(x) * cy;
28721 return [cy * sin$1(x) / k, sin$1(y) / k];
28724 gnomonicRaw.invert = azimuthalInvert(atan);
28726 var gnomonic = function() {
28727 return projection(gnomonicRaw)
28732 function scaleTranslate(kx, ky, tx, ty) {
28733 return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity$4 : transformer({
28734 point: function(x, y) {
28735 this.stream.point(x * kx + tx, y * ky + ty);
28740 var identity$5 = function() {
28741 var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform = identity$4, // scale, translate and reflect
28742 x0 = null, y0, x1, y1, clip = identity$4, // clip extent
28748 cache = cacheStream = null;
28752 return projection = {
28753 stream: function(stream) {
28754 return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream));
28756 clipExtent: function(_) {
28757 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]];
28759 scale: function(_) {
28760 return arguments.length ? (transform = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k;
28762 translate: function(_) {
28763 return arguments.length ? (transform = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty];
28765 reflectX: function(_) {
28766 return arguments.length ? (transform = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0;
28768 reflectY: function(_) {
28769 return arguments.length ? (transform = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0;
28771 fitExtent: function(extent, object) {
28772 return fitExtent(projection, extent, object);
28774 fitSize: function(size, object) {
28775 return fitSize(projection, size, object);
28780 function orthographicRaw(x, y) {
28781 return [cos$1(y) * sin$1(x), sin$1(y)];
28784 orthographicRaw.invert = azimuthalInvert(asin);
28786 var orthographic = function() {
28787 return projection(orthographicRaw)
28789 .clipAngle(90 + epsilon$2);
28792 function stereographicRaw(x, y) {
28793 var cy = cos$1(y), k = 1 + cos$1(x) * cy;
28794 return [cy * sin$1(x) / k, sin$1(y) / k];
28797 stereographicRaw.invert = azimuthalInvert(function(z) {
28798 return 2 * atan(z);
28801 var stereographic = function() {
28802 return projection(stereographicRaw)
28807 function transverseMercatorRaw(lambda, phi) {
28808 return [log(tan((halfPi$2 + phi) / 2)), -lambda];
28811 transverseMercatorRaw.invert = function(x, y) {
28812 return [-y, 2 * atan(exp(x)) - halfPi$2];
28815 var transverseMercator = function() {
28816 var m = mercatorProjection(transverseMercatorRaw),
28820 m.center = function(_) {
28821 return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
28824 m.rotate = function(_) {
28825 return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
28828 return rotate([0, 0, 90])
28832 function defaultSeparation(a, b) {
28833 return a.parent === b.parent ? 1 : 2;
28836 function meanX(children) {
28837 return children.reduce(meanXReduce, 0) / children.length;
28840 function meanXReduce(x, c) {
28844 function maxY(children) {
28845 return 1 + children.reduce(maxYReduce, 0);
28848 function maxYReduce(y, c) {
28849 return Math.max(y, c.y);
28852 function leafLeft(node) {
28854 while (children = node.children) node = children[0];
28858 function leafRight(node) {
28860 while (children = node.children) node = children[children.length - 1];
28864 var cluster = function() {
28865 var separation = defaultSeparation,
28870 function cluster(root) {
28874 // First walk, computing the initial x & y values.
28875 root.eachAfter(function(node) {
28876 var children = node.children;
28878 node.x = meanX(children);
28879 node.y = maxY(children);
28881 node.x = previousNode ? x += separation(node, previousNode) : 0;
28883 previousNode = node;
28887 var left = leafLeft(root),
28888 right = leafRight(root),
28889 x0 = left.x - separation(left, right) / 2,
28890 x1 = right.x + separation(right, left) / 2;
28892 // Second walk, normalizing x & y to the desired size.
28893 return root.eachAfter(nodeSize ? function(node) {
28894 node.x = (node.x - root.x) * dx;
28895 node.y = (root.y - node.y) * dy;
28896 } : function(node) {
28897 node.x = (node.x - x0) / (x1 - x0) * dx;
28898 node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
28902 cluster.separation = function(x) {
28903 return arguments.length ? (separation = x, cluster) : separation;
28906 cluster.size = function(x) {
28907 return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
28910 cluster.nodeSize = function(x) {
28911 return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
28917 function count(node) {
28919 children = node.children,
28920 i = children && children.length;
28922 else while (--i >= 0) sum += children[i].value;
28926 var node_count = function() {
28927 return this.eachAfter(count);
28930 var node_each = function(callback) {
28931 var node = this, current, next = [node], children, i, n;
28933 current = next.reverse(), next = [];
28934 while (node = current.pop()) {
28935 callback(node), children = node.children;
28936 if (children) for (i = 0, n = children.length; i < n; ++i) {
28937 next.push(children[i]);
28940 } while (next.length);
28944 var node_eachBefore = function(callback) {
28945 var node = this, nodes = [node], children, i;
28946 while (node = nodes.pop()) {
28947 callback(node), children = node.children;
28948 if (children) for (i = children.length - 1; i >= 0; --i) {
28949 nodes.push(children[i]);
28955 var node_eachAfter = function(callback) {
28956 var node = this, nodes = [node], next = [], children, i, n;
28957 while (node = nodes.pop()) {
28958 next.push(node), children = node.children;
28959 if (children) for (i = 0, n = children.length; i < n; ++i) {
28960 nodes.push(children[i]);
28963 while (node = next.pop()) {
28969 var node_sum = function(value) {
28970 return this.eachAfter(function(node) {
28971 var sum = +value(node.data) || 0,
28972 children = node.children,
28973 i = children && children.length;
28974 while (--i >= 0) sum += children[i].value;
28979 var node_sort = function(compare) {
28980 return this.eachBefore(function(node) {
28981 if (node.children) {
28982 node.children.sort(compare);
28987 var node_path = function(end) {
28989 ancestor = leastCommonAncestor(start, end),
28991 while (start !== ancestor) {
28992 start = start.parent;
28995 var k = nodes.length;
28996 while (end !== ancestor) {
28997 nodes.splice(k, 0, end);
29003 function leastCommonAncestor(a, b) {
29004 if (a === b) return a;
29005 var aNodes = a.ancestors(),
29006 bNodes = b.ancestors(),
29018 var node_ancestors = function() {
29019 var node = this, nodes = [node];
29020 while (node = node.parent) {
29026 var node_descendants = function() {
29028 this.each(function(node) {
29034 var node_leaves = function() {
29036 this.eachBefore(function(node) {
29037 if (!node.children) {
29044 var node_links = function() {
29045 var root = this, links = [];
29046 root.each(function(node) {
29047 if (node !== root) { // Don’t include the root’s parent, if any.
29048 links.push({source: node.parent, target: node});
29054 function hierarchy(data, children) {
29055 var root = new Node(data),
29056 valued = +data.value && (root.value = data.value),
29064 if (children == null) children = defaultChildren;
29066 while (node = nodes.pop()) {
29067 if (valued) node.value = +node.data.value;
29068 if ((childs = children(node.data)) && (n = childs.length)) {
29069 node.children = new Array(n);
29070 for (i = n - 1; i >= 0; --i) {
29071 nodes.push(child = node.children[i] = new Node(childs[i]));
29072 child.parent = node;
29073 child.depth = node.depth + 1;
29078 return root.eachBefore(computeHeight);
29081 function node_copy() {
29082 return hierarchy(this).eachBefore(copyData);
29085 function defaultChildren(d) {
29089 function copyData(node) {
29090 node.data = node.data.data;
29093 function computeHeight(node) {
29095 do node.height = height;
29096 while ((node = node.parent) && (node.height < ++height));
29099 function Node(data) {
29103 this.parent = null;
29106 Node.prototype = hierarchy.prototype = {
29110 eachAfter: node_eachAfter,
29111 eachBefore: node_eachBefore,
29115 ancestors: node_ancestors,
29116 descendants: node_descendants,
29117 leaves: node_leaves,
29122 function Node$2(value) {
29127 var shuffle$1 = function(array) {
29129 n = (array = array.slice()).length,
29134 var next = new Node$2(array[n - 1]);
29135 if (node) node = node.next = next;
29136 else node = head = next;
29137 array[i] = array[--n];
29146 var enclose = function(circles) {
29147 return encloseN(shuffle$1(circles), []);
29150 function encloses(a, b) {
29151 var dx = b.x - a.x,
29154 return dr * dr + 1e-6 > dx * dx + dy * dy;
29157 // Returns the smallest circle that contains circles L and intersects circles B.
29158 function encloseN(L, B) {
29165 switch (B.length) {
29166 case 1: circle = enclose1(B[0]); break;
29167 case 2: circle = enclose2(B[0], B[1]); break;
29168 case 3: circle = enclose3(B[0], B[1], B[2]); break;
29172 p1 = l1._, l2 = l1.next;
29173 if (!circle || !encloses(circle, p1)) {
29175 // Temporarily truncate L before l1.
29176 if (l0) L.tail = l0, l0.next = null;
29177 else L.head = L.tail = null;
29180 circle = encloseN(L, B); // Note: reorders L!
29183 // Move l1 to the front of L and reconnect the truncated list L.
29184 if (L.head) l1.next = L.head, L.head = l1;
29185 else l1.next = null, L.head = L.tail = l1;
29186 l0 = L.tail, l0.next = l2;
29198 function enclose1(a) {
29206 function enclose2(a, b) {
29207 var x1 = a.x, y1 = a.y, r1 = a.r,
29208 x2 = b.x, y2 = b.y, r2 = b.r,
29209 x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
29210 l = Math.sqrt(x21 * x21 + y21 * y21);
29212 x: (x1 + x2 + x21 / l * r21) / 2,
29213 y: (y1 + y2 + y21 / l * r21) / 2,
29214 r: (l + r1 + r2) / 2
29218 function enclose3(a, b, c) {
29219 var x1 = a.x, y1 = a.y, r1 = a.r,
29220 x2 = b.x, y2 = b.y, r2 = b.r,
29221 x3 = c.x, y3 = c.y, r3 = c.r,
29222 a2 = 2 * (x1 - x2),
29223 b2 = 2 * (y1 - y2),
29224 c2 = 2 * (r2 - r1),
29225 d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2,
29226 a3 = 2 * (x1 - x3),
29227 b3 = 2 * (y1 - y3),
29228 c3 = 2 * (r3 - r1),
29229 d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3,
29230 ab = a3 * b2 - a2 * b3,
29231 xa = (b2 * d3 - b3 * d2) / ab - x1,
29232 xb = (b3 * c2 - b2 * c3) / ab,
29233 ya = (a3 * d2 - a2 * d3) / ab - y1,
29234 yb = (a2 * c3 - a3 * c2) / ab,
29235 A = xb * xb + yb * yb - 1,
29236 B = 2 * (xa * xb + ya * yb + r1),
29237 C = xa * xa + ya * ya - r1 * r1,
29238 r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
29240 x: xa + xb * r + x1,
29241 y: ya + yb * r + y1,
29246 function place(a, b, c) {
29253 dc = dx * dx + dy * dy;
29255 var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc),
29256 y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
29257 c.x = ax + x * dx + y * dy;
29258 c.y = ay + x * dy - y * dx;
29265 function intersects(a, b) {
29266 var dx = b.x - a.x,
29269 return dr * dr - 1e-6 > dx * dx + dy * dy;
29272 function distance2(node, x, y) {
29276 dx = (a.x * b.r + b.x * a.r) / ab - x,
29277 dy = (a.y * b.r + b.y * a.r) / ab - y;
29278 return dx * dx + dy * dy;
29281 function Node$1(circle) {
29284 this.previous = null;
29287 function packEnclose(circles) {
29288 if (!(n = circles.length)) return 0;
29292 // Place the first circle.
29293 a = circles[0], a.x = 0, a.y = 0;
29294 if (!(n > 1)) return a.r;
29296 // Place the second circle.
29297 b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
29298 if (!(n > 2)) return a.r + b.r;
29300 // Place the third circle.
29301 place(b, a, c = circles[2]);
29303 // Initialize the weighted centroid.
29304 var aa = a.r * a.r,
29308 ox = aa * a.x + ba * b.x + ca * c.x,
29309 oy = aa * a.y + ba * b.y + ca * c.y,
29310 cx, cy, i, j, k, sj, sk;
29312 // Initialize the front-chain using the first three circles a, b and c.
29313 a = new Node$1(a), b = new Node$1(b), c = new Node$1(c);
29314 a.next = c.previous = b;
29315 b.next = a.previous = c;
29316 c.next = b.previous = a;
29318 // Attempt to place each remaining circle…
29319 pack: for (i = 3; i < n; ++i) {
29320 place(a._, b._, c = circles[i]), c = new Node$1(c);
29322 // Find the closest intersecting circle on the front-chain, if any.
29323 // “Closeness” is determined by linear distance along the front-chain.
29324 // “Ahead” or “behind” is likewise determined by linear distance.
29325 j = b.next, k = a.previous, sj = b._.r, sk = a._.r;
29328 if (intersects(j._, c._)) {
29329 b = j, a.next = b, b.previous = a, --i;
29332 sj += j._.r, j = j.next;
29334 if (intersects(k._, c._)) {
29335 a = k, a.next = b, b.previous = a, --i;
29338 sk += k._.r, k = k.previous;
29340 } while (j !== k.next);
29342 // Success! Insert the new circle c between a and b.
29343 c.previous = a, c.next = b, a.next = b.previous = b = c;
29345 // Update the weighted centroid.
29346 oa += ca = c._.r * c._.r;
29350 // Compute the new closest circle pair to the centroid.
29351 aa = distance2(a, cx = ox / oa, cy = oy / oa);
29352 while ((c = c.next) !== b) {
29353 if ((ca = distance2(c, cx, cy)) < aa) {
29360 // Compute the enclosing circle of the front chain.
29361 a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);
29363 // Translate the circles to put the enclosing circle around the origin.
29364 for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
29369 var siblings = function(circles) {
29370 packEnclose(circles);
29374 function optional(f) {
29375 return f == null ? null : required(f);
29378 function required(f) {
29379 if (typeof f !== "function") throw new Error;
29383 function constantZero() {
29387 var constant$8 = function(x) {
29388 return function() {
29393 function defaultRadius$1(d) {
29394 return Math.sqrt(d.value);
29397 var index$5 = function() {
29401 padding = constantZero;
29403 function pack(root) {
29404 root.x = dx / 2, root.y = dy / 2;
29406 root.eachBefore(radiusLeaf(radius))
29407 .eachAfter(packChildren(padding, 0.5))
29408 .eachBefore(translateChild(1));
29410 root.eachBefore(radiusLeaf(defaultRadius$1))
29411 .eachAfter(packChildren(constantZero, 1))
29412 .eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))
29413 .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
29418 pack.radius = function(x) {
29419 return arguments.length ? (radius = optional(x), pack) : radius;
29422 pack.size = function(x) {
29423 return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
29426 pack.padding = function(x) {
29427 return arguments.length ? (padding = typeof x === "function" ? x : constant$8(+x), pack) : padding;
29433 function radiusLeaf(radius) {
29434 return function(node) {
29435 if (!node.children) {
29436 node.r = Math.max(0, +radius(node) || 0);
29441 function packChildren(padding, k) {
29442 return function(node) {
29443 if (children = node.children) {
29446 n = children.length,
29447 r = padding(node) * k || 0,
29450 if (r) for (i = 0; i < n; ++i) children[i].r += r;
29451 e = packEnclose(children);
29452 if (r) for (i = 0; i < n; ++i) children[i].r -= r;
29458 function translateChild(k) {
29459 return function(node) {
29460 var parent = node.parent;
29463 node.x = parent.x + k * node.x;
29464 node.y = parent.y + k * node.y;
29469 var roundNode = function(node) {
29470 node.x0 = Math.round(node.x0);
29471 node.y0 = Math.round(node.y0);
29472 node.x1 = Math.round(node.x1);
29473 node.y1 = Math.round(node.y1);
29476 var treemapDice = function(parent, x0, y0, x1, y1) {
29477 var nodes = parent.children,
29481 k = parent.value && (x1 - x0) / parent.value;
29484 node = nodes[i], node.y0 = y0, node.y1 = y1;
29485 node.x0 = x0, node.x1 = x0 += node.value * k;
29489 var partition = function() {
29495 function partition(root) {
29496 var n = root.height + 1;
29501 root.eachBefore(positionNode(dy, n));
29502 if (round) root.eachBefore(roundNode);
29506 function positionNode(dy, n) {
29507 return function(node) {
29508 if (node.children) {
29509 treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
29513 x1 = node.x1 - padding,
29514 y1 = node.y1 - padding;
29515 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29516 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29524 partition.round = function(x) {
29525 return arguments.length ? (round = !!x, partition) : round;
29528 partition.size = function(x) {
29529 return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
29532 partition.padding = function(x) {
29533 return arguments.length ? (padding = +x, partition) : padding;
29539 var keyPrefix$1 = "$";
29540 var preroot = {depth: -1};
29541 var ambiguous = {};
29543 function defaultId(d) {
29547 function defaultParentId(d) {
29551 var stratify = function() {
29552 var id = defaultId,
29553 parentId = defaultParentId;
29555 function stratify(data) {
29562 nodes = new Array(n),
29567 for (i = 0; i < n; ++i) {
29568 d = data[i], node = nodes[i] = new Node(d);
29569 if ((nodeId = id(d, i, data)) != null && (nodeId += "")) {
29570 nodeKey = keyPrefix$1 + (node.id = nodeId);
29571 nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node;
29575 for (i = 0; i < n; ++i) {
29576 node = nodes[i], nodeId = parentId(data[i], i, data);
29577 if (nodeId == null || !(nodeId += "")) {
29578 if (root) throw new Error("multiple roots");
29581 parent = nodeByKey[keyPrefix$1 + nodeId];
29582 if (!parent) throw new Error("missing: " + nodeId);
29583 if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
29584 if (parent.children) parent.children.push(node);
29585 else parent.children = [node];
29586 node.parent = parent;
29590 if (!root) throw new Error("no root");
29591 root.parent = preroot;
29592 root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
29593 root.parent = null;
29594 if (n > 0) throw new Error("cycle");
29599 stratify.id = function(x) {
29600 return arguments.length ? (id = required(x), stratify) : id;
29603 stratify.parentId = function(x) {
29604 return arguments.length ? (parentId = required(x), stratify) : parentId;
29610 function defaultSeparation$1(a, b) {
29611 return a.parent === b.parent ? 1 : 2;
29614 // function radialSeparation(a, b) {
29615 // return (a.parent === b.parent ? 1 : 2) / a.depth;
29618 // This function is used to traverse the left contour of a subtree (or
29619 // subforest). It returns the successor of v on this contour. This successor is
29620 // either given by the leftmost child of v or by the thread of v. The function
29621 // returns null if and only if v is on the highest level of its subtree.
29622 function nextLeft(v) {
29623 var children = v.children;
29624 return children ? children[0] : v.t;
29627 // This function works analogously to nextLeft.
29628 function nextRight(v) {
29629 var children = v.children;
29630 return children ? children[children.length - 1] : v.t;
29633 // Shifts the current subtree rooted at w+. This is done by increasing
29634 // prelim(w+) and mod(w+) by shift.
29635 function moveSubtree(wm, wp, shift) {
29636 var change = shift / (wp.i - wm.i);
29644 // All other shifts, applied to the smaller subtrees between w- and w+, are
29645 // performed by this function. To prepare the shifts, we have to adjust
29646 // change(w+), shift(w+), and change(w-).
29647 function executeShifts(v) {
29650 children = v.children,
29651 i = children.length,
29657 shift += w.s + (change += w.c);
29661 // If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
29662 // returns the specified (default) ancestor.
29663 function nextAncestor(vim, v, ancestor) {
29664 return vim.a.parent === v.parent ? vim.a : ancestor;
29667 function TreeNode(node, i) {
29669 this.parent = null;
29670 this.children = null;
29671 this.A = null; // default ancestor
29672 this.a = this; // ancestor
29673 this.z = 0; // prelim
29675 this.c = 0; // change
29676 this.s = 0; // shift
29677 this.t = null; // thread
29678 this.i = i; // number
29681 TreeNode.prototype = Object.create(Node.prototype);
29683 function treeRoot(root) {
29684 var tree = new TreeNode(root, 0),
29692 while (node = nodes.pop()) {
29693 if (children = node._.children) {
29694 node.children = new Array(n = children.length);
29695 for (i = n - 1; i >= 0; --i) {
29696 nodes.push(child = node.children[i] = new TreeNode(children[i], i));
29697 child.parent = node;
29702 (tree.parent = new TreeNode(null, 0)).children = [tree];
29706 // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
29707 var tree = function() {
29708 var separation = defaultSeparation$1,
29713 function tree(root) {
29714 var t = treeRoot(root);
29716 // Compute the layout using Buchheim et al.’s algorithm.
29717 t.eachAfter(firstWalk), t.parent.m = -t.z;
29718 t.eachBefore(secondWalk);
29720 // If a fixed node size is specified, scale x and y.
29721 if (nodeSize) root.eachBefore(sizeNode);
29723 // If a fixed tree size is specified, scale x and y based on the extent.
29724 // Compute the left-most, right-most, and depth-most nodes for extents.
29729 root.eachBefore(function(node) {
29730 if (node.x < left.x) left = node;
29731 if (node.x > right.x) right = node;
29732 if (node.depth > bottom.depth) bottom = node;
29734 var s = left === right ? 1 : separation(left, right) / 2,
29736 kx = dx / (right.x + s + tx),
29737 ky = dy / (bottom.depth || 1);
29738 root.eachBefore(function(node) {
29739 node.x = (node.x + tx) * kx;
29740 node.y = node.depth * ky;
29747 // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
29748 // applied recursively to the children of v, as well as the function
29749 // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
29750 // node v is placed to the midpoint of its outermost children.
29751 function firstWalk(v) {
29752 var children = v.children,
29753 siblings = v.parent.children,
29754 w = v.i ? siblings[v.i - 1] : null;
29757 var midpoint = (children[0].z + children[children.length - 1].z) / 2;
29759 v.z = w.z + separation(v._, w._);
29760 v.m = v.z - midpoint;
29765 v.z = w.z + separation(v._, w._);
29767 v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
29770 // Computes all real x-coordinates by summing up the modifiers recursively.
29771 function secondWalk(v) {
29772 v._.x = v.z + v.parent.m;
29776 // The core of the algorithm. Here, a new subtree is combined with the
29777 // previous subtrees. Threads are used to traverse the inside and outside
29778 // contours of the left and right subtree up to the highest common level. The
29779 // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
29780 // superscript o means outside and i means inside, the subscript - means left
29781 // subtree and + means right subtree. For summing up the modifiers along the
29782 // contour, we use respective variables si+, si-, so-, and so+. Whenever two
29783 // nodes of the inside contours conflict, we compute the left one of the
29784 // greatest uncommon ancestors using the function ANCESTOR and call MOVE
29785 // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
29786 // Finally, we add a new thread (if necessary).
29787 function apportion(v, w, ancestor) {
29792 vom = vip.parent.children[0],
29798 while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
29799 vom = nextLeft(vom);
29800 vop = nextRight(vop);
29802 shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
29804 moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
29813 if (vim && !nextRight(vop)) {
29815 vop.m += sim - sop;
29817 if (vip && !nextLeft(vom)) {
29819 vom.m += sip - som;
29826 function sizeNode(node) {
29828 node.y = node.depth * dy;
29831 tree.separation = function(x) {
29832 return arguments.length ? (separation = x, tree) : separation;
29835 tree.size = function(x) {
29836 return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
29839 tree.nodeSize = function(x) {
29840 return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
29846 var treemapSlice = function(parent, x0, y0, x1, y1) {
29847 var nodes = parent.children,
29851 k = parent.value && (y1 - y0) / parent.value;
29854 node = nodes[i], node.x0 = x0, node.x1 = x1;
29855 node.y0 = y0, node.y1 = y0 += node.value * k;
29859 var phi = (1 + Math.sqrt(5)) / 2;
29861 function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
29863 nodes = parent.children,
29870 value = parent.value,
29880 dx = x1 - x0, dy = y1 - y0;
29882 // Find the next non-empty node.
29883 do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
29884 minValue = maxValue = sumValue;
29885 alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
29886 beta = sumValue * sumValue * alpha;
29887 minRatio = Math.max(maxValue / beta, beta / minValue);
29889 // Keep adding nodes while the aspect ratio maintains or improves.
29890 for (; i1 < n; ++i1) {
29891 sumValue += nodeValue = nodes[i1].value;
29892 if (nodeValue < minValue) minValue = nodeValue;
29893 if (nodeValue > maxValue) maxValue = nodeValue;
29894 beta = sumValue * sumValue * alpha;
29895 newRatio = Math.max(maxValue / beta, beta / minValue);
29896 if (newRatio > minRatio) { sumValue -= nodeValue; break; }
29897 minRatio = newRatio;
29900 // Position and record the row orientation.
29901 rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
29902 if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
29903 else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
29904 value -= sumValue, i0 = i1;
29910 var squarify = ((function custom(ratio) {
29912 function squarify(parent, x0, y0, x1, y1) {
29913 squarifyRatio(ratio, parent, x0, y0, x1, y1);
29916 squarify.ratio = function(x) {
29917 return custom((x = +x) > 1 ? x : 1);
29923 var index$6 = function() {
29924 var tile = squarify,
29928 paddingStack = [0],
29929 paddingInner = constantZero,
29930 paddingTop = constantZero,
29931 paddingRight = constantZero,
29932 paddingBottom = constantZero,
29933 paddingLeft = constantZero;
29935 function treemap(root) {
29940 root.eachBefore(positionNode);
29941 paddingStack = [0];
29942 if (round) root.eachBefore(roundNode);
29946 function positionNode(node) {
29947 var p = paddingStack[node.depth],
29952 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29953 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29958 if (node.children) {
29959 p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
29960 x0 += paddingLeft(node) - p;
29961 y0 += paddingTop(node) - p;
29962 x1 -= paddingRight(node) - p;
29963 y1 -= paddingBottom(node) - p;
29964 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29965 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29966 tile(node, x0, y0, x1, y1);
29970 treemap.round = function(x) {
29971 return arguments.length ? (round = !!x, treemap) : round;
29974 treemap.size = function(x) {
29975 return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
29978 treemap.tile = function(x) {
29979 return arguments.length ? (tile = required(x), treemap) : tile;
29982 treemap.padding = function(x) {
29983 return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
29986 treemap.paddingInner = function(x) {
29987 return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$8(+x), treemap) : paddingInner;
29990 treemap.paddingOuter = function(x) {
29991 return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
29994 treemap.paddingTop = function(x) {
29995 return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$8(+x), treemap) : paddingTop;
29998 treemap.paddingRight = function(x) {
29999 return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$8(+x), treemap) : paddingRight;
30002 treemap.paddingBottom = function(x) {
30003 return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$8(+x), treemap) : paddingBottom;
30006 treemap.paddingLeft = function(x) {
30007 return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$8(+x), treemap) : paddingLeft;
30013 var binary = function(parent, x0, y0, x1, y1) {
30014 var nodes = parent.children,
30015 i, n = nodes.length,
30016 sum, sums = new Array(n + 1);
30018 for (sums[0] = sum = i = 0; i < n; ++i) {
30019 sums[i + 1] = sum += nodes[i].value;
30022 partition(0, n, parent.value, x0, y0, x1, y1);
30024 function partition(i, j, value, x0, y0, x1, y1) {
30026 var node = nodes[i];
30027 node.x0 = x0, node.y0 = y0;
30028 node.x1 = x1, node.y1 = y1;
30032 var valueOffset = sums[i],
30033 valueTarget = (value / 2) + valueOffset,
30038 var mid = k + hi >>> 1;
30039 if (sums[mid] < valueTarget) k = mid + 1;
30043 if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k;
30045 var valueLeft = sums[k] - valueOffset,
30046 valueRight = value - valueLeft;
30048 if ((x1 - x0) > (y1 - y0)) {
30049 var xk = (x0 * valueRight + x1 * valueLeft) / value;
30050 partition(i, k, valueLeft, x0, y0, xk, y1);
30051 partition(k, j, valueRight, xk, y0, x1, y1);
30053 var yk = (y0 * valueRight + y1 * valueLeft) / value;
30054 partition(i, k, valueLeft, x0, y0, x1, yk);
30055 partition(k, j, valueRight, x0, yk, x1, y1);
30060 var sliceDice = function(parent, x0, y0, x1, y1) {
30061 (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
30064 var resquarify = ((function custom(ratio) {
30066 function resquarify(parent, x0, y0, x1, y1) {
30067 if ((rows = parent._squarify) && (rows.ratio === ratio)) {
30075 value = parent.value;
30078 row = rows[j], nodes = row.children;
30079 for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
30080 if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
30081 else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
30082 value -= row.value;
30085 parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
30086 rows.ratio = ratio;
30090 resquarify.ratio = function(x) {
30091 return custom((x = +x) > 1 ? x : 1);
30097 var d3polygonArea = function(polygon) {
30099 n = polygon.length,
30101 b = polygon[n - 1],
30107 area += a[1] * b[0] - a[0] * b[1];
30113 var d3polygonCentroid = function(polygon) {
30115 n = polygon.length,
30119 b = polygon[n - 1],
30126 k += c = a[0] * b[1] - b[0] * a[1];
30127 x += (a[0] + b[0]) * c;
30128 y += (a[1] + b[1]) * c;
30131 return k *= 3, [x / k, y / k];
30134 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
30135 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
30136 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
30137 // negative if clockwise, and zero if the points are collinear.
30138 var cross$1 = function(a, b, c) {
30139 return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
30142 function lexicographicOrder(a, b) {
30143 return a[0] - b[0] || a[1] - b[1];
30146 // Computes the upper convex hull per the monotone chain algorithm.
30147 // Assumes points.length >= 3, is sorted by x, unique in y.
30148 // Returns an array of indices into points in left-to-right order.
30149 function computeUpperHullIndexes(points) {
30150 var n = points.length,
30154 for (var i = 2; i < n; ++i) {
30155 while (size > 1 && cross$1(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size;
30156 indexes[size++] = i;
30159 return indexes.slice(0, size); // remove popped points
30162 var d3polygonHull = function(points) {
30163 if ((n = points.length) < 3) return null;
30167 sortedPoints = new Array(n),
30168 flippedPoints = new Array(n);
30170 for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i];
30171 sortedPoints.sort(lexicographicOrder);
30172 for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
30174 var upperIndexes = computeUpperHullIndexes(sortedPoints),
30175 lowerIndexes = computeUpperHullIndexes(flippedPoints);
30177 // Construct the hull polygon, removing possible duplicate endpoints.
30178 var skipLeft = lowerIndexes[0] === upperIndexes[0],
30179 skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
30182 // Add upper hull in right-to-l order.
30183 // Then add lower hull in left-to-right order.
30184 for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]);
30185 for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
30190 var contains$1 = function(polygon, point) {
30191 var n = polygon.length,
30192 p = polygon[n - 1],
30193 x = point[0], y = point[1],
30194 x0 = p[0], y0 = p[1],
30198 for (var i = 0; i < n; ++i) {
30199 p = polygon[i], x1 = p[0], y1 = p[1];
30200 if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside;
30207 var length$1 = function(polygon) {
30209 n = polygon.length,
30210 b = polygon[n - 1],
30225 perimeter += Math.sqrt(xa * xa + ya * ya);
30231 var slice$3 = [].slice;
30235 function Queue(size) {
30236 if (!(size >= 1)) throw new Error;
30239 this._error = null;
30245 this._start = 0; // inside a synchronous task callback?
30248 Queue.prototype = queue.prototype = {
30249 constructor: Queue,
30250 defer: function(callback) {
30251 if (typeof callback !== "function" || this._call) throw new Error;
30252 if (this._error != null) return this;
30253 var t = slice$3.call(arguments, 1);
30255 ++this._waiting, this._tasks.push(t);
30259 abort: function() {
30260 if (this._error == null) abort(this, new Error("abort"));
30263 await: function(callback) {
30264 if (typeof callback !== "function" || this._call) throw new Error;
30265 this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
30269 awaitAll: function(callback) {
30270 if (typeof callback !== "function" || this._call) throw new Error;
30271 this._call = callback;
30277 function poke$1(q) {
30279 try { start$1(q); } // let the current task complete
30281 if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously
30282 else if (!q._data) throw e; // await callback errored synchronously
30287 function start$1(q) {
30288 while (q._start = q._waiting && q._active < q._size) {
30289 var i = q._ended + q._active,
30294 --q._waiting, ++q._active;
30295 t = c.apply(null, t);
30296 if (!q._tasks[i]) continue; // task finished synchronously
30297 q._tasks[i] = t || noabort;
30301 function end(q, i) {
30302 return function(e, r) {
30303 if (!q._tasks[i]) return; // ignore multiple callbacks
30304 --q._active, ++q._ended;
30305 q._tasks[i] = null;
30306 if (q._error != null) return; // ignore secondary errors
30311 if (q._waiting) poke$1(q);
30312 else maybeNotify(q);
30317 function abort(q, e) {
30318 var i = q._tasks.length, t;
30319 q._error = e; // ignore active callbacks
30320 q._data = undefined; // allow gc
30321 q._waiting = NaN; // prevent starting
30324 if (t = q._tasks[i]) {
30325 q._tasks[i] = null;
30328 catch (e) { /* ignore */ }
30333 q._active = NaN; // allow notification
30337 function maybeNotify(q) {
30338 if (!q._active && q._call) {
30340 q._data = undefined; // allow gc
30341 q._call(q._error, d);
30345 function queue(concurrency) {
30346 return new Queue(arguments.length ? +concurrency : Infinity);
30349 var uniform = function(min, max) {
30350 min = min == null ? 0 : +min;
30351 max = max == null ? 1 : +max;
30352 if (arguments.length === 1) max = min, min = 0;
30354 return function() {
30355 return Math.random() * max + min;
30359 var normal = function(mu, sigma) {
30361 mu = mu == null ? 0 : +mu;
30362 sigma = sigma == null ? 1 : +sigma;
30363 return function() {
30366 // If available, use the second previously-generated uniform random.
30367 if (x != null) y = x, x = null;
30369 // Otherwise, generate a new x and y.
30371 x = Math.random() * 2 - 1;
30372 y = Math.random() * 2 - 1;
30374 } while (!r || r > 1);
30376 return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r);
30380 var logNormal = function() {
30381 var randomNormal = normal.apply(this, arguments);
30382 return function() {
30383 return Math.exp(randomNormal());
30387 var irwinHall = function(n) {
30388 return function() {
30389 for (var sum = 0, i = 0; i < n; ++i) sum += Math.random();
30394 var bates = function(n) {
30395 var randomIrwinHall = irwinHall(n);
30396 return function() {
30397 return randomIrwinHall() / n;
30401 var exponential$1 = function(lambda) {
30402 return function() {
30403 return -Math.log(1 - Math.random()) / lambda;
30407 var request = function(url, callback) {
30409 event = dispatch("beforesend", "progress", "load", "error"),
30412 xhr = new XMLHttpRequest,
30419 // If IE does not support CORS, use XDomainRequest.
30420 if (typeof XDomainRequest !== "undefined"
30421 && !("withCredentials" in xhr)
30422 && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest;
30425 ? xhr.onload = xhr.onerror = xhr.ontimeout = respond
30426 : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); };
30428 function respond(o) {
30429 var status = xhr.status, result;
30430 if (!status && hasResponse(xhr)
30431 || status >= 200 && status < 300
30432 || status === 304) {
30435 result = response.call(request, xhr);
30437 event.call("error", request, e);
30443 event.call("load", request, result);
30445 event.call("error", request, o);
30449 xhr.onprogress = function(e) {
30450 event.call("progress", request, e);
30454 header: function(name, value) {
30455 name = (name + "").toLowerCase();
30456 if (arguments.length < 2) return headers.get(name);
30457 if (value == null) headers.remove(name);
30458 else headers.set(name, value + "");
30462 // If mimeType is non-null and no Accept header is set, a default is used.
30463 mimeType: function(value) {
30464 if (!arguments.length) return mimeType;
30465 mimeType = value == null ? null : value + "";
30469 // Specifies what type the response value should take;
30470 // for instance, arraybuffer, blob, document, or text.
30471 responseType: function(value) {
30472 if (!arguments.length) return responseType;
30473 responseType = value;
30477 timeout: function(value) {
30478 if (!arguments.length) return timeout;
30483 user: function(value) {
30484 return arguments.length < 1 ? user : (user = value == null ? null : value + "", request);
30487 password: function(value) {
30488 return arguments.length < 1 ? password : (password = value == null ? null : value + "", request);
30491 // Specify how to convert the response content to a specific type;
30492 // changes the callback value on "load" events.
30493 response: function(value) {
30498 // Alias for send("GET", …).
30499 get: function(data, callback) {
30500 return request.send("GET", data, callback);
30503 // Alias for send("POST", …).
30504 post: function(data, callback) {
30505 return request.send("POST", data, callback);
30508 // If callback is non-null, it will be used for error and load events.
30509 send: function(method, data, callback) {
30510 xhr.open(method, url, true, user, password);
30511 if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*");
30512 if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); });
30513 if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType);
30514 if (responseType != null) xhr.responseType = responseType;
30515 if (timeout > 0) xhr.timeout = timeout;
30516 if (callback == null && typeof data === "function") callback = data, data = null;
30517 if (callback != null && callback.length === 1) callback = fixCallback(callback);
30518 if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); });
30519 event.call("beforesend", request, xhr);
30520 xhr.send(data == null ? null : data);
30524 abort: function() {
30530 var value = event.on.apply(event, arguments);
30531 return value === event ? request : value;
30535 if (callback != null) {
30536 if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
30537 return request.get(callback);
30543 function fixCallback(callback) {
30544 return function(error, xhr) {
30545 callback(error == null ? xhr : null);
30549 function hasResponse(xhr) {
30550 var type = xhr.responseType;
30551 return type && type !== "text"
30552 ? xhr.response // null on error
30553 : xhr.responseText; // "" on error
30556 var type$3 = function(defaultMimeType, response) {
30557 return function(url, callback) {
30558 var r = request(url).mimeType(defaultMimeType).response(response);
30559 if (callback != null) {
30560 if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
30561 return r.get(callback);
30567 var html = type$3("text/html", function(xhr) {
30568 return document.createRange().createContextualFragment(xhr.responseText);
30571 var json = type$3("application/json", function(xhr) {
30572 return JSON.parse(xhr.responseText);
30575 var text = type$3("text/plain", function(xhr) {
30576 return xhr.responseText;
30579 var xml = type$3("application/xml", function(xhr) {
30580 var xml = xhr.responseXML;
30581 if (!xml) throw new Error("parse error");
30585 var dsv$1 = function(defaultMimeType, parse) {
30586 return function(url, row, callback) {
30587 if (arguments.length < 3) callback = row, row = null;
30588 var r = request(url).mimeType(defaultMimeType);
30589 r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; };
30591 return callback ? r.get(callback) : r;
30595 function responseOf(parse, row) {
30596 return function(request$$1) {
30597 return parse(request$$1.responseText, row);
30601 var csv$1 = dsv$1("text/csv", csvParse);
30603 var tsv$1 = dsv$1("text/tab-separated-values", tsvParse);
30605 var array$2 = Array.prototype;
30607 var map$3 = array$2.map;
30608 var slice$4 = array$2.slice;
30610 var implicit = {name: "implicit"};
30612 function ordinal(range) {
30613 var index = map$1(),
30615 unknown = implicit;
30617 range = range == null ? [] : slice$4.call(range);
30619 function scale(d) {
30620 var key = d + "", i = index.get(key);
30622 if (unknown !== implicit) return unknown;
30623 index.set(key, i = domain.push(d));
30625 return range[(i - 1) % range.length];
30628 scale.domain = function(_) {
30629 if (!arguments.length) return domain.slice();
30630 domain = [], index = map$1();
30631 var i = -1, n = _.length, d, key;
30632 while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
30636 scale.range = function(_) {
30637 return arguments.length ? (range = slice$4.call(_), scale) : range.slice();
30640 scale.unknown = function(_) {
30641 return arguments.length ? (unknown = _, scale) : unknown;
30644 scale.copy = function() {
30655 var scale = ordinal().unknown(undefined),
30656 domain = scale.domain,
30657 ordinalRange = scale.range,
30666 delete scale.unknown;
30668 function rescale() {
30669 var n = domain().length,
30670 reverse = range$$1[1] < range$$1[0],
30671 start = range$$1[reverse - 0],
30672 stop = range$$1[1 - reverse];
30673 step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
30674 if (round) step = Math.floor(step);
30675 start += (stop - start - step * (n - paddingInner)) * align;
30676 bandwidth = step * (1 - paddingInner);
30677 if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
30678 var values = sequence(n).map(function(i) { return start + step * i; });
30679 return ordinalRange(reverse ? values.reverse() : values);
30682 scale.domain = function(_) {
30683 return arguments.length ? (domain(_), rescale()) : domain();
30686 scale.range = function(_) {
30687 return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice();
30690 scale.rangeRound = function(_) {
30691 return range$$1 = [+_[0], +_[1]], round = true, rescale();
30694 scale.bandwidth = function() {
30698 scale.step = function() {
30702 scale.round = function(_) {
30703 return arguments.length ? (round = !!_, rescale()) : round;
30706 scale.padding = function(_) {
30707 return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
30710 scale.paddingInner = function(_) {
30711 return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
30714 scale.paddingOuter = function(_) {
30715 return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter;
30718 scale.align = function(_) {
30719 return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
30722 scale.copy = function() {
30727 .paddingInner(paddingInner)
30728 .paddingOuter(paddingOuter)
30735 function pointish(scale) {
30736 var copy = scale.copy;
30738 scale.padding = scale.paddingOuter;
30739 delete scale.paddingInner;
30740 delete scale.paddingOuter;
30742 scale.copy = function() {
30743 return pointish(copy());
30749 function point$1() {
30750 return pointish(band().paddingInner(1));
30753 var constant$9 = function(x) {
30754 return function() {
30759 var number$1 = function(x) {
30765 function deinterpolateLinear(a, b) {
30766 return (b -= (a = +a))
30767 ? function(x) { return (x - a) / b; }
30771 function deinterpolateClamp(deinterpolate) {
30772 return function(a, b) {
30773 var d = deinterpolate(a = +a, b = +b);
30774 return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
30778 function reinterpolateClamp(reinterpolate) {
30779 return function(a, b) {
30780 var r = reinterpolate(a = +a, b = +b);
30781 return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
30785 function bimap(domain, range$$1, deinterpolate, reinterpolate) {
30786 var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1];
30787 if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
30788 else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
30789 return function(x) { return r0(d0(x)); };
30792 function polymap(domain, range$$1, deinterpolate, reinterpolate) {
30793 var j = Math.min(domain.length, range$$1.length) - 1,
30798 // Reverse descending domains.
30799 if (domain[j] < domain[0]) {
30800 domain = domain.slice().reverse();
30801 range$$1 = range$$1.slice().reverse();
30805 d[i] = deinterpolate(domain[i], domain[i + 1]);
30806 r[i] = reinterpolate(range$$1[i], range$$1[i + 1]);
30809 return function(x) {
30810 var i = bisectRight(domain, x, 1, j) - 1;
30811 return r[i](d[i](x));
30815 function copy(source, target) {
30817 .domain(source.domain())
30818 .range(source.range())
30819 .interpolate(source.interpolate())
30820 .clamp(source.clamp());
30823 // deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
30824 // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
30825 function continuous(deinterpolate, reinterpolate) {
30828 interpolate$$1 = interpolateValue,
30834 function rescale() {
30835 piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap;
30836 output = input = null;
30840 function scale(x) {
30841 return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x);
30844 scale.invert = function(y) {
30845 return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y);
30848 scale.domain = function(_) {
30849 return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice();
30852 scale.range = function(_) {
30853 return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice();
30856 scale.rangeRound = function(_) {
30857 return range$$1 = slice$4.call(_), interpolate$$1 = interpolateRound, rescale();
30860 scale.clamp = function(_) {
30861 return arguments.length ? (clamp = !!_, rescale()) : clamp;
30864 scale.interpolate = function(_) {
30865 return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1;
30871 var tickFormat = function(domain, count, specifier) {
30872 var start = domain[0],
30873 stop = domain[domain.length - 1],
30874 step = tickStep(start, stop, count == null ? 10 : count),
30876 specifier = formatSpecifier(specifier == null ? ",f" : specifier);
30877 switch (specifier.type) {
30879 var value = Math.max(Math.abs(start), Math.abs(stop));
30880 if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
30881 return formatPrefix(specifier, value);
30888 if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
30893 if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
30897 return format(specifier);
30900 function linearish(scale) {
30901 var domain = scale.domain;
30903 scale.ticks = function(count) {
30905 return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
30908 scale.tickFormat = function(count, specifier) {
30909 return tickFormat(domain(), count, specifier);
30912 scale.nice = function(count) {
30915 n = count == null ? 10 : count,
30918 step = tickStep(start, stop, n);
30921 step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n);
30922 d[0] = Math.floor(start / step) * step;
30923 d[i] = Math.ceil(stop / step) * step;
30933 function linear$2() {
30934 var scale = continuous(deinterpolateLinear, reinterpolate);
30936 scale.copy = function() {
30937 return copy(scale, linear$2());
30940 return linearish(scale);
30943 function identity$6() {
30944 var domain = [0, 1];
30946 function scale(x) {
30950 scale.invert = scale;
30952 scale.domain = scale.range = function(_) {
30953 return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice();
30956 scale.copy = function() {
30957 return identity$6().domain(domain);
30960 return linearish(scale);
30963 var nice = function(domain, interval) {
30964 domain = domain.slice();
30967 i1 = domain.length - 1,
30973 t = i0, i0 = i1, i1 = t;
30974 t = x0, x0 = x1, x1 = t;
30977 domain[i0] = interval.floor(x0);
30978 domain[i1] = interval.ceil(x1);
30982 function deinterpolate(a, b) {
30983 return (b = Math.log(b / a))
30984 ? function(x) { return Math.log(x / a) / b; }
30988 function reinterpolate$1(a, b) {
30990 ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
30991 : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
30994 function pow10(x) {
30995 return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
30998 function powp(base) {
30999 return base === 10 ? pow10
31000 : base === Math.E ? Math.exp
31001 : function(x) { return Math.pow(base, x); };
31004 function logp(base) {
31005 return base === Math.E ? Math.log
31006 : base === 10 && Math.log10
31007 || base === 2 && Math.log2
31008 || (base = Math.log(base), function(x) { return Math.log(x) / base; });
31011 function reflect(f) {
31012 return function(x) {
31018 var scale = continuous(deinterpolate, reinterpolate$1).domain([1, 10]),
31019 domain = scale.domain,
31024 function rescale() {
31025 logs = logp(base), pows = powp(base);
31026 if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
31030 scale.base = function(_) {
31031 return arguments.length ? (base = +_, rescale()) : base;
31034 scale.domain = function(_) {
31035 return arguments.length ? (domain(_), rescale()) : domain();
31038 scale.ticks = function(count) {
31041 v = d[d.length - 1],
31044 if (r = v < u) i = u, u = v, v = i;
31051 n = count == null ? 10 : +count,
31054 if (!(base % 1) && j - i < n) {
31055 i = Math.round(i) - 1, j = Math.round(j) + 1;
31056 if (u > 0) for (; i < j; ++i) {
31057 for (k = 1, p = pows(i); k < base; ++k) {
31059 if (t < u) continue;
31063 } else for (; i < j; ++i) {
31064 for (k = base - 1, p = pows(i); k >= 1; --k) {
31066 if (t < u) continue;
31072 z = ticks(i, j, Math.min(j - i, n)).map(pows);
31075 return r ? z.reverse() : z;
31078 scale.tickFormat = function(count, specifier) {
31079 if (specifier == null) specifier = base === 10 ? ".0e" : ",";
31080 if (typeof specifier !== "function") specifier = format(specifier);
31081 if (count === Infinity) return specifier;
31082 if (count == null) count = 10;
31083 var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
31084 return function(d) {
31085 var i = d / pows(Math.round(logs(d)));
31086 if (i * base < base - 0.5) i *= base;
31087 return i <= k ? specifier(d) : "";
31091 scale.nice = function() {
31092 return domain(nice(domain(), {
31093 floor: function(x) { return pows(Math.floor(logs(x))); },
31094 ceil: function(x) { return pows(Math.ceil(logs(x))); }
31098 scale.copy = function() {
31099 return copy(scale, log$1().base(base));
31105 function raise$1(x, exponent) {
31106 return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
31111 scale = continuous(deinterpolate, reinterpolate),
31112 domain = scale.domain;
31114 function deinterpolate(a, b) {
31115 return (b = raise$1(b, exponent) - (a = raise$1(a, exponent)))
31116 ? function(x) { return (raise$1(x, exponent) - a) / b; }
31120 function reinterpolate(a, b) {
31121 b = raise$1(b, exponent) - (a = raise$1(a, exponent));
31122 return function(t) { return raise$1(a + b * t, 1 / exponent); };
31125 scale.exponent = function(_) {
31126 return arguments.length ? (exponent = +_, domain(domain())) : exponent;
31129 scale.copy = function() {
31130 return copy(scale, pow$1().exponent(exponent));
31133 return linearish(scale);
31136 function sqrt$1() {
31137 return pow$1().exponent(0.5);
31140 function quantile$$1() {
31145 function rescale() {
31146 var i = 0, n = Math.max(1, range$$1.length);
31147 thresholds = new Array(n - 1);
31148 while (++i < n) thresholds[i - 1] = threshold(domain, i / n);
31152 function scale(x) {
31153 if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)];
31156 scale.invertExtent = function(y) {
31157 var i = range$$1.indexOf(y);
31158 return i < 0 ? [NaN, NaN] : [
31159 i > 0 ? thresholds[i - 1] : domain[0],
31160 i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
31164 scale.domain = function(_) {
31165 if (!arguments.length) return domain.slice();
31167 for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
31168 domain.sort(ascending);
31172 scale.range = function(_) {
31173 return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice();
31176 scale.quantiles = function() {
31177 return thresholds.slice();
31180 scale.copy = function() {
31181 return quantile$$1()
31189 function quantize$1() {
31196 function scale(x) {
31197 if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
31200 function rescale() {
31202 domain = new Array(n);
31203 while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
31207 scale.domain = function(_) {
31208 return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
31211 scale.range = function(_) {
31212 return arguments.length ? (n = (range$$1 = slice$4.call(_)).length - 1, rescale()) : range$$1.slice();
31215 scale.invertExtent = function(y) {
31216 var i = range$$1.indexOf(y);
31217 return i < 0 ? [NaN, NaN]
31218 : i < 1 ? [x0, domain[0]]
31219 : i >= n ? [domain[n - 1], x1]
31220 : [domain[i - 1], domain[i]];
31223 scale.copy = function() {
31224 return quantize$1()
31229 return linearish(scale);
31232 function threshold$1() {
31233 var domain = [0.5],
31237 function scale(x) {
31238 if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
31241 scale.domain = function(_) {
31242 return arguments.length ? (domain = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice();
31245 scale.range = function(_) {
31246 return arguments.length ? (range$$1 = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice();
31249 scale.invertExtent = function(y) {
31250 var i = range$$1.indexOf(y);
31251 return [domain[i - 1], domain[i]];
31254 scale.copy = function() {
31255 return threshold$1()
31263 var t0$1 = new Date;
31264 var t1$1 = new Date;
31266 function newInterval(floori, offseti, count, field) {
31268 function interval(date) {
31269 return floori(date = new Date(+date)), date;
31272 interval.floor = interval;
31274 interval.ceil = function(date) {
31275 return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
31278 interval.round = function(date) {
31279 var d0 = interval(date),
31280 d1 = interval.ceil(date);
31281 return date - d0 < d1 - date ? d0 : d1;
31284 interval.offset = function(date, step) {
31285 return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
31288 interval.range = function(start, stop, step) {
31290 start = interval.ceil(start);
31291 step = step == null ? 1 : Math.floor(step);
31292 if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
31293 do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop)
31297 interval.filter = function(test) {
31298 return newInterval(function(date) {
31299 if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
31300 }, function(date, step) {
31301 if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty
31306 interval.count = function(start, end) {
31307 t0$1.setTime(+start), t1$1.setTime(+end);
31308 floori(t0$1), floori(t1$1);
31309 return Math.floor(count(t0$1, t1$1));
31312 interval.every = function(step) {
31313 step = Math.floor(step);
31314 return !isFinite(step) || !(step > 0) ? null
31315 : !(step > 1) ? interval
31316 : interval.filter(field
31317 ? function(d) { return field(d) % step === 0; }
31318 : function(d) { return interval.count(0, d) % step === 0; });
31325 var millisecond = newInterval(function() {
31327 }, function(date, step) {
31328 date.setTime(+date + step);
31329 }, function(start, end) {
31330 return end - start;
31333 // An optimized implementation for this simple case.
31334 millisecond.every = function(k) {
31336 if (!isFinite(k) || !(k > 0)) return null;
31337 if (!(k > 1)) return millisecond;
31338 return newInterval(function(date) {
31339 date.setTime(Math.floor(date / k) * k);
31340 }, function(date, step) {
31341 date.setTime(+date + step * k);
31342 }, function(start, end) {
31343 return (end - start) / k;
31347 var milliseconds = millisecond.range;
31349 var durationSecond$1 = 1e3;
31350 var durationMinute$1 = 6e4;
31351 var durationHour$1 = 36e5;
31352 var durationDay$1 = 864e5;
31353 var durationWeek$1 = 6048e5;
31355 var second = newInterval(function(date) {
31356 date.setTime(Math.floor(date / durationSecond$1) * durationSecond$1);
31357 }, function(date, step) {
31358 date.setTime(+date + step * durationSecond$1);
31359 }, function(start, end) {
31360 return (end - start) / durationSecond$1;
31361 }, function(date) {
31362 return date.getUTCSeconds();
31365 var seconds = second.range;
31367 var minute = newInterval(function(date) {
31368 date.setTime(Math.floor(date / durationMinute$1) * durationMinute$1);
31369 }, function(date, step) {
31370 date.setTime(+date + step * durationMinute$1);
31371 }, function(start, end) {
31372 return (end - start) / durationMinute$1;
31373 }, function(date) {
31374 return date.getMinutes();
31377 var minutes = minute.range;
31379 var hour = newInterval(function(date) {
31380 var offset = date.getTimezoneOffset() * durationMinute$1 % durationHour$1;
31381 if (offset < 0) offset += durationHour$1;
31382 date.setTime(Math.floor((+date - offset) / durationHour$1) * durationHour$1 + offset);
31383 }, function(date, step) {
31384 date.setTime(+date + step * durationHour$1);
31385 }, function(start, end) {
31386 return (end - start) / durationHour$1;
31387 }, function(date) {
31388 return date.getHours();
31391 var hours = hour.range;
31393 var day = newInterval(function(date) {
31394 date.setHours(0, 0, 0, 0);
31395 }, function(date, step) {
31396 date.setDate(date.getDate() + step);
31397 }, function(start, end) {
31398 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationDay$1;
31399 }, function(date) {
31400 return date.getDate() - 1;
31403 var days = day.range;
31405 function weekday(i) {
31406 return newInterval(function(date) {
31407 date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
31408 date.setHours(0, 0, 0, 0);
31409 }, function(date, step) {
31410 date.setDate(date.getDate() + step * 7);
31411 }, function(start, end) {
31412 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationWeek$1;
31416 var sunday = weekday(0);
31417 var monday = weekday(1);
31418 var tuesday = weekday(2);
31419 var wednesday = weekday(3);
31420 var thursday = weekday(4);
31421 var friday = weekday(5);
31422 var saturday = weekday(6);
31424 var sundays = sunday.range;
31425 var mondays = monday.range;
31426 var tuesdays = tuesday.range;
31427 var wednesdays = wednesday.range;
31428 var thursdays = thursday.range;
31429 var fridays = friday.range;
31430 var saturdays = saturday.range;
31432 var month = newInterval(function(date) {
31434 date.setHours(0, 0, 0, 0);
31435 }, function(date, step) {
31436 date.setMonth(date.getMonth() + step);
31437 }, function(start, end) {
31438 return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
31439 }, function(date) {
31440 return date.getMonth();
31443 var months = month.range;
31445 var year = newInterval(function(date) {
31446 date.setMonth(0, 1);
31447 date.setHours(0, 0, 0, 0);
31448 }, function(date, step) {
31449 date.setFullYear(date.getFullYear() + step);
31450 }, function(start, end) {
31451 return end.getFullYear() - start.getFullYear();
31452 }, function(date) {
31453 return date.getFullYear();
31456 // An optimized implementation for this simple case.
31457 year.every = function(k) {
31458 return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
31459 date.setFullYear(Math.floor(date.getFullYear() / k) * k);
31460 date.setMonth(0, 1);
31461 date.setHours(0, 0, 0, 0);
31462 }, function(date, step) {
31463 date.setFullYear(date.getFullYear() + step * k);
31467 var years = year.range;
31469 var utcMinute = newInterval(function(date) {
31470 date.setUTCSeconds(0, 0);
31471 }, function(date, step) {
31472 date.setTime(+date + step * durationMinute$1);
31473 }, function(start, end) {
31474 return (end - start) / durationMinute$1;
31475 }, function(date) {
31476 return date.getUTCMinutes();
31479 var utcMinutes = utcMinute.range;
31481 var utcHour = newInterval(function(date) {
31482 date.setUTCMinutes(0, 0, 0);
31483 }, function(date, step) {
31484 date.setTime(+date + step * durationHour$1);
31485 }, function(start, end) {
31486 return (end - start) / durationHour$1;
31487 }, function(date) {
31488 return date.getUTCHours();
31491 var utcHours = utcHour.range;
31493 var utcDay = newInterval(function(date) {
31494 date.setUTCHours(0, 0, 0, 0);
31495 }, function(date, step) {
31496 date.setUTCDate(date.getUTCDate() + step);
31497 }, function(start, end) {
31498 return (end - start) / durationDay$1;
31499 }, function(date) {
31500 return date.getUTCDate() - 1;
31503 var utcDays = utcDay.range;
31505 function utcWeekday(i) {
31506 return newInterval(function(date) {
31507 date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
31508 date.setUTCHours(0, 0, 0, 0);
31509 }, function(date, step) {
31510 date.setUTCDate(date.getUTCDate() + step * 7);
31511 }, function(start, end) {
31512 return (end - start) / durationWeek$1;
31516 var utcSunday = utcWeekday(0);
31517 var utcMonday = utcWeekday(1);
31518 var utcTuesday = utcWeekday(2);
31519 var utcWednesday = utcWeekday(3);
31520 var utcThursday = utcWeekday(4);
31521 var utcFriday = utcWeekday(5);
31522 var utcSaturday = utcWeekday(6);
31524 var utcSundays = utcSunday.range;
31525 var utcMondays = utcMonday.range;
31526 var utcTuesdays = utcTuesday.range;
31527 var utcWednesdays = utcWednesday.range;
31528 var utcThursdays = utcThursday.range;
31529 var utcFridays = utcFriday.range;
31530 var utcSaturdays = utcSaturday.range;
31532 var utcMonth = newInterval(function(date) {
31533 date.setUTCDate(1);
31534 date.setUTCHours(0, 0, 0, 0);
31535 }, function(date, step) {
31536 date.setUTCMonth(date.getUTCMonth() + step);
31537 }, function(start, end) {
31538 return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
31539 }, function(date) {
31540 return date.getUTCMonth();
31543 var utcMonths = utcMonth.range;
31545 var utcYear = newInterval(function(date) {
31546 date.setUTCMonth(0, 1);
31547 date.setUTCHours(0, 0, 0, 0);
31548 }, function(date, step) {
31549 date.setUTCFullYear(date.getUTCFullYear() + step);
31550 }, function(start, end) {
31551 return end.getUTCFullYear() - start.getUTCFullYear();
31552 }, function(date) {
31553 return date.getUTCFullYear();
31556 // An optimized implementation for this simple case.
31557 utcYear.every = function(k) {
31558 return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
31559 date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
31560 date.setUTCMonth(0, 1);
31561 date.setUTCHours(0, 0, 0, 0);
31562 }, function(date, step) {
31563 date.setUTCFullYear(date.getUTCFullYear() + step * k);
31567 var utcYears = utcYear.range;
31569 function localDate(d) {
31570 if (0 <= d.y && d.y < 100) {
31571 var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
31572 date.setFullYear(d.y);
31575 return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
31578 function utcDate(d) {
31579 if (0 <= d.y && d.y < 100) {
31580 var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
31581 date.setUTCFullYear(d.y);
31584 return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
31587 function newYear(y) {
31588 return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
31591 function formatLocale$1(locale) {
31592 var locale_dateTime = locale.dateTime,
31593 locale_date = locale.date,
31594 locale_time = locale.time,
31595 locale_periods = locale.periods,
31596 locale_weekdays = locale.days,
31597 locale_shortWeekdays = locale.shortDays,
31598 locale_months = locale.months,
31599 locale_shortMonths = locale.shortMonths;
31601 var periodRe = formatRe(locale_periods),
31602 periodLookup = formatLookup(locale_periods),
31603 weekdayRe = formatRe(locale_weekdays),
31604 weekdayLookup = formatLookup(locale_weekdays),
31605 shortWeekdayRe = formatRe(locale_shortWeekdays),
31606 shortWeekdayLookup = formatLookup(locale_shortWeekdays),
31607 monthRe = formatRe(locale_months),
31608 monthLookup = formatLookup(locale_months),
31609 shortMonthRe = formatRe(locale_shortMonths),
31610 shortMonthLookup = formatLookup(locale_shortMonths);
31613 "a": formatShortWeekday,
31614 "A": formatWeekday,
31615 "b": formatShortMonth,
31618 "d": formatDayOfMonth,
31619 "e": formatDayOfMonth,
31622 "j": formatDayOfYear,
31623 "L": formatMilliseconds,
31624 "m": formatMonthNumber,
31625 "M": formatMinutes,
31627 "S": formatSeconds,
31628 "U": formatWeekNumberSunday,
31629 "w": formatWeekdayNumber,
31630 "W": formatWeekNumberMonday,
31634 "Y": formatFullYear,
31636 "%": formatLiteralPercent
31640 "a": formatUTCShortWeekday,
31641 "A": formatUTCWeekday,
31642 "b": formatUTCShortMonth,
31643 "B": formatUTCMonth,
31645 "d": formatUTCDayOfMonth,
31646 "e": formatUTCDayOfMonth,
31647 "H": formatUTCHour24,
31648 "I": formatUTCHour12,
31649 "j": formatUTCDayOfYear,
31650 "L": formatUTCMilliseconds,
31651 "m": formatUTCMonthNumber,
31652 "M": formatUTCMinutes,
31653 "p": formatUTCPeriod,
31654 "S": formatUTCSeconds,
31655 "U": formatUTCWeekNumberSunday,
31656 "w": formatUTCWeekdayNumber,
31657 "W": formatUTCWeekNumberMonday,
31660 "y": formatUTCYear,
31661 "Y": formatUTCFullYear,
31662 "Z": formatUTCZone,
31663 "%": formatLiteralPercent
31667 "a": parseShortWeekday,
31669 "b": parseShortMonth,
31671 "c": parseLocaleDateTime,
31672 "d": parseDayOfMonth,
31673 "e": parseDayOfMonth,
31676 "j": parseDayOfYear,
31677 "L": parseMilliseconds,
31678 "m": parseMonthNumber,
31682 "U": parseWeekNumberSunday,
31683 "w": parseWeekdayNumber,
31684 "W": parseWeekNumberMonday,
31685 "x": parseLocaleDate,
31686 "X": parseLocaleTime,
31688 "Y": parseFullYear,
31690 "%": parseLiteralPercent
31693 // These recursive directive definitions must be deferred.
31694 formats.x = newFormat(locale_date, formats);
31695 formats.X = newFormat(locale_time, formats);
31696 formats.c = newFormat(locale_dateTime, formats);
31697 utcFormats.x = newFormat(locale_date, utcFormats);
31698 utcFormats.X = newFormat(locale_time, utcFormats);
31699 utcFormats.c = newFormat(locale_dateTime, utcFormats);
31701 function newFormat(specifier, formats) {
31702 return function(date) {
31706 n = specifier.length,
31711 if (!(date instanceof Date)) date = new Date(+date);
31714 if (specifier.charCodeAt(i) === 37) {
31715 string.push(specifier.slice(j, i));
31716 if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
31717 else pad = c === "e" ? " " : "0";
31718 if (format = formats[c]) c = format(date, pad);
31724 string.push(specifier.slice(j, i));
31725 return string.join("");
31729 function newParse(specifier, newDate) {
31730 return function(string) {
31731 var d = newYear(1900),
31732 i = parseSpecifier(d, specifier, string += "", 0);
31733 if (i != string.length) return null;
31735 // The am-pm flag is 0 for AM, and 1 for PM.
31736 if ("p" in d) d.H = d.H % 12 + d.p * 12;
31738 // Convert day-of-week and week-of-year to day-of-year.
31739 if ("W" in d || "U" in d) {
31740 if (!("w" in d)) d.w = "W" in d ? 1 : 0;
31741 var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
31743 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;
31746 // If a time zone is specified, all fields are interpreted as UTC and then
31747 // offset according to the specified time zone.
31749 d.H += d.Z / 100 | 0;
31754 // Otherwise, all fields are in local time.
31759 function parseSpecifier(d, specifier, string, j) {
31761 n = specifier.length,
31767 if (j >= m) return -1;
31768 c = specifier.charCodeAt(i++);
31770 c = specifier.charAt(i++);
31771 parse = parses[c in pads ? specifier.charAt(i++) : c];
31772 if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
31773 } else if (c != string.charCodeAt(j++)) {
31781 function parsePeriod(d, string, i) {
31782 var n = periodRe.exec(string.slice(i));
31783 return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31786 function parseShortWeekday(d, string, i) {
31787 var n = shortWeekdayRe.exec(string.slice(i));
31788 return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31791 function parseWeekday(d, string, i) {
31792 var n = weekdayRe.exec(string.slice(i));
31793 return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31796 function parseShortMonth(d, string, i) {
31797 var n = shortMonthRe.exec(string.slice(i));
31798 return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31801 function parseMonth(d, string, i) {
31802 var n = monthRe.exec(string.slice(i));
31803 return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31806 function parseLocaleDateTime(d, string, i) {
31807 return parseSpecifier(d, locale_dateTime, string, i);
31810 function parseLocaleDate(d, string, i) {
31811 return parseSpecifier(d, locale_date, string, i);
31814 function parseLocaleTime(d, string, i) {
31815 return parseSpecifier(d, locale_time, string, i);
31818 function formatShortWeekday(d) {
31819 return locale_shortWeekdays[d.getDay()];
31822 function formatWeekday(d) {
31823 return locale_weekdays[d.getDay()];
31826 function formatShortMonth(d) {
31827 return locale_shortMonths[d.getMonth()];
31830 function formatMonth(d) {
31831 return locale_months[d.getMonth()];
31834 function formatPeriod(d) {
31835 return locale_periods[+(d.getHours() >= 12)];
31838 function formatUTCShortWeekday(d) {
31839 return locale_shortWeekdays[d.getUTCDay()];
31842 function formatUTCWeekday(d) {
31843 return locale_weekdays[d.getUTCDay()];
31846 function formatUTCShortMonth(d) {
31847 return locale_shortMonths[d.getUTCMonth()];
31850 function formatUTCMonth(d) {
31851 return locale_months[d.getUTCMonth()];
31854 function formatUTCPeriod(d) {
31855 return locale_periods[+(d.getUTCHours() >= 12)];
31859 format: function(specifier) {
31860 var f = newFormat(specifier += "", formats);
31861 f.toString = function() { return specifier; };
31864 parse: function(specifier) {
31865 var p = newParse(specifier += "", localDate);
31866 p.toString = function() { return specifier; };
31869 utcFormat: function(specifier) {
31870 var f = newFormat(specifier += "", utcFormats);
31871 f.toString = function() { return specifier; };
31874 utcParse: function(specifier) {
31875 var p = newParse(specifier, utcDate);
31876 p.toString = function() { return specifier; };
31882 var pads = {"-": "", "_": " ", "0": "0"};
31883 var numberRe = /^\s*\d+/;
31884 var percentRe = /^%/;
31885 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
31887 function pad(value, fill, width) {
31888 var sign = value < 0 ? "-" : "",
31889 string = (sign ? -value : value) + "",
31890 length = string.length;
31891 return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
31894 function requote(s) {
31895 return s.replace(requoteRe, "\\$&");
31898 function formatRe(names) {
31899 return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
31902 function formatLookup(names) {
31903 var map = {}, i = -1, n = names.length;
31904 while (++i < n) map[names[i].toLowerCase()] = i;
31908 function parseWeekdayNumber(d, string, i) {
31909 var n = numberRe.exec(string.slice(i, i + 1));
31910 return n ? (d.w = +n[0], i + n[0].length) : -1;
31913 function parseWeekNumberSunday(d, string, i) {
31914 var n = numberRe.exec(string.slice(i));
31915 return n ? (d.U = +n[0], i + n[0].length) : -1;
31918 function parseWeekNumberMonday(d, string, i) {
31919 var n = numberRe.exec(string.slice(i));
31920 return n ? (d.W = +n[0], i + n[0].length) : -1;
31923 function parseFullYear(d, string, i) {
31924 var n = numberRe.exec(string.slice(i, i + 4));
31925 return n ? (d.y = +n[0], i + n[0].length) : -1;
31928 function parseYear(d, string, i) {
31929 var n = numberRe.exec(string.slice(i, i + 2));
31930 return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
31933 function parseZone(d, string, i) {
31934 var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
31935 return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
31938 function parseMonthNumber(d, string, i) {
31939 var n = numberRe.exec(string.slice(i, i + 2));
31940 return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
31943 function parseDayOfMonth(d, string, i) {
31944 var n = numberRe.exec(string.slice(i, i + 2));
31945 return n ? (d.d = +n[0], i + n[0].length) : -1;
31948 function parseDayOfYear(d, string, i) {
31949 var n = numberRe.exec(string.slice(i, i + 3));
31950 return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
31953 function parseHour24(d, string, i) {
31954 var n = numberRe.exec(string.slice(i, i + 2));
31955 return n ? (d.H = +n[0], i + n[0].length) : -1;
31958 function parseMinutes(d, string, i) {
31959 var n = numberRe.exec(string.slice(i, i + 2));
31960 return n ? (d.M = +n[0], i + n[0].length) : -1;
31963 function parseSeconds(d, string, i) {
31964 var n = numberRe.exec(string.slice(i, i + 2));
31965 return n ? (d.S = +n[0], i + n[0].length) : -1;
31968 function parseMilliseconds(d, string, i) {
31969 var n = numberRe.exec(string.slice(i, i + 3));
31970 return n ? (d.L = +n[0], i + n[0].length) : -1;
31973 function parseLiteralPercent(d, string, i) {
31974 var n = percentRe.exec(string.slice(i, i + 1));
31975 return n ? i + n[0].length : -1;
31978 function formatDayOfMonth(d, p) {
31979 return pad(d.getDate(), p, 2);
31982 function formatHour24(d, p) {
31983 return pad(d.getHours(), p, 2);
31986 function formatHour12(d, p) {
31987 return pad(d.getHours() % 12 || 12, p, 2);
31990 function formatDayOfYear(d, p) {
31991 return pad(1 + day.count(year(d), d), p, 3);
31994 function formatMilliseconds(d, p) {
31995 return pad(d.getMilliseconds(), p, 3);
31998 function formatMonthNumber(d, p) {
31999 return pad(d.getMonth() + 1, p, 2);
32002 function formatMinutes(d, p) {
32003 return pad(d.getMinutes(), p, 2);
32006 function formatSeconds(d, p) {
32007 return pad(d.getSeconds(), p, 2);
32010 function formatWeekNumberSunday(d, p) {
32011 return pad(sunday.count(year(d), d), p, 2);
32014 function formatWeekdayNumber(d) {
32018 function formatWeekNumberMonday(d, p) {
32019 return pad(monday.count(year(d), d), p, 2);
32022 function formatYear(d, p) {
32023 return pad(d.getFullYear() % 100, p, 2);
32026 function formatFullYear(d, p) {
32027 return pad(d.getFullYear() % 10000, p, 4);
32030 function formatZone(d) {
32031 var z = d.getTimezoneOffset();
32032 return (z > 0 ? "-" : (z *= -1, "+"))
32033 + pad(z / 60 | 0, "0", 2)
32034 + pad(z % 60, "0", 2);
32037 function formatUTCDayOfMonth(d, p) {
32038 return pad(d.getUTCDate(), p, 2);
32041 function formatUTCHour24(d, p) {
32042 return pad(d.getUTCHours(), p, 2);
32045 function formatUTCHour12(d, p) {
32046 return pad(d.getUTCHours() % 12 || 12, p, 2);
32049 function formatUTCDayOfYear(d, p) {
32050 return pad(1 + utcDay.count(utcYear(d), d), p, 3);
32053 function formatUTCMilliseconds(d, p) {
32054 return pad(d.getUTCMilliseconds(), p, 3);
32057 function formatUTCMonthNumber(d, p) {
32058 return pad(d.getUTCMonth() + 1, p, 2);
32061 function formatUTCMinutes(d, p) {
32062 return pad(d.getUTCMinutes(), p, 2);
32065 function formatUTCSeconds(d, p) {
32066 return pad(d.getUTCSeconds(), p, 2);
32069 function formatUTCWeekNumberSunday(d, p) {
32070 return pad(utcSunday.count(utcYear(d), d), p, 2);
32073 function formatUTCWeekdayNumber(d) {
32074 return d.getUTCDay();
32077 function formatUTCWeekNumberMonday(d, p) {
32078 return pad(utcMonday.count(utcYear(d), d), p, 2);
32081 function formatUTCYear(d, p) {
32082 return pad(d.getUTCFullYear() % 100, p, 2);
32085 function formatUTCFullYear(d, p) {
32086 return pad(d.getUTCFullYear() % 10000, p, 4);
32089 function formatUTCZone() {
32093 function formatLiteralPercent() {
32104 dateTime: "%x, %X",
32105 date: "%-m/%-d/%Y",
32106 time: "%-I:%M:%S %p",
32107 periods: ["AM", "PM"],
32108 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
32109 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
32110 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
32111 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
32114 function defaultLocale$1(definition) {
32115 locale$2 = formatLocale$1(definition);
32116 timeFormat = locale$2.format;
32117 timeParse = locale$2.parse;
32118 utcFormat = locale$2.utcFormat;
32119 utcParse = locale$2.utcParse;
32123 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
32125 function formatIsoNative(date) {
32126 return date.toISOString();
32129 var formatIso = Date.prototype.toISOString
32131 : utcFormat(isoSpecifier);
32133 function parseIsoNative(string) {
32134 var date = new Date(string);
32135 return isNaN(date) ? null : date;
32138 var parseIso = +new Date("2000-01-01T00:00:00.000Z")
32140 : utcParse(isoSpecifier);
32142 var durationSecond = 1000;
32143 var durationMinute = durationSecond * 60;
32144 var durationHour = durationMinute * 60;
32145 var durationDay = durationHour * 24;
32146 var durationWeek = durationDay * 7;
32147 var durationMonth = durationDay * 30;
32148 var durationYear = durationDay * 365;
32150 function date$1(t) {
32151 return new Date(t);
32154 function number$2(t) {
32155 return t instanceof Date ? +t : +new Date(+t);
32158 function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) {
32159 var scale = continuous(deinterpolateLinear, reinterpolate),
32160 invert = scale.invert,
32161 domain = scale.domain;
32163 var formatMillisecond = format(".%L"),
32164 formatSecond = format(":%S"),
32165 formatMinute = format("%I:%M"),
32166 formatHour = format("%I %p"),
32167 formatDay = format("%a %d"),
32168 formatWeek = format("%b %d"),
32169 formatMonth = format("%B"),
32170 formatYear = format("%Y");
32172 var tickIntervals = [
32173 [second$$1, 1, durationSecond],
32174 [second$$1, 5, 5 * durationSecond],
32175 [second$$1, 15, 15 * durationSecond],
32176 [second$$1, 30, 30 * durationSecond],
32177 [minute$$1, 1, durationMinute],
32178 [minute$$1, 5, 5 * durationMinute],
32179 [minute$$1, 15, 15 * durationMinute],
32180 [minute$$1, 30, 30 * durationMinute],
32181 [ hour$$1, 1, durationHour ],
32182 [ hour$$1, 3, 3 * durationHour ],
32183 [ hour$$1, 6, 6 * durationHour ],
32184 [ hour$$1, 12, 12 * durationHour ],
32185 [ day$$1, 1, durationDay ],
32186 [ day$$1, 2, 2 * durationDay ],
32187 [ week, 1, durationWeek ],
32188 [ month$$1, 1, durationMonth ],
32189 [ month$$1, 3, 3 * durationMonth ],
32190 [ year$$1, 1, durationYear ]
32193 function tickFormat(date) {
32194 return (second$$1(date) < date ? formatMillisecond
32195 : minute$$1(date) < date ? formatSecond
32196 : hour$$1(date) < date ? formatMinute
32197 : day$$1(date) < date ? formatHour
32198 : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek)
32199 : year$$1(date) < date ? formatMonth
32200 : formatYear)(date);
32203 function tickInterval(interval, start, stop, step) {
32204 if (interval == null) interval = 10;
32206 // If a desired tick count is specified, pick a reasonable tick interval
32207 // based on the extent of the domain and a rough estimate of tick size.
32208 // Otherwise, assume interval is already a time interval and use it.
32209 if (typeof interval === "number") {
32210 var target = Math.abs(stop - start) / interval,
32211 i = bisector(function(i) { return i[2]; }).right(tickIntervals, target);
32212 if (i === tickIntervals.length) {
32213 step = tickStep(start / durationYear, stop / durationYear, interval);
32214 interval = year$$1;
32216 i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
32220 step = tickStep(start, stop, interval);
32221 interval = millisecond$$1;
32225 return step == null ? interval : interval.every(step);
32228 scale.invert = function(y) {
32229 return new Date(invert(y));
32232 scale.domain = function(_) {
32233 return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1);
32236 scale.ticks = function(interval, step) {
32239 t1 = d[d.length - 1],
32242 if (r) t = t0, t0 = t1, t1 = t;
32243 t = tickInterval(interval, t0, t1, step);
32244 t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
32245 return r ? t.reverse() : t;
32248 scale.tickFormat = function(count, specifier) {
32249 return specifier == null ? tickFormat : format(specifier);
32252 scale.nice = function(interval, step) {
32254 return (interval = tickInterval(interval, d[0], d[d.length - 1], step))
32255 ? domain(nice(d, interval))
32259 scale.copy = function() {
32260 return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format));
32266 var time = function() {
32267 return calendar(year, month, sunday, day, hour, minute, second, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]);
32270 var utcTime = function() {
32271 return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]);
32274 var colors = function(s) {
32275 return s.match(/.{6}/g).map(function(x) {
32280 var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf");
32282 var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6");
32284 var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9");
32286 var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5");
32288 var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0));
32290 var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
32292 var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
32294 var rainbow = cubehelix();
32296 var rainbow$1 = function(t) {
32297 if (t < 0 || t > 1) t -= Math.floor(t);
32298 var ts = Math.abs(t - 0.5);
32299 rainbow.h = 360 * t - 100;
32300 rainbow.s = 1.5 - 1.5 * ts;
32301 rainbow.l = 0.8 - 0.9 * ts;
32302 return rainbow + "";
32305 function ramp(range) {
32306 var n = range.length;
32307 return function(t) {
32308 return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];
32312 var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));
32314 var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf"));
32316 var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4"));
32318 var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));
32320 function sequential(interpolator) {
32325 function scale(x) {
32326 var t = (x - x0) / (x1 - x0);
32327 return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t);
32330 scale.domain = function(_) {
32331 return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1];
32334 scale.clamp = function(_) {
32335 return arguments.length ? (clamp = !!_, scale) : clamp;
32338 scale.interpolator = function(_) {
32339 return arguments.length ? (interpolator = _, scale) : interpolator;
32342 scale.copy = function() {
32343 return sequential(interpolator).domain([x0, x1]).clamp(clamp);
32346 return linearish(scale);
32349 var constant$10 = function(x) {
32350 return function constant() {
32355 var abs$1 = Math.abs;
32356 var atan2$1 = Math.atan2;
32357 var cos$2 = Math.cos;
32358 var max$2 = Math.max;
32359 var min$1 = Math.min;
32360 var sin$2 = Math.sin;
32361 var sqrt$2 = Math.sqrt;
32363 var epsilon$3 = 1e-12;
32364 var pi$4 = Math.PI;
32365 var halfPi$3 = pi$4 / 2;
32366 var tau$4 = 2 * pi$4;
32368 function acos$1(x) {
32369 return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x);
32372 function asin$1(x) {
32373 return x >= 1 ? halfPi$3 : x <= -1 ? -halfPi$3 : Math.asin(x);
32376 function arcInnerRadius(d) {
32377 return d.innerRadius;
32380 function arcOuterRadius(d) {
32381 return d.outerRadius;
32384 function arcStartAngle(d) {
32385 return d.startAngle;
32388 function arcEndAngle(d) {
32392 function arcPadAngle(d) {
32393 return d && d.padAngle; // Note: optional!
32396 function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
32397 var x10 = x1 - x0, y10 = y1 - y0,
32398 x32 = x3 - x2, y32 = y3 - y2,
32399 t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10);
32400 return [x0 + t * x10, y0 + t * y10];
32403 // Compute perpendicular offset line of length rc.
32404 // http://mathworld.wolfram.com/Circle-LineIntersection.html
32405 function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
32408 lo = (cw ? rc : -rc) / sqrt$2(x01 * x01 + y01 * y01),
32415 x00 = (x11 + x10) / 2,
32416 y00 = (y11 + y10) / 2,
32419 d2 = dx * dx + dy * dy,
32421 D = x11 * y10 - x10 * y11,
32422 d = (dy < 0 ? -1 : 1) * sqrt$2(max$2(0, r * r * d2 - D * D)),
32423 cx0 = (D * dy - dx * d) / d2,
32424 cy0 = (-D * dx - dy * d) / d2,
32425 cx1 = (D * dy + dx * d) / d2,
32426 cy1 = (-D * dx + dy * d) / d2,
32432 // Pick the closer of the two intersection points.
32433 // TODO Is there a faster way to determine which intersection to use?
32434 if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
32441 x11: cx0 * (r1 / r - 1),
32442 y11: cy0 * (r1 / r - 1)
32446 var arc = function() {
32447 var innerRadius = arcInnerRadius,
32448 outerRadius = arcOuterRadius,
32449 cornerRadius = constant$10(0),
32451 startAngle = arcStartAngle,
32452 endAngle = arcEndAngle,
32453 padAngle = arcPadAngle,
32459 r0 = +innerRadius.apply(this, arguments),
32460 r1 = +outerRadius.apply(this, arguments),
32461 a0 = startAngle.apply(this, arguments) - halfPi$3,
32462 a1 = endAngle.apply(this, arguments) - halfPi$3,
32463 da = abs$1(a1 - a0),
32466 if (!context) context = buffer = path();
32468 // Ensure that the outer radius is always larger than the inner radius.
32469 if (r1 < r0) r = r1, r1 = r0, r0 = r;
32472 if (!(r1 > epsilon$3)) context.moveTo(0, 0);
32474 // Or is it a circle or annulus?
32475 else if (da > tau$4 - epsilon$3) {
32476 context.moveTo(r1 * cos$2(a0), r1 * sin$2(a0));
32477 context.arc(0, 0, r1, a0, a1, !cw);
32478 if (r0 > epsilon$3) {
32479 context.moveTo(r0 * cos$2(a1), r0 * sin$2(a1));
32480 context.arc(0, 0, r0, a1, a0, cw);
32484 // Or is it a circular or annular sector?
32492 ap = padAngle.apply(this, arguments) / 2,
32493 rp = (ap > epsilon$3) && (padRadius ? +padRadius.apply(this, arguments) : sqrt$2(r0 * r0 + r1 * r1)),
32494 rc = min$1(abs$1(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
32500 // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
32501 if (rp > epsilon$3) {
32502 var p0 = asin$1(rp / r0 * sin$2(ap)),
32503 p1 = asin$1(rp / r1 * sin$2(ap));
32504 if ((da0 -= p0 * 2) > epsilon$3) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
32505 else da0 = 0, a00 = a10 = (a0 + a1) / 2;
32506 if ((da1 -= p1 * 2) > epsilon$3) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
32507 else da1 = 0, a01 = a11 = (a0 + a1) / 2;
32510 var x01 = r1 * cos$2(a01),
32511 y01 = r1 * sin$2(a01),
32512 x10 = r0 * cos$2(a10),
32513 y10 = r0 * sin$2(a10);
32515 // Apply rounded corners?
32516 if (rc > epsilon$3) {
32517 var x11 = r1 * cos$2(a11),
32518 y11 = r1 * sin$2(a11),
32519 x00 = r0 * cos$2(a00),
32520 y00 = r0 * sin$2(a00);
32522 // Restrict the corner radius according to the sector angle.
32524 var oc = da0 > epsilon$3 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10],
32529 kc = 1 / sin$2(acos$1((ax * bx + ay * by) / (sqrt$2(ax * ax + ay * ay) * sqrt$2(bx * bx + by * by))) / 2),
32530 lc = sqrt$2(oc[0] * oc[0] + oc[1] * oc[1]);
32531 rc0 = min$1(rc, (r0 - lc) / (kc - 1));
32532 rc1 = min$1(rc, (r1 - lc) / (kc + 1));
32536 // Is the sector collapsed to a line?
32537 if (!(da1 > epsilon$3)) context.moveTo(x01, y01);
32539 // Does the sector’s outer ring have rounded corners?
32540 else if (rc1 > epsilon$3) {
32541 t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
32542 t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
32544 context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
32546 // Have the corners merged?
32547 if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw);
32549 // Otherwise, draw the two corners and the ring.
32551 context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw);
32552 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);
32553 context.arc(t1.cx, t1.cy, rc1, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw);
32557 // Or is the outer ring just a circular arc?
32558 else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
32560 // Is there no inner ring, and it’s a circular sector?
32561 // Or perhaps it’s an annular sector collapsed due to padding?
32562 if (!(r0 > epsilon$3) || !(da0 > epsilon$3)) context.lineTo(x10, y10);
32564 // Does the sector’s inner ring (or point) have rounded corners?
32565 else if (rc0 > epsilon$3) {
32566 t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
32567 t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
32569 context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
32571 // Have the corners merged?
32572 if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw);
32574 // Otherwise, draw the two corners and the ring.
32576 context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw);
32577 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);
32578 context.arc(t1.cx, t1.cy, rc0, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw);
32582 // Or is the inner ring just a circular arc?
32583 else context.arc(0, 0, r0, a10, a00, cw);
32586 context.closePath();
32588 if (buffer) return context = null, buffer + "" || null;
32591 arc.centroid = function() {
32592 var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
32593 a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$4 / 2;
32594 return [cos$2(a) * r, sin$2(a) * r];
32597 arc.innerRadius = function(_) {
32598 return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : innerRadius;
32601 arc.outerRadius = function(_) {
32602 return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : outerRadius;
32605 arc.cornerRadius = function(_) {
32606 return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : cornerRadius;
32609 arc.padRadius = function(_) {
32610 return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), arc) : padRadius;
32613 arc.startAngle = function(_) {
32614 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : startAngle;
32617 arc.endAngle = function(_) {
32618 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : endAngle;
32621 arc.padAngle = function(_) {
32622 return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : padAngle;
32625 arc.context = function(_) {
32626 return arguments.length ? ((context = _ == null ? null : _), arc) : context;
32632 function Linear(context) {
32633 this._context = context;
32636 Linear.prototype = {
32637 areaStart: function() {
32640 areaEnd: function() {
32643 lineStart: function() {
32646 lineEnd: function() {
32647 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
32648 this._line = 1 - this._line;
32650 point: function(x, y) {
32652 switch (this._point) {
32653 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
32654 case 1: this._point = 2; // proceed
32655 default: this._context.lineTo(x, y); break;
32660 var curveLinear = function(context) {
32661 return new Linear(context);
32672 var line = function() {
32675 defined = constant$10(true),
32677 curve = curveLinear,
32680 function line(data) {
32687 if (context == null) output = curve(buffer = path());
32689 for (i = 0; i <= n; ++i) {
32690 if (!(i < n && defined(d = data[i], i, data)) === defined0) {
32691 if (defined0 = !defined0) output.lineStart();
32692 else output.lineEnd();
32694 if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data));
32697 if (buffer) return output = null, buffer + "" || null;
32700 line.x = function(_) {
32701 return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : x$$1;
32704 line.y = function(_) {
32705 return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : y$$1;
32708 line.defined = function(_) {
32709 return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), line) : defined;
32712 line.curve = function(_) {
32713 return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
32716 line.context = function(_) {
32717 return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
32723 var area$1 = function() {
32726 y0 = constant$10(0),
32728 defined = constant$10(true),
32730 curve = curveLinear,
32733 function area(data) {
32741 x0z = new Array(n),
32742 y0z = new Array(n);
32744 if (context == null) output = curve(buffer = path());
32746 for (i = 0; i <= n; ++i) {
32747 if (!(i < n && defined(d = data[i], i, data)) === defined0) {
32748 if (defined0 = !defined0) {
32750 output.areaStart();
32751 output.lineStart();
32754 output.lineStart();
32755 for (k = i - 1; k >= j; --k) {
32756 output.point(x0z[k], y0z[k]);
32763 x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
32764 output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
32768 if (buffer) return output = null, buffer + "" || null;
32771 function arealine() {
32772 return line().defined(defined).curve(curve).context(context);
32775 area.x = function(_) {
32776 return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), x1 = null, area) : x0;
32779 area.x0 = function(_) {
32780 return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), area) : x0;
32783 area.x1 = function(_) {
32784 return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : x1;
32787 area.y = function(_) {
32788 return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), y1 = null, area) : y0;
32791 area.y0 = function(_) {
32792 return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), area) : y0;
32795 area.y1 = function(_) {
32796 return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : y1;
32800 area.lineY0 = function() {
32801 return arealine().x(x0).y(y0);
32804 area.lineY1 = function() {
32805 return arealine().x(x0).y(y1);
32808 area.lineX1 = function() {
32809 return arealine().x(x1).y(y0);
32812 area.defined = function(_) {
32813 return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), area) : defined;
32816 area.curve = function(_) {
32817 return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
32820 area.context = function(_) {
32821 return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
32827 var descending$1 = function(a, b) {
32828 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
32831 var identity$7 = function(d) {
32835 var pie = function() {
32836 var value = identity$7,
32837 sortValues = descending$1,
32839 startAngle = constant$10(0),
32840 endAngle = constant$10(tau$4),
32841 padAngle = constant$10(0);
32843 function pie(data) {
32849 index = new Array(n),
32850 arcs = new Array(n),
32851 a0 = +startAngle.apply(this, arguments),
32852 da = Math.min(tau$4, Math.max(-tau$4, endAngle.apply(this, arguments) - a0)),
32854 p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
32855 pa = p * (da < 0 ? -1 : 1),
32858 for (i = 0; i < n; ++i) {
32859 if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
32864 // Optionally sort the arcs by previously-computed values or by data.
32865 if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
32866 else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); });
32868 // Compute the arcs! They are stored in the original data's order.
32869 for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
32870 j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
32883 pie.value = function(_) {
32884 return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), pie) : value;
32887 pie.sortValues = function(_) {
32888 return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
32891 pie.sort = function(_) {
32892 return arguments.length ? (sort = _, sortValues = null, pie) : sort;
32895 pie.startAngle = function(_) {
32896 return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : startAngle;
32899 pie.endAngle = function(_) {
32900 return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : endAngle;
32903 pie.padAngle = function(_) {
32904 return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : padAngle;
32910 var curveRadialLinear = curveRadial(curveLinear);
32912 function Radial(curve) {
32913 this._curve = curve;
32916 Radial.prototype = {
32917 areaStart: function() {
32918 this._curve.areaStart();
32920 areaEnd: function() {
32921 this._curve.areaEnd();
32923 lineStart: function() {
32924 this._curve.lineStart();
32926 lineEnd: function() {
32927 this._curve.lineEnd();
32929 point: function(a, r) {
32930 this._curve.point(r * Math.sin(a), r * -Math.cos(a));
32934 function curveRadial(curve) {
32936 function radial(context) {
32937 return new Radial(curve(context));
32940 radial._curve = curve;
32945 function radialLine(l) {
32948 l.angle = l.x, delete l.x;
32949 l.radius = l.y, delete l.y;
32951 l.curve = function(_) {
32952 return arguments.length ? c(curveRadial(_)) : c()._curve;
32958 var radialLine$1 = function() {
32959 return radialLine(line().curve(curveRadialLinear));
32962 var radialArea = function() {
32963 var a = area$1().curve(curveRadialLinear),
32970 a.angle = a.x, delete a.x;
32971 a.startAngle = a.x0, delete a.x0;
32972 a.endAngle = a.x1, delete a.x1;
32973 a.radius = a.y, delete a.y;
32974 a.innerRadius = a.y0, delete a.y0;
32975 a.outerRadius = a.y1, delete a.y1;
32976 a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0;
32977 a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1;
32978 a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0;
32979 a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1;
32981 a.curve = function(_) {
32982 return arguments.length ? c(curveRadial(_)) : c()._curve;
32989 draw: function(context, size) {
32990 var r = Math.sqrt(size / pi$4);
32991 context.moveTo(r, 0);
32992 context.arc(0, 0, r, 0, tau$4);
32997 draw: function(context, size) {
32998 var r = Math.sqrt(size / 5) / 2;
32999 context.moveTo(-3 * r, -r);
33000 context.lineTo(-r, -r);
33001 context.lineTo(-r, -3 * r);
33002 context.lineTo(r, -3 * r);
33003 context.lineTo(r, -r);
33004 context.lineTo(3 * r, -r);
33005 context.lineTo(3 * r, r);
33006 context.lineTo(r, r);
33007 context.lineTo(r, 3 * r);
33008 context.lineTo(-r, 3 * r);
33009 context.lineTo(-r, r);
33010 context.lineTo(-3 * r, r);
33011 context.closePath();
33015 var tan30 = Math.sqrt(1 / 3);
33016 var tan30_2 = tan30 * 2;
33019 draw: function(context, size) {
33020 var y = Math.sqrt(size / tan30_2),
33022 context.moveTo(0, -y);
33023 context.lineTo(x, 0);
33024 context.lineTo(0, y);
33025 context.lineTo(-x, 0);
33026 context.closePath();
33030 var ka = 0.89081309152928522810;
33031 var kr = Math.sin(pi$4 / 10) / Math.sin(7 * pi$4 / 10);
33032 var kx = Math.sin(tau$4 / 10) * kr;
33033 var ky = -Math.cos(tau$4 / 10) * kr;
33036 draw: function(context, size) {
33037 var r = Math.sqrt(size * ka),
33040 context.moveTo(0, -r);
33041 context.lineTo(x, y);
33042 for (var i = 1; i < 5; ++i) {
33043 var a = tau$4 * i / 5,
33046 context.lineTo(s * r, -c * r);
33047 context.lineTo(c * x - s * y, s * x + c * y);
33049 context.closePath();
33054 draw: function(context, size) {
33055 var w = Math.sqrt(size),
33057 context.rect(x, x, w, w);
33061 var sqrt3 = Math.sqrt(3);
33064 draw: function(context, size) {
33065 var y = -Math.sqrt(size / (sqrt3 * 3));
33066 context.moveTo(0, y * 2);
33067 context.lineTo(-sqrt3 * y, -y);
33068 context.lineTo(sqrt3 * y, -y);
33069 context.closePath();
33074 var s = Math.sqrt(3) / 2;
33075 var k = 1 / Math.sqrt(12);
33076 var a = (k / 2 + 1) * 3;
33079 draw: function(context, size) {
33080 var r = Math.sqrt(size / a),
33087 context.moveTo(x0, y0);
33088 context.lineTo(x1, y1);
33089 context.lineTo(x2, y2);
33090 context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
33091 context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
33092 context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
33093 context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
33094 context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
33095 context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
33096 context.closePath();
33110 var symbol = function() {
33111 var type = constant$10(circle$2),
33112 size = constant$10(64),
33115 function symbol() {
33117 if (!context) context = buffer = path();
33118 type.apply(this, arguments).draw(context, +size.apply(this, arguments));
33119 if (buffer) return context = null, buffer + "" || null;
33122 symbol.type = function(_) {
33123 return arguments.length ? (type = typeof _ === "function" ? _ : constant$10(_), symbol) : type;
33126 symbol.size = function(_) {
33127 return arguments.length ? (size = typeof _ === "function" ? _ : constant$10(+_), symbol) : size;
33130 symbol.context = function(_) {
33131 return arguments.length ? (context = _ == null ? null : _, symbol) : context;
33137 var noop$2 = function() {};
33139 function point$2(that, x, y) {
33140 that._context.bezierCurveTo(
33141 (2 * that._x0 + that._x1) / 3,
33142 (2 * that._y0 + that._y1) / 3,
33143 (that._x0 + 2 * that._x1) / 3,
33144 (that._y0 + 2 * that._y1) / 3,
33145 (that._x0 + 4 * that._x1 + x) / 6,
33146 (that._y0 + 4 * that._y1 + y) / 6
33150 function Basis(context) {
33151 this._context = context;
33154 Basis.prototype = {
33155 areaStart: function() {
33158 areaEnd: function() {
33161 lineStart: function() {
33162 this._x0 = this._x1 =
33163 this._y0 = this._y1 = NaN;
33166 lineEnd: function() {
33167 switch (this._point) {
33168 case 3: point$2(this, this._x1, this._y1); // proceed
33169 case 2: this._context.lineTo(this._x1, this._y1); break;
33171 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33172 this._line = 1 - this._line;
33174 point: function(x, y) {
33176 switch (this._point) {
33177 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33178 case 1: this._point = 2; break;
33179 case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed
33180 default: point$2(this, x, y); break;
33182 this._x0 = this._x1, this._x1 = x;
33183 this._y0 = this._y1, this._y1 = y;
33187 var basis$2 = function(context) {
33188 return new Basis(context);
33191 function BasisClosed(context) {
33192 this._context = context;
33195 BasisClosed.prototype = {
33198 lineStart: function() {
33199 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
33200 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
33203 lineEnd: function() {
33204 switch (this._point) {
33206 this._context.moveTo(this._x2, this._y2);
33207 this._context.closePath();
33211 this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
33212 this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
33213 this._context.closePath();
33217 this.point(this._x2, this._y2);
33218 this.point(this._x3, this._y3);
33219 this.point(this._x4, this._y4);
33224 point: function(x, y) {
33226 switch (this._point) {
33227 case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
33228 case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
33229 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;
33230 default: point$2(this, x, y); break;
33232 this._x0 = this._x1, this._x1 = x;
33233 this._y0 = this._y1, this._y1 = y;
33237 var basisClosed$1 = function(context) {
33238 return new BasisClosed(context);
33241 function BasisOpen(context) {
33242 this._context = context;
33245 BasisOpen.prototype = {
33246 areaStart: function() {
33249 areaEnd: function() {
33252 lineStart: function() {
33253 this._x0 = this._x1 =
33254 this._y0 = this._y1 = NaN;
33257 lineEnd: function() {
33258 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33259 this._line = 1 - this._line;
33261 point: function(x, y) {
33263 switch (this._point) {
33264 case 0: this._point = 1; break;
33265 case 1: this._point = 2; break;
33266 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;
33267 case 3: this._point = 4; // proceed
33268 default: point$2(this, x, y); break;
33270 this._x0 = this._x1, this._x1 = x;
33271 this._y0 = this._y1, this._y1 = y;
33275 var basisOpen = function(context) {
33276 return new BasisOpen(context);
33279 function Bundle(context, beta) {
33280 this._basis = new Basis(context);
33284 Bundle.prototype = {
33285 lineStart: function() {
33288 this._basis.lineStart();
33290 lineEnd: function() {
33306 this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
33307 this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
33312 this._x = this._y = null;
33313 this._basis.lineEnd();
33315 point: function(x, y) {
33321 var bundle = ((function custom(beta) {
33323 function bundle(context) {
33324 return beta === 1 ? new Basis(context) : new Bundle(context, beta);
33327 bundle.beta = function(beta) {
33328 return custom(+beta);
33334 function point$3(that, x, y) {
33335 that._context.bezierCurveTo(
33336 that._x1 + that._k * (that._x2 - that._x0),
33337 that._y1 + that._k * (that._y2 - that._y0),
33338 that._x2 + that._k * (that._x1 - x),
33339 that._y2 + that._k * (that._y1 - y),
33345 function Cardinal(context, tension) {
33346 this._context = context;
33347 this._k = (1 - tension) / 6;
33350 Cardinal.prototype = {
33351 areaStart: function() {
33354 areaEnd: function() {
33357 lineStart: function() {
33358 this._x0 = this._x1 = this._x2 =
33359 this._y0 = this._y1 = this._y2 = NaN;
33362 lineEnd: function() {
33363 switch (this._point) {
33364 case 2: this._context.lineTo(this._x2, this._y2); break;
33365 case 3: point$3(this, this._x1, this._y1); break;
33367 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33368 this._line = 1 - this._line;
33370 point: function(x, y) {
33372 switch (this._point) {
33373 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33374 case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
33375 case 2: this._point = 3; // proceed
33376 default: point$3(this, x, y); break;
33378 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33379 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33383 var cardinal = ((function custom(tension) {
33385 function cardinal(context) {
33386 return new Cardinal(context, tension);
33389 cardinal.tension = function(tension) {
33390 return custom(+tension);
33396 function CardinalClosed(context, tension) {
33397 this._context = context;
33398 this._k = (1 - tension) / 6;
33401 CardinalClosed.prototype = {
33404 lineStart: function() {
33405 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
33406 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
33409 lineEnd: function() {
33410 switch (this._point) {
33412 this._context.moveTo(this._x3, this._y3);
33413 this._context.closePath();
33417 this._context.lineTo(this._x3, this._y3);
33418 this._context.closePath();
33422 this.point(this._x3, this._y3);
33423 this.point(this._x4, this._y4);
33424 this.point(this._x5, this._y5);
33429 point: function(x, y) {
33431 switch (this._point) {
33432 case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
33433 case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
33434 case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
33435 default: point$3(this, x, y); break;
33437 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33438 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33442 var cardinalClosed = ((function custom(tension) {
33444 function cardinal(context) {
33445 return new CardinalClosed(context, tension);
33448 cardinal.tension = function(tension) {
33449 return custom(+tension);
33455 function CardinalOpen(context, tension) {
33456 this._context = context;
33457 this._k = (1 - tension) / 6;
33460 CardinalOpen.prototype = {
33461 areaStart: function() {
33464 areaEnd: function() {
33467 lineStart: function() {
33468 this._x0 = this._x1 = this._x2 =
33469 this._y0 = this._y1 = this._y2 = NaN;
33472 lineEnd: function() {
33473 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33474 this._line = 1 - this._line;
33476 point: function(x, y) {
33478 switch (this._point) {
33479 case 0: this._point = 1; break;
33480 case 1: this._point = 2; break;
33481 case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
33482 case 3: this._point = 4; // proceed
33483 default: point$3(this, x, y); break;
33485 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33486 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33490 var cardinalOpen = ((function custom(tension) {
33492 function cardinal(context) {
33493 return new CardinalOpen(context, tension);
33496 cardinal.tension = function(tension) {
33497 return custom(+tension);
33503 function point$4(that, x, y) {
33509 if (that._l01_a > epsilon$3) {
33510 var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
33511 n = 3 * that._l01_a * (that._l01_a + that._l12_a);
33512 x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
33513 y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
33516 if (that._l23_a > epsilon$3) {
33517 var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
33518 m = 3 * that._l23_a * (that._l23_a + that._l12_a);
33519 x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
33520 y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
33523 that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
33526 function CatmullRom(context, alpha) {
33527 this._context = context;
33528 this._alpha = alpha;
33531 CatmullRom.prototype = {
33532 areaStart: function() {
33535 areaEnd: function() {
33538 lineStart: function() {
33539 this._x0 = this._x1 = this._x2 =
33540 this._y0 = this._y1 = this._y2 = NaN;
33541 this._l01_a = this._l12_a = this._l23_a =
33542 this._l01_2a = this._l12_2a = this._l23_2a =
33545 lineEnd: function() {
33546 switch (this._point) {
33547 case 2: this._context.lineTo(this._x2, this._y2); break;
33548 case 3: this.point(this._x2, this._y2); break;
33550 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33551 this._line = 1 - this._line;
33553 point: function(x, y) {
33557 var x23 = this._x2 - x,
33558 y23 = this._y2 - y;
33559 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33562 switch (this._point) {
33563 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33564 case 1: this._point = 2; break;
33565 case 2: this._point = 3; // proceed
33566 default: point$4(this, x, y); break;
33569 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33570 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33571 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33572 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33576 var catmullRom = ((function custom(alpha) {
33578 function catmullRom(context) {
33579 return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
33582 catmullRom.alpha = function(alpha) {
33583 return custom(+alpha);
33589 function CatmullRomClosed(context, alpha) {
33590 this._context = context;
33591 this._alpha = alpha;
33594 CatmullRomClosed.prototype = {
33597 lineStart: function() {
33598 this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
33599 this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
33600 this._l01_a = this._l12_a = this._l23_a =
33601 this._l01_2a = this._l12_2a = this._l23_2a =
33604 lineEnd: function() {
33605 switch (this._point) {
33607 this._context.moveTo(this._x3, this._y3);
33608 this._context.closePath();
33612 this._context.lineTo(this._x3, this._y3);
33613 this._context.closePath();
33617 this.point(this._x3, this._y3);
33618 this.point(this._x4, this._y4);
33619 this.point(this._x5, this._y5);
33624 point: function(x, y) {
33628 var x23 = this._x2 - x,
33629 y23 = this._y2 - y;
33630 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33633 switch (this._point) {
33634 case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
33635 case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
33636 case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
33637 default: point$4(this, x, y); break;
33640 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33641 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33642 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33643 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33647 var catmullRomClosed = ((function custom(alpha) {
33649 function catmullRom(context) {
33650 return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
33653 catmullRom.alpha = function(alpha) {
33654 return custom(+alpha);
33660 function CatmullRomOpen(context, alpha) {
33661 this._context = context;
33662 this._alpha = alpha;
33665 CatmullRomOpen.prototype = {
33666 areaStart: function() {
33669 areaEnd: function() {
33672 lineStart: function() {
33673 this._x0 = this._x1 = this._x2 =
33674 this._y0 = this._y1 = this._y2 = NaN;
33675 this._l01_a = this._l12_a = this._l23_a =
33676 this._l01_2a = this._l12_2a = this._l23_2a =
33679 lineEnd: function() {
33680 if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33681 this._line = 1 - this._line;
33683 point: function(x, y) {
33687 var x23 = this._x2 - x,
33688 y23 = this._y2 - y;
33689 this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33692 switch (this._point) {
33693 case 0: this._point = 1; break;
33694 case 1: this._point = 2; break;
33695 case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
33696 case 3: this._point = 4; // proceed
33697 default: point$4(this, x, y); break;
33700 this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33701 this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33702 this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33703 this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33707 var catmullRomOpen = ((function custom(alpha) {
33709 function catmullRom(context) {
33710 return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
33713 catmullRom.alpha = function(alpha) {
33714 return custom(+alpha);
33720 function LinearClosed(context) {
33721 this._context = context;
33724 LinearClosed.prototype = {
33727 lineStart: function() {
33730 lineEnd: function() {
33731 if (this._point) this._context.closePath();
33733 point: function(x, y) {
33735 if (this._point) this._context.lineTo(x, y);
33736 else this._point = 1, this._context.moveTo(x, y);
33740 var linearClosed = function(context) {
33741 return new LinearClosed(context);
33744 function sign$1(x) {
33745 return x < 0 ? -1 : 1;
33748 // Calculate the slopes of the tangents (Hermite-type interpolation) based on
33749 // the following paper: Steffen, M. 1990. A Simple Method for Monotonic
33750 // Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
33751 // NOV(II), P. 443, 1990.
33752 function slope3(that, x2, y2) {
33753 var h0 = that._x1 - that._x0,
33754 h1 = x2 - that._x1,
33755 s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
33756 s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
33757 p = (s0 * h1 + s1 * h0) / (h0 + h1);
33758 return (sign$1(s0) + sign$1(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
33761 // Calculate a one-sided slope.
33762 function slope2(that, t) {
33763 var h = that._x1 - that._x0;
33764 return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
33767 // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
33768 // "you can express cubic Hermite interpolation in terms of cubic Bézier curves
33769 // with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
33770 function point$5(that, t0, t1) {
33775 dx = (x1 - x0) / 3;
33776 that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
33779 function MonotoneX(context) {
33780 this._context = context;
33783 MonotoneX.prototype = {
33784 areaStart: function() {
33787 areaEnd: function() {
33790 lineStart: function() {
33791 this._x0 = this._x1 =
33792 this._y0 = this._y1 =
33796 lineEnd: function() {
33797 switch (this._point) {
33798 case 2: this._context.lineTo(this._x1, this._y1); break;
33799 case 3: point$5(this, this._t0, slope2(this, this._t0)); break;
33801 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33802 this._line = 1 - this._line;
33804 point: function(x, y) {
33808 if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
33809 switch (this._point) {
33810 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33811 case 1: this._point = 2; break;
33812 case 2: this._point = 3; point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
33813 default: point$5(this, this._t0, t1 = slope3(this, x, y)); break;
33816 this._x0 = this._x1, this._x1 = x;
33817 this._y0 = this._y1, this._y1 = y;
33822 function MonotoneY(context) {
33823 this._context = new ReflectContext(context);
33826 (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
33827 MonotoneX.prototype.point.call(this, y, x);
33830 function ReflectContext(context) {
33831 this._context = context;
33834 ReflectContext.prototype = {
33835 moveTo: function(x, y) { this._context.moveTo(y, x); },
33836 closePath: function() { this._context.closePath(); },
33837 lineTo: function(x, y) { this._context.lineTo(y, x); },
33838 bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
33841 function monotoneX(context) {
33842 return new MonotoneX(context);
33845 function monotoneY(context) {
33846 return new MonotoneY(context);
33849 function Natural(context) {
33850 this._context = context;
33853 Natural.prototype = {
33854 areaStart: function() {
33857 areaEnd: function() {
33860 lineStart: function() {
33864 lineEnd: function() {
33870 this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
33872 this._context.lineTo(x[1], y[1]);
33874 var px = controlPoints(x),
33875 py = controlPoints(y);
33876 for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
33877 this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
33882 if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
33883 this._line = 1 - this._line;
33884 this._x = this._y = null;
33886 point: function(x, y) {
33892 // See https://www.particleincell.com/2012/bezier-splines/ for derivation.
33893 function controlPoints(x) {
33900 a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
33901 for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
33902 a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
33903 for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
33904 a[n - 1] = r[n - 1] / b[n - 1];
33905 for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
33906 b[n - 1] = (x[n] + a[n - 1]) / 2;
33907 for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
33911 var natural = function(context) {
33912 return new Natural(context);
33915 function Step(context, t) {
33916 this._context = context;
33921 areaStart: function() {
33924 areaEnd: function() {
33927 lineStart: function() {
33928 this._x = this._y = NaN;
33931 lineEnd: function() {
33932 if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
33933 if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33934 if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
33936 point: function(x, y) {
33938 switch (this._point) {
33939 case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33940 case 1: this._point = 2; // proceed
33942 if (this._t <= 0) {
33943 this._context.lineTo(this._x, y);
33944 this._context.lineTo(x, y);
33946 var x1 = this._x * (1 - this._t) + x * this._t;
33947 this._context.lineTo(x1, this._y);
33948 this._context.lineTo(x1, y);
33953 this._x = x, this._y = y;
33957 var step = function(context) {
33958 return new Step(context, 0.5);
33961 function stepBefore(context) {
33962 return new Step(context, 0);
33965 function stepAfter(context) {
33966 return new Step(context, 1);
33969 var slice$5 = Array.prototype.slice;
33971 var none$1 = function(series, order) {
33972 if (!((n = series.length) > 1)) return;
33973 for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
33974 s0 = s1, s1 = series[order[i]];
33975 for (var j = 0; j < m; ++j) {
33976 s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
33981 var none$2 = function(series) {
33982 var n = series.length, o = new Array(n);
33983 while (--n >= 0) o[n] = n;
33987 function stackValue(d, key) {
33991 var stack = function() {
33992 var keys = constant$10([]),
33995 value = stackValue;
33997 function stack(data) {
33998 var kz = keys.apply(this, arguments),
34005 for (i = 0; i < n; ++i) {
34006 for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
34007 si[j] = sij = [0, +value(data[j], ki, j, data)];
34008 sij.data = data[j];
34013 for (i = 0, oz = order(sz); i < n; ++i) {
34014 sz[oz[i]].index = i;
34021 stack.keys = function(_) {
34022 return arguments.length ? (keys = typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : keys;
34025 stack.value = function(_) {
34026 return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), stack) : value;
34029 stack.order = function(_) {
34030 return arguments.length ? (order = _ == null ? none$2 : typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : order;
34033 stack.offset = function(_) {
34034 return arguments.length ? (offset = _ == null ? none$1 : _, stack) : offset;
34040 var expand = function(series, order) {
34041 if (!((n = series.length) > 0)) return;
34042 for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
34043 for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0;
34044 if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y;
34046 none$1(series, order);
34049 var silhouette = function(series, order) {
34050 if (!((n = series.length) > 0)) return;
34051 for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
34052 for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0;
34053 s0[j][1] += s0[j][0] = -y / 2;
34055 none$1(series, order);
34058 var wiggle = function(series, order) {
34059 if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
34060 for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
34061 for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
34062 var si = series[order[i]],
34063 sij0 = si[j][1] || 0,
34064 sij1 = si[j - 1][1] || 0,
34065 s3 = (sij0 - sij1) / 2;
34066 for (var k = 0; k < i; ++k) {
34067 var sk = series[order[k]],
34068 skj0 = sk[j][1] || 0,
34069 skj1 = sk[j - 1][1] || 0;
34072 s1 += sij0, s2 += s3 * sij0;
34074 s0[j - 1][1] += s0[j - 1][0] = y;
34075 if (s1) y -= s2 / s1;
34077 s0[j - 1][1] += s0[j - 1][0] = y;
34078 none$1(series, order);
34081 var ascending$2 = function(series) {
34082 var sums = series.map(sum$2);
34083 return none$2(series).sort(function(a, b) { return sums[a] - sums[b]; });
34086 function sum$2(series) {
34087 var s = 0, i = -1, n = series.length, v;
34088 while (++i < n) if (v = +series[i][1]) s += v;
34092 var descending$2 = function(series) {
34093 return ascending$2(series).reverse();
34096 var insideOut = function(series) {
34097 var n = series.length,
34100 sums = series.map(sum$2),
34101 order = none$2(series).sort(function(a, b) { return sums[b] - sums[a]; }),
34107 for (i = 0; i < n; ++i) {
34109 if (top < bottom) {
34118 return bottoms.reverse().concat(tops);
34121 var reverse = function(series) {
34122 return none$2(series).reverse();
34125 var constant$11 = function(x) {
34126 return function() {
34139 function RedBlackTree() {
34140 this._ = null; // root node
34143 function RedBlackNode(node) {
34144 node.U = // parent node
34145 node.C = // color - true for red, false for black
34146 node.L = // left node
34147 node.R = // right node
34148 node.P = // previous node
34149 node.N = null; // next node
34152 RedBlackTree.prototype = {
34153 constructor: RedBlackTree,
34155 insert: function(after, node) {
34156 var parent, grandpa, uncle;
34161 if (after.N) after.N.P = node;
34165 while (after.L) after = after.L;
34171 } else if (this._) {
34172 after = RedBlackFirst(this._);
34175 after.P = after.L = node;
34178 node.P = node.N = null;
34182 node.L = node.R = null;
34187 while (parent && parent.C) {
34188 grandpa = parent.U;
34189 if (parent === grandpa.L) {
34191 if (uncle && uncle.C) {
34192 parent.C = uncle.C = false;
34196 if (after === parent.R) {
34197 RedBlackRotateLeft(this, parent);
34203 RedBlackRotateRight(this, grandpa);
34207 if (uncle && uncle.C) {
34208 parent.C = uncle.C = false;
34212 if (after === parent.L) {
34213 RedBlackRotateRight(this, parent);
34219 RedBlackRotateLeft(this, grandpa);
34227 remove: function(node) {
34228 if (node.N) node.N.P = node.P;
34229 if (node.P) node.P.N = node.N;
34230 node.N = node.P = null;
34232 var parent = node.U,
34239 if (!left) next = right;
34240 else if (!right) next = left;
34241 else next = RedBlackFirst(right);
34244 if (parent.L === node) parent.L = next;
34245 else parent.R = next;
34250 if (left && right) {
34255 if (next !== right) {
34272 if (node) node.U = parent;
34274 if (node && node.C) { node.C = false; return; }
34277 if (node === this._) break;
34278 if (node === parent.L) {
34279 sibling = parent.R;
34283 RedBlackRotateLeft(this, parent);
34284 sibling = parent.R;
34286 if ((sibling.L && sibling.L.C)
34287 || (sibling.R && sibling.R.C)) {
34288 if (!sibling.R || !sibling.R.C) {
34289 sibling.L.C = false;
34291 RedBlackRotateRight(this, sibling);
34292 sibling = parent.R;
34294 sibling.C = parent.C;
34295 parent.C = sibling.R.C = false;
34296 RedBlackRotateLeft(this, parent);
34301 sibling = parent.L;
34305 RedBlackRotateRight(this, parent);
34306 sibling = parent.L;
34308 if ((sibling.L && sibling.L.C)
34309 || (sibling.R && sibling.R.C)) {
34310 if (!sibling.L || !sibling.L.C) {
34311 sibling.R.C = false;
34313 RedBlackRotateLeft(this, sibling);
34314 sibling = parent.L;
34316 sibling.C = parent.C;
34317 parent.C = sibling.L.C = false;
34318 RedBlackRotateRight(this, parent);
34328 if (node) node.C = false;
34332 function RedBlackRotateLeft(tree, node) {
34338 if (parent.L === p) parent.L = q;
34347 if (p.R) p.R.U = p;
34351 function RedBlackRotateRight(tree, node) {
34357 if (parent.L === p) parent.L = q;
34366 if (p.L) p.L.U = p;
34370 function RedBlackFirst(node) {
34371 while (node.L) node = node.L;
34375 function createEdge(left, right, v0, v1) {
34376 var edge = [null, null],
34377 index = edges.push(edge) - 1;
34379 edge.right = right;
34380 if (v0) setEdgeEnd(edge, left, right, v0);
34381 if (v1) setEdgeEnd(edge, right, left, v1);
34382 cells[left.index].halfedges.push(index);
34383 cells[right.index].halfedges.push(index);
34387 function createBorderEdge(left, v0, v1) {
34388 var edge = [v0, v1];
34393 function setEdgeEnd(edge, left, right, vertex) {
34394 if (!edge[0] && !edge[1]) {
34397 edge.right = right;
34398 } else if (edge.left === right) {
34405 // Liang–Barsky line clipping.
34406 function clipEdge(edge, x0, y0, x1, y1) {
34420 if (!dx && r > 0) return;
34423 if (r < t0) return;
34424 if (r < t1) t1 = r;
34425 } else if (dx > 0) {
34426 if (r > t1) return;
34427 if (r > t0) t0 = r;
34431 if (!dx && r < 0) return;
34434 if (r > t1) return;
34435 if (r > t0) t0 = r;
34436 } else if (dx > 0) {
34437 if (r < t0) return;
34438 if (r < t1) t1 = r;
34442 if (!dy && r > 0) return;
34445 if (r < t0) return;
34446 if (r < t1) t1 = r;
34447 } else if (dy > 0) {
34448 if (r > t1) return;
34449 if (r > t0) t0 = r;
34453 if (!dy && r < 0) return;
34456 if (r > t1) return;
34457 if (r > t0) t0 = r;
34458 } else if (dy > 0) {
34459 if (r < t0) return;
34460 if (r < t1) t1 = r;
34463 if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
34465 if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
34466 if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
34470 function connectEdge(edge, x0, y0, x1, y1) {
34472 if (v1) return true;
34476 right = edge.right,
34481 fx = (lx + rx) / 2,
34482 fy = (ly + ry) / 2,
34487 if (fx < x0 || fx >= x1) return;
34489 if (!v0) v0 = [fx, y0];
34490 else if (v0[1] >= y1) return;
34493 if (!v0) v0 = [fx, y1];
34494 else if (v0[1] < y0) return;
34498 fm = (lx - rx) / (ry - ly);
34500 if (fm < -1 || fm > 1) {
34502 if (!v0) v0 = [(y0 - fb) / fm, y0];
34503 else if (v0[1] >= y1) return;
34504 v1 = [(y1 - fb) / fm, y1];
34506 if (!v0) v0 = [(y1 - fb) / fm, y1];
34507 else if (v0[1] < y0) return;
34508 v1 = [(y0 - fb) / fm, y0];
34512 if (!v0) v0 = [x0, fm * x0 + fb];
34513 else if (v0[0] >= x1) return;
34514 v1 = [x1, fm * x1 + fb];
34516 if (!v0) v0 = [x1, fm * x1 + fb];
34517 else if (v0[0] < x0) return;
34518 v1 = [x0, fm * x0 + fb];
34528 function clipEdges(x0, y0, x1, y1) {
34529 var i = edges.length,
34533 if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
34534 || !clipEdge(edge, x0, y0, x1, y1)
34535 || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$4
34536 || Math.abs(edge[0][1] - edge[1][1]) > epsilon$4)) {
34542 function createCell(site) {
34543 return cells[site.index] = {
34549 function cellHalfedgeAngle(cell, edge) {
34550 var site = cell.site,
34553 if (site === vb) vb = va, va = site;
34554 if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
34555 if (site === va) va = edge[1], vb = edge[0];
34556 else va = edge[0], vb = edge[1];
34557 return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
34560 function cellHalfedgeStart(cell, edge) {
34561 return edge[+(edge.left !== cell.site)];
34564 function cellHalfedgeEnd(cell, edge) {
34565 return edge[+(edge.left === cell.site)];
34568 function sortCellHalfedges() {
34569 for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
34570 if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
34571 var index = new Array(m),
34572 array = new Array(m);
34573 for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
34574 index.sort(function(i, j) { return array[j] - array[i]; });
34575 for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
34576 for (j = 0; j < m; ++j) halfedges[j] = array[j];
34581 function clipCells(x0, y0, x1, y1) {
34582 var nCells = cells.length,
34597 for (iCell = 0; iCell < nCells; ++iCell) {
34598 if (cell = cells[iCell]) {
34600 halfedges = cell.halfedges;
34601 iHalfedge = halfedges.length;
34603 // Remove any dangling clipped edges.
34604 while (iHalfedge--) {
34605 if (!edges[halfedges[iHalfedge]]) {
34606 halfedges.splice(iHalfedge, 1);
34610 // Insert any border edges as necessary.
34611 iHalfedge = 0, nHalfedges = halfedges.length;
34612 while (iHalfedge < nHalfedges) {
34613 end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
34614 start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
34615 if (Math.abs(endX - startX) > epsilon$4 || Math.abs(endY - startY) > epsilon$4) {
34616 halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
34617 Math.abs(endX - x0) < epsilon$4 && y1 - endY > epsilon$4 ? [x0, Math.abs(startX - x0) < epsilon$4 ? startY : y1]
34618 : Math.abs(endY - y1) < epsilon$4 && x1 - endX > epsilon$4 ? [Math.abs(startY - y1) < epsilon$4 ? startX : x1, y1]
34619 : Math.abs(endX - x1) < epsilon$4 && endY - y0 > epsilon$4 ? [x1, Math.abs(startX - x1) < epsilon$4 ? startY : y0]
34620 : Math.abs(endY - y0) < epsilon$4 && endX - x0 > epsilon$4 ? [Math.abs(startY - y0) < epsilon$4 ? startX : x0, y0]
34626 if (nHalfedges) cover = false;
34630 // If there weren’t any edges, have the closest site cover the extent.
34631 // It doesn’t matter which corner of the extent we measure!
34633 var dx, dy, d2, dc = Infinity;
34635 for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
34636 if (cell = cells[iCell]) {
34640 d2 = dx * dx + dy * dy;
34641 if (d2 < dc) dc = d2, cover = cell;
34646 var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
34647 cover.halfedges.push(
34648 edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
34649 edges.push(createBorderEdge(site, v01, v11)) - 1,
34650 edges.push(createBorderEdge(site, v11, v10)) - 1,
34651 edges.push(createBorderEdge(site, v10, v00)) - 1
34656 // Lastly delete any cells with no edges; these were entirely clipped.
34657 for (iCell = 0; iCell < nCells; ++iCell) {
34658 if (cell = cells[iCell]) {
34659 if (!cell.halfedges.length) {
34660 delete cells[iCell];
34666 var circlePool = [];
34670 function Circle() {
34671 RedBlackNode(this);
34679 function attachCircle(arc) {
34683 if (!lArc || !rArc) return;
34685 var lSite = lArc.site,
34689 if (lSite === rSite) return;
34693 ax = lSite[0] - bx,
34694 ay = lSite[1] - by,
34695 cx = rSite[0] - bx,
34696 cy = rSite[1] - by;
34698 var d = 2 * (ax * cy - ay * cx);
34699 if (d >= -epsilon2$2) return;
34701 var ha = ax * ax + ay * ay,
34702 hc = cx * cx + cy * cy,
34703 x = (cy * ha - ay * hc) / d,
34704 y = (ax * hc - cx * ha) / d;
34706 var circle = circlePool.pop() || new Circle;
34708 circle.site = cSite;
34710 circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
34712 arc.circle = circle;
34718 if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
34719 if (node.L) node = node.L;
34720 else { before = node.P; break; }
34722 if (node.R) node = node.R;
34723 else { before = node; break; }
34727 circles.insert(before, circle);
34728 if (!before) firstCircle = circle;
34731 function detachCircle(arc) {
34732 var circle = arc.circle;
34734 if (!circle.P) firstCircle = circle.N;
34735 circles.remove(circle);
34736 circlePool.push(circle);
34737 RedBlackNode(circle);
34742 var beachPool = [];
34745 RedBlackNode(this);
34748 this.circle = null;
34751 function createBeach(site) {
34752 var beach = beachPool.pop() || new Beach;
34757 function detachBeach(beach) {
34758 detachCircle(beach);
34759 beaches.remove(beach);
34760 beachPool.push(beach);
34761 RedBlackNode(beach);
34764 function removeBeach(beach) {
34765 var circle = beach.circle,
34769 previous = beach.P,
34771 disappearing = [beach];
34773 detachBeach(beach);
34775 var lArc = previous;
34777 && Math.abs(x - lArc.circle.x) < epsilon$4
34778 && Math.abs(y - lArc.circle.cy) < epsilon$4) {
34780 disappearing.unshift(lArc);
34785 disappearing.unshift(lArc);
34786 detachCircle(lArc);
34790 && Math.abs(x - rArc.circle.x) < epsilon$4
34791 && Math.abs(y - rArc.circle.cy) < epsilon$4) {
34793 disappearing.push(rArc);
34798 disappearing.push(rArc);
34799 detachCircle(rArc);
34801 var nArcs = disappearing.length,
34803 for (iArc = 1; iArc < nArcs; ++iArc) {
34804 rArc = disappearing[iArc];
34805 lArc = disappearing[iArc - 1];
34806 setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
34809 lArc = disappearing[0];
34810 rArc = disappearing[nArcs - 1];
34811 rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
34813 attachCircle(lArc);
34814 attachCircle(rArc);
34817 function addBeach(site) {
34819 directrix = site[1],
34827 dxl = leftBreakPoint(node, directrix) - x;
34828 if (dxl > epsilon$4) node = node.L; else {
34829 dxr = x - rightBreakPoint(node, directrix);
34830 if (dxr > epsilon$4) {
34837 if (dxl > -epsilon$4) {
34840 } else if (dxr > -epsilon$4) {
34844 lArc = rArc = node;
34852 var newArc = createBeach(site);
34853 beaches.insert(lArc, newArc);
34855 if (!lArc && !rArc) return;
34857 if (lArc === rArc) {
34858 detachCircle(lArc);
34859 rArc = createBeach(lArc.site);
34860 beaches.insert(newArc, rArc);
34861 newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
34862 attachCircle(lArc);
34863 attachCircle(rArc);
34867 if (!rArc) { // && lArc
34868 newArc.edge = createEdge(lArc.site, newArc.site);
34872 // else lArc !== rArc
34873 detachCircle(lArc);
34874 detachCircle(rArc);
34876 var lSite = lArc.site,
34882 cx = rSite[0] - ax,
34883 cy = rSite[1] - ay,
34884 d = 2 * (bx * cy - by * cx),
34885 hb = bx * bx + by * by,
34886 hc = cx * cx + cy * cy,
34887 vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
34889 setEdgeEnd(rArc.edge, lSite, rSite, vertex);
34890 newArc.edge = createEdge(lSite, site, null, vertex);
34891 rArc.edge = createEdge(site, rSite, null, vertex);
34892 attachCircle(lArc);
34893 attachCircle(rArc);
34896 function leftBreakPoint(arc, directrix) {
34897 var site = arc.site,
34900 pby2 = rfocy - directrix;
34902 if (!pby2) return rfocx;
34905 if (!lArc) return -Infinity;
34908 var lfocx = site[0],
34910 plby2 = lfocy - directrix;
34912 if (!plby2) return lfocx;
34914 var hl = lfocx - rfocx,
34915 aby2 = 1 / pby2 - 1 / plby2,
34918 if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
34920 return (rfocx + lfocx) / 2;
34923 function rightBreakPoint(arc, directrix) {
34925 if (rArc) return leftBreakPoint(rArc, directrix);
34926 var site = arc.site;
34927 return site[1] === directrix ? site[0] : Infinity;
34930 var epsilon$4 = 1e-6;
34931 var epsilon2$2 = 1e-12;
34937 function triangleArea(a, b, c) {
34938 return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
34941 function lexicographic(a, b) {
34946 function Diagram(sites, extent) {
34947 var site = sites.sort(lexicographic).pop(),
34953 cells = new Array(sites.length);
34954 beaches = new RedBlackTree;
34955 circles = new RedBlackTree;
34958 circle = firstCircle;
34959 if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
34960 if (site[0] !== x || site[1] !== y) {
34962 x = site[0], y = site[1];
34964 site = sites.pop();
34965 } else if (circle) {
34966 removeBeach(circle.arc);
34972 sortCellHalfedges();
34975 var x0 = +extent[0][0],
34976 y0 = +extent[0][1],
34977 x1 = +extent[1][0],
34978 y1 = +extent[1][1];
34979 clipEdges(x0, y0, x1, y1);
34980 clipCells(x0, y0, x1, y1);
34983 this.edges = edges;
34984 this.cells = cells;
34992 Diagram.prototype = {
34993 constructor: Diagram,
34995 polygons: function() {
34996 var edges = this.edges;
34998 return this.cells.map(function(cell) {
34999 var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); });
35000 polygon.data = cell.site.data;
35005 triangles: function() {
35006 var triangles = [],
35007 edges = this.edges;
35009 this.cells.forEach(function(cell, i) {
35010 if (!(m = (halfedges = cell.halfedges).length)) return;
35011 var site = cell.site,
35016 e1 = edges[halfedges[m - 1]],
35017 s1 = e1.left === site ? e1.right : e1.left;
35021 e1 = edges[halfedges[j]];
35022 s1 = e1.left === site ? e1.right : e1.left;
35023 if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
35024 triangles.push([site.data, s0.data, s1.data]);
35032 links: function() {
35033 return this.edges.filter(function(edge) {
35035 }).map(function(edge) {
35037 source: edge.left.data,
35038 target: edge.right.data
35043 find: function(x, y, radius) {
35044 var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell;
35046 // Use the previously-found cell, or start with an arbitrary one.
35047 while (!(cell = that.cells[i1])) if (++i1 >= n) return null;
35048 var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy;
35050 // Traverse the half-edges to find a closer cell, if any.
35052 cell = that.cells[i0 = i1], i1 = null;
35053 cell.halfedges.forEach(function(e) {
35054 var edge = that.edges[e], v = edge.left;
35055 if ((v === cell.site || !v) && !(v = edge.right)) return;
35056 var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy;
35057 if (v2 < d2) d2 = v2, i1 = v.index;
35059 } while (i1 !== null);
35063 return radius == null || d2 <= radius * radius ? cell.site : null;
35067 var voronoi = function() {
35072 function voronoi(data) {
35073 return new Diagram(data.map(function(d, i) {
35074 var s = [Math.round(x$$1(d, i, data) / epsilon$4) * epsilon$4, Math.round(y$$1(d, i, data) / epsilon$4) * epsilon$4];
35081 voronoi.polygons = function(data) {
35082 return voronoi(data).polygons();
35085 voronoi.links = function(data) {
35086 return voronoi(data).links();
35089 voronoi.triangles = function(data) {
35090 return voronoi(data).triangles();
35093 voronoi.x = function(_) {
35094 return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : x$$1;
35097 voronoi.y = function(_) {
35098 return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : y$$1;
35101 voronoi.extent = function(_) {
35102 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]]];
35105 voronoi.size = function(_) {
35106 return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]];
35112 var constant$12 = function(x) {
35113 return function() {
35118 function ZoomEvent(target, type, transform) {
35119 this.target = target;
35121 this.transform = transform;
35124 function Transform(k, x, y) {
35130 Transform.prototype = {
35131 constructor: Transform,
35132 scale: function(k) {
35133 return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
35135 translate: function(x, y) {
35136 return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
35138 apply: function(point) {
35139 return [point[0] * this.k + this.x, point[1] * this.k + this.y];
35141 applyX: function(x) {
35142 return x * this.k + this.x;
35144 applyY: function(y) {
35145 return y * this.k + this.y;
35147 invert: function(location) {
35148 return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
35150 invertX: function(x) {
35151 return (x - this.x) / this.k;
35153 invertY: function(y) {
35154 return (y - this.y) / this.k;
35156 rescaleX: function(x) {
35157 return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
35159 rescaleY: function(y) {
35160 return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
35162 toString: function() {
35163 return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
35167 var identity$8 = new Transform(1, 0, 0);
35169 transform$1.prototype = Transform.prototype;
35171 function transform$1(node) {
35172 return node.__zoom || identity$8;
35175 function nopropagation$2() {
35176 event.stopImmediatePropagation();
35179 var noevent$2 = function() {
35180 event.preventDefault();
35181 event.stopImmediatePropagation();
35184 // Ignore right-click, since that should open the context menu.
35185 function defaultFilter$2() {
35186 return !event.button;
35189 function defaultExtent$1() {
35190 var e = this, w, h;
35191 if (e instanceof SVGElement) {
35192 e = e.ownerSVGElement || e;
35193 w = e.width.baseVal.value;
35194 h = e.height.baseVal.value;
35197 h = e.clientHeight;
35199 return [[0, 0], [w, h]];
35202 function defaultTransform() {
35203 return this.__zoom || identity$8;
35206 var zoom = function() {
35207 var filter = defaultFilter$2,
35208 extent = defaultExtent$1,
35216 interpolate$$1 = interpolateZoom,
35218 listeners = dispatch("start", "zoom", "end"),
35224 function zoom(selection$$1) {
35226 .on("wheel.zoom", wheeled)
35227 .on("mousedown.zoom", mousedowned)
35228 .on("dblclick.zoom", dblclicked)
35229 .on("touchstart.zoom", touchstarted)
35230 .on("touchmove.zoom", touchmoved)
35231 .on("touchend.zoom touchcancel.zoom", touchended)
35232 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
35233 .property("__zoom", defaultTransform);
35236 zoom.transform = function(collection, transform) {
35237 var selection$$1 = collection.selection ? collection.selection() : collection;
35238 selection$$1.property("__zoom", defaultTransform);
35239 if (collection !== selection$$1) {
35240 schedule(collection, transform);
35242 selection$$1.interrupt().each(function() {
35243 gesture(this, arguments)
35245 .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform)
35251 zoom.scaleBy = function(selection$$1, k) {
35252 zoom.scaleTo(selection$$1, function() {
35253 var k0 = this.__zoom.k,
35254 k1 = typeof k === "function" ? k.apply(this, arguments) : k;
35259 zoom.scaleTo = function(selection$$1, k) {
35260 zoom.transform(selection$$1, function() {
35261 var e = extent.apply(this, arguments),
35264 p1 = t0.invert(p0),
35265 k1 = typeof k === "function" ? k.apply(this, arguments) : k;
35266 return constrain(translate(scale(t0, k1), p0, p1), e);
35270 zoom.translateBy = function(selection$$1, x, y) {
35271 zoom.transform(selection$$1, function() {
35272 return constrain(this.__zoom.translate(
35273 typeof x === "function" ? x.apply(this, arguments) : x,
35274 typeof y === "function" ? y.apply(this, arguments) : y
35275 ), extent.apply(this, arguments));
35279 function scale(transform, k) {
35280 k = Math.max(k0, Math.min(k1, k));
35281 return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
35284 function translate(transform, p0, p1) {
35285 var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k;
35286 return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
35289 function constrain(transform, extent) {
35290 var dx0 = transform.invertX(extent[0][0]) - x0,
35291 dx1 = transform.invertX(extent[1][0]) - x1,
35292 dy0 = transform.invertY(extent[0][1]) - y0,
35293 dy1 = transform.invertY(extent[1][1]) - y1;
35294 return transform.translate(
35295 dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1),
35296 dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)
35300 function centroid(extent) {
35301 return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
35304 function schedule(transition$$1, transform, center) {
35306 .on("start.zoom", function() { gesture(this, arguments).start(); })
35307 .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
35308 .tween("zoom", function() {
35311 g = gesture(that, args),
35312 e = extent.apply(that, args),
35313 p = center || centroid(e),
35314 w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
35316 b = typeof transform === "function" ? transform.apply(that, args) : transform,
35317 i = interpolate$$1(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
35318 return function(t) {
35319 if (t === 1) t = b; // Avoid rounding error on end.
35320 else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
35326 function gesture(that, args) {
35327 for (var i = 0, n = gestures.length, g; i < n; ++i) {
35328 if ((g = gestures[i]).that === that) {
35332 return new Gesture(that, args);
35335 function Gesture(that, args) {
35340 this.extent = extent.apply(that, args);
35343 Gesture.prototype = {
35344 start: function() {
35345 if (++this.active === 1) {
35346 this.index = gestures.push(this) - 1;
35347 this.emit("start");
35351 zoom: function(key, transform) {
35352 if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
35353 if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
35354 if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
35355 this.that.__zoom = transform;
35360 if (--this.active === 0) {
35361 gestures.splice(this.index, 1);
35367 emit: function(type) {
35368 customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
35372 function wheeled() {
35373 if (!filter.apply(this, arguments)) return;
35374 var g = gesture(this, arguments),
35376 k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500))),
35379 // If the mouse is in the same location as before, reuse it.
35380 // If there were recent wheel events, reset the wheel idle timeout.
35382 if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
35383 g.mouse[1] = t.invert(g.mouse[0] = p);
35385 clearTimeout(g.wheel);
35388 // If this wheel event won’t trigger a transform change, ignore it.
35389 else if (t.k === k) return;
35391 // Otherwise, capture the mouse point and location at the start.
35393 g.mouse = [p, t.invert(p)];
35399 g.wheel = setTimeout(wheelidled, wheelDelay);
35400 g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent));
35402 function wheelidled() {
35408 function mousedowned() {
35409 if (touchending || !filter.apply(this, arguments)) return;
35410 var g = gesture(this, arguments),
35411 v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
35414 dragDisable(event.view);
35416 g.mouse = [p, this.__zoom.invert(p)];
35420 function mousemoved() {
35423 g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent));
35426 function mouseupped() {
35427 v.on("mousemove.zoom mouseup.zoom", null);
35428 yesdrag(event.view, g.moved);
35434 function dblclicked() {
35435 if (!filter.apply(this, arguments)) return;
35436 var t0 = this.__zoom,
35438 p1 = t0.invert(p0),
35439 k1 = t0.k * (event.shiftKey ? 0.5 : 2),
35440 t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments));
35443 if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
35444 else select(this).call(zoom.transform, t1);
35447 function touchstarted() {
35448 if (!filter.apply(this, arguments)) return;
35449 var g = gesture(this, arguments),
35450 touches$$1 = event.changedTouches,
35452 n = touches$$1.length, i, t, p;
35455 for (i = 0; i < n; ++i) {
35456 t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
35457 p = [p, this.__zoom.invert(p), t.identifier];
35458 if (!g.touch0) g.touch0 = p, started = true;
35459 else if (!g.touch1) g.touch1 = p;
35462 // If this is a dbltap, reroute to the (optional) dblclick.zoom handler.
35463 if (touchstarting) {
35464 touchstarting = clearTimeout(touchstarting);
35467 p = select(this).on("dblclick.zoom");
35468 if (p) p.apply(this, arguments);
35474 touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay);
35480 function touchmoved() {
35481 var g = gesture(this, arguments),
35482 touches$$1 = event.changedTouches,
35483 n = touches$$1.length, i, t, p, l;
35486 if (touchstarting) touchstarting = clearTimeout(touchstarting);
35487 for (i = 0; i < n; ++i) {
35488 t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
35489 if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;
35490 else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
35494 var p0 = g.touch0[0], l0 = g.touch0[1],
35495 p1 = g.touch1[0], l1 = g.touch1[1],
35496 dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
35497 dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
35498 t = scale(t, Math.sqrt(dp / dl));
35499 p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
35500 l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
35502 else if (g.touch0) p = g.touch0[0], l = g.touch0[1];
35504 g.zoom("touch", constrain(translate(t, p, l), g.extent));
35507 function touchended() {
35508 var g = gesture(this, arguments),
35509 touches$$1 = event.changedTouches,
35510 n = touches$$1.length, i, t;
35513 if (touchending) clearTimeout(touchending);
35514 touchending = setTimeout(function() { touchending = null; }, touchDelay);
35515 for (i = 0; i < n; ++i) {
35517 if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;
35518 else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
35520 if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
35521 if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);
35525 zoom.filter = function(_) {
35526 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$12(!!_), zoom) : filter;
35529 zoom.extent = function(_) {
35530 return arguments.length ? (extent = typeof _ === "function" ? _ : constant$12([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
35533 zoom.scaleExtent = function(_) {
35534 return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1];
35537 zoom.translateExtent = function(_) {
35538 return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]];
35541 zoom.duration = function(_) {
35542 return arguments.length ? (duration = +_, zoom) : duration;
35545 zoom.interpolate = function(_) {
35546 return arguments.length ? (interpolate$$1 = _, zoom) : interpolate$$1;
35549 zoom.on = function() {
35550 var value = listeners.on.apply(listeners, arguments);
35551 return value === listeners ? zoom : value;
35559 var index$2 = Object.freeze({
35561 bisect: bisectRight,
35562 bisectRight: bisectRight,
35563 bisectLeft: bisectLeft,
35564 ascending: ascending,
35565 bisector: bisector,
35567 descending: descending,
35568 deviation: deviation,
35570 histogram: histogram,
35571 thresholdFreedmanDiaconis: freedmanDiaconis,
35572 thresholdScott: scott,
35573 thresholdSturges: sturges,
35581 quantile: threshold,
35587 tickIncrement: tickIncrement,
35588 tickStep: tickStep,
35589 transpose: transpose,
35590 variance: variance,
35593 axisRight: axisRight,
35594 axisBottom: axisBottom,
35595 axisLeft: axisLeft,
35599 brushSelection: brushSelection,
35613 cubehelix: cubehelix,
35614 dispatch: dispatch,
35616 dragDisable: dragDisable,
35617 dragEnable: yesdrag,
35619 csvParse: csvParse,
35620 csvParseRows: csvParseRows,
35621 csvFormat: csvFormat,
35622 csvFormatRows: csvFormatRows,
35623 tsvParse: tsvParse,
35624 tsvParseRows: tsvParseRows,
35625 tsvFormat: tsvFormat,
35626 tsvFormatRows: tsvFormatRows,
35627 easeLinear: linear$1,
35628 easeQuad: quadInOut,
35629 easeQuadIn: quadIn,
35630 easeQuadOut: quadOut,
35631 easeQuadInOut: quadInOut,
35632 easeCubic: cubicInOut,
35633 easeCubicIn: cubicIn,
35634 easeCubicOut: cubicOut,
35635 easeCubicInOut: cubicInOut,
35636 easePoly: polyInOut,
35637 easePolyIn: polyIn,
35638 easePolyOut: polyOut,
35639 easePolyInOut: polyInOut,
35642 easeSinOut: sinOut,
35643 easeSinInOut: sinInOut,
35646 easeExpOut: expOut,
35647 easeExpInOut: expInOut,
35648 easeCircle: circleInOut,
35649 easeCircleIn: circleIn,
35650 easeCircleOut: circleOut,
35651 easeCircleInOut: circleInOut,
35652 easeBounce: bounceOut,
35653 easeBounceIn: bounceIn,
35654 easeBounceOut: bounceOut,
35655 easeBounceInOut: bounceInOut,
35656 easeBack: backInOut,
35657 easeBackIn: backIn,
35658 easeBackOut: backOut,
35659 easeBackInOut: backInOut,
35660 easeElastic: elasticOut,
35661 easeElasticIn: elasticIn,
35662 easeElasticOut: elasticOut,
35663 easeElasticInOut: elasticInOut,
35664 forceCenter: center$1,
35665 forceCollide: collide,
35667 forceManyBody: manyBody,
35668 forceSimulation: simulation,
35671 formatDefaultLocale: defaultLocale,
35672 get format () { return format; },
35673 get formatPrefix () { return formatPrefix; },
35674 formatLocale: formatLocale,
35675 formatSpecifier: formatSpecifier,
35676 precisionFixed: precisionFixed,
35677 precisionPrefix: precisionPrefix,
35678 precisionRound: precisionRound,
35681 geoCentroid: d3GeoCentroid,
35683 geoClipExtent: extent$1,
35684 geoContains: contains,
35685 geoDistance: distance,
35686 geoGraticule: graticule,
35687 geoGraticule10: graticule10,
35688 geoInterpolate: interpolate$1,
35689 geoLength: d3GeoLength,
35692 geoAlbersUsa: albersUsa,
35693 geoAzimuthalEqualArea: azimuthalEqualArea,
35694 geoAzimuthalEqualAreaRaw: azimuthalEqualAreaRaw,
35695 geoAzimuthalEquidistant: azimuthalEquidistant,
35696 geoAzimuthalEquidistantRaw: azimuthalEquidistantRaw,
35697 geoConicConformal: conicConformal,
35698 geoConicConformalRaw: conicConformalRaw,
35699 geoConicEqualArea: conicEqualArea,
35700 geoConicEqualAreaRaw: conicEqualAreaRaw,
35701 geoConicEquidistant: conicEquidistant,
35702 geoConicEquidistantRaw: conicEquidistantRaw,
35703 geoEquirectangular: equirectangular,
35704 geoEquirectangularRaw: equirectangularRaw,
35705 geoGnomonic: gnomonic,
35706 geoGnomonicRaw: gnomonicRaw,
35707 geoIdentity: identity$5,
35708 geoProjection: projection,
35709 geoProjectionMutator: projectionMutator,
35710 geoMercator: mercator,
35711 geoMercatorRaw: mercatorRaw,
35712 geoOrthographic: orthographic,
35713 geoOrthographicRaw: orthographicRaw,
35714 geoStereographic: stereographic,
35715 geoStereographicRaw: stereographicRaw,
35716 geoTransverseMercator: transverseMercator,
35717 geoTransverseMercatorRaw: transverseMercatorRaw,
35718 geoRotation: rotation,
35719 geoStream: geoStream,
35720 geoTransform: transform,
35722 hierarchy: hierarchy,
35724 packSiblings: siblings,
35725 packEnclose: enclose,
35726 partition: partition,
35727 stratify: stratify,
35730 treemapBinary: binary,
35731 treemapDice: treemapDice,
35732 treemapSlice: treemapSlice,
35733 treemapSliceDice: sliceDice,
35734 treemapSquarify: squarify,
35735 treemapResquarify: resquarify,
35736 interpolate: interpolateValue,
35737 interpolateArray: array$1,
35738 interpolateBasis: basis$1,
35739 interpolateBasisClosed: basisClosed,
35740 interpolateDate: date,
35741 interpolateNumber: reinterpolate,
35742 interpolateObject: object,
35743 interpolateRound: interpolateRound,
35744 interpolateString: interpolateString,
35745 interpolateTransformCss: interpolateTransformCss,
35746 interpolateTransformSvg: interpolateTransformSvg,
35747 interpolateZoom: interpolateZoom,
35748 interpolateRgb: interpolateRgb,
35749 interpolateRgbBasis: rgbBasis,
35750 interpolateRgbBasisClosed: rgbBasisClosed,
35751 interpolateHsl: hsl$2,
35752 interpolateHslLong: hslLong,
35753 interpolateLab: lab$1,
35754 interpolateHcl: hcl$2,
35755 interpolateHclLong: hclLong,
35756 interpolateCubehelix: cubehelix$2,
35757 interpolateCubehelixLong: cubehelixLong,
35758 quantize: quantize,
35760 polygonArea: d3polygonArea,
35761 polygonCentroid: d3polygonCentroid,
35762 polygonHull: d3polygonHull,
35763 polygonContains: contains$1,
35764 polygonLength: length$1,
35765 quadtree: quadtree,
35767 randomUniform: uniform,
35768 randomNormal: normal,
35769 randomLogNormal: logNormal,
35770 randomBates: bates,
35771 randomIrwinHall: irwinHall,
35772 randomExponential: exponential$1,
35781 scalePoint: point$1,
35782 scaleIdentity: identity$6,
35783 scaleLinear: linear$2,
35785 scaleOrdinal: ordinal,
35786 scaleImplicit: implicit,
35789 scaleQuantile: quantile$$1,
35790 scaleQuantize: quantize$1,
35791 scaleThreshold: threshold$1,
35794 schemeCategory10: category10,
35795 schemeCategory20b: category20b,
35796 schemeCategory20c: category20c,
35797 schemeCategory20: category20,
35798 interpolateCubehelixDefault: cubehelix$3,
35799 interpolateRainbow: rainbow$1,
35800 interpolateWarm: warm,
35801 interpolateCool: cool,
35802 interpolateViridis: viridis,
35803 interpolateMagma: magma,
35804 interpolateInferno: inferno,
35805 interpolatePlasma: plasma,
35806 scaleSequential: sequential,
35809 matcher: matcher$1,
35811 namespace: namespace,
35812 namespaces: namespaces,
35814 selectAll: selectAll,
35815 selection: selection,
35816 selector: selector,
35817 selectorAll: selectorAll,
35821 get event () { return event; },
35822 customEvent: customEvent,
35827 radialArea: radialArea,
35828 radialLine: radialLine$1,
35831 symbolCircle: circle$2,
35832 symbolCross: cross$2,
35833 symbolDiamond: diamond,
35834 symbolSquare: square,
35836 symbolTriangle: triangle,
35838 curveBasisClosed: basisClosed$1,
35839 curveBasisOpen: basisOpen,
35840 curveBasis: basis$2,
35841 curveBundle: bundle,
35842 curveCardinalClosed: cardinalClosed,
35843 curveCardinalOpen: cardinalOpen,
35844 curveCardinal: cardinal,
35845 curveCatmullRomClosed: catmullRomClosed,
35846 curveCatmullRomOpen: catmullRomOpen,
35847 curveCatmullRom: catmullRom,
35848 curveLinearClosed: linearClosed,
35849 curveLinear: curveLinear,
35850 curveMonotoneX: monotoneX,
35851 curveMonotoneY: monotoneY,
35852 curveNatural: natural,
35854 curveStepAfter: stepAfter,
35855 curveStepBefore: stepBefore,
35857 stackOffsetExpand: expand,
35858 stackOffsetNone: none$1,
35859 stackOffsetSilhouette: silhouette,
35860 stackOffsetWiggle: wiggle,
35861 stackOrderAscending: ascending$2,
35862 stackOrderDescending: descending$2,
35863 stackOrderInsideOut: insideOut,
35864 stackOrderNone: none$2,
35865 stackOrderReverse: reverse,
35866 timeInterval: newInterval,
35867 timeMillisecond: millisecond,
35868 timeMilliseconds: milliseconds,
35869 utcMillisecond: millisecond,
35870 utcMilliseconds: milliseconds,
35871 timeSecond: second,
35872 timeSeconds: seconds,
35874 utcSeconds: seconds,
35875 timeMinute: minute,
35876 timeMinutes: minutes,
35882 timeWeeks: sundays,
35883 timeSunday: sunday,
35884 timeSundays: sundays,
35885 timeMonday: monday,
35886 timeMondays: mondays,
35887 timeTuesday: tuesday,
35888 timeTuesdays: tuesdays,
35889 timeWednesday: wednesday,
35890 timeWednesdays: wednesdays,
35891 timeThursday: thursday,
35892 timeThursdays: thursdays,
35893 timeFriday: friday,
35894 timeFridays: fridays,
35895 timeSaturday: saturday,
35896 timeSaturdays: saturdays,
35898 timeMonths: months,
35901 utcMinute: utcMinute,
35902 utcMinutes: utcMinutes,
35904 utcHours: utcHours,
35907 utcWeek: utcSunday,
35908 utcWeeks: utcSundays,
35909 utcSunday: utcSunday,
35910 utcSundays: utcSundays,
35911 utcMonday: utcMonday,
35912 utcMondays: utcMondays,
35913 utcTuesday: utcTuesday,
35914 utcTuesdays: utcTuesdays,
35915 utcWednesday: utcWednesday,
35916 utcWednesdays: utcWednesdays,
35917 utcThursday: utcThursday,
35918 utcThursdays: utcThursdays,
35919 utcFriday: utcFriday,
35920 utcFridays: utcFridays,
35921 utcSaturday: utcSaturday,
35922 utcSaturdays: utcSaturdays,
35923 utcMonth: utcMonth,
35924 utcMonths: utcMonths,
35926 utcYears: utcYears,
35927 timeFormatDefaultLocale: defaultLocale$1,
35928 get timeFormat () { return timeFormat; },
35929 get timeParse () { return timeParse; },
35930 get utcFormat () { return utcFormat; },
35931 get utcParse () { return utcParse; },
35932 timeFormatLocale: formatLocale$1,
35933 isoFormat: formatIso,
35934 isoParse: parseIso,
35937 timerFlush: timerFlush,
35938 timeout: timeout$1,
35939 interval: interval$1,
35940 transition: transition,
35942 interrupt: interrupt,
35945 zoomTransform: transform$1,
35946 zoomIdentity: identity$8
35950 Bypasses features of D3's default projection stream pipeline that are unnecessary:
35951 * Antimeridian clipping
35952 * Spherical rotation
35955 function geoRawMercator() {
35956 var project = mercatorRaw,
35957 k = 512 / Math.PI, // scale
35958 x = 0, y = 0, // translate
35959 clipExtent = [[0, 0], [0, 0]];
35962 function projection(point) {
35963 point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
35964 return [point[0] * k + x, y - point[1] * k];
35968 projection.invert = function(point) {
35969 point = project.invert((point[0] - x) / k, (y - point[1]) / k);
35970 return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
35974 projection.scale = function(_) {
35975 if (!arguments.length) return k;
35981 projection.translate = function(_) {
35982 if (!arguments.length) return [x, y];
35989 projection.clipExtent = function(_) {
35990 if (!arguments.length) return clipExtent;
35996 projection.transform = function(_) {
35997 if (!arguments.length) return identity$8.translate(x, y).scale(k);
36005 projection.stream = transform({
36006 point: function(x, y) {
36007 x = projection([x, y]);
36008 this.stream.point(x[0], x[1]);
36016 function osmChangeset() {
36017 if (!(this instanceof osmChangeset)) {
36018 return (new osmChangeset()).initialize(arguments);
36019 } else if (arguments.length) {
36020 this.initialize(arguments);
36025 osmEntity$$1.changeset = osmChangeset;
36027 osmChangeset.prototype = Object.create(osmEntity$$1.prototype);
36029 lodash.extend(osmChangeset.prototype, {
36034 extent: function() {
36035 return new geoExtent$$1();
36039 geometry: function() {
36040 return 'changeset';
36044 asJXON: function() {
36048 tag: lodash.map(this.tags, function(value, key) {
36049 return { '@k': key, '@v': value };
36059 // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
36060 // XML. Returns a string.
36061 osmChangeJXON: function(changes) {
36062 var changeset_id = this.id;
36064 function nest(x, order) {
36066 for (var i = 0; i < x.length; i++) {
36067 var tagName = Object.keys(x[i])[0];
36068 if (!groups[tagName]) groups[tagName] = [];
36069 groups[tagName].push(x[i][tagName]);
36072 order.forEach(function(o) {
36073 if (groups[o]) ordered[o] = groups[o];
36079 // sort relations in a changeset by dependencies
36080 function sort(changes) {
36082 // find a referenced relation in the current changeset
36083 function resolve(item) {
36084 return lodash.find(relations, function(relation) {
36085 return item.keyAttributes.type === 'relation'
36086 && item.keyAttributes.ref === relation['@id'];
36090 // a new item is an item that has not been already processed
36091 function isNew(item) {
36092 return !sorted[ item['@id'] ] && !lodash.find(processing, function(proc) {
36093 return proc['@id'] === item['@id'];
36097 var processing = [],
36099 relations = changes.relation;
36101 if (!relations) return changes;
36103 for (var i = 0; i < relations.length; i++) {
36104 var relation = relations[i];
36106 // skip relation if already sorted
36107 if (!sorted[relation['@id']]) {
36108 processing.push(relation);
36111 while (processing.length > 0) {
36112 var next = processing[0],
36113 deps = lodash.filter(lodash.compact(next.member.map(resolve)), isNew);
36114 if (deps.length === 0) {
36115 sorted[next['@id']] = next;
36116 processing.shift();
36118 processing = deps.concat(processing);
36123 changes.relation = lodash.values(sorted);
36127 function rep(entity) {
36128 return entity.asJXON(changeset_id);
36134 '@generator': 'iD',
36135 'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])),
36136 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
36137 'delete': lodash.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), { '@if-unused': true })
36143 asGeoJSON: function() {
36149 function osmNode() {
36150 if (!(this instanceof osmNode)) {
36151 return (new osmNode()).initialize(arguments);
36152 } else if (arguments.length) {
36153 this.initialize(arguments);
36157 osmEntity$$1.node = osmNode;
36159 osmNode.prototype = Object.create(osmEntity$$1.prototype);
36161 lodash.extend(osmNode.prototype, {
36166 extent: function() {
36167 return new geoExtent$$1(this.loc);
36171 geometry: function(graph) {
36172 return graph.transient(this, 'geometry', function() {
36173 return graph.isPoi(this) ? 'point' : 'vertex';
36178 move: function(loc) {
36179 return this.update({loc: loc});
36183 isDegenerate: function() {
36185 Array.isArray(this.loc) && this.loc.length === 2 &&
36186 this.loc[0] >= -180 && this.loc[0] <= 180 &&
36187 this.loc[1] >= -90 && this.loc[1] <= 90
36192 isEndpoint: function(resolver) {
36193 return resolver.transient(this, 'isEndpoint', function() {
36195 return resolver.parentWays(this).filter(function(parent) {
36196 return !parent.isClosed() && !!parent.affix(id);
36202 isConnected: function(resolver) {
36203 return resolver.transient(this, 'isConnected', function() {
36204 var parents = resolver.parentWays(this);
36206 function isLine(entity) {
36207 return entity.geometry(resolver) === 'line' &&
36208 entity.hasInterestingTags();
36211 // vertex is connected to multiple parent lines
36212 if (parents.length > 1 && lodash.some(parents, isLine)) {
36215 } else if (parents.length === 1) {
36216 var way = parents[0],
36217 nodes = way.nodes.slice();
36218 if (way.isClosed()) { nodes.pop(); } // ignore connecting node if closed
36220 // return true if vertex appears multiple times (way is self intersecting)
36221 return nodes.indexOf(this.id) !== nodes.lastIndexOf(this.id);
36229 isIntersection: function(resolver) {
36230 return resolver.transient(this, 'isIntersection', function() {
36231 return resolver.parentWays(this).filter(function(parent) {
36232 return (parent.tags.highway ||
36233 parent.tags.waterway ||
36234 parent.tags.railway ||
36235 parent.tags.aeroway) &&
36236 parent.geometry(resolver) === 'line';
36242 isHighwayIntersection: function(resolver) {
36243 return resolver.transient(this, 'isHighwayIntersection', function() {
36244 return resolver.parentWays(this).filter(function(parent) {
36245 return parent.tags.highway && parent.geometry(resolver) === 'line';
36251 isOnAddressLine: function(resolver) {
36252 return resolver.transient(this, 'isOnAddressLine', function() {
36253 return resolver.parentWays(this).filter(function(parent) {
36254 return parent.tags.hasOwnProperty('addr:interpolation') &&
36255 parent.geometry(resolver) === 'line';
36261 asJXON: function(changeset_id) {
36264 '@id': this.osmId(),
36265 '@lon': this.loc[0],
36266 '@lat': this.loc[1],
36267 '@version': (this.version || 0),
36268 tag: lodash.map(this.tags, function(v, k) {
36269 return { keyAttributes: { k: k, v: v } };
36273 if (changeset_id) r.node['@changeset'] = changeset_id;
36278 asGeoJSON: function() {
36281 coordinates: this.loc
36287 Order the nodes of a way in reverse order and reverse any direction dependent tags
36288 other than `oneway`. (We assume that correcting a backwards oneway is the primary
36289 reason for reversing a way.)
36291 The following transforms are performed:
36294 *:right=* ⟺ *:left=*
36295 *:forward=* ⟺ *:backward=*
36296 direction=up ⟺ direction=down
36297 incline=up ⟺ incline=down
36301 role=forward ⟺ role=backward
36302 role=north ⟺ role=south
36303 role=east ⟺ role=west
36305 In addition, numeric-valued `incline` tags are negated.
36307 The JOSM implementation was used as a guide, but transformations that were of unclear benefit
36308 or adjusted tags that don't seem to be used in practice were omitted.
36310 Also, each node on the way is examined for its own tags and the following transformations are performed
36311 in order to ensure associated nodes (eg a Stop Sign) is also reversed
36314 direction=forward ⟺ direction=backward
36315 direction=left ⟺ direction=right
36316 *:forward=* ⟺ *:backward=*
36317 *:left=* ⟺ *:right=*
36320 http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
36321 http://wiki.openstreetmap.org/wiki/Key:direction#Steps
36322 http://wiki.openstreetmap.org/wiki/Key:incline
36323 http://wiki.openstreetmap.org/wiki/Route#Members
36324 http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
36325 http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
36326 http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
36328 function actionReverse(wayId, options) {
36329 var replacements = [
36330 [/:right$/, ':left'], [/:left$/, ':right'],
36331 [/:forward$/, ':backward'], [/:backward$/, ':forward']
36333 numeric = /^([+\-]?)(?=[\d.])/,
36335 forward: 'backward',
36336 backward: 'forward',
36344 function reverseKey(key) {
36345 for (var i = 0; i < replacements.length; ++i) {
36346 var replacement = replacements[i];
36347 if (replacement[0].test(key)) {
36348 return key.replace(replacement[0], replacement[1]);
36355 function reverseValue(key, value) {
36356 if (key === 'incline' && numeric.test(value)) {
36357 return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
36358 } else if (key === 'incline' || key === 'direction') {
36359 return {up: 'down', down: 'up'}[value] || value;
36360 } else if (options && options.reverseOneway && key === 'oneway') {
36361 return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
36363 return {left: 'right', right: 'left'}[value] || value;
36368 function reverseDirectionTags(node) {
36369 // Update the direction based tags as appropriate then return an updated node
36370 return node.update({tags: lodash.transform(node.tags, function(acc, tagValue, tagKey) {
36371 // See if this is a direction tag and reverse (or use existing value if not recognised)
36372 if (tagKey === 'direction') {
36373 acc[tagKey] = {forward: 'backward', backward: 'forward', left: 'right', right: 'left'}[tagValue] || tagValue;
36375 // Use the reverseKey method to cater for situations such as traffic_sign:forward=stop
36376 // This will pass through other tags unchanged
36377 acc[reverseKey(tagKey)] = tagValue;
36384 function reverseTagsOnNodes(graph, nodeIds) {
36385 // Reverse the direction of appropriate tags attached to the nodes (#3076)
36386 return lodash(nodeIds)
36387 // Get each node from the graph
36388 .map(function(nodeId) { return graph.entity(nodeId);})
36389 // Check tags on the node, if there aren't any, we can skip
36390 .filter(function(existingNode) { return existingNode.tags !== undefined;})
36391 // Get a new version of each node with the appropriate tags reversed
36392 .map(function(existingNode) { return reverseDirectionTags(existingNode);})
36393 // Chain together consecutive updates to the graph for each updated node and return
36394 .reduce(function (accGraph, value) { return accGraph.replace(value); }, graph);
36398 return function(graph) {
36399 var way = graph.entity(wayId),
36400 nodes = way.nodes.slice().reverse(),
36401 tags = {}, key, role;
36403 for (key in way.tags) {
36404 tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
36407 graph.parentRelations(way).forEach(function(relation) {
36408 relation.members.forEach(function(member, index) {
36409 if (member.id === way.id && (role = roleReversals[member.role])) {
36410 relation = relation.updateMember({role: role}, index);
36411 graph = graph.replace(relation);
36416 // Reverse any associated directions on nodes on the way and then replace
36417 // the way itself with the reversed node ids and updated way tags
36418 return reverseTagsOnNodes(graph, nodes).replace(way.update({nodes: nodes, tags: tags}));
36422 // For fixing up rendering of multipolygons with tags on the outer member.
36423 // https://github.com/openstreetmap/iD/issues/613
36424 function osmIsSimpleMultipolygonOuterMember(entity, graph) {
36425 if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0)
36428 var parents = graph.parentRelations(entity);
36429 if (parents.length !== 1)
36432 var parent = parents[0];
36433 if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
36436 var members = parent.members, member;
36437 for (var i = 0; i < members.length; i++) {
36438 member = members[i];
36439 if (member.id === entity.id && member.role && member.role !== 'outer')
36440 return false; // Not outer member
36441 if (member.id !== entity.id && (!member.role || member.role === 'outer'))
36442 return false; // Not a simple multipolygon
36449 function osmSimpleMultipolygonOuterMember(entity, graph) {
36450 if (entity.type !== 'way')
36453 var parents = graph.parentRelations(entity);
36454 if (parents.length !== 1)
36457 var parent = parents[0];
36458 if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
36461 var members = parent.members, member, outerMember;
36462 for (var i = 0; i < members.length; i++) {
36463 member = members[i];
36464 if (!member.role || member.role === 'outer') {
36466 return false; // Not a simple multipolygon
36467 outerMember = member;
36474 var outerEntity = graph.hasEntity(outerMember.id);
36475 if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length)
36478 return outerEntity;
36482 // Join `array` into sequences of connecting ways.
36484 // Segments which share identical start/end nodes will, as much as possible,
36485 // be connected with each other.
36487 // The return value is a nested array. Each constituent array contains elements
36488 // of `array` which have been determined to connect. Each consitituent array
36489 // also has a `nodes` property whose value is an ordered array of member nodes,
36490 // with appropriate order reversal and start/end coordinate de-duplication.
36492 // Members of `array` must have, at minimum, `type` and `id` properties.
36493 // Thus either an array of `osmWay`s or a relation member array may be
36496 // If an member has a `tags` property, its tags will be reversed via
36497 // `actionReverse` in the output.
36499 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
36500 // false) and non-way members are ignored.
36502 function osmJoinWays(array, graph) {
36503 var joined = [], member, current, nodes, first, last, i, how, what;
36505 array = array.filter(function(member) {
36506 return member.type === 'way' && graph.hasEntity(member.id);
36509 function resolve(member) {
36510 return graph.childNodes(graph.entity(member.id));
36513 function reverse(member) {
36514 return member.tags ? actionReverse(member.id, { reverseOneway: true })(graph).entity(member.id) : member;
36517 while (array.length) {
36518 member = array.shift();
36519 current = [member];
36520 current.nodes = nodes = resolve(member).slice();
36521 joined.push(current);
36523 while (array.length && lodash.first(nodes) !== lodash.last(nodes)) {
36524 first = lodash.first(nodes);
36525 last = lodash.last(nodes);
36527 for (i = 0; i < array.length; i++) {
36529 what = resolve(member);
36531 if (last === lodash.first(what)) {
36533 what = what.slice(1);
36535 } else if (last === lodash.last(what)) {
36537 what = what.slice(0, -1).reverse();
36538 member = reverse(member);
36540 } else if (first === lodash.last(what)) {
36541 how = nodes.unshift;
36542 what = what.slice(0, -1);
36544 } else if (first === lodash.first(what)) {
36545 how = nodes.unshift;
36546 what = what.slice(1).reverse();
36547 member = reverse(member);
36555 break; // No more joinable ways.
36557 how.apply(current, [member]);
36558 how.apply(nodes, what);
36560 array.splice(i, 1);
36567 function osmRelation() {
36568 if (!(this instanceof osmRelation)) {
36569 return (new osmRelation()).initialize(arguments);
36570 } else if (arguments.length) {
36571 this.initialize(arguments);
36576 osmEntity$$1.relation = osmRelation;
36578 osmRelation.prototype = Object.create(osmEntity$$1.prototype);
36581 osmRelation.creationOrder = function(a, b) {
36582 var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10);
36583 var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10);
36585 if (aId < 0 || bId < 0) return aId - bId;
36590 lodash.extend(osmRelation.prototype, {
36595 copy: function(resolver, copies) {
36596 if (copies[this.id])
36597 return copies[this.id];
36599 var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
36601 var members = this.members.map(function(member) {
36602 return lodash.extend({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id });
36605 copy = copy.update({members: members});
36606 copies[this.id] = copy;
36612 extent: function(resolver, memo) {
36613 return resolver.transient(this, 'extent', function() {
36614 if (memo && memo[this.id]) return geoExtent$$1();
36616 memo[this.id] = true;
36618 var extent$$1 = geoExtent$$1();
36619 for (var i = 0; i < this.members.length; i++) {
36620 var member = resolver.hasEntity(this.members[i].id);
36622 extent$$1._extend(member.extent(resolver, memo));
36630 geometry: function(graph) {
36631 return graph.transient(this, 'geometry', function() {
36632 return this.isMultipolygon() ? 'area' : 'relation';
36637 isDegenerate: function() {
36638 return this.members.length === 0;
36642 // Return an array of members, each extended with an 'index' property whose value
36643 // is the member index.
36644 indexedMembers: function() {
36645 var result = new Array(this.members.length);
36646 for (var i = 0; i < this.members.length; i++) {
36647 result[i] = lodash.extend({}, this.members[i], {index: i});
36653 // Return the first member with the given role. A copy of the member object
36654 // is returned, extended with an 'index' property whose value is the member index.
36655 memberByRole: function(role) {
36656 for (var i = 0; i < this.members.length; i++) {
36657 if (this.members[i].role === role) {
36658 return lodash.extend({}, this.members[i], {index: i});
36664 // Return the first member with the given id. A copy of the member object
36665 // is returned, extended with an 'index' property whose value is the member index.
36666 memberById: function(id) {
36667 for (var i = 0; i < this.members.length; i++) {
36668 if (this.members[i].id === id) {
36669 return lodash.extend({}, this.members[i], {index: i});
36675 // Return the first member with the given id and role. A copy of the member object
36676 // is returned, extended with an 'index' property whose value is the member index.
36677 memberByIdAndRole: function(id, role) {
36678 for (var i = 0; i < this.members.length; i++) {
36679 if (this.members[i].id === id && this.members[i].role === role) {
36680 return lodash.extend({}, this.members[i], {index: i});
36686 addMember: function(member, index) {
36687 var members = this.members.slice();
36688 members.splice(index === undefined ? members.length : index, 0, member);
36689 return this.update({members: members});
36693 updateMember: function(member, index) {
36694 var members = this.members.slice();
36695 members.splice(index, 1, lodash.extend({}, members[index], member));
36696 return this.update({members: members});
36700 removeMember: function(index) {
36701 var members = this.members.slice();
36702 members.splice(index, 1);
36703 return this.update({members: members});
36707 removeMembersWithID: function(id) {
36708 var members = lodash.reject(this.members, function(m) { return m.id === id; });
36709 return this.update({members: members});
36713 // Wherever a member appears with id `needle.id`, replace it with a member
36714 // with id `replacement.id`, type `replacement.type`, and the original role,
36715 // unless a member already exists with that id and role. Return an updated
36717 replaceMember: function(needle, replacement) {
36718 if (!this.memberById(needle.id))
36723 for (var i = 0; i < this.members.length; i++) {
36724 var member = this.members[i];
36725 if (member.id !== needle.id) {
36726 members.push(member);
36727 } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
36728 members.push({id: replacement.id, type: replacement.type, role: member.role});
36732 return this.update({members: members});
36736 asJXON: function(changeset_id) {
36739 '@id': this.osmId(),
36740 '@version': this.version || 0,
36741 member: lodash.map(this.members, function(member) {
36746 ref: osmEntity$$1.id.toOSM(member.id)
36750 tag: lodash.map(this.tags, function(v, k) {
36751 return { keyAttributes: { k: k, v: v } };
36755 if (changeset_id) r.relation['@changeset'] = changeset_id;
36760 asGeoJSON: function(resolver) {
36761 return resolver.transient(this, 'GeoJSON', function () {
36762 if (this.isMultipolygon()) {
36764 type: 'MultiPolygon',
36765 coordinates: this.multipolygon(resolver)
36769 type: 'FeatureCollection',
36770 properties: this.tags,
36771 features: this.members.map(function (member) {
36772 return lodash.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
36780 area: function(resolver) {
36781 return resolver.transient(this, 'area', function() {
36782 return area(this.asGeoJSON(resolver));
36787 isMultipolygon: function() {
36788 return this.tags.type === 'multipolygon';
36792 isComplete: function(resolver) {
36793 for (var i = 0; i < this.members.length; i++) {
36794 if (!resolver.hasEntity(this.members[i].id)) {
36802 isRestriction: function() {
36803 return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
36807 // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
36808 // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
36810 // This corresponds to the structure needed for rendering a multipolygon path using a
36811 // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
36813 // In the case of invalid geometries, this function will still return a result which
36814 // includes the nodes of all way members, but some Nds may be unclosed and some inner
36815 // rings not matched with the intended outer ring.
36817 multipolygon: function(resolver) {
36818 var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
36819 inners = this.members.filter(function(m) { return 'inner' === m.role; });
36821 outers = osmJoinWays(outers, resolver);
36822 inners = osmJoinWays(inners, resolver);
36824 outers = outers.map(function(outer) { return lodash.map(outer.nodes, 'loc'); });
36825 inners = inners.map(function(inner) { return lodash.map(inner.nodes, 'loc'); });
36827 var result = outers.map(function(o) {
36828 // Heuristic for detecting counterclockwise winding order. Assumes
36829 // that OpenStreetMap polygons are not hemisphere-spanning.
36830 return [area({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o];
36833 function findOuter(inner) {
36836 for (o = 0; o < outers.length; o++) {
36838 if (geoPolygonContainsPolygon(outer, inner))
36842 for (o = 0; o < outers.length; o++) {
36844 if (geoPolygonIntersectsPolygon(outer, inner, false))
36849 for (var i = 0; i < inners.length; i++) {
36850 var inner = inners[i];
36852 if (area({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) {
36853 inner = inner.reverse();
36856 var o = findOuter(inners[i]);
36857 if (o !== undefined)
36858 result[o].push(inners[i]);
36860 result.push([inners[i]]); // Invalid geometry
36867 function osmLanes(entity) {
36868 if (entity.type !== 'way') return null;
36869 if (!entity.tags.highway) return null;
36871 var tags = entity.tags;
36872 var isOneWay = entity.isOneWay();
36873 var laneCount = getLaneCount(tags, isOneWay);
36874 var maxspeed = parseMaxspeed(tags);
36876 var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
36877 var forward = laneDirections.forward;
36878 var backward = laneDirections.backward;
36879 var bothways = laneDirections.bothways;
36881 // parse the piped string 'x|y|z' format
36882 var turnLanes = {};
36883 turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
36884 turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
36885 turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
36887 var maxspeedLanes = {};
36888 maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
36889 maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
36890 maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
36893 psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
36894 psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
36895 psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
36898 busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
36899 busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
36900 busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
36902 var taxiLanes = {};
36903 taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
36904 taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
36905 taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
36908 hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
36909 hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
36910 hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
36913 hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
36914 hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
36915 hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
36917 var bicyclewayLanes = {};
36918 bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
36919 bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
36920 bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
36928 // map forward/backward/unspecified of each lane type to lanesObj
36929 mapToLanesObj(lanesObj, turnLanes, 'turnLane');
36930 mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
36931 mapToLanesObj(lanesObj, psvLanes, 'psv');
36932 mapToLanesObj(lanesObj, busLanes, 'bus');
36933 mapToLanesObj(lanesObj, taxiLanes, 'taxi');
36934 mapToLanesObj(lanesObj, hovLanes, 'hov');
36935 mapToLanesObj(lanesObj, hgvLanes, 'hgv');
36936 mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
36943 backward: backward,
36944 bothways: bothways,
36945 turnLanes: turnLanes,
36946 maxspeed: maxspeed,
36947 maxspeedLanes: maxspeedLanes,
36948 psvLanes: psvLanes,
36949 busLanes: busLanes,
36950 taxiLanes: taxiLanes,
36951 hovLanes: hovLanes,
36952 hgvLanes: hgvLanes,
36953 bicyclewayLanes: bicyclewayLanes
36960 function getLaneCount(tags, isOneWay) {
36963 count = parseInt(tags.lanes, 10);
36970 switch (tags.highway) {
36973 count = isOneWay ? 2 : 4;
36976 count = isOneWay ? 1 : 2;
36984 function parseMaxspeed(tags) {
36985 var maxspeed = tags.maxspeed;
36986 if (lodash.isNumber(maxspeed)) return maxspeed;
36987 if (lodash.isString(maxspeed)) {
36988 maxspeed = maxspeed.match(/^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/g);
36989 if (!maxspeed) return;
36990 return parseInt(maxspeed, 10);
36995 function parseLaneDirections(tags, isOneWay, laneCount) {
36996 var forward = parseInt(tags['lanes:forward'], 10);
36997 var backward = parseInt(tags['lanes:backward'], 10);
36998 var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
37000 if (parseInt(tags.oneway, 10) === -1) {
37003 backward = laneCount;
37005 else if (isOneWay) {
37006 forward = laneCount;
37010 else if (lodash.isNaN(forward) && lodash.isNaN(backward)) {
37011 backward = Math.floor((laneCount - bothways) / 2);
37012 forward = laneCount - bothways - backward;
37014 else if (lodash.isNaN(forward)) {
37015 if (backward > laneCount - bothways) {
37016 backward = laneCount - bothways;
37018 forward = laneCount - bothways - backward;
37020 else if (lodash.isNaN(backward)) {
37021 if (forward > laneCount - bothways) {
37022 forward = laneCount - bothways;
37024 backward = laneCount - bothways - forward;
37028 backward: backward,
37034 function parseTurnLanes(tag){
37037 var validValues = [
37038 'left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right',
37039 'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'
37042 return tag.split('|')
37043 .map(function (s) {
37044 if (s === '') s = 'none';
37045 return s.split(';')
37046 .map(function (d) {
37047 return validValues.indexOf(d) === -1 ? 'unknown': d;
37053 function parseMaxspeedLanes(tag, maxspeed) {
37056 return tag.split('|')
37057 .map(function (s) {
37058 if (s === 'none') return s;
37059 var m = parseInt(s, 10);
37060 if (s === '' || m === maxspeed) return null;
37061 return lodash.isNaN(m) ? 'unknown': m;
37066 function parseMiscLanes(tag) {
37069 var validValues = [
37070 'yes', 'no', 'designated'
37073 return tag.split('|')
37074 .map(function (s) {
37075 if (s === '') s = 'no';
37076 return validValues.indexOf(s) === -1 ? 'unknown': s;
37081 function parseBicycleWay(tag) {
37084 var validValues = [
37085 'yes', 'no', 'designated', 'lane'
37088 return tag.split('|')
37089 .map(function (s) {
37090 if (s === '') s = 'no';
37091 return validValues.indexOf(s) === -1 ? 'unknown': s;
37096 function mapToLanesObj(lanesObj, data, key) {
37097 if (data.forward) data.forward.forEach(function(l, i) {
37098 if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
37099 lanesObj.forward[i][key] = l;
37101 if (data.backward) data.backward.forEach(function(l, i) {
37102 if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
37103 lanesObj.backward[i][key] = l;
37105 if (data.unspecified) data.unspecified.forEach(function(l, i) {
37106 if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
37107 lanesObj.unspecified[i][key] = l;
37111 var translations = Object.create(null);
37113 var currentLocale = 'en';
37114 var textDirection = 'ltr';
37116 function setLocale(_) {
37117 if (translations[_] !== undefined) {
37119 } else if (translations[_.split('-')[0]]) {
37120 currentLocale = _.split('-')[0];
37124 function addTranslation(id, value) {
37125 translations[id] = value;
37129 * Given a string identifier, try to find that string in the current
37130 * language, and return it.
37132 * @param {string} s string identifier
37133 * @returns {string?} locale string
37135 function t(s, o, loc) {
37136 loc = loc || currentLocale;
37138 var path = s.split('.').reverse();
37139 var rep = translations[loc];
37141 while (rep !== undefined && path.length) rep = rep[path.pop()];
37143 if (rep !== undefined) {
37144 if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
37148 if (loc !== 'en') {
37149 return t(s, o, 'en');
37152 if (o && 'default' in o) {
37156 var missing = 'Missing ' + loc + ' translation: ' + s;
37157 if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
37163 * Given string 'ltr' or 'rtl', save that setting
37165 * @param {string} s ltr or rtl
37168 function setTextDirection(dir) {
37169 textDirection = dir;
37174 function utilDetect(force) {
37175 if (detected && !force) return detected;
37178 var ua = navigator.userAgent,
37181 m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i); // Edge
37183 detected.browser = m[1];
37184 detected.version = m[2];
37186 if (!detected.browser) {
37187 m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11
37189 detected.browser = 'msie';
37190 detected.version = m[1];
37193 if (!detected.browser) {
37194 m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i); // Opera 15+
37196 detected.browser = 'Opera';
37197 detected.version = m[2];
37200 if (!detected.browser) {
37201 m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
37203 detected.browser = m[1];
37204 detected.version = m[2];
37205 m = ua.match(/version\/([\.\d]+)/i);
37206 if (m !== null) detected.version = m[1];
37209 if (!detected.browser) {
37210 detected.browser = navigator.appName;
37211 detected.version = navigator.appVersion;
37214 // keep major.minor version only..
37215 detected.version = detected.version.split(/\W/).slice(0,2).join('.');
37217 if (detected.browser.toLowerCase() === 'msie') {
37218 detected.ie = true;
37219 detected.browser = 'Internet Explorer';
37220 detected.support = parseFloat(detected.version) >= 11;
37222 detected.ie = false;
37223 detected.support = true;
37226 // Added due to incomplete svg style support. See #715
37227 detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
37229 detected.locale = (navigator.language || navigator.userLanguage || 'en-US');
37230 detected.language = detected.locale.split('-')[0];
37232 // Search `navigator.languages` for a better locale.. Prefer the first language,
37233 // unless the second language is a culture-specific version of the first one, see #3842
37234 if (navigator.languages && navigator.languages.length > 0) {
37235 var code0 = navigator.languages[0],
37236 parts0 = code0.split('-');
37238 detected.locale = code0;
37239 detected.language = parts0[0];
37241 if (navigator.languages.length > 1 && parts0.length === 1) {
37242 var code1 = navigator.languages[1],
37243 parts1 = code1.split('-');
37245 if (parts1[0] === parts0[0]) {
37246 detected.locale = code1;
37251 // Loaded locale is stored in currentLocale
37252 // return that instead (except in the situation where 'en' might override 'en-US')
37253 var loadedLocale = currentLocale || 'en';
37254 if (loadedLocale !== 'en') {
37255 detected.locale = loadedLocale;
37256 detected.language = detected.locale.split('-')[0];
37259 // detect text direction
37260 var q = utilStringQs(window.location.hash.substring(1));
37261 var lang = dataLocales[detected.locale];
37262 if ((lang && lang.rtl) || q.hasOwnProperty('rtl')) {
37263 detected.textDirection = 'rtl';
37265 detected.textDirection = 'ltr';
37267 setTextDirection(detected.textDirection);
37270 var loc = window.top.location;
37271 var origin = loc.origin;
37272 if (!origin) { // for unpatched IE11
37273 origin = loc.protocol + '//' + loc.hostname + (loc.port ? ':' + loc.port: '');
37276 detected.host = origin + loc.pathname;
37278 detected.filedrop = (window.FileReader && 'ondrop' in window);
37281 return navigator.userAgent.indexOf(x) !== -1;
37285 detected.os = 'win';
37286 detected.platform = 'Windows';
37288 else if (nav('Mac')) {
37289 detected.os = 'mac';
37290 detected.platform = 'Macintosh';
37292 else if (nav('X11') || nav('Linux')) {
37293 detected.os = 'linux';
37294 detected.platform = 'Linux';
37297 detected.os = 'win';
37298 detected.platform = 'Unknown';
37304 var remove$1 = removeDiacritics;
37306 var replacementList = [
37315 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",
37321 chars: "\u00C6\u01FC\u01E2",
37330 chars: "\uA738\uA73A",
37336 chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181",
37339 chars: "\u24b8\uff23\uA73E\u1E08\u0106\u0043\u0108\u010A\u010C\u00C7\u0187\u023B",
37342 chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779",
37348 chars: "\u01F1\u01C4",
37351 chars: "\u01F2\u01C5",
37354 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",
37357 chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B",
37360 chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262",
37363 chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D",
37366 chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197",
37369 chars: "\u24BF\uFF2A\u0134\u0248\u0237",
37372 chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2",
37375 chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780",
37384 chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB",
37387 chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E",
37396 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",
37411 chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754",
37414 chars: "\u24C6\uFF31\uA756\uA758\u024A",
37417 chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782",
37420 chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784",
37423 chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786",
37432 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",
37435 chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245",
37441 chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72",
37444 chars: "\u24CD\uFF38\u1E8A\u1E8C",
37447 chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE",
37450 chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762",
37453 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",
37459 chars: "\u00E6\u01FD\u01E3",
37468 chars: "\uA739\uA73B",
37474 chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182",
37477 chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184",
37480 chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA",
37486 chars: "\u01F3\u01C6",
37489 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",
37492 chars: "\u24D5\uFF46\u1E1F\u0192",
37510 chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79",
37513 chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265",
37519 chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131",
37522 chars: "\u24D9\uFF4A\u0135\u01F0\u0249",
37525 chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3",
37528 chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D",
37534 chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F",
37537 chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509",
37543 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",
37558 chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1",
37561 chars: "\u24E0\uFF51\u024B\uA757\uA759",
37564 chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783",
37567 chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282",
37573 chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787",
37582 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",
37585 chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C",
37591 chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73",
37594 chars: "\u24E7\uFF58\u1E8B\u1E8D",
37597 chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF",
37600 chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763",
37604 var diacriticsMap = {};
37605 for (var i = 0; i < replacementList.length; i += 1) {
37606 var chars = replacementList[i].chars;
37607 for (var j = 0; j < chars.length; j += 1) {
37608 diacriticsMap[chars[j]] = replacementList[i].base;
37612 function removeDiacritics(str) {
37613 return str.replace(/[^\u0000-\u007e]/g, function(c) {
37614 return diacriticsMap[c] || c;
37618 // see https://github.com/openstreetmap/iD/pull/3707
37619 // https://gist.github.com/mapmeld/556b09ddec07a2044c76e1ef45f01c60
37622 // madda above alef
37623 1570: { initial: 'آ', isolated: 'ﺁ', medial: 'ﺁ', final: 'ﺂ' },
37625 // hamza above and below alef
37626 1571: { initial: 'أ', isolated: 'ﺃ', medial: '', final: 'ﺄ' },
37628 1573: { initial: 'إ', isolated: 'ﺇ', medial: '', final: 'ﺈ' },
37630 1575: { initial: 'ا', isolated: 'ا', medial: '', final: 'ﺎ' },
37631 1576: { initial: 'ﺑ', isolated: 'ﺏ', medial: 'ﺒ', final: 'ﺐ' },
37634 1577: { initial: '', isolated: 'ة', medial: '', final: 'ﺔ' },
37636 1578: { initial: 'ﺗ', isolated: 'ﺕ', medial: 'ﺘ', final: 'ﺖ' },
37637 1579: { initial: 'ﺛ', isolated: 'ﺙ', medial: 'ﺜ', final: 'ﺚ' },
37638 1580: { initial: 'ﺟ', isolated: 'ﺝ', medial: 'ﺠ', final: 'ﺞ' },
37639 1581: { initial: 'ﺣ', isolated: 'ﺡ', medial: 'ﺤ', final: 'ﺢ' },
37640 1582: { initial: 'ﺧ', isolated: 'ﺥ', medial: 'ﺨ', final: 'ﺦ' },
37641 1583: { initial: 'ﺩ', isolated: 'ﺩ', medial: '', final: 'ﺪ' },
37642 1584: { initial: 'ﺫ', isolated: 'ﺫ', medial: '', final: 'ﺬ' },
37643 1585: { initial: 'ﺭ', isolated: 'ﺭ', medial: '', final: 'ﺮ' },
37644 1586: { initial: 'ﺯ', isolated: 'ﺯ', medial: '', final: 'ﺰ' },
37645 1688: { initial: 'ﮊ', isolated: 'ﮊ', medial: '', final: 'ﮋ' },
37646 1587: { initial: 'ﺳ', isolated: 'ﺱ', medial: 'ﺴ', final: 'ﺲ' },
37647 1588: { initial: 'ﺷ', isolated: 'ﺵ', medial: 'ﺸ', final: 'ﺶ' },
37648 1589: { initial: 'ﺻ', isolated: 'ﺹ', medial: 'ﺼ', final: 'ﺺ' },
37649 1590: { initial: 'ﺿ', isolated: 'ﺽ', medial: 'ﻀ', final: 'ﺾ' },
37650 1591: { initial: 'ﻃ', isolated: 'ﻁ', medial: 'ﻄ', final: 'ﻂ' },
37651 1592: { initial: 'ﻇ', isolated: 'ﻅ', medial: 'ﻈ', final: 'ﻆ' },
37652 1593: { initial: 'ﻋ', isolated: 'ﻉ', medial: 'ﻌ', final: 'ﻊ' },
37653 1594: { initial: 'ﻏ', isolated: 'ﻍ', medial: 'ﻐ', final: 'ﻎ' },
37655 // 1595 ػ - may be very rare
37657 1601: { initial: 'ﻓ', isolated: 'ﻑ', medial: 'ﻔ', final: 'ﻒ' },
37658 1602: { initial: 'ﻗ', isolated: 'ﻕ', medial: 'ﻘ', final: 'ﻖ' },
37659 1604: { initial: 'ﻟ', isolated: 'ﻝ', medial: 'ﻠ', final: 'ﻞ' },
37660 1605: { initial: 'ﻣ', isolated: 'ﻡ', medial: 'ﻤ', final: 'ﻢ' },
37661 1606: { initial: 'ﻧ', isolated: 'ﻥ', medial: 'ﻨ', final: 'ﻦ' },
37662 1607: { initial: 'ﻫ', isolated: 'ﻩ', medial: 'ﻬ', final: 'ﻪ' },
37663 1608: { initial: 'ﻭ', isolated: 'ﻭ', medial: '', final: 'ﻮ' },
37666 1609: { initial: 'ﯨ', isolated: 'ﻯ', medial: 'ﯩ', final: 'ﻰ' },
37668 1610: { initial: 'ﻳ', isolated: 'ﻱ', medial: 'ﻴ', final: 'ﻲ' },
37670 // short vowel sounds / tashkil markings
37672 1662: { initial: 'ﭘ', isolated: 'ﭖ', medial: 'ﭙ', final: 'ﭗ' },
37674 1670: { initial: 'ﭼ', isolated: 'ﭺ', medial: 'ﭽ', final: 'ﭻ' },
37675 1603: { initial: 'ﻛ', isolated: 'ﻙ', medial: 'ﻜ', final: 'ﻚ' },
37676 1705: { initial: 'ﻛ', isolated: 'ﮎ', medial: 'ﻜ', final: 'ﮏ' },
37677 1711: { initial: 'ﮔ', isolated: 'ﮒ', medial: 'ﮕ', final: 'ﮓ' },
37678 1740: { initial: 'ﻳ', isolated: 'ﻯ', medial: 'ﻴ', final: 'ﻰ' },
37679 5000: { initial: 'ﻻ', isolated: 'ﻻ', medial: '', final: 'ﻼ' }
37682 var rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0780-\u07BF]/;
37684 function fixRTLTextForSvg(inputText) {
37685 var context = true;
37687 var rtlBuffer = [];
37688 var arabicRegex = /[\u0600-\u06FF]/g;
37689 var arabicTashkil = /[\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED]/;
37690 var thaanaVowel = /[\u07A6-\u07B0]/;
37691 var hebrewSign = /[\u0591-\u05bd\u05bf\u05c1-\u05c5\u05c7]/;
37693 if (!arabicRegex.test(inputText)) {
37694 // Hebrew or Thaana RTL script
37695 for (var n = 0; n < inputText.length; n++) {
37696 var c = inputText[n];
37697 if ((thaanaVowel.test(c) || hebrewSign.test(c)) && rtlBuffer.length) {
37698 rtlBuffer[rtlBuffer.length - 1] += c;
37699 } else if (rtlRegex.test(c)) {
37701 } else if (c === ' ' && rtlBuffer.length) {
37702 // whitespace within RTL text
37703 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
37705 // non-RTL character
37706 ret += rtlBuffer.reverse().join('') + c;
37711 for (var i = 0, l = inputText.length; i < l; i++) {
37712 var code = inputText[i].charCodeAt(0);
37713 var nextCode = inputText[i + 1] ? inputText[i + 1].charCodeAt(0) : 0;
37715 if (!chars$1[code]) {
37716 if (code === 32 && rtlBuffer.length) {
37718 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
37719 } else if (arabicTashkil.test(inputText[i]) && rtlBuffer.length) {
37721 rtlBuffer[rtlBuffer.length - 1] += inputText[i];
37723 // non-RTL character
37724 ret += rtlBuffer.reverse().join('') + inputText[i];
37730 if (i === l - 1 || nextCode === 32) {
37731 rtlBuffer.push(chars$1[code].isolated);
37733 // special case for لا
37734 if (code === 1604 && nextCode === 1575) {
37735 rtlBuffer.push(chars$1[5000].initial);
37740 rtlBuffer.push(chars$1[code].initial);
37743 if (i === l - 1 || nextCode === 32){
37744 rtlBuffer.push(chars$1[code].final);
37746 // special case for ﻼ
37747 if (code === 1604 && nextCode === 1575){
37748 rtlBuffer.push(chars$1[5000].final);
37753 if (chars$1[code].medial === ''){
37754 rtlBuffer.push(chars$1[code].final);
37756 rtlBuffer.push(chars$1[code].medial);
37760 context = (chars$1[code].medial === '') || nextCode === 32;
37763 ret += rtlBuffer.reverse().join('');
37767 function utilTagText(entity) {
37768 return entries(entity.tags).map(function(e) {
37769 return e.key + '=' + e.value;
37774 function utilEntitySelector(ids) {
37775 return ids.length ? '.' + ids.join(',.') : 'nothing';
37779 function utilEntityOrMemberSelector(ids, graph) {
37780 var s = utilEntitySelector(ids);
37782 ids.forEach(function(id) {
37783 var entity = graph.hasEntity(id);
37784 if (entity && entity.type === 'relation') {
37785 entity.members.forEach(function(member) {
37786 s += ',.' + member.id;
37795 function utilGetAllNodes(ids, graph) {
37798 ids.forEach(getNodes);
37801 function getNodes(id) {
37802 if (seen[id]) return;
37805 var entity = graph.hasEntity(id);
37806 if (!entity) return;
37808 if (entity.type === 'node') {
37809 nodes.push(entity);
37810 } else if (entity.type === 'way') {
37811 entity.nodes.forEach(getNodes);
37813 entity.members.map(function(member) { return member.id; }).forEach(getNodes);
37819 function utilDisplayName(entity) {
37820 var localizedNameKey = 'name:' + utilDetect().locale.toLowerCase().split('-')[0],
37821 name = entity.tags[localizedNameKey] || entity.tags.name || '',
37822 network = entity.tags.cycle_network || entity.tags.network;
37824 if (!name && entity.tags.ref) {
37825 name = entity.tags.ref;
37827 name = network + ' ' + name;
37835 function utilDisplayNameForPath(entity) {
37836 var name = utilDisplayName(entity);
37837 var isFirefox = utilDetect().browser.toLowerCase().indexOf('firefox') > -1;
37839 if (!isFirefox && name && rtlRegex.test(name)) {
37840 name = fixRTLTextForSvg(name);
37847 function utilDisplayType(id) {
37849 n: t('inspector.node'),
37850 w: t('inspector.way'),
37851 r: t('inspector.relation')
37856 function utilStringQs(str) {
37857 return str.split('&').reduce(function(obj, pair){
37858 var parts = pair.split('=');
37859 if (parts.length === 2) {
37860 obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
37867 function utilQsString(obj, noencode) {
37868 function softEncode(s) {
37869 // encode everything except special characters used in certain hash parameters:
37870 // "/" in map states, ":", ",", {" and "}" in background
37871 return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
37873 return Object.keys(obj).sort().map(function(key) {
37874 return encodeURIComponent(key) + '=' + (
37875 noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
37880 function utilPrefixDOMProperty(property) {
37881 var prefixes = ['webkit', 'ms', 'moz', 'o'],
37883 n = prefixes.length,
37889 property = property.substr(0, 1).toUpperCase() + property.substr(1);
37892 if (prefixes[i] + property in s)
37893 return prefixes[i] + property;
37899 function utilPrefixCSSProperty(property) {
37900 var prefixes = ['webkit', 'ms', 'Moz', 'O'],
37902 n = prefixes.length,
37903 s = document.body.style;
37905 if (property.toLowerCase() in s)
37906 return property.toLowerCase();
37909 if (prefixes[i] + property in s)
37910 return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
37916 var transformProperty;
37917 function utilSetTransform(el, x, y, scale) {
37918 var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform'),
37919 translate = utilDetect().opera ?
37920 'translate(' + x + 'px,' + y + 'px)' :
37921 'translate3d(' + x + 'px,' + y + 'px,0)';
37922 return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
37926 // Calculates Levenshtein distance between two strings
37927 // see: https://en.wikipedia.org/wiki/Levenshtein_distance
37928 // first converts the strings to lowercase and replaces diacritic marks with ascii equivalents.
37929 function utilEditDistance(a, b) {
37930 a = remove$1(a.toLowerCase());
37931 b = remove$1(b.toLowerCase());
37932 if (a.length === 0) return b.length;
37933 if (b.length === 0) return a.length;
37935 for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
37936 for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
37937 for (i = 1; i <= b.length; i++) {
37938 for (j = 1; j <= a.length; j++) {
37939 if (b.charAt(i-1) === a.charAt(j-1)) {
37940 matrix[i][j] = matrix[i-1][j-1];
37942 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
37943 Math.min(matrix[i][j-1] + 1, // insertion
37944 matrix[i-1][j] + 1)); // deletion
37948 return matrix[b.length][a.length];
37952 // a d3.mouse-alike which
37953 // 1. Only works on HTML elements, not SVG
37954 // 2. Does not cause style recalculation
37955 function utilFastMouse(container) {
37956 var rect = container.getBoundingClientRect(),
37957 rectLeft = rect.left,
37958 rectTop = rect.top,
37959 clientLeft = +container.clientLeft,
37960 clientTop = +container.clientTop;
37961 if (textDirection === 'rtl') {
37964 return function(e) {
37966 e.clientX - rectLeft - clientLeft,
37967 e.clientY - rectTop - clientTop];
37972 /* eslint-disable no-proto */
37973 var utilGetPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
37974 /* eslint-enable no-proto */
37977 function utilAsyncMap(inputs, func, callback) {
37978 var remaining = inputs.length,
37982 inputs.forEach(function(d, i) {
37983 func(d, function done(err, data) {
37987 if (!remaining) callback(errors, results);
37993 // wraps an index to an interval [0..length-1]
37994 function utilWrap(index, length) {
37996 index += Math.ceil(-index/length)*length;
37997 return index % length;
38002 * a replacement for functor
38004 * @param {*} value any value
38005 * @returns {Function} a function that returns that value or the value if it's a function
38007 function utilFunctor(value) {
38008 if (typeof value === 'function') return value;
38009 return function() {
38015 function utilNoAuto(selection$$1) {
38016 return selection$$1
38017 .attr('autocomplete', 'off')
38018 .attr('autocorrect', 'off')
38019 .attr('autocapitalize', 'off')
38020 .attr('spellcheck', 'false');
38023 // Like selection.property('value', ...), but avoids no-op value sets,
38024 // which can result in layout/repaint thrashing in some situations.
38025 function utilGetSetValue(selection, value) {
38026 function d3_selection_value(value) {
38027 function valueNull() {
38031 function valueConstant() {
38032 if (this.value !== value) {
38033 this.value = value;
38037 function valueFunction() {
38038 var x = value.apply(this, arguments);
38041 } else if (this.value !== x) {
38046 return value == null
38047 ? valueNull : (typeof value === 'function'
38048 ? valueFunction : valueConstant);
38051 if (arguments.length === 1) {
38052 return selection.property('value');
38055 return selection.each(d3_selection_value(value));
38058 // Copies a variable number of methods from source to target.
38059 function utilRebind(target, source) {
38060 var i = 1, n = arguments.length, method;
38062 target[method = arguments[i]] = d3_rebind(target, source, source[method]);
38067 // Method is assumed to be a standard D3 getter-setter:
38068 // If passed with no arguments, gets the value.
38069 // If passed with arguments, sets the value and returns the target.
38070 function d3_rebind(target, source, method) {
38071 return function() {
38072 var value = method.apply(source, arguments);
38073 return value === source ? target : value;
38077 // A per-domain session mutex backed by a cookie and dead man's
38078 // switch. If the session crashes, the mutex will auto-release
38079 // after 5 seconds.
38081 function utilSessionMutex(name) {
38086 var expires = new Date();
38087 expires.setSeconds(expires.getSeconds() + 5);
38088 document.cookie = name + '=1; expires=' + expires.toUTCString();
38091 mutex.lock = function() {
38092 if (intervalID) return true;
38093 var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
38094 if (cookie) return false;
38096 intervalID = window.setInterval(renew, 4000);
38100 mutex.unlock = function() {
38101 if (!intervalID) return;
38102 document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
38103 clearInterval(intervalID);
38107 mutex.locked = function() {
38108 return !!intervalID;
38114 function utilSuggestNames(preset, suggestions) {
38115 preset = preset.id.split('/', 2);
38119 return function(value, callback) {
38121 if (value && value.length > 2) {
38122 if (suggestions[k] && suggestions[k][v]) {
38123 for (var sugg in suggestions[k][v]) {
38124 var dist = utilEditDistance(value, sugg.substring(0, value.length));
38134 result.sort(function(a, b) {
38135 return a.dist - b.dist;
38138 result = result.slice(0,3);
38143 function utilTriggerEvent(target, type) {
38144 target.each(function() {
38145 var evt = document.createEvent('HTMLEvents');
38146 evt.initEvent(type, true, true);
38147 this.dispatchEvent(evt);
38151 function validationDeprecatedTag() {
38153 var validation = function(changes) {
38155 for (var i = 0; i < changes.created.length; i++) {
38156 var change = changes.created[i],
38157 deprecatedTags = change.deprecatedTags();
38159 if (!lodash.isEmpty(deprecatedTags)) {
38160 var tags = utilTagText({ tags: deprecatedTags });
38162 id: 'deprecated_tags',
38163 message: t('validations.deprecated_tags', { tags: tags }),
38176 function validationDisconnectedHighway() {
38179 function isDisconnectedHighway(entity, graph) {
38180 if (!entity.tags.highway) return false;
38181 if (entity.geometry(graph) !== 'line') return false;
38183 return graph.childNodes(entity)
38184 .every(function(vertex) {
38185 var parents = graph.parentWays(vertex);
38186 if (parents.length === 1) { // standalone vertex
38188 } else { // shared vertex
38189 return !vertex.tags.entrance &&
38190 parents.filter(function(parent) {
38191 return parent.tags.highway && parent !== entity;
38198 var validation = function(changes, graph) {
38200 for (var i = 0; i < changes.created.length; i++) {
38201 var entity = changes.created[i];
38203 if (isDisconnectedHighway(entity, graph)) {
38205 id: 'disconnected_highway',
38206 message: t('validations.disconnected_highway'),
38207 tooltip: t('validations.disconnected_highway_tooltip'),
38220 function validationManyDeletions() {
38221 var threshold = 100;
38223 var validation = function(changes) {
38225 if (changes.deleted.length > threshold) {
38227 id: 'many_deletions',
38228 message: t('validations.many_deletions', { n: changes.deleted.length })
38239 function validationMissingTag() {
38241 // Slightly stricter check than Entity#isUsed (#3091)
38242 function hasTags(entity, graph) {
38243 return lodash.without(Object.keys(entity.tags), 'area', 'name').length > 0 ||
38244 graph.parentRelations(entity).length > 0;
38247 var validation = function(changes, graph) {
38248 var types = ['point', 'line', 'area', 'relation'],
38251 for (var i = 0; i < changes.created.length; i++) {
38252 var change = changes.created[i],
38253 geometry = change.geometry(graph);
38255 if (types.indexOf(geometry) !== -1 && !hasTags(change, graph)) {
38258 message: t('validations.untagged_' + geometry),
38259 tooltip: t('validations.untagged_' + geometry + '_tooltip'),
38272 function validationOldMultipolygon() {
38275 return function validation(changes, graph) {
38277 for (var i = 0; i < changes.created.length; i++) {
38278 var entity = changes.created[i];
38279 var parent = osmIsSimpleMultipolygonOuterMember(entity, graph);
38282 id: 'old_multipolygon',
38283 message: t('validations.old_multipolygon'),
38284 tooltip: t('validations.old_multipolygon_tooltip'),
38293 // https://github.com/openstreetmap/josm/blob/mirror/src/org/
38294 // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
38295 function validationTagSuggestsArea() {
38297 function tagSuggestsArea(tags) {
38298 if (lodash.isEmpty(tags)) return false;
38300 var presence = ['landuse', 'amenities', 'tourism', 'shop'];
38301 for (var i = 0; i < presence.length; i++) {
38302 if (tags[presence[i]] !== undefined) {
38303 return presence[i] + '=' + tags[presence[i]];
38307 if (tags.building && tags.building === 'yes') return 'building=yes';
38311 var validation = function(changes, graph) {
38313 for (var i = 0; i < changes.created.length; i++) {
38314 var change = changes.created[i],
38315 geometry = change.geometry(graph),
38316 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
38320 id: 'tag_suggests_area',
38321 message: t('validations.tag_suggests_area', { tag: suggestion }),
38336 var Validations = Object.freeze({
38337 validationDeprecatedTag: validationDeprecatedTag,
38338 validationDisconnectedHighway: validationDisconnectedHighway,
38339 validationManyDeletions: validationManyDeletions,
38340 validationMissingTag: validationMissingTag,
38341 validationOldMultipolygon: validationOldMultipolygon,
38342 validationTagSuggestsArea: validationTagSuggestsArea
38346 iD.Difference represents the difference between two graphs.
38347 It knows how to calculate the set of entities that were
38348 created, modified, or deleted, and also contains the logic
38349 for recursively extending a difference to the complete set
38350 of entities that will require a redraw, taking into account
38351 child and parent relationships.
38353 function coreDifference(base, head) {
38359 function changed(h, b) {
38360 return h !== b && !lodash.isEqual(lodash.omit(h, 'v'), lodash.omit(b, 'v'));
38364 lodash.each(head.entities, function(h, id) {
38365 var b = base.entities[id];
38366 if (changed(h, b)) {
38367 changes[id] = {base: b, head: h};
38373 lodash.each(base.entities, function(b, id) {
38374 var h = head.entities[id];
38375 if (!changes[id] && changed(h, b)) {
38376 changes[id] = {base: b, head: h};
38382 function addParents(parents, result) {
38383 for (var i = 0; i < parents.length; i++) {
38384 var parent = parents[i];
38386 if (parent.id in result)
38389 result[parent.id] = parent;
38390 addParents(head.parentRelations(parent), result);
38395 difference.length = function() {
38400 difference.changes = function() {
38405 difference.extantIDs = function() {
38407 lodash.each(changes, function(change, id) {
38408 if (change.head) result.push(id);
38414 difference.modified = function() {
38416 lodash.each(changes, function(change) {
38417 if (change.base && change.head) result.push(change.head);
38423 difference.created = function() {
38425 lodash.each(changes, function(change) {
38426 if (!change.base && change.head) result.push(change.head);
38432 difference.deleted = function() {
38434 lodash.each(changes, function(change) {
38435 if (change.base && !change.head) result.push(change.base);
38441 difference.summary = function() {
38444 function addEntity(entity, graph, changeType) {
38445 relevant[entity.id] = {
38448 changeType: changeType
38452 function addParents(entity) {
38453 var parents = head.parentWays(entity);
38454 for (var j = parents.length - 1; j >= 0; j--) {
38455 var parent = parents[j];
38456 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
38460 lodash.each(changes, function(change) {
38461 if (change.head && change.head.geometry(head) !== 'vertex') {
38462 addEntity(change.head, head, change.base ? 'modified' : 'created');
38464 } else if (change.base && change.base.geometry(base) !== 'vertex') {
38465 addEntity(change.base, base, 'deleted');
38467 } else if (change.base && change.head) { // modified vertex
38468 var moved = !lodash.isEqual(change.base.loc, change.head.loc),
38469 retagged = !lodash.isEqual(change.base.tags, change.head.tags);
38472 addParents(change.head);
38475 if (retagged || (moved && change.head.hasInterestingTags())) {
38476 addEntity(change.head, head, 'modified');
38479 } else if (change.head && change.head.hasInterestingTags()) { // created vertex
38480 addEntity(change.head, head, 'created');
38482 } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
38483 addEntity(change.base, base, 'deleted');
38487 return values(relevant);
38491 difference.complete = function(extent$$1) {
38492 var result = {}, id, change;
38494 for (id in changes) {
38495 change = changes[id];
38497 var h = change.head,
38502 (!h || !h.intersects(extent$$1, head)) &&
38503 (!b || !b.intersects(extent$$1, base)))
38508 if (entity.type === 'way') {
38509 var nh = h ? h.nodes : [],
38510 nb = b ? b.nodes : [],
38513 diff = lodash.difference(nh, nb);
38514 for (i = 0; i < diff.length; i++) {
38515 result[diff[i]] = head.hasEntity(diff[i]);
38518 diff = lodash.difference(nb, nh);
38519 for (i = 0; i < diff.length; i++) {
38520 result[diff[i]] = head.hasEntity(diff[i]);
38524 addParents(head.parentWays(entity), result);
38525 addParents(head.parentRelations(entity), result);
38535 function coreGraph$$1(other, mutable) {
38536 if (!(this instanceof coreGraph$$1)) return new coreGraph$$1(other, mutable);
38538 if (other instanceof coreGraph$$1) {
38539 var base = other.base();
38540 this.entities = lodash.assign(Object.create(base.entities), other.entities);
38541 this._parentWays = lodash.assign(Object.create(base.parentWays), other._parentWays);
38542 this._parentRels = lodash.assign(Object.create(base.parentRels), other._parentRels);
38545 this.entities = Object.create({});
38546 this._parentWays = Object.create({});
38547 this._parentRels = Object.create({});
38548 this.rebase(other || [], [this]);
38551 this.transients = {};
38552 this._childNodes = {};
38553 this.frozen = !mutable;
38557 coreGraph$$1.prototype = {
38559 hasEntity: function(id) {
38560 return this.entities[id];
38564 entity: function(id) {
38565 var entity = this.entities[id];
38567 throw new Error('entity ' + id + ' not found');
38573 transient: function(entity, key, fn) {
38574 var id = entity.id,
38575 transients = this.transients[id] ||
38576 (this.transients[id] = {});
38578 if (transients[key] !== undefined) {
38579 return transients[key];
38582 transients[key] = fn.call(entity);
38584 return transients[key];
38588 parentWays: function(entity) {
38589 var parents = this._parentWays[entity.id],
38593 for (var i = 0; i < parents.length; i++) {
38594 result.push(this.entity(parents[i]));
38601 isPoi: function(entity) {
38602 var parentWays = this._parentWays[entity.id];
38603 return !parentWays || parentWays.length === 0;
38607 isShared: function(entity) {
38608 var parentWays = this._parentWays[entity.id];
38609 return parentWays && parentWays.length > 1;
38613 parentRelations: function(entity) {
38614 var parents = this._parentRels[entity.id],
38618 for (var i = 0; i < parents.length; i++) {
38619 result.push(this.entity(parents[i]));
38626 childNodes: function(entity) {
38627 if (this._childNodes[entity.id]) return this._childNodes[entity.id];
38628 if (!entity.nodes) return [];
38631 for (var i = 0; i < entity.nodes.length; i++) {
38632 nodes[i] = this.entity(entity.nodes[i]);
38635 if (debug) Object.freeze(nodes);
38637 this._childNodes[entity.id] = nodes;
38638 return this._childNodes[entity.id];
38644 'entities': utilGetPrototypeOf(this.entities),
38645 'parentWays': utilGetPrototypeOf(this._parentWays),
38646 'parentRels': utilGetPrototypeOf(this._parentRels)
38651 // Unlike other graph methods, rebase mutates in place. This is because it
38652 // is used only during the history operation that merges newly downloaded
38653 // data into each state. To external consumers, it should appear as if the
38654 // graph always contained the newly downloaded data.
38655 rebase: function(entities, stack, force) {
38656 var base = this.base(),
38659 for (i = 0; i < entities.length; i++) {
38660 var entity = entities[i];
38662 if (!entity.visible || (!force && base.entities[entity.id]))
38665 // Merging data into the base graph
38666 base.entities[entity.id] = entity;
38667 this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
38669 // Restore provisionally-deleted nodes that are discovered to have an extant parent
38670 if (entity.type === 'way') {
38671 for (j = 0; j < entity.nodes.length; j++) {
38672 id = entity.nodes[j];
38673 for (k = 1; k < stack.length; k++) {
38674 var ents = stack[k].entities;
38675 if (ents.hasOwnProperty(id) && ents[id] === undefined) {
38683 for (i = 0; i < stack.length; i++) {
38684 stack[i]._updateRebased();
38689 _updateRebased: function() {
38690 var base = this.base(),
38691 i, k, child, id, keys;
38693 keys = Object.keys(this._parentWays);
38694 for (i = 0; i < keys.length; i++) {
38696 if (base.parentWays[child]) {
38697 for (k = 0; k < base.parentWays[child].length; k++) {
38698 id = base.parentWays[child][k];
38699 if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentWays[child], id)) {
38700 this._parentWays[child].push(id);
38706 keys = Object.keys(this._parentRels);
38707 for (i = 0; i < keys.length; i++) {
38709 if (base.parentRels[child]) {
38710 for (k = 0; k < base.parentRels[child].length; k++) {
38711 id = base.parentRels[child][k];
38712 if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentRels[child], id)) {
38713 this._parentRels[child].push(id);
38719 this.transients = {};
38721 // this._childNodes is not updated, under the assumption that
38722 // ways are always downloaded with their child nodes.
38726 // Updates calculated properties (parentWays, parentRels) for the specified change
38727 _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
38729 parentWays = parentWays || this._parentWays;
38730 parentRels = parentRels || this._parentRels;
38732 var type = entity && entity.type || oldentity && oldentity.type,
38733 removed, added, ways, rels, i;
38736 if (type === 'way') {
38738 // Update parentWays
38739 if (oldentity && entity) {
38740 removed = lodash.difference(oldentity.nodes, entity.nodes);
38741 added = lodash.difference(entity.nodes, oldentity.nodes);
38742 } else if (oldentity) {
38743 removed = oldentity.nodes;
38745 } else if (entity) {
38747 added = entity.nodes;
38749 for (i = 0; i < removed.length; i++) {
38750 parentWays[removed[i]] = lodash.without(parentWays[removed[i]], oldentity.id);
38752 for (i = 0; i < added.length; i++) {
38753 ways = lodash.without(parentWays[added[i]], entity.id);
38754 ways.push(entity.id);
38755 parentWays[added[i]] = ways;
38758 } else if (type === 'relation') {
38760 // Update parentRels
38761 if (oldentity && entity) {
38762 removed = lodash.difference(oldentity.members, entity.members);
38763 added = lodash.difference(entity.members, oldentity);
38764 } else if (oldentity) {
38765 removed = oldentity.members;
38767 } else if (entity) {
38769 added = entity.members;
38771 for (i = 0; i < removed.length; i++) {
38772 parentRels[removed[i].id] = lodash.without(parentRels[removed[i].id], oldentity.id);
38774 for (i = 0; i < added.length; i++) {
38775 rels = lodash.without(parentRels[added[i].id], entity.id);
38776 rels.push(entity.id);
38777 parentRels[added[i].id] = rels;
38783 replace: function(entity) {
38784 if (this.entities[entity.id] === entity)
38787 return this.update(function() {
38788 this._updateCalculated(this.entities[entity.id], entity);
38789 this.entities[entity.id] = entity;
38794 remove: function(entity) {
38795 return this.update(function() {
38796 this._updateCalculated(entity, undefined);
38797 this.entities[entity.id] = undefined;
38802 revert: function(id) {
38803 var baseEntity = this.base().entities[id],
38804 headEntity = this.entities[id];
38806 if (headEntity === baseEntity)
38809 return this.update(function() {
38810 this._updateCalculated(headEntity, baseEntity);
38811 delete this.entities[id];
38816 update: function() {
38817 var graph = this.frozen ? coreGraph$$1(this, true) : this;
38819 for (var i = 0; i < arguments.length; i++) {
38820 arguments[i].call(graph, graph);
38823 if (this.frozen) graph.frozen = true;
38829 // Obliterates any existing entities
38830 load: function(entities) {
38831 var base = this.base();
38832 this.entities = Object.create(base.entities);
38834 for (var i in entities) {
38835 this.entities[i] = entities[i];
38836 this._updateCalculated(base.entities[i], this.entities[i]);
38843 var index$10 = partialSort;
38845 // Floyd-Rivest selection algorithm:
38846 // Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
38847 // The k-th element will have the (k - left + 1)th smallest value in [left, right]
38849 function partialSort(arr, k, left, right, compare) {
38851 right = right || (arr.length - 1);
38852 compare = compare || defaultCompare;
38854 while (right > left) {
38855 if (right - left > 600) {
38856 var n = right - left + 1;
38857 var m = k - left + 1;
38858 var z = Math.log(n);
38859 var s = 0.5 * Math.exp(2 * z / 3);
38860 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
38861 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
38862 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
38863 partialSort(arr, k, newLeft, newRight, compare);
38870 swap(arr, left, k);
38871 if (compare(arr[right], t) > 0) swap(arr, left, right);
38877 while (compare(arr[i], t) < 0) i++;
38878 while (compare(arr[j], t) > 0) j--;
38881 if (compare(arr[left], t) === 0) swap(arr, left, j);
38884 swap(arr, j, right);
38887 if (j <= k) left = j + 1;
38888 if (k <= j) right = j - 1;
38892 function swap(arr, i, j) {
38898 function defaultCompare(a, b) {
38899 return a < b ? -1 : a > b ? 1 : 0;
38902 var index$9 = rbush;
38906 function rbush(maxEntries, format) {
38907 if (!(this instanceof rbush)) return new rbush(maxEntries, format);
38909 // max entries in a node is 9 by default; min node fill is 40% for best performance
38910 this._maxEntries = Math.max(4, maxEntries || 9);
38911 this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
38914 this._initFormat(format);
38920 rbush.prototype = {
38923 return this._all(this.data, []);
38926 search: function (bbox) {
38928 var node = this.data,
38930 toBBox = this.toBBox;
38932 if (!intersects$1(bbox, node)) return result;
38934 var nodesToSearch = [],
38935 i, len, child, childBBox;
38938 for (i = 0, len = node.children.length; i < len; i++) {
38940 child = node.children[i];
38941 childBBox = node.leaf ? toBBox(child) : child;
38943 if (intersects$1(bbox, childBBox)) {
38944 if (node.leaf) result.push(child);
38945 else if (contains$2(bbox, childBBox)) this._all(child, result);
38946 else nodesToSearch.push(child);
38949 node = nodesToSearch.pop();
38955 collides: function (bbox) {
38957 var node = this.data,
38958 toBBox = this.toBBox;
38960 if (!intersects$1(bbox, node)) return false;
38962 var nodesToSearch = [],
38963 i, len, child, childBBox;
38966 for (i = 0, len = node.children.length; i < len; i++) {
38968 child = node.children[i];
38969 childBBox = node.leaf ? toBBox(child) : child;
38971 if (intersects$1(bbox, childBBox)) {
38972 if (node.leaf || contains$2(bbox, childBBox)) return true;
38973 nodesToSearch.push(child);
38976 node = nodesToSearch.pop();
38982 load: function (data) {
38983 if (!(data && data.length)) return this;
38985 if (data.length < this._minEntries) {
38986 for (var i = 0, len = data.length; i < len; i++) {
38987 this.insert(data[i]);
38992 // recursively build the tree with the given data from stratch using OMT algorithm
38993 var node = this._build(data.slice(), 0, data.length - 1, 0);
38995 if (!this.data.children.length) {
38996 // save as is if tree is empty
38999 } else if (this.data.height === node.height) {
39000 // split root if trees have the same height
39001 this._splitRoot(this.data, node);
39004 if (this.data.height < node.height) {
39005 // swap trees if inserted one is bigger
39006 var tmpNode = this.data;
39011 // insert the small tree into the large tree at appropriate level
39012 this._insert(node, this.data.height - node.height - 1, true);
39018 insert: function (item) {
39019 if (item) this._insert(item, this.data.height - 1);
39023 clear: function () {
39024 this.data = createNode([]);
39028 remove: function (item, equalsFn) {
39029 if (!item) return this;
39031 var node = this.data,
39032 bbox = this.toBBox(item),
39035 i, parent, index, goingUp;
39037 // depth-first iterative tree traversal
39038 while (node || path.length) {
39040 if (!node) { // go up
39042 parent = path[path.length - 1];
39047 if (node.leaf) { // check current node
39048 index = findItem(item, node.children, equalsFn);
39050 if (index !== -1) {
39051 // item found, remove the item and condense tree upwards
39052 node.children.splice(index, 1);
39054 this._condense(path);
39059 if (!goingUp && !node.leaf && contains$2(node, bbox)) { // go down
39064 node = node.children[0];
39066 } else if (parent) { // go right
39068 node = parent.children[i];
39071 } else node = null; // nothing found
39077 toBBox: function (item) { return item; },
39079 compareMinX: compareNodeMinX,
39080 compareMinY: compareNodeMinY,
39082 toJSON: function () { return this.data; },
39084 fromJSON: function (data) {
39089 _all: function (node, result) {
39090 var nodesToSearch = [];
39092 if (node.leaf) result.push.apply(result, node.children);
39093 else nodesToSearch.push.apply(nodesToSearch, node.children);
39095 node = nodesToSearch.pop();
39100 _build: function (items, left, right, height) {
39102 var N = right - left + 1,
39103 M = this._maxEntries,
39107 // reached leaf level; return leaf
39108 node = createNode(items.slice(left, right + 1));
39109 calcBBox(node, this.toBBox);
39114 // target height of the bulk-loaded tree
39115 height = Math.ceil(Math.log(N) / Math.log(M));
39117 // target number of root entries to maximize storage utilization
39118 M = Math.ceil(N / Math.pow(M, height - 1));
39121 node = createNode([]);
39123 node.height = height;
39125 // split the items into M mostly square tiles
39127 var N2 = Math.ceil(N / M),
39128 N1 = N2 * Math.ceil(Math.sqrt(M)),
39129 i, j, right2, right3;
39131 multiSelect(items, left, right, N1, this.compareMinX);
39133 for (i = left; i <= right; i += N1) {
39135 right2 = Math.min(i + N1 - 1, right);
39137 multiSelect(items, i, right2, N2, this.compareMinY);
39139 for (j = i; j <= right2; j += N2) {
39141 right3 = Math.min(j + N2 - 1, right2);
39143 // pack each entry recursively
39144 node.children.push(this._build(items, j, right3, height - 1));
39148 calcBBox(node, this.toBBox);
39153 _chooseSubtree: function (bbox, node, level, path) {
39155 var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
39160 if (node.leaf || path.length - 1 === level) break;
39162 minArea = minEnlargement = Infinity;
39164 for (i = 0, len = node.children.length; i < len; i++) {
39165 child = node.children[i];
39166 area = bboxArea(child);
39167 enlargement = enlargedArea(bbox, child) - area;
39169 // choose entry with the least area enlargement
39170 if (enlargement < minEnlargement) {
39171 minEnlargement = enlargement;
39172 minArea = area < minArea ? area : minArea;
39173 targetNode = child;
39175 } else if (enlargement === minEnlargement) {
39176 // otherwise choose one with the smallest area
39177 if (area < minArea) {
39179 targetNode = child;
39184 node = targetNode || node.children[0];
39190 _insert: function (item, level, isNode) {
39192 var toBBox = this.toBBox,
39193 bbox = isNode ? item : toBBox(item),
39196 // find the best node for accommodating the item, saving all nodes along the path too
39197 var node = this._chooseSubtree(bbox, this.data, level, insertPath);
39199 // put the item into the node
39200 node.children.push(item);
39201 extend$1(node, bbox);
39203 // split on node overflow; propagate upwards if necessary
39204 while (level >= 0) {
39205 if (insertPath[level].children.length > this._maxEntries) {
39206 this._split(insertPath, level);
39211 // adjust bboxes along the insertion path
39212 this._adjustParentBBoxes(bbox, insertPath, level);
39215 // split overflowed node into two
39216 _split: function (insertPath, level) {
39218 var node = insertPath[level],
39219 M = node.children.length,
39220 m = this._minEntries;
39222 this._chooseSplitAxis(node, m, M);
39224 var splitIndex = this._chooseSplitIndex(node, m, M);
39226 var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
39227 newNode.height = node.height;
39228 newNode.leaf = node.leaf;
39230 calcBBox(node, this.toBBox);
39231 calcBBox(newNode, this.toBBox);
39233 if (level) insertPath[level - 1].children.push(newNode);
39234 else this._splitRoot(node, newNode);
39237 _splitRoot: function (node, newNode) {
39239 this.data = createNode([node, newNode]);
39240 this.data.height = node.height + 1;
39241 this.data.leaf = false;
39242 calcBBox(this.data, this.toBBox);
39245 _chooseSplitIndex: function (node, m, M) {
39247 var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
39249 minOverlap = minArea = Infinity;
39251 for (i = m; i <= M - m; i++) {
39252 bbox1 = distBBox(node, 0, i, this.toBBox);
39253 bbox2 = distBBox(node, i, M, this.toBBox);
39255 overlap = intersectionArea(bbox1, bbox2);
39256 area = bboxArea(bbox1) + bboxArea(bbox2);
39258 // choose distribution with minimum overlap
39259 if (overlap < minOverlap) {
39260 minOverlap = overlap;
39263 minArea = area < minArea ? area : minArea;
39265 } else if (overlap === minOverlap) {
39266 // otherwise choose distribution with minimum area
39267 if (area < minArea) {
39277 // sorts node children by the best axis for split
39278 _chooseSplitAxis: function (node, m, M) {
39280 var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
39281 compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
39282 xMargin = this._allDistMargin(node, m, M, compareMinX),
39283 yMargin = this._allDistMargin(node, m, M, compareMinY);
39285 // if total distributions margin value is minimal for x, sort by minX,
39286 // otherwise it's already sorted by minY
39287 if (xMargin < yMargin) node.children.sort(compareMinX);
39290 // total margin of all possible split distributions where each node is at least m full
39291 _allDistMargin: function (node, m, M, compare) {
39293 node.children.sort(compare);
39295 var toBBox = this.toBBox,
39296 leftBBox = distBBox(node, 0, m, toBBox),
39297 rightBBox = distBBox(node, M - m, M, toBBox),
39298 margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
39301 for (i = m; i < M - m; i++) {
39302 child = node.children[i];
39303 extend$1(leftBBox, node.leaf ? toBBox(child) : child);
39304 margin += bboxMargin(leftBBox);
39307 for (i = M - m - 1; i >= m; i--) {
39308 child = node.children[i];
39309 extend$1(rightBBox, node.leaf ? toBBox(child) : child);
39310 margin += bboxMargin(rightBBox);
39316 _adjustParentBBoxes: function (bbox, path, level) {
39317 // adjust bboxes along the given tree path
39318 for (var i = level; i >= 0; i--) {
39319 extend$1(path[i], bbox);
39323 _condense: function (path) {
39324 // go through the path, removing empty nodes and updating bboxes
39325 for (var i = path.length - 1, siblings; i >= 0; i--) {
39326 if (path[i].children.length === 0) {
39328 siblings = path[i - 1].children;
39329 siblings.splice(siblings.indexOf(path[i]), 1);
39331 } else this.clear();
39333 } else calcBBox(path[i], this.toBBox);
39337 _initFormat: function (format) {
39338 // data format (minX, minY, maxX, maxY accessors)
39340 // uses eval-type function compilation instead of just accepting a toBBox function
39341 // because the algorithms are very sensitive to sorting functions performance,
39342 // so they should be dead simple and without inner calls
39344 var compareArr = ['return a', ' - b', ';'];
39346 this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
39347 this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
39349 this.toBBox = new Function('a',
39350 'return {minX: a' + format[0] +
39351 ', minY: a' + format[1] +
39352 ', maxX: a' + format[2] +
39353 ', maxY: a' + format[3] + '};');
39357 function findItem(item, items, equalsFn) {
39358 if (!equalsFn) return items.indexOf(item);
39360 for (var i = 0; i < items.length; i++) {
39361 if (equalsFn(item, items[i])) return i;
39366 // calculate node's bbox from bboxes of its children
39367 function calcBBox(node, toBBox) {
39368 distBBox(node, 0, node.children.length, toBBox, node);
39371 // min bounding rectangle of node children from k to p-1
39372 function distBBox(node, k, p, toBBox, destNode) {
39373 if (!destNode) destNode = createNode(null);
39374 destNode.minX = Infinity;
39375 destNode.minY = Infinity;
39376 destNode.maxX = -Infinity;
39377 destNode.maxY = -Infinity;
39379 for (var i = k, child; i < p; i++) {
39380 child = node.children[i];
39381 extend$1(destNode, node.leaf ? toBBox(child) : child);
39387 function extend$1(a, b) {
39388 a.minX = Math.min(a.minX, b.minX);
39389 a.minY = Math.min(a.minY, b.minY);
39390 a.maxX = Math.max(a.maxX, b.maxX);
39391 a.maxY = Math.max(a.maxY, b.maxY);
39395 function compareNodeMinX(a, b) { return a.minX - b.minX; }
39396 function compareNodeMinY(a, b) { return a.minY - b.minY; }
39398 function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
39399 function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
39401 function enlargedArea(a, b) {
39402 return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
39403 (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
39406 function intersectionArea(a, b) {
39407 var minX = Math.max(a.minX, b.minX),
39408 minY = Math.max(a.minY, b.minY),
39409 maxX = Math.min(a.maxX, b.maxX),
39410 maxY = Math.min(a.maxY, b.maxY);
39412 return Math.max(0, maxX - minX) *
39413 Math.max(0, maxY - minY);
39416 function contains$2(a, b) {
39417 return a.minX <= b.minX &&
39418 a.minY <= b.minY &&
39419 b.maxX <= a.maxX &&
39423 function intersects$1(a, b) {
39424 return b.minX <= a.maxX &&
39425 b.minY <= a.maxY &&
39426 b.maxX >= a.minX &&
39430 function createNode(children) {
39432 children: children,
39442 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
39443 // combines selection algorithm with binary divide & conquer approach
39445 function multiSelect(arr, left, right, n, compare) {
39446 var stack = [left, right],
39449 while (stack.length) {
39450 right = stack.pop();
39451 left = stack.pop();
39453 if (right - left <= n) continue;
39455 mid = left + Math.ceil((right - left) / n / 2) * n;
39456 index$10(arr, mid, left, right, compare);
39458 stack.push(left, mid, mid, right);
39462 function coreTree(head) {
39463 var rtree = index$9(),
39468 function entityBBox(entity) {
39469 var bbox = entity.extent(head).bbox();
39470 bbox.id = entity.id;
39471 bboxes[entity.id] = bbox;
39476 function updateParents(entity, insertions, memo) {
39477 head.parentWays(entity).forEach(function(way) {
39478 if (bboxes[way.id]) {
39479 rtree.remove(bboxes[way.id]);
39480 insertions[way.id] = way;
39482 updateParents(way, insertions, memo);
39485 head.parentRelations(entity).forEach(function(relation) {
39486 if (memo[entity.id]) return;
39487 memo[entity.id] = true;
39488 if (bboxes[relation.id]) {
39489 rtree.remove(bboxes[relation.id]);
39490 insertions[relation.id] = relation;
39492 updateParents(relation, insertions, memo);
39497 tree.rebase = function(entities, force) {
39498 var insertions = {};
39500 for (var i = 0; i < entities.length; i++) {
39501 var entity = entities[i];
39503 if (!entity.visible)
39506 if (head.entities.hasOwnProperty(entity.id) || bboxes[entity.id]) {
39509 } else if (bboxes[entity.id]) {
39510 rtree.remove(bboxes[entity.id]);
39514 insertions[entity.id] = entity;
39515 updateParents(entity, insertions, {});
39518 rtree.load(lodash.map(insertions, entityBBox));
39524 tree.intersects = function(extent, graph) {
39525 if (graph !== head) {
39526 var diff = coreDifference(head, graph),
39531 diff.deleted().forEach(function(entity) {
39532 rtree.remove(bboxes[entity.id]);
39533 delete bboxes[entity.id];
39536 diff.modified().forEach(function(entity) {
39537 rtree.remove(bboxes[entity.id]);
39538 insertions[entity.id] = entity;
39539 updateParents(entity, insertions, {});
39542 diff.created().forEach(function(entity) {
39543 insertions[entity.id] = entity;
39546 rtree.load(lodash.map(insertions, entityBBox));
39549 return rtree.search(extent.bbox()).map(function(bbox) {
39550 return head.entity(bbox.id);
39559 * This code is licensed under the MIT license.
39561 * Copyright © 2013, iD authors.
39563 * Portions copyright © 2011, Keith Cirkel
39564 * See https://github.com/keithamus/jwerty
39567 function d3keybinding(namespace$$1) {
39570 function matches(binding, event$$1) {
39571 for (var p in binding.event) {
39572 if (event$$1[p] !== binding.event[p])
39578 function testBindings(isCapturing) {
39579 for (var i = 0; i < bindings.length; i++) {
39580 var binding = bindings[i];
39582 if (!!binding.capture === isCapturing && matches(binding, event)) {
39583 binding.callback();
39588 function capture() {
39589 testBindings(true);
39592 function bubble() {
39593 var tagName = select(event.target).node().tagName;
39594 if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
39597 testBindings(false);
39600 function keybinding(selection$$1) {
39601 selection$$1 = selection$$1 || select(document);
39602 selection$$1.on('keydown.capture' + namespace$$1, capture, true);
39603 selection$$1.on('keydown.bubble' + namespace$$1, bubble, false);
39607 keybinding.off = function(selection$$1) {
39609 selection$$1 = selection$$1 || select(document);
39610 selection$$1.on('keydown.capture' + namespace$$1, null);
39611 selection$$1.on('keydown.bubble' + namespace$$1, null);
39615 keybinding.on = function(codes, callback, capture) {
39616 var arr = [].concat(codes);
39617 for (var i = 0; i < arr.length; i++) {
39631 code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
39633 for (var j = 0; j < code.length; j++) {
39634 // Normalise matching errors
39635 if (code[j] === '++') code[i] = '+';
39637 if (code[j] in d3keybinding.modifierCodes) {
39638 binding.event[d3keybinding.modifierProperties[d3keybinding.modifierCodes[code[j]]]] = true;
39639 } else if (code[j] in d3keybinding.keyCodes) {
39640 binding.event.keyCode = d3keybinding.keyCodes[code[j]];
39644 bindings.push(binding);
39654 d3keybinding.modifierCodes = {
39656 '⇧': 16, shift: 16,
39657 // CTRL key, on Mac: ⌃
39659 // ALT key, on Mac: ⌥ (Alt)
39660 '⌥': 18, alt: 18, option: 18,
39661 // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
39662 '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
39665 d3keybinding.modifierProperties = {
39672 d3keybinding.keyCodes = {
39673 // Backspace key, on Mac: ⌫ (Backspace)
39674 '⌫': 8, backspace: 8,
39675 // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
39676 '⇥': 9, '⇆': 9, tab: 9,
39678 '↩': 13, 'return': 13, enter: 13, '⌅': 13,
39680 'pause': 19, 'pause-break': 19,
39681 // Caps Lock key, ⇪
39682 '⇪': 20, caps: 20, 'caps-lock': 20,
39683 // Escape key, on Mac: ⎋, on Windows: Esc
39684 '⎋': 27, escape: 27, esc: 27,
39687 // Page-Up key, or pgup, on Mac: ↖
39688 '↖': 33, pgup: 33, 'page-up': 33,
39689 // Page-Down key, or pgdown, on Mac: ↘
39690 '↘': 34, pgdown: 34, 'page-down': 34,
39691 // END key, on Mac: ⇟
39693 // HOME key, on Mac: ⇞
39695 // Insert key, or ins
39696 ins: 45, insert: 45,
39697 // Delete key, on Mac: ⌦ (Delete)
39698 '⌦': 46, del: 46, 'delete': 46,
39699 // Left Arrow Key, or ←
39700 '←': 37, left: 37, 'arrow-left': 37,
39701 // Up Arrow Key, or ↑
39702 '↑': 38, up: 38, 'arrow-up': 38,
39703 // Right Arrow Key, or →
39704 '→': 39, right: 39, 'arrow-right': 39,
39705 // Up Arrow Key, or ↓
39706 '↓': 40, down: 40, 'arrow-down': 40,
39707 // odities, printing characters that come out wrong:
39710 // Num-Multiply, or *
39711 '*': 106, star: 106, asterisk: 106, multiply: 106,
39713 '+': 107, 'plus': 107,
39714 // Num-Subtract, or -
39715 '-': 109, subtract: 109,
39721 ';': 186, semicolon: 186,
39723 '=': 187, 'equals': 187,
39725 ',': 188, comma: 188,
39726 // Dash / Underscore key
39728 // Period, or ., or full-stop
39729 '.': 190, period: 190, 'full-stop': 190,
39730 // Slash, or /, or forward-slash
39731 '/': 191, slash: 191, 'forward-slash': 191,
39732 // Tick, or `, or back-quote
39733 '`': 192, tick: 192, 'back-quote': 192,
39734 // Open bracket, or [
39735 '[': 219, 'open-bracket': 219,
39736 // Back slash, or \
39737 '\\': 220, 'back-slash': 220,
39738 // Close backet, or ]
39739 ']': 221, 'close-bracket': 221,
39740 // Apostrophe, or Quote, or '
39741 '\'': 222, quote: 222, apostrophe: 222
39747 while (++i$1 < 106) {
39748 d3keybinding.keyCodes['num-' + n] = i$1;
39754 while (++i$1 < 58) {
39755 d3keybinding.keyCodes[n] = i$1;
39761 while (++i$1 < 136) {
39762 d3keybinding.keyCodes['f' + n] = i$1;
39768 while (++i$1 < 91) {
39769 d3keybinding.keyCodes[String.fromCharCode(i$1).toLowerCase()] = i$1;
39772 function tooltip() {
39773 var tooltip = function(selection$$1) {
39774 selection$$1.each(setup);
39776 animation = utilFunctor(false),
39777 html$$1 = utilFunctor(false),
39778 title = function() {
39779 var title = this.getAttribute('data-original-title');
39783 title = this.getAttribute('title');
39784 this.removeAttribute('title');
39785 this.setAttribute('data-original-title', title);
39789 over = 'mouseenter.tooltip',
39790 out = 'mouseleave.tooltip',
39791 placement = utilFunctor('top');
39794 tooltip.title = function(_) {
39795 if (arguments.length) {
39796 title = utilFunctor(_);
39804 tooltip.html = function(_) {
39805 if (arguments.length) {
39806 html$$1 = utilFunctor(_);
39814 tooltip.placement = function(_) {
39815 if (arguments.length) {
39816 placement = utilFunctor(_);
39824 tooltip.show = function(selection$$1) {
39825 selection$$1.each(show);
39829 tooltip.hide = function(selection$$1) {
39830 selection$$1.each(hide);
39834 tooltip.toggle = function(selection$$1) {
39835 selection$$1.each(toggle);
39839 tooltip.destroy = function(selection$$1) {
39843 .attr('title', function() {
39844 return this.getAttribute('data-original-title') || this.getAttribute('title');
39846 .attr('data-original-title', null)
39847 .selectAll('.tooltip')
39853 var root = select(this),
39854 animate = animation.apply(this, arguments),
39855 tip = root.selectAll('.tooltip').data([0]);
39857 var enter = tip.enter()
39859 .attr('class', 'tooltip');
39863 .attr('class', 'tooltip-arrow');
39867 .attr('class', 'tooltip-inner');
39873 tip.classed('fade', true);
39876 var place = placement.apply(this, arguments);
39877 tip.classed(place, true);
39879 root.on(over, show);
39880 root.on(out, hide);
39885 var root = select(this),
39886 content = title.apply(this, arguments),
39887 tip = root.selectAll('.tooltip')
39888 .classed('in', true),
39889 markup = html$$1.apply(this, arguments);
39891 tip.selectAll('.tooltip-inner')[markup ? 'html' : 'text'](content);
39892 var place = placement.apply(this, arguments),
39893 outer = getPosition(root.node()),
39894 inner = getPosition(tip.node()),
39899 pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
39902 pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
39905 pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
39908 pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
39913 tip.style('left', ~~pos.x + 'px').style('top', ~~pos.y + 'px');
39915 tip.style('left', null).style('top', null);
39918 this.tooltipVisible = true;
39923 select(this).selectAll('.tooltip')
39924 .classed('in', false);
39926 this.tooltipVisible = false;
39930 function toggle() {
39931 if (this.tooltipVisible) {
39932 hide.apply(this, arguments);
39934 show.apply(this, arguments);
39942 function getPosition(node) {
39943 var mode = select(node).style('position');
39944 if (mode === 'absolute' || mode === 'static') {
39946 x: node.offsetLeft,
39948 w: node.offsetWidth,
39949 h: node.offsetHeight
39955 w: node.offsetWidth,
39956 h: node.offsetHeight
39961 function svgAreas$$1(projection, context) {
39962 // Patterns only work in Firefox when set directly on element.
39963 // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
39966 cemetery: 'cemetery',
39967 construction: 'construction',
39969 farmland: 'farmland',
39970 grave_yard: 'cemetery',
39972 military: 'construction',
39973 orchard: 'orchard',
39976 wetland: 'wetland',
39979 var patternKeys = ['landuse', 'natural', 'amenity'];
39982 function setPattern(d) {
39983 for (var i = 0; i < patternKeys.length; i++) {
39984 if (d.tags.building && d.tags.building !== 'no') continue;
39986 if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
39987 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
39991 this.style.fill = this.style.stroke = '';
39995 return function drawAreas(selection$$1, graph, entities, filter) {
39996 var path$$1 = svgPath(projection, graph, true),
40000 for (var i = 0; i < entities.length; i++) {
40001 var entity = entities[i];
40002 if (entity.geometry(graph) !== 'area') continue;
40004 multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph);
40005 if (multipolygon) {
40006 areas[multipolygon.id] = {
40007 entity: multipolygon.mergeTags(entity.tags),
40008 area: Math.abs(entity.area(graph))
40010 } else if (!areas[entity.id]) {
40011 areas[entity.id] = {
40013 area: Math.abs(entity.area(graph))
40018 areas = values(areas).filter(function hasPath(a) { return path$$1(a.entity); });
40019 areas.sort(function areaSort(a, b) { return b.area - a.area; });
40020 areas = lodash.map(areas, 'entity');
40022 var strokes = areas.filter(function(area$$1) {
40023 return area$$1.type === 'way';
40033 var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath')
40035 .data(data.clip, osmEntity$$1.key);
40040 var clipPathsEnter = clipPaths.enter()
40041 .append('clipPath')
40042 .attr('class', 'clipPath')
40043 .attr('id', function(entity) { return entity.id + '-clippath'; });
40048 clipPaths.merge(clipPathsEnter)
40050 .attr('d', path$$1);
40053 var layer = selection$$1.selectAll('.layer-areas');
40055 var areagroup = layer
40056 .selectAll('g.areagroup')
40057 .data(['fill', 'shadow', 'stroke']);
40059 areagroup = areagroup.enter()
40061 .attr('class', function(d) { return 'areagroup area-' + d; })
40064 var paths = areagroup
40067 .data(function(layer) { return data[layer]; }, osmEntity$$1.key);
40072 var fills = selection$$1.selectAll('.area-fill path.area').nodes();
40074 var bisect$$1 = bisector(function(node) {
40075 return -node.__data__.area(graph);
40078 function sortedByArea(entity) {
40079 if (this._parent.__data__ === 'fill') {
40080 return fills[bisect$$1(fills, -entity.area(graph))];
40084 paths = paths.enter()
40085 .insert('path', sortedByArea)
40087 .each(function(entity) {
40088 var layer = this.parentNode.__data__;
40090 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
40092 if (layer === 'fill') {
40093 this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
40094 setPattern.apply(this, arguments);
40097 .call(svgTagClasses())
40098 .attr('d', path$$1);
40102 function svgDebug(projection, context) {
40104 function multipolygons(imagery) {
40105 return imagery.map(function(data$$1) {
40107 type: 'MultiPolygon',
40108 coordinates: [ data$$1.polygon ]
40113 function drawDebug(selection$$1) {
40114 var showsTile = context.getDebug('tile'),
40115 showsCollision = context.getDebug('collision'),
40116 showsImagery = context.getDebug('imagery'),
40117 showsImperial = context.getDebug('imperial'),
40118 showsDriveLeft = context.getDebug('driveLeft'),
40119 path$$1 = index$4(projection);
40122 var debugData = [];
40124 debugData.push({ class: 'red', label: 'tile' });
40126 if (showsCollision) {
40127 debugData.push({ class: 'yellow', label: 'collision' });
40129 if (showsImagery) {
40130 debugData.push({ class: 'orange', label: 'imagery' });
40132 if (showsImperial) {
40133 debugData.push({ class: 'cyan', label: 'imperial' });
40135 if (showsDriveLeft) {
40136 debugData.push({ class: 'green', label: 'driveLeft' });
40140 var legend = select('#content')
40141 .selectAll('.debug-legend')
40142 .data(debugData.length ? [0] : []);
40147 legend = legend.enter()
40149 .attr('class', 'fillD debug-legend')
40153 var legendItems = legend.selectAll('.debug-legend-item')
40154 .data(debugData, function(d) { return d.label; });
40159 legendItems.enter()
40161 .attr('class', function(d) { return 'debug-legend-item ' + d.class; })
40162 .text(function(d) { return d.label; });
40165 var layer = selection$$1.selectAll('.layer-debug')
40166 .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
40171 layer = layer.enter()
40173 .attr('class', 'layer-debug')
40177 var extent$$1 = context.map().extent(),
40178 dataImagery = data.imagery || [],
40179 availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) {
40180 if (!source.polygon) return false;
40181 return source.polygon.some(function(polygon) {
40182 return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
40186 var imagery = layer.selectAll('path.debug-imagery')
40187 .data(showsImagery ? availableImagery : []);
40194 .attr('class', 'debug-imagery debug orange');
40197 var imperial = layer
40198 .selectAll('path.debug-imperial')
40199 .data(showsImperial ? [dataImperial] : []);
40206 .attr('class', 'debug-imperial debug cyan');
40209 var driveLeft = layer
40210 .selectAll('path.debug-drive-left')
40211 .data(showsDriveLeft ? [dataDriveLeft] : []);
40218 .attr('class', 'debug-drive-left debug green');
40222 layer.selectAll('path')
40223 .attr('d', path$$1);
40227 // This looks strange because `enabled` methods on other layers are
40228 // chainable getter/setters, and this one is just a getter.
40229 drawDebug.enabled = function() {
40230 if (!arguments.length) {
40231 return context.getDebug('tile') ||
40232 context.getDebug('collision') ||
40233 context.getDebug('imagery') ||
40234 context.getDebug('imperial') ||
40235 context.getDebug('driveLeft');
40246 A standalone SVG element that contains only a `defs` sub-element. To be
40247 used once globally, since defs IDs must be unique within a document.
40249 function svgDefs(context) {
40251 function SVGSpriteDefinition(id, href) {
40252 return function(defs) {
40254 .mimeType('image/svg+xml')
40255 .response(function(xhr) { return xhr.responseXML; })
40256 .get(function(err, svg) {
40258 defs.node().appendChild(
40259 select(svg.documentElement).attr('id', id).node()
40266 return function drawDefs(selection$$1) {
40267 var defs = selection$$1.append('defs');
40270 defs.append('marker')
40271 .attr('id', 'oneway-marker')
40272 .attr('viewBox', '0 0 10 10')
40275 .attr('markerWidth', 2)
40276 .attr('markerHeight', 2)
40277 .attr('markerUnits', 'strokeWidth')
40278 .attr('orient', 'auto')
40281 .attr('class', 'oneway')
40282 .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')
40283 .attr('stroke', 'none')
40284 .attr('fill', '#000')
40285 .attr('opacity', '0.75');
40288 var patterns = defs.selectAll('pattern')
40290 // pattern name, pattern image name
40291 ['wetland', 'wetland'],
40292 ['construction', 'construction'],
40293 ['cemetery', 'cemetery'],
40294 ['orchard', 'orchard'],
40295 ['farmland', 'farmland'],
40302 .attr('id', function (d) {
40303 return 'pattern-' + d[0];
40306 .attr('height', 32)
40307 .attr('patternUnits', 'userSpaceOnUse');
40309 patterns.append('rect')
40313 .attr('height', 32)
40314 .attr('class', function (d) {
40315 return 'pattern-color-' + d[0];
40318 patterns.append('image')
40322 .attr('height', 32)
40323 .attr('xlink:href', function (d) {
40324 return context.imagePath('pattern/' + d[1] + '.png');
40329 .data([12, 18, 20, 32, 45])
40331 .append('clipPath')
40332 .attr('id', function (d) {
40333 return 'clip-square-' + d;
40338 .attr('width', function (d) {
40341 .attr('height', function (d) {
40345 defs.call(SVGSpriteDefinition(
40347 context.imagePath('iD-sprite.svg')));
40349 defs.call(SVGSpriteDefinition(
40351 context.imagePath('maki-sprite.svg')));
40355 var sax = createCommonjsModule(function (module, exports) {
40356 //[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]
40357 //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
40358 //[5] Name ::= NameStartChar (NameChar)*
40359 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
40360 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\u203F-\u2040]");
40361 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
40362 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
40363 //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(',')
40365 //S_TAG, S_ATTR, S_EQ, S_V
40366 //S_ATTR_S, S_E, S_S, S_C
40367 var S_TAG = 0;//tag name offerring
40368 var S_ATTR = 1;//attr name offerring
40369 var S_ATTR_S=2;//attr name end and space offer
40370 var S_EQ = 3;//=space?
40371 var S_V = 4;//attr value(no quot value only)
40372 var S_E = 5;//attr value end and no space(quot end)
40373 var S_S = 6;//(attr value end || tag end ) && (space offer)
40374 var S_C = 7;//closed el<el />
40376 function XMLReader(){
40380 XMLReader.prototype = {
40381 parse:function(source,defaultNSMap,entityMap){
40382 var domBuilder = this.domBuilder;
40383 domBuilder.startDocument();
40384 _copy(defaultNSMap ,defaultNSMap = {});
40385 parse(source,defaultNSMap,entityMap,
40386 domBuilder,this.errorHandler);
40387 domBuilder.endDocument();
40390 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
40391 function fixedFromCharCode(code) {
40392 // String.prototype.fromCharCode does not supports
40393 // > 2 bytes unicode chars directly
40394 if (code > 0xffff) {
40396 var surrogate1 = 0xd800 + (code >> 10)
40397 , surrogate2 = 0xdc00 + (code & 0x3ff);
40399 return String.fromCharCode(surrogate1, surrogate2);
40401 return String.fromCharCode(code);
40404 function entityReplacer(a){
40405 var k = a.slice(1,-1);
40406 if(k in entityMap){
40407 return entityMap[k];
40408 }else if(k.charAt(0) === '#'){
40409 return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
40411 errorHandler.error('entity not found:'+a);
40415 function appendText(end){//has some bugs
40417 var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
40418 locator&&position(start);
40419 domBuilder.characters(xt,0,end-start);
40423 function position(p,m){
40424 while(p>=lineEnd && (m = linePattern.exec(source))){
40425 lineStart = m.index;
40426 lineEnd = lineStart + m[0].length;
40427 locator.lineNumber++;
40428 //console.log('line++:',locator,startPos,endPos)
40430 locator.columnNumber = p-lineStart+1;
40434 var linePattern = /.+(?:\r\n?|\n)|.*$/g;
40435 var locator = domBuilder.locator;
40437 var parseStack = [{currentNSMap:defaultNSMapCopy}];
40442 var tagStart = source.indexOf('<',start);
40444 if(!source.substr(start).match(/^\s*$/)){
40445 var doc = domBuilder.document;
40446 var text = doc.createTextNode(source.substr(start));
40447 doc.appendChild(text);
40448 domBuilder.currentElement = text;
40452 if(tagStart>start){
40453 appendText(tagStart);
40455 switch(source.charAt(tagStart+1)){
40457 var end = source.indexOf('>',tagStart+3);
40458 var tagName = source.substring(tagStart+2,end);
40459 var config = parseStack.pop();
40460 var localNSMap = config.localNSMap;
40461 if(config.tagName != tagName){
40462 errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
40464 domBuilder.endElement(config.uri,config.localName,tagName);
40466 for(var prefix in localNSMap){
40467 domBuilder.endPrefixMapping(prefix) ;
40473 case '?':// <?...?>
40474 locator&&position(tagStart);
40475 end = parseInstruction(source,tagStart,domBuilder);
40477 case '!':// <!doctype,<![CDATA,<!--
40478 locator&&position(tagStart);
40479 end = parseDCC(source,tagStart,domBuilder,errorHandler);
40483 locator&&position(tagStart);
40485 var el = new ElementAttributes();
40488 var end = parseElementStartPart(source,tagStart,el,entityReplacer,errorHandler);
40489 var len = el.length;
40493 //attribute position fixed
40494 for(var i = 0;i<len;i++){
40496 position(a.offset);
40497 a.offset = copyLocator(locator,{});
40502 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
40504 if(!entityMap.nbsp){
40505 errorHandler.warning('unclosed xml attribute');
40508 appendElement(el,domBuilder,parseStack);
40511 if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
40512 end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder);
40518 errorHandler.error('element parse error: '+e);
40524 //TODO: 这里有可能sax回退,有位置错误风险
40525 appendText(Math.max(tagStart,start)+1);
40529 function copyLocator(f,t){
40530 t.lineNumber = f.lineNumber;
40531 t.columnNumber = f.columnNumber;
40536 * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
40537 * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40539 function parseElementStartPart(source,start,el,entityReplacer,errorHandler){
40543 var s = S_TAG;//status
40545 var c = source.charAt(p);
40548 if(s === S_ATTR){//attrName
40549 attrName = source.slice(start,p);
40551 }else if(s === S_ATTR_S){
40554 //fatalError: equal must after attrName or space after attrName
40555 throw new Error('attribute equal must after attrName');
40560 if(s === S_EQ){//equal
40562 p = source.indexOf(c,start);
40564 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40565 el.add(attrName,value,start-1);
40568 //fatalError: no end quot match
40569 throw new Error('attribute value no end \''+c+'\' match');
40571 }else if(s == S_V){
40572 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40573 //console.log(attrName,value,start,p)
40574 el.add(attrName,value,start);
40576 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
40580 //fatalError: no equal before
40581 throw new Error('attribute value must after "="');
40587 el.setTagName(source.slice(start,p));
40599 throw new Error("attribute invalid close char('/')")
40602 case ''://end document
40603 //throw new Error('unexpected end of input')
40604 errorHandler.error('unexpected end of input');
40608 el.setTagName(source.slice(start,p));
40613 case S_V://Compatible state
40615 value = source.slice(start,p);
40616 if(value.slice(-1) === '/'){
40618 value = value.slice(0,-1);
40621 if(s === S_ATTR_S){
40625 errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40626 el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start);
40628 errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!');
40629 el.add(value,value,start);
40633 throw new Error('attribute value missed!!');
40635 // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
40637 /*xml space '\x20' | #x9 | #xD | #xA; */
40641 if(c<= ' '){//space
40644 el.setTagName(source.slice(start,p));//tagName
40648 attrName = source.slice(start,p);
40652 var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40653 errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40654 el.add(attrName,value,start);
40666 //S_TAG, S_ATTR, S_EQ, S_V
40667 //S_ATTR_S, S_E, S_S, S_C
40669 //case S_TAG:void();break;
40670 //case S_ATTR:void();break;
40671 //case S_V:void();break;
40673 errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!');
40674 el.add(attrName,attrName,start);
40679 errorHandler.warning('attribute space is required"'+attrName+'"!!');
40689 throw new Error("elements closed character '/' and '>' must be connected to");
40697 * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40699 function appendElement(el,domBuilder,parseStack){
40700 var tagName = el.tagName;
40701 var localNSMap = null;
40702 var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
40706 var qName = a.qName;
40707 var value = a.value;
40708 var nsp = qName.indexOf(':');
40710 var prefix = a.prefix = qName.slice(0,nsp);
40711 var localName = qName.slice(nsp+1);
40712 var nsPrefix = prefix === 'xmlns' && localName;
40716 nsPrefix = qName === 'xmlns' && '';
40718 //can not set prefix,because prefix !== ''
40719 a.localName = localName ;
40720 //prefix == null for no ns prefix attribute
40721 if(nsPrefix !== false){//hack!!
40722 if(localNSMap == null){
40724 //console.log(currentNSMap,0)
40725 _copy(currentNSMap,currentNSMap={});
40726 //console.log(currentNSMap,1)
40728 currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
40729 a.uri = 'http://www.w3.org/2000/xmlns/';
40730 domBuilder.startPrefixMapping(nsPrefix, value);
40736 var prefix = a.prefix;
40737 if(prefix){//no prefix attribute has no namespace
40738 if(prefix === 'xml'){
40739 a.uri = 'http://www.w3.org/XML/1998/namespace';
40740 }if(prefix !== 'xmlns'){
40741 a.uri = currentNSMap[prefix];
40743 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
40747 var nsp = tagName.indexOf(':');
40749 prefix = el.prefix = tagName.slice(0,nsp);
40750 localName = el.localName = tagName.slice(nsp+1);
40752 prefix = null;//important!!
40753 localName = el.localName = tagName;
40755 //no prefix element has default namespace
40756 var ns = el.uri = currentNSMap[prefix || ''];
40757 domBuilder.startElement(ns,localName,tagName,el);
40758 //endPrefixMapping and startPrefixMapping have not any help for dom builder
40759 //localNSMap = null
40761 domBuilder.endElement(ns,localName,tagName);
40763 for(prefix in localNSMap){
40764 domBuilder.endPrefixMapping(prefix);
40768 el.currentNSMap = currentNSMap;
40769 el.localNSMap = localNSMap;
40770 parseStack.push(el);
40773 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
40774 if(/^(?:script|textarea)$/i.test(tagName)){
40775 var elEndStart = source.indexOf('</'+tagName+'>',elStartEnd);
40776 var text = source.substring(elStartEnd+1,elEndStart);
40777 if(/[&<]/.test(text)){
40778 if(/^script$/i.test(tagName)){
40779 //if(!/\]\]>/.test(text)){
40780 //lexHandler.startCDATA();
40781 domBuilder.characters(text,0,text.length);
40782 //lexHandler.endCDATA();
40785 }//}else{//text area
40786 text = text.replace(/&#?\w+;/g,entityReplacer);
40787 domBuilder.characters(text,0,text.length);
40793 return elStartEnd+1;
40795 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
40796 //if(tagName in closeMap){
40797 var pos = closeMap[tagName];
40799 //console.log(tagName)
40800 pos = closeMap[tagName] = source.lastIndexOf('</'+tagName+'>');
40802 return pos<elStartEnd;
40805 function _copy(source,target){
40806 for(var n in source){target[n] = source[n];}
40808 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
40809 var next= source.charAt(start+2);
40812 if(source.charAt(start + 3) === '-'){
40813 var end = source.indexOf('-->',start+4);
40814 //append comment source.substring(4,end)//<!--
40816 domBuilder.comment(source,start+4,end-start-4);
40819 errorHandler.error("Unclosed comment");
40827 if(source.substr(start+3,6) == 'CDATA['){
40828 var end = source.indexOf(']]>',start+9);
40829 domBuilder.startCDATA();
40830 domBuilder.characters(source,start+9,end-start-9);
40831 domBuilder.endCDATA();
40835 //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
40836 var matchs = split(source,start);
40837 var len = matchs.length;
40838 if(len>1 && /!doctype/i.test(matchs[0][0])){
40839 var name = matchs[1][0];
40840 var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
40841 var sysid = len>4 && matchs[4][0];
40842 var lastMatch = matchs[len-1];
40843 domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
40844 sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
40845 domBuilder.endDTD();
40847 return lastMatch.index+lastMatch[0].length
40855 function parseInstruction(source,start,domBuilder){
40856 var end = source.indexOf('?>',start);
40858 var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
40860 var len = match[0].length;
40861 domBuilder.processingInstruction(match[1], match[2]) ;
40873 function ElementAttributes(source){
40876 ElementAttributes.prototype = {
40877 setTagName:function(tagName){
40878 if(!tagNamePattern.test(tagName)){
40879 throw new Error('invalid tagName:'+tagName)
40881 this.tagName = tagName;
40883 add:function(qName,value,offset){
40884 if(!tagNamePattern.test(qName)){
40885 throw new Error('invalid attribute:'+qName)
40887 this[this.length++] = {qName:qName,value:value,offset:offset};
40890 getLocalName:function(i){return this[i].localName},
40891 getOffset:function(i){return this[i].offset},
40892 getQName:function(i){return this[i].qName},
40893 getURI:function(i){return this[i].uri},
40894 getValue:function(i){return this[i].value}
40895 // ,getIndex:function(uri, localName)){
40902 // getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
40903 // getType:function(uri,localName){}
40904 // getType:function(i){},
40910 function _set_proto_(thiz,parent){
40911 thiz.__proto__ = parent;
40914 if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
40915 _set_proto_ = function(thiz,parent){
40917 p.prototype = parent;
40919 for(parent in thiz){
40920 p[parent] = thiz[parent];
40926 function split(source,start){
40929 var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
40930 reg.lastIndex = start;
40931 reg.exec(source);//skip <
40932 while(match = reg.exec(source)){
40934 if(match[1])return buf;
40938 if(typeof commonjsRequire == 'function'){
40939 exports.XMLReader = XMLReader;
40943 var dom = createCommonjsModule(function (module, exports) {
40946 * Object DOMException
40947 * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
40948 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
40951 function copy(src,dest){
40957 ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
40958 ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
40960 function _extends(Class,Super){
40961 var pt = Class.prototype;
40963 var ppt = Object.create(Super.prototype);
40964 pt.__proto__ = ppt;
40966 if(!(pt instanceof Super)){
40968 t.prototype = Super.prototype;
40971 Class.prototype = pt = t;
40973 if(pt.constructor != Class){
40974 if(typeof Class != 'function'){
40975 console.error("unknow Class:"+Class);
40977 pt.constructor = Class;
40980 var htmlns = 'http://www.w3.org/1999/xhtml';
40983 var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
40984 var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
40985 var TEXT_NODE = NodeType.TEXT_NODE = 3;
40986 var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4;
40987 var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5;
40988 var ENTITY_NODE = NodeType.ENTITY_NODE = 6;
40989 var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
40990 var COMMENT_NODE = NodeType.COMMENT_NODE = 8;
40991 var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9;
40992 var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10;
40993 var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
40994 var NOTATION_NODE = NodeType.NOTATION_NODE = 12;
40997 var ExceptionCode = {};
40998 var ExceptionMessage = {};
40999 var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1);
41000 var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2);
41001 var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3]="Hierarchy request error"),3);
41002 var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4]="Wrong document"),4);
41003 var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5]="Invalid character"),5);
41004 var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6]="No data allowed"),6);
41005 var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
41006 var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8]="Not found"),8);
41007 var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9]="Not supported"),9);
41008 var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10]="Attribute in use"),10);
41010 var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11]="Invalid state"),11);
41011 var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12]="Syntax error"),12);
41012 var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13]="Invalid modification"),13);
41013 var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14);
41014 var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15]="Invalid access"),15);
41017 function DOMException(code, message) {
41018 if(message instanceof Error){
41019 var error = message;
41022 Error.call(this, ExceptionMessage[code]);
41023 this.message = ExceptionMessage[code];
41024 if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
41027 if(message) this.message = this.message + ": " + message;
41030 DOMException.prototype = Error.prototype;
41031 copy(ExceptionCode,DOMException);
41033 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
41034 * 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.
41035 * The items in the NodeList are accessible via an integral index, starting from 0.
41037 function NodeList() {
41039 NodeList.prototype = {
41041 * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
41046 * 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.
41048 * @param index unsigned long
41049 * Index into the collection.
41051 * The node at the indexth position in the NodeList, or null if that is not a valid index.
41053 item: function(index) {
41054 return this[index] || null;
41056 toString:function(){
41057 for(var buf = [], i = 0;i<this.length;i++){
41058 serializeToString(this[i],buf);
41060 return buf.join('');
41063 function LiveNodeList(node,refresh){
41065 this._refresh = refresh;
41066 _updateLiveList(this);
41068 function _updateLiveList(list){
41069 var inc = list._node._inc || list._node.ownerDocument._inc;
41070 if(list._inc != inc){
41071 var ls = list._refresh(list._node);
41072 //console.log(ls.length)
41073 __set__(list,'length',ls.length);
41078 LiveNodeList.prototype.item = function(i){
41079 _updateLiveList(this);
41083 _extends(LiveNodeList,NodeList);
41086 * 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.
41087 * NamedNodeMap objects in the DOM are live.
41088 * used for attributes or DocumentType entities
41090 function NamedNodeMap() {
41093 function _findNodeIndex(list,node){
41094 var i = list.length;
41096 if(list[i] === node){return i}
41100 function _addNamedNode(el,list,newAttr,oldAttr){
41102 list[_findNodeIndex(list,oldAttr)] = newAttr;
41104 list[list.length++] = newAttr;
41107 newAttr.ownerElement = el;
41108 var doc = el.ownerDocument;
41110 oldAttr && _onRemoveAttribute(doc,el,oldAttr);
41111 _onAddAttribute(doc,el,newAttr);
41115 function _removeNamedNode(el,list,attr){
41116 var i = _findNodeIndex(list,attr);
41118 var lastIndex = list.length-1;
41119 while(i<lastIndex){
41120 list[i] = list[++i];
41122 list.length = lastIndex;
41124 var doc = el.ownerDocument;
41126 _onRemoveAttribute(doc,el,attr);
41127 attr.ownerElement = null;
41131 throw DOMException(NOT_FOUND_ERR,new Error())
41134 NamedNodeMap.prototype = {
41136 item:NodeList.prototype.item,
41137 getNamedItem: function(key) {
41138 // if(key.indexOf(':')>0 || key == 'xmlns'){
41141 var i = this.length;
41143 var attr = this[i];
41144 if(attr.nodeName == key){
41149 setNamedItem: function(attr) {
41150 var el = attr.ownerElement;
41151 if(el && el!=this._ownerElement){
41152 throw new DOMException(INUSE_ATTRIBUTE_ERR);
41154 var oldAttr = this.getNamedItem(attr.nodeName);
41155 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41159 setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
41160 var el = attr.ownerElement, oldAttr;
41161 if(el && el!=this._ownerElement){
41162 throw new DOMException(INUSE_ATTRIBUTE_ERR);
41164 oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
41165 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41170 removeNamedItem: function(key) {
41171 var attr = this.getNamedItem(key);
41172 _removeNamedNode(this._ownerElement,this,attr);
41176 },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
41179 removeNamedItemNS:function(namespaceURI,localName){
41180 var attr = this.getNamedItemNS(namespaceURI,localName);
41181 _removeNamedNode(this._ownerElement,this,attr);
41184 getNamedItemNS: function(namespaceURI, localName) {
41185 var i = this.length;
41187 var node = this[i];
41188 if(node.localName == localName && node.namespaceURI == namespaceURI){
41196 * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
41198 function DOMImplementation(/* Object */ features) {
41199 this._features = {};
41201 for (var feature in features) {
41202 this._features = features[feature];
41207 DOMImplementation.prototype = {
41208 hasFeature: function(/* string */ feature, /* string */ version) {
41209 var versions = this._features[feature.toLowerCase()];
41210 if (versions && (!version || version in versions)) {
41216 // Introduced in DOM Level 2:
41217 createDocument:function(namespaceURI, qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
41218 var doc = new Document();
41219 doc.implementation = this;
41220 doc.childNodes = new NodeList();
41221 doc.doctype = doctype;
41223 doc.appendChild(doctype);
41226 var root = doc.createElementNS(namespaceURI,qualifiedName);
41227 doc.appendChild(root);
41231 // Introduced in DOM Level 2:
41232 createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
41233 var node = new DocumentType();
41234 node.name = qualifiedName;
41235 node.nodeName = qualifiedName;
41236 node.publicId = publicId;
41237 node.systemId = systemId;
41238 // Introduced in DOM Level 2:
41239 //readonly attribute DOMString internalSubset;
41242 // readonly attribute NamedNodeMap entities;
41243 // readonly attribute NamedNodeMap notations;
41250 * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
41259 previousSibling : null,
41260 nextSibling : null,
41264 ownerDocument : null,
41266 namespaceURI : null,
41269 // Modified in DOM Level 2:
41270 insertBefore:function(newChild, refChild){//raises
41271 return _insertBefore(this,newChild,refChild);
41273 replaceChild:function(newChild, oldChild){//raises
41274 this.insertBefore(newChild,oldChild);
41276 this.removeChild(oldChild);
41279 removeChild:function(oldChild){
41280 return _removeChild(this,oldChild);
41282 appendChild:function(newChild){
41283 return this.insertBefore(newChild,null);
41285 hasChildNodes:function(){
41286 return this.firstChild != null;
41288 cloneNode:function(deep){
41289 return cloneNode(this.ownerDocument||this,this,deep);
41291 // Modified in DOM Level 2:
41292 normalize:function(){
41293 var child = this.firstChild;
41295 var next = child.nextSibling;
41296 if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
41297 this.removeChild(next);
41298 child.appendData(next.data);
41305 // Introduced in DOM Level 2:
41306 isSupported:function(feature, version){
41307 return this.ownerDocument.implementation.hasFeature(feature,version);
41309 // Introduced in DOM Level 2:
41310 hasAttributes:function(){
41311 return this.attributes.length>0;
41313 lookupPrefix:function(namespaceURI){
41316 var map = el._nsMap;
41320 if(map[n] == namespaceURI){
41325 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
41329 // Introduced in DOM Level 3:
41330 lookupNamespaceURI:function(prefix){
41333 var map = el._nsMap;
41337 return map[prefix] ;
41340 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
41344 // Introduced in DOM Level 3:
41345 isDefaultNamespace:function(namespaceURI){
41346 var prefix = this.lookupPrefix(namespaceURI);
41347 return prefix == null;
41352 function _xmlEncoder(c){
41353 return c == '<' && '<' ||
41354 c == '>' && '>' ||
41355 c == '&' && '&' ||
41356 c == '"' && '"' ||
41357 '&#'+c.charCodeAt()+';'
41361 copy(NodeType,Node);
41362 copy(NodeType,Node.prototype);
41365 * @param callback return true for continue,false for break
41366 * @return boolean true: break visit;
41368 function _visitNode(node,callback){
41369 if(callback(node)){
41372 if(node = node.firstChild){
41374 if(_visitNode(node,callback)){return true}
41375 }while(node=node.nextSibling)
41381 function Document(){
41383 function _onAddAttribute(doc,el,newAttr){
41385 var ns = newAttr.namespaceURI;
41386 if(ns == 'http://www.w3.org/2000/xmlns/'){
41388 el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value;
41391 function _onRemoveAttribute(doc,el,newAttr,remove){
41393 var ns = newAttr.namespaceURI;
41394 if(ns == 'http://www.w3.org/2000/xmlns/'){
41396 delete el._nsMap[newAttr.prefix?newAttr.localName:''];
41399 function _onUpdateChild(doc,el,newChild){
41400 if(doc && doc._inc){
41402 //update childNodes
41403 var cs = el.childNodes;
41405 cs[cs.length++] = newChild;
41408 var child = el.firstChild;
41412 child =child.nextSibling;
41423 * writeable properties:
41424 * nodeValue,Attr:value,CharacterData:data
41427 function _removeChild(parentNode,child){
41428 var previous = child.previousSibling;
41429 var next = child.nextSibling;
41431 previous.nextSibling = next;
41433 parentNode.firstChild = next;
41436 next.previousSibling = previous;
41438 parentNode.lastChild = previous;
41440 _onUpdateChild(parentNode.ownerDocument,parentNode);
41444 * preformance key(refChild == null)
41446 function _insertBefore(parentNode,newChild,nextChild){
41447 var cp = newChild.parentNode;
41449 cp.removeChild(newChild);//remove and update
41451 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41452 var newFirst = newChild.firstChild;
41453 if (newFirst == null) {
41456 var newLast = newChild.lastChild;
41458 newFirst = newLast = newChild;
41460 var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
41462 newFirst.previousSibling = pre;
41463 newLast.nextSibling = nextChild;
41467 pre.nextSibling = newFirst;
41469 parentNode.firstChild = newFirst;
41471 if(nextChild == null){
41472 parentNode.lastChild = newLast;
41474 nextChild.previousSibling = newLast;
41477 newFirst.parentNode = parentNode;
41478 }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
41479 _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
41480 //console.log(parentNode.lastChild.nextSibling == null)
41481 if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
41482 newChild.firstChild = newChild.lastChild = null;
41486 function _appendSingleChild(parentNode,newChild){
41487 var cp = newChild.parentNode;
41489 var pre = parentNode.lastChild;
41490 cp.removeChild(newChild);//remove and update
41491 var pre = parentNode.lastChild;
41493 var pre = parentNode.lastChild;
41494 newChild.parentNode = parentNode;
41495 newChild.previousSibling = pre;
41496 newChild.nextSibling = null;
41498 pre.nextSibling = newChild;
41500 parentNode.firstChild = newChild;
41502 parentNode.lastChild = newChild;
41503 _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
41505 //console.log("__aa",parentNode.lastChild.nextSibling == null)
41507 Document.prototype = {
41508 //implementation : null,
41509 nodeName : '#document',
41510 nodeType : DOCUMENT_NODE,
41512 documentElement : null,
41515 insertBefore : function(newChild, refChild){//raises
41516 if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
41517 var child = newChild.firstChild;
41519 var next = child.nextSibling;
41520 this.insertBefore(child,refChild);
41525 if(this.documentElement == null && newChild.nodeType == 1){
41526 this.documentElement = newChild;
41529 return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
41531 removeChild : function(oldChild){
41532 if(this.documentElement == oldChild){
41533 this.documentElement = null;
41535 return _removeChild(this,oldChild);
41537 // Introduced in DOM Level 2:
41538 importNode : function(importedNode,deep){
41539 return importNode(this,importedNode,deep);
41541 // Introduced in DOM Level 2:
41542 getElementById : function(id){
41544 _visitNode(this.documentElement,function(node){
41545 if(node.nodeType == 1){
41546 if(node.getAttribute('id') == id){
41555 //document factory method:
41556 createElement : function(tagName){
41557 var node = new Element();
41558 node.ownerDocument = this;
41559 node.nodeName = tagName;
41560 node.tagName = tagName;
41561 node.childNodes = new NodeList();
41562 var attrs = node.attributes = new NamedNodeMap();
41563 attrs._ownerElement = node;
41566 createDocumentFragment : function(){
41567 var node = new DocumentFragment();
41568 node.ownerDocument = this;
41569 node.childNodes = new NodeList();
41572 createTextNode : function(data){
41573 var node = new Text();
41574 node.ownerDocument = this;
41575 node.appendData(data);
41578 createComment : function(data){
41579 var node = new Comment();
41580 node.ownerDocument = this;
41581 node.appendData(data);
41584 createCDATASection : function(data){
41585 var node = new CDATASection();
41586 node.ownerDocument = this;
41587 node.appendData(data);
41590 createProcessingInstruction : function(target,data){
41591 var node = new ProcessingInstruction();
41592 node.ownerDocument = this;
41593 node.tagName = node.target = target;
41594 node.nodeValue= node.data = data;
41597 createAttribute : function(name){
41598 var node = new Attr();
41599 node.ownerDocument = this;
41601 node.nodeName = name;
41602 node.localName = name;
41603 node.specified = true;
41606 createEntityReference : function(name){
41607 var node = new EntityReference();
41608 node.ownerDocument = this;
41609 node.nodeName = name;
41612 // Introduced in DOM Level 2:
41613 createElementNS : function(namespaceURI,qualifiedName){
41614 var node = new Element();
41615 var pl = qualifiedName.split(':');
41616 var attrs = node.attributes = new NamedNodeMap();
41617 node.childNodes = new NodeList();
41618 node.ownerDocument = this;
41619 node.nodeName = qualifiedName;
41620 node.tagName = qualifiedName;
41621 node.namespaceURI = namespaceURI;
41622 if(pl.length == 2){
41623 node.prefix = pl[0];
41624 node.localName = pl[1];
41626 //el.prefix = null;
41627 node.localName = qualifiedName;
41629 attrs._ownerElement = node;
41632 // Introduced in DOM Level 2:
41633 createAttributeNS : function(namespaceURI,qualifiedName){
41634 var node = new Attr();
41635 var pl = qualifiedName.split(':');
41636 node.ownerDocument = this;
41637 node.nodeName = qualifiedName;
41638 node.name = qualifiedName;
41639 node.namespaceURI = namespaceURI;
41640 node.specified = true;
41641 if(pl.length == 2){
41642 node.prefix = pl[0];
41643 node.localName = pl[1];
41645 //el.prefix = null;
41646 node.localName = qualifiedName;
41651 _extends(Document,Node);
41654 function Element() {
41657 Element.prototype = {
41658 nodeType : ELEMENT_NODE,
41659 hasAttribute : function(name){
41660 return this.getAttributeNode(name)!=null;
41662 getAttribute : function(name){
41663 var attr = this.getAttributeNode(name);
41664 return attr && attr.value || '';
41666 getAttributeNode : function(name){
41667 return this.attributes.getNamedItem(name);
41669 setAttribute : function(name, value){
41670 var attr = this.ownerDocument.createAttribute(name);
41671 attr.value = attr.nodeValue = "" + value;
41672 this.setAttributeNode(attr);
41674 removeAttribute : function(name){
41675 var attr = this.getAttributeNode(name);
41676 attr && this.removeAttributeNode(attr);
41679 //four real opeartion method
41680 appendChild:function(newChild){
41681 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41682 return this.insertBefore(newChild,null);
41684 return _appendSingleChild(this,newChild);
41687 setAttributeNode : function(newAttr){
41688 return this.attributes.setNamedItem(newAttr);
41690 setAttributeNodeNS : function(newAttr){
41691 return this.attributes.setNamedItemNS(newAttr);
41693 removeAttributeNode : function(oldAttr){
41694 return this.attributes.removeNamedItem(oldAttr.nodeName);
41696 //get real attribute name,and remove it by removeAttributeNode
41697 removeAttributeNS : function(namespaceURI, localName){
41698 var old = this.getAttributeNodeNS(namespaceURI, localName);
41699 old && this.removeAttributeNode(old);
41702 hasAttributeNS : function(namespaceURI, localName){
41703 return this.getAttributeNodeNS(namespaceURI, localName)!=null;
41705 getAttributeNS : function(namespaceURI, localName){
41706 var attr = this.getAttributeNodeNS(namespaceURI, localName);
41707 return attr && attr.value || '';
41709 setAttributeNS : function(namespaceURI, qualifiedName, value){
41710 var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
41711 attr.value = attr.nodeValue = "" + value;
41712 this.setAttributeNode(attr);
41714 getAttributeNodeNS : function(namespaceURI, localName){
41715 return this.attributes.getNamedItemNS(namespaceURI, localName);
41718 getElementsByTagName : function(tagName){
41719 return new LiveNodeList(this,function(base){
41721 _visitNode(base,function(node){
41722 if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
41729 getElementsByTagNameNS : function(namespaceURI, localName){
41730 return new LiveNodeList(this,function(base){
41732 _visitNode(base,function(node){
41733 if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
41741 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
41742 Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
41745 _extends(Element,Node);
41748 Attr.prototype.nodeType = ATTRIBUTE_NODE;
41749 _extends(Attr,Node);
41752 function CharacterData() {
41754 CharacterData.prototype = {
41756 substringData : function(offset, count) {
41757 return this.data.substring(offset, offset+count);
41759 appendData: function(text) {
41760 text = this.data+text;
41761 this.nodeValue = this.data = text;
41762 this.length = text.length;
41764 insertData: function(offset,text) {
41765 this.replaceData(offset,0,text);
41768 appendChild:function(newChild){
41769 //if(!(newChild instanceof CharacterData)){
41770 throw new Error(ExceptionMessage[3])
41772 return Node.prototype.appendChild.apply(this,arguments)
41774 deleteData: function(offset, count) {
41775 this.replaceData(offset,count,"");
41777 replaceData: function(offset, count, text) {
41778 var start = this.data.substring(0,offset);
41779 var end = this.data.substring(offset+count);
41780 text = start + text + end;
41781 this.nodeValue = this.data = text;
41782 this.length = text.length;
41785 _extends(CharacterData,Node);
41789 nodeName : "#text",
41790 nodeType : TEXT_NODE,
41791 splitText : function(offset) {
41792 var text = this.data;
41793 var newText = text.substring(offset);
41794 text = text.substring(0, offset);
41795 this.data = this.nodeValue = text;
41796 this.length = text.length;
41797 var newNode = this.ownerDocument.createTextNode(newText);
41798 if(this.parentNode){
41799 this.parentNode.insertBefore(newNode, this.nextSibling);
41804 _extends(Text,CharacterData);
41805 function Comment() {
41807 Comment.prototype = {
41808 nodeName : "#comment",
41809 nodeType : COMMENT_NODE
41811 _extends(Comment,CharacterData);
41813 function CDATASection() {
41815 CDATASection.prototype = {
41816 nodeName : "#cdata-section",
41817 nodeType : CDATA_SECTION_NODE
41819 _extends(CDATASection,CharacterData);
41822 function DocumentType() {
41824 DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
41825 _extends(DocumentType,Node);
41827 function Notation() {
41829 Notation.prototype.nodeType = NOTATION_NODE;
41830 _extends(Notation,Node);
41832 function Entity() {
41834 Entity.prototype.nodeType = ENTITY_NODE;
41835 _extends(Entity,Node);
41837 function EntityReference() {
41839 EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
41840 _extends(EntityReference,Node);
41842 function DocumentFragment() {
41844 DocumentFragment.prototype.nodeName = "#document-fragment";
41845 DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
41846 _extends(DocumentFragment,Node);
41849 function ProcessingInstruction() {
41851 ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
41852 _extends(ProcessingInstruction,Node);
41853 function XMLSerializer(){}
41854 XMLSerializer.prototype.serializeToString = function(node,attributeSorter){
41855 return node.toString(attributeSorter);
41857 Node.prototype.toString =function(attributeSorter){
41859 serializeToString(this,buf,attributeSorter);
41860 return buf.join('');
41862 function serializeToString(node,buf,attributeSorter,isHTML){
41863 switch(node.nodeType){
41865 var attrs = node.attributes;
41866 var len = attrs.length;
41867 var child = node.firstChild;
41868 var nodeName = node.tagName;
41869 isHTML = (htmlns === node.namespaceURI) ||isHTML;
41870 buf.push('<',nodeName);
41871 if(attributeSorter){
41872 buf.sort.apply(attrs, attributeSorter);
41874 for(var i=0;i<len;i++){
41875 serializeToString(attrs.item(i),buf,attributeSorter,isHTML);
41877 if(child || isHTML && !/^(?:meta|link|img|br|hr|input|button)$/i.test(nodeName)){
41879 //if is cdata child node
41880 if(isHTML && /^script$/i.test(nodeName)){
41882 buf.push(child.data);
41886 serializeToString(child,buf,attributeSorter,isHTML);
41887 child = child.nextSibling;
41890 buf.push('</',nodeName,'>');
41895 case DOCUMENT_NODE:
41896 case DOCUMENT_FRAGMENT_NODE:
41897 var child = node.firstChild;
41899 serializeToString(child,buf,attributeSorter,isHTML);
41900 child = child.nextSibling;
41903 case ATTRIBUTE_NODE:
41904 return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
41906 return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
41907 case CDATA_SECTION_NODE:
41908 return buf.push( '<![CDATA[',node.data,']]>');
41910 return buf.push( "<!--",node.data,"-->");
41911 case DOCUMENT_TYPE_NODE:
41912 var pubid = node.publicId;
41913 var sysid = node.systemId;
41914 buf.push('<!DOCTYPE ',node.name);
41916 buf.push(' PUBLIC "',pubid);
41917 if (sysid && sysid!='.') {
41918 buf.push( '" "',sysid);
41921 }else if(sysid && sysid!='.'){
41922 buf.push(' SYSTEM "',sysid,'">');
41924 var sub = node.internalSubset;
41926 buf.push(" [",sub,"]");
41931 case PROCESSING_INSTRUCTION_NODE:
41932 return buf.push( "<?",node.target," ",node.data,"?>");
41933 case ENTITY_REFERENCE_NODE:
41934 return buf.push( '&',node.nodeName,';');
41935 //case ENTITY_NODE:
41936 //case NOTATION_NODE:
41938 buf.push('??',node.nodeName);
41941 function importNode(doc,node,deep){
41943 switch (node.nodeType) {
41945 node2 = node.cloneNode(false);
41946 node2.ownerDocument = doc;
41947 //var attrs = node2.attributes;
41948 //var len = attrs.length;
41949 //for(var i=0;i<len;i++){
41950 //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
41952 case DOCUMENT_FRAGMENT_NODE:
41954 case ATTRIBUTE_NODE:
41957 //case ENTITY_REFERENCE_NODE:
41958 //case PROCESSING_INSTRUCTION_NODE:
41959 ////case TEXT_NODE:
41960 //case CDATA_SECTION_NODE:
41961 //case COMMENT_NODE:
41964 //case DOCUMENT_NODE:
41965 //case DOCUMENT_TYPE_NODE:
41966 //cannot be imported.
41967 //case ENTITY_NODE:
41968 //case NOTATION_NODE:
41969 //can not hit in level3
41973 node2 = node.cloneNode(false);//false
41975 node2.ownerDocument = doc;
41976 node2.parentNode = null;
41978 var child = node.firstChild;
41980 node2.appendChild(importNode(doc,child,deep));
41981 child = child.nextSibling;
41987 //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
41988 // attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
41989 function cloneNode(doc,node,deep){
41990 var node2 = new node.constructor();
41991 for(var n in node){
41993 if(typeof v != 'object' ){
41999 if(node.childNodes){
42000 node2.childNodes = new NodeList();
42002 node2.ownerDocument = doc;
42003 switch (node2.nodeType) {
42005 var attrs = node.attributes;
42006 var attrs2 = node2.attributes = new NamedNodeMap();
42007 var len = attrs.length;
42008 attrs2._ownerElement = node2;
42009 for(var i=0;i<len;i++){
42010 node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
42013 case ATTRIBUTE_NODE:
42017 var child = node.firstChild;
42019 node2.appendChild(cloneNode(doc,child,deep));
42020 child = child.nextSibling;
42026 function __set__(object,key,value){
42027 object[key] = value;
42031 if(Object.defineProperty){
42032 Object.defineProperty(LiveNodeList.prototype,'length',{
42034 _updateLiveList(this);
42035 return this.$$length;
42038 Object.defineProperty(Node.prototype,'textContent',{
42040 return getTextContent(this);
42042 set:function(data){
42043 switch(this.nodeType){
42046 while(this.firstChild){
42047 this.removeChild(this.firstChild);
42049 if(data || String(data)){
42050 this.appendChild(this.ownerDocument.createTextNode(data));
42056 this.value = value;
42057 this.nodeValue = data;
42062 function getTextContent(node){
42063 switch(node.nodeType){
42067 node = node.firstChild;
42069 if(node.nodeType!==7 && node.nodeType !==8){
42070 buf.push(getTextContent(node));
42072 node = node.nextSibling;
42074 return buf.join('');
42076 return node.nodeValue;
42079 __set__ = function(object,key,value){
42080 //console.log(value)
42081 object['$$'+key] = value;
42087 if(typeof commonjsRequire == 'function'){
42088 exports.DOMImplementation = DOMImplementation;
42089 exports.XMLSerializer = XMLSerializer;
42093 var domParser = createCommonjsModule(function (module, exports) {
42094 function DOMParser(options){
42095 this.options = options ||{locator:{}};
42098 DOMParser.prototype.parseFromString = function(source,mimeType){
42099 var options = this.options;
42100 var sax$$1 = new XMLReader();
42101 var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
42102 var errorHandler = options.errorHandler;
42103 var locator = options.locator;
42104 var defaultNSMap = options.xmlns||{};
42105 var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
42107 domBuilder.setDocumentLocator(locator);
42110 sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
42111 sax$$1.domBuilder = options.domBuilder || domBuilder;
42112 if(/\/x?html?$/.test(mimeType)){
42113 entityMap.nbsp = '\xa0';
42114 entityMap.copy = '\xa9';
42115 defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
42117 defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
42119 sax$$1.parse(source,defaultNSMap,entityMap);
42121 sax$$1.errorHandler.error("invalid document source");
42123 return domBuilder.document;
42125 function buildErrorHandler(errorImpl,domBuilder,locator){
42127 if(domBuilder instanceof DOMHandler){
42130 errorImpl = domBuilder ;
42132 var errorHandler = {};
42133 var isCallback = errorImpl instanceof Function;
42134 locator = locator||{};
42135 function build(key){
42136 var fn = errorImpl[key];
42137 if(!fn && isCallback){
42138 fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl;
42140 errorHandler[key] = fn && function(msg){
42141 fn('[xmldom '+key+']\t'+msg+_locator(locator));
42146 build('fatalError');
42147 return errorHandler;
42150 //console.log('#\n\n\n\n\n\n\n####')
42152 * +ContentHandler+ErrorHandler
42153 * +LexicalHandler+EntityResolver2
42154 * -DeclHandler-DTDHandler
42156 * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
42157 * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
42158 * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
42160 function DOMHandler() {
42161 this.cdata = false;
42163 function position(locator,node){
42164 node.lineNumber = locator.lineNumber;
42165 node.columnNumber = locator.columnNumber;
42168 * @see org.xml.sax.ContentHandler#startDocument
42169 * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
42171 DOMHandler.prototype = {
42172 startDocument : function() {
42173 this.document = new DOMImplementation().createDocument(null, null, null);
42174 if (this.locator) {
42175 this.document.documentURI = this.locator.systemId;
42178 startElement:function(namespaceURI, localName, qName, attrs) {
42179 var doc = this.document;
42180 var el = doc.createElementNS(namespaceURI, qName||localName);
42181 var len = attrs.length;
42182 appendElement(this, el);
42183 this.currentElement = el;
42185 this.locator && position(this.locator,el);
42186 for (var i = 0 ; i < len; i++) {
42187 var namespaceURI = attrs.getURI(i);
42188 var value = attrs.getValue(i);
42189 var qName = attrs.getQName(i);
42190 var attr = doc.createAttributeNS(namespaceURI, qName);
42191 if( attr.getOffset){
42192 position(attr.getOffset(1),attr);
42194 attr.value = attr.nodeValue = value;
42195 el.setAttributeNode(attr);
42198 endElement:function(namespaceURI, localName, qName) {
42199 var current = this.currentElement;
42200 var tagName = current.tagName;
42201 this.currentElement = current.parentNode;
42203 startPrefixMapping:function(prefix, uri) {
42205 endPrefixMapping:function(prefix) {
42207 processingInstruction:function(target, data) {
42208 var ins = this.document.createProcessingInstruction(target, data);
42209 this.locator && position(this.locator,ins);
42210 appendElement(this, ins);
42212 ignorableWhitespace:function(ch, start, length) {
42214 characters:function(chars, start, length) {
42215 chars = _toString.apply(this,arguments);
42216 //console.log(chars)
42217 if(this.currentElement && chars){
42219 var charNode = this.document.createCDATASection(chars);
42220 this.currentElement.appendChild(charNode);
42222 var charNode = this.document.createTextNode(chars);
42223 this.currentElement.appendChild(charNode);
42225 this.locator && position(this.locator,charNode);
42228 skippedEntity:function(name) {
42230 endDocument:function() {
42231 this.document.normalize();
42233 setDocumentLocator:function (locator) {
42234 if(this.locator = locator){// && !('lineNumber' in locator)){
42235 locator.lineNumber = 0;
42239 comment:function(chars, start, length) {
42240 chars = _toString.apply(this,arguments);
42241 var comm = this.document.createComment(chars);
42242 this.locator && position(this.locator,comm);
42243 appendElement(this, comm);
42246 startCDATA:function() {
42247 //used in characters() methods
42250 endCDATA:function() {
42251 this.cdata = false;
42254 startDTD:function(name, publicId, systemId) {
42255 var impl = this.document.implementation;
42256 if (impl && impl.createDocumentType) {
42257 var dt = impl.createDocumentType(name, publicId, systemId);
42258 this.locator && position(this.locator,dt);
42259 appendElement(this, dt);
42263 * @see org.xml.sax.ErrorHandler
42264 * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
42266 warning:function(error) {
42267 console.warn('[xmldom warning]\t'+error,_locator(this.locator));
42269 error:function(error) {
42270 console.error('[xmldom error]\t'+error,_locator(this.locator));
42272 fatalError:function(error) {
42273 console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
42277 function _locator(l){
42279 return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
42282 function _toString(chars,start,length){
42283 if(typeof chars == 'string'){
42284 return chars.substr(start,length)
42285 }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
42286 if(chars.length >= start+length || start){
42287 return new java.lang.String(chars,start,length)+'';
42294 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
42295 * used method of org.xml.sax.ext.LexicalHandler:
42296 * #comment(chars, start, length)
42299 * #startDTD(name, publicId, systemId)
42302 * IGNORED method of org.xml.sax.ext.LexicalHandler:
42304 * #startEntity(name)
42308 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
42309 * IGNORED method of org.xml.sax.ext.DeclHandler
42310 * #attributeDecl(eName, aName, type, mode, value)
42311 * #elementDecl(name, model)
42312 * #externalEntityDecl(name, publicId, systemId)
42313 * #internalEntityDecl(name, value)
42314 * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
42315 * IGNORED method of org.xml.sax.EntityResolver2
42316 * #resolveEntity(String name,String publicId,String baseURI,String systemId)
42317 * #resolveEntity(publicId, systemId)
42318 * #getExternalSubset(name, baseURI)
42319 * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
42320 * IGNORED method of org.xml.sax.DTDHandler
42321 * #notationDecl(name, publicId, systemId) {};
42322 * #unparsedEntityDecl(name, publicId, systemId, notationName) {};
42324 "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
42325 DOMHandler.prototype[key] = function(){return null};
42328 /* 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 */
42329 function appendElement (hander,node) {
42330 if (!hander.currentElement) {
42331 hander.document.appendChild(node);
42333 hander.currentElement.appendChild(node);
42335 }//appendChild and setAttributeNS are preformance key
42337 if(typeof commonjsRequire == 'function'){
42338 var XMLReader = sax.XMLReader;
42339 var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation;
42340 exports.XMLSerializer = dom.XMLSerializer ;
42341 exports.DOMParser = DOMParser;
42345 var togeojson = createCommonjsModule(function (module, exports) {
42346 var toGeoJSON = (function() {
42349 var removeSpace = /\s*/g,
42350 trimSpace = /^\s*|\s*$/g,
42351 splitSpace = /\s+/;
42352 // generate a short, numeric hash of a string
42353 function okhash(x) {
42354 if (!x || !x.length) return 0;
42355 for (var i = 0, h = 0; i < x.length; i++) {
42356 h = ((h << 5) - h) + x.charCodeAt(i) | 0;
42359 // all Y children of X
42360 function get(x, y) { return x.getElementsByTagName(y); }
42361 function attr(x, y) { return x.getAttribute(y); }
42362 function attrf(x, y) { return parseFloat(attr(x, y)); }
42363 // one Y child of X, if any, otherwise null
42364 function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
42365 // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
42366 function norm(el) { if (el.normalize) { el.normalize(); } return el; }
42367 // cast array x into numbers
42368 function numarray(x) {
42369 for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); }
42372 // get the content of a text node, if any
42373 function nodeVal(x) {
42374 if (x) { norm(x); }
42375 return (x && x.textContent) || '';
42377 // get the contents of multiple text nodes, if present
42378 function getMulti(x, ys) {
42380 for (k = 0; k < ys.length; k++) {
42381 n = get1(x, ys[k]);
42382 if (n) o[ys[k]] = nodeVal(n);
42386 // add properties of Y to X, overwriting if present in both
42387 function extend(x, y) { for (var k in y) x[k] = y[k]; }
42388 // get one coordinate from a coordinate array, if any
42389 function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
42390 // get all coordinates from a coordinate array as [[],[]]
42391 function coord(v) {
42392 var coords = v.replace(trimSpace, '').split(splitSpace),
42394 for (var i = 0; i < coords.length; i++) {
42395 o.push(coord1(coords[i]));
42399 function coordPair(x) {
42400 var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
42401 ele = get1(x, 'ele'),
42402 // handle namespaced attribute in browser
42403 heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'),
42404 time = get1(x, 'time'),
42407 e = parseFloat(nodeVal(ele));
42414 time: time ? nodeVal(time) : null,
42415 heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null
42419 // create a new feature collection parent object
42422 type: 'FeatureCollection',
42428 if (typeof XMLSerializer !== 'undefined') {
42429 /* istanbul ignore next */
42430 serializer = new XMLSerializer();
42431 // only require xmldom in a node environment
42432 } else if ('object' === 'object' && typeof process === 'object' && !process.browser) {
42433 serializer = new (domParser.XMLSerializer)();
42435 function xml2str(str) {
42436 // IE9 will create a new XMLSerializer but it'll crash immediately.
42437 // This line is ignored because we don't run coverage tests in IE9
42438 /* istanbul ignore next */
42439 if (str.xml !== undefined) return str.xml;
42440 return serializer.serializeToString(str);
42444 kml: function(doc) {
42447 // styleindex keeps track of hashed styles in order to match features
42448 styleIndex = {}, styleByHash = {},
42449 // stylemapindex keeps track of style maps to expose in properties
42450 styleMapIndex = {},
42451 // atomic geospatial types supported by KML - MultiGeometry is
42452 // handled separately
42453 geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'],
42454 // all root placemarks in the file
42455 placemarks = get(doc, 'Placemark'),
42456 styles = get(doc, 'Style'),
42457 styleMaps = get(doc, 'StyleMap');
42459 for (var k = 0; k < styles.length; k++) {
42460 var hash = okhash(xml2str(styles[k])).toString(16);
42461 styleIndex['#' + attr(styles[k], 'id')] = hash;
42462 styleByHash[hash] = styles[k];
42464 for (var l = 0; l < styleMaps.length; l++) {
42465 styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16);
42466 var pairs = get(styleMaps[l], 'Pair');
42468 for (var m = 0; m < pairs.length; m++) {
42469 pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl'));
42471 styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap;
42474 for (var j = 0; j < placemarks.length; j++) {
42475 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
42477 function kmlColor(v) {
42478 var color, opacity;
42480 if (v.substr(0, 1) === '#') { v = v.substr(1); }
42481 if (v.length === 6 || v.length === 3) { color = v; }
42482 if (v.length === 8) {
42483 opacity = parseInt(v.substr(0, 2), 16) / 255;
42484 color = '#' + v.substr(6, 2) +
42488 return [color, isNaN(opacity) ? undefined : opacity];
42490 function gxCoord(v) { return numarray(v.split(' ')); }
42491 function gxCoords(root) {
42492 var elems = get(root, 'coord', 'gx'), coords = [], times = [];
42493 if (elems.length === 0) elems = get(root, 'gx:coord');
42494 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
42495 var timeElems = get(root, 'when');
42496 for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j]));
42502 function getGeometry(root) {
42503 var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = [];
42504 if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); }
42505 if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); }
42506 if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); }
42507 for (i = 0; i < geotypes.length; i++) {
42508 geomNodes = get(root, geotypes[i]);
42510 for (j = 0; j < geomNodes.length; j++) {
42511 geomNode = geomNodes[j];
42512 if (geotypes[i] === 'Point') {
42515 coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
42517 } else if (geotypes[i] === 'LineString') {
42519 type: 'LineString',
42520 coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
42522 } else if (geotypes[i] === 'Polygon') {
42523 var rings = get(geomNode, 'LinearRing'),
42525 for (k = 0; k < rings.length; k++) {
42526 coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
42530 coordinates: coords
42532 } else if (geotypes[i] === 'Track' ||
42533 geotypes[i] === 'gx:Track') {
42534 var track = gxCoords(geomNode);
42536 type: 'LineString',
42537 coordinates: track.coords
42539 if (track.times.length) coordTimes.push(track.times);
42546 coordTimes: coordTimes
42549 function getPlacemark(root) {
42550 var geomsAndTimes = getGeometry(root), i, properties = {},
42551 name = nodeVal(get1(root, 'name')),
42552 address = nodeVal(get1(root, 'address')),
42553 styleUrl = nodeVal(get1(root, 'styleUrl')),
42554 description = nodeVal(get1(root, 'description')),
42555 timeSpan = get1(root, 'TimeSpan'),
42556 timeStamp = get1(root, 'TimeStamp'),
42557 extendedData = get1(root, 'ExtendedData'),
42558 lineStyle = get1(root, 'LineStyle'),
42559 polyStyle = get1(root, 'PolyStyle'),
42560 visibility = get1(root, 'visibility');
42562 if (!geomsAndTimes.geoms.length) return [];
42563 if (name) properties.name = name;
42564 if (address) properties.address = address;
42566 if (styleUrl[0] !== '#') {
42567 styleUrl = '#' + styleUrl;
42570 properties.styleUrl = styleUrl;
42571 if (styleIndex[styleUrl]) {
42572 properties.styleHash = styleIndex[styleUrl];
42574 if (styleMapIndex[styleUrl]) {
42575 properties.styleMapHash = styleMapIndex[styleUrl];
42576 properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
42578 // Try to populate the lineStyle or polyStyle since we got the style hash
42579 var style = styleByHash[properties.styleHash];
42581 if (!lineStyle) lineStyle = get1(style, 'LineStyle');
42582 if (!polyStyle) polyStyle = get1(style, 'PolyStyle');
42585 if (description) properties.description = description;
42587 var begin = nodeVal(get1(timeSpan, 'begin'));
42588 var end = nodeVal(get1(timeSpan, 'end'));
42589 properties.timespan = { begin: begin, end: end };
42592 properties.timestamp = nodeVal(get1(timeStamp, 'when'));
42595 var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))),
42596 color = linestyles[0],
42597 opacity = linestyles[1],
42598 width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42599 if (color) properties.stroke = color;
42600 if (!isNaN(opacity)) properties['stroke-opacity'] = opacity;
42601 if (!isNaN(width)) properties['stroke-width'] = width;
42604 var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))),
42605 pcolor = polystyles[0],
42606 popacity = polystyles[1],
42607 fill = nodeVal(get1(polyStyle, 'fill')),
42608 outline = nodeVal(get1(polyStyle, 'outline'));
42609 if (pcolor) properties.fill = pcolor;
42610 if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
42611 if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0;
42612 if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0;
42614 if (extendedData) {
42615 var datas = get(extendedData, 'Data'),
42616 simpleDatas = get(extendedData, 'SimpleData');
42618 for (i = 0; i < datas.length; i++) {
42619 properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
42621 for (i = 0; i < simpleDatas.length; i++) {
42622 properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
42626 properties.visibility = nodeVal(visibility);
42628 if (geomsAndTimes.coordTimes.length) {
42629 properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
42630 geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
42634 geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : {
42635 type: 'GeometryCollection',
42636 geometries: geomsAndTimes.geoms
42638 properties: properties
42640 if (attr(root, 'id')) feature.id = attr(root, 'id');
42645 gpx: function(doc) {
42647 tracks = get(doc, 'trk'),
42648 routes = get(doc, 'rte'),
42649 waypoints = get(doc, 'wpt'),
42650 // a feature collection
42653 for (i = 0; i < tracks.length; i++) {
42654 feature = getTrack(tracks[i]);
42655 if (feature) gj.features.push(feature);
42657 for (i = 0; i < routes.length; i++) {
42658 feature = getRoute(routes[i]);
42659 if (feature) gj.features.push(feature);
42661 for (i = 0; i < waypoints.length; i++) {
42662 gj.features.push(getPoint(waypoints[i]));
42664 function getPoints(node, pointname) {
42665 var pts = get(node, pointname),
42670 if (l < 2) return {}; // Invalid line in GeoJSON
42671 for (var i = 0; i < l; i++) {
42672 var c = coordPair(pts[i]);
42673 line.push(c.coordinates);
42674 if (c.time) times.push(c.time);
42675 if (c.heartRate) heartRates.push(c.heartRate);
42680 heartRates: heartRates
42683 function getTrack(node) {
42684 var segments = get(node, 'trkseg'),
42689 for (var i = 0; i < segments.length; i++) {
42690 line = getPoints(segments[i], 'trkpt');
42692 if (line.line) track.push(line.line);
42693 if (line.times && line.times.length) times.push(line.times);
42694 if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates);
42697 if (track.length === 0) return;
42698 var properties = getProperties(node);
42699 extend(properties, getLineStyle(get1(node, 'extensions')));
42700 if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times;
42701 if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates;
42704 properties: properties,
42706 type: track.length === 1 ? 'LineString' : 'MultiLineString',
42707 coordinates: track.length === 1 ? track[0] : track
42711 function getRoute(node) {
42712 var line = getPoints(node, 'rtept');
42713 if (!line.line) return;
42714 var prop = getProperties(node);
42715 extend(prop, getLineStyle(get1(node, 'extensions')));
42720 type: 'LineString',
42721 coordinates: line.line
42726 function getPoint(node) {
42727 var prop = getProperties(node);
42728 extend(prop, getMulti(node, ['sym']));
42734 coordinates: coordPair(node).coordinates
42738 function getLineStyle(extensions) {
42741 var lineStyle = get1(extensions, 'line');
42743 var color = nodeVal(get1(lineStyle, 'color')),
42744 opacity = parseFloat(nodeVal(get1(lineStyle, 'opacity'))),
42745 width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42746 if (color) style.stroke = color;
42747 if (!isNaN(opacity)) style['stroke-opacity'] = opacity;
42748 // GPX width is in mm, convert to px with 96 px per inch
42749 if (!isNaN(width)) style['stroke-width'] = width * 96 / 25.4;
42754 function getProperties(node) {
42755 var prop = getMulti(node, ['name', 'cmt', 'desc', 'type', 'time', 'keywords']),
42756 links = get(node, 'link');
42757 if (links.length) prop.links = [];
42758 for (var i = 0, link; i < links.length; i++) {
42759 link = { href: attr(links[i], 'href') };
42760 extend(link, getMulti(links[i], ['text', 'type']));
42761 prop.links.push(link);
42771 module.exports = toGeoJSON;
42774 function svgGpx(projection, context, dispatch$$1) {
42775 var showLabels = true,
42776 detected = utilDetect(),
42781 if (svgGpx.initialized) return; // run once
42783 svgGpx.geojson = {};
42784 svgGpx.enabled = true;
42787 event.stopPropagation();
42788 event.preventDefault();
42789 event.dataTransfer.dropEffect = 'copy';
42793 .attr('dropzone', 'copy')
42794 .on('drop.localgpx', function() {
42795 event.stopPropagation();
42796 event.preventDefault();
42797 if (!detected.filedrop) return;
42798 drawGpx.files(event.dataTransfer.files);
42800 .on('dragenter.localgpx', over)
42801 .on('dragexit.localgpx', over)
42802 .on('dragover.localgpx', over);
42804 svgGpx.initialized = true;
42808 function drawGpx(selection$$1) {
42809 var geojson = svgGpx.geojson,
42810 enabled = svgGpx.enabled;
42812 layer = selection$$1.selectAll('.layer-gpx')
42813 .data(enabled ? [0] : []);
42818 layer = layer.enter()
42820 .attr('class', 'layer-gpx')
42831 paths = paths.enter()
42833 .attr('class', 'gpx')
42837 var path$$1 = index$4(projection);
42840 .attr('d', path$$1);
42843 var labels = layer.selectAll('text')
42844 .data(showLabels && geojson.features ? geojson.features : []);
42849 labels = labels.enter()
42851 .attr('class', 'gpx')
42855 .text(function(d) {
42856 return d.properties.desc || d.properties.name;
42858 .attr('x', function(d) {
42859 var centroid = path$$1.centroid(d);
42860 return centroid[0] + 7;
42862 .attr('y', function(d) {
42863 var centroid = path$$1.centroid(d);
42864 return centroid[1];
42870 function toDom(x) {
42871 return (new DOMParser()).parseFromString(x, 'text/xml');
42875 function getExtension(fileName) {
42876 if (lodash.isUndefined(fileName)) {
42880 var lastDotIndex = fileName.lastIndexOf('.');
42881 if (lastDotIndex < 0) {
42885 return fileName.substr(lastDotIndex);
42889 function parseSaveAndZoom(extension, data) {
42890 switch (extension) {
42892 drawGpx.geojson(togeojson.gpx(toDom(data))).fitZoom();
42895 drawGpx.geojson(togeojson.kml(toDom(data))).fitZoom();
42899 drawGpx.geojson(JSON.parse(data)).fitZoom();
42905 drawGpx.showLabels = function(_) {
42906 if (!arguments.length) return showLabels;
42912 drawGpx.enabled = function(_) {
42913 if (!arguments.length) return svgGpx.enabled;
42914 svgGpx.enabled = _;
42915 dispatch$$1.call('change');
42920 drawGpx.hasGpx = function() {
42921 var geojson = svgGpx.geojson;
42922 return (!(lodash.isEmpty(geojson) || lodash.isEmpty(geojson.features)));
42926 drawGpx.geojson = function(gj) {
42927 if (!arguments.length) return svgGpx.geojson;
42928 if (lodash.isEmpty(gj) || lodash.isEmpty(gj.features)) return this;
42929 svgGpx.geojson = gj;
42930 dispatch$$1.call('change');
42935 drawGpx.url = function(url) {
42936 text(url, function(err, data) {
42938 var extension = getExtension(url);
42939 parseSaveAndZoom(extension, data);
42946 drawGpx.files = function(fileList) {
42947 if (!fileList.length) return this;
42948 var f = fileList[0],
42949 reader = new FileReader();
42951 reader.onload = (function(file) {
42952 var extension = getExtension(file.name);
42954 return function (e) {
42955 parseSaveAndZoom(extension, e.target.result);
42959 reader.readAsText(f);
42964 drawGpx.fitZoom = function() {
42965 if (!this.hasGpx()) return this;
42966 var geojson = svgGpx.geojson;
42968 var map$$1 = context.map(),
42969 viewport = map$$1.trimmedExtent().polygon(),
42970 coords = lodash.reduce(geojson.features, function(coords, feature) {
42971 var c = feature.geometry.coordinates;
42973 /* eslint-disable no-fallthrough */
42974 switch (feature.geometry.type) {
42981 case 'MultiPolygon':
42982 c = lodash.flatten(c);
42984 case 'MultiLineString':
42985 c = lodash.flatten(c);
42988 /* eslint-enable no-fallthrough */
42990 return lodash.union(coords, c);
42993 if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
42994 var extent$$1 = geoExtent$$1(bounds({ type: 'LineString', coordinates: coords }));
42995 map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
43006 function svgIcon(name, svgklass, useklass) {
43007 return function drawIcon(selection) {
43008 selection.selectAll('svg')
43012 .attr('class', 'icon ' + (svgklass || ''))
43014 .attr('xlink:href', name)
43015 .attr('class', useklass);
43019 function svgLabels(projection, context) {
43020 var path$$1 = index$4(projection),
43021 detected = utilDetect(),
43022 baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'),
43023 rdrawn = index$9(),
43024 rskipped = index$9(),
43025 textWidthCache = {},
43028 // Listed from highest to lowest priority
43030 ['line', 'aeroway', '*', 12],
43031 ['line', 'highway', 'motorway', 12],
43032 ['line', 'highway', 'trunk', 12],
43033 ['line', 'highway', 'primary', 12],
43034 ['line', 'highway', 'secondary', 12],
43035 ['line', 'highway', 'tertiary', 12],
43036 ['line', 'highway', '*', 12],
43037 ['line', 'railway', '*', 12],
43038 ['line', 'waterway', '*', 12],
43039 ['area', 'aeroway', '*', 12],
43040 ['area', 'amenity', '*', 12],
43041 ['area', 'building', '*', 12],
43042 ['area', 'historic', '*', 12],
43043 ['area', 'leisure', '*', 12],
43044 ['area', 'man_made', '*', 12],
43045 ['area', 'natural', '*', 12],
43046 ['area', 'shop', '*', 12],
43047 ['area', 'tourism', '*', 12],
43048 ['area', 'camp_site', '*', 12],
43049 ['point', 'aeroway', '*', 10],
43050 ['point', 'amenity', '*', 10],
43051 ['point', 'building', '*', 10],
43052 ['point', 'historic', '*', 10],
43053 ['point', 'leisure', '*', 10],
43054 ['point', 'man_made', '*', 10],
43055 ['point', 'natural', '*', 10],
43056 ['point', 'shop', '*', 10],
43057 ['point', 'tourism', '*', 10],
43058 ['point', 'camp_site', '*', 10],
43059 ['line', 'name', '*', 12],
43060 ['area', 'name', '*', 12],
43061 ['point', 'name', '*', 10]
43065 function blacklisted(preset) {
43066 var noIcons = ['building', 'landuse', 'natural'];
43067 return lodash.some(noIcons, function(s) {
43068 return preset.id.indexOf(s) >= 0;
43073 function get(array, prop) {
43074 return function(d, i) { return array[i][prop]; };
43078 function textWidth(text$$1, size, elem) {
43079 var c = textWidthCache[size];
43080 if (!c) c = textWidthCache[size] = {};
43086 c[text$$1] = elem.getComputedTextLength();
43090 var str = encodeURIComponent(text$$1).match(/%[CDEFcdef]/g);
43091 if (str === null) {
43092 return size / 3 * 2 * text$$1.length;
43094 return size / 3 * (2 * text$$1.length + str.length);
43100 function drawLinePaths(selection$$1, entities, filter, classes, labels) {
43101 var paths = selection$$1.selectAll('path')
43103 .data(entities, osmEntity$$1.key);
43110 .style('stroke-width', get(labels, 'font-size'))
43111 .attr('id', function(d) { return 'labelpath-' + d.id; })
43112 .attr('class', classes)
43114 .attr('d', get(labels, 'lineString'));
43118 function drawLineLabels(selection$$1, entities, filter, classes, labels) {
43119 var texts = selection$$1.selectAll('text.' + classes)
43121 .data(entities, osmEntity$$1.key);
43128 .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
43129 .attr('dy', baselineHack ? '0.35em' : null)
43130 .append('textPath')
43131 .attr('class', 'textpath');
43133 texts = selection$$1.selectAll('text.' + classes);
43135 texts.selectAll('.textpath')
43137 .data(entities, osmEntity$$1.key)
43138 .attr('startOffset', '50%')
43139 .attr('xlink:href', function(d) { return '#labelpath-' + d.id; })
43140 .text(utilDisplayNameForPath);
43144 function drawPointLabels(selection$$1, entities, filter, classes, labels) {
43145 var texts = selection$$1.selectAll('text.' + classes)
43147 .data(entities, osmEntity$$1.key);
43152 texts = texts.enter()
43154 .attr('class', function(d, i) {
43155 return classes + ' ' + labels[i].classes + ' ' + d.id;
43160 .attr('x', get(labels, 'x'))
43161 .attr('y', get(labels, 'y'))
43162 .style('text-anchor', get(labels, 'textAnchor'))
43163 .text(utilDisplayName)
43164 .each(function(d, i) {
43165 textWidth(utilDisplayName(d), labels[i].height, this);
43170 function drawAreaLabels(selection$$1, entities, filter, classes, labels) {
43171 entities = entities.filter(hasText);
43172 labels = labels.filter(hasText);
43173 drawPointLabels(selection$$1, entities, filter, classes, labels);
43175 function hasText(d, i) {
43176 return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
43181 function drawAreaIcons(selection$$1, entities, filter, classes, labels) {
43182 var icons = selection$$1.selectAll('use.' + classes)
43184 .data(entities, osmEntity$$1.key);
43189 icons = icons.enter()
43191 .attr('class', 'icon ' + classes)
43192 .attr('width', '17px')
43193 .attr('height', '17px')
43197 .attr('transform', get(labels, 'transform'))
43198 .attr('xlink:href', function(d) {
43199 var preset = context.presets().match(d, context.graph()),
43200 picon = preset && preset.icon;
43205 var isMaki = dataFeatureIcons.indexOf(picon) !== -1;
43206 return '#' + picon + (isMaki ? '-15' : '');
43212 function drawCollisionBoxes(selection$$1, rtree, which) {
43213 var showDebug = context.getDebug('collision'),
43214 classes = 'debug ' + which + ' ' +
43215 (which === 'debug-skipped' ? 'orange' : 'yellow');
43217 var debug = selection$$1.selectAll('.layer-label-debug')
43218 .data(showDebug ? [true] : []);
43223 debug = debug.enter()
43225 .attr('class', 'layer-label-debug')
43229 var gj = rtree.all().map(function(d) {
43230 return { type: 'Polygon', coordinates: [[
43239 var debugboxes = debug.selectAll('.' + which)
43245 debugboxes = debugboxes.enter()
43247 .attr('class', classes)
43248 .merge(debugboxes);
43251 .attr('d', index$4());
43256 function drawLabels(selection$$1, graph, entities, filter, dimensions, fullRedraw) {
43257 var lowZoom = context.surface().classed('low-zoom');
43259 var labelable = [], i, j, k, entity, geometry;
43260 for (i = 0; i < labelStack.length; i++) {
43261 labelable.push([]);
43269 for (i = 0; i < entities.length; i++) {
43270 entity = entities[i];
43272 .concat(entitybboxes[entity.id] || [])
43273 .concat(entitybboxes[entity.id + 'I'] || []);
43275 for (j = 0; j < toRemove.length; j++) {
43276 rdrawn.remove(toRemove[j]);
43277 rskipped.remove(toRemove[j]);
43282 // Split entities into groups specified by labelStack
43283 for (i = 0; i < entities.length; i++) {
43284 entity = entities[i];
43285 geometry = entity.geometry(graph);
43286 if (geometry === 'vertex') { geometry = 'point'; } // treat vertex like point
43288 var preset = geometry === 'area' && context.presets().match(entity, graph),
43289 icon = preset && !blacklisted(preset) && preset.icon;
43291 if (!icon && !utilDisplayName(entity))
43294 for (k = 0; k < labelStack.length; k++) {
43295 var matchGeom = labelStack[k][0],
43296 matchKey = labelStack[k][1],
43297 matchVal = labelStack[k][2],
43298 hasVal = entity.tags[matchKey];
43300 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
43301 labelable[k].push(entity);
43319 // Try and find a valid label for labellable entities
43320 for (k = 0; k < labelable.length; k++) {
43321 var fontSize = labelStack[k][3];
43322 for (i = 0; i < labelable[k].length; i++) {
43323 entity = labelable[k][i];
43324 geometry = entity.geometry(graph);
43326 var getName = (geometry === 'line') ? utilDisplayNameForPath : utilDisplayName,
43327 name = getName(entity),
43328 width = name && textWidth(name, fontSize),
43331 if (geometry === 'point') {
43332 p = getPointLabel(entity, width, fontSize, geometry);
43333 } else if (geometry === 'vertex' && !lowZoom) {
43334 // don't label vertices at low zoom because they don't have icons
43335 p = getPointLabel(entity, width, fontSize, geometry);
43336 } else if (geometry === 'line') {
43337 p = getLineLabel(entity, width, fontSize);
43338 } else if (geometry === 'area') {
43339 p = getAreaLabel(entity, width, fontSize);
43343 if (geometry === 'vertex') { geometry = 'point'; } // treat vertex like point
43344 p.classes = geometry + ' tag-' + labelStack[k][1];
43345 positions[geometry].push(p);
43346 labelled[geometry].push(entity);
43352 function getPointLabel(entity, width, height, geometry) {
43353 var y = (geometry === 'point' ? -12 : 0),
43355 ltr: [15, y, 'start'],
43356 rtl: [-15, y, 'end']
43359 var coord = projection(entity.loc),
43361 offset = pointOffsets[textDirection],
43365 x: coord[0] + offset[0],
43366 y: coord[1] + offset[1],
43367 textAnchor: offset[2]
43371 if (textDirection === 'rtl') {
43373 minX: p.x - width - margin,
43374 minY: p.y - (height / 2) - margin,
43375 maxX: p.x + margin,
43376 maxY: p.y + (height / 2) + margin
43380 minX: p.x - margin,
43381 minY: p.y - (height / 2) - margin,
43382 maxX: p.x + width + margin,
43383 maxY: p.y + (height / 2) + margin
43387 if (tryInsert([bbox], entity.id, true)) {
43393 function getLineLabel(entity, width, height) {
43394 var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
43395 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection),
43396 length = geoPathLength(nodes);
43398 if (length < width + 20) return;
43400 // % along the line to attempt to place the label
43401 var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
43402 25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
43405 for (var i = 0; i < lineOffsets.length; i++) {
43406 var offset = lineOffsets[i],
43407 middle = offset / 100 * length,
43408 start = middle - width / 2;
43410 if (start < 0 || start + width > length) continue;
43412 // generate subpath and ignore paths that are invalid or don't cross viewport.
43413 var sub = subpath(nodes, start, start + width);
43414 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
43418 var isReverse = reverse(sub);
43420 sub = sub.reverse();
43424 boxsize = (height + 2) / 2;
43426 for (var j = 0; j < sub.length - 1; j++) {
43428 var b = sub[j + 1];
43429 var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
43431 for (var box = 0; box < num; box++) {
43432 var p = geoInterp(a, b, box / num);
43433 var x0 = p[0] - boxsize - margin;
43434 var y0 = p[1] - boxsize - margin;
43435 var x1 = p[0] + boxsize + margin;
43436 var y1 = p[1] + boxsize + margin;
43439 minX: Math.min(x0, x1),
43440 minY: Math.min(y0, y1),
43441 maxX: Math.max(x0, x1),
43442 maxY: Math.max(y0, y1)
43447 if (tryInsert(bboxes, entity.id, false)) {
43449 'font-size': height + 2,
43450 lineString: lineString(sub),
43451 startOffset: offset + '%'
43456 function reverse(p) {
43457 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
43458 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
43461 function lineString(nodes) {
43462 return 'M' + nodes.join('L');
43465 function subpath(nodes, from, to) {
43467 start, end, i0, i1;
43469 for (var i = 0; i < nodes.length - 1; i++) {
43472 var current = geoEuclideanDistance(a, b);
43474 if (!start && sofar + current >= from) {
43475 portion = (from - sofar) / current;
43477 a[0] + portion * (b[0] - a[0]),
43478 a[1] + portion * (b[1] - a[1])
43482 if (!end && sofar + current >= to) {
43483 portion = (to - sofar) / current;
43485 a[0] + portion * (b[0] - a[0]),
43486 a[1] + portion * (b[1] - a[1])
43493 var ret = nodes.slice(i0, i1);
43494 ret.unshift(start);
43501 function getAreaLabel(entity, width, height) {
43502 var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
43503 extent$$1 = entity.extent(graph),
43504 entitywidth = projection(extent$$1[1])[0] - projection(extent$$1[0])[0];
43506 if (isNaN(centroid[0]) || entitywidth < 20) return;
43509 iconX = centroid[0] - (iconSize / 2),
43510 iconY = centroid[1] - (iconSize / 2),
43512 textOffset = iconSize + margin,
43513 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
43518 maxX: iconX + iconSize,
43519 maxY: iconY + iconSize
43523 if (tryInsert([bbox], entity.id + 'I', true)) {
43524 if (width && entitywidth >= width + 20) {
43525 var labelX = centroid[0],
43526 labelY = centroid[1] + textOffset;
43529 minX: labelX - (width / 2) - margin,
43530 minY: labelY - (height / 2) - margin,
43531 maxX: labelX + (width / 2) + margin,
43532 maxY: labelY + (height / 2) + margin
43535 // try to add label
43536 if (tryInsert([bbox], entity.id, true)) {
43539 p.textAnchor = 'middle';
43549 function tryInsert(bboxes, id, saveSkipped) {
43550 var skipped = false,
43553 for (var i = 0; i < bboxes.length; i++) {
43557 // Check that label is visible
43558 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
43562 if (rdrawn.collides(bbox)) {
43568 entitybboxes[id] = bboxes;
43572 rskipped.load(bboxes);
43575 rdrawn.load(bboxes);
43582 var label = selection$$1.selectAll('.layer-label'),
43583 halo = selection$$1.selectAll('.layer-halo');
43586 drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
43587 drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
43590 drawLinePaths(halo, labelled.line, filter, '', positions.line);
43591 drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
43592 drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
43595 drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
43596 drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
43597 drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
43598 drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area);
43601 drawCollisionBoxes(label, rskipped, 'debug-skipped');
43602 drawCollisionBoxes(label, rdrawn, 'debug-drawn');
43604 selection$$1.call(filterLabels);
43608 function filterLabels(selection$$1) {
43609 var layers = selection$$1
43610 .selectAll('.layer-label, .layer-halo');
43612 layers.selectAll('.proximate')
43613 .classed('proximate', false);
43615 var mouse$$1 = context.mouse(),
43616 graph = context.graph(),
43617 selectedIDs = context.selectedIDs(),
43621 // hide labels near the mouse
43624 bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad };
43625 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43628 // hide labels along selected ways, or near selected vertices
43629 for (var i = 0; i < selectedIDs.length; i++) {
43630 var entity = graph.hasEntity(selectedIDs[i]);
43631 if (!entity) continue;
43632 var geometry = entity.geometry(graph);
43634 if (geometry === 'line') {
43635 ids.push(selectedIDs[i]);
43636 } else if (geometry === 'vertex') {
43637 var point = context.projection(entity.loc);
43639 bbox = { minX: point[0] - pad, minY: point[1] - pad, maxX: point[0] + pad, maxY: point[1] + pad };
43640 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43644 layers.selectAll(utilEntitySelector(ids))
43645 .classed('proximate', true);
43649 var throttleFilterLabels = lodash.throttle(filterLabels, 100);
43652 drawLabels.observe = function(selection$$1) {
43653 var listener = function() { throttleFilterLabels(selection$$1); };
43654 selection$$1.on('mousemove.hidelabels', listener);
43655 context.on('enter.hidelabels', listener);
43659 drawLabels.off = function(selection$$1) {
43660 throttleFilterLabels.cancel();
43661 selection$$1.on('mousemove.hidelabels', null);
43662 context.on('enter.hidelabels', null);
43669 function refresh(selection, node) {
43670 var cr = node.getBoundingClientRect();
43671 var prop = [cr.width, cr.height];
43672 selection.property('__dimensions__', prop);
43676 function utilGetDimensions(selection, force) {
43677 if (!selection || selection.empty()) {
43680 var node = selection.node(),
43681 cached = selection.property('__dimensions__');
43682 return (!cached || force) ? refresh(selection, node) : cached;
43686 function utilSetDimensions(selection, dimensions) {
43687 if (!selection || selection.empty()) {
43690 var node = selection.node();
43691 if (dimensions === null) {
43692 refresh(selection, node);
43696 .property('__dimensions__', [dimensions[0], dimensions[1]])
43697 .attr('width', dimensions[0])
43698 .attr('height', dimensions[1]);
43701 function svgPointTransform(projection) {
43702 return function(entity) {
43703 // http://jsperf.com/short-array-join
43704 var pt = projection(entity.loc);
43705 return 'translate(' + pt[0] + ',' + pt[1] + ')';
43709 function d3geoTile() {
43710 var size = [960, 500],
43712 scaleExtent = [0, 20],
43713 translate = [size[0] / 2, size[1] / 2],
43716 function bound(_) {
43717 return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
43721 var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
43722 z0 = bound(Math.round(z + zoomDelta)),
43723 k = Math.pow(2, z - z0 + 8),
43724 origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
43726 cols = sequence(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
43727 rows = sequence(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
43729 rows.forEach(function(y) {
43730 cols.forEach(function(x) {
43731 tiles.push([x, y, z0]);
43735 tiles.translate = origin;
43741 tile.scaleExtent = function(_) {
43742 if (!arguments.length) return scaleExtent;
43747 tile.size = function(_) {
43748 if (!arguments.length) return size;
43753 tile.scale = function(_) {
43754 if (!arguments.length) return scale;
43759 tile.translate = function(_) {
43760 if (!arguments.length) return translate;
43765 tile.zoomDelta = function(_) {
43766 if (!arguments.length) return zoomDelta;
43774 /* global Mapillary:false */
43775 var apibase = 'https://a.mapillary.com/v2/';
43776 var viewercss = 'mapillary-js/mapillary.min.css';
43777 var viewerjs = 'mapillary-js/mapillary.min.js';
43778 var trafficocss = 'traffico/stylesheets/traffico.css';
43779 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
43780 var maxResults = 1000;
43782 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
43783 var mapillaryCache;
43784 var mapillaryClicks;
43785 var mapillaryImage;
43786 var mapillarySignDefs;
43787 var mapillaryViewer;
43790 function abortRequest(i) {
43795 function nearNullIsland(x, y, z) {
43797 var center = Math.pow(2, z - 1),
43798 width = Math.pow(2, z - 6),
43799 min$$1 = center - (width / 2),
43800 max$$1 = center + (width / 2) - 1;
43801 return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
43807 function maxPageAtZoom(z) {
43808 if (z < 15) return 2;
43809 if (z === 15) return 5;
43810 if (z === 16) return 10;
43811 if (z === 17) return 20;
43812 if (z === 18) return 40;
43813 if (z > 18) return 80;
43817 function getTiles(projection) {
43818 var s = projection.scale() * 2 * Math.PI,
43819 z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
43820 ts = 256 * Math.pow(2, z - tileZoom),
43822 s / 2 - projection.translate()[0],
43823 s / 2 - projection.translate()[1]];
43826 .scaleExtent([tileZoom, tileZoom])
43828 .size(projection.clipExtent()[1])
43829 .translate(projection.translate())()
43830 .map(function(tile) {
43831 var x = tile[0] * ts - origin[0],
43832 y = tile[1] * ts - origin[1];
43835 id: tile.toString(),
43837 extent: geoExtent$$1(
43838 projection.invert([x, y + ts]),
43839 projection.invert([x + ts, y])
43846 function loadTiles(which, url, projection) {
43847 var s = projection.scale() * 2 * Math.PI,
43848 currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0));
43850 var tiles = getTiles(projection).filter(function(t) {
43851 return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
43854 lodash.filter(which.inflight, function(v, k) {
43855 var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
43856 if (!wanted) delete which.inflight[k];
43858 }).map(abortRequest);
43860 tiles.forEach(function(tile) {
43861 loadNextTilePage(which, currZoom, url, tile);
43866 function loadNextTilePage(which, currZoom, url, tile) {
43867 var cache = mapillaryCache[which],
43868 rect = tile.extent.rectangle(),
43869 maxPages = maxPageAtZoom(currZoom),
43870 nextPage = cache.nextPage[tile.id] || 0;
43872 if (nextPage > maxPages) return;
43874 var id = tile.id + ',' + String(nextPage);
43875 if (cache.loaded[id] || cache.inflight[id]) return;
43877 cache.inflight[id] = json(url +
43882 client_id: clientId,
43887 }), function(err, data) {
43888 cache.loaded[id] = true;
43889 delete cache.inflight[id];
43890 if (err || !data.features || !data.features.length) return;
43895 for (var i = 0; i < data.features.length; i++) {
43896 feature = data.features[i];
43897 loc = feature.geometry.coordinates;
43898 d = { key: feature.properties.key, loc: loc };
43899 if (which === 'images') d.ca = feature.properties.ca;
43900 if (which === 'signs') d.signs = feature.properties.rects;
43902 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
43905 cache.rtree.load(features);
43907 if (which === 'images') dispatch$2.call('loadedImages');
43908 if (which === 'signs') dispatch$2.call('loadedSigns');
43910 if (data.features.length === maxResults) { // more pages to load
43911 cache.nextPage[tile.id] = nextPage + 1;
43912 loadNextTilePage(which, currZoom, url, tile);
43914 cache.nextPage[tile.id] = Infinity; // no more pages to load
43921 // partition viewport into `psize` x `psize` regions
43922 function partitionViewport(psize, projection) {
43923 var dimensions = projection.clipExtent()[1];
43924 psize = psize || 16;
43925 var cols = sequence(0, dimensions[0], psize),
43926 rows = sequence(0, dimensions[1], psize),
43929 rows.forEach(function(y) {
43930 cols.forEach(function(x) {
43931 var min$$1 = [x, y + psize],
43932 max$$1 = [x + psize, y];
43934 geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)));
43942 // no more than `limit` results per partition.
43943 function searchLimited(psize, limit, projection, rtree) {
43944 limit = limit || 3;
43946 var partitions = partitionViewport(psize, projection);
43947 return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
43948 return rtree.search(extent$$1.bbox())
43950 .map(function(d) { return d.data; });
43956 var serviceMapillary = {
43959 if (!mapillaryCache) {
43963 this.event = utilRebind(this, dispatch$2, 'on');
43966 reset: function() {
43967 var cache = mapillaryCache;
43970 if (cache.images && cache.images.inflight) {
43971 lodash.forEach(cache.images.inflight, abortRequest);
43973 if (cache.signs && cache.signs.inflight) {
43974 lodash.forEach(cache.signs.inflight, abortRequest);
43979 images: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() },
43980 signs: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() }
43983 mapillaryImage = null;
43984 mapillaryClicks = [];
43988 images: function(projection) {
43989 var psize = 16, limit = 3;
43990 return searchLimited(psize, limit, projection, mapillaryCache.images.rtree);
43994 signs: function(projection) {
43995 var psize = 32, limit = 3;
43996 return searchLimited(psize, limit, projection, mapillaryCache.signs.rtree);
44000 signsSupported: function() {
44001 var detected = utilDetect();
44002 if (detected.ie) return false;
44003 if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
44008 signHTML: function(d) {
44009 if (!mapillarySignDefs) return;
44011 var detectionPackage = d.signs[0].package,
44012 type = d.signs[0].type,
44013 country = detectionPackage.split('_')[1];
44015 return mapillarySignDefs[country][type];
44019 loadImages: function(projection) {
44020 var url = apibase + 'search/im/geojson?';
44021 loadTiles('images', url, projection);
44025 loadSigns: function(context, projection) {
44026 var url = apibase + 'search/im/geojson/or?';
44027 loadTiles('signs', url, projection);
44029 // load traffico css
44030 select('head').selectAll('#traffico')
44034 .attr('id', 'traffico')
44035 .attr('rel', 'stylesheet')
44036 .attr('href', context.asset(trafficocss));
44038 // load traffico sign defs
44039 if (!mapillarySignDefs) {
44040 mapillarySignDefs = {};
44041 lodash.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
44042 json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
44044 if (region === 'de') region = 'eu';
44045 mapillarySignDefs[region] = data;
44052 loadViewer: function(context) {
44054 var wrap = select('#content').selectAll('.mapillary-wrap')
44057 var enter = wrap.enter()
44059 .attr('class', 'mapillary-wrap')
44060 .classed('al', true) // 'al'=left, 'ar'=right
44061 .classed('hidden', true);
44065 .attr('class', 'thumb-hide')
44066 .on('click', function () { that.hideViewer(); })
44068 .call(svgIcon('#icon-close'));
44073 .attr('class', 'mly-wrapper')
44074 .classed('active', false);
44076 // load mapillary-viewercss
44077 select('head').selectAll('#mapillary-viewercss')
44081 .attr('id', 'mapillary-viewercss')
44082 .attr('rel', 'stylesheet')
44083 .attr('href', context.asset(viewercss));
44085 // load mapillary-viewerjs
44086 select('head').selectAll('#mapillary-viewerjs')
44090 .attr('id', 'mapillary-viewerjs')
44091 .attr('src', context.asset(viewerjs));
44095 showViewer: function() {
44097 .selectAll('.mapillary-wrap')
44098 .classed('hidden', false)
44099 .selectAll('.mly-wrapper')
44100 .classed('active', true);
44106 hideViewer: function() {
44108 .selectAll('.mapillary-wrap')
44109 .classed('hidden', true)
44110 .selectAll('.mly-wrapper')
44111 .classed('active', false);
44113 selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44114 .classed('selected', false);
44116 mapillaryImage = null;
44121 updateViewer: function(imageKey, context) {
44122 if (!imageKey) return;
44124 if (!mapillaryViewer) {
44125 this.initViewer(imageKey, context);
44127 mapillaryViewer.moveToKey(imageKey);
44134 initViewer: function(imageKey, context) {
44136 if (Mapillary && imageKey) {
44138 baseImageSize: 320,
44145 mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
44146 mapillaryViewer.on('nodechanged', nodeChanged);
44149 function nodeChanged(node) {
44150 var clicks = mapillaryClicks;
44151 var index = clicks.indexOf(node.key);
44152 if (index > -1) { // nodechange initiated from clicking on a marker..
44153 clicks.splice(index, 1);
44154 } else { // nodechange initiated from the Mapillary viewer controls..
44155 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
44156 context.map().centerEase(loc);
44157 that.selectedImage(node.key, false);
44163 selectedImage: function(imageKey, fromClick) {
44164 if (!arguments.length) return mapillaryImage;
44166 mapillaryImage = imageKey;
44168 mapillaryClicks.push(imageKey);
44171 selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44172 .classed('selected', function(d) { return d.key === imageKey; });
44178 cache: function(_) {
44179 if (!arguments.length) return mapillaryCache;
44180 mapillaryCache = _;
44185 signDefs: function(_) {
44186 if (!arguments.length) return mapillarySignDefs;
44187 mapillarySignDefs = _;
44193 var apibase$1 = 'https://nominatim.openstreetmap.org/';
44195 var nominatimCache;
44198 var serviceNominatim = {
44202 nominatimCache = index$9();
44205 reset: function() {
44206 lodash.forEach(inflight, function(req) { req.abort(); });
44208 nominatimCache = index$9();
44212 countryCode: function (location, callback) {
44213 var countryCodes = nominatimCache.search(
44214 { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
44217 if (countryCodes.length > 0) {
44218 return callback(null, countryCodes[0].data);
44221 var params = { format: 'json', addressdetails: 1, lat: location[1], lon: location[0] };
44222 var url = apibase$1 + 'reverse?' + utilQsString(params);
44223 if (inflight[url]) return;
44225 inflight[url] = json(url, function(err, result) {
44226 delete inflight[url];
44229 return callback(err);
44230 else if (result && result.error)
44231 return callback(result.error);
44233 var extent$$1 = geoExtent$$1(location).padByMeters(1000);
44234 nominatimCache.insert(lodash.assign(extent$$1.bbox(),
44235 { data: result.address.country_code }
44238 callback(null, result.address.country_code);
44243 search: function (val, callback) {
44244 var searchVal = encodeURIComponent(val);
44245 var url = apibase$1 + 'search/' + searchVal + '?limit=10&format=json';
44246 if (inflight[url]) return;
44248 inflight[url] = json(url, function(err, result) {
44249 delete inflight[url];
44250 callback(err, result);
44256 var hashes = createCommonjsModule(function (module, exports) {
44258 * jshashes - https://github.com/h2non/jshashes
44259 * Released under the "New BSD" license
44261 * Algorithms specification:
44263 * MD5 - http://www.ietf.org/rfc/rfc1321.txt
44264 * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
44265 * SHA1 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44266 * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44267 * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44268 * HMAC - http://www.ietf.org/rfc/rfc2104.txt
44273 function utf8Encode(str) {
44274 var x, y, output = '',
44278 if (str && str.length) {
44280 while ((i += 1) < l) {
44281 /* Decode utf-16 surrogate pairs */
44282 x = str.charCodeAt(i);
44283 y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
44284 if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
44285 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
44288 /* Encode output as utf-8 */
44290 output += String.fromCharCode(x);
44291 } else if (x <= 0x7FF) {
44292 output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
44293 0x80 | (x & 0x3F));
44294 } else if (x <= 0xFFFF) {
44295 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
44296 0x80 | ((x >>> 6) & 0x3F),
44297 0x80 | (x & 0x3F));
44298 } else if (x <= 0x1FFFFF) {
44299 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
44300 0x80 | ((x >>> 12) & 0x3F),
44301 0x80 | ((x >>> 6) & 0x3F),
44302 0x80 | (x & 0x3F));
44309 function utf8Decode(str) {
44310 var i, ac, c1, c2, c3, arr = [],
44312 i = ac = c1 = c2 = c3 = 0;
44314 if (str && str.length) {
44319 c1 = str.charCodeAt(i);
44322 arr[ac] = String.fromCharCode(c1);
44324 } else if (c1 > 191 && c1 < 224) {
44325 c2 = str.charCodeAt(i + 1);
44326 arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
44329 c2 = str.charCodeAt(i + 1);
44330 c3 = str.charCodeAt(i + 2);
44331 arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
44336 return arr.join('');
44340 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
44341 * to work around bugs in some JS interpreters.
44344 function safe_add(x, y) {
44345 var lsw = (x & 0xFFFF) + (y & 0xFFFF),
44346 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
44347 return (msw << 16) | (lsw & 0xFFFF);
44351 * Bitwise rotate a 32-bit number to the left.
44354 function bit_rol(num, cnt) {
44355 return (num << cnt) | (num >>> (32 - cnt));
44359 * Convert a raw string to a hex string
44362 function rstr2hex(input, hexcase) {
44363 var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
44367 for (; i < l; i += 1) {
44368 x = input.charCodeAt(i);
44369 output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
44375 * Encode a string as utf-16
44378 function binb2rstr(input) {
44379 var i, l = input.length * 32,
44381 for (i = 0; i < l; i += 8) {
44382 output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
44388 * Convert an array of little-endian words to a string
44391 function binl2rstr(input) {
44392 var i, l = input.length * 32,
44394 for (i = 0; i < l; i += 8) {
44395 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
44401 * Convert a raw string to an array of little-endian words
44402 * Characters >255 have their high-byte silently ignored.
44405 function rstr2binl(input) {
44406 var i, l = input.length * 8,
44407 output = Array(input.length >> 2),
44408 lo = output.length;
44409 for (i = 0; i < lo; i += 1) {
44412 for (i = 0; i < l; i += 8) {
44413 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
44419 * Convert a raw string to an array of big-endian words
44420 * Characters >255 have their high-byte silently ignored.
44423 function rstr2binb(input) {
44424 var i, l = input.length * 8,
44425 output = Array(input.length >> 2),
44426 lo = output.length;
44427 for (i = 0; i < lo; i += 1) {
44430 for (i = 0; i < l; i += 8) {
44431 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
44437 * Convert a raw string to an arbitrary string encoding
44440 function rstr2any(input, encoding) {
44441 var divisor = encoding.length,
44442 remainders = Array(),
44443 i, q, x, ld, quotient, dividend, output, full_length;
44445 /* Convert to an array of 16-bit big-endian values, forming the dividend */
44446 dividend = Array(Math.ceil(input.length / 2));
44447 ld = dividend.length;
44448 for (i = 0; i < ld; i += 1) {
44449 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
44453 * Repeatedly perform a long division. The binary array forms the dividend,
44454 * the length of the encoding is the divisor. Once computed, the quotient
44455 * forms the dividend for the next step. We stop when the dividend is zerHashes.
44456 * All remainders are stored for later use.
44458 while (dividend.length > 0) {
44459 quotient = Array();
44461 for (i = 0; i < dividend.length; i += 1) {
44462 x = (x << 16) + dividend[i];
44463 q = Math.floor(x / divisor);
44465 if (quotient.length > 0 || q > 0) {
44466 quotient[quotient.length] = q;
44469 remainders[remainders.length] = x;
44470 dividend = quotient;
44473 /* Convert the remainders to the output string */
44475 for (i = remainders.length - 1; i >= 0; i--) {
44476 output += encoding.charAt(remainders[i]);
44479 /* Append leading zero equivalents */
44480 full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
44481 for (i = output.length; i < full_length; i += 1) {
44482 output = encoding[0] + output;
44488 * Convert a raw string to a base-64 string
44491 function rstr2b64(input, b64pad) {
44492 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44494 len = input.length,
44496 b64pad = b64pad || '=';
44497 for (i = 0; i < len; i += 3) {
44498 triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44499 for (j = 0; j < 4; j += 1) {
44500 if (i * 8 + j * 6 > input.length * 8) {
44503 output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44512 * @property {String} version
44521 Base64: function() {
44522 // private properties
44523 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44524 pad = '=', // default pad according with the RFC standard
44525 url = false, // URL encoding support @todo
44526 utf8 = true; // by default enable UTF-8 support encoding
44528 // public method for encoding
44529 this.encode = function(input) {
44532 len = input.length;
44535 input = (utf8) ? utf8Encode(input) : input;
44537 for (i = 0; i < len; i += 3) {
44538 triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44539 for (j = 0; j < 4; j += 1) {
44540 if (i * 8 + j * 6 > len * 8) {
44543 output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44550 // public method for decoding
44551 this.decode = function(input) {
44552 // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
44553 var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
44561 input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
44564 do { // unpack four hexets into three octets using index points in b64
44565 h1 = tab.indexOf(input.charAt(i += 1));
44566 h2 = tab.indexOf(input.charAt(i += 1));
44567 h3 = tab.indexOf(input.charAt(i += 1));
44568 h4 = tab.indexOf(input.charAt(i += 1));
44570 bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
44572 o1 = bits >> 16 & 0xff;
44573 o2 = bits >> 8 & 0xff;
44578 arr[ac] = String.fromCharCode(o1);
44579 } else if (h4 === 64) {
44580 arr[ac] = String.fromCharCode(o1, o2);
44582 arr[ac] = String.fromCharCode(o1, o2, o3);
44584 } while (i < input.length);
44586 dec = arr.join('');
44587 dec = (utf8) ? utf8Decode(dec) : dec;
44592 // set custom pad string
44593 this.setPad = function(str) {
44597 // set custom tab string characters
44598 this.setTab = function(str) {
44602 this.setUTF8 = function(bool) {
44603 if (typeof bool === 'boolean') {
44611 * CRC-32 calculation
44615 * @param {String} str Input String
44618 CRC32: function(str) {
44623 str = utf8Encode(str);
44626 '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
44627 '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
44628 '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
44629 '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
44630 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
44631 '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
44632 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
44633 '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
44634 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
44635 '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
44636 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
44637 '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
44638 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
44639 '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
44640 '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
44641 '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
44642 '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
44643 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
44644 '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
44645 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
44646 '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
44647 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
44648 '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
44649 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
44650 '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
44651 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
44655 for (i = 0, iTop = str.length; i < iTop; i += 1) {
44656 y = (crc ^ str.charCodeAt(i)) & 0xFF;
44657 x = '0x' + table.substr(y * 9, 8);
44658 crc = (crc >>> 8) ^ x;
44660 // always return a positive number (that's what >>> 0 does)
44661 return (crc ^ (-1)) >>> 0;
44667 * @param {Object} [config]
44669 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44670 * Digest Algorithm, as defined in RFC 1321.
44671 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44672 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44673 * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
44675 MD5: function(options) {
44677 * Private config properties. You may need to tweak these to be compatible with
44678 * the server-side, but the defaults work in most cases.
44679 * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44681 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44682 b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44683 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44685 // privileged (public) methods
44686 this.hex = function(s) {
44687 return rstr2hex(rstr(s, utf8), hexcase);
44689 this.b64 = function(s) {
44690 return rstr2b64(rstr(s), b64pad);
44692 this.any = function(s, e) {
44693 return rstr2any(rstr(s, utf8), e);
44695 this.raw = function(s) {
44696 return rstr(s, utf8);
44698 this.hex_hmac = function(k, d) {
44699 return rstr2hex(rstr_hmac(k, d), hexcase);
44701 this.b64_hmac = function(k, d) {
44702 return rstr2b64(rstr_hmac(k, d), b64pad);
44704 this.any_hmac = function(k, d, e) {
44705 return rstr2any(rstr_hmac(k, d), e);
44708 * Perform a simple self-test to see if the VM is working
44709 * @return {String} Hexadecimal hash sample
44711 this.vm_test = function() {
44712 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44715 * Enable/disable uppercase hexadecimal returned string
44717 * @return {Object} this
44719 this.setUpperCase = function(a) {
44720 if (typeof a === 'boolean') {
44726 * Defines a base64 pad string
44727 * @param {String} Pad
44728 * @return {Object} this
44730 this.setPad = function(a) {
44731 b64pad = a || b64pad;
44735 * Defines a base64 pad string
44737 * @return {Object} [this]
44739 this.setUTF8 = function(a) {
44740 if (typeof a === 'boolean') {
44749 * Calculate the MD5 of a raw string
44753 s = (utf8) ? utf8Encode(s) : s;
44754 return binl2rstr(binl(rstr2binl(s), s.length * 8));
44758 * Calculate the HMAC-MD5, of a key and some data (raw strings)
44761 function rstr_hmac(key, data) {
44762 var bkey, ipad, opad, hash, i;
44764 key = (utf8) ? utf8Encode(key) : key;
44765 data = (utf8) ? utf8Encode(data) : data;
44766 bkey = rstr2binl(key);
44767 if (bkey.length > 16) {
44768 bkey = binl(bkey, key.length * 8);
44771 ipad = Array(16), opad = Array(16);
44772 for (i = 0; i < 16; i += 1) {
44773 ipad[i] = bkey[i] ^ 0x36363636;
44774 opad[i] = bkey[i] ^ 0x5C5C5C5C;
44776 hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44777 return binl2rstr(binl(opad.concat(hash), 512 + 128));
44781 * Calculate the MD5 of an array of little-endian words, and a bit length.
44784 function binl(x, len) {
44785 var i, olda, oldb, oldc, oldd,
44791 /* append padding */
44792 x[len >> 5] |= 0x80 << ((len) % 32);
44793 x[(((len + 64) >>> 9) << 4) + 14] = len;
44795 for (i = 0; i < x.length; i += 16) {
44801 a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
44802 d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
44803 c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
44804 b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
44805 a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
44806 d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
44807 c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
44808 b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
44809 a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
44810 d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
44811 c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
44812 b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
44813 a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
44814 d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
44815 c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
44816 b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
44818 a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
44819 d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
44820 c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
44821 b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
44822 a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
44823 d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
44824 c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
44825 b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
44826 a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
44827 d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
44828 c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
44829 b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
44830 a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
44831 d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
44832 c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
44833 b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
44835 a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
44836 d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
44837 c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
44838 b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
44839 a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
44840 d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
44841 c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
44842 b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
44843 a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
44844 d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
44845 c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
44846 b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
44847 a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
44848 d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
44849 c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
44850 b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
44852 a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
44853 d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
44854 c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
44855 b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
44856 a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
44857 d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
44858 c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
44859 b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
44860 a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
44861 d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
44862 c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
44863 b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
44864 a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
44865 d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
44866 c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
44867 b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
44869 a = safe_add(a, olda);
44870 b = safe_add(b, oldb);
44871 c = safe_add(c, oldc);
44872 d = safe_add(d, oldd);
44874 return Array(a, b, c, d);
44878 * These functions implement the four basic operations the algorithm uses.
44881 function md5_cmn(q, a, b, x, s, t) {
44882 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
44885 function md5_ff(a, b, c, d, x, s, t) {
44886 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
44889 function md5_gg(a, b, c, d, x, s, t) {
44890 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
44893 function md5_hh(a, b, c, d, x, s, t) {
44894 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
44897 function md5_ii(a, b, c, d, x, s, t) {
44898 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
44903 * @class Hashes.SHA1
44904 * @param {Object} [config]
44907 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
44908 * Version 2.2 Copyright Paul Johnston 2000 - 2009.
44909 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44910 * See http://pajhome.org.uk/crypt/md5 for details.
44912 SHA1: function(options) {
44914 * Private config properties. You may need to tweak these to be compatible with
44915 * the server-side, but the defaults work in most cases.
44916 * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44918 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44919 b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44920 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44923 this.hex = function(s) {
44924 return rstr2hex(rstr(s, utf8), hexcase);
44926 this.b64 = function(s) {
44927 return rstr2b64(rstr(s, utf8), b64pad);
44929 this.any = function(s, e) {
44930 return rstr2any(rstr(s, utf8), e);
44932 this.raw = function(s) {
44933 return rstr(s, utf8);
44935 this.hex_hmac = function(k, d) {
44936 return rstr2hex(rstr_hmac(k, d));
44938 this.b64_hmac = function(k, d) {
44939 return rstr2b64(rstr_hmac(k, d), b64pad);
44941 this.any_hmac = function(k, d, e) {
44942 return rstr2any(rstr_hmac(k, d), e);
44945 * Perform a simple self-test to see if the VM is working
44946 * @return {String} Hexadecimal hash sample
44949 this.vm_test = function() {
44950 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44953 * @description Enable/disable uppercase hexadecimal returned string
44955 * @return {Object} this
44958 this.setUpperCase = function(a) {
44959 if (typeof a === 'boolean') {
44965 * @description Defines a base64 pad string
44966 * @param {string} Pad
44967 * @return {Object} this
44970 this.setPad = function(a) {
44971 b64pad = a || b64pad;
44975 * @description Defines a base64 pad string
44977 * @return {Object} this
44980 this.setUTF8 = function(a) {
44981 if (typeof a === 'boolean') {
44990 * Calculate the SHA-512 of a raw string
44994 s = (utf8) ? utf8Encode(s) : s;
44995 return binb2rstr(binb(rstr2binb(s), s.length * 8));
44999 * Calculate the HMAC-SHA1 of a key and some data (raw strings)
45002 function rstr_hmac(key, data) {
45003 var bkey, ipad, opad, i, hash;
45004 key = (utf8) ? utf8Encode(key) : key;
45005 data = (utf8) ? utf8Encode(data) : data;
45006 bkey = rstr2binb(key);
45008 if (bkey.length > 16) {
45009 bkey = binb(bkey, key.length * 8);
45011 ipad = Array(16), opad = Array(16);
45012 for (i = 0; i < 16; i += 1) {
45013 ipad[i] = bkey[i] ^ 0x36363636;
45014 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45016 hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45017 return binb2rstr(binb(opad.concat(hash), 512 + 160));
45021 * Calculate the SHA-1 of an array of big-endian words, and a bit length
45024 function binb(x, len) {
45025 var i, j, t, olda, oldb, oldc, oldd, olde,
45033 /* append padding */
45034 x[len >> 5] |= 0x80 << (24 - len % 32);
45035 x[((len + 64 >> 9) << 4) + 15] = len;
45037 for (i = 0; i < x.length; i += 16) {
45044 for (j = 0; j < 80; j += 1) {
45048 w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
45050 t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
45051 safe_add(safe_add(e, w[j]), sha1_kt(j)));
45054 c = bit_rol(b, 30);
45059 a = safe_add(a, olda);
45060 b = safe_add(b, oldb);
45061 c = safe_add(c, oldc);
45062 d = safe_add(d, oldd);
45063 e = safe_add(e, olde);
45065 return Array(a, b, c, d, e);
45069 * Perform the appropriate triplet combination function for the current
45073 function sha1_ft(t, b, c, d) {
45075 return (b & c) | ((~b) & d);
45081 return (b & c) | (b & d) | (c & d);
45087 * Determine the appropriate additive constant for the current iteration
45090 function sha1_kt(t) {
45091 return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
45092 (t < 60) ? -1894007588 : -899497514;
45096 * @class Hashes.SHA256
45099 * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
45100 * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
45101 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45102 * See http://pajhome.org.uk/crypt/md5 for details.
45103 * Also http://anmar.eu.org/projects/jssha2/
45105 SHA256: function(options) {
45107 * Private properties configuration variables. You may need to tweak these to be compatible with
45108 * the server-side, but the defaults work in most cases.
45109 * @see this.setUpperCase() method
45110 * @see this.setPad() method
45112 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */
45113 b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45114 /* base-64 pad character. Default '=' for strict RFC compliance */
45115 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45116 /* enable/disable utf8 encoding */
45119 /* privileged (public) methods */
45120 this.hex = function(s) {
45121 return rstr2hex(rstr(s, utf8));
45123 this.b64 = function(s) {
45124 return rstr2b64(rstr(s, utf8), b64pad);
45126 this.any = function(s, e) {
45127 return rstr2any(rstr(s, utf8), e);
45129 this.raw = function(s) {
45130 return rstr(s, utf8);
45132 this.hex_hmac = function(k, d) {
45133 return rstr2hex(rstr_hmac(k, d));
45135 this.b64_hmac = function(k, d) {
45136 return rstr2b64(rstr_hmac(k, d), b64pad);
45138 this.any_hmac = function(k, d, e) {
45139 return rstr2any(rstr_hmac(k, d), e);
45142 * Perform a simple self-test to see if the VM is working
45143 * @return {String} Hexadecimal hash sample
45146 this.vm_test = function() {
45147 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45150 * Enable/disable uppercase hexadecimal returned string
45152 * @return {Object} this
45155 this.setUpperCase = function(a) {
45156 if (typeof a === 'boolean') {
45162 * @description Defines a base64 pad string
45163 * @param {string} Pad
45164 * @return {Object} this
45167 this.setPad = function(a) {
45168 b64pad = a || b64pad;
45172 * Defines a base64 pad string
45174 * @return {Object} this
45177 this.setUTF8 = function(a) {
45178 if (typeof a === 'boolean') {
45187 * Calculate the SHA-512 of a raw string
45190 function rstr(s, utf8) {
45191 s = (utf8) ? utf8Encode(s) : s;
45192 return binb2rstr(binb(rstr2binb(s), s.length * 8));
45196 * Calculate the HMAC-sha256 of a key and some data (raw strings)
45199 function rstr_hmac(key, data) {
45200 key = (utf8) ? utf8Encode(key) : key;
45201 data = (utf8) ? utf8Encode(data) : data;
45203 bkey = rstr2binb(key),
45207 if (bkey.length > 16) {
45208 bkey = binb(bkey, key.length * 8);
45211 for (; i < 16; i += 1) {
45212 ipad[i] = bkey[i] ^ 0x36363636;
45213 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45216 hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45217 return binb2rstr(binb(opad.concat(hash), 512 + 256));
45221 * Main sha256 function, with its support functions
45224 function sha256_S(X, n) {
45225 return (X >>> n) | (X << (32 - n));
45228 function sha256_R(X, n) {
45232 function sha256_Ch(x, y, z) {
45233 return ((x & y) ^ ((~x) & z));
45236 function sha256_Maj(x, y, z) {
45237 return ((x & y) ^ (x & z) ^ (y & z));
45240 function sha256_Sigma0256(x) {
45241 return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
45244 function sha256_Sigma1256(x) {
45245 return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
45248 function sha256_Gamma0256(x) {
45249 return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
45252 function sha256_Gamma1256(x) {
45253 return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
45257 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
45258 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
45259 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
45260 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
45261 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
45262 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
45263 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
45266 function binb(m, l) {
45267 var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
45268 1359893119, -1694144372, 528734635, 1541459225
45270 var W = new Array(64);
45271 var a, b, c, d, e, f, g, h;
45274 /* append padding */
45275 m[l >> 5] |= 0x80 << (24 - l % 32);
45276 m[((l + 64 >> 9) << 4) + 15] = l;
45278 for (i = 0; i < m.length; i += 16) {
45288 for (j = 0; j < 64; j += 1) {
45292 W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
45293 sha256_Gamma0256(W[j - 15])), W[j - 16]);
45296 T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
45297 sha256_K[j]), W[j]);
45298 T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
45302 e = safe_add(d, T1);
45306 a = safe_add(T1, T2);
45309 HASH[0] = safe_add(a, HASH[0]);
45310 HASH[1] = safe_add(b, HASH[1]);
45311 HASH[2] = safe_add(c, HASH[2]);
45312 HASH[3] = safe_add(d, HASH[3]);
45313 HASH[4] = safe_add(e, HASH[4]);
45314 HASH[5] = safe_add(f, HASH[5]);
45315 HASH[6] = safe_add(g, HASH[6]);
45316 HASH[7] = safe_add(h, HASH[7]);
45324 * @class Hashes.SHA512
45327 * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
45328 * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
45329 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45330 * See http://pajhome.org.uk/crypt/md5 for details.
45332 SHA512: function(options) {
45334 * Private properties configuration variables. You may need to tweak these to be compatible with
45335 * the server-side, but the defaults work in most cases.
45336 * @see this.setUpperCase() method
45337 * @see this.setPad() method
45339 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45340 /* hexadecimal output case format. false - lowercase; true - uppercase */
45341 b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45342 /* base-64 pad character. Default '=' for strict RFC compliance */
45343 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45344 /* enable/disable utf8 encoding */
45347 /* privileged (public) methods */
45348 this.hex = function(s) {
45349 return rstr2hex(rstr(s));
45351 this.b64 = function(s) {
45352 return rstr2b64(rstr(s), b64pad);
45354 this.any = function(s, e) {
45355 return rstr2any(rstr(s), e);
45357 this.raw = function(s) {
45358 return rstr(s, utf8);
45360 this.hex_hmac = function(k, d) {
45361 return rstr2hex(rstr_hmac(k, d));
45363 this.b64_hmac = function(k, d) {
45364 return rstr2b64(rstr_hmac(k, d), b64pad);
45366 this.any_hmac = function(k, d, e) {
45367 return rstr2any(rstr_hmac(k, d), e);
45370 * Perform a simple self-test to see if the VM is working
45371 * @return {String} Hexadecimal hash sample
45374 this.vm_test = function() {
45375 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45378 * @description Enable/disable uppercase hexadecimal returned string
45380 * @return {Object} this
45383 this.setUpperCase = function(a) {
45384 if (typeof a === 'boolean') {
45390 * @description Defines a base64 pad string
45391 * @param {string} Pad
45392 * @return {Object} this
45395 this.setPad = function(a) {
45396 b64pad = a || b64pad;
45400 * @description Defines a base64 pad string
45402 * @return {Object} this
45405 this.setUTF8 = function(a) {
45406 if (typeof a === 'boolean') {
45412 /* private methods */
45415 * Calculate the SHA-512 of a raw string
45419 s = (utf8) ? utf8Encode(s) : s;
45420 return binb2rstr(binb(rstr2binb(s), s.length * 8));
45423 * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
45426 function rstr_hmac(key, data) {
45427 key = (utf8) ? utf8Encode(key) : key;
45428 data = (utf8) ? utf8Encode(data) : data;
45431 bkey = rstr2binb(key),
45435 if (bkey.length > 32) {
45436 bkey = binb(bkey, key.length * 8);
45439 for (; i < 32; i += 1) {
45440 ipad[i] = bkey[i] ^ 0x36363636;
45441 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45444 hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
45445 return binb2rstr(binb(opad.concat(hash), 1024 + 512));
45449 * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
45452 function binb(x, len) {
45455 hash = new Array(16),
45456 //Initial hash values
45458 new int64(0x6a09e667, -205731576),
45459 new int64(-1150833019, -2067093701),
45460 new int64(0x3c6ef372, -23791573),
45461 new int64(-1521486534, 0x5f1d36f1),
45462 new int64(0x510e527f, -1377402159),
45463 new int64(-1694144372, 0x2b3e6c1f),
45464 new int64(0x1f83d9ab, -79577749),
45465 new int64(0x5be0cd19, 0x137e2179)
45467 T1 = new int64(0, 0),
45468 T2 = new int64(0, 0),
45469 a = new int64(0, 0),
45470 b = new int64(0, 0),
45471 c = new int64(0, 0),
45472 d = new int64(0, 0),
45473 e = new int64(0, 0),
45474 f = new int64(0, 0),
45475 g = new int64(0, 0),
45476 h = new int64(0, 0),
45477 //Temporary variables not specified by the document
45478 s0 = new int64(0, 0),
45479 s1 = new int64(0, 0),
45480 Ch = new int64(0, 0),
45481 Maj = new int64(0, 0),
45482 r1 = new int64(0, 0),
45483 r2 = new int64(0, 0),
45484 r3 = new int64(0, 0);
45486 if (sha512_k === undefined) {
45489 new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
45490 new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
45491 new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
45492 new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
45493 new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
45494 new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
45495 new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
45496 new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
45497 new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
45498 new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
45499 new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
45500 new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
45501 new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
45502 new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
45503 new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
45504 new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
45505 new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
45506 new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
45507 new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
45508 new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
45509 new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
45510 new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
45511 new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
45512 new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
45513 new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
45514 new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
45515 new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
45516 new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
45517 new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
45518 new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
45519 new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
45520 new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
45521 new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
45522 new int64(-354779690, -840897762), new int64(-176337025, -294727304),
45523 new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
45524 new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
45525 new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
45526 new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
45527 new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
45528 new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
45532 for (i = 0; i < 80; i += 1) {
45533 W[i] = new int64(0, 0);
45536 // append padding to the source string. The format is described in the FIPS.
45537 x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
45538 x[((len + 128 >> 10) << 5) + 31] = len;
45540 for (i = 0; i < l; i += 32) { //32 dwords is the block size
45541 int64copy(a, H[0]);
45542 int64copy(b, H[1]);
45543 int64copy(c, H[2]);
45544 int64copy(d, H[3]);
45545 int64copy(e, H[4]);
45546 int64copy(f, H[5]);
45547 int64copy(g, H[6]);
45548 int64copy(h, H[7]);
45550 for (j = 0; j < 16; j += 1) {
45551 W[j].h = x[i + 2 * j];
45552 W[j].l = x[i + 2 * j + 1];
45555 for (j = 16; j < 80; j += 1) {
45557 int64rrot(r1, W[j - 2], 19);
45558 int64revrrot(r2, W[j - 2], 29);
45559 int64shr(r3, W[j - 2], 6);
45560 s1.l = r1.l ^ r2.l ^ r3.l;
45561 s1.h = r1.h ^ r2.h ^ r3.h;
45563 int64rrot(r1, W[j - 15], 1);
45564 int64rrot(r2, W[j - 15], 8);
45565 int64shr(r3, W[j - 15], 7);
45566 s0.l = r1.l ^ r2.l ^ r3.l;
45567 s0.h = r1.h ^ r2.h ^ r3.h;
45569 int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
45572 for (j = 0; j < 80; j += 1) {
45574 Ch.l = (e.l & f.l) ^ (~e.l & g.l);
45575 Ch.h = (e.h & f.h) ^ (~e.h & g.h);
45578 int64rrot(r1, e, 14);
45579 int64rrot(r2, e, 18);
45580 int64revrrot(r3, e, 9);
45581 s1.l = r1.l ^ r2.l ^ r3.l;
45582 s1.h = r1.h ^ r2.h ^ r3.h;
45585 int64rrot(r1, a, 28);
45586 int64revrrot(r2, a, 2);
45587 int64revrrot(r3, a, 7);
45588 s0.l = r1.l ^ r2.l ^ r3.l;
45589 s0.h = r1.h ^ r2.h ^ r3.h;
45592 Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
45593 Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
45595 int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
45596 int64add(T2, s0, Maj);
45601 int64add(e, d, T1);
45605 int64add(a, T1, T2);
45607 int64add(H[0], H[0], a);
45608 int64add(H[1], H[1], b);
45609 int64add(H[2], H[2], c);
45610 int64add(H[3], H[3], d);
45611 int64add(H[4], H[4], e);
45612 int64add(H[5], H[5], f);
45613 int64add(H[6], H[6], g);
45614 int64add(H[7], H[7], h);
45617 //represent the hash as an array of 32-bit dwords
45618 for (i = 0; i < 8; i += 1) {
45619 hash[2 * i] = H[i].h;
45620 hash[2 * i + 1] = H[i].l;
45625 //A constructor for 64-bit numbers
45627 function int64(h, l) {
45630 //this.toString = int64toString;
45633 //Copies src into dst, assuming both are 64-bit numbers
45635 function int64copy(dst, src) {
45640 //Right-rotates a 64-bit number by shift
45641 //Won't handle cases of shift>=32
45642 //The function revrrot() is for that
45644 function int64rrot(dst, x, shift) {
45645 dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45646 dst.h = (x.h >>> shift) | (x.l << (32 - shift));
45649 //Reverses the dwords of the source and then rotates right by shift.
45650 //This is equivalent to rotation by 32+shift
45652 function int64revrrot(dst, x, shift) {
45653 dst.l = (x.h >>> shift) | (x.l << (32 - shift));
45654 dst.h = (x.l >>> shift) | (x.h << (32 - shift));
45657 //Bitwise-shifts right a 64-bit number by shift
45658 //Won't handle shift>=32, but it's never needed in SHA512
45660 function int64shr(dst, x, shift) {
45661 dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45662 dst.h = (x.h >>> shift);
45665 //Adds two 64-bit numbers
45666 //Like the original implementation, does not rely on 32-bit operations
45668 function int64add(dst, x, y) {
45669 var w0 = (x.l & 0xffff) + (y.l & 0xffff);
45670 var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
45671 var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
45672 var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
45673 dst.l = (w0 & 0xffff) | (w1 << 16);
45674 dst.h = (w2 & 0xffff) | (w3 << 16);
45677 //Same, except with 4 addends. Works faster than adding them one by one.
45679 function int64add4(dst, a, b, c, d) {
45680 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
45681 var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
45682 var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
45683 var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
45684 dst.l = (w0 & 0xffff) | (w1 << 16);
45685 dst.h = (w2 & 0xffff) | (w3 << 16);
45688 //Same, except with 5 addends
45690 function int64add5(dst, a, b, c, d, e) {
45691 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
45692 w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
45693 w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
45694 w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
45695 dst.l = (w0 & 0xffff) | (w1 << 16);
45696 dst.h = (w2 & 0xffff) | (w3 << 16);
45700 * @class Hashes.RMD160
45702 * @param {Object} [config]
45704 * A JavaScript implementation of the RIPEMD-160 Algorithm
45705 * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
45706 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45707 * See http://pajhome.org.uk/crypt/md5 for details.
45708 * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
45710 RMD160: function(options) {
45712 * Private properties configuration variables. You may need to tweak these to be compatible with
45713 * the server-side, but the defaults work in most cases.
45714 * @see this.setUpperCase() method
45715 * @see this.setPad() method
45717 var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45718 /* hexadecimal output case format. false - lowercase; true - uppercase */
45719 b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45720 /* base-64 pad character. Default '=' for strict RFC compliance */
45721 utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45722 /* enable/disable utf8 encoding */
45724 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45725 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
45726 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
45727 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
45728 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
45731 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
45732 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
45733 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
45734 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
45735 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
45738 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
45739 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
45740 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
45741 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
45742 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
45745 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
45746 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
45747 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
45748 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
45749 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
45752 /* privileged (public) methods */
45753 this.hex = function(s) {
45754 return rstr2hex(rstr(s, utf8));
45756 this.b64 = function(s) {
45757 return rstr2b64(rstr(s, utf8), b64pad);
45759 this.any = function(s, e) {
45760 return rstr2any(rstr(s, utf8), e);
45762 this.raw = function(s) {
45763 return rstr(s, utf8);
45765 this.hex_hmac = function(k, d) {
45766 return rstr2hex(rstr_hmac(k, d));
45768 this.b64_hmac = function(k, d) {
45769 return rstr2b64(rstr_hmac(k, d), b64pad);
45771 this.any_hmac = function(k, d, e) {
45772 return rstr2any(rstr_hmac(k, d), e);
45775 * Perform a simple self-test to see if the VM is working
45776 * @return {String} Hexadecimal hash sample
45779 this.vm_test = function() {
45780 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45783 * @description Enable/disable uppercase hexadecimal returned string
45785 * @return {Object} this
45788 this.setUpperCase = function(a) {
45789 if (typeof a === 'boolean') {
45795 * @description Defines a base64 pad string
45796 * @param {string} Pad
45797 * @return {Object} this
45800 this.setPad = function(a) {
45801 if (typeof a !== 'undefined') {
45807 * @description Defines a base64 pad string
45809 * @return {Object} this
45812 this.setUTF8 = function(a) {
45813 if (typeof a === 'boolean') {
45819 /* private methods */
45822 * Calculate the rmd160 of a raw string
45826 s = (utf8) ? utf8Encode(s) : s;
45827 return binl2rstr(binl(rstr2binl(s), s.length * 8));
45831 * Calculate the HMAC-rmd160 of a key and some data (raw strings)
45834 function rstr_hmac(key, data) {
45835 key = (utf8) ? utf8Encode(key) : key;
45836 data = (utf8) ? utf8Encode(data) : data;
45838 bkey = rstr2binl(key),
45842 if (bkey.length > 16) {
45843 bkey = binl(bkey, key.length * 8);
45846 for (i = 0; i < 16; i += 1) {
45847 ipad[i] = bkey[i] ^ 0x36363636;
45848 opad[i] = bkey[i] ^ 0x5C5C5C5C;
45850 hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
45851 return binl2rstr(binl(opad.concat(hash), 512 + 160));
45855 * Convert an array of little-endian words to a string
45858 function binl2rstr(input) {
45859 var i, output = '',
45860 l = input.length * 32;
45861 for (i = 0; i < l; i += 8) {
45862 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
45868 * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
45871 function binl(x, len) {
45878 A1, B1, C1, D1, E1,
45879 A2, B2, C2, D2, E2;
45881 /* append padding */
45882 x[len >> 5] |= 0x80 << (len % 32);
45883 x[(((len + 64) >>> 9) << 4) + 14] = len;
45886 for (i = 0; i < l; i += 16) {
45892 for (j = 0; j <= 79; j += 1) {
45893 T = safe_add(A1, rmd160_f(j, B1, C1, D1));
45894 T = safe_add(T, x[i + rmd160_r1[j]]);
45895 T = safe_add(T, rmd160_K1(j));
45896 T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
45899 D1 = bit_rol(C1, 10);
45902 T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
45903 T = safe_add(T, x[i + rmd160_r2[j]]);
45904 T = safe_add(T, rmd160_K2(j));
45905 T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
45908 D2 = bit_rol(C2, 10);
45913 T = safe_add(h1, safe_add(C1, D2));
45914 h1 = safe_add(h2, safe_add(D1, E2));
45915 h2 = safe_add(h3, safe_add(E1, A2));
45916 h3 = safe_add(h4, safe_add(A1, B2));
45917 h4 = safe_add(h0, safe_add(B1, C2));
45920 return [h0, h1, h2, h3, h4];
45923 // specific algorithm methods
45925 function rmd160_f(j, x, y, z) {
45926 return (0 <= j && j <= 15) ? (x ^ y ^ z) :
45927 (16 <= j && j <= 31) ? (x & y) | (~x & z) :
45928 (32 <= j && j <= 47) ? (x | ~y) ^ z :
45929 (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
45930 (64 <= j && j <= 79) ? x ^ (y | ~z) :
45931 'rmd160_f: j out of range';
45934 function rmd160_K1(j) {
45935 return (0 <= j && j <= 15) ? 0x00000000 :
45936 (16 <= j && j <= 31) ? 0x5a827999 :
45937 (32 <= j && j <= 47) ? 0x6ed9eba1 :
45938 (48 <= j && j <= 63) ? 0x8f1bbcdc :
45939 (64 <= j && j <= 79) ? 0xa953fd4e :
45940 'rmd160_K1: j out of range';
45943 function rmd160_K2(j) {
45944 return (0 <= j && j <= 15) ? 0x50a28be6 :
45945 (16 <= j && j <= 31) ? 0x5c4dd124 :
45946 (32 <= j && j <= 47) ? 0x6d703ef3 :
45947 (48 <= j && j <= 63) ? 0x7a6d76e9 :
45948 (64 <= j && j <= 79) ? 0x00000000 :
45949 'rmd160_K2: j out of range';
45955 (function(window, undefined) {
45956 var freeExports = false;
45958 freeExports = exports;
45959 if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
45960 window = commonjsGlobal;
45964 if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) {
45965 // define as an anonymous module, so, through path mapping, it can be aliased
45966 undefined(function() {
45969 } else if (freeExports) {
45970 // in Node.js or RingoJS v0.8.0+
45971 if ('object' === 'object' && module && module.exports === freeExports) {
45972 module.exports = Hashes;
45974 // in Narwhal or RingoJS v0.7.0-
45976 freeExports.Hashes = Hashes;
45979 // in a browser or Rhino
45980 window.Hashes = Hashes;
45986 var immutable = extend$2;
45988 var hasOwnProperty = Object.prototype.hasOwnProperty;
45990 function extend$2() {
45993 for (var i = 0; i < arguments.length; i++) {
45994 var source = arguments[i];
45996 for (var key in source) {
45997 if (hasOwnProperty.call(source, key)) {
45998 target[key] = source[key];
46006 var sha1 = new hashes.SHA1();
46010 ohauth.qsString = function(obj) {
46011 return Object.keys(obj).sort().map(function(key) {
46012 return ohauth.percentEncode(key) + '=' +
46013 ohauth.percentEncode(obj[key]);
46017 ohauth.stringQs = function(str) {
46018 return str.split('&').filter(function (pair) {
46019 return pair !== '';
46020 }).reduce(function(obj, pair){
46021 var parts = pair.split('=');
46022 obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
46023 '' : decodeURIComponent(parts[1]);
46028 ohauth.rawxhr = function(method, url, data, headers, callback) {
46029 var xhr = new XMLHttpRequest(),
46030 twoHundred = /^20\d$/;
46031 xhr.onreadystatechange = function() {
46032 if (4 === xhr.readyState && 0 !== xhr.status) {
46033 if (twoHundred.test(xhr.status)) callback(null, xhr);
46034 else return callback(xhr, null);
46037 xhr.onerror = function(e) { return callback(e, null); };
46038 xhr.open(method, url, true);
46039 for (var h in headers) xhr.setRequestHeader(h, headers[h]);
46044 ohauth.xhr = function(method, url, auth, data, options, callback) {
46045 var headers = (options && options.header) || {
46046 'Content-Type': 'application/x-www-form-urlencoded'
46048 headers.Authorization = 'OAuth ' + ohauth.authHeader(auth);
46049 return ohauth.rawxhr(method, url, data, headers, callback);
46052 ohauth.nonce = function() {
46053 for (var o = ''; o.length < 6;) {
46054 o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
46059 ohauth.authHeader = function(obj) {
46060 return Object.keys(obj).sort().map(function(key) {
46061 return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
46065 ohauth.timestamp = function() { return ~~((+new Date()) / 1000); };
46067 ohauth.percentEncode = function(s) {
46068 return encodeURIComponent(s)
46069 .replace(/\!/g, '%21').replace(/\'/g, '%27')
46070 .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
46073 ohauth.baseString = function(method, url, params) {
46074 if (params.oauth_signature) delete params.oauth_signature;
46077 ohauth.percentEncode(url),
46078 ohauth.percentEncode(ohauth.qsString(params))].join('&');
46081 ohauth.signature = function(oauth_secret, token_secret, baseString) {
46082 return sha1.b64_hmac(
46083 ohauth.percentEncode(oauth_secret) + '&' +
46084 ohauth.percentEncode(token_secret),
46089 * Takes an options object for configuration (consumer_key,
46090 * consumer_secret, version, signature_method, token, token_secret)
46091 * and returns a function that generates the Authorization header
46094 * The returned function takes these parameters:
46095 * - method: GET/POST/...
46096 * - uri: full URI with protocol, port, path and query string
46097 * - extra_params: any extra parameters (that are passed in the POST data),
46098 * can be an object or a from-urlencoded string.
46100 * Returned function returns full OAuth header with "OAuth" string in it.
46103 ohauth.headerGenerator = function(options) {
46104 options = options || {};
46105 var consumer_key = options.consumer_key || '',
46106 consumer_secret = options.consumer_secret || '',
46107 signature_method = options.signature_method || 'HMAC-SHA1',
46108 version = options.version || '1.0',
46109 token = options.token || '',
46110 token_secret = options.token_secret || '';
46112 return function(method, uri, extra_params) {
46113 method = method.toUpperCase();
46114 if (typeof extra_params === 'string' && extra_params.length > 0) {
46115 extra_params = ohauth.stringQs(extra_params);
46118 var uri_parts = uri.split('?', 2),
46119 base_uri = uri_parts[0];
46121 var query_params = uri_parts.length === 2 ?
46122 ohauth.stringQs(uri_parts[1]) : {};
46124 var oauth_params = {
46125 oauth_consumer_key: consumer_key,
46126 oauth_signature_method: signature_method,
46127 oauth_version: version,
46128 oauth_timestamp: ohauth.timestamp(),
46129 oauth_nonce: ohauth.nonce()
46132 if (token) oauth_params.oauth_token = token;
46134 var all_params = immutable({}, oauth_params, query_params, extra_params),
46135 base_str = ohauth.baseString(method, base_uri, all_params);
46137 oauth_params.oauth_signature = ohauth.signature(consumer_secret, token_secret, base_str);
46139 return 'OAuth ' + ohauth.authHeader(oauth_params);
46143 var index$13 = ohauth;
46145 var store = createCommonjsModule(function (module, exports) {
46147 // Module export pattern from
46148 // https://github.com/umdjs/umd/blob/master/returnExports.js
46149 ;(function (root, factory) {
46150 if (typeof undefined === 'function' && undefined.amd) {
46151 // AMD. Register as an anonymous module.
46152 undefined([], factory);
46154 // Node. Does not work with strict CommonJS, but
46155 // only CommonJS-like environments that support module.exports,
46157 module.exports = factory();
46159 }(commonjsGlobal, function () {
46163 win = (typeof window != 'undefined' ? window : commonjsGlobal),
46164 doc = win.document,
46165 localStorageName = 'localStorage',
46166 scriptTag = 'script',
46169 store.disabled = false;
46170 store.version = '1.3.20';
46171 store.set = function(key, value) {};
46172 store.get = function(key, defaultVal) {};
46173 store.has = function(key) { return store.get(key) !== undefined };
46174 store.remove = function(key) {};
46175 store.clear = function() {};
46176 store.transact = function(key, defaultVal, transactionFn) {
46177 if (transactionFn == null) {
46178 transactionFn = defaultVal;
46181 if (defaultVal == null) {
46184 var val = store.get(key, defaultVal);
46185 transactionFn(val);
46186 store.set(key, val);
46188 store.getAll = function() {};
46189 store.forEach = function() {};
46191 store.serialize = function(value) {
46192 return JSON.stringify(value)
46194 store.deserialize = function(value) {
46195 if (typeof value != 'string') { return undefined }
46196 try { return JSON.parse(value) }
46197 catch(e) { return value || undefined }
46200 // Functions to encapsulate questionable FireFox 3.6.13 behavior
46201 // when about.config::dom.storage.enabled === false
46202 // See https://github.com/marcuswestin/store.js/issues#issue/13
46203 function isLocalStorageNameSupported() {
46204 try { return (localStorageName in win && win[localStorageName]) }
46205 catch(err) { return false }
46208 if (isLocalStorageNameSupported()) {
46209 storage = win[localStorageName];
46210 store.set = function(key, val) {
46211 if (val === undefined) { return store.remove(key) }
46212 storage.setItem(key, store.serialize(val));
46215 store.get = function(key, defaultVal) {
46216 var val = store.deserialize(storage.getItem(key));
46217 return (val === undefined ? defaultVal : val)
46219 store.remove = function(key) { storage.removeItem(key); };
46220 store.clear = function() { storage.clear(); };
46221 store.getAll = function() {
46223 store.forEach(function(key, val) {
46228 store.forEach = function(callback) {
46229 for (var i=0; i<storage.length; i++) {
46230 var key = storage.key(i);
46231 callback(key, store.get(key));
46234 } else if (doc && doc.documentElement.addBehavior) {
46237 // Since #userData storage applies only to specific paths, we need to
46238 // somehow link our data to a specific path. We choose /favicon.ico
46239 // as a pretty safe option, since all browsers already make a request to
46240 // this URL anyway and being a 404 will not hurt us here. We wrap an
46241 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
46242 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
46243 // since the iframe access rules appear to allow direct access and
46244 // manipulation of the document element, even for a 404 page. This
46245 // document can be used instead of the current document (which would
46246 // have been limited to the current path) to perform #userData storage.
46248 storageContainer = new ActiveXObject('htmlfile');
46249 storageContainer.open();
46250 storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
46251 storageContainer.close();
46252 storageOwner = storageContainer.w.frames[0].document;
46253 storage = storageOwner.createElement('div');
46255 // somehow ActiveXObject instantiation failed (perhaps some special
46256 // security settings or otherwse), fall back to per-path storage
46257 storage = doc.createElement('div');
46258 storageOwner = doc.body;
46260 var withIEStorage = function(storeFunction) {
46261 return function() {
46262 var args = Array.prototype.slice.call(arguments, 0);
46263 args.unshift(storage);
46264 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
46265 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
46266 storageOwner.appendChild(storage);
46267 storage.addBehavior('#default#userData');
46268 storage.load(localStorageName);
46269 var result = storeFunction.apply(store, args);
46270 storageOwner.removeChild(storage);
46275 // In IE7, keys cannot start with a digit or contain certain chars.
46276 // See https://github.com/marcuswestin/store.js/issues/40
46277 // See https://github.com/marcuswestin/store.js/issues/83
46278 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
46279 var ieKeyFix = function(key) {
46280 return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
46282 store.set = withIEStorage(function(storage, key, val) {
46283 key = ieKeyFix(key);
46284 if (val === undefined) { return store.remove(key) }
46285 storage.setAttribute(key, store.serialize(val));
46286 storage.save(localStorageName);
46289 store.get = withIEStorage(function(storage, key, defaultVal) {
46290 key = ieKeyFix(key);
46291 var val = store.deserialize(storage.getAttribute(key));
46292 return (val === undefined ? defaultVal : val)
46294 store.remove = withIEStorage(function(storage, key) {
46295 key = ieKeyFix(key);
46296 storage.removeAttribute(key);
46297 storage.save(localStorageName);
46299 store.clear = withIEStorage(function(storage) {
46300 var attributes = storage.XMLDocument.documentElement.attributes;
46301 storage.load(localStorageName);
46302 for (var i=attributes.length-1; i>=0; i--) {
46303 storage.removeAttribute(attributes[i].name);
46305 storage.save(localStorageName);
46307 store.getAll = function(storage) {
46309 store.forEach(function(key, val) {
46314 store.forEach = withIEStorage(function(storage, callback) {
46315 var attributes = storage.XMLDocument.documentElement.attributes;
46316 for (var i=0, attr; attr=attributes[i]; ++i) {
46317 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
46323 var testKey = '__storejs__';
46324 store.set(testKey, testKey);
46325 if (store.get(testKey) != testKey) { store.disabled = true; }
46326 store.remove(testKey);
46328 store.disabled = true;
46330 store.enabled = !store.disabled;
46338 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
46339 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
46340 // does not support custom headers, which this uses everywhere.
46341 var index$12 = function(o) {
46345 // authenticated users will also have a request token secret, but it's
46346 // not used in transactions with the server
46347 oauth.authenticated = function() {
46348 return !!(token('oauth_token') && token('oauth_token_secret'));
46351 oauth.logout = function() {
46352 token('oauth_token', '');
46353 token('oauth_token_secret', '');
46354 token('oauth_request_token_secret', '');
46358 // TODO: detect lack of click event
46359 oauth.authenticate = function(callback) {
46360 if (oauth.authenticated()) return callback();
46364 // ## Getting a request token
46365 var params = timenonce(getAuth(o)),
46366 url = o.url + '/oauth/request_token';
46368 params.oauth_signature = index$13.signature(
46369 o.oauth_secret, '',
46370 index$13.baseString('POST', url, params));
46372 if (!o.singlepage) {
46373 // Create a 600x550 popup window in the center of the screen
46374 var w = 600, h = 550,
46376 ['width', w], ['height', h],
46377 ['left', screen.width / 2 - w / 2],
46378 ['top', screen.height / 2 - h / 2]].map(function(x) {
46379 return x.join('=');
46381 popup = window.open('about:blank', 'oauth_window', settings);
46384 // Request a request token. When this is complete, the popup
46385 // window is redirected to OSM's authorization page.
46386 index$13.xhr('POST', url, params, null, {}, reqTokenDone);
46389 function reqTokenDone(err, xhr) {
46391 if (err) return callback(err);
46392 var resp = index$13.stringQs(xhr.response);
46393 token('oauth_request_token_secret', resp.oauth_token_secret);
46394 var authorize_url = o.url + '/oauth/authorize?' + index$13.qsString({
46395 oauth_token: resp.oauth_token,
46396 oauth_callback: location.href.replace('index.html', '')
46397 .replace(/#.*/, '').replace(location.search, '') + o.landing
46400 if (o.singlepage) {
46401 location.href = authorize_url;
46403 popup.location = authorize_url;
46407 // Called by a function in a landing page, in the popup window. The
46408 // window closes itself.
46409 window.authComplete = function(token) {
46410 var oauth_token = index$13.stringQs(token.split('?')[1]);
46411 get_access_token(oauth_token.oauth_token);
46412 delete window.authComplete;
46415 // ## Getting an request token
46417 // At this point we have an `oauth_token`, brought in from a function
46418 // call on a landing page popup.
46419 function get_access_token(oauth_token) {
46420 var url = o.url + '/oauth/access_token',
46421 params = timenonce(getAuth(o)),
46422 request_token_secret = token('oauth_request_token_secret');
46423 params.oauth_token = oauth_token;
46424 params.oauth_signature = index$13.signature(
46426 request_token_secret,
46427 index$13.baseString('POST', url, params));
46429 // ## Getting an access token
46431 // The final token required for authentication. At this point
46432 // we have a `request token secret`
46433 index$13.xhr('POST', url, params, null, {}, accessTokenDone);
46437 function accessTokenDone(err, xhr) {
46439 if (err) return callback(err);
46440 var access_token = index$13.stringQs(xhr.response);
46441 token('oauth_token', access_token.oauth_token);
46442 token('oauth_token_secret', access_token.oauth_token_secret);
46443 callback(null, oauth);
46447 oauth.bootstrapToken = function(oauth_token, callback) {
46448 // ## Getting an request token
46449 // At this point we have an `oauth_token`, brought in from a function
46450 // call on a landing page popup.
46451 function get_access_token(oauth_token) {
46452 var url = o.url + '/oauth/access_token',
46453 params = timenonce(getAuth(o)),
46454 request_token_secret = token('oauth_request_token_secret');
46455 params.oauth_token = oauth_token;
46456 params.oauth_signature = index$13.signature(
46458 request_token_secret,
46459 index$13.baseString('POST', url, params));
46461 // ## Getting an access token
46462 // The final token required for authentication. At this point
46463 // we have a `request token secret`
46464 index$13.xhr('POST', url, params, null, {}, accessTokenDone);
46468 function accessTokenDone(err, xhr) {
46470 if (err) return callback(err);
46471 var access_token = index$13.stringQs(xhr.response);
46472 token('oauth_token', access_token.oauth_token);
46473 token('oauth_token_secret', access_token.oauth_token_secret);
46474 callback(null, oauth);
46477 get_access_token(oauth_token);
46482 // A single XMLHttpRequest wrapper that does authenticated calls if the
46483 // user has logged in.
46484 oauth.xhr = function(options, callback) {
46485 if (!oauth.authenticated()) {
46487 return oauth.authenticate(run);
46489 callback('not authenticated', null);
46497 var params = timenonce(getAuth(o)),
46498 oauth_token_secret = token('oauth_token_secret'),
46499 url = (options.prefix !== false) ? o.url + options.path : options.path,
46500 url_parts = url.replace(/#.*$/, '').split('?', 2),
46501 base_url = url_parts[0],
46502 query = (url_parts.length === 2) ? url_parts[1] : '';
46504 // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
46505 if ((!options.options || !options.options.header ||
46506 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
46508 params = immutable(params, index$13.stringQs(options.content));
46511 params.oauth_token = token('oauth_token');
46512 params.oauth_signature = index$13.signature(
46514 oauth_token_secret,
46515 index$13.baseString(options.method, base_url, immutable(params, index$13.stringQs(query)))
46518 return index$13.xhr(options.method, url, params, options.content, options.options, done);
46521 function done(err, xhr) {
46522 if (err) return callback(err);
46523 else if (xhr.responseXML) return callback(err, xhr.responseXML);
46524 else return callback(err, xhr.response);
46528 // pre-authorize this object, if we can just get a token and token_secret
46530 oauth.preauth = function(c) {
46532 if (c.oauth_token) token('oauth_token', c.oauth_token);
46533 if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
46537 oauth.options = function(_) {
46538 if (!arguments.length) return o;
46541 o.url = o.url || 'http://www.openstreetmap.org';
46542 o.landing = o.landing || 'land.html';
46543 o.singlepage = o.singlepage || false;
46545 // Optional loading and loading-done functions for nice UI feedback.
46546 // by default, no-ops
46547 o.loading = o.loading || function() {};
46548 o.done = o.done || function() {};
46550 return oauth.preauth(o);
46553 // 'stamp' an authentication object from `getAuth()`
46554 // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
46556 function timenonce(o) {
46557 o.oauth_timestamp = index$13.timestamp();
46558 o.oauth_nonce = index$13.nonce();
46562 // get/set tokens. These are prefixed with the base URL so that `osm-auth`
46563 // can be used with multiple APIs and the keys in `localStorage`
46567 if (store.enabled) {
46568 token = function (x, y) {
46569 if (arguments.length === 1) return store.get(o.url + x);
46570 else if (arguments.length === 2) return store.set(o.url + x, y);
46574 token = function (x, y) {
46575 if (arguments.length === 1) return storage[o.url + x];
46576 else if (arguments.length === 2) return storage[o.url + x] = y;
46580 // Get an authentication object. If you just add and remove properties
46581 // from a single object, you'll need to use `delete` to make sure that
46582 // it doesn't contain undesired properties for authentication
46583 function getAuth(o) {
46585 oauth_consumer_key: o.oauth_consumer_key,
46586 oauth_signature_method: 'HMAC-SHA1'
46590 // potentially pre-authorize
46596 var JXON = new (function () {
46598 sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
46599 aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
46601 function parseText (sValue) {
46602 if (rIsNull.test(sValue)) { return null; }
46603 if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
46604 if (isFinite(sValue)) { return parseFloat(sValue); }
46605 if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
46609 function EmptyTree () { }
46610 EmptyTree.prototype.toString = function () { return 'null'; };
46611 EmptyTree.prototype.valueOf = function () { return null; };
46613 function objectify (vValue) {
46614 return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
46617 function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
46619 nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
46620 bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
46623 sProp, vContent, nLength = 0, sCollectedTxt = '',
46624 vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
46627 for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
46628 oNode = oParentNode.childNodes.item(nItem);
46629 if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
46630 else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
46631 else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
46635 var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
46637 if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
46639 for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
46640 sProp = aCache[nElId].nodeName.toLowerCase();
46641 vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
46642 if (vResult.hasOwnProperty(sProp)) {
46643 if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
46644 vResult[sProp].push(vContent);
46646 vResult[sProp] = vContent;
46653 nAttrLen = oParentNode.attributes.length,
46654 sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
46656 for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
46657 oAttrib = oParentNode.attributes.item(nAttrib);
46658 oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
46662 if (bFreeze) { Object.freeze(oAttrParent); }
46663 vResult[sAttributesProp] = oAttrParent;
46664 nLength -= nAttrLen - 1;
46668 if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
46669 vResult[sValueProp] = vBuiltVal;
46670 } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
46671 vResult = vBuiltVal;
46674 if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
46676 aCache.length = nLevelStart;
46681 function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
46682 var vValue, oChild;
46684 if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
46685 oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
46686 } else if (oParentObj.constructor === Date) {
46687 oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));
46690 for (var sName in oParentObj) {
46691 vValue = oParentObj[sName];
46692 if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
46693 if (sName === sValueProp) {
46694 if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
46695 } else if (sName === sAttributesProp) { /* verbosity level is 3 */
46696 for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
46697 } else if (sName.charAt(0) === sAttrPref) {
46698 oParentEl.setAttribute(sName.slice(1), vValue);
46699 } else if (vValue.constructor === Array) {
46700 for (var nItem = 0; nItem < vValue.length; nItem++) {
46701 oChild = oXMLDoc.createElement(sName);
46702 loadObjTree(oXMLDoc, oChild, vValue[nItem]);
46703 oParentEl.appendChild(oChild);
46706 oChild = oXMLDoc.createElement(sName);
46707 if (vValue instanceof Object) {
46708 loadObjTree(oXMLDoc, oChild, vValue);
46709 } else if (vValue !== null && vValue !== true) {
46710 oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
46712 oParentEl.appendChild(oChild);
46717 this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
46718 var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
46719 return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);
46722 this.unbuild = function (oObjTree) {
46723 var oNewDoc = document.implementation.createDocument('', '', null);
46724 loadObjTree(oNewDoc, oNewDoc, oObjTree);
46728 this.stringify = function (oObjTree) {
46729 return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
46733 // var myObject = JXON.build(doc);
46734 // we got our javascript object! try: alert(JSON.stringify(myObject));
46736 // var newDoc = JXON.unbuild(myObject);
46737 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
46739 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
46740 var urlroot = 'https://www.openstreetmap.org';
46741 var blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'];
46742 var inflight$1 = {};
46743 var loadedTiles = {};
46744 var tileZoom$1 = 16;
46745 var oauth = index$12({
46747 oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
46748 oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
46749 loading: authLoading,
46752 var rateLimitError;
46753 var userChangesets;
46758 function authLoading() {
46759 dispatch$3.call('authLoading');
46763 function authDone() {
46764 dispatch$3.call('authDone');
46768 function abortRequest$1(i) {
46775 function getLoc(attrs) {
46776 var lon = attrs.lon && attrs.lon.value,
46777 lat = attrs.lat && attrs.lat.value;
46778 return [parseFloat(lon), parseFloat(lat)];
46782 function getNodes(obj) {
46783 var elems = obj.getElementsByTagName('nd'),
46784 nodes = new Array(elems.length);
46785 for (var i = 0, l = elems.length; i < l; i++) {
46786 nodes[i] = 'n' + elems[i].attributes.ref.value;
46792 function getTags(obj) {
46793 var elems = obj.getElementsByTagName('tag'),
46795 for (var i = 0, l = elems.length; i < l; i++) {
46796 var attrs = elems[i].attributes;
46797 tags[attrs.k.value] = attrs.v.value;
46804 function getMembers(obj) {
46805 var elems = obj.getElementsByTagName('member'),
46806 members = new Array(elems.length);
46807 for (var i = 0, l = elems.length; i < l; i++) {
46808 var attrs = elems[i].attributes;
46810 id: attrs.type.value[0] + attrs.ref.value,
46811 type: attrs.type.value,
46812 role: attrs.role.value
46819 function getVisible(attrs) {
46820 return (!attrs.visible || attrs.visible.value !== 'false');
46825 node: function nodeData(obj) {
46826 var attrs = obj.attributes;
46827 return new osmNode({
46828 id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
46829 loc: getLoc(attrs),
46830 version: attrs.version.value,
46831 user: attrs.user && attrs.user.value,
46832 tags: getTags(obj),
46833 visible: getVisible(attrs)
46837 way: function wayData(obj) {
46838 var attrs = obj.attributes;
46839 return new osmWay({
46840 id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
46841 version: attrs.version.value,
46842 user: attrs.user && attrs.user.value,
46843 tags: getTags(obj),
46844 nodes: getNodes(obj),
46845 visible: getVisible(attrs)
46849 relation: function relationData(obj) {
46850 var attrs = obj.attributes;
46851 return new osmRelation({
46852 id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
46853 version: attrs.version.value,
46854 user: attrs.user && attrs.user.value,
46855 tags: getTags(obj),
46856 members: getMembers(obj),
46857 visible: getVisible(attrs)
46863 function parse(xml$$1) {
46864 if (!xml$$1 || !xml$$1.childNodes) return;
46866 var root = xml$$1.childNodes[0],
46867 children = root.childNodes,
46870 for (var i = 0, l = children.length; i < l; i++) {
46871 var child = children[i],
46872 parser = parsers[child.nodeName];
46874 entities.push(parser(child));
46885 utilRebind(this, dispatch$3, 'on');
46889 reset: function() {
46890 userChangesets = undefined;
46891 userDetails = undefined;
46892 rateLimitError = undefined;
46893 lodash.forEach(inflight$1, abortRequest$1);
46900 changesetURL: function(changesetId) {
46901 return urlroot + '/changeset/' + changesetId;
46905 changesetsURL: function(center, zoom$$1) {
46906 var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
46907 return urlroot + '/history#map=' +
46908 Math.floor(zoom$$1) + '/' +
46909 center[1].toFixed(precision) + '/' +
46910 center[0].toFixed(precision);
46914 entityURL: function(entity) {
46915 return urlroot + '/' + entity.type + '/' + entity.osmId();
46919 userURL: function(username) {
46920 return urlroot + '/user/' + username;
46924 loadFromAPI: function(path$$1, callback) {
46927 function done(err, xml$$1) {
46928 var isAuthenticated = that.authenticated();
46930 // 400 Bad Request, 401 Unauthorized, 403 Forbidden
46931 // Logout and retry the request..
46932 if (isAuthenticated && err &&
46933 (err.status === 400 || err.status === 401 || err.status === 403)) {
46935 that.loadFromAPI(path$$1, callback);
46937 // else, no retry..
46939 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
46940 // Set the rateLimitError flag and trigger a warning..
46941 if (!isAuthenticated && !rateLimitError && err &&
46942 (err.status === 509 || err.status === 429)) {
46943 rateLimitError = err;
46944 dispatch$3.call('change');
46948 callback(err, parse(xml$$1));
46953 if (this.authenticated()) {
46954 return oauth.xhr({ method: 'GET', path: path$$1 }, done);
46956 var url = urlroot + path$$1;
46957 return xml(url).get(done);
46962 loadEntity: function(id, callback) {
46963 var type = osmEntity$$1.id.type(id),
46964 osmID = osmEntity$$1.id.toOSM(id);
46967 '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
46968 function(err, entities) {
46969 if (callback) callback(err, { data: entities });
46975 loadEntityVersion: function(id, version$$1, callback) {
46976 var type = osmEntity$$1.id.type(id),
46977 osmID = osmEntity$$1.id.toOSM(id);
46980 '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
46981 function(err, entities) {
46982 if (callback) callback(err, { data: entities });
46988 loadMultiple: function(ids, callback) {
46990 lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
46991 var type = k + 's',
46992 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
46994 lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
46996 '/api/0.6/' + type + '?' + type + '=' + arr.join(),
46997 function(err, entities) {
46998 if (callback) callback(err, { data: entities });
47006 authenticated: function() {
47007 return oauth.authenticated();
47011 putChangeset: function(changeset, changes, callback) {
47013 // Create the changeset..
47016 path: '/api/0.6/changeset/create',
47017 options: { header: { 'Content-Type': 'text/xml' } },
47018 content: JXON.stringify(changeset.asJXON())
47019 }, createdChangeset);
47022 function createdChangeset(err, changeset_id) {
47023 if (err) return callback(err);
47024 changeset = changeset.update({ id: changeset_id });
47026 // Upload the changeset..
47029 path: '/api/0.6/changeset/' + changeset_id + '/upload',
47030 options: { header: { 'Content-Type': 'text/xml' } },
47031 content: JXON.stringify(changeset.osmChangeJXON(changes))
47032 }, uploadedChangeset);
47036 function uploadedChangeset(err) {
47037 if (err) return callback(err);
47039 // Upload was successful, safe to call the callback.
47040 // Add delay to allow for postgres replication #1646 #2678
47041 window.setTimeout(function() {
47042 callback(null, changeset);
47045 // Still attempt to close changeset, but ignore response because #2667
47048 path: '/api/0.6/changeset/' + changeset.id + '/close',
47049 options: { header: { 'Content-Type': 'text/xml' } }
47050 }, function() { return true; });
47055 userDetails: function(callback) {
47057 callback(undefined, userDetails);
47061 function done(err, user_details) {
47062 if (err) return callback(err);
47064 var u = user_details.getElementsByTagName('user')[0],
47065 img = u.getElementsByTagName('img'),
47068 if (img && img[0] && img[0].getAttribute('href')) {
47069 image_url = img[0].getAttribute('href');
47073 display_name: u.attributes.display_name.value,
47074 image_url: image_url,
47075 id: u.attributes.id.value
47078 callback(undefined, userDetails);
47081 oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
47085 userChangesets: function(callback) {
47086 if (userChangesets) {
47087 callback(undefined, userChangesets);
47091 this.userDetails(function(err, user) {
47097 function done(err, changesets) {
47101 userChangesets = Array.prototype.map.call(
47102 changesets.getElementsByTagName('changeset'),
47103 function (changeset) {
47104 return { tags: getTags(changeset) };
47106 ).filter(function (changeset) {
47107 var comment = changeset.tags.comment;
47108 return comment && comment !== '';
47110 callback(undefined, userChangesets);
47114 oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
47119 status: function(callback) {
47120 function done(xml$$1) {
47121 // update blacklists
47122 var elements = xml$$1.getElementsByTagName('blacklist'),
47124 for (var i = 0; i < elements.length; i++) {
47125 var regex = elements[i].getAttribute('regex'); // needs unencode?
47127 regexes.push(regex);
47130 if (regexes.length) {
47131 blacklists = regexes;
47135 if (rateLimitError) {
47136 callback(rateLimitError, 'rateLimited');
47138 var apiStatus = xml$$1.getElementsByTagName('status'),
47139 val = apiStatus[0].getAttribute('api');
47141 callback(undefined, val);
47145 xml(urlroot + '/api/capabilities').get()
47147 .on('error', callback);
47151 imageryBlacklists: function() {
47156 tileZoom: function(_) {
47157 if (!arguments.length) return tileZoom$1;
47163 loadTiles: function(projection, dimensions, callback) {
47167 s = projection.scale() * 2 * Math.PI,
47168 z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
47169 ts = 256 * Math.pow(2, z - tileZoom$1),
47171 s / 2 - projection.translate()[0],
47172 s / 2 - projection.translate()[1]
47175 var tiles = d3geoTile()
47176 .scaleExtent([tileZoom$1, tileZoom$1])
47179 .translate(projection.translate())()
47180 .map(function(tile) {
47181 var x = tile[0] * ts - origin[0],
47182 y = tile[1] * ts - origin[1];
47185 id: tile.toString(),
47186 extent: geoExtent$$1(
47187 projection.invert([x, y + ts]),
47188 projection.invert([x + ts, y]))
47192 lodash.filter(inflight$1, function(v, i) {
47193 var wanted = lodash.find(tiles, function(tile) {
47194 return i === tile.id;
47196 if (!wanted) delete inflight$1[i];
47198 }).map(abortRequest$1);
47200 tiles.forEach(function(tile) {
47203 if (loadedTiles[id] || inflight$1[id]) return;
47205 if (lodash.isEmpty(inflight$1)) {
47206 dispatch$3.call('loading');
47209 inflight$1[id] = that.loadFromAPI(
47210 '/api/0.6/map?bbox=' + tile.extent.toParam(),
47211 function(err, parsed) {
47212 delete inflight$1[id];
47214 loadedTiles[id] = true;
47218 callback(err, lodash.extend({ data: parsed }, tile));
47221 if (lodash.isEmpty(inflight$1)) {
47222 dispatch$3.call('loaded');
47230 switch: function(options) {
47231 urlroot = options.urlroot;
47233 oauth.options(lodash.extend({
47235 loading: authLoading,
47239 dispatch$3.call('change');
47241 this.userChangesets(function() {}); // eagerly load user details/changesets
47246 toggle: function(_) {
47252 loadedTiles: function(_) {
47253 if (!arguments.length) return loadedTiles;
47259 logout: function() {
47260 userChangesets = undefined;
47261 userDetails = undefined;
47263 dispatch$3.call('change');
47268 authenticate: function(callback) {
47270 userChangesets = undefined;
47271 userDetails = undefined;
47273 function done(err, res) {
47274 rateLimitError = undefined;
47275 dispatch$3.call('change');
47276 if (callback) callback(err, res);
47277 that.userChangesets(function() {}); // eagerly load user details/changesets
47280 return oauth.authenticate(done);
47284 var apibase$2 = 'https://taginfo.openstreetmap.org/api/4/';
47285 var inflight$2 = {};
47286 var popularKeys = {};
47287 var taginfoCache = {};
47289 point: 'count_nodes',
47290 vertex: 'count_nodes',
47291 area: 'count_ways',
47294 var tag_sort_members = {
47295 point: 'count_node_members',
47296 vertex: 'count_node_members',
47297 area: 'count_way_members',
47298 line: 'count_way_members',
47299 relation: 'count_relation_members'
47301 var tag_filters = {
47307 var tag_members_fractions = {
47308 point: 'count_node_members_fraction',
47309 vertex: 'count_node_members_fraction',
47310 area: 'count_way_members_fraction',
47311 line: 'count_way_members_fraction',
47312 relation: 'count_relation_members_fraction'
47316 function sets(params, n, o) {
47317 if (params.geometry && o[params.geometry]) {
47318 params[n] = o[params.geometry];
47324 function setFilter(params) {
47325 return sets(params, 'filter', tag_filters);
47329 function setSort(params) {
47330 return sets(params, 'sortname', tag_sorts);
47334 function setSortMembers(params) {
47335 return sets(params, 'sortname', tag_sort_members);
47339 function clean(params) {
47340 return lodash.omit(params, ['geometry', 'debounce']);
47344 function filterKeys(type) {
47345 var count_type = type ? 'count_' + type : 'count_all';
47346 return function(d) {
47347 return parseFloat(d[count_type]) > 2500 || d.in_wiki;
47352 function filterMultikeys(prefix) {
47353 return function(d) {
47354 // d.key begins with prefix, and d.key contains no additional ':'s
47355 var re = new RegExp('^' + prefix + '(.*)$');
47356 var matches = d.key.match(re) || [];
47357 return (matches.length === 2 && matches[1].indexOf(':') === -1);
47362 function filterValues(allowUpperCase) {
47363 return function(d) {
47364 if (d.value.match(/[;,]/) !== null) return false; // exclude some punctuation
47365 if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false; // exclude uppercase letters
47366 return parseFloat(d.fraction) > 0.0 || d.in_wiki;
47371 function filterRoles(geometry) {
47372 return function(d) {
47373 if (d.role === '') return false; // exclude empty role
47374 if (d.role.match(/[A-Z*;,]/) !== null) return false; // exclude uppercase letters and some punctuation
47375 return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
47380 function valKey(d) {
47388 function valKeyDescription(d) {
47391 title: d.description || d.value
47396 function roleKey(d) {
47404 // sort keys with ':' lower than keys without ':'
47405 function sortKeys(a, b) {
47406 return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
47407 : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
47412 var debouncedRequest = lodash.debounce(request$1, 500, { leading: false });
47414 function request$1(url, params, exactMatch, callback, loaded) {
47415 if (inflight$2[url]) return;
47417 if (checkCache(url, params, exactMatch, callback)) return;
47419 inflight$2[url] = json(url, function (err, data) {
47420 delete inflight$2[url];
47426 function checkCache(url, params, exactMatch, callback) {
47427 var rp = params.rp || 25,
47428 testQuery = params.query || '',
47432 var hit = taginfoCache[testUrl];
47434 // exact match, or shorter match yielding fewer than max results (rp)
47435 if (hit && (url === testUrl || hit.length < rp)) {
47436 callback(null, hit);
47440 // don't try to shorten the query
47441 if (exactMatch || !testQuery.length) return false;
47443 // do shorten the query to see if we already have a cached result
47444 // that has returned fewer than max results (rp)
47445 testQuery = testQuery.slice(0, -1);
47446 testUrl = url.replace(/&query=(.*?)&/, '&query=' + testQuery + '&');
47447 } while (testQuery.length >= 0);
47453 var serviceTaginfo = {
47460 // Fetch popular keys. We'll exclude these from `values`
47461 // lookups because they stress taginfo, and they aren't likely
47462 // to yield meaningful autocomplete results.. see #3955
47463 var params = { rp: 100, sortname: 'values_all', sortorder: 'desc', page: 1, debounce: false };
47464 this.keys(params, function(err, data) {
47466 data.forEach(function(d) {
47467 if (d.value === 'opening_hours') return; // exception
47468 popularKeys[d.value] = true;
47474 reset: function() {
47475 lodash.forEach(inflight$2, function(req) { req.abort(); });
47480 keys: function(params, callback) {
47481 var doRequest = params.debounce ? debouncedRequest : request$1;
47482 params = clean(setSort(params));
47483 params = lodash.extend({ rp: 10, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
47485 var url = apibase$2 + 'keys/all?' + utilQsString(params);
47486 doRequest(url, params, false, callback, function(err, d) {
47490 var f = filterKeys(params.filter);
47491 var result = d.data.filter(f).sort(sortKeys).map(valKey);
47492 taginfoCache[url] = result;
47493 callback(null, result);
47499 multikeys: function(params, callback) {
47500 var doRequest = params.debounce ? debouncedRequest : request$1;
47501 params = clean(setSort(params));
47502 params = lodash.extend({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
47503 var prefix = params.query;
47505 var url = apibase$2 + 'keys/all?' + utilQsString(params);
47506 doRequest(url, params, true, callback, function(err, d) {
47510 var f = filterMultikeys(prefix);
47511 var result = d.data.filter(f).map(valKey);
47512 taginfoCache[url] = result;
47513 callback(null, result);
47519 values: function(params, callback) {
47520 // Exclude popular keys from values lookups.. see #3955
47521 var key = params.key;
47522 if (key && popularKeys[key]) {
47523 callback(null, []);
47527 var doRequest = params.debounce ? debouncedRequest : request$1;
47528 params = clean(setSort(setFilter(params)));
47529 params = lodash.extend({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params);
47531 var url = apibase$2 + 'key/values?' + utilQsString(params);
47532 doRequest(url, params, false, callback, function(err, d) {
47536 // In most cases we prefer taginfo value results with lowercase letters.
47537 // A few OSM keys expect values to contain uppercase values (see #3377).
47538 // This is not an exhaustive list (e.g. `name` also has uppercase values)
47539 // but these are the fields where taginfo value lookup is most useful.
47540 var re = /network|taxon|genus|species|brand|grape_variety|_hours|_times/;
47541 var allowUpperCase = (params.key.match(re) !== null);
47542 var f = filterValues(allowUpperCase);
47544 var result = d.data.filter(f).map(valKeyDescription);
47545 taginfoCache[url] = result;
47546 callback(null, result);
47552 roles: function(params, callback) {
47553 var doRequest = params.debounce ? debouncedRequest : request$1;
47554 var geometry = params.geometry;
47555 params = clean(setSortMembers(params));
47556 params = lodash.extend({ rp: 25, sortname: 'count_all_members', sortorder: 'desc', page: 1 }, params);
47558 var url = apibase$2 + 'relation/roles?' + utilQsString(params);
47559 doRequest(url, params, true, callback, function(err, d) {
47563 var f = filterRoles(geometry);
47564 var result = d.data.filter(f).map(roleKey);
47565 taginfoCache[url] = result;
47566 callback(null, result);
47572 docs: function(params, callback) {
47573 var doRequest = params.debounce ? debouncedRequest : request$1;
47574 params = clean(setSort(params));
47576 var path$$1 = 'key/wiki_pages?';
47577 if (params.value) path$$1 = 'tag/wiki_pages?';
47578 else if (params.rtype) path$$1 = 'relation/wiki_pages?';
47580 var url = apibase$2 + path$$1 + utilQsString(params);
47581 doRequest(url, params, true, callback, function(err, d) {
47585 taginfoCache[url] = d.data;
47586 callback(null, d.data);
47592 apibase: function(_) {
47593 if (!arguments.length) return apibase$2;
47600 var jsonpCache = {};
47601 window.jsonpCache = jsonpCache;
47603 function jsonpRequest(url, callback) {
47605 if (window.JSONP_FIX) {
47606 if (window.JSONP_DELAY === 0) {
47607 callback(window.JSONP_FIX);
47609 setTimeout(function() {
47610 callback(window.JSONP_FIX);
47611 }, window.JSONP_DELAY || 0);
47617 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
47619 while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
47623 function create(url) {
47624 var e = url.match(/callback=(\w+)/),
47625 c = e ? e[1] : rand();
47626 jsonpCache[c] = function(data) {
47628 delete jsonpCache[c];
47631 return 'jsonpCache.' + c;
47634 var cb = create(url),
47635 script = select('head')
47637 .attr('type', 'text/javascript')
47638 .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
47641 var endpoint = 'https://www.wikidata.org/w/api.php?';
47643 var serviceWikidata = {
47645 init: function() {},
47646 reset: function() {},
47649 // Given a Wikipedia language and article title, return an array of
47650 // corresponding Wikidata entities.
47651 itemsByTitle: function(lang, title, callback) {
47657 lang = lang || 'en';
47658 jsonpRequest(endpoint + utilQsString({
47659 action: 'wbgetentities',
47661 sites: lang.replace(/-/g, '_') + 'wiki',
47663 languages: 'en', // shrink response by filtering to one language
47664 callback: '{callback}'
47665 }), function(data) {
47666 if (!data || data.error) {
47669 callback(title, data.entities || {});
47676 var endpoint$1 = 'https://en.wikipedia.org/w/api.php?';
47678 var serviceWikipedia = {
47680 init: function() {},
47681 reset: function() {},
47684 search: function(lang, query, callback) {
47690 lang = lang || 'en';
47691 jsonpRequest(endpoint$1.replace('en', lang) +
47696 srinfo: 'suggestion',
47698 callback: '{callback}',
47700 }), function(data) {
47701 if (!data || !data.query || !data.query.search || data.error) {
47704 var results = data.query.search.map(function(d) { return d.title; });
47705 callback(query, results);
47712 suggestions: function(lang, query, callback) {
47718 lang = lang || 'en';
47719 jsonpRequest(endpoint$1.replace('en', lang) +
47721 action: 'opensearch',
47725 callback: '{callback}',
47727 }), function(data) {
47728 if (!data || data.error) {
47731 callback(data[0], data[1] || []);
47738 translations: function(lang, title, callback) {
47744 jsonpRequest(endpoint$1.replace('en', lang) +
47749 callback: '{callback}',
47752 }), function(data) {
47753 if (!data || !data.query || !data.query.pages || data.error) {
47756 var list = data.query.pages[Object.keys(data.query.pages)[0]],
47758 if (list && list.langlinks) {
47759 list.langlinks.forEach(function(d) {
47760 translations[d.lang] = d['*'];
47763 callback(translations);
47772 mapillary: serviceMapillary,
47773 geocoder: serviceNominatim,
47775 taginfo: serviceTaginfo,
47776 wikidata: serviceWikidata,
47777 wikipedia: serviceWikipedia
47780 function svgMapillaryImages(projection, context, dispatch$$1) {
47781 var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47783 minViewfieldZoom = 17,
47784 layer = select(null),
47789 if (svgMapillaryImages.initialized) return; // run once
47790 svgMapillaryImages.enabled = false;
47791 svgMapillaryImages.initialized = true;
47795 function getMapillary() {
47796 if (services.mapillary && !_mapillary) {
47797 _mapillary = services.mapillary;
47798 _mapillary.event.on('loadedImages', throttledRedraw);
47799 } else if (!services.mapillary && _mapillary) {
47807 function showLayer() {
47808 var mapillary = getMapillary();
47809 if (!mapillary) return;
47811 mapillary.loadViewer(context);
47815 .style('opacity', 0)
47818 .style('opacity', 1)
47819 .on('end', function () { dispatch$$1.call('change'); });
47823 function hideLayer() {
47824 var mapillary = getMapillary();
47826 mapillary.hideViewer();
47829 throttledRedraw.cancel();
47834 .style('opacity', 0)
47835 .on('end', editOff);
47839 function editOn() {
47840 layer.style('display', 'block');
47844 function editOff() {
47845 layer.selectAll('.viewfield-group').remove();
47846 layer.style('display', 'none');
47850 function click(d) {
47851 var mapillary = getMapillary();
47852 if (!mapillary) return;
47854 context.map().centerEase(d.loc);
47857 .selectedImage(d.key, true)
47858 .updateViewer(d.key, context)
47863 function transform(d) {
47864 var t = svgPointTransform(projection)(d);
47865 if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
47870 function update() {
47871 var mapillary = getMapillary(),
47872 data = (mapillary ? mapillary.images(projection) : []),
47873 imageKey = mapillary ? mapillary.selectedImage() : null;
47875 var markers = layer.selectAll('.viewfield-group')
47876 .data(data, function(d) { return d.key; });
47881 var enter = markers.enter()
47883 .attr('class', 'viewfield-group')
47884 .classed('selected', function(d) { return d.key === imageKey; })
47885 .on('click', click);
47889 .attr('transform', transform);
47892 var viewfields = markers.selectAll('.viewfield')
47893 .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
47900 .attr('class', 'viewfield')
47901 .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
47902 .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');
47904 markers.selectAll('circle')
47914 function drawImages(selection$$1) {
47915 var enabled = svgMapillaryImages.enabled,
47916 mapillary = getMapillary();
47918 layer = selection$$1.selectAll('.layer-mapillary-images')
47919 .data(mapillary ? [0] : []);
47924 layer = layer.enter()
47926 .attr('class', 'layer-mapillary-images')
47927 .style('display', enabled ? 'block' : 'none')
47931 if (mapillary && ~~context.map().zoom() >= minZoom) {
47934 mapillary.loadImages(projection);
47942 drawImages.enabled = function(_) {
47943 if (!arguments.length) return svgMapillaryImages.enabled;
47944 svgMapillaryImages.enabled = _;
47945 if (svgMapillaryImages.enabled) {
47950 dispatch$$1.call('change');
47955 drawImages.supported = function() {
47956 return !!getMapillary();
47964 function svgMapillarySigns(projection, context, dispatch$$1) {
47965 var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47967 layer = select(null),
47972 if (svgMapillarySigns.initialized) return; // run once
47973 svgMapillarySigns.enabled = false;
47974 svgMapillarySigns.initialized = true;
47978 function getMapillary() {
47979 if (services.mapillary && !_mapillary) {
47980 _mapillary = services.mapillary;
47981 _mapillary.event.on('loadedSigns', throttledRedraw);
47982 } else if (!services.mapillary && _mapillary) {
47989 function showLayer() {
47994 function hideLayer() {
47995 throttledRedraw.cancel();
48000 function editOn() {
48001 layer.style('display', 'block');
48005 function editOff() {
48006 layer.selectAll('.icon-sign').remove();
48007 layer.style('display', 'none');
48011 function click(d) {
48012 var mapillary = getMapillary();
48013 if (!mapillary) return;
48015 context.map().centerEase(d.loc);
48018 .selectedImage(d.key, true)
48019 .updateViewer(d.key, context)
48024 function update() {
48025 var mapillary = getMapillary(),
48026 data = (mapillary ? mapillary.signs(projection) : []),
48027 imageKey = mapillary ? mapillary.selectedImage() : null;
48029 var signs = layer.selectAll('.icon-sign')
48030 .data(data, function(d) { return d.key; });
48035 var enter = signs.enter()
48036 .append('foreignObject')
48037 .attr('class', 'icon-sign')
48038 .attr('width', '32px') // for Firefox
48039 .attr('height', '32px') // for Firefox
48040 .classed('selected', function(d) { return d.key === imageKey; })
48041 .on('click', click);
48044 .append('xhtml:body')
48045 .attr('class', 'icon-sign-body')
48046 .html(mapillary.signHTML);
48050 .attr('x', function(d) { return projection(d.loc)[0] - 16; }) // offset by -16px to
48051 .attr('y', function(d) { return projection(d.loc)[1] - 16; }); // center signs on loc
48055 function drawSigns(selection$$1) {
48056 var enabled = svgMapillarySigns.enabled,
48057 mapillary = getMapillary();
48059 layer = selection$$1.selectAll('.layer-mapillary-signs')
48060 .data(mapillary ? [0] : []);
48065 layer = layer.enter()
48067 .attr('class', 'layer-mapillary-signs')
48068 .style('display', enabled ? 'block' : 'none')
48072 if (mapillary && ~~context.map().zoom() >= minZoom) {
48075 mapillary.loadSigns(context, projection);
48083 drawSigns.enabled = function(_) {
48084 if (!arguments.length) return svgMapillarySigns.enabled;
48085 svgMapillarySigns.enabled = _;
48086 if (svgMapillarySigns.enabled) {
48091 dispatch$$1.call('change');
48096 drawSigns.supported = function() {
48097 var mapillary = getMapillary();
48098 return (mapillary && mapillary.signsSupported());
48106 function svgOsm() {
48107 return function drawOsm(selection) {
48108 var layers = selection.selectAll('.layer-osm')
48109 .data(['areas', 'lines', 'hit', 'halo', 'label']);
48113 .attr('class', function(d) { return 'layer-osm layer-' + d; });
48117 function svgLayers(projection, context) {
48118 var dispatch$$1 = dispatch('change'),
48119 svg = select(null),
48121 { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) },
48122 { id: 'gpx', layer: svgGpx(projection, context, dispatch$$1) },
48123 { id: 'mapillary-images', layer: svgMapillaryImages(projection, context, dispatch$$1) },
48124 { id: 'mapillary-signs', layer: svgMapillarySigns(projection, context, dispatch$$1) },
48125 { id: 'debug', layer: svgDebug(projection, context, dispatch$$1) }
48129 function drawLayers(selection$$1) {
48130 svg = selection$$1.selectAll('.surface')
48135 .attr('class', 'surface')
48138 var defs = svg.selectAll('.surface-defs')
48143 .attr('class', 'surface-defs');
48145 var groups = svg.selectAll('.data-layer')
48153 .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
48155 .each(function(d) { select(this).call(d.layer); });
48159 drawLayers.all = function() {
48164 drawLayers.layer = function(id) {
48165 var obj = lodash.find(layers, function(o) {return o.id === id;});
48166 return obj && obj.layer;
48170 drawLayers.only = function(what) {
48171 var arr = [].concat(what);
48172 drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
48177 drawLayers.remove = function(what) {
48178 var arr = [].concat(what);
48179 arr.forEach(function(id) {
48180 layers = lodash.reject(layers, function(o) {return o.id === id;});
48182 dispatch$$1.call('change');
48187 drawLayers.add = function(what) {
48188 var arr = [].concat(what);
48189 arr.forEach(function(obj) {
48190 if ('id' in obj && 'layer' in obj) {
48194 dispatch$$1.call('change');
48199 drawLayers.dimensions = function(_) {
48200 if (!arguments.length) return utilGetDimensions(svg);
48201 utilSetDimensions(svg, _);
48206 return utilRebind(drawLayers, dispatch$$1, 'on');
48209 function svgLines$$1(projection, context) {
48210 var detected = utilDetect();
48212 var highway_stack = {
48228 function drawLines(selection$$1, graph, entities, filter) {
48231 function waystack(a, b) {
48232 var selected = context.selectedIDs(),
48233 scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0,
48234 scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0;
48236 if (a.tags.highway) { scoreA -= highway_stack[a.tags.highway]; }
48237 if (b.tags.highway) { scoreB -= highway_stack[b.tags.highway]; }
48238 return scoreA - scoreB;
48242 function drawLineGroup(selection$$1, klass, isSelected) {
48243 var lines = selection$$1
48246 .data(getPathData(isSelected), osmEntity$$1.key);
48251 // Optimization: call simple TagClasses only on enter selection. This
48252 // works because osmEntity.key is defined to include the entity v attribute.
48255 .attr('class', function(d) {
48256 return 'way line ' + klass + ' ' + d.id + (isSelected ? ' selected' : '') +
48257 (oldMultiPolygonOuters[d.id] ? ' old-multipolygon' : '');
48259 .call(svgTagClasses())
48262 .attr('d', getPath)
48263 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
48265 return selection$$1;
48269 function getPathData(isSelected) {
48270 return function() {
48271 var layer = this.parentNode.__data__;
48272 var data = pathdata[layer] || [];
48273 return data.filter(function(d) {
48275 return context.selectedIDs().indexOf(d.id) !== -1;
48277 return context.selectedIDs().indexOf(d.id) === -1;
48283 var getPath = svgPath(projection, graph),
48287 oldMultiPolygonOuters = {};
48289 for (var i = 0; i < entities.length; i++) {
48290 var entity = entities[i],
48291 outer = osmSimpleMultipolygonOuterMember(entity, graph);
48293 ways.push(entity.mergeTags(outer.tags));
48294 oldMultiPolygonOuters[outer.id] = true;
48295 } else if (entity.geometry(graph) === 'line') {
48300 ways = ways.filter(getPath);
48301 pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
48303 lodash.forOwn(pathdata, function(v, k) {
48304 onewaydata[k] = lodash(v)
48305 .filter(function(d) { return d.isOneWay(); })
48306 .map(svgOneWaySegments(projection, graph, 35))
48312 var layer = selection$$1.selectAll('.layer-lines');
48314 var layergroup = layer
48315 .selectAll('g.layergroup')
48316 .data(sequence(-10, 11));
48318 layergroup = layergroup.enter()
48320 .attr('class', function(d) { return 'layergroup layer' + String(d); })
48321 .merge(layergroup);
48324 .selectAll('g.linegroup')
48325 .data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted'])
48328 .attr('class', function(d) { return 'linegroup line-' + d; });
48331 layergroup.selectAll('g.line-shadow')
48332 .call(drawLineGroup, 'shadow', false);
48333 layergroup.selectAll('g.line-casing')
48334 .call(drawLineGroup, 'casing', false);
48335 layergroup.selectAll('g.line-stroke')
48336 .call(drawLineGroup, 'stroke', false);
48338 layergroup.selectAll('g.line-shadow-highlighted')
48339 .call(drawLineGroup, 'shadow', true);
48340 layergroup.selectAll('g.line-casing-highlighted')
48341 .call(drawLineGroup, 'casing', true);
48342 layergroup.selectAll('g.line-stroke-highlighted')
48343 .call(drawLineGroup, 'stroke', true);
48346 var onewaygroup = layergroup
48347 .selectAll('g.onewaygroup')
48350 onewaygroup = onewaygroup.enter()
48352 .attr('class', 'onewaygroup')
48353 .merge(onewaygroup);
48355 var oneways = onewaygroup
48359 function() { return onewaydata[this.parentNode.__data__] || []; },
48360 function(d) { return [d.id, d.index]; }
48366 oneways = oneways.enter()
48368 .attr('class', 'oneway')
48369 .attr('marker-mid', 'url(#oneway-marker)')
48371 .attr('d', function(d) { return d.d; });
48374 oneways.each(function() { this.parentNode.insertBefore(this, this); });
48382 function svgMidpoints$$1(projection, context) {
48384 return function drawMidpoints(selection, graph, entities, filter, extent) {
48385 var layer = selection.selectAll('.layer-hit');
48387 var mode = context.mode();
48388 if (mode && mode.id !== 'select') {
48389 layer.selectAll('g.midpoint').remove();
48393 var poly = extent.polygon(),
48396 for (var i = 0; i < entities.length; i++) {
48397 var entity = entities[i];
48399 if (entity.type !== 'way')
48401 if (!filter(entity))
48403 if (context.selectedIDs().indexOf(entity.id) < 0)
48406 var nodes = graph.childNodes(entity);
48407 for (var j = 0; j < nodes.length - 1; j++) {
48411 id = [a.id, b.id].sort().join('-');
48413 if (midpoints[id]) {
48414 midpoints[id].parents.push(entity);
48416 if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
48417 var point = geoInterp(a.loc, b.loc, 0.5),
48420 if (extent.intersects(point)) {
48423 for (var k = 0; k < 4; k++) {
48424 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
48426 geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
48427 geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
48440 edge: [a.id, b.id],
48450 function midpointFilter(d) {
48451 if (midpoints[d.id])
48454 for (var i = 0; i < d.parents.length; i++) {
48455 if (filter(d.parents[i])) {
48465 .selectAll('g.midpoint')
48466 .filter(midpointFilter)
48467 .data(lodash.values(midpoints), function(d) { return d.id; });
48472 var enter = groups.enter()
48473 .insert('g', ':first-child')
48474 .attr('class', 'midpoint');
48476 enter.append('polygon')
48477 .attr('points', '-6,8 10,0 -6,-8')
48478 .attr('class', 'shadow');
48480 enter.append('polygon')
48481 .attr('points', '-3,4 5,0 -3,-4')
48482 .attr('class', 'fill');
48486 .attr('transform', function(d) {
48487 var translate = svgPointTransform(projection),
48488 a = graph.entity(d.edge[0]),
48489 b = graph.entity(d.edge[1]),
48490 angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
48491 return translate(d) + ' rotate(' + angleVal + ')';
48493 .call(svgTagClasses().tags(
48494 function(d) { return d.parents[0].tags; }
48497 // Propagate data bindings.
48498 groups.select('polygon.shadow');
48499 groups.select('polygon.fill');
48504 function svgOneWaySegments(projection, graph, dt) {
48505 return function(entity) {
48511 clip = identity$5().clipExtent(projection.clipExtent()).stream,
48512 coordinates = graph.childNodes(entity).map(function(n) {
48516 if (entity.tags.oneway === '-1') coordinates.reverse();
48519 type: 'LineString',
48520 coordinates: coordinates
48521 }, projection.stream(clip({
48522 lineStart: function() {},
48523 lineEnd: function() {
48526 point: function(x, y) {
48530 var span = geoEuclideanDistance(a, b) - offset;
48533 var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
48534 dx = dt * Math.cos(angle),
48535 dy = dt * Math.sin(angle),
48536 p = [a[0] + offset * Math.cos(angle),
48537 a[1] + offset * Math.sin(angle)];
48539 var segment = 'M' + a[0] + ',' + a[1] +
48540 'L' + p[0] + ',' + p[1];
48542 for (span -= dt; span >= 0; span -= dt) {
48545 segment += 'L' + p[0] + ',' + p[1];
48548 segment += 'L' + b[0] + ',' + b[1];
48549 segments.push({id: entity.id, index: i, d: segment});
48564 function svgPath(projection, graph, isArea) {
48566 // Explanation of magic numbers:
48567 // "padding" here allows space for strokes to extend beyond the viewport,
48568 // so that the stroke isn't drawn along the edge of the viewport when
48569 // the shape is clipped.
48571 // When drawing lines, pad viewport by 5px.
48572 // When drawing areas, pad viewport by 65px in each direction to allow
48573 // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
48576 padding = isArea ? 65 : 5,
48577 viewport = projection.clipExtent(),
48579 [viewport[0][0] - padding, viewport[0][1] - padding],
48580 [viewport[1][0] + padding, viewport[1][1] + padding]
48582 clip = identity$5().clipExtent(paddedExtent).stream,
48583 project = projection.stream,
48584 path$$1 = index$4()
48585 .projection({stream: function(output) { return project(clip(output)); }});
48587 return function(entity) {
48588 if (entity.id in cache) {
48589 return cache[entity.id];
48591 return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
48596 function svgPoints$$1(projection, context) {
48598 function markerPath(selection, klass) {
48600 .attr('class', klass)
48601 .attr('transform', 'translate(-8, -23)')
48602 .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');
48605 function sortY(a, b) {
48606 return b.loc[1] - a.loc[1];
48610 return function drawPoints(selection, graph, entities, filter) {
48611 var wireframe = context.surface().classed('fill-wireframe'),
48612 points = wireframe ? [] : lodash.filter(entities, function(e) {
48613 return e.geometry(graph) === 'point';
48616 points.sort(sortY);
48618 var layer = selection.selectAll('.layer-hit');
48620 var groups = layer.selectAll('g.point')
48622 .data(points, osmEntity$$1.key);
48627 var enter = groups.enter()
48629 .attr('class', function(d) { return 'node point ' + d.id; })
48632 enter.append('path')
48633 .call(markerPath, 'shadow');
48635 enter.append('ellipse')
48640 .attr('class', 'stroke');
48642 enter.append('path')
48643 .call(markerPath, 'stroke');
48645 enter.append('use')
48646 .attr('transform', 'translate(-5, -19)')
48647 .attr('class', 'icon')
48648 .attr('width', '11px')
48649 .attr('height', '11px');
48653 .attr('transform', svgPointTransform(projection))
48654 .call(svgTagClasses());
48656 // Selecting the following implicitly
48657 // sets the data (point entity) on the element
48658 groups.select('.shadow');
48659 groups.select('.stroke');
48660 groups.select('.icon')
48661 .attr('xlink:href', function(entity) {
48662 var preset = context.presets().match(entity, graph),
48663 picon = preset && preset.icon;
48668 var isMaki = dataFeatureIcons.indexOf(picon) !== -1;
48669 return '#' + picon + (isMaki ? '-11' : '');
48675 function svgRelationMemberTags(graph) {
48676 return function(entity) {
48677 var tags = entity.tags;
48678 graph.parentRelations(entity).forEach(function(relation) {
48679 var type = relation.tags.type;
48680 if (type === 'multipolygon' || type === 'boundary') {
48681 tags = lodash.extend({}, relation.tags, tags);
48688 function svgTagClasses() {
48690 'building', 'highway', 'railway', 'waterway', 'aeroway',
48691 'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
48692 'leisure', 'military', 'place'
48695 'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
48696 'razed', 'demolished', 'obliterated'
48699 'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
48700 'surface', 'tracktype', 'crossing'
48702 tagClassRe = /^tag-/,
48703 tags = function(entity) { return entity.tags; };
48706 var tagClasses = function(selection$$1) {
48707 selection$$1.each(function tagClassesEach(entity) {
48708 var value = this.className,
48709 classes, primary, status;
48711 if (value.baseVal !== undefined) value = value.baseVal;
48713 classes = value.trim().split(/\s+/).filter(function(name) {
48714 return name.length && !tagClassRe.test(name);
48717 var t = tags(entity), i, k, v;
48719 // pick at most one primary classification tag..
48720 for (i = 0; i < primaries.length; i++) {
48723 if (!v || v === 'no') continue;
48726 if (statuses.indexOf(v) !== -1) { // e.g. `railway=abandoned`
48728 classes += ' tag-' + k;
48730 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48736 // add at most one status tag, only if relates to primary tag..
48738 for (i = 0; i < statuses.length; i++) {
48741 if (!v || v === 'no') continue;
48743 if (v === 'yes') { // e.g. `railway=rail + abandoned=yes`
48746 else if (primary && primary === v) { // e.g. `railway=rail + abandoned=railway`
48748 } else if (!primary && primaries.indexOf(v) !== -1) { // e.g. `abandoned=railway`
48751 classes += ' tag-' + v;
48752 } // else ignore e.g. `highway=path + abandoned=railway`
48759 classes += ' tag-status tag-status-' + status;
48762 // add any secondary (structure) tags
48763 for (i = 0; i < secondaries.length; i++) {
48764 k = secondaries[i];
48766 if (!v || v === 'no') continue;
48767 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48770 // For highways, look for surface tagging..
48771 if (primary === 'highway') {
48772 var paved = (t.highway !== 'track');
48775 if (k in osmPavedTags) {
48776 paved = !!osmPavedTags[k][v];
48781 classes += ' tag-unpaved';
48785 classes = classes.trim();
48787 if (classes !== value) {
48788 select(this).attr('class', classes);
48794 tagClasses.tags = function(_) {
48795 if (!arguments.length) return tags;
48803 function svgTurns(projection) {
48805 return function drawTurns(selection, graph, turns) {
48807 function key(turn) {
48808 return [turn.from.node + turn.via.node + turn.to.node].join('-');
48811 function icon(turn) {
48812 var u = turn.u ? '-u' : '';
48813 if (!turn.restriction)
48814 return '#turn-yes' + u;
48815 var restriction = graph.entity(turn.restriction).tags.restriction;
48817 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
48820 var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
48827 var enter = groups.enter()
48829 .attr('class', 'turn');
48832 .filter(function (turn) { return !turn.u; });
48834 nEnter.append('rect')
48835 .attr('transform', 'translate(-22, -12)')
48836 .attr('width', '44')
48837 .attr('height', '24');
48839 nEnter.append('use')
48840 .attr('transform', 'translate(-22, -12)')
48841 .attr('width', '44')
48842 .attr('height', '24');
48846 .filter(function (turn) { return turn.u; });
48848 uEnter.append('circle')
48851 uEnter.append('use')
48852 .attr('transform', 'translate(-16, -16)')
48853 .attr('width', '32')
48854 .attr('height', '32');
48861 .attr('transform', function (turn) {
48862 var v = graph.entity(turn.via.node),
48863 t = graph.entity(turn.to.node),
48864 a = geoAngle(v, t, projection),
48865 p = projection(v.loc),
48866 r = turn.u ? 0 : 60;
48868 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
48869 'rotate(' + a * 180 / Math.PI + ')';
48872 groups.select('use')
48873 .attr('xlink:href', icon);
48875 groups.select('rect');
48876 groups.select('circle');
48882 function svgVertices$$1(projection, context) {
48884 // z16-, z17, z18+, tagged
48885 shadow: [6, 7.5, 7.5, 11.5],
48886 stroke: [2.5, 3.5, 3.5, 7],
48887 fill: [1, 1.5, 1.5, 1.5]
48893 function siblingAndChildVertices(ids, graph, extent$$1) {
48896 function addChildVertices(entity) {
48897 if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
48899 if (entity.type === 'way') {
48900 for (i = 0; i < entity.nodes.length; i++) {
48901 addChildVertices(graph.entity(entity.nodes[i]));
48903 } else if (entity.type === 'relation') {
48904 for (i = 0; i < entity.members.length; i++) {
48905 var member = context.hasEntity(entity.members[i].id);
48907 addChildVertices(member);
48910 } else if (entity.intersects(extent$$1, graph)) {
48911 vertices[entity.id] = entity;
48916 ids.forEach(function(id) {
48917 var entity = context.hasEntity(id);
48918 if (entity && entity.type === 'node') {
48919 vertices[entity.id] = entity;
48920 context.graph().parentWays(entity).forEach(function(entity) {
48921 addChildVertices(entity);
48923 } else if (entity) {
48924 addChildVertices(entity);
48932 function draw(selection$$1, vertices, klass, graph, zoom$$1, siblings) {
48934 function icon(entity) {
48935 if (entity.id in icons) return icons[entity.id];
48937 entity.hasInterestingTags() &&
48938 context.presets().match(entity, graph).icon;
48939 return icons[entity.id];
48942 function setClass(klass) {
48943 return function(entity) {
48944 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
48948 function setAttributes(selection$$1) {
48949 ['shadow','stroke','fill'].forEach(function(klass) {
48950 var rads = radiuses[klass];
48951 selection$$1.selectAll('.' + klass)
48952 .each(function(entity) {
48953 var i = z && icon(entity),
48955 r = rads[i ? 3 : z];
48957 // slightly increase the size of unconnected endpoints #3775
48958 if (entity.isEndpoint(graph) && !entity.isConnected(graph)) {
48962 this.setAttribute('cx', c);
48963 this.setAttribute('cy', -c);
48964 this.setAttribute('r', r);
48965 if (i && klass === 'fill') {
48966 this.setAttribute('visibility', 'hidden');
48968 this.removeAttribute('visibility');
48973 selection$$1.selectAll('use')
48976 this.removeAttribute('visibility');
48978 this.setAttribute('visibility', 'hidden');
48984 siblings = siblings || {};
48987 z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
48989 var groups = selection$$1
48990 .data(vertices, osmEntity$$1.key);
48995 var enter = groups.enter()
48997 .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
48999 enter.append('circle')
49000 .each(setClass('shadow'));
49002 enter.append('circle')
49003 .each(setClass('stroke'));
49005 // Vertices with icons get a `use`.
49006 enter.filter(function(d) { return icon(d); })
49008 .attr('transform', 'translate(-5, -6)')
49009 .attr('xlink:href', function(d) {
49010 var picon = icon(d),
49011 isMaki = dataFeatureIcons.indexOf(picon) !== -1;
49012 return '#' + picon + (isMaki ? '-11' : '');
49014 .attr('width', '11px')
49015 .attr('height', '11px')
49016 .each(setClass('icon'));
49018 // Vertices with tags get a fill.
49019 enter.filter(function(d) { return d.hasInterestingTags(); })
49021 .each(setClass('fill'));
49025 .attr('transform', svgPointTransform(projection))
49026 .classed('sibling', function(entity) { return entity.id in siblings; })
49027 .classed('shared', function(entity) { return graph.isShared(entity); })
49028 .classed('endpoint', function(entity) { return entity.isEndpoint(graph); })
49029 .call(setAttributes);
49033 function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
49034 var siblings = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
49035 wireframe = context.surface().classed('fill-wireframe'),
49038 for (var i = 0; i < entities.length; i++) {
49039 var entity = entities[i],
49040 geometry = entity.geometry(graph);
49042 if (wireframe && geometry === 'point') {
49043 vertices.push(entity);
49047 if (geometry !== 'vertex')
49050 if (entity.id in siblings ||
49051 entity.hasInterestingTags() ||
49052 entity.isEndpoint(graph) ||
49053 entity.isConnected(graph)) {
49054 vertices.push(entity);
49058 var layer = selection$$1.selectAll('.layer-hit');
49059 layer.selectAll('g.vertex.vertex-persistent')
49061 .call(draw, vertices, 'vertex-persistent', graph, zoom$$1, siblings);
49063 drawHover(selection$$1, graph, extent$$1, zoom$$1);
49067 function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
49068 var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
49069 var layer = selection$$1.selectAll('.layer-hit');
49071 layer.selectAll('g.vertex.vertex-hover')
49072 .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
49076 drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
49077 if (target === hover) return;
49079 drawHover(selection$$1, graph, extent$$1, zoom$$1);
49082 return drawVertices;
49085 function behaviorEdit(context) {
49089 .minzoom(context.minEditableZoom());
49093 edit.off = function() {
49103 The hover behavior adds the `.hover` class on mouseover to all elements to which
49104 the identical datum is bound, and removes it on mouseout.
49106 The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
49107 representation may consist of several elements scattered throughout the DOM hierarchy.
49108 Only one of these elements can have the :hover pseudo-class, but all of them will
49109 have the .hover class.
49111 function behaviorHover(context) {
49112 var dispatch$$1 = dispatch('hover'),
49113 _selection = select(null),
49120 function keydown() {
49121 if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
49122 _selection.selectAll('.hover')
49123 .classed('hover-suppressed', true)
49124 .classed('hover', false);
49127 .classed('hover-disabled', true);
49129 dispatch$$1.call('hover', this, null);
49135 if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
49136 _selection.selectAll('.hover-suppressed')
49137 .classed('hover-suppressed', false)
49138 .classed('hover', true);
49141 .classed('hover-disabled', false);
49143 dispatch$$1.call('hover', this, target ? target.id : null);
49148 var hover = function(selection$$1) {
49149 _selection = selection$$1;
49153 .on('mouseover.hover', mouseover)
49154 .on('mouseout.hover', mouseout)
49155 .on('mousedown.hover', mousedown);
49158 .on('keydown.hover', keydown)
49159 .on('keyup.hover', keyup);
49162 function mouseover() {
49163 if (buttonDown) return;
49164 var target = event.target;
49165 enter(target ? target.__data__ : null);
49169 function mouseout() {
49170 if (buttonDown) return;
49171 var target = event.relatedTarget;
49172 enter(target ? target.__data__ : null);
49176 function mousedown() {
49179 .on('mouseup.hover', mouseup, true);
49183 function mouseup() {
49184 buttonDown = false;
49186 .on('mouseup.hover', null, true);
49190 function enter(d) {
49191 if (d === target) return;
49194 _selection.selectAll('.hover')
49195 .classed('hover', false);
49196 _selection.selectAll('.hover-suppressed')
49197 .classed('hover-suppressed', false);
49199 if (target instanceof osmEntity$$1 && target.id !== newId) {
49201 // If drawing a way, don't hover on a node that was just placed. #3974
49202 var mode = context.mode() && context.mode().id;
49203 if ((mode === 'draw-line' || mode === 'draw-area') && !newId && target.type === 'node') {
49208 var selector$$1 = '.' + target.id;
49210 if (target.type === 'relation') {
49211 target.members.forEach(function(member) {
49212 selector$$1 += ', .' + member.id;
49216 var suppressed = altDisables && event && event.altKey;
49218 _selection.selectAll(selector$$1)
49219 .classed(suppressed ? 'hover-suppressed' : 'hover', true);
49221 dispatch$$1.call('hover', this, !suppressed && target.id);
49224 dispatch$$1.call('hover', this, null);
49231 hover.off = function(selection$$1) {
49232 selection$$1.selectAll('.hover')
49233 .classed('hover', false);
49234 selection$$1.selectAll('.hover-suppressed')
49235 .classed('hover-suppressed', false);
49237 .classed('hover-disabled', false);
49241 .on('mouseover.hover', null)
49242 .on('mouseout.hover', null)
49243 .on('mousedown.hover', null);
49246 .on('keydown.hover', null)
49247 .on('keyup.hover', null);
49251 hover.altDisables = function(_) {
49252 if (!arguments.length) return altDisables;
49258 return utilRebind(hover, dispatch$$1, 'on');
49261 function behaviorTail() {
49265 tooltipSize = [0, 0],
49266 selectionSize = [0, 0];
49269 function tail(selection$$1) {
49270 if (!text$$1) return;
49273 .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
49275 container = select(document.body)
49277 .style('display', 'none')
49278 .attr('class', 'tail tooltip-inner');
49280 container.append('div')
49284 .on('mousemove.tail', mousemove)
49285 .on('mouseenter.tail', mouseenter)
49286 .on('mouseleave.tail', mouseleave);
49289 .on('mousemove.tail', mousemove);
49291 tooltipSize = utilGetDimensions(container);
49292 selectionSize = utilGetDimensions(selection$$1);
49296 container.style('display', 'block');
49297 tooltipSize = utilGetDimensions(container);
49301 function mousemove() {
49302 if (container.style('display') === 'none') show();
49303 var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
49304 -tooltipSize[0] - xmargin : xmargin;
49305 container.classed('left', xoffset > 0);
49306 utilSetTransform(container, event.clientX + xoffset, event.clientY);
49310 function mouseleave() {
49311 if (event.relatedTarget !== container.node()) {
49312 container.style('display', 'none');
49317 function mouseenter() {
49318 if (event.relatedTarget !== container.node()) {
49325 tail.off = function(selection$$1) {
49326 if (!text$$1) return;
49329 .on('mousemove.tail', null)
49333 .on('mousemove.tail', null)
49334 .on('mouseenter.tail', null)
49335 .on('mouseleave.tail', null);
49338 .on('resize.tail', null);
49342 tail.text = function(_) {
49343 if (!arguments.length) return text$$1;
49352 var usedTails = {};
49353 var disableSpace = false;
49354 var lastSpace = null;
49357 function behaviorDraw(context) {
49358 var dispatch$$1 = dispatch('move', 'click', 'clickWay',
49359 'clickNode', 'undo', 'cancel', 'finish'),
49360 keybinding = d3keybinding('draw'),
49361 hover = behaviorHover(context)
49363 .on('hover', context.ui().sidebar.hover),
49364 tail = behaviorTail(),
49365 edit = behaviorEdit(context),
49366 closeTolerance = 4,
49368 mouseLeave = false,
49373 if (event.altKey) return {};
49375 if (event.type === 'keydown') {
49376 return (lastMouse && lastMouse.target.__data__) || {};
49378 return event.target.__data__ || {};
49383 function mousedown() {
49386 var p = context.container().node();
49387 return touchId !== null ? touches(p).filter(function(p) {
49388 return p.identifier === touchId;
49392 var element = select(this),
49393 touchId = event.touches ? event.changedTouches[0].identifier : null,
49397 element.on('mousemove.draw', null);
49399 select(window).on('mouseup.draw', function() {
49400 var t2 = +new Date(),
49402 dist = geoEuclideanDistance(p1, p2);
49404 element.on('mousemove.draw', mousemove);
49405 select(window).on('mouseup.draw', null);
49407 if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
49408 // Prevent a quick second click
49409 select(window).on('click.draw-block', function() {
49410 event.stopPropagation();
49413 context.map().dblclickEnable(false);
49415 window.setTimeout(function() {
49416 context.map().dblclickEnable(true);
49417 select(window).on('click.draw-block', null);
49426 function mousemove() {
49428 dispatch$$1.call('move', this, datum());
49432 function mouseenter() {
49433 mouseLeave = false;
49437 function mouseleave() {
49444 if (d.type === 'way') {
49445 var dims = context.map().dimensions(),
49446 mouse$$1 = context.mouse(),
49448 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
49449 mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
49452 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
49453 edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
49454 dispatch$$1.call('clickWay', this, choice.loc, edge);
49456 dispatch$$1.call('click', this, context.map().mouseCoordinates());
49459 } else if (d.type === 'node') {
49460 dispatch$$1.call('clickNode', this, d);
49463 dispatch$$1.call('click', this, context.map().mouseCoordinates());
49469 event.preventDefault();
49470 event.stopPropagation();
49472 var currSpace = context.mouse();
49473 if (disableSpace && lastSpace) {
49474 var dist = geoEuclideanDistance(lastSpace, currSpace);
49475 if (dist > tolerance) {
49476 disableSpace = false;
49480 if (disableSpace || mouseLeave || !lastMouse) return;
49482 // user must move mouse or release space bar to allow another click
49483 lastSpace = currSpace;
49484 disableSpace = true;
49486 select(window).on('keyup.space-block', function() {
49487 event.preventDefault();
49488 event.stopPropagation();
49489 disableSpace = false;
49490 select(window).on('keyup.space-block', null);
49497 function backspace() {
49498 event.preventDefault();
49499 dispatch$$1.call('undo');
49504 event.preventDefault();
49505 dispatch$$1.call('cancel');
49510 event.preventDefault();
49511 dispatch$$1.call('finish');
49515 function draw(selection$$1) {
49516 context.install(hover);
49517 context.install(edit);
49519 if (!context.inIntro() && !usedTails[tail.text()]) {
49520 context.install(tail);
49524 .on('⌫', backspace)
49528 .on('space', space)
49529 .on('⌥space', space);
49532 .on('mouseenter.draw', mouseenter)
49533 .on('mouseleave.draw', mouseleave)
49534 .on('mousedown.draw', mousedown)
49535 .on('mousemove.draw', mousemove);
49544 draw.off = function(selection$$1) {
49545 context.ui().sidebar.hover.cancel();
49546 context.uninstall(hover);
49547 context.uninstall(edit);
49549 if (!context.inIntro() && !usedTails[tail.text()]) {
49550 context.uninstall(tail);
49551 usedTails[tail.text()] = true;
49555 .on('mouseenter.draw', null)
49556 .on('mouseleave.draw', null)
49557 .on('mousedown.draw', null)
49558 .on('mousemove.draw', null);
49561 .on('mouseup.draw', null);
49562 // note: keyup.space-block, click.draw-block should remain
49565 .call(keybinding.off);
49569 draw.tail = function(_) {
49575 return utilRebind(draw, dispatch$$1, 'on');
49578 function behaviorAddWay(context) {
49579 var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
49580 draw = behaviorDraw(context);
49582 var addWay = function(surface) {
49583 draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
49584 .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
49585 .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
49586 .on('cancel', addWay.cancel)
49587 .on('finish', addWay.cancel);
49590 .dblclickEnable(false);
49592 surface.call(draw);
49596 addWay.off = function(surface) {
49597 surface.call(draw.off);
49601 addWay.cancel = function() {
49602 window.setTimeout(function() {
49603 context.map().dblclickEnable(true);
49606 context.enter(modeBrowse(context));
49610 addWay.tail = function(text$$1) {
49611 draw.tail(text$$1);
49616 return utilRebind(addWay, dispatch$$1, 'on');
49619 function behaviorBreathe() {
49620 var duration = 800,
49622 selector$$1 = '.selected.shadow, .selected .shadow',
49623 selected = select(null),
49630 function ratchetyInterpolator(a, b, steps, units) {
49633 var sample = quantize$1()
49635 .range(quantize(reinterpolate(a, b), steps));
49637 return function(t) {
49638 return String(sample(t)) + (units || '');
49643 function reset(selection$$1) {
49645 .style('stroke-opacity', null)
49646 .style('stroke-width', null)
49647 .style('fill-opacity', null)
49652 function setAnimationParams(transition$$1, fromTo) {
49653 var toFrom = (fromTo === 'from' ? 'to' : 'from');
49656 .styleTween('stroke-opacity', function(d) {
49657 return ratchetyInterpolator(
49658 params[d.id][toFrom].opacity,
49659 params[d.id][fromTo].opacity,
49663 .styleTween('stroke-width', function(d) {
49664 return ratchetyInterpolator(
49665 params[d.id][toFrom].width,
49666 params[d.id][fromTo].width,
49671 .styleTween('fill-opacity', function(d) {
49672 return ratchetyInterpolator(
49673 params[d.id][toFrom].opacity,
49674 params[d.id][fromTo].opacity,
49678 .styleTween('r', function(d) {
49679 return ratchetyInterpolator(
49680 params[d.id][toFrom].width,
49681 params[d.id][fromTo].width,
49689 function calcAnimationParams(selection$$1) {
49692 .each(function(d) {
49693 var s = select(this),
49694 tag = s.node().tagName,
49695 p = {'from': {}, 'to': {}},
49698 // determine base opacity and width
49699 if (tag === 'circle') {
49700 opacity = parseFloat(s.style('fill-opacity') || 0.5);
49701 width = parseFloat(s.style('r') || 15.5);
49703 opacity = parseFloat(s.style('stroke-opacity') || 0.7);
49704 width = parseFloat(s.style('stroke-width') || 10);
49707 // calculate from/to interpolation params..
49709 p.from.opacity = opacity * 0.6;
49710 p.to.opacity = opacity * 1.25;
49711 p.from.width = width * 0.7;
49712 p.to.width = width * (tag === 'circle' ? 1.5 : 1);
49718 function run(surface, fromTo) {
49719 var toFrom = (fromTo === 'from' ? 'to' : 'from'),
49720 currSelected = surface.selectAll(selector$$1),
49721 currClassed = surface.attr('class');
49723 if (done || currSelected.empty()) {
49724 selected.call(reset);
49728 if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
49729 selected.call(reset);
49730 classed = currClassed;
49731 selected = currSelected.call(calcAnimationParams);
49736 .duration(duration)
49737 .call(setAnimationParams, fromTo)
49738 .on('end', function() {
49739 surface.call(run, toFrom);
49744 var breathe = function(surface) {
49746 timer$$1 = timer(function() {
49747 // wait for elements to actually become selected
49748 if (surface.selectAll(selector$$1).empty()) {
49752 surface.call(run, 'from');
49759 breathe.off = function() {
49773 function behaviorCopy(context) {
49774 var keybinding = d3keybinding('copy');
49777 function groupEntities(ids, graph) {
49778 var entities = ids.map(function (id) { return graph.entity(id); });
49779 return lodash.extend({relation: [], way: [], node: []},
49780 lodash.groupBy(entities, function(entity) { return entity.type; }));
49784 function getDescendants(id, graph, descendants) {
49785 var entity = graph.entity(id),
49788 descendants = descendants || {};
49790 if (entity.type === 'relation') {
49791 children = lodash.map(entity.members, 'id');
49792 } else if (entity.type === 'way') {
49793 children = entity.nodes;
49798 for (i = 0; i < children.length; i++) {
49799 if (!descendants[children[i]]) {
49800 descendants[children[i]] = true;
49801 descendants = getDescendants(children[i], graph, descendants);
49805 return descendants;
49809 function doCopy() {
49810 event.preventDefault();
49812 var graph = context.graph(),
49813 selected = groupEntities(context.selectedIDs(), graph),
49818 for (i = 0; i < selected.relation.length; i++) {
49819 entity = selected.relation[i];
49820 if (!skip[entity.id] && entity.isComplete(graph)) {
49821 canCopy.push(entity.id);
49822 skip = getDescendants(entity.id, graph, skip);
49825 for (i = 0; i < selected.way.length; i++) {
49826 entity = selected.way[i];
49827 if (!skip[entity.id]) {
49828 canCopy.push(entity.id);
49829 skip = getDescendants(entity.id, graph, skip);
49832 for (i = 0; i < selected.node.length; i++) {
49833 entity = selected.node[i];
49834 if (!skip[entity.id]) {
49835 canCopy.push(entity.id);
49839 context.copyIDs(canCopy);
49844 keybinding.on(uiCmd('⌘C'), doCopy);
49845 select(document).call(keybinding);
49850 copy.off = function() {
49851 select(document).call(keybinding.off);
49859 `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
49861 * The `origin` function is expected to return an [x, y] tuple rather than an
49863 * The events are `start`, `move`, and `end`.
49864 (https://github.com/mbostock/d3/issues/563)
49865 * The `start` event is not dispatched until the first cursor movement occurs.
49866 (https://github.com/mbostock/d3/pull/368)
49867 * The `move` event has a `point` and `delta` [x, y] tuple properties rather
49868 than `x`, `y`, `dx`, and `dy` properties.
49869 * The `end` event is not dispatched if no movement occurs.
49870 * An `off` function is available that unbinds the drag's internal event handlers.
49873 function behaviorDrag() {
49874 var event$$1 = dispatch('start', 'move', 'end'),
49878 event_, target, surface;
49881 var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
49882 d3_event_userSelectSuppress = function() {
49883 var selection$$1 = selection(),
49884 select$$1 = selection$$1.style(d3_event_userSelectProperty);
49885 selection$$1.style(d3_event_userSelectProperty, 'none');
49886 return function() {
49887 selection$$1.style(d3_event_userSelectProperty, select$$1);
49892 function d3_eventCancel() {
49893 event.stopPropagation();
49894 event.preventDefault();
49898 function eventOf(thiz, argumentz) {
49899 return function(e1) {
49900 e1.target = drag$$1;
49901 customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
49906 function dragstart() {
49908 event_ = eventOf(target, arguments);
49910 var eventTarget = event.target,
49911 touchId = event.touches ? event.changedTouches[0].identifier : null,
49915 selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
49918 .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
49919 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
49922 offset = origin.apply(target, arguments);
49923 offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
49928 if (touchId === null) {
49929 event.stopPropagation();
49934 var p = surface || target.parentNode;
49935 return touchId !== null ? touches(p).filter(function(p) {
49936 return p.identifier === touchId;
49941 function dragmove() {
49943 dx = p[0] - origin_[0],
49944 dy = p[1] - origin_[1];
49946 if (dx === 0 && dy === 0)
49951 event_({ type: 'start' });
49959 point: [p[0] + offset[0], p[1] + offset[1]],
49965 function dragend() {
49967 event_({ type: 'end' });
49970 if (event.target === eventTarget) {
49972 .on('click.drag', click, true);
49977 .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
49978 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
49987 .on('click.drag', null);
49992 function drag$$1(selection$$1) {
49993 var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
49994 delegate = dragstart;
49997 delegate = function() {
49999 target = event.target;
50000 for (; target && target !== root; target = target.parentNode) {
50001 if (target[matchesSelector](selector$$1) &&
50002 (!filter || filter(target.__data__))) {
50003 return dragstart.call(target, target.__data__);
50010 .on('mousedown.drag' + selector$$1, delegate)
50011 .on('touchstart.drag' + selector$$1, delegate);
50015 drag$$1.off = function(selection$$1) {
50017 .on('mousedown.drag' + selector$$1, null)
50018 .on('touchstart.drag' + selector$$1, null);
50022 drag$$1.selector = function(_) {
50023 if (!arguments.length) return selector$$1;
50029 drag$$1.filter = function(_) {
50030 if (!arguments.length) return origin;
50036 drag$$1.origin = function (_) {
50037 if (!arguments.length) return origin;
50043 drag$$1.cancel = function() {
50045 .on('mousemove.drag', null)
50046 .on('mouseup.drag', null);
50051 drag$$1.target = function() {
50052 if (!arguments.length) return target;
50053 target = arguments[0];
50054 event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
50059 drag$$1.surface = function() {
50060 if (!arguments.length) return surface;
50061 surface = arguments[0];
50066 return utilRebind(drag$$1, event$$1, 'on');
50069 function behaviorDrawWay(context, wayId, index, mode, startGraph) {
50071 var origWay = context.entity(wayId),
50072 isArea = context.geometry(wayId) === 'area',
50074 annotation = t((origWay.isDegenerate() ?
50075 'operations.start.annotation.' :
50076 'operations.continue.annotation.') + context.geometry(wayId)),
50077 draw = behaviorDraw(context),
50084 // initialize the temporary drawing entities
50086 startIndex = typeof index === 'undefined' ? origWay.nodes.length - 1 : 0;
50087 start = osmNode({ id: 'nStart', loc: context.entity(origWay.nodes[startIndex]).loc });
50088 end = osmNode({ id: 'nEnd', loc: context.map().mouseCoordinates() });
50089 segment = osmWay({ id: 'wTemp',
50090 nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
50091 tags: lodash.clone(origWay.tags)
50094 end = osmNode({ loc: context.map().mouseCoordinates() });
50097 // Push an annotated state for undo to return back to.
50098 // We must make sure to remove this edit later.
50099 context.perform(actionNoop(), annotation);
50102 // Add the temporary drawing entities to the graph.
50103 // We must make sure to remove this edit later.
50104 context.perform(AddDrawEntities());
50108 function move(datum) {
50111 if (datum.type === 'node' && datum.id !== end.id) {
50114 } else if (datum.type === 'way') {
50115 var dims = context.map().dimensions(),
50116 mouse = context.mouse(),
50118 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
50119 mouse[1] > pad && mouse[1] < dims[1] - pad;
50122 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
50127 loc = context.map().mouseCoordinates();
50130 context.replace(actionMoveNode(end.id, loc));
50131 end = context.entity(end.id);
50135 function undone() {
50136 // Undo popped the history back to the initial annotated no-op edit.
50137 // Remove initial no-op edit and whatever edit happened immediately before it.
50141 if (context.hasEntity(wayId)) {
50142 context.enter(mode);
50144 context.enter(modeBrowse(context));
50149 function setActiveElements() {
50150 var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
50151 context.surface().selectAll(utilEntitySelector(active))
50152 .classed('active', true);
50156 var drawWay = function(surface) {
50157 draw.on('move', move)
50158 .on('click', drawWay.add)
50159 .on('clickWay', drawWay.addWay)
50160 .on('clickNode', drawWay.addNode)
50161 .on('undo', context.undo)
50162 .on('cancel', drawWay.cancel)
50163 .on('finish', drawWay.finish);
50166 .dblclickEnable(false)
50167 .on('drawn.draw', setActiveElements);
50169 setActiveElements();
50171 surface.call(draw);
50174 .on('undone.draw', undone);
50178 drawWay.off = function(surface) {
50179 // Drawing was interrupted unexpectedly.
50180 // This can happen if the user changes modes,
50181 // clicks geolocate button, a hashchange event occurs, etc.
50183 context.pop(tempEdits);
50184 while (context.graph() !== startGraph) {
50190 .on('drawn.draw', null);
50192 surface.call(draw.off)
50193 .selectAll('.active')
50194 .classed('active', false);
50197 .on('undone.draw', null);
50201 function AddDrawEntities() {
50202 return function(graph) {
50204 // For area drawing, there is no need for a temporary node.
50205 // `end` gets inserted into the way as the penultimate node.
50208 .replace(origWay.addNode(end.id));
50210 // For line drawing, add a temporary start, end, and segment to the graph.
50211 // This allows us to class the new segment as `active`, but still
50212 // connect it back to parts of the way that have already been drawn.
50222 function ReplaceDrawEntities(newNode) {
50223 return function(graph) {
50225 // For area drawing, we didn't create a temporary node.
50226 // `newNode` gets inserted into the _original_ way as the penultimate node.
50228 .replace(origWay.addNode(newNode.id))
50231 // For line drawing, add the `newNode` to the way at specified index,
50232 // and remove the temporary start, end, and segment.
50234 .replace(origWay.addNode(newNode.id, index))
50243 // Accept the current position of the temporary node and continue drawing.
50244 drawWay.add = function(loc) {
50245 // prevent duplicate nodes
50246 var last = context.hasEntity(origWay.nodes[origWay.nodes.length - (isArea ? 2 : 1)]);
50247 if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
50249 context.pop(tempEdits);
50257 var newNode = osmNode({loc: loc});
50259 actionAddEntity(newNode),
50260 ReplaceDrawEntities(newNode),
50266 context.enter(mode);
50270 // Connect the way to an existing way.
50271 drawWay.addWay = function(loc, edge) {
50273 context.pop(tempEdits);
50277 actionAddMidpoint({ loc: loc, edge: edge}, end),
50281 var previousEdge = startIndex ?
50282 [origWay.nodes[startIndex], origWay.nodes[startIndex - 1]] :
50283 [origWay.nodes[0], origWay.nodes[1]];
50285 // Avoid creating duplicate segments
50286 if (geoEdgeEqual(edge, previousEdge))
50289 context.pop(tempEdits);
50291 var newNode = osmNode({ loc: loc });
50293 actionAddMidpoint({ loc: loc, edge: edge}, newNode),
50294 ReplaceDrawEntities(newNode),
50300 context.enter(mode);
50304 // Connect the way to an existing node and continue drawing.
50305 drawWay.addNode = function(node) {
50306 // Avoid creating duplicate segments
50307 if (origWay.areAdjacent(node.id, origWay.nodes[origWay.nodes.length - 1])) return;
50309 // Clicks should not occur on the drawing node, however a space keypress can
50310 // sometimes grab that node's datum (before it gets classed as `active`?) #4016
50311 if (node.id === end.id) {
50312 drawWay.add(node.loc);
50316 context.pop(tempEdits);
50319 ReplaceDrawEntities(node),
50324 context.enter(mode);
50328 // Finish the draw operation, removing the temporary edits.
50329 // If the way has enough nodes to be valid, it's selected.
50330 // Otherwise, delete everything and return to browse mode.
50331 drawWay.finish = function() {
50332 context.pop(tempEdits);
50335 var way = context.hasEntity(wayId);
50336 if (!way || way.isDegenerate()) {
50341 window.setTimeout(function() {
50342 context.map().dblclickEnable(true);
50345 context.enter(modeSelect(context, [wayId]).newFeature(true));
50349 // Cancel the draw operation, delete everything, and return to browse mode.
50350 drawWay.cancel = function() {
50351 context.pop(tempEdits);
50354 while (context.graph() !== startGraph) {
50358 window.setTimeout(function() {
50359 context.map().dblclickEnable(true);
50362 context.enter(modeBrowse(context));
50366 drawWay.tail = function(text) {
50375 function behaviorHash(context) {
50376 var s0 = null, // cached window.location.hash
50377 lat = 90 - 1e-8; // allowable latitude range
50380 var parser = function(map$$1, s) {
50381 var q = utilStringQs(s);
50382 var args = (q.map || '').split('/').map(Number);
50383 if (args.length < 3 || args.some(isNaN)) {
50384 return true; // replace bogus hash
50385 } else if (s !== formatter(map$$1).slice(1)) {
50386 var mode = context.mode();
50387 if (mode && mode.id.match(/^draw/) !== null) {
50388 context.enter(modeBrowse(context));
50390 map$$1.centerZoom([args[2], Math.min(lat, Math.max(-lat, args[1]))], args[0]);
50395 var formatter = function(map$$1) {
50396 var center = map$$1.center(),
50397 zoom$$1 = map$$1.zoom(),
50398 precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
50399 q = lodash.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
50403 var selected = context.selectedIDs().filter(function(id) {
50404 return !context.entity(id).isNew();
50406 if (selected.length) {
50407 newParams.id = selected.join(',');
50410 newParams.map = zoom$$1.toFixed(2) +
50411 '/' + center[1].toFixed(precision) +
50412 '/' + center[0].toFixed(precision);
50414 return '#' + utilQsString(lodash.assign(q, newParams), true);
50418 function update() {
50419 if (context.inIntro()) return;
50420 var s1 = formatter(context.map());
50422 window.location.replace(s0 = s1); // don't recenter the map!
50427 var throttledUpdate = lodash.throttle(update, 500);
50430 function hashchange() {
50431 if (window.location.hash === s0) return; // ignore spurious hashchange events
50432 if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
50433 update(); // replace bogus hash
50440 .on('move.hash', throttledUpdate);
50443 .on('enter.hash', throttledUpdate);
50446 .on('hashchange.hash', hashchange);
50448 if (window.location.hash) {
50449 var q = utilStringQs(window.location.hash.substring(1));
50451 context.zoomToEntity(q.id.split(',')[0], !q.map);
50454 context.storage('comment', q.comment);
50455 context.storage('commentDate', Date.now());
50458 if (q.map) hash.hadHash = true;
50463 hash.off = function() {
50464 throttledUpdate.cancel();
50467 .on('move.hash', null);
50470 .on('enter.hash', null);
50473 .on('hashchange.hash', null);
50475 window.location.hash = '';
50482 function behaviorLasso(context) {
50484 var behavior = function(selection$$1) {
50488 function mousedown() {
50489 var button = 0; // left
50490 if (event.button === button && event.shiftKey === true) {
50494 .on('mousemove.lasso', mousemove)
50495 .on('mouseup.lasso', mouseup);
50497 event.stopPropagation();
50502 function mousemove() {
50504 lasso = uiLasso(context);
50505 context.surface().call(lasso);
50508 lasso.p(context.mouse());
50512 function normalize(a, b) {
50514 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
50515 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
50519 function lassoed() {
50520 if (!lasso) return [];
50522 var graph = context.graph(),
50523 bounds = lasso.extent().map(context.projection.invert),
50524 extent$$1 = geoExtent$$1(normalize(bounds[0], bounds[1]));
50526 return lodash.map(context.intersects(extent$$1).filter(function(entity) {
50527 return entity.type === 'node' &&
50528 geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
50529 !context.features().isHidden(entity, graph, entity.geometry(graph));
50534 function mouseup() {
50536 .on('mousemove.lasso', null)
50537 .on('mouseup.lasso', null);
50539 if (!lasso) return;
50541 var ids = lassoed();
50545 context.enter(modeSelect(context, ids));
50550 .on('mousedown.lasso', mousedown);
50554 behavior.off = function(selection$$1) {
50555 selection$$1.on('mousedown.lasso', null);
50562 /* Creates a keybinding behavior for an operation */
50563 function behaviorOperation() {
50564 var which, keybinding;
50567 function drawIcon(selection$$1) {
50568 var button = selection$$1
50570 .attr('class', 'operation-icon')
50572 .attr('class', 'radial-menu-item radial-menu-item-' + which.id)
50573 .attr('transform', 'translate(10,10)')
50574 .classed('disabled', which.disabled());
50582 .attr('transform', 'translate(-7,-7)')
50583 .attr('width', '14')
50584 .attr('height', '14')
50585 .attr('xlink:href', '#operation-' + which.id);
50587 return selection$$1;
50591 var behavior = function () {
50592 if (which && which.available()) {
50593 keybinding = d3keybinding('behavior.key.' + which.id);
50594 keybinding.on(which.keys, function() {
50595 event.preventDefault();
50596 var disabled = which.disabled();
50603 .attr('class', 'operation-tip')
50604 .text(which.tooltip);
50611 .attr('class', 'operation-tip')
50612 .text(which.annotation() || which.title);
50617 select(document).call(keybinding);
50623 behavior.off = function() {
50625 select(document).call(keybinding.off);
50630 behavior.which = function (_) {
50631 if (!arguments.length) return which;
50640 function behaviorPaste(context) {
50641 var keybinding = d3keybinding('paste');
50643 function omitTag(v, k) {
50651 k === 'description' ||
50652 k.indexOf('name') !== -1 ||
50653 k.indexOf('wiki') === 0 ||
50654 k.indexOf('addr:') === 0 ||
50655 k.indexOf('contact:') === 0
50660 function doPaste() {
50661 event.preventDefault();
50663 var baseGraph = context.graph(),
50664 mouse$$1 = context.mouse(),
50665 projection = context.projection,
50666 viewport = geoExtent$$1(projection.clipExtent()).polygon();
50668 if (!geoPointInPolygon(mouse$$1, viewport)) return;
50670 var extent$$1 = geoExtent$$1(),
50671 oldIDs = context.copyIDs(),
50672 oldGraph = context.copyGraph(),
50675 if (!oldIDs.length) return;
50677 var action = actionCopyEntities(oldIDs, oldGraph);
50678 context.perform(action);
50680 var copies = action.copies();
50681 var originals = lodash.invert(lodash.mapValues(copies, 'id'));
50682 for (var id in copies) {
50683 var oldEntity = oldGraph.entity(id),
50684 newEntity = copies[id];
50686 extent$$1._extend(oldEntity.extent(oldGraph));
50688 actionChangeTags(newEntity.id, lodash.omitBy(newEntity.tags, omitTag))
50691 // Exclude child nodes from newIDs if their parent way was also copied.
50692 var parents = context.graph().parentWays(newEntity),
50693 parentCopied = false;
50694 for (var i = 0; i < parents.length; i++) {
50695 if (originals[parents[i].id]) {
50696 parentCopied = true;
50701 if (!parentCopied) {
50702 newIDs.push(newEntity.id);
50706 // Put pasted objects where mouse pointer is..
50707 var center = projection(extent$$1.center()),
50708 delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
50710 context.perform(actionMove(newIDs, delta, projection));
50711 context.enter(modeMove$$1(context, newIDs, baseGraph));
50716 keybinding.on(uiCmd('⌘V'), doPaste);
50717 select(document).call(keybinding);
50722 paste.off = function() {
50723 select(document).call(keybinding.off);
50730 function behaviorSelect(context) {
50731 var lastMouse = null,
50732 suppressMenu = true,
50738 return mouse(context.container().node());
50742 function keydown() {
50744 if (e && e.shiftKey) {
50746 .classed('behavior-multiselect', true);
50749 if (e && e.keyCode === 93) { // context menu
50750 e.preventDefault();
50751 e.stopPropagation();
50758 if (!e || !e.shiftKey) {
50760 .classed('behavior-multiselect', false);
50764 if (e && e.keyCode === 93) { // context menu
50765 e.preventDefault();
50766 e.stopPropagation();
50772 function mousedown() {
50773 if (!p1) p1 = point();
50775 .on('mouseup.select', mouseup, true);
50777 var isShowAlways = +context.storage('edit-menu-show-always') === 1;
50778 suppressMenu = !isShowAlways;
50782 function mousemove() {
50783 if (event) lastMouse = event;
50787 function mouseup() {
50792 function contextmenu() {
50794 e.preventDefault();
50795 e.stopPropagation();
50797 if (!+e.clientX && !+e.clientY) {
50799 e.sourceEvent = lastMouse;
50805 if (!p1) p1 = point();
50806 suppressMenu = false;
50813 .on('mouseup.select', null, true);
50817 dist = geoEuclideanDistance(p1, p2);
50820 if (dist > tolerance) {
50824 var isMultiselect = event.shiftKey || select('#surface .lasso').node(),
50825 isShowAlways = +context.storage('edit-menu-show-always') === 1,
50826 datum = event.target.__data__ || (lastMouse && lastMouse.target.__data__),
50827 mode = context.mode();
50830 if (datum && datum.type === 'midpoint') {
50831 datum = datum.parents[0];
50834 if (!(datum instanceof osmEntity$$1)) {
50835 // clicked nothing..
50836 if (!isMultiselect && mode.id !== 'browse') {
50837 context.enter(modeBrowse(context));
50841 // clicked an entity..
50842 var selectedIDs = context.selectedIDs();
50844 if (!isMultiselect) {
50845 if (selectedIDs.length > 1 && (!suppressMenu && !isShowAlways)) {
50846 // multiple things already selected, just show the menu...
50847 mode.suppressMenu(false).reselect();
50849 // select a single thing..
50850 context.enter(modeSelect(context, [datum.id]).suppressMenu(suppressMenu));
50854 if (selectedIDs.indexOf(datum.id) !== -1) {
50855 // clicked entity is already in the selectedIDs list..
50856 if (!suppressMenu && !isShowAlways) {
50857 // don't deselect clicked entity, just show the menu.
50858 mode.suppressMenu(false).reselect();
50860 // deselect clicked entity, then reenter select mode or return to browse mode..
50861 selectedIDs = lodash.without(selectedIDs, datum.id);
50862 context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse(context));
50865 // clicked entity is not in the selected list, add it..
50866 selectedIDs = selectedIDs.concat([datum.id]);
50867 context.enter(modeSelect(context, selectedIDs).suppressMenu(suppressMenu));
50872 // reset for next time..
50873 suppressMenu = true;
50877 var behavior = function(selection$$1) {
50879 suppressMenu = true;
50883 .on('keydown.select', keydown)
50884 .on('keyup.select', keyup)
50885 .on('contextmenu.select-window', function() {
50886 // Edge and IE really like to show the contextmenu on the
50887 // menubar when user presses a keyboard menu button
50888 // even after we've already preventdefaulted the key event.
50889 event.preventDefault();
50890 event.stopPropagation();
50894 .on('mousedown.select', mousedown)
50895 .on('mousemove.select', mousemove)
50896 .on('contextmenu.select', contextmenu);
50898 if (event && event.shiftKey) {
50900 .classed('behavior-multiselect', true);
50905 behavior.off = function(selection$$1) {
50907 .on('keydown.select', null)
50908 .on('keyup.select', null)
50909 .on('contextmenu.select-window', null)
50910 .on('mouseup.select', null, true);
50913 .on('mousedown.select', null)
50914 .on('mousemove.select', null)
50915 .on('contextmenu.select', null);
50918 .classed('behavior-multiselect', false);
50925 function modeAddArea$$1(context) {
50929 title: t('modes.add_area.title'),
50930 description: t('modes.add_area.description'),
50934 var behavior = behaviorAddWay(context)
50935 .tail(t('modes.add_area.tail'))
50936 .on('start', start)
50937 .on('startFromWay', startFromWay)
50938 .on('startFromNode', startFromNode),
50939 defaultTags = { area: 'yes' };
50942 function actionClose(wayId) {
50943 return function (graph) {
50944 return graph.replace(graph.entity(wayId).close());
50949 function start(loc) {
50950 var startGraph = context.graph(),
50951 node = osmNode({ loc: loc }),
50952 way = osmWay({ tags: defaultTags });
50955 actionAddEntity(node),
50956 actionAddEntity(way),
50957 actionAddVertex(way.id, node.id),
50958 actionClose(way.id)
50961 context.enter(modeDrawArea(context, way.id, startGraph));
50965 function startFromWay(loc, edge) {
50966 var startGraph = context.graph(),
50967 node = osmNode({ loc: loc }),
50968 way = osmWay({ tags: defaultTags });
50971 actionAddEntity(node),
50972 actionAddEntity(way),
50973 actionAddVertex(way.id, node.id),
50974 actionClose(way.id),
50975 actionAddMidpoint({ loc: loc, edge: edge }, node)
50978 context.enter(modeDrawArea(context, way.id, startGraph));
50982 function startFromNode(node) {
50983 var startGraph = context.graph(),
50984 way = osmWay({ tags: defaultTags });
50987 actionAddEntity(way),
50988 actionAddVertex(way.id, node.id),
50989 actionClose(way.id)
50992 context.enter(modeDrawArea(context, way.id, startGraph));
50996 mode.enter = function() {
50997 context.install(behavior);
51001 mode.exit = function() {
51002 context.uninstall(behavior);
51009 function modeAddLine$$1(context) {
51013 title: t('modes.add_line.title'),
51014 description: t('modes.add_line.description'),
51018 var behavior = behaviorAddWay(context)
51019 .tail(t('modes.add_line.tail'))
51020 .on('start', start)
51021 .on('startFromWay', startFromWay)
51022 .on('startFromNode', startFromNode);
51025 function start(loc) {
51026 var startGraph = context.graph(),
51027 node = osmNode({ loc: loc }),
51031 actionAddEntity(node),
51032 actionAddEntity(way),
51033 actionAddVertex(way.id, node.id)
51036 context.enter(modeDrawLine(context, way.id, startGraph));
51040 function startFromWay(loc, edge) {
51041 var startGraph = context.graph(),
51042 node = osmNode({ loc: loc }),
51046 actionAddEntity(node),
51047 actionAddEntity(way),
51048 actionAddVertex(way.id, node.id),
51049 actionAddMidpoint({ loc: loc, edge: edge }, node)
51052 context.enter(modeDrawLine(context, way.id, startGraph));
51056 function startFromNode(node) {
51057 var startGraph = context.graph(),
51061 actionAddEntity(way),
51062 actionAddVertex(way.id, node.id)
51065 context.enter(modeDrawLine(context, way.id, startGraph));
51069 mode.enter = function() {
51070 context.install(behavior);
51074 mode.exit = function() {
51075 context.uninstall(behavior);
51081 function modeAddPoint$$1(context) {
51085 title: t('modes.add_point.title'),
51086 description: t('modes.add_point.description'),
51090 var behavior = behaviorDraw(context)
51091 .tail(t('modes.add_point.tail'))
51093 .on('clickWay', addWay)
51094 .on('clickNode', addNode)
51095 .on('cancel', cancel)
51096 .on('finish', cancel);
51099 function add(loc) {
51100 var node = osmNode({ loc: loc });
51103 actionAddEntity(node),
51104 t('operations.add.annotation.point')
51108 modeSelect(context, [node.id]).newFeature(true)
51113 function addWay(loc) {
51118 function addNode(node) {
51123 function cancel() {
51124 context.enter(modeBrowse(context));
51128 mode.enter = function() {
51129 context.install(behavior);
51133 mode.exit = function() {
51134 context.uninstall(behavior);
51141 function modeDragNode$$1(context) {
51153 hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
51154 edit = behaviorEdit(context);
51157 function vecSub(a, b) {
51158 return [a[0] - b[0], a[1] - b[1]];
51161 function edge(point, size) {
51162 var pad = [80, 20, 50, 20], // top, right, bottom, left
51166 if (point[0] > size[0] - pad[1])
51168 if (point[0] < pad[3])
51170 if (point[1] > size[1] - pad[2])
51172 if (point[1] < pad[0])
51183 function startNudge(entity, nudge) {
51184 if (nudgeInterval) window.clearInterval(nudgeInterval);
51185 nudgeInterval = window.setInterval(function() {
51186 context.pan(nudge);
51187 doMove(entity, nudge);
51192 function stopNudge() {
51193 if (nudgeInterval) {
51194 window.clearInterval(nudgeInterval);
51195 nudgeInterval = null;
51200 function moveAnnotation(entity) {
51201 return t('operations.move.annotation.' + entity.geometry(context.graph()));
51205 function connectAnnotation(entity) {
51206 return t('operations.connect.annotation.' + entity.geometry(context.graph()));
51210 function origin(entity) {
51211 return context.projection(entity.loc);
51215 function start(entity) {
51216 wasMidpoint = entity.type === 'midpoint';
51218 isCancelled = event.sourceEvent.shiftKey ||
51219 context.features().hasHiddenConnections(entity, context.graph());
51222 return behavior.cancel();
51226 var midpoint = entity;
51227 entity = osmNode();
51228 context.perform(actionAddMidpoint(midpoint, entity));
51230 var vertex = context.surface().selectAll('.' + entity.id);
51231 behavior.target(vertex.node(), entity);
51234 context.perform(actionNoop());
51237 // activeIDs generate no pointer events. This prevents the node or vertex
51238 // being dragged from trying to connect to itself or its parent element.
51239 activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
51240 activeIDs.push(entity.id);
51241 setActiveElements();
51243 context.enter(mode);
51248 var event$$1 = event && event.sourceEvent;
51249 if (!event$$1 || event$$1.altKey) {
51252 return event$$1.target.__data__ || {};
51257 function doMove(entity, nudge) {
51258 nudge = nudge || [0, 0];
51260 var currPoint = (event && event.point) || context.projection(lastLoc),
51261 currMouse = vecSub(currPoint, nudge),
51262 loc = context.projection.invert(currMouse),
51265 if (!nudgeInterval) {
51266 if (d.type === 'node' && d.id !== entity.id) {
51268 } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
51269 loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
51274 actionMoveNode(entity.id, loc),
51275 moveAnnotation(entity)
51282 function move(entity) {
51283 if (isCancelled) return;
51284 event.sourceEvent.stopPropagation();
51285 lastLoc = context.projection.invert(event.point);
51288 var nudge = edge(event.point, context.map().dimensions());
51290 startNudge(entity, nudge);
51297 function end(entity) {
51298 if (isCancelled) return;
51302 if (d.type === 'way') {
51303 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
51305 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
51306 connectAnnotation(d)
51309 } else if (d.type === 'node' && d.id !== entity.id) {
51311 actionConnect([d.id, entity.id]),
51312 connectAnnotation(d)
51315 } else if (wasMidpoint) {
51318 t('operations.add.annotation.vertex')
51324 moveAnnotation(entity)
51328 var reselection = selectedIDs.filter(function(id) {
51329 return context.graph().hasEntity(id);
51332 if (reselection.length) {
51333 context.enter(modeSelect(context, reselection));
51335 context.enter(modeBrowse(context));
51340 function cancel() {
51342 context.enter(modeBrowse(context));
51346 function setActiveElements() {
51347 context.surface().selectAll(utilEntitySelector(activeIDs))
51348 .classed('active', true);
51352 var behavior = behaviorDrag()
51353 .selector('g.node, g.point, g.midpoint')
51354 .surface(select('#map').node())
51356 .on('start', start)
51361 mode.enter = function() {
51362 context.install(hover);
51363 context.install(edit);
51366 .on('undone.drag-node', cancel);
51369 .on('drawn.drag-node', setActiveElements);
51371 setActiveElements();
51375 mode.exit = function() {
51376 context.ui().sidebar.hover.cancel();
51377 context.uninstall(hover);
51378 context.uninstall(edit);
51381 .on('undone.drag-node', null);
51384 .on('drawn.drag-node', null);
51387 .selectAll('.active')
51388 .classed('active', false);
51394 mode.selectedIDs = function(_) {
51395 if (!arguments.length) return selectedIDs;
51401 mode.behavior = behavior;
51407 function modeBrowse(context) {
51411 title: t('modes.browse.title'),
51412 description: t('modes.browse.description')
51416 behaviorPaste(context),
51417 behaviorHover(context).on('hover', context.ui().sidebar.hover),
51418 behaviorSelect(context),
51419 behaviorLasso(context),
51420 modeDragNode$$1(context).behavior
51424 mode.enter = function() {
51425 behaviors.forEach(function(behavior) {
51426 context.install(behavior);
51429 // Get focus on the body.
51430 if (document.activeElement && document.activeElement.blur) {
51431 document.activeElement.blur();
51435 context.ui().sidebar.show(sidebar);
51437 context.ui().sidebar.select(null);
51442 mode.exit = function() {
51443 context.ui().sidebar.hover.cancel();
51444 behaviors.forEach(function(behavior) {
51445 context.uninstall(behavior);
51449 context.ui().sidebar.hide();
51454 mode.sidebar = function(_) {
51455 if (!arguments.length) return sidebar;
51464 function modeDrawArea(context, wayId, startGraph) {
51473 mode.enter = function() {
51474 var way = context.entity(wayId);
51476 behavior = behaviorDrawWay(context, wayId, undefined, mode, startGraph)
51477 .tail(t('modes.draw_area.tail'));
51479 var addNode = behavior.addNode;
51481 behavior.addNode = function(node) {
51482 var length = way.nodes.length,
51483 penultimate = length > 2 ? way.nodes[length - 2] : null;
51485 if (node.id === way.first() || node.id === penultimate) {
51492 context.install(behavior);
51496 mode.exit = function() {
51497 context.uninstall(behavior);
51501 mode.selectedIDs = function() {
51509 function modeDrawLine(context, wayId, startGraph, affix) {
51518 mode.enter = function() {
51519 var way = context.entity(wayId),
51520 index = (affix === 'prefix') ? 0 : undefined,
51521 headId = (affix === 'prefix') ? way.first() : way.last();
51523 behavior = behaviorDrawWay(context, wayId, index, mode, startGraph)
51524 .tail(t('modes.draw_line.tail'));
51526 var addNode = behavior.addNode;
51528 behavior.addNode = function(node) {
51529 if (node.id === headId) {
51536 context.install(behavior);
51540 mode.exit = function() {
51541 context.uninstall(behavior);
51545 mode.selectedIDs = function() {
51553 function operationCircularize(selectedIDs, context) {
51554 var entityId = selectedIDs[0],
51555 entity = context.entity(entityId),
51556 extent = entity.extent(context.graph()),
51557 geometry = context.geometry(entityId),
51558 action = actionCircularize(entityId, context.projection);
51561 var operation = function() {
51562 context.perform(action, operation.annotation());
51566 operation.available = function() {
51567 return selectedIDs.length === 1 &&
51568 entity.type === 'way' &&
51569 lodash.uniq(entity.nodes).length > 1;
51573 operation.disabled = function() {
51575 if (extent.percentContainedIn(context.extent()) < 0.8) {
51576 reason = 'too_large';
51577 } else if (context.hasHiddenConnections(entityId)) {
51578 reason = 'connected_to_hidden';
51580 return action.disabled(context.graph()) || reason;
51584 operation.tooltip = function() {
51585 var disable = operation.disabled();
51587 t('operations.circularize.' + disable) :
51588 t('operations.circularize.description.' + geometry);
51592 operation.annotation = function() {
51593 return t('operations.circularize.annotation.' + geometry);
51597 operation.id = 'circularize';
51598 operation.keys = [t('operations.circularize.key')];
51599 operation.title = t('operations.circularize.title');
51600 operation.behavior = behaviorOperation(context).which(operation);
51605 function operationContinue(selectedIDs, context) {
51606 var graph = context.graph(),
51607 entities = selectedIDs.map(function(id) { return graph.entity(id); }),
51608 geometries = lodash.extend({ line: [], vertex: [] },
51609 lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
51610 vertex = geometries.vertex[0];
51613 function candidateWays() {
51614 return graph.parentWays(vertex).filter(function(parent) {
51615 return parent.geometry(graph) === 'line' &&
51616 !parent.isClosed() &&
51617 parent.affix(vertex.id) &&
51618 (geometries.line.length === 0 || geometries.line[0] === parent);
51623 var operation = function() {
51624 var candidate = candidateWays()[0];
51626 modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
51631 operation.available = function() {
51632 return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
51633 !context.features().hasHiddenConnections(vertex, context.graph());
51637 operation.disabled = function() {
51638 var candidates = candidateWays();
51639 if (candidates.length === 0)
51640 return 'not_eligible';
51641 if (candidates.length > 1)
51646 operation.tooltip = function() {
51647 var disable = operation.disabled();
51649 t('operations.continue.' + disable) :
51650 t('operations.continue.description');
51654 operation.annotation = function() {
51655 return t('operations.continue.annotation.line');
51659 operation.id = 'continue';
51660 operation.keys = [t('operations.continue.key')];
51661 operation.title = t('operations.continue.title');
51662 operation.behavior = behaviorOperation(context).which(operation);
51667 function operationDelete(selectedIDs, context) {
51668 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51669 action = actionDeleteMultiple(selectedIDs),
51670 extent = selectedIDs.reduce(function(extent, id) {
51671 return extent.extend(context.entity(id).extent(context.graph()));
51672 }, geoExtent$$1());
51675 var operation = function() {
51676 var nextSelectedID;
51678 if (selectedIDs.length === 1) {
51679 var id = selectedIDs[0],
51680 entity = context.entity(id),
51681 geometry = context.geometry(id),
51682 parents = context.graph().parentWays(entity),
51683 parent = parents[0];
51685 // Select the next closest node in the way.
51686 if (geometry === 'vertex' && parent.nodes.length > 2) {
51687 var nodes = parent.nodes,
51688 i = nodes.indexOf(id);
51692 } else if (i === nodes.length - 1) {
51695 var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
51696 b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
51697 i = a < b ? i - 1 : i + 1;
51700 nextSelectedID = nodes[i];
51704 context.perform(action, operation.annotation());
51706 if (nextSelectedID && context.hasEntity(nextSelectedID)) {
51707 context.enter(modeSelect(context, [nextSelectedID]).follow(true));
51709 context.enter(modeBrowse(context));
51715 operation.available = function() {
51720 operation.disabled = function() {
51722 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51723 reason = 'too_large';
51724 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51725 reason = 'connected_to_hidden';
51726 } else if (lodash.some(selectedIDs, protectedMember)) {
51727 reason = 'part_of_relation';
51728 } else if (lodash.some(selectedIDs, incompleteRelation)) {
51729 reason = 'incomplete_relation';
51733 function incompleteRelation(id) {
51734 var entity = context.entity(id);
51735 return entity.type === 'relation' && !entity.isComplete(context.graph());
51738 function protectedMember(id) {
51739 var entity = context.entity(id);
51740 if (entity.type !== 'way') return false;
51742 var parents = context.graph().parentRelations(entity);
51743 for (var i = 0; i < parents.length; i++) {
51744 var parent = parents[i],
51745 type = parent.tags.type,
51746 role = parent.memberById(id).role || 'outer';
51747 if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
51757 operation.tooltip = function() {
51758 var disable = operation.disabled();
51760 t('operations.delete.' + disable + '.' + multi) :
51761 t('operations.delete.description' + '.' + multi);
51765 operation.annotation = function() {
51766 return selectedIDs.length === 1 ?
51767 t('operations.delete.annotation.' + context.geometry(selectedIDs[0])) :
51768 t('operations.delete.annotation.multiple', { n: selectedIDs.length });
51772 operation.id = 'delete';
51773 operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
51774 operation.title = t('operations.delete.title');
51775 operation.behavior = behaviorOperation(context).which(operation);
51780 function operationDisconnect(selectedIDs, context) {
51781 var vertices = lodash.filter(selectedIDs, function(entityId) {
51782 return context.geometry(entityId) === 'vertex';
51785 var entityId = vertices[0],
51786 action = actionDisconnect(entityId);
51788 if (selectedIDs.length > 1) {
51789 action.limitWays(lodash.without(selectedIDs, entityId));
51793 var operation = function() {
51794 context.perform(action, operation.annotation());
51798 operation.available = function() {
51799 return vertices.length === 1;
51803 operation.disabled = function() {
51805 if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51806 reason = 'connected_to_hidden';
51808 return action.disabled(context.graph()) || reason;
51812 operation.tooltip = function() {
51813 var disable = operation.disabled();
51815 t('operations.disconnect.' + disable) :
51816 t('operations.disconnect.description');
51820 operation.annotation = function() {
51821 return t('operations.disconnect.annotation');
51825 operation.id = 'disconnect';
51826 operation.keys = [t('operations.disconnect.key')];
51827 operation.title = t('operations.disconnect.title');
51828 operation.behavior = behaviorOperation(context).which(operation);
51833 function operationMerge(selectedIDs, context) {
51835 function updatePresetTags(oldGraph, newGraph, ids) {
51837 oldEntity = oldGraph.hasEntity(id),
51838 newEntity = newGraph.hasEntity(id);
51840 if (!oldEntity || !newEntity) return;
51842 var oldPreset = context.presets().match(oldEntity, oldGraph),
51843 newPreset = context.presets().match(newEntity, newGraph);
51845 context.replace(actionChangePreset(id, oldPreset, newPreset));
51849 var join = actionJoin(selectedIDs),
51850 merge = actionMerge(selectedIDs),
51851 mergePolygon = actionMergePolygon(selectedIDs);
51854 var operation = function() {
51855 var origGraph = context.graph(),
51858 if (!join.disabled(origGraph)) {
51860 } else if (!merge.disabled(origGraph)) {
51863 action = mergePolygon;
51866 context.perform(action, operation.annotation());
51868 var ids = selectedIDs.filter(function(id) {
51869 var entity = context.hasEntity(id);
51870 return entity && entity.type !== 'node';
51873 // if we merged tags, rematch preset and update tags if necessary (#3851)
51874 if (action === merge) {
51875 updatePresetTags(origGraph, context.graph(), ids);
51878 context.enter(modeSelect(context, ids));
51882 operation.available = function() {
51883 return selectedIDs.length >= 2;
51887 operation.disabled = function() {
51888 return join.disabled(context.graph()) &&
51889 merge.disabled(context.graph()) &&
51890 mergePolygon.disabled(context.graph());
51894 operation.tooltip = function() {
51895 var j = join.disabled(context.graph()),
51896 m = merge.disabled(context.graph()),
51897 p = mergePolygon.disabled(context.graph());
51899 if (j === 'restriction' && m && p) {
51900 return t('operations.merge.restriction',
51901 { relation: context.presets().item('type/restriction').name() });
51904 if (p === 'incomplete_relation' && j && m) {
51905 return t('operations.merge.incomplete_relation');
51909 return t('operations.merge.' + j);
51912 return t('operations.merge.description');
51916 operation.annotation = function() {
51917 return t('operations.merge.annotation', { n: selectedIDs.length });
51921 operation.id = 'merge';
51922 operation.keys = [t('operations.merge.key')];
51923 operation.title = t('operations.merge.title');
51924 operation.behavior = behaviorOperation(context).which(operation);
51929 function operationMove(selectedIDs, context) {
51930 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51931 extent = selectedIDs.reduce(function(extent, id) {
51932 return extent.extend(context.entity(id).extent(context.graph()));
51933 }, geoExtent$$1());
51936 var operation = function() {
51937 context.enter(modeMove$$1(context, selectedIDs));
51941 operation.available = function() {
51942 return selectedIDs.length > 1 ||
51943 context.entity(selectedIDs[0]).type !== 'node';
51947 operation.disabled = function() {
51949 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51950 reason = 'too_large';
51951 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51952 reason = 'connected_to_hidden';
51953 } else if (lodash.some(selectedIDs, incompleteRelation)) {
51954 reason = 'incomplete_relation';
51958 function incompleteRelation(id) {
51959 var entity = context.entity(id);
51960 return entity.type === 'relation' && !entity.isComplete(context.graph());
51965 operation.tooltip = function() {
51966 var disable = operation.disabled();
51968 t('operations.move.' + disable + '.' + multi) :
51969 t('operations.move.description.' + multi);
51973 operation.annotation = function() {
51974 return selectedIDs.length === 1 ?
51975 t('operations.move.annotation.' + context.geometry(selectedIDs[0])) :
51976 t('operations.move.annotation.multiple');
51980 operation.id = 'move';
51981 operation.keys = [t('operations.move.key')];
51982 operation.title = t('operations.move.title');
51983 operation.behavior = behaviorOperation(context).which(operation);
51988 function operationOrthogonalize(selectedIDs, context) {
51989 var entityId = selectedIDs[0],
51990 entity = context.entity(entityId),
51991 extent = entity.extent(context.graph()),
51992 geometry = context.geometry(entityId),
51993 action = actionOrthogonalize(entityId, context.projection);
51996 var operation = function() {
51997 context.perform(action, operation.annotation());
52001 operation.available = function() {
52002 return selectedIDs.length === 1 &&
52003 entity.type === 'way' &&
52004 entity.isClosed() &&
52005 lodash.uniq(entity.nodes).length > 2;
52009 operation.disabled = function() {
52011 if (extent.percentContainedIn(context.extent()) < 0.8) {
52012 reason = 'too_large';
52013 } else if (context.hasHiddenConnections(entityId)) {
52014 reason = 'connected_to_hidden';
52016 return action.disabled(context.graph()) || reason;
52020 operation.tooltip = function() {
52021 var disable = operation.disabled();
52023 t('operations.orthogonalize.' + disable) :
52024 t('operations.orthogonalize.description.' + geometry);
52028 operation.annotation = function() {
52029 return t('operations.orthogonalize.annotation.' + geometry);
52033 operation.id = 'orthogonalize';
52034 operation.keys = [t('operations.orthogonalize.key')];
52035 operation.title = t('operations.orthogonalize.title');
52036 operation.behavior = behaviorOperation(context).which(operation);
52041 function operationReflectShort(selectedIDs, context) {
52042 return operationReflect(selectedIDs, context, 'short');
52046 function operationReflectLong(selectedIDs, context) {
52047 return operationReflect(selectedIDs, context, 'long');
52051 function operationReflect(selectedIDs, context, axis) {
52052 axis = axis || 'long';
52053 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
52054 extent = selectedIDs.reduce(function(extent, id) {
52055 return extent.extend(context.entity(id).extent(context.graph()));
52056 }, geoExtent$$1());
52059 var operation = function() {
52060 var action = actionReflect(selectedIDs, context.projection)
52061 .useLongAxis(Boolean(axis === 'long'));
52062 context.perform(action, operation.annotation());
52066 operation.available = function() {
52067 return lodash.some(selectedIDs, hasArea);
52069 function hasArea(id) {
52070 var entity = context.entity(id);
52071 return (entity.type === 'way' && entity.isClosed()) ||
52072 (entity.type ==='relation' && entity.isMultipolygon());
52077 operation.disabled = function() {
52079 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
52080 reason = 'too_large';
52081 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
52082 reason = 'connected_to_hidden';
52083 } else if (lodash.some(selectedIDs, incompleteRelation)) {
52084 reason = 'incomplete_relation';
52088 function incompleteRelation(id) {
52089 var entity = context.entity(id);
52090 return entity.type === 'relation' && !entity.isComplete(context.graph());
52095 operation.tooltip = function() {
52096 var disable = operation.disabled();
52098 t('operations.reflect.' + disable + '.' + multi) :
52099 t('operations.reflect.description.' + axis + '.' + multi);
52103 operation.annotation = function() {
52104 return t('operations.reflect.annotation.' + axis + '.' + multi);
52108 operation.id = 'reflect-' + axis;
52109 operation.keys = [t('operations.reflect.key.' + axis)];
52110 operation.title = t('operations.reflect.title.' + axis);
52111 operation.behavior = behaviorOperation(context).which(operation);
52116 function operationReverse(selectedIDs, context) {
52117 var entityId = selectedIDs[0];
52119 var operation = function() {
52120 context.perform(actionReverse(entityId), operation.annotation());
52124 operation.available = function() {
52125 return selectedIDs.length === 1 && context.geometry(entityId) === 'line';
52129 operation.disabled = function() {
52134 operation.tooltip = function() {
52135 return t('operations.reverse.description');
52139 operation.annotation = function() {
52140 return t('operations.reverse.annotation');
52144 operation.id = 'reverse';
52145 operation.keys = [t('operations.reverse.key')];
52146 operation.title = t('operations.reverse.title');
52147 operation.behavior = behaviorOperation(context).which(operation);
52152 function operationRotate(selectedIDs, context) {
52153 var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
52154 extent = selectedIDs.reduce(function(extent, id) {
52155 return extent.extend(context.entity(id).extent(context.graph()));
52156 }, geoExtent$$1());
52159 var operation = function() {
52160 context.enter(modeRotate$$1(context, selectedIDs));
52164 operation.available = function() {
52165 return lodash.some(selectedIDs, hasArea);
52167 function hasArea(id) {
52168 var entity = context.entity(id);
52169 return (entity.type === 'way' && entity.isClosed()) ||
52170 (entity.type ==='relation' && entity.isMultipolygon());
52175 operation.disabled = function() {
52177 if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
52178 reason = 'too_large';
52179 } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
52180 reason = 'connected_to_hidden';
52181 } else if (lodash.some(selectedIDs, incompleteRelation)) {
52182 reason = 'incomplete_relation';
52186 function incompleteRelation(id) {
52187 var entity = context.entity(id);
52188 return entity.type === 'relation' && !entity.isComplete(context.graph());
52193 operation.tooltip = function() {
52194 var disable = operation.disabled();
52196 t('operations.rotate.' + disable + '.' + multi) :
52197 t('operations.rotate.description.' + multi);
52201 operation.annotation = function() {
52202 return selectedIDs.length === 1 ?
52203 t('operations.rotate.annotation.' + context.geometry(selectedIDs[0])) :
52204 t('operations.rotate.annotation.multiple');
52208 operation.id = 'rotate';
52209 operation.keys = [t('operations.rotate.key')];
52210 operation.title = t('operations.rotate.title');
52211 operation.behavior = behaviorOperation(context).which(operation);
52216 function operationSplit(selectedIDs, context) {
52217 var vertices = lodash.filter(selectedIDs, function(entityId) {
52218 return context.geometry(entityId) === 'vertex';
52221 var entityId = vertices[0],
52222 action = actionSplit(entityId),
52225 if (vertices.length === 1) {
52226 if (selectedIDs.length > 1) {
52227 action.limitWays(lodash.without(selectedIDs, entityId));
52229 ways = action.ways(context.graph());
52233 var operation = function() {
52234 var difference = context.perform(action, operation.annotation());
52235 context.enter(modeSelect(context, difference.extantIDs()));
52239 operation.available = function() {
52240 return vertices.length === 1;
52244 operation.disabled = function() {
52246 if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
52247 reason = 'connected_to_hidden';
52249 return action.disabled(context.graph()) || reason;
52253 operation.tooltip = function() {
52254 var disable = operation.disabled();
52256 return t('operations.split.' + disable);
52258 if (ways.length === 1) {
52259 return t('operations.split.description.' + context.geometry(ways[0].id));
52261 return t('operations.split.description.multiple');
52266 operation.annotation = function() {
52267 return ways.length === 1 ?
52268 t('operations.split.annotation.' + context.geometry(ways[0].id)) :
52269 t('operations.split.annotation.multiple', { n: ways.length });
52273 operation.id = 'split';
52274 operation.keys = [t('operations.split.key')];
52275 operation.title = t('operations.split.title');
52276 operation.behavior = behaviorOperation(context).which(operation);
52281 function operationStraighten(selectedIDs, context) {
52282 var entityId = selectedIDs[0],
52283 action = actionStraighten(entityId, context.projection);
52286 function operation() {
52287 context.perform(action, operation.annotation());
52291 operation.available = function() {
52292 var entity = context.entity(entityId);
52293 return selectedIDs.length === 1 &&
52294 entity.type === 'way' &&
52295 !entity.isClosed() &&
52296 lodash.uniq(entity.nodes).length > 2;
52300 operation.disabled = function() {
52302 if (context.hasHiddenConnections(entityId)) {
52303 reason = 'connected_to_hidden';
52305 return action.disabled(context.graph()) || reason;
52309 operation.tooltip = function() {
52310 var disable = operation.disabled();
52312 t('operations.straighten.' + disable) :
52313 t('operations.straighten.description');
52317 operation.annotation = function() {
52318 return t('operations.straighten.annotation');
52322 operation.id = 'straighten';
52323 operation.keys = [t('operations.straighten.key')];
52324 operation.title = t('operations.straighten.title');
52325 operation.behavior = behaviorOperation(context).which(operation);
52332 var Operations = Object.freeze({
52333 operationCircularize: operationCircularize,
52334 operationContinue: operationContinue,
52335 operationDelete: operationDelete,
52336 operationDisconnect: operationDisconnect,
52337 operationMerge: operationMerge,
52338 operationMove: operationMove,
52339 operationOrthogonalize: operationOrthogonalize,
52340 operationReflectShort: operationReflectShort,
52341 operationReflectLong: operationReflectLong,
52342 operationReverse: operationReverse,
52343 operationRotate: operationRotate,
52344 operationSplit: operationSplit,
52345 operationStraighten: operationStraighten
52348 function modeMove$$1(context, entityIDs, baseGraph) {
52354 var keybinding = d3keybinding('move'),
52356 behaviorEdit(context),
52357 operationCircularize(entityIDs, context).behavior,
52358 operationDelete(entityIDs, context).behavior,
52359 operationOrthogonalize(entityIDs, context).behavior,
52360 operationReflectLong(entityIDs, context).behavior,
52361 operationReflectShort(entityIDs, context).behavior,
52362 operationRotate(entityIDs, context).behavior
52364 annotation = entityIDs.length === 1 ?
52365 t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
52366 t('operations.move.annotation.multiple'),
52373 function vecSub(a, b) {
52374 return [a[0] - b[0], a[1] - b[1]];
52378 function edge(point, size) {
52379 var pad = [80, 20, 50, 20], // top, right, bottom, left
52383 if (point[0] > size[0] - pad[1])
52385 if (point[0] < pad[3])
52387 if (point[1] > size[1] - pad[2])
52389 if (point[1] < pad[0])
52400 function doMove(nudge) {
52401 nudge = nudge || [0, 0];
52404 if (prevGraph !== context.graph()) {
52406 origin = context.map().mouseCoordinates();
52407 fn = context.perform;
52409 fn = context.overwrite;
52412 var currMouse = context.mouse(),
52413 origMouse = context.projection(origin),
52414 delta = vecSub(vecSub(currMouse, origMouse), nudge);
52416 fn(actionMove(entityIDs, delta, context.projection, cache), annotation);
52417 prevGraph = context.graph();
52421 function startNudge(nudge) {
52422 if (nudgeInterval) window.clearInterval(nudgeInterval);
52423 nudgeInterval = window.setInterval(function() {
52424 context.pan(nudge);
52430 function stopNudge() {
52431 if (nudgeInterval) {
52432 window.clearInterval(nudgeInterval);
52433 nudgeInterval = null;
52440 var nudge = edge(context.mouse(), context.map().dimensions());
52449 function finish() {
52450 event.stopPropagation();
52451 context.enter(modeSelect(context, entityIDs));
52456 function cancel() {
52458 while (context.graph() !== baseGraph) context.pop();
52459 context.enter(modeBrowse(context));
52462 context.enter(modeSelect(context, entityIDs));
52468 function undone() {
52469 context.enter(modeBrowse(context));
52473 mode.enter = function() {
52474 origin = context.map().mouseCoordinates();
52478 behaviors.forEach(function(behavior) {
52479 context.install(behavior);
52483 .on('mousemove.move', move)
52484 .on('click.move', finish);
52487 .on('undone.move', undone);
52498 mode.exit = function() {
52501 behaviors.forEach(function(behavior) {
52502 context.uninstall(behavior);
52506 .on('mousemove.move', null)
52507 .on('click.move', null);
52510 .on('undone.move', null);
52519 function modeRotate$$1(context, entityIDs) {
52525 var keybinding = d3keybinding('rotate'),
52527 behaviorEdit(context),
52528 operationCircularize(entityIDs, context).behavior,
52529 operationDelete(entityIDs, context).behavior,
52530 operationMove(entityIDs, context).behavior,
52531 operationOrthogonalize(entityIDs, context).behavior,
52532 operationReflectLong(entityIDs, context).behavior,
52533 operationReflectShort(entityIDs, context).behavior
52535 annotation = entityIDs.length === 1 ?
52536 t('operations.rotate.annotation.' + context.geometry(entityIDs[0])) :
52537 t('operations.rotate.annotation.multiple'),
52544 function doRotate() {
52546 if (context.graph() !== prevGraph) {
52547 fn = context.perform;
52549 fn = context.replace;
52552 // projection changed, recalculate pivot
52553 var projection = context.projection;
52554 var currTransform = projection.transform();
52555 if (!prevTransform ||
52556 currTransform.k !== prevTransform.k ||
52557 currTransform.x !== prevTransform.x ||
52558 currTransform.y !== prevTransform.y) {
52560 var nodes = utilGetAllNodes(entityIDs, context.graph()),
52561 points = nodes.map(function(n) { return projection(n.loc); });
52563 pivot = d3polygonCentroid(d3polygonHull(points));
52564 prevAngle = undefined;
52568 var currMouse = context.mouse(),
52569 currAngle = Math.atan2(currMouse[1] - pivot[1], currMouse[0] - pivot[0]);
52571 if (typeof prevAngle === 'undefined') prevAngle = currAngle;
52572 var delta = currAngle - prevAngle;
52574 fn(actionRotate(entityIDs, pivot, delta, projection), annotation);
52576 prevTransform = currTransform;
52577 prevAngle = currAngle;
52578 prevGraph = context.graph();
52582 function finish() {
52583 event.stopPropagation();
52584 context.enter(modeSelect(context, entityIDs));
52588 function cancel() {
52590 context.enter(modeSelect(context, entityIDs));
52594 function undone() {
52595 context.enter(modeBrowse(context));
52599 mode.enter = function() {
52600 behaviors.forEach(function(behavior) {
52601 context.install(behavior);
52605 .on('mousemove.rotate', doRotate)
52606 .on('click.rotate', finish);
52609 .on('undone.rotate', undone);
52620 mode.exit = function() {
52621 behaviors.forEach(function(behavior) {
52622 context.uninstall(behavior);
52626 .on('mousemove.rotate', null)
52627 .on('click.rotate', null);
52630 .on('undone.rotate', null);
52639 function modeSave$$1(context) {
52644 var commit = uiCommit(context)
52645 .on('cancel', cancel)
52649 function cancel() {
52650 context.enter(modeBrowse(context));
52654 function save(changeset, tryAgain) {
52656 var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
52657 history = context.history(),
52658 origChanges = history.changes(actionDiscardTags(history.difference())),
52659 localGraph = context.graph(),
52660 remoteGraph = coreGraph$$1(history.base(), true),
52661 modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
52662 toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
52663 toLoad = withChildNodes(toCheck, localGraph),
52668 history.perform(actionNoop()); // checkpoint
52671 context.container().call(loading);
52673 if (toCheck.length) {
52674 context.connection().loadMultiple(toLoad, loaded);
52680 function withChildNodes(ids, graph) {
52681 return lodash.uniq(lodash.reduce(ids, function(result, id) {
52682 var entity = graph.entity(id);
52683 if (entity.type === 'way') {
52685 var cn = graph.childNodes(entity);
52686 result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
52688 /* eslint-disable no-console */
52689 if (typeof console !== 'undefined') console.error(err);
52690 /* eslint-enable no-console */
52694 }, lodash.clone(ids)));
52698 // Reload modified entities into an alternate graph and check for conflicts..
52699 function loaded(err, result) {
52700 if (errors.length) return;
52704 msg: err.responseText,
52705 details: [ t('save.status_code', { code: err.status }) ]
52711 lodash.each(result.data, function(entity) {
52712 remoteGraph.replace(entity);
52713 toLoad = lodash.without(toLoad, entity.id);
52715 // Because loadMultiple doesn't download /full like loadEntity,
52716 // need to also load children that aren't already being checked..
52717 if (!entity.visible) return;
52718 if (entity.type === 'way') {
52719 loadMore.push.apply(loadMore,
52720 lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
52721 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
52722 loadMore.push.apply(loadMore,
52723 lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
52727 if (loadMore.length) {
52728 toLoad.push.apply(toLoad, loadMore);
52729 context.connection().loadMultiple(loadMore, loaded);
52732 if (!toLoad.length) {
52739 function checkConflicts() {
52740 function choice(id, text$$1, action) {
52741 return { id: id, text: text$$1, action: function() { history.replace(action); } };
52743 function formatUser(d) {
52744 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
52746 function entityName(entity) {
52747 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
52750 function compareVersions(local$$1, remote) {
52751 if (local$$1.version !== remote.version) return false;
52753 if (local$$1.type === 'way') {
52754 var children = lodash.union(local$$1.nodes, remote.nodes);
52756 for (var i = 0; i < children.length; i++) {
52757 var a = localGraph.hasEntity(children[i]),
52758 b = remoteGraph.hasEntity(children[i]);
52760 if (a && b && a.version !== b.version) return false;
52767 lodash.each(toCheck, function(id) {
52768 var local$$1 = localGraph.entity(id),
52769 remote = remoteGraph.entity(id);
52771 if (compareVersions(local$$1, remote)) return;
52773 var action = actionMergeRemoteChanges,
52774 merge$$1 = action(id, localGraph, remoteGraph, formatUser);
52776 history.replace(merge$$1);
52778 var mergeConflicts = merge$$1.conflicts();
52779 if (!mergeConflicts.length) return; // merged safely
52781 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
52782 forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
52783 keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
52784 keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
52788 name: entityName(local$$1),
52789 details: mergeConflicts,
52792 choice(id, keepMine, forceLocal),
52793 choice(id, keepTheirs, forceRemote)
52802 function upload() {
52803 if (conflicts.length) {
52804 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
52806 } else if (errors.length) {
52809 var changes = history.changes(actionDiscardTags(history.difference()));
52810 if (changes.modified.length || changes.created.length || changes.deleted.length) {
52811 context.connection().putChangeset(changeset, changes, uploadCallback);
52812 } else { // changes were insignificant or reverted by user
52813 select('.inspector-wrap *').remove();
52822 function uploadCallback(err, changeset) {
52825 msg: err.responseText,
52826 details: [ t('save.status_code', { code: err.status }) ]
52830 history.clearSaved();
52831 success(changeset);
52832 // Add delay to allow for postgres replication #1646 #2678
52833 window.setTimeout(function() {
52834 select('.inspector-wrap *').remove();
52842 function showConflicts() {
52843 var selection$$1 = context.container()
52844 .select('#sidebar')
52846 .attr('class','sidebar-component');
52850 selection$$1.call(uiConflicts(context)
52852 .on('download', function() {
52853 var data = JXON.stringify(changeset.update({ id: 'CHANGEME' }).osmChangeJXON(origChanges)),
52854 win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
52857 .on('cancel', function() {
52859 selection$$1.remove();
52861 .on('save', function() {
52862 for (var i = 0; i < conflicts.length; i++) {
52863 if (conflicts[i].chosen === 1) { // user chose "keep theirs"
52864 var entity = context.hasEntity(conflicts[i].id);
52865 if (entity && entity.type === 'way') {
52866 var children = lodash.uniq(entity.nodes);
52867 for (var j = 0; j < children.length; j++) {
52868 history.replace(actionRevert(children[j]));
52871 history.replace(actionRevert(conflicts[i].id));
52875 selection$$1.remove();
52876 save(changeset, true);
52882 function showErrors() {
52883 var selection$$1 = uiConfirm(context.container());
52889 .select('.modal-section.header')
52891 .text(t('save.error'));
52893 addErrors(selection$$1, errors);
52894 selection$$1.okButton();
52898 function addErrors(selection$$1, data) {
52899 var message = selection$$1
52900 .select('.modal-section.message-text');
52902 var items = message
52903 .selectAll('.error-container')
52906 var enter = items.enter()
52908 .attr('class', 'error-container');
52912 .attr('class', 'error-description')
52914 .classed('hide-toggle', true)
52915 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
52916 .on('click', function() {
52917 var error = select(this),
52918 detail = select(this.nextElementSibling),
52919 exp = error.classed('expanded');
52921 detail.style('display', exp ? 'none' : 'block');
52922 error.classed('expanded', !exp);
52924 event.preventDefault();
52927 var details = enter
52929 .attr('class', 'error-detail-container')
52930 .style('display', 'none');
52934 .attr('class', 'error-detail-list')
52936 .data(function(d) { return d.details || []; })
52939 .attr('class', 'error-detail-item')
52940 .text(function(d) { return d; });
52949 function success(changeset) {
52951 context.enter(modeBrowse(context)
52952 .sidebar(uiSuccess(context)
52953 .changeset(changeset)
52954 .on('cancel', function() {
52955 context.ui().sidebar.hide();
52962 mode.enter = function() {
52964 context.ui().sidebar.show(commit);
52967 context.container().selectAll('#content')
52968 .attr('class', 'inactive');
52970 if (context.connection().authenticated()) {
52973 context.connection().authenticate(function(err) {
52984 mode.exit = function() {
52985 context.container().selectAll('#content')
52986 .attr('class', 'active');
52988 context.ui().sidebar.hide();
52994 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
52995 // For example, ⌘Z -> Ctrl+Z
52996 function uiCmd(code) {
52997 var detected = utilDetect();
52999 if (detected.os === 'mac') {
53003 if (detected.os === 'win') {
53004 if (code === '⌘⇧Z') return 'Ctrl+Y';
53016 for (var i = 0; i < code.length; i++) {
53017 if (code[i] in replacements) {
53018 result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
53027 // deprecation warning - Radial Menu to be removed in iD v3
53031 function modeSelect(context, selectedIDs) {
53037 var keybinding = d3keybinding('select'),
53040 behaviorCopy(context),
53041 behaviorPaste(context),
53042 behaviorBreathe(context),
53043 behaviorHover(context),
53044 behaviorSelect(context),
53045 behaviorLasso(context),
53046 modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
53050 newFeature = false,
53051 suppressMenu = true,
53055 var wrap = context.container()
53056 .select('.inspector-wrap');
53059 function singular() {
53060 if (selectedIDs.length === 1) {
53061 return context.hasEntity(selectedIDs[0]);
53066 function checkSelectedIDs() {
53068 if (Array.isArray(selectedIDs)) {
53069 ids = selectedIDs.filter(function(id) {
53070 return context.hasEntity(id);
53077 context.enter(modeBrowse(context));
53079 return !!ids.length;
53083 // find the common parent ways for nextVertex, previousVertex
53084 function commonParents() {
53085 var graph = context.graph(),
53086 commonParents = [];
53088 for (var i = 0; i < selectedIDs.length; i++) {
53089 var entity = context.hasEntity(selectedIDs[i]);
53090 if (!entity || entity.geometry(graph) !== 'vertex') {
53091 return []; // selection includes some not vertexes
53094 var currParents = lodash.map(graph.parentWays(entity), 'id');
53095 if (!commonParents.length) {
53096 commonParents = currParents;
53100 commonParents = lodash.intersection(commonParents, currParents);
53101 if (!commonParents.length) {
53106 return commonParents;
53110 function singularParent() {
53111 var parents = commonParents();
53112 if (!parents || parents.length === 0) {
53113 relatedParent = null;
53117 // relatedParent is used when we visit a vertex with multiple
53118 // parents, and we want to remember which parent line we started on.
53120 if (parents.length === 1) {
53121 relatedParent = parents[0]; // remember this parent for later
53122 return relatedParent;
53125 if (parents.indexOf(relatedParent) !== -1) {
53126 return relatedParent; // prefer the previously seen parent
53133 function closeMenu() {
53135 context.surface().call(editMenu.close);
53140 function positionMenu() {
53141 if (!editMenu) { return; }
53143 var entity = singular();
53144 if (entity && context.geometry(entity.id) === 'relation') {
53145 suppressMenu = true;
53147 var point = context.mouse(),
53148 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
53150 if (point && geoPointInPolygon(point, viewport)) {
53151 editMenu.center(point);
53153 suppressMenu = true;
53159 function showMenu() {
53162 context.surface().call(editMenu);
53167 function toggleMenu() {
53168 // deprecation warning - Radial Menu to be removed in iD v3
53169 if (select('.edit-menu, .radial-menu').empty()) {
53178 mode.selectedIDs = function() {
53179 return selectedIDs;
53183 mode.reselect = function() {
53184 if (!checkSelectedIDs()) return;
53186 var surfaceNode = context.surface().node();
53187 if (surfaceNode.focus) { // FF doesn't support it
53188 surfaceNode.focus();
53192 if (!suppressMenu) {
53198 mode.newFeature = function(_) {
53199 if (!arguments.length) return newFeature;
53205 mode.suppressMenu = function(_) {
53206 if (!arguments.length) return suppressMenu;
53212 mode.follow = function(_) {
53213 if (!arguments.length) return follow;
53219 mode.enter = function() {
53221 function update() {
53223 checkSelectedIDs();
53227 function dblclick() {
53228 var target = select(event.target),
53229 datum = target.datum();
53231 if (datum instanceof osmWay && !target.classed('fill')) {
53232 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
53233 prev = datum.nodes[choice.index - 1],
53234 next = datum.nodes[choice.index];
53237 actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, osmNode()),
53238 t('operations.add.annotation.vertex')
53241 event.preventDefault();
53242 event.stopPropagation();
53244 } else if (datum.type === 'midpoint') {
53246 actionAddMidpoint({loc: datum.loc, edge: datum.edge}, osmNode()),
53247 t('operations.add.annotation.vertex'));
53249 event.preventDefault();
53250 event.stopPropagation();
53255 function selectElements(drawn) {
53256 if (!checkSelectedIDs()) return;
53258 var surface = context.surface(),
53259 entity = singular();
53261 if (entity && context.geometry(entity.id) === 'relation') {
53262 suppressMenu = true;
53266 surface.selectAll('.related')
53267 .classed('related', false);
53270 if (relatedParent) {
53271 surface.selectAll(utilEntitySelector([relatedParent]))
53272 .classed('related', true);
53275 var selection$$1 = context.surface()
53276 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
53278 if (selection$$1.empty()) {
53279 // Return to browse mode if selected DOM elements have
53280 // disappeared because the user moved them out of view..
53281 var source = event && event.type === 'zoom' && event.sourceEvent;
53282 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
53283 context.enter(modeBrowse(context));
53287 .classed('selected', true);
53293 context.enter(modeBrowse(context));
53297 function firstVertex() {
53298 event.preventDefault();
53299 var parent = singularParent();
53301 var way = context.entity(parent);
53303 modeSelect(context, [way.first()]).follow(true)
53309 function lastVertex() {
53310 event.preventDefault();
53311 var parent = singularParent();
53313 var way = context.entity(parent);
53315 modeSelect(context, [way.last()]).follow(true)
53321 function previousVertex() {
53322 event.preventDefault();
53323 var parent = singularParent();
53324 if (!parent) return;
53326 var way = context.entity(parent),
53327 length = way.nodes.length,
53328 curr = way.nodes.indexOf(selectedIDs[0]),
53333 } else if (way.isClosed()) {
53334 index = length - 2;
53337 if (index !== -1) {
53339 modeSelect(context, [way.nodes[index]]).follow(true)
53345 function nextVertex() {
53346 event.preventDefault();
53347 var parent = singularParent();
53348 if (!parent) return;
53350 var way = context.entity(parent),
53351 length = way.nodes.length,
53352 curr = way.nodes.indexOf(selectedIDs[0]),
53355 if (curr < length - 1) {
53357 } else if (way.isClosed()) {
53361 if (index !== -1) {
53363 modeSelect(context, [way.nodes[index]]).follow(true)
53369 function nextParent() {
53370 event.preventDefault();
53371 var parents = lodash.uniq(commonParents());
53372 if (!parents || parents.length < 2) return;
53374 var index = parents.indexOf(relatedParent);
53375 if (index < 0 || index > parents.length - 2) {
53376 relatedParent = parents[0];
53378 relatedParent = parents[index + 1];
53381 var surface = context.surface();
53382 surface.selectAll('.related')
53383 .classed('related', false);
53385 if (relatedParent) {
53386 surface.selectAll(utilEntitySelector([relatedParent]))
53387 .classed('related', true);
53392 if (!checkSelectedIDs()) return;
53394 var operations = lodash.without(values(Operations), operationDelete)
53395 .map(function(o) { return o(selectedIDs, context); })
53396 .filter(function(o) { return o.available(); });
53398 // deprecation warning - Radial Menu to be removed in iD v3
53399 var isRadialMenu = context.storage('edit-menu-style') === 'radial';
53400 if (isRadialMenu) {
53401 operations = operations.slice(0,7);
53402 operations.unshift(operationDelete(selectedIDs, context));
53404 operations.push(operationDelete(selectedIDs, context));
53407 operations.forEach(function(operation) {
53408 if (operation.behavior) {
53409 behaviors.push(operation.behavior);
53413 behaviors.forEach(function(behavior) {
53414 context.install(behavior);
53418 .on(['[','pgup'], previousVertex)
53419 .on([']', 'pgdown'], nextVertex)
53420 .on([uiCmd('⌘['), 'home'], firstVertex)
53421 .on([uiCmd('⌘]'), 'end'], lastVertex)
53422 .on(['\\', 'pause'], nextParent)
53423 .on('⎋', esc, true)
53424 .on('space', toggleMenu);
53430 // deprecation warning - Radial Menu to be removed in iD v3
53431 editMenu = isRadialMenu
53432 ? uiRadialMenu(context, operations)
53433 : uiEditMenu(context, operations);
53435 context.ui().sidebar
53436 .select(singular() ? singular().id : null, newFeature);
53439 .on('undone.select', update)
53440 .on('redone.select', update);
53443 .on('move.select', closeMenu)
53444 .on('drawn.select', selectElements);
53447 .on('dblclick.select', dblclick);
53452 if (selectedIDs.length > 1) {
53453 var entities = uiSelectionList(context, selectedIDs);
53454 context.ui().sidebar.show(entities);
53458 var extent$$1 = geoExtent$$1(),
53459 graph = context.graph();
53460 selectedIDs.forEach(function(id) {
53461 var entity = context.entity(id);
53462 extent$$1._extend(entity.extent(graph));
53465 var loc = extent$$1.center();
53466 context.map().centerEase(loc);
53467 } else if (singular() && singular().type === 'way') {
53468 context.map().pan([0,0]); // full redraw, to adjust z-sorting #2914
53471 timeout$$1 = window.setTimeout(function() {
53473 if (!suppressMenu) {
53476 }, 270); /* after any centerEase completes */
53481 mode.exit = function() {
53482 if (timeout$$1) window.clearTimeout(timeout$$1);
53484 if (inspector) wrap.call(inspector.close);
53486 behaviors.forEach(function(behavior) {
53487 context.uninstall(behavior);
53492 editMenu = undefined;
53495 .on('undone.select', null)
53496 .on('redone.select', null);
53498 var surface = context.surface();
53501 .on('dblclick.select', null);
53504 .selectAll('.selected')
53505 .classed('selected', false);
53508 .selectAll('.related')
53509 .classed('related', false);
53511 context.map().on('drawn.select', null);
53512 context.ui().sidebar.hide();
53519 function uiAccount(context) {
53520 var connection = context.connection();
53523 function update(selection$$1) {
53524 if (!connection.authenticated()) {
53525 selection$$1.selectAll('#userLink, #logoutLink')
53526 .classed('hide', true);
53530 connection.userDetails(function(err, details) {
53531 var userLink = selection$$1.select('#userLink'),
53532 logoutLink = selection$$1.select('#logoutLink');
53535 logoutLink.html('');
53539 selection$$1.selectAll('#userLink, #logoutLink')
53540 .classed('hide', false);
53543 userLink.append('a')
53544 .attr('href', connection.userURL(details.display_name))
53545 .attr('target', '_blank');
53547 // Add thumbnail or dont
53548 if (details.image_url) {
53549 userLink.append('img')
53550 .attr('class', 'icon pre-text user-icon')
53551 .attr('src', details.image_url);
53554 .call(svgIcon('#icon-avatar', 'pre-text light'));
53558 userLink.append('span')
53559 .attr('class', 'label')
53560 .text(details.display_name);
53562 logoutLink.append('a')
53563 .attr('class', 'logout')
53566 .on('click.logout', function() {
53567 event.preventDefault();
53568 connection.logout();
53574 return function(selection$$1) {
53575 selection$$1.append('li')
53576 .attr('id', 'logoutLink')
53577 .classed('hide', true);
53579 selection$$1.append('li')
53580 .attr('id', 'userLink')
53581 .classed('hide', true);
53584 .on('change.account', function() { update(selection$$1); });
53586 update(selection$$1);
53590 function uiAttribution(context) {
53594 function attribution(data, klass) {
53595 var div = selection$$1.selectAll('.' + klass)
53600 .attr('class', klass)
53604 var background = div.selectAll('.attribution')
53605 .data(data, function(d) { return d.name(); });
53610 background = background.enter()
53612 .attr('class', 'attribution')
53613 .each(function(d) {
53614 if (d.terms_html) {
53616 .html(d.terms_html);
53620 var source = d.terms_text || d.id || d.name();
53623 source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
53629 .attr('href', d.terms_url)
53630 .attr('target', '_blank')
53637 .merge(background);
53640 var copyright = background.selectAll('.copyright-notice')
53641 .data(function(d) {
53642 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
53643 return notice ? [notice] : [];
53649 copyright = copyright.enter()
53651 .attr('class', 'copyright-notice')
53659 function update() {
53660 attribution([context.background().baseLayerSource()], 'base-layer-attribution');
53661 attribution(context.background().overlayLayerSources().filter(function (s) {
53662 return s.validZoom(context.map().zoom());
53663 }), 'overlay-layer-attribution');
53667 return function(select$$1) {
53668 selection$$1 = select$$1;
53670 context.background()
53671 .on('change.attribution', update);
53674 .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
53680 function rendererBackgroundSource(data) {
53681 var source = lodash.clone(data),
53683 name = source.name,
53684 best = !!source.best;
53686 source.scaleExtent = data.scaleExtent || [0, 20];
53687 source.overzoom = data.overzoom !== false;
53690 source.offset = function(_) {
53691 if (!arguments.length) return offset;
53697 source.nudge = function(_, zoomlevel) {
53698 offset[0] += _[0] / Math.pow(2, zoomlevel);
53699 offset[1] += _[1] / Math.pow(2, zoomlevel);
53704 source.name = function() {
53709 source.best = function() {
53714 source.area = function() {
53715 if (!data.polygon) return Number.MAX_VALUE; // worldwide
53716 var area$$1 = area({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
53717 return isNaN(area$$1) ? 0 : area$$1;
53721 source.imageryUsed = function() {
53722 return name || source.id;
53726 source.url = function(coord) {
53727 return data.template
53728 .replace('{x}', coord[0])
53729 .replace('{y}', coord[1])
53730 // TMS-flipped y coordinate
53731 .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
53732 .replace(/\{z(oom)?\}/, coord[2])
53733 .replace(/\{switch:([^}]+)\}/, function(s, r) {
53734 var subdomains = r.split(',');
53735 return subdomains[(coord[0] + coord[1]) % subdomains.length];
53737 .replace('{u}', function() {
53739 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
53741 var mask = 1 << (zoom$$1 - 1);
53742 if ((coord[0] & mask) !== 0) b++;
53743 if ((coord[1] & mask) !== 0) b += 2;
53751 source.intersects = function(extent$$1) {
53752 extent$$1 = extent$$1.polygon();
53753 return !data.polygon || data.polygon.some(function(polygon) {
53754 return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
53759 source.validZoom = function(z) {
53760 return source.scaleExtent[0] <= z &&
53761 (source.overzoom || source.scaleExtent[1] > z);
53765 source.isLocatorOverlay = function() {
53766 return source.id === 'mapbox_locator_overlay';
53770 source.copyrightNotices = function() {};
53777 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
53778 // http://msdn.microsoft.com/en-us/library/ff701716.aspx
53779 // http://msdn.microsoft.com/en-us/library/ff701701.aspx
53781 data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
53783 var bing = rendererBackgroundSource(data),
53784 key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
53785 url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
53786 key + '&jsonp={callback}',
53789 jsonpRequest(url, function(json$$1) {
53790 providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
53792 attribution: provider.attribution,
53793 areas: provider.coverageAreas.map(function(area$$1) {
53795 zoom: [area$$1.zoomMin, area$$1.zoomMax],
53796 extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
53801 dispatch$$1.call('change');
53804 bing.copyrightNotices = function(zoom$$1, extent$$1) {
53805 zoom$$1 = Math.min(zoom$$1, 21);
53806 return providers.filter(function(provider) {
53807 return lodash.some(provider.areas, function(area$$1) {
53808 return extent$$1.intersects(area$$1.extent) &&
53809 area$$1.zoom[0] <= zoom$$1 &&
53810 area$$1.zoom[1] >= zoom$$1;
53812 }).map(function(provider) {
53813 return provider.attribution;
53817 bing.logo = 'bing_maps.png';
53818 bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
53824 rendererBackgroundSource.None = function() {
53825 var source = rendererBackgroundSource({ id: 'none', template: '' });
53827 source.name = function() {
53828 return t('background.none');
53831 source.imageryUsed = function() {
53835 source.area = function() {
53836 return -1; // sources in background pane are sorted by area
53843 rendererBackgroundSource.Custom = function(template) {
53844 var source = rendererBackgroundSource({ id: 'custom', template: template });
53846 source.name = function() {
53847 return t('background.custom');
53850 source.imageryUsed = function() {
53851 return 'Custom (' + template + ')';
53854 source.area = function() {
53855 return -2; // sources in background pane are sorted by area
53861 function rendererTileLayer(context) {
53862 var tileSize = 256,
53863 tile = d3geoTile(),
53868 transformProp = utilPrefixCSSProperty('Transform'),
53869 source = rendererBackgroundSource.None();
53872 // blacklist overlay tiles around Null Island..
53873 function nearNullIsland(x, y, z) {
53875 var center = Math.pow(2, z - 1),
53876 width = Math.pow(2, z - 6),
53877 min$$1 = center - (width / 2),
53878 max$$1 = center + (width / 2) - 1;
53879 return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
53885 function tileSizeAtZoom(d, z) {
53886 var epsilon = 0.002;
53887 return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
53891 function atZoom(t, distance) {
53892 var power = Math.pow(2, distance);
53894 Math.floor(t[0] * power),
53895 Math.floor(t[1] * power),
53900 function lookUp(d) {
53901 for (var up = -1; up > -d[2]; up--) {
53902 var tile = atZoom(d, up);
53903 if (cache[source.url(tile)] !== false) {
53910 function uniqueBy(a, n) {
53911 var o = [], seen = {};
53912 for (var i = 0; i < a.length; i++) {
53913 if (seen[a[i][n]] === undefined) {
53915 seen[a[i][n]] = true;
53922 function addSource(d) {
53923 d.push(source.url(d));
53928 // Update tiles based on current state of `projection`.
53929 function background(selection$$1) {
53930 tile.scale(projection.scale() * 2 * Math.PI)
53931 .translate(projection.translate());
53934 projection.scale() * Math.PI - projection.translate()[0],
53935 projection.scale() * Math.PI - projection.translate()[1]];
53937 z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
53939 render(selection$$1);
53943 // Derive the tiles onscreen, remove those offscreen and position them.
53944 // Important that this part not depend on `projection` because it's
53945 // rentered when tiles load/error (see #644).
53946 function render(selection$$1) {
53948 var showDebug = context.getDebug('tile') && !source.overlay;
53950 if (source.validZoom(z)) {
53951 tile().forEach(function(d) {
53953 if (d[3] === '') return;
53954 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
53956 if (cache[d[3]] === false && lookUp(d)) {
53957 requests.push(addSource(lookUp(d)));
53961 requests = uniqueBy(requests, 3).filter(function(r) {
53962 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
53965 // don't re-request tiles which have failed in the past
53966 return cache[r[3]] !== false;
53970 var pixelOffset = [
53971 source.offset()[0] * Math.pow(2, z),
53972 source.offset()[1] * Math.pow(2, z)
53976 cache[d[3]] = true;
53980 .classed('tile-loaded', true);
53981 render(selection$$1);
53984 function error(d) {
53985 cache[d[3]] = false;
53990 render(selection$$1);
53993 function imageTransform(d) {
53994 var _ts = tileSize * Math.pow(2, z - d[2]);
53995 var scale = tileSizeAtZoom(d, z);
53996 return 'translate(' +
53997 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
53998 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
53999 'scale(' + scale + ',' + scale + ')';
54002 function debugTransform(d) {
54003 var _ts = tileSize * Math.pow(2, z - d[2]);
54004 var scale = tileSizeAtZoom(d, z);
54005 return 'translate(' +
54006 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
54007 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
54011 var image = selection$$1.selectAll('img')
54012 .data(requests, function(d) { return d[3]; });
54015 .style(transformProp, imageTransform)
54016 .classed('tile-removing', true)
54018 var tile = select(this);
54019 window.setTimeout(function() {
54020 if (tile.classed('tile-removing')) {
54028 .attr('class', 'tile')
54029 .attr('src', function(d) { return d[3]; })
54030 .on('error', error)
54033 .style(transformProp, imageTransform)
54034 .classed('tile-debug', showDebug)
54035 .classed('tile-removing', false);
54038 var debug = selection$$1.selectAll('.tile-label-debug')
54039 .data(showDebug ? requests : [], function(d) { return d[3]; });
54046 .attr('class', 'tile-label-debug')
54048 .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
54049 .style(transformProp, debugTransform);
54053 background.projection = function(_) {
54054 if (!arguments.length) return projection;
54060 background.dimensions = function(_) {
54061 if (!arguments.length) return tile.size();
54067 background.source = function(_) {
54068 if (!arguments.length) return source;
54071 tile.scaleExtent(source.scaleExtent);
54079 function rendererBackground(context) {
54080 var dispatch$$1 = dispatch('change'),
54081 baseLayer = rendererTileLayer(context).projection(context.projection),
54082 overlayLayers = [],
54086 function findSource(id) {
54087 return lodash.find(backgroundSources, function(d) {
54088 return d.id && d.id === id;
54093 function background(selection$$1) {
54094 var base = selection$$1.selectAll('.layer-background')
54098 .insert('div', '.layer-data')
54099 .attr('class', 'layer layer-background')
54103 var overlays = selection$$1.selectAll('.layer-overlay')
54104 .data(overlayLayers, function(d) { return d.source().name(); });
54110 .insert('div', '.layer-data')
54111 .attr('class', 'layer layer-overlay')
54113 .each(function(layer) { select(this).call(layer); });
54117 background.updateImagery = function() {
54118 if (context.inIntro()) return;
54120 var b = background.baseLayerSource(),
54122 .filter(function (d) { return !d.source().isLocatorOverlay(); })
54123 .map(function (d) { return d.source().id; })
54125 meters = geoOffsetToMeters(b.offset()),
54127 x = +meters[0].toFixed(2),
54128 y = +meters[1].toFixed(2),
54129 q = utilStringQs(window.location.hash.substring(1));
54132 if (id === 'custom') {
54133 id = 'custom:' + b.template;
54139 delete q.background;
54148 if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
54149 q.offset = x + ',' + y;
54154 window.location.replace('#' + utilQsString(q, true));
54156 var imageryUsed = [b.imageryUsed()];
54159 .filter(function (d) { return !d.source().isLocatorOverlay(); })
54160 .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); });
54162 var gpx = context.layers().layer('gpx');
54163 if (gpx && gpx.enabled() && gpx.hasGpx()) {
54164 imageryUsed.push('Local GPX');
54167 var mapillary_images = context.layers().layer('mapillary-images');
54168 if (mapillary_images && mapillary_images.enabled()) {
54169 imageryUsed.push('Mapillary Images');
54172 var mapillary_signs = context.layers().layer('mapillary-signs');
54173 if (mapillary_signs && mapillary_signs.enabled()) {
54174 imageryUsed.push('Mapillary Signs');
54177 context.history().imageryUsed(imageryUsed);
54181 background.sources = function(extent$$1) {
54182 return backgroundSources.filter(function(source) {
54183 return source.intersects(extent$$1);
54188 background.dimensions = function(_) {
54190 baseLayer.dimensions(_);
54192 overlayLayers.forEach(function(layer) {
54193 layer.dimensions(_);
54198 background.baseLayerSource = function(d) {
54199 if (!arguments.length) return baseLayer.source();
54201 // test source against OSM imagery blacklists..
54202 var blacklists = context.connection().imageryBlacklists();
54208 for (i = 0; i < blacklists.length; i++) {
54210 regex = new RegExp(blacklists[i]);
54211 fail = regex.test(d.template);
54219 // ensure at least one test was run.
54221 regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*');
54222 fail = regex.test(d.template);
54225 baseLayer.source(!fail ? d : rendererBackgroundSource.None());
54226 dispatch$$1.call('change');
54227 background.updateImagery();
54232 background.bing = function() {
54233 background.baseLayerSource(findSource('Bing'));
54237 background.showsLayer = function(d) {
54238 return d.id === baseLayer.source().id ||
54239 overlayLayers.some(function(layer) { return d.id === layer.source().id; });
54243 background.overlayLayerSources = function() {
54244 return overlayLayers.map(function (l) { return l.source(); });
54248 background.toggleOverlayLayer = function(d) {
54251 for (var i = 0; i < overlayLayers.length; i++) {
54252 layer = overlayLayers[i];
54253 if (layer.source() === d) {
54254 overlayLayers.splice(i, 1);
54255 dispatch$$1.call('change');
54256 background.updateImagery();
54261 layer = rendererTileLayer(context)
54263 .projection(context.projection)
54264 .dimensions(baseLayer.dimensions());
54266 overlayLayers.push(layer);
54267 dispatch$$1.call('change');
54268 background.updateImagery();
54272 background.nudge = function(d, zoom$$1) {
54273 baseLayer.source().nudge(d, zoom$$1);
54274 dispatch$$1.call('change');
54275 background.updateImagery();
54280 background.offset = function(d) {
54281 if (!arguments.length) return baseLayer.source().offset();
54282 baseLayer.source().offset(d);
54283 dispatch$$1.call('change');
54284 background.updateImagery();
54289 background.init = function() {
54290 function parseMap(qmap) {
54291 if (!qmap) return false;
54292 var args = qmap.split('/').map(Number);
54293 if (args.length < 3 || args.some(isNaN)) return false;
54294 return geoExtent$$1([args[2], args[1]]);
54297 var dataImagery = data.imagery || [],
54298 q = utilStringQs(window.location.hash.substring(1)),
54299 chosen = q.background || q.layer,
54300 extent$$1 = parseMap(q.map),
54303 backgroundSources = dataImagery.map(function(source) {
54304 if (source.type === 'bing') {
54305 return rendererBackgroundSource.Bing(source, dispatch$$1);
54307 return rendererBackgroundSource(source);
54311 backgroundSources.unshift(rendererBackgroundSource.None());
54313 if (!chosen && extent$$1) {
54314 best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
54317 if (chosen && chosen.indexOf('custom:') === 0) {
54318 background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
54320 background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
54323 var locator = lodash.find(backgroundSources, function(d) {
54324 return d.overlay && d.default;
54328 background.toggleOverlayLayer(locator);
54331 var overlays = (q.overlays || '').split(',');
54332 overlays.forEach(function(overlay) {
54333 overlay = findSource(overlay);
54335 background.toggleOverlayLayer(overlay);
54340 var gpx = context.layers().layer('gpx');
54347 var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
54348 return !isNaN(n) && n;
54351 if (offset.length === 2) {
54352 background.offset(geoMetersToOffset(offset));
54358 return utilRebind(background, dispatch$$1, 'on');
54361 function rendererFeatures(context) {
54362 var traffic_roads = {
54364 'motorway_link': true,
54366 'trunk_link': true,
54368 'primary_link': true,
54370 'secondary_link': true,
54372 'tertiary_link': true,
54373 'residential': true,
54374 'unclassified': true,
54375 'living_street': true
54378 var service_roads = {
54390 'pedestrian': true,
54394 var past_futures = {
54396 'construction': true,
54398 'dismantled': true,
54401 'demolished': true,
54402 'obliterated': true
54405 var dispatch$$1 = dispatch('change', 'redraw'),
54414 function update() {
54415 _hidden = features.hidden();
54416 dispatch$$1.call('change');
54417 dispatch$$1.call('redraw');
54421 function defineFeature(k, filter, max$$1) {
54425 enabled: true, // whether the user wants it enabled..
54427 currentMax: (max$$1 || Infinity),
54428 defaultMax: (max$$1 || Infinity),
54429 enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
54430 disable: function() { this.enabled = false; this.currentMax = 0; },
54431 hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
54432 autoHidden: function() { return this.hidden() && this.currentMax > 0; }
54437 defineFeature('points', function isPoint(entity, resolver, geometry) {
54438 return geometry === 'point';
54441 defineFeature('traffic_roads', function isTrafficRoad(entity) {
54442 return traffic_roads[entity.tags.highway];
54445 defineFeature('service_roads', function isServiceRoad(entity) {
54446 return service_roads[entity.tags.highway];
54449 defineFeature('paths', function isPath(entity) {
54450 return paths[entity.tags.highway];
54453 defineFeature('buildings', function isBuilding(entity) {
54455 !!entity.tags['building:part'] ||
54456 (!!entity.tags.building && entity.tags.building !== 'no') ||
54457 entity.tags.amenity === 'shelter' ||
54458 entity.tags.parking === 'multi-storey' ||
54459 entity.tags.parking === 'sheds' ||
54460 entity.tags.parking === 'carports' ||
54461 entity.tags.parking === 'garage_boxes'
54465 defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
54466 return geometry === 'area' &&
54467 !_features.buildings.filter(entity) &&
54468 !_features.water.filter(entity);
54471 defineFeature('boundaries', function isBoundary(entity) {
54472 return !!entity.tags.boundary;
54475 defineFeature('water', function isWater(entity) {
54477 !!entity.tags.waterway ||
54478 entity.tags.natural === 'water' ||
54479 entity.tags.natural === 'coastline' ||
54480 entity.tags.natural === 'bay' ||
54481 entity.tags.landuse === 'pond' ||
54482 entity.tags.landuse === 'basin' ||
54483 entity.tags.landuse === 'reservoir' ||
54484 entity.tags.landuse === 'salt_pond'
54488 defineFeature('rail', function isRail(entity) {
54490 !!entity.tags.railway ||
54491 entity.tags.landuse === 'railway'
54493 traffic_roads[entity.tags.highway] ||
54494 service_roads[entity.tags.highway] ||
54495 paths[entity.tags.highway]
54499 defineFeature('power', function isPower(entity) {
54500 return !!entity.tags.power;
54503 // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
54504 defineFeature('past_future', function isPastFuture(entity) {
54506 traffic_roads[entity.tags.highway] ||
54507 service_roads[entity.tags.highway] ||
54508 paths[entity.tags.highway]
54509 ) { return false; }
54511 var strings = Object.keys(entity.tags);
54513 for (var i = 0; i < strings.length; i++) {
54514 var s = strings[i];
54515 if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
54520 // Lines or areas that don't match another feature filter.
54521 // IMPORTANT: The 'others' feature must be the last one defined,
54522 // so that code in getMatches can skip this test if `hasMatch = true`
54523 defineFeature('others', function isOther(entity, resolver, geometry) {
54524 return (geometry === 'line' || geometry === 'area');
54528 function features() {}
54531 features.features = function() {
54536 features.keys = function() {
54541 features.enabled = function(k) {
54542 if (!arguments.length) {
54543 return _keys.filter(function(k) { return _features[k].enabled; });
54545 return _features[k] && _features[k].enabled;
54549 features.disabled = function(k) {
54550 if (!arguments.length) {
54551 return _keys.filter(function(k) { return !_features[k].enabled; });
54553 return _features[k] && !_features[k].enabled;
54557 features.hidden = function(k) {
54558 if (!arguments.length) {
54559 return _keys.filter(function(k) { return _features[k].hidden(); });
54561 return _features[k] && _features[k].hidden();
54565 features.autoHidden = function(k) {
54566 if (!arguments.length) {
54567 return _keys.filter(function(k) { return _features[k].autoHidden(); });
54569 return _features[k] && _features[k].autoHidden();
54573 features.enable = function(k) {
54574 if (_features[k] && !_features[k].enabled) {
54575 _features[k].enable();
54581 features.disable = function(k) {
54582 if (_features[k] && _features[k].enabled) {
54583 _features[k].disable();
54589 features.toggle = function(k) {
54590 if (_features[k]) {
54591 (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
54597 features.resetStats = function() {
54598 for (var i = 0; i < _keys.length; i++) {
54599 _features[_keys[i]].count = 0;
54601 dispatch$$1.call('change');
54605 features.gatherStats = function(d, resolver, dimensions) {
54606 var needsRedraw = false,
54607 type = lodash.groupBy(d, function(ent) { return ent.type; }),
54608 entities = [].concat(type.relation || [], type.way || [], type.node || []),
54609 currHidden, geometry, matches, i, j;
54611 for (i = 0; i < _keys.length; i++) {
54612 _features[_keys[i]].count = 0;
54615 // adjust the threshold for point/building culling based on viewport size..
54616 // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
54617 _cullFactor = dimensions[0] * dimensions[1] / 1000000;
54619 for (i = 0; i < entities.length; i++) {
54620 geometry = entities[i].geometry(resolver);
54621 if (!(geometry === 'vertex' || geometry === 'relation')) {
54622 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
54623 for (j = 0; j < matches.length; j++) {
54624 _features[matches[j]].count++;
54629 currHidden = features.hidden();
54630 if (currHidden !== _hidden) {
54631 _hidden = currHidden;
54632 needsRedraw = true;
54633 dispatch$$1.call('change');
54636 return needsRedraw;
54640 features.stats = function() {
54641 for (var i = 0; i < _keys.length; i++) {
54642 _stats[_keys[i]] = _features[_keys[i]].count;
54649 features.clear = function(d) {
54650 for (var i = 0; i < d.length; i++) {
54651 features.clearEntity(d[i]);
54656 features.clearEntity = function(entity) {
54657 delete _cache[osmEntity$$1.key(entity)];
54661 features.reset = function() {
54666 features.getMatches = function(entity, resolver, geometry) {
54667 if (geometry === 'vertex' || geometry === 'relation') return {};
54669 var ent = osmEntity$$1.key(entity);
54670 if (!_cache[ent]) {
54674 if (!_cache[ent].matches) {
54678 for (var i = 0; i < _keys.length; i++) {
54679 if (_keys[i] === 'others') {
54680 if (hasMatch) continue;
54682 // Multipolygon members:
54684 // 1. is a way that hasn't matched other 'interesting' feature rules,
54685 // 2. and it belongs to a single parent multipolygon relation
54686 // ...then match whatever feature rules the parent multipolygon has matched.
54687 // see #2548, #2887
54690 // For this to work, getMatches must be called on relations before ways.
54692 if (entity.type === 'way') {
54693 var parents = features.getParents(entity, resolver, geometry);
54694 if (parents.length === 1 && parents[0].isMultipolygon()) {
54695 var pkey = osmEntity$$1.key(parents[0]);
54696 if (_cache[pkey] && _cache[pkey].matches) {
54697 matches = lodash.clone(_cache[pkey].matches);
54704 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
54705 matches[_keys[i]] = hasMatch = true;
54708 _cache[ent].matches = matches;
54711 return _cache[ent].matches;
54715 features.getParents = function(entity, resolver, geometry) {
54716 if (geometry === 'point') return [];
54718 var ent = osmEntity$$1.key(entity);
54719 if (!_cache[ent]) {
54723 if (!_cache[ent].parents) {
54725 if (geometry === 'vertex') {
54726 parents = resolver.parentWays(entity);
54727 } else { // 'line', 'area', 'relation'
54728 parents = resolver.parentRelations(entity);
54730 _cache[ent].parents = parents;
54732 return _cache[ent].parents;
54736 features.isHiddenFeature = function(entity, resolver, geometry) {
54737 if (!_hidden.length) return false;
54738 if (!entity.version) return false;
54740 var matches = features.getMatches(entity, resolver, geometry);
54742 for (var i = 0; i < _hidden.length; i++) {
54743 if (matches[_hidden[i]]) return true;
54749 features.isHiddenChild = function(entity, resolver, geometry) {
54750 if (!_hidden.length) return false;
54751 if (!entity.version || geometry === 'point') return false;
54753 var parents = features.getParents(entity, resolver, geometry);
54754 if (!parents.length) return false;
54756 for (var i = 0; i < parents.length; i++) {
54757 if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
54765 features.hasHiddenConnections = function(entity, resolver) {
54766 if (!_hidden.length) return false;
54767 var childNodes, connections;
54769 if (entity.type === 'midpoint') {
54770 childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
54773 childNodes = entity.nodes ? resolver.childNodes(entity) : [];
54774 connections = features.getParents(entity, resolver, entity.geometry(resolver));
54777 // gather ways connected to child nodes..
54778 connections = lodash.reduce(childNodes, function(result, e) {
54779 return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
54782 return connections.length ? lodash.some(connections, function(e) {
54783 return features.isHidden(e, resolver, e.geometry(resolver));
54788 features.isHidden = function(entity, resolver, geometry) {
54789 if (!_hidden.length) return false;
54790 if (!entity.version) return false;
54792 var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
54793 return fn(entity, resolver, geometry);
54797 features.filter = function(d, resolver) {
54798 if (!_hidden.length) return d;
54801 for (var i = 0; i < d.length; i++) {
54803 if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
54804 result.push(entity);
54811 return utilRebind(features, dispatch$$1, 'on');
54814 function utilBindOnce(target, type, listener, capture) {
54815 var typeOnce = type + '.once';
54817 target.on(typeOnce, null);
54818 listener.apply(this, arguments);
54820 target.on(typeOnce, one, capture);
54824 function rendererMap(context) {
54826 var dimensions = [1, 1],
54827 dispatch$$1 = dispatch('move', 'drawn'),
54828 projection = context.projection,
54829 curtainProjection = context.curtainProjection,
54830 dblclickEnabled = true,
54831 redrawEnabled = true,
54832 transformStart = projection.transform(),
54834 transformed = false,
54836 drawLayers = svgLayers(projection, context),
54837 drawPoints = svgPoints$$1(projection, context),
54838 drawVertices = svgVertices$$1(projection, context),
54839 drawLines = svgLines$$1(projection, context),
54840 drawAreas = svgAreas$$1(projection, context),
54841 drawMidpoints = svgMidpoints$$1(projection, context),
54842 drawLabels = svgLabels(projection, context),
54843 supersurface = select(null),
54844 wrapper = select(null),
54845 surface = select(null),
54849 var zoom$$1 = zoom()
54850 .scaleExtent([ztok(2), ztok(24)])
54851 .interpolate(interpolateValue)
54852 .filter(zoomEventFilter)
54853 .on('zoom', zoomPan);
54855 var _selection = select(null);
54858 function map$$1(selection$$1) {
54860 _selection = selection$$1;
54863 .on('change.map', immediateRedraw);
54865 context.connection()
54866 .on('change.map', immediateRedraw);
54869 .on('change.map', immediateRedraw)
54870 .on('undone.map redone.map', function(stack$$1) {
54871 var mode = context.mode().id;
54872 if (mode !== 'browse' && mode !== 'select') return;
54874 var followSelected = false;
54875 if (Array.isArray(stack$$1.selectedIDs)) {
54876 followSelected = (stack$$1.selectedIDs.length === 1 && stack$$1.selectedIDs[0][0] === 'n');
54878 modeSelect(context, stack$$1.selectedIDs).follow(followSelected)
54881 if (!followSelected && stack$$1.transform) {
54882 map$$1.transformEase(stack$$1.transform);
54886 context.background()
54887 .on('change.map', immediateRedraw);
54890 .on('redraw.map', immediateRedraw);
54893 .on('change.map', function() {
54894 context.background().updateImagery();
54899 .on('dblclick.map', dblClick)
54901 .call(zoom$$1.transform, projection.transform());
54903 supersurface = selection$$1.append('div')
54904 .attr('id', 'supersurface')
54905 .call(utilSetTransform, 0, 0);
54907 // Need a wrapper div because Opera can't cope with an absolutely positioned
54908 // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
54909 wrapper = supersurface
54911 .attr('class', 'layer layer-data');
54913 map$$1.surface = surface = wrapper
54915 .selectAll('.surface')
54916 .attr('id', 'surface');
54919 .call(drawLabels.observe)
54920 .on('mousedown.zoom', function() {
54921 if (event.button === 2) {
54922 event.stopPropagation();
54925 .on('mouseup.zoom', function() {
54926 if (resetTransform()) immediateRedraw();
54928 .on('mousemove.map', function() {
54931 .on('mouseover.vertices', function() {
54932 if (map$$1.editable() && !transformed) {
54933 var hover = event.target.__data__;
54934 surface.selectAll('.data-layer-osm')
54935 .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
54936 dispatch$$1.call('drawn', this, {full: false});
54939 .on('mouseout.vertices', function() {
54940 if (map$$1.editable() && !transformed) {
54941 var hover = event.relatedTarget && event.relatedTarget.__data__;
54942 surface.selectAll('.data-layer-osm')
54943 .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
54944 dispatch$$1.call('drawn', this, {full: false});
54949 .call(context.background());
54951 context.on('enter.map', function() {
54952 if (map$$1.editable() && !transformed) {
54953 var all = context.intersects(map$$1.extent()),
54954 filter = utilFunctor(true),
54955 graph = context.graph();
54957 all = context.features().filter(all, graph);
54958 surface.selectAll('.data-layer-osm')
54959 .call(drawVertices, graph, all, filter, map$$1.extent(), map$$1.zoom())
54960 .call(drawMidpoints, graph, all, filter, map$$1.trimmedExtent());
54961 dispatch$$1.call('drawn', this, {full: false});
54965 map$$1.dimensions(utilGetDimensions(selection$$1));
54969 function zoomEventFilter() {
54970 // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
54971 // Intercept `mousedown` and check if there is an orphaned zoom gesture.
54972 // This can happen if a previous `mousedown` occurred without a `mouseup`.
54973 // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
54974 // so that d3-zoom won't stop propagation of new `mousedown` events.
54975 if (event.type === 'mousedown') {
54976 var hasOrphan = false;
54977 var listeners = window.__on;
54978 for (var i = 0; i < listeners.length; i++) {
54979 var listener = listeners[i];
54980 if (listener.name === 'zoom' && listener.type === 'mouseup') {
54986 var event$$1 = window.CustomEvent;
54988 event$$1 = new event$$1('mouseup');
54990 event$$1 = window.document.createEvent('Event');
54991 event$$1.initEvent('mouseup', false, false);
54993 // Event needs to be dispatched with an event.view property.
54994 event$$1.view = window;
54995 window.dispatchEvent(event$$1);
54999 return event.button !== 2; // ignore right clicks
55004 return 256 * Math.pow(2, z);
55008 return Math.max(Math.log(k) / Math.LN2 - 8, 0);
55011 function pxCenter() {
55012 return [dimensions[0] / 2, dimensions[1] / 2];
55016 function drawVector(difference, extent$$1) {
55017 var graph = context.graph(),
55018 features = context.features(),
55019 all = context.intersects(map$$1.extent()),
55023 var complete = difference.complete(map$$1.extent());
55024 data = lodash.compact(lodash.values(complete));
55025 filter = function(d) { return d.id in complete; };
55026 features.clear(data);
55029 // force a full redraw if gatherStats detects that a feature
55030 // should be auto-hidden (e.g. points or buildings)..
55031 if (features.gatherStats(all, graph, dimensions)) {
55032 extent$$1 = undefined;
55036 data = context.intersects(map$$1.extent().intersection(extent$$1));
55037 var set$$1 = set$2(lodash.map(data, 'id'));
55038 filter = function(d) { return set$$1.has(d.id); };
55042 filter = utilFunctor(true);
55046 data = features.filter(data, graph);
55048 surface.selectAll('.data-layer-osm')
55049 .call(drawVertices, graph, data, filter, map$$1.extent(), map$$1.zoom())
55050 .call(drawLines, graph, data, filter)
55051 .call(drawAreas, graph, data, filter)
55052 .call(drawMidpoints, graph, data, filter, map$$1.trimmedExtent())
55053 .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
55054 .call(drawPoints, graph, data, filter);
55056 dispatch$$1.call('drawn', this, {full: true});
55060 function editOff() {
55061 context.features().resetStats();
55062 surface.selectAll('.layer-osm *').remove();
55063 dispatch$$1.call('drawn', this, {full: true});
55067 function dblClick() {
55068 if (!dblclickEnabled) {
55069 event.preventDefault();
55070 event.stopImmediatePropagation();
55075 function zoomPan(manualEvent) {
55076 var event$$1 = (manualEvent || event),
55077 source = event$$1.sourceEvent,
55078 eventTransform = event$$1.transform;
55080 if (transformStart.x === eventTransform.x &&
55081 transformStart.y === eventTransform.y &&
55082 transformStart.k === eventTransform.k) {
55083 return; // no change
55086 // Normalize mousewheel - #3029
55087 // If wheel delta is provided in LINE units, recalculate it in PIXEL units
55088 // We are essentially redoing the calculations that occur here:
55089 // https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203
55090 // See this for more info:
55091 // https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js
55092 if (source && source.type === 'wheel' && source.deltaMode === 1 /* LINE */) {
55093 // pick sensible scroll amount if user scrolling fast or slow..
55094 var lines = Math.abs(source.deltaY),
55095 scroll = lines > 2 ? 40 : lines * 10;
55097 var t0 = transformed ? transformLast : transformStart,
55098 p0 = mouse$$1(source),
55099 p1 = t0.invert(p0),
55100 k2 = t0.k * Math.pow(2, -source.deltaY * scroll / 500),
55101 x2 = p0[0] - p1[0] * k2,
55102 y2 = p0[1] - p1[1] * k2;
55104 eventTransform = identity$8.translate(x2,y2).scale(k2);
55105 _selection.node().__zoom = eventTransform;
55108 if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
55109 surface.interrupt();
55110 uiFlash().text(t('cannot_zoom'));
55111 setZoom(context.minEditableZoom(), true);
55113 dispatch$$1.call('move', this, map$$1);
55117 projection.transform(eventTransform);
55119 var scale = eventTransform.k / transformStart.k,
55120 tX = (eventTransform.x / scale - transformStart.x) * scale,
55121 tY = (eventTransform.y / scale - transformStart.y) * scale;
55123 if (context.inIntro()) {
55124 curtainProjection.transform({
55125 x: eventTransform.x - tX,
55126 y: eventTransform.y - tY,
55127 k: eventTransform.k
55131 transformed = true;
55132 transformLast = eventTransform;
55133 utilSetTransform(supersurface, tX, tY, scale);
55136 dispatch$$1.call('move', this, map$$1);
55140 function resetTransform() {
55141 if (!transformed) return false;
55143 // deprecation warning - Radial Menu to be removed in iD v3
55144 surface.selectAll('.edit-menu, .radial-menu').interrupt().remove();
55145 utilSetTransform(supersurface, 0, 0);
55146 transformed = false;
55147 if (context.inIntro()) {
55148 curtainProjection.transform(projection.transform());
55154 function redraw(difference, extent$$1) {
55155 if (surface.empty() || !redrawEnabled) return;
55157 // If we are in the middle of a zoom/pan, we can't do differenced redraws.
55158 // It would result in artifacts where differenced entities are redrawn with
55159 // one transform and unchanged entities with another.
55160 if (resetTransform()) {
55161 difference = extent$$1 = undefined;
55164 var z = String(~~map$$1.zoom());
55165 if (surface.attr('data-zoom') !== z) {
55166 surface.attr('data-zoom', z)
55167 .classed('low-zoom', z <= 16);
55171 supersurface.call(context.background());
55178 if (map$$1.editable()) {
55179 context.loadTiles(projection, dimensions);
55180 drawVector(difference, extent$$1);
55185 transformStart = projection.transform();
55191 var queueRedraw = lodash.throttle(redraw, 750);
55194 var immediateRedraw = function(difference, extent$$1) {
55195 if (!difference && !extent$$1) queueRedraw.cancel();
55196 redraw(difference, extent$$1);
55200 function pointLocation(p) {
55201 var translate = projection.translate(),
55202 scale = projection.scale() * 2 * Math.PI;
55203 return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
55207 function locationPoint(l) {
55208 var translate = projection.translate(),
55209 scale = projection.scale() * 2 * Math.PI;
55210 return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
55214 map$$1.mouse = function() {
55215 var event$$1 = mousemove || event;
55218 while ((s = event$$1.sourceEvent)) { event$$1 = s; }
55219 return mouse$$1(event$$1);
55225 map$$1.mouseCoordinates = function() {
55226 return projection.invert(map$$1.mouse());
55230 map$$1.dblclickEnable = function(_) {
55231 if (!arguments.length) return dblclickEnabled;
55232 dblclickEnabled = _;
55237 map$$1.redrawEnable = function(_) {
55238 if (!arguments.length) return redrawEnabled;
55244 function setTransform(t2, duration, force) {
55245 var t$$1 = projection.transform();
55246 if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) {
55253 .duration(duration)
55254 .on('start', function() { map$$1.startEase(); })
55255 .call(zoom$$1.transform, identity$8.translate(t2.x, t2.y).scale(t2.k));
55257 projection.transform(t2);
55258 transformStart = t2;
55259 _selection.call(zoom$$1.transform, transformStart);
55264 function setZoom(z2, force, duration) {
55265 if (z2 === map$$1.zoom() && !force) {
55269 var k = projection.scale(),
55270 k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
55271 center = pxCenter(),
55272 l = pointLocation(center);
55274 projection.scale(k2);
55276 var t$$1 = projection.translate();
55277 l = locationPoint(l);
55279 t$$1[0] += center[0] - l[0];
55280 t$$1[1] += center[1] - l[1];
55283 projection.scale(k); // reset scale
55286 .duration(duration)
55287 .on('start', function() { map$$1.startEase(); })
55288 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k2));
55290 projection.translate(t$$1);
55291 transformStart = projection.transform();
55292 _selection.call(zoom$$1.transform, transformStart);
55299 function setCenter(loc2, duration) {
55300 var c = map$$1.center();
55301 if (loc2[0] === c[0] && loc2[1] === c[1]) {
55305 var t$$1 = projection.translate(),
55306 k = projection.scale(),
55308 ll = projection(loc2);
55310 t$$1[0] = t$$1[0] - ll[0] + pxC[0];
55311 t$$1[1] = t$$1[1] - ll[1] + pxC[1];
55316 .duration(duration)
55317 .on('start', function() { map$$1.startEase(); })
55318 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k));
55320 projection.translate(t$$1);
55321 transformStart = projection.transform();
55322 _selection.call(zoom$$1.transform, transformStart);
55329 map$$1.pan = function(delta, duration) {
55330 var t$$1 = projection.translate(),
55331 k = projection.scale();
55333 t$$1[0] += delta[0];
55334 t$$1[1] += delta[1];
55339 .duration(duration)
55340 .on('start', function() { map$$1.startEase(); })
55341 .call(zoom$$1.transform, identity$8.translate(t$$1[0], t$$1[1]).scale(k));
55343 projection.translate(t$$1);
55344 transformStart = projection.transform();
55345 _selection.call(zoom$$1.transform, transformStart);
55346 dispatch$$1.call('move', this, map$$1);
55354 map$$1.dimensions = function(_) {
55355 if (!arguments.length) return dimensions;
55356 var center = map$$1.center();
55358 drawLayers.dimensions(dimensions);
55359 context.background().dimensions(dimensions);
55360 projection.clipExtent([[0, 0], dimensions]);
55361 mouse$$1 = utilFastMouse(supersurface.node());
55369 function zoomIn(delta) {
55370 setZoom(~~map$$1.zoom() + delta, true, 250);
55373 function zoomOut(delta) {
55374 setZoom(~~map$$1.zoom() - delta, true, 250);
55377 map$$1.zoomIn = function() { zoomIn(1); };
55378 map$$1.zoomInFurther = function() { zoomIn(4); };
55380 map$$1.zoomOut = function() { zoomOut(1); };
55381 map$$1.zoomOutFurther = function() { zoomOut(4); };
55384 map$$1.center = function(loc2) {
55385 if (!arguments.length) {
55386 return projection.invert(pxCenter());
55389 if (setCenter(loc2)) {
55390 dispatch$$1.call('move', this, map$$1);
55398 map$$1.zoom = function(z2) {
55399 if (!arguments.length) {
55400 return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0);
55403 if (z2 < minzoom) {
55404 surface.interrupt();
55405 uiFlash().text(t('cannot_zoom'));
55406 z2 = context.minEditableZoom();
55410 dispatch$$1.call('move', this, map$$1);
55418 map$$1.zoomTo = function(entity, zoomLimits) {
55419 var extent$$1 = entity.extent(context.graph());
55420 if (!isFinite(extent$$1.area())) return;
55422 var z2 = map$$1.trimmedExtentZoom(extent$$1);
55423 zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
55424 map$$1.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
55428 map$$1.centerZoom = function(loc2, z2) {
55429 var centered = setCenter(loc2),
55430 zoomed = setZoom(z2);
55432 if (centered || zoomed) {
55433 dispatch$$1.call('move', this, map$$1);
55441 map$$1.centerEase = function(loc2, duration) {
55442 duration = duration || 250;
55443 setCenter(loc2, duration);
55448 map$$1.zoomEase = function(z2, duration) {
55449 duration = duration || 250;
55450 setZoom(z2, false, duration);
55455 map$$1.transformEase = function(t2, duration) {
55456 duration = duration || 250;
55457 setTransform(t2, duration, false);
55462 map$$1.startEase = function() {
55463 utilBindOnce(surface, 'mousedown.ease', function() {
55464 map$$1.cancelEase();
55470 map$$1.cancelEase = function() {
55471 _selection.interrupt();
55476 map$$1.extent = function(_) {
55477 if (!arguments.length) {
55478 return new geoExtent$$1(projection.invert([0, dimensions[1]]),
55479 projection.invert([dimensions[0], 0]));
55481 var extent$$1 = geoExtent$$1(_);
55482 map$$1.centerZoom(extent$$1.center(), map$$1.extentZoom(extent$$1));
55487 map$$1.trimmedExtent = function(_) {
55488 if (!arguments.length) {
55489 var headerY = 60, footerY = 30, pad = 10;
55490 return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]),
55491 projection.invert([dimensions[0] - pad, headerY + pad]));
55493 var extent$$1 = geoExtent$$1(_);
55494 map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
55499 function calcZoom(extent$$1, dim) {
55500 var tl = projection([extent$$1[0][0], extent$$1[1][1]]),
55501 br = projection([extent$$1[1][0], extent$$1[0][1]]);
55503 // Calculate maximum zoom that fits extent
55504 var hFactor = (br[0] - tl[0]) / dim[0],
55505 vFactor = (br[1] - tl[1]) / dim[1],
55506 hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
55507 vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
55508 newZoom = map$$1.zoom() - Math.max(hZoomDiff, vZoomDiff);
55514 map$$1.extentZoom = function(_) {
55515 return calcZoom(geoExtent$$1(_), dimensions);
55519 map$$1.trimmedExtentZoom = function(_) {
55520 var trimY = 120, trimX = 40,
55521 trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
55522 return calcZoom(geoExtent$$1(_), trimmed);
55526 map$$1.editable = function() {
55527 return map$$1.zoom() >= context.minEditableZoom();
55531 map$$1.minzoom = function(_) {
55532 if (!arguments.length) return minzoom;
55538 map$$1.layers = drawLayers;
55541 return utilRebind(map$$1, dispatch$$1, 'on');
55544 var TAU = 2 * Math.PI;
55545 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
55546 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
55547 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
55548 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
55551 function uiMapInMap(context) {
55555 function map_in_map(selection$$1) {
55556 var backgroundLayer = rendererTileLayer(context),
55557 overlayLayers = {},
55558 projection = geoRawMercator(),
55559 gpxLayer = svgGpx(projection, context).showLabels(false),
55560 debugLayer = svgDebug(projection, context),
55562 .scaleExtent([ztok(0.5), ztok(24)])
55563 .on('start', zoomStarted)
55564 .on('zoom', zoomed)
55565 .on('end', zoomEnded),
55566 isTransformed = false,
55568 skipEvents = false,
55570 zDiff = 6, // by default, minimap renders at (main zoom - 6)
55571 wrap = select(null),
55572 tiles = select(null),
55573 viewport = select(null),
55574 tStart, // transform at start of gesture
55575 tCurr, // transform at most recent event
55579 function zoomStarted() {
55580 if (skipEvents) return;
55581 tStart = tCurr = projection.transform();
55586 function zoomed() {
55587 if (skipEvents) return;
55589 var x = event.transform.x,
55590 y = event.transform.y,
55591 k = event.transform.k,
55592 isZooming = (k !== tStart.k),
55593 isPanning = (x !== tStart.x || y !== tStart.y);
55595 if (!isZooming && !isPanning) {
55596 return; // no change
55599 // lock in either zooming or panning, don't allow both in minimap.
55601 gesture = isZooming ? 'zoom' : 'pan';
55604 var tMini = projection.transform(),
55607 if (gesture === 'zoom') {
55608 var dMini = utilGetDimensions(wrap),
55609 cMini = vecScale(dMini, 0.5);
55610 scale = k / tMini.k;
55611 tX = (cMini[0] / scale - cMini[0]) * scale;
55612 tY = (cMini[1] / scale - cMini[1]) * scale;
55620 utilSetTransform(tiles, tX, tY, scale);
55621 utilSetTransform(viewport, 0, 0, scale);
55622 isTransformed = true;
55623 tCurr = identity$8.translate(x, y).scale(k);
55625 var zMain = ktoz(context.projection.scale()),
55628 zDiff = zMain - zMini;
55634 function zoomEnded() {
55635 if (skipEvents) return;
55636 if (gesture !== 'pan') return;
55638 updateProjection();
55640 var dMini = utilGetDimensions(wrap),
55641 cMini = vecScale(dMini, 0.5);
55642 context.map().center(projection.invert(cMini)); // recenter main map..
55646 function updateProjection() {
55647 var loc = context.map().center(),
55648 dMini = utilGetDimensions(wrap),
55649 cMini = vecScale(dMini, 0.5),
55650 tMain = context.projection.transform(),
55651 zMain = ktoz(tMain.k),
55652 zMini = Math.max(zMain - zDiff, 0.5),
55653 kMini = ztok(zMini);
55656 .translate([tMain.x, tMain.y])
55659 var point = projection(loc),
55660 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
55661 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
55662 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
55665 .translate([xMini, yMini])
55666 .clipExtent([[0, 0], dMini]);
55668 tCurr = projection.transform();
55670 if (isTransformed) {
55671 utilSetTransform(tiles, 0, 0);
55672 utilSetTransform(viewport, 0, 0);
55673 isTransformed = false;
55677 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
55680 wrap.call(zoom$$1.transform, tCurr);
55681 skipEvents = false;
55685 function redraw() {
55686 clearTimeout(timeoutId);
55687 if (isHidden) return;
55689 updateProjection();
55691 var dMini = utilGetDimensions(wrap),
55692 zMini = ktoz(projection.scale());
55694 // setup tile container
55696 .selectAll('.map-in-map-tiles')
55699 tiles = tiles.enter()
55701 .attr('class', 'map-in-map-tiles')
55704 // redraw background
55706 .source(context.background().baseLayerSource())
55707 .projection(projection)
55708 .dimensions(dMini);
55710 var background = tiles
55711 .selectAll('.map-in-map-background')
55716 .attr('class', 'map-in-map-background')
55718 .call(backgroundLayer);
55722 var overlaySources = context.background().overlayLayerSources();
55723 var activeOverlayLayers = [];
55724 for (var i = 0; i < overlaySources.length; i++) {
55725 if (overlaySources[i].validZoom(zMini)) {
55726 if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
55727 activeOverlayLayers.push(overlayLayers[i]
55728 .source(overlaySources[i])
55729 .projection(projection)
55730 .dimensions(dMini));
55734 var overlay = tiles
55735 .selectAll('.map-in-map-overlay')
55738 overlay = overlay.enter()
55740 .attr('class', 'map-in-map-overlay')
55744 var overlays = overlay
55746 .data(activeOverlayLayers, function(d) { return d.source().name(); });
55751 overlays = overlays.enter()
55754 .each(function(layer) { select(this).call(layer); });
55757 var dataLayers = tiles
55758 .selectAll('.map-in-map-data')
55764 dataLayers = dataLayers.enter()
55766 .attr('class', 'map-in-map-data')
55772 // redraw viewport bounding box
55773 if (gesture !== 'pan') {
55774 var getPath = index$4(projection),
55775 bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
55777 viewport = wrap.selectAll('.map-in-map-viewport')
55780 viewport = viewport.enter()
55782 .attr('class', 'map-in-map-viewport')
55786 var path$$1 = viewport.selectAll('.map-in-map-bbox')
55791 .attr('class', 'map-in-map-bbox')
55793 .attr('d', getPath)
55794 .classed('thick', function(d) { return getPath.area(d) < 30; });
55799 function queueRedraw() {
55800 clearTimeout(timeoutId);
55801 timeoutId = setTimeout(function() { redraw(); }, 750);
55805 function toggle() {
55806 if (event) event.preventDefault();
55808 isHidden = !isHidden;
55810 var label = select('.minimap-toggle');
55811 label.classed('active', !isHidden)
55812 .select('input').property('checked', !isHidden);
55816 .style('display', 'block')
55817 .style('opacity', '1')
55820 .style('opacity', '0')
55821 .on('end', function() {
55822 selection$$1.selectAll('.map-in-map')
55823 .style('display', 'none');
55827 .style('display', 'block')
55828 .style('opacity', '0')
55831 .style('opacity', '1')
55832 .on('end', function() {
55839 uiMapInMap.toggle = toggle;
55841 wrap = selection$$1.selectAll('.map-in-map')
55844 wrap = wrap.enter()
55846 .attr('class', 'map-in-map')
55847 .style('display', (isHidden ? 'none' : 'block'))
55849 .on('dblclick.zoom', null)
55853 .on('drawn.map-in-map', function(drawn) {
55854 if (drawn.full === true) {
55861 var keybinding = d3keybinding('map-in-map')
55871 function uiTooltipHtml(text, key, heading) {
55875 s += '<div class="tooltip-heading"><span>' + heading + '</span></div>';
55878 s += '<div class="tooltip-text"><span>' + text + '</span></div>';
55881 s += '<div class="keyhint-wrap"><span>' + t('tooltip_keyhint') + '</span>' +
55882 '<span class="keyhint">' + key + '</span></div>';
55888 function uiBackground(context) {
55890 detected = utilDetect(),
55891 opacities = [1, 0.75, 0.5, 0.25],
55893 ['right', [0.5, 0]],
55894 ['top', [0, -0.5]],
55895 ['left', [-0.5, 0]],
55896 ['bottom', [0, 0.5]]],
55897 opacityDefault = (context.storage('background-opacity') !== null) ?
55898 (+context.storage('background-opacity')) : 1.0,
55899 customTemplate = context.storage('background-custom-template') || '',
55902 // Can be 0 from <1.3.0 use or due to issue #1923.
55903 if (opacityDefault === 0) opacityDefault = 1.0;
55906 function background(selection$$1) {
55908 function sortSources(a, b) {
55909 return a.best() && !b.best() ? -1
55910 : b.best() && !a.best() ? 1
55911 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
55915 function setOpacity(d) {
55916 var bg = context.container().selectAll('.layer-background')
55918 .style('opacity', d)
55919 .attr('data-opacity', d);
55921 if (!detected.opera) {
55922 utilSetTransform(bg, 0, 0);
55925 opacityList.selectAll('li')
55926 .classed('active', function(_) { return _ === d; });
55928 context.storage('background-opacity', d);
55932 function setTooltips(selection$$1) {
55933 selection$$1.each(function(d, i, nodes) {
55934 var item = select(this).select('label'),
55935 span = item.select('span'),
55936 placement = (i < nodes.length / 2) ? 'bottom' : 'top',
55937 isOverflowing = (span.property('clientWidth') !== span.property('scrollWidth'));
55939 if (d === previous) {
55940 item.call(tooltip()
55941 .placement(placement)
55943 .title(function() {
55944 var tip = '<div>' + t('background.switch') + '</div>';
55945 return uiTooltipHtml(tip, uiCmd('⌘B'));
55948 } else if (d.description || isOverflowing) {
55949 item.call(tooltip()
55950 .placement(placement)
55951 .title(d.description || d.name())
55954 item.call(tooltip().destroy);
55960 function selectLayer() {
55961 function active$$1(d) {
55962 return context.background().showsLayer(d);
55965 content.selectAll('.layer, .custom_layer')
55966 .classed('active', active$$1)
55967 .classed('switch', function(d) { return d === previous; })
55969 .selectAll('input')
55970 .property('checked', active$$1);
55974 function clickSetSource(d) {
55975 event.preventDefault();
55976 previous = context.background().baseLayerSource();
55977 context.background().baseLayerSource(d);
55979 document.activeElement.blur();
55983 function editCustom() {
55984 event.preventDefault();
55985 var template = window.prompt(t('background.custom_prompt'), customTemplate);
55987 setCustom(template);
55994 function setCustom(template) {
55995 context.storage('background-custom-template', template);
55996 var d = rendererBackgroundSource.Custom(template);
55997 content.selectAll('.custom_layer').datum(d);
56002 function clickSetOverlay(d) {
56003 event.preventDefault();
56004 context.background().toggleOverlayLayer(d);
56006 document.activeElement.blur();
56010 function drawList(layerList, type, change, filter) {
56011 var sources = context.background()
56012 .sources(context.map().extent())
56015 var layerLinks = layerList.selectAll('li.layer')
56016 .data(sources, function(d) { return d.name(); });
56021 var enter = layerLinks.enter()
56022 .insert('li', '.custom_layer')
56023 .attr('class', 'layer')
56024 .classed('best', function(d) { return d.best(); });
56026 enter.filter(function(d) { return d.best(); })
56028 .attr('class', 'best')
56030 .title(t('background.best_imagery'))
56031 .placement((textDirection === 'rtl') ? 'right' : 'left'))
56040 .attr('type', type)
56041 .attr('name', 'layers')
56042 .on('change', change);
56046 .text(function(d) { return d.name(); });
56049 layerList.selectAll('li.layer')
56051 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
56055 function update() {
56056 backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
56057 overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
56061 var source = context.background().baseLayerSource();
56062 if (source.id === 'custom') {
56063 customTemplate = source.template;
56070 function updateOffsetVal() {
56071 var meters = geoOffsetToMeters(context.background().offset()),
56072 x = +meters[0].toFixed(2),
56073 y = +meters[1].toFixed(2);
56075 selectAll('.nudge-inner-rect')
56077 .classed('error', false)
56078 .property('value', x + ', ' + y);
56080 selectAll('.nudge-reset')
56081 .classed('disabled', function() {
56082 return (x === 0 && y === 0);
56087 function resetOffset() {
56088 if (event.button !== 0) return;
56089 context.background().offset([0, 0]);
56094 function nudge(d) {
56095 context.background().nudge(d, context.map().zoom());
56100 function buttonOffset(d) {
56101 if (event.button !== 0) return;
56102 var timeout$$1 = window.setTimeout(function() {
56103 interval$$1 = window.setInterval(nudge.bind(null, d), 100);
56107 function doneNudge() {
56108 window.clearTimeout(timeout$$1);
56109 window.clearInterval(interval$$1);
56111 .on('mouseup.buttonoffset', null, true)
56112 .on('mousedown.buttonoffset', null, true);
56116 .on('mouseup.buttonoffset', doneNudge, true)
56117 .on('mousedown.buttonoffset', doneNudge, true);
56123 function inputOffset() {
56124 if (event.button !== 0) return;
56125 var input = select(this);
56126 var d = input.node().value;
56128 if (d === '') return resetOffset();
56130 d = d.replace(/;/g, ',').split(',').map(function(n) {
56131 // if n is NaN, it will always get mapped to false.
56132 return !isNaN(n) && n;
56135 if (d.length !== 2 || !d[0] || !d[1]) {
56136 input.classed('error', true);
56140 context.background().offset(geoMetersToOffset(d));
56145 function dragOffset() {
56146 if (event.button !== 0) return;
56147 var origin = [event.clientX, event.clientY];
56149 context.container()
56151 .attr('class', 'nudge-surface');
56154 .on('mousemove.offset', function() {
56155 var latest = [event.clientX, event.clientY];
56157 -(origin[0] - latest[0]) / 4,
56158 -(origin[1] - latest[1]) / 4
56164 .on('mouseup.offset', function() {
56165 if (event.button !== 0) return;
56166 selectAll('.nudge-surface')
56170 .on('mousemove.offset', null)
56171 .on('mouseup.offset', null);
56174 event.preventDefault();
56183 function toggle() {
56184 if (event) event.preventDefault();
56185 tooltipBehavior.hide(button);
56186 setVisible(!button.classed('active'));
56190 function quickSwitch() {
56192 clickSetSource(previous);
56197 function setVisible(show) {
56198 if (show !== shown) {
56199 button.classed('active', show);
56204 .on('mousedown.background-inside', function() {
56205 event.stopPropagation();
56209 .style('display', 'block')
56210 .style('right', '-300px')
56213 .style('right', '0px');
56215 content.selectAll('.layer, .custom_layer')
56216 .call(setTooltips);
56220 .style('display', 'block')
56221 .style('right', '0px')
56224 .style('right', '-300px')
56225 .on('end', function() {
56226 select(this).style('display', 'none');
56230 .on('mousedown.background-inside', null);
56236 var content = selection$$1
56238 .attr('class', 'fillL map-overlay col3 content hide'),
56239 tooltipBehavior = tooltip()
56240 .placement((textDirection === 'rtl') ? 'right' : 'left')
56242 .title(uiTooltipHtml(t('background.description'), key)),
56243 button = selection$$1
56245 .attr('tabindex', -1)
56246 .on('click', toggle)
56247 .call(svgIcon('#icon-layers', 'light'))
56248 .call(tooltipBehavior),
56252 /* opacity switcher */
56254 var opawrap = content
56256 .attr('class', 'opacity-options-wrapper');
56260 .text(t('background.title'));
56262 var opacityList = opawrap
56264 .attr('class', 'opacity-options');
56266 opacityList.selectAll('div.opacity')
56270 .attr('data-original-title', function(d) {
56271 return t('background.percent_brightness', { opacity: (d * 100) });
56273 .on('click.set-opacity', setOpacity)
56274 .html('<div class="select-box"></div>')
56276 .placement((textDirection === 'rtl') ? 'right' : 'left'))
56278 .attr('class', 'opacity')
56279 .style('opacity', function(d) { return 1.25 - d; });
56282 /* background switcher */
56284 var backgroundList = content
56286 .attr('class', 'layer-list')
56287 .attr('dir', 'auto');
56289 var custom = backgroundList
56291 .attr('class', 'custom_layer')
56292 .datum(rendererBackgroundSource.Custom());
56296 .attr('class', 'layer-browse')
56298 .title(t('background.custom_button'))
56299 .placement((textDirection === 'rtl') ? 'right' : 'left'))
56300 .on('click', editCustom)
56301 .call(svgIcon('#icon-search'));
56308 .attr('type', 'radio')
56309 .attr('name', 'layers')
56310 .on('change', function () {
56311 if (customTemplate) {
56312 setCustom(customTemplate);
56320 .text(t('background.custom'));
56324 .attr('class', 'imagery-faq')
56326 .attr('target', '_blank')
56327 .attr('tabindex', -1)
56328 .call(svgIcon('#icon-out-link', 'inline'))
56329 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
56331 .text(t('background.imagery_source_faq'));
56333 var overlayList = content
56335 .attr('class', 'layer-list');
56337 var controls = content
56339 .attr('class', 'controls-list');
56342 /* minimap toggle */
56344 var minimapLabel = controls
56348 .title(uiTooltipHtml(t('background.minimap.tooltip'), '/'))
56353 .classed('minimap-toggle', true)
56355 .attr('type', 'checkbox')
56356 .on('change', function() {
56357 uiMapInMap.toggle();
56358 event.preventDefault();
56363 .text(t('background.minimap.description'));
56366 /* imagery offset controls */
56368 var adjustments = content
56370 .attr('class', 'adjustments');
56374 .text(t('background.fix_misalignment'))
56376 .classed('hide-toggle', true)
56377 .classed('expanded', false)
56378 .on('click', function() {
56379 if (event.button !== 0) return;
56380 var exp = select(this).classed('expanded');
56381 nudgeContainer.style('display', exp ? 'none' : 'block');
56382 select(this).classed('expanded', !exp);
56383 event.preventDefault();
56386 var nudgeContainer = adjustments
56388 .attr('class', 'nudge-container cf')
56389 .style('display', 'none');
56393 .attr('class', 'nudge-instructions')
56394 .text(t('background.offset'));
56396 var nudgeRect = nudgeContainer
56398 .attr('class', 'nudge-outer-rect')
56399 .on('mousedown', dragOffset);
56403 .attr('class', 'nudge-inner-rect')
56405 .on('change', inputOffset)
56406 .on('mousedown', function() {
56407 if (event.button !== 0) return;
56408 event.stopPropagation();
56413 .selectAll('button')
56414 .data(directions).enter()
56416 .attr('class', function(d) { return d[0] + ' nudge'; })
56417 .on('mousedown', function(d) {
56418 if (event.button !== 0) return;
56419 buttonOffset(d[1]);
56424 .attr('title', t('background.reset'))
56425 .attr('class', 'nudge-reset disabled')
56426 .on('click', resetOffset)
56428 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
56432 .on('move.background-update', lodash.debounce(update, 1000));
56434 context.background()
56435 .on('change.background-update', update);
56439 setOpacity(opacityDefault);
56441 var keybinding = d3keybinding('background')
56443 .on(uiCmd('⌘B'), quickSwitch)
56450 context.surface().on('mousedown.background-outside', hide);
56451 context.container().on('mousedown.background-outside', hide);
56457 function uiContributors(context) {
56458 var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
56461 wrap = select(null);
56464 function update() {
56466 entities = context.intersects(context.map().extent());
56468 entities.forEach(function(entity) {
56469 if (entity && entity.user) users[entity.user] = true;
56472 var u = Object.keys(users),
56473 subset = u.slice(0, u.length > limit ? limit - 1 : limit);
56476 .call(svgIcon('#icon-nearby', 'pre-text light'));
56478 var userList = select(document.createElement('span'));
56480 userList.selectAll()
56484 .attr('class', 'user-link')
56485 .attr('href', function(d) { return context.connection().userURL(d); })
56486 .attr('target', '_blank')
56487 .attr('tabindex', -1)
56490 if (u.length > limit) {
56491 var count = select(document.createElement('span'));
56494 .attr('target', '_blank')
56495 .attr('tabindex', -1)
56496 .attr('href', function() {
56497 return context.connection().changesetsURL(context.map().center(), context.map().zoom());
56499 .text(u.length - limit + 1);
56501 wrap.append('span')
56502 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
56505 wrap.append('span')
56506 .html(t('contributors.list', { users: userList.html() }));
56513 .style('opacity', 0);
56515 } else if (hidden) {
56518 .style('opacity', 1);
56523 return function(selection$$1) {
56524 wrap = selection$$1;
56527 context.connection().on('loaded.contributors', debouncedUpdate);
56528 context.map().on('move.contributors', debouncedUpdate);
56532 function uiFeatureInfo(context) {
56533 function update(selection$$1) {
56534 var features = context.features(),
56535 stats = features.stats(),
56537 hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
56540 return String(stats[k]) + ' ' + t('feature.' + k + '.description');
56544 selection$$1.html('');
56546 if (hiddenList.length) {
56547 var tooltipBehavior = tooltip()
56550 .title(function() {
56551 return uiTooltipHtml(hiddenList.join('<br/>'));
56554 var warning = selection$$1.append('a')
56556 .attr('tabindex', -1)
56557 .html(t('feature_info.hidden_warning', { count: count }))
56558 .call(tooltipBehavior)
56559 .on('click', function() {
56560 tooltipBehavior.hide(warning);
56561 // open map data panel?
56562 event.preventDefault();
56567 .classed('hide', !hiddenList.length);
56571 return function(selection$$1) {
56572 update(selection$$1);
56574 context.features().on('change.feature_info', function() {
56575 update(selection$$1);
56580 function uiFullScreen(context) {
56581 var element = context.container().node(),
56582 keybinding = d3keybinding('full-screen');
56586 function getFullScreenFn() {
56587 if (element.requestFullscreen) {
56588 return element.requestFullscreen;
56589 } else if (element.msRequestFullscreen) {
56590 return element.msRequestFullscreen;
56591 } else if (element.mozRequestFullScreen) {
56592 return element.mozRequestFullScreen;
56593 } else if (element.webkitRequestFullscreen) {
56594 return element.webkitRequestFullscreen;
56599 function getExitFullScreenFn() {
56600 if (document.exitFullscreen) {
56601 return document.exitFullscreen;
56602 } else if (document.msExitFullscreen) {
56603 return document.msExitFullscreen;
56604 } else if (document.mozCancelFullScreen) {
56605 return document.mozCancelFullScreen;
56606 } else if (document.webkitExitFullscreen) {
56607 return document.webkitExitFullscreen;
56612 function isFullScreen() {
56613 return document.fullscreenElement ||
56614 document.mozFullScreenElement ||
56615 document.webkitFullscreenElement ||
56616 document.msFullscreenElement;
56620 function isSupported() {
56621 return !!getFullScreenFn();
56625 function fullScreen() {
56626 event.preventDefault();
56627 if (!isFullScreen()) {
56628 // button.classed('active', true);
56629 getFullScreenFn().apply(element);
56631 // button.classed('active', false);
56632 getExitFullScreenFn().apply(document);
56637 return function() { // selection) {
56638 if (!isSupported())
56641 // button = selection.append('button')
56642 // .attr('title', t('full_screen'))
56643 // .attr('tabindex', -1)
56644 // .on('click', fullScreen)
56647 // button.append('span')
56648 // .attr('class', 'icon full-screen');
56651 .on('f11', fullScreen)
56652 .on(uiCmd('⌘⇧F'), fullScreen);
56659 function uiModal(selection$$1, blocking) {
56660 var keybinding = d3keybinding('modal');
56661 var previous = selection$$1.select('div.modal');
56662 var animate = previous.empty();
56664 previous.transition()
56666 .style('opacity', 0)
56669 var shaded = selection$$1
56671 .attr('class', 'shaded')
56672 .style('opacity', 0);
56674 shaded.close = function() {
56678 .style('opacity',0)
56684 .style('top','0px');
56692 .attr('class', 'modal fillL col6');
56695 shaded.on('click.remove-modal', function() {
56696 if (event.target === this) {
56701 modal.append('button')
56702 .attr('class', 'close')
56703 .on('click', shaded.close)
56704 .call(svgIcon('#icon-close'));
56707 .on('⌫', shaded.close)
56708 .on('⎋', shaded.close);
56716 .attr('class', 'content');
56719 shaded.transition().style('opacity', 1);
56721 shaded.style('opacity', 1);
56728 function uiLoading(context) {
56734 var loading = function(selection) {
56735 modalSelection = uiModal(selection, blocking);
56737 var loadertext = modalSelection.select('.content')
56738 .classed('loading-modal', true)
56740 .attr('class', 'modal-section fillL');
56744 .attr('class', 'loader')
56745 .attr('src', context.imagePath('loader-white.gif'));
56751 modalSelection.select('button.close')
56752 .attr('class', 'hide');
56758 loading.message = function(_) {
56759 if (!arguments.length) return message;
56765 loading.blocking = function(_) {
56766 if (!arguments.length) return blocking;
56772 loading.close = function() {
56773 modalSelection.remove();
56780 function uiGeolocate(context) {
56781 var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
56782 locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
56787 if (context.inIntro()) return;
56788 context.enter(modeBrowse(context));
56789 context.container().call(locating);
56790 navigator.geolocation.getCurrentPosition(success, error, geoOptions);
56792 // This timeout ensures that we still call finish() even if
56793 // the user declines to share their location in Firefox
56794 timeoutId = setTimeout(finish, 10000 /* 10sec */ );
56798 function success(position) {
56799 var map = context.map(),
56800 extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
56801 .padByMeters(position.coords.accuracy);
56803 map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
56813 function finish() {
56814 locating.close(); // unblock ui
56815 if (timeoutId) { clearTimeout(timeoutId); }
56816 timeoutId = undefined;
56820 return function(selection) {
56821 if (!navigator.geolocation) return;
56825 .attr('tabindex', -1)
56826 .attr('title', t('geolocate.title'))
56827 .on('click', click)
56828 .call(svgIcon('#icon-geolocate', 'light'))
56830 .placement((textDirection === 'rtl') ? 'right' : 'left'));
56834 var marked = createCommonjsModule(function (module, exports) {
56836 * marked - a markdown parser
56837 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
56838 * https://github.com/chjj/marked
56844 * Block-Level Grammar
56849 code: /^( {4}[^\n]+\n*)+/,
56851 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
56852 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
56854 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
56855 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
56856 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
56857 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
56858 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
56860 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
56864 block.bullet = /(?:[*+-]|\d+\.)/;
56865 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
56866 block.item = replace(block.item, 'gm')
56867 (/bull/g, block.bullet)
56870 block.list = replace(block.list)
56871 (/bull/g, block.bullet)
56872 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
56873 ('def', '\\n+(?=' + block.def.source + ')')
56876 block.blockquote = replace(block.blockquote)
56880 block._tag = '(?!(?:'
56881 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
56882 + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
56883 + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
56885 block.html = replace(block.html)
56886 ('comment', /<!--[\s\S]*?-->/)
56887 ('closed', /<(tag)[\s\S]+?<\/\1>/)
56888 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
56889 (/tag/g, block._tag)
56892 block.paragraph = replace(block.paragraph)
56894 ('heading', block.heading)
56895 ('lheading', block.lheading)
56896 ('blockquote', block.blockquote)
56897 ('tag', '<' + block._tag)
56902 * Normal Block Grammar
56905 block.normal = merge({}, block);
56908 * GFM Block Grammar
56911 block.gfm = merge({}, block.normal, {
56912 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
56914 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
56917 block.gfm.paragraph = replace(block.paragraph)
56919 + block.gfm.fences.source.replace('\\1', '\\2') + '|'
56920 + block.list.source.replace('\\1', '\\3') + '|')
56924 * GFM + Tables Block Grammar
56927 block.tables = merge({}, block.gfm, {
56928 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
56929 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
56936 function Lexer(options) {
56938 this.tokens.links = {};
56939 this.options = options || marked.defaults;
56940 this.rules = block.normal;
56942 if (this.options.gfm) {
56943 if (this.options.tables) {
56944 this.rules = block.tables;
56946 this.rules = block.gfm;
56952 * Expose Block Rules
56955 Lexer.rules = block;
56958 * Static Lex Method
56961 Lexer.lex = function(src, options) {
56962 var lexer = new Lexer(options);
56963 return lexer.lex(src);
56970 Lexer.prototype.lex = function(src) {
56972 .replace(/\r\n|\r/g, '\n')
56973 .replace(/\t/g, ' ')
56974 .replace(/\u00a0/g, ' ')
56975 .replace(/\u2424/g, '\n');
56977 return this.token(src, true);
56984 Lexer.prototype.token = function(src, top, bq) {
56985 var src = src.replace(/^ +$/gm, '')
56998 if (cap = this.rules.newline.exec(src)) {
56999 src = src.substring(cap[0].length);
57000 if (cap[0].length > 1) {
57008 if (cap = this.rules.code.exec(src)) {
57009 src = src.substring(cap[0].length);
57010 cap = cap[0].replace(/^ {4}/gm, '');
57013 text: !this.options.pedantic
57014 ? cap.replace(/\n+$/, '')
57021 if (cap = this.rules.fences.exec(src)) {
57022 src = src.substring(cap[0].length);
57032 if (cap = this.rules.heading.exec(src)) {
57033 src = src.substring(cap[0].length);
57036 depth: cap[1].length,
57042 // table no leading pipe (gfm)
57043 if (top && (cap = this.rules.nptable.exec(src))) {
57044 src = src.substring(cap[0].length);
57048 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
57049 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
57050 cells: cap[3].replace(/\n$/, '').split('\n')
57053 for (i = 0; i < item.align.length; i++) {
57054 if (/^ *-+: *$/.test(item.align[i])) {
57055 item.align[i] = 'right';
57056 } else if (/^ *:-+: *$/.test(item.align[i])) {
57057 item.align[i] = 'center';
57058 } else if (/^ *:-+ *$/.test(item.align[i])) {
57059 item.align[i] = 'left';
57061 item.align[i] = null;
57065 for (i = 0; i < item.cells.length; i++) {
57066 item.cells[i] = item.cells[i].split(/ *\| */);
57069 this.tokens.push(item);
57075 if (cap = this.rules.lheading.exec(src)) {
57076 src = src.substring(cap[0].length);
57079 depth: cap[2] === '=' ? 1 : 2,
57086 if (cap = this.rules.hr.exec(src)) {
57087 src = src.substring(cap[0].length);
57095 if (cap = this.rules.blockquote.exec(src)) {
57096 src = src.substring(cap[0].length);
57099 type: 'blockquote_start'
57102 cap = cap[0].replace(/^ *> ?/gm, '');
57104 // Pass `top` to keep the current
57105 // "toplevel" state. This is exactly
57106 // how markdown.pl works.
57107 this.token(cap, top, true);
57110 type: 'blockquote_end'
57117 if (cap = this.rules.list.exec(src)) {
57118 src = src.substring(cap[0].length);
57122 type: 'list_start',
57123 ordered: bull.length > 1
57126 // Get each top-level item.
57127 cap = cap[0].match(this.rules.item);
57133 for (; i < l; i++) {
57136 // Remove the list item's bullet
57137 // so it is seen as the next token.
57138 space = item.length;
57139 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
57141 // Outdent whatever the
57142 // list item contains. Hacky.
57143 if (~item.indexOf('\n ')) {
57144 space -= item.length;
57145 item = !this.options.pedantic
57146 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
57147 : item.replace(/^ {1,4}/gm, '');
57150 // Determine whether the next list item belongs here.
57151 // Backpedal if it does not belong in this list.
57152 if (this.options.smartLists && i !== l - 1) {
57153 b = block.bullet.exec(cap[i + 1])[0];
57154 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
57155 src = cap.slice(i + 1).join('\n') + src;
57160 // Determine whether item is loose or not.
57161 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
57162 // for discount behavior.
57163 loose = next || /\n\n(?!\s*$)/.test(item);
57165 next = item.charAt(item.length - 1) === '\n';
57166 if (!loose) loose = next;
57171 ? 'loose_item_start'
57172 : 'list_item_start'
57176 this.token(item, false, bq);
57179 type: 'list_item_end'
57191 if (cap = this.rules.html.exec(src)) {
57192 src = src.substring(cap[0].length);
57194 type: this.options.sanitize
57197 pre: !this.options.sanitizer
57198 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
57205 if ((!bq && top) && (cap = this.rules.def.exec(src))) {
57206 src = src.substring(cap[0].length);
57207 this.tokens.links[cap[1].toLowerCase()] = {
57215 if (top && (cap = this.rules.table.exec(src))) {
57216 src = src.substring(cap[0].length);
57220 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
57221 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
57222 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
57225 for (i = 0; i < item.align.length; i++) {
57226 if (/^ *-+: *$/.test(item.align[i])) {
57227 item.align[i] = 'right';
57228 } else if (/^ *:-+: *$/.test(item.align[i])) {
57229 item.align[i] = 'center';
57230 } else if (/^ *:-+ *$/.test(item.align[i])) {
57231 item.align[i] = 'left';
57233 item.align[i] = null;
57237 for (i = 0; i < item.cells.length; i++) {
57238 item.cells[i] = item.cells[i]
57239 .replace(/^ *\| *| *\| *$/g, '')
57243 this.tokens.push(item);
57248 // top-level paragraph
57249 if (top && (cap = this.rules.paragraph.exec(src))) {
57250 src = src.substring(cap[0].length);
57253 text: cap[1].charAt(cap[1].length - 1) === '\n'
57254 ? cap[1].slice(0, -1)
57261 if (cap = this.rules.text.exec(src)) {
57262 // Top-level should never reach here.
57263 src = src.substring(cap[0].length);
57273 Error('Infinite loop on byte: ' + src.charCodeAt(0));
57277 return this.tokens;
57281 * Inline-Level Grammar
57285 escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
57286 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
57288 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
57289 link: /^!?\[(inside)\]\(href\)/,
57290 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
57291 nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
57292 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
57293 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
57294 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
57295 br: /^ {2,}\n(?!\s*$)/,
57297 text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
57300 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
57301 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
57303 inline.link = replace(inline.link)
57304 ('inside', inline._inside)
57305 ('href', inline._href)
57308 inline.reflink = replace(inline.reflink)
57309 ('inside', inline._inside)
57313 * Normal Inline Grammar
57316 inline.normal = merge({}, inline);
57319 * Pedantic Inline Grammar
57322 inline.pedantic = merge({}, inline.normal, {
57323 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
57324 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
57328 * GFM Inline Grammar
57331 inline.gfm = merge({}, inline.normal, {
57332 escape: replace(inline.escape)('])', '~|])')(),
57333 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
57334 del: /^~~(?=\S)([\s\S]*?\S)~~/,
57335 text: replace(inline.text)
57337 ('|', '|https?://|')
57342 * GFM + Line Breaks Inline Grammar
57345 inline.breaks = merge({}, inline.gfm, {
57346 br: replace(inline.br)('{2,}', '*')(),
57347 text: replace(inline.gfm.text)('{2,}', '*')()
57351 * Inline Lexer & Compiler
57354 function InlineLexer(links, options) {
57355 this.options = options || marked.defaults;
57356 this.links = links;
57357 this.rules = inline.normal;
57358 this.renderer = this.options.renderer || new Renderer;
57359 this.renderer.options = this.options;
57363 Error('Tokens array requires a `links` property.');
57366 if (this.options.gfm) {
57367 if (this.options.breaks) {
57368 this.rules = inline.breaks;
57370 this.rules = inline.gfm;
57372 } else if (this.options.pedantic) {
57373 this.rules = inline.pedantic;
57378 * Expose Inline Rules
57381 InlineLexer.rules = inline;
57384 * Static Lexing/Compiling Method
57387 InlineLexer.output = function(src, links, options) {
57388 var inline = new InlineLexer(links, options);
57389 return inline.output(src);
57396 InlineLexer.prototype.output = function(src) {
57405 if (cap = this.rules.escape.exec(src)) {
57406 src = src.substring(cap[0].length);
57412 if (cap = this.rules.autolink.exec(src)) {
57413 src = src.substring(cap[0].length);
57414 if (cap[2] === '@') {
57415 text = cap[1].charAt(6) === ':'
57416 ? this.mangle(cap[1].substring(7))
57417 : this.mangle(cap[1]);
57418 href = this.mangle('mailto:') + text;
57420 text = escape(cap[1]);
57423 out += this.renderer.link(href, null, text);
57428 if (!this.inLink && (cap = this.rules.url.exec(src))) {
57429 src = src.substring(cap[0].length);
57430 text = escape(cap[1]);
57432 out += this.renderer.link(href, null, text);
57437 if (cap = this.rules.tag.exec(src)) {
57438 if (!this.inLink && /^<a /i.test(cap[0])) {
57439 this.inLink = true;
57440 } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
57441 this.inLink = false;
57443 src = src.substring(cap[0].length);
57444 out += this.options.sanitize
57445 ? this.options.sanitizer
57446 ? this.options.sanitizer(cap[0])
57453 if (cap = this.rules.link.exec(src)) {
57454 src = src.substring(cap[0].length);
57455 this.inLink = true;
57456 out += this.outputLink(cap, {
57460 this.inLink = false;
57465 if ((cap = this.rules.reflink.exec(src))
57466 || (cap = this.rules.nolink.exec(src))) {
57467 src = src.substring(cap[0].length);
57468 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
57469 link = this.links[link.toLowerCase()];
57470 if (!link || !link.href) {
57471 out += cap[0].charAt(0);
57472 src = cap[0].substring(1) + src;
57475 this.inLink = true;
57476 out += this.outputLink(cap, link);
57477 this.inLink = false;
57482 if (cap = this.rules.strong.exec(src)) {
57483 src = src.substring(cap[0].length);
57484 out += this.renderer.strong(this.output(cap[2] || cap[1]));
57489 if (cap = this.rules.em.exec(src)) {
57490 src = src.substring(cap[0].length);
57491 out += this.renderer.em(this.output(cap[2] || cap[1]));
57496 if (cap = this.rules.code.exec(src)) {
57497 src = src.substring(cap[0].length);
57498 out += this.renderer.codespan(escape(cap[2], true));
57503 if (cap = this.rules.br.exec(src)) {
57504 src = src.substring(cap[0].length);
57505 out += this.renderer.br();
57510 if (cap = this.rules.del.exec(src)) {
57511 src = src.substring(cap[0].length);
57512 out += this.renderer.del(this.output(cap[1]));
57517 if (cap = this.rules.text.exec(src)) {
57518 src = src.substring(cap[0].length);
57519 out += this.renderer.text(escape(this.smartypants(cap[0])));
57525 Error('Infinite loop on byte: ' + src.charCodeAt(0));
57536 InlineLexer.prototype.outputLink = function(cap, link) {
57537 var href = escape(link.href)
57538 , title = link.title ? escape(link.title) : null;
57540 return cap[0].charAt(0) !== '!'
57541 ? this.renderer.link(href, title, this.output(cap[1]))
57542 : this.renderer.image(href, title, escape(cap[1]));
57546 * Smartypants Transformations
57549 InlineLexer.prototype.smartypants = function(text) {
57550 if (!this.options.smartypants) return text;
57553 .replace(/---/g, '\u2014')
57555 .replace(/--/g, '\u2013')
57557 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
57558 // closing singles & apostrophes
57559 .replace(/'/g, '\u2019')
57561 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
57563 .replace(/"/g, '\u201d')
57565 .replace(/\.{3}/g, '\u2026');
57572 InlineLexer.prototype.mangle = function(text) {
57573 if (!this.options.mangle) return text;
57579 for (; i < l; i++) {
57580 ch = text.charCodeAt(i);
57581 if (Math.random() > 0.5) {
57582 ch = 'x' + ch.toString(16);
57584 out += '&#' + ch + ';';
57594 function Renderer(options) {
57595 this.options = options || {};
57598 Renderer.prototype.code = function(code, lang, escaped) {
57599 if (this.options.highlight) {
57600 var out = this.options.highlight(code, lang);
57601 if (out != null && out !== code) {
57608 return '<pre><code>'
57609 + (escaped ? code : escape(code, true))
57610 + '\n</code></pre>';
57613 return '<pre><code class="'
57614 + this.options.langPrefix
57615 + escape(lang, true)
57617 + (escaped ? code : escape(code, true))
57618 + '\n</code></pre>\n';
57621 Renderer.prototype.blockquote = function(quote) {
57622 return '<blockquote>\n' + quote + '</blockquote>\n';
57625 Renderer.prototype.html = function(html) {
57629 Renderer.prototype.heading = function(text, level, raw) {
57633 + this.options.headerPrefix
57634 + raw.toLowerCase().replace(/[^\w]+/g, '-')
57642 Renderer.prototype.hr = function() {
57643 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
57646 Renderer.prototype.list = function(body, ordered) {
57647 var type = ordered ? 'ol' : 'ul';
57648 return '<' + type + '>\n' + body + '</' + type + '>\n';
57651 Renderer.prototype.listitem = function(text) {
57652 return '<li>' + text + '</li>\n';
57655 Renderer.prototype.paragraph = function(text) {
57656 return '<p>' + text + '</p>\n';
57659 Renderer.prototype.table = function(header, body) {
57670 Renderer.prototype.tablerow = function(content) {
57671 return '<tr>\n' + content + '</tr>\n';
57674 Renderer.prototype.tablecell = function(content, flags) {
57675 var type = flags.header ? 'th' : 'td';
57676 var tag = flags.align
57677 ? '<' + type + ' style="text-align:' + flags.align + '">'
57678 : '<' + type + '>';
57679 return tag + content + '</' + type + '>\n';
57682 // span level renderer
57683 Renderer.prototype.strong = function(text) {
57684 return '<strong>' + text + '</strong>';
57687 Renderer.prototype.em = function(text) {
57688 return '<em>' + text + '</em>';
57691 Renderer.prototype.codespan = function(text) {
57692 return '<code>' + text + '</code>';
57695 Renderer.prototype.br = function() {
57696 return this.options.xhtml ? '<br/>' : '<br>';
57699 Renderer.prototype.del = function(text) {
57700 return '<del>' + text + '</del>';
57703 Renderer.prototype.link = function(href, title, text) {
57704 if (this.options.sanitize) {
57706 var prot = decodeURIComponent(unescape(href))
57707 .replace(/[^\w:]/g, '')
57712 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
57716 var out = '<a href="' + href + '"';
57718 out += ' title="' + title + '"';
57720 out += '>' + text + '</a>';
57724 Renderer.prototype.image = function(href, title, text) {
57725 var out = '<img src="' + href + '" alt="' + text + '"';
57727 out += ' title="' + title + '"';
57729 out += this.options.xhtml ? '/>' : '>';
57733 Renderer.prototype.text = function(text) {
57738 * Parsing & Compiling
57741 function Parser(options) {
57744 this.options = options || marked.defaults;
57745 this.options.renderer = this.options.renderer || new Renderer;
57746 this.renderer = this.options.renderer;
57747 this.renderer.options = this.options;
57751 * Static Parse Method
57754 Parser.parse = function(src, options, renderer) {
57755 var parser = new Parser(options, renderer);
57756 return parser.parse(src);
57763 Parser.prototype.parse = function(src) {
57764 this.inline = new InlineLexer(src.links, this.options, this.renderer);
57765 this.tokens = src.reverse();
57768 while (this.next()) {
57779 Parser.prototype.next = function() {
57780 return this.token = this.tokens.pop();
57784 * Preview Next Token
57787 Parser.prototype.peek = function() {
57788 return this.tokens[this.tokens.length - 1] || 0;
57792 * Parse Text Tokens
57795 Parser.prototype.parseText = function() {
57796 var body = this.token.text;
57798 while (this.peek().type === 'text') {
57799 body += '\n' + this.next().text;
57802 return this.inline.output(body);
57806 * Parse Current Token
57809 Parser.prototype.tok = function() {
57810 switch (this.token.type) {
57815 return this.renderer.hr();
57818 return this.renderer.heading(
57819 this.inline.output(this.token.text),
57824 return this.renderer.code(this.token.text,
57826 this.token.escaped);
57839 for (i = 0; i < this.token.header.length; i++) {
57840 flags = { header: true, align: this.token.align[i] };
57841 cell += this.renderer.tablecell(
57842 this.inline.output(this.token.header[i]),
57843 { header: true, align: this.token.align[i] }
57846 header += this.renderer.tablerow(cell);
57848 for (i = 0; i < this.token.cells.length; i++) {
57849 row = this.token.cells[i];
57852 for (j = 0; j < row.length; j++) {
57853 cell += this.renderer.tablecell(
57854 this.inline.output(row[j]),
57855 { header: false, align: this.token.align[j] }
57859 body += this.renderer.tablerow(cell);
57861 return this.renderer.table(header, body);
57863 case 'blockquote_start': {
57866 while (this.next().type !== 'blockquote_end') {
57867 body += this.tok();
57870 return this.renderer.blockquote(body);
57872 case 'list_start': {
57874 , ordered = this.token.ordered;
57876 while (this.next().type !== 'list_end') {
57877 body += this.tok();
57880 return this.renderer.list(body, ordered);
57882 case 'list_item_start': {
57885 while (this.next().type !== 'list_item_end') {
57886 body += this.token.type === 'text'
57891 return this.renderer.listitem(body);
57893 case 'loose_item_start': {
57896 while (this.next().type !== 'list_item_end') {
57897 body += this.tok();
57900 return this.renderer.listitem(body);
57903 var html = !this.token.pre && !this.options.pedantic
57904 ? this.inline.output(this.token.text)
57906 return this.renderer.html(html);
57908 case 'paragraph': {
57909 return this.renderer.paragraph(this.inline.output(this.token.text));
57912 return this.renderer.paragraph(this.parseText());
57921 function escape(html, encode) {
57923 .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
57924 .replace(/</g, '<')
57925 .replace(/>/g, '>')
57926 .replace(/"/g, '"')
57927 .replace(/'/g, ''');
57930 function unescape(html) {
57931 // explicitly match decimal, hex, and named HTML entities
57932 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
57933 n = n.toLowerCase();
57934 if (n === 'colon') return ':';
57935 if (n.charAt(0) === '#') {
57936 return n.charAt(1) === 'x'
57937 ? String.fromCharCode(parseInt(n.substring(2), 16))
57938 : String.fromCharCode(+n.substring(1));
57944 function replace(regex, opt) {
57945 regex = regex.source;
57947 return function self(name, val) {
57948 if (!name) return new RegExp(regex, opt);
57949 val = val.source || val;
57950 val = val.replace(/(^|[^\[])\^/g, '$1');
57951 regex = regex.replace(name, val);
57959 function merge(obj) {
57964 for (; i < arguments.length; i++) {
57965 target = arguments[i];
57966 for (key in target) {
57967 if (Object.prototype.hasOwnProperty.call(target, key)) {
57968 obj[key] = target[key];
57981 function marked(src, opt, callback) {
57982 if (callback || typeof opt === 'function') {
57988 opt = merge({}, marked.defaults, opt || {});
57990 var highlight = opt.highlight
57996 tokens = Lexer.lex(src, opt);
57998 return callback(e);
58001 pending = tokens.length;
58003 var done = function(err) {
58005 opt.highlight = highlight;
58006 return callback(err);
58012 out = Parser.parse(tokens, opt);
58017 opt.highlight = highlight;
58021 : callback(null, out);
58024 if (!highlight || highlight.length < 3) {
58028 delete opt.highlight;
58030 if (!pending) return done();
58032 for (; i < tokens.length; i++) {
58034 if (token.type !== 'code') {
58035 return --pending || done();
58037 return highlight(token.text, token.lang, function(err, code) {
58038 if (err) return done(err);
58039 if (code == null || code === token.text) {
58040 return --pending || done();
58043 token.escaped = true;
58044 --pending || done();
58052 if (opt) opt = merge({}, marked.defaults, opt);
58053 return Parser.parse(Lexer.lex(src, opt), opt);
58055 e.message += '\nPlease report this to https://github.com/chjj/marked.';
58056 if ((opt || marked.defaults).silent) {
58057 return '<p>An error occured:</p><pre>'
58058 + escape(e.message + '', true)
58070 marked.setOptions = function(opt) {
58071 merge(marked.defaults, opt);
58075 marked.defaults = {
58086 langPrefix: 'lang-',
58087 smartypants: false,
58089 renderer: new Renderer,
58097 marked.Parser = Parser;
58098 marked.parser = Parser.parse;
58100 marked.Renderer = Renderer;
58102 marked.Lexer = Lexer;
58103 marked.lexer = Lexer.lex;
58105 marked.InlineLexer = InlineLexer;
58106 marked.inlineLexer = InlineLexer.output;
58108 marked.parse = marked;
58111 module.exports = marked;
58114 }).call(function() {
58115 return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
58119 function pointBox(loc, context) {
58120 var rect = context.surfaceRect();
58121 var point = context.curtainProjection(loc);
58123 left: point[0] + rect.left - 40,
58124 top: point[1] + rect.top - 60,
58131 function pad$1(locOrBox, padding, context) {
58133 if (locOrBox instanceof Array) {
58134 var rect = context.surfaceRect();
58135 var point = context.curtainProjection(locOrBox);
58137 left: point[0] + rect.left,
58138 top: point[1] + rect.top
58145 left: box.left - padding,
58146 top: box.top - padding,
58147 width: (box.width || 0) + 2 * padding,
58148 height: (box.width || 0) + 2 * padding
58153 function icon(name, svgklass) {
58154 return '<svg class="icon ' + (svgklass || '') + '">' +
58155 '<use xlink:href="' + name + '"></use></svg>';
58159 function slugify(text$$1) {
58160 return text$$1.toString().toLowerCase()
58161 .replace(/\s+/g, '-') // Replace spaces with -
58162 .replace(/[^\w\-]+/g, '') // Remove all non-word chars
58163 .replace(/\-\-+/g, '-') // Replace multiple - with single -
58164 .replace(/^-+/, '') // Trim - from start of text
58165 .replace(/-+$/, ''); // Trim - from end of text
58169 // console warning for missing walkthrough names
58170 var missingStrings = {};
58171 function checkKey(key, text$$1) {
58172 if (t(key, { default: undefined}) === undefined) {
58173 if (missingStrings.hasOwnProperty(key)) return; // warn once
58174 missingStrings[key] = text$$1;
58175 var missing = key + ': ' + text$$1;
58176 if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line
58181 function localize(obj) {
58184 // Assign name if entity has one..
58185 var name = obj.tags && obj.tags.name;
58187 key = 'intro.graph.name.' + slugify(name);
58188 obj.tags.name = t(key, { default: name });
58189 checkKey(key, name);
58192 // Assign street name if entity has one..
58193 var street = obj.tags && obj.tags['addr:street'];
58195 key = 'intro.graph.name.' + slugify(street);
58196 obj.tags['addr:street'] = t(key, { default: street });
58197 checkKey(key, street);
58199 // Add address details common across walkthrough..
58201 'block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood',
58202 'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb'
58204 addrTags.forEach(function(k) {
58205 var key = 'intro.graph.' + k,
58207 val = obj.tags && obj.tags[tag],
58208 str = t(key, { default: val });
58211 if (str.match(/^<.*>$/) !== null) {
58212 delete obj.tags[tag];
58214 obj.tags[tag] = str;
58224 // Used to detect squareness.. some duplicataion of code from actionOrthogonalize.
58225 function isMostlySquare(points) {
58226 // note: uses 15 here instead of the 12 from actionOrthogonalize because
58227 // actionOrthogonalize can actually straighten some larger angles as it iterates
58228 var threshold = 15, // degrees within right or straight
58229 lowerBound = Math.cos((90 - threshold) * Math.PI / 180), // near right
58230 upperBound = Math.cos(threshold * Math.PI / 180), // near straight
58233 for (var i = 0; i < points.length; i++) {
58234 mag = Math.abs(normalizedDotProduct(i, points));
58235 if (mag > lowerBound && mag < upperBound) {
58243 function normalizedDotProduct(i, points) {
58244 var a = points[(i - 1 + points.length) % points.length],
58246 c = points[(i + 1) % points.length],
58247 p = subtractPoints(a, b),
58248 q = subtractPoints(c, b);
58250 p = normalizePoint(p);
58251 q = normalizePoint(q);
58253 return p[0] * q[0] + p[1] * q[1];
58256 function subtractPoints(a, b) {
58257 return [a[0] - b[0], a[1] - b[1]];
58260 function normalizePoint(point) {
58261 var vector = [0, 0];
58262 var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
58263 if (length !== 0) {
58264 vector[0] = point[0] / length;
58265 vector[1] = point[1] / length;
58273 function selectMenuItem(operation) {
58274 var selector$$1 = '.edit-menu .edit-menu-item-' + operation +
58275 ', .radial-menu .radial-menu-item-' + operation;
58276 return select(selector$$1);
58280 function transitionTime(point1, point2) {
58281 var distance = geoSphericalDistance(point1, point2);
58282 if (distance === 0)
58284 else if (distance < 80)
58290 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"}}};
58292 // toggles the visibility of ui elements, using a combination of the
58293 // hide class, which sets display=none, and a d3 transition for opacity.
58294 // this will cause blinking when called repeatedly, so check that the
58295 // value actually changes between calls.
58296 function uiToggle(show, callback) {
58297 return function(selection$$1) {
58299 .style('opacity', show ? 0 : 1)
58300 .classed('hide', false)
58302 .style('opacity', show ? 1 : 0)
58303 .on('end', function() {
58305 .classed('hide', !show)
58306 .style('opacity', null);
58307 if (callback) callback.apply(this);
58312 // Tooltips and svg mask used to highlight certain features
58313 function uiCurtain() {
58315 var surface = select(null),
58316 tooltip = select(null),
58317 darkness = select(null);
58319 function curtain(selection$$1) {
58320 surface = selection$$1
58322 .attr('id', 'curtain')
58323 .style('z-index', 1000)
58324 .style('pointer-events', 'none')
58325 .style('position', 'absolute')
58329 darkness = surface.append('path')
58332 .attr('class', 'curtain-darkness');
58334 select(window).on('resize.curtain', resize);
58336 tooltip = selection$$1.append('div')
58337 .attr('class', 'tooltip')
58338 .style('z-index', 1002);
58342 .attr('class', 'tooltip-arrow');
58346 .attr('class', 'tooltip-inner');
58351 function resize() {
58353 .attr('width', window.innerWidth)
58354 .attr('height', window.innerHeight);
58355 curtain.cut(darkness.datum());
58361 * Reveal cuts the curtain to highlight the given box,
58362 * and shows a tooltip with instructions next to the box.
58364 * @param {String|ClientRect} [box] box used to cut the curtain
58365 * @param {String} [text] text for a tooltip
58366 * @param {Object} [options]
58367 * @param {string} [options.tooltipClass] optional class to add to the tooltip
58368 * @param {integer} [options.duration] transition time in milliseconds
58369 * @param {string} [options.buttonText] if set, create a button with this text label
58370 * @param {function} [options.buttonCallback] if set, the callback for the button
58371 * @param {String|ClientRect} [options.tooltipBox] box for tooltip position, if different from box for the curtain
58373 curtain.reveal = function(box, text$$1, options) {
58374 if (typeof box === 'string') {
58375 box = select(box).node();
58377 if (box && box.getBoundingClientRect) {
58378 box = copyBox(box.getBoundingClientRect());
58381 options = options || {};
58384 if (options.tooltipBox) {
58385 tooltipBox = options.tooltipBox;
58386 if (typeof tooltipBox === 'string') {
58387 tooltipBox = select(tooltipBox).node();
58389 if (tooltipBox && tooltipBox.getBoundingClientRect) {
58390 tooltipBox = copyBox(tooltipBox.getBoundingClientRect());
58396 if (tooltipBox && text$$1) {
58397 // pseudo markdown bold text for the instruction section..
58398 var parts = text$$1.split('**');
58399 var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
58401 html$$1 += '<span class="instruction">' + parts[1] + '</span>';
58404 html$$1 = html$$1.replace(/\*(.*?)\*/g, '<em>$1</em>'); // emphasis
58405 html$$1 = html$$1.replace(/\{br\}/g, '<br/><br/>'); // linebreak
58407 if (options.buttonText && options.buttonCallback) {
58408 html$$1 += '<div class="button-section">' +
58409 '<button href="#" class="button action col8">' + options.buttonText + '</button></div>';
58412 var classes = 'curtain-tooltip tooltip in ' + (options.tooltipClass || '');
58414 .classed(classes, true)
58415 .selectAll('.tooltip-inner')
58418 if (options.buttonText && options.buttonCallback) {
58419 var button = tooltip.selectAll('.button-section .button.action');
58421 .on('click', function() {
58422 event.preventDefault();
58423 options.buttonCallback();
58427 var tip = copyBox(tooltip.node().getBoundingClientRect()),
58428 w = window.innerWidth,
58429 h = window.innerHeight,
58430 tooltipWidth = 200,
58435 // hack: this will have bottom placement,
58436 // so need to reserve extra space for the tooltip illustration.
58437 if (options.tooltipClass === 'intro-mouse') {
58441 // trim box dimensions to just the portion that fits in the window..
58442 if (tooltipBox.top + tooltipBox.height > h) {
58443 tooltipBox.height -= (tooltipBox.top + tooltipBox.height - h);
58445 if (tooltipBox.left + tooltipBox.width > w) {
58446 tooltipBox.width -= (tooltipBox.left + tooltipBox.width - w);
58449 // determine tooltip placement..
58451 if (tooltipBox.top + tooltipBox.height < 100) {
58452 // tooltip below box..
58455 tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
58456 tooltipBox.top + tooltipBox.height
58459 } else if (tooltipBox.top > h - 140) {
58460 // tooltip above box..
58463 tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
58464 tooltipBox.top - tip.height
58468 // tooltip to the side of the tooltipBox..
58469 var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2;
58471 if (textDirection === 'rtl') {
58472 if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) {
58474 pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
58478 pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
58482 if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
58484 pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
58488 pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
58493 if (options.duration !== 0 || !tooltip.classed(side)) {
58494 tooltip.call(uiToggle(true));
58498 .style('top', pos[1] + 'px')
58499 .style('left', pos[0] + 'px')
58500 .attr('class', classes + ' ' + side);
58503 // shift tooltip-inner if it is very close to the top or bottom edge
58504 // (doesn't affect the placement of the tooltip-arrow)
58506 if (side === 'left' || side === 'right') {
58508 shiftY = 60 - pos[1];
58510 else if (pos[1] + tip.height > h - 100) {
58511 shiftY = h - pos[1] - tip.height - 100;
58514 tooltip.selectAll('.tooltip-inner')
58515 .style('top', shiftY + 'px');
58519 .classed('in', false)
58520 .call(uiToggle(false));
58523 curtain.cut(box, options.duration);
58529 curtain.cut = function(datum, duration) {
58530 darkness.datum(datum)
58534 if (duration === 0) {
58535 selection$$1 = darkness;
58537 selection$$1 = darkness
58539 .duration(duration || 600)
58544 .attr('d', function(d) {
58545 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
58546 window.innerWidth + ',' + window.innerHeight + 'L' +
58547 window.innerWidth + ',0 Z';
58549 if (!d) return string;
58550 return string + 'M' +
58551 d.left + ',' + d.top + 'L' +
58552 d.left + ',' + (d.top + d.height) + 'L' +
58553 (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
58554 (d.left + d.width) + ',' + (d.top) + 'Z';
58560 curtain.remove = function() {
58563 select(window).on('resize.curtain', null);
58567 // ClientRects are immutable, so copy them to an object,
58568 // in case we need to trim the height/width.
58569 function copyBox(src) {
58573 bottom: src.bottom,
58584 function uiIntroWelcome(context, reveal) {
58585 var dispatch$$1 = dispatch('done'),
58586 listener = clickListener();
58589 title: 'intro.welcome.title'
58593 function welcome() {
58594 context.map().centerZoom([-85.63591, 41.94285], 19);
58595 reveal('.intro-nav-wrap .chapter-welcome',
58596 t('intro.welcome.welcome'),
58597 { buttonText: t('intro.ok'), buttonCallback: practice }
58601 function practice() {
58602 reveal('.intro-nav-wrap .chapter-welcome',
58603 t('intro.welcome.practice'),
58604 { buttonText: t('intro.ok'), buttonCallback: words }
58609 reveal('.intro-nav-wrap .chapter-welcome',
58610 t('intro.welcome.words'),
58611 { buttonText: t('intro.ok'), buttonCallback: mouse$$1 }
58616 function mouse$$1() {
58617 reveal('.intro-nav-wrap .chapter-welcome',
58618 t('intro.welcome.mouse'),
58619 { buttonText: t('intro.ok'), buttonCallback: leftClick }
58624 function leftClick() {
58628 var tooltip = reveal('.intro-nav-wrap .chapter-welcome',
58629 t('intro.welcome.leftclick', { num: times }),
58630 { tooltipClass: 'intro-mouse' }
58633 tooltip.selectAll('.tooltip-inner')
58634 .insert('svg', 'span')
58635 .attr('class', 'tooltip-illustration')
58637 .attr('xlink:href', '#walkthrough-mouse');
58641 .attr('class', 'counter');
58643 tooltip.call(listener);
58645 listener.on('click', function(which) {
58646 if (which === 'left') {
58647 select('.curtain-tooltip.intro-mouse .counter')
58648 .text(String(++counter));
58650 if (counter === times) {
58651 window.setTimeout(function() { continueTo(rightClick); }, 1000);
58656 function continueTo(nextStep) {
58657 listener.on('click', null);
58658 tooltip.call(listener.off);
58659 tooltip.select('.counter').remove();
58665 function rightClick() {
58669 var tooltip = reveal('.intro-nav-wrap .chapter-welcome',
58670 t('intro.welcome.rightclick', { num: times }),
58671 { tooltipClass: 'intro-mouse' }
58674 tooltip.selectAll('.tooltip-inner')
58675 .insert('svg', 'span')
58676 .attr('class', 'tooltip-illustration')
58678 .attr('xlink:href', '#walkthrough-mouse');
58682 .attr('class', 'counter');
58684 tooltip.call(listener);
58686 listener.on('click', function(which) {
58687 if (which === 'right') {
58688 select('.curtain-tooltip.intro-mouse .counter')
58689 .text(String(++counter));
58691 if (counter === times) {
58692 window.setTimeout(function() { continueTo(chapters); }, 1000);
58697 function continueTo(nextStep) {
58698 listener.on('click', null);
58699 tooltip.call(listener.off);
58700 tooltip.select('.counter').remove();
58706 function chapters() {
58707 dispatch$$1.call('done');
58708 reveal('.intro-nav-wrap .chapter-navigation',
58709 t('intro.welcome.chapters', { next: t('intro.navigation.title') })
58714 chapter.enter = function() {
58719 chapter.exit = function() {
58724 chapter.restart = function() {
58730 return utilRebind(chapter, dispatch$$1, 'on');
58735 function clickListener() {
58736 var dispatch$$1 = dispatch('click'),
58738 tooltip = select(null),
58741 // `down` keeps track of which buttons/keys are down.
58742 // Setting a property in `down` happens immediately.
58743 // Unsetting a property in `down` is delayed because
58744 // on Windows a contextmenu event happens after keyup/mouseup
58746 function keydown() {
58747 if (event.keyCode === 93) { // context menu
58748 event.preventDefault();
58749 event.stopPropagation();
58750 down.menu = event.timeStamp;
58751 tooltip.classed('rightclick', true);
58757 if (event.keyCode === 93) { // context menu
58758 event.preventDefault();
58759 event.stopPropagation();
58760 var endTime = event.timeStamp,
58761 startTime = down.menu || endTime,
58762 delay = (endTime - startTime < minTime) ? minTime : 0;
58764 window.setTimeout(function() {
58765 tooltip.classed('rightclick', false);
58766 down.menu = undefined; // delayed, for Windows
58769 dispatch$$1.call('click', this, 'right');
58774 function mousedown() {
58775 var button = event.button;
58776 if (button === 0 && !event.ctrlKey) {
58777 tooltip.classed('leftclick', true);
58778 } else if (button === 2) {
58779 tooltip.classed('rightclick', true);
58781 down[button] = event.timeStamp;
58785 function mouseup() {
58786 var button = event.button,
58787 endTime = event.timeStamp,
58788 startTime = down[button] || endTime,
58789 delay = (endTime - startTime < minTime) ? minTime : 0;
58791 if (button === 0 && !event.ctrlKey) {
58792 window.setTimeout(function() {
58793 tooltip.classed('leftclick', false);
58794 down[button] = undefined; // delayed, for Windows
58797 dispatch$$1.call('click', this, 'left');
58799 } else if (button === 2) {
58800 window.setTimeout(function() {
58801 tooltip.classed('rightclick', false);
58802 down[button] = undefined; // delayed, for Windows
58805 dispatch$$1.call('click', this, 'right');
58808 window.setTimeout(function() {
58809 down[button] = undefined; // delayed, for Windows
58815 function contextmenu() {
58816 event.preventDefault();
58817 event.stopPropagation();
58818 if (!down[2] && !down.menu) {
58819 tooltip.classed('rightclick', true);
58820 window.setTimeout(function() {
58821 tooltip.classed('rightclick', false);
58823 dispatch$$1.call('click', this, 'right');
58828 var behavior = function(selection$$1) {
58829 tooltip = selection$$1;
58833 .on('keydown.intro', keydown)
58834 .on('keyup.intro', keyup)
58835 .on('mousedown.intro', mousedown)
58836 .on('mouseup.intro', mouseup)
58837 .on('contextmenu.intro', contextmenu);
58841 behavior.off = function() {
58843 .on('keydown.intro', null)
58844 .on('keyup.intro', null)
58845 .on('mousedown.intro', null)
58846 .on('mouseup.intro', null)
58847 .on('contextmenu.intro', null);
58850 .classed('leftclick', false)
58851 .classed('rightclick', false);
58854 return utilRebind(behavior, dispatch$$1, 'on');
58857 function uiIntroNavigation(context, reveal) {
58858 var dispatch$$1 = dispatch('done'),
58861 townHall = [-85.63591, 41.94285],
58862 springStreetId = 'w397',
58863 springStreetEndId = 'n1834',
58864 springStreet = [-85.63582, 41.94255],
58865 onewayField = context.presets().field('oneway'),
58866 maxspeedField = context.presets().field('maxspeed');
58870 title: 'intro.navigation.title'
58874 function timeout$$1(f, t$$1) {
58875 timeouts.push(window.setTimeout(f, t$$1));
58879 function eventCancel() {
58880 event.stopPropagation();
58881 event.preventDefault();
58885 function isTownHallSelected() {
58886 var ids = context.selectedIDs();
58887 return ids.length === 1 && ids[0] === hallId;
58891 function dragMap() {
58892 context.enter(modeBrowse(context));
58893 context.history().reset('initial');
58895 var msec = transitionTime(townHall, context.map().center());
58896 if (msec) { reveal(null, null, { duration: 0 }); }
58897 context.map().zoom(19).centerEase(townHall, msec);
58899 timeout$$1(function() {
58900 var centerStart = context.map().center();
58902 reveal('#surface', t('intro.navigation.drag'));
58903 context.map().on('drawn.intro', function() {
58904 reveal('#surface', t('intro.navigation.drag'), { duration: 0 });
58907 context.map().on('move.intro', function() {
58908 var centerNow = context.map().center();
58909 if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) {
58910 context.map().on('move.intro', null);
58911 timeout$$1(function() { continueTo(zoomMap); }, 3000);
58917 function continueTo(nextStep) {
58918 context.map().on('move.intro drawn.intro', null);
58924 function zoomMap() {
58925 var zoomStart = context.map().zoom();
58928 t('intro.navigation.zoom', {
58929 plus: icon('#icon-plus', 'pre-text'),
58930 minus: icon('#icon-minus', 'pre-text')
58934 context.map().on('drawn.intro', function() {
58936 t('intro.navigation.zoom', {
58937 plus: icon('#icon-plus', 'pre-text'),
58938 minus: icon('#icon-minus', 'pre-text')
58939 }), { duration: 0 }
58943 context.map().on('move.intro', function() {
58944 if (context.map().zoom() !== zoomStart) {
58945 context.map().on('move.intro', null);
58946 timeout$$1(function() { continueTo(features); }, 3000);
58950 function continueTo(nextStep) {
58951 context.map().on('move.intro drawn.intro', null);
58957 function features() {
58958 var onClick = function() { continueTo(pointsLinesAreas); };
58960 reveal('#surface', t('intro.navigation.features'),
58961 { buttonText: t('intro.ok'), buttonCallback: onClick }
58964 context.map().on('drawn.intro', function() {
58965 reveal('#surface', t('intro.navigation.features'),
58966 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
58970 function continueTo(nextStep) {
58971 context.map().on('drawn.intro', null);
58976 function pointsLinesAreas() {
58977 var onClick = function() { continueTo(nodesWays); };
58979 reveal('#surface', t('intro.navigation.points_lines_areas'),
58980 { buttonText: t('intro.ok'), buttonCallback: onClick }
58983 context.map().on('drawn.intro', function() {
58984 reveal('#surface', t('intro.navigation.points_lines_areas'),
58985 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
58989 function continueTo(nextStep) {
58990 context.map().on('drawn.intro', null);
58995 function nodesWays() {
58996 var onClick = function() { continueTo(clickTownHall); };
58998 reveal('#surface', t('intro.navigation.nodes_ways'),
58999 { buttonText: t('intro.ok'), buttonCallback: onClick }
59002 context.map().on('drawn.intro', function() {
59003 reveal('#surface', t('intro.navigation.nodes_ways'),
59004 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
59008 function continueTo(nextStep) {
59009 context.map().on('drawn.intro', null);
59014 function clickTownHall() {
59015 context.enter(modeBrowse(context));
59016 context.history().reset('initial');
59018 reveal(null, null, { duration: 0 });
59019 context.map().zoomEase(19, 500);
59021 timeout$$1(function() {
59022 var entity = context.hasEntity(hallId);
59023 if (!entity) return;
59024 context.map().centerEase(entity.loc, 500);
59026 timeout$$1(function() {
59027 var entity = context.hasEntity(hallId);
59028 if (!entity) return;
59029 var box = pointBox(entity.loc, context);
59030 reveal(box, t('intro.navigation.click_townhall'));
59032 context.map().on('move.intro drawn.intro', function() {
59033 var entity = context.hasEntity(hallId);
59034 if (!entity) return;
59035 var box = pointBox(entity.loc, context);
59036 reveal(box, t('intro.navigation.click_townhall'), { duration: 0 });
59039 context.on('enter.intro', function() {
59040 if (isTownHallSelected()) continueTo(selectedTownHall);
59043 }, 550); // after centerEase
59045 }, 550); // after zoomEase
59047 context.history().on('change.intro', function() {
59048 if (!context.hasEntity(hallId)) {
59049 continueTo(clickTownHall);
59053 function continueTo(nextStep) {
59054 context.on('enter.intro', null);
59055 context.map().on('move.intro drawn.intro', null);
59056 context.history().on('change.intro', null);
59062 function selectedTownHall() {
59063 if (!isTownHallSelected()) return clickTownHall();
59065 var entity = context.hasEntity(hallId);
59066 if (!entity) return clickTownHall();
59068 var box = pointBox(entity.loc, context);
59069 var onClick = function() { continueTo(editorTownHall); };
59071 reveal(box, t('intro.navigation.selected_townhall'),
59072 { buttonText: t('intro.ok'), buttonCallback: onClick }
59075 context.map().on('move.intro drawn.intro', function() {
59076 var entity = context.hasEntity(hallId);
59077 if (!entity) return;
59078 var box = pointBox(entity.loc, context);
59079 reveal(box, t('intro.navigation.selected_townhall'),
59080 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
59084 context.history().on('change.intro', function() {
59085 if (!context.hasEntity(hallId)) {
59086 continueTo(clickTownHall);
59090 function continueTo(nextStep) {
59091 context.map().on('move.intro drawn.intro', null);
59092 context.history().on('change.intro', null);
59098 function editorTownHall() {
59099 if (!isTownHallSelected()) return clickTownHall();
59101 var onClick = function() { continueTo(presetTownHall); };
59103 reveal('.entity-editor-pane',
59104 t('intro.navigation.editor_townhall'),
59105 { buttonText: t('intro.ok'), buttonCallback: onClick }
59108 context.on('exit.intro', function() {
59109 continueTo(clickTownHall);
59112 context.history().on('change.intro', function() {
59113 if (!context.hasEntity(hallId)) {
59114 continueTo(clickTownHall);
59118 function continueTo(nextStep) {
59119 context.on('exit.intro', null);
59120 context.history().on('change.intro', null);
59126 function presetTownHall() {
59127 if (!isTownHallSelected()) return clickTownHall();
59129 // reset pane, in case user happened to change it..
59130 select('.inspector-wrap .panewrap').style('right', '0%');
59132 // preset match, in case the user happened to change it.
59133 var entity = context.entity(context.selectedIDs()[0]);
59134 var preset = context.presets().match(entity, context.graph());
59136 var onClick = function() { continueTo(fieldsTownHall); };
59138 context.on('exit.intro', function() {
59139 continueTo(clickTownHall);
59142 context.history().on('change.intro', function() {
59143 if (!context.hasEntity(hallId)) {
59144 continueTo(clickTownHall);
59148 reveal('.inspector-body .preset-list-item.inspector-inner',
59149 t('intro.navigation.preset_townhall', { preset: preset.name() }),
59150 { buttonText: t('intro.ok'), buttonCallback: onClick }
59153 function continueTo(nextStep) {
59154 context.on('exit.intro', null);
59155 context.history().on('change.intro', null);
59161 function fieldsTownHall() {
59162 if (!isTownHallSelected()) return clickTownHall();
59164 // reset pane, in case user happened to change it..
59165 select('.inspector-wrap .panewrap').style('right', '0%');
59167 var onClick = function() { continueTo(closeTownHall); };
59169 reveal('.inspector-body .inspector-preset',
59170 t('intro.navigation.fields_townhall'),
59171 { buttonText: t('intro.ok'), buttonCallback: onClick }
59174 context.on('exit.intro', function() {
59175 continueTo(clickTownHall);
59178 context.history().on('change.intro', function() {
59179 if (!context.hasEntity(hallId)) {
59180 continueTo(clickTownHall);
59184 function continueTo(nextStep) {
59185 context.on('exit.intro', null);
59186 context.history().on('change.intro', null);
59192 function closeTownHall() {
59193 if (!isTownHallSelected()) return clickTownHall();
59195 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59196 var href = select(selector$$1).attr('href') || '#icon-close';
59198 reveal('.entity-editor-pane',
59199 t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') })
59202 context.on('exit.intro', function() {
59203 continueTo(searchStreet);
59206 context.history().on('change.intro', function() {
59207 // update the close icon in the tooltip if the user edits something.
59208 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59209 var href = select(selector$$1).attr('href') || '#icon-close';
59211 reveal('.entity-editor-pane',
59212 t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }),
59217 function continueTo(nextStep) {
59218 context.on('exit.intro', null);
59219 context.history().on('change.intro', null);
59225 function searchStreet() {
59226 context.enter(modeBrowse(context));
59227 context.history().reset('initial'); // ensure spring street exists
59229 var msec = transitionTime(springStreet, context.map().center());
59230 if (msec) { reveal(null, null, { duration: 0 }); }
59231 context.map().zoom(19).centerEase(springStreet, msec); // ..and user can see it
59233 timeout$$1(function() {
59234 reveal('.search-header input',
59235 t('intro.navigation.search_street', { name: t('intro.graph.name.spring-street') })
59238 select('.search-header input')
59239 .on('keyup.intro', checkSearchResult);
59244 function checkSearchResult() {
59245 var first = select('.feature-list-item:nth-child(0n+2)'), // skip "No Results" item
59246 firstName = first.select('.entity-name'),
59247 name = t('intro.graph.name.spring-street');
59249 if (!firstName.empty() && firstName.text() === name) {
59250 reveal(first.node(),
59251 t('intro.navigation.choose_street', { name: name }),
59255 context.on('exit.intro', function() {
59256 continueTo(selectedStreet);
59259 select('.search-header input')
59260 .on('keydown.intro', eventCancel, true)
59261 .on('keyup.intro', null);
59264 function continueTo(nextStep) {
59265 context.on('exit.intro', null);
59266 select('.search-header input')
59267 .on('keydown.intro', null)
59268 .on('keyup.intro', null);
59274 function selectedStreet() {
59275 if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
59276 return searchStreet();
59279 var onClick = function() { continueTo(editorStreet); };
59280 var entity = context.entity(springStreetEndId);
59281 var box = pointBox(entity.loc, context);
59285 t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }),
59286 { duration: 600, buttonText: t('intro.ok'), buttonCallback: onClick }
59289 timeout$$1(function() {
59290 context.map().on('move.intro drawn.intro', function() {
59291 var entity = context.hasEntity(springStreetEndId);
59292 if (!entity) return;
59293 var box = pointBox(entity.loc, context);
59296 t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }),
59297 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
59300 }, 600); // after reveal.
59302 context.on('enter.intro', function(mode) {
59303 if (!context.hasEntity(springStreetId)) {
59304 return continueTo(searchStreet);
59306 var ids = context.selectedIDs();
59307 if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) {
59308 // keep Spring Street selected..
59309 context.enter(modeSelect(context, [springStreetId]));
59313 context.history().on('change.intro', function() {
59314 if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
59315 timeout$$1(function() {
59316 continueTo(searchStreet);
59317 }, 300); // after any transition (e.g. if user deleted intersection)
59321 function continueTo(nextStep) {
59322 context.map().on('move.intro drawn.intro', null);
59323 context.on('enter.intro', null);
59324 context.history().on('change.intro', null);
59330 function editorStreet() {
59331 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59332 var href = select(selector$$1).attr('href') || '#icon-close';
59334 reveal('.entity-editor-pane',
59335 t('intro.navigation.editor_street', {
59336 button: icon(href, 'pre-text'),
59337 field1: onewayField.label(),
59338 field2: maxspeedField.label()
59342 context.on('exit.intro', function() {
59346 context.history().on('change.intro', function() {
59347 // update the close icon in the tooltip if the user edits something.
59348 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59349 var href = select(selector$$1).attr('href') || '#icon-close';
59351 reveal('.entity-editor-pane',
59352 t('intro.navigation.editor_street', {
59353 button: icon(href, 'pre-text'),
59354 field1: onewayField.label().toLowerCase(),
59355 field2: maxspeedField.label().toLowerCase()
59356 }), { duration: 0 }
59360 function continueTo(nextStep) {
59361 context.on('exit.intro', null);
59362 context.history().on('change.intro', null);
59369 dispatch$$1.call('done');
59370 reveal('#id-container',
59371 t('intro.navigation.play', { next: t('intro.points.title') }), {
59372 tooltipBox: '.intro-nav-wrap .chapter-point',
59373 buttonText: t('intro.ok'),
59374 buttonCallback: function() { reveal('#id-container'); }
59380 chapter.enter = function() {
59385 chapter.exit = function() {
59386 timeouts.forEach(window.clearTimeout);
59387 context.on('enter.intro exit.intro', null);
59388 context.map().on('move.intro drawn.intro', null);
59389 context.history().on('change.intro', null);
59390 select('.search-header input').on('keydown.intro keyup.intro', null);
59394 chapter.restart = function() {
59400 return utilRebind(chapter, dispatch$$1, 'on');
59403 function uiIntroPoint(context, reveal) {
59404 var dispatch$$1 = dispatch('done'),
59406 intersection = [-85.63279, 41.94394],
59407 building = [-85.632422, 41.944045],
59408 cafePreset = context.presets().item('amenity/cafe'),
59413 title: 'intro.points.title'
59417 function timeout$$1(f, t$$1) {
59418 timeouts.push(window.setTimeout(f, t$$1));
59422 function revealEditMenu(loc, text$$1, options) {
59423 var rect = context.surfaceRect();
59424 var point = context.curtainProjection(loc);
59426 var width = 250 + (2 * pad$$1);
59428 var startX = rect.left + point[0];
59429 var left = (textDirection === 'rtl') ? (startX - width + pad$$1) : (startX - pad$$1);
59432 top: point[1] + rect.top - 60,
59436 reveal(box, text$$1, options);
59440 function eventCancel() {
59441 event.stopPropagation();
59442 event.preventDefault();
59446 function addPoint() {
59447 context.enter(modeBrowse(context));
59448 context.history().reset('initial');
59450 var msec = transitionTime(intersection, context.map().center());
59451 if (msec) { reveal(null, null, { duration: 0 }); }
59452 context.map().zoom(19).centerEase(intersection, msec);
59454 timeout$$1(function() {
59455 var tooltip = reveal('button.add-point',
59456 t('intro.points.add_point', { button: icon('#icon-point', 'pre-text') }));
59460 tooltip.selectAll('.tooltip-inner')
59461 .insert('svg', 'span')
59462 .attr('class', 'tooltip-illustration')
59464 .attr('xlink:href', '#poi-images');
59466 context.on('enter.intro', function(mode) {
59467 if (mode.id !== 'add-point') return;
59468 continueTo(placePoint);
59472 function continueTo(nextStep) {
59473 context.on('enter.intro', null);
59479 function placePoint() {
59480 if (context.mode().id !== 'add-point') {
59481 return chapter.restart();
59484 var pointBox$$1 = pad$1(building, 150, context);
59485 reveal(pointBox$$1, t('intro.points.place_point'));
59487 context.map().on('move.intro drawn.intro', function() {
59488 pointBox$$1 = pad$1(building, 150, context);
59489 reveal(pointBox$$1, t('intro.points.place_point'), { duration: 0 });
59492 context.on('enter.intro', function(mode) {
59493 if (mode.id !== 'select') return chapter.restart();
59494 pointId = context.mode().selectedIDs()[0];
59495 continueTo(searchPreset);
59498 function continueTo(nextStep) {
59499 context.map().on('move.intro drawn.intro', null);
59500 context.on('enter.intro', null);
59506 function searchPreset() {
59507 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59511 select('.preset-search-input')
59512 .on('keydown.intro', null)
59513 .on('keyup.intro', checkPresetSearch);
59515 reveal('.preset-search-input',
59516 t('intro.points.search_cafe', { preset: cafePreset.name() })
59519 context.on('enter.intro', function(mode) {
59520 if (!pointId || !context.hasEntity(pointId)) {
59521 return continueTo(addPoint);
59524 var ids = context.selectedIDs();
59525 if (mode.id !== 'select' || !ids.length || ids[0] !== pointId) {
59526 // keep the user's point selected..
59527 context.enter(modeSelect(context, [pointId]));
59529 select('.preset-search-input')
59530 .on('keydown.intro', null)
59531 .on('keyup.intro', checkPresetSearch);
59533 reveal('.preset-search-input',
59534 t('intro.points.search_cafe', { preset: cafePreset.name() })
59537 context.history().on('change.intro', null);
59542 function checkPresetSearch() {
59543 var first = select('.preset-list-item:first-child');
59545 if (first.classed('preset-amenity-cafe')) {
59546 select('.preset-search-input')
59547 .on('keydown.intro', eventCancel, true)
59548 .on('keyup.intro', null);
59550 reveal(first.select('.preset-list-button').node(),
59551 t('intro.points.choose_cafe', { preset: cafePreset.name() }),
59555 context.history().on('change.intro', function() {
59556 continueTo(aboutFeatureEditor);
59561 function continueTo(nextStep) {
59562 context.on('enter.intro', null);
59563 context.history().on('change.intro', null);
59564 select('.preset-search-input').on('keydown.intro keyup.intro', null);
59570 function aboutFeatureEditor() {
59571 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59575 timeout$$1(function() {
59576 reveal('.entity-editor-pane', t('intro.points.feature_editor'), {
59577 tooltipClass: 'intro-points-describe',
59578 buttonText: t('intro.ok'),
59579 buttonCallback: function() { continueTo(addName); }
59583 context.on('exit.intro', function() {
59584 // if user leaves select mode here, just continue with the tutorial.
59585 continueTo(reselectPoint);
59588 function continueTo(nextStep) {
59589 context.on('exit.intro', null);
59595 function addName() {
59596 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59600 // reset pane, in case user happened to change it..
59601 select('.inspector-wrap .panewrap').style('right', '0%');
59603 timeout$$1(function() {
59604 // It's possible for the user to add a name in a previous step..
59605 // If so, don't tell them to add the name in this step.
59606 // Give them an OK button instead.
59607 var entity = context.entity(pointId);
59608 if (entity.tags.name) {
59609 var tooltip = reveal('.entity-editor-pane', t('intro.points.add_name'), {
59610 tooltipClass: 'intro-points-describe',
59611 buttonText: t('intro.ok'),
59612 buttonCallback: function() { continueTo(addCloseEditor); }
59614 tooltip.select('.instruction').style('display', 'none');
59617 reveal('.entity-editor-pane', t('intro.points.add_name'),
59618 { tooltipClass: 'intro-points-describe' }
59623 context.history().on('change.intro', function() {
59624 continueTo(addCloseEditor);
59627 context.on('exit.intro', function() {
59628 // if user leaves select mode here, just continue with the tutorial.
59629 continueTo(reselectPoint);
59632 function continueTo(nextStep) {
59633 context.on('exit.intro', null);
59634 context.history().on('change.intro', null);
59640 function addCloseEditor() {
59641 // reset pane, in case user happened to change it..
59642 select('.inspector-wrap .panewrap').style('right', '0%');
59644 var selector$$1 = '.entity-editor-pane button.preset-close svg use';
59645 var href = select(selector$$1).attr('href') || '#icon-close';
59647 context.on('exit.intro', function() {
59648 continueTo(reselectPoint);
59651 reveal('.entity-editor-pane',
59652 t('intro.points.add_close', { button: icon(href, 'pre-text') })
59655 function continueTo(nextStep) {
59656 context.on('exit.intro', null);
59662 function reselectPoint() {
59663 if (!pointId) return chapter.restart();
59664 var entity = context.hasEntity(pointId);
59665 if (!entity) return chapter.restart();
59667 // make sure it's still a cafe, in case user somehow changed it..
59668 var oldPreset = context.presets().match(entity, context.graph());
59669 context.replace(actionChangePreset(pointId, oldPreset, cafePreset));
59671 context.enter(modeBrowse(context));
59673 var msec = transitionTime(entity.loc, context.map().center());
59674 if (msec) { reveal(null, null, { duration: 0 }); }
59675 context.map().centerEase(entity.loc, msec);
59677 timeout$$1(function() {
59678 var box = pointBox(entity.loc, context);
59679 reveal(box, t('intro.points.reselect'), { duration: 600 });
59681 timeout$$1(function() {
59682 context.map().on('move.intro drawn.intro', function() {
59683 var entity = context.hasEntity(pointId);
59684 if (!entity) return chapter.restart();
59685 var box = pointBox(entity.loc, context);
59686 reveal(box, t('intro.points.reselect'), { duration: 0 });
59688 }, 600); // after reveal..
59690 context.on('enter.intro', function(mode) {
59691 if (mode.id !== 'select') return;
59692 continueTo(updatePoint);
59697 function continueTo(nextStep) {
59698 context.map().on('move.intro drawn.intro', null);
59699 context.on('enter.intro', null);
59705 function updatePoint() {
59706 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59707 return continueTo(reselectPoint);
59710 // reset pane, in case user happened to untag the point..
59711 select('.inspector-wrap .panewrap').style('right', '0%');
59713 context.on('exit.intro', function() {
59714 continueTo(reselectPoint);
59717 context.history().on('change.intro', function() {
59718 continueTo(updateCloseEditor);
59721 timeout$$1(function() {
59722 reveal('.entity-editor-pane', t('intro.points.update'),
59723 { tooltipClass: 'intro-points-describe' }
59727 function continueTo(nextStep) {
59728 context.on('exit.intro', null);
59729 context.history().on('change.intro', null);
59735 function updateCloseEditor() {
59736 if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) {
59737 return continueTo(reselectPoint);
59740 // reset pane, in case user happened to change it..
59741 select('.inspector-wrap .panewrap').style('right', '0%');
59743 context.on('exit.intro', function() {
59744 continueTo(rightClickPoint);
59747 timeout$$1(function() {
59748 reveal('.entity-editor-pane',
59749 t('intro.points.update_close', { button: icon('#icon-apply', 'pre-text') })
59753 function continueTo(nextStep) {
59754 context.on('exit.intro', null);
59760 function rightClickPoint() {
59761 if (!pointId) return chapter.restart();
59762 var entity = context.hasEntity(pointId);
59763 if (!entity) return chapter.restart();
59765 context.enter(modeBrowse(context));
59767 var box = pointBox(entity.loc, context);
59768 reveal(box, t('intro.points.rightclick'), { duration: 600 });
59770 timeout$$1(function() {
59771 context.map().on('move.intro drawn.intro', function() {
59772 var entity = context.hasEntity(pointId);
59773 if (!entity) return chapter.restart();
59774 var box = pointBox(entity.loc, context);
59775 reveal(box, t('intro.points.rightclick'), { duration: 0 });
59777 }, 600); // after reveal
59779 context.on('enter.intro', function(mode) {
59780 if (mode.id !== 'select') return;
59781 var ids = context.selectedIDs();
59782 if (ids.length !== 1 || ids[0] !== pointId) return;
59784 timeout$$1(function() {
59785 var node = selectMenuItem('delete').node();
59787 continueTo(enterDelete);
59788 }, 300); // after menu visible
59791 function continueTo(nextStep) {
59792 context.on('enter.intro', null);
59793 context.map().on('move.intro drawn.intro', null);
59799 function enterDelete() {
59800 if (!pointId) return chapter.restart();
59801 var entity = context.hasEntity(pointId);
59802 if (!entity) return chapter.restart();
59804 var node = selectMenuItem('delete').node();
59805 if (!node) { return continueTo(rightClickPoint); }
59807 revealEditMenu(entity.loc,
59808 t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') })
59811 timeout$$1(function() {
59812 context.map().on('move.intro drawn.intro', function() {
59813 revealEditMenu(entity.loc,
59814 t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }),
59818 }, 300); // after menu visible
59820 context.on('exit.intro', function() {
59821 if (!pointId) return chapter.restart();
59822 var entity = context.hasEntity(pointId);
59823 if (entity) return continueTo(rightClickPoint); // point still exists
59826 context.history().on('change.intro', function(changed) {
59827 if (changed.deleted().length) {
59832 function continueTo(nextStep) {
59833 context.map().on('move.intro drawn.intro', null);
59834 context.history().on('change.intro', null);
59835 context.on('exit.intro', null);
59842 context.history().on('change.intro', function() {
59846 var iconName = '#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo');
59847 reveal('#bar button.undo-button',
59848 t('intro.points.undo', { button: icon(iconName, 'pre-text') })
59851 function continueTo(nextStep) {
59852 context.history().on('change.intro', null);
59859 dispatch$$1.call('done');
59860 reveal('#id-container',
59861 t('intro.points.play', { next: t('intro.areas.title') }), {
59862 tooltipBox: '.intro-nav-wrap .chapter-area',
59863 buttonText: t('intro.ok'),
59864 buttonCallback: function() { reveal('#id-container'); }
59870 chapter.enter = function() {
59875 chapter.exit = function() {
59876 timeouts.forEach(window.clearTimeout);
59877 context.on('enter.intro exit.intro', null);
59878 context.map().on('move.intro drawn.intro', null);
59879 context.history().on('change.intro', null);
59880 select('.preset-search-input').on('keydown.intro keyup.intro', null);
59884 chapter.restart = function() {
59890 return utilRebind(chapter, dispatch$$1, 'on');
59893 function uiIntroArea(context, reveal) {
59894 var dispatch$$1 = dispatch('done'),
59895 playground = [-85.63552, 41.94159],
59896 playgroundPreset = context.presets().item('leisure/playground'),
59897 descriptionField = context.presets().field('description'),
59903 title: 'intro.areas.title'
59907 function timeout$$1(f, t$$1) {
59908 timeouts.push(window.setTimeout(f, t$$1));
59912 function eventCancel() {
59913 event.stopPropagation();
59914 event.preventDefault();
59918 function revealPlayground(center, text$$1, options) {
59919 var padding = 180 * Math.pow(2, context.map().zoom() - 19.5);
59920 var box = pad$1(center, padding, context);
59921 reveal(box, text$$1, options);
59925 function addArea() {
59926 context.enter(modeBrowse(context));
59927 context.history().reset('initial');
59930 var msec = transitionTime(playground, context.map().center());
59931 if (msec) { reveal(null, null, { duration: 0 }); }
59932 context.map().zoom(19).centerEase(playground, msec);
59934 timeout$$1(function() {
59935 var tooltip = reveal('button.add-area',
59936 t('intro.areas.add_playground', { button: icon('#icon-area', 'pre-text') }));
59938 tooltip.selectAll('.tooltip-inner')
59939 .insert('svg', 'span')
59940 .attr('class', 'tooltip-illustration')
59942 .attr('xlink:href', '#landuse-images');
59944 context.on('enter.intro', function(mode) {
59945 if (mode.id !== 'add-area') return;
59946 continueTo(startPlayground);
59950 function continueTo(nextStep) {
59951 context.on('enter.intro', null);
59957 function startPlayground() {
59958 if (context.mode().id !== 'add-area') {
59959 return chapter.restart();
59963 context.map().zoomEase(19.5, 500);
59965 timeout$$1(function() {
59966 revealPlayground(playground,
59967 t('intro.areas.start_playground'), { duration: 250 }
59970 timeout$$1(function() {
59971 context.map().on('move.intro drawn.intro', function() {
59972 revealPlayground(playground,
59973 t('intro.areas.start_playground'), { duration: 0 }
59976 context.on('enter.intro', function(mode) {
59977 if (mode.id !== 'draw-area') return chapter.restart();
59978 continueTo(continuePlayground);
59980 }, 250); // after reveal
59982 }, 550); // after easing
59984 function continueTo(nextStep) {
59985 context.map().on('move.intro drawn.intro', null);
59986 context.on('enter.intro', null);
59992 function continuePlayground() {
59993 if (context.mode().id !== 'draw-area') {
59994 return chapter.restart();
59998 revealPlayground(playground,
59999 t('intro.areas.continue_playground'), { duration: 250 }
60002 timeout$$1(function() {
60003 context.map().on('move.intro drawn.intro', function() {
60004 revealPlayground(playground,
60005 t('intro.areas.continue_playground'), { duration: 0 }
60008 }, 250); // after reveal
60010 context.on('enter.intro', function(mode) {
60011 if (mode.id === 'draw-area') {
60012 var entity = context.hasEntity(context.selectedIDs()[0]);
60013 if (entity && entity.nodes.length >= 6) {
60014 return continueTo(finishPlayground);
60018 } else if (mode.id === 'select') {
60019 areaId = context.selectedIDs()[0];
60020 return continueTo(searchPresets);
60022 return chapter.restart();
60026 function continueTo(nextStep) {
60027 context.map().on('move.intro drawn.intro', null);
60028 context.on('enter.intro', null);
60034 function finishPlayground() {
60035 if (context.mode().id !== 'draw-area') {
60036 return chapter.restart();
60040 revealPlayground(playground,
60041 t('intro.areas.finish_playground'), { duration: 250 }
60044 timeout$$1(function() {
60045 context.map().on('move.intro drawn.intro', function() {
60046 revealPlayground(playground,
60047 t('intro.areas.finish_playground'), { duration: 0 }
60050 }, 250); // after reveal
60052 context.on('enter.intro', function(mode) {
60053 if (mode.id === 'draw-area') {
60055 } else if (mode.id === 'select') {
60056 areaId = context.selectedIDs()[0];
60057 return continueTo(searchPresets);
60059 return chapter.restart();
60063 function continueTo(nextStep) {
60064 context.map().on('move.intro drawn.intro', null);
60065 context.on('enter.intro', null);
60071 function searchPresets() {
60072 if (!areaId || !context.hasEntity(areaId)) {
60075 var ids = context.selectedIDs();
60076 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60077 context.enter(modeSelect(context, [areaId]));
60080 timeout$$1(function() {
60081 // reset pane, in case user somehow happened to change it..
60082 select('.inspector-wrap .panewrap').style('right', '-100%');
60084 select('.preset-search-input')
60085 .on('keydown.intro', null)
60086 .on('keyup.intro', checkPresetSearch);
60088 reveal('.preset-search-input',
60089 t('intro.areas.search_playground', { preset: playgroundPreset.name() })
60091 }, 400); // after preset list pane visible..
60093 context.on('enter.intro', function(mode) {
60094 if (!areaId || !context.hasEntity(areaId)) {
60095 return continueTo(addArea);
60098 var ids = context.selectedIDs();
60099 if (mode.id !== 'select' || !ids.length || ids[0] !== areaId) {
60100 // keep the user's area selected..
60101 context.enter(modeSelect(context, [areaId]));
60103 // reset pane, in case user somehow happened to change it..
60104 select('.inspector-wrap .panewrap').style('right', '-100%');
60106 select('.preset-search-input')
60107 .on('keydown.intro', null)
60108 .on('keyup.intro', checkPresetSearch);
60110 reveal('.preset-search-input',
60111 t('intro.areas.search_playground', { preset: playgroundPreset.name() })
60114 context.history().on('change.intro', null);
60118 function checkPresetSearch() {
60119 var first = select('.preset-list-item:first-child');
60121 if (first.classed('preset-leisure-playground')) {
60122 reveal(first.select('.preset-list-button').node(),
60123 t('intro.areas.choose_playground', { preset: playgroundPreset.name() }),
60127 select('.preset-search-input')
60128 .on('keydown.intro', eventCancel, true)
60129 .on('keyup.intro', null);
60131 context.history().on('change.intro', function() {
60132 continueTo(clickAddField);
60137 function continueTo(nextStep) {
60138 context.on('enter.intro', null);
60139 context.history().on('change.intro', null);
60140 select('.preset-search-input').on('keydown.intro keyup.intro', null);
60146 function clickAddField() {
60147 if (!areaId || !context.hasEntity(areaId)) {
60150 var ids = context.selectedIDs();
60151 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60152 return searchPresets();
60155 timeout$$1(function() {
60156 // reset pane, in case user somehow happened to change it..
60157 select('.inspector-wrap .panewrap').style('right', '0%');
60159 // It's possible for the user to add a description in a previous step..
60160 // If they did this already, just continue to next step.
60161 var entity = context.entity(areaId);
60162 if (entity.tags.description) {
60163 return continueTo(play);
60166 reveal('.more-fields .combobox-input',
60167 t('intro.areas.add_field'),
60171 select('.more-fields .combobox-input')
60172 .on('click.intro', function() {
60173 continueTo(chooseDescriptionField);
60175 }, 400); // after editor pane visible
60177 context.on('exit.intro', function() {
60178 return continueTo(searchPresets);
60181 function continueTo(nextStep) {
60182 select('.more-fields .combobox-input').on('click.intro', null);
60183 context.on('exit.intro', null);
60189 function chooseDescriptionField() {
60190 if (!areaId || !context.hasEntity(areaId)) {
60193 var ids = context.selectedIDs();
60194 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60195 return searchPresets();
60198 // Make sure combobox is ready..
60199 if (select('div.combobox').empty()) {
60200 return continueTo(clickAddField);
60202 // Watch for the combobox to go away..
60204 watcher = window.setInterval(function() {
60205 if (select('div.combobox').empty()) {
60206 window.clearInterval(watcher);
60207 timeout$$1(function() {
60208 if (select('.form-field-description').empty()) {
60209 continueTo(retryChooseDescription);
60211 continueTo(describePlayground);
60213 }, 300); // after description field added.
60217 reveal('div.combobox',
60218 t('intro.areas.choose_field', { field: descriptionField.label() }),
60222 context.on('exit.intro', function() {
60223 return continueTo(searchPresets);
60226 function continueTo(nextStep) {
60227 if (watcher) window.clearInterval(watcher);
60228 context.on('exit.intro', null);
60234 function describePlayground() {
60235 if (!areaId || !context.hasEntity(areaId)) {
60238 var ids = context.selectedIDs();
60239 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60240 return searchPresets();
60243 // reset pane, in case user happened to change it..
60244 select('.inspector-wrap .panewrap').style('right', '0%');
60246 if (select('.form-field-description').empty()) {
60247 return continueTo(retryChooseDescription);
60250 context.on('exit.intro', function() {
60254 reveal('.entity-editor-pane',
60255 t('intro.areas.describe_playground', { button: icon('#icon-apply', 'pre-text') }),
60259 function continueTo(nextStep) {
60260 context.on('exit.intro', null);
60266 function retryChooseDescription() {
60267 if (!areaId || !context.hasEntity(areaId)) {
60270 var ids = context.selectedIDs();
60271 if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) {
60272 return searchPresets();
60275 // reset pane, in case user happened to change it..
60276 select('.inspector-wrap .panewrap').style('right', '0%');
60278 reveal('.entity-editor-pane',
60279 t('intro.areas.retry_add_field', { field: descriptionField.label() }), {
60280 buttonText: t('intro.ok'),
60281 buttonCallback: function() { continueTo(clickAddField); }
60284 context.on('exit.intro', function() {
60285 return continueTo(searchPresets);
60288 function continueTo(nextStep) {
60289 context.on('exit.intro', null);
60296 dispatch$$1.call('done');
60297 reveal('#id-container',
60298 t('intro.areas.play', { next: t('intro.lines.title') }), {
60299 tooltipBox: '.intro-nav-wrap .chapter-line',
60300 buttonText: t('intro.ok'),
60301 buttonCallback: function() { reveal('#id-container'); }
60307 chapter.enter = function() {
60312 chapter.exit = function() {
60313 timeouts.forEach(window.clearTimeout);
60314 context.on('enter.intro exit.intro', null);
60315 context.map().on('move.intro drawn.intro', null);
60316 context.history().on('change.intro', null);
60317 select('.preset-search-input').on('keydown.intro keyup.intro', null);
60318 select('.more-fields .combobox-input').on('click.intro', null);
60322 chapter.restart = function() {
60328 return utilRebind(chapter, dispatch$$1, 'on');
60331 function uiIntroLine(context, reveal) {
60332 var dispatch$$1 = dispatch('done'),
60334 tulipRoadId = null,
60335 flowerRoadId = 'w646',
60336 tulipRoadStart = [-85.6297754121684, 41.95805253325314],
60337 tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204],
60338 tulipRoadIntersection = [-85.62974496187628, 41.95742515554585],
60339 roadCategory = context.presets().item('category-road'),
60340 residentialPreset = context.presets().item('highway/residential'),
60341 woodRoadId = 'w525',
60342 woodRoadEndId = 'n2862',
60343 woodRoadAddNode = [-85.62390110349587, 41.95397111462291],
60344 woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487],
60345 woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872],
60346 washingtonStreetId = 'w522',
60347 twelfthAvenueId = 'w1',
60348 eleventhAvenueEndId = 'n3550',
60349 twelfthAvenueEndId = 'n5',
60350 washingtonSegmentId = null,
60351 eleventhAvenueEnd = context.entity(eleventhAvenueEndId).loc,
60352 twelfthAvenueEnd = context.entity(twelfthAvenueEndId).loc,
60353 deleteLinesLoc = [-85.6219395542764, 41.95228033922477],
60354 twelfthAvenue = [-85.62219310052491, 41.952505413152956];
60358 title: 'intro.lines.title'
60362 function timeout$$1(f, t$$1) {
60363 timeouts.push(window.setTimeout(f, t$$1));
60367 function eventCancel() {
60368 event.stopPropagation();
60369 event.preventDefault();
60373 function revealEditMenu(loc, text$$1, options) {
60374 var rect = context.surfaceRect();
60375 var point = context.curtainProjection(loc);
60377 var width = 250 + (2 * pad$$1);
60379 var startX = rect.left + point[0];
60380 var left = (textDirection === 'rtl') ? (startX - width + pad$$1) : (startX - pad$$1);
60383 top: point[1] + rect.top - 60,
60387 reveal(box, text$$1, options);
60391 function addLine() {
60392 context.enter(modeBrowse(context));
60393 context.history().reset('initial');
60395 var msec = transitionTime(tulipRoadStart, context.map().center());
60396 if (msec) { reveal(null, null, { duration: 0 }); }
60397 context.map().zoom(18.5).centerEase(tulipRoadStart, msec);
60399 timeout$$1(function() {
60400 var tooltip = reveal('button.add-line',
60401 t('intro.lines.add_line', { button: icon('#icon-line', 'pre-text') }));
60403 tooltip.selectAll('.tooltip-inner')
60404 .insert('svg', 'span')
60405 .attr('class', 'tooltip-illustration')
60407 .attr('xlink:href', '#feature-images');
60409 context.on('enter.intro', function(mode) {
60410 if (mode.id !== 'add-line') return;
60411 continueTo(startLine);
60415 function continueTo(nextStep) {
60416 context.on('enter.intro', null);
60422 function startLine() {
60423 if (context.mode().id !== 'add-line') {
60424 return chapter.restart();
60427 tulipRoadId = null;
60429 var padding = 70 * Math.pow(2, context.map().zoom() - 18);
60430 var box = pad$1(tulipRoadStart, padding, context);
60431 box.height = box.height + 100;
60432 reveal(box, t('intro.lines.start_line'));
60434 context.map().on('move.intro drawn.intro', function() {
60435 padding = 70 * Math.pow(2, context.map().zoom() - 18);
60436 box = pad$1(tulipRoadStart, padding, context);
60437 box.height = box.height + 100;
60438 reveal(box, t('intro.lines.start_line'), { duration: 0 });
60441 context.on('enter.intro', function(mode) {
60442 if (mode.id !== 'draw-line') return chapter.restart();
60443 continueTo(drawLine);
60446 function continueTo(nextStep) {
60447 context.map().on('move.intro drawn.intro', null);
60448 context.on('enter.intro', null);
60454 function drawLine() {
60455 if (context.mode().id !== 'draw-line') {
60456 return chapter.restart();
60459 tulipRoadId = context.mode().selectedIDs()[0];
60460 context.map().centerEase(tulipRoadMidpoint, 500);
60462 timeout$$1(function() {
60463 var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
60464 var box = pad$1(tulipRoadMidpoint, padding, context);
60465 box.height = box.height * 2;
60467 t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') })
60470 context.map().on('move.intro drawn.intro', function() {
60471 padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
60472 box = pad$1(tulipRoadMidpoint, padding, context);
60473 box.height = box.height * 2;
60475 t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }),
60479 }, 550); // after easing..
60481 context.history().on('change.intro', function() {
60482 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
60483 if (!entity) return chapter.restart();
60485 if (isLineConnected()) {
60486 continueTo(continueLine);
60490 context.on('enter.intro', function(mode) {
60491 if (mode.id === 'draw-line')
60493 else if (mode.id === 'select') {
60494 continueTo(retryIntersect);
60498 return chapter.restart();
60501 function continueTo(nextStep) {
60502 context.map().on('move.intro drawn.intro', null);
60503 context.history().on('change.intro', null);
60504 context.on('enter.intro', null);
60510 function isLineConnected() {
60511 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
60512 if (!entity) return false;
60514 var drawNodes = context.graph().childNodes(entity);
60515 return lodash.some(drawNodes, function(node) {
60516 return lodash.some(context.graph().parentWays(node), function(parent) {
60517 return parent.id === flowerRoadId;
60523 function retryIntersect() {
60524 select(window).on('mousedown.intro', eventCancel, true);
60526 var box = pad$1(tulipRoadIntersection, 80, context);
60528 t('intro.lines.retry_intersect', { name: t('intro.graph.name.flower-street') })
60531 timeout$$1(chapter.restart, 3000);
60535 function continueLine() {
60536 if (context.mode().id !== 'draw-line') return chapter.restart();
60537 var entity = tulipRoadId && context.hasEntity(tulipRoadId);
60538 if (!entity) return chapter.restart();
60540 context.map().centerEase(tulipRoadIntersection, 500);
60542 reveal('#surface', t('intro.lines.continue_line'));
60544 context.on('enter.intro', function(mode) {
60545 if (mode.id === 'draw-line')
60547 else if (mode.id === 'select')
60548 return continueTo(chooseCategoryRoad);
60550 return chapter.restart();
60553 function continueTo(nextStep) {
60554 context.on('enter.intro', null);
60560 function chooseCategoryRoad() {
60561 if (context.mode().id !== 'select') {
60562 return chapter.restart();
60565 context.on('exit.intro', function() {
60566 return chapter.restart();
60569 var button = select('.preset-category-road .preset-list-button');
60570 if (button.empty()) return chapter.restart();
60572 timeout$$1(function() {
60573 reveal(button.node(),
60574 t('intro.lines.choose_category_road', { category: roadCategory.name() })
60576 button.on('click.intro', function() { continueTo(choosePresetResidential); });
60579 function continueTo(nextStep) {
60580 select('.preset-list-button').on('click.intro', null);
60581 context.on('exit.intro', null);
60587 function choosePresetResidential() {
60588 if (context.mode().id !== 'select') {
60589 return chapter.restart();
60592 context.on('exit.intro', function() {
60593 return chapter.restart();
60596 var subgrid = select('.preset-category-road .subgrid');
60597 if (subgrid.empty()) return chapter.restart();
60599 subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button')
60600 .on('click.intro', function() {
60601 continueTo(retryPresetResidential);
60604 subgrid.selectAll('.preset-highway-residential .preset-list-button')
60605 .on('click.intro', function() {
60606 continueTo(nameRoad);
60609 timeout$$1(function() {
60610 reveal(subgrid.node(),
60611 t('intro.lines.choose_preset_residential', { preset: residentialPreset.name() }),
60612 { tooltipBox: '.preset-highway-residential .preset-list-button', duration: 300 }
60616 function continueTo(nextStep) {
60617 select('.preset-list-button').on('click.intro', null);
60618 context.on('exit.intro', null);
60624 // selected wrong road type
60625 function retryPresetResidential() {
60626 if (context.mode().id !== 'select') {
60627 return chapter.restart();
60630 context.on('exit.intro', function() {
60631 return chapter.restart();
60634 timeout$$1(function() {
60635 var button = select('.entity-editor-pane .preset-list-button');
60636 reveal(button.node(),
60637 t('intro.lines.retry_preset_residential', { preset: residentialPreset.name() })
60639 button.on('click.intro', function() {
60640 continueTo(chooseCategoryRoad);
60644 function continueTo(nextStep) {
60645 select('.preset-list-button').on('click.intro', null);
60646 context.on('exit.intro', null);
60652 function nameRoad() {
60653 context.on('exit.intro', function() {
60654 continueTo(didNameRoad);
60657 timeout$$1(function() {
60658 reveal('.entity-editor-pane',
60659 t('intro.lines.name_road', { button: icon('#icon-apply', 'pre-text') }),
60660 { tooltipClass: 'intro-lines-name_road' }
60664 function continueTo(nextStep) {
60665 context.on('exit.intro', null);
60671 function didNameRoad() {
60672 context.history().checkpoint('doneAddLine');
60674 timeout$$1(function() {
60675 reveal('#surface', t('intro.lines.did_name_road'), {
60676 buttonText: t('intro.ok'),
60677 buttonCallback: function() { continueTo(updateLine); }
60681 function continueTo(nextStep) {
60687 function updateLine() {
60688 context.history().reset('doneAddLine');
60689 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60690 return chapter.restart();
60693 var msec = transitionTime(woodRoadDragMidpoint, context.map().center());
60694 if (msec) { reveal(null, null, { duration: 0 }); }
60695 context.map().zoom(19).centerEase(woodRoadDragMidpoint, msec);
60697 timeout$$1(function() {
60698 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
60699 var box = pad$1(woodRoadDragMidpoint, padding, context);
60700 var advance = function() { continueTo(addNode); };
60702 reveal(box, t('intro.lines.update_line'),
60703 { buttonText: t('intro.ok'), buttonCallback: advance }
60706 context.map().on('move.intro drawn.intro', function() {
60707 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
60708 var box = pad$1(woodRoadDragMidpoint, padding, context);
60709 reveal(box, t('intro.lines.update_line'),
60710 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
60715 function continueTo(nextStep) {
60716 context.map().on('move.intro drawn.intro', null);
60722 function addNode() {
60723 context.history().reset('doneAddLine');
60724 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60725 return chapter.restart();
60728 var padding = 40 * Math.pow(2, context.map().zoom() - 19);
60729 var box = pad$1(woodRoadAddNode, padding, context);
60730 reveal(box, t('intro.lines.add_node'));
60732 context.map().on('move.intro drawn.intro', function() {
60733 var padding = 40 * Math.pow(2, context.map().zoom() - 19);
60734 var box = pad$1(woodRoadAddNode, padding, context);
60735 reveal(box, t('intro.lines.add_node'), { duration: 0 });
60738 context.history().on('change.intro', function(changed) {
60739 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60740 return continueTo(updateLine);
60742 if (changed.created().length === 1) {
60743 timeout$$1(function() { continueTo(startDragEndpoint); }, 500);
60747 context.on('enter.intro', function(mode) {
60748 if (mode.id !== 'select') {
60749 continueTo(updateLine);
60753 function continueTo(nextStep) {
60754 context.map().on('move.intro drawn.intro', null);
60755 context.history().on('change.intro', null);
60756 context.on('enter.intro', null);
60762 function startDragEndpoint() {
60763 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60764 return continueTo(updateLine);
60766 if (context.selectedIDs().indexOf(woodRoadId) === -1) {
60767 context.enter(modeSelect(context, [woodRoadId]));
60770 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
60771 var box = pad$1(woodRoadDragEndpoint, padding, context);
60772 reveal(box, t('intro.lines.start_drag_endpoint'));
60774 context.map().on('move.intro drawn.intro', function() {
60775 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60776 return continueTo(updateLine);
60778 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
60779 var box = pad$1(woodRoadDragEndpoint, padding, context);
60780 reveal(box, t('intro.lines.start_drag_endpoint'), { duration: 0 });
60782 var entity = context.entity(woodRoadEndId);
60783 if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) {
60784 continueTo(finishDragEndpoint);
60788 context.on('enter.intro', function(mode) {
60789 if (mode.id !== 'select') {
60790 // keep Wood Road selected so endpoint stays draggable..
60791 context.enter(modeSelect(context, [woodRoadId]));
60795 function continueTo(nextStep) {
60796 context.map().on('move.intro drawn.intro', null);
60797 context.on('enter.intro', null);
60803 function finishDragEndpoint() {
60804 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60805 return continueTo(updateLine);
60808 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
60809 var box = pad$1(woodRoadDragEndpoint, padding, context);
60810 reveal(box, t('intro.lines.finish_drag_endpoint'));
60812 context.map().on('move.intro drawn.intro', function() {
60813 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60814 return continueTo(updateLine);
60816 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
60817 var box = pad$1(woodRoadDragEndpoint, padding, context);
60818 reveal(box, t('intro.lines.finish_drag_endpoint'), { duration: 0 });
60820 var entity = context.entity(woodRoadEndId);
60821 if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) {
60822 continueTo(startDragEndpoint);
60826 context.on('enter.intro', function() {
60827 continueTo(startDragMidpoint);
60830 function continueTo(nextStep) {
60831 context.map().on('move.intro drawn.intro', null);
60832 context.on('enter.intro', null);
60838 function startDragMidpoint() {
60839 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60840 return continueTo(updateLine);
60842 if (context.selectedIDs().indexOf(woodRoadId) === -1) {
60843 context.enter(modeSelect(context, [woodRoadId]));
60846 var padding = 80 * Math.pow(2, context.map().zoom() - 19);
60847 var box = pad$1(woodRoadDragMidpoint, padding, context);
60848 reveal(box, t('intro.lines.start_drag_midpoint'));
60850 context.map().on('move.intro drawn.intro', function() {
60851 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60852 return continueTo(updateLine);
60854 var padding = 80 * Math.pow(2, context.map().zoom() - 19);
60855 var box = pad$1(woodRoadDragMidpoint, padding, context);
60856 reveal(box, t('intro.lines.start_drag_midpoint'), { duration: 0 });
60859 context.history().on('change.intro', function(changed) {
60860 if (changed.created().length === 1) {
60861 continueTo(continueDragMidpoint);
60865 context.on('enter.intro', function(mode) {
60866 if (mode.id !== 'select') {
60867 // keep Wood Road selected so midpoint triangles are drawn..
60868 context.enter(modeSelect(context, [woodRoadId]));
60872 function continueTo(nextStep) {
60873 context.map().on('move.intro drawn.intro', null);
60874 context.history().on('change.intro', null);
60875 context.on('enter.intro', null);
60881 function continueDragMidpoint() {
60882 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60883 return continueTo(updateLine);
60886 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
60887 var box = pad$1(woodRoadDragEndpoint, padding, context);
60890 var advance = function() {
60891 context.history().checkpoint('doneUpdateLine');
60892 continueTo(deleteLines);
60895 reveal(box, t('intro.lines.continue_drag_midpoint'),
60896 { buttonText: t('intro.ok'), buttonCallback: advance }
60899 context.map().on('move.intro drawn.intro', function() {
60900 if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
60901 return continueTo(updateLine);
60903 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
60904 var box = pad$1(woodRoadDragEndpoint, padding, context);
60906 reveal(box, t('intro.lines.continue_drag_midpoint'),
60907 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
60911 function continueTo(nextStep) {
60912 context.map().on('move.intro drawn.intro', null);
60918 function deleteLines() {
60919 context.history().reset('doneUpdateLine');
60920 context.enter(modeBrowse(context));
60922 if (!context.hasEntity(washingtonStreetId) ||
60923 !context.hasEntity(twelfthAvenueId) ||
60924 !context.hasEntity(eleventhAvenueEndId)) {
60925 return chapter.restart();
60928 var msec = transitionTime(deleteLinesLoc, context.map().center());
60929 if (msec) { reveal(null, null, { duration: 0 }); }
60930 context.map().zoom(18).centerEase(deleteLinesLoc, msec);
60932 timeout$$1(function() {
60933 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
60934 var box = pad$1(deleteLinesLoc, padding, context);
60937 var advance = function() { continueTo(rightClickIntersection); };
60939 reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }),
60940 { buttonText: t('intro.ok'), buttonCallback: advance }
60943 context.map().on('move.intro drawn.intro', function() {
60944 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
60945 var box = pad$1(deleteLinesLoc, padding, context);
60948 reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }),
60949 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
60953 context.history().on('change.intro', function() {
60954 timeout$$1(function() {
60955 continueTo(deleteLines);
60956 }, 500); // after any transition (e.g. if user deleted intersection)
60961 function continueTo(nextStep) {
60962 context.map().on('move.intro drawn.intro', null);
60963 context.history().on('change.intro', null);
60969 function rightClickIntersection() {
60970 context.history().reset('doneUpdateLine');
60971 context.enter(modeBrowse(context));
60973 context.map().zoom(18).centerEase(eleventhAvenueEnd, 500);
60975 timeout$$1(function() {
60976 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
60977 var box = pad$1(eleventhAvenueEnd, padding, context);
60978 reveal(box, t('intro.lines.rightclick_intersection',
60979 { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') })
60982 context.map().on('move.intro drawn.intro', function() {
60983 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
60984 var box = pad$1(eleventhAvenueEnd, padding, context);
60985 reveal(box, t('intro.lines.rightclick_intersection',
60986 { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') }),
60991 context.on('enter.intro', function(mode) {
60992 if (mode.id !== 'select') return;
60993 var ids = context.selectedIDs();
60994 if (ids.length !== 1 || ids[0] !== eleventhAvenueEndId) return;
60996 timeout$$1(function() {
60997 var node = selectMenuItem('split').node();
60999 continueTo(splitIntersection);
61000 }, 300); // after menu visible
61003 context.history().on('change.intro', function() {
61004 timeout$$1(function() {
61005 continueTo(deleteLines);
61006 }, 300); // after any transition (e.g. if user deleted intersection)
61011 function continueTo(nextStep) {
61012 context.map().on('move.intro drawn.intro', null);
61013 context.on('enter.intro', null);
61014 context.history().on('change.intro', null);
61020 function splitIntersection() {
61021 if (!context.hasEntity(washingtonStreetId) ||
61022 !context.hasEntity(twelfthAvenueId) ||
61023 !context.hasEntity(eleventhAvenueEndId)) {
61024 return continueTo(deleteLines);
61027 var node = selectMenuItem('split').node();
61028 if (!node) { return continueTo(rightClickIntersection); }
61030 var wasChanged = false;
61031 var menuCoords = context.map().mouseCoordinates();
61032 washingtonSegmentId = null;
61034 revealEditMenu(menuCoords, t('intro.lines.split_intersection',
61035 { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') })
61038 context.map().on('move.intro drawn.intro', function() {
61039 var node = selectMenuItem('split').node();
61040 if (!wasChanged && !node) { return continueTo(rightClickIntersection); }
61042 revealEditMenu(menuCoords, t('intro.lines.split_intersection',
61043 { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') }),
61048 context.history().on('change.intro', function(changed) {
61050 timeout$$1(function() {
61051 if (context.history().undoAnnotation() === t('operations.split.annotation.line')) {
61052 washingtonSegmentId = changed.created()[0].id;
61053 continueTo(didSplit);
61055 washingtonSegmentId = null;
61056 continueTo(retrySplit);
61058 }, 300); // after any transition (e.g. if user deleted intersection)
61061 function continueTo(nextStep) {
61062 context.map().on('move.intro drawn.intro', null);
61063 context.history().on('change.intro', null);
61069 function retrySplit() {
61070 context.enter(modeBrowse(context));
61071 context.map().zoom(18).centerEase(eleventhAvenueEnd, 500);
61072 var advance = function() { continueTo(rightClickIntersection); };
61074 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
61075 var box = pad$1(eleventhAvenueEnd, padding, context);
61076 reveal(box, t('intro.lines.retry_split'),
61077 { buttonText: t('intro.ok'), buttonCallback: advance }
61080 context.map().on('move.intro drawn.intro', function() {
61081 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
61082 var box = pad$1(eleventhAvenueEnd, padding, context);
61083 reveal(box, t('intro.lines.retry_split'),
61084 { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
61088 function continueTo(nextStep) {
61089 context.map().on('move.intro drawn.intro', null);
61095 function didSplit() {
61096 if (!washingtonSegmentId ||
61097 !context.hasEntity(washingtonSegmentId) ||
61098 !context.hasEntity(washingtonStreetId) ||
61099 !context.hasEntity(twelfthAvenueId) ||
61100 !context.hasEntity(eleventhAvenueEndId)) {
61101 return continueTo(rightClickIntersection);
61104 var ids = context.selectedIDs();
61105 var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single');
61106 var street = t('intro.graph.name.washington-street');
61108 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61109 var box = pad$1(twelfthAvenue, padding, context);
61110 box.width = box.width / 2;
61111 reveal(box, t(string, { street1: street, street2: street }),
61115 timeout$$1(function() {
61116 context.map().zoom(18).centerEase(twelfthAvenue, 500);
61118 context.map().on('move.intro drawn.intro', function() {
61119 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61120 var box = pad$1(twelfthAvenue, padding, context);
61121 box.width = box.width / 2;
61122 reveal(box, t(string, { street1: street, street2: street }),
61126 }, 600); // after initial reveal and curtain cut
61128 context.on('enter.intro', function() {
61129 var ids = context.selectedIDs();
61130 if (ids.length === 1 && ids[0] === washingtonSegmentId) {
61131 continueTo(multiSelect);
61135 context.history().on('change.intro', function() {
61136 if (!washingtonSegmentId ||
61137 !context.hasEntity(washingtonSegmentId) ||
61138 !context.hasEntity(washingtonStreetId) ||
61139 !context.hasEntity(twelfthAvenueId) ||
61140 !context.hasEntity(eleventhAvenueEndId)) {
61141 return continueTo(rightClickIntersection);
61145 function continueTo(nextStep) {
61146 context.map().on('move.intro drawn.intro', null);
61147 context.on('enter.intro', null);
61148 context.history().on('change.intro', null);
61154 function multiSelect() {
61155 if (!washingtonSegmentId ||
61156 !context.hasEntity(washingtonSegmentId) ||
61157 !context.hasEntity(washingtonStreetId) ||
61158 !context.hasEntity(twelfthAvenueId) ||
61159 !context.hasEntity(eleventhAvenueEndId)) {
61160 return continueTo(rightClickIntersection);
61163 var ids = context.selectedIDs();
61164 var hasWashington = ids.indexOf(washingtonSegmentId) !== -1;
61165 var hasTwelfth = ids.indexOf(twelfthAvenueId) !== -1;
61167 if (hasWashington && hasTwelfth) {
61168 return continueTo(multiRightClick);
61169 } else if (!hasWashington && !hasTwelfth) {
61170 return continueTo(didSplit);
61173 context.map().zoom(18).centerEase(twelfthAvenue, 500);
61175 timeout$$1(function() {
61176 var selected, other, padding, box;
61177 if (hasWashington) {
61178 selected = t('intro.graph.name.washington-street');
61179 other = t('intro.graph.name.12th-avenue');
61180 padding = 60 * Math.pow(2, context.map().zoom() - 18);
61181 box = pad$1(twelfthAvenueEnd, padding, context);
61184 selected = t('intro.graph.name.12th-avenue');
61185 other = t('intro.graph.name.washington-street');
61186 padding = 200 * Math.pow(2, context.map().zoom() - 18);
61187 box = pad$1(twelfthAvenue, padding, context);
61192 t('intro.lines.multi_select', { selected: selected, other1: other, other2: other })
61195 context.map().on('move.intro drawn.intro', function() {
61196 if (hasWashington) {
61197 selected = t('intro.graph.name.washington-street');
61198 other = t('intro.graph.name.12th-avenue');
61199 padding = 60 * Math.pow(2, context.map().zoom() - 18);
61200 box = pad$1(twelfthAvenueEnd, padding, context);
61203 selected = t('intro.graph.name.12th-avenue');
61204 other = t('intro.graph.name.washington-street');
61205 padding = 200 * Math.pow(2, context.map().zoom() - 18);
61206 box = pad$1(twelfthAvenue, padding, context);
61211 t('intro.lines.multi_select', { selected: selected, other1: other, other2: other }),
61216 context.on('enter.intro', function() {
61217 continueTo(multiSelect);
61220 context.history().on('change.intro', function() {
61221 if (!washingtonSegmentId ||
61222 !context.hasEntity(washingtonSegmentId) ||
61223 !context.hasEntity(washingtonStreetId) ||
61224 !context.hasEntity(twelfthAvenueId) ||
61225 !context.hasEntity(eleventhAvenueEndId)) {
61226 return continueTo(rightClickIntersection);
61231 function continueTo(nextStep) {
61232 context.map().on('move.intro drawn.intro', null);
61233 context.on('enter.intro', null);
61234 context.history().on('change.intro', null);
61240 function multiRightClick() {
61241 if (!washingtonSegmentId ||
61242 !context.hasEntity(washingtonSegmentId) ||
61243 !context.hasEntity(washingtonStreetId) ||
61244 !context.hasEntity(twelfthAvenueId) ||
61245 !context.hasEntity(eleventhAvenueEndId)) {
61246 return continueTo(rightClickIntersection);
61249 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61250 var box = pad$1(twelfthAvenue, padding, context);
61251 reveal(box, t('intro.lines.multi_rightclick'));
61253 context.map().on('move.intro drawn.intro', function() {
61254 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61255 var box = pad$1(twelfthAvenue, padding, context);
61256 reveal(box, t('intro.lines.multi_rightclick'), { duration: 0 });
61259 select(window).on('click.intro contextmenu.intro', function() {
61260 timeout$$1(function() {
61261 var ids = context.selectedIDs();
61262 if (ids.length === 2 &&
61263 ids.indexOf(twelfthAvenueId) !== -1 &&
61264 ids.indexOf(washingtonSegmentId) !== -1) {
61265 var node = selectMenuItem('delete').node();
61267 continueTo(multiDelete);
61268 } else if (ids.length === 1 &&
61269 ids.indexOf(washingtonSegmentId) !== -1) {
61270 return continueTo(multiSelect);
61272 return continueTo(didSplit);
61274 }, 300); // after edit menu visible
61277 context.history().on('change.intro', function() {
61278 if (!washingtonSegmentId ||
61279 !context.hasEntity(washingtonSegmentId) ||
61280 !context.hasEntity(washingtonStreetId) ||
61281 !context.hasEntity(twelfthAvenueId) ||
61282 !context.hasEntity(eleventhAvenueEndId)) {
61283 return continueTo(rightClickIntersection);
61287 function continueTo(nextStep) {
61288 context.map().on('move.intro drawn.intro', null);
61289 select(window).on('click.intro contextmenu.intro', null, true);
61290 context.history().on('change.intro', null);
61296 function multiDelete() {
61297 if (!washingtonSegmentId ||
61298 !context.hasEntity(washingtonSegmentId) ||
61299 !context.hasEntity(washingtonStreetId) ||
61300 !context.hasEntity(twelfthAvenueId) ||
61301 !context.hasEntity(eleventhAvenueEndId)) {
61302 return continueTo(rightClickIntersection);
61305 var node = selectMenuItem('delete').node();
61306 if (!node) return continueTo(multiRightClick);
61308 var menuCoords = context.map().mouseCoordinates();
61309 revealEditMenu(menuCoords,
61310 t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') })
61313 context.map().on('move.intro drawn.intro', function() {
61314 revealEditMenu(menuCoords,
61315 t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') }),
61320 context.on('exit.intro', function() {
61321 if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) {
61322 return continueTo(multiSelect); // left select mode but roads still exist
61326 context.history().on('change.intro', function() {
61327 if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) {
61328 continueTo(retryDelete); // changed something but roads still exist
61334 function continueTo(nextStep) {
61335 context.map().on('move.intro drawn.intro', null);
61336 context.on('exit.intro', null);
61337 context.history().on('change.intro', null);
61343 function retryDelete() {
61344 context.enter(modeBrowse(context));
61346 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
61347 var box = pad$1(twelfthAvenue, padding, context);
61348 reveal(box, t('intro.lines.retry_delete'), {
61349 buttonText: t('intro.ok'),
61350 buttonCallback: function() { continueTo(multiSelect); }
61353 function continueTo(nextStep) {
61360 dispatch$$1.call('done');
61361 reveal('#id-container',
61362 t('intro.lines.play', { next: t('intro.buildings.title') }), {
61363 tooltipBox: '.intro-nav-wrap .chapter-building',
61364 buttonText: t('intro.ok'),
61365 buttonCallback: function() { reveal('#id-container'); }
61371 chapter.enter = function() {
61376 chapter.exit = function() {
61377 timeouts.forEach(window.clearTimeout);
61378 select(window).on('mousedown.intro', null, true);
61379 context.on('enter.intro exit.intro', null);
61380 context.map().on('move.intro drawn.intro', null);
61381 context.history().on('change.intro', null);
61382 select('.preset-list-button').on('click.intro', null);
61386 chapter.restart = function() {
61392 return utilRebind(chapter, dispatch$$1, 'on');
61395 function uiIntroBuilding(context, reveal) {
61396 var dispatch$$1 = dispatch('done'),
61397 house = [-85.62815, 41.95638],
61398 tank = [-85.62732, 41.95347],
61399 buildingCatetory = context.presets().item('category-building'),
61400 housePreset = context.presets().item('building/house'),
61401 tankPreset = context.presets().item('man_made/storage_tank'),
61408 title: 'intro.buildings.title'
61412 function timeout$$1(f, t$$1) {
61413 timeouts.push(window.setTimeout(f, t$$1));
61417 function eventCancel() {
61418 event.stopPropagation();
61419 event.preventDefault();
61423 function revealHouse(center, text$$1, options) {
61424 var padding = 160 * Math.pow(2, context.map().zoom() - 20);
61425 var box = pad$1(center, padding, context);
61426 reveal(box, text$$1, options);
61430 function revealTank(center, text$$1, options) {
61431 var padding = 190 * Math.pow(2, context.map().zoom() - 19.5);
61432 var box = pad$1(center, padding, context);
61433 reveal(box, text$$1, options);
61437 function revealEditMenu(loc, text$$1, options) {
61438 var rect = context.surfaceRect();
61439 var point = context.curtainProjection(loc);
61441 var width = 250 + (2 * pad$$1);
61443 var startX = rect.left + point[0];
61444 var left = (textDirection === 'rtl') ? (startX - width + pad$$1) : (startX - pad$$1);
61447 top: point[1] + rect.top - 60,
61451 reveal(box, text$$1, options);
61455 function addHouse() {
61456 context.enter(modeBrowse(context));
61457 context.history().reset('initial');
61460 var msec = transitionTime(house, context.map().center());
61461 if (msec) { reveal(null, null, { duration: 0 }); }
61462 context.map().zoom(19).centerEase(house, msec);
61464 timeout$$1(function() {
61465 var tooltip = reveal('button.add-area',
61466 t('intro.buildings.add_building', { button: icon('#icon-area', 'pre-text') }));
61468 tooltip.selectAll('.tooltip-inner')
61469 .insert('svg', 'span')
61470 .attr('class', 'tooltip-illustration')
61472 .attr('xlink:href', '#building-images');
61474 context.on('enter.intro', function(mode) {
61475 if (mode.id !== 'add-area') return;
61476 continueTo(startHouse);
61480 function continueTo(nextStep) {
61481 context.on('enter.intro', null);
61487 function startHouse() {
61488 if (context.mode().id !== 'add-area') {
61489 return continueTo(addHouse);
61493 context.map().zoomEase(20, 500);
61495 timeout$$1(function() {
61496 revealHouse(house, t('intro.buildings.start_building'));
61498 context.map().on('move.intro drawn.intro', function() {
61499 revealHouse(house, t('intro.buildings.start_building'), { duration: 0 });
61502 context.on('enter.intro', function(mode) {
61503 if (mode.id !== 'draw-area') return chapter.restart();
61504 continueTo(continueHouse);
61507 }, 550); // after easing
61509 function continueTo(nextStep) {
61510 context.map().on('move.intro drawn.intro', null);
61511 context.on('enter.intro', null);
61517 function continueHouse() {
61518 if (context.mode().id !== 'draw-area') {
61519 return continueTo(addHouse);
61524 revealHouse(house, t('intro.buildings.continue_building'));
61526 context.map().on('move.intro drawn.intro', function() {
61527 revealHouse(house, t('intro.buildings.continue_building'), { duration: 0 });
61530 context.on('enter.intro', function(mode) {
61531 if (mode.id === 'draw-area') {
61533 } else if (mode.id === 'select') {
61534 var graph = context.graph(),
61535 way = context.entity(context.selectedIDs()[0]),
61536 nodes = graph.childNodes(way),
61537 points = lodash.uniq(nodes).map(function(n) { return context.projection(n.loc); });
61539 if (isMostlySquare(points)) {
61541 return continueTo(chooseCategoryBuilding);
61543 return continueTo(retryHouse);
61547 return chapter.restart();
61551 function continueTo(nextStep) {
61552 context.map().on('move.intro drawn.intro', null);
61553 context.on('enter.intro', null);
61559 function retryHouse() {
61560 var onClick = function() { continueTo(addHouse); };
61562 revealHouse(house, t('intro.buildings.retry_building'),
61563 { buttonText: t('intro.ok'), buttonCallback: onClick }
61566 context.map().on('move.intro drawn.intro', function() {
61567 revealHouse(house, t('intro.buildings.retry_building'),
61568 { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick }
61572 function continueTo(nextStep) {
61573 context.map().on('move.intro drawn.intro', null);
61579 function chooseCategoryBuilding() {
61580 if (!houseId || !context.hasEntity(houseId)) {
61583 var ids = context.selectedIDs();
61584 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
61585 context.enter(modeSelect(context, [houseId]));
61588 timeout$$1(function() {
61589 // reset pane, in case user somehow happened to change it..
61590 select('.inspector-wrap .panewrap').style('right', '-100%');
61592 var button = select('.preset-category-building .preset-list-button');
61594 reveal(button.node(),
61595 t('intro.buildings.choose_category_building', { category: buildingCatetory.name() })
61598 button.on('click.intro', function() {
61599 button.on('click.intro', null);
61600 continueTo(choosePresetHouse);
61603 }, 400); // after preset list pane visible..
61606 context.on('enter.intro', function(mode) {
61607 if (!houseId || !context.hasEntity(houseId)) {
61608 return continueTo(addHouse);
61610 var ids = context.selectedIDs();
61611 if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) {
61612 return continueTo(chooseCategoryBuilding);
61616 function continueTo(nextStep) {
61617 select('.preset-list-button').on('click.intro', null);
61618 context.on('enter.intro', null);
61624 function choosePresetHouse() {
61625 if (!houseId || !context.hasEntity(houseId)) {
61628 var ids = context.selectedIDs();
61629 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
61630 context.enter(modeSelect(context, [houseId]));
61633 timeout$$1(function() {
61634 // reset pane, in case user somehow happened to change it..
61635 select('.inspector-wrap .panewrap').style('right', '-100%');
61637 var button = select('.preset-building-house .preset-list-button');
61639 reveal(button.node(),
61640 t('intro.buildings.choose_preset_house', { preset: housePreset.name() }),
61644 button.on('click.intro', function() {
61645 button.on('click.intro', null);
61646 continueTo(closeEditorHouse);
61648 }, 400); // after preset list pane visible..
61650 context.on('enter.intro', function(mode) {
61651 if (!houseId || !context.hasEntity(houseId)) {
61652 return continueTo(addHouse);
61654 var ids = context.selectedIDs();
61655 if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) {
61656 return continueTo(chooseCategoryBuilding);
61660 function continueTo(nextStep) {
61661 select('.preset-list-button').on('click.intro', null);
61662 context.on('enter.intro', null);
61668 function closeEditorHouse() {
61669 if (!houseId || !context.hasEntity(houseId)) {
61672 var ids = context.selectedIDs();
61673 if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) {
61674 context.enter(modeSelect(context, [houseId]));
61677 context.history().checkpoint('hasHouse');
61679 context.on('exit.intro', function() {
61680 continueTo(rightClickHouse);
61683 timeout$$1(function() {
61684 reveal('.entity-editor-pane',
61685 t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') })
61689 function continueTo(nextStep) {
61690 context.on('exit.intro', null);
61696 function rightClickHouse() {
61697 if (!houseId) return chapter.restart();
61699 context.enter(modeBrowse(context));
61700 context.history().reset('hasHouse');
61701 context.map().centerEase(house, 500);
61703 timeout$$1(function() {
61704 if (context.map().zoom() < 20) {
61705 context.map().zoomEase(20, 500);
61709 context.on('enter.intro', function(mode) {
61710 if (mode.id !== 'select') return;
61711 var ids = context.selectedIDs();
61712 if (ids.length !== 1 || ids[0] !== houseId) return;
61714 timeout$$1(function() {
61715 var node = selectMenuItem('orthogonalize').node();
61717 continueTo(clickSquare);
61718 }, 300); // after menu visible
61721 context.map().on('move.intro drawn.intro', function() {
61722 revealHouse(house, t('intro.buildings.rightclick_building'), { duration: 0 });
61725 context.history().on('change.intro', function() {
61726 continueTo(rightClickHouse);
61729 function continueTo(nextStep) {
61730 context.on('enter.intro', null);
61731 context.map().on('move.intro drawn.intro', null);
61732 context.history().on('change.intro', null);
61738 function clickSquare() {
61739 if (!houseId) return chapter.restart();
61740 var entity = context.hasEntity(houseId);
61741 if (!entity) return continueTo(rightClickHouse);
61743 var node = selectMenuItem('orthogonalize').node();
61744 if (!node) { return continueTo(rightClickHouse); }
61746 var wasChanged = false;
61747 var menuCoords = context.map().mouseCoordinates();
61749 revealEditMenu(menuCoords,
61750 t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') })
61753 context.on('enter.intro', function(mode) {
61754 if (mode.id === 'browse') {
61755 continueTo(rightClickHouse);
61756 } else if (mode.id === 'move' || mode.id === 'rotate') {
61757 continueTo(retryClickSquare);
61761 context.map().on('move.intro drawn.intro', function() {
61762 var node = selectMenuItem('orthogonalize').node();
61763 if (!wasChanged && !node) { return continueTo(rightClickHouse); }
61765 revealEditMenu(menuCoords,
61766 t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') }),
61771 context.history().on('change.intro', function() {
61773 context.history().on('change.intro', null);
61775 // Something changed. Wait for transition to complete and check undo annotation.
61776 timeout$$1(function() {
61777 if (context.history().undoAnnotation() === t('operations.orthogonalize.annotation.area')) {
61778 continueTo(doneSquare);
61780 continueTo(retryClickSquare);
61782 }, 500); // after transitioned actions
61785 function continueTo(nextStep) {
61786 context.on('enter.intro', null);
61787 context.map().on('move.intro drawn.intro', null);
61788 context.history().on('change.intro', null);
61794 function retryClickSquare() {
61795 context.enter(modeBrowse(context));
61797 revealHouse(house, t('intro.buildings.retry_square'), {
61798 buttonText: t('intro.ok'),
61799 buttonCallback: function() { continueTo(rightClickHouse); }
61802 function continueTo(nextStep) {
61808 function doneSquare() {
61809 context.history().checkpoint('doneSquare');
61811 revealHouse(house, t('intro.buildings.done_square'), {
61812 buttonText: t('intro.ok'),
61813 buttonCallback: function() { continueTo(addTank); }
61816 function continueTo(nextStep) {
61822 function addTank() {
61823 context.enter(modeBrowse(context));
61824 context.history().reset('doneSquare');
61827 var msec = transitionTime(tank, context.map().center());
61828 if (msec) { reveal(null, null, { duration: 0 }); }
61829 context.map().zoom(19.5).centerEase(tank, msec);
61831 timeout$$1(function() {
61832 reveal('button.add-area',
61833 t('intro.buildings.add_tank', { button: icon('#icon-area', 'pre-text') })
61836 context.on('enter.intro', function(mode) {
61837 if (mode.id !== 'add-area') return;
61838 continueTo(startTank);
61842 function continueTo(nextStep) {
61843 context.on('enter.intro', null);
61849 function startTank() {
61850 if (context.mode().id !== 'add-area') {
61851 return continueTo(addTank);
61856 timeout$$1(function() {
61857 revealTank(tank, t('intro.buildings.start_tank'));
61859 context.map().on('move.intro drawn.intro', function() {
61860 revealTank(tank, t('intro.buildings.start_tank'), { duration: 0 });
61863 context.on('enter.intro', function(mode) {
61864 if (mode.id !== 'draw-area') return chapter.restart();
61865 continueTo(continueTank);
61868 }, 550); // after easing
61870 function continueTo(nextStep) {
61871 context.map().on('move.intro drawn.intro', null);
61872 context.on('enter.intro', null);
61878 function continueTank() {
61879 if (context.mode().id !== 'draw-area') {
61880 return continueTo(addTank);
61885 revealTank(tank, t('intro.buildings.continue_tank'));
61887 context.map().on('move.intro drawn.intro', function() {
61888 revealTank(tank, t('intro.buildings.continue_tank'), { duration: 0 });
61891 context.on('enter.intro', function(mode) {
61892 if (mode.id === 'draw-area') {
61894 } else if (mode.id === 'select') {
61895 tankId = context.selectedIDs()[0];
61896 return continueTo(searchPresetTank);
61898 return continueTo(addTank);
61902 function continueTo(nextStep) {
61903 context.map().on('move.intro drawn.intro', null);
61904 context.on('enter.intro', null);
61910 function searchPresetTank() {
61911 if (!tankId || !context.hasEntity(tankId)) {
61914 var ids = context.selectedIDs();
61915 if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) {
61916 context.enter(modeSelect(context, [tankId]));
61919 timeout$$1(function() {
61920 // reset pane, in case user somehow happened to change it..
61921 select('.inspector-wrap .panewrap').style('right', '-100%');
61923 select('.preset-search-input')
61924 .on('keydown.intro', null)
61925 .on('keyup.intro', checkPresetSearch);
61927 reveal('.preset-search-input',
61928 t('intro.buildings.search_tank', { preset: tankPreset.name() })
61930 }, 400); // after preset list pane visible..
61932 context.on('enter.intro', function(mode) {
61933 if (!tankId || !context.hasEntity(tankId)) {
61934 return continueTo(addTank);
61937 var ids = context.selectedIDs();
61938 if (mode.id !== 'select' || !ids.length || ids[0] !== tankId) {
61939 // keep the user's area selected..
61940 context.enter(modeSelect(context, [tankId]));
61942 // reset pane, in case user somehow happened to change it..
61943 select('.inspector-wrap .panewrap').style('right', '-100%');
61945 select('.preset-search-input')
61946 .on('keydown.intro', null)
61947 .on('keyup.intro', checkPresetSearch);
61949 reveal('.preset-search-input',
61950 t('intro.buildings.search_tank', { preset: tankPreset.name() })
61953 context.history().on('change.intro', null);
61957 function checkPresetSearch() {
61958 var first = select('.preset-list-item:first-child');
61960 if (first.classed('preset-man_made-storage_tank')) {
61961 reveal(first.select('.preset-list-button').node(),
61962 t('intro.buildings.choose_tank', { preset: tankPreset.name() }),
61966 select('.preset-search-input')
61967 .on('keydown.intro', eventCancel, true)
61968 .on('keyup.intro', null);
61970 context.history().on('change.intro', function() {
61971 continueTo(closeEditorTank);
61976 function continueTo(nextStep) {
61977 context.on('enter.intro', null);
61978 context.history().on('change.intro', null);
61979 select('.preset-search-input').on('keydown.intro keyup.intro', null);
61985 function closeEditorTank() {
61986 if (!tankId || !context.hasEntity(tankId)) {
61989 var ids = context.selectedIDs();
61990 if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) {
61991 context.enter(modeSelect(context, [tankId]));
61994 context.history().checkpoint('hasTank');
61996 context.on('exit.intro', function() {
61997 continueTo(rightClickTank);
62000 timeout$$1(function() {
62001 reveal('.entity-editor-pane',
62002 t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') })
62006 function continueTo(nextStep) {
62007 context.on('exit.intro', null);
62013 function rightClickTank() {
62014 if (!tankId) return continueTo(addTank);
62016 context.enter(modeBrowse(context));
62017 context.history().reset('hasTank');
62018 context.map().centerEase(tank, 500);
62020 timeout$$1(function() {
62021 context.on('enter.intro', function(mode) {
62022 if (mode.id !== 'select') return;
62023 var ids = context.selectedIDs();
62024 if (ids.length !== 1 || ids[0] !== tankId) return;
62026 timeout$$1(function() {
62027 var node = selectMenuItem('circularize').node();
62029 continueTo(clickCircle);
62030 }, 300); // after menu visible
62033 revealTank(tank, t('intro.buildings.rightclick_tank'));
62035 context.map().on('move.intro drawn.intro', function() {
62036 revealTank(tank, t('intro.buildings.rightclick_tank'), { duration: 0 });
62039 context.history().on('change.intro', function() {
62040 continueTo(rightClickTank);
62045 function continueTo(nextStep) {
62046 context.on('enter.intro', null);
62047 context.map().on('move.intro drawn.intro', null);
62048 context.history().on('change.intro', null);
62054 function clickCircle() {
62055 if (!tankId) return chapter.restart();
62056 var entity = context.hasEntity(tankId);
62057 if (!entity) return continueTo(rightClickTank);
62059 var node = selectMenuItem('circularize').node();
62060 if (!node) { return continueTo(rightClickTank); }
62062 var wasChanged = false;
62063 var menuCoords = context.map().mouseCoordinates();
62065 revealEditMenu(menuCoords,
62066 t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') })
62069 context.on('enter.intro', function(mode) {
62070 if (mode.id === 'browse') {
62071 continueTo(rightClickTank);
62072 } else if (mode.id === 'move' || mode.id === 'rotate') {
62073 continueTo(retryClickCircle);
62077 context.map().on('move.intro drawn.intro', function() {
62078 var node = selectMenuItem('circularize').node();
62079 if (!wasChanged && !node) { return continueTo(rightClickTank); }
62081 revealEditMenu(menuCoords,
62082 t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') }),
62087 context.history().on('change.intro', function() {
62089 context.history().on('change.intro', null);
62091 // Something changed. Wait for transition to complete and check undo annotation.
62092 timeout$$1(function() {
62093 if (context.history().undoAnnotation() === t('operations.circularize.annotation.area')) {
62096 continueTo(retryClickCircle);
62098 }, 500); // after transitioned actions
62101 function continueTo(nextStep) {
62102 context.on('enter.intro', null);
62103 context.map().on('move.intro drawn.intro', null);
62104 context.history().on('change.intro', null);
62110 function retryClickCircle() {
62111 context.enter(modeBrowse(context));
62113 revealTank(tank, t('intro.buildings.retry_circle'), {
62114 buttonText: t('intro.ok'),
62115 buttonCallback: function() { continueTo(rightClickTank); }
62118 function continueTo(nextStep) {
62125 dispatch$$1.call('done');
62126 reveal('#id-container',
62127 t('intro.buildings.play', { next: t('intro.startediting.title') }), {
62128 tooltipBox: '.intro-nav-wrap .chapter-startEditing',
62129 buttonText: t('intro.ok'),
62130 buttonCallback: function() { reveal('#id-container'); }
62136 chapter.enter = function() {
62141 chapter.exit = function() {
62142 timeouts.forEach(window.clearTimeout);
62143 context.on('enter.intro exit.intro', null);
62144 context.map().on('move.intro drawn.intro', null);
62145 context.history().on('change.intro', null);
62146 select('.preset-search-input').on('keydown.intro keyup.intro', null);
62147 select('.more-fields .combobox-input').on('click.intro', null);
62151 chapter.restart = function() {
62157 return utilRebind(chapter, dispatch$$1, 'on');
62160 function uiIntroStartEditing(context, reveal) {
62161 var dispatch$$1 = dispatch('done', 'startEditing'),
62162 modalSelection = select(null);
62166 title: 'intro.startediting.title'
62170 function showHelp() {
62171 reveal('.map-control.help-control',
62172 t('intro.startediting.help', { button: icon('#icon-help', 'pre-text') }), {
62173 buttonText: t('intro.ok'),
62174 buttonCallback: function() { showSave(); }
62179 function showSave() {
62180 reveal('#bar button.save',
62181 t('intro.startediting.save'), {
62182 buttonText: t('intro.ok'),
62183 buttonCallback: function() { showStart(); }
62188 function showStart() {
62189 modalSelection = uiModal(context.container());
62191 modalSelection.select('.modal')
62192 .attr('class', 'modal-splash modal col6');
62194 modalSelection.selectAll('.close').remove();
62196 var startbutton = modalSelection.select('.content')
62197 .attr('class', 'fillL')
62199 .attr('class', 'modal-section huge-modal-button')
62200 .on('click', function() {
62201 modalSelection.remove();
62206 .attr('class', 'illustration')
62208 .attr('xlink:href', '#logo-walkthrough');
62212 .text(t('intro.startediting.start'));
62214 dispatch$$1.call('startEditing');
62218 chapter.enter = function() {
62223 chapter.exit = function() {
62224 modalSelection.remove();
62228 return utilRebind(chapter, dispatch$$1, 'on');
62232 welcome: uiIntroWelcome,
62233 navigation: uiIntroNavigation,
62234 point: uiIntroPoint,
62237 building: uiIntroBuilding,
62238 startEditing: uiIntroStartEditing
62241 var chapterFlow = [
62252 function uiIntro(context) {
62253 var introGraph = {},
62257 // create entities for intro graph and localize names
62258 for (var id in dataIntroGraph) {
62259 introGraph[id] = osmEntity$$1(localize(dataIntroGraph[id]));
62263 function intro(selection$$1) {
62264 context.enter(modeBrowse(context));
62266 // Save current map state
62267 var history = context.history().toJSON(),
62268 hash = window.location.hash,
62269 center = context.map().center(),
62270 zoom$$1 = context.map().zoom(),
62271 background = context.background().baseLayerSource(),
62272 overlays = context.background().overlayLayerSources(),
62273 opacity = selectAll('#map .layer-background').style('opacity'),
62274 loadedTiles = context.connection().loadedTiles(),
62275 baseEntities = context.history().graph().base().entities,
62276 countryCode = services.geocoder.countryCode;
62279 context.inIntro(true);
62281 // Load semi-real data used in intro
62282 context.connection().toggle(false).reset();
62283 context.history().reset();
62284 context.history().merge(values(coreGraph$$1().load(introGraph).entities));
62285 context.history().checkpoint('initial');
62286 context.background().bing();
62287 overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });
62290 services.geocoder.countryCode = function(location, callback) {
62291 callback(null, t('intro.graph.countrycode'));
62294 selectAll('#map .layer-background').style('opacity', 1);
62296 var curtain = uiCurtain();
62297 selection$$1.call(curtain);
62299 var chapters = chapterFlow.map(function(chapter, i) {
62300 var s = chapterUi[chapter](context, curtain.reveal)
62301 .on('done', function() {
62302 context.presets().init(); // clear away "recent" presets
62304 buttons.filter(function(d) {
62305 return d.title === s.title;
62306 }).classed('finished', true);
62308 if (i < chapterFlow.length - 1) {
62309 var next = chapterFlow[i + 1];
62310 select('button.chapter-' + next)
62311 .classed('next', true);
62317 chapters[chapters.length - 1].on('startEditing', function() {
62320 selectAll('#map .layer-background').style('opacity', opacity);
62321 context.connection().toggle(true).reset().loadedTiles(loadedTiles);
62322 context.history().reset().merge(values(baseEntities));
62323 context.background().baseLayerSource(background);
62324 overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });
62325 if (history) context.history().fromJSON(history, false);
62326 context.map().centerZoom(center, zoom$$1);
62327 window.location.replace(hash);
62328 services.geocoder.countryCode = countryCode;
62329 context.inIntro(false);
62332 var navwrap = selection$$1
62334 .attr('class', 'intro-nav-wrap fillD');
62338 .attr('class', 'intro-nav-wrap-logo')
62340 .attr('xlink:href', '#logo-walkthrough');
62342 var buttonwrap = navwrap
62344 .attr('class', 'joined')
62345 .selectAll('button.chapter');
62347 var buttons = buttonwrap
62351 .attr('class', function(d, i) { return 'chapter chapter-' + chapterFlow[i]; })
62352 .on('click', enterChapter);
62356 .text(function(d) { return t(d.title); });
62360 .attr('class', 'status')
62361 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'));
62363 enterChapter(chapters[0]);
62366 function enterChapter(newChapter) {
62367 if (currChapter) { currChapter.exit(); }
62368 context.enter(modeBrowse(context));
62370 currChapter = newChapter;
62371 currChapter.enter();
62374 .classed('next', false)
62375 .classed('active', function(d) {
62376 return d.title === currChapter.title;
62385 function uiHelp(context) {
62390 'help.editing_saving',
62399 var docs = docKeys.map(function(key) {
62400 var text$$1 = t(key);
62402 title: text$$1.split('\n')[0].replace('#', '').trim(),
62403 html: marked(text$$1.split('\n').slice(1).join('\n'))
62408 function help(selection$$1) {
62415 function toggle() {
62416 if (event) event.preventDefault();
62417 tooltipBehavior.hide(button);
62418 setVisible(!button.classed('active'));
62422 function setVisible(show) {
62423 if (show !== shown) {
62424 button.classed('active', show);
62428 selection$$1.on('mousedown.help-inside', function() {
62429 return event.stopPropagation();
62431 pane.style('display', 'block')
62432 .style('right', '-500px')
62435 .style('right', '0px');
62437 pane.style('right', '0px')
62440 .style('right', '-500px')
62441 .on('end', function() {
62442 select(this).style('display', 'none');
62444 selection$$1.on('mousedown.help-inside', null);
62450 function clickHelp(d, i) {
62451 var rtl = (textDirection === 'rtl');
62452 pane.property('scrollTop', 0);
62453 doctitle.html(d.title);
62456 body.selectAll('a')
62457 .attr('target', '_blank');
62458 menuItems.classed('selected', function(m) {
62459 return m.title === d.title;
62464 nav.call(drawNext).call(drawPrevious);
62466 nav.call(drawPrevious).call(drawNext);
62470 function drawNext(selection$$1) {
62471 if (i < docs.length - 1) {
62472 var nextLink = selection$$1
62474 .attr('class', 'next')
62475 .on('click', function() {
62476 clickHelp(docs[i + 1], i + 1);
62481 .text(docs[i + 1].title)
62482 .call(svgIcon((rtl ? '#icon-backward' : '#icon-forward'), 'inline'));
62487 function drawPrevious(selection$$1) {
62489 var prevLink = selection$$1
62491 .attr('class', 'previous')
62492 .on('click', function() {
62493 clickHelp(docs[i - 1], i - 1);
62497 .call(svgIcon((rtl ? '#icon-forward' : '#icon-backward'), 'inline'))
62499 .text(docs[i - 1].title);
62505 function clickWalkthrough() {
62506 if (context.inIntro()) return;
62507 context.container().call(uiIntro(context));
62512 var pane = selection$$1.append('div')
62513 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
62514 tooltipBehavior = tooltip()
62515 .placement((textDirection === 'rtl') ? 'right' : 'left')
62517 .title(uiTooltipHtml(t('help.title'), key)),
62518 button = selection$$1.append('button')
62519 .attr('tabindex', -1)
62520 .on('click', toggle)
62521 .call(svgIcon('#icon-help', 'light'))
62522 .call(tooltipBehavior),
62526 var toc = pane.append('ul')
62527 .attr('class', 'toc');
62529 var menuItems = toc.selectAll('li')
62534 .html(function(d) { return d.title; })
62535 .on('click', clickHelp);
62537 var walkthrough = toc
62539 .attr('class', 'walkthrough')
62541 .on('click', clickWalkthrough);
62545 .attr('class', 'logo logo-walkthrough')
62547 .attr('xlink:href', '#logo-walkthrough');
62551 .text(t('splash.walkthrough'));
62554 var content = pane.append('div')
62555 .attr('class', 'left-content');
62557 var doctitle = content.append('h2')
62558 .text(t('help.title'));
62560 var body = content.append('div')
62561 .attr('class', 'body');
62563 var nav = content.append('div')
62564 .attr('class', 'nav');
62566 clickHelp(docs[0], 0);
62568 var keybinding = d3keybinding('help')
62576 context.surface().on('mousedown.help-outside', hide);
62577 context.container().on('mousedown.help-outside', hide);
62583 function uiInfo(context) {
62584 var key = uiCmd('⌘I'),
62585 isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
62589 function info(selection$$1) {
62591 function radiansToMeters(r) {
62592 // using WGS84 authalic radius (6371007.1809 m)
62593 return r * 6371007.1809;
62596 function steradiansToSqmeters(r) {
62597 // http://gis.stackexchange.com/a/124857/40446
62598 return r / (4 * Math.PI) * 510065621724000;
62602 function toLineString(feature) {
62603 if (feature.type === 'LineString') return feature;
62605 var result = { type: 'LineString', coordinates: [] };
62606 if (feature.type === 'Polygon') {
62607 result.coordinates = feature.coordinates[0];
62608 } else if (feature.type === 'MultiPolygon') {
62609 result.coordinates = feature.coordinates[0][0];
62616 function displayLength(m) {
62617 var d = m * (isImperial ? 3.28084 : 1),
62636 // drop unnecessary precision
62637 p = d > 1000 ? 0 : d > 100 ? 1 : 2;
62639 return String(d.toFixed(p)) + ' ' + unit;
62643 function displayArea(m2) {
62644 var d = m2 * (isImperial ? 10.7639111056 : 1),
62645 d1, d2, p1, p2, unit1, unit2;
62648 if (d >= 6969600) { // > 0.25mi² show mi²
62656 if (d > 4356 && d < 43560000) { // 0.1 - 1000 acres
62662 if (d >= 250000) { // > 0.25km² show km²
62670 if (d > 1000 && d < 10000000) { // 0.1 - 1000 hectares
62676 // drop unnecessary precision
62677 p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
62678 p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
62680 return String(d1.toFixed(p1)) + ' ' + unit1 +
62681 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
62685 function redraw() {
62686 if (isHidden) return;
62688 var resolver = context.graph(),
62689 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
62690 singular = selected.length === 1 ? selected[0] : null,
62691 extent$$1 = geoExtent$$1(),
62696 .attr('class', 'infobox-heading fillD')
62697 .text(singular || t('infobox.selected', { n: selected.length }));
62699 if (!selected.length) return;
62702 for (var i = 0; i < selected.length; i++) {
62703 entity = context.entity(selected[i]);
62704 extent$$1._extend(entity.extent(resolver));
62706 center = extent$$1.center();
62709 var list = wrap.append('ul');
62711 // multiple features, just display extent center..
62714 .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
62718 // single feature, display details..
62719 if (!entity) return;
62720 var geometry = entity.geometry(resolver);
62722 if (geometry === 'line' || geometry === 'area') {
62723 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
62724 feature = entity.asGeoJSON(resolver),
62725 length = radiansToMeters(d3GeoLength(toLineString(feature))),
62726 lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
62727 centroid = d3GeoCentroid(feature);
62730 .text(t('infobox.geometry') + ': ' +
62731 (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
62734 var area$$1 = steradiansToSqmeters(entity.area(resolver));
62736 .text(t('infobox.area') + ': ' + displayArea(area$$1));
62740 .text(lengthLabel + ': ' + displayLength(length));
62743 .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
62746 var toggle = isImperial ? 'imperial' : 'metric';
62748 .text(t('infobox.' + toggle))
62750 .attr('class', 'button')
62751 .on('click', function() {
62752 event.preventDefault();
62753 isImperial = !isImperial;
62758 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
62761 .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
62764 .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
62769 function toggle() {
62771 event.preventDefault();
62774 isHidden = !isHidden;
62778 .style('display', 'block')
62779 .style('opacity', 1)
62782 .style('opacity', 0)
62783 .on('end', function() {
62784 select(this).style('display', 'none');
62788 .style('display', 'block')
62789 .style('opacity', 0)
62792 .style('opacity', 1)
62793 .on('end', function() {
62800 var wrap = selection$$1.selectAll('.infobox')
62803 wrap = wrap.enter()
62805 .attr('class', 'infobox fillD2')
62806 .style('display', (isHidden ? 'none' : 'block'))
62810 .on('drawn.info', redraw);
62814 var keybinding = d3keybinding('info')
62824 function uiMapData(context) {
62826 features = context.features().keys(),
62827 layers = context.layers(),
62828 fills = ['wireframe', 'partial', 'full'],
62829 fillDefault = context.storage('area-fill') || 'partial',
62830 fillSelected = fillDefault;
62833 function map_data(selection$$1) {
62835 function showsFeature(d) {
62836 return context.features().enabled(d);
62840 function autoHiddenFeature(d) {
62841 return context.features().autoHidden(d);
62845 function clickFeature(d) {
62846 context.features().toggle(d);
62851 function showsFill(d) {
62852 return fillSelected === d;
62856 function setFill(d) {
62857 lodash.each(fills, function(opt) {
62858 context.surface().classed('fill-' + opt, Boolean(opt === d));
62862 if (d !== 'wireframe') {
62864 context.storage('area-fill', d);
62870 function showsLayer(which) {
62871 var layer = layers.layer(which);
62873 return layer.enabled();
62879 function setLayer(which, enabled) {
62880 var layer = layers.layer(which);
62882 layer.enabled(enabled);
62888 function toggleLayer(which) {
62889 setLayer(which, !showsLayer(which));
62893 function clickGpx() {
62894 toggleLayer('gpx');
62898 function clickMapillaryImages() {
62899 toggleLayer('mapillary-images');
62900 if (!showsLayer('mapillary-images')) {
62901 setLayer('mapillary-signs', false);
62906 function clickMapillarySigns() {
62907 toggleLayer('mapillary-signs');
62911 function drawMapillaryItems(selection$$1) {
62912 var mapillaryImages = layers.layer('mapillary-images'),
62913 mapillarySigns = layers.layer('mapillary-signs'),
62914 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
62915 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
62916 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
62917 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
62919 var mapillaryList = selection$$1
62920 .selectAll('.layer-list-mapillary')
62923 mapillaryList = mapillaryList.enter()
62925 .attr('class', 'layer-list layer-list-mapillary')
62926 .merge(mapillaryList);
62929 var mapillaryImageLayerItem = mapillaryList
62930 .selectAll('.list-item-mapillary-images')
62931 .data(supportsMapillaryImages ? [0] : []);
62933 mapillaryImageLayerItem.exit()
62936 var enterImages = mapillaryImageLayerItem.enter()
62938 .attr('class', 'list-item-mapillary-images');
62940 var labelImages = enterImages
62943 .title(t('mapillary_images.tooltip'))
62944 .placement('top'));
62948 .attr('type', 'checkbox')
62949 .on('change', clickMapillaryImages);
62953 .text(t('mapillary_images.title'));
62956 var mapillarySignLayerItem = mapillaryList
62957 .selectAll('.list-item-mapillary-signs')
62958 .data(supportsMapillarySigns ? [0] : []);
62960 mapillarySignLayerItem.exit()
62963 var enterSigns = mapillarySignLayerItem.enter()
62965 .attr('class', 'list-item-mapillary-signs');
62967 var labelSigns = enterSigns
62970 .title(t('mapillary_signs.tooltip'))
62971 .placement('top'));
62975 .attr('type', 'checkbox')
62976 .on('change', clickMapillarySigns);
62980 .text(t('mapillary_signs.title'));
62984 mapillaryImageLayerItem = mapillaryImageLayerItem
62985 .merge(enterImages);
62987 mapillaryImageLayerItem
62988 .classed('active', showsMapillaryImages)
62989 .selectAll('input')
62990 .property('checked', showsMapillaryImages);
62993 mapillarySignLayerItem = mapillarySignLayerItem
62994 .merge(enterSigns);
62996 mapillarySignLayerItem
62997 .classed('active', showsMapillarySigns)
62998 .selectAll('input')
62999 .property('disabled', !showsMapillaryImages)
63000 .property('checked', showsMapillarySigns);
63002 mapillarySignLayerItem
63003 .selectAll('label')
63004 .classed('deemphasize', !showsMapillaryImages);
63008 function drawGpxItem(selection$$1) {
63009 var gpx = layers.layer('gpx'),
63010 hasGpx = gpx && gpx.hasGpx(),
63011 showsGpx = hasGpx && gpx.enabled();
63013 var gpxLayerItem = selection$$1
63014 .selectAll('.layer-list-gpx')
63015 .data(gpx ? [0] : []);
63018 gpxLayerItem.exit()
63022 var enter = gpxLayerItem.enter()
63024 .attr('class', 'layer-list layer-list-gpx')
63026 .classed('list-item-gpx', true);
63030 .attr('class', 'list-item-gpx-extent')
63032 .title(t('gpx.zoom'))
63033 .placement((textDirection === 'rtl') ? 'right' : 'left'))
63034 .on('click', function() {
63035 event.preventDefault();
63036 event.stopPropagation();
63039 .call(svgIcon('#icon-search'));
63043 .attr('class', 'list-item-gpx-browse')
63045 .title(t('gpx.browse'))
63046 .placement((textDirection === 'rtl') ? 'right' : 'left'))
63047 .on('click', function() {
63048 select(document.createElement('input'))
63049 .attr('type', 'file')
63050 .on('change', function() {
63051 gpx.files(event.target.files);
63055 .call(svgIcon('#icon-geolocate'));
63057 var labelGpx = enter
63059 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
63063 .attr('type', 'checkbox')
63064 .on('change', clickGpx);
63068 .text(t('gpx.local_layer'));
63072 gpxLayerItem = gpxLayerItem
63076 .classed('active', showsGpx)
63077 .selectAll('input')
63078 .property('disabled', !hasGpx)
63079 .property('checked', showsGpx);
63082 .selectAll('label')
63083 .classed('deemphasize', !hasGpx);
63087 function drawList(selection$$1, data, type, name, change, active$$1) {
63088 var items = selection$$1.selectAll('li')
63096 var enter = items.enter()
63098 .attr('class', 'layer')
63101 .title(function(d) {
63102 var tip = t(name + '.' + d + '.tooltip'),
63103 key = (d === 'wireframe' ? 'W' : null);
63105 if (name === 'feature' && autoHiddenFeature(d)) {
63106 tip += '<div>' + t('map_data.autohidden') + '</div>';
63108 return uiTooltipHtml(tip, key);
63118 .attr('type', type)
63119 .attr('name', name)
63120 .on('change', change);
63124 .text(function(d) { return t(name + '.' + d + '.description'); });
63131 .classed('active', active$$1)
63132 .selectAll('input')
63133 .property('checked', active$$1)
63134 .property('indeterminate', function(d) {
63135 return (name === 'feature' && autoHiddenFeature(d));
63140 function update() {
63141 dataLayerContainer.call(drawMapillaryItems);
63142 dataLayerContainer.call(drawGpxItem);
63144 fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
63145 featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
63149 function hidePanel() {
63154 function togglePanel() {
63155 if (event) event.preventDefault();
63156 tooltipBehavior.hide(button);
63157 setVisible(!button.classed('active'));
63161 function toggleWireframe() {
63163 event.preventDefault();
63164 event.stopPropagation();
63166 setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
63167 context.map().pan([0,0]); // trigger a redraw
63171 function setVisible(show) {
63172 if (show !== shown) {
63173 button.classed('active', show);
63178 selection$$1.on('mousedown.map_data-inside', function() {
63179 return event.stopPropagation();
63181 content.style('display', 'block')
63182 .style('right', '-300px')
63185 .style('right', '0px');
63187 content.style('display', 'block')
63188 .style('right', '0px')
63191 .style('right', '-300px')
63192 .on('end', function() {
63193 select(this).style('display', 'none');
63195 selection$$1.on('mousedown.map_data-inside', null);
63201 var content = selection$$1
63203 .attr('class', 'fillL map-overlay col3 content hide'),
63204 tooltipBehavior = tooltip()
63205 .placement((textDirection === 'rtl') ? 'right' : 'left')
63207 .title(uiTooltipHtml(t('map_data.description'), key)),
63208 button = selection$$1
63210 .attr('tabindex', -1)
63211 .on('click', togglePanel)
63212 .call(svgIcon('#icon-data', 'light'))
63213 .call(tooltipBehavior),
63218 .text(t('map_data.title'));
63224 .text(t('map_data.data_layers'))
63226 .classed('hide-toggle', true)
63227 .classed('expanded', true)
63228 .on('click', function() {
63229 var exp = select(this).classed('expanded');
63230 dataLayerContainer.style('display', exp ? 'none' : 'block');
63231 select(this).classed('expanded', !exp);
63232 event.preventDefault();
63235 var dataLayerContainer = content
63237 .attr('class', 'data-data-layers')
63238 .style('display', 'block');
63244 .text(t('map_data.fill_area'))
63246 .classed('hide-toggle', true)
63247 .classed('expanded', false)
63248 .on('click', function() {
63249 var exp = select(this).classed('expanded');
63250 fillContainer.style('display', exp ? 'none' : 'block');
63251 select(this).classed('expanded', !exp);
63252 event.preventDefault();
63255 var fillContainer = content
63257 .attr('class', 'data-area-fills')
63258 .style('display', 'none');
63260 var fillList = fillContainer
63262 .attr('class', 'layer-list layer-fill-list');
63268 .text(t('map_data.map_features'))
63270 .classed('hide-toggle', true)
63271 .classed('expanded', false)
63272 .on('click', function() {
63273 var exp = select(this).classed('expanded');
63274 featureContainer.style('display', exp ? 'none' : 'block');
63275 select(this).classed('expanded', !exp);
63276 event.preventDefault();
63279 var featureContainer = content
63281 .attr('class', 'data-feature-filters')
63282 .style('display', 'none');
63284 var featureList = featureContainer
63286 .attr('class', 'layer-list layer-feature-list');
63290 .on('change.map_data-update', update);
63292 setFill(fillDefault);
63294 var keybinding = d3keybinding('features')
63295 .on(key, togglePanel)
63296 .on('W', toggleWireframe)
63297 .on('B', hidePanel)
63298 .on('H', hidePanel);
63303 context.surface().on('mousedown.map_data-outside', hidePanel);
63304 context.container().on('mousedown.map_data-outside', hidePanel);
63311 function uiModes(context) {
63313 modeAddPoint$$1(context),
63314 modeAddLine$$1(context),
63315 modeAddArea$$1(context)
63319 function editable() {
63320 return context.editable() && context.mode().id !== 'save';
63324 return function(selection$$1) {
63325 var buttons = selection$$1.selectAll('button.add-button')
63328 buttons = buttons.enter()
63330 .attr('tabindex', -1)
63331 .attr('class', function(mode) { return mode.id + ' add-button col4'; })
63332 .on('click.mode-buttons', function(mode) {
63333 if (mode.id === context.mode().id) {
63334 context.enter(modeBrowse(context));
63336 context.enter(mode);
63340 .placement('bottom')
63342 .title(function(mode) {
63343 return uiTooltipHtml(mode.description, mode.key);
63348 .on('move.modes', lodash.debounce(update, 500));
63351 .on('enter.modes', update);
63354 .each(function(d) {
63356 .call(svgIcon('#icon-' + d.button, 'pre-text'));
63361 .attr('class', 'label')
63362 .text(function(mode) { return mode.title; });
63365 .on('enter.editor', function(entered) {
63366 selection$$1.selectAll('button.add-button')
63367 .classed('active', function(mode) { return entered.button === mode.button; });
63368 context.container()
63369 .classed('mode-' + entered.id, true);
63373 .on('exit.editor', function(exited) {
63374 context.container()
63375 .classed('mode-' + exited.id, false);
63378 var keybinding = d3keybinding('mode-buttons');
63380 modes.forEach(function(mode) {
63381 keybinding.on(mode.key, function() {
63383 if (mode.id === context.mode().id) {
63384 context.enter(modeBrowse(context));
63386 context.enter(mode);
63396 function update() {
63397 selection$$1.selectAll('button.add-button')
63398 .property('disabled', !editable());
63403 function uiRestore(context) {
63405 return function(selection) {
63406 if (!context.history().lock() || !context.history().restorableChanges())
63409 var modalSelection = uiModal(selection, true);
63411 modalSelection.select('.modal')
63412 .attr('class', 'modal fillL col6');
63414 var introModal = modalSelection.select('.content');
63417 .attr('class','cf');
63421 .attr('class', 'modal-section')
63423 .text(t('restore.heading'));
63427 .attr('class','modal-section')
63429 .text(t('restore.description'));
63431 var buttonWrap = introModal
63433 .attr('class', 'modal-actions cf');
63435 var restore = buttonWrap
63437 .attr('class', 'restore col6')
63438 .on('click', function() {
63439 context.history().restore();
63440 modalSelection.remove();
63445 .attr('class', 'logo logo-restore')
63447 .attr('xlink:href', '#logo-restore');
63451 .text(t('restore.restore'));
63453 var reset = buttonWrap
63455 .attr('class', 'reset col6')
63456 .on('click', function() {
63457 context.history().clearSaved();
63458 modalSelection.remove();
63463 .attr('class', 'logo logo-reset')
63465 .attr('xlink:href', '#logo-reset');
63469 .text(t('restore.reset'));
63471 restore.node().focus();
63475 function uiSave(context) {
63476 var history = context.history(),
63480 function saving() {
63481 return context.mode().id === 'save';
63486 event.preventDefault();
63487 if (!context.inIntro() && !saving() && history.hasChanges()) {
63488 context.enter(modeSave$$1(context));
63493 function getBackground(numChanges) {
63495 if (numChanges === 0) {
63497 } else if (numChanges <= 50) {
63498 step = numChanges / 50;
63499 return interpolateRgb('#fff', '#ff8')(step); // white -> yellow
63501 step = Math.min((numChanges - 50) / 50, 1.0);
63502 return interpolateRgb('#ff8', '#f88')(step); // yellow -> red
63507 return function(selection$$1) {
63508 var numChanges = 0;
63510 function updateCount() {
63511 var _ = history.difference().summary().length;
63512 if (_ === numChanges) return;
63516 .title(uiTooltipHtml(
63517 t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key)
63520 var background = getBackground(numChanges);
63523 .classed('disabled', numChanges === 0)
63524 .classed('has-count', numChanges > 0)
63525 .style('background', background);
63527 button.select('span.count')
63529 .style('background', background)
63530 .style('border-color', background);
63534 var tooltipBehavior = tooltip()
63535 .placement('bottom')
63537 .title(uiTooltipHtml(t('save.no_changes'), key));
63539 var button = selection$$1
63541 .attr('class', 'save col12 disabled')
63542 .attr('tabindex', -1)
63544 .call(tooltipBehavior);
63547 .call(svgIcon('#icon-save', 'pre-text'))
63549 .attr('class', 'label')
63550 .text(t('save.title'));
63554 .attr('class', 'count')
63560 var keybinding = d3keybinding('save')
63561 .on(key, save, true);
63567 .on('change.save', updateCount);
63570 .on('enter.save', function() {
63571 button.property('disabled', saving());
63572 if (saving()) button.call(tooltipBehavior.hide);
63577 function uiScale(context) {
63578 var projection = context.projection,
63579 isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
63584 function scaleDefs(loc1, loc2) {
63585 var lat = (loc2[1] + loc1[1]) / 2,
63586 conversion = (isImperial ? 3.28084 : 1),
63587 dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
63588 scale = { dist: 0, px: 0, text: '' },
63589 buckets, i, val, dLon;
63592 buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
63594 buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
63597 // determine a user-friendly endpoint for the scale
63598 for (i = 0; i < buckets.length; i++) {
63601 scale.dist = Math.floor(dist / val) * val;
63604 scale.dist = +dist.toFixed(2);
63608 dLon = geoMetersToLon(scale.dist / conversion, lat);
63609 scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
63612 if (scale.dist >= 5280) {
63613 scale.dist /= 5280;
63614 scale.text = String(scale.dist) + ' mi';
63616 scale.text = String(scale.dist) + ' ft';
63619 if (scale.dist >= 1000) {
63620 scale.dist /= 1000;
63621 scale.text = String(scale.dist) + ' km';
63623 scale.text = String(scale.dist) + ' m';
63631 function update(selection) {
63632 // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
63633 var dims = context.map().dimensions(),
63634 loc1 = projection.invert([0, dims[1]]),
63635 loc2 = projection.invert([maxLength, dims[1]]),
63636 scale = scaleDefs(loc1, loc2);
63638 selection.select('#scale-path')
63639 .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
63641 selection.select('#scale-textgroup')
63642 .attr('transform', 'translate(' + (scale.px + 8) + ',' + tickHeight + ')');
63644 selection.select('#scale-text')
63649 return function(selection) {
63650 function switchUnits() {
63651 isImperial = !isImperial;
63652 selection.call(update);
63655 var scalegroup = selection.append('svg')
63656 .attr('id', 'scale')
63657 .on('click', switchUnits)
63659 .attr('transform', 'translate(10,11)');
63663 .attr('id', 'scale-path');
63667 .attr('id', 'scale-textgroup')
63669 .attr('id', 'scale-text');
63671 selection.call(update);
63673 context.map().on('move.scale', function() {
63679 var pair_1 = pair$1;
63680 function search(x, dims, r) {
63681 if (!dims) dims = 'NSEW';
63682 if (typeof x !== 'string') return { val: null, regex: r };
63683 r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
63685 if (!m) return { val: null, regex: r };
63686 else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
63688 val: (((m[1]) ? parseFloat(m[1]) : 0) +
63689 ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
63690 ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
63691 ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
63698 function pair$1(x, dims) {
63700 var one = search(x, dims);
63701 if (one.val === null) return null;
63702 var two = search(x, dims, one.regex);
63703 if (two.val === null) return null;
63704 // null if one/two are not contiguous.
63705 if (one.raw + two.raw !== x) return null;
63707 return swapdim(one.val, two.val, one.dim);
63709 return [one.val, two.val];
63713 function swapdim(a, b, dim) {
63714 if (dim === 'N' || dim === 'S') return [a, b];
63715 if (dim === 'W' || dim === 'E') return [b, a];
63718 function uiFeatureList(context) {
63719 var geocodeResults;
63722 function featureList(selection$$1) {
63723 var header = selection$$1
63725 .attr('class', 'header fillL cf');
63727 header.append('h3')
63728 .text(t('inspector.feature_list'));
63730 var searchWrap = selection$$1
63732 .attr('class', 'search-header');
63734 var search = searchWrap
63736 .attr('placeholder', t('inspector.search'))
63737 .attr('type', 'search')
63739 .on('keypress', keypress)
63740 .on('input', inputevent);
63743 .call(svgIcon('#icon-search', 'pre-text'));
63745 var listWrap = selection$$1
63747 .attr('class', 'inspector-body');
63749 var list = listWrap
63751 .attr('class', 'feature-list cf');
63754 .on('exit.feature-list', clearSearch);
63756 .on('drawn.feature-list', mapDrawn);
63759 function keypress() {
63760 var q = search.property('value'),
63761 items = list.selectAll('.feature-list-item');
63762 if (event.keyCode === 13 && q.length && items.size()) {
63763 click(items.datum());
63768 function inputevent() {
63769 geocodeResults = undefined;
63774 function clearSearch() {
63775 search.property('value', '');
63780 function mapDrawn(e) {
63787 function features() {
63790 graph = context.graph(),
63791 q = search.property('value').toLowerCase();
63793 if (!q) return result;
63795 var idMatch = q.match(/^([nwr])([0-9]+)$/);
63800 geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
63801 type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
63806 var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
63808 if (locationMatch) {
63809 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
63813 type: t('inspector.location'),
63814 name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
63819 function addEntity(entity) {
63820 if (entity.id in entities || result.length > 200)
63823 entities[entity.id] = true;
63825 var name = utilDisplayName(entity) || '';
63826 if (name.toLowerCase().indexOf(q) >= 0) {
63827 var matched = context.presets().match(entity, graph),
63828 type = (matched && matched.name()) || utilDisplayType(entity.id);
63832 geometry: context.geometry(entity.id),
63838 graph.parentRelations(entity).forEach(function(parent) {
63843 var visible = context.surface().selectAll('.point, .line, .area').nodes();
63844 for (var i = 0; i < visible.length && result.length <= 200; i++) {
63845 addEntity(visible[i].__data__);
63848 (geocodeResults || []).forEach(function(d) {
63849 // https://github.com/openstreetmap/iD/issues/1890
63850 if (d.osm_type && d.osm_id) {
63852 id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
63853 geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
63854 type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
63855 : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
63856 name: d.display_name,
63857 extent: new geoExtent$$1(
63858 [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
63859 [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
63868 function drawList() {
63869 var value = search.property('value'),
63870 results = features();
63872 list.classed('filtered', value.length);
63874 var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
63876 var resultsIndicator = list.selectAll('.no-results-item')
63878 .enter().append('button')
63879 .property('disabled', true)
63880 .attr('class', 'no-results-item')
63881 .call(svgIcon('#icon-alert', 'pre-text'));
63883 resultsIndicator.append('span')
63884 .attr('class', 'entity-name');
63886 list.selectAll('.no-results-item .entity-name')
63887 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
63889 list.selectAll('.geocode-item')
63891 .enter().append('button')
63892 .attr('class', 'geocode-item')
63893 .on('click', geocoderSearch)
63895 .attr('class', 'label')
63897 .attr('class', 'entity-name')
63898 .text(t('geocoder.search'));
63900 list.selectAll('.no-results-item')
63901 .style('display', (value.length && !results.length) ? 'block' : 'none');
63903 list.selectAll('.geocode-item')
63904 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
63906 list.selectAll('.feature-list-item')
63910 var items = list.selectAll('.feature-list-item')
63911 .data(results, function(d) { return d.id; });
63913 var enter = items.enter()
63914 .insert('button', '.geocode-item')
63915 .attr('class', 'feature-list-item')
63916 .on('mouseover', mouseover)
63917 .on('mouseout', mouseout)
63918 .on('click', click);
63922 .attr('class', 'label');
63924 label.each(function(d) {
63926 .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
63929 label.append('span')
63930 .attr('class', 'entity-type')
63931 .text(function(d) { return d.type; });
63933 label.append('span')
63934 .attr('class', 'entity-name')
63935 .text(function(d) { return d.name; });
63937 enter.style('opacity', 0)
63939 .style('opacity', 1);
63948 function mouseover(d) {
63949 if (d.id === -1) return;
63951 context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
63952 .classed('hover', true);
63956 function mouseout() {
63957 context.surface().selectAll('.hover')
63958 .classed('hover', false);
63962 function click(d) {
63963 event.preventDefault();
63965 context.map().centerZoom([d.location[1], d.location[0]], 20);
63967 else if (d.entity) {
63968 if (d.entity.type === 'node') {
63969 context.map().center(d.entity.loc);
63970 } else if (d.entity.type === 'way') {
63971 var center = context.projection(context.map().center()),
63972 edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
63973 context.map().center(edge.loc);
63975 context.enter(modeSelect(context, [d.entity.id]));
63977 context.zoomToEntity(d.id);
63982 function geocoderSearch() {
63983 services.geocoder.search(search.property('value'), function (err, resp) {
63984 geocodeResults = resp || [];
63991 return featureList;
63994 function uiPresetIcon() {
63995 var preset, geometry;
63998 function presetIcon(selection$$1) {
63999 selection$$1.each(render);
64003 function getIcon(p, geom) {
64006 else if (geom === 'line')
64007 return 'other-line';
64008 else if (geom === 'vertex')
64009 return p.isFallback() ? '' : 'poi-vertex';
64011 return 'marker-stroked';
64015 function render() {
64016 var selection$$1 = select(this),
64017 p = preset.apply(this, arguments),
64018 geom = geometry.apply(this, arguments),
64019 picon = getIcon(p, geom),
64020 isPoi = picon.match(/^poi-/) !== null,
64021 isMaki = dataFeatureIcons.indexOf(picon) !== -1,
64022 isFramed = (geom === 'area' || geom === 'verex');
64025 function tag_classes(p) {
64027 for (var i in p.tags) {
64029 if (p.tags[i] !== '*') {
64030 s += ' tag-' + i + '-' + p.tags[i];
64037 var fill = selection$$1.selectAll('.preset-icon-fill')
64040 fill = fill.enter()
64045 .attr('class', function() {
64046 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
64050 var areaFrame = selection$$1.selectAll('.preset-icon-frame')
64051 .data((geom === 'area') ? [0] : []);
64056 areaFrame = areaFrame.enter()
64058 .attr('class', 'preset-icon-frame')
64059 .call(svgIcon('#preset-icon-frame'));
64062 var icon = selection$$1.selectAll('.preset-icon')
64065 icon = icon.enter()
64067 .attr('class', 'preset-icon')
64072 .attr('class', 'preset-icon preset-icon-' +
64073 ((isMaki || isPoi) ? (isFramed ? '24' : '28') : (isFramed ? '44' : '60'))
64076 icon.selectAll('svg')
64077 .attr('class', function() {
64078 return 'icon ' + picon + (isMaki || isPoi ? '' : tag_classes(p));
64081 icon.selectAll('use')
64082 .attr('href', '#' + picon + (isMaki ? '-15' : ''));
64086 presetIcon.preset = function(_) {
64087 if (!arguments.length) return preset;
64088 preset = utilFunctor(_);
64093 presetIcon.geometry = function(_) {
64094 if (!arguments.length) return geometry;
64095 geometry = utilFunctor(_);
64102 function d3combobox() {
64103 var dispatch$$1 = dispatch('accept'),
64104 container = select(document.body),
64108 caseSensitive = false;
64110 var fetcher = function(val, cb) {
64111 cb(data.filter(function(d) {
64115 .indexOf(val.toLowerCase()) !== -1;
64119 var combobox = function(input, attachTo) {
64121 wrapper = container
64122 .selectAll('div.combobox')
64123 .filter(function(d) { return d === input.node(); }),
64124 shown = !wrapper.empty();
64127 .classed('combobox-input', true)
64128 .on('focus.typeahead', focus)
64129 .on('blur.typeahead', blur)
64130 .on('keydown.typeahead', keydown)
64131 .on('keyup.typeahead', keyup)
64132 .on('input.typeahead', change)
64134 var parent = this.parentNode,
64135 sibling = this.nextSibling;
64137 var caret = select(parent).selectAll('.combobox-caret')
64138 .filter(function(d) { return d === input.node(); })
64139 .data([input.node()]);
64141 caret = caret.enter()
64142 .insert('div', function() { return sibling; })
64143 .attr('class', 'combobox-caret')
64147 .on('mousedown', function () {
64148 // prevent the form element from blurring. it blurs
64150 event.stopPropagation();
64151 event.preventDefault();
64153 input.node().focus();
64162 fetch(value(), render);
64166 window.setTimeout(hide, 150);
64171 wrapper = container
64172 .insert('div', ':first-child')
64173 .datum(input.node())
64174 .attr('class', 'combobox')
64175 .style('position', 'absolute')
64176 .style('display', 'block')
64177 .style('left', '0px')
64178 .on('mousedown', function () {
64179 // prevent moving focus out of the text field
64180 event.preventDefault();
64184 .on('scroll.combobox', render, true);
64196 .on('scroll.combobox', null);
64202 function keydown() {
64203 switch (event.keyCode) {
64204 // backspace, delete
64207 input.on('input.typeahead', function() {
64210 var start = input.property('selectionStart');
64211 input.node().setSelectionRange(start, start);
64212 input.on('input.typeahead', change);
64217 wrapper.selectAll('a.selected').each(function (d) {
64218 dispatch$$1.call('accept', this, d);
64224 event.preventDefault();
64229 event.preventDefault();
64234 event.preventDefault();
64237 event.stopPropagation();
64241 switch (event.keyCode) {
64248 wrapper.selectAll('a.selected').each(function (d) {
64249 dispatch$$1.call('accept', this, d);
64256 function change() {
64257 fetch(value(), function() {
64258 if (input.property('selectionEnd') === input.property('value').length) {
64265 function nav(dir) {
64266 if (!suggestions.length) return;
64267 idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
64268 input.property('value', suggestions[idx].value);
64274 var value = input.property('value'),
64275 start = input.property('selectionStart'),
64276 end = input.property('selectionEnd');
64278 if (start && end) {
64279 value = value.substring(0, start);
64285 function fetch(v, cb) {
64286 fetcher.call(input, v, function(_) {
64292 function autocomplete() {
64293 var v = caseSensitive ? value() : value().toLowerCase();
64297 for (var i = 0; i < suggestions.length; i++) {
64298 var suggestion = suggestions[i].value,
64299 compare = caseSensitive ? suggestion : suggestion.toLowerCase();
64301 if (compare.indexOf(v) === 0) {
64303 input.property('value', suggestion);
64304 input.node().setSelectionRange(v.length, suggestion.length);
64310 function render() {
64311 if (suggestions.length >= minItems && document.activeElement === input.node()) {
64318 var options = wrapper
64319 .selectAll('a.combobox-option')
64320 .data(suggestions, function(d) { return d.value; });
64327 .attr('class', 'combobox-option')
64328 .text(function(d) { return d.value; })
64330 .attr('title', function(d) { return d.title; })
64331 .classed('selected', function(d, i) { return i === idx; })
64332 .on('mouseover', select$$1)
64333 .on('click', accept)
64337 var node = attachTo ? attachTo.node() : input.node(),
64338 rect = node.getBoundingClientRect();
64341 .style('left', rect.left + 'px')
64342 .style('width', rect.width + 'px')
64343 .style('top', rect.height + rect.top + 'px');
64346 function select$$1(d, i) {
64351 function ensureVisible() {
64352 var node = wrapper.selectAll('a.selected').node();
64353 if (node) node.scrollIntoView();
64356 function accept(d) {
64357 if (!shown) return;
64358 input.property('value', d.value);
64359 utilTriggerEvent(input, 'change');
64360 dispatch$$1.call('accept', this, d);
64365 combobox.fetcher = function(_) {
64366 if (!arguments.length) return fetcher;
64371 combobox.data = function(_) {
64372 if (!arguments.length) return data;
64377 combobox.minItems = function(_) {
64378 if (!arguments.length) return minItems;
64383 combobox.caseSensitive = function(_) {
64384 if (!arguments.length) return caseSensitive;
64389 combobox.container = function(_) {
64390 if (!arguments.length) return container;
64395 return utilRebind(combobox, dispatch$$1, 'on');
64399 d3combobox.off = function(input) {
64401 .on('focus.typeahead', null)
64402 .on('blur.typeahead', null)
64403 .on('keydown.typeahead', null)
64404 .on('keyup.typeahead', null)
64405 .on('input.typeahead', null)
64407 select(this.parentNode).selectAll('.combobox-caret')
64408 .filter(function(d) { return d === input.node(); })
64409 .on('mousedown', null);
64413 .on('scroll.combobox', null);
64416 function uiDisclosure() {
64417 var dispatch$$1 = dispatch('toggled'),
64420 content = function () {};
64423 var disclosure = function(selection$$1) {
64424 var hideToggle = selection$$1.selectAll('.hide-toggle')
64427 hideToggle = hideToggle.enter()
64430 .attr('class', 'hide-toggle')
64431 .merge(hideToggle);
64435 .on('click', toggle)
64436 .classed('expanded', expanded);
64439 var wrap = selection$$1.selectAll('div')
64442 wrap = wrap.enter()
64447 .classed('hide', !expanded)
64451 function toggle() {
64452 expanded = !expanded;
64453 hideToggle.classed('expanded', expanded);
64454 wrap.call(uiToggle(expanded));
64455 dispatch$$1.call('toggled', this, expanded);
64460 disclosure.title = function(_) {
64461 if (!arguments.length) return title;
64467 disclosure.expanded = function(_) {
64468 if (!arguments.length) return expanded;
64474 disclosure.content = function(_) {
64475 if (!arguments.length) return content;
64481 return utilRebind(disclosure, dispatch$$1, 'on');
64484 function uiRawMemberEditor(context) {
64486 taginfo = services.taginfo;
64489 function selectMember(d) {
64490 event.preventDefault();
64491 context.enter(modeSelect(context, [d.id]));
64495 function changeRole(d) {
64496 var role = select(this).property('value');
64497 var member = { id: d.id, type: d.type, role: role };
64499 actionChangeMember(d.relation.id, member, d.index),
64500 t('operations.change_role.annotation')
64505 function deleteMember(d) {
64507 actionDeleteMember(d.relation.id, d.index),
64508 t('operations.delete_member.annotation')
64511 if (!context.hasEntity(d.relation.id)) {
64512 context.enter(modeBrowse(context));
64517 function rawMemberEditor(selection$$1) {
64518 var entity = context.entity(id),
64521 entity.members.slice(0, 1000).forEach(function(member, index) {
64528 member: context.hasEntity(member.id)
64532 var gt = entity.members.length > 1000 ? '>' : '';
64533 selection$$1.call(uiDisclosure()
64534 .title(t('inspector.all_members') + ' (' + gt + memberships.length + ')')
64536 .on('toggled', toggled)
64541 function toggled(expanded) {
64543 selection$$1.node().parentNode.scrollTop += 200;
64548 function content(wrap) {
64549 var list = wrap.selectAll('.member-list')
64552 list = list.enter()
64554 .attr('class', 'member-list')
64558 var items = list.selectAll('li')
64559 .data(memberships, function(d) {
64560 return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
64561 (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
64568 var enter = items.enter()
64570 .attr('class', 'member-row form-field')
64571 .classed('member-incomplete', function(d) { return !d.member; });
64574 .each(function(d) {
64576 var label = select(this).append('label')
64577 .attr('class', 'form-label')
64580 .on('click', selectMember);
64582 label.append('span')
64583 .attr('class', 'member-entity-type')
64584 .text(function(d) {
64585 var matched = context.presets().match(d.member, context.graph());
64586 return (matched && matched.name()) || utilDisplayType(d.member.id);
64589 label.append('span')
64590 .attr('class', 'member-entity-name')
64591 .text(function(d) { return utilDisplayName(d.member); });
64594 select(this).append('label')
64595 .attr('class', 'form-label')
64596 .text(t('inspector.incomplete', { id: d.id }));
64602 .attr('class', 'member-role')
64603 .property('type', 'text')
64604 .attr('maxlength', 255)
64605 .attr('placeholder', t('inspector.role'))
64607 .property('value', function(d) { return d.role; })
64608 .on('change', changeRole);
64612 .attr('tabindex', -1)
64613 .attr('class', 'remove button-input-action member-delete minor')
64614 .on('click', deleteMember)
64615 .call(svgIcon('#operation-delete'));
64618 enter.each(bindTypeahead);
64622 function bindTypeahead(d) {
64623 var row = select(this),
64624 role = row.selectAll('input.member-role');
64626 function sort(value, data) {
64627 var sameletter = [],
64629 for (var i = 0; i < data.length; i++) {
64630 if (data[i].value.substring(0, value.length) === value) {
64631 sameletter.push(data[i]);
64633 other.push(data[i]);
64636 return sameletter.concat(other);
64639 role.call(d3combobox()
64640 .container(context.container())
64641 .fetcher(function(role, callback) {
64642 var rtype = entity.tags.type;
64645 rtype: rtype || '',
64646 geometry: context.geometry(d.member.id),
64648 }, function(err, data) {
64649 if (!err) callback(sort(role, data));
64655 function unbind() {
64656 var row = select(this);
64658 row.selectAll('input.member-role')
64659 .call(d3combobox.off);
64665 rawMemberEditor.entityID = function(_) {
64666 if (!arguments.length) return id;
64668 return rawMemberEditor;
64672 return rawMemberEditor;
64675 function uiRawMembershipEditor(context) {
64676 var taginfo = services.taginfo,
64680 function selectRelation(d) {
64681 event.preventDefault();
64682 context.enter(modeSelect(context, [d.relation.id]));
64686 function changeRole(d) {
64687 var role = select(this).property('value');
64689 actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
64690 t('operations.change_role.annotation')
64695 function addMembership(d, role) {
64700 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
64701 t('operations.add_member.annotation')
64705 var relation = osmRelation();
64707 actionAddEntity(relation),
64708 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
64709 t('operations.add.annotation.relation')
64712 context.enter(modeSelect(context, [relation.id]));
64717 function deleteMembership(d) {
64719 actionDeleteMember(d.relation.id, d.index),
64720 t('operations.delete_member.annotation')
64725 function relations(q) {
64726 var newRelation = {
64728 value: t('inspector.new_relation')
64731 graph = context.graph();
64733 context.intersects(context.extent()).forEach(function(entity) {
64734 if (entity.type !== 'relation' || entity.id === id)
64737 var matched = context.presets().match(entity, graph),
64738 presetName = (matched && matched.name()) || t('inspector.relation'),
64739 entityName = utilDisplayName(entity) || '';
64741 var value = presetName + ' ' + entityName;
64742 if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
64751 result.sort(function(a, b) {
64752 return osmRelation.creationOrder(a.relation, b.relation);
64755 // Dedupe identical names by appending relation id - see #2891
64756 var dupeGroups = lodash(result)
64758 .filter(function(v) { return v.length > 1; })
64761 dupeGroups.forEach(function(group) {
64762 group.forEach(function(obj) {
64763 obj.value += ' ' + obj.relation.id;
64767 result.unshift(newRelation);
64772 function rawMembershipEditor(selection$$1) {
64773 var entity = context.entity(id),
64774 parents = context.graph().parentRelations(entity),
64777 parents.slice(0, 1000).forEach(function(relation) {
64778 relation.members.forEach(function(member, index) {
64779 if (member.id === entity.id) {
64780 memberships.push({ relation: relation, member: member, index: index });
64785 var gt = parents.length > 1000 ? '>' : '';
64786 selection$$1.call(uiDisclosure()
64787 .title(t('inspector.all_relations') + ' (' + gt + memberships.length + ')')
64789 .on('toggled', toggled)
64794 function toggled(expanded) {
64796 selection$$1.node().parentNode.scrollTop += 200;
64801 function content(wrap) {
64802 var list = wrap.selectAll('.member-list')
64805 list = list.enter()
64807 .attr('class', 'member-list')
64811 var items = list.selectAll('li.member-row-normal')
64812 .data(memberships, function(d) {
64813 return osmEntity$$1.key(d.relation) + ',' + d.index;
64820 var enter = items.enter()
64822 .attr('class', 'member-row member-row-normal form-field');
64826 .attr('class', 'form-label')
64829 .on('click', selectRelation);
64833 .attr('class', 'member-entity-type')
64834 .text(function(d) {
64835 var matched = context.presets().match(d.relation, context.graph());
64836 return (matched && matched.name()) || t('inspector.relation');
64841 .attr('class', 'member-entity-name')
64842 .text(function(d) { return utilDisplayName(d.relation); });
64846 .attr('class', 'member-role')
64847 .property('type', 'text')
64848 .attr('maxlength', 255)
64849 .attr('placeholder', t('inspector.role'))
64851 .property('value', function(d) { return d.member.role; })
64852 .on('change', changeRole);
64856 .attr('tabindex', -1)
64857 .attr('class', 'remove button-input-action member-delete minor')
64858 .on('click', deleteMembership)
64859 .call(svgIcon('#operation-delete'));
64862 enter.each(bindTypeahead);
64866 var newrow = list.selectAll('.member-row-new')
64867 .data(showBlank ? [0] : []);
64872 enter = newrow.enter()
64874 .attr('class', 'member-row member-row-new form-field');
64878 .attr('type', 'text')
64879 .attr('class', 'member-entity-input')
64884 .attr('class', 'member-role')
64885 .property('type', 'text')
64886 .attr('maxlength', 255)
64887 .attr('placeholder', t('inspector.role'))
64889 .on('change', changeRole);
64893 .attr('tabindex', -1)
64894 .attr('class', 'remove button-input-action member-delete minor')
64895 .on('click', deleteMembership)
64896 .call(svgIcon('#operation-delete'));
64901 newrow.selectAll('.member-entity-input')
64903 .container(context.container())
64905 .fetcher(function(value, callback) { callback(relations(value)); })
64906 .on('accept', onAccept)
64910 var addrel = wrap.selectAll('.add-relation')
64913 addrel = addrel.enter()
64915 .attr('class', 'add-relation')
64919 .call(svgIcon('#icon-plus', 'light'))
64920 .on('click', function() {
64923 list.selectAll('.member-entity-input').node().focus();
64927 function onAccept(d) {
64928 var role = list.selectAll('.member-row-new .member-role').property('value');
64929 addMembership(d, role);
64933 function bindTypeahead(d) {
64934 var row = select(this),
64935 role = row.selectAll('input.member-role');
64937 function sort(value, data) {
64938 var sameletter = [],
64940 for (var i = 0; i < data.length; i++) {
64941 if (data[i].value.substring(0, value.length) === value) {
64942 sameletter.push(data[i]);
64944 other.push(data[i]);
64947 return sameletter.concat(other);
64950 role.call(d3combobox()
64951 .container(context.container())
64952 .fetcher(function(role, callback) {
64953 var rtype = d.relation.tags.type;
64956 rtype: rtype || '',
64957 geometry: context.geometry(id),
64959 }, function(err, data) {
64960 if (!err) callback(sort(role, data));
64966 function unbind() {
64967 var row = select(this);
64969 row.selectAll('input.member-role')
64970 .call(d3combobox.off);
64976 rawMembershipEditor.entityID = function(_) {
64977 if (!arguments.length) return id;
64979 return rawMembershipEditor;
64983 return rawMembershipEditor;
64986 function uiTagReference(tag) {
64987 var taginfo = services.taginfo,
64995 function findLocal(data) {
64996 var locale = utilDetect().locale.toLowerCase(),
64999 if (locale !== 'pt-br') { // see #3776, prefer 'pt' over 'pt-br'
65000 localized = lodash.find(data, function(d) {
65001 return d.lang.toLowerCase() === locale;
65003 if (localized) return localized;
65006 // try the non-regional version of a language, like
65007 // 'en' if the language is 'en-US'
65008 if (locale.indexOf('-') !== -1) {
65009 var first = locale.split('-')[0];
65010 localized = lodash.find(data, function(d) {
65011 return d.lang.toLowerCase() === first;
65013 if (localized) return localized;
65016 // finally fall back to english
65017 return lodash.find(data, function(d) {
65018 return d.lang.toLowerCase() === 'en';
65023 function load(param) {
65024 if (!taginfo) return;
65026 button.classed('tag-reference-loading', true);
65028 taginfo.docs(param, function show(err, data) {
65030 if (!err && data) {
65031 docs = findLocal(data);
65037 if (!docs || !docs.title) {
65038 if (param.hasOwnProperty('value')) {
65039 load(lodash.omit(param, 'value')); // retry with key only
65041 body.append('p').text(t('inspector.no_documentation_key'));
65048 if (docs.image && docs.image.thumb_url_prefix) {
65051 .attr('class', 'wiki-image')
65052 .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
65053 .on('load', function() { done(); })
65054 .on('error', function() { select(this).remove(); done(); });
65061 .text(docs.description || t('inspector.documentation_redirect'));
65065 .attr('target', '_blank')
65066 .attr('tabindex', -1)
65067 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
65068 .call(svgIcon('#icon-out-link', 'inline'))
65070 .text(t('inspector.reference'));
65078 button.classed('tag-reference-loading', false);
65082 .style('max-height', '200px')
65083 .style('opacity', '1');
65089 function hide(selection$$1) {
65090 selection$$1 = selection$$1 || body.transition().duration(200);
65093 .style('max-height', '0px')
65094 .style('opacity', '0');
65100 tagReference.button = function(selection$$1) {
65101 button = selection$$1.selectAll('.tag-reference-button')
65104 button = button.enter()
65106 .attr('class', 'tag-reference-button')
65107 .attr('tabindex', -1)
65108 .call(svgIcon('#icon-inspect'))
65112 .on('click', function () {
65113 event.stopPropagation();
65114 event.preventDefault();
65117 } else if (loaded) {
65126 tagReference.body = function(selection$$1) {
65127 body = selection$$1.selectAll('.tag-reference-body')
65130 body = body.enter()
65132 .attr('class', 'tag-reference-body cf')
65133 .style('max-height', '0')
65134 .style('opacity', '0')
65137 if (showing === false) {
65143 tagReference.showing = function(_) {
65144 if (!arguments.length) return showing;
65146 return tagReference;
65150 return tagReference;
65153 function uiRawTagEditor(context) {
65154 var taginfo = services.taginfo,
65155 dispatch$$1 = dispatch('change'),
65156 expanded = context.storage('raw_tag_editor.expanded') === 'true',
65158 updatePreference = true,
65167 function rawTagEditor(selection$$1) {
65168 var count = Object.keys(tags).filter(function(d) { return d; }).length;
65170 selection$$1.call(uiDisclosure()
65171 .title(t('inspector.all_tags') + ' (' + count + ')')
65172 .expanded(expanded)
65173 .on('toggled', toggled)
65177 function toggled(expanded) {
65178 if (updatePreference) {
65179 context.storage('raw_tag_editor.expanded', expanded);
65182 selection$$1.node().parentNode.scrollTop += 200;
65188 function content(wrap) {
65189 var entries$$1 = entries(tags);
65191 if (!entries$$1.length || showBlank) {
65193 entries$$1.push({key: '', value: ''});
65197 var list = wrap.selectAll('.tag-list')
65200 list = list.enter()
65202 .attr('class', 'tag-list')
65205 var newTag = wrap.selectAll('.add-tag')
65210 .attr('class', 'add-tag')
65211 .on('click', addTag)
65212 .call(svgIcon('#icon-plus', 'light'));
65215 var items = list.selectAll('.tag-row')
65216 .data(entries$$1, function(d) { return d.key; });
65224 var enter = items.enter()
65226 .attr('class', 'tag-row cf')
65227 .classed('readonly', isReadOnly);
65231 .attr('class', 'key-wrap')
65233 .property('type', 'text')
65234 .attr('class', 'key')
65235 .attr('maxlength', 255)
65237 .on('blur', keyChange)
65238 .on('change', keyChange);
65242 .attr('class', 'input-wrap-position')
65244 .property('type', 'text')
65245 .attr('class', 'value')
65246 .attr('maxlength', 255)
65248 .on('blur', valueChange)
65249 .on('change', valueChange)
65250 .on('keydown.push-more', pushMore);
65254 .attr('tabindex', -1)
65255 .attr('class', 'remove minor')
65256 .call(svgIcon('#operation-delete'));
65263 .sort(function(a, b) {
65264 return (a.key === newRow && b.key !== newRow) ? 1
65265 : (a.key !== newRow && b.key === newRow) ? -1
65266 : ascending(a.key, b.key);
65270 .each(function(tag) {
65271 var row = select(this),
65272 key = row.select('input.key'), // propagate bound data to child
65273 value = row.select('input.value'); // propagate bound data to child
65275 if (id && taginfo) {
65276 bindTypeahead(key, value);
65279 var isRelation = (id && context.entity(id).type === 'relation'),
65282 if (isRelation && tag.key === 'type') {
65283 reference = uiTagReference({ rtype: tag.value }, context);
65285 reference = uiTagReference({ key: tag.key, value: tag.value }, context);
65288 if (state === 'hover') {
65289 reference.showing(false);
65293 .call(reference.button)
65294 .call(reference.body);
65297 items.selectAll('input.key')
65298 .attr('title', function(d) { return d.key; })
65299 .call(utilGetSetValue, function(d) { return d.key; })
65300 .property('disabled', isReadOnly);
65302 items.selectAll('input.value')
65303 .attr('title', function(d) { return d.value; })
65304 .call(utilGetSetValue, function(d) { return d.value; })
65305 .property('disabled', isReadOnly);
65307 items.selectAll('button.remove')
65308 .on('click', removeTag);
65312 function isReadOnly(d) {
65313 return readOnlyTags.indexOf(d.key) !== -1;
65317 function pushMore() {
65318 if (event.keyCode === 9 && !event.shiftKey &&
65319 list.selectAll('li:last-child input.value').node() === this) {
65325 function bindTypeahead(key, value) {
65326 if (isReadOnly({ key: key })) return;
65327 var geometry = context.geometry(id);
65329 key.call(d3combobox()
65330 .container(context.container())
65331 .fetcher(function(value, callback) {
65334 geometry: geometry,
65336 }, function(err, data) {
65337 if (!err) callback(sort(value, data));
65341 value.call(d3combobox()
65342 .container(context.container())
65343 .fetcher(function(value, callback) {
65346 key: utilGetSetValue(key),
65347 geometry: geometry,
65349 }, function(err, data) {
65350 if (!err) callback(sort(value, data));
65355 function sort(value, data) {
65356 var sameletter = [],
65358 for (var i = 0; i < data.length; i++) {
65359 if (data[i].value.substring(0, value.length) === value) {
65360 sameletter.push(data[i]);
65362 other.push(data[i]);
65365 return sameletter.concat(other);
65370 function unbind() {
65371 var row = select(this);
65373 row.selectAll('input.key')
65374 .call(d3combobox.off);
65376 row.selectAll('input.value')
65377 .call(d3combobox.off);
65381 function keyChange(d) {
65383 kNew = this.value.trim(),
65387 if (isReadOnly({ key: kNew })) {
65392 if (kNew && kNew !== kOld) {
65393 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
65395 suffix = +(match[2] || 1);
65396 while (tags[kNew]) { // rename key if already in use
65397 kNew = base + '_' + suffix++;
65400 tag[kOld] = undefined;
65401 tag[kNew] = d.value;
65403 d.key = kNew; // Maintain DOM identity through the subsequent update.
65405 if (newRow === kOld) { // see if this row is still a new row
65406 newRow = ((d.value === '' || kNew === '') ? kNew : undefined);
65410 dispatch$$1.call('change', this, tag);
65414 function valueChange(d) {
65415 if (isReadOnly(d)) return;
65417 tag[d.key] = this.value;
65419 if (newRow === d.key && d.key !== '' && d.value !== '') { // not a new row anymore
65420 newRow = undefined;
65423 dispatch$$1.call('change', this, tag);
65427 function removeTag(d) {
65428 if (isReadOnly(d)) return;
65430 tag[d.key] = undefined;
65431 dispatch$$1.call('change', this, tag);
65432 select(this.parentNode).remove();
65436 function addTag() {
65437 // Wrapped in a setTimeout in case it's being called from a blur
65438 // handler. Without the setTimeout, the call to `content` would
65439 // wipe out the pending value change.
65440 setTimeout(function() {
65443 list.selectAll('li:last-child input.key').node().focus();
65449 rawTagEditor.state = function(_) {
65450 if (!arguments.length) return state;
65452 return rawTagEditor;
65456 rawTagEditor.preset = function(_) {
65457 if (!arguments.length) return preset;
65459 if (preset.isFallback()) {
65461 updatePreference = false;
65463 expanded = context.storage('raw_tag_editor.expanded') === 'true';
65464 updatePreference = true;
65466 return rawTagEditor;
65470 rawTagEditor.tags = function(_) {
65471 if (!arguments.length) return tags;
65473 return rawTagEditor;
65477 rawTagEditor.entityID = function(_) {
65478 if (!arguments.length) return id;
65480 return rawTagEditor;
65484 rawTagEditor.expanded = function(_) {
65485 if (!arguments.length) return expanded;
65487 updatePreference = false;
65488 return rawTagEditor;
65492 rawTagEditor.readOnlyTags = function(_) {
65493 if (!arguments.length) return readOnlyTags;
65495 return rawTagEditor;
65499 return utilRebind(rawTagEditor, dispatch$$1, 'on');
65502 function uiFieldCheck(field, context) {
65503 var dispatch$$1 = dispatch('change'),
65504 options = field.strings && field.strings.options,
65507 input = select(null),
65508 text$$1 = select(null),
65509 label = select(null),
65510 reverser = select(null),
65517 for (var k in options) {
65518 values$$1.push(k === 'undefined' ? undefined : k);
65519 texts.push(field.t('options.' + k, { 'default': options[k] }));
65522 values$$1 = [undefined, 'yes'];
65523 texts = [t('inspector.unknown'), t('inspector.check.yes')];
65524 if (field.type !== 'defaultCheck') {
65525 values$$1.push('no');
65526 texts.push(t('inspector.check.no'));
65531 // Checks tags to see whether an undefined value is "Assumed to be Yes"
65532 function checkImpliedYes() {
65533 impliedYes = (field.id === 'oneway_yes');
65535 // hack: pretend `oneway` field is a `oneway_yes` field
65536 // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
65537 if (field.id === 'oneway') {
65538 var entity = context.entity(entityId);
65539 for (var key in entity.tags) {
65540 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
65542 texts[0] = t('presets.fields.oneway_yes.options.undefined');
65550 function reverserHidden() {
65551 if (!select('div.inspector-hover').empty()) return true;
65552 return !(value === 'yes' || (impliedYes && !value));
65556 function reverserSetText(selection$$1) {
65557 var entity = context.hasEntity(entityId);
65558 if (reverserHidden() || !entity) return selection$$1;
65560 var first = entity.first(),
65561 last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last(),
65562 pseudoDirection = first < last,
65563 icon = pseudoDirection ? '#icon-forward' : '#icon-backward';
65565 selection$$1.selectAll('.reverser-span')
65566 .text(t('inspector.check.reverser'))
65567 .call(svgIcon(icon, 'inline'));
65569 return selection$$1;
65573 var check = function(selection$$1) {
65575 selection$$1.classed('checkselect', 'true');
65577 label = selection$$1.selectAll('.preset-input-wrap')
65580 var enter = label.enter()
65582 .attr('class', 'preset-input-wrap');
65586 .property('indeterminate', field.type !== 'defaultCheck')
65587 .attr('type', 'checkbox')
65588 .attr('id', 'preset-input-' + field.id);
65593 .attr('class', 'value');
65595 if (field.type === 'onewayCheck') {
65598 .attr('id', 'preset-input-' + field.id + '-reverser')
65599 .attr('class', 'reverser button' + (reverserHidden() ? ' hide' : ''))
65602 .attr('class', 'reverser-span');
65605 label = label.merge(enter);
65606 input = label.selectAll('input');
65607 text$$1 = label.selectAll('span.value');
65610 .on('click', function() {
65612 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
65613 dispatch$$1.call('change', this, t$$1);
65614 event.stopPropagation();
65617 if (field.type === 'onewayCheck') {
65618 reverser = label.selectAll('.reverser');
65621 .call(reverserSetText)
65622 .on('click', function() {
65623 event.preventDefault();
65624 event.stopPropagation();
65626 actionReverse(entityId),
65627 t('operations.reverse.annotation')
65630 .call(reverserSetText);
65636 check.entity = function(_) {
65637 if (!arguments.length) return context.hasEntity(entityId);
65643 check.tags = function(tags) {
65645 value = tags[field.key] && tags[field.key].toLowerCase();
65647 if (field.type === 'onewayCheck' && (value === '1' || value === '-1')) {
65652 .property('indeterminate', field.type !== 'defaultCheck' && !value)
65653 .property('checked', value === 'yes');
65656 .text(texts[values$$1.indexOf(value)]);
65659 .classed('set', !!value);
65661 if (field.type === 'onewayCheck') {
65663 .classed('hide', reverserHidden())
65664 .call(reverserSetText);
65669 check.focus = function() {
65670 input.node().focus();
65673 return utilRebind(check, dispatch$$1, 'on');
65676 function uiFieldCombo(field, context) {
65677 var dispatch$$1 = dispatch('change'),
65678 nominatim = services.geocoder,
65679 taginfo = services.taginfo,
65680 isMulti = (field.type === 'multiCombo'),
65681 isNetwork = (field.type === 'networkCombo'),
65682 isSemi = (field.type === 'semiCombo'),
65683 optstrings = field.strings && field.strings.options,
65684 optarray = field.options,
65685 snake_case = (field.snake_case || (field.snake_case === undefined)),
65686 combobox = d3combobox()
65687 .container(context.container())
65688 .minItems(isMulti || isSemi ? 1 : 2),
65696 // ensure multiCombo field.key ends with a ':'
65697 if (isMulti && field.key.match(/:$/) === null) {
65702 function snake(s) {
65703 return s.replace(/\s+/g, '_');
65706 function unsnake(s) {
65707 return s.replace(/_+/g, ' ');
65710 function clean(s) {
65711 return s.split(';')
65712 .map(function(s) { return s.trim(); })
65717 // returns the tag value for a display value
65718 // (for multiCombo, dval should be the key suffix, not the entire key)
65719 function tagValue(dval) {
65720 dval = clean(dval || '');
65723 var match = lodash.find(comboData, function(o) {
65724 return o.key && clean(o.value) === dval;
65731 if (field.type === 'typeCombo' && !dval) {
65735 return (snake_case ? snake(dval) : dval) || undefined;
65739 // returns the display value for a tag value
65740 // (for multiCombo, tval should be the key suffix, not the entire key)
65741 function displayValue(tval) {
65745 var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
65747 return match.value;
65751 if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
65755 return snake_case ? unsnake(tval) : tval;
65759 function objectDifference(a, b) {
65760 return lodash.reject(a, function(d1) {
65761 return lodash.some(b, function(d2) { return d1.value === d2.value; });
65766 function initCombo(selection$$1, attachTo) {
65768 selection$$1.attr('readonly', 'readonly');
65769 selection$$1.call(combobox, attachTo);
65770 setStaticValues(setPlaceholder);
65772 } else if (optarray) {
65773 selection$$1.call(combobox, attachTo);
65774 setStaticValues(setPlaceholder);
65776 } else if (taginfo) {
65777 selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
65778 setTaginfoValues('', setPlaceholder);
65783 function setStaticValues(callback) {
65784 if (!(optstrings || optarray)) return;
65787 comboData = Object.keys(optstrings).map(function(k) {
65788 var v = field.t('options.' + k, { 'default': optstrings[k] });
65796 } else if (optarray) {
65797 comboData = optarray.map(function(k) {
65798 var v = snake_case ? unsnake(k) : k;
65807 combobox.data(objectDifference(comboData, multiData));
65808 if (callback) callback(comboData);
65812 function setTaginfoValues(q, callback) {
65813 var fn = isMulti ? 'multikeys' : 'values';
65814 var query = (isMulti ? field.key : '') + q;
65815 var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
65816 if (hasCountryPrefix) {
65817 query = country + ':';
65821 debounce: (q !== ''),
65823 geometry: context.geometry(entity.id),
65825 }, function(err, data) {
65827 if (hasCountryPrefix) {
65828 data = lodash.filter(data, function(d) {
65829 return d.value.toLowerCase().indexOf(country + ':') === 0;
65833 comboData = lodash.map(data, function(d) {
65835 if (isMulti) k = k.replace(field.key, '');
65836 var v = snake_case ? unsnake(k) : k;
65840 title: isMulti ? v : d.title
65844 comboData = objectDifference(comboData, multiData);
65845 if (callback) callback(comboData);
65850 function setPlaceholder(d) {
65853 if (isMulti || isSemi) {
65854 ph = field.placeholder() || t('inspector.add');
65856 var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
65857 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
65858 ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
65861 if (ph.match(/(…|\.\.\.)$/) === null) {
65865 container.selectAll('input')
65866 .attr('placeholder', ph);
65870 function change() {
65871 var val = tagValue(utilGetSetValue(input)),
65874 if (isMulti || isSemi) {
65876 container.classed('active', false);
65877 utilGetSetValue(input, '');
65879 field.keys.push(field.key + val);
65880 t$$1[field.key + val] = 'yes';
65881 } else if (isSemi) {
65882 var arr = multiData.map(function(d) { return d.key; });
65884 t$$1[field.key] = lodash.compact(lodash.uniq(arr)).join(';');
65886 window.setTimeout(function() { input.node().focus(); }, 10);
65889 t$$1[field.key] = val;
65892 dispatch$$1.call('change', this, t$$1);
65896 function removeMultikey(d) {
65897 event.stopPropagation();
65900 t$$1[d.key] = undefined;
65901 } else if (isSemi) {
65902 lodash.remove(multiData, function(md) { return md.key === d.key; });
65903 var arr = multiData.map(function(md) { return md.key; });
65904 arr = lodash.compact(lodash.uniq(arr));
65905 t$$1[field.key] = arr.length ? arr.join(';') : undefined;
65907 dispatch$$1.call('change', this, t$$1);
65911 function combo(selection$$1) {
65912 if (isMulti || isSemi) {
65913 container = selection$$1.selectAll('ul').data([0]);
65915 container = container.enter()
65917 .attr('class', 'form-field-multicombo')
65918 .on('click', function() {
65919 window.setTimeout(function() { input.node().focus(); }, 10);
65924 container = selection$$1;
65927 input = container.selectAll('input')
65930 input = input.enter()
65932 .attr('type', 'text')
65933 .attr('id', 'preset-input-' + field.id)
65935 .call(initCombo, selection$$1)
65938 if (isNetwork && nominatim && entity) {
65939 var center = entity.extent(context.graph()).center();
65940 nominatim.countryCode(center, function (err, code) {
65946 .on('change', change)
65947 .on('blur', change);
65949 if (isMulti || isSemi) {
65951 .on('accept', function() {
65952 input.node().blur();
65953 input.node().focus();
65957 .on('focus', function() { container.classed('active', true); });
65962 combo.tags = function(tags) {
65963 if (isMulti || isSemi) {
65967 // Build multiData array containing keys already set..
65968 Object.keys(tags).forEach(function(key) {
65969 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
65971 var suffix = key.substring(field.key.length);
65974 value: displayValue(suffix)
65978 // Set keys for form-field modified (needed for undo and reset buttons)..
65979 field.keys = lodash.map(multiData, 'key');
65981 } else if (isSemi) {
65982 var arr = lodash.compact(lodash.uniq((tags[field.key] || '').split(';')));
65983 multiData = arr.map(function(key) {
65986 value: displayValue(key)
65991 // Exclude existing multikeys from combo options..
65992 var available = objectDifference(comboData, multiData);
65993 combobox.data(available);
65995 // Hide 'Add' button if this field uses fixed set of
65996 // translateable optstrings and they're all currently used..
65997 container.selectAll('.combobox-input, .combobox-caret')
65998 .classed('hide', optstrings && !available.length);
66002 var chips = container.selectAll('.chips')
66008 var enter = chips.enter()
66009 .insert('li', 'input')
66010 .attr('class', 'chips');
66012 enter.append('span');
66015 chips = chips.merge(enter);
66017 chips.select('span')
66018 .text(function(d) { return d.value; });
66021 .on('click', removeMultikey)
66022 .attr('class', 'remove')
66026 utilGetSetValue(input, displayValue(tags[field.key]));
66031 combo.focus = function() {
66032 input.node().focus();
66036 combo.entity = function(_) {
66037 if (!arguments.length) return entity;
66043 return utilRebind(combo, dispatch$$1, 'on');
66046 function uiFieldText(field, context) {
66047 var dispatch$$1 = dispatch('change'),
66048 nominatim = services.geocoder,
66053 function i(selection$$1) {
66054 var fieldId = 'preset-input-' + field.id;
66056 input = selection$$1.selectAll('input')
66059 input = input.enter()
66061 .attr('type', field.type)
66062 .attr('id', fieldId)
66063 .attr('placeholder', field.placeholder() || t('inspector.unknown'))
66068 .on('input', change(true))
66069 .on('blur', change())
66070 .on('change', change());
66072 if (field.type === 'tel' && nominatim && entity) {
66073 var center = entity.extent(context.graph()).center();
66074 nominatim.countryCode(center, function (err, countryCode) {
66075 if (err || !dataPhoneFormats[countryCode]) return;
66076 selection$$1.selectAll('#' + fieldId)
66077 .attr('placeholder', dataPhoneFormats[countryCode]);
66080 } else if (field.type === 'number') {
66081 input.attr('type', 'text');
66083 var spinControl = selection$$1.selectAll('.spin-control')
66086 var enter = spinControl.enter()
66088 .attr('class', 'spin-control');
66093 .attr('class', 'decrement')
66094 .attr('tabindex', -1);
66099 .attr('class', 'increment')
66100 .attr('tabindex', -1);
66102 spinControl = spinControl
66105 spinControl.selectAll('button')
66106 .on('click', function(d) {
66107 event.preventDefault();
66108 var num = parseInt(input.node().value || 0, 10);
66109 if (!isNaN(num)) input.node().value = num + d;
66116 function change(onInput) {
66117 return function() {
66119 t$$1[field.key] = utilGetSetValue(input) || undefined;
66120 dispatch$$1.call('change', this, t$$1, onInput);
66125 i.entity = function(_) {
66126 if (!arguments.length) return entity;
66132 i.tags = function(tags) {
66133 utilGetSetValue(input, tags[field.key] || '');
66137 i.focus = function() {
66138 var node = input.node();
66139 if (node) node.focus();
66142 return utilRebind(i, dispatch$$1, 'on');
66145 function uiFieldAccess(field, context) {
66146 var dispatch$$1 = dispatch('change'),
66149 function access(selection$$1) {
66150 var wrap = selection$$1.selectAll('.preset-input-wrap')
66153 wrap = wrap.enter()
66155 .attr('class', 'cf preset-input-wrap')
66159 var list = wrap.selectAll('ul')
66162 list = list.enter()
66167 items = list.selectAll('li')
66171 var enter = items.enter()
66173 .attr('class', function(d) { return 'cf preset-access-' + d; });
66177 .attr('class', 'col6 label preset-label-access')
66178 .attr('for', function(d) { return 'preset-input-access-' + d; })
66179 .text(function(d) { return field.t('types.' + d); });
66183 .attr('class', 'col6 preset-input-access-wrap')
66185 .attr('type', 'text')
66186 .attr('class', 'preset-input-access')
66187 .attr('id', function(d) { return 'preset-input-access-' + d; })
66189 .each(function(d) {
66192 .container(context.container())
66193 .data(access.options(d))
66199 items = items.merge(enter);
66201 wrap.selectAll('.preset-input-access')
66202 .on('change', change)
66203 .on('blur', change);
66207 function change(d) {
66209 tag[d] = utilGetSetValue(select(this)) || undefined;
66210 dispatch$$1.call('change', this, tag);
66214 access.options = function(type) {
66215 var options = ['no', 'permissive', 'private', 'destination'];
66217 if (type !== 'access') {
66218 options.unshift('yes');
66219 options.push('designated');
66221 if (type === 'bicycle') {
66222 options.push('dismount');
66226 return options.map(function(option) {
66228 title: field.t('options.' + option + '.description'),
66235 var placeholders = {
66237 foot: 'designated',
66238 motor_vehicle: 'no'
66242 motor_vehicle: 'no',
66248 motor_vehicle: 'no'
66251 motor_vehicle: 'no',
66252 bicycle: 'designated'
66255 motor_vehicle: 'no',
66256 horse: 'designated'
66260 motor_vehicle: 'no',
66266 motor_vehicle: 'yes',
66271 motor_vehicle: 'yes'
66275 motor_vehicle: 'yes',
66281 motor_vehicle: 'yes',
66287 motor_vehicle: 'yes',
66293 motor_vehicle: 'yes',
66299 motor_vehicle: 'yes',
66305 motor_vehicle: 'yes',
66311 motor_vehicle: 'yes',
66316 motor_vehicle: 'yes'
66320 motor_vehicle: 'yes',
66326 motor_vehicle: 'yes',
66332 motor_vehicle: 'yes',
66339 access.tags = function(tags) {
66340 utilGetSetValue(items.selectAll('.preset-input-access'),
66341 function(d) { return tags[d] || ''; })
66342 .attr('placeholder', function() {
66343 return tags.access ? tags.access : field.placeholder();
66346 items.selectAll('#preset-input-access-access')
66347 .attr('placeholder', 'yes');
66349 lodash.forEach(placeholders[tags.highway], function(v, k) {
66350 items.selectAll('#preset-input-access-' + k)
66351 .attr('placeholder', function() { return (tags.access || v); });
66356 access.focus = function() {
66357 items.selectAll('.preset-input-access')
66362 return utilRebind(access, dispatch$$1, 'on');
66365 function uiFieldAddress(field, context) {
66366 var dispatch$$1 = dispatch('init', 'change'),
66367 nominatim = services.geocoder,
66368 wrap = select(null),
66369 isInitialized = false,
66372 function getNearStreets() {
66373 var extent$$1 = entity.extent(context.graph()),
66374 l = extent$$1.center(),
66375 box = geoExtent$$1(l).padByMeters(200);
66377 var streets = context.intersects(box)
66378 .filter(isAddressable)
66380 var loc = context.projection([
66381 (extent$$1[0][0] + extent$$1[1][0]) / 2,
66382 (extent$$1[0][1] + extent$$1[1][1]) / 2]),
66383 choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
66385 title: d.tags.name,
66386 value: d.tags.name,
66387 dist: choice.distance
66390 .sort(function(a, b) {
66391 return a.dist - b.dist;
66394 return lodash.uniqBy(streets, 'value');
66396 function isAddressable(d) {
66397 return d.tags.highway && d.tags.name && d.type === 'way';
66402 function getNearCities() {
66403 var extent$$1 = entity.extent(context.graph()),
66404 l = extent$$1.center(),
66405 box = geoExtent$$1(l).padByMeters(200);
66407 var cities = context.intersects(box)
66408 .filter(isAddressable)
66411 title: d.tags['addr:city'] || d.tags.name,
66412 value: d.tags['addr:city'] || d.tags.name,
66413 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
66416 .sort(function(a, b) {
66417 return a.dist - b.dist;
66420 return lodash.uniqBy(cities, 'value');
66423 function isAddressable(d) {
66425 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
66428 if (d.tags.place && d.tags.name && (
66429 d.tags.place === 'city' ||
66430 d.tags.place === 'town' ||
66431 d.tags.place === 'village'))
66434 if (d.tags['addr:city']) return true;
66440 function getNearValues(key) {
66441 var extent$$1 = entity.extent(context.graph()),
66442 l = extent$$1.center(),
66443 box = geoExtent$$1(l).padByMeters(200);
66445 var results = context.intersects(box)
66446 .filter(function hasTag(d) {
66447 return d.tags[key];
66451 title: d.tags[key],
66452 value: d.tags[key],
66453 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
66456 .sort(function(a, b) {
66457 return a.dist - b.dist;
66460 return lodash.uniqBy(results, 'value');
66464 function initCallback(err, countryCode) {
66467 var addressFormat = lodash.find(dataAddressFormats, function (a) {
66468 return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode.toLowerCase());
66469 }) || lodash.first(dataAddressFormats);
66471 var widths = addressFormat.widths || {
66472 housenumber: 1/3, street: 2/3,
66473 city: 2/3, state: 1/4, postcode: 1/3
66477 // Normalize widths.
66478 var total = lodash.reduce(r, function(sum$$1, field) {
66479 return sum$$1 + (widths[field] || 0.5);
66482 return r.map(function (field) {
66485 width: (widths[field] || 0.5) / total
66490 wrap.selectAll('div.addr-row')
66491 .data(addressFormat.format)
66494 .attr('class', 'addr-row')
66495 .selectAll('input')
66499 .property('type', 'text')
66500 .attr('placeholder', function (d) {
66501 var localkey = d.id + '!' + countryCode.toLowerCase(),
66502 tkey = field.strings.placeholders[localkey] ? localkey : d.id;
66503 return field.t('placeholders.' + tkey);
66505 .attr('class', function (d) { return 'addr-' + d.id; })
66507 .style('width', function (d) { return d.width * 100 + '%'; });
66511 // setup dropdowns for common address tags
66512 var dropdowns = addressFormat.dropdowns || [
66513 'city', 'county', 'country', 'district', 'hamlet',
66514 'neighbourhood', 'place', 'postcode', 'province',
66515 'quarter', 'state', 'street', 'subdistrict', 'suburb'
66518 // If fields exist for any of these tags, create dropdowns to pick nearby values..
66519 dropdowns.forEach(function(tag) {
66520 var nearValues = (tag === 'street') ? getNearStreets
66521 : (tag === 'city') ? getNearCities
66524 wrap.selectAll('input.addr-' + tag)
66526 .container(context.container())
66528 .fetcher(function(value, callback) {
66529 callback(nearValues('addr:' + tag));
66534 wrap.selectAll('input')
66535 .on('blur', change())
66536 .on('change', change());
66538 wrap.selectAll('input:not(.combobox-input)')
66539 .on('input', change(true));
66541 dispatch$$1.call('init');
66542 isInitialized = true;
66546 function address(selection$$1) {
66547 isInitialized = false;
66549 wrap = selection$$1.selectAll('.preset-input-wrap')
66552 wrap = wrap.enter()
66554 .attr('class', 'preset-input-wrap')
66557 if (nominatim && entity) {
66558 var center = entity.extent(context.graph()).center();
66559 nominatim.countryCode(center, initCallback);
66564 function change(onInput) {
66565 return function() {
66568 wrap.selectAll('input')
66569 .each(function (field) {
66570 tags['addr:' + field.id] = this.value || undefined;
66573 dispatch$$1.call('change', this, tags, onInput);
66578 function updateTags(tags) {
66579 utilGetSetValue(wrap.selectAll('input'), function (field) {
66580 return tags['addr:' + field.id] || '';
66585 address.entity = function(_) {
66586 if (!arguments.length) return entity;
66592 address.tags = function(tags) {
66593 if (isInitialized) {
66596 dispatch$$1.on('init', function () {
66597 dispatch$$1.on('init', null);
66604 address.focus = function() {
66605 var node = wrap.selectAll('input').node();
66606 if (node) node.focus();
66610 return utilRebind(address, dispatch$$1, 'on');
66613 function uiFieldCycleway(field, context) {
66614 var dispatch$$1 = dispatch('change'),
66615 items = select(null);
66618 function cycleway(selection$$1) {
66620 function stripcolon(s) {
66621 return s.replace(':', '');
66625 var wrap = selection$$1.selectAll('.preset-input-wrap')
66628 wrap = wrap.enter()
66630 .attr('class', 'cf preset-input-wrap')
66634 var div = wrap.selectAll('ul')
66642 items = div.selectAll('li')
66645 var enter = items.enter()
66647 .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
66651 .attr('class', 'col6 label preset-label-cycleway')
66652 .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
66653 .text(function(d) { return field.t('types.' + d); });
66657 .attr('class', 'col6 preset-input-cycleway-wrap')
66659 .attr('type', 'text')
66660 .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
66662 .each(function(d) {
66665 .container(context.container())
66666 .data(cycleway.options(d))
66672 wrap.selectAll('.preset-input-cycleway')
66673 .on('change', change)
66674 .on('blur', change);
66678 function change() {
66679 var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
66680 right = utilGetSetValue(select('.preset-input-cyclewayright')),
66683 if (left === 'none' || left === '') { left = undefined; }
66684 if (right === 'none' || right === '') { right = undefined; }
66686 // Always set both left and right as changing one can affect the other
66688 cycleway: undefined,
66689 'cycleway:left': left,
66690 'cycleway:right': right
66693 // If the left and right tags match, use the cycleway tag to tag both
66694 // sides the same way
66695 if (left === right) {
66698 'cycleway:left': undefined,
66699 'cycleway:right': undefined
66703 dispatch$$1.call('change', this, tag);
66707 cycleway.options = function() {
66708 return keys(field.strings.options).map(function(option) {
66710 title: field.t('options.' + option + '.description'),
66717 cycleway.tags = function(tags) {
66718 utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
66719 // If cycleway is set, always return that
66720 if (tags.cycleway) {
66721 return tags.cycleway;
66723 return tags[d] || '';
66725 .attr('placeholder', field.placeholder());
66729 cycleway.focus = function() {
66730 items.selectAll('.preset-input-cycleway')
66735 return utilRebind(cycleway, dispatch$$1, 'on');
66738 function uiFieldLanes(field, context) {
66739 var dispatch$$1 = dispatch('change'),
66745 function lanes(selection$$1) {
66746 lanesData = context.entity(wayID).lanes();
66748 if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
66749 selection$$1.call(lanes.off);
66753 var wrap = selection$$1.selectAll('.preset-input-wrap')
66756 wrap = wrap.enter()
66758 .attr('class', 'preset-input-wrap')
66761 var surface = wrap.selectAll('.surface')
66764 var d = utilGetDimensions(wrap);
66765 var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
66767 surface = surface.enter()
66769 .attr('width', d[0])
66770 .attr('height', 300)
66771 .attr('class', 'surface')
66775 var lanesSelection = surface.selectAll('.lanes')
66778 lanesSelection = lanesSelection.enter()
66780 .attr('class', 'lanes')
66781 .merge(lanesSelection);
66784 .attr('transform', function () {
66785 return 'translate(' + (freeSpace / 2) + ', 0)';
66789 var lane = lanesSelection.selectAll('.lane')
66790 .data(lanesData.lanes);
66795 var enter = lane.enter()
66797 .attr('class', 'lane');
66803 .attr('width', LANE_WIDTH)
66804 .attr('height', LANE_HEIGHT);
66808 .attr('class', 'forward')
66816 .attr('class', 'bothways')
66824 .attr('class', 'backward')
66835 .attr('transform', function(d) {
66836 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
66839 lane.select('.forward')
66840 .style('visibility', function(d) {
66841 return d.direction === 'forward' ? 'visible' : 'hidden';
66844 lane.select('.bothways')
66845 .style('visibility', function(d) {
66846 return d.direction === 'bothways' ? 'visible' : 'hidden';
66849 lane.select('.backward')
66850 .style('visibility', function(d) {
66851 return d.direction === 'backward' ? 'visible' : 'hidden';
66856 lanes.entity = function(_) {
66857 if (!wayID || wayID !== _.id) {
66862 lanes.tags = function() {};
66863 lanes.focus = function() {};
66864 lanes.off = function() {};
66866 return utilRebind(lanes, dispatch$$1, 'on');
66869 function uiFieldLocalized(field, context) {
66870 var dispatch$$1 = dispatch('change', 'input'),
66871 wikipedia = services.wikipedia,
66872 input = select(null),
66873 localizedInputs = select(null),
66878 function localized(selection$$1) {
66879 input = selection$$1.selectAll('.localized-main')
66882 input = input.enter()
66884 .attr('type', 'text')
66885 .attr('id', 'preset-input-' + field.id)
66886 .attr('class', 'localized-main')
66887 .attr('placeholder', field.placeholder())
66891 if (field.id === 'name') {
66892 var preset = context.presets().match(entity, context.graph());
66895 .container(context.container())
66896 .fetcher(utilSuggestNames(preset, dataSuggestions))
66901 .on('input', change(true))
66902 .on('blur', change())
66903 .on('change', change());
66906 var translateButton = selection$$1.selectAll('.localized-add')
66909 translateButton = translateButton.enter()
66911 .attr('class', 'button-input-action localized-add minor')
66912 .attr('tabindex', -1)
66913 .call(svgIcon('#icon-plus'))
66915 .title(t('translate.translate'))
66916 .placement('left'))
66917 .merge(translateButton);
66920 .on('click', addNew);
66923 localizedInputs = selection$$1.selectAll('.localized-wrap')
66926 localizedInputs = localizedInputs.enter().append('div')
66927 .attr('class', 'localized-wrap')
66928 .merge(localizedInputs);
66932 function addNew() {
66933 event.preventDefault();
66934 var data$$1 = localizedInputs.selectAll('div.entry').data();
66935 var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
66936 var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
66937 var isLangEn = defaultLang.indexOf('en') > -1;
66938 if (isLangEn || langExists) {
66941 data$$1.push({ lang: defaultLang, value: '' });
66942 localizedInputs.call(render, data$$1);
66946 function change(onInput) {
66947 return function() {
66949 t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
66950 dispatch$$1.call('change', this, t$$1, onInput);
66955 function key(lang) {
66956 return field.key + ':' + lang;
66960 function changeLang(d) {
66961 var lang = utilGetSetValue(select(this)),
66963 language = lodash.find(dataWikipedia, function(d) {
66964 return d[0].toLowerCase() === lang.toLowerCase() ||
66965 d[1].toLowerCase() === lang.toLowerCase();
66968 if (language) lang = language[2];
66970 if (d.lang && d.lang !== lang) {
66971 t$$1[key(d.lang)] = undefined;
66974 var value = utilGetSetValue(select(this.parentNode)
66975 .selectAll('.localized-value'));
66977 if (lang && value) {
66978 t$$1[key(lang)] = value;
66979 } else if (lang && wikiTitles && wikiTitles[d.lang]) {
66980 t$$1[key(lang)] = wikiTitles[d.lang];
66984 dispatch$$1.call('change', this, t$$1);
66988 function changeValue(d) {
66989 if (!d.lang) return;
66991 t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
66992 dispatch$$1.call('change', this, t$$1);
66996 function fetcher(value, cb) {
66997 var v = value.toLowerCase();
66999 cb(dataWikipedia.filter(function(d) {
67000 return d[0].toLowerCase().indexOf(v) >= 0 ||
67001 d[1].toLowerCase().indexOf(v) >= 0 ||
67002 d[2].toLowerCase().indexOf(v) >= 0;
67003 }).map(function(d) {
67004 return { value: d[1] };
67009 function render(selection$$1, data$$1) {
67010 var wraps = selection$$1.selectAll('div.entry').
67011 data(data$$1, function(d) { return d.lang; });
67016 .style('max-height','0px')
67017 .style('opacity', '0')
67018 .style('top','-10px')
67021 var innerWrap = wraps.enter()
67022 .insert('div', ':first-child');
67024 innerWrap.attr('class', 'entry')
67026 var wrap = select(this);
67027 var langcombo = d3combobox()
67028 .container(context.container())
67034 .attr('class','form-label')
67035 .text(t('translate.localized_translation_label'))
67036 .attr('for','localized-lang');
67040 .attr('class', 'minor remove')
67041 .on('click', function(d){
67042 event.preventDefault();
67044 t$$1[key(d.lang)] = undefined;
67045 dispatch$$1.call('change', this, t$$1);
67046 select(this.parentNode.parentNode)
67048 .style('max-height','240px')
67050 .style('opacity', '0')
67051 .style('max-height','0px')
67054 .call(svgIcon('#operation-delete'));
67058 .attr('class', 'localized-lang')
67059 .attr('type', 'text')
67060 .attr('placeholder',t('translate.localized_translation_language'))
67061 .on('blur', changeLang)
67062 .on('change', changeLang)
67067 .on('blur', changeValue)
67068 .on('change', changeValue)
67069 .attr('type', 'text')
67070 .attr('placeholder', t('translate.localized_translation_name'))
67071 .attr('class', 'localized-value');
67075 .style('margin-top', '0px')
67076 .style('max-height', '0px')
67077 .style('opacity', '0')
67080 .style('margin-top', '10px')
67081 .style('max-height', '240px')
67082 .style('opacity', '1')
67083 .on('end', function() {
67085 .style('max-height', '')
67086 .style('overflow', 'visible');
67090 var entry = selection$$1.selectAll('.entry');
67092 utilGetSetValue(entry.select('.localized-lang'), function(d) {
67093 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
67094 return lang ? lang[1] : d.lang;
67097 utilGetSetValue(entry.select('.localized-value'),
67098 function(d) { return d.value; });
67102 localized.tags = function(tags) {
67103 // Fetch translations from wikipedia
67104 if (tags.wikipedia && !wikiTitles) {
67106 var wm = tags.wikipedia.match(/([^:]+):(.+)/);
67107 if (wm && wm[0] && wm[1]) {
67108 wikipedia.translations(wm[1], wm[2], function(d) {
67114 utilGetSetValue(input, tags[field.key] || '');
67116 var postfixed = [], k, m;
67118 m = k.match(/^(.*):([a-zA-Z_-]+)$/);
67119 if (m && m[1] === field.key && m[2]) {
67120 postfixed.push({ lang: m[2], value: tags[k] });
67124 localizedInputs.call(render, postfixed.reverse());
67128 localized.focus = function() {
67129 input.node().focus();
67133 localized.entity = function(_) {
67134 if (!arguments.length) return entity;
67139 return utilRebind(localized, dispatch$$1, 'on');
67142 function uiFieldMaxspeed(field, context) {
67143 var dispatch$$1 = dispatch('change'),
67146 unitInput = select(null),
67147 input = select(null),
67150 var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
67151 imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
67154 function maxspeed(selection$$1) {
67155 combobox = d3combobox()
67156 .container(context.container());
67158 var unitCombobox = d3combobox()
67159 .container(context.container())
67160 .data(['km/h', 'mph'].map(comboValues));
67162 input = selection$$1.selectAll('#preset-input-' + field.id)
67165 input = input.enter()
67167 .attr('type', 'text')
67168 .attr('id', 'preset-input-' + field.id)
67169 .attr('placeholder', field.placeholder())
67175 .on('change', change)
67176 .on('blur', change);
67178 var childNodes = context.graph().childNodes(context.entity(entity.id)),
67179 loc = childNodes[~~(childNodes.length/2)].loc;
67181 isImperial = lodash.some(dataImperial.features, function(f) {
67182 return lodash.some(f.geometry.coordinates, function(d) {
67183 return geoPointInPolygon(loc, d);
67187 unitInput = selection$$1.selectAll('input.maxspeed-unit')
67190 unitInput = unitInput.enter()
67192 .attr('type', 'text')
67193 .attr('class', 'maxspeed-unit')
67194 .call(unitCombobox)
67198 .on('blur', changeUnits)
67199 .on('change', changeUnits);
67202 function changeUnits() {
67203 isImperial = utilGetSetValue(unitInput) === 'mph';
67204 utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
67211 function setSuggestions() {
67212 combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
67213 utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
67217 function comboValues(d) {
67219 value: d.toString(),
67220 title: d.toString()
67225 function change() {
67227 value = utilGetSetValue(input);
67230 tag[field.key] = undefined;
67231 } else if (isNaN(value) || !isImperial) {
67232 tag[field.key] = value;
67234 tag[field.key] = value + ' mph';
67237 dispatch$$1.call('change', this, tag);
67241 maxspeed.tags = function(tags) {
67242 var value = tags[field.key];
67244 if (value && value.indexOf('mph') >= 0) {
67245 value = parseInt(value, 10);
67247 } else if (value) {
67248 isImperial = false;
67252 utilGetSetValue(input, value || '');
67256 maxspeed.focus = function() {
67257 input.node().focus();
67261 maxspeed.entity = function(_) {
67266 return utilRebind(maxspeed, dispatch$$1, 'on');
67269 function uiFieldRadio(field, context) {
67270 var dispatch$$1 = dispatch('change'),
67271 taginfo = services.taginfo,
67272 placeholder = select(null),
67273 wrap = select(null),
67274 labels = select(null),
67275 radios = select(null),
67276 typeInput = select(null),
67277 layerInput = select(null),
67282 function selectedKey() {
67283 var selector$$1 = '.form-field-structure .toggle-list label.active input',
67284 node = selectAll(selector$$1);
67285 return !node.empty() && node.datum();
67288 // returns the tag value for a display value
67289 function tagValue(dispVal) {
67290 dispVal = snake(clean(dispVal || ''));
67291 return dispVal.toLowerCase() || 'yes';
67294 // returns the display value for a tag value
67295 function displayValue(tagVal) {
67296 tagVal = tagVal || '';
67297 return tagVal.toLowerCase() === 'yes' ? '' : unsnake(tagVal);
67300 function snake(s) {
67301 return s.replace(/\s+/g, '_');
67304 function unsnake(s) {
67305 return s.replace(/_+/g, ' ');
67308 function clean(s) {
67309 return s.split(';')
67310 .map(function(s) { return s.trim(); })
67315 function radio(selection$$1) {
67316 selection$$1.classed('preset-radio', true);
67318 wrap = selection$$1.selectAll('.preset-input-wrap')
67321 var enter = wrap.enter()
67323 .attr('class', 'preset-input-wrap toggle-list');
67327 .attr('class', 'placeholder');
67333 placeholder = wrap.selectAll('.placeholder');
67335 labels = wrap.selectAll('label')
67336 .data(field.options || field.keys);
67338 enter = labels.enter()
67343 .attr('type', 'radio')
67344 .attr('name', field.id)
67345 .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
67346 .attr('checked', false);
67350 .text(function(d) { return field.t('options.' + d, { 'default': d }); });
67355 radios = labels.selectAll('input')
67356 .on('change', changeRadio);
67360 function structureExtras(selection$$1) {
67361 var selected = selectedKey();
67363 var extrasWrap = selection$$1.selectAll('.structure-extras-wrap')
67364 .data(selected ? [0] : []);
67369 extrasWrap = extrasWrap.enter()
67371 .attr('class', 'structure-extras-wrap')
67372 .merge(extrasWrap);
67374 var list = extrasWrap.selectAll('ul')
67377 list = list.enter()
67383 var typeItem = list.selectAll('.structure-type-item')
67386 var typeEnter = typeItem.enter()
67388 .attr('class', 'cf structure-type-item');
67392 .attr('class', 'col6 label structure-label-type')
67393 .attr('for', 'structure-input-type')
67394 .text(t('inspector.radio.structure.type'));
67398 .attr('class', 'col6 structure-input-type-wrap')
67400 .attr('type', 'text')
67401 .attr('class', 'structure-input-type')
67402 .attr('placeholder', t('inspector.radio.structure.default'))
67405 typeItem = typeItem
67408 typeInput = typeItem.selectAll('.structure-input-type');
67413 .container(context.container())
67414 .fetcher(typeFetcher)
67419 .on('change', changeType)
67420 .on('blur', changeType);
67424 var showLayer = (selected === 'bridge' || selected === 'tunnel');
67426 var layerItem = list.selectAll('.structure-layer-item')
67427 .data(showLayer ? [0] : []);
67432 var layerEnter = layerItem.enter()
67434 .attr('class', 'cf structure-layer-item');
67438 .attr('class', 'col6 label structure-label-layer')
67439 .attr('for', 'structure-input-layer')
67440 .text(t('inspector.radio.structure.layer'));
67444 .attr('class', 'col6 structure-input-layer-wrap')
67446 .attr('type', 'text')
67447 .attr('class', 'structure-input-layer')
67448 .attr('placeholder', '0')
67451 var spin = layerEnter
67453 .attr('class', 'spin-control');
67458 .attr('class', 'decrement')
67459 .attr('tabindex', -1);
67464 .attr('class', 'increment')
67465 .attr('tabindex', -1);
67467 layerItem = layerItem
67468 .merge(layerEnter);
67470 layerInput = layerItem.selectAll('.structure-input-layer')
67471 .on('change', changeLayer)
67472 .on('blur', changeLayer);
67474 layerItem.selectAll('button')
67475 .on('click', function(d) {
67476 event.preventDefault();
67477 var num = parseInt(layerInput.node().value || 0, 10);
67478 if (!isNaN(num)) layerInput.node().value = num + d;
67485 function typeFetcher(q, callback) {
67488 key: selectedKey(),
67490 }, function(err, data) {
67492 var comboData = data.map(function(d) {
67495 value: unsnake(d.value),
67499 if (callback) callback(comboData);
67504 function changeType() {
67505 var key = selectedKey(),
67509 var val = tagValue(utilGetSetValue(typeInput));
67511 if (val !== 'no') oldType[key] = val;
67512 dispatch$$1.call('change', this, t$$1);
67516 function changeLayer() {
67517 // note: don't use utilGetSetValue here because we want 0 to be falsy.
67518 var t$$1 = { layer: layerInput.node().value || undefined };
67519 dispatch$$1.call('change', this, t$$1);
67523 function changeRadio() {
67528 t$$1[field.key] = undefined;
67531 radios.each(function(d) {
67532 var active$$1 = select(this).property('checked');
67533 if (active$$1) activeKey = d;
67536 if (active$$1) t$$1[field.key] = d;
67538 var val = oldType[activeKey] || 'yes';
67539 t$$1[d] = active$$1 ? val : undefined;
67543 if (field.type === 'structureRadio') {
67544 if (activeKey === 'bridge') {
67546 } else if (activeKey === 'tunnel') {
67549 t$$1.layer = undefined;
67553 dispatch$$1.call('change', this, t$$1);
67557 radio.tags = function(tags) {
67558 function checked(d) {
67560 return tags[field.key] === d;
67562 return !!(tags[d] && tags[d].toLowerCase() !== 'no');
67566 labels.classed('active', checked);
67567 radios.property('checked', checked);
67569 var selection$$1 = radios.filter(function() { return this.checked; });
67572 if (selection$$1.empty()) {
67573 placeholder.text(t('inspector.none'));
67575 placeholder.text(selection$$1.attr('value'));
67576 typeVal = oldType[selection$$1.datum()] = tags[selection$$1.datum()];
67579 if (field.type === 'structureRadio') {
67580 wrap.call(structureExtras);
67581 utilGetSetValue(typeInput, displayValue(typeVal) || '');
67582 utilGetSetValue(layerInput, tags.layer || '');
67587 radio.focus = function() {
67588 radios.node().focus();
67592 radio.entity = function(_) {
67593 if (!arguments.length) return entity;
67600 return utilRebind(radio, dispatch$$1, 'on');
67603 function uiFieldRestrictions(field, context) {
67604 var dispatch$$1 = dispatch('change'),
67605 breathe = behaviorBreathe(context),
67606 hover = behaviorHover(context),
67607 initialized = false,
67612 function restrictions(selection$$1) {
67613 // if form field is hidden or has detached from dom, clean up.
67614 if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
67615 selection$$1.call(restrictions.off);
67619 var wrap = selection$$1.selectAll('.preset-input-wrap')
67622 var enter = wrap.enter()
67624 .attr('class', 'preset-input-wrap');
67628 .attr('class', 'restriction-help');
67631 var intersection = osmIntersection(context.graph(), vertexID),
67632 graph = intersection.graph,
67633 vertex = graph.entity(vertexID),
67634 filter = utilFunctor(true),
67635 extent$$1 = geoExtent$$1(),
67636 projection = geoRawMercator();
67638 var d = utilGetDimensions(wrap.merge(enter)),
67639 c = [d[0] / 2, d[1] / 2],
67643 .scale(256 * Math.pow(2, z) / (2 * Math.PI));
67645 var s = projection(vertex.loc);
67648 .translate([c[0] - s[0], c[1] - s[1]])
67649 .clipExtent([[0, 0], d]);
67651 var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
67652 drawVertices = svgVertices$$1(projection, context),
67653 drawLines = svgLines$$1(projection, context),
67654 drawTurns = svgTurns(projection, context);
67662 var surface = wrap.selectAll('.surface');
67664 if (!enter.empty()) {
67665 initialized = true;
67672 .call(utilSetDimensions, d)
67673 .call(drawVertices, graph, [vertex], filter, extent$$1, z)
67674 .call(drawLines, graph, intersection.ways, filter)
67675 .call(drawTurns, graph, intersection.turns(fromNodeID));
67678 .on('click.restrictions', click)
67679 .on('mouseover.restrictions', mouseover)
67680 .on('mouseout.restrictions', mouseout);
67683 .selectAll('.selected')
67684 .classed('selected', false);
67688 .selectAll('.' + intersection.highways[fromNodeID].id)
67689 .classed('selected', true);
67695 .on('change.restrictions', render);
67698 .on('resize.restrictions', function() {
67699 utilSetDimensions(wrap, null);
67709 var datum = event.target.__data__;
67710 if (datum instanceof osmEntity$$1) {
67711 fromNodeID = intersection.adjacentNodeId(datum.id);
67713 } else if (datum instanceof osmTurn) {
67714 if (datum.restriction) {
67716 actionUnrestrictTurn(datum, projection),
67717 t('operations.restriction.annotation.delete')
67721 actionRestrictTurn(datum, projection),
67722 t('operations.restriction.annotation.create')
67729 function mouseover() {
67730 var datum = event.target.__data__;
67731 if (datum instanceof osmTurn) {
67732 var graph = context.graph(),
67733 presets = context.presets(),
67736 if (datum.restriction) {
67737 preset = presets.match(graph.entity(datum.restriction), graph);
67739 preset = presets.item('type/restriction/' +
67740 osmInferRestriction(
67750 wrap.selectAll('.restriction-help')
67751 .text(t('operations.restriction.help.' +
67752 (datum.restriction ? 'toggle_off' : 'toggle_on'),
67753 { restriction: preset.name() })
67759 function mouseout() {
67760 wrap.selectAll('.restriction-help')
67761 .text(t('operations.restriction.help.' +
67762 (fromNodeID ? 'toggle' : 'select'))
67767 function render() {
67768 if (context.hasEntity(vertexID)) {
67769 restrictions(selection$$1);
67775 restrictions.entity = function(_) {
67776 if (!vertexID || vertexID !== _.id) {
67783 restrictions.tags = function() {};
67784 restrictions.focus = function() {};
67787 restrictions.off = function(selection$$1) {
67788 if (!initialized) return;
67790 selection$$1.selectAll('.surface')
67793 .on('click.restrictions', null)
67794 .on('mouseover.restrictions', null)
67795 .on('mouseout.restrictions', null);
67798 .on('change.restrictions', null);
67801 .on('resize.restrictions', null);
67805 return utilRebind(restrictions, dispatch$$1, 'on');
67808 function uiFieldTextarea(field) {
67809 var dispatch$$1 = dispatch('change'),
67810 input = select(null);
67813 function textarea(selection$$1) {
67814 input = selection$$1.selectAll('textarea')
67817 input = input.enter()
67818 .append('textarea')
67819 .attr('id', 'preset-input-' + field.id)
67820 .attr('placeholder', field.placeholder() || t('inspector.unknown'))
67821 .attr('maxlength', 255)
67823 .on('input', change(true))
67824 .on('blur', change())
67825 .on('change', change())
67830 function change(onInput) {
67831 return function() {
67833 t$$1[field.key] = utilGetSetValue(input) || undefined;
67834 dispatch$$1.call('change', this, t$$1, onInput);
67839 textarea.tags = function(tags) {
67840 utilGetSetValue(input, tags[field.key] || '');
67844 textarea.focus = function() {
67845 input.node().focus();
67849 return utilRebind(textarea, dispatch$$1, 'on');
67852 function uiFieldWikipedia(field, context) {
67853 var dispatch$$1 = dispatch('change'),
67854 wikipedia = services.wikipedia,
67855 wikidata = services.wikidata,
67856 link = select(null),
67857 lang = select(null),
67858 title = select(null),
67863 function wiki(selection$$1) {
67864 var langcombo = d3combobox()
67865 .container(context.container())
67866 .fetcher(function(value, cb) {
67867 var v = value.toLowerCase();
67869 cb(dataWikipedia.filter(function(d) {
67870 return d[0].toLowerCase().indexOf(v) >= 0 ||
67871 d[1].toLowerCase().indexOf(v) >= 0 ||
67872 d[2].toLowerCase().indexOf(v) >= 0;
67873 }).map(function(d) {
67874 return { value: d[1] };
67878 var titlecombo = d3combobox()
67879 .container(context.container())
67880 .fetcher(function(value, cb) {
67882 value = context.entity(entity.id).tags.name || '';
67885 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
67886 searchfn(language()[2], value, function(query, data$$1) {
67887 cb(data$$1.map(function(d) {
67888 return { value: d };
67894 lang = selection$$1.selectAll('input.wiki-lang')
67897 lang = lang.enter()
67899 .attr('type', 'text')
67900 .attr('class', 'wiki-lang')
67901 .attr('placeholder', t('translate.localized_translation_language'))
67905 utilGetSetValue(lang, language()[1]);
67909 .on('blur', changeLang)
67910 .on('change', changeLang);
67913 title = selection$$1.selectAll('input.wiki-title')
67916 title = title.enter()
67918 .attr('type', 'text')
67919 .attr('class', 'wiki-title')
67920 .attr('id', 'preset-input-' + field.id)
67927 .on('change', change);
67930 link = selection$$1.selectAll('.wiki-link')
67933 link = link.enter()
67935 .attr('class', 'button-input-action wiki-link minor')
67936 .attr('tabindex', -1)
67937 .call(svgIcon('#icon-out-link'))
67941 .on('click', function() {
67942 event.preventDefault();
67943 if (wikiURL) window.open(wikiURL, '_blank');
67948 function language() {
67949 var value = utilGetSetValue(lang).toLowerCase();
67950 var locale = utilDetect().locale.toLowerCase();
67951 var localeLanguage;
67952 return lodash.find(dataWikipedia, function(d) {
67953 if (d[2] === locale) localeLanguage = d;
67954 return d[0].toLowerCase() === value ||
67955 d[1].toLowerCase() === value ||
67957 }) || localeLanguage || ['English', 'English', 'en'];
67961 function changeLang() {
67962 utilGetSetValue(lang, language()[1]);
67972 function change(skipWikidata) {
67973 var value = utilGetSetValue(title),
67974 m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
67975 l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
67980 // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
67981 value = decodeURIComponent(m[2]).replace(/_/g, ' ');
67984 // Best-effort `anchordecode:` implementation
67985 anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
67987 anchor = decodeURIComponent(m[3]);
67989 value += '#' + anchor.replace(/_/g, ' ');
67991 value = value.slice(0, 1).toUpperCase() + value.slice(1);
67992 utilGetSetValue(lang, l[1]);
67993 utilGetSetValue(title, value);
67996 syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
67997 if (!skipWikidata) {
67998 syncTags.wikidata = undefined;
68001 dispatch$$1.call('change', this, syncTags);
68004 if (skipWikidata || !value || !language()[2]) return;
68006 // attempt asynchronous update of wikidata tag..
68007 var initEntityId = entity.id,
68008 initWikipedia = context.entity(initEntityId).tags.wikipedia;
68010 wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
68011 if (!data$$1 || !Object.keys(data$$1).length) return;
68012 var qids = Object.keys(data$$1);
68014 // 1. most recent change was a tag change
68015 var annotation = t('operations.change_tags.annotation'),
68016 currAnnotation = context.history().undoAnnotation();
68017 if (currAnnotation !== annotation) return;
68019 // 2. same entity exists and still selected
68020 var selectedIds = context.selectedIDs(),
68021 currEntityId = selectedIds.length > 0 && selectedIds[0];
68022 if (currEntityId !== initEntityId) return;
68024 // 3. wikipedia value has not changed
68025 var currTags = lodash.clone(context.entity(currEntityId).tags);
68026 if (initWikipedia !== currTags.wikipedia) return;
68028 // ok to coalesce the update of wikidata tag into the previous tag change
68029 currTags.wikidata = qids && lodash.find(qids, function(id) {
68030 return id.match(/^Q\d+$/);
68033 context.overwrite(actionChangeTags(currEntityId, currTags), annotation);
68034 dispatch$$1.call('change', this, currTags);
68039 wiki.tags = function(tags) {
68040 var value = tags[field.key] || '',
68041 m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
68042 l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
68043 anchor = m && m[3];
68045 // value in correct format
68047 utilGetSetValue(lang, l[1]);
68048 utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
68051 // Best-effort `anchorencode:` implementation
68052 anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
68054 anchor = anchor.replace(/ /g, '_');
68057 wikiURL = 'https://' + m[1] + '.wikipedia.org/wiki/' +
68058 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : '');
68060 // unrecognized value format
68062 utilGetSetValue(title, value);
68063 if (value && value !== '') {
68064 utilGetSetValue(lang, '');
68065 wikiURL = 'https://en.wikipedia.org/wiki/Special:Search?search=' + value;
68073 wiki.entity = function(_) {
68074 if (!arguments.length) return entity;
68080 wiki.focus = function() {
68081 title.node().focus();
68085 return utilRebind(wiki, dispatch$$1, 'on');
68089 access: uiFieldAccess,
68090 address: uiFieldAddress,
68091 check: uiFieldCheck,
68092 combo: uiFieldCombo,
68093 cycleway: uiFieldCycleway,
68094 defaultCheck: uiFieldCheck,
68095 email: uiFieldText,
68096 lanes: uiFieldLanes,
68097 localized: uiFieldLocalized,
68098 maxspeed: uiFieldMaxspeed,
68099 multiCombo: uiFieldCombo,
68100 networkCombo: uiFieldCombo,
68101 number: uiFieldText,
68102 onewayCheck: uiFieldCheck,
68103 radio: uiFieldRadio,
68104 restrictions: uiFieldRestrictions,
68105 semiCombo: uiFieldCombo,
68106 structureRadio: uiFieldRadio,
68109 textarea: uiFieldTextarea,
68110 typeCombo: uiFieldCombo,
68112 wikipedia: uiFieldWikipedia
68115 function uiPreset(context) {
68116 var dispatch$$1 = dispatch('change'),
68124 // Field Constructor
68125 function UIField(field, entity, show) {
68126 field = lodash.clone(field);
68128 field.input = uiFields[field.type](field, context)
68129 .on('change', function(t$$1, onInput) {
68130 dispatch$$1.call('change', field, t$$1, onInput);
68133 if (field.input.entity) field.input.entity(entity);
68135 field.keys = field.keys || [field.key];
68139 field.shown = function() {
68140 return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
68143 field.modified = function() {
68144 var original = context.graph().base().entities[entity.id];
68145 return lodash.some(field.keys, function(key) {
68146 return original ? tags[key] !== original.tags[key] : tags[key];
68150 field.revert = function() {
68151 var original = context.graph().base().entities[entity.id],
68153 field.keys.forEach(function(key) {
68154 t$$1[key] = original ? original.tags[key] : undefined;
68159 field.present = function() {
68160 return lodash.some(field.keys, function(key) {
68165 field.remove = function() {
68167 field.keys.forEach(function(key) {
68168 t$$1[key] = undefined;
68177 function fieldKey(field) {
68182 function presets(selection$$1) {
68183 selection$$1.call(uiDisclosure()
68184 .title(t('inspector.all_fields'))
68185 .expanded(context.storage('preset_fields.expanded') !== 'false')
68186 .on('toggled', toggled)
68190 function toggled(expanded) {
68191 context.storage('preset_fields.expanded', expanded);
68196 function content(selection$$1) {
68198 var entity = context.entity(id),
68199 geometry = context.geometry(id),
68200 presets = context.presets();
68204 if (presets.field('name')) {
68205 fieldsArr.push(UIField(presets.field('name'), entity));
68208 preset.fields.forEach(function(field) {
68209 if (field.matchGeometry(geometry)) {
68210 fieldsArr.push(UIField(field, entity, true));
68214 if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
68215 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
68218 presets.universal().forEach(function(field) {
68219 if (preset.fields.indexOf(field) < 0) {
68220 fieldsArr.push(UIField(field, entity));
68225 var shown = fieldsArr.filter(function(field) { return field.shown(); }),
68226 notShown = fieldsArr.filter(function(field) { return !field.shown(); });
68229 var form = selection$$1.selectAll('.preset-form')
68232 form = form.enter()
68234 .attr('class', 'preset-form inspector-inner fillL3')
68238 var fields = form.selectAll('.form-field')
68239 .data(shown, fieldKey);
68245 var enter = fields.enter()
68247 .attr('class', function(field) {
68248 return 'form-field form-field-' + field.id;
68253 .attr('class', 'form-label')
68254 .attr('for', function(field) { return 'preset-input-' + field.id; })
68255 .text(function(field) { return field.label(); });
68259 .attr('class', 'form-label-button-wrap');
68261 wrap.append('button')
68262 .attr('class', 'remove-icon')
68263 .attr('tabindex', -1)
68264 .call(svgIcon('#operation-delete'));
68266 wrap.append('button')
68267 .attr('class', 'modified-icon')
68268 .attr('tabindex', -1)
68270 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
68278 fields.selectAll('.form-label-button-wrap .remove-icon')
68279 .on('click', remove);
68281 fields.selectAll('.modified-icon')
68282 .on('click', revert);
68286 .classed('modified', function(field) { return field.modified(); })
68287 .classed('present', function(field) { return field.present(); })
68288 .each(function(field) {
68289 var reference = uiTagReference(field.reference || { key: field.key }, context);
68291 if (state === 'hover') {
68292 reference.showing(false);
68297 .selectAll('input')
68298 .on('keydown', function() {
68299 // if user presses enter, and combobox is not active, accept edits..
68300 if (event.keyCode === 13 && select('.combobox').empty()) {
68301 context.enter(modeBrowse(context));
68306 .call(reference.body)
68307 .select('.form-label-button-wrap')
68308 .call(reference.button);
68310 field.input.tags(tags);
68313 notShown = notShown.map(function(field) {
68315 title: field.label(),
68316 value: field.label(),
68322 var more = selection$$1.selectAll('.more-fields')
68323 .data((notShown.length > 0) ? [0] : []);
68328 more = more.enter()
68330 .attr('class', 'more-fields')
68332 .text(t('inspector.add_fields'))
68336 var input = more.selectAll('.value')
68342 input = input.enter()
68344 .attr('class', 'value')
68345 .attr('type', 'text')
68350 .call(utilGetSetValue, '')
68351 .attr('placeholder', function() {
68352 var placeholder = [];
68353 for (var field in notShown) {
68354 placeholder.push(notShown[field].title);
68356 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
68359 .container(context.container())
68362 .on('accept', show)
68366 function show(field) {
68367 field = field.field;
68369 content(selection$$1);
68370 field.input.focus();
68374 function revert(field) {
68375 event.stopPropagation();
68376 event.preventDefault();
68377 dispatch$$1.call('change', field, field.revert());
68381 function remove(field) {
68382 event.stopPropagation();
68383 event.preventDefault();
68384 dispatch$$1.call('change', field, field.remove());
68389 presets.preset = function(_) {
68390 if (!arguments.length) return preset;
68391 if (preset && preset.id === _.id) return presets;
68398 presets.state = function(_) {
68399 if (!arguments.length) return state;
68405 presets.tags = function(_) {
68406 if (!arguments.length) return tags;
68408 // Don't reset fieldsArr here.
68413 presets.entityID = function(_) {
68414 if (!arguments.length) return id;
68415 if (id === _) return presets;
68422 return utilRebind(presets, dispatch$$1, 'on');
68425 function uiEntityEditor(context) {
68426 var dispatch$$1 = dispatch('choose'),
68428 coalesceChanges = false,
68435 var presetEditor = uiPreset(context)
68436 .on('change', changeTags);
68437 var rawTagEditor = uiRawTagEditor(context)
68438 .on('change', changeTags);
68441 function entityEditor(selection$$1) {
68442 var entity = context.entity(id),
68443 tags = lodash.clone(entity.tags);
68446 var header = selection$$1.selectAll('.header')
68450 var enter = header.enter()
68452 .attr('class', 'header fillL cf');
68456 .attr('class', 'fl preset-reset preset-choose')
68457 .call(svgIcon((textDirection === 'rtl') ? '#icon-forward' : '#icon-backward'));
68461 .attr('class', 'fr preset-close')
68462 .on('click', function() { context.enter(modeBrowse(context)); })
68463 .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
68467 .text(t('inspector.edit'));
68473 header.selectAll('.preset-reset')
68474 .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
68478 var body = selection$$1.selectAll('.inspector-body')
68482 enter = body.enter()
68484 .attr('class', 'inspector-body');
68488 .attr('class', 'preset-list-item inspector-inner')
68490 .attr('class', 'preset-list-button-wrap')
68492 .attr('class', 'preset-list-button preset-reset')
68493 .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
68495 .attr('class', 'label');
68499 .attr('class', 'inspector-border inspector-preset');
68503 .attr('class', 'inspector-border raw-tag-editor inspector-inner');
68507 .attr('class', 'inspector-border raw-member-editor inspector-inner');
68511 .attr('class', 'raw-membership-editor inspector-inner');
68517 body.selectAll('.preset-list-button-wrap')
68518 .call(reference.button);
68520 body.selectAll('.preset-list-item')
68521 .call(reference.body);
68523 body.selectAll('.preset-reset')
68524 .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
68526 body.select('.preset-list-item button')
68527 .call(uiPresetIcon()
68528 .geometry(context.geometry(id))
68529 .preset(activePreset));
68531 body.select('.preset-list-item .label')
68532 .text(activePreset.name());
68534 body.select('.inspector-preset')
68536 .preset(activePreset)
68541 body.select('.raw-tag-editor')
68543 .preset(activePreset)
68548 if (entity.type === 'relation') {
68549 body.select('.raw-member-editor')
68550 .style('display', 'block')
68551 .call(uiRawMemberEditor(context)
68554 body.select('.raw-member-editor')
68555 .style('display', 'none');
68558 body.select('.raw-membership-editor')
68559 .call(uiRawMembershipEditor(context)
68564 .on('change.entity-editor', historyChanged);
68567 function historyChanged() {
68568 if (state === 'hide') return;
68570 var entity = context.hasEntity(id),
68571 graph = context.graph();
68572 if (!entity) return;
68574 entityEditor.preset(context.presets().match(entity, graph));
68575 entityEditor.modified(base !== graph);
68576 entityEditor(selection$$1);
68581 function clean(o) {
68583 function cleanVal(k, v) {
68584 function keepSpaces(k) {
68585 return k.match(/_hours|_times/) !== null;
68588 var blacklist = ['description', 'note', 'fixme'];
68589 if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
68591 var cleaned = v.split(';')
68592 .map(function(s) { return s.trim(); })
68593 .join(keepSpaces(k) ? '; ' : ';');
68595 // The code below is not intended to validate websites and emails.
68596 // It is only intended to prevent obvious copy-paste errors. (#2323)
68597 // clean website- and email-like tags
68598 if (k.indexOf('website') !== -1 ||
68599 k.indexOf('email') !== -1 ||
68600 cleaned.indexOf('http') === 0) {
68602 .replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars
68609 var out = {}, k, v;
68611 if (k && (v = o[k]) !== undefined) {
68612 out[k] = cleanVal(k, v);
68619 // Tag changes that fire on input can all get coalesced into a single
68620 // history operation when the user leaves the field. #2342
68621 function changeTags(changed, onInput) {
68622 var entity = context.entity(id),
68623 annotation = t('operations.change_tags.annotation'),
68624 tags = lodash.clone(entity.tags);
68626 lodash.forEach(changed, function(v, k) {
68627 if (v !== undefined || tags.hasOwnProperty(k)) {
68633 tags = clean(tags);
68636 if (!lodash.isEqual(entity.tags, tags)) {
68637 if (coalesceChanges) {
68638 context.overwrite(actionChangeTags(id, tags), annotation);
68640 context.perform(actionChangeTags(id, tags), annotation);
68641 coalesceChanges = !!onInput;
68647 entityEditor.modified = function(_) {
68648 if (!arguments.length) return modified;
68650 selectAll('button.preset-close use')
68651 .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
68655 entityEditor.state = function(_) {
68656 if (!arguments.length) return state;
68658 return entityEditor;
68662 entityEditor.entityID = function(_) {
68663 if (!arguments.length) return id;
68665 base = context.graph();
68666 entityEditor.preset(context.presets().match(context.entity(id), base));
68667 entityEditor.modified(false);
68668 coalesceChanges = false;
68669 return entityEditor;
68673 entityEditor.preset = function(_) {
68674 if (!arguments.length) return activePreset;
68675 if (_ !== activePreset) {
68677 reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
68680 return entityEditor;
68684 return utilRebind(entityEditor, dispatch$$1, 'on');
68687 function uiPresetList(context) {
68688 var dispatch$$1 = dispatch('choose'),
68694 function presetList(selection$$1) {
68695 var entity = context.entity(id),
68696 geometry = context.geometry(id);
68698 // Treat entities on addr:interpolation lines as points, not vertices (#3241)
68699 if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
68700 geometry = 'point';
68703 var presets = context.presets().matchGeometry(geometry);
68705 selection$$1.html('');
68707 var messagewrap = selection$$1
68709 .attr('class', 'header fillL cf');
68711 var message = messagewrap
68713 .text(t('inspector.choose'));
68715 if (context.entity(id).isUsed(context.graph())) {
68718 .attr('class', 'preset-choose')
68719 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
68720 .call(svgIcon((textDirection === 'rtl') ? '#icon-backward' : '#icon-forward'));
68724 .attr('class', 'close')
68725 .on('click', function() {
68726 context.enter(modeBrowse(context));
68728 .call(svgIcon('#icon-close'));
68731 function keydown() {
68732 // hack to let delete shortcut work when search is autofocused
68733 if (search.property('value').length === 0 &&
68734 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
68735 event.keyCode === d3keybinding.keyCodes['⌦'])) {
68736 event.preventDefault();
68737 event.stopPropagation();
68738 operationDelete([id], context)();
68739 } else if (search.property('value').length === 0 &&
68740 (event.ctrlKey || event.metaKey) &&
68741 event.keyCode === d3keybinding.keyCodes.z) {
68742 event.preventDefault();
68743 event.stopPropagation();
68745 } else if (!event.ctrlKey && !event.metaKey) {
68746 select(this).on('keydown', null);
68750 function keypress() {
68752 var value = search.property('value');
68753 if (event.keyCode === 13 && value.length) {
68754 list.selectAll('.preset-list-item:first-child').datum().choose();
68758 function inputevent() {
68759 var value = search.property('value');
68760 list.classed('filtered', value.length);
68761 if (value.length) {
68762 var results = presets.search(value, geometry);
68763 message.text(t('inspector.results', {
68764 n: results.collection.length,
68767 list.call(drawList, results);
68769 list.call(drawList, context.presets().defaults(geometry, 36));
68770 message.text(t('inspector.choose'));
68774 var searchWrap = selection$$1
68776 .attr('class', 'search-header');
68778 var search = searchWrap
68780 .attr('class', 'preset-search-input')
68781 .attr('placeholder', t('inspector.search'))
68782 .attr('type', 'search')
68784 .on('keydown', keydown)
68785 .on('keypress', keypress)
68786 .on('input', inputevent);
68789 .call(svgIcon('#icon-search', 'pre-text'));
68792 search.node().focus();
68795 var listWrap = selection$$1
68797 .attr('class', 'inspector-body');
68799 var list = listWrap
68801 .attr('class', 'preset-list fillL cf')
68802 .call(drawList, context.presets().defaults(geometry, 36));
68806 function drawList(list, presets) {
68807 var collection = presets.collection.map(function(preset) {
68808 return preset.members ? CategoryItem(preset) : PresetItem(preset);
68811 var items = list.selectAll('.preset-list-item')
68812 .data(collection, function(d) { return d.preset.id; });
68821 .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
68822 .classed('current', function(item) { return item.preset === currentPreset; })
68823 .each(function(item) { select(this).call(item); })
68824 .style('opacity', 0)
68826 .style('opacity', 1);
68830 function CategoryItem(preset) {
68831 var box, sublist, shown = false;
68833 function item(selection$$1) {
68834 var wrap = selection$$1.append('div')
68835 .attr('class', 'preset-list-button-wrap category col12');
68839 .attr('class', 'preset-list-button')
68840 .classed('expanded', false)
68841 .call(uiPresetIcon()
68842 .geometry(context.geometry(id))
68844 .on('click', function() {
68845 var isExpanded = select(this).classed('expanded');
68846 var iconName = isExpanded ?
68847 (textDirection === 'rtl' ? '#icon-backward' : '#icon-forward') : '#icon-down';
68849 .classed('expanded', !isExpanded);
68850 select(this).selectAll('div.label svg.icon use')
68851 .attr('href', iconName);
68857 .attr('class', 'label');
68860 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'))
68862 .html(function() { return preset.name() + '…'; });
68864 box = selection$$1.append('div')
68865 .attr('class', 'subgrid col12')
68866 .style('max-height', '0px')
68867 .style('opacity', 0);
68870 .attr('class', 'arrow');
68872 sublist = box.append('div')
68873 .attr('class', 'preset-list fillL3 cf fl');
68877 item.choose = function() {
68878 if (!box || !sublist) return;
68884 .style('opacity', '0')
68885 .style('max-height', '0px')
68886 .style('padding-bottom', '0px');
68889 sublist.call(drawList, preset.members);
68892 .style('opacity', '1')
68893 .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
68894 .style('padding-bottom', '20px');
68898 item.preset = preset;
68904 function PresetItem(preset) {
68905 function item(selection$$1) {
68906 var wrap = selection$$1.append('div')
68907 .attr('class', 'preset-list-button-wrap col12');
68909 wrap.append('button')
68910 .attr('class', 'preset-list-button')
68911 .call(uiPresetIcon()
68912 .geometry(context.geometry(id))
68914 .on('click', item.choose)
68916 .attr('class', 'label')
68917 .text(preset.name());
68919 wrap.call(item.reference.button);
68920 selection$$1.call(item.reference.body);
68923 item.choose = function() {
68924 context.presets().choose(preset);
68927 actionChangePreset(id, currentPreset, preset),
68928 t('operations.change_tags.annotation')
68931 dispatch$$1.call('choose', this, preset);
68934 item.help = function() {
68935 event.stopPropagation();
68936 item.reference.toggle();
68939 item.preset = preset;
68940 item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
68946 presetList.autofocus = function(_) {
68947 if (!arguments.length) return autofocus;
68953 presetList.entityID = function(_) {
68954 if (!arguments.length) return id;
68956 presetList.preset(context.presets().match(context.entity(id), context.graph()));
68961 presetList.preset = function(_) {
68962 if (!arguments.length) return currentPreset;
68968 return utilRebind(presetList, dispatch$$1, 'on');
68971 function uiViewOnOSM(context) {
68974 function viewOnOSM(selection) {
68975 var entity = context.entity(id);
68977 selection.style('display', entity.isNew() ? 'none' : null);
68979 var link = selection.selectAll('.view-on-osm')
68982 var enter = link.enter()
68984 .attr('class', 'view-on-osm')
68985 .attr('target', '_blank')
68986 .call(svgIcon('#icon-out-link', 'inline'));
68990 .text(t('inspector.view_on_osm'));
68994 .attr('href', context.connection().entityURL(entity));
68998 viewOnOSM.entityID = function(_) {
68999 if (!arguments.length) return id;
69007 function uiInspector(context) {
69008 var presetList = uiPresetList(context),
69009 entityEditor = uiEntityEditor(context),
69012 newFeature = false;
69015 function inspector(selection$$1) {
69017 .entityID(entityID)
69018 .autofocus(newFeature)
69019 .on('choose', setPreset);
69023 .entityID(entityID)
69024 .on('choose', showList);
69026 var wrap = selection$$1.selectAll('.panewrap')
69029 var enter = wrap.enter()
69031 .attr('class', 'panewrap');
69035 .attr('class', 'preset-list-pane pane');
69039 .attr('class', 'entity-editor-pane pane');
69041 wrap = wrap.merge(enter);
69042 var presetPane = wrap.selectAll('.preset-list-pane');
69043 var editorPane = wrap.selectAll('.entity-editor-pane');
69045 var graph = context.graph(),
69046 entity = context.entity(entityID),
69047 showEditor = state === 'hover' ||
69048 entity.isUsed(graph) ||
69049 entity.isHighwayIntersection(graph);
69052 wrap.style('right', '0%');
69053 editorPane.call(entityEditor);
69055 wrap.style('right', '-100%');
69056 presetPane.call(presetList);
69059 var footer = selection$$1.selectAll('.footer')
69062 footer = footer.enter()
69064 .attr('class', 'footer')
69068 .call(uiViewOnOSM(context).entityID(entityID));
69071 function showList(preset) {
69073 .styleTween('right', function() { return interpolateValue('0%', '-100%'); });
69076 .call(presetList.preset(preset).autofocus(true));
69080 function setPreset(preset) {
69082 .styleTween('right', function() { return interpolateValue('-100%', '0%'); });
69085 .call(entityEditor.preset(preset));
69090 inspector.state = function(_) {
69091 if (!arguments.length) return state;
69093 entityEditor.state(state);
69098 inspector.entityID = function(_) {
69099 if (!arguments.length) return entityID;
69105 inspector.newFeature = function(_) {
69106 if (!arguments.length) return newFeature;
69115 function uiNotice(context) {
69117 return function(selection) {
69118 var div = selection
69120 .attr('class', 'notice');
69124 .attr('class', 'zoom-to notice')
69125 .on('click', function() { context.map().zoom(context.minEditableZoom()); });
69128 .call(svgIcon('#icon-plus', 'pre-text'))
69130 .attr('class', 'label')
69131 .text(t('zoom_in_edit'));
69134 function disableTooHigh() {
69135 div.style('display', context.editable() ? 'none' : 'block');
69139 .on('move.notice', lodash.debounce(disableTooHigh, 500));
69145 function uiSidebar(context) {
69146 var inspector = uiInspector(context),
69150 function sidebar(selection) {
69151 var featureListWrap = selection
69153 .attr('class', 'feature-list-pane')
69154 .call(uiFeatureList(context));
69157 .call(uiNotice(context));
69159 var inspectorWrap = selection
69161 .attr('class', 'inspector-hidden inspector-wrap fr');
69164 function hover(id) {
69165 if (!current && context.hasEntity(id)) {
69167 .classed('inspector-hidden', true);
69170 .classed('inspector-hidden', false)
69171 .classed('inspector-hover', true);
69173 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
69182 } else if (!current) {
69184 .classed('inspector-hidden', false);
69186 .classed('inspector-hidden', true);
69193 sidebar.hover = lodash.throttle(hover, 200);
69196 sidebar.select = function(id, newFeature) {
69197 if (!current && id) {
69199 .classed('inspector-hidden', true);
69202 .classed('inspector-hidden', false)
69203 .classed('inspector-hover', false);
69205 if (inspector.entityID() !== id || inspector.state() !== 'select') {
69209 .newFeature(newFeature);
69215 } else if (!current) {
69217 .classed('inspector-hidden', false);
69219 .classed('inspector-hidden', true);
69226 sidebar.show = function(component) {
69228 .classed('inspector-hidden', true);
69230 .classed('inspector-hidden', true);
69232 if (current) current.remove();
69233 current = selection
69235 .attr('class', 'sidebar-component')
69240 sidebar.hide = function() {
69242 .classed('inspector-hidden', false);
69244 .classed('inspector-hidden', true);
69246 if (current) current.remove();
69252 sidebar.hover = function() {};
69253 sidebar.hover.cancel = function() {};
69254 sidebar.select = function() {};
69255 sidebar.show = function() {};
69256 sidebar.hide = function() {};
69261 function uiSpinner(context) {
69262 var connection = context.connection();
69265 return function(selection) {
69266 var img = selection
69268 .attr('src', context.imagePath('loader-black.gif'))
69269 .style('opacity', 0);
69272 .on('loading.spinner', function() {
69274 .style('opacity', 1);
69278 .on('loaded.spinner', function() {
69280 .style('opacity', 0);
69285 function uiSplash(context) {
69287 return function(selection) {
69288 if (context.storage('sawSplash'))
69291 context.storage('sawSplash', true);
69293 var modalSelection = uiModal(selection);
69295 modalSelection.select('.modal')
69296 .attr('class', 'modal-splash modal col6');
69298 var introModal = modalSelection.select('.content')
69300 .attr('class', 'fillL');
69304 .attr('class','modal-section cf')
69305 .append('h3').text(t('splash.welcome'));
69309 .attr('class','modal-section')
69311 .html(t('splash.text', {
69312 version: context.version,
69313 website: '<a href="http://ideditor.com/">ideditor.com</a>',
69314 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
69317 var buttonWrap = introModal
69319 .attr('class', 'modal-actions cf');
69321 var walkthrough = buttonWrap
69323 .attr('class', 'walkthrough col6')
69324 .on('click', function() {
69325 context.container().call(uiIntro(context));
69326 modalSelection.close();
69331 .attr('class', 'logo logo-walkthrough')
69333 .attr('xlink:href', '#logo-walkthrough');
69337 .text(t('splash.walkthrough'));
69339 var startEditing = buttonWrap
69341 .attr('class', 'start-editing col6')
69342 .on('click', modalSelection.close);
69346 .attr('class', 'logo logo-features')
69348 .attr('xlink:href', '#logo-features');
69352 .text(t('splash.start'));
69355 modalSelection.select('button.close')
69356 .attr('class','hide');
69361 function uiStatus(context) {
69362 var connection = context.connection();
69364 return function(selection$$1) {
69366 function update() {
69367 connection.status(function(err, apiStatus) {
69368 selection$$1.html('');
69371 if (apiStatus === 'rateLimited') {
69373 .text(t('status.rateLimit'))
69375 .attr('class', 'api-status-login')
69376 .attr('target', '_blank')
69377 .call(svgIcon('#icon-out-link', 'inline'))
69380 .on('click.login', function() {
69381 event.preventDefault();
69382 connection.authenticate();
69385 // TODO: nice messages for different error types
69386 selection$$1.text(t('status.error'));
69389 } else if (apiStatus === 'readonly') {
69390 selection$$1.text(t('status.readonly'));
69391 } else if (apiStatus === 'offline') {
69392 selection$$1.text(t('status.offline'));
69395 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
69400 .on('change', function() { update(selection$$1); });
69402 window.setInterval(update, 90000);
69403 update(selection$$1);
69407 function uiUndoRedo(context) {
69411 action: function() { if (!saving()) context.undo(); },
69412 annotation: function() { return context.history().undoAnnotation(); }
69416 action: function() { if (!saving()) context.redo(); },
69417 annotation: function() { return context.history().redoAnnotation(); }
69421 function saving() {
69422 return context.mode().id === 'save';
69426 return function(selection$$1) {
69427 var tooltipBehavior = tooltip()
69428 .placement('bottom')
69430 .title(function (d) {
69431 return uiTooltipHtml(d.annotation() ?
69432 t(d.id + '.tooltip', {action: d.annotation()}) :
69433 t(d.id + '.nothing'), d.cmd);
69436 var buttons = selection$$1.selectAll('button')
69440 .attr('class', function(d) { return 'col6 disabled ' + d.id + '-button'; })
69441 .on('click', function(d) { return d.action(); })
69442 .call(tooltipBehavior);
69444 buttons.each(function(d) {
69445 var iconName = d.id;
69446 if (textDirection === 'rtl') {
69447 if (iconName === 'undo') {
69449 } else if (iconName === 'redo') {
69454 .call(svgIcon('#icon-' + iconName));
69457 var keybinding = d3keybinding('undo')
69458 .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
69459 .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
69465 .on('change.undo_redo', update);
69468 .on('enter.undo_redo', update);
69470 function update() {
69472 .property('disabled', saving())
69473 .classed('disabled', function(d) { return !d.annotation(); })
69475 var selection$$1 = select(this);
69476 if (selection$$1.property('tooltipVisible')) {
69477 selection$$1.call(tooltipBehavior.show);
69484 // these are module variables so they are preserved through a ui.restart()
69485 var sawVersion = null;
69486 var isNewVersion = false;
69487 var isNewUser = false;
69490 function uiVersion(context) {
69492 var currVersion = context.version,
69493 matchedVersion = currVersion.match(/\d\.\d\.\d.*/);
69495 if (sawVersion === null && matchedVersion !== null) {
69496 isNewVersion = (context.storage('sawVersion') !== currVersion);
69497 isNewUser = !context.storage('sawSplash');
69498 context.storage('sawVersion', currVersion);
69499 sawVersion = currVersion;
69502 return function(selection) {
69505 .attr('target', '_blank')
69506 .attr('tabindex', -1)
69507 .attr('href', 'https://github.com/openstreetmap/iD')
69508 .text(currVersion);
69510 // only show new version indicator to users that have used iD before
69511 if (isNewVersion && !isNewUser) {
69514 .attr('class', 'badge')
69516 .attr('target', '_blank')
69517 .attr('tabindex', -1)
69518 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CHANGELOG.md#whats-new')
69519 .call(svgIcon('#gift-11'))
69521 .title(t('version.whats_new', { version: currVersion }))
69528 function uiZoom(context) {
69532 title: t('zoom.in'),
69533 action: context.zoomIn,
69538 title: t('zoom.out'),
69539 action: context.zoomOut,
69544 function zoomIn() {
69545 event.preventDefault();
69550 function zoomOut() {
69551 event.preventDefault();
69556 function zoomInFurther() {
69557 event.preventDefault();
69558 context.zoomInFurther();
69562 function zoomOutFurther() {
69563 event.preventDefault();
69564 context.zoomOutFurther();
69568 return function(selection$$1) {
69569 var button = selection$$1.selectAll('button')
69573 .attr('tabindex', -1)
69574 .attr('class', function(d) { return d.id; })
69575 .on('click.editor', function(d) { d.action(); })
69577 .placement((textDirection === 'rtl') ? 'right' : 'left')
69579 .title(function(d) {
69580 return uiTooltipHtml(d.title, d.key);
69584 button.each(function(d) {
69586 .call(svgIcon('#icon-' + d.icon, 'light'));
69589 var keybinding = d3keybinding('zoom');
69591 lodash.each(['=','ffequals','plus','ffplus'], function(key) {
69592 keybinding.on([key, '⇧' + key], zoomIn);
69593 keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomInFurther);
69595 lodash.each(['-','ffminus','dash'], function(key) {
69596 keybinding.on([key, '⇧' + key], zoomOut);
69597 keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomOutFurther);
69605 function uiInit(context) {
69606 var uiInitCounter = 0;
69609 function render(container) {
69611 .attr('dir', textDirection);
69613 var map$$1 = context.map();
69615 var hash = behaviorHash(context);
69618 if (!hash.hadHash) {
69619 map$$1.centerZoom([0, 0], 2);
69624 .attr('id', 'defs')
69625 .call(svgDefs(context));
69629 .attr('id', 'sidebar')
69630 .attr('class', 'col4')
69633 var content = container
69635 .attr('id', 'content')
69636 .attr('class', 'active');
69641 .attr('class', 'fillD');
69646 .attr('dir', 'ltr')
69650 .call(uiMapInMap(context));
69654 .call(uiInfo(context));
69658 .attr('class', 'spacer col4');
69660 var limiter = bar.append('div')
69661 .attr('class', 'limiter');
69665 .attr('class', 'button-wrap joined col3')
69666 .call(uiModes(context), limiter);
69670 .attr('class', 'button-wrap joined col1')
69671 .call(uiUndoRedo(context));
69675 .attr('class', 'button-wrap col1')
69676 .call(uiSave(context));
69680 .attr('class', 'full-screen')
69681 .call(uiFullScreen(context));
69685 .attr('class', 'spinner')
69686 .call(uiSpinner(context));
69691 .attr('class', 'map-controls');
69695 .attr('class', 'map-control zoombuttons')
69696 .call(uiZoom(context));
69700 .attr('class', 'map-control geolocate-control')
69701 .call(uiGeolocate(context));
69705 .attr('class', 'map-control background-control')
69706 .call(uiBackground(context));
69710 .attr('class', 'map-control map-data-control')
69711 .call(uiMapData(context));
69715 .attr('class', 'map-control help-control')
69716 .call(uiHelp(context));
69719 var about = content
69721 .attr('id', 'about');
69725 .attr('id', 'attrib')
69726 .attr('dir', 'ltr')
69727 .call(uiAttribution(context));
69731 .attr('class', 'api-status')
69732 .call(uiStatus(context));
69737 .attr('id', 'footer')
69738 .attr('class', 'fillD');
69742 .attr('id', 'flash-wrap')
69743 .attr('class', 'footer-hide');
69745 var footerWrap = footer
69747 .attr('id', 'footer-wrap')
69748 .attr('class', 'footer-show');
69752 .attr('id', 'scale-block')
69753 .call(uiScale(context));
69755 var aboutList = footerWrap
69757 .attr('id', 'info-block')
69759 .attr('id', 'about-list');
69761 if (!context.embed()) {
69763 .call(uiAccount(context));
69768 .attr('class', 'version')
69769 .call(uiVersion(context));
69771 var issueLinks = aboutList
69776 .attr('target', '_blank')
69777 .attr('tabindex', -1)
69778 .attr('href', 'https://github.com/openstreetmap/iD/issues')
69779 .call(svgIcon('#icon-bug', 'light'))
69780 .call(tooltip().title(t('report_a_bug')).placement('top'));
69784 .attr('target', '_blank')
69785 .attr('tabindex', -1)
69786 .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
69787 .call(svgIcon('#icon-translate', 'light'))
69788 .call(tooltip().title(t('help_translate')).placement('top'));
69792 .attr('class', 'feature-warning')
69793 .attr('tabindex', -1)
69794 .call(uiFeatureInfo(context));
69798 .attr('class', 'user-list')
69799 .attr('tabindex', -1)
69800 .call(uiContributors(context));
69803 window.onbeforeunload = function() {
69804 return context.save();
69807 window.onunload = function() {
69808 context.history().unlock();
69811 var mapDimensions = map$$1.dimensions();
69814 function onResize() {
69815 mapDimensions = utilGetDimensions(content, true);
69816 map$$1.dimensions(mapDimensions);
69820 .on('resize.editor', onResize);
69825 return function() {
69826 event.preventDefault();
69827 context.pan(d, 100);
69835 var keybinding = d3keybinding('main')
69836 .on('⌫', function() { event.preventDefault(); })
69837 .on('←', pan([pa, 0]))
69838 .on('↑', pan([0, pa]))
69839 .on('→', pan([-pa, 0]))
69840 .on('↓', pan([0, -pa]))
69841 .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
69842 .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
69843 .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
69844 .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
69849 context.enter(modeBrowse(context));
69851 if (!uiInitCounter++) {
69852 context.container()
69853 .call(uiSplash(context))
69854 .call(uiRestore(context));
69857 var authenticating = uiLoading(context)
69858 .message(t('loading_auth'))
69861 context.connection()
69862 .on('authLoading.ui', function() {
69863 context.container()
69864 .call(authenticating);
69866 .on('authDone.ui', function() {
69867 authenticating.close();
69874 var renderCallback;
69876 function ui(node, callback) {
69877 renderCallback = callback;
69878 var container = select(node);
69879 context.container(container);
69880 context.loadLocale(function(err) {
69891 ui.restart = function(arg) {
69892 context.locale(arg);
69893 context.loadLocale(function(err) {
69895 context.container().selectAll('*').remove();
69896 render(context.container());
69897 if (renderCallback) renderCallback();
69903 ui.sidebar = uiSidebar(context);
69909 var readOnlyTags = ['created_by', 'imagery_used', 'host', 'locale'];
69912 function uiCommit(context) {
69913 var dispatch$$1 = dispatch('cancel', 'save');
69916 function commit(selection$$1) {
69918 var detected = utilDetect(),
69920 created_by: ('iD ' + context.version).substr(0, 255),
69921 imagery_used: context.history().imageryUsed().join(';').substr(0, 255),
69922 host: detected.host.substr(0, 255),
69923 locale: detected.locale.substr(0, 255)
69926 changeset = new osmChangeset({ tags: tags });
69930 var changes = context.history().changes(),
69931 summary = context.history().difference().summary(),
69932 rawTagEditor = uiRawTagEditor(context).on('change', changeTags),
69933 comment = context.storage('comment') || '',
69934 commentDate = +context.storage('commentDate') || 0,
69935 currDate = Date.now(),
69936 cutoff = 2 * 86400 * 1000; // 2 days
69938 // expire the stored comment if it is too old - #3947
69939 if (commentDate > currDate || currDate - commentDate > cutoff) {
69945 .attr('class', 'header fillL')
69947 .text(t('commit.title'));
69949 var body = selection$$1
69951 .attr('class', 'body');
69953 var commentSection = body
69955 .attr('class', 'modal-section form-field commit-form');
69959 .attr('class', 'form-label')
69960 .text(t('commit.message_label'));
69962 var commentField = commentSection
69963 .append('textarea')
69964 .attr('class', 'commit-form-comment')
69965 .attr('placeholder', t('commit.description_placeholder'))
69966 .attr('maxlength', 255)
69967 .property('value', comment)
69968 .on('input.save', change(true))
69969 .on('change.save', change())
69970 .on('blur.save', function() {
69971 context.storage('comment', this.value);
69972 context.storage('commentDate', Date.now());
69976 commentField.node().select();
69978 context.connection().userChangesets(function (err, changesets) {
69981 var comments = changesets.map(function(changeset) {
69983 title: changeset.tags.comment,
69984 value: changeset.tags.comment
69990 .container(context.container())
69991 .caseSensitive(true)
69992 .data(lodash.uniqBy(comments, 'title'))
69996 var clippyArea = commentSection.append('div')
69997 .attr('class', 'clippy-area');
69999 var changeSetInfo = commentSection.append('div')
70000 .attr('class', 'changeset-info');
70002 changeSetInfo.append('a')
70003 .attr('target', '_blank')
70004 .attr('tabindex', -1)
70005 .call(svgIcon('#icon-out-link', 'inline'))
70006 .attr('href', t('commit.about_changeset_comments_link'))
70008 .text(t('commit.about_changeset_comments'));
70012 var warnings = body.selectAll('div.warning-section')
70013 .data([context.history().validate(changes)]);
70015 warnings = warnings.enter()
70017 .attr('class', 'modal-section warning-section fillL2')
70018 .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
70019 .style('background', '#ffb')
70024 .text(t('commit.warnings'));
70028 .attr('class', 'changeset-list');
70030 var warningLi = warnings.select('ul').selectAll('li')
70031 .data(function(d) { return d; });
70033 warningLi = warningLi.enter()
70035 .on('mouseover', mouseover)
70036 .on('mouseout', mouseout)
70037 .on('click', warningClick)
70041 .call(svgIcon('#icon-alert', 'pre-text'));
70045 .text(function(d) { return d.message; });
70047 warningLi.filter(function(d) { return d.tooltip; })
70049 .title(function(d) { return d.tooltip; })
70054 // Upload Explanation
70055 var saveSection = body
70057 .attr('class','modal-section save-section fillL cf');
70059 var prose = saveSection
70061 .attr('class', 'commit-info')
70062 .html(t('commit.upload_explanation'));
70065 context.connection().userDetails(function(err, user) {
70068 var userLink = select(document.createElement('div'));
70070 if (user.image_url) {
70073 .attr('src', user.image_url)
70074 .attr('class', 'icon pre-text user-icon');
70079 .attr('class','user-info')
70080 .text(user.display_name)
70081 .attr('href', context.connection().userURL(user.display_name))
70082 .attr('tabindex', -1)
70083 .attr('target', '_blank');
70086 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
70091 var buttonSection = saveSection
70093 .attr('class', 'buttons fillL cf');
70095 var cancelButton = buttonSection
70097 .attr('class', 'secondary-action col5 button cancel-button')
70098 .on('click.cancel', function() {
70099 dispatch$$1.call('cancel');
70104 .attr('class', 'label')
70105 .text(t('commit.cancel'));
70107 var saveButton = buttonSection
70109 .attr('class', 'action col5 button save-button')
70110 .attr('disabled', function() {
70111 var n = select('.commit-form textarea').node();
70112 return (n && n.value.length) ? null : true;
70114 .on('click.save', function() {
70115 dispatch$$1.call('save', this, changeset);
70120 .attr('class', 'label')
70121 .text(t('commit.save'));
70125 var tagSection = body
70127 .attr('class', 'modal-section tag-section raw-tag-editor');
70131 var changeSection = body
70133 .attr('class', 'commit-section modal-section fillL2');
70135 changeSection.append('h3')
70136 .text(t('commit.changes', { count: summary.length }));
70138 var li = changeSection
70140 .attr('class', 'changeset-list')
70146 .on('mouseover', mouseover)
70147 .on('mouseout', mouseout)
70148 .on('click', zoomToEntity)
70151 li.each(function(d) {
70153 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
70157 .attr('class', 'change-type')
70158 .text(function(d) { return t('commit.' + d.changeType) + ' '; });
70160 li.append('strong')
70161 .attr('class', 'entity-type')
70162 .text(function(d) {
70163 var matched = context.presets().match(d.entity, d.graph);
70164 return (matched && matched.name()) || utilDisplayType(d.entity.id);
70168 .attr('class', 'entity-name')
70169 .text(function(d) {
70170 var name = utilDisplayName(d.entity) || '',
70172 if (name !== '') string += ':';
70173 return string += ' ' + name;
70176 li.style('opacity', 0)
70178 .style('opacity', 1);
70181 // Call change() off the bat, in case a changeset
70182 // comment is recovered from localStorage
70183 utilTriggerEvent(commentField, 'input');
70186 function mouseover(d) {
70188 context.surface().selectAll(
70189 utilEntityOrMemberSelector([d.entity.id], context.graph())
70190 ).classed('hover', true);
70195 function mouseout() {
70196 context.surface().selectAll('.hover')
70197 .classed('hover', false);
70201 function warningClick(d) {
70203 context.map().zoomTo(d.entity);
70204 context.enter(modeSelect(context, [d.entity.id]));
70209 function zoomToEntity(change) {
70210 var entity = change.entity;
70211 if (change.changeType !== 'deleted' &&
70212 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
70213 context.map().zoomTo(entity);
70214 context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph()))
70215 .classed('hover', true);
70220 function checkComment(comment) {
70221 // Save button disabled if there is no comment..
70222 selectAll('.save-section .save-button')
70223 .attr('disabled', (comment.length ? null : true));
70225 // Warn if comment mentions Google..
70226 var googleWarning = clippyArea
70229 .data(comment.match(/google/i) ? [true] : []);
70231 googleWarning.exit()
70234 googleWarning.enter()
70236 .attr('target', '_blank')
70237 .attr('tabindex', -1)
70238 .call(svgIcon('#icon-alert', 'inline'))
70239 .attr('href', t('commit.google_warning_link'))
70241 .text(t('commit.google_warning'));
70245 function change(onInput) {
70246 return function() {
70247 var comment = commentField.property('value').trim();
70249 commentField.property('value', comment);
70252 checkComment(comment);
70254 var changeset = updateChangeset({ comment: comment });
70255 var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty();
70259 .expanded(expanded)
70260 .readOnlyTags(readOnlyTags)
70261 .tags(lodash.clone(changeset.tags))
70267 function changeTags(changed) {
70268 if (changed.hasOwnProperty('comment')) {
70269 if (changed.comment === undefined) {
70270 changed.comment = '';
70272 changed.comment = changed.comment.trim();
70273 commentField.property('value', changed.comment);
70275 updateChangeset(changed);
70276 utilTriggerEvent(commentField, 'input');
70280 function updateChangeset(changed) {
70281 var tags = lodash.clone(changeset.tags);
70283 lodash.forEach(changed, function(v, k) {
70284 k = k.trim().substr(0, 255);
70285 if (readOnlyTags.indexOf(k) !== -1) return;
70287 if (k !== '' && v !== undefined) {
70288 tags[k] = v.trim().substr(0, 255);
70294 if (!lodash.isEqual(changeset.tags, tags)) {
70295 changeset = changeset.update({ tags: tags });
70304 commit.reset = function() {
70309 return utilRebind(commit, dispatch$$1, 'on');
70312 function uiConfirm(selection) {
70313 var modalSelection = uiModal(selection);
70315 modalSelection.select('.modal')
70316 .classed('modal-alert', true);
70318 var section = modalSelection.select('.content');
70320 section.append('div')
70321 .attr('class', 'modal-section header');
70323 section.append('div')
70324 .attr('class', 'modal-section message-text');
70326 var buttons = section.append('div')
70327 .attr('class', 'modal-section buttons cf');
70330 modalSelection.okButton = function() {
70333 .attr('class', 'action col4')
70334 .on('click.confirm', function() {
70335 modalSelection.remove();
70337 .text(t('confirm.okay'));
70339 return modalSelection;
70343 return modalSelection;
70346 function uiConflicts(context) {
70347 var dispatch$$1 = dispatch('download', 'cancel', 'save'),
70351 function conflicts(selection$$1) {
70352 var header = selection$$1
70354 .attr('class', 'header fillL');
70358 .attr('class', 'fr')
70359 .on('click', function() { dispatch$$1.call('cancel'); })
70360 .call(svgIcon('#icon-close'));
70364 .text(t('save.conflict.header'));
70366 var body = selection$$1
70368 .attr('class', 'body fillL');
70372 .attr('class', 'conflicts-help')
70373 .text(t('save.conflict.help'))
70375 .attr('class', 'conflicts-download')
70376 .text(t('save.conflict.download_changes'))
70377 .on('click.download', function() { dispatch$$1.call('download'); });
70381 .attr('class', 'conflict-container fillL3')
70382 .call(showConflict, 0);
70386 .attr('class', 'conflicts-done')
70387 .attr('opacity', 0)
70388 .style('display', 'none')
70389 .text(t('save.conflict.done'));
70393 .attr('class','buttons col12 joined conflicts-buttons');
70397 .attr('disabled', list.length > 1)
70398 .attr('class', 'action conflicts-button col6')
70399 .text(t('save.title'))
70400 .on('click.try_again', function() { dispatch$$1.call('save'); });
70404 .attr('class', 'secondary-action conflicts-button col6')
70405 .text(t('confirm.cancel'))
70406 .on('click.cancel', function() { dispatch$$1.call('cancel'); });
70410 function showConflict(selection$$1, index) {
70411 if (index < 0 || index >= list.length) return;
70413 var parent = select(selection$$1.node().parentNode);
70415 // enable save button if this is the last conflict being reviewed..
70416 if (index === list.length - 1) {
70417 window.setTimeout(function() {
70418 parent.select('.conflicts-button')
70419 .attr('disabled', null);
70421 parent.select('.conflicts-done')
70423 .attr('opacity', 1)
70424 .style('display', 'block');
70428 var item = selection$$1
70429 .selectAll('.conflict')
70430 .data([list[index]]);
70432 var enter = item.enter()
70434 .attr('class', 'conflict');
70438 .attr('class', 'conflict-count')
70439 .text(t('save.conflict.count', { num: index + 1, total: list.length }));
70443 .attr('class', 'conflict-description')
70445 .text(function(d) { return d.name; })
70446 .on('click', function(d) {
70447 zoomToEntity(d.id);
70448 event.preventDefault();
70451 var details = enter
70453 .attr('class', 'conflict-detail-container');
70457 .attr('class', 'conflict-detail-list')
70459 .data(function(d) { return d.details || []; })
70462 .attr('class', 'conflict-detail-item')
70463 .html(function(d) { return d; });
70467 .attr('class', 'conflict-choices')
70472 .attr('class', 'conflict-nav-buttons joined cf')
70473 .selectAll('button')
70474 .data(['previous', 'next'])
70477 .text(function(d) { return t('save.conflict.' + d); })
70478 .attr('class', 'conflict-nav-button action col6')
70479 .attr('disabled', function(d, i) {
70480 return (i === 0 && index === 0) ||
70481 (i === 1 && index === list.length - 1) || null;
70483 .on('click', function(d, i) {
70484 var container = parent.select('.conflict-container'),
70485 sign = (i === 0 ? -1 : 1);
70488 .selectAll('.conflict')
70492 .call(showConflict, index + sign);
70494 event.preventDefault();
70502 function addChoices(selection$$1) {
70503 var choices = selection$$1
70505 .attr('class', 'layer-list')
70507 .data(function(d) { return d.choices || []; });
70509 var enter = choices.enter()
70511 .attr('class', 'layer');
70518 .attr('type', 'radio')
70519 .attr('name', function(d) { return d.id; })
70520 .on('change', function(d, i) {
70521 var ul = this.parentNode.parentNode.parentNode;
70522 ul.__data__.chosen = i;
70528 .text(function(d) { return d.text; });
70531 .each(function(d, i) {
70532 var ul = this.parentNode;
70533 if (ul.__data__.chosen === i) choose(ul, d);
70538 function choose(ul, datum) {
70539 if (event) event.preventDefault();
70543 .classed('active', function(d) { return d === datum; })
70544 .selectAll('input')
70545 .property('checked', function(d) { return d === datum; });
70547 var extent$$1 = geoExtent$$1(),
70550 entity = context.graph().hasEntity(datum.id);
70551 if (entity) extent$$1._extend(entity.extent(context.graph()));
70555 entity = context.graph().hasEntity(datum.id);
70556 if (entity) extent$$1._extend(entity.extent(context.graph()));
70558 zoomToEntity(datum.id, extent$$1);
70562 function zoomToEntity(id, extent$$1) {
70563 context.surface().selectAll('.hover')
70564 .classed('hover', false);
70566 var entity = context.graph().hasEntity(id);
70569 context.map().trimmedExtent(extent$$1);
70571 context.map().zoomTo(entity);
70573 context.surface().selectAll(
70574 utilEntityOrMemberSelector([entity.id], context.graph()))
70575 .classed('hover', true);
70580 // The conflict list should be an array of objects like:
70583 // name: entityName(local),
70584 // details: merge.conflicts(),
70587 // choice(id, keepMine, forceLocal),
70588 // choice(id, keepTheirs, forceRemote)
70591 conflicts.list = function(_) {
70592 if (!arguments.length) return list;
70598 return utilRebind(conflicts, dispatch$$1, 'on');
70601 function uiEditMenu(context, operations) {
70607 var p = 8, // top padding
70608 m = 4, // top margin
70609 h = 15, // height of icon
70610 vpBottomMargin = 45, // viewport bottom margin
70611 vpSideMargin = 35, // viewport side margin
70613 buttonHeight = (2 * p + h),
70614 menuWidth = buttonWidth,
70615 menuHeight = (2 * m) + operations.length * buttonHeight,
70616 menuSideMargin = 10,
70617 tooltipWidth = 200,
70618 tooltipHeight = 200; // a reasonable guess, real height depends on tooltip contents
70621 var editMenu = function (selection$$1) {
70622 if (!operations.length) return;
70624 selection$$1.node().parentNode.focus();
70626 var isRTL = textDirection === 'rtl',
70627 viewport = context.surfaceRect();
70629 if (!isRTL && (center[0] + menuSideMargin + menuWidth) > (viewport.width - vpSideMargin)) {
70630 // menu is going left-to-right and near right viewport edge, go left instead
70632 } else if (isRTL && (center[0] - menuSideMargin - menuWidth) < vpSideMargin) {
70633 // menu is going right-to-left and near left viewport edge, go right instead
70637 offset[0] = (isRTL ? -1 * (menuSideMargin + menuWidth) : menuSideMargin);
70639 if (center[1] + menuHeight > (viewport.height - vpBottomMargin)) {
70640 // menu is near bottom viewport edge, shift upwards
70641 offset[1] = -1 * (center[1] + menuHeight - viewport.height + vpBottomMargin);
70644 var origin = [ center[0] + offset[0], center[1] + offset[1] ];
70646 menu = selection$$1
70648 .attr('class', 'edit-menu')
70649 .attr('transform', 'translate(' + origin + ')')
70650 .attr('opacity', 0);
70654 .attr('opacity', 1);
70658 .attr('class', 'edit-menu-background')
70662 .attr('width', menuWidth)
70663 .attr('height', menuHeight)
70664 .attr('stroke-linecap', 'round');
70667 var button = menu.selectAll('.edit-menu-item')
70671 .attr('class', function (d) { return 'edit-menu-item edit-menu-item-' + d.id; })
70672 .classed('disabled', function (d) { return d.disabled(); })
70673 .attr('transform', function (d, i) {
70674 return 'translate(' + geoRoundCoords([
70676 m + i * buttonHeight
70677 ]).join(',') + ')';
70683 .attr('width', buttonWidth)
70684 .attr('height', buttonHeight)
70685 .on('click', click)
70686 .on('mousedown', mousedown)
70687 .on('mouseover', mouseover)
70688 .on('mouseout', mouseout);
70692 .attr('width', '20')
70693 .attr('height', '20')
70694 .attr('transform', function () {
70695 return 'translate(' + [2 * p, 5] + ')';
70697 .attr('xlink:href', function (d) { return '#operation-' + d.id; });
70699 tooltip = select(document.body)
70701 .attr('class', 'tooltip-inner edit-menu-tooltip');
70704 function click(operation) {
70705 event.stopPropagation();
70706 if (operation.disabled()) return;
70711 function mousedown() {
70712 event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
70715 function mouseover(d, i) {
70719 tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
70721 tipX = viewport.left + origin[0] - 4 - tooltipWidth;
70724 if (tipX + tooltipWidth > viewport.right) {
70725 // tip is going left-to-right and near right viewport edge, go left instead
70726 tipX = viewport.left + origin[0] - 4 - tooltipWidth;
70727 } else if (tipX < viewport.left) {
70728 // tip is going right-to-left and near left viewport edge, go right instead
70729 tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
70732 tipY = viewport.top + origin[1] + (i * buttonHeight);
70733 if (tipY + tooltipHeight > viewport.bottom) {
70734 // tip is near bottom viewport edge, shift upwards
70735 tipY -= tipY + tooltipHeight - viewport.bottom;
70739 .style('left', tipX + 'px')
70740 .style('top', tipY + 'px')
70741 .style('display', 'block')
70742 .html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title));
70745 function mouseout() {
70746 tooltip.style('display', 'none');
70751 editMenu.close = function () {
70754 .style('pointer-events', 'none')
70756 .attr('opacity', 0)
70766 editMenu.center = function (_) {
70767 if (!arguments.length) return center;
70778 function uiFlash(showDuration) {
70779 showDuration = showDuration || 1500;
70785 select('#footer-wrap')
70786 .attr('class', 'footer-hide');
70787 select('#flash-wrap')
70788 .attr('class', 'footer-show');
70790 var content = select('#flash-wrap').selectAll('.content')
70793 content = content.enter()
70795 .attr('class', 'content')
70798 timer$1 = timeout$1(function() {
70800 select('#footer-wrap')
70801 .attr('class', 'footer-show');
70802 select('#flash-wrap')
70803 .attr('class', 'footer-hide');
70810 function uiLasso(context) {
70811 var group, polygon;
70813 lasso.coordinates = [];
70815 function lasso(selection$$1) {
70816 context.container()
70817 .classed('lasso', true);
70819 group = selection$$1
70821 .attr('class', 'lasso hide');
70825 .attr('class', 'lasso-path');
70828 .call(uiToggle(true));
70834 polygon.data([lasso.coordinates])
70835 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
70840 lasso.extent = function () {
70841 return lasso.coordinates.reduce(function(extent$$1, point) {
70842 return extent$$1.extend(geoExtent$$1(point));
70843 }, geoExtent$$1());
70847 lasso.p = function(_) {
70848 if (!arguments.length) return lasso;
70849 lasso.coordinates.push(_);
70855 lasso.close = function() {
70857 group.call(uiToggle(false, function() {
70858 select(this).remove();
70861 context.container().classed('lasso', false);
70868 function uiRadialMenu(context, operations) {
70874 var radialMenu = function(selection$$1) {
70875 if (!operations.length) return;
70877 selection$$1.node().parentNode.focus();
70879 function click(operation) {
70880 event.stopPropagation();
70881 if (operation.disabled()) return;
70883 radialMenu.close();
70886 menu = selection$$1
70888 .attr('class', 'radial-menu')
70889 .attr('transform', 'translate(' + center + ')')
70890 .attr('opacity', 0);
70894 .attr('opacity', 1);
70899 a1 = a0 + (operations.length - 1) * a;
70903 .attr('class', 'radial-menu-background')
70904 .attr('d', 'M' + r * Math.sin(a0) + ',' +
70906 ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
70907 (r * Math.sin(a1) + 1e-3) + ',' +
70908 (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
70909 .attr('stroke-width', 50)
70910 .attr('stroke-linecap', 'round');
70912 var button = menu.selectAll()
70916 .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
70917 .classed('disabled', function(d) { return d.disabled(); })
70918 .attr('transform', function(d, i) {
70919 return 'translate(' + geoRoundCoords([
70920 r * Math.sin(a0 + i * a),
70921 r * Math.cos(a0 + i * a)]).join(',') + ')';
70927 .on('click', click)
70928 .on('mousedown', mousedown)
70929 .on('mouseover', mouseover)
70930 .on('mouseout', mouseout);
70934 .attr('transform', 'translate(-10,-10)')
70935 .attr('width', '20')
70936 .attr('height', '20')
70937 .attr('xlink:href', function(d) { return '#operation-' + d.id; });
70939 tooltip = select(document.body)
70941 .attr('class', 'tooltip-inner radial-menu-tooltip');
70943 function mousedown() {
70944 event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
70947 function mouseover(d, i) {
70948 var rect = context.surfaceRect(),
70949 angle = a0 + i * a,
70950 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
70951 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
70952 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
70953 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
70956 .style('top', null)
70957 .style('left', null)
70958 .style('bottom', null)
70959 .style('right', null)
70960 .style('display', 'block')
70961 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
70965 .style('right', right)
70966 .style('top', top);
70967 } else if (i >= 4) {
70969 .style('left', left)
70970 .style('bottom', bottom);
70973 .style('left', left)
70974 .style('top', top);
70978 function mouseout() {
70979 tooltip.style('display', 'none');
70984 radialMenu.close = function() {
70987 .style('pointer-events', 'none')
70989 .attr('opacity', 0)
70999 radialMenu.center = function(_) {
71000 if (!arguments.length) return center;
71009 function uiSelectionList(context, selectedIDs) {
71011 function selectEntity(entity) {
71012 context.enter(modeSelect(context, [entity.id]));
71016 function deselectEntity(entity) {
71017 event.stopPropagation();
71018 var index = selectedIDs.indexOf(entity.id);
71020 selectedIDs.splice(index, 1);
71022 context.enter(modeSelect(context, selectedIDs));
71026 function selectionList(selection$$1) {
71027 selection$$1.classed('selection-list-pane', true);
71029 var header = selection$$1
71031 .attr('class', 'header fillL cf');
71035 .text(t('inspector.multiselect'));
71037 var listWrap = selection$$1
71039 .attr('class', 'inspector-body');
71041 var list = listWrap
71043 .attr('class', 'feature-list cf');
71045 context.history().on('change.selection-list', drawList);
71049 function drawList() {
71050 var entities = selectedIDs
71051 .map(function(id) { return context.hasEntity(id); })
71052 .filter(function(entity) { return entity; });
71054 var items = list.selectAll('.feature-list-item')
71055 .data(entities, osmEntity$$1.key);
71061 var enter = items.enter()
71063 .attr('class', 'feature-list-item')
71064 .on('click', selectEntity);
71068 .attr('class', 'label');
71072 .attr('class', 'close')
71073 .on('click', deselectEntity)
71074 .call(svgIcon('#icon-close'));
71078 .attr('class', 'entity-geom-icon')
71079 .call(svgIcon('', 'pre-text'));
71083 .attr('class', 'entity-type');
71087 .attr('class', 'entity-name');
71090 items = items.merge(enter);
71092 items.selectAll('.entity-geom-icon use')
71093 .attr('href', function() {
71094 var entity = this.parentNode.parentNode.__data__;
71095 return '#icon-' + context.geometry(entity.id);
71098 items.selectAll('.entity-type')
71099 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
71101 items.selectAll('.entity-name')
71102 .text(function(entity) { return utilDisplayName(entity); });
71106 return selectionList;
71109 function uiSourceSwitch(context) {
71114 event.preventDefault();
71116 if (context.history().hasChanges() &&
71117 !window.confirm(t('source_switch.lose_changes'))) return;
71119 var live = select(this)
71122 context.connection()
71123 .switch(live ? keys$$1[1] : keys$$1[0]);
71125 context.enter(modeBrowse(context));
71129 .text(live ? t('source_switch.dev') : t('source_switch.live'))
71130 .classed('live', !live);
71133 var sourceSwitch = function(selection$$1) {
71137 .text(t('source_switch.live'))
71138 .classed('live', true)
71139 .attr('tabindex', -1)
71140 .on('click', click);
71144 sourceSwitch.keys = function(_) {
71145 if (!arguments.length) return keys$$1;
71147 return sourceSwitch;
71151 return sourceSwitch;
71154 function uiSuccess(context) {
71155 var dispatch$$1 = dispatch('cancel'),
71159 function success(selection$$1) {
71160 var header = selection$$1
71162 .attr('class', 'header fillL');
71166 .attr('class', 'fr')
71167 .on('click', function() { dispatch$$1.call('cancel'); })
71168 .call(svgIcon('#icon-close'));
71172 .text(t('success.just_edited'));
71174 var body = selection$$1
71176 .attr('class', 'body save-success fillL');
71180 .html(t('success.help_html'));
71184 .attr('class', 'details')
71185 .attr('target', '_blank')
71186 .attr('tabindex', -1)
71187 .call(svgIcon('#icon-out-link', 'inline'))
71188 .attr('href', t('success.help_link_url'))
71190 .text(t('success.help_link_text'));
71192 var changesetURL = context.connection().changesetURL(changeset.id);
71195 var viewOnOsm = body
71197 .attr('class', 'button col12 osm')
71198 .attr('target', '_blank')
71199 .attr('href', changesetURL);
71203 .attr('class', 'logo logo-osm')
71205 .attr('xlink:href', '#logo-osm');
71209 .text(t('success.view_on_osm'));
71212 var message = (changeset.tags.comment || t('success.edited_osm')).substring(0, 130) +
71213 ' ' + context.connection().changesetURL(changeset.id);
71216 facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
71217 twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
71218 google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
71221 body.selectAll('.button.social')
71222 .data(entries(sharing))
71225 .attr('class', 'button social col4')
71226 .attr('target', '_blank')
71227 .attr('href', function(d) { return d.value; })
71229 .title(function(d) { return t('success.' + d.key); })
71230 .placement('bottom'))
71231 .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
71235 success.changeset = function(_) {
71236 if (!arguments.length) return changeset;
71242 return utilRebind(success, dispatch$$1, 'on');
71245 function coreHistory(context) {
71246 var imageryUsed = ['Bing'],
71247 dispatch$$1 = dispatch('change', 'undone', 'redone'),
71248 lock = utilSessionMutex('lock'),
71251 stack$$1, index, tree$$1;
71254 // internal _act, accepts list of actions and eased time
71255 function _act(actions, t) {
71256 actions = Array.prototype.slice.call(actions);
71260 if (!lodash.isFunction(lodash.last(actions))) {
71261 annotation = actions.pop();
71264 stack$$1[index].transform = context.projection.transform();
71265 stack$$1[index].selectedIDs = context.selectedIDs();
71267 var graph = stack$$1[index].graph;
71268 for (var i = 0; i < actions.length; i++) {
71269 graph = actions[i](graph, t);
71274 annotation: annotation,
71275 imageryUsed: imageryUsed
71280 // internal _perform with eased time
71281 function _perform(args, t) {
71282 var previous = stack$$1[index].graph;
71283 stack$$1 = stack$$1.slice(0, index + 1);
71284 stack$$1.push(_act(args, t));
71286 return change(previous);
71290 // internal _replace with eased time
71291 function _replace(args, t) {
71292 var previous = stack$$1[index].graph;
71293 // assert(index == stack.length - 1)
71294 stack$$1[index] = _act(args, t);
71295 return change(previous);
71299 // internal _overwrite with eased time
71300 function _overwrite(args, t) {
71301 var previous = stack$$1[index].graph;
71306 stack$$1 = stack$$1.slice(0, index + 1);
71307 stack$$1.push(_act(args, t));
71309 return change(previous);
71313 // determine diffrence and dispatch a change event
71314 function change(previous) {
71315 var difference = coreDifference(previous, history.graph());
71316 dispatch$$1.call('change', this, difference);
71321 // iD uses namespaced keys so multiple installations do not conflict
71322 function getKey(n) {
71323 return 'iD_' + window.location.origin + '_' + n;
71329 graph: function() {
71330 return stack$$1[index].graph;
71335 return stack$$1[0].graph;
71339 merge: function(entities, extent$$1) {
71340 stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
71341 tree$$1.rebase(entities, false);
71343 dispatch$$1.call('change', this, undefined, extent$$1);
71347 perform: function() {
71348 // complete any transition already in progress
71349 select(document).interrupt('history.perform');
71351 var transitionable = false,
71352 action0 = arguments[0];
71354 if (arguments.length === 1 ||
71355 arguments.length === 2 && !lodash.isFunction(arguments[1])) {
71356 transitionable = !!action0.transitionable;
71359 if (transitionable) {
71360 var origArguments = arguments;
71362 .transition('history.perform')
71363 .duration(duration)
71365 .tween('history.tween', function() {
71366 return function(t) {
71367 if (t < 1) _overwrite([action0], t);
71370 .on('start', function() {
71371 _perform([action0], 0);
71373 .on('end interrupt', function() {
71374 _overwrite(origArguments, 1);
71378 return _perform(arguments);
71383 replace: function() {
71384 select(document).interrupt('history.perform');
71385 return _replace(arguments, 1);
71389 // Same as calling pop and then perform
71390 overwrite: function() {
71391 select(document).interrupt('history.perform');
71392 return _overwrite(arguments, 1);
71397 select(document).interrupt('history.perform');
71399 var previous = stack$$1[index].graph;
71400 if (isNaN(+n) || +n < 0) {
71403 while (n-- > 0 && index > 0) {
71407 return change(previous);
71411 // Back to the previous annotated state or index = 0.
71413 select(document).interrupt('history.perform');
71415 var previous = stack$$1[index].graph;
71416 while (index > 0) {
71418 if (stack$$1[index].annotation) break;
71421 dispatch$$1.call('undone', this, stack$$1[index]);
71422 return change(previous);
71426 // Forward to the next annotated state.
71428 select(document).interrupt('history.perform');
71430 var previous = stack$$1[index].graph;
71431 var tryIndex = index;
71432 while (tryIndex < stack$$1.length - 1) {
71434 if (stack$$1[tryIndex].annotation) {
71436 dispatch$$1.call('redone', this, stack$$1[index]);
71441 return change(previous);
71445 undoAnnotation: function() {
71448 if (stack$$1[i].annotation) return stack$$1[i].annotation;
71454 redoAnnotation: function() {
71456 while (i <= stack$$1.length - 1) {
71457 if (stack$$1[i].annotation) return stack$$1[i].annotation;
71463 intersects: function(extent$$1) {
71464 return tree$$1.intersects(extent$$1, stack$$1[index].graph);
71468 difference: function() {
71469 var base = stack$$1[0].graph,
71470 head = stack$$1[index].graph;
71471 return coreDifference(base, head);
71475 changes: function(action) {
71476 var base = stack$$1[0].graph,
71477 head = stack$$1[index].graph;
71480 head = action(head);
71483 var difference = coreDifference(base, head);
71486 modified: difference.modified(),
71487 created: difference.created(),
71488 deleted: difference.deleted()
71493 validate: function(changes) {
71494 return lodash(Validations)
71495 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
71501 hasChanges: function() {
71502 return this.difference().length() > 0;
71506 imageryUsed: function(sources) {
71508 imageryUsed = sources;
71511 return lodash(stack$$1.slice(1, index + 1))
71512 .map('imageryUsed')
71515 .without(undefined, 'Custom')
71521 // save the current history state
71522 checkpoint: function(key) {
71523 checkpoints[key] = {
71524 stack: lodash.cloneDeep(stack$$1),
71531 // restore history state to a given checkpoint or reset completely
71532 reset: function(key) {
71533 if (key !== undefined && checkpoints.hasOwnProperty(key)) {
71534 stack$$1 = lodash.cloneDeep(checkpoints[key].stack);
71535 index = checkpoints[key].index;
71537 stack$$1 = [{graph: coreGraph$$1()}];
71539 tree$$1 = coreTree(stack$$1[0].graph);
71542 dispatch$$1.call('change');
71547 toIntroGraph: function() {
71548 var nextId = { n: 0, r: 0, w: 0 },
71550 graph = this.graph(),
71553 // clone base entities..
71554 lodash.forEach(graph.base().entities, function(entity) {
71555 var copy = lodash.cloneDeepWith(entity, customizer);
71556 baseEntities[copy.id] = copy;
71559 // replace base entities with head entities..
71560 lodash.forEach(graph.entities, function(entity, id) {
71562 var copy = lodash.cloneDeepWith(entity, customizer);
71563 baseEntities[copy.id] = copy;
71565 delete baseEntities[id];
71569 // swap temporary for permanent ids..
71570 lodash.forEach(baseEntities, function(entity) {
71571 if (Array.isArray(entity.nodes)) {
71572 entity.nodes = entity.nodes.map(function(node) {
71573 return permIds[node] || node;
71576 if (Array.isArray(entity.members)) {
71577 entity.members = entity.members.map(function(member) {
71578 member.id = permIds[member.id] || member.id;
71584 return JSON.stringify({ dataIntroGraph: baseEntities });
71587 function customizer(src) {
71588 var copy = lodash.omit(lodash.cloneDeep(src), ['type', 'user', 'v', 'version', 'visible']);
71589 if (lodash.isEmpty(copy.tags)) {
71593 if (Array.isArray(copy.loc)) {
71594 copy.loc[0] = +copy.loc[0].toFixed(6);
71595 copy.loc[1] = +copy.loc[1].toFixed(6);
71598 var match = src.id.match(/([nrw])-\d*/); // temporary id
71599 if (match !== null) {
71600 var nrw = match[1], permId;
71601 do { permId = nrw + (++nextId[nrw]); }
71602 while (baseEntities.hasOwnProperty(permId));
71604 copy.id = permIds[src.id] = permId;
71611 toJSON: function() {
71612 if (!this.hasChanges()) return;
71614 var allEntities = {},
71616 base = stack$$1[0];
71618 var s = stack$$1.map(function(i) {
71619 var modified = [], deleted = [];
71621 lodash.forEach(i.graph.entities, function(entity, id) {
71623 var key = osmEntity$$1.key(entity);
71624 allEntities[key] = entity;
71625 modified.push(key);
71630 // make sure that the originals of changed or deleted entities get merged
71631 // into the base of the stack after restoring the data from JSON.
71632 if (id in base.graph.entities) {
71633 baseEntities[id] = base.graph.entities[id];
71635 // get originals of parent entities too
71636 lodash.forEach(base.graph._parentWays[id], function(parentId) {
71637 if (parentId in base.graph.entities) {
71638 baseEntities[parentId] = base.graph.entities[parentId];
71645 if (modified.length) x.modified = modified;
71646 if (deleted.length) x.deleted = deleted;
71647 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
71648 if (i.annotation) x.annotation = i.annotation;
71653 return JSON.stringify({
71655 entities: lodash.values(allEntities),
71656 baseEntities: lodash.values(baseEntities),
71658 nextIDs: osmEntity$$1.id.next,
71664 fromJSON: function(json$$1, loadChildNodes) {
71665 var h = JSON.parse(json$$1),
71666 loadComplete = true;
71668 osmEntity$$1.id.next = h.nextIDs;
71671 if (h.version === 2 || h.version === 3) {
71672 var allEntities = {};
71674 h.entities.forEach(function(entity) {
71675 allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
71678 if (h.version === 3) {
71679 // This merges originals for changed entities into the base of
71680 // the stack even if the current stack doesn't have them (for
71681 // example when iD has been restarted in a different region)
71682 var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
71683 stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
71684 tree$$1.rebase(baseEntities, true);
71686 // When we restore a modified way, we also need to fetch any missing
71687 // childnodes that would normally have been downloaded with it.. #2142
71688 if (loadChildNodes) {
71689 var missing = lodash(baseEntities)
71690 .filter({ type: 'way' })
71694 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
71697 if (!lodash.isEmpty(missing)) {
71698 loadComplete = false;
71699 context.redrawEnable(false);
71701 var loading = uiLoading(context).blocking(true);
71702 context.container().call(loading);
71704 var childNodesLoaded = function(err, result) {
71706 var visible = lodash.groupBy(result.data, 'visible');
71707 if (!lodash.isEmpty(visible.true)) {
71708 missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
71709 stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
71710 tree$$1.rebase(visible.true, true);
71713 // fetch older versions of nodes that were deleted..
71714 lodash.each(visible.false, function(entity) {
71715 context.connection()
71716 .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
71720 if (err || lodash.isEmpty(missing)) {
71722 context.redrawEnable(true);
71723 dispatch$$1.call('change');
71727 context.connection().loadMultiple(missing, childNodesLoaded);
71732 stack$$1 = h.stack.map(function(d) {
71733 var entities = {}, entity;
71736 d.modified.forEach(function(key) {
71737 entity = allEntities[key];
71738 entities[entity.id] = entity;
71743 d.deleted.forEach(function(id) {
71744 entities[id] = undefined;
71749 graph: coreGraph$$1(stack$$1[0].graph).load(entities),
71750 annotation: d.annotation,
71751 imageryUsed: d.imageryUsed
71755 } else { // original version
71756 stack$$1 = h.stack.map(function(d) {
71759 for (var i in d.entities) {
71760 var entity = d.entities[i];
71761 entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
71764 d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
71769 if (loadComplete) {
71770 dispatch$$1.call('change');
71778 if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
71783 clearSaved: function() {
71784 context.debouncedSave.cancel();
71785 if (lock.locked()) context.storage(getKey('saved_history'), null);
71791 return lock.lock();
71795 unlock: function() {
71800 // is iD not open in another window and it detects that
71801 // there's a history stored in localStorage that's recoverable?
71802 restorableChanges: function() {
71803 return lock.locked() && !!context.storage(getKey('saved_history'));
71807 // load history from a version stored in localStorage
71808 restore: function() {
71809 if (!lock.locked()) return;
71811 var json$$1 = context.storage(getKey('saved_history'));
71812 if (json$$1) history.fromJSON(json$$1, true);
71823 return utilRebind(history, dispatch$$1, 'on');
71826 function presetCollection(collection) {
71827 var maxSearchResults = 50,
71828 maxSuggestionResults = 10;
71832 collection: collection,
71835 item: function(id) {
71836 return lodash.find(this.collection, function(d) {
71837 return d.id === id;
71842 matchGeometry: function(geometry) {
71843 return presetCollection(this.collection.filter(function(d) {
71844 return d.matchGeometry(geometry);
71849 search: function(value, geometry) {
71850 if (!value) return this;
71852 function leading(a) {
71853 var index = a.indexOf(value);
71854 return index === 0 || a[index - 1] === ' ';
71857 function suggestionName(name) {
71858 var nameArray = name.split(' - ');
71859 if (nameArray.length > 1) {
71860 name = nameArray.slice(0, nameArray.length - 1).join(' - ');
71862 return name.toLowerCase();
71866 value = value.toLowerCase();
71868 var searchable = lodash.filter(this.collection, function(a) {
71869 return a.searchable !== false && a.suggestion !== true;
71871 suggestions = lodash.filter(this.collection, function(a) {
71872 return a.suggestion === true;
71876 // matches value to preset.name
71877 var leading_name = lodash.filter(searchable, function(a) {
71878 return leading(a.name().toLowerCase());
71879 }).sort(function(a, b) {
71881 i = b.originalScore - a.originalScore;
71882 if (i !== 0) return i;
71884 i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
71885 if (i !== 0) return i;
71887 return a.name().length - b.name().length;
71890 // matches value to preset.terms values
71891 var leading_terms = lodash.filter(searchable, function(a) {
71892 return lodash.some(a.terms() || [], leading);
71895 // matches value to preset.tags values
71896 var leading_tag_values = lodash.filter(searchable, function(a) {
71897 return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
71901 // finds close matches to value in preset.name
71902 var similar_name = searchable.map(function(a) {
71905 dist: utilEditDistance(value, a.name())
71907 }).filter(function(a) {
71908 return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
71909 }).sort(function(a, b) {
71910 return a.dist - b.dist;
71911 }).map(function(a) {
71915 // finds close matches to value in preset.terms
71916 var similar_terms = lodash.filter(searchable, function(a) {
71917 return lodash.some(a.terms() || [], function(b) {
71918 return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
71922 var leading_suggestions = lodash.filter(suggestions, function(a) {
71923 return leading(suggestionName(a.name()));
71924 }).sort(function(a, b) {
71925 a = suggestionName(a.name());
71926 b = suggestionName(b.name());
71927 var i = a.indexOf(value) - b.indexOf(value);
71928 if (i === 0) return a.length - b.length;
71932 var similar_suggestions = suggestions.map(function(a) {
71935 dist: utilEditDistance(value, suggestionName(a.name()))
71937 }).filter(function(a) {
71938 return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
71939 }).sort(function(a, b) {
71940 return a.dist - b.dist;
71941 }).map(function(a) {
71945 var other = presets.item(geometry);
71947 var results = leading_name.concat(
71949 leading_tag_values,
71950 leading_suggestions.slice(0, maxSuggestionResults + 5),
71953 similar_suggestions.slice(0, maxSuggestionResults)
71954 ).slice(0, maxSearchResults - 1);
71956 return presetCollection(lodash.uniq(results.concat(other)));
71964 function presetCategory(id, category, all) {
71965 category = lodash.clone(category);
71970 category.members = presetCollection(category.members.map(function(id) {
71971 return all.item(id);
71975 category.matchGeometry = function(geometry) {
71976 return category.geometry.indexOf(geometry) >= 0;
71980 category.matchScore = function() {
71985 category.name = function() {
71986 return t('presets.categories.' + id + '.name', {'default': id});
71990 category.terms = function() {
71998 function presetField(id, field) {
71999 field = lodash.clone(field);
72004 field.matchGeometry = function(geometry) {
72005 return !field.geometry || field.geometry === geometry;
72009 field.t = function(scope, options) {
72010 return t('presets.fields.' + id + '.' + scope, options);
72014 field.label = function() {
72015 return field.t('label', {'default': id});
72019 var placeholder = field.placeholder;
72020 field.placeholder = function() {
72021 return field.t('placeholder', {'default': placeholder});
72028 function presetPreset(id, preset, fields) {
72029 preset = lodash.clone(preset);
72032 preset.fields = (preset.fields || []).map(getFields);
72033 preset.geometry = (preset.geometry || []);
72036 function getFields(f) {
72041 preset.matchGeometry = function(geometry) {
72042 return preset.geometry.indexOf(geometry) >= 0;
72046 preset.originalScore = preset.matchScore || 1;
72049 preset.matchScore = function(entity) {
72050 var tags = preset.tags,
72053 for (var t$$1 in tags) {
72054 if (entity.tags[t$$1] === tags[t$$1]) {
72055 score += preset.originalScore;
72056 } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
72057 score += preset.originalScore / 2;
72067 preset.t = function(scope, options) {
72068 return t('presets.presets.' + id + '.' + scope, options);
72072 var name = preset.name || '';
72073 preset.name = function() {
72074 if (preset.suggestion) {
72075 id = id.split('/');
72076 id = id[0] + '/' + id[1];
72077 return name + ' - ' + t('presets.presets.' + id + '.name');
72079 return preset.t('name', {'default': name});
72083 preset.terms = function() {
72084 return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
72088 preset.isFallback = function() {
72089 var tagCount = Object.keys(preset.tags).length;
72090 return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
72094 var reference = preset.reference || {};
72095 preset.reference = function(geometry) {
72096 var key = reference.key || Object.keys(preset.tags)[0],
72097 value = reference.value || preset.tags[key];
72099 if (geometry === 'relation' && key === 'type') {
72100 if (value in preset.tags) {
72102 value = preset.tags[key];
72104 return { rtype: value };
72108 if (value === '*') {
72109 return { key: key };
72111 return { key: key, value: value };
72116 var removeTags = preset.removeTags || preset.tags;
72117 preset.removeTags = function(tags, geometry) {
72118 tags = lodash.omit(tags, lodash.keys(removeTags));
72120 for (var f in preset.fields) {
72121 var field = preset.fields[f];
72122 if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
72123 delete tags[field.key];
72132 var applyTags = preset.addTags || preset.tags;
72133 preset.applyTags = function(tags, geometry) {
72136 tags = lodash.clone(tags);
72138 for (k in applyTags) {
72139 if (applyTags[k] === '*') {
72142 tags[k] = applyTags[k];
72146 // Add area=yes if necessary.
72147 // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
72148 // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
72149 // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
72150 if (geometry === 'area') {
72151 var needsAreaTag = true;
72152 if (preset.geometry.indexOf('line') === -1) {
72153 for (k in applyTags) {
72154 if (k in areaKeys) {
72155 needsAreaTag = false;
72160 if (needsAreaTag) {
72165 for (var f in preset.fields) {
72166 var field = preset.fields[f];
72167 if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
72168 tags[field.key] = field.default;
72179 function presetIndex() {
72180 // a presetCollection with methods for
72181 // loading new data and returning defaults
72183 var all = presetCollection([]),
72184 defaults = { area: all, line: all, point: all, vertex: all, relation: all },
72187 recent = presetCollection([]);
72189 // Index of presets by (geometry, tag key).
72198 all.match = function(entity, resolver) {
72199 var geometry = entity.geometry(resolver);
72201 // Treat entities on addr:interpolation lines as points, not vertices (#3241)
72202 if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
72203 geometry = 'point';
72206 var geometryMatches = index[geometry],
72210 for (var k in entity.tags) {
72211 var keyMatches = geometryMatches[k];
72212 if (!keyMatches) continue;
72214 for (var i = 0; i < keyMatches.length; i++) {
72215 var score = keyMatches[i].matchScore(entity);
72216 if (score > best) {
72218 match = keyMatches[i];
72223 return match || all.item(geometry);
72227 // Because of the open nature of tagging, iD will never have a complete
72228 // list of tags used in OSM, so we want it to have logic like "assume
72229 // that a closed way with an amenity tag is an area, unless the amenity
72230 // is one of these specific types". This function computes a structure
72231 // that allows testing of such conditions, based on the presets designated
72232 // as as supporting (or not supporting) the area geometry.
72234 // The returned object L is a whitelist/blacklist of tags. A closed way
72235 // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
72236 // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
72237 // and the subkeys form the blacklist.
72238 all.areaKeys = function() {
72240 ignore = ['barrier', 'highway', 'footway', 'railway', 'type'], // probably a line..
72241 presets = lodash.reject(all.collection, 'suggestion');
72244 presets.forEach(function(d) {
72245 for (var key in d.tags) break;
72247 if (ignore.indexOf(key) !== -1) return;
72249 if (d.geometry.indexOf('area') !== -1) { // probably an area..
72250 areaKeys[key] = areaKeys[key] || {};
72255 presets.forEach(function(d) {
72256 for (var key in d.tags) break;
72258 if (ignore.indexOf(key) !== -1) return;
72260 var value = d.tags[key];
72261 if (key in areaKeys && // probably an area...
72262 d.geometry.indexOf('line') !== -1 && // but sometimes a line
72264 areaKeys[key][value] = true;
72272 all.init = function() {
72273 var d = data.presets;
72275 all.collection = [];
72276 recent.collection = [];
72279 index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
72282 lodash.forEach(d.fields, function(d, id) {
72283 fields[id] = presetField(id, d);
72284 if (d.universal) universal.push(fields[id]);
72289 lodash.forEach(d.presets, function(d, id) {
72290 all.collection.push(presetPreset(id, d, fields));
72294 if (d.categories) {
72295 lodash.forEach(d.categories, function(d, id) {
72296 all.collection.push(presetCategory(id, d, all));
72301 var getItem = lodash.bind(all.item, all);
72303 area: presetCollection(d.defaults.area.map(getItem)),
72304 line: presetCollection(d.defaults.line.map(getItem)),
72305 point: presetCollection(d.defaults.point.map(getItem)),
72306 vertex: presetCollection(d.defaults.vertex.map(getItem)),
72307 relation: presetCollection(d.defaults.relation.map(getItem))
72311 for (var i = 0; i < all.collection.length; i++) {
72312 var preset = all.collection[i],
72313 geometry = preset.geometry;
72315 for (var j = 0; j < geometry.length; j++) {
72316 var g = index[geometry[j]];
72317 for (var k in preset.tags) {
72318 (g[k] = g[k] || []).push(preset);
72326 all.field = function(id) {
72330 all.universal = function() {
72334 all.defaults = function(geometry, n) {
72335 var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
72336 def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
72337 return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
72340 all.choose = function(preset) {
72341 if (!preset.isFallback()) {
72342 recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
72352 function setAreaKeys(value) {
72357 function coreContext() {
72359 // create a special translation that contains the keys in place of the strings
72360 var tkeys = lodash.cloneDeep(en);
72363 function traverser(v, k, obj) {
72365 if (lodash.isObject(v)) {
72366 lodash.forOwn(v, traverser);
72367 } else if (lodash.isString(v)) {
72368 obj[k] = parents.join('.');
72373 lodash.forOwn(tkeys, traverser);
72374 addTranslation('_tkeys_', tkeys);
72376 addTranslation('en', en);
72379 var dispatch$$1 = dispatch('enter', 'exit', 'change'),
72382 // https://github.com/openstreetmap/iD/issues/772
72383 // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
72385 try { storage = localStorage; } catch (e) {} // eslint-disable-line no-empty
72386 storage = storage || (function() {
72389 getItem: function(k) { return s[k]; },
72390 setItem: function(k, v) { s[k] = v; },
72391 removeItem: function(k) { delete s[k]; }
72395 context.storage = function(k, v) {
72397 if (arguments.length === 1) return storage.getItem(k);
72398 else if (v === null) storage.removeItem(k);
72399 else storage.setItem(k, v);
72401 // localstorage quota exceeded
72402 /* eslint-disable no-console */
72403 if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
72404 /* eslint-enable no-console */
72409 /* Straight accessors. Avoid using these if you can. */
72410 var ui, connection, history;
72411 context.ui = function() { return ui; };
72412 context.connection = function() { return connection; };
72413 context.history = function() { return history; };
72417 function entitiesLoaded(err, result) {
72418 if (!err) history.merge(result.data, result.extent);
72421 context.preauth = function(options) {
72422 connection.switch(options);
72426 context.loadTiles = function(projection, dimensions, callback) {
72427 function done(err, result) {
72428 entitiesLoaded(err, result);
72429 if (callback) callback(err, result);
72431 connection.loadTiles(projection, dimensions, done);
72434 context.loadEntity = function(id, callback) {
72435 function done(err, result) {
72436 entitiesLoaded(err, result);
72437 if (callback) callback(err, result);
72439 connection.loadEntity(id, done);
72442 context.zoomToEntity = function(id, zoomTo) {
72443 if (zoomTo !== false) {
72444 this.loadEntity(id, function(err, result) {
72446 var entity = lodash.find(result.data, function(e) { return e.id === id; });
72447 if (entity) { map$$1.zoomTo(entity); }
72451 map$$1.on('drawn.zoomToEntity', function() {
72452 if (!context.hasEntity(id)) return;
72453 map$$1.on('drawn.zoomToEntity', null);
72454 context.on('enter.zoomToEntity', null);
72455 context.enter(modeSelect(context, [id]));
72458 context.on('enter.zoomToEntity', function() {
72459 if (mode.id !== 'browse') {
72460 map$$1.on('drawn.zoomToEntity', null);
72461 context.on('enter.zoomToEntity', null);
72466 var minEditableZoom = 16;
72467 context.minEditableZoom = function(_) {
72468 if (!arguments.length) return minEditableZoom;
72469 minEditableZoom = _;
72470 connection.tileZoom(_);
72476 var inIntro = false;
72477 context.inIntro = function(_) {
72478 if (!arguments.length) return inIntro;
72483 context.save = function() {
72484 // no history save, no message onbeforeunload
72485 if (inIntro || select('.modal').size()) return;
72488 if (mode && mode.id === 'save') {
72491 canSave = context.selectedIDs().every(function(id) {
72492 var entity = context.hasEntity(id);
72493 return entity && !entity.isDegenerate();
72500 if (history.hasChanges()) {
72501 return t('save.unsaved_changes');
72507 context.hasEntity = function(id) {
72508 return history.graph().hasEntity(id);
72510 context.entity = function(id) {
72511 return history.graph().entity(id);
72513 context.childNodes = function(way) {
72514 return history.graph().childNodes(way);
72516 context.geometry = function(id) {
72517 return context.entity(id).geometry(history.graph());
72523 context.mode = function() {
72526 context.enter = function(newMode) {
72529 dispatch$$1.call('exit', this, mode);
72534 dispatch$$1.call('enter', this, mode);
72537 context.selectedIDs = function() {
72538 if (mode && mode.selectedIDs) {
72539 return mode.selectedIDs();
72547 context.install = function(behavior) {
72548 context.surface().call(behavior);
72550 context.uninstall = function(behavior) {
72551 context.surface().call(behavior.off);
72556 var copyIDs = [], copyGraph;
72557 context.copyGraph = function() { return copyGraph; };
72558 context.copyIDs = function(_) {
72559 if (!arguments.length) return copyIDs;
72561 copyGraph = history.graph();
72568 context.background = function() { return background; };
72573 context.features = function() { return features; };
72574 context.hasHiddenConnections = function(id) {
72575 var graph = history.graph(),
72576 entity = graph.entity(id);
72577 return features.hasHiddenConnections(entity, graph);
72583 context.presets = function() { return presets; };
72588 context.map = function() { return map$$1; };
72589 context.layers = function() { return map$$1.layers; };
72590 context.surface = function() { return map$$1.surface; };
72591 context.editable = function() { return map$$1.editable(); };
72592 context.surfaceRect = function() {
72593 return map$$1.surface.node().getBoundingClientRect();
72605 context.debugFlags = function() {
72608 context.setDebug = function(flag, val) {
72609 if (arguments.length === 1) val = true;
72610 debugFlags[flag] = val;
72611 dispatch$$1.call('change');
72614 context.getDebug = function(flag) {
72615 return flag && debugFlags[flag];
72620 var container = select(document.body);
72621 context.container = function(_) {
72622 if (!arguments.length) return container;
72624 container.classed('id-container', true);
72628 context.embed = function(_) {
72629 if (!arguments.length) return embed;
72636 var assetPath = '';
72637 context.assetPath = function(_) {
72638 if (!arguments.length) return assetPath;
72644 context.assetMap = function(_) {
72645 if (!arguments.length) return assetMap;
72650 context.asset = function(_) {
72651 var filename = assetPath + _;
72652 return assetMap[filename] || filename;
72655 context.imagePath = function(_) {
72656 return context.asset('img/' + _);
72661 // `locale` variable contains a "requested locale".
72662 // It won't become the `currentLocale` until after loadLocale() is called.
72663 var locale, localePath;
72665 context.locale = function(loc, path$$1) {
72666 if (!arguments.length) return currentLocale;
72668 localePath = path$$1;
72672 context.loadLocale = function(callback) {
72673 if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) {
72674 localePath = localePath || context.asset('locales/' + locale + '.json');
72675 json(localePath, function(err, result) {
72677 addTranslation(locale, result[locale]);
72697 /* reset (aka flush) */
72698 context.reset = context.flush = function() {
72699 context.debouncedSave.cancel();
72700 lodash.each(services, function(service) {
72701 if (service && typeof service.reset === 'function') {
72702 service.reset(context);
72712 context.version = '2.2.0';
72714 context.projection = geoRawMercator();
72715 context.curtainProjection = geoRawMercator();
72717 locale = utilDetect().locale;
72718 if (locale && !dataLocales.hasOwnProperty(locale)) {
72719 locale = locale.split('-')[0];
72722 history = coreHistory(context);
72723 context.graph = history.graph;
72724 context.changes = history.changes;
72725 context.intersects = history.intersects;
72727 // Debounce save, since it's a synchronous localStorage write,
72728 // and history changes can happen frequently (e.g. when dragging).
72729 context.debouncedSave = lodash.debounce(context.save, 350);
72730 function withDebouncedSave(fn) {
72731 return function() {
72732 var result = fn.apply(history, arguments);
72733 context.debouncedSave();
72738 context.perform = withDebouncedSave(history.perform);
72739 context.replace = withDebouncedSave(history.replace);
72740 context.pop = withDebouncedSave(history.pop);
72741 context.overwrite = withDebouncedSave(history.overwrite);
72742 context.undo = withDebouncedSave(history.undo);
72743 context.redo = withDebouncedSave(history.redo);
72745 ui = uiInit(context);
72747 connection = services.osm;
72748 background = rendererBackground(context);
72749 features = rendererFeatures(context);
72750 presets = presetIndex();
72752 map$$1 = rendererMap(context);
72753 context.mouse = map$$1.mouse;
72754 context.extent = map$$1.extent;
72755 context.pan = map$$1.pan;
72756 context.zoomIn = map$$1.zoomIn;
72757 context.zoomOut = map$$1.zoomOut;
72758 context.zoomInFurther = map$$1.zoomInFurther;
72759 context.zoomOutFurther = map$$1.zoomOutFurther;
72760 context.redrawEnable = map$$1.redrawEnable;
72762 lodash.each(services, function(service) {
72763 if (service && typeof service.init === 'function') {
72764 service.init(context);
72770 areaKeys = presets.areaKeys();
72773 return utilRebind(context, dispatch$$1, 'on');
72776 function osmWay() {
72777 if (!(this instanceof osmWay)) {
72778 return (new osmWay()).initialize(arguments);
72779 } else if (arguments.length) {
72780 this.initialize(arguments);
72785 osmEntity$$1.way = osmWay;
72787 osmWay.prototype = Object.create(osmEntity$$1.prototype);
72790 lodash.extend(osmWay.prototype, {
72795 copy: function(resolver, copies) {
72796 if (copies[this.id])
72797 return copies[this.id];
72799 var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
72801 var nodes = this.nodes.map(function(id) {
72802 return resolver.entity(id).copy(resolver, copies).id;
72805 copy = copy.update({ nodes: nodes });
72806 copies[this.id] = copy;
72812 extent: function(resolver) {
72813 return resolver.transient(this, 'extent', function() {
72814 var extent$$1 = geoExtent$$1();
72815 for (var i = 0; i < this.nodes.length; i++) {
72816 var node = resolver.hasEntity(this.nodes[i]);
72818 extent$$1._extend(node.extent());
72826 first: function() {
72827 return this.nodes[0];
72832 return this.nodes[this.nodes.length - 1];
72836 contains: function(node) {
72837 return this.nodes.indexOf(node) >= 0;
72841 affix: function(node) {
72842 if (this.nodes[0] === node) return 'prefix';
72843 if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
72847 layer: function() {
72848 // explicit layer tag, clamp between -10, 10..
72849 if (isFinite(this.tags.layer)) {
72850 return Math.max(-10, Math.min(+(this.tags.layer), 10));
72853 // implied layer tag..
72854 if (this.tags.location === 'overground') return 1;
72855 if (this.tags.location === 'underground') return -1;
72856 if (this.tags.location === 'underwater') return -10;
72858 if (this.tags.power === 'line') return 10;
72859 if (this.tags.power === 'minor_line') return 10;
72860 if (this.tags.aerialway) return 10;
72861 if (this.tags.bridge) return 1;
72862 if (this.tags.cutting) return -1;
72863 if (this.tags.tunnel) return -1;
72864 if (this.tags.waterway) return -1;
72865 if (this.tags.man_made === 'pipeline') return -10;
72866 if (this.tags.boundary) return -10;
72871 isOneWay: function() {
72872 // explicit oneway tag..
72873 if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
72874 if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
72876 // implied oneway tag..
72877 for (var key in this.tags) {
72878 if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
72885 lanes: function() {
72886 return osmLanes(this);
72890 isClosed: function() {
72891 return this.nodes.length > 1 && this.first() === this.last();
72895 isConvex: function(resolver) {
72896 if (!this.isClosed() || this.isDegenerate()) return null;
72898 var nodes = lodash.uniq(resolver.childNodes(this)),
72899 coords = lodash.map(nodes, 'loc'),
72900 curr = 0, prev = 0;
72902 for (var i = 0; i < coords.length; i++) {
72903 var o = coords[(i+1) % coords.length],
72905 b = coords[(i+2) % coords.length],
72906 res = geoCross(o, a, b);
72908 curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
72911 } else if (prev && curr !== prev) {
72920 isArea: function() {
72921 if (this.tags.area === 'yes')
72923 if (!this.isClosed() || this.tags.area === 'no')
72925 for (var key in this.tags) {
72926 if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
72934 isDegenerate: function() {
72935 return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
72939 areAdjacent: function(n1, n2) {
72940 for (var i = 0; i < this.nodes.length; i++) {
72941 if (this.nodes[i] === n1) {
72942 if (this.nodes[i - 1] === n2) return true;
72943 if (this.nodes[i + 1] === n2) return true;
72950 geometry: function(graph) {
72951 return graph.transient(this, 'geometry', function() {
72952 return this.isArea() ? 'area' : 'line';
72957 // If this way is not closed, append the beginning node to the end of the nodelist to close it.
72958 close: function() {
72959 if (this.isClosed() || !this.nodes.length) return this;
72961 var nodes = this.nodes.slice();
72962 nodes = nodes.filter(noRepeatNodes);
72963 nodes.push(nodes[0]);
72964 return this.update({ nodes: nodes });
72968 // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
72969 unclose: function() {
72970 if (!this.isClosed()) return this;
72972 var nodes = this.nodes.slice(),
72973 connector = this.first(),
72974 i = nodes.length - 1;
72976 // remove trailing connectors..
72977 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
72978 nodes.splice(i, 1);
72979 i = nodes.length - 1;
72982 nodes = nodes.filter(noRepeatNodes);
72983 return this.update({ nodes: nodes });
72987 // Adds a node (id) in front of the node which is currently at position index.
72988 // If index is undefined, the node will be added to the end of the way for linear ways,
72989 // or just before the final connecting node for circular ways.
72990 // Consecutive duplicates are eliminated including existing ones.
72991 // Circularity is always preserved when adding a node.
72992 addNode: function(id, index) {
72993 var nodes = this.nodes.slice(),
72994 isClosed = this.isClosed(),
72995 max$$1 = isClosed ? nodes.length - 1 : nodes.length;
72997 if (index === undefined) {
73001 if (index < 0 || index > max$$1) {
73002 throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
73005 // If this is a closed way, remove all connector nodes except the first one
73006 // (there may be duplicates) and adjust index if necessary..
73008 var connector = this.first();
73010 // leading connectors..
73012 while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
73013 nodes.splice(i, 1);
73014 if (index > i) index--;
73017 // trailing connectors..
73018 i = nodes.length - 1;
73019 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
73020 nodes.splice(i, 1);
73021 if (index > i) index--;
73022 i = nodes.length - 1;
73026 nodes.splice(index, 0, id);
73027 nodes = nodes.filter(noRepeatNodes);
73029 // If the way was closed before, append a connector node to keep it closed..
73030 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
73031 nodes.push(nodes[0]);
73034 return this.update({ nodes: nodes });
73038 // Replaces the node which is currently at position index with the given node (id).
73039 // Consecutive duplicates are eliminated including existing ones.
73040 // Circularity is preserved when updating a node.
73041 updateNode: function(id, index) {
73042 var nodes = this.nodes.slice(),
73043 isClosed = this.isClosed(),
73044 max$$1 = nodes.length - 1;
73046 if (index === undefined || index < 0 || index > max$$1) {
73047 throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
73050 // If this is a closed way, remove all connector nodes except the first one
73051 // (there may be duplicates) and adjust index if necessary..
73053 var connector = this.first();
73055 // leading connectors..
73057 while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
73058 nodes.splice(i, 1);
73059 if (index > i) index--;
73062 // trailing connectors..
73063 i = nodes.length - 1;
73064 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
73065 nodes.splice(i, 1);
73066 if (index === i) index = 0; // update leading connector instead
73067 i = nodes.length - 1;
73071 nodes.splice(index, 1, id);
73072 nodes = nodes.filter(noRepeatNodes);
73074 // If the way was closed before, append a connector node to keep it closed..
73075 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
73076 nodes.push(nodes[0]);
73079 return this.update({nodes: nodes});
73083 // Replaces each occurrence of node id needle with replacement.
73084 // Consecutive duplicates are eliminated including existing ones.
73085 // Circularity is preserved.
73086 replaceNode: function(needle, replacement) {
73087 var nodes = this.nodes.slice(),
73088 isClosed = this.isClosed();
73090 for (var i = 0; i < nodes.length; i++) {
73091 if (nodes[i] === needle) {
73092 nodes[i] = replacement;
73096 nodes = nodes.filter(noRepeatNodes);
73098 // If the way was closed before, append a connector node to keep it closed..
73099 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
73100 nodes.push(nodes[0]);
73103 return this.update({nodes: nodes});
73107 // Removes each occurrence of node id needle with replacement.
73108 // Consecutive duplicates are eliminated including existing ones.
73109 // Circularity is preserved.
73110 removeNode: function(id) {
73111 var nodes = this.nodes.slice(),
73112 isClosed = this.isClosed();
73115 .filter(function(node) { return node !== id; })
73116 .filter(noRepeatNodes);
73118 // If the way was closed before, append a connector node to keep it closed..
73119 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
73120 nodes.push(nodes[0]);
73123 return this.update({nodes: nodes});
73127 asJXON: function(changeset_id) {
73130 '@id': this.osmId(),
73131 '@version': this.version || 0,
73132 nd: lodash.map(this.nodes, function(id) {
73133 return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
73135 tag: lodash.map(this.tags, function(v, k) {
73136 return { keyAttributes: { k: k, v: v } };
73140 if (changeset_id) {
73141 r.way['@changeset'] = changeset_id;
73147 asGeoJSON: function(resolver) {
73148 return resolver.transient(this, 'GeoJSON', function() {
73149 var coordinates = lodash.map(resolver.childNodes(this), 'loc');
73150 if (this.isArea() && this.isClosed()) {
73153 coordinates: [coordinates]
73157 type: 'LineString',
73158 coordinates: coordinates
73165 area: function(resolver) {
73166 return resolver.transient(this, 'area', function() {
73167 var nodes = resolver.childNodes(this);
73171 coordinates: [lodash.map(nodes, 'loc')]
73174 if (!this.isClosed() && nodes.length) {
73175 json$$1.coordinates[0].push(nodes[0].loc);
73178 var area$$1 = area(json$$1);
73180 // Heuristic for detecting counterclockwise winding order. Assumes
73181 // that OpenStreetMap polygons are not hemisphere-spanning.
73182 if (area$$1 > 2 * Math.PI) {
73183 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
73184 area$$1 = area(json$$1);
73187 return isNaN(area$$1) ? 0 : area$$1;
73193 // Filter function to eliminate consecutive duplicates.
73194 function noRepeatNodes(node, i, arr) {
73195 return i === 0 || node !== arr[i - 1];
73198 function osmTurn(turn) {
73199 if (!(this instanceof osmTurn))
73200 return new osmTurn(turn);
73201 lodash.extend(this, turn);
73205 function osmIntersection(graph, vertexId) {
73206 var vertex = graph.entity(vertexId),
73207 parentWays = graph.parentWays(vertex),
73211 function addHighway(way, adjacentNodeId) {
73212 if (highways[adjacentNodeId]) {
73213 coincident.push(adjacentNodeId);
73215 highways[adjacentNodeId] = way;
73219 // Pre-split ways that would need to be split in
73220 // order to add a restriction. The real split will
73221 // happen when the restriction is added.
73222 parentWays.forEach(function(way) {
73223 if (!way.tags.highway || way.isArea() || way.isDegenerate())
73226 var isFirst = (vertexId === way.first()),
73227 isLast = (vertexId === way.last()),
73228 isAffix = (isFirst || isLast),
73229 isClosingNode = (isFirst && isLast);
73231 if (isAffix && !isClosingNode) {
73232 var index = (isFirst ? 1 : way.nodes.length - 2);
73233 addHighway(way, way.nodes[index]);
73236 var splitIndex, wayA, wayB, indexA, indexB;
73237 if (isClosingNode) {
73238 splitIndex = Math.ceil(way.nodes.length / 2); // split at midpoint
73239 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
73240 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
73242 indexB = way.nodes.length - 2;
73244 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1); // split at vertexid
73245 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
73246 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
73247 indexA = splitIndex - 1;
73248 indexB = splitIndex + 1;
73250 graph = graph.replace(wayA).replace(wayB);
73251 addHighway(wayA, way.nodes[indexA]);
73252 addHighway(wayB, way.nodes[indexB]);
73256 // remove any ways from this intersection that are coincident
73257 // (i.e. any adjacent node used by more than one intersecting way)
73258 coincident.forEach(function (n) {
73259 delete highways[n];
73263 var intersection = {
73264 highways: highways,
73265 ways: lodash.values(highways),
73270 intersection.adjacentNodeId = function(fromWayId) {
73271 return lodash.find(lodash.keys(highways), function(k) {
73272 return highways[k].id === fromWayId;
73277 intersection.turns = function(fromNodeId) {
73278 var start = highways[fromNodeId];
73282 if (start.first() === vertex.id && start.tags.oneway === 'yes')
73284 if (start.last() === vertex.id && start.tags.oneway === '-1')
73287 function withRestriction(turn) {
73288 graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
73289 if (relation.tags.type !== 'restriction')
73292 var f = relation.memberByRole('from'),
73293 t = relation.memberByRole('to'),
73294 v = relation.memberByRole('via');
73296 if (f && f.id === turn.from.way &&
73297 v && v.id === turn.via.node &&
73298 t && t.id === turn.to.way) {
73299 turn.restriction = relation.id;
73300 } else if (/^only_/.test(relation.tags.restriction) &&
73301 f && f.id === turn.from.way &&
73302 v && v.id === turn.via.node &&
73303 t && t.id !== turn.to.way) {
73304 turn.restriction = relation.id;
73305 turn.indirect_restriction = true;
73309 return osmTurn(turn);
73315 way: start.id.split(/-(a|b)/)[0]
73317 via = { node: vertex.id },
73320 lodash.each(highways, function(end, adjacentNodeId) {
73325 if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
73326 turns.push(withRestriction({
73330 node: adjacentNodeId,
73331 way: end.id.split(/-(a|b)/)[0]
73337 if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
73338 turns.push(withRestriction({
73342 node: adjacentNodeId,
73343 way: end.id.split(/-(a|b)/)[0]
73351 if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
73352 turns.push(withRestriction({
73363 return intersection;
73367 function osmInferRestriction(graph, from, via, to, projection) {
73368 var fromWay = graph.entity(from.way),
73369 fromNode = graph.entity(from.node),
73370 toWay = graph.entity(to.way),
73371 toNode = graph.entity(to.node),
73372 viaNode = graph.entity(via.node),
73373 fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
73374 (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
73375 toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
73376 (toWay.tags.oneway === '-1' && toWay.last() === via.node),
73377 angle = geoAngle(viaNode, fromNode, projection) -
73378 geoAngle(viaNode, toNode, projection);
73380 angle = angle * 180 / Math.PI;
73385 if (fromNode === toNode)
73386 return 'no_u_turn';
73387 if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
73388 return 'no_u_turn';
73390 return 'no_right_turn';
73392 return 'no_left_turn';
73394 return 'no_straight_on';
73397 function actionAddMember(relationId, member, memberIndex) {
73398 return function(graph) {
73399 var relation = graph.entity(relationId);
73401 if (isNaN(memberIndex) && member.type === 'way') {
73402 var members = relation.indexedMembers();
73403 members.push(member);
73405 var joined = osmJoinWays(members, graph);
73406 for (var i = 0; i < joined.length; i++) {
73407 var segment = joined[i];
73408 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
73409 if (segment[j] !== member)
73413 memberIndex = segment[j + 1].index;
73414 } else if (j === segment.length - 1) {
73415 memberIndex = segment[j - 1].index + 1;
73417 memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
73423 return graph.replace(relation.addMember(member, memberIndex));
73427 function actionAddMidpoint(midpoint, node) {
73428 return function(graph) {
73429 graph = graph.replace(node.move(midpoint.loc));
73431 var parents = lodash.intersection(
73432 graph.parentWays(graph.entity(midpoint.edge[0])),
73433 graph.parentWays(graph.entity(midpoint.edge[1])));
73435 parents.forEach(function(way) {
73436 for (var i = 0; i < way.nodes.length - 1; i++) {
73437 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
73438 graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
73440 // Add only one midpoint on doubled-back segments,
73441 // turning them into self-intersections.
73451 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
73452 function actionAddVertex(wayId, nodeId, index) {
73453 return function(graph) {
73454 return graph.replace(graph.entity(wayId).addNode(nodeId, index));
73458 function actionChangeMember(relationId, member, memberIndex) {
73459 return function(graph) {
73460 return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
73464 function actionChangePreset(entityId, oldPreset, newPreset) {
73465 return function(graph) {
73466 var entity = graph.entity(entityId),
73467 geometry = entity.geometry(graph),
73468 tags = entity.tags;
73470 if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
73471 if (newPreset) tags = newPreset.applyTags(tags, geometry);
73473 return graph.replace(entity.update({tags: tags}));
73477 function actionChangeTags(entityId, tags) {
73478 return function(graph) {
73479 var entity = graph.entity(entityId);
73480 return graph.replace(entity.update({tags: tags}));
73484 function actionCircularize(wayId, projection, maxAngle) {
73485 maxAngle = (maxAngle || 20) * Math.PI / 180;
73488 var action = function(graph, t) {
73489 if (t === null || !isFinite(t)) t = 1;
73490 t = Math.min(Math.max(+t, 0), 1);
73492 var way = graph.entity(wayId),
73495 graph.childNodes(way).forEach(function(node) {
73496 if (!origNodes[node.id]) origNodes[node.id] = node;
73499 if (!way.isConvex(graph)) {
73500 graph = action.makeConvex(graph);
73503 var nodes = lodash.uniq(graph.childNodes(way)),
73504 keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
73505 points = nodes.map(function(n) { return projection(n.loc); }),
73506 keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
73507 centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
73508 radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
73509 sign = d3polygonArea(points) > 0 ? 1 : -1,
73512 // we need atleast two key nodes for the algorithm to work
73513 if (!keyNodes.length) {
73514 keyNodes = [nodes[0]];
73515 keyPoints = [points[0]];
73518 if (keyNodes.length === 1) {
73519 var index = nodes.indexOf(keyNodes[0]),
73520 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
73522 keyNodes.push(nodes[oppositeIndex]);
73523 keyPoints.push(points[oppositeIndex]);
73526 // key points and nodes are those connected to the ways,
73527 // they are projected onto the circle, inbetween nodes are moved
73528 // to constant intervals between key nodes, extra inbetween nodes are
73529 // added if necessary.
73530 for (var i = 0; i < keyPoints.length; i++) {
73531 var nextKeyNodeIndex = (i + 1) % keyNodes.length,
73532 startNode = keyNodes[i],
73533 endNode = keyNodes[nextKeyNodeIndex],
73534 startNodeIndex = nodes.indexOf(startNode),
73535 endNodeIndex = nodes.indexOf(endNode),
73536 numberNewPoints = -1,
73537 indexRange = endNodeIndex - startNodeIndex,
73539 inBetweenNodes = [],
73540 startAngle, endAngle, totalAngle, eachAngle,
73541 angle, loc, node, origNode, j;
73543 if (indexRange < 0) {
73544 indexRange += nodes.length;
73547 // position this key node
73548 var distance = geoEuclideanDistance(centroid, keyPoints[i]);
73549 if (distance === 0) { distance = 1e-4; }
73551 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
73552 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius
73554 loc = projection.invert(keyPoints[i]);
73555 node = keyNodes[i];
73556 origNode = origNodes[node.id];
73557 node = node.move(geoInterp(origNode.loc, loc, t));
73558 graph = graph.replace(node);
73560 // figure out the between delta angle we want to match to
73561 startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
73562 endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
73563 totalAngle = endAngle - startAngle;
73565 // detects looping around -pi/pi
73566 if (totalAngle * sign > 0) {
73567 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
73572 eachAngle = totalAngle / (indexRange + numberNewPoints);
73573 } while (Math.abs(eachAngle) > maxAngle);
73576 // move existing nodes
73577 for (j = 1; j < indexRange; j++) {
73578 angle = startAngle + j * eachAngle;
73579 loc = projection.invert([
73580 centroid[0] + Math.cos(angle) * radius,
73581 centroid[1] + Math.sin(angle) * radius
73584 node = nodes[(j + startNodeIndex) % nodes.length];
73585 origNode = origNodes[node.id];
73586 nearNodes[node.id] = angle;
73588 node = node.move(geoInterp(origNode.loc, loc, t));
73589 graph = graph.replace(node);
73592 // add new inbetween nodes if necessary
73593 for (j = 0; j < numberNewPoints; j++) {
73594 angle = startAngle + (indexRange + j) * eachAngle;
73595 loc = projection.invert([
73596 centroid[0] + Math.cos(angle) * radius,
73597 centroid[1] + Math.sin(angle) * radius
73600 // choose a nearnode to use as the original
73601 var min$$1 = Infinity;
73602 for (var nodeId in nearNodes) {
73603 var nearAngle = nearNodes[nodeId],
73604 dist = Math.abs(nearAngle - angle);
73605 if (dist < min$$1) {
73607 origNode = origNodes[nodeId];
73611 node = osmNode({ loc: geoInterp(origNode.loc, loc, t) });
73612 graph = graph.replace(node);
73614 nodes.splice(endNodeIndex + j, 0, node);
73615 inBetweenNodes.push(node.id);
73618 // Check for other ways that share these keyNodes..
73619 // If keyNodes are adjacent in both ways,
73620 // we can add inBetween nodes to that shared way too..
73621 if (indexRange === 1 && inBetweenNodes.length) {
73622 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
73623 endIndex1 = way.nodes.lastIndexOf(endNode.id),
73624 wayDirection1 = (endIndex1 - startIndex1);
73625 if (wayDirection1 < -1) { wayDirection1 = 1; }
73627 /* eslint-disable no-loop-func */
73628 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
73629 if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
73630 var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
73631 endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
73632 wayDirection2 = (endIndex2 - startIndex2),
73633 insertAt = endIndex2;
73634 if (wayDirection2 < -1) { wayDirection2 = 1; }
73636 if (wayDirection1 !== wayDirection2) {
73637 inBetweenNodes.reverse();
73638 insertAt = startIndex2;
73640 for (j = 0; j < inBetweenNodes.length; j++) {
73641 sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
73643 graph = graph.replace(sharedWay);
73646 /* eslint-enable no-loop-func */
73651 // update the way to have all the new nodes
73652 ids = nodes.map(function(n) { return n.id; });
73655 way = way.update({nodes: ids});
73656 graph = graph.replace(way);
73662 action.makeConvex = function(graph) {
73663 var way = graph.entity(wayId),
73664 nodes = lodash.uniq(graph.childNodes(way)),
73665 points = nodes.map(function(n) { return projection(n.loc); }),
73666 sign = d3polygonArea(points) > 0 ? 1 : -1,
73667 hull = d3polygonHull(points);
73669 // D3 convex hulls go counterclockwise..
73675 for (var i = 0; i < hull.length - 1; i++) {
73676 var startIndex = points.indexOf(hull[i]),
73677 endIndex = points.indexOf(hull[i+1]),
73678 indexRange = (endIndex - startIndex);
73680 if (indexRange < 0) {
73681 indexRange += nodes.length;
73684 // move interior nodes to the surface of the convex hull..
73685 for (var j = 1; j < indexRange; j++) {
73686 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
73687 node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
73688 graph = graph.replace(node);
73695 action.disabled = function(graph) {
73696 if (!graph.entity(wayId).isClosed())
73697 return 'not_closed';
73701 action.transitionable = true;
73707 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
73708 function actionDeleteWay(wayId) {
73711 function canDeleteNode(node, graph) {
73712 return !graph.parentWays(node).length &&
73713 !graph.parentRelations(node).length &&
73714 !node.hasInterestingTags();
73718 var action = function(graph) {
73719 var way = graph.entity(wayId);
73721 graph.parentRelations(way)
73722 .forEach(function(parent) {
73723 parent = parent.removeMembersWithID(wayId);
73724 graph = graph.replace(parent);
73726 if (parent.isDegenerate()) {
73727 graph = actionDeleteRelation(parent.id)(graph);
73731 lodash.uniq(way.nodes).forEach(function(nodeId) {
73732 graph = graph.replace(way.removeNode(nodeId));
73734 var node = graph.entity(nodeId);
73735 if (canDeleteNode(node, graph)) {
73736 graph = graph.remove(node);
73740 return graph.remove(way);
73747 function actionDeleteMultiple(ids) {
73749 way: actionDeleteWay,
73750 node: actionDeleteNode,
73751 relation: actionDeleteRelation
73755 var action = function(graph) {
73756 ids.forEach(function(id) {
73757 if (graph.hasEntity(id)) { // It may have been deleted aready.
73758 graph = actions[graph.entity(id).type](id)(graph);
73769 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
73770 function actionDeleteRelation(relationId) {
73773 function canDeleteEntity(entity, graph) {
73774 return !graph.parentWays(entity).length &&
73775 !graph.parentRelations(entity).length &&
73776 !entity.hasInterestingTags();
73780 var action = function(graph) {
73781 var relation = graph.entity(relationId);
73783 graph.parentRelations(relation)
73784 .forEach(function(parent) {
73785 parent = parent.removeMembersWithID(relationId);
73786 graph = graph.replace(parent);
73788 if (parent.isDegenerate()) {
73789 graph = actionDeleteRelation(parent.id)(graph);
73793 lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
73794 graph = graph.replace(relation.removeMembersWithID(memberId));
73796 var entity = graph.entity(memberId);
73797 if (canDeleteEntity(entity, graph)) {
73798 graph = actionDeleteMultiple([memberId])(graph);
73802 return graph.remove(relation);
73809 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
73810 function actionDeleteNode(nodeId) {
73811 var action = function(graph) {
73812 var node = graph.entity(nodeId);
73814 graph.parentWays(node)
73815 .forEach(function(parent) {
73816 parent = parent.removeNode(nodeId);
73817 graph = graph.replace(parent);
73819 if (parent.isDegenerate()) {
73820 graph = actionDeleteWay(parent.id)(graph);
73824 graph.parentRelations(node)
73825 .forEach(function(parent) {
73826 parent = parent.removeMembersWithID(nodeId);
73827 graph = graph.replace(parent);
73829 if (parent.isDegenerate()) {
73830 graph = actionDeleteRelation(parent.id)(graph);
73834 return graph.remove(node);
73841 // Connect the ways at the given nodes.
73843 // The last node will survive. All other nodes will be replaced with
73844 // the surviving node in parent ways, and then removed.
73846 // Tags and relation memberships of of non-surviving nodes are merged
73847 // to the survivor.
73849 // This is the inverse of `iD.actionDisconnect`.
73852 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
73853 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
73855 function actionConnect(nodeIds) {
73856 return function(graph) {
73857 var survivor = graph.entity(lodash.last(nodeIds));
73859 for (var i = 0; i < nodeIds.length - 1; i++) {
73860 var node = graph.entity(nodeIds[i]);
73862 /* eslint-disable no-loop-func */
73863 graph.parentWays(node).forEach(function(parent) {
73864 if (!parent.areAdjacent(node.id, survivor.id)) {
73865 graph = graph.replace(parent.replaceNode(node.id, survivor.id));
73869 graph.parentRelations(node).forEach(function(parent) {
73870 graph = graph.replace(parent.replaceMember(node, survivor));
73872 /* eslint-enable no-loop-func */
73874 survivor = survivor.mergeTags(node.tags);
73875 graph = actionDeleteNode(node.id)(graph);
73878 graph = graph.replace(survivor);
73884 function actionCopyEntities(ids, fromGraph) {
73888 var action = function(graph) {
73889 ids.forEach(function(id) {
73890 fromGraph.entity(id).copy(fromGraph, copies);
73893 for (var id in copies) {
73894 graph = graph.replace(copies[id]);
73901 action.copies = function() {
73909 function actionDeleteMember(relationId, memberIndex) {
73910 return function(graph) {
73911 var relation = graph.entity(relationId)
73912 .removeMember(memberIndex);
73914 graph = graph.replace(relation);
73916 if (relation.isDegenerate())
73917 graph = actionDeleteRelation(relation.id)(graph);
73923 function actionDeprecateTags(entityId) {
73925 return function(graph) {
73926 var entity = graph.entity(entityId),
73927 newtags = lodash.clone(entity.tags),
73931 // This handles dataDeprecated tags with a single condition
73932 for (var i = 0; i < dataDeprecated.length; i++) {
73934 rule = dataDeprecated[i];
73935 var match = lodash.toPairs(rule.old)[0],
73936 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
73938 if (entity.tags[match[0]] && match[1] === '*') {
73940 var value = entity.tags[match[0]];
73941 if (replacements && !newtags[replacements[0][0]]) {
73942 newtags[replacements[0][0]] = value;
73944 delete newtags[match[0]];
73947 } else if (entity.tags[match[0]] === match[1]) {
73948 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
73954 return graph.replace(entity.update({tags: newtags}));
73961 function actionDiscardTags(difference) {
73963 return function(graph) {
73964 function discardTags(entity) {
73965 if (!lodash.isEmpty(entity.tags)) {
73967 lodash.each(entity.tags, function(v, k) {
73968 if (v) tags[k] = v;
73971 graph = graph.replace(entity.update({
73972 tags: lodash.omit(tags, dataDiscarded)
73977 difference.modified().forEach(discardTags);
73978 difference.created().forEach(discardTags);
73984 // Disconect the ways at the given node.
73986 // Optionally, disconnect only the given ways.
73988 // For testing convenience, accepts an ID to assign to the (first) new node.
73989 // Normally, this will be undefined and the way will automatically
73990 // be assigned a new ID.
73992 // This is the inverse of `iD.actionConnect`.
73995 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
73996 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
73998 function actionDisconnect(nodeId, newNodeId) {
74002 var action = function(graph) {
74003 var node = graph.entity(nodeId),
74004 connections = action.connections(graph);
74006 connections.forEach(function(connection) {
74007 var way = graph.entity(connection.wayID),
74008 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
74010 graph = graph.replace(newNode);
74011 if (connection.index === 0 && way.isArea()) {
74012 // replace shared node with shared node..
74013 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
74014 } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
74015 // replace closing node with new new node..
74016 graph = graph.replace(way.unclose().addNode(newNode.id));
74018 // replace shared node with multiple new nodes..
74019 graph = graph.replace(way.updateNode(newNode.id, connection.index));
74027 action.connections = function(graph) {
74028 var candidates = [],
74030 parentWays = graph.parentWays(graph.entity(nodeId));
74032 parentWays.forEach(function(way) {
74033 if (wayIds && wayIds.indexOf(way.id) === -1) {
74037 if (way.isArea() && (way.nodes[0] === nodeId)) {
74038 candidates.push({ wayID: way.id, index: 0 });
74040 way.nodes.forEach(function(waynode, index) {
74041 if (waynode === nodeId) {
74042 candidates.push({ wayID: way.id, index: index });
74048 return keeping ? candidates : candidates.slice(1);
74052 action.disabled = function(graph) {
74053 var connections = action.connections(graph);
74054 if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
74055 return 'not_connected';
74057 var parentWays = graph.parentWays(graph.entity(nodeId)),
74058 seenRelationIds = {},
74061 parentWays.forEach(function(way) {
74062 if (wayIds && wayIds.indexOf(way.id) === -1)
74065 var relations = graph.parentRelations(way);
74066 relations.forEach(function(relation) {
74067 if (relation.id in seenRelationIds) {
74068 sharedRelation = relation;
74070 seenRelationIds[relation.id] = true;
74075 if (sharedRelation)
74080 action.limitWays = function(_) {
74081 if (!arguments.length) return wayIds;
74090 // Join ways at the end node they share.
74092 // This is the inverse of `iD.actionSplit`.
74095 // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
74096 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
74098 function actionJoin(ids) {
74100 function groupEntitiesByGeometry(graph) {
74101 var entities = ids.map(function(id) { return graph.entity(id); });
74102 return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
74106 var action = function(graph) {
74107 var ways = ids.map(graph.entity, graph),
74108 survivor = ways[0];
74110 // Prefer to keep an existing way.
74111 for (var i = 0; i < ways.length; i++) {
74112 if (!ways[i].isNew()) {
74113 survivor = ways[i];
74118 var joined = osmJoinWays(ways, graph)[0];
74120 survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
74121 graph = graph.replace(survivor);
74123 joined.forEach(function(way) {
74124 if (way.id === survivor.id)
74127 graph.parentRelations(way).forEach(function(parent) {
74128 graph = graph.replace(parent.replaceMember(way, survivor));
74131 survivor = survivor.mergeTags(way.tags);
74133 graph = graph.replace(survivor);
74134 graph = actionDeleteWay(way.id)(graph);
74141 action.disabled = function(graph) {
74142 var geometries = groupEntitiesByGeometry(graph);
74143 if (ids.length < 2 || ids.length !== geometries.line.length)
74144 return 'not_eligible';
74146 var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
74147 if (joined.length > 1)
74148 return 'not_adjacent';
74150 var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
74153 conflicting = false;
74155 joined[0].forEach(function(way) {
74156 var parents = graph.parentRelations(way);
74157 parents.forEach(function(parent) {
74158 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
74162 for (var k in way.tags) {
74163 if (!(k in tags)) {
74164 tags[k] = way.tags[k];
74165 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
74166 conflicting = true;
74172 return 'restriction';
74175 return 'conflicting_tags';
74182 function actionMerge(ids) {
74184 function groupEntitiesByGeometry(graph) {
74185 var entities = ids.map(function(id) { return graph.entity(id); });
74186 return lodash.extend({point: [], area: [], line: [], relation: []},
74187 lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
74191 var action = function(graph) {
74192 var geometries = groupEntitiesByGeometry(graph),
74193 target = geometries.area[0] || geometries.line[0],
74194 points = geometries.point;
74196 points.forEach(function(point) {
74197 target = target.mergeTags(point.tags);
74198 graph = graph.replace(target);
74200 graph.parentRelations(point).forEach(function(parent) {
74201 graph = graph.replace(parent.replaceMember(point, target));
74204 var nodes = lodash.uniq(graph.childNodes(target)),
74205 removeNode = point;
74207 for (var i = 0; i < nodes.length; i++) {
74208 var node = nodes[i];
74209 if (graph.parentWays(node).length > 1 ||
74210 graph.parentRelations(node).length ||
74211 node.hasInterestingTags()) {
74215 // Found an uninteresting child node on the target way.
74216 // Move orig point into its place to preserve point's history. #3683
74217 graph = graph.replace(point.update({ tags: {}, loc: node.loc }));
74218 target = target.replaceNode(node.id, point.id);
74219 graph = graph.replace(target);
74224 graph = graph.remove(removeNode);
74231 action.disabled = function(graph) {
74232 var geometries = groupEntitiesByGeometry(graph);
74233 if (geometries.point.length === 0 ||
74234 (geometries.area.length + geometries.line.length) !== 1 ||
74235 geometries.relation.length !== 0)
74236 return 'not_eligible';
74243 function actionMergePolygon(ids, newRelationId) {
74245 function groupEntities(graph) {
74246 var entities = ids.map(function (id) { return graph.entity(id); });
74247 return lodash.extend({
74251 }, lodash.groupBy(entities, function(entity) {
74252 if (entity.type === 'way' && entity.isClosed()) {
74253 return 'closedWay';
74254 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
74255 return 'multipolygon';
74263 var action = function(graph) {
74264 var entities = groupEntities(graph);
74266 // An array representing all the polygons that are part of the multipolygon.
74268 // Each element is itself an array of objects with an id property, and has a
74269 // locs property which is an array of the locations forming the polygon.
74270 var polygons = entities.multipolygon.reduce(function(polygons, m) {
74271 return polygons.concat(osmJoinWays(m.members, graph));
74272 }, []).concat(entities.closedWay.map(function(d) {
74273 var member = [{id: d.id}];
74274 member.nodes = graph.childNodes(d);
74278 // contained is an array of arrays of boolean values,
74279 // where contained[j][k] is true iff the jth way is
74280 // contained by the kth way.
74281 var contained = polygons.map(function(w, i) {
74282 return polygons.map(function(d, n) {
74283 if (i === n) return null;
74284 return geoPolygonContainsPolygon(
74285 lodash.map(d.nodes, 'loc'),
74286 lodash.map(w.nodes, 'loc'));
74290 // Sort all polygons as either outer or inner ways
74294 while (polygons.length) {
74295 extractUncontained(polygons);
74296 polygons = polygons.filter(isContained);
74297 contained = contained.filter(isContained).map(filterContained);
74300 function isContained(d, i) {
74301 return lodash.some(contained[i]);
74304 function filterContained(d) {
74305 return d.filter(isContained);
74308 function extractUncontained(polygons) {
74309 polygons.forEach(function(d, i) {
74310 if (!isContained(d, i)) {
74311 d.forEach(function(member) {
74315 role: outer ? 'outer' : 'inner'
74323 // Move all tags to one relation
74324 var relation = entities.multipolygon[0] ||
74325 osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
74327 entities.multipolygon.slice(1).forEach(function(m) {
74328 relation = relation.mergeTags(m.tags);
74329 graph = graph.remove(m);
74332 entities.closedWay.forEach(function(way) {
74333 function isThisOuter(m) {
74334 return m.id === way.id && m.role !== 'inner';
74336 if (members.some(isThisOuter)) {
74337 relation = relation.mergeTags(way.tags);
74338 graph = graph.replace(way.update({ tags: {} }));
74342 return graph.replace(relation.update({
74344 tags: lodash.omit(relation.tags, 'area')
74349 action.disabled = function(graph) {
74350 var entities = groupEntities(graph);
74351 if (entities.other.length > 0 ||
74352 entities.closedWay.length + entities.multipolygon.length < 2)
74353 return 'not_eligible';
74354 if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
74355 return 'incomplete_relation';
74362 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
74363 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
74365 // Permission is hereby granted, free of charge, to any person
74366 // obtaining a copy of this software and associated documentation files
74367 // (the "Software"), to deal in the Software without restriction,
74368 // including without limitation the rights to use, copy, modify, merge,
74369 // publish, distribute, sublicense, and/or sell copies of the Software,
74370 // and to permit persons to whom the Software is furnished to do so,
74371 // subject to the following conditions:
74373 // The above copyright notice and this permission notice shall be
74374 // included in all copies or substantial portions of the Software.
74376 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
74377 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
74378 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
74379 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
74380 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
74381 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
74382 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
74385 // source: https://bitbucket.org/lshift/synchrotron/src
74386 function longest_common_subsequence(file1, file2) {
74387 /* Text diff algorithm following Hunt and McIlroy 1976.
74388 * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
74389 * comparison, Bell Telephone Laboratories CSTR #41 (1976)
74390 * http://www.cs.dartmouth.edu/~doug/
74392 * Expects two arrays of strings.
74394 var equivalenceClasses;
74399 var c, i, j, jX, r, s;
74401 equivalenceClasses = {};
74402 for (j = 0; j < file2.length; j++) {
74404 if (equivalenceClasses[line]) {
74405 equivalenceClasses[line].push(j);
74407 equivalenceClasses[line] = [j];
74411 candidates = [{file1index: -1,
74415 for (i = 0; i < file1.length; i++) {
74417 file2indices = equivalenceClasses[line] || [];
74422 for (jX = 0; jX < file2indices.length; jX++) {
74423 j = file2indices[jX];
74425 for (s = 0; s < candidates.length; s++) {
74426 if ((candidates[s].file2index < j) &&
74427 ((s === candidates.length - 1) ||
74428 (candidates[s + 1].file2index > j)))
74432 if (s < candidates.length) {
74433 newCandidate = {file1index: i,
74435 chain: candidates[s]};
74436 if (r === candidates.length) {
74437 candidates.push(c);
74443 if (r === candidates.length) {
74444 break; // no point in examining further (j)s
74452 // At this point, we know the LCS: it's in the reverse of the
74453 // linked-list through .chain of
74454 // candidates[candidates.length - 1].
74456 return candidates[candidates.length - 1];
74469 function diff_indices(file1, file2) {
74470 // We apply the LCS to give a simple representation of the
74471 // offsets and lengths of mismatched chunks in the input
74472 // files. This is used by diff3_merge_indices below.
74475 var tail1 = file1.length;
74476 var tail2 = file2.length;
74478 for (var candidate = longest_common_subsequence(file1, file2);
74479 candidate !== null;
74480 candidate = candidate.chain)
74482 var mismatchLength1 = tail1 - candidate.file1index - 1;
74483 var mismatchLength2 = tail2 - candidate.file2index - 1;
74484 tail1 = candidate.file1index;
74485 tail2 = candidate.file2index;
74487 if (mismatchLength1 || mismatchLength2) {
74488 result.push({file1: [tail1 + 1, mismatchLength1],
74489 file2: [tail2 + 1, mismatchLength2]});
74497 function diff3_merge_indices (a, o, b) {
74498 // Given three files, A, O, and B, where both A and B are
74499 // independently derived from O, returns a fairly complicated
74500 // internal representation of merge decisions it's taken. The
74501 // interested reader may wish to consult
74503 // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
74504 // Formal Investigation of Diff3." In Arvind and Prasad,
74505 // editors, Foundations of Software Technology and Theoretical
74506 // Computer Science (FSTTCS), December 2007.
74508 // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
74511 var m1 = diff_indices(o, a);
74512 var m2 = diff_indices(o, b);
74515 function addHunk(h, side) {
74516 hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
74518 for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
74519 for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
74523 var commonOffset = 0;
74524 function copyCommon(targetOffset) {
74525 if (targetOffset > commonOffset) {
74526 result.push([1, commonOffset, targetOffset - commonOffset]);
74527 commonOffset = targetOffset;
74531 for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
74532 var firstHunkIndex = hunkIndex;
74533 var hunk = hunks[hunkIndex];
74534 var regionLhs = hunk[0];
74535 var regionRhs = regionLhs + hunk[2];
74536 while (hunkIndex < hunks.length - 1) {
74537 var maybeOverlapping = hunks[hunkIndex + 1];
74538 var maybeLhs = maybeOverlapping[0];
74539 if (maybeLhs > regionRhs) break;
74540 regionRhs = maybeLhs + maybeOverlapping[2];
74544 copyCommon(regionLhs);
74545 if (firstHunkIndex === hunkIndex) {
74546 // The "overlap" was only one hunk long, meaning that
74547 // there's no conflict here. Either a and o were the
74548 // same, or b and o were the same.
74550 result.push([hunk[1], hunk[3], hunk[4]]);
74553 // A proper conflict. Determine the extents of the
74554 // regions involved from a, o and b. Effectively merge
74555 // all the hunks on the left into one giant hunk, and
74556 // do the same for the right; then, correct for skew
74557 // in the regions of o that each side changed, and
74558 // report appropriate spans for the three sides.
74560 0: [a.length, -1, o.length, -1],
74561 2: [b.length, -1, o.length, -1]
74563 for (i = firstHunkIndex; i <= hunkIndex; i++) {
74565 var side = hunk[1];
74566 var r = regions[side];
74567 var oLhs = hunk[0];
74568 var oRhs = oLhs + hunk[2];
74569 var abLhs = hunk[3];
74570 var abRhs = abLhs + hunk[4];
74571 r[0] = Math.min(abLhs, r[0]);
74572 r[1] = Math.max(abRhs, r[1]);
74573 r[2] = Math.min(oLhs, r[2]);
74574 r[3] = Math.max(oRhs, r[3]);
74576 var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
74577 var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
74578 var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
74579 var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
74582 regionLhs, regionRhs - regionLhs,
74583 bLhs, bRhs - bLhs]);
74585 commonOffset = regionRhs;
74588 copyCommon(o.length);
74592 function diff3_merge (a, o, b, excludeFalseConflicts) {
74593 // Applies the output of Diff3.diff3_merge_indices to actually
74594 // construct the merged file; the returned result alternates
74595 // between "ok" and "conflict" blocks.
74598 var files = [a, o, b];
74599 var indices = diff3_merge_indices(a, o, b);
74602 function flushOk() {
74603 if (okLines.length) {
74604 result.push({ok: okLines});
74608 function pushOk(xs) {
74609 for (var j = 0; j < xs.length; j++) {
74610 okLines.push(xs[j]);
74614 function isTrueConflict(rec) {
74615 if (rec[2] !== rec[6]) return true;
74618 for (var j = 0; j < rec[2]; j++) {
74619 if (a[j + aoff] !== b[j + boff]) return true;
74624 for (var i = 0; i < indices.length; i++) {
74625 var x = indices[i];
74628 if (excludeFalseConflicts && !isTrueConflict(x)) {
74629 pushOk(files[0].slice(x[1], x[1] + x[2]));
74632 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
74634 o: o.slice(x[3], x[3] + x[4]),
74636 b: b.slice(x[5], x[5] + x[6]),
74640 pushOk(files[side].slice(x[1], x[1] + x[2]));
74648 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
74649 var option = 'safe', // 'safe', 'force_local', 'force_remote'
74654 return lodash.isFunction(formatUser) ? formatUser(d) : d;
74658 function mergeLocation(remote, target) {
74659 function pointEqual(a, b) {
74660 var epsilon = 1e-6;
74661 return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
74664 if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
74667 if (option === 'force_remote') {
74668 return target.update({loc: remote.loc});
74671 conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
74676 function mergeNodes(base, remote, target) {
74677 if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
74680 if (option === 'force_remote') {
74681 return target.update({nodes: remote.nodes});
74684 var ccount = conflicts.length,
74685 o = base.nodes || [],
74686 a = target.nodes || [],
74687 b = remote.nodes || [],
74689 hunks = diff3_merge(a, o, b, true);
74691 for (var i = 0; i < hunks.length; i++) {
74692 var hunk = hunks[i];
74694 nodes.push.apply(nodes, hunk.ok);
74696 // for all conflicts, we can assume c.a !== c.b
74697 // because `diff3_merge` called with `true` option to exclude false conflicts..
74698 var c = hunk.conflict;
74699 if (lodash.isEqual(c.o, c.a)) { // only changed remotely
74700 nodes.push.apply(nodes, c.b);
74701 } else if (lodash.isEqual(c.o, c.b)) { // only changed locally
74702 nodes.push.apply(nodes, c.a);
74703 } else { // changed both locally and remotely
74704 conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
74710 return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
74714 function mergeChildren(targetWay, children, updates, graph) {
74715 function isUsed(node, targetWay) {
74716 var parentWays = lodash.map(graph.parentWays(node), 'id');
74717 return node.hasInterestingTags() ||
74718 lodash.without(parentWays, targetWay.id).length > 0 ||
74719 graph.parentRelations(node).length > 0;
74722 var ccount = conflicts.length;
74724 for (var i = 0; i < children.length; i++) {
74725 var id = children[i],
74726 node = graph.hasEntity(id);
74728 // remove unused childNodes..
74729 if (targetWay.nodes.indexOf(id) === -1) {
74730 if (node && !isUsed(node, targetWay)) {
74731 updates.removeIds.push(id);
74736 // restore used childNodes..
74737 var local = localGraph.hasEntity(id),
74738 remote = remoteGraph.hasEntity(id),
74741 if (option === 'force_remote' && remote && remote.visible) {
74742 updates.replacements.push(remote);
74744 } else if (option === 'force_local' && local) {
74745 target = osmEntity$$1(local);
74747 target = target.update({ version: remote.version });
74749 updates.replacements.push(target);
74751 } else if (option === 'safe' && local && remote && local.version !== remote.version) {
74752 target = osmEntity$$1(local, { version: remote.version });
74753 if (remote.visible) {
74754 target = mergeLocation(remote, target);
74756 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
74759 if (conflicts.length !== ccount) break;
74760 updates.replacements.push(target);
74768 function updateChildren(updates, graph) {
74769 for (var i = 0; i < updates.replacements.length; i++) {
74770 graph = graph.replace(updates.replacements[i]);
74772 if (updates.removeIds.length) {
74773 graph = actionDeleteMultiple(updates.removeIds)(graph);
74779 function mergeMembers(remote, target) {
74780 if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
74783 if (option === 'force_remote') {
74784 return target.update({members: remote.members});
74787 conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
74792 function mergeTags(base, remote, target) {
74793 function ignoreKey(k) {
74794 return lodash.includes(dataDiscarded, k);
74797 if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
74800 if (option === 'force_remote') {
74801 return target.update({tags: remote.tags});
74804 var ccount = conflicts.length,
74805 o = base.tags || {},
74806 a = target.tags || {},
74807 b = remote.tags || {},
74808 keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
74809 tags = lodash.clone(a),
74812 for (var i = 0; i < keys.length; i++) {
74815 if (o[k] !== b[k] && a[k] !== b[k]) { // changed remotely..
74816 if (o[k] !== a[k]) { // changed locally..
74817 conflicts.push(t('merge_remote_changes.conflict.tags',
74818 { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
74820 } else { // unchanged locally, accept remote change..
74821 if (b.hasOwnProperty(k)) {
74831 return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
74835 // `graph.base()` is the common ancestor of the two graphs.
74836 // `localGraph` contains user's edits up to saving
74837 // `remoteGraph` contains remote edits to modified nodes
74838 // `graph` must be a descendent of `localGraph` and may include
74839 // some conflict resolution actions performed on it.
74841 // --- ... --- `localGraph` -- ... -- `graph`
74843 // `graph.base()` --- ... --- `remoteGraph`
74845 var action = function(graph) {
74846 var updates = { replacements: [], removeIds: [] },
74847 base = graph.base().entities[id],
74848 local = localGraph.entity(id),
74849 remote = remoteGraph.entity(id),
74850 target = osmEntity$$1(local, { version: remote.version });
74853 if (!remote.visible) {
74854 if (option === 'force_remote') {
74855 return actionDeleteMultiple([id])(graph);
74857 } else if (option === 'force_local') {
74858 if (target.type === 'way') {
74859 target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
74860 graph = updateChildren(updates, graph);
74862 return graph.replace(target);
74865 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
74866 return graph; // do nothing
74871 if (target.type === 'node') {
74872 target = mergeLocation(remote, target);
74874 } else if (target.type === 'way') {
74875 // pull in any child nodes that may not be present locally..
74876 graph.rebase(remoteGraph.childNodes(remote), [graph], false);
74877 target = mergeNodes(base, remote, target);
74878 target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
74880 } else if (target.type === 'relation') {
74881 target = mergeMembers(remote, target);
74884 target = mergeTags(base, remote, target);
74886 if (!conflicts.length) {
74887 graph = updateChildren(updates, graph).replace(target);
74894 action.withOption = function(opt) {
74900 action.conflicts = function() {
74908 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
74909 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
74910 function actionMove(moveIds, tryDelta, projection, cache) {
74911 var delta = tryDelta;
74913 function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
74914 function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
74916 function setupCache(graph) {
74917 function canMove(nodeId) {
74918 // Allow movement of any node that is in the selectedIDs list..
74919 if (moveIds.indexOf(nodeId) !== -1) return true;
74921 // Allow movement of a vertex where 2 ways meet..
74922 var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
74923 if (parents.length < 3) return true;
74925 // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
74926 var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
74927 if (!parentsMoving) delete cache.moving[nodeId];
74929 return parentsMoving;
74932 function cacheEntities(ids) {
74933 ids.forEach(function(id) {
74934 if (cache.moving[id]) return;
74935 cache.moving[id] = true;
74937 var entity = graph.hasEntity(id);
74938 if (!entity) return;
74940 if (entity.type === 'node') {
74941 cache.nodes.push(id);
74942 cache.startLoc[id] = entity.loc;
74943 } else if (entity.type === 'way') {
74944 cache.ways.push(id);
74945 cacheEntities(entity.nodes);
74947 cacheEntities(entity.members.map(function(member) {
74954 function cacheIntersections(ids) {
74955 function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
74957 ids.forEach(function(id) {
74958 // consider only intersections with 1 moved and 1 unmoved way.
74959 var childNodes = graph.childNodes(graph.entity(id));
74960 childNodes.forEach(function(node) {
74961 var parents = graph.parentWays(node);
74962 if (parents.length !== 2) return;
74964 var moved = graph.entity(id),
74965 unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
74966 if (!unmoved) return;
74968 // exclude ways that are overly connected..
74969 if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
74971 if (moved.isArea() || unmoved.isArea()) return;
74973 cache.intersection[node.id] = {
74976 unmovedId: unmoved.id,
74977 movedIsEP: isEndpoint(moved, node.id),
74978 unmovedIsEP: isEndpoint(unmoved, node.id)
74990 cache.intersection = {};
74991 cache.replacedVertex = {};
74992 cache.startLoc = {};
74996 cacheEntities(moveIds);
74997 cacheIntersections(cache.ways);
74998 cache.nodes = lodash.filter(cache.nodes, canMove);
75005 // Place a vertex where the moved vertex used to be, to preserve way shape..
75006 function replaceMovedVertex(nodeId, wayId, graph, delta) {
75007 var way = graph.entity(wayId),
75008 moved = graph.entity(nodeId),
75009 movedIndex = way.nodes.indexOf(nodeId),
75010 len, prevIndex, nextIndex;
75012 if (way.isClosed()) {
75013 len = way.nodes.length - 1;
75014 prevIndex = (movedIndex + len - 1) % len;
75015 nextIndex = (movedIndex + len + 1) % len;
75017 len = way.nodes.length;
75018 prevIndex = movedIndex - 1;
75019 nextIndex = movedIndex + 1;
75022 var prev = graph.hasEntity(way.nodes[prevIndex]),
75023 next = graph.hasEntity(way.nodes[nextIndex]);
75025 // Don't add orig vertex at endpoint..
75026 if (!prev || !next) return graph;
75028 var key = wayId + '_' + nodeId,
75029 orig = cache.replacedVertex[key];
75032 cache.replacedVertex[key] = orig;
75033 cache.startLoc[orig.id] = cache.startLoc[nodeId];
75038 start = projection(cache.startLoc[nodeId]);
75039 end = projection.invert(vecAdd(start, delta));
75041 end = cache.startLoc[nodeId];
75043 orig = orig.move(end);
75045 var angle = Math.abs(geoAngle(orig, prev, projection) -
75046 geoAngle(orig, next, projection)) * 180 / Math.PI;
75048 // Don't add orig vertex if it would just make a straight line..
75049 if (angle > 175 && angle < 185) return graph;
75051 // Don't add orig vertex if another point is already nearby (within 10m)
75052 if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
75053 geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
75055 // moving forward or backward along way?
75056 var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
75057 p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
75058 d1 = geoPathLength(p1),
75059 d2 = geoPathLength(p2),
75060 insertAt = (d1 < d2) ? movedIndex : nextIndex;
75062 // moving around closed loop?
75063 if (way.isClosed() && insertAt === 0) insertAt = len;
75065 way = way.addNode(orig.id, insertAt);
75066 return graph.replace(orig).replace(way);
75070 // Reorder nodes around intersections that have moved..
75071 function unZorroIntersection(intersection, graph) {
75072 var vertex = graph.entity(intersection.nodeId),
75073 way1 = graph.entity(intersection.movedId),
75074 way2 = graph.entity(intersection.unmovedId),
75075 isEP1 = intersection.movedIsEP,
75076 isEP2 = intersection.unmovedIsEP;
75078 // don't move the vertex if it is the endpoint of both ways.
75079 if (isEP1 && isEP2) return graph;
75081 var nodes1 = lodash.without(graph.childNodes(way1), vertex),
75082 nodes2 = lodash.without(graph.childNodes(way2), vertex);
75084 if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
75085 if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
75087 var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
75088 edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
75091 // snap vertex to nearest edge (or some point between them)..
75092 if (!isEP1 && !isEP2) {
75093 var epsilon = 1e-4, maxIter = 10;
75094 for (var i = 0; i < maxIter; i++) {
75095 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
75096 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
75097 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
75098 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
75100 } else if (!isEP1) {
75106 graph = graph.replace(vertex.move(loc));
75108 // if zorro happened, reorder nodes..
75109 if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
75110 way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
75111 graph = graph.replace(way1);
75113 if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
75114 way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
75115 graph = graph.replace(way2);
75122 function cleanupIntersections(graph) {
75123 lodash.each(cache.intersection, function(obj) {
75124 graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
75125 graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
75126 graph = unZorroIntersection(obj, graph);
75133 // check if moving way endpoint can cross an unmoved way, if so limit delta..
75134 function limitDelta(graph) {
75135 lodash.each(cache.intersection, function(obj) {
75136 // Don't limit movement if this is vertex joins 2 endpoints..
75137 if (obj.movedIsEP && obj.unmovedIsEP) return;
75138 // Don't limit movement if this vertex is not an endpoint anyway..
75139 if (!obj.movedIsEP) return;
75141 var node = graph.entity(obj.nodeId),
75142 start = projection(node.loc),
75143 end = vecAdd(start, delta),
75144 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
75145 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
75146 function(loc) { return vecAdd(projection(loc), delta); }),
75147 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
75148 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
75149 hits = geoPathIntersections(movedPath, unmovedPath);
75151 for (var i = 0; i < hits.length; i++) {
75152 if (lodash.isEqual(hits[i], end)) continue;
75153 var edge = geoChooseEdge(unmovedNodes, end, projection);
75154 delta = vecSub(projection(edge.loc), start);
75160 var action = function(graph) {
75161 if (delta[0] === 0 && delta[1] === 0) return graph;
75165 if (!lodash.isEmpty(cache.intersection)) {
75169 lodash.each(cache.nodes, function(id) {
75170 var node = graph.entity(id),
75171 start = projection(node.loc),
75172 end = vecAdd(start, delta);
75173 graph = graph.replace(node.move(projection.invert(end)));
75176 if (!lodash.isEmpty(cache.intersection)) {
75177 graph = cleanupIntersections(graph);
75184 action.delta = function() {
75192 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
75193 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
75194 function actionMoveNode(nodeId, loc) {
75195 return function(graph) {
75196 return graph.replace(graph.entity(nodeId).move(loc));
75200 function actionNoop() {
75201 return function(graph) {
75207 * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
75209 function actionOrthogonalize(wayId, projection) {
75210 var threshold = 12, // degrees within right or straight to alter
75211 lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
75212 upperThreshold = Math.cos(threshold * Math.PI / 180);
75215 var action = function(graph, t) {
75216 if (t === null || !isFinite(t)) t = 1;
75217 t = Math.min(Math.max(+t, 0), 1);
75219 var way = graph.entity(wayId),
75220 nodes = graph.childNodes(way),
75221 points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
75222 corner = {i: 0, dotp: 1},
75224 node, loc, score, motions, i, j;
75226 if (points.length === 3) { // move only one vertex for right triangle
75227 for (i = 0; i < 1000; i++) {
75228 motions = points.map(calcMotion);
75229 points[corner.i] = addPoints(points[corner.i], motions[corner.i]);
75230 score = corner.dotp;
75231 if (score < epsilon) {
75236 node = graph.entity(nodes[corner.i].id);
75237 loc = projection.invert(points[corner.i]);
75238 graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
75242 originalPoints = lodash.clone(points);
75245 for (i = 0; i < 1000; i++) {
75246 motions = points.map(calcMotion);
75247 for (j = 0; j < motions.length; j++) {
75248 points[j] = addPoints(points[j],motions[j]);
75250 var newScore = squareness(points);
75251 if (newScore < score) {
75252 best = lodash.clone(points);
75255 if (score < epsilon) {
75262 for (i = 0; i < points.length; i++) {
75263 // only move the points that actually moved
75264 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
75265 loc = projection.invert(points[i]);
75266 node = graph.entity(nodes[i].id);
75267 graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
75271 // remove empty nodes on straight sections
75272 for (i = 0; t === 1 && i < points.length; i++) {
75273 node = graph.entity(nodes[i].id);
75275 if (graph.parentWays(node).length > 1 ||
75276 graph.parentRelations(node).length ||
75277 node.hasInterestingTags()) {
75281 var dotp = normalizedDotProduct(i, points);
75282 if (dotp < -1 + epsilon) {
75283 graph = actionDeleteNode(node.id)(graph);
75291 function calcMotion(b, i, array) {
75292 var a = array[(i - 1 + array.length) % array.length],
75293 c = array[(i + 1) % array.length],
75294 p = subtractPoints(a, b),
75295 q = subtractPoints(c, b),
75298 scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
75299 p = normalizePoint(p, 1.0);
75300 q = normalizePoint(q, 1.0);
75302 dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
75304 // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
75305 if (array.length > 3) {
75306 if (dotp < -0.707106781186547) {
75309 } else if (dotp && Math.abs(dotp) < corner.dotp) {
75311 corner.dotp = Math.abs(dotp);
75314 return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
75319 function squareness(points) {
75320 return points.reduce(function(sum, val, i, array) {
75321 var dotp = normalizedDotProduct(i, array);
75323 dotp = filterDotProduct(dotp);
75324 return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
75329 function normalizedDotProduct(i, points) {
75330 var a = points[(i - 1 + points.length) % points.length],
75332 c = points[(i + 1) % points.length],
75333 p = subtractPoints(a, b),
75334 q = subtractPoints(c, b);
75336 p = normalizePoint(p, 1.0);
75337 q = normalizePoint(q, 1.0);
75339 return p[0] * q[0] + p[1] * q[1];
75343 function subtractPoints(a, b) {
75344 return [a[0] - b[0], a[1] - b[1]];
75348 function addPoints(a, b) {
75349 return [a[0] + b[0], a[1] + b[1]];
75353 function normalizePoint(point, scale) {
75354 var vector = [0, 0];
75355 var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
75356 if (length !== 0) {
75357 vector[0] = point[0] / length;
75358 vector[1] = point[1] / length;
75361 vector[0] *= scale;
75362 vector[1] *= scale;
75368 function filterDotProduct(dotp) {
75369 if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
75377 action.disabled = function(graph) {
75378 var way = graph.entity(wayId),
75379 nodes = graph.childNodes(way),
75380 points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
75382 if (squareness(points)) {
75386 return 'not_squarish';
75390 action.transitionable = true;
75396 // Split a way at the given node.
75398 // Optionally, split only the given ways, if multiple ways share
75401 // This is the inverse of `iD.actionJoin`.
75403 // For testing convenience, accepts an ID to assign to the new way.
75404 // Normally, this will be undefined and the way will automatically
75405 // be assigned a new ID.
75408 // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
75410 function actionSplit(nodeId, newWayIds) {
75413 // if the way is closed, we need to search for a partner node
75414 // to split the way at.
75416 // The following looks for a node that is both far away from
75417 // the initial node in terms of way segment length and nearby
75418 // in terms of beeline-distance. This assures that areas get
75419 // split on the most "natural" points (independent of the number
75421 // For example: bone-shaped areas get split across their waist
75422 // line, circles across the diameter.
75423 function splitArea(nodes, idxA, graph) {
75424 var lengths = new Array(nodes.length),
75430 function wrap(index) {
75431 return utilWrap(index, nodes.length);
75434 function dist(nA, nB) {
75435 return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
75438 // calculate lengths
75440 for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
75441 length += dist(nodes[i], nodes[wrap(i-1)]);
75442 lengths[i] = length;
75446 for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
75447 length += dist(nodes[i], nodes[wrap(i+1)]);
75448 if (length < lengths[i])
75449 lengths[i] = length;
75452 // determine best opposite node to split
75453 for (i = 0; i < nodes.length; i++) {
75454 var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
75465 function split(graph, wayA, newWayId) {
75466 var wayB = osmWay({id: newWayId, tags: wayA.tags}),
75469 isArea = wayA.isArea(),
75470 isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
75472 if (wayA.isClosed()) {
75473 var nodes = wayA.nodes.slice(0, -1),
75474 idxA = lodash.indexOf(nodes, nodeId),
75475 idxB = splitArea(nodes, idxA, graph);
75478 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
75479 nodesB = nodes.slice(idxB, idxA + 1);
75481 nodesA = nodes.slice(idxA, idxB + 1);
75482 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
75485 var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
75486 nodesA = wayA.nodes.slice(0, idx + 1);
75487 nodesB = wayA.nodes.slice(idx);
75490 wayA = wayA.update({nodes: nodesA});
75491 wayB = wayB.update({nodes: nodesB});
75493 graph = graph.replace(wayA);
75494 graph = graph.replace(wayB);
75496 graph.parentRelations(wayA).forEach(function(relation) {
75497 if (relation.isRestriction()) {
75498 var via = relation.memberByRole('via');
75499 if (via && wayB.contains(via.id)) {
75500 relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
75501 graph = graph.replace(relation);
75504 if (relation === isOuter) {
75505 graph = graph.replace(relation.mergeTags(wayA.tags));
75506 graph = graph.replace(wayA.update({tags: {}}));
75507 graph = graph.replace(wayB.update({tags: {}}));
75513 role: relation.memberById(wayA.id).role
75516 graph = actionAddMember(relation.id, member)(graph);
75520 if (!isOuter && isArea) {
75521 var multipolygon = osmRelation({
75522 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
75524 {id: wayA.id, role: 'outer', type: 'way'},
75525 {id: wayB.id, role: 'outer', type: 'way'}
75528 graph = graph.replace(multipolygon);
75529 graph = graph.replace(wayA.update({tags: {}}));
75530 graph = graph.replace(wayB.update({tags: {}}));
75537 var action = function(graph) {
75538 var candidates = action.ways(graph);
75539 for (var i = 0; i < candidates.length; i++) {
75540 graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
75546 action.ways = function(graph) {
75547 var node = graph.entity(nodeId),
75548 parents = graph.parentWays(node),
75549 hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
75551 return parents.filter(function(parent) {
75552 if (wayIds && wayIds.indexOf(parent.id) === -1)
75555 if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
75558 if (parent.isClosed()) {
75562 for (var i = 1; i < parent.nodes.length - 1; i++) {
75563 if (parent.nodes[i] === nodeId) {
75573 action.disabled = function(graph) {
75574 var candidates = action.ways(graph);
75575 if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
75576 return 'not_eligible';
75580 action.limitWays = function(_) {
75581 if (!arguments.length) return wayIds;
75590 // Create a restriction relation for `turn`, which must have the following structure:
75593 // from: { node: <node ID>, way: <way ID> },
75594 // via: { node: <node ID> },
75595 // to: { node: <node ID>, way: <way ID> },
75596 // restriction: <'no_right_turn', 'no_left_turn', etc.>
75599 // This specifies a restriction of type `restriction` when traveling from
75600 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
75601 // (The action does not check that these entities form a valid intersection.)
75603 // If `restriction` is not provided, it is automatically determined by
75604 // osmInferRestriction.
75606 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
75607 // and `to.node` are used to determine which portion of the split ways become
75608 // members of the restriction.
75610 // For testing convenience, accepts an ID to assign to the new relation.
75611 // Normally, this will be undefined and the relation will automatically
75612 // be assigned a new ID.
75614 function actionRestrictTurn(turn, projection, restrictionId) {
75616 return function(graph) {
75617 var from = graph.entity(turn.from.way),
75618 via = graph.entity(turn.via.node),
75619 to = graph.entity(turn.to.way);
75621 function isClosingNode(way, nodeId) {
75622 return nodeId === way.first() && nodeId === way.last();
75625 function split(toOrFrom) {
75626 var newID = toOrFrom.newID || osmWay().id;
75627 graph = actionSplit(via.id, [newID])
75628 .limitWays([toOrFrom.way])(graph);
75630 var a = graph.entity(newID),
75631 b = graph.entity(toOrFrom.way);
75633 if (a.nodes.indexOf(toOrFrom.node) !== -1) {
75640 if (!from.affix(via.id) || isClosingNode(from, via.id)) {
75641 if (turn.from.node === turn.to.node) {
75643 from = to = split(turn.from)[0];
75644 } else if (turn.from.way === turn.to.way) {
75645 // Straight-on or circular
75646 var s = split(turn.from);
75651 from = split(turn.from)[0];
75655 if (!to.affix(via.id) || isClosingNode(to, via.id)) {
75656 to = split(turn.to)[0];
75659 return graph.replace(osmRelation({
75662 type: 'restriction',
75663 restriction: turn.restriction ||
75664 osmInferRestriction(
75672 {id: from.id, type: 'way', role: 'from'},
75673 {id: via.id, type: 'node', role: 'via'},
75674 {id: to.id, type: 'way', role: 'to'}
75680 function actionRevert(id) {
75681 var action = function(graph) {
75682 var entity = graph.hasEntity(id),
75683 base = graph.base().entities[id];
75685 if (entity && !base) { // entity will be removed..
75686 if (entity.type === 'node') {
75687 graph.parentWays(entity)
75688 .forEach(function(parent) {
75689 parent = parent.removeNode(id);
75690 graph = graph.replace(parent);
75692 if (parent.isDegenerate()) {
75693 graph = actionDeleteWay(parent.id)(graph);
75698 graph.parentRelations(entity)
75699 .forEach(function(parent) {
75700 parent = parent.removeMembersWithID(id);
75701 graph = graph.replace(parent);
75703 if (parent.isDegenerate()) {
75704 graph = actionDeleteRelation(parent.id)(graph);
75709 return graph.revert(id);
75715 function actionRotate(rotateIds, pivot, angle, projection) {
75717 var action = function(graph) {
75718 return graph.update(function(graph) {
75719 utilGetAllNodes(rotateIds, graph).forEach(function(node) {
75720 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
75721 graph = graph.replace(node.move(projection.invert(point)));
75730 * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
75732 function actionStraighten(wayId, projection) {
75734 function positionAlongWay(n, s, e) {
75735 return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) /
75736 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
75740 var action = function(graph, t) {
75741 if (t === null || !isFinite(t)) t = 1;
75742 t = Math.min(Math.max(+t, 0), 1);
75744 var way = graph.entity(wayId),
75745 nodes = graph.childNodes(way),
75746 points = nodes.map(function(n) { return projection(n.loc); }),
75747 startPoint = points[0],
75748 endPoint = points[points.length-1],
75752 for (i = 1; i < points.length-1; i++) {
75753 var node = nodes[i],
75756 if (t < 1 || graph.parentWays(node).length > 1 ||
75757 graph.parentRelations(node).length ||
75758 node.hasInterestingTags()) {
75760 var u = positionAlongWay(point, startPoint, endPoint),
75762 startPoint[0] + u * (endPoint[0] - startPoint[0]),
75763 startPoint[1] + u * (endPoint[1] - startPoint[1])
75765 loc2 = projection.invert(p);
75767 graph = graph.replace(node.move(geoInterp(node.loc, loc2, t)));
75771 if (toDelete.indexOf(node) === -1) {
75772 toDelete.push(node);
75777 for (i = 0; i < toDelete.length; i++) {
75778 graph = actionDeleteNode(toDelete[i].id)(graph);
75785 action.disabled = function(graph) {
75786 // check way isn't too bendy
75787 var way = graph.entity(wayId),
75788 nodes = graph.childNodes(way),
75789 points = nodes.map(function(n) { return projection(n.loc); }),
75790 startPoint = points[0],
75791 endPoint = points[points.length-1],
75792 threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
75795 if (threshold === 0) {
75796 return 'too_bendy';
75799 for (i = 1; i < points.length-1; i++) {
75800 var point = points[i],
75801 u = positionAlongWay(point, startPoint, endPoint),
75802 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
75803 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
75804 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
75806 // to bendy if point is off by 20% of total start/end distance in projected space
75807 if (isNaN(dist) || dist > threshold) {
75808 return 'too_bendy';
75814 action.transitionable = true;
75820 // Remove the effects of `turn.restriction` on `turn`, which must have the
75821 // following structure:
75824 // from: { node: <node ID>, way: <way ID> },
75825 // via: { node: <node ID> },
75826 // to: { node: <node ID>, way: <way ID> },
75827 // restriction: <relation ID>
75830 // In the simple case, `restriction` is a reference to a `no_*` restriction
75831 // on the turn itself. In this case, it is simply deleted.
75833 // The more complex case is where `restriction` references an `only_*`
75834 // restriction on a different turn in the same intersection. In that case,
75835 // that restriction is also deleted, but at the same time restrictions on
75836 // the turns other than the first two are created.
75838 function actionUnrestrictTurn(turn) {
75839 return function(graph) {
75840 return actionDeleteRelation(turn.restriction)(graph);
75844 /* Reflect the given area around its axis of symmetry */
75845 function actionReflect(reflectIds, projection) {
75846 var useLongAxis = true;
75849 // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
75850 // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
75851 function getSmallestSurroundingRectangle(graph, nodes) {
75852 var points = nodes.map(function(n) { return projection(n.loc); }),
75853 hull = d3polygonHull(points),
75854 centroid = d3polygonCentroid(hull),
75855 minArea = Infinity,
75860 for (var i = 0; i < hull.length - 1; i++) {
75861 var c2 = hull[i + 1],
75862 angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]),
75863 poly = geoRotate(hull, -angle, centroid),
75864 extent$$1 = poly.reduce(function(extent$$1, point) {
75865 return extent$$1.extend(geoExtent$$1(point));
75866 }, geoExtent$$1()),
75867 area$$1 = extent$$1.area();
75869 if (area$$1 < minArea) {
75871 ssrExtent = extent$$1;
75878 poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
75884 var action = function(graph, t) {
75885 if (t === null || !isFinite(t)) t = 1;
75886 t = Math.min(Math.max(+t, 0), 1);
75888 var nodes = utilGetAllNodes(reflectIds, graph),
75889 ssr = getSmallestSurroundingRectangle(graph, nodes);
75891 // Choose line pq = axis of symmetry.
75892 // The shape's surrounding rectangle has 2 axes of symmetry.
75893 // Reflect across the longer axis by default.
75894 var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2 ],
75895 q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2 ],
75896 p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2 ],
75897 q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ],
75900 var isLong = (geoEuclideanDistance(p1, q1) > geoEuclideanDistance(p2, q2));
75901 if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) {
75909 // reflect c across pq
75910 // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
75911 var dx = q[0] - p[0];
75912 var dy = q[1] - p[1];
75913 var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
75914 var b = 2 * dx * dy / (dx * dx + dy * dy);
75915 for (var i = 0; i < nodes.length; i++) {
75916 var node = nodes[i];
75917 var c = projection(node.loc);
75919 a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0],
75920 b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]
75922 var loc2 = projection.invert(c2);
75923 node = node.move(geoInterp(node.loc, loc2, t));
75924 graph = graph.replace(node);
75931 action.useLongAxis = function(_) {
75932 if (!arguments.length) return useLongAxis;
75938 action.transitionable = true;
75946 var index$17 = Object.freeze({
75947 d3combobox: d3combobox,
75948 d3geoTile: d3geoTile,
75949 d3keybinding: d3keybinding
75952 /* export some legacy symbols: */
75953 var Connection = services.osm;
75959 var iD = Object.freeze({
75960 Connection: Connection,
75965 Context: coreContext,
75966 setAreaKeys: setAreaKeys,
75967 Difference: coreDifference,
75968 Graph: coreGraph$$1,
75969 History: coreHistory,
75971 Entity: osmEntity$$1,
75973 Relation: osmRelation,
75975 BackgroundSource: rendererBackgroundSource,
75976 Background: rendererBackground,
75977 Features: rendererFeatures,
75979 TileLayer: rendererTileLayer,
75980 Detect: utilDetect,
75981 actionAddEntity: actionAddEntity,
75982 actionAddMember: actionAddMember,
75983 actionAddMidpoint: actionAddMidpoint,
75984 actionAddVertex: actionAddVertex,
75985 actionChangeMember: actionChangeMember,
75986 actionChangePreset: actionChangePreset,
75987 actionChangeTags: actionChangeTags,
75988 actionCircularize: actionCircularize,
75989 actionConnect: actionConnect,
75990 actionCopyEntities: actionCopyEntities,
75991 actionDeleteMember: actionDeleteMember,
75992 actionDeleteMultiple: actionDeleteMultiple,
75993 actionDeleteNode: actionDeleteNode,
75994 actionDeleteRelation: actionDeleteRelation,
75995 actionDeleteWay: actionDeleteWay,
75996 actionDeprecateTags: actionDeprecateTags,
75997 actionDiscardTags: actionDiscardTags,
75998 actionDisconnect: actionDisconnect,
75999 actionJoin: actionJoin,
76000 actionMerge: actionMerge,
76001 actionMergePolygon: actionMergePolygon,
76002 actionMergeRemoteChanges: actionMergeRemoteChanges,
76003 actionMove: actionMove,
76004 actionMoveNode: actionMoveNode,
76005 actionNoop: actionNoop,
76006 actionOrthogonalize: actionOrthogonalize,
76007 actionRestrictTurn: actionRestrictTurn,
76008 actionReverse: actionReverse,
76009 actionRevert: actionRevert,
76010 actionRotate: actionRotate,
76011 actionSplit: actionSplit,
76012 actionStraighten: actionStraighten,
76013 actionUnrestrictTurn: actionUnrestrictTurn,
76014 actionReflect: actionReflect,
76015 behaviorAddWay: behaviorAddWay,
76016 behaviorBreathe: behaviorBreathe,
76017 behaviorCopy: behaviorCopy,
76018 behaviorDrag: behaviorDrag,
76019 behaviorDrawWay: behaviorDrawWay,
76020 behaviorDraw: behaviorDraw,
76021 behaviorEdit: behaviorEdit,
76022 behaviorHash: behaviorHash,
76023 behaviorHover: behaviorHover,
76024 behaviorLasso: behaviorLasso,
76025 behaviorOperation: behaviorOperation,
76026 behaviorPaste: behaviorPaste,
76027 behaviorSelect: behaviorSelect,
76028 behaviorTail: behaviorTail,
76029 coreContext: coreContext,
76030 coreDifference: coreDifference,
76031 coreGraph: coreGraph$$1,
76032 coreHistory: coreHistory,
76033 coreTree: coreTree,
76034 dataFeatureIcons: dataFeatureIcons,
76036 dataWikipedia: dataWikipedia,
76037 dataSuggestions: dataSuggestions,
76038 dataAddressFormats: dataAddressFormats,
76039 dataDeprecated: dataDeprecated,
76040 dataDiscarded: dataDiscarded,
76041 dataLocales: dataLocales,
76042 dataPhoneFormats: dataPhoneFormats,
76043 dataImperial: dataImperial,
76044 dataDriveLeft: dataDriveLeft,
76046 geoAngle: geoAngle,
76047 geoChooseEdge: geoChooseEdge,
76048 geoCross: geoCross,
76049 geoEdgeEqual: geoEdgeEqual,
76050 geoEuclideanDistance: geoEuclideanDistance,
76051 geoExtent: geoExtent$$1,
76052 geoInterp: geoInterp,
76053 geoRawMercator: geoRawMercator,
76054 geoRoundCoords: geoRoundCoords,
76055 geoRotate: geoRotate,
76056 geoLatToMeters: geoLatToMeters,
76057 geoLineIntersection: geoLineIntersection,
76058 geoLonToMeters: geoLonToMeters,
76059 geoMetersToLat: geoMetersToLat,
76060 geoMetersToLon: geoMetersToLon,
76061 geoMetersToOffset: geoMetersToOffset,
76062 geoOffsetToMeters: geoOffsetToMeters,
76063 geoPathIntersections: geoPathIntersections,
76064 geoPathLength: geoPathLength,
76065 geoPointInPolygon: geoPointInPolygon,
76066 geoPolygonContainsPolygon: geoPolygonContainsPolygon,
76067 geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
76068 geoSphericalDistance: geoSphericalDistance,
76069 modeAddArea: modeAddArea$$1,
76070 modeAddLine: modeAddLine$$1,
76071 modeAddPoint: modeAddPoint$$1,
76072 modeBrowse: modeBrowse,
76073 modeDragNode: modeDragNode$$1,
76074 modeDrawArea: modeDrawArea,
76075 modeDrawLine: modeDrawLine,
76076 modeMove: modeMove$$1,
76077 modeRotate: modeRotate$$1,
76078 modeSave: modeSave$$1,
76079 modeSelect: modeSelect,
76080 operationCircularize: operationCircularize,
76081 operationContinue: operationContinue,
76082 operationDelete: operationDelete,
76083 operationDisconnect: operationDisconnect,
76084 operationMerge: operationMerge,
76085 operationMove: operationMove,
76086 operationOrthogonalize: operationOrthogonalize,
76087 operationReflectShort: operationReflectShort,
76088 operationReflectLong: operationReflectLong,
76089 operationReverse: operationReverse,
76090 operationRotate: operationRotate,
76091 operationSplit: operationSplit,
76092 operationStraighten: operationStraighten,
76093 osmChangeset: osmChangeset,
76094 osmEntity: osmEntity$$1,
76096 osmRelation: osmRelation,
76098 osmIntersection: osmIntersection,
76100 osmInferRestriction: osmInferRestriction,
76101 osmLanes: osmLanes,
76102 osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
76103 osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
76104 osmJoinWays: osmJoinWays,
76105 osmOneWayTags: osmOneWayTags,
76106 osmPavedTags: osmPavedTags,
76107 osmIsInterestingTag: osmIsInterestingTag,
76108 presetCategory: presetCategory,
76109 presetCollection: presetCollection,
76110 presetField: presetField,
76111 presetPreset: presetPreset,
76112 presetIndex: presetIndex,
76113 rendererBackgroundSource: rendererBackgroundSource,
76114 rendererBackground: rendererBackground,
76115 rendererFeatures: rendererFeatures,
76116 rendererMap: rendererMap,
76117 rendererTileLayer: rendererTileLayer,
76118 services: services,
76119 svgAreas: svgAreas$$1,
76120 svgDebug: svgDebug,
76124 svgLabels: svgLabels,
76125 svgLayers: svgLayers,
76126 svgLines: svgLines$$1,
76127 svgMapillaryImages: svgMapillaryImages,
76128 svgMapillarySigns: svgMapillarySigns,
76129 svgMidpoints: svgMidpoints$$1,
76130 svgOneWaySegments: svgOneWaySegments,
76133 svgPointTransform: svgPointTransform,
76134 svgPoints: svgPoints$$1,
76135 svgRelationMemberTags: svgRelationMemberTags,
76136 svgTagClasses: svgTagClasses,
76137 svgTurns: svgTurns,
76138 svgVertices: svgVertices$$1,
76139 uiFields: uiFields,
76140 uiFieldDefaultCheck: uiFieldCheck,
76141 uiFieldOnewayCheck: uiFieldCheck,
76142 uiFieldCheck: uiFieldCheck,
76143 uiFieldMultiCombo: uiFieldCombo,
76144 uiFieldNetworkCombo: uiFieldCombo,
76145 uiFieldSemiCombo: uiFieldCombo,
76146 uiFieldTypeCombo: uiFieldCombo,
76147 uiFieldCombo: uiFieldCombo,
76148 uiFieldUrl: uiFieldText,
76149 uiFieldNumber: uiFieldText,
76150 uiFieldTel: uiFieldText,
76151 uiFieldEmail: uiFieldText,
76152 uiFieldText: uiFieldText,
76153 uiFieldAccess: uiFieldAccess,
76154 uiFieldAddress: uiFieldAddress,
76155 uiFieldCycleway: uiFieldCycleway,
76156 uiFieldLanes: uiFieldLanes,
76157 uiFieldLocalized: uiFieldLocalized,
76158 uiFieldMaxspeed: uiFieldMaxspeed,
76159 uiFieldStructureRadio: uiFieldRadio,
76160 uiFieldRadio: uiFieldRadio,
76161 uiFieldRestrictions: uiFieldRestrictions,
76162 uiFieldTextarea: uiFieldTextarea,
76163 uiFieldWikipedia: uiFieldWikipedia,
76166 uiAccount: uiAccount,
76167 uiAttribution: uiAttribution,
76168 uiBackground: uiBackground,
76170 uiCommit: uiCommit,
76171 uiConfirm: uiConfirm,
76172 uiConflicts: uiConflicts,
76173 uiContributors: uiContributors,
76174 uiCurtain: uiCurtain,
76175 uiDisclosure: uiDisclosure,
76176 uiEditMenu: uiEditMenu,
76177 uiEntityEditor: uiEntityEditor,
76178 uiFeatureInfo: uiFeatureInfo,
76179 uiFeatureList: uiFeatureList,
76181 uiFullScreen: uiFullScreen,
76182 uiGeolocate: uiGeolocate,
76185 uiInspector: uiInspector,
76187 uiLoading: uiLoading,
76188 uiMapData: uiMapData,
76189 uiMapInMap: uiMapInMap,
76192 uiNotice: uiNotice,
76193 uiPreset: uiPreset,
76194 uiPresetIcon: uiPresetIcon,
76195 uiPresetList: uiPresetList,
76196 uiRadialMenu: uiRadialMenu,
76197 uiRawMemberEditor: uiRawMemberEditor,
76198 uiRawMembershipEditor: uiRawMembershipEditor,
76199 uiRawTagEditor: uiRawTagEditor,
76200 uiRestore: uiRestore,
76203 uiSelectionList: uiSelectionList,
76204 uiSidebar: uiSidebar,
76205 uiSourceSwitch: uiSourceSwitch,
76206 uiSpinner: uiSpinner,
76207 uiSplash: uiSplash,
76208 uiStatus: uiStatus,
76209 uiSuccess: uiSuccess,
76210 uiTagReference: uiTagReference,
76211 uiToggle: uiToggle,
76212 uiTooltipHtml: uiTooltipHtml,
76213 uiUndoRedo: uiUndoRedo,
76214 uiVersion: uiVersion,
76215 uiViewOnOSM: uiViewOnOSM,
76217 utilAsyncMap: utilAsyncMap,
76218 utilDisplayName: utilDisplayName,
76219 utilDisplayNameForPath: utilDisplayNameForPath,
76220 utilDisplayType: utilDisplayType,
76221 utilEditDistance: utilEditDistance,
76222 utilEntitySelector: utilEntitySelector,
76223 utilEntityOrMemberSelector: utilEntityOrMemberSelector,
76224 utilFastMouse: utilFastMouse,
76225 utilFunctor: utilFunctor,
76226 utilGetAllNodes: utilGetAllNodes,
76227 utilGetPrototypeOf: utilGetPrototypeOf,
76228 utilGetSetValue: utilGetSetValue,
76229 utilNoAuto: utilNoAuto,
76230 utilPrefixCSSProperty: utilPrefixCSSProperty,
76231 utilPrefixDOMProperty: utilPrefixDOMProperty,
76232 utilQsString: utilQsString,
76233 utilRebind: utilRebind,
76234 utilSetTransform: utilSetTransform,
76235 utilSessionMutex: utilSessionMutex,
76236 utilStringQs: utilStringQs,
76237 utilSuggestNames: utilSuggestNames,
76238 utilTagText: utilTagText,
76239 utilTriggerEvent: utilTriggerEvent,
76240 utilWrap: utilWrap,
76241 d3combobox: d3combobox,
76242 d3geoTile: d3geoTile,
76243 d3keybinding: d3keybinding,
76244 validationDeprecatedTag: validationDeprecatedTag,
76245 validationDisconnectedHighway: validationDisconnectedHighway,
76246 validationManyDeletions: validationManyDeletions,
76247 validationMissingTag: validationMissingTag,
76248 validationOldMultipolygon: validationOldMultipolygon,
76249 validationTagSuggestsArea: validationTagSuggestsArea
76255 //# sourceMappingURL=iD.js.map