From: Tom Hughes Date: Sun, 10 Jun 2018 16:02:12 +0000 (+0100) Subject: Merge branch 'master' into next X-Git-Tag: live~2981^2~6 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/d3700e6201b4b78a70bbb2941572edc985b63c2c?hp=2aca6920dc3488a381b275d21a31344da02029e6 Merge branch 'master' into next --- diff --git a/.rubocop.yml b/.rubocop.yml index 6f721998d..fc2b5cd85 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,26 +1,5 @@ inherit_from: .rubocop_todo.yml -AllCops: - Include: - - '**/*.gemspec' - - '**/*.podspec' - - '**/*.jbuilder' - - '**/*.rake' - - '**/*.opal' - - '**/config.ru' - - '**/Gemfile' - - '**/Rakefile' - - '**/Capfile' - - '**/Guardfile' - - '**/Podfile' - - '**/Thorfile' - - '**/Vagrantfile' - - '**/Berksfile' - - '**/Cheffile' - - '**/Vagabondfile' - - '**/Fastfile' - - '**/*.builder' - Rails: Enabled: true diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 5846de44f..da801d681 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -33,9 +33,9 @@ Lint/AssignmentInCondition: - 'app/controllers/application_controller.rb' - 'app/controllers/geocoder_controller.rb' - 'app/controllers/notes_controller.rb' - - 'app/controllers/trace_controller.rb' + - 'app/controllers/traces_controller.rb' - 'app/controllers/user_controller.rb' - - 'app/controllers/user_preference_controller.rb' + - 'app/controllers/user_preferences_controller.rb' - 'app/helpers/application_helper.rb' - 'app/helpers/browse_helper.rb' - 'app/models/client_application.rb' @@ -67,7 +67,7 @@ Metrics/AbcSize: # Offense count: 41 # Configuration parameters: CountComments, ExcludedMethods. Metrics/BlockLength: - Max: 250 + Max: 257 # Offense count: 12 # Configuration parameters: CountBlocks. diff --git a/CONFIGURE.md b/CONFIGURE.md index 3cbe31cb9..0b8af0483 100644 --- a/CONFIGURE.md +++ b/CONFIGURE.md @@ -86,6 +86,8 @@ potlatch2_key: "8lFmZPsagHV4l3rkAHq0hWY5vV3Ctl3oEFY1aXth" Follow the same process for registering and configuring iD (`id_key`) and the website/Notes (`oauth_key`), or to save time, simply reuse the same consumer key for each. +**NOTE:** If you forget to set up OAuth, then you will get an error message similar to `uninitialized constant ActionView::CompiledTemplates::ID_KEY`. + ## Troubleshooting Rails has its own log. To inspect the log, do this: diff --git a/Gemfile b/Gemfile index a9a6cb4b6..ef14d06c5 100644 --- a/Gemfile +++ b/Gemfile @@ -108,6 +108,8 @@ gem "logstasher" # Gems useful for development group :development do gem "annotate" + gem "better_errors" + gem "binding_of_caller" gem "listen" gem "vendorer" end diff --git a/Gemfile.lock b/Gemfile.lock index d1a9a0dd2..49f9b5977 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -44,17 +44,23 @@ GEM tzinfo (~> 1.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) - annotate (2.7.2) + annotate (2.7.3) activerecord (>= 3.2, < 6.0) rake (>= 10.4, < 13.0) arel (8.0.0) ast (2.4.0) - autoprefixer-rails (8.2.0) + autoprefixer-rails (8.5.1) execjs + better_errors (2.4.0) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) bigdecimal (1.1.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) builder (3.2.3) - canonical-rails (0.2.2) - rails (>= 4.1, < 5.2) + canonical-rails (0.2.3) + rails (>= 4.1, < 5.3) capybara (2.18.0) addressable mini_mime (>= 0.1.3) @@ -64,6 +70,7 @@ GEM xpath (>= 2.0, < 4.0) climate_control (0.2.0) cliver (0.3.2) + coderay (1.1.2) coffee-rails (4.2.2) coffee-script (>= 2.2.0) railties (>= 4.0.0) @@ -82,17 +89,18 @@ GEM tins (~> 1.6) crack (0.4.3) safe_yaml (~> 1.0.0) - crass (1.0.3) - dalli (2.7.6) + crass (1.0.4) + dalli (2.7.8) + debug_inspector (0.0.3) docile (1.1.5) dynamic_form (1.1.4) erubi (1.7.1) execjs (2.7.0) - exifr (1.3.3) - factory_bot (4.8.2) + exifr (1.3.4) + factory_bot (4.10.0) activesupport (>= 3.0.0) - factory_bot_rails (4.8.2) - factory_bot (~> 4.8.2) + factory_bot_rails (4.10.0) + factory_bot (~> 4.10.0) railties (>= 3.0.0) faraday (0.12.2) multipart-post (>= 1.2, < 3) @@ -121,7 +129,7 @@ GEM sprockets image_size (1.5.0) in_threads (1.5.0) - jquery-rails (4.3.1) + jquery-rails (4.3.3) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -164,7 +172,7 @@ GEM multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) - nio4r (2.3.0) + nio4r (2.3.1) nokogiri (1.8.2) mini_portile2 (~> 2.3.0) nokogumbo (1.5.0) @@ -184,7 +192,7 @@ GEM omniauth (1.8.1) hashie (>= 3.4.6, < 3.6.0) rack (>= 1.6.2, < 3) - omniauth-facebook (4.0.0) + omniauth-facebook (5.0.0) omniauth-oauth2 (~> 1.2) omniauth-github (1.3.0) omniauth (~> 1.5) @@ -216,25 +224,25 @@ GEM mimemagic (~> 0.3.0) terrapin (~> 0.6.0) parallel (1.12.1) - parser (2.5.0.5) + parser (2.5.1.0) ast (~> 2.4.0) pg (0.21.0) - poltergeist (1.17.0) - capybara (~> 2.1) + poltergeist (1.18.1) + capybara (>= 2.1, < 4) cliver (~> 0.3.1) websocket-driver (>= 0.2.0) powerpack (0.1.1) progress (3.4.0) psych (3.0.2) public_suffix (3.0.2) - puma (3.11.3) + puma (3.11.4) r2 (0.2.7) - rack (2.0.4) + rack (2.0.5) rack-cors (1.0.2) rack-openid (1.3.1) rack (>= 1.1.0) ruby-openid (>= 2.1.8) - rack-test (0.8.3) + rack-test (1.0.0) rack (>= 1.0, < 3) rack-uri_sanitizer (0.0.2) rails (5.1.5) @@ -280,7 +288,7 @@ GEM rack (>= 1.4) rinku (2.0.4) rotp (3.3.1) - rubocop (0.54.0) + rubocop (0.56.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) @@ -291,7 +299,7 @@ GEM ruby-progressbar (1.9.0) ruby_dep (1.5.0) safe_yaml (1.0.4) - sanitize (4.6.4) + sanitize (4.6.5) crass (~> 1.0.2) nokogiri (>= 1.4.4) nokogumbo (~> 1.4) @@ -306,8 +314,7 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - secure_headers (5.0.5) - useragent (>= 0.15.0) + secure_headers (6.0.0) simplecov (0.14.1) docile (~> 1.1.0) json (>= 1.8, < 3) @@ -333,21 +340,20 @@ GEM tins (1.16.3) tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (4.1.8) + uglifier (4.1.10) execjs (>= 0.3.0, < 3) - unicode-display_width (1.3.0) - useragent (0.16.10) + unicode-display_width (1.3.2) validates_email_format_of (1.6.3) i18n vendorer (0.1.16) - webmock (3.3.0) + webmock (3.4.1) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) - xpath (3.0.0) + xpath (3.1.0) nokogiri (~> 1.8) PLATFORMS @@ -359,7 +365,9 @@ DEPENDENCIES actionpack-page_caching annotate autoprefixer-rails + better_errors bigdecimal (~> 1.1.0) + binding_of_caller canonical-rails capybara (~> 2.13) coffee-rails (~> 4.2) @@ -417,4 +425,4 @@ DEPENDENCIES webmock BUNDLED WITH - 1.15.4 + 1.16.2 diff --git a/Vagrantfile b/Vagrantfile index f41f9676c..44d914d75 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -12,13 +12,13 @@ Vagrant.configure("2") do |config| # use third party image and NFS sharing for lxc config.vm.provider "lxc" do |_, override| - override.vm.box = "sputnik13/trusty64" + override.vm.box = "generic/ubuntu1604" override.vm.synced_folder ".", "/srv/openstreetmap-website", :type => "nfs" end # use third party image and NFS sharing for libvirt config.vm.provider "libvirt" do |_, override| - override.vm.box = "sputnik13/trusty64" + override.vm.box = "generic/ubuntu1604" override.vm.synced_folder ".", "/srv/openstreetmap-website", :type => "nfs" end diff --git a/Vendorfile b/Vendorfile index e57ab21fe..67307f844 100644 --- a/Vendorfile +++ b/Vendorfile @@ -68,5 +68,13 @@ folder 'vendor/assets' do folder 'javascripts' do file 'html5shiv.js', 'https://raw.githubusercontent.com/aFarkas/html5shiv/master/src/html5shiv.js' + file 'bowser.js', 'https://github.com/lancedikson/bowser/releases/download/1.9.3/bowser.js' + end + + folder 'swfobject' do + from 'git://github.com/swfobject/swfobject.git', :tag => '2.2' do + file 'expressInstall.swf', 'swfobject/expressInstall.swf' + file 'swfobject.js', 'swfobject/src/swfobject.js' + end end end diff --git a/app/assets/javascripts/edit/id.js.erb b/app/assets/javascripts/edit/id.js.erb index 983117183..a85fcef45 100644 --- a/app/assets/javascripts/edit/id.js.erb +++ b/app/assets/javascripts/edit/id.js.erb @@ -2,9 +2,9 @@ $(document).ready(function () { var id = $("#id-embed"); if (id.data("key")) { - var hashParams = OSM.params(location.hash.substring(1)), - mapParams = OSM.mapParams(), - params = {}; + var hashParams = OSM.params(location.hash.substring(1)); + var mapParams = OSM.mapParams(); + var params = {}; if (mapParams.object) { params.id = mapParams.object.type[0] + mapParams.object.id; @@ -20,8 +20,9 @@ $(document).ready(function () { if (hashParams.background) params.background = hashParams.background; if (hashParams.comment) params.comment = hashParams.comment; - if (hashParams.disable_features) params.disable_features = hashParams.disable_features; if (hashParams.hashtags) params.hashtags = hashParams.hashtags; + if (hashParams.source) params.source = hashParams.source; + if (hashParams.disable_features) params.disable_features = hashParams.disable_features; if (hashParams.offset) params.offset = hashParams.offset; if (hashParams.walkthrough) params.walkthrough = hashParams.walkthrough; diff --git a/app/assets/javascripts/index.js b/app/assets/javascripts/index.js index 4ea643b26..ccf4e561c 100644 --- a/app/assets/javascripts/index.js +++ b/app/assets/javascripts/index.js @@ -20,6 +20,7 @@ //= require index/changeset //= require index/query //= require router +//= require bowser $(document).ready(function () { var loaderTimeout; @@ -241,7 +242,7 @@ $(document).ready(function () { function remoteEditHandler(bbox, object) { var loaded = false, - url = "http://127.0.0.1:8111/load_and_zoom?", + url, query = { left: bbox.getWest() - 0.0001, top: bbox.getNorth() + 0.0001, @@ -249,6 +250,13 @@ $(document).ready(function () { bottom: bbox.getSouth() - 0.0001 }; + if (location.protocol === 'http' || + bowser.check({chrome: "53", firefox: "55"})) { + url = "http://127.0.0.1:8111/load_and_zoom?"; + } else { + url = "https://127.0.0.1:8112/load_and_zoom?"; + } + if (object) query.select = object.type + object.id; var iframe = $(''); + storageContainer.close(); + storageOwner = storageContainer.w.frames[0].document; + storageEl = storageOwner.createElement('div'); + } catch(e) { + // somehow ActiveXObject instantiation failed (perhaps some special + // security settings or otherwse), fall back to per-path storage + storageEl = doc.createElement('div'); + storageOwner = doc.body; + } + + return function(storeFunction) { + var args = [].slice.call(arguments, 0); + args.unshift(storageEl); + // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx + // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx + storageOwner.appendChild(storageEl); + storageEl.addBehavior('#default#userData'); + storageEl.load(storageName); + storeFunction.apply(this, args); + storageOwner.removeChild(storageEl); + return + } + } - d3_selectAll('.layer-mapillary-images .sequence') - .classed('highlighted', function(d) { return d.properties.key === hoveredSequenceKey; }) - .classed('selected', function(d) { return d.properties.key === selectedSequenceKey; }); + // cookieStorage is useful Safari private browser mode, where localStorage + // doesn't work but cookies do. This implementation is adopted from + // https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage - return this; - }, + var Global$4 = util.Global; + var trim$1 = util.trim; - updateDetections: function(d) { - if (!_mlyViewer || _mlyFallback) return; + var cookieStorage = { + name: 'cookieStorage', + read: read$3, + write: write$3, + each: each$5, + remove: remove$5, + clearAll: clearAll$3, + }; - var imageKey = d && d.key; - var detections = (imageKey && _mlyCache.detections[imageKey]) || []; + var doc$1 = Global$4.document; - forEach(detections, function(data, k) { - if (isEmpty(data)) { - loadDetection(k); - } else { - var tag = makeTag(data); - if (tag) { - var tagComponent = _mlyViewer.getComponent('tag'); - tagComponent.add([tag]); - } - } - }); + function read$3(key) { + if (!key || !_has(key)) { return null } + var regexpStr = "(?:^|.*;\\s*)" + + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"; + return unescape(doc$1.cookie.replace(new RegExp(regexpStr), "$1")) + } + function each$5(callback) { + var cookies = doc$1.cookie.split(/; ?/g); + for (var i = cookies.length - 1; i >= 0; i--) { + if (!trim$1(cookies[i])) { + continue + } + var kvp = cookies[i].split('='); + var key = unescape(kvp[0]); + var val = unescape(kvp[1]); + callback(val, key); + } + } - function loadDetection(detectionKey) { - var url = apibase + 'detections/'+ - detectionKey + '?' + utilQsString({ - client_id: clientId, - }); - - d3_request(url) - .mimeType('application/json') - .response(function(xhr) { - return JSON.parse(xhr.responseText); - }) - .get(function(err, data) { - if (!data || !data.properties) return; - - var imageKey = data.properties.image_key; - _mlyCache.detections[imageKey][detectionKey] = data; - - var selectedKey = _mlySelectedImage && _mlySelectedImage.key; - if (imageKey === selectedKey) { - var tag = makeTag(data); - if (tag) { - var tagComponent = _mlyViewer.getComponent('tag'); - tagComponent.add([tag]); - } - } - }); - } + function write$3(key, data) { + if(!key) { return } + doc$1.cookie = escape(key) + "=" + escape(data) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"; + } + function remove$5(key) { + if (!key || !_has(key)) { + return + } + doc$1.cookie = escape(key) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"; + } - function makeTag(data) { - var valueParts = data.properties.value.split('--'); - if (valueParts.length !== 3) return; - - var text = valueParts[1].replace(/-/g, ' '); - var tag; - - // Currently only two shapes - if (data.properties.shape.type === 'Polygon') { - var polygonGeometry = new Mapillary - .TagComponent - .PolygonGeometry(data.properties.shape.coordinates[0]); - - tag = new Mapillary.TagComponent.OutlineTag( - data.properties.key, - polygonGeometry, - { - text: text, - textColor: 0xffff00, - lineColor: 0xffff00, - lineWidth: 2, - fillColor: 0xffff00, - fillOpacity: 0.3, - } - ); - - } else if (data.properties.shape.type === 'Point') { - var pointGeometry = new Mapillary - .TagComponent - .PointGeometry(data.properties.shape.coordinates[0]); - - tag = new Mapillary.TagComponent.SpotTag( - data.properties.key, - pointGeometry, - { - text: text, - color: 0xffff00, - textColor: 0xffff00 - } - ); - } + function clearAll$3() { + each$5(function(_, key) { + remove$5(key); + }); + } - return tag; - } - }, + function _has(key) { + return (new RegExp("(?:^|;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(doc$1.cookie) + } + var Global$5 = util.Global; - cache: function() { - return _mlyCache; - }, + var sessionStorage_1 = { + name: 'sessionStorage', + read: read$4, + write: write$4, + each: each$6, + remove: remove$6, + clearAll: clearAll$4 + }; + function sessionStorage() { + return Global$5.sessionStorage + } - signDefs: function(_) { - if (!arguments.length) return _mlySignDefs; - _mlySignDefs = _; - return this; - } + function read$4(key) { + return sessionStorage().getItem(key) + } -}; + function write$4(key, data) { + return sessionStorage().setItem(key, data) + } -var apibase$1 = 'https://nominatim.openstreetmap.org/', - inflight = {}, - nominatimCache; + function each$6(fn) { + for (var i = sessionStorage().length - 1; i >= 0; i--) { + var key = sessionStorage().key(i); + fn(read$4(key), key); + } + } + function remove$6(key) { + return sessionStorage().removeItem(key) + } -var serviceNominatim = { + function clearAll$4() { + return sessionStorage().clear() + } - init: function() { - inflight = {}; - nominatimCache = rbush_1(); - }, + // memoryStorage is a useful last fallback to ensure that the store + // is functions (meaning store.get(), store.set(), etc will all function). + // However, stored values will not persist when the browser navigates to + // a new page or reloads the current page. + + var memoryStorage_1 = { + name: 'memoryStorage', + read: read$5, + write: write$5, + each: each$7, + remove: remove$7, + clearAll: clearAll$5, + }; - reset: function() { - forEach(inflight, function(req) { req.abort(); }); - inflight = {}; - nominatimCache = rbush_1(); - }, + var memoryStorage = {}; + function read$5(key) { + return memoryStorage[key] + } - countryCode: function (location, callback) { - this.reverse(location, function(err, result) { - if (err) { - return callback(err); - } else if (result.address) { - return callback(null, result.address.country_code); - } else { - return callback('Unable to geocode', null); - } - }); - }, + function write$5(key, data) { + memoryStorage[key] = data; + } + function each$7(callback) { + for (var key in memoryStorage) { + if (memoryStorage.hasOwnProperty(key)) { + callback(memoryStorage[key], key); + } + } + } - reverse: function (location, callback) { - var cached = nominatimCache.search( - { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] } - ); + function remove$7(key) { + delete memoryStorage[key]; + } - if (cached.length > 0) { - return callback(null, cached[0].data); - } + function clearAll$5(key) { + memoryStorage = {}; + } - var params = { zoom: 13, format: 'json', addressdetails: 1, lat: location[1], lon: location[0] }; - var url = apibase$1 + 'reverse?' + utilQsString(params); - if (inflight[url]) return; + var all$3 = [ + // Listed in order of usage preference + localStorage_1, + oldFFGlobalStorage, + oldIEUserDataStorage, + cookieStorage, + sessionStorage_1, + memoryStorage_1 + ]; - inflight[url] = d3_json(url, function(err, result) { - delete inflight[url]; + /* eslint-disable */ + + // json2.js + // 2016-10-28 + // Public Domain. + // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + // See http://www.JSON.org/js.html + // This code should be minified before deployment. + // See http://javascript.crockford.com/jsmin.html + + // USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + // NOT CONTROL. + + // This file creates a global JSON object containing two methods: stringify + // and parse. This file provides the ES5 JSON capability to ES3 systems. + // If a project might run on IE8 or earlier, then this file should be included. + // This file does nothing on ES5 systems. + + // JSON.stringify(value, replacer, space) + // value any JavaScript value, usually an object or array. + // replacer an optional parameter that determines how object + // values are stringified for objects. It can be a + // function or an array of strings. + // space an optional parameter that specifies the indentation + // of nested structures. If it is omitted, the text will + // be packed without extra whitespace. If it is a number, + // it will specify the number of spaces to indent at each + // level. If it is a string (such as "\t" or " "), + // it contains the characters used to indent at each level. + // This method produces a JSON text from a JavaScript value. + // When an object value is found, if the object contains a toJSON + // method, its toJSON method will be called and the result will be + // stringified. A toJSON method does not serialize: it returns the + // value represented by the name/value pair that should be serialized, + // or undefined if nothing should be serialized. The toJSON method + // will be passed the key associated with the value, and this will be + // bound to the value. + + // For example, this would serialize Dates as ISO strings. + + // Date.prototype.toJSON = function (key) { + // function f(n) { + // // Format integers to have at least two digits. + // return (n < 10) + // ? "0" + n + // : n; + // } + // return this.getUTCFullYear() + "-" + + // f(this.getUTCMonth() + 1) + "-" + + // f(this.getUTCDate()) + "T" + + // f(this.getUTCHours()) + ":" + + // f(this.getUTCMinutes()) + ":" + + // f(this.getUTCSeconds()) + "Z"; + // }; + + // You can provide an optional replacer method. It will be passed the + // key and value of each member, with this bound to the containing + // object. The value that is returned from your method will be + // serialized. If your method returns undefined, then the member will + // be excluded from the serialization. + + // If the replacer parameter is an array of strings, then it will be + // used to select the members to be serialized. It filters the results + // such that only members with keys listed in the replacer array are + // stringified. + + // Values that do not have JSON representations, such as undefined or + // functions, will not be serialized. Such values in objects will be + // dropped; in arrays they will be replaced with null. You can use + // a replacer function to replace those with JSON values. + + // JSON.stringify(undefined) returns undefined. + + // The optional space parameter produces a stringification of the + // value that is filled with line breaks and indentation to make it + // easier to read. + + // If the space parameter is a non-empty string, then that string will + // be used for indentation. If the space parameter is a number, then + // the indentation will be that many spaces. + + // Example: + + // text = JSON.stringify(["e", {pluribus: "unum"}]); + // // text is '["e",{"pluribus":"unum"}]' + + // text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t"); + // // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + // text = JSON.stringify([new Date()], function (key, value) { + // return this[key] instanceof Date + // ? "Date(" + this[key] + ")" + // : value; + // }); + // // text is '["Date(---current time---)"]' + + // JSON.parse(text, reviver) + // This method parses a JSON text to produce an object or array. + // It can throw a SyntaxError exception. + + // The optional reviver parameter is a function that can filter and + // transform the results. It receives each of the keys and values, + // and its return value is used instead of the original value. + // If it returns what it received, then the structure is not modified. + // If it returns undefined then the member is deleted. + + // Example: + + // // Parse the text. Values that look like ISO date strings will + // // be converted to Date objects. + + // myData = JSON.parse(text, function (key, value) { + // var a; + // if (typeof value === "string") { + // a = + // /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + // if (a) { + // return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + // +a[5], +a[6])); + // } + // } + // return value; + // }); + + // myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + // var d; + // if (typeof value === "string" && + // value.slice(0, 5) === "Date(" && + // value.slice(-1) === ")") { + // d = new Date(value.slice(5, -1)); + // if (d) { + // return d; + // } + // } + // return value; + // }); + + // This is a reference implementation. You are free to copy, modify, or + // redistribute. + + /*jslint + eval, for, this + */ + + /*property + JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf + */ + + + // Create a JSON object only if one does not already exist. We create the + // methods in a closure to avoid creating global variables. + + if (typeof JSON !== "object") { + JSON = {}; + } - if (err) { - return callback(err); - } else if (result && result.error) { - return callback(result.error); - } + (function () { - var extent = geoExtent$$1(location).padByMeters(200); - nominatimCache.insert(assign(extent.bbox(), {data: result})); + var rx_one = /^[\],:{}\s]*$/; + var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; + var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; + var rx_four = /(?:^|:|,)(?:\s*\[)+/g; + var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - callback(null, result); - }); - }, + function f(n) { + // Format integers to have at least two digits. + return n < 10 + ? "0" + n + : n; + } + function this_value() { + return this.valueOf(); + } - search: function (val, callback) { - var searchVal = encodeURIComponent(val); - var url = apibase$1 + 'search/' + searchVal + '?limit=10&format=json'; - if (inflight[url]) return; + if (typeof Date.prototype.toJSON !== "function") { - inflight[url] = d3_json(url, function(err, result) { - delete inflight[url]; - callback(err, result); - }); - } + Date.prototype.toJSON = function () { -}; + return isFinite(this.valueOf()) + ? this.getUTCFullYear() + "-" + + f(this.getUTCMonth() + 1) + "-" + + f(this.getUTCDate()) + "T" + + f(this.getUTCHours()) + ":" + + f(this.getUTCMinutes()) + ":" + + f(this.getUTCSeconds()) + "Z" + : null; + }; -var apibase$2 = 'https://openstreetcam.org', - maxResults$1 = 1000, - tileZoom$1 = 14, - dispatch$2 = dispatch('loadedImages'), - imgZoom = d3_zoom() - .extent([[0, 0], [320, 240]]) - .translateExtent([[0, 0], [320, 240]]) - .scaleExtent([1, 15]) - .on('zoom', zoomPan), - _oscCache, - _oscSelectedImage; + Boolean.prototype.toJSON = this_value; + Number.prototype.toJSON = this_value; + String.prototype.toJSON = this_value; + } + var gap; + var indent; + var meta; + var rep; -function abortRequest$1(i) { - i.abort(); -} + function quote(string) { -function nearNullIsland$1(x, y, z) { - if (z >= 7) { - var center = Math.pow(2, z - 1), - width = Math.pow(2, z - 6), - min$$1 = center - (width / 2), - max$$1 = center + (width / 2) - 1; - return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1; - } - return false; -} - - -function maxPageAtZoom$1(z) { - if (z < 15) return 2; - if (z === 15) return 5; - if (z === 16) return 10; - if (z === 17) return 20; - if (z === 18) return 40; - if (z > 18) return 80; -} - - -function getTiles$1(projection) { - var s = projection.scale() * 2 * Math.PI, - z = Math.max(Math.log(s) / Math.log(2) - 8, 0), - ts = 256 * Math.pow(2, z - tileZoom$1), - origin = [ - s / 2 - projection.translate()[0], - s / 2 - projection.translate()[1]]; - - return d3geoTile() - .scaleExtent([tileZoom$1, tileZoom$1]) - .scale(s) - .size(projection.clipExtent()[1]) - .translate(projection.translate())() - .map(function(tile) { - var x = tile[0] * ts - origin[0], - y = tile[1] * ts - origin[1]; - - return { - id: tile.toString(), - xyz: tile, - extent: geoExtent$$1( - projection.invert([x, y + ts]), - projection.invert([x + ts, y]) - ) - }; - }); -} + // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe escape + // sequences. + rx_escapable.lastIndex = 0; + return rx_escapable.test(string) + ? "\"" + string.replace(rx_escapable, function (a) { + var c = meta[a]; + return typeof c === "string" + ? c + : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4); + }) + "\"" + : "\"" + string + "\""; + } -function loadTiles$1(which, url, projection) { - var s = projection.scale() * 2 * Math.PI, - currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0)); - var tiles = getTiles$1(projection).filter(function(t) { - return !nearNullIsland$1(t.xyz[0], t.xyz[1], t.xyz[2]); - }); + function str(key, holder) { - filter(which.inflight, function(v, k) { - var wanted = find$1(tiles, function(tile) { return k === (tile.id + ',0'); }); - if (!wanted) delete which.inflight[k]; - return !wanted; - }).map(abortRequest$1); + // Produce a string from holder[key]. - tiles.forEach(function(tile) { - loadNextTilePage$1(which, currZoom, url, tile); - }); -} - - -function loadNextTilePage$1(which, currZoom, url, tile) { - var cache = _oscCache[which]; - var bbox = tile.extent.bbox(); - var maxPages = maxPageAtZoom$1(currZoom); - var nextPage = cache.nextPage[tile.id] || 1; - var params = utilQsString({ - ipp: maxResults$1, - page: nextPage, - // client_id: clientId, - bbTopLeft: [bbox.maxY, bbox.minX].join(','), - bbBottomRight: [bbox.minY, bbox.maxX].join(',') - }, true); - - if (nextPage > maxPages) return; - - var id = tile.id + ',' + String(nextPage); - if (cache.loaded[id] || cache.inflight[id]) return; - - cache.inflight[id] = d3_request(url) - .mimeType('application/json') - .header('Content-type', 'application/x-www-form-urlencoded') - .response(function(xhr) { return JSON.parse(xhr.responseText); }) - .post(params, function(err, data) { - cache.loaded[id] = true; - delete cache.inflight[id]; - if (err || !data.currentPageItems || !data.currentPageItems.length) return; - - function localeDateString(s) { - if (!s) return null; - var detected = utilDetect(); - var options = { day: 'numeric', month: 'short', year: 'numeric' }; - var d = new Date(s); - if (isNaN(d.getTime())) return null; - return d.toLocaleDateString(detected.locale, options); - } + var i; // The loop counter. + var k; // The member key. + var v; // The member value. + var length; + var mind = gap; + var partial; + var value = holder[key]; - var features = data.currentPageItems.map(function(item) { - var loc = [+item.lng, +item.lat], - d; - - if (which === 'images') { - d = { - loc: loc, - key: item.id, - ca: +item.heading, - captured_at: localeDateString(item.shot_date || item.date_added), - captured_by: item.username, - imagePath: item.lth_name, - sequence_id: item.sequence_id, - sequence_index: +item.sequence_index - }; - - // cache sequence info - var seq = _oscCache.sequences[d.sequence_id]; - if (!seq) { - seq = { rotation: 0, images: [] }; - _oscCache.sequences[d.sequence_id] = seq; - } - seq.images[d.sequence_index] = d; - } - - return { - minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d - }; - }); + // If the value has a toJSON method, call it to obtain a replacement value. - cache.rtree.load(features); + if (value && typeof value === "object" && + typeof value.toJSON === "function") { + value = value.toJSON(key); + } - if (which === 'images') { - dispatch$2.call('loadedImages'); - } + // If we were called with a replacer function, then call the replacer to + // obtain a replacement value. - if (data.currentPageItems.length === maxResults$1) { // more pages to load - cache.nextPage[tile.id] = nextPage + 1; - loadNextTilePage$1(which, currZoom, url, tile); - } else { - cache.nextPage[tile.id] = Infinity; // no more pages to load - } - }); -} + if (typeof rep === "function") { + value = rep.call(holder, key, value); + } + // What happens next depends on the value's type. -// partition viewport into `psize` x `psize` regions -function partitionViewport$1(psize, projection) { - var dimensions = projection.clipExtent()[1]; - psize = psize || 16; - var cols = d3_range(0, dimensions[0], psize), - rows = d3_range(0, dimensions[1], psize), - partitions = []; + switch (typeof value) { + case "string": + return quote(value); - rows.forEach(function(y) { - cols.forEach(function(x) { - var min$$1 = [x, y + psize], - max$$1 = [x + psize, y]; - partitions.push( - geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1))); - }); - }); + case "number": + + // JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) + ? String(value) + : "null"; + + case "boolean": + case "null": + + // If the value is a boolean or null, convert it to a string. Note: + // typeof null does not produce "null". The case is included here in + // the remote chance that this gets fixed someday. + + return String(value); + + // If the type is "object", we might be dealing with an object or an array or + // null. + + case "object": + + // Due to a specification blunder in ECMAScript, typeof null is "object", + // so watch out for that case. + + if (!value) { + return "null"; + } + + // Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + + // Is the value an array? + + if (Object.prototype.toString.apply(value) === "[object Array]") { + + // The value is an array. Stringify every element. Use null as a placeholder + // for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || "null"; + } + + // Join all of the elements together, separated with commas, and wrap them in + // brackets. + + v = partial.length === 0 + ? "[]" + : gap + ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" + : "[" + partial.join(",") + "]"; + gap = mind; + return v; + } + + // If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === "object") { + length = rep.length; + for (i = 0; i < length; i += 1) { + if (typeof rep[i] === "string") { + k = rep[i]; + v = str(k, value); + if (v) { + partial.push(quote(k) + ( + gap + ? ": " + : ":" + ) + v); + } + } + } + } else { + + // Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + ( + gap + ? ": " + : ":" + ) + v); + } + } + } + } + + // Join all of the member texts together, separated with commas, + // and wrap them in braces. + + v = partial.length === 0 + ? "{}" + : gap + ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" + : "{" + partial.join(",") + "}"; + gap = mind; + return v; + } + } - return partitions; -} + // If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== "function") { + meta = { // table of character substitutions + "\b": "\\b", + "\t": "\\t", + "\n": "\\n", + "\f": "\\f", + "\r": "\\r", + "\"": "\\\"", + "\\": "\\\\" + }; + JSON.stringify = function (value, replacer, space) { + // The stringify method takes a value and an optional replacer, and an optional + // space parameter, and returns a JSON text. The replacer can be a function + // that can replace values, or an array of strings that will select the keys. + // A default replacer method can be provided. Use of the space parameter can + // produce text that is more easily readable. -// no more than `limit` results per partition. -function searchLimited$1(psize, limit, projection, rtree) { - limit = limit || 3; + var i; + gap = ""; + indent = ""; - var partitions = partitionViewport$1(psize, projection); - var results; + // If the space parameter is a number, make an indent string containing that + // many spaces. - results = flatten(map$3(partitions, function(extent$$1) { - return rtree.search(extent$$1.bbox()) - .slice(0, limit) - .map(function(d) { return d.data; }); - })); - return results; -} + if (typeof space === "number") { + for (i = 0; i < space; i += 1) { + indent += " "; + } + // If the space parameter is a string, it will be used as the indent string. -function zoomPan() { - var t = event.transform; - d3_select('#photoviewer .osc-image-wrap') - .call(utilSetTransform, t.x, t.y, t.k); -} + } else if (typeof space === "string") { + indent = space; + } + // If there is a replacer, it must be a function or an array. + // Otherwise, throw an error. -var serviceOpenstreetcam = { + rep = replacer; + if (replacer && typeof replacer !== "function" && + (typeof replacer !== "object" || + typeof replacer.length !== "number")) { + throw new Error("JSON.stringify"); + } - init: function() { - if (!_oscCache) { - this.reset(); - } + // Make a fake root object containing our value under the key of "". + // Return the result of stringifying the value. - this.event = utilRebind(this, dispatch$2, 'on'); - }, + return str("", {"": value}); + }; + } - reset: function() { - var cache = _oscCache; - if (cache) { - if (cache.images && cache.images.inflight) { - forEach(cache.images.inflight, abortRequest$1); - } - } + // If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== "function") { + JSON.parse = function (text, reviver) { + + // The parse method takes a text and an optional reviver function, and returns + // a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + + // The walk method is used to recursively walk the resulting structure so + // that modifications can be made. + + var k; + var v; + var value = holder[key]; + if (value && typeof value === "object") { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + + // Parsing happens in four stages. In the first stage, we replace certain + // Unicode characters with escape sequences. JavaScript handles many characters + // incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + rx_dangerous.lastIndex = 0; + if (rx_dangerous.test(text)) { + text = text.replace(rx_dangerous, function (a) { + return "\\u" + + ("0000" + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + + // In the second stage, we run the text against regular expressions that look + // for non-JSON patterns. We are especially concerned with "()" and "new" + // because they can cause invocation, and "=" because it can cause mutation. + // But just to be safe, we want to reject all unexpected forms. + + // We split the second stage into 4 regexp operations in order to work around + // crippling inefficiencies in IE's and Safari's regexp engines. First we + // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we + // replace all simple value tokens with "]" characters. Third, we delete all + // open brackets that follow a colon or comma or that begin the text. Finally, + // we look to see that the remaining characters are only whitespace or "]" or + // "," or ":" or "{" or "}". If that is so, then the text is safe for eval. + + if ( + rx_one.test( + text + .replace(rx_two, "@") + .replace(rx_three, "]") + .replace(rx_four, "") + ) + ) { + + // In the third stage we use the eval function to compile the text into a + // JavaScript structure. The "{" operator is subject to a syntactic ambiguity + // in JavaScript: it can begin a block or an object literal. We wrap the text + // in parens to eliminate the ambiguity. + + j = eval("(" + text + ")"); + + // In the optional fourth stage, we recursively walk the new structure, passing + // each name/value pair to a reviver function for possible transformation. + + return (typeof reviver === "function") + ? walk({"": j}, "") + : j; + } + + // If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError("JSON.parse"); + }; + } + }()); - _oscCache = { - images: { inflight: {}, loaded: {}, nextPage: {}, rtree: rbush_1() }, - sequences: {} - }; + var json2 = json2Plugin; - _oscSelectedImage = null; - }, + function json2Plugin() { + + return {} + } + var plugins = [json2]; - images: function(projection) { - var psize = 16, limit = 3; - return searchLimited$1(psize, limit, projection, _oscCache.images.rtree); - }, + var store_legacy = storeEngine.createStore(all$3, plugins); + // # osm-auth + // + // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo) + // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing), + // does not support custom headers, which this uses everywhere. + var osmAuth = function(o) { - sequences: function(projection) { - var viewport = projection.clipExtent(); - var min$$1 = [viewport[0][0], viewport[1][1]]; - var max$$1 = [viewport[1][0], viewport[0][1]]; - var bbox = geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)).bbox(); - var sequenceKeys = {}; - - // all sequences for images in viewport - _oscCache.images.rtree.search(bbox) - .forEach(function(d) { sequenceKeys[d.data.sequence_id] = true; }); - - // make linestrings from those sequences - var lineStrings = []; - Object.keys(sequenceKeys) - .forEach(function(sequenceKey) { - var seq = _oscCache.sequences[sequenceKey]; - var images = seq && seq.images; - if (images) { - lineStrings.push({ - type: 'LineString', - coordinates: images.map(function (d) { return d.loc; }).filter(Boolean), - properties: { key: sequenceKey } - }); - } - }); - return lineStrings; - }, + var oauth = {}; + // authenticated users will also have a request token secret, but it's + // not used in transactions with the server + oauth.authenticated = function() { + return !!(token('oauth_token') && token('oauth_token_secret')); + }; - loadImages: function(projection) { - var url = apibase$2 + '/1.0/list/nearby-photos/'; - loadTiles$1('images', url, projection); - }, + oauth.logout = function() { + token('oauth_token', ''); + token('oauth_token_secret', ''); + token('oauth_request_token_secret', ''); + return oauth; + }; + // TODO: detect lack of click event + oauth.authenticate = function(callback) { + if (oauth.authenticated()) return callback(); + + oauth.logout(); + + // ## Getting a request token + var params = timenonce(getAuth(o)), + url = o.url + '/oauth/request_token'; + + params.oauth_signature = ohauth_1.signature( + o.oauth_secret, '', + ohauth_1.baseString('POST', url, params)); + + if (!o.singlepage) { + // Create a 600x550 popup window in the center of the screen + var w = 600, h = 550, + settings = [ + ['width', w], ['height', h], + ['left', screen.width / 2 - w / 2], + ['top', screen.height / 2 - h / 2]].map(function(x) { + return x.join('='); + }).join(','), + popup = window.open('about:blank', 'oauth_window', settings); + } - loadViewer: function(context) { - var that = this; - - // add osc-wrapper - var wrap = d3_select('#photoviewer').selectAll('.osc-wrapper') - .data([0]); - - var wrapEnter = wrap.enter() - .append('div') - .attr('class', 'photo-wrapper osc-wrapper') - .classed('hide', true) - .call(imgZoom) - .on('dblclick.zoom', null); - - wrapEnter - .append('div') - .attr('class', 'photo-attribution fillD'); - - var controlsEnter = wrapEnter - .append('div') - .attr('class', 'osc-controls-wrap') - .append('div') - .attr('class', 'osc-controls'); - - controlsEnter - .append('button') - .on('click.back', step(-1)) - .text('◄'); - - controlsEnter - .append('button') - .on('click.rotate-ccw', rotate(-90)) - .text('⤿'); - - controlsEnter - .append('button') - .on('click.rotate-cw', rotate(90)) - .text('⤾'); - - controlsEnter - .append('button') - .on('click.forward', step(1)) - .text('►'); - - wrapEnter - .append('div') - .attr('class', 'osc-image-wrap'); - - - function rotate(deg) { - return function() { - if (!_oscSelectedImage) return; - var sequenceKey = _oscSelectedImage.sequence_id; - var sequence = _oscCache.sequences[sequenceKey]; - if (!sequence) return; - - var r = sequence.rotation || 0; - r += deg; - - if (r > 180) r -= 360; - if (r < -180) r += 360; - sequence.rotation = r; - - var wrap = d3_select('#photoviewer .osc-wrapper'); - - wrap - .transition() - .duration(100) - .call(imgZoom.transform, identity$7); - - wrap.selectAll('.osc-image') - .transition() - .duration(100) - .style('transform', 'rotate(' + r + 'deg)'); - }; - } + // Request a request token. When this is complete, the popup + // window is redirected to OSM's authorization page. + ohauth_1.xhr('POST', url, params, null, {}, reqTokenDone); + o.loading(); + + function reqTokenDone(err, xhr) { + o.done(); + if (err) return callback(err); + var resp = ohauth_1.stringQs(xhr.response); + token('oauth_request_token_secret', resp.oauth_token_secret); + var authorize_url = o.url + '/oauth/authorize?' + ohauth_1.qsString({ + oauth_token: resp.oauth_token, + oauth_callback: resolveUrl(o.landing) + }); + + if (o.singlepage) { + location.href = authorize_url; + } else { + popup.location = authorize_url; + } + } - function step(stepBy) { - return function() { - if (!_oscSelectedImage) return; - var sequenceKey = _oscSelectedImage.sequence_id; - var sequence = _oscCache.sequences[sequenceKey]; - if (!sequence) return; + // Called by a function in a landing page, in the popup window. The + // window closes itself. + window.authComplete = function(token) { + var oauth_token = ohauth_1.stringQs(token.split('?')[1]); + get_access_token(oauth_token.oauth_token); + delete window.authComplete; + }; - var nextIndex = _oscSelectedImage.sequence_index + stepBy; - var nextImage = sequence.images[nextIndex]; - if (!nextImage) return; + // ## Getting an request token + // + // At this point we have an `oauth_token`, brought in from a function + // call on a landing page popup. + function get_access_token(oauth_token) { + var url = o.url + '/oauth/access_token', + params = timenonce(getAuth(o)), + request_token_secret = token('oauth_request_token_secret'); + params.oauth_token = oauth_token; + params.oauth_signature = ohauth_1.signature( + o.oauth_secret, + request_token_secret, + ohauth_1.baseString('POST', url, params)); + + // ## Getting an access token + // + // The final token required for authentication. At this point + // we have a `request token secret` + ohauth_1.xhr('POST', url, params, null, {}, accessTokenDone); + o.loading(); + } - context.map().centerEase(nextImage.loc); + function accessTokenDone(err, xhr) { + o.done(); + if (err) return callback(err); + var access_token = ohauth_1.stringQs(xhr.response); + token('oauth_token', access_token.oauth_token); + token('oauth_token_secret', access_token.oauth_token_secret); + callback(null, oauth); + } + }; - that - .selectImage(nextImage) - .updateViewer(nextImage); - }; - } - }, + oauth.bootstrapToken = function(oauth_token, callback) { + // ## Getting an request token + // At this point we have an `oauth_token`, brought in from a function + // call on a landing page popup. + function get_access_token(oauth_token) { + var url = o.url + '/oauth/access_token', + params = timenonce(getAuth(o)), + request_token_secret = token('oauth_request_token_secret'); + params.oauth_token = oauth_token; + params.oauth_signature = ohauth_1.signature( + o.oauth_secret, + request_token_secret, + ohauth_1.baseString('POST', url, params)); + + // ## Getting an access token + // The final token required for authentication. At this point + // we have a `request token secret` + ohauth_1.xhr('POST', url, params, null, {}, accessTokenDone); + o.loading(); + } + function accessTokenDone(err, xhr) { + o.done(); + if (err) return callback(err); + var access_token = ohauth_1.stringQs(xhr.response); + token('oauth_token', access_token.oauth_token); + token('oauth_token_secret', access_token.oauth_token_secret); + callback(null, oauth); + } - showViewer: function() { - var viewer = d3_select('#photoviewer') - .classed('hide', false); + get_access_token(oauth_token); + }; - var isHidden = viewer.selectAll('.photo-wrapper.osc-wrapper.hide').size(); + // # xhr + // + // A single XMLHttpRequest wrapper that does authenticated calls if the + // user has logged in. + oauth.xhr = function(options, callback) { + if (!oauth.authenticated()) { + if (o.auto) { + return oauth.authenticate(run); + } else { + callback('not authenticated', null); + return; + } + } else { + return run(); + } - if (isHidden) { - viewer - .selectAll('.photo-wrapper:not(.osc-wrapper)') - .classed('hide', true); + function run() { + var params = timenonce(getAuth(o)), + oauth_token_secret = token('oauth_token_secret'), + url = (options.prefix !== false) ? o.url + options.path : options.path, + url_parts = url.replace(/#.*$/, '').split('?', 2), + base_url = url_parts[0], + query = (url_parts.length === 2) ? url_parts[1] : ''; + + // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1 + if ((!options.options || !options.options.header || + options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') && + options.content) { + params = immutable(params, ohauth_1.stringQs(options.content)); + } + + params.oauth_token = token('oauth_token'); + params.oauth_signature = ohauth_1.signature( + o.oauth_secret, + oauth_token_secret, + ohauth_1.baseString(options.method, base_url, immutable(params, ohauth_1.stringQs(query))) + ); + + return ohauth_1.xhr(options.method, url, params, options.content, options.options, done); + } - viewer - .selectAll('.photo-wrapper.osc-wrapper') - .classed('hide', false); - } + function done(err, xhr) { + if (err) return callback(err); + else if (xhr.responseXML) return callback(err, xhr.responseXML); + else return callback(err, xhr.response); + } + }; - return this; - }, + // pre-authorize this object, if we can just get a token and token_secret + // from the start + oauth.preauth = function(c) { + if (!c) return; + if (c.oauth_token) token('oauth_token', c.oauth_token); + if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret); + return oauth; + }; + oauth.options = function(_) { + if (!arguments.length) return o; - hideViewer: function() { - _oscSelectedImage = null; + o = _; + o.url = o.url || 'https://www.openstreetmap.org'; + o.landing = o.landing || 'land.html'; + o.singlepage = o.singlepage || false; - var viewer = d3_select('#photoviewer'); - if (!viewer.empty()) viewer.datum(null); + // Optional loading and loading-done functions for nice UI feedback. + // by default, no-ops + o.loading = o.loading || function() {}; + o.done = o.done || function() {}; - viewer - .classed('hide', true) - .selectAll('.photo-wrapper') - .classed('hide', true); + return oauth.preauth(o); + }; - d3_selectAll('.viewfield-group, .sequence, .icon-sign') - .classed('selected', false); + // 'stamp' an authentication object from `getAuth()` + // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce) + // and timestamp + function timenonce(o) { + o.oauth_timestamp = ohauth_1.timestamp(); + o.oauth_nonce = ohauth_1.nonce(); + return o; + } - return this.setStyles(null, true); - }, + // get/set tokens. These are prefixed with the base URL so that `osm-auth` + // can be used with multiple APIs and the keys in `localStorage` + // will not clash + var token; + if (store_legacy.enabled) { + token = function (x, y) { + if (arguments.length === 1) return store_legacy.get(o.url + x); + else if (arguments.length === 2) return store_legacy.set(o.url + x, y); + }; + } else { + var storage = {}; + token = function (x, y) { + if (arguments.length === 1) return storage[o.url + x]; + else if (arguments.length === 2) return storage[o.url + x] = y; + }; + } - updateViewer: function(d) { - var wrap = d3_select('#photoviewer .osc-wrapper'); - var imageWrap = wrap.selectAll('.osc-image-wrap'); - var attribution = wrap.selectAll('.photo-attribution').html(''); + // Get an authentication object. If you just add and remove properties + // from a single object, you'll need to use `delete` to make sure that + // it doesn't contain undesired properties for authentication + function getAuth(o) { + return { + oauth_consumer_key: o.oauth_consumer_key, + oauth_signature_method: 'HMAC-SHA1' + }; + } - wrap - .transition() - .duration(100) - .call(imgZoom.transform, identity$7); + // potentially pre-authorize + oauth.options(o); - imageWrap - .selectAll('.osc-image') - .remove(); + return oauth; + }; - if (d) { - var sequence = _oscCache.sequences[d.sequence_id]; - var r = (sequence && sequence.rotation) || 0; + var JXON = new (function () { + var + sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */ + aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i; - imageWrap - .append('img') - .attr('class', 'osc-image') - .attr('src', apibase$2 + '/' + d.imagePath) - .style('transform', 'rotate(' + r + 'deg)'); + function parseText (sValue) { + if (rIsNull.test(sValue)) { return null; } + if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; } + if (isFinite(sValue)) { return parseFloat(sValue); } + if (isFinite(Date.parse(sValue))) { return new Date(sValue); } + return sValue; + } - if (d.captured_by) { - attribution - .append('a') - .attr('class', 'captured_by') - .attr('target', '_blank') - .attr('href', 'https://openstreetcam.org/user/' + encodeURIComponent(d.captured_by)) - .text('@' + d.captured_by); + function EmptyTree () { } + EmptyTree.prototype.toString = function () { return 'null'; }; + EmptyTree.prototype.valueOf = function () { return null; }; - attribution - .append('span') - .text('|'); - } + function objectify (vValue) { + return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue); + } - if (d.captured_at) { - attribution - .append('span') - .attr('class', 'captured_at') - .text(d.captured_at); + function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) { + var + nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(), + bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2); - attribution - .append('span') - .text('|'); - } + var + sProp, vContent, nLength = 0, sCollectedTxt = '', + vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true; - attribution - .append('a') - .attr('class', 'image_link') - .attr('target', '_blank') - .attr('href', 'https://openstreetcam.org/details/' + d.sequence_id + '/' + d.sequence_index) - .text('openstreetcam.org'); + if (bChildren) { + for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) { + oNode = oParentNode.childNodes.item(nItem); + if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */ + else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */ + else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */ } - return this; - }, + } + var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt); - selectImage: function(d) { - _oscSelectedImage = d; - var viewer = d3_select('#photoviewer'); - if (!viewer.empty()) viewer.datum(d); + if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; } - this.setStyles(null, true); + for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) { + sProp = aCache[nElId].nodeName.toLowerCase(); + vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr); + if (vResult.hasOwnProperty(sProp)) { + if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; } + vResult[sProp].push(vContent); + } else { + vResult[sProp] = vContent; + nLength++; + } + } - d3_selectAll('.icon-sign') - .classed('selected', false); + if (bAttributes) { + var + nAttrLen = oParentNode.attributes.length, + sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult; - return this; - }, + for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) { + oAttrib = oParentNode.attributes.item(nAttrib); + oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim()); + } + + if (bNesteAttr) { + if (bFreeze) { Object.freeze(oAttrParent); } + vResult[sAttributesProp] = oAttrParent; + nLength -= nAttrLen - 1; + } + } + if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) { + vResult[sValueProp] = vBuiltVal; + } else if (!bHighVerb && nLength === 0 && sCollectedTxt) { + vResult = vBuiltVal; + } - getSelectedImage: function() { - return _oscSelectedImage; - }, + if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); } + aCache.length = nLevelStart; - getSequenceKeyForImage: function(d) { - return d && d.sequence_id; - }, + return vResult; + } + function loadObjTree (oXMLDoc, oParentEl, oParentObj) { + var vValue, oChild; - setStyles: function(hovered, reset) { - if (reset) { // reset all layers - d3_selectAll('.viewfield-group') - .classed('highlighted', false) - .classed('hovered', false) - .classed('selected', false); + if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) { + oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */ + } else if (oParentObj.constructor === Date) { + oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString())); + } - d3_selectAll('.sequence') - .classed('highlighted', false) - .classed('selected', false); - } + for (var sName in oParentObj) { + vValue = oParentObj[sName]; + if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */ + if (sName === sValueProp) { + if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); } + } else if (sName === sAttributesProp) { /* verbosity level is 3 */ + for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); } + } else if (sName.charAt(0) === sAttrPref) { + oParentEl.setAttribute(sName.slice(1), vValue); + } else if (vValue.constructor === Array) { + for (var nItem = 0; nItem < vValue.length; nItem++) { + oChild = oXMLDoc.createElement(sName); + loadObjTree(oXMLDoc, oChild, vValue[nItem]); + oParentEl.appendChild(oChild); + } + } else { + oChild = oXMLDoc.createElement(sName); + if (vValue instanceof Object) { + loadObjTree(oXMLDoc, oChild, vValue); + } else if (vValue !== null && vValue !== true) { + oChild.appendChild(oXMLDoc.createTextNode(vValue.toString())); + } + oParentEl.appendChild(oChild); + } + } + } - var hoveredImageKey = hovered && hovered.key; - var hoveredSequenceKey = this.getSequenceKeyForImage(hovered); - var hoveredSequence = hoveredSequenceKey && _oscCache.sequences[hoveredSequenceKey]; - var hoveredImageKeys = (hoveredSequence && hoveredSequence.images.map(function (d) { return d.key; })) || []; + this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) { + var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1; + return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3); + }; - var viewer = d3_select('#photoviewer'); - var selected = viewer.empty() ? undefined : viewer.datum(); - var selectedImageKey = selected && selected.key; - var selectedSequenceKey = this.getSequenceKeyForImage(selected); - var selectedSequence = selectedSequenceKey && _oscCache.sequences[selectedSequenceKey]; - var selectedImageKeys = (selectedSequence && selectedSequence.images.map(function (d) { return d.key; })) || []; + this.unbuild = function (oObjTree) { + var oNewDoc = document.implementation.createDocument('', '', null); + loadObjTree(oNewDoc, oNewDoc, oObjTree); + return oNewDoc; + }; - // highlight sibling viewfields on either the selected or the hovered sequences - var highlightedImageKeys = union(hoveredImageKeys, selectedImageKeys); + this.stringify = function (oObjTree) { + return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree)); + }; + })(); + + // var myObject = JXON.build(doc); + // we got our javascript object! try: alert(JSON.stringify(myObject)); + + // var newDoc = JXON.unbuild(myObject); + // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc)); + + var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded'); + var urlroot = 'https://www.openstreetmap.org'; + var oauth = osmAuth({ + url: urlroot, + oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT', + oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL', + loading: authLoading, + done: authDone + }); - d3_selectAll('.layer-openstreetcam-images .viewfield-group') - .classed('highlighted', function(d) { return highlightedImageKeys.indexOf(d.key) !== -1; }) - .classed('hovered', function(d) { return d.key === hoveredImageKey; }) - .classed('selected', function(d) { return d.key === selectedImageKey; }); + var _blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*']; + var _tiles = { loaded: {}, inflight: {} }; + var _changeset = {}; + var _entityCache = {}; + var _connectionID = 1; + var _tileZoom = 16; + var _rateLimitError; + var _userChangesets; + var _userDetails; + var _off; - d3_selectAll('.layer-openstreetcam-images .sequence') - .classed('highlighted', function(d) { return d.properties.key === hoveredSequenceKey; }) - .classed('selected', function(d) { return d.properties.key === selectedSequenceKey; }); - return this; - }, + function authLoading() { + dispatch$3.call('authLoading'); + } - cache: function() { - return _oscCache; - } - -}; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeCeil = Math.ceil, - nativeMax$4 = Math.max; - -/** - * Creates an array of elements split into groups the length of `size`. - * If `array` can't be split evenly, the final chunk will be the remaining - * elements. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to process. - * @param {number} [size=1] The length of each chunk - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Array} Returns the new array of chunks. - * @example - * - * _.chunk(['a', 'b', 'c', 'd'], 2); - * // => [['a', 'b'], ['c', 'd']] - * - * _.chunk(['a', 'b', 'c', 'd'], 3); - * // => [['a', 'b', 'c'], ['d']] - */ -function chunk(array, size, guard) { - if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { - size = 1; - } else { - size = nativeMax$4(toInteger(size), 0); - } - var length = array == null ? 0 : array.length; - if (!length || size < 1) { - return []; + function authDone() { + dispatch$3.call('authDone'); } - var index = 0, - resIndex = 0, - result = Array(nativeCeil(length / size)); - - while (index < length) { - result[resIndex++] = baseSlice(array, index, (index += size)); - } - return result; -} - -var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var hashes = createCommonjsModule(function (module, exports) { -/** - * jshashes - https://github.com/h2non/jshashes - * Released under the "New BSD" license - * - * Algorithms specification: - * - * MD5 - http://www.ietf.org/rfc/rfc1321.txt - * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html - * SHA1 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - * HMAC - http://www.ietf.org/rfc/rfc2104.txt - */ -(function() { - var Hashes; - - function utf8Encode(str) { - var x, y, output = '', - i = -1, - l; - - if (str && str.length) { - l = str.length; - while ((i += 1) < l) { - /* Decode utf-16 surrogate pairs */ - x = str.charCodeAt(i); - y = i + 1 < l ? str.charCodeAt(i + 1) : 0; - if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { - x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); - i += 1; - } - /* Encode output as utf-8 */ - if (x <= 0x7F) { - output += String.fromCharCode(x); - } else if (x <= 0x7FF) { - output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F), - 0x80 | (x & 0x3F)); - } else if (x <= 0xFFFF) { - output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), - 0x80 | ((x >>> 6) & 0x3F), - 0x80 | (x & 0x3F)); - } else if (x <= 0x1FFFFF) { - output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), - 0x80 | ((x >>> 12) & 0x3F), - 0x80 | ((x >>> 6) & 0x3F), - 0x80 | (x & 0x3F)); - } + + + function abortRequest$2(i) { + if (i) { + i.abort(); } - } - return output; } - function utf8Decode(str) { - var i, ac, c1, c2, c3, arr = [], - l; - i = ac = c1 = c2 = c3 = 0; - if (str && str.length) { - l = str.length; - str += ''; + function getLoc(attrs) { + var lon = attrs.lon && attrs.lon.value; + var lat = attrs.lat && attrs.lat.value; + return [parseFloat(lon), parseFloat(lat)]; + } + - while (i < l) { - c1 = str.charCodeAt(i); - ac += 1; - if (c1 < 128) { - arr[ac] = String.fromCharCode(c1); - i += 1; - } else if (c1 > 191 && c1 < 224) { - c2 = str.charCodeAt(i + 1); - arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); - i += 2; - } else { - c2 = str.charCodeAt(i + 1); - c3 = str.charCodeAt(i + 2); - arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - i += 3; - } + function getNodes(obj) { + var elems = obj.getElementsByTagName('nd'); + var nodes = new Array(elems.length); + for (var i = 0, l = elems.length; i < l; i++) { + nodes[i] = 'n' + elems[i].attributes.ref.value; } - } - return arr.join(''); + return nodes; } - /** - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ - function safe_add(x, y) { - var lsw = (x & 0xFFFF) + (y & 0xFFFF), - msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); + function getTags(obj) { + var elems = obj.getElementsByTagName('tag'); + var tags = {}; + for (var i = 0, l = elems.length; i < l; i++) { + var attrs = elems[i].attributes; + tags[attrs.k.value] = attrs.v.value; + } + + return tags; } - /** - * Bitwise rotate a 32-bit number to the left. - */ - function bit_rol(num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)); + function getMembers(obj) { + var elems = obj.getElementsByTagName('member'); + var members = new Array(elems.length); + for (var i = 0, l = elems.length; i < l; i++) { + var attrs = elems[i].attributes; + members[i] = { + id: attrs.type.value[0] + attrs.ref.value, + type: attrs.type.value, + role: attrs.role.value + }; + } + return members; } - /** - * Convert a raw string to a hex string - */ - function rstr2hex(input, hexcase) { - var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef', - output = '', - x, i = 0, - l = input.length; - for (; i < l; i += 1) { - x = input.charCodeAt(i); - output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F); - } - return output; + function getVisible(attrs) { + return (!attrs.visible || attrs.visible.value !== 'false'); } - /** - * Convert an array of big-endian words to a string - */ - function binb2rstr(input) { - var i, l = input.length * 32, - output = ''; - for (i = 0; i < l; i += 8) { - output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF); - } - return output; - } + var parsers = { + node: function nodeData(obj, uid) { + var attrs = obj.attributes; + return new osmNode({ + id:uid, + visible: getVisible(attrs), + version: attrs.version.value, + changeset: attrs.changeset && attrs.changeset.value, + timestamp: attrs.timestamp && attrs.timestamp.value, + user: attrs.user && attrs.user.value, + uid: attrs.uid && attrs.uid.value, + loc: getLoc(attrs), + tags: getTags(obj) + }); + }, - /** - * Convert an array of little-endian words to a string - */ + way: function wayData(obj, uid) { + var attrs = obj.attributes; + return new osmWay({ + id: uid, + visible: getVisible(attrs), + version: attrs.version.value, + changeset: attrs.changeset && attrs.changeset.value, + timestamp: attrs.timestamp && attrs.timestamp.value, + user: attrs.user && attrs.user.value, + uid: attrs.uid && attrs.uid.value, + tags: getTags(obj), + nodes: getNodes(obj), + }); + }, - function binl2rstr(input) { - var i, l = input.length * 32, - output = ''; - for (i = 0; i < l; i += 8) { - output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); - } - return output; - } + relation: function relationData(obj, uid) { + var attrs = obj.attributes; + return new osmRelation({ + id: uid, + visible: getVisible(attrs), + version: attrs.version.value, + changeset: attrs.changeset && attrs.changeset.value, + timestamp: attrs.timestamp && attrs.timestamp.value, + user: attrs.user && attrs.user.value, + uid: attrs.uid && attrs.uid.value, + tags: getTags(obj), + members: getMembers(obj) + }); + } + }; - /** - * Convert a raw string to an array of little-endian words - * Characters >255 have their high-byte silently ignored. - */ - function rstr2binl(input) { - var i, l = input.length * 8, - output = Array(input.length >> 2), - lo = output.length; - for (i = 0; i < lo; i += 1) { - output[i] = 0; - } - for (i = 0; i < l; i += 8) { - output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); - } - return output; - } + function parse(xml$$1, callback, options) { + options = assignIn({ cache: true }, options); + if (!xml$$1 || !xml$$1.childNodes) return; - /** - * Convert a raw string to an array of big-endian words - * Characters >255 have their high-byte silently ignored. - */ + var root = xml$$1.childNodes[0]; + var children = root.childNodes; - function rstr2binb(input) { - var i, l = input.length * 8, - output = Array(input.length >> 2), - lo = output.length; - for (i = 0; i < lo; i += 1) { - output[i] = 0; - } - for (i = 0; i < l; i += 8) { - output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); - } - return output; + function parseChild(child) { + var parser = parsers[child.nodeName]; + if (parser) { + var uid = osmEntity$$1.id.fromOSM(child.nodeName, child.attributes.id.value); + if (options.cache && _entityCache[uid]) { + return null; + } + return parser(child, uid); + } + } + + utilIdleWorker(children, parseChild, callback); } - /** - * Convert a raw string to an arbitrary string encoding - */ - function rstr2any(input, encoding) { - var divisor = encoding.length, - remainders = Array(), - i, q, x, ld, quotient, dividend, output, full_length; + var serviceOsm = { - /* Convert to an array of 16-bit big-endian values, forming the dividend */ - dividend = Array(Math.ceil(input.length / 2)); - ld = dividend.length; - for (i = 0; i < ld; i += 1) { - dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); - } + init: function() { + utilRebind(this, dispatch$3, 'on'); + }, - /** - * Repeatedly perform a long division. The binary array forms the dividend, - * the length of the encoding is the divisor. Once computed, the quotient - * forms the dividend for the next step. We stop when the dividend is zerHashes. - * All remainders are stored for later use. - */ - while (dividend.length > 0) { - quotient = Array(); - x = 0; - for (i = 0; i < dividend.length; i += 1) { - x = (x << 16) + dividend[i]; - q = Math.floor(x / divisor); - x -= q * divisor; - if (quotient.length > 0 || q > 0) { - quotient[quotient.length] = q; - } - } - remainders[remainders.length] = x; - dividend = quotient; - } - /* Convert the remainders to the output string */ - output = ''; - for (i = remainders.length - 1; i >= 0; i--) { - output += encoding.charAt(remainders[i]); - } + reset: function() { + _connectionID++; + _userChangesets = undefined; + _userDetails = undefined; + _rateLimitError = undefined; + forEach(_tiles.inflight, abortRequest$2); + if (_changeset.inflight) abortRequest$2(_changeset.inflight); + _tiles = { loaded: {}, inflight: {} }; + _changeset = {}; + _entityCache = {}; + return this; + }, - /* Append leading zero equivalents */ - full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2))); - for (i = output.length; i < full_length; i += 1) { - output = encoding[0] + output; - } - return output; - } - /** - * Convert a raw string to a base-64 string - */ + getConnectionId: function() { + return _connectionID; + }, - function rstr2b64(input, b64pad) { - var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', - output = '', - len = input.length, - i, j, triplet; - b64pad = b64pad || '='; - for (i = 0; i < len; i += 3) { - triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); - for (j = 0; j < 4; j += 1) { - if (i * 8 + j * 6 > input.length * 8) { - output += b64pad; - } else { - output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); - } - } - } - return output; - } - Hashes = { - /** - * @property {String} version - * @readonly - */ - VERSION: '1.0.6', - /** - * @member Hashes - * @class Base64 - * @constructor - */ - Base64: function() { - // private properties - var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', - pad = '=', // default pad according with the RFC standard - utf8 = true; // by default enable UTF-8 support encoding - - // public method for encoding - this.encode = function(input) { - var i, j, triplet, - output = '', - len = input.length; - - pad = pad || '='; - input = (utf8) ? utf8Encode(input) : input; - - for (i = 0; i < len; i += 3) { - triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); - for (j = 0; j < 4; j += 1) { - if (i * 8 + j * 6 > len * 8) { - output += pad; - } else { - output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); - } - } - } - return output; - }; + changesetURL: function(changesetId) { + return urlroot + '/changeset/' + changesetId; + }, - // public method for decoding - this.decode = function(input) { - // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - var i, o1, o2, o3, h1, h2, h3, h4, bits, ac, - dec = '', - arr = []; - if (!input) { - return input; - } - i = ac = 0; - input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '=' - //input += ''; + changesetsURL: function(center, zoom) { + var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)); + return urlroot + '/history#map=' + + Math.floor(zoom) + '/' + + center[1].toFixed(precision) + '/' + + center[0].toFixed(precision); + }, - do { // unpack four hexets into three octets using index points in b64 - h1 = tab.indexOf(input.charAt(i += 1)); - h2 = tab.indexOf(input.charAt(i += 1)); - h3 = tab.indexOf(input.charAt(i += 1)); - h4 = tab.indexOf(input.charAt(i += 1)); - bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + entityURL: function(entity) { + return urlroot + '/' + entity.type + '/' + entity.osmId(); + }, - o1 = bits >> 16 & 0xff; - o2 = bits >> 8 & 0xff; - o3 = bits & 0xff; - ac += 1; - if (h3 === 64) { - arr[ac] = String.fromCharCode(o1); - } else if (h4 === 64) { - arr[ac] = String.fromCharCode(o1, o2); + historyURL: function(entity) { + return urlroot + '/' + entity.type + '/' + entity.osmId() + '/history'; + }, + + + userURL: function(username) { + return urlroot + '/user/' + username; + }, + + + loadFromAPI: function(path, callback, options) { + options = assignIn({ cache: true }, options); + var that = this; + var cid = _connectionID; + + function done(err, xml$$1) { + if (that.getConnectionId() !== cid) { + if (callback) callback({ message: 'Connection Switched', status: -1 }); + return; + } + + var isAuthenticated = that.authenticated(); + + // 400 Bad Request, 401 Unauthorized, 403 Forbidden + // Logout and retry the request.. + if (isAuthenticated && err && (err.status === 400 || err.status === 401 || err.status === 403)) { + that.logout(); + that.loadFromAPI(path, callback); + + // else, no retry.. + } else { + // 509 Bandwidth Limit Exceeded, 429 Too Many Requests + // Set the rateLimitError flag and trigger a warning.. + if (!isAuthenticated && !_rateLimitError && err && + (err.status === 509 || err.status === 429)) { + _rateLimitError = err; + dispatch$3.call('change'); + } + + if (callback) { + if (err) return callback(err, null); + parse(xml$$1, function (entities) { + if (options.cache) { + for (var i in entities) { + _entityCache[entities[i].id] = true; + } + } + callback(null, entities); + }, options); + } + } + } + + if (this.authenticated()) { + return oauth.xhr({ method: 'GET', path: path }, done); } else { - arr[ac] = String.fromCharCode(o1, o2, o3); + var url = urlroot + path; + return d3_xml(url).get(done); } - } while (i < input.length); + }, - dec = arr.join(''); - dec = (utf8) ? utf8Decode(dec) : dec; - return dec; - }; + loadEntity: function(id, callback) { + var type = osmEntity$$1.id.type(id); + var osmID = osmEntity$$1.id.toOSM(id); + var options = { cache: false }; - // set custom pad string - this.setPad = function(str) { - pad = str || pad; - return this; - }; - // set custom tab string characters - this.setTab = function(str) { - tab = str || tab; - return this; - }; - this.setUTF8 = function(bool) { - if (typeof bool === 'boolean') { - utf8 = bool; - } - return this; - }; - }, + this.loadFromAPI( + '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''), + function(err, entities) { + if (callback) callback(err, { data: entities }); + }, + options + ); + }, - /** - * CRC-32 calculation - * @member Hashes - * @method CRC32 - * @static - * @param {String} str Input String - * @return {String} - */ - CRC32: function(str) { - var crc = 0, - x = 0, - y = 0, - table, i, iTop; - str = utf8Encode(str); - - table = [ - '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ', - '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ', - '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ', - '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ', - 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ', - '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ', - 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ', - '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ', - 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ', - '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ', - 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ', - '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ', - 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ', - '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ', - '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ', - '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ', - '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ', - 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ', - '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ', - 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ', - '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ', - 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ', - '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ', - 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ', - '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ', - 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D' - ].join(''); - - crc = crc ^ (-1); - for (i = 0, iTop = str.length; i < iTop; i += 1) { - y = (crc ^ str.charCodeAt(i)) & 0xFF; - x = '0x' + table.substr(y * 9, 8); - crc = (crc >>> 8) ^ x; - } - // always return a positive number (that's what >>> 0 does) - return (crc ^ (-1)) >>> 0; - }, - /** - * @member Hashes - * @class MD5 - * @constructor - * @param {Object} [config] - * - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * See for more infHashes. - */ - MD5: function(options) { - /** - * Private config properties. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} - */ - var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase - b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance - utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding - // privileged (public) methods - this.hex = function(s) { - return rstr2hex(rstr(s, utf8), hexcase); - }; - this.b64 = function(s) { - return rstr2b64(rstr(s), b64pad); - }; - this.any = function(s, e) { - return rstr2any(rstr(s, utf8), e); - }; - this.raw = function(s) { - return rstr(s, utf8); - }; - this.hex_hmac = function(k, d) { - return rstr2hex(rstr_hmac(k, d), hexcase); - }; - this.b64_hmac = function(k, d) { - return rstr2b64(rstr_hmac(k, d), b64pad); - }; - this.any_hmac = function(k, d, e) { - return rstr2any(rstr_hmac(k, d), e); - }; - /** - * Perform a simple self-test to see if the VM is working - * @return {String} Hexadecimal hash sample - */ - this.vm_test = function() { - return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; - }; - /** - * Enable/disable uppercase hexadecimal returned string - * @param {Boolean} - * @return {Object} this - */ - this.setUpperCase = function(a) { - if (typeof a === 'boolean') { - hexcase = a; - } - return this; - }; - /** - * Defines a base64 pad string - * @param {String} Pad - * @return {Object} this - */ - this.setPad = function(a) { - b64pad = a || b64pad; - return this; - }; - /** - * Defines a base64 pad string - * @param {Boolean} - * @return {Object} [this] - */ - this.setUTF8 = function(a) { - if (typeof a === 'boolean') { - utf8 = a; - } - return this; - }; + loadEntityVersion: function(id, version, callback) { + var type = osmEntity$$1.id.type(id); + var osmID = osmEntity$$1.id.toOSM(id); + var options = { cache: false }; - // private methods + this.loadFromAPI( + '/api/0.6/' + type + '/' + osmID + '/' + version, + function(err, entities) { + if (callback) callback(err, { data: entities }); + }, + options + ); + }, - /** - * Calculate the MD5 of a raw string - */ - function rstr(s) { - s = (utf8) ? utf8Encode(s) : s; - return binl2rstr(binl(rstr2binl(s), s.length * 8)); - } + loadMultiple: function(ids, callback) { + var that = this; - /** - * Calculate the HMAC-MD5, of a key and some data (raw strings) - */ + forEach(groupBy(uniq(ids), osmEntity$$1.id.type), function(v, k) { + var type = k + 's'; + var osmIDs = map$3(v, osmEntity$$1.id.toOSM); + var options = { cache: false }; - function rstr_hmac(key, data) { - var bkey, ipad, opad, hash, i; + forEach(chunk(osmIDs, 150), function(arr) { + that.loadFromAPI( + '/api/0.6/' + type + '?' + type + '=' + arr.join(), + function(err, entities) { + if (callback) callback(err, { data: entities }); + }, + options + ); + }); + }); + }, - key = (utf8) ? utf8Encode(key) : key; - data = (utf8) ? utf8Encode(data) : data; - bkey = rstr2binl(key); - if (bkey.length > 16) { - bkey = binl(bkey, key.length * 8); - } - ipad = Array(16), opad = Array(16); - for (i = 0; i < 16; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); - return binl2rstr(binl(opad.concat(hash), 512 + 128)); - } + authenticated: function() { + return oauth.authenticated(); + }, - /** - * Calculate the MD5 of an array of little-endian words, and a bit length. - */ - function binl(x, len) { - var i, olda, oldb, oldc, oldd, - a = 1732584193, - b = -271733879, - c = -1732584194, - d = 271733878; - - /* append padding */ - x[len >> 5] |= 0x80 << ((len) % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - - for (i = 0; i < x.length; i += 16) { - olda = a; - oldb = b; - oldc = c; - oldd = d; - - a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); - d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); - c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); - b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); - a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); - d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); - c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); - b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); - a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); - d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); - c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); - b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); - a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); - d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); - c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); - b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); - - a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); - d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); - c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); - b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); - a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); - d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); - c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); - b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); - a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); - d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); - c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); - b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); - a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); - d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); - c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); - b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); - - a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); - d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); - c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); - b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); - a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); - d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); - c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); - b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); - a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); - d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); - c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); - b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); - a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); - d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); - c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); - b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); - - a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); - d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); - c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); - b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); - a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); - d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); - c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); - b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); - a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); - d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); - c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); - b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); - a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); - d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); - c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); - b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - } - return Array(a, b, c, d); - } + putChangeset: function(changeset, changes, callback) { + if (_changeset.inflight) { + return callback({ message: 'Changeset already inflight', status: -2 }, changeset); + } - /** - * These functions implement the four basic operations the algorithm uses. - */ + var that = this; + var cid = _connectionID; + + if (_changeset.open) { // reuse existing open changeset.. + createdChangeset(null, _changeset.open); + } else { // open a new changeset.. + _changeset.inflight = oauth.xhr({ + method: 'PUT', + path: '/api/0.6/changeset/create', + options: { header: { 'Content-Type': 'text/xml' } }, + content: JXON.stringify(changeset.asJXON()) + }, createdChangeset); + } - function md5_cmn(q, a, b, x, s, t) { - return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); - } - function md5_ff(a, b, c, d, x, s, t) { - return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); - } + function createdChangeset(err, changesetID) { + _changeset.inflight = null; + + if (err) { + // 400 Bad Request, 401 Unauthorized, 403 Forbidden.. + if (err.status === 400 || err.status === 401 || err.status === 403) { + that.logout(); + } + return callback(err, changeset); + } + if (that.getConnectionId() !== cid) { + return callback({ message: 'Connection Switched', status: -1 }, changeset); + } + + _changeset.open = changesetID; + changeset = changeset.update({ id: changesetID }); + + // Upload the changeset.. + _changeset.inflight = oauth.xhr({ + method: 'POST', + path: '/api/0.6/changeset/' + changesetID + '/upload', + options: { header: { 'Content-Type': 'text/xml' } }, + content: JXON.stringify(changeset.osmChangeJXON(changes)) + }, uploadedChangeset); + } - function md5_gg(a, b, c, d, x, s, t) { - return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); - } - function md5_hh(a, b, c, d, x, s, t) { - return md5_cmn(b ^ c ^ d, a, b, x, s, t); - } + function uploadedChangeset(err) { + _changeset.inflight = null; - function md5_ii(a, b, c, d, x, s, t) { - return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); - } - }, - /** - * @member Hashes - * @class Hashes.SHA1 - * @param {Object} [config] - * @constructor - * - * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1 - * Version 2.2 Copyright Paul Johnston 2000 - 2009. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * See http://pajhome.org.uk/crypt/md5 for details. - */ - SHA1: function(options) { - /** - * Private config properties. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} - */ - var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase - b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance - utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding + if (err) return callback(err, changeset); - // public methods - this.hex = function(s) { - return rstr2hex(rstr(s, utf8), hexcase); - }; - this.b64 = function(s) { - return rstr2b64(rstr(s, utf8), b64pad); - }; - this.any = function(s, e) { - return rstr2any(rstr(s, utf8), e); - }; - this.raw = function(s) { - return rstr(s, utf8); - }; - this.hex_hmac = function(k, d) { - return rstr2hex(rstr_hmac(k, d)); - }; - this.b64_hmac = function(k, d) { - return rstr2b64(rstr_hmac(k, d), b64pad); - }; - this.any_hmac = function(k, d, e) { - return rstr2any(rstr_hmac(k, d), e); - }; - /** - * Perform a simple self-test to see if the VM is working - * @return {String} Hexadecimal hash sample - * @public - */ - this.vm_test = function() { - return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; - }; - /** - * @description Enable/disable uppercase hexadecimal returned string - * @param {boolean} - * @return {Object} this - * @public - */ - this.setUpperCase = function(a) { - if (typeof a === 'boolean') { - hexcase = a; - } - return this; - }; - /** - * @description Defines a base64 pad string - * @param {string} Pad - * @return {Object} this - * @public - */ - this.setPad = function(a) { - b64pad = a || b64pad; - return this; - }; - /** - * @description Defines a base64 pad string - * @param {boolean} - * @return {Object} this - * @public - */ - this.setUTF8 = function(a) { - if (typeof a === 'boolean') { - utf8 = a; - } - return this; - }; + // Upload was successful, safe to call the callback. + // Add delay to allow for postgres replication #1646 #2678 + window.setTimeout(function() { + callback(null, changeset); + }, 2500); + + _changeset.open = null; + + // At this point, we don't really care if the connection was switched.. + // Only try to close the changeset if we're still talking to the same server. + if (that.getConnectionId() === cid) { + // Still attempt to close changeset, but ignore response because #2667 + oauth.xhr({ + method: 'PUT', + path: '/api/0.6/changeset/' + changeset.id + '/close', + options: { header: { 'Content-Type': 'text/xml' } } + }, function() { return true; }); + } + } + }, + + + userDetails: function(callback) { + if (_userDetails) { + callback(undefined, _userDetails); + return; + } - // private methods + var that = this; + var cid = _connectionID; + + function done(err, user_details) { + if (err) { + // 400 Bad Request, 401 Unauthorized, 403 Forbidden.. + if (err.status === 400 || err.status === 401 || err.status === 403) { + that.logout(); + } + return callback(err); + } + if (that.getConnectionId() !== cid) { + return callback({ message: 'Connection Switched', status: -1 }); + } + + + var u = user_details.getElementsByTagName('user')[0]; + var img = u.getElementsByTagName('img'); + var image_url = ''; + + if (img && img[0] && img[0].getAttribute('href')) { + image_url = img[0].getAttribute('href'); + } + + var changesets = u.getElementsByTagName('changesets'); + var changesets_count = 0; + + if (changesets && changesets[0] && changesets[0].getAttribute('count')) { + changesets_count = changesets[0].getAttribute('count'); + } + + _userDetails = { + id: u.attributes.id.value, + display_name: u.attributes.display_name.value, + image_url: image_url, + changesets_count: changesets_count + }; + + callback(undefined, _userDetails); + } - /** - * Calculate the SHA-512 of a raw string - */ + oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done); + }, - function rstr(s) { - s = (utf8) ? utf8Encode(s) : s; - return binb2rstr(binb(rstr2binb(s), s.length * 8)); - } - /** - * Calculate the HMAC-SHA1 of a key and some data (raw strings) - */ + userChangesets: function(callback) { + if (_userChangesets) { + callback(undefined, _userChangesets); + return; + } - function rstr_hmac(key, data) { - var bkey, ipad, opad, i, hash; - key = (utf8) ? utf8Encode(key) : key; - data = (utf8) ? utf8Encode(data) : data; - bkey = rstr2binb(key); + var that = this; + var cid = _connectionID; + + this.userDetails(function(err, user) { + if (err) { + return callback(err); + } + if (that.getConnectionId() !== cid) { + return callback({ message: 'Connection Switched', status: -1 }); + } + + function done(err, changesets) { + if (err) { + // 400 Bad Request, 401 Unauthorized, 403 Forbidden.. + if (err.status === 400 || err.status === 401 || err.status === 403) { + that.logout(); + } + return callback(err); + } + if (that.getConnectionId() !== cid) { + return callback({ message: 'Connection Switched', status: -1 }); + } + + _userChangesets = Array.prototype.map.call( + changesets.getElementsByTagName('changeset'), + function (changeset) { + return { tags: getTags(changeset) }; + } + ).filter(function (changeset) { + var comment = changeset.tags.comment; + return comment && comment !== ''; + }); + + callback(undefined, _userChangesets); + } + + oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done); + }); + }, - if (bkey.length > 16) { - bkey = binb(bkey, key.length * 8); - } - ipad = Array(16), opad = Array(16); - for (i = 0; i < 16; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); - return binb2rstr(binb(opad.concat(hash), 512 + 160)); - } - /** - * Calculate the SHA-1 of an array of big-endian words, and a bit length - */ + status: function(callback) { + var that = this; + var cid = _connectionID; + + function done(xml$$1) { + if (that.getConnectionId() !== cid) { + return callback({ message: 'Connection Switched', status: -1 }, 'connectionSwitched'); + } + + // update blacklists + var elements = xml$$1.getElementsByTagName('blacklist'); + var regexes = []; + for (var i = 0; i < elements.length; i++) { + var regex = elements[i].getAttribute('regex'); // needs unencode? + if (regex) { + regexes.push(regex); + } + } + if (regexes.length) { + _blacklists = regexes; + } + + + if (_rateLimitError) { + callback(_rateLimitError, 'rateLimited'); + } else { + var apiStatus = xml$$1.getElementsByTagName('status'); + var val = apiStatus[0].getAttribute('api'); + + callback(undefined, val); + } + } - function binb(x, len) { - var i, j, t, olda, oldb, oldc, oldd, olde, - w = Array(80), - a = 1732584193, - b = -271733879, - c = -1732584194, - d = 271733878, - e = -1009589776; - - /* append padding */ - x[len >> 5] |= 0x80 << (24 - len % 32); - x[((len + 64 >> 9) << 4) + 15] = len; - - for (i = 0; i < x.length; i += 16) { - olda = a; - oldb = b; - oldc = c; - oldd = d; - olde = e; - - for (j = 0; j < 80; j += 1) { - if (j < 16) { - w[j] = x[i + j]; - } else { - w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); - } - t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), - safe_add(safe_add(e, w[j]), sha1_kt(j))); - e = d; - d = c; - c = bit_rol(b, 30); - b = a; - a = t; - } - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - e = safe_add(e, olde); - } - return Array(a, b, c, d, e); - } + d3_xml(urlroot + '/api/capabilities').get() + .on('load', done) + .on('error', callback); + }, - /** - * Perform the appropriate triplet combination function for the current - * iteration - */ - function sha1_ft(t, b, c, d) { - if (t < 20) { - return (b & c) | ((~b) & d); - } - if (t < 40) { - return b ^ c ^ d; - } - if (t < 60) { - return (b & c) | (b & d) | (c & d); - } - return b ^ c ^ d; - } + imageryBlacklists: function() { + return _blacklists; + }, - /** - * Determine the appropriate additive constant for the current iteration - */ - function sha1_kt(t) { - return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : - (t < 60) ? -1894007588 : -899497514; - } - }, - /** - * @class Hashes.SHA256 - * @param {config} - * - * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2 - * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * See http://pajhome.org.uk/crypt/md5 for details. - * Also http://anmar.eu.org/projects/jssha2/ - */ - SHA256: function(options) { - /** - * Private properties configuration variables. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - * @see this.setUpperCase() method - * @see this.setPad() method - */ - var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */ - b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', - /* base-64 pad character. Default '=' for strict RFC compliance */ - utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, - /* enable/disable utf8 encoding */ - sha256_K; + tileZoom: function(_) { + if (!arguments.length) return _tileZoom; + _tileZoom = _; + return this; + }, - /* privileged (public) methods */ - this.hex = function(s) { - return rstr2hex(rstr(s, utf8)); - }; - this.b64 = function(s) { - return rstr2b64(rstr(s, utf8), b64pad); - }; - this.any = function(s, e) { - return rstr2any(rstr(s, utf8), e); - }; - this.raw = function(s) { - return rstr(s, utf8); - }; - this.hex_hmac = function(k, d) { - return rstr2hex(rstr_hmac(k, d)); - }; - this.b64_hmac = function(k, d) { - return rstr2b64(rstr_hmac(k, d), b64pad); - }; - this.any_hmac = function(k, d, e) { - return rstr2any(rstr_hmac(k, d), e); - }; - /** - * Perform a simple self-test to see if the VM is working - * @return {String} Hexadecimal hash sample - * @public - */ - this.vm_test = function() { - return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; - }; - /** - * Enable/disable uppercase hexadecimal returned string - * @param {boolean} - * @return {Object} this - * @public - */ - this.setUpperCase = function(a) { - if (typeof a === 'boolean') { - hexcase = a; - } - return this; - }; - /** - * @description Defines a base64 pad string - * @param {string} Pad - * @return {Object} this - * @public - */ - this.setPad = function(a) { - b64pad = a || b64pad; - return this; - }; - /** - * Defines a base64 pad string - * @param {boolean} - * @return {Object} this - * @public - */ - this.setUTF8 = function(a) { - if (typeof a === 'boolean') { - utf8 = a; - } - return this; - }; - // private methods + loadTiles: function(projection, dimensions, callback) { + if (_off) return; - /** - * Calculate the SHA-512 of a raw string - */ + var that = this; + var s = projection.scale() * 2 * Math.PI; + var z = Math.max(Math.log(s) / Math.log(2) - 8, 0); + var ts = 256 * Math.pow(2, z - _tileZoom); + var origin = [ + s / 2 - projection.translate()[0], + s / 2 - projection.translate()[1] + ]; - function rstr(s, utf8) { - s = (utf8) ? utf8Encode(s) : s; - return binb2rstr(binb(rstr2binb(s), s.length * 8)); - } + var tiles = d3geoTile() + .scaleExtent([_tileZoom, _tileZoom]) + .scale(s) + .size(dimensions) + .translate(projection.translate())() + .map(function(tile) { + var x = tile[0] * ts - origin[0]; + var y = tile[1] * ts - origin[1]; + + return { + id: tile.toString(), + extent: geoExtent$$1( + projection.invert([x, y + ts]), + projection.invert([x + ts, y])) + }; + }); + + filter(_tiles.inflight, function(v, i) { + var wanted = find$1(tiles, function(tile) { + return i === tile.id; + }); + if (!wanted) delete _tiles.inflight[i]; + return !wanted; + }).map(abortRequest$2); + + tiles.forEach(function(tile) { + var id = tile.id; + + if (_tiles.loaded[id] || _tiles.inflight[id]) return; + + if (isEmpty(_tiles.inflight)) { + dispatch$3.call('loading'); + } + + _tiles.inflight[id] = that.loadFromAPI( + '/api/0.6/map?bbox=' + tile.extent.toParam(), + function(err, parsed) { + delete _tiles.inflight[id]; + if (!err) { + _tiles.loaded[id] = true; + } + + if (callback) { + callback(err, assignIn({ data: parsed }, tile)); + } + + if (isEmpty(_tiles.inflight)) { + dispatch$3.call('loaded'); + } + } + ); + }); + }, - /** - * Calculate the HMAC-sha256 of a key and some data (raw strings) - */ - function rstr_hmac(key, data) { - key = (utf8) ? utf8Encode(key) : key; - data = (utf8) ? utf8Encode(data) : data; - var hash, i = 0, - bkey = rstr2binb(key), - ipad = Array(16), - opad = Array(16); + switch: function(options) { + urlroot = options.urlroot; - if (bkey.length > 16) { - bkey = binb(bkey, key.length * 8); - } + oauth.options(assignIn({ + url: urlroot, + loading: authLoading, + done: authDone + }, options)); - for (; i < 16; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } + this.reset(); + this.userChangesets(function() {}); // eagerly load user details/changesets + dispatch$3.call('change'); + return this; + }, - hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); - return binb2rstr(binb(opad.concat(hash), 512 + 256)); - } - /* - * Main sha256 function, with its support functions - */ + toggle: function(_) { + _off = !_; + return this; + }, - function sha256_S(X, n) { - return (X >>> n) | (X << (32 - n)); - } - function sha256_R(X, n) { - return (X >>> n); - } + loadedTiles: function(_) { + if (!arguments.length) return _tiles.loaded; + _tiles.loaded = _; + return this; + }, - function sha256_Ch(x, y, z) { - return ((x & y) ^ ((~x) & z)); - } - function sha256_Maj(x, y, z) { - return ((x & y) ^ (x & z) ^ (y & z)); - } + logout: function() { + _userChangesets = undefined; + _userDetails = undefined; + oauth.logout(); + dispatch$3.call('change'); + return this; + }, - function sha256_Sigma0256(x) { - return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22)); - } - function sha256_Sigma1256(x) { - return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25)); - } + authenticate: function(callback) { + var that = this; + var cid = _connectionID; + _userChangesets = undefined; + _userDetails = undefined; + + function done(err, res) { + if (err) { + if (callback) callback(err); + return; + } + if (that.getConnectionId() !== cid) { + if (callback) callback({ message: 'Connection Switched', status: -1 }); + return; + } + _rateLimitError = undefined; + dispatch$3.call('change'); + if (callback) callback(err, res); + that.userChangesets(function() {}); // eagerly load user details/changesets + } - function sha256_Gamma0256(x) { - return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3)); + return oauth.authenticate(done); } + }; + + var apibase$3 = 'https://taginfo.openstreetmap.org/api/4/', + inflight$1 = {}, + popularKeys = {}, + taginfoCache = {}, + tag_sorts = { + point: 'count_nodes', + vertex: 'count_nodes', + area: 'count_ways', + line: 'count_ways' + }, + tag_sort_members = { + point: 'count_node_members', + vertex: 'count_node_members', + area: 'count_way_members', + line: 'count_way_members', + relation: 'count_relation_members' + }, + tag_filters = { + point: 'nodes', + vertex: 'nodes', + area: 'ways', + line: 'ways' + }, + tag_members_fractions = { + point: 'count_node_members_fraction', + vertex: 'count_node_members_fraction', + area: 'count_way_members_fraction', + line: 'count_way_members_fraction', + relation: 'count_relation_members_fraction' + }; + - function sha256_Gamma1256(x) { - return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10)); + function sets(params, n, o) { + if (params.geometry && o[params.geometry]) { + params[n] = o[params.geometry]; } + return params; + } - sha256_K = [ - 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, - 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, - 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, - 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, - 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, - 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, - 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998 - ]; - function binb(m, l) { - var HASH = [1779033703, -1150833019, 1013904242, -1521486534, - 1359893119, -1694144372, 528734635, 1541459225 - ]; - var W = new Array(64); - var a, b, c, d, e, f, g, h; - var i, j, T1, T2; - - /* append padding */ - m[l >> 5] |= 0x80 << (24 - l % 32); - m[((l + 64 >> 9) << 4) + 15] = l; - - for (i = 0; i < m.length; i += 16) { - a = HASH[0]; - b = HASH[1]; - c = HASH[2]; - d = HASH[3]; - e = HASH[4]; - f = HASH[5]; - g = HASH[6]; - h = HASH[7]; - - for (j = 0; j < 64; j += 1) { - if (j < 16) { - W[j] = m[j + i]; - } else { - W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), - sha256_Gamma0256(W[j - 15])), W[j - 16]); - } + function setFilter(params) { + return sets(params, 'filter', tag_filters); + } - T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), - sha256_K[j]), W[j]); - T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c)); - h = g; - g = f; - f = e; - e = safe_add(d, T1); - d = c; - c = b; - b = a; - a = safe_add(T1, T2); - } - - HASH[0] = safe_add(a, HASH[0]); - HASH[1] = safe_add(b, HASH[1]); - HASH[2] = safe_add(c, HASH[2]); - HASH[3] = safe_add(d, HASH[3]); - HASH[4] = safe_add(e, HASH[4]); - HASH[5] = safe_add(f, HASH[5]); - HASH[6] = safe_add(g, HASH[6]); - HASH[7] = safe_add(h, HASH[7]); - } - return HASH; - } - }, + function setSort(params) { + return sets(params, 'sortname', tag_sorts); + } - /** - * @class Hashes.SHA512 - * @param {config} - * - * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2 - * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * See http://pajhome.org.uk/crypt/md5 for details. - */ - SHA512: function(options) { - /** - * Private properties configuration variables. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - * @see this.setUpperCase() method - * @see this.setPad() method - */ - var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, - /* hexadecimal output case format. false - lowercase; true - uppercase */ - b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', - /* base-64 pad character. Default '=' for strict RFC compliance */ - utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, - /* enable/disable utf8 encoding */ - sha512_k; - /* privileged (public) methods */ - this.hex = function(s) { - return rstr2hex(rstr(s)); - }; - this.b64 = function(s) { - return rstr2b64(rstr(s), b64pad); - }; - this.any = function(s, e) { - return rstr2any(rstr(s), e); - }; - this.raw = function(s) { - return rstr(s, utf8); - }; - this.hex_hmac = function(k, d) { - return rstr2hex(rstr_hmac(k, d)); - }; - this.b64_hmac = function(k, d) { - return rstr2b64(rstr_hmac(k, d), b64pad); - }; - this.any_hmac = function(k, d, e) { - return rstr2any(rstr_hmac(k, d), e); - }; - /** - * Perform a simple self-test to see if the VM is working - * @return {String} Hexadecimal hash sample - * @public - */ - this.vm_test = function() { - return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + function setSortMembers(params) { + return sets(params, 'sortname', tag_sort_members); + } + + + function clean(params) { + return omit(params, ['geometry', 'debounce']); + } + + + function filterKeys(type) { + var count_type = type ? 'count_' + type : 'count_all'; + return function(d) { + return parseFloat(d[count_type]) > 2500 || d.in_wiki; }; - /** - * @description Enable/disable uppercase hexadecimal returned string - * @param {boolean} - * @return {Object} this - * @public - */ - this.setUpperCase = function(a) { - if (typeof a === 'boolean') { - hexcase = a; - } - return this; + } + + + function filterMultikeys(prefix) { + return function(d) { + // d.key begins with prefix, and d.key contains no additional ':'s + var re = new RegExp('^' + prefix + '(.*)$'); + var matches = d.key.match(re) || []; + return (matches.length === 2 && matches[1].indexOf(':') === -1); }; - /** - * @description Defines a base64 pad string - * @param {string} Pad - * @return {Object} this - * @public - */ - this.setPad = function(a) { - b64pad = a || b64pad; - return this; + } + + + function filterValues(allowUpperCase) { + return function(d) { + if (d.value.match(/[;,]/) !== null) return false; // exclude some punctuation + if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false; // exclude uppercase letters + return parseFloat(d.fraction) > 0.0 || d.in_wiki; }; - /** - * @description Defines a base64 pad string - * @param {boolean} - * @return {Object} this - * @public - */ - this.setUTF8 = function(a) { - if (typeof a === 'boolean') { - utf8 = a; - } - return this; + } + + + function filterRoles(geometry) { + return function(d) { + if (d.role === '') return false; // exclude empty role + if (d.role.match(/[A-Z*;,]/) !== null) return false; // exclude uppercase letters and some punctuation + return parseFloat(d[tag_members_fractions[geometry]]) > 0.0; }; + } - /* private methods */ - /** - * Calculate the SHA-512 of a raw string - */ + function valKey(d) { + return { + value: d.key, + title: d.key + }; + } - function rstr(s) { - s = (utf8) ? utf8Encode(s) : s; - return binb2rstr(binb(rstr2binb(s), s.length * 8)); - } - /* - * Calculate the HMAC-SHA-512 of a key and some data (raw strings) - */ - function rstr_hmac(key, data) { - key = (utf8) ? utf8Encode(key) : key; - data = (utf8) ? utf8Encode(data) : data; + function valKeyDescription(d) { + return { + value: d.value, + title: d.description || d.value + }; + } - var hash, i = 0, - bkey = rstr2binb(key), - ipad = Array(32), - opad = Array(32); - if (bkey.length > 32) { - bkey = binb(bkey, key.length * 8); - } + function roleKey(d) { + return { + value: d.role, + title: d.role + }; + } - for (; i < 32; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8); - return binb2rstr(binb(opad.concat(hash), 1024 + 512)); - } + // sort keys with ':' lower than keys without ':' + function sortKeys(a, b) { + return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1 + : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1 + : 0; + } - /** - * Calculate the SHA-512 of an array of big-endian dwords, and a bit length - */ - function binb(x, len) { - var j, i, l, - W = new Array(80), - hash = new Array(16), - //Initial hash values - H = [ - new int64(0x6a09e667, -205731576), - new int64(-1150833019, -2067093701), - new int64(0x3c6ef372, -23791573), - new int64(-1521486534, 0x5f1d36f1), - new int64(0x510e527f, -1377402159), - new int64(-1694144372, 0x2b3e6c1f), - new int64(0x1f83d9ab, -79577749), - new int64(0x5be0cd19, 0x137e2179) - ], - T1 = new int64(0, 0), - T2 = new int64(0, 0), - a = new int64(0, 0), - b = new int64(0, 0), - c = new int64(0, 0), - d = new int64(0, 0), - e = new int64(0, 0), - f = new int64(0, 0), - g = new int64(0, 0), - h = new int64(0, 0), - //Temporary variables not specified by the document - s0 = new int64(0, 0), - s1 = new int64(0, 0), - Ch = new int64(0, 0), - Maj = new int64(0, 0), - r1 = new int64(0, 0), - r2 = new int64(0, 0), - r3 = new int64(0, 0); - - if (sha512_k === undefined) { - //SHA512 constants - sha512_k = [ - new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd), - new int64(-1245643825, -330482897), new int64(-373957723, -2121671748), - new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031), - new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736), - new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe), - new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302), - new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1), - new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428), - new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3), - new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65), - new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483), - new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459), - new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210), - new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340), - new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395), - new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70), - new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926), - new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473), - new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8), - new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b), - new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023), - new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30), - new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910), - new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8), - new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53), - new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016), - new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893), - new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397), - new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60), - new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec), - new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047), - new int64(-1090935817, -1295615723), new int64(-965641998, -479046869), - new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207), - new int64(-354779690, -840897762), new int64(-176337025, -294727304), - new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026), - new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b), - new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493), - new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620), - new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430), - new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817) - ]; - } + var debouncedRequest = debounce(request$1, 500, { leading: false }); - for (i = 0; i < 80; i += 1) { - W[i] = new int64(0, 0); - } + function request$1(url, params, exactMatch, callback, loaded) { + if (inflight$1[url]) return; - // append padding to the source string. The format is described in the FIPS. - x[len >> 5] |= 0x80 << (24 - (len & 0x1f)); - x[((len + 128 >> 10) << 5) + 31] = len; - l = x.length; - for (i = 0; i < l; i += 32) { //32 dwords is the block size - int64copy(a, H[0]); - int64copy(b, H[1]); - int64copy(c, H[2]); - int64copy(d, H[3]); - int64copy(e, H[4]); - int64copy(f, H[5]); - int64copy(g, H[6]); - int64copy(h, H[7]); - - for (j = 0; j < 16; j += 1) { - W[j].h = x[i + 2 * j]; - W[j].l = x[i + 2 * j + 1]; - } - - for (j = 16; j < 80; j += 1) { - //sigma1 - int64rrot(r1, W[j - 2], 19); - int64revrrot(r2, W[j - 2], 29); - int64shr(r3, W[j - 2], 6); - s1.l = r1.l ^ r2.l ^ r3.l; - s1.h = r1.h ^ r2.h ^ r3.h; - //sigma0 - int64rrot(r1, W[j - 15], 1); - int64rrot(r2, W[j - 15], 8); - int64shr(r3, W[j - 15], 7); - s0.l = r1.l ^ r2.l ^ r3.l; - s0.h = r1.h ^ r2.h ^ r3.h; - - int64add4(W[j], s1, W[j - 7], s0, W[j - 16]); - } - - for (j = 0; j < 80; j += 1) { - //Ch - Ch.l = (e.l & f.l) ^ (~e.l & g.l); - Ch.h = (e.h & f.h) ^ (~e.h & g.h); - - //Sigma1 - int64rrot(r1, e, 14); - int64rrot(r2, e, 18); - int64revrrot(r3, e, 9); - s1.l = r1.l ^ r2.l ^ r3.l; - s1.h = r1.h ^ r2.h ^ r3.h; - - //Sigma0 - int64rrot(r1, a, 28); - int64revrrot(r2, a, 2); - int64revrrot(r3, a, 7); - s0.l = r1.l ^ r2.l ^ r3.l; - s0.h = r1.h ^ r2.h ^ r3.h; - - //Maj - Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l); - Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h); - - int64add5(T1, h, s1, Ch, sha512_k[j], W[j]); - int64add(T2, s0, Maj); - - int64copy(h, g); - int64copy(g, f); - int64copy(f, e); - int64add(e, d, T1); - int64copy(d, c); - int64copy(c, b); - int64copy(b, a); - int64add(a, T1, T2); - } - int64add(H[0], H[0], a); - int64add(H[1], H[1], b); - int64add(H[2], H[2], c); - int64add(H[3], H[3], d); - int64add(H[4], H[4], e); - int64add(H[5], H[5], f); - int64add(H[6], H[6], g); - int64add(H[7], H[7], h); - } + if (checkCache(url, params, exactMatch, callback)) return; - //represent the hash as an array of 32-bit dwords - for (i = 0; i < 8; i += 1) { - hash[2 * i] = H[i].h; - hash[2 * i + 1] = H[i].l; - } - return hash; - } + inflight$1[url] = d3_json(url, function (err, data) { + delete inflight$1[url]; + loaded(err, data); + }); + } - //A constructor for 64-bit numbers - function int64(h, l) { - this.h = h; - this.l = l; - //this.toString = int64toString; - } + function checkCache(url, params, exactMatch, callback) { + var rp = params.rp || 25, + testQuery = params.query || '', + testUrl = url; - //Copies src into dst, assuming both are 64-bit numbers + do { + var hit = taginfoCache[testUrl]; - function int64copy(dst, src) { - dst.h = src.h; - dst.l = src.l; - } + // exact match, or shorter match yielding fewer than max results (rp) + if (hit && (url === testUrl || hit.length < rp)) { + callback(null, hit); + return true; + } - //Right-rotates a 64-bit number by shift - //Won't handle cases of shift>=32 - //The function revrrot() is for that + // don't try to shorten the query + if (exactMatch || !testQuery.length) return false; - function int64rrot(dst, x, shift) { - dst.l = (x.l >>> shift) | (x.h << (32 - shift)); - dst.h = (x.h >>> shift) | (x.l << (32 - shift)); - } + // do shorten the query to see if we already have a cached result + // that has returned fewer than max results (rp) + testQuery = testQuery.slice(0, -1); + testUrl = url.replace(/&query=(.*?)&/, '&query=' + testQuery + '&'); + } while (testQuery.length >= 0); - //Reverses the dwords of the source and then rotates right by shift. - //This is equivalent to rotation by 32+shift + return false; + } - function int64revrrot(dst, x, shift) { - dst.l = (x.h >>> shift) | (x.l << (32 - shift)); - dst.h = (x.l >>> shift) | (x.h << (32 - shift)); - } - //Bitwise-shifts right a 64-bit number by shift - //Won't handle shift>=32, but it's never needed in SHA512 + var serviceTaginfo = { - function int64shr(dst, x, shift) { - dst.l = (x.l >>> shift) | (x.h << (32 - shift)); - dst.h = (x.h >>> shift); - } + init: function() { + inflight$1 = {}; + taginfoCache = {}; + popularKeys = {}; - //Adds two 64-bit numbers - //Like the original implementation, does not rely on 32-bit operations + // Fetch popular keys. We'll exclude these from `values` + // lookups because they stress taginfo, and they aren't likely + // to yield meaningful autocomplete results.. see #3955 + var params = { rp: 100, sortname: 'values_all', sortorder: 'desc', page: 1, debounce: false }; + this.keys(params, function(err, data) { + if (err) return; + data.forEach(function(d) { + if (d.value === 'opening_hours') return; // exception + popularKeys[d.value] = true; + }); + }); + }, - function int64add(dst, x, y) { - var w0 = (x.l & 0xffff) + (y.l & 0xffff); - var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16); - var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16); - var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16); - dst.l = (w0 & 0xffff) | (w1 << 16); - dst.h = (w2 & 0xffff) | (w3 << 16); - } - //Same, except with 4 addends. Works faster than adding them one by one. + reset: function() { + forEach(inflight$1, function(req) { req.abort(); }); + inflight$1 = {}; + }, - function int64add4(dst, a, b, c, d) { - var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff); - var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16); - var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16); - var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16); - dst.l = (w0 & 0xffff) | (w1 << 16); - dst.h = (w2 & 0xffff) | (w3 << 16); - } - //Same, except with 5 addends + keys: function(params, callback) { + var doRequest = params.debounce ? debouncedRequest : request$1; + params = clean(setSort(params)); + params = assignIn({ rp: 10, sortname: 'count_all', sortorder: 'desc', page: 1 }, params); + + var url = apibase$3 + 'keys/all?' + utilQsString(params); + doRequest(url, params, false, callback, function(err, d) { + if (err) { + callback(err); + } else { + var f = filterKeys(params.filter); + var result = d.data.filter(f).sort(sortKeys).map(valKey); + taginfoCache[url] = result; + callback(null, result); + } + }); + }, - function int64add5(dst, a, b, c, d, e) { - var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff), - w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16), - w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16), - w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16); - dst.l = (w0 & 0xffff) | (w1 << 16); - dst.h = (w2 & 0xffff) | (w3 << 16); - } - }, - /** - * @class Hashes.RMD160 - * @constructor - * @param {Object} [config] - * - * A JavaScript implementation of the RIPEMD-160 Algorithm - * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * See http://pajhome.org.uk/crypt/md5 for details. - * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/ - */ - RMD160: function(options) { - /** - * Private properties configuration variables. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - * @see this.setUpperCase() method - * @see this.setPad() method - */ - var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, - /* hexadecimal output case format. false - lowercase; true - uppercase */ - b64pad = (options && typeof options.pad === 'string') ? options.pa : '=', - /* base-64 pad character. Default '=' for strict RFC compliance */ - utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, - /* enable/disable utf8 encoding */ - rmd160_r1 = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 - ], - rmd160_r2 = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 - ], - rmd160_s1 = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 - ], - rmd160_s2 = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 - ]; - /* privileged (public) methods */ - this.hex = function(s) { - return rstr2hex(rstr(s, utf8)); - }; - this.b64 = function(s) { - return rstr2b64(rstr(s, utf8), b64pad); - }; - this.any = function(s, e) { - return rstr2any(rstr(s, utf8), e); - }; - this.raw = function(s) { - return rstr(s, utf8); - }; - this.hex_hmac = function(k, d) { - return rstr2hex(rstr_hmac(k, d)); - }; - this.b64_hmac = function(k, d) { - return rstr2b64(rstr_hmac(k, d), b64pad); - }; - this.any_hmac = function(k, d, e) { - return rstr2any(rstr_hmac(k, d), e); - }; - /** - * Perform a simple self-test to see if the VM is working - * @return {String} Hexadecimal hash sample - * @public - */ - this.vm_test = function() { - return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; - }; - /** - * @description Enable/disable uppercase hexadecimal returned string - * @param {boolean} - * @return {Object} this - * @public - */ - this.setUpperCase = function(a) { - if (typeof a === 'boolean') { - hexcase = a; - } - return this; - }; - /** - * @description Defines a base64 pad string - * @param {string} Pad - * @return {Object} this - * @public - */ - this.setPad = function(a) { - if (typeof a !== 'undefined') { - b64pad = a; - } - return this; - }; - /** - * @description Defines a base64 pad string - * @param {boolean} - * @return {Object} this - * @public - */ - this.setUTF8 = function(a) { - if (typeof a === 'boolean') { - utf8 = a; - } - return this; - }; + multikeys: function(params, callback) { + var doRequest = params.debounce ? debouncedRequest : request$1; + params = clean(setSort(params)); + params = assignIn({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params); + var prefix = params.query; + + var url = apibase$3 + 'keys/all?' + utilQsString(params); + doRequest(url, params, true, callback, function(err, d) { + if (err) { + callback(err); + } else { + var f = filterMultikeys(prefix); + var result = d.data.filter(f).map(valKey); + taginfoCache[url] = result; + callback(null, result); + } + }); + }, - /* private methods */ - /** - * Calculate the rmd160 of a raw string - */ + values: function(params, callback) { + // Exclude popular keys from values lookups.. see #3955 + var key = params.key; + if (key && popularKeys[key]) { + callback(null, []); + return; + } - function rstr(s) { - s = (utf8) ? utf8Encode(s) : s; - return binl2rstr(binl(rstr2binl(s), s.length * 8)); - } + var doRequest = params.debounce ? debouncedRequest : request$1; + params = clean(setSort(setFilter(params))); + params = assignIn({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params); + + var url = apibase$3 + 'key/values?' + utilQsString(params); + doRequest(url, params, false, callback, function(err, d) { + if (err) { + callback(err); + } else { + // In most cases we prefer taginfo value results with lowercase letters. + // A few OSM keys expect values to contain uppercase values (see #3377). + // This is not an exhaustive list (e.g. `name` also has uppercase values) + // but these are the fields where taginfo value lookup is most useful. + var re = /network|taxon|genus|species|brand|grape_variety|rating|:output|_hours|_times/; + var allowUpperCase = (params.key.match(re) !== null); + var f = filterValues(allowUpperCase); + + var result = d.data.filter(f).map(valKeyDescription); + taginfoCache[url] = result; + callback(null, result); + } + }); + }, - /** - * Calculate the HMAC-rmd160 of a key and some data (raw strings) - */ - function rstr_hmac(key, data) { - key = (utf8) ? utf8Encode(key) : key; - data = (utf8) ? utf8Encode(data) : data; - var i, hash, - bkey = rstr2binl(key), - ipad = Array(16), - opad = Array(16); + roles: function(params, callback) { + var doRequest = params.debounce ? debouncedRequest : request$1; + var geometry = params.geometry; + params = clean(setSortMembers(params)); + params = assignIn({ rp: 25, sortname: 'count_all_members', sortorder: 'desc', page: 1 }, params); + + var url = apibase$3 + 'relation/roles?' + utilQsString(params); + doRequest(url, params, true, callback, function(err, d) { + if (err) { + callback(err); + } else { + var f = filterRoles(geometry); + var result = d.data.filter(f).map(roleKey); + taginfoCache[url] = result; + callback(null, result); + } + }); + }, - if (bkey.length > 16) { - bkey = binl(bkey, key.length * 8); - } - for (i = 0; i < 16; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); - return binl2rstr(binl(opad.concat(hash), 512 + 160)); - } + docs: function(params, callback) { + var doRequest = params.debounce ? debouncedRequest : request$1; + params = clean(setSort(params)); - /** - * Convert an array of little-endian words to a string - */ + var path = 'key/wiki_pages?'; + if (params.value) path = 'tag/wiki_pages?'; + else if (params.rtype) path = 'relation/wiki_pages?'; - function binl2rstr(input) { - var i, output = '', - l = input.length * 32; - for (i = 0; i < l; i += 8) { - output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); - } - return output; - } + var url = apibase$3 + path + utilQsString(params); + doRequest(url, params, true, callback, function(err, d) { + if (err) { + callback(err); + } else { + taginfoCache[url] = d.data; + callback(null, d.data); + } + }); + }, - /** - * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length. - */ - function binl(x, len) { - var T, j, i, l, - h0 = 0x67452301, - h1 = 0xefcdab89, - h2 = 0x98badcfe, - h3 = 0x10325476, - h4 = 0xc3d2e1f0, - A1, B1, C1, D1, E1, - A2, B2, C2, D2, E2; - - /* append padding */ - x[len >> 5] |= 0x80 << (len % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - l = x.length; - - for (i = 0; i < l; i += 16) { - A1 = A2 = h0; - B1 = B2 = h1; - C1 = C2 = h2; - D1 = D2 = h3; - E1 = E2 = h4; - for (j = 0; j <= 79; j += 1) { - T = safe_add(A1, rmd160_f(j, B1, C1, D1)); - T = safe_add(T, x[i + rmd160_r1[j]]); - T = safe_add(T, rmd160_K1(j)); - T = safe_add(bit_rol(T, rmd160_s1[j]), E1); - A1 = E1; - E1 = D1; - D1 = bit_rol(C1, 10); - C1 = B1; - B1 = T; - T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2)); - T = safe_add(T, x[i + rmd160_r2[j]]); - T = safe_add(T, rmd160_K2(j)); - T = safe_add(bit_rol(T, rmd160_s2[j]), E2); - A2 = E2; - E2 = D2; - D2 = bit_rol(C2, 10); - C2 = B2; - B2 = T; - } - - T = safe_add(h1, safe_add(C1, D2)); - h1 = safe_add(h2, safe_add(D1, E2)); - h2 = safe_add(h3, safe_add(E1, A2)); - h3 = safe_add(h4, safe_add(A1, B2)); - h4 = safe_add(h0, safe_add(B1, C2)); - h0 = T; - } - return [h0, h1, h2, h3, h4]; + apibase: function(_) { + if (!arguments.length) return apibase$3; + apibase$3 = _; + return this; } - // specific algorithm methods + }; - function rmd160_f(j, x, y, z) { - return (0 <= j && j <= 15) ? (x ^ y ^ z) : - (16 <= j && j <= 31) ? (x & y) | (~x & z) : - (32 <= j && j <= 47) ? (x | ~y) ^ z : - (48 <= j && j <= 63) ? (x & z) | (y & ~z) : - (64 <= j && j <= 79) ? x ^ (y | ~z) : - 'rmd160_f: j out of range'; - } + var jsonpCache = {}; + window.jsonpCache = jsonpCache; - function rmd160_K1(j) { - return (0 <= j && j <= 15) ? 0x00000000 : - (16 <= j && j <= 31) ? 0x5a827999 : - (32 <= j && j <= 47) ? 0x6ed9eba1 : - (48 <= j && j <= 63) ? 0x8f1bbcdc : - (64 <= j && j <= 79) ? 0xa953fd4e : - 'rmd160_K1: j out of range'; - } + function jsonpRequest(url, callback) { - function rmd160_K2(j) { - return (0 <= j && j <= 15) ? 0x50a28be6 : - (16 <= j && j <= 31) ? 0x5c4dd124 : - (32 <= j && j <= 47) ? 0x6d703ef3 : - (48 <= j && j <= 63) ? 0x7a6d76e9 : - (64 <= j && j <= 79) ? 0x00000000 : - 'rmd160_K2: j out of range'; + if (window.JSONP_FIX) { + if (window.JSONP_DELAY === 0) { + callback(window.JSONP_FIX); + } else { + setTimeout(function() { + callback(window.JSONP_FIX); + }, window.JSONP_DELAY || 0); } + return; } - }; - // exposes Hashes - (function(window, undefined) { - var freeExports = false; - { - freeExports = exports; - if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) { - window = commonjsGlobal; - } + function rand() { + var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', + c = '', i = -1; + while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52)); + return c; } - - if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) { - // define as an anonymous module, so, through path mapping, it can be aliased - undefined(function() { - return Hashes; - }); - } else if (freeExports) { - // in Node.js or RingoJS v0.8.0+ - if ('object' === 'object' && module && module.exports === freeExports) { - module.exports = Hashes; - } - // in Narwhal or RingoJS v0.7.0- - else { - freeExports.Hashes = Hashes; - } - } else { - // in a browser or Rhino - window.Hashes = Hashes; + + function create$$1(url) { + var e = url.match(/callback=(\w+)/), + c = e ? e[1] : rand(); + jsonpCache[c] = function(data) { + callback(data); + delete jsonpCache[c]; + script.remove(); + }; + return 'jsonpCache.' + c; } - }(this)); -}()); // IIFE -}); -var immutable = extend$2; + var cb = create$$1(url), + script = select('head') + .append('script') + .attr('type', 'text/javascript') + .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb)); + } -var hasOwnProperty$16 = Object.prototype.hasOwnProperty; + var endpoint = 'https://www.wikidata.org/w/api.php?'; -function extend$2() { - var target = {}; + var serviceWikidata = { - for (var i = 0; i < arguments.length; i++) { - var source = arguments[i]; + init: function() {}, + reset: function() {}, - for (var key in source) { - if (hasOwnProperty$16.call(source, key)) { - target[key] = source[key]; - } - } - } - return target -} - -var sha1 = new hashes.SHA1(); - -var ohauth = {}; - -ohauth.qsString = function(obj) { - return Object.keys(obj).sort().map(function(key) { - return ohauth.percentEncode(key) + '=' + - ohauth.percentEncode(obj[key]); - }).join('&'); -}; - -ohauth.stringQs = function(str) { - return str.split('&').filter(function (pair) { - return pair !== ''; - }).reduce(function(obj, pair){ - var parts = pair.split('='); - obj[decodeURIComponent(parts[0])] = (null === parts[1]) ? - '' : decodeURIComponent(parts[1]); - return obj; - }, {}); -}; - -ohauth.rawxhr = function(method, url, data, headers, callback) { - var xhr = new XMLHttpRequest(), - twoHundred = /^20\d$/; - xhr.onreadystatechange = function() { - if (4 === xhr.readyState && 0 !== xhr.status) { - if (twoHundred.test(xhr.status)) callback(null, xhr); - else return callback(xhr, null); - } - }; - xhr.onerror = function(e) { return callback(e, null); }; - xhr.open(method, url, true); - for (var h in headers) xhr.setRequestHeader(h, headers[h]); - xhr.send(data); - return xhr; -}; - -ohauth.xhr = function(method, url, auth, data, options, callback) { - var headers = (options && options.header) || { - 'Content-Type': 'application/x-www-form-urlencoded' - }; - headers.Authorization = 'OAuth ' + ohauth.authHeader(auth); - return ohauth.rawxhr(method, url, data, headers, callback); -}; + // Given a Wikipedia language and article title, return an array of + // corresponding Wikidata entities. + itemsByTitle: function(lang, title, callback) { + if (!title) { + callback('', {}); + return; + } -ohauth.nonce = function() { - for (var o = ''; o.length < 6;) { - o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)]; - } - return o; -}; + lang = lang || 'en'; + jsonpRequest(endpoint + utilQsString({ + action: 'wbgetentities', + format: 'json', + sites: lang.replace(/-/g, '_') + 'wiki', + titles: title, + languages: 'en', // shrink response by filtering to one language + callback: '{callback}' + }), function(data) { + if (!data || data.error) { + callback('', {}); + } else { + callback(title, data.entities || {}); + } + }); + } -ohauth.authHeader = function(obj) { - return Object.keys(obj).sort().map(function(key) { - return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"'; - }).join(', '); -}; + }; -ohauth.timestamp = function() { return ~~((+new Date()) / 1000); }; + var endpoint$1 = 'https://en.wikipedia.org/w/api.php?'; -ohauth.percentEncode = function(s) { - return encodeURIComponent(s) - .replace(/\!/g, '%21').replace(/\'/g, '%27') - .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29'); -}; + var serviceWikipedia = { -ohauth.baseString = function(method, url, params) { - if (params.oauth_signature) delete params.oauth_signature; - return [ - method, - ohauth.percentEncode(url), - ohauth.percentEncode(ohauth.qsString(params))].join('&'); -}; - -ohauth.signature = function(oauth_secret, token_secret, baseString) { - return sha1.b64_hmac( - ohauth.percentEncode(oauth_secret) + '&' + - ohauth.percentEncode(token_secret), - baseString); -}; - -/** - * Takes an options object for configuration (consumer_key, - * consumer_secret, version, signature_method, token, token_secret) - * and returns a function that generates the Authorization header - * for given data. - * - * The returned function takes these parameters: - * - method: GET/POST/... - * - uri: full URI with protocol, port, path and query string - * - extra_params: any extra parameters (that are passed in the POST data), - * can be an object or a from-urlencoded string. - * - * Returned function returns full OAuth header with "OAuth" string in it. - */ - -ohauth.headerGenerator = function(options) { - options = options || {}; - var consumer_key = options.consumer_key || '', - consumer_secret = options.consumer_secret || '', - signature_method = options.signature_method || 'HMAC-SHA1', - version = options.version || '1.0', - token = options.token || '', - token_secret = options.token_secret || ''; - - return function(method, uri, extra_params) { - method = method.toUpperCase(); - if (typeof extra_params === 'string' && extra_params.length > 0) { - extra_params = ohauth.stringQs(extra_params); - } + init: function() {}, + reset: function() {}, - var uri_parts = uri.split('?', 2), - base_uri = uri_parts[0]; - var query_params = uri_parts.length === 2 ? - ohauth.stringQs(uri_parts[1]) : {}; + search: function(lang, query, callback) { + if (!query) { + callback('', []); + return; + } - var oauth_params = { - oauth_consumer_key: consumer_key, - oauth_signature_method: signature_method, - oauth_version: version, - oauth_timestamp: ohauth.timestamp(), - oauth_nonce: ohauth.nonce() - }; + lang = lang || 'en'; + jsonpRequest(endpoint$1.replace('en', lang) + + utilQsString({ + action: 'query', + list: 'search', + srlimit: '10', + srinfo: 'suggestion', + format: 'json', + callback: '{callback}', + srsearch: query + }), function(data) { + if (!data || !data.query || !data.query.search || data.error) { + callback('', []); + } else { + var results = data.query.search.map(function(d) { return d.title; }); + callback(query, results); + } + } + ); + }, - if (token) oauth_params.oauth_token = token; - var all_params = immutable({}, oauth_params, query_params, extra_params), - base_str = ohauth.baseString(method, base_uri, all_params); + suggestions: function(lang, query, callback) { + if (!query) { + callback('', []); + return; + } - oauth_params.oauth_signature = ohauth.signature(consumer_secret, token_secret, base_str); + lang = lang || 'en'; + jsonpRequest(endpoint$1.replace('en', lang) + + utilQsString({ + action: 'opensearch', + namespace: 0, + suggest: '', + format: 'json', + callback: '{callback}', + search: query + }), function(data) { + if (!data || data.error) { + callback('', []); + } else { + callback(data[0], data[1] || []); + } + } + ); + }, - return 'OAuth ' + ohauth.authHeader(oauth_params); - }; -}; - -var ohauth_1 = ohauth; - -var resolveUrl = createCommonjsModule(function (module, exports) { -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -void (function(root, factory) { - if (typeof undefined === "function" && undefined.amd) { - undefined(factory); - } else { - module.exports = factory(); - } -}(commonjsGlobal, function() { - - function resolveUrl(/* ...urls */) { - var numUrls = arguments.length; - - if (numUrls === 0) { - throw new Error("resolveUrl requires at least one argument; got none.") - } - - var base = document.createElement("base"); - base.href = arguments[0]; - - if (numUrls === 1) { - return base.href - } - - var head = document.getElementsByTagName("head")[0]; - head.insertBefore(base, head.firstChild); - - var a = document.createElement("a"); - var resolved; - - for (var index = 1; index < numUrls; index++) { - a.href = arguments[index]; - resolved = a.href; - base.href = resolved; - } - - head.removeChild(base); - - return resolved - } - - return resolveUrl - -})); -}); - -var assign$1 = make_assign(); -var create$2 = make_create(); -var trim = make_trim(); -var Global = (typeof window !== 'undefined' ? window : commonjsGlobal); - -var util = { - assign: assign$1, - create: create$2, - trim: trim, - bind: bind, - slice: slice$7, - each: each, - map: map$4, - pluck: pluck, - isList: isList, - isFunction: isFunction$1, - isObject: isObject$1, - Global: Global -}; - -function make_assign() { - if (Object.assign) { - return Object.assign - } else { - return function shimAssign(obj, props1, props2, etc) { - for (var i = 1; i < arguments.length; i++) { - each(Object(arguments[i]), function(val, key) { - obj[key] = val; - }); - } - return obj - } - } -} - -function make_create() { - if (Object.create) { - return function create(obj, assignProps1, assignProps2, etc) { - var assignArgsList = slice$7(arguments, 1); - return assign$1.apply(this, [Object.create(obj)].concat(assignArgsList)) - } - } else { - function F() {} // eslint-disable-line no-inner-declarations - return function create(obj, assignProps1, assignProps2, etc) { - var assignArgsList = slice$7(arguments, 1); - F.prototype = obj; - return assign$1.apply(this, [new F()].concat(assignArgsList)) - } - } -} - -function make_trim() { - if (String.prototype.trim) { - return function trim(str) { - return String.prototype.trim.call(str) - } - } else { - return function trim(str) { - return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '') - } - } -} - -function bind(obj, fn) { - return function() { - return fn.apply(obj, Array.prototype.slice.call(arguments, 0)) - } -} - -function slice$7(arr, index) { - return Array.prototype.slice.call(arr, index || 0) -} - -function each(obj, fn) { - pluck(obj, function(val, key) { - fn(val, key); - return false - }); -} - -function map$4(obj, fn) { - var res = (isList(obj) ? [] : {}); - pluck(obj, function(v, k) { - res[k] = fn(v, k); - return false - }); - return res -} - -function pluck(obj, fn) { - if (isList(obj)) { - for (var i=0; i= 0; i--) { - var key = localStorage$1().key(i); - fn(read(key), key); - } -} - -function remove$2(key) { - return localStorage$1().removeItem(key) -} - -function clearAll() { - return localStorage$1().clear() -} - -// oldFF-globalStorage provides storage for Firefox -// versions 6 and 7, where no localStorage, etc -// is available. - - -var Global$2 = util.Global; - -var oldFFGlobalStorage = { - name: 'oldFF-globalStorage', - read: read$1, - write: write$1, - each: each$3, - remove: remove$3, - clearAll: clearAll$1, -}; - -var globalStorage = Global$2.globalStorage; - -function read$1(key) { - return globalStorage[key] -} - -function write$1(key, data) { - globalStorage[key] = data; -} - -function each$3(fn) { - for (var i = globalStorage.length - 1; i >= 0; i--) { - var key = globalStorage.key(i); - fn(globalStorage[key], key); - } -} - -function remove$3(key) { - return globalStorage.removeItem(key) -} - -function clearAll$1() { - each$3(function(key, _) { - delete globalStorage[key]; - }); -} - -// oldIE-userDataStorage provides storage for Internet Explorer -// versions 6 and 7, where no localStorage, sessionStorage, etc -// is available. - - -var Global$3 = util.Global; - -var oldIEUserDataStorage = { - name: 'oldIE-userDataStorage', - write: write$2, - read: read$2, - each: each$4, - remove: remove$4, - clearAll: clearAll$2, -}; - -var storageName = 'storejs'; -var doc = Global$3.document; -var _withStorageEl = _makeIEStorageElFunction(); -var disable = (Global$3.navigator ? Global$3.navigator.userAgent : '').match(/ (MSIE 8|MSIE 9|MSIE 10)\./); // MSIE 9.x, MSIE 10.x - -function write$2(unfixedKey, data) { - if (disable) { return } - var fixedKey = fixKey(unfixedKey); - _withStorageEl(function(storageEl) { - storageEl.setAttribute(fixedKey, data); - storageEl.save(storageName); - }); -} - -function read$2(unfixedKey) { - if (disable) { return } - var fixedKey = fixKey(unfixedKey); - var res = null; - _withStorageEl(function(storageEl) { - res = storageEl.getAttribute(fixedKey); - }); - return res -} - -function each$4(callback) { - _withStorageEl(function(storageEl) { - var attributes = storageEl.XMLDocument.documentElement.attributes; - for (var i=attributes.length-1; i>=0; i--) { - var attr = attributes[i]; - callback(storageEl.getAttribute(attr.name), attr.name); - } - }); -} - -function remove$4(unfixedKey) { - var fixedKey = fixKey(unfixedKey); - _withStorageEl(function(storageEl) { - storageEl.removeAttribute(fixedKey); - storageEl.save(storageName); - }); -} - -function clearAll$2() { - _withStorageEl(function(storageEl) { - var attributes = storageEl.XMLDocument.documentElement.attributes; - storageEl.load(storageName); - for (var i=attributes.length-1; i>=0; i--) { - storageEl.removeAttribute(attributes[i].name); - } - storageEl.save(storageName); - }); -} - -// Helpers -////////// - -// In IE7, keys cannot start with a digit or contain certain chars. -// See https://github.com/marcuswestin/store.js/issues/40 -// See https://github.com/marcuswestin/store.js/issues/83 -var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g"); -function fixKey(key) { - return key.replace(/^\d/, '___$&').replace(forbiddenCharsRegex, '___') -} - -function _makeIEStorageElFunction() { - if (!doc || !doc.documentElement || !doc.documentElement.addBehavior) { - return null - } - var scriptTag = 'script', - storageOwner, - storageContainer, - storageEl; - - // Since #userData storage applies only to specific paths, we need to - // somehow link our data to a specific path. We choose /favicon.ico - // as a pretty safe option, since all browsers already make a request to - // this URL anyway and being a 404 will not hurt us here. We wrap an - // iframe pointing to the favicon in an ActiveXObject(htmlfile) object - // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx) - // since the iframe access rules appear to allow direct access and - // manipulation of the document element, even for a 404 page. This - // document can be used instead of the current document (which would - // have been limited to the current path) to perform #userData storage. - try { - /* global ActiveXObject */ - storageContainer = new ActiveXObject('htmlfile'); - storageContainer.open(); - storageContainer.write('<'+scriptTag+'>document.w=window'); - storageContainer.close(); - storageOwner = storageContainer.w.frames[0].document; - storageEl = storageOwner.createElement('div'); - } catch(e) { - // somehow ActiveXObject instantiation failed (perhaps some special - // security settings or otherwse), fall back to per-path storage - storageEl = doc.createElement('div'); - storageOwner = doc.body; - } - - return function(storeFunction) { - var args = [].slice.call(arguments, 0); - args.unshift(storageEl); - // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx - // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx - storageOwner.appendChild(storageEl); - storageEl.addBehavior('#default#userData'); - storageEl.load(storageName); - storeFunction.apply(this, args); - storageOwner.removeChild(storageEl); - return - } -} - -// cookieStorage is useful Safari private browser mode, where localStorage -// doesn't work but cookies do. This implementation is adopted from -// https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage - - -var Global$4 = util.Global; -var trim$1 = util.trim; - -var cookieStorage = { - name: 'cookieStorage', - read: read$3, - write: write$3, - each: each$5, - remove: remove$5, - clearAll: clearAll$3, -}; - -var doc$1 = Global$4.document; - -function read$3(key) { - if (!key || !_has(key)) { return null } - var regexpStr = "(?:^|.*;\\s*)" + - escape(key).replace(/[\-\.\+\*]/g, "\\$&") + - "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"; - return unescape(doc$1.cookie.replace(new RegExp(regexpStr), "$1")) -} - -function each$5(callback) { - var cookies = doc$1.cookie.split(/; ?/g); - for (var i = cookies.length - 1; i >= 0; i--) { - if (!trim$1(cookies[i])) { - continue - } - var kvp = cookies[i].split('='); - var key = unescape(kvp[0]); - var val = unescape(kvp[1]); - callback(val, key); - } -} - -function write$3(key, data) { - if(!key) { return } - doc$1.cookie = escape(key) + "=" + escape(data) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"; -} - -function remove$5(key) { - if (!key || !_has(key)) { - return - } - doc$1.cookie = escape(key) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"; -} - -function clearAll$3() { - each$5(function(_, key) { - remove$5(key); - }); -} - -function _has(key) { - return (new RegExp("(?:^|;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(doc$1.cookie) -} - -var Global$5 = util.Global; - -var sessionStorage_1 = { - name: 'sessionStorage', - read: read$4, - write: write$4, - each: each$6, - remove: remove$6, - clearAll: clearAll$4 -}; - -function sessionStorage() { - return Global$5.sessionStorage -} - -function read$4(key) { - return sessionStorage().getItem(key) -} - -function write$4(key, data) { - return sessionStorage().setItem(key, data) -} - -function each$6(fn) { - for (var i = sessionStorage().length - 1; i >= 0; i--) { - var key = sessionStorage().key(i); - fn(read$4(key), key); - } -} - -function remove$6(key) { - return sessionStorage().removeItem(key) -} - -function clearAll$4() { - return sessionStorage().clear() -} - -// memoryStorage is a useful last fallback to ensure that the store -// is functions (meaning store.get(), store.set(), etc will all function). -// However, stored values will not persist when the browser navigates to -// a new page or reloads the current page. - -var memoryStorage_1 = { - name: 'memoryStorage', - read: read$5, - write: write$5, - each: each$7, - remove: remove$7, - clearAll: clearAll$5, -}; - -var memoryStorage = {}; - -function read$5(key) { - return memoryStorage[key] -} - -function write$5(key, data) { - memoryStorage[key] = data; -} - -function each$7(callback) { - for (var key in memoryStorage) { - if (memoryStorage.hasOwnProperty(key)) { - callback(memoryStorage[key], key); - } - } -} - -function remove$7(key) { - delete memoryStorage[key]; -} - -function clearAll$5(key) { - memoryStorage = {}; -} - -var all$3 = [ - // Listed in order of usage preference - localStorage_1, - oldFFGlobalStorage, - oldIEUserDataStorage, - cookieStorage, - sessionStorage_1, - memoryStorage_1 -]; - -/* eslint-disable */ - -// json2.js -// 2016-10-28 -// Public Domain. -// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. -// See http://www.JSON.org/js.html -// This code should be minified before deployment. -// See http://javascript.crockford.com/jsmin.html - -// USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO -// NOT CONTROL. - -// This file creates a global JSON object containing two methods: stringify -// and parse. This file provides the ES5 JSON capability to ES3 systems. -// If a project might run on IE8 or earlier, then this file should be included. -// This file does nothing on ES5 systems. - -// JSON.stringify(value, replacer, space) -// value any JavaScript value, usually an object or array. -// replacer an optional parameter that determines how object -// values are stringified for objects. It can be a -// function or an array of strings. -// space an optional parameter that specifies the indentation -// of nested structures. If it is omitted, the text will -// be packed without extra whitespace. If it is a number, -// it will specify the number of spaces to indent at each -// level. If it is a string (such as "\t" or " "), -// it contains the characters used to indent at each level. -// This method produces a JSON text from a JavaScript value. -// When an object value is found, if the object contains a toJSON -// method, its toJSON method will be called and the result will be -// stringified. A toJSON method does not serialize: it returns the -// value represented by the name/value pair that should be serialized, -// or undefined if nothing should be serialized. The toJSON method -// will be passed the key associated with the value, and this will be -// bound to the value. - -// For example, this would serialize Dates as ISO strings. - -// Date.prototype.toJSON = function (key) { -// function f(n) { -// // Format integers to have at least two digits. -// return (n < 10) -// ? "0" + n -// : n; -// } -// return this.getUTCFullYear() + "-" + -// f(this.getUTCMonth() + 1) + "-" + -// f(this.getUTCDate()) + "T" + -// f(this.getUTCHours()) + ":" + -// f(this.getUTCMinutes()) + ":" + -// f(this.getUTCSeconds()) + "Z"; -// }; - -// You can provide an optional replacer method. It will be passed the -// key and value of each member, with this bound to the containing -// object. The value that is returned from your method will be -// serialized. If your method returns undefined, then the member will -// be excluded from the serialization. - -// If the replacer parameter is an array of strings, then it will be -// used to select the members to be serialized. It filters the results -// such that only members with keys listed in the replacer array are -// stringified. - -// Values that do not have JSON representations, such as undefined or -// functions, will not be serialized. Such values in objects will be -// dropped; in arrays they will be replaced with null. You can use -// a replacer function to replace those with JSON values. - -// JSON.stringify(undefined) returns undefined. - -// The optional space parameter produces a stringification of the -// value that is filled with line breaks and indentation to make it -// easier to read. - -// If the space parameter is a non-empty string, then that string will -// be used for indentation. If the space parameter is a number, then -// the indentation will be that many spaces. - -// Example: - -// text = JSON.stringify(["e", {pluribus: "unum"}]); -// // text is '["e",{"pluribus":"unum"}]' - -// text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t"); -// // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' - -// text = JSON.stringify([new Date()], function (key, value) { -// return this[key] instanceof Date -// ? "Date(" + this[key] + ")" -// : value; -// }); -// // text is '["Date(---current time---)"]' - -// JSON.parse(text, reviver) -// This method parses a JSON text to produce an object or array. -// It can throw a SyntaxError exception. - -// The optional reviver parameter is a function that can filter and -// transform the results. It receives each of the keys and values, -// and its return value is used instead of the original value. -// If it returns what it received, then the structure is not modified. -// If it returns undefined then the member is deleted. - -// Example: - -// // Parse the text. Values that look like ISO date strings will -// // be converted to Date objects. - -// myData = JSON.parse(text, function (key, value) { -// var a; -// if (typeof value === "string") { -// a = -// /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); -// if (a) { -// return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], -// +a[5], +a[6])); -// } -// } -// return value; -// }); - -// myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { -// var d; -// if (typeof value === "string" && -// value.slice(0, 5) === "Date(" && -// value.slice(-1) === ")") { -// d = new Date(value.slice(5, -1)); -// if (d) { -// return d; -// } -// } -// return value; -// }); - -// This is a reference implementation. You are free to copy, modify, or -// redistribute. - -/*jslint - eval, for, this -*/ - -/*property - JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, - lastIndex, length, parse, prototype, push, replace, slice, stringify, - test, toJSON, toString, valueOf -*/ - - -// Create a JSON object only if one does not already exist. We create the -// methods in a closure to avoid creating global variables. - -if (typeof JSON !== "object") { - JSON = {}; -} -(function () { + translations: function(lang, title, callback) { + if (!title) { + callback({}); + return; + } - var rx_one = /^[\],:{}\s]*$/; - var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; - var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; - var rx_four = /(?:^|:|,)(?:\s*\[)+/g; - var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + jsonpRequest(endpoint$1.replace('en', lang) + + utilQsString({ + action: 'query', + prop: 'langlinks', + format: 'json', + callback: '{callback}', + lllimit: 500, + titles: title + }), function(data) { + if (!data || !data.query || !data.query.pages || data.error) { + callback({}); + } else { + var list = data.query.pages[Object.keys(data.query.pages)[0]], + translations = {}; + if (list && list.langlinks) { + list.langlinks.forEach(function(d) { + translations[d.lang] = d['*']; + }); + } + callback(translations); + } + } + ); + } - function f(n) { - // Format integers to have at least two digits. - return n < 10 - ? "0" + n - : n; - } + }; - function this_value() { - return this.valueOf(); - } + var services = { + geocoder: serviceNominatim, + mapillary: serviceMapillary, + openstreetcam: serviceOpenstreetcam, + osm: serviceOsm, + taginfo: serviceTaginfo, + wikidata: serviceWikidata, + wikipedia: serviceWikipedia + }; - if (typeof Date.prototype.toJSON !== "function") { + var _isSaving = false; - Date.prototype.toJSON = function () { - return isFinite(this.valueOf()) - ? this.getUTCFullYear() + "-" + - f(this.getUTCMonth() + 1) + "-" + - f(this.getUTCDate()) + "T" + - f(this.getUTCHours()) + ":" + - f(this.getUTCMinutes()) + ":" + - f(this.getUTCSeconds()) + "Z" - : null; - }; + function modeSave$$1(context) { + var mode = { id: 'save' }; + var keybinding = d3keybinding('modeSave'); - Boolean.prototype.toJSON = this_value; - Number.prototype.toJSON = this_value; - String.prototype.toJSON = this_value; - } + var loading = uiLoading(context) + .message(t('save.uploading')) + .blocking(true); - var gap; - var indent; - var meta; - var rep; + var commit = uiCommit(context) + .on('cancel', cancel) + .on('save', save); + var _toCheck = []; + var _toLoad = []; + var _loaded = {}; + var _toLoadCount = 0; + var _toLoadTotal = 0; - function quote(string) { + var _conflicts = []; + var _errors = []; + var _origChanges; + var _location; -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - rx_escapable.lastIndex = 0; - return rx_escapable.test(string) - ? "\"" + string.replace(rx_escapable, function (a) { - var c = meta[a]; - return typeof c === "string" - ? c - : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4); - }) + "\"" - : "\"" + string + "\""; - } + function cancel(selectedID) { + if (selectedID) { + context.enter(modeSelect(context, [selectedID])); + } else { + context.enter(modeBrowse(context)); + } + } - function str(key, holder) { + function save(changeset, tryAgain, checkConflicts) { + // Guard against accidentally entering save code twice - #4641 + if (_isSaving && !tryAgain) { + return; + } -// Produce a string from holder[key]. + var osm = context.connection(); + if (!osm) { + cancel(); + return; + } - var i; // The loop counter. - var k; // The member key. - var v; // The member value. - var length; - var mind = gap; - var partial; - var value = holder[key]; + // If user somehow got logged out mid-save, try to reauthenticate.. + // This can happen if they were logged in from before, but the tokens are no longer valid. + if (!osm.authenticated()) { + osm.authenticate(function(err) { + if (err) { + cancel(); // quit save mode.. + } else { + save(changeset, tryAgain, checkConflicts); // continue where we left off.. + } + }); + return; + } -// If the value has a toJSON method, call it to obtain a replacement value. + if (!_isSaving) { + keybindingOff(); + context.container().call(loading); // block input + _isSaving = true; + } - if (value && typeof value === "object" && - typeof value.toJSON === "function") { - value = value.toJSON(key); - } + var history = context.history(); + var localGraph = context.graph(); + var remoteGraph = coreGraph$$1(history.base(), true); -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. + _conflicts = []; + _errors = []; - if (typeof rep === "function") { - value = rep.call(holder, key, value); - } + // Store original changes, in case user wants to download them as an .osc file + _origChanges = history.changes(actionDiscardTags(history.difference())); -// What happens next depends on the value's type. + // First time, `history.perform` a no-op action. + // Any conflict resolutions will be done as `history.replace` + if (!tryAgain) { + history.perform(actionNoop()); + } - switch (typeof value) { - case "string": - return quote(value); + // Attempt a fast upload.. If there are conflicts, re-enter with `checkConflicts = true` + if (!checkConflicts) { + upload(changeset); - case "number": + // Do the full (slow) conflict check.. + } else { + var modified = filter(history.difference().summary(), { changeType: 'modified' }); + _toCheck = map$3(map$3(modified, 'entity'), 'id'); + _toLoad = withChildNodes(_toCheck, localGraph); + _loaded = {}; + _toLoadCount = 0; + _toLoadTotal = _toLoad.length; + + if (_toCheck.length) { + showProgress(_toLoadCount, _toLoadTotal); + _toLoad.forEach(function(id) { _loaded[id] = false; }); + osm.loadMultiple(_toLoad, loaded); + } else { + upload(changeset); + } + } -// JSON numbers must be finite. Encode non-finite numbers as null. + return; - return isFinite(value) - ? String(value) - : "null"; - case "boolean": - case "null": + function withChildNodes(ids, graph) { + return uniq(reduce(ids, function(result, id) { + var entity = graph.entity(id); + if (entity.type === 'way') { + try { + var children = graph.childNodes(entity); + result.push.apply(result, map$3(filter(children, 'version'), 'id')); + } catch (err) { + /* eslint-disable no-console */ + if (typeof console !== 'undefined') console.error(err); + /* eslint-enable no-console */ + } + } + return result; + }, clone(ids))); + } -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce "null". The case is included here in -// the remote chance that this gets fixed someday. - return String(value); + // Reload modified entities into an alternate graph and check for conflicts.. + function loaded(err, result) { + if (_errors.length) return; + + if (err) { + _errors.push({ + msg: err.message || err.responseText, + details: [ t('save.status_code', { code: err.status }) ] + }); + showErrors(); + + } else { + var loadMore = []; + + result.data.forEach(function(entity) { + remoteGraph.replace(entity); + _loaded[entity.id] = true; + _toLoad = without(_toLoad, entity.id); + + if (!entity.visible) return; + + // Because loadMultiple doesn't download /full like loadEntity, + // need to also load children that aren't already being checked.. + var i, id; + if (entity.type === 'way') { + for (i = 0; i < entity.nodes.length; i++) { + id = entity.nodes[i]; + if (_loaded[id] === undefined) { + _loaded[id] = false; + loadMore.push(id); + } + } + } else if (entity.type === 'relation' && entity.isMultipolygon()) { + for (i = 0; i < entity.members.length; i++) { + id = entity.members[i].id; + if (_loaded[id] === undefined) { + _loaded[id] = false; + loadMore.push(id); + } + } + } + }); + + _toLoadCount += result.data.length; + _toLoadTotal += loadMore.length; + showProgress(_toLoadCount, _toLoadTotal); + + if (loadMore.length) { + _toLoad.push.apply(_toLoad, loadMore); + osm.loadMultiple(loadMore, loaded); + } + + if (!_toLoad.length) { + detectConflicts(); + } + } + } -// If the type is "object", we might be dealing with an object or an array or -// null. - case "object": + function detectConflicts() { + function choice(id, text, action) { + return { id: id, text: text, action: function() { history.replace(action); } }; + } + function formatUser(d) { + return '' + d + ''; + } + function entityName(entity) { + return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id); + } + + function sameVersions(local$$1, remote) { + if (local$$1.version !== remote.version) return false; + + if (local$$1.type === 'way') { + var children = union(local$$1.nodes, remote.nodes); + for (var i = 0; i < children.length; i++) { + var a = localGraph.hasEntity(children[i]); + var b = remoteGraph.hasEntity(children[i]); + if (a && b && a.version !== b.version) return false; + } + } + + return true; + } + + _toCheck.forEach(function(id) { + var local$$1 = localGraph.entity(id); + var remote = remoteGraph.entity(id); + + if (sameVersions(local$$1, remote)) return; + + var action = actionMergeRemoteChanges; + var merge = action(id, localGraph, remoteGraph, formatUser); + + history.replace(merge); + + var mergeConflicts = merge.conflicts(); + if (!mergeConflicts.length) return; // merged safely + + var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'); + var forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'); + var keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')); + var keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete')); + + _conflicts.push({ + id: id, + name: entityName(local$$1), + details: mergeConflicts, + chosen: 1, + choices: [ + choice(id, keepMine, forceLocal), + choice(id, keepTheirs, forceRemote) + ] + }); + }); + + upload(changeset); + } + } -// Due to a specification blunder in ECMAScript, typeof null is "object", -// so watch out for that case. - if (!value) { - return "null"; - } + function upload(changeset) { + var osm = context.connection(); + if (!osm) { + _errors.push({ msg: 'No OSM Service' }); + } -// Make an array to hold the partial results of stringifying this object value. + if (_conflicts.length) { + _conflicts.sort(function(a, b) { return b.id.localeCompare(a.id); }); + showConflicts(changeset); - gap += indent; - partial = []; + } else if (_errors.length) { + showErrors(); -// Is the value an array? + } else { + var history = context.history(); + var changes = history.changes(actionDiscardTags(history.difference())); + if (changes.modified.length || changes.created.length || changes.deleted.length) { + loadLocation(); // so it is ready when we display the save screen + osm.putChangeset(changeset, changes, uploadCallback); + } else { // changes were insignificant or reverted by user + select('.inspector-wrap *').remove(); + loading.close(); + _isSaving = false; + context.flush(); + cancel(); + } + } + } - if (Object.prototype.toString.apply(value) === "[object Array]") { -// The value is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. + function uploadCallback(err, changeset) { + if (err) { + if (err.status === 409) { // 409 Conflict + save(changeset, true, true); // tryAgain = true, checkConflicts = true + } else { + _errors.push({ + msg: err.message || err.responseText, + details: [ t('save.status_code', { code: err.status }) ] + }); + showErrors(); + } - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || "null"; - } + } else { + context.history().clearSaved(); + success(changeset); + // Add delay to allow for postgres replication #1646 #2678 + window.setTimeout(function() { + select('.inspector-wrap *').remove(); + loading.close(); + _isSaving = false; + context.flush(); + }, 2500); + } + } -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - v = partial.length === 0 - ? "[]" - : gap - ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" - : "[" + partial.join(",") + "]"; - gap = mind; - return v; - } + function showProgress(num, total) { + var modal = context.container().select('.loading-modal .modal-section'); + var progress = modal.selectAll('.progress') + .data([0]); -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === "object") { - length = rep.length; - for (i = 0; i < length; i += 1) { - if (typeof rep[i] === "string") { - k = rep[i]; - v = str(k, value); - if (v) { - partial.push(quote(k) + ( - gap - ? ": " - : ":" - ) + v); - } - } - } - } else { + // enter/update + progress.enter() + .append('div') + .attr('class', 'progress') + .merge(progress) + .text(t('save.conflict_progress', { num: num, total: total })); + } -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + ( - gap - ? ": " - : ":" - ) + v); - } - } - } - } -// Join all of the member texts together, separated with commas, -// and wrap them in braces. + function showConflicts(changeset) { + var history = context.history(); + var selection$$1 = context.container() + .select('#sidebar') + .append('div') + .attr('class','sidebar-component'); + + loading.close(); + _isSaving = false; + + var ui = uiConflicts(context) + .conflictList(_conflicts) + .origChanges(_origChanges) + .on('cancel', function() { + history.pop(); + selection$$1.remove(); + keybindingOn(); + }) + .on('save', function() { + for (var i = 0; i < _conflicts.length; i++) { + if (_conflicts[i].chosen === 1) { // user chose "keep theirs" + var entity = context.hasEntity(_conflicts[i].id); + if (entity && entity.type === 'way') { + var children = uniq(entity.nodes); + for (var j = 0; j < children.length; j++) { + history.replace(actionRevert(children[j])); + } + } + history.replace(actionRevert(_conflicts[i].id)); + } + } + + selection$$1.remove(); + save(changeset, true, false); // tryAgain = true, checkConflicts = false + }); + + selection$$1.call(ui); + } - v = partial.length === 0 - ? "{}" - : gap - ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" - : "{" + partial.join(",") + "}"; - gap = mind; - return v; - } - } -// If the JSON object does not yet have a stringify method, give it one. + function showErrors() { + keybindingOn(); + context.history().pop(); + loading.close(); + _isSaving = false; - if (typeof JSON.stringify !== "function") { - meta = { // table of character substitutions - "\b": "\\b", - "\t": "\\t", - "\n": "\\n", - "\f": "\\f", - "\r": "\\r", - "\"": "\\\"", - "\\": "\\\\" - }; - JSON.stringify = function (value, replacer, space) { + var selection$$1 = uiConfirm(context.container()); + selection$$1 + .select('.modal-section.header') + .append('h3') + .text(t('save.error')); -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. + addErrors(selection$$1, _errors); + selection$$1.okButton(); + } - var i; - gap = ""; - indent = ""; -// If the space parameter is a number, make an indent string containing that -// many spaces. + function addErrors(selection$$1, data) { + var message = selection$$1 + .select('.modal-section.message-text'); + + var items = message + .selectAll('.error-container') + .data(data); + + var enter = items.enter() + .append('div') + .attr('class', 'error-container'); + + enter + .append('a') + .attr('class', 'error-description') + .attr('href', '#') + .classed('hide-toggle', true) + .text(function(d) { return d.msg || t('save.unknown_error_details'); }) + .on('click', function() { + event.preventDefault(); + + var error = select(this); + var detail = select(this.nextElementSibling); + var exp = error.classed('expanded'); + + detail.style('display', exp ? 'none' : 'block'); + error.classed('expanded', !exp); + }); + + var details = enter + .append('div') + .attr('class', 'error-detail-container') + .style('display', 'none'); + + details + .append('ul') + .attr('class', 'error-detail-list') + .selectAll('li') + .data(function(d) { return d.details || []; }) + .enter() + .append('li') + .attr('class', 'error-detail-item') + .text(function(d) { return d; }); + + items.exit() + .remove(); + } - if (typeof space === "number") { - for (i = 0; i < space; i += 1) { - indent += " "; - } -// If the space parameter is a string, it will be used as the indent string. + function success(changeset) { + commit.reset(); - } else if (typeof space === "string") { - indent = space; - } + var ui = uiSuccess$$1(context) + .changeset(changeset) + .location(_location) + .on('cancel', function() { context.ui().sidebar.hide(); }); -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. + context.enter(modeBrowse(context).sidebar(ui)); + } - rep = replacer; - if (replacer && typeof replacer !== "function" && - (typeof replacer !== "object" || - typeof replacer.length !== "number")) { - throw new Error("JSON.stringify"); - } -// Make a fake root object containing our value under the key of "". -// Return the result of stringifying the value. + function keybindingOn() { + select(document) + .call(keybinding.on('⎋', cancel, true)); + } - return str("", {"": value}); - }; - } + function keybindingOff() { + select(document) + .call(keybinding.off); + } -// If the JSON object does not yet have a parse method, give it one. - if (typeof JSON.parse !== "function") { - JSON.parse = function (text, reviver) { + // Reverse geocode current map location so we can display a message on + // the success screen like "Thank you for editing around city, state." + function loadLocation() { + _location = null; + if (!services.geocoder) return; -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. + services.geocoder.reverse(context.map().center(), function(err, result) { + if (err || !result || !result.address) return; - var j; + var parts = []; + var addr = result.address; + var city = addr && (addr.town || addr.city || addr.county); + if (city) parts.push(city); + var region = addr && (addr.state || addr.country); + if (region) parts.push(region); - function walk(holder, key) { + _location = parts.join(', '); + }); + } -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - var k; - var v; - var value = holder[key]; - if (value && typeof value === "object") { - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } + mode.enter = function() { + function done() { + context.ui().sidebar.show(commit); + } + keybindingOn(); -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. + context.container().selectAll('#content') + .attr('class', 'inactive'); - text = String(text); - rx_dangerous.lastIndex = 0; - if (rx_dangerous.test(text)) { - text = text.replace(rx_dangerous, function (a) { - return "\\u" + - ("0000" + a.charCodeAt(0).toString(16)).slice(-4); - }); - } + var osm = context.connection(); + if (!osm) { + cancel(); + return; + } -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with "()" and "new" -// because they can cause invocation, and "=" because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with "@" (a non-JSON character). Second, we -// replace all simple value tokens with "]" characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or "]" or -// "," or ":" or "{" or "}". If that is so, then the text is safe for eval. - - if ( - rx_one.test( - text - .replace(rx_two, "@") - .replace(rx_three, "]") - .replace(rx_four, "") - ) - ) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The "{" operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval("(" + text + ")"); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return (typeof reviver === "function") - ? walk({"": j}, "") - : j; - } + if (osm.authenticated()) { + done(); + } else { + osm.authenticate(function(err) { + if (err) { + cancel(); + } else { + done(); + } + }); + } + }; -// If the text is not JSON parseable, then a SyntaxError is thrown. - throw new SyntaxError("JSON.parse"); - }; - } -}()); + mode.exit = function() { + _isSaving = false; -var json2 = json2Plugin; + keybindingOff(); -function json2Plugin() { - - return {} -} + context.container().selectAll('#content') + .attr('class', 'active'); -var plugins = [json2]; + context.ui().sidebar.hide(); + }; -var store_legacy = storeEngine.createStore(all$3, plugins); + return mode; + } -// # osm-auth -// -// This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo) -// object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing), -// does not support custom headers, which this uses everywhere. -var osmAuth = function(o) { + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMin$1 = Math.min; - var oauth = {}; + /** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin$1(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; - // authenticated users will also have a request token secret, but it's - // not used in transactions with the server - oauth.authenticated = function() { - return !!(token('oauth_token') && token('oauth_token_secret')); - }; + var index = -1, + seen = caches[0]; - oauth.logout = function() { - token('oauth_token', ''); - token('oauth_token_secret', ''); - token('oauth_request_token_secret', ''); - return oauth; - }; + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; - // TODO: detect lack of click event - oauth.authenticate = function(callback) { - if (oauth.authenticated()) return callback(); - - oauth.logout(); - - // ## Getting a request token - var params = timenonce(getAuth(o)), - url = o.url + '/oauth/request_token'; - - params.oauth_signature = ohauth_1.signature( - o.oauth_secret, '', - ohauth_1.baseString('POST', url, params)); - - if (!o.singlepage) { - // Create a 600x550 popup window in the center of the screen - var w = 600, h = 550, - settings = [ - ['width', w], ['height', h], - ['left', screen.width / 2 - w / 2], - ['top', screen.height / 2 - h / 2]].map(function(x) { - return x.join('='); - }).join(','), - popup = window.open('about:blank', 'oauth_window', settings); + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); } + result.push(value); + } + } + return result; + } - // Request a request token. When this is complete, the popup - // window is redirected to OSM's authorization page. - ohauth_1.xhr('POST', url, params, null, {}, reqTokenDone); - o.loading(); - - function reqTokenDone(err, xhr) { - o.done(); - if (err) return callback(err); - var resp = ohauth_1.stringQs(xhr.response); - token('oauth_request_token_secret', resp.oauth_token_secret); - var authorize_url = o.url + '/oauth/authorize?' + ohauth_1.qsString({ - oauth_token: resp.oauth_token, - oauth_callback: resolveUrl(o.landing) - }); + /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } - if (o.singlepage) { - location.href = authorize_url; - } else { - popup.location = authorize_url; - } - } + /** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; + }); - // Called by a function in a landing page, in the popup window. The - // window closes itself. - window.authComplete = function(token) { - var oauth_token = ohauth_1.stringQs(token.split('?')[1]); - get_access_token(oauth_token.oauth_token); - delete window.authComplete; - }; + // Translate a MacOS key command into the appropriate Windows/Linux equivalent. + // For example, ⌘Z -> Ctrl+Z + var uiCmd = function (code) { + var detected = utilDetect(); - // ## Getting an request token - // - // At this point we have an `oauth_token`, brought in from a function - // call on a landing page popup. - function get_access_token(oauth_token) { - var url = o.url + '/oauth/access_token', - params = timenonce(getAuth(o)), - request_token_secret = token('oauth_request_token_secret'); - params.oauth_token = oauth_token; - params.oauth_signature = ohauth_1.signature( - o.oauth_secret, - request_token_secret, - ohauth_1.baseString('POST', url, params)); - - // ## Getting an access token - // - // The final token required for authentication. At this point - // we have a `request token secret` - ohauth_1.xhr('POST', url, params, null, {}, accessTokenDone); - o.loading(); - } + if (detected.os === 'mac') { + return code; + } - function accessTokenDone(err, xhr) { - o.done(); - if (err) return callback(err); - var access_token = ohauth_1.stringQs(xhr.response); - token('oauth_token', access_token.oauth_token); - token('oauth_token_secret', access_token.oauth_token_secret); - callback(null, oauth); - } - }; + if (detected.os === 'win') { + if (code === '⌘⇧Z') return 'Ctrl+Y'; + } - oauth.bootstrapToken = function(oauth_token, callback) { - // ## Getting an request token - // At this point we have an `oauth_token`, brought in from a function - // call on a landing page popup. - function get_access_token(oauth_token) { - var url = o.url + '/oauth/access_token', - params = timenonce(getAuth(o)), - request_token_secret = token('oauth_request_token_secret'); - params.oauth_token = oauth_token; - params.oauth_signature = ohauth_1.signature( - o.oauth_secret, - request_token_secret, - ohauth_1.baseString('POST', url, params)); - - // ## Getting an access token - // The final token required for authentication. At this point - // we have a `request token secret` - ohauth_1.xhr('POST', url, params, null, {}, accessTokenDone); - o.loading(); - } + var result = '', + replacements = { + '⌘': 'Ctrl', + '⇧': 'Shift', + '⌥': 'Alt', + '⌫': 'Backspace', + '⌦': 'Delete' + }; - function accessTokenDone(err, xhr) { - o.done(); - if (err) return callback(err); - var access_token = ohauth_1.stringQs(xhr.response); - token('oauth_token', access_token.oauth_token); - token('oauth_token_secret', access_token.oauth_token_secret); - callback(null, oauth); - } + for (var i = 0; i < code.length; i++) { + if (code[i] in replacements) { + result += replacements[code[i]] + (i < code.length - 1 ? '+' : ''); + } else { + result += code[i]; + } + } - get_access_token(oauth_token); - }; + return result; + }; - // # xhr - // - // A single XMLHttpRequest wrapper that does authenticated calls if the - // user has logged in. - oauth.xhr = function(options, callback) { - if (!oauth.authenticated()) { - if (o.auto) { - return oauth.authenticate(run); - } else { - callback('not authenticated', null); - return; - } - } else { - return run(); - } - function run() { - var params = timenonce(getAuth(o)), - oauth_token_secret = token('oauth_token_secret'), - url = (options.prefix !== false) ? o.url + options.path : options.path, - url_parts = url.replace(/#.*$/, '').split('?', 2), - base_url = url_parts[0], - query = (url_parts.length === 2) ? url_parts[1] : ''; - - // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1 - if ((!options.options || !options.options.header || - options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') && - options.content) { - params = immutable(params, ohauth_1.stringQs(options.content)); - } + // return a display-focused string for a given keyboard code + uiCmd.display = function(code) { + if (code.length !== 1) return code; + + var detected = utilDetect(); + var mac = (detected.os === 'mac'); + var replacements = { + '⌘': mac ? '⌘ ' + t('shortcuts.key.cmd') : t('shortcuts.key.ctrl'), + '⇧': mac ? '⇧ ' + t('shortcuts.key.shift') : t('shortcuts.key.shift'), + '⌥': mac ? '⌥ ' + t('shortcuts.key.option') : t('shortcuts.key.alt'), + '⌃': mac ? '⌃ ' + t('shortcuts.key.ctrl') : t('shortcuts.key.ctrl'), + '⌫': mac ? '⌫ ' + t('shortcuts.key.delete') : t('shortcuts.key.backspace'), + '⌦': mac ? '⌦ ' + t('shortcuts.key.del') : t('shortcuts.key.del'), + '↖': mac ? '↖ ' + t('shortcuts.key.pgup') : t('shortcuts.key.pgup'), + '↘': mac ? '↘ ' + t('shortcuts.key.pgdn') : t('shortcuts.key.pgdn'), + '⇞': mac ? '⇞ ' + t('shortcuts.key.home') : t('shortcuts.key.home'), + '⇟': mac ? '⇟ ' + t('shortcuts.key.end') : t('shortcuts.key.end'), + '↵': mac ? '↵ ' + t('shortcuts.key.return') : t('shortcuts.key.enter'), + '⎋': mac ? '⎋ ' + t('shortcuts.key.esc') : t('shortcuts.key.esc'), + }; - params.oauth_token = token('oauth_token'); - params.oauth_signature = ohauth_1.signature( - o.oauth_secret, - oauth_token_secret, - ohauth_1.baseString(options.method, base_url, immutable(params, ohauth_1.stringQs(query))) - ); + return replacements[code] || code; + }; - return ohauth_1.xhr(options.method, url, params, options.content, options.options, done); - } + var relatedParent; - function done(err, xhr) { - if (err) return callback(err); - else if (xhr.responseXML) return callback(err, xhr.responseXML); - else return callback(err, xhr.response); - } - }; - // pre-authorize this object, if we can just get a token and token_secret - // from the start - oauth.preauth = function(c) { - if (!c) return; - if (c.oauth_token) token('oauth_token', c.oauth_token); - if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret); - return oauth; - }; + function modeSelect(context, selectedIDs) { + var mode = { + id: 'select', + button: 'browse' + }; - oauth.options = function(_) { - if (!arguments.length) return o; + var keybinding = d3keybinding('select'); + var timeout = null; + var behaviors = [ + behaviorCopy(context), + behaviorPaste(context), + behaviorBreathe(context), + behaviorHover(context), + behaviorSelect(context), + behaviorLasso(context), + modeDragNode$$1(context).restoreSelectedIDs(selectedIDs).behavior + ]; + var inspector; + var editMenu; + var newFeature = false; + var suppressMenu = true; + var follow = false; - o = _; - o.url = o.url || 'https://www.openstreetmap.org'; - o.landing = o.landing || 'land.html'; - o.singlepage = o.singlepage || false; - // Optional loading and loading-done functions for nice UI feedback. - // by default, no-ops - o.loading = o.loading || function() {}; - o.done = o.done || function() {}; + var wrap = context.container() + .select('.inspector-wrap'); - return oauth.preauth(o); - }; - // 'stamp' an authentication object from `getAuth()` - // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce) - // and timestamp - function timenonce(o) { - o.oauth_timestamp = ohauth_1.timestamp(); - o.oauth_nonce = ohauth_1.nonce(); - return o; - } + function singular() { + if (selectedIDs.length === 1) { + return context.hasEntity(selectedIDs[0]); + } + } - // get/set tokens. These are prefixed with the base URL so that `osm-auth` - // can be used with multiple APIs and the keys in `localStorage` - // will not clash - var token; - if (store_legacy.enabled) { - token = function (x, y) { - if (arguments.length === 1) return store_legacy.get(o.url + x); - else if (arguments.length === 2) return store_legacy.set(o.url + x, y); - }; - } else { - var storage = {}; - token = function (x, y) { - if (arguments.length === 1) return storage[o.url + x]; - else if (arguments.length === 2) return storage[o.url + x] = y; - }; - } + function checkSelectedIDs() { + var ids = []; + if (Array.isArray(selectedIDs)) { + ids = selectedIDs.filter(function(id) { + return context.hasEntity(id); + }); + } - // Get an authentication object. If you just add and remove properties - // from a single object, you'll need to use `delete` to make sure that - // it doesn't contain undesired properties for authentication - function getAuth(o) { - return { - oauth_consumer_key: o.oauth_consumer_key, - oauth_signature_method: 'HMAC-SHA1' - }; - } + if (ids.length) { + selectedIDs = ids; + } else { + context.enter(modeBrowse(context)); + } + return !!ids.length; + } - // potentially pre-authorize - oauth.options(o); - return oauth; -}; + // find the common parent ways for nextVertex, previousVertex + function commonParents() { + var graph = context.graph(); + var commonParents = []; -var JXON = new (function () { - var - sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */ - aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i; + for (var i = 0; i < selectedIDs.length; i++) { + var entity = context.hasEntity(selectedIDs[i]); + if (!entity || entity.geometry(graph) !== 'vertex') { + return []; // selection includes some not vertexes + } - function parseText (sValue) { - if (rIsNull.test(sValue)) { return null; } - if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; } - if (isFinite(sValue)) { return parseFloat(sValue); } - if (isFinite(Date.parse(sValue))) { return new Date(sValue); } - return sValue; - } + var currParents = map$3(graph.parentWays(entity), 'id'); + if (!commonParents.length) { + commonParents = currParents; + continue; + } - function EmptyTree () { } - EmptyTree.prototype.toString = function () { return 'null'; }; - EmptyTree.prototype.valueOf = function () { return null; }; + commonParents = intersection(commonParents, currParents); + if (!commonParents.length) { + return []; + } + } - function objectify (vValue) { - return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue); - } + return commonParents; + } - function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) { - var - nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(), - bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2); - var - sProp, vContent, nLength = 0, sCollectedTxt = '', - vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true; + function singularParent() { + var parents = commonParents(); + if (!parents || parents.length === 0) { + relatedParent = null; + return null; + } + + // relatedParent is used when we visit a vertex with multiple + // parents, and we want to remember which parent line we started on. + + if (parents.length === 1) { + relatedParent = parents[0]; // remember this parent for later + return relatedParent; + } + + if (parents.indexOf(relatedParent) !== -1) { + return relatedParent; // prefer the previously seen parent + } - if (bChildren) { - for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) { - oNode = oParentNode.childNodes.item(nItem); - if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */ - else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */ - else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */ + return parents[0]; } - } - var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt); - if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; } + function closeMenu() { + if (editMenu) { + context.surface().call(editMenu.close); + } + } - for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) { - sProp = aCache[nElId].nodeName.toLowerCase(); - vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr); - if (vResult.hasOwnProperty(sProp)) { - if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; } - vResult[sProp].push(vContent); - } else { - vResult[sProp] = vContent; - nLength++; + + function positionMenu() { + if (!editMenu) { return; } + + var entity = singular(); + if (entity && context.geometry(entity.id) === 'relation') { + suppressMenu = true; + } else { + var point$$1 = context.mouse(); + var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(); + + if (point$$1 && geoPointInPolygon(point$$1, viewport)) { + editMenu.center(point$$1); + } else { + suppressMenu = true; + } + } } - } - if (bAttributes) { - var - nAttrLen = oParentNode.attributes.length, - sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult; - for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) { - oAttrib = oParentNode.attributes.item(nAttrib); - oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim()); + function showMenu() { + closeMenu(); + if (editMenu) { + context.surface().call(editMenu); + } } - if (bNesteAttr) { - if (bFreeze) { Object.freeze(oAttrParent); } - vResult[sAttributesProp] = oAttrParent; - nLength -= nAttrLen - 1; + + function toggleMenu() { + // deprecation warning - Radial Menu to be removed in iD v3 + if (select('.edit-menu, .radial-menu').empty()) { + positionMenu(); + showMenu(); + } else { + closeMenu(); + } } - } - if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) { - vResult[sValueProp] = vBuiltVal; - } else if (!bHighVerb && nLength === 0 && sCollectedTxt) { - vResult = vBuiltVal; - } - if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); } + mode.selectedIDs = function() { + return selectedIDs; + }; + - aCache.length = nLevelStart; + mode.reselect = function() { + if (!checkSelectedIDs()) return; - return vResult; - } + var surfaceNode = context.surface().node(); + if (surfaceNode.focus) { // FF doesn't support it + surfaceNode.focus(); + } - function loadObjTree (oXMLDoc, oParentEl, oParentObj) { - var vValue, oChild; + positionMenu(); + if (!suppressMenu) { + showMenu(); + } + }; - if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) { - oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */ - } else if (oParentObj.constructor === Date) { - oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString())); - } - for (var sName in oParentObj) { - vValue = oParentObj[sName]; - if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */ - if (sName === sValueProp) { - if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); } - } else if (sName === sAttributesProp) { /* verbosity level is 3 */ - for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); } - } else if (sName.charAt(0) === sAttrPref) { - oParentEl.setAttribute(sName.slice(1), vValue); - } else if (vValue.constructor === Array) { - for (var nItem = 0; nItem < vValue.length; nItem++) { - oChild = oXMLDoc.createElement(sName); - loadObjTree(oXMLDoc, oChild, vValue[nItem]); - oParentEl.appendChild(oChild); - } - } else { - oChild = oXMLDoc.createElement(sName); - if (vValue instanceof Object) { - loadObjTree(oXMLDoc, oChild, vValue); - } else if (vValue !== null && vValue !== true) { - oChild.appendChild(oXMLDoc.createTextNode(vValue.toString())); - } - oParentEl.appendChild(oChild); - } - } - } + mode.newFeature = function(_) { + if (!arguments.length) return newFeature; + newFeature = _; + return mode; + }; - this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) { - var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1; - return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3); - }; - this.unbuild = function (oObjTree) { - var oNewDoc = document.implementation.createDocument('', '', null); - loadObjTree(oNewDoc, oNewDoc, oObjTree); - return oNewDoc; - }; + mode.suppressMenu = function(_) { + if (!arguments.length) return suppressMenu; + suppressMenu = _; + return mode; + }; - this.stringify = function (oObjTree) { - return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree)); - }; -})(); -// var myObject = JXON.build(doc); -// we got our javascript object! try: alert(JSON.stringify(myObject)); + mode.follow = function(_) { + if (!arguments.length) return follow; + follow = _; + return mode; + }; -// var newDoc = JXON.unbuild(myObject); -// we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc)); -var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded'); -var urlroot = 'https://www.openstreetmap.org'; -var oauth = osmAuth({ - url: urlroot, - oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT', - oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL', - loading: authLoading, - done: authDone -}); + mode.enter = function() { -var _blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*']; -var _tiles = { loaded: {}, inflight: {} }; -var _changeset = {}; -var _entityCache = {}; -var _connectionID = 1; -var _tileZoom = 16; -var _rateLimitError; -var _userChangesets; -var _userDetails; -var _off; + function update() { + closeMenu(); + checkSelectedIDs(); + } -function authLoading() { - dispatch$3.call('authLoading'); -} + function dblclick() { + var target = select(event.target); + var datum = target.datum(); + var entity = datum && datum.properties && datum.properties.entity; + if (!entity) return; -function authDone() { - dispatch$3.call('authDone'); -} + if (entity instanceof osmWay && target.classed('target')) { + var choice = geoChooseEdge(context.childNodes(entity), context.mouse(), context.projection); + var prev = entity.nodes[choice.index - 1]; + var next = entity.nodes[choice.index]; + context.perform( + actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, osmNode()), + t('operations.add.annotation.vertex') + ); -function abortRequest$2(i) { - if (i) { - i.abort(); - } -} + event.preventDefault(); + event.stopPropagation(); + } else if (entity.type === 'midpoint') { + context.perform( + actionAddMidpoint({loc: entity.loc, edge: entity.edge}, osmNode()), + t('operations.add.annotation.vertex')); -function getLoc(attrs) { - var lon = attrs.lon && attrs.lon.value; - var lat = attrs.lat && attrs.lat.value; - return [parseFloat(lon), parseFloat(lat)]; -} + event.preventDefault(); + event.stopPropagation(); + } + } -function getNodes(obj) { - var elems = obj.getElementsByTagName('nd'); - var nodes = new Array(elems.length); - for (var i = 0, l = elems.length; i < l; i++) { - nodes[i] = 'n' + elems[i].attributes.ref.value; - } - return nodes; -} + function selectElements(drawn) { + if (!checkSelectedIDs()) return; + + var surface = context.surface(); + var entity = singular(); + + if (entity && context.geometry(entity.id) === 'relation') { + suppressMenu = true; + return; + } + + surface.selectAll('.related') + .classed('related', false); + + singularParent(); + if (relatedParent) { + surface.selectAll(utilEntitySelector([relatedParent])) + .classed('related', true); + } + + var selection$$1 = context.surface() + .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph())); + + if (selection$$1.empty()) { + // Return to browse mode if selected DOM elements have + // disappeared because the user moved them out of view.. + var source = event && event.type === 'zoom' && event.sourceEvent; + if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) { + context.enter(modeBrowse(context)); + } + } else { + selection$$1 + .classed('selected', true); + } + } -function getTags(obj) { - var elems = obj.getElementsByTagName('tag'); - var tags = {}; - for (var i = 0, l = elems.length; i < l; i++) { - var attrs = elems[i].attributes; - tags[attrs.k.value] = attrs.v.value; - } + function esc() { + context.enter(modeBrowse(context)); + } - return tags; -} + function firstVertex() { + event.preventDefault(); + var entity = singular(); + var parent = singularParent(); + var way; -function getMembers(obj) { - var elems = obj.getElementsByTagName('member'); - var members = new Array(elems.length); - for (var i = 0, l = elems.length; i < l; i++) { - var attrs = elems[i].attributes; - members[i] = { - id: attrs.type.value[0] + attrs.ref.value, - type: attrs.type.value, - role: attrs.role.value - }; - } - return members; -} + if (entity && entity.type === 'way') { + way = entity; + } else if (parent) { + way = context.entity(parent); + } + if (way) { + context.enter( + modeSelect(context, [way.first()]).follow(true) + ); + } + } -function getVisible(attrs) { - return (!attrs.visible || attrs.visible.value !== 'false'); -} + function lastVertex() { + event.preventDefault(); + var entity = singular(); + var parent = singularParent(); + var way; -var parsers = { - node: function nodeData(obj, uid) { - var attrs = obj.attributes; - return new osmNode({ - id:uid, - visible: getVisible(attrs), - version: attrs.version.value, - changeset: attrs.changeset && attrs.changeset.value, - timestamp: attrs.timestamp && attrs.timestamp.value, - user: attrs.user && attrs.user.value, - uid: attrs.uid && attrs.uid.value, - loc: getLoc(attrs), - tags: getTags(obj) - }); - }, + if (entity && entity.type === 'way') { + way = entity; + } else if (parent) { + way = context.entity(parent); + } - way: function wayData(obj, uid) { - var attrs = obj.attributes; - return new osmWay({ - id: uid, - visible: getVisible(attrs), - version: attrs.version.value, - changeset: attrs.changeset && attrs.changeset.value, - timestamp: attrs.timestamp && attrs.timestamp.value, - user: attrs.user && attrs.user.value, - uid: attrs.uid && attrs.uid.value, - tags: getTags(obj), - nodes: getNodes(obj), - }); - }, + if (way) { + context.enter( + modeSelect(context, [way.last()]).follow(true) + ); + } + } - relation: function relationData(obj, uid) { - var attrs = obj.attributes; - return new osmRelation({ - id: uid, - visible: getVisible(attrs), - version: attrs.version.value, - changeset: attrs.changeset && attrs.changeset.value, - timestamp: attrs.timestamp && attrs.timestamp.value, - user: attrs.user && attrs.user.value, - uid: attrs.uid && attrs.uid.value, - tags: getTags(obj), - members: getMembers(obj) - }); - } -}; + function previousVertex() { + event.preventDefault(); + var parent = singularParent(); + if (!parent) return; -function parse(xml$$1, callback, options) { - options = assignIn({ cache: true }, options); - if (!xml$$1 || !xml$$1.childNodes) return; + var way = context.entity(parent); + var length = way.nodes.length; + var curr = way.nodes.indexOf(selectedIDs[0]); + var index = -1; - var root = xml$$1.childNodes[0]; - var children = root.childNodes; + if (curr > 0) { + index = curr - 1; + } else if (way.isClosed()) { + index = length - 2; + } - function parseChild(child) { - var parser = parsers[child.nodeName]; - if (parser) { - var uid = osmEntity$$1.id.fromOSM(child.nodeName, child.attributes.id.value); - if (options.cache && _entityCache[uid]) { - return null; - } - return parser(child, uid); - } - } + if (index !== -1) { + context.enter( + modeSelect(context, [way.nodes[index]]).follow(true) + ); + } + } - utilIdleWorker(children, parseChild, callback); -} + function nextVertex() { + event.preventDefault(); + var parent = singularParent(); + if (!parent) return; -var serviceOsm = { + var way = context.entity(parent); + var length = way.nodes.length; + var curr = way.nodes.indexOf(selectedIDs[0]); + var index = -1; - init: function() { - utilRebind(this, dispatch$3, 'on'); - }, + if (curr < length - 1) { + index = curr + 1; + } else if (way.isClosed()) { + index = 0; + } + if (index !== -1) { + context.enter( + modeSelect(context, [way.nodes[index]]).follow(true) + ); + } + } - reset: function() { - _connectionID++; - _userChangesets = undefined; - _userDetails = undefined; - _rateLimitError = undefined; - forEach(_tiles.inflight, abortRequest$2); - if (_changeset.inflight) abortRequest$2(_changeset.inflight); - _tiles = { loaded: {}, inflight: {} }; - _changeset = {}; - _entityCache = {}; - return this; - }, + function nextParent() { + event.preventDefault(); + var parents = uniq(commonParents()); + if (!parents || parents.length < 2) return; - getConnectionId: function() { - return _connectionID; - }, + var index = parents.indexOf(relatedParent); + if (index < 0 || index > parents.length - 2) { + relatedParent = parents[0]; + } else { + relatedParent = parents[index + 1]; + } + var surface = context.surface(); + surface.selectAll('.related') + .classed('related', false); - changesetURL: function(changesetId) { - return urlroot + '/changeset/' + changesetId; - }, + if (relatedParent) { + surface.selectAll(utilEntitySelector([relatedParent])) + .classed('related', true); + } + } - changesetsURL: function(center, zoom) { - var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)); - return urlroot + '/history#map=' + - Math.floor(zoom) + '/' + - center[1].toFixed(precision) + '/' + - center[0].toFixed(precision); - }, + if (!checkSelectedIDs()) return; + var operations = without(values$1(Operations), operationDelete) + .map(function(o) { return o(selectedIDs, context); }) + .filter(function(o) { return o.available(); }); - entityURL: function(entity) { - return urlroot + '/' + entity.type + '/' + entity.osmId(); - }, + // deprecation warning - Radial Menu to be removed in iD v3 + var isRadialMenu = context.storage('edit-menu-style') === 'radial'; + if (isRadialMenu) { + operations = operations.slice(0,7); + operations.unshift(operationDelete(selectedIDs, context)); + } else { + operations.push(operationDelete(selectedIDs, context)); + } + operations.forEach(function(operation) { + if (operation.behavior) { + behaviors.push(operation.behavior); + } + }); - historyURL: function(entity) { - return urlroot + '/' + entity.type + '/' + entity.osmId() + '/history'; - }, + behaviors.forEach(function(behavior) { + context.install(behavior); + }); + keybinding + .on(['[', 'pgup'], previousVertex) + .on([']', 'pgdown'], nextVertex) + .on(['{', uiCmd('⌘['), 'home'], firstVertex) + .on(['}', uiCmd('⌘]'), 'end'], lastVertex) + .on(['\\', 'pause'], nextParent) + .on('⎋', esc, true) + .on('space', toggleMenu); - userURL: function(username) { - return urlroot + '/user/' + username; - }, + select(document) + .call(keybinding); - loadFromAPI: function(path, callback, options) { - options = assignIn({ cache: true }, options); - var that = this; - var cid = _connectionID; + // deprecation warning - Radial Menu to be removed in iD v3 + editMenu = isRadialMenu + ? uiRadialMenu(context, operations) + : uiEditMenu(context, operations); - function done(err, xml$$1) { - if (that.getConnectionId() !== cid) { - if (callback) callback({ message: 'Connection Switched', status: -1 }); - return; - } + context.ui().sidebar + .select(singular() ? singular().id : null, newFeature); - var isAuthenticated = that.authenticated(); + context.history() + .on('undone.select', update) + .on('redone.select', update); - // 400 Bad Request, 401 Unauthorized, 403 Forbidden - // Logout and retry the request.. - if (isAuthenticated && err && (err.status === 400 || err.status === 401 || err.status === 403)) { - that.logout(); - that.loadFromAPI(path, callback); + context.map() + .on('move.select', closeMenu) + .on('drawn.select', selectElements); - // else, no retry.. - } else { - // 509 Bandwidth Limit Exceeded, 429 Too Many Requests - // Set the rateLimitError flag and trigger a warning.. - if (!isAuthenticated && !_rateLimitError && err && - (err.status === 509 || err.status === 429)) { - _rateLimitError = err; - dispatch$3.call('change'); - } - - if (callback) { - if (err) return callback(err, null); - parse(xml$$1, function (entities) { - if (options.cache) { - for (var i in entities) { - _entityCache[entities[i].id] = true; - } - } - callback(null, entities); - }, options); - } - } - } + context.surface() + .on('dblclick.select', dblclick); - if (this.authenticated()) { - return oauth.xhr({ method: 'GET', path: path }, done); - } else { - var url = urlroot + path; - return d3_xml(url).get(done); - } - }, + selectElements(); - loadEntity: function(id, callback) { - var type = osmEntity$$1.id.type(id); - var osmID = osmEntity$$1.id.toOSM(id); - var options = { cache: false }; + if (selectedIDs.length > 1) { + var entities = uiSelectionList(context, selectedIDs); + context.ui().sidebar.show(entities); + } - this.loadFromAPI( - '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''), - function(err, entities) { - if (callback) callback(err, { data: entities }); - }, - options - ); - }, + if (follow) { + var extent = geoExtent$$1(); + var graph = context.graph(); + selectedIDs.forEach(function(id) { + var entity = context.entity(id); + extent._extend(entity.extent(graph)); + }); + + var loc = extent.center(); + context.map().centerEase(loc); + } else if (singular() && singular().type === 'way') { + context.map().pan([0,0]); // full redraw, to adjust z-sorting #2914 + } + timeout = window.setTimeout(function() { + positionMenu(); + if (!suppressMenu) { + showMenu(); + } + }, 270); /* after any centerEase completes */ - loadEntityVersion: function(id, version, callback) { - var type = osmEntity$$1.id.type(id); - var osmID = osmEntity$$1.id.toOSM(id); - var options = { cache: false }; + }; - this.loadFromAPI( - '/api/0.6/' + type + '/' + osmID + '/' + version, - function(err, entities) { - if (callback) callback(err, { data: entities }); - }, - options - ); - }, + mode.exit = function() { + if (timeout) window.clearTimeout(timeout); + if (inspector) wrap.call(inspector.close); - loadMultiple: function(ids, callback) { - var that = this; + behaviors.forEach(function(behavior) { + context.uninstall(behavior); + }); - forEach(groupBy(uniq(ids), osmEntity$$1.id.type), function(v, k) { - var type = k + 's'; - var osmIDs = map$3(v, osmEntity$$1.id.toOSM); - var options = { cache: false }; + keybinding.off(); + closeMenu(); + editMenu = undefined; - forEach(chunk(osmIDs, 150), function(arr) { - that.loadFromAPI( - '/api/0.6/' + type + '?' + type + '=' + arr.join(), - function(err, entities) { - if (callback) callback(err, { data: entities }); - }, - options - ); - }); - }); - }, + context.history() + .on('undone.select', null) + .on('redone.select', null); + var surface = context.surface(); - authenticated: function() { - return oauth.authenticated(); - }, + surface + .on('dblclick.select', null); + surface + .selectAll('.selected') + .classed('selected', false); - putChangeset: function(changeset, changes, callback) { - if (_changeset.inflight) { - return callback({ message: 'Changeset already inflight', status: -2 }, changeset); - } + surface + .selectAll('.related') + .classed('related', false); - var that = this; - var cid = _connectionID; - - if (_changeset.open) { // reuse existing open changeset.. - createdChangeset(null, _changeset.open); - } else { // open a new changeset.. - _changeset.inflight = oauth.xhr({ - method: 'PUT', - path: '/api/0.6/changeset/create', - options: { header: { 'Content-Type': 'text/xml' } }, - content: JXON.stringify(changeset.asJXON()) - }, createdChangeset); - } + context.map().on('drawn.select', null); + context.ui().sidebar.hide(); + }; - function createdChangeset(err, changesetID) { - _changeset.inflight = null; + return mode; + } - if (err) { - // 400 Bad Request, 401 Unauthorized, 403 Forbidden.. - if (err.status === 400 || err.status === 401 || err.status === 403) { - that.logout(); - } - return callback(err, changeset); - } - if (that.getConnectionId() !== cid) { - return callback({ message: 'Connection Switched', status: -1 }, changeset); - } + function behaviorAddWay(context) { + var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'), + draw = behaviorDraw(context); - _changeset.open = changesetID; - changeset = changeset.update({ id: changesetID }); + var addWay = function(surface) { + draw.on('click', function() { dispatch$$1.apply('start', this, arguments); }) + .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); }) + .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); }) + .on('cancel', addWay.cancel) + .on('finish', addWay.cancel); - // Upload the changeset.. - _changeset.inflight = oauth.xhr({ - method: 'POST', - path: '/api/0.6/changeset/' + changesetID + '/upload', - options: { header: { 'Content-Type': 'text/xml' } }, - content: JXON.stringify(changeset.osmChangeJXON(changes)) - }, uploadedChangeset); - } + context.map() + .dblclickEnable(false); + surface.call(draw); + }; - function uploadedChangeset(err) { - _changeset.inflight = null; - if (err) return callback(err, changeset); + addWay.off = function(surface) { + surface.call(draw.off); + }; - // Upload was successful, safe to call the callback. - // Add delay to allow for postgres replication #1646 #2678 - window.setTimeout(function() { - callback(null, changeset); - }, 2500); - _changeset.open = null; + addWay.cancel = function() { + window.setTimeout(function() { + context.map().dblclickEnable(true); + }, 1000); - // At this point, we don't really care if the connection was switched.. - // Only try to close the changeset if we're still talking to the same server. - if (that.getConnectionId() === cid) { - // Still attempt to close changeset, but ignore response because #2667 - oauth.xhr({ - method: 'PUT', - path: '/api/0.6/changeset/' + changeset.id + '/close', - options: { header: { 'Content-Type': 'text/xml' } } - }, function() { return true; }); - } - } - }, + context.enter(modeBrowse(context)); + }; - userDetails: function(callback) { - if (_userDetails) { - callback(undefined, _userDetails); - return; - } + addWay.tail = function(text) { + draw.tail(text); + return addWay; + }; - var that = this; - var cid = _connectionID; - function done(err, user_details) { - if (err) { - // 400 Bad Request, 401 Unauthorized, 403 Forbidden.. - if (err.status === 400 || err.status === 401 || err.status === 403) { - that.logout(); - } - return callback(err); - } - if (that.getConnectionId() !== cid) { - return callback({ message: 'Connection Switched', status: -1 }); - } + return utilRebind(addWay, dispatch$$1, 'on'); + } + function behaviorBreathe() { + var duration = 800, + steps = 4, + selector$$1 = '.selected.shadow, .selected .shadow', + selected = select(null), + classed = '', + params = {}, + done = false, + timer$$1; - var u = user_details.getElementsByTagName('user')[0]; - var img = u.getElementsByTagName('img'); - var image_url = ''; - if (img && img[0] && img[0].getAttribute('href')) { - image_url = img[0].getAttribute('href'); - } + function ratchetyInterpolator(a, b, steps, units) { + a = parseFloat(a); + b = parseFloat(b); + var sample = quantize() + .domain([0, 1]) + .range(d3_quantize(interpolateNumber(a, b), steps)); - var changesets = u.getElementsByTagName('changesets'); - var changesets_count = 0; + return function(t) { + return String(sample(t)) + (units || ''); + }; + } - if (changesets && changesets[0] && changesets[0].getAttribute('count')) { - changesets_count = changesets[0].getAttribute('count'); - } - _userDetails = { - id: u.attributes.id.value, - display_name: u.attributes.display_name.value, - image_url: image_url, - changesets_count: changesets_count - }; + function reset(selection$$1) { + selection$$1 + .style('stroke-opacity', null) + .style('stroke-width', null) + .style('fill-opacity', null) + .style('r', null); + } - callback(undefined, _userDetails); - } - oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done); - }, + function setAnimationParams(transition, fromTo) { + var toFrom = (fromTo === 'from' ? 'to' : 'from'); + + transition + .styleTween('stroke-opacity', function(d) { + return ratchetyInterpolator( + params[d.id][toFrom].opacity, + params[d.id][fromTo].opacity, + steps + ); + }) + .styleTween('stroke-width', function(d) { + return ratchetyInterpolator( + params[d.id][toFrom].width, + params[d.id][fromTo].width, + steps, + 'px' + ); + }) + .styleTween('fill-opacity', function(d) { + return ratchetyInterpolator( + params[d.id][toFrom].opacity, + params[d.id][fromTo].opacity, + steps + ); + }) + .styleTween('r', function(d) { + return ratchetyInterpolator( + params[d.id][toFrom].width, + params[d.id][fromTo].width, + steps, + 'px' + ); + }); + } - userChangesets: function(callback) { - if (_userChangesets) { - callback(undefined, _userChangesets); - return; - } + function calcAnimationParams(selection$$1) { + selection$$1 + .call(reset) + .each(function(d) { + var s = select(this), + tag = s.node().tagName, + p = {'from': {}, 'to': {}}, + opacity, width; + + // determine base opacity and width + if (tag === 'circle') { + opacity = parseFloat(s.style('fill-opacity') || 0.5); + width = parseFloat(s.style('r') || 15.5); + } else { + opacity = parseFloat(s.style('stroke-opacity') || 0.7); + width = parseFloat(s.style('stroke-width') || 10); + } + + // calculate from/to interpolation params.. + p.tag = tag; + p.from.opacity = opacity * 0.6; + p.to.opacity = opacity * 1.25; + p.from.width = width * 0.7; + p.to.width = width * (tag === 'circle' ? 1.5 : 1); + params[d.id] = p; + }); + } - var that = this; - var cid = _connectionID; - this.userDetails(function(err, user) { - if (err) { - return callback(err); - } - if (that.getConnectionId() !== cid) { - return callback({ message: 'Connection Switched', status: -1 }); - } + function run(surface, fromTo) { + var toFrom = (fromTo === 'from' ? 'to' : 'from'), + currSelected = surface.selectAll(selector$$1), + currClassed = surface.attr('class'); - function done(err, changesets) { - if (err) { - // 400 Bad Request, 401 Unauthorized, 403 Forbidden.. - if (err.status === 400 || err.status === 401 || err.status === 403) { - that.logout(); - } - return callback(err); - } - if (that.getConnectionId() !== cid) { - return callback({ message: 'Connection Switched', status: -1 }); - } - - _userChangesets = Array.prototype.map.call( - changesets.getElementsByTagName('changeset'), - function (changeset) { - return { tags: getTags(changeset) }; - } - ).filter(function (changeset) { - var comment = changeset.tags.comment; - return comment && comment !== ''; - }); - - callback(undefined, _userChangesets); - } + if (done || currSelected.empty()) { + selected.call(reset); + return; + } - oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done); - }); - }, + if (!isEqual(currSelected.data(), selected.data()) || currClassed !== classed) { + selected.call(reset); + classed = currClassed; + selected = currSelected.call(calcAnimationParams); + } + selected + .transition() + .duration(duration) + .call(setAnimationParams, fromTo) + .on('end', function() { + surface.call(run, toFrom); + }); + } - status: function(callback) { - var that = this; - var cid = _connectionID; - function done(xml$$1) { - if (that.getConnectionId() !== cid) { - return callback({ message: 'Connection Switched', status: -1 }, 'connectionSwitched'); - } + var breathe = function(surface) { + done = false; + timer$$1 = timer(function() { + // wait for elements to actually become selected + if (surface.selectAll(selector$$1).empty()) { + return false; + } - // update blacklists - var elements = xml$$1.getElementsByTagName('blacklist'); - var regexes = []; - for (var i = 0; i < elements.length; i++) { - var regex = elements[i].getAttribute('regex'); // needs unencode? - if (regex) { - regexes.push(regex); - } - } - if (regexes.length) { - _blacklists = regexes; - } + surface.call(run, 'from'); + timer$$1.stop(); + return true; + }, 20); + }; - if (_rateLimitError) { - callback(_rateLimitError, 'rateLimited'); - } else { - var apiStatus = xml$$1.getElementsByTagName('status'); - var val = apiStatus[0].getAttribute('api'); + breathe.off = function() { + done = true; + if (timer$$1) { + timer$$1.stop(); + } + selected + .interrupt() + .call(reset); + }; - callback(undefined, val); - } - } - d3_xml(urlroot + '/api/capabilities').get() - .on('load', done) - .on('error', callback); - }, + return breathe; + } + function behaviorCopy(context) { + var keybinding = d3keybinding('copy'); - imageryBlacklists: function() { - return _blacklists; - }, + function groupEntities(ids, graph) { + var entities = ids.map(function (id) { return graph.entity(id); }); + return assignIn({relation: [], way: [], node: []}, + groupBy(entities, function(entity) { return entity.type; })); + } - tileZoom: function(_) { - if (!arguments.length) return _tileZoom; - _tileZoom = _; - return this; - }, + function getDescendants(id, graph, descendants) { + var entity = graph.entity(id), + i, children; - loadTiles: function(projection, dimensions, callback) { - if (_off) return; + descendants = descendants || {}; - var that = this; - var s = projection.scale() * 2 * Math.PI; - var z = Math.max(Math.log(s) / Math.log(2) - 8, 0); - var ts = 256 * Math.pow(2, z - _tileZoom); - var origin = [ - s / 2 - projection.translate()[0], - s / 2 - projection.translate()[1] - ]; + if (entity.type === 'relation') { + children = map$3(entity.members, 'id'); + } else if (entity.type === 'way') { + children = entity.nodes; + } else { + children = []; + } - var tiles = d3geoTile() - .scaleExtent([_tileZoom, _tileZoom]) - .scale(s) - .size(dimensions) - .translate(projection.translate())() - .map(function(tile) { - var x = tile[0] * ts - origin[0]; - var y = tile[1] * ts - origin[1]; - - return { - id: tile.toString(), - extent: geoExtent$$1( - projection.invert([x, y + ts]), - projection.invert([x + ts, y])) - }; - }); + for (i = 0; i < children.length; i++) { + if (!descendants[children[i]]) { + descendants[children[i]] = true; + descendants = getDescendants(children[i], graph, descendants); + } + } - filter(_tiles.inflight, function(v, i) { - var wanted = find$1(tiles, function(tile) { - return i === tile.id; - }); - if (!wanted) delete _tiles.inflight[i]; - return !wanted; - }).map(abortRequest$2); + return descendants; + } - tiles.forEach(function(tile) { - var id = tile.id; - if (_tiles.loaded[id] || _tiles.inflight[id]) return; + function doCopy() { + if (!getSelectionText()) event.preventDefault(); - if (isEmpty(_tiles.inflight)) { - dispatch$3.call('loading'); - } + var graph = context.graph(), + selected = groupEntities(context.selectedIDs(), graph), + canCopy = [], + skip = {}, + i, entity; - _tiles.inflight[id] = that.loadFromAPI( - '/api/0.6/map?bbox=' + tile.extent.toParam(), - function(err, parsed) { - delete _tiles.inflight[id]; - if (!err) { - _tiles.loaded[id] = true; - } - - if (callback) { - callback(err, assignIn({ data: parsed }, tile)); - } - - if (isEmpty(_tiles.inflight)) { - dispatch$3.call('loaded'); - } - } - ); - }); - }, + for (i = 0; i < selected.relation.length; i++) { + entity = selected.relation[i]; + if (!skip[entity.id] && entity.isComplete(graph)) { + canCopy.push(entity.id); + skip = getDescendants(entity.id, graph, skip); + } + } + for (i = 0; i < selected.way.length; i++) { + entity = selected.way[i]; + if (!skip[entity.id]) { + canCopy.push(entity.id); + skip = getDescendants(entity.id, graph, skip); + } + } + for (i = 0; i < selected.node.length; i++) { + entity = selected.node[i]; + if (!skip[entity.id]) { + canCopy.push(entity.id); + } + } + context.copyIDs(canCopy); + } - switch: function(options) { - urlroot = options.urlroot; - oauth.options(assignIn({ - url: urlroot, - loading: authLoading, - done: authDone - }, options)); + function copy() { + keybinding.on(uiCmd('⌘C'), doCopy); + select(document).call(keybinding); + return copy; + } - this.reset(); - this.userChangesets(function() {}); // eagerly load user details/changesets - dispatch$3.call('change'); - return this; - }, + function getSelectionText() { + return window.getSelection().toString(); + } + copy.off = function() { + select(document).call(keybinding.off); + }; - toggle: function(_) { - _off = !_; - return this; - }, + return copy; + } - loadedTiles: function(_) { - if (!arguments.length) return _tiles.loaded; - _tiles.loaded = _; - return this; - }, + /* + `behaviorDrag` is like `d3_behavior.drag`, with the following differences: + + * The `origin` function is expected to return an [x, y] tuple rather than an + {x, y} object. + * The events are `start`, `move`, and `end`. + (https://github.com/mbostock/d3/issues/563) + * The `start` event is not dispatched until the first cursor movement occurs. + (https://github.com/mbostock/d3/pull/368) + * The `move` event has a `point` and `delta` [x, y] tuple properties rather + than `x`, `y`, `dx`, and `dy` properties. + * The `end` event is not dispatched if no movement occurs. + * An `off` function is available that unbinds the drag's internal event handlers. + */ + function behaviorDrag() { + var dispatch$$1 = dispatch('start', 'move', 'end'); + var _origin = null; + var _selector = ''; + var _event; + var _target; + var _surface; + + + var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'); + var d3_event_userSelectSuppress = function() { + var selection$$1 = selection(); + var select$$1 = selection$$1.style(d3_event_userSelectProperty); + selection$$1.style(d3_event_userSelectProperty, 'none'); + return function() { + selection$$1.style(d3_event_userSelectProperty, select$$1); + }; + }; - logout: function() { - _userChangesets = undefined; - _userDetails = undefined; - oauth.logout(); - dispatch$3.call('change'); - return this; - }, + function d3_eventCancel() { + event.stopPropagation(); + event.preventDefault(); + } - authenticate: function(callback) { - var that = this; - var cid = _connectionID; - _userChangesets = undefined; - _userDetails = undefined; - function done(err, res) { - if (err) { - if (callback) callback(err); - return; - } - if (that.getConnectionId() !== cid) { - if (callback) callback({ message: 'Connection Switched', status: -1 }); - return; - } - _rateLimitError = undefined; - dispatch$3.call('change'); - if (callback) callback(err, res); - that.userChangesets(function() {}); // eagerly load user details/changesets - } + function eventOf(thiz, argumentz) { + return function(e1) { + e1.target = drag; + customEvent(e1, dispatch$$1.apply, dispatch$$1, [e1.type, thiz, argumentz]); + }; + } - return oauth.authenticate(done); - } -}; -var apibase$3 = 'https://taginfo.openstreetmap.org/api/4/', - inflight$1 = {}, - popularKeys = {}, - taginfoCache = {}, - tag_sorts = { - point: 'count_nodes', - vertex: 'count_nodes', - area: 'count_ways', - line: 'count_ways' - }, - tag_sort_members = { - point: 'count_node_members', - vertex: 'count_node_members', - area: 'count_way_members', - line: 'count_way_members', - relation: 'count_relation_members' - }, - tag_filters = { - point: 'nodes', - vertex: 'nodes', - area: 'ways', - line: 'ways' - }, - tag_members_fractions = { - point: 'count_node_members_fraction', - vertex: 'count_node_members_fraction', - area: 'count_way_members_fraction', - line: 'count_way_members_fraction', - relation: 'count_relation_members_fraction' - }; + function dragstart() { + _target = this; + _event = eventOf(_target, arguments); + var eventTarget = event.target; + var touchId = event.touches ? event.changedTouches[0].identifier : null; + var offset; + var startOrigin = point$$1(); + var started = false; + var selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag'); -function sets(params, n, o) { - if (params.geometry && o[params.geometry]) { - params[n] = o[params.geometry]; - } - return params; -} + select(window) + .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove) + .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true); + if (_origin) { + offset = _origin.apply(_target, arguments); + offset = [offset[0] - startOrigin[0], offset[1] - startOrigin[1]]; + } else { + offset = [0, 0]; + } + + if (touchId === null) { + event.stopPropagation(); + } -function setFilter(params) { - return sets(params, 'filter', tag_filters); -} + function point$$1() { + var p = _surface || _target.parentNode; + return touchId !== null ? d3_touches(p).filter(function(p) { + return p.identifier === touchId; + })[0] : mouse(p); + } -function setSort(params) { - return sets(params, 'sortname', tag_sorts); -} + function dragmove() { + var p = point$$1(); + var dx = p[0] - startOrigin[0]; + var dy = p[1] - startOrigin[1]; -function setSortMembers(params) { - return sets(params, 'sortname', tag_sort_members); -} + if (dx === 0 && dy === 0) + return; + startOrigin = p; + d3_eventCancel(); -function clean(params) { - return omit(params, ['geometry', 'debounce']); -} + if (!started) { + started = true; + _event({ type: 'start' }); + } else { + _event({ + type: 'move', + point: [p[0] + offset[0], p[1] + offset[1]], + delta: [dx, dy] + }); + } + } -function filterKeys(type) { - var count_type = type ? 'count_' + type : 'count_all'; - return function(d) { - return parseFloat(d[count_type]) > 2500 || d.in_wiki; - }; -} + function dragend() { + if (started) { + _event({ type: 'end' }); + d3_eventCancel(); + if (event.target === eventTarget) { + select(window) + .on('click.drag', click, true); + } + } -function filterMultikeys(prefix) { - return function(d) { - // d.key begins with prefix, and d.key contains no additional ':'s - var re = new RegExp('^' + prefix + '(.*)$'); - var matches = d.key.match(re) || []; - return (matches.length === 2 && matches[1].indexOf(':') === -1); - }; -} + select(window) + .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null) + .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null); + selectEnable(); + } -function filterValues(allowUpperCase) { - return function(d) { - if (d.value.match(/[;,]/) !== null) return false; // exclude some punctuation - if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false; // exclude uppercase letters - return parseFloat(d.fraction) > 0.0 || d.in_wiki; - }; -} + function click() { + d3_eventCancel(); + select(window) + .on('click.drag', null); + } + } -function filterRoles(geometry) { - return function(d) { - if (d.role === '') return false; // exclude empty role - if (d.role.match(/[A-Z*;,]/) !== null) return false; // exclude uppercase letters and some punctuation - return parseFloat(d[tag_members_fractions[geometry]]) > 0.0; - }; -} + function drag(selection$$1) { + var matchesSelector = utilPrefixDOMProperty('matchesSelector'); + var delegate = dragstart; + + if (_selector) { + delegate = function() { + var root = this; + var target = event.target; + for (; target && target !== root; target = target.parentNode) { + var datum = target.__data__; + var entity = datum && datum.properties && datum.properties.entity; + if (entity && target[matchesSelector](_selector)) { + return dragstart.call(target, entity); + } + } + }; + } -function valKey(d) { - return { - value: d.key, - title: d.key - }; -} + selection$$1 + .on('mousedown.drag' + _selector, delegate) + .on('touchstart.drag' + _selector, delegate); + } -function valKeyDescription(d) { - return { - value: d.value, - title: d.description || d.value - }; -} + drag.off = function(selection$$1) { + selection$$1 + .on('mousedown.drag' + _selector, null) + .on('touchstart.drag' + _selector, null); + }; -function roleKey(d) { - return { - value: d.role, - title: d.role - }; -} + drag.selector = function(_) { + if (!arguments.length) return _selector; + _selector = _; + return drag; + }; -// sort keys with ':' lower than keys without ':' -function sortKeys(a, b) { - return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1 - : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1 - : 0; -} + drag.origin = function (_) { + if (!arguments.length) return _origin; + _origin = _; + return drag; + }; -var debouncedRequest = debounce(request, 500, { leading: false }); + drag.cancel = function() { + select(window) + .on('mousemove.drag', null) + .on('mouseup.drag', null); + return drag; + }; -function request(url, params, exactMatch, callback, loaded) { - if (inflight$1[url]) return; - if (checkCache(url, params, exactMatch, callback)) return; + drag.target = function() { + if (!arguments.length) return _target; + _target = arguments[0]; + _event = eventOf(_target, Array.prototype.slice.call(arguments, 1)); + return drag; + }; - inflight$1[url] = d3_json(url, function (err, data) { - delete inflight$1[url]; - loaded(err, data); - }); -} + drag.surface = function() { + if (!arguments.length) return _surface; + _surface = arguments[0]; + return drag; + }; -function checkCache(url, params, exactMatch, callback) { - var rp = params.rp || 25, - testQuery = params.query || '', - testUrl = url; - do { - var hit = taginfoCache[testUrl]; + return utilRebind(drag, dispatch$$1, 'on'); + } - // exact match, or shorter match yielding fewer than max results (rp) - if (hit && (url === testUrl || hit.length < rp)) { - callback(null, hit); - return true; - } + function behaviorDrawWay(context, wayId, index, mode, startGraph) { + var origWay = context.entity(wayId); + var annotation = t((origWay.isDegenerate() ? + 'operations.start.annotation.' : + 'operations.continue.annotation.') + context.geometry(wayId) + ); + var behavior = behaviorDraw(context); + var _tempEdits = 0; - // don't try to shorten the query - if (exactMatch || !testQuery.length) return false; + var end = osmNode({ loc: context.map().mouseCoordinates() }); - // do shorten the query to see if we already have a cached result - // that has returned fewer than max results (rp) - testQuery = testQuery.slice(0, -1); - testUrl = url.replace(/&query=(.*?)&/, '&query=' + testQuery + '&'); - } while (testQuery.length >= 0); + // Push an annotated state for undo to return back to. + // We must make sure to remove this edit later. + context.perform(actionNoop(), annotation); + _tempEdits++; - return false; -} + // Add the drawing node to the graph. + // We must make sure to remove this edit later. + context.perform(_actionAddDrawNode()); + _tempEdits++; -var serviceTaginfo = { - init: function() { - inflight$1 = {}; - taginfoCache = {}; - popularKeys = {}; + function keydown() { + if (event.keyCode === d3keybinding.modifierCodes.alt) { + if (context.surface().classed('nope')) { + context.surface() + .classed('nope-suppressed', true); + } + context.surface() + .classed('nope', false) + .classed('nope-disabled', true); + } + } - // Fetch popular keys. We'll exclude these from `values` - // lookups because they stress taginfo, and they aren't likely - // to yield meaningful autocomplete results.. see #3955 - var params = { rp: 100, sortname: 'values_all', sortorder: 'desc', page: 1, debounce: false }; - this.keys(params, function(err, data) { - if (err) return; - data.forEach(function(d) { - if (d.value === 'opening_hours') return; // exception - popularKeys[d.value] = true; - }); - }); - }, + function keyup() { + if (event.keyCode === d3keybinding.modifierCodes.alt) { + if (context.surface().classed('nope-suppressed')) { + context.surface() + .classed('nope', true); + } + context.surface() + .classed('nope-suppressed', false) + .classed('nope-disabled', false); + } + } - reset: function() { - forEach(inflight$1, function(req) { req.abort(); }); - inflight$1 = {}; - }, + // related code + // - `mode/drag_node.js` `doMode()` + // - `behavior/draw.js` `click()` + // - `behavior/draw_way.js` `move()` + function move(datum) { + context.surface().classed('nope-disabled', event.altKey); - keys: function(params, callback) { - var doRequest = params.debounce ? debouncedRequest : request; - params = clean(setSort(params)); - params = assignIn({ rp: 10, sortname: 'count_all', sortorder: 'desc', page: 1 }, params); + var targetLoc = datum && datum.properties && datum.properties.entity && datum.properties.entity.loc; + var targetNodes = datum && datum.properties && datum.properties.nodes; + var loc = context.map().mouseCoordinates(); - var url = apibase$3 + 'keys/all?' + utilQsString(params); - doRequest(url, params, false, callback, function(err, d) { - if (err) { - callback(err); - } else { - var f = filterKeys(params.filter); - var result = d.data.filter(f).sort(sortKeys).map(valKey); - taginfoCache[url] = result; - callback(null, result); - } - }); - }, + if (targetLoc) { // snap to node/vertex - a point target with `.loc` + loc = targetLoc; + } else if (targetNodes) { // snap to way - a line target with `.nodes` + var choice = geoChooseEdge(targetNodes, context.mouse(), context.projection, end.id); + if (choice) { + loc = choice.loc; + } + } - multikeys: function(params, callback) { - var doRequest = params.debounce ? debouncedRequest : request; - params = clean(setSort(params)); - params = assignIn({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params); - var prefix = params.query; + context.replace(actionMoveNode(end.id, loc)); + end = context.entity(end.id); + checkGeometry(false); + } - var url = apibase$3 + 'keys/all?' + utilQsString(params); - doRequest(url, params, true, callback, function(err, d) { - if (err) { - callback(err); - } else { - var f = filterMultikeys(prefix); - var result = d.data.filter(f).map(valKey); - taginfoCache[url] = result; - callback(null, result); - } - }); - }, + // Check whether this edit causes the geometry to break. + // If so, class the surface with a nope cursor. + // `finishDraw` - Only checks the relevant line segments if finishing drawing + function checkGeometry(finishDraw) { + var nopeDisabled = context.surface().classed('nope-disabled'); + var isInvalid = isInvalidGeometry(end, context.graph(), finishDraw); - values: function(params, callback) { - // Exclude popular keys from values lookups.. see #3955 - var key = params.key; - if (key && popularKeys[key]) { - callback(null, []); - return; - } + if (nopeDisabled) { + context.surface() + .classed('nope', false) + .classed('nope-suppressed', isInvalid); + } else { + context.surface() + .classed('nope', isInvalid) + .classed('nope-suppressed', false); + } + } - var doRequest = params.debounce ? debouncedRequest : request; - params = clean(setSort(setFilter(params))); - params = assignIn({ rp: 25, sortname: 'count_all', sortorder: 'desc', page: 1 }, params); - var url = apibase$3 + 'key/values?' + utilQsString(params); - doRequest(url, params, false, callback, function(err, d) { - if (err) { - callback(err); - } else { - // In most cases we prefer taginfo value results with lowercase letters. - // A few OSM keys expect values to contain uppercase values (see #3377). - // This is not an exhaustive list (e.g. `name` also has uppercase values) - // but these are the fields where taginfo value lookup is most useful. - var re = /network|taxon|genus|species|brand|grape_variety|rating|:output|_hours|_times/; - var allowUpperCase = (params.key.match(re) !== null); - var f = filterValues(allowUpperCase); - - var result = d.data.filter(f).map(valKeyDescription); - taginfoCache[url] = result; - callback(null, result); - } - }); - }, + function isInvalidGeometry(entity, graph, finishDraw) { + var parents = graph.parentWays(entity); + + for (var i = 0; i < parents.length; i++) { + var parent = parents[i]; + var nodes = parent.nodes.map(function(nodeID) { return graph.entity(nodeID); }); + + if (origWay.isClosed()) { // Check if Area + if (finishDraw) { + nodes.splice(-2, 1); + entity = nodes[nodes.length-2]; + } else { + nodes.pop(); + } + } else { // Line + if (finishDraw) { + nodes.pop(); + } + } + + if (geoHasSelfIntersections(nodes, entity.id)) { + return true; + } + } + return false; + } - roles: function(params, callback) { - var doRequest = params.debounce ? debouncedRequest : request; - var geometry = params.geometry; - params = clean(setSortMembers(params)); - params = assignIn({ rp: 25, sortname: 'count_all_members', sortorder: 'desc', page: 1 }, params); - var url = apibase$3 + 'relation/roles?' + utilQsString(params); - doRequest(url, params, true, callback, function(err, d) { - if (err) { - callback(err); - } else { - var f = filterRoles(geometry); - var result = d.data.filter(f).map(roleKey); - taginfoCache[url] = result; - callback(null, result); - } - }); - }, + function undone() { + // Undo popped the history back to the initial annotated no-op edit. + // Remove initial no-op edit and whatever edit happened immediately before it. + context.pop(2); + _tempEdits = 0; + if (context.hasEntity(wayId)) { + context.enter(mode); + } else { + context.enter(modeBrowse(context)); + } + } - docs: function(params, callback) { - var doRequest = params.debounce ? debouncedRequest : request; - params = clean(setSort(params)); - var path = 'key/wiki_pages?'; - if (params.value) path = 'tag/wiki_pages?'; - else if (params.rtype) path = 'relation/wiki_pages?'; + function setActiveElements() { + context.surface().selectAll('.' + end.id) + .classed('active', true); + } - var url = apibase$3 + path + utilQsString(params); - doRequest(url, params, true, callback, function(err, d) { - if (err) { - callback(err); - } else { - taginfoCache[url] = d.data; - callback(null, d.data); - } - }); - }, + var drawWay = function(surface) { + behavior + .on('move', move) + .on('click', drawWay.add) + .on('clickWay', drawWay.addWay) + .on('clickNode', drawWay.addNode) + .on('undo', context.undo) + .on('cancel', drawWay.cancel) + .on('finish', drawWay.finish); - apibase: function(_) { - if (!arguments.length) return apibase$3; - apibase$3 = _; - return this; - } + select(window) + .on('keydown.drawWay', keydown) + .on('keyup.drawWay', keyup); -}; + context.map() + .dblclickEnable(false) + .on('drawn.draw', setActiveElements); -var jsonpCache = {}; -window.jsonpCache = jsonpCache; + setActiveElements(); -function jsonpRequest(url, callback) { + surface.call(behavior); - if (window.JSONP_FIX) { - if (window.JSONP_DELAY === 0) { - callback(window.JSONP_FIX); - } else { - setTimeout(function() { - callback(window.JSONP_FIX); - }, window.JSONP_DELAY || 0); - } - return; - } + context.history() + .on('undone.draw', undone); + }; - function rand() { - var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', - c = '', i = -1; - while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52)); - return c; - } - function create$$1(url) { - var e = url.match(/callback=(\w+)/), - c = e ? e[1] : rand(); - jsonpCache[c] = function(data) { - callback(data); - delete jsonpCache[c]; - script.remove(); - }; - return 'jsonpCache.' + c; - } + drawWay.off = function(surface) { + // Drawing was interrupted unexpectedly. + // This can happen if the user changes modes, + // clicks geolocate button, a hashchange event occurs, etc. + if (_tempEdits) { + context.pop(_tempEdits); + while (context.graph() !== startGraph) { + context.pop(); + } + } - var cb = create$$1(url), - script = d3_select('head') - .append('script') - .attr('type', 'text/javascript') - .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb)); -} + context.map() + .on('drawn.draw', null); -var endpoint = 'https://www.wikidata.org/w/api.php?'; + surface.call(behavior.off) + .selectAll('.active') + .classed('active', false); -var serviceWikidata = { + surface + .classed('nope', false) + .classed('nope-suppressed', false) + .classed('nope-disabled', false); - init: function() {}, - reset: function() {}, + select(window) + .on('keydown.hover', null) + .on('keyup.hover', null); + context.history() + .on('undone.draw', null); + }; - // Given a Wikipedia language and article title, return an array of - // corresponding Wikidata entities. - itemsByTitle: function(lang, title, callback) { - if (!title) { - callback('', {}); - return; - } - lang = lang || 'en'; - jsonpRequest(endpoint + utilQsString({ - action: 'wbgetentities', - format: 'json', - sites: lang.replace(/-/g, '_') + 'wiki', - titles: title, - languages: 'en', // shrink response by filtering to one language - callback: '{callback}' - }), function(data) { - if (!data || data.error) { - callback('', {}); - } else { - callback(title, data.entities || {}); - } - }); - } + function _actionAddDrawNode() { + return function(graph) { + return graph + .replace(end) + .replace(origWay.addNode(end.id, index)); + }; + } -}; -var endpoint$1 = 'https://en.wikipedia.org/w/api.php?'; + function _actionReplaceDrawNode(newNode) { + return function(graph) { + return graph + .replace(origWay.addNode(newNode.id, index)) + .remove(end); + }; + } -var serviceWikipedia = { - init: function() {}, - reset: function() {}, + // Accept the current position of the drawing node and continue drawing. + drawWay.add = function(loc, d) { + if ((d && d.properties && d.properties.nope) || context.surface().classed('nope')) { + return; // can't click here + } + context.pop(_tempEdits); + _tempEdits = 0; - search: function(lang, query, callback) { - if (!query) { - callback('', []); - return; - } + context.perform( + _actionAddDrawNode(), + annotation + ); - lang = lang || 'en'; - jsonpRequest(endpoint$1.replace('en', lang) + - utilQsString({ - action: 'query', - list: 'search', - srlimit: '10', - srinfo: 'suggestion', - format: 'json', - callback: '{callback}', - srsearch: query - }), function(data) { - if (!data || !data.query || !data.query.search || data.error) { - callback('', []); - } else { - var results = data.query.search.map(function(d) { return d.title; }); - callback(query, results); - } - } - ); - }, + checkGeometry(false); // finishDraw = false + context.enter(mode); + }; - suggestions: function(lang, query, callback) { - if (!query) { - callback('', []); - return; - } + // Connect the way to an existing way. + drawWay.addWay = function(loc, edge, d) { + if ((d && d.properties && d.properties.nope) || context.surface().classed('nope')) { + return; // can't click here + } - lang = lang || 'en'; - jsonpRequest(endpoint$1.replace('en', lang) + - utilQsString({ - action: 'opensearch', - namespace: 0, - suggest: '', - format: 'json', - callback: '{callback}', - search: query - }), function(data) { - if (!data || data.error) { - callback('', []); - } else { - callback(data[0], data[1] || []); - } - } - ); - }, + context.pop(_tempEdits); + _tempEdits = 0; + context.perform( + _actionAddDrawNode(), + actionAddMidpoint({ loc: loc, edge: edge }, end), + annotation + ); - translations: function(lang, title, callback) { - if (!title) { - callback({}); - return; - } + checkGeometry(false); // finishDraw = false + context.enter(mode); + }; - jsonpRequest(endpoint$1.replace('en', lang) + - utilQsString({ - action: 'query', - prop: 'langlinks', - format: 'json', - callback: '{callback}', - lllimit: 500, - titles: title - }), function(data) { - if (!data || !data.query || !data.query.pages || data.error) { - callback({}); - } else { - var list = data.query.pages[Object.keys(data.query.pages)[0]], - translations = {}; - if (list && list.langlinks) { - list.langlinks.forEach(function(d) { - translations[d.lang] = d['*']; - }); - } - callback(translations); - } - } - ); - } -}; - -var services = { - geocoder: serviceNominatim, - mapillary: serviceMapillary, - openstreetcam: serviceOpenstreetcam, - osm: serviceOsm, - taginfo: serviceTaginfo, - wikidata: serviceWikidata, - wikipedia: serviceWikipedia -}; - -function svgAreas$$1(projection, context) { - // Patterns only work in Firefox when set directly on element. - // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632) - var patterns = { - beach: 'beach', - cemetery: 'cemetery', - construction: 'construction', - farm: 'farmland', - farmland: 'farmland', - grave_yard: 'cemetery', - meadow: 'meadow', - military: 'construction', - orchard: 'orchard', - sand: 'beach', - scrub: 'scrub', - wetland: 'wetland', - }; + // Connect the way to an existing node and continue drawing. + drawWay.addNode = function(node, d) { + if ((d && d.properties && d.properties.nope) || context.surface().classed('nope')) { + return; // can't click here + } - var patternKeys = ['landuse', 'natural', 'amenity']; + context.pop(_tempEdits); + _tempEdits = 0; + context.perform( + _actionReplaceDrawNode(node), + annotation + ); - function setPattern(d) { - for (var i = 0; i < patternKeys.length; i++) { - if (d.tags.building && d.tags.building !== 'no') continue; + checkGeometry(false); // finishDraw = false + context.enter(mode); + }; - if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) { - this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")'; - return; - } - } - this.style.fill = this.style.stroke = ''; - } + // Finish the draw operation, removing the temporary edits. + // If the way has enough nodes to be valid, it's selected. + // Otherwise, delete everything and return to browse mode. + drawWay.finish = function() { + checkGeometry(true); // finishDraw = true + if (context.surface().classed('nope')) { + return; // can't click here + } - function drawTargets(selection, graph, entities, filter) { - var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor '; - var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor '; - var getPath = svgPath(projection).geojson; - var activeID = context.activeID(); + context.pop(_tempEdits); + _tempEdits = 0; - // The targets and nopes will be MultiLineString sub-segments of the ways - var data = { targets: [], nopes: [] }; + var way = context.hasEntity(wayId); + if (!way || way.isDegenerate()) { + drawWay.cancel(); + return; + } - entities.forEach(function(way) { - var features = svgSegmentWay(way, graph, activeID); - data.targets.push.apply(data.targets, features.passive); - data.nopes.push.apply(data.nopes, features.active); - }); + window.setTimeout(function() { + context.map().dblclickEnable(true); + }, 1000); + context.enter(modeSelect(context, [wayId]).newFeature(true)); + }; - // Targets allow hover and vertex snapping - var targetData = data.targets.filter(getPath); - var targets = selection.selectAll('.area.target-allowed') - .filter(function(d) { return filter(d.properties.entity); }) - .data(targetData, function key(d) { return d.id; }); - - // exit - targets.exit() - .remove(); - - // enter/update - targets.enter() - .append('path') - .merge(targets) - .attr('d', getPath) - .attr('class', function(d) { return 'way area target target-allowed ' + targetClass + d.id; }); - - - // NOPE - var nopeData = data.nopes.filter(getPath); - var nopes = selection.selectAll('.area.target-nope') - .filter(function(d) { return filter(d.properties.entity); }) - .data(nopeData, function key(d) { return d.id; }); - - // exit - nopes.exit() - .remove(); - - // enter/update - nopes.enter() - .append('path') - .merge(nopes) - .attr('d', getPath) - .attr('class', function(d) { return 'way area target target-nope ' + nopeClass + d.id; }); - } - - - function drawAreas(selection, graph, entities, filter) { - var path = svgPath(projection, graph, true), - areas = {}, - multipolygon; - - for (var i = 0; i < entities.length; i++) { - var entity = entities[i]; - if (entity.geometry(graph) !== 'area') continue; - - multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph); - if (multipolygon) { - areas[multipolygon.id] = { - entity: multipolygon.mergeTags(entity.tags), - area: Math.abs(entity.area(graph)) - }; - } else if (!areas[entity.id]) { - areas[entity.id] = { - entity: entity, - area: Math.abs(entity.area(graph)) - }; - } - } - areas = values$1(areas).filter(function hasPath(a) { return path(a.entity); }); - areas.sort(function areaSort(a, b) { return b.area - a.area; }); - areas = map$3(areas, 'entity'); + // Cancel the draw operation, delete everything, and return to browse mode. + drawWay.cancel = function() { + context.pop(_tempEdits); + _tempEdits = 0; - var strokes = areas.filter(function(area) { - return area.type === 'way'; - }); + while (context.graph() !== startGraph) { + context.pop(); + } - var data = { - clip: areas, - shadow: strokes, - stroke: strokes, - fill: areas - }; + window.setTimeout(function() { + context.map().dblclickEnable(true); + }, 1000); - var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath') - .filter(filter) - .data(data.clip, osmEntity$$1.key); + context.surface() + .classed('nope', false) + .classed('nope-disabled', false) + .classed('nope-suppressed', false); - clipPaths.exit() - .remove(); + context.enter(modeBrowse(context)); + }; - var clipPathsEnter = clipPaths.enter() - .append('clipPath') - .attr('class', 'clipPath') - .attr('id', function(entity) { return entity.id + '-clippath'; }); - clipPathsEnter - .append('path'); + drawWay.activeID = function() { + if (!arguments.length) return end.id; + // no assign + return drawWay; + }; - clipPaths.merge(clipPathsEnter) - .selectAll('path') - .attr('d', path); + drawWay.tail = function(text) { + behavior.tail(text); + return drawWay; + }; - var layer = selection.selectAll('.layer-areas .layer-areas-areas'); - var areagroup = layer - .selectAll('g.areagroup') - .data(['fill', 'shadow', 'stroke']); + return drawWay; + } - areagroup = areagroup.enter() - .append('g') - .attr('class', function(d) { return 'areagroup area-' + d; }) - .merge(areagroup); + /** Error message constants. */ + var FUNC_ERROR_TEXT$3 = 'Expected a function'; - var paths = areagroup - .selectAll('path') - .filter(filter) - .data(function(layer) { return data[layer]; }, osmEntity$$1.key); + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; - paths.exit() - .remove(); + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT$3); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } - var fills = selection.selectAll('.area-fill path.area').nodes(); + function behaviorHash(context) { + var s0 = null; // cached window.location.hash + var lat = 90 - 1e-8; // allowable latitude range - var bisect = d3_bisector(function(node) { - return -node.__data__.area(graph); - }).left; - function sortedByArea(entity) { - if (this._parent.__data__ === 'fill') { - return fills[bisect(fills, -entity.area(graph))]; - } - } + var parser = function(map, s) { + var q = utilStringQs(s); + var args = (q.map || '').split('/').map(Number); - paths = paths.enter() - .insert('path', sortedByArea) - .merge(paths) - .each(function(entity) { - var layer = this.parentNode.__data__; + if (args.length < 3 || args.some(isNaN)) { + return true; // replace bogus hash - this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id); + } else if (s !== formatter(map).slice(1)) { // hash has changed + var mode = context.mode(), + dist = geoSphericalDistance(map.center(), [args[2], args[1]]), + maxdist = 500; - if (layer === 'fill') { - this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)'); - setPattern.apply(this, arguments); - } - }) - .call(svgTagClasses()) - .attr('d', path); + // Don't allow the hash location to change too much while drawing + // This can happen if the user accidently hit the back button. #3996 + if (mode && mode.id.match(/^draw/) !== null && dist > maxdist) { + context.enter(modeBrowse(context)); + } + map.centerZoom([args[2], Math.min(lat, Math.max(-lat, args[1]))], args[0]); + } + }; - // touch targets - selection.selectAll('.layer-areas .layer-areas-targets') - .call(drawTargets, graph, data.stroke, filter); - } - return drawAreas; -} + var formatter = function(map) { + var center = map.center(); + var zoom = map.zoom(); + var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)); + var q = omit(utilStringQs(window.location.hash.substring(1)), + ['comment', 'source', 'hashtags', 'walkthrough'] + ); + var newParams = {}; -function svgDebug$$1(projection, context) { + delete q.id; + var selected = context.selectedIDs().filter(function(id) { + return !context.entity(id).isNew(); + }); + if (selected.length) { + newParams.id = selected.join(','); + } - function multipolygons(imagery) { - return imagery.map(function(data$$1) { - return { - type: 'MultiPolygon', - coordinates: [ data$$1.polygon ] - }; - }); - } + newParams.map = zoom.toFixed(2) + + '/' + center[1].toFixed(precision) + + '/' + center[0].toFixed(precision); - function drawDebug(selection$$1) { - var showsTile = context.getDebug('tile'); - var showsCollision = context.getDebug('collision'); - var showsImagery = context.getDebug('imagery'); - var showsImperial = context.getDebug('imperial'); - var showsDriveLeft = context.getDebug('driveLeft'); - var showsTouchTargets = context.getDebug('target'); + return '#' + utilQsString(assign(q, newParams), true); + }; - var debugData = []; - if (showsTile) { - debugData.push({ class: 'red', label: 'tile' }); - } - if (showsCollision) { - debugData.push({ class: 'yellow', label: 'collision' }); - } - if (showsImagery) { - debugData.push({ class: 'orange', label: 'imagery' }); - } - if (showsImperial) { - debugData.push({ class: 'cyan', label: 'imperial' }); - } - if (showsDriveLeft) { - debugData.push({ class: 'green', label: 'driveLeft' }); - } - if (showsTouchTargets) { - debugData.push({ class: 'pink', label: 'touchTargets' }); - } + function update() { + if (context.inIntro()) return; + var s1 = formatter(context.map()); + if (s0 !== s1) { + window.location.replace(s0 = s1); // don't recenter the map! + } + } - var legend = d3_select('#content') - .selectAll('.debug-legend') - .data(debugData.length ? [0] : []); - legend.exit() - .remove(); + var throttledUpdate = throttle(update, 500); - legend = legend.enter() - .append('div') - .attr('class', 'fillD debug-legend') - .merge(legend); + function hashchange() { + if (window.location.hash === s0) return; // ignore spurious hashchange events + if (parser(context.map(), (s0 = window.location.hash).substring(1))) { + update(); // replace bogus hash + } + } - var legendItems = legend.selectAll('.debug-legend-item') - .data(debugData, function(d) { return d.label; }); - legendItems.exit() - .remove(); + function hash() { + context.map() + .on('move.hash', throttledUpdate); - legendItems.enter() - .append('span') - .attr('class', function(d) { return 'debug-legend-item ' + d.class; }) - .text(function(d) { return d.label; }); + context + .on('enter.hash', throttledUpdate); + select(window) + .on('hashchange.hash', hashchange); - var layer = selection$$1.selectAll('.layer-debug') - .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []); + if (window.location.hash) { - layer.exit() - .remove(); + var q = utilStringQs(window.location.hash.substring(1)); - layer = layer.enter() - .append('g') - .attr('class', 'layer-debug') - .merge(layer); + if (q.id) { + context.zoomToEntity(q.id.split(',')[0], !q.map); + } + if (q.comment) { + context.storage('comment', q.comment); + context.storage('commentDate', Date.now()); + } - var extent = context.map().extent(); - var dataImagery = data.imagery || []; - var availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) { - if (!source.polygon) return false; - return source.polygon.some(function(polygon) { - return geoPolygonIntersectsPolygon(polygon, extent, true); - }); - })); + if (q.source) { + context.storage('source', q.source); + context.storage('commentDate', Date.now()); + } - var imagery = layer.selectAll('path.debug-imagery') - .data(showsImagery ? availableImagery : []); + if (q.hashtags) { + context.storage('hashtags', q.hashtags); + } - imagery.exit() - .remove(); + if (q.walkthrough === 'true') { + hash.startWalkthrough = true; + } - imagery.enter() - .append('path') - .attr('class', 'debug-imagery debug orange'); + hashchange(); + if (q.map) { + hash.hadHash = true; + } + } + } - var imperial = layer - .selectAll('path.debug-imperial') - .data(showsImperial ? [dataImperial] : []); - imperial.exit() - .remove(); + hash.off = function() { + throttledUpdate.cancel(); - imperial.enter() - .append('path') - .attr('class', 'debug-imperial debug cyan'); + context.map() + .on('move.hash', null); + context + .on('enter.hash', null); - var driveLeft = layer - .selectAll('path.debug-drive-left') - .data(showsDriveLeft ? [dataDriveLeft] : []); + select(window) + .on('hashchange.hash', null); - driveLeft.exit() - .remove(); + window.location.hash = ''; + }; - driveLeft.enter() - .append('path') - .attr('class', 'debug-drive-left debug green'); + return hash; + } - // update - layer.selectAll('path') - .attr('d', svgPath(projection).geojson); - } + function behaviorLasso(context) { + var behavior = function(selection$$1) { + var lasso; - // This looks strange because `enabled` methods on other layers are - // chainable getter/setters, and this one is just a getter. - drawDebug.enabled = function() { - if (!arguments.length) { - return context.getDebug('tile') || - context.getDebug('collision') || - context.getDebug('imagery') || - context.getDebug('imperial') || - context.getDebug('driveLeft') || - context.getDebug('target'); - } else { - return this; - } - }; + function mousedown() { + var button = 0; // left + if (event.button === button && event.shiftKey === true) { + lasso = null; - return drawDebug; -} - -/* - A standalone SVG element that contains only a `defs` sub-element. To be - used once globally, since defs IDs must be unique within a document. -*/ -function svgDefs(context) { - - function SVGSpriteDefinition(id, href) { - return function(defs) { - d3_request(href) - .mimeType('image/svg+xml') - .response(function(xhr) { return xhr.responseXML; }) - .get(function(err, svg) { - if (err) return; - defs.node().appendChild( - d3_select(svg.documentElement).attr('id', id).node() - ); - }); - }; - } + select(window) + .on('mousemove.lasso', mousemove) + .on('mouseup.lasso', mouseup); + event.stopPropagation(); + } + } - return function drawDefs(selection$$1) { - var defs = selection$$1.append('defs'); - - // markers - defs - .append('marker') - .attr('id', 'oneway-marker') - .attr('viewBox', '0 0 10 5') - .attr('refX', 2.5) - .attr('refY', 2.5) - .attr('markerWidth', 2) - .attr('markerHeight', 2) - .attr('markerUnits', 'strokeWidth') - .attr('orient', 'auto') - .append('path') - .attr('class', 'oneway-marker-path') - .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') - .attr('stroke', 'none') - .attr('fill', '#000') - .attr('opacity', '0.75'); - - defs - .append('marker') - .attr('id', 'viewfield-marker') - .attr('viewBox', '0 0 16 16') - .attr('refX', 8) - .attr('refY', 16) - .attr('markerWidth', 4) - .attr('markerHeight', 4) - .attr('markerUnits', 'strokeWidth') - .attr('orient', 'auto') - .append('path') - .attr('class', 'viewfield-marker-path') - .attr('d', 'M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z') - .attr('fill', '#333') - .attr('fill-opacity', '0.75') - .attr('stroke', '#fff') - .attr('stroke-width', '0.5px') - .attr('stroke-opacity', '0.75'); - - defs - .append('marker') - .attr('id', 'viewfield-marker-wireframe') - .attr('viewBox', '0 0 16 16') - .attr('refX', 8) - .attr('refY', 16) - .attr('markerWidth', 4) - .attr('markerHeight', 4) - .attr('markerUnits', 'strokeWidth') - .attr('orient', 'auto') - .append('path') - .attr('class', 'viewfield-marker-path') - .attr('d', 'M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z') - .attr('fill', 'none') - .attr('stroke', '#fff') - .attr('stroke-width', '0.5px') - .attr('stroke-opacity', '0.75'); - - // patterns - var patterns = defs.selectAll('pattern') - .data([ - // pattern name, pattern image name - ['wetland', 'wetland'], - ['construction', 'construction'], - ['cemetery', 'cemetery'], - ['orchard', 'orchard'], - ['farmland', 'farmland'], - ['beach', 'dots'], - ['scrub', 'dots'], - ['meadow', 'dots'] - ]) - .enter() - .append('pattern') - .attr('id', function (d) { return 'pattern-' + d[0]; }) - .attr('width', 32) - .attr('height', 32) - .attr('patternUnits', 'userSpaceOnUse'); - - patterns - .append('rect') - .attr('x', 0) - .attr('y', 0) - .attr('width', 32) - .attr('height', 32) - .attr('class', function (d) { return 'pattern-color-' + d[0]; }); - - patterns - .append('image') - .attr('x', 0) - .attr('y', 0) - .attr('width', 32) - .attr('height', 32) - .attr('xlink:href', function (d) { - return context.imagePath('pattern/' + d[1] + '.png'); - }); - // clip paths - defs.selectAll('clipPath') - .data([12, 18, 20, 32, 45]) - .enter() - .append('clipPath') - .attr('id', function (d) { return 'clip-square-' + d; }) - .append('rect') - .attr('x', 0) - .attr('y', 0) - .attr('width', function (d) { return d; }) - .attr('height', function (d) { return d; }); - - // symbol spritesheets - defs - .call(SVGSpriteDefinition('iD-sprite', context.imagePath('iD-sprite.svg'))) - .call(SVGSpriteDefinition('maki-sprite', context.imagePath('maki-sprite.svg'))); - }; -} - -/** - * Checks if `value` is `undefined`. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. - * @example - * - * _.isUndefined(void 0); - * // => true - * - * _.isUndefined(null); - * // => false - */ -function isUndefined(value) { - return value === undefined; -} - -//[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] -//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] -//[5] Name ::= NameStartChar (NameChar)* -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 -var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]"); -var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$'); -//var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/ -//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(',') - -//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE -//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE -var S_TAG = 0;//tag name offerring -var S_ATTR = 1;//attr name offerring -var S_ATTR_SPACE=2;//attr name end and space offer -var S_EQ = 3;//=space? -var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only) -var S_ATTR_END = 5;//attr value end and no space(quot end) -var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer) -var S_TAG_CLOSE = 7;//closed el - -function XMLReader(){ - -} - -XMLReader.prototype = { - parse:function(source,defaultNSMap,entityMap){ - var domBuilder = this.domBuilder; - domBuilder.startDocument(); - _copy(defaultNSMap ,defaultNSMap = {}); - parse$1(source,defaultNSMap,entityMap, - domBuilder,this.errorHandler); - domBuilder.endDocument(); - } -}; -function parse$1(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){ - function fixedFromCharCode(code) { - // String.prototype.fromCharCode does not supports - // > 2 bytes unicode chars directly - if (code > 0xffff) { - code -= 0x10000; - var surrogate1 = 0xd800 + (code >> 10) - , surrogate2 = 0xdc00 + (code & 0x3ff); - - return String.fromCharCode(surrogate1, surrogate2); - } else { - return String.fromCharCode(code); - } - } - function entityReplacer(a){ - var k = a.slice(1,-1); - if(k in entityMap){ - return entityMap[k]; - }else if(k.charAt(0) === '#'){ - return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x'))) - }else{ - errorHandler.error('entity not found:'+a); - return a; - } - } - function appendText(end){//has some bugs - if(end>start){ - var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer); - locator&&position(start); - domBuilder.characters(xt,0,end-start); - start = end; - } - } - function position(p,m){ - while(p>=lineEnd && (m = linePattern.exec(source))){ - lineStart = m.index; - lineEnd = lineStart + m[0].length; - locator.lineNumber++; - //console.log('line++:',locator,startPos,endPos) - } - locator.columnNumber = p-lineStart+1; - } - var lineStart = 0; - var lineEnd = 0; - var linePattern = /.*(?:\r\n?|\n)|.*$/g; - var locator = domBuilder.locator; - - var parseStack = [{currentNSMap:defaultNSMapCopy}]; - var closeMap = {}; - var start = 0; - while(true){ - try{ - var tagStart = source.indexOf('<',start); - if(tagStart<0){ - if(!source.substr(start).match(/^\s*$/)){ - var doc = domBuilder.doc; - var text = doc.createTextNode(source.substr(start)); - doc.appendChild(text); - domBuilder.currentElement = text; - } - return; - } - if(tagStart>start){ - appendText(tagStart); - } - switch(source.charAt(tagStart+1)){ - case '/': - var end = source.indexOf('>',tagStart+3); - var tagName = source.substring(tagStart+2,end); - var config = parseStack.pop(); - if(end<0){ - - tagName = source.substring(tagStart+2).replace(/[\s<].*/,''); - //console.error('#@@@@@@'+tagName) - errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName); - end = tagStart+1+tagName.length; - }else if(tagName.match(/\s - locator&&position(tagStart); - end = parseInstruction(source,tagStart,domBuilder); - break; - case '!':// start){ - start = end; - }else{ - //TODO: 这里有可能sax回退,有位置错误风险 - appendText(Math.max(tagStart,start)+1); - } - } -} -function copyLocator(f,t){ - t.lineNumber = f.lineNumber; - t.columnNumber = f.columnNumber; - return t; -} - -/** - * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack); - * @return end of the elementStartPart(end of elementEndPart for selfClosed el) - */ -function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){ - var attrName; - var value; - var p = ++start; - var s = S_TAG;//status - while(true){ - var c = source.charAt(p); - switch(c){ - case '=': - if(s === S_ATTR){//attrName - attrName = source.slice(start,p); - s = S_EQ; - }else if(s === S_ATTR_SPACE){ - s = S_EQ; - }else{ - //fatalError: equal must after attrName or space after attrName - throw new Error('attribute equal must after attrName'); - } - break; - case '\'': - case '"': - if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE - ){//equal - if(s === S_ATTR){ - errorHandler.warning('attribute value must after "="'); - attrName = source.slice(start,p); - } - start = p+1; - p = source.indexOf(c,start); - if(p>0){ - value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); - el.add(attrName,value,start-1); - s = S_ATTR_END; - }else{ - //fatalError: no end quot match - throw new Error('attribute value no end \''+c+'\' match'); - } - }else if(s == S_ATTR_NOQUOT_VALUE){ - value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); - //console.log(attrName,value,start,p) - el.add(attrName,value,start); - //console.dir(el) - errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!'); - start = p+1; - s = S_ATTR_END; - }else{ - //fatalError: no equal before - throw new Error('attribute value must after "="'); - } - break; - case '/': - switch(s){ - case S_TAG: - el.setTagName(source.slice(start,p)); - case S_ATTR_END: - case S_TAG_SPACE: - case S_TAG_CLOSE: - s =S_TAG_CLOSE; - el.closed = true; - case S_ATTR_NOQUOT_VALUE: - case S_ATTR: - case S_ATTR_SPACE: - break; - //case S_EQ: - default: - throw new Error("attribute invalid close char('/')") - } - break; - case ''://end document - //throw new Error('unexpected end of input') - errorHandler.error('unexpected end of input'); - if(s == S_TAG){ - el.setTagName(source.slice(start,p)); - } - return p; - case '>': - switch(s){ - case S_TAG: - el.setTagName(source.slice(start,p)); - case S_ATTR_END: - case S_TAG_SPACE: - case S_TAG_CLOSE: - break;//normal - case S_ATTR_NOQUOT_VALUE://Compatible state - case S_ATTR: - value = source.slice(start,p); - if(value.slice(-1) === '/'){ - el.closed = true; - value = value.slice(0,-1); - } - case S_ATTR_SPACE: - if(s === S_ATTR_SPACE){ - value = attrName; - } - if(s == S_ATTR_NOQUOT_VALUE){ - errorHandler.warning('attribute "'+value+'" missed quot(")!!'); - el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start); - }else{ - if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){ - errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!'); - } - el.add(value,value,start); - } - break; - case S_EQ: - throw new Error('attribute value missed!!'); - } -// console.log(tagName,tagNamePattern,tagNamePattern.test(tagName)) - return p; - /*xml space '\x20' | #x9 | #xD | #xA; */ - case '\u0080': - c = ' '; - default: - if(c<= ' '){//space - switch(s){ - case S_TAG: - el.setTagName(source.slice(start,p));//tagName - s = S_TAG_SPACE; - break; - case S_ATTR: - attrName = source.slice(start,p); - s = S_ATTR_SPACE; - break; - case S_ATTR_NOQUOT_VALUE: - var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); - errorHandler.warning('attribute "'+value+'" missed quot(")!!'); - el.add(attrName,value,start); - case S_ATTR_END: - s = S_TAG_SPACE; - break; - //case S_TAG_SPACE: - //case S_EQ: - //case S_ATTR_SPACE: - // void();break; - //case S_TAG_CLOSE: - //ignore warning - } - }else{//not space -//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE -//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE - switch(s){ - //case S_TAG:void();break; - //case S_ATTR:void();break; - //case S_ATTR_NOQUOT_VALUE:void();break; - case S_ATTR_SPACE: - var tagName = el.tagName; - if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){ - errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!'); - } - el.add(attrName,attrName,start); - start = p; - s = S_ATTR; - break; - case S_ATTR_END: - errorHandler.warning('attribute space is required"'+attrName+'"!!'); - case S_TAG_SPACE: - s = S_ATTR; - start = p; - break; - case S_EQ: - s = S_ATTR_NOQUOT_VALUE; - start = p; - break; - case S_TAG_CLOSE: - throw new Error("elements closed character '/' and '>' must be connected to"); - } - } - }//end outer switch - //console.log('p++',p) - p++; - } -} -/** - * @return true if has new namespace define - */ -function appendElement(el,domBuilder,currentNSMap){ - var tagName = el.tagName; - var localNSMap = null; - //var currentNSMap = parseStack[parseStack.length-1].currentNSMap; - var i = el.length; - while(i--){ - var a = el[i]; - var qName = a.qName; - var value = a.value; - var nsp = qName.indexOf(':'); - if(nsp>0){ - var prefix = a.prefix = qName.slice(0,nsp); - var localName = qName.slice(nsp+1); - var nsPrefix = prefix === 'xmlns' && localName; - }else{ - localName = qName; - prefix = null; - nsPrefix = qName === 'xmlns' && ''; - } - //can not set prefix,because prefix !== '' - a.localName = localName ; - //prefix == null for no ns prefix attribute - if(nsPrefix !== false){//hack!! - if(localNSMap == null){ - localNSMap = {}; - //console.log(currentNSMap,0) - _copy(currentNSMap,currentNSMap={}); - //console.log(currentNSMap,1) - } - currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value; - a.uri = 'http://www.w3.org/2000/xmlns/'; - domBuilder.startPrefixMapping(nsPrefix, value); - } - } - var i = el.length; - while(i--){ - a = el[i]; - var prefix = a.prefix; - if(prefix){//no prefix attribute has no namespace - if(prefix === 'xml'){ - a.uri = 'http://www.w3.org/XML/1998/namespace'; - }if(prefix !== 'xmlns'){ - a.uri = currentNSMap[prefix || '']; - - //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)} - } - } - } - var nsp = tagName.indexOf(':'); - if(nsp>0){ - prefix = el.prefix = tagName.slice(0,nsp); - localName = el.localName = tagName.slice(nsp+1); - }else{ - prefix = null;//important!! - localName = el.localName = tagName; - } - //no prefix element has default namespace - var ns = el.uri = currentNSMap[prefix || '']; - domBuilder.startElement(ns,localName,tagName,el); - //endPrefixMapping and startPrefixMapping have not any help for dom builder - //localNSMap = null - if(el.closed){ - domBuilder.endElement(ns,localName,tagName); - if(localNSMap){ - for(prefix in localNSMap){ - domBuilder.endPrefixMapping(prefix); - } - } - }else{ - el.currentNSMap = currentNSMap; - el.localNSMap = localNSMap; - //parseStack.push(el); - return true; - } -} -function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){ - if(/^(?:script|textarea)$/i.test(tagName)){ - var elEndStart = source.indexOf('',elStartEnd); - var text = source.substring(elStartEnd+1,elEndStart); - if(/[&<]/.test(text)){ - if(/^script$/i.test(tagName)){ - //if(!/\]\]>/.test(text)){ - //lexHandler.startCDATA(); - domBuilder.characters(text,0,text.length); - //lexHandler.endCDATA(); - return elEndStart; - //} - }//}else{//text area - text = text.replace(/&#?\w+;/g,entityReplacer); - domBuilder.characters(text,0,text.length); - return elEndStart; - //} - - } - } - return elStartEnd+1; -} -function fixSelfClosed(source,elStartEnd,tagName,closeMap){ - //if(tagName in closeMap){ - var pos = closeMap[tagName]; - if(pos == null){ - //console.log(tagName) - pos = source.lastIndexOf(''); - if(pos',start+4); - //append comment source.substring(4,end)//"); - case DOCUMENT_TYPE_NODE: - var pubid = node.publicId; - var sysid = node.systemId; - buf.push(''); - }else if(sysid && sysid!='.'){ - buf.push(' SYSTEM "',sysid,'">'); - }else{ - var sub = node.internalSubset; - if(sub){ - buf.push(" [",sub,"]"); - } - buf.push(">"); - } - return; - case PROCESSING_INSTRUCTION_NODE: - return buf.push( ""); - case ENTITY_REFERENCE_NODE: - return buf.push( '&',node.nodeName,';'); - //case ENTITY_NODE: - //case NOTATION_NODE: - default: - buf.push('??',node.nodeName); - } -} -function importNode(doc,node,deep){ - var node2; - switch (node.nodeType) { - case ELEMENT_NODE: - node2 = node.cloneNode(false); - node2.ownerDocument = doc; - //var attrs = node2.attributes; - //var len = attrs.length; - //for(var i=0;i','amp':'&','quot':'"','apos':"'"}; - if(locator){ - domBuilder.setDocumentLocator(locator); - } - - sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator); - sax$$1.domBuilder = options.domBuilder || domBuilder; - if(/\/x?html?$/.test(mimeType)){ - entityMap.nbsp = '\xa0'; - entityMap.copy = '\xa9'; - defaultNSMap['']= 'http://www.w3.org/1999/xhtml'; - } - defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace'; - if(source){ - sax$$1.parse(source,defaultNSMap,entityMap); - }else{ - sax$$1.errorHandler.error("invalid doc source"); - } - return domBuilder.doc; -}; -function buildErrorHandler(errorImpl,domBuilder,locator){ - if(!errorImpl){ - if(domBuilder instanceof DOMHandler){ - return domBuilder; - } - errorImpl = domBuilder ; - } - var errorHandler = {}; - var isCallback = errorImpl instanceof Function; - locator = locator||{}; - function build(key){ - var fn = errorImpl[key]; - if(!fn && isCallback){ - fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl; - } - errorHandler[key] = fn && function(msg){ - fn('[xmldom '+key+']\t'+msg+_locator(locator)); - }||function(){}; - } - build('warning'); - build('error'); - build('fatalError'); - return errorHandler; -} - -//console.log('#\n\n\n\n\n\n\n####') -/** - * +ContentHandler+ErrorHandler - * +LexicalHandler+EntityResolver2 - * -DeclHandler-DTDHandler - * - * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler - * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2 - * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html - */ -function DOMHandler() { - this.cdata = false; -} -function position(locator,node){ - node.lineNumber = locator.lineNumber; - node.columnNumber = locator.columnNumber; -} -/** - * @see org.xml.sax.ContentHandler#startDocument - * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html - */ -DOMHandler.prototype = { - startDocument : function() { - this.doc = new DOMImplementation().createDocument(null, null, null); - if (this.locator) { - this.doc.documentURI = this.locator.systemId; - } - }, - startElement:function(namespaceURI, localName, qName, attrs) { - var doc = this.doc; - var el = doc.createElementNS(namespaceURI, qName||localName); - var len = attrs.length; - appendElement(this, el); - this.currentElement = el; - - this.locator && position(this.locator,el); - for (var i = 0 ; i < len; i++) { - var namespaceURI = attrs.getURI(i); - var value = attrs.getValue(i); - var qName = attrs.getQName(i); - var attr = doc.createAttributeNS(namespaceURI, qName); - this.locator &&position(attrs.getLocator(i),attr); - attr.value = attr.nodeValue = value; - el.setAttributeNode(attr); - } - }, - endElement:function(namespaceURI, localName, qName) { - var current = this.currentElement; - var tagName = current.tagName; - this.currentElement = current.parentNode; - }, - startPrefixMapping:function(prefix, uri) { - }, - endPrefixMapping:function(prefix) { - }, - processingInstruction:function(target, data) { - var ins = this.doc.createProcessingInstruction(target, data); - this.locator && position(this.locator,ins); - appendElement(this, ins); - }, - ignorableWhitespace:function(ch, start, length) { - }, - characters:function(chars, start, length) { - chars = _toString.apply(this,arguments); - //console.log(chars) - if(chars){ - if (this.cdata) { - var charNode = this.doc.createCDATASection(chars); - } else { - var charNode = this.doc.createTextNode(chars); - } - if(this.currentElement){ - this.currentElement.appendChild(charNode); - }else if(/^\s*$/.test(chars)){ - this.doc.appendChild(charNode); - //process xml - } - this.locator && position(this.locator,charNode); - } - }, - skippedEntity:function(name) { - }, - endDocument:function() { - this.doc.normalize(); - }, - setDocumentLocator:function (locator) { - if(this.locator = locator){// && !('lineNumber' in locator)){ - locator.lineNumber = 0; - } - }, - //LexicalHandler - comment:function(chars, start, length) { - chars = _toString.apply(this,arguments); - var comm = this.doc.createComment(chars); - this.locator && position(this.locator,comm); - appendElement(this, comm); - }, - - startCDATA:function() { - //used in characters() methods - this.cdata = true; - }, - endCDATA:function() { - this.cdata = false; - }, - - startDTD:function(name, publicId, systemId) { - var impl = this.doc.implementation; - if (impl && impl.createDocumentType) { - var dt = impl.createDocumentType(name, publicId, systemId); - this.locator && position(this.locator,dt); - appendElement(this, dt); - } - }, - /** - * @see org.xml.sax.ErrorHandler - * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html - */ - warning:function(error) { - console.warn('[xmldom warning]\t'+error,_locator(this.locator)); - }, - error:function(error) { - console.error('[xmldom error]\t'+error,_locator(this.locator)); - }, - fatalError:function(error) { - console.error('[xmldom fatalError]\t'+error,_locator(this.locator)); - throw error; - } -}; -function _locator(l){ - if(l){ - return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']' - } -} -function _toString(chars,start,length){ - if(typeof chars == 'string'){ - return chars.substr(start,length) - }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") - if(chars.length >= start+length || start){ - return new java.lang.String(chars,start,length)+''; - } - return chars; - } -} - -/* - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html - * used method of org.xml.sax.ext.LexicalHandler: - * #comment(chars, start, length) - * #startCDATA() - * #endCDATA() - * #startDTD(name, publicId, systemId) - * - * - * IGNORED method of org.xml.sax.ext.LexicalHandler: - * #endDTD() - * #startEntity(name) - * #endEntity(name) - * - * - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html - * IGNORED method of org.xml.sax.ext.DeclHandler - * #attributeDecl(eName, aName, type, mode, value) - * #elementDecl(name, model) - * #externalEntityDecl(name, publicId, systemId) - * #internalEntityDecl(name, value) - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html - * IGNORED method of org.xml.sax.EntityResolver2 - * #resolveEntity(String name,String publicId,String baseURI,String systemId) - * #resolveEntity(publicId, systemId) - * #getExternalSubset(name, baseURI) - * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html - * IGNORED method of org.xml.sax.DTDHandler - * #notationDecl(name, publicId, systemId) {}; - * #unparsedEntityDecl(name, publicId, systemId, notationName) {}; - */ -"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){ - DOMHandler.prototype[key] = function(){return null}; -}); - -/* 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 */ -function appendElement (hander,node) { - if (!hander.currentElement) { - hander.doc.appendChild(node); - } else { - hander.currentElement.appendChild(node); - } -}//appendChild and setAttributeNS are preformance key - -//if(typeof require == 'function'){ - var XMLReader = sax.XMLReader; - var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation; - exports.XMLSerializer = dom.XMLSerializer ; - exports.DOMParser = DOMParser; -//} -}); -var domParser_1 = domParser.DOMImplementation; -var domParser_2 = domParser.XMLSerializer; -var domParser_3 = domParser.DOMParser; - -var togeojson = createCommonjsModule(function (module, exports) { -var toGeoJSON = (function() { - - var removeSpace = /\s*/g, - trimSpace = /^\s*|\s*$/g, - splitSpace = /\s+/; - // generate a short, numeric hash of a string - function okhash(x) { - if (!x || !x.length) return 0; - for (var i = 0, h = 0; i < x.length; i++) { - h = ((h << 5) - h) + x.charCodeAt(i) | 0; - } return h; - } - // all Y children of X - function get(x, y) { return x.getElementsByTagName(y); } - function attr(x, y) { return x.getAttribute(y); } - function attrf(x, y) { return parseFloat(attr(x, y)); } - // one Y child of X, if any, otherwise null - function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; } - // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize - function norm(el) { if (el.normalize) { el.normalize(); } return el; } - // cast array x into numbers - function numarray(x) { - for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); } - return o; - } - // get the content of a text node, if any - function nodeVal(x) { - if (x) { norm(x); } - return (x && x.textContent) || ''; - } - // get the contents of multiple text nodes, if present - function getMulti(x, ys) { - var o = {}, n, k; - for (k = 0; k < ys.length; k++) { - n = get1(x, ys[k]); - if (n) o[ys[k]] = nodeVal(n); - } - return o; - } - // add properties of Y to X, overwriting if present in both - function extend(x, y) { for (var k in y) x[k] = y[k]; } - // get one coordinate from a coordinate array, if any - function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); } - // get all coordinates from a coordinate array as [[],[]] - function coord(v) { - var coords = v.replace(trimSpace, '').split(splitSpace), - o = []; - for (var i = 0; i < coords.length; i++) { - o.push(coord1(coords[i])); - } - return o; - } - function coordPair(x) { - var ll = [attrf(x, 'lon'), attrf(x, 'lat')], - ele = get1(x, 'ele'), - // handle namespaced attribute in browser - heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'), - time = get1(x, 'time'), - e; - if (ele) { - e = parseFloat(nodeVal(ele)); - if (!isNaN(e)) { - ll.push(e); - } - } - return { - coordinates: ll, - time: time ? nodeVal(time) : null, - heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null - }; - } + function mousemove() { + if (!lasso) { + lasso = uiLasso(context); + context.surface().call(lasso); + } - // create a new feature collection parent object - function fc() { - return { - type: 'FeatureCollection', - features: [] - }; - } + lasso.p(context.mouse()); + } - var serializer; - if (typeof XMLSerializer !== 'undefined') { - /* istanbul ignore next */ - serializer = new XMLSerializer(); - // only require xmldom in a node environment - } else if ('object' === 'object' && typeof process === 'object' && !process.browser) { - serializer = new (domParser.XMLSerializer)(); - } - function xml2str(str) { - // IE9 will create a new XMLSerializer but it'll crash immediately. - // This line is ignored because we don't run coverage tests in IE9 - /* istanbul ignore next */ - if (str.xml !== undefined) return str.xml; - return serializer.serializeToString(str); - } - - var t = { - kml: function(doc) { - - var gj = fc(), - // styleindex keeps track of hashed styles in order to match features - styleIndex = {}, styleByHash = {}, - // stylemapindex keeps track of style maps to expose in properties - styleMapIndex = {}, - // atomic geospatial types supported by KML - MultiGeometry is - // handled separately - geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'], - // all root placemarks in the file - placemarks = get(doc, 'Placemark'), - styles = get(doc, 'Style'), - styleMaps = get(doc, 'StyleMap'); - - for (var k = 0; k < styles.length; k++) { - var hash = okhash(xml2str(styles[k])).toString(16); - styleIndex['#' + attr(styles[k], 'id')] = hash; - styleByHash[hash] = styles[k]; - } - for (var l = 0; l < styleMaps.length; l++) { - styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16); - var pairs = get(styleMaps[l], 'Pair'); - var pairsMap = {}; - for (var m = 0; m < pairs.length; m++) { - pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl')); - } - styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap; - } - for (var j = 0; j < placemarks.length; j++) { - gj.features = gj.features.concat(getPlacemark(placemarks[j])); - } - function kmlColor(v) { - var color, opacity; - v = v || ''; - if (v.substr(0, 1) === '#') { v = v.substr(1); } - if (v.length === 6 || v.length === 3) { color = v; } - if (v.length === 8) { - opacity = parseInt(v.substr(0, 2), 16) / 255; - color = '#' + v.substr(6, 2) + - v.substr(4, 2) + - v.substr(2, 2); - } - return [color, isNaN(opacity) ? undefined : opacity]; - } - function gxCoord(v) { return numarray(v.split(' ')); } - function gxCoords(root) { - var elems = get(root, 'coord', 'gx'), coords = [], times = []; - if (elems.length === 0) elems = get(root, 'gx:coord'); - for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i]))); - var timeElems = get(root, 'when'); - for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j])); - return { - coords: coords, - times: times - }; - } - function getGeometry(root) { - var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = []; - if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); } - if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); } - if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); } - for (i = 0; i < geotypes.length; i++) { - geomNodes = get(root, geotypes[i]); - if (geomNodes) { - for (j = 0; j < geomNodes.length; j++) { - geomNode = geomNodes[j]; - if (geotypes[i] === 'Point') { - geoms.push({ - type: 'Point', - coordinates: coord1(nodeVal(get1(geomNode, 'coordinates'))) - }); - } else if (geotypes[i] === 'LineString') { - geoms.push({ - type: 'LineString', - coordinates: coord(nodeVal(get1(geomNode, 'coordinates'))) - }); - } else if (geotypes[i] === 'Polygon') { - var rings = get(geomNode, 'LinearRing'), - coords = []; - for (k = 0; k < rings.length; k++) { - coords.push(coord(nodeVal(get1(rings[k], 'coordinates')))); - } - geoms.push({ - type: 'Polygon', - coordinates: coords - }); - } else if (geotypes[i] === 'Track' || - geotypes[i] === 'gx:Track') { - var track = gxCoords(geomNode); - geoms.push({ - type: 'LineString', - coordinates: track.coords - }); - if (track.times.length) coordTimes.push(track.times); - } - } - } - } - return { - geoms: geoms, - coordTimes: coordTimes - }; - } - function getPlacemark(root) { - var geomsAndTimes = getGeometry(root), i, properties = {}, - name = nodeVal(get1(root, 'name')), - address = nodeVal(get1(root, 'address')), - styleUrl = nodeVal(get1(root, 'styleUrl')), - description = nodeVal(get1(root, 'description')), - timeSpan = get1(root, 'TimeSpan'), - timeStamp = get1(root, 'TimeStamp'), - extendedData = get1(root, 'ExtendedData'), - lineStyle = get1(root, 'LineStyle'), - polyStyle = get1(root, 'PolyStyle'), - visibility = get1(root, 'visibility'); - - if (!geomsAndTimes.geoms.length) return []; - if (name) properties.name = name; - if (address) properties.address = address; - if (styleUrl) { - if (styleUrl[0] !== '#') { - styleUrl = '#' + styleUrl; - } - - properties.styleUrl = styleUrl; - if (styleIndex[styleUrl]) { - properties.styleHash = styleIndex[styleUrl]; - } - if (styleMapIndex[styleUrl]) { - properties.styleMapHash = styleMapIndex[styleUrl]; - properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal]; - } - // Try to populate the lineStyle or polyStyle since we got the style hash - var style = styleByHash[properties.styleHash]; - if (style) { - if (!lineStyle) lineStyle = get1(style, 'LineStyle'); - if (!polyStyle) polyStyle = get1(style, 'PolyStyle'); - } - } - if (description) properties.description = description; - if (timeSpan) { - var begin = nodeVal(get1(timeSpan, 'begin')); - var end = nodeVal(get1(timeSpan, 'end')); - properties.timespan = { begin: begin, end: end }; - } - if (timeStamp) { - properties.timestamp = nodeVal(get1(timeStamp, 'when')); - } - if (lineStyle) { - var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))), - color = linestyles[0], - opacity = linestyles[1], - width = parseFloat(nodeVal(get1(lineStyle, 'width'))); - if (color) properties.stroke = color; - if (!isNaN(opacity)) properties['stroke-opacity'] = opacity; - if (!isNaN(width)) properties['stroke-width'] = width; - } - if (polyStyle) { - var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))), - pcolor = polystyles[0], - popacity = polystyles[1], - fill = nodeVal(get1(polyStyle, 'fill')), - outline = nodeVal(get1(polyStyle, 'outline')); - if (pcolor) properties.fill = pcolor; - if (!isNaN(popacity)) properties['fill-opacity'] = popacity; - if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0; - if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0; - } - if (extendedData) { - var datas = get(extendedData, 'Data'), - simpleDatas = get(extendedData, 'SimpleData'); - - for (i = 0; i < datas.length; i++) { - properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value')); - } - for (i = 0; i < simpleDatas.length; i++) { - properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]); - } - } - if (visibility) { - properties.visibility = nodeVal(visibility); - } - if (geomsAndTimes.coordTimes.length) { - properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ? - geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes; - } - var feature = { - type: 'Feature', - geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : { - type: 'GeometryCollection', - geometries: geomsAndTimes.geoms - }, - properties: properties - }; - if (attr(root, 'id')) feature.id = attr(root, 'id'); - return [feature]; - } - return gj; - }, - gpx: function(doc) { - var i, - tracks = get(doc, 'trk'), - routes = get(doc, 'rte'), - waypoints = get(doc, 'wpt'), - // a feature collection - gj = fc(), - feature; - for (i = 0; i < tracks.length; i++) { - feature = getTrack(tracks[i]); - if (feature) gj.features.push(feature); - } - for (i = 0; i < routes.length; i++) { - feature = getRoute(routes[i]); - if (feature) gj.features.push(feature); - } - for (i = 0; i < waypoints.length; i++) { - gj.features.push(getPoint(waypoints[i])); - } - function getPoints(node, pointname) { - var pts = get(node, pointname), - line = [], - times = [], - heartRates = [], - l = pts.length; - if (l < 2) return {}; // Invalid line in GeoJSON - for (var i = 0; i < l; i++) { - var c = coordPair(pts[i]); - line.push(c.coordinates); - if (c.time) times.push(c.time); - if (c.heartRate) heartRates.push(c.heartRate); - } - return { - line: line, - times: times, - heartRates: heartRates - }; - } - function getTrack(node) { - var segments = get(node, 'trkseg'), - track = [], - times = [], - heartRates = [], - line; - for (var i = 0; i < segments.length; i++) { - line = getPoints(segments[i], 'trkpt'); - if (line) { - if (line.line) track.push(line.line); - if (line.times && line.times.length) times.push(line.times); - if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates); - } - } - if (track.length === 0) return; - var properties = getProperties(node); - extend(properties, getLineStyle(get1(node, 'extensions'))); - if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times; - if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates; - return { - type: 'Feature', - properties: properties, - geometry: { - type: track.length === 1 ? 'LineString' : 'MultiLineString', - coordinates: track.length === 1 ? track[0] : track - } - }; - } - function getRoute(node) { - var line = getPoints(node, 'rtept'); - if (!line.line) return; - var prop = getProperties(node); - extend(prop, getLineStyle(get1(node, 'extensions'))); - var routeObj = { - type: 'Feature', - properties: prop, - geometry: { - type: 'LineString', - coordinates: line.line - } - }; - return routeObj; - } - function getPoint(node) { - var prop = getProperties(node); - extend(prop, getMulti(node, ['sym'])); - return { - type: 'Feature', - properties: prop, - geometry: { - type: 'Point', - coordinates: coordPair(node).coordinates - } - }; - } - function getLineStyle(extensions) { - var style = {}; - if (extensions) { - var lineStyle = get1(extensions, 'line'); - if (lineStyle) { - var color = nodeVal(get1(lineStyle, 'color')), - opacity = parseFloat(nodeVal(get1(lineStyle, 'opacity'))), - width = parseFloat(nodeVal(get1(lineStyle, 'width'))); - if (color) style.stroke = color; - if (!isNaN(opacity)) style['stroke-opacity'] = opacity; - // GPX width is in mm, convert to px with 96 px per inch - if (!isNaN(width)) style['stroke-width'] = width * 96 / 25.4; - } - } - return style; - } - function getProperties(node) { - var prop = getMulti(node, ['name', 'cmt', 'desc', 'type', 'time', 'keywords']), - links = get(node, 'link'); - if (links.length) prop.links = []; - for (var i = 0, link; i < links.length; i++) { - link = { href: attr(links[i], 'href') }; - extend(link, getMulti(links[i], ['text', 'type'])); - prop.links.push(link); - } - return prop; - } - return gj; - } - }; - return t; -})(); + function normalize(a, b) { + return [ + [Math.min(a[0], b[0]), Math.min(a[1], b[1])], + [Math.max(a[0], b[0]), Math.max(a[1], b[1])]]; + } -module.exports = toGeoJSON; -}); -var _initialized = false; -var _enabled = false; -var _geojson; + function lassoed() { + if (!lasso) return []; + var graph = context.graph(), + bounds = lasso.extent().map(context.projection.invert), + extent = geoExtent$$1(normalize(bounds[0], bounds[1])); -function svgGpx$$1(projection$$1, context, dispatch) { - var _showLabels = true; - var detected = utilDetect(); - var layer; - var _src; + return map$3(context.intersects(extent).filter(function(entity) { + return entity.type === 'node' && + geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) && + !context.features().isHidden(entity, graph, entity.geometry(graph)); + }), 'id'); + } - function init() { - if (_initialized) return; // run once + function mouseup() { + select(window) + .on('mousemove.lasso', null) + .on('mouseup.lasso', null); - _geojson = {}; - _enabled = true; + if (!lasso) return; - function over() { - event.stopPropagation(); - event.preventDefault(); - event.dataTransfer.dropEffect = 'copy'; - } + var ids = lassoed(); + lasso.close(); - d3_select('body') - .attr('dropzone', 'copy') - .on('drop.localgpx', function() { - event.stopPropagation(); - event.preventDefault(); - if (!detected.filedrop) return; - drawGpx.files(event.dataTransfer.files); - }) - .on('dragenter.localgpx', over) - .on('dragexit.localgpx', over) - .on('dragover.localgpx', over); + if (ids.length) { + context.enter(modeSelect(context, ids)); + } + } - _initialized = true; - } + selection$$1 + .on('mousedown.lasso', mousedown); + }; - function drawGpx(selection$$1) { - var getPath = svgPath(projection$$1).geojson; + behavior.off = function(selection$$1) { + selection$$1.on('mousedown.lasso', null); + }; - layer = selection$$1.selectAll('.layer-gpx') - .data(_enabled ? [0] : []); - layer.exit() - .remove(); + return behavior; + } - layer = layer.enter() - .append('g') - .attr('class', 'layer-gpx') - .merge(layer); + /* Creates a keybinding behavior for an operation */ + function behaviorOperation() { + var _operation, keybinding; + + var behavior = function () { + if (_operation && _operation.available()) { + keybinding = d3keybinding('behavior.key.' + _operation.id); + keybinding.on(_operation.keys, function() { + event.preventDefault(); + var disabled = _operation.disabled(); + var flash; + + if (disabled) { + flash = uiFlash() + .duration(4000) + .iconName('#operation-' + _operation.id) + .iconClass('operation disabled') + .text(_operation.tooltip); + + flash(); + + } else { + flash = uiFlash() + .duration(2000) + .iconName('#operation-' + _operation.id) + .iconClass('operation') + .text(_operation.annotation() || _operation.title); + + flash(); + _operation(); + } + }); + + select(document).call(keybinding); + } + return behavior; + }; - var paths = layer - .selectAll('path') - .data([_geojson]); - paths.exit() - .remove(); + behavior.off = function() { + if (keybinding) { + select(document).call(keybinding.off); + } + }; - paths = paths.enter() - .append('path') - .attr('class', 'gpx') - .merge(paths); - paths - .attr('d', getPath); + behavior.which = function (_) { + if (!arguments.length) return _operation; + _operation = _; + return behavior; + }; - var labelData = _showLabels && _geojson.features ? _geojson.features : []; - labelData = labelData.filter(getPath); + return behavior; + } - layer - .call(drawLabels, 'gpxlabel-halo', labelData) - .call(drawLabels, 'gpxlabel', labelData); + /** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ + function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; + } + /** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ + function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; + } - function drawLabels(selection$$1, textClass, data) { - var labels = selection$$1.selectAll('text.' + textClass) - .data(data); + /** Used for built-in method references. */ + var objectProto$19 = Object.prototype; - // exit - labels.exit() - .remove(); + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString$2 = objectProto$19.toString; - // enter/update - labels = labels.enter() - .append('text') - .attr('class', textClass) - .merge(labels) - .text(function(d) { - if (d.properties) { - return d.properties.desc || d.properties.name; - } - return null; - }) - .attr('x', function(d) { - var centroid = getPath.centroid(d); - return centroid[0] + 11; - }) - .attr('y', function(d) { - var centroid = getPath.centroid(d); - return centroid[1]; - }); - } + /** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ + var invert = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString$2.call(value); } + result[value] = key; + }, constant$13(identity$8)); - function toDom(x) { - return (new DOMParser()).parseFromString(x, 'text/xml'); - } - + /** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ + function mapValues(object, iteratee) { + var result = {}; + iteratee = baseIteratee(iteratee, 3); - function getExtension(fileName) { - if (isUndefined(fileName)) { - return ''; - } + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; + } - var lastDotIndex = fileName.lastIndexOf('.'); - if (lastDotIndex < 0) { - return ''; - } + function behaviorPaste(context) { + var keybinding = d3keybinding('paste'); - return fileName.substr(lastDotIndex); - } + function doPaste() { + event.preventDefault(); - function parseSaveAndZoom(extension, data) { - switch (extension) { - default: - drawGpx.geojson(togeojson.gpx(toDom(data))).fitZoom(); - break; - case '.kml': - drawGpx.geojson(togeojson.kml(toDom(data))).fitZoom(); - break; - case '.geojson': - case '.json': - drawGpx.geojson(JSON.parse(data)).fitZoom(); - break; - } - } + var baseGraph = context.graph(), + mouse$$1 = context.mouse(), + projection = context.projection, + viewport = geoExtent$$1(projection.clipExtent()).polygon(); + if (!geoPointInPolygon(mouse$$1, viewport)) return; - drawGpx.showLabels = function(_) { - if (!arguments.length) return _showLabels; - _showLabels = _; - return this; - }; + var extent = geoExtent$$1(), + oldIDs = context.copyIDs(), + oldGraph = context.copyGraph(), + newIDs = []; + if (!oldIDs.length) return; - drawGpx.enabled = function(_) { - if (!arguments.length) return _enabled; - _enabled = _; - dispatch.call('change'); - return this; - }; + var action = actionCopyEntities(oldIDs, oldGraph); + context.perform(action); + var copies = action.copies(); + var originals = invert(mapValues(copies, 'id')); + for (var id in copies) { + var oldEntity = oldGraph.entity(id), + newEntity = copies[id]; - drawGpx.hasGpx = function() { - return (!(isEmpty(_geojson) || isEmpty(_geojson.features))); - }; + extent._extend(oldEntity.extent(oldGraph)); + // Exclude child nodes from newIDs if their parent way was also copied. + var parents = context.graph().parentWays(newEntity), + parentCopied = false; + for (var i = 0; i < parents.length; i++) { + if (originals[parents[i].id]) { + parentCopied = true; + break; + } + } - drawGpx.geojson = function(gj) { - if (!arguments.length) return _geojson; - if (isEmpty(gj) || isEmpty(gj.features)) return this; - _geojson = gj; - dispatch.call('change'); - return this; - }; + if (!parentCopied) { + newIDs.push(newEntity.id); + } + } + // Put pasted objects where mouse pointer is.. + var center = projection(extent.center()), + delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ]; - drawGpx.url = function(url) { - d3_text(url, function(err, data) { - if (!err) { - _src = url; - var extension = getExtension(url); - parseSaveAndZoom(extension, data); - } - }); - return this; - }; + context.perform(actionMove(newIDs, delta, projection)); + context.enter(modeMove$$1(context, newIDs, baseGraph)); + } - drawGpx.files = function(fileList) { - if (!fileList.length) return this; - var f = fileList[0], - reader = new FileReader(); + function paste() { + keybinding.on(uiCmd('⌘V'), doPaste); + select(document).call(keybinding); + return paste; + } - reader.onload = (function(file) { - _src = file.name; - var extension = getExtension(file.name); - return function (e) { - parseSaveAndZoom(extension, e.target.result); - }; - })(f); - reader.readAsText(f); - return this; - }; + paste.off = function() { + select(document).call(keybinding.off); + }; - drawGpx.getSrc = function () { - return _src; - }; + return paste; + } + function behaviorSelect(context) { + var lastMouse = null; + var suppressMenu = true; + var tolerance = 4; + var p1 = null; - drawGpx.fitZoom = function() { - if (!this.hasGpx()) return this; - - var map = context.map(); - var viewport = map.trimmedExtent().polygon(); - var coords = reduce(_geojson.features, function(coords, feature) { - var c = feature.geometry.coordinates; - - /* eslint-disable no-fallthrough */ - switch (feature.geometry.type) { - case 'Point': - c = [c]; - case 'MultiPoint': - case 'LineString': - break; - - case 'MultiPolygon': - c = flatten(c); - case 'Polygon': - case 'MultiLineString': - c = flatten(c); - break; - } - /* eslint-enable no-fallthrough */ - return union(coords, c); - }, []); + function point$$1() { + return mouse(context.container().node()); + } - if (!geoPolygonIntersectsPolygon(viewport, coords, true)) { - var extent = geoExtent$$1(d3_geoBounds({ type: 'LineString', coordinates: coords })); - map.centerZoom(extent.center(), map.trimmedExtentZoom(extent)); - } - return this; - }; + function keydown() { + var e = event; + if (e && e.shiftKey) { + context.surface() + .classed('behavior-multiselect', true); + } + if (e && e.keyCode === 93) { // context menu + e.preventDefault(); + e.stopPropagation(); + } + } - init(); - return drawGpx; -} - -function svgIcon(name, svgklass, useklass) { - return function drawIcon(selection) { - selection.selectAll('svg') - .data([0]) - .enter() - .append('svg') - .attr('class', 'icon ' + (svgklass || '')) - .append('use') - .attr('xlink:href', name) - .attr('class', useklass); - }; -} - -function svgLabels(projection$$1, context) { - var path = d3_geoPath(projection$$1); - var detected = utilDetect(); - var baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'); - var _rdrawn = rbush_1(); - var _rskipped = rbush_1(); - var _textWidthCache = {}; - var _entitybboxes = {}; - - // Listed from highest to lowest priority - var labelStack = [ - ['line', 'aeroway', '*', 12], - ['line', 'highway', 'motorway', 12], - ['line', 'highway', 'trunk', 12], - ['line', 'highway', 'primary', 12], - ['line', 'highway', 'secondary', 12], - ['line', 'highway', 'tertiary', 12], - ['line', 'highway', '*', 12], - ['line', 'railway', '*', 12], - ['line', 'waterway', '*', 12], - ['area', 'aeroway', '*', 12], - ['area', 'amenity', '*', 12], - ['area', 'building', '*', 12], - ['area', 'historic', '*', 12], - ['area', 'leisure', '*', 12], - ['area', 'man_made', '*', 12], - ['area', 'natural', '*', 12], - ['area', 'shop', '*', 12], - ['area', 'tourism', '*', 12], - ['area', 'camp_site', '*', 12], - ['point', 'aeroway', '*', 10], - ['point', 'amenity', '*', 10], - ['point', 'building', '*', 10], - ['point', 'historic', '*', 10], - ['point', 'leisure', '*', 10], - ['point', 'man_made', '*', 10], - ['point', 'natural', '*', 10], - ['point', 'shop', '*', 10], - ['point', 'tourism', '*', 10], - ['point', 'camp_site', '*', 10], - ['line', 'name', '*', 12], - ['area', 'name', '*', 12], - ['point', 'name', '*', 10] - ]; + function keyup() { + var e = event; + if (!e || !e.shiftKey) { + context.surface() + .classed('behavior-multiselect', false); + } - function blacklisted(preset) { - var noIcons = ['building', 'landuse', 'natural']; - return some(noIcons, function(s) { - return preset.id.indexOf(s) >= 0; - }); - } + if (e && e.keyCode === 93) { // context menu + e.preventDefault(); + e.stopPropagation(); + contextmenu(); + } + } - function get(array, prop) { - return function(d, i) { return array[i][prop]; }; - } + function mousedown() { + if (!p1) p1 = point$$1(); + select(window) + .on('mouseup.select', mouseup, true); - function textWidth(text, size, elem) { - var c = _textWidthCache[size]; - if (!c) c = _textWidthCache[size] = {}; + var isShowAlways = +context.storage('edit-menu-show-always') === 1; + suppressMenu = !isShowAlways; + } - if (c[text]) { - return c[text]; - } else if (elem) { - c[text] = elem.getComputedTextLength(); - return c[text]; + function mousemove() { + if (event) lastMouse = event; + } - } else { - var str = encodeURIComponent(text).match(/%[CDEFcdef]/g); - if (str === null) { - return size / 3 * 2 * text.length; - } else { - return size / 3 * (2 * text.length + str.length); - } - } - } + function mouseup() { + click(); + } - function drawLinePaths(selection, entities, filter, classes, labels) { - var paths = selection.selectAll('path') - .filter(filter) - .data(entities, osmEntity$$1.key); - - // exit - paths.exit() - .remove(); - - // enter/update - paths.enter() - .append('path') - .style('stroke-width', get(labels, 'font-size')) - .attr('id', function(d) { return 'labelpath-' + d.id; }) - .attr('class', classes) - .merge(paths) - .attr('d', get(labels, 'lineString')); - } - - - function drawLineLabels(selection, entities, filter, classes, labels) { - var texts = selection.selectAll('text.' + classes) - .filter(filter) - .data(entities, osmEntity$$1.key); - - // exit - texts.exit() - .remove(); - - // enter - texts.enter() - .append('text') - .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; }) - .attr('dy', baselineHack ? '0.35em' : null) - .append('textPath') - .attr('class', 'textpath'); - - // update - selection.selectAll('text.' + classes).selectAll('.textpath') - .filter(filter) - .data(entities, osmEntity$$1.key) - .attr('startOffset', '50%') - .attr('xlink:href', function(d) { return '#labelpath-' + d.id; }) - .text(utilDisplayNameForPath); - } - - - function drawPointLabels(selection, entities, filter, classes, labels) { - var texts = selection.selectAll('text.' + classes) - .filter(filter) - .data(entities, osmEntity$$1.key); - - // exit - texts.exit() - .remove(); - - // enter/update - texts.enter() - .append('text') - .attr('class', function(d, i) { - return classes + ' ' + labels[i].classes + ' ' + d.id; - }) - .merge(texts) - .attr('x', get(labels, 'x')) - .attr('y', get(labels, 'y')) - .style('text-anchor', get(labels, 'textAnchor')) - .text(utilDisplayName) - .each(function(d, i) { - textWidth(utilDisplayName(d), labels[i].height, this); - }); - } + function contextmenu() { + var e = event; + e.preventDefault(); + e.stopPropagation(); - function drawAreaLabels(selection, entities, filter, classes, labels) { - entities = entities.filter(hasText); - labels = labels.filter(hasText); - drawPointLabels(selection, entities, filter, classes, labels); + if (!+e.clientX && !+e.clientY) { + if (lastMouse) { + e.sourceEvent = lastMouse; + } else { + return; + } + } - function hasText(d, i) { - return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y'); - } - } + if (!p1) p1 = point$$1(); + suppressMenu = false; + click(); + } - function drawAreaIcons(selection, entities, filter, classes, labels) { - var icons = selection.selectAll('use.' + classes) - .filter(filter) - .data(entities, osmEntity$$1.key); - - // exit - icons.exit() - .remove(); - - // enter/update - icons.enter() - .append('use') - .attr('class', 'icon ' + classes) - .attr('width', '17px') - .attr('height', '17px') - .merge(icons) - .attr('transform', get(labels, 'transform')) - .attr('xlink:href', function(d) { - var preset = context.presets().match(d, context.graph()); - var picon = preset && preset.icon; - - if (!picon) { - return ''; - } else { - var isMaki = dataFeatureIcons.indexOf(picon) !== -1; - return '#' + picon + (isMaki ? '-15' : ''); - } - }); - } + function click() { + select(window) + .on('mouseup.select', null, true); + if (!p1) return; + var p2 = point$$1(); + var dist = geoVecLength(p1, p2); - function drawCollisionBoxes(selection, rtree, which) { - var classes = 'debug ' + which + ' ' + (which === 'debug-skipped' ? 'orange' : 'yellow'); + p1 = null; + if (dist > tolerance) { + return; + } - var gj = []; - if (context.getDebug('collision')) { - gj = rtree.all().map(function(d) { - return { type: 'Polygon', coordinates: [[ - [d.minX, d.minY], - [d.maxX, d.minY], - [d.maxX, d.maxY], - [d.minX, d.maxY], - [d.minX, d.minY] - ]]}; - }); - } + var isMultiselect = event.shiftKey || select('#surface .lasso').node(); + var isShowAlways = +context.storage('edit-menu-show-always') === 1; + var datum = event.target.__data__ || (lastMouse && lastMouse.target.__data__); + var mode = context.mode(); - var boxes = selection.selectAll('.' + which) - .data(gj); + var entity = datum && datum.properties && datum.properties.entity; + if (entity) datum = entity; - // exit - boxes.exit() - .remove(); + if (datum && datum.type === 'midpoint') { + datum = datum.parents[0]; + } - // enter/update - boxes.enter() - .append('path') - .attr('class', classes) - .merge(boxes) - .attr('d', d3_geoPath()); - } + if (!(datum instanceof osmEntity$$1)) { + // clicked nothing.. + if (!isMultiselect && mode.id !== 'browse') { + context.enter(modeBrowse(context)); + } + } else { + // clicked an entity.. + var selectedIDs = context.selectedIDs(); + + if (!isMultiselect) { + if (selectedIDs.length > 1 && (!suppressMenu && !isShowAlways)) { + // multiple things already selected, just show the menu... + mode.suppressMenu(false).reselect(); + } else { + // select a single thing.. + context.enter(modeSelect(context, [datum.id]).suppressMenu(suppressMenu)); + } + + } else { + if (selectedIDs.indexOf(datum.id) !== -1) { + // clicked entity is already in the selectedIDs list.. + if (!suppressMenu && !isShowAlways) { + // don't deselect clicked entity, just show the menu. + mode.suppressMenu(false).reselect(); + } else { + // deselect clicked entity, then reenter select mode or return to browse mode.. + selectedIDs = without(selectedIDs, datum.id); + context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse(context)); + } + } else { + // clicked entity is not in the selected list, add it.. + selectedIDs = selectedIDs.concat([datum.id]); + context.enter(modeSelect(context, selectedIDs).suppressMenu(suppressMenu)); + } + } + } - function drawLabels(selection, graph, entities, filter, dimensions, fullRedraw) { - var wireframe = context.surface().classed('fill-wireframe'); - var zoom = geoScaleToZoom(projection$$1.scale()); + // reset for next time.. + suppressMenu = true; + } - var labelable = []; - var renderNodeAs = {}; - var i, j, k, entity, geometry; - for (i = 0; i < labelStack.length; i++) { - labelable.push([]); - } + var behavior = function(selection$$1) { + lastMouse = null; + suppressMenu = true; + p1 = null; + + select(window) + .on('keydown.select', keydown) + .on('keyup.select', keyup) + .on('contextmenu.select-window', function() { + // Edge and IE really like to show the contextmenu on the + // menubar when user presses a keyboard menu button + // even after we've already preventdefaulted the key event. + var e = event; + if (+e.clientX === 0 && +e.clientY === 0) { + event.preventDefault(); + event.stopPropagation(); + } + }); + + selection$$1 + .on('mousedown.select', mousedown) + .on('mousemove.select', mousemove) + .on('contextmenu.select', contextmenu); + + if (event && event.shiftKey) { + context.surface() + .classed('behavior-multiselect', true); + } + }; - if (fullRedraw) { - _rdrawn.clear(); - _rskipped.clear(); - _entitybboxes = {}; - } else { - for (i = 0; i < entities.length; i++) { - entity = entities[i]; - var toRemove = [] - .concat(_entitybboxes[entity.id] || []) - .concat(_entitybboxes[entity.id + 'I'] || []); - - for (j = 0; j < toRemove.length; j++) { - _rdrawn.remove(toRemove[j]); - _rskipped.remove(toRemove[j]); - } - } - } + behavior.off = function(selection$$1) { + select(window) + .on('keydown.select', null) + .on('keyup.select', null) + .on('contextmenu.select-window', null) + .on('mouseup.select', null, true); - // Loop through all the entities to do some preprocessing - for (i = 0; i < entities.length; i++) { - entity = entities[i]; - geometry = entity.geometry(graph); - - // Insert collision boxes around interesting points/vertices - if (geometry === 'point' || (geometry === 'vertex' && isInterestingVertex(entity))) { - var hasDirections = entity.directions(graph, projection$$1).length; - var markerPadding; - - if (!wireframe && geometry === 'point' && !(zoom >= 18 && hasDirections)) { - renderNodeAs[entity.id] = 'point'; - markerPadding = 20; // extra y for marker height - } else { - renderNodeAs[entity.id] = 'vertex'; - markerPadding = 0; - } - - var coord = projection$$1(entity.loc); - var nodePadding = 10; - var bbox = { - minX: coord[0] - nodePadding, - minY: coord[1] - nodePadding - markerPadding, - maxX: coord[0] + nodePadding, - maxY: coord[1] + nodePadding - }; - - doInsert(bbox, entity.id + 'P'); - } + selection$$1 + .on('mousedown.select', null) + .on('mousemove.select', null) + .on('contextmenu.select', null); - // From here on, treat vertices like points - if (geometry === 'vertex') { - geometry = 'point'; - } + context.surface() + .classed('behavior-multiselect', false); + }; - // Determine which entities are label-able - var preset = geometry === 'area' && context.presets().match(entity, graph); - var icon = preset && !blacklisted(preset) && preset.icon; - if (!icon && !utilDisplayName(entity)) - continue; + return behavior; + } - for (k = 0; k < labelStack.length; k++) { - var matchGeom = labelStack[k][0]; - var matchKey = labelStack[k][1]; - var matchVal = labelStack[k][2]; - var hasVal = entity.tags[matchKey]; + function svgAreas$$1(projection, context) { + // Patterns only work in Firefox when set directly on element. + // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632) + var patterns = { + beach: 'beach', + cemetery: 'cemetery', + construction: 'construction', + farm: 'farmland', + farmland: 'farmland', + grave_yard: 'cemetery', + meadow: 'meadow', + military: 'construction', + orchard: 'orchard', + sand: 'beach', + scrub: 'scrub', + wetland: 'wetland', + }; - if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) { - labelable[k].push(entity); - break; - } - } - } + var patternKeys = ['landuse', 'natural', 'amenity']; - var positions = { - point: [], - line: [], - area: [] - }; - var labelled = { - point: [], - line: [], - area: [] - }; + function setPattern(d) { + for (var i = 0; i < patternKeys.length; i++) { + if (d.tags.building && d.tags.building !== 'no') continue; - // Try and find a valid label for labellable entities - for (k = 0; k < labelable.length; k++) { - var fontSize = labelStack[k][3]; - - for (i = 0; i < labelable[k].length; i++) { - entity = labelable[k][i]; - geometry = entity.geometry(graph); - - var getName = (geometry === 'line') ? utilDisplayNameForPath : utilDisplayName; - var name = getName(entity); - var width = name && textWidth(name, fontSize); - var p = null; - - if (geometry === 'point' || geometry === 'vertex') { - // no point or vertex labels in wireframe mode - // no vertex labels at low zooms (vertices have no icons) - if (wireframe) continue; - var renderAs = renderNodeAs[entity.id]; - if (renderAs === 'vertex' && zoom < 17) continue; - - p = getPointLabel(entity, width, fontSize, renderAs); - - } else if (geometry === 'line') { - p = getLineLabel(entity, width, fontSize); - - } else if (geometry === 'area') { - p = getAreaLabel(entity, width, fontSize); - } - - if (p) { - if (geometry === 'vertex') { geometry = 'point'; } // treat vertex like point - p.classes = geometry + ' tag-' + labelStack[k][1]; - positions[geometry].push(p); - labelled[geometry].push(entity); - } - } - } + if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) { + this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")'; + return; + } + } + this.style.fill = this.style.stroke = ''; + } - function isInterestingVertex(entity) { - var selectedIDs = context.selectedIDs(); + function drawTargets(selection, graph, entities, filter) { + var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor '; + var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor '; + var getPath = svgPath(projection).geojson; + var activeID = context.activeID(); - return entity.hasInterestingTags() || - entity.isEndpoint(graph) || - entity.isConnected(graph) || - selectedIDs.indexOf(entity.id) !== -1 || - some(graph.parentWays(entity), function(parent) { - return selectedIDs.indexOf(parent.id) !== -1; - }); - } + // The targets and nopes will be MultiLineString sub-segments of the ways + var data = { targets: [], nopes: [] }; + entities.forEach(function(way) { + var features = svgSegmentWay(way, graph, activeID); + data.targets.push.apply(data.targets, features.passive); + data.nopes.push.apply(data.nopes, features.active); + }); - function getPointLabel(entity, width, height, geometry) { - var y = (geometry === 'point' ? -12 : 0); - var pointOffsets = { - ltr: [15, y, 'start'], - rtl: [-15, y, 'end'] - }; - var coord = projection$$1(entity.loc); - var textPadding = 2; - var offset = pointOffsets[textDirection]; - var p = { - height: height, - width: width, - x: coord[0] + offset[0], - y: coord[1] + offset[1], - textAnchor: offset[2] - }; + // Targets allow hover and vertex snapping + var targetData = data.targets.filter(getPath); + var targets = selection.selectAll('.area.target-allowed') + .filter(function(d) { return filter(d.properties.entity); }) + .data(targetData, function key(d) { return d.id; }); + + // exit + targets.exit() + .remove(); + + // enter/update + targets.enter() + .append('path') + .merge(targets) + .attr('d', getPath) + .attr('class', function(d) { return 'way area target target-allowed ' + targetClass + d.id; }); + + + // NOPE + var nopeData = data.nopes.filter(getPath); + var nopes = selection.selectAll('.area.target-nope') + .filter(function(d) { return filter(d.properties.entity); }) + .data(nopeData, function key(d) { return d.id; }); + + // exit + nopes.exit() + .remove(); + + // enter/update + nopes.enter() + .append('path') + .merge(nopes) + .attr('d', getPath) + .attr('class', function(d) { return 'way area target target-nope ' + nopeClass + d.id; }); + } - // insert a collision box for the text label.. - var bbox; - if (textDirection === 'rtl') { - bbox = { - minX: p.x - width - textPadding, - minY: p.y - (height / 2) - textPadding, - maxX: p.x + textPadding, - maxY: p.y + (height / 2) + textPadding - }; - } else { - bbox = { - minX: p.x - textPadding, - minY: p.y - (height / 2) - textPadding, - maxX: p.x + width + textPadding, - maxY: p.y + (height / 2) + textPadding - }; - } - if (tryInsert([bbox], entity.id, true)) { - return p; - } - } + function drawAreas(selection, graph, entities, filter) { + var path = svgPath(projection, graph, true), + areas = {}, + multipolygon; + + for (var i = 0; i < entities.length; i++) { + var entity = entities[i]; + if (entity.geometry(graph) !== 'area') continue; + + multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph); + if (multipolygon) { + areas[multipolygon.id] = { + entity: multipolygon.mergeTags(entity.tags), + area: Math.abs(entity.area(graph)) + }; + } else if (!areas[entity.id]) { + areas[entity.id] = { + entity: entity, + area: Math.abs(entity.area(graph)) + }; + } + } + areas = values$1(areas).filter(function hasPath(a) { return path(a.entity); }); + areas.sort(function areaSort(a, b) { return b.area - a.area; }); + areas = map$3(areas, 'entity'); - function getLineLabel(entity, width, height) { - var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(); - var points = map$3(graph.childNodes(entity), 'loc').map(projection$$1); - var length = geoPathLength(points); - - if (length < width + 20) return; - - // todo: properly clip points to viewport - - // % along the line to attempt to place the label - var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70, - 25, 75, 20, 80, 15, 95, 10, 90, 5, 95]; - var padding = 3; - - for (var i = 0; i < lineOffsets.length; i++) { - var offset = lineOffsets[i]; - var middle = offset / 100 * length; - var start = middle - width / 2; - - if (start < 0 || start + width > length) continue; - - // generate subpath and ignore paths that are invalid or don't cross viewport. - var sub = subpath(points, start, start + width); - if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) { - continue; - } - - var isReverse = reverse(sub); - if (isReverse) { - sub = sub.reverse(); - } - - var bboxes = []; - var boxsize = (height + 2) / 2; - - for (var j = 0; j < sub.length - 1; j++) { - var a = sub[j]; - var b = sub[j + 1]; - - // split up the text into small collision boxes - var num = Math.max(1, Math.floor(geoVecLength(a, b) / boxsize / 2)); - - for (var box = 0; box < num; box++) { - var p = geoVecInterp(a, b, box / num); - var x0 = p[0] - boxsize - padding; - var y0 = p[1] - boxsize - padding; - var x1 = p[0] + boxsize + padding; - var y1 = p[1] + boxsize + padding; - - bboxes.push({ - minX: Math.min(x0, x1), - minY: Math.min(y0, y1), - maxX: Math.max(x0, x1), - maxY: Math.max(y0, y1) - }); - } - } - - if (tryInsert(bboxes, entity.id, false)) { // accept this one - return { - 'font-size': height + 2, - lineString: lineString(sub), - startOffset: offset + '%' - }; - } - } + var strokes = areas.filter(function(area) { + return area.type === 'way'; + }); - function reverse(p) { - var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]); - return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2); - } + var data = { + clip: areas, + shadow: strokes, + stroke: strokes, + fill: areas + }; - function lineString(points) { - return 'M' + points.join('L'); - } + var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath') + .filter(filter) + .data(data.clip, osmEntity$$1.key); - function subpath(points, from, to) { - var sofar = 0; - var start, end, i0, i1; - - for (var i = 0; i < points.length - 1; i++) { - var a = points[i]; - var b = points[i + 1]; - var current = geoVecLength(a, b); - var portion; - if (!start && sofar + current >= from) { - portion = (from - sofar) / current; - start = [ - a[0] + portion * (b[0] - a[0]), - a[1] + portion * (b[1] - a[1]) - ]; - i0 = i + 1; - } - if (!end && sofar + current >= to) { - portion = (to - sofar) / current; - end = [ - a[0] + portion * (b[0] - a[0]), - a[1] + portion * (b[1] - a[1]) - ]; - i1 = i + 1; - } - sofar += current; - } - - var result = points.slice(i0, i1); - result.unshift(start); - result.push(end); - return result; - } - } + clipPaths.exit() + .remove(); + var clipPathsEnter = clipPaths.enter() + .append('clipPath') + .attr('class', 'clipPath') + .attr('id', function(entity) { return entity.id + '-clippath'; }); - function getAreaLabel(entity, width, height) { - var centroid = path.centroid(entity.asGeoJSON(graph, true)); - var extent = entity.extent(graph); - var areaWidth = projection$$1(extent[1])[0] - projection$$1(extent[0])[0]; - - if (isNaN(centroid[0]) || areaWidth < 20) return; - - var preset = context.presets().match(entity, context.graph()); - var picon = preset && preset.icon; - var iconSize = 17; - var padding = 2; - var p = {}; - - if (picon) { // icon and label.. - if (addIcon()) { - addLabel(iconSize + padding); - return p; - } - } else { // label only.. - if (addLabel(0)) { - return p; - } - } + clipPathsEnter + .append('path'); + clipPaths.merge(clipPathsEnter) + .selectAll('path') + .attr('d', path); - function addIcon() { - var iconX = centroid[0] - (iconSize / 2); - var iconY = centroid[1] - (iconSize / 2); - var bbox = { - minX: iconX, - minY: iconY, - maxX: iconX + iconSize, - maxY: iconY + iconSize - }; - - if (tryInsert([bbox], entity.id + 'I', true)) { - p.transform = 'translate(' + iconX + ',' + iconY + ')'; - return true; - } - return false; - } - function addLabel(yOffset) { - if (width && areaWidth >= width + 20) { - var labelX = centroid[0]; - var labelY = centroid[1] + yOffset; - var bbox = { - minX: labelX - (width / 2) - padding, - minY: labelY - (height / 2) - padding, - maxX: labelX + (width / 2) + padding, - maxY: labelY + (height / 2) + padding - }; - - if (tryInsert([bbox], entity.id, true)) { - p.x = labelX; - p.y = labelY; - p.textAnchor = 'middle'; - p.height = height; - return true; - } - } - return false; - } - } + var layer = selection.selectAll('.layer-areas .layer-areas-areas'); + var areagroup = layer + .selectAll('g.areagroup') + .data(['fill', 'shadow', 'stroke']); - // force insert a singular bounding box - // singular box only, no array, id better be unique - function doInsert(bbox, id) { - bbox.id = id; + areagroup = areagroup.enter() + .append('g') + .attr('class', function(d) { return 'areagroup area-' + d; }) + .merge(areagroup); - var oldbox = _entitybboxes[id]; - if (oldbox) { - _rdrawn.remove(oldbox); - } - _entitybboxes[id] = bbox; - _rdrawn.insert(bbox); - } + var paths = areagroup + .selectAll('path') + .filter(filter) + .data(function(layer) { return data[layer]; }, osmEntity$$1.key); + paths.exit() + .remove(); - function tryInsert(bboxes, id, saveSkipped) { - var skipped = false; + var fills = selection.selectAll('.area-fill path.area').nodes(); - for (var i = 0; i < bboxes.length; i++) { - var bbox = bboxes[i]; - bbox.id = id; + var bisect = bisector(function(node) { + return -node.__data__.area(graph); + }).left; - // Check that label is visible - if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) { - skipped = true; - break; - } - if (_rdrawn.collides(bbox)) { - skipped = true; - break; - } - } + function sortedByArea(entity) { + if (this._parent.__data__ === 'fill') { + return fills[bisect(fills, -entity.area(graph))]; + } + } - _entitybboxes[id] = bboxes; + paths = paths.enter() + .insert('path', sortedByArea) + .merge(paths) + .each(function(entity) { + var layer = this.parentNode.__data__; - if (skipped) { - if (saveSkipped) { - _rskipped.load(bboxes); - } - } else { - _rdrawn.load(bboxes); - } + this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id); - return !skipped; - } + if (layer === 'fill') { + this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)'); + setPattern.apply(this, arguments); + } + }) + .call(svgTagClasses()) + .attr('d', path); - var layer = selection.selectAll('.layer-labels'); - var halo = layer.selectAll('.layer-labels-halo'); - var label = layer.selectAll('.layer-labels-label'); - var debug = layer.selectAll('.layer-labels-debug'); + // touch targets + selection.selectAll('.layer-areas .layer-areas-targets') + .call(drawTargets, graph, data.stroke, filter); + } - // points - drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point); - drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point); + return drawAreas; + } - // lines - drawLinePaths(halo, labelled.line, filter, '', positions.line); - drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line); - drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line); + function svgDebug$$1(projection, context) { - // areas - drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area); - drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area); - drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area); - drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area); + function multipolygons(imagery) { + return imagery.map(function(data$$1) { + return { + type: 'MultiPolygon', + coordinates: [ data$$1.polygon ] + }; + }); + } - // debug - drawCollisionBoxes(debug, _rskipped, 'debug-skipped'); - drawCollisionBoxes(debug, _rdrawn, 'debug-drawn'); + function drawDebug(selection$$1) { + var showsTile = context.getDebug('tile'); + var showsCollision = context.getDebug('collision'); + var showsImagery = context.getDebug('imagery'); + var showsCommunity = context.getDebug('community'); + var showsImperial = context.getDebug('imperial'); + var showsDriveLeft = context.getDebug('driveLeft'); + var showsTouchTargets = context.getDebug('target'); + + var debugData = []; + if (showsTile) { + debugData.push({ class: 'red', label: 'tile' }); + } + if (showsCollision) { + debugData.push({ class: 'yellow', label: 'collision' }); + } + if (showsImagery) { + debugData.push({ class: 'orange', label: 'imagery' }); + } + if (showsCommunity) { + debugData.push({ class: 'blue', label: 'community' }); + } + if (showsImperial) { + debugData.push({ class: 'cyan', label: 'imperial' }); + } + if (showsDriveLeft) { + debugData.push({ class: 'green', label: 'driveLeft' }); + } + if (showsTouchTargets) { + debugData.push({ class: 'pink', label: 'touchTargets' }); + } - layer.call(filterLabels); - } + var legend = select('#content') + .selectAll('.debug-legend') + .data(debugData.length ? [0] : []); - function filterLabels(selection) { - var layers = selection - .selectAll('.layer-labels-label, .layer-labels-halo'); + legend.exit() + .remove(); - layers.selectAll('.nolabel') - .classed('nolabel', false); + legend = legend.enter() + .append('div') + .attr('class', 'fillD debug-legend') + .merge(legend); - var mouse = context.mouse(); - var graph = context.graph(); - var selectedIDs = context.selectedIDs(); - var ids = []; - var pad, bbox; - // hide labels near the mouse - if (mouse) { - pad = 20; - bbox = { minX: mouse[0] - pad, minY: mouse[1] - pad, maxX: mouse[0] + pad, maxY: mouse[1] + pad }; - ids.push.apply(ids, map$3(_rdrawn.search(bbox), 'id')); - } + var legendItems = legend.selectAll('.debug-legend-item') + .data(debugData, function(d) { return d.label; }); - // hide labels on selected nodes (they look weird when dragging / haloed) - for (var i = 0; i < selectedIDs.length; i++) { - var entity = graph.hasEntity(selectedIDs[i]); - if (entity && entity.type === 'node') { - ids.push(selectedIDs[i]); - } - } + legendItems.exit() + .remove(); - layers.selectAll(utilEntitySelector(ids)) - .classed('nolabel', true); - - - // draw the mouse bbox if debugging is on.. - var debug = selection.selectAll('.layer-labels-debug'); - var gj = []; - if (context.getDebug('collision')) { - gj = bbox ? [{ - type: 'Polygon', - coordinates: [[ - [bbox.minX, bbox.minY], - [bbox.maxX, bbox.minY], - [bbox.maxX, bbox.maxY], - [bbox.minX, bbox.maxY], - [bbox.minX, bbox.minY] - ]] - }] : []; - } + legendItems.enter() + .append('span') + .attr('class', function(d) { return 'debug-legend-item ' + d.class; }) + .text(function(d) { return d.label; }); - var box = debug.selectAll('.debug-mouse') - .data(gj); - // exit - box.exit() - .remove(); + var layer = selection$$1.selectAll('.layer-debug') + .data(showsImagery || showsCommunity || showsImperial || showsDriveLeft ? [0] : []); - // enter/update - box.enter() - .append('path') - .attr('class', 'debug debug-mouse yellow') - .merge(box) - .attr('d', d3_geoPath()); - } + layer.exit() + .remove(); + layer = layer.enter() + .append('g') + .attr('class', 'layer-debug') + .merge(layer); - var throttleFilterLabels = throttle(utilCallWhenIdle(filterLabels), 100); + var extent = context.map().extent(); + var dataImagery = data.imagery || []; + var availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) { + if (!source.polygon) return false; + return source.polygon.some(function(polygon) { + return geoPolygonIntersectsPolygon(polygon, extent, true); + }); + })); - drawLabels.observe = function(selection) { - var listener = function() { throttleFilterLabels(selection); }; - selection.on('mousemove.hidelabels', listener); - context.on('enter.hidelabels', listener); - }; + var imagery = layer.selectAll('path.debug-imagery') + .data(showsImagery ? availableImagery : []); + imagery.exit() + .remove(); - drawLabels.off = function(selection) { - throttleFilterLabels.cancel(); - selection.on('mousemove.hidelabels', null); - context.on('enter.hidelabels', null); - }; + imagery.enter() + .append('path') + .attr('class', 'debug-imagery debug orange'); - return drawLabels; -} + var community = layer.selectAll('path.debug-community') + .data(showsCommunity ? values$1(data.community.features) : []); -function svgMapillaryImages$$1(projection, context, dispatch) { - var throttledRedraw = throttle(function () { dispatch.call('change'); }, 1000); - var minZoom = 12; - var minMarkerZoom = 16; - var minViewfieldZoom = 18; - var layer = d3_select(null); - var _mapillary; + community.exit() + .remove(); + community.enter() + .append('path') + .attr('class', 'debug-community debug blue'); - function init() { - if (svgMapillaryImages$$1.initialized) return; // run once - svgMapillaryImages$$1.enabled = false; - svgMapillaryImages$$1.initialized = true; - } + var imperial = layer + .selectAll('path.debug-imperial') + .data(showsImperial ? [dataImperial] : []); - function getService() { - if (services.mapillary && !_mapillary) { - _mapillary = services.mapillary; - _mapillary.event.on('loadedImages', throttledRedraw); - } else if (!services.mapillary && _mapillary) { - _mapillary = null; - } + imperial.exit() + .remove(); - return _mapillary; - } + imperial.enter() + .append('path') + .attr('class', 'debug-imperial debug cyan'); - function showLayer() { - var service = getService(); - if (!service) return; + var driveLeft = layer + .selectAll('path.debug-drive-left') + .data(showsDriveLeft ? [dataDriveLeft] : []); - service.loadViewer(context); - editOn(); + driveLeft.exit() + .remove(); - layer - .style('opacity', 0) - .transition() - .duration(250) - .style('opacity', 1) - .on('end', function () { dispatch.call('change'); }); - } + driveLeft.enter() + .append('path') + .attr('class', 'debug-drive-left debug green'); - function hideLayer() { - var service = getService(); - if (service) { - service.hideViewer(); - } + // update + layer.selectAll('path') + .attr('d', svgPath(projection).geojson); + } - throttledRedraw.cancel(); - layer - .transition() - .duration(250) - .style('opacity', 0) - .on('end', editOff); - } + // This looks strange because `enabled` methods on other layers are + // chainable getter/setters, and this one is just a getter. + drawDebug.enabled = function() { + if (!arguments.length) { + return context.getDebug('tile') || + context.getDebug('collision') || + context.getDebug('imagery') || + context.getDebug('imperial') || + context.getDebug('driveLeft') || + context.getDebug('target'); + } else { + return this; + } + }; - function editOn() { - layer.style('display', 'block'); - } + return drawDebug; + } + /* + A standalone SVG element that contains only a `defs` sub-element. To be + used once globally, since defs IDs must be unique within a document. + */ + function svgDefs(context) { + + function SVGSpriteDefinition(id, href) { + return function(defs) { + request(href) + .mimeType('image/svg+xml') + .response(function(xhr) { return xhr.responseXML; }) + .get(function(err, svg) { + if (err) return; + defs.node().appendChild( + select(svg.documentElement).attr('id', id).node() + ); + }); + }; + } - function editOff() { - layer.selectAll('.viewfield-group').remove(); - layer.style('display', 'none'); - } + return function drawDefs(selection$$1) { + var defs = selection$$1.append('defs'); + + // markers + defs + .append('marker') + .attr('id', 'oneway-marker') + .attr('viewBox', '0 0 10 5') + .attr('refX', 2.5) + .attr('refY', 2.5) + .attr('markerWidth', 2) + .attr('markerHeight', 2) + .attr('markerUnits', 'strokeWidth') + .attr('orient', 'auto') + .append('path') + .attr('class', 'oneway-marker-path') + .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') + .attr('stroke', 'none') + .attr('fill', '#000') + .attr('opacity', '0.75'); + + defs + .append('marker') + .attr('id', 'viewfield-marker') + .attr('viewBox', '0 0 16 16') + .attr('refX', 8) + .attr('refY', 16) + .attr('markerWidth', 4) + .attr('markerHeight', 4) + .attr('markerUnits', 'strokeWidth') + .attr('orient', 'auto') + .append('path') + .attr('class', 'viewfield-marker-path') + .attr('d', 'M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z') + .attr('fill', '#333') + .attr('fill-opacity', '0.75') + .attr('stroke', '#fff') + .attr('stroke-width', '0.5px') + .attr('stroke-opacity', '0.75'); + + defs + .append('marker') + .attr('id', 'viewfield-marker-wireframe') + .attr('viewBox', '0 0 16 16') + .attr('refX', 8) + .attr('refY', 16) + .attr('markerWidth', 4) + .attr('markerHeight', 4) + .attr('markerUnits', 'strokeWidth') + .attr('orient', 'auto') + .append('path') + .attr('class', 'viewfield-marker-path') + .attr('d', 'M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z') + .attr('fill', 'none') + .attr('stroke', '#fff') + .attr('stroke-width', '0.5px') + .attr('stroke-opacity', '0.75'); + + // patterns + var patterns = defs.selectAll('pattern') + .data([ + // pattern name, pattern image name + ['wetland', 'wetland'], + ['construction', 'construction'], + ['cemetery', 'cemetery'], + ['orchard', 'orchard'], + ['farmland', 'farmland'], + ['beach', 'dots'], + ['scrub', 'dots'], + ['meadow', 'dots'] + ]) + .enter() + .append('pattern') + .attr('id', function (d) { return 'pattern-' + d[0]; }) + .attr('width', 32) + .attr('height', 32) + .attr('patternUnits', 'userSpaceOnUse'); + + patterns + .append('rect') + .attr('x', 0) + .attr('y', 0) + .attr('width', 32) + .attr('height', 32) + .attr('class', function (d) { return 'pattern-color-' + d[0]; }); + + patterns + .append('image') + .attr('x', 0) + .attr('y', 0) + .attr('width', 32) + .attr('height', 32) + .attr('xlink:href', function (d) { + return context.imagePath('pattern/' + d[1] + '.png'); + }); + + // clip paths + defs.selectAll('clipPath') + .data([12, 18, 20, 32, 45]) + .enter() + .append('clipPath') + .attr('id', function (d) { return 'clip-square-' + d; }) + .append('rect') + .attr('x', 0) + .attr('y', 0) + .attr('width', function (d) { return d; }) + .attr('height', function (d) { return d; }); + + // symbol spritesheets + defs + .call(SVGSpriteDefinition('iD-sprite', context.imagePath('iD-sprite.svg'))) + .call(SVGSpriteDefinition('maki-sprite', context.imagePath('maki-sprite.svg'))) + .call(SVGSpriteDefinition('community-sprite', context.imagePath('community-sprite.svg'))); + }; + } - function click(d) { - var service = getService(); - if (!service) return; + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } - service - .selectImage(d) - .updateViewer(d.key, context) - .showViewer(); + //[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] + //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] + //[5] Name ::= NameStartChar (NameChar)* + 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 + var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]"); + var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$'); + //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/ + //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(',') + + //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE + //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE + var S_TAG = 0;//tag name offerring + var S_ATTR = 1;//attr name offerring + var S_ATTR_SPACE=2;//attr name end and space offer + var S_EQ = 3;//=space? + var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only) + var S_ATTR_END = 5;//attr value end and no space(quot end) + var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer) + var S_TAG_CLOSE = 7;//closed el + + function XMLReader(){ + + } - context.map().centerEase(d.loc); - } + XMLReader.prototype = { + parse:function(source,defaultNSMap,entityMap){ + var domBuilder = this.domBuilder; + domBuilder.startDocument(); + _copy(defaultNSMap ,defaultNSMap = {}); + parse$1(source,defaultNSMap,entityMap, + domBuilder,this.errorHandler); + domBuilder.endDocument(); + } + }; + function parse$1(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){ + function fixedFromCharCode(code) { + // String.prototype.fromCharCode does not supports + // > 2 bytes unicode chars directly + if (code > 0xffff) { + code -= 0x10000; + var surrogate1 = 0xd800 + (code >> 10) + , surrogate2 = 0xdc00 + (code & 0x3ff); + + return String.fromCharCode(surrogate1, surrogate2); + } else { + return String.fromCharCode(code); + } + } + function entityReplacer(a){ + var k = a.slice(1,-1); + if(k in entityMap){ + return entityMap[k]; + }else if(k.charAt(0) === '#'){ + return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x'))) + }else{ + errorHandler.error('entity not found:'+a); + return a; + } + } + function appendText(end){//has some bugs + if(end>start){ + var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer); + locator&&position(start); + domBuilder.characters(xt,0,end-start); + start = end; + } + } + function position(p,m){ + while(p>=lineEnd && (m = linePattern.exec(source))){ + lineStart = m.index; + lineEnd = lineStart + m[0].length; + locator.lineNumber++; + //console.log('line++:',locator,startPos,endPos) + } + locator.columnNumber = p-lineStart+1; + } + var lineStart = 0; + var lineEnd = 0; + var linePattern = /.*(?:\r\n?|\n)|.*$/g; + var locator = domBuilder.locator; + + var parseStack = [{currentNSMap:defaultNSMapCopy}]; + var closeMap = {}; + var start = 0; + while(true){ + try{ + var tagStart = source.indexOf('<',start); + if(tagStart<0){ + if(!source.substr(start).match(/^\s*$/)){ + var doc = domBuilder.doc; + var text = doc.createTextNode(source.substr(start)); + doc.appendChild(text); + domBuilder.currentElement = text; + } + return; + } + if(tagStart>start){ + appendText(tagStart); + } + switch(source.charAt(tagStart+1)){ + case '/': + var end = source.indexOf('>',tagStart+3); + var tagName = source.substring(tagStart+2,end); + var config = parseStack.pop(); + if(end<0){ + + tagName = source.substring(tagStart+2).replace(/[\s<].*/,''); + //console.error('#@@@@@@'+tagName) + errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName); + end = tagStart+1+tagName.length; + }else if(tagName.match(/\s + locator&&position(tagStart); + end = parseInstruction(source,tagStart,domBuilder); + break; + case '!':// start){ + start = end; + }else{ + //TODO: 这里有可能sax回退,有位置错误风险 + appendText(Math.max(tagStart,start)+1); + } + } + } + function copyLocator(f,t){ + t.lineNumber = f.lineNumber; + t.columnNumber = f.columnNumber; + return t; + } + /** + * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack); + * @return end of the elementStartPart(end of elementEndPart for selfClosed el) + */ + function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){ + var attrName; + var value; + var p = ++start; + var s = S_TAG;//status + while(true){ + var c = source.charAt(p); + switch(c){ + case '=': + if(s === S_ATTR){//attrName + attrName = source.slice(start,p); + s = S_EQ; + }else if(s === S_ATTR_SPACE){ + s = S_EQ; + }else{ + //fatalError: equal must after attrName or space after attrName + throw new Error('attribute equal must after attrName'); + } + break; + case '\'': + case '"': + if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE + ){//equal + if(s === S_ATTR){ + errorHandler.warning('attribute value must after "="'); + attrName = source.slice(start,p); + } + start = p+1; + p = source.indexOf(c,start); + if(p>0){ + value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); + el.add(attrName,value,start-1); + s = S_ATTR_END; + }else{ + //fatalError: no end quot match + throw new Error('attribute value no end \''+c+'\' match'); + } + }else if(s == S_ATTR_NOQUOT_VALUE){ + value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); + //console.log(attrName,value,start,p) + el.add(attrName,value,start); + //console.dir(el) + errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!'); + start = p+1; + s = S_ATTR_END; + }else{ + //fatalError: no equal before + throw new Error('attribute value must after "="'); + } + break; + case '/': + switch(s){ + case S_TAG: + el.setTagName(source.slice(start,p)); + case S_ATTR_END: + case S_TAG_SPACE: + case S_TAG_CLOSE: + s =S_TAG_CLOSE; + el.closed = true; + case S_ATTR_NOQUOT_VALUE: + case S_ATTR: + case S_ATTR_SPACE: + break; + //case S_EQ: + default: + throw new Error("attribute invalid close char('/')") + } + break; + case ''://end document + //throw new Error('unexpected end of input') + errorHandler.error('unexpected end of input'); + if(s == S_TAG){ + el.setTagName(source.slice(start,p)); + } + return p; + case '>': + switch(s){ + case S_TAG: + el.setTagName(source.slice(start,p)); + case S_ATTR_END: + case S_TAG_SPACE: + case S_TAG_CLOSE: + break;//normal + case S_ATTR_NOQUOT_VALUE://Compatible state + case S_ATTR: + value = source.slice(start,p); + if(value.slice(-1) === '/'){ + el.closed = true; + value = value.slice(0,-1); + } + case S_ATTR_SPACE: + if(s === S_ATTR_SPACE){ + value = attrName; + } + if(s == S_ATTR_NOQUOT_VALUE){ + errorHandler.warning('attribute "'+value+'" missed quot(")!!'); + el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start); + }else{ + if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){ + errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!'); + } + el.add(value,value,start); + } + break; + case S_EQ: + throw new Error('attribute value missed!!'); + } + // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName)) + return p; + /*xml space '\x20' | #x9 | #xD | #xA; */ + case '\u0080': + c = ' '; + default: + if(c<= ' '){//space + switch(s){ + case S_TAG: + el.setTagName(source.slice(start,p));//tagName + s = S_TAG_SPACE; + break; + case S_ATTR: + attrName = source.slice(start,p); + s = S_ATTR_SPACE; + break; + case S_ATTR_NOQUOT_VALUE: + var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); + errorHandler.warning('attribute "'+value+'" missed quot(")!!'); + el.add(attrName,value,start); + case S_ATTR_END: + s = S_TAG_SPACE; + break; + //case S_TAG_SPACE: + //case S_EQ: + //case S_ATTR_SPACE: + // void();break; + //case S_TAG_CLOSE: + //ignore warning + } + }else{//not space + //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE + //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE + switch(s){ + //case S_TAG:void();break; + //case S_ATTR:void();break; + //case S_ATTR_NOQUOT_VALUE:void();break; + case S_ATTR_SPACE: + var tagName = el.tagName; + if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){ + errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!'); + } + el.add(attrName,attrName,start); + start = p; + s = S_ATTR; + break; + case S_ATTR_END: + errorHandler.warning('attribute space is required"'+attrName+'"!!'); + case S_TAG_SPACE: + s = S_ATTR; + start = p; + break; + case S_EQ: + s = S_ATTR_NOQUOT_VALUE; + start = p; + break; + case S_TAG_CLOSE: + throw new Error("elements closed character '/' and '>' must be connected to"); + } + } + }//end outer switch + //console.log('p++',p) + p++; + } + } + /** + * @return true if has new namespace define + */ + function appendElement(el,domBuilder,currentNSMap){ + var tagName = el.tagName; + var localNSMap = null; + //var currentNSMap = parseStack[parseStack.length-1].currentNSMap; + var i = el.length; + while(i--){ + var a = el[i]; + var qName = a.qName; + var value = a.value; + var nsp = qName.indexOf(':'); + if(nsp>0){ + var prefix = a.prefix = qName.slice(0,nsp); + var localName = qName.slice(nsp+1); + var nsPrefix = prefix === 'xmlns' && localName; + }else{ + localName = qName; + prefix = null; + nsPrefix = qName === 'xmlns' && ''; + } + //can not set prefix,because prefix !== '' + a.localName = localName ; + //prefix == null for no ns prefix attribute + if(nsPrefix !== false){//hack!! + if(localNSMap == null){ + localNSMap = {}; + //console.log(currentNSMap,0) + _copy(currentNSMap,currentNSMap={}); + //console.log(currentNSMap,1) + } + currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value; + a.uri = 'http://www.w3.org/2000/xmlns/'; + domBuilder.startPrefixMapping(nsPrefix, value); + } + } + var i = el.length; + while(i--){ + a = el[i]; + var prefix = a.prefix; + if(prefix){//no prefix attribute has no namespace + if(prefix === 'xml'){ + a.uri = 'http://www.w3.org/XML/1998/namespace'; + }if(prefix !== 'xmlns'){ + a.uri = currentNSMap[prefix || '']; + + //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)} + } + } + } + var nsp = tagName.indexOf(':'); + if(nsp>0){ + prefix = el.prefix = tagName.slice(0,nsp); + localName = el.localName = tagName.slice(nsp+1); + }else{ + prefix = null;//important!! + localName = el.localName = tagName; + } + //no prefix element has default namespace + var ns = el.uri = currentNSMap[prefix || '']; + domBuilder.startElement(ns,localName,tagName,el); + //endPrefixMapping and startPrefixMapping have not any help for dom builder + //localNSMap = null + if(el.closed){ + domBuilder.endElement(ns,localName,tagName); + if(localNSMap){ + for(prefix in localNSMap){ + domBuilder.endPrefixMapping(prefix); + } + } + }else{ + el.currentNSMap = currentNSMap; + el.localNSMap = localNSMap; + //parseStack.push(el); + return true; + } + } + function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){ + if(/^(?:script|textarea)$/i.test(tagName)){ + var elEndStart = source.indexOf('',elStartEnd); + var text = source.substring(elStartEnd+1,elEndStart); + if(/[&<]/.test(text)){ + if(/^script$/i.test(tagName)){ + //if(!/\]\]>/.test(text)){ + //lexHandler.startCDATA(); + domBuilder.characters(text,0,text.length); + //lexHandler.endCDATA(); + return elEndStart; + //} + }//}else{//text area + text = text.replace(/&#?\w+;/g,entityReplacer); + domBuilder.characters(text,0,text.length); + return elEndStart; + //} + + } + } + return elStartEnd+1; + } + function fixSelfClosed(source,elStartEnd,tagName,closeMap){ + //if(tagName in closeMap){ + var pos = closeMap[tagName]; + if(pos == null){ + //console.log(tagName) + pos = source.lastIndexOf(''); + if(pos',start+4); + //append comment source.substring(4,end)//"); + case DOCUMENT_TYPE_NODE: + var pubid = node.publicId; + var sysid = node.systemId; + buf.push(''); + }else if(sysid && sysid!='.'){ + buf.push(' SYSTEM "',sysid,'">'); + }else{ + var sub = node.internalSubset; + if(sub){ + buf.push(" [",sub,"]"); + } + buf.push(">"); + } + return; + case PROCESSING_INSTRUCTION_NODE: + return buf.push( ""); + case ENTITY_REFERENCE_NODE: + return buf.push( '&',node.nodeName,';'); + //case ENTITY_NODE: + //case NOTATION_NODE: + default: + buf.push('??',node.nodeName); + } + } + function importNode(doc,node,deep){ + var node2; + switch (node.nodeType) { + case ELEMENT_NODE: + node2 = node.cloneNode(false); + node2.ownerDocument = doc; + //var attrs = node2.attributes; + //var len = attrs.length; + //for(var i=0;i','amp':'&','quot':'"','apos':"'"}; + if(locator){ + domBuilder.setDocumentLocator(locator); + } + + sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator); + sax$$1.domBuilder = options.domBuilder || domBuilder; + if(/\/x?html?$/.test(mimeType)){ + entityMap.nbsp = '\xa0'; + entityMap.copy = '\xa9'; + defaultNSMap['']= 'http://www.w3.org/1999/xhtml'; + } + defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace'; + if(source){ + sax$$1.parse(source,defaultNSMap,entityMap); + }else{ + sax$$1.errorHandler.error("invalid doc source"); + } + return domBuilder.doc; + }; + function buildErrorHandler(errorImpl,domBuilder,locator){ + if(!errorImpl){ + if(domBuilder instanceof DOMHandler){ + return domBuilder; + } + errorImpl = domBuilder ; + } + var errorHandler = {}; + var isCallback = errorImpl instanceof Function; + locator = locator||{}; + function build(key){ + var fn = errorImpl[key]; + if(!fn && isCallback){ + fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl; + } + errorHandler[key] = fn && function(msg){ + fn('[xmldom '+key+']\t'+msg+_locator(locator)); + }||function(){}; + } + build('warning'); + build('error'); + build('fatalError'); + return errorHandler; + } + //console.log('#\n\n\n\n\n\n\n####') + /** + * +ContentHandler+ErrorHandler + * +LexicalHandler+EntityResolver2 + * -DeclHandler-DTDHandler + * + * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler + * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2 + * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html + */ + function DOMHandler() { + this.cdata = false; + } + function position(locator,node){ + node.lineNumber = locator.lineNumber; + node.columnNumber = locator.columnNumber; + } + /** + * @see org.xml.sax.ContentHandler#startDocument + * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html + */ + DOMHandler.prototype = { + startDocument : function() { + this.doc = new DOMImplementation().createDocument(null, null, null); + if (this.locator) { + this.doc.documentURI = this.locator.systemId; + } + }, + startElement:function(namespaceURI, localName, qName, attrs) { + var doc = this.doc; + var el = doc.createElementNS(namespaceURI, qName||localName); + var len = attrs.length; + appendElement(this, el); + this.currentElement = el; + + this.locator && position(this.locator,el); + for (var i = 0 ; i < len; i++) { + var namespaceURI = attrs.getURI(i); + var value = attrs.getValue(i); + var qName = attrs.getQName(i); + var attr = doc.createAttributeNS(namespaceURI, qName); + this.locator &&position(attrs.getLocator(i),attr); + attr.value = attr.nodeValue = value; + el.setAttributeNode(attr); + } + }, + endElement:function(namespaceURI, localName, qName) { + var current = this.currentElement; + var tagName = current.tagName; + this.currentElement = current.parentNode; + }, + startPrefixMapping:function(prefix, uri) { + }, + endPrefixMapping:function(prefix) { + }, + processingInstruction:function(target, data) { + var ins = this.doc.createProcessingInstruction(target, data); + this.locator && position(this.locator,ins); + appendElement(this, ins); + }, + ignorableWhitespace:function(ch, start, length) { + }, + characters:function(chars, start, length) { + chars = _toString.apply(this,arguments); + //console.log(chars) + if(chars){ + if (this.cdata) { + var charNode = this.doc.createCDATASection(chars); + } else { + var charNode = this.doc.createTextNode(chars); + } + if(this.currentElement){ + this.currentElement.appendChild(charNode); + }else if(/^\s*$/.test(chars)){ + this.doc.appendChild(charNode); + //process xml + } + this.locator && position(this.locator,charNode); + } + }, + skippedEntity:function(name) { + }, + endDocument:function() { + this.doc.normalize(); + }, + setDocumentLocator:function (locator) { + if(this.locator = locator){// && !('lineNumber' in locator)){ + locator.lineNumber = 0; + } + }, + //LexicalHandler + comment:function(chars, start, length) { + chars = _toString.apply(this,arguments); + var comm = this.doc.createComment(chars); + this.locator && position(this.locator,comm); + appendElement(this, comm); + }, + + startCDATA:function() { + //used in characters() methods + this.cdata = true; + }, + endCDATA:function() { + this.cdata = false; + }, + + startDTD:function(name, publicId, systemId) { + var impl = this.doc.implementation; + if (impl && impl.createDocumentType) { + var dt = impl.createDocumentType(name, publicId, systemId); + this.locator && position(this.locator,dt); + appendElement(this, dt); + } + }, + /** + * @see org.xml.sax.ErrorHandler + * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html + */ + warning:function(error) { + console.warn('[xmldom warning]\t'+error,_locator(this.locator)); + }, + error:function(error) { + console.error('[xmldom error]\t'+error,_locator(this.locator)); + }, + fatalError:function(error) { + console.error('[xmldom fatalError]\t'+error,_locator(this.locator)); + throw error; + } + }; + function _locator(l){ + if(l){ + return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']' + } + } + function _toString(chars,start,length){ + if(typeof chars == 'string'){ + return chars.substr(start,length) + }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") + if(chars.length >= start+length || start){ + return new java.lang.String(chars,start,length)+''; + } + return chars; + } + } - function update() { - var service = getService(); - var data = (service ? service.signs(projection) : []); - var viewer = d3_select('#photoviewer'); - var selected = viewer.empty() ? undefined : viewer.datum(); - var selectedImageKey = selected && selected.key; + /* + * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html + * used method of org.xml.sax.ext.LexicalHandler: + * #comment(chars, start, length) + * #startCDATA() + * #endCDATA() + * #startDTD(name, publicId, systemId) + * + * + * IGNORED method of org.xml.sax.ext.LexicalHandler: + * #endDTD() + * #startEntity(name) + * #endEntity(name) + * + * + * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html + * IGNORED method of org.xml.sax.ext.DeclHandler + * #attributeDecl(eName, aName, type, mode, value) + * #elementDecl(name, model) + * #externalEntityDecl(name, publicId, systemId) + * #internalEntityDecl(name, value) + * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html + * IGNORED method of org.xml.sax.EntityResolver2 + * #resolveEntity(String name,String publicId,String baseURI,String systemId) + * #resolveEntity(publicId, systemId) + * #getExternalSubset(name, baseURI) + * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html + * IGNORED method of org.xml.sax.DTDHandler + * #notationDecl(name, publicId, systemId) {}; + * #unparsedEntityDecl(name, publicId, systemId, notationName) {}; + */ + "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){ + DOMHandler.prototype[key] = function(){return null}; + }); - var signs = layer.selectAll('.icon-sign') - .data(data, function(d) { return d.key; }); + /* 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 */ + function appendElement (hander,node) { + if (!hander.currentElement) { + hander.doc.appendChild(node); + } else { + hander.currentElement.appendChild(node); + } + }//appendChild and setAttributeNS are preformance key + + //if(typeof require == 'function'){ + var XMLReader = sax.XMLReader; + var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation; + exports.XMLSerializer = dom.XMLSerializer ; + exports.DOMParser = DOMParser; + //} + }); + var domParser_1 = domParser.DOMImplementation; + var domParser_2 = domParser.XMLSerializer; + var domParser_3 = domParser.DOMParser; + + var togeojson = createCommonjsModule(function (module, exports) { + var toGeoJSON = (function() { + + var removeSpace = /\s*/g, + trimSpace = /^\s*|\s*$/g, + splitSpace = /\s+/; + // generate a short, numeric hash of a string + function okhash(x) { + if (!x || !x.length) return 0; + for (var i = 0, h = 0; i < x.length; i++) { + h = ((h << 5) - h) + x.charCodeAt(i) | 0; + } return h; + } + // all Y children of X + function get(x, y) { return x.getElementsByTagName(y); } + function attr(x, y) { return x.getAttribute(y); } + function attrf(x, y) { return parseFloat(attr(x, y)); } + // one Y child of X, if any, otherwise null + function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; } + // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize + function norm(el) { if (el.normalize) { el.normalize(); } return el; } + // cast array x into numbers + function numarray(x) { + for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); } + return o; + } + // get the content of a text node, if any + function nodeVal(x) { + if (x) { norm(x); } + return (x && x.textContent) || ''; + } + // get the contents of multiple text nodes, if present + function getMulti(x, ys) { + var o = {}, n, k; + for (k = 0; k < ys.length; k++) { + n = get1(x, ys[k]); + if (n) o[ys[k]] = nodeVal(n); + } + return o; + } + // add properties of Y to X, overwriting if present in both + function extend(x, y) { for (var k in y) x[k] = y[k]; } + // get one coordinate from a coordinate array, if any + function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); } + // get all coordinates from a coordinate array as [[],[]] + function coord(v) { + var coords = v.replace(trimSpace, '').split(splitSpace), + o = []; + for (var i = 0; i < coords.length; i++) { + o.push(coord1(coords[i])); + } + return o; + } + function coordPair(x) { + var ll = [attrf(x, 'lon'), attrf(x, 'lat')], + ele = get1(x, 'ele'), + // handle namespaced attribute in browser + heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'), + time = get1(x, 'time'), + e; + if (ele) { + e = parseFloat(nodeVal(ele)); + if (!isNaN(e)) { + ll.push(e); + } + } + return { + coordinates: ll, + time: time ? nodeVal(time) : null, + heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null + }; + } - signs.exit() - .remove(); + // create a new feature collection parent object + function fc() { + return { + type: 'FeatureCollection', + features: [] + }; + } - var enter = signs.enter() - .append('foreignObject') - .attr('class', 'icon-sign') - .attr('width', '24px') // for Firefox - .attr('height', '24px') // for Firefox - .classed('selected', function(d) { - return some(d.detections, function(detection) { - return detection.image_key === selectedImageKey; - }); - }) - .on('click', click); + var serializer; + if (typeof XMLSerializer !== 'undefined') { + /* istanbul ignore next */ + serializer = new XMLSerializer(); + // only require xmldom in a node environment + } else if (typeof process === 'object' && !process.browser) { + serializer = new (domParser.XMLSerializer)(); + } + function xml2str(str) { + // IE9 will create a new XMLSerializer but it'll crash immediately. + // This line is ignored because we don't run coverage tests in IE9 + /* istanbul ignore next */ + if (str.xml !== undefined) return str.xml; + return serializer.serializeToString(str); + } - enter - .append('xhtml:body') - .attr('class', 'icon-sign-body') - .html(service.signHTML); + var t = { + kml: function(doc) { + + var gj = fc(), + // styleindex keeps track of hashed styles in order to match features + styleIndex = {}, styleByHash = {}, + // stylemapindex keeps track of style maps to expose in properties + styleMapIndex = {}, + // atomic geospatial types supported by KML - MultiGeometry is + // handled separately + geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'], + // all root placemarks in the file + placemarks = get(doc, 'Placemark'), + styles = get(doc, 'Style'), + styleMaps = get(doc, 'StyleMap'); + + for (var k = 0; k < styles.length; k++) { + var hash = okhash(xml2str(styles[k])).toString(16); + styleIndex['#' + attr(styles[k], 'id')] = hash; + styleByHash[hash] = styles[k]; + } + for (var l = 0; l < styleMaps.length; l++) { + styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16); + var pairs = get(styleMaps[l], 'Pair'); + var pairsMap = {}; + for (var m = 0; m < pairs.length; m++) { + pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl')); + } + styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap; + + } + for (var j = 0; j < placemarks.length; j++) { + gj.features = gj.features.concat(getPlacemark(placemarks[j])); + } + function kmlColor(v) { + var color, opacity; + v = v || ''; + if (v.substr(0, 1) === '#') { v = v.substr(1); } + if (v.length === 6 || v.length === 3) { color = v; } + if (v.length === 8) { + opacity = parseInt(v.substr(0, 2), 16) / 255; + color = '#' + v.substr(6, 2) + + v.substr(4, 2) + + v.substr(2, 2); + } + return [color, isNaN(opacity) ? undefined : opacity]; + } + function gxCoord(v) { return numarray(v.split(' ')); } + function gxCoords(root) { + var elems = get(root, 'coord', 'gx'), coords = [], times = []; + if (elems.length === 0) elems = get(root, 'gx:coord'); + for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i]))); + var timeElems = get(root, 'when'); + for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j])); + return { + coords: coords, + times: times + }; + } + function getGeometry(root) { + var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = []; + if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); } + if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); } + if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); } + for (i = 0; i < geotypes.length; i++) { + geomNodes = get(root, geotypes[i]); + if (geomNodes) { + for (j = 0; j < geomNodes.length; j++) { + geomNode = geomNodes[j]; + if (geotypes[i] === 'Point') { + geoms.push({ + type: 'Point', + coordinates: coord1(nodeVal(get1(geomNode, 'coordinates'))) + }); + } else if (geotypes[i] === 'LineString') { + geoms.push({ + type: 'LineString', + coordinates: coord(nodeVal(get1(geomNode, 'coordinates'))) + }); + } else if (geotypes[i] === 'Polygon') { + var rings = get(geomNode, 'LinearRing'), + coords = []; + for (k = 0; k < rings.length; k++) { + coords.push(coord(nodeVal(get1(rings[k], 'coordinates')))); + } + geoms.push({ + type: 'Polygon', + coordinates: coords + }); + } else if (geotypes[i] === 'Track' || + geotypes[i] === 'gx:Track') { + var track = gxCoords(geomNode); + geoms.push({ + type: 'LineString', + coordinates: track.coords + }); + if (track.times.length) coordTimes.push(track.times); + } + } + } + } + return { + geoms: geoms, + coordTimes: coordTimes + }; + } + function getPlacemark(root) { + var geomsAndTimes = getGeometry(root), i, properties = {}, + name = nodeVal(get1(root, 'name')), + address = nodeVal(get1(root, 'address')), + styleUrl = nodeVal(get1(root, 'styleUrl')), + description = nodeVal(get1(root, 'description')), + timeSpan = get1(root, 'TimeSpan'), + timeStamp = get1(root, 'TimeStamp'), + extendedData = get1(root, 'ExtendedData'), + lineStyle = get1(root, 'LineStyle'), + polyStyle = get1(root, 'PolyStyle'), + visibility = get1(root, 'visibility'); + + if (!geomsAndTimes.geoms.length) return []; + if (name) properties.name = name; + if (address) properties.address = address; + if (styleUrl) { + if (styleUrl[0] !== '#') { + styleUrl = '#' + styleUrl; + } + + properties.styleUrl = styleUrl; + if (styleIndex[styleUrl]) { + properties.styleHash = styleIndex[styleUrl]; + } + if (styleMapIndex[styleUrl]) { + properties.styleMapHash = styleMapIndex[styleUrl]; + properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal]; + } + // Try to populate the lineStyle or polyStyle since we got the style hash + var style = styleByHash[properties.styleHash]; + if (style) { + if (!lineStyle) lineStyle = get1(style, 'LineStyle'); + if (!polyStyle) polyStyle = get1(style, 'PolyStyle'); + } + } + if (description) properties.description = description; + if (timeSpan) { + var begin = nodeVal(get1(timeSpan, 'begin')); + var end = nodeVal(get1(timeSpan, 'end')); + properties.timespan = { begin: begin, end: end }; + } + if (timeStamp) { + properties.timestamp = nodeVal(get1(timeStamp, 'when')); + } + if (lineStyle) { + var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))), + color = linestyles[0], + opacity = linestyles[1], + width = parseFloat(nodeVal(get1(lineStyle, 'width'))); + if (color) properties.stroke = color; + if (!isNaN(opacity)) properties['stroke-opacity'] = opacity; + if (!isNaN(width)) properties['stroke-width'] = width; + } + if (polyStyle) { + var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))), + pcolor = polystyles[0], + popacity = polystyles[1], + fill = nodeVal(get1(polyStyle, 'fill')), + outline = nodeVal(get1(polyStyle, 'outline')); + if (pcolor) properties.fill = pcolor; + if (!isNaN(popacity)) properties['fill-opacity'] = popacity; + if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0; + if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0; + } + if (extendedData) { + var datas = get(extendedData, 'Data'), + simpleDatas = get(extendedData, 'SimpleData'); + + for (i = 0; i < datas.length; i++) { + properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value')); + } + for (i = 0; i < simpleDatas.length; i++) { + properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]); + } + } + if (visibility) { + properties.visibility = nodeVal(visibility); + } + if (geomsAndTimes.coordTimes.length) { + properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ? + geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes; + } + var feature = { + type: 'Feature', + geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : { + type: 'GeometryCollection', + geometries: geomsAndTimes.geoms + }, + properties: properties + }; + if (attr(root, 'id')) feature.id = attr(root, 'id'); + return [feature]; + } + return gj; + }, + gpx: function(doc) { + var i, + tracks = get(doc, 'trk'), + routes = get(doc, 'rte'), + waypoints = get(doc, 'wpt'), + // a feature collection + gj = fc(), + feature; + for (i = 0; i < tracks.length; i++) { + feature = getTrack(tracks[i]); + if (feature) gj.features.push(feature); + } + for (i = 0; i < routes.length; i++) { + feature = getRoute(routes[i]); + if (feature) gj.features.push(feature); + } + for (i = 0; i < waypoints.length; i++) { + gj.features.push(getPoint(waypoints[i])); + } + function getPoints(node, pointname) { + var pts = get(node, pointname), + line = [], + times = [], + heartRates = [], + l = pts.length; + if (l < 2) return {}; // Invalid line in GeoJSON + for (var i = 0; i < l; i++) { + var c = coordPair(pts[i]); + line.push(c.coordinates); + if (c.time) times.push(c.time); + if (c.heartRate) heartRates.push(c.heartRate); + } + return { + line: line, + times: times, + heartRates: heartRates + }; + } + function getTrack(node) { + var segments = get(node, 'trkseg'), + track = [], + times = [], + heartRates = [], + line; + for (var i = 0; i < segments.length; i++) { + line = getPoints(segments[i], 'trkpt'); + if (line) { + if (line.line) track.push(line.line); + if (line.times && line.times.length) times.push(line.times); + if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates); + } + } + if (track.length === 0) return; + var properties = getProperties(node); + extend(properties, getLineStyle(get1(node, 'extensions'))); + if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times; + if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates; + return { + type: 'Feature', + properties: properties, + geometry: { + type: track.length === 1 ? 'LineString' : 'MultiLineString', + coordinates: track.length === 1 ? track[0] : track + } + }; + } + function getRoute(node) { + var line = getPoints(node, 'rtept'); + if (!line.line) return; + var prop = getProperties(node); + extend(prop, getLineStyle(get1(node, 'extensions'))); + var routeObj = { + type: 'Feature', + properties: prop, + geometry: { + type: 'LineString', + coordinates: line.line + } + }; + return routeObj; + } + function getPoint(node) { + var prop = getProperties(node); + extend(prop, getMulti(node, ['sym'])); + return { + type: 'Feature', + properties: prop, + geometry: { + type: 'Point', + coordinates: coordPair(node).coordinates + } + }; + } + function getLineStyle(extensions) { + var style = {}; + if (extensions) { + var lineStyle = get1(extensions, 'line'); + if (lineStyle) { + var color = nodeVal(get1(lineStyle, 'color')), + opacity = parseFloat(nodeVal(get1(lineStyle, 'opacity'))), + width = parseFloat(nodeVal(get1(lineStyle, 'width'))); + if (color) style.stroke = color; + if (!isNaN(opacity)) style['stroke-opacity'] = opacity; + // GPX width is in mm, convert to px with 96 px per inch + if (!isNaN(width)) style['stroke-width'] = width * 96 / 25.4; + } + } + return style; + } + function getProperties(node) { + var prop = getMulti(node, ['name', 'cmt', 'desc', 'type', 'time', 'keywords']), + links = get(node, 'link'); + if (links.length) prop.links = []; + for (var i = 0, link; i < links.length; i++) { + link = { href: attr(links[i], 'href') }; + extend(link, getMulti(links[i], ['text', 'type'])); + prop.links.push(link); + } + return prop; + } + return gj; + } + }; + return t; + })(); - signs - .merge(enter) - .attr('x', function(d) { return projection(d.loc)[0] - 12; }) // offset by -12px to - .attr('y', function(d) { return projection(d.loc)[1] - 12; }); // center signs on loc - } + module.exports = toGeoJSON; + }); + var _initialized = false; + var _enabled = false; + var _geojson; - function drawSigns(selection$$1) { - var enabled = svgMapillarySigns.enabled, - service = getService(); - layer = selection$$1.selectAll('.layer-mapillary-signs') - .data(service ? [0] : []); + function svgGpx$$1(projection$$1, context, dispatch) { + var _showLabels = true; + var detected = utilDetect(); + var layer; + var _src; - layer.exit() - .remove(); - layer = layer.enter() - .append('g') - .attr('class', 'layer-mapillary-signs') - .style('display', enabled ? 'block' : 'none') - .merge(layer); + function init() { + if (_initialized) return; // run once - if (enabled) { - if (service && ~~context.map().zoom() >= minZoom) { - editOn(); - update(); - service.loadSigns(context, projection); - } else { - editOff(); - } - } - } + _geojson = {}; + _enabled = true; + function over() { + event.stopPropagation(); + event.preventDefault(); + event.dataTransfer.dropEffect = 'copy'; + } - drawSigns.enabled = function(_) { - if (!arguments.length) return svgMapillarySigns.enabled; - svgMapillarySigns.enabled = _; - if (svgMapillarySigns.enabled) { - showLayer(); - } else { - hideLayer(); - } - dispatch.call('change'); - return this; - }; + select('body') + .attr('dropzone', 'copy') + .on('drop.localgpx', function() { + event.stopPropagation(); + event.preventDefault(); + if (!detected.filedrop) return; + drawGpx.files(event.dataTransfer.files); + }) + .on('dragenter.localgpx', over) + .on('dragexit.localgpx', over) + .on('dragover.localgpx', over); + + _initialized = true; + } - drawSigns.supported = function() { - var service = getService(); - return (service && service.signsSupported()); - }; + function drawGpx(selection$$1) { + var getPath = svgPath(projection$$1).geojson; + layer = selection$$1.selectAll('.layer-gpx') + .data(_enabled ? [0] : []); - init(); - return drawSigns; -} + layer.exit() + .remove(); -function svgOpenstreetcamImages$$1(projection, context, dispatch) { - var throttledRedraw = throttle(function () { dispatch.call('change'); }, 1000); - var minZoom = 12; - var minMarkerZoom = 16; - var minViewfieldZoom = 18; - var layer = d3_select(null); - var _openstreetcam; + layer = layer.enter() + .append('g') + .attr('class', 'layer-gpx') + .merge(layer); - function init() { - if (svgOpenstreetcamImages$$1.initialized) return; // run once - svgOpenstreetcamImages$$1.enabled = false; - svgOpenstreetcamImages$$1.initialized = true; - } + var paths = layer + .selectAll('path') + .data([_geojson]); + paths.exit() + .remove(); - function getService() { - if (services.openstreetcam && !_openstreetcam) { - _openstreetcam = services.openstreetcam; - _openstreetcam.event.on('loadedImages', throttledRedraw); - } else if (!services.openstreetcam && _openstreetcam) { - _openstreetcam = null; - } + paths = paths.enter() + .append('path') + .attr('class', 'gpx') + .merge(paths); - return _openstreetcam; - } + paths + .attr('d', getPath); - function showLayer() { - var service = getService(); - if (!service) return; + var labelData = _showLabels && _geojson.features ? _geojson.features : []; + labelData = labelData.filter(getPath); - service.loadViewer(context); - editOn(); + layer + .call(drawLabels, 'gpxlabel-halo', labelData) + .call(drawLabels, 'gpxlabel', labelData); - layer - .style('opacity', 0) - .transition() - .duration(250) - .style('opacity', 1) - .on('end', function () { dispatch.call('change'); }); - } + function drawLabels(selection$$1, textClass, data) { + var labels = selection$$1.selectAll('text.' + textClass) + .data(data); - function hideLayer() { - var service = getService(); - if (service) { - service.hideViewer(); - } + // exit + labels.exit() + .remove(); - throttledRedraw.cancel(); + // enter/update + labels = labels.enter() + .append('text') + .attr('class', textClass) + .merge(labels) + .text(function(d) { + if (d.properties) { + return d.properties.desc || d.properties.name; + } + return null; + }) + .attr('x', function(d) { + var centroid = getPath.centroid(d); + return centroid[0] + 11; + }) + .attr('y', function(d) { + var centroid = getPath.centroid(d); + return centroid[1]; + }); + } + } - layer - .transition() - .duration(250) - .style('opacity', 0) - .on('end', editOff); - } + function toDom(x) { + return (new DOMParser()).parseFromString(x, 'text/xml'); + } - function editOn() { - layer.style('display', 'block'); - } + function getExtension(fileName) { + if (isUndefined(fileName)) { + return ''; + } - function editOff() { - layer.selectAll('.viewfield-group').remove(); - layer.style('display', 'none'); - } + var lastDotIndex = fileName.lastIndexOf('.'); + if (lastDotIndex < 0) { + return ''; + } + return fileName.substr(lastDotIndex); + } - function click(d) { - var service = getService(); - if (!service) return; - service - .selectImage(d) - .updateViewer(d) - .showViewer(); + function parseSaveAndZoom(extension, data) { + switch (extension) { + default: + drawGpx.geojson(togeojson.gpx(toDom(data))).fitZoom(); + break; + case '.kml': + drawGpx.geojson(togeojson.kml(toDom(data))).fitZoom(); + break; + case '.geojson': + case '.json': + drawGpx.geojson(JSON.parse(data)).fitZoom(); + break; + } + } - context.map().centerEase(d.loc); - } + drawGpx.showLabels = function(_) { + if (!arguments.length) return _showLabels; + _showLabels = _; + return this; + }; - function mouseover(d) { - var service = getService(); - if (service) service.setStyles(d); - } + drawGpx.enabled = function(_) { + if (!arguments.length) return _enabled; + _enabled = _; + dispatch.call('change'); + return this; + }; - function mouseout() { - var service = getService(); - if (service) service.setStyles(null); - } + drawGpx.hasGpx = function() { + return (!(isEmpty(_geojson) || isEmpty(_geojson.features))); + }; - function transform(d) { - var t = svgPointTransform(projection)(d); - if (d.ca) { - t += ' rotate(' + Math.floor(d.ca) + ',0,0)'; - } - return t; - } + drawGpx.geojson = function(gj) { + if (!arguments.length) return _geojson; + if (isEmpty(gj) || isEmpty(gj.features)) return this; + _geojson = gj; + dispatch.call('change'); + return this; + }; - function update() { - var viewer = d3_select('#photoviewer'); - var selected = viewer.empty() ? undefined : viewer.datum(); - var z = ~~context.map().zoom(); - var showMarkers = (z >= minMarkerZoom); - var showViewfields = (z >= minViewfieldZoom); + drawGpx.url = function(url) { + d3_text(url, function(err, data) { + if (!err) { + _src = url; + var extension = getExtension(url); + parseSaveAndZoom(extension, data); + } + }); + return this; + }; - var service = getService(); - var sequences = (service ? service.sequences(projection) : []); - var images = (service && showMarkers ? service.images(projection) : []); - var traces = layer.selectAll('.sequences').selectAll('.sequence') - .data(sequences, function(d) { return d.properties.key; }); + drawGpx.files = function(fileList) { + if (!fileList.length) return this; + var f = fileList[0], + reader = new FileReader(); - // exit - traces.exit() - .remove(); + reader.onload = (function(file) { + _src = file.name; + var extension = getExtension(file.name); + return function (e) { + parseSaveAndZoom(extension, e.target.result); + }; + })(f); - // enter/update - traces = traces.enter() - .append('path') - .attr('class', 'sequence') - .merge(traces) - .attr('d', svgPath(projection).geojson); + reader.readAsText(f); + return this; + }; - var groups = layer.selectAll('.markers').selectAll('.viewfield-group') - .data(images, function(d) { return d.key; }); + drawGpx.getSrc = function () { + return _src; + }; - // exit - groups.exit() - .remove(); - // enter - var groupsEnter = groups.enter() - .append('g') - .attr('class', 'viewfield-group') - .on('mouseover', mouseover) - .on('mouseout', mouseout) - .on('click', click); + drawGpx.fitZoom = function() { + if (!this.hasGpx()) return this; + + var map = context.map(); + var viewport = map.trimmedExtent().polygon(); + var coords = reduce(_geojson.features, function(coords, feature) { + var c = feature.geometry.coordinates; + + /* eslint-disable no-fallthrough */ + switch (feature.geometry.type) { + case 'Point': + c = [c]; + case 'MultiPoint': + case 'LineString': + break; + + case 'MultiPolygon': + c = flatten(c); + case 'Polygon': + case 'MultiLineString': + c = flatten(c); + break; + } + /* eslint-enable no-fallthrough */ + + return union(coords, c); + }, []); + + if (!geoPolygonIntersectsPolygon(viewport, coords, true)) { + var extent = geoExtent$$1(d3_geoBounds({ type: 'LineString', coordinates: coords })); + map.centerZoom(extent.center(), map.trimmedExtentZoom(extent)); + } - groupsEnter - .append('g') - .attr('class', 'viewfield-scale'); + return this; + }; - // update - var markers = groups - .merge(groupsEnter) - .sort(function(a, b) { - return (a === selected) ? 1 - : (b === selected) ? -1 - : b.loc[1] - a.loc[1]; // sort Y - }) - .attr('transform', transform) - .select('.viewfield-scale'); + init(); + return drawGpx; + } - markers.selectAll('circle') - .data([0]) - .enter() - .append('circle') - .attr('dx', '0') - .attr('dy', '0') - .attr('r', '6'); + function svgIcon(name, svgklass, useklass) { + return function drawIcon(selection) { + selection.selectAll('svg') + .data([0]) + .enter() + .append('svg') + .attr('class', 'icon ' + (svgklass || '')) + .append('use') + .attr('xlink:href', name) + .attr('class', useklass); + }; + } - var viewfields = markers.selectAll('.viewfield') - .data(showViewfields ? [0] : []); + function svgLabels(projection$$1, context) { + var path = d3_geoPath(projection$$1); + var detected = utilDetect(); + var baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'); + var _rdrawn = rbush_1(); + var _rskipped = rbush_1(); + var _textWidthCache = {}; + var _entitybboxes = {}; + + // Listed from highest to lowest priority + var labelStack = [ + ['line', 'aeroway', '*', 12], + ['line', 'highway', 'motorway', 12], + ['line', 'highway', 'trunk', 12], + ['line', 'highway', 'primary', 12], + ['line', 'highway', 'secondary', 12], + ['line', 'highway', 'tertiary', 12], + ['line', 'highway', '*', 12], + ['line', 'railway', '*', 12], + ['line', 'waterway', '*', 12], + ['area', 'aeroway', '*', 12], + ['area', 'amenity', '*', 12], + ['area', 'building', '*', 12], + ['area', 'historic', '*', 12], + ['area', 'leisure', '*', 12], + ['area', 'man_made', '*', 12], + ['area', 'natural', '*', 12], + ['area', 'shop', '*', 12], + ['area', 'tourism', '*', 12], + ['area', 'camp_site', '*', 12], + ['point', 'aeroway', '*', 10], + ['point', 'amenity', '*', 10], + ['point', 'building', '*', 10], + ['point', 'historic', '*', 10], + ['point', 'leisure', '*', 10], + ['point', 'man_made', '*', 10], + ['point', 'natural', '*', 10], + ['point', 'shop', '*', 10], + ['point', 'tourism', '*', 10], + ['point', 'camp_site', '*', 10], + ['line', 'name', '*', 12], + ['area', 'name', '*', 12], + ['point', 'name', '*', 10] + ]; - viewfields.exit() - .remove(); - viewfields.enter() // viewfields may or may not be drawn... - .insert('path', 'circle') // but if they are, draw below the circles - .attr('class', 'viewfield') - .attr('transform', 'scale(1.5,1.5),translate(-8, -13)') - .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'); - } + function blacklisted(preset) { + var noIcons = ['building', 'landuse', 'natural']; + return some(noIcons, function(s) { + return preset.id.indexOf(s) >= 0; + }); + } - function drawImages(selection$$1) { - var enabled = svgOpenstreetcamImages$$1.enabled, - service = getService(); + function get(array, prop) { + return function(d, i) { return array[i][prop]; }; + } - layer = selection$$1.selectAll('.layer-openstreetcam-images') - .data(service ? [0] : []); - layer.exit() - .remove(); + function textWidth(text, size, elem) { + var c = _textWidthCache[size]; + if (!c) c = _textWidthCache[size] = {}; - var layerEnter = layer.enter() - .append('g') - .attr('class', 'layer-openstreetcam-images') - .style('display', enabled ? 'block' : 'none'); + if (c[text]) { + return c[text]; - layerEnter - .append('g') - .attr('class', 'sequences'); + } else if (elem) { + c[text] = elem.getComputedTextLength(); + return c[text]; - layerEnter - .append('g') - .attr('class', 'markers'); - - layer = layerEnter - .merge(layer); - - if (enabled) { - if (service && ~~context.map().zoom() >= minZoom) { - editOn(); - update(); - service.loadImages(projection); - } else { - editOff(); - } - } - } + } else { + var str = encodeURIComponent(text).match(/%[CDEFcdef]/g); + if (str === null) { + return size / 3 * 2 * text.length; + } else { + return size / 3 * (2 * text.length + str.length); + } + } + } - drawImages.enabled = function(_) { - if (!arguments.length) return svgOpenstreetcamImages$$1.enabled; - svgOpenstreetcamImages$$1.enabled = _; - if (svgOpenstreetcamImages$$1.enabled) { - showLayer(); - } else { - hideLayer(); - } - dispatch.call('change'); - return this; - }; + function drawLinePaths(selection, entities, filter, classes, labels) { + var paths = selection.selectAll('path') + .filter(filter) + .data(entities, osmEntity$$1.key); + // exit + paths.exit() + .remove(); - drawImages.supported = function() { - return !!getService(); - }; + // enter/update + paths.enter() + .append('path') + .style('stroke-width', get(labels, 'font-size')) + .attr('id', function(d) { return 'labelpath-' + d.id; }) + .attr('class', classes) + .merge(paths) + .attr('d', get(labels, 'lineString')); + } - init(); - return drawImages; -} + function drawLineLabels(selection, entities, filter, classes, labels) { + var texts = selection.selectAll('text.' + classes) + .filter(filter) + .data(entities, osmEntity$$1.key); + + // exit + texts.exit() + .remove(); + + // enter + texts.enter() + .append('text') + .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; }) + .attr('dy', baselineHack ? '0.35em' : null) + .append('textPath') + .attr('class', 'textpath'); + + // update + selection.selectAll('text.' + classes).selectAll('.textpath') + .filter(filter) + .data(entities, osmEntity$$1.key) + .attr('startOffset', '50%') + .attr('xlink:href', function(d) { return '#labelpath-' + d.id; }) + .text(utilDisplayNameForPath); + } -function svgOsm(projection, context, dispatch) { - var enabled = true; + function drawPointLabels(selection, entities, filter, classes, labels) { + var texts = selection.selectAll('text.' + classes) + .filter(filter) + .data(entities, osmEntity$$1.key); + + // exit + texts.exit() + .remove(); + + // enter/update + texts.enter() + .append('text') + .attr('class', function(d, i) { + return classes + ' ' + labels[i].classes + ' ' + d.id; + }) + .merge(texts) + .attr('x', get(labels, 'x')) + .attr('y', get(labels, 'y')) + .style('text-anchor', get(labels, 'textAnchor')) + .text(utilDisplayName) + .each(function(d, i) { + textWidth(utilDisplayName(d), labels[i].height, this); + }); + } - function drawOsm(selection) { - selection.selectAll('.layer-osm') - .data(['covered', 'areas', 'lines', 'points', 'labels']) - .enter() - .append('g') - .attr('class', function(d) { return 'layer-osm layer-' + d; }); - selection.selectAll('.layer-areas').selectAll('.layer-areas-group') - .data(['areas', 'targets']) - .enter() - .append('g') - .attr('class', function(d) { return 'layer-areas-group layer-areas-' + d; }); + function drawAreaLabels(selection, entities, filter, classes, labels) { + entities = entities.filter(hasText); + labels = labels.filter(hasText); + drawPointLabels(selection, entities, filter, classes, labels); - selection.selectAll('.layer-lines').selectAll('.layer-lines-group') - .data(['lines', 'targets']) - .enter() - .append('g') - .attr('class', function(d) { return 'layer-lines-group layer-lines-' + d; }); + function hasText(d, i) { + return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y'); + } + } - selection.selectAll('.layer-points').selectAll('.layer-points-group') - .data(['points', 'midpoints', 'vertices', 'turns', 'targets']) - .enter() - .append('g') - .attr('class', function(d) { return 'layer-points-group layer-points-' + d; }); - selection.selectAll('.layer-labels').selectAll('.layer-labels-group') - .data(['halo', 'label', 'debug']) - .enter() - .append('g') - .attr('class', function(d) { return 'layer-labels-group layer-labels-' + d; }); - } + function drawAreaIcons(selection, entities, filter, classes, labels) { + var icons = selection.selectAll('use.' + classes) + .filter(filter) + .data(entities, osmEntity$$1.key); + + // exit + icons.exit() + .remove(); + + // enter/update + icons.enter() + .append('use') + .attr('class', 'icon ' + classes) + .attr('width', '17px') + .attr('height', '17px') + .merge(icons) + .attr('transform', get(labels, 'transform')) + .attr('xlink:href', function(d) { + var preset = context.presets().match(d, context.graph()); + var picon = preset && preset.icon; + + if (!picon) { + return ''; + } else { + var isMaki = dataFeatureIcons.indexOf(picon) !== -1; + return '#' + picon + (isMaki ? '-15' : ''); + } + }); + } - function showLayer() { - var layer = context.surface().selectAll('.data-layer-osm'); - layer.interrupt(); + function drawCollisionBoxes(selection, rtree, which) { + var classes = 'debug ' + which + ' ' + (which === 'debug-skipped' ? 'orange' : 'yellow'); + + var gj = []; + if (context.getDebug('collision')) { + gj = rtree.all().map(function(d) { + return { type: 'Polygon', coordinates: [[ + [d.minX, d.minY], + [d.maxX, d.minY], + [d.maxX, d.maxY], + [d.minX, d.maxY], + [d.minX, d.minY] + ]]}; + }); + } - layer - .classed('disabled', false) - .style('opacity', 0) - .transition() - .duration(250) - .style('opacity', 1) - .on('end interrupt', function () { - dispatch.call('change'); - }); - } + var boxes = selection.selectAll('.' + which) + .data(gj); + // exit + boxes.exit() + .remove(); - function hideLayer() { - var layer = context.surface().selectAll('.data-layer-osm'); - layer.interrupt(); + // enter/update + boxes.enter() + .append('path') + .attr('class', classes) + .merge(boxes) + .attr('d', d3_geoPath()); + } - layer - .transition() - .duration(250) - .style('opacity', 0) - .on('end interrupt', function () { - layer.classed('disabled', true); - dispatch.call('change'); - }); - } + function drawLabels(selection, graph, entities, filter, dimensions, fullRedraw) { + var wireframe = context.surface().classed('fill-wireframe'); + var zoom = geoScaleToZoom(projection$$1.scale()); - drawOsm.enabled = function(_) { - if (!arguments.length) return enabled; - enabled = _; + var labelable = []; + var renderNodeAs = {}; + var i, j, k, entity, geometry; - if (enabled) { - showLayer(); - } else { - hideLayer(); - } + for (i = 0; i < labelStack.length; i++) { + labelable.push([]); + } - dispatch.call('change'); - return this; - }; + if (fullRedraw) { + _rdrawn.clear(); + _rskipped.clear(); + _entitybboxes = {}; + } else { + for (i = 0; i < entities.length; i++) { + entity = entities[i]; + var toRemove = [] + .concat(_entitybboxes[entity.id] || []) + .concat(_entitybboxes[entity.id + 'I'] || []); + + for (j = 0; j < toRemove.length; j++) { + _rdrawn.remove(toRemove[j]); + _rskipped.remove(toRemove[j]); + } + } + } - return drawOsm; -} + // Loop through all the entities to do some preprocessing + for (i = 0; i < entities.length; i++) { + entity = entities[i]; + geometry = entity.geometry(graph); + + // Insert collision boxes around interesting points/vertices + if (geometry === 'point' || (geometry === 'vertex' && isInterestingVertex(entity))) { + var hasDirections = entity.directions(graph, projection$$1).length; + var markerPadding; + + if (!wireframe && geometry === 'point' && !(zoom >= 18 && hasDirections)) { + renderNodeAs[entity.id] = 'point'; + markerPadding = 20; // extra y for marker height + } else { + renderNodeAs[entity.id] = 'vertex'; + markerPadding = 0; + } + + var coord = projection$$1(entity.loc); + var nodePadding = 10; + var bbox = { + minX: coord[0] - nodePadding, + minY: coord[1] - nodePadding - markerPadding, + maxX: coord[0] + nodePadding, + maxY: coord[1] + nodePadding + }; + + doInsert(bbox, entity.id + 'P'); + } + + // From here on, treat vertices like points + if (geometry === 'vertex') { + geometry = 'point'; + } + + // Determine which entities are label-able + var preset = geometry === 'area' && context.presets().match(entity, graph); + var icon = preset && !blacklisted(preset) && preset.icon; + + if (!icon && !utilDisplayName(entity)) + continue; + + for (k = 0; k < labelStack.length; k++) { + var matchGeom = labelStack[k][0]; + var matchKey = labelStack[k][1]; + var matchVal = labelStack[k][2]; + var hasVal = entity.tags[matchKey]; + + if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) { + labelable[k].push(entity); + break; + } + } + } -function svgLayers(projection, context) { - var dispatch$$1 = dispatch('change'), - svg = d3_select(null), - layers = [ - { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) }, - { id: 'gpx', layer: svgGpx$$1(projection, context, dispatch$$1) }, - { id: 'mapillary-images', layer: svgMapillaryImages$$1(projection, context, dispatch$$1) }, - { id: 'mapillary-signs', layer: svgMapillarySigns(projection, context, dispatch$$1) }, - { id: 'openstreetcam-images', layer: svgOpenstreetcamImages$$1(projection, context, dispatch$$1) }, - { id: 'debug', layer: svgDebug$$1(projection, context, dispatch$$1) } - ]; + var positions = { + point: [], + line: [], + area: [] + }; + var labelled = { + point: [], + line: [], + area: [] + }; - function drawLayers(selection$$1) { - svg = selection$$1.selectAll('.surface') - .data([0]); + // Try and find a valid label for labellable entities + for (k = 0; k < labelable.length; k++) { + var fontSize = labelStack[k][3]; + + for (i = 0; i < labelable[k].length; i++) { + entity = labelable[k][i]; + geometry = entity.geometry(graph); + + var getName = (geometry === 'line') ? utilDisplayNameForPath : utilDisplayName; + var name = getName(entity); + var width = name && textWidth(name, fontSize); + var p = null; + + if (geometry === 'point' || geometry === 'vertex') { + // no point or vertex labels in wireframe mode + // no vertex labels at low zooms (vertices have no icons) + if (wireframe) continue; + var renderAs = renderNodeAs[entity.id]; + if (renderAs === 'vertex' && zoom < 17) continue; + + p = getPointLabel(entity, width, fontSize, renderAs); + + } else if (geometry === 'line') { + p = getLineLabel(entity, width, fontSize); + + } else if (geometry === 'area') { + p = getAreaLabel(entity, width, fontSize); + } + + if (p) { + if (geometry === 'vertex') { geometry = 'point'; } // treat vertex like point + p.classes = geometry + ' tag-' + labelStack[k][1]; + positions[geometry].push(p); + labelled[geometry].push(entity); + } + } + } - svg = svg.enter() - .append('svg') - .attr('class', 'surface') - .merge(svg); - var defs = svg.selectAll('.surface-defs') - .data([0]); + function isInterestingVertex(entity) { + var selectedIDs = context.selectedIDs(); - defs.enter() - .append('defs') - .attr('class', 'surface-defs'); + return entity.hasInterestingTags() || + entity.isEndpoint(graph) || + entity.isConnected(graph) || + selectedIDs.indexOf(entity.id) !== -1 || + some(graph.parentWays(entity), function(parent) { + return selectedIDs.indexOf(parent.id) !== -1; + }); + } - var groups = svg.selectAll('.data-layer') - .data(layers); - groups.exit() - .remove(); + function getPointLabel(entity, width, height, geometry) { + var y = (geometry === 'point' ? -12 : 0); + var pointOffsets = { + ltr: [15, y, 'start'], + rtl: [-15, y, 'end'] + }; + + var coord = projection$$1(entity.loc); + var textPadding = 2; + var offset = pointOffsets[textDirection]; + var p = { + height: height, + width: width, + x: coord[0] + offset[0], + y: coord[1] + offset[1], + textAnchor: offset[2] + }; + + // insert a collision box for the text label.. + var bbox; + if (textDirection === 'rtl') { + bbox = { + minX: p.x - width - textPadding, + minY: p.y - (height / 2) - textPadding, + maxX: p.x + textPadding, + maxY: p.y + (height / 2) + textPadding + }; + } else { + bbox = { + minX: p.x - textPadding, + minY: p.y - (height / 2) - textPadding, + maxX: p.x + width + textPadding, + maxY: p.y + (height / 2) + textPadding + }; + } + + if (tryInsert([bbox], entity.id, true)) { + return p; + } + } - groups.enter() - .append('g') - .attr('class', function(d) { return 'data-layer data-layer-' + d.id; }) - .merge(groups) - .each(function(d) { d3_select(this).call(d.layer); }); - } + function getLineLabel(entity, width, height) { + var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(); + var points = map$3(graph.childNodes(entity), 'loc').map(projection$$1); + var length = geoPathLength(points); + + if (length < width + 20) return; + + // todo: properly clip points to viewport + + // % along the line to attempt to place the label + var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70, + 25, 75, 20, 80, 15, 95, 10, 90, 5, 95]; + var padding = 3; + + for (var i = 0; i < lineOffsets.length; i++) { + var offset = lineOffsets[i]; + var middle = offset / 100 * length; + var start = middle - width / 2; + + if (start < 0 || start + width > length) continue; + + // generate subpath and ignore paths that are invalid or don't cross viewport. + var sub = subpath(points, start, start + width); + if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) { + continue; + } + + var isReverse = reverse(sub); + if (isReverse) { + sub = sub.reverse(); + } + + var bboxes = []; + var boxsize = (height + 2) / 2; + + for (var j = 0; j < sub.length - 1; j++) { + var a = sub[j]; + var b = sub[j + 1]; + + // split up the text into small collision boxes + var num = Math.max(1, Math.floor(geoVecLength(a, b) / boxsize / 2)); + + for (var box = 0; box < num; box++) { + var p = geoVecInterp(a, b, box / num); + var x0 = p[0] - boxsize - padding; + var y0 = p[1] - boxsize - padding; + var x1 = p[0] + boxsize + padding; + var y1 = p[1] + boxsize + padding; + + bboxes.push({ + minX: Math.min(x0, x1), + minY: Math.min(y0, y1), + maxX: Math.max(x0, x1), + maxY: Math.max(y0, y1) + }); + } + } + + if (tryInsert(bboxes, entity.id, false)) { // accept this one + return { + 'font-size': height + 2, + lineString: lineString(sub), + startOffset: offset + '%' + }; + } + } + + function reverse(p) { + var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]); + return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2); + } + + function lineString(points) { + return 'M' + points.join('L'); + } + + function subpath(points, from, to) { + var sofar = 0; + var start, end, i0, i1; + + for (var i = 0; i < points.length - 1; i++) { + var a = points[i]; + var b = points[i + 1]; + var current = geoVecLength(a, b); + var portion; + if (!start && sofar + current >= from) { + portion = (from - sofar) / current; + start = [ + a[0] + portion * (b[0] - a[0]), + a[1] + portion * (b[1] - a[1]) + ]; + i0 = i + 1; + } + if (!end && sofar + current >= to) { + portion = (to - sofar) / current; + end = [ + a[0] + portion * (b[0] - a[0]), + a[1] + portion * (b[1] - a[1]) + ]; + i1 = i + 1; + } + sofar += current; + } + + var result = points.slice(i0, i1); + result.unshift(start); + result.push(end); + return result; + } + } - drawLayers.all = function() { - return layers; - }; + function getAreaLabel(entity, width, height) { + var centroid = path.centroid(entity.asGeoJSON(graph, true)); + var extent = entity.extent(graph); + var areaWidth = projection$$1(extent[1])[0] - projection$$1(extent[0])[0]; + + if (isNaN(centroid[0]) || areaWidth < 20) return; + + var preset = context.presets().match(entity, context.graph()); + var picon = preset && preset.icon; + var iconSize = 17; + var padding = 2; + var p = {}; + + if (picon) { // icon and label.. + if (addIcon()) { + addLabel(iconSize + padding); + return p; + } + } else { // label only.. + if (addLabel(0)) { + return p; + } + } + + + function addIcon() { + var iconX = centroid[0] - (iconSize / 2); + var iconY = centroid[1] - (iconSize / 2); + var bbox = { + minX: iconX, + minY: iconY, + maxX: iconX + iconSize, + maxY: iconY + iconSize + }; + + if (tryInsert([bbox], entity.id + 'I', true)) { + p.transform = 'translate(' + iconX + ',' + iconY + ')'; + return true; + } + return false; + } + + function addLabel(yOffset) { + if (width && areaWidth >= width + 20) { + var labelX = centroid[0]; + var labelY = centroid[1] + yOffset; + var bbox = { + minX: labelX - (width / 2) - padding, + minY: labelY - (height / 2) - padding, + maxX: labelX + (width / 2) + padding, + maxY: labelY + (height / 2) + padding + }; + + if (tryInsert([bbox], entity.id, true)) { + p.x = labelX; + p.y = labelY; + p.textAnchor = 'middle'; + p.height = height; + return true; + } + } + return false; + } + } - drawLayers.layer = function(id) { - var obj = find$1(layers, function(o) {return o.id === id;}); - return obj && obj.layer; - }; + // force insert a singular bounding box + // singular box only, no array, id better be unique + function doInsert(bbox, id) { + bbox.id = id; - drawLayers.only = function(what) { - var arr = [].concat(what); - drawLayers.remove(difference(map$3(layers, 'id'), arr)); - return this; - }; + var oldbox = _entitybboxes[id]; + if (oldbox) { + _rdrawn.remove(oldbox); + } + _entitybboxes[id] = bbox; + _rdrawn.insert(bbox); + } - drawLayers.remove = function(what) { - var arr = [].concat(what); - arr.forEach(function(id) { - layers = reject(layers, function(o) {return o.id === id;}); - }); - dispatch$$1.call('change'); - return this; - }; + function tryInsert(bboxes, id, saveSkipped) { + var skipped = false; + for (var i = 0; i < bboxes.length; i++) { + var bbox = bboxes[i]; + bbox.id = id; - drawLayers.add = function(what) { - var arr = [].concat(what); - arr.forEach(function(obj) { - if ('id' in obj && 'layer' in obj) { - layers.push(obj); - } - }); - dispatch$$1.call('change'); - return this; - }; + // Check that label is visible + if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) { + skipped = true; + break; + } + if (_rdrawn.collides(bbox)) { + skipped = true; + break; + } + } + _entitybboxes[id] = bboxes; - drawLayers.dimensions = function(_) { - if (!arguments.length) return utilGetDimensions(svg); - utilSetDimensions(svg, _); - return this; - }; + if (skipped) { + if (saveSkipped) { + _rskipped.load(bboxes); + } + } else { + _rdrawn.load(bboxes); + } + return !skipped; + } - return utilRebind(drawLayers, dispatch$$1, 'on'); -} - -function svgLines$$1(projection, context) { - var detected = utilDetect(); - - var highway_stack = { - motorway: 0, - motorway_link: 1, - trunk: 2, - trunk_link: 3, - primary: 4, - primary_link: 5, - secondary: 6, - tertiary: 7, - unclassified: 8, - residential: 9, - service: 10, - footway: 11 - }; + var layer = selection.selectAll('.layer-labels'); + var halo = layer.selectAll('.layer-labels-halo'); + var label = layer.selectAll('.layer-labels-label'); + var debug = layer.selectAll('.layer-labels-debug'); - function drawTargets(selection, graph, entities, filter$$1) { - var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor '; - var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor '; - var getPath = svgPath(projection).geojson; - var activeID = context.activeID(); + // points + drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point); + drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point); - // The targets and nopes will be MultiLineString sub-segments of the ways - var data = { targets: [], nopes: [] }; + // lines + drawLinePaths(halo, labelled.line, filter, '', positions.line); + drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line); + drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line); - entities.forEach(function(way) { - var features = svgSegmentWay(way, graph, activeID); - data.targets.push.apply(data.targets, features.passive); - data.nopes.push.apply(data.nopes, features.active); - }); + // areas + drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area); + drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area); + drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area); + drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area); + // debug + drawCollisionBoxes(debug, _rskipped, 'debug-skipped'); + drawCollisionBoxes(debug, _rdrawn, 'debug-drawn'); - // Targets allow hover and vertex snapping - var targetData = data.targets.filter(getPath); - var targets = selection.selectAll('.line.target-allowed') - .filter(function(d) { return filter$$1(d.properties.entity); }) - .data(targetData, function key(d) { return d.id; }); + layer.call(filterLabels); + } - // exit - targets.exit() - .remove(); - // enter/update - targets.enter() - .append('path') - .merge(targets) - .attr('d', getPath) - .attr('class', function(d) { return 'way line target target-allowed ' + targetClass + d.id; }); + function filterLabels(selection) { + var layers = selection + .selectAll('.layer-labels-label, .layer-labels-halo'); + layers.selectAll('.nolabel') + .classed('nolabel', false); - // NOPE - var nopeData = data.nopes.filter(getPath); - var nopes = selection.selectAll('.line.target-nope') - .filter(function(d) { return filter$$1(d.properties.entity); }) - .data(nopeData, function key(d) { return d.id; }); + var mouse = context.mouse(); + var graph = context.graph(); + var selectedIDs = context.selectedIDs(); + var ids = []; + var pad, bbox; - // exit - nopes.exit() - .remove(); + // hide labels near the mouse + if (mouse) { + pad = 20; + bbox = { minX: mouse[0] - pad, minY: mouse[1] - pad, maxX: mouse[0] + pad, maxY: mouse[1] + pad }; + ids.push.apply(ids, map$3(_rdrawn.search(bbox), 'id')); + } - // enter/update - nopes.enter() - .append('path') - .merge(nopes) - .attr('d', getPath) - .attr('class', function(d) { return 'way line target target-nope ' + nopeClass + d.id; }); - } + // hide labels on selected nodes (they look weird when dragging / haloed) + for (var i = 0; i < selectedIDs.length; i++) { + var entity = graph.hasEntity(selectedIDs[i]); + if (entity && entity.type === 'node') { + ids.push(selectedIDs[i]); + } + } + layers.selectAll(utilEntitySelector(ids)) + .classed('nolabel', true); + + + // draw the mouse bbox if debugging is on.. + var debug = selection.selectAll('.layer-labels-debug'); + var gj = []; + if (context.getDebug('collision')) { + gj = bbox ? [{ + type: 'Polygon', + coordinates: [[ + [bbox.minX, bbox.minY], + [bbox.maxX, bbox.minY], + [bbox.maxX, bbox.maxY], + [bbox.minX, bbox.maxY], + [bbox.minX, bbox.minY] + ]] + }] : []; + } - function drawLines(selection, graph, entities, filter$$1) { + var box = debug.selectAll('.debug-mouse') + .data(gj); - function waystack(a, b) { - var selected = context.selectedIDs(); - var scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0; - var scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0; + // exit + box.exit() + .remove(); - if (a.tags.highway) { scoreA -= highway_stack[a.tags.highway]; } - if (b.tags.highway) { scoreB -= highway_stack[b.tags.highway]; } - return scoreA - scoreB; - } + // enter/update + box.enter() + .append('path') + .attr('class', 'debug debug-mouse yellow') + .merge(box) + .attr('d', d3_geoPath()); + } - function drawLineGroup(selection, klass, isSelected) { - // Note: Don't add `.selected` class in draw modes - var mode = context.mode(); - var isDrawing = mode && /^draw/.test(mode.id); - var selectedClass = (!isDrawing && isSelected) ? 'selected ' : ''; - - var lines = selection - .selectAll('path') - .filter(filter$$1) - .data(getPathData(isSelected), osmEntity$$1.key); - - lines.exit() - .remove(); - - // Optimization: Call expensive TagClasses only on enter selection. This - // works because osmEntity.key is defined to include the entity v attribute. - lines.enter() - .append('path') - .attr('class', function(d) { - var oldMPClass = oldMultiPolygonOuters[d.id] ? 'old-multipolygon ' : ''; - return 'way line ' + klass + ' ' + selectedClass + oldMPClass + d.id; - }) - .call(svgTagClasses()) - .merge(lines) - .sort(waystack) - .attr('d', getPath) - .call(svgTagClasses().tags(svgRelationMemberTags(graph))); - - return selection; - } + var throttleFilterLabels = throttle(utilCallWhenIdle(filterLabels), 100); - function getPathData(isSelected) { - return function() { - var layer = this.parentNode.__data__; - var data = pathdata[layer] || []; - return data.filter(function(d) { - if (isSelected) - return context.selectedIDs().indexOf(d.id) !== -1; - else - return context.selectedIDs().indexOf(d.id) === -1; - }); - }; - } + drawLabels.observe = function(selection) { + var listener = function() { throttleFilterLabels(selection); }; + selection.on('mousemove.hidelabels', listener); + context.on('enter.hidelabels', listener); + }; - var getPath = svgPath(projection, graph); - var ways = []; - var pathdata = {}; - var onewaydata = {}; - var oldMultiPolygonOuters = {}; - - for (var i = 0; i < entities.length; i++) { - var entity = entities[i]; - var outer = osmSimpleMultipolygonOuterMember(entity, graph); - if (outer) { - ways.push(entity.mergeTags(outer.tags)); - oldMultiPolygonOuters[outer.id] = true; - } else if (entity.geometry(graph) === 'line') { - ways.push(entity); - } - } + drawLabels.off = function(selection) { + throttleFilterLabels.cancel(); + selection.on('mousemove.hidelabels', null); + context.on('enter.hidelabels', null); + }; - ways = ways.filter(getPath); - pathdata = groupBy(ways, function(way) { return way.layer(); }); - forOwn(pathdata, function(v, k) { - var arr = filter(v, function(d) { return d.isOneWay(); }); - onewaydata[k] = flatten(map$3(arr, svgOneWaySegments(projection, graph, 35))); - }); + return drawLabels; + } + function svgMapillaryImages$$1(projection, context, dispatch) { + var throttledRedraw = throttle(function () { dispatch.call('change'); }, 1000); + var minZoom = 12; + var minMarkerZoom = 16; + var minViewfieldZoom = 18; + var layer = select(null); + var _mapillary; - var covered = selection.selectAll('.layer-covered'); // under areas - var uncovered = selection.selectAll('.layer-lines .layer-lines-lines'); // over areas - - [covered, uncovered].forEach(function(selection) { - var range$$1 = (selection === covered ? d3_range(-10,0) : d3_range(0,11)); - var layergroup = selection - .selectAll('g.layergroup') - .data(range$$1); - - layergroup = layergroup.enter() - .append('g') - .attr('class', function(d) { return 'layergroup layer' + String(d); }) - .merge(layergroup); - - layergroup - .selectAll('g.linegroup') - .data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted']) - .enter() - .append('g') - .attr('class', function(d) { return 'linegroup line-' + d; }); - - layergroup.selectAll('g.line-shadow') - .call(drawLineGroup, 'shadow', false); - layergroup.selectAll('g.line-casing') - .call(drawLineGroup, 'casing', false); - layergroup.selectAll('g.line-stroke') - .call(drawLineGroup, 'stroke', false); - - layergroup.selectAll('g.line-shadow-highlighted') - .call(drawLineGroup, 'shadow', true); - layergroup.selectAll('g.line-casing-highlighted') - .call(drawLineGroup, 'casing', true); - layergroup.selectAll('g.line-stroke-highlighted') - .call(drawLineGroup, 'stroke', true); - - - var onewaygroup = layergroup - .selectAll('g.onewaygroup') - .data(['oneway']); - - onewaygroup = onewaygroup.enter() - .append('g') - .attr('class', 'onewaygroup') - .merge(onewaygroup); - - var oneways = onewaygroup - .selectAll('path') - .filter(filter$$1) - .data( - function data() { return onewaydata[this.parentNode.__data__] || []; }, - function key(d) { return [d.id, d.index]; } - ); - - oneways.exit() - .remove(); - - oneways = oneways.enter() - .append('path') - .attr('class', 'oneway') - .attr('marker-mid', 'url(#oneway-marker)') - .merge(oneways) - .attr('d', function(d) { return d.d; }); - - if (detected.ie) { - oneways.each(function() { this.parentNode.insertBefore(this, this); }); - } - }); - // touch targets - selection.selectAll('.layer-lines .layer-lines-targets') - .call(drawTargets, graph, ways, filter$$1); - } + function init() { + if (svgMapillaryImages$$1.initialized) return; // run once + svgMapillaryImages$$1.enabled = false; + svgMapillaryImages$$1.initialized = true; + } - return drawLines; -} + function getService() { + if (services.mapillary && !_mapillary) { + _mapillary = services.mapillary; + _mapillary.event.on('loadedImages', throttledRedraw); + } else if (!services.mapillary && _mapillary) { + _mapillary = null; + } -function svgMidpoints$$1(projection, context) { - var targetRadius = 8; + return _mapillary; + } - function drawTargets(selection, graph, entities, filter) { - var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor '; - var getTransform = svgPointTransform(projection).geojson; - var data = entities.map(function(midpoint) { - return { - type: 'Feature', - id: midpoint.id, - properties: { - target: true, - entity: midpoint - }, - geometry: { - type: 'Point', - coordinates: midpoint.loc - } - }; - }); + function showLayer() { + var service = getService(); + if (!service) return; - var targets = selection.selectAll('.midpoint.target') - .filter(function(d) { return filter(d.properties.entity); }) - .data(data, function key(d) { return d.id; }); + service.loadViewer(context); + editOn(); - // exit - targets.exit() - .remove(); + layer + .style('opacity', 0) + .transition() + .duration(250) + .style('opacity', 1) + .on('end', function () { dispatch.call('change'); }); + } - // enter/update - targets.enter() - .append('circle') - .attr('r', targetRadius) - .merge(targets) - .attr('class', function(d) { return 'node midpoint target ' + fillClass + d.id; }) - .attr('transform', getTransform); - } + function hideLayer() { + var service = getService(); + if (service) { + service.hideViewer(); + } - function drawMidpoints(selection, graph, entities, filter, extent) { - var layer = selection.selectAll('.layer-points .layer-points-midpoints'); + throttledRedraw.cancel(); - var mode = context.mode(); - if (mode && mode.id !== 'select') { - layer.selectAll('g.midpoint') - .remove(); + layer + .transition() + .duration(250) + .style('opacity', 0) + .on('end', editOff); + } - selection.selectAll('.layer-points .layer-points-targets .midpoint.target') - .remove(); - return; - } + function editOn() { + layer.style('display', 'block'); + } - var poly = extent.polygon(); - var midpoints = {}; - - for (var i = 0; i < entities.length; i++) { - var entity = entities[i]; - - if (entity.type !== 'way') - continue; - if (!filter(entity)) - continue; - if (context.selectedIDs().indexOf(entity.id) < 0) - continue; - - var nodes = graph.childNodes(entity); - for (var j = 0; j < nodes.length - 1; j++) { - - var a = nodes[j]; - var b = nodes[j + 1]; - var id = [a.id, b.id].sort().join('-'); - - if (midpoints[id]) { - midpoints[id].parents.push(entity); - } else { - if (geoVecLength(projection(a.loc), projection(b.loc)) > 40) { - var point = geoVecInterp(a.loc, b.loc, 0.5); - var loc = null; - - if (extent.intersects(point)) { - loc = point; - } else { - for (var k = 0; k < 4; k++) { - point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]); - if (point && - geoVecLength(projection(a.loc), projection(point)) > 20 && - geoVecLength(projection(b.loc), projection(point)) > 20) - { - loc = point; - break; - } - } - } - - if (loc) { - midpoints[id] = { - type: 'midpoint', - id: id, - loc: loc, - edge: [a.id, b.id], - parents: [entity] - }; - } - } - } - } - } + function editOff() { + layer.selectAll('.viewfield-group').remove(); + layer.style('display', 'none'); + } - function midpointFilter(d) { - if (midpoints[d.id]) - return true; - for (var i = 0; i < d.parents.length; i++) { - if (filter(d.parents[i])) { - return true; - } - } + function click(d) { + var service = getService(); + if (!service) return; - return false; - } + service + .selectImage(d) + .updateViewer(d.key, context) + .showViewer(); + context.map().centerEase(d.loc); + } - var groups = layer - .selectAll('g.midpoint') - .filter(midpointFilter) - .data(values$1(midpoints), function(d) { return d.id; }); - - groups.exit() - .remove(); - - var enter = groups.enter() - .insert('g', ':first-child') - .attr('class', 'midpoint'); - - enter - .append('polygon') - .attr('points', '-6,8 10,0 -6,-8') - .attr('class', 'shadow'); - - enter - .append('polygon') - .attr('points', '-3,4 5,0 -3,-4') - .attr('class', 'fill'); - - groups = groups - .merge(enter) - .attr('transform', function(d) { - var translate = svgPointTransform(projection); - var a = graph.entity(d.edge[0]); - var b = graph.entity(d.edge[1]); - var angle = geoAngle(a, b, projection) * (180 / Math.PI); - return translate(d) + ' rotate(' + angle + ')'; - }) - .call(svgTagClasses().tags( - function(d) { return d.parents[0].tags; } - )); - - // Propagate data bindings. - groups.select('polygon.shadow'); - groups.select('polygon.fill'); - - - // Draw touch targets.. - selection.selectAll('.layer-points .layer-points-targets') - .call(drawTargets, graph, values$1(midpoints), midpointFilter); - } - - return drawMidpoints; -} - -// Touch targets control which other vertices we can drag a vertex onto. -// -// - the activeID - nope -// - 1 away (adjacent) to the activeID - yes (vertices will be merged) -// - 2 away from the activeID - nope (would create a self intersecting segment) -// - all others on a linear way - yes -// - all others on a closed way - nope (would create a self intersecting polygon) -// -// returns -// 0 = active vertex - no touch/connect -// 1 = passive vertex - yes touch/connect -// 2 = adjacent vertex - yes but pay attention segmenting a line here -// -function svgPassiveVertex(node, graph, activeID) { - if (!activeID) return 1; - if (activeID === node.id) return 0; - - var parents = graph.parentWays(node); - - for (var i = 0; i < parents.length; i++) { - var nodes = parents[i].nodes; - var isClosed = parents[i].isClosed(); - for (var j = 0; j < nodes.length; j++) { // find this vertex, look nearby - if (nodes[j] === node.id) { - var ix1 = j - 2; - var ix2 = j - 1; - var ix3 = j + 1; - var ix4 = j + 2; - - if (isClosed) { // wraparound if needed - var max = nodes.length - 1; - if (ix1 < 0) ix1 = max + ix1; - if (ix2 < 0) ix2 = max + ix2; - if (ix3 > max) ix3 = ix3 - max; - if (ix4 > max) ix4 = ix4 - max; - } - - if (nodes[ix1] === activeID) return 0; // no - prevent self intersect - else if (nodes[ix2] === activeID) return 2; // ok - adjacent - else if (nodes[ix3] === activeID) return 2; // ok - adjacent - else if (nodes[ix4] === activeID) return 0; // no - prevent self intersect - else if (isClosed && nodes.indexOf(activeID) !== -1) return 0; // no - prevent self intersect - } - } - } - return 1; // ok -} + function mouseover(d) { + var service = getService(); + if (service) service.setStyles(d); + } -function svgOneWaySegments(projection$$1, graph, dt) { - return function(entity) { - var i = 0; - var offset = dt; - var segments = []; - var clip = d3_geoIdentity().clipExtent(projection$$1.clipExtent()).stream; - var coordinates = graph.childNodes(entity).map(function(n) { return n.loc; }); - var a, b; + function mouseout() { + var service = getService(); + if (service) service.setStyles(null); + } - if (entity.tags.oneway === '-1') { - coordinates.reverse(); - } - var isReversible = (entity.tags.oneway === 'reversible' || entity.tags.oneway === 'alternating'); - - d3_geoStream({ - type: 'LineString', - coordinates: coordinates - }, projection$$1.stream(clip({ - lineStart: function() {}, - lineEnd: function() { a = null; }, - point: function(x, y) { - b = [x, y]; - - if (a) { - var span = geoVecLength(a, b) - offset; - - if (span >= 0) { - var heading = geoVecAngle(a, b); - var dx = dt * Math.cos(heading); - var dy = dt * Math.sin(heading); - var p = [ - a[0] + offset * Math.cos(heading), - a[1] + offset * Math.sin(heading) - ]; - - // gather coordinates - var coord = [a, p]; - for (span -= dt; span >= 0; span -= dt) { - p = geoVecAdd(p, [dx, dy]); - coord.push(p); - } - coord.push(b); - - // generate svg paths - var segment = ''; - var j; - - for (j = 0; j < coord.length; j++) { - segment += (j === 0 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1]; - } - segments.push({ id: entity.id, index: i++, d: segment }); - - if (isReversible) { - segment = ''; - for (j = coord.length - 1; j >= 0; j--) { - segment += (j === coord.length - 1 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1]; - } - segments.push({ id: entity.id, index: i++, d: segment }); - } - } - - offset = -span; - } - - a = b; - } - }))); + function transform(d) { + var t = svgPointTransform(projection)(d); + if (d.ca) { + t += ' rotate(' + Math.floor(d.ca) + ',0,0)'; + } + return t; + } - return segments; - }; -} + function update() { + var viewer = select('#photoviewer'); + var selected = viewer.empty() ? undefined : viewer.datum(); + + var z = ~~context.map().zoom(); + var showMarkers = (z >= minMarkerZoom); + var showViewfields = (z >= minViewfieldZoom); + + var service = getService(); + var sequences = (service ? service.sequences(projection) : []); + var images = (service && showMarkers ? service.images(projection) : []); + + var traces = layer.selectAll('.sequences').selectAll('.sequence') + .data(sequences, function(d) { return d.properties.key; }); + + // exit + traces.exit() + .remove(); + + // enter/update + traces = traces.enter() + .append('path') + .attr('class', 'sequence') + .merge(traces) + .attr('d', svgPath(projection).geojson); + + + var groups = layer.selectAll('.markers').selectAll('.viewfield-group') + .data(images, function(d) { return d.key; }); + + // exit + groups.exit() + .remove(); + + // enter + var groupsEnter = groups.enter() + .append('g') + .attr('class', 'viewfield-group') + .on('mouseover', mouseover) + .on('mouseout', mouseout) + .on('click', click); + + groupsEnter + .append('g') + .attr('class', 'viewfield-scale'); + + // update + var markers = groups + .merge(groupsEnter) + .sort(function(a, b) { + return (a === selected) ? 1 + : (b === selected) ? -1 + : b.loc[1] - a.loc[1]; // sort Y + }) + .attr('transform', transform) + .select('.viewfield-scale'); + + + markers.selectAll('circle') + .data([0]) + .enter() + .append('circle') + .attr('dx', '0') + .attr('dy', '0') + .attr('r', '6'); + + var viewfields = markers.selectAll('.viewfield') + .data(showViewfields ? [0] : []); + + viewfields.exit() + .remove(); + + viewfields.enter() // viewfields may or may not be drawn... + .insert('path', 'circle') // but if they are, draw below the circles + .attr('class', 'viewfield') + .attr('transform', 'scale(1.5,1.5),translate(-8, -13)') + .attr('d', viewfieldPath); + + function viewfieldPath() { + var d = this.parentNode.__data__; + if (d.pano) { + return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0'; + } else { + return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z'; + } + } + } -function svgPath(projection$$1, graph, isArea) { - // Explanation of magic numbers: - // "padding" here allows space for strokes to extend beyond the viewport, - // so that the stroke isn't drawn along the edge of the viewport when - // the shape is clipped. - // - // When drawing lines, pad viewport by 5px. - // When drawing areas, pad viewport by 65px in each direction to allow - // for 60px area fill stroke (see ".fill-partial path.fill" css rule) - - var cache = {}; - var padding = isArea ? 65 : 5; - var viewport = projection$$1.clipExtent(); - var paddedExtent = [ - [viewport[0][0] - padding, viewport[0][1] - padding], - [viewport[1][0] + padding, viewport[1][1] + padding] - ]; - var clip = d3_geoIdentity().clipExtent(paddedExtent).stream; - var project = projection$$1.stream; - var path = d3_geoPath() - .projection({stream: function(output) { return project(clip(output)); }}); - - var svgpath = function(entity) { - if (entity.id in cache) { - return cache[entity.id]; - } else { - return cache[entity.id] = path(entity.asGeoJSON(graph)); - } - }; + function drawImages(selection$$1) { + var enabled = svgMapillaryImages$$1.enabled, + service = getService(); - svgpath.geojson = path; + layer = selection$$1.selectAll('.layer-mapillary-images') + .data(service ? [0] : []); - return svgpath; -} + layer.exit() + .remove(); + var layerEnter = layer.enter() + .append('g') + .attr('class', 'layer-mapillary-images') + .style('display', enabled ? 'block' : 'none'); -function svgPointTransform(projection$$1) { - var svgpoint = function(entity) { - // http://jsperf.com/short-array-join - var pt = projection$$1(entity.loc); - return 'translate(' + pt[0] + ',' + pt[1] + ')'; - }; + layerEnter + .append('g') + .attr('class', 'sequences'); - svgpoint.geojson = function(d) { - return svgpoint(d.properties.entity); - }; + layerEnter + .append('g') + .attr('class', 'markers'); - return svgpoint; -} + layer = layerEnter + .merge(layer); + if (enabled) { + if (service && ~~context.map().zoom() >= minZoom) { + editOn(); + update(); + service.loadImages(projection); + } else { + editOff(); + } + } + } -function svgRelationMemberTags(graph) { - return function(entity) { - var tags = entity.tags; - graph.parentRelations(entity).forEach(function(relation) { - var type = relation.tags.type; - if (type === 'multipolygon' || type === 'boundary') { - tags = assignIn({}, relation.tags, tags); - } - }); - return tags; - }; -} - - -function svgSegmentWay(way, graph, activeID) { - var isActiveWay = (way.nodes.indexOf(activeID) !== -1); - var features = { passive: [], active: [] }; - var start = {}; - var end = {}; - var node, type; - - for (var i = 0; i < way.nodes.length; i++) { - node = graph.entity(way.nodes[i]); - type = svgPassiveVertex(node, graph, activeID); - end = { node: node, type: type }; - - if (start.type !== undefined) { - if (start.node.id === activeID || end.node.id === activeID) { - // push nothing - } else if (isActiveWay && (start.type === 2 || end.type === 2)) { // one adjacent vertex - pushActive(start, end, i); - } else if (start.type === 0 && end.type === 0) { // both active vertices - pushActive(start, end, i); - } else { - pushPassive(start, end, i); - } - } - start = end; - } + drawImages.enabled = function(_) { + if (!arguments.length) return svgMapillaryImages$$1.enabled; + svgMapillaryImages$$1.enabled = _; + if (svgMapillaryImages$$1.enabled) { + showLayer(); + } else { + hideLayer(); + } + dispatch.call('change'); + return this; + }; - return features; + drawImages.supported = function() { + return !!getService(); + }; - function pushActive(start, end, index) { - features.active.push({ - type: 'Feature', - id: way.id + '-' + index + '-nope', - properties: { - nope: true, - target: true, - entity: way, - nodes: [start.node, end.node], - index: index - }, - geometry: { - type: 'LineString', - coordinates: [start.node.loc, end.node.loc] - } - }); - } - function pushPassive(start, end, index) { - features.passive.push({ - type: 'Feature', - id: way.id + '-' + index, - properties: { - target: true, - entity: way, - nodes: [start.node, end.node], - index: index - }, - geometry: { - type: 'LineString', - coordinates: [start.node.loc, end.node.loc] - } - }); - } -} + init(); + return drawImages; + } -function svgPoints$$1(projection, context) { + function svgMapillarySigns(projection, context, dispatch) { + var throttledRedraw = throttle(function () { dispatch.call('change'); }, 1000); + var minZoom = 12; + var layer = select(null); + var _mapillary; - function markerPath(selection, klass) { - selection - .attr('class', klass) - .attr('transform', 'translate(-8, -23)') - .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'); - } - function sortY(a, b) { - return b.loc[1] - a.loc[1]; - } + function init() { + if (svgMapillarySigns.initialized) return; // run once + svgMapillarySigns.enabled = false; + svgMapillarySigns.initialized = true; + } - // Avoid exit/enter if we're just moving stuff around. - // The node will get a new version but we only need to run the update selection. - function fastEntityKey(d) { - var mode = context.mode(); - var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id); - return isMoving ? d.id : osmEntity$$1.key(d); - } + function getService() { + if (services.mapillary && !_mapillary) { + _mapillary = services.mapillary; + _mapillary.event.on('loadedSigns', throttledRedraw); + } else if (!services.mapillary && _mapillary) { + _mapillary = null; + } + return _mapillary; + } - function drawTargets(selection, graph, entities, filter) { - var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor '; - var getTransform = svgPointTransform(projection).geojson; - var activeID = context.activeID(); - var data$$1 = []; + function showLayer() { + var service = getService(); + if (!service) return; - entities.forEach(function(node) { - if (activeID === node.id) return; // draw no target on the activeID + service.loadViewer(context); + editOn(); + } - data$$1.push({ - type: 'Feature', - id: node.id, - properties: { - target: true, - entity: node - }, - geometry: node.asGeoJSON() - }); - }); - var targets = selection.selectAll('.point.target') - .filter(function(d) { return filter(d.properties.entity); }) - .data(data$$1, function key(d) { return d.id; }); + function hideLayer() { + throttledRedraw.cancel(); + editOff(); + } - // exit - targets.exit() - .remove(); - // enter/update - targets.enter() - .append('rect') - .attr('x', -10) - .attr('y', -26) - .attr('width', 20) - .attr('height', 30) - .merge(targets) - .attr('class', function(d) { return 'node point target ' + fillClass + d.id; }) - .attr('transform', getTransform); - } + function editOn() { + layer.style('display', 'block'); + } - function drawPoints(selection, graph, entities, filter) { - var wireframe = context.surface().classed('fill-wireframe'); - var zoom = geoScaleToZoom(projection.scale()); + function editOff() { + layer.selectAll('.icon-sign').remove(); + layer.style('display', 'none'); + } - // points with a direction will render as vertices at higher zooms - function renderAsPoint(entity) { - return entity.geometry(graph) === 'point' && - !(zoom >= 18 && entity.directions(graph, projection).length); - } - // all points will render as vertices in wireframe mode too - var points = wireframe ? [] : entities.filter(renderAsPoint); - - points.sort(sortY); - - - var layer = selection.selectAll('.layer-points .layer-points-points'); - - var groups = layer.selectAll('g.point') - .filter(filter) - .data(points, fastEntityKey); - - groups.exit() - .remove(); - - var enter = groups.enter() - .append('g') - .attr('class', function(d) { return 'node point ' + d.id; }) - .order(); - - enter - .append('path') - .call(markerPath, 'shadow'); - - enter - .append('ellipse') - .attr('cx', 0.5) - .attr('cy', 1) - .attr('rx', 6.5) - .attr('ry', 3) - .attr('class', 'stroke'); - - enter - .append('path') - .call(markerPath, 'stroke'); - - enter - .append('use') - .attr('transform', 'translate(-5, -19)') - .attr('class', 'icon') - .attr('width', '11px') - .attr('height', '11px'); - - groups = groups - .merge(enter) - .attr('transform', svgPointTransform(projection)) - .call(svgTagClasses()); - - // Selecting the following implicitly - // sets the data (point entity) on the element - groups.select('.shadow'); - groups.select('.stroke'); - groups.select('.icon') - .attr('xlink:href', function(entity) { - var preset = context.presets().match(entity, graph); - var picon = preset && preset.icon; - - if (!picon) - return ''; - else { - var isMaki = dataFeatureIcons.indexOf(picon) !== -1; - return '#' + picon + (isMaki ? '-11' : ''); - } - }); + function click(d) { + var service = getService(); + if (!service) return; + context.map().centerEase(d.loc); - // touch targets - selection.selectAll('.layer-points .layer-points-targets') - .call(drawTargets, graph, points, filter); - } + var selected = service.getSelectedImage(); + var selectedImageKey = selected && selected.key; + var imageKey; + // Pick one of the images the sign was detected in, + // preference given to an image already selected. + d.detections.forEach(function(detection) { + if (!imageKey || selectedImageKey === detection.image_key) { + imageKey = detection.image_key; + } + }); - return drawPoints; -} + service + .selectImage(null, imageKey) + .updateViewer(imageKey, context) + .showViewer(); + } -function svgTagClasses() { - var primaries = [ - 'building', 'highway', 'railway', 'waterway', 'aeroway', - 'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse', - 'leisure', 'military', 'place' - ], - statuses = [ - 'proposed', 'construction', 'disused', 'abandoned', 'dismantled', - 'razed', 'demolished', 'obliterated', 'intermittent' - ], - secondaries = [ - 'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier', - 'surface', 'tracktype', 'crossing', 'service', 'sport' - ], - tagClassRe = /^tag-/, - tags = function(entity) { return entity.tags; }; + function update() { + var service = getService(); + var data = (service ? service.signs(projection) : []); + var viewer = select('#photoviewer'); + var selected = viewer.empty() ? undefined : viewer.datum(); + var selectedImageKey = selected && selected.key; + + var signs = layer.selectAll('.icon-sign') + .data(data, function(d) { return d.key; }); + + signs.exit() + .remove(); + + var enter = signs.enter() + .append('foreignObject') + .attr('class', 'icon-sign') + .attr('width', '24px') // for Firefox + .attr('height', '24px') // for Firefox + .classed('selected', function(d) { + return some(d.detections, function(detection) { + return detection.image_key === selectedImageKey; + }); + }) + .on('click', click); + + enter + .append('xhtml:body') + .attr('class', 'icon-sign-body') + .html(service.signHTML); + + signs + .merge(enter) + .attr('x', function(d) { return projection(d.loc)[0] - 12; }) // offset by -12px to + .attr('y', function(d) { return projection(d.loc)[1] - 12; }); // center signs on loc + } - var tagClasses = function(selection$$1) { - selection$$1.each(function tagClassesEach(entity) { - var value = this.className, - classes, primary, status; - if (value.baseVal !== undefined) value = value.baseVal; + function drawSigns(selection$$1) { + var enabled = svgMapillarySigns.enabled, + service = getService(); - classes = value.trim().split(/\s+/).filter(function(name) { - return name.length && !tagClassRe.test(name); - }).join(' '); + layer = selection$$1.selectAll('.layer-mapillary-signs') + .data(service ? [0] : []); - var t = tags(entity), i, k, v; + layer.exit() + .remove(); - // pick at most one primary classification tag.. - for (i = 0; i < primaries.length; i++) { - k = primaries[i]; - v = t[k]; - if (!v || v === 'no') continue; + layer = layer.enter() + .append('g') + .attr('class', 'layer-mapillary-signs') + .style('display', enabled ? 'block' : 'none') + .merge(layer); - primary = k; - if (statuses.indexOf(v) !== -1) { // e.g. `railway=abandoned` - status = v; - classes += ' tag-' + k; - } else { - classes += ' tag-' + k + ' tag-' + k + '-' + v; - } + if (enabled) { + if (service && ~~context.map().zoom() >= minZoom) { + editOn(); + update(); + service.loadSigns(context, projection); + } else { + editOff(); + } + } + } - break; - } - // add at most one status tag, only if relates to primary tag.. - if (!status) { - for (i = 0; i < statuses.length; i++) { - k = statuses[i]; - v = t[k]; - if (!v || v === 'no') continue; - - if (v === 'yes') { // e.g. `railway=rail + abandoned=yes` - status = k; - } - else if (primary && primary === v) { // e.g. `railway=rail + abandoned=railway` - status = k; - } else if (!primary && primaries.indexOf(v) !== -1) { // e.g. `abandoned=railway` - status = k; - primary = v; - classes += ' tag-' + v; - } // else ignore e.g. `highway=path + abandoned=railway` - - if (status) break; - } - } + drawSigns.enabled = function(_) { + if (!arguments.length) return svgMapillarySigns.enabled; + svgMapillarySigns.enabled = _; + if (svgMapillarySigns.enabled) { + showLayer(); + } else { + hideLayer(); + } + dispatch.call('change'); + return this; + }; - if (status) { - classes += ' tag-status tag-status-' + status; - } - // add any secondary (structure) tags - for (i = 0; i < secondaries.length; i++) { - k = secondaries[i]; - v = t[k]; - if (!v || v === 'no') continue; - classes += ' tag-' + k + ' tag-' + k + '-' + v; - } + drawSigns.supported = function() { + var service = getService(); + return (service && service.signsSupported()); + }; - // For highways, look for surface tagging.. - if (primary === 'highway') { - var paved = (t.highway !== 'track'); - for (k in t) { - v = t[k]; - if (k in osmPavedTags) { - paved = !!osmPavedTags[k][v]; - break; - } - } - if (!paved) { - classes += ' tag-unpaved'; - } - } - classes = classes.trim(); + init(); + return drawSigns; + } - if (classes !== value) { - d3_select(this).attr('class', classes); - } - }); - }; + function svgOpenstreetcamImages$$1(projection, context, dispatch) { + var throttledRedraw = throttle(function () { dispatch.call('change'); }, 1000); + var minZoom = 12; + var minMarkerZoom = 16; + var minViewfieldZoom = 18; + var layer = select(null); + var _openstreetcam; - tagClasses.tags = function(_) { - if (!arguments.length) return tags; - tags = _; - return tagClasses; - }; + function init() { + if (svgOpenstreetcamImages$$1.initialized) return; // run once + svgOpenstreetcamImages$$1.enabled = false; + svgOpenstreetcamImages$$1.initialized = true; + } - return tagClasses; -} -function svgTurns(projection) { + function getService() { + if (services.openstreetcam && !_openstreetcam) { + _openstreetcam = services.openstreetcam; + _openstreetcam.event.on('loadedImages', throttledRedraw); + } else if (!services.openstreetcam && _openstreetcam) { + _openstreetcam = null; + } - return function drawTurns(selection, graph, turns) { + return _openstreetcam; + } - function icon(turn) { - var u = turn.u ? '-u' : ''; - if (turn.no) return '#turn-no' + u; - if (turn.only) return '#turn-only' + u; - return '#turn-yes' + u; - } - var layer = selection.selectAll('.data-layer-osm').selectAll('.layer-turns') - .data([0]); + function showLayer() { + var service = getService(); + if (!service) return; - layer = layer.enter() - .append('g') - .attr('class', 'layer-osm layer-turns') - .merge(layer); + service.loadViewer(context); + editOn(); + layer + .style('opacity', 0) + .transition() + .duration(250) + .style('opacity', 1) + .on('end', function () { dispatch.call('change'); }); + } - var groups = layer.selectAll('g.turn') - .data(turns, function(d) { return d.key; }); - groups.exit() - .remove(); + function hideLayer() { + var service = getService(); + if (service) { + service.hideViewer(); + } + throttledRedraw.cancel(); - var enter = groups.enter() - .append('g') - .attr('class', function(d) { return 'turn ' + d.key; }); + layer + .transition() + .duration(250) + .style('opacity', 0) + .on('end', editOff); + } - var nEnter = enter - .filter(function(d) { return !d.u; }); - nEnter.append('rect') - .attr('transform', 'translate(-22, -12)') - .attr('width', '44') - .attr('height', '24'); + function editOn() { + layer.style('display', 'block'); + } - nEnter.append('use') - .attr('transform', 'translate(-22, -12)') - .attr('width', '44') - .attr('height', '24'); + function editOff() { + layer.selectAll('.viewfield-group').remove(); + layer.style('display', 'none'); + } - var uEnter = enter - .filter(function(d) { return d.u; }); - uEnter.append('circle') - .attr('r', '16'); + function click(d) { + var service = getService(); + if (!service) return; - uEnter.append('use') - .attr('transform', 'translate(-16, -16)') - .attr('width', '32') - .attr('height', '32'); + service + .selectImage(d) + .updateViewer(d) + .showViewer(); + context.map().centerEase(d.loc); + } - groups = groups - .merge(enter); - groups - .attr('opacity', function(d) { - return d.direct === false ? '0.7' : null; - }) - .attr('transform', function(d) { - var pxRadius = 50; - var toWay = graph.entity(d.to.way); - var toPoints = graph.childNodes(toWay) - .map(function (n) { return n.loc; }) - .map(projection); - var toLength = geoPathLength(toPoints); - var mid = toLength / 2; // midpoint of destination way + function mouseover(d) { + var service = getService(); + if (service) service.setStyles(d); + } - var toNode = graph.entity(d.to.node); - var toVertex = graph.entity(d.to.vertex); - var a = geoAngle(toVertex, toNode, projection); - var o = projection(toVertex.loc); - var r = d.u ? 0 // u-turn: no radius - : !toWay.__via ? pxRadius // leaf way: put marker at pxRadius - : Math.min(mid, pxRadius); // via way: prefer pxRadius, fallback to mid for very short ways - return 'translate(' + (r * Math.cos(a) + o[0]) + ',' + (r * Math.sin(a) + o[1]) + ') ' + - 'rotate(' + a * 180 / Math.PI + ')'; - }); + function mouseout() { + var service = getService(); + if (service) service.setStyles(null); + } - groups.select('use') - .attr('xlink:href', icon); - groups.select('rect'); - groups.select('circle'); + function transform(d) { + var t = svgPointTransform(projection)(d); + if (d.ca) { + t += ' rotate(' + Math.floor(d.ca) + ',0,0)'; + } + return t; + } - return this; - }; -} - -function svgVertices$$1(projection, context) { - var radiuses = { - // z16-, z17, z18+, w/icon - shadow: [6, 7.5, 7.5, 12], - stroke: [2.5, 3.5, 3.5, 8], - fill: [1, 1.5, 1.5, 1.5] - }; - var _currHoverTarget; - var _currPersistent = {}; - var _currHover = {}; - var _prevHover = {}; - var _currSelected = {}; - var _prevSelected = {}; - var _radii = {}; + function update() { + var viewer = select('#photoviewer'); + var selected = viewer.empty() ? undefined : viewer.datum(); + + var z = ~~context.map().zoom(); + var showMarkers = (z >= minMarkerZoom); + var showViewfields = (z >= minViewfieldZoom); + + var service = getService(); + var sequences = (service ? service.sequences(projection) : []); + var images = (service && showMarkers ? service.images(projection) : []); + + var traces = layer.selectAll('.sequences').selectAll('.sequence') + .data(sequences, function(d) { return d.properties.key; }); + + // exit + traces.exit() + .remove(); + + // enter/update + traces = traces.enter() + .append('path') + .attr('class', 'sequence') + .merge(traces) + .attr('d', svgPath(projection).geojson); + + + var groups = layer.selectAll('.markers').selectAll('.viewfield-group') + .data(images, function(d) { return d.key; }); + + // exit + groups.exit() + .remove(); + + // enter + var groupsEnter = groups.enter() + .append('g') + .attr('class', 'viewfield-group') + .on('mouseover', mouseover) + .on('mouseout', mouseout) + .on('click', click); + + groupsEnter + .append('g') + .attr('class', 'viewfield-scale'); + + // update + var markers = groups + .merge(groupsEnter) + .sort(function(a, b) { + return (a === selected) ? 1 + : (b === selected) ? -1 + : b.loc[1] - a.loc[1]; // sort Y + }) + .attr('transform', transform) + .select('.viewfield-scale'); + + + markers.selectAll('circle') + .data([0]) + .enter() + .append('circle') + .attr('dx', '0') + .attr('dy', '0') + .attr('r', '6'); + + var viewfields = markers.selectAll('.viewfield') + .data(showViewfields ? [0] : []); + + viewfields.exit() + .remove(); + + viewfields.enter() // viewfields may or may not be drawn... + .insert('path', 'circle') // but if they are, draw below the circles + .attr('class', 'viewfield') + .attr('transform', 'scale(1.5,1.5),translate(-8, -13)') + .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'); + } - function sortY(a, b) { - return b.loc[1] - a.loc[1]; - } + function drawImages(selection$$1) { + var enabled = svgOpenstreetcamImages$$1.enabled, + service = getService(); - // Avoid exit/enter if we're just moving stuff around. - // The node will get a new version but we only need to run the update selection. - function fastEntityKey(d) { - var mode = context.mode(); - var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id); - return isMoving ? d.id : osmEntity$$1.key(d); - } + layer = selection$$1.selectAll('.layer-openstreetcam-images') + .data(service ? [0] : []); + layer.exit() + .remove(); - function draw(selection$$1, graph, vertices, sets, filter) { - sets = sets || { selected: {}, important: {}, hovered: {} }; + var layerEnter = layer.enter() + .append('g') + .attr('class', 'layer-openstreetcam-images') + .style('display', enabled ? 'block' : 'none'); - var icons = {}; - var directions = {}; - var wireframe = context.surface().classed('fill-wireframe'); - var zoom = geoScaleToZoom(projection.scale()); - var z = (zoom < 17 ? 0 : zoom < 18 ? 1 : 2); + layerEnter + .append('g') + .attr('class', 'sequences'); + layerEnter + .append('g') + .attr('class', 'markers'); - function getIcon(entity) { - if (entity.id in icons) return icons[entity.id]; + layer = layerEnter + .merge(layer); - icons[entity.id] = - entity.hasInterestingTags() && - context.presets().match(entity, graph).icon; - return icons[entity.id]; - } + if (enabled) { + if (service && ~~context.map().zoom() >= minZoom) { + editOn(); + update(); + service.loadImages(projection); + } else { + editOff(); + } + } + } - // memoize directions results, return false for empty arrays (for use in filter) - function getDirections(entity) { - if (entity.id in directions) return directions[entity.id]; + drawImages.enabled = function(_) { + if (!arguments.length) return svgOpenstreetcamImages$$1.enabled; + svgOpenstreetcamImages$$1.enabled = _; + if (svgOpenstreetcamImages$$1.enabled) { + showLayer(); + } else { + hideLayer(); + } + dispatch.call('change'); + return this; + }; - var angles = entity.directions(graph, projection); - directions[entity.id] = angles.length ? angles : false; - return angles; - } + drawImages.supported = function() { + return !!getService(); + }; - function updateAttributes(selection$$1) { - ['shadow', 'stroke', 'fill'].forEach(function(klass) { - var rads = radiuses[klass]; - selection$$1.selectAll('.' + klass) - .each(function(entity) { - var i = z && getIcon(entity); - var r = rads[i ? 3 : z]; - // slightly increase the size of unconnected endpoints #3775 - if (entity.isEndpoint(graph) && !entity.isConnected(graph)) { - r += 1.5; - } + init(); + return drawImages; + } - if (klass === 'shadow') { // remember this value, so we don't need to - _radii[entity.id] = r; // recompute it when we draw the touch targets - } + function svgOsm(projection, context, dispatch) { + var enabled = true; + + + function drawOsm(selection) { + selection.selectAll('.layer-osm') + .data(['covered', 'areas', 'lines', 'points', 'labels']) + .enter() + .append('g') + .attr('class', function(d) { return 'layer-osm layer-' + d; }); + + selection.selectAll('.layer-areas').selectAll('.layer-areas-group') + .data(['areas', 'targets']) + .enter() + .append('g') + .attr('class', function(d) { return 'layer-areas-group layer-areas-' + d; }); + + selection.selectAll('.layer-lines').selectAll('.layer-lines-group') + .data(['lines', 'targets']) + .enter() + .append('g') + .attr('class', function(d) { return 'layer-lines-group layer-lines-' + d; }); + + selection.selectAll('.layer-points').selectAll('.layer-points-group') + .data(['points', 'midpoints', 'vertices', 'turns', 'targets']) + .enter() + .append('g') + .attr('class', function(d) { return 'layer-points-group layer-points-' + d; }); + + selection.selectAll('.layer-labels').selectAll('.layer-labels-group') + .data(['halo', 'label', 'debug']) + .enter() + .append('g') + .attr('class', function(d) { return 'layer-labels-group layer-labels-' + d; }); + } - d3_select(this) - .attr('r', r) - .attr('visibility', (i && klass === 'fill') ? 'hidden' : null); - }); - }); - selection$$1.selectAll('use') - .attr('visibility', (z === 0 ? 'hidden' : null)); - } + function showLayer() { + var layer = context.surface().selectAll('.data-layer-osm'); + layer.interrupt(); - vertices.sort(sortY); - - var groups = selection$$1.selectAll('g.vertex') - .filter(filter) - .data(vertices, fastEntityKey); - - // exit - groups.exit() - .remove(); - - // enter - var enter = groups.enter() - .append('g') - .attr('class', function(d) { return 'node vertex ' + d.id; }) - .order(); - - enter - .append('circle') - .attr('class', 'shadow'); - - enter - .append('circle') - .attr('class', 'stroke'); - - // Vertices with icons get a `use`. - enter.filter(function(d) { return getIcon(d); }) - .append('use') - .attr('class', 'icon') - .attr('width', '11px') - .attr('height', '11px') - .attr('transform', 'translate(-5.5, -5.5)') - .attr('xlink:href', function(d) { - var picon = getIcon(d); - var isMaki = dataFeatureIcons.indexOf(picon) !== -1; - return '#' + picon + (isMaki ? '-11' : ''); - }); + layer + .classed('disabled', false) + .style('opacity', 0) + .transition() + .duration(250) + .style('opacity', 1) + .on('end interrupt', function () { + dispatch.call('change'); + }); + } - // Vertices with tags get a fill. - enter.filter(function(d) { return d.hasInterestingTags(); }) - .append('circle') - .attr('class', 'fill'); - - // update - groups = groups - .merge(enter) - .attr('transform', svgPointTransform(projection)) - .classed('sibling', function(d) { return d.id in sets.selected; }) - .classed('shared', function(d) { return graph.isShared(d); }) - .classed('endpoint', function(d) { return d.isEndpoint(graph); }) - .call(updateAttributes); - - - // Directional vertices get viewfields - var dgroups = groups.filter(function(d) { return getDirections(d); }) - .selectAll('.viewfieldgroup') - .data(function data$$1(d) { return zoom >= 18 ? [d] : []; }, osmEntity$$1.key); - - // exit - dgroups.exit() - .remove(); - - // enter/update - dgroups = dgroups.enter() - .insert('g', '.shadow') - .attr('class', 'viewfieldgroup') - .merge(dgroups); - - var viewfields = dgroups.selectAll('.viewfield') - .data(getDirections, function key(d) { return d; }); - - // exit - viewfields.exit() - .remove(); - - // enter/update - viewfields.enter() - .append('path') - .attr('class', 'viewfield') - .attr('d', 'M0,0H0') - .merge(viewfields) - .attr('marker-start', 'url(#viewfield-marker' + (wireframe ? '-wireframe' : '') + ')') - .attr('transform', function(d) { return 'rotate(' + d + ')'; }); - } - - - function drawTargets(selection$$1, graph, entities, filter) { - var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor '; - var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor '; - var getTransform = svgPointTransform(projection).geojson; - var activeID = context.activeID(); - var data$$1 = { targets: [], nopes: [] }; - - entities.forEach(function(node) { - if (activeID === node.id) return; // draw no target on the activeID - - var vertexType = svgPassiveVertex(node, graph, activeID); - if (vertexType !== 0) { // passive or adjacent - allow to connect - data$$1.targets.push({ - type: 'Feature', - id: node.id, - properties: { - target: true, - entity: node - }, - geometry: node.asGeoJSON() - }); - } else { - data$$1.nopes.push({ - type: 'Feature', - id: node.id + '-nope', - properties: { - nope: true, - target: true, - entity: node - }, - geometry: node.asGeoJSON() - }); - } - }); + function hideLayer() { + var layer = context.surface().selectAll('.data-layer-osm'); + layer.interrupt(); - // Targets allow hover and vertex snapping - var targets = selection$$1.selectAll('.vertex.target-allowed') - .filter(function(d) { return filter(d.properties.entity); }) - .data(data$$1.targets, function key(d) { return d.id; }); - - // exit - targets.exit() - .remove(); - - // enter/update - targets.enter() - .append('circle') - .attr('r', function(d) { return (_radii[d.id] || radiuses.shadow[3]); }) - .merge(targets) - .attr('class', function(d) { return 'node vertex target target-allowed ' + targetClass + d.id; }) - .attr('transform', getTransform); - - - // NOPE - var nopes = selection$$1.selectAll('.vertex.target-nope') - .filter(function(d) { return filter(d.properties.entity); }) - .data(data$$1.nopes, function key(d) { return d.id; }); - - // exit - nopes.exit() - .remove(); - - // enter/update - nopes.enter() - .append('circle') - .attr('r', function(d) { return (_radii[d.properties.entity.id] || radiuses.shadow[3]); }) - .merge(nopes) - .attr('class', function(d) { return 'node vertex target target-nope ' + nopeClass + d.id; }) - .attr('transform', getTransform); - } - - - // Points can also render as vertices: - // 1. in wireframe mode or - // 2. at higher zooms if they have a direction - function renderAsVertex(entity, graph, wireframe, zoom) { - var geometry = entity.geometry(graph); - return geometry === 'vertex' || (geometry === 'point' && ( - wireframe || (zoom >= 18 && entity.directions(graph, projection).length) - )); - } - - - function getSiblingAndChildVertices(ids, graph, wireframe, zoom) { - var results = {}; - - function addChildVertices(entity) { - var geometry = entity.geometry(graph); - if (!context.features().isHiddenFeature(entity, graph, geometry)) { - var i; - if (entity.type === 'way') { - for (i = 0; i < entity.nodes.length; i++) { - var child = graph.hasEntity(entity.nodes[i]); - if (child) { - addChildVertices(child); - } - } - } else if (entity.type === 'relation') { - for (i = 0; i < entity.members.length; i++) { - var member = graph.hasEntity(entity.members[i].id); - if (member) { - addChildVertices(member); - } - } - } else if (renderAsVertex(entity, graph, wireframe, zoom)) { - results[entity.id] = entity; - } - } - } + layer + .transition() + .duration(250) + .style('opacity', 0) + .on('end interrupt', function () { + layer.classed('disabled', true); + dispatch.call('change'); + }); + } - ids.forEach(function(id) { - var entity = graph.hasEntity(id); - if (!entity) return; - - if (entity.type === 'node') { - if (renderAsVertex(entity, graph, wireframe, zoom)) { - results[entity.id] = entity; - graph.parentWays(entity).forEach(function(entity) { - addChildVertices(entity); - }); - } - } else { // way, relation - addChildVertices(entity); - } - }); - return results; - } + drawOsm.enabled = function(_) { + if (!arguments.length) return enabled; + enabled = _; + if (enabled) { + showLayer(); + } else { + hideLayer(); + } - function drawVertices(selection$$1, graph, entities, filter, extent, fullRedraw) { - var wireframe = context.surface().classed('fill-wireframe'); - var zoom = geoScaleToZoom(projection.scale()); - var mode = context.mode(); - var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id); + dispatch.call('change'); + return this; + }; - if (fullRedraw) { - _currPersistent = {}; - _radii = {}; - } - // Collect important vertices from the `entities` list.. - // (during a paritial redraw, it will not contain everything) - for (var i = 0; i < entities.length; i++) { - var entity = entities[i]; - var geometry = entity.geometry(graph); - var keep = false; - - // a point that looks like a vertex.. - if ((geometry === 'point') && renderAsVertex(entity, graph, wireframe, zoom)) { - _currPersistent[entity.id] = entity; - keep = true; - - // a vertex of some importance.. - } else if (geometry === 'vertex' && - (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph))) { - _currPersistent[entity.id] = entity; - keep = true; - } + return drawOsm; + } - // whatever this is, it's not a persistent vertex.. - if (!keep && !fullRedraw) { - delete _currPersistent[entity.id]; - } - } + function svgLayers(projection, context) { + var dispatch$$1 = dispatch('change'), + svg = select(null), + layers = [ + { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) }, + { id: 'gpx', layer: svgGpx$$1(projection, context, dispatch$$1) }, + { id: 'mapillary-images', layer: svgMapillaryImages$$1(projection, context, dispatch$$1) }, + { id: 'mapillary-signs', layer: svgMapillarySigns(projection, context, dispatch$$1) }, + { id: 'openstreetcam-images', layer: svgOpenstreetcamImages$$1(projection, context, dispatch$$1) }, + { id: 'debug', layer: svgDebug$$1(projection, context, dispatch$$1) } + ]; - // 3 sets of vertices to consider: - var sets = { - persistent: _currPersistent, // persistent = important vertices (render always) - selected: _currSelected, // selected + siblings of selected (render always) - hovered: _currHover // hovered + siblings of hovered (render only in draw modes) - }; - var all = assign({}, (isMoving ? _currHover : {}), _currSelected, _currPersistent); + function drawLayers(selection$$1) { + svg = selection$$1.selectAll('.surface') + .data([0]); - // Draw the vertices.. - // The filter function controls the scope of what objects d3 will touch (exit/enter/update) - // Adjust the filter function to expand the scope beyond whatever entities were passed in. - var filterRendered = function(d) { - return d.id in _currPersistent || d.id in _currSelected || d.id in _currHover || filter(d); - }; - selection$$1.selectAll('.layer-points .layer-points-vertices') - .call(draw, graph, currentVisible(all), sets, filterRendered); + svg = svg.enter() + .append('svg') + .attr('class', 'surface') + .merge(svg); - // Draw touch targets.. - // When drawing, render all targets (not just those affected by a partial redraw) - var filterTouch = function(d) { - return isMoving ? true : filterRendered(d); - }; - selection$$1.selectAll('.layer-points .layer-points-targets') - .call(drawTargets, graph, currentVisible(all), filterTouch); + var defs = svg.selectAll('.surface-defs') + .data([0]); + defs.enter() + .append('defs') + .attr('class', 'surface-defs'); - function currentVisible(which) { - return Object.keys(which) - .map(graph.hasEntity, graph) // the current version of this entity - .filter(function (entity) { return entity && entity.intersects(extent, graph); }); - } - } + var groups = svg.selectAll('.data-layer') + .data(layers); + groups.exit() + .remove(); - // partial redraw - only update the selected items.. - drawVertices.drawSelected = function(selection$$1, graph, extent) { - var wireframe = context.surface().classed('fill-wireframe'); - var zoom = geoScaleToZoom(projection.scale()); + groups.enter() + .append('g') + .attr('class', function(d) { return 'data-layer data-layer-' + d.id; }) + .merge(groups) + .each(function(d) { select(this).call(d.layer); }); + } - _prevSelected = _currSelected || {}; - _currSelected = getSiblingAndChildVertices(context.selectedIDs(), graph, wireframe, zoom); - // note that drawVertices will add `_currSelected` automatically if needed.. - var filter = function(d) { return d.id in _prevSelected; }; - drawVertices(selection$$1, graph, values$1(_prevSelected), filter, extent, false); - }; + drawLayers.all = function() { + return layers; + }; - // partial redraw - only update the hovered items.. - drawVertices.drawHover = function(selection$$1, graph, target, extent) { - if (target === _currHoverTarget) return; // continue only if something changed + drawLayers.layer = function(id) { + var obj = find$1(layers, function(o) {return o.id === id;}); + return obj && obj.layer; + }; - var wireframe = context.surface().classed('fill-wireframe'); - var zoom = geoScaleToZoom(projection.scale()); - _prevHover = _currHover || {}; - _currHoverTarget = target; - var entity = target && target.properties && target.properties.entity; + drawLayers.only = function(what) { + var arr = [].concat(what); + drawLayers.remove(difference(map$3(layers, 'id'), arr)); + return this; + }; - if (entity) { - _currHover = getSiblingAndChildVertices([entity.id], graph, wireframe, zoom); - } else { - _currHover = {}; - } - // note that drawVertices will add `_currHover` automatically if needed.. - var filter = function(d) { return d.id in _prevHover; }; - drawVertices(selection$$1, graph, values$1(_prevHover), filter, extent, false); - }; + drawLayers.remove = function(what) { + var arr = [].concat(what); + arr.forEach(function(id) { + layers = reject(layers, function(o) {return o.id === id;}); + }); + dispatch$$1.call('change'); + return this; + }; - return drawVertices; -} -function uiAccount(context) { - var osm = context.connection(); + drawLayers.add = function(what) { + var arr = [].concat(what); + arr.forEach(function(obj) { + if ('id' in obj && 'layer' in obj) { + layers.push(obj); + } + }); + dispatch$$1.call('change'); + return this; + }; - function update(selection$$1) { - if (!osm) return; + drawLayers.dimensions = function(_) { + if (!arguments.length) return utilGetDimensions(svg); + utilSetDimensions(svg, _); + return this; + }; - if (!osm.authenticated()) { - selection$$1.selectAll('#userLink, #logoutLink') - .classed('hide', true); - return; - } - osm.userDetails(function(err, details) { - var userLink = selection$$1.select('#userLink'), - logoutLink = selection$$1.select('#logoutLink'); + return utilRebind(drawLayers, dispatch$$1, 'on'); + } - userLink.html(''); - logoutLink.html(''); + function svgLines$$1(projection, context) { + var detected = utilDetect(); + + var highway_stack = { + motorway: 0, + motorway_link: 1, + trunk: 2, + trunk_link: 3, + primary: 4, + primary_link: 5, + secondary: 6, + tertiary: 7, + unclassified: 8, + residential: 9, + service: 10, + footway: 11 + }; - if (err) return; - selection$$1.selectAll('#userLink, #logoutLink') - .classed('hide', false); + function drawTargets(selection, graph, entities, filter$$1) { + var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor '; + var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor '; + var getPath = svgPath(projection).geojson; + var activeID = context.activeID(); - // Link - userLink.append('a') - .attr('href', osm.userURL(details.display_name)) - .attr('target', '_blank'); + // The targets and nopes will be MultiLineString sub-segments of the ways + var data = { targets: [], nopes: [] }; - // Add thumbnail or dont - if (details.image_url) { - userLink.append('img') - .attr('class', 'icon pre-text user-icon') - .attr('src', details.image_url); - } else { - userLink - .call(svgIcon('#icon-avatar', 'pre-text light')); - } + entities.forEach(function(way) { + var features = svgSegmentWay(way, graph, activeID); + data.targets.push.apply(data.targets, features.passive); + data.nopes.push.apply(data.nopes, features.active); + }); - // Add user name - userLink.append('span') - .attr('class', 'label') - .text(details.display_name); - - logoutLink.append('a') - .attr('class', 'logout') - .attr('href', '#') - .text(t('logout')) - .on('click.logout', function() { - event.preventDefault(); - osm.logout(); - }); - }); - } + // Targets allow hover and vertex snapping + var targetData = data.targets.filter(getPath); + var targets = selection.selectAll('.line.target-allowed') + .filter(function(d) { return filter$$1(d.properties.entity); }) + .data(targetData, function key(d) { return d.id; }); + + // exit + targets.exit() + .remove(); + + // enter/update + targets.enter() + .append('path') + .merge(targets) + .attr('d', getPath) + .attr('class', function(d) { return 'way line target target-allowed ' + targetClass + d.id; }); + + + // NOPE + var nopeData = data.nopes.filter(getPath); + var nopes = selection.selectAll('.line.target-nope') + .filter(function(d) { return filter$$1(d.properties.entity); }) + .data(nopeData, function key(d) { return d.id; }); + + // exit + nopes.exit() + .remove(); + + // enter/update + nopes.enter() + .append('path') + .merge(nopes) + .attr('d', getPath) + .attr('class', function(d) { return 'way line target target-nope ' + nopeClass + d.id; }); + } - return function(selection$$1) { - selection$$1.append('li') - .attr('id', 'logoutLink') - .classed('hide', true); - selection$$1.append('li') - .attr('id', 'userLink') - .classed('hide', true); + function drawLines(selection, graph, entities, filter$$1) { - if (osm) { - osm.on('change.account', function() { update(selection$$1); }); - update(selection$$1); - } - }; -} - -function uiAttribution(context) { - var selection$$1; - - - function attribution(data, klass) { - var div = selection$$1.selectAll('.' + klass) - .data([0]); - - div = div.enter() - .append('div') - .attr('class', klass) - .merge(div); - - - var background = div.selectAll('.attribution') - .data(data, function(d) { return d.name(); }); - - background.exit() - .remove(); - - background = background.enter() - .append('span') - .attr('class', 'attribution') - .each(function(d) { - if (d.terms_html) { - d3_select(this) - .html(d.terms_html); - return; - } - - var selection$$1; - if (d.terms_url) { - selection$$1 = d3_select(this) - .append('a') - .attr('href', d.terms_url) - .attr('target', '_blank'); - } else { - selection$$1 = d3_select(this); - } - - - var id_safe = d.id.replace('.', ''); - var terms_text = t('imagery.' + id_safe + '.attribution.text', - { default: d.terms_text || d.id || d.name() } - ); - - if (d.icon && !d.overlay) { - selection$$1 - .append('img') - .attr('class', 'source-image') - .attr('src', d.icon); - } - - selection$$1 - .append('span') - .attr('class', 'attribution-text') - .text(terms_text); - }) - .merge(background); + function waystack(a, b) { + var selected = context.selectedIDs(); + var scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0; + var scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0; + if (a.tags.highway) { scoreA -= highway_stack[a.tags.highway]; } + if (b.tags.highway) { scoreB -= highway_stack[b.tags.highway]; } + return scoreA - scoreB; + } - var copyright = background.selectAll('.copyright-notice') - .data(function(d) { - var notice = d.copyrightNotices(context.map().zoom(), context.map().extent()); - return notice ? [notice] : []; - }); - copyright.exit() - .remove(); + function drawLineGroup(selection, klass, isSelected) { + // Note: Don't add `.selected` class in draw modes + var mode = context.mode(); + var isDrawing = mode && /^draw/.test(mode.id); + var selectedClass = (!isDrawing && isSelected) ? 'selected ' : ''; + + var lines = selection + .selectAll('path') + .filter(filter$$1) + .data(getPathData(isSelected), osmEntity$$1.key); + + lines.exit() + .remove(); + + // Optimization: Call expensive TagClasses only on enter selection. This + // works because osmEntity.key is defined to include the entity v attribute. + lines.enter() + .append('path') + .attr('class', function(d) { + var oldMPClass = oldMultiPolygonOuters[d.id] ? 'old-multipolygon ' : ''; + return 'way line ' + klass + ' ' + selectedClass + oldMPClass + d.id; + }) + .call(svgTagClasses()) + .merge(lines) + .sort(waystack) + .attr('d', getPath) + .call(svgTagClasses().tags(svgRelationMemberTags(graph))); + + return selection; + } - copyright = copyright.enter() - .append('span') - .attr('class', 'copyright-notice') - .merge(copyright); - copyright - .text(String); - } + function getPathData(isSelected) { + return function() { + var layer = this.parentNode.__data__; + var data = pathdata[layer] || []; + return data.filter(function(d) { + if (isSelected) + return context.selectedIDs().indexOf(d.id) !== -1; + else + return context.selectedIDs().indexOf(d.id) === -1; + }); + }; + } - function update() { - attribution([context.background().baseLayerSource()], 'base-layer-attribution'); - attribution(context.background().overlayLayerSources().filter(function (s) { - return s.validZoom(context.map().zoom()); - }), 'overlay-layer-attribution'); - } + var getPath = svgPath(projection, graph); + var ways = []; + var pathdata = {}; + var onewaydata = {}; + var oldMultiPolygonOuters = {}; + + for (var i = 0; i < entities.length; i++) { + var entity = entities[i]; + var outer = osmSimpleMultipolygonOuterMember(entity, graph); + if (outer) { + ways.push(entity.mergeTags(outer.tags)); + oldMultiPolygonOuters[outer.id] = true; + } else if (entity.geometry(graph) === 'line') { + ways.push(entity); + } + } + + ways = ways.filter(getPath); + pathdata = groupBy(ways, function(way) { return way.layer(); }); + forOwn(pathdata, function(v, k) { + var arr = filter(v, function(d) { return d.isOneWay(); }); + onewaydata[k] = flatten(map$3(arr, svgOneWaySegments(projection, graph, 35))); + }); - return function(select$$1) { - selection$$1 = select$$1; - context.background() - .on('change.attribution', update); + var covered = selection.selectAll('.layer-covered'); // under areas + var uncovered = selection.selectAll('.layer-lines .layer-lines-lines'); // over areas - context.map() - .on('move.attribution', throttle(update, 400, {leading: false})); + [covered, uncovered].forEach(function(selection) { + var range$$1 = (selection === covered ? range(-10,0) : range(0,11)); + var layergroup = selection + .selectAll('g.layergroup') + .data(range$$1); - update(); - }; -} - -// toggles the visibility of ui elements, using a combination of the -// hide class, which sets display=none, and a d3 transition for opacity. -// this will cause blinking when called repeatedly, so check that the -// value actually changes between calls. -function uiToggle(show, callback) { - return function(selection$$1) { - selection$$1 - .style('opacity', show ? 0 : 1) - .classed('hide', false) - .transition() - .style('opacity', show ? 1 : 0) - .on('end', function() { - d3_select(this) - .classed('hide', !show) - .style('opacity', null); - if (callback) callback.apply(this); - }); - }; -} - -function uiDisclosure(context, key, expandedDefault) { - var dispatch$$1 = dispatch('toggled'), - _preference = (context.storage('disclosure.' + key + '.expanded')), - _expanded = (_preference === null ? !!expandedDefault : (_preference === 'true')), - _title, - _updatePreference = true, - _content = function () {}; - - - var disclosure = function(selection$$1) { - var hideToggle = selection$$1.selectAll('.hide-toggle-' + key) - .data([0]); - - // enter - var hideToggleEnter = hideToggle.enter() - .append('a') - .attr('href', '#') - .attr('class', 'hide-toggle hide-toggle-' + key) - .call(svgIcon('', 'pre-text', 'hide-toggle-icon')); - - hideToggleEnter - .append('span') - .attr('class', 'hide-toggle-text'); - - // update - hideToggle = hideToggleEnter - .merge(hideToggle); - - hideToggle - .on('click', toggle) - .classed('expanded', _expanded); - - hideToggle.selectAll('.hide-toggle-text') - .text(_title); - - hideToggle.selectAll('.hide-toggle-icon') - .attr('xlink:href', _expanded ? '#icon-down' - : (textDirection === 'rtl') ? '#icon-backward' : '#icon-forward' - ); + layergroup = layergroup.enter() + .append('g') + .attr('class', function(d) { return 'layergroup layer' + String(d); }) + .merge(layergroup); + layergroup + .selectAll('g.linegroup') + .data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted']) + .enter() + .append('g') + .attr('class', function(d) { return 'linegroup line-' + d; }); + + layergroup.selectAll('g.line-shadow') + .call(drawLineGroup, 'shadow', false); + layergroup.selectAll('g.line-casing') + .call(drawLineGroup, 'casing', false); + layergroup.selectAll('g.line-stroke') + .call(drawLineGroup, 'stroke', false); + + layergroup.selectAll('g.line-shadow-highlighted') + .call(drawLineGroup, 'shadow', true); + layergroup.selectAll('g.line-casing-highlighted') + .call(drawLineGroup, 'casing', true); + layergroup.selectAll('g.line-stroke-highlighted') + .call(drawLineGroup, 'stroke', true); + + + var onewaygroup = layergroup + .selectAll('g.onewaygroup') + .data(['oneway']); + + onewaygroup = onewaygroup.enter() + .append('g') + .attr('class', 'onewaygroup') + .merge(onewaygroup); + + var oneways = onewaygroup + .selectAll('path') + .filter(filter$$1) + .data( + function data() { return onewaydata[this.parentNode.__data__] || []; }, + function key(d) { return [d.id, d.index]; } + ); + + oneways.exit() + .remove(); + + oneways = oneways.enter() + .append('path') + .attr('class', 'oneway') + .attr('marker-mid', 'url(#oneway-marker)') + .merge(oneways) + .attr('d', function(d) { return d.d; }); + + if (detected.ie) { + oneways.each(function() { this.parentNode.insertBefore(this, this); }); + } + }); - var wrap = selection$$1.selectAll('.disclosure-wrap') - .data([0]); + // touch targets + selection.selectAll('.layer-lines .layer-lines-targets') + .call(drawTargets, graph, ways, filter$$1); + } - wrap = wrap.enter() - .append('div') - .attr('class', 'disclosure-wrap disclosure-wrap-' + key) - .merge(wrap); - wrap - .classed('hide', !_expanded) - .call(_content); + return drawLines; + } + function svgMidpoints$$1(projection, context) { + var targetRadius = 8; + + function drawTargets(selection, graph, entities, filter) { + var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor '; + var getTransform = svgPointTransform(projection).geojson; + + var data = entities.map(function(midpoint) { + return { + type: 'Feature', + id: midpoint.id, + properties: { + target: true, + entity: midpoint + }, + geometry: { + type: 'Point', + coordinates: midpoint.loc + } + }; + }); - function toggle() { - event.preventDefault(); + var targets = selection.selectAll('.midpoint.target') + .filter(function(d) { return filter(d.properties.entity); }) + .data(data, function key(d) { return d.id; }); + + // exit + targets.exit() + .remove(); + + // enter/update + targets.enter() + .append('circle') + .attr('r', targetRadius) + .merge(targets) + .attr('class', function(d) { return 'node midpoint target ' + fillClass + d.id; }) + .attr('transform', getTransform); + } - _expanded = !_expanded; - if (_updatePreference) { - context.storage('disclosure.' + key + '.expanded', _expanded); - } + function drawMidpoints(selection, graph, entities, filter, extent) { + var layer = selection.selectAll('.layer-points .layer-points-midpoints'); - hideToggle - .classed('expanded', _expanded); + var mode = context.mode(); + if (mode && mode.id !== 'select') { + layer.selectAll('g.midpoint') + .remove(); - hideToggle.selectAll('.hide-toggle-icon') - .attr('xlink:href', _expanded ? '#icon-down' - : (textDirection === 'rtl') ? '#icon-backward' : '#icon-forward' - ); + selection.selectAll('.layer-points .layer-points-targets .midpoint.target') + .remove(); - wrap - .call(uiToggle(_expanded)); + return; + } - dispatch$$1.call('toggled', this, _expanded); - } - }; + var poly = extent.polygon(); + var midpoints = {}; + + for (var i = 0; i < entities.length; i++) { + var entity = entities[i]; + + if (entity.type !== 'way') + continue; + if (!filter(entity)) + continue; + if (context.selectedIDs().indexOf(entity.id) < 0) + continue; + + var nodes = graph.childNodes(entity); + for (var j = 0; j < nodes.length - 1; j++) { + + var a = nodes[j]; + var b = nodes[j + 1]; + var id = [a.id, b.id].sort().join('-'); + + if (midpoints[id]) { + midpoints[id].parents.push(entity); + } else { + if (geoVecLength(projection(a.loc), projection(b.loc)) > 40) { + var point = geoVecInterp(a.loc, b.loc, 0.5); + var loc = null; + + if (extent.intersects(point)) { + loc = point; + } else { + for (var k = 0; k < 4; k++) { + point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]); + if (point && + geoVecLength(projection(a.loc), projection(point)) > 20 && + geoVecLength(projection(b.loc), projection(point)) > 20) + { + loc = point; + break; + } + } + } + + if (loc) { + midpoints[id] = { + type: 'midpoint', + id: id, + loc: loc, + edge: [a.id, b.id], + parents: [entity] + }; + } + } + } + } + } - disclosure.title = function(_) { - if (!arguments.length) return _title; - _title = _; - return disclosure; - }; + function midpointFilter(d) { + if (midpoints[d.id]) + return true; + for (var i = 0; i < d.parents.length; i++) { + if (filter(d.parents[i])) { + return true; + } + } - disclosure.expanded = function(_) { - if (!arguments.length) return _expanded; - _expanded = _; - return disclosure; - }; + return false; + } - disclosure.updatePreference = function(_) { - if (!arguments.length) return _updatePreference; - _updatePreference = _; - return disclosure; - }; + var groups = layer + .selectAll('g.midpoint') + .filter(midpointFilter) + .data(values$1(midpoints), function(d) { return d.id; }); + + groups.exit() + .remove(); + + var enter = groups.enter() + .insert('g', ':first-child') + .attr('class', 'midpoint'); + + enter + .append('polygon') + .attr('points', '-6,8 10,0 -6,-8') + .attr('class', 'shadow'); + + enter + .append('polygon') + .attr('points', '-3,4 5,0 -3,-4') + .attr('class', 'fill'); + + groups = groups + .merge(enter) + .attr('transform', function(d) { + var translate = svgPointTransform(projection); + var a = graph.entity(d.edge[0]); + var b = graph.entity(d.edge[1]); + var angle = geoAngle(a, b, projection) * (180 / Math.PI); + return translate(d) + ' rotate(' + angle + ')'; + }) + .call(svgTagClasses().tags( + function(d) { return d.parents[0].tags; } + )); + + // Propagate data bindings. + groups.select('polygon.shadow'); + groups.select('polygon.fill'); + + + // Draw touch targets.. + selection.selectAll('.layer-points .layer-points-targets') + .call(drawTargets, graph, values$1(midpoints), midpointFilter); + } + return drawMidpoints; + } - disclosure.content = function(_) { - if (!arguments.length) return _content; - _content = _; - return disclosure; - }; + // Touch targets control which other vertices we can drag a vertex onto. + // + // - the activeID - nope + // - 1 away (adjacent) to the activeID - yes (vertices will be merged) + // - 2 away from the activeID - nope (would create a self intersecting segment) + // - all others on a linear way - yes + // - all others on a closed way - nope (would create a self intersecting polygon) + // + // returns + // 0 = active vertex - no touch/connect + // 1 = passive vertex - yes touch/connect + // 2 = adjacent vertex - yes but pay attention segmenting a line here + // + function svgPassiveVertex(node, graph, activeID) { + if (!activeID) return 1; + if (activeID === node.id) return 0; + + var parents = graph.parentWays(node); + + for (var i = 0; i < parents.length; i++) { + var nodes = parents[i].nodes; + var isClosed = parents[i].isClosed(); + for (var j = 0; j < nodes.length; j++) { // find this vertex, look nearby + if (nodes[j] === node.id) { + var ix1 = j - 2; + var ix2 = j - 1; + var ix3 = j + 1; + var ix4 = j + 2; + + if (isClosed) { // wraparound if needed + var max = nodes.length - 1; + if (ix1 < 0) ix1 = max + ix1; + if (ix2 < 0) ix2 = max + ix2; + if (ix3 > max) ix3 = ix3 - max; + if (ix4 > max) ix4 = ix4 - max; + } + + if (nodes[ix1] === activeID) return 0; // no - prevent self intersect + else if (nodes[ix2] === activeID) return 2; // ok - adjacent + else if (nodes[ix3] === activeID) return 2; // ok - adjacent + else if (nodes[ix4] === activeID) return 0; // no - prevent self intersect + else if (isClosed && nodes.indexOf(activeID) !== -1) return 0; // no - prevent self intersect + } + } + } + return 1; // ok + } - return utilRebind(disclosure, dispatch$$1, 'on'); -} -function uiBackgroundDisplayOptions(context) { - var detected = utilDetect(); - var storedOpacity = context.storage('background-opacity'); - var minVal = 0.25; - var maxVal = detected.cssfilters ? 2 : 1; + function svgOneWaySegments(projection$$1, graph, dt) { + return function(entity) { + var i = 0; + var offset = dt; + var segments = []; + var clip = d3_geoIdentity().clipExtent(projection$$1.clipExtent()).stream; + var coordinates = graph.childNodes(entity).map(function(n) { return n.loc; }); + var a, b; - var sliders = detected.cssfilters - ? ['brightness', 'contrast', 'saturation', 'sharpness'] - : ['brightness']; + if (entity.tags.oneway === '-1') { + coordinates.reverse(); + } - var _options = { - brightness: (storedOpacity !== null ? (+storedOpacity) : 1), - contrast: 1, - saturation: 1, - sharpness: 1 - }; + var isReversible = (entity.tags.oneway === 'reversible' || entity.tags.oneway === 'alternating'); + + geoStream({ + type: 'LineString', + coordinates: coordinates + }, projection$$1.stream(clip({ + lineStart: function() {}, + lineEnd: function() { a = null; }, + point: function(x, y) { + b = [x, y]; + + if (a) { + var span = geoVecLength(a, b) - offset; + + if (span >= 0) { + var heading = geoVecAngle(a, b); + var dx = dt * Math.cos(heading); + var dy = dt * Math.sin(heading); + var p = [ + a[0] + offset * Math.cos(heading), + a[1] + offset * Math.sin(heading) + ]; + + // gather coordinates + var coord = [a, p]; + for (span -= dt; span >= 0; span -= dt) { + p = geoVecAdd(p, [dx, dy]); + coord.push(p); + } + coord.push(b); + + // generate svg paths + var segment = ''; + var j; + + for (j = 0; j < coord.length; j++) { + segment += (j === 0 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1]; + } + segments.push({ id: entity.id, index: i++, d: segment }); + + if (isReversible) { + segment = ''; + for (j = coord.length - 1; j >= 0; j--) { + segment += (j === coord.length - 1 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1]; + } + segments.push({ id: entity.id, index: i++, d: segment }); + } + } + + offset = -span; + } + + a = b; + } + }))); + + return segments; + }; + } - var _selection = d3_select(null); + function svgPath(projection$$1, graph, isArea) { - function clamp(x, min, max) { - return Math.max(min, Math.min(x, max)); - } + // Explanation of magic numbers: + // "padding" here allows space for strokes to extend beyond the viewport, + // so that the stroke isn't drawn along the edge of the viewport when + // the shape is clipped. + // + // When drawing lines, pad viewport by 5px. + // When drawing areas, pad viewport by 65px in each direction to allow + // for 60px area fill stroke (see ".fill-partial path.fill" css rule) + var cache = {}; + var padding = isArea ? 65 : 5; + var viewport = projection$$1.clipExtent(); + var paddedExtent = [ + [viewport[0][0] - padding, viewport[0][1] - padding], + [viewport[1][0] + padding, viewport[1][1] + padding] + ]; + var clip = d3_geoIdentity().clipExtent(paddedExtent).stream; + var project = projection$$1.stream; + var path = d3_geoPath() + .projection({stream: function(output) { return project(clip(output)); }}); + + var svgpath = function(entity) { + if (entity.id in cache) { + return cache[entity.id]; + } else { + return cache[entity.id] = path(entity.asGeoJSON(graph)); + } + }; - function updateValue(d, val) { - if (!val && event && event.target) { - val = event.target.value; - } + svgpath.geojson = path; - val = clamp(val, minVal, maxVal); + return svgpath; + } - _options[d] = val; - context.background()[d](val); - if (d === 'brightness') { - context.storage('background-opacity', val); - } + function svgPointTransform(projection$$1) { + var svgpoint = function(entity) { + // http://jsperf.com/short-array-join + var pt = projection$$1(entity.loc); + return 'translate(' + pt[0] + ',' + pt[1] + ')'; + }; - _selection - .call(render); - } - - - function render(selection$$1) { - var container = selection$$1.selectAll('.display-options-container') - .data([0]); - - var containerEnter = container.enter() - .append('div') - .attr('class', 'display-options-container controls-list'); - - // add slider controls - var slidersEnter = containerEnter.selectAll('.display-control') - .data(sliders) - .enter() - .append('div') - .attr('class', function(d) { return 'display-control display-control-' + d; }); - - slidersEnter - .append('h5') - .text(function(d) { return t('background.' + d); }) - .append('span') - .attr('class', function(d) { return 'display-option-value display-option-value-' + d; }); - - slidersEnter - .append('input') - .attr('class', function(d) { return 'display-option-input display-option-input-' + d; }) - .attr('type', 'range') - .attr('min', minVal) - .attr('max', maxVal) - .attr('step', '0.05') - .on('input', function(d) { - var val = d3_select(this).property('value'); - updateValue(d, val); - }); + svgpoint.geojson = function(d) { + return svgpoint(d.properties.entity); + }; - slidersEnter - .append('button') - .attr('title', t('background.reset')) - .attr('class', function(d) { return 'display-option-reset display-option-reset-' + d; }) - .on('click', function(d) { - if (event.button !== 0) return; - updateValue(d, 1); - }) - .call(svgIcon('#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo'))); + return svgpoint; + } - // update - container = containerEnter - .merge(container); + function svgRelationMemberTags(graph) { + return function(entity) { + var tags = entity.tags; + graph.parentRelations(entity).forEach(function(relation) { + var type = relation.tags.type; + if (type === 'multipolygon' || type === 'boundary') { + tags = assignIn({}, relation.tags, tags); + } + }); + return tags; + }; + } - container.selectAll('.display-option-input') - .property('value', function(d) { return _options[d]; }); - container.selectAll('.display-option-value') - .text(function(d) { return Math.floor(_options[d] * 100) + '%'; }); + function svgSegmentWay(way, graph, activeID) { + var isActiveWay = (way.nodes.indexOf(activeID) !== -1); + var features = { passive: [], active: [] }; + var start = {}; + var end = {}; + var node, type; + + for (var i = 0; i < way.nodes.length; i++) { + node = graph.entity(way.nodes[i]); + type = svgPassiveVertex(node, graph, activeID); + end = { node: node, type: type }; + + if (start.type !== undefined) { + if (start.node.id === activeID || end.node.id === activeID) ; else if (isActiveWay && (start.type === 2 || end.type === 2)) { // one adjacent vertex + pushActive(start, end, i); + } else if (start.type === 0 && end.type === 0) { // both active vertices + pushActive(start, end, i); + } else { + pushPassive(start, end, i); + } + } - container.selectAll('.display-option-reset') - .classed('disabled', function(d) { return _options[d] === 1; }); + start = end; + } - // first time only, set brightness if needed - if (containerEnter.size() && _options.brightness !== 1) { - context.background().brightness(_options.brightness); - } - } + return features; + + + function pushActive(start, end, index) { + features.active.push({ + type: 'Feature', + id: way.id + '-' + index + '-nope', + properties: { + nope: true, + target: true, + entity: way, + nodes: [start.node, end.node], + index: index + }, + geometry: { + type: 'LineString', + coordinates: [start.node.loc, end.node.loc] + } + }); + } + function pushPassive(start, end, index) { + features.passive.push({ + type: 'Feature', + id: way.id + '-' + index, + properties: { + target: true, + entity: way, + nodes: [start.node, end.node], + index: index + }, + geometry: { + type: 'LineString', + coordinates: [start.node.loc, end.node.loc] + } + }); + } + } - function backgroundDisplayOptions(selection$$1) { - _selection = selection$$1; + function svgPoints$$1(projection, context) { - selection$$1 - .call(uiDisclosure(context, 'background_display_options', true) - .title(t('background.display_options')) - .content(render) - ); - } + function markerPath(selection, klass) { + selection + .attr('class', klass) + .attr('transform', 'translate(-8, -23)') + .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'); + } + function sortY(a, b) { + return b.loc[1] - a.loc[1]; + } - return backgroundDisplayOptions; -} -function uiBackgroundOffset(context) { - var directions = [ - ['right', [0.5, 0]], - ['top', [0, -0.5]], - ['left', [-0.5, 0]], - ['bottom', [0, 0.5]] - ]; + // Avoid exit/enter if we're just moving stuff around. + // The node will get a new version but we only need to run the update selection. + function fastEntityKey(d) { + var mode = context.mode(); + var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id); + return isMoving ? d.id : osmEntity$$1.key(d); + } - function d3_eventCancel() { - event.stopPropagation(); - event.preventDefault(); - } + function drawTargets(selection, graph, entities, filter) { + var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor '; + var getTransform = svgPointTransform(projection).geojson; + var activeID = context.activeID(); + var data$$1 = []; + + entities.forEach(function(node) { + if (activeID === node.id) return; // draw no target on the activeID + + data$$1.push({ + type: 'Feature', + id: node.id, + properties: { + target: true, + entity: node + }, + geometry: node.asGeoJSON() + }); + }); + var targets = selection.selectAll('.point.target') + .filter(function(d) { return filter(d.properties.entity); }) + .data(data$$1, function key(d) { return d.id; }); + + // exit + targets.exit() + .remove(); + + // enter/update + targets.enter() + .append('rect') + .attr('x', -10) + .attr('y', -26) + .attr('width', 20) + .attr('height', 30) + .merge(targets) + .attr('class', function(d) { return 'node point target ' + fillClass + d.id; }) + .attr('transform', getTransform); + } - function updateValue() { - var meters = geoOffsetToMeters(context.background().offset()); - var x = +meters[0].toFixed(2); - var y = +meters[1].toFixed(2); - d3_selectAll('.nudge-inner-rect') - .select('input') - .classed('error', false) - .property('value', x + ', ' + y); + function drawPoints(selection, graph, entities, filter) { + var wireframe = context.surface().classed('fill-wireframe'); + var zoom = geoScaleToZoom(projection.scale()); - d3_selectAll('.nudge-reset') - .classed('disabled', function() { - return (x === 0 && y === 0); - }); - } + // points with a direction will render as vertices at higher zooms + function renderAsPoint(entity) { + return entity.geometry(graph) === 'point' && + !(zoom >= 18 && entity.directions(graph, projection).length); + } + // all points will render as vertices in wireframe mode too + var points = wireframe ? [] : entities.filter(renderAsPoint); + + points.sort(sortY); + + + var layer = selection.selectAll('.layer-points .layer-points-points'); + + var groups = layer.selectAll('g.point') + .filter(filter) + .data(points, fastEntityKey); + + groups.exit() + .remove(); + + var enter = groups.enter() + .append('g') + .attr('class', function(d) { return 'node point ' + d.id; }) + .order(); + + enter + .append('path') + .call(markerPath, 'shadow'); + + enter + .append('ellipse') + .attr('cx', 0.5) + .attr('cy', 1) + .attr('rx', 6.5) + .attr('ry', 3) + .attr('class', 'stroke'); + + enter + .append('path') + .call(markerPath, 'stroke'); + + enter + .append('use') + .attr('transform', 'translate(-5, -19)') + .attr('class', 'icon') + .attr('width', '11px') + .attr('height', '11px'); + + groups = groups + .merge(enter) + .attr('transform', svgPointTransform(projection)) + .call(svgTagClasses()); + + // Selecting the following implicitly + // sets the data (point entity) on the element + groups.select('.shadow'); + groups.select('.stroke'); + groups.select('.icon') + .attr('xlink:href', function(entity) { + var preset = context.presets().match(entity, graph); + var picon = preset && preset.icon; + + if (!picon) + return ''; + else { + var isMaki = dataFeatureIcons.indexOf(picon) !== -1; + return '#' + picon + (isMaki ? '-11' : ''); + } + }); + + + // touch targets + selection.selectAll('.layer-points .layer-points-targets') + .call(drawTargets, graph, points, filter); + } - function resetOffset() { - context.background().offset([0, 0]); - updateValue(); - } + return drawPoints; + } - function nudge(d) { - context.background().nudge(d, context.map().zoom()); - updateValue(); - } + function svgTagClasses() { + var primaries = [ + 'building', 'highway', 'railway', 'waterway', 'aeroway', + 'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse', + 'leisure', 'military', 'place' + ], + statuses = [ + 'proposed', 'construction', 'disused', 'abandoned', 'dismantled', + 'razed', 'demolished', 'obliterated', 'intermittent' + ], + secondaries = [ + 'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier', + 'surface', 'tracktype', 'crossing', 'service', 'sport' + ], + tagClassRe = /^tag-/, + tags = function(entity) { return entity.tags; }; + + + var tagClasses = function(selection$$1) { + selection$$1.each(function tagClassesEach(entity) { + var value = this.className, + classes, primary, status; + + if (value.baseVal !== undefined) value = value.baseVal; + + classes = value.trim().split(/\s+/).filter(function(name) { + return name.length && !tagClassRe.test(name); + }).join(' '); + + var t = tags(entity), i, k, v; + + // pick at most one primary classification tag.. + for (i = 0; i < primaries.length; i++) { + k = primaries[i]; + v = t[k]; + if (!v || v === 'no') continue; + + primary = k; + if (statuses.indexOf(v) !== -1) { // e.g. `railway=abandoned` + status = v; + classes += ' tag-' + k; + } else { + classes += ' tag-' + k + ' tag-' + k + '-' + v; + } + + break; + } + + // add at most one status tag, only if relates to primary tag.. + if (!status) { + for (i = 0; i < statuses.length; i++) { + k = statuses[i]; + v = t[k]; + if (!v || v === 'no') continue; + + if (v === 'yes') { // e.g. `railway=rail + abandoned=yes` + status = k; + } + else if (primary && primary === v) { // e.g. `railway=rail + abandoned=railway` + status = k; + } else if (!primary && primaries.indexOf(v) !== -1) { // e.g. `abandoned=railway` + status = k; + primary = v; + classes += ' tag-' + v; + } // else ignore e.g. `highway=path + abandoned=railway` + + if (status) break; + } + } + + if (status) { + classes += ' tag-status tag-status-' + status; + } + + // add any secondary (structure) tags + for (i = 0; i < secondaries.length; i++) { + k = secondaries[i]; + v = t[k]; + if (!v || v === 'no') continue; + classes += ' tag-' + k + ' tag-' + k + '-' + v; + } + + // For highways, look for surface tagging.. + if (primary === 'highway') { + var paved = (t.highway !== 'track'); + for (k in t) { + v = t[k]; + if (k in osmPavedTags) { + paved = !!osmPavedTags[k][v]; + break; + } + } + if (!paved) { + classes += ' tag-unpaved'; + } + } + + classes = classes.trim(); + + if (classes !== value) { + select(this).attr('class', classes); + } + }); + }; - function clickNudgeButton(d) { - var interval; - var timeout = window.setTimeout(function() { - interval = window.setInterval(nudge.bind(null, d), 100); - }, 500); + tagClasses.tags = function(_) { + if (!arguments.length) return tags; + tags = _; + return tagClasses; + }; - function doneNudge() { - window.clearTimeout(timeout); - window.clearInterval(interval); - d3_select(window) - .on('mouseup.buttonoffset', null, true) - .on('mousedown.buttonoffset', null, true); - } + return tagClasses; + } - d3_select(window) - .on('mouseup.buttonoffset', doneNudge, true) - .on('mousedown.buttonoffset', doneNudge, true); + function svgTurns(projection) { - nudge(d); - } + return function drawTurns(selection, graph, turns) { + function icon(turn) { + var u = turn.u ? '-u' : ''; + if (turn.no) return '#turn-no' + u; + if (turn.only) return '#turn-only' + u; + return '#turn-yes' + u; + } - function inputOffset() { - var input = d3_select(this); - var d = input.node().value; + var layer = selection.selectAll('.data-layer-osm').selectAll('.layer-turns') + .data([0]); - if (d === '') return resetOffset(); + layer = layer.enter() + .append('g') + .attr('class', 'layer-osm layer-turns') + .merge(layer); - d = d.replace(/;/g, ',').split(',').map(function(n) { - // if n is NaN, it will always get mapped to false. - return !isNaN(n) && n; - }); - if (d.length !== 2 || !d[0] || !d[1]) { - input.classed('error', true); - return; - } + var groups = layer.selectAll('g.turn') + .data(turns, function(d) { return d.key; }); - context.background().offset(geoMetersToOffset(d)); - updateValue(); - } + groups.exit() + .remove(); - function dragOffset() { - event.preventDefault(); - if (event.button !== 0) return; + var enter = groups.enter() + .append('g') + .attr('class', function(d) { return 'turn ' + d.key; }); - var origin = [event.clientX, event.clientY]; + var nEnter = enter + .filter(function(d) { return !d.u; }); - context.container() - .append('div') - .attr('class', 'nudge-surface'); + nEnter.append('rect') + .attr('transform', 'translate(-22, -12)') + .attr('width', '44') + .attr('height', '24'); - d3_select(window) - .on('mousemove.offset', function() { - var latest = [event.clientX, event.clientY]; - var d = [ - -(origin[0] - latest[0]) / 4, - -(origin[1] - latest[1]) / 4 - ]; + nEnter.append('use') + .attr('transform', 'translate(-22, -12)') + .attr('width', '44') + .attr('height', '24'); - origin = latest; - nudge(d); - }) - .on('mouseup.offset', function() { - if (event.button !== 0) return; - d3_selectAll('.nudge-surface') - .remove(); - d3_select(window) - .on('mousemove.offset', null) - .on('mouseup.offset', null); - }); - } + var uEnter = enter + .filter(function(d) { return d.u; }); + uEnter.append('circle') + .attr('r', '16'); - function render(selection$$1) { - var container = selection$$1.selectAll('.nudge-container') - .data([0]); - - var containerEnter = container.enter() - .append('div') - .attr('class', 'nudge-container cf'); - - containerEnter - .append('div') - .attr('class', 'nudge-instructions') - .text(t('background.offset')); - - var nudgeEnter = containerEnter - .append('div') - .attr('class', 'nudge-outer-rect') - .on('mousedown', dragOffset); - - nudgeEnter - .append('div') - .attr('class', 'nudge-inner-rect') - .append('input') - .on('change', inputOffset); - - containerEnter - .append('div') - .selectAll('button') - .data(directions).enter() - .append('button') - .attr('class', function(d) { return d[0] + ' nudge'; }) - .on('contextmenu', d3_eventCancel) - .on('mousedown', function(d) { - if (event.button !== 0) return; - clickNudgeButton(d[1]); - }); + uEnter.append('use') + .attr('transform', 'translate(-16, -16)') + .attr('width', '32') + .attr('height', '32'); - containerEnter - .append('button') - .attr('title', t('background.reset')) - .attr('class', 'nudge-reset disabled') - .on('contextmenu', d3_eventCancel) - .on('click', function() { - if (event.button !== 0) return; - resetOffset(); - }) - .call(svgIcon('#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo'))); - updateValue(); - } + groups = groups + .merge(enter); + groups + .attr('opacity', function(d) { + return d.direct === false ? '0.7' : null; + }) + .attr('transform', function(d) { + var pxRadius = 50; + var toWay = graph.entity(d.to.way); + var toPoints = graph.childNodes(toWay) + .map(function (n) { return n.loc; }) + .map(projection); + var toLength = geoPathLength(toPoints); + var mid = toLength / 2; // midpoint of destination way - function backgroundOffset(selection$$1) { - selection$$1 - .call(uiDisclosure(context, 'background_offset', false) - .title(t('background.fix_misalignment')) - .content(render) - ); - } + var toNode = graph.entity(d.to.node); + var toVertex = graph.entity(d.to.vertex); + var a = geoAngle(toVertex, toNode, projection); + var o = projection(toVertex.loc); + var r = d.u ? 0 // u-turn: no radius + : !toWay.__via ? pxRadius // leaf way: put marker at pxRadius + : Math.min(mid, pxRadius); // via way: prefer pxRadius, fallback to mid for very short ways + return 'translate(' + (r * Math.cos(a) + o[0]) + ',' + (r * Math.sin(a) + o[1]) + ') ' + + 'rotate(' + a * 180 / Math.PI + ')'; + }); - context.background() - .on('change.backgroundOffset-update', updateValue); - - return backgroundOffset; -} - -var marked = createCommonjsModule(function (module, exports) { -(function(root) { - -/** - * Block-Level Grammar - */ - -var block = { - newline: /^\n+/, - code: /^( {4}[^\n]+\n*)+/, - fences: noop, - hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, - heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, - nptable: noop, - blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, - list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, - html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, - def: /^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, - table: noop, - lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, - paragraph: /^([^\n]+(?:\n?(?!hr|heading|lheading| {0,3}>|tag)[^\n]+)+)/, - text: /^[^\n]+/ -}; - -block._label = /(?:\\[\[\]]|[^\[\]])+/; -block._title = /(?:"(?:\\"|[^"]|"[^"\n]*")*"|'\n?(?:[^'\n]+\n?)*'|\([^()]*\))/; -block.def = edit(block.def) - .replace('label', block._label) - .replace('title', block._title) - .getRegex(); - -block.bullet = /(?:[*+-]|\d+\.)/; -block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; -block.item = edit(block.item, 'gm') - .replace(/bull/g, block.bullet) - .getRegex(); - -block.list = edit(block.list) - .replace(/bull/g, block.bullet) - .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))') - .replace('def', '\\n+(?=' + block.def.source + ')') - .getRegex(); - -block._tag = '(?!(?:' - + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' - + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' - + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b'; - -block.html = edit(block.html) - .replace('comment', //) - .replace('closed', /<(tag)[\s\S]+?<\/\1>/) - .replace('closing', /\s]*)*?\/?>/) - .replace(/tag/g, block._tag) - .getRegex(); - -block.paragraph = edit(block.paragraph) - .replace('hr', block.hr) - .replace('heading', block.heading) - .replace('lheading', block.lheading) - .replace('tag', '<' + block._tag) - .getRegex(); - -block.blockquote = edit(block.blockquote) - .replace('paragraph', block.paragraph) - .getRegex(); - -/** - * Normal Block Grammar - */ - -block.normal = merge({}, block); - -/** - * GFM Block Grammar - */ - -block.gfm = merge({}, block.normal, { - fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/, - paragraph: /^/, - heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ -}); - -block.gfm.paragraph = edit(block.paragraph) - .replace('(?!', '(?!' - + block.gfm.fences.source.replace('\\1', '\\2') + '|' - + block.list.source.replace('\\1', '\\3') + '|') - .getRegex(); - -/** - * GFM + Tables Block Grammar - */ - -block.tables = merge({}, block.gfm, { - nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, - table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ -}); - -/** - * Block Lexer - */ - -function Lexer(options) { - this.tokens = []; - this.tokens.links = {}; - this.options = options || marked.defaults; - this.rules = block.normal; - - if (this.options.gfm) { - if (this.options.tables) { - this.rules = block.tables; - } else { - this.rules = block.gfm; - } - } -} - -/** - * Expose Block Rules - */ - -Lexer.rules = block; - -/** - * Static Lex Method - */ - -Lexer.lex = function(src, options) { - var lexer = new Lexer(options); - return lexer.lex(src); -}; - -/** - * Preprocessing - */ - -Lexer.prototype.lex = function(src) { - src = src - .replace(/\r\n|\r/g, '\n') - .replace(/\t/g, ' ') - .replace(/\u00a0/g, ' ') - .replace(/\u2424/g, '\n'); - - return this.token(src, true); -}; - -/** - * Lexing - */ - -Lexer.prototype.token = function(src, top) { - src = src.replace(/^ +$/gm, ''); - var next, - loose, - cap, - bull, - b, - item, - space, - i, - tag, - l; - - while (src) { - // newline - if (cap = this.rules.newline.exec(src)) { - src = src.substring(cap[0].length); - if (cap[0].length > 1) { - this.tokens.push({ - type: 'space' - }); - } - } + groups.select('use') + .attr('xlink:href', icon); - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - cap = cap[0].replace(/^ {4}/gm, ''); - this.tokens.push({ - type: 'code', - text: !this.options.pedantic - ? cap.replace(/\n+$/, '') - : cap - }); - continue; - } + groups.select('rect'); + groups.select('circle'); - // fences (gfm) - if (cap = this.rules.fences.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'code', - lang: cap[2], - text: cap[3] || '' - }); - continue; - } + return this; + }; + } - // heading - if (cap = this.rules.heading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[1].length, - text: cap[2] - }); - continue; - } + function svgVertices$$1(projection, context) { + var radiuses = { + // z16-, z17, z18+, w/icon + shadow: [6, 7.5, 7.5, 12], + stroke: [2.5, 3.5, 3.5, 8], + fill: [1, 1.5, 1.5, 1.5] + }; - // table no leading pipe (gfm) - if (top && (cap = this.rules.nptable.exec(src))) { - src = src.substring(cap[0].length); + var _currHoverTarget; + var _currPersistent = {}; + var _currHover = {}; + var _prevHover = {}; + var _currSelected = {}; + var _prevSelected = {}; + var _radii = {}; - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/\n$/, '').split('\n') - }; - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } + function sortY(a, b) { + return b.loc[1] - a.loc[1]; } - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i].split(/ *\| */); + // Avoid exit/enter if we're just moving stuff around. + // The node will get a new version but we only need to run the update selection. + function fastEntityKey(d) { + var mode = context.mode(); + var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id); + return isMoving ? d.id : osmEntity$$1.key(d); } - this.tokens.push(item); - - continue; - } - - // hr - if (cap = this.rules.hr.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'hr' - }); - continue; - } - // blockquote - if (cap = this.rules.blockquote.exec(src)) { - src = src.substring(cap[0].length); + function draw(selection$$1, graph, vertices, sets, filter) { + sets = sets || { selected: {}, important: {}, hovered: {} }; - this.tokens.push({ - type: 'blockquote_start' - }); + var icons = {}; + var directions = {}; + var wireframe = context.surface().classed('fill-wireframe'); + var zoom = geoScaleToZoom(projection.scale()); + var z = (zoom < 17 ? 0 : zoom < 18 ? 1 : 2); - cap = cap[0].replace(/^ *> ?/gm, ''); - // Pass `top` to keep the current - // "toplevel" state. This is exactly - // how markdown.pl works. - this.token(cap, top); + function getIcon(entity) { + if (entity.id in icons) return icons[entity.id]; - this.tokens.push({ - type: 'blockquote_end' - }); + icons[entity.id] = + entity.hasInterestingTags() && + context.presets().match(entity, graph).icon; + return icons[entity.id]; + } - continue; - } - // list - if (cap = this.rules.list.exec(src)) { - src = src.substring(cap[0].length); - bull = cap[2]; + // memoize directions results, return false for empty arrays (for use in filter) + function getDirections(entity) { + if (entity.id in directions) return directions[entity.id]; - this.tokens.push({ - type: 'list_start', - ordered: bull.length > 1 - }); + var angles = entity.directions(graph, projection); + directions[entity.id] = angles.length ? angles : false; + return angles; + } - // Get each top-level item. - cap = cap[0].match(this.rules.item); - next = false; - l = cap.length; - i = 0; + function updateAttributes(selection$$1) { + ['shadow', 'stroke', 'fill'].forEach(function(klass) { + var rads = radiuses[klass]; + selection$$1.selectAll('.' + klass) + .each(function(entity) { + var i = z && getIcon(entity); + var r = rads[i ? 3 : z]; - for (; i < l; i++) { - item = cap[i]; + // slightly increase the size of unconnected endpoints #3775 + if (entity.isEndpoint(graph) && !entity.isConnected(graph)) { + r += 1.5; + } - // Remove the list item's bullet - // so it is seen as the next token. - space = item.length; - item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + if (klass === 'shadow') { // remember this value, so we don't need to + _radii[entity.id] = r; // recompute it when we draw the touch targets + } - // Outdent whatever the - // list item contains. Hacky. - if (~item.indexOf('\n ')) { - space -= item.length; - item = !this.options.pedantic - ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') - : item.replace(/^ {1,4}/gm, ''); - } + select(this) + .attr('r', r) + .attr('visibility', (i && klass === 'fill') ? 'hidden' : null); + }); + }); - // Determine whether the next list item belongs here. - // Backpedal if it does not belong in this list. - if (this.options.smartLists && i !== l - 1) { - b = block.bullet.exec(cap[i + 1])[0]; - if (bull !== b && !(bull.length > 1 && b.length > 1)) { - src = cap.slice(i + 1).join('\n') + src; - i = l - 1; + selection$$1.selectAll('use') + .attr('visibility', (z === 0 ? 'hidden' : null)); } - } - - // Determine whether item is loose or not. - // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ - // for discount behavior. - loose = next || /\n\n(?!\s*$)/.test(item); - if (i !== l - 1) { - next = item.charAt(item.length - 1) === '\n'; - if (!loose) loose = next; - } - this.tokens.push({ - type: loose - ? 'loose_item_start' - : 'list_item_start' - }); + vertices.sort(sortY); + + var groups = selection$$1.selectAll('g.vertex') + .filter(filter) + .data(vertices, fastEntityKey); + + // exit + groups.exit() + .remove(); + + // enter + var enter = groups.enter() + .append('g') + .attr('class', function(d) { return 'node vertex ' + d.id; }) + .order(); + + enter + .append('circle') + .attr('class', 'shadow'); + + enter + .append('circle') + .attr('class', 'stroke'); + + // Vertices with icons get a `use`. + enter.filter(function(d) { return getIcon(d); }) + .append('use') + .attr('class', 'icon') + .attr('width', '11px') + .attr('height', '11px') + .attr('transform', 'translate(-5.5, -5.5)') + .attr('xlink:href', function(d) { + var picon = getIcon(d); + var isMaki = dataFeatureIcons.indexOf(picon) !== -1; + return '#' + picon + (isMaki ? '-11' : ''); + }); + + // Vertices with tags get a fill. + enter.filter(function(d) { return d.hasInterestingTags(); }) + .append('circle') + .attr('class', 'fill'); + + // update + groups = groups + .merge(enter) + .attr('transform', svgPointTransform(projection)) + .classed('sibling', function(d) { return d.id in sets.selected; }) + .classed('shared', function(d) { return graph.isShared(d); }) + .classed('endpoint', function(d) { return d.isEndpoint(graph); }) + .call(updateAttributes); + + + // Directional vertices get viewfields + var dgroups = groups.filter(function(d) { return getDirections(d); }) + .selectAll('.viewfieldgroup') + .data(function data$$1(d) { return zoom >= 18 ? [d] : []; }, osmEntity$$1.key); + + // exit + dgroups.exit() + .remove(); + + // enter/update + dgroups = dgroups.enter() + .insert('g', '.shadow') + .attr('class', 'viewfieldgroup') + .merge(dgroups); + + var viewfields = dgroups.selectAll('.viewfield') + .data(getDirections, function key(d) { return d; }); + + // exit + viewfields.exit() + .remove(); + + // enter/update + viewfields.enter() + .append('path') + .attr('class', 'viewfield') + .attr('d', 'M0,0H0') + .merge(viewfields) + .attr('marker-start', 'url(#viewfield-marker' + (wireframe ? '-wireframe' : '') + ')') + .attr('transform', function(d) { return 'rotate(' + d + ')'; }); + } - // Recurse. - this.token(item, false); - this.tokens.push({ - type: 'list_item_end' - }); - } + function drawTargets(selection$$1, graph, entities, filter) { + var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor '; + var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor '; + var getTransform = svgPointTransform(projection).geojson; + var activeID = context.activeID(); + var data$$1 = { targets: [], nopes: [] }; + + entities.forEach(function(node) { + if (activeID === node.id) return; // draw no target on the activeID + + var vertexType = svgPassiveVertex(node, graph, activeID); + if (vertexType !== 0) { // passive or adjacent - allow to connect + data$$1.targets.push({ + type: 'Feature', + id: node.id, + properties: { + target: true, + entity: node + }, + geometry: node.asGeoJSON() + }); + } else { + data$$1.nopes.push({ + type: 'Feature', + id: node.id + '-nope', + properties: { + nope: true, + target: true, + entity: node + }, + geometry: node.asGeoJSON() + }); + } + }); - this.tokens.push({ - type: 'list_end' - }); - continue; - } + // Targets allow hover and vertex snapping + var targets = selection$$1.selectAll('.vertex.target-allowed') + .filter(function(d) { return filter(d.properties.entity); }) + .data(data$$1.targets, function key(d) { return d.id; }); + + // exit + targets.exit() + .remove(); + + // enter/update + targets.enter() + .append('circle') + .attr('r', function(d) { return (_radii[d.id] || radiuses.shadow[3]); }) + .merge(targets) + .attr('class', function(d) { return 'node vertex target target-allowed ' + targetClass + d.id; }) + .attr('transform', getTransform); + + + // NOPE + var nopes = selection$$1.selectAll('.vertex.target-nope') + .filter(function(d) { return filter(d.properties.entity); }) + .data(data$$1.nopes, function key(d) { return d.id; }); + + // exit + nopes.exit() + .remove(); + + // enter/update + nopes.enter() + .append('circle') + .attr('r', function(d) { return (_radii[d.properties.entity.id] || radiuses.shadow[3]); }) + .merge(nopes) + .attr('class', function(d) { return 'node vertex target target-nope ' + nopeClass + d.id; }) + .attr('transform', getTransform); + } - // html - if (cap = this.rules.html.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: this.options.sanitize - ? 'paragraph' - : 'html', - pre: !this.options.sanitizer - && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), - text: cap[0] - }); - continue; - } - // def - if (top && (cap = this.rules.def.exec(src))) { - src = src.substring(cap[0].length); - if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1); - tag = cap[1].toLowerCase(); - if (!this.tokens.links[tag]) { - this.tokens.links[tag] = { - href: cap[2], - title: cap[3] - }; + // Points can also render as vertices: + // 1. in wireframe mode or + // 2. at higher zooms if they have a direction + function renderAsVertex(entity, graph, wireframe, zoom) { + var geometry = entity.geometry(graph); + return geometry === 'vertex' || (geometry === 'point' && ( + wireframe || (zoom >= 18 && entity.directions(graph, projection).length) + )); } - continue; - } - // table (gfm) - if (top && (cap = this.rules.table.exec(src))) { - src = src.substring(cap[0].length); - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') - }; + function getSiblingAndChildVertices(ids, graph, wireframe, zoom) { + var results = {}; + + function addChildVertices(entity) { + var geometry = entity.geometry(graph); + if (!context.features().isHiddenFeature(entity, graph, geometry)) { + var i; + if (entity.type === 'way') { + for (i = 0; i < entity.nodes.length; i++) { + var child = graph.hasEntity(entity.nodes[i]); + if (child) { + addChildVertices(child); + } + } + } else if (entity.type === 'relation') { + for (i = 0; i < entity.members.length; i++) { + var member = graph.hasEntity(entity.members[i].id); + if (member) { + addChildVertices(member); + } + } + } else if (renderAsVertex(entity, graph, wireframe, zoom)) { + results[entity.id] = entity; + } + } + } - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } + ids.forEach(function(id) { + var entity = graph.hasEntity(id); + if (!entity) return; + + if (entity.type === 'node') { + if (renderAsVertex(entity, graph, wireframe, zoom)) { + results[entity.id] = entity; + graph.parentWays(entity).forEach(function(entity) { + addChildVertices(entity); + }); + } + } else { // way, relation + addChildVertices(entity); + } + }); - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i] - .replace(/^ *\| *| *\| *$/g, '') - .split(/ *\| */); + return results; } - this.tokens.push(item); - - continue; - } - // lheading - if (cap = this.rules.lheading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[2] === '=' ? 1 : 2, - text: cap[1] - }); - continue; - } + function drawVertices(selection$$1, graph, entities, filter, extent, fullRedraw) { + var wireframe = context.surface().classed('fill-wireframe'); + var zoom = geoScaleToZoom(projection.scale()); + var mode = context.mode(); + var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id); - // top-level paragraph - if (top && (cap = this.rules.paragraph.exec(src))) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'paragraph', - text: cap[1].charAt(cap[1].length - 1) === '\n' - ? cap[1].slice(0, -1) - : cap[1] - }); - continue; - } + if (fullRedraw) { + _currPersistent = {}; + _radii = {}; + } - // text - if (cap = this.rules.text.exec(src)) { - // Top-level should never reach here. - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'text', - text: cap[0] - }); - continue; - } + // Collect important vertices from the `entities` list.. + // (during a paritial redraw, it will not contain everything) + for (var i = 0; i < entities.length; i++) { + var entity = entities[i]; + var geometry = entity.geometry(graph); + var keep = false; + + // a point that looks like a vertex.. + if ((geometry === 'point') && renderAsVertex(entity, graph, wireframe, zoom)) { + _currPersistent[entity.id] = entity; + keep = true; + + // a vertex of some importance.. + } else if (geometry === 'vertex' && + (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph))) { + _currPersistent[entity.id] = entity; + keep = true; + } + + // whatever this is, it's not a persistent vertex.. + if (!keep && !fullRedraw) { + delete _currPersistent[entity.id]; + } + } - if (src) { - throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } + // 3 sets of vertices to consider: + var sets = { + persistent: _currPersistent, // persistent = important vertices (render always) + selected: _currSelected, // selected + siblings of selected (render always) + hovered: _currHover // hovered + siblings of hovered (render only in draw modes) + }; - return this.tokens; -}; + var all = assign({}, (isMoving ? _currHover : {}), _currSelected, _currPersistent); -/** - * Inline-Level Grammar - */ + // Draw the vertices.. + // The filter function controls the scope of what objects d3 will touch (exit/enter/update) + // Adjust the filter function to expand the scope beyond whatever entities were passed in. + var filterRendered = function(d) { + return d.id in _currPersistent || d.id in _currSelected || d.id in _currHover || filter(d); + }; + selection$$1.selectAll('.layer-points .layer-points-vertices') + .call(draw, graph, currentVisible(all), sets, filterRendered); -var inline = { - escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, - autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, - url: noop, - tag: /^|^<\/?[a-zA-Z0-9\-]+(?:"[^"]*"|'[^']*'|\s[^<'">\/\s]*)*?\/?>/, - link: /^!?\[(inside)\]\(href\)/, - reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, - nolink: /^!?\[((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\]/, - strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, - em: /^_([^\s_](?:[^_]|__)+?[^\s_])_\b|^\*((?:\*\*|[^*])+?)\*(?!\*)/, - code: /^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/, - br: /^ {2,}\n(?!\s*$)/, - del: noop, - text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; -inline.link = edit(inline.link) - .replace('inside', inline._inside) - .replace('href', inline._href) - .getRegex(); + // partial redraw - only update the selected items.. + drawVertices.drawSelected = function(selection$$1, graph, extent) { + var wireframe = context.surface().classed('fill-wireframe'); + var zoom = geoScaleToZoom(projection.scale()); -inline.reflink = edit(inline.reflink) - .replace('inside', inline._inside) - .getRegex(); + _prevSelected = _currSelected || {}; + _currSelected = getSiblingAndChildVertices(context.selectedIDs(), graph, wireframe, zoom); -/** - * Normal Inline Grammar - */ + // note that drawVertices will add `_currSelected` automatically if needed.. + var filter = function(d) { return d.id in _prevSelected; }; + drawVertices(selection$$1, graph, values$1(_prevSelected), filter, extent, false); + }; -inline.normal = merge({}, inline); -/** - * Pedantic Inline Grammar - */ + // partial redraw - only update the hovered items.. + drawVertices.drawHover = function(selection$$1, graph, target, extent) { + if (target === _currHoverTarget) return; // continue only if something changed -inline.pedantic = merge({}, inline.normal, { - strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, - em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ -}); + var wireframe = context.surface().classed('fill-wireframe'); + var zoom = geoScaleToZoom(projection.scale()); -/** - * GFM Inline Grammar - */ + _prevHover = _currHover || {}; + _currHoverTarget = target; + var entity = target && target.properties && target.properties.entity; -inline.gfm = merge({}, inline.normal, { - escape: edit(inline.escape).replace('])', '~|])').getRegex(), - url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/) - .replace('email', inline._email) - .getRegex(), - _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, - del: /^~~(?=\S)([\s\S]*?\S)~~/, - text: edit(inline.text) - .replace(']|', '~]|') - .replace('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|') - .getRegex() -}); - -/** - * GFM + Line Breaks Inline Grammar - */ - -inline.breaks = merge({}, inline.gfm, { - br: edit(inline.br).replace('{2,}', '*').getRegex(), - text: edit(inline.gfm.text).replace('{2,}', '*').getRegex() -}); - -/** - * Inline Lexer & Compiler - */ - -function InlineLexer(links, options) { - this.options = options || marked.defaults; - this.links = links; - this.rules = inline.normal; - this.renderer = this.options.renderer || new Renderer(); - this.renderer.options = this.options; - - if (!this.links) { - throw new Error('Tokens array requires a `links` property.'); - } - - if (this.options.gfm) { - if (this.options.breaks) { - this.rules = inline.breaks; - } else { - this.rules = inline.gfm; - } - } else if (this.options.pedantic) { - this.rules = inline.pedantic; - } -} + if (entity) { + _currHover = getSiblingAndChildVertices([entity.id], graph, wireframe, zoom); + } else { + _currHover = {}; + } -/** - * Expose Inline Rules - */ + // note that drawVertices will add `_currHover` automatically if needed.. + var filter = function(d) { return d.id in _prevHover; }; + drawVertices(selection$$1, graph, values$1(_prevHover), filter, extent, false); + }; -InlineLexer.rules = inline; + return drawVertices; + } -/** - * Static Lexing/Compiling Method - */ + function uiAccount(context) { + var osm = context.connection(); -InlineLexer.output = function(src, links, options) { - var inline = new InlineLexer(links, options); - return inline.output(src); -}; -/** - * Lexing/Compiling - */ + function update(selection$$1) { + if (!osm) return; -InlineLexer.prototype.output = function(src) { - var out = '', - link, - text, - href, - cap; + if (!osm.authenticated()) { + selection$$1.selectAll('#userLink, #logoutLink') + .classed('hide', true); + return; + } - while (src) { - // escape - if (cap = this.rules.escape.exec(src)) { - src = src.substring(cap[0].length); - out += cap[1]; - continue; - } + osm.userDetails(function(err, details) { + var userLink = selection$$1.select('#userLink'), + logoutLink = selection$$1.select('#logoutLink'); - // autolink - if (cap = this.rules.autolink.exec(src)) { - src = src.substring(cap[0].length); - if (cap[2] === '@') { - text = escape(this.mangle(cap[1])); - href = 'mailto:' + text; - } else { - text = escape(cap[1]); - href = text; - } - out += this.renderer.link(href, null, text); - continue; - } + userLink.html(''); + logoutLink.html(''); - // url (gfm) - if (!this.inLink && (cap = this.rules.url.exec(src))) { - cap[0] = this.rules._backpedal.exec(cap[0])[0]; - src = src.substring(cap[0].length); - if (cap[2] === '@') { - text = escape(cap[0]); - href = 'mailto:' + text; - } else { - text = escape(cap[0]); - if (cap[1] === 'www.') { - href = 'http://' + text; - } else { - href = text; - } - } - out += this.renderer.link(href, null, text); - continue; - } + if (err) return; - // tag - if (cap = this.rules.tag.exec(src)) { - if (!this.inLink && /^/i.test(cap[0])) { - this.inLink = false; - } - src = src.substring(cap[0].length); - out += this.options.sanitize - ? this.options.sanitizer - ? this.options.sanitizer(cap[0]) - : escape(cap[0]) - : cap[0]; - continue; - } - - // link - if (cap = this.rules.link.exec(src)) { - src = src.substring(cap[0].length); - this.inLink = true; - out += this.outputLink(cap, { - href: cap[2], - title: cap[3] - }); - this.inLink = false; - continue; - } - - // reflink, nolink - if ((cap = this.rules.reflink.exec(src)) - || (cap = this.rules.nolink.exec(src))) { - src = src.substring(cap[0].length); - link = (cap[2] || cap[1]).replace(/\s+/g, ' '); - link = this.links[link.toLowerCase()]; - if (!link || !link.href) { - out += cap[0].charAt(0); - src = cap[0].substring(1) + src; - continue; - } - this.inLink = true; - out += this.outputLink(cap, link); - this.inLink = false; - continue; - } + selection$$1.selectAll('#userLink, #logoutLink') + .classed('hide', false); - // strong - if (cap = this.rules.strong.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.strong(this.output(cap[2] || cap[1])); - continue; - } + // Link + userLink.append('a') + .attr('href', osm.userURL(details.display_name)) + .attr('target', '_blank'); - // em - if (cap = this.rules.em.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.em(this.output(cap[2] || cap[1])); - continue; - } + // Add thumbnail or dont + if (details.image_url) { + userLink.append('img') + .attr('class', 'icon pre-text user-icon') + .attr('src', details.image_url); + } else { + userLink + .call(svgIcon('#icon-avatar', 'pre-text light')); + } - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.codespan(escape(cap[2].trim(), true)); - continue; - } + // Add user name + userLink.append('span') + .attr('class', 'label') + .text(details.display_name); + + logoutLink.append('a') + .attr('class', 'logout') + .attr('href', '#') + .text(t('logout')) + .on('click.logout', function() { + event.preventDefault(); + osm.logout(); + }); + }); + } - // br - if (cap = this.rules.br.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.br(); - continue; - } - // del (gfm) - if (cap = this.rules.del.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.del(this.output(cap[1])); - continue; - } + return function(selection$$1) { + selection$$1.append('li') + .attr('id', 'logoutLink') + .classed('hide', true); - // text - if (cap = this.rules.text.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.text(escape(this.smartypants(cap[0]))); - continue; - } + selection$$1.append('li') + .attr('id', 'userLink') + .classed('hide', true); - if (src) { - throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } + if (osm) { + osm.on('change.account', function() { update(selection$$1); }); + update(selection$$1); + } + }; } - return out; -}; - -/** - * Compile Link - */ + function uiAttribution(context) { + var selection$$1; + + + function attribution(data, klass) { + var div = selection$$1.selectAll('.' + klass) + .data([0]); + + div = div.enter() + .append('div') + .attr('class', klass) + .merge(div); + + + var background = div.selectAll('.attribution') + .data(data, function(d) { return d.name(); }); + + background.exit() + .remove(); + + background = background.enter() + .append('span') + .attr('class', 'attribution') + .each(function(d) { + if (d.terms_html) { + select(this) + .html(d.terms_html); + return; + } + + var selection$$1; + if (d.terms_url) { + selection$$1 = select(this) + .append('a') + .attr('href', d.terms_url) + .attr('target', '_blank'); + } else { + selection$$1 = select(this); + } + + + var id_safe = d.id.replace('.', ''); + var terms_text = t('imagery.' + id_safe + '.attribution.text', + { default: d.terms_text || d.id || d.name() } + ); + + if (d.icon && !d.overlay) { + selection$$1 + .append('img') + .attr('class', 'source-image') + .attr('src', d.icon); + } + + selection$$1 + .append('span') + .attr('class', 'attribution-text') + .text(terms_text); + }) + .merge(background); + + + var copyright = background.selectAll('.copyright-notice') + .data(function(d) { + var notice = d.copyrightNotices(context.map().zoom(), context.map().extent()); + return notice ? [notice] : []; + }); + + copyright.exit() + .remove(); + + copyright = copyright.enter() + .append('span') + .attr('class', 'copyright-notice') + .merge(copyright); + + copyright + .text(String); + } -InlineLexer.prototype.outputLink = function(cap, link) { - var href = escape(link.href), - title = link.title ? escape(link.title) : null; - return cap[0].charAt(0) !== '!' - ? this.renderer.link(href, title, this.output(cap[1])) - : this.renderer.image(href, title, escape(cap[1])); -}; + function update() { + attribution([context.background().baseLayerSource()], 'base-layer-attribution'); + attribution(context.background().overlayLayerSources().filter(function (s) { + return s.validZoom(context.map().zoom()); + }), 'overlay-layer-attribution'); + } -/** - * Smartypants Transformations - */ -InlineLexer.prototype.smartypants = function(text) { - if (!this.options.smartypants) return text; - return text - // em-dashes - .replace(/---/g, '\u2014') - // en-dashes - .replace(/--/g, '\u2013') - // opening singles - .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') - // closing singles & apostrophes - .replace(/'/g, '\u2019') - // opening doubles - .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') - // closing doubles - .replace(/"/g, '\u201d') - // ellipses - .replace(/\.{3}/g, '\u2026'); -}; + return function(select$$1) { + selection$$1 = select$$1; -/** - * Mangle Links - */ + context.background() + .on('change.attribution', update); -InlineLexer.prototype.mangle = function(text) { - if (!this.options.mangle) return text; - var out = '', - l = text.length, - i = 0, - ch; + context.map() + .on('move.attribution', throttle(update, 400, {leading: false})); - for (; i < l; i++) { - ch = text.charCodeAt(i); - if (Math.random() > 0.5) { - ch = 'x' + ch.toString(16); - } - out += '&#' + ch + ';'; + update(); + }; } - return out; -}; + // toggles the visibility of ui elements, using a combination of the + // hide class, which sets display=none, and a d3 transition for opacity. + // this will cause blinking when called repeatedly, so check that the + // value actually changes between calls. + function uiToggle(show, callback) { + return function(selection$$1) { + selection$$1 + .style('opacity', show ? 0 : 1) + .classed('hide', false) + .transition() + .style('opacity', show ? 1 : 0) + .on('end', function() { + select(this) + .classed('hide', !show) + .style('opacity', null); + if (callback) callback.apply(this); + }); + }; + } -/** - * Renderer - */ + function uiDisclosure(context, key, expandedDefault) { + var dispatch$$1 = dispatch('toggled'), + _preference = (context.storage('disclosure.' + key + '.expanded')), + _expanded = (_preference === null ? !!expandedDefault : (_preference === 'true')), + _title, + _updatePreference = true, + _content = function () {}; -function Renderer(options) { - this.options = options || {}; -} -Renderer.prototype.code = function(code, lang, escaped) { - if (this.options.highlight) { - var out = this.options.highlight(code, lang); - if (out != null && out !== code) { - escaped = true; - code = out; - } - } + var disclosure = function(selection$$1) { + var hideToggle = selection$$1.selectAll('.hide-toggle-' + key) + .data([0]); - if (!lang) { - return '
'
-      + (escaped ? code : escape(code, true))
-      + '\n
'; - } - - return '
'
-    + (escaped ? code : escape(code, true))
-    + '\n
\n'; -}; - -Renderer.prototype.blockquote = function(quote) { - return '
\n' + quote + '
\n'; -}; - -Renderer.prototype.html = function(html) { - return html; -}; - -Renderer.prototype.heading = function(text, level, raw) { - return '' - + text - + '\n'; -}; - -Renderer.prototype.hr = function() { - return this.options.xhtml ? '
\n' : '
\n'; -}; - -Renderer.prototype.list = function(body, ordered) { - var type = ordered ? 'ol' : 'ul'; - return '<' + type + '>\n' + body + '\n'; -}; - -Renderer.prototype.listitem = function(text) { - return '
  • ' + text + '
  • \n'; -}; - -Renderer.prototype.paragraph = function(text) { - return '

    ' + text + '

    \n'; -}; - -Renderer.prototype.table = function(header, body) { - return '\n' - + '\n' - + header - + '\n' - + '\n' - + body - + '\n' - + '
    \n'; -}; - -Renderer.prototype.tablerow = function(content) { - return '\n' + content + '\n'; -}; - -Renderer.prototype.tablecell = function(content, flags) { - var type = flags.header ? 'th' : 'td'; - var tag = flags.align - ? '<' + type + ' style="text-align:' + flags.align + '">' - : '<' + type + '>'; - return tag + content + '\n'; -}; - -// span level renderer -Renderer.prototype.strong = function(text) { - return '' + text + ''; -}; - -Renderer.prototype.em = function(text) { - return '' + text + ''; -}; - -Renderer.prototype.codespan = function(text) { - return '' + text + ''; -}; - -Renderer.prototype.br = function() { - return this.options.xhtml ? '
    ' : '
    '; -}; - -Renderer.prototype.del = function(text) { - return '' + text + ''; -}; - -Renderer.prototype.link = function(href, title, text) { - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(unescape(href)) - .replace(/[^\w:]/g, '') - .toLowerCase(); - } catch (e) { - return text; - } - if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { - return text; - } - } - if (this.options.baseUrl && !originIndependentUrl.test(href)) { - href = resolveUrl(this.options.baseUrl, href); - } - var out = '
    '; - return out; -}; - -Renderer.prototype.image = function(href, title, text) { - if (this.options.baseUrl && !originIndependentUrl.test(href)) { - href = resolveUrl(this.options.baseUrl, href); - } - var out = '' + text + '' : '>'; - return out; -}; - -Renderer.prototype.text = function(text) { - return text; -}; - -/** - * TextRenderer - * returns only the textual part of the token - */ - -function TextRenderer() {} - -// no need for block level renderers - -TextRenderer.prototype.strong = -TextRenderer.prototype.em = -TextRenderer.prototype.codespan = -TextRenderer.prototype.del = -TextRenderer.prototype.text = function (text) { - return text; -}; - -TextRenderer.prototype.link = -TextRenderer.prototype.image = function(href, title, text) { - return '' + text; -}; - -TextRenderer.prototype.br = function() { - return ''; -}; - -/** - * Parsing & Compiling - */ - -function Parser(options) { - this.tokens = []; - this.token = null; - this.options = options || marked.defaults; - this.options.renderer = this.options.renderer || new Renderer(); - this.renderer = this.options.renderer; - this.renderer.options = this.options; -} - -/** - * Static Parse Method - */ - -Parser.parse = function(src, options) { - var parser = new Parser(options); - return parser.parse(src); -}; - -/** - * Parse Loop - */ - -Parser.prototype.parse = function(src) { - this.inline = new InlineLexer(src.links, this.options); - // use an InlineLexer with a TextRenderer to extract pure text - this.inlineText = new InlineLexer( - src.links, - merge({}, this.options, {renderer: new TextRenderer()}) - ); - this.tokens = src.reverse(); + // enter + var hideToggleEnter = hideToggle.enter() + .append('a') + .attr('href', '#') + .attr('class', 'hide-toggle hide-toggle-' + key) + .call(svgIcon('', 'pre-text', 'hide-toggle-icon')); - var out = ''; - while (this.next()) { - out += this.tok(); - } + hideToggleEnter + .append('span') + .attr('class', 'hide-toggle-text'); - return out; -}; + // update + hideToggle = hideToggleEnter + .merge(hideToggle); -/** - * Next Token - */ + hideToggle + .on('click', toggle) + .classed('expanded', _expanded); -Parser.prototype.next = function() { - return this.token = this.tokens.pop(); -}; + hideToggle.selectAll('.hide-toggle-text') + .text(_title); -/** - * Preview Next Token - */ + hideToggle.selectAll('.hide-toggle-icon') + .attr('xlink:href', _expanded ? '#icon-down' + : (textDirection === 'rtl') ? '#icon-backward' : '#icon-forward' + ); -Parser.prototype.peek = function() { - return this.tokens[this.tokens.length - 1] || 0; -}; -/** - * Parse Text Tokens - */ + var wrap = selection$$1.selectAll('.disclosure-wrap') + .data([0]); -Parser.prototype.parseText = function() { - var body = this.token.text; + wrap = wrap.enter() + .append('div') + .attr('class', 'disclosure-wrap disclosure-wrap-' + key) + .merge(wrap); - while (this.peek().type === 'text') { - body += '\n' + this.next().text; - } + wrap + .classed('hide', !_expanded) + .call(_content); - return this.inline.output(body); -}; -/** - * Parse Current Token - */ + function toggle() { + event.preventDefault(); -Parser.prototype.tok = function() { - switch (this.token.type) { - case 'space': { - return ''; - } - case 'hr': { - return this.renderer.hr(); - } - case 'heading': { - return this.renderer.heading( - this.inline.output(this.token.text), - this.token.depth, - unescape(this.inlineText.output(this.token.text))); - } - case 'code': { - return this.renderer.code(this.token.text, - this.token.lang, - this.token.escaped); - } - case 'table': { - var header = '', - body = '', - i, - row, - cell, - j; + _expanded = !_expanded; - // header - cell = ''; - for (i = 0; i < this.token.header.length; i++) { - cell += this.renderer.tablecell( - this.inline.output(this.token.header[i]), - { header: true, align: this.token.align[i] } - ); - } - header += this.renderer.tablerow(cell); + if (_updatePreference) { + context.storage('disclosure.' + key + '.expanded', _expanded); + } - for (i = 0; i < this.token.cells.length; i++) { - row = this.token.cells[i]; + hideToggle + .classed('expanded', _expanded); - cell = ''; - for (j = 0; j < row.length; j++) { - cell += this.renderer.tablecell( - this.inline.output(row[j]), - { header: false, align: this.token.align[j] } - ); - } + hideToggle.selectAll('.hide-toggle-icon') + .attr('xlink:href', _expanded ? '#icon-down' + : (textDirection === 'rtl') ? '#icon-backward' : '#icon-forward' + ); - body += this.renderer.tablerow(cell); - } - return this.renderer.table(header, body); - } - case 'blockquote_start': { - body = ''; + wrap + .call(uiToggle(_expanded)); - while (this.next().type !== 'blockquote_end') { - body += this.tok(); - } + dispatch$$1.call('toggled', this, _expanded); + } + }; - return this.renderer.blockquote(body); - } - case 'list_start': { - body = ''; - var ordered = this.token.ordered; - while (this.next().type !== 'list_end') { - body += this.tok(); - } + disclosure.title = function(_) { + if (!arguments.length) return _title; + _title = _; + return disclosure; + }; - return this.renderer.list(body, ordered); - } - case 'list_item_start': { - body = ''; - while (this.next().type !== 'list_item_end') { - body += this.token.type === 'text' - ? this.parseText() - : this.tok(); - } + disclosure.expanded = function(_) { + if (!arguments.length) return _expanded; + _expanded = _; + return disclosure; + }; - return this.renderer.listitem(body); - } - case 'loose_item_start': { - body = ''; - while (this.next().type !== 'list_item_end') { - body += this.tok(); - } + disclosure.updatePreference = function(_) { + if (!arguments.length) return _updatePreference; + _updatePreference = _; + return disclosure; + }; - return this.renderer.listitem(body); - } - case 'html': { - var html = !this.token.pre && !this.options.pedantic - ? this.inline.output(this.token.text) - : this.token.text; - return this.renderer.html(html); - } - case 'paragraph': { - return this.renderer.paragraph(this.inline.output(this.token.text)); - } - case 'text': { - return this.renderer.paragraph(this.parseText()); - } - } -}; -/** - * Helpers - */ + disclosure.content = function(_) { + if (!arguments.length) return _content; + _content = _; + return disclosure; + }; -function escape(html, encode) { - return html - .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} -function unescape(html) { - // explicitly match decimal, hex, and named HTML entities - return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) { - n = n.toLowerCase(); - if (n === 'colon') return ':'; - if (n.charAt(0) === '#') { - return n.charAt(1) === 'x' - ? String.fromCharCode(parseInt(n.substring(2), 16)) - : String.fromCharCode(+n.substring(1)); - } - return ''; - }); -} - -function edit(regex, opt) { - regex = regex.source; - opt = opt || ''; - return { - replace: function(name, val) { - val = val.source || val; - val = val.replace(/(^|[^\[])\^/g, '$1'); - regex = regex.replace(name, val); - return this; - }, - getRegex: function() { - return new RegExp(regex, opt); - } - }; -} - -function resolveUrl(base, href) { - if (!baseUrls[' ' + base]) { - // we can ignore everything in base after the last slash of its path component, - // but we might need to add _that_ - // https://tools.ietf.org/html/rfc3986#section-3 - if (/^[^:]+:\/*[^/]*$/.test(base)) { - baseUrls[' ' + base] = base + '/'; - } else { - baseUrls[' ' + base] = base.replace(/[^/]*$/, ''); - } + return utilRebind(disclosure, dispatch$$1, 'on'); } - base = baseUrls[' ' + base]; - if (href.slice(0, 2) === '//') { - return base.replace(/:[\s\S]*/, ':') + href; - } else if (href.charAt(0) === '/') { - return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href; - } else { - return base + href; - } -} -var baseUrls = {}; -var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; + function uiBackgroundDisplayOptions(context) { + var detected = utilDetect(); + var storedOpacity = context.storage('background-opacity'); + var minVal = 0.25; + var maxVal = detected.cssfilters ? 2 : 1; + + var sliders = detected.cssfilters + ? ['brightness', 'contrast', 'saturation', 'sharpness'] + : ['brightness']; + + var _options = { + brightness: (storedOpacity !== null ? (+storedOpacity) : 1), + contrast: 1, + saturation: 1, + sharpness: 1 + }; -function noop() {} -noop.exec = noop; + var _selection = select(null); -function merge(obj) { - var i = 1, - target, - key; - for (; i < arguments.length; i++) { - target = arguments[i]; - for (key in target) { - if (Object.prototype.hasOwnProperty.call(target, key)) { - obj[key] = target[key]; + function clamp(x, min, max) { + return Math.max(min, Math.min(x, max)); } - } - } - return obj; -} -/** - * Marked - */ - -function marked(src, opt, callback) { - // throw error in case of non string input - if (typeof src === 'undefined' || src === null) { - throw new Error('marked(): input parameter is undefined or null'); - } - if (typeof src !== 'string') { - throw new Error('marked(): input parameter is of type ' - + Object.prototype.toString.call(src) + ', string expected'); - } - - if (callback || typeof opt === 'function') { - if (!callback) { - callback = opt; - opt = null; - } - - opt = merge({}, marked.defaults, opt || {}); + function updateValue(d, val) { + if (!val && event && event.target) { + val = event.target.value; + } - var highlight = opt.highlight, - tokens, - pending, - i = 0; + val = clamp(val, minVal, maxVal); - try { - tokens = Lexer.lex(src, opt); - } catch (e) { - return callback(e); - } + _options[d] = val; + context.background()[d](val); - pending = tokens.length; + if (d === 'brightness') { + context.storage('background-opacity', val); + } - var done = function(err) { - if (err) { - opt.highlight = highlight; - return callback(err); + _selection + .call(render); } - var out; - try { - out = Parser.parse(tokens, opt); - } catch (e) { - err = e; + function render(selection$$1) { + var container = selection$$1.selectAll('.display-options-container') + .data([0]); + + var containerEnter = container.enter() + .append('div') + .attr('class', 'display-options-container controls-list'); + + // add slider controls + var slidersEnter = containerEnter.selectAll('.display-control') + .data(sliders) + .enter() + .append('div') + .attr('class', function(d) { return 'display-control display-control-' + d; }); + + slidersEnter + .append('h5') + .text(function(d) { return t('background.' + d); }) + .append('span') + .attr('class', function(d) { return 'display-option-value display-option-value-' + d; }); + + slidersEnter + .append('input') + .attr('class', function(d) { return 'display-option-input display-option-input-' + d; }) + .attr('type', 'range') + .attr('min', minVal) + .attr('max', maxVal) + .attr('step', '0.05') + .on('input', function(d) { + var val = select(this).property('value'); + updateValue(d, val); + }); + + slidersEnter + .append('button') + .attr('title', t('background.reset')) + .attr('class', function(d) { return 'display-option-reset display-option-reset-' + d; }) + .on('click', function(d) { + if (event.button !== 0) return; + updateValue(d, 1); + }) + .call(svgIcon('#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo'))); + + + // update + container = containerEnter + .merge(container); + + container.selectAll('.display-option-input') + .property('value', function(d) { return _options[d]; }); + + container.selectAll('.display-option-value') + .text(function(d) { return Math.floor(_options[d] * 100) + '%'; }); + + container.selectAll('.display-option-reset') + .classed('disabled', function(d) { return _options[d] === 1; }); + + // first time only, set brightness if needed + if (containerEnter.size() && _options.brightness !== 1) { + context.background().brightness(_options.brightness); + } } - opt.highlight = highlight; - return err - ? callback(err) - : callback(null, out); - }; - - if (!highlight || highlight.length < 3) { - return done(); - } - - delete opt.highlight; - - if (!pending) return done(); - - for (; i < tokens.length; i++) { - (function(token) { - if (token.type !== 'code') { - return --pending || done(); - } - return highlight(token.text, token.lang, function(err, code) { - if (err) return done(err); - if (code == null || code === token.text) { - return --pending || done(); - } - token.text = code; - token.escaped = true; - --pending || done(); - }); - })(tokens[i]); - } - - return; - } - try { - if (opt) opt = merge({}, marked.defaults, opt); - return Parser.parse(Lexer.lex(src, opt), opt); - } catch (e) { - e.message += '\nPlease report this to https://github.com/chjj/marked.'; - if ((opt || marked.defaults).silent) { - return '

    An error occurred:

    '
    -        + escape(e.message + '', true)
    -        + '
    '; - } - throw e; - } -} - -/** - * Options - */ - -marked.options = -marked.setOptions = function(opt) { - merge(marked.defaults, opt); - return marked; -}; - -marked.defaults = { - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: false, - sanitizer: null, - mangle: true, - smartLists: false, - silent: false, - highlight: null, - langPrefix: 'lang-', - smartypants: false, - headerPrefix: '', - renderer: new Renderer(), - xhtml: false, - baseUrl: null -}; - -/** - * Expose - */ - -marked.Parser = Parser; -marked.parser = Parser.parse; - -marked.Renderer = Renderer; -marked.TextRenderer = TextRenderer; - -marked.Lexer = Lexer; -marked.lexer = Lexer.lex; - -marked.InlineLexer = InlineLexer; -marked.inlineLexer = InlineLexer.output; - -marked.parse = marked; - -{ - module.exports = marked; -} -})(commonjsGlobal || (typeof window !== 'undefined' ? window : commonjsGlobal)); -}); - -function pointBox(loc, context) { - var rect = context.surfaceRect(); - var point$$1 = context.curtainProjection(loc); - return { - left: point$$1[0] + rect.left - 40, - top: point$$1[1] + rect.top - 60, - width: 80, - height: 90 - }; -} + function backgroundDisplayOptions(selection$$1) { + _selection = selection$$1; + selection$$1 + .call(uiDisclosure(context, 'background_display_options', true) + .title(t('background.display_options')) + .content(render) + ); + } -function pad$1(locOrBox, padding, context) { - var box; - if (locOrBox instanceof Array) { - var rect = context.surfaceRect(); - var point$$1 = context.curtainProjection(locOrBox); - box = { - left: point$$1[0] + rect.left, - top: point$$1[1] + rect.top - }; - } else { - box = locOrBox; - } - - return { - left: box.left - padding, - top: box.top - padding, - width: (box.width || 0) + 2 * padding, - height: (box.width || 0) + 2 * padding - }; -} + return backgroundDisplayOptions; + } -function icon(name, svgklass, useklass) { - return '' + - ''; -} + function uiBackgroundOffset(context) { + var directions = [ + ['right', [0.5, 0]], + ['top', [0, -0.5]], + ['left', [-0.5, 0]], + ['bottom', [0, 0.5]] + ]; -function slugify(text) { - return text.toString().toLowerCase() - .replace(/\s+/g, '-') // Replace spaces with - - .replace(/[^\w\-]+/g, '') // Remove all non-word chars - .replace(/\-\-+/g, '-') // Replace multiple - with single - - .replace(/^-+/, '') // Trim - from start of text - .replace(/-+$/, ''); // Trim - from end of text -} + function d3_eventCancel() { + event.stopPropagation(); + event.preventDefault(); + } -// console warning for missing walkthrough names -var missingStrings = {}; -function checkKey(key, text) { - if (t(key, { default: undefined}) === undefined) { - if (missingStrings.hasOwnProperty(key)) return; // warn once - missingStrings[key] = text; - var missing = key + ': ' + text; - if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line - } -} + function updateValue() { + var meters = geoOffsetToMeters(context.background().offset()); + var x = +meters[0].toFixed(2); + var y = +meters[1].toFixed(2); + d3_selectAll('.nudge-inner-rect') + .select('input') + .classed('error', false) + .property('value', x + ', ' + y); -function localize(obj) { - var key; + d3_selectAll('.nudge-reset') + .classed('disabled', function() { + return (x === 0 && y === 0); + }); + } - // Assign name if entity has one.. - var name = obj.tags && obj.tags.name; - if (name) { - key = 'intro.graph.name.' + slugify(name); - obj.tags.name = t(key, { default: name }); - checkKey(key, name); - } - // Assign street name if entity has one.. - var street = obj.tags && obj.tags['addr:street']; - if (street) { - key = 'intro.graph.name.' + slugify(street); - obj.tags['addr:street'] = t(key, { default: street }); - checkKey(key, street); + function resetOffset() { + context.background().offset([0, 0]); + updateValue(); + } - // Add address details common across walkthrough.. - var addrTags = [ - 'block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood', - 'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb' - ]; - addrTags.forEach(function(k) { - var key = 'intro.graph.' + k, - tag = 'addr:' + k, - val = obj.tags && obj.tags[tag], - str = t(key, { default: val }); - - if (str) { - if (str.match(/^<.*>$/) !== null) { - delete obj.tags[tag]; - } else { - obj.tags[tag] = str; - } - } - }); - } - return obj; -} - - -// Used to detect squareness.. some duplicataion of code from actionOrthogonalize. -function isMostlySquare(points) { - // note: uses 15 here instead of the 12 from actionOrthogonalize because - // actionOrthogonalize can actually straighten some larger angles as it iterates - var threshold = 15, // degrees within right or straight - lowerBound = Math.cos((90 - threshold) * Math.PI / 180), // near right - upperBound = Math.cos(threshold * Math.PI / 180), // near straight - mag; - - for (var i = 0; i < points.length; i++) { - mag = Math.abs(normalizedDotProduct(i, points)); - if (mag > lowerBound && mag < upperBound) { - return false; - } - } + function nudge(d) { + context.background().nudge(d, context.map().zoom()); + updateValue(); + } - return true; + function clickNudgeButton(d) { + var interval; + var timeout = window.setTimeout(function() { + interval = window.setInterval(nudge.bind(null, d), 100); + }, 500); - function normalizedDotProduct(i, points) { - var a = points[(i - 1 + points.length) % points.length], - b = points[i], - c = points[(i + 1) % points.length], - p = subtractPoints(a, b), - q = subtractPoints(c, b); + function doneNudge() { + window.clearTimeout(timeout); + window.clearInterval(interval); + select(window) + .on('mouseup.buttonoffset', null, true) + .on('mousedown.buttonoffset', null, true); + } - p = normalizePoint(p); - q = normalizePoint(q); + select(window) + .on('mouseup.buttonoffset', doneNudge, true) + .on('mousedown.buttonoffset', doneNudge, true); - return p[0] * q[0] + p[1] * q[1]; + nudge(d); + } - function subtractPoints(a, b) { - return [a[0] - b[0], a[1] - b[1]]; - } + function inputOffset() { + var input = select(this); + var d = input.node().value; - function normalizePoint(point$$1) { - var vector = [0, 0]; - var length = Math.sqrt(point$$1[0] * point$$1[0] + point$$1[1] * point$$1[1]); - if (length !== 0) { - vector[0] = point$$1[0] / length; - vector[1] = point$$1[1] / length; - } - return vector; - } - } -} + if (d === '') return resetOffset(); + d = d.replace(/;/g, ',').split(',').map(function(n) { + // if n is NaN, it will always get mapped to false. + return !isNaN(n) && n; + }); -function selectMenuItem(operation) { - var selector$$1 = '.edit-menu .edit-menu-item-' + operation + - ', .radial-menu .radial-menu-item-' + operation; - return d3_select(selector$$1); -} + if (d.length !== 2 || !d[0] || !d[1]) { + input.classed('error', true); + return; + } + context.background().offset(geoMetersToOffset(d)); + updateValue(); + } -function transitionTime(point1, point2) { - var distance = geoSphericalDistance(point1, point2); - if (distance === 0) - return 0; - else if (distance < 80) - return 500; - else - return 1000; -} -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","traffic_signals:direction":"both"}},"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","traffic_signals:direction":"both"}},"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","traffic_signals:direction":"both"}},"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.616762,41.952222]},"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.616557,41.951997]},"n3867":{"id":"n3867","loc":[-85.61658,41.952093]},"n3868":{"id":"n3868","loc":[-85.616636,41.952145]},"n3869":{"id":"n3869","loc":[-85.616918,41.952276]},"n387":{"id":"n387","loc":[-85.632524,41.943912]},"n3870":{"id":"n3870","loc":[-85.617098,41.952235]},"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.616502,41.951946]},"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","direction":"forward","stop":"minor"}},"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","direction":"forward"}},"n4501":{"id":"n4501","loc":[-85.627921,41.954783],"tags":{"highway":"stop","stop":"all","direction":"backward"}},"n4502":{"id":"n4502","loc":[-85.62775,41.954696],"tags":{"highway":"stop","stop":"all","direction":"backward"}},"n4503":{"id":"n4503","loc":[-85.628046,41.954591],"tags":{"highway":"stop","stop":"all","direction":"forward"}},"n4504":{"id":"n4504","loc":[-85.631074,41.957428],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4505":{"id":"n4505","loc":[-85.630768,41.957429],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"n4506":{"id":"n4506","loc":[-85.629888,41.957432],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4507":{"id":"n4507","loc":[-85.629565,41.957433],"tags":{"highway":"stop","stop":"minor","direction":"forward"}},"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","stop":"minor","direction":"backward"}},"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","direction":"forward","stop":"minor"}},"n4536":{"id":"n4536","loc":[-85.630881,41.954806],"tags":{"highway":"stop","stop":"minor","direction":"backward"}},"n4537":{"id":"n4537","loc":[-85.630879,41.954564],"tags":{"highway":"stop","stop":"minor","direction":"forward"}},"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","stop":"minor","direction":"backward"}},"n4544":{"id":"n4544","loc":[-85.632071,41.959029],"tags":{"highway":"stop","stop":"minor","direction":"forward"}},"n4545":{"id":"n4545","loc":[-85.632257,41.959027],"tags":{"highway":"stop","stop":"minor","direction":"backward"}},"n4546":{"id":"n4546","loc":[-85.631966,41.957427],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"n4547":{"id":"n4547","loc":[-85.632297,41.957426],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4548":{"id":"n4548","loc":[-85.631976,41.955911],"tags":{"highway":"give_way","direction":"forward"}},"n4549":{"id":"n4549","loc":[-85.632272,41.955911],"tags":{"highway":"give_way","direction":"backward"}},"n455":{"id":"n455","loc":[-85.635224,41.943869]},"n4550":{"id":"n4550","loc":[-85.632097,41.954805],"tags":{"highway":"stop","stop":"minor","direction":"backward"}},"n4551":{"id":"n4551","loc":[-85.632094,41.954566],"tags":{"highway":"stop","stop":"minor","direction":"forward"}},"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","direction":"backward","stop":"minor"}},"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","direction":"forward","stop":"minor"}},"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","direction":"forward","stop":"minor"}},"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","direction":"forward","stop":"minor"}},"n4587":{"id":"n4587","loc":[-85.620485,41.951948],"tags":{"emergency":"fire_hydrant"}},"n4588":{"id":"n4588","loc":[-85.620316,41.950999],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4589":{"id":"n4589","loc":[-85.620311,41.950131],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"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","direction":"backward","stop":"minor"}},"n4592":{"id":"n4592","loc":[-85.620278,41.947443],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4593":{"id":"n4593","loc":[-85.619844,41.947444],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"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","stop":"minor","direction":"backward"}},"n4597":{"id":"n4597","loc":[-85.622739,41.947316],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"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","direction":"forward","stop":"minor"}},"n4602":{"id":"n4602","loc":[-85.622769,41.949325],"tags":{"highway":"stop","stop":"minor","direction":"backward"}},"n4603":{"id":"n4603","loc":[-85.622837,41.949329],"tags":{"emergency":"fire_hydrant"}},"n4604":{"id":"n4604","loc":[-85.622614,41.950113],"tags":{"highway":"give_way","direction":"forward"}},"n4605":{"id":"n4605","loc":[-85.624777,41.949219],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"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","stop":"minor","direction":"forward"}},"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.618232,41.949913]},"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","direction":"forward","stop":"minor"}},"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","direction":"forward","stop":"minor"}},"n4685":{"id":"n4685","loc":[-85.635961,41.940125],"tags":{"highway":"stop","stop":"minor","direction":"backward"}},"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","direction":"forward","stop":"minor"}},"n4695":{"id":"n4695","loc":[-85.637174,41.941354],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4696":{"id":"n4696","loc":[-85.637091,41.941273],"tags":{"emergency":"fire_hydrant"}},"n4697":{"id":"n4697","loc":[-85.638058,41.941346],"tags":{"highway":"give_way","direction":"forward"}},"n4698":{"id":"n4698","loc":[-85.638359,41.941344],"tags":{"highway":"give_way","direction":"backward"}},"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","direction":"forward"}},"n4702":{"id":"n4702","loc":[-85.639548,41.941334],"tags":{"highway":"give_way","direction":"backward"}},"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","direction":"forward","stop":"minor"}},"n4706":{"id":"n4706","loc":[-85.640803,41.941324],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4707":{"id":"n4707","loc":[-85.641717,41.941317],"tags":{"highway":"stop","direction":"forward","stop":"all"}},"n4708":{"id":"n4708","loc":[-85.641846,41.941415],"tags":{"highway":"stop","direction":"backward","stop":"all"}},"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","direction":"forward","stop":"all"}},"n4711":{"id":"n4711","loc":[-85.641854,41.942455],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"n4712":{"id":"n4712","loc":[-85.641859,41.942739],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4713":{"id":"n4713","loc":[-85.640754,41.942707],"tags":{"emergency":"fire_hydrant"}},"n4714":{"id":"n4714","loc":[-85.640669,41.942716],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4715":{"id":"n4715","loc":[-85.640664,41.942478],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"n4716":{"id":"n4716","loc":[-85.63964,41.94274],"tags":{"man_made":"flagpole"}},"n4717":{"id":"n4717","loc":[-85.639455,41.942731],"tags":{"highway":"stop","direction":"backward","stop":"minor"}},"n4718":{"id":"n4718","loc":[-85.63945,41.942492],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"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","direction":"backward","stop":"minor"}},"n4721":{"id":"n4721","loc":[-85.638233,41.942511],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"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","direction":"forward","stop":"minor"}},"n4726":{"id":"n4726","loc":[-85.633467,41.943818],"tags":{"highway":"stop","stop":"minor","direction":"backward"}},"n4727":{"id":"n4727","loc":[-85.633987,41.943531],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"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","stop":"minor","direction":"backward"}},"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","direction":"forward","stop":"minor"}},"n4746":{"id":"n4746","loc":[-85.639635,41.94387],"tags":{"highway":"stop","stop":"minor","direction":"backward"}},"n4747":{"id":"n4747","loc":[-85.639549,41.943756],"tags":{"emergency":"fire_hydrant"}},"n4748":{"id":"n4748","loc":[-85.64055,41.943862],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"n4749":{"id":"n4749","loc":[-85.640864,41.943859],"tags":{"highway":"stop","stop":"minor","direction":"backward"}},"n475":{"id":"n475","loc":[-85.633906,41.943535]},"n4750":{"id":"n4750","loc":[-85.640718,41.945022],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"n4751":{"id":"n4751","loc":[-85.640664,41.945076],"tags":{"emergency":"fire_hydrant"}},"n4752":{"id":"n4752","loc":[-85.641913,41.94502],"tags":{"highway":"stop","direction":"forward","stop":"minor"}},"n4753":{"id":"n4753","loc":[-85.641838,41.945076],"tags":{"emergency":"fire_hydrant"}},"n4754":{"id":"n4754","loc":[-85.642045,41.94385],"tags":{"highway":"give_way","direction":"backward"}},"n4755":{"id":"n4755","loc":[-85.641738,41.943852],"tags":{"highway":"give_way","direction":"forward"}},"n4756":{"id":"n4756","loc":[-85.642928,41.943843],"tags":{"highway":"stop","stop":"minor","direction":"forward"}},"n4757":{"id":"n4757","loc":[-85.64305,41.943902],"tags":{"emergency":"fire_hydrant"}},"n4758":{"id":"n4758","loc":[-85.642986,41.945105],"tags":{"highway":"stop","direction":"backward","stop":"all"}},"n4759":{"id":"n4759","loc":[-85.643136,41.94502],"tags":{"highway":"stop","stop":"all","direction":"forward"}},"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","n2938","n3866","n2939","n3867","n3868","n3858","n2937","n3869","n2935","n2934","n3870","n3348","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","n3351","n3950","n3354","n3350","n3951","n3349","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"}},"n2934":{"id":"n2934","loc":[-85.617051,41.952263]},"n2935":{"id":"n2935","loc":[-85.61699,41.952276]},"n2937":{"id":"n2937","loc":[-85.616847,41.952262]},"n2938":{"id":"n2938","loc":[-85.616577,41.951956]},"n2939":{"id":"n2939","loc":[-85.61656,41.952044]},"n3348":{"id":"n3348","loc":[-85.61714,41.9522]},"n3349":{"id":"n3349","loc":[-85.616517,41.95212]},"n3350":{"id":"n3350","loc":[-85.616489,41.952033]},"n3351":{"id":"n3351","loc":[-85.616529,41.951907]},"n3354":{"id":"n3354","loc":[-85.616488,41.951994]}}; + function dragOffset() { + event.preventDefault(); + if (event.button !== 0) return; + + var origin = [event.clientX, event.clientY]; + + context.container() + .append('div') + .attr('class', 'nudge-surface'); + + select(window) + .on('mousemove.offset', function() { + var latest = [event.clientX, event.clientY]; + var d = [ + -(origin[0] - latest[0]) / 4, + -(origin[1] - latest[1]) / 4 + ]; + + origin = latest; + nudge(d); + }) + .on('mouseup.offset', function() { + if (event.button !== 0) return; + d3_selectAll('.nudge-surface') + .remove(); + + select(window) + .on('mousemove.offset', null) + .on('mouseup.offset', null); + }); + } -// Tooltips and svg mask used to highlight certain features -function uiCurtain() { - var surface = d3_select(null), - tooltip = d3_select(null), - darkness = d3_select(null); + function render(selection$$1) { + var container = selection$$1.selectAll('.nudge-container') + .data([0]); + + var containerEnter = container.enter() + .append('div') + .attr('class', 'nudge-container cf'); + + containerEnter + .append('div') + .attr('class', 'nudge-instructions') + .text(t('background.offset')); + + var nudgeEnter = containerEnter + .append('div') + .attr('class', 'nudge-outer-rect') + .on('mousedown', dragOffset); + + nudgeEnter + .append('div') + .attr('class', 'nudge-inner-rect') + .append('input') + .on('change', inputOffset); + + containerEnter + .append('div') + .selectAll('button') + .data(directions).enter() + .append('button') + .attr('class', function(d) { return d[0] + ' nudge'; }) + .on('contextmenu', d3_eventCancel) + .on('mousedown', function(d) { + if (event.button !== 0) return; + clickNudgeButton(d[1]); + }); + + containerEnter + .append('button') + .attr('title', t('background.reset')) + .attr('class', 'nudge-reset disabled') + .on('contextmenu', d3_eventCancel) + .on('click', function() { + if (event.button !== 0) return; + resetOffset(); + }) + .call(svgIcon('#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo'))); + + updateValue(); + } - function curtain(selection$$1) { - surface = selection$$1 - .append('svg') - .attr('id', 'curtain') - .style('z-index', 1000) - .style('pointer-events', 'none') - .style('position', 'absolute') - .style('top', 0) - .style('left', 0); - darkness = surface.append('path') - .attr('x', 0) - .attr('y', 0) - .attr('class', 'curtain-darkness'); + function backgroundOffset(selection$$1) { + selection$$1 + .call(uiDisclosure(context, 'background_offset', false) + .title(t('background.fix_misalignment')) + .content(render) + ); + } - d3_select(window).on('resize.curtain', resize); - tooltip = selection$$1.append('div') - .attr('class', 'tooltip') - .style('z-index', 1002); + context.background() + .on('change.backgroundOffset-update', updateValue); - tooltip - .append('div') - .attr('class', 'tooltip-arrow'); + return backgroundOffset; + } - tooltip - .append('div') - .attr('class', 'tooltip-inner'); + var marked = createCommonjsModule(function (module, exports) { + (function(root) { - resize(); + /** + * Block-Level Grammar + */ + var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, + nptable: noop, + blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, + def: /^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, + table: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + paragraph: /^([^\n]+(?:\n?(?!hr|heading|lheading| {0,3}>|tag)[^\n]+)+)/, + text: /^[^\n]+/ + }; - function resize() { - surface - .attr('width', window.innerWidth) - .attr('height', window.innerHeight); - curtain.cut(darkness.datum()); - } - } + block._label = /(?:\\[\[\]]|[^\[\]])+/; + block._title = /(?:"(?:\\"|[^"]|"[^"\n]*")*"|'\n?(?:[^'\n]+\n?)*'|\([^()]*\))/; + block.def = edit(block.def) + .replace('label', block._label) + .replace('title', block._title) + .getRegex(); + + block.bullet = /(?:[*+-]|\d+\.)/; + block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; + block.item = edit(block.item, 'gm') + .replace(/bull/g, block.bullet) + .getRegex(); + + block.list = edit(block.list) + .replace(/bull/g, block.bullet) + .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))') + .replace('def', '\\n+(?=' + block.def.source + ')') + .getRegex(); + + block._tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b'; + + block.html = edit(block.html) + .replace('comment', //) + .replace('closed', /<(tag)[\s\S]+?<\/\1>/) + .replace('closing', /\s]*)*?\/?>/) + .replace(/tag/g, block._tag) + .getRegex(); + + block.paragraph = edit(block.paragraph) + .replace('hr', block.hr) + .replace('heading', block.heading) + .replace('lheading', block.lheading) + .replace('tag', '<' + block._tag) + .getRegex(); + + block.blockquote = edit(block.blockquote) + .replace('paragraph', block.paragraph) + .getRegex(); + /** + * Normal Block Grammar + */ - /** - * Reveal cuts the curtain to highlight the given box, - * and shows a tooltip with instructions next to the box. - * - * @param {String|ClientRect} [box] box used to cut the curtain - * @param {String} [text] text for a tooltip - * @param {Object} [options] - * @param {string} [options.tooltipClass] optional class to add to the tooltip - * @param {integer} [options.duration] transition time in milliseconds - * @param {string} [options.buttonText] if set, create a button with this text label - * @param {function} [options.buttonCallback] if set, the callback for the button - * @param {String|ClientRect} [options.tooltipBox] box for tooltip position, if different from box for the curtain - */ - curtain.reveal = function(box, text, options) { - if (typeof box === 'string') { - box = d3_select(box).node(); - } - if (box && box.getBoundingClientRect) { - box = copyBox(box.getBoundingClientRect()); - } + block.normal = merge({}, block); - options = options || {}; + /** + * GFM Block Grammar + */ - var tooltipBox; - if (options.tooltipBox) { - tooltipBox = options.tooltipBox; - if (typeof tooltipBox === 'string') { - tooltipBox = d3_select(tooltipBox).node(); - } - if (tooltipBox && tooltipBox.getBoundingClientRect) { - tooltipBox = copyBox(tooltipBox.getBoundingClientRect()); - } - } else { - tooltipBox = box; - } + block.gfm = merge({}, block.normal, { + fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ + }); - if (tooltipBox && text) { - // pseudo markdown bold text for the instruction section.. - var parts = text.split('**'); - var html = parts[0] ? '' + parts[0] + '' : ''; - if (parts[1]) { - html += '' + parts[1] + ''; - } + block.gfm.paragraph = edit(block.paragraph) + .replace('(?!', '(?!' + + block.gfm.fences.source.replace('\\1', '\\2') + '|' + + block.list.source.replace('\\1', '\\3') + '|') + .getRegex(); - html = html.replace(/\*(.*?)\*/g, '$1'); // emphasis - html = html.replace(/\{br\}/g, '

    '); // linebreak + /** + * GFM + Tables Block Grammar + */ - if (options.buttonText && options.buttonCallback) { - html += '
    ' + - '
    '; - } + block.tables = merge({}, block.gfm, { + nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, + table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ + }); - var classes = 'curtain-tooltip tooltip in ' + (options.tooltipClass || ''); - tooltip - .classed(classes, true) - .selectAll('.tooltip-inner') - .html(html); - - if (options.buttonText && options.buttonCallback) { - var button = tooltip.selectAll('.button-section .button.action'); - button - .on('click', function() { - event.preventDefault(); - options.buttonCallback(); - }); - } + /** + * Block Lexer + */ - var tip = copyBox(tooltip.node().getBoundingClientRect()), - w = window.innerWidth, - h = window.innerHeight, - tooltipWidth = 200, - tooltipArrow = 5, - side, pos; + function Lexer(options) { + this.tokens = []; + this.tokens.links = {}; + this.options = options || marked.defaults; + this.rules = block.normal; + if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } + } - // hack: this will have bottom placement, - // so need to reserve extra space for the tooltip illustration. - if (options.tooltipClass === 'intro-mouse') { - tip.height += 80; - } + /** + * Expose Block Rules + */ - // trim box dimensions to just the portion that fits in the window.. - if (tooltipBox.top + tooltipBox.height > h) { - tooltipBox.height -= (tooltipBox.top + tooltipBox.height - h); - } - if (tooltipBox.left + tooltipBox.width > w) { - tooltipBox.width -= (tooltipBox.left + tooltipBox.width - w); - } + Lexer.rules = block; - // determine tooltip placement.. + /** + * Static Lex Method + */ - if (tooltipBox.top + tooltipBox.height < 100) { - // tooltip below box.. - side = 'bottom'; - pos = [ - tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, - tooltipBox.top + tooltipBox.height - ]; + Lexer.lex = function(src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); + }; - } else if (tooltipBox.top > h - 140) { - // tooltip above box.. - side = 'top'; - pos = [ - tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, - tooltipBox.top - tip.height - ]; + /** + * Preprocessing + */ - } else { - // tooltip to the side of the tooltipBox.. - var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2; - - if (textDirection === 'rtl') { - if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) { - side = 'right'; - pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY]; - - } else { - side = 'left'; - pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY]; - } - - } else { - if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) { - side = 'left'; - pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY]; - } - else { - side = 'right'; - pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY]; - } - } - } + Lexer.prototype.lex = function(src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' ') + .replace(/\u00a0/g, ' ') + .replace(/\u2424/g, '\n'); - if (options.duration !== 0 || !tooltip.classed(side)) { - tooltip.call(uiToggle(true)); - } + return this.token(src, true); + }; - tooltip - .style('top', pos[1] + 'px') - .style('left', pos[0] + 'px') - .attr('class', classes + ' ' + side); - - - // shift tooltip-inner if it is very close to the top or bottom edge - // (doesn't affect the placement of the tooltip-arrow) - var shiftY = 0; - if (side === 'left' || side === 'right') { - if (pos[1] < 60) { - shiftY = 60 - pos[1]; - } - else if (pos[1] + tip.height > h - 100) { - shiftY = h - pos[1] - tip.height - 100; - } - } - tooltip.selectAll('.tooltip-inner') - .style('top', shiftY + 'px'); + /** + * Lexing + */ - } else { - tooltip - .classed('in', false) - .call(uiToggle(false)); + Lexer.prototype.token = function(src, top) { + src = src.replace(/^ +$/gm, ''); + var next, + loose, + cap, + bull, + b, + item, + space, + i, + tag, + l, + isordered; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); } + } - curtain.cut(box, options.duration); - - return tooltip; - }; + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic + ? cap.replace(/\n+$/, '') + : cap + }); + continue; + } + // fences (gfm) + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2], + text: cap[3] || '' + }); + continue; + } - curtain.cut = function(datum, duration) { - darkness.datum(datum) - .interrupt(); + // heading + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } - var selection$$1; - if (duration === 0) { - selection$$1 = darkness; - } else { - selection$$1 = darkness - .transition() - .duration(duration || 600) - .ease(linear$1); - } + // table no leading pipe (gfm) + if (top && (cap = this.rules.nptable.exec(src))) { + src = src.substring(cap[0].length); - selection$$1 - .attr('d', function(d) { - var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' + - window.innerWidth + ',' + window.innerHeight + 'L' + - window.innerWidth + ',0 Z'; + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/\n$/, '').split('\n') + }; - if (!d) return string; - return string + 'M' + - d.left + ',' + d.top + 'L' + - d.left + ',' + (d.top + d.height) + 'L' + - (d.left + d.width) + ',' + (d.top + d.height) + 'L' + - (d.left + d.width) + ',' + (d.top) + 'Z'; + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } - }); - }; + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i].split(/ *\| */); + } + this.tokens.push(item); - curtain.remove = function() { - surface.remove(); - tooltip.remove(); - d3_select(window).on('resize.curtain', null); - }; + continue; + } + // hr + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } - // ClientRects are immutable, so copy them to an object, - // in case we need to trim the height/width. - function copyBox(src) { - return { - top: src.top, - right: src.right, - bottom: src.bottom, - left: src.left, - width: src.width, - height: src.height - }; - } + // blockquote + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'blockquote_start' + }); - return curtain; -} + cap = cap[0].replace(/^ *> ?/gm, ''); -function uiIntroWelcome(context, reveal) { - var dispatch$$1 = dispatch('done'), - listener = clickListener(); + // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + this.token(cap, top); - var chapter = { - title: 'intro.welcome.title' - }; + this.tokens.push({ + type: 'blockquote_end' + }); + continue; + } - function welcome() { - context.map().centerZoom([-85.63591, 41.94285], 19); - reveal('.intro-nav-wrap .chapter-welcome', - t('intro.welcome.welcome'), - { buttonText: t('intro.ok'), buttonCallback: practice } - ); - } + // list + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + isordered = bull.length > 1; - function practice() { - reveal('.intro-nav-wrap .chapter-welcome', - t('intro.welcome.practice'), - { buttonText: t('intro.ok'), buttonCallback: words } - ); - } + this.tokens.push({ + type: 'list_start', + ordered: isordered, + start: isordered ? +bull : '' + }); - function words() { - reveal('.intro-nav-wrap .chapter-welcome', - t('intro.welcome.words'), - { buttonText: t('intro.ok'), buttonCallback: mouse } - ); - } + // Get each top-level item. + cap = cap[0].match(this.rules.item); + next = false; + l = cap.length; + i = 0; - function mouse() { - reveal('.intro-nav-wrap .chapter-welcome', - t('intro.welcome.mouse'), - { buttonText: t('intro.ok'), buttonCallback: leftClick } - ); - } + for (; i < l; i++) { + item = cap[i]; + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (this.options.smartLists && i !== l - 1) { + b = block.bullet.exec(cap[i + 1])[0]; + if (bull !== b && !(bull.length > 1 && b.length > 1)) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } - function leftClick() { - var counter = 0, - times = 5; + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } - var tooltip = reveal('.intro-nav-wrap .chapter-welcome', - t('intro.welcome.leftclick', { num: times }), - { tooltipClass: 'intro-mouse' } - ); + this.tokens.push({ + type: loose + ? 'loose_item_start' + : 'list_item_start' + }); - tooltip.selectAll('.tooltip-inner') - .insert('svg', 'span') - .attr('class', 'tooltip-illustration') - .append('use') - .attr('xlink:href', '#walkthrough-mouse'); + // Recurse. + this.token(item, false); - tooltip - .append('div') - .attr('class', 'counter'); + this.tokens.push({ + type: 'list_item_end' + }); + } - tooltip.call(listener); + this.tokens.push({ + type: 'list_end' + }); - listener.on('click', function(which) { - if (which === 'left') { - d3_select('.curtain-tooltip.intro-mouse .counter') - .text(String(++counter)); + continue; + } - if (counter === times) { - window.setTimeout(function() { continueTo(rightClick); }, 1000); - } - } + // html + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize + ? 'paragraph' + : 'html', + pre: !this.options.sanitizer + && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: cap[0] }); + continue; + } - function continueTo(nextStep) { - listener.on('click', null); - tooltip.call(listener.off); - tooltip.select('.counter').remove(); - nextStep(); + // def + if (top && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1); + tag = cap[1].toLowerCase(); + if (!this.tokens.links[tag]) { + this.tokens.links[tag] = { + href: cap[2], + title: cap[3] + }; } - } + continue; + } + // table (gfm) + if (top && (cap = this.rules.table.exec(src))) { + src = src.substring(cap[0].length); - function rightClick() { - var counter = 0, - times = 5; + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') + }; - var tooltip = reveal('.intro-nav-wrap .chapter-welcome', - t('intro.welcome.rightclick', { num: times }), - { tooltipClass: 'intro-mouse' } - ); + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } - tooltip.selectAll('.tooltip-inner') - .insert('svg', 'span') - .attr('class', 'tooltip-illustration') - .append('use') - .attr('xlink:href', '#walkthrough-mouse'); + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i] + .replace(/^ *\| *| *\| *$/g, '') + .split(/ *\| */); + } - tooltip - .append('div') - .attr('class', 'counter'); + this.tokens.push(item); - tooltip.call(listener); + continue; + } - listener.on('click', function(which) { - if (which === 'right') { - d3_select('.curtain-tooltip.intro-mouse .counter') - .text(String(++counter)); + // lheading + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } - if (counter === times) { - window.setTimeout(function() { continueTo(chapters); }, 1000); - } - } + // top-level paragraph + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] }); + continue; + } - function continueTo(nextStep) { - listener.on('click', null); - tooltip.call(listener.off); - tooltip.select('.counter').remove(); - nextStep(); - } + // text + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } } + return this.tokens; + }; - function chapters() { - dispatch$$1.call('done'); - reveal('.intro-nav-wrap .chapter-navigation', - t('intro.welcome.chapters', { next: t('intro.navigation.title') }) - ); - } + /** + * Inline-Level Grammar + */ + + var inline = { + escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, + autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, + url: noop, + tag: /^|^<\/?[a-zA-Z0-9\-]+(?:"[^"]*"|'[^']*'|\s[^<'">\/\s]*)*?\/?>/, + link: /^!?\[(inside)\]\(href\)/, + reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, + nolink: /^!?\[((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\]/, + strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, + em: /^_([^\s_](?:[^_]|__)+?[^\s_])_\b|^\*((?:\*\*|[^*])+?)\*(?!\*)/, + code: /^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/, + br: /^ {2,}\n(?!\s*$)/, + del: noop, + text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; - chapter.exit = function() { - listener.off(); - d3_select('.curtain-tooltip.intro-mouse') - .selectAll('.counter') - .remove(); - }; + inline.link = edit(inline.link) + .replace('inside', inline._inside) + .replace('href', inline._href) + .getRegex(); + inline.reflink = edit(inline.reflink) + .replace('inside', inline._inside) + .getRegex(); - chapter.restart = function() { - chapter.exit(); - chapter.enter(); - }; + /** + * Normal Inline Grammar + */ + + inline.normal = merge({}, inline); + /** + * Pedantic Inline Grammar + */ + + inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ + }); + + /** + * GFM Inline Grammar + */ + + inline.gfm = merge({}, inline.normal, { + escape: edit(inline.escape).replace('])', '~|])').getRegex(), + url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/) + .replace('email', inline._email) + .getRegex(), + _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, + del: /^~~(?=\S)([\s\S]*?\S)~~/, + text: edit(inline.text) + .replace(']|', '~]|') + .replace('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|') + .getRegex() + }); - return utilRebind(chapter, dispatch$$1, 'on'); -} + /** + * GFM + Line Breaks Inline Grammar + */ + inline.breaks = merge({}, inline.gfm, { + br: edit(inline.br).replace('{2,}', '*').getRegex(), + text: edit(inline.gfm.text).replace('{2,}', '*').getRegex() + }); + /** + * Inline Lexer & Compiler + */ -function clickListener() { - var dispatch$$1 = dispatch('click'), - minTime = 120, - tooltip = d3_select(null), - down = {}; + function InlineLexer(links, options) { + this.options = options || marked.defaults; + this.links = links; + this.rules = inline.normal; + this.renderer = this.options.renderer || new Renderer(); + this.renderer.options = this.options; - // `down` keeps track of which buttons/keys are down. - // Setting a property in `down` happens immediately. - // Unsetting a property in `down` is delayed because - // on Windows a contextmenu event happens after keyup/mouseup + if (!this.links) { + throw new Error('Tokens array requires a `links` property.'); + } - function keydown() { - if (event.keyCode === 93) { // context menu - event.preventDefault(); - event.stopPropagation(); - down.menu = event.timeStamp; - tooltip.classed('rightclick', true); - } + if (this.options.gfm) { + if (this.options.breaks) { + this.rules = inline.breaks; + } else { + this.rules = inline.gfm; + } + } else if (this.options.pedantic) { + this.rules = inline.pedantic; } + } + /** + * Expose Inline Rules + */ - function keyup() { - if (event.keyCode === 93) { // context menu - event.preventDefault(); - event.stopPropagation(); - var endTime = event.timeStamp, - startTime = down.menu || endTime, - delay = (endTime - startTime < minTime) ? minTime : 0; + InlineLexer.rules = inline; - window.setTimeout(function() { - tooltip.classed('rightclick', false); - down.menu = undefined; // delayed, for Windows - }, delay); + /** + * Static Lexing/Compiling Method + */ - dispatch$$1.call('click', this, 'right'); - } - } + InlineLexer.output = function(src, links, options) { + var inline = new InlineLexer(links, options); + return inline.output(src); + }; + + /** + * Lexing/Compiling + */ + + InlineLexer.prototype.output = function(src) { + var out = '', + link, + text, + href, + cap; + + while (src) { + // escape + if (cap = this.rules.escape.exec(src)) { + src = src.substring(cap[0].length); + out += cap[1]; + continue; + } + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = escape(this.mangle(cap[1])); + href = 'mailto:' + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } - function mousedown() { - var button = event.button; - if (button === 0 && !event.ctrlKey) { - tooltip.classed('leftclick', true); - } else if (button === 2) { - tooltip.classed('rightclick', true); + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + cap[0] = this.rules._backpedal.exec(cap[0])[0]; + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = escape(cap[0]); + href = 'mailto:' + text; + } else { + text = escape(cap[0]); + if (cap[1] === 'www.') { + href = 'http://' + text; + } else { + href = text; + } } - down[button] = event.timeStamp; - } + out += this.renderer.link(href, null, text); + continue; + } + + // tag + if (cap = this.rules.tag.exec(src)) { + if (!this.inLink && /^
    /i.test(cap[0])) { + this.inLink = false; + } + src = src.substring(cap[0].length); + out += this.options.sanitize + ? this.options.sanitizer + ? this.options.sanitizer(cap[0]) + : escape(cap[0]) + : cap[0]; + continue; + } + // link + if (cap = this.rules.link.exec(src)) { + src = src.substring(cap[0].length); + this.inLink = true; + out += this.outputLink(cap, { + href: cap[2], + title: cap[3] + }); + this.inLink = false; + continue; + } - function mouseup() { - var button = event.button, - endTime = event.timeStamp, - startTime = down[button] || endTime, - delay = (endTime - startTime < minTime) ? minTime : 0; + // reflink, nolink + if ((cap = this.rules.reflink.exec(src)) + || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } - if (button === 0 && !event.ctrlKey) { - window.setTimeout(function() { - tooltip.classed('leftclick', false); - down[button] = undefined; // delayed, for Windows - }, delay); + // strong + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[2] || cap[1])); + continue; + } - dispatch$$1.call('click', this, 'left'); + // em + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[2] || cap[1])); + continue; + } - } else if (button === 2) { - window.setTimeout(function() { - tooltip.classed('rightclick', false); - down[button] = undefined; // delayed, for Windows - }, delay); + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2].trim(), true)); + continue; + } - dispatch$$1.call('click', this, 'right'); + // br + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } - } else { - window.setTimeout(function() { - down[button] = undefined; // delayed, for Windows - }, delay); - } - } + // del (gfm) + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } + // text + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.text(escape(this.smartypants(cap[0]))); + continue; + } - function contextmenu() { - event.preventDefault(); - event.stopPropagation(); - if (!down[2] && !down.menu) { - tooltip.classed('rightclick', true); - window.setTimeout(function() { - tooltip.classed('rightclick', false); - }, minTime); - dispatch$$1.call('click', this, 'right'); - } + if (src) { + throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } } + return out; + }; - var behavior = function(selection$$1) { - tooltip = selection$$1; - down = {}; + /** + * Compile Link + */ - d3_select(window) - .on('keydown.intro', keydown) - .on('keyup.intro', keyup) - .on('mousedown.intro', mousedown) - .on('mouseup.intro', mouseup) - .on('contextmenu.intro', contextmenu); - }; + InlineLexer.prototype.outputLink = function(cap, link) { + var href = escape(link.href), + title = link.title ? escape(link.title) : null; + return cap[0].charAt(0) !== '!' + ? this.renderer.link(href, title, this.output(cap[1])) + : this.renderer.image(href, title, escape(cap[1])); + }; - behavior.off = function() { - d3_select(window) - .on('keydown.intro', null) - .on('keyup.intro', null) - .on('mousedown.intro', null) - .on('mouseup.intro', null) - .on('contextmenu.intro', null); + /** + * Smartypants Transformations + */ - tooltip - .classed('leftclick', false) - .classed('rightclick', false); - }; + InlineLexer.prototype.smartypants = function(text) { + if (!this.options.smartypants) return text; + return text + // em-dashes + .replace(/---/g, '\u2014') + // en-dashes + .replace(/--/g, '\u2013') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026'); + }; - return utilRebind(behavior, dispatch$$1, 'on'); -} + /** + * Mangle Links + */ -function uiIntroNavigation(context, reveal) { - var dispatch$$1 = dispatch('done'), - timeouts = [], - hallId = 'n2061', - townHall = [-85.63591, 41.94285], - springStreetId = 'w397', - springStreetEndId = 'n1834', - springStreet = [-85.63582, 41.94255], - onewayField = context.presets().field('oneway'), - maxspeedField = context.presets().field('maxspeed'); + InlineLexer.prototype.mangle = function(text) { + if (!this.options.mangle) return text; + var out = '', + l = text.length, + i = 0, + ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + return out; + }; - var chapter = { - title: 'intro.navigation.title' - }; + /** + * Renderer + */ + function Renderer(options) { + this.options = options || {}; + } - function timeout(f, t$$1) { - timeouts.push(window.setTimeout(f, t$$1)); + Renderer.prototype.code = function(code, lang, escaped) { + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } } - - function eventCancel() { - event.stopPropagation(); - event.preventDefault(); + if (!lang) { + return '
    '
    +        + (escaped ? code : escape(code, true))
    +        + '\n
    '; } + return '
    '
    +      + (escaped ? code : escape(code, true))
    +      + '\n
    \n'; + }; + + Renderer.prototype.blockquote = function(quote) { + return '
    \n' + quote + '
    \n'; + }; - function isTownHallSelected() { - var ids = context.selectedIDs(); - return ids.length === 1 && ids[0] === hallId; - } + Renderer.prototype.html = function(html) { + return html; + }; + Renderer.prototype.heading = function(text, level, raw) { + return '' + + text + + '\n'; + }; - function dragMap() { - context.enter(modeBrowse(context)); - context.history().reset('initial'); + Renderer.prototype.hr = function() { + return this.options.xhtml ? '
    \n' : '
    \n'; + }; - var msec = transitionTime(townHall, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(19).centerEase(townHall, msec); + Renderer.prototype.list = function(body, ordered, start) { + var type = ordered ? 'ol' : 'ul', + startatt = (ordered && start !== 1) ? (' start="' + start + '"') : ''; + return '<' + type + startatt + '>\n' + body + '\n'; + }; - timeout(function() { - var centerStart = context.map().center(); + Renderer.prototype.listitem = function(text) { + return '
  • ' + text + '
  • \n'; + }; - reveal('#surface', t('intro.navigation.drag')); - context.map().on('drawn.intro', function() { - reveal('#surface', t('intro.navigation.drag'), { duration: 0 }); - }); + Renderer.prototype.paragraph = function(text) { + return '

    ' + text + '

    \n'; + }; - context.map().on('move.intro', function() { - var centerNow = context.map().center(); - if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) { - context.map().on('move.intro', null); - timeout(function() { continueTo(zoomMap); }, 3000); - } - }); + Renderer.prototype.table = function(header, body) { + return '\n' + + '\n' + + header + + '\n' + + '\n' + + body + + '\n' + + '
    \n'; + }; - }, msec + 100); + Renderer.prototype.tablerow = function(content) { + return '\n' + content + '\n'; + }; - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - nextStep(); - } - } + Renderer.prototype.tablecell = function(content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' style="text-align:' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '\n'; + }; + // span level renderer + Renderer.prototype.strong = function(text) { + return '' + text + ''; + }; - function zoomMap() { - var zoomStart = context.map().zoom(); + Renderer.prototype.em = function(text) { + return '' + text + ''; + }; - reveal('#surface', - t('intro.navigation.zoom', { - plus: icon('#icon-plus', 'pre-text'), - minus: icon('#icon-minus', 'pre-text') - }) - ); + Renderer.prototype.codespan = function(text) { + return '' + text + ''; + }; - context.map().on('drawn.intro', function() { - reveal('#surface', - t('intro.navigation.zoom', { - plus: icon('#icon-plus', 'pre-text'), - minus: icon('#icon-minus', 'pre-text') - }), { duration: 0 } - ); - }); + Renderer.prototype.br = function() { + return this.options.xhtml ? '
    ' : '
    '; + }; - context.map().on('move.intro', function() { - if (context.map().zoom() !== zoomStart) { - context.map().on('move.intro', null); - timeout(function() { continueTo(features); }, 3000); - } - }); + Renderer.prototype.del = function(text) { + return '' + text + ''; + }; - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - nextStep(); - } + Renderer.prototype.link = function(href, title, text) { + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return text; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return text; + } } + if (this.options.baseUrl && !originIndependentUrl.test(href)) { + href = resolveUrl(this.options.baseUrl, href); + } + var out = '
    '; + return out; + }; + Renderer.prototype.image = function(href, title, text) { + if (this.options.baseUrl && !originIndependentUrl.test(href)) { + href = resolveUrl(this.options.baseUrl, href); + } + var out = '' + text + '' : '>'; + return out; + }; - function features() { - var onClick = function() { continueTo(pointsLinesAreas); }; + Renderer.prototype.text = function(text) { + return text; + }; - reveal('#surface', t('intro.navigation.features'), - { buttonText: t('intro.ok'), buttonCallback: onClick } - ); + /** + * TextRenderer + * returns only the textual part of the token + */ - context.map().on('drawn.intro', function() { - reveal('#surface', t('intro.navigation.features'), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } - ); - }); + function TextRenderer() {} - function continueTo(nextStep) { - context.map().on('drawn.intro', null); - nextStep(); - } - } + // no need for block level renderers - function pointsLinesAreas() { - var onClick = function() { continueTo(nodesWays); }; + TextRenderer.prototype.strong = + TextRenderer.prototype.em = + TextRenderer.prototype.codespan = + TextRenderer.prototype.del = + TextRenderer.prototype.text = function (text) { + return text; + }; - reveal('#surface', t('intro.navigation.points_lines_areas'), - { buttonText: t('intro.ok'), buttonCallback: onClick } - ); + TextRenderer.prototype.link = + TextRenderer.prototype.image = function(href, title, text) { + return '' + text; + }; - context.map().on('drawn.intro', function() { - reveal('#surface', t('intro.navigation.points_lines_areas'), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } - ); - }); + TextRenderer.prototype.br = function() { + return ''; + }; - function continueTo(nextStep) { - context.map().on('drawn.intro', null); - nextStep(); - } - } + /** + * Parsing & Compiling + */ - function nodesWays() { - var onClick = function() { continueTo(clickTownHall); }; + function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer(); + this.renderer = this.options.renderer; + this.renderer.options = this.options; + } - reveal('#surface', t('intro.navigation.nodes_ways'), - { buttonText: t('intro.ok'), buttonCallback: onClick } - ); + /** + * Static Parse Method + */ - context.map().on('drawn.intro', function() { - reveal('#surface', t('intro.navigation.nodes_ways'), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } - ); - }); + Parser.parse = function(src, options) { + var parser = new Parser(options); + return parser.parse(src); + }; - function continueTo(nextStep) { - context.map().on('drawn.intro', null); - nextStep(); - } - } + /** + * Parse Loop + */ - function clickTownHall() { - context.enter(modeBrowse(context)); - context.history().reset('initial'); + Parser.prototype.parse = function(src) { + this.inline = new InlineLexer(src.links, this.options); + // use an InlineLexer with a TextRenderer to extract pure text + this.inlineText = new InlineLexer( + src.links, + merge({}, this.options, {renderer: new TextRenderer()}) + ); + this.tokens = src.reverse(); - reveal(null, null, { duration: 0 }); - context.map().zoomEase(19, 500); + var out = ''; + while (this.next()) { + out += this.tok(); + } - timeout(function() { - var entity = context.hasEntity(hallId); - if (!entity) return; - context.map().centerEase(entity.loc, 500); + return out; + }; - timeout(function() { - var entity = context.hasEntity(hallId); - if (!entity) return; - var box = pointBox(entity.loc, context); - reveal(box, t('intro.navigation.click_townhall')); + /** + * Next Token + */ - context.map().on('move.intro drawn.intro', function() { - var entity = context.hasEntity(hallId); - if (!entity) return; - var box = pointBox(entity.loc, context); - reveal(box, t('intro.navigation.click_townhall'), { duration: 0 }); - }); + Parser.prototype.next = function() { + return this.token = this.tokens.pop(); + }; - context.on('enter.intro', function() { - if (isTownHallSelected()) continueTo(selectedTownHall); - }); + /** + * Preview Next Token + */ - }, 550); // after centerEase + Parser.prototype.peek = function() { + return this.tokens[this.tokens.length - 1] || 0; + }; - }, 550); // after zoomEase + /** + * Parse Text Tokens + */ - context.history().on('change.intro', function() { - if (!context.hasEntity(hallId)) { - continueTo(clickTownHall); - } - }); + Parser.prototype.parseText = function() { + var body = this.token.text; - function continueTo(nextStep) { - context.on('enter.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - nextStep(); - } + while (this.peek().type === 'text') { + body += '\n' + this.next().text; } + return this.inline.output(body); + }; - function selectedTownHall() { - if (!isTownHallSelected()) return clickTownHall(); - - var entity = context.hasEntity(hallId); - if (!entity) return clickTownHall(); + /** + * Parse Current Token + */ - var box = pointBox(entity.loc, context); - var onClick = function() { continueTo(editorTownHall); }; + Parser.prototype.tok = function() { + switch (this.token.type) { + case 'space': { + return ''; + } + case 'hr': { + return this.renderer.hr(); + } + case 'heading': { + return this.renderer.heading( + this.inline.output(this.token.text), + this.token.depth, + unescape(this.inlineText.output(this.token.text))); + } + case 'code': { + return this.renderer.code(this.token.text, + this.token.lang, + this.token.escaped); + } + case 'table': { + var header = '', + body = '', + i, + row, + cell, + j; + + // header + cell = ''; + for (i = 0; i < this.token.header.length; i++) { + cell += this.renderer.tablecell( + this.inline.output(this.token.header[i]), + { header: true, align: this.token.align[i] } + ); + } + header += this.renderer.tablerow(cell); - reveal(box, t('intro.navigation.selected_townhall'), - { buttonText: t('intro.ok'), buttonCallback: onClick } - ); + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; - context.map().on('move.intro drawn.intro', function() { - var entity = context.hasEntity(hallId); - if (!entity) return; - var box = pointBox(entity.loc, context); - reveal(box, t('intro.navigation.selected_townhall'), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } + cell = ''; + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell( + this.inline.output(row[j]), + { header: false, align: this.token.align[j] } ); - }); - - context.history().on('change.intro', function() { - if (!context.hasEntity(hallId)) { - continueTo(clickTownHall); - } - }); + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - nextStep(); + body += this.renderer.tablerow(cell); } - } - + return this.renderer.table(header, body); + } + case 'blockquote_start': { + body = ''; - function editorTownHall() { - if (!isTownHallSelected()) return clickTownHall(); + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + return this.renderer.blockquote(body); + } + case 'list_start': { + body = ''; + var ordered = this.token.ordered, + start = this.token.start; - var onClick = function() { continueTo(presetTownHall); }; + while (this.next().type !== 'list_end') { + body += this.tok(); + } - reveal('.entity-editor-pane', - t('intro.navigation.editor_townhall'), - { buttonText: t('intro.ok'), buttonCallback: onClick } - ); + return this.renderer.list(body, ordered, start); + } + case 'list_item_start': { + body = ''; - context.on('exit.intro', function() { - continueTo(clickTownHall); - }); + while (this.next().type !== 'list_item_end') { + body += this.token.type === 'text' + ? this.parseText() + : this.tok(); + } - context.history().on('change.intro', function() { - if (!context.hasEntity(hallId)) { - continueTo(clickTownHall); - } - }); + return this.renderer.listitem(body); + } + case 'loose_item_start': { + body = ''; - function continueTo(nextStep) { - context.on('exit.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', null); - nextStep(); + while (this.next().type !== 'list_item_end') { + body += this.tok(); } + + return this.renderer.listitem(body); + } + case 'html': { + var html = !this.token.pre && !this.options.pedantic + ? this.inline.output(this.token.text) + : this.token.text; + return this.renderer.html(html); + } + case 'paragraph': { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + case 'text': { + return this.renderer.paragraph(this.parseText()); + } } + }; + /** + * Helpers + */ - function presetTownHall() { - if (!isTownHallSelected()) return clickTownHall(); + function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } - // reset pane, in case user happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); + } - // preset match, in case the user happened to change it. - var entity = context.entity(context.selectedIDs()[0]); - var preset = context.presets().match(entity, context.graph()); + function edit(regex, opt) { + regex = regex.source; + opt = opt || ''; + return { + replace: function(name, val) { + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return this; + }, + getRegex: function() { + return new RegExp(regex, opt); + } + }; + } - var onClick = function() { continueTo(fieldsTownHall); }; + function resolveUrl(base, href) { + if (!baseUrls[' ' + base]) { + // we can ignore everything in base after the last slash of its path component, + // but we might need to add _that_ + // https://tools.ietf.org/html/rfc3986#section-3 + if (/^[^:]+:\/*[^/]*$/.test(base)) { + baseUrls[' ' + base] = base + '/'; + } else { + baseUrls[' ' + base] = base.replace(/[^/]*$/, ''); + } + } + base = baseUrls[' ' + base]; - context.on('exit.intro', function() { - continueTo(clickTownHall); - }); + if (href.slice(0, 2) === '//') { + return base.replace(/:[\s\S]*/, ':') + href; + } else if (href.charAt(0) === '/') { + return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href; + } else { + return base + href; + } + } + var baseUrls = {}; + var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; - context.history().on('change.intro', function() { - if (!context.hasEntity(hallId)) { - continueTo(clickTownHall); - } - }); + function noop() {} + noop.exec = noop; - reveal('.inspector-body .preset-list-item.inspector-inner', - t('intro.navigation.preset_townhall', { preset: preset.name() }), - { buttonText: t('intro.ok'), buttonCallback: onClick } - ); + function merge(obj) { + var i = 1, + target, + key; - function continueTo(nextStep) { - context.on('exit.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', null); - nextStep(); + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; } + } } + return obj; + } + + /** + * Marked + */ - function fieldsTownHall() { - if (!isTownHallSelected()) return clickTownHall(); + function marked(src, opt, callback) { + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + throw new Error('marked(): input parameter is undefined or null'); + } + if (typeof src !== 'string') { + throw new Error('marked(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected'); + } - // reset pane, in case user happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } - var onClick = function() { continueTo(closeTownHall); }; + opt = merge({}, marked.defaults, opt || {}); - reveal('.inspector-body .preset-editor', - t('intro.navigation.fields_townhall'), - { buttonText: t('intro.ok'), buttonCallback: onClick } - ); + var highlight = opt.highlight, + tokens, + pending, + i = 0; - context.on('exit.intro', function() { - continueTo(clickTownHall); - }); + try { + tokens = Lexer.lex(src, opt); + } catch (e) { + return callback(e); + } - context.history().on('change.intro', function() { - if (!context.hasEntity(hallId)) { - continueTo(clickTownHall); - } - }); + pending = tokens.length; - function continueTo(nextStep) { - context.on('exit.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', null); - nextStep(); + var done = function(err) { + if (err) { + opt.highlight = highlight; + return callback(err); } - } + var out; - function closeTownHall() { - if (!isTownHallSelected()) return clickTownHall(); + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } - var selector$$1 = '.entity-editor-pane button.preset-close svg use'; - var href = d3_select(selector$$1).attr('href') || '#icon-close'; + opt.highlight = highlight; - reveal('.entity-editor-pane', - t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }) - ); + return err + ? callback(err) + : callback(null, out); + }; - context.on('exit.intro', function() { - continueTo(searchStreet); - }); + if (!highlight || highlight.length < 3) { + return done(); + } - context.history().on('change.intro', function() { - // update the close icon in the tooltip if the user edits something. - var selector$$1 = '.entity-editor-pane button.preset-close svg use'; - var href = d3_select(selector$$1).attr('href') || '#icon-close'; + delete opt.highlight; - reveal('.entity-editor-pane', - t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }), - { duration: 0 } - ); - }); + if (!pending) return done(); - function continueTo(nextStep) { - context.on('exit.intro', null); - context.history().on('change.intro', null); - nextStep(); - } + for (; i < tokens.length; i++) { + (function(token) { + if (token.type !== 'code') { + return --pending || done(); + } + return highlight(token.text, token.lang, function(err, code) { + if (err) return done(err); + if (code == null || code === token.text) { + return --pending || done(); + } + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if ((opt || marked.defaults).silent) { + return '

    An error occurred:

    '
    +          + escape(e.message + '', true)
    +          + '
    '; + } + throw e; } + } + /** + * Options + */ - function searchStreet() { - context.enter(modeBrowse(context)); - context.history().reset('initial'); // ensure spring street exists + marked.options = + marked.setOptions = function(opt) { + merge(marked.defaults, opt); + return marked; + }; - var msec = transitionTime(springStreet, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(19).centerEase(springStreet, msec); // ..and user can see it + marked.defaults = { + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + sanitizer: null, + mangle: true, + smartLists: false, + silent: false, + highlight: null, + langPrefix: 'lang-', + smartypants: false, + headerPrefix: '', + renderer: new Renderer(), + xhtml: false, + baseUrl: null + }; - timeout(function() { - reveal('.search-header input', - t('intro.navigation.search_street', { name: t('intro.graph.name.spring-street') }) - ); + /** + * Expose + */ - d3_select('.search-header input') - .on('keyup.intro', checkSearchResult); - }, msec + 100); - } + marked.Parser = Parser; + marked.parser = Parser.parse; + marked.Renderer = Renderer; + marked.TextRenderer = TextRenderer; - function checkSearchResult() { - var first = d3_select('.feature-list-item:nth-child(0n+2)'), // skip "No Results" item - firstName = first.select('.entity-name'), - name = t('intro.graph.name.spring-street'); + marked.Lexer = Lexer; + marked.lexer = Lexer.lex; - if (!firstName.empty() && firstName.text() === name) { - reveal(first.node(), - t('intro.navigation.choose_street', { name: name }), - { duration: 300 } - ); + marked.InlineLexer = InlineLexer; + marked.inlineLexer = InlineLexer.output; - context.on('exit.intro', function() { - continueTo(selectedStreet); - }); + marked.parse = marked; - d3_select('.search-header input') - .on('keydown.intro', eventCancel, true) - .on('keyup.intro', null); - } + { + module.exports = marked; + } + })(commonjsGlobal || (typeof window !== 'undefined' ? window : commonjsGlobal)); + }); - function continueTo(nextStep) { - context.on('exit.intro', null); - d3_select('.search-header input') - .on('keydown.intro', null) - .on('keyup.intro', null); - nextStep(); - } - } + function pointBox(loc, context) { + var rect = context.surfaceRect(); + var point$$1 = context.curtainProjection(loc); + return { + left: point$$1[0] + rect.left - 40, + top: point$$1[1] + rect.top - 60, + width: 80, + height: 90 + }; + } - function selectedStreet() { - if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) { - return searchStreet(); - } + function pad$1(locOrBox, padding, context) { + var box; + if (locOrBox instanceof Array) { + var rect = context.surfaceRect(); + var point$$1 = context.curtainProjection(locOrBox); + box = { + left: point$$1[0] + rect.left, + top: point$$1[1] + rect.top + }; + } else { + box = locOrBox; + } + + return { + left: box.left - padding, + top: box.top - padding, + width: (box.width || 0) + 2 * padding, + height: (box.width || 0) + 2 * padding + }; + } - var onClick = function() { continueTo(editorStreet); }; - var entity = context.entity(springStreetEndId); - var box = pointBox(entity.loc, context); - box.height = 500; - reveal(box, - t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }), - { duration: 600, buttonText: t('intro.ok'), buttonCallback: onClick } - ); + function icon(name, svgklass, useklass) { + return '' + + ''; + } - timeout(function() { - context.map().on('move.intro drawn.intro', function() { - var entity = context.hasEntity(springStreetEndId); - if (!entity) return; - var box = pointBox(entity.loc, context); - box.height = 500; - reveal(box, - t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } - ); - }); - }, 600); // after reveal. - context.on('enter.intro', function(mode) { - if (!context.hasEntity(springStreetId)) { - return continueTo(searchStreet); - } - var ids = context.selectedIDs(); - if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) { - // keep Spring Street selected.. - context.enter(modeSelect(context, [springStreetId])); - } - }); + function slugify(text) { + return text.toString().toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with - + .replace(/[^\w\-]+/g, '') // Remove all non-word chars + .replace(/\-\-+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, ''); // Trim - from end of text + } - context.history().on('change.intro', function() { - if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) { - timeout(function() { - continueTo(searchStreet); - }, 300); // after any transition (e.g. if user deleted intersection) - } - }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + // console warning for missing walkthrough names + var missingStrings = {}; + function checkKey(key, text) { + if (t(key, { default: undefined}) === undefined) { + if (missingStrings.hasOwnProperty(key)) return; // warn once + missingStrings[key] = text; + var missing = key + ': ' + text; + if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line + } + } + + function localize(obj) { + var key; - function editorStreet() { - var selector$$1 = '.entity-editor-pane button.preset-close svg use'; - var href = d3_select(selector$$1).attr('href') || '#icon-close'; + // Assign name if entity has one.. + var name = obj.tags && obj.tags.name; + if (name) { + key = 'intro.graph.name.' + slugify(name); + obj.tags.name = t(key, { default: name }); + checkKey(key, name); + } - reveal('.entity-editor-pane', - t('intro.navigation.editor_street', { - button: icon(href, 'pre-text'), - field1: onewayField.label(), - field2: maxspeedField.label() - }) - ); + // Assign street name if entity has one.. + var street = obj.tags && obj.tags['addr:street']; + if (street) { + key = 'intro.graph.name.' + slugify(street); + obj.tags['addr:street'] = t(key, { default: street }); + checkKey(key, street); + + // Add address details common across walkthrough.. + var addrTags = [ + 'block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood', + 'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb' + ]; + addrTags.forEach(function(k) { + var key = 'intro.graph.' + k, + tag = 'addr:' + k, + val = obj.tags && obj.tags[tag], + str = t(key, { default: val }); + + if (str) { + if (str.match(/^<.*>$/) !== null) { + delete obj.tags[tag]; + } else { + obj.tags[tag] = str; + } + } + }); + } - context.on('exit.intro', function() { - continueTo(play); - }); + return obj; + } - context.history().on('change.intro', function() { - // update the close icon in the tooltip if the user edits something. - var selector$$1 = '.entity-editor-pane button.preset-close svg use'; - var href = d3_select(selector$$1).attr('href') || '#icon-close'; - - reveal('.entity-editor-pane', - t('intro.navigation.editor_street', { - button: icon(href, 'pre-text'), - field1: onewayField.label().toLowerCase(), - field2: maxspeedField.label().toLowerCase() - }), { duration: 0 } - ); - }); - function continueTo(nextStep) { - context.on('exit.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + // Used to detect squareness.. some duplicataion of code from actionOrthogonalize. + function isMostlySquare(points) { + // note: uses 15 here instead of the 12 from actionOrthogonalize because + // actionOrthogonalize can actually straighten some larger angles as it iterates + var threshold = 15, // degrees within right or straight + lowerBound = Math.cos((90 - threshold) * Math.PI / 180), // near right + upperBound = Math.cos(threshold * Math.PI / 180), // near straight + mag; + for (var i = 0; i < points.length; i++) { + mag = Math.abs(normalizedDotProduct(i, points)); + if (mag > lowerBound && mag < upperBound) { + return false; + } + } - function play() { - dispatch$$1.call('done'); - reveal('#id-container', - t('intro.navigation.play', { next: t('intro.points.title') }), { - tooltipBox: '.intro-nav-wrap .chapter-point', - buttonText: t('intro.ok'), - buttonCallback: function() { reveal('#id-container'); } - } - ); - } + return true; - chapter.enter = function() { - dragMap(); - }; + function normalizedDotProduct(i, points) { + var a = points[(i - 1 + points.length) % points.length], + b = points[i], + c = points[(i + 1) % points.length], + p = subtractPoints(a, b), + q = subtractPoints(c, b); + p = normalizePoint(p); + q = normalizePoint(q); - chapter.exit = function() { - timeouts.forEach(window.clearTimeout); - context.on('enter.intro exit.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.search-header input').on('keydown.intro keyup.intro', null); - }; + return p[0] * q[0] + p[1] * q[1]; - chapter.restart = function() { - chapter.exit(); - chapter.enter(); - }; + function subtractPoints(a, b) { + return [a[0] - b[0], a[1] - b[1]]; + } + function normalizePoint(point$$1) { + var vector = [0, 0]; + var length = Math.sqrt(point$$1[0] * point$$1[0] + point$$1[1] * point$$1[1]); + if (length !== 0) { + vector[0] = point$$1[0] / length; + vector[1] = point$$1[1] / length; + } + return vector; + } + } + } - return utilRebind(chapter, dispatch$$1, 'on'); -} -function uiIntroPoint(context, reveal) { - var dispatch$$1 = dispatch('done'), - timeouts = [], - intersection = [-85.63279, 41.94394], - building = [-85.632422, 41.944045], - cafePreset = context.presets().item('amenity/cafe'), - pointId = null; + function selectMenuItem(operation) { + var selector$$1 = '.edit-menu .edit-menu-item-' + operation + + ', .radial-menu .radial-menu-item-' + operation; + return select(selector$$1); + } - var chapter = { - title: 'intro.points.title' - }; + function transitionTime(point1, point2) { + var distance = geoSphericalDistance(point1, point2); + if (distance === 0) + return 0; + else if (distance < 80) + return 500; + else + return 1000; + } + 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", + "traffic_signals:direction": "both" + } + }, + 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", + "traffic_signals:direction": "both" + } + }, + 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", + "traffic_signals:direction": "both" + } + }, + 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.616762, + 41.952222 + ] + }, + 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.616557, + 41.951997 + ] + }, + n3867: { + id: "n3867", + loc: [ + -85.61658, + 41.952093 + ] + }, + n3868: { + id: "n3868", + loc: [ + -85.616636, + 41.952145 + ] + }, + n3869: { + id: "n3869", + loc: [ + -85.616918, + 41.952276 + ] + }, + n387: { + id: "n387", + loc: [ + -85.632524, + 41.943912 + ] + }, + n3870: { + id: "n3870", + loc: [ + -85.617098, + 41.952235 + ] + }, + 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.616502, + 41.951946 + ] + }, + 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", + direction: "forward", + stop: "minor" + } + }, + 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", + direction: "forward" + } + }, + n4501: { + id: "n4501", + loc: [ + -85.627921, + 41.954783 + ], + tags: { + highway: "stop", + stop: "all", + direction: "backward" + } + }, + n4502: { + id: "n4502", + loc: [ + -85.62775, + 41.954696 + ], + tags: { + highway: "stop", + stop: "all", + direction: "backward" + } + }, + n4503: { + id: "n4503", + loc: [ + -85.628046, + 41.954591 + ], + tags: { + highway: "stop", + stop: "all", + direction: "forward" + } + }, + n4504: { + id: "n4504", + loc: [ + -85.631074, + 41.957428 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4505: { + id: "n4505", + loc: [ + -85.630768, + 41.957429 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + n4506: { + id: "n4506", + loc: [ + -85.629888, + 41.957432 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4507: { + id: "n4507", + loc: [ + -85.629565, + 41.957433 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "forward" + } + }, + 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", + stop: "minor", + direction: "backward" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + n4536: { + id: "n4536", + loc: [ + -85.630881, + 41.954806 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "backward" + } + }, + n4537: { + id: "n4537", + loc: [ + -85.630879, + 41.954564 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "forward" + } + }, + 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", + stop: "minor", + direction: "backward" + } + }, + n4544: { + id: "n4544", + loc: [ + -85.632071, + 41.959029 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "forward" + } + }, + n4545: { + id: "n4545", + loc: [ + -85.632257, + 41.959027 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "backward" + } + }, + n4546: { + id: "n4546", + loc: [ + -85.631966, + 41.957427 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + n4547: { + id: "n4547", + loc: [ + -85.632297, + 41.957426 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4548: { + id: "n4548", + loc: [ + -85.631976, + 41.955911 + ], + tags: { + highway: "give_way", + direction: "forward" + } + }, + n4549: { + id: "n4549", + loc: [ + -85.632272, + 41.955911 + ], + tags: { + highway: "give_way", + direction: "backward" + } + }, + n455: { + id: "n455", + loc: [ + -85.635224, + 41.943869 + ] + }, + n4550: { + id: "n4550", + loc: [ + -85.632097, + 41.954805 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "backward" + } + }, + n4551: { + id: "n4551", + loc: [ + -85.632094, + 41.954566 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "forward" + } + }, + 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", + direction: "backward", + stop: "minor" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + n4587: { + id: "n4587", + loc: [ + -85.620485, + 41.951948 + ], + tags: { + emergency: "fire_hydrant" + } + }, + n4588: { + id: "n4588", + loc: [ + -85.620316, + 41.950999 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4589: { + id: "n4589", + loc: [ + -85.620311, + 41.950131 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + 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", + direction: "backward", + stop: "minor" + } + }, + n4592: { + id: "n4592", + loc: [ + -85.620278, + 41.947443 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4593: { + id: "n4593", + loc: [ + -85.619844, + 41.947444 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + 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", + stop: "minor", + direction: "backward" + } + }, + n4597: { + id: "n4597", + loc: [ + -85.622739, + 41.947316 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + n4602: { + id: "n4602", + loc: [ + -85.622769, + 41.949325 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "backward" + } + }, + n4603: { + id: "n4603", + loc: [ + -85.622837, + 41.949329 + ], + tags: { + emergency: "fire_hydrant" + } + }, + n4604: { + id: "n4604", + loc: [ + -85.622614, + 41.950113 + ], + tags: { + highway: "give_way", + direction: "forward" + } + }, + n4605: { + id: "n4605", + loc: [ + -85.624777, + 41.949219 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + 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", + stop: "minor", + direction: "forward" + } + }, + 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.618232, + 41.949913 + ] + }, + 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", + direction: "forward", + stop: "minor" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + n4685: { + id: "n4685", + loc: [ + -85.635961, + 41.940125 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "backward" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + n4695: { + id: "n4695", + loc: [ + -85.637174, + 41.941354 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4696: { + id: "n4696", + loc: [ + -85.637091, + 41.941273 + ], + tags: { + emergency: "fire_hydrant" + } + }, + n4697: { + id: "n4697", + loc: [ + -85.638058, + 41.941346 + ], + tags: { + highway: "give_way", + direction: "forward" + } + }, + n4698: { + id: "n4698", + loc: [ + -85.638359, + 41.941344 + ], + tags: { + highway: "give_way", + direction: "backward" + } + }, + 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", + direction: "forward" + } + }, + n4702: { + id: "n4702", + loc: [ + -85.639548, + 41.941334 + ], + tags: { + highway: "give_way", + direction: "backward" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + n4706: { + id: "n4706", + loc: [ + -85.640803, + 41.941324 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4707: { + id: "n4707", + loc: [ + -85.641717, + 41.941317 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "all" + } + }, + n4708: { + id: "n4708", + loc: [ + -85.641846, + 41.941415 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "all" + } + }, + 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", + direction: "forward", + stop: "all" + } + }, + n4711: { + id: "n4711", + loc: [ + -85.641854, + 41.942455 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + n4712: { + id: "n4712", + loc: [ + -85.641859, + 41.942739 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4713: { + id: "n4713", + loc: [ + -85.640754, + 41.942707 + ], + tags: { + emergency: "fire_hydrant" + } + }, + n4714: { + id: "n4714", + loc: [ + -85.640669, + 41.942716 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4715: { + id: "n4715", + loc: [ + -85.640664, + 41.942478 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + n4716: { + id: "n4716", + loc: [ + -85.63964, + 41.94274 + ], + tags: { + man_made: "flagpole" + } + }, + n4717: { + id: "n4717", + loc: [ + -85.639455, + 41.942731 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "minor" + } + }, + n4718: { + id: "n4718", + loc: [ + -85.63945, + 41.942492 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + 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", + direction: "backward", + stop: "minor" + } + }, + n4721: { + id: "n4721", + loc: [ + -85.638233, + 41.942511 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + n4726: { + id: "n4726", + loc: [ + -85.633467, + 41.943818 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "backward" + } + }, + n4727: { + id: "n4727", + loc: [ + -85.633987, + 41.943531 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + 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", + stop: "minor", + direction: "backward" + } + }, + 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", + direction: "forward", + stop: "minor" + } + }, + n4746: { + id: "n4746", + loc: [ + -85.639635, + 41.94387 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "backward" + } + }, + n4747: { + id: "n4747", + loc: [ + -85.639549, + 41.943756 + ], + tags: { + emergency: "fire_hydrant" + } + }, + n4748: { + id: "n4748", + loc: [ + -85.64055, + 41.943862 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + n4749: { + id: "n4749", + loc: [ + -85.640864, + 41.943859 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "backward" + } + }, + n475: { + id: "n475", + loc: [ + -85.633906, + 41.943535 + ] + }, + n4750: { + id: "n4750", + loc: [ + -85.640718, + 41.945022 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + n4751: { + id: "n4751", + loc: [ + -85.640664, + 41.945076 + ], + tags: { + emergency: "fire_hydrant" + } + }, + n4752: { + id: "n4752", + loc: [ + -85.641913, + 41.94502 + ], + tags: { + highway: "stop", + direction: "forward", + stop: "minor" + } + }, + n4753: { + id: "n4753", + loc: [ + -85.641838, + 41.945076 + ], + tags: { + emergency: "fire_hydrant" + } + }, + n4754: { + id: "n4754", + loc: [ + -85.642045, + 41.94385 + ], + tags: { + highway: "give_way", + direction: "backward" + } + }, + n4755: { + id: "n4755", + loc: [ + -85.641738, + 41.943852 + ], + tags: { + highway: "give_way", + direction: "forward" + } + }, + n4756: { + id: "n4756", + loc: [ + -85.642928, + 41.943843 + ], + tags: { + highway: "stop", + stop: "minor", + direction: "forward" + } + }, + n4757: { + id: "n4757", + loc: [ + -85.64305, + 41.943902 + ], + tags: { + emergency: "fire_hydrant" + } + }, + n4758: { + id: "n4758", + loc: [ + -85.642986, + 41.945105 + ], + tags: { + highway: "stop", + direction: "backward", + stop: "all" + } + }, + n4759: { + id: "n4759", + loc: [ + -85.643136, + 41.94502 + ], + tags: { + highway: "stop", + stop: "all", + direction: "forward" + } + }, + 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", + "n2938", + "n3866", + "n2939", + "n3867", + "n3868", + "n3858", + "n2937", + "n3869", + "n2935", + "n2934", + "n3870", + "n3348", + "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", + "n3351", + "n3950", + "n3354", + "n3350", + "n3951", + "n3349", + "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" + } + }, + n2934: { + id: "n2934", + loc: [ + -85.617051, + 41.952263 + ] + }, + n2935: { + id: "n2935", + loc: [ + -85.61699, + 41.952276 + ] + }, + n2937: { + id: "n2937", + loc: [ + -85.616847, + 41.952262 + ] + }, + n2938: { + id: "n2938", + loc: [ + -85.616577, + 41.951956 + ] + }, + n2939: { + id: "n2939", + loc: [ + -85.61656, + 41.952044 + ] + }, + n3348: { + id: "n3348", + loc: [ + -85.61714, + 41.9522 + ] + }, + n3349: { + id: "n3349", + loc: [ + -85.616517, + 41.95212 + ] + }, + n3350: { + id: "n3350", + loc: [ + -85.616489, + 41.952033 + ] + }, + n3351: { + id: "n3351", + loc: [ + -85.616529, + 41.951907 + ] + }, + n3354: { + id: "n3354", + loc: [ + -85.616488, + 41.951994 + ] + } + }; - function timeout(f, t$$1) { - timeouts.push(window.setTimeout(f, t$$1)); - } + // Tooltips and svg mask used to highlight certain features + function uiCurtain() { + var surface = select(null), + tooltip = select(null), + darkness = select(null); - function revealEditMenu(loc, text, options) { - var rect = context.surfaceRect(); - var point$$1 = context.curtainProjection(loc); - var pad = 40; - var width = 250 + (2 * pad); - var height = 250; - var startX = rect.left + point$$1[0]; - var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad); - var box = { - left: left, - top: point$$1[1] + rect.top - 60, - width: width, - height: height - }; - reveal(box, text, options); - } + function curtain(selection$$1) { + surface = selection$$1 + .append('svg') + .attr('id', 'curtain') + .style('z-index', 1000) + .style('pointer-events', 'none') + .style('position', 'absolute') + .style('top', 0) + .style('left', 0); + darkness = surface.append('path') + .attr('x', 0) + .attr('y', 0) + .attr('class', 'curtain-darkness'); - function eventCancel() { - event.stopPropagation(); - event.preventDefault(); - } + select(window).on('resize.curtain', resize); + tooltip = selection$$1.append('div') + .attr('class', 'tooltip') + .style('z-index', 1002); - function addPoint() { - context.enter(modeBrowse(context)); - context.history().reset('initial'); + tooltip + .append('div') + .attr('class', 'tooltip-arrow'); - var msec = transitionTime(intersection, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(19).centerEase(intersection, msec); + tooltip + .append('div') + .attr('class', 'tooltip-inner'); - timeout(function() { - var tooltip = reveal('button.add-point', - t('intro.points.add_point', { button: icon('#icon-point', 'pre-text') })); + resize(); - pointId = null; - tooltip.selectAll('.tooltip-inner') - .insert('svg', 'span') - .attr('class', 'tooltip-illustration') - .append('use') - .attr('xlink:href', '#poi-images'); + function resize() { + surface + .attr('width', window.innerWidth) + .attr('height', window.innerHeight); + curtain.cut(darkness.datum()); + } + } - context.on('enter.intro', function(mode) { - if (mode.id !== 'add-point') return; - continueTo(placePoint); - }); - }, msec + 100); - function continueTo(nextStep) { - context.on('enter.intro', null); - nextStep(); - } - } + /** + * Reveal cuts the curtain to highlight the given box, + * and shows a tooltip with instructions next to the box. + * + * @param {String|ClientRect} [box] box used to cut the curtain + * @param {String} [text] text for a tooltip + * @param {Object} [options] + * @param {string} [options.tooltipClass] optional class to add to the tooltip + * @param {integer} [options.duration] transition time in milliseconds + * @param {string} [options.buttonText] if set, create a button with this text label + * @param {function} [options.buttonCallback] if set, the callback for the button + * @param {String|ClientRect} [options.tooltipBox] box for tooltip position, if different from box for the curtain + */ + curtain.reveal = function(box, text, options) { + if (typeof box === 'string') { + box = select(box).node(); + } + if (box && box.getBoundingClientRect) { + box = copyBox(box.getBoundingClientRect()); + } + options = options || {}; + + var tooltipBox; + if (options.tooltipBox) { + tooltipBox = options.tooltipBox; + if (typeof tooltipBox === 'string') { + tooltipBox = select(tooltipBox).node(); + } + if (tooltipBox && tooltipBox.getBoundingClientRect) { + tooltipBox = copyBox(tooltipBox.getBoundingClientRect()); + } + } else { + tooltipBox = box; + } - function placePoint() { - if (context.mode().id !== 'add-point') { - return chapter.restart(); - } + if (tooltipBox && text) { + // pseudo markdown bold text for the instruction section.. + var parts = text.split('**'); + var html = parts[0] ? '' + parts[0] + '' : ''; + if (parts[1]) { + html += '' + parts[1] + ''; + } + + html = html.replace(/\*(.*?)\*/g, '$1'); // emphasis + html = html.replace(/\{br\}/g, '

    '); // linebreak + + if (options.buttonText && options.buttonCallback) { + html += '
    ' + + '
    '; + } + + var classes = 'curtain-tooltip tooltip in ' + (options.tooltipClass || ''); + tooltip + .classed(classes, true) + .selectAll('.tooltip-inner') + .html(html); + + if (options.buttonText && options.buttonCallback) { + var button = tooltip.selectAll('.button-section .button.action'); + button + .on('click', function() { + event.preventDefault(); + options.buttonCallback(); + }); + } + + var tip = copyBox(tooltip.node().getBoundingClientRect()), + w = window.innerWidth, + h = window.innerHeight, + tooltipWidth = 200, + tooltipArrow = 5, + side, pos; + + + // hack: this will have bottom placement, + // so need to reserve extra space for the tooltip illustration. + if (options.tooltipClass === 'intro-mouse') { + tip.height += 80; + } + + // trim box dimensions to just the portion that fits in the window.. + if (tooltipBox.top + tooltipBox.height > h) { + tooltipBox.height -= (tooltipBox.top + tooltipBox.height - h); + } + if (tooltipBox.left + tooltipBox.width > w) { + tooltipBox.width -= (tooltipBox.left + tooltipBox.width - w); + } + + // determine tooltip placement.. + + if (tooltipBox.top + tooltipBox.height < 100) { + // tooltip below box.. + side = 'bottom'; + pos = [ + tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, + tooltipBox.top + tooltipBox.height + ]; + + } else if (tooltipBox.top > h - 140) { + // tooltip above box.. + side = 'top'; + pos = [ + tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, + tooltipBox.top - tip.height + ]; + + } else { + // tooltip to the side of the tooltipBox.. + var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2; + + if (textDirection === 'rtl') { + if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) { + side = 'right'; + pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY]; + + } else { + side = 'left'; + pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY]; + } + + } else { + if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) { + side = 'left'; + pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY]; + } + else { + side = 'right'; + pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY]; + } + } + } + + if (options.duration !== 0 || !tooltip.classed(side)) { + tooltip.call(uiToggle(true)); + } + + tooltip + .style('top', pos[1] + 'px') + .style('left', pos[0] + 'px') + .attr('class', classes + ' ' + side); + + + // shift tooltip-inner if it is very close to the top or bottom edge + // (doesn't affect the placement of the tooltip-arrow) + var shiftY = 0; + if (side === 'left' || side === 'right') { + if (pos[1] < 60) { + shiftY = 60 - pos[1]; + } + else if (pos[1] + tip.height > h - 100) { + shiftY = h - pos[1] - tip.height - 100; + } + } + tooltip.selectAll('.tooltip-inner') + .style('top', shiftY + 'px'); - var pointBox$$1 = pad$1(building, 150, context); - reveal(pointBox$$1, t('intro.points.place_point')); + } else { + tooltip + .classed('in', false) + .call(uiToggle(false)); + } - context.map().on('move.intro drawn.intro', function() { - pointBox$$1 = pad$1(building, 150, context); - reveal(pointBox$$1, t('intro.points.place_point'), { duration: 0 }); - }); + curtain.cut(box, options.duration); - context.on('enter.intro', function(mode) { - if (mode.id !== 'select') return chapter.restart(); - pointId = context.mode().selectedIDs()[0]; - continueTo(searchPreset); - }); + return tooltip; + }; - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + curtain.cut = function(datum, duration) { + darkness.datum(datum) + .interrupt(); - function searchPreset() { - if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { - return addPoint(); - } + var selection$$1; + if (duration === 0) { + selection$$1 = darkness; + } else { + selection$$1 = darkness + .transition() + .duration(duration || 600) + .ease(linear$1); + } - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + selection$$1 + .attr('d', function(d) { + var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' + + window.innerWidth + ',' + window.innerHeight + 'L' + + window.innerWidth + ',0 Z'; - d3_select('.preset-search-input') - .on('keydown.intro', null) - .on('keyup.intro', checkPresetSearch); + if (!d) return string; + return string + 'M' + + d.left + ',' + d.top + 'L' + + d.left + ',' + (d.top + d.height) + 'L' + + (d.left + d.width) + ',' + (d.top + d.height) + 'L' + + (d.left + d.width) + ',' + (d.top) + 'Z'; - reveal('.preset-search-input', - t('intro.points.search_cafe', { preset: cafePreset.name() }) - ); + }); + }; - context.on('enter.intro', function(mode) { - if (!pointId || !context.hasEntity(pointId)) { - return continueTo(addPoint); - } - var ids = context.selectedIDs(); - if (mode.id !== 'select' || !ids.length || ids[0] !== pointId) { - // keep the user's point selected.. - context.enter(modeSelect(context, [pointId])); + curtain.remove = function() { + surface.remove(); + tooltip.remove(); + select(window).on('resize.curtain', null); + }; - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); - d3_select('.preset-search-input') - .on('keydown.intro', null) - .on('keyup.intro', checkPresetSearch); + // ClientRects are immutable, so copy them to an object, + // in case we need to trim the height/width. + function copyBox(src) { + return { + top: src.top, + right: src.right, + bottom: src.bottom, + left: src.left, + width: src.width, + height: src.height + }; + } - reveal('.preset-search-input', - t('intro.points.search_cafe', { preset: cafePreset.name() }) - ); - context.history().on('change.intro', null); - } - }); + return curtain; + } + function uiIntroWelcome(context, reveal) { + var dispatch$$1 = dispatch('done'), + listener = clickListener(); - function checkPresetSearch() { - var first = d3_select('.preset-list-item:first-child'); + var chapter = { + title: 'intro.welcome.title' + }; - if (first.classed('preset-amenity-cafe')) { - d3_select('.preset-search-input') - .on('keydown.intro', eventCancel, true) - .on('keyup.intro', null); - reveal(first.select('.preset-list-button').node(), - t('intro.points.choose_cafe', { preset: cafePreset.name() }), - { duration: 300 } - ); + function welcome() { + context.map().centerZoom([-85.63591, 41.94285], 19); + reveal('.intro-nav-wrap .chapter-welcome', + t('intro.welcome.welcome'), + { buttonText: t('intro.ok'), buttonCallback: practice } + ); + } - context.history().on('change.intro', function() { - continueTo(aboutFeatureEditor); - }); - } - } + function practice() { + reveal('.intro-nav-wrap .chapter-welcome', + t('intro.welcome.practice'), + { buttonText: t('intro.ok'), buttonCallback: words } + ); + } - function continueTo(nextStep) { - context.on('enter.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.preset-search-input').on('keydown.intro keyup.intro', null); - nextStep(); - } - } + function words() { + reveal('.intro-nav-wrap .chapter-welcome', + t('intro.welcome.words'), + { buttonText: t('intro.ok'), buttonCallback: mouse$$1 } + ); + } - function aboutFeatureEditor() { - if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { - return addPoint(); - } + function mouse$$1() { + reveal('.intro-nav-wrap .chapter-welcome', + t('intro.welcome.mouse'), + { buttonText: t('intro.ok'), buttonCallback: leftClick } + ); + } - timeout(function() { - reveal('.entity-editor-pane', t('intro.points.feature_editor'), { - tooltipClass: 'intro-points-describe', - buttonText: t('intro.ok'), - buttonCallback: function() { continueTo(addName); } - }); - }, 400); - context.on('exit.intro', function() { - // if user leaves select mode here, just continue with the tutorial. - continueTo(reselectPoint); - }); + function leftClick() { + var counter = 0, + times = 5; - function continueTo(nextStep) { - context.on('exit.intro', null); - nextStep(); - } - } + var tooltip = reveal('.intro-nav-wrap .chapter-welcome', + t('intro.welcome.leftclick', { num: times }), + { tooltipClass: 'intro-mouse' } + ); + tooltip.selectAll('.tooltip-inner') + .insert('svg', 'span') + .attr('class', 'tooltip-illustration') + .append('use') + .attr('xlink:href', '#walkthrough-mouse'); - function addName() { - if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { - return addPoint(); - } + tooltip + .append('div') + .attr('class', 'counter'); - // reset pane, in case user happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); - - timeout(function() { - // It's possible for the user to add a name in a previous step.. - // If so, don't tell them to add the name in this step. - // Give them an OK button instead. - var entity = context.entity(pointId); - if (entity.tags.name) { - var tooltip = reveal('.entity-editor-pane', t('intro.points.add_name'), { - tooltipClass: 'intro-points-describe', - buttonText: t('intro.ok'), - buttonCallback: function() { continueTo(addCloseEditor); } - }); - tooltip.select('.instruction').style('display', 'none'); + tooltip.call(listener); - } else { - reveal('.entity-editor-pane', t('intro.points.add_name'), - { tooltipClass: 'intro-points-describe' } - ); - } - }, 400); + listener.on('click', function(which) { + if (which === 'left') { + select('.curtain-tooltip.intro-mouse .counter') + .text(String(++counter)); - context.history().on('change.intro', function() { - continueTo(addCloseEditor); - }); + if (counter === times) { + window.setTimeout(function() { continueTo(rightClick); }, 1000); + } + } + }); - context.on('exit.intro', function() { - // if user leaves select mode here, just continue with the tutorial. - continueTo(reselectPoint); - }); + function continueTo(nextStep) { + listener.on('click', null); + tooltip.call(listener.off); + tooltip.select('.counter').remove(); + nextStep(); + } + } - function continueTo(nextStep) { - context.on('exit.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + function rightClick() { + var counter = 0, + times = 5; - function addCloseEditor() { - // reset pane, in case user happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); + var tooltip = reveal('.intro-nav-wrap .chapter-welcome', + t('intro.welcome.rightclick', { num: times }), + { tooltipClass: 'intro-mouse' } + ); - var selector$$1 = '.entity-editor-pane button.preset-close svg use'; - var href = d3_select(selector$$1).attr('href') || '#icon-close'; + tooltip.selectAll('.tooltip-inner') + .insert('svg', 'span') + .attr('class', 'tooltip-illustration') + .append('use') + .attr('xlink:href', '#walkthrough-mouse'); - context.on('exit.intro', function() { - continueTo(reselectPoint); - }); + tooltip + .append('div') + .attr('class', 'counter'); - reveal('.entity-editor-pane', - t('intro.points.add_close', { button: icon(href, 'pre-text') }) - ); + tooltip.call(listener); - function continueTo(nextStep) { - context.on('exit.intro', null); - nextStep(); - } - } + listener.on('click', function(which) { + if (which === 'right') { + select('.curtain-tooltip.intro-mouse .counter') + .text(String(++counter)); + if (counter === times) { + window.setTimeout(function() { continueTo(chapters); }, 1000); + } + } + }); - function reselectPoint() { - if (!pointId) return chapter.restart(); - var entity = context.hasEntity(pointId); - if (!entity) return chapter.restart(); + function continueTo(nextStep) { + listener.on('click', null); + tooltip.call(listener.off); + tooltip.select('.counter').remove(); + nextStep(); + } + } - // make sure it's still a cafe, in case user somehow changed it.. - var oldPreset = context.presets().match(entity, context.graph()); - context.replace(actionChangePreset(pointId, oldPreset, cafePreset)); - context.enter(modeBrowse(context)); + function chapters() { + dispatch$$1.call('done'); + reveal('.intro-nav-wrap .chapter-navigation', + t('intro.welcome.chapters', { next: t('intro.navigation.title') }) + ); + } - var msec = transitionTime(entity.loc, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().centerEase(entity.loc, msec); - timeout(function() { - var box = pointBox(entity.loc, context); - reveal(box, t('intro.points.reselect'), { duration: 600 }); + chapter.enter = function() { + welcome(); + }; - timeout(function() { - context.map().on('move.intro drawn.intro', function() { - var entity = context.hasEntity(pointId); - if (!entity) return chapter.restart(); - var box = pointBox(entity.loc, context); - reveal(box, t('intro.points.reselect'), { duration: 0 }); - }); - }, 600); // after reveal.. - context.on('enter.intro', function(mode) { - if (mode.id !== 'select') return; - continueTo(updatePoint); - }); + chapter.exit = function() { + listener.off(); + select('.curtain-tooltip.intro-mouse') + .selectAll('.counter') + .remove(); + }; - }, msec + 100); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + chapter.restart = function() { + chapter.exit(); + chapter.enter(); + }; - function updatePoint() { - if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { - return continueTo(reselectPoint); - } + return utilRebind(chapter, dispatch$$1, 'on'); + } - // reset pane, in case user happened to untag the point.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); - context.on('exit.intro', function() { - continueTo(reselectPoint); - }); - context.history().on('change.intro', function() { - continueTo(updateCloseEditor); - }); + function clickListener() { + var dispatch$$1 = dispatch('click'), + minTime = 120, + tooltip = select(null), + down = {}; - timeout(function() { - reveal('.entity-editor-pane', t('intro.points.update'), - { tooltipClass: 'intro-points-describe' } - ); - }, 400); + // `down` keeps track of which buttons/keys are down. + // Setting a property in `down` happens immediately. + // Unsetting a property in `down` is delayed because + // on Windows a contextmenu event happens after keyup/mouseup - function continueTo(nextStep) { - context.on('exit.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + function keydown() { + if (event.keyCode === 93) { // context menu + event.preventDefault(); + event.stopPropagation(); + down.menu = event.timeStamp; + tooltip.classed('rightclick', true); + } + } - function updateCloseEditor() { - if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { - return continueTo(reselectPoint); - } + function keyup() { + if (event.keyCode === 93) { // context menu + event.preventDefault(); + event.stopPropagation(); + var endTime = event.timeStamp, + startTime = down.menu || endTime, + delay = (endTime - startTime < minTime) ? minTime : 0; - // reset pane, in case user happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); + window.setTimeout(function() { + tooltip.classed('rightclick', false); + down.menu = undefined; // delayed, for Windows + }, delay); - context.on('exit.intro', function() { - continueTo(rightClickPoint); - }); + dispatch$$1.call('click', this, 'right'); + } + } - timeout(function() { - reveal('.entity-editor-pane', - t('intro.points.update_close', { button: icon('#icon-apply', 'pre-text') }) - ); - }, 500); - function continueTo(nextStep) { - context.on('exit.intro', null); - nextStep(); - } - } + function mousedown() { + var button = event.button; + if (button === 0 && !event.ctrlKey) { + tooltip.classed('leftclick', true); + } else if (button === 2) { + tooltip.classed('rightclick', true); + } + down[button] = event.timeStamp; + } - function rightClickPoint() { - if (!pointId) return chapter.restart(); - var entity = context.hasEntity(pointId); - if (!entity) return chapter.restart(); + function mouseup() { + var button = event.button, + endTime = event.timeStamp, + startTime = down[button] || endTime, + delay = (endTime - startTime < minTime) ? minTime : 0; - context.enter(modeBrowse(context)); + if (button === 0 && !event.ctrlKey) { + window.setTimeout(function() { + tooltip.classed('leftclick', false); + down[button] = undefined; // delayed, for Windows + }, delay); - var box = pointBox(entity.loc, context); - reveal(box, t('intro.points.rightclick'), { duration: 600 }); + dispatch$$1.call('click', this, 'left'); - timeout(function() { - context.map().on('move.intro drawn.intro', function() { - var entity = context.hasEntity(pointId); - if (!entity) return chapter.restart(); - var box = pointBox(entity.loc, context); - reveal(box, t('intro.points.rightclick'), { duration: 0 }); - }); - }, 600); // after reveal - - context.on('enter.intro', function(mode) { - if (mode.id !== 'select') return; - var ids = context.selectedIDs(); - if (ids.length !== 1 || ids[0] !== pointId) return; - - timeout(function() { - var node = selectMenuItem('delete').node(); - if (!node) return; - continueTo(enterDelete); - }, 300); // after menu visible - }); + } else if (button === 2) { + window.setTimeout(function() { + tooltip.classed('rightclick', false); + down[button] = undefined; // delayed, for Windows + }, delay); - function continueTo(nextStep) { - context.on('enter.intro', null); - context.map().on('move.intro drawn.intro', null); - nextStep(); - } - } + dispatch$$1.call('click', this, 'right'); + } else { + window.setTimeout(function() { + down[button] = undefined; // delayed, for Windows + }, delay); + } + } - function enterDelete() { - if (!pointId) return chapter.restart(); - var entity = context.hasEntity(pointId); - if (!entity) return chapter.restart(); - var node = selectMenuItem('delete').node(); - if (!node) { return continueTo(rightClickPoint); } + function contextmenu() { + event.preventDefault(); + event.stopPropagation(); + if (!down[2] && !down.menu) { + tooltip.classed('rightclick', true); + window.setTimeout(function() { + tooltip.classed('rightclick', false); + }, minTime); + dispatch$$1.call('click', this, 'right'); + } + } - revealEditMenu(entity.loc, - t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }) - ); - timeout(function() { - context.map().on('move.intro drawn.intro', function() { - revealEditMenu(entity.loc, - t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }), - { duration: 0} - ); - }); - }, 300); // after menu visible + var behavior = function(selection$$1) { + tooltip = selection$$1; + down = {}; - context.on('exit.intro', function() { - if (!pointId) return chapter.restart(); - var entity = context.hasEntity(pointId); - if (entity) return continueTo(rightClickPoint); // point still exists - }); + select(window) + .on('keydown.intro', keydown) + .on('keyup.intro', keyup) + .on('mousedown.intro', mousedown) + .on('mouseup.intro', mouseup) + .on('contextmenu.intro', contextmenu); + }; - context.history().on('change.intro', function(changed) { - if (changed.deleted().length) { - continueTo(undo); - } - }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - context.on('exit.intro', null); - nextStep(); - } - } + behavior.off = function() { + select(window) + .on('keydown.intro', null) + .on('keyup.intro', null) + .on('mousedown.intro', null) + .on('mouseup.intro', null) + .on('contextmenu.intro', null); + tooltip + .classed('leftclick', false) + .classed('rightclick', false); + }; - function undo() { - context.history().on('change.intro', function() { - continueTo(play); - }); + return utilRebind(behavior, dispatch$$1, 'on'); + } - var iconName = '#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo'); - reveal('#bar button.undo-button', - t('intro.points.undo', { button: icon(iconName, 'pre-text') }) - ); + function uiIntroNavigation(context, reveal) { + var dispatch$$1 = dispatch('done'), + timeouts = [], + hallId = 'n2061', + townHall = [-85.63591, 41.94285], + springStreetId = 'w397', + springStreetEndId = 'n1834', + springStreet = [-85.63582, 41.94255], + onewayField = context.presets().field('oneway'), + maxspeedField = context.presets().field('maxspeed'); - function continueTo(nextStep) { - context.history().on('change.intro', null); - nextStep(); - } - } + var chapter = { + title: 'intro.navigation.title' + }; - function play() { - dispatch$$1.call('done'); - reveal('#id-container', - t('intro.points.play', { next: t('intro.areas.title') }), { - tooltipBox: '.intro-nav-wrap .chapter-area', - buttonText: t('intro.ok'), - buttonCallback: function() { reveal('#id-container'); } - } - ); - } + function timeout(f, t$$1) { + timeouts.push(window.setTimeout(f, t$$1)); + } - chapter.enter = function() { - addPoint(); - }; + function eventCancel() { + event.stopPropagation(); + event.preventDefault(); + } - chapter.exit = function() { - timeouts.forEach(window.clearTimeout); - context.on('enter.intro exit.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); - d3_select('.preset-search-input').on('keydown.intro keyup.intro', null); - }; + function isTownHallSelected() { + var ids = context.selectedIDs(); + return ids.length === 1 && ids[0] === hallId; + } - chapter.restart = function() { - chapter.exit(); - chapter.enter(); - }; + function dragMap() { + context.enter(modeBrowse(context)); + context.history().reset('initial'); - return utilRebind(chapter, dispatch$$1, 'on'); -} + var msec = transitionTime(townHall, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(19).centerEase(townHall, msec); -function uiIntroArea(context, reveal) { - var dispatch$$1 = dispatch('done'), - playground = [-85.63552, 41.94159], - playgroundPreset = context.presets().item('leisure/playground'), - descriptionField = context.presets().field('description'), - timeouts = [], - areaId; + timeout(function() { + var centerStart = context.map().center(); + reveal('#surface', t('intro.navigation.drag')); + context.map().on('drawn.intro', function() { + reveal('#surface', t('intro.navigation.drag'), { duration: 0 }); + }); - var chapter = { - title: 'intro.areas.title' - }; + context.map().on('move.intro', function() { + var centerNow = context.map().center(); + if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) { + context.map().on('move.intro', null); + timeout(function() { continueTo(zoomMap); }, 3000); + } + }); + }, msec + 100); - function timeout(f, t$$1) { - timeouts.push(window.setTimeout(f, t$$1)); - } + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + nextStep(); + } + } - function eventCancel() { - event.stopPropagation(); - event.preventDefault(); - } + function zoomMap() { + var zoomStart = context.map().zoom(); + reveal('#surface', + t('intro.navigation.zoom', { + plus: icon('#icon-plus', 'pre-text'), + minus: icon('#icon-minus', 'pre-text') + }) + ); - function revealPlayground(center, text, options) { - var padding = 180 * Math.pow(2, context.map().zoom() - 19.5); - var box = pad$1(center, padding, context); - reveal(box, text, options); - } + context.map().on('drawn.intro', function() { + reveal('#surface', + t('intro.navigation.zoom', { + plus: icon('#icon-plus', 'pre-text'), + minus: icon('#icon-minus', 'pre-text') + }), { duration: 0 } + ); + }); + context.map().on('move.intro', function() { + if (context.map().zoom() !== zoomStart) { + context.map().on('move.intro', null); + timeout(function() { continueTo(features); }, 3000); + } + }); - function addArea() { - context.enter(modeBrowse(context)); - context.history().reset('initial'); - areaId = null; + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + nextStep(); + } + } - var msec = transitionTime(playground, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(19).centerEase(playground, msec); - timeout(function() { - var tooltip = reveal('button.add-area', - t('intro.areas.add_playground', { button: icon('#icon-area', 'pre-text') })); + function features() { + var onClick = function() { continueTo(pointsLinesAreas); }; - tooltip.selectAll('.tooltip-inner') - .insert('svg', 'span') - .attr('class', 'tooltip-illustration') - .append('use') - .attr('xlink:href', '#landuse-images'); + reveal('#surface', t('intro.navigation.features'), + { buttonText: t('intro.ok'), buttonCallback: onClick } + ); - context.on('enter.intro', function(mode) { - if (mode.id !== 'add-area') return; - continueTo(startPlayground); - }); - }, msec + 100); + context.map().on('drawn.intro', function() { + reveal('#surface', t('intro.navigation.features'), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } + ); + }); - function continueTo(nextStep) { - context.on('enter.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + context.map().on('drawn.intro', null); + nextStep(); + } + } + function pointsLinesAreas() { + var onClick = function() { continueTo(nodesWays); }; - function startPlayground() { - if (context.mode().id !== 'add-area') { - return chapter.restart(); - } + reveal('#surface', t('intro.navigation.points_lines_areas'), + { buttonText: t('intro.ok'), buttonCallback: onClick } + ); - areaId = null; - context.map().zoomEase(19.5, 500); + context.map().on('drawn.intro', function() { + reveal('#surface', t('intro.navigation.points_lines_areas'), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } + ); + }); - timeout(function() { - revealPlayground(playground, - t('intro.areas.start_playground'), { duration: 250 } - ); + function continueTo(nextStep) { + context.map().on('drawn.intro', null); + nextStep(); + } + } - timeout(function() { - context.map().on('move.intro drawn.intro', function() { - revealPlayground(playground, - t('intro.areas.start_playground'), { duration: 0 } - ); - }); - context.on('enter.intro', function(mode) { - if (mode.id !== 'draw-area') return chapter.restart(); - continueTo(continuePlayground); - }); - }, 250); // after reveal - - }, 550); // after easing - - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + function nodesWays() { + var onClick = function() { continueTo(clickTownHall); }; + reveal('#surface', t('intro.navigation.nodes_ways'), + { buttonText: t('intro.ok'), buttonCallback: onClick } + ); - function continuePlayground() { - if (context.mode().id !== 'draw-area') { - return chapter.restart(); - } + context.map().on('drawn.intro', function() { + reveal('#surface', t('intro.navigation.nodes_ways'), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } + ); + }); - areaId = null; - revealPlayground(playground, - t('intro.areas.continue_playground', { alt: uiCmd.display('⌥') }), - { duration: 250 } - ); + function continueTo(nextStep) { + context.map().on('drawn.intro', null); + nextStep(); + } + } - timeout(function() { - context.map().on('move.intro drawn.intro', function() { - revealPlayground(playground, - t('intro.areas.continue_playground', { alt: uiCmd.display('⌥') }), - { duration: 0 } - ); - }); - }, 250); // after reveal - - context.on('enter.intro', function(mode) { - if (mode.id === 'draw-area') { - var entity = context.hasEntity(context.selectedIDs()[0]); - if (entity && entity.nodes.length >= 6) { - return continueTo(finishPlayground); - } else { - return; - } - } else if (mode.id === 'select') { - areaId = context.selectedIDs()[0]; - return continueTo(searchPresets); - } else { - return chapter.restart(); - } - }); + function clickTownHall() { + context.enter(modeBrowse(context)); + context.history().reset('initial'); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + reveal(null, null, { duration: 0 }); + context.map().zoomEase(19, 500); + timeout(function() { + var entity = context.hasEntity(hallId); + if (!entity) return; + context.map().centerEase(entity.loc, 500); - function finishPlayground() { - if (context.mode().id !== 'draw-area') { - return chapter.restart(); - } + timeout(function() { + var entity = context.hasEntity(hallId); + if (!entity) return; + var box = pointBox(entity.loc, context); + reveal(box, t('intro.navigation.click_townhall')); - areaId = null; - revealPlayground(playground, - t('intro.areas.finish_playground'), { duration: 250 } - ); + context.map().on('move.intro drawn.intro', function() { + var entity = context.hasEntity(hallId); + if (!entity) return; + var box = pointBox(entity.loc, context); + reveal(box, t('intro.navigation.click_townhall'), { duration: 0 }); + }); - timeout(function() { - context.map().on('move.intro drawn.intro', function() { - revealPlayground(playground, - t('intro.areas.finish_playground'), { duration: 0 } - ); - }); - }, 250); // after reveal - - context.on('enter.intro', function(mode) { - if (mode.id === 'draw-area') { - return; - } else if (mode.id === 'select') { - areaId = context.selectedIDs()[0]; - return continueTo(searchPresets); - } else { - return chapter.restart(); - } - }); + context.on('enter.intro', function() { + if (isTownHallSelected()) continueTo(selectedTownHall); + }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + }, 550); // after centerEase + }, 550); // after zoomEase - function searchPresets() { - if (!areaId || !context.hasEntity(areaId)) { - return addArea(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { - context.enter(modeSelect(context, [areaId])); - } + context.history().on('change.intro', function() { + if (!context.hasEntity(hallId)) { + continueTo(clickTownHall); + } + }); - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + function continueTo(nextStep) { + context.on('enter.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - timeout(function() { - // reset pane, in case user somehow happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '-100%'); - d3_select('.preset-search-input') - .on('keydown.intro', null) - .on('keyup.intro', checkPresetSearch); + function selectedTownHall() { + if (!isTownHallSelected()) return clickTownHall(); - reveal('.preset-search-input', - t('intro.areas.search_playground', { preset: playgroundPreset.name() }) - ); - }, 400); // after preset list pane visible.. + var entity = context.hasEntity(hallId); + if (!entity) return clickTownHall(); - context.on('enter.intro', function(mode) { - if (!areaId || !context.hasEntity(areaId)) { - return continueTo(addArea); - } + var box = pointBox(entity.loc, context); + var onClick = function() { continueTo(editorTownHall); }; - var ids = context.selectedIDs(); - if (mode.id !== 'select' || !ids.length || ids[0] !== areaId) { - // keep the user's area selected.. - context.enter(modeSelect(context, [areaId])); + reveal(box, t('intro.navigation.selected_townhall'), + { buttonText: t('intro.ok'), buttonCallback: onClick } + ); - // reset pane, in case user somehow happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '-100%'); - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + context.map().on('move.intro drawn.intro', function() { + var entity = context.hasEntity(hallId); + if (!entity) return; + var box = pointBox(entity.loc, context); + reveal(box, t('intro.navigation.selected_townhall'), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } + ); + }); - d3_select('.preset-search-input') - .on('keydown.intro', null) - .on('keyup.intro', checkPresetSearch); + context.history().on('change.intro', function() { + if (!context.hasEntity(hallId)) { + continueTo(clickTownHall); + } + }); - reveal('.preset-search-input', - t('intro.areas.search_playground', { preset: playgroundPreset.name() }) - ); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - context.history().on('change.intro', null); - } - }); - function checkPresetSearch() { - var first = d3_select('.preset-list-item:first-child'); + function editorTownHall() { + if (!isTownHallSelected()) return clickTownHall(); - if (first.classed('preset-leisure-playground')) { - reveal(first.select('.preset-list-button').node(), - t('intro.areas.choose_playground', { preset: playgroundPreset.name() }), - { duration: 300 } - ); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - d3_select('.preset-search-input') - .on('keydown.intro', eventCancel, true) - .on('keyup.intro', null); + var onClick = function() { continueTo(presetTownHall); }; - context.history().on('change.intro', function() { - continueTo(clickAddField); - }); - } - } + reveal('.entity-editor-pane', + t('intro.navigation.editor_townhall'), + { buttonText: t('intro.ok'), buttonCallback: onClick } + ); - function continueTo(nextStep) { - d3_select('.inspector-wrap').on('wheel.intro', null); - context.on('enter.intro', null); - context.history().on('change.intro', null); - d3_select('.preset-search-input').on('keydown.intro keyup.intro', null); - nextStep(); - } - } + context.on('exit.intro', function() { + continueTo(clickTownHall); + }); + context.history().on('change.intro', function() { + if (!context.hasEntity(hallId)) { + continueTo(clickTownHall); + } + }); - function clickAddField() { - if (!areaId || !context.hasEntity(areaId)) { - return addArea(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { - return searchPresets(); - } + function continueTo(nextStep) { + context.on('exit.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', null); + nextStep(); + } + } - if (!d3_select('.form-field-description').empty()) { - return continueTo(describePlayground); - } - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + function presetTownHall() { + if (!isTownHallSelected()) return clickTownHall(); - timeout(function() { - // reset pane, in case user somehow happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); + // reset pane, in case user happened to change it.. + select('.inspector-wrap .panewrap').style('right', '0%'); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - // It's possible for the user to add a description in a previous step.. - // If they did this already, just continue to next step. - var entity = context.entity(areaId); - if (entity.tags.description) { - return continueTo(play); - } + // preset match, in case the user happened to change it. + var entity = context.entity(context.selectedIDs()[0]); + var preset = context.presets().match(entity, context.graph()); - // scroll "Add field" into view - var box = d3_select('.more-fields').node().getBoundingClientRect(); - if (box.top > 300) { - var pane = d3_select('.entity-editor-pane .inspector-body'); - var start = pane.node().scrollTop; - var end = start + (box.top - 300); - - pane - .transition() - .duration(250) - .tween('scroll.inspector', function() { - var node = this; - var i = d3_interpolateNumber(start, end); - return function(t$$1) { - node.scrollTop = i(t$$1); - }; - }); - } + var onClick = function() { continueTo(fieldsTownHall); }; - timeout(function() { - reveal('.more-fields .combobox-input', - t('intro.areas.add_field'), - { duration: 300 } - ); + context.on('exit.intro', function() { + continueTo(clickTownHall); + }); - d3_select('.more-fields .combobox-input') - .on('click.intro', function() { - continueTo(chooseDescriptionField); - }); - }, 300); // after "Add Field" visible + context.history().on('change.intro', function() { + if (!context.hasEntity(hallId)) { + continueTo(clickTownHall); + } + }); - }, 400); // after editor pane visible + reveal('.inspector-body .preset-list-item.inspector-inner', + t('intro.navigation.preset_townhall', { preset: preset.name() }), + { buttonText: t('intro.ok'), buttonCallback: onClick } + ); - context.on('exit.intro', function() { - return continueTo(searchPresets); - }); + function continueTo(nextStep) { + context.on('exit.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.more-fields .combobox-input').on('click.intro', null); - context.on('exit.intro', null); - nextStep(); - } - } + function fieldsTownHall() { + if (!isTownHallSelected()) return clickTownHall(); - function chooseDescriptionField() { - if (!areaId || !context.hasEntity(areaId)) { - return addArea(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { - return searchPresets(); - } + // reset pane, in case user happened to change it.. + select('.inspector-wrap .panewrap').style('right', '0%'); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - if (!d3_select('.form-field-description').empty()) { - return continueTo(describePlayground); - } + var onClick = function() { continueTo(closeTownHall); }; - // Make sure combobox is ready.. - if (d3_select('div.combobox').empty()) { - return continueTo(clickAddField); - } - // Watch for the combobox to go away.. - var watcher; - watcher = window.setInterval(function() { - if (d3_select('div.combobox').empty()) { - window.clearInterval(watcher); - timeout(function() { - if (d3_select('.form-field-description').empty()) { - continueTo(retryChooseDescription); - } else { - continueTo(describePlayground); - } - }, 300); // after description field added. - } - }, 300); + reveal('.inspector-body .preset-editor', + t('intro.navigation.fields_townhall'), + { buttonText: t('intro.ok'), buttonCallback: onClick } + ); - reveal('div.combobox', - t('intro.areas.choose_field', { field: descriptionField.label() }), - { duration: 300 } - ); + context.on('exit.intro', function() { + continueTo(clickTownHall); + }); - context.on('exit.intro', function() { - return continueTo(searchPresets); - }); + context.history().on('change.intro', function() { + if (!context.hasEntity(hallId)) { + continueTo(clickTownHall); + } + }); + + function continueTo(nextStep) { + context.on('exit.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - if (watcher) window.clearInterval(watcher); - context.on('exit.intro', null); - nextStep(); - } - } + function closeTownHall() { + if (!isTownHallSelected()) return clickTownHall(); - function describePlayground() { - if (!areaId || !context.hasEntity(areaId)) { - return addArea(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { - return searchPresets(); - } + var selector$$1 = '.entity-editor-pane button.preset-close svg use'; + var href = select(selector$$1).attr('href') || '#icon-close'; - // reset pane, in case user happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); + reveal('.entity-editor-pane', + t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }) + ); - if (d3_select('.form-field-description').empty()) { - return continueTo(retryChooseDescription); - } + context.on('exit.intro', function() { + continueTo(searchStreet); + }); - context.on('exit.intro', function() { - continueTo(play); - }); + context.history().on('change.intro', function() { + // update the close icon in the tooltip if the user edits something. + var selector$$1 = '.entity-editor-pane button.preset-close svg use'; + var href = select(selector$$1).attr('href') || '#icon-close'; - reveal('.entity-editor-pane', - t('intro.areas.describe_playground', { button: icon('#icon-apply', 'pre-text') }), - { duration: 300 } - ); + reveal('.entity-editor-pane', + t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }), + { duration: 0 } + ); + }); - function continueTo(nextStep) { - context.on('exit.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + context.on('exit.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - function retryChooseDescription() { - if (!areaId || !context.hasEntity(areaId)) { - return addArea(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { - return searchPresets(); - } + function searchStreet() { + context.enter(modeBrowse(context)); + context.history().reset('initial'); // ensure spring street exists - // reset pane, in case user happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '0%'); + var msec = transitionTime(springStreet, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(19).centerEase(springStreet, msec); // ..and user can see it - reveal('.entity-editor-pane', - t('intro.areas.retry_add_field', { field: descriptionField.label() }), { - buttonText: t('intro.ok'), - buttonCallback: function() { continueTo(clickAddField); } - }); + timeout(function() { + reveal('.search-header input', + t('intro.navigation.search_street', { name: t('intro.graph.name.spring-street') }) + ); - context.on('exit.intro', function() { - return continueTo(searchPresets); - }); + select('.search-header input') + .on('keyup.intro', checkSearchResult); + }, msec + 100); + } - function continueTo(nextStep) { - context.on('exit.intro', null); - nextStep(); - } - } + function checkSearchResult() { + var first = select('.feature-list-item:nth-child(0n+2)'), // skip "No Results" item + firstName = first.select('.entity-name'), + name = t('intro.graph.name.spring-street'); - function play() { - dispatch$$1.call('done'); - reveal('#id-container', - t('intro.areas.play', { next: t('intro.lines.title') }), { - tooltipBox: '.intro-nav-wrap .chapter-line', - buttonText: t('intro.ok'), - buttonCallback: function() { reveal('#id-container'); } - } - ); - } + if (!firstName.empty() && firstName.text() === name) { + reveal(first.node(), + t('intro.navigation.choose_street', { name: name }), + { duration: 300 } + ); + context.on('exit.intro', function() { + continueTo(selectedStreet); + }); - chapter.enter = function() { - addArea(); - }; + select('.search-header input') + .on('keydown.intro', eventCancel, true) + .on('keyup.intro', null); + } + function continueTo(nextStep) { + context.on('exit.intro', null); + select('.search-header input') + .on('keydown.intro', null) + .on('keyup.intro', null); + nextStep(); + } + } - chapter.exit = function() { - timeouts.forEach(window.clearTimeout); - context.on('enter.intro exit.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.preset-search-input').on('keydown.intro keyup.intro', null); - d3_select('.more-fields .combobox-input').on('click.intro', null); - }; + function selectedStreet() { + if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) { + return searchStreet(); + } - chapter.restart = function() { - chapter.exit(); - chapter.enter(); - }; + var onClick = function() { continueTo(editorStreet); }; + var entity = context.entity(springStreetEndId); + var box = pointBox(entity.loc, context); + box.height = 500; + reveal(box, + t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }), + { duration: 600, buttonText: t('intro.ok'), buttonCallback: onClick } + ); - return utilRebind(chapter, dispatch$$1, 'on'); -} - -function uiIntroLine(context, reveal) { - var dispatch$$1 = dispatch('done'), - timeouts = [], - tulipRoadId = null, - flowerRoadId = 'w646', - tulipRoadStart = [-85.6297754121684, 41.95805253325314], - tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204], - tulipRoadIntersection = [-85.62974496187628, 41.95742515554585], - roadCategory = context.presets().item('category-road'), - residentialPreset = context.presets().item('highway/residential'), - woodRoadId = 'w525', - woodRoadEndId = 'n2862', - woodRoadAddNode = [-85.62390110349587, 41.95397111462291], - woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487], - woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872], - washingtonStreetId = 'w522', - twelfthAvenueId = 'w1', - eleventhAvenueEndId = 'n3550', - twelfthAvenueEndId = 'n5', - washingtonSegmentId = null, - eleventhAvenueEnd = context.entity(eleventhAvenueEndId).loc, - twelfthAvenueEnd = context.entity(twelfthAvenueEndId).loc, - deleteLinesLoc = [-85.6219395542764, 41.95228033922477], - twelfthAvenue = [-85.62219310052491, 41.952505413152956]; - - - var chapter = { - title: 'intro.lines.title' - }; + timeout(function() { + context.map().on('move.intro drawn.intro', function() { + var entity = context.hasEntity(springStreetEndId); + if (!entity) return; + var box = pointBox(entity.loc, context); + box.height = 500; + reveal(box, + t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } + ); + }); + }, 600); // after reveal. + + context.on('enter.intro', function(mode) { + if (!context.hasEntity(springStreetId)) { + return continueTo(searchStreet); + } + var ids = context.selectedIDs(); + if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) { + // keep Spring Street selected.. + context.enter(modeSelect(context, [springStreetId])); + } + }); + context.history().on('change.intro', function() { + if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) { + timeout(function() { + continueTo(searchStreet); + }, 300); // after any transition (e.g. if user deleted intersection) + } + }); - function timeout(f, t$$1) { - timeouts.push(window.setTimeout(f, t$$1)); - } + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - function eventCancel() { - event.stopPropagation(); - event.preventDefault(); - } + function editorStreet() { + var selector$$1 = '.entity-editor-pane button.preset-close svg use'; + var href = select(selector$$1).attr('href') || '#icon-close'; + reveal('.entity-editor-pane', + t('intro.navigation.editor_street', { + button: icon(href, 'pre-text'), + field1: onewayField.label(), + field2: maxspeedField.label() + }) + ); - function revealEditMenu(loc, text, options) { - var rect = context.surfaceRect(); - var point$$1 = context.curtainProjection(loc); - var pad = 40; - var width = 250 + (2 * pad); - var height = 350; - var startX = rect.left + point$$1[0]; - var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad); - var box = { - left: left, - top: point$$1[1] + rect.top - 60, - width: width, - height: height - }; - reveal(box, text, options); - } + context.on('exit.intro', function() { + continueTo(play); + }); + context.history().on('change.intro', function() { + // update the close icon in the tooltip if the user edits something. + var selector$$1 = '.entity-editor-pane button.preset-close svg use'; + var href = select(selector$$1).attr('href') || '#icon-close'; + + reveal('.entity-editor-pane', + t('intro.navigation.editor_street', { + button: icon(href, 'pre-text'), + field1: onewayField.label().toLowerCase(), + field2: maxspeedField.label().toLowerCase() + }), { duration: 0 } + ); + }); - function addLine() { - context.enter(modeBrowse(context)); - context.history().reset('initial'); + function continueTo(nextStep) { + context.on('exit.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - var msec = transitionTime(tulipRoadStart, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(18.5).centerEase(tulipRoadStart, msec); - timeout(function() { - var tooltip = reveal('button.add-line', - t('intro.lines.add_line', { button: icon('#icon-line', 'pre-text') })); + function play() { + dispatch$$1.call('done'); + reveal('#id-container', + t('intro.navigation.play', { next: t('intro.points.title') }), { + tooltipBox: '.intro-nav-wrap .chapter-point', + buttonText: t('intro.ok'), + buttonCallback: function() { reveal('#id-container'); } + } + ); + } - tooltip.selectAll('.tooltip-inner') - .insert('svg', 'span') - .attr('class', 'tooltip-illustration') - .append('use') - .attr('xlink:href', '#feature-images'); - context.on('enter.intro', function(mode) { - if (mode.id !== 'add-line') return; - continueTo(startLine); - }); - }, msec + 100); + chapter.enter = function() { + dragMap(); + }; - function continueTo(nextStep) { - context.on('enter.intro', null); - nextStep(); - } - } + chapter.exit = function() { + timeouts.forEach(window.clearTimeout); + context.on('enter.intro exit.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', null); + select('.search-header input').on('keydown.intro keyup.intro', null); + }; - function startLine() { - if (context.mode().id !== 'add-line') { - return chapter.restart(); - } - tulipRoadId = null; + chapter.restart = function() { + chapter.exit(); + chapter.enter(); + }; - var padding = 70 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(tulipRoadStart, padding, context); - box.height = box.height + 100; - reveal(box, t('intro.lines.start_line')); - context.map().on('move.intro drawn.intro', function() { - padding = 70 * Math.pow(2, context.map().zoom() - 18); - box = pad$1(tulipRoadStart, padding, context); - box.height = box.height + 100; - reveal(box, t('intro.lines.start_line'), { duration: 0 }); - }); + return utilRebind(chapter, dispatch$$1, 'on'); + } - context.on('enter.intro', function(mode) { - if (mode.id !== 'draw-line') return chapter.restart(); - continueTo(drawLine); - }); + function uiIntroPoint(context, reveal) { + var dispatch$$1 = dispatch('done'), + timeouts = [], + intersection = [-85.63279, 41.94394], + building = [-85.632422, 41.944045], + cafePreset = context.presets().item('amenity/cafe'), + pointId = null; - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + var chapter = { + title: 'intro.points.title' + }; - function drawLine() { - if (context.mode().id !== 'draw-line') { - return chapter.restart(); - } - tulipRoadId = context.mode().selectedIDs()[0]; - context.map().centerEase(tulipRoadMidpoint, 500); + function timeout(f, t$$1) { + timeouts.push(window.setTimeout(f, t$$1)); + } - timeout(function() { - var padding = 200 * Math.pow(2, context.map().zoom() - 18.5); - var box = pad$1(tulipRoadMidpoint, padding, context); - box.height = box.height * 2; - reveal(box, - t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }) - ); - context.map().on('move.intro drawn.intro', function() { - padding = 200 * Math.pow(2, context.map().zoom() - 18.5); - box = pad$1(tulipRoadMidpoint, padding, context); - box.height = box.height * 2; - reveal(box, - t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }), - { duration: 0 } - ); - }); - }, 550); // after easing.. + function revealEditMenu(loc, text, options) { + var rect = context.surfaceRect(); + var point$$1 = context.curtainProjection(loc); + var pad = 40; + var width = 250 + (2 * pad); + var height = 250; + var startX = rect.left + point$$1[0]; + var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad); + var box = { + left: left, + top: point$$1[1] + rect.top - 60, + width: width, + height: height + }; + reveal(box, text, options); + } - context.history().on('change.intro', function() { - var entity = tulipRoadId && context.hasEntity(tulipRoadId); - if (!entity) return chapter.restart(); - if (isLineConnected()) { - continueTo(continueLine); - } - }); + function eventCancel() { + event.stopPropagation(); + event.preventDefault(); + } - context.on('enter.intro', function(mode) { - if (mode.id === 'draw-line') - return; - else if (mode.id === 'select') { - continueTo(retryIntersect); - return; - } - else - return chapter.restart(); - }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + function addPoint() { + context.enter(modeBrowse(context)); + context.history().reset('initial'); + var msec = transitionTime(intersection, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(19).centerEase(intersection, msec); - function isLineConnected() { - var entity = tulipRoadId && context.hasEntity(tulipRoadId); - if (!entity) return false; + timeout(function() { + var tooltip = reveal('button.add-point', + t('intro.points.add_point', { button: icon('#icon-point', 'pre-text') })); - var drawNodes = context.graph().childNodes(entity); - return some(drawNodes, function(node) { - return some(context.graph().parentWays(node), function(parent) { - return parent.id === flowerRoadId; - }); - }); - } + pointId = null; + tooltip.selectAll('.tooltip-inner') + .insert('svg', 'span') + .attr('class', 'tooltip-illustration') + .append('use') + .attr('xlink:href', '#poi-images'); - function retryIntersect() { - d3_select(window).on('mousedown.intro', eventCancel, true); + context.on('enter.intro', function(mode) { + if (mode.id !== 'add-point') return; + continueTo(placePoint); + }); + }, msec + 100); - var box = pad$1(tulipRoadIntersection, 80, context); - reveal(box, - t('intro.lines.retry_intersect', { name: t('intro.graph.name.flower-street') }) - ); + function continueTo(nextStep) { + context.on('enter.intro', null); + nextStep(); + } + } - timeout(chapter.restart, 3000); - } + function placePoint() { + if (context.mode().id !== 'add-point') { + return chapter.restart(); + } - function continueLine() { - if (context.mode().id !== 'draw-line') return chapter.restart(); - var entity = tulipRoadId && context.hasEntity(tulipRoadId); - if (!entity) return chapter.restart(); + var pointBox$$1 = pad$1(building, 150, context); + reveal(pointBox$$1, t('intro.points.place_point')); - context.map().centerEase(tulipRoadIntersection, 500); + context.map().on('move.intro drawn.intro', function() { + pointBox$$1 = pad$1(building, 150, context); + reveal(pointBox$$1, t('intro.points.place_point'), { duration: 0 }); + }); - reveal('#surface', t('intro.lines.continue_line')); + context.on('enter.intro', function(mode) { + if (mode.id !== 'select') return chapter.restart(); + pointId = context.mode().selectedIDs()[0]; + continueTo(searchPreset); + }); - context.on('enter.intro', function(mode) { - if (mode.id === 'draw-line') - return; - else if (mode.id === 'select') - return continueTo(chooseCategoryRoad); - else - return chapter.restart(); - }); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - context.on('enter.intro', null); - nextStep(); - } - } + function searchPreset() { + if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { + return addPoint(); + } - function chooseCategoryRoad() { - if (context.mode().id !== 'select') { - return chapter.restart(); - } + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - context.on('exit.intro', function() { - return chapter.restart(); - }); + select('.preset-search-input') + .on('keydown.intro', null) + .on('keyup.intro', checkPresetSearch); - var button = d3_select('.preset-category-road .preset-list-button'); - if (button.empty()) return chapter.restart(); + reveal('.preset-search-input', + t('intro.points.search_cafe', { preset: cafePreset.name() }) + ); - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + context.on('enter.intro', function(mode) { + if (!pointId || !context.hasEntity(pointId)) { + return continueTo(addPoint); + } - timeout(function() { - // reset pane, in case user somehow happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '-100%'); + var ids = context.selectedIDs(); + if (mode.id !== 'select' || !ids.length || ids[0] !== pointId) { + // keep the user's point selected.. + context.enter(modeSelect(context, [pointId])); - reveal(button.node(), - t('intro.lines.choose_category_road', { category: roadCategory.name() }) - ); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - button.on('click.intro', function() { - continueTo(choosePresetResidential); - }); + select('.preset-search-input') + .on('keydown.intro', null) + .on('keyup.intro', checkPresetSearch); - }, 400); // after editor pane visible + reveal('.preset-search-input', + t('intro.points.search_cafe', { preset: cafePreset.name() }) + ); - function continueTo(nextStep) { - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.preset-list-button').on('click.intro', null); - context.on('exit.intro', null); - nextStep(); - } - } + context.history().on('change.intro', null); + } + }); - function choosePresetResidential() { - if (context.mode().id !== 'select') { - return chapter.restart(); - } + function checkPresetSearch() { + var first = select('.preset-list-item:first-child'); - context.on('exit.intro', function() { - return chapter.restart(); - }); + if (first.classed('preset-amenity-cafe')) { + select('.preset-search-input') + .on('keydown.intro', eventCancel, true) + .on('keyup.intro', null); - var subgrid = d3_select('.preset-category-road .subgrid'); - if (subgrid.empty()) return chapter.restart(); + reveal(first.select('.preset-list-button').node(), + t('intro.points.choose_cafe', { preset: cafePreset.name() }), + { duration: 300 } + ); - subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button') - .on('click.intro', function() { - continueTo(retryPresetResidential); - }); + context.history().on('change.intro', function() { + continueTo(aboutFeatureEditor); + }); + } + } - subgrid.selectAll('.preset-highway-residential .preset-list-button') - .on('click.intro', function() { - continueTo(nameRoad); - }); + function continueTo(nextStep) { + context.on('enter.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', null); + select('.preset-search-input').on('keydown.intro keyup.intro', null); + nextStep(); + } + } - timeout(function() { - reveal(subgrid.node(), - t('intro.lines.choose_preset_residential', { preset: residentialPreset.name() }), - { tooltipBox: '.preset-highway-residential .preset-list-button', duration: 300 } - ); - }, 300); - function continueTo(nextStep) { - d3_select('.preset-list-button').on('click.intro', null); - context.on('exit.intro', null); - nextStep(); - } - } + function aboutFeatureEditor() { + if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { + return addPoint(); + } + timeout(function() { + reveal('.entity-editor-pane', t('intro.points.feature_editor'), { + tooltipClass: 'intro-points-describe', + buttonText: t('intro.ok'), + buttonCallback: function() { continueTo(addName); } + }); + }, 400); + + context.on('exit.intro', function() { + // if user leaves select mode here, just continue with the tutorial. + continueTo(reselectPoint); + }); - // selected wrong road type - function retryPresetResidential() { - if (context.mode().id !== 'select') { - return chapter.restart(); - } + function continueTo(nextStep) { + context.on('exit.intro', null); + nextStep(); + } + } - context.on('exit.intro', function() { - return chapter.restart(); - }); - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + function addName() { + if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { + return addPoint(); + } - timeout(function() { - var button = d3_select('.entity-editor-pane .preset-list-button'); + // reset pane, in case user happened to change it.. + select('.inspector-wrap .panewrap').style('right', '0%'); + + timeout(function() { + // It's possible for the user to add a name in a previous step.. + // If so, don't tell them to add the name in this step. + // Give them an OK button instead. + var entity = context.entity(pointId); + if (entity.tags.name) { + var tooltip = reveal('.entity-editor-pane', t('intro.points.add_name'), { + tooltipClass: 'intro-points-describe', + buttonText: t('intro.ok'), + buttonCallback: function() { continueTo(addCloseEditor); } + }); + tooltip.select('.instruction').style('display', 'none'); + + } else { + reveal('.entity-editor-pane', t('intro.points.add_name'), + { tooltipClass: 'intro-points-describe' } + ); + } + }, 400); + + context.history().on('change.intro', function() { + continueTo(addCloseEditor); + }); - reveal(button.node(), - t('intro.lines.retry_preset_residential', { preset: residentialPreset.name() }) - ); + context.on('exit.intro', function() { + // if user leaves select mode here, just continue with the tutorial. + continueTo(reselectPoint); + }); - button.on('click.intro', function() { - continueTo(chooseCategoryRoad); - }); + function continueTo(nextStep) { + context.on('exit.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - }, 500); - function continueTo(nextStep) { - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.preset-list-button').on('click.intro', null); - context.on('exit.intro', null); - nextStep(); - } - } + function addCloseEditor() { + // reset pane, in case user happened to change it.. + select('.inspector-wrap .panewrap').style('right', '0%'); + var selector$$1 = '.entity-editor-pane button.preset-close svg use'; + var href = select(selector$$1).attr('href') || '#icon-close'; - function nameRoad() { - context.on('exit.intro', function() { - continueTo(didNameRoad); - }); + context.on('exit.intro', function() { + continueTo(reselectPoint); + }); - timeout(function() { - reveal('.entity-editor-pane', - t('intro.lines.name_road', { button: icon('#icon-apply', 'pre-text') }), - { tooltipClass: 'intro-lines-name_road' } - ); - }, 500); + reveal('.entity-editor-pane', + t('intro.points.add_close', { button: icon(href, 'pre-text') }) + ); - function continueTo(nextStep) { - context.on('exit.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + context.on('exit.intro', null); + nextStep(); + } + } - function didNameRoad() { - context.history().checkpoint('doneAddLine'); + function reselectPoint() { + if (!pointId) return chapter.restart(); + var entity = context.hasEntity(pointId); + if (!entity) return chapter.restart(); - timeout(function() { - reveal('#surface', t('intro.lines.did_name_road'), { - buttonText: t('intro.ok'), - buttonCallback: function() { continueTo(updateLine); } - }); - }, 500); + // make sure it's still a cafe, in case user somehow changed it.. + var oldPreset = context.presets().match(entity, context.graph()); + context.replace(actionChangePreset(pointId, oldPreset, cafePreset)); - function continueTo(nextStep) { - nextStep(); - } - } + context.enter(modeBrowse(context)); + var msec = transitionTime(entity.loc, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().centerEase(entity.loc, msec); - function updateLine() { - context.history().reset('doneAddLine'); - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return chapter.restart(); - } + timeout(function() { + var box = pointBox(entity.loc, context); + reveal(box, t('intro.points.reselect'), { duration: 600 }); - var msec = transitionTime(woodRoadDragMidpoint, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(19).centerEase(woodRoadDragMidpoint, msec); + timeout(function() { + context.map().on('move.intro drawn.intro', function() { + var entity = context.hasEntity(pointId); + if (!entity) return chapter.restart(); + var box = pointBox(entity.loc, context); + reveal(box, t('intro.points.reselect'), { duration: 0 }); + }); + }, 600); // after reveal.. - timeout(function() { - var padding = 250 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragMidpoint, padding, context); - var advance = function() { continueTo(addNode); }; + context.on('enter.intro', function(mode) { + if (mode.id !== 'select') return; + continueTo(updatePoint); + }); - reveal(box, t('intro.lines.update_line'), - { buttonText: t('intro.ok'), buttonCallback: advance } - ); + }, msec + 100); - context.map().on('move.intro drawn.intro', function() { - var padding = 250 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragMidpoint, padding, context); - reveal(box, t('intro.lines.update_line'), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance } - ); - }); - }, msec + 100); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - nextStep(); - } - } + function updatePoint() { + if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { + return continueTo(reselectPoint); + } - function addNode() { - context.history().reset('doneAddLine'); - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return chapter.restart(); - } + // reset pane, in case user happened to untag the point.. + select('.inspector-wrap .panewrap').style('right', '0%'); - var padding = 40 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadAddNode, padding, context); - reveal(box, t('intro.lines.add_node')); + context.on('exit.intro', function() { + continueTo(reselectPoint); + }); - context.map().on('move.intro drawn.intro', function() { - var padding = 40 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadAddNode, padding, context); - reveal(box, t('intro.lines.add_node'), { duration: 0 }); - }); + context.history().on('change.intro', function() { + continueTo(updateCloseEditor); + }); - context.history().on('change.intro', function(changed) { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } - if (changed.created().length === 1) { - timeout(function() { continueTo(startDragEndpoint); }, 500); - } - }); + timeout(function() { + reveal('.entity-editor-pane', t('intro.points.update'), + { tooltipClass: 'intro-points-describe' } + ); + }, 400); - context.on('enter.intro', function(mode) { - if (mode.id !== 'select') { - continueTo(updateLine); - } - }); + function continueTo(nextStep) { + context.on('exit.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + function updateCloseEditor() { + if (context.mode().id !== 'select' || !pointId || !context.hasEntity(pointId)) { + return continueTo(reselectPoint); + } - function startDragEndpoint() { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } - var padding = 100 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragEndpoint, padding, context); - reveal(box, t('intro.lines.start_drag_endpoint')); + // reset pane, in case user happened to change it.. + select('.inspector-wrap .panewrap').style('right', '0%'); - context.map().on('move.intro drawn.intro', function() { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } - var padding = 100 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragEndpoint, padding, context); - reveal(box, t('intro.lines.start_drag_endpoint'), { duration: 0 }); + context.on('exit.intro', function() { + continueTo(rightClickPoint); + }); - var entity = context.entity(woodRoadEndId); - if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) { - continueTo(finishDragEndpoint); - } - }); + timeout(function() { + reveal('.entity-editor-pane', + t('intro.points.update_close', { button: icon('#icon-apply', 'pre-text') }) + ); + }, 500); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + context.on('exit.intro', null); + nextStep(); + } + } - function finishDragEndpoint() { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } + function rightClickPoint() { + if (!pointId) return chapter.restart(); + var entity = context.hasEntity(pointId); + if (!entity) return chapter.restart(); - var padding = 100 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragEndpoint, padding, context); - reveal(box, t('intro.lines.finish_drag_endpoint')); + context.enter(modeBrowse(context)); - context.map().on('move.intro drawn.intro', function() { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } - var padding = 100 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragEndpoint, padding, context); - reveal(box, t('intro.lines.finish_drag_endpoint'), { duration: 0 }); + var box = pointBox(entity.loc, context); + reveal(box, t('intro.points.rightclick'), { duration: 600 }); - var entity = context.entity(woodRoadEndId); - if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) { - continueTo(startDragEndpoint); - } - }); + timeout(function() { + context.map().on('move.intro drawn.intro', function() { + var entity = context.hasEntity(pointId); + if (!entity) return chapter.restart(); + var box = pointBox(entity.loc, context); + reveal(box, t('intro.points.rightclick'), { duration: 0 }); + }); + }, 600); // after reveal - context.on('enter.intro', function() { - continueTo(startDragMidpoint); - }); + context.on('enter.intro', function(mode) { + if (mode.id !== 'select') return; + var ids = context.selectedIDs(); + if (ids.length !== 1 || ids[0] !== pointId) return; - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + timeout(function() { + var node = selectMenuItem('delete').node(); + if (!node) return; + continueTo(enterDelete); + }, 300); // after menu visible + }); + function continueTo(nextStep) { + context.on('enter.intro', null); + context.map().on('move.intro drawn.intro', null); + nextStep(); + } + } - function startDragMidpoint() { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } - if (context.selectedIDs().indexOf(woodRoadId) === -1) { - context.enter(modeSelect(context, [woodRoadId])); - } - var padding = 80 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragMidpoint, padding, context); - reveal(box, t('intro.lines.start_drag_midpoint')); + function enterDelete() { + if (!pointId) return chapter.restart(); + var entity = context.hasEntity(pointId); + if (!entity) return chapter.restart(); - context.map().on('move.intro drawn.intro', function() { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } - var padding = 80 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragMidpoint, padding, context); - reveal(box, t('intro.lines.start_drag_midpoint'), { duration: 0 }); - }); + var node = selectMenuItem('delete').node(); + if (!node) { return continueTo(rightClickPoint); } - context.history().on('change.intro', function(changed) { - if (changed.created().length === 1) { - continueTo(continueDragMidpoint); - } - }); + revealEditMenu(entity.loc, + t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }) + ); - context.on('enter.intro', function(mode) { - if (mode.id !== 'select') { - // keep Wood Road selected so midpoint triangles are drawn.. - context.enter(modeSelect(context, [woodRoadId])); - } - }); + timeout(function() { + context.map().on('move.intro drawn.intro', function() { + revealEditMenu(entity.loc, + t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }), + { duration: 0} + ); + }); + }, 300); // after menu visible + + context.on('exit.intro', function() { + if (!pointId) return chapter.restart(); + var entity = context.hasEntity(pointId); + if (entity) return continueTo(rightClickPoint); // point still exists + }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + context.history().on('change.intro', function(changed) { + if (changed.deleted().length) { + continueTo(undo); + } + }); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + context.on('exit.intro', null); + nextStep(); + } + } - function continueDragMidpoint() { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } - var padding = 100 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragEndpoint, padding, context); - box.height += 400; + function undo() { + context.history().on('change.intro', function() { + continueTo(play); + }); - var advance = function() { - context.history().checkpoint('doneUpdateLine'); - continueTo(deleteLines); - }; + var iconName = '#icon-' + (textDirection === 'rtl' ? 'redo' : 'undo'); + reveal('#bar button.undo-button', + t('intro.points.undo', { button: icon(iconName, 'pre-text') }) + ); - reveal(box, t('intro.lines.continue_drag_midpoint'), - { buttonText: t('intro.ok'), buttonCallback: advance } - ); + function continueTo(nextStep) { + context.history().on('change.intro', null); + nextStep(); + } + } - context.map().on('move.intro drawn.intro', function() { - if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { - return continueTo(updateLine); - } - var padding = 100 * Math.pow(2, context.map().zoom() - 19); - var box = pad$1(woodRoadDragEndpoint, padding, context); - box.height += 400; - reveal(box, t('intro.lines.continue_drag_midpoint'), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance } - ); - }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - nextStep(); - } - } + function play() { + dispatch$$1.call('done'); + reveal('#id-container', + t('intro.points.play', { next: t('intro.areas.title') }), { + tooltipBox: '.intro-nav-wrap .chapter-area', + buttonText: t('intro.ok'), + buttonCallback: function() { reveal('#id-container'); } + } + ); + } - function deleteLines() { - context.history().reset('doneUpdateLine'); - context.enter(modeBrowse(context)); + chapter.enter = function() { + addPoint(); + }; - if (!context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return chapter.restart(); - } - var msec = transitionTime(deleteLinesLoc, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(18).centerEase(deleteLinesLoc, msec); + chapter.exit = function() { + timeouts.forEach(window.clearTimeout); + context.on('enter.intro exit.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', eventCancel); + select('.preset-search-input').on('keydown.intro keyup.intro', null); + }; - timeout(function() { - var padding = 200 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(deleteLinesLoc, padding, context); - box.top -= 200; - box.height += 400; - var advance = function() { continueTo(rightClickIntersection); }; - reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }), - { buttonText: t('intro.ok'), buttonCallback: advance } - ); + chapter.restart = function() { + chapter.exit(); + chapter.enter(); + }; - context.map().on('move.intro drawn.intro', function() { - var padding = 200 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(deleteLinesLoc, padding, context); - box.top -= 200; - box.height += 400; - reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance } - ); - }); - context.history().on('change.intro', function() { - timeout(function() { - continueTo(deleteLines); - }, 500); // after any transition (e.g. if user deleted intersection) - }); + return utilRebind(chapter, dispatch$$1, 'on'); + } - }, msec + 100); + function uiIntroArea(context, reveal) { + var dispatch$$1 = dispatch('done'), + playground = [-85.63552, 41.94159], + playgroundPreset = context.presets().item('leisure/playground'), + descriptionField = context.presets().field('description'), + timeouts = [], + areaId; - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + var chapter = { + title: 'intro.areas.title' + }; - function rightClickIntersection() { - context.history().reset('doneUpdateLine'); - context.enter(modeBrowse(context)); - context.map().zoom(18).centerEase(eleventhAvenueEnd, 500); + function timeout(f, t$$1) { + timeouts.push(window.setTimeout(f, t$$1)); + } - timeout(function() { - var padding = 60 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(eleventhAvenueEnd, padding, context); - reveal(box, t('intro.lines.rightclick_intersection', - { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') }) - ); - context.map().on('move.intro drawn.intro', function() { - var padding = 60 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(eleventhAvenueEnd, padding, context); - reveal(box, t('intro.lines.rightclick_intersection', - { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') }), - { duration: 0 } - ); - }); + function eventCancel() { + event.stopPropagation(); + event.preventDefault(); + } - context.on('enter.intro', function(mode) { - if (mode.id !== 'select') return; - var ids = context.selectedIDs(); - if (ids.length !== 1 || ids[0] !== eleventhAvenueEndId) return; - timeout(function() { - var node = selectMenuItem('split').node(); - if (!node) return; - continueTo(splitIntersection); - }, 300); // after menu visible - }); + function revealPlayground(center, text, options) { + var padding = 180 * Math.pow(2, context.map().zoom() - 19.5); + var box = pad$1(center, padding, context); + reveal(box, text, options); + } - context.history().on('change.intro', function() { - timeout(function() { - continueTo(deleteLines); - }, 300); // after any transition (e.g. if user deleted intersection) - }); - }, 600); + function addArea() { + context.enter(modeBrowse(context)); + context.history().reset('initial'); + areaId = null; - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + var msec = transitionTime(playground, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(19).centerEase(playground, msec); + timeout(function() { + var tooltip = reveal('button.add-area', + t('intro.areas.add_playground', { button: icon('#icon-area', 'pre-text') })); - function splitIntersection() { - if (!context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return continueTo(deleteLines); - } + tooltip.selectAll('.tooltip-inner') + .insert('svg', 'span') + .attr('class', 'tooltip-illustration') + .append('use') + .attr('xlink:href', '#landuse-images'); - var node = selectMenuItem('split').node(); - if (!node) { return continueTo(rightClickIntersection); } + context.on('enter.intro', function(mode) { + if (mode.id !== 'add-area') return; + continueTo(startPlayground); + }); + }, msec + 100); - var wasChanged = false; - var menuCoords = context.map().mouseCoordinates(); - washingtonSegmentId = null; + function continueTo(nextStep) { + context.on('enter.intro', null); + nextStep(); + } + } - revealEditMenu(menuCoords, t('intro.lines.split_intersection', - { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') }) - ); - context.map().on('move.intro drawn.intro', function() { - var node = selectMenuItem('split').node(); - if (!wasChanged && !node) { return continueTo(rightClickIntersection); } + function startPlayground() { + if (context.mode().id !== 'add-area') { + return chapter.restart(); + } - revealEditMenu(menuCoords, t('intro.lines.split_intersection', - { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') }), - { duration: 0 } - ); - }); + areaId = null; + context.map().zoomEase(19.5, 500); + + timeout(function() { + revealPlayground(playground, + t('intro.areas.start_playground'), { duration: 250 } + ); + + timeout(function() { + context.map().on('move.intro drawn.intro', function() { + revealPlayground(playground, + t('intro.areas.start_playground'), { duration: 0 } + ); + }); + context.on('enter.intro', function(mode) { + if (mode.id !== 'draw-area') return chapter.restart(); + continueTo(continuePlayground); + }); + }, 250); // after reveal + + }, 550); // after easing + + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - context.history().on('change.intro', function(changed) { - wasChanged = true; - timeout(function() { - if (context.history().undoAnnotation() === t('operations.split.annotation.line')) { - washingtonSegmentId = changed.created()[0].id; - continueTo(didSplit); - } else { - washingtonSegmentId = null; - continueTo(retrySplit); - } - }, 300); // after any transition (e.g. if user deleted intersection) - }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + function continuePlayground() { + if (context.mode().id !== 'draw-area') { + return chapter.restart(); + } + areaId = null; + revealPlayground(playground, + t('intro.areas.continue_playground', { alt: uiCmd.display('⌥') }), + { duration: 250 } + ); - function retrySplit() { - context.enter(modeBrowse(context)); - context.map().zoom(18).centerEase(eleventhAvenueEnd, 500); - var advance = function() { continueTo(rightClickIntersection); }; + timeout(function() { + context.map().on('move.intro drawn.intro', function() { + revealPlayground(playground, + t('intro.areas.continue_playground', { alt: uiCmd.display('⌥') }), + { duration: 0 } + ); + }); + }, 250); // after reveal + + context.on('enter.intro', function(mode) { + if (mode.id === 'draw-area') { + var entity = context.hasEntity(context.selectedIDs()[0]); + if (entity && entity.nodes.length >= 6) { + return continueTo(finishPlayground); + } else { + return; + } + } else if (mode.id === 'select') { + areaId = context.selectedIDs()[0]; + return continueTo(searchPresets); + } else { + return chapter.restart(); + } + }); - var padding = 60 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(eleventhAvenueEnd, padding, context); - reveal(box, t('intro.lines.retry_split'), - { buttonText: t('intro.ok'), buttonCallback: advance } - ); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - context.map().on('move.intro drawn.intro', function() { - var padding = 60 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(eleventhAvenueEnd, padding, context); - reveal(box, t('intro.lines.retry_split'), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance } - ); - }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - nextStep(); - } - } + function finishPlayground() { + if (context.mode().id !== 'draw-area') { + return chapter.restart(); + } + areaId = null; + revealPlayground(playground, + t('intro.areas.finish_playground'), { duration: 250 } + ); - function didSplit() { - if (!washingtonSegmentId || - !context.hasEntity(washingtonSegmentId) || - !context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return continueTo(rightClickIntersection); - } + timeout(function() { + context.map().on('move.intro drawn.intro', function() { + revealPlayground(playground, + t('intro.areas.finish_playground'), { duration: 0 } + ); + }); + }, 250); // after reveal + + context.on('enter.intro', function(mode) { + if (mode.id === 'draw-area') { + return; + } else if (mode.id === 'select') { + areaId = context.selectedIDs()[0]; + return continueTo(searchPresets); + } else { + return chapter.restart(); + } + }); - var ids = context.selectedIDs(); - var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single'); - var street = t('intro.graph.name.washington-street'); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - var padding = 200 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(twelfthAvenue, padding, context); - box.width = box.width / 2; - reveal(box, t(string, { street1: street, street2: street }), - { duration: 500 } - ); - timeout(function() { - context.map().zoom(18).centerEase(twelfthAvenue, 500); + function searchPresets() { + if (!areaId || !context.hasEntity(areaId)) { + return addArea(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { + context.enter(modeSelect(context, [areaId])); + } - context.map().on('move.intro drawn.intro', function() { - var padding = 200 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(twelfthAvenue, padding, context); - box.width = box.width / 2; - reveal(box, t(string, { street1: street, street2: street }), - { duration: 0 } - ); - }); - }, 600); // after initial reveal and curtain cut + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - context.on('enter.intro', function() { - var ids = context.selectedIDs(); - if (ids.length === 1 && ids[0] === washingtonSegmentId) { - continueTo(multiSelect); - } - }); + timeout(function() { + // reset pane, in case user somehow happened to change it.. + select('.inspector-wrap .panewrap').style('right', '-100%'); - context.history().on('change.intro', function() { - if (!washingtonSegmentId || - !context.hasEntity(washingtonSegmentId) || - !context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return continueTo(rightClickIntersection); - } - }); + select('.preset-search-input') + .on('keydown.intro', null) + .on('keyup.intro', checkPresetSearch); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + reveal('.preset-search-input', + t('intro.areas.search_playground', { preset: playgroundPreset.name() }) + ); + }, 400); // after preset list pane visible.. + context.on('enter.intro', function(mode) { + if (!areaId || !context.hasEntity(areaId)) { + return continueTo(addArea); + } - function multiSelect() { - if (!washingtonSegmentId || - !context.hasEntity(washingtonSegmentId) || - !context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return continueTo(rightClickIntersection); - } + var ids = context.selectedIDs(); + if (mode.id !== 'select' || !ids.length || ids[0] !== areaId) { + // keep the user's area selected.. + context.enter(modeSelect(context, [areaId])); - var ids = context.selectedIDs(); - var hasWashington = ids.indexOf(washingtonSegmentId) !== -1; - var hasTwelfth = ids.indexOf(twelfthAvenueId) !== -1; + // reset pane, in case user somehow happened to change it.. + select('.inspector-wrap .panewrap').style('right', '-100%'); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - if (hasWashington && hasTwelfth) { - return continueTo(multiRightClick); - } else if (!hasWashington && !hasTwelfth) { - return continueTo(didSplit); - } + select('.preset-search-input') + .on('keydown.intro', null) + .on('keyup.intro', checkPresetSearch); - context.map().zoom(18).centerEase(twelfthAvenue, 500); + reveal('.preset-search-input', + t('intro.areas.search_playground', { preset: playgroundPreset.name() }) + ); - timeout(function() { - var selected, other, padding, box; - if (hasWashington) { - selected = t('intro.graph.name.washington-street'); - other = t('intro.graph.name.12th-avenue'); - padding = 60 * Math.pow(2, context.map().zoom() - 18); - box = pad$1(twelfthAvenueEnd, padding, context); - box.width *= 3; - } else { - selected = t('intro.graph.name.12th-avenue'); - other = t('intro.graph.name.washington-street'); - padding = 200 * Math.pow(2, context.map().zoom() - 18); - box = pad$1(twelfthAvenue, padding, context); - box.width /= 2; - } + context.history().on('change.intro', null); + } + }); - reveal(box, - t('intro.lines.multi_select', { selected: selected, other1: other, other2: other }) - ); + function checkPresetSearch() { + var first = select('.preset-list-item:first-child'); - context.map().on('move.intro drawn.intro', function() { - if (hasWashington) { - selected = t('intro.graph.name.washington-street'); - other = t('intro.graph.name.12th-avenue'); - padding = 60 * Math.pow(2, context.map().zoom() - 18); - box = pad$1(twelfthAvenueEnd, padding, context); - box.width *= 3; - } else { - selected = t('intro.graph.name.12th-avenue'); - other = t('intro.graph.name.washington-street'); - padding = 200 * Math.pow(2, context.map().zoom() - 18); - box = pad$1(twelfthAvenue, padding, context); - box.width /= 2; - } - - reveal(box, - t('intro.lines.multi_select', { selected: selected, other1: other, other2: other }), - { duration: 0 } - ); - }); + if (first.classed('preset-leisure-playground')) { + reveal(first.select('.preset-list-button').node(), + t('intro.areas.choose_playground', { preset: playgroundPreset.name() }), + { duration: 300 } + ); - context.on('enter.intro', function() { - continueTo(multiSelect); - }); + select('.preset-search-input') + .on('keydown.intro', eventCancel, true) + .on('keyup.intro', null); - context.history().on('change.intro', function() { - if (!washingtonSegmentId || - !context.hasEntity(washingtonSegmentId) || - !context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return continueTo(rightClickIntersection); - } - }); - }, 600); + context.history().on('change.intro', function() { + continueTo(clickAddField); + }); + } + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + select('.inspector-wrap').on('wheel.intro', null); + context.on('enter.intro', null); + context.history().on('change.intro', null); + select('.preset-search-input').on('keydown.intro keyup.intro', null); + nextStep(); + } + } - function multiRightClick() { - if (!washingtonSegmentId || - !context.hasEntity(washingtonSegmentId) || - !context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return continueTo(rightClickIntersection); - } + function clickAddField() { + if (!areaId || !context.hasEntity(areaId)) { + return addArea(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { + return searchPresets(); + } - var padding = 200 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(twelfthAvenue, padding, context); - reveal(box, t('intro.lines.multi_rightclick')); + if (!select('.form-field-description').empty()) { + return continueTo(describePlayground); + } - context.map().on('move.intro drawn.intro', function() { - var padding = 200 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(twelfthAvenue, padding, context); - reveal(box, t('intro.lines.multi_rightclick'), { duration: 0 }); - }); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); + + timeout(function() { + // reset pane, in case user somehow happened to change it.. + select('.inspector-wrap .panewrap').style('right', '0%'); + + // It's possible for the user to add a description in a previous step.. + // If they did this already, just continue to next step. + var entity = context.entity(areaId); + if (entity.tags.description) { + return continueTo(play); + } + + // scroll "Add field" into view + var box = select('.more-fields').node().getBoundingClientRect(); + if (box.top > 300) { + var pane = select('.entity-editor-pane .inspector-body'); + var start = pane.node().scrollTop; + var end = start + (box.top - 300); + + pane + .transition() + .duration(250) + .tween('scroll.inspector', function() { + var node = this; + var i = interpolateNumber(start, end); + return function(t$$1) { + node.scrollTop = i(t$$1); + }; + }); + } + + timeout(function() { + reveal('.more-fields .combobox-input', + t('intro.areas.add_field'), + { duration: 300 } + ); + + select('.more-fields .combobox-input') + .on('click.intro', function() { + continueTo(chooseDescriptionField); + }); + }, 300); // after "Add Field" visible + + }, 400); // after editor pane visible + + context.on('exit.intro', function() { + return continueTo(searchPresets); + }); - d3_select(window).on('click.intro contextmenu.intro', function() { - timeout(function() { - var ids = context.selectedIDs(); - if (ids.length === 2 && - ids.indexOf(twelfthAvenueId) !== -1 && - ids.indexOf(washingtonSegmentId) !== -1) { - var node = selectMenuItem('delete').node(); - if (!node) return; - continueTo(multiDelete); - } else if (ids.length === 1 && - ids.indexOf(washingtonSegmentId) !== -1) { - return continueTo(multiSelect); - } else { - return continueTo(didSplit); - } - }, 300); // after edit menu visible - }, true); - - context.history().on('change.intro', function() { - if (!washingtonSegmentId || - !context.hasEntity(washingtonSegmentId) || - !context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return continueTo(rightClickIntersection); - } - }); + function continueTo(nextStep) { + select('.inspector-wrap').on('wheel.intro', null); + select('.more-fields .combobox-input').on('click.intro', null); + context.on('exit.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - d3_select(window).on('click.intro contextmenu.intro', null, true); - context.history().on('change.intro', null); - nextStep(); - } - } + function chooseDescriptionField() { + if (!areaId || !context.hasEntity(areaId)) { + return addArea(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { + return searchPresets(); + } - function multiDelete() { - if (!washingtonSegmentId || - !context.hasEntity(washingtonSegmentId) || - !context.hasEntity(washingtonStreetId) || - !context.hasEntity(twelfthAvenueId) || - !context.hasEntity(eleventhAvenueEndId)) { - return continueTo(rightClickIntersection); - } + if (!select('.form-field-description').empty()) { + return continueTo(describePlayground); + } - var node = selectMenuItem('delete').node(); - if (!node) return continueTo(multiRightClick); + // Make sure combobox is ready.. + if (select('div.combobox').empty()) { + return continueTo(clickAddField); + } + // Watch for the combobox to go away.. + var watcher; + watcher = window.setInterval(function() { + if (select('div.combobox').empty()) { + window.clearInterval(watcher); + timeout(function() { + if (select('.form-field-description').empty()) { + continueTo(retryChooseDescription); + } else { + continueTo(describePlayground); + } + }, 300); // after description field added. + } + }, 300); + + reveal('div.combobox', + t('intro.areas.choose_field', { field: descriptionField.label() }), + { duration: 300 } + ); - var menuCoords = context.map().mouseCoordinates(); - revealEditMenu(menuCoords, - t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') }) - ); + context.on('exit.intro', function() { + return continueTo(searchPresets); + }); - context.map().on('move.intro drawn.intro', function() { - revealEditMenu(menuCoords, - t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') }), - { duration: 0 } - ); - }); + function continueTo(nextStep) { + if (watcher) window.clearInterval(watcher); + context.on('exit.intro', null); + nextStep(); + } + } - context.on('exit.intro', function() { - if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) { - return continueTo(multiSelect); // left select mode but roads still exist - } - }); - context.history().on('change.intro', function() { - if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) { - continueTo(retryDelete); // changed something but roads still exist - } else { - continueTo(play); - } - }); + function describePlayground() { + if (!areaId || !context.hasEntity(areaId)) { + return addArea(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { + return searchPresets(); + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('exit.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + // reset pane, in case user happened to change it.. + select('.inspector-wrap .panewrap').style('right', '0%'); + if (select('.form-field-description').empty()) { + return continueTo(retryChooseDescription); + } - function retryDelete() { - context.enter(modeBrowse(context)); + context.on('exit.intro', function() { + continueTo(play); + }); - var padding = 200 * Math.pow(2, context.map().zoom() - 18); - var box = pad$1(twelfthAvenue, padding, context); - reveal(box, t('intro.lines.retry_delete'), { - buttonText: t('intro.ok'), - buttonCallback: function() { continueTo(multiSelect); } - }); + reveal('.entity-editor-pane', + t('intro.areas.describe_playground', { button: icon('#icon-apply', 'pre-text') }), + { duration: 300 } + ); - function continueTo(nextStep) { - nextStep(); - } - } + function continueTo(nextStep) { + context.on('exit.intro', null); + nextStep(); + } + } - function play() { - dispatch$$1.call('done'); - reveal('#id-container', - t('intro.lines.play', { next: t('intro.buildings.title') }), { - tooltipBox: '.intro-nav-wrap .chapter-building', - buttonText: t('intro.ok'), - buttonCallback: function() { reveal('#id-container'); } - } - ); - } + function retryChooseDescription() { + if (!areaId || !context.hasEntity(areaId)) { + return addArea(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== areaId) { + return searchPresets(); + } + // reset pane, in case user happened to change it.. + select('.inspector-wrap .panewrap').style('right', '0%'); - chapter.enter = function() { - addLine(); - }; + reveal('.entity-editor-pane', + t('intro.areas.retry_add_field', { field: descriptionField.label() }), { + buttonText: t('intro.ok'), + buttonCallback: function() { continueTo(clickAddField); } + }); + context.on('exit.intro', function() { + return continueTo(searchPresets); + }); - chapter.exit = function() { - timeouts.forEach(window.clearTimeout); - d3_select(window).on('mousedown.intro', null, true); - context.on('enter.intro exit.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.preset-list-button').on('click.intro', null); - }; + function continueTo(nextStep) { + context.on('exit.intro', null); + nextStep(); + } + } - chapter.restart = function() { - chapter.exit(); - chapter.enter(); - }; + function play() { + dispatch$$1.call('done'); + reveal('#id-container', + t('intro.areas.play', { next: t('intro.lines.title') }), { + tooltipBox: '.intro-nav-wrap .chapter-line', + buttonText: t('intro.ok'), + buttonCallback: function() { reveal('#id-container'); } + } + ); + } - return utilRebind(chapter, dispatch$$1, 'on'); -} + chapter.enter = function() { + addArea(); + }; -function uiIntroBuilding(context, reveal) { - var dispatch$$1 = dispatch('done'), - house = [-85.62815, 41.95638], - tank = [-85.62732, 41.95347], - buildingCatetory = context.presets().item('category-building'), - housePreset = context.presets().item('building/house'), - tankPreset = context.presets().item('man_made/storage_tank'), - timeouts = [], - houseId = null, - tankId = null; + chapter.exit = function() { + timeouts.forEach(window.clearTimeout); + context.on('enter.intro exit.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', null); + select('.preset-search-input').on('keydown.intro keyup.intro', null); + select('.more-fields .combobox-input').on('click.intro', null); + }; - var chapter = { - title: 'intro.buildings.title' - }; + chapter.restart = function() { + chapter.exit(); + chapter.enter(); + }; - function timeout(f, t$$1) { - timeouts.push(window.setTimeout(f, t$$1)); - } + return utilRebind(chapter, dispatch$$1, 'on'); + } - function eventCancel() { - event.stopPropagation(); - event.preventDefault(); - } + function uiIntroLine(context, reveal) { + var dispatch$$1 = dispatch('done'), + timeouts = [], + tulipRoadId = null, + flowerRoadId = 'w646', + tulipRoadStart = [-85.6297754121684, 41.95805253325314], + tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204], + tulipRoadIntersection = [-85.62974496187628, 41.95742515554585], + roadCategory = context.presets().item('category-road'), + residentialPreset = context.presets().item('highway/residential'), + woodRoadId = 'w525', + woodRoadEndId = 'n2862', + woodRoadAddNode = [-85.62390110349587, 41.95397111462291], + woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487], + woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872], + washingtonStreetId = 'w522', + twelfthAvenueId = 'w1', + eleventhAvenueEndId = 'n3550', + twelfthAvenueEndId = 'n5', + washingtonSegmentId = null, + eleventhAvenueEnd = context.entity(eleventhAvenueEndId).loc, + twelfthAvenueEnd = context.entity(twelfthAvenueEndId).loc, + deleteLinesLoc = [-85.6219395542764, 41.95228033922477], + twelfthAvenue = [-85.62219310052491, 41.952505413152956]; + + + var chapter = { + title: 'intro.lines.title' + }; - function revealHouse(center, text, options) { - var padding = 160 * Math.pow(2, context.map().zoom() - 20); - var box = pad$1(center, padding, context); - reveal(box, text, options); - } + function timeout(f, t$$1) { + timeouts.push(window.setTimeout(f, t$$1)); + } - function revealTank(center, text, options) { - var padding = 190 * Math.pow(2, context.map().zoom() - 19.5); - var box = pad$1(center, padding, context); - reveal(box, text, options); - } + function eventCancel() { + event.stopPropagation(); + event.preventDefault(); + } - function revealEditMenu(loc, text, options) { - var rect = context.surfaceRect(); - var point$$1 = context.curtainProjection(loc); - var pad = 40; - var width = 250 + (2 * pad); - var height = 350; - var startX = rect.left + point$$1[0]; - var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad); - var box = { - left: left, - top: point$$1[1] + rect.top - 60, - width: width, - height: height - }; - reveal(box, text, options); - } + function revealEditMenu(loc, text, options) { + var rect = context.surfaceRect(); + var point$$1 = context.curtainProjection(loc); + var pad = 40; + var width = 250 + (2 * pad); + var height = 350; + var startX = rect.left + point$$1[0]; + var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad); + var box = { + left: left, + top: point$$1[1] + rect.top - 60, + width: width, + height: height + }; + reveal(box, text, options); + } - function addHouse() { - context.enter(modeBrowse(context)); - context.history().reset('initial'); - houseId = null; + function addLine() { + context.enter(modeBrowse(context)); + context.history().reset('initial'); - var msec = transitionTime(house, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(19).centerEase(house, msec); + var msec = transitionTime(tulipRoadStart, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(18.5).centerEase(tulipRoadStart, msec); - timeout(function() { - var tooltip = reveal('button.add-area', - t('intro.buildings.add_building', { button: icon('#icon-area', 'pre-text') })); + timeout(function() { + var tooltip = reveal('button.add-line', + t('intro.lines.add_line', { button: icon('#icon-line', 'pre-text') })); - tooltip.selectAll('.tooltip-inner') - .insert('svg', 'span') - .attr('class', 'tooltip-illustration') - .append('use') - .attr('xlink:href', '#building-images'); + tooltip.selectAll('.tooltip-inner') + .insert('svg', 'span') + .attr('class', 'tooltip-illustration') + .append('use') + .attr('xlink:href', '#feature-images'); - context.on('enter.intro', function(mode) { - if (mode.id !== 'add-area') return; - continueTo(startHouse); - }); - }, msec + 100); + context.on('enter.intro', function(mode) { + if (mode.id !== 'add-line') return; + continueTo(startLine); + }); + }, msec + 100); - function continueTo(nextStep) { - context.on('enter.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + context.on('enter.intro', null); + nextStep(); + } + } - function startHouse() { - if (context.mode().id !== 'add-area') { - return continueTo(addHouse); - } + function startLine() { + if (context.mode().id !== 'add-line') { + return chapter.restart(); + } - houseId = null; - context.map().zoomEase(20, 500); + tulipRoadId = null; - timeout(function() { - revealHouse(house, t('intro.buildings.start_building')); + var padding = 70 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(tulipRoadStart, padding, context); + box.height = box.height + 100; + reveal(box, t('intro.lines.start_line')); - context.map().on('move.intro drawn.intro', function() { - revealHouse(house, t('intro.buildings.start_building'), { duration: 0 }); - }); + context.map().on('move.intro drawn.intro', function() { + padding = 70 * Math.pow(2, context.map().zoom() - 18); + box = pad$1(tulipRoadStart, padding, context); + box.height = box.height + 100; + reveal(box, t('intro.lines.start_line'), { duration: 0 }); + }); - context.on('enter.intro', function(mode) { - if (mode.id !== 'draw-area') return chapter.restart(); - continueTo(continueHouse); - }); + context.on('enter.intro', function(mode) { + if (mode.id !== 'draw-line') return chapter.restart(); + continueTo(drawLine); + }); - }, 550); // after easing + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + function drawLine() { + if (context.mode().id !== 'draw-line') { + return chapter.restart(); + } - function continueHouse() { - if (context.mode().id !== 'draw-area') { - return continueTo(addHouse); - } + tulipRoadId = context.mode().selectedIDs()[0]; + context.map().centerEase(tulipRoadMidpoint, 500); + + timeout(function() { + var padding = 200 * Math.pow(2, context.map().zoom() - 18.5); + var box = pad$1(tulipRoadMidpoint, padding, context); + box.height = box.height * 2; + reveal(box, + t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }) + ); + + context.map().on('move.intro drawn.intro', function() { + padding = 200 * Math.pow(2, context.map().zoom() - 18.5); + box = pad$1(tulipRoadMidpoint, padding, context); + box.height = box.height * 2; + reveal(box, + t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }), + { duration: 0 } + ); + }); + }, 550); // after easing.. + + context.history().on('change.intro', function() { + var entity = tulipRoadId && context.hasEntity(tulipRoadId); + if (!entity) return chapter.restart(); + + if (isLineConnected()) { + continueTo(continueLine); + } + }); - houseId = null; + context.on('enter.intro', function(mode) { + if (mode.id === 'draw-line') + return; + else if (mode.id === 'select') { + continueTo(retryIntersect); + return; + } + else + return chapter.restart(); + }); - revealHouse(house, t('intro.buildings.continue_building')); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - context.map().on('move.intro drawn.intro', function() { - revealHouse(house, t('intro.buildings.continue_building'), { duration: 0 }); - }); - context.on('enter.intro', function(mode) { - if (mode.id === 'draw-area') { - return; - } else if (mode.id === 'select') { - var graph = context.graph(), - way = context.entity(context.selectedIDs()[0]), - nodes = graph.childNodes(way), - points = uniq(nodes).map(function(n) { return context.projection(n.loc); }); - - if (isMostlySquare(points)) { - houseId = way.id; - return continueTo(chooseCategoryBuilding); - } else { - return continueTo(retryHouse); - } + function isLineConnected() { + var entity = tulipRoadId && context.hasEntity(tulipRoadId); + if (!entity) return false; - } else { - return chapter.restart(); - } - }); + var drawNodes = context.graph().childNodes(entity); + return some(drawNodes, function(node) { + return some(context.graph().parentWays(node), function(parent) { + return parent.id === flowerRoadId; + }); + }); + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + function retryIntersect() { + select(window).on('mousedown.intro', eventCancel, true); - function retryHouse() { - var onClick = function() { continueTo(addHouse); }; + var box = pad$1(tulipRoadIntersection, 80, context); + reveal(box, + t('intro.lines.retry_intersect', { name: t('intro.graph.name.flower-street') }) + ); - revealHouse(house, t('intro.buildings.retry_building'), - { buttonText: t('intro.ok'), buttonCallback: onClick } - ); + timeout(chapter.restart, 3000); + } - context.map().on('move.intro drawn.intro', function() { - revealHouse(house, t('intro.buildings.retry_building'), - { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } - ); - }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - nextStep(); - } - } + function continueLine() { + if (context.mode().id !== 'draw-line') return chapter.restart(); + var entity = tulipRoadId && context.hasEntity(tulipRoadId); + if (!entity) return chapter.restart(); + context.map().centerEase(tulipRoadIntersection, 500); - function chooseCategoryBuilding() { - if (!houseId || !context.hasEntity(houseId)) { - return addHouse(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) { - context.enter(modeSelect(context, [houseId])); - } + reveal('#surface', t('intro.lines.continue_line')); - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + context.on('enter.intro', function(mode) { + if (mode.id === 'draw-line') + return; + else if (mode.id === 'select') + return continueTo(chooseCategoryRoad); + else + return chapter.restart(); + }); - timeout(function() { - // reset pane, in case user somehow happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '-100%'); + function continueTo(nextStep) { + context.on('enter.intro', null); + nextStep(); + } + } - var button = d3_select('.preset-category-building .preset-list-button'); - reveal(button.node(), - t('intro.buildings.choose_category_building', { category: buildingCatetory.name() }) - ); + function chooseCategoryRoad() { + if (context.mode().id !== 'select') { + return chapter.restart(); + } - button.on('click.intro', function() { - button.on('click.intro', null); - continueTo(choosePresetHouse); - }); + context.on('exit.intro', function() { + return chapter.restart(); + }); - }, 400); // after preset list pane visible.. + var button = select('.preset-category-road .preset-list-button'); + if (button.empty()) return chapter.restart(); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - context.on('enter.intro', function(mode) { - if (!houseId || !context.hasEntity(houseId)) { - return continueTo(addHouse); - } - var ids = context.selectedIDs(); - if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) { - return continueTo(chooseCategoryBuilding); - } - }); + timeout(function() { + // reset pane, in case user somehow happened to change it.. + select('.inspector-wrap .panewrap').style('right', '-100%'); - function continueTo(nextStep) { - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.preset-list-button').on('click.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + reveal(button.node(), + t('intro.lines.choose_category_road', { category: roadCategory.name() }) + ); + button.on('click.intro', function() { + continueTo(choosePresetResidential); + }); - function choosePresetHouse() { - if (!houseId || !context.hasEntity(houseId)) { - return addHouse(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) { - context.enter(modeSelect(context, [houseId])); - } + }, 400); // after editor pane visible - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + function continueTo(nextStep) { + select('.inspector-wrap').on('wheel.intro', null); + select('.preset-list-button').on('click.intro', null); + context.on('exit.intro', null); + nextStep(); + } + } - timeout(function() { - // reset pane, in case user somehow happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '-100%'); - var button = d3_select('.preset-building-house .preset-list-button'); + function choosePresetResidential() { + if (context.mode().id !== 'select') { + return chapter.restart(); + } - reveal(button.node(), - t('intro.buildings.choose_preset_house', { preset: housePreset.name() }), - { duration: 300 } - ); + context.on('exit.intro', function() { + return chapter.restart(); + }); - button.on('click.intro', function() { - button.on('click.intro', null); - continueTo(closeEditorHouse); - }); + var subgrid = select('.preset-category-road .subgrid'); + if (subgrid.empty()) return chapter.restart(); + + subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button') + .on('click.intro', function() { + continueTo(retryPresetResidential); + }); + + subgrid.selectAll('.preset-highway-residential .preset-list-button') + .on('click.intro', function() { + continueTo(nameRoad); + }); + + timeout(function() { + reveal(subgrid.node(), + t('intro.lines.choose_preset_residential', { preset: residentialPreset.name() }), + { tooltipBox: '.preset-highway-residential .preset-list-button', duration: 300 } + ); + }, 300); + + function continueTo(nextStep) { + select('.preset-list-button').on('click.intro', null); + context.on('exit.intro', null); + nextStep(); + } + } - }, 400); // after preset list pane visible.. + // selected wrong road type + function retryPresetResidential() { + if (context.mode().id !== 'select') { + return chapter.restart(); + } - context.on('enter.intro', function(mode) { - if (!houseId || !context.hasEntity(houseId)) { - return continueTo(addHouse); - } - var ids = context.selectedIDs(); - if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) { - return continueTo(chooseCategoryBuilding); - } - }); + context.on('exit.intro', function() { + return chapter.restart(); + }); - function continueTo(nextStep) { - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.preset-list-button').on('click.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); + timeout(function() { + var button = select('.entity-editor-pane .preset-list-button'); - function closeEditorHouse() { - if (!houseId || !context.hasEntity(houseId)) { - return addHouse(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) { - context.enter(modeSelect(context, [houseId])); - } + reveal(button.node(), + t('intro.lines.retry_preset_residential', { preset: residentialPreset.name() }) + ); - context.history().checkpoint('hasHouse'); + button.on('click.intro', function() { + continueTo(chooseCategoryRoad); + }); - context.on('exit.intro', function() { - continueTo(rightClickHouse); - }); + }, 500); - timeout(function() { - reveal('.entity-editor-pane', - t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') }) - ); - }, 500); + function continueTo(nextStep) { + select('.inspector-wrap').on('wheel.intro', null); + select('.preset-list-button').on('click.intro', null); + context.on('exit.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - context.on('exit.intro', null); - nextStep(); - } - } + function nameRoad() { + context.on('exit.intro', function() { + continueTo(didNameRoad); + }); - function rightClickHouse() { - if (!houseId) return chapter.restart(); + timeout(function() { + reveal('.entity-editor-pane', + t('intro.lines.name_road', { button: icon('#icon-apply', 'pre-text') }), + { tooltipClass: 'intro-lines-name_road' } + ); + }, 500); - context.enter(modeBrowse(context)); - context.history().reset('hasHouse'); - context.map().centerEase(house, 500); + function continueTo(nextStep) { + context.on('exit.intro', null); + nextStep(); + } + } - timeout(function() { - if (context.map().zoom() < 20) { - context.map().zoomEase(20, 500); - } - }, 520); - - context.on('enter.intro', function(mode) { - if (mode.id !== 'select') return; - var ids = context.selectedIDs(); - if (ids.length !== 1 || ids[0] !== houseId) return; - - timeout(function() { - var node = selectMenuItem('orthogonalize').node(); - if (!node) return; - continueTo(clickSquare); - }, 300); // after menu visible - }); - context.map().on('move.intro drawn.intro', function() { - revealHouse(house, t('intro.buildings.rightclick_building'), { duration: 0 }); - }); + function didNameRoad() { + context.history().checkpoint('doneAddLine'); - context.history().on('change.intro', function() { - continueTo(rightClickHouse); - }); + timeout(function() { + reveal('#surface', t('intro.lines.did_name_road'), { + buttonText: t('intro.ok'), + buttonCallback: function() { continueTo(updateLine); } + }); + }, 500); - function continueTo(nextStep) { - context.on('enter.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + nextStep(); + } + } - function clickSquare() { - if (!houseId) return chapter.restart(); - var entity = context.hasEntity(houseId); - if (!entity) return continueTo(rightClickHouse); + function updateLine() { + context.history().reset('doneAddLine'); + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return chapter.restart(); + } - var node = selectMenuItem('orthogonalize').node(); - if (!node) { return continueTo(rightClickHouse); } + var msec = transitionTime(woodRoadDragMidpoint, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(19).centerEase(woodRoadDragMidpoint, msec); + + timeout(function() { + var padding = 250 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragMidpoint, padding, context); + var advance = function() { continueTo(addNode); }; + + reveal(box, t('intro.lines.update_line'), + { buttonText: t('intro.ok'), buttonCallback: advance } + ); + + context.map().on('move.intro drawn.intro', function() { + var padding = 250 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragMidpoint, padding, context); + reveal(box, t('intro.lines.update_line'), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance } + ); + }); + }, msec + 100); + + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + nextStep(); + } + } - var wasChanged = false; - var menuCoords = context.map().mouseCoordinates(); - revealEditMenu(menuCoords, - t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') }) - ); + function addNode() { + context.history().reset('doneAddLine'); + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return chapter.restart(); + } - context.on('enter.intro', function(mode) { - if (mode.id === 'browse') { - continueTo(rightClickHouse); - } else if (mode.id === 'move' || mode.id === 'rotate') { - continueTo(retryClickSquare); - } - }); + var padding = 40 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadAddNode, padding, context); + reveal(box, t('intro.lines.add_node')); - context.map().on('move.intro drawn.intro', function() { - var node = selectMenuItem('orthogonalize').node(); - if (!wasChanged && !node) { return continueTo(rightClickHouse); } + context.map().on('move.intro drawn.intro', function() { + var padding = 40 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadAddNode, padding, context); + reveal(box, t('intro.lines.add_node'), { duration: 0 }); + }); - revealEditMenu(menuCoords, - t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') }), - { duration: 0 } - ); - }); + context.history().on('change.intro', function(changed) { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } + if (changed.created().length === 1) { + timeout(function() { continueTo(startDragEndpoint); }, 500); + } + }); - context.history().on('change.intro', function() { - wasChanged = true; - context.history().on('change.intro', null); - - // Something changed. Wait for transition to complete and check undo annotation. - timeout(function() { - if (context.history().undoAnnotation() === t('operations.orthogonalize.annotation.area')) { - continueTo(doneSquare); - } else { - continueTo(retryClickSquare); - } - }, 500); // after transitioned actions - }); + context.on('enter.intro', function(mode) { + if (mode.id !== 'select') { + continueTo(updateLine); + } + }); - function continueTo(nextStep) { - context.on('enter.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - function retryClickSquare() { - context.enter(modeBrowse(context)); + function startDragEndpoint() { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } + var padding = 100 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragEndpoint, padding, context); + reveal(box, t('intro.lines.start_drag_endpoint')); + + context.map().on('move.intro drawn.intro', function() { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } + var padding = 100 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragEndpoint, padding, context); + reveal(box, t('intro.lines.start_drag_endpoint'), { duration: 0 }); + + var entity = context.entity(woodRoadEndId); + if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) { + continueTo(finishDragEndpoint); + } + }); - revealHouse(house, t('intro.buildings.retry_square'), { - buttonText: t('intro.ok'), - buttonCallback: function() { continueTo(rightClickHouse); } - }); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - nextStep(); - } - } + function finishDragEndpoint() { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } - function doneSquare() { - context.history().checkpoint('doneSquare'); + var padding = 100 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragEndpoint, padding, context); + reveal(box, t('intro.lines.finish_drag_endpoint')); + + context.map().on('move.intro drawn.intro', function() { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } + var padding = 100 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragEndpoint, padding, context); + reveal(box, t('intro.lines.finish_drag_endpoint'), { duration: 0 }); + + var entity = context.entity(woodRoadEndId); + if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) { + continueTo(startDragEndpoint); + } + }); - revealHouse(house, t('intro.buildings.done_square'), { - buttonText: t('intro.ok'), - buttonCallback: function() { continueTo(addTank); } - }); + context.on('enter.intro', function() { + continueTo(startDragMidpoint); + }); - function continueTo(nextStep) { - nextStep(); - } - } + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - function addTank() { - context.enter(modeBrowse(context)); - context.history().reset('doneSquare'); - tankId = null; + function startDragMidpoint() { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } + if (context.selectedIDs().indexOf(woodRoadId) === -1) { + context.enter(modeSelect(context, [woodRoadId])); + } - var msec = transitionTime(tank, context.map().center()); - if (msec) { reveal(null, null, { duration: 0 }); } - context.map().zoom(19.5).centerEase(tank, msec); + var padding = 80 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragMidpoint, padding, context); + reveal(box, t('intro.lines.start_drag_midpoint')); + + context.map().on('move.intro drawn.intro', function() { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } + var padding = 80 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragMidpoint, padding, context); + reveal(box, t('intro.lines.start_drag_midpoint'), { duration: 0 }); + }); - timeout(function() { - reveal('button.add-area', - t('intro.buildings.add_tank', { button: icon('#icon-area', 'pre-text') }) - ); + context.history().on('change.intro', function(changed) { + if (changed.created().length === 1) { + continueTo(continueDragMidpoint); + } + }); - context.on('enter.intro', function(mode) { - if (mode.id !== 'add-area') return; - continueTo(startTank); - }); - }, msec + 100); + context.on('enter.intro', function(mode) { + if (mode.id !== 'select') { + // keep Wood Road selected so midpoint triangles are drawn.. + context.enter(modeSelect(context, [woodRoadId])); + } + }); - function continueTo(nextStep) { - context.on('enter.intro', null); - nextStep(); - } - } + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - function startTank() { - if (context.mode().id !== 'add-area') { - return continueTo(addTank); - } + function continueDragMidpoint() { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } - tankId = null; + var padding = 100 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragEndpoint, padding, context); + box.height += 400; - timeout(function() { - revealTank(tank, t('intro.buildings.start_tank')); + var advance = function() { + context.history().checkpoint('doneUpdateLine'); + continueTo(deleteLines); + }; - context.map().on('move.intro drawn.intro', function() { - revealTank(tank, t('intro.buildings.start_tank'), { duration: 0 }); - }); + reveal(box, t('intro.lines.continue_drag_midpoint'), + { buttonText: t('intro.ok'), buttonCallback: advance } + ); - context.on('enter.intro', function(mode) { - if (mode.id !== 'draw-area') return chapter.restart(); - continueTo(continueTank); - }); + context.map().on('move.intro drawn.intro', function() { + if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) { + return continueTo(updateLine); + } + var padding = 100 * Math.pow(2, context.map().zoom() - 19); + var box = pad$1(woodRoadDragEndpoint, padding, context); + box.height += 400; + reveal(box, t('intro.lines.continue_drag_midpoint'), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance } + ); + }); - }, 550); // after easing + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + nextStep(); + } + } - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + function deleteLines() { + context.history().reset('doneUpdateLine'); + context.enter(modeBrowse(context)); - function continueTank() { - if (context.mode().id !== 'draw-area') { - return continueTo(addTank); - } + if (!context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return chapter.restart(); + } - tankId = null; + var msec = transitionTime(deleteLinesLoc, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(18).centerEase(deleteLinesLoc, msec); + + timeout(function() { + var padding = 200 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(deleteLinesLoc, padding, context); + box.top -= 200; + box.height += 400; + var advance = function() { continueTo(rightClickIntersection); }; + + reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }), + { buttonText: t('intro.ok'), buttonCallback: advance } + ); + + context.map().on('move.intro drawn.intro', function() { + var padding = 200 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(deleteLinesLoc, padding, context); + box.top -= 200; + box.height += 400; + reveal(box, t('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance } + ); + }); + + context.history().on('change.intro', function() { + timeout(function() { + continueTo(deleteLines); + }, 500); // after any transition (e.g. if user deleted intersection) + }); + + }, msec + 100); + + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - revealTank(tank, t('intro.buildings.continue_tank')); - context.map().on('move.intro drawn.intro', function() { - revealTank(tank, t('intro.buildings.continue_tank'), { duration: 0 }); - }); + function rightClickIntersection() { + context.history().reset('doneUpdateLine'); + context.enter(modeBrowse(context)); + + context.map().zoom(18).centerEase(eleventhAvenueEnd, 500); + + timeout(function() { + var padding = 60 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(eleventhAvenueEnd, padding, context); + reveal(box, t('intro.lines.rightclick_intersection', + { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') }) + ); + + context.map().on('move.intro drawn.intro', function() { + var padding = 60 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(eleventhAvenueEnd, padding, context); + reveal(box, t('intro.lines.rightclick_intersection', + { street1: t('intro.graph.name.11th-avenue'), street2: t('intro.graph.name.washington-street') }), + { duration: 0 } + ); + }); + + context.on('enter.intro', function(mode) { + if (mode.id !== 'select') return; + var ids = context.selectedIDs(); + if (ids.length !== 1 || ids[0] !== eleventhAvenueEndId) return; + + timeout(function() { + var node = selectMenuItem('split').node(); + if (!node) return; + continueTo(splitIntersection); + }, 300); // after menu visible + }); + + context.history().on('change.intro', function() { + timeout(function() { + continueTo(deleteLines); + }, 300); // after any transition (e.g. if user deleted intersection) + }); + + }, 600); + + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - context.on('enter.intro', function(mode) { - if (mode.id === 'draw-area') { - return; - } else if (mode.id === 'select') { - tankId = context.selectedIDs()[0]; - return continueTo(searchPresetTank); - } else { - return continueTo(addTank); - } - }); - function continueTo(nextStep) { - context.map().on('move.intro drawn.intro', null); - context.on('enter.intro', null); - nextStep(); - } - } + function splitIntersection() { + if (!context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return continueTo(deleteLines); + } + var node = selectMenuItem('split').node(); + if (!node) { return continueTo(rightClickIntersection); } - function searchPresetTank() { - if (!tankId || !context.hasEntity(tankId)) { - return addTank(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) { - context.enter(modeSelect(context, [tankId])); - } + var wasChanged = false; + var menuCoords = context.map().mouseCoordinates(); + washingtonSegmentId = null; - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + revealEditMenu(menuCoords, t('intro.lines.split_intersection', + { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') }) + ); - timeout(function() { - // reset pane, in case user somehow happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '-100%'); + context.map().on('move.intro drawn.intro', function() { + var node = selectMenuItem('split').node(); + if (!wasChanged && !node) { return continueTo(rightClickIntersection); } - d3_select('.preset-search-input') - .on('keydown.intro', null) - .on('keyup.intro', checkPresetSearch); + revealEditMenu(menuCoords, t('intro.lines.split_intersection', + { button: icon('#operation-split', 'pre-text'), street: t('intro.graph.name.washington-street') }), + { duration: 0 } + ); + }); - reveal('.preset-search-input', - t('intro.buildings.search_tank', { preset: tankPreset.name() }) - ); - }, 400); // after preset list pane visible.. + context.history().on('change.intro', function(changed) { + wasChanged = true; + timeout(function() { + if (context.history().undoAnnotation() === t('operations.split.annotation.line')) { + washingtonSegmentId = changed.created()[0].id; + continueTo(didSplit); + } else { + washingtonSegmentId = null; + continueTo(retrySplit); + } + }, 300); // after any transition (e.g. if user deleted intersection) + }); - context.on('enter.intro', function(mode) { - if (!tankId || !context.hasEntity(tankId)) { - return continueTo(addTank); - } + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - var ids = context.selectedIDs(); - if (mode.id !== 'select' || !ids.length || ids[0] !== tankId) { - // keep the user's area selected.. - context.enter(modeSelect(context, [tankId])); - // reset pane, in case user somehow happened to change it.. - d3_select('.inspector-wrap .panewrap').style('right', '-100%'); - // disallow scrolling - d3_select('.inspector-wrap').on('wheel.intro', eventCancel); + function retrySplit() { + context.enter(modeBrowse(context)); + context.map().zoom(18).centerEase(eleventhAvenueEnd, 500); + var advance = function() { continueTo(rightClickIntersection); }; - d3_select('.preset-search-input') - .on('keydown.intro', null) - .on('keyup.intro', checkPresetSearch); + var padding = 60 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(eleventhAvenueEnd, padding, context); + reveal(box, t('intro.lines.retry_split'), + { buttonText: t('intro.ok'), buttonCallback: advance } + ); - reveal('.preset-search-input', - t('intro.buildings.search_tank', { preset: tankPreset.name() }) - ); + context.map().on('move.intro drawn.intro', function() { + var padding = 60 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(eleventhAvenueEnd, padding, context); + reveal(box, t('intro.lines.retry_split'), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: advance } + ); + }); - context.history().on('change.intro', null); - } - }); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + nextStep(); + } + } - function checkPresetSearch() { - var first = d3_select('.preset-list-item:first-child'); - if (first.classed('preset-man_made-storage_tank')) { - reveal(first.select('.preset-list-button').node(), - t('intro.buildings.choose_tank', { preset: tankPreset.name() }), - { duration: 300 } - ); + function didSplit() { + if (!washingtonSegmentId || + !context.hasEntity(washingtonSegmentId) || + !context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return continueTo(rightClickIntersection); + } - d3_select('.preset-search-input') - .on('keydown.intro', eventCancel, true) - .on('keyup.intro', null); + var ids = context.selectedIDs(); + var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single'); + var street = t('intro.graph.name.washington-street'); - context.history().on('change.intro', function() { - continueTo(closeEditorTank); - }); - } - } + var padding = 200 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(twelfthAvenue, padding, context); + box.width = box.width / 2; + reveal(box, t(string, { street1: street, street2: street }), + { duration: 500 } + ); - function continueTo(nextStep) { - d3_select('.inspector-wrap').on('wheel.intro', null); - context.on('enter.intro', null); - context.history().on('change.intro', null); - d3_select('.preset-search-input').on('keydown.intro keyup.intro', null); - nextStep(); - } - } + timeout(function() { + context.map().zoom(18).centerEase(twelfthAvenue, 500); + + context.map().on('move.intro drawn.intro', function() { + var padding = 200 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(twelfthAvenue, padding, context); + box.width = box.width / 2; + reveal(box, t(string, { street1: street, street2: street }), + { duration: 0 } + ); + }); + }, 600); // after initial reveal and curtain cut + + context.on('enter.intro', function() { + var ids = context.selectedIDs(); + if (ids.length === 1 && ids[0] === washingtonSegmentId) { + continueTo(multiSelect); + } + }); + context.history().on('change.intro', function() { + if (!washingtonSegmentId || + !context.hasEntity(washingtonSegmentId) || + !context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return continueTo(rightClickIntersection); + } + }); - function closeEditorTank() { - if (!tankId || !context.hasEntity(tankId)) { - return addTank(); - } - var ids = context.selectedIDs(); - if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) { - context.enter(modeSelect(context, [tankId])); - } + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - context.history().checkpoint('hasTank'); - context.on('exit.intro', function() { - continueTo(rightClickTank); - }); + function multiSelect() { + if (!washingtonSegmentId || + !context.hasEntity(washingtonSegmentId) || + !context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return continueTo(rightClickIntersection); + } - timeout(function() { - reveal('.entity-editor-pane', - t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') }) - ); - }, 500); + var ids = context.selectedIDs(); + var hasWashington = ids.indexOf(washingtonSegmentId) !== -1; + var hasTwelfth = ids.indexOf(twelfthAvenueId) !== -1; - function continueTo(nextStep) { - context.on('exit.intro', null); - nextStep(); - } - } + if (hasWashington && hasTwelfth) { + return continueTo(multiRightClick); + } else if (!hasWashington && !hasTwelfth) { + return continueTo(didSplit); + } + context.map().zoom(18).centerEase(twelfthAvenue, 500); + + timeout(function() { + var selected, other, padding, box; + if (hasWashington) { + selected = t('intro.graph.name.washington-street'); + other = t('intro.graph.name.12th-avenue'); + padding = 60 * Math.pow(2, context.map().zoom() - 18); + box = pad$1(twelfthAvenueEnd, padding, context); + box.width *= 3; + } else { + selected = t('intro.graph.name.12th-avenue'); + other = t('intro.graph.name.washington-street'); + padding = 200 * Math.pow(2, context.map().zoom() - 18); + box = pad$1(twelfthAvenue, padding, context); + box.width /= 2; + } + + reveal(box, + t('intro.lines.multi_select', { selected: selected, other1: other, other2: other }) + ); + + context.map().on('move.intro drawn.intro', function() { + if (hasWashington) { + selected = t('intro.graph.name.washington-street'); + other = t('intro.graph.name.12th-avenue'); + padding = 60 * Math.pow(2, context.map().zoom() - 18); + box = pad$1(twelfthAvenueEnd, padding, context); + box.width *= 3; + } else { + selected = t('intro.graph.name.12th-avenue'); + other = t('intro.graph.name.washington-street'); + padding = 200 * Math.pow(2, context.map().zoom() - 18); + box = pad$1(twelfthAvenue, padding, context); + box.width /= 2; + } + + reveal(box, + t('intro.lines.multi_select', { selected: selected, other1: other, other2: other }), + { duration: 0 } + ); + }); + + context.on('enter.intro', function() { + continueTo(multiSelect); + }); + + context.history().on('change.intro', function() { + if (!washingtonSegmentId || + !context.hasEntity(washingtonSegmentId) || + !context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return continueTo(rightClickIntersection); + } + }); + }, 600); + + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - function rightClickTank() { - if (!tankId) return continueTo(addTank); - context.enter(modeBrowse(context)); - context.history().reset('hasTank'); - context.map().centerEase(tank, 500); + function multiRightClick() { + if (!washingtonSegmentId || + !context.hasEntity(washingtonSegmentId) || + !context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return continueTo(rightClickIntersection); + } - timeout(function() { - context.on('enter.intro', function(mode) { - if (mode.id !== 'select') return; - var ids = context.selectedIDs(); - if (ids.length !== 1 || ids[0] !== tankId) return; + var padding = 200 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(twelfthAvenue, padding, context); + reveal(box, t('intro.lines.multi_rightclick')); - timeout(function() { - var node = selectMenuItem('circularize').node(); - if (!node) return; - continueTo(clickCircle); - }, 300); // after menu visible - }); + context.map().on('move.intro drawn.intro', function() { + var padding = 200 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(twelfthAvenue, padding, context); + reveal(box, t('intro.lines.multi_rightclick'), { duration: 0 }); + }); - revealTank(tank, t('intro.buildings.rightclick_tank')); + select(window).on('click.intro contextmenu.intro', function() { + timeout(function() { + var ids = context.selectedIDs(); + if (ids.length === 2 && + ids.indexOf(twelfthAvenueId) !== -1 && + ids.indexOf(washingtonSegmentId) !== -1) { + var node = selectMenuItem('delete').node(); + if (!node) return; + continueTo(multiDelete); + } else if (ids.length === 1 && + ids.indexOf(washingtonSegmentId) !== -1) { + return continueTo(multiSelect); + } else { + return continueTo(didSplit); + } + }, 300); // after edit menu visible + }, true); + + context.history().on('change.intro', function() { + if (!washingtonSegmentId || + !context.hasEntity(washingtonSegmentId) || + !context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return continueTo(rightClickIntersection); + } + }); - context.map().on('move.intro drawn.intro', function() { - revealTank(tank, t('intro.buildings.rightclick_tank'), { duration: 0 }); - }); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + select(window).on('click.intro contextmenu.intro', null, true); + context.history().on('change.intro', null); + nextStep(); + } + } - context.history().on('change.intro', function() { - continueTo(rightClickTank); - }); - }, 600); + function multiDelete() { + if (!washingtonSegmentId || + !context.hasEntity(washingtonSegmentId) || + !context.hasEntity(washingtonStreetId) || + !context.hasEntity(twelfthAvenueId) || + !context.hasEntity(eleventhAvenueEndId)) { + return continueTo(rightClickIntersection); + } - function continueTo(nextStep) { - context.on('enter.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + var node = selectMenuItem('delete').node(); + if (!node) return continueTo(multiRightClick); + var menuCoords = context.map().mouseCoordinates(); + revealEditMenu(menuCoords, + t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') }) + ); - function clickCircle() { - if (!tankId) return chapter.restart(); - var entity = context.hasEntity(tankId); - if (!entity) return continueTo(rightClickTank); + context.map().on('move.intro drawn.intro', function() { + revealEditMenu(menuCoords, + t('intro.lines.multi_delete', { button: icon('#operation-delete', 'pre-text') }), + { duration: 0 } + ); + }); - var node = selectMenuItem('circularize').node(); - if (!node) { return continueTo(rightClickTank); } + context.on('exit.intro', function() { + if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) { + return continueTo(multiSelect); // left select mode but roads still exist + } + }); - var wasChanged = false; - var menuCoords = context.map().mouseCoordinates(); + context.history().on('change.intro', function() { + if (context.hasEntity(washingtonSegmentId) || context.hasEntity(twelfthAvenueId)) { + continueTo(retryDelete); // changed something but roads still exist + } else { + continueTo(play); + } + }); - revealEditMenu(menuCoords, - t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') }) - ); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('exit.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - context.on('enter.intro', function(mode) { - if (mode.id === 'browse') { - continueTo(rightClickTank); - } else if (mode.id === 'move' || mode.id === 'rotate') { - continueTo(retryClickCircle); - } - }); - context.map().on('move.intro drawn.intro', function() { - var node = selectMenuItem('circularize').node(); - if (!wasChanged && !node) { return continueTo(rightClickTank); } + function retryDelete() { + context.enter(modeBrowse(context)); - revealEditMenu(menuCoords, - t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') }), - { duration: 0 } - ); - }); + var padding = 200 * Math.pow(2, context.map().zoom() - 18); + var box = pad$1(twelfthAvenue, padding, context); + reveal(box, t('intro.lines.retry_delete'), { + buttonText: t('intro.ok'), + buttonCallback: function() { continueTo(multiSelect); } + }); - context.history().on('change.intro', function() { - wasChanged = true; - context.history().on('change.intro', null); - - // Something changed. Wait for transition to complete and check undo annotation. - timeout(function() { - if (context.history().undoAnnotation() === t('operations.circularize.annotation.area')) { - continueTo(play); - } else { - continueTo(retryClickCircle); - } - }, 500); // after transitioned actions - }); + function continueTo(nextStep) { + nextStep(); + } + } - function continueTo(nextStep) { - context.on('enter.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - nextStep(); - } - } + function play() { + dispatch$$1.call('done'); + reveal('#id-container', + t('intro.lines.play', { next: t('intro.buildings.title') }), { + tooltipBox: '.intro-nav-wrap .chapter-building', + buttonText: t('intro.ok'), + buttonCallback: function() { reveal('#id-container'); } + } + ); + } - function retryClickCircle() { - context.enter(modeBrowse(context)); - revealTank(tank, t('intro.buildings.retry_circle'), { - buttonText: t('intro.ok'), - buttonCallback: function() { continueTo(rightClickTank); } - }); + chapter.enter = function() { + addLine(); + }; - function continueTo(nextStep) { - nextStep(); - } - } + chapter.exit = function() { + timeouts.forEach(window.clearTimeout); + select(window).on('mousedown.intro', null, true); + context.on('enter.intro exit.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', null); + select('.preset-list-button').on('click.intro', null); + }; - function play() { - dispatch$$1.call('done'); - reveal('#id-container', - t('intro.buildings.play', { next: t('intro.startediting.title') }), { - tooltipBox: '.intro-nav-wrap .chapter-startEditing', - buttonText: t('intro.ok'), - buttonCallback: function() { reveal('#id-container'); } - } - ); - } + chapter.restart = function() { + chapter.exit(); + chapter.enter(); + }; - chapter.enter = function() { - addHouse(); - }; + return utilRebind(chapter, dispatch$$1, 'on'); + } - chapter.exit = function() { - timeouts.forEach(window.clearTimeout); - context.on('enter.intro exit.intro', null); - context.map().on('move.intro drawn.intro', null); - context.history().on('change.intro', null); - d3_select('.inspector-wrap').on('wheel.intro', null); - d3_select('.preset-search-input').on('keydown.intro keyup.intro', null); - d3_select('.more-fields .combobox-input').on('click.intro', null); - }; + function uiIntroBuilding(context, reveal) { + var dispatch$$1 = dispatch('done'), + house = [-85.62815, 41.95638], + tank = [-85.62732, 41.95347], + buildingCatetory = context.presets().item('category-building'), + housePreset = context.presets().item('building/house'), + tankPreset = context.presets().item('man_made/storage_tank'), + timeouts = [], + houseId = null, + tankId = null; - chapter.restart = function() { - chapter.exit(); - chapter.enter(); - }; + var chapter = { + title: 'intro.buildings.title' + }; - return utilRebind(chapter, dispatch$$1, 'on'); -} + function timeout(f, t$$1) { + timeouts.push(window.setTimeout(f, t$$1)); + } -function uiModal(selection$$1, blocking) { - var keybinding = d3keybinding('modal'); - var previous = selection$$1.select('div.modal'); - var animate = previous.empty(); - previous.transition() - .duration(200) - .style('opacity', 0) - .remove(); + function eventCancel() { + event.stopPropagation(); + event.preventDefault(); + } - var shaded = selection$$1 - .append('div') - .attr('class', 'shaded') - .style('opacity', 0); - - shaded.close = function() { - shaded - .transition() - .duration(200) - .style('opacity',0) - .remove(); - - modal - .transition() - .duration(200) - .style('top','0px'); - - keybinding.off(); - }; + function revealHouse(center, text, options) { + var padding = 160 * Math.pow(2, context.map().zoom() - 20); + var box = pad$1(center, padding, context); + reveal(box, text, options); + } - var modal = shaded - .append('div') - .attr('class', 'modal fillL col6'); - if (!blocking) { - shaded.on('click.remove-modal', function() { - if (event.target === this) { - shaded.close(); - } - }); + function revealTank(center, text, options) { + var padding = 190 * Math.pow(2, context.map().zoom() - 19.5); + var box = pad$1(center, padding, context); + reveal(box, text, options); + } - modal.append('button') - .attr('class', 'close') - .on('click', shaded.close) - .call(svgIcon('#icon-close')); - keybinding - .on('⌫', shaded.close) - .on('⎋', shaded.close); + function revealEditMenu(loc, text, options) { + var rect = context.surfaceRect(); + var point$$1 = context.curtainProjection(loc); + var pad = 40; + var width = 250 + (2 * pad); + var height = 350; + var startX = rect.left + point$$1[0]; + var left = (textDirection === 'rtl') ? (startX - width + pad) : (startX - pad); + var box = { + left: left, + top: point$$1[1] + rect.top - 60, + width: width, + height: height + }; + reveal(box, text, options); + } - d3_select(document) - .call(keybinding); - } - modal - .append('div') - .attr('class', 'content'); + function addHouse() { + context.enter(modeBrowse(context)); + context.history().reset('initial'); + houseId = null; - if (animate) { - shaded.transition().style('opacity', 1); - } else { - shaded.style('opacity', 1); - } + var msec = transitionTime(house, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(19).centerEase(house, msec); + timeout(function() { + var tooltip = reveal('button.add-area', + t('intro.buildings.add_building', { button: icon('#icon-area', 'pre-text') })); - return shaded; -} + tooltip.selectAll('.tooltip-inner') + .insert('svg', 'span') + .attr('class', 'tooltip-illustration') + .append('use') + .attr('xlink:href', '#building-images'); -function uiIntroStartEditing(context, reveal) { - var dispatch$$1 = dispatch('done', 'startEditing'), - modalSelection = d3_select(null); + context.on('enter.intro', function(mode) { + if (mode.id !== 'add-area') return; + continueTo(startHouse); + }); + }, msec + 100); + function continueTo(nextStep) { + context.on('enter.intro', null); + nextStep(); + } + } - var chapter = { - title: 'intro.startediting.title' - }; - function showHelp() { - reveal('.map-control.help-control', - t('intro.startediting.help', { button: icon('#icon-help', 'pre-text'), key: t('help.key') }), { - buttonText: t('intro.ok'), - buttonCallback: function() { shortcuts(); } - } - ); - } + function startHouse() { + if (context.mode().id !== 'add-area') { + return continueTo(addHouse); + } - function shortcuts() { - reveal('.map-control.help-control', - t('intro.startediting.shortcuts', { key: t('shortcuts.toggle.key') }), { - buttonText: t('intro.ok'), - buttonCallback: function() { showSave(); } - } - ); - } + houseId = null; + context.map().zoomEase(20, 500); - function showSave() { - d3_selectAll('.shaded').remove(); // in case user opened keyboard shortcuts - reveal('#bar button.save', - t('intro.startediting.save'), { - buttonText: t('intro.ok'), - buttonCallback: function() { showStart(); } - } - ); - } + timeout(function() { + revealHouse(house, t('intro.buildings.start_building')); + + context.map().on('move.intro drawn.intro', function() { + revealHouse(house, t('intro.buildings.start_building'), { duration: 0 }); + }); - function showStart() { - d3_selectAll('.shaded').remove(); // in case user opened keyboard shortcuts + context.on('enter.intro', function(mode) { + if (mode.id !== 'draw-area') return chapter.restart(); + continueTo(continueHouse); + }); - modalSelection = uiModal(context.container()); + }, 550); // after easing - modalSelection.select('.modal') - .attr('class', 'modal-splash modal col6'); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - modalSelection.selectAll('.close').remove(); - var startbutton = modalSelection.select('.content') - .attr('class', 'fillL') - .append('button') - .attr('class', 'modal-section huge-modal-button') - .on('click', function() { - modalSelection.remove(); - }); + function continueHouse() { + if (context.mode().id !== 'draw-area') { + return continueTo(addHouse); + } - startbutton - .append('svg') - .attr('class', 'illustration') - .append('use') - .attr('xlink:href', '#logo-walkthrough'); + houseId = null; - startbutton - .append('h2') - .text(t('intro.startediting.start')); + revealHouse(house, t('intro.buildings.continue_building')); - dispatch$$1.call('startEditing'); - } + context.map().on('move.intro drawn.intro', function() { + revealHouse(house, t('intro.buildings.continue_building'), { duration: 0 }); + }); + context.on('enter.intro', function(mode) { + if (mode.id === 'draw-area') { + return; + } else if (mode.id === 'select') { + var graph = context.graph(), + way = context.entity(context.selectedIDs()[0]), + nodes = graph.childNodes(way), + points = uniq(nodes).map(function(n) { return context.projection(n.loc); }); + + if (isMostlySquare(points)) { + houseId = way.id; + return continueTo(chooseCategoryBuilding); + } else { + return continueTo(retryHouse); + } + + } else { + return chapter.restart(); + } + }); - chapter.enter = function() { - showHelp(); - }; + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - chapter.exit = function() { - modalSelection.remove(); - d3_selectAll('.shaded').remove(); // in case user opened keyboard shortcuts - }; + function retryHouse() { + var onClick = function() { continueTo(addHouse); }; + revealHouse(house, t('intro.buildings.retry_building'), + { buttonText: t('intro.ok'), buttonCallback: onClick } + ); - return utilRebind(chapter, dispatch$$1, 'on'); -} - -var chapterUi = { - welcome: uiIntroWelcome, - navigation: uiIntroNavigation, - point: uiIntroPoint, - area: uiIntroArea, - line: uiIntroLine, - building: uiIntroBuilding, - startEditing: uiIntroStartEditing -}; - -var chapterFlow = [ - 'welcome', - 'navigation', - 'point', - 'area', - 'line', - 'building', - 'startEditing' -]; - - -function uiIntro(context) { - var introGraph = {}, - currChapter; - - - // create entities for intro graph and localize names - for (var id in dataIntroGraph) { - introGraph[id] = osmEntity$$1(localize(dataIntroGraph[id])); - } - - - function intro(selection$$1) { - context.enter(modeBrowse(context)); - - // Save current map state - var osm = context.connection(), - history = context.history().toJSON(), - hash = window.location.hash, - center = context.map().center(), - zoom = context.map().zoom(), - background = context.background().baseLayerSource(), - overlays = context.background().overlayLayerSources(), - opacity = d3_selectAll('#map .layer-background').style('opacity'), - loadedTiles = osm && osm.loadedTiles(), - baseEntities = context.history().graph().base().entities, - countryCode = services.geocoder.countryCode; - - // Block saving - context.inIntro(true); - - // Load semi-real data used in intro - if (osm) { osm.toggle(false).reset(); } - context.history().reset(); - context.history().merge(values$1(coreGraph$$1().load(introGraph).entities)); - context.history().checkpoint('initial'); - - var esri = context.background().findSource('EsriWorldImagery'); - if (esri) { - context.background().baseLayerSource(esri); - } else { - context.background().bing(); - } - overlays.forEach(function (d) { - context.background().toggleOverlayLayer(d); - }); + context.map().on('move.intro drawn.intro', function() { + revealHouse(house, t('intro.buildings.retry_building'), + { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } + ); + }); - // Mock geocoder - services.geocoder.countryCode = function(location, callback) { - callback(null, t('intro.graph.countrycode')); - }; + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + nextStep(); + } + } - d3_selectAll('#map .layer-background').style('opacity', 1); - var curtain = uiCurtain(); - selection$$1.call(curtain); + function chooseCategoryBuilding() { + if (!houseId || !context.hasEntity(houseId)) { + return addHouse(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) { + context.enter(modeSelect(context, [houseId])); + } - // store that the user started the walkthrough.. - context.storage('walkthrough_started', 'yes'); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - // restore previous walkthrough progress.. - var storedProgress = context.storage('walkthrough_progress') || ''; - var progress = storedProgress.split(';').filter(Boolean); + timeout(function() { + // reset pane, in case user somehow happened to change it.. + select('.inspector-wrap .panewrap').style('right', '-100%'); - var chapters = chapterFlow.map(function(chapter, i) { - var s = chapterUi[chapter](context, curtain.reveal) - .on('done', function() { - context.presets().init(); // clear away "recent" presets + var button = select('.preset-category-building .preset-list-button'); - buttons.filter(function(d) { - return d.title === s.title; - }).classed('finished', true); + reveal(button.node(), + t('intro.buildings.choose_category_building', { category: buildingCatetory.name() }) + ); - if (i < chapterFlow.length - 1) { - var next = chapterFlow[i + 1]; - d3_select('button.chapter-' + next) - .classed('next', true); - } + button.on('click.intro', function() { + button.on('click.intro', null); + continueTo(choosePresetHouse); + }); - // store walkthrough progress.. - progress.push(chapter); - context.storage('walkthrough_progress', uniq(progress).join(';')); - }); - return s; - }); + }, 400); // after preset list pane visible.. - chapters[chapters.length - 1].on('startEditing', function() { - // store walkthrough progress.. - progress.push('startEditing'); - context.storage('walkthrough_progress', uniq(progress).join(';')); - // store if walkthrough is completed.. - var incomplete = difference(chapterFlow, progress); - if (!incomplete.length) { - context.storage('walkthrough_completed', 'yes'); - } + context.on('enter.intro', function(mode) { + if (!houseId || !context.hasEntity(houseId)) { + return continueTo(addHouse); + } + var ids = context.selectedIDs(); + if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) { + return continueTo(chooseCategoryBuilding); + } + }); - curtain.remove(); - navwrap.remove(); - d3_selectAll('#map .layer-background').style('opacity', opacity); - if (osm) { osm.toggle(true).reset().loadedTiles(loadedTiles); } - context.history().reset().merge(values$1(baseEntities)); - context.background().baseLayerSource(background); - overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); }); - if (history) { context.history().fromJSON(history, false); } - context.map().centerZoom(center, zoom); - window.location.replace(hash); - services.geocoder.countryCode = countryCode; - context.inIntro(false); - }); + function continueTo(nextStep) { + select('.inspector-wrap').on('wheel.intro', null); + select('.preset-list-button').on('click.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - var navwrap = selection$$1 - .append('div') - .attr('class', 'intro-nav-wrap fillD'); - navwrap - .append('svg') - .attr('class', 'intro-nav-wrap-logo') - .append('use') - .attr('xlink:href', '#logo-walkthrough'); + function choosePresetHouse() { + if (!houseId || !context.hasEntity(houseId)) { + return addHouse(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) { + context.enter(modeSelect(context, [houseId])); + } - var buttonwrap = navwrap - .append('div') - .attr('class', 'joined') - .selectAll('button.chapter'); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - var buttons = buttonwrap - .data(chapters) - .enter() - .append('button') - .attr('class', function(d, i) { return 'chapter chapter-' + chapterFlow[i]; }) - .on('click', enterChapter); + timeout(function() { + // reset pane, in case user somehow happened to change it.. + select('.inspector-wrap .panewrap').style('right', '-100%'); - buttons - .append('span') - .text(function(d) { return t(d.title); }); + var button = select('.preset-building-house .preset-list-button'); - buttons - .append('span') - .attr('class', 'status') - .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline')); + reveal(button.node(), + t('intro.buildings.choose_preset_house', { preset: housePreset.name() }), + { duration: 300 } + ); - enterChapter(chapters[0]); + button.on('click.intro', function() { + button.on('click.intro', null); + continueTo(closeEditorHouse); + }); - function enterChapter(newChapter) { - if (currChapter) { currChapter.exit(); } - context.enter(modeBrowse(context)); + }, 400); // after preset list pane visible.. - currChapter = newChapter; - currChapter.enter(); + context.on('enter.intro', function(mode) { + if (!houseId || !context.hasEntity(houseId)) { + return continueTo(addHouse); + } + var ids = context.selectedIDs(); + if (mode.id !== 'select' || !ids.length || ids[0] !== houseId) { + return continueTo(chooseCategoryBuilding); + } + }); - buttons - .classed('next', false) - .classed('active', function(d) { - return d.title === currChapter.title; - }); - } - } + function continueTo(nextStep) { + select('.inspector-wrap').on('wheel.intro', null); + select('.preset-list-button').on('click.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - return intro; -} + function closeEditorHouse() { + if (!houseId || !context.hasEntity(houseId)) { + return addHouse(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== houseId) { + context.enter(modeSelect(context, [houseId])); + } -function uiTooltipHtml(text, key, heading) { - var s = ''; + context.history().checkpoint('hasHouse'); - if (heading) { - s += '
    ' + heading + '
    '; - } - if (text) { - s += '
    ' + text + '
    '; - } - if (key) { - s += '
    ' + t('tooltip_keyhint') + '' + - '' + key + '
    '; - } + context.on('exit.intro', function() { + continueTo(rightClickHouse); + }); - return s; -} + timeout(function() { + reveal('.entity-editor-pane', + t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') }) + ); + }, 500); -function uiMapData(context) { - var key = t('map_data.key'); - var features = context.features().keys(); - var layers = context.layers(); - var fills = ['wireframe', 'partial', 'full']; + function continueTo(nextStep) { + context.on('exit.intro', null); + nextStep(); + } + } - var _fillSelected = context.storage('area-fill') || 'partial'; - var _shown = false; - var _dataLayerContainer = d3_select(null); - var _fillList = d3_select(null); - var _featureList = d3_select(null); + function rightClickHouse() { + if (!houseId) return chapter.restart(); - function showsFeature(d) { - return context.features().enabled(d); - } + context.enter(modeBrowse(context)); + context.history().reset('hasHouse'); + context.map().centerEase(house, 500); + timeout(function() { + if (context.map().zoom() < 20) { + context.map().zoomEase(20, 500); + } + }, 520); - function autoHiddenFeature(d) { - return context.features().autoHidden(d); - } + context.on('enter.intro', function(mode) { + if (mode.id !== 'select') return; + var ids = context.selectedIDs(); + if (ids.length !== 1 || ids[0] !== houseId) return; + timeout(function() { + var node = selectMenuItem('orthogonalize').node(); + if (!node) return; + continueTo(clickSquare); + }, 300); // after menu visible + }); - function clickFeature(d) { - context.features().toggle(d); - update(); - } + context.map().on('move.intro drawn.intro', function() { + revealHouse(house, t('intro.buildings.rightclick_building'), { duration: 0 }); + }); + context.history().on('change.intro', function() { + continueTo(rightClickHouse); + }); - function showsFill(d) { - return _fillSelected === d; - } + function continueTo(nextStep) { + context.on('enter.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - function setFill(d) { - fills.forEach(function(opt) { - context.surface().classed('fill-' + opt, Boolean(opt === d)); - }); + function clickSquare() { + if (!houseId) return chapter.restart(); + var entity = context.hasEntity(houseId); + if (!entity) return continueTo(rightClickHouse); - _fillSelected = d; - context.storage('area-fill', d); - if (d !== 'wireframe') { - context.storage('area-fill-toggle', d); - } - update(); - } + var node = selectMenuItem('orthogonalize').node(); + if (!node) { return continueTo(rightClickHouse); } + var wasChanged = false; + var menuCoords = context.map().mouseCoordinates(); - function showsLayer(which) { - var layer = layers.layer(which); - if (layer) { - return layer.enabled(); - } - return false; - } + revealEditMenu(menuCoords, + t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') }) + ); + context.on('enter.intro', function(mode) { + if (mode.id === 'browse') { + continueTo(rightClickHouse); + } else if (mode.id === 'move' || mode.id === 'rotate') { + continueTo(retryClickSquare); + } + }); - function setLayer(which, enabled) { - var layer = layers.layer(which); - if (layer) { - layer.enabled(enabled); - update(); - } - } + context.map().on('move.intro drawn.intro', function() { + var node = selectMenuItem('orthogonalize').node(); + if (!wasChanged && !node) { return continueTo(rightClickHouse); } + revealEditMenu(menuCoords, + t('intro.buildings.square_building', { button: icon('#operation-orthogonalize', 'pre-text') }), + { duration: 0 } + ); + }); - function toggleLayer(which) { - setLayer(which, !showsLayer(which)); - } + context.history().on('change.intro', function() { + wasChanged = true; + context.history().on('change.intro', null); + + // Something changed. Wait for transition to complete and check undo annotation. + timeout(function() { + if (context.history().undoAnnotation() === t('operations.orthogonalize.annotation.area')) { + continueTo(doneSquare); + } else { + continueTo(retryClickSquare); + } + }, 500); // after transitioned actions + }); + function continueTo(nextStep) { + context.on('enter.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - function drawPhotoItems(selection$$1) { - var photoKeys = ['mapillary-images', 'mapillary-signs', 'openstreetcam-images']; - var photoLayers = layers.all().filter(function(obj) { return photoKeys.indexOf(obj.id) !== -1; }); - var data = photoLayers.filter(function(obj) { return obj.layer.supported(); }); - function layerSupported(d) { - return d.layer && d.layer.supported(); - } - function layerEnabled(d) { - return layerSupported(d) && d.layer.enabled(); - } + function retryClickSquare() { + context.enter(modeBrowse(context)); - var ul = selection$$1 - .selectAll('.layer-list-photos') - .data([0]); - - ul = ul.enter() - .append('ul') - .attr('class', 'layer-list layer-list-photos') - .merge(ul); - - var li = ul.selectAll('.list-item-photos') - .data(data); - - li.exit() - .remove(); - - var liEnter = li.enter() - .append('li') - .attr('class', function(d) { return 'list-item-photos list-item-' + d.id; }); - - var labelEnter = liEnter - .append('label') - .each(function(d) { - d3_select(this) - .call(tooltip() - .title(t(d.id.replace('-', '_') + '.tooltip')) - .placement('top') - ); - }); + revealHouse(house, t('intro.buildings.retry_square'), { + buttonText: t('intro.ok'), + buttonCallback: function() { continueTo(rightClickHouse); } + }); - labelEnter - .append('input') - .attr('type', 'checkbox') - .on('change', function(d) { toggleLayer(d.id); }); + function continueTo(nextStep) { + nextStep(); + } + } - labelEnter - .append('span') - .text(function(d) { return t(d.id.replace('-', '_') + '.title'); }); + function doneSquare() { + context.history().checkpoint('doneSquare'); - // Update - li = li - .merge(liEnter); + revealHouse(house, t('intro.buildings.done_square'), { + buttonText: t('intro.ok'), + buttonCallback: function() { continueTo(addTank); } + }); - li - .classed('active', layerEnabled) - .selectAll('input') - .property('checked', layerEnabled); - } + function continueTo(nextStep) { + nextStep(); + } + } - function drawOsmItem(selection$$1) { - var osm = layers.layer('osm'), - showsOsm = osm.enabled(); + function addTank() { + context.enter(modeBrowse(context)); + context.history().reset('doneSquare'); + tankId = null; - var ul = selection$$1 - .selectAll('.layer-list-osm') - .data(osm ? [0] : []); + var msec = transitionTime(tank, context.map().center()); + if (msec) { reveal(null, null, { duration: 0 }); } + context.map().zoom(19.5).centerEase(tank, msec); - // Exit - ul.exit() - .remove(); + timeout(function() { + reveal('button.add-area', + t('intro.buildings.add_tank', { button: icon('#icon-area', 'pre-text') }) + ); - // Enter - var ulEnter = ul.enter() - .append('ul') - .attr('class', 'layer-list layer-list-osm'); + context.on('enter.intro', function(mode) { + if (mode.id !== 'add-area') return; + continueTo(startTank); + }); + }, msec + 100); - var liEnter = ulEnter - .append('li') - .attr('class', 'list-item-osm'); + function continueTo(nextStep) { + context.on('enter.intro', null); + nextStep(); + } + } - var labelEnter = liEnter - .append('label') - .call(tooltip() - .title(t('map_data.layers.osm.tooltip')) - .placement('top') - ); - labelEnter - .append('input') - .attr('type', 'checkbox') - .on('change', function() { toggleLayer('osm'); }); - - labelEnter - .append('span') - .text(t('map_data.layers.osm.title')); - - // Update - ul = ul - .merge(ulEnter); - - ul.selectAll('.list-item-osm') - .classed('active', showsOsm) - .selectAll('input') - .property('checked', showsOsm); - } - - - function drawGpxItem(selection$$1) { - var gpx = layers.layer('gpx'), - hasGpx = gpx && gpx.hasGpx(), - showsGpx = hasGpx && gpx.enabled(); - - var ul = selection$$1 - .selectAll('.layer-list-gpx') - .data(gpx ? [0] : []); - - // Exit - ul.exit() - .remove(); - - // Enter - var ulEnter = ul.enter() - .append('ul') - .attr('class', 'layer-list layer-list-gpx'); - - var liEnter = ulEnter - .append('li') - .attr('class', 'list-item-gpx'); - - liEnter - .append('button') - .attr('class', 'list-item-gpx-extent') - .call(tooltip() - .title(t('gpx.zoom')) - .placement((textDirection === 'rtl') ? 'right' : 'left') - ) - .on('click', function() { - event.preventDefault(); - event.stopPropagation(); - gpx.fitZoom(); - }) - .call(svgIcon('#icon-search')); - - liEnter - .append('button') - .attr('class', 'list-item-gpx-browse') - .call(tooltip() - .title(t('gpx.browse')) - .placement((textDirection === 'rtl') ? 'right' : 'left') - ) - .on('click', function() { - d3_select(document.createElement('input')) - .attr('type', 'file') - .on('change', function() { - gpx.files(event.target.files); - }) - .node().click(); - }) - .call(svgIcon('#icon-geolocate')); - - var labelEnter = liEnter - .append('label') - .call(tooltip() - .title(t('gpx.drag_drop')) - .placement('top') - ); + function startTank() { + if (context.mode().id !== 'add-area') { + return continueTo(addTank); + } - labelEnter - .append('input') - .attr('type', 'checkbox') - .on('change', function() { toggleLayer('gpx'); }); - - labelEnter - .append('span') - .text(t('gpx.local_layer')); - - // Update - ul = ul - .merge(ulEnter); - - ul.selectAll('.list-item-gpx') - .classed('active', showsGpx) - .selectAll('label') - .classed('deemphasize', !hasGpx) - .selectAll('input') - .property('disabled', !hasGpx) - .property('checked', showsGpx); - } - - - function drawListItems(selection$$1, data, type, name, change, active) { - var items = selection$$1.selectAll('li') - .data(data); - - // Exit - items.exit() - .remove(); - - // Enter - var enter = items.enter() - .append('li') - .attr('class', 'layer') - .call(tooltip() - .html(true) - .title(function(d) { - var tip = t(name + '.' + d + '.tooltip'), - key = (d === 'wireframe' ? t('area_fill.wireframe.key') : null); - - if (name === 'feature' && autoHiddenFeature(d)) { - var msg = showsLayer('osm') ? t('map_data.autohidden') : t('map_data.osmhidden'); - tip += '
    ' + msg + '
    '; - } - return uiTooltipHtml(tip, key); - }) - .placement('top') - ); + tankId = null; - var label = enter - .append('label'); - - label - .append('input') - .attr('type', type) - .attr('name', name) - .on('change', change); - - label - .append('span') - .text(function(d) { return t(name + '.' + d + '.description'); }); - - // Update - items = items - .merge(enter); - - items - .classed('active', active) - .selectAll('input') - .property('checked', active) - .property('indeterminate', function(d) { - return (name === 'feature' && autoHiddenFeature(d)); - }); - } + timeout(function() { + revealTank(tank, t('intro.buildings.start_tank')); + context.map().on('move.intro drawn.intro', function() { + revealTank(tank, t('intro.buildings.start_tank'), { duration: 0 }); + }); - function renderDataLayers(selection$$1) { - var container = selection$$1.selectAll('data-layer-container') - .data([0]); + context.on('enter.intro', function(mode) { + if (mode.id !== 'draw-area') return chapter.restart(); + continueTo(continueTank); + }); - _dataLayerContainer = container.enter() - .append('div') - .attr('class', 'data-layer-container') - .merge(container); - } + }, 550); // after easing + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - function renderFillList(selection$$1) { - var container = selection$$1.selectAll('layer-fill-list') - .data([0]); - _fillList = container.enter() - .append('ul') - .attr('class', 'layer-list layer-fill-list') - .merge(container); - } + function continueTank() { + if (context.mode().id !== 'draw-area') { + return continueTo(addTank); + } + tankId = null; - function renderFeatureList(selection$$1) { - var container = selection$$1.selectAll('layer-feature-list') - .data([0]); + revealTank(tank, t('intro.buildings.continue_tank')); - _featureList = container.enter() - .append('ul') - .attr('class', 'layer-list layer-feature-list') - .merge(container); - } + context.map().on('move.intro drawn.intro', function() { + revealTank(tank, t('intro.buildings.continue_tank'), { duration: 0 }); + }); + context.on('enter.intro', function(mode) { + if (mode.id === 'draw-area') { + return; + } else if (mode.id === 'select') { + tankId = context.selectedIDs()[0]; + return continueTo(searchPresetTank); + } else { + return continueTo(addTank); + } + }); - function update() { - _dataLayerContainer - .call(drawOsmItem) - .call(drawPhotoItems) - .call(drawGpxItem); + function continueTo(nextStep) { + context.map().on('move.intro drawn.intro', null); + context.on('enter.intro', null); + nextStep(); + } + } - _fillList - .call(drawListItems, fills, 'radio', 'area_fill', setFill, showsFill); - _featureList - .call(drawListItems, features, 'checkbox', 'feature', clickFeature, showsFeature); - } + function searchPresetTank() { + if (!tankId || !context.hasEntity(tankId)) { + return addTank(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) { + context.enter(modeSelect(context, [tankId])); + } + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - function toggleWireframe() { - if (event) { - event.preventDefault(); - event.stopPropagation(); - } + timeout(function() { + // reset pane, in case user somehow happened to change it.. + select('.inspector-wrap .panewrap').style('right', '-100%'); - if (_fillSelected === 'wireframe') { - _fillSelected = context.storage('area-fill-toggle') || 'partial'; - } else { - _fillSelected = 'wireframe'; - } + select('.preset-search-input') + .on('keydown.intro', null) + .on('keyup.intro', checkPresetSearch); - setFill(_fillSelected); - context.map().pan([0,0]); // trigger a redraw - } + reveal('.preset-search-input', + t('intro.buildings.search_tank', { preset: tankPreset.name() }) + ); + }, 400); // after preset list pane visible.. + context.on('enter.intro', function(mode) { + if (!tankId || !context.hasEntity(tankId)) { + return continueTo(addTank); + } - function mapData(selection$$1) { + var ids = context.selectedIDs(); + if (mode.id !== 'select' || !ids.length || ids[0] !== tankId) { + // keep the user's area selected.. + context.enter(modeSelect(context, [tankId])); - function hidePane() { - setVisible(false); - } + // reset pane, in case user somehow happened to change it.. + select('.inspector-wrap .panewrap').style('right', '-100%'); + // disallow scrolling + select('.inspector-wrap').on('wheel.intro', eventCancel); - function togglePane() { - if (event) event.preventDefault(); - paneTooltip.hide(button); - setVisible(!button.classed('active')); - } + select('.preset-search-input') + .on('keydown.intro', null) + .on('keyup.intro', checkPresetSearch); - function setVisible(show) { - if (show !== _shown) { - button.classed('active', show); - _shown = show; - - if (show) { - uiBackground.hidePane(); - uiHelp.hidePane(); - update(); - - pane - .style('display', 'block') - .style('right', '-300px') - .transition() - .duration(200) - .style('right', '0px'); - - } else { - pane - .style('display', 'block') - .style('right', '0px') - .transition() - .duration(200) - .style('right', '-300px') - .on('end', function() { - d3_select(this).style('display', 'none'); - }); - } - } - } + reveal('.preset-search-input', + t('intro.buildings.search_tank', { preset: tankPreset.name() }) + ); + context.history().on('change.intro', null); + } + }); - var pane = selection$$1 - .append('div') - .attr('class', 'fillL map-overlay col3 content hide'); + function checkPresetSearch() { + var first = select('.preset-list-item:first-child'); - var paneTooltip = tooltip() - .placement((textDirection === 'rtl') ? 'right' : 'left') - .html(true) - .title(uiTooltipHtml(t('map_data.description'), key)); + if (first.classed('preset-man_made-storage_tank')) { + reveal(first.select('.preset-list-button').node(), + t('intro.buildings.choose_tank', { preset: tankPreset.name() }), + { duration: 300 } + ); - var button = selection$$1 - .append('button') - .attr('tabindex', -1) - .on('click', togglePane) - .call(svgIcon('#icon-data', 'light')) - .call(paneTooltip); + select('.preset-search-input') + .on('keydown.intro', eventCancel, true) + .on('keyup.intro', null); + context.history().on('change.intro', function() { + continueTo(closeEditorTank); + }); + } + } - pane - .append('h2') - .text(t('map_data.title')); + function continueTo(nextStep) { + select('.inspector-wrap').on('wheel.intro', null); + context.on('enter.intro', null); + context.history().on('change.intro', null); + select('.preset-search-input').on('keydown.intro keyup.intro', null); + nextStep(); + } + } - // data layers - pane - .append('div') - .attr('class', 'map-data-data-layers') - .call(uiDisclosure(context, 'data_layers', true) - .title(t('map_data.data_layers')) - .content(renderDataLayers) - ); + function closeEditorTank() { + if (!tankId || !context.hasEntity(tankId)) { + return addTank(); + } + var ids = context.selectedIDs(); + if (context.mode().id !== 'select' || !ids.length || ids[0] !== tankId) { + context.enter(modeSelect(context, [tankId])); + } - // area fills - pane - .append('div') - .attr('class', 'map-data-area-fills') - .call(uiDisclosure(context, 'fill_area', false) - .title(t('map_data.fill_area')) - .content(renderFillList) - ); + context.history().checkpoint('hasTank'); - // feature filters - pane - .append('div') - .attr('class', 'map-data-feature-filters') - .call(uiDisclosure(context, 'map_features', false) - .title(t('map_data.map_features')) - .content(renderFeatureList) - ); + context.on('exit.intro', function() { + continueTo(rightClickTank); + }); + timeout(function() { + reveal('.entity-editor-pane', + t('intro.buildings.close', { button: icon('#icon-apply', 'pre-text') }) + ); + }, 500); - // add listeners - context.features() - .on('change.map_data-update', update); + function continueTo(nextStep) { + context.on('exit.intro', null); + nextStep(); + } + } - update(); - setFill(_fillSelected); - var keybinding = d3keybinding('features') - .on(key, togglePane) - .on(t('area_fill.wireframe.key'), toggleWireframe) - .on([t('background.key'), t('help.key')], hidePane); + function rightClickTank() { + if (!tankId) return continueTo(addTank); - d3_select(document) - .call(keybinding); + context.enter(modeBrowse(context)); + context.history().reset('hasTank'); + context.map().centerEase(tank, 500); - uiMapData.hidePane = hidePane; - uiMapData.togglePane = togglePane; - uiMapData.setVisible = setVisible; - } + timeout(function() { + context.on('enter.intro', function(mode) { + if (mode.id !== 'select') return; + var ids = context.selectedIDs(); + if (ids.length !== 1 || ids[0] !== tankId) return; - return mapData; -} + timeout(function() { + var node = selectMenuItem('circularize').node(); + if (!node) return; + continueTo(clickCircle); + }, 300); // after menu visible + }); -function uiShortcuts() { - var detected = utilDetect(); - var activeTab = 0; - var modalSelection; - var savedSelection; + revealTank(tank, t('intro.buildings.rightclick_tank')); + context.map().on('move.intro drawn.intro', function() { + revealTank(tank, t('intro.buildings.rightclick_tank'), { duration: 0 }); + }); - var keybinding = d3keybinding('shortcuts') - .on(t('shortcuts.toggle.key'), function () { - if (d3_selectAll('.modal-shortcuts').size()) { // already showing - if (modalSelection) { - modalSelection.close(); - modalSelection = null; - } - } else { - modalSelection = uiModal(savedSelection); - shortcutsModal(modalSelection); - } - }); + context.history().on('change.intro', function() { + continueTo(rightClickTank); + }); - d3_select(document) - .call(keybinding); + }, 600); + function continueTo(nextStep) { + context.on('enter.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - function shortcutsModal(modalSelection) { - modalSelection.select('.modal') - .classed('modal-shortcuts', true); + function clickCircle() { + if (!tankId) return chapter.restart(); + var entity = context.hasEntity(tankId); + if (!entity) return continueTo(rightClickTank); - var shortcutsModal = modalSelection.select('.content'); + var node = selectMenuItem('circularize').node(); + if (!node) { return continueTo(rightClickTank); } - shortcutsModal - .append('div') - .attr('class', 'modal-section') - .append('h3') - .text(t('shortcuts.title')); + var wasChanged = false; + var menuCoords = context.map().mouseCoordinates(); - shortcutsModal - .call(render); - } + revealEditMenu(menuCoords, + t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') }) + ); + context.on('enter.intro', function(mode) { + if (mode.id === 'browse') { + continueTo(rightClickTank); + } else if (mode.id === 'move' || mode.id === 'rotate') { + continueTo(retryClickCircle); + } + }); - function render(selection$$1) { - var wrapper = selection$$1 - .selectAll('.wrapper') - .data([0]); + context.map().on('move.intro drawn.intro', function() { + var node = selectMenuItem('circularize').node(); + if (!wasChanged && !node) { return continueTo(rightClickTank); } - var wrapperEnter = wrapper - .enter() - .append('div') - .attr('class', 'wrapper modal-section'); + revealEditMenu(menuCoords, + t('intro.buildings.circle_tank', { button: icon('#operation-circularize', 'pre-text') }), + { duration: 0 } + ); + }); - var tabsBar = wrapperEnter - .append('div') - .attr('class', 'tabs-bar'); + context.history().on('change.intro', function() { + wasChanged = true; + context.history().on('change.intro', null); + + // Something changed. Wait for transition to complete and check undo annotation. + timeout(function() { + if (context.history().undoAnnotation() === t('operations.circularize.annotation.area')) { + continueTo(play); + } else { + continueTo(retryClickCircle); + } + }, 500); // after transitioned actions + }); - var shortcutsList = wrapperEnter - .append('div') - .attr('class', 'shortcuts-list'); + function continueTo(nextStep) { + context.on('enter.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + nextStep(); + } + } - wrapper = wrapper.merge(wrapperEnter); - var tabs = tabsBar - .selectAll('.tab') - .data(dataShortcuts); + function retryClickCircle() { + context.enter(modeBrowse(context)); - var tabsEnter = tabs - .enter() - .append('div') - .attr('class', 'tab') - .on('click', function (d, i) { - activeTab = i; - render(selection$$1); - }); + revealTank(tank, t('intro.buildings.retry_circle'), { + buttonText: t('intro.ok'), + buttonCallback: function() { continueTo(rightClickTank); } + }); - tabsEnter - .append('span') - .text(function (d) { return t(d.text); }); + function continueTo(nextStep) { + nextStep(); + } + } - tabs = tabs - .merge(tabsEnter); - // Update - wrapper.selectAll('.tab') - .classed('active', function (d, i) { - return i === activeTab; - }); + function play() { + dispatch$$1.call('done'); + reveal('#id-container', + t('intro.buildings.play', { next: t('intro.startediting.title') }), { + tooltipBox: '.intro-nav-wrap .chapter-startEditing', + buttonText: t('intro.ok'), + buttonCallback: function() { reveal('#id-container'); } + } + ); + } - var shortcuts = shortcutsList - .selectAll('.shortcut-tab') - .data(dataShortcuts); - - var shortcutsEnter = shortcuts - .enter() - .append('div') - .attr('class', function(d) { return 'shortcut-tab shortcut-tab-' + d.tab; }); - - var columnsEnter = shortcutsEnter - .selectAll('.shortcut-column') - .data(function (d) { return d.columns; }) - .enter() - .append('table') - .attr('class', 'shortcut-column'); - - var rowsEnter = columnsEnter - .selectAll('.shortcut-row') - .data(function (d) { return d.rows; }) - .enter() - .append('tr') - .attr('class', 'shortcut-row'); - - - var sectionRows = rowsEnter - .filter(function (d) { return !d.shortcuts; }); - - sectionRows - .append('td'); - - sectionRows - .append('td') - .attr('class', 'shortcut-section') - .append('h3') - .text(function (d) { return t(d.text); }); - - - var shortcutRows = rowsEnter - .filter(function (d) { return d.shortcuts; }); - - var shortcutKeys = shortcutRows - .append('td') - .attr('class', 'shortcut-keys'); - - var modifierKeys = shortcutKeys - .filter(function (d) { return d.modifiers; }); - - modifierKeys - .selectAll('kbd.modifier') - .data(function (d) { - if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') { - return ['⌘']; - } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') { - return []; - } else { - return d.modifiers; - } - }) - .enter() - .each(function () { - var selection$$1 = d3_select(this); - - selection$$1 - .append('kbd') - .attr('class', 'modifier') - .text(function (d) { return uiCmd.display(d); }); - - selection$$1 - .append('span') - .text('+'); - }); + chapter.enter = function() { + addHouse(); + }; - shortcutKeys - .selectAll('kbd.shortcut') - .data(function (d) { - var arr = d.shortcuts; - if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') { - arr = ['Y']; - } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') { - arr = ['F11']; - } - - return arr.map(function(s) { - return { - shortcut: s, - separator: d.separator - }; - }); - }) - .enter() - .each(function (d, i, nodes) { - var selection$$1 = d3_select(this); - var click = d.shortcut.toLowerCase().match(/(.*).click/); - - if (click && click[1]) { - selection$$1 - .call(svgIcon('#walkthrough-mouse', 'mouseclick', click[1])); - } else { - selection$$1 - .append('kbd') - .attr('class', 'shortcut') - .text(function (d) { - var key = d.shortcut; - return key.indexOf('.') !== -1 ? uiCmd.display(t(key)) : uiCmd.display(key); - }); - } - - if (i < nodes.length - 1) { - selection$$1 - .append('span') - .text(d.separator || '\u00a0' + t('shortcuts.or') + '\u00a0'); - } - }); + chapter.exit = function() { + timeouts.forEach(window.clearTimeout); + context.on('enter.intro exit.intro', null); + context.map().on('move.intro drawn.intro', null); + context.history().on('change.intro', null); + select('.inspector-wrap').on('wheel.intro', null); + select('.preset-search-input').on('keydown.intro keyup.intro', null); + select('.more-fields .combobox-input').on('click.intro', null); + }; - shortcutKeys - .filter(function(d) { return d.gesture; }) - .each(function () { - var selection$$1 = d3_select(this); + chapter.restart = function() { + chapter.exit(); + chapter.enter(); + }; - selection$$1 - .append('span') - .text('+'); - selection$$1 - .append('span') - .attr('class', 'gesture') - .text(function (d) { return t(d.gesture); }); - }); + return utilRebind(chapter, dispatch$$1, 'on'); + } + function uiModal(selection$$1, blocking) { + var keybinding = d3keybinding('modal'); + var previous = selection$$1.select('div.modal'); + var animate = previous.empty(); + + previous.transition() + .duration(200) + .style('opacity', 0) + .remove(); + + var shaded = selection$$1 + .append('div') + .attr('class', 'shaded') + .style('opacity', 0); + + shaded.close = function() { + shaded + .transition() + .duration(200) + .style('opacity',0) + .remove(); + + modal + .transition() + .duration(200) + .style('top','0px'); + + keybinding.off(); + }; - shortcutRows - .append('td') - .attr('class', 'shortcut-desc') - .text(function (d) { return d.text ? t(d.text) : '\u00a0'; }); + var modal = shaded + .append('div') + .attr('class', 'modal fillL col6'); - shortcuts = shortcuts - .merge(shortcutsEnter); + if (!blocking) { + shaded.on('click.remove-modal', function() { + if (event.target === this) { + shaded.close(); + } + }); - // Update - wrapper.selectAll('.shortcut-tab') - .style('display', function (d, i) { - return i === activeTab ? 'flex' : 'none'; - }); - } + modal.append('button') + .attr('class', 'close') + .on('click', shaded.close) + .call(svgIcon('#icon-close')); + keybinding + .on('⌫', shaded.close) + .on('⎋', shaded.close); - return function(selection$$1, show) { - savedSelection = selection$$1; - if (show) { - modalSelection = uiModal(selection$$1); - shortcutsModal(modalSelection); - } - }; -} - -function uiHelp(context) { - var key = t('help.key'); - - var docKeys = [ - ['help', [ - 'welcome', - 'open_data_h', - 'open_data', - 'before_start_h', - 'before_start', - 'open_source_h', - 'open_source', - 'open_source_help' - ]], - ['overview', [ - 'navigation_h', - 'navigation_drag', - 'navigation_zoom', - 'features_h', - 'features', - 'nodes_ways' - ]], - ['editing', [ - 'select_h', - 'select_left_click', - 'select_right_click', - 'multiselect_h', - 'multiselect_shift_click', - 'multiselect_lasso', - 'undo_redo_h', - 'undo_redo', - 'save_h', - 'save', - 'save_validation', - 'upload_h', - 'upload', - 'backups_h', - 'backups', - 'keyboard_h', - 'keyboard' - ]], - ['feature_editor', [ - 'intro', - 'definitions', - 'type_h', - 'type', - 'type_picker', - 'fields_h', - 'fields_all_fields', - 'fields_example', - 'fields_add_field', - 'tags_h', - 'tags_all_tags', - 'tags_resources' - ]], - ['points', [ - 'intro', - 'add_point_h', - 'add_point', - 'add_point_finish', - 'move_point_h', - 'move_point', - 'delete_point_h', - 'delete_point', - 'delete_point_command' - ]], - ['lines', [ - 'intro', - 'add_line_h', - 'add_line', - 'add_line_draw', - 'add_line_finish', - 'modify_line_h', - 'modify_line_dragnode', - 'modify_line_addnode', - 'connect_line_h', - 'connect_line', - 'connect_line_display', - 'connect_line_drag', - 'connect_line_tag', - 'disconnect_line_h', - 'disconnect_line_command', - 'move_line_h', - 'move_line_command', - 'move_line_connected', - 'delete_line_h', - 'delete_line', - 'delete_line_command' - ]], - ['areas', [ - 'intro', - 'point_or_area_h', - 'point_or_area', - 'add_area_h', - 'add_area_command', - 'add_area_draw', - 'add_area_finish', - 'square_area_h', - 'square_area_command', - 'modify_area_h', - 'modify_area_dragnode', - 'modify_area_addnode', - 'delete_area_h', - 'delete_area', - 'delete_area_command' - ]], - ['relations', [ - 'intro', - 'edit_relation_h', - 'edit_relation', - 'edit_relation_add', - 'edit_relation_delete', - 'maintain_relation_h', - 'maintain_relation', - 'relation_types_h', - 'multipolygon_h', - 'multipolygon', - 'multipolygon_create', - 'multipolygon_merge', - 'turn_restriction_h', - 'turn_restriction', - 'turn_restriction_field', - 'turn_restriction_editing', - 'route_h', - 'route', - 'route_add', - 'boundary_h', - 'boundary', - 'boundary_add' - ]], - ['imagery', [ - 'intro', - 'sources_h', - 'choosing', - 'sources', - 'offsets_h', - 'offset', - 'offset_change' - ]], - ['streetlevel', [ - 'intro', - 'using_h', - 'using', - 'photos', - 'viewer' - ]], - ['gps', [ - 'intro', - 'survey', - 'using_h', - 'using', - 'tracing', - 'upload' - ]] - ]; + select(document) + .call(keybinding); + } - var headings = { - 'help.help.open_data_h': 3, - 'help.help.before_start_h': 3, - 'help.help.open_source_h': 3, - 'help.overview.navigation_h': 3, - 'help.overview.features_h': 3, - 'help.editing.select_h': 3, - 'help.editing.multiselect_h': 3, - 'help.editing.undo_redo_h': 3, - 'help.editing.save_h': 3, - 'help.editing.upload_h': 3, - 'help.editing.backups_h': 3, - 'help.editing.keyboard_h': 3, - 'help.feature_editor.type_h': 3, - 'help.feature_editor.fields_h': 3, - 'help.feature_editor.tags_h': 3, - 'help.points.add_point_h': 3, - 'help.points.move_point_h': 3, - 'help.points.delete_point_h': 3, - 'help.lines.add_line_h': 3, - 'help.lines.modify_line_h': 3, - 'help.lines.connect_line_h': 3, - 'help.lines.disconnect_line_h': 3, - 'help.lines.move_line_h': 3, - 'help.lines.delete_line_h': 3, - 'help.areas.point_or_area_h': 3, - 'help.areas.add_area_h': 3, - 'help.areas.square_area_h': 3, - 'help.areas.modify_area_h': 3, - 'help.areas.delete_area_h': 3, - 'help.relations.edit_relation_h': 3, - 'help.relations.maintain_relation_h': 3, - 'help.relations.relation_types_h': 2, - 'help.relations.multipolygon_h': 3, - 'help.relations.turn_restriction_h': 3, - 'help.relations.route_h': 3, - 'help.relations.boundary_h': 3, - 'help.imagery.sources_h': 3, - 'help.imagery.offsets_h': 3, - 'help.streetlevel.using_h': 3, - 'help.gps.using_h': 3, - }; + modal + .append('div') + .attr('class', 'content'); - var replacements = { - point: icon('#icon-point', 'pre-text'), - line: icon('#icon-line', 'pre-text'), - area: icon('#icon-area', 'pre-text'), - plus: icon('#icon-plus', 'pre-text'), - minus: icon('#icon-minus', 'pre-text'), - orthogonalize: icon('#operation-orthogonalize', 'pre-text'), - disconnect: icon('#operation-disconnect', 'pre-text'), - layers: icon('#icon-layers', 'pre-text'), - data: icon('#icon-data', 'pre-text'), - inspect: icon('#icon-inspect', 'pre-text'), - move: icon('#operation-move', 'pre-text'), - merge: icon('#operation-merge', 'pre-text'), - delete: icon('#operation-delete', 'pre-text'), - close: icon('#icon-close', 'pre-text'), - undo: icon(textDirection === 'rtl' ? '#icon-redo' : '#icon-undo', 'pre-text'), - redo: icon(textDirection === 'rtl' ? '#icon-undo' : '#icon-redo', 'pre-text'), - save: icon('#icon-save', 'pre-text'), - leftclick: icon('#walkthrough-mouse', 'pre-text mouseclick', 'left'), - rightclick: icon('#walkthrough-mouse', 'pre-text mouseclick', 'right'), - shift: uiCmd.display('⇧'), - alt: uiCmd.display('⌥'), - return: uiCmd.display('↵'), - version: context.version - }; + if (animate) { + shaded.transition().style('opacity', 1); + } else { + shaded.style('opacity', 1); + } - // For each section, squash all the texts into a single markdown document - var docs = docKeys.map(function(key) { - var helpkey = 'help.' + key[0]; - var text = key[1].reduce(function(all, part) { - var subkey = helpkey + '.' + part; - var depth = headings[subkey]; // is this subkey a heading? - var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s - return all + hhh + t(subkey, replacements) + '\n\n'; - }, ''); - return { - title: t(helpkey + '.title'), - html: marked(text.trim()) - }; - }); + return shaded; + } + function uiIntroStartEditing(context, reveal) { + var dispatch$$1 = dispatch('done', 'startEditing'), + modalSelection = select(null); - function help(selection$$1) { - function hidePane() { - setVisible(false); - } + var chapter = { + title: 'intro.startediting.title' + }; + function showHelp() { + reveal('.map-control.help-control', + t('intro.startediting.help', { button: icon('#icon-help', 'pre-text'), key: t('help.key') }), { + buttonText: t('intro.ok'), + buttonCallback: function() { shortcuts(); } + } + ); + } - function togglePane() { - if (event) event.preventDefault(); - tooltipBehavior.hide(button); - setVisible(!button.classed('active')); - } + function shortcuts() { + reveal('.map-control.help-control', + t('intro.startediting.shortcuts', { key: t('shortcuts.toggle.key') }), { + buttonText: t('intro.ok'), + buttonCallback: function() { showSave(); } + } + ); + } + function showSave() { + d3_selectAll('.shaded').remove(); // in case user opened keyboard shortcuts + reveal('#bar button.save', + t('intro.startediting.save'), { + buttonText: t('intro.ok'), + buttonCallback: function() { showStart(); } + } + ); + } - function setVisible(show) { - if (show !== shown) { - button.classed('active', show); - shown = show; - - if (show) { - uiBackground.hidePane(); - uiMapData.hidePane(); - - pane.style('display', 'block') - .style('right', '-500px') - .transition() - .duration(200) - .style('right', '0px'); - - } else { - pane.style('right', '0px') - .transition() - .duration(200) - .style('right', '-500px') - .on('end', function() { - d3_select(this).style('display', 'none'); - }); - } - } - } + function showStart() { + d3_selectAll('.shaded').remove(); // in case user opened keyboard shortcuts + modalSelection = uiModal(context.container()); - function clickHelp(d, i) { - var rtl = (textDirection === 'rtl'); - pane.property('scrollTop', 0); - doctitle.html(d.title); + modalSelection.select('.modal') + .attr('class', 'modal-splash modal col6'); - body.html(d.html); - body.selectAll('a') - .attr('target', '_blank'); - menuItems.classed('selected', function(m) { - return m.title === d.title; - }); + modalSelection.selectAll('.close').remove(); - nav.html(''); - if (rtl) { - nav.call(drawNext).call(drawPrevious); - } else { - nav.call(drawPrevious).call(drawNext); - } + var startbutton = modalSelection.select('.content') + .attr('class', 'fillL') + .append('button') + .attr('class', 'modal-section huge-modal-button') + .on('click', function() { + modalSelection.remove(); + }); + startbutton + .append('svg') + .attr('class', 'illustration') + .append('use') + .attr('xlink:href', '#logo-walkthrough'); - function drawNext(selection$$1) { - if (i < docs.length - 1) { - var nextLink = selection$$1 - .append('a') - .attr('class', 'next') - .on('click', function() { - clickHelp(docs[i + 1], i + 1); - }); - - nextLink - .append('span') - .text(docs[i + 1].title) - .call(svgIcon((rtl ? '#icon-backward' : '#icon-forward'), 'inline')); - } - } + startbutton + .append('h2') + .text(t('intro.startediting.start')); + dispatch$$1.call('startEditing'); + } - function drawPrevious(selection$$1) { - if (i > 0) { - var prevLink = selection$$1 - .append('a') - .attr('class', 'previous') - .on('click', function() { - clickHelp(docs[i - 1], i - 1); - }); - - prevLink - .call(svgIcon((rtl ? '#icon-forward' : '#icon-backward'), 'inline')) - .append('span') - .text(docs[i - 1].title); - } - } - } + chapter.enter = function() { + showHelp(); + }; - function clickWalkthrough() { - if (context.inIntro()) return; - context.container().call(uiIntro(context)); - setVisible(false); - } + chapter.exit = function() { + modalSelection.remove(); + d3_selectAll('.shaded').remove(); // in case user opened keyboard shortcuts + }; - function clickShortcuts() { - context.container().call(uiShortcuts(context), true); - } + return utilRebind(chapter, dispatch$$1, 'on'); + } - var pane = selection$$1.append('div') - .attr('class', 'help-wrap map-overlay fillL col6 content hide'); - var tooltipBehavior = tooltip() - .placement((textDirection === 'rtl') ? 'right' : 'left') - .html(true) - .title(uiTooltipHtml(t('help.title'), key)); - var button = selection$$1.append('button') - .attr('tabindex', -1) - .on('click', togglePane) - .call(svgIcon('#icon-help', 'light')) - .call(tooltipBehavior); - var shown = false; - - - var toc = pane - .append('ul') - .attr('class', 'toc'); - - var menuItems = toc.selectAll('li') - .data(docs) - .enter() - .append('li') - .append('a') - .html(function(d) { return d.title; }) - .on('click', clickHelp); - - var shortcuts = toc - .append('li') - .attr('class', 'shortcuts') - .call(tooltip() - .html(true) - .title(uiTooltipHtml(t('shortcuts.tooltip'), '?')) - .placement('top') - ) - .append('a') - .on('click', clickShortcuts); - - shortcuts - .append('div') - .text(t('shortcuts.title')); - - var walkthrough = toc - .append('li') - .attr('class', 'walkthrough') - .append('a') - .on('click', clickWalkthrough); - - walkthrough - .append('svg') - .attr('class', 'logo logo-walkthrough') - .append('use') - .attr('xlink:href', '#logo-walkthrough'); - - walkthrough - .append('div') - .text(t('splash.walkthrough')); - - - var content = pane - .append('div') - .attr('class', 'left-content'); - - var doctitle = content - .append('h2') - .text(t('help.title')); - - var body = content - .append('div') - .attr('class', 'body'); - - var nav = content - .append('div') - .attr('class', 'nav'); - - clickHelp(docs[0], 0); - - var keybinding = d3keybinding('help') - .on(key, togglePane) - .on([t('background.key'), t('map_data.key')], hidePane); - - d3_select(document) - .call(keybinding); - - uiHelp.hidePane = hidePane; - uiHelp.togglePane = togglePane; - uiHelp.setVisible = setVisible; - } - - return help; -} - -function localeDateString(s) { - if (!s) return null; - var detected = utilDetect(); - var options = { day: 'numeric', month: 'short', year: 'numeric' }; - var d = new Date(s); - if (isNaN(d.getTime())) return null; - return d.toLocaleDateString(detected.locale, options); -} - -function vintageRange(vintage) { - var s; - if (vintage.start || vintage.end) { - s = (vintage.start || '?'); - if (vintage.start !== vintage.end) { - s += ' - ' + (vintage.end || '?'); - } - } - return s; -} + var chapterUi = { + welcome: uiIntroWelcome, + navigation: uiIntroNavigation, + point: uiIntroPoint, + area: uiIntroArea, + line: uiIntroLine, + building: uiIntroBuilding, + startEditing: uiIntroStartEditing + }; + var chapterFlow = [ + 'welcome', + 'navigation', + 'point', + 'area', + 'line', + 'building', + 'startEditing' + ]; -function rendererBackgroundSource(data) { - var source = clone(data); - var offset = [0, 0]; - var name = source.name; - var description = source.description; - var best = !!source.best; - var template = source.template; - source.scaleExtent = data.scaleExtent || [0, 22]; - source.overzoom = data.overzoom !== false; + function uiIntro(context) { + var introGraph = {}, + currChapter; - source.offset = function(_) { - if (!arguments.length) return offset; - offset = _; - return source; - }; + // create entities for intro graph and localize names + for (var id in dataIntroGraph) { + introGraph[id] = osmEntity$$1(localize(dataIntroGraph[id])); + } - source.nudge = function(_, zoomlevel) { - offset[0] += _[0] / Math.pow(2, zoomlevel); - offset[1] += _[1] / Math.pow(2, zoomlevel); - return source; - }; + function intro(selection$$1) { + context.enter(modeBrowse(context)); + + // Save current map state + var osm = context.connection(), + history = context.history().toJSON(), + hash = window.location.hash, + center = context.map().center(), + zoom = context.map().zoom(), + background = context.background().baseLayerSource(), + overlays = context.background().overlayLayerSources(), + opacity = d3_selectAll('#map .layer-background').style('opacity'), + loadedTiles = osm && osm.loadedTiles(), + baseEntities = context.history().graph().base().entities, + countryCode = services.geocoder.countryCode; + + // Block saving + context.inIntro(true); + + // Load semi-real data used in intro + if (osm) { osm.toggle(false).reset(); } + context.history().reset(); + context.history().merge(values$1(coreGraph$$1().load(introGraph).entities)); + context.history().checkpoint('initial'); + + var esri = context.background().findSource('EsriWorldImagery'); + if (esri) { + context.background().baseLayerSource(esri); + } else { + context.background().bing(); + } + overlays.forEach(function (d) { + context.background().toggleOverlayLayer(d); + }); + // Mock geocoder + services.geocoder.countryCode = function(location, callback) { + callback(null, t('intro.graph.countrycode')); + }; - source.name = function() { - var id_safe = source.id.replace('.', ''); - return t('imagery.' + id_safe + '.name', { default: name }); - }; + d3_selectAll('#map .layer-background').style('opacity', 1); + var curtain = uiCurtain(); + selection$$1.call(curtain); - source.description = function() { - var id_safe = source.id.replace('.', ''); - return t('imagery.' + id_safe + '.description', { default: description }); - }; + // store that the user started the walkthrough.. + context.storage('walkthrough_started', 'yes'); + // restore previous walkthrough progress.. + var storedProgress = context.storage('walkthrough_progress') || ''; + var progress = storedProgress.split(';').filter(Boolean); - source.best = function() { - return best; - }; + var chapters = chapterFlow.map(function(chapter, i) { + var s = chapterUi[chapter](context, curtain.reveal) + .on('done', function() { + context.presets().init(); // clear away "recent" presets + buttons.filter(function(d) { + return d.title === s.title; + }).classed('finished', true); - source.area = function() { - if (!data.polygon) return Number.MAX_VALUE; // worldwide - var area = d3_geoArea({ type: 'MultiPolygon', coordinates: [ data.polygon ] }); - return isNaN(area) ? 0 : area; - }; + if (i < chapterFlow.length - 1) { + var next = chapterFlow[i + 1]; + select('button.chapter-' + next) + .classed('next', true); + } + // store walkthrough progress.. + progress.push(chapter); + context.storage('walkthrough_progress', uniq(progress).join(';')); + }); + return s; + }); - source.imageryUsed = function() { - return name || source.id; - }; + chapters[chapters.length - 1].on('startEditing', function() { + // store walkthrough progress.. + progress.push('startEditing'); + context.storage('walkthrough_progress', uniq(progress).join(';')); + + // store if walkthrough is completed.. + var incomplete = difference(chapterFlow, progress); + if (!incomplete.length) { + context.storage('walkthrough_completed', 'yes'); + } + + curtain.remove(); + navwrap.remove(); + d3_selectAll('#map .layer-background').style('opacity', opacity); + if (osm) { osm.toggle(true).reset().loadedTiles(loadedTiles); } + context.history().reset().merge(values$1(baseEntities)); + context.background().baseLayerSource(background); + overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); }); + if (history) { context.history().fromJSON(history, false); } + context.map().centerZoom(center, zoom); + window.location.replace(hash); + services.geocoder.countryCode = countryCode; + context.inIntro(false); + }); + var navwrap = selection$$1 + .append('div') + .attr('class', 'intro-nav-wrap fillD'); - source.template = function(_) { - if (!arguments.length) return template; - if (source.id === 'custom') template = _; - return source; - }; + navwrap + .append('svg') + .attr('class', 'intro-nav-wrap-logo') + .append('use') + .attr('xlink:href', '#logo-walkthrough'); + var buttonwrap = navwrap + .append('div') + .attr('class', 'joined') + .selectAll('button.chapter'); - source.url = function(coord) { - if (this.type === 'wms') { - var tileToProjectedCoords = (function(x, y, z) { - //polyfill for IE11, PhantomJS - var sinh = Math.sinh || function(x) { - var y = Math.exp(x); - return (y - 1 / y) / 2; - }; - - var zoomSize = Math.pow(2, z); - var lon = x / zoomSize * Math.PI * 2 - Math.PI; - var lat = Math.atan(sinh(Math.PI * (1 - 2 * y / zoomSize))); - - switch (this.projection) { - case 'EPSG:4326': // todo: alternative codes of WGS 84? - return { - x: lon * 180 / Math.PI, - y: lat * 180 / Math.PI - }; - default: // EPSG:3857 and synonyms - var mercCoords = mercatorRaw(lon, lat); - return { - x: 20037508.34 / Math.PI * mercCoords[0], - y: 20037508.34 / Math.PI * mercCoords[1] - }; - } - }).bind(this); - var minXmaxY = tileToProjectedCoords(coord[0], coord[1], coord[2]); - var maxXminY = tileToProjectedCoords(coord[0]+1, coord[1]+1, coord[2]); - return template - .replace('{width}', 256) - .replace('{height}', 256) - .replace('{proj}', this.projection) - .replace('{bbox}', minXmaxY.x + ',' + maxXminY.y + ',' + maxXminY.x + ',' + minXmaxY.y); - } - return template - .replace('{x}', coord[0]) - .replace('{y}', coord[1]) - // TMS-flipped y coordinate - .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1) - .replace(/\{z(oom)?\}/, coord[2]) - .replace(/\{switch:([^}]+)\}/, function(s, r) { - var subdomains = r.split(','); - return subdomains[(coord[0] + coord[1]) % subdomains.length]; - }) - .replace('{u}', function() { - var u = ''; - for (var zoom = coord[2]; zoom > 0; zoom--) { - var b = 0; - var mask = 1 << (zoom - 1); - if ((coord[0] & mask) !== 0) b++; - if ((coord[1] & mask) !== 0) b += 2; - u += b.toString(); - } - return u; - }); - }; + var buttons = buttonwrap + .data(chapters) + .enter() + .append('button') + .attr('class', function(d, i) { return 'chapter chapter-' + chapterFlow[i]; }) + .on('click', enterChapter); + buttons + .append('span') + .text(function(d) { return t(d.title); }); - source.intersects = function(extent) { - extent = extent.polygon(); - return !data.polygon || data.polygon.some(function(polygon) { - return geoPolygonIntersectsPolygon(polygon, extent, true); - }); - }; + buttons + .append('span') + .attr('class', 'status') + .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline')); + enterChapter(chapters[0]); - source.validZoom = function(z) { - return source.scaleExtent[0] <= z && - (source.overzoom || source.scaleExtent[1] > z); - }; + function enterChapter(newChapter) { + if (currChapter) { currChapter.exit(); } + context.enter(modeBrowse(context)); - source.isLocatorOverlay = function() { - return source.id === 'mapbox_locator_overlay'; - }; + currChapter = newChapter; + currChapter.enter(); + + buttons + .classed('next', false) + .classed('active', function(d) { + return d.title === currChapter.title; + }); + } + } - /* hides a source from the list, but leaves it available for use */ - source.isHidden = function() { - return source.id === 'DigitalGlobe-Premium-vintage' || - source.id === 'DigitalGlobe-Standard-vintage'; - }; + return intro; + } + function uiTooltipHtml(text, key, heading) { + var s = ''; - source.copyrightNotices = function() {}; + if (heading) { + s += '
    ' + heading + '
    '; + } + if (text) { + s += '
    ' + text + '
    '; + } + if (key) { + s += '
    ' + t('tooltip_keyhint') + '' + + '' + key + '
    '; + } + return s; + } - source.getMetadata = function(center, tileCoord, callback) { - var vintage = { - start: localeDateString(source.startDate), - end: localeDateString(source.endDate) - }; - vintage.range = vintageRange(vintage); + function uiMapData(context) { + var key = t('map_data.key'); + var features = context.features().keys(); + var layers = context.layers(); + var fills = ['wireframe', 'partial', 'full']; - var metadata = { vintage: vintage }; - callback(null, metadata); - }; + var _fillSelected = context.storage('area-fill') || 'partial'; + var _shown = false; + var _dataLayerContainer = select(null); + var _fillList = select(null); + var _featureList = select(null); - return source; -} + function showsFeature(d) { + return context.features().enabled(d); + } -rendererBackgroundSource.Bing = function(data, dispatch) { - // http://msdn.microsoft.com/en-us/library/ff701716.aspx - // http://msdn.microsoft.com/en-us/library/ff701701.aspx + function autoHiddenFeature(d) { + return context.features().autoHidden(d); + } - data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z'; - var bing = rendererBackgroundSource(data), - key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM - url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' + - key + '&jsonp={callback}', - cache = {}, - inflight = {}, - providers = []; + function clickFeature(d) { + context.features().toggle(d); + update(); + } - jsonpRequest(url, function(json) { - providers = json.resourceSets[0].resources[0].imageryProviders.map(function(provider) { - return { - attribution: provider.attribution, - areas: provider.coverageAreas.map(function(area) { - return { - zoom: [area.zoomMin, area.zoomMax], - extent: geoExtent$$1([area.bbox[1], area.bbox[0]], [area.bbox[3], area.bbox[2]]) - }; - }) - }; - }); - dispatch.call('change'); - }); + function showsFill(d) { + return _fillSelected === d; + } - bing.copyrightNotices = function(zoom, extent) { - zoom = Math.min(zoom, 21); - return providers.filter(function(provider) { - return some(provider.areas, function(area) { - return extent.intersects(area.extent) && - area.zoom[0] <= zoom && - area.zoom[1] >= zoom; - }); - }).map(function(provider) { - return provider.attribution; - }).join(', '); - }; + function setFill(d) { + fills.forEach(function(opt) { + context.surface().classed('fill-' + opt, Boolean(opt === d)); + }); - bing.getMetadata = function(center, tileCoord, callback) { - var tileId = tileCoord.slice(0, 3).join('/'), - zoom = Math.min(tileCoord[2], 21), - centerPoint = center[1] + ',' + center[0], // lat,lng - url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/' + centerPoint + - '?zl=' + zoom + '&key=' + key + '&jsonp={callback}'; + _fillSelected = d; + context.storage('area-fill', d); + if (d !== 'wireframe') { + context.storage('area-fill-toggle', d); + } + update(); + } - if (inflight[tileId]) return; - if (!cache[tileId]) { - cache[tileId] = {}; - } - if (cache[tileId] && cache[tileId].metadata) { - return callback(null, cache[tileId].metadata); - } + function showsLayer(which) { + var layer = layers.layer(which); + if (layer) { + return layer.enabled(); + } + return false; + } - inflight[tileId] = true; - jsonpRequest(url, function(result) { - delete inflight[tileId]; - var err = (!result && 'Unknown Error') || result.errorDetails; - if (err) { - return callback(err); - } else { - var vintage = { - start: localeDateString(result.resourceSets[0].resources[0].vintageStart), - end: localeDateString(result.resourceSets[0].resources[0].vintageEnd) - }; - vintage.range = vintageRange(vintage); - - var metadata = { vintage: vintage }; - cache[tileId].metadata = metadata; - return callback(null, metadata); - } - }); - }; + function setLayer(which, enabled) { + var layer = layers.layer(which); + if (layer) { + layer.enabled(enabled); + update(); + } + } - bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details'; + function toggleLayer(which) { + setLayer(which, !showsLayer(which)); + } - return bing; -}; + function drawPhotoItems(selection$$1) { + var photoKeys = ['mapillary-images', 'mapillary-signs', 'openstreetcam-images']; + var photoLayers = layers.all().filter(function(obj) { return photoKeys.indexOf(obj.id) !== -1; }); + var data = photoLayers.filter(function(obj) { return obj.layer.supported(); }); + function layerSupported(d) { + return d.layer && d.layer.supported(); + } + function layerEnabled(d) { + return layerSupported(d) && d.layer.enabled(); + } + var ul = selection$$1 + .selectAll('.layer-list-photos') + .data([0]); + + ul = ul.enter() + .append('ul') + .attr('class', 'layer-list layer-list-photos') + .merge(ul); + + var li = ul.selectAll('.list-item-photos') + .data(data); + + li.exit() + .remove(); + + var liEnter = li.enter() + .append('li') + .attr('class', function(d) { return 'list-item-photos list-item-' + d.id; }); + + var labelEnter = liEnter + .append('label') + .each(function(d) { + select(this) + .call(tooltip() + .title(t(d.id.replace('-', '_') + '.tooltip')) + .placement('top') + ); + }); + + labelEnter + .append('input') + .attr('type', 'checkbox') + .on('change', function(d) { toggleLayer(d.id); }); + + labelEnter + .append('span') + .text(function(d) { return t(d.id.replace('-', '_') + '.title'); }); + + + // Update + li = li + .merge(liEnter); + + li + .classed('active', layerEnabled) + .selectAll('input') + .property('checked', layerEnabled); + } -rendererBackgroundSource.Esri = function(data) { - // don't request blank tiles, instead overzoom real tiles - #4327 - // deprecated technique, but it works (for now) - if (data.template.match(/blankTile/) === null) { - data.template = data.template + '?blankTile=false'; - } + function drawOsmItem(selection$$1) { + var osm = layers.layer('osm'), + showsOsm = osm.enabled(); - var esri = rendererBackgroundSource(data), - cache = {}, - inflight = {}; + var ul = selection$$1 + .selectAll('.layer-list-osm') + .data(osm ? [0] : []); - esri.getMetadata = function(center, tileCoord, callback) { - var tileId = tileCoord.slice(0, 3).join('/'), - zoom = Math.min(tileCoord[2], esri.scaleExtent[1]), - centerPoint = center[0] + ',' + center[1], // long, lat (as it should be) - unknown = t('info_panels.background.unknown'), - metadataLayer, - vintage = {}, - metadata = {}; + // Exit + ul.exit() + .remove(); - if (inflight[tileId]) return; + // Enter + var ulEnter = ul.enter() + .append('ul') + .attr('class', 'layer-list layer-list-osm'); - switch (true) { - case (zoom >= 20 && esri.id === 'EsriWorldImageryClarity'): - metadataLayer = 4; - break; - case zoom >= 19: - metadataLayer = 3; - break; - case zoom >= 17: - metadataLayer = 2; - break; - case zoom >= 13: - metadataLayer = 0; - break; - default: - metadataLayer = 99; - } + var liEnter = ulEnter + .append('li') + .attr('class', 'list-item-osm'); - var url; - // build up query using the layer appropriate to the current zoom - if (esri.id === 'EsriWorldImagery') { - url = 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/'; - } else if (esri.id === 'EsriWorldImageryClarity') { - url = 'https://serviceslab.arcgisonline.com/arcgis/rest/services/Clarity_World_Imagery/MapServer/'; - } + var labelEnter = liEnter + .append('label') + .call(tooltip() + .title(t('map_data.layers.osm.tooltip')) + .placement('top') + ); - url += metadataLayer + '/query?returnGeometry=false&geometry=' + centerPoint + '&inSR=4326&geometryType=esriGeometryPoint&outFields=*&f=json&callback={callback}'; + labelEnter + .append('input') + .attr('type', 'checkbox') + .on('change', function() { toggleLayer('osm'); }); - if (!cache[tileId]) { - cache[tileId] = {}; - } - if (cache[tileId] && cache[tileId].metadata) { - return callback(null, cache[tileId].metadata); - } + labelEnter + .append('span') + .text(t('map_data.layers.osm.title')); - // accurate metadata is only available >= 13 - if (metadataLayer === 99) { - vintage = { - start: null, - end: null, - range: null - }; - metadata = { - vintage: null, - source: unknown, - description: unknown, - resolution: unknown, - accuracy: unknown - }; + // Update + ul = ul + .merge(ulEnter); - callback(null, metadata); + ul.selectAll('.list-item-osm') + .classed('active', showsOsm) + .selectAll('input') + .property('checked', showsOsm); + } - } else { - inflight[tileId] = true; - jsonpRequest(url, function(result) { - delete inflight[tileId]; - - var err; - if (!result) { - err = 'Unknown Error'; - } else if (result.features && result.features.length < 1) { - err = 'No Results'; - } else if (result.error && result.error.message) { - err = result.error.message; - } - - if (err) { - return callback(err); - } else { - // pass through the discrete capture date from metadata - var captureDate = localeDateString(result.features[0].attributes.SRC_DATE2); - vintage = { - start: captureDate, - end: captureDate, - range: captureDate - }; - metadata = { - vintage: vintage, - source: clean(result.features[0].attributes.NICE_NAME), - description: clean(result.features[0].attributes.NICE_DESC), - resolution: clean(result.features[0].attributes.SRC_RES), - accuracy: clean(result.features[0].attributes.SRC_ACC) - }; - - // append units - meters - if (isFinite(metadata.resolution)) { - metadata.resolution += ' m'; - } - if (isFinite(metadata.accuracy)) { - metadata.accuracy += ' m'; - } - - cache[tileId].metadata = metadata; - return callback(null, metadata); - } - }); - } + function drawGpxItem(selection$$1) { + var gpx = layers.layer('gpx'), + hasGpx = gpx && gpx.hasGpx(), + showsGpx = hasGpx && gpx.enabled(); + + var ul = selection$$1 + .selectAll('.layer-list-gpx') + .data(gpx ? [0] : []); + + // Exit + ul.exit() + .remove(); + + // Enter + var ulEnter = ul.enter() + .append('ul') + .attr('class', 'layer-list layer-list-gpx'); + + var liEnter = ulEnter + .append('li') + .attr('class', 'list-item-gpx'); + + liEnter + .append('button') + .attr('class', 'list-item-gpx-extent') + .call(tooltip() + .title(t('gpx.zoom')) + .placement((textDirection === 'rtl') ? 'right' : 'left') + ) + .on('click', function() { + event.preventDefault(); + event.stopPropagation(); + gpx.fitZoom(); + }) + .call(svgIcon('#icon-search')); + + liEnter + .append('button') + .attr('class', 'list-item-gpx-browse') + .call(tooltip() + .title(t('gpx.browse')) + .placement((textDirection === 'rtl') ? 'right' : 'left') + ) + .on('click', function() { + select(document.createElement('input')) + .attr('type', 'file') + .on('change', function() { + gpx.files(event.target.files); + }) + .node().click(); + }) + .call(svgIcon('#icon-geolocate')); + + var labelEnter = liEnter + .append('label') + .call(tooltip() + .title(t('gpx.drag_drop')) + .placement('top') + ); + + labelEnter + .append('input') + .attr('type', 'checkbox') + .on('change', function() { toggleLayer('gpx'); }); + + labelEnter + .append('span') + .text(t('gpx.local_layer')); + + // Update + ul = ul + .merge(ulEnter); + + ul.selectAll('.list-item-gpx') + .classed('active', showsGpx) + .selectAll('label') + .classed('deemphasize', !hasGpx) + .selectAll('input') + .property('disabled', !hasGpx) + .property('checked', showsGpx); + } - function clean(val) { - return String(val).trim() || unknown; - } - }; - return esri; -}; + function drawListItems(selection$$1, data, type, name, change, active) { + var items = selection$$1.selectAll('li') + .data(data); + + // Exit + items.exit() + .remove(); + + // Enter + var enter = items.enter() + .append('li') + .attr('class', 'layer') + .call(tooltip() + .html(true) + .title(function(d) { + var tip = t(name + '.' + d + '.tooltip'), + key = (d === 'wireframe' ? t('area_fill.wireframe.key') : null); + + if (name === 'feature' && autoHiddenFeature(d)) { + var msg = showsLayer('osm') ? t('map_data.autohidden') : t('map_data.osmhidden'); + tip += '
    ' + msg + '
    '; + } + return uiTooltipHtml(tip, key); + }) + .placement('top') + ); + + var label = enter + .append('label'); + + label + .append('input') + .attr('type', type) + .attr('name', name) + .on('change', change); + + label + .append('span') + .text(function(d) { return t(name + '.' + d + '.description'); }); + + // Update + items = items + .merge(enter); + + items + .classed('active', active) + .selectAll('input') + .property('checked', active) + .property('indeterminate', function(d) { + return (name === 'feature' && autoHiddenFeature(d)); + }); + } -rendererBackgroundSource.None = function() { - var source = rendererBackgroundSource({ id: 'none', template: '' }); + function renderDataLayers(selection$$1) { + var container = selection$$1.selectAll('data-layer-container') + .data([0]); + _dataLayerContainer = container.enter() + .append('div') + .attr('class', 'data-layer-container') + .merge(container); + } - source.name = function() { - return t('background.none'); - }; + function renderFillList(selection$$1) { + var container = selection$$1.selectAll('layer-fill-list') + .data([0]); - source.imageryUsed = function() { - return 'None'; - }; + _fillList = container.enter() + .append('ul') + .attr('class', 'layer-list layer-fill-list') + .merge(container); + } - source.area = function() { - return -1; // sources in background pane are sorted by area - }; + function renderFeatureList(selection$$1) { + var container = selection$$1.selectAll('layer-feature-list') + .data([0]); + _featureList = container.enter() + .append('ul') + .attr('class', 'layer-list layer-feature-list') + .merge(container); + } - return source; -}; + function update() { + _dataLayerContainer + .call(drawOsmItem) + .call(drawPhotoItems) + .call(drawGpxItem); -rendererBackgroundSource.Custom = function(template) { - var source = rendererBackgroundSource({ id: 'custom', template: template }); + _fillList + .call(drawListItems, fills, 'radio', 'area_fill', setFill, showsFill); + _featureList + .call(drawListItems, features, 'checkbox', 'feature', clickFeature, showsFeature); + } - source.name = function() { - return t('background.custom'); - }; + function toggleWireframe() { + if (event) { + event.preventDefault(); + event.stopPropagation(); + } - source.imageryUsed = function() { - return 'Custom (' + source.template() + ')'; - }; + if (_fillSelected === 'wireframe') { + _fillSelected = context.storage('area-fill-toggle') || 'partial'; + } else { + _fillSelected = 'wireframe'; + } + setFill(_fillSelected); + context.map().pan([0,0]); // trigger a redraw + } - source.area = function() { - return -2; // sources in background pane are sorted by area - }; + function mapData(selection$$1) { - return source; -}; + function hidePane() { + setVisible(false); + } -function rendererTileLayer(context) { - var tileSize = 256; - var transformProp = utilPrefixCSSProperty('Transform'); - var geotile = d3geoTile(); + function togglePane() { + if (event) event.preventDefault(); + paneTooltip.hide(button); + setVisible(!button.classed('active')); + } - var _projection; - var _cache = {}; - var _tileOrigin; - var _zoom; - var _source; + function setVisible(show) { + if (show !== _shown) { + button.classed('active', show); + _shown = show; + + if (show) { + uiBackground.hidePane(); + uiHelp.hidePane(); + update(); + + pane + .style('display', 'block') + .style('right', '-300px') + .transition() + .duration(200) + .style('right', '0px'); + + } else { + pane + .style('display', 'block') + .style('right', '0px') + .transition() + .duration(200) + .style('right', '-300px') + .on('end', function() { + select(this).style('display', 'none'); + }); + } + } + } - // blacklist overlay tiles around Null Island.. - function nearNullIsland(x, y, z) { - if (z >= 7) { - var center = Math.pow(2, z - 1); - var width = Math.pow(2, z - 6); - var min = center - (width / 2); - var max = center + (width / 2) - 1; - return x >= min && x <= max && y >= min && y <= max; - } - return false; - } + var pane = selection$$1 + .append('div') + .attr('class', 'fillL map-pane col4 hide'); + + var paneTooltip = tooltip() + .placement((textDirection === 'rtl') ? 'right' : 'left') + .html(true) + .title(uiTooltipHtml(t('map_data.description'), key)); + + var button = selection$$1 + .append('button') + .attr('tabindex', -1) + .on('click', togglePane) + .call(svgIcon('#icon-data', 'light')) + .call(paneTooltip); + + + var heading = pane + .append('div') + .attr('class', 'pane-heading'); + + heading + .append('h2') + .text(t('map_data.title')); + + heading + .append('button') + .on('click', function() { uiMapData.hidePane(); }) + .call(svgIcon('#icon-close')); + + + var content = pane + .append('div') + .attr('class', 'pane-content'); + + // data layers + content + .append('div') + .attr('class', 'map-data-data-layers') + .call(uiDisclosure(context, 'data_layers', true) + .title(t('map_data.data_layers')) + .content(renderDataLayers) + ); + + // area fills + content + .append('div') + .attr('class', 'map-data-area-fills') + .call(uiDisclosure(context, 'fill_area', false) + .title(t('map_data.fill_area')) + .content(renderFillList) + ); + + // feature filters + content + .append('div') + .attr('class', 'map-data-feature-filters') + .call(uiDisclosure(context, 'map_features', false) + .title(t('map_data.map_features')) + .content(renderFeatureList) + ); + + + // add listeners + context.features() + .on('change.map_data-update', update); + + update(); + setFill(_fillSelected); + + var keybinding = d3keybinding('features') + .on(key, togglePane) + .on(t('area_fill.wireframe.key'), toggleWireframe) + .on([t('background.key'), t('help.key')], hidePane); + + select(document) + .call(keybinding); + + uiMapData.hidePane = hidePane; + uiMapData.togglePane = togglePane; + uiMapData.setVisible = setVisible; + } + return mapData; + } - function tileSizeAtZoom(d, z) { - var EPSILON = 0.002; - return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + EPSILON; - } + function uiShortcuts() { + var detected = utilDetect(); + var activeTab = 0; + var modalSelection; + var savedSelection; + + + var keybinding = d3keybinding('shortcuts') + .on(t('shortcuts.toggle.key'), function () { + if (d3_selectAll('.modal-shortcuts').size()) { // already showing + if (modalSelection) { + modalSelection.close(); + modalSelection = null; + } + } else { + modalSelection = uiModal(savedSelection); + shortcutsModal(modalSelection); + } + }); + select(document) + .call(keybinding); - function atZoom(t$$1, distance) { - var power = Math.pow(2, distance); - return [ - Math.floor(t$$1[0] * power), - Math.floor(t$$1[1] * power), - t$$1[2] + distance - ]; - } - function lookUp(d) { - for (var up = -1; up > -d[2]; up--) { - var tile = atZoom(d, up); - if (_cache[_source.url(tile)] !== false) { - return tile; - } - } - } + function shortcutsModal(modalSelection) { + modalSelection.select('.modal') + .classed('modal-shortcuts', true); + var shortcutsModal = modalSelection.select('.content'); - function uniqueBy(a, n) { - var o = []; - var seen = {}; - for (var i = 0; i < a.length; i++) { - if (seen[a[i][n]] === undefined) { - o.push(a[i]); - seen[a[i][n]] = true; - } - } - return o; - } + shortcutsModal + .append('div') + .attr('class', 'modal-section') + .append('h3') + .text(t('shortcuts.title')); + shortcutsModal + .call(render); + } - function addSource(d) { - d.push(_source.url(d)); - return d; - } + function render(selection$$1) { + var wrapper = selection$$1 + .selectAll('.wrapper') + .data([0]); + + var wrapperEnter = wrapper + .enter() + .append('div') + .attr('class', 'wrapper modal-section'); + + var tabsBar = wrapperEnter + .append('div') + .attr('class', 'tabs-bar'); + + var shortcutsList = wrapperEnter + .append('div') + .attr('class', 'shortcuts-list'); + + wrapper = wrapper.merge(wrapperEnter); + + var tabs = tabsBar + .selectAll('.tab') + .data(dataShortcuts); + + var tabsEnter = tabs + .enter() + .append('div') + .attr('class', 'tab') + .on('click', function (d, i) { + activeTab = i; + render(selection$$1); + }); + + tabsEnter + .append('span') + .text(function (d) { return t(d.text); }); + + tabs = tabs + .merge(tabsEnter); + + // Update + wrapper.selectAll('.tab') + .classed('active', function (d, i) { + return i === activeTab; + }); + + + var shortcuts = shortcutsList + .selectAll('.shortcut-tab') + .data(dataShortcuts); + + var shortcutsEnter = shortcuts + .enter() + .append('div') + .attr('class', function(d) { return 'shortcut-tab shortcut-tab-' + d.tab; }); + + var columnsEnter = shortcutsEnter + .selectAll('.shortcut-column') + .data(function (d) { return d.columns; }) + .enter() + .append('table') + .attr('class', 'shortcut-column'); + + var rowsEnter = columnsEnter + .selectAll('.shortcut-row') + .data(function (d) { return d.rows; }) + .enter() + .append('tr') + .attr('class', 'shortcut-row'); + + + var sectionRows = rowsEnter + .filter(function (d) { return !d.shortcuts; }); + + sectionRows + .append('td'); + + sectionRows + .append('td') + .attr('class', 'shortcut-section') + .append('h3') + .text(function (d) { return t(d.text); }); + + + var shortcutRows = rowsEnter + .filter(function (d) { return d.shortcuts; }); + + var shortcutKeys = shortcutRows + .append('td') + .attr('class', 'shortcut-keys'); + + var modifierKeys = shortcutKeys + .filter(function (d) { return d.modifiers; }); + + modifierKeys + .selectAll('kbd.modifier') + .data(function (d) { + if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') { + return ['⌘']; + } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') { + return []; + } else { + return d.modifiers; + } + }) + .enter() + .each(function () { + var selection$$1 = select(this); + + selection$$1 + .append('kbd') + .attr('class', 'modifier') + .text(function (d) { return uiCmd.display(d); }); + + selection$$1 + .append('span') + .text('+'); + }); + + + shortcutKeys + .selectAll('kbd.shortcut') + .data(function (d) { + var arr = d.shortcuts; + if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') { + arr = ['Y']; + } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') { + arr = ['F11']; + } + + return arr.map(function(s) { + return { + shortcut: s, + separator: d.separator + }; + }); + }) + .enter() + .each(function (d, i, nodes) { + var selection$$1 = select(this); + var click = d.shortcut.toLowerCase().match(/(.*).click/); + + if (click && click[1]) { + selection$$1 + .call(svgIcon('#walkthrough-mouse', 'mouseclick', click[1])); + } else { + selection$$1 + .append('kbd') + .attr('class', 'shortcut') + .text(function (d) { + var key = d.shortcut; + return key.indexOf('.') !== -1 ? uiCmd.display(t(key)) : uiCmd.display(key); + }); + } + + if (i < nodes.length - 1) { + selection$$1 + .append('span') + .text(d.separator || '\u00a0' + t('shortcuts.or') + '\u00a0'); + } + }); + + + shortcutKeys + .filter(function(d) { return d.gesture; }) + .each(function () { + var selection$$1 = select(this); + + selection$$1 + .append('span') + .text('+'); + + selection$$1 + .append('span') + .attr('class', 'gesture') + .text(function (d) { return t(d.gesture); }); + }); + + + shortcutRows + .append('td') + .attr('class', 'shortcut-desc') + .text(function (d) { return d.text ? t(d.text) : '\u00a0'; }); + + + shortcuts = shortcuts + .merge(shortcutsEnter); + + // Update + wrapper.selectAll('.shortcut-tab') + .style('display', function (d, i) { + return i === activeTab ? 'flex' : 'none'; + }); + } - // Update tiles based on current state of `projection`. - function background(selection$$1) { - _zoom = geoScaleToZoom(_projection.scale(), tileSize); - var pixelOffset; - if (_source) { - pixelOffset = [ - _source.offset()[0] * Math.pow(2, _zoom), - _source.offset()[1] * Math.pow(2, _zoom) - ]; - } else { - pixelOffset = [0, 0]; - } + return function(selection$$1, show) { + savedSelection = selection$$1; + if (show) { + modalSelection = uiModal(selection$$1); + shortcutsModal(modalSelection); + } + }; + } - var translate = [ - _projection.translate()[0] + pixelOffset[0], - _projection.translate()[1] + pixelOffset[1] - ]; + function uiHelp(context) { + var key = t('help.key'); + + var docKeys = [ + ['help', [ + 'welcome', + 'open_data_h', + 'open_data', + 'before_start_h', + 'before_start', + 'open_source_h', + 'open_source', + 'open_source_help' + ]], + ['overview', [ + 'navigation_h', + 'navigation_drag', + 'navigation_zoom', + 'features_h', + 'features', + 'nodes_ways' + ]], + ['editing', [ + 'select_h', + 'select_left_click', + 'select_right_click', + 'multiselect_h', + 'multiselect_shift_click', + 'multiselect_lasso', + 'undo_redo_h', + 'undo_redo', + 'save_h', + 'save', + 'save_validation', + 'upload_h', + 'upload', + 'backups_h', + 'backups', + 'keyboard_h', + 'keyboard' + ]], + ['feature_editor', [ + 'intro', + 'definitions', + 'type_h', + 'type', + 'type_picker', + 'fields_h', + 'fields_all_fields', + 'fields_example', + 'fields_add_field', + 'tags_h', + 'tags_all_tags', + 'tags_resources' + ]], + ['points', [ + 'intro', + 'add_point_h', + 'add_point', + 'add_point_finish', + 'move_point_h', + 'move_point', + 'delete_point_h', + 'delete_point', + 'delete_point_command' + ]], + ['lines', [ + 'intro', + 'add_line_h', + 'add_line', + 'add_line_draw', + 'add_line_finish', + 'modify_line_h', + 'modify_line_dragnode', + 'modify_line_addnode', + 'connect_line_h', + 'connect_line', + 'connect_line_display', + 'connect_line_drag', + 'connect_line_tag', + 'disconnect_line_h', + 'disconnect_line_command', + 'move_line_h', + 'move_line_command', + 'move_line_connected', + 'delete_line_h', + 'delete_line', + 'delete_line_command' + ]], + ['areas', [ + 'intro', + 'point_or_area_h', + 'point_or_area', + 'add_area_h', + 'add_area_command', + 'add_area_draw', + 'add_area_finish', + 'square_area_h', + 'square_area_command', + 'modify_area_h', + 'modify_area_dragnode', + 'modify_area_addnode', + 'delete_area_h', + 'delete_area', + 'delete_area_command' + ]], + ['relations', [ + 'intro', + 'edit_relation_h', + 'edit_relation', + 'edit_relation_add', + 'edit_relation_delete', + 'maintain_relation_h', + 'maintain_relation', + 'relation_types_h', + 'multipolygon_h', + 'multipolygon', + 'multipolygon_create', + 'multipolygon_merge', + 'turn_restriction_h', + 'turn_restriction', + 'turn_restriction_field', + 'turn_restriction_editing', + 'route_h', + 'route', + 'route_add', + 'boundary_h', + 'boundary', + 'boundary_add' + ]], + ['imagery', [ + 'intro', + 'sources_h', + 'choosing', + 'sources', + 'offsets_h', + 'offset', + 'offset_change' + ]], + ['streetlevel', [ + 'intro', + 'using_h', + 'using', + 'photos', + 'viewer' + ]], + ['gps', [ + 'intro', + 'survey', + 'using_h', + 'using', + 'tracing', + 'upload' + ]] + ]; - geotile - .scale(_projection.scale() * 2 * Math.PI) - .translate(translate); + var headings = { + 'help.help.open_data_h': 3, + 'help.help.before_start_h': 3, + 'help.help.open_source_h': 3, + 'help.overview.navigation_h': 3, + 'help.overview.features_h': 3, + 'help.editing.select_h': 3, + 'help.editing.multiselect_h': 3, + 'help.editing.undo_redo_h': 3, + 'help.editing.save_h': 3, + 'help.editing.upload_h': 3, + 'help.editing.backups_h': 3, + 'help.editing.keyboard_h': 3, + 'help.feature_editor.type_h': 3, + 'help.feature_editor.fields_h': 3, + 'help.feature_editor.tags_h': 3, + 'help.points.add_point_h': 3, + 'help.points.move_point_h': 3, + 'help.points.delete_point_h': 3, + 'help.lines.add_line_h': 3, + 'help.lines.modify_line_h': 3, + 'help.lines.connect_line_h': 3, + 'help.lines.disconnect_line_h': 3, + 'help.lines.move_line_h': 3, + 'help.lines.delete_line_h': 3, + 'help.areas.point_or_area_h': 3, + 'help.areas.add_area_h': 3, + 'help.areas.square_area_h': 3, + 'help.areas.modify_area_h': 3, + 'help.areas.delete_area_h': 3, + 'help.relations.edit_relation_h': 3, + 'help.relations.maintain_relation_h': 3, + 'help.relations.relation_types_h': 2, + 'help.relations.multipolygon_h': 3, + 'help.relations.turn_restriction_h': 3, + 'help.relations.route_h': 3, + 'help.relations.boundary_h': 3, + 'help.imagery.sources_h': 3, + 'help.imagery.offsets_h': 3, + 'help.streetlevel.using_h': 3, + 'help.gps.using_h': 3, + }; - _tileOrigin = [ - _projection.scale() * Math.PI - translate[0], - _projection.scale() * Math.PI - translate[1] - ]; + var replacements = { + point: icon('#icon-point', 'pre-text'), + line: icon('#icon-line', 'pre-text'), + area: icon('#icon-area', 'pre-text'), + plus: icon('#icon-plus', 'pre-text'), + minus: icon('#icon-minus', 'pre-text'), + orthogonalize: icon('#operation-orthogonalize', 'pre-text'), + disconnect: icon('#operation-disconnect', 'pre-text'), + layers: icon('#icon-layers', 'pre-text'), + data: icon('#icon-data', 'pre-text'), + inspect: icon('#icon-inspect', 'pre-text'), + move: icon('#operation-move', 'pre-text'), + merge: icon('#operation-merge', 'pre-text'), + delete: icon('#operation-delete', 'pre-text'), + close: icon('#icon-close', 'pre-text'), + undo: icon(textDirection === 'rtl' ? '#icon-redo' : '#icon-undo', 'pre-text'), + redo: icon(textDirection === 'rtl' ? '#icon-undo' : '#icon-redo', 'pre-text'), + save: icon('#icon-save', 'pre-text'), + leftclick: icon('#walkthrough-mouse', 'pre-text mouseclick', 'left'), + rightclick: icon('#walkthrough-mouse', 'pre-text mouseclick', 'right'), + shift: uiCmd.display('⇧'), + alt: uiCmd.display('⌥'), + return: uiCmd.display('↵'), + version: context.version + }; - render(selection$$1); - } + // For each section, squash all the texts into a single markdown document + var docs = docKeys.map(function(key) { + var helpkey = 'help.' + key[0]; + var text = key[1].reduce(function(all, part) { + var subkey = helpkey + '.' + part; + var depth = headings[subkey]; // is this subkey a heading? + var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s + return all + hhh + t(subkey, replacements) + '\n\n'; + }, ''); + + return { + title: t(helpkey + '.title'), + html: marked(text.trim()) + }; + }); - // Derive the tiles onscreen, remove those offscreen and position them. - // Important that this part not depend on `_projection` because it's - // rentered when tiles load/error (see #644). - function render(selection$$1) { - if (!_source) return; - var requests = []; - var showDebug = context.getDebug('tile') && !_source.overlay; + function help(selection$$1) { - if (_source.validZoom(_zoom)) { - geotile().forEach(function(d) { - addSource(d); - if (d[3] === '') return; - if (typeof d[3] !== 'string') return; // Workaround for #2295 - requests.push(d); - if (_cache[d[3]] === false && lookUp(d)) { - requests.push(addSource(lookUp(d))); - } - }); + function hidePane() { + setVisible(false); + } - requests = uniqueBy(requests, 3).filter(function(r) { - if (!!_source.overlay && nearNullIsland(r[0], r[1], r[2])) { - return false; - } - // don't re-request tiles which have failed in the past - return _cache[r[3]] !== false; - }); - } + function togglePane() { + if (event) event.preventDefault(); + tooltipBehavior.hide(button); + setVisible(!button.classed('active')); + } - function load(d) { - _cache[d[3]] = true; - d3_select(this) - .on('error', null) - .on('load', null) - .classed('tile-loaded', true); - render(selection$$1); - } - function error(d) { - _cache[d[3]] = false; - d3_select(this) - .on('error', null) - .on('load', null) - .remove(); - render(selection$$1); - } + function setVisible(show) { + if (show !== shown) { + button.classed('active', show); + shown = show; + + if (show) { + uiBackground.hidePane(); + uiMapData.hidePane(); + + pane.style('display', 'block') + .style('right', '-500px') + .transition() + .duration(200) + .style('right', '0px'); + + } else { + pane.style('right', '0px') + .transition() + .duration(200) + .style('right', '-500px') + .on('end', function() { + select(this).style('display', 'none'); + }); + } + } + } - function imageTransform(d) { - var ts = tileSize * Math.pow(2, _zoom - d[2]); - var scale = tileSizeAtZoom(d, _zoom); - return 'translate(' + - ((d[0] * ts) - _tileOrigin[0]) + 'px,' + - ((d[1] * ts) - _tileOrigin[1]) + 'px) ' + - 'scale(' + scale + ',' + scale + ')'; - } - function tileCenter(d) { - var ts = tileSize * Math.pow(2, _zoom - d[2]); - return [ - ((d[0] * ts) - _tileOrigin[0] + (ts / 2)), - ((d[1] * ts) - _tileOrigin[1] + (ts / 2)) - ]; - } + function clickHelp(d, i) { + var rtl = (textDirection === 'rtl'); + pane.property('scrollTop', 0); + doctitle.html(d.title); + + body.html(d.html); + body.selectAll('a') + .attr('target', '_blank'); + menuItems.classed('selected', function(m) { + return m.title === d.title; + }); + + nav.html(''); + if (rtl) { + nav.call(drawNext).call(drawPrevious); + } else { + nav.call(drawPrevious).call(drawNext); + } + + + function drawNext(selection$$1) { + if (i < docs.length - 1) { + var nextLink = selection$$1 + .append('a') + .attr('class', 'next') + .on('click', function() { + clickHelp(docs[i + 1], i + 1); + }); + + nextLink + .append('span') + .text(docs[i + 1].title) + .call(svgIcon((rtl ? '#icon-backward' : '#icon-forward'), 'inline')); + } + } + + + function drawPrevious(selection$$1) { + if (i > 0) { + var prevLink = selection$$1 + .append('a') + .attr('class', 'previous') + .on('click', function() { + clickHelp(docs[i - 1], i - 1); + }); + + prevLink + .call(svgIcon((rtl ? '#icon-forward' : '#icon-backward'), 'inline')) + .append('span') + .text(docs[i - 1].title); + } + } + } - function debugTransform(d) { - var coord = tileCenter(d); - return 'translate(' + coord[0] + 'px,' + coord[1] + 'px)'; - } + function clickWalkthrough() { + if (context.inIntro()) return; + context.container().call(uiIntro(context)); + setVisible(false); + } - // Pick a representative tile near the center of the viewport - // (This is useful for sampling the imagery vintage) - var dims = geotile.size(); - var mapCenter = [dims[0] / 2, dims[1] / 2]; - var minDist = Math.max(dims[0], dims[1]); - var nearCenter; - requests.forEach(function(d) { - var c = tileCenter(d); - var dist = geoVecLength(c, mapCenter); - if (dist < minDist) { - minDist = dist; - nearCenter = d; - } - }); + function clickShortcuts() { + context.container().call(uiShortcuts(context), true); + } - var image = selection$$1.selectAll('img') - .data(requests, function(d) { return d[3]; }); + var pane = selection$$1.append('div') + .attr('class', 'help-wrap map-pane fillL col6 hide'); - image.exit() - .style(transformProp, imageTransform) - .classed('tile-removing', true) - .classed('tile-center', false) - .each(function() { - var tile = d3_select(this); - window.setTimeout(function() { - if (tile.classed('tile-removing')) { - tile.remove(); - } - }, 300); - }); + var tooltipBehavior = tooltip() + .placement((textDirection === 'rtl') ? 'right' : 'left') + .html(true) + .title(uiTooltipHtml(t('help.title'), key)); - image.enter() - .append('img') - .attr('class', 'tile') - .attr('src', function(d) { return d[3]; }) - .on('error', error) - .on('load', load) - .merge(image) - .style(transformProp, imageTransform) - .classed('tile-debug', showDebug) - .classed('tile-removing', false) - .classed('tile-center', function(d) { return d === nearCenter; }); - - - - var debug = selection$$1.selectAll('.tile-label-debug') - .data(showDebug ? requests : [], function(d) { return d[3]; }); - - debug.exit() - .remove(); - - if (showDebug) { - var debugEnter = debug.enter() - .append('div') - .attr('class', 'tile-label-debug'); - - debugEnter - .append('div') - .attr('class', 'tile-label-debug-coord'); - - debugEnter - .append('div') - .attr('class', 'tile-label-debug-vintage'); - - debug = debug.merge(debugEnter); - - debug - .style(transformProp, debugTransform); - - debug - .selectAll('.tile-label-debug-coord') - .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; }); - - debug - .selectAll('.tile-label-debug-vintage') - .each(function(d) { - var span = d3_select(this); - var center = context.projection.invert(tileCenter(d)); - _source.getMetadata(center, d, function(err, result) { - span.text((result && result.vintage && result.vintage.range) || - t('info_panels.background.vintage') + ': ' + t('info_panels.background.unknown') - ); - }); - }); - } + var button = selection$$1.append('button') + .attr('tabindex', -1) + .on('click', togglePane) + .call(svgIcon('#icon-help', 'light')) + .call(tooltipBehavior); - } + var shown = false; - background.projection = function(_) { - if (!arguments.length) return _projection; - _projection = _; - return background; - }; + var heading = pane + .append('div') + .attr('class', 'pane-heading'); + var doctitle = heading + .append('h2') + .text(t('help.title')); - background.dimensions = function(_) { - if (!arguments.length) return geotile.size(); - geotile.size(_); - return background; - }; + heading + .append('button') + .on('click', function() { uiHelp.hidePane(); }) + .call(svgIcon('#icon-close')); - background.source = function(_) { - if (!arguments.length) return _source; - _source = _; - _cache = {}; - geotile.scaleExtent(_source.scaleExtent); - return background; - }; + var content = pane + .append('div') + .attr('class', 'pane-content'); + var toc = content + .append('ul') + .attr('class', 'toc'); - return background; -} + var menuItems = toc.selectAll('li') + .data(docs) + .enter() + .append('li') + .append('a') + .html(function(d) { return d.title; }) + .on('click', clickHelp); -function rendererBackground(context) { - var dispatch$$1 = dispatch('change'); - var detected = utilDetect(); - var baseLayer = rendererTileLayer(context).projection(context.projection); - var _overlayLayers = []; - var _backgroundSources = []; - var _brightness = 1; - var _contrast = 1; - var _saturation = 1; - var _sharpness = 1; + var shortcuts = toc + .append('li') + .attr('class', 'shortcuts') + .call(tooltip() + .html(true) + .title(uiTooltipHtml(t('shortcuts.tooltip'), '?')) + .placement('top') + ) + .append('a') + .on('click', clickShortcuts); + shortcuts + .append('div') + .text(t('shortcuts.title')); - function background(selection$$1) { + var walkthrough = toc + .append('li') + .attr('class', 'walkthrough') + .append('a') + .on('click', clickWalkthrough); - var baseFilter = ''; - if (detected.cssfilters) { - if (_brightness !== 1) { - baseFilter += 'brightness(' + _brightness + ')'; - } - if (_contrast !== 1) { - baseFilter += 'contrast(' + _contrast + ')'; - } - if (_saturation !== 1) { - baseFilter += 'saturate(' + _saturation + ')'; - } - if (_sharpness < 1) { // gaussian blur - var blur = d3_interpolateNumber(0.5, 5)(1 - _sharpness); - baseFilter += 'blur(' + blur + 'px)'; - } - } + walkthrough + .append('svg') + .attr('class', 'logo logo-walkthrough') + .append('use') + .attr('xlink:href', '#logo-walkthrough'); - var base = selection$$1.selectAll('.layer-background') - .data([0]); + walkthrough + .append('div') + .text(t('splash.walkthrough')); - base = base.enter() - .insert('div', '.layer-data') - .attr('class', 'layer layer-background') - .merge(base); - if (detected.cssfilters) { - base.style('filter', baseFilter || null); - } else { - base.style('opacity', _brightness); - } + var helpContent = content + .append('div') + .attr('class', 'left-content'); + var body = helpContent + .append('div') + .attr('class', 'body'); - var imagery = base.selectAll('.layer-imagery') - .data([0]); + var nav = helpContent + .append('div') + .attr('class', 'nav'); - imagery.enter() - .append('div') - .attr('class', 'layer layer-imagery') - .merge(imagery) - .call(baseLayer); + clickHelp(docs[0], 0); + var keybinding = d3keybinding('help') + .on(key, togglePane) + .on([t('background.key'), t('map_data.key')], hidePane); - var maskFilter = ''; - var mixBlendMode = ''; - if (detected.cssfilters && _sharpness > 1) { // apply unsharp mask - mixBlendMode = 'overlay'; - maskFilter = 'saturate(0) blur(3px) invert(1)'; + select(document) + .call(keybinding); + + uiHelp.hidePane = hidePane; + uiHelp.togglePane = togglePane; + uiHelp.setVisible = setVisible; + } - var contrast = _sharpness - 1; - maskFilter += ' contrast(' + contrast + ')'; + return help; + } - var brightness = d3_interpolateNumber(1, 0.85)(_sharpness - 1); - maskFilter += ' brightness(' + brightness + ')'; - } + function localeDateString(s) { + if (!s) return null; + var detected = utilDetect(); + var options = { day: 'numeric', month: 'short', year: 'numeric' }; + var d = new Date(s); + if (isNaN(d.getTime())) return null; + return d.toLocaleDateString(detected.locale, options); + } - var mask = base.selectAll('.layer-unsharp-mask') - .data(detected.cssfilters && _sharpness > 1 ? [0] : []); + function vintageRange(vintage) { + var s; + if (vintage.start || vintage.end) { + s = (vintage.start || '?'); + if (vintage.start !== vintage.end) { + s += ' - ' + (vintage.end || '?'); + } + } + return s; + } - mask.exit() - .remove(); - mask.enter() - .append('div') - .attr('class', 'layer layer-mask layer-unsharp-mask') - .merge(mask) - .call(baseLayer) - .style('filter', maskFilter || null) - .style('mix-blend-mode', mixBlendMode || null); + function rendererBackgroundSource(data) { + var source = clone(data); + var offset = [0, 0]; + var name = source.name; + var description = source.description; + var best = !!source.best; + var template = source.template; + source.scaleExtent = data.scaleExtent || [0, 22]; + source.overzoom = data.overzoom !== false; - var overlays = selection$$1.selectAll('.layer-overlay') - .data(_overlayLayers, function(d) { return d.source().name(); }); - overlays.exit() - .remove(); + source.offset = function(_) { + if (!arguments.length) return offset; + offset = _; + return source; + }; - overlays.enter() - .insert('div', '.layer-data') - .attr('class', 'layer layer-overlay') - .merge(overlays) - .each(function(layer) { d3_select(this).call(layer); }); - } + source.nudge = function(_, zoomlevel) { + offset[0] += _[0] / Math.pow(2, zoomlevel); + offset[1] += _[1] / Math.pow(2, zoomlevel); + return source; + }; - background.updateImagery = function() { - if (context.inIntro()) return; - var b = background.baseLayerSource(), - o = _overlayLayers - .filter(function (d) { return !d.source().isLocatorOverlay() && !d.source().isHidden(); }) - .map(function (d) { return d.source().id; }) - .join(','), - meters = geoOffsetToMeters(b.offset()), - epsilon = 0.01, - x = +meters[0].toFixed(2), - y = +meters[1].toFixed(2), - q = utilStringQs(window.location.hash.substring(1)); + source.name = function() { + var id_safe = source.id.replace('.', ''); + return t('imagery.' + id_safe + '.name', { default: name }); + }; - var id = b.id; - if (id === 'custom') { - id = 'custom:' + b.template(); - } - if (id) { - q.background = id; - } else { - delete q.background; - } + source.description = function() { + var id_safe = source.id.replace('.', ''); + return t('imagery.' + id_safe + '.description', { default: description }); + }; - if (o) { - q.overlays = o; - } else { - delete q.overlays; - } - if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) { - q.offset = x + ',' + y; - } else { - delete q.offset; - } + source.best = function() { + return best; + }; - if (!window.mocha) { - window.location.replace('#' + utilQsString(q, true)); - } - var imageryUsed = [b.imageryUsed()]; + source.area = function() { + if (!data.polygon) return Number.MAX_VALUE; // worldwide + var area = d3_geoArea({ type: 'MultiPolygon', coordinates: [ data.polygon ] }); + return isNaN(area) ? 0 : area; + }; - _overlayLayers - .filter(function (d) { return !d.source().isLocatorOverlay() && !d.source().isHidden(); }) - .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); }); - var gpx = context.layers().layer('gpx'); - if (gpx && gpx.enabled() && gpx.hasGpx()) { - // Include a string like '.gpx data file' or '.geojson data file' - var match = gpx.getSrc().match(/(kml|gpx|(?:geo)?json)$/i); - var extension = match ? ('.' + match[0].toLowerCase() + ' ') : ''; - imageryUsed.push(extension + 'data file'); - } + source.imageryUsed = function() { + return name || source.id; + }; - var mapillary_images = context.layers().layer('mapillary-images'); - if (mapillary_images && mapillary_images.enabled()) { - imageryUsed.push('Mapillary Images'); - } - var mapillary_signs = context.layers().layer('mapillary-signs'); - if (mapillary_signs && mapillary_signs.enabled()) { - imageryUsed.push('Mapillary Signs'); - } + source.template = function(_) { + if (!arguments.length) return template; + if (source.id === 'custom') template = _; + return source; + }; - var openstreetcam_images = context.layers().layer('openstreetcam-images'); - if (openstreetcam_images && openstreetcam_images.enabled()) { - imageryUsed.push('OpenStreetCam Images'); - } - context.history().imageryUsed(imageryUsed); - }; + source.url = function(coord) { + if (this.type === 'wms') { + var tileToProjectedCoords = (function(x, y, z) { + //polyfill for IE11, PhantomJS + var sinh = Math.sinh || function(x) { + var y = Math.exp(x); + return (y - 1 / y) / 2; + }; + + var zoomSize = Math.pow(2, z); + var lon = x / zoomSize * Math.PI * 2 - Math.PI; + var lat = Math.atan(sinh(Math.PI * (1 - 2 * y / zoomSize))); + + switch (this.projection) { + case 'EPSG:4326': // todo: alternative codes of WGS 84? + return { + x: lon * 180 / Math.PI, + y: lat * 180 / Math.PI + }; + default: // EPSG:3857 and synonyms + var mercCoords = mercatorRaw(lon, lat); + return { + x: 20037508.34 / Math.PI * mercCoords[0], + y: 20037508.34 / Math.PI * mercCoords[1] + }; + } + }).bind(this); + var minXmaxY = tileToProjectedCoords(coord[0], coord[1], coord[2]); + var maxXminY = tileToProjectedCoords(coord[0]+1, coord[1]+1, coord[2]); + return template + .replace('{width}', 256) + .replace('{height}', 256) + .replace('{proj}', this.projection) + .replace('{bbox}', minXmaxY.x + ',' + maxXminY.y + ',' + maxXminY.x + ',' + minXmaxY.y); + } + return template + .replace('{x}', coord[0]) + .replace('{y}', coord[1]) + // TMS-flipped y coordinate + .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1) + .replace(/\{z(oom)?\}/, coord[2]) + .replace(/\{switch:([^}]+)\}/, function(s, r) { + var subdomains = r.split(','); + return subdomains[(coord[0] + coord[1]) % subdomains.length]; + }) + .replace('{u}', function() { + var u = ''; + for (var zoom = coord[2]; zoom > 0; zoom--) { + var b = 0; + var mask = 1 << (zoom - 1); + if ((coord[0] & mask) !== 0) b++; + if ((coord[1] & mask) !== 0) b += 2; + u += b.toString(); + } + return u; + }); + }; - background.sources = function(extent) { - return _backgroundSources.filter(function(source) { - return source.intersects(extent); - }); - }; + source.intersects = function(extent) { + extent = extent.polygon(); + return !data.polygon || data.polygon.some(function(polygon) { + return geoPolygonIntersectsPolygon(polygon, extent, true); + }); + }; - background.dimensions = function(_) { - if (!_) return; - baseLayer.dimensions(_); + source.validZoom = function(z) { + return source.scaleExtent[0] <= z && + (source.overzoom || source.scaleExtent[1] > z); + }; - _overlayLayers.forEach(function(layer) { - layer.dimensions(_); - }); - }; + source.isLocatorOverlay = function() { + return source.id === 'mapbox_locator_overlay'; + }; - background.baseLayerSource = function(d) { - if (!arguments.length) return baseLayer.source(); - // test source against OSM imagery blacklists.. - var osm = context.connection(); - if (!osm) return background; + /* hides a source from the list, but leaves it available for use */ + source.isHidden = function() { + return source.id === 'DigitalGlobe-Premium-vintage' || + source.id === 'DigitalGlobe-Standard-vintage'; + }; - var blacklists = context.connection().imageryBlacklists(); - var template = d.template(), - fail = false, - tested = 0, - regex, i; + source.copyrightNotices = function() {}; - for (i = 0; i < blacklists.length; i++) { - try { - regex = new RegExp(blacklists[i]); - fail = regex.test(template); - tested++; - if (fail) break; - } catch (e) { - /* noop */ - } - } - // ensure at least one test was run. - if (!tested) { - regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'); - fail = regex.test(template); - } + source.getMetadata = function(center, tileCoord, callback) { + var vintage = { + start: localeDateString(source.startDate), + end: localeDateString(source.endDate) + }; + vintage.range = vintageRange(vintage); - baseLayer.source(!fail ? d : background.findSource('none')); - dispatch$$1.call('change'); - background.updateImagery(); - return background; - }; + var metadata = { vintage: vintage }; + callback(null, metadata); + }; - background.findSource = function(id) { - return find$1(_backgroundSources, function(d) { - return d.id && d.id === id; - }); - }; + return source; + } - background.bing = function() { - background.baseLayerSource(background.findSource('Bing')); - }; + rendererBackgroundSource.Bing = function(data, dispatch) { + // http://msdn.microsoft.com/en-us/library/ff701716.aspx + // http://msdn.microsoft.com/en-us/library/ff701701.aspx + + data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z'; + + var bing = rendererBackgroundSource(data), + key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM + url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' + + key + '&jsonp={callback}', + cache = {}, + inflight = {}, + providers = []; + + jsonpRequest(url, function(json) { + providers = json.resourceSets[0].resources[0].imageryProviders.map(function(provider) { + return { + attribution: provider.attribution, + areas: provider.coverageAreas.map(function(area) { + return { + zoom: [area.zoomMin, area.zoomMax], + extent: geoExtent$$1([area.bbox[1], area.bbox[0]], [area.bbox[3], area.bbox[2]]) + }; + }) + }; + }); + dispatch.call('change'); + }); - background.showsLayer = function(d) { - return d.id === baseLayer.source().id || - _overlayLayers.some(function(layer) { return d.id === layer.source().id; }); - }; + bing.copyrightNotices = function(zoom, extent) { + zoom = Math.min(zoom, 21); + return providers.filter(function(provider) { + return some(provider.areas, function(area) { + return extent.intersects(area.extent) && + area.zoom[0] <= zoom && + area.zoom[1] >= zoom; + }); + }).map(function(provider) { + return provider.attribution; + }).join(', '); + }; - background.overlayLayerSources = function() { - return _overlayLayers.map(function (l) { return l.source(); }); - }; + bing.getMetadata = function(center, tileCoord, callback) { + var tileId = tileCoord.slice(0, 3).join('/'), + zoom = Math.min(tileCoord[2], 21), + centerPoint = center[1] + ',' + center[0], // lat,lng + url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/' + centerPoint + + '?zl=' + zoom + '&key=' + key + '&jsonp={callback}'; + if (inflight[tileId]) return; - background.toggleOverlayLayer = function(d) { - var layer; + if (!cache[tileId]) { + cache[tileId] = {}; + } + if (cache[tileId] && cache[tileId].metadata) { + return callback(null, cache[tileId].metadata); + } - for (var i = 0; i < _overlayLayers.length; i++) { - layer = _overlayLayers[i]; - if (layer.source() === d) { - _overlayLayers.splice(i, 1); - dispatch$$1.call('change'); - background.updateImagery(); - return; - } - } + inflight[tileId] = true; + jsonpRequest(url, function(result) { + delete inflight[tileId]; + + var err = (!result && 'Unknown Error') || result.errorDetails; + if (err) { + return callback(err); + } else { + var vintage = { + start: localeDateString(result.resourceSets[0].resources[0].vintageStart), + end: localeDateString(result.resourceSets[0].resources[0].vintageEnd) + }; + vintage.range = vintageRange(vintage); + + var metadata = { vintage: vintage }; + cache[tileId].metadata = metadata; + return callback(null, metadata); + } + }); + }; - layer = rendererTileLayer(context) - .source(d) - .projection(context.projection) - .dimensions(baseLayer.dimensions() - ); - _overlayLayers.push(layer); - dispatch$$1.call('change'); - background.updateImagery(); - }; + bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details'; - background.nudge = function(d, zoom) { - baseLayer.source().nudge(d, zoom); - dispatch$$1.call('change'); - background.updateImagery(); - return background; - }; + return bing; + }; - background.offset = function(d) { - if (!arguments.length) return baseLayer.source().offset(); - baseLayer.source().offset(d); - dispatch$$1.call('change'); - background.updateImagery(); - return background; - }; + rendererBackgroundSource.Esri = function(data) { - background.brightness = function(d) { - if (!arguments.length) return _brightness; - _brightness = d; - if (context.mode()) dispatch$$1.call('change'); - return background; - }; + // don't request blank tiles, instead overzoom real tiles - #4327 + // deprecated technique, but it works (for now) + if (data.template.match(/blankTile/) === null) { + data.template = data.template + '?blankTile=false'; + } + var esri = rendererBackgroundSource(data), + cache = {}, + inflight = {}; + + esri.getMetadata = function(center, tileCoord, callback) { + var tileId = tileCoord.slice(0, 3).join('/'), + zoom = Math.min(tileCoord[2], esri.scaleExtent[1]), + centerPoint = center[0] + ',' + center[1], // long, lat (as it should be) + unknown = t('info_panels.background.unknown'), + metadataLayer, + vintage = {}, + metadata = {}; + + if (inflight[tileId]) return; + + switch (true) { + case (zoom >= 20 && esri.id === 'EsriWorldImageryClarity'): + metadataLayer = 4; + break; + case zoom >= 19: + metadataLayer = 3; + break; + case zoom >= 17: + metadataLayer = 2; + break; + case zoom >= 13: + metadataLayer = 0; + break; + default: + metadataLayer = 99; + } - background.contrast = function(d) { - if (!arguments.length) return _contrast; - _contrast = d; - if (context.mode()) dispatch$$1.call('change'); - return background; - }; + var url; + // build up query using the layer appropriate to the current zoom + if (esri.id === 'EsriWorldImagery') { + url = 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/'; + } else if (esri.id === 'EsriWorldImageryClarity') { + url = 'https://serviceslab.arcgisonline.com/arcgis/rest/services/Clarity_World_Imagery/MapServer/'; + } + url += metadataLayer + '/query?returnGeometry=false&geometry=' + centerPoint + '&inSR=4326&geometryType=esriGeometryPoint&outFields=*&f=json&callback={callback}'; - background.saturation = function(d) { - if (!arguments.length) return _saturation; - _saturation = d; - if (context.mode()) dispatch$$1.call('change'); - return background; - }; + if (!cache[tileId]) { + cache[tileId] = {}; + } + if (cache[tileId] && cache[tileId].metadata) { + return callback(null, cache[tileId].metadata); + } + // accurate metadata is only available >= 13 + if (metadataLayer === 99) { + vintage = { + start: null, + end: null, + range: null + }; + metadata = { + vintage: null, + source: unknown, + description: unknown, + resolution: unknown, + accuracy: unknown + }; + + callback(null, metadata); - background.sharpness = function(d) { - if (!arguments.length) return _sharpness; - _sharpness = d; - if (context.mode()) dispatch$$1.call('change'); - return background; - }; + } else { + inflight[tileId] = true; + jsonpRequest(url, function(result) { + delete inflight[tileId]; + + var err; + if (!result) { + err = 'Unknown Error'; + } else if (result.features && result.features.length < 1) { + err = 'No Results'; + } else if (result.error && result.error.message) { + err = result.error.message; + } + + if (err) { + return callback(err); + } else { + // pass through the discrete capture date from metadata + var captureDate = localeDateString(result.features[0].attributes.SRC_DATE2); + vintage = { + start: captureDate, + end: captureDate, + range: captureDate + }; + metadata = { + vintage: vintage, + source: clean(result.features[0].attributes.NICE_NAME), + description: clean(result.features[0].attributes.NICE_DESC), + resolution: clean(result.features[0].attributes.SRC_RES), + accuracy: clean(result.features[0].attributes.SRC_ACC) + }; + + // append units - meters + if (isFinite(metadata.resolution)) { + metadata.resolution += ' m'; + } + if (isFinite(metadata.accuracy)) { + metadata.accuracy += ' m'; + } + + cache[tileId].metadata = metadata; + return callback(null, metadata); + } + }); + } - background.init = function() { - function parseMap(qmap) { - if (!qmap) return false; - var args = qmap.split('/').map(Number); - if (args.length < 3 || args.some(isNaN)) return false; - return geoExtent$$1([args[2], args[1]]); - } + function clean(val) { + return String(val).trim() || unknown; + } + }; - var dataImagery = data.imagery || [], - q = utilStringQs(window.location.hash.substring(1)), - requested = q.background || q.layer, - extent = parseMap(q.map), - first, - best; - - // Add all the available imagery sources - _backgroundSources = dataImagery.map(function(source) { - if (source.type === 'bing') { - return rendererBackgroundSource.Bing(source, dispatch$$1); - } else if (/^EsriWorldImagery/.test(source.id)) { - return rendererBackgroundSource.Esri(source); - } else { - return rendererBackgroundSource(source); - } - }); + return esri; + }; - first = _backgroundSources.length && _backgroundSources[0]; - // Add 'None' - _backgroundSources.unshift(rendererBackgroundSource.None()); + rendererBackgroundSource.None = function() { + var source = rendererBackgroundSource({ id: 'none', template: '' }); - // Add 'Custom' - var template = context.storage('background-custom-template') || ''; - var custom = rendererBackgroundSource.Custom(template); - _backgroundSources.unshift(custom); + source.name = function() { + return t('background.none'); + }; - // Decide which background layer to display - if (!requested && extent) { - best = find$1(this.sources(extent), function(s) { return s.best(); }); - } - if (requested && requested.indexOf('custom:') === 0) { - template = requested.replace(/^custom:/, ''); - background.baseLayerSource(custom.template(template)); - context.storage('background-custom-template', template); - } else { - background.baseLayerSource( - background.findSource(requested) || - best || - background.findSource(context.storage('background-last-used')) || - background.findSource('Bing') || - first || - background.findSource('none') - ); - } - var locator = find$1(_backgroundSources, function(d) { - return d.overlay && d.default; - }); + source.imageryUsed = function() { + return 'None'; + }; - if (locator) { - background.toggleOverlayLayer(locator); - } - var overlays = (q.overlays || '').split(','); - overlays.forEach(function(overlay) { - overlay = background.findSource(overlay); - if (overlay) { - background.toggleOverlayLayer(overlay); - } - }); + source.area = function() { + return -1; // sources in background pane are sorted by area + }; - if (q.gpx) { - var gpx = context.layers().layer('gpx'); - if (gpx) { - gpx.url(q.gpx); - } - } - if (q.offset) { - var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) { - return !isNaN(n) && n; - }); + return source; + }; - if (offset.length === 2) { - background.offset(geoMetersToOffset(offset)); - } - } - }; + rendererBackgroundSource.Custom = function(template) { + var source = rendererBackgroundSource({ id: 'custom', template: template }); - return utilRebind(background, dispatch$$1, 'on'); -} - -function rendererFeatures(context) { - var traffic_roads = { - 'motorway': true, - 'motorway_link': true, - 'trunk': true, - 'trunk_link': true, - 'primary': true, - 'primary_link': true, - 'secondary': true, - 'secondary_link': true, - 'tertiary': true, - 'tertiary_link': true, - 'residential': true, - 'unclassified': true, - 'living_street': true - }; - var service_roads = { - 'service': true, - 'road': true, - 'track': true - }; + source.name = function() { + return t('background.custom'); + }; - var paths = { - 'path': true, - 'footway': true, - 'cycleway': true, - 'bridleway': true, - 'steps': true, - 'pedestrian': true, - 'corridor': true - }; - var past_futures = { - 'proposed': true, - 'construction': true, - 'abandoned': true, - 'dismantled': true, - 'disused': true, - 'razed': true, - 'demolished': true, - 'obliterated': true - }; + source.imageryUsed = function() { + return 'Custom (' + source.template() + ')'; + }; - var dispatch$$1 = dispatch('change', 'redraw'), - _cullFactor = 1, - _cache = {}, - _features = {}, - _stats = {}, - _keys = [], - _hidden = []; - - - function update() { - if (!window.mocha) { - var q = utilStringQs(window.location.hash.substring(1)); - var disabled = features.disabled(); - if (disabled.length) { - q.disable_features = disabled.join(','); - } else { - delete q.disable_features; - } - window.location.replace('#' + utilQsString(q, true)); - context.storage('disabled-features', disabled.join(',')); - } - _hidden = features.hidden(); - dispatch$$1.call('change'); - dispatch$$1.call('redraw'); - } - - - function defineFeature(k, filter, max) { - var isEnabled = true; - - _keys.push(k); - _features[k] = { - filter: filter, - enabled: isEnabled, // whether the user wants it enabled.. - count: 0, - currentMax: (max || Infinity), - defaultMax: (max || Infinity), - enable: function() { this.enabled = true; this.currentMax = this.defaultMax; }, - disable: function() { this.enabled = false; this.currentMax = 0; }, - hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; }, - autoHidden: function() { return this.hidden() && this.currentMax > 0; } - }; - } + source.area = function() { + return -2; // sources in background pane are sorted by area + }; - defineFeature('points', function isPoint(entity, resolver, geometry) { - return geometry === 'point'; - }, 200); - defineFeature('traffic_roads', function isTrafficRoad(entity) { - return traffic_roads[entity.tags.highway]; - }); + return source; + }; - defineFeature('service_roads', function isServiceRoad(entity) { - return service_roads[entity.tags.highway]; - }); + function rendererTileLayer(context) { + var tileSize = 256; + var transformProp = utilPrefixCSSProperty('Transform'); + var geotile = d3geoTile(); + + var _projection; + var _cache = {}; + var _tileOrigin; + var _zoom; + var _source; + + + // blacklist overlay tiles around Null Island.. + function nearNullIsland(x, y, z) { + if (z >= 7) { + var center = Math.pow(2, z - 1); + var width = Math.pow(2, z - 6); + var min = center - (width / 2); + var max = center + (width / 2) - 1; + return x >= min && x <= max && y >= min && y <= max; + } + return false; + } - defineFeature('paths', function isPath(entity) { - return paths[entity.tags.highway]; - }); - defineFeature('buildings', function isBuilding(entity) { - return ( - !!entity.tags['building:part'] || - (!!entity.tags.building && entity.tags.building !== 'no') || - entity.tags.amenity === 'shelter' || - entity.tags.parking === 'multi-storey' || - entity.tags.parking === 'sheds' || - entity.tags.parking === 'carports' || - entity.tags.parking === 'garage_boxes' - ); - }, 250); + function tileSizeAtZoom(d, z) { + var EPSILON = 0.002; + return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + EPSILON; + } - defineFeature('landuse', function isLanduse(entity, resolver, geometry) { - return geometry === 'area' && - !_features.buildings.filter(entity) && - !_features.water.filter(entity); - }); - defineFeature('boundaries', function isBoundary(entity) { - return !!entity.tags.boundary; - }); + function atZoom(t$$1, distance) { + var power = Math.pow(2, distance); + return [ + Math.floor(t$$1[0] * power), + Math.floor(t$$1[1] * power), + t$$1[2] + distance + ]; + } - defineFeature('water', function isWater(entity) { - return ( - !!entity.tags.waterway || - entity.tags.natural === 'water' || - entity.tags.natural === 'coastline' || - entity.tags.natural === 'bay' || - entity.tags.landuse === 'pond' || - entity.tags.landuse === 'basin' || - entity.tags.landuse === 'reservoir' || - entity.tags.landuse === 'salt_pond' - ); - }); - defineFeature('rail', function isRail(entity) { - return ( - !!entity.tags.railway || - entity.tags.landuse === 'railway' - ) && !( - traffic_roads[entity.tags.highway] || - service_roads[entity.tags.highway] || - paths[entity.tags.highway] - ); - }); + function lookUp(d) { + for (var up = -1; up > -d[2]; up--) { + var tile = atZoom(d, up); + if (_cache[_source.url(tile)] !== false) { + return tile; + } + } + } - defineFeature('power', function isPower(entity) { - return !!entity.tags.power; - }); - // contains a past/future tag, but not in active use as a road/path/cycleway/etc.. - defineFeature('past_future', function isPastFuture(entity) { - if ( - traffic_roads[entity.tags.highway] || - service_roads[entity.tags.highway] || - paths[entity.tags.highway] - ) { return false; } + function uniqueBy(a, n) { + var o = []; + var seen = {}; + for (var i = 0; i < a.length; i++) { + if (seen[a[i][n]] === undefined) { + o.push(a[i]); + seen[a[i][n]] = true; + } + } + return o; + } - var strings = Object.keys(entity.tags); - for (var i = 0; i < strings.length; i++) { - var s = strings[i]; - if (past_futures[s] || past_futures[entity.tags[s]]) { return true; } - } - return false; - }); + function addSource(d) { + d.push(_source.url(d)); + return d; + } - // Lines or areas that don't match another feature filter. - // IMPORTANT: The 'others' feature must be the last one defined, - // so that code in getMatches can skip this test if `hasMatch = true` - defineFeature('others', function isOther(entity, resolver, geometry) { - return (geometry === 'line' || geometry === 'area'); - }); + // Update tiles based on current state of `projection`. + function background(selection$$1) { + _zoom = geoScaleToZoom(_projection.scale(), tileSize); - function features() {} + var pixelOffset; + if (_source) { + pixelOffset = [ + _source.offset()[0] * Math.pow(2, _zoom), + _source.offset()[1] * Math.pow(2, _zoom) + ]; + } else { + pixelOffset = [0, 0]; + } + var translate = [ + _projection.translate()[0] + pixelOffset[0], + _projection.translate()[1] + pixelOffset[1] + ]; - features.features = function() { - return _features; - }; + geotile + .scale(_projection.scale() * 2 * Math.PI) + .translate(translate); + _tileOrigin = [ + _projection.scale() * Math.PI - translate[0], + _projection.scale() * Math.PI - translate[1] + ]; - features.keys = function() { - return _keys; - }; + render(selection$$1); + } - features.enabled = function(k) { - if (!arguments.length) { - return _keys.filter(function(k) { return _features[k].enabled; }); - } - return _features[k] && _features[k].enabled; - }; + // Derive the tiles onscreen, remove those offscreen and position them. + // Important that this part not depend on `_projection` because it's + // rentered when tiles load/error (see #644). + function render(selection$$1) { + if (!_source) return; + var requests = []; + var showDebug = context.getDebug('tile') && !_source.overlay; + + if (_source.validZoom(_zoom)) { + geotile().forEach(function(d) { + addSource(d); + if (d[3] === '') return; + if (typeof d[3] !== 'string') return; // Workaround for #2295 + requests.push(d); + if (_cache[d[3]] === false && lookUp(d)) { + requests.push(addSource(lookUp(d))); + } + }); + + requests = uniqueBy(requests, 3).filter(function(r) { + if (!!_source.overlay && nearNullIsland(r[0], r[1], r[2])) { + return false; + } + // don't re-request tiles which have failed in the past + return _cache[r[3]] !== false; + }); + } - features.disabled = function(k) { - if (!arguments.length) { - return _keys.filter(function(k) { return !_features[k].enabled; }); - } - return _features[k] && !_features[k].enabled; - }; + function load(d) { + _cache[d[3]] = true; + select(this) + .on('error', null) + .on('load', null) + .classed('tile-loaded', true); + render(selection$$1); + } + function error(d) { + _cache[d[3]] = false; + select(this) + .on('error', null) + .on('load', null) + .remove(); + render(selection$$1); + } - features.hidden = function(k) { - if (!arguments.length) { - return _keys.filter(function(k) { return _features[k].hidden(); }); - } - return _features[k] && _features[k].hidden(); - }; + function imageTransform(d) { + var ts = tileSize * Math.pow(2, _zoom - d[2]); + var scale = tileSizeAtZoom(d, _zoom); + return 'translate(' + + ((d[0] * ts) - _tileOrigin[0]) + 'px,' + + ((d[1] * ts) - _tileOrigin[1]) + 'px) ' + + 'scale(' + scale + ',' + scale + ')'; + } + function tileCenter(d) { + var ts = tileSize * Math.pow(2, _zoom - d[2]); + return [ + ((d[0] * ts) - _tileOrigin[0] + (ts / 2)), + ((d[1] * ts) - _tileOrigin[1] + (ts / 2)) + ]; + } - features.autoHidden = function(k) { - if (!arguments.length) { - return _keys.filter(function(k) { return _features[k].autoHidden(); }); - } - return _features[k] && _features[k].autoHidden(); - }; + function debugTransform(d) { + var coord = tileCenter(d); + return 'translate(' + coord[0] + 'px,' + coord[1] + 'px)'; + } - features.enable = function(k) { - if (_features[k] && !_features[k].enabled) { - _features[k].enable(); - update(); - } - }; + // Pick a representative tile near the center of the viewport + // (This is useful for sampling the imagery vintage) + var dims = geotile.size(); + var mapCenter = [dims[0] / 2, dims[1] / 2]; + var minDist = Math.max(dims[0], dims[1]); + var nearCenter; + + requests.forEach(function(d) { + var c = tileCenter(d); + var dist = geoVecLength(c, mapCenter); + if (dist < minDist) { + minDist = dist; + nearCenter = d; + } + }); - features.disable = function(k) { - if (_features[k] && _features[k].enabled) { - _features[k].disable(); - update(); - } - }; + var image = selection$$1.selectAll('img') + .data(requests, function(d) { return d[3]; }); + image.exit() + .style(transformProp, imageTransform) + .classed('tile-removing', true) + .classed('tile-center', false) + .each(function() { + var tile = select(this); + window.setTimeout(function() { + if (tile.classed('tile-removing')) { + tile.remove(); + } + }, 300); + }); - features.toggle = function(k) { - if (_features[k]) { - (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k])); - update(); - } - }; + image.enter() + .append('img') + .attr('class', 'tile') + .attr('src', function(d) { return d[3]; }) + .on('error', error) + .on('load', load) + .merge(image) + .style(transformProp, imageTransform) + .classed('tile-debug', showDebug) + .classed('tile-removing', false) + .classed('tile-center', function(d) { return d === nearCenter; }); - features.resetStats = function() { - for (var i = 0; i < _keys.length; i++) { - _features[_keys[i]].count = 0; - } - dispatch$$1.call('change'); - }; + var debug = selection$$1.selectAll('.tile-label-debug') + .data(showDebug ? requests : [], function(d) { return d[3]; }); - features.gatherStats = function(d, resolver, dimensions) { - var needsRedraw = false, - type = groupBy(d, function(ent) { return ent.type; }), - entities = [].concat(type.relation || [], type.way || [], type.node || []), - currHidden, geometry, matches, i, j; + debug.exit() + .remove(); - for (i = 0; i < _keys.length; i++) { - _features[_keys[i]].count = 0; - } + if (showDebug) { + var debugEnter = debug.enter() + .append('div') + .attr('class', 'tile-label-debug'); - // adjust the threshold for point/building culling based on viewport size.. - // a _cullFactor of 1 corresponds to a 1000x1000px viewport.. - _cullFactor = dimensions[0] * dimensions[1] / 1000000; - - for (i = 0; i < entities.length; i++) { - geometry = entities[i].geometry(resolver); - if (!(geometry === 'vertex' || geometry === 'relation')) { - matches = Object.keys(features.getMatches(entities[i], resolver, geometry)); - for (j = 0; j < matches.length; j++) { - _features[matches[j]].count++; - } - } - } + debugEnter + .append('div') + .attr('class', 'tile-label-debug-coord'); - currHidden = features.hidden(); - if (currHidden !== _hidden) { - _hidden = currHidden; - needsRedraw = true; - dispatch$$1.call('change'); - } + debugEnter + .append('div') + .attr('class', 'tile-label-debug-vintage'); + + debug = debug.merge(debugEnter); + + debug + .style(transformProp, debugTransform); + + debug + .selectAll('.tile-label-debug-coord') + .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; }); + + debug + .selectAll('.tile-label-debug-vintage') + .each(function(d) { + var span = select(this); + var center = context.projection.invert(tileCenter(d)); + _source.getMetadata(center, d, function(err, result) { + span.text((result && result.vintage && result.vintage.range) || + t('info_panels.background.vintage') + ': ' + t('info_panels.background.unknown') + ); + }); + }); + } - return needsRedraw; - }; + } - features.stats = function() { - for (var i = 0; i < _keys.length; i++) { - _stats[_keys[i]] = _features[_keys[i]].count; - } + background.projection = function(_) { + if (!arguments.length) return _projection; + _projection = _; + return background; + }; - return _stats; - }; + background.dimensions = function(_) { + if (!arguments.length) return geotile.size(); + geotile.size(_); + return background; + }; - features.clear = function(d) { - for (var i = 0; i < d.length; i++) { - features.clearEntity(d[i]); - } - }; + background.source = function(_) { + if (!arguments.length) return _source; + _source = _; + _cache = {}; + geotile.scaleExtent(_source.scaleExtent); + return background; + }; - features.clearEntity = function(entity) { - delete _cache[osmEntity$$1.key(entity)]; - }; + return background; + } - features.reset = function() { - _cache = {}; - }; + function rendererBackground(context) { + var dispatch$$1 = dispatch('change'); + var detected = utilDetect(); + var baseLayer = rendererTileLayer(context).projection(context.projection); + var _overlayLayers = []; + var _backgroundSources = []; + var _brightness = 1; + var _contrast = 1; + var _saturation = 1; + var _sharpness = 1; + + + function background(selection$$1) { + + var baseFilter = ''; + if (detected.cssfilters) { + if (_brightness !== 1) { + baseFilter += 'brightness(' + _brightness + ')'; + } + if (_contrast !== 1) { + baseFilter += 'contrast(' + _contrast + ')'; + } + if (_saturation !== 1) { + baseFilter += 'saturate(' + _saturation + ')'; + } + if (_sharpness < 1) { // gaussian blur + var blur = interpolateNumber(0.5, 5)(1 - _sharpness); + baseFilter += 'blur(' + blur + 'px)'; + } + } + var base = selection$$1.selectAll('.layer-background') + .data([0]); - features.getMatches = function(entity, resolver, geometry) { - if (geometry === 'vertex' || geometry === 'relation') return {}; + base = base.enter() + .insert('div', '.layer-data') + .attr('class', 'layer layer-background') + .merge(base); - var ent = osmEntity$$1.key(entity); - if (!_cache[ent]) { - _cache[ent] = {}; - } + if (detected.cssfilters) { + base.style('filter', baseFilter || null); + } else { + base.style('opacity', _brightness); + } - if (!_cache[ent].matches) { - var matches = {}, - hasMatch = false; - - for (var i = 0; i < _keys.length; i++) { - if (_keys[i] === 'others') { - if (hasMatch) continue; - - // Multipolygon members: - // If an entity... - // 1. is a way that hasn't matched other 'interesting' feature rules, - // 2. and it belongs to a single parent multipolygon relation - // ...then match whatever feature rules the parent multipolygon has matched. - // see #2548, #2887 - // - // IMPORTANT: - // For this to work, getMatches must be called on relations before ways. - // - if (entity.type === 'way') { - var parents = features.getParents(entity, resolver, geometry); - if (parents.length === 1 && parents[0].isMultipolygon()) { - var pkey = osmEntity$$1.key(parents[0]); - if (_cache[pkey] && _cache[pkey].matches) { - matches = clone(_cache[pkey].matches); - continue; - } - } - } - } - - if (_features[_keys[i]].filter(entity, resolver, geometry)) { - matches[_keys[i]] = hasMatch = true; - } - } - _cache[ent].matches = matches; - } - return _cache[ent].matches; - }; + var imagery = base.selectAll('.layer-imagery') + .data([0]); + imagery.enter() + .append('div') + .attr('class', 'layer layer-imagery') + .merge(imagery) + .call(baseLayer); - features.getParents = function(entity, resolver, geometry) { - if (geometry === 'point') return []; - var ent = osmEntity$$1.key(entity); - if (!_cache[ent]) { - _cache[ent] = {}; - } + var maskFilter = ''; + var mixBlendMode = ''; + if (detected.cssfilters && _sharpness > 1) { // apply unsharp mask + mixBlendMode = 'overlay'; + maskFilter = 'saturate(0) blur(3px) invert(1)'; - if (!_cache[ent].parents) { - var parents = []; - if (geometry === 'vertex') { - parents = resolver.parentWays(entity); - } else { // 'line', 'area', 'relation' - parents = resolver.parentRelations(entity); - } - _cache[ent].parents = parents; - } - return _cache[ent].parents; - }; + var contrast = _sharpness - 1; + maskFilter += ' contrast(' + contrast + ')'; + var brightness = interpolateNumber(1, 0.85)(_sharpness - 1); + maskFilter += ' brightness(' + brightness + ')'; + } - features.isHiddenFeature = function(entity, resolver, geometry) { - if (!_hidden.length) return false; - if (!entity.version) return false; + var mask = base.selectAll('.layer-unsharp-mask') + .data(detected.cssfilters && _sharpness > 1 ? [0] : []); - var matches = features.getMatches(entity, resolver, geometry); + mask.exit() + .remove(); - for (var i = 0; i < _hidden.length; i++) { - if (matches[_hidden[i]]) return true; - } - return false; - }; + mask.enter() + .append('div') + .attr('class', 'layer layer-mask layer-unsharp-mask') + .merge(mask) + .call(baseLayer) + .style('filter', maskFilter || null) + .style('mix-blend-mode', mixBlendMode || null); - features.isHiddenChild = function(entity, resolver, geometry) { - if (!_hidden.length) return false; - if (!entity.version || geometry === 'point') return false; + var overlays = selection$$1.selectAll('.layer-overlay') + .data(_overlayLayers, function(d) { return d.source().name(); }); - var parents = features.getParents(entity, resolver, geometry); - if (!parents.length) return false; + overlays.exit() + .remove(); - for (var i = 0; i < parents.length; i++) { - if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) { - return false; - } - } - return true; - }; + overlays.enter() + .insert('div', '.layer-data') + .attr('class', 'layer layer-overlay') + .merge(overlays) + .each(function(layer) { select(this).call(layer); }); + } - features.hasHiddenConnections = function(entity, resolver) { - if (!_hidden.length) return false; - var childNodes, connections; + background.updateImagery = function() { + if (context.inIntro()) return; - if (entity.type === 'midpoint') { - childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])]; - connections = []; - } else { - childNodes = entity.nodes ? resolver.childNodes(entity) : []; - connections = features.getParents(entity, resolver, entity.geometry(resolver)); - } + var b = background.baseLayerSource(), + o = _overlayLayers + .filter(function (d) { return !d.source().isLocatorOverlay() && !d.source().isHidden(); }) + .map(function (d) { return d.source().id; }) + .join(','), + meters = geoOffsetToMeters(b.offset()), + epsilon = 0.01, + x = +meters[0].toFixed(2), + y = +meters[1].toFixed(2), + q = utilStringQs(window.location.hash.substring(1)); - // gather ways connected to child nodes.. - connections = reduce(childNodes, function(result, e) { - return resolver.isShared(e) ? union(result, resolver.parentWays(e)) : result; - }, connections); + var id = b.id; + if (id === 'custom') { + id = 'custom:' + b.template(); + } - return connections.length ? some(connections, function(e) { - return features.isHidden(e, resolver, e.geometry(resolver)); - }) : false; - }; + if (id) { + q.background = id; + } else { + delete q.background; + } + if (o) { + q.overlays = o; + } else { + delete q.overlays; + } - features.isHidden = function(entity, resolver, geometry) { - if (!_hidden.length) return false; - if (!entity.version) return false; + if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) { + q.offset = x + ',' + y; + } else { + delete q.offset; + } - var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature); - return fn(entity, resolver, geometry); - }; + if (!window.mocha) { + window.location.replace('#' + utilQsString(q, true)); + } + var imageryUsed = [b.imageryUsed()]; - features.filter = function(d, resolver) { - if (!_hidden.length) return d; + _overlayLayers + .filter(function (d) { return !d.source().isLocatorOverlay() && !d.source().isHidden(); }) + .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); }); - var result = []; - for (var i = 0; i < d.length; i++) { - var entity = d[i]; - if (!features.isHidden(entity, resolver, entity.geometry(resolver))) { - result.push(entity); - } - } - return result; - }; + var gpx = context.layers().layer('gpx'); + if (gpx && gpx.enabled() && gpx.hasGpx()) { + // Include a string like '.gpx data file' or '.geojson data file' + var match = gpx.getSrc().match(/(kml|gpx|(?:geo)?json)$/i); + var extension = match ? ('.' + match[0].toLowerCase() + ' ') : ''; + imageryUsed.push(extension + 'data file'); + } + var mapillary_images = context.layers().layer('mapillary-images'); + if (mapillary_images && mapillary_images.enabled()) { + imageryUsed.push('Mapillary Images'); + } - features.init = function() { - var storage = context.storage('disabled-features'); - if (storage) { - var storageDisabled = storage.replace(/;/g, ',').split(','); - storageDisabled.forEach(features.disable); - } - - var q = utilStringQs(window.location.hash.substring(1)); - if (q.disable_features) { - var hashDisabled = q.disable_features.replace(/;/g, ',').split(','); - hashDisabled.forEach(features.disable); - } - }; + var mapillary_signs = context.layers().layer('mapillary-signs'); + if (mapillary_signs && mapillary_signs.enabled()) { + imageryUsed.push('Mapillary Signs'); + } - return utilRebind(features, dispatch$$1, 'on'); -} + var openstreetcam_images = context.layers().layer('openstreetcam-images'); + if (openstreetcam_images && openstreetcam_images.enabled()) { + imageryUsed.push('OpenStreetCam Images'); + } -function utilBindOnce(target, type, listener, capture) { - var typeOnce = type + '.once'; - function one() { - target.on(typeOnce, null); - listener.apply(this, arguments); - } - target.on(typeOnce, one, capture); - return this; -} - -function rendererMap(context) { - - var dimensions = [1, 1], - dispatch$$1 = dispatch('move', 'drawn'), - projection = context.projection, - curtainProjection = context.curtainProjection, - dblclickEnabled = true, - redrawEnabled = true, - transformStart = projection.transform(), - transformLast, - transformed = false, - minzoom = 0, - drawLayers = svgLayers(projection, context), - drawPoints = svgPoints$$1(projection, context), - drawVertices = svgVertices$$1(projection, context), - drawLines = svgLines$$1(projection, context), - drawAreas = svgAreas$$1(projection, context), - drawMidpoints = svgMidpoints$$1(projection, context), - drawLabels = svgLabels(projection, context), - supersurface = d3_select(null), - wrapper = d3_select(null), - surface = d3_select(null), - mouse, - mousemove; - - var zoom$$1 = d3_zoom() - .scaleExtent([ztok(2), ztok(24)]) - .interpolate(d3_interpolate) - .filter(zoomEventFilter) - .on('zoom', zoomPan); - - var _selection = d3_select(null); - - var scheduleRedraw = throttle(redraw, 750); - // var isRedrawScheduled = false; - // var pendingRedrawCall; - // function scheduleRedraw() { - // // Only schedule the redraw if one has not already been set. - // if (isRedrawScheduled) return; - // isRedrawScheduled = true; - // var that = this; - // var args = arguments; - // pendingRedrawCall = window.requestIdleCallback(function () { - // // Reset the boolean so future redraws can be set. - // isRedrawScheduled = false; - // redraw.apply(that, args); - // }, { timeout: 1400 }); - // } - - function cancelPendingRedraw() { - scheduleRedraw.cancel(); - // isRedrawScheduled = false; - // window.cancelIdleCallback(pendingRedrawCall); - } - - function map(selection$$1) { - - _selection = selection$$1; - - context - .on('change.map', immediateRedraw); - - var osm = context.connection(); - if (osm) { - osm.on('change.map', immediateRedraw); - } + context.history().imageryUsed(imageryUsed); + }; - context.history() - .on('change.map', immediateRedraw) - .on('undone.map redone.map', function(stack) { - var mode = context.mode().id; - if (mode !== 'browse' && mode !== 'select') return; - - var followSelected = false; - if (Array.isArray(stack.selectedIDs)) { - followSelected = (stack.selectedIDs.length === 1 && stack.selectedIDs[0][0] === 'n'); - context.enter( - modeSelect(context, stack.selectedIDs).follow(followSelected) - ); - } - if (!followSelected && stack.transform) { - map.transformEase(stack.transform); - } - }); - context.background() - .on('change.map', immediateRedraw); + background.sources = function(extent) { + return _backgroundSources.filter(function(source) { + return source.intersects(extent); + }); + }; - context.features() - .on('redraw.map', immediateRedraw); - drawLayers - .on('change.map', function() { - context.background().updateImagery(); - immediateRedraw(); - }); + background.dimensions = function(_) { + if (!_) return; + baseLayer.dimensions(_); - selection$$1 - .on('dblclick.map', dblClick) - .call(zoom$$1) - .call(zoom$$1.transform, projection.transform()); - - supersurface = selection$$1.append('div') - .attr('id', 'supersurface') - .call(utilSetTransform, 0, 0); - - // Need a wrapper div because Opera can't cope with an absolutely positioned - // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16 - wrapper = supersurface - .append('div') - .attr('class', 'layer layer-data'); - - map.surface = surface = wrapper - .call(drawLayers) - .selectAll('.surface') - .attr('id', 'surface'); - - surface - .call(drawLabels.observe) - .on('mousedown.zoom', function() { - if (event.button === 2) { - event.stopPropagation(); - } - }, true) - .on('mouseup.zoom', function() { - if (resetTransform()) immediateRedraw(); - }) - .on('mousemove.map', function() { - mousemove = event; - }) - .on('mouseover.vertices', function() { - if (map.editable() && !transformed) { - var hover = event.target.__data__; - surface.selectAll('.data-layer-osm') - .call(drawVertices.drawHover, context.graph(), hover, map.extent()); - dispatch$$1.call('drawn', this, { full: false }); - } - }) - .on('mouseout.vertices', function() { - if (map.editable() && !transformed) { - var hover = event.relatedTarget && event.relatedTarget.__data__; - surface.selectAll('.data-layer-osm') - .call(drawVertices.drawHover, context.graph(), hover, map.extent()); - dispatch$$1.call('drawn', this, { full: false }); - } - }); + _overlayLayers.forEach(function(layer) { + layer.dimensions(_); + }); + }; - supersurface - .call(context.background()); - - context.on('enter.map', function() { - if (map.editable() && !transformed) { - - // redraw immediately any objects affected by a change in selectedIDs. - var graph = context.graph(); - var selectedAndParents = {}; - context.selectedIDs().forEach(function(id) { - var entity = graph.hasEntity(id); - if (entity) { - selectedAndParents[entity.id] = entity; - if (entity.type === 'node') { - graph.parentWays(entity).forEach(function(parent) { - selectedAndParents[parent.id] = parent; - }); - } - } - }); - var data = values$1(selectedAndParents); - var filter = function(d) { return d.id in selectedAndParents; }; - - data = context.features().filter(data, graph); - - surface.selectAll('.data-layer-osm') - .call(drawVertices.drawSelected, graph, map.extent()) - .call(drawLines, graph, data, filter) - .call(drawAreas, graph, data, filter) - .call(drawMidpoints, graph, data, filter, map.trimmedExtent()); - - dispatch$$1.call('drawn', this, { full: false }); - - - // redraw everything else later - scheduleRedraw(); - } - }); - map.dimensions(utilGetDimensions(selection$$1)); - } - - - function zoomEventFilter() { - // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18) - // Intercept `mousedown` and check if there is an orphaned zoom gesture. - // This can happen if a previous `mousedown` occurred without a `mouseup`. - // If we detect this, dispatch `mouseup` to complete the orphaned gesture, - // so that d3-zoom won't stop propagation of new `mousedown` events. - if (event.type === 'mousedown') { - var hasOrphan = false; - var listeners = window.__on; - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - if (listener.name === 'zoom' && listener.type === 'mouseup') { - hasOrphan = true; - break; - } - } - if (hasOrphan) { - var event$$1 = window.CustomEvent; - if (event$$1) { - event$$1 = new event$$1('mouseup'); - } else { - event$$1 = window.document.createEvent('Event'); - event$$1.initEvent('mouseup', false, false); - } - // Event needs to be dispatched with an event.view property. - event$$1.view = window; - window.dispatchEvent(event$$1); - } - } + background.baseLayerSource = function(d) { + if (!arguments.length) return baseLayer.source(); - return event.button !== 2; // ignore right clicks - } + // test source against OSM imagery blacklists.. + var osm = context.connection(); + if (!osm) return background; + var blacklists = context.connection().imageryBlacklists(); - function ztok(z) { - return 256 * Math.pow(2, z); - } + var template = d.template(), + fail = false, + tested = 0, + regex, i; - function ktoz(k) { - return Math.max(Math.log(k) / Math.LN2 - 8, 0); - } + for (i = 0; i < blacklists.length; i++) { + try { + regex = new RegExp(blacklists[i]); + fail = regex.test(template); + tested++; + if (fail) break; + } catch (e) { + /* noop */ + } + } - function pxCenter() { - return [dimensions[0] / 2, dimensions[1] / 2]; - } + // ensure at least one test was run. + if (!tested) { + regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'); + fail = regex.test(template); + } + baseLayer.source(!fail ? d : background.findSource('none')); + dispatch$$1.call('change'); + background.updateImagery(); + return background; + }; - function drawVector(difference, extent) { - var mode = context.mode(); - var graph = context.graph(); - var features = context.features(); - var all = context.intersects(map.extent()); - var fullRedraw = false; - var data; - var filter; - if (difference) { - var complete = difference.complete(map.extent()); - data = compact(values$1(complete)); - filter = function(d) { return d.id in complete; }; - features.clear(data); + background.findSource = function(id) { + return find$1(_backgroundSources, function(d) { + return d.id && d.id === id; + }); + }; - } else { - // force a full redraw if gatherStats detects that a feature - // should be auto-hidden (e.g. points or buildings).. - if (features.gatherStats(all, graph, dimensions)) { - extent = undefined; - } - if (extent) { - data = context.intersects(map.extent().intersection(extent)); - var set$$1 = set$2(map$3(data, 'id')); - filter = function(d) { return set$$1.has(d.id); }; + background.bing = function() { + background.baseLayerSource(background.findSource('Bing')); + }; - } else { - data = all; - fullRedraw = true; - filter = utilFunctor(true); - } - } - data = features.filter(data, graph); + background.showsLayer = function(d) { + return d.id === baseLayer.source().id || + _overlayLayers.some(function(layer) { return d.id === layer.source().id; }); + }; - if (mode && mode.id === 'select') { - // update selected vertices - the user might have just double-clicked a way, - // creating a new vertex, triggering a partial redraw without a mode change - surface.selectAll('.data-layer-osm') - .call(drawVertices.drawSelected, graph, map.extent()); - } - surface.selectAll('.data-layer-osm') - .call(drawVertices, graph, data, filter, map.extent(), fullRedraw) - .call(drawLines, graph, data, filter) - .call(drawAreas, graph, data, filter) - .call(drawMidpoints, graph, data, filter, map.trimmedExtent()) - .call(drawLabels, graph, data, filter, dimensions, fullRedraw) - .call(drawPoints, graph, data, filter); + background.overlayLayerSources = function() { + return _overlayLayers.map(function (l) { return l.source(); }); + }; - dispatch$$1.call('drawn', this, {full: true}); - } + background.toggleOverlayLayer = function(d) { + var layer; - function editOff() { - context.features().resetStats(); - surface.selectAll('.layer-osm *').remove(); + for (var i = 0; i < _overlayLayers.length; i++) { + layer = _overlayLayers[i]; + if (layer.source() === d) { + _overlayLayers.splice(i, 1); + dispatch$$1.call('change'); + background.updateImagery(); + return; + } + } - var mode = context.mode(); - if (mode && mode.id !== 'save') { - context.enter(modeBrowse(context)); - } + layer = rendererTileLayer(context) + .source(d) + .projection(context.projection) + .dimensions(baseLayer.dimensions() + ); - dispatch$$1.call('drawn', this, {full: true}); - } + _overlayLayers.push(layer); + dispatch$$1.call('change'); + background.updateImagery(); + }; - function dblClick() { - if (!dblclickEnabled) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - } + background.nudge = function(d, zoom) { + baseLayer.source().nudge(d, zoom); + dispatch$$1.call('change'); + background.updateImagery(); + return background; + }; - function zoomPan(manualEvent) { - var event$$1 = (manualEvent || event); - var source = event$$1.sourceEvent; - var eventTransform = event$$1.transform; + background.offset = function(d) { + if (!arguments.length) return baseLayer.source().offset(); + baseLayer.source().offset(d); + dispatch$$1.call('change'); + background.updateImagery(); + return background; + }; - if (transformStart.x === eventTransform.x && - transformStart.y === eventTransform.y && - transformStart.k === eventTransform.k) { - return; // no change - } - // Normalize mousewheel - #3029 - // If wheel delta is provided in LINE units, recalculate it in PIXEL units - // We are essentially redoing the calculations that occur here: - // https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203 - // See this for more info: - // https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js - if (source && source.type === 'wheel' && source.deltaMode === 1 /* LINE */) { - // pick sensible scroll amount if user scrolling fast or slow.. - var lines = Math.abs(source.deltaY); - var scroll = lines > 2 ? 40 : lines * 10; - - var t0 = transformed ? transformLast : transformStart; - var p0 = mouse(source); - var p1 = t0.invert(p0); - var k2 = t0.k * Math.pow(2, -source.deltaY * scroll / 500); - var x2 = p0[0] - p1[0] * k2; - var y2 = p0[1] - p1[1] * k2; - - eventTransform = identity$7.translate(x2,y2).scale(k2); - _selection.node().__zoom = eventTransform; - } + background.brightness = function(d) { + if (!arguments.length) return _brightness; + _brightness = d; + if (context.mode()) dispatch$$1.call('change'); + return background; + }; - if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) { - surface.interrupt(); - uiFlash().text(t('cannot_zoom'))(); - setZoom(context.minEditableZoom(), true); - scheduleRedraw(); - dispatch$$1.call('move', this, map); - return; - } - projection.transform(eventTransform); + background.contrast = function(d) { + if (!arguments.length) return _contrast; + _contrast = d; + if (context.mode()) dispatch$$1.call('change'); + return background; + }; - var scale = eventTransform.k / transformStart.k; - var tX = (eventTransform.x / scale - transformStart.x) * scale; - var tY = (eventTransform.y / scale - transformStart.y) * scale; - if (context.inIntro()) { - curtainProjection.transform({ - x: eventTransform.x - tX, - y: eventTransform.y - tY, - k: eventTransform.k - }); - } + background.saturation = function(d) { + if (!arguments.length) return _saturation; + _saturation = d; + if (context.mode()) dispatch$$1.call('change'); + return background; + }; - if (source) mousemove = event$$1; - transformed = true; - transformLast = eventTransform; - utilSetTransform(supersurface, tX, tY, scale); - scheduleRedraw(); - dispatch$$1.call('move', this, map); - } + background.sharpness = function(d) { + if (!arguments.length) return _sharpness; + _sharpness = d; + if (context.mode()) dispatch$$1.call('change'); + return background; + }; - function resetTransform() { - if (!transformed) return false; + background.init = function() { + function parseMap(qmap) { + if (!qmap) return false; + var args = qmap.split('/').map(Number); + if (args.length < 3 || args.some(isNaN)) return false; + return geoExtent$$1([args[2], args[1]]); + } - // deprecation warning - Radial Menu to be removed in iD v3 - surface.selectAll('.edit-menu, .radial-menu').interrupt().remove(); - utilSetTransform(supersurface, 0, 0); - transformed = false; - if (context.inIntro()) { - curtainProjection.transform(projection.transform()); - } - return true; - } + var dataImagery = data.imagery || [], + q = utilStringQs(window.location.hash.substring(1)), + requested = q.background || q.layer, + extent = parseMap(q.map), + first, + best; + + // Add all the available imagery sources + _backgroundSources = dataImagery.map(function(source) { + if (source.type === 'bing') { + return rendererBackgroundSource.Bing(source, dispatch$$1); + } else if (/^EsriWorldImagery/.test(source.id)) { + return rendererBackgroundSource.Esri(source); + } else { + return rendererBackgroundSource(source); + } + }); + first = _backgroundSources.length && _backgroundSources[0]; - function redraw(difference, extent) { - if (surface.empty() || !redrawEnabled) return; + // Add 'None' + _backgroundSources.unshift(rendererBackgroundSource.None()); - // If we are in the middle of a zoom/pan, we can't do differenced redraws. - // It would result in artifacts where differenced entities are redrawn with - // one transform and unchanged entities with another. - if (resetTransform()) { - difference = extent = undefined; - } + // Add 'Custom' + var template = context.storage('background-custom-template') || ''; + var custom = rendererBackgroundSource.Custom(template); + _backgroundSources.unshift(custom); - var z = String(~~map.zoom()); - if (surface.attr('data-zoom') !== z) { - surface.attr('data-zoom', z) - .classed('low-zoom', z <= 16); - } - if (!difference) { - supersurface.call(context.background()); - } + // Decide which background layer to display + if (!requested && extent) { + best = find$1(this.sources(extent), function(s) { return s.best(); }); + } + if (requested && requested.indexOf('custom:') === 0) { + template = requested.replace(/^custom:/, ''); + background.baseLayerSource(custom.template(template)); + context.storage('background-custom-template', template); + } else { + background.baseLayerSource( + background.findSource(requested) || + best || + background.findSource(context.storage('background-last-used')) || + background.findSource('Bing') || + first || + background.findSource('none') + ); + } - wrapper - .call(drawLayers); + var locator = find$1(_backgroundSources, function(d) { + return d.overlay && d.default; + }); - // OSM - if (map.editable()) { - context.loadTiles(projection, dimensions); - drawVector(difference, extent); - } else { - editOff(); - } + if (locator) { + background.toggleOverlayLayer(locator); + } - transformStart = projection.transform(); + var overlays = (q.overlays || '').split(','); + overlays.forEach(function(overlay) { + overlay = background.findSource(overlay); + if (overlay) { + background.toggleOverlayLayer(overlay); + } + }); - return map; - } + if (q.gpx) { + var gpx = context.layers().layer('gpx'); + if (gpx) { + gpx.url(q.gpx); + } + } + if (q.offset) { + var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) { + return !isNaN(n) && n; + }); + if (offset.length === 2) { + background.offset(geoMetersToOffset(offset)); + } + } + }; - var immediateRedraw = function(difference, extent) { - if (!difference && !extent) cancelPendingRedraw(); - redraw(difference, extent); - }; + return utilRebind(background, dispatch$$1, 'on'); + } - function pointLocation(p) { - var translate = projection.translate(), - scale = projection.scale() * 2 * Math.PI; - return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale]; - } + function rendererFeatures(context) { + var traffic_roads = { + 'motorway': true, + 'motorway_link': true, + 'trunk': true, + 'trunk_link': true, + 'primary': true, + 'primary_link': true, + 'secondary': true, + 'secondary_link': true, + 'tertiary': true, + 'tertiary_link': true, + 'residential': true, + 'unclassified': true, + 'living_street': true + }; + var service_roads = { + 'service': true, + 'road': true, + 'track': true + }; - function locationPoint(l) { - var translate = projection.translate(), - scale = projection.scale() * 2 * Math.PI; - return [l[0] * scale + translate[0], l[1] * scale + translate[1]]; - } + var paths = { + 'path': true, + 'footway': true, + 'cycleway': true, + 'bridleway': true, + 'steps': true, + 'pedestrian': true, + 'corridor': true + }; + var past_futures = { + 'proposed': true, + 'construction': true, + 'abandoned': true, + 'dismantled': true, + 'disused': true, + 'razed': true, + 'demolished': true, + 'obliterated': true + }; - map.mouse = function() { - var event$$1 = mousemove || event; - if (event$$1) { - var s; - while ((s = event$$1.sourceEvent)) { event$$1 = s; } - return mouse(event$$1); - } - return null; - }; + var dispatch$$1 = dispatch('change', 'redraw'), + _cullFactor = 1, + _cache = {}, + _features = {}, + _stats = {}, + _keys = [], + _hidden = []; + + + function update() { + if (!window.mocha) { + var q = utilStringQs(window.location.hash.substring(1)); + var disabled = features.disabled(); + if (disabled.length) { + q.disable_features = disabled.join(','); + } else { + delete q.disable_features; + } + window.location.replace('#' + utilQsString(q, true)); + context.storage('disabled-features', disabled.join(',')); + } + _hidden = features.hidden(); + dispatch$$1.call('change'); + dispatch$$1.call('redraw'); + } - // returns Lng/Lat - map.mouseCoordinates = function() { - var coord = map.mouse() || pxCenter(); - return projection.invert(coord); - }; + function defineFeature(k, filter, max) { + var isEnabled = true; + + _keys.push(k); + _features[k] = { + filter: filter, + enabled: isEnabled, // whether the user wants it enabled.. + count: 0, + currentMax: (max || Infinity), + defaultMax: (max || Infinity), + enable: function() { this.enabled = true; this.currentMax = this.defaultMax; }, + disable: function() { this.enabled = false; this.currentMax = 0; }, + hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; }, + autoHidden: function() { return this.hidden() && this.currentMax > 0; } + }; + } - map.dblclickEnable = function(_) { - if (!arguments.length) return dblclickEnabled; - dblclickEnabled = _; - return map; - }; + defineFeature('points', function isPoint(entity, resolver, geometry) { + return geometry === 'point'; + }, 200); + defineFeature('traffic_roads', function isTrafficRoad(entity) { + return traffic_roads[entity.tags.highway]; + }); - map.redrawEnable = function(_) { - if (!arguments.length) return redrawEnabled; - redrawEnabled = _; - return map; - }; + defineFeature('service_roads', function isServiceRoad(entity) { + return service_roads[entity.tags.highway]; + }); + defineFeature('paths', function isPath(entity) { + return paths[entity.tags.highway]; + }); - function setTransform(t2, duration, force) { - var t$$1 = projection.transform(); - if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) { - return false; - } + defineFeature('buildings', function isBuilding(entity) { + return ( + !!entity.tags['building:part'] || + (!!entity.tags.building && entity.tags.building !== 'no') || + entity.tags.amenity === 'shelter' || + entity.tags.parking === 'multi-storey' || + entity.tags.parking === 'sheds' || + entity.tags.parking === 'carports' || + entity.tags.parking === 'garage_boxes' + ); + }, 250); - if (duration) { - _selection - .transition() - .duration(duration) - .on('start', function() { map.startEase(); }) - .call(zoom$$1.transform, identity$7.translate(t2.x, t2.y).scale(t2.k)); - } else { - projection.transform(t2); - transformStart = t2; - _selection.call(zoom$$1.transform, transformStart); - } - } + defineFeature('landuse', function isLanduse(entity, resolver, geometry) { + return geometry === 'area' && + !_features.buildings.filter(entity) && + !_features.water.filter(entity); + }); + defineFeature('boundaries', function isBoundary(entity) { + return ( + !!entity.tags.boundary + ) && !( + traffic_roads[entity.tags.highway] || + service_roads[entity.tags.highway] || + paths[entity.tags.highway] + ); + }); - function setZoom(z2, force, duration) { - if (z2 === map.zoom() && !force) { - return false; - } + defineFeature('water', function isWater(entity) { + return ( + !!entity.tags.waterway || + entity.tags.natural === 'water' || + entity.tags.natural === 'coastline' || + entity.tags.natural === 'bay' || + entity.tags.landuse === 'pond' || + entity.tags.landuse === 'basin' || + entity.tags.landuse === 'reservoir' || + entity.tags.landuse === 'salt_pond' + ); + }); - var k = projection.scale(), - k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI), - center = pxCenter(), - l = pointLocation(center); + defineFeature('rail', function isRail(entity) { + return ( + !!entity.tags.railway || + entity.tags.landuse === 'railway' + ) && !( + traffic_roads[entity.tags.highway] || + service_roads[entity.tags.highway] || + paths[entity.tags.highway] + ); + }); - projection.scale(k2); + defineFeature('power', function isPower(entity) { + return !!entity.tags.power; + }); - var t$$1 = projection.translate(); - l = locationPoint(l); + // contains a past/future tag, but not in active use as a road/path/cycleway/etc.. + defineFeature('past_future', function isPastFuture(entity) { + if ( + traffic_roads[entity.tags.highway] || + service_roads[entity.tags.highway] || + paths[entity.tags.highway] + ) { return false; } - t$$1[0] += center[0] - l[0]; - t$$1[1] += center[1] - l[1]; + var strings = Object.keys(entity.tags); - if (duration) { - projection.scale(k); // reset scale - _selection - .transition() - .duration(duration) - .on('start', function() { map.startEase(); }) - .call(zoom$$1.transform, identity$7.translate(t$$1[0], t$$1[1]).scale(k2)); - } else { - projection.translate(t$$1); - transformStart = projection.transform(); - _selection.call(zoom$$1.transform, transformStart); - } + for (var i = 0; i < strings.length; i++) { + var s = strings[i]; + if (past_futures[s] || past_futures[entity.tags[s]]) { return true; } + } + return false; + }); - return true; - } + // Lines or areas that don't match another feature filter. + // IMPORTANT: The 'others' feature must be the last one defined, + // so that code in getMatches can skip this test if `hasMatch = true` + defineFeature('others', function isOther(entity, resolver, geometry) { + return (geometry === 'line' || geometry === 'area'); + }); - function setCenter(loc2, duration) { - var c = map.center(); - if (loc2[0] === c[0] && loc2[1] === c[1]) { - return false; - } + function features() {} - var t$$1 = projection.translate(), - k = projection.scale(), - pxC = pxCenter(), - ll = projection(loc2); - t$$1[0] = t$$1[0] - ll[0] + pxC[0]; - t$$1[1] = t$$1[1] - ll[1] + pxC[1]; + features.features = function() { + return _features; + }; - if (duration) { - _selection - .transition() - .duration(duration) - .on('start', function() { map.startEase(); }) - .call(zoom$$1.transform, identity$7.translate(t$$1[0], t$$1[1]).scale(k)); - } else { - projection.translate(t$$1); - transformStart = projection.transform(); - _selection.call(zoom$$1.transform, transformStart); - } - return true; - } + features.keys = function() { + return _keys; + }; - map.pan = function(delta, duration) { - var t$$1 = projection.translate(), - k = projection.scale(); + features.enabled = function(k) { + if (!arguments.length) { + return _keys.filter(function(k) { return _features[k].enabled; }); + } + return _features[k] && _features[k].enabled; + }; - t$$1[0] += delta[0]; - t$$1[1] += delta[1]; - if (duration) { - _selection - .transition() - .duration(duration) - .on('start', function() { map.startEase(); }) - .call(zoom$$1.transform, identity$7.translate(t$$1[0], t$$1[1]).scale(k)); - } else { - projection.translate(t$$1); - transformStart = projection.transform(); - _selection.call(zoom$$1.transform, transformStart); - dispatch$$1.call('move', this, map); - immediateRedraw(); - } + features.disabled = function(k) { + if (!arguments.length) { + return _keys.filter(function(k) { return !_features[k].enabled; }); + } + return _features[k] && !_features[k].enabled; + }; - return map; - }; + features.hidden = function(k) { + if (!arguments.length) { + return _keys.filter(function(k) { return _features[k].hidden(); }); + } + return _features[k] && _features[k].hidden(); + }; - map.dimensions = function(_) { - if (!arguments.length) return dimensions; - var center = map.center(); - dimensions = _; - drawLayers.dimensions(dimensions); - context.background().dimensions(dimensions); - projection.clipExtent([[0, 0], dimensions]); - mouse = utilFastMouse(supersurface.node()); - setCenter(center); - scheduleRedraw(); - return map; - }; + features.autoHidden = function(k) { + if (!arguments.length) { + return _keys.filter(function(k) { return _features[k].autoHidden(); }); + } + return _features[k] && _features[k].autoHidden(); + }; - function zoomIn(delta) { - setZoom(~~map.zoom() + delta, true, 250); - } + features.enable = function(k) { + if (_features[k] && !_features[k].enabled) { + _features[k].enable(); + update(); + } + }; - function zoomOut(delta) { - setZoom(~~map.zoom() - delta, true, 250); - } - map.zoomIn = function() { zoomIn(1); }; - map.zoomInFurther = function() { zoomIn(4); }; + features.disable = function(k) { + if (_features[k] && _features[k].enabled) { + _features[k].disable(); + update(); + } + }; - map.zoomOut = function() { zoomOut(1); }; - map.zoomOutFurther = function() { zoomOut(4); }; + features.toggle = function(k) { + if (_features[k]) { + (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k])); + update(); + } + }; - map.center = function(loc2) { - if (!arguments.length) { - return projection.invert(pxCenter()); - } - if (setCenter(loc2)) { - dispatch$$1.call('move', this, map); - } + features.resetStats = function() { + for (var i = 0; i < _keys.length; i++) { + _features[_keys[i]].count = 0; + } + dispatch$$1.call('change'); + }; - scheduleRedraw(); - return map; - }; + features.gatherStats = function(d, resolver, dimensions) { + var needsRedraw = false, + type = groupBy(d, function(ent) { return ent.type; }), + entities = [].concat(type.relation || [], type.way || [], type.node || []), + currHidden, geometry, matches, i, j; - map.zoom = function(z2) { - if (!arguments.length) { - return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0); - } + for (i = 0; i < _keys.length; i++) { + _features[_keys[i]].count = 0; + } - if (z2 < minzoom) { - surface.interrupt(); - uiFlash().text(t('cannot_zoom'))(); - z2 = context.minEditableZoom(); - } + // adjust the threshold for point/building culling based on viewport size.. + // a _cullFactor of 1 corresponds to a 1000x1000px viewport.. + _cullFactor = dimensions[0] * dimensions[1] / 1000000; + + for (i = 0; i < entities.length; i++) { + geometry = entities[i].geometry(resolver); + if (!(geometry === 'vertex' || geometry === 'relation')) { + matches = Object.keys(features.getMatches(entities[i], resolver, geometry)); + for (j = 0; j < matches.length; j++) { + _features[matches[j]].count++; + } + } + } - if (setZoom(z2)) { - dispatch$$1.call('move', this, map); - } + currHidden = features.hidden(); + if (currHidden !== _hidden) { + _hidden = currHidden; + needsRedraw = true; + dispatch$$1.call('change'); + } - scheduleRedraw(); - return map; - }; + return needsRedraw; + }; - map.zoomTo = function(entity, zoomLimits) { - var extent = entity.extent(context.graph()); - if (!isFinite(extent.area())) return; + features.stats = function() { + for (var i = 0; i < _keys.length; i++) { + _stats[_keys[i]] = _features[_keys[i]].count; + } - var z2 = map.trimmedExtentZoom(extent); - zoomLimits = zoomLimits || [context.minEditableZoom(), 20]; - map.centerZoom(extent.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1])); - }; + return _stats; + }; - map.centerZoom = function(loc2, z2) { - var centered = setCenter(loc2), - zoomed = setZoom(z2); + features.clear = function(d) { + for (var i = 0; i < d.length; i++) { + features.clearEntity(d[i]); + } + }; - if (centered || zoomed) { - dispatch$$1.call('move', this, map); - } - scheduleRedraw(); - return map; - }; + features.clearEntity = function(entity) { + delete _cache[osmEntity$$1.key(entity)]; + }; - map.centerEase = function(loc2, duration) { - duration = duration || 250; - setCenter(loc2, duration); - return map; - }; + features.reset = function() { + _cache = {}; + }; - map.zoomEase = function(z2, duration) { - duration = duration || 250; - setZoom(z2, false, duration); - return map; - }; + features.getMatches = function(entity, resolver, geometry) { + if (geometry === 'vertex' || geometry === 'relation') return {}; + var ent = osmEntity$$1.key(entity); + if (!_cache[ent]) { + _cache[ent] = {}; + } - map.transformEase = function(t2, duration) { - duration = duration || 250; - setTransform(t2, duration, false); - return map; - }; + if (!_cache[ent].matches) { + var matches = {}, + hasMatch = false; + + for (var i = 0; i < _keys.length; i++) { + if (_keys[i] === 'others') { + if (hasMatch) continue; + + // Multipolygon members: + // If an entity... + // 1. is a way that hasn't matched other 'interesting' feature rules, + // 2. and it belongs to a single parent multipolygon relation + // ...then match whatever feature rules the parent multipolygon has matched. + // see #2548, #2887 + // + // IMPORTANT: + // For this to work, getMatches must be called on relations before ways. + // + if (entity.type === 'way') { + var parents = features.getParents(entity, resolver, geometry); + if (parents.length === 1 && parents[0].isMultipolygon()) { + var pkey = osmEntity$$1.key(parents[0]); + if (_cache[pkey] && _cache[pkey].matches) { + matches = clone(_cache[pkey].matches); + continue; + } + } + } + } + + if (_features[_keys[i]].filter(entity, resolver, geometry)) { + matches[_keys[i]] = hasMatch = true; + } + } + _cache[ent].matches = matches; + } + return _cache[ent].matches; + }; - map.startEase = function() { - utilBindOnce(surface, 'mousedown.ease', function() { - map.cancelEase(); - }); - return map; - }; + features.getParents = function(entity, resolver, geometry) { + if (geometry === 'point') return []; - map.cancelEase = function() { - _selection.interrupt(); - return map; - }; + var ent = osmEntity$$1.key(entity); + if (!_cache[ent]) { + _cache[ent] = {}; + } + if (!_cache[ent].parents) { + var parents = []; + if (geometry === 'vertex') { + parents = resolver.parentWays(entity); + } else { // 'line', 'area', 'relation' + parents = resolver.parentRelations(entity); + } + _cache[ent].parents = parents; + } + return _cache[ent].parents; + }; - map.extent = function(_) { - if (!arguments.length) { - return new geoExtent$$1(projection.invert([0, dimensions[1]]), - projection.invert([dimensions[0], 0])); - } else { - var extent = geoExtent$$1(_); - map.centerZoom(extent.center(), map.extentZoom(extent)); - } - }; + features.isHiddenFeature = function(entity, resolver, geometry) { + if (!_hidden.length) return false; + if (!entity.version) return false; - map.trimmedExtent = function(_) { - if (!arguments.length) { - var headerY = 60, footerY = 30, pad = 10; - return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]), - projection.invert([dimensions[0] - pad, headerY + pad])); - } else { - var extent = geoExtent$$1(_); - map.centerZoom(extent.center(), map.trimmedExtentZoom(extent)); - } - }; + var matches = features.getMatches(entity, resolver, geometry); + for (var i = 0; i < _hidden.length; i++) { + if (matches[_hidden[i]]) return true; + } + return false; + }; - function calcZoom(extent, dim) { - var tl = projection([extent[0][0], extent[1][1]]), - br = projection([extent[1][0], extent[0][1]]); - // Calculate maximum zoom that fits extent - var hFactor = (br[0] - tl[0]) / dim[0], - vFactor = (br[1] - tl[1]) / dim[1], - hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2, - vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2, - newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff); + features.isHiddenChild = function(entity, resolver, geometry) { + if (!_hidden.length) return false; + if (!entity.version || geometry === 'point') return false; - return newZoom; - } + var parents = features.getParents(entity, resolver, geometry); + if (!parents.length) return false; + for (var i = 0; i < parents.length; i++) { + if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) { + return false; + } + } + return true; + }; - map.extentZoom = function(_) { - return calcZoom(geoExtent$$1(_), dimensions); - }; + features.hasHiddenConnections = function(entity, resolver) { + if (!_hidden.length) return false; + var childNodes, connections; - map.trimmedExtentZoom = function(_) { - var trimY = 120, trimX = 40, - trimmed = [dimensions[0] - trimX, dimensions[1] - trimY]; - return calcZoom(geoExtent$$1(_), trimmed); - }; + if (entity.type === 'midpoint') { + childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])]; + connections = []; + } else { + childNodes = entity.nodes ? resolver.childNodes(entity) : []; + connections = features.getParents(entity, resolver, entity.geometry(resolver)); + } + // gather ways connected to child nodes.. + connections = reduce(childNodes, function(result, e) { + return resolver.isShared(e) ? union(result, resolver.parentWays(e)) : result; + }, connections); - map.editable = function() { - var osmLayer = surface.selectAll('.data-layer-osm'); - if (!osmLayer.empty() && osmLayer.classed('disabled')) return false; + return connections.length ? some(connections, function(e) { + return features.isHidden(e, resolver, e.geometry(resolver)); + }) : false; + }; - return map.zoom() >= context.minEditableZoom(); - }; + features.isHidden = function(entity, resolver, geometry) { + if (!_hidden.length) return false; + if (!entity.version) return false; - map.minzoom = function(_) { - if (!arguments.length) return minzoom; - minzoom = _; - return map; - }; + var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature); + return fn(entity, resolver, geometry); + }; - map.layers = drawLayers; - - - return utilRebind(map, dispatch$$1, 'on'); -} - -function uiMapInMap(context) { - - function map_in_map(selection$$1) { - var backgroundLayer = rendererTileLayer(context); - var overlayLayers = {}; - var projection$$1 = geoRawMercator(); - var gpxLayer = svgGpx$$1(projection$$1, context).showLabels(false); - var debugLayer = svgDebug$$1(projection$$1, context); - var zoom$$1 = d3_zoom() - .scaleExtent([geoZoomToScale(0.5), geoZoomToScale(24)]) - .on('start', zoomStarted) - .on('zoom', zoomed) - .on('end', zoomEnded); - var isTransformed = false; - var isHidden = true; - var skipEvents = false; - var gesture = null; - var zDiff = 6; // by default, minimap renders at (main zoom - 6) - var wrap = d3_select(null); - var tiles = d3_select(null); - var viewport = d3_select(null); - var tStart; // transform at start of gesture - var tCurr; // transform at most recent event - var timeoutId; - - - function zoomStarted() { - if (skipEvents) return; - tStart = tCurr = projection$$1.transform(); - gesture = null; - } + features.filter = function(d, resolver) { + if (!_hidden.length) return d; + + var result = []; + for (var i = 0; i < d.length; i++) { + var entity = d[i]; + if (!features.isHidden(entity, resolver, entity.geometry(resolver))) { + result.push(entity); + } + } + return result; + }; - function zoomed() { - if (skipEvents) return; + features.init = function() { + var storage = context.storage('disabled-features'); + if (storage) { + var storageDisabled = storage.replace(/;/g, ',').split(','); + storageDisabled.forEach(features.disable); + } - var x = event.transform.x; - var y = event.transform.y; - var k = event.transform.k; - var isZooming = (k !== tStart.k); - var isPanning = (x !== tStart.x || y !== tStart.y); + var q = utilStringQs(window.location.hash.substring(1)); + if (q.disable_features) { + var hashDisabled = q.disable_features.replace(/;/g, ',').split(','); + hashDisabled.forEach(features.disable); + } + }; - if (!isZooming && !isPanning) { - return; // no change - } + return utilRebind(features, dispatch$$1, 'on'); + } - // lock in either zooming or panning, don't allow both in minimap. - if (!gesture) { - gesture = isZooming ? 'zoom' : 'pan'; - } + function utilBindOnce(target, type, listener, capture) { + var typeOnce = type + '.once'; + function one() { + target.on(typeOnce, null); + listener.apply(this, arguments); + } + target.on(typeOnce, one, capture); + return this; + } - var tMini = projection$$1.transform(); - var tX, tY, scale; + // constants + var TAU$1 = 2 * Math.PI; + var TILESIZE = 256; + var kMin = geoZoomToScale(2, TILESIZE); + var kMax = geoZoomToScale(24, TILESIZE); + + + function rendererMap(context) { + var dispatch$$1 = dispatch('move', 'drawn'); + var projection = context.projection; + var curtainProjection = context.curtainProjection; + var drawLayers = svgLayers(projection, context); + var drawPoints = svgPoints$$1(projection, context); + var drawVertices = svgVertices$$1(projection, context); + var drawLines = svgLines$$1(projection, context); + var drawAreas = svgAreas$$1(projection, context); + var drawMidpoints = svgMidpoints$$1(projection, context); + var drawLabels = svgLabels(projection, context); + + var _selection = select(null); + var supersurface = select(null); + var wrapper = select(null); + var surface = select(null); + + var dimensions = [1, 1]; + var dblclickEnabled = true; + var redrawEnabled = true; + var transformStart = projection.transform(); + var transformLast; + var transformed = false; + var minzoom = 0; + var mouse$$1; + var mousemove; + + var zoom$$1 = d3_zoom() + .scaleExtent([kMin, kMax]) + .interpolate(interpolate) + .filter(zoomEventFilter) + .on('zoom', zoomPan); + + var scheduleRedraw = throttle(redraw, 750); + // var isRedrawScheduled = false; + // var pendingRedrawCall; + // function scheduleRedraw() { + // // Only schedule the redraw if one has not already been set. + // if (isRedrawScheduled) return; + // isRedrawScheduled = true; + // var that = this; + // var args = arguments; + // pendingRedrawCall = window.requestIdleCallback(function () { + // // Reset the boolean so future redraws can be set. + // isRedrawScheduled = false; + // redraw.apply(that, args); + // }, { timeout: 1400 }); + // } + + function cancelPendingRedraw() { + scheduleRedraw.cancel(); + // isRedrawScheduled = false; + // window.cancelIdleCallback(pendingRedrawCall); + } - if (gesture === 'zoom') { - var dMini = utilGetDimensions(wrap); - var cMini = geoVecScale(dMini, 0.5); - scale = k / tMini.k; - tX = (cMini[0] / scale - cMini[0]) * scale; - tY = (cMini[1] / scale - cMini[1]) * scale; - } else { - k = tMini.k; - scale = 1; - tX = x - tMini.x; - tY = y - tMini.y; - } - utilSetTransform(tiles, tX, tY, scale); - utilSetTransform(viewport, 0, 0, scale); - isTransformed = true; - tCurr = identity$7.translate(x, y).scale(k); + function map(selection$$1) { + _selection = selection$$1; - var zMain = geoScaleToZoom(context.projection.scale()); - var zMini = geoScaleToZoom(k); + context + .on('change.map', immediateRedraw); - zDiff = zMain - zMini; + var osm = context.connection(); + if (osm) { + osm.on('change.map', immediateRedraw); + } - queueRedraw(); - } + context.history() + .on('change.map', immediateRedraw) + .on('undone.map redone.map', function(stack) { + var mode = context.mode().id; + if (mode !== 'browse' && mode !== 'select') return; + + var followSelected = false; + if (Array.isArray(stack.selectedIDs)) { + followSelected = (stack.selectedIDs.length === 1 && stack.selectedIDs[0][0] === 'n'); + context.enter( + modeSelect(context, stack.selectedIDs).follow(followSelected) + ); + } + if (!followSelected && stack.transform) { + map.transformEase(stack.transform); + } + }); + + context.background() + .on('change.map', immediateRedraw); + + context.features() + .on('redraw.map', immediateRedraw); + + drawLayers + .on('change.map', function() { + context.background().updateImagery(); + immediateRedraw(); + }); + + selection$$1 + .on('dblclick.map', dblClick) + .call(zoom$$1) + .call(zoom$$1.transform, projection.transform()); + + supersurface = selection$$1.append('div') + .attr('id', 'supersurface') + .call(utilSetTransform, 0, 0); + + // Need a wrapper div because Opera can't cope with an absolutely positioned + // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16 + wrapper = supersurface + .append('div') + .attr('class', 'layer layer-data'); + + map.surface = surface = wrapper + .call(drawLayers) + .selectAll('.surface') + .attr('id', 'surface'); + + surface + .call(drawLabels.observe) + .on('mousedown.zoom', function() { + if (event.button === 2) { + event.stopPropagation(); + } + }, true) + .on('mouseup.zoom', function() { + if (resetTransform()) immediateRedraw(); + }) + .on('mousemove.map', function() { + mousemove = event; + }) + .on('mouseover.vertices', function() { + if (map.editable() && !transformed) { + var hover = event.target.__data__; + surface.selectAll('.data-layer-osm') + .call(drawVertices.drawHover, context.graph(), hover, map.extent()); + dispatch$$1.call('drawn', this, { full: false }); + } + }) + .on('mouseout.vertices', function() { + if (map.editable() && !transformed) { + var hover = event.relatedTarget && event.relatedTarget.__data__; + surface.selectAll('.data-layer-osm') + .call(drawVertices.drawHover, context.graph(), hover, map.extent()); + dispatch$$1.call('drawn', this, { full: false }); + } + }); + + supersurface + .call(context.background()); + + context.on('enter.map', function() { + if (map.editable() && !transformed) { + + // redraw immediately any objects affected by a change in selectedIDs. + var graph = context.graph(); + var selectedAndParents = {}; + context.selectedIDs().forEach(function(id) { + var entity = graph.hasEntity(id); + if (entity) { + selectedAndParents[entity.id] = entity; + if (entity.type === 'node') { + graph.parentWays(entity).forEach(function(parent) { + selectedAndParents[parent.id] = parent; + }); + } + } + }); + var data = values$1(selectedAndParents); + var filter = function(d) { return d.id in selectedAndParents; }; + + data = context.features().filter(data, graph); + + surface.selectAll('.data-layer-osm') + .call(drawVertices.drawSelected, graph, map.extent()) + .call(drawLines, graph, data, filter) + .call(drawAreas, graph, data, filter) + .call(drawMidpoints, graph, data, filter, map.trimmedExtent()); + + dispatch$$1.call('drawn', this, { full: false }); + + + // redraw everything else later + scheduleRedraw(); + } + }); + map.dimensions(utilGetDimensions(selection$$1)); + } - function zoomEnded() { - if (skipEvents) return; - if (gesture !== 'pan') return; - updateProjection(); - gesture = null; - var dMini = utilGetDimensions(wrap); - var cMini = geoVecScale(dMini, 0.5); - context.map().center(projection$$1.invert(cMini)); // recenter main map.. - } + function zoomEventFilter() { + // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18) + // Intercept `mousedown` and check if there is an orphaned zoom gesture. + // This can happen if a previous `mousedown` occurred without a `mouseup`. + // If we detect this, dispatch `mouseup` to complete the orphaned gesture, + // so that d3-zoom won't stop propagation of new `mousedown` events. + if (event.type === 'mousedown') { + var hasOrphan = false; + var listeners = window.__on; + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + if (listener.name === 'zoom' && listener.type === 'mouseup') { + hasOrphan = true; + break; + } + } + if (hasOrphan) { + var event$$1 = window.CustomEvent; + if (event$$1) { + event$$1 = new event$$1('mouseup'); + } else { + event$$1 = window.document.createEvent('Event'); + event$$1.initEvent('mouseup', false, false); + } + // Event needs to be dispatched with an event.view property. + event$$1.view = window; + window.dispatchEvent(event$$1); + } + } + return event.button !== 2; // ignore right clicks + } - function updateProjection() { - var loc = context.map().center(); - var dMini = utilGetDimensions(wrap); - var cMini = geoVecScale(dMini, 0.5); - var tMain = context.projection.transform(); - var zMain = geoScaleToZoom(tMain.k); - var zMini = Math.max(zMain - zDiff, 0.5); - var kMini = geoZoomToScale(zMini); - projection$$1 - .translate([tMain.x, tMain.y]) - .scale(kMini); + function pxCenter() { + return [dimensions[0] / 2, dimensions[1] / 2]; + } - var point$$1 = projection$$1(loc); - var mouse = (gesture === 'pan') ? geoVecSubtract([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0]; - var xMini = cMini[0] - point$$1[0] + tMain.x + mouse[0]; - var yMini = cMini[1] - point$$1[1] + tMain.y + mouse[1]; - projection$$1 - .translate([xMini, yMini]) - .clipExtent([[0, 0], dMini]); + function drawVector(difference, extent) { + var mode = context.mode(); + var graph = context.graph(); + var features = context.features(); + var all = context.intersects(map.extent()); + var fullRedraw = false; + var data; + var filter; - tCurr = projection$$1.transform(); + if (difference) { + var complete = difference.complete(map.extent()); + data = compact(values$1(complete)); + filter = function(d) { return d.id in complete; }; + features.clear(data); - if (isTransformed) { - utilSetTransform(tiles, 0, 0); - utilSetTransform(viewport, 0, 0); - isTransformed = false; - } + } else { + // force a full redraw if gatherStats detects that a feature + // should be auto-hidden (e.g. points or buildings).. + if (features.gatherStats(all, graph, dimensions)) { + extent = undefined; + } + + if (extent) { + data = context.intersects(map.extent().intersection(extent)); + var set$$1 = set$2(map$3(data, 'id')); + filter = function(d) { return set$$1.has(d.id); }; + + } else { + data = all; + fullRedraw = true; + filter = utilFunctor(true); + } + } - zoom$$1 - .scaleExtent([geoZoomToScale(0.5), geoZoomToScale(zMain - 3)]); + data = features.filter(data, graph); - skipEvents = true; - wrap.call(zoom$$1.transform, tCurr); - skipEvents = false; - } + if (mode && mode.id === 'select') { + // update selected vertices - the user might have just double-clicked a way, + // creating a new vertex, triggering a partial redraw without a mode change + surface.selectAll('.data-layer-osm') + .call(drawVertices.drawSelected, graph, map.extent()); + } + surface.selectAll('.data-layer-osm') + .call(drawVertices, graph, data, filter, map.extent(), fullRedraw) + .call(drawLines, graph, data, filter) + .call(drawAreas, graph, data, filter) + .call(drawMidpoints, graph, data, filter, map.trimmedExtent()) + .call(drawLabels, graph, data, filter, dimensions, fullRedraw) + .call(drawPoints, graph, data, filter); - function redraw() { - clearTimeout(timeoutId); - if (isHidden) return; - - updateProjection(); - - var dMini = utilGetDimensions(wrap); - var zMini = geoScaleToZoom(projection$$1.scale()); - - // setup tile container - tiles = wrap - .selectAll('.map-in-map-tiles') - .data([0]); - - tiles = tiles.enter() - .append('div') - .attr('class', 'map-in-map-tiles') - .merge(tiles); - - // redraw background - backgroundLayer - .source(context.background().baseLayerSource()) - .projection(projection$$1) - .dimensions(dMini); - - var background = tiles - .selectAll('.map-in-map-background') - .data([0]); - - background.enter() - .append('div') - .attr('class', 'map-in-map-background') - .merge(background) - .call(backgroundLayer); - - - // redraw overlay - var overlaySources = context.background().overlayLayerSources(); - var activeOverlayLayers = []; - for (var i = 0; i < overlaySources.length; i++) { - if (overlaySources[i].validZoom(zMini)) { - if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context); - activeOverlayLayers.push(overlayLayers[i] - .source(overlaySources[i]) - .projection(projection$$1) - .dimensions(dMini)); - } - } + dispatch$$1.call('drawn', this, {full: true}); + } - var overlay = tiles - .selectAll('.map-in-map-overlay') - .data([0]); - overlay = overlay.enter() - .append('div') - .attr('class', 'map-in-map-overlay') - .merge(overlay); + function editOff() { + context.features().resetStats(); + surface.selectAll('.layer-osm *').remove(); + var mode = context.mode(); + if (mode && mode.id !== 'save') { + context.enter(modeBrowse(context)); + } - var overlays = overlay - .selectAll('div') - .data(activeOverlayLayers, function(d) { return d.source().name(); }); + dispatch$$1.call('drawn', this, {full: true}); + } - overlays.exit() - .remove(); - overlays = overlays.enter() - .append('div') - .merge(overlays) - .each(function(layer) { d3_select(this).call(layer); }); + function dblClick() { + if (!dblclickEnabled) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + } - var dataLayers = tiles - .selectAll('.map-in-map-data') - .data([0]); + function zoomPan(manualEvent) { + var event$$1 = (manualEvent || event); + var source = event$$1.sourceEvent; + var eventTransform = event$$1.transform; - dataLayers.exit() - .remove(); + if (transformStart.x === eventTransform.x && + transformStart.y === eventTransform.y && + transformStart.k === eventTransform.k) { + return; // no change + } - dataLayers = dataLayers.enter() - .append('svg') - .attr('class', 'map-in-map-data') - .merge(dataLayers) - .call(gpxLayer) - .call(debugLayer); + // Normalize mousewheel - #3029 + // If wheel delta is provided in LINE units, recalculate it in PIXEL units + // We are essentially redoing the calculations that occur here: + // https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203 + // See this for more info: + // https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js + if (source && source.type === 'wheel' && source.deltaMode === 1 /* LINE */) { + // pick sensible scroll amount if user scrolling fast or slow.. + var lines = Math.abs(source.deltaY); + var scroll = lines > 2 ? 40 : lines * 10; + + var t0 = transformed ? transformLast : transformStart; + var p0 = mouse$$1(source); + var p1 = t0.invert(p0); + var k2 = t0.k * Math.pow(2, -source.deltaY * scroll / 500); + var x2 = p0[0] - p1[0] * k2; + var y2 = p0[1] - p1[1] * k2; + + eventTransform = identity$7.translate(x2,y2).scale(k2); + _selection.node().__zoom = eventTransform; + } + if (geoScaleToZoom(eventTransform.k, TILESIZE) < minzoom) { + surface.interrupt(); + uiFlash().text(t('cannot_zoom'))(); + setZoom(context.minEditableZoom(), true); + scheduleRedraw(); + dispatch$$1.call('move', this, map); + return; + } - // redraw viewport bounding box - if (gesture !== 'pan') { - var getPath = d3_geoPath(projection$$1); - var bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] }; + projection.transform(eventTransform); - viewport = wrap.selectAll('.map-in-map-viewport') - .data([0]); + var scale = eventTransform.k / transformStart.k; + var tX = (eventTransform.x / scale - transformStart.x) * scale; + var tY = (eventTransform.y / scale - transformStart.y) * scale; - viewport = viewport.enter() - .append('svg') - .attr('class', 'map-in-map-viewport') - .merge(viewport); + if (context.inIntro()) { + curtainProjection.transform({ + x: eventTransform.x - tX, + y: eventTransform.y - tY, + k: eventTransform.k + }); + } + if (source) mousemove = event$$1; + transformed = true; + transformLast = eventTransform; + utilSetTransform(supersurface, tX, tY, scale); + scheduleRedraw(); - var path = viewport.selectAll('.map-in-map-bbox') - .data([bbox]); + dispatch$$1.call('move', this, map); + } - path.enter() - .append('path') - .attr('class', 'map-in-map-bbox') - .merge(path) - .attr('d', getPath) - .classed('thick', function(d) { return getPath.area(d) < 30; }); - } - } + function resetTransform() { + if (!transformed) return false; - function queueRedraw() { - clearTimeout(timeoutId); - timeoutId = setTimeout(function() { redraw(); }, 750); - } + // deprecation warning - Radial Menu to be removed in iD v3 + surface.selectAll('.edit-menu, .radial-menu').interrupt().remove(); + utilSetTransform(supersurface, 0, 0); + transformed = false; + if (context.inIntro()) { + curtainProjection.transform(projection.transform()); + } + return true; + } - function toggle() { - if (event) event.preventDefault(); + function redraw(difference, extent) { + if (surface.empty() || !redrawEnabled) return; - isHidden = !isHidden; + // If we are in the middle of a zoom/pan, we can't do differenced redraws. + // It would result in artifacts where differenced entities are redrawn with + // one transform and unchanged entities with another. + if (resetTransform()) { + difference = extent = undefined; + } - d3_select('.minimap-toggle-item') - .classed('active', !isHidden) - .select('input') - .property('checked', !isHidden); + var z = String(~~map.zoom()); + if (surface.attr('data-zoom') !== z) { + surface.attr('data-zoom', z) + .classed('low-zoom', z <= 16); + } - if (isHidden) { - wrap - .style('display', 'block') - .style('opacity', '1') - .transition() - .duration(200) - .style('opacity', '0') - .on('end', function() { - selection$$1.selectAll('.map-in-map') - .style('display', 'none'); - }); - } else { - wrap - .style('display', 'block') - .style('opacity', '0') - .transition() - .duration(200) - .style('opacity', '1') - .on('end', function() { - redraw(); - }); - } - } + if (!difference) { + supersurface.call(context.background()); + } + wrapper + .call(drawLayers); - uiMapInMap.toggle = toggle; + // OSM + if (map.editable()) { + context.loadTiles(projection, dimensions); + drawVector(difference, extent); + } else { + editOff(); + } - wrap = selection$$1.selectAll('.map-in-map') - .data([0]); + transformStart = projection.transform(); - wrap = wrap.enter() - .append('div') - .attr('class', 'map-in-map') - .style('display', (isHidden ? 'none' : 'block')) - .call(zoom$$1) - .on('dblclick.zoom', null) - .merge(wrap); + return map; + } - context.map() - .on('drawn.map-in-map', function(drawn) { - if (drawn.full === true) { - redraw(); - } - }); - redraw(); - var keybinding = d3keybinding('map-in-map') - .on(t('background.minimap.key'), toggle); + var immediateRedraw = function(difference, extent) { + if (!difference && !extent) cancelPendingRedraw(); + redraw(difference, extent); + }; - d3_select(document) - .call(keybinding); - } - return map_in_map; -} + map.mouse = function() { + var event$$1 = mousemove || event; + if (event$$1) { + var s; + while ((s = event$$1.sourceEvent)) { event$$1 = s; } + return mouse$$1(event$$1); + } + return null; + }; + -function uiBackground(context) { - var key = t('background.key'); + // returns Lng/Lat + map.mouseCoordinates = function() { + var coord = map.mouse() || pxCenter(); + return projection.invert(coord); + }; - var _customSource = context.background().findSource('custom'); - var _previousBackground = context.background().findSource(context.storage('background-last-used-toggle')); - var _shown = false; - var _backgroundList = d3_select(null); - var _overlayList = d3_select(null); - var _displayOptionsContainer = d3_select(null); - var _offsetContainer = d3_select(null); + map.dblclickEnable = function(_) { + if (!arguments.length) return dblclickEnabled; + dblclickEnabled = _; + return map; + }; - var backgroundDisplayOptions = uiBackgroundDisplayOptions(context); - var backgroundOffset = uiBackgroundOffset(context); + map.redrawEnable = function(_) { + if (!arguments.length) return redrawEnabled; + redrawEnabled = _; + return map; + }; - function setTooltips(selection$$1) { - selection$$1.each(function(d, i, nodes) { - var item = d3_select(this).select('label'); - var span = item.select('span'); - var placement = (i < nodes.length / 2) ? 'bottom' : 'top'; - var description = d.description(); - var isOverflowing = (span.property('clientWidth') !== span.property('scrollWidth')); - if (d === _previousBackground) { - item.call(tooltip() - .placement(placement) - .html(true) - .title(function() { - var tip = '
    ' + t('background.switch') + '
    '; - return uiTooltipHtml(tip, uiCmd('⌘' + key)); - }) - ); - } else if (description || isOverflowing) { - item.call(tooltip() - .placement(placement) - .title(description || d.name()) - ); - } else { - item.call(tooltip().destroy); - } - }); - } + function setTransform(t2, duration, force) { + var t$$1 = projection.transform(); + if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) { + return false; + } + if (duration) { + _selection + .transition() + .duration(duration) + .on('start', function() { map.startEase(); }) + .call(zoom$$1.transform, identity$7.translate(t2.x, t2.y).scale(t2.k)); + } else { + projection.transform(t2); + transformStart = t2; + _selection.call(zoom$$1.transform, transformStart); + } + } - function updateLayerSelections(selection$$1) { - function active(d) { - return context.background().showsLayer(d); - } - selection$$1.selectAll('.layer') - .classed('active', active) - .classed('switch', function(d) { return d === _previousBackground; }) - .call(setTooltips) - .selectAll('input') - .property('checked', active); - } + function setZoom(z2, force, duration) { + if (z2 === map.zoom() && !force) { + return false; + } + var k = projection.scale(); + var k2 = Math.max(kMin, Math.min(kMax, geoZoomToScale(z2, TILESIZE))); + var center = pxCenter(); + var l = pointLocation(center); - function chooseBackground(d) { - if (d.id === 'custom' && !d.template()) { - return editCustom(); - } + projection.scale(k2); - event.preventDefault(); - _previousBackground = context.background().baseLayerSource(); - context.storage('background-last-used-toggle', _previousBackground.id); - context.storage('background-last-used', d.id); - context.background().baseLayerSource(d); - _backgroundList.call(updateLayerSelections); - document.activeElement.blur(); - } + var t$$1 = projection.translate(); + l = locationPoint(l); + t$$1[0] += center[0] - l[0]; + t$$1[1] += center[1] - l[1]; - function editCustom() { - event.preventDefault(); - var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png'; - var template = window.prompt( - t('background.custom_prompt', { example: example }), - _customSource.template() || example - ); + if (duration) { + projection.scale(k); // reset scale + _selection + .transition() + .duration(duration) + .on('start', function() { map.startEase(); }) + .call(zoom$$1.transform, identity$7.translate(t$$1[0], t$$1[1]).scale(k2)); + } else { + projection.translate(t$$1); + transformStart = projection.transform(); + _selection.call(zoom$$1.transform, transformStart); + } - if (template) { - context.storage('background-custom-template', template); - _customSource.template(template); - chooseBackground(_customSource); - } else { - _backgroundList.call(updateLayerSelections); - } - } + return true; - function chooseOverlay(d) { - event.preventDefault(); - context.background().toggleOverlayLayer(d); - _overlayList.call(updateLayerSelections); - document.activeElement.blur(); - } + function locationPoint(l) { + var translate = projection.translate(); + var scale = projection.scale() * TAU$1; + return [l[0] * scale + translate[0], l[1] * scale + translate[1]]; + } + function pointLocation(p) { + var translate = projection.translate(); + var scale = projection.scale() * TAU$1; + return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale]; + } + } - function drawListItems(layerList, type, change, filter) { - var sources = context.background() - .sources(context.map().extent()) - .filter(filter); - var layerLinks = layerList.selectAll('li.layer') - .data(sources, function(d) { return d.name(); }); + function setCenter(loc2, duration) { + var c = map.center(); + if (loc2[0] === c[0] && loc2[1] === c[1]) { + return false; + } - layerLinks.exit() - .remove(); + var t$$1 = projection.translate(); + var k = projection.scale(); + var pxC = pxCenter(); + var ll = projection(loc2); - var enter = layerLinks.enter() - .append('li') - .attr('class', 'layer') - .classed('layer-custom', function(d) { return d.id === 'custom'; }) - .classed('best', function(d) { return d.best(); }); + t$$1[0] = t$$1[0] - ll[0] + pxC[0]; + t$$1[1] = t$$1[1] - ll[1] + pxC[1]; - enter.filter(function(d) { return d.id === 'custom'; }) - .append('button') - .attr('class', 'layer-browse') - .call(tooltip() - .title(t('background.custom_button')) - .placement((textDirection === 'rtl') ? 'right' : 'left') - ) - .on('click', editCustom) - .call(svgIcon('#icon-search')); + if (duration) { + _selection + .transition() + .duration(duration) + .on('start', function() { map.startEase(); }) + .call(zoom$$1.transform, identity$7.translate(t$$1[0], t$$1[1]).scale(k)); + } else { + projection.translate(t$$1); + transformStart = projection.transform(); + _selection.call(zoom$$1.transform, transformStart); + } - enter.filter(function(d) { return d.best(); }) - .append('div') - .attr('class', 'best') - .call(tooltip() - .title(t('background.best_imagery')) - .placement((textDirection === 'rtl') ? 'right' : 'left') - ) - .append('span') - .html('★'); + return true; + } - var label = enter - .append('label'); - label - .append('input') - .attr('type', type) - .attr('name', 'layers') - .on('change', change); + map.pan = function(delta, duration) { + var t$$1 = projection.translate(); + var k = projection.scale(); - label - .append('span') - .text(function(d) { return d.name(); }); + t$$1[0] += delta[0]; + t$$1[1] += delta[1]; + if (duration) { + _selection + .transition() + .duration(duration) + .on('start', function() { map.startEase(); }) + .call(zoom$$1.transform, identity$7.translate(t$$1[0], t$$1[1]).scale(k)); + } else { + projection.translate(t$$1); + transformStart = projection.transform(); + _selection.call(zoom$$1.transform, transformStart); + dispatch$$1.call('move', this, map); + immediateRedraw(); + } - layerList.selectAll('li.layer') - .sort(sortSources) - .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none'); + return map; + }; - layerList - .call(updateLayerSelections); + map.dimensions = function(_) { + if (!arguments.length) return dimensions; + var center = map.center(); + dimensions = _; + drawLayers.dimensions(dimensions); + context.background().dimensions(dimensions); + projection.clipExtent([[0, 0], dimensions]); + mouse$$1 = utilFastMouse(supersurface.node()); + setCenter(center); - function sortSources(a, b) { - return a.best() && !b.best() ? -1 - : b.best() && !a.best() ? 1 - : d3_descending(a.area(), b.area()) || d3_ascending(a.name(), b.name()) || 0; - } - } + scheduleRedraw(); + return map; + }; - function renderBackgroundList(selection$$1) { + function zoomIn(delta) { + setZoom(~~map.zoom() + delta, true, 250); + } - // the background list - var container = selection$$1.selectAll('.layer-background-list') - .data([0]); + function zoomOut(delta) { + setZoom(~~map.zoom() - delta, true, 250); + } - _backgroundList = container.enter() - .append('ul') - .attr('class', 'layer-list layer-background-list') - .attr('dir', 'auto') - .merge(container); + map.zoomIn = function() { zoomIn(1); }; + map.zoomInFurther = function() { zoomIn(4); }; + map.zoomOut = function() { zoomOut(1); }; + map.zoomOutFurther = function() { zoomOut(4); }; - // add minimap toggle below list - var minimapEnter = selection$$1.selectAll('.minimap-toggle-list') - .data([0]) - .enter() - .append('ul') - .attr('class', 'layer-list minimap-toggle-list') - .append('li') - .attr('class', 'layer minimap-toggle-item'); - var minimapLabelEnter = minimapEnter - .append('label') - .call(tooltip() - .html(true) - .title(uiTooltipHtml(t('background.minimap.tooltip'), t('background.minimap.key'))) - .placement('top') - ); + map.center = function(loc2) { + if (!arguments.length) { + return projection.invert(pxCenter()); + } - minimapLabelEnter - .append('input') - .attr('type', 'checkbox') - .on('change', function() { - event.preventDefault(); - uiMapInMap.toggle(); - }); + if (setCenter(loc2)) { + dispatch$$1.call('move', this, map); + } - minimapLabelEnter - .append('span') - .text(t('background.minimap.description')); + scheduleRedraw(); + return map; + }; - // "Info / Report a Problem" link - selection$$1.selectAll('.imagery-faq') - .data([0]) - .enter() - .append('div') - .attr('class', 'imagery-faq') - .append('a') - .attr('target', '_blank') - .attr('tabindex', -1) - .call(svgIcon('#icon-out-link', 'inline')) - .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery') - .append('span') - .text(t('background.imagery_source_faq')); - } + map.zoom = function(z2) { + if (!arguments.length) { + return Math.max(geoScaleToZoom(projection.scale(), TILESIZE), 0); + } + if (z2 < minzoom) { + surface.interrupt(); + uiFlash().text(t('cannot_zoom'))(); + z2 = context.minEditableZoom(); + } - function renderOverlayList(selection$$1) { - var container = selection$$1.selectAll('.layer-overlay-list') - .data([0]); + if (setZoom(z2)) { + dispatch$$1.call('move', this, map); + } - _overlayList = container.enter() - .append('ul') - .attr('class', 'layer-list layer-overlay-list') - .attr('dir', 'auto') - .merge(container); - } + scheduleRedraw(); + return map; + }; - function update() { - _backgroundList - .call(drawListItems, 'radio', chooseBackground, function(d) { return !d.isHidden() && !d.overlay; }); + map.zoomTo = function(entity, zoomLimits) { + var extent = entity.extent(context.graph()); + if (!isFinite(extent.area())) return; - _overlayList - .call(drawListItems, 'checkbox', chooseOverlay, function(d) { return !d.isHidden() && d.overlay; }); + var z2 = map.trimmedExtentZoom(extent); + zoomLimits = zoomLimits || [context.minEditableZoom(), 24]; + map.centerZoom(extent.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1])); + }; - _displayOptionsContainer - .call(backgroundDisplayOptions); - _offsetContainer - .call(backgroundOffset); - } + map.centerZoom = function(loc2, z2) { + var centered = setCenter(loc2); + var zoomed = setZoom(z2); + if (centered || zoomed) { + dispatch$$1.call('move', this, map); + } - function quickSwitch() { - if (event) { - event.stopImmediatePropagation(); - event.preventDefault(); - } - if (_previousBackground) { - chooseBackground(_previousBackground); - } - } + scheduleRedraw(); + return map; + }; - function background(selection$$1) { + map.centerEase = function(loc2, duration) { + duration = duration || 250; + setCenter(loc2, duration); + return map; + }; - function hidePane() { - setVisible(false); - } - function togglePane() { - if (event) event.preventDefault(); - paneTooltip.hide(button); - setVisible(!button.classed('active')); - } + map.zoomEase = function(z2, duration) { + duration = duration || 250; + setZoom(z2, false, duration); + return map; + }; - function setVisible(show) { - if (show !== _shown) { - button.classed('active', show); - _shown = show; - - if (show) { - uiMapData.hidePane(); - uiHelp.hidePane(); - update(); - - pane - .style('display', 'block') - .style('right', '-300px') - .transition() - .duration(200) - .style('right', '0px'); - - } else { - pane - .style('display', 'block') - .style('right', '0px') - .transition() - .duration(200) - .style('right', '-300px') - .on('end', function() { - d3_select(this).style('display', 'none'); - }); - } - } - } + map.transformEase = function(t2, duration) { + duration = duration || 250; + setTransform(t2, duration, false); + return map; + }; - var pane = selection$$1 - .append('div') - .attr('class', 'fillL map-overlay col3 content hide'); - - var paneTooltip = tooltip() - .placement((textDirection === 'rtl') ? 'right' : 'left') - .html(true) - .title(uiTooltipHtml(t('background.description'), key)); - - var button = selection$$1 - .append('button') - .attr('tabindex', -1) - .on('click', togglePane) - .call(svgIcon('#icon-layers', 'light')) - .call(paneTooltip); - - pane - .append('h2') - .text(t('background.title')); - - // background list - pane - .append('div') - .attr('class', 'background-background-list-container') - .call(uiDisclosure(context, 'background_list', true) - .title(t('background.backgrounds')) - .content(renderBackgroundList) - ); - // overlay list - pane - .append('div') - .attr('class', 'background-overlay-list-container') - .call(uiDisclosure(context, 'overlay_list', true) - .title(t('background.overlays')) - .content(renderOverlayList) - ); + map.startEase = function() { + utilBindOnce(surface, 'mousedown.ease', function() { + map.cancelEase(); + }); + return map; + }; - // display options - _displayOptionsContainer = pane - .append('div') - .attr('class', 'background-display-options'); - // offset controls - _offsetContainer = pane - .append('div') - .attr('class', 'background-offset'); + map.cancelEase = function() { + _selection.interrupt(); + return map; + }; - // add listeners - context.map() - .on('move.background-update', debounce(utilCallWhenIdle(update), 1000)); + map.extent = function(_) { + if (!arguments.length) { + return new geoExtent$$1( + projection.invert([0, dimensions[1]]), + projection.invert([dimensions[0], 0]) + ); + } else { + var extent = geoExtent$$1(_); + map.centerZoom(extent.center(), map.extentZoom(extent)); + } + }; - context.background() - .on('change.background-update', update); + map.trimmedExtent = function(_) { + if (!arguments.length) { + var headerY = 60; + var footerY = 30; + var pad = 10; + return new geoExtent$$1( + projection.invert([pad, dimensions[1] - footerY - pad]), + projection.invert([dimensions[0] - pad, headerY + pad]) + ); + } else { + var extent = geoExtent$$1(_); + map.centerZoom(extent.center(), map.trimmedExtentZoom(extent)); + } + }; - update(); - var keybinding = d3keybinding('background') - .on(key, togglePane) - .on(uiCmd('⌘' + key), quickSwitch) - .on([t('map_data.key'), t('help.key')], hidePane); + function calcZoom(extent, dim) { + var tl = projection([extent[0][0], extent[1][1]]); + var br = projection([extent[1][0], extent[0][1]]); - d3_select(document) - .call(keybinding); + // Calculate maximum zoom that fits extent + var hFactor = (br[0] - tl[0]) / dim[0]; + var vFactor = (br[1] - tl[1]) / dim[1]; + var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2; + var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2; + var newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff); - uiBackground.hidePane = hidePane; - uiBackground.togglePane = togglePane; - uiBackground.setVisible = setVisible; - } + return newZoom; + } - return background; -} -function uiContributors(context) { - var osm = context.connection(), - debouncedUpdate = debounce(function() { update(); }, 1000), - limit = 4, - hidden = false, - wrap = d3_select(null); + map.extentZoom = function(_) { + return calcZoom(geoExtent$$1(_), dimensions); + }; - function update() { - if (!osm) return; + map.trimmedExtentZoom = function(_) { + var trimY = 120; + var trimX = 40; + var trimmed = [dimensions[0] - trimX, dimensions[1] - trimY]; + return calcZoom(geoExtent$$1(_), trimmed); + }; - var users = {}, - entities = context.intersects(context.map().extent()); - entities.forEach(function(entity) { - if (entity && entity.user) users[entity.user] = true; - }); + map.editable = function() { + var osmLayer = surface.selectAll('.data-layer-osm'); + if (!osmLayer.empty() && osmLayer.classed('disabled')) return false; - var u = Object.keys(users), - subset = u.slice(0, u.length > limit ? limit - 1 : limit); + return map.zoom() >= context.minEditableZoom(); + }; - wrap.html('') - .call(svgIcon('#icon-nearby', 'pre-text light')); - var userList = d3_select(document.createElement('span')); + map.minzoom = function(_) { + if (!arguments.length) return minzoom; + minzoom = _; + return map; + }; - userList.selectAll() - .data(subset) - .enter() - .append('a') - .attr('class', 'user-link') - .attr('href', function(d) { return osm.userURL(d); }) - .attr('target', '_blank') - .attr('tabindex', -1) - .text(String); - if (u.length > limit) { - var count = d3_select(document.createElement('span')); + map.layers = drawLayers; - count.append('a') - .attr('target', '_blank') - .attr('tabindex', -1) - .attr('href', function() { - return osm.changesetsURL(context.map().center(), context.map().zoom()); - }) - .text(u.length - limit + 1); - wrap.append('span') - .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() })); + return utilRebind(map, dispatch$$1, 'on'); + } - } else { - wrap.append('span') - .html(t('contributors.list', { users: userList.html() })); - } + function uiMapInMap(context) { + + function map_in_map(selection$$1) { + var backgroundLayer = rendererTileLayer(context); + var overlayLayers = {}; + var projection$$1 = geoRawMercator(); + var gpxLayer = svgGpx$$1(projection$$1, context).showLabels(false); + var debugLayer = svgDebug$$1(projection$$1, context); + var zoom$$1 = d3_zoom() + .scaleExtent([geoZoomToScale(0.5), geoZoomToScale(24)]) + .on('start', zoomStarted) + .on('zoom', zoomed) + .on('end', zoomEnded); + var isTransformed = false; + var isHidden = true; + var skipEvents = false; + var gesture = null; + var zDiff = 6; // by default, minimap renders at (main zoom - 6) + var wrap = select(null); + var tiles = select(null); + var viewport = select(null); + var tStart; // transform at start of gesture + var tCurr; // transform at most recent event + var timeoutId; + + + function zoomStarted() { + if (skipEvents) return; + tStart = tCurr = projection$$1.transform(); + gesture = null; + } - if (!u.length) { - hidden = true; - wrap - .transition() - .style('opacity', 0); - } else if (hidden) { - wrap - .transition() - .style('opacity', 1); - } - } + function zoomed() { + if (skipEvents) return; + var x = event.transform.x; + var y = event.transform.y; + var k = event.transform.k; + var isZooming = (k !== tStart.k); + var isPanning = (x !== tStart.x || y !== tStart.y); - return function(selection$$1) { - if (!osm) return; - wrap = selection$$1; - update(); + if (!isZooming && !isPanning) { + return; // no change + } - osm.on('loaded.contributors', debouncedUpdate); - context.map().on('move.contributors', debouncedUpdate); - }; -} - -function uiFeatureInfo(context) { - function update(selection$$1) { - var features = context.features(), - stats = features.stats(), - count = 0, - hiddenList = compact(map$3(features.hidden(), function(k) { - if (stats[k]) { - count += stats[k]; - return String(stats[k]) + ' ' + t('feature.' + k + '.description'); - } - })); - - selection$$1.html(''); - - if (hiddenList.length) { - var tooltipBehavior = tooltip() - .placement('top') - .html(true) - .title(function() { - return uiTooltipHtml(hiddenList.join('
    ')); - }); - - var warning = selection$$1.append('a') - .attr('href', '#') - .attr('tabindex', -1) - .html(t('feature_info.hidden_warning', { count: count })) - .call(tooltipBehavior) - .on('click', function() { - tooltipBehavior.hide(warning); - // open map data panel? - event.preventDefault(); - }); - } + // lock in either zooming or panning, don't allow both in minimap. + if (!gesture) { + gesture = isZooming ? 'zoom' : 'pan'; + } - selection$$1 - .classed('hide', !hiddenList.length); - } + var tMini = projection$$1.transform(); + var tX, tY, scale; + if (gesture === 'zoom') { + var dMini = utilGetDimensions(wrap); + var cMini = geoVecScale(dMini, 0.5); + scale = k / tMini.k; + tX = (cMini[0] / scale - cMini[0]) * scale; + tY = (cMini[1] / scale - cMini[1]) * scale; + } else { + k = tMini.k; + scale = 1; + tX = x - tMini.x; + tY = y - tMini.y; + } - return function(selection$$1) { - update(selection$$1); + utilSetTransform(tiles, tX, tY, scale); + utilSetTransform(viewport, 0, 0, scale); + isTransformed = true; + tCurr = identity$7.translate(x, y).scale(k); - context.features().on('change.feature_info', function() { - update(selection$$1); - }); - }; -} - -function uiFullScreen(context) { - var element = context.container().node(), - keybinding = d3keybinding('full-screen'); - // button; - - - function getFullScreenFn() { - if (element.requestFullscreen) { - return element.requestFullscreen; - } else if (element.msRequestFullscreen) { - return element.msRequestFullscreen; - } else if (element.mozRequestFullScreen) { - return element.mozRequestFullScreen; - } else if (element.webkitRequestFullscreen) { - return element.webkitRequestFullscreen; - } - } + var zMain = geoScaleToZoom(context.projection.scale()); + var zMini = geoScaleToZoom(k); + zDiff = zMain - zMini; - function getExitFullScreenFn() { - if (document.exitFullscreen) { - return document.exitFullscreen; - } else if (document.msExitFullscreen) { - return document.msExitFullscreen; - } else if (document.mozCancelFullScreen) { - return document.mozCancelFullScreen; - } else if (document.webkitExitFullscreen) { - return document.webkitExitFullscreen; - } - } + queueRedraw(); + } - function isFullScreen() { - return document.fullscreenElement || - document.mozFullScreenElement || - document.webkitFullscreenElement || - document.msFullscreenElement; - } + function zoomEnded() { + if (skipEvents) return; + if (gesture !== 'pan') return; + updateProjection(); + gesture = null; + var dMini = utilGetDimensions(wrap); + var cMini = geoVecScale(dMini, 0.5); + context.map().center(projection$$1.invert(cMini)); // recenter main map.. + } - function isSupported() { - return !!getFullScreenFn(); - } + function updateProjection() { + var loc = context.map().center(); + var dMini = utilGetDimensions(wrap); + var cMini = geoVecScale(dMini, 0.5); + var tMain = context.projection.transform(); + var zMain = geoScaleToZoom(tMain.k); + var zMini = Math.max(zMain - zDiff, 0.5); + var kMini = geoZoomToScale(zMini); - function fullScreen() { - event.preventDefault(); - if (!isFullScreen()) { - // button.classed('active', true); - getFullScreenFn().apply(element); - } else { - // button.classed('active', false); - getExitFullScreenFn().apply(document); - } - } + projection$$1 + .translate([tMain.x, tMain.y]) + .scale(kMini); + var point$$1 = projection$$1(loc); + var mouse$$1 = (gesture === 'pan') ? geoVecSubtract([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0]; + var xMini = cMini[0] - point$$1[0] + tMain.x + mouse$$1[0]; + var yMini = cMini[1] - point$$1[1] + tMain.y + mouse$$1[1]; - return function() { // selection) { - if (!isSupported()) - return; + projection$$1 + .translate([xMini, yMini]) + .clipExtent([[0, 0], dMini]); - // button = selection.append('button') - // .attr('title', t('full_screen')) - // .attr('tabindex', -1) - // .on('click', fullScreen) - // .call(tooltip); + tCurr = projection$$1.transform(); - // button.append('span') - // .attr('class', 'icon full-screen'); + if (isTransformed) { + utilSetTransform(tiles, 0, 0); + utilSetTransform(viewport, 0, 0); + isTransformed = false; + } - var detected = utilDetect(); - var keys = detected.os === 'mac' ? [uiCmd('⌃⌘F'), 'f11'] : ['f11']; - keybinding.on(keys, fullScreen); + zoom$$1 + .scaleExtent([geoZoomToScale(0.5), geoZoomToScale(zMain - 3)]); - d3_select(document) - .call(keybinding); - }; -} + skipEvents = true; + wrap.call(zoom$$1.transform, tCurr); + skipEvents = false; + } -function uiLoading(context) { - var _modalSelection = d3_select(null); - var _message = ''; - var _blocking = false; + function redraw() { + clearTimeout(timeoutId); + if (isHidden) return; - var loading = function(selection$$1) { - _modalSelection = uiModal(selection$$1, _blocking); + updateProjection(); - var loadertext = _modalSelection.select('.content') - .classed('loading-modal', true) - .append('div') - .attr('class', 'modal-section fillL'); + var dMini = utilGetDimensions(wrap); + var zMini = geoScaleToZoom(projection$$1.scale()); - loadertext - .append('img') - .attr('class', 'loader') - .attr('src', context.imagePath('loader-white.gif')); + // setup tile container + tiles = wrap + .selectAll('.map-in-map-tiles') + .data([0]); - loadertext - .append('h3') - .text(_message); + tiles = tiles.enter() + .append('div') + .attr('class', 'map-in-map-tiles') + .merge(tiles); - _modalSelection.select('button.close') - .attr('class', 'hide'); + // redraw background + backgroundLayer + .source(context.background().baseLayerSource()) + .projection(projection$$1) + .dimensions(dMini); - return loading; - }; + var background = tiles + .selectAll('.map-in-map-background') + .data([0]); + background.enter() + .append('div') + .attr('class', 'map-in-map-background') + .merge(background) + .call(backgroundLayer); + + + // redraw overlay + var overlaySources = context.background().overlayLayerSources(); + var activeOverlayLayers = []; + for (var i = 0; i < overlaySources.length; i++) { + if (overlaySources[i].validZoom(zMini)) { + if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context); + activeOverlayLayers.push(overlayLayers[i] + .source(overlaySources[i]) + .projection(projection$$1) + .dimensions(dMini)); + } + } + + var overlay = tiles + .selectAll('.map-in-map-overlay') + .data([0]); + + overlay = overlay.enter() + .append('div') + .attr('class', 'map-in-map-overlay') + .merge(overlay); - loading.message = function(_) { - if (!arguments.length) return _message; - _message = _; - return loading; - }; + var overlays = overlay + .selectAll('div') + .data(activeOverlayLayers, function(d) { return d.source().name(); }); - loading.blocking = function(_) { - if (!arguments.length) return _blocking; - _blocking = _; - return loading; - }; + overlays.exit() + .remove(); + overlays = overlays.enter() + .append('div') + .merge(overlays) + .each(function(layer) { select(this).call(layer); }); - loading.close = function() { - _modalSelection.remove(); - }; + var dataLayers = tiles + .selectAll('.map-in-map-data') + .data([0]); - return loading; -} + dataLayers.exit() + .remove(); -function uiGeolocate(context) { - var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ }, - locating = uiLoading(context).message(t('geolocate.locating')).blocking(true), - timeoutId; + dataLayers = dataLayers.enter() + .append('svg') + .attr('class', 'map-in-map-data') + .merge(dataLayers) + .call(gpxLayer) + .call(debugLayer); - function click() { - if (context.inIntro()) return; - context.enter(modeBrowse(context)); - context.container().call(locating); - navigator.geolocation.getCurrentPosition(success, error, geoOptions); + // redraw viewport bounding box + if (gesture !== 'pan') { + var getPath = d3_geoPath(projection$$1); + var bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] }; - // This timeout ensures that we still call finish() even if - // the user declines to share their location in Firefox - timeoutId = setTimeout(finish, 10000 /* 10sec */ ); - } + viewport = wrap.selectAll('.map-in-map-viewport') + .data([0]); + viewport = viewport.enter() + .append('svg') + .attr('class', 'map-in-map-viewport') + .merge(viewport); - function success(position) { - var map = context.map(), - extent = geoExtent$$1([position.coords.longitude, position.coords.latitude]) - .padByMeters(position.coords.accuracy); - map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent))); - finish(); - } + var path = viewport.selectAll('.map-in-map-bbox') + .data([bbox]); + path.enter() + .append('path') + .attr('class', 'map-in-map-bbox') + .merge(path) + .attr('d', getPath) + .classed('thick', function(d) { return getPath.area(d) < 30; }); + } + } - function error() { - finish(); - } + function queueRedraw() { + clearTimeout(timeoutId); + timeoutId = setTimeout(function() { redraw(); }, 750); + } - function finish() { - locating.close(); // unblock ui - if (timeoutId) { clearTimeout(timeoutId); } - timeoutId = undefined; - } + function toggle() { + if (event) event.preventDefault(); + + isHidden = !isHidden; + + select('.minimap-toggle-item') + .classed('active', !isHidden) + .select('input') + .property('checked', !isHidden); + + if (isHidden) { + wrap + .style('display', 'block') + .style('opacity', '1') + .transition() + .duration(200) + .style('opacity', '0') + .on('end', function() { + selection$$1.selectAll('.map-in-map') + .style('display', 'none'); + }); + } else { + wrap + .style('display', 'block') + .style('opacity', '0') + .transition() + .duration(200) + .style('opacity', '1') + .on('end', function() { + redraw(); + }); + } + } - return function(selection) { - if (!navigator.geolocation) return; - selection - .append('button') - .attr('tabindex', -1) - .attr('title', t('geolocate.title')) - .on('click', click) - .call(svgIcon('#icon-geolocate', 'light')) - .call(tooltip() - .placement((textDirection === 'rtl') ? 'right' : 'left')); - }; -} - -function uiPanelBackground(context) { - var background = context.background(); - var currSourceName = null; - var metadata = {}; - var metadataKeys = [ - 'zoom', 'vintage', 'source', 'description', 'resolution', 'accuracy' - ]; + uiMapInMap.toggle = toggle; - var debouncedRedraw = debounce(redraw, 250); + wrap = selection$$1.selectAll('.map-in-map') + .data([0]); - function redraw(selection$$1) { - var source = background.baseLayerSource(), - isDG = (source.id.match(/^DigitalGlobe/i) !== null); + wrap = wrap.enter() + .append('div') + .attr('class', 'map-in-map') + .style('display', (isHidden ? 'none' : 'block')) + .call(zoom$$1) + .on('dblclick.zoom', null) + .merge(wrap); - if (currSourceName !== source.name()) { - currSourceName = source.name(); - metadata = {}; - } + context.map() + .on('drawn.map-in-map', function(drawn) { + if (drawn.full === true) { + redraw(); + } + }); - selection$$1.html(''); + redraw(); - var list = selection$$1 - .append('ul') - .attr('class', 'background-info'); + var keybinding = d3keybinding('map-in-map') + .on(t('background.minimap.key'), toggle); - list - .append('li') - .text(currSourceName); + select(document) + .call(keybinding); + } - metadataKeys.forEach(function(k) { - // DigitalGlobe vintage is available in raster layers for now. - if (isDG && k === 'vintage') return; + return map_in_map; + } - list - .append('li') - .attr('class', 'background-info-list-' + k) - .classed('hide', !metadata[k]) - .text(t('info_panels.background.' + k) + ':') - .append('span') - .attr('class', 'background-info-span-' + k) - .text(metadata[k]); - }); + function uiBackground(context) { + var key = t('background.key'); + + var _customSource = context.background().findSource('custom'); + var _previousBackground = context.background().findSource(context.storage('background-last-used-toggle')); + var _shown = false; + + var _backgroundList = select(null); + var _overlayList = select(null); + var _displayOptionsContainer = select(null); + var _offsetContainer = select(null); + + var backgroundDisplayOptions = uiBackgroundDisplayOptions(context); + var backgroundOffset = uiBackgroundOffset(context); + + + function setTooltips(selection$$1) { + selection$$1.each(function(d, i, nodes) { + var item = select(this).select('label'); + var span = item.select('span'); + var placement = (i < nodes.length / 2) ? 'bottom' : 'top'; + var description = d.description(); + var isOverflowing = (span.property('clientWidth') !== span.property('scrollWidth')); + + if (d === _previousBackground) { + item.call(tooltip() + .placement(placement) + .html(true) + .title(function() { + var tip = '
    ' + t('background.switch') + '
    '; + return uiTooltipHtml(tip, uiCmd('⌘' + key)); + }) + ); + } else if (description || isOverflowing) { + item.call(tooltip() + .placement(placement) + .title(description || d.name()) + ); + } else { + item.call(tooltip().destroy); + } + }); + } - debouncedGetMetadata(selection$$1); - var toggleTiles = context.getDebug('tile') ? 'hide_tiles' : 'show_tiles'; + function updateLayerSelections(selection$$1) { + function active(d) { + return context.background().showsLayer(d); + } - selection$$1 - .append('a') - .text(t('info_panels.background.' + toggleTiles)) - .attr('href', '#') - .attr('class', 'button button-toggle-tiles') - .on('click', function() { - event.preventDefault(); - context.setDebug('tile', !context.getDebug('tile')); - selection$$1.call(redraw); - }); + selection$$1.selectAll('.layer') + .classed('active', active) + .classed('switch', function(d) { return d === _previousBackground; }) + .call(setTooltips) + .selectAll('input') + .property('checked', active); + } - if (isDG) { - var key = source.id + '-vintage'; - var sourceVintage = context.background().findSource(key); - var showsVintage = context.background().showsLayer(sourceVintage); - var toggleVintage = showsVintage ? 'hide_vintage' : 'show_vintage'; - selection$$1 - .append('a') - .text(t('info_panels.background.' + toggleVintage)) - .attr('href', '#') - .attr('class', 'button button-toggle-vintage') - .on('click', function() { - event.preventDefault(); - context.background().toggleOverlayLayer(sourceVintage); - selection$$1.call(redraw); - }); - } - // disable if necessary - ['DigitalGlobe-Premium', 'DigitalGlobe-Standard'].forEach(function(layerId) { - if (source.id !== layerId) { - var key = layerId + '-vintage'; - var sourceVintage = context.background().findSource(key); - if (context.background().showsLayer(sourceVintage)) { - context.background().toggleOverlayLayer(sourceVintage); - } - } - }); - } + function chooseBackground(d) { + if (d.id === 'custom' && !d.template()) { + return editCustom(); + } + event.preventDefault(); + _previousBackground = context.background().baseLayerSource(); + context.storage('background-last-used-toggle', _previousBackground.id); + context.storage('background-last-used', d.id); + context.background().baseLayerSource(d); + _backgroundList.call(updateLayerSelections); + document.activeElement.blur(); + } - var debouncedGetMetadata = debounce(getMetadata, 250); - - function getMetadata(selection$$1) { - var tile = d3_select('.layer-background img.tile-center'); // tile near viewport center - if (tile.empty()) return; - - var sourceName = currSourceName, - d = tile.datum(), - zoom = (d && d.length >= 3 && d[2]) || Math.floor(context.map().zoom()), - center = context.map().center(); - - // update zoom - metadata.zoom = String(zoom); - selection$$1.selectAll('.background-info-list-zoom') - .classed('hide', false) - .selectAll('.background-info-span-zoom') - .text(metadata.zoom); - - if (!d || !d.length >= 3) return; - - background.baseLayerSource().getMetadata(center, d, function(err, result) { - if (err || currSourceName !== sourceName) return; - - // update vintage - var vintage = result.vintage; - metadata.vintage = (vintage && vintage.range) || t('info_panels.background.unknown'); - selection$$1.selectAll('.background-info-list-vintage') - .classed('hide', false) - .selectAll('.background-info-span-vintage') - .text(metadata.vintage); - - // update other metdata - without(metadataKeys, 'zoom', 'vintage') - .forEach(function(k) { - var val = result[k]; - metadata[k] = val; - selection$$1.selectAll('.background-info-list-' + k) - .classed('hide', !val) - .selectAll('.background-info-span-' + k) - .text(val); - }); - }); - } + function editCustom() { + event.preventDefault(); + var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png'; + var template = window.prompt( + t('background.custom_prompt', { example: example }), + _customSource.template() || example + ); - var panel = function(selection$$1) { - selection$$1.call(redraw); + if (template) { + context.storage('background-custom-template', template); + _customSource.template(template); + chooseBackground(_customSource); + } else { + _backgroundList.call(updateLayerSelections); + } + } - context.map() - .on('drawn.info-background', function() { - selection$$1.call(debouncedRedraw); - }) - .on('move.info-background', function() { - selection$$1.call(debouncedGetMetadata); - }); - }; + function chooseOverlay(d) { + event.preventDefault(); + context.background().toggleOverlayLayer(d); + _overlayList.call(updateLayerSelections); + document.activeElement.blur(); + } - panel.off = function() { - context.map() - .on('drawn.info-background', null) - .on('move.info-background', null); - }; - panel.id = 'background'; - panel.title = t('info_panels.background.title'); - panel.key = t('info_panels.background.key'); + function drawListItems(layerList, type, change, filter) { + var sources = context.background() + .sources(context.map().extent()) + .filter(filter); + + var layerLinks = layerList.selectAll('li.layer') + .data(sources, function(d) { return d.name(); }); + + layerLinks.exit() + .remove(); + + var enter = layerLinks.enter() + .append('li') + .attr('class', 'layer') + .classed('layer-custom', function(d) { return d.id === 'custom'; }) + .classed('best', function(d) { return d.best(); }); + + enter.filter(function(d) { return d.id === 'custom'; }) + .append('button') + .attr('class', 'layer-browse') + .call(tooltip() + .title(t('background.custom_button')) + .placement((textDirection === 'rtl') ? 'right' : 'left') + ) + .on('click', editCustom) + .call(svgIcon('#icon-edit')); + + enter.filter(function(d) { return d.best(); }) + .append('div') + .attr('class', 'best') + .call(tooltip() + .title(t('background.best_imagery')) + .placement((textDirection === 'rtl') ? 'right' : 'left') + ) + .append('span') + .html('★'); + + var label = enter + .append('label'); + + label + .append('input') + .attr('type', type) + .attr('name', 'layers') + .on('change', change); + + label + .append('span') + .text(function(d) { return d.name(); }); + + + layerList.selectAll('li.layer') + .sort(sortSources) + .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none'); + + layerList + .call(updateLayerSelections); + + + function sortSources(a, b) { + return a.best() && !b.best() ? -1 + : b.best() && !a.best() ? 1 + : d3_descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0; + } + } - return panel; -} + function renderBackgroundList(selection$$1) { + + // the background list + var container = selection$$1.selectAll('.layer-background-list') + .data([0]); + + _backgroundList = container.enter() + .append('ul') + .attr('class', 'layer-list layer-background-list') + .attr('dir', 'auto') + .merge(container); + + + // add minimap toggle below list + var minimapEnter = selection$$1.selectAll('.minimap-toggle-list') + .data([0]) + .enter() + .append('ul') + .attr('class', 'layer-list minimap-toggle-list') + .append('li') + .attr('class', 'layer minimap-toggle-item'); + + var minimapLabelEnter = minimapEnter + .append('label') + .call(tooltip() + .html(true) + .title(uiTooltipHtml(t('background.minimap.tooltip'), t('background.minimap.key'))) + .placement('top') + ); + + minimapLabelEnter + .append('input') + .attr('type', 'checkbox') + .on('change', function() { + event.preventDefault(); + uiMapInMap.toggle(); + }); + + minimapLabelEnter + .append('span') + .text(t('background.minimap.description')); + + + // "Info / Report a Problem" link + selection$$1.selectAll('.imagery-faq') + .data([0]) + .enter() + .append('div') + .attr('class', 'imagery-faq') + .append('a') + .attr('target', '_blank') + .attr('tabindex', -1) + .call(svgIcon('#icon-out-link', 'inline')) + .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery') + .append('span') + .text(t('background.imagery_source_faq')); + } -function uiPanelHistory(context) { - var osm; - function displayTimestamp(entity) { - if (!entity.timestamp) return t('info_panels.history.unknown'); - var detected = utilDetect(); - var options = { - day: 'numeric', month: 'short', year: 'numeric', - hour: 'numeric', minute: 'numeric', second: 'numeric' - }; - var d = new Date(entity.timestamp); - if (isNaN(d.getTime())) return t('info_panels.history.unknown'); - return d.toLocaleString(detected.locale, options); - } + function renderOverlayList(selection$$1) { + var container = selection$$1.selectAll('.layer-overlay-list') + .data([0]); + _overlayList = container.enter() + .append('ul') + .attr('class', 'layer-list layer-overlay-list') + .attr('dir', 'auto') + .merge(container); + } - function displayUser(selection, entity) { - if (!entity.user) { - selection - .append('span') - .text(t('info_panels.history.unknown')); - return; - } - selection - .append('span') - .attr('class', 'user-name') - .text(entity.user); - - var links = selection - .append('div') - .attr('class', 'links'); - - if (osm) { - links - .append('a') - .attr('class', 'user-osm-link') - .attr('href', osm.userURL(entity.user)) - .attr('target', '_blank') - .attr('tabindex', -1) - .text('OSM'); - } + function update() { + _backgroundList + .call(drawListItems, 'radio', chooseBackground, function(d) { return !d.isHidden() && !d.overlay; }); - links - .append('a') - .attr('class', 'user-hdyc-link') - .attr('href', 'https://hdyc.neis-one.org/?' + entity.user) - .attr('target', '_blank') - .attr('tabindex', -1) - .text('HDYC'); - } + _overlayList + .call(drawListItems, 'checkbox', chooseOverlay, function(d) { return !d.isHidden() && d.overlay; }); + _displayOptionsContainer + .call(backgroundDisplayOptions); - function displayChangeset(selection, entity) { - if (!entity.changeset) { - selection - .append('span') - .text(t('info_panels.history.unknown')); - return; - } + _offsetContainer + .call(backgroundOffset); + } - selection - .append('span') - .attr('class', 'changeset-id') - .text(entity.changeset); - - var links = selection - .append('div') - .attr('class', 'links'); - - if (osm) { - links - .append('a') - .attr('class', 'changeset-osm-link') - .attr('href', osm.changesetURL(entity.changeset)) - .attr('target', '_blank') - .attr('tabindex', -1) - .text('OSM'); - } - links - .append('a') - .attr('class', 'changeset-osmcha-link') - .attr('href', 'https://osmcha.mapbox.com/changesets/' + entity.changeset) - .attr('target', '_blank') - .attr('tabindex', -1) - .text('OSMCha'); - } + function quickSwitch() { + if (event) { + event.stopImmediatePropagation(); + event.preventDefault(); + } + if (_previousBackground) { + chooseBackground(_previousBackground); + } + } - function redraw(selection) { - var selected = filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }), - singular = selected.length === 1 ? selected[0] : null; + function background(selection$$1) { - osm = context.connection(); + function hidePane() { + setVisible(false); + } - selection.html(''); + function togglePane() { + if (event) event.preventDefault(); + paneTooltip.hide(button); + setVisible(!button.classed('active')); + } - selection - .append('h4') - .attr('class', 'history-heading') - .text(singular || t('info_panels.history.selected', { n: selected.length })); + function setVisible(show) { + if (show !== _shown) { + button.classed('active', show); + _shown = show; + + if (show) { + uiMapData.hidePane(); + uiHelp.hidePane(); + update(); + + pane + .style('display', 'block') + .style('right', '-300px') + .transition() + .duration(200) + .style('right', '0px'); + + } else { + pane + .style('display', 'block') + .style('right', '0px') + .transition() + .duration(200) + .style('right', '-300px') + .on('end', function() { + select(this).style('display', 'none'); + }); + } + } + } - if (!singular) return; - var entity = context.entity(singular); + var pane = selection$$1 + .append('div') + .attr('class', 'fillL map-pane col4 hide'); - var list = selection - .append('ul'); + var paneTooltip = tooltip() + .placement((textDirection === 'rtl') ? 'right' : 'left') + .html(true) + .title(uiTooltipHtml(t('background.description'), key)); - list - .append('li') - .text(t('info_panels.history.version') + ':') - .append('span') - .text(entity.version); + var button = selection$$1 + .append('button') + .attr('tabindex', -1) + .on('click', togglePane) + .call(svgIcon('#icon-layers', 'light')) + .call(paneTooltip); - list - .append('li') - .text(t('info_panels.history.last_edit') + ':') - .append('span') - .text(displayTimestamp(entity)); - list - .append('li') - .text(t('info_panels.history.edited_by') + ':') - .call(displayUser, entity); + var heading = pane + .append('div') + .attr('class', 'pane-heading'); - list - .append('li') - .text(t('info_panels.history.changeset') + ':') - .call(displayChangeset, entity); + heading + .append('h2') + .text(t('background.title')); - if (osm) { - selection - .append('a') - .attr('class', 'view-history-on-osm') - .attr('target', '_blank') - .attr('tabindex', -1) - .attr('href', osm.historyURL(entity)) - .call(svgIcon('#icon-out-link', 'inline')) - .append('span') - .text(t('info_panels.history.link_text')); - } - } + heading + .append('button') + .on('click', function() { uiBackground.hidePane(); }) + .call(svgIcon('#icon-close')); - var panel = function(selection) { - selection.call(redraw); + var content = pane + .append('div') + .attr('class', 'pane-content'); - context.map() - .on('drawn.info-history', function() { - selection.call(redraw); - }); - }; + // background list + content + .append('div') + .attr('class', 'background-background-list-container') + .call(uiDisclosure(context, 'background_list', true) + .title(t('background.backgrounds')) + .content(renderBackgroundList) + ); - panel.off = function() { - context.map() - .on('drawn.info-history', null); - }; + // overlay list + content + .append('div') + .attr('class', 'background-overlay-list-container') + .call(uiDisclosure(context, 'overlay_list', true) + .title(t('background.overlays')) + .content(renderOverlayList) + ); - panel.id = 'history'; - panel.title = t('info_panels.history.title'); - panel.key = t('info_panels.history.key'); - - - return panel; -} - -// - -var OSM_PRECISION = 7; -var locale$2 = utilDetect().locale; - -/** - * Returns a localized representation of the given length measurement. - * - * @param {Number} m area in meters - * @param {Boolean} isImperial true for U.S. customary units; false for metric - */ -function displayLength(m , isImperial ) { - var d = m * (isImperial ? 3.28084 : 1), - unit; - - if (isImperial) { - if (d >= 5280) { - d /= 5280; - unit = 'miles'; - } else { - unit = 'feet'; - } - } else { - if (d >= 1000) { - d /= 1000; - unit = 'kilometers'; - } else { - unit = 'meters'; - } - } - - return t('units.' + unit, { - quantity: d.toLocaleString(locale$2, { - maximumSignificantDigits: 4 - }) - }); -} - -/** - * Returns a localized representation of the given area measurement. - * - * @param {Number} m2 area in square meters - * @param {Boolean} isImperial true for U.S. customary units; false for metric - */ -function displayArea(m2 , isImperial ) { - var d = m2 * (isImperial ? 10.7639111056 : 1), - d1, d2, area; - var unit1 = ''; - var unit2 = ''; - - if (isImperial) { - if (d >= 6969600) { // > 0.25mi² show mi² - d1 = d / 27878400; - unit1 = 'square_miles'; - } else { - d1 = d; - unit1 = 'square_feet'; - } - - if (d > 4356 && d < 43560000) { // 0.1 - 1000 acres - d2 = d / 43560; - unit2 = 'acres'; - } - - } else { - if (d >= 250000) { // > 0.25km² show km² - d1 = d / 1000000; - unit1 = 'square_kilometers'; - } else { - d1 = d; - unit1 = 'square_meters'; - } - - if (d > 1000 && d < 10000000) { // 0.1 - 1000 hectares - d2 = d / 10000; - unit2 = 'hectares'; - } - } - - area = t('units.' + unit1, { - quantity: d1.toLocaleString(locale$2, { - maximumSignificantDigits: 4 - }) - }); - - if (d2) { - return t('units.area_pair', { - area1: area, - area2: t('units.' + unit2, { - quantity: d2.toLocaleString(locale$2, { - maximumSignificantDigits: 2 - }) - }) - }); - } else { - return area; - } -} - -function wrap(x , min , max ) { - var d = max - min; - return ((x - min) % d + d) % d + min; -} - -function clamp(x , min , max ) { - return Math.max(min, Math.min(x, max)); -} - -function displayCoordinate(deg , pos , neg ) { - var min = (Math.abs(deg) - Math.floor(Math.abs(deg))) * 60, - sec = (min - Math.floor(min)) * 60, - displayDegrees = t('units.arcdegrees', { - quantity: Math.floor(Math.abs(deg)).toLocaleString(locale$2) - }), - displayCoordinate; - - if (Math.floor(sec) > 0) { - displayCoordinate = displayDegrees + - t('units.arcminutes', { - quantity: Math.floor(min).toLocaleString(locale$2) - }) + - t('units.arcseconds', { - quantity: Math.round(sec).toLocaleString(locale$2) - }); - } else if (Math.floor(min) > 0) { - displayCoordinate = displayDegrees + - t('units.arcminutes', { - quantity: Math.round(min).toLocaleString(locale$2) - }); - } else { - displayCoordinate = t('units.arcdegrees', { - quantity: Math.round(Math.abs(deg)).toLocaleString(locale$2) - }); - } - - if (deg === 0) { - return displayCoordinate; - } else { - return t('units.coordinate', { - coordinate: displayCoordinate, - direction: t('units.' + (deg > 0 ? pos : neg)) - }); - } -} - -/** - * Returns given coordinate pair in degree-minute-second format. - * - * @param {Array} coord longitude and latitude - */ -function dmsCoordinatePair(coord ) { - return t('units.coordinate_pair', { - latitude: displayCoordinate(clamp(coord[1], -90, 90), 'north', 'south'), - longitude: displayCoordinate(wrap(coord[0], -180, 180), 'east', 'west') - }); -} - -/** - * Returns the given coordinate pair in decimal format. - * note: unlocalized to avoid comma ambiguity - see #4765 - * - * @param {Array} coord longitude and latitude - */ -function decimalCoordinatePair(coord ) { - return t('units.coordinate_pair', { - latitude: clamp(coord[1], -90, 90).toFixed(OSM_PRECISION), - longitude: wrap(coord[0], -180, 180).toFixed(OSM_PRECISION) - }); -} - -function uiPanelLocation(context) { - var currLocation = ''; - - - function redraw(selection) { - selection.html(''); - - var list = selection - .append('ul'); - - // Mouse coordinates - var coord = context.map().mouseCoordinates(); - if (coord.some(isNaN)) { - coord = context.map().center(); - } + // display options + _displayOptionsContainer = content + .append('div') + .attr('class', 'background-display-options'); - list - .append('li') - .text(dmsCoordinatePair(coord)) - .append('li') - .text(decimalCoordinatePair(coord)); + // offset controls + _offsetContainer = content + .append('div') + .attr('class', 'background-offset'); - // Location Info - selection - .append('div') - .attr('class', 'location-info') - .text(currLocation || ' '); - debouncedGetLocation(selection, coord); - } + // add listeners + context.map() + .on('move.background-update', debounce(utilCallWhenIdle(update), 1000)); + context.background() + .on('change.background-update', update); - var debouncedGetLocation = debounce(getLocation, 250); - function getLocation(selection, coord) { - if (!services.geocoder) { - currLocation = t('info_panels.location.unknown_location'); - selection.selectAll('.location-info') - .text(currLocation); - } else { - services.geocoder.reverse(coord, function(err, result) { - currLocation = result ? result.display_name : t('info_panels.location.unknown_location'); - selection.selectAll('.location-info') - .text(currLocation); - }); - } - } + update(); - var panel = function(selection) { - selection.call(redraw); + var keybinding = d3keybinding('background') + .on(key, togglePane) + .on(uiCmd('⌘' + key), quickSwitch) + .on([t('map_data.key'), t('help.key')], hidePane); - context.surface() - .on('mousemove.info-location', function() { - selection.call(redraw); - }); - }; + select(document) + .call(keybinding); - panel.off = function() { - context.surface() - .on('mousemove.info-location', null); - }; + uiBackground.hidePane = hidePane; + uiBackground.togglePane = togglePane; + uiBackground.setVisible = setVisible; + } - panel.id = 'location'; - panel.title = t('info_panels.location.title'); - panel.key = t('info_panels.location.key'); + return background; + } + function uiContributors(context) { + var osm = context.connection(), + debouncedUpdate = debounce(function() { update(); }, 1000), + limit = 4, + hidden = false, + wrap = select(null); - return panel; -} -function uiPanelMeasurement(context) { - var locale = utilDetect().locale, - isImperial = (locale.toLowerCase() === 'en-us'); + function update() { + if (!osm) return; + var users = {}, + entities = context.intersects(context.map().extent()); - function radiansToMeters(r) { - // using WGS84 authalic radius (6371007.1809 m) - return r * 6371007.1809; - } + entities.forEach(function(entity) { + if (entity && entity.user) users[entity.user] = true; + }); - function steradiansToSqmeters(r) { - // http://gis.stackexchange.com/a/124857/40446 - return r / (4 * Math.PI) * 510065621724000; - } + var u = Object.keys(users), + subset = u.slice(0, u.length > limit ? limit - 1 : limit); + wrap.html('') + .call(svgIcon('#icon-nearby', 'pre-text light')); - function toLineString(feature) { - if (feature.type === 'LineString') return feature; + var userList = select(document.createElement('span')); - var result = { type: 'LineString', coordinates: [] }; - if (feature.type === 'Polygon') { - result.coordinates = feature.coordinates[0]; - } else if (feature.type === 'MultiPolygon') { - result.coordinates = feature.coordinates[0][0]; - } + userList.selectAll() + .data(subset) + .enter() + .append('a') + .attr('class', 'user-link') + .attr('href', function(d) { return osm.userURL(d); }) + .attr('target', '_blank') + .attr('tabindex', -1) + .text(String); - return result; - } + if (u.length > limit) { + var count = select(document.createElement('span')); - function nodeCount(feature) { - if (feature.type === 'LineString') return feature.coordinates.length; + count.append('a') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', function() { + return osm.changesetsURL(context.map().center(), context.map().zoom()); + }) + .text(u.length - limit + 1); - if (feature.type === 'Polygon') { - return feature.coordinates[0].length - 1; - } - } + wrap.append('span') + .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() })); + } else { + wrap.append('span') + .html(t('contributors.list', { users: userList.html() })); + } - function redraw(selection$$1) { - var resolver = context.graph(); - var selected = filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }); - var singular = selected.length === 1 ? selected[0] : null; - var extent = geoExtent$$1(); - var entity; + if (!u.length) { + hidden = true; + wrap + .transition() + .style('opacity', 0); - selection$$1.html(''); + } else if (hidden) { + wrap + .transition() + .style('opacity', 1); + } + } - selection$$1 - .append('h4') - .attr('class', 'measurement-heading') - .text(singular || t('info_panels.measurement.selected', { n: selected.length.toLocaleString(locale) })); - if (!selected.length) return; + return function(selection$$1) { + if (!osm) return; + wrap = selection$$1; + update(); - var center; - for (var i = 0; i < selected.length; i++) { - entity = context.entity(selected[i]); - extent._extend(entity.extent(resolver)); - } - center = extent.center(); - - - var list = selection$$1 - .append('ul'); - var coordItem; - - // multiple features, just display extent center.. - if (!singular) { - coordItem = list - .append('li') - .text(t('info_panels.measurement.center') + ':'); - coordItem.append('span') - .text(dmsCoordinatePair(center)); - coordItem.append('span') - .text(decimalCoordinatePair(center)); - return; - } + osm.on('loaded.contributors', debouncedUpdate); + context.map().on('move.contributors', debouncedUpdate); + }; + } - // single feature, display details.. - if (!entity) return; - var geometry = entity.geometry(resolver); - - if (geometry === 'line' || geometry === 'area') { - var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()), - feature = entity.asGeoJSON(resolver), - length = radiansToMeters(d3_geoLength(toLineString(feature))), - lengthLabel = t('info_panels.measurement.' + (closed ? 'perimeter' : 'length')), - centroid = d3_geoCentroid(feature); - - list - .append('li') - .text(t('info_panels.measurement.geometry') + ':') - .append('span') - .text( - closed ? t('info_panels.measurement.closed_' + geometry) : t('geometry.' + geometry) - ); - - if (entity.type !== 'relation') { - list - .append('li') - .text(t('info_panels.measurement.node_count') + ':') - .append('span') - .text(nodeCount(feature).toLocaleString(locale)); - } + function uiFeatureInfo(context) { + function update(selection$$1) { + var features = context.features(), + stats = features.stats(), + count = 0, + hiddenList = compact(map$3(features.hidden(), function(k) { + if (stats[k]) { + count += stats[k]; + return String(stats[k]) + ' ' + t('feature.' + k + '.description'); + } + })); + + selection$$1.html(''); + + if (hiddenList.length) { + var tooltipBehavior = tooltip() + .placement('top') + .html(true) + .title(function() { + return uiTooltipHtml(hiddenList.join('
    ')); + }); + + var warning = selection$$1.append('a') + .attr('href', '#') + .attr('tabindex', -1) + .html(t('feature_info.hidden_warning', { count: count })) + .call(tooltipBehavior) + .on('click', function() { + tooltipBehavior.hide(warning); + // open map data panel? + event.preventDefault(); + }); + } - if (closed) { - var area = steradiansToSqmeters(entity.area(resolver)); - list - .append('li') - .text(t('info_panels.measurement.area') + ':') - .append('span') - .text(displayArea(area, isImperial)); - } + selection$$1 + .classed('hide', !hiddenList.length); + } - list - .append('li') - .text(lengthLabel + ':') - .append('span') - .text(displayLength(length, isImperial)); - - coordItem = list - .append('li') - .text(t('info_panels.measurement.centroid') + ':'); - coordItem.append('span') - .text(dmsCoordinatePair(centroid)); - coordItem.append('span') - .text(decimalCoordinatePair(centroid)); - - var toggle = isImperial ? 'imperial' : 'metric'; - - selection$$1 - .append('a') - .text(t('info_panels.measurement.' + toggle)) - .attr('href', '#') - .attr('class', 'button button-toggle-units') - .on('click', function() { - event.preventDefault(); - isImperial = !isImperial; - selection$$1.call(redraw); - }); + return function(selection$$1) { + update(selection$$1); - } else { - var centerLabel = t('info_panels.measurement.' + (entity.type === 'node' ? 'location' : 'center')); - - list - .append('li') - .text(t('info_panels.measurement.geometry') + ':') - .append('span') - .text(t('geometry.' + geometry)); - - coordItem = list - .append('li') - .text(centerLabel + ':'); - coordItem.append('span') - .text(dmsCoordinatePair(center)); - coordItem.append('span') - .text(decimalCoordinatePair(center)); - } - } + context.features().on('change.feature_info', function() { + update(selection$$1); + }); + }; + } + function uiFullScreen(context) { + var element = context.container().node(), + keybinding = d3keybinding('full-screen'); + // button; + + + function getFullScreenFn() { + if (element.requestFullscreen) { + return element.requestFullscreen; + } else if (element.msRequestFullscreen) { + return element.msRequestFullscreen; + } else if (element.mozRequestFullScreen) { + return element.mozRequestFullScreen; + } else if (element.webkitRequestFullscreen) { + return element.webkitRequestFullscreen; + } + } - var panel = function(selection$$1) { - selection$$1.call(redraw); - context.map() - .on('drawn.info-measurement', function() { - selection$$1.call(redraw); - }); - }; + function getExitFullScreenFn() { + if (document.exitFullscreen) { + return document.exitFullscreen; + } else if (document.msExitFullscreen) { + return document.msExitFullscreen; + } else if (document.mozCancelFullScreen) { + return document.mozCancelFullScreen; + } else if (document.webkitExitFullscreen) { + return document.webkitExitFullscreen; + } + } - panel.off = function() { - context.map() - .on('drawn.info-measurement', null); - }; - panel.id = 'measurement'; - panel.title = t('info_panels.measurement.title'); - panel.key = t('info_panels.measurement.key'); + function isFullScreen() { + return document.fullscreenElement || + document.mozFullScreenElement || + document.webkitFullscreenElement || + document.msFullscreenElement; + } - return panel; -} + function isSupported() { + return !!getFullScreenFn(); + } -var uiInfoPanels = { - background: uiPanelBackground, - history: uiPanelHistory, - location: uiPanelLocation, - measurement: uiPanelMeasurement, -}; -function uiInfo(context) { - var ids = Object.keys(uiInfoPanels), - wasActive = ['measurement'], - panels = {}, - active = {}; + function fullScreen() { + event.preventDefault(); + if (!isFullScreen()) { + // button.classed('active', true); + getFullScreenFn().apply(element); + } else { + // button.classed('active', false); + getExitFullScreenFn().apply(document); + } + } - // create panels - ids.forEach(function(k) { - if (!panels[k]) { - panels[k] = uiInfoPanels[k](context); - active[k] = false; - } - }); + return function() { // selection) { + if (!isSupported()) + return; - function info(selection$$1) { + // button = selection.append('button') + // .attr('title', t('full_screen')) + // .attr('tabindex', -1) + // .on('click', fullScreen) + // .call(tooltip); - function redraw() { - var activeids = ids.filter(function(k) { return active[k]; }).sort(); + // button.append('span') + // .attr('class', 'icon full-screen'); - var containers = infoPanels.selectAll('.panel-container') - .data(activeids, function(k) { return k; }); + var detected = utilDetect(); + var keys = detected.os === 'mac' ? [uiCmd('⌃⌘F'), 'f11'] : ['f11']; + keybinding.on(keys, fullScreen); - containers.exit() - .style('opacity', 1) - .transition() - .duration(200) - .style('opacity', 0) - .on('end', function(d) { - d3_select(this) - .call(panels[d].off) - .remove(); - }); + select(document) + .call(keybinding); + }; + } - var enter = containers.enter() - .append('div') - .attr('class', function(d) { return 'fillD2 panel-container panel-container-' + d; }); + function uiLoading(context) { + var _modalSelection = select(null); + var _message = ''; + var _blocking = false; - enter - .style('opacity', 0) - .transition() - .duration(200) - .style('opacity', 1); - var title = enter - .append('div') - .attr('class', 'panel-title fillD2'); + var loading = function(selection$$1) { + _modalSelection = uiModal(selection$$1, _blocking); - title - .append('h3') - .text(function(d) { return panels[d].title; }); + var loadertext = _modalSelection.select('.content') + .classed('loading-modal', true) + .append('div') + .attr('class', 'modal-section fillL'); - title - .append('button') - .attr('class', 'close') - .on('click', function (d) { toggle(d); }) - .call(svgIcon('#icon-close')); + loadertext + .append('img') + .attr('class', 'loader') + .attr('src', context.imagePath('loader-white.gif')); - enter - .append('div') - .attr('class', function(d) { return 'panel-content panel-content-' + d; }); + loadertext + .append('h3') + .text(_message); + _modalSelection.select('button.close') + .attr('class', 'hide'); - // redraw the panels - infoPanels.selectAll('.panel-content') - .each(function(d) { - d3_select(this).call(panels[d]); - }); - } + return loading; + }; - function toggle(which) { - if (event) { - event.stopImmediatePropagation(); - event.preventDefault(); - } + loading.message = function(_) { + if (!arguments.length) return _message; + _message = _; + return loading; + }; - var activeids = ids.filter(function(k) { return active[k]; }); - - if (which) { // toggle one - active[which] = !active[which]; - if (activeids.length === 1 && activeids[0] === which) { // none active anymore - wasActive = [which]; - } - } else { // toggle all - if (activeids.length) { - wasActive = activeids; - activeids.forEach(function(k) { active[k] = false; }); - } else { - wasActive.forEach(function(k) { active[k] = true; }); - } - } - redraw(); - } + loading.blocking = function(_) { + if (!arguments.length) return _blocking; + _blocking = _; + return loading; + }; - var infoPanels = selection$$1.selectAll('.info-panels') - .data([0]); + loading.close = function() { + _modalSelection.remove(); + }; - infoPanels = infoPanels.enter() - .append('div') - .attr('class', 'info-panels') - .merge(infoPanels); - redraw(); + return loading; + } - var keybinding = d3keybinding('info') - .on(uiCmd('⌘' + t('info_panels.key')), toggle); + function uiGeolocate(context) { + var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ }, + locating = uiLoading(context).message(t('geolocate.locating')).blocking(true), + timeoutId; - ids.forEach(function(k) { - var key = t('info_panels.' + k + '.key', { default: null }); - if (!key) return; - keybinding - .on(uiCmd('⌘⇧' + key), function() { toggle(k); }); - }); - d3_select(document) - .call(keybinding); - } + function click() { + if (context.inIntro()) return; + context.enter(modeBrowse(context)); + context.container().call(locating); + navigator.geolocation.getCurrentPosition(success, error, geoOptions); - return info; -} + // This timeout ensures that we still call finish() even if + // the user declines to share their location in Firefox + timeoutId = setTimeout(finish, 10000 /* 10sec */ ); + } -function uiModes(context) { - var modes = [ - modeAddPoint$$1(context), - modeAddLine$$1(context), - modeAddArea$$1(context) - ]; + function success(position) { + var map = context.map(), + extent = geoExtent$$1([position.coords.longitude, position.coords.latitude]) + .padByMeters(position.coords.accuracy); - function editable() { - var mode = context.mode(); - return context.editable() && mode && mode.id !== 'save'; - } - - - return function(selection$$1) { - var buttons = selection$$1.selectAll('button.add-button') - .data(modes); - - buttons = buttons.enter() - .append('button') - .attr('tabindex', -1) - .attr('class', function(mode) { return mode.id + ' add-button col4'; }) - .on('click.mode-buttons', function(mode) { - // When drawing, ignore accidental clicks on mode buttons - #4042 - var currMode = context.mode().id; - if (currMode.match(/^draw/) !== null) return; - - if (mode.id === currMode) { - context.enter(modeBrowse(context)); - } else { - context.enter(mode); - } - }) - .call(tooltip() - .placement('bottom') - .html(true) - .title(function(mode) { - return uiTooltipHtml(mode.description, mode.key); - }) - ); + map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent))); + finish(); + } - buttons - .each(function(d) { - d3_select(this) - .call(svgIcon('#icon-' + d.button, 'pre-text')); - }); - buttons - .append('span') - .attr('class', 'label') - .text(function(mode) { return mode.title; }); - - context - .on('enter.editor', function(entered) { - selection$$1.selectAll('button.add-button') - .classed('active', function(mode) { return entered.button === mode.button; }); - context.container() - .classed('mode-' + entered.id, true); - }); + function error() { + finish(); + } - context - .on('exit.editor', function(exited) { - context.container() - .classed('mode-' + exited.id, false); - }); - var keybinding = d3keybinding('mode-buttons'); - - modes.forEach(function(mode) { - keybinding.on(mode.key, function() { - if (editable()) { - if (mode.id === context.mode().id) { - context.enter(modeBrowse(context)); - } else { - context.enter(mode); - } - } - }); - }); + function finish() { + locating.close(); // unblock ui + if (timeoutId) { clearTimeout(timeoutId); } + timeoutId = undefined; + } - d3_select(document) - .call(keybinding); + return function(selection) { + if (!navigator.geolocation) return; - var debouncedUpdate = debounce(update, 500, { leading: true, trailing: true }); + selection + .append('button') + .attr('tabindex', -1) + .attr('title', t('geolocate.title')) + .on('click', click) + .call(svgIcon('#icon-geolocate', 'light')) + .call(tooltip() + .placement((textDirection === 'rtl') ? 'right' : 'left')); + }; + } - context.map() - .on('move.modes', debouncedUpdate) - .on('drawn.modes', debouncedUpdate); + function uiPanelBackground(context) { + var background = context.background(); + var currSourceName = null; + var metadata = {}; + var metadataKeys = [ + 'zoom', 'vintage', 'source', 'description', 'resolution', 'accuracy' + ]; - context - .on('enter.modes', update); + var debouncedRedraw = debounce(redraw, 250); + function redraw(selection$$1) { + var source = background.baseLayerSource(), + isDG = (source.id.match(/^DigitalGlobe/i) !== null); + if (currSourceName !== source.name()) { + currSourceName = source.name(); + metadata = {}; + } - function update() { - selection$$1.selectAll('button.add-button') - .property('disabled', !editable()); - } - }; -} - -function uiNotice(context) { - - return function(selection$$1) { - var div = selection$$1 - .append('div') - .attr('class', 'notice'); - - var button = div - .append('button') - .attr('class', 'zoom-to notice fillD') - .on('click', function() { - context.map().zoomEase(context.minEditableZoom()); - }) - .on('wheel', function() { // let wheel events pass through #4482 - var e2 = new WheelEvent(event.type, event); - context.surface().node().dispatchEvent(e2); - }); + selection$$1.html(''); - button - .call(svgIcon('#icon-plus', 'pre-text')) - .append('span') - .attr('class', 'label') - .text(t('zoom_in_edit')); + var list = selection$$1 + .append('ul') + .attr('class', 'background-info'); + list + .append('li') + .text(currSourceName); - function disableTooHigh() { - var canEdit = context.map().zoom() >= context.minEditableZoom(); - div.style('display', canEdit ? 'none' : 'block'); - } + metadataKeys.forEach(function(k) { + // DigitalGlobe vintage is available in raster layers for now. + if (isDG && k === 'vintage') return; - context.map() - .on('move.notice', debounce(disableTooHigh, 500)); + list + .append('li') + .attr('class', 'background-info-list-' + k) + .classed('hide', !metadata[k]) + .text(t('info_panels.background.' + k) + ':') + .append('span') + .attr('class', 'background-info-span-' + k) + .text(metadata[k]); + }); - disableTooHigh(); - }; -} + debouncedGetMetadata(selection$$1); + + var toggleTiles = context.getDebug('tile') ? 'hide_tiles' : 'show_tiles'; + + selection$$1 + .append('a') + .text(t('info_panels.background.' + toggleTiles)) + .attr('href', '#') + .attr('class', 'button button-toggle-tiles') + .on('click', function() { + event.preventDefault(); + context.setDebug('tile', !context.getDebug('tile')); + selection$$1.call(redraw); + }); + + if (isDG) { + var key = source.id + '-vintage'; + var sourceVintage = context.background().findSource(key); + var showsVintage = context.background().showsLayer(sourceVintage); + var toggleVintage = showsVintage ? 'hide_vintage' : 'show_vintage'; + selection$$1 + .append('a') + .text(t('info_panels.background.' + toggleVintage)) + .attr('href', '#') + .attr('class', 'button button-toggle-vintage') + .on('click', function() { + event.preventDefault(); + context.background().toggleOverlayLayer(sourceVintage); + selection$$1.call(redraw); + }); + } -function uiRestore(context) { + // disable if necessary + ['DigitalGlobe-Premium', 'DigitalGlobe-Standard'].forEach(function(layerId) { + if (source.id !== layerId) { + var key = layerId + '-vintage'; + var sourceVintage = context.background().findSource(key); + if (context.background().showsLayer(sourceVintage)) { + context.background().toggleOverlayLayer(sourceVintage); + } + } + }); + } - return function(selection) { - if (!context.history().lock() || !context.history().restorableChanges()) - return; - var modalSelection = uiModal(selection, true); + var debouncedGetMetadata = debounce(getMetadata, 250); + + function getMetadata(selection$$1) { + var tile = select('.layer-background img.tile-center'); // tile near viewport center + if (tile.empty()) return; + + var sourceName = currSourceName, + d = tile.datum(), + zoom = (d && d.length >= 3 && d[2]) || Math.floor(context.map().zoom()), + center = context.map().center(); + + // update zoom + metadata.zoom = String(zoom); + selection$$1.selectAll('.background-info-list-zoom') + .classed('hide', false) + .selectAll('.background-info-span-zoom') + .text(metadata.zoom); + + if (!d || !d.length >= 3) return; + + background.baseLayerSource().getMetadata(center, d, function(err, result) { + if (err || currSourceName !== sourceName) return; + + // update vintage + var vintage = result.vintage; + metadata.vintage = (vintage && vintage.range) || t('info_panels.background.unknown'); + selection$$1.selectAll('.background-info-list-vintage') + .classed('hide', false) + .selectAll('.background-info-span-vintage') + .text(metadata.vintage); + + // update other metdata + without(metadataKeys, 'zoom', 'vintage') + .forEach(function(k) { + var val = result[k]; + metadata[k] = val; + selection$$1.selectAll('.background-info-list-' + k) + .classed('hide', !val) + .selectAll('.background-info-span-' + k) + .text(val); + }); + }); + } - modalSelection.select('.modal') - .attr('class', 'modal fillL col6'); - var introModal = modalSelection.select('.content'); + var panel = function(selection$$1) { + selection$$1.call(redraw); - introModal - .attr('class','cf'); + context.map() + .on('drawn.info-background', function() { + selection$$1.call(debouncedRedraw); + }) + .on('move.info-background', function() { + selection$$1.call(debouncedGetMetadata); + }); - introModal - .append('div') - .attr('class', 'modal-section') - .append('h3') - .text(t('restore.heading')); + }; - introModal - .append('div') - .attr('class','modal-section') - .append('p') - .text(t('restore.description')); + panel.off = function() { + context.map() + .on('drawn.info-background', null) + .on('move.info-background', null); + }; - var buttonWrap = introModal - .append('div') - .attr('class', 'modal-actions cf'); + panel.id = 'background'; + panel.title = t('info_panels.background.title'); + panel.key = t('info_panels.background.key'); - var restore = buttonWrap - .append('button') - .attr('class', 'restore col6') - .on('click', function() { - context.history().restore(); - modalSelection.remove(); - }); - restore - .append('svg') - .attr('class', 'logo logo-restore') - .append('use') - .attr('xlink:href', '#logo-restore'); - - restore - .append('div') - .text(t('restore.restore')); - - var reset = buttonWrap - .append('button') - .attr('class', 'reset col6') - .on('click', function() { - context.history().clearSaved(); - modalSelection.remove(); - }); + return panel; + } - reset - .append('svg') - .attr('class', 'logo logo-reset') - .append('use') - .attr('xlink:href', '#logo-reset'); + function uiPanelHistory(context) { + var osm; - reset - .append('div') - .text(t('restore.reset')); + function displayTimestamp(entity) { + if (!entity.timestamp) return t('info_panels.history.unknown'); + var detected = utilDetect(); + var options = { + day: 'numeric', month: 'short', year: 'numeric', + hour: 'numeric', minute: 'numeric', second: 'numeric' + }; + var d = new Date(entity.timestamp); + if (isNaN(d.getTime())) return t('info_panels.history.unknown'); + return d.toLocaleString(detected.locale, options); + } - restore.node().focus(); - }; -} -function uiSave(context) { - var history = context.history(); - var key = uiCmd('⌘S'); + function displayUser(selection, entity) { + if (!entity.user) { + selection + .append('span') + .text(t('info_panels.history.unknown')); + return; + } + selection + .append('span') + .attr('class', 'user-name') + .text(entity.user); + + var links = selection + .append('div') + .attr('class', 'links'); + + if (osm) { + links + .append('a') + .attr('class', 'user-osm-link') + .attr('href', osm.userURL(entity.user)) + .attr('target', '_blank') + .attr('tabindex', -1) + .text('OSM'); + } - function saving() { - var mode = context.mode(); - return mode && mode.id === 'save'; - } + links + .append('a') + .attr('class', 'user-hdyc-link') + .attr('href', 'https://hdyc.neis-one.org/?' + entity.user) + .attr('target', '_blank') + .attr('tabindex', -1) + .text('HDYC'); + } - function save() { - event.preventDefault(); - if (!context.inIntro() && !saving() && history.hasChanges()) { - context.enter(modeSave$$1(context)); - } - } + function displayChangeset(selection, entity) { + if (!entity.changeset) { + selection + .append('span') + .text(t('info_panels.history.unknown')); + return; + } + selection + .append('span') + .attr('class', 'changeset-id') + .text(entity.changeset); + + var links = selection + .append('div') + .attr('class', 'links'); + + if (osm) { + links + .append('a') + .attr('class', 'changeset-osm-link') + .attr('href', osm.changesetURL(entity.changeset)) + .attr('target', '_blank') + .attr('tabindex', -1) + .text('OSM'); + } - function getBackground(numChanges) { - var step; - if (numChanges === 0) { - return null; - } else if (numChanges <= 50) { - step = numChanges / 50; - return d3_interpolateRgb('#fff', '#ff8')(step); // white -> yellow - } else { - step = Math.min((numChanges - 50) / 50, 1.0); - return d3_interpolateRgb('#ff8', '#f88')(step); // yellow -> red - } - } + links + .append('a') + .attr('class', 'changeset-osmcha-link') + .attr('href', 'https://osmcha.mapbox.com/changesets/' + entity.changeset) + .attr('target', '_blank') + .attr('tabindex', -1) + .text('OSMCha'); + } - return function(selection$$1) { - var numChanges = 0; + function redraw(selection) { + var selected = filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }); + var singular = selected.length === 1 ? selected[0] : null; - function updateCount() { - var _ = history.difference().summary().length; - if (_ === numChanges) return; - numChanges = _; + osm = context.connection(); - tooltipBehavior - .title(uiTooltipHtml( - t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key) - ); + selection.html(''); - var background = getBackground(numChanges); + selection + .append('h4') + .attr('class', 'history-heading') + .text(singular || t('info_panels.history.selected', { n: selected.length })); - button - .classed('disabled', numChanges === 0) - .classed('has-count', numChanges > 0) - .style('background', background); + if (!singular) return; - button.select('span.count') - .text(numChanges) - .style('background', background) - .style('border-color', background); - } + var entity = context.entity(singular); + if (!entity.version) { + selection + .append('div') + .text(t('info_panels.history.no_history')); + return; + } - var tooltipBehavior = tooltip() - .placement('bottom') - .html(true) - .title(uiTooltipHtml(t('save.no_changes'), key)); + var list = selection + .append('ul'); + + list + .append('li') + .text(t('info_panels.history.version') + ':') + .append('span') + .text(entity.version); + + list + .append('li') + .text(t('info_panels.history.last_edit') + ':') + .append('span') + .text(displayTimestamp(entity)); + + list + .append('li') + .text(t('info_panels.history.edited_by') + ':') + .call(displayUser, entity); + + list + .append('li') + .text(t('info_panels.history.changeset') + ':') + .call(displayChangeset, entity); + + if (osm) { + selection + .append('a') + .attr('class', 'view-history-on-osm') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', osm.historyURL(entity)) + .call(svgIcon('#icon-out-link', 'inline')) + .append('span') + .text(t('info_panels.history.link_text')); + } + } - var button = selection$$1 - .append('button') - .attr('class', 'save col12 disabled') - .attr('tabindex', -1) - .on('click', save) - .call(tooltipBehavior); - button - .call(svgIcon('#icon-save', 'pre-text')) - .append('span') - .attr('class', 'label') - .text(t('save.title')); + var panel = function(selection) { + selection.call(redraw); - button - .append('span') - .attr('class', 'count') - .text('0'); + context.map() + .on('drawn.info-history', function() { + selection.call(redraw); + }); + }; - updateCount(); + panel.off = function() { + context.map() + .on('drawn.info-history', null); + }; + panel.id = 'history'; + panel.title = t('info_panels.history.title'); + panel.key = t('info_panels.history.key'); - var keybinding = d3keybinding('uiSave') - .on(key, save, true); - d3_select(document) - .call(keybinding); + return panel; + } - context.history() - .on('change.save', updateCount); + var OSM_PRECISION = 7; + var locale$2 = utilDetect().locale; - context - .on('enter.save', function() { - button.property('disabled', saving()); - if (saving()) button.call(tooltipBehavior.hide); - }); - }; -} + /** + * Returns a localized representation of the given length measurement. + * + * @param {Number} m area in meters + * @param {Boolean} isImperial true for U.S. customary units; false for metric + */ + function displayLength(m, isImperial) { + var d = m * (isImperial ? 3.28084 : 1); + var unit; + + if (isImperial) { + if (d >= 5280) { + d /= 5280; + unit = 'miles'; + } else { + unit = 'feet'; + } + } else { + if (d >= 1000) { + d /= 1000; + unit = 'kilometers'; + } else { + unit = 'meters'; + } + } -function uiScale(context) { - var projection = context.projection, - isImperial = (utilDetect().locale.toLowerCase() === 'en-us'), - maxLength = 180, - tickHeight = 8; + return t('units.' + unit, { + quantity: d.toLocaleString(locale$2, { + maximumSignificantDigits: 4 + }) + }); + } + /** + * Returns a localized representation of the given area measurement. + * + * @param {Number} m2 area in square meters + * @param {Boolean} isImperial true for U.S. customary units; false for metric + */ + function displayArea(m2, isImperial) { + var d = m2 * (isImperial ? 10.7639111056 : 1); + var d1, d2, area; + var unit1 = ''; + var unit2 = ''; + + if (isImperial) { + if (d >= 6969600) { // > 0.25mi² show mi² + d1 = d / 27878400; + unit1 = 'square_miles'; + } else { + d1 = d; + unit1 = 'square_feet'; + } - function scaleDefs(loc1, loc2) { - var lat = (loc2[1] + loc1[1]) / 2, - conversion = (isImperial ? 3.28084 : 1), - dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion, - scale = { dist: 0, px: 0, text: '' }, - buckets, i, val, dLon; + if (d > 4356 && d < 43560000) { // 0.1 - 1000 acres + d2 = d / 43560; + unit2 = 'acres'; + } - if (isImperial) { - buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1]; - } else { - buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1]; - } + } else { + if (d >= 250000) { // > 0.25km² show km² + d1 = d / 1000000; + unit1 = 'square_kilometers'; + } else { + d1 = d; + unit1 = 'square_meters'; + } - // determine a user-friendly endpoint for the scale - for (i = 0; i < buckets.length; i++) { - val = buckets[i]; - if (dist >= val) { - scale.dist = Math.floor(dist / val) * val; - break; - } else { - scale.dist = +dist.toFixed(2); - } - } + if (d > 1000 && d < 10000000) { // 0.1 - 1000 hectares + d2 = d / 10000; + unit2 = 'hectares'; + } + } + + area = t('units.' + unit1, { + quantity: d1.toLocaleString(locale$2, { + maximumSignificantDigits: 4 + }) + }); - dLon = geoMetersToLon(scale.dist / conversion, lat); - scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]); + if (d2) { + return t('units.area_pair', { + area1: area, + area2: t('units.' + unit2, { + quantity: d2.toLocaleString(locale$2, { + maximumSignificantDigits: 2 + }) + }) + }); + } else { + return area; + } + } - scale.text = displayLength(scale.dist / conversion, isImperial); + function wrap(x, min, max) { + var d = max - min; + return ((x - min) % d + d) % d + min; + } - return scale; - } + function clamp(x, min, max) { + return Math.max(min, Math.min(x, max)); + } + function displayCoordinate(deg, pos, neg) { + var min = (Math.abs(deg) - Math.floor(Math.abs(deg))) * 60; + var sec = (min - Math.floor(min)) * 60; + var displayDegrees = t('units.arcdegrees', { + quantity: Math.floor(Math.abs(deg)).toLocaleString(locale$2) + }); + var displayCoordinate; + + if (Math.floor(sec) > 0) { + displayCoordinate = displayDegrees + + t('units.arcminutes', { + quantity: Math.floor(min).toLocaleString(locale$2) + }) + + t('units.arcseconds', { + quantity: Math.round(sec).toLocaleString(locale$2) + }); + } else if (Math.floor(min) > 0) { + displayCoordinate = displayDegrees + + t('units.arcminutes', { + quantity: Math.round(min).toLocaleString(locale$2) + }); + } else { + displayCoordinate = t('units.arcdegrees', { + quantity: Math.round(Math.abs(deg)).toLocaleString(locale$2) + }); + } - function update(selection) { - // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn) - var dims = context.map().dimensions(), - loc1 = projection.invert([0, dims[1]]), - loc2 = projection.invert([maxLength, dims[1]]), - scale = scaleDefs(loc1, loc2); + if (deg === 0) { + return displayCoordinate; + } else { + return t('units.coordinate', { + coordinate: displayCoordinate, + direction: t('units.' + (deg > 0 ? pos : neg)) + }); + } + } - selection.select('#scale-path') - .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight); + /** + * Returns given coordinate pair in degree-minute-second format. + * + * @param {Array} coord longitude and latitude + */ + function dmsCoordinatePair(coord) { + return t('units.coordinate_pair', { + latitude: displayCoordinate(clamp(coord[1], -90, 90), 'north', 'south'), + longitude: displayCoordinate(wrap(coord[0], -180, 180), 'east', 'west') + }); + } - selection.select('#scale-textgroup') - .attr('transform', 'translate(' + (scale.px + 8) + ',' + tickHeight + ')'); + /** + * Returns the given coordinate pair in decimal format. + * note: unlocalized to avoid comma ambiguity - see #4765 + * + * @param {Array} coord longitude and latitude + */ + function decimalCoordinatePair(coord) { + return t('units.coordinate_pair', { + latitude: clamp(coord[1], -90, 90).toFixed(OSM_PRECISION), + longitude: wrap(coord[0], -180, 180).toFixed(OSM_PRECISION) + }); + } - selection.select('#scale-text') - .text(scale.text); - } + function uiPanelLocation(context) { + var currLocation = ''; - return function(selection) { - function switchUnits() { - isImperial = !isImperial; - selection.call(update); - } + function redraw(selection) { + selection.html(''); - var scalegroup = selection.append('svg') - .attr('id', 'scale') - .on('click', switchUnits) - .append('g') - .attr('transform', 'translate(10,11)'); + var list = selection + .append('ul'); - scalegroup - .append('path') - .attr('id', 'scale-path'); + // Mouse coordinates + var coord = context.map().mouseCoordinates(); + if (coord.some(isNaN)) { + coord = context.map().center(); + } - scalegroup - .append('g') - .attr('id', 'scale-textgroup') - .append('text') - .attr('id', 'scale-text'); + list + .append('li') + .text(dmsCoordinatePair(coord)) + .append('li') + .text(decimalCoordinatePair(coord)); - selection.call(update); + // Location Info + selection + .append('div') + .attr('class', 'location-info') + .text(currLocation || ' '); - context.map().on('move.scale', function() { - update(selection); - }); - }; -} + debouncedGetLocation(selection, coord); + } -var pair_1 = pair$1; -function search(x, dims, r) { - if (!dims) dims = 'NSEW'; - if (typeof x !== 'string') return { val: null, regex: r }; + var debouncedGetLocation = debounce(getLocation, 250); + function getLocation(selection, coord) { + if (!services.geocoder) { + currLocation = t('info_panels.location.unknown_location'); + selection.selectAll('.location-info') + .text(currLocation); + } else { + services.geocoder.reverse(coord, function(err, result) { + currLocation = result ? result.display_name : t('info_panels.location.unknown_location'); + selection.selectAll('.location-info') + .text(currLocation); + }); + } + } - r = r || /[\s\,]*([NSEW])?\s*([\-|\—|\―]?[0-9.]+)°?\s*(?:([0-9.]+)['’′‘]\s*)?(?:([0-9.]+)(?:''|"|”|″)\s*)?([NSEW])?/gi; - var m = r.exec(x); - if (!m) return { val: null, regex: r }; + var panel = function(selection) { + selection.call(redraw); - var dim = m[1] || m[5]; - if (dim && dims.indexOf(dim) === -1) return { val: null, regex: r }; + context.surface() + .on('mousemove.info-location', function() { + selection.call(redraw); + }); + }; - return { - val: (((m[2]) ? parseFloat(m[2]) : 0) + - ((m[3] ? parseFloat(m[3]) / 60 : 0)) + - ((m[4] ? parseFloat(m[4]) / 3600 : 0))) * - ((dim === 'S' || dim === 'W') ? -1 : 1), - regex: r, - raw: m[0], - dim: dim - }; -} - -function pair$1(x, dims) { - x = x.trim(); - var one = search(x, dims); - if (one.val === null) return null; - var two = search(x, dims, one.regex); - if (two.val === null) return null; - // null if one/two are not contiguous. - if (one.raw + two.raw !== x) return null; - if (one.dim) { - return swapdim(one.val, two.val, one.dim); - } else { - return [one.val, two.val]; - } -} - -function swapdim(a, b, dim) { - if (dim === 'N' || dim === 'S') return [a, b]; - if (dim === 'W' || dim === 'E') return [b, a]; -} - -function uiFeatureList(context) { - var keybinding = d3keybinding('uiFeatureList'); - var _geocodeResults; - - - function featureList(selection$$1) { - var header = selection$$1 - .append('div') - .attr('class', 'header fillL cf'); - - header - .append('h3') - .text(t('inspector.feature_list')); - - var searchWrap = selection$$1 - .append('div') - .attr('class', 'search-header'); - - var search = searchWrap - .append('input') - .attr('placeholder', t('inspector.search')) - .attr('type', 'search') - .call(utilNoAuto) - .on('keypress', keypress) - .on('keydown', keydown) - .on('input', inputevent); - - searchWrap - .call(svgIcon('#icon-search', 'pre-text')); - - var listWrap = selection$$1 - .append('div') - .attr('class', 'inspector-body'); - - var list = listWrap - .append('div') - .attr('class', 'feature-list cf'); - - context - .on('exit.feature-list', clearSearch); - context.map() - .on('drawn.feature-list', mapDrawn); - - keybinding - .on(uiCmd('⌘F'), focusSearch); - - d3_select(document) - .call(keybinding); - - - function focusSearch() { - var mode = context.mode() && context.mode().id; - if (mode !== 'browse') return; - - event.preventDefault(); - search.node().focus(); - } + panel.off = function() { + context.surface() + .on('mousemove.info-location', null); + }; + panel.id = 'location'; + panel.title = t('info_panels.location.title'); + panel.key = t('info_panels.location.key'); - function keydown() { - if (event.keyCode === 27) { // escape - search.node().blur(); - } - } + return panel; + } - function keypress() { - var q = search.property('value'), - items = list.selectAll('.feature-list-item'); - if (event.keyCode === 13 && q.length && items.size()) { // return - click(items.datum()); - } - } + function uiPanelMeasurement(context) { + var locale = utilDetect().locale, + isImperial = (locale.toLowerCase() === 'en-us'); - function inputevent() { - _geocodeResults = undefined; - drawList(); - } + function radiansToMeters(r) { + // using WGS84 authalic radius (6371007.1809 m) + return r * 6371007.1809; + } + function steradiansToSqmeters(r) { + // http://gis.stackexchange.com/a/124857/40446 + return r / (4 * Math.PI) * 510065621724000; + } - function clearSearch() { - search.property('value', ''); - drawList(); - } + function toLineString(feature) { + if (feature.type === 'LineString') return feature; - function mapDrawn(e) { - if (e.full) { - drawList(); - } - } + var result = { type: 'LineString', coordinates: [] }; + if (feature.type === 'Polygon') { + result.coordinates = feature.coordinates[0]; + } else if (feature.type === 'MultiPolygon') { + result.coordinates = feature.coordinates[0][0]; + } + return result; + } - function features() { - var entities = {}; - var result = []; - var graph = context.graph(); - var q = search.property('value').toLowerCase(); + function nodeCount(feature) { + if (feature.type === 'LineString') return feature.coordinates.length; - if (!q) return result; + if (feature.type === 'Polygon') { + return feature.coordinates[0].length - 1; + } + } - var idMatch = q.match(/^([nwr])([0-9]+)$/); - if (idMatch) { - result.push({ - id: idMatch[0], - geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation', - type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'), - name: idMatch[2] - }); - } + function redraw(selection$$1) { + var resolver = context.graph(); + var selected = filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }); + var singular = selected.length === 1 ? selected[0] : null; + var extent = geoExtent$$1(); + var entity; - var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/); - - if (locationMatch) { - var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])]; - result.push({ - id: -1, - geometry: 'point', - type: t('inspector.location'), - name: dmsCoordinatePair([loc[1], loc[0]]), - location: loc - }); - } + selection$$1.html(''); - function addEntity(entity) { - if (entity.id in entities || result.length > 200) - return; - - entities[entity.id] = true; - - var name = utilDisplayName(entity) || ''; - if (name.toLowerCase().indexOf(q) >= 0) { - var matched = context.presets().match(entity, graph); - var type = (matched && matched.name()) || utilDisplayType(entity.id); - - result.push({ - id: entity.id, - entity: entity, - geometry: context.geometry(entity.id), - type: type, - name: name - }); - } - - graph.parentRelations(entity).forEach(function(parent) { - addEntity(parent); - }); - } + selection$$1 + .append('h4') + .attr('class', 'measurement-heading') + .text(singular || t('info_panels.measurement.selected', { n: selected.length.toLocaleString(locale) })); - var visible = context.surface().selectAll('.point, .line, .area').nodes(); - for (var i = 0; i < visible.length && result.length <= 200; i++) { - var datum = visible[i].__data__; - var entity = datum && datum.properties && datum.properties.entity; - if (entity) { addEntity(entity); } - } + if (!selected.length) return; - (_geocodeResults || []).forEach(function(d) { - if (d.osm_type && d.osm_id) { // some results may be missing these - #1890 - - // Make a temporary osmEntity so we can preset match - // and better localize the search result - #4725 - var id = osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id); - var tags = {}; - tags[d.class] = d.type; - - var attrs = { id: id, type: d.osm_type, tags: tags }; - if (d.osm_type === 'way') { // for ways, add some fake closed nodes - attrs.nodes = ['a','a']; // so that geometry area is possible - } - - var tempEntity = osmEntity$$1(attrs); - var tempGraph = coreGraph$$1([tempEntity]); - var matched = context.presets().match(tempEntity, tempGraph); - var type = (matched && matched.name()) || utilDisplayType(id); - - result.push({ - id: tempEntity.id, - geometry: tempEntity.geometry(tempGraph), - type: type, - name: d.display_name, - extent: new geoExtent$$1( - [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])], - [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])]) - }); - } - }); + var center; + for (var i = 0; i < selected.length; i++) { + entity = context.entity(selected[i]); + extent._extend(entity.extent(resolver)); + } + center = extent.center(); + + + var list = selection$$1 + .append('ul'); + var coordItem; + + // multiple features, just display extent center.. + if (!singular) { + coordItem = list + .append('li') + .text(t('info_panels.measurement.center') + ':'); + coordItem.append('span') + .text(dmsCoordinatePair(center)); + coordItem.append('span') + .text(decimalCoordinatePair(center)); + return; + } - return result; - } + // single feature, display details.. + if (!entity) return; + var geometry = entity.geometry(resolver); + if (geometry === 'line' || geometry === 'area') { + var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()), + feature = entity.asGeoJSON(resolver), + length = radiansToMeters(length$1(toLineString(feature))), + lengthLabel = t('info_panels.measurement.' + (closed ? 'perimeter' : 'length')), + centroid = d3_geoCentroid(feature); - function drawList() { - var value = search.property('value'); - var results = features(); + list + .append('li') + .text(t('info_panels.measurement.geometry') + ':') + .append('span') + .text( + closed ? t('info_panels.measurement.closed_' + geometry) : t('geometry.' + geometry) + ); + + if (entity.type !== 'relation') { + list + .append('li') + .text(t('info_panels.measurement.node_count') + ':') + .append('span') + .text(nodeCount(feature).toLocaleString(locale)); + } + + if (closed) { + var area = steradiansToSqmeters(entity.area(resolver)); + list + .append('li') + .text(t('info_panels.measurement.area') + ':') + .append('span') + .text(displayArea(area, isImperial)); + } + + + list + .append('li') + .text(lengthLabel + ':') + .append('span') + .text(displayLength(length, isImperial)); + + coordItem = list + .append('li') + .text(t('info_panels.measurement.centroid') + ':'); + coordItem.append('span') + .text(dmsCoordinatePair(centroid)); + coordItem.append('span') + .text(decimalCoordinatePair(centroid)); + + var toggle = isImperial ? 'imperial' : 'metric'; + + selection$$1 + .append('a') + .text(t('info_panels.measurement.' + toggle)) + .attr('href', '#') + .attr('class', 'button button-toggle-units') + .on('click', function() { + event.preventDefault(); + isImperial = !isImperial; + selection$$1.call(redraw); + }); - list.classed('filtered', value.length); + } else { + var centerLabel = t('info_panels.measurement.' + (entity.type === 'node' ? 'location' : 'center')); - var noResultsWorldwide = _geocodeResults && _geocodeResults.length === 0; + list + .append('li') + .text(t('info_panels.measurement.geometry') + ':') + .append('span') + .text(t('geometry.' + geometry)); + + coordItem = list + .append('li') + .text(centerLabel + ':'); + coordItem.append('span') + .text(dmsCoordinatePair(center)); + coordItem.append('span') + .text(decimalCoordinatePair(center)); + } + } - var resultsIndicator = list.selectAll('.no-results-item') - .data([0]) - .enter() - .append('button') - .property('disabled', true) - .attr('class', 'no-results-item') - .call(svgIcon('#icon-alert', 'pre-text')); - resultsIndicator.append('span') - .attr('class', 'entity-name'); + var panel = function(selection$$1) { + selection$$1.call(redraw); - list.selectAll('.no-results-item .entity-name') - .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible')); + context.map() + .on('drawn.info-measurement', function() { + selection$$1.call(redraw); + }); + }; - if (services.geocoder) { - list.selectAll('.geocode-item') - .data([0]) - .enter() - .append('button') - .attr('class', 'geocode-item') - .on('click', geocoderSearch) - .append('div') - .attr('class', 'label') - .append('span') - .attr('class', 'entity-name') - .text(t('geocoder.search')); - } + panel.off = function() { + context.map() + .on('drawn.info-measurement', null); + }; - list.selectAll('.no-results-item') - .style('display', (value.length && !results.length) ? 'block' : 'none'); + panel.id = 'measurement'; + panel.title = t('info_panels.measurement.title'); + panel.key = t('info_panels.measurement.key'); - list.selectAll('.geocode-item') - .style('display', (value && _geocodeResults === undefined) ? 'block' : 'none'); - list.selectAll('.feature-list-item') - .data([-1]) - .remove(); + return panel; + } - var items = list.selectAll('.feature-list-item') - .data(results, function(d) { return d.id; }); + var uiInfoPanels = { + background: uiPanelBackground, + history: uiPanelHistory, + location: uiPanelLocation, + measurement: uiPanelMeasurement, + }; - var enter = items.enter() - .insert('button', '.geocode-item') - .attr('class', 'feature-list-item') - .on('mouseover', mouseover) - .on('mouseout', mouseout) - .on('click', click); + function uiInfo(context) { + var ids = Object.keys(uiInfoPanels), + wasActive = ['measurement'], + panels = {}, + active = {}; + + // create panels + ids.forEach(function(k) { + if (!panels[k]) { + panels[k] = uiInfoPanels[k](context); + active[k] = false; + } + }); - var label = enter - .append('div') - .attr('class', 'label'); - label - .each(function(d) { - d3_select(this) - .call(svgIcon('#icon-' + d.geometry, 'pre-text')); - }); + function info(selection$$1) { - label - .append('span') - .attr('class', 'entity-type') - .text(function(d) { return d.type; }); + function redraw() { + var activeids = ids.filter(function(k) { return active[k]; }).sort(); - label - .append('span') - .attr('class', 'entity-name') - .text(function(d) { return d.name; }); + var containers = infoPanels.selectAll('.panel-container') + .data(activeids, function(k) { return k; }); - enter - .style('opacity', 0) - .transition() - .style('opacity', 1); + containers.exit() + .style('opacity', 1) + .transition() + .duration(200) + .style('opacity', 0) + .on('end', function(d) { + select(this) + .call(panels[d].off) + .remove(); + }); - items.order(); + var enter = containers.enter() + .append('div') + .attr('class', function(d) { return 'fillD2 panel-container panel-container-' + d; }); - items.exit() - .remove(); - } + enter + .style('opacity', 0) + .transition() + .duration(200) + .style('opacity', 1); + var title = enter + .append('div') + .attr('class', 'panel-title fillD2'); - function mouseover(d) { - if (d.id === -1) return; + title + .append('h3') + .text(function(d) { return panels[d].title; }); - context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph())) - .classed('hover', true); - } + title + .append('button') + .attr('class', 'close') + .on('click', function (d) { toggle(d); }) + .call(svgIcon('#icon-close')); + enter + .append('div') + .attr('class', function(d) { return 'panel-content panel-content-' + d; }); - function mouseout() { - context.surface().selectAll('.hover') - .classed('hover', false); - } + // redraw the panels + infoPanels.selectAll('.panel-content') + .each(function(d) { + select(this).call(panels[d]); + }); + } - function click(d) { - event.preventDefault(); - if (d.location) { - context.map().centerZoom([d.location[1], d.location[0]], 20); - } - else if (d.entity) { - if (d.entity.type === 'node') { - context.map().center(d.entity.loc); - } else if (d.entity.type === 'way') { - var center = context.projection(context.map().center()); - var edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection); - context.map().center(edge.loc); - } - context.enter(modeSelect(context, [d.entity.id])); - } else { - context.zoomToEntity(d.id); - } - } + function toggle(which) { + if (event) { + event.stopImmediatePropagation(); + event.preventDefault(); + } + + var activeids = ids.filter(function(k) { return active[k]; }); + + if (which) { // toggle one + active[which] = !active[which]; + if (activeids.length === 1 && activeids[0] === which) { // none active anymore + wasActive = [which]; + } + } else { // toggle all + if (activeids.length) { + wasActive = activeids; + activeids.forEach(function(k) { active[k] = false; }); + } else { + wasActive.forEach(function(k) { active[k] = true; }); + } + } + + redraw(); + } - function geocoderSearch() { - services.geocoder.search(search.property('value'), function (err, resp) { - _geocodeResults = resp || []; - drawList(); - }); - } - } + var infoPanels = selection$$1.selectAll('.info-panels') + .data([0]); - return featureList; -} + infoPanels = infoPanels.enter() + .append('div') + .attr('class', 'info-panels') + .merge(infoPanels); -function uiPresetIcon() { - var preset, geometry; + redraw(); + var keybinding = d3keybinding('info') + .on(uiCmd('⌘' + t('info_panels.key')), toggle); - function presetIcon(selection$$1) { - selection$$1.each(render); - } + ids.forEach(function(k) { + var key = t('info_panels.' + k + '.key', { default: null }); + if (!key) return; + keybinding + .on(uiCmd('⌘⇧' + key), function() { toggle(k); }); + }); + select(document) + .call(keybinding); + } - function getIcon(p, geom) { - if (p.icon) - return p.icon; - else if (geom === 'line') - return 'other-line'; - else if (geom === 'vertex') - return p.isFallback() ? '' : 'poi-vertex'; - else - return 'marker-stroked'; - } + return info; + } + function uiModes(context) { + var modes = [ + modeAddPoint$$1(context), + modeAddLine$$1(context), + modeAddArea$$1(context) + ]; - function render() { - var selection$$1 = d3_select(this), - p = preset.apply(this, arguments), - geom = geometry.apply(this, arguments), - picon = getIcon(p, geom), - isPoi = picon.match(/^poi-/) !== null, - isMaki = dataFeatureIcons.indexOf(picon) !== -1, - isFramed = (geom === 'area' || geom === 'verex'); + function editable() { + var mode = context.mode(); + return context.editable() && mode && mode.id !== 'save'; + } - function tag_classes(p) { - var s = ''; - for (var i in p.tags) { - s += ' tag-' + i; - if (p.tags[i] !== '*') { - s += ' tag-' + i + '-' + p.tags[i]; - } - } - return s; - } + return function(selection$$1) { + var buttons = selection$$1.selectAll('button.add-button') + .data(modes); + + buttons = buttons.enter() + .append('button') + .attr('tabindex', -1) + .attr('class', function(mode) { return mode.id + ' add-button col4'; }) + .on('click.mode-buttons', function(mode) { + // When drawing, ignore accidental clicks on mode buttons - #4042 + var currMode = context.mode().id; + if (currMode.match(/^draw/) !== null) return; + + if (mode.id === currMode) { + context.enter(modeBrowse(context)); + } else { + context.enter(mode); + } + }) + .call(tooltip() + .placement('bottom') + .html(true) + .title(function(mode) { + return uiTooltipHtml(mode.description, mode.key); + }) + ); + + buttons + .each(function(d) { + select(this) + .call(svgIcon('#icon-' + d.button, 'pre-text')); + }); + + buttons + .append('span') + .attr('class', 'label') + .text(function(mode) { return mode.title; }); + + context + .on('enter.editor', function(entered) { + selection$$1.selectAll('button.add-button') + .classed('active', function(mode) { return entered.button === mode.button; }); + context.container() + .classed('mode-' + entered.id, true); + }); + + context + .on('exit.editor', function(exited) { + context.container() + .classed('mode-' + exited.id, false); + }); + + var keybinding = d3keybinding('mode-buttons'); + + modes.forEach(function(mode) { + keybinding.on(mode.key, function() { + if (editable()) { + if (mode.id === context.mode().id) { + context.enter(modeBrowse(context)); + } else { + context.enter(mode); + } + } + }); + }); - var fill = selection$$1.selectAll('.preset-icon-fill') - .data([0]); + select(document) + .call(keybinding); - fill = fill.enter() - .append('div') - .merge(fill); - fill - .attr('class', function() { - return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p); - }); + var debouncedUpdate = debounce(update, 500, { leading: true, trailing: true }); + context.map() + .on('move.modes', debouncedUpdate) + .on('drawn.modes', debouncedUpdate); - var areaFrame = selection$$1.selectAll('.preset-icon-frame') - .data((geom === 'area') ? [0] : []); + context + .on('enter.modes', update); - areaFrame.exit() - .remove(); - areaFrame = areaFrame.enter() - .append('div') - .attr('class', 'preset-icon-frame') - .call(svgIcon('#preset-icon-frame')); + function update() { + selection$$1.selectAll('button.add-button') + .property('disabled', !editable()); + } + }; + } - var icon = selection$$1.selectAll('.preset-icon') - .data([0]); + function uiNotice(context) { + + return function(selection$$1) { + var div = selection$$1 + .append('div') + .attr('class', 'notice'); + + var button = div + .append('button') + .attr('class', 'zoom-to notice fillD') + .on('click', function() { + context.map().zoomEase(context.minEditableZoom()); + }) + .on('wheel', function() { // let wheel events pass through #4482 + var e2 = new WheelEvent(event.type, event); + context.surface().node().dispatchEvent(e2); + }); + + button + .call(svgIcon('#icon-plus', 'pre-text')) + .append('span') + .attr('class', 'label') + .text(t('zoom_in_edit')); + + + function disableTooHigh() { + var canEdit = context.map().zoom() >= context.minEditableZoom(); + div.style('display', canEdit ? 'none' : 'block'); + } - icon = icon.enter() - .append('div') - .attr('class', 'preset-icon') - .call(svgIcon('')) - .merge(icon); + context.map() + .on('move.notice', debounce(disableTooHigh, 500)); - icon - .attr('class', 'preset-icon preset-icon-' + - ((isMaki || isPoi) ? (isFramed ? '24' : '28') : (isFramed ? '44' : '60')) - ); + disableTooHigh(); + }; + } - icon.selectAll('svg') - .attr('class', function() { - return 'icon ' + picon + (isMaki || isPoi ? '' : tag_classes(p)); - }); + function uiRestore(context) { + + return function(selection) { + if (!context.history().lock() || !context.history().restorableChanges()) + return; + + var modalSelection = uiModal(selection, true); + + modalSelection.select('.modal') + .attr('class', 'modal fillL col6'); + + var introModal = modalSelection.select('.content'); + + introModal + .attr('class','cf'); + + introModal + .append('div') + .attr('class', 'modal-section') + .append('h3') + .text(t('restore.heading')); + + introModal + .append('div') + .attr('class','modal-section') + .append('p') + .text(t('restore.description')); + + var buttonWrap = introModal + .append('div') + .attr('class', 'modal-actions cf'); + + var restore = buttonWrap + .append('button') + .attr('class', 'restore col6') + .on('click', function() { + context.history().restore(); + modalSelection.remove(); + }); + + restore + .append('svg') + .attr('class', 'logo logo-restore') + .append('use') + .attr('xlink:href', '#logo-restore'); + + restore + .append('div') + .text(t('restore.restore')); + + var reset = buttonWrap + .append('button') + .attr('class', 'reset col6') + .on('click', function() { + context.history().clearSaved(); + modalSelection.remove(); + }); + + reset + .append('svg') + .attr('class', 'logo logo-reset') + .append('use') + .attr('xlink:href', '#logo-reset'); + + reset + .append('div') + .text(t('restore.reset')); + + restore.node().focus(); + }; + } - icon.selectAll('use') - .attr('href', '#' + picon + (isMaki ? '-15' : '')); - } + function uiSave(context) { + var history = context.history(); + var key = uiCmd('⌘S'); - presetIcon.preset = function(_) { - if (!arguments.length) return preset; - preset = utilFunctor(_); - return presetIcon; - }; + function saving() { + var mode = context.mode(); + return mode && mode.id === 'save'; + } - presetIcon.geometry = function(_) { - if (!arguments.length) return geometry; - geometry = utilFunctor(_); - return presetIcon; - }; + function save() { + event.preventDefault(); + if (!context.inIntro() && !saving() && history.hasChanges()) { + context.enter(modeSave$$1(context)); + } + } - return presetIcon; -} - -function d3combobox() { - var dispatch$$1 = dispatch('accept'); - var _container = d3_select(document.body); - var _data = []; - var _suggestions = []; - var _minItems = 2; - var _caseSensitive = false; - - var _fetcher = function(val, cb) { - cb(_data.filter(function(d) { - return d.value - .toString() - .toLowerCase() - .indexOf(val.toLowerCase()) !== -1; - })); - }; - var combobox = function(input, attachTo) { - var idx = -1; - var wrapper = _container - .selectAll('div.combobox') - .filter(function(d) { return d === input.node(); }); - var shown = !wrapper.empty(); - var tagName = input.node() ? input.node().tagName.toLowerCase() : ''; - - input - .classed('combobox-input', true) - .on('focus.typeahead', focus) - .on('blur.typeahead', blur) - .on('keydown.typeahead', keydown) - .on('keyup.typeahead', keyup) - .on('input.typeahead', change) - .each(function() { - var parent = this.parentNode; - var sibling = this.nextSibling; - - var caret = d3_select(parent).selectAll('.combobox-caret') - .filter(function(d) { return d === input.node(); }) - .data([input.node()]); - - caret = caret.enter() - .insert('div', function() { return sibling; }) - .attr('class', 'combobox-caret') - .merge(caret); - - caret - .on('mousedown', function () { - // prevent the form element from blurring. it blurs - // on mousedown - event.stopPropagation(); - event.preventDefault(); - if (!shown) { - input.node().focus(); - fetch('', render); - } else { - hide(); - } - }); - }); + function getBackground(numChanges) { + var step; + if (numChanges === 0) { + return null; + } else if (numChanges <= 50) { + step = numChanges / 50; + return interpolateRgb('#fff', '#ff8')(step); // white -> yellow + } else { + step = Math.min((numChanges - 50) / 50, 1.0); + return interpolateRgb('#ff8', '#f88')(step); // yellow -> red + } + } - function focus() { - fetch(value(), render); - } - function blur() { - window.setTimeout(hide, 150); - } + return function(selection$$1) { + var numChanges = 0; - function show() { - if (!shown) { - wrapper = _container - .insert('div', ':first-child') - .datum(input.node()) - .attr('class', 'combobox') - .style('position', 'absolute') - .style('display', 'block') - .style('left', '0px') - .on('mousedown', function () { - // prevent moving focus out of the text field - event.preventDefault(); - }); - - d3_select('body') - .on('scroll.combobox', render, true); - - shown = true; - } - } + function updateCount() { + var _ = history.difference().summary().length; + if (_ === numChanges) return; + numChanges = _; - function hide() { - if (shown) { - idx = -1; - wrapper.remove(); + tooltipBehavior + .title(uiTooltipHtml( + t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key) + ); - d3_select('body') - .on('scroll.combobox', null); + var background = getBackground(numChanges); - shown = false; - } - } + button + .classed('disabled', numChanges === 0) + .classed('has-count', numChanges > 0) + .style('background', background); - function keydown() { - switch (event.keyCode) { - // backspace, delete - case 8: - case 46: - input.on('input.typeahead', function() { - idx = -1; - render(); - var start = input.property('selectionStart'); - input.node().setSelectionRange(start, start); - input.on('input.typeahead', change); - }); - break; - // tab - case 9: - wrapper.selectAll('a.selected').each(function (d) { - dispatch$$1.call('accept', this, d); - }); - hide(); - break; - // return - case 13: - event.preventDefault(); - break; - // up arrow - case 38: - if (tagName === 'textarea' && !shown) return; - nav(-1); - event.preventDefault(); - break; - // down arrow - case 40: - if (tagName === 'textarea' && !shown) return; - nav(+1); - event.preventDefault(); - break; - } - event.stopPropagation(); - } + button.select('span.count') + .text(numChanges) + .style('background', background) + .style('border-color', background); + } - function keyup() { - switch (event.keyCode) { - // escape - case 27: - hide(); - break; - // return - case 13: - wrapper.selectAll('a.selected').each(function (d) { - dispatch$$1.call('accept', this, d); - }); - hide(); - break; - } - } - function change() { - fetch(value(), function() { - if (input.property('selectionEnd') === input.property('value').length) { - autocomplete(); - } - render(); - }); - } + var tooltipBehavior = tooltip() + .placement('bottom') + .html(true) + .title(uiTooltipHtml(t('save.no_changes'), key)); - function nav(dir) { - if (!_suggestions.length) return; - idx = Math.max(Math.min(idx + dir, _suggestions.length - 1), 0); - input.property('value', _suggestions[idx].value); - render(); - ensureVisible(); - } + var button = selection$$1 + .append('button') + .attr('class', 'save col12 disabled') + .attr('tabindex', -1) + .on('click', save) + .call(tooltipBehavior); - function value() { - var value = input.property('value'); - var start = input.property('selectionStart'); - var end = input.property('selectionEnd'); + button + .call(svgIcon('#icon-save', 'pre-text')) + .append('span') + .attr('class', 'label') + .text(t('save.title')); - if (start && end) { - value = value.substring(0, start); - } + button + .append('span') + .attr('class', 'count') + .text('0'); - return value; - } + updateCount(); - function fetch(v, cb) { - _fetcher.call(input, v, function(_) { - _suggestions = _; - cb(); - }); - } - function autocomplete() { - var v = _caseSensitive ? value() : value().toLowerCase(); - idx = -1; - if (!v) return; + var keybinding = d3keybinding('uiSave') + .on(key, save, true); - var best = -1; - var suggestion, compare; + select(document) + .call(keybinding); - for (var i = 0; i < _suggestions.length; i++) { - suggestion = _suggestions[i].value; - compare = _caseSensitive ? suggestion : suggestion.toLowerCase(); + context.history() + .on('change.save', updateCount); - // if search string matches suggestion exactly, pick it.. - if (compare === v) { - best = i; - break; + context + .on('enter.save', function() { + button.property('disabled', saving()); + if (saving()) button.call(tooltipBehavior.hide); + }); + }; + } - // otherwise lock in the first result that starts with the search string.. - } else if (best === -1 && compare.indexOf(v) === 0) { - best = i; - } - } + function uiScale(context) { + var projection = context.projection, + isImperial = (utilDetect().locale.toLowerCase() === 'en-us'), + maxLength = 180, + tickHeight = 8; - if (best !== -1) { - idx = best; - suggestion = _suggestions[best].value; - input.property('value', suggestion); - input.node().setSelectionRange(v.length, suggestion.length); - } - } - function render() { - if (_suggestions.length >= _minItems && document.activeElement === input.node()) { - show(); - } else { - hide(); - return; - } + function scaleDefs(loc1, loc2) { + var lat = (loc2[1] + loc1[1]) / 2, + conversion = (isImperial ? 3.28084 : 1), + dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion, + scale = { dist: 0, px: 0, text: '' }, + buckets, i, val, dLon; - var options = wrapper - .selectAll('a.combobox-option') - .data(_suggestions, function(d) { return d.value; }); + if (isImperial) { + buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1]; + } else { + buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1]; + } - options.exit() - .remove(); + // determine a user-friendly endpoint for the scale + for (i = 0; i < buckets.length; i++) { + val = buckets[i]; + if (dist >= val) { + scale.dist = Math.floor(dist / val) * val; + break; + } else { + scale.dist = +dist.toFixed(2); + } + } - options.enter() - .append('a') - .attr('class', 'combobox-option') - .text(function(d) { return d.value; }) - .merge(options) - .attr('title', function(d) { return d.title; }) - .classed('selected', function(d, i) { return i === idx; }) - .on('mouseover', select$$1) - .on('click', accept) - .order(); + dLon = geoMetersToLon(scale.dist / conversion, lat); + scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]); + scale.text = displayLength(scale.dist / conversion, isImperial); - var node = attachTo ? attachTo.node() : input.node(); - var rect = node.getBoundingClientRect(); + return scale; + } - wrapper - .style('left', (rect.left + 5) + 'px') - .style('width', (rect.width - 10) + 'px') - .style('top', rect.height + rect.top + 'px'); - } - function select$$1(d, i) { - idx = i; - render(); - } + function update(selection) { + // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn) + var dims = context.map().dimensions(), + loc1 = projection.invert([0, dims[1]]), + loc2 = projection.invert([maxLength, dims[1]]), + scale = scaleDefs(loc1, loc2); - function ensureVisible() { - var node = wrapper.selectAll('a.selected').node(); - if (node) node.scrollIntoView(); - } + selection.select('#scale-path') + .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight); - function accept(d) { - if (!shown) return; - input.property('value', d.value); - utilTriggerEvent(input, 'change'); - dispatch$$1.call('accept', this, d); - hide(); - } - }; + selection.select('#scale-textgroup') + .attr('transform', 'translate(' + (scale.px + 8) + ',' + tickHeight + ')'); - combobox.fetcher = function(_) { - if (!arguments.length) return _fetcher; - _fetcher = _; - return combobox; - }; + selection.select('#scale-text') + .text(scale.text); + } - combobox.data = function(_) { - if (!arguments.length) return _data; - _data = _; - return combobox; - }; - combobox.minItems = function(_) { - if (!arguments.length) return _minItems; - _minItems = _; - return combobox; - }; + return function(selection) { + function switchUnits() { + isImperial = !isImperial; + selection.call(update); + } - combobox.caseSensitive = function(_) { - if (!arguments.length) return _caseSensitive; - _caseSensitive = _; - return combobox; - }; + var scalegroup = selection.append('svg') + .attr('id', 'scale') + .on('click', switchUnits) + .append('g') + .attr('transform', 'translate(10,11)'); - combobox.container = function(_) { - if (!arguments.length) return _container; - _container = _; - return combobox; - }; + scalegroup + .append('path') + .attr('id', 'scale-path'); - return utilRebind(combobox, dispatch$$1, 'on'); -} - - -d3combobox.off = function(input) { - input - .on('focus.typeahead', null) - .on('blur.typeahead', null) - .on('keydown.typeahead', null) - .on('keyup.typeahead', null) - .on('input.typeahead', null) - .each(function() { - d3_select(this.parentNode).selectAll('.combobox-caret') - .filter(function(d) { return d === input.node(); }) - .on('mousedown', null); - }); + scalegroup + .append('g') + .attr('id', 'scale-textgroup') + .append('text') + .attr('id', 'scale-text'); - d3_select('body') - .on('scroll.combobox', null); -}; + selection.call(update); -function uiRawMemberEditor(context) { - var taginfo = services.taginfo, - _entityID; + context.map().on('move.scale', function() { + update(selection); + }); + }; + } + var pair_1 = pair$1; - function selectMember(d) { - event.preventDefault(); - context.enter(modeSelect(context, [d.id])); - } + function search(x, dims, r) { + if (!dims) dims = 'NSEW'; + if (typeof x !== 'string') return { val: null, regex: r }; + r = r || /[\s\,]*([NSEW])?\s*([\-|\—|\―]?[0-9.]+)°?\s*(?:([0-9.]+)['’′‘]\s*)?(?:([0-9.]+)(?:''|"|”|″)\s*)?([NSEW])?/gi; - function changeRole(d) { - var role = d3_select(this).property('value'); - var member = { id: d.id, type: d.type, role: role }; - context.perform( - actionChangeMember(d.relation.id, member, d.index), - t('operations.change_role.annotation') - ); - } + var m = r.exec(x); + if (!m) return { val: null, regex: r }; + var dim = m[1] || m[5]; + if (dim && dims.indexOf(dim) === -1) return { val: null, regex: r }; - function deleteMember(d) { - context.perform( - actionDeleteMember(d.relation.id, d.index), - t('operations.delete_member.annotation') - ); + return { + val: (((m[2]) ? parseFloat(m[2]) : 0) + + ((m[3] ? parseFloat(m[3]) / 60 : 0)) + + ((m[4] ? parseFloat(m[4]) / 3600 : 0))) * + ((dim === 'S' || dim === 'W') ? -1 : 1), + regex: r, + raw: m[0], + dim: dim + }; + } - if (!context.hasEntity(d.relation.id)) { - context.enter(modeBrowse(context)); - } + function pair$1(x, dims) { + x = x.trim(); + var one = search(x, dims); + if (one.val === null) return null; + var two = search(x, dims, one.regex); + if (two.val === null) return null; + // null if one/two are not contiguous. + if (one.raw + two.raw !== x) return null; + if (one.dim) { + return swapdim(one.val, two.val, one.dim); + } else { + return [one.val, two.val]; } + } + function swapdim(a, b, dim) { + if (dim === 'N' || dim === 'S') return [a, b]; + if (dim === 'W' || dim === 'E') return [b, a]; + } - function rawMemberEditor(selection$$1) { - var entity = context.entity(_entityID), - memberships = []; - - entity.members.slice(0, 1000).forEach(function(member, index) { - memberships.push({ - index: index, - id: member.id, - type: member.type, - role: member.role, - relation: entity, - member: context.hasEntity(member.id) - }); - }); - - var gt = entity.members.length > 1000 ? '>' : ''; - selection$$1.call(uiDisclosure(context, 'raw_member_editor', true) - .title(t('inspector.all_members') + ' (' + gt + memberships.length + ')') - .expanded(true) - .updatePreference(false) - .on('toggled', function(expanded) { - if (expanded) { selection$$1.node().parentNode.scrollTop += 200; } - }) - .content(content) - ); - + function uiFeatureList(context) { + var keybinding = d3keybinding('uiFeatureList'); + var _geocodeResults; - function content(wrap) { - var list = wrap.selectAll('.member-list') - .data([0]); - - list = list.enter() - .append('ul') - .attr('class', 'member-list') - .merge(list); - - - var items = list.selectAll('li') - .data(memberships, function(d) { - return osmEntity$$1.key(d.relation) + ',' + d.index + ',' + - (d.member ? osmEntity$$1.key(d.member) : 'incomplete'); - }); - - items.exit() - .each(unbind) - .remove(); - - var enter = items.enter() - .append('li') - .attr('class', 'member-row form-field') - .classed('member-incomplete', function(d) { return !d.member; }); - - enter - .each(function(d) { - if (d.member) { - var label = d3_select(this).append('label') - .attr('class', 'form-label') - .append('a') - .attr('href', '#') - .on('click', selectMember); - - label.append('span') - .attr('class', 'member-entity-type') - .text(function(d) { - var matched = context.presets().match(d.member, context.graph()); - return (matched && matched.name()) || utilDisplayType(d.member.id); - }); - - label.append('span') - .attr('class', 'member-entity-name') - .text(function(d) { return utilDisplayName(d.member); }); - - } else { - d3_select(this).append('label') - .attr('class', 'form-label') - .text(t('inspector.incomplete', { id: d.id })); - } - }); - - enter - .append('input') - .attr('class', 'member-role') - .property('type', 'text') - .attr('maxlength', 255) - .attr('placeholder', t('inspector.role')) - .call(utilNoAuto) - .property('value', function(d) { return d.role; }) - .on('change', changeRole); - - enter - .append('button') - .attr('tabindex', -1) - .attr('class', 'remove button-input-action member-delete minor') - .on('click', deleteMember) - .call(svgIcon('#operation-delete')); - - if (taginfo) { - enter.each(bindTypeahead); - } + function featureList(selection$$1) { + var header = selection$$1 + .append('div') + .attr('class', 'header fillL cf'); - function bindTypeahead(d) { - var row = d3_select(this), - role = row.selectAll('input.member-role'); - - function sort(value, data) { - var sameletter = [], - other = []; - for (var i = 0; i < data.length; i++) { - if (data[i].value.substring(0, value.length) === value) { - sameletter.push(data[i]); - } else { - other.push(data[i]); - } - } - return sameletter.concat(other); - } - - role.call(d3combobox() - .container(context.container()) - .fetcher(function(role, callback) { - var rtype = entity.tags.type; - taginfo.roles({ - debounce: true, - rtype: rtype || '', - geometry: context.geometry(d.member.id), - query: role - }, function(err, data) { - if (!err) callback(sort(role, data)); - }); - })); - } + header + .append('h3') + .text(t('inspector.feature_list')); + var searchWrap = selection$$1 + .append('div') + .attr('class', 'search-header'); - function unbind() { - var row = d3_select(this); + var search = searchWrap + .append('input') + .attr('placeholder', t('inspector.search')) + .attr('type', 'search') + .call(utilNoAuto) + .on('keypress', keypress) + .on('keydown', keydown) + .on('input', inputevent); - row.selectAll('input.member-role') - .call(d3combobox.off); - } - } - } + searchWrap + .call(svgIcon('#icon-search', 'pre-text')); + var listWrap = selection$$1 + .append('div') + .attr('class', 'inspector-body'); - rawMemberEditor.entityID = function(_) { - if (!arguments.length) return _entityID; - _entityID = _; - return rawMemberEditor; - }; + var list = listWrap + .append('div') + .attr('class', 'feature-list cf'); + context + .on('exit.feature-list', clearSearch); + context.map() + .on('drawn.feature-list', mapDrawn); - return rawMemberEditor; -} + keybinding + .on(uiCmd('⌘F'), focusSearch); -function uiRawMembershipEditor(context) { - var taginfo = services.taginfo, - _entityID, - _showBlank; + select(document) + .call(keybinding); - function selectRelation(d) { - event.preventDefault(); - context.enter(modeSelect(context, [d.relation.id])); - } + function focusSearch() { + var mode = context.mode() && context.mode().id; + if (mode !== 'browse') return; + event.preventDefault(); + search.node().focus(); + } - function changeRole(d) { - var role = d3_select(this).property('value'); - context.perform( - actionChangeMember(d.relation.id, assignIn({}, d.member, { role: role }), d.index), - t('operations.change_role.annotation') - ); - } + function keydown() { + if (event.keyCode === 27) { // escape + search.node().blur(); + } + } - function addMembership(d, role) { - _showBlank = false; - var member = { id: _entityID, type: context.entity(_entityID).type, role: role }; + function keypress() { + var q = search.property('value'), + items = list.selectAll('.feature-list-item'); + if (event.keyCode === 13 && q.length && items.size()) { // return + click(items.datum()); + } + } - if (d.relation) { - context.perform( - actionAddMember(d.relation.id, member), - t('operations.add_member.annotation') - ); - } else { - var relation = osmRelation(); - context.perform( - actionAddEntity(relation), - actionAddMember(relation.id, member), - t('operations.add.annotation.relation') - ); + function inputevent() { + _geocodeResults = undefined; + drawList(); + } - context.enter(modeSelect(context, [relation.id])); - } - } + function clearSearch() { + search.property('value', ''); + drawList(); + } - function deleteMembership(d) { - context.perform( - actionDeleteMember(d.relation.id, d.index), - t('operations.delete_member.annotation') - ); - } + function mapDrawn(e) { + if (e.full) { + drawList(); + } + } - function relations(q) { - var newRelation = { relation: null, value: t('inspector.new_relation') }; - var result = []; - var graph = context.graph(); - context.intersects(context.extent()).forEach(function(entity) { - if (entity.type !== 'relation' || entity.id === _entityID) - return; + function features() { + var entities = {}; + var result = []; + var graph = context.graph(); + var q = search.property('value').toLowerCase(); + + if (!q) return result; + + var idMatch = q.match(/^([nwr])([0-9]+)$/); + + if (idMatch) { + result.push({ + id: idMatch[0], + geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation', + type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'), + name: idMatch[2] + }); + } + + var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/); + + if (locationMatch) { + var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])]; + result.push({ + id: -1, + geometry: 'point', + type: t('inspector.location'), + name: dmsCoordinatePair([loc[1], loc[0]]), + location: loc + }); + } + + function addEntity(entity) { + if (entity.id in entities || result.length > 200) + return; + + entities[entity.id] = true; + + var name = utilDisplayName(entity) || ''; + if (name.toLowerCase().indexOf(q) >= 0) { + var matched = context.presets().match(entity, graph); + var type = (matched && matched.name()) || utilDisplayType(entity.id); + + result.push({ + id: entity.id, + entity: entity, + geometry: context.geometry(entity.id), + type: type, + name: name + }); + } + + graph.parentRelations(entity).forEach(function(parent) { + addEntity(parent); + }); + } + + var visible = context.surface().selectAll('.point, .line, .area').nodes(); + for (var i = 0; i < visible.length && result.length <= 200; i++) { + var datum = visible[i].__data__; + var entity = datum && datum.properties && datum.properties.entity; + if (entity) { addEntity(entity); } + } + + (_geocodeResults || []).forEach(function(d) { + if (d.osm_type && d.osm_id) { // some results may be missing these - #1890 + + // Make a temporary osmEntity so we can preset match + // and better localize the search result - #4725 + var id = osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id); + var tags = {}; + tags[d.class] = d.type; + + var attrs = { id: id, type: d.osm_type, tags: tags }; + if (d.osm_type === 'way') { // for ways, add some fake closed nodes + attrs.nodes = ['a','a']; // so that geometry area is possible + } + + var tempEntity = osmEntity$$1(attrs); + var tempGraph = coreGraph$$1([tempEntity]); + var matched = context.presets().match(tempEntity, tempGraph); + var type = (matched && matched.name()) || utilDisplayType(id); + + result.push({ + id: tempEntity.id, + geometry: tempEntity.geometry(tempGraph), + type: type, + name: d.display_name, + extent: new geoExtent$$1( + [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])], + [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])]) + }); + } + }); + + return result; + } - var matched = context.presets().match(entity, graph), - presetName = (matched && matched.name()) || t('inspector.relation'), - entityName = utilDisplayName(entity) || ''; - var value = presetName + ' ' + entityName; - if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1) - return; + function drawList() { + var value = search.property('value'); + var results = features(); - result.push({ relation: entity, value: value }); - }); + list.classed('filtered', value.length); - result.sort(function(a, b) { - return osmRelation.creationOrder(a.relation, b.relation); - }); + var noResultsWorldwide = _geocodeResults && _geocodeResults.length === 0; - // Dedupe identical names by appending relation id - see #2891 - var dupeGroups = filter( - groupBy(result, 'value'), - function(v) { return v.length > 1; } - ); + var resultsIndicator = list.selectAll('.no-results-item') + .data([0]) + .enter() + .append('button') + .property('disabled', true) + .attr('class', 'no-results-item') + .call(svgIcon('#icon-alert', 'pre-text')); - dupeGroups.forEach(function(group) { - group.forEach(function(obj) { - obj.value += ' ' + obj.relation.id; - }); - }); + resultsIndicator.append('span') + .attr('class', 'entity-name'); - forEach(result, function(obj) { - obj.title = obj.value; - }); + list.selectAll('.no-results-item .entity-name') + .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible')); - result.unshift(newRelation); - return result; - } + if (services.geocoder) { + list.selectAll('.geocode-item') + .data([0]) + .enter() + .append('button') + .attr('class', 'geocode-item') + .on('click', geocoderSearch) + .append('div') + .attr('class', 'label') + .append('span') + .attr('class', 'entity-name') + .text(t('geocoder.search')); + } + list.selectAll('.no-results-item') + .style('display', (value.length && !results.length) ? 'block' : 'none'); - function rawMembershipEditor(selection$$1) { - var entity = context.entity(_entityID), - parents = context.graph().parentRelations(entity), - memberships = []; + list.selectAll('.geocode-item') + .style('display', (value && _geocodeResults === undefined) ? 'block' : 'none'); - parents.slice(0, 1000).forEach(function(relation) { - relation.members.forEach(function(member, index) { - if (member.id === entity.id) { - memberships.push({ relation: relation, member: member, index: index }); - } - }); - }); + list.selectAll('.feature-list-item') + .data([-1]) + .remove(); - var gt = parents.length > 1000 ? '>' : ''; - selection$$1.call(uiDisclosure(context, 'raw_membership_editor', true) - .title(t('inspector.all_relations') + ' (' + gt + memberships.length + ')') - .expanded(true) - .updatePreference(false) - .on('toggled', function(expanded) { - if (expanded) { selection$$1.node().parentNode.scrollTop += 200; } - }) - .content(content) - ); + var items = list.selectAll('.feature-list-item') + .data(results, function(d) { return d.id; }); + var enter = items.enter() + .insert('button', '.geocode-item') + .attr('class', 'feature-list-item') + .on('mouseover', mouseover) + .on('mouseout', mouseout) + .on('click', click); - function content(wrap) { - var list = wrap.selectAll('.member-list') - .data([0]); - - list = list.enter() - .append('ul') - .attr('class', 'member-list') - .merge(list); - - - var items = list.selectAll('li.member-row-normal') - .data(memberships, function(d) { - return osmEntity$$1.key(d.relation) + ',' + d.index; - }); - - items.exit() - .each(unbind) - .remove(); - - var enter = items.enter() - .append('li') - .attr('class', 'member-row member-row-normal form-field'); - - var label = enter - .append('label') - .attr('class', 'form-label') - .append('a') - .attr('href', '#') - .on('click', selectRelation); - - label - .append('span') - .attr('class', 'member-entity-type') - .text(function(d) { - var matched = context.presets().match(d.relation, context.graph()); - return (matched && matched.name()) || t('inspector.relation'); - }); - - label - .append('span') - .attr('class', 'member-entity-name') - .text(function(d) { return utilDisplayName(d.relation); }); - - enter - .append('input') - .attr('class', 'member-role') - .property('type', 'text') - .attr('maxlength', 255) - .attr('placeholder', t('inspector.role')) - .call(utilNoAuto) - .property('value', function(d) { return d.member.role; }) - .on('change', changeRole); - - enter - .append('button') - .attr('tabindex', -1) - .attr('class', 'remove button-input-action member-delete minor') - .on('click', deleteMembership) - .call(svgIcon('#operation-delete')); - - if (taginfo) { - enter.each(bindTypeahead); - } + var label = enter + .append('div') + .attr('class', 'label'); + label + .each(function(d) { + select(this) + .call(svgIcon('#icon-' + d.geometry, 'pre-text')); + }); - var newrow = list.selectAll('.member-row-new') - .data(_showBlank ? [0] : []); - - newrow.exit() - .remove(); - - enter = newrow.enter() - .append('li') - .attr('class', 'member-row member-row-new form-field'); - - enter - .append('input') - .attr('type', 'text') - .attr('class', 'member-entity-input') - .call(utilNoAuto); - - enter - .append('input') - .attr('class', 'member-role') - .property('type', 'text') - .attr('maxlength', 255) - .attr('placeholder', t('inspector.role')) - .call(utilNoAuto) - .on('change', changeRole); - - enter - .append('button') - .attr('tabindex', -1) - .attr('class', 'remove button-input-action member-delete minor') - .on('click', deleteMembership) - .call(svgIcon('#operation-delete')); - - newrow = newrow - .merge(enter); - - newrow.selectAll('.member-entity-input') - .call(d3combobox() - .container(context.container()) - .minItems(1) - .fetcher(function(value, callback) { callback(relations(value)); }) - .on('accept', onAccept) - ); - - - var addrel = wrap.selectAll('.add-relation') - .data([0]); - - addrel = addrel.enter() - .append('button') - .attr('class', 'add-relation') - .merge(addrel); - - addrel - .call(svgIcon('#icon-plus', 'light')) - .on('click', function() { - _showBlank = true; - content(wrap); - list.selectAll('.member-entity-input').node().focus(); - }); - - - function onAccept(d) { - var role = list.selectAll('.member-row-new .member-role').property('value'); - addMembership(d, role); - } + label + .append('span') + .attr('class', 'entity-type') + .text(function(d) { return d.type; }); + label + .append('span') + .attr('class', 'entity-name') + .text(function(d) { return d.name; }); - function bindTypeahead(d) { - var row = d3_select(this), - role = row.selectAll('input.member-role'); - - function sort(value, data) { - var sameletter = [], - other = []; - for (var i = 0; i < data.length; i++) { - if (data[i].value.substring(0, value.length) === value) { - sameletter.push(data[i]); - } else { - other.push(data[i]); - } - } - return sameletter.concat(other); - } - - role.call(d3combobox() - .container(context.container()) - .fetcher(function(role, callback) { - var rtype = d.relation.tags.type; - taginfo.roles({ - debounce: true, - rtype: rtype || '', - geometry: context.geometry(_entityID), - query: role - }, function(err, data) { - if (!err) callback(sort(role, data)); - }); - })); - } + enter + .style('opacity', 0) + .transition() + .style('opacity', 1); + items.order(); - function unbind() { - var row = d3_select(this); + items.exit() + .remove(); + } - row.selectAll('input.member-role') - .call(d3combobox.off); - } - } - } + function mouseover(d) { + if (d.id === -1) return; - rawMembershipEditor.entityID = function(_) { - if (!arguments.length) return _entityID; - _entityID = _; - return rawMembershipEditor; - }; + context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph())) + .classed('hover', true); + } - return rawMembershipEditor; -} + function mouseout() { + context.surface().selectAll('.hover') + .classed('hover', false); + } -function uiTagReference(tag) { - var taginfo = services.taginfo; - var tagReference = {}; - var _button = d3_select(null); - var _body = d3_select(null); - var _loaded; - var _showing; + function click(d) { + event.preventDefault(); + if (d.location) { + context.map().centerZoom([d.location[1], d.location[0]], 20); + } + else if (d.entity) { + if (d.entity.type === 'node') { + context.map().center(d.entity.loc); + } else if (d.entity.type === 'way') { + var center = context.projection(context.map().center()); + var edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection); + context.map().center(edge.loc); + } + context.enter(modeSelect(context, [d.entity.id])); + } else { + context.zoomToEntity(d.id); + } + } - function findLocal(data) { - var locale = utilDetect().locale.toLowerCase(); - var localized; + function geocoderSearch() { + services.geocoder.search(search.property('value'), function (err, resp) { + _geocodeResults = resp || []; + drawList(); + }); + } + } - if (locale !== 'pt-br') { // see #3776, prefer 'pt' over 'pt-br' - localized = find$1(data, function(d) { - return d.lang.toLowerCase() === locale; - }); - if (localized) return localized; - } - // try the non-regional version of a language, like - // 'en' if the language is 'en-US' - if (locale.indexOf('-') !== -1) { - var first = locale.split('-')[0]; - localized = find$1(data, function(d) { - return d.lang.toLowerCase() === first; - }); - if (localized) return localized; - } + return featureList; + } - // finally fall back to english - return find$1(data, function(d) { - return d.lang.toLowerCase() === 'en'; - }); - } + function uiPresetIcon() { + var preset, geometry; - function load(param) { - if (!taginfo) return; + function presetIcon(selection$$1) { + selection$$1.each(render); + } - _button - .classed('tag-reference-loading', true); - taginfo.docs(param, function show(err, data) { - var docs; - if (!err && data) { - docs = findLocal(data); - } + function getIcon(p, geom) { + if (p.icon) + return p.icon; + else if (geom === 'line') + return 'other-line'; + else if (geom === 'vertex') + return p.isFallback() ? '' : 'poi-vertex'; + else + return 'marker-stroked'; + } - _body.html(''); - - if (!docs || !docs.title) { - if (param.hasOwnProperty('value')) { - load(omit(param, 'value')); // retry with key only - } else { - _body - .append('p') - .attr('class', 'tag-reference-description') - .text(t('inspector.no_documentation_key')); - done(); - } - return; - } - if (docs.image && docs.image.thumb_url_prefix) { - _body - .append('img') - .attr('class', 'tag-reference-wiki-image') - .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix) - .on('load', function() { done(); }) - .on('error', function() { d3_select(this).remove(); done(); }); - } else { - done(); - } + function render() { + var selection$$1 = select(this), + p = preset.apply(this, arguments), + geom = geometry.apply(this, arguments), + picon = getIcon(p, geom), + isPoi = picon.match(/^poi-/) !== null, + isMaki = dataFeatureIcons.indexOf(picon) !== -1, + isFramed = (geom === 'area' || geom === 'verex'); + + + function tag_classes(p) { + var s = ''; + for (var i in p.tags) { + s += ' tag-' + i; + if (p.tags[i] !== '*') { + s += ' tag-' + i + '-' + p.tags[i]; + } + } + return s; + } - _body - .append('p') - .attr('class', 'tag-reference-description') - .text(docs.description || t('inspector.documentation_redirect')); - - _body - .append('a') - .attr('class', 'tag-reference-link') - .attr('target', '_blank') - .attr('tabindex', -1) - .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title) - .call(svgIcon('#icon-out-link', 'inline')) - .append('span') - .text(t('inspector.reference')); - - // Add link to info about "good changeset comments" - #2923 - if (param.key === 'comment') { - _body - .append('a') - .attr('class', 'tag-reference-comment-link') - .attr('target', '_blank') - .attr('tabindex', -1) - .call(svgIcon('#icon-out-link', 'inline')) - .attr('href', t('commit.about_changeset_comments_link')) - .append('span') - .text(t('commit.about_changeset_comments')); - } - }); - } + var fill = selection$$1.selectAll('.preset-icon-fill') + .data([0]); - function done() { - _loaded = true; + fill = fill.enter() + .append('div') + .merge(fill); - _button - .classed('tag-reference-loading', false); + fill + .attr('class', function() { + return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p); + }); - _body - .classed('expanded', true) - .transition() - .duration(200) - .style('max-height', '200px') - .style('opacity', '1'); - _showing = true; - } + var areaFrame = selection$$1.selectAll('.preset-icon-frame') + .data((geom === 'area') ? [0] : []); + areaFrame.exit() + .remove(); - function hide() { - _body - .transition() - .duration(200) - .style('max-height', '0px') - .style('opacity', '0') - .on('end', function () { - _body.classed('expanded', false); - }); + areaFrame = areaFrame.enter() + .append('div') + .attr('class', 'preset-icon-frame') + .call(svgIcon('#preset-icon-frame')); - _showing = false; - } + var icon = selection$$1.selectAll('.preset-icon') + .data([0]); - tagReference.button = function(selection$$1) { - _button = selection$$1.selectAll('.tag-reference-button') - .data([0]); + icon = icon.enter() + .append('div') + .attr('class', 'preset-icon') + .call(svgIcon('')) + .merge(icon); - _button = _button.enter() - .append('button') - .attr('class', 'tag-reference-button') - .attr('tabindex', -1) - .call(svgIcon('#icon-inspect')) - .merge(_button); + icon + .attr('class', 'preset-icon preset-icon-' + + ((isMaki || isPoi) ? (isFramed ? '24' : '28') : (isFramed ? '44' : '60')) + ); - _button - .on('click', function () { - event.stopPropagation(); - event.preventDefault(); - if (_showing) { - hide(); - } else if (_loaded) { - done(); - } else { - load(tag); - } - }); - }; + icon.selectAll('svg') + .attr('class', function() { + return 'icon ' + picon + (isMaki || isPoi ? '' : tag_classes(p)); + }); + icon.selectAll('use') + .attr('href', '#' + picon + (isMaki ? '-15' : '')); + } - tagReference.body = function(selection$$1) { - var tagid = tag.rtype || (tag.key + '-' + tag.value); - _body = selection$$1.selectAll('.tag-reference-body') - .data([tagid], function(d) { return d; }); - _body.exit() - .remove(); + presetIcon.preset = function(_) { + if (!arguments.length) return preset; + preset = utilFunctor(_); + return presetIcon; + }; - _body = _body.enter() - .append('div') - .attr('class', 'tag-reference-body cf') - .style('max-height', '0') - .style('opacity', '0') - .merge(_body); - if (_showing === false) { - hide(); - } - }; + presetIcon.geometry = function(_) { + if (!arguments.length) return geometry; + geometry = utilFunctor(_); + return presetIcon; + }; + return presetIcon; + } - tagReference.showing = function(_) { - if (!arguments.length) return _showing; - _showing = _; - return tagReference; - }; + function d3combobox() { + var dispatch$$1 = dispatch('accept'); + var _container = select(document.body); + var _data = []; + var _suggestions = []; + var _minItems = 2; + var _caseSensitive = false; + + var _fetcher = function(val, cb) { + cb(_data.filter(function(d) { + return d.value + .toString() + .toLowerCase() + .indexOf(val.toLowerCase()) !== -1; + })); + }; + var combobox = function(input, attachTo) { + var idx = -1; + var wrapper = _container + .selectAll('div.combobox') + .filter(function(d) { return d === input.node(); }); + var shown = !wrapper.empty(); + var tagName = input.node() ? input.node().tagName.toLowerCase() : ''; + + input + .classed('combobox-input', true) + .on('focus.typeahead', focus) + .on('blur.typeahead', blur) + .on('keydown.typeahead', keydown) + .on('keyup.typeahead', keyup) + .on('input.typeahead', change) + .each(function() { + var parent = this.parentNode; + var sibling = this.nextSibling; + + var caret = select(parent).selectAll('.combobox-caret') + .filter(function(d) { return d === input.node(); }) + .data([input.node()]); + + caret = caret.enter() + .insert('div', function() { return sibling; }) + .attr('class', 'combobox-caret') + .merge(caret); + + caret + .on('mousedown', function () { + // prevent the form element from blurring. it blurs + // on mousedown + event.stopPropagation(); + event.preventDefault(); + if (!shown) { + input.node().focus(); + fetch('', render); + } else { + hide(); + } + }); + }); + + function focus() { + fetch(value(), render); + } - return tagReference; -} - -function uiRawTagEditor(context) { - var taginfo = services.taginfo, - dispatch$$1 = dispatch('change'), - _readOnlyTags = [], - _showBlank = false, - _updatePreference = true, - _expanded = false, - _newRow, - _state, - _preset, - _tags, - _entityID; - - - function rawTagEditor(selection$$1) { - var count = Object.keys(_tags).filter(function(d) { return d; }).length; - - var disclosure = uiDisclosure(context, 'raw_tag_editor', false) - .title(t('inspector.all_tags') + ' (' + count + ')') - .on('toggled', toggled) - .updatePreference(_updatePreference) - .content(content); - - // Sometimes we want to force the raw_tag_editor to be opened/closed.. - // When undefined, uiDisclosure will use the user's stored preference. - if (_expanded !== undefined) { - disclosure.expanded(_expanded); - } + function blur() { + window.setTimeout(hide, 150); + } - selection$$1.call(disclosure); + function show() { + if (!shown) { + wrapper = _container + .insert('div', ':first-child') + .datum(input.node()) + .attr('class', 'combobox') + .style('position', 'absolute') + .style('display', 'block') + .style('left', '0px') + .on('mousedown', function () { + // prevent moving focus out of the text field + event.preventDefault(); + }); + + select('body') + .on('scroll.combobox', render, true); + + shown = true; + } + } - function toggled(expanded) { - _expanded = expanded; - if (expanded) { - selection$$1.node().parentNode.scrollTop += 200; - } - } - } + function hide() { + if (shown) { + idx = -1; + wrapper.remove(); + select('body') + .on('scroll.combobox', null); - function content(wrap) { - var entries = map$3(_tags, function(v, k) { - return { key: k, value: v }; - }); + shown = false; + } + } - if (!entries.length || _showBlank) { - _showBlank = false; - entries.push({key: '', value: ''}); - _newRow = ''; - } + function keydown() { + switch (event.keyCode) { + // backspace, delete + case 8: + case 46: + input.on('input.typeahead', function() { + idx = -1; + render(); + var start = input.property('selectionStart'); + input.node().setSelectionRange(start, start); + input.on('input.typeahead', change); + }); + break; + // tab + case 9: + wrapper.selectAll('a.selected').each(function (d) { + dispatch$$1.call('accept', this, d); + }); + hide(); + break; + // return + case 13: + event.preventDefault(); + break; + // up arrow + case 38: + if (tagName === 'textarea' && !shown) return; + nav(-1); + event.preventDefault(); + break; + // down arrow + case 40: + if (tagName === 'textarea' && !shown) return; + nav(+1); + event.preventDefault(); + break; + } + event.stopPropagation(); + } - var list = wrap.selectAll('.tag-list') - .data([0]); - - list = list.enter() - .append('ul') - .attr('class', 'tag-list') - .merge(list); - - var newTag = wrap.selectAll('.add-tag') - .data([0]); - - newTag.enter() - .append('button') - .attr('class', 'add-tag') - .on('click', addTag) - .call(svgIcon('#icon-plus', 'light')); - - - var items = list.selectAll('.tag-row') - .data(entries, function(d) { return d.key; }); - - items.exit() - .each(unbind) - .remove(); - - // Enter - - var enter = items.enter() - .append('li') - .attr('class', 'tag-row cf') - .classed('readonly', isReadOnly); - - enter - .append('div') - .attr('class', 'key-wrap') - .append('input') - .property('type', 'text') - .attr('class', 'key') - .attr('maxlength', 255) - .call(utilNoAuto) - .on('blur', keyChange) - .on('change', keyChange); - - enter - .append('div') - .attr('class', 'input-wrap-position') - .append('input') - .property('type', 'text') - .attr('class', 'value') - .attr('maxlength', 255) - .call(utilNoAuto) - .on('blur', valueChange) - .on('change', valueChange) - .on('keydown.push-more', pushMore); - - enter - .append('button') - .attr('tabindex', -1) - .attr('class', 'remove minor') - .call(svgIcon('#operation-delete')); - - - // Update - - items = items - .merge(enter) - .sort(function(a, b) { - return (a.key === _newRow && b.key !== _newRow) ? 1 - : (a.key !== _newRow && b.key === _newRow) ? -1 - : d3_ascending(a.key, b.key); - }); + function keyup() { + switch (event.keyCode) { + // escape + case 27: + hide(); + break; + // return + case 13: + wrapper.selectAll('a.selected').each(function (d) { + dispatch$$1.call('accept', this, d); + }); + hide(); + break; + } + } - items - .each(function(tag) { - var row = d3_select(this), - key = row.select('input.key'), // propagate bound data to child - value = row.select('input.value'); // propagate bound data to child + function change() { + fetch(value(), function() { + if (input.property('selectionEnd') === input.property('value').length) { + autocomplete(); + } + render(); + }); + } - if (_entityID && taginfo) { - bindTypeahead(key, value); - } + function nav(dir) { + if (!_suggestions.length) return; + idx = Math.max(Math.min(idx + dir, _suggestions.length - 1), 0); + input.property('value', _suggestions[idx].value); + render(); + ensureVisible(); + } - var isRelation = (_entityID && context.entity(_entityID).type === 'relation'), - reference; + function value() { + var value = input.property('value'); + var start = input.property('selectionStart'); + var end = input.property('selectionEnd'); - if (isRelation && tag.key === 'type') { - reference = uiTagReference({ rtype: tag.value }, context); - } else { - reference = uiTagReference({ key: tag.key, value: tag.value }, context); - } + if (start && end) { + value = value.substring(0, start); + } - if (_state === 'hover') { - reference.showing(false); - } + return value; + } - row - .call(reference.button) - .call(reference.body); - }); + function fetch(v, cb) { + _fetcher.call(input, v, function(_) { + _suggestions = _; + cb(); + }); + } - items.selectAll('input.key') - .attr('title', function(d) { return d.key; }) - .call(utilGetSetValue, function(d) { return d.key; }) - .property('disabled', isReadOnly); + function autocomplete() { + var v = _caseSensitive ? value() : value().toLowerCase(); + idx = -1; + if (!v) return; + + // Don't autocomplete if user is typing a number - #4935 + if (!isNaN(parseFloat(v)) && isFinite(v)) return; + + var best = -1; + var suggestion, compare; + + for (var i = 0; i < _suggestions.length; i++) { + suggestion = _suggestions[i].value; + compare = _caseSensitive ? suggestion : suggestion.toLowerCase(); + + // if search string matches suggestion exactly, pick it.. + if (compare === v) { + best = i; + break; + + // otherwise lock in the first result that starts with the search string.. + } else if (best === -1 && compare.indexOf(v) === 0) { + best = i; + } + } + + if (best !== -1) { + idx = best; + suggestion = _suggestions[best].value; + input.property('value', suggestion); + input.node().setSelectionRange(v.length, suggestion.length); + } + } - items.selectAll('input.value') - .attr('title', function(d) { return d.value; }) - .call(utilGetSetValue, function(d) { return d.value; }) - .property('disabled', isReadOnly); + function render() { + if (_suggestions.length >= _minItems && document.activeElement === input.node()) { + show(); + } else { + hide(); + return; + } + + var options = wrapper + .selectAll('a.combobox-option') + .data(_suggestions, function(d) { return d.value; }); + + options.exit() + .remove(); + + options.enter() + .append('a') + .attr('class', 'combobox-option') + .text(function(d) { return d.value; }) + .merge(options) + .attr('title', function(d) { return d.title; }) + .classed('selected', function(d, i) { return i === idx; }) + .on('mouseover', select$$1) + .on('click', accept) + .order(); + + + var node = attachTo ? attachTo.node() : input.node(); + var rect = node.getBoundingClientRect(); + + wrapper + .style('left', (rect.left + 5) + 'px') + .style('width', (rect.width - 10) + 'px') + .style('top', rect.height + rect.top + 'px'); + } - items.selectAll('button.remove') - .on('click', removeTag); + function select$$1(d, i) { + idx = i; + render(); + } + function ensureVisible() { + var node = wrapper.selectAll('a.selected').node(); + if (node) node.scrollIntoView(); + } + function accept(d) { + if (!shown) return; + input.property('value', d.value); + utilTriggerEvent(input, 'change'); + dispatch$$1.call('accept', this, d); + hide(); + } + }; - function isReadOnly(d) { - for (var i = 0; i < _readOnlyTags.length; i++) { - if (d.key.match(_readOnlyTags[i]) !== null) { - return true; - } - } - return false; - } + combobox.fetcher = function(_) { + if (!arguments.length) return _fetcher; + _fetcher = _; + return combobox; + }; + combobox.data = function(_) { + if (!arguments.length) return _data; + _data = _; + return combobox; + }; - function pushMore() { - if (event.keyCode === 9 && !event.shiftKey && - list.selectAll('li:last-child input.value').node() === this) { - addTag(); - } - } + combobox.minItems = function(_) { + if (!arguments.length) return _minItems; + _minItems = _; + return combobox; + }; + combobox.caseSensitive = function(_) { + if (!arguments.length) return _caseSensitive; + _caseSensitive = _; + return combobox; + }; - function bindTypeahead(key, value) { - if (isReadOnly({ key: key })) return; - var geometry = context.geometry(_entityID); - - key.call(d3combobox() - .container(context.container()) - .fetcher(function(value, callback) { - taginfo.keys({ - debounce: true, - geometry: geometry, - query: value - }, function(err, data) { - if (!err) callback(sort(value, data)); - }); - })); - - value.call(d3combobox() - .container(context.container()) - .fetcher(function(value, callback) { - taginfo.values({ - debounce: true, - key: utilGetSetValue(key), - geometry: geometry, - query: value - }, function(err, data) { - if (!err) callback(sort(value, data)); - }); - })); - - - function sort(value, data) { - var sameletter = [], - other = []; - for (var i = 0; i < data.length; i++) { - if (data[i].value.substring(0, value.length) === value) { - sameletter.push(data[i]); - } else { - other.push(data[i]); - } - } - return sameletter.concat(other); - } - } + combobox.container = function(_) { + if (!arguments.length) return _container; + _container = _; + return combobox; + }; + return utilRebind(combobox, dispatch$$1, 'on'); + } - function unbind() { - var row = d3_select(this); - row.selectAll('input.key') - .call(d3combobox.off); + d3combobox.off = function(input) { + input + .on('focus.typeahead', null) + .on('blur.typeahead', null) + .on('keydown.typeahead', null) + .on('keyup.typeahead', null) + .on('input.typeahead', null) + .each(function() { + select(this.parentNode).selectAll('.combobox-caret') + .filter(function(d) { return d === input.node(); }) + .on('mousedown', null); + }); - row.selectAll('input.value') - .call(d3combobox.off); - } + select('body') + .on('scroll.combobox', null); + }; + function uiRawMemberEditor(context) { + var taginfo = services.taginfo, + _entityID; - function keyChange(d) { - var kOld = d.key, - kNew = this.value.trim(), - tag = {}; + function selectMember(d) { + event.preventDefault(); + context.enter(modeSelect(context, [d.id])); + } - if (isReadOnly({ key: kNew })) { - this.value = kOld; - return; - } - if (kNew && kNew !== kOld) { - var match = kNew.match(/^(.*?)(?:_(\d+))?$/), - base = match[1], - suffix = +(match[2] || 1); - while (_tags[kNew]) { // rename key if already in use - kNew = base + '_' + suffix++; - } - } - tag[kOld] = undefined; - tag[kNew] = d.value; + function changeRole(d) { + var role = select(this).property('value'); + var member = { id: d.id, type: d.type, role: role }; + context.perform( + actionChangeMember(d.relation.id, member, d.index), + t('operations.change_role.annotation') + ); + } - d.key = kNew; // Maintain DOM identity through the subsequent update. - if (_newRow === kOld) { // see if this row is still a new row - _newRow = ((d.value === '' || kNew === '') ? kNew : undefined); - } + function deleteMember(d) { + context.perform( + actionDeleteMember(d.relation.id, d.index), + t('operations.delete_member.annotation') + ); - this.value = kNew; - dispatch$$1.call('change', this, tag); - } + if (!context.hasEntity(d.relation.id)) { + context.enter(modeBrowse(context)); + } + } - function valueChange(d) { - if (isReadOnly(d)) return; - var tag = {}; - tag[d.key] = this.value; + function rawMemberEditor(selection$$1) { + var entity = context.entity(_entityID), + memberships = []; - if (_newRow === d.key && d.key !== '' && d.value !== '') { // not a new row anymore - _newRow = undefined; - } + entity.members.slice(0, 1000).forEach(function(member, index) { + memberships.push({ + index: index, + id: member.id, + type: member.type, + role: member.role, + relation: entity, + member: context.hasEntity(member.id) + }); + }); - dispatch$$1.call('change', this, tag); - } + var gt = entity.members.length > 1000 ? '>' : ''; + selection$$1.call(uiDisclosure(context, 'raw_member_editor', true) + .title(t('inspector.all_members') + ' (' + gt + memberships.length + ')') + .expanded(true) + .updatePreference(false) + .on('toggled', function(expanded) { + if (expanded) { selection$$1.node().parentNode.scrollTop += 200; } + }) + .content(content) + ); - function removeTag(d) { - if (isReadOnly(d)) return; - var tag = {}; - tag[d.key] = undefined; - dispatch$$1.call('change', this, tag); - d3_select(this.parentNode).remove(); - } + function content(wrap) { + var list = wrap.selectAll('.member-list') + .data([0]); + + list = list.enter() + .append('ul') + .attr('class', 'member-list') + .merge(list); + + + var items = list.selectAll('li') + .data(memberships, function(d) { + return osmEntity$$1.key(d.relation) + ',' + d.index + ',' + + (d.member ? osmEntity$$1.key(d.member) : 'incomplete'); + }); + + items.exit() + .each(unbind) + .remove(); + + var enter = items.enter() + .append('li') + .attr('class', 'member-row form-field') + .classed('member-incomplete', function(d) { return !d.member; }); + + enter + .each(function(d) { + if (d.member) { + var label = select(this).append('label') + .attr('class', 'form-label') + .append('a') + .attr('href', '#') + .on('click', selectMember); + + label.append('span') + .attr('class', 'member-entity-type') + .text(function(d) { + var matched = context.presets().match(d.member, context.graph()); + return (matched && matched.name()) || utilDisplayType(d.member.id); + }); + + label.append('span') + .attr('class', 'member-entity-name') + .text(function(d) { return utilDisplayName(d.member); }); + + } else { + select(this).append('label') + .attr('class', 'form-label') + .text(t('inspector.incomplete', { id: d.id })); + } + }); + + enter + .append('input') + .attr('class', 'member-role') + .property('type', 'text') + .attr('maxlength', 255) + .attr('placeholder', t('inspector.role')) + .call(utilNoAuto) + .property('value', function(d) { return d.role; }) + .on('change', changeRole); + + enter + .append('button') + .attr('tabindex', -1) + .attr('class', 'remove button-input-action member-delete minor') + .on('click', deleteMember) + .call(svgIcon('#operation-delete')); + + if (taginfo) { + enter.each(bindTypeahead); + } + + + function bindTypeahead(d) { + var row = select(this), + role = row.selectAll('input.member-role'); + + function sort(value, data) { + var sameletter = [], + other = []; + for (var i = 0; i < data.length; i++) { + if (data[i].value.substring(0, value.length) === value) { + sameletter.push(data[i]); + } else { + other.push(data[i]); + } + } + return sameletter.concat(other); + } + + role.call(d3combobox() + .container(context.container()) + .fetcher(function(role, callback) { + var rtype = entity.tags.type; + taginfo.roles({ + debounce: true, + rtype: rtype || '', + geometry: context.geometry(d.member.id), + query: role + }, function(err, data) { + if (!err) callback(sort(role, data)); + }); + })); + } + + + function unbind() { + var row = select(this); + + row.selectAll('input.member-role') + .call(d3combobox.off); + } + } + } - function addTag() { - // Wrapped in a setTimeout in case it's being called from a blur - // handler. Without the setTimeout, the call to `content` would - // wipe out the pending value change. - setTimeout(function() { - _showBlank = true; - content(wrap); - list.selectAll('li:last-child input.key').node().focus(); - }, 0); - } - } + rawMemberEditor.entityID = function(_) { + if (!arguments.length) return _entityID; + _entityID = _; + return rawMemberEditor; + }; - rawTagEditor.state = function(_) { - if (!arguments.length) return _state; - _state = _; - return rawTagEditor; - }; + return rawMemberEditor; + } + function uiRawMembershipEditor(context) { + var taginfo = services.taginfo, + _entityID, + _showBlank; - rawTagEditor.preset = function(_) { - if (!arguments.length) return _preset; - _preset = _; - if (_preset.isFallback()) { - _expanded = true; - _updatePreference = false; - } else { - _expanded = undefined; - _updatePreference = true; - } - return rawTagEditor; - }; + function selectRelation(d) { + event.preventDefault(); + context.enter(modeSelect(context, [d.relation.id])); + } - rawTagEditor.tags = function(_) { - if (!arguments.length) return _tags; - _tags = _; - return rawTagEditor; - }; + function changeRole(d) { + var role = select(this).property('value'); + context.perform( + actionChangeMember(d.relation.id, assignIn({}, d.member, { role: role }), d.index), + t('operations.change_role.annotation') + ); + } - rawTagEditor.entityID = function(_) { - if (!arguments.length) return _entityID; - _entityID = _; - return rawTagEditor; - }; + function addMembership(d, role) { + _showBlank = false; - rawTagEditor.expanded = function(_) { - if (!arguments.length) return _expanded; - _expanded = _; - _updatePreference = false; - return rawTagEditor; - }; + var member = { id: _entityID, type: context.entity(_entityID).type, role: role }; + if (d.relation) { + context.perform( + actionAddMember(d.relation.id, member), + t('operations.add_member.annotation') + ); - rawTagEditor.readOnlyTags = function(_) { - if (!arguments.length) return _readOnlyTags; - _readOnlyTags = _; - return rawTagEditor; - }; + } else { + var relation = osmRelation(); + context.perform( + actionAddEntity(relation), + actionAddMember(relation.id, member), + t('operations.add.annotation.relation') + ); + + context.enter(modeSelect(context, [relation.id])); + } + } - return utilRebind(rawTagEditor, dispatch$$1, 'on'); -} - -// This currently only works with the 'restrictions' field -// It borrows some code from uiHelp - -function uiFieldHelp(context, fieldName) { - var fieldHelp = {}; - var _inspector = d3_select(null); - var _wrap = d3_select(null); - var _body = d3_select(null); - - var fieldHelpKeys = { - restrictions: [ - ['about',[ - 'about', - 'from_via_to', - 'maxdist', - 'maxvia' - ]], - ['inspecting',[ - 'about', - 'from_shadow', - 'allow_shadow', - 'restrict_shadow', - 'only_shadow', - 'restricted', - 'only' - ]], - ['modifying',[ - 'about', - 'indicators', - 'allow_turn', - 'restrict_turn', - 'only_turn' - ]], - ['tips',[ - 'simple', - 'simple_example', - 'indirect', - 'indirect_example', - 'indirect_noedit' - ]] - ] - }; + function deleteMembership(d) { + context.perform( + actionDeleteMember(d.relation.id, d.index), + t('operations.delete_member.annotation') + ); + } - var fieldHelpHeadings = {}; - - var replacements = { - distField: t('restriction.controls.distance'), - viaField: t('restriction.controls.via'), - fromShadow: icon('#turn-shadow', 'pre-text shadow from'), - allowShadow: icon('#turn-shadow', 'pre-text shadow allow'), - restrictShadow: icon('#turn-shadow', 'pre-text shadow restrict'), - onlyShadow: icon('#turn-shadow', 'pre-text shadow only'), - allowTurn: icon('#turn-yes', 'pre-text turn'), - restrictTurn: icon('#turn-no', 'pre-text turn'), - onlyTurn: icon('#turn-only', 'pre-text turn') - }; + function relations(q) { + var newRelation = { relation: null, value: t('inspector.new_relation') }; + var result = []; + var graph = context.graph(); - // For each section, squash all the texts into a single markdown document - var docs = fieldHelpKeys[fieldName].map(function(key) { - var helpkey = 'help.field.' + fieldName + '.' + key[0]; - var text = key[1].reduce(function(all, part) { - var subkey = helpkey + '.' + part; - var depth = fieldHelpHeadings[subkey]; // is this subkey a heading? - var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s - return all + hhh + t(subkey, replacements) + '\n\n'; - }, ''); + context.intersects(context.extent()).forEach(function(entity) { + if (entity.type !== 'relation' || entity.id === _entityID) + return; - return { - key: helpkey, - title: t(helpkey + '.title'), - html: marked(text.trim()) - }; - }); + var matched = context.presets().match(entity, graph), + presetName = (matched && matched.name()) || t('inspector.relation'), + entityName = utilDisplayName(entity) || ''; + var value = presetName + ' ' + entityName; + if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1) + return; - function show() { - updatePosition(); + result.push({ relation: entity, value: value }); + }); - _body - .classed('hide', false) - .style('opacity', '0') - .transition() - .duration(200) - .style('opacity', '1'); - } + result.sort(function(a, b) { + return osmRelation.creationOrder(a.relation, b.relation); + }); + // Dedupe identical names by appending relation id - see #2891 + var dupeGroups = filter( + groupBy(result, 'value'), + function(v) { return v.length > 1; } + ); - function hide() { - _body - .classed('hide', true) - .transition() - .duration(200) - .style('opacity', '0') - .on('end', function () { - _body.classed('hide', true); - }); - } + dupeGroups.forEach(function(group) { + group.forEach(function(obj) { + obj.value += ' ' + obj.relation.id; + }); + }); + forEach(result, function(obj) { + obj.title = obj.value; + }); - function clickHelp(index) { - var d = docs[index]; - var tkeys = fieldHelpKeys[fieldName][index][1]; + result.unshift(newRelation); + return result; + } - _body.selectAll('.field-help-nav-item') - .classed('active', function(d, i) { return i === index; }); - var content = _body.selectAll('.field-help-content') - .html(d.html); + function rawMembershipEditor(selection$$1) { + var entity = context.entity(_entityID), + parents = context.graph().parentRelations(entity), + memberships = []; - // class the paragraphs so we can find and style them - content.selectAll('p') - .attr('class', function(d, i) { return tkeys[i]; }); + parents.slice(0, 1000).forEach(function(relation) { + relation.members.forEach(function(member, index) { + if (member.id === entity.id) { + memberships.push({ relation: relation, member: member, index: index }); + } + }); + }); - // insert special content for certain help sections - if (d.key === 'help.field.restrictions.inspecting') { - content - .insert('img', 'p.from_shadow') - .attr('class', 'field-help-image cf') - .attr('src', context.imagePath('tr_inspect.gif')); + var gt = parents.length > 1000 ? '>' : ''; + selection$$1.call(uiDisclosure(context, 'raw_membership_editor', true) + .title(t('inspector.all_relations') + ' (' + gt + memberships.length + ')') + .expanded(true) + .updatePreference(false) + .on('toggled', function(expanded) { + if (expanded) { selection$$1.node().parentNode.scrollTop += 200; } + }) + .content(content) + ); - } else if (d.key === 'help.field.restrictions.modifying') { - content - .insert('img', 'p.allow_turn') - .attr('class', 'field-help-image cf') - .attr('src', context.imagePath('tr_modify.gif')); - } - } + function content(wrap) { + var list = wrap.selectAll('.member-list') + .data([0]); - fieldHelp.button = function(selection$$1) { - if (_body.empty()) return; - - var button = selection$$1.selectAll('.field-help-button') - .data([0]); - - // enter/update - button.enter() - .append('button') - .attr('class', 'field-help-button') - .attr('tabindex', -1) - .call(svgIcon('#icon-help')) - .merge(button) - .on('click', function () { - event.stopPropagation(); - event.preventDefault(); - if (_body.classed('hide')) { - show(); - } else { - hide(); - } - }); - }; + list = list.enter() + .append('ul') + .attr('class', 'member-list') + .merge(list); - function updatePosition() { - var wrap = _wrap.node(); - var inspector = _inspector.node(); - var wRect = wrap.getBoundingClientRect(); - var iRect = inspector.getBoundingClientRect(); - - _body - .style('top', wRect.top + inspector.scrollTop - iRect.top + 'px'); - } - - - fieldHelp.body = function(selection$$1) { - // This control expects the field to have a preset-input-wrap div - _wrap = selection$$1.selectAll('.preset-input-wrap'); - if (_wrap.empty()) return; - - // absolute position relative to the inspector, so it "floats" above the fields - _inspector = d3_select('#sidebar .entity-editor-pane .inspector-body'); - if (_inspector.empty()) return; - - _body = _inspector.selectAll('.field-help-body') - .data([0]); - - var enter = _body.enter() - .append('div') - .attr('class', 'field-help-body hide'); // initially hidden - - var titleEnter = enter - .append('div') - .attr('class', 'field-help-title cf'); - - titleEnter - .append('h2') - .attr('class', 'fl') - .text(t('help.field.' + fieldName + '.title')); - - titleEnter - .append('button') - .attr('class', 'fr close') - .on('click', function() { - event.stopPropagation(); - event.preventDefault(); - hide(); - }) - .call(svgIcon('#icon-close')); - - var navEnter = enter - .append('div') - .attr('class', 'field-help-nav cf'); - - var titles = docs.map(function(d) { return d.title; }); - navEnter.selectAll('.field-help-nav-item') - .data(titles) - .enter() - .append('div') - .attr('class', 'field-help-nav-item') - .text(function(d) { return d; }) - .on('click', function(d, i) { - event.stopPropagation(); - event.preventDefault(); - clickHelp(i); - }); + var items = list.selectAll('li.member-row-normal') + .data(memberships, function(d) { + return osmEntity$$1.key(d.relation) + ',' + d.index; + }); - enter - .append('div') - .attr('class', 'field-help-content'); + items.exit() + .each(unbind) + .remove(); - _body = _body - .merge(enter); + var enter = items.enter() + .append('li') + .attr('class', 'member-row member-row-normal form-field'); - clickHelp(0); - }; + var label = enter + .append('label') + .attr('class', 'form-label') + .append('a') + .attr('href', '#') + .on('click', selectRelation); + label + .append('span') + .attr('class', 'member-entity-type') + .text(function(d) { + var matched = context.presets().match(d.relation, context.graph()); + return (matched && matched.name()) || t('inspector.relation'); + }); - return fieldHelp; -} + label + .append('span') + .attr('class', 'member-entity-name') + .text(function(d) { return utilDisplayName(d.relation); }); + + enter + .append('input') + .attr('class', 'member-role') + .property('type', 'text') + .attr('maxlength', 255) + .attr('placeholder', t('inspector.role')) + .call(utilNoAuto) + .property('value', function(d) { return d.member.role; }) + .on('change', changeRole); + + enter + .append('button') + .attr('tabindex', -1) + .attr('class', 'remove button-input-action member-delete minor') + .on('click', deleteMembership) + .call(svgIcon('#operation-delete')); + + if (taginfo) { + enter.each(bindTypeahead); + } + + + var newrow = list.selectAll('.member-row-new') + .data(_showBlank ? [0] : []); + + newrow.exit() + .remove(); + + enter = newrow.enter() + .append('li') + .attr('class', 'member-row member-row-new form-field'); + + enter + .append('input') + .attr('type', 'text') + .attr('class', 'member-entity-input') + .call(utilNoAuto); + + enter + .append('input') + .attr('class', 'member-role') + .property('type', 'text') + .attr('maxlength', 255) + .attr('placeholder', t('inspector.role')) + .call(utilNoAuto) + .on('change', changeRole); + + enter + .append('button') + .attr('tabindex', -1) + .attr('class', 'remove button-input-action member-delete minor') + .on('click', deleteMembership) + .call(svgIcon('#operation-delete')); -function uiFieldCheck(field, context) { - var dispatch$$1 = dispatch('change'); - var options = field.strings && field.strings.options; - var values = []; - var texts = []; + newrow = newrow + .merge(enter); - var input = d3_select(null); - var text = d3_select(null); - var label = d3_select(null); - var reverser = d3_select(null); + newrow.selectAll('.member-entity-input') + .call(d3combobox() + .container(context.container()) + .minItems(1) + .fetcher(function(value, callback) { callback(relations(value)); }) + .on('accept', onAccept) + ); - var _impliedYes; - var _entityID; - var _value; + var addrel = wrap.selectAll('.add-relation') + .data([0]); - if (options) { - for (var k in options) { - values.push(k === 'undefined' ? undefined : k); - texts.push(field.t('options.' + k, { 'default': options[k] })); - } - } else { - values = [undefined, 'yes']; - texts = [t('inspector.unknown'), t('inspector.check.yes')]; - if (field.type !== 'defaultCheck') { - values.push('no'); - texts.push(t('inspector.check.no')); - } - } + addrel = addrel.enter() + .append('button') + .attr('class', 'add-relation') + .merge(addrel); + + addrel + .call(svgIcon('#icon-plus', 'light')) + .on('click', function() { + _showBlank = true; + content(wrap); + list.selectAll('.member-entity-input').node().focus(); + }); + + + function onAccept(d) { + var role = list.selectAll('.member-row-new .member-role').property('value'); + addMembership(d, role); + } + + + function bindTypeahead(d) { + var row = select(this), + role = row.selectAll('input.member-role'); + + function sort(value, data) { + var sameletter = [], + other = []; + for (var i = 0; i < data.length; i++) { + if (data[i].value.substring(0, value.length) === value) { + sameletter.push(data[i]); + } else { + other.push(data[i]); + } + } + return sameletter.concat(other); + } + + role.call(d3combobox() + .container(context.container()) + .fetcher(function(role, callback) { + var rtype = d.relation.tags.type; + taginfo.roles({ + debounce: true, + rtype: rtype || '', + geometry: context.geometry(_entityID), + query: role + }, function(err, data) { + if (!err) callback(sort(role, data)); + }); + })); + } + + + function unbind() { + var row = select(this); + + row.selectAll('input.member-role') + .call(d3combobox.off); + } + } + } - // Checks tags to see whether an undefined value is "Assumed to be Yes" - function checkImpliedYes() { - _impliedYes = (field.id === 'oneway_yes'); + rawMembershipEditor.entityID = function(_) { + if (!arguments.length) return _entityID; + _entityID = _; + return rawMembershipEditor; + }; - // hack: pretend `oneway` field is a `oneway_yes` field - // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841 - if (field.id === 'oneway') { - var entity = context.entity(_entityID); - for (var key in entity.tags) { - if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) { - _impliedYes = true; - texts[0] = t('presets.fields.oneway_yes.options.undefined'); - break; - } - } - } - } + return rawMembershipEditor; + } - function reverserHidden() { - if (!d3_select('div.inspector-hover').empty()) return true; - return !(_value === 'yes' || (_impliedYes && !_value)); - } + function uiTagReference(tag) { + var taginfo = services.taginfo; + var tagReference = {}; + var _button = select(null); + var _body = select(null); + var _loaded; + var _showing; - function reverserSetText(selection$$1) { - var entity = context.hasEntity(_entityID); - if (reverserHidden() || !entity) return selection$$1; - var first = entity.first(); - var last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last(); - var pseudoDirection = first < last; - var icon = pseudoDirection ? '#icon-forward' : '#icon-backward'; + function findLocal(data) { + var locale = utilDetect().locale.toLowerCase(); + var localized; - selection$$1.selectAll('.reverser-span') - .text(t('inspector.check.reverser')) - .call(svgIcon(icon, 'inline')); + if (locale !== 'pt-br') { // see #3776, prefer 'pt' over 'pt-br' + localized = find$1(data, function(d) { + return d.lang.toLowerCase() === locale; + }); + if (localized) return localized; + } - return selection$$1; - } + // try the non-regional version of a language, like + // 'en' if the language is 'en-US' + if (locale.indexOf('-') !== -1) { + var first = locale.split('-')[0]; + localized = find$1(data, function(d) { + return d.lang.toLowerCase() === first; + }); + if (localized) return localized; + } + // finally fall back to english + return find$1(data, function(d) { + return d.lang.toLowerCase() === 'en'; + }); + } - var check = function(selection$$1) { - checkImpliedYes(); - selection$$1.classed('checkselect', 'true'); - label = selection$$1.selectAll('.preset-input-wrap') - .data([0]); + function load(param) { + if (!taginfo) return; + + _button + .classed('tag-reference-loading', true); + + taginfo.docs(param, function show(err, data) { + var docs; + if (!err && data) { + docs = findLocal(data); + } + + _body.html(''); + + if (!docs || !docs.title) { + if (param.hasOwnProperty('value')) { + load(omit(param, 'value')); // retry with key only + } else { + _body + .append('p') + .attr('class', 'tag-reference-description') + .text(t('inspector.no_documentation_key')); + done(); + } + return; + } + + if (docs.image && docs.image.thumb_url_prefix) { + _body + .append('img') + .attr('class', 'tag-reference-wiki-image') + .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix) + .on('load', function() { done(); }) + .on('error', function() { select(this).remove(); done(); }); + } else { + done(); + } + + _body + .append('p') + .attr('class', 'tag-reference-description') + .text(docs.description || t('inspector.documentation_redirect')); + + _body + .append('a') + .attr('class', 'tag-reference-link') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title) + .call(svgIcon('#icon-out-link', 'inline')) + .append('span') + .text(t('inspector.reference')); + + // Add link to info about "good changeset comments" - #2923 + if (param.key === 'comment') { + _body + .append('a') + .attr('class', 'tag-reference-comment-link') + .attr('target', '_blank') + .attr('tabindex', -1) + .call(svgIcon('#icon-out-link', 'inline')) + .attr('href', t('commit.about_changeset_comments_link')) + .append('span') + .text(t('commit.about_changeset_comments')); + } + }); + } - var enter = label.enter() - .append('label') - .attr('class', 'preset-input-wrap'); - enter - .append('input') - .property('indeterminate', field.type !== 'defaultCheck') - .attr('type', 'checkbox') - .attr('id', 'preset-input-' + field.id); + function done() { + _loaded = true; - enter - .append('span') - .text(texts[0]) - .attr('class', 'value'); + _button + .classed('tag-reference-loading', false); - if (field.type === 'onewayCheck') { - enter - .append('a') - .attr('id', 'preset-input-' + field.id + '-reverser') - .attr('class', 'reverser button' + (reverserHidden() ? ' hide' : '')) - .attr('href', '#') - .append('span') - .attr('class', 'reverser-span'); - } + _body + .classed('expanded', true) + .transition() + .duration(200) + .style('max-height', '200px') + .style('opacity', '1'); - label = label.merge(enter); - input = label.selectAll('input'); - text = label.selectAll('span.value'); + _showing = true; + } - input - .on('click', function() { - var t$$1 = {}; - t$$1[field.key] = values[(values.indexOf(_value) + 1) % values.length]; - dispatch$$1.call('change', this, t$$1); - event.stopPropagation(); - }); - if (field.type === 'onewayCheck') { - reverser = label.selectAll('.reverser'); - - reverser - .call(reverserSetText) - .on('click', function() { - event.preventDefault(); - event.stopPropagation(); - context.perform( - actionReverse(_entityID), - t('operations.reverse.annotation') - ); - d3_select(this) - .call(reverserSetText); - }); - } - }; + function hide() { + _body + .transition() + .duration(200) + .style('max-height', '0px') + .style('opacity', '0') + .on('end', function () { + _body.classed('expanded', false); + }); + _showing = false; + } - check.entity = function(_) { - if (!arguments.length) return context.hasEntity(_entityID); - _entityID = _.id; - return check; - }; + tagReference.button = function(selection$$1) { + _button = selection$$1.selectAll('.tag-reference-button') + .data([0]); + + _button = _button.enter() + .append('button') + .attr('class', 'tag-reference-button') + .attr('title', t('icons.information')) + .attr('tabindex', -1) + .call(svgIcon('#icon-inspect')) + .merge(_button); + + _button + .on('click', function () { + event.stopPropagation(); + event.preventDefault(); + if (_showing) { + hide(); + } else if (_loaded) { + done(); + } else { + load(tag); + } + }); + }; - check.tags = function(tags) { - function isChecked(val) { - return val !== 'no' && val !== '' && val !== undefined && val !== null; - } + tagReference.body = function(selection$$1) { + var tagid = tag.rtype || (tag.key + '-' + tag.value); + _body = selection$$1.selectAll('.tag-reference-body') + .data([tagid], function(d) { return d; }); - function textFor(val) { - if (val === '') val = undefined; - var index = values.indexOf(val); - return (index !== -1 ? texts[index] : ('"' + val + '"')); - } + _body.exit() + .remove(); - checkImpliedYes(); - _value = tags[field.key] && tags[field.key].toLowerCase(); + _body = _body.enter() + .append('div') + .attr('class', 'tag-reference-body cf') + .style('max-height', '0') + .style('opacity', '0') + .merge(_body); - if (field.type === 'onewayCheck' && (_value === '1' || _value === '-1')) { - _value = 'yes'; - } + if (_showing === false) { + hide(); + } + }; - input - .property('indeterminate', field.type !== 'defaultCheck' && !_value) - .property('checked', isChecked(_value)); - text - .text(textFor(_value)); + tagReference.showing = function(_) { + if (!arguments.length) return _showing; + _showing = _; + return tagReference; + }; - label - .classed('set', !!_value); - if (field.type === 'onewayCheck') { - reverser - .classed('hide', reverserHidden()) - .call(reverserSetText); - } - }; + return tagReference; + } + function uiRawTagEditor(context) { + var taginfo = services.taginfo, + dispatch$$1 = dispatch('change'), + _readOnlyTags = [], + _showBlank = false, + _updatePreference = true, + _expanded = false, + _newRow, + _state, + _preset, + _tags, + _entityID; + + + function rawTagEditor(selection$$1) { + var count = Object.keys(_tags).filter(function(d) { return d; }).length; + + var disclosure = uiDisclosure(context, 'raw_tag_editor', false) + .title(t('inspector.all_tags') + ' (' + count + ')') + .on('toggled', toggled) + .updatePreference(_updatePreference) + .content(content); + + // Sometimes we want to force the raw_tag_editor to be opened/closed.. + // When undefined, uiDisclosure will use the user's stored preference. + if (_expanded !== undefined) { + disclosure.expanded(_expanded); + } - check.focus = function() { - input.node().focus(); - }; + selection$$1.call(disclosure); - return utilRebind(check, dispatch$$1, 'on'); -} - -/** Used for built-in method references. */ -var arrayProto$1 = Array.prototype; - -/** Built-in value references. */ -var splice$1 = arrayProto$1.splice; - -/** - * The base implementation of `_.pullAt` without support for individual - * indexes or capturing the removed elements. - * - * @private - * @param {Array} array The array to modify. - * @param {number[]} indexes The indexes of elements to remove. - * @returns {Array} Returns `array`. - */ -function basePullAt(array, indexes) { - var length = array ? indexes.length : 0, - lastIndex = length - 1; - - while (length--) { - var index = indexes[length]; - if (length == lastIndex || index !== previous) { - var previous = index; - if (isIndex(index)) { - splice$1.call(array, index, 1); - } else { - baseUnset(array, index); - } - } - } - return array; -} - -/** - * Removes all elements from `array` that `predicate` returns truthy for - * and returns an array of the removed elements. The predicate is invoked - * with three arguments: (value, index, array). - * - * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` - * to pull elements from an array by value. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Array - * @param {Array} array The array to modify. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new array of removed elements. - * @example - * - * var array = [1, 2, 3, 4]; - * var evens = _.remove(array, function(n) { - * return n % 2 == 0; - * }); - * - * console.log(array); - * // => [1, 3] - * - * console.log(evens); - * // => [2, 4] - */ -function remove$8(array, predicate) { - var result = []; - if (!(array && array.length)) { - return result; - } - var index = -1, - indexes = [], - length = array.length; + function toggled(expanded) { + _expanded = expanded; + if (expanded) { + selection$$1.node().parentNode.scrollTop += 200; + } + } + } - predicate = baseIteratee(predicate, 3); - while (++index < length) { - var value = array[index]; - if (predicate(value, index, array)) { - result.push(value); - indexes.push(index); - } - } - basePullAt(array, indexes); - return result; -} -function uiFieldCombo(field, context) { - var dispatch$$1 = dispatch('change'), - nominatim = services.geocoder, - taginfo = services.taginfo, - isMulti = (field.type === 'multiCombo'), - isNetwork = (field.type === 'networkCombo'), - isSemi = (field.type === 'semiCombo'), - optstrings = field.strings && field.strings.options, - optarray = field.options, - snake_case = (field.snake_case || (field.snake_case === undefined)), - caseSensitive = field.caseSensitive, - combobox = d3combobox() - .container(context.container()) - .caseSensitive(caseSensitive) - .minItems(isMulti || isSemi ? 1 : 2), - comboData = [], - multiData = [], - container, - input, - entity, - country; + function content(wrap) { + var entries = map$3(_tags, function(v, k) { + return { key: k, value: v }; + }); - // ensure multiCombo field.key ends with a ':' - if (isMulti && field.key.match(/:$/) === null) { - field.key += ':'; - } + if (!entries.length || _showBlank) { + _showBlank = false; + entries.push({key: '', value: ''}); + _newRow = ''; + } + var list = wrap.selectAll('.tag-list') + .data([0]); + + list = list.enter() + .append('ul') + .attr('class', 'tag-list') + .merge(list); + + var newTag = wrap.selectAll('.add-tag') + .data([0]); + + newTag.enter() + .append('button') + .attr('class', 'add-tag') + .on('click', addTag) + .call(svgIcon('#icon-plus', 'light')); + + + var items = list.selectAll('.tag-row') + .data(entries, function(d) { return d.key; }); + + items.exit() + .each(unbind) + .remove(); + + // Enter + + var enter = items.enter() + .append('li') + .attr('class', 'tag-row cf') + .classed('readonly', isReadOnly); + + enter + .append('div') + .attr('class', 'key-wrap') + .append('input') + .property('type', 'text') + .attr('class', 'key') + .attr('maxlength', 255) + .call(utilNoAuto) + .on('blur', keyChange) + .on('change', keyChange); + + enter + .append('div') + .attr('class', 'input-wrap-position') + .append('input') + .property('type', 'text') + .attr('class', 'value') + .attr('maxlength', 255) + .call(utilNoAuto) + .on('blur', valueChange) + .on('change', valueChange) + .on('keydown.push-more', pushMore); + + enter + .append('button') + .attr('tabindex', -1) + .attr('class', 'remove minor') + .call(svgIcon('#operation-delete')); + + + // Update + + items = items + .merge(enter) + .sort(function(a, b) { + return (a.key === _newRow && b.key !== _newRow) ? 1 + : (a.key !== _newRow && b.key === _newRow) ? -1 + : ascending(a.key, b.key); + }); + + items + .each(function(tag) { + var row = select(this), + key = row.select('input.key'), // propagate bound data to child + value = row.select('input.value'); // propagate bound data to child + + if (_entityID && taginfo) { + bindTypeahead(key, value); + } + + var isRelation = (_entityID && context.entity(_entityID).type === 'relation'), + reference; + + if (isRelation && tag.key === 'type') { + reference = uiTagReference({ rtype: tag.value }, context); + } else { + reference = uiTagReference({ key: tag.key, value: tag.value }, context); + } + + if (_state === 'hover') { + reference.showing(false); + } + + row + .call(reference.button) + .call(reference.body); + }); + + items.selectAll('input.key') + .attr('title', function(d) { return d.key; }) + .call(utilGetSetValue, function(d) { return d.key; }) + .property('disabled', isReadOnly); + + items.selectAll('input.value') + .attr('title', function(d) { return d.value; }) + .call(utilGetSetValue, function(d) { return d.value; }) + .property('disabled', isReadOnly); + + items.selectAll('button.remove') + .on('click', removeTag); + + + + function isReadOnly(d) { + for (var i = 0; i < _readOnlyTags.length; i++) { + if (d.key.match(_readOnlyTags[i]) !== null) { + return true; + } + } + return false; + } - function snake(s) { - return s.replace(/\s+/g, '_'); - } - function unsnake(s) { - return s.replace(/_+/g, ' '); - } + function pushMore() { + if (event.keyCode === 9 && !event.shiftKey && + list.selectAll('li:last-child input.value').node() === this) { + addTag(); + } + } - function clean(s) { - return s.split(';') - .map(function(s) { return s.trim(); }) - .join(';'); - } + function bindTypeahead(key, value) { + if (isReadOnly(key.datum())) return; + + var geometry = context.geometry(_entityID); + + key.call(d3combobox() + .container(context.container()) + .fetcher(function(value, callback) { + taginfo.keys({ + debounce: true, + geometry: geometry, + query: value + }, function(err, data) { + if (!err) callback(sort(value, data)); + }); + })); + + value.call(d3combobox() + .container(context.container()) + .fetcher(function(value, callback) { + taginfo.values({ + debounce: true, + key: utilGetSetValue(key), + geometry: geometry, + query: value + }, function(err, data) { + if (!err) callback(sort(value, data)); + }); + })); + + + function sort(value, data) { + var sameletter = [], + other = []; + for (var i = 0; i < data.length; i++) { + if (data[i].value.substring(0, value.length) === value) { + sameletter.push(data[i]); + } else { + other.push(data[i]); + } + } + return sameletter.concat(other); + } + } - // returns the tag value for a display value - // (for multiCombo, dval should be the key suffix, not the entire key) - function tagValue(dval) { - dval = clean(dval || ''); - if (optstrings) { - var match = find$1(comboData, function(o) { - return o.key && clean(o.value) === dval; - }); - if (match) { - return match.key; - } - } + function unbind() { + var row = select(this); - if (field.type === 'typeCombo' && !dval) { - return 'yes'; - } + row.selectAll('input.key') + .call(d3combobox.off); - return (snake_case ? snake(dval) : dval) || undefined; - } + row.selectAll('input.value') + .call(d3combobox.off); + } - // returns the display value for a tag value - // (for multiCombo, tval should be the key suffix, not the entire key) - function displayValue(tval) { - tval = tval || ''; + function keyChange(d) { + var kOld = d.key, + kNew = this.value.trim(), + tag = {}; - if (optstrings) { - var match = find$1(comboData, function(o) { return o.key === tval && o.value; }); - if (match) { - return match.value; - } - } - if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') { - return ''; - } + if (isReadOnly({ key: kNew })) { + this.value = kOld; + return; + } - return snake_case ? unsnake(tval) : tval; - } + if (kNew && kNew !== kOld) { + var match = kNew.match(/^(.*?)(?:_(\d+))?$/), + base = match[1], + suffix = +(match[2] || 1); + while (_tags[kNew]) { // rename key if already in use + kNew = base + '_' + suffix++; + } + } + tag[kOld] = undefined; + tag[kNew] = d.value; + d.key = kNew; // Maintain DOM identity through the subsequent update. - function objectDifference(a, b) { - return reject(a, function(d1) { - return some(b, function(d2) { return d1.value === d2.value; }); - }); - } + if (_newRow === kOld) { // see if this row is still a new row + _newRow = ((d.value === '' || kNew === '') ? kNew : undefined); + } + this.value = kNew; + dispatch$$1.call('change', this, tag); + } - function initCombo(selection$$1, attachTo) { - if (optstrings) { - selection$$1.attr('readonly', 'readonly'); - selection$$1.call(combobox, attachTo); - setStaticValues(setPlaceholder); - } else if (optarray) { - selection$$1.call(combobox, attachTo); - setStaticValues(setPlaceholder); + function valueChange(d) { + if (isReadOnly(d)) return; + var tag = {}; + tag[d.key] = this.value; - } else if (taginfo) { - selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo); - setTaginfoValues('', setPlaceholder); - } - } + if (_newRow === d.key && d.key !== '' && d.value !== '') { // not a new row anymore + _newRow = undefined; + } + dispatch$$1.call('change', this, tag); + } - function setStaticValues(callback) { - if (!(optstrings || optarray)) return; - if (optstrings) { - comboData = Object.keys(optstrings).map(function(k) { - var v = field.t('options.' + k, { 'default': optstrings[k] }); - return { - key: k, - value: v, - title: v - }; - }); + function removeTag(d) { + if (isReadOnly(d)) return; + var tag = {}; + tag[d.key] = undefined; + dispatch$$1.call('change', this, tag); + select(this.parentNode).remove(); + } - } else if (optarray) { - comboData = optarray.map(function(k) { - var v = snake_case ? unsnake(k) : k; - return { - key: k, - value: v, - title: v - }; - }); - } - combobox.data(objectDifference(comboData, multiData)); - if (callback) callback(comboData); - } + function addTag() { + // Wrapped in a setTimeout in case it's being called from a blur + // handler. Without the setTimeout, the call to `content` would + // wipe out the pending value change. + window.setTimeout(function() { + _showBlank = true; + content(wrap); + list.selectAll('li:last-child input.key').node().focus(); + }, 1); + } + } - function setTaginfoValues(q, callback) { - var fn = isMulti ? 'multikeys' : 'values'; - var query = (isMulti ? field.key : '') + q; - var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0; - if (hasCountryPrefix) { - query = country + ':'; - } + rawTagEditor.state = function(_) { + if (!arguments.length) return _state; + _state = _; + return rawTagEditor; + }; - var params = { - debounce: (q !== ''), - key: field.key, - query: query - }; - if (entity) { - params.geometry = context.geometry(entity.id); - } + rawTagEditor.preset = function(_) { + if (!arguments.length) return _preset; + _preset = _; + if (_preset.isFallback()) { + _expanded = true; + _updatePreference = false; + } else { + _expanded = undefined; + _updatePreference = true; + } + return rawTagEditor; + }; - taginfo[fn](params, function(err, data) { - if (err) return; - if (hasCountryPrefix) { - data = filter(data, function(d) { - return d.value.toLowerCase().indexOf(country + ':') === 0; - }); - } - comboData = map$3(data, function(d) { - var k = d.value; - if (isMulti) k = k.replace(field.key, ''); - var v = snake_case ? unsnake(k) : k; - return { - key: k, - value: v, - title: isMulti ? v : d.title - }; - }); + rawTagEditor.tags = function(_) { + if (!arguments.length) return _tags; + _tags = _; + return rawTagEditor; + }; - comboData = objectDifference(comboData, multiData); - if (callback) callback(comboData); - }); - } + rawTagEditor.entityID = function(_) { + if (!arguments.length) return _entityID; + _entityID = _; + return rawTagEditor; + }; - function setPlaceholder(d) { - var ph; - if (isMulti || isSemi) { - ph = field.placeholder() || t('inspector.add'); - } else { - var vals = map$3(d, 'value').filter(function(s) { return s.length < 20; }), - placeholders = vals.length > 1 ? vals : map$3(d, 'key'); - ph = field.placeholder() || placeholders.slice(0, 3).join(', '); - } + rawTagEditor.expanded = function(_) { + if (!arguments.length) return _expanded; + _expanded = _; + _updatePreference = false; + return rawTagEditor; + }; - if (ph.match(/(…|\.\.\.)$/) === null) { - ph += '…'; - } - container.selectAll('input') - .attr('placeholder', ph); - } + rawTagEditor.readOnlyTags = function(_) { + if (!arguments.length) return _readOnlyTags; + _readOnlyTags = _; + return rawTagEditor; + }; - function change() { - var val = tagValue(utilGetSetValue(input)), - t$$1 = {}; + return utilRebind(rawTagEditor, dispatch$$1, 'on'); + } - if (isMulti || isSemi) { - if (!val) return; - container.classed('active', false); - utilGetSetValue(input, ''); - if (isMulti) { - field.keys.push(field.key + val); - t$$1[field.key + val] = 'yes'; - } else if (isSemi) { - var arr = multiData.map(function(d) { return d.key; }); - arr.push(val); - t$$1[field.key] = compact(uniq(arr)).join(';'); - } - window.setTimeout(function() { input.node().focus(); }, 10); + // This currently only works with the 'restrictions' field + // It borrows some code from uiHelp + + function uiFieldHelp(context, fieldName) { + var fieldHelp = {}; + var _inspector = select(null); + var _wrap = select(null); + var _body = select(null); + + var fieldHelpKeys = { + restrictions: [ + ['about',[ + 'about', + 'from_via_to', + 'maxdist', + 'maxvia' + ]], + ['inspecting',[ + 'about', + 'from_shadow', + 'allow_shadow', + 'restrict_shadow', + 'only_shadow', + 'restricted', + 'only' + ]], + ['modifying',[ + 'about', + 'indicators', + 'allow_turn', + 'restrict_turn', + 'only_turn' + ]], + ['tips',[ + 'simple', + 'simple_example', + 'indirect', + 'indirect_example', + 'indirect_noedit' + ]] + ] + }; - } else { - t$$1[field.key] = val; - } + var fieldHelpHeadings = {}; + + var replacements = { + distField: t('restriction.controls.distance'), + viaField: t('restriction.controls.via'), + fromShadow: icon('#turn-shadow', 'pre-text shadow from'), + allowShadow: icon('#turn-shadow', 'pre-text shadow allow'), + restrictShadow: icon('#turn-shadow', 'pre-text shadow restrict'), + onlyShadow: icon('#turn-shadow', 'pre-text shadow only'), + allowTurn: icon('#turn-yes', 'pre-text turn'), + restrictTurn: icon('#turn-no', 'pre-text turn'), + onlyTurn: icon('#turn-only', 'pre-text turn') + }; - dispatch$$1.call('change', this, t$$1); - } + + // For each section, squash all the texts into a single markdown document + var docs = fieldHelpKeys[fieldName].map(function(key) { + var helpkey = 'help.field.' + fieldName + '.' + key[0]; + var text = key[1].reduce(function(all, part) { + var subkey = helpkey + '.' + part; + var depth = fieldHelpHeadings[subkey]; // is this subkey a heading? + var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s + return all + hhh + t(subkey, replacements) + '\n\n'; + }, ''); + + return { + key: helpkey, + title: t(helpkey + '.title'), + html: marked(text.trim()) + }; + }); - function removeMultikey(d) { - event.stopPropagation(); - var t$$1 = {}; - if (isMulti) { - t$$1[d.key] = undefined; - } else if (isSemi) { - remove$8(multiData, function(md) { return md.key === d.key; }); - var arr = multiData.map(function(md) { return md.key; }); - arr = compact(uniq(arr)); - t$$1[field.key] = arr.length ? arr.join(';') : undefined; - } - dispatch$$1.call('change', this, t$$1); - } + function show() { + updatePosition(); + _body + .classed('hide', false) + .style('opacity', '0') + .transition() + .duration(200) + .style('opacity', '1'); + } - function combo(selection$$1) { - if (isMulti || isSemi) { - container = selection$$1.selectAll('ul').data([0]); - container = container.enter() - .append('ul') - .attr('class', 'form-field-multicombo') - .on('click', function() { - window.setTimeout(function() { input.node().focus(); }, 10); - }) - .merge(container); + function hide() { + _body + .classed('hide', true) + .transition() + .duration(200) + .style('opacity', '0') + .on('end', function () { + _body.classed('hide', true); + }); + } - } else { - container = selection$$1; - } - input = container.selectAll('input') - .data([0]); - - input = input.enter() - .append('input') - .attr('type', 'text') - .attr('id', 'preset-input-' + field.id) - .call(utilNoAuto) - .call(initCombo, selection$$1) - .merge(input); - - if (isNetwork && nominatim && entity) { - var center = entity.extent(context.graph()).center(); - nominatim.countryCode(center, function (err, code) { - country = code; - }); - } + function clickHelp(index) { + var d = docs[index]; + var tkeys = fieldHelpKeys[fieldName][index][1]; - input - .on('change', change) - .on('blur', change); + _body.selectAll('.field-help-nav-item') + .classed('active', function(d, i) { return i === index; }); - if (isMulti || isSemi) { - combobox - .on('accept', function() { - input.node().blur(); - input.node().focus(); - }); + var content = _body.selectAll('.field-help-content') + .html(d.html); - input - .on('focus', function() { container.classed('active', true); }); - } - } + // class the paragraphs so we can find and style them + content.selectAll('p') + .attr('class', function(d, i) { return tkeys[i]; }); + // insert special content for certain help sections + if (d.key === 'help.field.restrictions.inspecting') { + content + .insert('img', 'p.from_shadow') + .attr('class', 'field-help-image cf') + .attr('src', context.imagePath('tr_inspect.gif')); - combo.tags = function(tags) { - if (isMulti || isSemi) { - multiData = []; + } else if (d.key === 'help.field.restrictions.modifying') { + content + .insert('img', 'p.allow_turn') + .attr('class', 'field-help-image cf') + .attr('src', context.imagePath('tr_modify.gif')); + } + } - if (isMulti) { - // Build multiData array containing keys already set.. - Object.keys(tags).forEach(function(key) { - if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return; - var suffix = key.substring(field.key.length); - multiData.push({ - key: key, - value: displayValue(suffix) - }); - }); + fieldHelp.button = function(selection$$1) { + if (_body.empty()) return; + + var button = selection$$1.selectAll('.field-help-button') + .data([0]); + + // enter/update + button.enter() + .append('button') + .attr('class', 'field-help-button') + .attr('tabindex', -1) + .call(svgIcon('#icon-help')) + .merge(button) + .on('click', function () { + event.stopPropagation(); + event.preventDefault(); + if (_body.classed('hide')) { + show(); + } else { + hide(); + } + }); + }; - // Set keys for form-field modified (needed for undo and reset buttons).. - field.keys = map$3(multiData, 'key'); - } else if (isSemi) { - var arr = compact(uniq((tags[field.key] || '').split(';'))); - multiData = arr.map(function(key) { - return { - key: key, - value: displayValue(key) - }; - }); - } + function updatePosition() { + var wrap = _wrap.node(); + var inspector = _inspector.node(); + var wRect = wrap.getBoundingClientRect(); + var iRect = inspector.getBoundingClientRect(); + + _body + .style('top', wRect.top + inspector.scrollTop - iRect.top + 'px'); + } - // Exclude existing multikeys from combo options.. - var available = objectDifference(comboData, multiData); - combobox.data(available); - // Hide 'Add' button if this field uses fixed set of - // translateable optstrings and they're all currently used.. - container.selectAll('.combobox-input, .combobox-caret') - .classed('hide', optstrings && !available.length); + fieldHelp.body = function(selection$$1) { + // This control expects the field to have a preset-input-wrap div + _wrap = selection$$1.selectAll('.preset-input-wrap'); + if (_wrap.empty()) return; + + // absolute position relative to the inspector, so it "floats" above the fields + _inspector = select('#sidebar .entity-editor-pane .inspector-body'); + if (_inspector.empty()) return; + + _body = _inspector.selectAll('.field-help-body') + .data([0]); + + var enter = _body.enter() + .append('div') + .attr('class', 'field-help-body hide'); // initially hidden + + var titleEnter = enter + .append('div') + .attr('class', 'field-help-title cf'); + + titleEnter + .append('h2') + .attr('class', 'fl') + .text(t('help.field.' + fieldName + '.title')); + + titleEnter + .append('button') + .attr('class', 'fr close') + .on('click', function() { + event.stopPropagation(); + event.preventDefault(); + hide(); + }) + .call(svgIcon('#icon-close')); + + var navEnter = enter + .append('div') + .attr('class', 'field-help-nav cf'); + + var titles = docs.map(function(d) { return d.title; }); + navEnter.selectAll('.field-help-nav-item') + .data(titles) + .enter() + .append('div') + .attr('class', 'field-help-nav-item') + .text(function(d) { return d; }) + .on('click', function(d, i) { + event.stopPropagation(); + event.preventDefault(); + clickHelp(i); + }); + + enter + .append('div') + .attr('class', 'field-help-content'); + + _body = _body + .merge(enter); + + clickHelp(0); + }; - // Render chips - var chips = container.selectAll('.chips') - .data(multiData); + return fieldHelp; + } - chips.exit() - .remove(); + function uiFieldCheck(field, context) { + var dispatch$$1 = dispatch('change'); + var options = field.strings && field.strings.options; + var values = []; + var texts = []; - var enter = chips.enter() - .insert('li', 'input') - .attr('class', 'chips'); + var input = select(null); + var text = select(null); + var label = select(null); + var reverser = select(null); - enter.append('span'); - enter.append('a'); + var _impliedYes; + var _entityID; + var _value; - chips = chips.merge(enter); - chips.select('span') - .text(function(d) { return d.value; }); + if (options) { + for (var k in options) { + values.push(k === 'undefined' ? undefined : k); + texts.push(field.t('options.' + k, { 'default': options[k] })); + } + } else { + values = [undefined, 'yes']; + texts = [t('inspector.unknown'), t('inspector.check.yes')]; + if (field.type !== 'defaultCheck') { + values.push('no'); + texts.push(t('inspector.check.no')); + } + } - chips.select('a') - .on('click', removeMultikey) - .attr('class', 'remove') - .text('×'); - } else { - utilGetSetValue(input, displayValue(tags[field.key])); - } - }; + // Checks tags to see whether an undefined value is "Assumed to be Yes" + function checkImpliedYes() { + _impliedYes = (field.id === 'oneway_yes'); + + // hack: pretend `oneway` field is a `oneway_yes` field + // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841 + if (field.id === 'oneway') { + var entity = context.entity(_entityID); + for (var key in entity.tags) { + if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) { + _impliedYes = true; + texts[0] = t('presets.fields.oneway_yes.options.undefined'); + break; + } + } + } + } - combo.focus = function() { - input.node().focus(); - }; + function reverserHidden() { + if (!select('div.inspector-hover').empty()) return true; + return !(_value === 'yes' || (_impliedYes && !_value)); + } - combo.entity = function(_) { - if (!arguments.length) return entity; - entity = _; - return combo; - }; + function reverserSetText(selection$$1) { + var entity = context.hasEntity(_entityID); + if (reverserHidden() || !entity) return selection$$1; + var first = entity.first(); + var last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last(); + var pseudoDirection = first < last; + var icon = pseudoDirection ? '#icon-forward' : '#icon-backward'; - return utilRebind(combo, dispatch$$1, 'on'); -} + selection$$1.selectAll('.reverser-span') + .text(t('inspector.check.reverser')) + .call(svgIcon(icon, 'inline')); -function uiFieldText(field, context) { - var dispatch$$1 = dispatch('change'), - nominatim = services.geocoder, - input, - entity; + return selection$$1; + } - function i(selection$$1) { - var fieldId = 'preset-input-' + field.id; + var check = function(selection$$1) { + checkImpliedYes(); + selection$$1.classed('checkselect', 'true'); - input = selection$$1.selectAll('input') - .data([0]); + label = selection$$1.selectAll('.preset-input-wrap') + .data([0]); - input = input.enter() - .append('input') - .attr('type', field.type) - .attr('id', fieldId) - .attr('placeholder', field.placeholder() || t('inspector.unknown')) - .call(utilNoAuto) - .merge(input); + var enter = label.enter() + .append('label') + .attr('class', 'preset-input-wrap'); - input - .on('input', change(true)) - .on('blur', change()) - .on('change', change()); + enter + .append('input') + .property('indeterminate', field.type !== 'defaultCheck') + .attr('type', 'checkbox') + .attr('id', 'preset-input-' + field.safeid); - if (field.type === 'tel' && nominatim && entity) { - var center = entity.extent(context.graph()).center(); - nominatim.countryCode(center, function (err, countryCode) { - if (err || !dataPhoneFormats[countryCode]) return; - selection$$1.selectAll('#' + fieldId) - .attr('placeholder', dataPhoneFormats[countryCode]); - }); + enter + .append('span') + .text(texts[0]) + .attr('class', 'value'); - } else if (field.type === 'number') { - var rtl = (textDirection === 'rtl'); + if (field.type === 'onewayCheck') { + enter + .append('a') + .attr('id', 'preset-input-' + field.safeid + '-reverser') + .attr('class', 'reverser button' + (reverserHidden() ? ' hide' : '')) + .attr('href', '#') + .append('span') + .attr('class', 'reverser-span'); + } - input.attr('type', 'text'); + label = label.merge(enter); + input = label.selectAll('input'); + text = label.selectAll('span.value'); + + input + .on('click', function() { + event.stopPropagation(); + var t$$1 = {}; + t$$1[field.key] = values[(values.indexOf(_value) + 1) % values.length]; + + // Don't cycle through `alternating` or `reversible` states - #4970 + // (They are supported as translated strings, but should not toggle with clicks) + if (t$$1[field.key] === 'reversible' || t$$1[field.key] === 'alternating') { + t$$1[field.key] = values[0]; + } + + dispatch$$1.call('change', this, t$$1); + }); + + if (field.type === 'onewayCheck') { + reverser = label.selectAll('.reverser'); + + reverser + .call(reverserSetText) + .on('click', function() { + event.preventDefault(); + event.stopPropagation(); + context.perform( + actionReverse(_entityID), + t('operations.reverse.annotation') + ); + select(this) + .call(reverserSetText); + }); + } + }; - var spinControl = selection$$1.selectAll('.spin-control') - .data([0]); - var enter = spinControl.enter() - .append('div') - .attr('class', 'spin-control'); + check.entity = function(_) { + if (!arguments.length) return context.hasEntity(_entityID); + _entityID = _.id; + return check; + }; - enter - .append('button') - .datum(rtl ? 1 : -1) - .attr('class', rtl ? 'increment' : 'decrement') - .attr('tabindex', -1); - enter - .append('button') - .datum(rtl ? -1 : 1) - .attr('class', rtl ? 'decrement' : 'increment') - .attr('tabindex', -1); + check.tags = function(tags) { - spinControl = spinControl - .merge(enter); + function isChecked(val) { + return val !== 'no' && val !== '' && val !== undefined && val !== null; + } - spinControl.selectAll('button') - .on('click', function(d) { - event.preventDefault(); - var num = parseInt(input.node().value || 0, 10); - if (!isNaN(num)) input.node().value = num + d; - change()(); - }); - } - } + function textFor(val) { + if (val === '') val = undefined; + var index = values.indexOf(val); + return (index !== -1 ? texts[index] : ('"' + val + '"')); + } + checkImpliedYes(); + _value = tags[field.key] && tags[field.key].toLowerCase(); - function change(onInput) { - return function() { - var t$$1 = {}; - t$$1[field.key] = utilGetSetValue(input) || undefined; - dispatch$$1.call('change', this, t$$1, onInput); - }; - } + if (field.type === 'onewayCheck' && (_value === '1' || _value === '-1')) { + _value = 'yes'; + } + input + .property('indeterminate', field.type !== 'defaultCheck' && !_value) + .property('checked', isChecked(_value)); - i.entity = function(_) { - if (!arguments.length) return entity; - entity = _; - return i; - }; + text + .text(textFor(_value)); + label + .classed('set', !!_value); - i.tags = function(tags) { - utilGetSetValue(input, tags[field.key] || ''); - }; + if (field.type === 'onewayCheck') { + reverser + .classed('hide', reverserHidden()) + .call(reverserSetText); + } + }; - i.focus = function() { - var node = input.node(); - if (node) node.focus(); - }; + check.focus = function() { + input.node().focus(); + }; - return utilRebind(i, dispatch$$1, 'on'); -} - -function uiFieldAccess(field, context) { - var dispatch$$1 = dispatch('change'), - items; - - function access(selection$$1) { - var wrap = selection$$1.selectAll('.preset-input-wrap') - .data([0]); - - wrap = wrap.enter() - .append('div') - .attr('class', 'cf preset-input-wrap') - .append('ul') - .merge(wrap); - - var list = wrap.selectAll('ul') - .data([0]); - - list = list.enter() - .append('ul') - .merge(list); - - - items = list.selectAll('li') - .data(field.keys); - - // Enter - var enter = items.enter() - .append('li') - .attr('class', function(d) { return 'cf preset-access-' + d; }); - - enter - .append('span') - .attr('class', 'col6 label preset-label-access') - .attr('for', function(d) { return 'preset-input-access-' + d; }) - .text(function(d) { return field.t('types.' + d); }); - - enter - .append('div') - .attr('class', 'col6 preset-input-access-wrap') - .append('input') - .attr('type', 'text') - .attr('class', 'preset-input-access') - .attr('id', function(d) { return 'preset-input-access-' + d; }) - .call(utilNoAuto) - .each(function(d) { - d3_select(this) - .call(d3combobox() - .container(context.container()) - .data(access.options(d)) - ); - }); + return utilRebind(check, dispatch$$1, 'on'); + } + + /** Used for built-in method references. */ + var arrayProto$1 = Array.prototype; + /** Built-in value references. */ + var splice$1 = arrayProto$1.splice; - // Update - items = items.merge(enter); + /** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; - wrap.selectAll('.preset-input-access') - .on('change', change) - .on('blur', change); + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice$1.call(array, index, 1); + } else { + baseUnset(array, index); + } + } } + return array; + } + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is invoked + * with three arguments: (value, index, array). + * + * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` + * to pull elements from an array by value. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove$8(array, predicate) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, + indexes = [], + length = array.length; - function change(d) { - var tag = {}; - tag[d] = utilGetSetValue(d3_select(this)) || undefined; - dispatch$$1.call('change', this, tag); + predicate = baseIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } } + basePullAt(array, indexes); + return result; + } + function uiFieldCombo(field, context) { + var dispatch$$1 = dispatch('change'), + nominatim = services.geocoder, + taginfo = services.taginfo, + isMulti = (field.type === 'multiCombo'), + isNetwork = (field.type === 'networkCombo'), + isSemi = (field.type === 'semiCombo'), + optstrings = field.strings && field.strings.options, + optarray = field.options, + snake_case = (field.snake_case || (field.snake_case === undefined)), + caseSensitive = field.caseSensitive, + combobox = d3combobox() + .container(context.container()) + .caseSensitive(caseSensitive) + .minItems(isMulti || isSemi ? 1 : 2), + comboData = [], + multiData = [], + container, + input, + entity, + country; + + // ensure multiCombo field.key ends with a ':' + if (isMulti && field.key.match(/:$/) === null) { + field.key += ':'; + } - access.options = function(type) { - var options = ['no', 'permissive', 'private', 'destination']; - if (type !== 'access') { - options.unshift('yes'); - options.push('designated'); + function snake(s) { + return s.replace(/\s+/g, '_'); + } - if (type === 'bicycle') { - options.push('dismount'); - } - } + function unsnake(s) { + return s.replace(/_+/g, ' '); + } - return options.map(function(option) { - return { - title: field.t('options.' + option + '.description'), - value: option - }; - }); - }; + function clean(s) { + return s.split(';') + .map(function(s) { return s.trim(); }) + .join(';'); + } - var placeholders = { - footway: { - foot: 'designated', - motor_vehicle: 'no' - }, - steps: { - foot: 'yes', - motor_vehicle: 'no', - bicycle: 'no', - horse: 'no' - }, - pedestrian: { - foot: 'yes', - motor_vehicle: 'no' - }, - cycleway: { - motor_vehicle: 'no', - bicycle: 'designated' - }, - bridleway: { - motor_vehicle: 'no', - horse: 'designated' - }, - path: { - foot: 'yes', - motor_vehicle: 'no', - bicycle: 'yes', - horse: 'yes' - }, - motorway: { - foot: 'no', - motor_vehicle: 'yes', - bicycle: 'no', - horse: 'no' - }, - trunk: { - motor_vehicle: 'yes' - }, - primary: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - }, - secondary: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - }, - tertiary: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - }, - residential: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - }, - unclassified: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - }, - service: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - }, - motorway_link: { - foot: 'no', - motor_vehicle: 'yes', - bicycle: 'no', - horse: 'no' - }, - trunk_link: { - motor_vehicle: 'yes' - }, - primary_link: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - }, - secondary_link: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - }, - tertiary_link: { - foot: 'yes', - motor_vehicle: 'yes', - bicycle: 'yes', - horse: 'yes' - } - }; + // returns the tag value for a display value + // (for multiCombo, dval should be the key suffix, not the entire key) + function tagValue(dval) { + dval = clean(dval || ''); + if (optstrings) { + var match = find$1(comboData, function(o) { + return o.key && clean(o.value) === dval; + }); + if (match) { + return match.key; + } + } - access.tags = function(tags) { - utilGetSetValue(items.selectAll('.preset-input-access'), - function(d) { return tags[d] || ''; }) - .attr('placeholder', function() { - return tags.access ? tags.access : field.placeholder(); - }); + if (field.type === 'typeCombo' && !dval) { + return 'yes'; + } - items.selectAll('#preset-input-access-access') - .attr('placeholder', 'yes'); + return (snake_case ? snake(dval) : dval) || undefined; + } - forEach(placeholders[tags.highway], function(v, k) { - items.selectAll('#preset-input-access-' + k) - .attr('placeholder', function() { return (tags.access || v); }); - }); - }; + // returns the display value for a tag value + // (for multiCombo, tval should be the key suffix, not the entire key) + function displayValue(tval) { + tval = tval || ''; - access.focus = function() { - items.selectAll('.preset-input-access') - .node().focus(); - }; + if (optstrings) { + var match = find$1(comboData, function(o) { return o.key === tval && o.value; }); + if (match) { + return match.value; + } + } + if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') { + return ''; + } - return utilRebind(access, dispatch$$1, 'on'); -} - -function uiFieldAddress(field, context) { - var dispatch$$1 = dispatch('init', 'change'), - nominatim = services.geocoder, - wrap = d3_select(null), - isInitialized = false, - entity; - - function getNearStreets() { - var extent = entity.extent(context.graph()), - l = extent.center(), - box = geoExtent$$1(l).padByMeters(200); - - var streets = context.intersects(box) - .filter(isAddressable) - .map(function(d) { - var loc = context.projection([ - (extent[0][0] + extent[1][0]) / 2, - (extent[0][1] + extent[1][1]) / 2]), - choice = geoChooseEdge(context.childNodes(d), loc, context.projection); - return { - title: d.tags.name, - value: d.tags.name, - dist: choice.distance - }; - }) - .sort(function(a, b) { - return a.dist - b.dist; - }); + return snake_case ? unsnake(tval) : tval; + } - return uniqBy(streets, 'value'); - function isAddressable(d) { - return d.tags.highway && d.tags.name && d.type === 'way'; - } - } + function objectDifference(a, b) { + return reject(a, function(d1) { + return some(b, function(d2) { return d1.value === d2.value; }); + }); + } - function getNearCities() { - var extent = entity.extent(context.graph()), - l = extent.center(), - box = geoExtent$$1(l).padByMeters(200); + function initCombo(selection$$1, attachTo) { + if (optstrings) { + selection$$1.attr('readonly', 'readonly'); + selection$$1.call(combobox, attachTo); + setStaticValues(setPlaceholder); - var cities = context.intersects(box) - .filter(isAddressable) - .map(function(d) { - return { - title: d.tags['addr:city'] || d.tags.name, - value: d.tags['addr:city'] || d.tags.name, - dist: geoSphericalDistance(d.extent(context.graph()).center(), l) - }; - }) - .sort(function(a, b) { - return a.dist - b.dist; - }); + } else if (optarray) { + selection$$1.call(combobox, attachTo); + setStaticValues(setPlaceholder); - return uniqBy(cities, 'value'); + } else if (taginfo) { + selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo); + setTaginfoValues('', setPlaceholder); + } + } - function isAddressable(d) { - if (d.tags.name && - (d.tags.admin_level === '8' || d.tags.border_type === 'city')) - return true; + function setStaticValues(callback) { + if (!(optstrings || optarray)) return; + + if (optstrings) { + comboData = Object.keys(optstrings).map(function(k) { + var v = field.t('options.' + k, { 'default': optstrings[k] }); + return { + key: k, + value: v, + title: v + }; + }); + + } else if (optarray) { + comboData = optarray.map(function(k) { + var v = snake_case ? unsnake(k) : k; + return { + key: k, + value: v, + title: v + }; + }); + } - if (d.tags.place && d.tags.name && ( - d.tags.place === 'city' || - d.tags.place === 'town' || - d.tags.place === 'village')) - return true; + combobox.data(objectDifference(comboData, multiData)); + if (callback) callback(comboData); + } - if (d.tags['addr:city']) return true; - return false; - } - } + function setTaginfoValues(q, callback) { + var fn = isMulti ? 'multikeys' : 'values'; + var query = (isMulti ? field.key : '') + q; + var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0; + if (hasCountryPrefix) { + query = country + ':'; + } - function getNearValues(key) { - var extent = entity.extent(context.graph()), - l = extent.center(), - box = geoExtent$$1(l).padByMeters(200); - - var results = context.intersects(box) - .filter(function hasTag(d) { - return d.tags[key]; - }) - .map(function(d) { - return { - title: d.tags[key], - value: d.tags[key], - dist: geoSphericalDistance(d.extent(context.graph()).center(), l) - }; - }) - .sort(function(a, b) { - return a.dist - b.dist; - }); + var params = { + debounce: (q !== ''), + key: field.key, + query: query + }; - return uniqBy(results, 'value'); - } + if (entity) { + params.geometry = context.geometry(entity.id); + } + taginfo[fn](params, function(err, data) { + if (err) return; + if (hasCountryPrefix) { + data = filter(data, function(d) { + return d.value.toLowerCase().indexOf(country + ':') === 0; + }); + } + + comboData = map$3(data, function(d) { + var k = d.value; + if (isMulti) k = k.replace(field.key, ''); + var v = snake_case ? unsnake(k) : k; + return { + key: k, + value: v, + title: isMulti ? v : d.title + }; + }); + + comboData = objectDifference(comboData, multiData); + if (callback) callback(comboData); + }); + } - function initCallback(err, countryCode) { - if (err) return; - var addressFormat = find$1(dataAddressFormats, function (a) { - return a && a.countryCodes && includes(a.countryCodes, countryCode.toLowerCase()); - }) || dataAddressFormats[0]; + function setPlaceholder(d) { + var ph; - var widths = addressFormat.widths || { - housenumber: 1/3, street: 2/3, - city: 2/3, state: 1/4, postcode: 1/3 - }; + if (isMulti || isSemi) { + ph = field.placeholder() || t('inspector.add'); + } else { + var vals = map$3(d, 'value').filter(function(s) { return s.length < 20; }), + placeholders = vals.length > 1 ? vals : map$3(d, 'key'); + ph = field.placeholder() || placeholders.slice(0, 3).join(', '); + } - function row(r) { - // Normalize widths. - var total = reduce(r, function(sum, field) { - return sum + (widths[field] || 0.5); - }, 0); - - return r.map(function (field) { - return { - id: field, - width: (widths[field] || 0.5) / total - }; - }); - } + if (ph.match(/(…|\.\.\.)$/) === null) { + ph += '…'; + } - wrap.selectAll('div.addr-row') - .data(addressFormat.format) - .enter() - .append('div') - .attr('class', 'addr-row') - .selectAll('input') - .data(row) - .enter() - .append('input') - .property('type', 'text') - .attr('placeholder', function (d) { - var localkey = d.id + '!' + countryCode.toLowerCase(), - tkey = field.strings.placeholders[localkey] ? localkey : d.id; - return field.t('placeholders.' + tkey); - }) - .attr('class', function (d) { return 'addr-' + d.id; }) - .call(utilNoAuto) - .style('width', function (d) { return d.width * 100 + '%'; }); - - // Update - - // setup dropdowns for common address tags - var dropdowns = addressFormat.dropdowns || [ - 'city', 'county', 'country', 'district', 'hamlet', - 'neighbourhood', 'place', 'postcode', 'province', - 'quarter', 'state', 'street', 'subdistrict', 'suburb' - ]; + container.selectAll('input') + .attr('placeholder', ph); + } - // If fields exist for any of these tags, create dropdowns to pick nearby values.. - dropdowns.forEach(function(tag) { - var nearValues = (tag === 'street') ? getNearStreets - : (tag === 'city') ? getNearCities - : getNearValues; - - wrap.selectAll('input.addr-' + tag) - .call(d3combobox() - .container(context.container()) - .minItems(1) - .fetcher(function(value, callback) { - callback(nearValues('addr:' + tag)); - }) - ); - }); - wrap.selectAll('input') - .on('blur', change()) - .on('change', change()); + function change() { + var val = tagValue(utilGetSetValue(input)), + t$$1 = {}; + + if (isMulti || isSemi) { + if (!val) return; + container.classed('active', false); + utilGetSetValue(input, ''); + if (isMulti) { + field.keys.push(field.key + val); + t$$1[field.key + val] = 'yes'; + } else if (isSemi) { + var arr = multiData.map(function(d) { return d.key; }); + arr.push(val); + t$$1[field.key] = compact(uniq(arr)).join(';'); + } + window.setTimeout(function() { input.node().focus(); }, 10); - wrap.selectAll('input:not(.combobox-input)') - .on('input', change(true)); + } else { + t$$1[field.key] = val; + } - dispatch$$1.call('init'); - isInitialized = true; - } + dispatch$$1.call('change', this, t$$1); + } - function address(selection$$1) { - isInitialized = false; + function removeMultikey(d) { + event.stopPropagation(); + var t$$1 = {}; + if (isMulti) { + t$$1[d.key] = undefined; + } else if (isSemi) { + remove$8(multiData, function(md) { return md.key === d.key; }); + var arr = multiData.map(function(md) { return md.key; }); + arr = compact(uniq(arr)); + t$$1[field.key] = arr.length ? arr.join(';') : undefined; + } + dispatch$$1.call('change', this, t$$1); + } - wrap = selection$$1.selectAll('.preset-input-wrap') - .data([0]); - wrap = wrap.enter() - .append('div') - .attr('class', 'preset-input-wrap') - .merge(wrap); + function combo(selection$$1) { + if (isMulti || isSemi) { + container = selection$$1.selectAll('ul').data([0]); - if (nominatim && entity) { - var center = entity.extent(context.graph()).center(); - nominatim.countryCode(center, initCallback); - } - } + container = container.enter() + .append('ul') + .attr('class', 'form-field-multicombo') + .on('click', function() { + window.setTimeout(function() { input.node().focus(); }, 10); + }) + .merge(container); + } else { + container = selection$$1; + } - function change(onInput) { - return function() { - var tags = {}; + input = container.selectAll('input') + .data([0]); + + input = input.enter() + .append('input') + .attr('type', 'text') + .attr('id', 'preset-input-' + field.safeid) + .call(utilNoAuto) + .call(initCombo, selection$$1) + .merge(input); + + if (isNetwork && nominatim && entity) { + var center = entity.extent(context.graph()).center(); + nominatim.countryCode(center, function (err, code) { + country = code; + }); + } - wrap.selectAll('input') - .each(function (field) { - tags['addr:' + field.id] = this.value || undefined; - }); + input + .on('change', change) + .on('blur', change); - dispatch$$1.call('change', this, tags, onInput); - }; - } + if (isMulti || isSemi) { + combobox + .on('accept', function() { + input.node().blur(); + input.node().focus(); + }); + input + .on('focus', function() { container.classed('active', true); }); + } + } - function updateTags(tags) { - utilGetSetValue(wrap.selectAll('input'), function (field) { - return tags['addr:' + field.id] || ''; - }); - } + combo.tags = function(tags) { + if (isMulti || isSemi) { + multiData = []; - address.entity = function(_) { - if (!arguments.length) return entity; - entity = _; - return address; - }; + if (isMulti) { + // Build multiData array containing keys already set.. + Object.keys(tags).forEach(function(key) { + if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return; + var suffix = key.substring(field.key.length); + multiData.push({ + key: key, + value: displayValue(suffix) + }); + }); - address.tags = function(tags) { - if (isInitialized) { - updateTags(tags); - } else { - dispatch$$1.on('init', function () { - dispatch$$1.on('init', null); - updateTags(tags); - }); - } - }; + // Set keys for form-field modified (needed for undo and reset buttons).. + field.keys = map$3(multiData, 'key'); + } else if (isSemi) { + var arr = compact(uniq((tags[field.key] || '').split(';'))); + multiData = arr.map(function(key) { + return { + key: key, + value: displayValue(key) + }; + }); + } - address.focus = function() { - var node = wrap.selectAll('input').node(); - if (node) node.focus(); - }; + // Exclude existing multikeys from combo options.. + var available = objectDifference(comboData, multiData); + combobox.data(available); + // Hide 'Add' button if this field uses fixed set of + // translateable optstrings and they're all currently used.. + container.selectAll('.combobox-input, .combobox-caret') + .classed('hide', optstrings && !available.length); - return utilRebind(address, dispatch$$1, 'on'); -} -function uiFieldCycleway(field, context) { - var dispatch$$1 = dispatch('change'), - items = d3_select(null); + // Render chips + var chips = container.selectAll('.chips') + .data(multiData); + chips.exit() + .remove(); - function cycleway(selection$$1) { + var enter = chips.enter() + .insert('li', 'input') + .attr('class', 'chips'); - function stripcolon(s) { - return s.replace(':', ''); - } + enter.append('span'); + enter.append('a'); + chips = chips.merge(enter); - var wrap = selection$$1.selectAll('.preset-input-wrap') - .data([0]); + chips.select('span') + .text(function(d) { return d.value; }); - wrap = wrap.enter() - .append('div') - .attr('class', 'cf preset-input-wrap') - .merge(wrap); + chips.select('a') + .on('click', removeMultikey) + .attr('class', 'remove') + .text('×'); + } else { + utilGetSetValue(input, displayValue(tags[field.key])); + } + }; - var div = wrap.selectAll('ul') - .data([0]); - div = div.enter() - .append('ul') - .merge(div); + combo.focus = function() { + input.node().focus(); + }; - items = div.selectAll('li') - .data(field.keys); + combo.entity = function(_) { + if (!arguments.length) return entity; + entity = _; + return combo; + }; - var enter = items.enter() - .append('li') - .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); }); - enter - .append('span') - .attr('class', 'col6 label preset-label-cycleway') - .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); }) - .text(function(d) { return field.t('types.' + d); }); + return utilRebind(combo, dispatch$$1, 'on'); + } - enter - .append('div') - .attr('class', 'col6 preset-input-cycleway-wrap') - .append('input') - .attr('type', 'text') - .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); }) - .call(utilNoAuto) - .each(function(d) { - d3_select(this) - .call(d3combobox() - .container(context.container()) - .data(cycleway.options(d)) - ); - }); + function uiFieldText(field, context) { + var dispatch$$1 = dispatch('change'), + nominatim = services.geocoder, + input, + entity; - // Update - wrap.selectAll('.preset-input-cycleway') - .on('change', change) - .on('blur', change); - } + function i(selection$$1) { + var fieldId = 'preset-input-' + field.safeid; + input = selection$$1.selectAll('input') + .data([0]); - function change() { - var left = utilGetSetValue(d3_select('.preset-input-cyclewayleft')), - right = utilGetSetValue(d3_select('.preset-input-cyclewayright')), - tag = {}; + input = input.enter() + .append('input') + .attr('type', field.type) + .attr('id', fieldId) + .attr('placeholder', field.placeholder() || t('inspector.unknown')) + .call(utilNoAuto) + .merge(input); - if (left === 'none' || left === '') { left = undefined; } - if (right === 'none' || right === '') { right = undefined; } + input + .on('input', change(true)) + .on('blur', change()) + .on('change', change()); - // Always set both left and right as changing one can affect the other - tag = { - cycleway: undefined, - 'cycleway:left': left, - 'cycleway:right': right - }; + if (field.type === 'tel' && nominatim && entity) { + var center = entity.extent(context.graph()).center(); + nominatim.countryCode(center, function (err, countryCode) { + if (err || !dataPhoneFormats[countryCode]) return; + selection$$1.selectAll('#' + fieldId) + .attr('placeholder', dataPhoneFormats[countryCode]); + }); - // If the left and right tags match, use the cycleway tag to tag both - // sides the same way - if (left === right) { - tag = { - cycleway: left, - 'cycleway:left': undefined, - 'cycleway:right': undefined - }; - } + } else if (field.type === 'number') { + var rtl = (textDirection === 'rtl'); - dispatch$$1.call('change', this, tag); - } + input.attr('type', 'text'); + var spinControl = selection$$1.selectAll('.spin-control') + .data([0]); - cycleway.options = function() { - return keys$1(field.strings.options).map(function(option) { - return { - title: field.t('options.' + option + '.description'), - value: option - }; - }); - }; + var enter = spinControl.enter() + .append('div') + .attr('class', 'spin-control'); + enter + .append('button') + .datum(rtl ? 1 : -1) + .attr('class', rtl ? 'increment' : 'decrement') + .attr('tabindex', -1); - cycleway.tags = function(tags) { - utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) { - // If cycleway is set, always return that - if (tags.cycleway) { - return tags.cycleway; - } - return tags[d] || ''; - }) - .attr('placeholder', field.placeholder()); - }; + enter + .append('button') + .datum(rtl ? -1 : 1) + .attr('class', rtl ? 'decrement' : 'increment') + .attr('tabindex', -1); + + spinControl = spinControl + .merge(enter); + + spinControl.selectAll('button') + .on('click', function(d) { + event.preventDefault(); + var num = parseInt(input.node().value || 0, 10); + if (!isNaN(num)) input.node().value = num + d; + change()(); + }); + } + } - cycleway.focus = function() { - items.selectAll('.preset-input-cycleway') - .node().focus(); - }; + function change(onInput) { + return function() { + var t$$1 = {}; + t$$1[field.key] = utilGetSetValue(input) || undefined; + dispatch$$1.call('change', this, t$$1, onInput); + }; + } - return utilRebind(cycleway, dispatch$$1, 'on'); -} + i.entity = function(_) { + if (!arguments.length) return entity; + entity = _; + return i; + }; -function uiFieldLanes(field, context) { - var dispatch$$1 = dispatch('change'), - LANE_WIDTH = 40, - LANE_HEIGHT = 200, - wayID, - lanesData; - function lanes(selection$$1) { - lanesData = context.entity(wayID).lanes(); + i.tags = function(tags) { + utilGetSetValue(input, tags[field.key] || ''); + }; - if (!d3_select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) { - selection$$1.call(lanes.off); - return; - } - var wrap = selection$$1.selectAll('.preset-input-wrap') - .data([0]); + i.focus = function() { + var node = input.node(); + if (node) node.focus(); + }; - wrap = wrap.enter() - .append('div') - .attr('class', 'preset-input-wrap') - .merge(wrap); + return utilRebind(i, dispatch$$1, 'on'); + } - var surface = wrap.selectAll('.surface') - .data([0]); + function uiFieldAccess(field, context) { + var dispatch$$1 = dispatch('change'), + items; + + function access(selection$$1) { + var wrap = selection$$1.selectAll('.preset-input-wrap') + .data([0]); + + wrap = wrap.enter() + .append('div') + .attr('class', 'cf preset-input-wrap') + .append('ul') + .merge(wrap); + + var list = wrap.selectAll('ul') + .data([0]); + + list = list.enter() + .append('ul') + .merge(list); + + + items = list.selectAll('li') + .data(field.keys); + + // Enter + var enter = items.enter() + .append('li') + .attr('class', function(d) { return 'cf preset-access-' + d; }); + + enter + .append('span') + .attr('class', 'col6 label preset-label-access') + .attr('for', function(d) { return 'preset-input-access-' + d; }) + .text(function(d) { return field.t('types.' + d); }); + + enter + .append('div') + .attr('class', 'col6 preset-input-access-wrap') + .append('input') + .attr('type', 'text') + .attr('class', 'preset-input-access') + .attr('id', function(d) { return 'preset-input-access-' + d; }) + .call(utilNoAuto) + .each(function(d) { + select(this) + .call(d3combobox() + .container(context.container()) + .data(access.options(d)) + ); + }); + + + // Update + items = items.merge(enter); + + wrap.selectAll('.preset-input-access') + .on('change', change) + .on('blur', change); + } - var d = utilGetDimensions(wrap); - var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5; - surface = surface.enter() - .append('svg') - .attr('width', d[0]) - .attr('height', 300) - .attr('class', 'surface') - .merge(surface); + function change(d) { + var tag = {}; + tag[d] = utilGetSetValue(select(this)) || undefined; + dispatch$$1.call('change', this, tag); + } - var lanesSelection = surface.selectAll('.lanes') - .data([0]); + access.options = function(type) { + var options = ['no', 'permissive', 'private', 'destination']; - lanesSelection = lanesSelection.enter() - .append('g') - .attr('class', 'lanes') - .merge(lanesSelection); + if (type !== 'access') { + options.unshift('yes'); + options.push('designated'); - lanesSelection - .attr('transform', function () { - return 'translate(' + (freeSpace / 2) + ', 0)'; - }); + if (type === 'bicycle') { + options.push('dismount'); + } + } + return options.map(function(option) { + return { + title: field.t('options.' + option + '.description'), + value: option + }; + }); + }; - var lane = lanesSelection.selectAll('.lane') - .data(lanesData.lanes); - - lane.exit() - .remove(); - - var enter = lane.enter() - .append('g') - .attr('class', 'lane'); - - enter - .append('g') - .append('rect') - .attr('y', 50) - .attr('width', LANE_WIDTH) - .attr('height', LANE_HEIGHT); - - enter - .append('g') - .attr('class', 'forward') - .append('text') - .attr('y', 40) - .attr('x', 14) - .text('▲'); - - enter - .append('g') - .attr('class', 'bothways') - .append('text') - .attr('y', 40) - .attr('x', 14) - .text('▲▼'); - - enter - .append('g') - .attr('class', 'backward') - .append('text') - .attr('y', 40) - .attr('x', 14) - .text('▼'); - - - lane = lane - .merge(enter); - - lane - .attr('transform', function(d) { - return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)'; - }); - lane.select('.forward') - .style('visibility', function(d) { - return d.direction === 'forward' ? 'visible' : 'hidden'; - }); + var placeholders = { + footway: { + foot: 'designated', + motor_vehicle: 'no' + }, + steps: { + foot: 'yes', + motor_vehicle: 'no', + bicycle: 'no', + horse: 'no' + }, + pedestrian: { + foot: 'yes', + motor_vehicle: 'no' + }, + cycleway: { + motor_vehicle: 'no', + bicycle: 'designated' + }, + bridleway: { + motor_vehicle: 'no', + horse: 'designated' + }, + path: { + foot: 'yes', + motor_vehicle: 'no', + bicycle: 'yes', + horse: 'yes' + }, + motorway: { + foot: 'no', + motor_vehicle: 'yes', + bicycle: 'no', + horse: 'no' + }, + trunk: { + motor_vehicle: 'yes' + }, + primary: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + }, + secondary: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + }, + tertiary: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + }, + residential: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + }, + unclassified: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + }, + service: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + }, + motorway_link: { + foot: 'no', + motor_vehicle: 'yes', + bicycle: 'no', + horse: 'no' + }, + trunk_link: { + motor_vehicle: 'yes' + }, + primary_link: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + }, + secondary_link: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + }, + tertiary_link: { + foot: 'yes', + motor_vehicle: 'yes', + bicycle: 'yes', + horse: 'yes' + } + }; - lane.select('.bothways') - .style('visibility', function(d) { - return d.direction === 'bothways' ? 'visible' : 'hidden'; - }); - lane.select('.backward') - .style('visibility', function(d) { - return d.direction === 'backward' ? 'visible' : 'hidden'; - }); - } + access.tags = function(tags) { + utilGetSetValue(items.selectAll('.preset-input-access'), + function(d) { return tags[d] || ''; }) + .attr('placeholder', function() { + return tags.access ? tags.access : field.placeholder(); + }); + items.selectAll('#preset-input-access-access') + .attr('placeholder', 'yes'); - lanes.entity = function(_) { - if (!wayID || wayID !== _.id) { - wayID = _.id; - } - }; + forEach(placeholders[tags.highway], function(v, k) { + items.selectAll('#preset-input-access-' + k) + .attr('placeholder', function() { return (tags.access || v); }); + }); + }; - lanes.tags = function() {}; - lanes.focus = function() {}; - lanes.off = function() {}; - - return utilRebind(lanes, dispatch$$1, 'on'); -} - -function uiFieldLocalized(field, context) { - var dispatch$$1 = dispatch('change', 'input'), - wikipedia = services.wikipedia, - input = d3_select(null), - localizedInputs = d3_select(null), - wikiTitles, - entity; - - - function localized(selection$$1) { - input = selection$$1.selectAll('.localized-main') - .data([0]); - - input = input.enter() - .append('input') - .attr('type', 'text') - .attr('id', 'preset-input-' + field.id) - .attr('class', 'localized-main') - .attr('placeholder', field.placeholder()) - .call(utilNoAuto) - .merge(input); - - if (field.id === 'name') { - var preset = context.presets().match(entity, context.graph()); - input - .call(d3combobox() - .container(context.container()) - .fetcher(utilSuggestNames(preset, dataSuggestions)) - ); - } - input - .on('input', change(true)) - .on('blur', change()) - .on('change', change()); + access.focus = function() { + items.selectAll('.preset-input-access') + .node().focus(); + }; - var translateButton = selection$$1.selectAll('.localized-add') - .data([0]); + return utilRebind(access, dispatch$$1, 'on'); + } - translateButton = translateButton.enter() - .append('button') - .attr('class', 'button-input-action localized-add minor') - .attr('tabindex', -1) - .call(svgIcon('#icon-plus')) - .call(tooltip() - .title(t('translate.translate')) - .placement('left')) - .merge(translateButton); + function uiFieldAddress(field, context) { + var dispatch$$1 = dispatch('init', 'change'), + nominatim = services.geocoder, + wrap = select(null), + isInitialized = false, + entity; + + function getNearStreets() { + var extent = entity.extent(context.graph()), + l = extent.center(), + box = geoExtent$$1(l).padByMeters(200); + + var streets = context.intersects(box) + .filter(isAddressable) + .map(function(d) { + var loc = context.projection([ + (extent[0][0] + extent[1][0]) / 2, + (extent[0][1] + extent[1][1]) / 2]), + choice = geoChooseEdge(context.childNodes(d), loc, context.projection); + return { + title: d.tags.name, + value: d.tags.name, + dist: choice.distance + }; + }) + .sort(function(a, b) { + return a.dist - b.dist; + }); + + return uniqBy(streets, 'value'); + + function isAddressable(d) { + return d.tags.highway && d.tags.name && d.type === 'way'; + } + } - translateButton - .on('click', addNew); + function getNearCities() { + var extent = entity.extent(context.graph()), + l = extent.center(), + box = geoExtent$$1(l).padByMeters(200); + + var cities = context.intersects(box) + .filter(isAddressable) + .map(function(d) { + return { + title: d.tags['addr:city'] || d.tags.name, + value: d.tags['addr:city'] || d.tags.name, + dist: geoSphericalDistance(d.extent(context.graph()).center(), l) + }; + }) + .sort(function(a, b) { + return a.dist - b.dist; + }); + + return uniqBy(cities, 'value'); + + + function isAddressable(d) { + if (d.tags.name) { + if (d.tags.admin_level === '8' && d.tags.boundary === 'administrative') + return true; + if (d.tags.border_type === 'city') + return true; + if (d.tags.place === 'city' || d.tags.place === 'town' || d.tags.place === 'village') + return true; + } + + if (d.tags['addr:city']) + return true; + + return false; + } + } - localizedInputs = selection$$1.selectAll('.localized-wrap') - .data([0]); + function getNearValues(key) { + var extent = entity.extent(context.graph()), + l = extent.center(), + box = geoExtent$$1(l).padByMeters(200); + + var results = context.intersects(box) + .filter(function hasTag(d) { + return d.tags[key]; + }) + .map(function(d) { + return { + title: d.tags[key], + value: d.tags[key], + dist: geoSphericalDistance(d.extent(context.graph()).center(), l) + }; + }) + .sort(function(a, b) { + return a.dist - b.dist; + }); + + return uniqBy(results, 'value'); + } - localizedInputs = localizedInputs.enter().append('div') - .attr('class', 'localized-wrap') - .merge(localizedInputs); - } + function initCallback(err, countryCode) { + if (err) return; - function addNew() { - event.preventDefault(); - var data$$1 = localizedInputs.selectAll('div.entry').data(); - var defaultLang = utilDetect().locale.toLowerCase().split('-')[0]; - var langExists = find$1(data$$1, function(datum) { return datum.lang === defaultLang;}); - var isLangEn = defaultLang.indexOf('en') > -1; - if (isLangEn || langExists) { - defaultLang = ''; - } - data$$1.push({ lang: defaultLang, value: '' }); - localizedInputs.call(render, data$$1); - } + var addressFormat = find$1(dataAddressFormats, function (a) { + return a && a.countryCodes && includes(a.countryCodes, countryCode.toLowerCase()); + }) || dataAddressFormats[0]; + var widths = addressFormat.widths || { + housenumber: 1/3, street: 2/3, + city: 2/3, state: 1/4, postcode: 1/3 + }; - function change(onInput) { - return function() { - var t$$1 = {}; - t$$1[field.key] = utilGetSetValue(d3_select(this)) || undefined; - dispatch$$1.call('change', this, t$$1, onInput); - }; - } + function row(r) { + // Normalize widths. + var total = reduce(r, function(sum, field) { + return sum + (widths[field] || 0.5); + }, 0); + + return r.map(function (field) { + return { + id: field, + width: (widths[field] || 0.5) / total + }; + }); + } + wrap.selectAll('div.addr-row') + .data(addressFormat.format) + .enter() + .append('div') + .attr('class', 'addr-row') + .selectAll('input') + .data(row) + .enter() + .append('input') + .property('type', 'text') + .attr('placeholder', function (d) { + var localkey = d.id + '!' + countryCode.toLowerCase(), + tkey = field.strings.placeholders[localkey] ? localkey : d.id; + return field.t('placeholders.' + tkey); + }) + .attr('class', function (d) { return 'addr-' + d.id; }) + .call(utilNoAuto) + .style('width', function (d) { return d.width * 100 + '%'; }); + + // Update + + // setup dropdowns for common address tags + var dropdowns = addressFormat.dropdowns || [ + 'city', 'county', 'country', 'district', 'hamlet', + 'neighbourhood', 'place', 'postcode', 'province', + 'quarter', 'state', 'street', 'subdistrict', 'suburb' + ]; - function key(lang) { - return field.key + ':' + lang; - } + // If fields exist for any of these tags, create dropdowns to pick nearby values.. + dropdowns.forEach(function(tag) { + var nearValues = (tag === 'street') ? getNearStreets + : (tag === 'city') ? getNearCities + : getNearValues; + + wrap.selectAll('input.addr-' + tag) + .call(d3combobox() + .container(context.container()) + .minItems(1) + .fetcher(function(value, callback) { + callback(nearValues('addr:' + tag)); + }) + ); + }); + wrap.selectAll('input') + .on('blur', change()) + .on('change', change()); - function changeLang(d) { - var lang = utilGetSetValue(d3_select(this)), - t$$1 = {}, - language = find$1(wikipedia$2, function(d) { - return d[0].toLowerCase() === lang.toLowerCase() || - d[1].toLowerCase() === lang.toLowerCase(); - }); + wrap.selectAll('input:not(.combobox-input)') + .on('input', change(true)); - if (language) lang = language[2]; + dispatch$$1.call('init'); + isInitialized = true; + } - if (d.lang && d.lang !== lang) { - t$$1[key(d.lang)] = undefined; - } - var value = utilGetSetValue(d3_select(this.parentNode) - .selectAll('.localized-value')); + function address(selection$$1) { + isInitialized = false; - if (lang && value) { - t$$1[key(lang)] = value; - } else if (lang && wikiTitles && wikiTitles[d.lang]) { - t$$1[key(lang)] = wikiTitles[d.lang]; - } + wrap = selection$$1.selectAll('.preset-input-wrap') + .data([0]); - d.lang = lang; - dispatch$$1.call('change', this, t$$1); - } + wrap = wrap.enter() + .append('div') + .attr('class', 'preset-input-wrap') + .merge(wrap); + if (nominatim && entity) { + var center = entity.extent(context.graph()).center(); + nominatim.countryCode(center, initCallback); + } + } - function changeValue(d) { - if (!d.lang) return; - var t$$1 = {}; - t$$1[key(d.lang)] = utilGetSetValue(d3_select(this)) || undefined; - dispatch$$1.call('change', this, t$$1); - } + function change(onInput) { + return function() { + var tags = {}; - function fetcher(value, cb) { - var v = value.toLowerCase(); + wrap.selectAll('input') + .each(function (field) { + tags['addr:' + field.id] = this.value || undefined; + }); - cb(wikipedia$2.filter(function(d) { - return d[0].toLowerCase().indexOf(v) >= 0 || - d[1].toLowerCase().indexOf(v) >= 0 || - d[2].toLowerCase().indexOf(v) >= 0; - }).map(function(d) { - return { value: d[1] }; - })); - } + dispatch$$1.call('change', this, tags, onInput); + }; + } - function render(selection$$1, data$$1) { - var wraps = selection$$1.selectAll('div.entry'). - data(data$$1, function(d) { return d.lang; }); + function updateTags(tags) { + utilGetSetValue(wrap.selectAll('input'), function (field) { + return tags['addr:' + field.id] || ''; + }); + } - wraps.exit() - .transition() - .duration(200) - .style('max-height','0px') - .style('opacity', '0') - .style('top','-10px') - .remove(); - var innerWrap = wraps.enter() - .insert('div', ':first-child'); + address.entity = function(_) { + if (!arguments.length) return entity; + entity = _; + return address; + }; - innerWrap.attr('class', 'entry') - .each(function() { - var wrap = d3_select(this); - var langcombo = d3combobox() - .container(context.container()) - .fetcher(fetcher) - .minItems(0); - - var label = wrap - .append('label') - .attr('class','form-label') - .text(t('translate.localized_translation_label')) - .attr('for','localized-lang'); - - label - .append('button') - .attr('class', 'minor remove') - .on('click', function(d){ - event.preventDefault(); - var t$$1 = {}; - t$$1[key(d.lang)] = undefined; - dispatch$$1.call('change', this, t$$1); - d3_select(this.parentNode.parentNode) - .style('top','0') - .style('max-height','240px') - .transition() - .style('opacity', '0') - .style('max-height','0px') - .remove(); - }) - .call(svgIcon('#operation-delete')); - - wrap - .append('input') - .attr('class', 'localized-lang') - .attr('type', 'text') - .attr('placeholder',t('translate.localized_translation_language')) - .on('blur', changeLang) - .on('change', changeLang) - .call(langcombo); - - wrap - .append('input') - .on('blur', changeValue) - .on('change', changeValue) - .attr('type', 'text') - .attr('placeholder', t('translate.localized_translation_name')) - .attr('class', 'localized-value'); - }); - innerWrap - .style('margin-top', '0px') - .style('max-height', '0px') - .style('opacity', '0') - .transition() - .duration(200) - .style('margin-top', '10px') - .style('max-height', '240px') - .style('opacity', '1') - .on('end', function() { - d3_select(this) - .style('max-height', '') - .style('overflow', 'visible'); - }); + address.tags = function(tags) { + if (isInitialized) { + updateTags(tags); + } else { + dispatch$$1.on('init', function () { + dispatch$$1.on('init', null); + updateTags(tags); + }); + } + }; - var entry = selection$$1.selectAll('.entry'); + address.focus = function() { + var node = wrap.selectAll('input').node(); + if (node) node.focus(); + }; - utilGetSetValue(entry.select('.localized-lang'), function(d) { - var lang = find$1(wikipedia$2, function(lang) { return lang[2] === d.lang; }); - return lang ? lang[1] : d.lang; - }); - utilGetSetValue(entry.select('.localized-value'), - function(d) { return d.value; }); - } + return utilRebind(address, dispatch$$1, 'on'); + } + function uiFieldCycleway(field, context) { + var dispatch$$1 = dispatch('change'), + items = select(null); - localized.tags = function(tags) { - // Fetch translations from wikipedia - if (tags.wikipedia && !wikiTitles) { - wikiTitles = {}; - var wm = tags.wikipedia.match(/([^:]+):(.+)/); - if (wm && wm[0] && wm[1]) { - wikipedia.translations(wm[1], wm[2], function(d) { - wikiTitles = d; - }); - } - } - utilGetSetValue(input, tags[field.key] || ''); + function cycleway(selection$$1) { - var postfixed = [], k, m; - for (k in tags) { - m = k.match(/^(.*):([a-zA-Z_-]+)$/); - if (m && m[1] === field.key && m[2]) { - postfixed.push({ lang: m[2], value: tags[k] }); - } - } + function stripcolon(s) { + return s.replace(':', ''); + } - localizedInputs.call(render, postfixed.reverse()); - }; + var wrap = selection$$1.selectAll('.preset-input-wrap') + .data([0]); - localized.focus = function() { - input.node().focus(); - }; + wrap = wrap.enter() + .append('div') + .attr('class', 'cf preset-input-wrap') + .merge(wrap); - localized.entity = function(_) { - if (!arguments.length) return entity; - entity = _; - return localized; - }; + var div = wrap.selectAll('ul') + .data([0]); - return utilRebind(localized, dispatch$$1, 'on'); -} + div = div.enter() + .append('ul') + .merge(div); -function uiFieldMaxspeed(field, context) { - var dispatch$$1 = dispatch('change'), - entity, - isImperial, - unitInput = d3_select(null), - input = d3_select(null), - combobox; - var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120], - imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80]; + items = div.selectAll('li') + .data(field.keys); + var enter = items.enter() + .append('li') + .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); }); - function maxspeed(selection$$1) { - combobox = d3combobox() - .container(context.container()); + enter + .append('span') + .attr('class', 'col6 label preset-label-cycleway') + .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); }) + .text(function(d) { return field.t('types.' + d); }); - var unitCombobox = d3combobox() - .container(context.container()) - .data(['km/h', 'mph'].map(comboValues)); + enter + .append('div') + .attr('class', 'col6 preset-input-cycleway-wrap') + .append('input') + .attr('type', 'text') + .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); }) + .call(utilNoAuto) + .each(function(d) { + select(this) + .call(d3combobox() + .container(context.container()) + .data(cycleway.options(d)) + ); + }); - input = selection$$1.selectAll('#preset-input-' + field.id) - .data([0]); - input = input.enter() - .append('input') - .attr('type', 'text') - .attr('id', 'preset-input-' + field.id) - .attr('placeholder', field.placeholder()) - .call(utilNoAuto) - .call(combobox) - .merge(input); + // Update + wrap.selectAll('.preset-input-cycleway') + .on('change', change) + .on('blur', change); + } - input - .on('change', change) - .on('blur', change); - var childNodes = context.graph().childNodes(context.entity(entity.id)), - loc = childNodes[~~(childNodes.length/2)].loc; + function change() { + var left = utilGetSetValue(select('.preset-input-cyclewayleft')), + right = utilGetSetValue(select('.preset-input-cyclewayright')), + tag = {}; - isImperial = some(dataImperial.features, function(f) { - return some(f.geometry.coordinates, function(d) { - return geoPointInPolygon(loc, d); - }); - }); + if (left === 'none' || left === '') { left = undefined; } + if (right === 'none' || right === '') { right = undefined; } - unitInput = selection$$1.selectAll('input.maxspeed-unit') - .data([0]); + // Always set both left and right as changing one can affect the other + tag = { + cycleway: undefined, + 'cycleway:left': left, + 'cycleway:right': right + }; - unitInput = unitInput.enter() - .append('input') - .attr('type', 'text') - .attr('class', 'maxspeed-unit') - .call(unitCombobox) - .merge(unitInput); + // If the left and right tags match, use the cycleway tag to tag both + // sides the same way + if (left === right) { + tag = { + cycleway: left, + 'cycleway:left': undefined, + 'cycleway:right': undefined + }; + } - unitInput - .on('blur', changeUnits) - .on('change', changeUnits); + dispatch$$1.call('change', this, tag); + } - function changeUnits() { - isImperial = utilGetSetValue(unitInput) === 'mph'; - utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h'); - setSuggestions(); - change(); - } - } + cycleway.options = function() { + return keys$1(field.strings.options).map(function(option) { + return { + title: field.t('options.' + option + '.description'), + value: option + }; + }); + }; - function setSuggestions() { - combobox.data((isImperial ? imperialValues : metricValues).map(comboValues)); - utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h'); - } + cycleway.tags = function(tags) { + utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) { + // If cycleway is set, always return that + if (tags.cycleway) { + return tags.cycleway; + } + return tags[d] || ''; + }) + .attr('placeholder', field.placeholder()); + }; - function comboValues(d) { - return { - value: d.toString(), - title: d.toString() - }; - } + cycleway.focus = function() { + items.selectAll('.preset-input-cycleway') + .node().focus(); + }; - function change() { - var tag = {}, - value = utilGetSetValue(input); + return utilRebind(cycleway, dispatch$$1, 'on'); + } - if (!value) { - tag[field.key] = undefined; - } else if (isNaN(value) || !isImperial) { - tag[field.key] = value; - } else { - tag[field.key] = value + ' mph'; - } + function uiFieldLanes(field, context) { + var dispatch$$1 = dispatch('change'), + LANE_WIDTH = 40, + LANE_HEIGHT = 200, + wayID, + lanesData; - dispatch$$1.call('change', this, tag); - } + function lanes(selection$$1) { + lanesData = context.entity(wayID).lanes(); + if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) { + selection$$1.call(lanes.off); + return; + } - maxspeed.tags = function(tags) { - var value = tags[field.key]; + var wrap = selection$$1.selectAll('.preset-input-wrap') + .data([0]); + + wrap = wrap.enter() + .append('div') + .attr('class', 'preset-input-wrap') + .merge(wrap); + + var surface = wrap.selectAll('.surface') + .data([0]); + + var d = utilGetDimensions(wrap); + var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5; + + surface = surface.enter() + .append('svg') + .attr('width', d[0]) + .attr('height', 300) + .attr('class', 'surface') + .merge(surface); + + + var lanesSelection = surface.selectAll('.lanes') + .data([0]); + + lanesSelection = lanesSelection.enter() + .append('g') + .attr('class', 'lanes') + .merge(lanesSelection); + + lanesSelection + .attr('transform', function () { + return 'translate(' + (freeSpace / 2) + ', 0)'; + }); + + + var lane = lanesSelection.selectAll('.lane') + .data(lanesData.lanes); + + lane.exit() + .remove(); + + var enter = lane.enter() + .append('g') + .attr('class', 'lane'); + + enter + .append('g') + .append('rect') + .attr('y', 50) + .attr('width', LANE_WIDTH) + .attr('height', LANE_HEIGHT); + + enter + .append('g') + .attr('class', 'forward') + .append('text') + .attr('y', 40) + .attr('x', 14) + .text('▲'); + + enter + .append('g') + .attr('class', 'bothways') + .append('text') + .attr('y', 40) + .attr('x', 14) + .text('▲▼'); + + enter + .append('g') + .attr('class', 'backward') + .append('text') + .attr('y', 40) + .attr('x', 14) + .text('▼'); + + + lane = lane + .merge(enter); + + lane + .attr('transform', function(d) { + return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)'; + }); + + lane.select('.forward') + .style('visibility', function(d) { + return d.direction === 'forward' ? 'visible' : 'hidden'; + }); + + lane.select('.bothways') + .style('visibility', function(d) { + return d.direction === 'bothways' ? 'visible' : 'hidden'; + }); + + lane.select('.backward') + .style('visibility', function(d) { + return d.direction === 'backward' ? 'visible' : 'hidden'; + }); + } - if (value && value.indexOf('mph') >= 0) { - value = parseInt(value, 10); - isImperial = true; - } else if (value) { - isImperial = false; - } - setSuggestions(); - utilGetSetValue(input, value || ''); - }; + lanes.entity = function(_) { + if (!wayID || wayID !== _.id) { + wayID = _.id; + } + }; + lanes.tags = function() {}; + lanes.focus = function() {}; + lanes.off = function() {}; - maxspeed.focus = function() { - input.node().focus(); - }; + return utilRebind(lanes, dispatch$$1, 'on'); + } + function uiFieldLocalized(field, context) { + var dispatch$$1 = dispatch('change', 'input'), + wikipedia = services.wikipedia, + input = select(null), + localizedInputs = select(null), + wikiTitles, + entity; + + + function localized(selection$$1) { + input = selection$$1.selectAll('.localized-main') + .data([0]); + + input = input.enter() + .append('input') + .attr('type', 'text') + .attr('id', 'preset-input-' + field.safeid) + .attr('class', 'localized-main') + .attr('placeholder', field.placeholder()) + .call(utilNoAuto) + .merge(input); + + if (field.id === 'name') { + var preset = context.presets().match(entity, context.graph()); + input + .call(d3combobox() + .container(context.container()) + .fetcher(utilSuggestNames(preset, dataSuggestions)) + ); + } - maxspeed.entity = function(_) { - entity = _; - }; + input + .on('input', change(true)) + .on('blur', change()) + .on('change', change()); - return utilRebind(maxspeed, dispatch$$1, 'on'); -} - -/** - * This function is like `baseIndexOf` except that it accepts a comparator. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} fromIndex The index to search from. - * @param {Function} comparator The comparator invoked per element. - * @returns {number} Returns the index of the matched value, else `-1`. - */ -function baseIndexOfWith(array, value, fromIndex, comparator) { - var index = fromIndex - 1, - length = array.length; - - while (++index < length) { - if (comparator(array[index], value)) { - return index; - } - } - return -1; -} - -/** Used for built-in method references. */ -var arrayProto$2 = Array.prototype; - -/** Built-in value references. */ -var splice$2 = arrayProto$2.splice; - -/** - * The base implementation of `_.pullAllBy` without support for iteratee - * shorthands. - * - * @private - * @param {Array} array The array to modify. - * @param {Array} values The values to remove. - * @param {Function} [iteratee] The iteratee invoked per element. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns `array`. - */ -function basePullAll(array, values, iteratee, comparator) { - var indexOf = comparator ? baseIndexOfWith : baseIndexOf, - index = -1, - length = values.length, - seen = array; - - if (array === values) { - values = copyArray(values); - } - if (iteratee) { - seen = arrayMap(array, baseUnary(iteratee)); - } - while (++index < length) { - var fromIndex = 0, - value = values[index], - computed = iteratee ? iteratee(value) : value; - - while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { - if (seen !== array) { - splice$2.call(seen, fromIndex, 1); - } - splice$2.call(array, fromIndex, 1); - } - } - return array; -} - -/** - * This method is like `_.pull` except that it accepts an array of values to remove. - * - * **Note:** Unlike `_.difference`, this method mutates `array`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to modify. - * @param {Array} values The values to remove. - * @returns {Array} Returns `array`. - * @example - * - * var array = ['a', 'b', 'c', 'a', 'b', 'c']; - * - * _.pullAll(array, ['a', 'c']); - * console.log(array); - * // => ['b', 'b'] - */ -function pullAll(array, values) { - return (array && array.length && values && values.length) - ? basePullAll(array, values) - : array; -} - -/** - * Removes all given values from `array` using - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. - * - * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` - * to remove elements from an array by predicate. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Array - * @param {Array} array The array to modify. - * @param {...*} [values] The values to remove. - * @returns {Array} Returns `array`. - * @example - * - * var array = ['a', 'b', 'c', 'a', 'b', 'c']; - * - * _.pull(array, 'a', 'c'); - * console.log(array); - * // => ['b', 'b'] - */ -var pull = baseRest(pullAll); - -function uiFieldRadio(field, context) { - var dispatch$$1 = dispatch('change'), - placeholder = d3_select(null), - wrap = d3_select(null), - labels = d3_select(null), - radios = d3_select(null), - radioData = clone(field.options || field.keys), - typeField, - layerField, - oldType = {}, - entity; - - - function selectedKey() { - var node = wrap.selectAll('.toggle-list label.active input'); - return !node.empty() && node.datum(); - } - - - function radio(selection$$1) { - selection$$1.classed('preset-radio', true); - - wrap = selection$$1.selectAll('.preset-input-wrap') - .data([0]); - - var enter = wrap.enter() - .append('div') - .attr('class', 'preset-input-wrap toggle-list'); - - enter - .append('span') - .attr('class', 'placeholder'); - - wrap = wrap - .merge(enter); - - - placeholder = wrap.selectAll('.placeholder'); - - labels = wrap.selectAll('label') - .data(radioData); - - enter = labels.enter() - .append('label'); - - enter - .append('input') - .attr('type', 'radio') - .attr('name', field.id) - .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); }) - .attr('checked', false); - - enter - .append('span') - .text(function(d) { return field.t('options.' + d, { 'default': d }); }); - - labels = labels - .merge(enter); - - radios = labels.selectAll('input') - .on('change', changeRadio); - - } - - - function structureExtras(selection$$1, tags) { - var selected = selectedKey(), - type = context.presets().field(selected), - layer = context.presets().field('layer'), - showLayer = (selected === 'bridge' || selected === 'tunnel'); + var translateButton = selection$$1.selectAll('.localized-add') + .data([0]); + translateButton = translateButton.enter() + .append('button') + .attr('class', 'button-input-action localized-add minor') + .attr('tabindex', -1) + .call(svgIcon('#icon-plus')) + .call(tooltip() + .title(t('translate.translate')) + .placement('left')) + .merge(translateButton); - var extrasWrap = selection$$1.selectAll('.structure-extras-wrap') - .data(selected ? [0] : []); + translateButton + .on('click', addNew); - extrasWrap.exit() - .remove(); - extrasWrap = extrasWrap.enter() - .append('div') - .attr('class', 'structure-extras-wrap') - .merge(extrasWrap); + localizedInputs = selection$$1.selectAll('.localized-wrap') + .data([0]); - var list = extrasWrap.selectAll('ul') - .data([0]); + localizedInputs = localizedInputs.enter().append('div') + .attr('class', 'localized-wrap') + .merge(localizedInputs); + } - list = list.enter() - .append('ul') - .merge(list); + function addNew() { + event.preventDefault(); + var data$$1 = localizedInputs.selectAll('div.entry').data(); + var defaultLang = utilDetect().locale.toLowerCase().split('-')[0]; + var langExists = find$1(data$$1, function(datum) { return datum.lang === defaultLang;}); + var isLangEn = defaultLang.indexOf('en') > -1; + if (isLangEn || langExists) { + defaultLang = ''; + } + data$$1.push({ lang: defaultLang, value: '' }); + localizedInputs.call(render, data$$1); + } - // Type - if (type) { - if (!typeField || typeField.id !== selected) { - typeField = uiField(context, type, entity, { wrap: false }) - .on('change', changeType); - } - typeField.tags(tags); - } else { - typeField = null; - } - var typeItem = list.selectAll('.structure-type-item') - .data(typeField ? [typeField] : [], function(d) { return d.id; }); + function change(onInput) { + return function() { + var t$$1 = {}; + t$$1[field.key] = utilGetSetValue(select(this)) || undefined; + dispatch$$1.call('change', this, t$$1, onInput); + }; + } - // Exit - typeItem.exit() - .remove(); - // Enter - var typeEnter = typeItem.enter() - .insert('li', ':first-child') - .attr('class', 'cf structure-type-item'); + function key(lang) { + return field.key + ':' + lang; + } - typeEnter - .append('span') - .attr('class', 'col6 label structure-label-type') - .attr('for', 'preset-input-' + selected) - .text(t('inspector.radio.structure.type')); - typeEnter - .append('div') - .attr('class', 'col6 structure-input-type-wrap'); + function changeLang(d) { + var lang = utilGetSetValue(select(this)), + t$$1 = {}, + language = find$1(wikipedia$2, function(d) { + return d[0].toLowerCase() === lang.toLowerCase() || + d[1].toLowerCase() === lang.toLowerCase(); + }); - // Update - typeItem = typeItem - .merge(typeEnter); + if (language) lang = language[2]; - if (typeField) { - typeItem.selectAll('.structure-input-type-wrap') - .call(typeField.render); - } + if (d.lang && d.lang !== lang) { + t$$1[key(d.lang)] = undefined; + } + var value = utilGetSetValue(select(this.parentNode) + .selectAll('.localized-value')); - // Layer - if (layer && showLayer) { - if (!layerField) { - layerField = uiField(context, layer, entity, { wrap: false }) - .on('change', changeLayer); - } - layerField.tags(tags); - field.keys = union(field.keys, ['layer']); - } else { - layerField = null; - pull(field.keys, 'layer'); - } + if (lang && value) { + t$$1[key(lang)] = value; + } else if (lang && wikiTitles && wikiTitles[d.lang]) { + t$$1[key(lang)] = wikiTitles[d.lang]; + } - var layerItem = list.selectAll('.structure-layer-item') - .data(layerField ? [layerField] : []); + d.lang = lang; + dispatch$$1.call('change', this, t$$1); + } - // Exit - layerItem.exit() - .remove(); - // Enter - var layerEnter = layerItem.enter() - .append('li') - .attr('class', 'cf structure-layer-item'); + function changeValue(d) { + if (!d.lang) return; + var t$$1 = {}; + t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined; + dispatch$$1.call('change', this, t$$1); + } - layerEnter - .append('span') - .attr('class', 'col6 label structure-label-layer') - .attr('for', 'preset-input-layer') - .text(t('inspector.radio.structure.layer')); - layerEnter - .append('div') - .attr('class', 'col6 structure-input-layer-wrap'); + function fetcher(value, cb) { + var v = value.toLowerCase(); - // Update - layerItem = layerItem - .merge(layerEnter); + cb(wikipedia$2.filter(function(d) { + return d[0].toLowerCase().indexOf(v) >= 0 || + d[1].toLowerCase().indexOf(v) >= 0 || + d[2].toLowerCase().indexOf(v) >= 0; + }).map(function(d) { + return { value: d[1] }; + })); + } - if (layerField) { - layerItem.selectAll('.structure-input-layer-wrap') - .call(layerField.render); - } - } + function render(selection$$1, data$$1) { + var wraps = selection$$1.selectAll('div.entry'). + data(data$$1, function(d) { return d.lang; }); + + wraps.exit() + .transition() + .duration(200) + .style('max-height','0px') + .style('opacity', '0') + .style('top','-10px') + .remove(); + + var innerWrap = wraps.enter() + .insert('div', ':first-child'); + + innerWrap.attr('class', 'entry') + .each(function() { + var wrap = select(this); + var langcombo = d3combobox() + .container(context.container()) + .fetcher(fetcher) + .minItems(0); + + var label = wrap + .append('label') + .attr('class','form-label') + .text(t('translate.localized_translation_label')) + .attr('for','localized-lang'); + + label + .append('button') + .attr('class', 'minor remove') + .on('click', function(d){ + event.preventDefault(); + var t$$1 = {}; + t$$1[key(d.lang)] = undefined; + dispatch$$1.call('change', this, t$$1); + select(this.parentNode.parentNode) + .style('top','0') + .style('max-height','240px') + .transition() + .style('opacity', '0') + .style('max-height','0px') + .remove(); + }) + .call(svgIcon('#operation-delete')); + + wrap + .append('input') + .attr('class', 'localized-lang') + .attr('type', 'text') + .attr('placeholder',t('translate.localized_translation_language')) + .on('blur', changeLang) + .on('change', changeLang) + .call(langcombo); + + wrap + .append('input') + .on('blur', changeValue) + .on('change', changeValue) + .attr('type', 'text') + .attr('placeholder', t('translate.localized_translation_name')) + .attr('class', 'localized-value'); + }); + + innerWrap + .style('margin-top', '0px') + .style('max-height', '0px') + .style('opacity', '0') + .transition() + .duration(200) + .style('margin-top', '10px') + .style('max-height', '240px') + .style('opacity', '1') + .on('end', function() { + select(this) + .style('max-height', '') + .style('overflow', 'visible'); + }); + + + var entry = selection$$1.selectAll('.entry'); + + utilGetSetValue(entry.select('.localized-lang'), function(d) { + var lang = find$1(wikipedia$2, function(lang) { return lang[2] === d.lang; }); + return lang ? lang[1] : d.lang; + }); + + utilGetSetValue(entry.select('.localized-value'), + function(d) { return d.value; }); + } - function changeType(t$$1, onInput) { - var key = selectedKey(); - if (!key) return; - var val = t$$1[key]; - if (val !== 'no') { - oldType[key] = val; - } + localized.tags = function(tags) { + // Fetch translations from wikipedia + if (tags.wikipedia && !wikiTitles) { + wikiTitles = {}; + var wm = tags.wikipedia.match(/([^:]+):(.+)/); + if (wm && wm[0] && wm[1]) { + wikipedia.translations(wm[1], wm[2], function(d) { + wikiTitles = d; + }); + } + } - if (field.type === 'structureRadio') { - // remove layer if it should not be set - if (val === 'no' || - (key !== 'bridge' && key !== 'tunnel') || - (key === 'tunnel' && val === 'building_passage')) { - t$$1.layer = undefined; - } - // add layer if it should be set - if (t$$1.layer === undefined) { - if (key === 'bridge' && val !== 'no') { - t$$1.layer = '1'; - } - if (key === 'tunnel' && val !== 'no' && val !== 'building_passage') { - t$$1.layer = '-1'; - } - } - } + utilGetSetValue(input, tags[field.key] || ''); - dispatch$$1.call('change', this, t$$1, onInput); - } + var postfixed = [], k, m; + for (k in tags) { + m = k.match(/^(.*):([a-zA-Z_-]+)$/); + if (m && m[1] === field.key && m[2]) { + postfixed.push({ lang: m[2], value: tags[k] }); + } + } + localizedInputs.call(render, postfixed.reverse()); + }; - function changeLayer(t$$1, onInput) { - if (t$$1.layer === '0') { - t$$1.layer = undefined; - } - dispatch$$1.call('change', this, t$$1, onInput); - } + localized.focus = function() { + input.node().focus(); + }; - function changeRadio() { - var t$$1 = {}, - activeKey; - if (field.key) { - t$$1[field.key] = undefined; - } + localized.entity = function(_) { + if (!arguments.length) return entity; + entity = _; + return localized; + }; - radios.each(function(d) { - var active = d3_select(this).property('checked'); - if (active) activeKey = d; + return utilRebind(localized, dispatch$$1, 'on'); + } - if (field.key) { - if (active) t$$1[field.key] = d; - } else { - var val = oldType[activeKey] || 'yes'; - t$$1[d] = active ? val : undefined; - } - }); + function uiFieldMaxspeed(field, context) { + var dispatch$$1 = dispatch('change'), + entity, + isImperial, + unitInput = select(null), + input = select(null), + combobox; + + var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120], + imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80]; + + + function maxspeed(selection$$1) { + combobox = d3combobox() + .container(context.container()); + + var unitCombobox = d3combobox() + .container(context.container()) + .data(['km/h', 'mph'].map(comboValues)); + + input = selection$$1.selectAll('#preset-input-' + field.safeid) + .data([0]); + + input = input.enter() + .append('input') + .attr('type', 'text') + .attr('id', 'preset-input-' + field.safeid) + .attr('placeholder', field.placeholder()) + .call(utilNoAuto) + .call(combobox) + .merge(input); + + input + .on('change', change) + .on('blur', change); + + var childNodes = context.graph().childNodes(context.entity(entity.id)), + loc = childNodes[~~(childNodes.length/2)].loc; + + isImperial = some(dataImperial.features, function(f) { + return some(f.geometry.coordinates, function(d) { + return geoPointInPolygon(loc, d); + }); + }); - if (field.type === 'structureRadio') { - if (activeKey === 'bridge') { - t$$1.layer = '1'; - } else if (activeKey === 'tunnel' && t$$1.tunnel !== 'building_passage') { - t$$1.layer = '-1'; - } else { - t$$1.layer = undefined; - } - } + unitInput = selection$$1.selectAll('input.maxspeed-unit') + .data([0]); - dispatch$$1.call('change', this, t$$1); - } + unitInput = unitInput.enter() + .append('input') + .attr('type', 'text') + .attr('class', 'maxspeed-unit') + .call(unitCombobox) + .merge(unitInput); + unitInput + .on('blur', changeUnits) + .on('change', changeUnits); - radio.tags = function(tags) { - function checked(d) { - if (field.key) { - return tags[field.key] === d; - } else { - return !!(tags[d] && tags[d].toLowerCase() !== 'no'); - } - } - labels.classed('active', checked); - radios.property('checked', checked); + function changeUnits() { + isImperial = utilGetSetValue(unitInput) === 'mph'; + utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h'); + setSuggestions(); + change(); + } + } - var selection$$1 = radios.filter(function() { return this.checked; }); - if (selection$$1.empty()) { - placeholder.text(t('inspector.none')); - } else { - placeholder.text(selection$$1.attr('value')); - oldType[selection$$1.datum()] = tags[selection$$1.datum()]; - } + function setSuggestions() { + combobox.data((isImperial ? imperialValues : metricValues).map(comboValues)); + utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h'); + } - if (field.type === 'structureRadio') { - // For waterways without a tunnel tag, set 'culvert' as - // the oldType to default to if the user picks 'tunnel' - if (!!tags.waterway && !oldType.tunnel) { - oldType.tunnel = 'culvert'; - } - wrap.call(structureExtras, tags); - } - }; + function comboValues(d) { + return { + value: d.toString(), + title: d.toString() + }; + } - radio.focus = function() { - radios.node().focus(); - }; + function change() { + var tag = {}, + value = utilGetSetValue(input); + if (!value) { + tag[field.key] = undefined; + } else if (isNaN(value) || !isImperial) { + tag[field.key] = value; + } else { + tag[field.key] = value + ' mph'; + } - radio.entity = function(_) { - if (!arguments.length) return entity; - entity = _; - oldType = {}; - return radio; - }; + dispatch$$1.call('change', this, tag); + } - return utilRebind(radio, dispatch$$1, 'on'); -} + maxspeed.tags = function(tags) { + var value = tags[field.key]; -function uiFieldRestrictions(field, context) { - var dispatch$$1 = dispatch('change'); - var breathe = behaviorBreathe(context); - var storedViaWay = context.storage('turn-restriction-via-way'); - var storedDistance = context.storage('turn-restriction-distance'); + if (value && value.indexOf('mph') >= 0) { + value = parseInt(value, 10); + isImperial = true; + } else if (value) { + isImperial = false; + } - var _maxViaWay = storedViaWay !== null ? (+storedViaWay) : 1; - var _maxDistance = storedDistance ? (+storedDistance) : 30; - var _initialized = false; - var _parent = d3_select(null); // the entire field - var _container = d3_select(null); // just the map - var _oldTurns; - var _graph; - var _vertexID; - var _intersection; - var _fromWayID; + setSuggestions(); + utilGetSetValue(input, value || ''); + }; - function restrictions(selection$$1) { - _parent = selection$$1; + maxspeed.focus = function() { + input.node().focus(); + }; - // try to reuse the intersection, but always rebuild it if the graph has changed - if (_vertexID && (context.graph() !== _graph || !_intersection)) { - _graph = context.graph(); - _intersection = osmIntersection(_graph, _vertexID, _maxDistance); - } - // It's possible for there to be no actual intersection here. - // for example, a vertex of two `highway=path` - // In this case, hide the field. - var isOK = (_intersection && _intersection.vertices.length && _intersection.ways.length); - d3_select(selection$$1.node().parentNode).classed('hide', !isOK); - - // if form field is hidden or has detached from dom, clean up. - if (!isOK || - !d3_select('.inspector-wrap.inspector-hidden').empty() || - !selection$$1.node().parentNode || - !selection$$1.node().parentNode.parentNode) { - selection$$1.call(restrictions.off); - return; - } + maxspeed.entity = function(_) { + entity = _; + }; - var wrap = selection$$1.selectAll('.preset-input-wrap') - .data([0]); - - wrap = wrap.enter() - .append('div') - .attr('class', 'preset-input-wrap') - .merge(wrap); - - var container = wrap.selectAll('.restriction-container') - .data([0]); - - // enter - var containerEnter = container.enter() - .append('div') - .attr('class', 'restriction-container'); - - containerEnter - .append('div') - .attr('class', 'restriction-help'); - - // update - _container = containerEnter - .merge(container) - .call(renderViewer); - - var controls = wrap.selectAll('.restriction-controls') - .data([0]); - - // enter/update - controls.enter() - .append('div') - .attr('class', 'restriction-controls-container') - .append('div') - .attr('class', 'restriction-controls') - .merge(controls) - .call(renderControls); - } - - - function renderControls(selection$$1) { - var distControl = selection$$1.selectAll('.restriction-distance') - .data([0]); - - distControl.exit() - .remove(); - - var distControlEnter = distControl.enter() - .append('div') - .attr('class', 'restriction-control restriction-distance'); - - distControlEnter - .append('span') - .attr('class', 'restriction-control-label restriction-distance-label') - .text(t('restriction.controls.distance') + ':'); - - distControlEnter - .append('input') - .attr('class', 'restriction-distance-input') - .attr('type', 'range') - .attr('min', '20') - .attr('max', '50') - .attr('step', '5'); - - distControlEnter - .append('span') - .attr('class', 'restriction-distance-text'); - - // update - selection$$1.selectAll('.restriction-distance-input') - .property('value', _maxDistance) - .on('input', function() { - var val = d3_select(this).property('value'); - _maxDistance = +val; - _intersection = null; - _container.selectAll('.layer-osm .layer-turns *').remove(); - context.storage('turn-restriction-distance', _maxDistance); - _parent.call(restrictions); - }); + return utilRebind(maxspeed, dispatch$$1, 'on'); + } - selection$$1.selectAll('.restriction-distance-text') - .text(displayMaxDistance(_maxDistance)); - - - var viaControl = selection$$1.selectAll('.restriction-via-way') - .data([0]); - - viaControl.exit() - .remove(); - - var viaControlEnter = viaControl.enter() - .append('div') - .attr('class', 'restriction-control restriction-via-way'); - - viaControlEnter - .append('span') - .attr('class', 'restriction-control-label restriction-via-way-label') - .text(t('restriction.controls.via') + ':'); - - viaControlEnter - .append('input') - .attr('class', 'restriction-via-way-input') - .attr('type', 'range') - .attr('min', '0') - .attr('max', '2') - .attr('step', '1'); - - viaControlEnter - .append('span') - .attr('class', 'restriction-via-way-text'); - - // update - selection$$1.selectAll('.restriction-via-way-input') - .property('value', _maxViaWay) - .on('input', function() { - var val = d3_select(this).property('value'); - _maxViaWay = +val; - _container.selectAll('.layer-osm .layer-turns *').remove(); - context.storage('turn-restriction-via-way', _maxViaWay); - _parent.call(restrictions); - }); + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; - selection$$1.selectAll('.restriction-via-way-text') - .text(displayMaxVia(_maxViaWay)); + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } } + return -1; + } + /** Used for built-in method references. */ + var arrayProto$2 = Array.prototype; - function renderViewer(selection$$1) { - if (!_intersection) return; - - var vgraph = _intersection.graph; - var filter = utilFunctor(true); - var projection = geoRawMercator(); + /** Built-in value references. */ + var splice$2 = arrayProto$2.splice; - var d = utilGetDimensions(selection$$1); - var c = geoVecScale(d, 0.5); - var z = 22; + /** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; - projection.scale(geoZoomToScale(z)); + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; - // Calculate extent of all key vertices - var extent = geoExtent$$1(); - for (var i = 0; i < _intersection.vertices.length; i++) { - extent._extend(_intersection.vertices[i].extent()); + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice$2.call(seen, fromIndex, 1); } + splice$2.call(array, fromIndex, 1); + } + } + return array; + } - // If this is a large intersection, adjust zoom to fit extent - if (_intersection.vertices.length > 1) { - var padding = 180; // in z22 pixels - var tl = projection([extent[0][0], extent[1][1]]); - var br = projection([extent[1][0], extent[0][1]]); - var hFactor = (br[0] - tl[0]) / (d[0] - padding); - var vFactor = (br[1] - tl[1]) / (d[1] - padding); - var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2; - var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2; - z = z - Math.max(hZoomDiff, vZoomDiff); - projection.scale(geoZoomToScale(z)); - } + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ + function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; + } - var padTop = 35; // reserve top space for hint text - var extentCenter = projection(extent.center()); - extentCenter[1] = extentCenter[1] - padTop; + /** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ + var pull = baseRest(pullAll); + + function uiFieldRadio(field, context) { + var dispatch$$1 = dispatch('change'), + placeholder = select(null), + wrap = select(null), + labels = select(null), + radios = select(null), + radioData = clone(field.options || field.keys), + typeField, + layerField, + oldType = {}, + entity; + + + function selectedKey() { + var node = wrap.selectAll('.toggle-list label.active input'); + return !node.empty() && node.datum(); + } - projection - .translate(geoVecSubtract(c, extentCenter)) - .clipExtent([[0, 0], d]); - var drawLayers = svgLayers(projection, context).only('osm').dimensions(d); - var drawVertices = svgVertices$$1(projection, context); - var drawLines = svgLines$$1(projection, context); - var drawTurns = svgTurns(projection, context); + function radio(selection$$1) { + selection$$1.classed('preset-radio', true); - var firstTime = selection$$1.selectAll('.surface').empty(); + wrap = selection$$1.selectAll('.preset-input-wrap') + .data([0]); - selection$$1 - .call(drawLayers); + var enter = wrap.enter() + .append('div') + .attr('class', 'preset-input-wrap toggle-list'); - var surface = selection$$1.selectAll('.surface') - .classed('tr', true); + enter + .append('span') + .attr('class', 'placeholder'); - if (firstTime) { - _initialized = true; + wrap = wrap + .merge(enter); - surface - .call(breathe); - d3_select(window) - .on('resize.restrictions', function() { - utilSetDimensions(_container, null); - redraw(); - }); - } + placeholder = wrap.selectAll('.placeholder'); + labels = wrap.selectAll('label') + .data(radioData); - // This can happen if we've lowered the detail while a FROM way - // is selected, and that way is no longer part of the intersection. - if (_fromWayID && !vgraph.hasEntity(_fromWayID)) { - _fromWayID = null; - _oldTurns = null; - } + enter = labels.enter() + .append('label'); - surface - .call(utilSetDimensions, d) - .call(drawVertices, vgraph, _intersection.vertices, filter, extent, z) - .call(drawLines, vgraph, _intersection.ways, filter) - .call(drawTurns, vgraph, _intersection.turns(_fromWayID, _maxViaWay)); - - surface - .on('click.restrictions', click) - .on('mouseover.restrictions', mouseover); - - surface - .selectAll('.selected') - .classed('selected', false); - - surface - .selectAll('.related') - .classed('related', false); - - if (_fromWayID) { - var way = vgraph.entity(_fromWayID); - surface - .selectAll('.' + _fromWayID) - .classed('selected', true) - .classed('related', true); - } + enter + .append('input') + .attr('type', 'radio') + .attr('name', field.id) + .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); }) + .attr('checked', false); - updateHints(null); + enter + .append('span') + .text(function(d) { return field.t('options.' + d, { 'default': d }); }); + labels = labels + .merge(enter); - function click() { - surface - .call(breathe.off) - .call(breathe); + radios = labels.selectAll('input') + .on('change', changeRadio); - var datum = event.target.__data__; - var entity = datum && datum.properties && datum.properties.entity; - if (entity) { - datum = entity; - } + } - if (datum instanceof osmWay && (datum.__from || datum.__via)) { - _fromWayID = datum.id; - _oldTurns = null; - redraw(); - - } else if (datum instanceof osmTurn) { - var actions, extraActions, turns, i; - var restrictionType = osmInferRestriction(vgraph, datum, projection); - - if (datum.restrictionID && !datum.direct) { - return; - - } else if (datum.restrictionID && !datum.only) { // NO -> ONLY - var datumOnly = cloneDeep(datum); - datumOnly.only = true; - restrictionType = restrictionType.replace(/^no/, 'only'); - - // Adding an ONLY restriction should destroy all other direct restrictions from the FROM. - // We will remember them in _oldTurns, and restore them if the user clicks again. - turns = _intersection.turns(_fromWayID, 2); - extraActions = []; - _oldTurns = []; - for (i = 0; i < turns.length; i++) { - if (turns[i].direct) { - turns[i].restrictionType = osmInferRestriction(vgraph, turns[i], projection); - _oldTurns.push(turns[i]); - extraActions.push(actionUnrestrictTurn(turns[i])); - } - } - - actions = _intersection.actions.concat(extraActions, [ - actionRestrictTurn(datumOnly, restrictionType), - t('operations.restriction.annotation.create') - ]); - - } else if (datum.restrictionID) { // ONLY -> Allowed - // Restore whatever restrictions we might have destroyed by cycling thru the ONLY state. - // This relies on the assumption that the intersection was already split up when we - // performed the previous action (NO -> ONLY), so the IDs in _oldTurns shouldn't have changed. - turns = _oldTurns || []; - extraActions = []; - for (i = 0; i < turns.length; i++) { - if (turns[i].key !== datum.key) { - extraActions.push(actionRestrictTurn(turns[i], turns[i].restrictionType)); - } - } - _oldTurns = null; - - actions = _intersection.actions.concat(extraActions, [ - actionUnrestrictTurn(datum), - t('operations.restriction.annotation.delete') - ]); - - } else { // Allowed -> NO - actions = _intersection.actions.concat([ - actionRestrictTurn(datum, restrictionType), - t('operations.restriction.annotation.create') - ]); - } - - context.perform.apply(context, actions); - - // At this point the datum will be changed, but will have same key.. - // Refresh it and update the help.. - var s = surface.selectAll('.' + datum.key); - datum = s.empty() ? null : s.datum(); - updateHints(datum); - } else { - _fromWayID = null; - _oldTurns = null; - redraw(); - } - } + function structureExtras(selection$$1, tags) { + var selected = selectedKey(), + type = context.presets().field(selected), + layer = context.presets().field('layer'), + showLayer = (selected === 'bridge' || selected === 'tunnel'); - function mouseover() { - var datum = event.target.__data__; - updateHints(datum); - } + var extrasWrap = selection$$1.selectAll('.structure-extras-wrap') + .data(selected ? [0] : []); + extrasWrap.exit() + .remove(); - function redraw() { - if (context.hasEntity(_vertexID)) { - _container.call(renderViewer); - } - } + extrasWrap = extrasWrap.enter() + .append('div') + .attr('class', 'structure-extras-wrap') + .merge(extrasWrap); + var list = extrasWrap.selectAll('ul') + .data([0]); - function highlightPathsFrom(wayID) { - surface.selectAll('.related') - .classed('related', false) - .classed('allow', false) - .classed('restrict', false) - .classed('only', false); - - surface.selectAll('.' + wayID) - .classed('related', true); - - if (wayID) { - var turns = _intersection.turns(wayID, _maxViaWay); - for (var i = 0; i < turns.length; i++) { - var turn = turns[i]; - var ids = [turn.to.way]; - var klass = (turn.no ? 'restrict' : (turn.only ? 'only' : 'allow')); - - if (turn.only || turns.length === 1) { - if (turn.via.ways) { - ids = ids.concat(turn.via.ways); - } - } else if (turn.to.way === wayID) { - continue; - } - - surface.selectAll(utilEntitySelector(ids)) - .classed('related', true) - .classed('allow', (klass === 'allow')) - .classed('restrict', (klass === 'restrict')) - .classed('only', (klass === 'only')); - } - } - } + list = list.enter() + .append('ul') + .merge(list); - function updateHints(datum) { - var help = _container.selectAll('.restriction-help').html(''); + // Type + if (type) { + if (!typeField || typeField.id !== selected) { + typeField = uiField(context, type, entity, { wrap: false }) + .on('change', changeType); + } + typeField.tags(tags); + } else { + typeField = null; + } - var placeholders = {}; - ['from', 'via', 'to'].forEach(function(k) { - placeholders[k] = '' + t('restriction.help.' + k) + ''; - }); + var typeItem = list.selectAll('.structure-type-item') + .data(typeField ? [typeField] : [], function(d) { return d.id; }); - var entity = datum && datum.properties && datum.properties.entity; - if (entity) { - datum = entity; - } + // Exit + typeItem.exit() + .remove(); - if (_fromWayID) { - way = vgraph.entity(_fromWayID); - surface - .selectAll('.' + _fromWayID) - .classed('selected', true) - .classed('related', true); - } + // Enter + var typeEnter = typeItem.enter() + .insert('li', ':first-child') + .attr('class', 'cf structure-type-item'); - // Hovering a way - if (datum instanceof osmWay && datum.__from) { - way = datum; - - highlightPathsFrom(_fromWayID ? null : way.id); - surface.selectAll('.' + way.id) - .classed('related', true); - - var clickSelect = (!_fromWayID || _fromWayID !== way.id); - help - .append('div') // "Click to select FROM {fromName}." / "FROM {fromName}" - .html(t('restriction.help.' + (clickSelect ? 'select_from_name' : 'from_name'), { - from: placeholders.from, - fromName: displayName(way.id, vgraph) - })); - - - // Hovering a turn arrow - } else if (datum instanceof osmTurn) { - var restrictionType = osmInferRestriction(vgraph, datum, projection); - var turnType = restrictionType.replace(/^(only|no)\_/, ''); - var indirect = (datum.direct === false ? t('restriction.help.indirect') : ''); - var klass, turnText, nextText; - - if (datum.no) { - klass = 'restrict'; - turnText = t('restriction.help.turn.no_' + turnType, { indirect: indirect }); - nextText = t('restriction.help.turn.only_' + turnType, { indirect: '' }); - } else if (datum.only) { - klass = 'only'; - turnText = t('restriction.help.turn.only_' + turnType, { indirect: indirect }); - nextText = t('restriction.help.turn.allowed_' + turnType, { indirect: '' }); - } else { - klass = 'allow'; - turnText = t('restriction.help.turn.allowed_' + turnType, { indirect: indirect }); - nextText = t('restriction.help.turn.no_' + turnType, { indirect: '' }); - } - - help - .append('div') // "NO Right Turn (indirect)" - .attr('class', 'qualifier ' + klass) - .text(turnText); - - help - .append('div') // "FROM {fromName} TO {toName}" - .html(t('restriction.help.from_name_to_name', { - from: placeholders.from, - fromName: displayName(datum.from.way, vgraph), - to: placeholders.to, - toName: displayName(datum.to.way, vgraph) - })); - - if (datum.via.ways && datum.via.ways.length) { - var names = []; - for (var i = 0; i < datum.via.ways.length; i++) { - var prev = names[names.length - 1]; - var curr = displayName(datum.via.ways[i], vgraph); - if (!prev || curr !== prev) // collapse identical names - names.push(curr); - } - - help - .append('div') // "VIA {viaNames}" - .html(t('restriction.help.via_names', { - via: placeholders.via, - viaNames: names.join(', ') - })); - } - - if (!indirect) { - help - .append('div') // Click for "No Right Turn" - .text(t('restriction.help.toggle', { turn: nextText.trim() })); - } - - highlightPathsFrom(null); - var alongIDs = datum.path.slice(); - surface.selectAll(utilEntitySelector(alongIDs)) - .classed('related', true) - .classed('allow', (klass === 'allow')) - .classed('restrict', (klass === 'restrict')) - .classed('only', (klass === 'only')); - - - // Hovering empty surface - } else { - highlightPathsFrom(null); - if (_fromWayID) { - help - .append('div') // "FROM {fromName}" - .html(t('restriction.help.from_name', { - from: placeholders.from, - fromName: displayName(_fromWayID, vgraph) - })); - - } else { - help - .append('div') // "Click to select a FROM segment." - .html(t('restriction.help.select_from', { - from: placeholders.from - })); - } - } - } - } + typeEnter + .append('span') + .attr('class', 'col6 label structure-label-type') + .attr('for', 'preset-input-' + selected) + .text(t('inspector.radio.structure.type')); + typeEnter + .append('div') + .attr('class', 'col6 structure-input-type-wrap'); - function displayMaxDistance(maxDist) { - var isImperial = (utilDetect().locale.toLowerCase() === 'en-us'); - var opts; + // Update + typeItem = typeItem + .merge(typeEnter); - if (isImperial) { - var distToFeet = { // imprecise conversion for prettier display - 20: 70, 25: 85, 30: 100, 35: 115, 40: 130, 45: 145, 50: 160 - }[maxDist]; - opts = { distance: t('units.feet', { quantity: distToFeet }) }; - } else { - opts = { distance: t('units.meters', { quantity: maxDist }) }; - } + if (typeField) { + typeItem.selectAll('.structure-input-type-wrap') + .call(typeField.render); + } - return t('restriction.controls.distance_up_to', opts); - } + // Layer + if (layer && showLayer) { + if (!layerField) { + layerField = uiField(context, layer, entity, { wrap: false }) + .on('change', changeLayer); + } + layerField.tags(tags); + field.keys = union(field.keys, ['layer']); + } else { + layerField = null; + pull(field.keys, 'layer'); + } - function displayMaxVia(maxVia) { - return maxVia === 0 ? t('restriction.controls.via_node_only') - : maxVia === 1 ? t('restriction.controls.via_up_to_one') - : t('restriction.controls.via_up_to_two'); - } + var layerItem = list.selectAll('.structure-layer-item') + .data(layerField ? [layerField] : []); + // Exit + layerItem.exit() + .remove(); - function displayName(entityID, graph) { - var entity = graph.entity(entityID); - var name = utilDisplayName(entity) || ''; - var matched = context.presets().match(entity, graph); - var type = (matched && matched.name()) || utilDisplayType(entity.id); - return name || type; - } + // Enter + var layerEnter = layerItem.enter() + .append('li') + .attr('class', 'cf structure-layer-item'); + layerEnter + .append('span') + .attr('class', 'col6 label structure-label-layer') + .attr('for', 'preset-input-layer') + .text(t('inspector.radio.structure.layer')); - restrictions.entity = function(_) { - _intersection = null; - _fromWayID = null; - _oldTurns = null; - _vertexID = _.id; - }; + layerEnter + .append('div') + .attr('class', 'col6 structure-input-layer-wrap'); + // Update + layerItem = layerItem + .merge(layerEnter); - restrictions.tags = function() {}; - restrictions.focus = function() {}; + if (layerField) { + layerItem.selectAll('.structure-input-layer-wrap') + .call(layerField.render); + } + } - restrictions.off = function(selection$$1) { - if (!_initialized) return; + function changeType(t$$1, onInput) { + var key = selectedKey(); + if (!key) return; - selection$$1.selectAll('.surface') - .call(breathe.off) - .on('click.restrictions', null) - .on('mouseover.restrictions', null); + var val = t$$1[key]; + if (val !== 'no') { + oldType[key] = val; + } - d3_select(window) - .on('resize.restrictions', null); - }; + if (field.type === 'structureRadio') { + // remove layer if it should not be set + if (val === 'no' || + (key !== 'bridge' && key !== 'tunnel') || + (key === 'tunnel' && val === 'building_passage')) { + t$$1.layer = undefined; + } + // add layer if it should be set + if (t$$1.layer === undefined) { + if (key === 'bridge' && val !== 'no') { + t$$1.layer = '1'; + } + if (key === 'tunnel' && val !== 'no' && val !== 'building_passage') { + t$$1.layer = '-1'; + } + } + } + dispatch$$1.call('change', this, t$$1, onInput); + } - return utilRebind(restrictions, dispatch$$1, 'on'); -} -function uiFieldTextarea(field) { - var dispatch$$1 = dispatch('change'), - input = d3_select(null); + function changeLayer(t$$1, onInput) { + if (t$$1.layer === '0') { + t$$1.layer = undefined; + } + dispatch$$1.call('change', this, t$$1, onInput); + } - function textarea(selection$$1) { - input = selection$$1.selectAll('textarea') - .data([0]); + function changeRadio() { + var t$$1 = {}, + activeKey; - input = input.enter() - .append('textarea') - .attr('id', 'preset-input-' + field.id) - .attr('placeholder', field.placeholder() || t('inspector.unknown')) - .attr('maxlength', 255) - .call(utilNoAuto) - .on('input', change(true)) - .on('blur', change()) - .on('change', change()) - .merge(input); - } + if (field.key) { + t$$1[field.key] = undefined; + } + radios.each(function(d) { + var active = select(this).property('checked'); + if (active) activeKey = d; - function change(onInput) { - return function() { - var t$$1 = {}; - t$$1[field.key] = utilGetSetValue(input) || undefined; - dispatch$$1.call('change', this, t$$1, onInput); - }; - } + if (field.key) { + if (active) t$$1[field.key] = d; + } else { + var val = oldType[activeKey] || 'yes'; + t$$1[d] = active ? val : undefined; + } + }); + if (field.type === 'structureRadio') { + if (activeKey === 'bridge') { + t$$1.layer = '1'; + } else if (activeKey === 'tunnel' && t$$1.tunnel !== 'building_passage') { + t$$1.layer = '-1'; + } else { + t$$1.layer = undefined; + } + } - textarea.tags = function(tags) { - utilGetSetValue(input, tags[field.key] || ''); - }; + dispatch$$1.call('change', this, t$$1); + } - textarea.focus = function() { - input.node().focus(); - }; + radio.tags = function(tags) { + function checked(d) { + if (field.key) { + return tags[field.key] === d; + } else { + return !!(tags[d] && tags[d].toLowerCase() !== 'no'); + } + } + labels.classed('active', checked); + radios.property('checked', checked); - return utilRebind(textarea, dispatch$$1, 'on'); -} - -function uiFieldWikipedia(field, context) { - var dispatch$$1 = dispatch('change'), - wikipedia = services.wikipedia, - wikidata = services.wikidata, - link = d3_select(null), - lang = d3_select(null), - title = d3_select(null), - wikiURL = '', - entity; - - - function wiki(selection$$1) { - var langcombo = d3combobox() - .container(context.container()) - .fetcher(function(value, cb) { - var v = value.toLowerCase(); - - cb(wikipedia$2.filter(function(d) { - return d[0].toLowerCase().indexOf(v) >= 0 || - d[1].toLowerCase().indexOf(v) >= 0 || - d[2].toLowerCase().indexOf(v) >= 0; - }).map(function(d) { - return { value: d[1] }; - })); - }); + var selection$$1 = radios.filter(function() { return this.checked; }); - var titlecombo = d3combobox() - .container(context.container()) - .fetcher(function(value, cb) { - if (!value) { - value = context.entity(entity.id).tags.name || ''; - } - - var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions; - searchfn(language()[2], value, function(query, data$$1) { - cb(data$$1.map(function(d) { - return { value: d }; - })); - }); - }); + if (selection$$1.empty()) { + placeholder.text(t('inspector.none')); + } else { + placeholder.text(selection$$1.attr('value')); + oldType[selection$$1.datum()] = tags[selection$$1.datum()]; + } + if (field.type === 'structureRadio') { + // For waterways without a tunnel tag, set 'culvert' as + // the oldType to default to if the user picks 'tunnel' + if (!!tags.waterway && !oldType.tunnel) { + oldType.tunnel = 'culvert'; + } - lang = selection$$1.selectAll('input.wiki-lang') - .data([0]); + wrap.call(structureExtras, tags); + } + }; - lang = lang.enter() - .append('input') - .attr('type', 'text') - .attr('class', 'wiki-lang') - .attr('placeholder', t('translate.localized_translation_language')) - .call(utilNoAuto) - .merge(lang); - utilGetSetValue(lang, language()[1]); + radio.focus = function() { + radios.node().focus(); + }; - lang - .call(langcombo) - .on('blur', changeLang) - .on('change', changeLang); + radio.entity = function(_) { + if (!arguments.length) return entity; + entity = _; + oldType = {}; + return radio; + }; - title = selection$$1.selectAll('input.wiki-title') - .data([0]); - title = title.enter() - .append('input') - .attr('type', 'text') - .attr('class', 'wiki-title') - .attr('id', 'preset-input-' + field.id) - .call(utilNoAuto) - .merge(title); + return utilRebind(radio, dispatch$$1, 'on'); + } - title - .call(titlecombo) - .on('blur', blur) - .on('change', change); + function uiFieldRestrictions(field, context) { + var dispatch$$1 = dispatch('change'); + var breathe = behaviorBreathe(context); + var storedViaWay = context.storage('turn-restriction-via-way'); + var storedDistance = context.storage('turn-restriction-distance'); + + var _maxViaWay = storedViaWay !== null ? (+storedViaWay) : 1; + var _maxDistance = storedDistance ? (+storedDistance) : 30; + var _initialized = false; + var _parent = select(null); // the entire field + var _container = select(null); // just the map + var _oldTurns; + var _graph; + var _vertexID; + var _intersection; + var _fromWayID; + + + function restrictions(selection$$1) { + _parent = selection$$1; + + // try to reuse the intersection, but always rebuild it if the graph has changed + if (_vertexID && (context.graph() !== _graph || !_intersection)) { + _graph = context.graph(); + _intersection = osmIntersection(_graph, _vertexID, _maxDistance); + } + // It's possible for there to be no actual intersection here. + // for example, a vertex of two `highway=path` + // In this case, hide the field. + var isOK = ( + _intersection && + _intersection.vertices.length && // has vertices + _intersection.vertices // has the vertex that the user selected + .filter(function(vertex) { return vertex.id === _vertexID; }).length && + _intersection.ways.length > 2 && // has more than 2 ways + _intersection.ways // has more than 1 TO way + .filter(function(way) { return way.__to; }).length > 1 + ); - link = selection$$1.selectAll('.wiki-link') - .data([0]); + // Also hide in the case where + select(selection$$1.node().parentNode).classed('hide', !isOK); - link = link.enter() - .append('button') - .attr('class', 'button-input-action wiki-link minor') - .attr('tabindex', -1) - .call(svgIcon('#icon-out-link')) - .merge(link); + // if form field is hidden or has detached from dom, clean up. + if (!isOK || + !select('.inspector-wrap.inspector-hidden').empty() || + !selection$$1.node().parentNode || + !selection$$1.node().parentNode.parentNode) { + selection$$1.call(restrictions.off); + return; + } - link - .on('click', function() { - event.preventDefault(); - if (wikiURL) window.open(wikiURL, '_blank'); - }); - } + var wrap = selection$$1.selectAll('.preset-input-wrap') + .data([0]); - function language() { - var value = utilGetSetValue(lang).toLowerCase(); - var locale = utilDetect().locale.toLowerCase(); - var localeLanguage; - return find$1(wikipedia$2, function(d) { - if (d[2] === locale) localeLanguage = d; - return d[0].toLowerCase() === value || - d[1].toLowerCase() === value || - d[2] === value; - }) || localeLanguage || ['English', 'English', 'en']; - } + wrap = wrap.enter() + .append('div') + .attr('class', 'preset-input-wrap') + .merge(wrap); + var container = wrap.selectAll('.restriction-container') + .data([0]); - function changeLang() { - utilGetSetValue(lang, language()[1]); - change(true); - } + // enter + var containerEnter = container.enter() + .append('div') + .attr('class', 'restriction-container'); + containerEnter + .append('div') + .attr('class', 'restriction-help'); - function blur() { - change(true); - } + // update + _container = containerEnter + .merge(container) + .call(renderViewer); + var controls = wrap.selectAll('.restriction-controls') + .data([0]); - function change(skipWikidata) { - var value = utilGetSetValue(title), - m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/), - l = m && find$1(wikipedia$2, function(d) { return m[1] === d[2]; }), - syncTags = {}; + // enter/update + controls.enter() + .append('div') + .attr('class', 'restriction-controls-container') + .append('div') + .attr('class', 'restriction-controls') + .merge(controls) + .call(renderControls); + } - if (l) { - // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization - value = decodeURIComponent(m[2]).replace(/_/g, ' '); - if (m[3]) { - var anchor; - try { - // Best-effort `anchordecode:` implementation - anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1')); - } catch (e) { - anchor = decodeURIComponent(m[3]); - } - value += '#' + anchor.replace(/_/g, ' '); - } - value = value.slice(0, 1).toUpperCase() + value.slice(1); - utilGetSetValue(lang, l[1]); - utilGetSetValue(title, value); - } - if (value) { - syncTags.wikipedia = language()[2] + ':' + value; - } else { - syncTags.wikipedia = undefined; - syncTags.wikidata = undefined; - } + function renderControls(selection$$1) { + var distControl = selection$$1.selectAll('.restriction-distance') + .data([0]); + + distControl.exit() + .remove(); + + var distControlEnter = distControl.enter() + .append('div') + .attr('class', 'restriction-control restriction-distance'); + + distControlEnter + .append('span') + .attr('class', 'restriction-control-label restriction-distance-label') + .text(t('restriction.controls.distance') + ':'); + + distControlEnter + .append('input') + .attr('class', 'restriction-distance-input') + .attr('type', 'range') + .attr('min', '20') + .attr('max', '50') + .attr('step', '5'); + + distControlEnter + .append('span') + .attr('class', 'restriction-distance-text'); + + // update + selection$$1.selectAll('.restriction-distance-input') + .property('value', _maxDistance) + .on('input', function() { + var val = select(this).property('value'); + _maxDistance = +val; + _intersection = null; + _container.selectAll('.layer-osm .layer-turns *').remove(); + context.storage('turn-restriction-distance', _maxDistance); + _parent.call(restrictions); + }); + + selection$$1.selectAll('.restriction-distance-text') + .text(displayMaxDistance(_maxDistance)); + + + var viaControl = selection$$1.selectAll('.restriction-via-way') + .data([0]); + + viaControl.exit() + .remove(); + + var viaControlEnter = viaControl.enter() + .append('div') + .attr('class', 'restriction-control restriction-via-way'); + + viaControlEnter + .append('span') + .attr('class', 'restriction-control-label restriction-via-way-label') + .text(t('restriction.controls.via') + ':'); + + viaControlEnter + .append('input') + .attr('class', 'restriction-via-way-input') + .attr('type', 'range') + .attr('min', '0') + .attr('max', '2') + .attr('step', '1'); + + viaControlEnter + .append('span') + .attr('class', 'restriction-via-way-text'); + + // update + selection$$1.selectAll('.restriction-via-way-input') + .property('value', _maxViaWay) + .on('input', function() { + var val = select(this).property('value'); + _maxViaWay = +val; + _container.selectAll('.layer-osm .layer-turns *').remove(); + context.storage('turn-restriction-via-way', _maxViaWay); + _parent.call(restrictions); + }); + + selection$$1.selectAll('.restriction-via-way-text') + .text(displayMaxVia(_maxViaWay)); + } - dispatch$$1.call('change', this, syncTags); + function renderViewer(selection$$1) { + if (!_intersection) return; - if (skipWikidata || !value || !language()[2]) return; + var vgraph = _intersection.graph; + var filter = utilFunctor(true); + var projection = geoRawMercator(); - // attempt asynchronous update of wikidata tag.. - var initGraph = context.graph(), - initEntityId = entity.id; + var d = utilGetDimensions(selection$$1); + var c = geoVecScale(d, 0.5); + var z = 22; - wikidata.itemsByTitle(language()[2], value, function(title, data$$1) { - // If graph has changed, we can't apply this update. - if (context.graph() !== initGraph) return; + projection.scale(geoZoomToScale(z)); - if (!data$$1 || !Object.keys(data$$1).length) return; + // Calculate extent of all key vertices + var extent = geoExtent$$1(); + for (var i = 0; i < _intersection.vertices.length; i++) { + extent._extend(_intersection.vertices[i].extent()); + } - var qids = Object.keys(data$$1); - var value = qids && find$1(qids, function(id) { return id.match(/^Q\d+$/); }); - var currTags = clone(context.entity(initEntityId).tags); + // If this is a large intersection, adjust zoom to fit extent + if (_intersection.vertices.length > 1) { + var padding = 180; // in z22 pixels + var tl = projection([extent[0][0], extent[1][1]]); + var br = projection([extent[1][0], extent[0][1]]); + var hFactor = (br[0] - tl[0]) / (d[0] - padding); + var vFactor = (br[1] - tl[1]) / (d[1] - padding); + var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2; + var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2; + z = z - Math.max(hZoomDiff, vZoomDiff); + projection.scale(geoZoomToScale(z)); + } - currTags.wikidata = value; + var padTop = 35; // reserve top space for hint text + var extentCenter = projection(extent.center()); + extentCenter[1] = extentCenter[1] - padTop; - // Coalesce the update of wikidata tag into the previous tag change - context.overwrite( - actionChangeTags(initEntityId, currTags), - context.history().undoAnnotation() - ); + projection + .translate(geoVecSubtract(c, extentCenter)) + .clipExtent([[0, 0], d]); - // do not dispatch.call('change') here, because entity_editor - // changeTags() is not intended to be called asynchronously - }); - } + var drawLayers = svgLayers(projection, context).only('osm').dimensions(d); + var drawVertices = svgVertices$$1(projection, context); + var drawLines = svgLines$$1(projection, context); + var drawTurns = svgTurns(projection, context); + var firstTime = selection$$1.selectAll('.surface').empty(); - wiki.tags = function(tags) { - var value = tags[field.key] || '', - m = value.match(/([^:]+):([^#]+)(?:#(.+))?/), - l = m && find$1(wikipedia$2, function(d) { return m[1] === d[2]; }), - anchor = m && m[3]; - - // value in correct format - if (l) { - utilGetSetValue(lang, l[1]); - utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : '')); - if (anchor) { - try { - // Best-effort `anchorencode:` implementation - anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.'); - } catch (e) { - anchor = anchor.replace(/ /g, '_'); - } - } - wikiURL = 'https://' + m[1] + '.wikipedia.org/wiki/' + - m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''); + selection$$1 + .call(drawLayers); - // unrecognized value format - } else { - utilGetSetValue(title, value); - if (value && value !== '') { - utilGetSetValue(lang, ''); - wikiURL = 'https://en.wikipedia.org/wiki/Special:Search?search=' + value; - } else { - wikiURL = ''; - } - } - }; + var surface = selection$$1.selectAll('.surface') + .classed('tr', true); + if (firstTime) { + _initialized = true; - wiki.entity = function(_) { - if (!arguments.length) return entity; - entity = _; - return wiki; - }; + surface + .call(breathe); + select(window) + .on('resize.restrictions', function() { + utilSetDimensions(_container, null); + redraw(); + }); + } - wiki.focus = function() { - title.node().focus(); - }; + // This can happen if we've lowered the detail while a FROM way + // is selected, and that way is no longer part of the intersection. + if (_fromWayID && !vgraph.hasEntity(_fromWayID)) { + _fromWayID = null; + _oldTurns = null; + } - return utilRebind(wiki, dispatch$$1, 'on'); -} - -var uiFields = { - access: uiFieldAccess, - address: uiFieldAddress, - check: uiFieldCheck, - combo: uiFieldCombo, - cycleway: uiFieldCycleway, - defaultCheck: uiFieldCheck, - email: uiFieldText, - lanes: uiFieldLanes, - localized: uiFieldLocalized, - maxspeed: uiFieldMaxspeed, - multiCombo: uiFieldCombo, - networkCombo: uiFieldCombo, - number: uiFieldText, - onewayCheck: uiFieldCheck, - radio: uiFieldRadio, - restrictions: uiFieldRestrictions, - semiCombo: uiFieldCombo, - structureRadio: uiFieldRadio, - tel: uiFieldText, - text: uiFieldText, - textarea: uiFieldTextarea, - typeCombo: uiFieldCombo, - url: uiFieldText, - wikipedia: uiFieldWikipedia -}; - -function uiField(context, presetField, entity, options) { - options = assignIn({ - show: true, - wrap: true, - remove: true, - revert: true, - info: true - }, options); - - var dispatch$$1 = dispatch('change'); - var field = clone(presetField); - var _show = options.show; - var _state = ''; - var _tags = {}; - - - field.impl = uiFields[field.type](field, context) - .on('change', function(t$$1, onInput) { - dispatch$$1.call('change', field, t$$1, onInput); - }); + surface + .call(utilSetDimensions, d) + .call(drawVertices, vgraph, _intersection.vertices, filter, extent, z) + .call(drawLines, vgraph, _intersection.ways, filter) + .call(drawTurns, vgraph, _intersection.turns(_fromWayID, _maxViaWay)); + + surface + .on('click.restrictions', click) + .on('mouseover.restrictions', mouseover); + + surface + .selectAll('.selected') + .classed('selected', false); + + surface + .selectAll('.related') + .classed('related', false); + + if (_fromWayID) { + var way = vgraph.entity(_fromWayID); + surface + .selectAll('.' + _fromWayID) + .classed('selected', true) + .classed('related', true); + } - if (entity && field.impl.entity) { - field.impl.entity(entity); - } + updateHints(null); + + + function click() { + surface + .call(breathe.off) + .call(breathe); + + var datum = event.target.__data__; + var entity = datum && datum.properties && datum.properties.entity; + if (entity) { + datum = entity; + } + + if (datum instanceof osmWay && (datum.__from || datum.__via)) { + _fromWayID = datum.id; + _oldTurns = null; + redraw(); + + } else if (datum instanceof osmTurn) { + var actions, extraActions, turns, i; + var restrictionType = osmInferRestriction(vgraph, datum, projection); + + if (datum.restrictionID && !datum.direct) { + return; + + } else if (datum.restrictionID && !datum.only) { // NO -> ONLY + var seen = {}; + var datumOnly = cloneDeep(datum); + datumOnly.only = true; + restrictionType = restrictionType.replace(/^no/, 'only'); + + // Adding an ONLY restriction should destroy all other direct restrictions from the FROM towards the VIA. + // We will remember them in _oldTurns, and restore them if the user clicks again. + turns = _intersection.turns(_fromWayID, 2); + extraActions = []; + _oldTurns = []; + for (i = 0; i < turns.length; i++) { + var turn = turns[i]; + if (seen[turn.restrictionID]) continue; // avoid deleting the turn twice (#4968, #4928) + + if (turn.direct && turn.path[1] === datum.path[1]) { + seen[turns[i].restrictionID] = true; + turn.restrictionType = osmInferRestriction(vgraph, turn, projection); + _oldTurns.push(turn); + extraActions.push(actionUnrestrictTurn(turn)); + } + } + + actions = _intersection.actions.concat(extraActions, [ + actionRestrictTurn(datumOnly, restrictionType), + t('operations.restriction.annotation.create') + ]); + + } else if (datum.restrictionID) { // ONLY -> Allowed + // Restore whatever restrictions we might have destroyed by cycling thru the ONLY state. + // This relies on the assumption that the intersection was already split up when we + // performed the previous action (NO -> ONLY), so the IDs in _oldTurns shouldn't have changed. + turns = _oldTurns || []; + extraActions = []; + for (i = 0; i < turns.length; i++) { + if (turns[i].key !== datum.key) { + extraActions.push(actionRestrictTurn(turns[i], turns[i].restrictionType)); + } + } + _oldTurns = null; + + actions = _intersection.actions.concat(extraActions, [ + actionUnrestrictTurn(datum), + t('operations.restriction.annotation.delete') + ]); + + } else { // Allowed -> NO + actions = _intersection.actions.concat([ + actionRestrictTurn(datum, restrictionType), + t('operations.restriction.annotation.create') + ]); + } + + context.perform.apply(context, actions); + + // At this point the datum will be changed, but will have same key.. + // Refresh it and update the help.. + var s = surface.selectAll('.' + datum.key); + datum = s.empty() ? null : s.datum(); + updateHints(datum); + + } else { + _fromWayID = null; + _oldTurns = null; + redraw(); + } + } - field.keys = field.keys || [field.key]; + function mouseover() { + var datum = event.target.__data__; + updateHints(datum); + } - function isModified() { - if (!entity) return false; - var original = context.graph().base().entities[entity.id]; - return some(field.keys, function(key) { - return original ? _tags[key] !== original.tags[key] : _tags[key]; - }); - } + function redraw() { + if (context.hasEntity(_vertexID)) { + _container.call(renderViewer); + } + } - function isPresent() { - return some(field.keys, function(key) { - return _tags[key]; - }); - } + function highlightPathsFrom(wayID) { + surface.selectAll('.related') + .classed('related', false) + .classed('allow', false) + .classed('restrict', false) + .classed('only', false); + + surface.selectAll('.' + wayID) + .classed('related', true); + + if (wayID) { + var turns = _intersection.turns(wayID, _maxViaWay); + for (var i = 0; i < turns.length; i++) { + var turn = turns[i]; + var ids = [turn.to.way]; + var klass = (turn.no ? 'restrict' : (turn.only ? 'only' : 'allow')); + + if (turn.only || turns.length === 1) { + if (turn.via.ways) { + ids = ids.concat(turn.via.ways); + } + } else if (turn.to.way === wayID) { + continue; + } + + surface.selectAll(utilEntitySelector(ids)) + .classed('related', true) + .classed('allow', (klass === 'allow')) + .classed('restrict', (klass === 'restrict')) + .classed('only', (klass === 'only')); + } + } + } - function revert(d) { - event.stopPropagation(); - event.preventDefault(); - if (!entity) return false; - var original = context.graph().base().entities[entity.id]; - var t$$1 = {}; - d.keys.forEach(function(key) { - t$$1[key] = original ? original.tags[key] : undefined; - }); + function updateHints(datum) { + var help = _container.selectAll('.restriction-help').html(''); + + var placeholders = {}; + ['from', 'via', 'to'].forEach(function(k) { + placeholders[k] = '' + t('restriction.help.' + k) + ''; + }); + + var entity = datum && datum.properties && datum.properties.entity; + if (entity) { + datum = entity; + } + + if (_fromWayID) { + way = vgraph.entity(_fromWayID); + surface + .selectAll('.' + _fromWayID) + .classed('selected', true) + .classed('related', true); + } + + // Hovering a way + if (datum instanceof osmWay && datum.__from) { + way = datum; + + highlightPathsFrom(_fromWayID ? null : way.id); + surface.selectAll('.' + way.id) + .classed('related', true); + + var clickSelect = (!_fromWayID || _fromWayID !== way.id); + help + .append('div') // "Click to select FROM {fromName}." / "FROM {fromName}" + .html(t('restriction.help.' + (clickSelect ? 'select_from_name' : 'from_name'), { + from: placeholders.from, + fromName: displayName(way.id, vgraph) + })); + + + // Hovering a turn arrow + } else if (datum instanceof osmTurn) { + var restrictionType = osmInferRestriction(vgraph, datum, projection); + var turnType = restrictionType.replace(/^(only|no)\_/, ''); + var indirect = (datum.direct === false ? t('restriction.help.indirect') : ''); + var klass, turnText, nextText; + + if (datum.no) { + klass = 'restrict'; + turnText = t('restriction.help.turn.no_' + turnType, { indirect: indirect }); + nextText = t('restriction.help.turn.only_' + turnType, { indirect: '' }); + } else if (datum.only) { + klass = 'only'; + turnText = t('restriction.help.turn.only_' + turnType, { indirect: indirect }); + nextText = t('restriction.help.turn.allowed_' + turnType, { indirect: '' }); + } else { + klass = 'allow'; + turnText = t('restriction.help.turn.allowed_' + turnType, { indirect: indirect }); + nextText = t('restriction.help.turn.no_' + turnType, { indirect: '' }); + } + + help + .append('div') // "NO Right Turn (indirect)" + .attr('class', 'qualifier ' + klass) + .text(turnText); + + help + .append('div') // "FROM {fromName} TO {toName}" + .html(t('restriction.help.from_name_to_name', { + from: placeholders.from, + fromName: displayName(datum.from.way, vgraph), + to: placeholders.to, + toName: displayName(datum.to.way, vgraph) + })); + + if (datum.via.ways && datum.via.ways.length) { + var names = []; + for (var i = 0; i < datum.via.ways.length; i++) { + var prev = names[names.length - 1]; + var curr = displayName(datum.via.ways[i], vgraph); + if (!prev || curr !== prev) // collapse identical names + names.push(curr); + } + + help + .append('div') // "VIA {viaNames}" + .html(t('restriction.help.via_names', { + via: placeholders.via, + viaNames: names.join(', ') + })); + } + + if (!indirect) { + help + .append('div') // Click for "No Right Turn" + .text(t('restriction.help.toggle', { turn: nextText.trim() })); + } + + highlightPathsFrom(null); + var alongIDs = datum.path.slice(); + surface.selectAll(utilEntitySelector(alongIDs)) + .classed('related', true) + .classed('allow', (klass === 'allow')) + .classed('restrict', (klass === 'restrict')) + .classed('only', (klass === 'only')); + + + // Hovering empty surface + } else { + highlightPathsFrom(null); + if (_fromWayID) { + help + .append('div') // "FROM {fromName}" + .html(t('restriction.help.from_name', { + from: placeholders.from, + fromName: displayName(_fromWayID, vgraph) + })); + + } else { + help + .append('div') // "Click to select a FROM segment." + .html(t('restriction.help.select_from', { + from: placeholders.from + })); + } + } + } + } - dispatch$$1.call('change', d, t$$1); - } + function displayMaxDistance(maxDist) { + var isImperial = (utilDetect().locale.toLowerCase() === 'en-us'); + var opts; - function remove(d) { - event.stopPropagation(); - event.preventDefault(); + if (isImperial) { + var distToFeet = { // imprecise conversion for prettier display + 20: 70, 25: 85, 30: 100, 35: 115, 40: 130, 45: 145, 50: 160 + }[maxDist]; + opts = { distance: t('units.feet', { quantity: distToFeet }) }; + } else { + opts = { distance: t('units.meters', { quantity: maxDist }) }; + } - var t$$1 = {}; - d.keys.forEach(function(key) { - t$$1[key] = undefined; - }); + return t('restriction.controls.distance_up_to', opts); + } - dispatch$$1.call('change', d, t$$1); - } + function displayMaxVia(maxVia) { + return maxVia === 0 ? t('restriction.controls.via_node_only') + : maxVia === 1 ? t('restriction.controls.via_up_to_one') + : t('restriction.controls.via_up_to_two'); + } - field.render = function(selection$$1) { - var container = selection$$1.selectAll('.form-field') - .data([field]); - // Enter - var enter = container.enter() - .append('div') - .attr('class', function(d) { return 'form-field form-field-' + d.id; }) - .classed('nowrap', !options.wrap); + function displayName(entityID, graph) { + var entity = graph.entity(entityID); + var name = utilDisplayName(entity) || ''; + var matched = context.presets().match(entity, graph); + var type = (matched && matched.name()) || utilDisplayType(entity.id); + return name || type; + } - if (options.wrap) { - var label = enter - .append('label') - .attr('class', 'form-label') - .attr('for', function(d) { return 'preset-input-' + d.id; }) - .text(function(d) { return d.label(); }); - var wrap = label - .append('div') - .attr('class', 'form-label-button-wrap'); + restrictions.entity = function(_) { + _intersection = null; + _fromWayID = null; + _oldTurns = null; + _vertexID = _.id; + }; - if (options.remove) { - wrap - .append('button') - .attr('class', 'remove-icon') - .attr('tabindex', -1) - .call(svgIcon('#operation-delete')); - } - if (options.revert) { - wrap - .append('button') - .attr('class', 'modified-icon') - .attr('tabindex', -1) - .call( - (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo') - ); - } - } + restrictions.tags = function() {}; + restrictions.focus = function() {}; - // Update - container = container - .merge(enter); - - container.selectAll('.form-label-button-wrap .remove-icon') - .on('click', remove); - - container.selectAll('.form-label-button-wrap .modified-icon') - .on('click', revert); - - container - .classed('modified', isModified()) - .classed('present', isPresent()) - .each(function(d) { - var reference, help; - - // instantiate field help - if (options.wrap && field.type === 'restrictions') { - help = uiFieldHelp(context, 'restrictions'); - } - - // instantiate tag reference - if (options.wrap && options.info) { - var referenceKey = d.key; - if (d.type === 'multiCombo') { // lookup key without the trailing ':' - referenceKey = referenceKey.replace(/:$/, ''); - } - - reference = uiTagReference(d.reference || { key: referenceKey }, context); - if (_state === 'hover') { - reference.showing(false); - } - } - - d3_select(this) - .call(d.impl); - - // add field help components - if (help) { - d3_select(this) - .call(help.body) - .select('.form-label-button-wrap') - .call(help.button); - } - - // add tag reference components - if (reference) { - d3_select(this) - .call(reference.body) - .select('.form-label-button-wrap') - .call(reference.button); - } - - d.impl.tags(_tags); - }); - }; + restrictions.off = function(selection$$1) { + if (!_initialized) return; + selection$$1.selectAll('.surface') + .call(breathe.off) + .on('click.restrictions', null) + .on('mouseover.restrictions', null); - field.state = function(_) { - if (!arguments.length) return _state; - _state = _; - return field; - }; + select(window) + .on('resize.restrictions', null); + }; - field.tags = function(_) { - if (!arguments.length) return _tags; - _tags = _; - return field; - }; + return utilRebind(restrictions, dispatch$$1, 'on'); + } + function uiFieldTextarea(field) { + var dispatch$$1 = dispatch('change'), + input = select(null); + + + function textarea(selection$$1) { + input = selection$$1.selectAll('textarea') + .data([0]); + + input = input.enter() + .append('textarea') + .attr('id', 'preset-input-' + field.safeid) + .attr('placeholder', field.placeholder() || t('inspector.unknown')) + .attr('maxlength', 255) + .call(utilNoAuto) + .on('input', change(true)) + .on('blur', change()) + .on('change', change()) + .merge(input); + } - field.show = function() { - _show = true; - if (field.default && field.key && _tags[field.key] !== field.default) { - var t$$1 = {}; - t$$1[field.key] = field.default; - dispatch$$1.call('change', this, t$$1); - } - }; + function change(onInput) { + return function() { + var t$$1 = {}; + t$$1[field.key] = utilGetSetValue(input) || undefined; + dispatch$$1.call('change', this, t$$1, onInput); + }; + } - field.isShown = function() { - return _show || some(field.keys, function(key) { return !!_tags[key]; }); - }; + + textarea.tags = function(tags) { + utilGetSetValue(input, tags[field.key] || ''); + }; - field.focus = function() { - field.impl.focus(); - }; + textarea.focus = function() { + input.node().focus(); + }; + + return utilRebind(textarea, dispatch$$1, 'on'); + } - return utilRebind(field, dispatch$$1, 'on'); -} + function uiFieldWikipedia(field, context) { + var dispatch$$1 = dispatch('change'), + wikipedia = services.wikipedia, + wikidata = services.wikidata, + link = select(null), + lang = select(null), + title = select(null), + wikiURL = '', + entity; + + + function wiki(selection$$1) { + var langcombo = d3combobox() + .container(context.container()) + .fetcher(function(value, cb) { + var v = value.toLowerCase(); + + cb(wikipedia$2.filter(function(d) { + return d[0].toLowerCase().indexOf(v) >= 0 || + d[1].toLowerCase().indexOf(v) >= 0 || + d[2].toLowerCase().indexOf(v) >= 0; + }).map(function(d) { + return { value: d[1] }; + })); + }); + + var titlecombo = d3combobox() + .container(context.container()) + .fetcher(function(value, cb) { + if (!value) { + value = context.entity(entity.id).tags.name || ''; + } + + var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions; + searchfn(language()[2], value, function(query, data$$1) { + cb(data$$1.map(function(d) { + return { value: d }; + })); + }); + }); + + + lang = selection$$1.selectAll('input.wiki-lang') + .data([0]); + + lang = lang.enter() + .append('input') + .attr('type', 'text') + .attr('class', 'wiki-lang') + .attr('placeholder', t('translate.localized_translation_language')) + .call(utilNoAuto) + .merge(lang); + + utilGetSetValue(lang, language()[1]); + + lang + .call(langcombo) + .on('blur', changeLang) + .on('change', changeLang); + + + title = selection$$1.selectAll('input.wiki-title') + .data([0]); + + title = title.enter() + .append('input') + .attr('type', 'text') + .attr('class', 'wiki-title') + .attr('id', 'preset-input-' + field.safeid) + .call(utilNoAuto) + .merge(title); + + title + .call(titlecombo) + .on('blur', blur) + .on('change', change); + + + link = selection$$1.selectAll('.wiki-link') + .data([0]); + + link = link.enter() + .append('button') + .attr('class', 'button-input-action wiki-link minor') + .attr('tabindex', -1) + .call(svgIcon('#icon-out-link')) + .merge(link); + + link + .on('click', function() { + event.preventDefault(); + if (wikiURL) window.open(wikiURL, '_blank'); + }); + } -function uiFormFields(context) { - var fieldsArr; + function language() { + var value = utilGetSetValue(lang).toLowerCase(); + var locale = utilDetect().locale.toLowerCase(); + var localeLanguage; + return find$1(wikipedia$2, function(d) { + if (d[2] === locale) localeLanguage = d; + return d[0].toLowerCase() === value || + d[1].toLowerCase() === value || + d[2] === value; + }) || localeLanguage || ['English', 'English', 'en']; + } - function formFields(selection$$1, klass) { - render(selection$$1, klass); - } + function changeLang() { + utilGetSetValue(lang, language()[1]); + change(true); + } - function render(selection$$1, klass) { - var shown = fieldsArr.filter(function(field) { return field.isShown(); }), - notShown = fieldsArr.filter(function(field) { return !field.isShown(); }); + function blur() { + change(true); + } - var container = selection$$1.selectAll('.form-fields-container') - .data([0]); - container = container.enter() - .append('div') - .attr('class', 'form-fields-container ' + (klass || '')) - .merge(container); + function change(skipWikidata) { + var value = utilGetSetValue(title), + m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/), + l = m && find$1(wikipedia$2, function(d) { return m[1] === d[2]; }), + syncTags = {}; + + if (l) { + // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization + value = decodeURIComponent(m[2]).replace(/_/g, ' '); + if (m[3]) { + var anchor; + try { + // Best-effort `anchordecode:` implementation + anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1')); + } catch (e) { + anchor = decodeURIComponent(m[3]); + } + value += '#' + anchor.replace(/_/g, ' '); + } + value = value.slice(0, 1).toUpperCase() + value.slice(1); + utilGetSetValue(lang, l[1]); + utilGetSetValue(title, value); + } + if (value) { + syncTags.wikipedia = language()[2] + ':' + value; + } else { + syncTags.wikipedia = undefined; + syncTags.wikidata = undefined; + } - var fields = container.selectAll('.wrap-form-field') - .data(shown, function(d) { return d.id; }); + dispatch$$1.call('change', this, syncTags); - fields.exit() - .remove(); - // Enter - var enter = fields.enter() - .append('div') - .attr('class', function(d) { return 'wrap-form-field wrap-form-field-' + d.id; }); + if (skipWikidata || !value || !language()[2]) return; - // Update - fields = fields - .merge(enter); + // attempt asynchronous update of wikidata tag.. + var initGraph = context.graph(), + initEntityId = entity.id; - fields - .order() - .each(function(d) { - d3_select(this) - .call(d.render); - }); + wikidata.itemsByTitle(language()[2], value, function(title, data$$1) { + // If graph has changed, we can't apply this update. + if (context.graph() !== initGraph) return; + if (!data$$1 || !Object.keys(data$$1).length) return; - notShown = notShown.map(function(field) { - return { - title: field.label(), - value: field.label(), - field: field - }; - }); + var qids = Object.keys(data$$1); + var value = qids && find$1(qids, function(id) { return id.match(/^Q\d+$/); }); + var currTags = clone(context.entity(initEntityId).tags); + currTags.wikidata = value; - var more = selection$$1.selectAll('.more-fields') - .data((notShown.length > 0) ? [0] : []); - - more.exit() - .remove(); - - more = more.enter() - .append('div') - .attr('class', 'more-fields') - .append('label') - .text(t('inspector.add_fields')) - .merge(more); - - - var input = more.selectAll('.value') - .data([0]); - - input.exit() - .remove(); - - input = input.enter() - .append('input') - .attr('class', 'value') - .attr('type', 'text') - .call(utilNoAuto) - .merge(input); - - input - .call(utilGetSetValue, '') - .attr('placeholder', function() { - var placeholder = []; - for (var field in notShown) { - placeholder.push(notShown[field].title); - } - return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : ''); - }) - .call(d3combobox() - .container(context.container()) - .data(notShown) - .minItems(1) - .on('accept', function (d) { - var field = d.field; - field.show(); - render(selection$$1); - if (field.type !== 'semiCombo' && field.type !== 'multiCombo') { - field.focus(); - } - }) - ); - } + // Coalesce the update of wikidata tag into the previous tag change + context.overwrite( + actionChangeTags(initEntityId, currTags), + context.history().undoAnnotation() + ); + + // do not dispatch.call('change') here, because entity_editor + // changeTags() is not intended to be called asynchronously + }); + } - formFields.fieldsArr = function(_) { - if (!arguments.length) return fieldsArr; - fieldsArr = _; - return formFields; - }; + wiki.tags = function(tags) { + var value = tags[field.key] || '', + m = value.match(/([^:]+):([^#]+)(?:#(.+))?/), + l = m && find$1(wikipedia$2, function(d) { return m[1] === d[2]; }), + anchor = m && m[3]; + + // value in correct format + if (l) { + utilGetSetValue(lang, l[1]); + utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : '')); + if (anchor) { + try { + // Best-effort `anchorencode:` implementation + anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.'); + } catch (e) { + anchor = anchor.replace(/ /g, '_'); + } + } + wikiURL = 'https://' + m[1] + '.wikipedia.org/wiki/' + + m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''); + + // unrecognized value format + } else { + utilGetSetValue(title, value); + if (value && value !== '') { + utilGetSetValue(lang, ''); + wikiURL = 'https://en.wikipedia.org/wiki/Special:Search?search=' + value; + } else { + wikiURL = ''; + } + } + }; - return formFields; -} + wiki.entity = function(_) { + if (!arguments.length) return entity; + entity = _; + return wiki; + }; -function uiPresetEditor(context) { - var dispatch$$1 = dispatch('change'), - formFields = uiFormFields(context), - state, - fieldsArr, - preset, - tags, - entityId; + wiki.focus = function() { + title.node().focus(); + }; - function presetEditor(selection$$1) { - selection$$1.call(uiDisclosure(context, 'preset_fields', true) - .title(t('inspector.all_fields')) - .content(render) - ); - } + return utilRebind(wiki, dispatch$$1, 'on'); + } - function render(selection$$1) { - if (!fieldsArr) { - var entity = context.entity(entityId), - geometry = context.geometry(entityId), - presets = context.presets(); + var uiFields = { + access: uiFieldAccess, + address: uiFieldAddress, + check: uiFieldCheck, + combo: uiFieldCombo, + cycleway: uiFieldCycleway, + defaultCheck: uiFieldCheck, + email: uiFieldText, + lanes: uiFieldLanes, + localized: uiFieldLocalized, + maxspeed: uiFieldMaxspeed, + multiCombo: uiFieldCombo, + networkCombo: uiFieldCombo, + number: uiFieldText, + onewayCheck: uiFieldCheck, + radio: uiFieldRadio, + restrictions: uiFieldRestrictions, + semiCombo: uiFieldCombo, + structureRadio: uiFieldRadio, + tel: uiFieldText, + text: uiFieldText, + textarea: uiFieldTextarea, + typeCombo: uiFieldCombo, + url: uiFieldText, + wikipedia: uiFieldWikipedia + }; - fieldsArr = []; + function uiField(context, presetField, entity, options) { + options = assignIn({ + show: true, + wrap: true, + remove: true, + revert: true, + info: true + }, options); + + var dispatch$$1 = dispatch('change'); + var field = clone(presetField); + var _show = options.show; + var _state = ''; + var _tags = {}; + + + field.impl = uiFields[field.type](field, context) + .on('change', function(t$$1, onInput) { + dispatch$$1.call('change', field, t$$1, onInput); + }); - preset.fields.forEach(function(field) { - if (field.matchGeometry(geometry)) { - fieldsArr.push( - uiField(context, field, entity) - ); - } - }); + if (entity && field.impl.entity) { + field.impl.entity(entity); + } - if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) { - fieldsArr.push( - uiField(context, presets.field('restrictions'), entity) - ); - } + field.keys = field.keys || [field.key]; - presets.universal().forEach(function(field) { - if (preset.fields.indexOf(field) === -1) { - fieldsArr.push( - uiField(context, field, entity, { show: false }) - ); - } - }); - fieldsArr.forEach(function(field) { - field - .on('change', function(t$$1, onInput) { - dispatch$$1.call('change', field, t$$1, onInput); - }); - }); - } + function isModified() { + if (!entity) return false; + var original = context.graph().base().entities[entity.id]; + return some(field.keys, function(key) { + return original ? _tags[key] !== original.tags[key] : _tags[key]; + }); + } - fieldsArr.forEach(function(field) { - field - .state(state) - .tags(tags); - }); + function isPresent() { + return some(field.keys, function(key) { + return _tags[key]; + }); + } - selection$$1 - .call(formFields.fieldsArr(fieldsArr), 'inspector-inner fillL3'); + function revert(d) { + event.stopPropagation(); + event.preventDefault(); + if (!entity) return false; - selection$$1.selectAll('.wrap-form-field input') - .on('keydown', function() { - // if user presses enter, and combobox is not active, accept edits.. - if (event.keyCode === 13 && d3_select('.combobox').empty()) { - context.enter(modeBrowse(context)); - } - }); - } + var original = context.graph().base().entities[entity.id]; + var t$$1 = {}; + d.keys.forEach(function(key) { + t$$1[key] = original ? original.tags[key] : undefined; + }); + dispatch$$1.call('change', d, t$$1); + } - presetEditor.preset = function(_) { - if (!arguments.length) return preset; - if (preset && preset.id === _.id) return presetEditor; - preset = _; - fieldsArr = null; - return presetEditor; - }; + function remove(d) { + event.stopPropagation(); + event.preventDefault(); - presetEditor.state = function(_) { - if (!arguments.length) return state; - state = _; - return presetEditor; - }; + var t$$1 = {}; + d.keys.forEach(function(key) { + t$$1[key] = undefined; + }); + dispatch$$1.call('change', d, t$$1); + } - presetEditor.tags = function(_) { - if (!arguments.length) return tags; - tags = _; - // Don't reset fieldsArr here. - return presetEditor; - }; + field.render = function(selection$$1) { + var container = selection$$1.selectAll('.form-field') + .data([field]); - presetEditor.entityID = function(_) { - if (!arguments.length) return entityId; - if (entityId === _) return presetEditor; - entityId = _; - fieldsArr = null; - return presetEditor; - }; + // Enter + var enter = container.enter() + .append('div') + .attr('class', function(d) { return 'form-field form-field-' + d.safeid; }) + .classed('nowrap', !options.wrap); + if (options.wrap) { + var label = enter + .append('label') + .attr('class', 'form-label') + .attr('for', function(d) { return 'preset-input-' + d.safeid; }) + .text(function(d) { return d.label(); }); - return utilRebind(presetEditor, dispatch$$1, 'on'); -} - -function uiEntityEditor(context) { - var dispatch$$1 = dispatch('choose'), - state = 'select', - coalesceChanges = false, - modified = false, - base, - entityId, - activePreset, - reference; - - var presetEditor = uiPresetEditor(context) - .on('change', changeTags); - var rawTagEditor = uiRawTagEditor(context) - .on('change', changeTags); - - - function entityEditor(selection$$1) { - var entity = context.entity(entityId), - tags = clone(entity.tags); - - // Header - var header = selection$$1.selectAll('.header') - .data([0]); - - // Enter - var enter = header.enter() - .append('div') - .attr('class', 'header fillL cf'); - - enter - .append('button') - .attr('class', 'fl preset-reset preset-choose') - .call(svgIcon((textDirection === 'rtl') ? '#icon-forward' : '#icon-backward')); - - enter - .append('button') - .attr('class', 'fr preset-close') - .on('click', function() { context.enter(modeBrowse(context)); }) - .call(svgIcon(modified ? '#icon-apply' : '#icon-close')); - - enter - .append('h3') - .text(t('inspector.edit')); - - // Update - header = header - .merge(enter); - - header.selectAll('.preset-reset') - .on('click', function() { - dispatch$$1.call('choose', this, activePreset); - }); + var wrap = label + .append('div') + .attr('class', 'form-label-button-wrap'); + + if (options.remove) { + wrap + .append('button') + .attr('class', 'remove-icon') + .attr('title', t('icons.remove')) + .attr('tabindex', -1) + .call(svgIcon('#operation-delete')); + } + + if (options.revert) { + wrap + .append('button') + .attr('class', 'modified-icon') + .attr('title', t('icons.undo')) + .attr('tabindex', -1) + .call( + (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo') + ); + } + } - // Body - var body = selection$$1.selectAll('.inspector-body') - .data([0]); + // Update + container = container + .merge(enter); + + container.selectAll('.form-label-button-wrap .remove-icon') + .on('click', remove); + + container.selectAll('.form-label-button-wrap .modified-icon') + .on('click', revert); + + container + .classed('modified', isModified()) + .classed('present', isPresent()) + .each(function(d) { + var reference, help; + + // instantiate field help + if (options.wrap && field.type === 'restrictions') { + help = uiFieldHelp(context, 'restrictions'); + } + + // instantiate tag reference + if (options.wrap && options.info) { + var referenceKey = d.key; + if (d.type === 'multiCombo') { // lookup key without the trailing ':' + referenceKey = referenceKey.replace(/:$/, ''); + } + + reference = uiTagReference(d.reference || { key: referenceKey }, context); + if (_state === 'hover') { + reference.showing(false); + } + } + + select(this) + .call(d.impl); + + // add field help components + if (help) { + select(this) + .call(help.body) + .select('.form-label-button-wrap') + .call(help.button); + } + + // add tag reference components + if (reference) { + select(this) + .call(reference.body) + .select('.form-label-button-wrap') + .call(reference.button); + } + + d.impl.tags(_tags); + }); + }; - // Enter - enter = body.enter() - .append('div') - .attr('class', 'inspector-body'); - enter - .append('div') - .attr('class', 'preset-list-item inspector-inner') - .append('div') - .attr('class', 'preset-list-button-wrap') - .append('button') - .attr('class', 'preset-list-button preset-reset') - .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom')) - .append('div') - .attr('class', 'label'); + field.state = function(_) { + if (!arguments.length) return _state; + _state = _; + return field; + }; - enter - .append('div') - .attr('class', 'inspector-border preset-editor'); - enter - .append('div') - .attr('class', 'inspector-border raw-tag-editor inspector-inner'); + field.tags = function(_) { + if (!arguments.length) return _tags; + _tags = _; + return field; + }; - enter - .append('div') - .attr('class', 'inspector-border raw-member-editor inspector-inner'); - enter - .append('div') - .attr('class', 'raw-membership-editor inspector-inner'); + field.show = function() { + _show = true; + if (field.default && field.key && _tags[field.key] !== field.default) { + var t$$1 = {}; + t$$1[field.key] = field.default; + dispatch$$1.call('change', this, t$$1); + } + }; - enter - .append('input') - .attr('type', 'text') - .attr('class', 'key-trap'); + field.isShown = function() { + return _show || some(field.keys, function(key) { return !!_tags[key]; }); + }; - // Update - body = body - .merge(enter); - body.selectAll('.preset-list-button-wrap') - .call(reference.button); + field.focus = function() { + field.impl.focus(); + }; - body.selectAll('.preset-list-item') - .call(reference.body); - body.selectAll('.preset-reset') - .on('click', function() { - dispatch$$1.call('choose', this, activePreset); - }); + return utilRebind(field, dispatch$$1, 'on'); + } - body.select('.preset-list-item button') - .call(uiPresetIcon() - .geometry(context.geometry(entityId)) - .preset(activePreset) - ); + function uiFormFields(context) { + var fieldsArr; - body.select('.preset-list-item .label') - .text(activePreset.name()); - body.select('.preset-editor') - .call(presetEditor - .preset(activePreset) - .entityID(entityId) - .tags(tags) - .state(state) - ); + function formFields(selection$$1, klass) { + render(selection$$1, klass); + } - body.select('.raw-tag-editor') - .call(rawTagEditor - .preset(activePreset) - .entityID(entityId) - .tags(tags) - .state(state) - ); - if (entity.type === 'relation') { - body.select('.raw-member-editor') - .style('display', 'block') - .call(uiRawMemberEditor(context) - .entityID(entityId) - ); - } else { - body.select('.raw-member-editor') - .style('display', 'none'); - } + function render(selection$$1, klass) { - body.select('.raw-membership-editor') - .call(uiRawMembershipEditor(context) - .entityID(entityId) - ); + var shown = fieldsArr.filter(function(field) { return field.isShown(); }), + notShown = fieldsArr.filter(function(field) { return !field.isShown(); }); - body.select('.key-trap') - .on('keydown.key-trap', function() { - // On tabbing, send focus back to the first field on the inspector-body - // (probably the `name` field) #4159 - if (event.keyCode === 9 && !event.shiftKey) { - event.preventDefault(); - body.select('input').node().focus(); - } - }); + var container = selection$$1.selectAll('.form-fields-container') + .data([0]); - context.history() - .on('change.entity-editor', historyChanged); + container = container.enter() + .append('div') + .attr('class', 'form-fields-container ' + (klass || '')) + .merge(container); - function historyChanged() { - if (state === 'hide') return; + var fields = container.selectAll('.wrap-form-field') + .data(shown, function(d) { return d.id; }); - var entity = context.hasEntity(entityId); - var graph = context.graph(); - if (!entity) return; + fields.exit() + .remove(); - var match = context.presets().match(entity, graph); - var activePreset = entityEditor.preset(); - var weakPreset = activePreset && isEmpty(activePreset.addTags); + // Enter + var enter = fields.enter() + .append('div') + .attr('class', function(d) { return 'wrap-form-field wrap-form-field-' + d.safeid; }); - // A "weak" preset doesn't set any tags. (e.g. "Address") - // Don't replace a weak preset with a fallback preset (e.g. "Point") - if (!(weakPreset && match.isFallback())) { - entityEditor.preset(match); - } - entityEditor.modified(base !== graph); - entityEditor(selection$$1); - } - } + // Update + fields = fields + .merge(enter); + fields + .order() + .each(function(d) { + select(this) + .call(d.render); + }); - function clean(o) { - function cleanVal(k, v) { - function keepSpaces(k) { - return k.match(/_hours|_times/) !== null; - } + notShown = notShown.map(function(field) { + return { + title: field.label(), + value: field.label(), + field: field + }; + }); - var blacklist = ['description', 'note', 'fixme']; - if (some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v; - var cleaned = v.split(';') - .map(function(s) { return s.trim(); }) - .join(keepSpaces(k) ? '; ' : ';'); + var more = selection$$1.selectAll('.more-fields') + .data((notShown.length > 0) ? [0] : []); + + more.exit() + .remove(); + + more = more.enter() + .append('div') + .attr('class', 'more-fields') + .append('label') + .text(t('inspector.add_fields')) + .merge(more); + + + var input = more.selectAll('.value') + .data([0]); + + input.exit() + .remove(); + + input = input.enter() + .append('input') + .attr('class', 'value') + .attr('type', 'text') + .call(utilNoAuto) + .merge(input); + + input + .call(utilGetSetValue, '') + .attr('placeholder', function() { + var placeholder = []; + for (var field in notShown) { + placeholder.push(notShown[field].title); + } + return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : ''); + }) + .call(d3combobox() + .container(context.container()) + .data(notShown) + .minItems(1) + .on('accept', function (d) { + var field = d.field; + field.show(); + render(selection$$1); + if (field.type !== 'semiCombo' && field.type !== 'multiCombo') { + field.focus(); + } + }) + ); + } - // The code below is not intended to validate websites and emails. - // It is only intended to prevent obvious copy-paste errors. (#2323) - // clean website- and email-like tags - if (k.indexOf('website') !== -1 || - k.indexOf('email') !== -1 || - cleaned.indexOf('http') === 0) { - cleaned = cleaned - .replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars - } + formFields.fieldsArr = function(_) { + if (!arguments.length) return fieldsArr; + fieldsArr = _; + return formFields; + }; - return cleaned; - } - var out = {}, k, v; - for (k in o) { - if (k && (v = o[k]) !== undefined) { - out[k] = cleanVal(k, v); - } - } - return out; - } + return formFields; + } + function uiPresetEditor(context) { + var dispatch$$1 = dispatch('change'), + formFields = uiFormFields(context), + state, + fieldsArr, + preset, + tags, + entityId; - // Tag changes that fire on input can all get coalesced into a single - // history operation when the user leaves the field. #2342 - function changeTags(changed, onInput) { - var entity = context.entity(entityId), - annotation = t('operations.change_tags.annotation'), - tags = clone(entity.tags); - forEach(changed, function(v, k) { - if (v !== undefined || tags.hasOwnProperty(k)) { - tags[k] = v; - } - }); + function presetEditor(selection$$1) { + selection$$1.call(uiDisclosure(context, 'preset_fields', true) + .title(t('inspector.all_fields')) + .content(render) + ); + } - if (!onInput) { - tags = clean(tags); - } - if (!isEqual(entity.tags, tags)) { - if (coalesceChanges) { - context.overwrite(actionChangeTags(entityId, tags), annotation); - } else { - context.perform(actionChangeTags(entityId, tags), annotation); - coalesceChanges = !!onInput; - } - } - } + function render(selection$$1) { + if (!fieldsArr) { + var entity = context.entity(entityId), + geometry = context.geometry(entityId), + presets = context.presets(); + + fieldsArr = []; + + preset.fields.forEach(function(field) { + if (field.matchGeometry(geometry)) { + fieldsArr.push( + uiField(context, field, entity) + ); + } + }); + + if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) { + fieldsArr.push( + uiField(context, presets.field('restrictions'), entity) + ); + } + + presets.universal().forEach(function(field) { + if (preset.fields.indexOf(field) === -1) { + fieldsArr.push( + uiField(context, field, entity, { show: false }) + ); + } + }); + + fieldsArr.forEach(function(field) { + field + .on('change', function(t$$1, onInput) { + dispatch$$1.call('change', field, t$$1, onInput); + }); + }); + } + fieldsArr.forEach(function(field) { + field + .state(state) + .tags(tags); + }); - entityEditor.modified = function(_) { - if (!arguments.length) return modified; - modified = _; - d3_selectAll('button.preset-close use') - .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close')); - }; + selection$$1 + .call(formFields.fieldsArr(fieldsArr), 'inspector-inner fillL3'); - entityEditor.state = function(_) { - if (!arguments.length) return state; - state = _; - return entityEditor; - }; + selection$$1.selectAll('.wrap-form-field input') + .on('keydown', function() { + // if user presses enter, and combobox is not active, accept edits.. + if (event.keyCode === 13 && select('.combobox').empty()) { + context.enter(modeBrowse(context)); + } + }); + } - entityEditor.entityID = function(_) { - if (!arguments.length) return entityId; - entityId = _; - base = context.graph(); - entityEditor.preset(context.presets().match(context.entity(entityId), base)); - entityEditor.modified(false); - coalesceChanges = false; - return entityEditor; - }; + presetEditor.preset = function(_) { + if (!arguments.length) return preset; + if (preset && preset.id === _.id) return presetEditor; + preset = _; + fieldsArr = null; + return presetEditor; + }; - entityEditor.preset = function(_) { - if (!arguments.length) return activePreset; - if (_ !== activePreset) { - activePreset = _; - reference = uiTagReference(activePreset.reference(context.geometry(entityId)), context) - .showing(false); - } - return entityEditor; - }; + presetEditor.state = function(_) { + if (!arguments.length) return state; + state = _; + return presetEditor; + }; - return utilRebind(entityEditor, dispatch$$1, 'on'); -} -function uiPresetList(context) { - var dispatch$$1 = dispatch('choose'), - id, - currentPreset, - autofocus = false; + presetEditor.tags = function(_) { + if (!arguments.length) return tags; + tags = _; + // Don't reset fieldsArr here. + return presetEditor; + }; - function presetList(selection$$1) { - var entity = context.entity(id), - geometry = context.geometry(id); + presetEditor.entityID = function(_) { + if (!arguments.length) return entityId; + if (entityId === _) return presetEditor; + entityId = _; + fieldsArr = null; + return presetEditor; + }; - // Treat entities on addr:interpolation lines as points, not vertices (#3241) - if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) { - geometry = 'point'; - } - var presets = context.presets().matchGeometry(geometry); + return utilRebind(presetEditor, dispatch$$1, 'on'); + } - selection$$1.html(''); + function uiEntityEditor(context) { + var dispatch$$1 = dispatch('choose'); + var _state = 'select'; + var _coalesceChanges = false; + var _modified = false; + var _base; + var _entityID; + var _activePreset; + var _tagReference; + + var presetEditor = uiPresetEditor(context) + .on('change', changeTags); + var rawTagEditor = uiRawTagEditor(context) + .on('change', changeTags); + + + function entityEditor(selection$$1) { + var entity = context.entity(_entityID); + var tags = clone(entity.tags); + + // Header + var header = selection$$1.selectAll('.header') + .data([0]); + + // Enter + var enter = header.enter() + .append('div') + .attr('class', 'header fillL cf'); + + enter + .append('button') + .attr('class', 'fl preset-reset preset-choose') + .call(svgIcon((textDirection === 'rtl') ? '#icon-forward' : '#icon-backward')); + + enter + .append('button') + .attr('class', 'fr preset-close') + .on('click', function() { context.enter(modeBrowse(context)); }) + .call(svgIcon(_modified ? '#icon-apply' : '#icon-close')); + + enter + .append('h3') + .text(t('inspector.edit')); + + // Update + header = header + .merge(enter); + + header.selectAll('.preset-reset') + .on('click', function() { + dispatch$$1.call('choose', this, _activePreset); + }); + + + // Body + var body = selection$$1.selectAll('.inspector-body') + .data([0]); + + // Enter + enter = body.enter() + .append('div') + .attr('class', 'inspector-body'); + + enter + .append('div') + .attr('class', 'preset-list-item inspector-inner') + .append('div') + .attr('class', 'preset-list-button-wrap') + .append('button') + .attr('class', 'preset-list-button preset-reset') + .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom')) + .append('div') + .attr('class', 'label'); + + enter + .append('div') + .attr('class', 'inspector-border preset-editor'); + + enter + .append('div') + .attr('class', 'inspector-border raw-tag-editor inspector-inner'); + + enter + .append('div') + .attr('class', 'inspector-border raw-member-editor inspector-inner'); + + enter + .append('div') + .attr('class', 'raw-membership-editor inspector-inner'); + + enter + .append('input') + .attr('type', 'text') + .attr('class', 'key-trap'); + + + // Update + body = body + .merge(enter); + + if (_tagReference) { + body.selectAll('.preset-list-button-wrap') + .call(_tagReference.button); + + body.selectAll('.preset-list-item') + .call(_tagReference.body); + } - var messagewrap = selection$$1 - .append('div') - .attr('class', 'header fillL cf'); + body.selectAll('.preset-reset') + .on('click', function() { + dispatch$$1.call('choose', this, _activePreset); + }); + + body.select('.preset-list-item button') + .call(uiPresetIcon() + .geometry(context.geometry(_entityID)) + .preset(_activePreset) + ); + + body.select('.preset-list-item .label') + .text(_activePreset.name()); + + body.select('.preset-editor') + .call(presetEditor + .preset(_activePreset) + .entityID(_entityID) + .tags(tags) + .state(_state) + ); + + body.select('.raw-tag-editor') + .call(rawTagEditor + .preset(_activePreset) + .entityID(_entityID) + .tags(tags) + .state(_state) + ); + + if (entity.type === 'relation') { + body.select('.raw-member-editor') + .style('display', 'block') + .call(uiRawMemberEditor(context) + .entityID(_entityID) + ); + } else { + body.select('.raw-member-editor') + .style('display', 'none'); + } - var message = messagewrap - .append('h3') - .text(t('inspector.choose')); + body.select('.raw-membership-editor') + .call(uiRawMembershipEditor(context) + .entityID(_entityID) + ); + + body.select('.key-trap') + .on('keydown.key-trap', function() { + // On tabbing, send focus back to the first field on the inspector-body + // (probably the `name` field) #4159 + if (event.keyCode === 9 && !event.shiftKey) { + event.preventDefault(); + body.select('input').node().focus(); + } + }); + + context.history() + .on('change.entity-editor', historyChanged); + + + function historyChanged() { + if (_state === 'hide') return; + + var entity = context.hasEntity(_entityID); + var graph = context.graph(); + if (!entity) return; + + var match = context.presets().match(entity, graph); + var activePreset = entityEditor.preset(); + var weakPreset = activePreset && isEmpty(activePreset.addTags); + + // A "weak" preset doesn't set any tags. (e.g. "Address") + // Don't replace a weak preset with a fallback preset (e.g. "Point") + if (!(weakPreset && match.isFallback())) { + entityEditor.preset(match); + } + entityEditor.modified(_base !== graph); + entityEditor(selection$$1); + } + } - if (context.entity(id).isUsed(context.graph())) { - messagewrap - .append('button') - .attr('class', 'preset-choose') - .on('click', function() { dispatch$$1.call('choose', this, currentPreset); }) - .call(svgIcon((textDirection === 'rtl') ? '#icon-backward' : '#icon-forward')); - } else { - messagewrap - .append('button') - .attr('class', 'close') - .on('click', function() { - context.enter(modeBrowse(context)); - }) - .call(svgIcon('#icon-close')); - } - function keydown() { - // hack to let delete shortcut work when search is autofocused - if (search.property('value').length === 0 && - (event.keyCode === d3keybinding.keyCodes['⌫'] || - event.keyCode === d3keybinding.keyCodes['⌦'])) { - event.preventDefault(); - event.stopPropagation(); - operationDelete([id], context)(); - } else if (search.property('value').length === 0 && - (event.ctrlKey || event.metaKey) && - event.keyCode === d3keybinding.keyCodes.z) { - event.preventDefault(); - event.stopPropagation(); - context.undo(); - } else if (!event.ctrlKey && !event.metaKey) { - d3_select(this).on('keydown', null); - } - } + // Tag changes that fire on input can all get coalesced into a single + // history operation when the user leaves the field. #2342 + function changeTags(changed, onInput) { + var entity = context.entity(_entityID); + var annotation = t('operations.change_tags.annotation'); + var tags = clone(entity.tags); - function keypress() { - // enter - var value = search.property('value'); - if (event.keyCode === 13 && value.length) { - list.selectAll('.preset-list-item:first-child').datum().choose(); - } - } + for (var k in changed) { + if (!k) continue; + var v = changed[k]; + if (v !== undefined || tags.hasOwnProperty(k)) { + tags[k] = v; + } + } - function inputevent() { - var value = search.property('value'); - list.classed('filtered', value.length); - if (value.length) { - var results = presets.search(value, geometry); - message.text(t('inspector.results', { - n: results.collection.length, - search: value - })); - list.call(drawList, results); - } else { - list.call(drawList, context.presets().defaults(geometry, 36)); - message.text(t('inspector.choose')); - } - } + if (!onInput) { + tags = utilCleanTags(tags); + } - var searchWrap = selection$$1 - .append('div') - .attr('class', 'search-header'); - - var search = searchWrap - .append('input') - .attr('class', 'preset-search-input') - .attr('placeholder', t('inspector.search')) - .attr('type', 'search') - .call(utilNoAuto) - .on('keydown', keydown) - .on('keypress', keypress) - .on('input', inputevent); - - searchWrap - .call(svgIcon('#icon-search', 'pre-text')); - - if (autofocus) { - search.node().focus(); - } + if (!isEqual(entity.tags, tags)) { + if (_coalesceChanges) { + context.overwrite(actionChangeTags(_entityID, tags), annotation); + } else { + context.perform(actionChangeTags(_entityID, tags), annotation); + _coalesceChanges = !!onInput; + } + } + } - var listWrap = selection$$1 - .append('div') - .attr('class', 'inspector-body'); - var list = listWrap - .append('div') - .attr('class', 'preset-list fillL cf') - .call(drawList, context.presets().defaults(geometry, 36)); - } + entityEditor.modified = function(_) { + if (!arguments.length) return _modified; + _modified = _; + d3_selectAll('button.preset-close use') + .attr('xlink:href', (_modified ? '#icon-apply' : '#icon-close')); + return entityEditor; + }; - function drawList(list, presets) { - var collection = presets.collection.map(function(preset) { - return preset.members ? CategoryItem(preset) : PresetItem(preset); - }); + entityEditor.state = function(_) { + if (!arguments.length) return _state; + _state = _; + return entityEditor; + }; - var items = list.selectAll('.preset-list-item') - .data(collection, function(d) { return d.preset.id; }); - - items.order(); - - items.exit() - .remove(); - - items.enter() - .append('div') - .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); }) - .classed('current', function(item) { return item.preset === currentPreset; }) - .each(function(item) { d3_select(this).call(item); }) - .style('opacity', 0) - .transition() - .style('opacity', 1); - } - - - function CategoryItem(preset) { - var box, sublist, shown = false; - - function item(selection$$1) { - var wrap = selection$$1.append('div') - .attr('class', 'preset-list-button-wrap category col12'); - - var button = wrap - .append('button') - .attr('class', 'preset-list-button') - .classed('expanded', false) - .call(uiPresetIcon() - .geometry(context.geometry(id)) - .preset(preset)) - .on('click', function() { - var isExpanded = d3_select(this).classed('expanded'); - var iconName = isExpanded ? - (textDirection === 'rtl' ? '#icon-backward' : '#icon-forward') : '#icon-down'; - d3_select(this) - .classed('expanded', !isExpanded); - d3_select(this).selectAll('div.label svg.icon use') - .attr('href', iconName); - item.choose(); - }); - - var label = button - .append('div') - .attr('class', 'label'); - - label - .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline')) - .append('span') - .html(function() { return preset.name() + '…'; }); - - box = selection$$1.append('div') - .attr('class', 'subgrid col12') - .style('max-height', '0px') - .style('opacity', 0); - - box.append('div') - .attr('class', 'arrow'); - - sublist = box.append('div') - .attr('class', 'preset-list fillL3 cf fl'); - } + entityEditor.entityID = function(_) { + if (!arguments.length) return _entityID; + _entityID = _; + _base = context.graph(); + _coalesceChanges = false; - item.choose = function() { - if (!box || !sublist) return; + var presetMatch = context.presets().match(context.entity(_entityID), _base); - if (shown) { - shown = false; - box.transition() - .duration(200) - .style('opacity', '0') - .style('max-height', '0px') - .style('padding-bottom', '0px'); - } else { - shown = true; - sublist.call(drawList, preset.members); - box.transition() - .duration(200) - .style('opacity', '1') - .style('max-height', 200 + preset.members.collection.length * 190 + 'px') - .style('padding-bottom', '20px'); - } - }; + return entityEditor + .preset(presetMatch) + .modified(false); + }; - item.preset = preset; - return item; - } + entityEditor.preset = function(_) { + if (!arguments.length) return _activePreset; + if (_ !== _activePreset) { + _activePreset = _; + _tagReference = uiTagReference(_activePreset.reference(context.geometry(_entityID)), context) + .showing(false); + } + return entityEditor; + }; - function PresetItem(preset) { - function item(selection$$1) { - var wrap = selection$$1.append('div') - .attr('class', 'preset-list-button-wrap col12'); + return utilRebind(entityEditor, dispatch$$1, 'on'); + } - wrap.append('button') - .attr('class', 'preset-list-button') - .call(uiPresetIcon() - .geometry(context.geometry(id)) - .preset(preset)) - .on('click', item.choose) - .append('div') - .attr('class', 'label') - .text(preset.name()); + function uiPresetList(context) { + var dispatch$$1 = dispatch('choose'), + id, + currentPreset, + autofocus = false; - wrap.call(item.reference.button); - selection$$1.call(item.reference.body); - } - item.choose = function() { - context.presets().choose(preset); + function presetList(selection$$1) { + var entity = context.entity(id), + geometry = context.geometry(id); - context.perform( - actionChangePreset(id, currentPreset, preset), - t('operations.change_tags.annotation') - ); + // Treat entities on addr:interpolation lines as points, not vertices (#3241) + if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) { + geometry = 'point'; + } - dispatch$$1.call('choose', this, preset); - }; + var presets = context.presets().matchGeometry(geometry); - item.help = function() { - event.stopPropagation(); - item.reference.toggle(); - }; + selection$$1.html(''); - item.preset = preset; - item.reference = uiTagReference(preset.reference(context.geometry(id)), context); + var messagewrap = selection$$1 + .append('div') + .attr('class', 'header fillL cf'); - return item; - } + var message = messagewrap + .append('h3') + .text(t('inspector.choose')); + if (context.entity(id).isUsed(context.graph())) { + messagewrap + .append('button') + .attr('class', 'preset-choose') + .on('click', function() { dispatch$$1.call('choose', this, currentPreset); }) + .call(svgIcon((textDirection === 'rtl') ? '#icon-backward' : '#icon-forward')); + } else { + messagewrap + .append('button') + .attr('class', 'close') + .on('click', function() { + context.enter(modeBrowse(context)); + }) + .call(svgIcon('#icon-close')); + } - presetList.autofocus = function(_) { - if (!arguments.length) return autofocus; - autofocus = _; - return presetList; - }; + function keydown() { + // hack to let delete shortcut work when search is autofocused + if (search.property('value').length === 0 && + (event.keyCode === d3keybinding.keyCodes['⌫'] || + event.keyCode === d3keybinding.keyCodes['⌦'])) { + event.preventDefault(); + event.stopPropagation(); + operationDelete([id], context)(); + } else if (search.property('value').length === 0 && + (event.ctrlKey || event.metaKey) && + event.keyCode === d3keybinding.keyCodes.z) { + event.preventDefault(); + event.stopPropagation(); + context.undo(); + } else if (!event.ctrlKey && !event.metaKey) { + select(this).on('keydown', null); + } + } + function keypress() { + // enter + var value = search.property('value'); + if (event.keyCode === 13 && value.length) { + list.selectAll('.preset-list-item:first-child').datum().choose(); + } + } - presetList.entityID = function(_) { - if (!arguments.length) return id; - id = _; - presetList.preset(context.presets().match(context.entity(id), context.graph())); - return presetList; - }; + function inputevent() { + var value = search.property('value'); + list.classed('filtered', value.length); + if (value.length) { + var results = presets.search(value, geometry); + message.text(t('inspector.results', { + n: results.collection.length, + search: value + })); + list.call(drawList, results); + } else { + list.call(drawList, context.presets().defaults(geometry, 36)); + message.text(t('inspector.choose')); + } + } + var searchWrap = selection$$1 + .append('div') + .attr('class', 'search-header'); + + var search = searchWrap + .append('input') + .attr('class', 'preset-search-input') + .attr('placeholder', t('inspector.search')) + .attr('type', 'search') + .call(utilNoAuto) + .on('keydown', keydown) + .on('keypress', keypress) + .on('input', inputevent); + + searchWrap + .call(svgIcon('#icon-search', 'pre-text')); + + if (autofocus) { + search.node().focus(); + } - presetList.preset = function(_) { - if (!arguments.length) return currentPreset; - currentPreset = _; - return presetList; - }; + var listWrap = selection$$1 + .append('div') + .attr('class', 'inspector-body'); + var list = listWrap + .append('div') + .attr('class', 'preset-list fillL cf') + .call(drawList, context.presets().defaults(geometry, 36)); + } - return utilRebind(presetList, dispatch$$1, 'on'); -} -function uiViewOnOSM(context) { - var id; + function drawList(list, presets) { + var collection = presets.collection.map(function(preset) { + return preset.members ? CategoryItem(preset) : PresetItem(preset); + }); - function viewOnOSM(selection) { - var entity = context.entity(id); + var items = list.selectAll('.preset-list-item') + .data(collection, function(d) { return d.preset.id; }); - selection.style('display', entity.isNew() ? 'none' : null); + items.order(); - var link = selection.selectAll('.view-on-osm') - .data([0]); + items.exit() + .remove(); - var enter = link.enter() - .append('a') - .attr('class', 'view-on-osm') - .attr('target', '_blank') - .call(svgIcon('#icon-out-link', 'inline')); + items.enter() + .append('div') + .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); }) + .classed('current', function(item) { return item.preset === currentPreset; }) + .each(function(item) { select(this).call(item); }) + .style('opacity', 0) + .transition() + .style('opacity', 1); + } - enter - .append('span') - .text(t('inspector.view_on_osm')); - link - .merge(enter) - .attr('href', context.connection().entityURL(entity)); - } + function CategoryItem(preset) { + var box, sublist, shown = false; + function item(selection$$1) { + var wrap = selection$$1.append('div') + .attr('class', 'preset-list-button-wrap category col12'); - viewOnOSM.entityID = function(_) { - if (!arguments.length) return id; - id = _; - return viewOnOSM; - }; + var button = wrap + .append('button') + .attr('class', 'preset-list-button') + .classed('expanded', false) + .call(uiPresetIcon() + .geometry(context.geometry(id)) + .preset(preset)) + .on('click', function() { + var isExpanded = select(this).classed('expanded'); + var iconName = isExpanded ? + (textDirection === 'rtl' ? '#icon-backward' : '#icon-forward') : '#icon-down'; + select(this) + .classed('expanded', !isExpanded); + select(this).selectAll('div.label svg.icon use') + .attr('href', iconName); + item.choose(); + }); + + var label = button + .append('div') + .attr('class', 'label'); - return viewOnOSM; -} + label + .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline')) + .append('span') + .html(function() { return preset.name() + '…'; }); -function uiInspector(context) { - var presetList = uiPresetList(context); - var entityEditor = uiEntityEditor(context); - var _state = 'select'; - var _entityID; - var _newFeature = false; + box = selection$$1.append('div') + .attr('class', 'subgrid col12') + .style('max-height', '0px') + .style('opacity', 0); + box.append('div') + .attr('class', 'arrow'); - function inspector(selection$$1) { - presetList - .entityID(_entityID) - .autofocus(_newFeature) - .on('choose', setPreset); + sublist = box.append('div') + .attr('class', 'preset-list fillL3 cf fl'); + } - entityEditor - .state(_state) - .entityID(_entityID) - .on('choose', showList); - var wrap = selection$$1.selectAll('.panewrap') - .data([0]); + item.choose = function() { + if (!box || !sublist) return; + + if (shown) { + shown = false; + box.transition() + .duration(200) + .style('opacity', '0') + .style('max-height', '0px') + .style('padding-bottom', '0px'); + } else { + shown = true; + sublist.call(drawList, preset.members); + box.transition() + .duration(200) + .style('opacity', '1') + .style('max-height', 200 + preset.members.collection.length * 190 + 'px') + .style('padding-bottom', '20px'); + } + }; - var enter = wrap.enter() - .append('div') - .attr('class', 'panewrap'); + item.preset = preset; - enter - .append('div') - .attr('class', 'preset-list-pane pane'); + return item; + } - enter - .append('div') - .attr('class', 'entity-editor-pane pane'); - wrap = wrap.merge(enter); - var presetPane = wrap.selectAll('.preset-list-pane'); - var editorPane = wrap.selectAll('.entity-editor-pane'); + function PresetItem(preset) { + function item(selection$$1) { + var wrap = selection$$1.append('div') + .attr('class', 'preset-list-button-wrap col12'); - var graph = context.graph(), - entity = context.entity(_entityID), - showEditor = _state === 'hover' || - entity.isUsed(graph) || - entity.isHighwayIntersection(graph); + wrap.append('button') + .attr('class', 'preset-list-button') + .call(uiPresetIcon() + .geometry(context.geometry(id)) + .preset(preset)) + .on('click', item.choose) + .append('div') + .attr('class', 'label') + .text(preset.name()); - if (showEditor) { - wrap.style('right', '0%'); - editorPane.call(entityEditor); - } else { - wrap.style('right', '-100%'); - presetPane.call(presetList); - } + wrap.call(item.reference.button); + selection$$1.call(item.reference.body); + } - var footer = selection$$1.selectAll('.footer') - .data([0]); + item.choose = function() { + context.presets().choose(preset); - footer = footer.enter() - .append('div') - .attr('class', 'footer') - .merge(footer); + context.perform( + actionChangePreset(id, currentPreset, preset), + t('operations.change_tags.annotation') + ); - footer - .call(uiViewOnOSM(context).entityID(_entityID)); + dispatch$$1.call('choose', this, preset); + }; + item.help = function() { + event.stopPropagation(); + item.reference.toggle(); + }; - function showList(preset) { - wrap.transition() - .styleTween('right', function() { return d3_interpolate('0%', '-100%'); }); + item.preset = preset; + item.reference = uiTagReference(preset.reference(context.geometry(id)), context); - presetPane - .call(presetList.preset(preset).autofocus(true)); - } + return item; + } - function setPreset(preset) { - wrap.transition() - .styleTween('right', function() { return d3_interpolate('-100%', '0%'); }); + presetList.autofocus = function(_) { + if (!arguments.length) return autofocus; + autofocus = _; + return presetList; + }; - editorPane - .call(entityEditor.preset(preset)); - } - } + presetList.entityID = function(_) { + if (!arguments.length) return id; + id = _; + presetList.preset(context.presets().match(context.entity(id), context.graph())); + return presetList; + }; - inspector.state = function(_) { - if (!arguments.length) return _state; - _state = _; - entityEditor.state(_state); - // remove any old field help overlay that might have gotten attached to the inspector - d3_selectAll('.field-help-body').remove(); + presetList.preset = function(_) { + if (!arguments.length) return currentPreset; + currentPreset = _; + return presetList; + }; - return inspector; - }; + return utilRebind(presetList, dispatch$$1, 'on'); + } - inspector.entityID = function(_) { - if (!arguments.length) return _entityID; - _entityID = _; - return inspector; - }; + function uiViewOnOSM(context) { + var id; + function viewOnOSM(selection) { + var entity = context.entity(id); - inspector.newFeature = function(_) { - if (!arguments.length) return _newFeature; - _newFeature = _; - return inspector; - }; + selection.style('display', entity.isNew() ? 'none' : null); + var link = selection.selectAll('.view-on-osm') + .data([0]); - return inspector; -} + var enter = link.enter() + .append('a') + .attr('class', 'view-on-osm') + .attr('target', '_blank') + .call(svgIcon('#icon-out-link', 'inline')); -function uiSidebar(context) { - var inspector = uiInspector(context), - current; + enter + .append('span') + .text(t('inspector.view_on_osm')); + link + .merge(enter) + .attr('href', context.connection().entityURL(entity)); + } - function sidebar(selection) { - var featureListWrap = selection - .append('div') - .attr('class', 'feature-list-pane') - .call(uiFeatureList(context)); + viewOnOSM.entityID = function(_) { + if (!arguments.length) return id; + id = _; + return viewOnOSM; + }; - var inspectorWrap = selection - .append('div') - .attr('class', 'inspector-hidden inspector-wrap fr'); + return viewOnOSM; + } + function uiInspector(context) { + var presetList = uiPresetList(context); + var entityEditor = uiEntityEditor(context); + var _state = 'select'; + var _entityID; + var _newFeature = false; + + + function inspector(selection$$1) { + presetList + .entityID(_entityID) + .autofocus(_newFeature) + .on('choose', setPreset); + + entityEditor + .state(_state) + .entityID(_entityID) + .on('choose', showList); + + var wrap = selection$$1.selectAll('.panewrap') + .data([0]); + + var enter = wrap.enter() + .append('div') + .attr('class', 'panewrap'); + + enter + .append('div') + .attr('class', 'preset-list-pane pane'); + + enter + .append('div') + .attr('class', 'entity-editor-pane pane'); + + wrap = wrap.merge(enter); + var presetPane = wrap.selectAll('.preset-list-pane'); + var editorPane = wrap.selectAll('.entity-editor-pane'); + + var graph = context.graph(), + entity = context.entity(_entityID), + showEditor = _state === 'hover' || + entity.isUsed(graph) || + entity.isHighwayIntersection(graph); + + if (showEditor) { + wrap.style('right', '0%'); + editorPane.call(entityEditor); + } else { + wrap.style('right', '-100%'); + presetPane.call(presetList); + } - function hover(id) { - if (!current && context.hasEntity(id)) { - featureListWrap - .classed('inspector-hidden', true); + var footer = selection$$1.selectAll('.footer') + .data([0]); - inspectorWrap - .classed('inspector-hidden', false) - .classed('inspector-hover', true); + footer = footer.enter() + .append('div') + .attr('class', 'footer') + .merge(footer); - if (inspector.entityID() !== id || inspector.state() !== 'hover') { - inspector - .state('hover') - .entityID(id); + footer + .call(uiViewOnOSM(context).entityID(_entityID)); - inspectorWrap - .call(inspector); - } - } else if (!current) { - featureListWrap - .classed('inspector-hidden', false); - inspectorWrap - .classed('inspector-hidden', true); - inspector - .state('hide'); - } - } + function showList(preset) { + wrap.transition() + .styleTween('right', function() { return interpolate('0%', '-100%'); }); + presetPane + .call(presetList.preset(preset).autofocus(true)); + } - sidebar.hover = throttle(hover, 200); + function setPreset(preset) { + wrap.transition() + .styleTween('right', function() { return interpolate('-100%', '0%'); }); - sidebar.select = function(id, newFeature) { - if (!current && id) { - featureListWrap - .classed('inspector-hidden', true); + editorPane + .call(entityEditor.preset(preset)); + } + } - inspectorWrap - .classed('inspector-hidden', false) - .classed('inspector-hover', false); - if (inspector.entityID() !== id || inspector.state() !== 'select') { - inspector - .state('select') - .entityID(id) - .newFeature(newFeature); + inspector.state = function(_) { + if (!arguments.length) return _state; + _state = _; + entityEditor.state(_state); - inspectorWrap - .call(inspector); - } + // remove any old field help overlay that might have gotten attached to the inspector + d3_selectAll('.field-help-body').remove(); - } else if (!current) { - featureListWrap - .classed('inspector-hidden', false); - inspectorWrap - .classed('inspector-hidden', true); - inspector - .state('hide'); - } - }; + return inspector; + }; - sidebar.show = function(component) { - featureListWrap - .classed('inspector-hidden', true); - inspectorWrap - .classed('inspector-hidden', true); + inspector.entityID = function(_) { + if (!arguments.length) return _entityID; + _entityID = _; + return inspector; + }; - if (current) current.remove(); - current = selection - .append('div') - .attr('class', 'sidebar-component') - .call(component); - }; + inspector.newFeature = function(_) { + if (!arguments.length) return _newFeature; + _newFeature = _; + return inspector; + }; - sidebar.hide = function() { - featureListWrap - .classed('inspector-hidden', false); - inspectorWrap - .classed('inspector-hidden', true); - if (current) current.remove(); - current = null; - }; - } + return inspector; + } + function uiSidebar(context) { + var inspector = uiInspector(context), + current; - sidebar.hover = function() {}; - sidebar.hover.cancel = function() {}; - sidebar.select = function() {}; - sidebar.show = function() {}; - sidebar.hide = function() {}; - return sidebar; -} + function sidebar(selection) { + var featureListWrap = selection + .append('div') + .attr('class', 'feature-list-pane') + .call(uiFeatureList(context)); -function uiSpinner(context) { - var osm = context.connection(); + var inspectorWrap = selection + .append('div') + .attr('class', 'inspector-hidden inspector-wrap fr'); - return function(selection) { - var img = selection - .append('img') - .attr('src', context.imagePath('loader-black.gif')) - .style('opacity', 0); - - if (osm) { - osm - .on('loading.spinner', function() { - img.transition() - .style('opacity', 1); - }) - .on('loaded.spinner', function() { - img.transition() - .style('opacity', 0); - }); - } - }; -} - -function uiSplash(context) { - - return function(selection) { - if (context.storage('sawSplash')) - return; - - context.storage('sawSplash', true); - - var modalSelection = uiModal(selection); - - modalSelection.select('.modal') - .attr('class', 'modal-splash modal col6'); - - var introModal = modalSelection.select('.content') - .append('div') - .attr('class', 'fillL'); - - introModal - .append('div') - .attr('class','modal-section cf') - .append('h3').text(t('splash.welcome')); - - introModal - .append('div') - .attr('class','modal-section') - .append('p') - .html(t('splash.text', { - version: context.version, - website: '
    ideditor.com', - github: 'github.com' - })); - - var buttonWrap = introModal - .append('div') - .attr('class', 'modal-actions cf'); - - var walkthrough = buttonWrap - .append('button') - .attr('class', 'walkthrough col6') - .on('click', function() { - context.container().call(uiIntro(context)); - modalSelection.close(); - }); - walkthrough - .append('svg') - .attr('class', 'logo logo-walkthrough') - .append('use') - .attr('xlink:href', '#logo-walkthrough'); + function hover(id) { + if (!current && context.hasEntity(id)) { + featureListWrap + .classed('inspector-hidden', true); - walkthrough - .append('div') - .text(t('splash.walkthrough')); + inspectorWrap + .classed('inspector-hidden', false) + .classed('inspector-hover', true); - var startEditing = buttonWrap - .append('button') - .attr('class', 'start-editing col6') - .on('click', modalSelection.close); + if (inspector.entityID() !== id || inspector.state() !== 'hover') { + inspector + .state('hover') + .entityID(id); - startEditing - .append('svg') - .attr('class', 'logo logo-features') - .append('use') - .attr('xlink:href', '#logo-features'); + inspectorWrap + .call(inspector); + } - startEditing - .append('div') - .text(t('splash.start')); + } else if (!current) { + featureListWrap + .classed('inspector-hidden', false); + inspectorWrap + .classed('inspector-hidden', true); + inspector + .state('hide'); + } + } - modalSelection.select('button.close') - .attr('class','hide'); + sidebar.hover = throttle(hover, 200); - }; -} - -function uiStatus(context) { - var osm = context.connection(); - - - return function(selection$$1) { - if (!osm) return; - - function update() { - osm.status(function(err, apiStatus) { - selection$$1.html(''); - - if (err) { - if (apiStatus === 'connectionSwitched') { - // if the connection was just switched, we can't rely on - // the status (we're getting the status of the previous api) - return; - - } else if (apiStatus === 'rateLimited') { - selection$$1 - .text(t('status.rateLimit')) - .append('a') - .attr('class', 'api-status-login') - .attr('target', '_blank') - .call(svgIcon('#icon-out-link', 'inline')) - .append('span') - .text(t('login')) - .on('click.login', function() { - event.preventDefault(); - osm.authenticate(); - }); - } else { - // eslint-disable-next-line no-warning-comments - // TODO: nice messages for different error types - selection$$1.text(t('status.error')); - } - - } else if (apiStatus === 'readonly') { - selection$$1.text(t('status.readonly')); - } else if (apiStatus === 'offline') { - selection$$1.text(t('status.offline')); - } - - selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus)); - }); - } - osm.on('change', function() { update(selection$$1); }); + sidebar.select = function(id, newFeature) { + if (!current && id) { + featureListWrap + .classed('inspector-hidden', true); - window.setInterval(update, 90000); - update(selection$$1); - }; -} - -function uiUndoRedo(context) { - var commands = [{ - id: 'undo', - cmd: uiCmd('⌘Z'), - action: function() { if (editable()) context.undo(); }, - annotation: function() { return context.history().undoAnnotation(); } - }, { - id: 'redo', - cmd: uiCmd('⌘⇧Z'), - action: function() { if (editable()) context.redo(); }, - annotation: function() { return context.history().redoAnnotation(); } - }]; + inspectorWrap + .classed('inspector-hidden', false) + .classed('inspector-hover', false); + if (inspector.entityID() !== id || inspector.state() !== 'select') { + inspector + .state('select') + .entityID(id) + .newFeature(newFeature); - function editable() { - var mode = context.mode(); - return context.editable() && mode && mode.id !== 'save'; - } + inspectorWrap + .call(inspector); + } + } else if (!current) { + featureListWrap + .classed('inspector-hidden', false); + inspectorWrap + .classed('inspector-hidden', true); + inspector + .state('hide'); + } + }; - return function(selection$$1) { - var tooltipBehavior = tooltip() - .placement('bottom') - .html(true) - .title(function (d) { - return uiTooltipHtml(d.annotation() ? - t(d.id + '.tooltip', {action: d.annotation()}) : - t(d.id + '.nothing'), d.cmd); - }); - var buttons = selection$$1.selectAll('button') - .data(commands) - .enter() - .append('button') - .attr('class', function(d) { return 'col6 disabled ' + d.id + '-button'; }) - .on('click', function(d) { return d.action(); }) - .call(tooltipBehavior); - - buttons.each(function(d) { - var iconName = d.id; - if (textDirection === 'rtl') { - if (iconName === 'undo') { - iconName = 'redo'; - } else if (iconName === 'redo') { - iconName = 'undo'; - } - } - d3_select(this) - .call(svgIcon('#icon-' + iconName)); - }); + sidebar.show = function(component) { + featureListWrap + .classed('inspector-hidden', true); + inspectorWrap + .classed('inspector-hidden', true); - var keybinding = d3keybinding('undo') - .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); }) - .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); }); + if (current) current.remove(); + current = selection + .append('div') + .attr('class', 'sidebar-component') + .call(component); + }; - d3_select(document) - .call(keybinding); + sidebar.hide = function() { + featureListWrap + .classed('inspector-hidden', false); + inspectorWrap + .classed('inspector-hidden', true); - var debouncedUpdate = debounce(update, 500, { leading: true, trailing: true }); + if (current) current.remove(); + current = null; + }; + } - context.map() - .on('move.undo_redo', debouncedUpdate) - .on('drawn.undo_redo', debouncedUpdate); - context.history() - .on('change.undo_redo', update); + sidebar.hover = function() {}; + sidebar.hover.cancel = function() {}; + sidebar.select = function() {}; + sidebar.show = function() {}; + sidebar.hide = function() {}; - context - .on('enter.undo_redo', update); + return sidebar; + } + function uiSpinner(context) { + var osm = context.connection(); + + + return function(selection) { + var img = selection + .append('img') + .attr('src', context.imagePath('loader-black.gif')) + .style('opacity', 0); + + if (osm) { + osm + .on('loading.spinner', function() { + img.transition() + .style('opacity', 1); + }) + .on('loaded.spinner', function() { + img.transition() + .style('opacity', 0); + }); + } + }; + } - function update() { - buttons - .property('disabled', !editable()) - .classed('disabled', function(d) { return !d.annotation(); }) - .each(function() { - var selection$$1 = d3_select(this); - if (selection$$1.property('tooltipVisible')) { - selection$$1.call(tooltipBehavior.show); - } - }); - } - }; -} - -// these are module variables so they are preserved through a ui.restart() -var sawVersion = null, - isNewVersion = false, - isNewUser = false; - - -function uiVersion(context) { - - var currVersion = context.version, - matchedVersion = currVersion.match(/\d\.\d\.\d.*/); - - if (sawVersion === null && matchedVersion !== null) { - isNewVersion = (context.storage('sawVersion') !== currVersion); - isNewUser = !context.storage('sawSplash'); - context.storage('sawVersion', currVersion); - sawVersion = currVersion; - } - - return function(selection) { - selection - .append('a') - .attr('target', '_blank') - .attr('tabindex', -1) - .attr('href', 'https://github.com/openstreetmap/iD') - .text(currVersion); - - // only show new version indicator to users that have used iD before - if (isNewVersion && !isNewUser) { - selection - .append('div') - .attr('class', 'badge') - .append('a') - .attr('target', '_blank') - .attr('tabindex', -1) - .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CHANGELOG.md#whats-new') - .call(svgIcon('#gift-11')) - .call(tooltip() - .title(t('version.whats_new', { version: currVersion })) - .placement('top') - ); - } - }; -} - -function uiZoom(context) { - var zooms = [{ - id: 'zoom-in', - icon: 'plus', - title: t('zoom.in'), - action: context.zoomIn, - key: '+' - }, { - id: 'zoom-out', - icon: 'minus', - title: t('zoom.out'), - action: context.zoomOut, - key: '-' - }]; + function uiSplash(context) { + return function(selection) { + if (context.storage('sawSplash')) + return; - function zoomIn() { - event.preventDefault(); - context.zoomIn(); - } + context.storage('sawSplash', true); + var modalSelection = uiModal(selection); - function zoomOut() { - event.preventDefault(); - context.zoomOut(); - } + modalSelection.select('.modal') + .attr('class', 'modal-splash modal col6'); + var introModal = modalSelection.select('.content') + .append('div') + .attr('class', 'fillL'); - function zoomInFurther() { - event.preventDefault(); - context.zoomInFurther(); - } + introModal + .append('div') + .attr('class','modal-section cf') + .append('h3').text(t('splash.welcome')); + introModal + .append('div') + .attr('class','modal-section') + .append('p') + .html(t('splash.text', { + version: context.version, + website: 'ideditor.com', + github: 'github.com' + })); - function zoomOutFurther() { - event.preventDefault(); - context.zoomOutFurther(); - } + var buttonWrap = introModal + .append('div') + .attr('class', 'modal-actions cf'); + var walkthrough = buttonWrap + .append('button') + .attr('class', 'walkthrough col6') + .on('click', function() { + context.container().call(uiIntro(context)); + modalSelection.close(); + }); - return function(selection$$1) { - var button = selection$$1.selectAll('button') - .data(zooms) - .enter() - .append('button') - .attr('tabindex', -1) - .attr('class', function(d) { return d.id; }) - .on('click.editor', function(d) { d.action(); }) - .call(tooltip() - .placement((textDirection === 'rtl') ? 'right' : 'left') - .html(true) - .title(function(d) { - return uiTooltipHtml(d.title, d.key); - }) - ); + walkthrough + .append('svg') + .attr('class', 'logo logo-walkthrough') + .append('use') + .attr('xlink:href', '#logo-walkthrough'); - button.each(function(d) { - d3_select(this) - .call(svgIcon('#icon-' + d.icon, 'light')); - }); + walkthrough + .append('div') + .text(t('splash.walkthrough')); - var keybinding = d3keybinding('zoom'); + var startEditing = buttonWrap + .append('button') + .attr('class', 'start-editing col6') + .on('click', modalSelection.close); - ['plus', 'ffplus', '=', 'ffequals'].forEach(function(key) { - keybinding.on([key], zoomIn); - keybinding.on([uiCmd('⌘' + key)], zoomInFurther); - }); + startEditing + .append('svg') + .attr('class', 'logo logo-features') + .append('use') + .attr('xlink:href', '#logo-features'); - ['_', '-', 'ffminus', 'dash'].forEach(function(key) { - keybinding.on([key], zoomOut); - keybinding.on([uiCmd('⌘' + key)], zoomOutFurther); - }); + startEditing + .append('div') + .text(t('splash.start')); - d3_select(document) - .call(keybinding); - }; -} -function uiInit(context) { - var uiInitCounter = 0; + modalSelection.select('button.close') + .attr('class','hide'); + }; + } - function render(container) { - container - .attr('dir', textDirection); + function uiStatus(context) { + var osm = context.connection(); + + + return function(selection$$1) { + if (!osm) return; + + function update() { + osm.status(function(err, apiStatus) { + selection$$1.html(''); + + if (err) { + if (apiStatus === 'connectionSwitched') { + // if the connection was just switched, we can't rely on + // the status (we're getting the status of the previous api) + return; + + } else if (apiStatus === 'rateLimited') { + selection$$1 + .text(t('status.rateLimit')) + .append('a') + .attr('class', 'api-status-login') + .attr('target', '_blank') + .call(svgIcon('#icon-out-link', 'inline')) + .append('span') + .text(t('login')) + .on('click.login', function() { + event.preventDefault(); + osm.authenticate(); + }); + } else { + // eslint-disable-next-line no-warning-comments + // TODO: nice messages for different error types + selection$$1.text(t('status.error')); + } + + } else if (apiStatus === 'readonly') { + selection$$1.text(t('status.readonly')); + } else if (apiStatus === 'offline') { + selection$$1.text(t('status.offline')); + } + + selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus)); + }); + } - var map = context.map(); + osm.on('change', function() { update(selection$$1); }); - var hash = behaviorHash(context); - hash(); + window.setInterval(update, 90000); + update(selection$$1); + }; + } - if (!hash.hadHash) { - map.centerZoom([0, 0], 2); - } + function uiUndoRedo(context) { + var commands = [{ + id: 'undo', + cmd: uiCmd('⌘Z'), + action: function() { if (editable()) context.undo(); }, + annotation: function() { return context.history().undoAnnotation(); } + }, { + id: 'redo', + cmd: uiCmd('⌘⇧Z'), + action: function() { if (editable()) context.redo(); }, + annotation: function() { return context.history().redoAnnotation(); } + }]; + + + function editable() { + var mode = context.mode(); + return context.editable() && mode && mode.id !== 'save'; + } - container - .append('svg') - .attr('id', 'defs') - .call(svgDefs(context)); - - container - .append('div') - .attr('id', 'sidebar') - .attr('class', 'col4') - .call(ui.sidebar); - - var content = container - .append('div') - .attr('id', 'content') - .attr('class', 'active'); - - var bar = content - .append('div') - .attr('id', 'bar') - .attr('class', 'fillD'); - - content - .append('div') - .attr('id', 'map') - .attr('dir', 'ltr') - .call(map); - - content - .call(uiMapInMap(context)) - .call(uiInfo(context)) - .call(uiNotice(context)); - - bar - .append('div') - .attr('class', 'spacer col4'); - - var limiter = bar.append('div') - .attr('class', 'limiter'); - - limiter - .append('div') - .attr('class', 'button-wrap joined col3') - .call(uiModes(context), limiter); - - limiter - .append('div') - .attr('class', 'button-wrap joined col1') - .call(uiUndoRedo(context)); - - limiter - .append('div') - .attr('class', 'button-wrap col1') - .call(uiSave(context)); - - bar - .append('div') - .attr('class', 'full-screen') - .call(uiFullScreen(context)); - - bar - .append('div') - .attr('class', 'spinner') - .call(uiSpinner(context)); - - - var controls = bar - .append('div') - .attr('class', 'map-controls'); - - controls - .append('div') - .attr('class', 'map-control zoombuttons') - .call(uiZoom(context)); - - controls - .append('div') - .attr('class', 'map-control geolocate-control') - .call(uiGeolocate(context)); - - controls - .append('div') - .attr('class', 'map-control background-control') - .call(uiBackground(context)); - - controls - .append('div') - .attr('class', 'map-control map-data-control') - .call(uiMapData(context)); - - controls - .append('div') - .attr('class', 'map-control help-control') - .call(uiHelp(context)); - - - var about = content - .append('div') - .attr('id', 'about'); - - about - .append('div') - .attr('id', 'attrib') - .attr('dir', 'ltr') - .call(uiAttribution(context)); - - about - .append('div') - .attr('class', 'api-status') - .call(uiStatus(context)); - - - var footer = about - .append('div') - .attr('id', 'footer') - .attr('class', 'fillD'); - - footer - .append('div') - .attr('id', 'flash-wrap') - .attr('class', 'footer-hide'); - - var footerWrap = footer - .append('div') - .attr('id', 'footer-wrap') - .attr('class', 'footer-show'); - - footerWrap - .append('div') - .attr('id', 'scale-block') - .call(uiScale(context)); - - var aboutList = footerWrap - .append('div') - .attr('id', 'info-block') - .append('ul') - .attr('id', 'about-list'); - - if (!context.embed()) { - aboutList - .call(uiAccount(context)); - } - aboutList - .append('li') - .attr('class', 'version') - .call(uiVersion(context)); - - var issueLinks = aboutList - .append('li'); - - issueLinks - .append('a') - .attr('target', '_blank') - .attr('tabindex', -1) - .attr('href', 'https://github.com/openstreetmap/iD/issues') - .call(svgIcon('#icon-bug', 'light')) - .call(tooltip().title(t('report_a_bug')).placement('top')); - - issueLinks - .append('a') - .attr('target', '_blank') - .attr('tabindex', -1) - .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating') - .call(svgIcon('#icon-translate', 'light')) - .call(tooltip().title(t('help_translate')).placement('top')); - - aboutList - .append('li') - .attr('class', 'feature-warning') - .attr('tabindex', -1) - .call(uiFeatureInfo(context)); - - aboutList - .append('li') - .attr('class', 'user-list') - .attr('tabindex', -1) - .call(uiContributors(context)); - - - var photoviewer = content - .append('div') - .attr('id', 'photoviewer') - .classed('al', true) // 'al'=left, 'ar'=right - .classed('hide', true); - - photoviewer - .append('button') - .attr('class', 'thumb-hide') - .on('click', function () { - if (services.mapillary) { services.mapillary.hideViewer(); } - if (services.openstreetcam) { services.openstreetcam.hideViewer(); } - }) - .append('div') - .call(svgIcon('#icon-close')); - - - window.onbeforeunload = function() { - return context.save(); - }; + return function(selection$$1) { + var tooltipBehavior = tooltip() + .placement('bottom') + .html(true) + .title(function (d) { + return uiTooltipHtml(d.annotation() ? + t(d.id + '.tooltip', {action: d.annotation()}) : + t(d.id + '.nothing'), d.cmd); + }); + + var buttons = selection$$1.selectAll('button') + .data(commands) + .enter() + .append('button') + .attr('class', function(d) { return 'col6 disabled ' + d.id + '-button'; }) + .on('click', function(d) { return d.action(); }) + .call(tooltipBehavior); + + buttons.each(function(d) { + var iconName = d.id; + if (textDirection === 'rtl') { + if (iconName === 'undo') { + iconName = 'redo'; + } else if (iconName === 'redo') { + iconName = 'undo'; + } + } + select(this) + .call(svgIcon('#icon-' + iconName)); + }); - window.onunload = function() { - context.history().unlock(); - }; + var keybinding = d3keybinding('undo') + .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); }) + .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); }); - var mapDimensions = map.dimensions(); + select(document) + .call(keybinding); - function onResize() { - mapDimensions = utilGetDimensions(content, true); - map.dimensions(mapDimensions); - } + var debouncedUpdate = debounce(update, 500, { leading: true, trailing: true }); - d3_select(window) - .on('resize.editor', onResize); + context.map() + .on('move.undo_redo', debouncedUpdate) + .on('drawn.undo_redo', debouncedUpdate); - onResize(); + context.history() + .on('change.undo_redo', update); - function pan(d) { - return function() { - event.preventDefault(); - context.pan(d, 100); - }; - } + context + .on('enter.undo_redo', update); - // pan amount - var pa = 80; + function update() { + buttons + .property('disabled', !editable()) + .classed('disabled', function(d) { return !d.annotation(); }) + .each(function() { + var selection$$1 = select(this); + if (selection$$1.property('tooltipVisible')) { + selection$$1.call(tooltipBehavior.show); + } + }); + } + }; + } - var keybinding = d3keybinding('main') - .on('⌫', function() { event.preventDefault(); }) - .on('←', pan([pa, 0])) - .on('↑', pan([0, pa])) - .on('→', pan([-pa, 0])) - .on('↓', pan([0, -pa])) - .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0])) - .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]])) - .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0])) - .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]])); + // these are module variables so they are preserved through a ui.restart() + var sawVersion = null, + isNewVersion = false, + isNewUser = false; - d3_select(document) - .call(keybinding); - context.enter(modeBrowse(context)); + function uiVersion(context) { - if (!uiInitCounter++) { - if (!hash.startWalkthrough) { - context.container() - .call(uiSplash(context)) - .call(uiRestore(context)); - } + var currVersion = context.version, + matchedVersion = currVersion.match(/\d\.\d\.\d.*/); - context.container() - .call(uiShortcuts(context)); - } + if (sawVersion === null && matchedVersion !== null) { + isNewVersion = (context.storage('sawVersion') !== currVersion); + isNewUser = !context.storage('sawSplash'); + context.storage('sawVersion', currVersion); + sawVersion = currVersion; + } - var osm = context.connection(), - auth = uiLoading(context).message(t('loading_auth')).blocking(true); - - if (osm && auth) { - osm - .on('authLoading.ui', function() { - context.container() - .call(auth); - }) - .on('authDone.ui', function() { - auth.close(); - }); - } + return function(selection) { + selection + .append('a') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', 'https://github.com/openstreetmap/iD') + .text(currVersion); + + // only show new version indicator to users that have used iD before + if (isNewVersion && !isNewUser) { + selection + .append('div') + .attr('class', 'badge') + .append('a') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CHANGELOG.md#whats-new') + .call(svgIcon('#gift-11')) + .call(tooltip() + .title(t('version.whats_new', { version: currVersion })) + .placement('top') + ); + } + }; + } - uiInitCounter++; + function uiZoom(context) { + var zooms = [{ + id: 'zoom-in', + icon: 'plus', + title: t('zoom.in'), + action: context.zoomIn, + key: '+' + }, { + id: 'zoom-out', + icon: 'minus', + title: t('zoom.out'), + action: context.zoomOut, + key: '-' + }]; + + + function zoomIn() { + event.preventDefault(); + context.zoomIn(); + } - if (hash.startWalkthrough) { - hash.startWalkthrough = false; - context.container().call(uiIntro(context)); - } - } + function zoomOut() { + event.preventDefault(); + context.zoomOut(); + } - var renderCallback; - function ui(node, callback) { - renderCallback = callback; - var container = d3_select(node); - context.container(container); - context.loadLocale(function(err) { - if (!err) { - render(container); - } - if (callback) { - callback(err); - } - }); - } + function zoomInFurther() { + event.preventDefault(); + context.zoomInFurther(); + } - ui.restart = function(arg) { - context.locale(arg); - context.loadLocale(function(err) { - if (!err) { - context.container().selectAll('*').remove(); - render(context.container()); - if (renderCallback) renderCallback(); - } - }); - }; + function zoomOutFurther() { + event.preventDefault(); + context.zoomOutFurther(); + } - ui.sidebar = uiSidebar(context); + return function(selection$$1) { + var button = selection$$1.selectAll('button') + .data(zooms) + .enter() + .append('button') + .attr('tabindex', -1) + .attr('class', function(d) { return d.id; }) + .on('click.editor', function(d) { d.action(); }) + .call(tooltip() + .placement((textDirection === 'rtl') ? 'right' : 'left') + .html(true) + .title(function(d) { + return uiTooltipHtml(d.title, d.key); + }) + ); + + button.each(function(d) { + select(this) + .call(svgIcon('#icon-' + d.icon, 'light')); + }); - return ui; -} + var keybinding = d3keybinding('zoom'); -function uiChangesetEditor(context) { - var dispatch$$1 = dispatch('change'), - formFields = uiFormFields(context), - fieldsArr, - tags, - changesetId; + ['plus', 'ffplus', '=', 'ffequals'].forEach(function(key) { + keybinding.on([key], zoomIn); + keybinding.on([uiCmd('⌘' + key)], zoomInFurther); + }); + ['_', '-', 'ffminus', 'dash'].forEach(function(key) { + keybinding.on([key], zoomOut); + keybinding.on([uiCmd('⌘' + key)], zoomOutFurther); + }); + select(document) + .call(keybinding); + }; + } - function changesetEditor(selection) { - render(selection); - } + function uiInit(context) { + var uiInitCounter = 0; - function render(selection) { - var initial = false; + function render(container) { + container + .attr('dir', textDirection); - if (!fieldsArr) { - initial = true; - var presets = context.presets(); + var map = context.map(); - fieldsArr = [ - uiField(context, presets.field('comment'), null, { show: true, revert: false }), - uiField(context, presets.field('source'), null, { show: false, revert: false }), - uiField(context, presets.field('hashtags'), null, { show: false, revert: false }), - ]; + var hash = behaviorHash(context); + hash(); - fieldsArr.forEach(function(field) { - field - .on('change', function(t$$1, onInput) { - dispatch$$1.call('change', field, t$$1, onInput); - }); - }); - } + if (!hash.hadHash) { + map.centerZoom([0, 0], 2); + } - fieldsArr.forEach(function(field) { - field - .tags(tags); - }); + container + .append('svg') + .attr('id', 'defs') + .call(svgDefs(context)); + + container + .append('div') + .attr('id', 'sidebar') + .attr('class', 'col4') + .call(ui.sidebar); + + var content = container + .append('div') + .attr('id', 'content') + .attr('class', 'active'); + + var bar = content + .append('div') + .attr('id', 'bar') + .attr('class', 'fillD'); + + content + .append('div') + .attr('id', 'map') + .attr('dir', 'ltr') + .call(map); + + content + .call(uiMapInMap(context)) + .call(uiInfo(context)) + .call(uiNotice(context)); + + bar + .append('div') + .attr('class', 'spacer col4'); + + var limiter = bar.append('div') + .attr('class', 'limiter'); + + limiter + .append('div') + .attr('class', 'button-wrap joined col3') + .call(uiModes(context), limiter); + + limiter + .append('div') + .attr('class', 'button-wrap joined col1') + .call(uiUndoRedo(context)); + + limiter + .append('div') + .attr('class', 'button-wrap col1') + .call(uiSave(context)); + + bar + .append('div') + .attr('class', 'full-screen') + .call(uiFullScreen(context)); + + bar + .append('div') + .attr('class', 'spinner') + .call(uiSpinner(context)); + + + var controls = bar + .append('div') + .attr('class', 'map-controls'); + + controls + .append('div') + .attr('class', 'map-control zoombuttons') + .call(uiZoom(context)); + + controls + .append('div') + .attr('class', 'map-control geolocate-control') + .call(uiGeolocate(context)); + + controls + .append('div') + .attr('class', 'map-control background-control') + .call(uiBackground(context)); + + controls + .append('div') + .attr('class', 'map-control map-data-control') + .call(uiMapData(context)); + + controls + .append('div') + .attr('class', 'map-control help-control') + .call(uiHelp(context)); + + + var about = content + .append('div') + .attr('id', 'about'); + + about + .append('div') + .attr('id', 'attrib') + .attr('dir', 'ltr') + .call(uiAttribution(context)); + + about + .append('div') + .attr('class', 'api-status') + .call(uiStatus(context)); + + + var footer = about + .append('div') + .attr('id', 'footer') + .attr('class', 'fillD'); + + footer + .append('div') + .attr('id', 'flash-wrap') + .attr('class', 'footer-hide'); + + var footerWrap = footer + .append('div') + .attr('id', 'footer-wrap') + .attr('class', 'footer-show'); + + footerWrap + .append('div') + .attr('id', 'scale-block') + .call(uiScale(context)); + + var aboutList = footerWrap + .append('div') + .attr('id', 'info-block') + .append('ul') + .attr('id', 'about-list'); + + if (!context.embed()) { + aboutList + .call(uiAccount(context)); + } + aboutList + .append('li') + .attr('class', 'version') + .call(uiVersion(context)); + + var issueLinks = aboutList + .append('li'); + + issueLinks + .append('a') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', 'https://github.com/openstreetmap/iD/issues') + .call(svgIcon('#icon-bug', 'light')) + .call(tooltip().title(t('report_a_bug')).placement('top')); + + issueLinks + .append('a') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating') + .call(svgIcon('#icon-translate', 'light')) + .call(tooltip().title(t('help_translate')).placement('top')); + + aboutList + .append('li') + .attr('class', 'feature-warning') + .attr('tabindex', -1) + .call(uiFeatureInfo(context)); + + aboutList + .append('li') + .attr('class', 'user-list') + .attr('tabindex', -1) + .call(uiContributors(context)); + + + var photoviewer = content + .append('div') + .attr('id', 'photoviewer') + .classed('al', true) // 'al'=left, 'ar'=right + .classed('hide', true); + + photoviewer + .append('button') + .attr('class', 'thumb-hide') + .on('click', function () { + if (services.mapillary) { services.mapillary.hideViewer(); } + if (services.openstreetcam) { services.openstreetcam.hideViewer(); } + }) + .append('div') + .call(svgIcon('#icon-close')); + + + window.onbeforeunload = function() { + return context.save(); + }; - selection - .call(formFields.fieldsArr(fieldsArr)); + window.onunload = function() { + context.history().unlock(); + }; + var mapDimensions = map.dimensions(); - if (initial) { - var commentField = selection.select('#preset-input-comment'), - commentNode = commentField.node(); - if (commentNode) { - commentNode.focus(); - commentNode.select(); - } + function onResize() { + mapDimensions = utilGetDimensions(content, true); + map.dimensions(mapDimensions); + } - // trigger a 'blur' event so that comment field can be cleaned - // and checked for hashtags, even if retrieved from localstorage - utilTriggerEvent(commentField, 'blur'); - - var osm = context.connection(); - if (osm) { - osm.userChangesets(function (err, changesets) { - if (err) return; - - var comments = changesets.map(function(changeset) { - return { - title: changeset.tags.comment, - value: changeset.tags.comment - }; - }); - - commentField - .call(d3combobox() - .container(context.container()) - .caseSensitive(true) - .data(uniqBy(comments, 'title')) - ); - }); - } - } + select(window) + .on('resize.editor', onResize); - // Add warning if comment mentions Google - var hasGoogle = tags.comment.match(/google/i); - var commentWarning = selection.select('.form-field-comment').selectAll('.comment-warning') - .data(hasGoogle ? [0] : []); - - commentWarning.exit() - .transition() - .duration(200) - .style('opacity', 0) - .remove(); - - var commentEnter = commentWarning.enter() - .insert('div', '.tag-reference-body') - .attr('class', 'field-warning comment-warning') - .style('opacity', 0); - - commentEnter - .append('a') - .attr('target', '_blank') - .attr('tabindex', -1) - .call(svgIcon('#icon-alert', 'inline')) - .attr('href', t('commit.google_warning_link')) - .append('span') - .text(t('commit.google_warning')); - - commentEnter - .transition() - .duration(200) - .style('opacity', 1); - } - - - changesetEditor.tags = function(_) { - if (!arguments.length) return tags; - tags = _; - // Don't reset fieldsArr here. - return changesetEditor; - }; + onResize(); + function pan(d) { + return function() { + event.preventDefault(); + context.pan(d, 100); + }; + } - changesetEditor.changesetID = function(_) { - if (!arguments.length) return changesetId; - if (changesetId === _) return changesetEditor; - changesetId = _; - fieldsArr = null; - return changesetEditor; - }; + // pan amount + var pa = 80; - return utilRebind(changesetEditor, dispatch$$1, 'on'); -} - -/** - * This method is like `_.union` except that it accepts `iteratee` which is - * invoked for each element of each `arrays` to generate the criterion by - * which uniqueness is computed. Result values are chosen from the first - * array in which the value occurs. The iteratee is invoked with one argument: - * (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns the new array of combined values. - * @example - * - * _.unionBy([2.1], [1.2, 2.3], Math.floor); - * // => [2.1, 1.2] - * - * // The `_.property` iteratee shorthand. - * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 1 }, { 'x': 2 }] - */ -var unionBy = baseRest(function(arrays) { - var iteratee = last(arrays); - if (isArrayLikeObject(iteratee)) { - iteratee = undefined; - } - return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), baseIteratee(iteratee, 2)); -}); - -function uiCommitChanges(context) { - var detected = utilDetect(); - var _entityID; - - - function commitChanges(selection$$1) { - var history = context.history(); - var summary = history.difference().summary(); - - var container = selection$$1.selectAll('.modal-section.commit-section') - .data([0]); - - var containerEnter = container.enter() - .append('div') - .attr('class', 'commit-section modal-section fillL2'); - - containerEnter - .append('h3') - .text(t('commit.changes', { count: summary.length })); - - containerEnter - .append('ul') - .attr('class', 'changeset-list'); - - container = containerEnter - .merge(container); - - - var items = container.select('ul').selectAll('li') - .data(summary); - - var itemsEnter = items.enter() - .append('li') - .attr('class', 'change-item'); - - itemsEnter - .each(function(d) { - d3_select(this) - .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType)); - }); + var keybinding = d3keybinding('main') + .on('⌫', function() { event.preventDefault(); }) + .on('←', pan([pa, 0])) + .on('↑', pan([0, pa])) + .on('→', pan([-pa, 0])) + .on('↓', pan([0, -pa])) + .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0])) + .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]])) + .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0])) + .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]])); - itemsEnter - .append('span') - .attr('class', 'change-type') - .text(function(d) { return t('commit.' + d.changeType) + ' '; }); - - itemsEnter - .append('strong') - .attr('class', 'entity-type') - .text(function(d) { - var matched = context.presets().match(d.entity, d.graph); - return (matched && matched.name()) || utilDisplayType(d.entity.id); - }); + select(document) + .call(keybinding); - itemsEnter - .append('span') - .attr('class', 'entity-name') - .text(function(d) { - var name = utilDisplayName(d.entity) || '', - string = ''; - if (name !== '') { - string += ':'; - } - return string += ' ' + name; - }); + context.enter(modeBrowse(context)); - itemsEnter - .style('opacity', 0) - .transition() - .style('opacity', 1); + if (!uiInitCounter++) { + if (!hash.startWalkthrough) { + context.container() + .call(uiSplash(context)) + .call(uiRestore(context)); + } - items = itemsEnter - .merge(items); + context.container() + .call(uiShortcuts(context)); + } - items - .on('mouseover', mouseover) - .on('mouseout', mouseout) - .on('click', click); + var osm = context.connection(), + auth = uiLoading(context).message(t('loading_auth')).blocking(true); + + if (osm && auth) { + osm + .on('authLoading.ui', function() { + context.container() + .call(auth); + }) + .on('authDone.ui', function() { + auth.close(); + }); + } + uiInitCounter++; - // Download changeset link - var changeset = new osmChangeset().update({ id: undefined }); - var changes = history.changes(actionDiscardTags(history.difference())); + if (hash.startWalkthrough) { + hash.startWalkthrough = false; + context.container().call(uiIntro(context)); + } + } - delete changeset.id; // Export without chnageset_id - var data = JXON.stringify(changeset.osmChangeJXON(changes)); - var blob = new Blob([data], {type: 'text/xml;charset=utf-8;'}); - var fileName = 'changes.osc'; + var renderCallback; - var linkEnter = container.selectAll('.download-changes') - .data([0]) - .enter() - .append('a') - .attr('class', 'download-changes'); + function ui(node, callback) { + renderCallback = callback; + var container = select(node); + context.container(container); + context.loadLocale(function(err) { + if (!err) { + render(container); + } + if (callback) { + callback(err); + } + }); + } - if (detected.download) { // All except IE11 and Edge - linkEnter // download the data as a file - .attr('href', window.URL.createObjectURL(blob)) - .attr('download', fileName); - } else { // IE11 and Edge - linkEnter // open data uri in a new tab - .attr('target', '_blank') - .on('click.download', function() { - navigator.msSaveBlob(blob, fileName); - }); - } + ui.restart = function(arg) { + context.locale(arg); + context.loadLocale(function(err) { + if (!err) { + context.container().selectAll('*').remove(); + render(context.container()); + if (renderCallback) renderCallback(); + } + }); + }; - linkEnter - .call(svgIcon('#icon-load', 'inline')) - .append('span') - .text(t('commit.download_changes')); + ui.sidebar = uiSidebar(context); - function mouseover(d) { - if (d.entity) { - context.surface().selectAll( - utilEntityOrMemberSelector([d.entity.id], context.graph()) - ).classed('hover', true); - } - } + return ui; + } + function uiChangesetEditor(context) { + var dispatch$$1 = dispatch('change'); + var formFields = uiFormFields(context); + var _fieldsArr; + var _tags; + var _changesetID; - function mouseout() { - context.surface().selectAll('.hover') - .classed('hover', false); - } + function changesetEditor(selection) { + render(selection); + } - function click(change) { - if (change.changeType === 'deleted') { - _entityID = null; - } else { - var entity = change.entity; - _entityID = change.entity.id; - context.map().zoomTo(entity); - context.surface().selectAll(utilEntityOrMemberSelector([_entityID], context.graph())) - .classed('hover', true); - } - } - } + function render(selection) { + var initial = false; - commitChanges.entityID = function(_) { - if (!arguments.length) return _entityID; - _entityID = _; - return commitChanges; - }; + if (!_fieldsArr) { + initial = true; + var presets = context.presets(); + _fieldsArr = [ + uiField(context, presets.field('comment'), null, { show: true, revert: false }), + uiField(context, presets.field('source'), null, { show: false, revert: false }), + uiField(context, presets.field('hashtags'), null, { show: false, revert: false }), + ]; - return commitChanges; -} + _fieldsArr.forEach(function(field) { + field + .on('change', function(t$$1, onInput) { + dispatch$$1.call('change', field, t$$1, onInput); + }); + }); + } -function uiCommitWarnings(context) { + _fieldsArr.forEach(function(field) { + field + .tags(_tags); + }); - function commitWarnings(selection) { - var changes = context.history().changes(); - var warnings = context.history().validate(changes); + selection + .call(formFields.fieldsArr(_fieldsArr)); - var container = selection.selectAll('.warning-section') - .data(warnings.length ? [0] : []); - container.exit() - .remove(); + if (initial) { + var commentField = selection.select('#preset-input-comment'); + var commentNode = commentField.node(); - var containerEnter = container.enter() - .append('div') - .attr('class', 'modal-section warning-section fillL2'); + if (commentNode) { + commentNode.focus(); + commentNode.select(); + } - containerEnter - .append('h3') - .text(t('commit.warnings')); + // trigger a 'blur' event so that comment field can be cleaned + // and checked for hashtags, even if retrieved from localstorage + utilTriggerEvent(commentField, 'blur'); - containerEnter - .append('ul') - .attr('class', 'changeset-list'); + var osm = context.connection(); + if (osm) { + osm.userChangesets(function (err, changesets) { + if (err) return; - container = containerEnter - .merge(container); + var comments = changesets.map(function(changeset) { + return { + title: changeset.tags.comment, + value: changeset.tags.comment + }; + }); + commentField + .call(d3combobox() + .container(context.container()) + .caseSensitive(true) + .data(uniqBy(comments, 'title')) + ); + }); + } + } - var items = container.select('ul').selectAll('li') - .data(warnings); + // Add warning if comment mentions Google + var hasGoogle = _tags.comment.match(/google/i); + var commentWarning = selection.select('.form-field-comment').selectAll('.comment-warning') + .data(hasGoogle ? [0] : []); + + commentWarning.exit() + .transition() + .duration(200) + .style('opacity', 0) + .remove(); + + var commentEnter = commentWarning.enter() + .insert('div', '.tag-reference-body') + .attr('class', 'field-warning comment-warning') + .style('opacity', 0); + + commentEnter + .append('a') + .attr('target', '_blank') + .attr('tabindex', -1) + .call(svgIcon('#icon-alert', 'inline')) + .attr('href', t('commit.google_warning_link')) + .append('span') + .text(t('commit.google_warning')); + + commentEnter + .transition() + .duration(200) + .style('opacity', 1); + } - items.exit() - .remove(); - var itemsEnter = items.enter() - .append('li') - .attr('class', 'warning-item'); + changesetEditor.tags = function(_) { + if (!arguments.length) return _tags; + _tags = _; + // Don't reset _fieldsArr here. + return changesetEditor; + }; - itemsEnter - .call(svgIcon('#icon-alert', 'pre-text')); - itemsEnter - .append('strong') - .text(function(d) { return d.message; }); + changesetEditor.changesetID = function(_) { + if (!arguments.length) return _changesetID; + if (_changesetID === _) return changesetEditor; + _changesetID = _; + _fieldsArr = null; + return changesetEditor; + }; - itemsEnter.filter(function(d) { return d.tooltip; }) - .call(tooltip() - .title(function(d) { return d.tooltip; }) - .placement('top') - ); - items = itemsEnter - .merge(items); + return utilRebind(changesetEditor, dispatch$$1, 'on'); + } - items - .on('mouseover', mouseover) - .on('mouseout', mouseout) - .on('click', warningClick); + /** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + var unionBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), baseIteratee(iteratee, 2)); + }); + function uiCommitChanges(context) { + var detected = utilDetect(); + var _entityID; + + + function commitChanges(selection$$1) { + var history = context.history(); + var summary = history.difference().summary(); + + var container = selection$$1.selectAll('.modal-section.commit-section') + .data([0]); + + var containerEnter = container.enter() + .append('div') + .attr('class', 'commit-section modal-section fillL2'); + + containerEnter + .append('h3') + .text(t('commit.changes', { count: summary.length })); + + containerEnter + .append('ul') + .attr('class', 'changeset-list'); + + container = containerEnter + .merge(container); + + + var items = container.select('ul').selectAll('li') + .data(summary); + + var itemsEnter = items.enter() + .append('li') + .attr('class', 'change-item'); + + itemsEnter + .each(function(d) { + select(this) + .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType)); + }); + + itemsEnter + .append('span') + .attr('class', 'change-type') + .text(function(d) { return t('commit.' + d.changeType) + ' '; }); + + itemsEnter + .append('strong') + .attr('class', 'entity-type') + .text(function(d) { + var matched = context.presets().match(d.entity, d.graph); + return (matched && matched.name()) || utilDisplayType(d.entity.id); + }); + + itemsEnter + .append('span') + .attr('class', 'entity-name') + .text(function(d) { + var name = utilDisplayName(d.entity) || '', + string = ''; + if (name !== '') { + string += ':'; + } + return string += ' ' + name; + }); + + itemsEnter + .style('opacity', 0) + .transition() + .style('opacity', 1); + + items = itemsEnter + .merge(items); + + items + .on('mouseover', mouseover) + .on('mouseout', mouseout) + .on('click', click); + + + // Download changeset link + var changeset = new osmChangeset().update({ id: undefined }); + var changes = history.changes(actionDiscardTags(history.difference())); + + delete changeset.id; // Export without chnageset_id + + var data = JXON.stringify(changeset.osmChangeJXON(changes)); + var blob = new Blob([data], {type: 'text/xml;charset=utf-8;'}); + var fileName = 'changes.osc'; + + var linkEnter = container.selectAll('.download-changes') + .data([0]) + .enter() + .append('a') + .attr('class', 'download-changes'); + + if (detected.download) { // All except IE11 and Edge + linkEnter // download the data as a file + .attr('href', window.URL.createObjectURL(blob)) + .attr('download', fileName); + + } else { // IE11 and Edge + linkEnter // open data uri in a new tab + .attr('target', '_blank') + .on('click.download', function() { + navigator.msSaveBlob(blob, fileName); + }); + } - function mouseover(d) { - if (d.entity) { - context.surface().selectAll( - utilEntityOrMemberSelector([d.entity.id], context.graph()) - ).classed('hover', true); - } - } + linkEnter + .call(svgIcon('#icon-load', 'inline')) + .append('span') + .text(t('commit.download_changes')); - function mouseout() { - context.surface().selectAll('.hover') - .classed('hover', false); - } + function mouseover(d) { + if (d.entity) { + context.surface().selectAll( + utilEntityOrMemberSelector([d.entity.id], context.graph()) + ).classed('hover', true); + } + } - function warningClick(d) { - if (d.entity) { - context.map().zoomTo(d.entity); - context.enter(modeSelect(context, [d.entity.id])); - } - } + function mouseout() { + context.surface().selectAll('.hover') + .classed('hover', false); + } - } + function click(change) { + if (change.changeType === 'deleted') { + _entityID = null; + } else { + var entity = change.entity; + _entityID = change.entity.id; + context.map().zoomTo(entity); + context.surface().selectAll(utilEntityOrMemberSelector([_entityID], context.graph())) + .classed('hover', true); + } + } + } - return commitWarnings; -} -var _changeset$1; -var readOnlyTags = [ - /^_changesets_count$/, - /^created_by$/, - /^ideditor:/, - /^imagery_used$/, - /^host$/, - /^locale$/ -]; + commitChanges.entityID = function(_) { + if (!arguments.length) return _entityID; + _entityID = _; + return commitChanges; + }; -// treat most punctuation (except -, _, +, &) as hashtag delimiters - #4398 -// from https://stackoverflow.com/a/25575009 -var hashtagRegex = /(#[^\u2000-\u206F\u2E00-\u2E7F\s\\'!"#$%()*,.\/:;<=>?@\[\]^`{|}~]+)/g; + return commitChanges; + } -function uiCommit(context) { - var dispatch$$1 = dispatch('cancel', 'save'); - var _userDetails; - var _selection; + function uiCommitWarnings(context) { - var changesetEditor = uiChangesetEditor(context) - .on('change', changeTags); - var rawTagEditor = uiRawTagEditor(context) - .on('change', changeTags); - var commitChanges = uiCommitChanges(context); - var commitWarnings = uiCommitWarnings(context); + function commitWarnings(selection) { + var changes = context.history().changes(); + var warnings = context.history().validate(changes); - function commit(selection$$1) { - _selection = selection$$1; + var container = selection.selectAll('.warning-section') + .data(warnings.length ? [0] : []); - var osm = context.connection(); - if (!osm) return; + container.exit() + .remove(); - // expire stored comment and hashtags after cutoff datetime - #3947 - var commentDate = +context.storage('commentDate') || 0; - var currDate = Date.now(); - var cutoff = 2 * 86400 * 1000; // 2 days - if (commentDate > currDate || currDate - commentDate > cutoff) { - context.storage('comment', null); - context.storage('hashtags', null); - } + var containerEnter = container.enter() + .append('div') + .attr('class', 'modal-section warning-section fillL2'); - var tags; - if (!_changeset$1) { - var detected = utilDetect(); - tags = { - comment: context.storage('comment') || '', - created_by: ('iD ' + context.version).substr(0, 255), - host: detected.host.substr(0, 255), - locale: detected.locale.substr(0, 255) - }; + containerEnter + .append('h3') + .text(t('commit.warnings')); - // call findHashtags initially - this will remove stored - // hashtags if any hashtags are found in the comment - #4304 - findHashtags(tags, true); + containerEnter + .append('ul') + .attr('class', 'changeset-list'); - var hashtags = context.storage('hashtags'); - if (hashtags) { - tags.hashtags = hashtags; - } + container = containerEnter + .merge(container); - _changeset$1 = new osmChangeset({ tags: tags }); - } - tags = clone(_changeset$1.tags); - tags.imagery_used = context.history().imageryUsed().join(';').substr(0, 255); - _changeset$1 = _changeset$1.update({ tags: tags }); + var items = container.select('ul').selectAll('li') + .data(warnings); - var header = selection$$1.selectAll('.header') - .data([0]); + items.exit() + .remove(); - header.enter() - .append('div') - .attr('class', 'header fillL') - .append('h3') - .text(t('commit.title')); + var itemsEnter = items.enter() + .append('li') + .attr('class', 'warning-item'); - var body = selection$$1.selectAll('.body') - .data([0]); + itemsEnter + .call(svgIcon('#icon-alert', 'pre-text')); - body = body.enter() - .append('div') - .attr('class', 'body') - .merge(body); + itemsEnter + .append('strong') + .text(function(d) { return d.message; }); + itemsEnter.filter(function(d) { return d.tooltip; }) + .call(tooltip() + .title(function(d) { return d.tooltip; }) + .placement('top') + ); - // Changeset Section - var changesetSection = body.selectAll('.changeset-editor') - .data([0]); + items = itemsEnter + .merge(items); - changesetSection = changesetSection.enter() - .append('div') - .attr('class', 'modal-section changeset-editor') - .merge(changesetSection); + items + .on('mouseover', mouseover) + .on('mouseout', mouseout) + .on('click', warningClick); - changesetSection - .call(changesetEditor - .changesetID(_changeset$1.id) - .tags(tags) - ); + function mouseover(d) { + if (d.entity) { + context.surface().selectAll( + utilEntityOrMemberSelector([d.entity.id], context.graph()) + ).classed('hover', true); + } + } - // Warnings - body.call(commitWarnings); + function mouseout() { + context.surface().selectAll('.hover') + .classed('hover', false); + } - // Upload Explanation - var saveSection = body.selectAll('.save-section') - .data([0]); - saveSection = saveSection.enter() - .append('div') - .attr('class','modal-section save-section fillL cf') - .merge(saveSection); + function warningClick(d) { + if (d.entity) { + context.map().zoomTo(d.entity); + context.enter(modeSelect(context, [d.entity.id])); + } + } - var prose = saveSection.selectAll('.commit-info') - .data([0]); + } - prose = prose.enter() - .append('p') - .attr('class', 'commit-info') - .text(t('commit.upload_explanation')) - .merge(prose); - osm.userDetails(function(err, user) { - if (err) return; + return commitWarnings; + } - var userLink = d3_select(document.createElement('div')); + var _changeset$1; + var readOnlyTags = [ + /^changesets_count$/, + /^created_by$/, + /^ideditor:/, + /^imagery_used$/, + /^host$/, + /^locale$/ + ]; - _userDetails = user; + // treat most punctuation (except -, _, +, &) as hashtag delimiters - #4398 + // from https://stackoverflow.com/a/25575009 + var hashtagRegex = /(#[^\u2000-\u206F\u2E00-\u2E7F\s\\'!"#$%()*,.\/:;<=>?@\[\]^`{|}~]+)/g; - if (user.image_url) { - userLink - .append('img') - .attr('src', user.image_url) - .attr('class', 'icon pre-text user-icon'); - } - userLink - .append('a') - .attr('class','user-info') - .text(user.display_name) - .attr('href', osm.userURL(user.display_name)) - .attr('tabindex', -1) - .attr('target', '_blank'); + function uiCommit(context) { + var dispatch$$1 = dispatch('cancel', 'save'); + var _userDetails; + var _selection; - prose - .html(t('commit.upload_explanation_with_user', { user: userLink.html() })); - }); + var changesetEditor = uiChangesetEditor(context) + .on('change', changeTags); + var rawTagEditor = uiRawTagEditor(context) + .on('change', changeTags); + var commitChanges = uiCommitChanges(context); + var commitWarnings = uiCommitWarnings(context); - // Request Review - var requestReview = saveSection.selectAll('.request-review') - .data([0]); - - // Enter - var requestReviewEnter = requestReview.enter() - .append('div') - .attr('class', 'request-review'); - - var labelEnter = requestReviewEnter - .append('label') - .attr('for', 'commit-input-request-review'); - - labelEnter - .append('input') - .attr('type', 'checkbox') - .attr('id', 'commit-input-request-review'); - - labelEnter - .append('span') - .text(t('commit.request_review')); - - // Update - requestReview = requestReview - .merge(requestReviewEnter); - - var requestReviewInput = requestReview.selectAll('input') - .property('checked', isReviewRequested(_changeset$1.tags)) - .on('change', toggleRequestReview); - - - // Buttons - var buttonSection = saveSection.selectAll('.buttons') - .data([0]); - - // enter - var buttonEnter = buttonSection.enter() - .append('div') - .attr('class', 'buttons fillL cf'); - - buttonEnter - .append('button') - .attr('class', 'secondary-action col5 button cancel-button') - .append('span') - .attr('class', 'label') - .text(t('commit.cancel')); - - buttonEnter - .append('button') - .attr('class', 'action col5 button save-button') - .append('span') - .attr('class', 'label') - .text(t('commit.save')); - - // update - buttonSection = buttonSection - .merge(buttonEnter); - - buttonSection.selectAll('.cancel-button') - .on('click.cancel', function() { - var selectedID = commitChanges.entityID(); - dispatch$$1.call('cancel', this, selectedID); - }); + function commit(selection$$1) { + _selection = selection$$1; - buttonSection.selectAll('.save-button') - .attr('disabled', function() { - var n = d3_select('#preset-input-comment').node(); - return (n && n.value.length) ? null : true; - }) - .on('click.save', function() { - this.blur(); // avoid keeping focus on the button - #4641 - dispatch$$1.call('save', this, _changeset$1); - }); + var osm = context.connection(); + if (!osm) return; + // expire stored comment, hashtags, source after cutoff datetime - #3947 #4899 + var commentDate = +context.storage('commentDate') || 0; + var currDate = Date.now(); + var cutoff = 2 * 86400 * 1000; // 2 days + if (commentDate > currDate || currDate - commentDate > cutoff) { + context.storage('comment', null); + context.storage('hashtags', null); + context.storage('source', null); + } - // Raw Tag Editor - var tagSection = body.selectAll('.tag-section.raw-tag-editor') - .data([0]); + var tags; + if (!_changeset$1) { + var detected = utilDetect(); + tags = { + comment: context.storage('comment') || '', + created_by: ('iD ' + context.version).substr(0, 255), + host: detected.host.substr(0, 255), + locale: detected.locale.substr(0, 255) + }; + + // call findHashtags initially - this will remove stored + // hashtags if any hashtags are found in the comment - #4304 + findHashtags(tags, true); + + var hashtags = context.storage('hashtags'); + if (hashtags) { + tags.hashtags = hashtags; + } + + // iD 2.8.1 could write a literal 'undefined' here.. see #5021 + // (old source values expire after 2 days, so 'undefined' checks can go away in v2.9) + var source = context.storage('source'); + if (source && source !== 'undefined') { + tags.source = source; + } else if (source === 'undefined') { + context.storage('source', null); + } + + _changeset$1 = new osmChangeset({ tags: tags }); + } - tagSection = tagSection.enter() - .append('div') - .attr('class', 'modal-section tag-section raw-tag-editor') - .merge(tagSection); + tags = clone(_changeset$1.tags); + tags.imagery_used = context.history().imageryUsed().join(';').substr(0, 255); + _changeset$1 = _changeset$1.update({ tags: tags }); - var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty(); - tagSection - .call(rawTagEditor - .expanded(expanded) - .readOnlyTags(readOnlyTags) - .tags(clone(_changeset$1.tags)) - ); + var header = selection$$1.selectAll('.header') + .data([0]); + header.enter() + .append('div') + .attr('class', 'header fillL') + .append('h3') + .text(t('commit.title')); - // Change summary - body.call(commitChanges); + var body = selection$$1.selectAll('.body') + .data([0]); + body = body.enter() + .append('div') + .attr('class', 'body') + .merge(body); - function toggleRequestReview() { - var rr = requestReviewInput.property('checked'); - updateChangeset({ review_requested: (rr ? 'yes' : undefined) }); - var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty(); - tagSection - .call(rawTagEditor - .expanded(expanded) - .readOnlyTags(readOnlyTags) - .tags(clone(_changeset$1.tags)) - ); - } - } + // Changeset Section + var changesetSection = body.selectAll('.changeset-editor') + .data([0]); + changesetSection = changesetSection.enter() + .append('div') + .attr('class', 'modal-section changeset-editor') + .merge(changesetSection); - function changeTags(changed, onInput) { - if (changed.hasOwnProperty('comment')) { - if (changed.comment === undefined) { - changed.comment = ''; - } - if (!onInput) { - context.storage('comment', changed.comment); - context.storage('commentDate', Date.now()); - } - } + changesetSection + .call(changesetEditor + .changesetID(_changeset$1.id) + .tags(tags) + ); - updateChangeset(changed, onInput); - if (_selection) { - _selection.call(commit); - } - } + // Warnings + body.call(commitWarnings); - function findHashtags(tags, commentOnly) { - var inComment = commentTags(); - var inHashTags = hashTags(); + // Upload Explanation + var saveSection = body.selectAll('.save-section') + .data([0]); - if (inComment !== null) { // when hashtags are detected in comment... - context.storage('hashtags', null); // always remove stored hashtags - #4304 - if (commentOnly) { inHashTags = null; } // optionally override hashtags field - } - return unionBy(inComment, inHashTags, function (s) { - return s.toLowerCase(); - }); + saveSection = saveSection.enter() + .append('div') + .attr('class','modal-section save-section fillL cf') + .merge(saveSection); - // Extract hashtags from `comment` - function commentTags() { - return tags.comment - .replace(/http\S*/g, '') // drop anything that looks like a URL - #4289 - .match(hashtagRegex); - } + var prose = saveSection.selectAll('.commit-info') + .data([0]); - // Extract and clean hashtags from `hashtags` - function hashTags() { - var t$$1 = tags.hashtags || ''; - return t$$1 - .split(/[,;\s]+/) - .map(function (s) { - if (s[0] !== '#') { s = '#' + s; } // prepend '#' - var matched = s.match(hashtagRegex); - return matched && matched[0]; - }).filter(Boolean); // exclude falsey - } - } + prose = prose.enter() + .append('p') + .attr('class', 'commit-info') + .text(t('commit.upload_explanation')) + .merge(prose); + osm.userDetails(function(err, user) { + if (err) return; - function isReviewRequested(tags) { - var rr = tags.review_requested; - if (rr === undefined) return false; - rr = rr.trim().toLowerCase(); - return !(rr === '' || rr === 'no'); - } + var userLink = select(document.createElement('div')); + _userDetails = user; - function updateChangeset(changed, onInput) { - var tags = clone(_changeset$1.tags); + if (user.image_url) { + userLink + .append('img') + .attr('src', user.image_url) + .attr('class', 'icon pre-text user-icon'); + } - forEach(changed, function(v, k) { - k = k.trim().substr(0, 255); - if (readOnlyTags.indexOf(k) !== -1) return; + userLink + .append('a') + .attr('class','user-info') + .text(user.display_name) + .attr('href', osm.userURL(user.display_name)) + .attr('tabindex', -1) + .attr('target', '_blank'); - if (k !== '' && v !== undefined) { - if (onInput) { - tags[k] = v; - } else { - tags[k] = v.trim().substr(0, 255); - } - } else { - delete tags[k]; - } - }); + prose + .html(t('commit.upload_explanation_with_user', { user: userLink.html() })); + }); - if (!onInput) { - // when changing the comment, override hashtags with any found in comment. - var commentOnly = changed.hasOwnProperty('comment') && (changed.comment !== ''); - var arr = findHashtags(tags, commentOnly); - if (arr.length) { - tags.hashtags = arr.join(';').substr(0, 255); - context.storage('hashtags', tags.hashtags); - } else { - delete tags.hashtags; - context.storage('hashtags', null); - } - } - // always update userdetails, just in case user reauthenticates as someone else - if (_userDetails && _userDetails.changesets_count !== undefined) { - var changesetsCount = parseInt(_userDetails.changesets_count, 10) + 1; // #4283 - tags.changesets_count = String(changesetsCount); - - // first 100 edits - new user - if (changesetsCount <= 100) { - var s; - s = context.storage('walkthrough_completed'); - if (s) { - tags['ideditor:walkthrough_completed'] = s; - } - - s = context.storage('walkthrough_progress'); - if (s) { - tags['ideditor:walkthrough_progress'] = s; - } - - s = context.storage('walkthrough_started'); - if (s) { - tags['ideditor:walkthrough_started'] = s; - } - } - } else { - delete tags.changesets_count; - } + // Request Review + var requestReview = saveSection.selectAll('.request-review') + .data([0]); + + // Enter + var requestReviewEnter = requestReview.enter() + .append('div') + .attr('class', 'request-review'); + + var labelEnter = requestReviewEnter + .append('label') + .attr('for', 'commit-input-request-review'); + + labelEnter + .append('input') + .attr('type', 'checkbox') + .attr('id', 'commit-input-request-review'); + + labelEnter + .append('span') + .text(t('commit.request_review')); + + // Update + requestReview = requestReview + .merge(requestReviewEnter); + + var requestReviewInput = requestReview.selectAll('input') + .property('checked', isReviewRequested(_changeset$1.tags)) + .on('change', toggleRequestReview); + + + // Buttons + var buttonSection = saveSection.selectAll('.buttons') + .data([0]); + + // enter + var buttonEnter = buttonSection.enter() + .append('div') + .attr('class', 'buttons fillL cf'); + + buttonEnter + .append('button') + .attr('class', 'secondary-action col5 button cancel-button') + .append('span') + .attr('class', 'label') + .text(t('commit.cancel')); + + buttonEnter + .append('button') + .attr('class', 'action col5 button save-button') + .append('span') + .attr('class', 'label') + .text(t('commit.save')); + + // update + buttonSection = buttonSection + .merge(buttonEnter); + + buttonSection.selectAll('.cancel-button') + .on('click.cancel', function() { + var selectedID = commitChanges.entityID(); + dispatch$$1.call('cancel', this, selectedID); + }); + + buttonSection.selectAll('.save-button') + .attr('disabled', function() { + var n = select('#preset-input-comment').node(); + return (n && n.value.length) ? null : true; + }) + .on('click.save', function() { + this.blur(); // avoid keeping focus on the button - #4641 + dispatch$$1.call('save', this, _changeset$1); + }); + + + // Raw Tag Editor + var tagSection = body.selectAll('.tag-section.raw-tag-editor') + .data([0]); + + tagSection = tagSection.enter() + .append('div') + .attr('class', 'modal-section tag-section raw-tag-editor') + .merge(tagSection); + + var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty(); + tagSection + .call(rawTagEditor + .expanded(expanded) + .readOnlyTags(readOnlyTags) + .tags(clone(_changeset$1.tags)) + ); + + + // Change summary + body.call(commitChanges); + + + function toggleRequestReview() { + var rr = requestReviewInput.property('checked'); + updateChangeset({ review_requested: (rr ? 'yes' : undefined) }); + + var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty(); + tagSection + .call(rawTagEditor + .expanded(expanded) + .readOnlyTags(readOnlyTags) + .tags(clone(_changeset$1.tags)) + ); + } + } - if (!isEqual(_changeset$1.tags, tags)) { - _changeset$1 = _changeset$1.update({ tags: tags }); - } - } + function changeTags(changed, onInput) { + if (changed.hasOwnProperty('comment')) { + if (changed.comment === undefined) { + changed.comment = ''; + } + if (!onInput) { + context.storage('comment', changed.comment); + context.storage('commentDate', Date.now()); + } + } + if (changed.hasOwnProperty('source')) { + if (changed.source === undefined) { + context.storage('source', null); + } else if (!onInput) { + context.storage('source', changed.source); + context.storage('commentDate', Date.now()); + } + } + + updateChangeset(changed, onInput); - commit.reset = function() { - _changeset$1 = null; - }; + if (_selection) { + _selection.call(commit); + } + } - return utilRebind(commit, dispatch$$1, 'on'); -} + function findHashtags(tags, commentOnly) { + var inComment = commentTags(); + var inHashTags = hashTags(); -function uiConfirm(selection) { - var modalSelection = uiModal(selection); + if (inComment !== null) { // when hashtags are detected in comment... + context.storage('hashtags', null); // always remove stored hashtags - #4304 + if (commentOnly) { inHashTags = null; } // optionally override hashtags field + } + return unionBy(inComment, inHashTags, function (s) { + return s.toLowerCase(); + }); - modalSelection.select('.modal') - .classed('modal-alert', true); + // Extract hashtags from `comment` + function commentTags() { + return tags.comment + .replace(/http\S*/g, '') // drop anything that looks like a URL - #4289 + .match(hashtagRegex); + } - var section = modalSelection.select('.content'); + // Extract and clean hashtags from `hashtags` + function hashTags() { + var t$$1 = tags.hashtags || ''; + return t$$1 + .split(/[,;\s]+/) + .map(function (s) { + if (s[0] !== '#') { s = '#' + s; } // prepend '#' + var matched = s.match(hashtagRegex); + return matched && matched[0]; + }).filter(Boolean); // exclude falsey + } + } - section.append('div') - .attr('class', 'modal-section header'); - section.append('div') - .attr('class', 'modal-section message-text'); + function isReviewRequested(tags) { + var rr = tags.review_requested; + if (rr === undefined) return false; + rr = rr.trim().toLowerCase(); + return !(rr === '' || rr === 'no'); + } - var buttons = section.append('div') - .attr('class', 'modal-section buttons cf'); + function updateChangeset(changed, onInput) { + var tags = clone(_changeset$1.tags); - modalSelection.okButton = function() { - buttons - .append('button') - .attr('class', 'action col4') - .on('click.confirm', function() { - modalSelection.remove(); - }) - .text(t('confirm.okay')) - .node() - .focus(); + forEach(changed, function(v, k) { + k = k.trim().substr(0, 255); + if (readOnlyTags.indexOf(k) !== -1) return; - return modalSelection; - }; + if (k !== '' && v !== undefined) { + if (onInput) { + tags[k] = v; + } else { + tags[k] = v.trim().substr(0, 255); + } + } else { + delete tags[k]; + } + }); + if (!onInput) { + // when changing the comment, override hashtags with any found in comment. + var commentOnly = changed.hasOwnProperty('comment') && (changed.comment !== ''); + var arr = findHashtags(tags, commentOnly); + if (arr.length) { + tags.hashtags = arr.join(';').substr(0, 255); + context.storage('hashtags', tags.hashtags); + } else { + delete tags.hashtags; + context.storage('hashtags', null); + } + } - return modalSelection; -} + // always update userdetails, just in case user reauthenticates as someone else + if (_userDetails && _userDetails.changesets_count !== undefined) { + var changesetsCount = parseInt(_userDetails.changesets_count, 10) + 1; // #4283 + tags.changesets_count = String(changesetsCount); + + // first 100 edits - new user + if (changesetsCount <= 100) { + var s; + s = context.storage('walkthrough_completed'); + if (s) { + tags['ideditor:walkthrough_completed'] = s; + } + + s = context.storage('walkthrough_progress'); + if (s) { + tags['ideditor:walkthrough_progress'] = s; + } + + s = context.storage('walkthrough_started'); + if (s) { + tags['ideditor:walkthrough_started'] = s; + } + } + } else { + delete tags.changesets_count; + } -function uiConflicts(context) { - var dispatch$$1 = dispatch('cancel', 'save'); - var keybinding = d3keybinding('conflicts'); - var _origChanges; - var _conflictList; + if (!isEqual(_changeset$1.tags, tags)) { + _changeset$1 = _changeset$1.update({ tags: tags }); + } + } - function keybindingOn() { - d3_select(document) - .call(keybinding.on('⎋', cancel, true)); - } + commit.reset = function() { + _changeset$1 = null; + }; - function keybindingOff() { - d3_select(document) - .call(keybinding.off); - } - function tryAgain() { - keybindingOff(); - dispatch$$1.call('save'); - } + return utilRebind(commit, dispatch$$1, 'on'); + } - function cancel() { - keybindingOff(); - dispatch$$1.call('cancel'); - } + function uiConfirm(selection) { + var modalSelection = uiModal(selection); + modalSelection.select('.modal') + .classed('modal-alert', true); - function conflicts(selection$$1) { - keybindingOn(); + var section = modalSelection.select('.content'); - var headerEnter = selection$$1.selectAll('.header') - .data([0]) - .enter() - .append('div') - .attr('class', 'header fillL'); + section.append('div') + .attr('class', 'modal-section header'); - headerEnter - .append('button') - .attr('class', 'fr') - .on('click', cancel) - .call(svgIcon('#icon-close')); + section.append('div') + .attr('class', 'modal-section message-text'); - headerEnter - .append('h3') - .text(t('save.conflict.header')); + var buttons = section.append('div') + .attr('class', 'modal-section buttons cf'); - var bodyEnter = selection$$1.selectAll('.body') - .data([0]) - .enter() - .append('div') - .attr('class', 'body fillL'); - var conflictsHelpEnter = bodyEnter - .append('div') - .attr('class', 'conflicts-help') - .text(t('save.conflict.help')); + modalSelection.okButton = function() { + buttons + .append('button') + .attr('class', 'action col4') + .on('click.confirm', function() { + modalSelection.remove(); + }) + .text(t('confirm.okay')) + .node() + .focus(); + return modalSelection; + }; - // Download changes link - var detected = utilDetect(); - var changeset = new osmChangeset(); - delete changeset.id; // Export without changeset_id + return modalSelection; + } - var data = JXON.stringify(changeset.osmChangeJXON(_origChanges)); - var blob = new Blob([data], { type: 'text/xml;charset=utf-8;' }); - var fileName = 'changes.osc'; + function uiConflicts(context) { + var dispatch$$1 = dispatch('cancel', 'save'); + var keybinding = d3keybinding('conflicts'); + var _origChanges; + var _conflictList; - var linkEnter = conflictsHelpEnter.selectAll('.download-changes') - .append('a') - .attr('class', 'download-changes'); - if (detected.download) { // All except IE11 and Edge - linkEnter // download the data as a file - .attr('href', window.URL.createObjectURL(blob)) - .attr('download', fileName); + function keybindingOn() { + select(document) + .call(keybinding.on('⎋', cancel, true)); + } - } else { // IE11 and Edge - linkEnter // open data uri in a new tab - .attr('target', '_blank') - .on('click.download', function() { - navigator.msSaveBlob(blob, fileName); - }); - } + function keybindingOff() { + select(document) + .call(keybinding.off); + } - linkEnter - .call(svgIcon('#icon-load', 'inline')) - .append('span') - .text(t('save.conflict.download_changes')); + function tryAgain() { + keybindingOff(); + dispatch$$1.call('save'); + } + function cancel() { + keybindingOff(); + dispatch$$1.call('cancel'); + } - bodyEnter - .append('div') - .attr('class', 'conflict-container fillL3') - .call(showConflict, 0); - bodyEnter - .append('div') - .attr('class', 'conflicts-done') - .attr('opacity', 0) - .style('display', 'none') - .text(t('save.conflict.done')); + function conflicts(selection$$1) { + keybindingOn(); - var buttonsEnter = bodyEnter - .append('div') - .attr('class','buttons col12 joined conflicts-buttons'); + var headerEnter = selection$$1.selectAll('.header') + .data([0]) + .enter() + .append('div') + .attr('class', 'header fillL'); - buttonsEnter - .append('button') - .attr('disabled', _conflictList.length > 1) - .attr('class', 'action conflicts-button col6') - .text(t('save.title')) - .on('click.try_again', tryAgain); + headerEnter + .append('button') + .attr('class', 'fr') + .on('click', cancel) + .call(svgIcon('#icon-close')); - buttonsEnter - .append('button') - .attr('class', 'secondary-action conflicts-button col6') - .text(t('confirm.cancel')) - .on('click.cancel', cancel); - } + headerEnter + .append('h3') + .text(t('save.conflict.header')); + var bodyEnter = selection$$1.selectAll('.body') + .data([0]) + .enter() + .append('div') + .attr('class', 'body fillL'); - function showConflict(selection$$1, index) { - index = utilWrap(index, _conflictList.length); + var conflictsHelpEnter = bodyEnter + .append('div') + .attr('class', 'conflicts-help') + .text(t('save.conflict.help')); - var parent = d3_select(selection$$1.node().parentNode); - // enable save button if this is the last conflict being reviewed.. - if (index === _conflictList.length - 1) { - window.setTimeout(function() { - parent.select('.conflicts-button') - .attr('disabled', null); + // Download changes link + var detected = utilDetect(); + var changeset = new osmChangeset(); - parent.select('.conflicts-done') - .transition() - .attr('opacity', 1) - .style('display', 'block'); - }, 250); - } + delete changeset.id; // Export without changeset_id - var conflict = selection$$1 - .selectAll('.conflict') - .data([_conflictList[index]]); - - conflict.exit() - .remove(); - - var conflictEnter = conflict.enter() - .append('div') - .attr('class', 'conflict'); - - conflictEnter - .append('h4') - .attr('class', 'conflict-count') - .text(t('save.conflict.count', { num: index + 1, total: _conflictList.length })); - - conflictEnter - .append('a') - .attr('class', 'conflict-description') - .attr('href', '#') - .text(function(d) { return d.name; }) - .on('click', function(d) { - event.preventDefault(); - zoomToEntity(d.id); - }); + var data = JXON.stringify(changeset.osmChangeJXON(_origChanges)); + var blob = new Blob([data], { type: 'text/xml;charset=utf-8;' }); + var fileName = 'changes.osc'; - var details = conflictEnter - .append('div') - .attr('class', 'conflict-detail-container'); - - details - .append('ul') - .attr('class', 'conflict-detail-list') - .selectAll('li') - .data(function(d) { return d.details || []; }) - .enter() - .append('li') - .attr('class', 'conflict-detail-item') - .html(function(d) { return d; }); - - details - .append('div') - .attr('class', 'conflict-choices') - .call(addChoices); - - details - .append('div') - .attr('class', 'conflict-nav-buttons joined cf') - .selectAll('button') - .data(['previous', 'next']) - .enter() - .append('button') - .text(function(d) { return t('save.conflict.' + d); }) - .attr('class', 'conflict-nav-button action col6') - .attr('disabled', function(d, i) { - return (i === 0 && index === 0) || - (i === 1 && index === _conflictList.length - 1) || null; - }) - .on('click', function(d, i) { - event.preventDefault(); - - var container = parent.selectAll('.conflict-container'); - var sign = (i === 0 ? -1 : 1); - - container - .selectAll('.conflict') - .remove(); - - container - .call(showConflict, index + sign); - }); + var linkEnter = conflictsHelpEnter.selectAll('.download-changes') + .append('a') + .attr('class', 'download-changes'); - } + if (detected.download) { // All except IE11 and Edge + linkEnter // download the data as a file + .attr('href', window.URL.createObjectURL(blob)) + .attr('download', fileName); + } else { // IE11 and Edge + linkEnter // open data uri in a new tab + .attr('target', '_blank') + .on('click.download', function() { + navigator.msSaveBlob(blob, fileName); + }); + } - function addChoices(selection$$1) { - var choices = selection$$1 - .append('ul') - .attr('class', 'layer-list') - .selectAll('li') - .data(function(d) { return d.choices || []; }); + linkEnter + .call(svgIcon('#icon-load', 'inline')) + .append('span') + .text(t('save.conflict.download_changes')); + + + bodyEnter + .append('div') + .attr('class', 'conflict-container fillL3') + .call(showConflict, 0); + + bodyEnter + .append('div') + .attr('class', 'conflicts-done') + .attr('opacity', 0) + .style('display', 'none') + .text(t('save.conflict.done')); + + var buttonsEnter = bodyEnter + .append('div') + .attr('class','buttons col12 joined conflicts-buttons'); + + buttonsEnter + .append('button') + .attr('disabled', _conflictList.length > 1) + .attr('class', 'action conflicts-button col6') + .text(t('save.title')) + .on('click.try_again', tryAgain); + + buttonsEnter + .append('button') + .attr('class', 'secondary-action conflicts-button col6') + .text(t('confirm.cancel')) + .on('click.cancel', cancel); + } - // enter - var choicesEnter = choices.enter() - .append('li') - .attr('class', 'layer'); - var labelEnter = choicesEnter - .append('label'); + function showConflict(selection$$1, index) { + index = utilWrap(index, _conflictList.length); - labelEnter - .append('input') - .attr('type', 'radio') - .attr('name', function(d) { return d.id; }) - .on('change', function(d, i) { - var ul = this.parentNode.parentNode.parentNode; - ul.__data__.chosen = i; - choose(ul, d); - }); + var parent = select(selection$$1.node().parentNode); - labelEnter - .append('span') - .text(function(d) { return d.text; }); - - // update - choicesEnter - .merge(choices) - .each(function(d, i) { - var ul = this.parentNode; - if (ul.__data__.chosen === i) { - choose(ul, d); - } - }); - } + // enable save button if this is the last conflict being reviewed.. + if (index === _conflictList.length - 1) { + window.setTimeout(function() { + parent.select('.conflicts-button') + .attr('disabled', null); + parent.select('.conflicts-done') + .transition() + .attr('opacity', 1) + .style('display', 'block'); + }, 250); + } - function choose(ul, datum) { - if (event) event.preventDefault(); + var conflict = selection$$1 + .selectAll('.conflict') + .data([_conflictList[index]]); + + conflict.exit() + .remove(); + + var conflictEnter = conflict.enter() + .append('div') + .attr('class', 'conflict'); + + conflictEnter + .append('h4') + .attr('class', 'conflict-count') + .text(t('save.conflict.count', { num: index + 1, total: _conflictList.length })); + + conflictEnter + .append('a') + .attr('class', 'conflict-description') + .attr('href', '#') + .text(function(d) { return d.name; }) + .on('click', function(d) { + event.preventDefault(); + zoomToEntity(d.id); + }); + + var details = conflictEnter + .append('div') + .attr('class', 'conflict-detail-container'); + + details + .append('ul') + .attr('class', 'conflict-detail-list') + .selectAll('li') + .data(function(d) { return d.details || []; }) + .enter() + .append('li') + .attr('class', 'conflict-detail-item') + .html(function(d) { return d; }); + + details + .append('div') + .attr('class', 'conflict-choices') + .call(addChoices); + + details + .append('div') + .attr('class', 'conflict-nav-buttons joined cf') + .selectAll('button') + .data(['previous', 'next']) + .enter() + .append('button') + .text(function(d) { return t('save.conflict.' + d); }) + .attr('class', 'conflict-nav-button action col6') + .attr('disabled', function(d, i) { + return (i === 0 && index === 0) || + (i === 1 && index === _conflictList.length - 1) || null; + }) + .on('click', function(d, i) { + event.preventDefault(); + + var container = parent.selectAll('.conflict-container'); + var sign = (i === 0 ? -1 : 1); + + container + .selectAll('.conflict') + .remove(); + + container + .call(showConflict, index + sign); + }); - d3_select(ul) - .selectAll('li') - .classed('active', function(d) { return d === datum; }) - .selectAll('input') - .property('checked', function(d) { return d === datum; }); + } - var extent = geoExtent$$1(); - var entity; - entity = context.graph().hasEntity(datum.id); - if (entity) extent._extend(entity.extent(context.graph())); + function addChoices(selection$$1) { + var choices = selection$$1 + .append('ul') + .attr('class', 'layer-list') + .selectAll('li') + .data(function(d) { return d.choices || []; }); + + // enter + var choicesEnter = choices.enter() + .append('li') + .attr('class', 'layer'); + + var labelEnter = choicesEnter + .append('label'); + + labelEnter + .append('input') + .attr('type', 'radio') + .attr('name', function(d) { return d.id; }) + .on('change', function(d, i) { + var ul = this.parentNode.parentNode.parentNode; + ul.__data__.chosen = i; + choose(ul, d); + }); + + labelEnter + .append('span') + .text(function(d) { return d.text; }); + + // update + choicesEnter + .merge(choices) + .each(function(d, i) { + var ul = this.parentNode; + if (ul.__data__.chosen === i) { + choose(ul, d); + } + }); + } - datum.action(); - entity = context.graph().hasEntity(datum.id); - if (entity) extent._extend(entity.extent(context.graph())); + function choose(ul, datum) { + if (event) event.preventDefault(); - zoomToEntity(datum.id, extent); - } + select(ul) + .selectAll('li') + .classed('active', function(d) { return d === datum; }) + .selectAll('input') + .property('checked', function(d) { return d === datum; }); + var extent = geoExtent$$1(); + var entity; - function zoomToEntity(id, extent) { - context.surface().selectAll('.hover') - .classed('hover', false); + entity = context.graph().hasEntity(datum.id); + if (entity) extent._extend(entity.extent(context.graph())); - var entity = context.graph().hasEntity(id); - if (entity) { - if (extent) { - context.map().trimmedExtent(extent); - } else { - context.map().zoomTo(entity); - } - context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())) - .classed('hover', true); - } - } + datum.action(); + entity = context.graph().hasEntity(datum.id); + if (entity) extent._extend(entity.extent(context.graph())); - // The conflict list should be an array of objects like: - // { - // id: id, - // name: entityName(local), - // details: merge.conflicts(), - // chosen: 1, - // choices: [ - // choice(id, keepMine, forceLocal), - // choice(id, keepTheirs, forceRemote) - // ] - // } - conflicts.conflictList = function(_) { - if (!arguments.length) return _conflictList; - _conflictList = _; - return conflicts; - }; + zoomToEntity(datum.id, extent); + } - conflicts.origChanges = function(_) { - if (!arguments.length) return _origChanges; - _origChanges = _; - return conflicts; - }; + function zoomToEntity(id, extent) { + context.surface().selectAll('.hover') + .classed('hover', false); + var entity = context.graph().hasEntity(id); + if (entity) { + if (extent) { + context.map().trimmedExtent(extent); + } else { + context.map().zoomTo(entity); + } + context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())) + .classed('hover', true); + } + } - return utilRebind(conflicts, dispatch$$1, 'on'); -} -function uiEditMenu(context, operations) { - var menu, - center = [0, 0], - offset = [0, 0], - tooltip; + // The conflict list should be an array of objects like: + // { + // id: id, + // name: entityName(local), + // details: merge.conflicts(), + // chosen: 1, + // choices: [ + // choice(id, keepMine, forceLocal), + // choice(id, keepTheirs, forceRemote) + // ] + // } + conflicts.conflictList = function(_) { + if (!arguments.length) return _conflictList; + _conflictList = _; + return conflicts; + }; - var p = 8, // top padding - m = 4, // top margin - h = 15, // height of icon - vpBottomMargin = 45, // viewport bottom margin - vpSideMargin = 35, // viewport side margin - buttonWidth = 44, - buttonHeight = (2 * p + h), - menuWidth = buttonWidth, - menuHeight = (2 * m) + operations.length * buttonHeight, - menuSideMargin = 10, - tooltipWidth = 200, - tooltipHeight = 200; // a reasonable guess, real height depends on tooltip contents + conflicts.origChanges = function(_) { + if (!arguments.length) return _origChanges; + _origChanges = _; + return conflicts; + }; - var editMenu = function (selection$$1) { - if (!operations.length) return; - selection$$1.node().parentNode.focus(); + return utilRebind(conflicts, dispatch$$1, 'on'); + } - var isRTL = textDirection === 'rtl', - viewport = context.surfaceRect(); + function uiEditMenu(context, operations) { + var menu, + center = [0, 0], + offset = [0, 0], + tooltip; + + var p = 8, // top padding + m = 4, // top margin + h = 15, // height of icon + vpBottomMargin = 45, // viewport bottom margin + vpSideMargin = 35, // viewport side margin + buttonWidth = 44, + buttonHeight = (2 * p + h), + menuWidth = buttonWidth, + menuHeight = (2 * m) + operations.length * buttonHeight, + menuSideMargin = 10, + tooltipWidth = 200, + tooltipHeight = 200; // a reasonable guess, real height depends on tooltip contents + + + var editMenu = function (selection$$1) { + if (!operations.length) return; + + selection$$1.node().parentNode.focus(); + + var isRTL = textDirection === 'rtl', + viewport = context.surfaceRect(); + + if (!isRTL && (center[0] + menuSideMargin + menuWidth) > (viewport.width - vpSideMargin)) { + // menu is going left-to-right and near right viewport edge, go left instead + isRTL = true; + } else if (isRTL && (center[0] - menuSideMargin - menuWidth) < vpSideMargin) { + // menu is going right-to-left and near left viewport edge, go right instead + isRTL = false; + } - if (!isRTL && (center[0] + menuSideMargin + menuWidth) > (viewport.width - vpSideMargin)) { - // menu is going left-to-right and near right viewport edge, go left instead - isRTL = true; - } else if (isRTL && (center[0] - menuSideMargin - menuWidth) < vpSideMargin) { - // menu is going right-to-left and near left viewport edge, go right instead - isRTL = false; - } + offset[0] = (isRTL ? -1 * (menuSideMargin + menuWidth) : menuSideMargin); - offset[0] = (isRTL ? -1 * (menuSideMargin + menuWidth) : menuSideMargin); + if (center[1] + menuHeight > (viewport.height - vpBottomMargin)) { + // menu is near bottom viewport edge, shift upwards + offset[1] = -1 * (center[1] + menuHeight - viewport.height + vpBottomMargin); + } - if (center[1] + menuHeight > (viewport.height - vpBottomMargin)) { - // menu is near bottom viewport edge, shift upwards - offset[1] = -1 * (center[1] + menuHeight - viewport.height + vpBottomMargin); - } + var origin = [ center[0] + offset[0], center[1] + offset[1] ]; + + menu = selection$$1 + .append('g') + .attr('class', 'edit-menu') + .attr('transform', 'translate(' + origin + ')') + .attr('opacity', 0); + + menu + .transition() + .attr('opacity', 1); + + menu + .append('rect') + .attr('class', 'edit-menu-background') + .attr('x', 4) + .attr('rx', 4) + .attr('ry', 4) + .attr('width', menuWidth) + .attr('height', menuHeight) + .attr('stroke-linecap', 'round'); + + + var button = menu.selectAll('.edit-menu-item') + .data(operations) + .enter() + .append('g') + .attr('class', function (d) { return 'edit-menu-item edit-menu-item-' + d.id; }) + .classed('disabled', function (d) { return d.disabled(); }) + .attr('transform', function (d, i) { + return 'translate(' + geoVecFloor([ + 0, + m + i * buttonHeight + ]).join(',') + ')'; + }); + + button + .append('rect') + .attr('x', 4) + .attr('width', buttonWidth) + .attr('height', buttonHeight) + .on('click', click) + .on('mousedown', mousedown) + .on('mouseover', mouseover) + .on('mouseout', mouseout); + + button + .append('use') + .attr('width', '20') + .attr('height', '20') + .attr('transform', function () { + return 'translate(' + [2 * p, 5] + ')'; + }) + .attr('xlink:href', function (d) { return '#operation-' + d.id; }); + + tooltip = select(document.body) + .append('div') + .attr('class', 'tooltip-inner edit-menu-tooltip'); + + + function click(operation) { + event.stopPropagation(); + if (operation.disabled()) return; + operation(); + editMenu.close(); + } - var origin = [ center[0] + offset[0], center[1] + offset[1] ]; - - menu = selection$$1 - .append('g') - .attr('class', 'edit-menu') - .attr('transform', 'translate(' + origin + ')') - .attr('opacity', 0); - - menu - .transition() - .attr('opacity', 1); - - menu - .append('rect') - .attr('class', 'edit-menu-background') - .attr('x', 4) - .attr('rx', 4) - .attr('ry', 4) - .attr('width', menuWidth) - .attr('height', menuHeight) - .attr('stroke-linecap', 'round'); - - - var button = menu.selectAll('.edit-menu-item') - .data(operations) - .enter() - .append('g') - .attr('class', function (d) { return 'edit-menu-item edit-menu-item-' + d.id; }) - .classed('disabled', function (d) { return d.disabled(); }) - .attr('transform', function (d, i) { - return 'translate(' + geoVecFloor([ - 0, - m + i * buttonHeight - ]).join(',') + ')'; - }); + function mousedown() { + event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869 + } - button - .append('rect') - .attr('x', 4) - .attr('width', buttonWidth) - .attr('height', buttonHeight) - .on('click', click) - .on('mousedown', mousedown) - .on('mouseover', mouseover) - .on('mouseout', mouseout); - - button - .append('use') - .attr('width', '20') - .attr('height', '20') - .attr('transform', function () { - return 'translate(' + [2 * p, 5] + ')'; - }) - .attr('xlink:href', function (d) { return '#operation-' + d.id; }); - - tooltip = d3_select(document.body) - .append('div') - .attr('class', 'tooltip-inner edit-menu-tooltip'); - - - function click(operation) { - event.stopPropagation(); - if (operation.disabled()) return; - operation(); - editMenu.close(); - } + function mouseover(d, i) { + var tipX, tipY; + + if (!isRTL) { + tipX = viewport.left + origin[0] + menuSideMargin + menuWidth; + } else { + tipX = viewport.left + origin[0] - 4 - tooltipWidth; + } + + if (tipX + tooltipWidth > viewport.right) { + // tip is going left-to-right and near right viewport edge, go left instead + tipX = viewport.left + origin[0] - 4 - tooltipWidth; + } else if (tipX < viewport.left) { + // tip is going right-to-left and near left viewport edge, go right instead + tipX = viewport.left + origin[0] + menuSideMargin + menuWidth; + } + + tipY = viewport.top + origin[1] + (i * buttonHeight); + if (tipY + tooltipHeight > viewport.bottom) { + // tip is near bottom viewport edge, shift upwards + tipY -= tipY + tooltipHeight - viewport.bottom; + } + + tooltip + .style('left', tipX + 'px') + .style('top', tipY + 'px') + .style('display', 'block') + .html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title)); + } - function mousedown() { - event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869 - } + function mouseout() { + tooltip.style('display', 'none'); + } + }; - function mouseover(d, i) { - var tipX, tipY; - if (!isRTL) { - tipX = viewport.left + origin[0] + menuSideMargin + menuWidth; - } else { - tipX = viewport.left + origin[0] - 4 - tooltipWidth; - } + editMenu.close = function () { + if (menu) { + menu + .style('pointer-events', 'none') + .transition() + .attr('opacity', 0) + .remove(); + } - if (tipX + tooltipWidth > viewport.right) { - // tip is going left-to-right and near right viewport edge, go left instead - tipX = viewport.left + origin[0] - 4 - tooltipWidth; - } else if (tipX < viewport.left) { - // tip is going right-to-left and near left viewport edge, go right instead - tipX = viewport.left + origin[0] + menuSideMargin + menuWidth; - } + if (tooltip) { + tooltip.remove(); + } + }; - tipY = viewport.top + origin[1] + (i * buttonHeight); - if (tipY + tooltipHeight > viewport.bottom) { - // tip is near bottom viewport edge, shift upwards - tipY -= tipY + tooltipHeight - viewport.bottom; - } - tooltip - .style('left', tipX + 'px') - .style('top', tipY + 'px') - .style('display', 'block') - .html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title)); - } + editMenu.center = function (_) { + if (!arguments.length) return center; + center = _; + return editMenu; + }; - function mouseout() { - tooltip.style('display', 'none'); - } - }; + return editMenu; + } - editMenu.close = function () { - if (menu) { - menu - .style('pointer-events', 'none') - .transition() - .attr('opacity', 0) - .remove(); - } + var _flashTimer; - if (tooltip) { - tooltip.remove(); - } - }; + function uiFlash() { + var _duration = 2000; + var _iconName = '#icon-no'; + var _iconClass = 'disabled'; + var _text = ''; + var _textClass; - editMenu.center = function (_) { - if (!arguments.length) return center; - center = _; - return editMenu; - }; + function flash() { + if (_flashTimer) { + _flashTimer.stop(); + } - return editMenu; -} + select('#footer-wrap') + .attr('class', 'footer-hide'); + select('#flash-wrap') + .attr('class', 'footer-show'); -var _flashTimer; + var content = select('#flash-wrap').selectAll('.flash-content') + .data([0]); + // Enter + var contentEnter = content.enter() + .append('div') + .attr('class', 'flash-content'); -function uiFlash() { - var _duration = 2000; - var _iconName = '#icon-no'; - var _iconClass = 'disabled'; - var _text = ''; - var _textClass; + var iconEnter = contentEnter + .append('svg') + .attr('class', 'flash-icon') + .append('g') + .attr('transform', 'translate(10,10)'); + iconEnter + .append('circle') + .attr('r', 9); - function flash() { - if (_flashTimer) { - _flashTimer.stop(); - } + iconEnter + .append('use') + .attr('transform', 'translate(-7,-7)') + .attr('width', '14') + .attr('height', '14'); - d3_select('#footer-wrap') - .attr('class', 'footer-hide'); - d3_select('#flash-wrap') - .attr('class', 'footer-show'); + contentEnter + .append('div') + .attr('class', 'flash-text'); - var content = d3_select('#flash-wrap').selectAll('.flash-content') - .data([0]); - // Enter - var contentEnter = content.enter() - .append('div') - .attr('class', 'flash-content'); + // Update + content = content + .merge(contentEnter); - var iconEnter = contentEnter - .append('svg') - .attr('class', 'flash-icon') - .append('g') - .attr('transform', 'translate(10,10)'); + content + .selectAll('.flash-icon') + .attr('class', 'flash-icon ' + (_iconClass || '')); - iconEnter - .append('circle') - .attr('r', 9); + content + .selectAll('.flash-icon use') + .attr('xlink:href', _iconName); - iconEnter - .append('use') - .attr('transform', 'translate(-7,-7)') - .attr('width', '14') - .attr('height', '14'); + content + .selectAll('.flash-text') + .attr('class', 'flash-text ' + (_textClass || '')) + .text(_text); - contentEnter - .append('div') - .attr('class', 'flash-text'); + _flashTimer = timeout$1(function() { + _flashTimer = null; + select('#footer-wrap') + .attr('class', 'footer-show'); + select('#flash-wrap') + .attr('class', 'footer-hide'); + }, _duration); - // Update - content = content - .merge(contentEnter); + return content; + } - content - .selectAll('.flash-icon') - .attr('class', 'flash-icon ' + (_iconClass || '')); - content - .selectAll('.flash-icon use') - .attr('xlink:href', _iconName); + flash.duration = function(_) { + if (!arguments.length) return _duration; + _duration = _; + return flash; + }; - content - .selectAll('.flash-text') - .attr('class', 'flash-text ' + (_textClass || '')) - .text(_text); + flash.text = function(_) { + if (!arguments.length) return _text; + _text = _; + return flash; + }; + flash.textClass = function(_) { + if (!arguments.length) return _textClass; + _textClass = _; + return flash; + }; - _flashTimer = d3_timeout(function() { - _flashTimer = null; - d3_select('#footer-wrap') - .attr('class', 'footer-show'); - d3_select('#flash-wrap') - .attr('class', 'footer-hide'); - }, _duration); + flash.iconName = function(_) { + if (!arguments.length) return _iconName; + _iconName = _; + return flash; + }; - return content; - } + flash.iconClass = function(_) { + if (!arguments.length) return _iconClass; + _iconClass = _; + return flash; + }; + return flash; + } - flash.duration = function(_) { - if (!arguments.length) return _duration; - _duration = _; - return flash; - }; + function uiLasso(context) { + var group, polygon; - flash.text = function(_) { - if (!arguments.length) return _text; - _text = _; - return flash; - }; + lasso.coordinates = []; - flash.textClass = function(_) { - if (!arguments.length) return _textClass; - _textClass = _; - return flash; - }; + function lasso(selection$$1) { + context.container() + .classed('lasso', true); - flash.iconName = function(_) { - if (!arguments.length) return _iconName; - _iconName = _; - return flash; - }; + group = selection$$1 + .append('g') + .attr('class', 'lasso hide'); - flash.iconClass = function(_) { - if (!arguments.length) return _iconClass; - _iconClass = _; - return flash; - }; + polygon = group + .append('path') + .attr('class', 'lasso-path'); - return flash; -} + group + .call(uiToggle(true)); + } -function uiLasso(context) { - var group, polygon; - lasso.coordinates = []; + function draw() { + if (polygon) { + polygon.data([lasso.coordinates]) + .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; }); + } + } - function lasso(selection$$1) { - context.container() - .classed('lasso', true); - group = selection$$1 - .append('g') - .attr('class', 'lasso hide'); + lasso.extent = function () { + return lasso.coordinates.reduce(function(extent, point$$1) { + return extent.extend(geoExtent$$1(point$$1)); + }, geoExtent$$1()); + }; - polygon = group - .append('path') - .attr('class', 'lasso-path'); - group - .call(uiToggle(true)); - } + lasso.p = function(_) { + if (!arguments.length) return lasso; + lasso.coordinates.push(_); + draw(); + return lasso; + }; - function draw() { - if (polygon) { - polygon.data([lasso.coordinates]) - .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; }); - } - } + lasso.close = function() { + if (group) { + group.call(uiToggle(false, function() { + select(this).remove(); + })); + } + context.container().classed('lasso', false); + }; - lasso.extent = function () { - return lasso.coordinates.reduce(function(extent, point$$1) { - return extent.extend(geoExtent$$1(point$$1)); - }, geoExtent$$1()); - }; + return lasso; + } + function uiRadialMenu(context, operations) { + var menu, + center = [0, 0], + tooltip; - lasso.p = function(_) { - if (!arguments.length) return lasso; - lasso.coordinates.push(_); - draw(); - return lasso; - }; + var radialMenu = function(selection$$1) { + if (!operations.length) return; - lasso.close = function() { - if (group) { - group.call(uiToggle(false, function() { - d3_select(this).remove(); - })); - } - context.container().classed('lasso', false); - }; + selection$$1.node().parentNode.focus(); + function click(operation) { + event.stopPropagation(); + if (operation.disabled()) return; + operation(); + radialMenu.close(); + } - return lasso; -} + menu = selection$$1 + .append('g') + .attr('class', 'radial-menu') + .attr('transform', 'translate(' + center + ')') + .attr('opacity', 0); + + menu + .transition() + .attr('opacity', 1); + + var r = 50, + a = Math.PI / 4, + a0 = -Math.PI / 4, + a1 = a0 + (operations.length - 1) * a; + + menu + .append('path') + .attr('class', 'radial-menu-background') + .attr('d', 'M' + r * Math.sin(a0) + ',' + + r * Math.cos(a0) + + ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' + + (r * Math.sin(a1) + 1e-3) + ',' + + (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305) + .attr('stroke-width', 50) + .attr('stroke-linecap', 'round'); + + var button = menu.selectAll() + .data(operations) + .enter() + .append('g') + .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; }) + .classed('disabled', function(d) { return d.disabled(); }) + .attr('transform', function(d, i) { + return 'translate(' + geoVecFloor([ + r * Math.sin(a0 + i * a), + r * Math.cos(a0 + i * a)]).join(',') + ')'; + }); + + button + .append('circle') + .attr('r', 15) + .on('click', click) + .on('mousedown', mousedown) + .on('mouseover', mouseover) + .on('mouseout', mouseout); + + button + .append('use') + .attr('transform', 'translate(-10,-10)') + .attr('width', '20') + .attr('height', '20') + .attr('xlink:href', function(d) { return '#operation-' + d.id; }); + + tooltip = select(document.body) + .append('div') + .attr('class', 'tooltip-inner radial-menu-tooltip'); + + function mousedown() { + event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869 + } -function uiRadialMenu(context, operations) { - var menu, - center = [0, 0], - tooltip; + function mouseover(d, i) { + var rect = context.surfaceRect(), + angle = a0 + i * a, + top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px', + left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px', + bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px', + right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px'; + + tooltip + .style('top', null) + .style('left', null) + .style('bottom', null) + .style('right', null) + .style('display', 'block') + .html(uiTooltipHtml(d.tooltip(), d.keys[0])); + + if (i === 0) { + tooltip + .style('right', right) + .style('top', top); + } else if (i >= 4) { + tooltip + .style('left', left) + .style('bottom', bottom); + } else { + tooltip + .style('left', left) + .style('top', top); + } + } + function mouseout() { + tooltip.style('display', 'none'); + } + }; - var radialMenu = function(selection$$1) { - if (!operations.length) return; - selection$$1.node().parentNode.focus(); + radialMenu.close = function() { + if (menu) { + menu + .style('pointer-events', 'none') + .transition() + .attr('opacity', 0) + .remove(); + } - function click(operation) { - event.stopPropagation(); - if (operation.disabled()) return; - operation(); - radialMenu.close(); - } + if (tooltip) { + tooltip.remove(); + } + }; - menu = selection$$1 - .append('g') - .attr('class', 'radial-menu') - .attr('transform', 'translate(' + center + ')') - .attr('opacity', 0); - - menu - .transition() - .attr('opacity', 1); - - var r = 50, - a = Math.PI / 4, - a0 = -Math.PI / 4, - a1 = a0 + (operations.length - 1) * a; - - menu - .append('path') - .attr('class', 'radial-menu-background') - .attr('d', 'M' + r * Math.sin(a0) + ',' + - r * Math.cos(a0) + - ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' + - (r * Math.sin(a1) + 1e-3) + ',' + - (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305) - .attr('stroke-width', 50) - .attr('stroke-linecap', 'round'); - - var button = menu.selectAll() - .data(operations) - .enter() - .append('g') - .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; }) - .classed('disabled', function(d) { return d.disabled(); }) - .attr('transform', function(d, i) { - return 'translate(' + geoVecFloor([ - r * Math.sin(a0 + i * a), - r * Math.cos(a0 + i * a)]).join(',') + ')'; - }); - button - .append('circle') - .attr('r', 15) - .on('click', click) - .on('mousedown', mousedown) - .on('mouseover', mouseover) - .on('mouseout', mouseout); - - button - .append('use') - .attr('transform', 'translate(-10,-10)') - .attr('width', '20') - .attr('height', '20') - .attr('xlink:href', function(d) { return '#operation-' + d.id; }); - - tooltip = d3_select(document.body) - .append('div') - .attr('class', 'tooltip-inner radial-menu-tooltip'); - - function mousedown() { - event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869 - } + radialMenu.center = function(_) { + if (!arguments.length) return center; + center = _; + return radialMenu; + }; - function mouseover(d, i) { - var rect = context.surfaceRect(), - angle = a0 + i * a, - top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px', - left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px', - bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px', - right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px'; - - tooltip - .style('top', null) - .style('left', null) - .style('bottom', null) - .style('right', null) - .style('display', 'block') - .html(uiTooltipHtml(d.tooltip(), d.keys[0])); - - if (i === 0) { - tooltip - .style('right', right) - .style('top', top); - } else if (i >= 4) { - tooltip - .style('left', left) - .style('bottom', bottom); - } else { - tooltip - .style('left', left) - .style('top', top); - } - } - function mouseout() { - tooltip.style('display', 'none'); - } - }; + return radialMenu; + } + function uiSelectionList(context, selectedIDs) { - radialMenu.close = function() { - if (menu) { - menu - .style('pointer-events', 'none') - .transition() - .attr('opacity', 0) - .remove(); - } + function selectEntity(entity) { + context.enter(modeSelect(context, [entity.id])); + } - if (tooltip) { - tooltip.remove(); - } - }; + function deselectEntity(entity) { + event.stopPropagation(); + var index = selectedIDs.indexOf(entity.id); + if (index > -1) { + selectedIDs.splice(index, 1); + } + context.enter(modeSelect(context, selectedIDs)); + } - radialMenu.center = function(_) { - if (!arguments.length) return center; - center = _; - return radialMenu; - }; + function selectionList(selection$$1) { + selection$$1.classed('selection-list-pane', true); - return radialMenu; -} + var header = selection$$1 + .append('div') + .attr('class', 'header fillL cf'); -function uiSelectionList(context, selectedIDs) { + header + .append('h3') + .text(t('inspector.multiselect')); - function selectEntity(entity) { - context.enter(modeSelect(context, [entity.id])); - } + var listWrap = selection$$1 + .append('div') + .attr('class', 'inspector-body'); + var list = listWrap + .append('div') + .attr('class', 'feature-list cf'); - function deselectEntity(entity) { - event.stopPropagation(); - var index = selectedIDs.indexOf(entity.id); - if (index > -1) { - selectedIDs.splice(index, 1); - } - context.enter(modeSelect(context, selectedIDs)); - } + context.history().on('change.selection-list', drawList); + drawList(); - function selectionList(selection$$1) { - selection$$1.classed('selection-list-pane', true); + function drawList() { + var entities = selectedIDs + .map(function(id) { return context.hasEntity(id); }) + .filter(function(entity) { return entity; }); - var header = selection$$1 - .append('div') - .attr('class', 'header fillL cf'); + var items = list.selectAll('.feature-list-item') + .data(entities, osmEntity$$1.key); - header - .append('h3') - .text(t('inspector.multiselect')); + items.exit() + .remove(); - var listWrap = selection$$1 - .append('div') - .attr('class', 'inspector-body'); + // Enter + var enter = items.enter() + .append('div') + .attr('class', 'feature-list-item') + .on('click', selectEntity); - var list = listWrap - .append('div') - .attr('class', 'feature-list cf'); + var label = enter + .append('button') + .attr('class', 'label'); - context.history().on('change.selection-list', drawList); - drawList(); + enter + .append('button') + .attr('class', 'close') + .on('click', deselectEntity) + .call(svgIcon('#icon-close')); + label + .append('span') + .attr('class', 'entity-geom-icon') + .call(svgIcon('', 'pre-text')); - function drawList() { - var entities = selectedIDs - .map(function(id) { return context.hasEntity(id); }) - .filter(function(entity) { return entity; }); + label + .append('span') + .attr('class', 'entity-type'); - var items = list.selectAll('.feature-list-item') - .data(entities, osmEntity$$1.key); + label + .append('span') + .attr('class', 'entity-name'); - items.exit() - .remove(); + // Update + items = items.merge(enter); - // Enter - var enter = items.enter() - .append('div') - .attr('class', 'feature-list-item') - .on('click', selectEntity); + items.selectAll('.entity-geom-icon use') + .attr('href', function() { + var entity = this.parentNode.parentNode.__data__; + return '#icon-' + context.geometry(entity.id); + }); - var label = enter - .append('button') - .attr('class', 'label'); + items.selectAll('.entity-type') + .text(function(entity) { return context.presets().match(entity, context.graph()).name(); }); - enter - .append('button') - .attr('class', 'close') - .on('click', deselectEntity) - .call(svgIcon('#icon-close')); + items.selectAll('.entity-name') + .text(function(entity) { return utilDisplayName(entity); }); + } + } - label - .append('span') - .attr('class', 'entity-geom-icon') - .call(svgIcon('', 'pre-text')); + return selectionList; + } - label - .append('span') - .attr('class', 'entity-type'); + function uiSourceSwitch(context) { + var keys; - label - .append('span') - .attr('class', 'entity-name'); - // Update - items = items.merge(enter); + function click() { + event.preventDefault(); - items.selectAll('.entity-geom-icon use') - .attr('href', function() { - var entity = this.parentNode.parentNode.__data__; - return '#icon-' + context.geometry(entity.id); - }); + var osm = context.connection(); + if (!osm) return; - items.selectAll('.entity-type') - .text(function(entity) { return context.presets().match(entity, context.graph()).name(); }); + if (context.inIntro()) return; - items.selectAll('.entity-name') - .text(function(entity) { return utilDisplayName(entity); }); - } - } + if (context.history().hasChanges() && + !window.confirm(t('source_switch.lose_changes'))) return; - return selectionList; -} + var isLive = select(this) + .classed('live'); -function uiSourceSwitch(context) { - var keys; + isLive = !isLive; + context.enter(modeBrowse(context)); + context.history().clearSaved(); // remove saved history + context.flush(); // remove stored data + select(this) + .text(isLive ? t('source_switch.live') : t('source_switch.dev')) + .classed('live', isLive); - function click() { - event.preventDefault(); + osm.switch(isLive ? keys[0] : keys[1]); // switch connection (warning: dispatches 'change' event) + } - var osm = context.connection(); - if (!osm) return; + var sourceSwitch = function(selection$$1) { + selection$$1 + .append('a') + .attr('href', '#') + .text(t('source_switch.live')) + .classed('live', true) + .attr('tabindex', -1) + .on('click', click); + }; - if (context.inIntro()) return; - if (context.history().hasChanges() && - !window.confirm(t('source_switch.lose_changes'))) return; + sourceSwitch.keys = function(_) { + if (!arguments.length) return keys; + keys = _; + return sourceSwitch; + }; - var isLive = d3_select(this) - .classed('live'); - isLive = !isLive; - context.enter(modeBrowse(context)); - context.history().clearSaved(); // remove saved history - context.flush(); // remove stored data + return sourceSwitch; + } - d3_select(this) - .text(isLive ? t('source_switch.live') : t('source_switch.dev')) - .classed('live', isLive); + function uiSuccess$$1(context) { + var MAXEVENTS = 2; + + // All else being equal, rank more "social" communities higher + // (anything not in this list receives no adjustment) + var COMMUNITYRANK = { + 'meetup': +5, + 'slack': +4, + 'facebook': +3, + 'reddit': +2, + 'forum': -2, + 'mailinglist': -3, + 'irc': -4 + }; - osm.switch(isLive ? keys[0] : keys[1]); // switch connection (warning: dispatches 'change' event) - } + var detected = utilDetect(); + var dispatch$$1 = dispatch('cancel'); + var _changeset; + var _location; - var sourceSwitch = function(selection$$1) { - selection$$1 - .append('a') - .attr('href', '#') - .text(t('source_switch.live')) - .classed('live', true) - .attr('tabindex', -1) - .on('click', click); - }; + // string-to-date parsing in JavaScript is weird + function parseEventDate(when) { + if (!when) return; - sourceSwitch.keys = function(_) { - if (!arguments.length) return keys; - keys = _; - return sourceSwitch; - }; + var raw = when.trim(); + if (!raw) return; + if (!/Z$/.test(raw)) { // if no trailing 'Z', add one + raw += 'Z'; // this forces date to be parsed as a UTC date + } - return sourceSwitch; -} + var parsed = new Date(raw); + return new Date(parsed.toUTCString().substr(0, 25)); // convert to local timezone + } -function uiSuccess(context) { - var dispatch$$1 = dispatch('cancel'), - changeset; + function success(selection$$1) { + var header = selection$$1 + .append('div') + .attr('class', 'header fillL'); + + header + .append('button') + .attr('class', 'fr') + .on('click', function() { dispatch$$1.call('cancel'); }) + .call(svgIcon('#icon-close')); + + header + .append('h3') + .text(t('success.just_edited')); + + var body = selection$$1 + .append('div') + .attr('class', 'body save-success fillL'); + + var summary = body + .append('div') + .attr('class', 'save-summary'); + + summary + .append('h3') + .text(t('success.thank_you' + (_location ? '_location' : ''), { where: _location })); + + summary + .append('p') + .text(t('success.help_html')) + .append('a') + .attr('class', 'link-out') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', t('success.help_link_url')) + .call(svgIcon('#icon-out-link', 'inline')) + .append('span') + .text(t('success.help_link_text')); + + var osm = context.connection(); + if (!osm) return; + + var changesetURL = osm.changesetURL(_changeset.id); + + var table = summary + .append('table') + .attr('class', 'summary-table'); + + var row = table + .append('tr') + .attr('class', 'summary-row'); + + row + .append('td') + .attr('class', 'cell-icon summary-icon') + .append('a') + .attr('target', '_blank') + .attr('href', changesetURL) + .append('svg') + .attr('class', 'logo-small') + .append('use') + .attr('xlink:href', '#logo-osm'); + + var summaryDetail = row + .append('td') + .attr('class', 'cell-detail summary-detail'); + + summaryDetail + .append('a') + .attr('class', 'cell-detail summary-view-on-osm') + .attr('target', '_blank') + .attr('href', changesetURL) + .text(t('success.view_on_osm')); + + summaryDetail + .append('div') + .text(t('success.changeset_id', { changeset_id: _changeset.id })); + + + // Gather community polygon IDs intersecting the map.. + var matchFeatures = data.community.query(context.map().center(), true) || []; + var matchIDs = matchFeatures.map(function(feature) { return feature.id; }); + + // Gather community resources that are either global or match a polygon. + var matchResources = filter(data.community.resources, function(v) { + return !v.featureId || matchIDs.indexOf(v.featureId) !== -1; + }); - function success(selection$$1) { - var header = selection$$1 - .append('div') - .attr('class', 'header fillL'); + if (matchResources.length) { + // sort by size ascending, then by community rank + matchResources.sort(function(a, b) { + var aSize = Infinity; + var bSize = Infinity; + var aRank = COMMUNITYRANK[a.type] || 0; + var bRank = COMMUNITYRANK[b.type] || 0; + + if (a.featureId) { + aSize = data.community.features[a.featureId].properties.area; + } + if (b.featureId) { + bSize = data.community.features[b.featureId].properties.area; + } + + return aSize < bSize ? -1 : aSize > bSize ? 1 : bRank - aRank; + }); + + body + .call(showCommunityLinks, matchResources); + } + } - header - .append('button') - .attr('class', 'fr') - .on('click', function() { dispatch$$1.call('cancel'); }) - .call(svgIcon('#icon-close')); - header - .append('h3') - .text(t('success.just_edited')); + function showCommunityLinks(selection$$1, matchResources) { + var communityLinks = selection$$1 + .append('div') + .attr('class', 'save-communityLinks'); + + communityLinks + .append('h3') + .text(t('success.like_osm')); + + var table = communityLinks + .append('table') + .attr('class', 'community-table'); + + var row = table.selectAll('.community-row') + .data(matchResources); + + var rowEnter = row.enter() + .append('tr') + .attr('class', 'community-row'); + + rowEnter + .append('td') + .attr('class', 'cell-icon community-icon') + .append('a') + .attr('target', '_blank') + .attr('href', function(d) { return d.url; }) + .append('svg') + .attr('class', 'logo-small') + .append('use') + .attr('xlink:href', function(d) { return '#community-' + d.type; }); + + var communityDetail = rowEnter + .append('td') + .attr('class', 'cell-detail community-detail'); + + communityDetail + .each(showCommunityDetails); + + communityLinks + .append('div') + .attr('class', 'community-missing') + .text(t('success.missing')) + .append('a') + .attr('class', 'link-out') + .attr('target', '_blank') + .attr('tabindex', -1) + .call(svgIcon('#icon-out-link', 'inline')) + .attr('href', 'https://github.com/osmlab/osm-community-index/issues') + .append('span') + .text(t('success.tell_us')); + } - var body = selection$$1 - .append('div') - .attr('class', 'body save-success fillL'); - body - .append('p') - .html(t('success.help_html')); + function showCommunityDetails(d) { + var selection$$1 = select(this); + var communityID = d.id; + var replacements = { + url: linkify(d.url), + signupUrl: linkify(d.signupUrl || d.url) + }; - body - .append('a') - .attr('class', 'details') - .attr('target', '_blank') - .attr('tabindex', -1) - .call(svgIcon('#icon-out-link', 'inline')) - .attr('href', t('success.help_link_url')) - .append('span') - .text(t('success.help_link_text')); + selection$$1 + .append('div') + .attr('class', 'community-name') + .append('a') + .attr('target', '_blank') + .attr('href', d.url) + .text(t('community.' + d.id + '.name')); - var osm = context.connection(); - if (!osm) return; + var descriptionHTML = t('community.' + d.id + '.description', replacements); - var changesetURL = osm.changesetURL(changeset.id); + if (d.type === 'reddit') { // linkify subreddits #4997 + descriptionHTML = descriptionHTML + .replace(/(\/r\/\w*\/*)/i, function(match) { return linkify(d.url, match); }); + } - var viewOnOsm = body - .append('a') - .attr('class', 'button col12 osm') - .attr('target', '_blank') - .attr('href', changesetURL); + selection$$1 + .append('div') + .attr('class', 'community-description') + .html(descriptionHTML); - viewOnOsm - .append('svg') - .attr('class', 'logo logo-osm') - .append('use') - .attr('xlink:href', '#logo-osm'); + if (d.extendedDescription || (d.languageCodes && d.languageCodes.length)) { + selection$$1 + .append('div') + .call(uiDisclosure(context, 'community-more-' + d.id, false) + .expanded(false) + .updatePreference(false) + .title(t('success.more')) + .content(showMore) + ); + } - viewOnOsm - .append('div') - .text(t('success.view_on_osm')); + var nextEvents = (d.events || []) + .map(function(event$$1) { + event$$1.date = parseEventDate(event$$1.when); + return event$$1; + }) + .filter(function(event$$1) { // date is valid and future (or today) + var t$$1 = event$$1.date.getTime(); + var now = (new Date()).setHours(0,0,0,0); + return !isNaN(t$$1) && t$$1 >= now; + }) + .sort(function(a, b) { // sort by date ascending + return a.date < b.date ? -1 : a.date > b.date ? 1 : 0; + }) + .slice(0, MAXEVENTS); // limit number of events shown + + if (nextEvents.length) { + selection$$1 + .append('div') + .call(uiDisclosure(context, 'community-events-' + d.id, false) + .expanded(false) + .updatePreference(false) + .title(t('success.events')) + .content(showNextEvents) + ) + .select('.hide-toggle') + .append('span') + .attr('class', 'badge-text') + .text(nextEvents.length); + } - var message = (changeset.tags.comment || t('success.edited_osm')).substring(0, 130) + - ' ' + changesetURL; - var sharing = [ - { key: 'facebook', value: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL) }, - { key: 'twitter', value: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message) }, - { key: 'google', value: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL) } - ]; + function showMore(selection$$1) { + var more = selection$$1 + .append('div') + .attr('class', 'community-more'); + + if (d.extendedDescription) { + more + .append('div') + .attr('class', 'community-extended-description') + .html(t('community.' + d.id + '.extendedDescription', replacements)); + } + + if (d.languageCodes && d.languageCodes.length) { + more + .append('div') + .attr('class', 'community-languages') + .text(t('success.languages', { languages: d.languageCodes.join(', ') })); + } + } - body.selectAll('.button.social') - .data(sharing) - .enter() - .append('a') - .attr('class', 'button social col4') - .attr('target', '_blank') - .attr('href', function(d) { return d.value; }) - .call(tooltip() - .title(function(d) { return t('success.' + d.key); }) - .placement('bottom')) - .each(function(d) { d3_select(this).call(svgIcon('#logo-' + d.key, 'social')); }); - } + function showNextEvents(selection$$1) { + var events = selection$$1 + .append('div') + .attr('class', 'community-events'); - success.changeset = function(_) { - if (!arguments.length) return changeset; - changeset = _; - return success; - }; + var item = events.selectAll('.community-event') + .data(nextEvents); + var itemEnter = item.enter() + .append('div') + .attr('class', 'community-event'); - return utilRebind(success, dispatch$$1, 'on'); -} + itemEnter + .append('div') + .attr('class', 'community-event-name') + .append('a') + .attr('target', '_blank') + .attr('href', function(d) { return d.url; }) + .text(function(d) { + var name = d.name; + if (d.i18n && d.id) { + name = t('community.' + communityID + '.events.' + d.id + '.name', { default: name }); + } + return name; + }); + + itemEnter + .append('div') + .attr('class', 'community-event-when') + .text(function(d) { + var options = { + weekday: 'short', day: 'numeric', month: 'short', year: 'numeric' + }; + if (d.date.getHours() || d.date.getMinutes()) { // include time if it has one + options.hour = 'numeric'; + options.minute = 'numeric'; + } + return d.date.toLocaleString(detected.locale, options); + }); + + itemEnter + .append('div') + .attr('class', 'community-event-where') + .text(function(d) { + var where = d.where; + if (d.i18n && d.id) { + where = t('community.' + communityID + '.events.' + d.id + '.where', { default: where }); + } + return where; + }); + + itemEnter + .append('div') + .attr('class', 'community-event-description') + .text(function(d) { + var description = d.description; + if (d.i18n && d.id) { + description = t('community.' + communityID + '.events.' + d.id + '.description', { default: description }); + } + return description; + }); + } -function coreHistory(context) { - var imageryUsed = ['Bing']; - var dispatch$$1 = dispatch('change', 'undone', 'redone'); - var lock = utilSessionMutex('lock'); - var duration = 150; - var _checkpoints = {}; - var _stack; - var _index; - var _tree; + function linkify(url, text) { + text = text || url; + return '' + text + ''; + } + } - // internal _act, accepts list of actions and eased time - function _act(actions, t) { - actions = Array.prototype.slice.call(actions); - var annotation; - if (!isFunction(actions[actions.length - 1])) { - annotation = actions.pop(); - } + success.changeset = function(_) { + if (!arguments.length) return _changeset; + _changeset = _; + return success; + }; - _stack[_index].transform = context.projection.transform(); - _stack[_index].selectedIDs = context.selectedIDs(); - var graph = _stack[_index].graph; - for (var i = 0; i < actions.length; i++) { - graph = actions[i](graph, t); - } + success.location = function(_) { + if (!arguments.length) return _location; + _location = _; + return success; + }; - return { - graph: graph, - annotation: annotation, - imageryUsed: imageryUsed - }; - } + return utilRebind(success, dispatch$$1, 'on'); + } - // internal _perform with eased time - function _perform(args, t) { - var previous = _stack[_index].graph; - _stack = _stack.slice(0, _index + 1); - _stack.push(_act(args, t)); - _index++; - return change(previous); - } + function coreHistory(context) { + var imageryUsed = ['Bing']; + var dispatch$$1 = dispatch('change', 'undone', 'redone'); + var lock = utilSessionMutex('lock'); + var duration = 150; + var _checkpoints = {}; + var _stack; + var _index; + var _tree; - // internal _replace with eased time - function _replace(args, t) { - var previous = _stack[_index].graph; - // assert(_index == _stack.length - 1) - _stack[_index] = _act(args, t); - return change(previous); - } + // internal _act, accepts list of actions and eased time + function _act(actions, t) { + actions = Array.prototype.slice.call(actions); + var annotation; + if (!isFunction(actions[actions.length - 1])) { + annotation = actions.pop(); + } - // internal _overwrite with eased time - function _overwrite(args, t) { - var previous = _stack[_index].graph; - if (_index > 0) { - _index--; - _stack.pop(); - } - _stack = _stack.slice(0, _index + 1); - _stack.push(_act(args, t)); - _index++; - return change(previous); - } + _stack[_index].transform = context.projection.transform(); + _stack[_index].selectedIDs = context.selectedIDs(); + var graph = _stack[_index].graph; + for (var i = 0; i < actions.length; i++) { + graph = actions[i](graph, t); + } - // determine diffrence and dispatch a change event - function change(previous) { - var difference$$1 = coreDifference(previous, history.graph()); - dispatch$$1.call('change', this, difference$$1); - return difference$$1; - } + return { + graph: graph, + annotation: annotation, + imageryUsed: imageryUsed + }; + } - // iD uses namespaced keys so multiple installations do not conflict - function getKey(n) { - return 'iD_' + window.location.origin + '_' + n; - } + // internal _perform with eased time + function _perform(args, t) { + var previous = _stack[_index].graph; + _stack = _stack.slice(0, _index + 1); + _stack.push(_act(args, t)); + _index++; + return change(previous); + } - var history = { + // internal _replace with eased time + function _replace(args, t) { + var previous = _stack[_index].graph; + // assert(_index == _stack.length - 1) + _stack[_index] = _act(args, t); + return change(previous); + } - graph: function() { - return _stack[_index].graph; - }, + // internal _overwrite with eased time + function _overwrite(args, t) { + var previous = _stack[_index].graph; + if (_index > 0) { + _index--; + _stack.pop(); + } + _stack = _stack.slice(0, _index + 1); + _stack.push(_act(args, t)); + _index++; + return change(previous); + } - base: function() { - return _stack[0].graph; - }, + // determine diffrence and dispatch a change event + function change(previous) { + var difference$$1 = coreDifference(previous, history.graph()); + dispatch$$1.call('change', this, difference$$1); + return difference$$1; + } - merge: function(entities, extent) { - _stack[0].graph.rebase(entities, map$3(_stack, 'graph'), false); - _tree.rebase(entities, false); - dispatch$$1.call('change', this, undefined, extent); - }, + // iD uses namespaced keys so multiple installations do not conflict + function getKey(n) { + return 'iD_' + window.location.origin + '_' + n; + } - perform: function() { - // complete any transition already in progress - d3_select(document).interrupt('history.perform'); + var history = { - var transitionable = false; - var action0 = arguments[0]; + graph: function() { + return _stack[_index].graph; + }, - if (arguments.length === 1 || - arguments.length === 2 && !isFunction(arguments[1])) { - transitionable = !!action0.transitionable; - } - if (transitionable) { - var origArguments = arguments; - d3_select(document) - .transition('history.perform') - .duration(duration) - .ease(linear$1) - .tween('history.tween', function() { - return function(t) { - if (t < 1) _overwrite([action0], t); - }; - }) - .on('start', function() { - _perform([action0], 0); - }) - .on('end interrupt', function() { - _overwrite(origArguments, 1); - }); + base: function() { + return _stack[0].graph; + }, - } else { - return _perform(arguments); - } - }, + merge: function(entities, extent) { + _stack[0].graph.rebase(entities, map$3(_stack, 'graph'), false); + _tree.rebase(entities, false); - replace: function() { - d3_select(document).interrupt('history.perform'); - return _replace(arguments, 1); - }, + dispatch$$1.call('change', this, undefined, extent); + }, - // Same as calling pop and then perform - overwrite: function() { - d3_select(document).interrupt('history.perform'); - return _overwrite(arguments, 1); - }, + perform: function() { + // complete any transition already in progress + select(document).interrupt('history.perform'); + var transitionable = false; + var action0 = arguments[0]; - pop: function(n) { - d3_select(document).interrupt('history.perform'); + if (arguments.length === 1 || + arguments.length === 2 && !isFunction(arguments[1])) { + transitionable = !!action0.transitionable; + } - var previous = _stack[_index].graph; - if (isNaN(+n) || +n < 0) { - n = 1; - } - while (n-- > 0 && _index > 0) { - _index--; - _stack.pop(); - } - return change(previous); - }, + if (transitionable) { + var origArguments = arguments; + select(document) + .transition('history.perform') + .duration(duration) + .ease(linear$1) + .tween('history.tween', function() { + return function(t) { + if (t < 1) _overwrite([action0], t); + }; + }) + .on('start', function() { + _perform([action0], 0); + }) + .on('end interrupt', function() { + _overwrite(origArguments, 1); + }); + } else { + return _perform(arguments); + } + }, - // Back to the previous annotated state or _index = 0. - undo: function() { - d3_select(document).interrupt('history.perform'); - var previous = _stack[_index].graph; - while (_index > 0) { - _index--; - if (_stack[_index].annotation) break; - } + replace: function() { + select(document).interrupt('history.perform'); + return _replace(arguments, 1); + }, - dispatch$$1.call('undone', this, _stack[_index]); - return change(previous); - }, + // Same as calling pop and then perform + overwrite: function() { + select(document).interrupt('history.perform'); + return _overwrite(arguments, 1); + }, - // Forward to the next annotated state. - redo: function() { - d3_select(document).interrupt('history.perform'); - var previous = _stack[_index].graph; - var tryIndex = _index; - while (tryIndex < _stack.length - 1) { - tryIndex++; - if (_stack[tryIndex].annotation) { - _index = tryIndex; - dispatch$$1.call('redone', this, _stack[_index]); - break; - } - } + pop: function(n) { + select(document).interrupt('history.perform'); - return change(previous); - }, + var previous = _stack[_index].graph; + if (isNaN(+n) || +n < 0) { + n = 1; + } + while (n-- > 0 && _index > 0) { + _index--; + _stack.pop(); + } + return change(previous); + }, - undoAnnotation: function() { - var i = _index; - while (i >= 0) { - if (_stack[i].annotation) return _stack[i].annotation; - i--; - } - }, + // Back to the previous annotated state or _index = 0. + undo: function() { + select(document).interrupt('history.perform'); + var previous = _stack[_index].graph; + while (_index > 0) { + _index--; + if (_stack[_index].annotation) break; + } - redoAnnotation: function() { - var i = _index + 1; - while (i <= _stack.length - 1) { - if (_stack[i].annotation) return _stack[i].annotation; - i++; - } - }, + dispatch$$1.call('undone', this, _stack[_index]); + return change(previous); + }, - intersects: function(extent) { - return _tree.intersects(extent, _stack[_index].graph); - }, + // Forward to the next annotated state. + redo: function() { + select(document).interrupt('history.perform'); + + var previous = _stack[_index].graph; + var tryIndex = _index; + while (tryIndex < _stack.length - 1) { + tryIndex++; + if (_stack[tryIndex].annotation) { + _index = tryIndex; + dispatch$$1.call('redone', this, _stack[_index]); + break; + } + } + + return change(previous); + }, + + + undoAnnotation: function() { + var i = _index; + while (i >= 0) { + if (_stack[i].annotation) return _stack[i].annotation; + i--; + } + }, + + + redoAnnotation: function() { + var i = _index + 1; + while (i <= _stack.length - 1) { + if (_stack[i].annotation) return _stack[i].annotation; + i++; + } + }, + + + intersects: function(extent) { + return _tree.intersects(extent, _stack[_index].graph); + }, + + + difference: function() { + var base = _stack[0].graph; + var head = _stack[_index].graph; + return coreDifference(base, head); + }, + + + changes: function(action) { + var base = _stack[0].graph; + var head = _stack[_index].graph; + + if (action) { + head = action(head); + } + + var difference$$1 = coreDifference(base, head); + + return { + modified: difference$$1.modified(), + created: difference$$1.created(), + deleted: difference$$1.deleted() + }; + }, + + + validate: function(changes) { + return flatten( + map$3(Validations, function(fn) { return fn()(changes, _stack[_index].graph); }) + ); + }, + + + hasChanges: function() { + return this.difference().length() > 0; + }, + + + imageryUsed: function(sources) { + if (sources) { + imageryUsed = sources; + return history; + } else { + var arr = map$3(_stack.slice(1, _index + 1), 'imageryUsed'); + return without(uniq(flatten(arr)), 'Custom'); + } + }, + + + // save the current history state + checkpoint: function(key) { + _checkpoints[key] = { + stack: cloneDeep(_stack), + index: _index + }; + return history; + }, + + + // restore history state to a given checkpoint or reset completely + reset: function(key) { + if (key !== undefined && _checkpoints.hasOwnProperty(key)) { + _stack = cloneDeep(_checkpoints[key].stack); + _index = _checkpoints[key].index; + } else { + _stack = [{graph: coreGraph$$1()}]; + _index = 0; + _tree = coreTree(_stack[0].graph); + _checkpoints = {}; + } + dispatch$$1.call('change'); + return history; + }, + + + toIntroGraph: function() { + var nextId = { n: 0, r: 0, w: 0 }; + var permIds = {}; + var graph = this.graph(); + var baseEntities = {}; + + // clone base entities.. + forEach(graph.base().entities, function(entity) { + var copy = cloneDeepWith(entity, customizer); + baseEntities[copy.id] = copy; + }); + + // replace base entities with head entities.. + forEach(graph.entities, function(entity, id) { + if (entity) { + var copy = cloneDeepWith(entity, customizer); + baseEntities[copy.id] = copy; + } else { + delete baseEntities[id]; + } + }); + + // swap temporary for permanent ids.. + forEach(baseEntities, function(entity) { + if (Array.isArray(entity.nodes)) { + entity.nodes = entity.nodes.map(function(node) { + return permIds[node] || node; + }); + } + if (Array.isArray(entity.members)) { + entity.members = entity.members.map(function(member) { + member.id = permIds[member.id] || member.id; + return member; + }); + } + }); + + return JSON.stringify({ dataIntroGraph: baseEntities }); + + + function customizer(src) { + var copy = omit(cloneDeep(src), ['type', 'user', 'v', 'version', 'visible']); + if (isEmpty(copy.tags)) { + delete copy.tags; + } + + if (Array.isArray(copy.loc)) { + copy.loc[0] = +copy.loc[0].toFixed(6); + copy.loc[1] = +copy.loc[1].toFixed(6); + } + + var match = src.id.match(/([nrw])-\d*/); // temporary id + if (match !== null) { + var nrw = match[1], permId; + do { permId = nrw + (++nextId[nrw]); } + while (baseEntities.hasOwnProperty(permId)); + + copy.id = permIds[src.id] = permId; + } + return copy; + } + }, + + + toJSON: function() { + if (!this.hasChanges()) return; + + var allEntities = {}; + var baseEntities = {}; + var base = _stack[0]; + + var s = _stack.map(function(i) { + var modified = [], deleted = []; + + forEach(i.graph.entities, function(entity, id) { + if (entity) { + var key = osmEntity$$1.key(entity); + allEntities[key] = entity; + modified.push(key); + } else { + deleted.push(id); + } + + // make sure that the originals of changed or deleted entities get merged + // into the base of the _stack after restoring the data from JSON. + if (id in base.graph.entities) { + baseEntities[id] = base.graph.entities[id]; + } + // get originals of parent entities too + forEach(base.graph._parentWays[id], function(parentId) { + if (parentId in base.graph.entities) { + baseEntities[parentId] = base.graph.entities[parentId]; + } + }); + }); + + var x = {}; + + if (modified.length) x.modified = modified; + if (deleted.length) x.deleted = deleted; + if (i.imageryUsed) x.imageryUsed = i.imageryUsed; + if (i.annotation) x.annotation = i.annotation; + + return x; + }); + + return JSON.stringify({ + version: 3, + entities: values$1(allEntities), + baseEntities: values$1(baseEntities), + stack: s, + nextIDs: osmEntity$$1.id.next, + index: _index + }); + }, + + + fromJSON: function(json, loadChildNodes) { + var h = JSON.parse(json); + var loadComplete = true; + + osmEntity$$1.id.next = h.nextIDs; + _index = h.index; + + if (h.version === 2 || h.version === 3) { + var allEntities = {}; + + h.entities.forEach(function(entity) { + allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity); + }); + + if (h.version === 3) { + // This merges originals for changed entities into the base of + // the _stack even if the current _stack doesn't have them (for + // example when iD has been restarted in a different region) + var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); }); + _stack[0].graph.rebase(baseEntities, map$3(_stack, 'graph'), true); + _tree.rebase(baseEntities, true); + + // When we restore a modified way, we also need to fetch any missing + // childnodes that would normally have been downloaded with it.. #2142 + if (loadChildNodes) { + var osm = context.connection(); + var nodes = flatten(uniq(map$3(filter(baseEntities, { type: 'way' }), 'nodes'))); + var missing = reject(nodes, function(n) { return _stack[0].graph.hasEntity(n); }); + + if (!isEmpty(missing) && osm) { + loadComplete = false; + context.redrawEnable(false); + + var loading = uiLoading(context).blocking(true); + context.container().call(loading); + + var childNodesLoaded = function(err, result) { + if (!err) { + var visible = groupBy(result.data, 'visible'); + if (!isEmpty(visible.true)) { + missing = difference(missing, map$3(visible.true, 'id')); + _stack[0].graph.rebase(visible.true, map$3(_stack, 'graph'), true); + _tree.rebase(visible.true, true); + } + + // fetch older versions of nodes that were deleted.. + forEach(visible.false, function(entity) { + osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded); + }); + } + + if (err || isEmpty(missing)) { + loading.close(); + context.redrawEnable(true); + dispatch$$1.call('change'); + } + }; + + osm.loadMultiple(missing, childNodesLoaded); + } + } + } + + _stack = h.stack.map(function(d) { + var entities = {}, entity; + + if (d.modified) { + d.modified.forEach(function(key) { + entity = allEntities[key]; + entities[entity.id] = entity; + }); + } + + if (d.deleted) { + d.deleted.forEach(function(id) { + entities[id] = undefined; + }); + } + return { + graph: coreGraph$$1(_stack[0].graph).load(entities), + annotation: d.annotation, + imageryUsed: d.imageryUsed + }; + }); + + } else { // original version + _stack = h.stack.map(function(d) { + var entities = {}; + + for (var i in d.entities) { + var entity = d.entities[i]; + entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity); + } - difference: function() { - var base = _stack[0].graph; - var head = _stack[_index].graph; - return coreDifference(base, head); - }, + d.graph = coreGraph$$1(_stack[0].graph).load(entities); + return d; + }); + } + if (loadComplete) { + dispatch$$1.call('change'); + } - changes: function(action) { - var base = _stack[0].graph; - var head = _stack[_index].graph; + return history; + }, - if (action) { - head = action(head); - } - var difference$$1 = coreDifference(base, head); + save: function() { + if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null); + return history; + }, + + + clearSaved: function() { + context.debouncedSave.cancel(); + if (lock.locked()) context.storage(getKey('saved_history'), null); + return history; + }, + - return { - modified: difference$$1.modified(), - created: difference$$1.created(), - deleted: difference$$1.deleted() - }; - }, + lock: function() { + return lock.lock(); + }, - validate: function(changes) { - return flatten( - map$3(Validations, function(fn) { return fn()(changes, _stack[_index].graph); }) - ); - }, + unlock: function() { + lock.unlock(); + }, - hasChanges: function() { - return this.difference().length() > 0; - }, + // is iD not open in another window and it detects that + // there's a history stored in localStorage that's recoverable? + restorableChanges: function() { + return lock.locked() && !!context.storage(getKey('saved_history')); + }, - imageryUsed: function(sources) { - if (sources) { - imageryUsed = sources; - return history; - } else { - var arr = map$3(_stack.slice(1, _index + 1), 'imageryUsed'); - return without(uniq(flatten(arr)), 'Custom'); - } - }, + // load history from a version stored in localStorage + restore: function() { + if (!lock.locked()) return; + var json = context.storage(getKey('saved_history')); + if (json) history.fromJSON(json, true); + }, - // save the current history state - checkpoint: function(key) { - _checkpoints[key] = { - stack: cloneDeep(_stack), - index: _index - }; - return history; - }, + _getKey: getKey - // restore history state to a given checkpoint or reset completely - reset: function(key) { - if (key !== undefined && _checkpoints.hasOwnProperty(key)) { - _stack = cloneDeep(_checkpoints[key].stack); - _index = _checkpoints[key].index; - } else { - _stack = [{graph: coreGraph$$1()}]; - _index = 0; - _tree = coreTree(_stack[0].graph); - _checkpoints = {}; - } - dispatch$$1.call('change'); - return history; - }, + }; - toIntroGraph: function() { - var nextId = { n: 0, r: 0, w: 0 }; - var permIds = {}; - var graph = this.graph(); - var baseEntities = {}; + history.reset(); - // clone base entities.. - forEach(graph.base().entities, function(entity) { - var copy = cloneDeepWith(entity, customizer); - baseEntities[copy.id] = copy; - }); + return utilRebind(history, dispatch$$1, 'on'); + } - // replace base entities with head entities.. - forEach(graph.entities, function(entity, id) { - if (entity) { - var copy = cloneDeepWith(entity, customizer); - baseEntities[copy.id] = copy; - } else { - delete baseEntities[id]; - } - }); + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; - // swap temporary for permanent ids.. - forEach(baseEntities, function(entity) { - if (Array.isArray(entity.nodes)) { - entity.nodes = entity.nodes.map(function(node) { - return permIds[node] || node; - }); - } - if (Array.isArray(entity.members)) { - entity.members = entity.members.map(function(member) { - member.id = permIds[member.id] || member.id; - return member; - }); - } - }); + /** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity$8 : function(func, data) { + metaMap.set(func, data); + return func; + }; - return JSON.stringify({ dataIntroGraph: baseEntities }); + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } - function customizer(src) { - var copy = omit(cloneDeep(src), ['type', 'user', 'v', 'version', 'visible']); - if (isEmpty(copy.tags)) { - delete copy.tags; - } + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1; - if (Array.isArray(copy.loc)) { - copy.loc[0] = +copy.loc[0].toFixed(6); - copy.loc[1] = +copy.loc[1].toFixed(6); - } + /** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); - var match = src.id.match(/([nrw])-\d*/); // temporary id - if (match !== null) { - var nrw = match[1], permId; - do { permId = nrw + (++nextId[nrw]); } - while (baseEntities.hasOwnProperty(permId)); + function wrapper() { + var fn = (this && this !== root$2 && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } - copy.id = permIds[src.id] = permId; - } - return copy; - } - }, + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMax$5 = Math.max; + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax$5(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; - toJSON: function() { - if (!this.hasChanges()) return; - - var allEntities = {}; - var baseEntities = {}; - var base = _stack[0]; - - var s = _stack.map(function(i) { - var modified = [], deleted = []; - - forEach(i.graph.entities, function(entity, id) { - if (entity) { - var key = osmEntity$$1.key(entity); - allEntities[key] = entity; - modified.push(key); - } else { - deleted.push(id); - } - - // make sure that the originals of changed or deleted entities get merged - // into the base of the _stack after restoring the data from JSON. - if (id in base.graph.entities) { - baseEntities[id] = base.graph.entities[id]; - } - // get originals of parent entities too - forEach(base.graph._parentWays[id], function(parentId) { - if (parentId in base.graph.entities) { - baseEntities[parentId] = base.graph.entities[parentId]; - } - }); - }); - - var x = {}; - - if (modified.length) x.modified = modified; - if (deleted.length) x.deleted = deleted; - if (i.imageryUsed) x.imageryUsed = i.imageryUsed; - if (i.annotation) x.annotation = i.annotation; - - return x; - }); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } - return JSON.stringify({ - version: 3, - entities: values$1(allEntities), - baseEntities: values$1(baseEntities), - stack: s, - nextIDs: osmEntity$$1.id.next, - index: _index - }); - }, + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMax$6 = Math.max; + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax$6(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; + } - fromJSON: function(json, loadChildNodes) { - var h = JSON.parse(json); - var loadComplete = true; - - osmEntity$$1.id.next = h.nextIDs; - _index = h.index; - - if (h.version === 2 || h.version === 3) { - var allEntities = {}; - - h.entities.forEach(function(entity) { - allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity); - }); - - if (h.version === 3) { - // This merges originals for changed entities into the base of - // the _stack even if the current _stack doesn't have them (for - // example when iD has been restarted in a different region) - var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); }); - _stack[0].graph.rebase(baseEntities, map$3(_stack, 'graph'), true); - _tree.rebase(baseEntities, true); - - // When we restore a modified way, we also need to fetch any missing - // childnodes that would normally have been downloaded with it.. #2142 - if (loadChildNodes) { - var osm = context.connection(); - var nodes = flatten(uniq(map$3(filter(baseEntities, { type: 'way' }), 'nodes'))); - var missing = reject(nodes, function(n) { return _stack[0].graph.hasEntity(n); }); - - if (!isEmpty(missing) && osm) { - loadComplete = false; - context.redrawEnable(false); - - var loading = uiLoading(context).blocking(true); - context.container().call(loading); - - var childNodesLoaded = function(err, result) { - if (!err) { - var visible = groupBy(result.data, 'visible'); - if (!isEmpty(visible.true)) { - missing = difference(missing, map$3(visible.true, 'id')); - _stack[0].graph.rebase(visible.true, map$3(_stack, 'graph'), true); - _tree.rebase(visible.true, true); - } - - // fetch older versions of nodes that were deleted.. - forEach(visible.false, function(entity) { - osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded); - }); - } - - if (err || isEmpty(missing)) { - loading.close(); - context.redrawEnable(true); - dispatch$$1.call('change'); - } - }; - - osm.loadMultiple(missing, childNodesLoaded); - } - } - } - - _stack = h.stack.map(function(d) { - var entities = {}, entity; - - if (d.modified) { - d.modified.forEach(function(key) { - entity = allEntities[key]; - entities[entity.id] = entity; - }); - } - - if (d.deleted) { - d.deleted.forEach(function(id) { - entities[id] = undefined; - }); - } - - return { - graph: coreGraph$$1(_stack[0].graph).load(entities), - annotation: d.annotation, - imageryUsed: d.imageryUsed - }; - }); - - } else { // original version - _stack = h.stack.map(function(d) { - var entities = {}; - - for (var i in d.entities) { - var entity = d.entities[i]; - entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity); - } - - d.graph = coreGraph$$1(_stack[0].graph).load(entities); - return d; - }); - } + /** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ + function countHolders(array, placeholder) { + var length = array.length, + result = 0; - if (loadComplete) { - dispatch$$1.call('change'); - } + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } - return history; - }, + /** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ + function baseLodash() { + // No operation performed. + } + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = 4294967295; - save: function() { - if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null); - return history; - }, + /** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; - clearSaved: function() { - context.debouncedSave.cancel(); - if (lock.locked()) context.storage(getKey('saved_history'), null); - return history; - }, + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop$3 : function(func) { + return metaMap.get(func); + }; + /** Used to lookup unminified function names. */ + var realNames = {}; - lock: function() { - return lock.lock(); - }, + /** Used for built-in method references. */ + var objectProto$20 = Object.prototype; + /** Used to check objects for own properties. */ + var hasOwnProperty$17 = objectProto$20.hasOwnProperty; - unlock: function() { - lock.unlock(); - }, + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty$17.call(realNames, result) ? array.length : 0; + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } - // is iD not open in another window and it detects that - // there's a history stored in localStorage that's recoverable? - restorableChanges: function() { - return lock.locked() && !!context.storage(getKey('saved_history')); - }, + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; + } + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; - // load history from a version stored in localStorage - restore: function() { - if (!lock.locked()) return; + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; + } - var json = context.storage(getKey('saved_history')); - if (json) history.fromJSON(json, true); - }, + /** Used for built-in method references. */ + var objectProto$21 = Object.prototype; + /** Used to check objects for own properties. */ + var hasOwnProperty$18 = objectProto$21.hasOwnProperty; - _getKey: getKey + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty$18.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } - }; + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; - history.reset(); - - return utilRebind(history, dispatch$$1, 'on'); -} - -/** Used to store function metadata. */ -var metaMap = WeakMap && new WeakMap; - -/** - * The base implementation of `setData` without support for hot loop shorting. - * - * @private - * @param {Function} func The function to associate metadata with. - * @param {*} data The metadata. - * @returns {Function} Returns `func`. - */ -var baseSetData = !metaMap ? identity$8 : function(func, data) { - metaMap.set(func, data); - return func; -}; - -/** - * Creates a function that produces an instance of `Ctor` regardless of - * whether it was invoked as part of a `new` expression or by `call` or `apply`. - * - * @private - * @param {Function} Ctor The constructor to wrap. - * @returns {Function} Returns the new wrapped function. - */ -function createCtor(Ctor) { - return function() { - // Use a `switch` statement to work with class constructors. See - // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist - // for more details. - var args = arguments; - switch (args.length) { - case 0: return new Ctor; - case 1: return new Ctor(args[0]); - case 2: return new Ctor(args[0], args[1]); - case 3: return new Ctor(args[0], args[1], args[2]); - case 4: return new Ctor(args[0], args[1], args[2], args[3]); - case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); - case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); - case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - } - var thisBinding = baseCreate(Ctor.prototype), - result = Ctor.apply(thisBinding, args); - - // Mimic the constructor's `return` behavior. - // See https://es5.github.io/#x13.2.2 for more details. - return isObject(result) ? result : thisBinding; - }; -} - -/** Used to compose bitmasks for function metadata. */ -var WRAP_BIND_FLAG = 1; - -/** - * Creates a function that wraps `func` to invoke it with the optional `this` - * binding of `thisArg`. - * - * @private - * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {*} [thisArg] The `this` binding of `func`. - * @returns {Function} Returns the new wrapped function. - */ -function createBind(func, bitmask, thisArg) { - var isBind = bitmask & WRAP_BIND_FLAG, - Ctor = createCtor(func); - - function wrapper() { - var fn = (this && this !== root$2 && this instanceof wrapper) ? Ctor : func; - return fn.apply(isBind ? thisArg : this, arguments); - } - return wrapper; -} - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax$5 = Math.max; - -/** - * Creates an array that is the composition of partially applied arguments, - * placeholders, and provided arguments into a single array of arguments. - * - * @private - * @param {Array} args The provided arguments. - * @param {Array} partials The arguments to prepend to those provided. - * @param {Array} holders The `partials` placeholder indexes. - * @params {boolean} [isCurried] Specify composing for a curried function. - * @returns {Array} Returns the new array of composed arguments. - */ -function composeArgs(args, partials, holders, isCurried) { - var argsIndex = -1, - argsLength = args.length, - holdersLength = holders.length, - leftIndex = -1, - leftLength = partials.length, - rangeLength = nativeMax$5(argsLength - holdersLength, 0), - result = Array(leftLength + rangeLength), - isUncurried = !isCurried; - - while (++leftIndex < leftLength) { - result[leftIndex] = partials[leftIndex]; - } - while (++argsIndex < holdersLength) { - if (isUncurried || argsIndex < argsLength) { - result[holders[argsIndex]] = args[argsIndex]; - } - } - while (rangeLength--) { - result[leftIndex++] = args[argsIndex++]; - } - return result; -} - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax$6 = Math.max; - -/** - * This function is like `composeArgs` except that the arguments composition - * is tailored for `_.partialRight`. - * - * @private - * @param {Array} args The provided arguments. - * @param {Array} partials The arguments to append to those provided. - * @param {Array} holders The `partials` placeholder indexes. - * @params {boolean} [isCurried] Specify composing for a curried function. - * @returns {Array} Returns the new array of composed arguments. - */ -function composeArgsRight(args, partials, holders, isCurried) { - var argsIndex = -1, - argsLength = args.length, - holdersIndex = -1, - holdersLength = holders.length, - rightIndex = -1, - rightLength = partials.length, - rangeLength = nativeMax$6(argsLength - holdersLength, 0), - result = Array(rangeLength + rightLength), - isUncurried = !isCurried; - - while (++argsIndex < rangeLength) { - result[argsIndex] = args[argsIndex]; - } - var offset = argsIndex; - while (++rightIndex < rightLength) { - result[offset + rightIndex] = partials[rightIndex]; - } - while (++holdersIndex < holdersLength) { - if (isUncurried || argsIndex < argsLength) { - result[offset + holders[holdersIndex]] = args[argsIndex++]; - } - } - return result; -} - -/** - * Gets the number of `placeholder` occurrences in `array`. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} placeholder The placeholder to search for. - * @returns {number} Returns the placeholder count. - */ -function countHolders(array, placeholder) { - var length = array.length, - result = 0; - - while (length--) { - if (array[length] === placeholder) { - ++result; - } - } - return result; -} - -/** - * The function whose prototype chain sequence wrappers inherit from. - * - * @private - */ -function baseLodash() { - // No operation performed. -} - -/** Used as references for the maximum length and index of an array. */ -var MAX_ARRAY_LENGTH = 4294967295; - -/** - * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. - * - * @private - * @constructor - * @param {*} value The value to wrap. - */ -function LazyWrapper(value) { - this.__wrapped__ = value; - this.__actions__ = []; - this.__dir__ = 1; - this.__filtered__ = false; - this.__iteratees__ = []; - this.__takeCount__ = MAX_ARRAY_LENGTH; - this.__views__ = []; -} - -// Ensure `LazyWrapper` is an instance of `baseLodash`. -LazyWrapper.prototype = baseCreate(baseLodash.prototype); -LazyWrapper.prototype.constructor = LazyWrapper; - -/** - * Gets metadata for `func`. - * - * @private - * @param {Function} func The function to query. - * @returns {*} Returns the metadata for `func`. - */ -var getData = !metaMap ? noop$3 : function(func) { - return metaMap.get(func); -}; - -/** Used to lookup unminified function names. */ -var realNames = {}; - -/** Used for built-in method references. */ -var objectProto$20 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$17 = objectProto$20.hasOwnProperty; - -/** - * Gets the name of `func`. - * - * @private - * @param {Function} func The function to query. - * @returns {string} Returns the function name. - */ -function getFuncName(func) { - var result = (func.name + ''), - array = realNames[result], - length = hasOwnProperty$17.call(realNames, result) ? array.length : 0; - - while (length--) { - var data = array[length], - otherFunc = data.func; - if (otherFunc == null || otherFunc == func) { - return data.name; - } - } - return result; -} - -/** - * The base constructor for creating `lodash` wrapper objects. - * - * @private - * @param {*} value The value to wrap. - * @param {boolean} [chainAll] Enable explicit method chain sequences. - */ -function LodashWrapper(value, chainAll) { - this.__wrapped__ = value; - this.__actions__ = []; - this.__chain__ = !!chainAll; - this.__index__ = 0; - this.__values__ = undefined; -} - -LodashWrapper.prototype = baseCreate(baseLodash.prototype); -LodashWrapper.prototype.constructor = LodashWrapper; - -/** - * Creates a clone of `wrapper`. - * - * @private - * @param {Object} wrapper The wrapper to clone. - * @returns {Object} Returns the cloned wrapper. - */ -function wrapperClone(wrapper) { - if (wrapper instanceof LazyWrapper) { - return wrapper.clone(); - } - var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); - result.__actions__ = copyArray(wrapper.__actions__); - result.__index__ = wrapper.__index__; - result.__values__ = wrapper.__values__; - return result; -} - -/** Used for built-in method references. */ -var objectProto$21 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$18 = objectProto$21.hasOwnProperty; - -/** - * Creates a `lodash` object which wraps `value` to enable implicit method - * chain sequences. Methods that operate on and return arrays, collections, - * and functions can be chained together. Methods that retrieve a single value - * or may return a primitive value will automatically end the chain sequence - * and return the unwrapped value. Otherwise, the value must be unwrapped - * with `_#value`. - * - * Explicit chain sequences, which must be unwrapped with `_#value`, may be - * enabled using `_.chain`. - * - * The execution of chained methods is lazy, that is, it's deferred until - * `_#value` is implicitly or explicitly called. - * - * Lazy evaluation allows several methods to support shortcut fusion. - * Shortcut fusion is an optimization to merge iteratee calls; this avoids - * the creation of intermediate arrays and can greatly reduce the number of - * iteratee executions. Sections of a chain sequence qualify for shortcut - * fusion if the section is applied to an array and iteratees accept only - * one argument. The heuristic for whether a section qualifies for shortcut - * fusion is subject to change. - * - * Chaining is supported in custom builds as long as the `_#value` method is - * directly or indirectly included in the build. - * - * In addition to lodash methods, wrappers have `Array` and `String` methods. - * - * The wrapper `Array` methods are: - * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` - * - * The wrapper `String` methods are: - * `replace` and `split` - * - * The wrapper methods that support shortcut fusion are: - * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, - * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, - * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` - * - * The chainable wrapper methods are: - * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, - * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, - * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, - * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, - * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, - * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, - * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, - * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, - * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, - * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, - * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, - * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, - * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, - * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, - * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, - * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, - * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, - * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, - * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, - * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, - * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, - * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, - * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, - * `zipObject`, `zipObjectDeep`, and `zipWith` - * - * The wrapper methods that are **not** chainable by default are: - * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, - * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, - * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, - * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, - * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, - * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, - * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, - * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, - * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, - * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, - * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, - * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, - * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, - * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, - * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, - * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, - * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, - * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, - * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, - * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, - * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, - * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, - * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, - * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, - * `upperFirst`, `value`, and `words` - * - * @name _ - * @constructor - * @category Seq - * @param {*} value The value to wrap in a `lodash` instance. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * function square(n) { - * return n * n; - * } - * - * var wrapped = _([1, 2, 3]); - * - * // Returns an unwrapped value. - * wrapped.reduce(_.add); - * // => 6 - * - * // Returns a wrapped value. - * var squares = wrapped.map(square); - * - * _.isArray(squares); - * // => false - * - * _.isArray(squares.value()); - * // => true - */ -function lodash(value) { - if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { - if (value instanceof LodashWrapper) { - return value; + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; } - if (hasOwnProperty$18.call(value, '__wrapped__')) { - return wrapperClone(value); + if (func === other) { + return true; } + var data = getData(other); + return !!data && func === data[0]; } - return new LodashWrapper(value); -} -// Ensure wrappers are instances of `baseLodash`. -lodash.prototype = baseLodash.prototype; -lodash.prototype.constructor = lodash; + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = shortOut(baseSetData); -/** - * Checks if `func` has a lazy counterpart. - * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` has a lazy counterpart, - * else `false`. - */ -function isLaziable(func) { - var funcName = getFuncName(func), - other = lodash[funcName]; + /** Used to match wrap detail comments. */ + var reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; - if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { - return false; - } - if (func === other) { - return true; + /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; } - var data = getData(other); - return !!data && func === data[0]; -} - -/** - * Sets metadata for `func`. - * - * **Note:** If this function becomes hot, i.e. is invoked a lot in a short - * period of time, it will trip its breaker and transition to an identity - * function to avoid garbage collection pauses in V8. See - * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) - * for more details. - * - * @private - * @param {Function} func The function to associate metadata with. - * @param {*} data The metadata. - * @returns {Function} Returns `func`. - */ -var setData = shortOut(baseSetData); - -/** Used to match wrap detail comments. */ -var reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, - reSplitDetails = /,? & /; - -/** - * Extracts wrapper details from the `source` body comment. - * - * @private - * @param {string} source The source to inspect. - * @returns {Array} Returns the wrapper details. - */ -function getWrapDetails(source) { - var match = source.match(reWrapDetails); - return match ? match[1].split(reSplitDetails) : []; -} - -/** Used to match wrap detail comments. */ -var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/; - -/** - * Inserts wrapper `details` in a comment at the top of the `source` body. - * - * @private - * @param {string} source The source to modify. - * @returns {Array} details The details to insert. - * @returns {string} Returns the modified source. - */ -function insertWrapDetails(source, details) { - var length = details.length; - if (!length) { - return source; - } - var lastIndex = length - 1; - details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; - details = details.join(length > 2 ? ', ' : ' '); - return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); -} - -/** Used to compose bitmasks for function metadata. */ -var WRAP_BIND_FLAG$1 = 1, - WRAP_BIND_KEY_FLAG = 2, - WRAP_CURRY_FLAG = 8, - WRAP_CURRY_RIGHT_FLAG = 16, - WRAP_PARTIAL_FLAG = 32, - WRAP_PARTIAL_RIGHT_FLAG = 64, - WRAP_ARY_FLAG = 128, - WRAP_REARG_FLAG = 256, - WRAP_FLIP_FLAG = 512; - -/** Used to associate wrap methods with their bit flags. */ -var wrapFlags = [ - ['ary', WRAP_ARY_FLAG], - ['bind', WRAP_BIND_FLAG$1], - ['bindKey', WRAP_BIND_KEY_FLAG], - ['curry', WRAP_CURRY_FLAG], - ['curryRight', WRAP_CURRY_RIGHT_FLAG], - ['flip', WRAP_FLIP_FLAG], - ['partial', WRAP_PARTIAL_FLAG], - ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], - ['rearg', WRAP_REARG_FLAG] -]; - -/** - * Updates wrapper `details` based on `bitmask` flags. - * - * @private - * @returns {Array} details The details to modify. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @returns {Array} Returns `details`. - */ -function updateWrapDetails(details, bitmask) { - arrayEach(wrapFlags, function(pair) { - var value = '_.' + pair[0]; - if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { - details.push(value); - } - }); - return details.sort(); -} - -/** - * Sets the `toString` method of `wrapper` to mimic the source of `reference` - * with wrapper details in a comment at the top of the source body. - * - * @private - * @param {Function} wrapper The function to modify. - * @param {Function} reference The reference function. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @returns {Function} Returns `wrapper`. - */ -function setWrapToString(wrapper, reference, bitmask) { - var source = (reference + ''); - return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); -} - -/** Used to compose bitmasks for function metadata. */ -var WRAP_BIND_FLAG$2 = 1, - WRAP_BIND_KEY_FLAG$1 = 2, - WRAP_CURRY_BOUND_FLAG = 4, - WRAP_CURRY_FLAG$1 = 8, - WRAP_PARTIAL_FLAG$1 = 32, - WRAP_PARTIAL_RIGHT_FLAG$1 = 64; - -/** - * Creates a function that wraps `func` to continue currying. - * - * @private - * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {Function} wrapFunc The function to create the `func` wrapper. - * @param {*} placeholder The placeholder value. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {Array} [partials] The arguments to prepend to those provided to - * the new function. - * @param {Array} [holders] The `partials` placeholder indexes. - * @param {Array} [argPos] The argument positions of the new function. - * @param {number} [ary] The arity cap of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new wrapped function. - */ -function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { - var isCurry = bitmask & WRAP_CURRY_FLAG$1, - newHolders = isCurry ? holders : undefined, - newHoldersRight = isCurry ? undefined : holders, - newPartials = isCurry ? partials : undefined, - newPartialsRight = isCurry ? undefined : partials; - - bitmask |= (isCurry ? WRAP_PARTIAL_FLAG$1 : WRAP_PARTIAL_RIGHT_FLAG$1); - bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG$1 : WRAP_PARTIAL_FLAG$1); - - if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { - bitmask &= ~(WRAP_BIND_FLAG$2 | WRAP_BIND_KEY_FLAG$1); - } - var newData = [ - func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, - newHoldersRight, argPos, ary, arity - ]; - var result = wrapFunc.apply(undefined, newData); - if (isLaziable(func)) { - setData(result, newData); - } - result.placeholder = placeholder; - return setWrapToString(result, func, bitmask); -} - -/** - * Gets the argument placeholder value for `func`. - * - * @private - * @param {Function} func The function to inspect. - * @returns {*} Returns the placeholder value. - */ -function getHolder(func) { - var object = func; - return object.placeholder; -} - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMin$2 = Math.min; - -/** - * Reorder `array` according to the specified indexes where the element at - * the first index is assigned as the first element, the element at - * the second index is assigned as the second element, and so on. - * - * @private - * @param {Array} array The array to reorder. - * @param {Array} indexes The arranged array indexes. - * @returns {Array} Returns `array`. - */ -function reorder(array, indexes) { - var arrLength = array.length, - length = nativeMin$2(indexes.length, arrLength), - oldArray = copyArray(array); - - while (length--) { - var index = indexes[length]; - array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; - } - return array; -} - -/** Used as the internal argument placeholder. */ -var PLACEHOLDER = '__lodash_placeholder__'; - -/** - * Replaces all `placeholder` elements in `array` with an internal placeholder - * and returns an array of their indexes. - * - * @private - * @param {Array} array The array to modify. - * @param {*} placeholder The placeholder to replace. - * @returns {Array} Returns the new array of placeholder indexes. - */ -function replaceHolders(array, placeholder) { - var index = -1, - length = array.length, - resIndex = 0, - result = []; - - while (++index < length) { - var value = array[index]; - if (value === placeholder || value === PLACEHOLDER) { - array[index] = PLACEHOLDER; - result[resIndex++] = index; - } - } - return result; -} - -/** Used to compose bitmasks for function metadata. */ -var WRAP_BIND_FLAG$3 = 1, - WRAP_BIND_KEY_FLAG$2 = 2, - WRAP_CURRY_FLAG$2 = 8, - WRAP_CURRY_RIGHT_FLAG$1 = 16, - WRAP_ARY_FLAG$1 = 128, - WRAP_FLIP_FLAG$1 = 512; - -/** - * Creates a function that wraps `func` to invoke it with optional `this` - * binding of `thisArg`, partial application, and currying. - * - * @private - * @param {Function|string} func The function or method name to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {Array} [partials] The arguments to prepend to those provided to - * the new function. - * @param {Array} [holders] The `partials` placeholder indexes. - * @param {Array} [partialsRight] The arguments to append to those provided - * to the new function. - * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. - * @param {Array} [argPos] The argument positions of the new function. - * @param {number} [ary] The arity cap of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new wrapped function. - */ -function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { - var isAry = bitmask & WRAP_ARY_FLAG$1, - isBind = bitmask & WRAP_BIND_FLAG$3, - isBindKey = bitmask & WRAP_BIND_KEY_FLAG$2, - isCurried = bitmask & (WRAP_CURRY_FLAG$2 | WRAP_CURRY_RIGHT_FLAG$1), - isFlip = bitmask & WRAP_FLIP_FLAG$1, - Ctor = isBindKey ? undefined : createCtor(func); - - function wrapper() { - var length = arguments.length, - args = Array(length), - index = length; + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/; - while (index--) { - args[index] = arguments[index]; - } - if (isCurried) { - var placeholder = getHolder(wrapper), - holdersCount = countHolders(args, placeholder); - } - if (partials) { - args = composeArgs(args, partials, holders, isCurried); - } - if (partialsRight) { - args = composeArgsRight(args, partialsRight, holdersRight, isCurried); - } - length -= holdersCount; - if (isCurried && length < arity) { - var newHolders = replaceHolders(args, placeholder); - return createRecurry( - func, bitmask, createHybrid, wrapper.placeholder, thisArg, - args, newHolders, argPos, ary, arity - length - ); - } - var thisBinding = isBind ? thisArg : this, - fn = isBindKey ? thisBinding[func] : func; + /** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } - length = args.length; - if (argPos) { - args = reorder(args, argPos); - } else if (isFlip && length > 1) { - args.reverse(); - } - if (isAry && ary < length) { - args.length = ary; - } - if (this && this !== root$2 && this instanceof wrapper) { - fn = Ctor || createCtor(fn); - } - return fn.apply(thisBinding, args); + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG$1 = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256, + WRAP_FLIP_FLAG = 512; + + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', WRAP_ARY_FLAG], + ['bind', WRAP_BIND_FLAG$1], + ['bindKey', WRAP_BIND_KEY_FLAG], + ['curry', WRAP_CURRY_FLAG], + ['curryRight', WRAP_CURRY_RIGHT_FLAG], + ['flip', WRAP_FLIP_FLAG], + ['partial', WRAP_PARTIAL_FLAG], + ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], + ['rearg', WRAP_REARG_FLAG] + ]; + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); } - return wrapper; -} -/** - * Creates a function that wraps `func` to enable currying. - * - * @private - * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {number} arity The arity of `func`. - * @returns {Function} Returns the new wrapped function. - */ -function createCurry(func, bitmask, arity) { - var Ctor = createCtor(func); + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } - function wrapper() { - var length = arguments.length, - args = Array(length), - index = length, - placeholder = getHolder(wrapper); + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG$2 = 1, + WRAP_BIND_KEY_FLAG$1 = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG$1 = 8, + WRAP_PARTIAL_FLAG$1 = 32, + WRAP_PARTIAL_RIGHT_FLAG$1 = 64; - while (index--) { - args[index] = arguments[index]; - } - var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) - ? [] - : replaceHolders(args, placeholder); - - length -= holders.length; - if (length < arity) { - return createRecurry( - func, bitmask, createHybrid, wrapper.placeholder, undefined, - args, holders, undefined, undefined, arity - length); - } - var fn = (this && this !== root$2 && this instanceof wrapper) ? Ctor : func; - return apply(fn, this, args); - } - return wrapper; -} - -/** Used to compose bitmasks for function metadata. */ -var WRAP_BIND_FLAG$4 = 1; - -/** - * Creates a function that wraps `func` to invoke it with the `this` binding - * of `thisArg` and `partials` prepended to the arguments it receives. - * - * @private - * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {*} thisArg The `this` binding of `func`. - * @param {Array} partials The arguments to prepend to those provided to - * the new function. - * @returns {Function} Returns the new wrapped function. - */ -function createPartial(func, bitmask, thisArg, partials) { - var isBind = bitmask & WRAP_BIND_FLAG$4, - Ctor = createCtor(func); - - function wrapper() { - var argsIndex = -1, - argsLength = arguments.length, - leftIndex = -1, - leftLength = partials.length, - args = Array(leftLength + argsLength), - fn = (this && this !== root$2 && this instanceof wrapper) ? Ctor : func; + /** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG$1, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? WRAP_PARTIAL_FLAG$1 : WRAP_PARTIAL_RIGHT_FLAG$1); + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG$1 : WRAP_PARTIAL_FLAG$1); + + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG$2 | WRAP_BIND_KEY_FLAG$1); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; - while (++leftIndex < leftLength) { - args[leftIndex] = partials[leftIndex]; - } - while (argsLength--) { - args[leftIndex++] = arguments[++argsIndex]; - } - return apply(fn, isBind ? thisArg : this, args); - } - return wrapper; -} - -/** Used as the internal argument placeholder. */ -var PLACEHOLDER$1 = '__lodash_placeholder__'; - -/** Used to compose bitmasks for function metadata. */ -var WRAP_BIND_FLAG$5 = 1, - WRAP_BIND_KEY_FLAG$3 = 2, - WRAP_CURRY_BOUND_FLAG$1 = 4, - WRAP_CURRY_FLAG$3 = 8, - WRAP_ARY_FLAG$2 = 128, - WRAP_REARG_FLAG$1 = 256; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMin$3 = Math.min; - -/** - * Merges the function metadata of `source` into `data`. - * - * Merging metadata reduces the number of wrappers used to invoke a function. - * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` - * may be applied regardless of execution order. Methods like `_.ary` and - * `_.rearg` modify function arguments, making the order in which they are - * executed important, preventing the merging of metadata. However, we make - * an exception for a safe combined case where curried functions have `_.ary` - * and or `_.rearg` applied. - * - * @private - * @param {Array} data The destination metadata. - * @param {Array} source The source metadata. - * @returns {Array} Returns `data`. - */ -function mergeData(data, source) { - var bitmask = data[1], - srcBitmask = source[1], - newBitmask = bitmask | srcBitmask, - isCommon = newBitmask < (WRAP_BIND_FLAG$5 | WRAP_BIND_KEY_FLAG$3 | WRAP_ARY_FLAG$2); - - var isCombo = - ((srcBitmask == WRAP_ARY_FLAG$2) && (bitmask == WRAP_CURRY_FLAG$3)) || - ((srcBitmask == WRAP_ARY_FLAG$2) && (bitmask == WRAP_REARG_FLAG$1) && (data[7].length <= source[8])) || - ((srcBitmask == (WRAP_ARY_FLAG$2 | WRAP_REARG_FLAG$1)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG$3)); - - // Exit early if metadata can't be merged. - if (!(isCommon || isCombo)) { - return data; + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); } - // Use source `thisArg` if available. - if (srcBitmask & WRAP_BIND_FLAG$5) { - data[2] = source[2]; - // Set when currying a bound function. - newBitmask |= bitmask & WRAP_BIND_FLAG$5 ? 0 : WRAP_CURRY_BOUND_FLAG$1; - } - // Compose partial arguments. - var value = source[3]; - if (value) { - var partials = data[3]; - data[3] = partials ? composeArgs(partials, value, source[4]) : value; - data[4] = partials ? replaceHolders(data[3], PLACEHOLDER$1) : source[4]; - } - // Compose partial right arguments. - value = source[5]; - if (value) { - partials = data[5]; - data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; - data[6] = partials ? replaceHolders(data[5], PLACEHOLDER$1) : source[6]; - } - // Use source `argPos` if available. - value = source[7]; - if (value) { - data[7] = value; - } - // Use source `ary` if it's smaller. - if (srcBitmask & WRAP_ARY_FLAG$2) { - data[8] = data[8] == null ? source[8] : nativeMin$3(data[8], source[8]); - } - // Use source `arity` if one is not provided. - if (data[9] == null) { - data[9] = source[9]; - } - // Use source `func` and merge bitmasks. - data[0] = source[0]; - data[1] = newBitmask; - - return data; -} - -/** Error message constants. */ -var FUNC_ERROR_TEXT$4 = 'Expected a function'; - -/** Used to compose bitmasks for function metadata. */ -var WRAP_BIND_FLAG$6 = 1, - WRAP_BIND_KEY_FLAG$4 = 2, - WRAP_CURRY_FLAG$4 = 8, - WRAP_CURRY_RIGHT_FLAG$2 = 16, - WRAP_PARTIAL_FLAG$2 = 32, - WRAP_PARTIAL_RIGHT_FLAG$2 = 64; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax$7 = Math.max; - -/** - * Creates a function that either curries or invokes `func` with optional - * `this` binding and partially applied arguments. - * - * @private - * @param {Function|string} func The function or method name to wrap. - * @param {number} bitmask The bitmask flags. - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` or `_.curryRight` of a bound function - * 8 - `_.curry` - * 16 - `_.curryRight` - * 32 - `_.partial` - * 64 - `_.partialRight` - * 128 - `_.rearg` - * 256 - `_.ary` - * 512 - `_.flip` - * @param {*} [thisArg] The `this` binding of `func`. - * @param {Array} [partials] The arguments to be partially applied. - * @param {Array} [holders] The `partials` placeholder indexes. - * @param {Array} [argPos] The argument positions of the new function. - * @param {number} [ary] The arity cap of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new wrapped function. - */ -function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { - var isBindKey = bitmask & WRAP_BIND_KEY_FLAG$4; - if (!isBindKey && typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT$4); - } - var length = partials ? partials.length : 0; - if (!length) { - bitmask &= ~(WRAP_PARTIAL_FLAG$2 | WRAP_PARTIAL_RIGHT_FLAG$2); - partials = holders = undefined; - } - ary = ary === undefined ? ary : nativeMax$7(toInteger(ary), 0); - arity = arity === undefined ? arity : toInteger(arity); - length -= holders ? holders.length : 0; - - if (bitmask & WRAP_PARTIAL_RIGHT_FLAG$2) { - var partialsRight = partials, - holdersRight = holders; - - partials = holders = undefined; - } - var data = isBindKey ? undefined : getData(func); - - var newData = [ - func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, - argPos, ary, arity - ]; - - if (data) { - mergeData(newData, data); - } - func = newData[0]; - bitmask = newData[1]; - thisArg = newData[2]; - partials = newData[3]; - holders = newData[4]; - arity = newData[9] = newData[9] === undefined - ? (isBindKey ? 0 : func.length) - : nativeMax$7(newData[9] - length, 0); - - if (!arity && bitmask & (WRAP_CURRY_FLAG$4 | WRAP_CURRY_RIGHT_FLAG$2)) { - bitmask &= ~(WRAP_CURRY_FLAG$4 | WRAP_CURRY_RIGHT_FLAG$2); - } - if (!bitmask || bitmask == WRAP_BIND_FLAG$6) { - var result = createBind(func, bitmask, thisArg); - } else if (bitmask == WRAP_CURRY_FLAG$4 || bitmask == WRAP_CURRY_RIGHT_FLAG$2) { - result = createCurry(func, bitmask, arity); - } else if ((bitmask == WRAP_PARTIAL_FLAG$2 || bitmask == (WRAP_BIND_FLAG$6 | WRAP_PARTIAL_FLAG$2)) && !holders.length) { - result = createPartial(func, bitmask, thisArg, partials); - } else { - result = createHybrid.apply(undefined, newData); - } - var setter = data ? baseSetData : setData; - return setWrapToString(setter(result, newData), func, bitmask); -} - -/** Used to compose bitmasks for function metadata. */ -var WRAP_BIND_FLAG$7 = 1, - WRAP_PARTIAL_FLAG$3 = 32; - -/** - * Creates a function that invokes `func` with the `this` binding of `thisArg` - * and `partials` prepended to the arguments it receives. - * - * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, - * may be used as a placeholder for partially applied arguments. - * - * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" - * property of bound functions. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to bind. - * @param {*} thisArg The `this` binding of `func`. - * @param {...*} [partials] The arguments to be partially applied. - * @returns {Function} Returns the new bound function. - * @example - * - * function greet(greeting, punctuation) { - * return greeting + ' ' + this.user + punctuation; - * } - * - * var object = { 'user': 'fred' }; - * - * var bound = _.bind(greet, object, 'hi'); - * bound('!'); - * // => 'hi fred!' - * - * // Bound with placeholders. - * var bound = _.bind(greet, object, _, '!'); - * bound('hi'); - * // => 'hi fred!' - */ -var bind$2 = baseRest(function(func, thisArg, partials) { - var bitmask = WRAP_BIND_FLAG$7; - if (partials.length) { - var holders = replaceHolders(partials, getHolder(bind$2)); - bitmask |= WRAP_PARTIAL_FLAG$3; - } - return createWrap(func, bitmask, thisArg, partials, holders); -}); - -// Assign default placeholders. -bind$2.placeholder = {}; - -function presetCollection(collection) { - var maxSearchResults = 50, - maxSuggestionResults = 10; - - var presets = { - - collection: collection, - - - item: function(id) { - return find$1(this.collection, function(d) { - return d.id === id; - }); - }, + /** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = func; + return object.placeholder; + } - matchGeometry: function(geometry) { - return presetCollection(this.collection.filter(function(d) { - return d.matchGeometry(geometry); - })); - }, + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMin$2 = Math.min; + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin$2(indexes.length, arrLength), + oldArray = copyArray(array); - search: function(value, geometry) { - if (!value) return this; + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } - function leading(a) { - var index = a.indexOf(value); - return index === 0 || a[index - 1] === ' '; - } + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; - function suggestionName(name) { - var nameArray = name.split(' - '); - if (nameArray.length > 1) { - name = nameArray.slice(0, nameArray.length - 1).join(' - '); - } - return name.toLowerCase(); - } + /** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } - value = value.toLowerCase(); - - var searchable = filter(this.collection, function(a) { - return a.searchable !== false && a.suggestion !== true; - }), - suggestions = filter(this.collection, function(a) { - return a.suggestion === true; - }); - - - // matches value to preset.name - var leading_name = filter(searchable, function(a) { - return leading(a.name().toLowerCase()); - }).sort(function(a, b) { - var aCompare = a.name().toLowerCase(), - bCompare = b.name().toLowerCase(), - i; - - // priority if search string matches preset name exactly - #4325 - if (value === aCompare) return -1; - if (value === bCompare) return 1; - - // priority for higher matchScore - i = b.originalScore - a.originalScore; - if (i !== 0) return i; - - // priority if search string appears earlier in preset name - i = aCompare.indexOf(value) - bCompare.indexOf(value); - if (i !== 0) return i; - - // priority for shorter preset names - return a.name().length - b.name().length; - }); - - // matches value to preset.terms values - var leading_terms = filter(searchable, function(a) { - return some(a.terms() || [], leading); - }); - - // matches value to preset.tags values - var leading_tag_values = filter(searchable, function(a) { - return some(without(values$1(a.tags || {}), '*'), leading); - }); - - - // finds close matches to value in preset.name - var similar_name = searchable.map(function(a) { - return { - preset: a, - dist: utilEditDistance(value, a.name()) - }; - }).filter(function(a) { - return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3; - }).sort(function(a, b) { - return a.dist - b.dist; - }).map(function(a) { - return a.preset; - }); - - // finds close matches to value in preset.terms - var similar_terms = filter(searchable, function(a) { - return some(a.terms() || [], function(b) { - return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3; - }); - }); - - var leading_suggestions = filter(suggestions, function(a) { - return leading(suggestionName(a.name())); - }).sort(function(a, b) { - a = suggestionName(a.name()); - b = suggestionName(b.name()); - var i = a.indexOf(value) - b.indexOf(value); - if (i === 0) return a.length - b.length; - else return i; - }); - - var similar_suggestions = suggestions.map(function(a) { - return { - preset: a, - dist: utilEditDistance(value, suggestionName(a.name())) - }; - }).filter(function(a) { - return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1; - }).sort(function(a, b) { - return a.dist - b.dist; - }).map(function(a) { - return a.preset; - }); - - var other = presets.item(geometry); - - var results = leading_name.concat( - leading_terms, - leading_tag_values, - leading_suggestions.slice(0, maxSuggestionResults + 5), - similar_name, - similar_terms, - similar_suggestions.slice(0, maxSuggestionResults) - ).slice(0, maxSearchResults - 1); - - return presetCollection(uniq(results.concat(other))); - } - }; + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG$3 = 1, + WRAP_BIND_KEY_FLAG$2 = 2, + WRAP_CURRY_FLAG$2 = 8, + WRAP_CURRY_RIGHT_FLAG$1 = 16, + WRAP_ARY_FLAG$1 = 128, + WRAP_FLIP_FLAG$1 = 512; + /** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & WRAP_ARY_FLAG$1, + isBind = bitmask & WRAP_BIND_FLAG$3, + isBindKey = bitmask & WRAP_BIND_KEY_FLAG$2, + isCurried = bitmask & (WRAP_CURRY_FLAG$2 | WRAP_CURRY_RIGHT_FLAG$1), + isFlip = bitmask & WRAP_FLIP_FLAG$1, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root$2 && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } - return presets; -} + /** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); -function presetCategory(id, category, all) { - category = clone(category); + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); - category.id = id; + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root$2 && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG$4 = 1; - category.members = presetCollection(category.members.map(function(id) { - return all.item(id); - })); + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG$4, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root$2 && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + /** Used as the internal argument placeholder. */ + var PLACEHOLDER$1 = '__lodash_placeholder__'; - category.matchGeometry = function(geometry) { - return category.geometry.indexOf(geometry) >= 0; - }; + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG$5 = 1, + WRAP_BIND_KEY_FLAG$3 = 2, + WRAP_CURRY_BOUND_FLAG$1 = 4, + WRAP_CURRY_FLAG$3 = 8, + WRAP_ARY_FLAG$2 = 128, + WRAP_REARG_FLAG$1 = 256; + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMin$3 = Math.min; - category.matchScore = function() { - return -1; - }; + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (WRAP_BIND_FLAG$5 | WRAP_BIND_KEY_FLAG$3 | WRAP_ARY_FLAG$2); + + var isCombo = + ((srcBitmask == WRAP_ARY_FLAG$2) && (bitmask == WRAP_CURRY_FLAG$3)) || + ((srcBitmask == WRAP_ARY_FLAG$2) && (bitmask == WRAP_REARG_FLAG$1) && (data[7].length <= source[8])) || + ((srcBitmask == (WRAP_ARY_FLAG$2 | WRAP_REARG_FLAG$1)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG$3)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & WRAP_BIND_FLAG$5) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & WRAP_BIND_FLAG$5 ? 0 : WRAP_CURRY_BOUND_FLAG$1; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER$1) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER$1) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & WRAP_ARY_FLAG$2) { + data[8] = data[8] == null ? source[8] : nativeMin$3(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + return data; + } - category.name = function() { - return t('presets.categories.' + id + '.name', {'default': id}); - }; + /** Error message constants. */ + var FUNC_ERROR_TEXT$4 = 'Expected a function'; + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG$6 = 1, + WRAP_BIND_KEY_FLAG$4 = 2, + WRAP_CURRY_FLAG$4 = 8, + WRAP_CURRY_RIGHT_FLAG$2 = 16, + WRAP_PARTIAL_FLAG$2 = 32, + WRAP_PARTIAL_RIGHT_FLAG$2 = 64; - category.terms = function() { - return []; - }; + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMax$7 = Math.max; + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG$4; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT$4); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(WRAP_PARTIAL_FLAG$2 | WRAP_PARTIAL_RIGHT_FLAG$2); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax$7(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; - return category; -} + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG$2) { + var partialsRight = partials, + holdersRight = holders; -function presetField(id, field) { - field = clone(field); + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); - field.id = id; + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] === undefined + ? (isBindKey ? 0 : func.length) + : nativeMax$7(newData[9] - length, 0); + + if (!arity && bitmask & (WRAP_CURRY_FLAG$4 | WRAP_CURRY_RIGHT_FLAG$2)) { + bitmask &= ~(WRAP_CURRY_FLAG$4 | WRAP_CURRY_RIGHT_FLAG$2); + } + if (!bitmask || bitmask == WRAP_BIND_FLAG$6) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG$4 || bitmask == WRAP_CURRY_RIGHT_FLAG$2) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG$2 || bitmask == (WRAP_BIND_FLAG$6 | WRAP_PARTIAL_FLAG$2)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); + } - field.matchGeometry = function(geometry) { - return !field.geometry || field.geometry === geometry; - }; + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG$7 = 1, + WRAP_PARTIAL_FLAG$3 = 32; + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind$2 = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG$7; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind$2)); + bitmask |= WRAP_PARTIAL_FLAG$3; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); - field.t = function(scope, options) { - return t('presets.fields.' + id + '.' + scope, options); - }; + // Assign default placeholders. + bind$2.placeholder = {}; + function presetCollection(collection) { + var maxSearchResults = 50, + maxSuggestionResults = 10; + + var presets = { - field.label = function() { - return field.t('label', {'default': id}); - }; + collection: collection, + + + item: function(id) { + return find$1(this.collection, function(d) { + return d.id === id; + }); + }, + + + matchGeometry: function(geometry) { + return presetCollection(this.collection.filter(function(d) { + return d.matchGeometry(geometry); + })); + }, + + + search: function(value, geometry) { + if (!value) return this; + + function leading(a) { + var index = a.indexOf(value); + return index === 0 || a[index - 1] === ' '; + } + + function suggestionName(name) { + var nameArray = name.split(' - '); + if (nameArray.length > 1) { + name = nameArray.slice(0, nameArray.length - 1).join(' - '); + } + return name.toLowerCase(); + } + + + value = value.toLowerCase(); + + var searchable = filter(this.collection, function(a) { + return a.searchable !== false && a.suggestion !== true; + }), + suggestions = filter(this.collection, function(a) { + return a.suggestion === true; + }); + + + // matches value to preset.name + var leading_name = filter(searchable, function(a) { + return leading(a.name().toLowerCase()); + }).sort(function(a, b) { + var aCompare = a.name().toLowerCase(), + bCompare = b.name().toLowerCase(), + i; + + // priority if search string matches preset name exactly - #4325 + if (value === aCompare) return -1; + if (value === bCompare) return 1; + + // priority for higher matchScore + i = b.originalScore - a.originalScore; + if (i !== 0) return i; + + // priority if search string appears earlier in preset name + i = aCompare.indexOf(value) - bCompare.indexOf(value); + if (i !== 0) return i; + + // priority for shorter preset names + return a.name().length - b.name().length; + }); + + // matches value to preset.terms values + var leading_terms = filter(searchable, function(a) { + return some(a.terms() || [], leading); + }); + + // matches value to preset.tags values + var leading_tag_values = filter(searchable, function(a) { + return some(without(values$1(a.tags || {}), '*'), leading); + }); + + + // finds close matches to value in preset.name + var similar_name = searchable.map(function(a) { + return { + preset: a, + dist: utilEditDistance(value, a.name()) + }; + }).filter(function(a) { + return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3; + }).sort(function(a, b) { + return a.dist - b.dist; + }).map(function(a) { + return a.preset; + }); + + // finds close matches to value in preset.terms + var similar_terms = filter(searchable, function(a) { + return some(a.terms() || [], function(b) { + return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3; + }); + }); + + var leading_suggestions = filter(suggestions, function(a) { + return leading(suggestionName(a.name())); + }).sort(function(a, b) { + a = suggestionName(a.name()); + b = suggestionName(b.name()); + var i = a.indexOf(value) - b.indexOf(value); + if (i === 0) return a.length - b.length; + else return i; + }); + + var similar_suggestions = suggestions.map(function(a) { + return { + preset: a, + dist: utilEditDistance(value, suggestionName(a.name())) + }; + }).filter(function(a) { + return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1; + }).sort(function(a, b) { + return a.dist - b.dist; + }).map(function(a) { + return a.preset; + }); + + var other = presets.item(geometry); + + var results = leading_name.concat( + leading_terms, + leading_tag_values, + leading_suggestions.slice(0, maxSuggestionResults + 5), + similar_name, + similar_terms, + similar_suggestions.slice(0, maxSuggestionResults) + ).slice(0, maxSearchResults - 1); + + return presetCollection(uniq(results.concat(other))); + } + }; - var placeholder = field.placeholder; - field.placeholder = function() { - return field.t('placeholder', {'default': placeholder}); - }; + return presets; + } + function presetCategory(id, category, all) { + category = clone(category); - return field; -} + category.id = id; -function presetPreset(id, preset, fields) { - preset = clone(preset); - preset.id = id; - preset.fields = (preset.fields || []).map(getFields); - preset.geometry = (preset.geometry || []); + category.members = presetCollection(category.members.map(function(id) { + return all.item(id); + })); - function getFields(f) { - return fields[f]; - } + category.matchGeometry = function(geometry) { + return category.geometry.indexOf(geometry) >= 0; + }; - preset.matchGeometry = function(geometry) { - return preset.geometry.indexOf(geometry) >= 0; - }; + category.matchScore = function() { + return -1; + }; - preset.originalScore = preset.matchScore || 1; + category.name = function() { + return t('presets.categories.' + id + '.name', {'default': id}); + }; - preset.matchScore = function(entity) { - var tags = preset.tags, - score = 0; + category.terms = function() { + return []; + }; - for (var t$$1 in tags) { - if (entity.tags[t$$1] === tags[t$$1]) { - score += preset.originalScore; - } else if (tags[t$$1] === '*' && t$$1 in entity.tags) { - score += preset.originalScore / 2; - } else { - return -1; - } - } - return score; - }; + return category; + } + function presetField(id, field) { + field = clone(field); - preset.t = function(scope, options) { - return t('presets.presets.' + id + '.' + scope, options); - }; + field.id = id; + // for use in classes, element ids, css selectors + field.safeid = id.replace(/[^_a-zA-Z0-9\-]/g, '_'); - var origName = preset.name || ''; - preset.name = function() { - if (preset.suggestion) { - id = id.split('/'); - id = id[0] + '/' + id[1]; - return origName + ' - ' + t('presets.presets.' + id + '.name'); - } - return preset.t('name', { 'default': origName }); - }; + field.matchGeometry = function(geometry) { + return !field.geometry || field.geometry === geometry; + }; - var origTerms = (preset.terms || []).join(); - preset.terms = function() { - return preset.t('terms', { 'default': origTerms }).toLowerCase().trim().split(/\s*,+\s*/); - }; + field.t = function(scope, options) { + return t('presets.fields.' + id + '.' + scope, options); + }; - preset.isFallback = function() { - var tagCount = Object.keys(preset.tags).length; - return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area')); - }; + field.label = function() { + return field.t('label', {'default': id}); + }; - var reference = preset.reference || {}; - preset.reference = function(geometry) { - var key = reference.key || Object.keys(omit(preset.tags, 'name'))[0], - value = reference.value || preset.tags[key]; - if (geometry === 'relation' && key === 'type') { - if (value in preset.tags) { - key = value; - value = preset.tags[key]; - } else { - return { rtype: value }; - } - } + var placeholder = field.placeholder; + field.placeholder = function() { + return field.t('placeholder', {'default': placeholder}); + }; - if (value === '*') { - return { key: key }; - } else { - return { key: key, value: value }; - } - }; + return field; + } - var removeTags = preset.removeTags || preset.tags || {}; - preset.removeTags = function(tags, geometry) { - tags = omit(tags, keys$1(removeTags)); + function presetPreset(id, preset, fields) { + preset = clone(preset); - for (var f in preset.fields) { - var field = preset.fields[f]; - if (field.matchGeometry(geometry) && field.default === tags[field.key]) { - delete tags[field.key]; - } - } + preset.id = id; + preset.fields = (preset.fields || []).map(getFields); + preset.geometry = (preset.geometry || []); - delete tags.area; - return tags; - }; + function getFields(f) { + return fields[f]; + } - var applyTags = preset.addTags || preset.tags || {}; - preset.applyTags = function(tags, geometry) { - var k; - tags = clone(tags); + preset.matchGeometry = function(geometry) { + return preset.geometry.indexOf(geometry) >= 0; + }; - for (k in applyTags) { - if (applyTags[k] === '*') { - tags[k] = 'yes'; - } else { - tags[k] = applyTags[k]; - } - } - // Add area=yes if necessary. - // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of: - // 1. chosen preset could be either an area or a line (`barrier=city_wall`) - // 2. chosen preset doesn't have a key in areaKeys (`railway=station`) - if (!applyTags.hasOwnProperty('area')) { - delete tags.area; - if (geometry === 'area') { - var needsAreaTag = true; - if (preset.geometry.indexOf('line') === -1) { - for (k in applyTags) { - if (k in areaKeys) { - needsAreaTag = false; - break; - } - } - } - if (needsAreaTag) { - tags.area = 'yes'; - } - } - } + preset.originalScore = preset.matchScore || 1; - for (var f in preset.fields) { - var field = preset.fields[f]; - if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) { - tags[field.key] = field.default; - } - } - return tags; - }; + preset.matchScore = function(entity) { + var tags = preset.tags, + score = 0; + for (var t$$1 in tags) { + if (entity.tags[t$$1] === tags[t$$1]) { + score += preset.originalScore; + } else if (tags[t$$1] === '*' && t$$1 in entity.tags) { + score += preset.originalScore / 2; + } else { + return -1; + } + } - return preset; -} + return score; + }; -function presetIndex() { - // a presetCollection with methods for - // loading new data and returning defaults - var all = presetCollection([]); - var _defaults = { area: all, line: all, point: all, vertex: all, relation: all }; - var _fields = {}; - var _universal = []; - var _recent = presetCollection([]); + preset.t = function(scope, options) { + return t('presets.presets.' + id + '.' + scope, options); + }; - // Index of presets by (geometry, tag key). - var _index = { - point: {}, - vertex: {}, - line: {}, - area: {}, - relation: {} - }; - all.match = function(entity, resolver) { - var geometry = entity.geometry(resolver); - var address; + var origName = preset.name || ''; + preset.name = function() { + if (preset.suggestion) { + id = id.split('/'); + id = id[0] + '/' + id[1]; + return origName + ' - ' + t('presets.presets.' + id + '.name'); + } + return preset.t('name', { 'default': origName }); + }; - // Treat entities on addr:interpolation lines as points, not vertices - #3241 - if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) { - geometry = 'point'; - } + var origTerms = (preset.terms || []).join(); + preset.terms = function() { + return preset.t('terms', { 'default': origTerms }).toLowerCase().trim().split(/\s*,+\s*/); + }; - var geometryMatches = _index[geometry]; - var best = -1; - var match; - for (var k in entity.tags) { - // If any part of an address is present, - // allow fallback to "Address" preset - #4353 - if (k.match(/^addr:/) !== null && geometryMatches['addr:*']) { - address = geometryMatches['addr:*'][0]; - } + preset.isFallback = function() { + var tagCount = Object.keys(preset.tags).length; + return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area')); + }; - var keyMatches = geometryMatches[k]; - if (!keyMatches) continue; - for (var i = 0; i < keyMatches.length; i++) { - var score = keyMatches[i].matchScore(entity); - if (score > best) { - best = score; - match = keyMatches[i]; - } - } - } + var reference = preset.reference || {}; + preset.reference = function(geometry) { + var key = reference.key || Object.keys(omit(preset.tags, 'name'))[0], + value = reference.value || preset.tags[key]; - if (address && (!match || match.isFallback())) { - match = address; - } + if (geometry === 'relation' && key === 'type') { + if (value in preset.tags) { + key = value; + value = preset.tags[key]; + } else { + return { rtype: value }; + } + } - return match || all.item(geometry); - }; + if (value === '*') { + return { key: key }; + } else { + return { key: key, value: value }; + } + }; - // Because of the open nature of tagging, iD will never have a complete - // list of tags used in OSM, so we want it to have logic like "assume - // that a closed way with an amenity tag is an area, unless the amenity - // is one of these specific types". This function computes a structure - // that allows testing of such conditions, based on the presets designated - // as as supporting (or not supporting) the area geometry. - // - // The returned object L is a whitelist/blacklist of tags. A closed way - // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])` - // (see `Way#isArea()`). In other words, the keys of L form the whitelist, - // and the subkeys form the blacklist. - all.areaKeys = function() { - var areaKeys = {}; - var ignore = ['barrier', 'highway', 'footway', 'railway', 'type']; // probably a line.. - var presets = reject(all.collection, 'suggestion'); - - // whitelist - presets.forEach(function(d) { - for (var key in d.tags) break; - if (!key) return; - if (ignore.indexOf(key) !== -1) return; - - if (d.geometry.indexOf('area') !== -1) { // probably an area.. - areaKeys[key] = areaKeys[key] || {}; - } - }); + var removeTags = preset.removeTags || preset.tags || {}; + preset.removeTags = function(tags, geometry) { + tags = omit(tags, keys$1(removeTags)); - // blacklist - presets.forEach(function(d) { - for (var key in d.tags) break; - if (!key) return; - if (ignore.indexOf(key) !== -1) return; - - var value = d.tags[key]; - if (key in areaKeys && // probably an area... - d.geometry.indexOf('line') !== -1 && // but sometimes a line - value !== '*') { - areaKeys[key][value] = true; - } - }); + for (var f in preset.fields) { + var field = preset.fields[f]; + if (field.matchGeometry(geometry) && field.default === tags[field.key]) { + delete tags[field.key]; + } + } - return areaKeys; - }; + delete tags.area; + return tags; + }; - all.init = function() { - var d = data.presets; + var applyTags = preset.addTags || preset.tags || {}; + preset.applyTags = function(tags, geometry) { + var k; - all.collection = []; - _recent.collection = []; - _fields = {}; - _universal = []; - _index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} }; + tags = clone(tags); - if (d.fields) { - forEach(d.fields, function(d, id) { - _fields[id] = presetField(id, d); - if (d.universal) { - _universal.push(_fields[id]); - } - }); - } + for (k in applyTags) { + if (applyTags[k] === '*') { + tags[k] = 'yes'; + } else { + tags[k] = applyTags[k]; + } + } - if (d.presets) { - forEach(d.presets, function(d, id) { - all.collection.push(presetPreset(id, d, _fields)); - }); - } + // Add area=yes if necessary. + // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of: + // 1. chosen preset could be either an area or a line (`barrier=city_wall`) + // 2. chosen preset doesn't have a key in areaKeys (`railway=station`) + if (!applyTags.hasOwnProperty('area')) { + delete tags.area; + if (geometry === 'area') { + var needsAreaTag = true; + if (preset.geometry.indexOf('line') === -1) { + for (k in applyTags) { + if (k in areaKeys) { + needsAreaTag = false; + break; + } + } + } + if (needsAreaTag) { + tags.area = 'yes'; + } + } + } - if (d.categories) { - forEach(d.categories, function(d, id) { - all.collection.push(presetCategory(id, d, all)); - }); - } + for (var f in preset.fields) { + var field = preset.fields[f]; + if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) { + tags[field.key] = field.default; + } + } - if (d.defaults) { - var getItem = bind$2(all.item, all); - _defaults = { - area: presetCollection(d.defaults.area.map(getItem)), - line: presetCollection(d.defaults.line.map(getItem)), - point: presetCollection(d.defaults.point.map(getItem)), - vertex: presetCollection(d.defaults.vertex.map(getItem)), - relation: presetCollection(d.defaults.relation.map(getItem)) - }; - } + return tags; + }; - for (var i = 0; i < all.collection.length; i++) { - var preset = all.collection[i]; - var geometry = preset.geometry; - for (var j = 0; j < geometry.length; j++) { - var g = _index[geometry[j]]; - for (var k in preset.tags) { - (g[k] = g[k] || []).push(preset); - } - } - } + return preset; + } - return all; - }; + function presetIndex() { + // a presetCollection with methods for + // loading new data and returning defaults + + var all = presetCollection([]); + var _defaults = { area: all, line: all, point: all, vertex: all, relation: all }; + var _fields = {}; + var _universal = []; + var _recent = presetCollection([]); + + // Index of presets by (geometry, tag key). + var _index = { + point: {}, + vertex: {}, + line: {}, + area: {}, + relation: {} + }; - all.field = function(id) { - return _fields[id]; - }; + all.match = function(entity, resolver) { + var geometry = entity.geometry(resolver); + var address; - all.universal = function() { - return _universal; - }; + // Treat entities on addr:interpolation lines as points, not vertices - #3241 + if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) { + geometry = 'point'; + } - all.defaults = function(geometry, n) { - var rec = _recent.matchGeometry(geometry).collection.slice(0, 4); - var def = uniq(rec.concat(_defaults[geometry].collection)).slice(0, n - 1); - return presetCollection(uniq(rec.concat(def).concat(all.item(geometry)))); - }; + var geometryMatches = _index[geometry]; + var best = -1; + var match; + + for (var k in entity.tags) { + // If any part of an address is present, + // allow fallback to "Address" preset - #4353 + if (k.match(/^addr:/) !== null && geometryMatches['addr:*']) { + address = geometryMatches['addr:*'][0]; + } + + var keyMatches = geometryMatches[k]; + if (!keyMatches) continue; + + for (var i = 0; i < keyMatches.length; i++) { + var score = keyMatches[i].matchScore(entity); + if (score > best) { + best = score; + match = keyMatches[i]; + } + } + } - all.choose = function(preset) { - _recent = presetCollection(uniq([preset].concat(_recent.collection))); - return all; - }; + if (address && (!match || match.isFallback())) { + match = address; + } - return all; -} + return match || all.item(geometry); + }; -var areaKeys = {}; -function setAreaKeys(value) { - areaKeys = value; -} + // Because of the open nature of tagging, iD will never have a complete + // list of tags used in OSM, so we want it to have logic like "assume + // that a closed way with an amenity tag is an area, unless the amenity + // is one of these specific types". This function computes a structure + // that allows testing of such conditions, based on the presets designated + // as as supporting (or not supporting) the area geometry. + // + // The returned object L is a whitelist/blacklist of tags. A closed way + // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])` + // (see `Way#isArea()`). In other words, the keys of L form the whitelist, + // and the subkeys form the blacklist. + all.areaKeys = function() { + var areaKeys = {}; + var ignore = ['barrier', 'highway', 'footway', 'railway', 'type']; // probably a line.. + var presets = reject(all.collection, 'suggestion'); + + // whitelist + presets.forEach(function(d) { + for (var key in d.tags) break; + if (!key) return; + if (ignore.indexOf(key) !== -1) return; + + if (d.geometry.indexOf('area') !== -1) { // probably an area.. + areaKeys[key] = areaKeys[key] || {}; + } + }); + // blacklist + presets.forEach(function(d) { + for (var key in d.tags) break; + if (!key) return; + if (ignore.indexOf(key) !== -1) return; + + var value = d.tags[key]; + if (key in areaKeys && // probably an area... + d.geometry.indexOf('line') !== -1 && // but sometimes a line + value !== '*') { + areaKeys[key][value] = true; + } + }); -function coreContext() { - var context = {}; - context.version = '2.7.1'; + return areaKeys; + }; - // create a special translation that contains the keys in place of the strings - var tkeys = cloneDeep(en); - var parents = []; - function traverser(v, k, obj) { - parents.push(k); - if (isObject(v)) { - forOwn(v, traverser); - } else if (isString(v)) { - obj[k] = parents.join('.'); - } - parents.pop(); - } + all.init = function() { + var d = data.presets; - forOwn(tkeys, traverser); - addTranslation('_tkeys_', tkeys); + all.collection = []; + _recent.collection = []; + _fields = {}; + _universal = []; + _index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} }; - addTranslation('en', en); - setLocale('en'); + if (d.fields) { + forEach(d.fields, function(d, id) { + _fields[id] = presetField(id, d); + if (d.universal) { + _universal.push(_fields[id]); + } + }); + } - var dispatch$$1 = dispatch('enter', 'exit', 'change'); + if (d.presets) { + forEach(d.presets, function(d, id) { + all.collection.push(presetPreset(id, d, _fields)); + }); + } - // https://github.com/openstreetmap/iD/issues/772 - // http://mathiasbynens.be/notes/localstorage-pattern#comment-9 - var storage; - try { storage = localStorage; } catch (e) {} // eslint-disable-line no-empty - storage = storage || (function() { - var s = {}; - return { - getItem: function(k) { return s[k]; }, - setItem: function(k, v) { s[k] = v; }, - removeItem: function(k) { delete s[k]; } - }; - })(); + if (d.categories) { + forEach(d.categories, function(d, id) { + all.collection.push(presetCategory(id, d, all)); + }); + } - context.storage = function(k, v) { - try { - if (arguments.length === 1) return storage.getItem(k); - else if (v === null) storage.removeItem(k); - else storage.setItem(k, v); - } catch (e) { - // localstorage quota exceeded - /* eslint-disable no-console */ - if (typeof console !== 'undefined') console.error('localStorage quota exceeded'); - /* eslint-enable no-console */ - } - }; + if (d.defaults) { + var getItem = bind$2(all.item, all); + _defaults = { + area: presetCollection(d.defaults.area.map(getItem)), + line: presetCollection(d.defaults.line.map(getItem)), + point: presetCollection(d.defaults.point.map(getItem)), + vertex: presetCollection(d.defaults.vertex.map(getItem)), + relation: presetCollection(d.defaults.relation.map(getItem)) + }; + } + for (var i = 0; i < all.collection.length; i++) { + var preset = all.collection[i]; + var geometry = preset.geometry; - /* Straight accessors. Avoid using these if you can. */ - var ui, connection, history; - context.ui = function() { return ui; }; - context.connection = function() { return connection; }; - context.history = function() { return history; }; + for (var j = 0; j < geometry.length; j++) { + var g = _index[geometry[j]]; + for (var k in preset.tags) { + (g[k] = g[k] || []).push(preset); + } + } + } + return all; + }; - /* Connection */ - context.preauth = function(options) { - if (connection) { - connection.switch(options); - } - return context; - }; + all.field = function(id) { + return _fields[id]; + }; - context.loadTiles = utilCallWhenIdle(function(projection, dimensions, callback) { - var cid; - function done(err, result) { - if (connection.getConnectionId() !== cid) { - if (callback) callback({ message: 'Connection Switched', status: -1 }); - return; - } - if (!err) history.merge(result.data, result.extent); - if (callback) callback(err, result); - } - if (connection && context.editable()) { - cid = connection.getConnectionId(); - connection.loadTiles(projection, dimensions, done); - } - }); + all.universal = function() { + return _universal; + }; - context.loadEntity = function(entityId, callback) { - var cid; - function done(err, result) { - if (connection.getConnectionId() !== cid) { - if (callback) callback({ message: 'Connection Switched', status: -1 }); - return; - } - if (!err) history.merge(result.data, result.extent); - if (callback) callback(err, result); - } - if (connection) { - cid = connection.getConnectionId(); - connection.loadEntity(entityId, done); - } - }; + all.defaults = function(geometry, n) { + var rec = _recent.matchGeometry(geometry).collection.slice(0, 4); + var def = uniq(rec.concat(_defaults[geometry].collection)).slice(0, n - 1); + return presetCollection(uniq(rec.concat(def).concat(all.item(geometry)))); + }; - context.zoomToEntity = function(entityId, zoomTo) { - if (zoomTo !== false) { - this.loadEntity(entityId, function(err, result) { - if (err) return; - var entity = find$1(result.data, function(e) { return e.id === entityId; }); - if (entity) { map.zoomTo(entity); } - }); - } + all.choose = function(preset) { + _recent = presetCollection(uniq([preset].concat(_recent.collection))); + return all; + }; - map.on('drawn.zoomToEntity', function() { - if (!context.hasEntity(entityId)) return; - map.on('drawn.zoomToEntity', null); - context.on('enter.zoomToEntity', null); - context.enter(modeSelect(context, [entityId])); - }); + return all; + } - context.on('enter.zoomToEntity', function() { - if (mode.id !== 'browse') { - map.on('drawn.zoomToEntity', null); - context.on('enter.zoomToEntity', null); - } - }); - }; + var areaKeys = {}; - var minEditableZoom = 16; - context.minEditableZoom = function(_) { - if (!arguments.length) return minEditableZoom; - minEditableZoom = _; - if (connection) { - connection.tileZoom(_); - } - return context; - }; + function setAreaKeys(value) { + areaKeys = value; + } - /* History */ - var inIntro = false; - context.inIntro = function(_) { - if (!arguments.length) return inIntro; - inIntro = _; - return context; - }; + function coreContext() { + var context = {}; + context.version = '2.8.2'; - context.save = function() { - // no history save, no message onbeforeunload - if (inIntro || d3_select('.modal').size()) return; + // create a special translation that contains the keys in place of the strings + var tkeys = cloneDeep(en); + var parents = []; - var canSave; - if (mode && mode.id === 'save') { - canSave = false; - } else { - canSave = context.selectedIDs().every(function(id) { - var entity = context.hasEntity(id); - return entity && !entity.isDegenerate(); - }); - } + function traverser(v, k, obj) { + parents.push(k); + if (isObject(v)) { + forOwn(v, traverser); + } else if (isString(v)) { + obj[k] = parents.join('.'); + } + parents.pop(); + } - if (canSave) { - history.save(); - } - if (history.hasChanges()) { - return t('save.unsaved_changes'); - } - }; + forOwn(tkeys, traverser); + addTranslation('_tkeys_', tkeys); + addTranslation('en', en); + setLocale('en'); - /* Graph */ - context.hasEntity = function(id) { - return history.graph().hasEntity(id); - }; - context.entity = function(id) { - return history.graph().entity(id); - }; - context.childNodes = function(way) { - return history.graph().childNodes(way); - }; - context.geometry = function(id) { - return context.entity(id).geometry(history.graph()); - }; + var dispatch$$1 = dispatch('enter', 'exit', 'change'); + // https://github.com/openstreetmap/iD/issues/772 + // http://mathiasbynens.be/notes/localstorage-pattern#comment-9 + var storage; + try { storage = localStorage; } catch (e) {} // eslint-disable-line no-empty + storage = storage || (function() { + var s = {}; + return { + getItem: function(k) { return s[k]; }, + setItem: function(k, v) { s[k] = v; }, + removeItem: function(k) { delete s[k]; } + }; + })(); + + context.storage = function(k, v) { + try { + if (arguments.length === 1) return storage.getItem(k); + else if (v === null) storage.removeItem(k); + else storage.setItem(k, v); + } catch (e) { + // localstorage quota exceeded + /* eslint-disable no-console */ + if (typeof console !== 'undefined') console.error('localStorage quota exceeded'); + /* eslint-enable no-console */ + } + }; - /* Modes */ - var mode; - context.mode = function() { - return mode; - }; - context.enter = function(newMode) { - if (mode) { - mode.exit(); - dispatch$$1.call('exit', this, mode); - } - mode = newMode; - mode.enter(); - dispatch$$1.call('enter', this, mode); - }; + /* Straight accessors. Avoid using these if you can. */ + var ui, connection, history; + context.ui = function() { return ui; }; + context.connection = function() { return connection; }; + context.history = function() { return history; }; - context.selectedIDs = function() { - if (mode && mode.selectedIDs) { - return mode.selectedIDs(); - } else { - return []; - } - }; - context.activeID = function() { - return mode && mode.activeID && mode.activeID(); - }; + /* Connection */ + context.preauth = function(options) { + if (connection) { + connection.switch(options); + } + return context; + }; - /* Behaviors */ - context.install = function(behavior) { - context.surface().call(behavior); - }; - context.uninstall = function(behavior) { - context.surface().call(behavior.off); - }; + context.loadTiles = utilCallWhenIdle(function(projection, dimensions, callback) { + var cid; + function done(err, result) { + if (connection.getConnectionId() !== cid) { + if (callback) callback({ message: 'Connection Switched', status: -1 }); + return; + } + if (!err) history.merge(result.data, result.extent); + if (callback) callback(err, result); + } + if (connection && context.editable()) { + cid = connection.getConnectionId(); + connection.loadTiles(projection, dimensions, done); + } + }); + context.loadEntity = function(entityId, callback) { + var cid; + function done(err, result) { + if (connection.getConnectionId() !== cid) { + if (callback) callback({ message: 'Connection Switched', status: -1 }); + return; + } + if (!err) history.merge(result.data, result.extent); + if (callback) callback(err, result); + } + if (connection) { + cid = connection.getConnectionId(); + connection.loadEntity(entityId, done); + } + }; - /* Copy/Paste */ - var copyIDs = [], copyGraph; - context.copyGraph = function() { return copyGraph; }; - context.copyIDs = function(_) { - if (!arguments.length) return copyIDs; - copyIDs = _; - copyGraph = history.graph(); - return context; - }; + context.zoomToEntity = function(entityId, zoomTo) { + if (zoomTo !== false) { + this.loadEntity(entityId, function(err, result) { + if (err) return; + var entity = find$1(result.data, function(e) { return e.id === entityId; }); + if (entity) { map.zoomTo(entity); } + }); + } + map.on('drawn.zoomToEntity', function() { + if (!context.hasEntity(entityId)) return; + map.on('drawn.zoomToEntity', null); + context.on('enter.zoomToEntity', null); + context.enter(modeSelect(context, [entityId])); + }); - /* Background */ - var background; - context.background = function() { return background; }; + context.on('enter.zoomToEntity', function() { + if (mode.id !== 'browse') { + map.on('drawn.zoomToEntity', null); + context.on('enter.zoomToEntity', null); + } + }); + }; + var minEditableZoom = 16; + context.minEditableZoom = function(_) { + if (!arguments.length) return minEditableZoom; + minEditableZoom = _; + if (connection) { + connection.tileZoom(_); + } + return context; + }; - /* Features */ - var features; - context.features = function() { return features; }; - context.hasHiddenConnections = function(id) { - var graph = history.graph(), - entity = graph.entity(id); - return features.hasHiddenConnections(entity, graph); - }; + /* History */ + var inIntro = false; + context.inIntro = function(_) { + if (!arguments.length) return inIntro; + inIntro = _; + return context; + }; - /* Presets */ - var presets; - context.presets = function() { return presets; }; + context.save = function() { + // no history save, no message onbeforeunload + if (inIntro || select('.modal').size()) return; + var canSave; + if (mode && mode.id === 'save') { + canSave = false; + } else { + canSave = context.selectedIDs().every(function(id) { + var entity = context.hasEntity(id); + return entity && !entity.isDegenerate(); + }); + } - /* Map */ - var map; - context.map = function() { return map; }; - context.layers = function() { return map.layers; }; - context.surface = function() { return map.surface; }; - context.editable = function() { return map.editable(); }; - context.surfaceRect = function() { - return map.surface.node().getBoundingClientRect(); - }; + if (canSave) { + history.save(); + } + if (history.hasChanges()) { + return t('save.unsaved_changes'); + } + }; - /* Debug */ - var debugFlags = { - tile: false, // tile boundaries - collision: false, // label collision bounding boxes - imagery: false, // imagery bounding polygons - imperial: false, // imperial (not metric) bounding polygons - driveLeft: false, // driveLeft bounding polygons - target: false // touch targets - }; - context.debugFlags = function() { - return debugFlags; - }; - context.setDebug = function(flag, val) { - if (arguments.length === 1) val = true; - debugFlags[flag] = val; - dispatch$$1.call('change'); - return context; - }; - context.getDebug = function(flag) { - return flag && debugFlags[flag]; - }; + /* Graph */ + context.hasEntity = function(id) { + return history.graph().hasEntity(id); + }; + context.entity = function(id) { + return history.graph().entity(id); + }; + context.childNodes = function(way) { + return history.graph().childNodes(way); + }; + context.geometry = function(id) { + return context.entity(id).geometry(history.graph()); + }; - /* Container */ - var container = d3_select(document.body); - context.container = function(_) { - if (!arguments.length) return container; - container = _; - container.classed('id-container', true); - return context; - }; - var embed; - context.embed = function(_) { - if (!arguments.length) return embed; - embed = _; - return context; - }; + /* Modes */ + var mode; + context.mode = function() { + return mode; + }; + context.enter = function(newMode) { + if (mode) { + mode.exit(); + dispatch$$1.call('exit', this, mode); + } + mode = newMode; + mode.enter(); + dispatch$$1.call('enter', this, mode); + }; - /* Assets */ - var assetPath = ''; - context.assetPath = function(_) { - if (!arguments.length) return assetPath; - assetPath = _; - return context; - }; + context.selectedIDs = function() { + if (mode && mode.selectedIDs) { + return mode.selectedIDs(); + } else { + return []; + } + }; + context.activeID = function() { + return mode && mode.activeID && mode.activeID(); + }; - var assetMap = {}; - context.assetMap = function(_) { - if (!arguments.length) return assetMap; - assetMap = _; - return context; - }; - context.asset = function(_) { - var filename = assetPath + _; - return assetMap[filename] || filename; - }; + /* Behaviors */ + context.install = function(behavior) { + context.surface().call(behavior); + }; + context.uninstall = function(behavior) { + context.surface().call(behavior.off); + }; - context.imagePath = function(_) { - return context.asset('img/' + _); - }; + /* Copy/Paste */ + var copyIDs = [], copyGraph; + context.copyGraph = function() { return copyGraph; }; + context.copyIDs = function(_) { + if (!arguments.length) return copyIDs; + copyIDs = _; + copyGraph = history.graph(); + return context; + }; - /* locales */ - // `locale` variable contains a "requested locale". - // It won't become the `currentLocale` until after loadLocale() is called. - var locale, localePath; - context.locale = function(loc, path) { - if (!arguments.length) return currentLocale; - locale = loc; - localePath = path; - return context; - }; + /* Background */ + var background; + context.background = function() { return background; }; - context.loadLocale = function(callback) { - if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) { - localePath = localePath || context.asset('locales/' + locale + '.json'); - d3_json(localePath, function(err, result) { - if (!err) { - addTranslation(locale, result[locale]); - setLocale(locale); - utilDetect(true); - } - if (callback) { - callback(err); - } - }); - } else { - if (locale) { - setLocale(locale); - utilDetect(true); - } - if (callback) { - callback(); - } - } - }; + /* Features */ + var features; + context.features = function() { return features; }; + context.hasHiddenConnections = function(id) { + var graph = history.graph(), + entity = graph.entity(id); + return features.hasHiddenConnections(entity, graph); + }; - /* reset (aka flush) */ - context.reset = context.flush = function() { - context.debouncedSave.cancel(); - forEach(services, function(service) { - if (service && typeof service.reset === 'function') { - service.reset(context); - } - }); - features.reset(); - history.reset(); - return context; - }; + /* Presets */ + var presets; + context.presets = function() { return presets; }; - /* Init */ - context.projection = geoRawMercator(); - context.curtainProjection = geoRawMercator(); + /* Map */ + var map; + context.map = function() { return map; }; + context.layers = function() { return map.layers; }; + context.surface = function() { return map.surface; }; + context.editable = function() { return map.editable(); }; + context.surfaceRect = function() { + return map.surface.node().getBoundingClientRect(); + }; - locale = utilDetect().locale; - if (locale && !dataLocales.hasOwnProperty(locale)) { - locale = locale.split('-')[0]; - } - history = coreHistory(context); - context.graph = history.graph; - context.changes = history.changes; - context.intersects = history.intersects; + /* Debug */ + var debugFlags = { + tile: false, // tile boundaries + collision: false, // label collision bounding boxes + imagery: false, // imagery bounding polygons + community: false, // community bounding polygons + imperial: false, // imperial (not metric) bounding polygons + driveLeft: false, // driveLeft bounding polygons + target: false // touch targets + }; + context.debugFlags = function() { + return debugFlags; + }; + context.setDebug = function(flag, val) { + if (arguments.length === 1) val = true; + debugFlags[flag] = val; + dispatch$$1.call('change'); + return context; + }; + context.getDebug = function(flag) { + return flag && debugFlags[flag]; + }; - // Debounce save, since it's a synchronous localStorage write, - // and history changes can happen frequently (e.g. when dragging). - context.debouncedSave = debounce(context.save, 350); - function withDebouncedSave(fn) { - return function() { - var result = fn.apply(history, arguments); - context.debouncedSave(); - return result; - }; - } - context.perform = withDebouncedSave(history.perform); - context.replace = withDebouncedSave(history.replace); - context.pop = withDebouncedSave(history.pop); - context.overwrite = withDebouncedSave(history.overwrite); - context.undo = withDebouncedSave(history.undo); - context.redo = withDebouncedSave(history.redo); - - ui = uiInit(context); - - connection = services.osm; - background = rendererBackground(context); - features = rendererFeatures(context); - presets = presetIndex(); - - map = rendererMap(context); - context.mouse = map.mouse; - context.extent = map.extent; - context.pan = map.pan; - context.zoomIn = map.zoomIn; - context.zoomOut = map.zoomOut; - context.zoomInFurther = map.zoomInFurther; - context.zoomOutFurther = map.zoomOutFurther; - context.redrawEnable = map.redrawEnable; - - forEach(services, function(service) { - if (service && typeof service.init === 'function') { - service.init(context); - } - }); + /* Container */ + var container = select(document.body); + context.container = function(_) { + if (!arguments.length) return container; + container = _; + container.classed('id-container', true); + return context; + }; + var embed; + context.embed = function(_) { + if (!arguments.length) return embed; + embed = _; + return context; + }; - background.init(); - features.init(); - presets.init(); - areaKeys = presets.areaKeys(); + /* Assets */ + var assetPath = ''; + context.assetPath = function(_) { + if (!arguments.length) return assetPath; + assetPath = _; + return context; + }; - return utilRebind(context, dispatch$$1, 'on'); -} + var assetMap = {}; + context.assetMap = function(_) { + if (!arguments.length) return assetMap; + assetMap = _; + return context; + }; -function osmWay() { - if (!(this instanceof osmWay)) { - return (new osmWay()).initialize(arguments); - } else if (arguments.length) { - this.initialize(arguments); - } -} + context.asset = function(_) { + var filename = assetPath + _; + return assetMap[filename] || filename; + }; + context.imagePath = function(_) { + return context.asset('img/' + _); + }; -osmEntity$$1.way = osmWay; -osmWay.prototype = Object.create(osmEntity$$1.prototype); + /* locales */ + // `locale` variable contains a "requested locale". + // It won't become the `currentLocale` until after loadLocale() is called. + var locale, localePath; + context.locale = function(loc, path) { + if (!arguments.length) return currentLocale; + locale = loc; + localePath = path; + return context; + }; -assignIn(osmWay.prototype, { - type: 'way', - nodes: [], + context.loadLocale = function(callback) { + if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) { + localePath = localePath || context.asset('locales/' + locale + '.json'); + d3_json(localePath, function(err, result) { + if (!err) { + addTranslation(locale, result[locale]); + setLocale(locale); + utilDetect(true); + } + if (callback) { + callback(err); + } + }); + } else { + if (locale) { + setLocale(locale); + utilDetect(true); + } + if (callback) { + callback(); + } + } + }; - copy: function(resolver, copies) { - if (copies[this.id]) - return copies[this.id]; + /* reset (aka flush) */ + context.reset = context.flush = function() { + context.debouncedSave.cancel(); + forEach(services, function(service) { + if (service && typeof service.reset === 'function') { + service.reset(context); + } + }); + features.reset(); + history.reset(); + return context; + }; - var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies); - var nodes = this.nodes.map(function(id) { - return resolver.entity(id).copy(resolver, copies).id; - }); + /* Init */ - copy = copy.update({ nodes: nodes }); - copies[this.id] = copy; + context.projection = geoRawMercator(); + context.curtainProjection = geoRawMercator(); - return copy; - }, + locale = utilDetect().locale; + if (locale && !dataLocales.hasOwnProperty(locale)) { + locale = locale.split('-')[0]; + } + history = coreHistory(context); + context.graph = history.graph; + context.changes = history.changes; + context.intersects = history.intersects; + + // Debounce save, since it's a synchronous localStorage write, + // and history changes can happen frequently (e.g. when dragging). + context.debouncedSave = debounce(context.save, 350); + function withDebouncedSave(fn) { + return function() { + var result = fn.apply(history, arguments); + context.debouncedSave(); + return result; + }; + } - extent: function(resolver) { - return resolver.transient(this, 'extent', function() { - var extent = geoExtent$$1(); - for (var i = 0; i < this.nodes.length; i++) { - var node = resolver.hasEntity(this.nodes[i]); - if (node) { - extent._extend(node.extent()); - } - } - return extent; - }); - }, + context.perform = withDebouncedSave(history.perform); + context.replace = withDebouncedSave(history.replace); + context.pop = withDebouncedSave(history.pop); + context.overwrite = withDebouncedSave(history.overwrite); + context.undo = withDebouncedSave(history.undo); + context.redo = withDebouncedSave(history.redo); + + ui = uiInit(context); + + connection = services.osm; + background = rendererBackground(context); + features = rendererFeatures(context); + presets = presetIndex(); + + map = rendererMap(context); + context.mouse = map.mouse; + context.extent = map.extent; + context.pan = map.pan; + context.zoomIn = map.zoomIn; + context.zoomOut = map.zoomOut; + context.zoomInFurther = map.zoomInFurther; + context.zoomOutFurther = map.zoomOutFurther; + context.redrawEnable = map.redrawEnable; + + forEach(services, function(service) { + if (service && typeof service.init === 'function') { + service.init(context); + } + }); + background.init(); + features.init(); + presets.init(); + areaKeys = presets.areaKeys(); - first: function() { - return this.nodes[0]; - }, + return utilRebind(context, dispatch$$1, 'on'); + } - last: function() { - return this.nodes[this.nodes.length - 1]; - }, + function osmWay() { + if (!(this instanceof osmWay)) { + return (new osmWay()).initialize(arguments); + } else if (arguments.length) { + this.initialize(arguments); + } + } - contains: function(node) { - return this.nodes.indexOf(node) >= 0; - }, + osmEntity$$1.way = osmWay; + osmWay.prototype = Object.create(osmEntity$$1.prototype); - affix: function(node) { - if (this.nodes[0] === node) return 'prefix'; - if (this.nodes[this.nodes.length - 1] === node) return 'suffix'; - }, + assignIn(osmWay.prototype, { + type: 'way', + nodes: [], - layer: function() { - // explicit layer tag, clamp between -10, 10.. - if (isFinite(this.tags.layer)) { - return Math.max(-10, Math.min(+(this.tags.layer), 10)); - } - // implied layer tag.. - if (this.tags.covered === 'yes') return -1; - if (this.tags.location === 'overground') return 1; - if (this.tags.location === 'underground') return -1; - if (this.tags.location === 'underwater') return -10; - - if (this.tags.power === 'line') return 10; - if (this.tags.power === 'minor_line') return 10; - if (this.tags.aerialway) return 10; - if (this.tags.bridge) return 1; - if (this.tags.cutting) return -1; - if (this.tags.tunnel) return -1; - if (this.tags.waterway) return -1; - if (this.tags.man_made === 'pipeline') return -10; - if (this.tags.boundary) return -10; - return 0; - }, + copy: function(resolver, copies) { + if (copies[this.id]) + return copies[this.id]; + var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies); - isOneWay: function() { - // explicit oneway tag.. - var values = { - 'yes': true, - '1': true, - '-1': true, - 'reversible': true, - 'alternating': true, - 'no': false, - '0': false - }; - if (values[this.tags.oneway] !== undefined) { - return values[this.tags.oneway]; - } + var nodes = this.nodes.map(function(id) { + return resolver.entity(id).copy(resolver, copies).id; + }); - // implied oneway tag.. - for (var key in this.tags) { - if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key])) - return true; - } - return false; - }, + copy = copy.update({ nodes: nodes }); + copies[this.id] = copy; + return copy; + }, - lanes: function() { - return osmLanes(this); - }, + extent: function(resolver) { + return resolver.transient(this, 'extent', function() { + var extent = geoExtent$$1(); + for (var i = 0; i < this.nodes.length; i++) { + var node = resolver.hasEntity(this.nodes[i]); + if (node) { + extent._extend(node.extent()); + } + } + return extent; + }); + }, - isClosed: function() { - return this.nodes.length > 1 && this.first() === this.last(); - }, + first: function() { + return this.nodes[0]; + }, - isConvex: function(resolver) { - if (!this.isClosed() || this.isDegenerate()) return null; - var nodes = uniq(resolver.childNodes(this)); - var coords = map$3(nodes, 'loc'); - var curr = 0; - var prev = 0; + last: function() { + return this.nodes[this.nodes.length - 1]; + }, - for (var i = 0; i < coords.length; i++) { - var o = coords[(i+1) % coords.length]; - var a = coords[i]; - var b = coords[(i+2) % coords.length]; - var res = geoVecCross(a, b, o); - curr = (res > 0) ? 1 : (res < 0) ? -1 : 0; - if (curr === 0) { - continue; - } else if (prev && curr !== prev) { - return false; - } - prev = curr; - } - return true; - }, + contains: function(node) { + return this.nodes.indexOf(node) >= 0; + }, - isArea: function() { - // `highway` and `railway` are typically linear features, but there - // are a few exceptions that should be treated as areas, even in the - // absence of a proper `area=yes` or `areaKeys` tag.. see #4194 - var lineKeys = { - highway: { - rest_area: true, - services: true - }, - railway: { - roundhouse: true, - station: true, - traverser: true, - turntable: true, - wash: true - } - }; + affix: function(node) { + if (this.nodes[0] === node) return 'prefix'; + if (this.nodes[this.nodes.length - 1] === node) return 'suffix'; + }, - if (this.tags.area === 'yes') - return true; - if (!this.isClosed() || this.tags.area === 'no') - return false; - for (var key in this.tags) { - if (key in areaKeys && !(this.tags[key] in areaKeys[key])) { - return true; - } - if (key in lineKeys && this.tags[key] in lineKeys[key]) { - return true; - } - } - return false; - }, + layer: function() { + // explicit layer tag, clamp between -10, 10.. + if (isFinite(this.tags.layer)) { + return Math.max(-10, Math.min(+(this.tags.layer), 10)); + } - isDegenerate: function() { - return uniq(this.nodes).length < (this.isArea() ? 3 : 2); - }, + // implied layer tag.. + if (this.tags.covered === 'yes') return -1; + if (this.tags.location === 'overground') return 1; + if (this.tags.location === 'underground') return -1; + if (this.tags.location === 'underwater') return -10; + + if (this.tags.power === 'line') return 10; + if (this.tags.power === 'minor_line') return 10; + if (this.tags.aerialway) return 10; + if (this.tags.bridge) return 1; + if (this.tags.cutting) return -1; + if (this.tags.tunnel) return -1; + if (this.tags.waterway) return -1; + if (this.tags.man_made === 'pipeline') return -10; + if (this.tags.boundary) return -10; + return 0; + }, - areAdjacent: function(n1, n2) { - for (var i = 0; i < this.nodes.length; i++) { - if (this.nodes[i] === n1) { - if (this.nodes[i - 1] === n2) return true; - if (this.nodes[i + 1] === n2) return true; - } - } - return false; - }, + isOneWay: function() { + // explicit oneway tag.. + var values = { + 'yes': true, + '1': true, + '-1': true, + 'reversible': true, + 'alternating': true, + 'no': false, + '0': false + }; + if (values[this.tags.oneway] !== undefined) { + return values[this.tags.oneway]; + } + // implied oneway tag.. + for (var key in this.tags) { + if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key])) + return true; + } + return false; + }, - geometry: function(graph) { - return graph.transient(this, 'geometry', function() { - return this.isArea() ? 'area' : 'line'; - }); - }, + lanes: function() { + return osmLanes(this); + }, - // If this way is not closed, append the beginning node to the end of the nodelist to close it. - close: function() { - if (this.isClosed() || !this.nodes.length) return this; - var nodes = this.nodes.slice(); - nodes = nodes.filter(noRepeatNodes); - nodes.push(nodes[0]); - return this.update({ nodes: nodes }); - }, + isClosed: function() { + return this.nodes.length > 1 && this.first() === this.last(); + }, - // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it. - unclose: function() { - if (!this.isClosed()) return this; + isConvex: function(resolver) { + if (!this.isClosed() || this.isDegenerate()) return null; - var nodes = this.nodes.slice(), - connector = this.first(), - i = nodes.length - 1; + var nodes = uniq(resolver.childNodes(this)); + var coords = map$3(nodes, 'loc'); + var curr = 0; + var prev = 0; - // remove trailing connectors.. - while (i > 0 && nodes.length > 1 && nodes[i] === connector) { - nodes.splice(i, 1); - i = nodes.length - 1; - } + for (var i = 0; i < coords.length; i++) { + var o = coords[(i+1) % coords.length]; + var a = coords[i]; + var b = coords[(i+2) % coords.length]; + var res = geoVecCross(a, b, o); - nodes = nodes.filter(noRepeatNodes); - return this.update({ nodes: nodes }); - }, + curr = (res > 0) ? 1 : (res < 0) ? -1 : 0; + if (curr === 0) { + continue; + } else if (prev && curr !== prev) { + return false; + } + prev = curr; + } + return true; + }, - // Adds a node (id) in front of the node which is currently at position index. - // If index is undefined, the node will be added to the end of the way for linear ways, - // or just before the final connecting node for circular ways. - // Consecutive duplicates are eliminated including existing ones. - // Circularity is always preserved when adding a node. - addNode: function(id, index) { - var nodes = this.nodes.slice(), - isClosed = this.isClosed(), - max = isClosed ? nodes.length - 1 : nodes.length; + isArea: function() { + // `highway` and `railway` are typically linear features, but there + // are a few exceptions that should be treated as areas, even in the + // absence of a proper `area=yes` or `areaKeys` tag.. see #4194 + var lineKeys = { + highway: { + rest_area: true, + services: true + }, + railway: { + roundhouse: true, + station: true, + traverser: true, + turntable: true, + wash: true + } + }; - if (index === undefined) { - index = max; - } + if (this.tags.area === 'yes') + return true; + if (!this.isClosed() || this.tags.area === 'no') + return false; + for (var key in this.tags) { + if (key in areaKeys && !(this.tags[key] in areaKeys[key])) { + return true; + } + if (key in lineKeys && this.tags[key] in lineKeys[key]) { + return true; + } + } + return false; + }, - if (index < 0 || index > max) { - throw new RangeError('index ' + index + ' out of range 0..' + max); - } - // If this is a closed way, remove all connector nodes except the first one - // (there may be duplicates) and adjust index if necessary.. - if (isClosed) { - var connector = this.first(); + isDegenerate: function() { + return uniq(this.nodes).length < (this.isArea() ? 3 : 2); + }, - // leading connectors.. - var i = 1; - while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) { - nodes.splice(i, 1); - if (index > i) index--; - } - // trailing connectors.. - i = nodes.length - 1; - while (i > 0 && nodes.length > 1 && nodes[i] === connector) { - nodes.splice(i, 1); - if (index > i) index--; - i = nodes.length - 1; - } - } + areAdjacent: function(n1, n2) { + for (var i = 0; i < this.nodes.length; i++) { + if (this.nodes[i] === n1) { + if (this.nodes[i - 1] === n2) return true; + if (this.nodes[i + 1] === n2) return true; + } + } + return false; + }, - nodes.splice(index, 0, id); - nodes = nodes.filter(noRepeatNodes); - // If the way was closed before, append a connector node to keep it closed.. - if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) { - nodes.push(nodes[0]); - } + geometry: function(graph) { + return graph.transient(this, 'geometry', function() { + return this.isArea() ? 'area' : 'line'; + }); + }, - return this.update({ nodes: nodes }); - }, + // If this way is not closed, append the beginning node to the end of the nodelist to close it. + close: function() { + if (this.isClosed() || !this.nodes.length) return this; - // Replaces the node which is currently at position index with the given node (id). - // Consecutive duplicates are eliminated including existing ones. - // Circularity is preserved when updating a node. - updateNode: function(id, index) { - var nodes = this.nodes.slice(), - isClosed = this.isClosed(), - max = nodes.length - 1; + var nodes = this.nodes.slice(); + nodes = nodes.filter(noRepeatNodes); + nodes.push(nodes[0]); + return this.update({ nodes: nodes }); + }, - if (index === undefined || index < 0 || index > max) { - throw new RangeError('index ' + index + ' out of range 0..' + max); - } - // If this is a closed way, remove all connector nodes except the first one - // (there may be duplicates) and adjust index if necessary.. - if (isClosed) { - var connector = this.first(); + // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it. + unclose: function() { + if (!this.isClosed()) return this; - // leading connectors.. - var i = 1; - while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) { - nodes.splice(i, 1); - if (index > i) index--; - } + var nodes = this.nodes.slice(), + connector = this.first(), + i = nodes.length - 1; - // trailing connectors.. - i = nodes.length - 1; - while (i > 0 && nodes.length > 1 && nodes[i] === connector) { - nodes.splice(i, 1); - if (index === i) index = 0; // update leading connector instead - i = nodes.length - 1; - } - } + // remove trailing connectors.. + while (i > 0 && nodes.length > 1 && nodes[i] === connector) { + nodes.splice(i, 1); + i = nodes.length - 1; + } - nodes.splice(index, 1, id); - nodes = nodes.filter(noRepeatNodes); + nodes = nodes.filter(noRepeatNodes); + return this.update({ nodes: nodes }); + }, - // If the way was closed before, append a connector node to keep it closed.. - if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) { - nodes.push(nodes[0]); - } - return this.update({nodes: nodes}); - }, + // Adds a node (id) in front of the node which is currently at position index. + // If index is undefined, the node will be added to the end of the way for linear ways, + // or just before the final connecting node for circular ways. + // Consecutive duplicates are eliminated including existing ones. + // Circularity is always preserved when adding a node. + addNode: function(id, index) { + var nodes = this.nodes.slice(), + isClosed = this.isClosed(), + max = isClosed ? nodes.length - 1 : nodes.length; + if (index === undefined) { + index = max; + } - // Replaces each occurrence of node id needle with replacement. - // Consecutive duplicates are eliminated including existing ones. - // Circularity is preserved. - replaceNode: function(needle, replacement) { - var nodes = this.nodes.slice(), - isClosed = this.isClosed(); + if (index < 0 || index > max) { + throw new RangeError('index ' + index + ' out of range 0..' + max); + } - for (var i = 0; i < nodes.length; i++) { - if (nodes[i] === needle) { - nodes[i] = replacement; - } - } + // If this is a closed way, remove all connector nodes except the first one + // (there may be duplicates) and adjust index if necessary.. + if (isClosed) { + var connector = this.first(); + + // leading connectors.. + var i = 1; + while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) { + nodes.splice(i, 1); + if (index > i) index--; + } + + // trailing connectors.. + i = nodes.length - 1; + while (i > 0 && nodes.length > 1 && nodes[i] === connector) { + nodes.splice(i, 1); + if (index > i) index--; + i = nodes.length - 1; + } + } - nodes = nodes.filter(noRepeatNodes); + nodes.splice(index, 0, id); + nodes = nodes.filter(noRepeatNodes); - // If the way was closed before, append a connector node to keep it closed.. - if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) { - nodes.push(nodes[0]); - } + // If the way was closed before, append a connector node to keep it closed.. + if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) { + nodes.push(nodes[0]); + } - return this.update({nodes: nodes}); - }, + return this.update({ nodes: nodes }); + }, - // Removes each occurrence of node id needle with replacement. - // Consecutive duplicates are eliminated including existing ones. - // Circularity is preserved. - removeNode: function(id) { - var nodes = this.nodes.slice(), - isClosed = this.isClosed(); + // Replaces the node which is currently at position index with the given node (id). + // Consecutive duplicates are eliminated including existing ones. + // Circularity is preserved when updating a node. + updateNode: function(id, index) { + var nodes = this.nodes.slice(), + isClosed = this.isClosed(), + max = nodes.length - 1; - nodes = nodes - .filter(function(node) { return node !== id; }) - .filter(noRepeatNodes); + if (index === undefined || index < 0 || index > max) { + throw new RangeError('index ' + index + ' out of range 0..' + max); + } - // If the way was closed before, append a connector node to keep it closed.. - if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) { - nodes.push(nodes[0]); - } + // If this is a closed way, remove all connector nodes except the first one + // (there may be duplicates) and adjust index if necessary.. + if (isClosed) { + var connector = this.first(); + + // leading connectors.. + var i = 1; + while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) { + nodes.splice(i, 1); + if (index > i) index--; + } + + // trailing connectors.. + i = nodes.length - 1; + while (i > 0 && nodes.length > 1 && nodes[i] === connector) { + nodes.splice(i, 1); + if (index === i) index = 0; // update leading connector instead + i = nodes.length - 1; + } + } - return this.update({nodes: nodes}); - }, + nodes.splice(index, 1, id); + nodes = nodes.filter(noRepeatNodes); + // If the way was closed before, append a connector node to keep it closed.. + if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) { + nodes.push(nodes[0]); + } - asJXON: function(changeset_id) { - var r = { - way: { - '@id': this.osmId(), - '@version': this.version || 0, - nd: map$3(this.nodes, function(id) { - return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } }; - }), - tag: map$3(this.tags, function(v, k) { - return { keyAttributes: { k: k, v: v } }; - }) - } - }; - if (changeset_id) { - r.way['@changeset'] = changeset_id; - } - return r; - }, + return this.update({nodes: nodes}); + }, - asGeoJSON: function(resolver) { - return resolver.transient(this, 'GeoJSON', function() { - var coordinates = map$3(resolver.childNodes(this), 'loc'); - if (this.isArea() && this.isClosed()) { - return { - type: 'Polygon', - coordinates: [coordinates] - }; - } else { - return { - type: 'LineString', - coordinates: coordinates - }; - } - }); - }, + // Replaces each occurrence of node id needle with replacement. + // Consecutive duplicates are eliminated including existing ones. + // Circularity is preserved. + replaceNode: function(needle, replacement) { + var nodes = this.nodes.slice(), + isClosed = this.isClosed(); + for (var i = 0; i < nodes.length; i++) { + if (nodes[i] === needle) { + nodes[i] = replacement; + } + } - area: function(resolver) { - return resolver.transient(this, 'area', function() { - var nodes = resolver.childNodes(this); + nodes = nodes.filter(noRepeatNodes); - var json = { - type: 'Polygon', - coordinates: [map$3(nodes, 'loc')] - }; + // If the way was closed before, append a connector node to keep it closed.. + if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) { + nodes.push(nodes[0]); + } - if (!this.isClosed() && nodes.length) { - json.coordinates[0].push(nodes[0].loc); - } + return this.update({nodes: nodes}); + }, - var area = d3_geoArea(json); - // Heuristic for detecting counterclockwise winding order. Assumes - // that OpenStreetMap polygons are not hemisphere-spanning. - if (area > 2 * Math.PI) { - json.coordinates[0] = json.coordinates[0].reverse(); - area = d3_geoArea(json); - } + // Removes each occurrence of node id needle with replacement. + // Consecutive duplicates are eliminated including existing ones. + // Circularity is preserved. + removeNode: function(id) { + var nodes = this.nodes.slice(), + isClosed = this.isClosed(); - return isNaN(area) ? 0 : area; - }); - } -}); + nodes = nodes + .filter(function(node) { return node !== id; }) + .filter(noRepeatNodes); + // If the way was closed before, append a connector node to keep it closed.. + if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) { + nodes.push(nodes[0]); + } -// Filter function to eliminate consecutive duplicates. -function noRepeatNodes(node, i, arr) { - return i === 0 || node !== arr[i - 1]; -} + return this.update({nodes: nodes}); + }, -// For fixing up rendering of multipolygons with tags on the outer member. -// https://github.com/openstreetmap/iD/issues/613 -function osmIsSimpleMultipolygonOuterMember(entity, graph) { - if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0) - return false; - var parents = graph.parentRelations(entity); - if (parents.length !== 1) - return false; + asJXON: function(changeset_id) { + var r = { + way: { + '@id': this.osmId(), + '@version': this.version || 0, + nd: map$3(this.nodes, function(id) { + return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } }; + }), + tag: map$3(this.tags, function(v, k) { + return { keyAttributes: { k: k, v: v } }; + }) + } + }; + if (changeset_id) { + r.way['@changeset'] = changeset_id; + } + return r; + }, - var parent = parents[0]; - if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) - return false; - var members = parent.members, member; - for (var i = 0; i < members.length; i++) { - member = members[i]; - if (member.id === entity.id && member.role && member.role !== 'outer') - return false; // Not outer member - if (member.id !== entity.id && (!member.role || member.role === 'outer')) - return false; // Not a simple multipolygon - } + asGeoJSON: function(resolver) { + return resolver.transient(this, 'GeoJSON', function() { + var coordinates = map$3(resolver.childNodes(this), 'loc'); + if (this.isArea() && this.isClosed()) { + return { + type: 'Polygon', + coordinates: [coordinates] + }; + } else { + return { + type: 'LineString', + coordinates: coordinates + }; + } + }); + }, - return parent; -} + area: function(resolver) { + return resolver.transient(this, 'area', function() { + var nodes = resolver.childNodes(this); -function osmSimpleMultipolygonOuterMember(entity, graph) { - if (entity.type !== 'way') - return false; + var json = { + type: 'Polygon', + coordinates: [map$3(nodes, 'loc')] + }; - var parents = graph.parentRelations(entity); - if (parents.length !== 1) - return false; + if (!this.isClosed() && nodes.length) { + json.coordinates[0].push(nodes[0].loc); + } - var parent = parents[0]; - if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) - return false; + var area = d3_geoArea(json); - var members = parent.members, member, outerMember; - for (var i = 0; i < members.length; i++) { - member = members[i]; - if (!member.role || member.role === 'outer') { - if (outerMember) - return false; // Not a simple multipolygon - outerMember = member; - } - } + // Heuristic for detecting counterclockwise winding order. Assumes + // that OpenStreetMap polygons are not hemisphere-spanning. + if (area > 2 * Math.PI) { + json.coordinates[0] = json.coordinates[0].reverse(); + area = d3_geoArea(json); + } - if (!outerMember) - return false; + return isNaN(area) ? 0 : area; + }); + } + }); - var outerEntity = graph.hasEntity(outerMember.id); - if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length) - return false; - return outerEntity; -} - - -// Join `toJoin` array into sequences of connecting ways. - -// Segments which share identical start/end nodes will, as much as possible, -// be connected with each other. -// -// The return value is a nested array. Each constituent array contains elements -// of `toJoin` which have been determined to connect. -// -// Each consitituent array also has a `nodes` property whose value is an -// ordered array of member nodes, with appropriate order reversal and -// start/end coordinate de-duplication. -// -// Members of `toJoin` must have, at minimum, `type` and `id` properties. -// Thus either an array of `osmWay`s or a relation member array may be used. -// -// If an member is an `osmWay`, its tags and childnodes may be reversed via -// `actionReverse` in the output. -// -// The returned sequences array also has an `actions` array property, containing -// any reversal actions that should be applied to the graph, should the calling -// code attempt to actually join the given ways. -// -// Incomplete members (those for which `graph.hasEntity(element.id)` returns -// false) and non-way members are ignored. -// -function osmJoinWays(toJoin, graph) { - function resolve(member) { - return graph.childNodes(graph.entity(member.id)); - } - - function reverse(item) { - var action = actionReverse(item.id, { reverseOneway: true }); - sequences.actions.push(action); - return (item instanceof osmWay) ? action(graph).entity(item.id) : item; - } - - // make a copy containing only the items to join - toJoin = toJoin.filter(function(member) { - return member.type === 'way' && graph.hasEntity(member.id); - }); + // Filter function to eliminate consecutive duplicates. + function noRepeatNodes(node, i, arr) { + return i === 0 || node !== arr[i - 1]; + } + // For fixing up rendering of multipolygons with tags on the outer member. + // https://github.com/openstreetmap/iD/issues/613 + function osmIsSimpleMultipolygonOuterMember(entity, graph) { + if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0) + return false; + + var parents = graph.parentRelations(entity); + if (parents.length !== 1) + return false; + + var parent = parents[0]; + if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) + return false; + + var members = parent.members, member; + for (var i = 0; i < members.length; i++) { + member = members[i]; + if (member.id === entity.id && member.role && member.role !== 'outer') + return false; // Not outer member + if (member.id !== entity.id && (!member.role || member.role === 'outer')) + return false; // Not a simple multipolygon + } - var sequences = []; - sequences.actions = []; - - while (toJoin.length) { - // start a new sequence - var item = toJoin.shift(); - var currWays = [item]; - var currNodes = resolve(item).slice(); - var doneSequence = false; - - // add to it - while (toJoin.length && !doneSequence) { - var start = currNodes[0]; - var end = currNodes[currNodes.length - 1]; - var fn = null; - var nodes = null; - var i; - - // Find the next way/member to join. - for (i = 0; i < toJoin.length; i++) { - item = toJoin[i]; - nodes = resolve(item); - - // Strongly prefer to generate a forward path that preserves the order - // of the members array. For multipolygons and most relations, member - // order does not matter - but for routes, it does. If we started this - // sequence backwards (i.e. next member way attaches to the start node - // and not the end node), reverse the initial way before continuing. - if (currWays.length === 1 && nodes[0] !== end && nodes[nodes.length - 1] !== end && - (nodes[nodes.length - 1] === start || nodes[0] === start) - ) { - currWays[0] = reverse(currWays[0]); - currNodes.reverse(); - start = currNodes[0]; - end = currNodes[currNodes.length - 1]; - } - - if (nodes[0] === end) { - fn = currNodes.push; // join to end - nodes = nodes.slice(1); - break; - } else if (nodes[nodes.length - 1] === end) { - fn = currNodes.push; // join to end - nodes = nodes.slice(0, -1).reverse(); - item = reverse(item); - break; - } else if (nodes[nodes.length - 1] === start) { - fn = currNodes.unshift; // join to beginning - nodes = nodes.slice(0, -1); - break; - } else if (nodes[0] === start) { - fn = currNodes.unshift; // join to beginning - nodes = nodes.slice(1).reverse(); - item = reverse(item); - break; - } else { - fn = nodes = null; - } - } + return parent; + } - if (!nodes) { // couldn't find a joinable way/member - doneSequence = true; - break; - } - fn.apply(currWays, [item]); - fn.apply(currNodes, nodes); + function osmSimpleMultipolygonOuterMember(entity, graph) { + if (entity.type !== 'way') + return false; - toJoin.splice(i, 1); - } + var parents = graph.parentRelations(entity); + if (parents.length !== 1) + return false; - currWays.nodes = currNodes; - sequences.push(currWays); - } + var parent = parents[0]; + if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) + return false; - return sequences; -} + var members = parent.members, member, outerMember; + for (var i = 0; i < members.length; i++) { + member = members[i]; + if (!member.role || member.role === 'outer') { + if (outerMember) + return false; // Not a simple multipolygon + outerMember = member; + } + } -function osmRelation() { - if (!(this instanceof osmRelation)) { - return (new osmRelation()).initialize(arguments); - } else if (arguments.length) { - this.initialize(arguments); - } -} + if (!outerMember) + return false; + var outerEntity = graph.hasEntity(outerMember.id); + if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length) + return false; -osmEntity$$1.relation = osmRelation; + return outerEntity; + } -osmRelation.prototype = Object.create(osmEntity$$1.prototype); + // Join `toJoin` array into sequences of connecting ways. -osmRelation.creationOrder = function(a, b) { - var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10); - var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10); + // Segments which share identical start/end nodes will, as much as possible, + // be connected with each other. + // + // The return value is a nested array. Each constituent array contains elements + // of `toJoin` which have been determined to connect. + // + // Each consitituent array also has a `nodes` property whose value is an + // ordered array of member nodes, with appropriate order reversal and + // start/end coordinate de-duplication. + // + // Members of `toJoin` must have, at minimum, `type` and `id` properties. + // Thus either an array of `osmWay`s or a relation member array may be used. + // + // If an member is an `osmWay`, its tags and childnodes may be reversed via + // `actionReverse` in the output. + // + // The returned sequences array also has an `actions` array property, containing + // any reversal actions that should be applied to the graph, should the calling + // code attempt to actually join the given ways. + // + // Incomplete members (those for which `graph.hasEntity(element.id)` returns + // false) and non-way members are ignored. + // + function osmJoinWays(toJoin, graph) { + function resolve(member) { + return graph.childNodes(graph.entity(member.id)); + } - if (aId < 0 || bId < 0) return aId - bId; - return bId - aId; -}; + function reverse(item) { + var action = actionReverse(item.id, { reverseOneway: true }); + sequences.actions.push(action); + return (item instanceof osmWay) ? action(graph).entity(item.id) : item; + } + // make a copy containing only the items to join + toJoin = toJoin.filter(function(member) { + return member.type === 'way' && graph.hasEntity(member.id); + }); -assignIn(osmRelation.prototype, { - type: 'relation', - members: [], + // Are the things we are joining relation members or `osmWays`? + // If `osmWays`, skip the "prefer a forward path" code below (see #4872) + var i; + var joinAsMembers = true; + for (i = 0; i < toJoin.length; i++) { + if (toJoin[i] instanceof osmWay) { + joinAsMembers = false; + break; + } + } + var sequences = []; + sequences.actions = []; + + while (toJoin.length) { + // start a new sequence + var item = toJoin.shift(); + var currWays = [item]; + var currNodes = resolve(item).slice(); + var doneSequence = false; + + // add to it + while (toJoin.length && !doneSequence) { + var start = currNodes[0]; + var end = currNodes[currNodes.length - 1]; + var fn = null; + var nodes = null; + + // Find the next way/member to join. + for (i = 0; i < toJoin.length; i++) { + item = toJoin[i]; + nodes = resolve(item); + + // (for member ordering only, not way ordering - see #4872) + // Strongly prefer to generate a forward path that preserves the order + // of the members array. For multipolygons and most relations, member + // order does not matter - but for routes, it does. (see #4589) + // If we started this sequence backwards (i.e. next member way attaches to + // the start node and not the end node), reverse the initial way before continuing. + if (joinAsMembers && currWays.length === 1 && nodes[0] !== end && nodes[nodes.length - 1] !== end && + (nodes[nodes.length - 1] === start || nodes[0] === start) + ) { + currWays[0] = reverse(currWays[0]); + currNodes.reverse(); + start = currNodes[0]; + end = currNodes[currNodes.length - 1]; + } + + if (nodes[0] === end) { + fn = currNodes.push; // join to end + nodes = nodes.slice(1); + break; + } else if (nodes[nodes.length - 1] === end) { + fn = currNodes.push; // join to end + nodes = nodes.slice(0, -1).reverse(); + item = reverse(item); + break; + } else if (nodes[nodes.length - 1] === start) { + fn = currNodes.unshift; // join to beginning + nodes = nodes.slice(0, -1); + break; + } else if (nodes[0] === start) { + fn = currNodes.unshift; // join to beginning + nodes = nodes.slice(1).reverse(); + item = reverse(item); + break; + } else { + fn = nodes = null; + } + } + + if (!nodes) { // couldn't find a joinable way/member + doneSequence = true; + break; + } + + fn.apply(currWays, [item]); + fn.apply(currNodes, nodes); + + toJoin.splice(i, 1); + } - copy: function(resolver, copies) { - if (copies[this.id]) - return copies[this.id]; + currWays.nodes = currNodes; + sequences.push(currWays); + } - var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies); + return sequences; + } - var members = this.members.map(function(member) { - return assignIn({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id }); - }); + function osmRelation() { + if (!(this instanceof osmRelation)) { + return (new osmRelation()).initialize(arguments); + } else if (arguments.length) { + this.initialize(arguments); + } + } - copy = copy.update({members: members}); - copies[this.id] = copy; - return copy; - }, + osmEntity$$1.relation = osmRelation; + osmRelation.prototype = Object.create(osmEntity$$1.prototype); - extent: function(resolver, memo) { - return resolver.transient(this, 'extent', function() { - if (memo && memo[this.id]) return geoExtent$$1(); - memo = memo || {}; - memo[this.id] = true; - var extent = geoExtent$$1(); - for (var i = 0; i < this.members.length; i++) { - var member = resolver.hasEntity(this.members[i].id); - if (member) { - extent._extend(member.extent(resolver, memo)); - } - } - return extent; - }); - }, + osmRelation.creationOrder = function(a, b) { + var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10); + var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10); + if (aId < 0 || bId < 0) return aId - bId; + return bId - aId; + }; - geometry: function(graph) { - return graph.transient(this, 'geometry', function() { - return this.isMultipolygon() ? 'area' : 'relation'; - }); - }, + assignIn(osmRelation.prototype, { + type: 'relation', + members: [], - isDegenerate: function() { - return this.members.length === 0; - }, + copy: function(resolver, copies) { + if (copies[this.id]) + return copies[this.id]; - // Return an array of members, each extended with an 'index' property whose value - // is the member index. - indexedMembers: function() { - var result = new Array(this.members.length); - for (var i = 0; i < this.members.length; i++) { - result[i] = assignIn({}, this.members[i], {index: i}); - } - return result; - }, + var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies); + var members = this.members.map(function(member) { + return assignIn({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id }); + }); - // Return the first member with the given role. A copy of the member object - // is returned, extended with an 'index' property whose value is the member index. - memberByRole: function(role) { - for (var i = 0; i < this.members.length; i++) { - if (this.members[i].role === role) { - return assignIn({}, this.members[i], {index: i}); - } - } - }, + copy = copy.update({members: members}); + copies[this.id] = copy; - // Same as memberByRole, but returns all members with the given role - membersByRole: function(role) { - var result = []; - for (var i = 0; i < this.members.length; i++) { - if (this.members[i].role === role) { - result.push(assignIn({}, this.members[i], {index: i})); - } - } - return result; - }, + return copy; + }, - // Return the first member with the given id. A copy of the member object - // is returned, extended with an 'index' property whose value is the member index. - memberById: function(id) { - for (var i = 0; i < this.members.length; i++) { - if (this.members[i].id === id) { - return assignIn({}, this.members[i], {index: i}); - } - } - }, + extent: function(resolver, memo) { + return resolver.transient(this, 'extent', function() { + if (memo && memo[this.id]) return geoExtent$$1(); + memo = memo || {}; + memo[this.id] = true; + + var extent = geoExtent$$1(); + for (var i = 0; i < this.members.length; i++) { + var member = resolver.hasEntity(this.members[i].id); + if (member) { + extent._extend(member.extent(resolver, memo)); + } + } + return extent; + }); + }, - // Return the first member with the given id and role. A copy of the member object - // is returned, extended with an 'index' property whose value is the member index. - memberByIdAndRole: function(id, role) { - for (var i = 0; i < this.members.length; i++) { - if (this.members[i].id === id && this.members[i].role === role) { - return assignIn({}, this.members[i], {index: i}); - } - } - }, + geometry: function(graph) { + return graph.transient(this, 'geometry', function() { + return this.isMultipolygon() ? 'area' : 'relation'; + }); + }, - addMember: function(member, index) { - var members = this.members.slice(); - members.splice(index === undefined ? members.length : index, 0, member); - return this.update({members: members}); - }, + isDegenerate: function() { + return this.members.length === 0; + }, - updateMember: function(member, index) { - var members = this.members.slice(); - members.splice(index, 1, assignIn({}, members[index], member)); - return this.update({members: members}); - }, + // Return an array of members, each extended with an 'index' property whose value + // is the member index. + indexedMembers: function() { + var result = new Array(this.members.length); + for (var i = 0; i < this.members.length; i++) { + result[i] = assignIn({}, this.members[i], {index: i}); + } + return result; + }, - removeMember: function(index) { - var members = this.members.slice(); - members.splice(index, 1); - return this.update({members: members}); - }, + // Return the first member with the given role. A copy of the member object + // is returned, extended with an 'index' property whose value is the member index. + memberByRole: function(role) { + for (var i = 0; i < this.members.length; i++) { + if (this.members[i].role === role) { + return assignIn({}, this.members[i], {index: i}); + } + } + }, - removeMembersWithID: function(id) { - var members = reject(this.members, function(m) { return m.id === id; }); - return this.update({members: members}); - }, + // Same as memberByRole, but returns all members with the given role + membersByRole: function(role) { + var result = []; + for (var i = 0; i < this.members.length; i++) { + if (this.members[i].role === role) { + result.push(assignIn({}, this.members[i], {index: i})); + } + } + return result; + }, + // Return the first member with the given id. A copy of the member object + // is returned, extended with an 'index' property whose value is the member index. + memberById: function(id) { + for (var i = 0; i < this.members.length; i++) { + if (this.members[i].id === id) { + return assignIn({}, this.members[i], {index: i}); + } + } + }, - // Wherever a member appears with id `needle.id`, replace it with a member - // with id `replacement.id`, type `replacement.type`, and the original role, - // By default, adding a duplicate member (by id and role) is prevented. - // Return an updated relation. - replaceMember: function(needle, replacement, keepDuplicates) { - if (!this.memberById(needle.id)) - return this; - var members = []; + // Return the first member with the given id and role. A copy of the member object + // is returned, extended with an 'index' property whose value is the member index. + memberByIdAndRole: function(id, role) { + for (var i = 0; i < this.members.length; i++) { + if (this.members[i].id === id && this.members[i].role === role) { + return assignIn({}, this.members[i], {index: i}); + } + } + }, - for (var i = 0; i < this.members.length; i++) { - var member = this.members[i]; - if (member.id !== needle.id) { - members.push(member); - } else if (keepDuplicates || !this.memberByIdAndRole(replacement.id, member.role)) { - members.push({id: replacement.id, type: replacement.type, role: member.role}); - } - } - return this.update({members: members}); - }, + addMember: function(member, index) { + var members = this.members.slice(); + members.splice(index === undefined ? members.length : index, 0, member); + return this.update({members: members}); + }, - asJXON: function(changeset_id) { - var r = { - relation: { - '@id': this.osmId(), - '@version': this.version || 0, - member: map$3(this.members, function(member) { - return { - keyAttributes: { - type: member.type, - role: member.role, - ref: osmEntity$$1.id.toOSM(member.id) - } - }; - }), - tag: map$3(this.tags, function(v, k) { - return { keyAttributes: { k: k, v: v } }; - }) - } - }; - if (changeset_id) r.relation['@changeset'] = changeset_id; - return r; - }, + updateMember: function(member, index) { + var members = this.members.slice(); + members.splice(index, 1, assignIn({}, members[index], member)); + return this.update({members: members}); + }, - asGeoJSON: function(resolver) { - return resolver.transient(this, 'GeoJSON', function () { - if (this.isMultipolygon()) { - return { - type: 'MultiPolygon', - coordinates: this.multipolygon(resolver) - }; - } else { - return { - type: 'FeatureCollection', - properties: this.tags, - features: this.members.map(function (member) { - return assignIn({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver)); - }) - }; - } - }); - }, + removeMember: function(index) { + var members = this.members.slice(); + members.splice(index, 1); + return this.update({members: members}); + }, - area: function(resolver) { - return resolver.transient(this, 'area', function() { - return d3_geoArea(this.asGeoJSON(resolver)); - }); - }, + removeMembersWithID: function(id) { + var members = reject(this.members, function(m) { return m.id === id; }); + return this.update({members: members}); + }, - isMultipolygon: function() { - return this.tags.type === 'multipolygon'; - }, + // Wherever a member appears with id `needle.id`, replace it with a member + // with id `replacement.id`, type `replacement.type`, and the original role, + // By default, adding a duplicate member (by id and role) is prevented. + // Return an updated relation. + replaceMember: function(needle, replacement, keepDuplicates) { + if (!this.memberById(needle.id)) + return this; + var members = []; - isComplete: function(resolver) { - for (var i = 0; i < this.members.length; i++) { - if (!resolver.hasEntity(this.members[i].id)) { - return false; - } - } - return true; - }, + for (var i = 0; i < this.members.length; i++) { + var member = this.members[i]; + if (member.id !== needle.id) { + members.push(member); + } else if (keepDuplicates || !this.memberByIdAndRole(replacement.id, member.role)) { + members.push({id: replacement.id, type: replacement.type, role: member.role}); + } + } + return this.update({members: members}); + }, - isRestriction: function() { - return !!(this.tags.type && this.tags.type.match(/^restriction:?/)); - }, + asJXON: function(changeset_id) { + var r = { + relation: { + '@id': this.osmId(), + '@version': this.version || 0, + member: map$3(this.members, function(member) { + return { + keyAttributes: { + type: member.type, + role: member.role, + ref: osmEntity$$1.id.toOSM(member.id) + } + }; + }), + tag: map$3(this.tags, function(v, k) { + return { keyAttributes: { k: k, v: v } }; + }) + } + }; + if (changeset_id) r.relation['@changeset'] = changeset_id; + return r; + }, - isValidRestriction: function() { - if (!this.isRestriction()) return false; - var froms = this.members.filter(function(m) { return m.role === 'from'; }); - var vias = this.members.filter(function(m) { return m.role === 'via'; }); - var tos = this.members.filter(function(m) { return m.role === 'to'; }); + asGeoJSON: function(resolver) { + return resolver.transient(this, 'GeoJSON', function () { + if (this.isMultipolygon()) { + return { + type: 'MultiPolygon', + coordinates: this.multipolygon(resolver) + }; + } else { + return { + type: 'FeatureCollection', + properties: this.tags, + features: this.members.map(function (member) { + return assignIn({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver)); + }) + }; + } + }); + }, - if (froms.length !== 1 && this.tags.restriction !== 'no_entry') return false; - if (froms.some(function(m) { return m.type !== 'way'; })) return false; - if (tos.length !== 1 && this.tags.restriction !== 'no_exit') return false; - if (tos.some(function(m) { return m.type !== 'way'; })) return false; + area: function(resolver) { + return resolver.transient(this, 'area', function() { + return d3_geoArea(this.asGeoJSON(resolver)); + }); + }, - if (vias.length === 0) return false; - if (vias.length > 1 && vias.some(function(m) { return m.type !== 'way'; })) return false; - return true; - }, + isMultipolygon: function() { + return this.tags.type === 'multipolygon'; + }, - // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm], - // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings. - // - // This corresponds to the structure needed for rendering a multipolygon path using a - // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry. - // - // In the case of invalid geometries, this function will still return a result which - // includes the nodes of all way members, but some Nds may be unclosed and some inner - // rings not matched with the intended outer ring. - // - multipolygon: function(resolver) { - var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }); - var inners = this.members.filter(function(m) { return 'inner' === m.role; }); + isComplete: function(resolver) { + for (var i = 0; i < this.members.length; i++) { + if (!resolver.hasEntity(this.members[i].id)) { + return false; + } + } + return true; + }, - outers = osmJoinWays(outers, resolver); - inners = osmJoinWays(inners, resolver); - outers = outers.map(function(outer) { return map$3(outer.nodes, 'loc'); }); - inners = inners.map(function(inner) { return map$3(inner.nodes, 'loc'); }); + isRestriction: function() { + return !!(this.tags.type && this.tags.type.match(/^restriction:?/)); + }, - var result = outers.map(function(o) { - // Heuristic for detecting counterclockwise winding order. Assumes - // that OpenStreetMap polygons are not hemisphere-spanning. - return [d3_geoArea({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o]; - }); - function findOuter(inner) { - var o, outer; + isValidRestriction: function() { + if (!this.isRestriction()) return false; - for (o = 0; o < outers.length; o++) { - outer = outers[o]; - if (geoPolygonContainsPolygon(outer, inner)) - return o; - } + var froms = this.members.filter(function(m) { return m.role === 'from'; }); + var vias = this.members.filter(function(m) { return m.role === 'via'; }); + var tos = this.members.filter(function(m) { return m.role === 'to'; }); - for (o = 0; o < outers.length; o++) { - outer = outers[o]; - if (geoPolygonIntersectsPolygon(outer, inner, false)) - return o; - } - } + if (froms.length !== 1 && this.tags.restriction !== 'no_entry') return false; + if (froms.some(function(m) { return m.type !== 'way'; })) return false; - for (var i = 0; i < inners.length; i++) { - var inner = inners[i]; + if (tos.length !== 1 && this.tags.restriction !== 'no_exit') return false; + if (tos.some(function(m) { return m.type !== 'way'; })) return false; - if (d3_geoArea({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) { - inner = inner.reverse(); - } + if (vias.length === 0) return false; + if (vias.length > 1 && vias.some(function(m) { return m.type !== 'way'; })) return false; - var o = findOuter(inners[i]); - if (o !== undefined) - result[o].push(inners[i]); - else - result.push([inners[i]]); // Invalid geometry - } + return true; + }, - return result; - } -}); - -function osmTurn(turn) { - if (!(this instanceof osmTurn)) { - return new osmTurn(turn); - } - assignIn(this, turn); -} - - -function osmIntersection(graph, startVertexId, maxDistance) { - maxDistance = maxDistance || 30; // in meters - var vgraph = coreGraph$$1(); // virtual graph - var i, j, k; - - - function memberOfRestriction(entity) { - return graph.parentRelations(entity) - .some(function(r) { return r.isRestriction(); }); - } - - function isRoad(way) { - if (way.isArea() || way.isDegenerate()) return false; - var roads = { - 'motorway': true, - 'motorway_link': true, - 'trunk': true, - 'trunk_link': true, - 'primary': true, - 'primary_link': true, - 'secondary': true, - 'secondary_link': true, - 'tertiary': true, - 'tertiary_link': true, - 'residential': true, - 'unclassified': true, - 'living_street': true, - 'service': true, - 'road': true, - 'track': true - }; - return roads[way.tags.highway]; - } + // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm], + // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings. + // + // This corresponds to the structure needed for rendering a multipolygon path using a + // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry. + // + // In the case of invalid geometries, this function will still return a result which + // includes the nodes of all way members, but some Nds may be unclosed and some inner + // rings not matched with the intended outer ring. + // + multipolygon: function(resolver) { + var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }); + var inners = this.members.filter(function(m) { return 'inner' === m.role; }); + + outers = osmJoinWays(outers, resolver); + inners = osmJoinWays(inners, resolver); + + outers = outers.map(function(outer) { return map$3(outer.nodes, 'loc'); }); + inners = inners.map(function(inner) { return map$3(inner.nodes, 'loc'); }); + + var result = outers.map(function(o) { + // Heuristic for detecting counterclockwise winding order. Assumes + // that OpenStreetMap polygons are not hemisphere-spanning. + return [d3_geoArea({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o]; + }); - var startNode = graph.entity(startVertexId); - var checkVertices = [startNode]; - var checkWays; - var vertices = []; - var vertexIds = []; - var vertex; - var ways = []; - var wayIds = []; - var way; - var nodes = []; - var node; - var parents = []; - var parent; - - // `actions` will store whatever actions must be performed to satisfy - // preconditions for adding a turn restriction to this intersection. - // - Remove any existing degenerate turn restrictions (missing from/to, etc) - // - Reverse oneways so that they are drawn in the forward direction - // - Split ways on key vertices - var actions = []; - - - // STEP 1: walk the graph outwards from starting vertex to search - // for more key vertices and ways to include in the intersection.. - - while (checkVertices.length) { - vertex = checkVertices.pop(); - - // check this vertex for parent ways that are roads - checkWays = graph.parentWays(vertex); - var hasWays = false; - for (i = 0; i < checkWays.length; i++) { - way = checkWays[i]; - if (!isRoad(way) && !memberOfRestriction(way)) continue; - - ways.push(way); // it's a road, or it's already in a turn restriction - hasWays = true; - - // check the way's children for more key vertices - nodes = uniq(graph.childNodes(way)); - for (j = 0; j < nodes.length; j++) { - node = nodes[j]; - if (node === vertex) continue; // same thing - if (vertices.indexOf(node) !== -1) continue; // seen it already - if (node.loc && startNode.loc && - geoSphericalDistance(node.loc, startNode.loc) > maxDistance) continue; // too far from start - - // a key vertex will have parents that are also roads - var hasParents = false; - parents = graph.parentWays(node); - for (k = 0; k < parents.length; k++) { - parent = parents[k]; - if (parent === way) continue; // same thing - if (ways.indexOf(parent) !== -1) continue; // seen it already - if (!isRoad(parent)) continue; // not a road - hasParents = true; - break; - } - - if (hasParents) { - checkVertices.push(node); - } - } - } + function findOuter(inner) { + var o, outer; - if (hasWays) { - vertices.push(vertex); - } - } + for (o = 0; o < outers.length; o++) { + outer = outers[o]; + if (geoPolygonContainsPolygon(outer, inner)) + return o; + } - vertices = uniq(vertices); - ways = uniq(ways); + for (o = 0; o < outers.length; o++) { + outer = outers[o]; + if (geoPolygonIntersectsPolygon(outer, inner, false)) + return o; + } + } + for (var i = 0; i < inners.length; i++) { + var inner = inners[i]; - // STEP 2: Build a virtual graph containing only the entities in the intersection.. - // Everything done after this step should act on the virtual graph - // Any actions that must be performed later to the main graph go in `actions` array - ways.forEach(function(way) { - graph.childNodes(way).forEach(function(node) { - vgraph = vgraph.replace(node); - }); + if (d3_geoArea({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) { + inner = inner.reverse(); + } - vgraph = vgraph.replace(way); + var o = findOuter(inners[i]); + if (o !== undefined) + result[o].push(inners[i]); + else + result.push([inners[i]]); // Invalid geometry + } - graph.parentRelations(way).forEach(function(relation) { - if (relation.isRestriction()) { - if (relation.isValidRestriction(graph)) { - vgraph = vgraph.replace(relation); - } else if (relation.isComplete(graph)) { - actions.push(actionDeleteRelation(relation.id)); - } - } - }); - }); + return result; + } + }); + function osmTurn(turn) { + if (!(this instanceof osmTurn)) { + return new osmTurn(turn); + } + assignIn(this, turn); + } - // STEP 3: Force all oneways to be drawn in the forward direction - ways.forEach(function(w) { - var way = vgraph.entity(w.id); - if (way.tags.oneway === '-1') { - var action = actionReverse(way.id, { reverseOneway: true }); - actions.push(action); - vgraph = action(vgraph); - } - }); + function osmIntersection(graph, startVertexId, maxDistance) { + maxDistance = maxDistance || 30; // in meters + var vgraph = coreGraph$$1(); // virtual graph + var i, j, k; - // STEP 4: Split ways on key vertices - var origCount = osmEntity$$1.id.next.way; - vertices.forEach(function(v) { - // This is an odd way to do it, but we need to find all the ways that - // will be split here, then split them one at a time to ensure that these - // actions can be replayed on the main graph exactly in the same order. - // (It is unintuitive, but the order of ways returned from graph.parentWays() - // is arbitrary, depending on how the main graph and vgraph were built) - var splitAll = actionSplit(v.id); - if (!splitAll.disabled(vgraph)) { - splitAll.ways(vgraph).forEach(function(way) { - var splitOne = actionSplit(v.id).limitWays([way.id]); - actions.push(splitOne); - vgraph = splitOne(vgraph); - }); - } - }); - // In here is where we should also split the intersection at nearby junction. - // for https://github.com/mapbox/iD-internal/issues/31 - // nearbyVertices.forEach(function(v) { - // }); - - // Reasons why we reset the way id count here: - // 1. Continuity with way ids created by the splits so that we can replay - // these actions later if the user decides to create a turn restriction - // 2. Avoids churning way ids just by hovering over a vertex - // and displaying the turn restriction editor - osmEntity$$1.id.next.way = origCount; - - - // STEP 5: Update arrays to point to vgraph entities - vertexIds = vertices.map(function(v) { return v.id; }); - vertices = []; - ways = []; - - vertexIds.forEach(function(id) { - var vertex = vgraph.entity(id); - var parents = vgraph.parentWays(vertex); - vertices.push(vertex); - ways = ways.concat(parents); - }); + function memberOfRestriction(entity) { + return graph.parentRelations(entity) + .some(function(r) { return r.isRestriction(); }); + } - vertices = uniq(vertices); - ways = uniq(ways); + function isRoad(way) { + if (way.isArea() || way.isDegenerate()) return false; + var roads = { + 'motorway': true, + 'motorway_link': true, + 'trunk': true, + 'trunk_link': true, + 'primary': true, + 'primary_link': true, + 'secondary': true, + 'secondary_link': true, + 'tertiary': true, + 'tertiary_link': true, + 'residential': true, + 'unclassified': true, + 'living_street': true, + 'service': true, + 'road': true, + 'track': true + }; + return roads[way.tags.highway]; + } - vertexIds = vertices.map(function(v) { return v.id; }); - wayIds = ways.map(function(w) { return w.id; }); + var startNode = graph.entity(startVertexId); + var checkVertices = [startNode]; + var checkWays; + var vertices = []; + var vertexIds = []; + var vertex; + var ways = []; + var wayIds = []; + var way; + var nodes = []; + var node; + var parents = []; + var parent; + + // `actions` will store whatever actions must be performed to satisfy + // preconditions for adding a turn restriction to this intersection. + // - Remove any existing degenerate turn restrictions (missing from/to, etc) + // - Reverse oneways so that they are drawn in the forward direction + // - Split ways on key vertices + var actions = []; + + + // STEP 1: walk the graph outwards from starting vertex to search + // for more key vertices and ways to include in the intersection.. + + while (checkVertices.length) { + vertex = checkVertices.pop(); + + // check this vertex for parent ways that are roads + checkWays = graph.parentWays(vertex); + var hasWays = false; + for (i = 0; i < checkWays.length; i++) { + way = checkWays[i]; + if (!isRoad(way) && !memberOfRestriction(way)) continue; + + ways.push(way); // it's a road, or it's already in a turn restriction + hasWays = true; + + // check the way's children for more key vertices + nodes = uniq(graph.childNodes(way)); + for (j = 0; j < nodes.length; j++) { + node = nodes[j]; + if (node === vertex) continue; // same thing + if (vertices.indexOf(node) !== -1) continue; // seen it already + if (node.loc && startNode.loc && + geoSphericalDistance(node.loc, startNode.loc) > maxDistance) continue; // too far from start + + // a key vertex will have parents that are also roads + var hasParents = false; + parents = graph.parentWays(node); + for (k = 0; k < parents.length; k++) { + parent = parents[k]; + if (parent === way) continue; // same thing + if (ways.indexOf(parent) !== -1) continue; // seen it already + if (!isRoad(parent)) continue; // not a road + hasParents = true; + break; + } + + if (hasParents) { + checkVertices.push(node); + } + } + } - // STEP 6: Update the ways with some metadata that will be useful for - // walking the intersection graph later and rendering turn arrows. + if (hasWays) { + vertices.push(vertex); + } + } - function withMetadata(way, vertexIds) { - var __oneWay = way.isOneWay(); + vertices = uniq(vertices); + ways = uniq(ways); - // which affixes are key vertices? - var __first = (vertexIds.indexOf(way.first()) !== -1); - var __last = (vertexIds.indexOf(way.last()) !== -1); - // what roles is this way eligible for? - var __via = (__first && __last); - var __from = ((__first && !__oneWay) || __last); - var __to = (__first || (__last && !__oneWay)); + // STEP 2: Build a virtual graph containing only the entities in the intersection.. + // Everything done after this step should act on the virtual graph + // Any actions that must be performed later to the main graph go in `actions` array + ways.forEach(function(way) { + graph.childNodes(way).forEach(function(node) { + vgraph = vgraph.replace(node); + }); - return way.update({ - __first: __first, - __last: __last, - __from: __from, - __via: __via, - __to: __to, - __oneWay: __oneWay - }); - } + vgraph = vgraph.replace(way); - ways = []; - wayIds.forEach(function(id) { - var way = withMetadata(vgraph.entity(id), vertexIds); - vgraph = vgraph.replace(way); - ways.push(way); - }); + graph.parentRelations(way).forEach(function(relation) { + if (relation.isRestriction()) { + if (relation.isValidRestriction(graph)) { + vgraph = vgraph.replace(relation); + } else if (relation.isComplete(graph)) { + actions.push(actionDeleteRelation(relation.id)); + } + } + }); + }); - // STEP 7: Simplify - This is an iterative process where we: - // 1. Find trivial vertices with only 2 parents - // 2. trim off the leaf way from those vertices and remove from vgraph + // STEP 3: Force all oneways to be drawn in the forward direction + ways.forEach(function(w) { + var way = vgraph.entity(w.id); + if (way.tags.oneway === '-1') { + var action = actionReverse(way.id, { reverseOneway: true }); + actions.push(action); + vgraph = action(vgraph); + } + }); - var keepGoing; - var removeWayIds = []; - var removeVertexIds = []; - do { - keepGoing = false; - checkVertices = vertexIds.slice(); - - for (i = 0; i < checkVertices.length; i++) { - var vertexId = checkVertices[i]; - vertex = vgraph.hasEntity(vertexId); - - if (!vertex) { - if (vertexIds.indexOf(vertexId) !== -1) { - vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one - } - removeVertexIds.push(vertexId); - continue; - } + // STEP 4: Split ways on key vertices + var origCount = osmEntity$$1.id.next.way; + vertices.forEach(function(v) { + // This is an odd way to do it, but we need to find all the ways that + // will be split here, then split them one at a time to ensure that these + // actions can be replayed on the main graph exactly in the same order. + // (It is unintuitive, but the order of ways returned from graph.parentWays() + // is arbitrary, depending on how the main graph and vgraph were built) + var splitAll = actionSplit(v.id); + if (!splitAll.disabled(vgraph)) { + splitAll.ways(vgraph).forEach(function(way) { + var splitOne = actionSplit(v.id).limitWays([way.id]); + actions.push(splitOne); + vgraph = splitOne(vgraph); + }); + } + }); - parents = vgraph.parentWays(vertex); - if (parents.length < 3) { - if (vertexIds.indexOf(vertexId) !== -1) { - vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one - } - } + // In here is where we should also split the intersection at nearby junction. + // for https://github.com/mapbox/iD-internal/issues/31 + // nearbyVertices.forEach(function(v) { + // }); + + // Reasons why we reset the way id count here: + // 1. Continuity with way ids created by the splits so that we can replay + // these actions later if the user decides to create a turn restriction + // 2. Avoids churning way ids just by hovering over a vertex + // and displaying the turn restriction editor + osmEntity$$1.id.next.way = origCount; + + + // STEP 5: Update arrays to point to vgraph entities + vertexIds = vertices.map(function(v) { return v.id; }); + vertices = []; + ways = []; + + vertexIds.forEach(function(id) { + var vertex = vgraph.entity(id); + var parents = vgraph.parentWays(vertex); + vertices.push(vertex); + ways = ways.concat(parents); + }); - if (parents.length === 2) { // vertex with 2 parents is trivial - var a = parents[0]; - var b = parents[1]; - var aIsLeaf = a && !a.__via; - var bIsLeaf = b && !b.__via; - var leaf, survivor; - - if (aIsLeaf && !bIsLeaf) { - leaf = a; - survivor = b; - } else if (!aIsLeaf && bIsLeaf) { - leaf = b; - survivor = a; - } - - if (leaf && survivor) { - survivor = withMetadata(survivor, vertexIds); // update survivor way - vgraph = vgraph.replace(survivor).remove(leaf); // update graph - removeWayIds.push(leaf.id); - keepGoing = true; - } - } + vertices = uniq(vertices); + ways = uniq(ways); - parents = vgraph.parentWays(vertex); + vertexIds = vertices.map(function(v) { return v.id; }); + wayIds = ways.map(function(w) { return w.id; }); - if (parents.length < 2) { // vertex is no longer a key vertex - if (vertexIds.indexOf(vertexId) !== -1) { - vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one - } - removeVertexIds.push(vertexId); - keepGoing = true; - } - if (parents.length < 1) { // vertex is no longer attached to anything - vgraph = vgraph.remove(vertex); - } + // STEP 6: Update the ways with some metadata that will be useful for + // walking the intersection graph later and rendering turn arrows. - } - } while (keepGoing); + function withMetadata(way, vertexIds) { + var __oneWay = way.isOneWay(); + // which affixes are key vertices? + var __first = (vertexIds.indexOf(way.first()) !== -1); + var __last = (vertexIds.indexOf(way.last()) !== -1); - vertices = vertices - .filter(function(vertex) { return removeVertexIds.indexOf(vertex.id) === -1; }) - .map(function(vertex) { return vgraph.entity(vertex.id); }); - ways = ways - .filter(function(way) { return removeWayIds.indexOf(way.id) === -1; }) - .map(function(way) { return vgraph.entity(way.id); }); + // what roles is this way eligible for? + var __via = (__first && __last); + var __from = ((__first && !__oneWay) || __last); + var __to = (__first || (__last && !__oneWay)); + return way.update({ + __first: __first, + __last: __last, + __from: __from, + __via: __via, + __to: __to, + __oneWay: __oneWay + }); + } - // OK! Here is our intersection.. - var intersection = { - graph: vgraph, - actions: actions, - vertices: vertices, - ways: ways, - }; + ways = []; + wayIds.forEach(function(id) { + var way = withMetadata(vgraph.entity(id), vertexIds); + vgraph = vgraph.replace(way); + ways.push(way); + }); + // STEP 7: Simplify - This is an iterative process where we: + // 1. Find trivial vertices with only 2 parents + // 2. trim off the leaf way from those vertices and remove from vgraph + + var keepGoing; + var removeWayIds = []; + var removeVertexIds = []; + + do { + keepGoing = false; + checkVertices = vertexIds.slice(); + + for (i = 0; i < checkVertices.length; i++) { + var vertexId = checkVertices[i]; + vertex = vgraph.hasEntity(vertexId); + + if (!vertex) { + if (vertexIds.indexOf(vertexId) !== -1) { + vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one + } + removeVertexIds.push(vertexId); + continue; + } + + parents = vgraph.parentWays(vertex); + if (parents.length < 3) { + if (vertexIds.indexOf(vertexId) !== -1) { + vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one + } + } + + if (parents.length === 2) { // vertex with 2 parents is trivial + var a = parents[0]; + var b = parents[1]; + var aIsLeaf = a && !a.__via; + var bIsLeaf = b && !b.__via; + var leaf, survivor; + + if (aIsLeaf && !bIsLeaf) { + leaf = a; + survivor = b; + } else if (!aIsLeaf && bIsLeaf) { + leaf = b; + survivor = a; + } + + if (leaf && survivor) { + survivor = withMetadata(survivor, vertexIds); // update survivor way + vgraph = vgraph.replace(survivor).remove(leaf); // update graph + removeWayIds.push(leaf.id); + keepGoing = true; + } + } + + parents = vgraph.parentWays(vertex); + + if (parents.length < 2) { // vertex is no longer a key vertex + if (vertexIds.indexOf(vertexId) !== -1) { + vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one + } + removeVertexIds.push(vertexId); + keepGoing = true; + } + + if (parents.length < 1) { // vertex is no longer attached to anything + vgraph = vgraph.remove(vertex); + } - // Get all the valid turns through this intersection given a starting way id. - // This operates on the virtual graph for everything. - // - // Basically, walk through all possible paths from starting way, - // honoring the existing turn restrictions as we go (watch out for loops!) - // - // For each path found, generate and return a `osmTurn` datastructure. - // - intersection.turns = function(fromWayId, maxViaWay) { - if (!fromWayId) return []; - if (!maxViaWay) maxViaWay = 0; - - var vgraph = intersection.graph; - var keyVertexIds = intersection.vertices.map(function(v) { return v.id; }); - - var start = vgraph.entity(fromWayId); - if (!start || !(start.__from || start.__via)) return []; - - // maxViaWay=0 from-*-to (0 vias) - // maxViaWay=1 from-*-via-*-to (1 via max) - // maxViaWay=2 from-*-via-*-via-*-to (2 vias max) - var maxPathLength = (maxViaWay * 2) + 3; - var turns = []; - - step(start); - return turns; - - - // traverse the intersection graph and find all the valid paths - function step(entity, currPath, currRestrictions, matchedRestriction) { - currPath = clone(currPath || []); - if (currPath.length >= maxPathLength) return; - currPath.push(entity.id); - currRestrictions = clone(currRestrictions || []); - var i, j; - - if (entity.type === 'node') { - var parents = vgraph.parentWays(entity); - var nextWays = []; - - // which ways can we step into? - for (i = 0; i < parents.length; i++) { - var way = parents[i]; - - // if next way is a oneway incoming to this vertex, skip - if (way.__oneWay && way.nodes[0] !== entity.id) continue; - - // if we have seen it before (allowing for an initial u-turn), skip - if (currPath.indexOf(way.id) !== -1 && currPath.length >= 3) continue; - - // Check all "current" restrictions (where we've already walked the `FROM`) - var restrict = undefined; - for (j = 0; j < currRestrictions.length; j++) { - var restriction = currRestrictions[j]; - var f = restriction.memberByRole('from'); - var v = restriction.membersByRole('via'); - var t = restriction.memberByRole('to'); - var isOnly = /^only_/.test(restriction.tags.restriction); - - // Does the current path match this turn restriction? - var matchesFrom = (f.id === fromWayId); - var matchesViaTo = false; - var isAlongOnlyPath = false; - - if (t.id === way.id) { // match VIA, TO - if (v.length === 1 && v[0].type === 'node' && v[0].id === entity.id) { - matchesViaTo = true; // match VIA node - } else if (every(v, function(via) { return currPath.indexOf(via.id) !== -1; })) { - matchesViaTo = true; // match all VIA ways - } - - } else if (isOnly) { - for (k = 0; k < v.length; k++) { - // way doesn't match TO, but is one of the via ways along the path of an "only" - if (v[k].type === 'way' && v[k].id === way.id) { - isAlongOnlyPath = true; - break; - } - } - } - - if (matchesViaTo) { - if (isOnly) { - restrict = { id: restriction.id, direct: matchesFrom, from: f.id, only: true, end: true }; - } else { - restrict = { id: restriction.id, direct: matchesFrom, from: f.id, no: true, end: true }; - } - } else { // indirect - caused by a different nearby restriction - if (isAlongOnlyPath) { - restrict = { id: restriction.id, direct: false, from: f.id, only: true, end: false }; - } else if (isOnly) { - restrict = { id: restriction.id, direct: false, from: f.id, no: true, end: true }; - } - } - - // stop looking if we find a "direct" restriction (matching FROM, VIA, TO) - if (restrict && restrict.direct) - break; - } - - nextWays.push({ way: way, restrict: restrict }); - } - - nextWays.forEach(function(nextWay) { - step(nextWay.way, currPath, currRestrictions, nextWay.restrict); - }); - - - } else { // entity.type === 'way' - if (currPath.length >= 3) { // this is a "complete" path.. - var turnPath = clone(currPath); - - // an indirect restriction - only include the partial path (starting at FROM) - if (matchedRestriction && matchedRestriction.direct === false) { - for (i = 0; i < turnPath.length; i++) { - if (turnPath[i] === matchedRestriction.from) { - turnPath = turnPath.slice(i); - break; - } - } - } - - var turn = pathToTurn(turnPath); - if (turn) { - if (matchedRestriction) { - turn.restrictionID = matchedRestriction.id; - turn.no = matchedRestriction.no; - turn.only = matchedRestriction.only; - turn.direct = matchedRestriction.direct; - } - turns.push(osmTurn(turn)); - } - - if (currPath[0] === currPath[2]) return; // if we made a u-turn - stop here - } - - if (matchedRestriction && matchedRestriction.end) return; // don't advance any further - - // which nodes can we step into? - var n1 = vgraph.entity(entity.first()); - var n2 = vgraph.entity(entity.last()); - var dist = n1.loc && n2.loc && geoSphericalDistance(n1.loc, n2.loc); - var nextNodes = []; - - if (currPath.length > 1) { - if (dist > maxDistance) return; // the next node is too far - if (!entity.__via) return; // this way is a leaf / can't be a via - } - - if (!entity.__oneWay && // bidirectional.. - keyVertexIds.indexOf(n1.id) !== -1 && // key vertex.. - currPath.indexOf(n1.id) === -1) { // haven't seen it yet.. - nextNodes.push(n1); // can advance to first node - } - if (keyVertexIds.indexOf(n2.id) !== -1 && // key vertex.. - currPath.indexOf(n2.id) === -1) { // haven't seen it yet.. - nextNodes.push(n2); // can advance to last node - } - - nextNodes.forEach(function(nextNode) { - // gather restrictions FROM this way - var fromRestrictions = vgraph.parentRelations(entity).filter(function(r) { - if (!r.isRestriction()) return false; - - var f = r.memberByRole('from'); - if (!f || f.id !== entity.id) return false; - - var isOnly = /^only_/.test(r.tags.restriction); - if (!isOnly) return true; - - // `only_` restrictions only matter along the direction of the VIA - #4849 - var isOnlyVia = false; - var v = r.membersByRole('via'); - if (v.length === 1 && v[0].type === 'node') { // via node - isOnlyVia = (v[0].id === nextNode.id); - } else { // via way(s) - for (k = 0; k < v.length; k++) { - if (v[k].type === 'way' && vgraph.entity(v[k].id).first() === nextNode.id) { - isOnlyVia = true; - break; - } - } - } - return isOnlyVia; - }); - - step(nextNode, currPath, currRestrictions.concat(fromRestrictions), false); - }); - } - } + } + } while (keepGoing); - // assumes path is alternating way-node-way of odd length - function pathToTurn(path) { - if (path.length < 3) return; - var fromWayId, fromNodeId, fromVertexId; - var toWayId, toNodeId, toVertexId; - var viaWayIds, viaNodeId, isUturn; + vertices = vertices + .filter(function(vertex) { return removeVertexIds.indexOf(vertex.id) === -1; }) + .map(function(vertex) { return vgraph.entity(vertex.id); }); + ways = ways + .filter(function(way) { return removeWayIds.indexOf(way.id) === -1; }) + .map(function(way) { return vgraph.entity(way.id); }); - fromWayId = path[0]; - toWayId = path[path.length - 1]; - if (path.length === 3 && fromWayId === toWayId) { // u turn - var way = vgraph.entity(fromWayId); - if (way.__oneWay) return null; + // OK! Here is our intersection.. + var intersection = { + graph: vgraph, + actions: actions, + vertices: vertices, + ways: ways, + }; - isUturn = true; - viaNodeId = fromVertexId = toVertexId = path[1]; - fromNodeId = toNodeId = adjacentNode(fromWayId, viaNodeId); - } else { - isUturn = false; - fromVertexId = path[1]; - fromNodeId = adjacentNode(fromWayId, fromVertexId); - toVertexId = path[path.length - 2]; - toNodeId = adjacentNode(toWayId, toVertexId); - - if (path.length === 3) { - viaNodeId = path[1]; - } else { - viaWayIds = path.filter(function(entityId) { return entityId[0] === 'w'; }); - viaWayIds = viaWayIds.slice(1, viaWayIds.length - 1); // remove first, last - } - } - return { - key: path.join('_'), - path: path, - from: { node: fromNodeId, way: fromWayId, vertex: fromVertexId }, - via: { node: viaNodeId, ways: viaWayIds }, - to: { node: toNodeId, way: toWayId, vertex: toVertexId }, - u: isUturn - }; + // Get all the valid turns through this intersection given a starting way id. + // This operates on the virtual graph for everything. + // + // Basically, walk through all possible paths from starting way, + // honoring the existing turn restrictions as we go (watch out for loops!) + // + // For each path found, generate and return a `osmTurn` datastructure. + // + intersection.turns = function(fromWayId, maxViaWay) { + if (!fromWayId) return []; + if (!maxViaWay) maxViaWay = 0; + + var vgraph = intersection.graph; + var keyVertexIds = intersection.vertices.map(function(v) { return v.id; }); + + var start = vgraph.entity(fromWayId); + if (!start || !(start.__from || start.__via)) return []; + + // maxViaWay=0 from-*-to (0 vias) + // maxViaWay=1 from-*-via-*-to (1 via max) + // maxViaWay=2 from-*-via-*-via-*-to (2 vias max) + var maxPathLength = (maxViaWay * 2) + 3; + var turns = []; + + step(start); + return turns; + + + // traverse the intersection graph and find all the valid paths + function step(entity, currPath, currRestrictions, matchedRestriction) { + currPath = clone(currPath || []); + if (currPath.length >= maxPathLength) return; + currPath.push(entity.id); + currRestrictions = clone(currRestrictions || []); + var i, j; + + if (entity.type === 'node') { + var parents = vgraph.parentWays(entity); + var nextWays = []; + + // which ways can we step into? + for (i = 0; i < parents.length; i++) { + var way = parents[i]; + + // if next way is a oneway incoming to this vertex, skip + if (way.__oneWay && way.nodes[0] !== entity.id) continue; + + // if we have seen it before (allowing for an initial u-turn), skip + if (currPath.indexOf(way.id) !== -1 && currPath.length >= 3) continue; + + // Check all "current" restrictions (where we've already walked the `FROM`) + var restrict = undefined; + for (j = 0; j < currRestrictions.length; j++) { + var restriction = currRestrictions[j]; + var f = restriction.memberByRole('from'); + var v = restriction.membersByRole('via'); + var t = restriction.memberByRole('to'); + var isOnly = /^only_/.test(restriction.tags.restriction); + + // Does the current path match this turn restriction? + var matchesFrom = (f.id === fromWayId); + var matchesViaTo = false; + var isAlongOnlyPath = false; + + if (t.id === way.id) { // match TO + + if (v.length === 1 && v[0].type === 'node') { // match VIA node + matchesViaTo = (v[0].id === entity.id && ( + (matchesFrom && currPath.length === 2) || + (!matchesFrom && currPath.length > 2) + )); + + } else { // match all VIA ways + var pathVias = []; + for (k = 2; k < currPath.length; k +=2 ) { // k = 2 skips FROM + pathVias.push(currPath[k]); // (path goes way-node-way...) + } + var restrictionVias = []; + for (k = 0; k < v.length; k++) { + if (v[k].type === 'way') { + restrictionVias.push(v[k].id); + } + } + var diff = difference(pathVias, restrictionVias); + matchesViaTo = !diff.length; + } + + } else if (isOnly) { + for (k = 0; k < v.length; k++) { + // way doesn't match TO, but is one of the via ways along the path of an "only" + if (v[k].type === 'way' && v[k].id === way.id) { + isAlongOnlyPath = true; + break; + } + } + } + + if (matchesViaTo) { + if (isOnly) { + restrict = { id: restriction.id, direct: matchesFrom, from: f.id, only: true, end: true }; + } else { + restrict = { id: restriction.id, direct: matchesFrom, from: f.id, no: true, end: true }; + } + } else { // indirect - caused by a different nearby restriction + if (isAlongOnlyPath) { + restrict = { id: restriction.id, direct: false, from: f.id, only: true, end: false }; + } else if (isOnly) { + restrict = { id: restriction.id, direct: false, from: f.id, no: true, end: true }; + } + } + + // stop looking if we find a "direct" restriction (matching FROM, VIA, TO) + if (restrict && restrict.direct) + break; + } + + nextWays.push({ way: way, restrict: restrict }); + } + + nextWays.forEach(function(nextWay) { + step(nextWay.way, currPath, currRestrictions, nextWay.restrict); + }); + + + } else { // entity.type === 'way' + if (currPath.length >= 3) { // this is a "complete" path.. + var turnPath = clone(currPath); + + // an indirect restriction - only include the partial path (starting at FROM) + if (matchedRestriction && matchedRestriction.direct === false) { + for (i = 0; i < turnPath.length; i++) { + if (turnPath[i] === matchedRestriction.from) { + turnPath = turnPath.slice(i); + break; + } + } + } + + var turn = pathToTurn(turnPath); + if (turn) { + if (matchedRestriction) { + turn.restrictionID = matchedRestriction.id; + turn.no = matchedRestriction.no; + turn.only = matchedRestriction.only; + turn.direct = matchedRestriction.direct; + } + turns.push(osmTurn(turn)); + } + + if (currPath[0] === currPath[2]) return; // if we made a u-turn - stop here + } + + if (matchedRestriction && matchedRestriction.end) return; // don't advance any further + + // which nodes can we step into? + var n1 = vgraph.entity(entity.first()); + var n2 = vgraph.entity(entity.last()); + var dist = n1.loc && n2.loc && geoSphericalDistance(n1.loc, n2.loc); + var nextNodes = []; + + if (currPath.length > 1) { + if (dist > maxDistance) return; // the next node is too far + if (!entity.__via) return; // this way is a leaf / can't be a via + } + + if (!entity.__oneWay && // bidirectional.. + keyVertexIds.indexOf(n1.id) !== -1 && // key vertex.. + currPath.indexOf(n1.id) === -1) { // haven't seen it yet.. + nextNodes.push(n1); // can advance to first node + } + if (keyVertexIds.indexOf(n2.id) !== -1 && // key vertex.. + currPath.indexOf(n2.id) === -1) { // haven't seen it yet.. + nextNodes.push(n2); // can advance to last node + } + + nextNodes.forEach(function(nextNode) { + // gather restrictions FROM this way + var fromRestrictions = vgraph.parentRelations(entity).filter(function(r) { + if (!r.isRestriction()) return false; + + var f = r.memberByRole('from'); + if (!f || f.id !== entity.id) return false; + + var isOnly = /^only_/.test(r.tags.restriction); + if (!isOnly) return true; + + // `only_` restrictions only matter along the direction of the VIA - #4849 + var isOnlyVia = false; + var v = r.membersByRole('via'); + if (v.length === 1 && v[0].type === 'node') { // via node + isOnlyVia = (v[0].id === nextNode.id); + } else { // via way(s) + for (var i = 0; i < v.length; i++) { + if (v[i].type !== 'way') continue; + var viaWay = vgraph.entity(v[i].id); + if (viaWay.first() === nextNode.id || viaWay.last() === nextNode.id) { + isOnlyVia = true; + break; + } + } + } + return isOnlyVia; + }); + + step(nextNode, currPath, currRestrictions.concat(fromRestrictions), false); + }); + } + } - function adjacentNode(wayId, affixId) { - var nodes = vgraph.entity(wayId).nodes; - return affixId === nodes[0] ? nodes[1] : nodes[nodes.length - 2]; - } - } + // assumes path is alternating way-node-way of odd length + function pathToTurn(path) { + if (path.length < 3) return; + var fromWayId, fromNodeId, fromVertexId; + var toWayId, toNodeId, toVertexId; + var viaWayIds, viaNodeId, isUturn; + + fromWayId = path[0]; + toWayId = path[path.length - 1]; + + if (path.length === 3 && fromWayId === toWayId) { // u turn + var way = vgraph.entity(fromWayId); + if (way.__oneWay) return null; + + isUturn = true; + viaNodeId = fromVertexId = toVertexId = path[1]; + fromNodeId = toNodeId = adjacentNode(fromWayId, viaNodeId); + + } else { + isUturn = false; + fromVertexId = path[1]; + fromNodeId = adjacentNode(fromWayId, fromVertexId); + toVertexId = path[path.length - 2]; + toNodeId = adjacentNode(toWayId, toVertexId); + + if (path.length === 3) { + viaNodeId = path[1]; + } else { + viaWayIds = path.filter(function(entityId) { return entityId[0] === 'w'; }); + viaWayIds = viaWayIds.slice(1, viaWayIds.length - 1); // remove first, last + } + } + + return { + key: path.join('_'), + path: path, + from: { node: fromNodeId, way: fromWayId, vertex: fromVertexId }, + via: { node: viaNodeId, ways: viaWayIds }, + to: { node: toNodeId, way: toWayId, vertex: toVertexId }, + u: isUturn + }; + + + function adjacentNode(wayId, affixId) { + var nodes = vgraph.entity(wayId).nodes; + return affixId === nodes[0] ? nodes[1] : nodes[nodes.length - 2]; + } + } - }; + }; - return intersection; -} + return intersection; + } -function osmInferRestriction(graph, turn, projection) { - var fromWay = graph.entity(turn.from.way); - var fromNode = graph.entity(turn.from.node); - var fromVertex = graph.entity(turn.from.vertex); - var toWay = graph.entity(turn.to.way); - var toNode = graph.entity(turn.to.node); - var toVertex = graph.entity(turn.to.vertex); + function osmInferRestriction(graph, turn, projection) { + var fromWay = graph.entity(turn.from.way); + var fromNode = graph.entity(turn.from.node); + var fromVertex = graph.entity(turn.from.vertex); + var toWay = graph.entity(turn.to.way); + var toNode = graph.entity(turn.to.node); + var toVertex = graph.entity(turn.to.vertex); + + var fromOneWay = (fromWay.tags.oneway === 'yes'); + var toOneWay = (toWay.tags.oneway === 'yes'); + var angle = (geoAngle(fromVertex, fromNode, projection) - + geoAngle(toVertex, toNode, projection)) * 180 / Math.PI; + + while (angle < 0) + angle += 360; + + if (fromNode === toNode) + return 'no_u_turn'; + if ((angle < 23 || angle > 336) && fromOneWay && toOneWay) + return 'no_u_turn'; // wider tolerance for u-turn if both ways are oneway + if ((angle < 40 || angle > 319) && fromOneWay && toOneWay && turn.from.vertex !== turn.to.vertex) + return 'no_u_turn'; // even wider tolerance for u-turn if there is a via way (from !== to) + if (angle < 158) + return 'no_right_turn'; + if (angle > 202) + return 'no_left_turn'; + + return 'no_straight_on'; + } - var fromOneWay = (fromWay.tags.oneway === 'yes'); - var toOneWay = (toWay.tags.oneway === 'yes'); - var angle = (geoAngle(fromVertex, fromNode, projection) - - geoAngle(toVertex, toNode, projection)) * 180 / Math.PI; + function actionAddMember(relationId, member, memberIndex, insertPair) { - while (angle < 0) - angle += 360; + return function action(graph) { + var relation = graph.entity(relationId); - if (fromNode === toNode) - return 'no_u_turn'; - if ((angle < 23 || angle > 336) && fromOneWay && toOneWay) - return 'no_u_turn'; // wider tolerance for u-turn if both ways are oneway - if ((angle < 40 || angle > 319) && fromOneWay && toOneWay && turn.from.vertex !== turn.to.vertex) - return 'no_u_turn'; // even wider tolerance for u-turn if there is a via way (from !== to) - if (angle < 158) - return 'no_right_turn'; - if (angle > 202) - return 'no_left_turn'; + // There are some special rules for Public Transport v2 routes. + var isPTv2 = /stop|platform/.test(member.role); - return 'no_straight_on'; -} + if ((isNaN(memberIndex) || insertPair) && member.type === 'way' && !isPTv2) { + // Try to perform sensible inserts based on how the ways join together + graph = addWayMember(relation, graph); + } else { + // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes + // Stops and Platforms for PTv2 should be ordered first. + // hack: We do not currently have the ability to place them in the exactly correct order. + if (isPTv2 && isNaN(memberIndex)) { + memberIndex = 0; + } + + graph = graph.replace(relation.addMember(member, memberIndex)); + } -function actionAddMember(relationId, member, memberIndex, insertPair) { + return graph; + }; - return function action(graph) { - var relation = graph.entity(relationId); - // There are some special rules for Public Transport v2 routes. - var isPTv2 = (member.role === 'stop' || member.role === 'platform'); + // Add a way member into the relation "wherever it makes sense". + // In this situation we were not supplied a memberIndex. + function addWayMember(relation, graph) { + var groups, tempWay, item, i, j, k; + + // remove PTv2 stops and platforms before doing anything. + var PTv2members = []; + var members = []; + for (i = 0; i < relation.members.length; i++) { + var m = relation.members[i]; + if (/stop|platform/.test(m.role)) { + PTv2members.push(m); + } else { + members.push(m); + } + } + relation = relation.update({ members: members }); + + + if (insertPair) { + // We're adding a member that must stay paired with an existing member. + // (This feature is used by `actionSplit`) + // + // This is tricky because the members may exist multiple times in the + // member list, and with different A-B/B-A ordering and different roles. + // (e.g. a bus route that loops out and back - #4589). + // + // Replace the existing member with a temporary way, + // so that `osmJoinWays` can treat the pair like a single way. + tempWay = osmWay({ id: 'wTemp', nodes: insertPair.nodes }); + graph = graph.replace(tempWay); + var tempMember = { id: tempWay.id, type: 'way', role: member.role }; + var tempRelation = relation.replaceMember({id: insertPair.originalID}, tempMember, true); + groups = groupBy(tempRelation.members, function(m) { return m.type; }); + groups.way = groups.way || []; - if ((isNaN(memberIndex) || insertPair) && member.type === 'way' && !isPTv2) { - // Try to perform sensible inserts based on how the ways join together - graph = addWayMember(relation, graph); - } else { - // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes - // Stops and Platforms for PTv2 should be ordered first. - // hack: We do not currently have the ability to place them in the exactly correct order. - if (isPTv2 && isNaN(memberIndex)) { - memberIndex = 0; - } + } else { + // Add the member anywhere, one time. Just push and let `osmJoinWays` decide where to put it. + groups = groupBy(relation.members, function(m) { return m.type; }); + groups.way = groups.way || []; + groups.way.push(member); + } - graph = graph.replace(relation.addMember(member, memberIndex)); - } + members = withIndex(groups.way); + var joined = osmJoinWays(members, graph); + + // `joined` might not contain all of the way members, + // But will contain only the completed (downloaded) members + for (i = 0; i < joined.length; i++) { + var segment = joined[i]; + var nodes = segment.nodes.slice(); + var startIndex = segment[0].index; + + // j = array index in `members` where this segment starts + for (j = 0; j < members.length; j++) { + if (members[j].index === startIndex) { + break; + } + } + + // k = each member in segment + for (k = 0; k < segment.length; k++) { + item = segment[k]; + var way = graph.entity(item.id); + + // If this is a paired item, generate members in correct order and role + if (tempWay && item.id === tempWay.id) { + if (nodes[0].id === insertPair.nodes[0]) { + item.pair = [ + { id: insertPair.originalID, type: 'way', role: item.role }, + { id: insertPair.insertedID, type: 'way', role: item.role } + ]; + } else { + item.pair = [ + { id: insertPair.insertedID, type: 'way', role: item.role }, + { id: insertPair.originalID, type: 'way', role: item.role } + ]; + } + } + + // reorder `members` if necessary + if (k > 0) { + if (j+k >= members.length || item.index !== members[j+k].index) { + moveMember(members, item.index, j+k); + } + } + + nodes.splice(0, way.nodes.length - 1); + } + } - return graph; - }; + if (tempWay) { + graph = graph.remove(tempWay); + } + // Final pass: skip dead items, split pairs, remove index properties + var wayMembers = []; + for (i = 0; i < members.length; i++) { + item = members[i]; + if (item.index === -1) continue; + + if (item.pair) { + wayMembers.push(item.pair[0]); + wayMembers.push(item.pair[1]); + } else { + wayMembers.push(omit(item, 'index')); + } + } - // Add a way member into the relation "wherever it makes sense". - // In this situation we were not supplied a memberIndex. - function addWayMember(relation, graph) { - var groups, tempWay, item, i, j, k; + // Put stops and platforms first, then nodes, ways, relations + // This is recommended for Public Transport v2 routes: + // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes + var newMembers = PTv2members.concat( (groups.node || []), wayMembers, (groups.relation || []) ); + + return graph.replace(relation.update({members: newMembers})); + + + // `moveMember()` changes the `members` array in place by splicing + // the item with `.index = findIndex` to where it belongs, + // and marking the old position as "dead" with `.index = -1` + // + // j=5, k=0 jk + // segment 5 4 7 6 + // members 0 1 2 3 4 5 6 7 8 9 keep 5 in j+k + // + // j=5, k=1 j k + // segment 5 4 7 6 + // members 0 1 2 3 4 5 6 7 8 9 move 4 to j+k + // members 0 1 2 3 x 5 4 6 7 8 9 moved + // + // j=5, k=2 j k + // segment 5 4 7 6 + // members 0 1 2 3 x 5 4 6 7 8 9 move 7 to j+k + // members 0 1 2 3 x 5 4 7 6 x 8 9 moved + // + // j=5, k=3 j k + // segment 5 4 7 6 + // members 0 1 2 3 x 5 4 7 6 x 8 9 keep 6 in j+k + // + function moveMember(arr, findIndex, toIndex) { + for (var i = 0; i < arr.length; i++) { + if (arr[i].index === findIndex) { + break; + } + } + + var item = clone(arr[i]); + arr[i].index = -1; // mark as dead + item.index = toIndex; + arr.splice(toIndex, 0, item); + } - // remove PTv2 stops and platforms before doing anything. - var PTv2members = []; - var members = []; - for (i = 0; i < relation.members.length; i++) { - var m = relation.members[i]; - if (m.role === 'stop' || m.role === 'platform') { - PTv2members.push(m); - } else { - members.push(m); - } - } - relation = relation.update({ members: members }); - - - if (insertPair) { - // We're adding a member that must stay paired with an existing member. - // (This feature is used by `actionSplit`) - // - // This is tricky because the members may exist multiple times in the - // member list, and with different A-B/B-A ordering and different roles. - // (e.g. a bus route that loops out and back - #4589). - // - // Replace the existing member with a temporary way, - // so that `osmJoinWays` can treat the pair like a single way. - tempWay = osmWay({ id: 'wTemp', nodes: insertPair.nodes }); - graph = graph.replace(tempWay); - var tempMember = { id: tempWay.id, type: 'way', role: member.role }; - var tempRelation = relation.replaceMember({id: insertPair.originalID}, tempMember, true); - groups = groupBy(tempRelation.members, function(m) { return m.type; }); - groups.way = groups.way || []; - } else { - // Add the member anywhere, one time. Just push and let `osmJoinWays` decide where to put it. - groups = groupBy(relation.members, function(m) { return m.type; }); - groups.way = groups.way || []; - groups.way.push(member); - } + // This is the same as `Relation.indexedMembers`, + // Except we don't want to index all the members, only the ways + function withIndex(arr) { + var result = new Array(arr.length); + for (var i = 0; i < arr.length; i++) { + result[i] = arr[i]; + result[i].index = i; + } + return result; + } + } - members = withIndex(groups.way); - var joined = osmJoinWays(members, graph); - - // `joined` might not contain all of the way members, - // But will contain only the completed (downloaded) members - for (i = 0; i < joined.length; i++) { - var segment = joined[i]; - var nodes = segment.nodes.slice(); - var startIndex = segment[0].index; - - // j = array index in `members` where this segment starts - for (j = 0; j < members.length; j++) { - if (members[j].index === startIndex) { - break; - } - } + } - // k = each member in segment - for (k = 0; k < segment.length; k++) { - item = segment[k]; - var way = graph.entity(item.id); - - // If this is a paired item, generate members in correct order and role - if (tempWay && item.id === tempWay.id) { - if (nodes[0].id === insertPair.nodes[0]) { - item.pair = [ - { id: insertPair.originalID, type: 'way', role: item.role }, - { id: insertPair.insertedID, type: 'way', role: item.role } - ]; - } else { - item.pair = [ - { id: insertPair.insertedID, type: 'way', role: item.role }, - { id: insertPair.originalID, type: 'way', role: item.role } - ]; - } - } - - // reorder `members` if necessary - if (k > 0) { - if (j+k >= members.length || item.index !== members[j+k].index) { - moveMember(members, item.index, j+k); - } - } - - nodes.splice(0, way.nodes.length - 1); - } - } + function actionAddMidpoint(midpoint, node) { + return function(graph) { + graph = graph.replace(node.move(midpoint.loc)); - if (tempWay) { - graph = graph.remove(tempWay); - } + var parents = intersection( + graph.parentWays(graph.entity(midpoint.edge[0])), + graph.parentWays(graph.entity(midpoint.edge[1]))); - // Final pass: skip dead items, split pairs, remove index properties - var wayMembers = []; - for (i = 0; i < members.length; i++) { - item = members[i]; - if (item.index === -1) continue; + parents.forEach(function(way) { + for (var i = 0; i < way.nodes.length - 1; i++) { + if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) { + graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1)); - if (item.pair) { - wayMembers.push(item.pair[0]); - wayMembers.push(item.pair[1]); - } else { - wayMembers.push(omit(item, 'index')); - } - } + // Add only one midpoint on doubled-back segments, + // turning them into self-intersections. + return; + } + } + }); - // Put stops and platforms first, then nodes, ways, relations - // This is recommended for Public Transport v2 routes: - // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes - var newMembers = PTv2members.concat( (groups.node || []), wayMembers, (groups.relation || []) ); - - return graph.replace(relation.update({members: newMembers})); - - - // `moveMember()` changes the `members` array in place by splicing - // the item with `.index = findIndex` to where it belongs, - // and marking the old position as "dead" with `.index = -1` - // - // j=5, k=0 jk - // segment 5 4 7 6 - // members 0 1 2 3 4 5 6 7 8 9 keep 5 in j+k - // - // j=5, k=1 j k - // segment 5 4 7 6 - // members 0 1 2 3 4 5 6 7 8 9 move 4 to j+k - // members 0 1 2 3 x 5 4 6 7 8 9 moved - // - // j=5, k=2 j k - // segment 5 4 7 6 - // members 0 1 2 3 x 5 4 6 7 8 9 move 7 to j+k - // members 0 1 2 3 x 5 4 7 6 x 8 9 moved - // - // j=5, k=3 j k - // segment 5 4 7 6 - // members 0 1 2 3 x 5 4 7 6 x 8 9 keep 6 in j+k - // - function moveMember(arr, findIndex, toIndex) { - for (var i = 0; i < arr.length; i++) { - if (arr[i].index === findIndex) { - break; - } - } + return graph; + }; + } - var item = clone(arr[i]); - arr[i].index = -1; // mark as dead - item.index = toIndex; - arr.splice(toIndex, 0, item); - } + // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as + function actionAddVertex(wayId, nodeId, index) { + return function(graph) { + return graph.replace(graph.entity(wayId).addNode(nodeId, index)); + }; + } + function actionChangeMember(relationId, member, memberIndex) { + return function(graph) { + return graph.replace(graph.entity(relationId).updateMember(member, memberIndex)); + }; + } - // This is the same as `Relation.indexedMembers`, - // Except we don't want to index all the members, only the ways - function withIndex(arr) { - var result = new Array(arr.length); - for (var i = 0; i < arr.length; i++) { - result[i] = arr[i]; - result[i].index = i; - } - return result; - } - } + function actionChangePreset(entityId, oldPreset, newPreset) { + return function(graph) { + var entity = graph.entity(entityId), + geometry = entity.geometry(graph), + tags = entity.tags; -} + if (oldPreset) tags = oldPreset.removeTags(tags, geometry); + if (newPreset) tags = newPreset.applyTags(tags, geometry); -function actionAddMidpoint(midpoint, node) { - return function(graph) { - graph = graph.replace(node.move(midpoint.loc)); + return graph.replace(entity.update({tags: tags})); + }; + } - var parents = intersection( - graph.parentWays(graph.entity(midpoint.edge[0])), - graph.parentWays(graph.entity(midpoint.edge[1]))); + function actionChangeTags(entityId, tags) { + return function(graph) { + var entity = graph.entity(entityId); + return graph.replace(entity.update({tags: tags})); + }; + } - parents.forEach(function(way) { - for (var i = 0; i < way.nodes.length - 1; i++) { - if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) { - graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1)); + function actionCircularize(wayId, projection, maxAngle) { + maxAngle = (maxAngle || 20) * Math.PI / 180; - // Add only one midpoint on doubled-back segments, - // turning them into self-intersections. - return; - } - } - }); - return graph; - }; -} + var action = function(graph, t) { + if (t === null || !isFinite(t)) t = 1; + t = Math.min(Math.max(+t, 0), 1); -// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as -function actionAddVertex(wayId, nodeId, index) { - return function(graph) { - return graph.replace(graph.entity(wayId).addNode(nodeId, index)); - }; -} + var way = graph.entity(wayId), + origNodes = {}; -function actionChangeMember(relationId, member, memberIndex) { - return function(graph) { - return graph.replace(graph.entity(relationId).updateMember(member, memberIndex)); - }; -} + graph.childNodes(way).forEach(function(node) { + if (!origNodes[node.id]) origNodes[node.id] = node; + }); -function actionChangePreset(entityId, oldPreset, newPreset) { - return function(graph) { - var entity = graph.entity(entityId), - geometry = entity.geometry(graph), - tags = entity.tags; + if (!way.isConvex(graph)) { + graph = action.makeConvex(graph); + } - if (oldPreset) tags = oldPreset.removeTags(tags, geometry); - if (newPreset) tags = newPreset.applyTags(tags, geometry); + var nodes = uniq(graph.childNodes(way)), + keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }), + points = nodes.map(function(n) { return projection(n.loc); }), + keyPoints = keyNodes.map(function(n) { return projection(n.loc); }), + centroid = (points.length === 2) ? geoVecInterp(points[0], points[1], 0.5) : d3_polygonCentroid(points), + radius = d3_median(points, function(p) { return geoVecLength(centroid, p); }), + sign = d3_polygonArea(points) > 0 ? 1 : -1, + ids; + + // we need atleast two key nodes for the algorithm to work + if (!keyNodes.length) { + keyNodes = [nodes[0]]; + keyPoints = [points[0]]; + } - return graph.replace(entity.update({tags: tags})); - }; -} + if (keyNodes.length === 1) { + var index = nodes.indexOf(keyNodes[0]), + oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length); -function actionChangeTags(entityId, tags) { - return function(graph) { - var entity = graph.entity(entityId); - return graph.replace(entity.update({tags: tags})); - }; -} + keyNodes.push(nodes[oppositeIndex]); + keyPoints.push(points[oppositeIndex]); + } -function actionCircularize(wayId, projection, maxAngle) { - maxAngle = (maxAngle || 20) * Math.PI / 180; + // key points and nodes are those connected to the ways, + // they are projected onto the circle, inbetween nodes are moved + // to constant intervals between key nodes, extra inbetween nodes are + // added if necessary. + for (var i = 0; i < keyPoints.length; i++) { + var nextKeyNodeIndex = (i + 1) % keyNodes.length, + startNode = keyNodes[i], + endNode = keyNodes[nextKeyNodeIndex], + startNodeIndex = nodes.indexOf(startNode), + endNodeIndex = nodes.indexOf(endNode), + numberNewPoints = -1, + indexRange = endNodeIndex - startNodeIndex, + nearNodes = {}, + inBetweenNodes = [], + startAngle, endAngle, totalAngle, eachAngle, + angle, loc, node, origNode, j; + + if (indexRange < 0) { + indexRange += nodes.length; + } + + // position this key node + var distance = geoVecLength(centroid, keyPoints[i]); + if (distance === 0) { distance = 1e-4; } + keyPoints[i] = [ + centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius, + centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius + ]; + loc = projection.invert(keyPoints[i]); + node = keyNodes[i]; + origNode = origNodes[node.id]; + node = node.move(geoVecInterp(origNode.loc, loc, t)); + graph = graph.replace(node); + + // figure out the between delta angle we want to match to + startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]); + endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]); + totalAngle = endAngle - startAngle; + + // detects looping around -pi/pi + if (totalAngle * sign > 0) { + totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle)); + } + + do { + numberNewPoints++; + eachAngle = totalAngle / (indexRange + numberNewPoints); + } while (Math.abs(eachAngle) > maxAngle); + + + // move existing nodes + for (j = 1; j < indexRange; j++) { + angle = startAngle + j * eachAngle; + loc = projection.invert([ + centroid[0] + Math.cos(angle) * radius, + centroid[1] + Math.sin(angle) * radius + ]); + + node = nodes[(j + startNodeIndex) % nodes.length]; + origNode = origNodes[node.id]; + nearNodes[node.id] = angle; + + node = node.move(geoVecInterp(origNode.loc, loc, t)); + graph = graph.replace(node); + } + + // add new inbetween nodes if necessary + for (j = 0; j < numberNewPoints; j++) { + angle = startAngle + (indexRange + j) * eachAngle; + loc = projection.invert([ + centroid[0] + Math.cos(angle) * radius, + centroid[1] + Math.sin(angle) * radius + ]); + + // choose a nearnode to use as the original + var min$$1 = Infinity; + for (var nodeId in nearNodes) { + var nearAngle = nearNodes[nodeId], + dist = Math.abs(nearAngle - angle); + if (dist < min$$1) { + dist = min$$1; + origNode = origNodes[nodeId]; + } + } + + node = osmNode({ loc: geoVecInterp(origNode.loc, loc, t) }); + graph = graph.replace(node); + + nodes.splice(endNodeIndex + j, 0, node); + inBetweenNodes.push(node.id); + } + + // Check for other ways that share these keyNodes.. + // If keyNodes are adjacent in both ways, + // we can add inBetween nodes to that shared way too.. + if (indexRange === 1 && inBetweenNodes.length) { + var startIndex1 = way.nodes.lastIndexOf(startNode.id), + endIndex1 = way.nodes.lastIndexOf(endNode.id), + wayDirection1 = (endIndex1 - startIndex1); + if (wayDirection1 < -1) { wayDirection1 = 1; } + + /* eslint-disable no-loop-func */ + forEach(without(graph.parentWays(keyNodes[i]), way), function(sharedWay) { + if (sharedWay.areAdjacent(startNode.id, endNode.id)) { + var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id), + endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id), + wayDirection2 = (endIndex2 - startIndex2), + insertAt = endIndex2; + if (wayDirection2 < -1) { wayDirection2 = 1; } + + if (wayDirection1 !== wayDirection2) { + inBetweenNodes.reverse(); + insertAt = startIndex2; + } + for (j = 0; j < inBetweenNodes.length; j++) { + sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j); + } + graph = graph.replace(sharedWay); + } + }); + /* eslint-enable no-loop-func */ + } + } - var action = function(graph, t) { - if (t === null || !isFinite(t)) t = 1; - t = Math.min(Math.max(+t, 0), 1); + // update the way to have all the new nodes + ids = nodes.map(function(n) { return n.id; }); + ids.push(ids[0]); - var way = graph.entity(wayId), - origNodes = {}; + way = way.update({nodes: ids}); + graph = graph.replace(way); - graph.childNodes(way).forEach(function(node) { - if (!origNodes[node.id]) origNodes[node.id] = node; - }); + return graph; + }; - if (!way.isConvex(graph)) { - graph = action.makeConvex(graph); - } - var nodes = uniq(graph.childNodes(way)), - keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }), - points = nodes.map(function(n) { return projection(n.loc); }), - keyPoints = keyNodes.map(function(n) { return projection(n.loc); }), - centroid = (points.length === 2) ? geoVecInterp(points[0], points[1], 0.5) : d3_polygonCentroid(points), - radius = d3_median(points, function(p) { return geoVecLength(centroid, p); }), - sign = d3_polygonArea(points) > 0 ? 1 : -1, - ids; - - // we need atleast two key nodes for the algorithm to work - if (!keyNodes.length) { - keyNodes = [nodes[0]]; - keyPoints = [points[0]]; - } + action.makeConvex = function(graph) { + var way = graph.entity(wayId), + nodes = uniq(graph.childNodes(way)), + points = nodes.map(function(n) { return projection(n.loc); }), + sign = d3_polygonArea(points) > 0 ? 1 : -1, + hull = d3_polygonHull(points); - if (keyNodes.length === 1) { - var index = nodes.indexOf(keyNodes[0]), - oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length); + // D3 convex hulls go counterclockwise.. + if (sign === -1) { + nodes.reverse(); + points.reverse(); + } - keyNodes.push(nodes[oppositeIndex]); - keyPoints.push(points[oppositeIndex]); - } + for (var i = 0; i < hull.length - 1; i++) { + var startIndex = points.indexOf(hull[i]), + endIndex = points.indexOf(hull[i+1]), + indexRange = (endIndex - startIndex); + + if (indexRange < 0) { + indexRange += nodes.length; + } + + // move interior nodes to the surface of the convex hull.. + for (var j = 1; j < indexRange; j++) { + var point = geoVecInterp(hull[i], hull[i+1], j / indexRange), + node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point)); + graph = graph.replace(node); + } + } + return graph; + }; - // key points and nodes are those connected to the ways, - // they are projected onto the circle, inbetween nodes are moved - // to constant intervals between key nodes, extra inbetween nodes are - // added if necessary. - for (var i = 0; i < keyPoints.length; i++) { - var nextKeyNodeIndex = (i + 1) % keyNodes.length, - startNode = keyNodes[i], - endNode = keyNodes[nextKeyNodeIndex], - startNodeIndex = nodes.indexOf(startNode), - endNodeIndex = nodes.indexOf(endNode), - numberNewPoints = -1, - indexRange = endNodeIndex - startNodeIndex, - nearNodes = {}, - inBetweenNodes = [], - startAngle, endAngle, totalAngle, eachAngle, - angle, loc, node, origNode, j; - - if (indexRange < 0) { - indexRange += nodes.length; - } - // position this key node - var distance = geoVecLength(centroid, keyPoints[i]); - if (distance === 0) { distance = 1e-4; } - keyPoints[i] = [ - centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius, - centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius - ]; - loc = projection.invert(keyPoints[i]); - node = keyNodes[i]; - origNode = origNodes[node.id]; - node = node.move(geoVecInterp(origNode.loc, loc, t)); - graph = graph.replace(node); - - // figure out the between delta angle we want to match to - startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]); - endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]); - totalAngle = endAngle - startAngle; - - // detects looping around -pi/pi - if (totalAngle * sign > 0) { - totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle)); - } + action.disabled = function(graph) { + if (!graph.entity(wayId).isClosed()) + return 'not_closed'; + }; - do { - numberNewPoints++; - eachAngle = totalAngle / (indexRange + numberNewPoints); - } while (Math.abs(eachAngle) > maxAngle); + action.transitionable = true; - // move existing nodes - for (j = 1; j < indexRange; j++) { - angle = startAngle + j * eachAngle; - loc = projection.invert([ - centroid[0] + Math.cos(angle) * radius, - centroid[1] + Math.sin(angle) * radius - ]); - node = nodes[(j + startNodeIndex) % nodes.length]; - origNode = origNodes[node.id]; - nearNodes[node.id] = angle; + return action; + } - node = node.move(geoVecInterp(origNode.loc, loc, t)); - graph = graph.replace(node); - } + // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as + function actionDeleteWay(wayId) { - // add new inbetween nodes if necessary - for (j = 0; j < numberNewPoints; j++) { - angle = startAngle + (indexRange + j) * eachAngle; - loc = projection.invert([ - centroid[0] + Math.cos(angle) * radius, - centroid[1] + Math.sin(angle) * radius - ]); - - // choose a nearnode to use as the original - var min$$1 = Infinity; - for (var nodeId in nearNodes) { - var nearAngle = nearNodes[nodeId], - dist = Math.abs(nearAngle - angle); - if (dist < min$$1) { - dist = min$$1; - origNode = origNodes[nodeId]; - } - } - - node = osmNode({ loc: geoVecInterp(origNode.loc, loc, t) }); - graph = graph.replace(node); - - nodes.splice(endNodeIndex + j, 0, node); - inBetweenNodes.push(node.id); - } - // Check for other ways that share these keyNodes.. - // If keyNodes are adjacent in both ways, - // we can add inBetween nodes to that shared way too.. - if (indexRange === 1 && inBetweenNodes.length) { - var startIndex1 = way.nodes.lastIndexOf(startNode.id), - endIndex1 = way.nodes.lastIndexOf(endNode.id), - wayDirection1 = (endIndex1 - startIndex1); - if (wayDirection1 < -1) { wayDirection1 = 1; } - - /* eslint-disable no-loop-func */ - forEach(without(graph.parentWays(keyNodes[i]), way), function(sharedWay) { - if (sharedWay.areAdjacent(startNode.id, endNode.id)) { - var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id), - endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id), - wayDirection2 = (endIndex2 - startIndex2), - insertAt = endIndex2; - if (wayDirection2 < -1) { wayDirection2 = 1; } - - if (wayDirection1 !== wayDirection2) { - inBetweenNodes.reverse(); - insertAt = startIndex2; - } - for (j = 0; j < inBetweenNodes.length; j++) { - sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j); - } - graph = graph.replace(sharedWay); - } - }); - /* eslint-enable no-loop-func */ - } + function canDeleteNode(node, graph) { + return !graph.parentWays(node).length && + !graph.parentRelations(node).length && + !node.hasInterestingTags(); + } - } - // update the way to have all the new nodes - ids = nodes.map(function(n) { return n.id; }); - ids.push(ids[0]); + var action = function(graph) { + var way = graph.entity(wayId); - way = way.update({nodes: ids}); - graph = graph.replace(way); + graph.parentRelations(way) + .forEach(function(parent) { + parent = parent.removeMembersWithID(wayId); + graph = graph.replace(parent); - return graph; - }; + if (parent.isDegenerate()) { + graph = actionDeleteRelation(parent.id)(graph); + } + }); + uniq(way.nodes).forEach(function(nodeId) { + graph = graph.replace(way.removeNode(nodeId)); - action.makeConvex = function(graph) { - var way = graph.entity(wayId), - nodes = uniq(graph.childNodes(way)), - points = nodes.map(function(n) { return projection(n.loc); }), - sign = d3_polygonArea(points) > 0 ? 1 : -1, - hull = d3_polygonHull(points); + var node = graph.entity(nodeId); + if (canDeleteNode(node, graph)) { + graph = graph.remove(node); + } + }); - // D3 convex hulls go counterclockwise.. - if (sign === -1) { - nodes.reverse(); - points.reverse(); - } + return graph.remove(way); + }; - for (var i = 0; i < hull.length - 1; i++) { - var startIndex = points.indexOf(hull[i]), - endIndex = points.indexOf(hull[i+1]), - indexRange = (endIndex - startIndex); - if (indexRange < 0) { - indexRange += nodes.length; - } + return action; + } - // move interior nodes to the surface of the convex hull.. - for (var j = 1; j < indexRange; j++) { - var point = geoVecInterp(hull[i], hull[i+1], j / indexRange), - node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point)); - graph = graph.replace(node); - } - } - return graph; - }; + function actionDeleteMultiple(ids) { + var actions = { + way: actionDeleteWay, + node: actionDeleteNode, + relation: actionDeleteRelation + }; - action.disabled = function(graph) { - if (!graph.entity(wayId).isClosed()) - return 'not_closed'; - }; + var action = function(graph) { + ids.forEach(function(id) { + if (graph.hasEntity(id)) { // It may have been deleted aready. + graph = actions[graph.entity(id).type](id)(graph); + } + }); + return graph; + }; - action.transitionable = true; + return action; + } - return action; -} + // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as + function actionDeleteRelation(relationId) { -// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as -function actionDeleteWay(wayId) { + function canDeleteEntity(entity, graph) { + return !graph.parentWays(entity).length && + !graph.parentRelations(entity).length && + !entity.hasInterestingTags(); + } - function canDeleteNode(node, graph) { - return !graph.parentWays(node).length && - !graph.parentRelations(node).length && - !node.hasInterestingTags(); - } + var action = function(graph) { + var relation = graph.entity(relationId); - var action = function(graph) { - var way = graph.entity(wayId); + graph.parentRelations(relation) + .forEach(function(parent) { + parent = parent.removeMembersWithID(relationId); + graph = graph.replace(parent); - graph.parentRelations(way) - .forEach(function(parent) { - parent = parent.removeMembersWithID(wayId); - graph = graph.replace(parent); + if (parent.isDegenerate()) { + graph = actionDeleteRelation(parent.id)(graph); + } + }); - if (parent.isDegenerate()) { - graph = actionDeleteRelation(parent.id)(graph); - } - }); + uniq(map$3(relation.members, 'id')).forEach(function(memberId) { + graph = graph.replace(relation.removeMembersWithID(memberId)); - uniq(way.nodes).forEach(function(nodeId) { - graph = graph.replace(way.removeNode(nodeId)); + var entity = graph.entity(memberId); + if (canDeleteEntity(entity, graph)) { + graph = actionDeleteMultiple([memberId])(graph); + } + }); - var node = graph.entity(nodeId); - if (canDeleteNode(node, graph)) { - graph = graph.remove(node); - } - }); + return graph.remove(relation); + }; - return graph.remove(way); - }; + return action; + } - return action; -} + // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as + function actionDeleteNode(nodeId) { + var action = function(graph) { + var node = graph.entity(nodeId); -function actionDeleteMultiple(ids) { - var actions = { - way: actionDeleteWay, - node: actionDeleteNode, - relation: actionDeleteRelation - }; + graph.parentWays(node) + .forEach(function(parent) { + parent = parent.removeNode(nodeId); + graph = graph.replace(parent); + if (parent.isDegenerate()) { + graph = actionDeleteWay(parent.id)(graph); + } + }); - var action = function(graph) { - ids.forEach(function(id) { - if (graph.hasEntity(id)) { // It may have been deleted aready. - graph = actions[graph.entity(id).type](id)(graph); - } - }); + graph.parentRelations(node) + .forEach(function(parent) { + parent = parent.removeMembersWithID(nodeId); + graph = graph.replace(parent); + + if (parent.isDegenerate()) { + graph = actionDeleteRelation(parent.id)(graph); + } + }); + + return graph.remove(node); + }; - return graph; - }; + return action; + } - return action; -} + // Connect the ways at the given nodes. + // + // First choose a node to be the survivor, with preference given + // to an existing (not new) node. + // + // Tags and relation memberships of of non-surviving nodes are merged + // to the survivor. + // + // This is the inverse of `iD.actionDisconnect`. + // + // Reference: + // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as + // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java + // + function actionConnect(nodeIDs) { + var action = function(graph) { + var survivor; + var node; + var parents; + var i, j; + + // Choose a survivor node, prefer an existing (not new) node - #4974 + for (i = 0; i < nodeIDs.length; i++) { + survivor = graph.entity(nodeIDs[i]); + if (survivor.version) break; // found one + } -// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as -function actionDeleteRelation(relationId) { + // Replace all non-surviving nodes with the survivor and merge tags. + for (i = 0; i < nodeIDs.length; i++) { + node = graph.entity(nodeIDs[i]); + if (node.id === survivor.id) continue; + + parents = graph.parentWays(node); + for (j = 0; j < parents.length; j++) { + if (!parents[j].areAdjacent(node.id, survivor.id)) { + graph = graph.replace(parents[j].replaceNode(node.id, survivor.id)); + } + } + + parents = graph.parentRelations(node); + for (j = 0; j < parents.length; j++) { + graph = graph.replace(parents[j].replaceMember(node, survivor)); + } + + survivor = survivor.mergeTags(node.tags); + graph = actionDeleteNode(node.id)(graph); + } + graph = graph.replace(survivor); - function canDeleteEntity(entity, graph) { - return !graph.parentWays(entity).length && - !graph.parentRelations(entity).length && - !entity.hasInterestingTags(); - } + return graph; + }; - var action = function(graph) { - var relation = graph.entity(relationId); + action.disabled = function(graph) { + var seen = {}; + var restrictionIDs = []; + var survivor; + var node, way; + var relations, relation, role; + var i, j, k; - graph.parentRelations(relation) - .forEach(function(parent) { - parent = parent.removeMembersWithID(relationId); - graph = graph.replace(parent); + // Choose a survivor node, prefer an existing (not new) node - #4974 + for (i = 0; i < nodeIDs.length; i++) { + survivor = graph.entity(nodeIDs[i]); + if (survivor.version) break; // found one + } - if (parent.isDegenerate()) { - graph = actionDeleteRelation(parent.id)(graph); - } - }); + // 1. disable if the nodes being connected have conflicting relation roles + for (i = 0; i < nodeIDs.length; i++) { + node = graph.entity(nodeIDs[i]); + relations = graph.parentRelations(node); + + for (j = 0; j < relations.length; j++) { + relation = relations[j]; + role = relation.memberById(node.id).role || ''; + + // if this node is a via node in a restriction, remember for later + if (relation.isValidRestriction()) { + restrictionIDs.push(relation.id); + } + + if (seen[relation.id] !== undefined && seen[relation.id] !== role) { + return 'relation'; + } else { + seen[relation.id] = role; + } + } + } - uniq(map$3(relation.members, 'id')).forEach(function(memberId) { - graph = graph.replace(relation.removeMembersWithID(memberId)); + // gather restrictions for parent ways + for (i = 0; i < nodeIDs.length; i++) { + node = graph.entity(nodeIDs[i]); + + var parents = graph.parentWays(node); + for (j = 0; j < parents.length; j++) { + var parent = parents[j]; + relations = graph.parentRelations(parent); + + for (k = 0; k < relations.length; k++) { + relation = relations[k]; + if (relation.isValidRestriction()) { + restrictionIDs.push(relation.id); + } + } + } + } - var entity = graph.entity(memberId); - if (canDeleteEntity(entity, graph)) { - graph = actionDeleteMultiple([memberId])(graph); - } - }); - return graph.remove(relation); - }; + // test restrictions + restrictionIDs = uniq(restrictionIDs); + for (i = 0; i < restrictionIDs.length; i++) { + relation = graph.entity(restrictionIDs[i]); + if (!relation.isComplete(graph)) continue; + + var memberWays = relation.members + .filter(function(m) { return m.type === 'way'; }) + .map(function(m) { return graph.entity(m.id); }); + + memberWays = uniq(memberWays); + var f = relation.memberByRole('from'); + var t = relation.memberByRole('to'); + var isUturn = (f.id === t.id); + + // 2a. disable if connection would damage a restriction + // (a key node is a node at the junction of ways) + var nodes = { from: [], via: [], to: [], keyfrom: [], keyto: [] }; + for (j = 0; j < relation.members.length; j++) { + collectNodes(relation.members[j], nodes); + } + + nodes.keyfrom = uniq(nodes.keyfrom.filter(hasDuplicates)); + nodes.keyto = uniq(nodes.keyto.filter(hasDuplicates)); + + var filter = keyNodeFilter(nodes.keyfrom, nodes.keyto); + nodes.from = nodes.from.filter(filter); + nodes.via = nodes.via.filter(filter); + nodes.to = nodes.to.filter(filter); + + var connectFrom = false; + var connectVia = false; + var connectTo = false; + var connectKeyFrom = false; + var connectKeyTo = false; + + for (j = 0; j < nodeIDs.length; j++) { + var n = nodeIDs[j]; + if (nodes.from.indexOf(n) !== -1) { connectFrom = true; } + if (nodes.via.indexOf(n) !== -1) { connectVia = true; } + if (nodes.to.indexOf(n) !== -1) { connectTo = true; } + if (nodes.keyfrom.indexOf(n) !== -1) { connectKeyFrom = true; } + if (nodes.keyto.indexOf(n) !== -1) { connectKeyTo = true; } + } + if (connectFrom && connectTo && !isUturn) { return 'restriction'; } + if (connectFrom && connectVia) { return 'restriction'; } + if (connectTo && connectVia) { return 'restriction'; } + + // connecting to a key node - + // if both nodes are on a member way (i.e. part of the turn restriction), + // the connecting node must be adjacent to the key node. + if (connectKeyFrom || connectKeyTo) { + if (nodeIDs.length !== 2) { return 'restriction'; } + + var n0 = null; + var n1 = null; + for (j = 0; j < memberWays.length; j++) { + way = memberWays[j]; + if (way.contains(nodeIDs[0])) { n0 = nodeIDs[0]; } + if (way.contains(nodeIDs[1])) { n1 = nodeIDs[1]; } + } + + if (n0 && n1) { // both nodes are part of the restriction + var ok = false; + for (j = 0; j < memberWays.length; j++) { + way = memberWays[j]; + if (way.areAdjacent(n0, n1)) { + ok = true; + break; + } + } + if (!ok) { + return 'restriction'; + } + } + } + + // 2b. disable if nodes being connected will destroy a member way in a restriction + // (to test, make a copy and try actually connecting the nodes) + for (j = 0; j < memberWays.length; j++) { + way = memberWays[j].update({}); // make copy + for (k = 0; k < nodeIDs.length; k++) { + if (nodeIDs[k] === survivor.id) continue; + + if (way.areAdjacent(nodeIDs[k], survivor.id)) { + way = way.removeNode(nodeIDs[k]); + } else { + way = way.replaceNode(nodeIDs[k], survivor.id); + } + } + if (way.isDegenerate()) { + return 'restriction'; + } + } + } + return false; - return action; -} -// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as -function actionDeleteNode(nodeId) { - var action = function(graph) { - var node = graph.entity(nodeId); + // if a key node appears multiple times (indexOf !== lastIndexOf) it's a FROM-VIA or TO-VIA junction + function hasDuplicates(n, i, arr) { + return arr.indexOf(n) !== arr.lastIndexOf(n); + } - graph.parentWays(node) - .forEach(function(parent) { - parent = parent.removeNode(nodeId); - graph = graph.replace(parent); + function keyNodeFilter(froms, tos) { + return function(n) { + return froms.indexOf(n) === -1 && tos.indexOf(n) === -1; + }; + } - if (parent.isDegenerate()) { - graph = actionDeleteWay(parent.id)(graph); - } - }); + function collectNodes(member, collection) { + var entity = graph.hasEntity(member.id); + if (!entity) return; + + var role = member.role || ''; + if (!collection[role]) { + collection[role] = []; + } + + if (member.type === 'node') { + collection[role].push(member.id); + if (role === 'via') { + collection.keyfrom.push(member.id); + collection.keyto.push(member.id); + } + + } else if (member.type === 'way') { + collection[role].push.apply(collection[role], entity.nodes); + if (role === 'from' || role === 'via') { + collection.keyfrom.push(entity.first()); + collection.keyfrom.push(entity.last()); + } + if (role === 'to' || role === 'via') { + collection.keyto.push(entity.first()); + collection.keyto.push(entity.last()); + } + } + } + }; - graph.parentRelations(node) - .forEach(function(parent) { - parent = parent.removeMembersWithID(nodeId); - graph = graph.replace(parent); - if (parent.isDegenerate()) { - graph = actionDeleteRelation(parent.id)(graph); - } - }); + return action; + } - return graph.remove(node); - }; + function actionCopyEntities(ids, fromGraph) { + var copies = {}; - return action; -} - -// Connect the ways at the given nodes. -// -// The last node will survive. All other nodes will be replaced with -// the surviving node in parent ways, and then removed. -// -// Tags and relation memberships of of non-surviving nodes are merged -// to the survivor. -// -// This is the inverse of `iD.actionDisconnect`. -// -// Reference: -// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as -// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java -// -function actionConnect(nodeIds) { - return function(graph) { - var last = nodeIds[nodeIds.length - 1]; - var survivor = graph.entity(last); - - for (var i = 0; i < nodeIds.length - 1; i++) { - var node = graph.entity(nodeIds[i]); - - /* eslint-disable no-loop-func */ - graph.parentWays(node).forEach(function(parent) { - if (!parent.areAdjacent(node.id, survivor.id)) { - graph = graph.replace(parent.replaceNode(node.id, survivor.id)); - } - }); + var action = function(graph) { + ids.forEach(function(id) { + fromGraph.entity(id).copy(fromGraph, copies); + }); - graph.parentRelations(node).forEach(function(parent) { - graph = graph.replace(parent.replaceMember(node, survivor)); - }); - /* eslint-enable no-loop-func */ + for (var id in copies) { + graph = graph.replace(copies[id]); + } - survivor = survivor.mergeTags(node.tags); - graph = actionDeleteNode(node.id)(graph); - } + return graph; + }; - graph = graph.replace(survivor); - return graph; - }; -} + action.copies = function() { + return copies; + }; -function actionCopyEntities(ids, fromGraph) { - var copies = {}; + return action; + } - var action = function(graph) { - ids.forEach(function(id) { - fromGraph.entity(id).copy(fromGraph, copies); - }); + function actionDeleteMember(relationId, memberIndex) { + return function(graph) { + var relation = graph.entity(relationId) + .removeMember(memberIndex); - for (var id in copies) { - graph = graph.replace(copies[id]); - } + graph = graph.replace(relation); - return graph; - }; + if (relation.isDegenerate()) + graph = actionDeleteRelation(relation.id)(graph); + return graph; + }; + } - action.copies = function() { - return copies; - }; + function actionDeprecateTags(entityId) { + return function(graph) { + var entity = graph.entity(entityId), + newtags = clone(entity.tags), + change = false, + rule; - return action; -} + // This handles dataDeprecated tags with a single condition + for (var i = 0; i < dataDeprecated.length; i++) { -function actionDeleteMember(relationId, memberIndex) { - return function(graph) { - var relation = graph.entity(relationId) - .removeMember(memberIndex); + rule = dataDeprecated[i]; + var match = toPairs(rule.old)[0], + replacements = rule.replace ? toPairs(rule.replace) : null; - graph = graph.replace(relation); + if (entity.tags[match[0]] && match[1] === '*') { - if (relation.isDegenerate()) - graph = actionDeleteRelation(relation.id)(graph); + var value = entity.tags[match[0]]; + if (replacements && !newtags[replacements[0][0]]) { + newtags[replacements[0][0]] = value; + } + delete newtags[match[0]]; + change = true; - return graph; - }; -} + } else if (entity.tags[match[0]] === match[1]) { + newtags = assign({}, rule.replace || {}, omit(newtags, match[0])); + change = true; + } + } -function actionDeprecateTags(entityId) { + if (change) { + return graph.replace(entity.update({tags: newtags})); + } else { + return graph; + } + }; + } - return function(graph) { - var entity = graph.entity(entityId), - newtags = clone(entity.tags), - change = false, - rule; + function actionDiscardTags(difference) { + + return function(graph) { + function discardTags(entity) { + var tags = {}; + var keys = Object.keys(entity.tags); + var discarded = false; + + for (var i = 0; i < keys.length; i++) { + var k = keys[i]; + if (dataDiscarded[k] || !entity.tags[k]) { + discarded = true; + } else { + tags[k] = entity.tags[k]; + } + } + + if (discarded) { + graph = graph.replace(entity.update({ tags: tags })); + } + } - // This handles dataDeprecated tags with a single condition - for (var i = 0; i < dataDeprecated.length; i++) { + difference.modified().forEach(discardTags); + difference.created().forEach(discardTags); - rule = dataDeprecated[i]; - var match = toPairs(rule.old)[0], - replacements = rule.replace ? toPairs(rule.replace) : null; + return graph; + }; + } - if (entity.tags[match[0]] && match[1] === '*') { + // Disconect the ways at the given node. + // + // Optionally, disconnect only the given ways. + // + // For testing convenience, accepts an ID to assign to the (first) new node. + // Normally, this will be undefined and the way will automatically + // be assigned a new ID. + // + // This is the inverse of `iD.actionConnect`. + // + // Reference: + // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as + // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java + // + function actionDisconnect(nodeId, newNodeId) { + var wayIds; + + + var action = function(graph) { + var node = graph.entity(nodeId); + var connections = action.connections(graph); + + connections.forEach(function(connection) { + var way = graph.entity(connection.wayID); + var newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags}); + + graph = graph.replace(newNode); + if (connection.index === 0 && way.isArea()) { + // replace shared node with shared node.. + graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id)); + } else if (way.isClosed() && connection.index === way.nodes.length - 1) { + // replace closing node with new new node.. + graph = graph.replace(way.unclose().addNode(newNode.id)); + } else { + // replace shared node with multiple new nodes.. + graph = graph.replace(way.updateNode(newNode.id, connection.index)); + } + }); - var value = entity.tags[match[0]]; - if (replacements && !newtags[replacements[0][0]]) { - newtags[replacements[0][0]] = value; - } - delete newtags[match[0]]; - change = true; + return graph; + }; - } else if (entity.tags[match[0]] === match[1]) { - newtags = assign({}, rule.replace || {}, omit(newtags, match[0])); - change = true; - } - } - if (change) { - return graph.replace(entity.update({tags: newtags})); - } else { - return graph; - } - }; -} - -function actionDiscardTags(difference) { - - return function(graph) { - function discardTags(entity) { - var tags = {}; - var keys = Object.keys(entity.tags); - var discarded = false; - - for (var i = 0; i < keys.length; i++) { - var k = keys[i]; - if (dataDiscarded[k] || !entity.tags[k]) { - discarded = true; - } else { - tags[k] = entity.tags[k]; - } - } + action.connections = function(graph) { + var candidates = []; + var keeping = false; + var parentWays = graph.parentWays(graph.entity(nodeId)); + + parentWays.forEach(function(way) { + if (wayIds && wayIds.indexOf(way.id) === -1) { + keeping = true; + return; + } + if (way.isArea() && (way.nodes[0] === nodeId)) { + candidates.push({ wayID: way.id, index: 0 }); + } else { + way.nodes.forEach(function(waynode, index) { + if (waynode === nodeId) { + candidates.push({ wayID: way.id, index: index }); + } + }); + } + }); - if (discarded) { - graph = graph.replace(entity.update({ tags: tags })); - } - } + return keeping ? candidates : candidates.slice(1); + }; - difference.modified().forEach(discardTags); - difference.created().forEach(discardTags); - return graph; - }; -} - -// Disconect the ways at the given node. -// -// Optionally, disconnect only the given ways. -// -// For testing convenience, accepts an ID to assign to the (first) new node. -// Normally, this will be undefined and the way will automatically -// be assigned a new ID. -// -// This is the inverse of `iD.actionConnect`. -// -// Reference: -// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as -// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java -// -function actionDisconnect(nodeId, newNodeId) { - var wayIds; - - - var action = function(graph) { - var node = graph.entity(nodeId), - connections = action.connections(graph); - - connections.forEach(function(connection) { - var way = graph.entity(connection.wayID), - newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags}); - - graph = graph.replace(newNode); - if (connection.index === 0 && way.isArea()) { - // replace shared node with shared node.. - graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id)); - } else if (way.isClosed() && connection.index === way.nodes.length - 1) { - // replace closing node with new new node.. - graph = graph.replace(way.unclose().addNode(newNode.id)); - } else { - // replace shared node with multiple new nodes.. - graph = graph.replace(way.updateNode(newNode.id, connection.index)); - } - }); + action.disabled = function(graph) { + var connections = action.connections(graph); + if (connections.length === 0 || (wayIds && wayIds.length !== connections.length)) + return 'not_connected'; - return graph; - }; + var parentWays = graph.parentWays(graph.entity(nodeId)); + var seenRelationIds = {}; + var sharedRelation; + parentWays.forEach(function(way) { + if (wayIds && wayIds.indexOf(way.id) === -1) + return; - action.connections = function(graph) { - var candidates = [], - keeping = false, - parentWays = graph.parentWays(graph.entity(nodeId)); + var relations = graph.parentRelations(way); + relations.forEach(function(relation) { + if (relation.id in seenRelationIds) { + sharedRelation = relation; + } else { + seenRelationIds[relation.id] = true; + } + }); + }); - parentWays.forEach(function(way) { - if (wayIds && wayIds.indexOf(way.id) === -1) { - keeping = true; - return; - } - if (way.isArea() && (way.nodes[0] === nodeId)) { - candidates.push({ wayID: way.id, index: 0 }); - } else { - way.nodes.forEach(function(waynode, index) { - if (waynode === nodeId) { - candidates.push({ wayID: way.id, index: index }); - } - }); - } - }); + if (sharedRelation) + return 'relation'; + }; - return keeping ? candidates : candidates.slice(1); - }; + action.limitWays = function(_) { + if (!arguments.length) return wayIds; + wayIds = _; + return action; + }; - action.disabled = function(graph) { - var connections = action.connections(graph); - if (connections.length === 0 || (wayIds && wayIds.length !== connections.length)) - return 'not_connected'; - var parentWays = graph.parentWays(graph.entity(nodeId)), - seenRelationIds = {}, - sharedRelation; + return action; + } - parentWays.forEach(function(way) { - if (wayIds && wayIds.indexOf(way.id) === -1) - return; + // Join ways at the end node they share. + // + // This is the inverse of `iD.actionSplit`. + // + // Reference: + // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as + // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java + // + function actionJoin(ids) { - var relations = graph.parentRelations(way); - relations.forEach(function(relation) { - if (relation.id in seenRelationIds) { - sharedRelation = relation; - } else { - seenRelationIds[relation.id] = true; - } - }); - }); + function groupEntitiesByGeometry(graph) { + var entities = ids.map(function(id) { return graph.entity(id); }); + return assignIn({line: []}, groupBy(entities, function(entity) { return entity.geometry(graph); })); + } - if (sharedRelation) - return 'relation'; - }; + var action = function(graph) { + var ways = ids.map(graph.entity, graph); + var survivorID = ways[0].id; - action.limitWays = function(_) { - if (!arguments.length) return wayIds; - wayIds = _; - return action; - }; + // Prefer to keep an existing way. + for (var i = 0; i < ways.length; i++) { + if (!ways[i].isNew()) { + survivorID = ways[i].id; + break; + } + } + var sequences = osmJoinWays(ways, graph); + var joined = sequences[0]; - return action; -} + // We might need to reverse some of these ways before joining them. #4688 + // `joined.actions` property will contain any actions we need to apply. + graph = sequences.actions.reduce(function(g, action) { return action(g); }, graph); -// Join ways at the end node they share. -// -// This is the inverse of `iD.actionSplit`. -// -// Reference: -// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as -// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java -// -function actionJoin(ids) { + var survivor = graph.entity(survivorID); + survivor = survivor.update({ nodes: joined.nodes.map(function(n) { return n.id; }) }); + graph = graph.replace(survivor); - function groupEntitiesByGeometry(graph) { - var entities = ids.map(function(id) { return graph.entity(id); }); - return assignIn({line: []}, groupBy(entities, function(entity) { return entity.geometry(graph); })); - } + joined.forEach(function(way) { + if (way.id === survivorID) return; + graph.parentRelations(way).forEach(function(parent) { + graph = graph.replace(parent.replaceMember(way, survivor)); + }); - var action = function(graph) { - var ways = ids.map(graph.entity, graph); - var survivorID = ways[0].id; + survivor = survivor.mergeTags(way.tags); - // Prefer to keep an existing way. - for (var i = 0; i < ways.length; i++) { - if (!ways[i].isNew()) { - survivorID = ways[i].id; - break; - } - } + graph = graph.replace(survivor); + graph = actionDeleteWay(way.id)(graph); + }); - var sequences = osmJoinWays(ways, graph); - var joined = sequences[0]; + return graph; + }; - // We might need to reverse some of these ways before joining them. #4688 - // `joined.actions` property will contain any actions we need to apply. - graph = sequences.actions.reduce(function(g, action) { return action(g); }, graph); - var survivor = graph.entity(survivorID); - survivor = survivor.update({ nodes: joined.nodes.map(function(n) { return n.id; }) }); - graph = graph.replace(survivor); + action.disabled = function(graph) { + var geometries = groupEntitiesByGeometry(graph); + if (ids.length < 2 || ids.length !== geometries.line.length) + return 'not_eligible'; + + var joined = osmJoinWays(ids.map(graph.entity, graph), graph); + if (joined.length > 1) + return 'not_adjacent'; + + var nodeIds = joined[0].nodes.map(function(n) { return n.id; }).slice(1, -1); + var relation; + var tags = {}; + var conflicting = false; + + joined[0].forEach(function(way) { + var parents = graph.parentRelations(way); + parents.forEach(function(parent) { + if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; })) + relation = parent; + }); + + for (var k in way.tags) { + if (!(k in tags)) { + tags[k] = way.tags[k]; + } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) { + conflicting = true; + } + } + }); - joined.forEach(function(way) { - if (way.id === survivorID) return; + if (relation) + return 'restriction'; - graph.parentRelations(way).forEach(function(parent) { - graph = graph.replace(parent.replaceMember(way, survivor)); - }); + if (conflicting) + return 'conflicting_tags'; + }; - survivor = survivor.mergeTags(way.tags); - graph = graph.replace(survivor); - graph = actionDeleteWay(way.id)(graph); - }); + return action; + } - return graph; - }; + function actionMerge(ids) { + function groupEntitiesByGeometry(graph) { + var entities = ids.map(function(id) { return graph.entity(id); }); + return assignIn({point: [], area: [], line: [], relation: []}, + groupBy(entities, function(entity) { return entity.geometry(graph); })); + } - action.disabled = function(graph) { - var geometries = groupEntitiesByGeometry(graph); - if (ids.length < 2 || ids.length !== geometries.line.length) - return 'not_eligible'; - var joined = osmJoinWays(ids.map(graph.entity, graph), graph); - if (joined.length > 1) - return 'not_adjacent'; + var action = function(graph) { + var geometries = groupEntitiesByGeometry(graph), + target = geometries.area[0] || geometries.line[0], + points = geometries.point; + + points.forEach(function(point) { + target = target.mergeTags(point.tags); + graph = graph.replace(target); + + graph.parentRelations(point).forEach(function(parent) { + graph = graph.replace(parent.replaceMember(point, target)); + }); + + var nodes = uniq(graph.childNodes(target)), + removeNode = point; + + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + if (graph.parentWays(node).length > 1 || + graph.parentRelations(node).length || + node.hasInterestingTags()) { + continue; + } + + // Found an uninteresting child node on the target way. + // Move orig point into its place to preserve point's history. #3683 + graph = graph.replace(point.update({ tags: {}, loc: node.loc })); + target = target.replaceNode(node.id, point.id); + graph = graph.replace(target); + removeNode = node; + break; + } + + graph = graph.remove(removeNode); + }); - var nodeIds = joined[0].nodes.map(function(n) { return n.id; }).slice(1, -1); - var relation; - var tags = {}; - var conflicting = false; + return graph; + }; - joined[0].forEach(function(way) { - var parents = graph.parentRelations(way); - parents.forEach(function(parent) { - if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; })) - relation = parent; - }); - for (var k in way.tags) { - if (!(k in tags)) { - tags[k] = way.tags[k]; - } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) { - conflicting = true; - } - } - }); + action.disabled = function(graph) { + var geometries = groupEntitiesByGeometry(graph); + if (geometries.point.length === 0 || + (geometries.area.length + geometries.line.length) !== 1 || + geometries.relation.length !== 0) + return 'not_eligible'; + }; - if (relation) - return 'restriction'; - if (conflicting) - return 'conflicting_tags'; - }; + return action; + } + // `actionMergeNodes` is just a combination of: + // + // 1. move all the nodes to a common location + // 2. `actionConnect` them + + function actionMergeNodes(nodeIDs) { + + // If there is a single "interesting" node, use that as the location. + // Otherwise return the average location of all the nodes. + function chooseLoc(graph) { + if (!nodeIDs.length) return null; + var sum = [0,0]; + var interestingCount = 0; + var interestingLoc; + + for (var i = 0; i < nodeIDs.length; i++) { + var node = graph.entity(nodeIDs[i]); + if (node.hasInterestingTags()) { + interestingLoc = (++interestingCount === 1) ? node.loc : null; + } + sum = geoVecAdd(sum, node.loc); + } - return action; -} + return interestingLoc || geoVecScale(sum, 1 / nodeIDs.length); + } -function actionMerge(ids) { - function groupEntitiesByGeometry(graph) { - var entities = ids.map(function(id) { return graph.entity(id); }); - return assignIn({point: [], area: [], line: [], relation: []}, - groupBy(entities, function(entity) { return entity.geometry(graph); })); - } + var action = function(graph) { + if (nodeIDs.length < 2) return graph; + var toLoc = chooseLoc(graph); + for (var i = 0; i < nodeIDs.length; i++) { + var node = graph.entity(nodeIDs[i]); + graph = graph.replace(node.move(toLoc)); + } - var action = function(graph) { - var geometries = groupEntitiesByGeometry(graph), - target = geometries.area[0] || geometries.line[0], - points = geometries.point; + return actionConnect(nodeIDs)(graph); + }; - points.forEach(function(point) { - target = target.mergeTags(point.tags); - graph = graph.replace(target); - graph.parentRelations(point).forEach(function(parent) { - graph = graph.replace(parent.replaceMember(point, target)); - }); + action.disabled = function(graph) { + if (nodeIDs.length < 2) return 'not_eligible'; - var nodes = uniq(graph.childNodes(target)), - removeNode = point; - - for (var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - if (graph.parentWays(node).length > 1 || - graph.parentRelations(node).length || - node.hasInterestingTags()) { - continue; - } - - // Found an uninteresting child node on the target way. - // Move orig point into its place to preserve point's history. #3683 - graph = graph.replace(point.update({ tags: {}, loc: node.loc })); - target = target.replaceNode(node.id, point.id); - graph = graph.replace(target); - removeNode = node; - break; - } + for (var i = 0; i < nodeIDs.length; i++) { + var entity = graph.entity(nodeIDs[i]); + if (entity.type !== 'node') return 'not_eligible'; + } - graph = graph.remove(removeNode); - }); + return actionConnect(nodeIDs).disabled(graph); + }; - return graph; - }; + return action; + } + function actionMergePolygon(ids, newRelationId) { + + function groupEntities(graph) { + var entities = ids.map(function (id) { return graph.entity(id); }); + return assignIn({ + closedWay: [], + multipolygon: [], + other: [] + }, groupBy(entities, function(entity) { + if (entity.type === 'way' && entity.isClosed()) { + return 'closedWay'; + } else if (entity.type === 'relation' && entity.isMultipolygon()) { + return 'multipolygon'; + } else { + return 'other'; + } + })); + } - action.disabled = function(graph) { - var geometries = groupEntitiesByGeometry(graph); - if (geometries.point.length === 0 || - (geometries.area.length + geometries.line.length) !== 1 || - geometries.relation.length !== 0) - return 'not_eligible'; - }; + var action = function(graph) { + var entities = groupEntities(graph); + + // An array representing all the polygons that are part of the multipolygon. + // + // Each element is itself an array of objects with an id property, and has a + // locs property which is an array of the locations forming the polygon. + var polygons = entities.multipolygon.reduce(function(polygons, m) { + return polygons.concat(osmJoinWays(m.members, graph)); + }, []).concat(entities.closedWay.map(function(d) { + var member = [{id: d.id}]; + member.nodes = graph.childNodes(d); + return member; + })); + + // contained is an array of arrays of boolean values, + // where contained[j][k] is true iff the jth way is + // contained by the kth way. + var contained = polygons.map(function(w, i) { + return polygons.map(function(d, n) { + if (i === n) return null; + return geoPolygonContainsPolygon( + map$3(d.nodes, 'loc'), + map$3(w.nodes, 'loc')); + }); + }); - return action; -} - -function actionMergePolygon(ids, newRelationId) { - - function groupEntities(graph) { - var entities = ids.map(function (id) { return graph.entity(id); }); - return assignIn({ - closedWay: [], - multipolygon: [], - other: [] - }, groupBy(entities, function(entity) { - if (entity.type === 'way' && entity.isClosed()) { - return 'closedWay'; - } else if (entity.type === 'relation' && entity.isMultipolygon()) { - return 'multipolygon'; - } else { - return 'other'; - } - })); - } - - - var action = function(graph) { - var entities = groupEntities(graph); - - // An array representing all the polygons that are part of the multipolygon. - // - // Each element is itself an array of objects with an id property, and has a - // locs property which is an array of the locations forming the polygon. - var polygons = entities.multipolygon.reduce(function(polygons, m) { - return polygons.concat(osmJoinWays(m.members, graph)); - }, []).concat(entities.closedWay.map(function(d) { - var member = [{id: d.id}]; - member.nodes = graph.childNodes(d); - return member; - })); - - // contained is an array of arrays of boolean values, - // where contained[j][k] is true iff the jth way is - // contained by the kth way. - var contained = polygons.map(function(w, i) { - return polygons.map(function(d, n) { - if (i === n) return null; - return geoPolygonContainsPolygon( - map$3(d.nodes, 'loc'), - map$3(w.nodes, 'loc')); - }); - }); + // Sort all polygons as either outer or inner ways + var members = [], + outer = true; - // Sort all polygons as either outer or inner ways - var members = [], - outer = true; + while (polygons.length) { + extractUncontained(polygons); + polygons = polygons.filter(isContained); + contained = contained.filter(isContained).map(filterContained); + } - while (polygons.length) { - extractUncontained(polygons); - polygons = polygons.filter(isContained); - contained = contained.filter(isContained).map(filterContained); - } + function isContained(d, i) { + return some(contained[i]); + } - function isContained(d, i) { - return some(contained[i]); - } + function filterContained(d) { + return d.filter(isContained); + } - function filterContained(d) { - return d.filter(isContained); - } + function extractUncontained(polygons) { + polygons.forEach(function(d, i) { + if (!isContained(d, i)) { + d.forEach(function(member) { + members.push({ + type: 'way', + id: member.id, + role: outer ? 'outer' : 'inner' + }); + }); + } + }); + outer = !outer; + } - function extractUncontained(polygons) { - polygons.forEach(function(d, i) { - if (!isContained(d, i)) { - d.forEach(function(member) { - members.push({ - type: 'way', - id: member.id, - role: outer ? 'outer' : 'inner' - }); - }); - } - }); - outer = !outer; - } + // Move all tags to one relation + var relation = entities.multipolygon[0] || + osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }}); - // Move all tags to one relation - var relation = entities.multipolygon[0] || - osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }}); + entities.multipolygon.slice(1).forEach(function(m) { + relation = relation.mergeTags(m.tags); + graph = graph.remove(m); + }); - entities.multipolygon.slice(1).forEach(function(m) { - relation = relation.mergeTags(m.tags); - graph = graph.remove(m); - }); + entities.closedWay.forEach(function(way) { + function isThisOuter(m) { + return m.id === way.id && m.role !== 'inner'; + } + if (members.some(isThisOuter)) { + relation = relation.mergeTags(way.tags); + graph = graph.replace(way.update({ tags: {} })); + } + }); - entities.closedWay.forEach(function(way) { - function isThisOuter(m) { - return m.id === way.id && m.role !== 'inner'; - } - if (members.some(isThisOuter)) { - relation = relation.mergeTags(way.tags); - graph = graph.replace(way.update({ tags: {} })); - } - }); + return graph.replace(relation.update({ + members: members, + tags: omit(relation.tags, 'area') + })); + }; - return graph.replace(relation.update({ - members: members, - tags: omit(relation.tags, 'area') - })); - }; + action.disabled = function(graph) { + var entities = groupEntities(graph); + if (entities.other.length > 0 || + entities.closedWay.length + entities.multipolygon.length < 2) + return 'not_eligible'; + if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); })) + return 'incomplete_relation'; + }; - action.disabled = function(graph) { - var entities = groupEntities(graph); - if (entities.other.length > 0 || - entities.closedWay.length + entities.multipolygon.length < 2) - return 'not_eligible'; - if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); })) - return 'incomplete_relation'; - }; + return action; + } - return action; -} - -// Text diff algorithm following Hunt and McIlroy 1976. -// J. W. Hunt and M. D. McIlroy, An algorithm for differential file -// comparison, Bell Telephone Laboratories CSTR #41 (1976) -// http://www.cs.dartmouth.edu/~doug/ -// -// Expects two arrays of strings. -function LCS(file1, file2) { - var equivalenceClasses; - var file2indices; - var newCandidate; - var candidates; - var line; - var c, i, j, jX, r, s; - - equivalenceClasses = {}; - for (j = 0; j < file2.length; j++) { - line = file2[j]; - if (equivalenceClasses[line]) { - equivalenceClasses[line].push(j); - } else { - equivalenceClasses[line] = [j]; + // Text diff algorithm following Hunt and McIlroy 1976. + // J. W. Hunt and M. D. McIlroy, An algorithm for differential file + // comparison, Bell Telephone Laboratories CSTR #41 (1976) + // http://www.cs.dartmouth.edu/~doug/ + // + // Expects two arrays of strings. + function LCS(file1, file2) { + var equivalenceClasses; + var file2indices; + var newCandidate; + var candidates; + var line; + var c, i, j, jX, r, s; + + equivalenceClasses = {}; + for (j = 0; j < file2.length; j++) { + line = file2[j]; + if (equivalenceClasses[line]) { + equivalenceClasses[line].push(j); + } else { + equivalenceClasses[line] = [j]; + } } - } - candidates = [ - { file1index: -1, file2index: -1, chain: null } - ]; + candidates = [ + { file1index: -1, file2index: -1, chain: null } + ]; - for (i = 0; i < file1.length; i++) { - line = file1[i]; - file2indices = equivalenceClasses[line] || []; + for (i = 0; i < file1.length; i++) { + line = file1[i]; + file2indices = equivalenceClasses[line] || []; - r = 0; - c = candidates[0]; + r = 0; + c = candidates[0]; - for (jX = 0; jX < file2indices.length; jX++) { - j = file2indices[jX]; + for (jX = 0; jX < file2indices.length; jX++) { + j = file2indices[jX]; - for (s = r; s < candidates.length; s++) { - if ((candidates[s].file2index < j) && ((s === candidates.length - 1) || (candidates[s + 1].file2index > j))) { - break; + for (s = r; s < candidates.length; s++) { + if ((candidates[s].file2index < j) && ((s === candidates.length - 1) || (candidates[s + 1].file2index > j))) { + break; + } } - } - if (s < candidates.length) { - newCandidate = { file1index: i, file2index: j, chain: candidates[s] }; - if (r === candidates.length) { - candidates.push(c); - } else { - candidates[r] = c; - } - r = s + 1; - c = newCandidate; - if (r === candidates.length) { - break; // no point in examining further (j)s + if (s < candidates.length) { + newCandidate = { file1index: i, file2index: j, chain: candidates[s] }; + if (r === candidates.length) { + candidates.push(c); + } else { + candidates[r] = c; + } + r = s + 1; + c = newCandidate; + if (r === candidates.length) { + break; // no point in examining further (j)s + } } } + + candidates[r] = c; } - candidates[r] = c; - } + // At this point, we know the LCS: it's in the reverse of the + // linked-list through .chain of candidates[candidates.length - 1]. - // At this point, we know the LCS: it's in the reverse of the - // linked-list through .chain of candidates[candidates.length - 1]. + return candidates[candidates.length - 1]; + } - return candidates[candidates.length - 1]; -} + // We apply the LCS to give a simple representation of the + // offsets and lengths of mismatched chunks in the input + // files. This is used by diff3MergeIndices below. + function diffIndices(file1, file2) { + var result = []; + var tail1 = file1.length; + var tail2 = file2.length; -// We apply the LCS to give a simple representation of the -// offsets and lengths of mismatched chunks in the input -// files. This is used by diff3MergeIndices below. -function diffIndices(file1, file2) { - var result = []; - var tail1 = file1.length; - var tail2 = file2.length; + for (var candidate = LCS(file1, file2); + candidate !== null; + candidate = candidate.chain) + { + var mismatchLength1 = tail1 - candidate.file1index - 1; + var mismatchLength2 = tail2 - candidate.file2index - 1; + tail1 = candidate.file1index; + tail2 = candidate.file2index; - for (var candidate = LCS(file1, file2); - candidate !== null; - candidate = candidate.chain) - { - var mismatchLength1 = tail1 - candidate.file1index - 1; - var mismatchLength2 = tail2 - candidate.file2index - 1; - tail1 = candidate.file1index; - tail2 = candidate.file2index; - - if (mismatchLength1 || mismatchLength2) { - result.push({ - file1: [tail1 + 1, mismatchLength1], - file2: [tail2 + 1, mismatchLength2] - }); + if (mismatchLength1 || mismatchLength2) { + result.push({ + file1: [tail1 + 1, mismatchLength1], + file2: [tail2 + 1, mismatchLength2] + }); + } } + + result.reverse(); + return result; } - result.reverse(); - return result; -} - - -// Given three files, A, O, and B, where both A and B are -// independently derived from O, returns a fairly complicated -// internal representation of merge decisions it's taken. The -// interested reader may wish to consult -// -// Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. -// 'A Formal Investigation of ' In Arvind and Prasad, -// editors, Foundations of Software Technology and Theoretical -// Computer Science (FSTTCS), December 2007. -// -// (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf) -function diff3MergeIndices(a, o, b) { - var i; - var m1 = diffIndices(o, a); - var m2 = diffIndices(o, b); - - var hunks = []; - function addHunk(h, side) { - hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]); - } - for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); } - for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); } - hunks.sort(function (x, y) { return x[0] - y[0]; }); - - var result = []; - var commonOffset = 0; - function copyCommon(targetOffset) { - if (targetOffset > commonOffset) { - result.push([1, commonOffset, targetOffset - commonOffset]); - commonOffset = targetOffset; - } - } - - for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) { - var firstHunkIndex = hunkIndex; - var hunk = hunks[hunkIndex]; - var regionLhs = hunk[0]; - var regionRhs = regionLhs + hunk[2]; - while (hunkIndex < hunks.length - 1) { - var maybeOverlapping = hunks[hunkIndex + 1]; - var maybeLhs = maybeOverlapping[0]; - if (maybeLhs > regionRhs) { - break; + + // Given three files, A, O, and B, where both A and B are + // independently derived from O, returns a fairly complicated + // internal representation of merge decisions it's taken. The + // interested reader may wish to consult + // + // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. + // 'A Formal Investigation of ' In Arvind and Prasad, + // editors, Foundations of Software Technology and Theoretical + // Computer Science (FSTTCS), December 2007. + // + // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf) + function diff3MergeIndices(a, o, b) { + var i; + var m1 = diffIndices(o, a); + var m2 = diffIndices(o, b); + + var hunks = []; + function addHunk(h, side) { + hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]); + } + for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); } + for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); } + hunks.sort(function (x, y) { return x[0] - y[0]; }); + + var result = []; + var commonOffset = 0; + function copyCommon(targetOffset) { + if (targetOffset > commonOffset) { + result.push([1, commonOffset, targetOffset - commonOffset]); + commonOffset = targetOffset; } - regionRhs = Math.max(regionRhs, maybeLhs + maybeOverlapping[2]); - hunkIndex++; } - copyCommon(regionLhs); - if (firstHunkIndex === hunkIndex) { - // The 'overlap' was only one hunk long, meaning that - // there's no conflict here. Either a and o were the - // same, or b and o were the same. - if (hunk[4] > 0) { - result.push([hunk[1], hunk[3], hunk[4]]); - } - } else { - // A proper conflict. Determine the extents of the - // regions involved from a, o and b. Effectively merge - // all the hunks on the left into one giant hunk, and - // do the same for the right; then, correct for skew - // in the regions of o that each side changed, and - // report appropriate spans for the three sides. - var regions = { - 0: [a.length, -1, o.length, -1], - 2: [b.length, -1, o.length, -1] - }; - for (i = firstHunkIndex; i <= hunkIndex; i++) { - hunk = hunks[i]; - var side = hunk[1]; - var r = regions[side]; - var oLhs = hunk[0]; - var oRhs = oLhs + hunk[2]; - var abLhs = hunk[3]; - var abRhs = abLhs + hunk[4]; - r[0] = Math.min(abLhs, r[0]); - r[1] = Math.max(abRhs, r[1]); - r[2] = Math.min(oLhs, r[2]); - r[3] = Math.max(oRhs, r[3]); - } - var aLhs = regions[0][0] + (regionLhs - regions[0][2]); - var aRhs = regions[0][1] + (regionRhs - regions[0][3]); - var bLhs = regions[2][0] + (regionLhs - regions[2][2]); - var bRhs = regions[2][1] + (regionRhs - regions[2][3]); - result.push([-1, - aLhs, aRhs - aLhs, - regionLhs, regionRhs - regionLhs, - bLhs, bRhs - bLhs]); - } - commonOffset = regionRhs; - } - - copyCommon(o.length); - return result; -} - - -// Applies the output of diff3MergeIndices to actually -// construct the merged file; the returned result alternates -// between 'ok' and 'conflict' blocks. -function diff3Merge(a, o, b, excludeFalseConflicts) { - var result = []; - var files = [a, o, b]; - var indices = diff3MergeIndices(a, o, b); - - var okLines = []; - function flushOk() { - if (okLines.length) { - result.push({ok: okLines}); - } - okLines = []; - } - function pushOk(xs) { - for (var j = 0; j < xs.length; j++) { - okLines.push(xs[j]); - } - } - - function isTrueConflict(rec) { - if (rec[2] !== rec[6]) return true; - var aoff = rec[1]; - var boff = rec[5]; - for (var j = 0; j < rec[2]; j++) { - if (a[j + aoff] !== b[j + boff]) { - return true; + for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) { + var firstHunkIndex = hunkIndex; + var hunk = hunks[hunkIndex]; + var regionLhs = hunk[0]; + var regionRhs = regionLhs + hunk[2]; + while (hunkIndex < hunks.length - 1) { + var maybeOverlapping = hunks[hunkIndex + 1]; + var maybeLhs = maybeOverlapping[0]; + if (maybeLhs > regionRhs) { + break; + } + regionRhs = Math.max(regionRhs, maybeLhs + maybeOverlapping[2]); + hunkIndex++; } - } - return false; - } - for (var i = 0; i < indices.length; i++) { - var x = indices[i]; - var side = x[0]; - if (side === -1) { - if (excludeFalseConflicts && !isTrueConflict(x)) { - pushOk(files[0].slice(x[1], x[1] + x[2])); + copyCommon(regionLhs); + if (firstHunkIndex === hunkIndex) { + // The 'overlap' was only one hunk long, meaning that + // there's no conflict here. Either a and o were the + // same, or b and o were the same. + if (hunk[4] > 0) { + result.push([hunk[1], hunk[3], hunk[4]]); + } } else { - flushOk(); - result.push({ - conflict: { - a: a.slice(x[1], x[1] + x[2]), - aIndex: x[1], - o: o.slice(x[3], x[3] + x[4]), - oIndex: x[3], - b: b.slice(x[5], x[5] + x[6]), - bIndex: x[5] - } - }); + // A proper conflict. Determine the extents of the + // regions involved from a, o and b. Effectively merge + // all the hunks on the left into one giant hunk, and + // do the same for the right; then, correct for skew + // in the regions of o that each side changed, and + // report appropriate spans for the three sides. + var regions = { + 0: [a.length, -1, o.length, -1], + 2: [b.length, -1, o.length, -1] + }; + for (i = firstHunkIndex; i <= hunkIndex; i++) { + hunk = hunks[i]; + var side = hunk[1]; + var r = regions[side]; + var oLhs = hunk[0]; + var oRhs = oLhs + hunk[2]; + var abLhs = hunk[3]; + var abRhs = abLhs + hunk[4]; + r[0] = Math.min(abLhs, r[0]); + r[1] = Math.max(abRhs, r[1]); + r[2] = Math.min(oLhs, r[2]); + r[3] = Math.max(oRhs, r[3]); + } + var aLhs = regions[0][0] + (regionLhs - regions[0][2]); + var aRhs = regions[0][1] + (regionRhs - regions[0][3]); + var bLhs = regions[2][0] + (regionLhs - regions[2][2]); + var bRhs = regions[2][1] + (regionRhs - regions[2][3]); + result.push([-1, + aLhs, aRhs - aLhs, + regionLhs, regionRhs - regionLhs, + bLhs, bRhs - bLhs]); } - } else { - pushOk(files[side].slice(x[1], x[1] + x[2])); + commonOffset = regionRhs; } - } - flushOk(); - return result; -} + copyCommon(o.length); + return result; + } -function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) { - var _option = 'safe'; // 'safe', 'force_local', 'force_remote' - var _conflicts = []; + // Applies the output of diff3MergeIndices to actually + // construct the merged file; the returned result alternates + // between 'ok' and 'conflict' blocks. + function diff3Merge(a, o, b, excludeFalseConflicts) { + var result = []; + var files = [a, o, b]; + var indices = diff3MergeIndices(a, o, b); - function user(d) { - return isFunction(formatUser) ? formatUser(d) : d; + var okLines = []; + function flushOk() { + if (okLines.length) { + result.push({ok: okLines}); + } + okLines = []; + } + function pushOk(xs) { + for (var j = 0; j < xs.length; j++) { + okLines.push(xs[j]); + } } - - function mergeLocation(remote, target) { - function pointEqual(a, b) { - var epsilon = 1e-6; - return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon); + function isTrueConflict(rec) { + if (rec[2] !== rec[6]) return true; + var aoff = rec[1]; + var boff = rec[5]; + for (var j = 0; j < rec[2]; j++) { + if (a[j + aoff] !== b[j + boff]) { + return true; } + } + return false; + } - if (_option === 'force_local' || pointEqual(target.loc, remote.loc)) { - return target; - } - if (_option === 'force_remote') { - return target.update({loc: remote.loc}); + for (var i = 0; i < indices.length; i++) { + var x = indices[i]; + var side = x[0]; + if (side === -1) { + if (excludeFalseConflicts && !isTrueConflict(x)) { + pushOk(files[0].slice(x[1], x[1] + x[2])); + } else { + flushOk(); + result.push({ + conflict: { + a: a.slice(x[1], x[1] + x[2]), + aIndex: x[1], + o: o.slice(x[3], x[3] + x[4]), + oIndex: x[3], + b: b.slice(x[5], x[5] + x[6]), + bIndex: x[5] + } + }); } - - _conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) })); - return target; + } else { + pushOk(files[side].slice(x[1], x[1] + x[2])); + } } + flushOk(); + return result; + } - function mergeNodes(base, remote, target) { - if (_option === 'force_local' || isEqual(target.nodes, remote.nodes)) { - return target; - } - if (_option === 'force_remote') { - return target.update({nodes: remote.nodes}); - } + function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) { + var _option = 'safe'; // 'safe', 'force_local', 'force_remote' + var _conflicts = []; - var ccount = _conflicts.length; - var o = base.nodes || []; - var a = target.nodes || []; - var b = remote.nodes || []; - var nodes = []; - var hunks = diff3Merge(a, o, b, true); - - for (var i = 0; i < hunks.length; i++) { - var hunk = hunks[i]; - if (hunk.ok) { - nodes.push.apply(nodes, hunk.ok); - } else { - // for all conflicts, we can assume c.a !== c.b - // because `diff3Merge` called with `true` option to exclude false conflicts.. - var c = hunk.conflict; - if (isEqual(c.o, c.a)) { // only changed remotely - nodes.push.apply(nodes, c.b); - } else if (isEqual(c.o, c.b)) { // only changed locally - nodes.push.apply(nodes, c.a); - } else { // changed both locally and remotely - _conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) })); - break; - } - } - } - return (_conflicts.length === ccount) ? target.update({nodes: nodes}) : target; - } + function user(d) { + return isFunction(formatUser) ? formatUser(d) : d; + } - function mergeChildren(targetWay, children, updates, graph) { - function isUsed(node, targetWay) { - var parentWays = map$3(graph.parentWays(node), 'id'); - return node.hasInterestingTags() || - without(parentWays, targetWay.id).length > 0 || - graph.parentRelations(node).length > 0; - } + function mergeLocation(remote, target) { + function pointEqual(a, b) { + var epsilon = 1e-6; + return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon); + } - var ccount = _conflicts.length; + if (_option === 'force_local' || pointEqual(target.loc, remote.loc)) { + return target; + } + if (_option === 'force_remote') { + return target.update({loc: remote.loc}); + } - for (var i = 0; i < children.length; i++) { - var id = children[i]; - var node = graph.hasEntity(id); + _conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) })); + return target; + } - // remove unused childNodes.. - if (targetWay.nodes.indexOf(id) === -1) { - if (node && !isUsed(node, targetWay)) { - updates.removeIds.push(id); - } - continue; - } - // restore used childNodes.. - var local = localGraph.hasEntity(id); - var remote = remoteGraph.hasEntity(id); - var target; - - if (_option === 'force_remote' && remote && remote.visible) { - updates.replacements.push(remote); - - } else if (_option === 'force_local' && local) { - target = osmEntity$$1(local); - if (remote) { - target = target.update({ version: remote.version }); - } - updates.replacements.push(target); - - } else if (_option === 'safe' && local && remote && local.version !== remote.version) { - target = osmEntity$$1(local, { version: remote.version }); - if (remote.visible) { - target = mergeLocation(remote, target); - } else { - _conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) })); - } - - if (_conflicts.length !== ccount) break; - updates.replacements.push(target); - } - } + function mergeNodes(base, remote, target) { + if (_option === 'force_local' || isEqual(target.nodes, remote.nodes)) { + return target; + } + if (_option === 'force_remote') { + return target.update({nodes: remote.nodes}); + } - return targetWay; - } + var ccount = _conflicts.length; + var o = base.nodes || []; + var a = target.nodes || []; + var b = remote.nodes || []; + var nodes = []; + var hunks = diff3Merge(a, o, b, true); + + for (var i = 0; i < hunks.length; i++) { + var hunk = hunks[i]; + if (hunk.ok) { + nodes.push.apply(nodes, hunk.ok); + } else { + // for all conflicts, we can assume c.a !== c.b + // because `diff3Merge` called with `true` option to exclude false conflicts.. + var c = hunk.conflict; + if (isEqual(c.o, c.a)) { // only changed remotely + nodes.push.apply(nodes, c.b); + } else if (isEqual(c.o, c.b)) { // only changed locally + nodes.push.apply(nodes, c.a); + } else { // changed both locally and remotely + _conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) })); + break; + } + } + } + return (_conflicts.length === ccount) ? target.update({nodes: nodes}) : target; + } - function updateChildren(updates, graph) { - for (var i = 0; i < updates.replacements.length; i++) { - graph = graph.replace(updates.replacements[i]); - } - if (updates.removeIds.length) { - graph = actionDeleteMultiple(updates.removeIds)(graph); - } - return graph; - } + function mergeChildren(targetWay, children, updates, graph) { + function isUsed(node, targetWay) { + var parentWays = map$3(graph.parentWays(node), 'id'); + return node.hasInterestingTags() || + without(parentWays, targetWay.id).length > 0 || + graph.parentRelations(node).length > 0; + } - function mergeMembers(remote, target) { - if (_option === 'force_local' || isEqual(target.members, remote.members)) { - return target; - } - if (_option === 'force_remote') { - return target.update({members: remote.members}); - } + var ccount = _conflicts.length; + + for (var i = 0; i < children.length; i++) { + var id = children[i]; + var node = graph.hasEntity(id); + + // remove unused childNodes.. + if (targetWay.nodes.indexOf(id) === -1) { + if (node && !isUsed(node, targetWay)) { + updates.removeIds.push(id); + } + continue; + } + + // restore used childNodes.. + var local = localGraph.hasEntity(id); + var remote = remoteGraph.hasEntity(id); + var target; + + if (_option === 'force_remote' && remote && remote.visible) { + updates.replacements.push(remote); + + } else if (_option === 'force_local' && local) { + target = osmEntity$$1(local); + if (remote) { + target = target.update({ version: remote.version }); + } + updates.replacements.push(target); + + } else if (_option === 'safe' && local && remote && local.version !== remote.version) { + target = osmEntity$$1(local, { version: remote.version }); + if (remote.visible) { + target = mergeLocation(remote, target); + } else { + _conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) })); + } + + if (_conflicts.length !== ccount) break; + updates.replacements.push(target); + } + } - _conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) })); - return target; - } + return targetWay; + } - function mergeTags(base, remote, target) { - function ignoreKey(k) { - return dataDiscarded[k]; - } + function updateChildren(updates, graph) { + for (var i = 0; i < updates.replacements.length; i++) { + graph = graph.replace(updates.replacements[i]); + } + if (updates.removeIds.length) { + graph = actionDeleteMultiple(updates.removeIds)(graph); + } + return graph; + } - if (_option === 'force_local' || isEqual(target.tags, remote.tags)) { - return target; - } - if (_option === 'force_remote') { - return target.update({tags: remote.tags}); - } - var ccount = _conflicts.length; - var o = base.tags || {}; - var a = target.tags || {}; - var b = remote.tags || {}; - var keys = reject(union(keys$1(o), keys$1(a), keys$1(b)), ignoreKey); - var tags = clone(a); - var changed = false; - - for (var i = 0; i < keys.length; i++) { - var k = keys[i]; - - if (o[k] !== b[k] && a[k] !== b[k]) { // changed remotely.. - if (o[k] !== a[k]) { // changed locally.. - _conflicts.push(t('merge_remote_changes.conflict.tags', - { tag: k, local: a[k], remote: b[k], user: user(remote.user) })); - - } else { // unchanged locally, accept remote change.. - if (b.hasOwnProperty(k)) { - tags[k] = b[k]; - } else { - delete tags[k]; - } - changed = true; - } - } - } + function mergeMembers(remote, target) { + if (_option === 'force_local' || isEqual(target.members, remote.members)) { + return target; + } + if (_option === 'force_remote') { + return target.update({members: remote.members}); + } - return (changed && _conflicts.length === ccount) ? target.update({tags: tags}) : target; - } + _conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) })); + return target; + } - // `graph.base()` is the common ancestor of the two graphs. - // `localGraph` contains user's edits up to saving - // `remoteGraph` contains remote edits to modified nodes - // `graph` must be a descendent of `localGraph` and may include - // some conflict resolution actions performed on it. - // - // --- ... --- `localGraph` -- ... -- `graph` - // / - // `graph.base()` --- ... --- `remoteGraph` - // - var action = function(graph) { - var updates = { replacements: [], removeIds: [] }; - var base = graph.base().entities[id]; - var local = localGraph.entity(id); - var remote = remoteGraph.entity(id); - var target = osmEntity$$1(local, { version: remote.version }); - - // delete/undelete - if (!remote.visible) { - if (_option === 'force_remote') { - return actionDeleteMultiple([id])(graph); - - } else if (_option === 'force_local') { - if (target.type === 'way') { - target = mergeChildren(target, uniq(local.nodes), updates, graph); - graph = updateChildren(updates, graph); - } - return graph.replace(target); + function mergeTags(base, remote, target) { + function ignoreKey(k) { + return dataDiscarded[k]; + } - } else { - _conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) })); - return graph; // do nothing - } - } + if (_option === 'force_local' || isEqual(target.tags, remote.tags)) { + return target; + } + if (_option === 'force_remote') { + return target.update({tags: remote.tags}); + } + + var ccount = _conflicts.length; + var o = base.tags || {}; + var a = target.tags || {}; + var b = remote.tags || {}; + var keys = reject(union(keys$1(o), keys$1(a), keys$1(b)), ignoreKey); + var tags = clone(a); + var changed = false; + + for (var i = 0; i < keys.length; i++) { + var k = keys[i]; + + if (o[k] !== b[k] && a[k] !== b[k]) { // changed remotely.. + if (o[k] !== a[k]) { // changed locally.. + _conflicts.push(t('merge_remote_changes.conflict.tags', + { tag: k, local: a[k], remote: b[k], user: user(remote.user) })); + + } else { // unchanged locally, accept remote change.. + if (b.hasOwnProperty(k)) { + tags[k] = b[k]; + } else { + delete tags[k]; + } + changed = true; + } + } + } - // merge - if (target.type === 'node') { - target = mergeLocation(remote, target); + return (changed && _conflicts.length === ccount) ? target.update({tags: tags}) : target; + } - } else if (target.type === 'way') { - // pull in any child nodes that may not be present locally.. - graph.rebase(remoteGraph.childNodes(remote), [graph], false); - target = mergeNodes(base, remote, target); - target = mergeChildren(target, union(local.nodes, remote.nodes), updates, graph); - } else if (target.type === 'relation') { - target = mergeMembers(remote, target); - } + // `graph.base()` is the common ancestor of the two graphs. + // `localGraph` contains user's edits up to saving + // `remoteGraph` contains remote edits to modified nodes + // `graph` must be a descendent of `localGraph` and may include + // some conflict resolution actions performed on it. + // + // --- ... --- `localGraph` -- ... -- `graph` + // / + // `graph.base()` --- ... --- `remoteGraph` + // + var action = function(graph) { + var updates = { replacements: [], removeIds: [] }; + var base = graph.base().entities[id]; + var local = localGraph.entity(id); + var remote = remoteGraph.entity(id); + var target = osmEntity$$1(local, { version: remote.version }); + + // delete/undelete + if (!remote.visible) { + if (_option === 'force_remote') { + return actionDeleteMultiple([id])(graph); + + } else if (_option === 'force_local') { + if (target.type === 'way') { + target = mergeChildren(target, uniq(local.nodes), updates, graph); + graph = updateChildren(updates, graph); + } + return graph.replace(target); + + } else { + _conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) })); + return graph; // do nothing + } + } - target = mergeTags(base, remote, target); + // merge + if (target.type === 'node') { + target = mergeLocation(remote, target); - if (!_conflicts.length) { - graph = updateChildren(updates, graph).replace(target); - } + } else if (target.type === 'way') { + // pull in any child nodes that may not be present locally.. + graph.rebase(remoteGraph.childNodes(remote), [graph], false); + target = mergeNodes(base, remote, target); + target = mergeChildren(target, union(local.nodes, remote.nodes), updates, graph); - return graph; - }; + } else if (target.type === 'relation') { + target = mergeMembers(remote, target); + } + target = mergeTags(base, remote, target); - action.withOption = function(opt) { - _option = opt; - return action; - }; + if (!_conflicts.length) { + graph = updateChildren(updates, graph).replace(target); + } + return graph; + }; - action.conflicts = function() { - return _conflicts; - }; + action.withOption = function(opt) { + _option = opt; + return action; + }; - return action; -} -// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java -// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as -function actionMove(moveIds, tryDelta, projection, cache) { - var _delta = tryDelta; + action.conflicts = function() { + return _conflicts; + }; - function setupCache(graph) { - function canMove(nodeId) { - // Allow movement of any node that is in the selectedIDs list.. - if (moveIds.indexOf(nodeId) !== -1) return true; - // Allow movement of a vertex where 2 ways meet.. - var parents = map$3(graph.parentWays(graph.entity(nodeId)), 'id'); - if (parents.length < 3) return true; + return action; + } - // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too.. - var parentsMoving = every(parents, function(id) { return cache.moving[id]; }); - if (!parentsMoving) delete cache.moving[nodeId]; + // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java + // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as + function actionMove(moveIds, tryDelta, projection, cache) { + var _delta = tryDelta; - return parentsMoving; - } + function setupCache(graph) { + function canMove(nodeId) { + // Allow movement of any node that is in the selectedIDs list.. + if (moveIds.indexOf(nodeId) !== -1) return true; - function cacheEntities(ids) { - for (var i = 0; i < ids.length; i++) { - var id = ids[i]; - if (cache.moving[id]) continue; - cache.moving[id] = true; - - var entity = graph.hasEntity(id); - if (!entity) continue; - - if (entity.type === 'node') { - cache.nodes.push(id); - cache.startLoc[id] = entity.loc; - } else if (entity.type === 'way') { - cache.ways.push(id); - cacheEntities(entity.nodes); - } else { - cacheEntities(entity.members.map(function(member) { - return member.id; - })); - } - } - } + // Allow movement of a vertex where 2 ways meet.. + var parents = map$3(graph.parentWays(graph.entity(nodeId)), 'id'); + if (parents.length < 3) return true; - function cacheIntersections(ids) { - function isEndpoint(way, id) { - return !way.isClosed() && !!way.affix(id); - } + // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too.. + var parentsMoving = every(parents, function(id) { return cache.moving[id]; }); + if (!parentsMoving) delete cache.moving[nodeId]; - for (var i = 0; i < ids.length; i++) { - var id = ids[i]; - - // consider only intersections with 1 moved and 1 unmoved way. - var childNodes = graph.childNodes(graph.entity(id)); - for (var j = 0; j < childNodes.length; j++) { - var node = childNodes[j]; - var parents = graph.parentWays(node); - if (parents.length !== 2) continue; - - var moved = graph.entity(id); - var unmoved = null; - for (var k = 0; k < parents.length; k++) { - var way = parents[k]; - if (!cache.moving[way.id]) { - unmoved = way; - break; - } - } - if (!unmoved) continue; - - // exclude ways that are overly connected.. - if (intersection(moved.nodes, unmoved.nodes).length > 2) continue; - if (moved.isArea() || unmoved.isArea()) continue; - - cache.intersections.push({ - nodeId: node.id, - movedId: moved.id, - unmovedId: unmoved.id, - movedIsEP: isEndpoint(moved, node.id), - unmovedIsEP: isEndpoint(unmoved, node.id) - }); - } - } - } + return parentsMoving; + } + function cacheEntities(ids) { + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + if (cache.moving[id]) continue; + cache.moving[id] = true; + + var entity = graph.hasEntity(id); + if (!entity) continue; + + if (entity.type === 'node') { + cache.nodes.push(id); + cache.startLoc[id] = entity.loc; + } else if (entity.type === 'way') { + cache.ways.push(id); + cacheEntities(entity.nodes); + } else { + cacheEntities(entity.members.map(function(member) { + return member.id; + })); + } + } + } - if (!cache) { - cache = {}; - } - if (!cache.ok) { - cache.moving = {}; - cache.intersections = []; - cache.replacedVertex = {}; - cache.startLoc = {}; - cache.nodes = []; - cache.ways = []; - - cacheEntities(moveIds); - cacheIntersections(cache.ways); - cache.nodes = filter(cache.nodes, canMove); - - cache.ok = true; - } - } + function cacheIntersections(ids) { + function isEndpoint(way, id) { + return !way.isClosed() && !!way.affix(id); + } + + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + + // consider only intersections with 1 moved and 1 unmoved way. + var childNodes = graph.childNodes(graph.entity(id)); + for (var j = 0; j < childNodes.length; j++) { + var node = childNodes[j]; + var parents = graph.parentWays(node); + if (parents.length !== 2) continue; + + var moved = graph.entity(id); + var unmoved = null; + for (var k = 0; k < parents.length; k++) { + var way = parents[k]; + if (!cache.moving[way.id]) { + unmoved = way; + break; + } + } + if (!unmoved) continue; + + // exclude ways that are overly connected.. + if (intersection(moved.nodes, unmoved.nodes).length > 2) continue; + if (moved.isArea() || unmoved.isArea()) continue; + + cache.intersections.push({ + nodeId: node.id, + movedId: moved.id, + unmovedId: unmoved.id, + movedIsEP: isEndpoint(moved, node.id), + unmovedIsEP: isEndpoint(unmoved, node.id) + }); + } + } + } - // Place a vertex where the moved vertex used to be, to preserve way shape.. - // - // Start: - // b ---- e - // / \ - // / \ - // / \ - // a c - // - // * node '*' added to preserve shape - // / \ - // / b ---- e way `b,e` moved here: - // / \ - // a c - // - // - function replaceMovedVertex(nodeId, wayId, graph, delta) { - var way = graph.entity(wayId); - var moved = graph.entity(nodeId); - var movedIndex = way.nodes.indexOf(nodeId); - var len, prevIndex, nextIndex; - - if (way.isClosed()) { - len = way.nodes.length - 1; - prevIndex = (movedIndex + len - 1) % len; - nextIndex = (movedIndex + len + 1) % len; - } else { - len = way.nodes.length; - prevIndex = movedIndex - 1; - nextIndex = movedIndex + 1; - } + if (!cache) { + cache = {}; + } + if (!cache.ok) { + cache.moving = {}; + cache.intersections = []; + cache.replacedVertex = {}; + cache.startLoc = {}; + cache.nodes = []; + cache.ways = []; + + cacheEntities(moveIds); + cacheIntersections(cache.ways); + cache.nodes = filter(cache.nodes, canMove); + + cache.ok = true; + } + } - var prev = graph.hasEntity(way.nodes[prevIndex]); - var next = graph.hasEntity(way.nodes[nextIndex]); - // Don't add orig vertex at endpoint.. - if (!prev || !next) return graph; + // Place a vertex where the moved vertex used to be, to preserve way shape.. + // + // Start: + // b ---- e + // / \ + // / \ + // / \ + // a c + // + // * node '*' added to preserve shape + // / \ + // / b ---- e way `b,e` moved here: + // / \ + // a c + // + // + function replaceMovedVertex(nodeId, wayId, graph, delta) { + var way = graph.entity(wayId); + var moved = graph.entity(nodeId); + var movedIndex = way.nodes.indexOf(nodeId); + var len, prevIndex, nextIndex; + + if (way.isClosed()) { + len = way.nodes.length - 1; + prevIndex = (movedIndex + len - 1) % len; + nextIndex = (movedIndex + len + 1) % len; + } else { + len = way.nodes.length; + prevIndex = movedIndex - 1; + nextIndex = movedIndex + 1; + } - var key = wayId + '_' + nodeId; - var orig = cache.replacedVertex[key]; - if (!orig) { - orig = osmNode(); - cache.replacedVertex[key] = orig; - cache.startLoc[orig.id] = cache.startLoc[nodeId]; - } + var prev = graph.hasEntity(way.nodes[prevIndex]); + var next = graph.hasEntity(way.nodes[nextIndex]); - var start, end; - if (delta) { - start = projection(cache.startLoc[nodeId]); - end = projection.invert(geoVecAdd(start, delta)); - } else { - end = cache.startLoc[nodeId]; - } - orig = orig.move(end); + // Don't add orig vertex at endpoint.. + if (!prev || !next) return graph; - var angle = Math.abs(geoAngle(orig, prev, projection) - - geoAngle(orig, next, projection)) * 180 / Math.PI; + var key = wayId + '_' + nodeId; + var orig = cache.replacedVertex[key]; + if (!orig) { + orig = osmNode(); + cache.replacedVertex[key] = orig; + cache.startLoc[orig.id] = cache.startLoc[nodeId]; + } - // Don't add orig vertex if it would just make a straight line.. - if (angle > 175 && angle < 185) return graph; + var start, end; + if (delta) { + start = projection(cache.startLoc[nodeId]); + end = projection.invert(geoVecAdd(start, delta)); + } else { + end = cache.startLoc[nodeId]; + } + orig = orig.move(end); - // moving forward or backward along way? - var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection); - var p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection); - var d1 = geoPathLength(p1); - var d2 = geoPathLength(p2); - var insertAt = (d1 <= d2) ? movedIndex : nextIndex; + var angle = Math.abs(geoAngle(orig, prev, projection) - + geoAngle(orig, next, projection)) * 180 / Math.PI; - // moving around closed loop? - if (way.isClosed() && insertAt === 0) insertAt = len; + // Don't add orig vertex if it would just make a straight line.. + if (angle > 175 && angle < 185) return graph; - way = way.addNode(orig.id, insertAt); - return graph.replace(orig).replace(way); - } + // moving forward or backward along way? + var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection); + var p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection); + var d1 = geoPathLength(p1); + var d2 = geoPathLength(p2); + var insertAt = (d1 <= d2) ? movedIndex : nextIndex; + // moving around closed loop? + if (way.isClosed() && insertAt === 0) insertAt = len; - // Remove duplicate vertex that might have been added by - // replaceMovedVertex. This is done after the unzorro checks. - function removeDuplicateVertices(wayId, graph) { - var way = graph.entity(wayId); - var epsilon = 1e-6; - var prev, curr; + way = way.addNode(orig.id, insertAt); + return graph.replace(orig).replace(way); + } - function isInteresting(node, graph) { - return graph.parentWays(node).length > 1 || - graph.parentRelations(node).length || - node.hasInterestingTags(); - } - for (var i = 0; i < way.nodes.length; i++) { - curr = graph.entity(way.nodes[i]); - - if (prev && curr && geoVecEqual(prev.loc, curr.loc, epsilon)) { - if (!isInteresting(prev, graph)) { - way = way.removeNode(prev.id); - graph = graph.replace(way).remove(prev); - } else if (!isInteresting(curr, graph)) { - way = way.removeNode(curr.id); - graph = graph.replace(way).remove(curr); - } - } + // Remove duplicate vertex that might have been added by + // replaceMovedVertex. This is done after the unzorro checks. + function removeDuplicateVertices(wayId, graph) { + var way = graph.entity(wayId); + var epsilon = 1e-6; + var prev, curr; - prev = curr; - } + function isInteresting(node, graph) { + return graph.parentWays(node).length > 1 || + graph.parentRelations(node).length || + node.hasInterestingTags(); + } - return graph; - } + for (var i = 0; i < way.nodes.length; i++) { + curr = graph.entity(way.nodes[i]); + if (prev && curr && geoVecEqual(prev.loc, curr.loc, epsilon)) { + if (!isInteresting(prev, graph)) { + way = way.removeNode(prev.id); + graph = graph.replace(way).remove(prev); + } else if (!isInteresting(curr, graph)) { + way = way.removeNode(curr.id); + graph = graph.replace(way).remove(curr); + } + } - // Reorder nodes around intersections that have moved.. - // - // Start: way1.nodes: b,e (moving) - // a - b - c ----- d way2.nodes: a,b,c,d (static) - // | vertex: b - // e isEP1: true, isEP2, false - // - // way1 `b,e` moved here: - // a ----- c = b - d - // | - // e - // - // reorder nodes way1.nodes: b,e - // a ----- c - b - d way2.nodes: a,c,b,d - // | - // e - // - function unZorroIntersection(intersection$$1, graph) { - var vertex = graph.entity(intersection$$1.nodeId); - var way1 = graph.entity(intersection$$1.movedId); - var way2 = graph.entity(intersection$$1.unmovedId); - var isEP1 = intersection$$1.movedIsEP; - var isEP2 = intersection$$1.unmovedIsEP; - - // don't move the vertex if it is the endpoint of both ways. - if (isEP1 && isEP2) return graph; - - var nodes1 = without(graph.childNodes(way1), vertex); - var nodes2 = without(graph.childNodes(way2), vertex); - - if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]); - if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]); - - var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection); - var edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection); - var loc; - - // snap vertex to nearest edge (or some point between them).. - if (!isEP1 && !isEP2) { - var epsilon = 1e-6, maxIter = 10; - for (var i = 0; i < maxIter; i++) { - loc = geoVecInterp(edge1.loc, edge2.loc, 0.5); - edge1 = geoChooseEdge(nodes1, projection(loc), projection); - edge2 = geoChooseEdge(nodes2, projection(loc), projection); - if (Math.abs(edge1.distance - edge2.distance) < epsilon) break; - } - } else if (!isEP1) { - loc = edge1.loc; - } else { - loc = edge2.loc; - } + prev = curr; + } - graph = graph.replace(vertex.move(loc)); + return graph; + } - // if zorro happened, reorder nodes.. - if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) { - way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index); - graph = graph.replace(way1); - } - if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) { - way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index); - graph = graph.replace(way2); - } - return graph; - } + // Reorder nodes around intersections that have moved.. + // + // Start: way1.nodes: b,e (moving) + // a - b - c ----- d way2.nodes: a,b,c,d (static) + // | vertex: b + // e isEP1: true, isEP2, false + // + // way1 `b,e` moved here: + // a ----- c = b - d + // | + // e + // + // reorder nodes way1.nodes: b,e + // a ----- c - b - d way2.nodes: a,c,b,d + // | + // e + // + function unZorroIntersection(intersection$$1, graph) { + var vertex = graph.entity(intersection$$1.nodeId); + var way1 = graph.entity(intersection$$1.movedId); + var way2 = graph.entity(intersection$$1.unmovedId); + var isEP1 = intersection$$1.movedIsEP; + var isEP2 = intersection$$1.unmovedIsEP; + + // don't move the vertex if it is the endpoint of both ways. + if (isEP1 && isEP2) return graph; + + var nodes1 = without(graph.childNodes(way1), vertex); + var nodes2 = without(graph.childNodes(way2), vertex); + + if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]); + if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]); + + var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection); + var edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection); + var loc; + + // snap vertex to nearest edge (or some point between them).. + if (!isEP1 && !isEP2) { + var epsilon = 1e-6, maxIter = 10; + for (var i = 0; i < maxIter; i++) { + loc = geoVecInterp(edge1.loc, edge2.loc, 0.5); + edge1 = geoChooseEdge(nodes1, projection(loc), projection); + edge2 = geoChooseEdge(nodes2, projection(loc), projection); + if (Math.abs(edge1.distance - edge2.distance) < epsilon) break; + } + } else if (!isEP1) { + loc = edge1.loc; + } else { + loc = edge2.loc; + } + graph = graph.replace(vertex.move(loc)); - function cleanupIntersections(graph) { - for (var i = 0; i < cache.intersections.length; i++) { - var obj = cache.intersections[i]; - graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, _delta); - graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null); - graph = unZorroIntersection(obj, graph); - graph = removeDuplicateVertices(obj.movedId, graph); - graph = removeDuplicateVertices(obj.unmovedId, graph); - } + // if zorro happened, reorder nodes.. + if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) { + way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index); + graph = graph.replace(way1); + } + if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) { + way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index); + graph = graph.replace(way2); + } - return graph; - } + return graph; + } - // check if moving way endpoint can cross an unmoved way, if so limit delta.. - function limitDelta(graph) { - function moveNode(loc) { - return geoVecAdd(projection(loc), _delta); - } + function cleanupIntersections(graph) { + for (var i = 0; i < cache.intersections.length; i++) { + var obj = cache.intersections[i]; + graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, _delta); + graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null); + graph = unZorroIntersection(obj, graph); + graph = removeDuplicateVertices(obj.movedId, graph); + graph = removeDuplicateVertices(obj.unmovedId, graph); + } - for (var i = 0; i < cache.intersections.length; i++) { - var obj = cache.intersections[i]; - - // Don't limit movement if this is vertex joins 2 endpoints.. - if (obj.movedIsEP && obj.unmovedIsEP) continue; - // Don't limit movement if this vertex is not an endpoint anyway.. - if (!obj.movedIsEP) continue; - - var node = graph.entity(obj.nodeId); - var start = projection(node.loc); - var end = geoVecAdd(start, _delta); - var movedNodes = graph.childNodes(graph.entity(obj.movedId)); - var movedPath = map$3(map$3(movedNodes, 'loc'), moveNode); - var unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)); - var unmovedPath = map$3(map$3(unmovedNodes, 'loc'), projection); - var hits = geoPathIntersections(movedPath, unmovedPath); - - for (var j = 0; i < hits.length; i++) { - if (isEqual(hits[j], end)) continue; - var edge = geoChooseEdge(unmovedNodes, end, projection); - _delta = geoVecSubtract(projection(edge.loc), start); - } - } - } + return graph; + } - var action = function(graph) { - if (_delta[0] === 0 && _delta[1] === 0) return graph; + // check if moving way endpoint can cross an unmoved way, if so limit delta.. + function limitDelta(graph) { + function moveNode(loc) { + return geoVecAdd(projection(loc), _delta); + } - setupCache(graph); + for (var i = 0; i < cache.intersections.length; i++) { + var obj = cache.intersections[i]; + + // Don't limit movement if this is vertex joins 2 endpoints.. + if (obj.movedIsEP && obj.unmovedIsEP) continue; + // Don't limit movement if this vertex is not an endpoint anyway.. + if (!obj.movedIsEP) continue; + + var node = graph.entity(obj.nodeId); + var start = projection(node.loc); + var end = geoVecAdd(start, _delta); + var movedNodes = graph.childNodes(graph.entity(obj.movedId)); + var movedPath = map$3(map$3(movedNodes, 'loc'), moveNode); + var unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)); + var unmovedPath = map$3(map$3(unmovedNodes, 'loc'), projection); + var hits = geoPathIntersections(movedPath, unmovedPath); + + for (var j = 0; i < hits.length; i++) { + if (isEqual(hits[j], end)) continue; + var edge = geoChooseEdge(unmovedNodes, end, projection); + _delta = geoVecSubtract(projection(edge.loc), start); + } + } + } - if (cache.intersections.length) { - limitDelta(graph); - } - for (var i = 0; i < cache.nodes.length; i++) { - var node = graph.entity(cache.nodes[i]); - var start = projection(node.loc); - var end = geoVecAdd(start, _delta); - graph = graph.replace(node.move(projection.invert(end))); - } + var action = function(graph) { + if (_delta[0] === 0 && _delta[1] === 0) return graph; - if (cache.intersections.length) { - graph = cleanupIntersections(graph); - } + setupCache(graph); - return graph; - }; + if (cache.intersections.length) { + limitDelta(graph); + } + for (var i = 0; i < cache.nodes.length; i++) { + var node = graph.entity(cache.nodes[i]); + var start = projection(node.loc); + var end = geoVecAdd(start, _delta); + graph = graph.replace(node.move(projection.invert(end))); + } - action.delta = function() { - return _delta; - }; + if (cache.intersections.length) { + graph = cleanupIntersections(graph); + } + return graph; + }; - return action; -} -function actionMoveNode(nodeID, toLoc) { + action.delta = function() { + return _delta; + }; - var action = function(graph, t) { - if (t === null || !isFinite(t)) t = 1; - t = Math.min(Math.max(+t, 0), 1); - var node = graph.entity(nodeID); - return graph.replace( - node.move(geoVecInterp(node.loc, toLoc, t)) - ); - }; + return action; + } - action.transitionable = true; + function actionMoveNode(nodeID, toLoc) { - return action; -} + var action = function(graph, t) { + if (t === null || !isFinite(t)) t = 1; + t = Math.min(Math.max(+t, 0), 1); -function actionNoop() { - return function(graph) { - return graph; - }; -} - -/* - * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as - */ -function actionOrthogonalize(wayId, projection) { - var threshold = 12, // degrees within right or straight to alter - lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180), - upperThreshold = Math.cos(threshold * Math.PI / 180); - - - var action = function(graph, t) { - if (t === null || !isFinite(t)) t = 1; - t = Math.min(Math.max(+t, 0), 1); - - var way = graph.entity(wayId), - nodes = graph.childNodes(way), - points = uniq(nodes).map(function(n) { return projection(n.loc); }), - corner = {i: 0, dotp: 1}, - epsilon = 1e-4, - node, loc, score, motions, i, j; - - if (points.length === 3) { // move only one vertex for right triangle - for (i = 0; i < 1000; i++) { - motions = points.map(calcMotion); - points[corner.i] = addPoints(points[corner.i], motions[corner.i]); - score = corner.dotp; - if (score < epsilon) { - break; - } - } + var node = graph.entity(nodeID); + return graph.replace( + node.move(geoVecInterp(node.loc, toLoc, t)) + ); + }; - node = graph.entity(nodes[corner.i].id); - loc = projection.invert(points[corner.i]); - graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t))); + action.transitionable = true; - } else { - var best, - originalPoints = clone(points); - score = Infinity; - - for (i = 0; i < 1000; i++) { - motions = points.map(calcMotion); - for (j = 0; j < motions.length; j++) { - points[j] = addPoints(points[j],motions[j]); - } - var newScore = squareness(points); - if (newScore < score) { - best = clone(points); - score = newScore; - } - if (score < epsilon) { - break; - } - } + return action; + } - points = best; + function actionNoop() { + return function(graph) { + return graph; + }; + } - for (i = 0; i < points.length; i++) { - // only move the points that actually moved - if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) { - loc = projection.invert(points[i]); - node = graph.entity(nodes[i].id); - graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t))); - } - } + /* + * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as + */ + function actionOrthogonalize(wayId, projection) { + var threshold = 12, // degrees within right or straight to alter + lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180), + upperThreshold = Math.cos(threshold * Math.PI / 180); + + + var action = function(graph, t) { + if (t === null || !isFinite(t)) t = 1; + t = Math.min(Math.max(+t, 0), 1); + + var way = graph.entity(wayId), + nodes = graph.childNodes(way), + points = uniq(nodes).map(function(n) { return projection(n.loc); }), + corner = {i: 0, dotp: 1}, + epsilon = 1e-4, + node, loc, score, motions, i, j; + + if (points.length === 3) { // move only one vertex for right triangle + for (i = 0; i < 1000; i++) { + motions = points.map(calcMotion); + points[corner.i] = addPoints(points[corner.i], motions[corner.i]); + score = corner.dotp; + if (score < epsilon) { + break; + } + } + + node = graph.entity(nodes[corner.i].id); + loc = projection.invert(points[corner.i]); + graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t))); - // remove empty nodes on straight sections - for (i = 0; t === 1 && i < points.length; i++) { - node = graph.entity(nodes[i].id); + } else { + var best, + originalPoints = clone(points); + score = Infinity; + + for (i = 0; i < 1000; i++) { + motions = points.map(calcMotion); + for (j = 0; j < motions.length; j++) { + points[j] = addPoints(points[j],motions[j]); + } + var newScore = squareness(points); + if (newScore < score) { + best = clone(points); + score = newScore; + } + if (score < epsilon) { + break; + } + } + + points = best; + + for (i = 0; i < points.length; i++) { + // only move the points that actually moved + if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) { + loc = projection.invert(points[i]); + node = graph.entity(nodes[i].id); + graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t))); + } + } + + // remove empty nodes on straight sections + for (i = 0; t === 1 && i < points.length; i++) { + node = graph.entity(nodes[i].id); + + if (graph.parentWays(node).length > 1 || + graph.parentRelations(node).length || + node.hasInterestingTags()) { + continue; + } + + var dotp = normalizedDotProduct(i, points); + if (dotp < -1 + epsilon) { + graph = actionDeleteNode(node.id)(graph); + } + } + } - if (graph.parentWays(node).length > 1 || - graph.parentRelations(node).length || - node.hasInterestingTags()) { - continue; - } + return graph; - var dotp = normalizedDotProduct(i, points); - if (dotp < -1 + epsilon) { - graph = actionDeleteNode(node.id)(graph); - } - } - } - return graph; + function calcMotion(b, i, array) { + var a = array[(i - 1 + array.length) % array.length], + c = array[(i + 1) % array.length], + p = subtractPoints(a, b), + q = subtractPoints(c, b), + scale, dotp; + scale = 2 * Math.min(geoVecLength(p, [0, 0]), geoVecLength(q, [0, 0])); + p = normalizePoint(p, 1.0); + q = normalizePoint(q, 1.0); - function calcMotion(b, i, array) { - var a = array[(i - 1 + array.length) % array.length], - c = array[(i + 1) % array.length], - p = subtractPoints(a, b), - q = subtractPoints(c, b), - scale, dotp; + dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]); - scale = 2 * Math.min(geoVecLength(p, [0, 0]), geoVecLength(q, [0, 0])); - p = normalizePoint(p, 1.0); - q = normalizePoint(q, 1.0); + // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270). + if (array.length > 3) { + if (dotp < -0.707106781186547) { + dotp += 1.0; + } + } else if (dotp && Math.abs(dotp) < corner.dotp) { + corner.i = i; + corner.dotp = Math.abs(dotp); + } - dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]); + return normalizePoint(addPoints(p, q), 0.1 * dotp * scale); + } + }; - // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270). - if (array.length > 3) { - if (dotp < -0.707106781186547) { - dotp += 1.0; - } - } else if (dotp && Math.abs(dotp) < corner.dotp) { - corner.i = i; - corner.dotp = Math.abs(dotp); - } - return normalizePoint(addPoints(p, q), 0.1 * dotp * scale); - } - }; + function squareness(points) { + return points.reduce(function(sum, val, i, array) { + var dotp = normalizedDotProduct(i, array); + dotp = filterDotProduct(dotp); + return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1))); + }, 0); + } - function squareness(points) { - return points.reduce(function(sum, val, i, array) { - var dotp = normalizedDotProduct(i, array); - dotp = filterDotProduct(dotp); - return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1))); - }, 0); - } + function normalizedDotProduct(i, points) { + var a = points[(i - 1 + points.length) % points.length], + b = points[i], + c = points[(i + 1) % points.length], + p = subtractPoints(a, b), + q = subtractPoints(c, b); + p = normalizePoint(p, 1.0); + q = normalizePoint(q, 1.0); - function normalizedDotProduct(i, points) { - var a = points[(i - 1 + points.length) % points.length], - b = points[i], - c = points[(i + 1) % points.length], - p = subtractPoints(a, b), - q = subtractPoints(c, b); + return p[0] * q[0] + p[1] * q[1]; + } - p = normalizePoint(p, 1.0); - q = normalizePoint(q, 1.0); - return p[0] * q[0] + p[1] * q[1]; - } + function subtractPoints(a, b) { + return [a[0] - b[0], a[1] - b[1]]; + } - function subtractPoints(a, b) { - return [a[0] - b[0], a[1] - b[1]]; - } + function addPoints(a, b) { + return [a[0] + b[0], a[1] + b[1]]; + } - function addPoints(a, b) { - return [a[0] + b[0], a[1] + b[1]]; - } + function normalizePoint(point, scale) { + var vector = [0, 0]; + var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]); + if (length !== 0) { + vector[0] = point[0] / length; + vector[1] = point[1] / length; + } + vector[0] *= scale; + vector[1] *= scale; - function normalizePoint(point, scale) { - var vector = [0, 0]; - var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]); - if (length !== 0) { - vector[0] = point[0] / length; - vector[1] = point[1] / length; - } + return vector; + } - vector[0] *= scale; - vector[1] *= scale; - return vector; - } + function filterDotProduct(dotp) { + if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) { + return dotp; + } + return 0; + } - function filterDotProduct(dotp) { - if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) { - return dotp; - } - return 0; - } + action.disabled = function(graph) { + var way = graph.entity(wayId), + nodes = graph.childNodes(way), + points = uniq(nodes).map(function(n) { return projection(n.loc); }); + if (squareness(points)) { + return false; + } - action.disabled = function(graph) { - var way = graph.entity(wayId), - nodes = graph.childNodes(way), - points = uniq(nodes).map(function(n) { return projection(n.loc); }); + return 'not_squarish'; + }; - if (squareness(points)) { - return false; - } - return 'not_squarish'; - }; + action.transitionable = true; - action.transitionable = true; - - - return action; -} - -// `actionRestrictTurn` creates a turn restriction relation. -// -// `turn` must be an `osmTurn` object -// see osm/intersection.js, pathToTurn() -// -// This specifies a restriction of type `restriction` when traveling from -// `turn.from.way` toward `turn.to.way` via `turn.via.node` OR `turn.via.ways`. -// (The action does not check that these entities form a valid intersection.) -// -// From, to, and via ways should be split before calling this action. -// (old versions of the code would split the ways here, but we no longer do it) -// -// For testing convenience, accepts a restrictionID to assign to the new -// relation. Normally, this will be undefined and the relation will -// automatically be assigned a new ID. -// -function actionRestrictTurn(turn, restrictionType, restrictionID) { - - return function(graph) { - var fromWay = graph.entity(turn.from.way); - var toWay = graph.entity(turn.to.way); - var viaNode = turn.via.node && graph.entity(turn.via.node); - var viaWays = turn.via.ways && turn.via.ways.map(function(id) { return graph.entity(id); }); - var members = []; - - members.push({ id: fromWay.id, type: 'way', role: 'from' }); - - if (viaNode) { - members.push({ id: viaNode.id, type: 'node', role: 'via' }); - } else if (viaWays) { - viaWays.forEach(function(viaWay) { - members.push({ id: viaWay.id, type: 'way', role: 'via' }); - }); - } + return action; + } - members.push({ id: toWay.id, type: 'way', role: 'to' }); + // `actionRestrictTurn` creates a turn restriction relation. + // + // `turn` must be an `osmTurn` object + // see osm/intersection.js, pathToTurn() + // + // This specifies a restriction of type `restriction` when traveling from + // `turn.from.way` toward `turn.to.way` via `turn.via.node` OR `turn.via.ways`. + // (The action does not check that these entities form a valid intersection.) + // + // From, to, and via ways should be split before calling this action. + // (old versions of the code would split the ways here, but we no longer do it) + // + // For testing convenience, accepts a restrictionID to assign to the new + // relation. Normally, this will be undefined and the relation will + // automatically be assigned a new ID. + // + function actionRestrictTurn(turn, restrictionType, restrictionID) { + + return function(graph) { + var fromWay = graph.entity(turn.from.way); + var toWay = graph.entity(turn.to.way); + var viaNode = turn.via.node && graph.entity(turn.via.node); + var viaWays = turn.via.ways && turn.via.ways.map(function(id) { return graph.entity(id); }); + var members = []; + + members.push({ id: fromWay.id, type: 'way', role: 'from' }); + + if (viaNode) { + members.push({ id: viaNode.id, type: 'node', role: 'via' }); + } else if (viaWays) { + viaWays.forEach(function(viaWay) { + members.push({ id: viaWay.id, type: 'way', role: 'via' }); + }); + } - return graph.replace(osmRelation({ - id: restrictionID, - tags: { - type: 'restriction', - restriction: restrictionType - }, - members: members - })); - }; -} - -function actionRevert(id) { - var action = function(graph) { - var entity = graph.hasEntity(id), - base = graph.base().entities[id]; - - if (entity && !base) { // entity will be removed.. - if (entity.type === 'node') { - graph.parentWays(entity) - .forEach(function(parent) { - parent = parent.removeNode(id); - graph = graph.replace(parent); - - if (parent.isDegenerate()) { - graph = actionDeleteWay(parent.id)(graph); - } - }); - } + members.push({ id: toWay.id, type: 'way', role: 'to' }); - graph.parentRelations(entity) - .forEach(function(parent) { - parent = parent.removeMembersWithID(id); - graph = graph.replace(parent); + return graph.replace(osmRelation({ + id: restrictionID, + tags: { + type: 'restriction', + restriction: restrictionType + }, + members: members + })); + }; + } - if (parent.isDegenerate()) { - graph = actionDeleteRelation(parent.id)(graph); - } - }); - } + function actionRevert(id) { + var action = function(graph) { + var entity = graph.hasEntity(id), + base = graph.base().entities[id]; + + if (entity && !base) { // entity will be removed.. + if (entity.type === 'node') { + graph.parentWays(entity) + .forEach(function(parent) { + parent = parent.removeNode(id); + graph = graph.replace(parent); + + if (parent.isDegenerate()) { + graph = actionDeleteWay(parent.id)(graph); + } + }); + } + + graph.parentRelations(entity) + .forEach(function(parent) { + parent = parent.removeMembersWithID(id); + graph = graph.replace(parent); + + if (parent.isDegenerate()) { + graph = actionDeleteRelation(parent.id)(graph); + } + }); + } - return graph.revert(id); - }; + return graph.revert(id); + }; - return action; -} + return action; + } -function actionRotate(rotateIds, pivot, angle, projection) { + function actionRotate(rotateIds, pivot, angle, projection) { - var action = function(graph) { - return graph.update(function(graph) { - utilGetAllNodes(rotateIds, graph).forEach(function(node) { - var point = geoRotate([projection(node.loc)], angle, pivot)[0]; - graph = graph.replace(node.move(projection.invert(point))); - }); - }); - }; + var action = function(graph) { + return graph.update(function(graph) { + utilGetAllNodes(rotateIds, graph).forEach(function(node) { + var point = geoRotate([projection(node.loc)], angle, pivot)[0]; + graph = graph.replace(node.move(projection.invert(point))); + }); + }); + }; - return action; -} - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax$8 = Math.max; - -/** - * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. If `fromIndex` is negative, it's used as the - * offset from the end of `array`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - * @example - * - * _.indexOf([1, 2, 1, 2], 2); - * // => 1 - * - * // Search from the `fromIndex`. - * _.indexOf([1, 2, 1, 2], 2, 2); - * // => 3 - */ -function indexOf(array, value, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; + return action; } - var index = fromIndex == null ? 0 : toInteger(fromIndex); - if (index < 0) { - index = nativeMax$8(length + index, 0); - } - return baseIndexOf(array, value, index); -} - -// Split a way at the given node. -// -// Optionally, split only the given ways, if multiple ways share -// the given node. -// -// This is the inverse of `iD.actionJoin`. -// -// For testing convenience, accepts an ID to assign to the new way. -// Normally, this will be undefined and the way will automatically -// be assigned a new ID. -// -// Reference: -// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as -// -function actionSplit(nodeId, newWayIds) { - var _wayIDs; - - // If the way is closed, we need to search for a partner node - // to split the way at. - // - // The following looks for a node that is both far away from - // the initial node in terms of way segment length and nearby - // in terms of beeline-distance. This assures that areas get - // split on the most "natural" points (independent of the number - // of nodes). - // For example: bone-shaped areas get split across their waist - // line, circles across the diameter. - function splitArea(nodes, idxA, graph) { - var lengths = new Array(nodes.length); - var length; - var i; - var best = 0; - var idxB; - - function wrap(index) { - return utilWrap(index, nodes.length); - } - function dist(nA, nB) { - var locA = graph.entity(nA).loc; - var locB = graph.entity(nB).loc; - var epsilon = 1e-6; - return (locA && locB) ? geoSphericalDistance(locA, locB) : epsilon; - } + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMax$8 = Math.max; - // calculate lengths - length = 0; - for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) { - length += dist(nodes[i], nodes[wrap(i-1)]); - lengths[i] = length; - } + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax$8(length + index, 0); + } + return baseIndexOf(array, value, index); + } - length = 0; - for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) { - length += dist(nodes[i], nodes[wrap(i+1)]); - if (length < lengths[i]) - lengths[i] = length; - } + // Split a way at the given node. + // + // Optionally, split only the given ways, if multiple ways share + // the given node. + // + // This is the inverse of `iD.actionJoin`. + // + // For testing convenience, accepts an ID to assign to the new way. + // Normally, this will be undefined and the way will automatically + // be assigned a new ID. + // + // Reference: + // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as + // + function actionSplit(nodeId, newWayIds) { + var _wayIDs; + + // If the way is closed, we need to search for a partner node + // to split the way at. + // + // The following looks for a node that is both far away from + // the initial node in terms of way segment length and nearby + // in terms of beeline-distance. This assures that areas get + // split on the most "natural" points (independent of the number + // of nodes). + // For example: bone-shaped areas get split across their waist + // line, circles across the diameter. + function splitArea(nodes, idxA, graph) { + var lengths = new Array(nodes.length); + var length; + var i; + var best = 0; + var idxB; + + function wrap(index) { + return utilWrap(index, nodes.length); + } - // determine best opposite node to split - for (i = 0; i < nodes.length; i++) { - var cost = lengths[i] / dist(nodes[idxA], nodes[i]); - if (cost > best) { - idxB = i; - best = cost; - } - } + function dist(nA, nB) { + var locA = graph.entity(nA).loc; + var locB = graph.entity(nB).loc; + var epsilon = 1e-6; + return (locA && locB) ? geoSphericalDistance(locA, locB) : epsilon; + } - return idxB; - } + // calculate lengths + length = 0; + for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) { + length += dist(nodes[i], nodes[wrap(i-1)]); + lengths[i] = length; + } + length = 0; + for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) { + length += dist(nodes[i], nodes[wrap(i+1)]); + if (length < lengths[i]) + lengths[i] = length; + } - function split(graph, wayA, newWayId) { - var wayB = osmWay({id: newWayId, tags: wayA.tags}); // `wayB` is the NEW way - var origNodes = wayA.nodes.slice(); - var nodesA; - var nodesB; - var isArea = wayA.isArea(); - var isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph); + // determine best opposite node to split + for (i = 0; i < nodes.length; i++) { + var cost = lengths[i] / dist(nodes[idxA], nodes[i]); + if (cost > best) { + idxB = i; + best = cost; + } + } - if (wayA.isClosed()) { - var nodes = wayA.nodes.slice(0, -1); - var idxA = indexOf(nodes, nodeId); - var idxB = splitArea(nodes, idxA, graph); + return idxB; + } - if (idxB < idxA) { - nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1)); - nodesB = nodes.slice(idxB, idxA + 1); - } else { - nodesA = nodes.slice(idxA, idxB + 1); - nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1)); - } - } else { - var idx = indexOf(wayA.nodes, nodeId, 1); - nodesA = wayA.nodes.slice(0, idx + 1); - nodesB = wayA.nodes.slice(idx); - } - wayA = wayA.update({nodes: nodesA}); - wayB = wayB.update({nodes: nodesB}); - - graph = graph.replace(wayA); - graph = graph.replace(wayB); - - graph.parentRelations(wayA).forEach(function(relation) { - var member; - - // Turn restrictions - make sure: - // 1. Splitting a FROM/TO way - only `wayA` OR `wayB` remains in relation - // (whichever one is connected to the VIA node/ways) - // 2. Splitting a VIA way - `wayB` remains in relation as a VIA way - if (relation.isRestriction()) { - var f = relation.memberByRole('from'); - var v = relation.membersByRole('via'); - var t = relation.memberByRole('to'); - var i; - - // 1. split a FROM/TO - if (f.id === wayA.id || t.id === wayA.id) { - var keepB = false; - if (v.length === 1 && v[0].type === 'node') { // check via node - keepB = wayB.contains(v[0].id); - } else { // check via way(s) - for (i = 0; i < v.length; i++) { - if (v[i].type === 'way') { - var wayVia = graph.hasEntity(v[i].id); - if (wayVia && intersection(wayB.nodes, wayVia.nodes).length) { - keepB = true; - break; - } - } - } - } - - if (keepB) { - relation = relation.replaceMember(wayA, wayB); - graph = graph.replace(relation); - } - - // 2. split a VIA - } else { - for (i = 0; i < v.length; i++) { - if (v[i].type === 'way' && v[i].id === wayA.id) { - member = { - id: wayB.id, - type: 'way', - role: 'via' - }; - graph = actionAddMember(relation.id, member, v[i].index + 1)(graph); - break; - } - } - } - - // All other relations (Routes, Multipolygons, etc): - // 1. Both `wayA` and `wayB` remain in the relation - // 2. But must be inserted as a pair (see `actionAddMember` for details) - } else { - if (relation === isOuter) { - graph = graph.replace(relation.mergeTags(wayA.tags)); - graph = graph.replace(wayA.update({tags: {}})); - graph = graph.replace(wayB.update({tags: {}})); - } - - member = { - id: wayB.id, - type: 'way', - role: relation.memberById(wayA.id).role - }; - - var insertPair = { - originalID: wayA.id, - insertedID: wayB.id, - nodes: origNodes - }; - - graph = actionAddMember(relation.id, member, undefined, insertPair)(graph); - } - }); + function split(graph, wayA, newWayId) { + var wayB = osmWay({id: newWayId, tags: wayA.tags}); // `wayB` is the NEW way + var origNodes = wayA.nodes.slice(); + var nodesA; + var nodesB; + var isArea = wayA.isArea(); + var isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph); + + if (wayA.isClosed()) { + var nodes = wayA.nodes.slice(0, -1); + var idxA = indexOf(nodes, nodeId); + var idxB = splitArea(nodes, idxA, graph); + + if (idxB < idxA) { + nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1)); + nodesB = nodes.slice(idxB, idxA + 1); + } else { + nodesA = nodes.slice(idxA, idxB + 1); + nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1)); + } + } else { + var idx = indexOf(wayA.nodes, nodeId, 1); + nodesA = wayA.nodes.slice(0, idx + 1); + nodesB = wayA.nodes.slice(idx); + } - if (!isOuter && isArea) { - var multipolygon = osmRelation({ - tags: assignIn({}, wayA.tags, {type: 'multipolygon'}), - members: [ - {id: wayA.id, role: 'outer', type: 'way'}, - {id: wayB.id, role: 'outer', type: 'way'} - ] - }); + wayA = wayA.update({nodes: nodesA}); + wayB = wayB.update({nodes: nodesB}); + + graph = graph.replace(wayA); + graph = graph.replace(wayB); + + graph.parentRelations(wayA).forEach(function(relation) { + var member; + + // Turn restrictions - make sure: + // 1. Splitting a FROM/TO way - only `wayA` OR `wayB` remains in relation + // (whichever one is connected to the VIA node/ways) + // 2. Splitting a VIA way - `wayB` remains in relation as a VIA way + if (relation.isRestriction()) { + var f = relation.memberByRole('from'); + var v = relation.membersByRole('via'); + var t = relation.memberByRole('to'); + var i; + + // 1. split a FROM/TO + if (f.id === wayA.id || t.id === wayA.id) { + var keepB = false; + if (v.length === 1 && v[0].type === 'node') { // check via node + keepB = wayB.contains(v[0].id); + } else { // check via way(s) + for (i = 0; i < v.length; i++) { + if (v[i].type === 'way') { + var wayVia = graph.hasEntity(v[i].id); + if (wayVia && intersection(wayB.nodes, wayVia.nodes).length) { + keepB = true; + break; + } + } + } + } + + if (keepB) { + relation = relation.replaceMember(wayA, wayB); + graph = graph.replace(relation); + } + + // 2. split a VIA + } else { + for (i = 0; i < v.length; i++) { + if (v[i].type === 'way' && v[i].id === wayA.id) { + member = { + id: wayB.id, + type: 'way', + role: 'via' + }; + graph = actionAddMember(relation.id, member, v[i].index + 1)(graph); + break; + } + } + } + + // All other relations (Routes, Multipolygons, etc): + // 1. Both `wayA` and `wayB` remain in the relation + // 2. But must be inserted as a pair (see `actionAddMember` for details) + } else { + if (relation === isOuter) { + graph = graph.replace(relation.mergeTags(wayA.tags)); + graph = graph.replace(wayA.update({tags: {}})); + graph = graph.replace(wayB.update({tags: {}})); + } + + member = { + id: wayB.id, + type: 'way', + role: relation.memberById(wayA.id).role + }; + + var insertPair = { + originalID: wayA.id, + insertedID: wayB.id, + nodes: origNodes + }; + + graph = actionAddMember(relation.id, member, undefined, insertPair)(graph); + } + }); - graph = graph.replace(multipolygon); - graph = graph.replace(wayA.update({tags: {}})); - graph = graph.replace(wayB.update({tags: {}})); - } + if (!isOuter && isArea) { + var multipolygon = osmRelation({ + tags: assignIn({}, wayA.tags, {type: 'multipolygon'}), + members: [ + {id: wayA.id, role: 'outer', type: 'way'}, + {id: wayB.id, role: 'outer', type: 'way'} + ] + }); + + graph = graph.replace(multipolygon); + graph = graph.replace(wayA.update({tags: {}})); + graph = graph.replace(wayB.update({tags: {}})); + } - return graph; - } + return graph; + } - var action = function(graph) { - var candidates = action.ways(graph); - for (var i = 0; i < candidates.length; i++) { - graph = split(graph, candidates[i], newWayIds && newWayIds[i]); - } - return graph; - }; + var action = function(graph) { + var candidates = action.ways(graph); + for (var i = 0; i < candidates.length; i++) { + graph = split(graph, candidates[i], newWayIds && newWayIds[i]); + } + return graph; + }; - action.ways = function(graph) { - var node = graph.entity(nodeId); - var parents = graph.parentWays(node); - var hasLines = some(parents, function(parent) { return parent.geometry(graph) === 'line'; }); + action.ways = function(graph) { + var node = graph.entity(nodeId); + var parents = graph.parentWays(node); + var hasLines = some(parents, function(parent) { return parent.geometry(graph) === 'line'; }); - return parents.filter(function(parent) { - if (_wayIDs && _wayIDs.indexOf(parent.id) === -1) - return false; + return parents.filter(function(parent) { + if (_wayIDs && _wayIDs.indexOf(parent.id) === -1) + return false; - if (!_wayIDs && hasLines && parent.geometry(graph) !== 'line') - return false; + if (!_wayIDs && hasLines && parent.geometry(graph) !== 'line') + return false; - if (parent.isClosed()) { - return true; - } + if (parent.isClosed()) { + return true; + } - for (var i = 1; i < parent.nodes.length - 1; i++) { - if (parent.nodes[i] === nodeId) { - return true; - } - } + for (var i = 1; i < parent.nodes.length - 1; i++) { + if (parent.nodes[i] === nodeId) { + return true; + } + } - return false; - }); - }; + return false; + }); + }; - action.disabled = function(graph) { - var candidates = action.ways(graph); - if (candidates.length === 0 || (_wayIDs && _wayIDs.length !== candidates.length)) - return 'not_eligible'; - }; + action.disabled = function(graph) { + var candidates = action.ways(graph); + if (candidates.length === 0 || (_wayIDs && _wayIDs.length !== candidates.length)) + return 'not_eligible'; + }; - action.limitWays = function(_) { - if (!arguments.length) return _wayIDs; - _wayIDs = _; - return action; - }; + action.limitWays = function(_) { + if (!arguments.length) return _wayIDs; + _wayIDs = _; + return action; + }; - return action; -} + return action; + } -/* - * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as - */ -function actionStraighten(wayId, projection) { + /* + * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as + */ + function actionStraighten(wayId, projection) { - function positionAlongWay(n, s, e) { - return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) / - (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2)); - } + function positionAlongWay(n, s, e) { + return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) / + (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2)); + } - var action = function(graph, t) { - if (t === null || !isFinite(t)) t = 1; - t = Math.min(Math.max(+t, 0), 1); + var action = function(graph, t) { + if (t === null || !isFinite(t)) t = 1; + t = Math.min(Math.max(+t, 0), 1); + + var way = graph.entity(wayId), + nodes = graph.childNodes(way), + points = nodes.map(function(n) { return projection(n.loc); }), + startPoint = points[0], + endPoint = points[points.length-1], + toDelete = [], + i; + + for (i = 1; i < points.length-1; i++) { + var node = nodes[i], + point = points[i]; + + if (t < 1 || graph.parentWays(node).length > 1 || + graph.parentRelations(node).length || + node.hasInterestingTags()) { + + var u = positionAlongWay(point, startPoint, endPoint), + p = [ + startPoint[0] + u * (endPoint[0] - startPoint[0]), + startPoint[1] + u * (endPoint[1] - startPoint[1]) + ], + loc2 = projection.invert(p); + + graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t))); + + } else { + // safe to delete + if (toDelete.indexOf(node) === -1) { + toDelete.push(node); + } + } + } + + for (i = 0; i < toDelete.length; i++) { + graph = actionDeleteNode(toDelete[i].id)(graph); + } - var way = graph.entity(wayId), - nodes = graph.childNodes(way), - points = nodes.map(function(n) { return projection(n.loc); }), - startPoint = points[0], - endPoint = points[points.length-1], - toDelete = [], - i; + return graph; + }; - for (i = 1; i < points.length-1; i++) { - var node = nodes[i], - point = points[i]; - if (t < 1 || graph.parentWays(node).length > 1 || - graph.parentRelations(node).length || - node.hasInterestingTags()) { + action.disabled = function(graph) { + // check way isn't too bendy + var way = graph.entity(wayId), + nodes = graph.childNodes(way), + points = nodes.map(function(n) { return projection(n.loc); }), + startPoint = points[0], + endPoint = points[points.length-1], + threshold = 0.2 * geoVecLength(startPoint, endPoint), + i; - var u = positionAlongWay(point, startPoint, endPoint), - p = [ - startPoint[0] + u * (endPoint[0] - startPoint[0]), - startPoint[1] + u * (endPoint[1] - startPoint[1]) - ], - loc2 = projection.invert(p); + if (threshold === 0) { + return 'too_bendy'; + } - graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t))); + for (i = 1; i < points.length-1; i++) { + var point = points[i], + u = positionAlongWay(point, startPoint, endPoint), + p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]), + p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]), + dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2)); + + // to bendy if point is off by 20% of total start/end distance in projected space + if (isNaN(dist) || dist > threshold) { + return 'too_bendy'; + } + } + }; - } else { - // safe to delete - if (toDelete.indexOf(node) === -1) { - toDelete.push(node); - } - } - } - for (i = 0; i < toDelete.length; i++) { - graph = actionDeleteNode(toDelete[i].id)(graph); - } + action.transitionable = true; - return graph; - }; + return action; + } - action.disabled = function(graph) { - // check way isn't too bendy - var way = graph.entity(wayId), - nodes = graph.childNodes(way), - points = nodes.map(function(n) { return projection(n.loc); }), - startPoint = points[0], - endPoint = points[points.length-1], - threshold = 0.2 * geoVecLength(startPoint, endPoint), - i; + // `actionUnrestrictTurn` deletes a turn restriction relation. + // + // `turn` must be an `osmTurn` object with a `restrictionID` property. + // see osm/intersection.js, pathToTurn() + // + function actionUnrestrictTurn(turn) { + return function(graph) { + return actionDeleteRelation(turn.restrictionID)(graph); + }; + } - if (threshold === 0) { - return 'too_bendy'; - } + /* Reflect the given area around its axis of symmetry */ + function actionReflect(reflectIds, projection) { + var useLongAxis = true; + + + // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points + // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756 + function getSmallestSurroundingRectangle(graph, nodes) { + var points = nodes.map(function(n) { return projection(n.loc); }), + hull = d3_polygonHull(points), + centroid = d3_polygonCentroid(hull), + minArea = Infinity, + ssrExtent = [], + ssrAngle = 0, + c1 = hull[0]; + + for (var i = 0; i <= hull.length - 1; i++) { + var c2 = (i === hull.length - 1) ? hull[0] : hull[i + 1], + angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]), + poly = geoRotate(hull, -angle, centroid), + extent = poly.reduce(function(extent, point) { + return extent.extend(geoExtent$$1(point)); + }, geoExtent$$1()), + area = extent.area(); + + if (area < minArea) { + minArea = area; + ssrExtent = extent; + ssrAngle = angle; + } + c1 = c2; + } - for (i = 1; i < points.length-1; i++) { - var point = points[i], - u = positionAlongWay(point, startPoint, endPoint), - p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]), - p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]), - dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2)); + return { + poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid), + angle: ssrAngle + }; + } - // to bendy if point is off by 20% of total start/end distance in projected space - if (isNaN(dist) || dist > threshold) { - return 'too_bendy'; - } - } - }; + var action = function(graph, t) { + if (t === null || !isFinite(t)) t = 1; + t = Math.min(Math.max(+t, 0), 1); - action.transitionable = true; + var nodes = utilGetAllNodes(reflectIds, graph), + ssr = getSmallestSurroundingRectangle(graph, nodes); + // Choose line pq = axis of symmetry. + // The shape's surrounding rectangle has 2 axes of symmetry. + // Reflect across the longer axis by default. + var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2 ], + q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2 ], + p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2 ], + q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ], + p, q; - return action; -} + var isLong = (geoVecLength(p1, q1) > geoVecLength(p2, q2)); + if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) { + p = p1; + q = q1; + } else { + p = p2; + q = q2; + } -// `actionUnrestrictTurn` deletes a turn restriction relation. -// -// `turn` must be an `osmTurn` object with a `restrictionID` property. -// see osm/intersection.js, pathToTurn() -// -function actionUnrestrictTurn(turn) { - return function(graph) { - return actionDeleteRelation(turn.restrictionID)(graph); - }; -} - -/* Reflect the given area around its axis of symmetry */ -function actionReflect(reflectIds, projection) { - var useLongAxis = true; - - - // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points - // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756 - function getSmallestSurroundingRectangle(graph, nodes) { - var points = nodes.map(function(n) { return projection(n.loc); }), - hull = d3_polygonHull(points), - centroid = d3_polygonCentroid(hull), - minArea = Infinity, - ssrExtent = [], - ssrAngle = 0, - c1 = hull[0]; - - for (var i = 0; i <= hull.length - 1; i++) { - var c2 = (i === hull.length - 1) ? hull[0] : hull[i + 1], - angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]), - poly = geoRotate(hull, -angle, centroid), - extent = poly.reduce(function(extent, point) { - return extent.extend(geoExtent$$1(point)); - }, geoExtent$$1()), - area = extent.area(); - - if (area < minArea) { - minArea = area; - ssrExtent = extent; - ssrAngle = angle; - } - c1 = c2; - } + // reflect c across pq + // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line + var dx = q[0] - p[0]; + var dy = q[1] - p[1]; + var a = (dx * dx - dy * dy) / (dx * dx + dy * dy); + var b = 2 * dx * dy / (dx * dx + dy * dy); + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + var c = projection(node.loc); + var c2 = [ + a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0], + b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1] + ]; + var loc2 = projection.invert(c2); + node = node.move(geoVecInterp(node.loc, loc2, t)); + graph = graph.replace(node); + } - return { - poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid), - angle: ssrAngle - }; - } + return graph; + }; - var action = function(graph, t) { - if (t === null || !isFinite(t)) t = 1; - t = Math.min(Math.max(+t, 0), 1); + action.useLongAxis = function(_) { + if (!arguments.length) return useLongAxis; + useLongAxis = _; + return action; + }; - var nodes = utilGetAllNodes(reflectIds, graph), - ssr = getSmallestSurroundingRectangle(graph, nodes); - // Choose line pq = axis of symmetry. - // The shape's surrounding rectangle has 2 axes of symmetry. - // Reflect across the longer axis by default. - var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2 ], - q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2 ], - p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2 ], - q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ], - p, q; + action.transitionable = true; - var isLong = (geoVecLength(p1, q1) > geoVecLength(p2, q2)); - if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) { - p = p1; - q = q1; - } else { - p = p2; - q = q2; - } - // reflect c across pq - // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line - var dx = q[0] - p[0]; - var dy = q[1] - p[1]; - var a = (dx * dx - dy * dy) / (dx * dx + dy * dy); - var b = 2 * dx * dy / (dx * dx + dy * dy); - for (var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - var c = projection(node.loc); - var c2 = [ - a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0], - b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1] - ]; - var loc2 = projection.invert(c2); - node = node.move(geoVecInterp(node.loc, loc2, t)); - graph = graph.replace(node); - } + return action; + } - return graph; - }; - action.useLongAxis = function(_) { - if (!arguments.length) return useLongAxis; - useLongAxis = _; - return action; - }; + var index$4 = /*#__PURE__*/Object.freeze({ + d3combobox: d3combobox, + d3geoTile: d3geoTile, + d3keybinding: d3keybinding + }); + var Connection = services.osm; + + var debug = false; + + var iD = /*#__PURE__*/Object.freeze({ + Connection: Connection, + debug: debug, + lib: index$4, + d3: index$3, + Context: coreContext, + setAreaKeys: setAreaKeys, + Difference: coreDifference, + Graph: coreGraph$$1, + History: coreHistory, + Tree: coreTree, + geoCross: geoVecCross, + geoInterp: geoVecInterp, + geoRoundCoordinates: geoVecFloor, + geoEuclideanDistance: geoVecLength, + Entity: osmEntity$$1, + Node: osmNode, + Relation: osmRelation, + Way: osmWay, + BackgroundSource: rendererBackgroundSource, + Background: rendererBackground, + Features: rendererFeatures, + Map: rendererMap, + TileLayer: rendererTileLayer, + Detect: utilDetect, + uiPreset: uiPresetEditor, + actionAddEntity: actionAddEntity, + actionAddMember: actionAddMember, + actionAddMidpoint: actionAddMidpoint, + actionAddVertex: actionAddVertex, + actionChangeMember: actionChangeMember, + actionChangePreset: actionChangePreset, + actionChangeTags: actionChangeTags, + actionCircularize: actionCircularize, + actionConnect: actionConnect, + actionCopyEntities: actionCopyEntities, + actionDeleteMember: actionDeleteMember, + actionDeleteMultiple: actionDeleteMultiple, + actionDeleteNode: actionDeleteNode, + actionDeleteRelation: actionDeleteRelation, + actionDeleteWay: actionDeleteWay, + actionDeprecateTags: actionDeprecateTags, + actionDiscardTags: actionDiscardTags, + actionDisconnect: actionDisconnect, + actionJoin: actionJoin, + actionMerge: actionMerge, + actionMergeNodes: actionMergeNodes, + actionMergePolygon: actionMergePolygon, + actionMergeRemoteChanges: actionMergeRemoteChanges, + actionMove: actionMove, + actionMoveNode: actionMoveNode, + actionNoop: actionNoop, + actionOrthogonalize: actionOrthogonalize, + actionRestrictTurn: actionRestrictTurn, + actionReverse: actionReverse, + actionRevert: actionRevert, + actionRotate: actionRotate, + actionSplit: actionSplit, + actionStraighten: actionStraighten, + actionUnrestrictTurn: actionUnrestrictTurn, + actionReflect: actionReflect, + behaviorAddWay: behaviorAddWay, + behaviorBreathe: behaviorBreathe, + behaviorCopy: behaviorCopy, + behaviorDrag: behaviorDrag, + behaviorDrawWay: behaviorDrawWay, + behaviorDraw: behaviorDraw, + behaviorEdit: behaviorEdit, + behaviorHash: behaviorHash, + behaviorHover: behaviorHover, + behaviorLasso: behaviorLasso, + behaviorOperation: behaviorOperation, + behaviorPaste: behaviorPaste, + behaviorSelect: behaviorSelect, + behaviorTail: behaviorTail, + coreContext: coreContext, + coreDifference: coreDifference, + coreGraph: coreGraph$$1, + coreHistory: coreHistory, + coreTree: coreTree, + dataFeatureIcons: dataFeatureIcons, + data: data, + dataWikipedia: wikipedia$2, + dataSuggestions: dataSuggestions, + dataAddressFormats: dataAddressFormats, + dataDeprecated: dataDeprecated, + dataDiscarded: dataDiscarded, + dataLocales: dataLocales, + dataPhoneFormats: dataPhoneFormats, + dataShortcuts: dataShortcuts, + dataImperial: dataImperial, + dataDriveLeft: dataDriveLeft, + dataEn: en, + geoExtent: geoExtent$$1, + geoLatToMeters: geoLatToMeters, + geoLonToMeters: geoLonToMeters, + geoMetersToLat: geoMetersToLat, + geoMetersToLon: geoMetersToLon, + geoMetersToOffset: geoMetersToOffset, + geoOffsetToMeters: geoOffsetToMeters, + geoScaleToZoom: geoScaleToZoom, + geoSphericalDistance: geoSphericalDistance, + geoZoomToScale: geoZoomToScale, + geoAngle: geoAngle, + geoChooseEdge: geoChooseEdge, + geoEdgeEqual: geoEdgeEqual, + geoHasLineIntersections: geoHasLineIntersections, + geoHasSelfIntersections: geoHasSelfIntersections, + geoRotate: geoRotate, + geoLineIntersection: geoLineIntersection, + geoPathHasIntersections: geoPathHasIntersections, + geoPathIntersections: geoPathIntersections, + geoPathLength: geoPathLength, + geoPointInPolygon: geoPointInPolygon, + geoPolygonContainsPolygon: geoPolygonContainsPolygon, + geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon, + geoViewportEdge: geoViewportEdge, + geoRawMercator: geoRawMercator, + geoVecAdd: geoVecAdd, + geoVecAngle: geoVecAngle, + geoVecCross: geoVecCross, + geoVecDot: geoVecDot, + geoVecEqual: geoVecEqual, + geoVecFloor: geoVecFloor, + geoVecInterp: geoVecInterp, + geoVecLength: geoVecLength, + geoVecSubtract: geoVecSubtract, + geoVecScale: geoVecScale, + modeAddArea: modeAddArea$$1, + modeAddLine: modeAddLine$$1, + modeAddPoint: modeAddPoint$$1, + modeBrowse: modeBrowse, + modeDragNode: modeDragNode$$1, + modeDrawArea: modeDrawArea, + modeDrawLine: modeDrawLine, + modeMove: modeMove$$1, + modeRotate: modeRotate$$1, + modeSave: modeSave$$1, + modeSelect: modeSelect, + operationCircularize: operationCircularize, + operationContinue: operationContinue, + operationDelete: operationDelete, + operationDisconnect: operationDisconnect, + operationMerge: operationMerge, + operationMove: operationMove, + operationOrthogonalize: operationOrthogonalize, + operationReflectShort: operationReflectShort, + operationReflectLong: operationReflectLong, + operationReverse: operationReverse, + operationRotate: operationRotate, + operationSplit: operationSplit, + operationStraighten: operationStraighten, + osmChangeset: osmChangeset, + osmEntity: osmEntity$$1, + osmNode: osmNode, + osmRelation: osmRelation, + osmWay: osmWay, + osmIntersection: osmIntersection, + osmTurn: osmTurn, + osmInferRestriction: osmInferRestriction, + osmLanes: osmLanes, + osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember, + osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember, + osmJoinWays: osmJoinWays, + osmOneWayTags: osmOneWayTags, + osmPavedTags: osmPavedTags, + osmIsInterestingTag: osmIsInterestingTag, + presetCategory: presetCategory, + presetCollection: presetCollection, + presetField: presetField, + presetPreset: presetPreset, + presetIndex: presetIndex, + rendererBackgroundSource: rendererBackgroundSource, + rendererBackground: rendererBackground, + rendererFeatures: rendererFeatures, + rendererMap: rendererMap, + rendererTileLayer: rendererTileLayer, + services: services, + serviceMapillary: serviceMapillary, + serviceNominatim: serviceNominatim, + serviceOpenstreetcam: serviceOpenstreetcam, + serviceOsm: serviceOsm, + serviceTaginfo: serviceTaginfo, + serviceWikidata: serviceWikidata, + serviceWikipedia: serviceWikipedia, + svgAreas: svgAreas$$1, + svgDebug: svgDebug$$1, + svgDefs: svgDefs, + svgGpx: svgGpx$$1, + svgIcon: svgIcon, + svgLabels: svgLabels, + svgLayers: svgLayers, + svgLines: svgLines$$1, + svgMapillaryImages: svgMapillaryImages$$1, + svgMapillarySigns: svgMapillarySigns, + svgMidpoints: svgMidpoints$$1, + svgOneWaySegments: svgOneWaySegments, + svgOpenstreetcamImages: svgOpenstreetcamImages$$1, + svgOsm: svgOsm, + svgPassiveVertex: svgPassiveVertex, + svgPath: svgPath, + svgPointTransform: svgPointTransform, + svgPoints: svgPoints$$1, + svgRelationMemberTags: svgRelationMemberTags, + svgSegmentWay: svgSegmentWay, + svgTagClasses: svgTagClasses, + svgTurns: svgTurns, + svgVertices: svgVertices$$1, + uiFields: uiFields, + uiFieldDefaultCheck: uiFieldCheck, + uiFieldOnewayCheck: uiFieldCheck, + uiFieldCheck: uiFieldCheck, + uiFieldMultiCombo: uiFieldCombo, + uiFieldNetworkCombo: uiFieldCombo, + uiFieldSemiCombo: uiFieldCombo, + uiFieldTypeCombo: uiFieldCombo, + uiFieldCombo: uiFieldCombo, + uiFieldUrl: uiFieldText, + uiFieldNumber: uiFieldText, + uiFieldTel: uiFieldText, + uiFieldEmail: uiFieldText, + uiFieldText: uiFieldText, + uiFieldAccess: uiFieldAccess, + uiFieldAddress: uiFieldAddress, + uiFieldCycleway: uiFieldCycleway, + uiFieldLanes: uiFieldLanes, + uiFieldLocalized: uiFieldLocalized, + uiFieldMaxspeed: uiFieldMaxspeed, + uiFieldStructureRadio: uiFieldRadio, + uiFieldRadio: uiFieldRadio, + uiFieldRestrictions: uiFieldRestrictions, + uiFieldTextarea: uiFieldTextarea, + uiFieldWikipedia: uiFieldWikipedia, + uiIntro: uiIntro, + uiInfoPanels: uiInfoPanels, + uiPanelBackground: uiPanelBackground, + uiPanelHistory: uiPanelHistory, + uiPanelLocation: uiPanelLocation, + uiPanelMeasurement: uiPanelMeasurement, + uiInit: uiInit, + uiAccount: uiAccount, + uiAttribution: uiAttribution, + uiBackground: uiBackground, + uiBackgroundDisplayOptions: uiBackgroundDisplayOptions, + uiBackgroundOffset: uiBackgroundOffset, + uiChangesetEditor: uiChangesetEditor, + uiCmd: uiCmd, + uiCommit: uiCommit, + uiCommitChanges: uiCommitChanges, + uiCommitWarnings: uiCommitWarnings, + uiConfirm: uiConfirm, + uiConflicts: uiConflicts, + uiContributors: uiContributors, + uiCurtain: uiCurtain, + uiDisclosure: uiDisclosure, + uiEditMenu: uiEditMenu, + uiEntityEditor: uiEntityEditor, + uiFeatureInfo: uiFeatureInfo, + uiFeatureList: uiFeatureList, + uiField: uiField, + uiFieldHelp: uiFieldHelp, + uiFlash: uiFlash, + uiFormFields: uiFormFields, + uiFullScreen: uiFullScreen, + uiGeolocate: uiGeolocate, + uiHelp: uiHelp, + uiInfo: uiInfo, + uiInspector: uiInspector, + uiLasso: uiLasso, + uiLoading: uiLoading, + uiMapData: uiMapData, + uiMapInMap: uiMapInMap, + uiModal: uiModal, + uiModes: uiModes, + uiNotice: uiNotice, + uiPresetEditor: uiPresetEditor, + uiPresetIcon: uiPresetIcon, + uiPresetList: uiPresetList, + uiRadialMenu: uiRadialMenu, + uiRawMemberEditor: uiRawMemberEditor, + uiRawMembershipEditor: uiRawMembershipEditor, + uiRawTagEditor: uiRawTagEditor, + uiRestore: uiRestore, + uiSave: uiSave, + uiScale: uiScale, + uiSelectionList: uiSelectionList, + uiSidebar: uiSidebar, + uiSourceSwitch: uiSourceSwitch, + uiSpinner: uiSpinner, + uiSplash: uiSplash, + uiStatus: uiStatus, + uiSuccess: uiSuccess$$1, + uiTagReference: uiTagReference, + uiToggle: uiToggle, + uiTooltipHtml: uiTooltipHtml, + uiUndoRedo: uiUndoRedo, + uiVersion: uiVersion, + uiViewOnOSM: uiViewOnOSM, + uiZoom: uiZoom, + utilAsyncMap: utilAsyncMap, + utilCallWhenIdle: utilCallWhenIdle, + utilCleanTags: utilCleanTags, + utilDisplayName: utilDisplayName, + utilDisplayNameForPath: utilDisplayNameForPath, + utilDisplayType: utilDisplayType, + utilEditDistance: utilEditDistance, + utilEntitySelector: utilEntitySelector, + utilEntityOrMemberSelector: utilEntityOrMemberSelector, + utilFastMouse: utilFastMouse, + utilFunctor: utilFunctor, + utilGetAllNodes: utilGetAllNodes, + utilGetPrototypeOf: utilGetPrototypeOf, + utilGetSetValue: utilGetSetValue, + utilIdleWorker: utilIdleWorker, + utilNoAuto: utilNoAuto, + utilPrefixCSSProperty: utilPrefixCSSProperty, + utilPrefixDOMProperty: utilPrefixDOMProperty, + utilQsString: utilQsString, + utilRebind: utilRebind, + utilSetTransform: utilSetTransform, + utilSessionMutex: utilSessionMutex, + utilStringQs: utilStringQs, + utilSuggestNames: utilSuggestNames, + utilTagText: utilTagText, + utilTriggerEvent: utilTriggerEvent, + utilWrap: utilWrap, + d3combobox: d3combobox, + d3geoTile: d3geoTile, + d3keybinding: d3keybinding, + validationDeprecatedTag: validationDeprecatedTag, + validationDisconnectedHighway: validationDisconnectedHighway, + validationManyDeletions: validationManyDeletions, + validationMissingTag: validationMissingTag, + validationOldMultipolygon: validationOldMultipolygon, + validationTagSuggestsArea: validationTagSuggestsArea + }); - action.transitionable = true; - - - return action; -} - - - -var index$4 = Object.freeze({ - d3combobox: d3combobox, - d3geoTile: d3geoTile, - d3keybinding: d3keybinding -}); - -var Connection = services.osm; - -var debug = false; - - -var iD = Object.freeze({ - Connection: Connection, - debug: debug, - lib: index$4, - d3: index$3, - Context: coreContext, - setAreaKeys: setAreaKeys, - Difference: coreDifference, - Graph: coreGraph$$1, - History: coreHistory, - Tree: coreTree, - geoCross: geoVecCross, - geoInterp: geoVecInterp, - geoRoundCoordinates: geoVecFloor, - geoEuclideanDistance: geoVecLength, - Entity: osmEntity$$1, - Node: osmNode, - Relation: osmRelation, - Way: osmWay, - BackgroundSource: rendererBackgroundSource, - Background: rendererBackground, - Features: rendererFeatures, - Map: rendererMap, - TileLayer: rendererTileLayer, - Detect: utilDetect, - uiPreset: uiPresetEditor, - actionAddEntity: actionAddEntity, - actionAddMember: actionAddMember, - actionAddMidpoint: actionAddMidpoint, - actionAddVertex: actionAddVertex, - actionChangeMember: actionChangeMember, - actionChangePreset: actionChangePreset, - actionChangeTags: actionChangeTags, - actionCircularize: actionCircularize, - actionConnect: actionConnect, - actionCopyEntities: actionCopyEntities, - actionDeleteMember: actionDeleteMember, - actionDeleteMultiple: actionDeleteMultiple, - actionDeleteNode: actionDeleteNode, - actionDeleteRelation: actionDeleteRelation, - actionDeleteWay: actionDeleteWay, - actionDeprecateTags: actionDeprecateTags, - actionDiscardTags: actionDiscardTags, - actionDisconnect: actionDisconnect, - actionJoin: actionJoin, - actionMerge: actionMerge, - actionMergePolygon: actionMergePolygon, - actionMergeRemoteChanges: actionMergeRemoteChanges, - actionMove: actionMove, - actionMoveNode: actionMoveNode, - actionNoop: actionNoop, - actionOrthogonalize: actionOrthogonalize, - actionRestrictTurn: actionRestrictTurn, - actionReverse: actionReverse, - actionRevert: actionRevert, - actionRotate: actionRotate, - actionSplit: actionSplit, - actionStraighten: actionStraighten, - actionUnrestrictTurn: actionUnrestrictTurn, - actionReflect: actionReflect, - behaviorAddWay: behaviorAddWay, - behaviorBreathe: behaviorBreathe, - behaviorCopy: behaviorCopy, - behaviorDrag: behaviorDrag, - behaviorDrawWay: behaviorDrawWay, - behaviorDraw: behaviorDraw, - behaviorEdit: behaviorEdit, - behaviorHash: behaviorHash, - behaviorHover: behaviorHover, - behaviorLasso: behaviorLasso, - behaviorOperation: behaviorOperation, - behaviorPaste: behaviorPaste, - behaviorSelect: behaviorSelect, - behaviorTail: behaviorTail, - coreContext: coreContext, - coreDifference: coreDifference, - coreGraph: coreGraph$$1, - coreHistory: coreHistory, - coreTree: coreTree, - dataFeatureIcons: dataFeatureIcons, - data: data, - dataWikipedia: wikipedia$2, - dataSuggestions: dataSuggestions, - dataAddressFormats: dataAddressFormats, - dataDeprecated: dataDeprecated, - dataDiscarded: dataDiscarded, - dataLocales: dataLocales, - dataPhoneFormats: dataPhoneFormats, - dataShortcuts: dataShortcuts, - dataImperial: dataImperial, - dataDriveLeft: dataDriveLeft, - dataEn: en, - geoExtent: geoExtent$$1, - geoLatToMeters: geoLatToMeters, - geoLonToMeters: geoLonToMeters, - geoMetersToLat: geoMetersToLat, - geoMetersToLon: geoMetersToLon, - geoMetersToOffset: geoMetersToOffset, - geoOffsetToMeters: geoOffsetToMeters, - geoScaleToZoom: geoScaleToZoom, - geoSphericalDistance: geoSphericalDistance, - geoZoomToScale: geoZoomToScale, - geoAngle: geoAngle, - geoChooseEdge: geoChooseEdge, - geoEdgeEqual: geoEdgeEqual, - geoHasLineIntersections: geoHasLineIntersections, - geoHasSelfIntersections: geoHasSelfIntersections, - geoRotate: geoRotate, - geoLineIntersection: geoLineIntersection, - geoPathHasIntersections: geoPathHasIntersections, - geoPathIntersections: geoPathIntersections, - geoPathLength: geoPathLength, - geoPointInPolygon: geoPointInPolygon, - geoPolygonContainsPolygon: geoPolygonContainsPolygon, - geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon, - geoViewportEdge: geoViewportEdge, - geoRawMercator: geoRawMercator, - geoVecAdd: geoVecAdd, - geoVecAngle: geoVecAngle, - geoVecCross: geoVecCross, - geoVecDot: geoVecDot, - geoVecEqual: geoVecEqual, - geoVecFloor: geoVecFloor, - geoVecInterp: geoVecInterp, - geoVecLength: geoVecLength, - geoVecSubtract: geoVecSubtract, - geoVecScale: geoVecScale, - modeAddArea: modeAddArea$$1, - modeAddLine: modeAddLine$$1, - modeAddPoint: modeAddPoint$$1, - modeBrowse: modeBrowse, - modeDragNode: modeDragNode$$1, - modeDrawArea: modeDrawArea, - modeDrawLine: modeDrawLine, - modeMove: modeMove$$1, - modeRotate: modeRotate$$1, - modeSave: modeSave$$1, - modeSelect: modeSelect, - operationCircularize: operationCircularize, - operationContinue: operationContinue, - operationDelete: operationDelete, - operationDisconnect: operationDisconnect, - operationMerge: operationMerge, - operationMove: operationMove, - operationOrthogonalize: operationOrthogonalize, - operationReflectShort: operationReflectShort, - operationReflectLong: operationReflectLong, - operationReverse: operationReverse, - operationRotate: operationRotate, - operationSplit: operationSplit, - operationStraighten: operationStraighten, - osmChangeset: osmChangeset, - osmEntity: osmEntity$$1, - osmNode: osmNode, - osmRelation: osmRelation, - osmWay: osmWay, - osmIntersection: osmIntersection, - osmTurn: osmTurn, - osmInferRestriction: osmInferRestriction, - osmLanes: osmLanes, - osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember, - osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember, - osmJoinWays: osmJoinWays, - osmOneWayTags: osmOneWayTags, - osmPavedTags: osmPavedTags, - osmIsInterestingTag: osmIsInterestingTag, - presetCategory: presetCategory, - presetCollection: presetCollection, - presetField: presetField, - presetPreset: presetPreset, - presetIndex: presetIndex, - rendererBackgroundSource: rendererBackgroundSource, - rendererBackground: rendererBackground, - rendererFeatures: rendererFeatures, - rendererMap: rendererMap, - rendererTileLayer: rendererTileLayer, - services: services, - serviceMapillary: serviceMapillary, - serviceNominatim: serviceNominatim, - serviceOpenstreetcam: serviceOpenstreetcam, - serviceOsm: serviceOsm, - serviceTaginfo: serviceTaginfo, - serviceWikidata: serviceWikidata, - serviceWikipedia: serviceWikipedia, - svgAreas: svgAreas$$1, - svgDebug: svgDebug$$1, - svgDefs: svgDefs, - svgGpx: svgGpx$$1, - svgIcon: svgIcon, - svgLabels: svgLabels, - svgLayers: svgLayers, - svgLines: svgLines$$1, - svgMapillaryImages: svgMapillaryImages$$1, - svgMapillarySigns: svgMapillarySigns, - svgMidpoints: svgMidpoints$$1, - svgOneWaySegments: svgOneWaySegments, - svgOpenstreetcamImages: svgOpenstreetcamImages$$1, - svgOsm: svgOsm, - svgPassiveVertex: svgPassiveVertex, - svgPath: svgPath, - svgPointTransform: svgPointTransform, - svgPoints: svgPoints$$1, - svgRelationMemberTags: svgRelationMemberTags, - svgSegmentWay: svgSegmentWay, - svgTagClasses: svgTagClasses, - svgTurns: svgTurns, - svgVertices: svgVertices$$1, - uiFields: uiFields, - uiFieldDefaultCheck: uiFieldCheck, - uiFieldOnewayCheck: uiFieldCheck, - uiFieldCheck: uiFieldCheck, - uiFieldMultiCombo: uiFieldCombo, - uiFieldNetworkCombo: uiFieldCombo, - uiFieldSemiCombo: uiFieldCombo, - uiFieldTypeCombo: uiFieldCombo, - uiFieldCombo: uiFieldCombo, - uiFieldUrl: uiFieldText, - uiFieldNumber: uiFieldText, - uiFieldTel: uiFieldText, - uiFieldEmail: uiFieldText, - uiFieldText: uiFieldText, - uiFieldAccess: uiFieldAccess, - uiFieldAddress: uiFieldAddress, - uiFieldCycleway: uiFieldCycleway, - uiFieldLanes: uiFieldLanes, - uiFieldLocalized: uiFieldLocalized, - uiFieldMaxspeed: uiFieldMaxspeed, - uiFieldStructureRadio: uiFieldRadio, - uiFieldRadio: uiFieldRadio, - uiFieldRestrictions: uiFieldRestrictions, - uiFieldTextarea: uiFieldTextarea, - uiFieldWikipedia: uiFieldWikipedia, - uiIntro: uiIntro, - uiInfoPanels: uiInfoPanels, - uiPanelBackground: uiPanelBackground, - uiPanelHistory: uiPanelHistory, - uiPanelLocation: uiPanelLocation, - uiPanelMeasurement: uiPanelMeasurement, - uiInit: uiInit, - uiAccount: uiAccount, - uiAttribution: uiAttribution, - uiBackground: uiBackground, - uiBackgroundDisplayOptions: uiBackgroundDisplayOptions, - uiBackgroundOffset: uiBackgroundOffset, - uiChangesetEditor: uiChangesetEditor, - uiCmd: uiCmd, - uiCommit: uiCommit, - uiCommitChanges: uiCommitChanges, - uiCommitWarnings: uiCommitWarnings, - uiConfirm: uiConfirm, - uiConflicts: uiConflicts, - uiContributors: uiContributors, - uiCurtain: uiCurtain, - uiDisclosure: uiDisclosure, - uiEditMenu: uiEditMenu, - uiEntityEditor: uiEntityEditor, - uiFeatureInfo: uiFeatureInfo, - uiFeatureList: uiFeatureList, - uiField: uiField, - uiFieldHelp: uiFieldHelp, - uiFlash: uiFlash, - uiFormFields: uiFormFields, - uiFullScreen: uiFullScreen, - uiGeolocate: uiGeolocate, - uiHelp: uiHelp, - uiInfo: uiInfo, - uiInspector: uiInspector, - uiLasso: uiLasso, - uiLoading: uiLoading, - uiMapData: uiMapData, - uiMapInMap: uiMapInMap, - uiModal: uiModal, - uiModes: uiModes, - uiNotice: uiNotice, - uiPresetEditor: uiPresetEditor, - uiPresetIcon: uiPresetIcon, - uiPresetList: uiPresetList, - uiRadialMenu: uiRadialMenu, - uiRawMemberEditor: uiRawMemberEditor, - uiRawMembershipEditor: uiRawMembershipEditor, - uiRawTagEditor: uiRawTagEditor, - uiRestore: uiRestore, - uiSave: uiSave, - uiScale: uiScale, - uiSelectionList: uiSelectionList, - uiSidebar: uiSidebar, - uiSourceSwitch: uiSourceSwitch, - uiSpinner: uiSpinner, - uiSplash: uiSplash, - uiStatus: uiStatus, - uiSuccess: uiSuccess, - uiTagReference: uiTagReference, - uiToggle: uiToggle, - uiTooltipHtml: uiTooltipHtml, - uiUndoRedo: uiUndoRedo, - uiVersion: uiVersion, - uiViewOnOSM: uiViewOnOSM, - uiZoom: uiZoom, - utilAsyncMap: utilAsyncMap, - utilCallWhenIdle: utilCallWhenIdle, - utilDisplayName: utilDisplayName, - utilDisplayNameForPath: utilDisplayNameForPath, - utilDisplayType: utilDisplayType, - utilEditDistance: utilEditDistance, - utilEntitySelector: utilEntitySelector, - utilEntityOrMemberSelector: utilEntityOrMemberSelector, - utilFastMouse: utilFastMouse, - utilFunctor: utilFunctor, - utilGetAllNodes: utilGetAllNodes, - utilGetPrototypeOf: utilGetPrototypeOf, - utilGetSetValue: utilGetSetValue, - utilIdleWorker: utilIdleWorker, - utilNoAuto: utilNoAuto, - utilPrefixCSSProperty: utilPrefixCSSProperty, - utilPrefixDOMProperty: utilPrefixDOMProperty, - utilQsString: utilQsString, - utilRebind: utilRebind, - utilSetTransform: utilSetTransform, - utilSessionMutex: utilSessionMutex, - utilStringQs: utilStringQs, - utilSuggestNames: utilSuggestNames, - utilTagText: utilTagText, - utilTriggerEvent: utilTriggerEvent, - utilWrap: utilWrap, - d3combobox: d3combobox, - d3geoTile: d3geoTile, - d3keybinding: d3keybinding, - validationDeprecatedTag: validationDeprecatedTag, - validationDisconnectedHighway: validationDisconnectedHighway, - validationManyDeletions: validationManyDeletions, - validationMissingTag: validationMissingTag, - validationOldMultipolygon: validationOldMultipolygon, - validationTagSuggestsArea: validationTagSuggestsArea -}); - -window.iD = iD; + window.iD = iD; }()); //# sourceMappingURL=iD.js.map diff --git a/vendor/assets/iD/iD/img/community-sprite.svg b/vendor/assets/iD/iD/img/community-sprite.svg new file mode 100644 index 000000000..5c19a9bf9 --- /dev/null +++ b/vendor/assets/iD/iD/img/community-sprite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/assets/iD/iD/img/iD-sprite.svg b/vendor/assets/iD/iD/img/iD-sprite.svg index 3a1fb094d..1dad62812 100644 --- a/vendor/assets/iD/iD/img/iD-sprite.svg +++ b/vendor/assets/iD/iD/img/iD-sprite.svg @@ -194,10 +194,10 @@ - - - - + + + + @@ -479,6 +479,9 @@ + + + @@ -1386,6 +1389,9 @@ + + + diff --git a/vendor/assets/iD/iD/img/maki-sprite.svg b/vendor/assets/iD/iD/img/maki-sprite.svg index 4aa525957..927b93357 100644 --- a/vendor/assets/iD/iD/img/maki-sprite.svg +++ b/vendor/assets/iD/iD/img/maki-sprite.svg @@ -1 +1 @@ -barrier-11barrier-15bbq-11grill-15blood-bank-11blood-bank-15buddhismbuddhismbuildingsbuildingscity-11city-15defibrillator-11defibrillator-15drinking-water-11drinking-water-15emergency-phone-11emergency-phone-15entrance-alt1-11entrance-alt1-15farm-11farm-15fence-11fence-15florist-11florist-15gaminggaminggarden-center-11home-11home-15horse-riding-11horse-riding-15karaokelandmarklandmarklanduse-11landuse-15logging-11logging-15marker-stroked-11marker-stroked-15mobile-phone-11mobile-phone-15natural-11natural-15park-alt1-11park-alt1-15recycling-11recycling-15buildingsbuildingsscooter-11scooter-15slaughterhouse-11-01slaughterhouse-15-01snowmobile-11snowmobile-15teahousetelephone-11telephone-15town-11-01town-15village-11village-15 \ No newline at end of file + \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/af.json b/vendor/assets/iD/iD/locales/af.json index ec364e86c..8266a2aa0 100644 --- a/vendor/assets/iD/iD/locales/af.json +++ b/vendor/assets/iD/iD/locales/af.json @@ -183,8 +183,7 @@ "unsaved_changes": "Jy het ongestoorde veranderinge" }, "success": { - "just_edited": "Jy het nou net 'n OpenStreetMapKaart bydra gemaak!", - "view_on_osm": "Besigtig op OSM" + "just_edited": "Jy het nou net 'n OpenStreetMapKaart bydra gemaak!" }, "splash": { "welcome": "Welkom by die iD OpenStreetMap program", @@ -444,7 +443,6 @@ "label": "Tipe" }, "phone": { - "label": "Telefoon", "placeholder": "+27 11 907 1111" }, "place": { diff --git a/vendor/assets/iD/iD/locales/ar.json b/vendor/assets/iD/iD/locales/ar.json index 387e914a9..7ff77fdaf 100644 --- a/vendor/assets/iD/iD/locales/ar.json +++ b/vendor/assets/iD/iD/locales/ar.json @@ -1,5 +1,10 @@ { "ar": { + "icons": { + "information": "معلومات", + "remove": "إزالة", + "undo": "تراجع" + }, "modes": { "add_area": { "title": "مساحة", @@ -163,7 +168,6 @@ "annotation": "تم دمج {n} عناصر.", "not_eligible": "لا يمكن دمج هذه العناصر.", "not_adjacent": "لا يمكن دمج هذه العناصر لأن نقاط نهاياتها غير متصلة.", - "restriction": "لا يمكن دمج هذه العناصر لأن واحدة منها على الأقل جزء من العلاقة \"{relation}\".", "incomplete_relation": "لا يمكن دمج هذه العناصر لأن واحد منها على الأقل لم يتم تحميله بالكامل.", "conflicting_tags": "لا يمكن دمج هذه العناصر لأن بعض وسومها تحتوي قيما متعارضة مع بعضها." }, @@ -604,11 +608,6 @@ }, "success": { "just_edited": "لقد قمت للتو بتحرير OpenStreetMap!", - "view_on_osm": "عرض على OSM", - "facebook": "شارك على فيس بوك", - "twitter": "شارك على تويتر", - "google": "شارك على جوجل بلس", - "help_html": "ينبغي أن تظهر التغييرات التي قمت بها في الطبقة \"القياسية\" خلال بضع دقائق. قد تأخذ الطبقات الأخرى وقتا أطول.", "help_link_text": "تفاصيل", "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" }, @@ -708,16 +707,27 @@ "select_left_click": "{leftclick} انقر نقرة بالزر الأيسر على عنصر ما لاختياره. سيقوم ذلك بتمييز العنصر بحد متوهج ينبض باستمرار، وسيظهر شريط جانبي يعرض لك تفاصيل عن العنصر المُختار، كاسمه وعنوانه ونحو ذلك.", "select_right_click": "{rightclick} انقر نقرة بالزر الأيمن على عنصر ما لإظهار قائمة التعديل، والتي تعرض لك الأوامر المتاحة لتعديل العنصر، كتحريكه أو تدويره أو حذفه.", "multiselect_h": "الاختيار المتعدد", + "multiselect_shift_click": "`{shift}`+{leftclick} لاختيار أكثر من عنصر في نفس الوقت. يجعل ذلك من السهل تحريك أو حذف أكثر من عنصر في نفس الوقت.", + "multiselect_lasso": "هناك طريقة أخرى لاخيار عدة عناصر في نفس الوقت وهي بالضغط مع الاستمرار على مفتاح `{shift}`، ثم الضغط مع الاستمرار على زر الفأرة الأيسر {leftclick} وسحب الفأرة لرسم مساحة حُرة للتحديد. وبذلك سيتم تحديد جميع النقاط بداخل مساحة الرسم المرسومة.", "undo_redo_h": "التراجع والإعادة", + "undo_redo": "يتم حفظ تعديلاتك وتخزينها في المتصفح حتى تقوم باختيار حفظها على خادوم OpenStreetMap.\nيمكنك التراجع عن التعديلات عن طريق الضغط على زر **التراجع** {undo}، أو العودة عن التراجع عن طريق الضغط على زر **الإعادة** {redo}.", "save_h": "الحفظ", + "save": "انقر زر **حفظ** {save} لإنهاء تعديلاتك وإرسالها إلى OpenStreetMap. ينبغي عليك أن تتذكر حفظ تعديلاتك بشكل متكرر حتى لا يضيع مجهودك!", + "save_validation": "في شاشة الحفظ، سيكون لديك الفرصة لكتابة تعليق أو ملاحظات على ما قمت به من تعديلات. كما سيقوم المحرر iD تلقائيا بعمل بعض الفحوصات الأساسية عن البيانات التي قد تكون ناقصة وقد يقدم بعض الاقتراحات والتحذيرات المفيدة إن كان هناك شيء ما لا يبدو صحيحا. ", "upload_h": "الرفع", "upload": "قبل رفع تغييراتك ينبغي عليك إدخال [تعليق على التغييرات](https://wiki.openstreetmap.org/wiki/Good_changeset_comments). ثم اضغط على **رفع** لإرسال تغييراتك إلى خرائط OpenStreetMap, حيث ستدمج هذه التغييرات مع الخرائط وتكون مرئية للجميع.", "backups_h": "النسخ الاحتياطي التلقائي", - "keyboard_h": "اختصارات لوحة المفاتيح" + "backups": "إن لم تستطع إنهاء وحفظ تعديلاتك في نفس الجلسة، على سبيل المثال إنطفاء جهاز حاسوبك فجأة أو حدوث عطل في متصفحك أدى إلى غلقه بشكل مفاجيء أو نحو ذلك، فلا تقلق فإن تعديلاتك لا تزال محفوظة في متصفحك. حيث يمكنك العودة لاحقا (على نفس جهازك ونفس المتصفح)، وسيعرض عليك محرر iD استعادة أعمالك من حيث تركتها.", + "keyboard_h": "اختصارات لوحة المفاتيح", + "keyboard": "يمكنك عرض قائمة باختصارات لوحة المفاتيح عن طريق الضغط على مفتاح `?`." }, "feature_editor": { "title": "محرر العناصر", + "intro": "يظهر *محرر العناصر* على جانب الخريطة، ويتيح لك عرض وتحرير جميع المعلومات المتعلقة بالعنصر المُختار.", + "definitions": "يعرض لك القسم العلوي نوع العنصر.\nكما يحتوي القسم الأوسط على *حقول* تعرض خصائص وسمات العنصر، كالاسم والعنوان.", "type_h": "نوع العنصر", + "type": "يمكنك النقر على نوع العنصر لتغيير العنصر إلى نواع مختلف. أي شيء موجود في العالم الحقيقي يمكن إضافته إلى خرائط OpenStreetMap، لذلك هناك الآلاف من أنواع العناصر التي يمكنك الاختيار بينها.", + "type_picker": "عند اختيار نوع العنصر يظهر لك في الأعلى أنواع العناصر الأكثر شيوعا واستخداما، مثل مواقف السيارات، والمستشفيات، والمطاعم، والطُرق، والمباني، ونحو ذلك.\nيمكنك البحث عن أي شيء عن طريق كتابة ما تريده في حقل البحث. كما يمكنك أيضا النقر على أيقونة {inspect} **معلومات** الموجودة بجانب نوع العنصر لمعرفة المزيد عنه.", "fields_h": "الحقول", "tags_h": "الوسوم" }, @@ -752,6 +762,13 @@ }, "imagery": { "title": "صور الخلفية" + }, + "field": { + "restrictions": { + "tips": { + "title": "نصائح" + } + } } }, "intro": { @@ -815,6 +832,8 @@ "lafayette-park": "حديقة لافاييت", "las-coffee-cafe": "مقهى لاس كوفي", "lincoln-avenue": "جادة لينكولن", + "lowrys-books": "مكتبة لاوريز", + "lynns-garage": "جراج لين", "main-street-cafe": "مقهى الشارع الرئيسي", "main-street-fitness": "مركز لياقة بدنية", "main-street": "الشارع الرئيسي", @@ -823,13 +842,45 @@ "market-street": "شارع السوق", "michigan-avenue": "جادة ميشيغان", "middle-street": "الشارع الأوسط", + "millard-street": "شارع ميلارد", + "moore-street": "شارع موور", + "morris-avenue": "ضاحية موريس", + "mural-mall": "سوق مورال التجاري", + "paisanos-bar-and-grill": "بار وشوي بايسانوز", + "paisley-emporium": "متجر بيزلي", + "paparazzi-tattoo": "وشم باباراتزي", + "pealer-street": "شارع بيلر", + "pine-street": "شارع الصنوبر", "pizza-hut": "بيتزا هت", + "river-road": "طريق النهر", + "river-street": "شارع النهر", + "riviera-theatre": "مسرح ريفيرا", + "rocky-river": "نهر روكي", "saint-joseph-river": "نهر القديس يوسف", + "scidmore-park": "منتزه سكيدمور", + "scouter-park": "منتزه سكوتر", + "sherwin-williams": "شيروين وليامز", "south-street": "الشارع الجنوبي", + "southern-michigan-bank": "بنك جنوب ميشيغان", "spring-street": "شارع الربيع", - "three-rivers-fire-department": "قسم إطفاء الثلاثة أنهار", + "sturgeon-river-road": "شارع نهر ستورجيون", + "three-rivers-city-hall": "مجلس بلدية ثري ريفرز", + "three-rivers-elementary-school": "مدرسة ثري ريفرز الإبتدائية", + "three-rivers-fire-department": "قسم إطفاء ثري ريفرز", + "three-rivers-high-school": "مدرسة ثري ريفرز الثانوية", + "three-rivers-middle-school": "مدرسة ثري ريفرز المتوسطة", + "three-rivers-municipal-airport": "مطار ثري ريفرز المحلي", + "three-rivers-post-office": "مكتب بريد ثري ريفرز", + "three-rivers-public-library": "مكتبة ثري ريفرز العامة", + "three-rivers": "ثري ريفرز", + "unique-jewelry": "مجوهرات فريدة", + "walnut-street": "شارع وولنات", "washington-street": "شارع واشنطن", - "west-street": "الشارع الغربي" + "water-street": "شارع المياه", + "west-street": "الشارع الغربي", + "wheeler-street": "شارع ويلر", + "wood-street": "شارع الخشب", + "world-fare": "وورلد فير" } }, "welcome": { @@ -937,15 +988,17 @@ }, "key": { "alt": "Alt", + "backspace": "Backspace", + "cmd": "Cmd", "ctrl": "Ctrl", "delete": "Delete", "del": "Del", "end": "End", "enter": "Enter", "esc": "Esc", - "home": "الرئيسية", + "home": "Home", "option": "خيارات", - "pause": "إلباث", + "pause": "Pause", "pgdn": "PgDn", "pgup": "PgUp", "return": "رجوع", @@ -991,25 +1044,38 @@ "edit_menu": "فتح قائمة التحرير" }, "vertex_selected": { - "title": "مع القعدة المختارة", + "title": "مع العقدة المختارة", "previous": "قفز إلى العقدة السابقة", "next": "قفز إلى القعدة التالية", "first": "قفز إلى العقدة الأولى", - "last": "فز إلى العقدة الأخيرة" + "last": "قفز إلى العقدة الأخيرة" } }, "editing": { "title": "تحرير", "drawing": { "title": "رسم", - "place_point": "أضف نقطة" + "add_point": "نمط \"إضافة نقطة\"", + "add_line": "نمط \"إضافة خط\"", + "add_area": "نمط \"إضافة مساحة\"", + "place_point": "إضافة نقطة", + "disable_snap": "اضغط مع الاستمرار لتعطيل ميزة الانجذاب للنقاط", + "stop_line": "إنهاء رسم خط أو مساحة" }, "operations": { "title": "عمليات", + "continue_line": "استكمال خط من العُقدة المُختارة", + "merge": "دمج العناصر المُختارة", + "disconnect": "فصل العناصر عند العُقدة المُختارة", "split": "افصل الخط إلى خطين عند نقطة التلاقي المُختارة", "reverse": "عكس الخط", + "move": "نقل العناصر المُختارة", + "rotate": "تدوير العناصر المُختارة", "orthogonalize": "جعله خط مستقيما / جعلها مساحة مربعة", - "delete": "حذف الميزات المحددة" + "circularize": "جعل الخطوط المغلقة أو المنطقة دائرية", + "reflect_long": "انعكاس العناصر خلال المحور الأطول", + "reflect_short": "انعكاس العناصر خلال المحور الأقصر", + "delete": "حذف العناصر المُختارة" }, "commands": { "title": "الأوامر", @@ -1041,6 +1107,9 @@ "kilometers": "{quantity} كلم", "square_meters": "{quantity} م²", "square_kilometers": "{quantity} كلم²", + "arcdegrees": "{quantity}°", + "arcminutes": "{quantity}′", + "arcseconds": "{quantity}″", "north": "شمال", "south": "جنوب", "east": "شرق", @@ -1197,6 +1266,7 @@ "placeholder": "...8 ,4 ,2" }, "aerialway/summer/access": { + "label": "دخول (في الصيف)", "options": { "both": "كلاهما", "entry": "مدخل", @@ -1323,7 +1393,8 @@ "label": "وقت الاستلام" }, "comment": { - "label": "التعليق على التغييرات" + "label": "التعليق على التغييرات", + "placeholder": "وصف موجز لمساهماتك وتعديلاتك (مطلوب)" }, "communication_multi": { "label": "أنواع الاتصال" @@ -1465,6 +1536,9 @@ "display": { "label": "عرض" }, + "distance": { + "label": "المسافة الكلية" + }, "dock": { "label": "النوع" }, @@ -1627,9 +1701,15 @@ "indoor": { "label": "داخلي" }, + "industrial": { + "label": "النوع" + }, "information": { "label": "النوع" }, + "intermittent": { + "label": "متقطع" + }, "internet_access": { "label": "خدمة إنترنت", "options": { @@ -1662,26 +1742,37 @@ "leaf_cycle": { "label": "دورة أوراق الشجر", "options": { - "evergreen": "دائم الخضرة" + "deciduous": "نفضية", + "evergreen": "دائمة الخضرة", + "mixed": "مختلط", + "semi_deciduous": "شبه نفضية", + "semi_evergreen": "شبه دائمة الخضرة" } }, "leaf_cycle_singular": { + "label": "دورة أوراق الشجر", "options": { - "evergreen": "دائم الخضرة" + "deciduous": "نفضية", + "evergreen": "دائمة الخضرة", + "semi_deciduous": "شبه نفضية", + "semi_evergreen": "شبه دائمة الخضرة" } }, "leaf_type": { "label": "نوع ورق الشجر", "options": { "broadleaved": "عريضة الأوراق", - "leafless": "بدون أوراق" + "leafless": "بدون أوراق", + "mixed": "مختلط", + "needleleaved": "إبرية" } }, "leaf_type_singular": { "label": "نوع ورق الشجر", "options": { "broadleaved": "عريضة الأوراق", - "leafless": "بدون أوراق" + "leafless": "بدون أوراق", + "needleleaved": "إبرية" } }, "leisure": { @@ -1729,6 +1820,9 @@ "memorial": { "label": "النوع" }, + "monitoring_multi": { + "label": "رصد" + }, "mtb/scale": { "placeholder": "0, 1, 2, 3..." }, @@ -1793,6 +1887,7 @@ "oneway": { "label": "مسار واحد", "options": { + "alternating": "بالتناوب", "no": "لا", "undefined": "يفترض أنها لا", "yes": "نعم" @@ -1801,6 +1896,7 @@ "oneway_yes": { "label": "مسار واحد", "options": { + "alternating": "بالتناوب", "no": "لا", "undefined": "يفترض أنها نعم", "yes": "نعم" @@ -1833,7 +1929,6 @@ "label": "طرق الدفع" }, "phone": { - "label": "هاتف", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -1858,6 +1953,7 @@ "options": { "downhill": "انحدار", "ice_skate": "تزلج على الجليد", + "nordic": "شمال أوروبا", "playground": "ساحة لعب" } }, @@ -1874,6 +1970,12 @@ "playground/baby": { "label": "مقعد طفل" }, + "playground/max_age": { + "label": "الحد الأقصى للعمر" + }, + "playground/min_age": { + "label": "الحد الأدنى للعمر" + }, "population": { "label": "السكان" }, @@ -1889,6 +1991,9 @@ "railway": { "label": "النوع" }, + "recycling_accepts": { + "label": "يقبل" + }, "ref": { "label": "الرمز المرجعي" }, @@ -1905,6 +2010,9 @@ "ref_road_number": { "label": "رقم الطريق" }, + "ref_route": { + "label": "رقم المسار" + }, "ref_runway": { "label": "رقم المدرج" }, @@ -2076,6 +2184,9 @@ "toilets/disposal": { "label": "مردم نفايات" }, + "toll": { + "label": "رسوم" + }, "tomb": { "label": "النوع" }, @@ -2125,6 +2236,17 @@ "label": "النوع", "placeholder": "الافتراضي" }, + "usage_rail": { + "label": "إستعمال", + "options": { + "branch": "ثانوي", + "industrial": "صناعي", + "main": "رئيسي", + "military": "عسكري", + "test": "تجريبي", + "tourism": "سياحي" + } + }, "vending": { "label": "أنواع البضائع" }, @@ -2139,11 +2261,20 @@ "volcano/status": { "label": "حالة البركان", "options": { - "active": "نشط" + "active": "نشط", + "extinct": "خامد" } }, "volcano/type": { - "label": "نوع البركان" + "label": "نوع البركان", + "options": { + "scoria": "سكوريا", + "shield": "درعي", + "stratovolcano": "طبقي" + } + }, + "voltage": { + "label": "جهد كهربائي" }, "wall": { "label": "النوع" @@ -2177,7 +2308,7 @@ "terms": "عنوان" }, "aerialway": { - "name": "محطة النقل بالكابلات " + "name": "النقل بالكابلات " }, "aerialway/cable_car": { "name": "تلفريك", @@ -2191,8 +2322,12 @@ "name": "نقل البضائع بالكابلات ", "terms": "نقل البضائع بالكابلات " }, + "aerialway/pylon": { + "name": "برج التلفريك / المصعد التزلج", + "terms": "برج التلفريك ; المصعد التزلج" + }, "aerialway/station": { - "name": "محطة النقل بالكابلات " + "name": "محطة النقل بالكابلات" }, "aeroway": { "name": "جوي" @@ -2205,6 +2340,10 @@ "name": "ساحة المطار", "terms": "ساحة المطار" }, + "aeroway/gate": { + "name": "بوابة المطار", + "terms": "بوابة المطار" + }, "aeroway/hangar": { "name": "حظيرة الطائرات", "terms": "حظائر الطائرات" @@ -2221,9 +2360,17 @@ "name": "طريق للمدرج", "terms": "طريق للمدرج,طريق تدريج الطائرات" }, + "aeroway/terminal": { + "name": "محطة المطار", + "terms": "محطة المطار" + }, "amenity": { "name": "مرفق" }, + "amenity/animal_shelter": { + "name": "مأوى حيوانات", + "terms": "مأوى حيوانات; ملجأ" + }, "amenity/arts_centre": { "name": "مركز فنون", "terms": "مركز الفنون، معرض الفن، ساحة عرض، ملتقى فني" @@ -2240,6 +2387,10 @@ "name": "حانة", "terms": "بار , حانة , خمَّارَة ,مَشْرَب" }, + "amenity/bbq": { + "name": "مكان مخصص للشواء", + "terms": "شواء، باربيكيو" + }, "amenity/bench": { "name": "مقعد", "terms": "مقعد, مقعد طويل" @@ -2264,6 +2415,9 @@ "name": "تحويل أموال", "terms": "" }, + "amenity/bus_station": { + "name": "محطة حافلات" + }, "amenity/cafe": { "name": "مقهى", "terms": "مقهى, مطعم, ناد ليلي" @@ -2289,7 +2443,8 @@ "terms": "محطة شحن" }, "amenity/childcare": { - "name": "رعاية الأطفال" + "name": "رعاية الأطفال", + "terms": "رعاية الأطفال; حضانة" }, "amenity/cinema": { "name": "سينما", @@ -2299,25 +2454,48 @@ "name": "عيادة", "terms": "عيادة; مستوصف" }, + "amenity/clinic/abortion": { + "name": "عيادة الإجهاض", + "terms": "عيادة الإجهاض" + }, + "amenity/clinic/fertility": { + "name": "عيادة الخصوبة", + "terms": "عيادة الخصوبة" + }, "amenity/clock": { "name": "ساعة", "terms": "ساعة" }, "amenity/college": { - "name": "أرض كلية" + "name": "أرض كلية", + "terms": "أرض كلية" + }, + "amenity/community_centre": { + "name": "مركز اجتماعي", + "terms": "مركز اجتماعي" }, "amenity/compressed_air": { - "name": "هواء مضغوط" + "name": "هواء مضغوط", + "terms": "هواء مضغوط" }, "amenity/courthouse": { "name": "دار العدل", "terms": "مجمع المحاكم, دار العدل, دار القضاء" }, + "amenity/coworking_space": { + "name": "مساحة عمل مشتركة" + }, "amenity/dentist": { - "name": "طبيب أسنان" + "name": "طبيب أسنان", + "terms": "طبيب أسنان" }, "amenity/doctors": { - "name": "طبيب" + "name": "طبيب", + "terms": "طبيب" + }, + "amenity/dojo": { + "name": "دوجو / أكاديمية الفنون القتالية", + "terms": "دوجو; أكاديمية الفنون القتالية" }, "amenity/drinking_water": { "name": "مياه شرب", @@ -2334,6 +2512,9 @@ "name": "وجبات سريعة", "terms": "مأكولات السريعة" }, + "amenity/ferry_terminal": { + "name": "المحطة البحرية" + }, "amenity/fire_station": { "name": "محطة إطفاء حريق", "terms": "محطة إطفاء" @@ -2357,11 +2538,17 @@ "name": "أرض مستشفى", "terms": "أرض مستشفى; مستشفى" }, + "amenity/ice_cream": { + "name": "محل بيع المثلجات", + "terms": "مثلجات" + }, "amenity/internet_cafe": { - "name": "مقهى إنترنت" + "name": "مقهى إنترنت", + "terms": "مقهى إنترنت" }, "amenity/kindergarten": { - "name": "روضة أطفال" + "name": "روضة أطفال", + "terms": "روضة أطفال" }, "amenity/library": { "name": "مكتبة", @@ -2375,9 +2562,16 @@ "name": "موقف دراجات نارية", "terms": "دراجة نارية, دراجة بخارية; موقف; مواقف; ركن" }, + "amenity/music_school": { + "name": "مدرسة موسيقى", + "terms": "مدرسة موسيقى" + }, "amenity/nightclub": { "name": "ملهى ليلي" }, + "amenity/nursing_home": { + "name": "دار التمريض" + }, "amenity/parking": { "name": "موقف سيارات", "terms": "مواقف سيارات عامة ، مصف للسيارات، مواقف مركبات عمومية, مركن سيارات, جراج" @@ -2410,6 +2604,10 @@ "name": "مسجد", "terms": "مسجد, جامع" }, + "amenity/planetarium": { + "name": "قبة فلكية", + "terms": "قبة فلكية، قبة سماوية، بلانتاريوم" + }, "amenity/police": { "name": "شرطة", "terms": "مركز الشرطة, الشرطة " @@ -2422,6 +2620,10 @@ "name": "مكتب البريد", "terms": "دائرة البريد, مكتب البريد, مكتب بريد" }, + "amenity/prison": { + "name": "سجن", + "terms": "سجن" + }, "amenity/pub": { "name": "حانة", "terms": "مشرب, حانة, خمارة" @@ -2430,18 +2632,24 @@ "name": "محطة الحراسة", "terms": "محطة الحراسة" }, + "amenity/recycling": { + "name": "حاوية إعادة تدوير", + "terms": "حاوية إعادة تدوير" + }, "amenity/recycling_centre": { - "name": "مركز إعادة تدوير" + "name": "مركز إعادة تدوير", + "terms": "مركز إعادة تدوير" }, "amenity/register_office": { - "name": "مكتب تسجيل" + "name": "مكتب السجل المدني" }, "amenity/restaurant": { "name": "مطعم", "terms": "مطعم" }, "amenity/school": { - "name": "أرض مدرسة" + "name": "أرض مدرسة", + "terms": "مدرسة" }, "amenity/scrapyard": { "name": "مقبرة السيارات" @@ -2450,11 +2658,29 @@ "name": "مأوى", "terms": "مأوى, ملجأ, ملاذ, سقيفة, وقاء" }, + "amenity/social_facility": { + "name": "مؤسسة اجتماعية", + "terms": "مؤسسة اجتماعية" + }, "amenity/social_facility/food_bank": { - "name": "بنك غذاء" + "name": "بنك الطعام", + "terms": "بنك الطعام" + }, + "amenity/social_facility/group_home": { + "name": "دار المسنين", + "terms": "دار المسنين" + }, + "amenity/social_facility/homeless_shelter": { + "name": "ملجأ مشردين", + "terms": "ملجأ مشردين، مأوى" + }, + "amenity/social_facility/nursing_home": { + "name": "دار التمريض", + "terms": "دار التمريض" }, "amenity/studio": { - "name": "أستوديو" + "name": "أستوديو", + "terms": "أستوديو; إذاعة; راديو; تلفزيون" }, "amenity/swimming_pool": { "name": "حوض سباحة" @@ -2483,15 +2709,36 @@ "name": "أرض جامعة", "terms": "أرض جامعة, حرم جامعي" }, + "amenity/vending_machine": { + "name": "آلة بيع", + "terms": "آلة بيع" + }, "amenity/vending_machine/cigarettes": { - "name": "آلة بيع السجائر" + "name": "آلة بيع السجائر", + "terms": "سجائر" + }, + "amenity/vending_machine/coffee": { + "name": "آلة بيع القهوة", + "terms": "قهوة" + }, + "amenity/vending_machine/drinks": { + "name": "آلة بيع المشروبات", + "terms": "مشروبات" + }, + "amenity/vending_machine/news_papers": { + "name": "آلة بيع الجرائد" + }, + "amenity/vending_machine/newspapers": { + "name": "آلة بيع الجرائد", + "terms": "جرائد" }, "amenity/vending_machine/parking_tickets": { "name": "ماكينة بيع تذاكر وقوف", "terms": "ماكينة تذاكر" }, "amenity/veterinary": { - "name": "طبيب حيوانات" + "name": "بيطري", + "terms": "بيطري، طبيب حيوانات" }, "amenity/waste_basket": { "name": "سلة مهملات", @@ -2505,6 +2752,34 @@ "name": "سطح الطريق", "terms": "" }, + "attraction/animal": { + "name": "حيوان", + "terms": "حيوان" + }, + "attraction/big_wheel": { + "name": "دولاب هواء", + "terms": "دولاب هواء; العجلة الكبيرة" + }, + "attraction/bumper_car": { + "name": "سيارة اصطدامية", + "terms": "سيارة اصطدامية" + }, + "attraction/carousel": { + "name": "دوامة خيل", + "terms": "دوامة خيل" + }, + "attraction/maze": { + "name": "متاهة", + "terms": "متاهة" + }, + "attraction/pirate_ship": { + "name": "سفينة قراصنة", + "terms": "سفينة قراصنة" + }, + "attraction/roller_coaster": { + "name": "السفينة الدوارة", + "terms": "سفينة دوارة" + }, "barrier": { "name": "حاجز", "terms": "حاجز, عائق, تخم, قلعة محصنة, مدينة محصنة, مزلقان" @@ -2517,18 +2792,26 @@ "name": "عمود صلب", "terms": "عمود صلب" }, + "barrier/border_control": { + "name": "معبر حدودي", + "terms": "معبر حدودي" + }, "barrier/cattle_grid": { "name": "شبكة الماشية", "terms": "شبكة الماشية,شبكة لمنع الماشية" }, "barrier/city_wall": { "name": "جدار المدينة", - "terms": "جدار المدينة" + "terms": "جدار المدينة; سور" }, "barrier/cycle_barrier": { "name": "حاجز دراجات هوائية", "terms": "حاجز دراجات هوائية; حاجز; ممر; حاجز مرور; حاجز دراجات" }, + "barrier/ditch": { + "name": "خندق", + "terms": "خندق" + }, "barrier/entrance": { "name": "مدخل" }, @@ -2635,7 +2918,8 @@ "terms": "جراج; جراج سيارات; موقف; موقف سيارات; ركن; ركنة" }, "building/greenhouse": { - "name": "دفيئة زراعية" + "name": "دفيئة زراعية", + "terms": "دفيئة زراعية; بيت بلاستيكي; بيت زجاجي" }, "building/hospital": { "name": "مبنى مستشفى", @@ -2661,6 +2945,10 @@ "name": "مبنى روضة أطفال", "terms": "روضة; أطفال" }, + "building/mosque": { + "name": "مبنى المسجد", + "terms": "مبنى المسجد" + }, "building/public": { "name": "مبنى عمومي", "terms": "عام; عمومي" @@ -2685,11 +2973,52 @@ "name": "مبنى شبه منفصل", "terms": "" }, + "building/shed": { + "name": "سقيفة", + "terms": "سقيفة; بيت" + }, + "building/stable": { + "name": "إسطبل", + "terms": "إسطبل" + }, + "building/stadium": { + "name": "مبنى الملعب", + "terms": "مبنى الملعب" + }, + "building/temple": { + "name": "مبنى المعبد", + "terms": "مبنى المعبد" + }, + "building/terrace": { + "name": "صف منازل", + "terms": "صف منازل" + }, "building/train_station": { "name": "محطة قطار" }, + "building/transportation": { + "name": "مبنى للنقل العام", + "terms": "مبنى للنقل العام" + }, "building/university": { - "name": "مبنى جامعي" + "name": "مبنى جامعي", + "terms": "جامعة; كلية" + }, + "building/warehouse": { + "name": "مستودع", + "terms": "مستودع; مخزن" + }, + "club": { + "name": "نادي", + "terms": "نادي" + }, + "craft": { + "name": "حرفة", + "terms": "حرفة" + }, + "craft/basket_maker": { + "name": "صانع السلال", + "terms": "صانع السلال" }, "craft/beekeeper": { "name": "مربي النحل", @@ -2712,7 +3041,8 @@ "terms": "بيرة; جعة" }, "craft/carpenter": { - "name": "نجار" + "name": "نجار", + "terms": "نجار" }, "craft/caterer": { "name": "منظم حفلات", @@ -2730,41 +3060,99 @@ "name": "كهربائي", "terms": "كهربائي" }, + "craft/electronics_repair": { + "name": "خدمة تصليح الأجهزة الإلكترونية", + "terms": "خدمة تصليح الأجهزة الإلكترونية" + }, "craft/gardener": { - "name": "بستاني" + "name": "بستاني", + "terms": "بستاني" + }, + "craft/handicraft": { + "name": "حرفي", + "terms": "حرفي" }, "craft/jeweler": { "name": "بائع مجوهرات" }, + "craft/locksmith": { + "name": "قفال - صانع أقفال" + }, + "craft/metal_construction": { + "name": "البناء المعدني", + "terms": "البناء المعدني" + }, "craft/painter": { - "name": "دهّان" + "name": "دهّان", + "terms": "دهّان" }, "craft/photographer": { - "name": "مصور" + "name": "مصور", + "terms": "مصور" + }, + "craft/photographic_laboratory": { + "name": "مختبر التصوير", + "terms": "مختبر التصوير" }, "craft/plumber": { - "name": "سمكري" + "name": "سباك", + "terms": "سباك; سمكري" }, "craft/pottery": { "name": "مصنع فخار وخزف", "terms": "فخار; خزف; بورسلين" }, + "craft/roofer": { + "name": "بنّاء السقف", + "terms": "بنّاء السقف" + }, "craft/saddler": { - "name": "صانع سراج" + "name": "صانع سراج", + "terms": "صانع سراج" + }, + "craft/sailmaker": { + "name": "صانع أشرعة", + "terms": "صانع أشرعة" + }, + "craft/sawmill": { + "name": "منشرة", + "terms": "منشرة" + }, + "craft/scaffolder": { + "name": "مركب السقالة", + "terms": "مركب السقالة" + }, + "craft/sculptor": { + "name": "نحّات", + "terms": "نحّات" }, "craft/shoemaker": { - "name": "إسكافي" + "name": "إسكافي", + "terms": "إسكافي" }, "craft/tailor": { "name": "خياط" }, "craft/tiler": { - "name": "خياط" + "name": "مركِّب البلاط", + "terms": "مركِّب البلاط" + }, + "craft/upholsterer": { + "name": "منجد", + "terms": "منجد; تنجيد; أثاث" + }, + "craft/watchmaker": { + "name": "ساعاتي (ساعات يدوية)", + "terms": "ساعاتي" }, "emergency/ambulance_station": { "name": "محطة إسعاف", "terms": "محطة إسعاف, محطة اسعاف" }, + "emergency/defibrillator": { + "name": "مزيل الرجفان", + "terms": "مزيل الرجفان" + }, "emergency/fire_hydrant": { "name": "خرطوم إطفاء", "terms": "خرطوم; مطافئ; إطفاء; اطفاء" @@ -2793,6 +3181,58 @@ "name": "ممر مائي", "terms": "ممر مائي; ممر; مائي; ماء" }, + "healthcare": { + "name": "مرفق الرعاية الصحية", + "terms": "مرفق الرعاية الصحية" + }, + "healthcare/alternative": { + "name": "متخصص في الطب البديل", + "terms": "متخصص في الطب البديل" + }, + "healthcare/alternative/chiropractic": { + "name": "المعالج للأمراض يدويا", + "terms": "المعالج للأمراض يدويا; مقوم العظام" + }, + "healthcare/audiologist": { + "name": "أخصائي السمع", + "terms": "أخصائي السمع" + }, + "healthcare/blood_donation": { + "name": "مركز التبرع بالدم", + "terms": "تبرع بالدم" + }, + "healthcare/laboratory": { + "name": "مختبر طبي", + "terms": "مختبر طبي; مخبر التحاليل الطبية" + }, + "healthcare/occupational_therapist": { + "name": "أخصائي العلاج الوظيفي", + "terms": "أخصائي العلاج الوظيفي" + }, + "healthcare/optometrist": { + "name": "أخصائي البصريات", + "terms": "أخصائي البصريات" + }, + "healthcare/physiotherapist": { + "name": "أخصائي العلاج الطبيعي", + "terms": "أخصائي العلاج الطبيعي" + }, + "healthcare/podiatrist": { + "name": "طبيب الأقدام", + "terms": "طبيب الأقدام; الأرجل" + }, + "healthcare/psychotherapist": { + "name": "معالج نفسي", + "terms": "معالج نفسي" + }, + "healthcare/rehabilitation": { + "name": "مركز إعادة التأهيل", + "terms": "مركز إعادة التأهيل" + }, + "healthcare/speech_therapist": { + "name": "معالج النطق", + "terms": "معالج النطق، نطق" + }, "highway": { "name": "طريق سريع" }, @@ -2800,6 +3240,13 @@ "name": "طريق الخيول", "terms": "طريق الخيول, ممر للخيول" }, + "highway/bus_stop": { + "name": "موقف حافلات" + }, + "highway/corridor": { + "name": "ممر داخلي", + "terms": "ممر داخلي; رواق" + }, "highway/crossing": { "name": "معبر طريق", "terms": "معبر; عبور; عبور طريق; عبور شارع; معبر شارع; معبر طريق" @@ -2812,10 +3259,18 @@ "name": "مسار دراجات", "terms": "طريق دراجات; مسار دراجات" }, + "highway/elevator": { + "name": "مصعد", + "terms": "مصعد" + }, "highway/footway": { "name": "طريق مشي بالأقدام", "terms": "ممشى بالأقدام" }, + "highway/give_way": { + "name": "إشارة \"أفسح الطريق\"", + "terms": "أفسح الطريق" + }, "highway/living_street": { "name": "شارع سكني", "terms": "شارع سكني" @@ -2839,6 +3294,14 @@ "name": "طريق", "terms": "طريق , ممر , مسلك , درب" }, + "highway/pedestrian_area": { + "name": "منطقة للمشاة", + "terms": "منطقة للمشاة" + }, + "highway/pedestrian_line": { + "name": "شارع للمشاة", + "terms": "شارع للمشاة" + }, "highway/primary": { "name": "طريق رئيسي", "terms": "شارع رئيسي" @@ -2847,6 +3310,10 @@ "name": "رابط لطريق رئيسي", "terms": "رابط لطريق رئيسي" }, + "highway/raceway": { + "name": "مضمار سباق السيارات والدراجات النارية", + "terms": "مضمار سباق، سيارات، دراجات نارية" + }, "highway/residential": { "name": "طريق سكني", "terms": "شارع سكني" @@ -2896,7 +3363,8 @@ "terms": "خدمة سيارات; منطقة خدمة سيارات; منطقة خدمية" }, "highway/speed_camera": { - "name": "كاميرا مراقبة" + "name": "كاميرا مراقبة السرعة", + "terms": "كاميرا مراقبة السرعة" }, "highway/steps": { "name": "درج", @@ -2907,7 +3375,8 @@ "terms": "إشارة توقف، ممنوع الوقوف، قف" }, "highway/street_lamp": { - "name": "مصباح الشارع" + "name": "مصباح الشارع", + "terms": "مصباح الشارع" }, "highway/tertiary": { "name": "طريق ثالثي", @@ -2941,6 +3410,10 @@ "name": "دائرة رجوع", "terms": "دائرة رجوع" }, + "highway/unclassified": { + "name": "طريق غير مصنف", + "terms": "طريق غير مصنف" + }, "historic": { "name": "موقع تاريخي", "terms": "موقع تأريخي" @@ -2954,8 +3427,8 @@ "terms": "صخرة حدودية" }, "historic/castle": { - "name": "حصن", - "terms": "حصن" + "name": "حصن / قلعة", + "terms": "حصن; قلعة; قصر" }, "historic/memorial": { "name": "نصب تذكاري", @@ -2969,16 +3442,25 @@ "name": "آثار", "terms": "أطلال" }, + "historic/tomb": { + "name": "قبر / ضريح", + "terms": "قبر، ضريح" + }, "historic/wayside_shrine": { "name": "مقام نصراني على الطريق", "terms": "مقام نصراني على الطريق" }, + "junction": { + "name": "مفترق طرق", + "terms": "مفترق طرق" + }, "landuse": { "name": "أرض", "terms": "<ترجم بالمصطلحات أو المرادفات لـ \"الأراضي\"، فاصلا المدخلات بالفاصلة \",\">" }, "landuse/aquaculture": { - "name": "مزرعة سمكية" + "name": "مزرعة سمكية", + "terms": "مزرعة سمكية" }, "landuse/basin": { "name": "حوض", @@ -3000,7 +3482,8 @@ "name": "أرض زراعية" }, "landuse/farmland": { - "name": "أرض زراعية" + "name": "أرض زراعية", + "terms": "أرض زراعية، فلاحة" }, "landuse/farmyard": { "name": "فناء المزرعة", @@ -3014,10 +3497,30 @@ "name": "عشب", "terms": "عشب, غطاء أخضر" }, + "landuse/greenhouse_horticulture": { + "name": "الدفيئات الزراعية", + "terms": "الدفيئات الزراعية" + }, + "landuse/harbour": { + "name": "مرفأ", + "terms": "مرفأ، ميناء" + }, "landuse/industrial": { "name": "منطقة صناعية", "terms": "صناعية; صناعي; صناعات; منطقة صناعات; منطقة صناعة; صناعة; صنع" }, + "landuse/industrial/scrap_yard": { + "name": "مقبرة السيارات", + "terms": "مقبرة السيارات" + }, + "landuse/industrial/slaughterhouse": { + "name": "مسلخ", + "terms": "مسلخ" + }, + "landuse/landfill": { + "name": "مكب نفايات", + "terms": "مكب نفايات" + }, "landuse/meadow": { "name": "مرج", "terms": " مرج, روضة, مخضرة" @@ -3026,6 +3529,22 @@ "name": "منطقة عسكرية", "terms": "جيش, قوات مسلحة, عسكرية" }, + "landuse/military/airfield": { + "name": "قاعدة جوية", + "terms": "قاعدة جوية، مطار عسكري" + }, + "landuse/military/barracks": { + "name": "ثكنة عسكرية", + "terms": "ثكنة عسكرية" + }, + "landuse/military/bunker": { + "name": "ملجأ عسكري", + "terms": "ملجأ عسكري" + }, + "landuse/military/checkpoint": { + "name": "نقطة تفتيش عسكرية", + "terms": "نقطة تفتيش عسكرية" + }, "landuse/military/danger_area": { "name": "منطقة خطرة", "terms": "منطقة خطر; خطر" @@ -3034,11 +3553,16 @@ "name": "قاعدة بحرية", "terms": "بحرية; بحري; بحر; قاعدة" }, + "landuse/military/nuclear_explosion_site": { + "name": "موقع الانفجار النووي", + "terms": "موقع الانفجار النووي" + }, "landuse/military/office": { "name": "مكتب عسكري" }, "landuse/military/range": { - "name": "نطاق عسكري" + "name": "ميدان الرماية العسكرية", + "terms": "ميدان الرماية العسكرية" }, "landuse/military/training_area": { "name": "منطقة تدريب", @@ -3056,6 +3580,14 @@ "name": "محجر", "terms": "محجر" }, + "landuse/railway": { + "name": "منطقة السكك الحديدية", + "terms": "منطقة السكك الحديدية" + }, + "landuse/recreation_ground": { + "name": "ميدان الألعاب", + "terms": "ميدان الألعاب" + }, "landuse/residential": { "name": "منطقة سكنية", "terms": "منطقة سكانية; سكان; سكنية; سكن; منطقة سكن" @@ -3072,6 +3604,10 @@ "name": "الترفيه", "terms": "الترفيه" }, + "leisure/beach_resort": { + "name": "منتجع الشاطئ", + "terms": "منتجع الشاطئ" + }, "leisure/bowling_alley": { "name": "بولينغ", "terms": "بولينغ، بولينج" @@ -3084,6 +3620,10 @@ "name": "قاعة الرقص", "terms": "قاعة الرقص" }, + "leisure/dancing_school": { + "name": "مدرسة الرقص", + "terms": "مدرسة الرقص" + }, "leisure/dog_park": { "name": "حديقة كلاب", "terms": "حديقة كلاب" @@ -3102,7 +3642,7 @@ }, "leisure/golf_course": { "name": "معلب جولف", - "terms": "معلب جولف" + "terms": "معلب جولف، غولف" }, "leisure/horse_riding": { "name": "منشأة ركوب خيل", @@ -3116,12 +3656,17 @@ "name": "مرسى السفن", "terms": "حوض سفن, رصيف سفن, مرسى سفن" }, + "leisure/miniature_golf": { + "name": "ملعب الجولف المصغرة", + "terms": "ملعب الجولف المصغرة، غولف" + }, "leisure/nature_reserve": { - "name": "محمية طبيعية" + "name": "محمية طبيعية", + "terms": "محمية طبيعية" }, "leisure/park": { - "name": "حديقة", - "terms": "منتزه" + "name": "منتزه", + "terms": "منتزه، حديقة" }, "leisure/pitch": { "name": "ملعب رياضي", @@ -3139,10 +3684,30 @@ "name": "ملعب كرة السلة", "terms": "ملعب كرة السلة" }, + "leisure/pitch/beachvolleyball": { + "name": "ملعب كرة الطائرة الشاطئية", + "terms": "ملعب" + }, + "leisure/pitch/boules": { + "name": "ملعب كرة حديدية", + "terms": "ملعب كرة حديدية" + }, + "leisure/pitch/cricket": { + "name": "ملعب كريكت", + "terms": "ملعب كريكت" + }, "leisure/pitch/equestrian": { "name": "حلبة ركوب خيل", "terms": "حلبة; ساحة; حلبة ركوب; ساحة ركوب; خيل; ركوب خيل" }, + "leisure/pitch/rugby_league": { + "name": "ملعب اتحاد الرغبي", + "terms": "ملعب اتحاد الرغبي، رجبي" + }, + "leisure/pitch/rugby_union": { + "name": "ملعب دوري الرغبي", + "terms": "ملعب دوري الرغبي، رجبي" + }, "leisure/pitch/skateboard": { "name": "حديقة تزلج", "terms": "حديقة تزلج، ساحة تزلج" @@ -3151,6 +3716,10 @@ "name": "ملعب كرة القدم", "terms": "ملعب كرة القدم" }, + "leisure/pitch/table_tennis": { + "name": "طاولة كرة المضرب", + "terms": "طاولة كرة المضرب" + }, "leisure/pitch/tennis": { "name": "ملعب تنس", "terms": "معلب كرة التنس" @@ -3167,13 +3736,21 @@ "name": "منتجع", "terms": "منتجع" }, + "leisure/running_track": { + "name": "مضمار ركض", + "terms": "مضمار ركض" + }, + "leisure/sauna": { + "name": "سونا", + "terms": "سونا" + }, "leisure/slipway": { "name": "مزلقة سفن", "terms": "مزلقة سفن" }, "leisure/sports_centre": { "name": "مركز رياضي", - "terms": " مركز رياضي، نادي رياضي " + "terms": " مركز رياضي; نادي رياضي; مجمع رياضي" }, "leisure/sports_centre/swimming": { "name": "مبنى حوض سباحة", @@ -3193,7 +3770,7 @@ }, "leisure/water_park": { "name": "ملاهي مائية", - "terms": "ملاهي مائية" + "terms": "ملاهي مائية; حديقة مائية; منتزه مائي" }, "line": { "name": "طريق", @@ -3216,22 +3793,40 @@ "terms": "جسر" }, "man_made/chimney": { - "name": "مدخنة" + "name": "مدخنة", + "terms": "مدخنة" + }, + "man_made/crane": { + "name": "رافعة", + "terms": "رافعة" }, "man_made/cutline": { "name": "خط الفصل", "terms": "خط الفصل" }, + "man_made/flagpole": { + "name": "سارية العلم", + "terms": "سارية العلم" + }, "man_made/lighthouse": { "name": "منارة", "terms": "منارة , فنارة" }, + "man_made/monitoring_station": { + "name": "محطة الرصد", + "terms": "محطة الرصد" + }, "man_made/observation": { "name": "برج مراقبة", "terms": "برمج المراقبة، أبراج المراقبة، أبراج المشاهدة، " }, + "man_made/observatory": { + "name": "مرصد", + "terms": "مرصد" + }, "man_made/petroleum_well": { - "name": "بئر نفط" + "name": "بئر نفط", + "terms": "بئر نفط، بترول" }, "man_made/pier": { "name": "رصيف بحري", @@ -3242,20 +3837,24 @@ "terms": "خط أنابيب" }, "man_made/pumping_station": { - "name": "محطة ضخ" + "name": "محطة ضخ", + "terms": "محطة ضخ" }, "man_made/silo": { "name": "صومعة", "terms": "صومعة; صومعة غلال" }, "man_made/storage_tank": { - "name": "خزان" + "name": "خزان", + "terms": "خزان" }, "man_made/surveillance": { - "name": "مراقبة" + "name": "مراقبة", + "terms": "مراقبة" }, "man_made/surveillance_camera": { - "name": "كاميرا مراقبة" + "name": "كاميرا مراقبة", + "terms": "كاميرا مراقبة" }, "man_made/survey_point": { "name": "نقطة مسح", @@ -3274,7 +3873,8 @@ "terms": "خزان مائي" }, "man_made/water_well": { - "name": "بئر ماء" + "name": "بئر ماء", + "terms": "بئر ماء" }, "man_made/water_works": { "name": "محطة مياه", @@ -3284,6 +3884,10 @@ "name": "طاحونة مائية", "terms": "طاحونة مائية" }, + "man_made/windmill": { + "name": "طاحونة هوائية", + "terms": "طاحونة هوائية" + }, "man_made/works": { "name": "مصنع", "terms": "مصنع" @@ -3332,34 +3936,53 @@ "name": "مرج", "terms": "مرج" }, + "natural/mud": { + "name": "وحل", + "terms": "وحل، طين" + }, "natural/peak": { "name": "قمة", "terms": "قمة, ذروة" }, + "natural/reef": { + "name": "شعاب", + "terms": "شعاب" + }, + "natural/ridge": { + "name": "نتوء جبلي", + "terms": "نتوء جبلي، قمة جبل" + }, + "natural/saddle": { + "name": "ممر جبلي", + "terms": "ممر جبلي" + }, "natural/sand": { - "name": "رمل" + "name": "رمل", + "terms": "رمل" }, "natural/scree": { "name": "ركام حجارة", "terms": "ركام حجارة، تلة، مجموعة صخور، تلة حصاة" }, "natural/scrub": { - "name": "أدغال", - "terms": "دغل; أدغال" + "name": "أراضي الأشجار القمئية", + "terms": "دغل; أدغال; أراضي الأشجار القمئية" }, "natural/spring": { "name": "نبع", - "terms": "نبع" + "terms": "نبع; منبع" }, "natural/tree": { "name": "شجرة", "terms": "شجرة" }, "natural/tree_row": { - "name": "خط أشجار" + "name": "خط الأشجار", + "terms": "خط الأشجار; صف من الأشجار" }, "natural/volcano": { - "name": "بركان" + "name": "بركان", + "terms": "بركان" }, "natural/water": { "name": "مياه", @@ -3379,7 +4002,7 @@ }, "natural/wetland": { "name": "أرض رطبة", - "terms": "أرض رطبة" + "terms": "أرض رطبة; مستنقع; هور" }, "natural/wood": { "name": "غابة أخشاب", @@ -3410,14 +4033,19 @@ }, "office/association": { "name": "جمعية ", - "terms": "جمعية، منظمة غير ربحية " + "terms": "جمعية، منظمة غير ربحية" }, "office/charity": { "name": "منظمة خيرية", "terms": "منظمة خيرية" }, "office/company": { - "name": "مكتب شركة" + "name": "مكتب شركة", + "terms": "إدارة شركة، إدارة مؤسسة، إدارة عامة" + }, + "office/coworking": { + "name": "مساحة عمل مشتركة", + "terms": "مساحة عمل مشتركة" }, "office/educational_institution": { "name": "مؤسسة تعليمية ", @@ -3427,6 +4055,10 @@ "name": "مكتب التوظيف ", "terms": "إدارة شؤون الموظفين، مكتب العمل" }, + "office/energy_supplier": { + "name": "شركة مرافق الكهرباء", + "terms": "شركة مرافق الكهرباء" + }, "office/estate_agent": { "name": "مكتب عقاري", "terms": "الطابو، دائرة السجل العقاري، إدارة تسجيل الممتلكات" @@ -3448,17 +4080,25 @@ "terms": "رئاسة الوزراء، إدارة الدولة، المكتب العام، " }, "office/government/register_office": { - "name": "مكتب تسجيل", - "terms": "مكتب تسجيل" + "name": "مكتب السجل المدني", + "terms": "مكتب السجل المدني" }, "office/government/tax": { "name": "مكتب الضرائب", "terms": "مكتب الضرائب" }, + "office/guide": { + "name": "مكتب الدليل السياحي", + "terms": "مكتب الدليل السياحي; مكتب المرشد السياحي" + }, "office/insurance": { "name": "مكتب تأمينات", "terms": "مديرية المعاشات، دائرة التأمينات الاجتماعية، إدارة التأمين" }, + "office/it": { + "name": "متخصص في تكنولوجيا المعلومات", + "terms": "متخصص في تكنولوجيا المعلومات; معلوماتية" + }, "office/lawyer": { "name": "مكتب قانوني ", "terms": "مكتب محاماة، اﻹدارة القانونية، المحكمة،" @@ -3520,6 +4160,10 @@ "name": "شركة المياه", "terms": "شركة المياه" }, + "piste": { + "name": "منحدر تزلج", + "terms": "منحدر تزلج" + }, "place": { "name": "قصر" }, @@ -3538,6 +4182,10 @@ "name": "جزيرة", "terms": "جزيرة" }, + "place/islet": { + "name": "جزيرة صغيرة", + "terms": "جزيرة صغيرة" + }, "place/isolated_dwelling": { "name": "مساكن متفرقة", "terms": "مساكن متفرقة" @@ -3547,11 +4195,16 @@ "terms": "موقع" }, "place/neighbourhood": { - "name": "حي سكني" + "name": "حي سكني", + "terms": "حي سكني" + }, + "place/plot": { + "name": "قطعة الأرض", + "terms": "قطعة الأرض" }, "place/square": { "name": "ساحة", - "terms": "ساحة" + "terms": "ساحة; باحة; ممشى" }, "place/suburb": { "name": "ضاحية", @@ -3607,6 +4260,10 @@ "name": "محطة فرعية", "terms": "محطة فرعية" }, + "power/switch": { + "name": "معدة وصل وفصل", + "terms": "معدة وصل وفصل" + }, "power/tower": { "name": "برج عالي الجهد", "terms": "برج عالي الجهد, برج تيار عالي الجهد, تيار عالي الجهد" @@ -3615,6 +4272,34 @@ "name": "محول كهربائي", "terms": "محول الكهربائي" }, + "public_transport/linear_platform_bus": { + "name": "موقف حافلات", + "terms": "موقف حافلات" + }, + "public_transport/linear_platform_train": { + "name": "رصيف سكة حديد", + "terms": "رصيف سكة حديد" + }, + "public_transport/platform_train": { + "name": "رصيف سكة حديد", + "terms": "رصيف سكة حديد" + }, + "public_transport/station_aerialway": { + "name": "محطة النقل بالكابلات", + "terms": "محطة النقل بالكابلات; محطة تلفريك" + }, + "public_transport/station_bus": { + "name": "محطة الحافلات", + "terms": "محطة الحافلات" + }, + "public_transport/station_subway": { + "name": "محطة مترو", + "terms": "محطة مترو" + }, + "public_transport/station_train": { + "name": "محطة القطار", + "terms": "محطة القطار" + }, "railway": { "name": "سكة حديد" }, @@ -3638,18 +4323,35 @@ "name": "قطار جبلي مائل", "terms": "قطار جبلي مائل" }, + "railway/halt": { + "name": "موقف القطار" + }, "railway/level_crossing": { "name": "معبر سكة حديد (طريق)", "terms": "معبر سكة حديد; معبر" }, + "railway/light_rail": { + "name": "قطار خفيف", + "terms": "قطار خفيف" + }, "railway/monorail": { "name": "سكة حديدة مفردة", "terms": "سكة حديدة مفردة" }, + "railway/platform": { + "name": "رصيف سكة حديد" + }, "railway/rail": { "name": "قطار", "terms": "قطار" }, + "railway/signal": { + "name": "إشارات المرور ( السكك الحديدية )", + "terms": "إشارة المرور " + }, + "railway/station": { + "name": "محطة سكة حديد" + }, "railway/subway": { "name": "مترو الأنفاق", "terms": "مترو الأنفاق" @@ -3662,10 +4364,16 @@ "name": "ترام", "terms": "ترام" }, + "railway/tram_stop": { + "name": "موقف ترام" + }, "relation": { "name": "علاقة", "terms": "علاقة" }, + "roundabout": { + "name": "دوار مروري" + }, "route/ferry": { "name": "مسار عبّارة", "terms": "مسار عبّارة, مسار سفن" @@ -3678,6 +4386,14 @@ "name": "محل خمور", "terms": "محل خمور" }, + "shop/appliance": { + "name": "متجر الأجهزة المنزلية", + "terms": "متجر الأجهزة المنزلية" + }, + "shop/art": { + "name": "متجر الفنون", + "terms": "متجر فنون" + }, "shop/baby_goods": { "name": "متجر سلع أطفال" }, @@ -3689,6 +4405,9 @@ "name": "مخبز", "terms": "مخبز" }, + "shop/bathroom_furnishing": { + "name": "متجر أثاث الحمام" + }, "shop/beauty": { "name": "محل تجميل", "terms": "محل تجميل" @@ -3702,7 +4421,8 @@ "terms": "محل دراجات هوائية; متجر دراجات; محل دراجات; بائع دراجات" }, "shop/books": { - "name": "متجر كتب" + "name": "متجر كتب", + "terms": "مكتبة، كتب" }, "shop/boutique": { "name": "بوتيك", @@ -3712,6 +4432,10 @@ "name": "جزار", "terms": "جزار, محل بيع لحوم. محل جزارة, لحوم" }, + "shop/candles": { + "name": "متجر الشموع", + "terms": "متجر الشموع" + }, "shop/car": { "name": "وكالة سيارات", "terms": "وكالة سيارات" @@ -3725,10 +4449,12 @@ "terms": "محل تصليح سيارات; ورشة تصليح; ورشة; ميكانيكي" }, "shop/carpet": { - "name": "متجر سجاد" + "name": "متجر سجاد", + "terms": "متجر سجاد; زرابي" }, "shop/cheese": { - "name": "متجر أجبان" + "name": "متجر أجبان", + "terms": "متجر أجبان" }, "shop/chocolate": { "name": "متجر شوكولاتة" @@ -3737,6 +4463,10 @@ "name": "محل ملابس", "terms": "محل بيع ملابس" }, + "shop/coffee": { + "name": "متجر القهوة", + "terms": "متجر القهوة" + }, "shop/computer": { "name": "محل حاسوب", "terms": "محل حاسوب" @@ -3752,6 +4482,22 @@ "shop/copyshop": { "name": "متجر نسخ وتصوير" }, + "shop/cosmetics": { + "name": "متجر مستحضرات التجميل", + "terms": "متجر مستحضرات التجميل" + }, + "shop/craft": { + "name": "متجر الفنون والحرف", + "terms": "متجر الفنون والحرف" + }, + "shop/curtain": { + "name": "محل بيع الستائر", + "terms": "ستائر" + }, + "shop/dairy": { + "name": "متجر الألبان", + "terms": "متجر الألبان، الألبان" + }, "shop/deli": { "name": "محل أطعمة لذيذة", "terms": "محل أطعمة لذيذة, ديلي" @@ -3768,6 +4514,10 @@ "name": "محل إلكترونيات", "terms": "محل إلكترونيات" }, + "shop/fabric": { + "name": "محل بيع الأقمشة", + "terms": "الأقمشة" + }, "shop/farm": { "name": "المنتج", "terms": "المنتج" @@ -3803,18 +4553,42 @@ "name": "محل أجهزة", "terms": "محل بيع عتاد" }, + "shop/hearing_aids": { + "name": "متجر السماعات الأذن الطبية", + "terms": "سماعات الأذن الطبية; معينات سمعية; أجهزة تقوية السمع; مساعدات السمع" + }, + "shop/herbalist": { + "name": "محل بيع الأعشاب الطبية", + "terms": "محل بيع الأعشاب الطبية" + }, "shop/hifi": { "name": "محل بيع أجهزة عالية الدقة", "terms": "محل بيع أجهزة عالية الدقة" }, + "shop/houseware": { + "name": "متجر الأدوات المنزلية", + "terms": "متجر الأدوات المنزلية" + }, + "shop/interior_decoration": { + "name": "متجر الديكور الداخلي", + "terms": "متجر الديكور الداخلي" + }, "shop/jewelry": { "name": "محل بيع مجوهرات", "terms": "محل بيع المجوهرات, محل بيع الذهب" }, + "shop/kiosk": { + "name": "كشك", + "terms": "كشك" + }, "shop/laundry": { "name": "محل غسيل ملابس", "terms": "غسيل ملابس" }, + "shop/leather": { + "name": "متجر المنتجات الجلدية", + "terms": "متجر المنتجات الجلدية" + }, "shop/locksmith": { "name": "محل أقفال", "terms": "صانع اﻷقفال، أقفال، حداد، " @@ -3823,6 +4597,14 @@ "name": "مركز تسوق مول", "terms": "مركز تسوق, مول" }, + "shop/massage": { + "name": "صالون التدليك", + "terms": "صالون التدليك" + }, + "shop/medical_supply": { + "name": "متجر مستلزمات طبية", + "terms": "متجر مستلزمات طبية" + }, "shop/mobile_phone": { "name": "محل بيع هواتف", "terms": "محل بيع هواتف" @@ -3835,10 +4617,38 @@ "name": "محل بيع موسيقى", "terms": "محل بيع الموسيقى" }, + "shop/musical_instrument": { + "name": "محل بيع الآلات الموسيقية", + "terms": "محل بيع الآلات الموسيقية" + }, + "shop/newsagent": { + "name": "محل بيع الجرائد", + "terms": "جرائد" + }, + "shop/nutrition_supplements": { + "name": "متجر المكملات الغذائية", + "terms": "متجر المكملات الغذائية، مكملات غذائية" + }, "shop/optician": { "name": "محل بيع نظارات", "terms": "محل بيع نظارات" }, + "shop/organic": { + "name": "محل بيع المنتجات العضوية", + "terms": "منتجات عضوية" + }, + "shop/paint": { + "name": "متجر الطلاء", + "terms": "طلاء" + }, + "shop/pastry": { + "name": "متجر الحلويات", + "terms": "متجر الحلويات" + }, + "shop/perfumery": { + "name": "متجر العطور", + "terms": "عطور" + }, "shop/pet": { "name": "محل حيوانات أليفة", "terms": "محل حيوانات أليفة" @@ -3851,6 +4661,18 @@ "name": "متجر ألعاب نارية", "terms": "ألعاب نارية" }, + "shop/radiotechnics": { + "name": "متجر المكونات الإلكترونية", + "terms": "متجر المكونات الإلكترونية" + }, + "shop/seafood": { + "name": "مسمكة / متجر المأكولات البحرية", + "terms": "مأكولات بحرية، مسمكة ، سمك" + }, + "shop/second_hand": { + "name": "محل لبيع البضائع المستعملة", + "terms": "محل لبيع البضائع المستعملة" + }, "shop/shoes": { "name": "محل بيع أحذية", "terms": "محل بيع أحذية" @@ -3867,6 +4689,26 @@ "name": "سوبر ماركت", "terms": "سوبرماركت, متجر كبير" }, + "shop/tailor": { + "name": "خياط", + "terms": "خياط" + }, + "shop/tea": { + "name": "محل بيع الشاي", + "terms": "محل بيع الشاي، شاي" + }, + "shop/ticket": { + "name": "بائع التذاكر", + "terms": "بائع التذاكر; تذاكر" + }, + "shop/tiles": { + "name": "محل بيع البلاط", + "terms": "محل بيع البلاط، بلاط، خزف" + }, + "shop/tobacco": { + "name": "محل بيع التبغ", + "terms": "تبغ، سيجارة" + }, "shop/toys": { "name": "محل ألعاب", "terms": "محل ألعاب" @@ -3882,6 +4724,10 @@ "shop/vacant": { "name": "محل شاغر" }, + "shop/vacuum_cleaner": { + "name": "متجر المكنسات الكهربائية", + "terms": "متجر المكنسات الكهربائية; مكنسات كهربائية" + }, "shop/variety_store": { "name": "محل كل شيء ", "terms": "محل كل شيء, محل بالجملة" @@ -3894,9 +4740,17 @@ "name": "متجر العاب الفيديو", "terms": "متجر العاب الفيديو" }, + "shop/watches": { + "name": "متجر الساعات اليدوية", + "terms": "متجر الساعات اليدوية" + }, "shop/weapons": { "name": "متجر أسلحة" }, + "shop/wholesale": { + "name": "محل بيع بالجملة", + "terms": "محل بيع بالجملة" + }, "shop/wine": { "name": "متجر نبيذ" }, @@ -3905,11 +4759,16 @@ "terms": "سياحة" }, "tourism/alpine_hut": { - "name": "داراستراحة", + "name": "كوخ جبلي", "terms": "دار استراحة" }, + "tourism/apartment": { + "name": "شقة سياحية", + "terms": "شقة سياحية" + }, "tourism/aquarium": { - "name": "حوض سمك" + "name": "حوض سمك", + "terms": "حوض سمك" }, "tourism/artwork": { "name": "عمل فني", @@ -3919,16 +4778,25 @@ "name": "معلم سياحي", "terms": "معلم سياحي, مكان سياحي" }, + "tourism/camp_site": { + "name": "مكان التخييم", + "terms": "مكان التخييم" + }, "tourism/caravan_site": { "name": "موقف عربات كبيرة", "terms": "موقف عربات كبيرة" }, + "tourism/chalet": { + "name": "كوخ لقضاء العطلة", + "terms": "كوخ لقضاء العطلة" + }, "tourism/gallery": { - "name": "رواق فنون" + "name": "رواق الفنون", + "terms": "رواق الفنون، متحف الفنون" }, "tourism/guest_house": { - "name": "استراحة", - "terms": "استراحة" + "name": "دار الضيافة", + "terms": "دار الضيافة" }, "tourism/hostel": { "name": "نزل", @@ -3939,14 +4807,20 @@ "terms": "فندق" }, "tourism/information": { - "name": "معلومات", - "terms": "معلومات" + "name": "معلومات سياحية", + "terms": "معلومات سياحية" + }, + "tourism/information/board": { + "name": "لوحة المعلومات", + "terms": "لوحة المعلومات" }, "tourism/information/map": { - "name": "خريطة" + "name": "خريطة", + "terms": "خريطة" }, "tourism/information/office": { - "name": "مكتب معلومات السياحة" + "name": "مكتب المعلومات السياحية", + "terms": "مكتب المعلومات السياحية" }, "tourism/motel": { "name": "فندق رخيص", @@ -3976,6 +4850,10 @@ "name": "مخفف سرعة", "terms": "مطب; مخفف; مهديء; مهدئ; ممهل; تخفيف; تمهيل; مطب صناعي" }, + "traffic_calming/bump": { + "name": "مطب", + "terms": "مطب" + }, "type/boundary": { "name": "حدود", "terms": "حدود" @@ -3991,6 +4869,14 @@ "name": "قيود", "terms": "قيود" }, + "type/restriction/no_left_turn": { + "name": "ممنوع الإنعطاف لليسار", + "terms": "ممنوع الإنعطاف لليسار" + }, + "type/restriction/no_right_turn": { + "name": "ممنوع الإنعطاف لليمين", + "terms": "ممنوع الإنعطاف لليمين" + }, "type/restriction/no_u_turn": { "name": "لا يوجد دوران", "terms": "لا يوجد دوران" @@ -4017,7 +4903,7 @@ }, "type/route/bus": { "name": "مسار الباصات", - "terms": "مسار باصات" + "terms": "مسار باصات، حافلات" }, "type/route/detour": { "name": "مسار طريق جانبي", @@ -4039,10 +4925,18 @@ "name": "مسار ركوب", "terms": "مسار ركوب" }, + "type/route/light_rail": { + "name": "مسار القطار الخفيف", + "terms": "قطار خفيف، ترام" + }, "type/route/pipeline": { "name": "مسار خط أنابيب", "terms": "مسار خط أنابيب" }, + "type/route/piste": { + "name": "مسار التزلج", + "terms": "تزلج" + }, "type/route/power": { "name": "مسار خط كهربائي", "terms": "مسار الطاقة, مسار الكهرباء" @@ -4051,6 +4945,10 @@ "name": "مسار طريق", "terms": "مسار الطريق" }, + "type/route/subway": { + "name": "مسار مترو", + "terms": "مسار مترو" + }, "type/route/train": { "name": "مسار قطار", "terms": "مسار القطار" @@ -4067,6 +4965,10 @@ "name": "موقع", "terms": "موقع" }, + "type/waterway": { + "name": "مجرى مائي", + "terms": "مجرى مائي، ممر مائي" + }, "vertex": { "name": "أخرى", "terms": "أخرى" @@ -4075,8 +4977,8 @@ "name": "مجرى مائي" }, "waterway/boatyard": { - "name": "ساحة بناء المراكب", - "terms": "ساحة بناء المراكب" + "name": "حوض بناء سفن", + "terms": "حوض بناء سفن; ورشة" }, "waterway/canal": { "name": "قناة", @@ -4116,7 +5018,11 @@ }, "waterway/stream": { "name": "مجرى", - "terms": "مجرى" + "terms": "مجرى، جدول مائي" + }, + "waterway/stream_intermittent": { + "name": "مجرى متقطع", + "terms": "مجرى متقطع" }, "waterway/water_point": { "name": "مياه الشرب البحرية", @@ -4127,8 +5033,8 @@ "terms": "شلال" }, "waterway/weir": { - "name": "سد", - "terms": "سد" + "name": "هدار - سد صغير", + "terms": "هدار، سد صغير" } } }, diff --git a/vendor/assets/iD/iD/locales/ast.json b/vendor/assets/iD/iD/locales/ast.json index 87e66f121..a4bb0fac1 100644 --- a/vendor/assets/iD/iD/locales/ast.json +++ b/vendor/assets/iD/iD/locales/ast.json @@ -163,7 +163,6 @@ "annotation": "Meciéronse {n} carauterístiques.", "not_eligible": "Eses carauterístiques nun puen amestase", "not_adjacent": "Estos oxetos nun pueden fusionase porque los sos estremos nun tán coneutaos.", - "restriction": "Eses carauterístiques nun puen mecese porque una polo menos ye miembru d'una rellación \"{relation}\".", "incomplete_relation": "Estes carauterístiques nun puen entemecese porque polo menos una nun se descargó completamente.", "conflicting_tags": "Eses carauterístiques nun puen mecese porque dalgún valor de les etiquetes fai conflictu." }, @@ -577,12 +576,7 @@ } }, "success": { - "edited_osm": "¡Editáu OSM!", "just_edited": "¡Acaba d'editar OpenStreetMap!", - "view_on_osm": "Ver en OSM", - "facebook": "Compartir en Facebook", - "twitter": "Compartir en Twitter", - "google": "Compartir en Google+", "help_link_text": "Detalles" }, "confirm": { @@ -1612,7 +1606,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Teléfonu", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2018,9 +2011,6 @@ "label": "Tipu", "placeholder": "Predetermináu" }, - "vending": { - "label": "Tipu de mercancía" - }, "visibility": { "label": "Visibilidá", "options": { @@ -4461,15 +4451,6 @@ "type/restriction/no_u_turn": { "name": "Sin cambiu de sentíu" }, - "type/restriction/only_left_turn": { - "name": "Xirar sólo a la izquierda" - }, - "type/restriction/only_right_turn": { - "name": "Xirar sólo a la drecha" - }, - "type/restriction/only_straight_on": { - "name": "Xiru torgáu" - }, "type/route": { "name": "Ruta" }, @@ -4612,7 +4593,6 @@ "attribution": { "text": "Términos y comentarios " }, - "description": "Llendes de les imáxenes y dates de la toma. Les etiquetes apaecen col nivel d'ampliación 14 y mayor.", "name": "Imáxenes antigües de DigitalGlobe Premium" }, "DigitalGlobe-Standard": { @@ -4626,7 +4606,6 @@ "attribution": { "text": "Términos y comentarios " }, - "description": "Llendes de les imáxenes y dates de la toma. Les etiquetes apaecen col nivel d'ampliación 14 y mayor.", "name": "Imáxenes antigües de DigitalGlobe Standard" }, "EsriWorldImagery": { @@ -4722,7 +4701,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Mapa base d'Austria, basáu en datos del gobiernu.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -4783,9 +4761,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Mosaicu del mapa por Stamen Design, baxo CC BY 3.0" - }, "name": "Terrén Stamen" }, "tf-cycle": { diff --git a/vendor/assets/iD/iD/locales/bg-BG.json b/vendor/assets/iD/iD/locales/bg-BG.json deleted file mode 100644 index 935d0b745..000000000 --- a/vendor/assets/iD/iD/locales/bg-BG.json +++ /dev/null @@ -1,1642 +0,0 @@ -{ - "bg-BG": { - "modes": { - "add_area": { - "title": "Площ", - "description": "Добавяне на паркове, сгради, езера или други площи към картата.", - "tail": "Щракнете върху картата, за да започнете чертането на площен обект като парк, езеро или сграда." - }, - "add_line": { - "title": "Линия", - "description": "Добавяне на пътища, улици, пешеходни алеи, канали или други линейни обекти към картата.", - "tail": "Щракнете върху картата, за да започнете да чертаете път, пътека или маршрут." - }, - "add_point": { - "title": "Точка", - "description": "Добавяне на ресторанти, паметници, пощенски кутии или други точки към картата.", - "tail": "Щракнете върху картата за да добавите точка." - }, - "browse": { - "title": "Разглеждане", - "description": "Движете и увеличете картата." - }, - "draw_area": { - "tail": "Щракнете, за да добавите възли към вашия площен обект. Щракнете върху първия възел, за да завършите площния обект." - }, - "draw_line": { - "tail": "Щракнете, за да добавите още възли към линията. Щракнете върху други линии, за да ги свържете и двойно щракване, за да завършите линията." - } - }, - "operations": { - "add": { - "annotation": { - "point": "Добавена е точка.", - "vertex": "Добавен е възел към път.", - "relation": "Добавена е връзка" - } - }, - "start": { - "annotation": { - "line": "Започната е линия.", - "area": "Започнат е площен обект." - } - }, - "continue": { - "key": "A", - "title": "Продължи", - "description": "Продължи тази линия.", - "not_eligible": "Линията не може да бъде продължена.", - "multiple": "Няколко линии могат да бъдат продължени тук. За да изберете линия натиснете бутон Shift и кликнете върху линията, за да я изберете.", - "annotation": { - "line": "Продължена е линия.", - "area": "Продължен е площен обект." - } - }, - "cancel_draw": { - "annotation": "Чертането е отказано." - }, - "change_role": { - "annotation": "Сменена е ролята на член на релация." - }, - "change_tags": { - "annotation": "Променени са тагове." - }, - "circularize": { - "title": "Направете окръжност", - "description": { - "line": "Направете тази линия кръг.", - "area": "Превърнете този площен обект в окръжност." - }, - "key": "O", - "annotation": { - "line": "Линията е превърната в окръжност.", - "area": "Площният обект е превърнат в окръжност." - }, - "not_closed": "Този обект не може да стане кръг, защото не е затворен.", - "too_large": "Това не може да бъде направено кръгло, защото не достатъчна част от него е видима към момента.", - "connected_to_hidden": "Това не може да бъде кръгло, защото е свързано със скрит обект." - }, - "orthogonalize": { - "title": "Квадрат", - "description": { - "line": "Изправете ъглите на линията.", - "area": "Изправете ъглите на полигона." - }, - "key": "S", - "annotation": { - "line": "Изправихте ъглите на линия.", - "area": "Изправихте ъглите на площен обект." - }, - "not_squarish": "Това не може да бъде квадрат, защото не е квадратно.", - "too_large": "Това не може да бъде направено квадратно, защото не достатъчна част от него е видима в момента.", - "connected_to_hidden": "Това не може да бъде кръгло, защото е свързано със скрит обект." - }, - "straighten": { - "title": "Изправям", - "description": "Изправи тази линията.", - "key": "S", - "annotation": "Изправи линия.", - "too_bendy": "Това не може да се изправи защото се огъва твърде много.", - "connected_to_hidden": "Тази линия не може да се изправи, защото е свързана със скрит обект." - }, - "delete": { - "title": "Изтриване", - "annotation": { - "point": "Изтрита е точка.", - "vertex": "Изтрит е възел от път.", - "line": "Изтрита е линия.", - "area": "Изтрит е площен обект.", - "relation": "Изтрита е релация." - } - }, - "add_member": { - "annotation": "Добавен член към релация." - }, - "delete_member": { - "annotation": "Премахнат член на релация." - }, - "connect": { - "annotation": { - "point": "Свързан е път с точка.", - "vertex": "Свързан е път с друг път.", - "line": "Свързан е път с линия.", - "area": "Свързан е път с площен обект." - } - }, - "disconnect": { - "title": "Прекъсване", - "description": "Разделете тези линии/площни обекти едни от други.", - "key": "D", - "annotation": "Разделени са линии/площни обекти.", - "not_connected": "Няма достатъчно линии/площни обекти за разделяне тук.", - "connected_to_hidden": "Това не може да бъде", - "relation": "Това не може да се разпадне, защото свързва части от релацията." - }, - "merge": { - "title": "Обединяване", - "description": "Обедини обектите.", - "key": "C", - "annotation": "Обедини {n} обекти.", - "not_eligible": "Тези обекти не могат да бъдат обединени.", - "restriction": "Тези обекти не могат да се обединят, защото поне единият е част от \"{relation}\" връзка.", - "incomplete_relation": "Тези обекти не могат да се обединят, защото поне единият не е бил напълно изтеглен.", - "conflicting_tags": "Тези обекти не могат да се обединят, защото някои от тях имат противоречиви стойности." - }, - "move": { - "title": "Преместване", - "key": "M", - "annotation": { - "point": "Преместена е точка.", - "vertex": "Преместен е възел от път.", - "line": "Преместена е линия.", - "area": "Преместен е площен обект" - } - }, - "rotate": { - "title": "Въртене", - "key": "R", - "annotation": { - "line": "Завъртяна е линия.", - "area": "Завъртян е площен обект." - } - }, - "reverse": { - "title": "Объръщане", - "description": "Сменете посоката на линията с противоположната.", - "key": "V", - "annotation": "Обърната е посоката на линия." - }, - "split": { - "title": "Разделяне", - "description": { - "line": "Разделете линията на две при този възел.", - "area": "Разделете границата на площния обект на две.", - "multiple": "Разделете на две линиите/границите на площния обект при този възел." - }, - "key": "X", - "annotation": { - "line": "Разделете линия.", - "area": "Разделете границата на площния обект.", - "multiple": "Разделете {n} линии/граници на площни обекти. " - }, - "not_eligible": "Линиите не могат да бъдат разделяни в началото или края им.", - "multiple_ways": "Има твърде много линии за разделяне тук.", - "connected_to_hidden": "Това не може да се разцепи, защото е свързано със скрит обект." - }, - "restriction": { - "help": { - "select": "Клик за селекция на пътен сегмент", - "toggle": "Натиснете за обръщане на ограниченията за завиване", - "toggle_on": "Натиснете за добавяне на \"{restriction}\" ограничение.", - "toggle_off": "Натиснете за премахване на \"{restriction}\" ограничение." - }, - "annotation": { - "create": "Добавено ограничение в завойте", - "delete": "Изтрийте ограничение за завиване." - } - } - }, - "undo": { - "tooltip": "Назад: {action}", - "nothing": "Нищо за отменяне." - }, - "redo": { - "tooltip": "Отново: {action}", - "nothing": "Нищо за повторение." - }, - "tooltip_keyhint": "Бързи клавиши:", - "browser_notice": "Този редактор се поддържа във Firefox, Chrome, Safari, Opera и Internet Explorer 11 и следващи. Моля обновете своя браузър или използвайте Potlatch 2, за да редактирате картата.", - "translate": { - "translate": "Превод", - "localized_translation_label": "Многоезично име", - "localized_translation_language": "Изберете език", - "localized_translation_name": "Име" - }, - "logout": "изход", - "loading_auth": "Свързване с OpenStreetMap...", - "report_a_bug": "Докладвай грешка", - "help_translate": "Помощ за превода", - "feature_info": { - "hidden_warning": "{count} скрити обекти", - "hidden_details": "Следните обекти са скрити: {details}" - }, - "status": { - "error": "Не може да се свърже с API-то.", - "offline": "API-то е офлайн. Моля опитайте да редактирате по-късно.", - "readonly": "API-то е в режим само за четене. Ще трябва да почакате, за да запазите вашите промени." - }, - "commit": { - "upload_explanation": "Промените, които качвате ще са видими на всички карти използващи данни от OpenStreetMap.", - "upload_explanation_with_user": "Промените, които качвате като {user} ще са видими на всички карти използващи данни от OpenStreetMap.", - "cancel": "Отказ", - "changes": "{count} промени", - "warnings": "Предупреждения", - "modified": "Променени", - "deleted": "Изтрити", - "created": "Създадени" - }, - "contributors": { - "list": "Редакции от {users}", - "truncated_list": "Редакции от {users} и още {count} други" - }, - "geometry": { - "point": "точка", - "vertex": "чупка", - "line": "линия", - "area": "площ", - "relation": "връзка" - }, - "geocoder": { - "search": "Търси навсякъде...", - "no_results_visible": "Няма резултати във видимата част на картата", - "no_results_worldwide": "Няма намерени резултати" - }, - "geolocate": { - "title": "Показване на моето местоположение", - "locating": "Зареждане, моля изчакайте..." - }, - "inspector": { - "no_documentation_combination": "Няма налична документация за тази комбинация от тагове", - "no_documentation_key": "Няма налична документация за този ключ", - "show_more": "Покажи още", - "view_on_osm": "Вижте на openstreetmap.org", - "all_fields": "Всички полета", - "all_tags": "Всички тагове", - "all_members": "Всички членове", - "all_relations": "Всички релации", - "new_relation": "Нова връзка...", - "role": "Роля", - "choose": "Изберете вид обект", - "results": "{n} резултата за {search}", - "reference": "Вижте в OpenStreetMap Wiki", - "back_tooltip": "Смяна на обект", - "remove": "Премахнете", - "search": "Търсене", - "unknown": "Неизвестно", - "incomplete": "<не е свалено>", - "feature_list": "Търсене на обекти", - "edit": "Редактиране на обект", - "check": { - "yes": "Да", - "no": "Не" - }, - "none": "Никакъв", - "node": "Възел", - "way": "Начин", - "relation": "Релация", - "location": "Местоположение", - "add_fields": "Добави поле:" - }, - "background": { - "title": "Изображения", - "description": "Изображения настройки", - "none": "Никакъв", - "best_imagery": "Най-известен източник на изображения за това местоположение", - "custom": "Обичаен", - "reset": "презареждане" - }, - "map_data": { - "title": "Картни Данни", - "description": "Картни Данни", - "data_layers": "Слоеве с данни", - "map_features": "Обекти от картата", - "autohidden": "Тези обекти бяха скрити автоматично, защото щяха да са пказани твърде много на екрана. Можете да увеличите, за да ги редактирате." - }, - "feature": { - "points": { - "description": "Точки" - }, - "traffic_roads": { - "tooltip": "Шосета, Улици, и др." - }, - "service_roads": { - "description": "Обслужващи Улици" - }, - "paths": { - "description": "Пътеки", - "tooltip": "Тротоари, Пешеходни Зони, Велосипедни Алеи, и т.н." - }, - "buildings": { - "description": "Сгради", - "tooltip": "Сгради, Заслони, Гаражи, и т.н." - }, - "landuse": { - "description": "Обекти за земеползване", - "tooltip": "Гори, Земеделски Земи, Жилищни зони, Търговски зони, и т.н." - }, - "boundaries": { - "description": "Граници", - "tooltip": "Административни Граници" - }, - "water": { - "description": "Водни Обекти" - }, - "rail": { - "description": "Железопътни Обекти", - "tooltip": "Железопътни линии" - }, - "power": { - "description": "Енергийни обекти", - "tooltip": "Електропроводи , Електроцентрали, Подстанции, и т.н." - }, - "past_future": { - "description": "Минал/Бъдещ" - }, - "others": { - "description": "Други", - "tooltip": "Всичко Друго" - } - }, - "area_fill": { - "partial": { - "description": "Частично Попълнен" - } - }, - "restore": { - "heading": "Имате незапазени промени", - "description": "Искате ли да възстановите незаписаните промени от предишна сесия?" - }, - "save": { - "title": "Запис", - "no_changes": "Няма промени за запис.", - "error": "Грешки настъпили докато се опитваме да запазим", - "status_code": "Сървърът върна статус с код {code}", - "unknown_error_details": "Моля уверете се че сте свързани с интернет.", - "unsaved_changes": "Имате незаписани промени", - "conflict": { - "header": "Решение на несъвместими редакции.", - "count": "Несъвместими {num} от {total}", - "previous": "< Предишен", - "next": "Следващ >", - "keep_remote": "Използвай техните", - "restore": "Възстанови", - "delete": "Остави Изтрито", - "done": "Всички несъответствия са решени!" - } - }, - "merge_remote_changes": { - "conflict": { - "nodelist": "Възлите са били променени и от вас и от {user}. ", - "memberlist": "Части от връзката бяха променени и от вас и от {user}.", - "tags": "Вие променихте {tag} таг на \"{local}\" и {user} се промени на \"{remote}\"." - } - }, - "success": { - "edited_osm": "Редактирахте OSM!", - "just_edited": "Вие редактирахте OpenStreetMap!", - "view_on_osm": "Вижте в OSM", - "facebook": "Споделете във Facebook", - "twitter": "Сподели в Twitter", - "google": "Сподели в Google+", - "help_link_text": "Детайли" - }, - "confirm": { - "cancel": "Отказ" - }, - "splash": { - "welcome": "Добре дошли в iD редактора за OpenStreetMap", - "text": "iD e лесен, но мощен инструмент за попълване на най-добрата свободна карта на света. Това е версия {version}. За повече информация вижте {website} и докладвайте за бъгове в {github}.", - "walkthrough": "Започнете опознавателната обиколка" - }, - "source_switch": { - "live": "live", - "lose_changes": "Имате незапазени промени. Смяната на картния сървър ще ги отхвърли. Сигурни ли сте, че искате да смените сървърите?", - "dev": "dev" - }, - "tag_reference": { - "description": "Описание", - "on_wiki": "{tag} в wiki.osm.org", - "used_with": "използва се с {type}" - }, - "validations": { - "untagged_point": "Точка без тагове.", - "untagged_point_tooltip": "Изберете типът обект който описва каква е тази точка.", - "untagged_line": "Линия без таг", - "untagged_line_tooltip": "Изберете типът обект който описва каква е тази линия.", - "untagged_area": "Площен обект без таг", - "untagged_area_tooltip": "Изберете типът обект който описва каква е тази площ.", - "tag_suggests_area": "Тагът {tag} предполага линията да е площен обект, но тя не е", - "deprecated_tags": "Отхвърлени тагове: {tags}" - }, - "cannot_zoom": "Не можете да намалявате повече в текущия режим.", - "full_screen": "Превключи на Цял Екран", - "mapillary_images": { - "tooltip": "Снимки за ниво на улицата от Mapillary" - }, - "mapillary": { - "view_on_mapillary": "Вижте тази снимка на Mapillary" - }, - "help": { - "title": "Помощ" - }, - "intro": { - "graph": { - "block_number": "", - "county": "", - "district": "", - "hamlet": "", - "neighbourhood": "", - "province": "", - "quarter": "", - "state": "", - "subdistrict": "", - "suburb": "", - "countrycode": "bg" - }, - "navigation": { - "title": "Навигация" - }, - "points": { - "title": "Точки" - }, - "areas": { - "title": "Площи" - }, - "lines": { - "title": "Линии" - }, - "startediting": { - "title": "Започване на редакция", - "save": "Не забравяйте да записвате редовно промените, които правите!", - "start": "Започнете да картографирате!" - } - }, - "presets": { - "categories": { - "category-rail": { - "name": "Железопътни Обекти" - }, - "category-water-area": { - "name": "Водни Обекти" - }, - "category-water-line": { - "name": "Водни Обекти" - } - }, - "fields": { - "access": { - "options": { - "designated": { - "description": "Достъпът позволен според указателни табели или специфични местни разпоредби", - "title": "По предназначение" - }, - "destination": { - "description": "Достъпът разрешен само за достигане до дестинация", - "title": "До дестинация" - }, - "no": { - "description": "Забранен публичният достъп", - "title": "Забранен" - }, - "permissive": { - "description": "Достъпът позволен докато собственика позволява", - "title": "Частичен" - }, - "private": { - "description": "Достъпът разрешен само с позволение на собственика", - "title": "Частен" - }, - "yes": { - "description": "Достъпът позволен с нормативен акт; право на преминаване", - "title": "Разрешен" - } - }, - "types": { - "bicycle": "Велосипеди", - "foot": "Пешеходен", - "horse": "Коне", - "motor_vehicle": "МПС" - } - }, - "address": { - "label": "Адрес", - "placeholders": { - "city": "Град", - "country": "Държава", - "district": "Община", - "housename": "Къща", - "housenumber": "123", - "place": "Място", - "province": "Област", - "state": "Икономически район NUT2", - "street": "Улица", - "subdistrict": "Землище", - "suburb": "Квартал" - } - }, - "admin_level": { - "label": "Административно деление" - }, - "aeroway": { - "label": "Вид" - }, - "amenity": { - "label": "Вид" - }, - "atm": { - "label": "Банкомат" - }, - "barrier": { - "label": "Вид" - }, - "bicycle_parking": { - "label": "Вид" - }, - "boundary": { - "label": "Вид" - }, - "building": { - "label": "Сграда" - }, - "building_area": { - "label": "Сграда" - }, - "capacity": { - "label": "Капацитет", - "placeholder": "50, 100, 200..." - }, - "collection_times": { - "label": "График на събиране" - }, - "construction": { - "label": "Вид" - }, - "country": { - "label": "Държава" - }, - "crossing": { - "label": "Вид" - }, - "cycleway": { - "options": { - "none": { - "title": "Никакъв" - } - } - }, - "denomination": { - "label": "Вероизповедание" - }, - "denotation": { - "label": "Название" - }, - "description": { - "label": "Описание" - }, - "electrified": { - "options": { - "no": "Не" - } - }, - "elevation": { - "label": "Надморска височина" - }, - "emergency": { - "label": "Спешни случаи" - }, - "entrance": { - "label": "Вид" - }, - "fax": { - "label": "Факс", - "placeholder": "+31 42 123 4567" - }, - "fee": { - "label": "Такса" - }, - "fixme": { - "label": "Поправи ме" - }, - "highway": { - "label": "Вид" - }, - "historic": { - "label": "Вид" - }, - "iata": { - "label": "IATA" - }, - "icao": { - "label": "ICAO" - }, - "incline": { - "label": "Наклон" - }, - "internet_access": { - "label": "Интернет достъп", - "options": { - "no": "Не", - "terminal": "Терминал", - "wired": "Кабелен", - "wlan": "Wifi", - "yes": "Да" - } - }, - "lamp_type": { - "label": "Тип" - }, - "landuse": { - "label": "Вид" - }, - "lanes": { - "label": "Платна", - "placeholder": "1, 2, 3..." - }, - "layer": { - "label": "Слой" - }, - "leisure": { - "label": "Вид" - }, - "levels": { - "label": "Нива", - "placeholder": "2, 4, 6..." - }, - "location": { - "label": "Местоположение" - }, - "man_made": { - "label": "Вид" - }, - "maxspeed": { - "label": "Ограничение на скоростта", - "placeholder": "40, 50, 60..." - }, - "name": { - "label": "Име", - "placeholder": "Популярно наименование (ако има такова)" - }, - "natural": { - "label": "Природа" - }, - "network": { - "label": "Мрежа" - }, - "note": { - "label": "Бележка" - }, - "office": { - "label": "Вид" - }, - "oneway": { - "label": "Еднопосочнoст", - "options": { - "no": "Не", - "yes": "Да" - } - }, - "oneway_yes": { - "label": "Еднопосочен", - "options": { - "no": "Не", - "yes": "Да" - } - }, - "opening_hours": { - "label": "Работно време" - }, - "operator": { - "label": "Оператор" - }, - "park_ride": { - "label": "Буферен паркинг" - }, - "parking": { - "label": "Вид" - }, - "phone": { - "label": "Телефон", - "placeholder": "+31 42 123 4567" - }, - "place": { - "label": "Вид" - }, - "power": { - "label": "Вид" - }, - "railway": { - "label": "Вид" - }, - "relation": { - "label": "Вид" - }, - "religion": { - "label": "Религия" - }, - "restriction": { - "label": "Вид" - }, - "route": { - "label": "Вид" - }, - "route_master": { - "label": "Вид" - }, - "service": { - "label": "Вид" - }, - "shelter": { - "label": "Навес" - }, - "shop": { - "label": "Вид" - }, - "structure": { - "label": "Структура", - "options": { - "bridge": "Мост", - "cutting": "Изкоп", - "embankment": "Насип", - "tunnel": "Тунел" - }, - "placeholder": "Неизвестен" - }, - "supervised": { - "label": "Под наблюдение" - }, - "surface": { - "label": "Повърхност" - }, - "takeaway": { - "options": { - "no": "Не", - "yes": "Да" - } - }, - "tourism": { - "label": "Вид" - }, - "trail_visibility": { - "label": "Видимост на туристическата пътека" - }, - "water": { - "label": "Вид" - }, - "waterway": { - "label": "Вид" - }, - "website": { - "label": "Уебсайт", - "placeholder": "http://example.com/" - }, - "wetland": { - "label": "Вид" - }, - "wheelchair": { - "label": "Достъп за инвалиди" - }, - "wikipedia": { - "label": "Wikipedia" - } - }, - "presets": { - "address": { - "name": "Адрес" - }, - "aeroway": { - "name": "Въздухоплаване" - }, - "aeroway/aerodrome": { - "name": "Летище" - }, - "aeroway/apron": { - "name": "Стоянка за самолети" - }, - "aeroway/hangar": { - "name": "Хангар" - }, - "aeroway/helipad": { - "name": "Хеликоптерна площадка" - }, - "aeroway/runway": { - "name": "Летателна писта" - }, - "aeroway/taxiway": { - "name": "Рольожка" - }, - "amenity": { - "name": "Услуги" - }, - "amenity/atm": { - "name": "Банкомат" - }, - "amenity/bank": { - "name": "Банка" - }, - "amenity/bar": { - "name": "Бар" - }, - "amenity/bench": { - "name": "Пейка" - }, - "amenity/bicycle_parking": { - "name": "Паркинг за велосипеди" - }, - "amenity/bicycle_rental": { - "name": "Наем на велосипеди" - }, - "amenity/cafe": { - "name": "Кафене" - }, - "amenity/car_rental": { - "name": "Коли под наем" - }, - "amenity/car_sharing": { - "name": "Споделяне на коли" - }, - "amenity/car_wash": { - "name": "Автомивка" - }, - "amenity/cinema": { - "name": "Кино" - }, - "amenity/courthouse": { - "name": "Съд" - }, - "amenity/drinking_water": { - "name": "Чешма" - }, - "amenity/embassy": { - "name": "Посолство" - }, - "amenity/fast_food": { - "name": "Бърза закуска" - }, - "amenity/fire_station": { - "name": "Пожарна" - }, - "amenity/fountain": { - "name": "Фонтан" - }, - "amenity/fuel": { - "name": "Бензиностанция" - }, - "amenity/grave_yard": { - "name": "Гробище" - }, - "amenity/library": { - "name": "Библиотека" - }, - "amenity/marketplace": { - "name": "Пазар" - }, - "amenity/pharmacy": { - "name": "Аптека" - }, - "amenity/place_of_worship": { - "name": "Религиозен храм" - }, - "amenity/place_of_worship/buddhist": { - "name": "Будистки храм" - }, - "amenity/place_of_worship/christian": { - "name": "Църква" - }, - "amenity/place_of_worship/jewish": { - "name": "Синагога" - }, - "amenity/place_of_worship/muslim": { - "name": "Джамия" - }, - "amenity/police": { - "name": "Полиция" - }, - "amenity/post_box": { - "name": "Пощенска кутия" - }, - "amenity/post_office": { - "name": "Поща" - }, - "amenity/pub": { - "name": "Пъб" - }, - "amenity/restaurant": { - "name": "Ресторант" - }, - "amenity/swimming_pool": { - "name": "Плувен басейн" - }, - "amenity/taxi": { - "name": "Такси стоянка" - }, - "amenity/telephone": { - "name": "Телефон" - }, - "amenity/theatre": { - "name": "Театър" - }, - "amenity/toilets": { - "name": "Тоалетна" - }, - "amenity/townhall": { - "name": "Кметство" - }, - "amenity/waste_basket": { - "name": "Кош за боклук" - }, - "area": { - "name": "Площ" - }, - "barrier": { - "name": "Преграда" - }, - "barrier/block": { - "name": "Бетонен блок" - }, - "barrier/bollard": { - "name": "Колче" - }, - "barrier/cattle_grid": { - "name": "Тексаска мрежа" - }, - "barrier/city_wall": { - "name": "Градска стена" - }, - "barrier/cycle_barrier": { - "name": "Велосипедна преграда" - }, - "barrier/entrance": { - "name": "Вход" - }, - "barrier/fence": { - "name": "Ограда" - }, - "barrier/gate": { - "name": "Портал" - }, - "barrier/hedge": { - "name": "Жив плет" - }, - "barrier/kissing_gate": { - "name": "Препятствие за животни" - }, - "barrier/lift_gate": { - "name": "Бариера" - }, - "barrier/retaining_wall": { - "name": "Подпорна стена" - }, - "barrier/stile": { - "name": "Стълби за преминаване през ограда" - }, - "barrier/toll_booth": { - "name": "Будка за тол такса" - }, - "barrier/wall": { - "name": "Стена" - }, - "boundary/administrative": { - "name": "Административна граница" - }, - "building": { - "name": "Сграда" - }, - "building/apartments": { - "name": "Жилищен блок" - }, - "building/house": { - "name": "Къща" - }, - "emergency/phone": { - "name": "Телефон за спешна помощ" - }, - "highway": { - "name": "Път" - }, - "highway/bridleway": { - "name": "Конска пътека" - }, - "highway/cycleway": { - "name": "Велоалея" - }, - "highway/footway": { - "name": "Пешеходна алея" - }, - "highway/living_street": { - "name": "Жилищна улица" - }, - "highway/mini_roundabout": { - "name": "Малко кръгово кръстовище" - }, - "highway/motorway": { - "name": "Автомагистрала" - }, - "highway/motorway_link": { - "name": "Автомагистрална връзка" - }, - "highway/path": { - "name": "Пътека" - }, - "highway/primary": { - "name": "Първокласен път" - }, - "highway/primary_link": { - "name": "Връзка с първокласен път" - }, - "highway/residential": { - "name": "Улица" - }, - "highway/road": { - "name": "Непроучен път" - }, - "highway/secondary": { - "name": "Второкласен път" - }, - "highway/secondary_link": { - "name": "Връзка с второкласен път" - }, - "highway/service": { - "name": "Сервизна улица" - }, - "highway/service/alley": { - "name": "Тясна уличка между имоти" - }, - "highway/service/drive-through": { - "name": "Обслужване без напускане на автомобила" - }, - "highway/service/driveway": { - "name": "Алея за коли към жилище" - }, - "highway/service/emergency_access": { - "name": "За достъп при спешни случаи" - }, - "highway/service/parking_aisle": { - "name": "Път в паркинг" - }, - "highway/steps": { - "name": "Стъпала" - }, - "highway/street_lamp": { - "name": "Улична лампа" - }, - "highway/tertiary": { - "name": "Третокласен път" - }, - "highway/tertiary_link": { - "name": "Връзка с третокласен път" - }, - "highway/traffic_signals": { - "name": "Светофари" - }, - "highway/trunk": { - "name": "Скоростен път" - }, - "highway/trunk_link": { - "name": "Връзка със скоростен път" - }, - "highway/turning_circle": { - "name": "Място за обръщане" - }, - "historic": { - "name": "Място с историческо значение" - }, - "historic/archaeological_site": { - "name": "Археологически обект" - }, - "historic/boundary_stone": { - "name": "Граничен камък" - }, - "historic/castle": { - "name": "Замък" - }, - "historic/memorial": { - "name": "Мемориална плоча" - }, - "historic/monument": { - "name": "Паметник" - }, - "historic/ruins": { - "name": "Руини" - }, - "historic/wayside_cross": { - "name": "Крайпътен кръст" - }, - "historic/wayside_shrine": { - "name": "Крайпътен параклис" - }, - "landuse/basin": { - "name": "Басейн" - }, - "landuse/cemetery": { - "name": "Гробищен парк" - }, - "landuse/construction": { - "name": "Строеж" - }, - "landuse/farmyard": { - "name": "Селскостопански двор" - }, - "landuse/forest": { - "name": "Гора" - }, - "landuse/grass": { - "name": "Трева" - }, - "landuse/meadow": { - "name": "Пасище" - }, - "landuse/orchard": { - "name": "Овощна градина " - }, - "landuse/quarry": { - "name": "Кариера" - }, - "landuse/vineyard": { - "name": "Лозе" - }, - "leisure": { - "name": "Отдих" - }, - "leisure/garden": { - "name": "Градина" - }, - "leisure/golf_course": { - "name": "Голф игрище" - }, - "leisure/marina": { - "name": "Яхт клуб" - }, - "leisure/park": { - "name": "Парк" - }, - "leisure/pitch": { - "name": "Спортно игрище" - }, - "leisure/pitch/american_football": { - "name": "Игрище за американски футбол" - }, - "leisure/pitch/baseball": { - "name": "Игрище за бейзбол" - }, - "leisure/pitch/basketball": { - "name": "Баскетболно игрище" - }, - "leisure/pitch/soccer": { - "name": "Футболно игрище" - }, - "leisure/pitch/tennis": { - "name": "Тенис корт" - }, - "leisure/pitch/volleyball": { - "name": "Волейболно игрище" - }, - "leisure/playground": { - "name": "Детска площадка" - }, - "leisure/slipway": { - "name": "Хелинг" - }, - "leisure/stadium": { - "name": "Стадион" - }, - "leisure/swimming_pool": { - "name": "Плувен басейн" - }, - "line": { - "name": "Линия" - }, - "man_made": { - "name": "Съоръжения" - }, - "man_made/breakwater": { - "name": "Вълнолом" - }, - "man_made/cutline": { - "name": "Просека" - }, - "man_made/lighthouse": { - "name": "Морски фар" - }, - "man_made/pier": { - "name": "Кей" - }, - "man_made/pipeline": { - "name": "Тръбопровод" - }, - "man_made/survey_point": { - "name": "Геодезическа точка" - }, - "man_made/tower": { - "name": "Кула" - }, - "man_made/wastewater_plant": { - "name": "Пречиствателна станция" - }, - "man_made/water_tower": { - "name": "Водна кула" - }, - "man_made/water_works": { - "name": "Помпена станция" - }, - "natural": { - "name": "Природа" - }, - "natural/bay": { - "name": "Залив" - }, - "natural/beach": { - "name": "Плаж" - }, - "natural/cliff": { - "name": "Скала" - }, - "natural/coastline": { - "name": "Брегова линия" - }, - "natural/glacier": { - "name": "Ледник" - }, - "natural/grassland": { - "name": "Степ" - }, - "natural/heath": { - "name": "Малки храсти" - }, - "natural/peak": { - "name": "Връх" - }, - "natural/scrub": { - "name": "Шубрак" - }, - "natural/spring": { - "name": "Извор" - }, - "natural/tree": { - "name": "Дърво" - }, - "natural/water": { - "name": "Водна площ" - }, - "natural/water/lake": { - "name": "Езеро" - }, - "natural/water/pond": { - "name": "Малко езеро" - }, - "natural/water/reservoir": { - "name": "Язовир" - }, - "natural/wetland": { - "name": "Блатиста зона" - }, - "natural/wood": { - "name": "Гора" - }, - "office": { - "name": "Офис" - }, - "place": { - "name": "Населени места" - }, - "place/city": { - "name": "Град над 100 000" - }, - "place/hamlet": { - "name": "Махала" - }, - "place/island": { - "name": "Остров" - }, - "place/isolated_dwelling": { - "name": "Изолирано жилище" - }, - "place/locality": { - "name": "Местност" - }, - "place/town": { - "name": "Град под 100 000" - }, - "place/village": { - "name": "Село" - }, - "point": { - "name": "Точка" - }, - "power": { - "name": "Енергетика" - }, - "power/line": { - "name": "Електропровод" - }, - "power/pole": { - "name": "Електрически стълб" - }, - "power/sub_station": { - "name": "Подстанция" - }, - "power/tower": { - "name": "Жере" - }, - "power/transformer": { - "name": "Трансформатор" - }, - "railway": { - "name": "ЖП транспорт" - }, - "railway/abandoned": { - "name": "Изоставена железопътна линия" - }, - "railway/disused": { - "name": "Закрита железопътна линия" - }, - "railway/monorail": { - "name": "Монорелсов път" - }, - "railway/rail": { - "name": "ЖП линия" - }, - "railway/subway": { - "name": "Метро" - }, - "railway/subway_entrance": { - "name": "Вход на метростанция" - }, - "railway/tram": { - "name": "Трамвайни релси" - }, - "relation": { - "name": "Релация" - }, - "route/ferry": { - "name": "Фериботна връзка" - }, - "shop": { - "name": "Магазин" - }, - "shop/alcohol": { - "name": "Магазин за алкохол" - }, - "shop/bakery": { - "name": "Пекарна" - }, - "shop/beauty": { - "name": "Козметик" - }, - "shop/beverages": { - "name": "Магазин за алкохол и цигари" - }, - "shop/bicycle": { - "name": "Магазин за велосипеди" - }, - "shop/boutique": { - "name": "Бутик" - }, - "shop/butcher": { - "name": "Колбаси" - }, - "shop/car": { - "name": "Автомобили" - }, - "shop/car_parts": { - "name": "Авточасти" - }, - "shop/car_repair": { - "name": "Сервиз автомобили" - }, - "shop/clothes": { - "name": "Магазин за дрехи" - }, - "shop/computer": { - "name": "Компютърен магазин" - }, - "shop/convenience": { - "name": "Магазин за хранителни стоки" - }, - "shop/deli": { - "name": "Магазин за деликатеси" - }, - "shop/department_store": { - "name": "Универсален магазин" - }, - "shop/doityourself": { - "name": "Магазин \"Направи си сам\"" - }, - "shop/electronics": { - "name": "Магазин за електроника" - }, - "shop/farm": { - "name": "Щанд за плодове и зеленчуци" - }, - "shop/fishmonger": { - "name": "Магазин за риба" - }, - "shop/florist": { - "name": "Магазин за цветя" - }, - "shop/furniture": { - "name": "Мебелен магазин" - }, - "shop/garden_centre": { - "name": "Градински център" - }, - "shop/gift": { - "name": "Магазин за подаръци" - }, - "shop/greengrocer": { - "name": "Плод-зеленчук" - }, - "shop/hairdresser": { - "name": "Фризьорски салон" - }, - "shop/hardware": { - "name": "Железария" - }, - "shop/hifi": { - "name": "Магазин за аудиотехника" - }, - "shop/jewelry": { - "name": "Бижутер" - }, - "shop/laundry": { - "name": "Пералня" - }, - "shop/mall": { - "name": "Мол" - }, - "shop/mobile_phone": { - "name": "Магазин за мобилни телефони" - }, - "shop/motorcycle": { - "name": "Магазин за мотоциклети" - }, - "shop/music": { - "name": "Музикален магазин" - }, - "shop/optician": { - "name": "Оптика" - }, - "shop/pet": { - "name": "Зоо магазин" - }, - "shop/shoes": { - "name": "Магазин за обувки" - }, - "shop/sports": { - "name": "Спортен магазин" - }, - "shop/stationery": { - "name": "Магазин за канцеларски стоки" - }, - "shop/supermarket": { - "name": "Супермаркет" - }, - "shop/toys": { - "name": "Магазин за играчки" - }, - "shop/travel_agency": { - "name": "Туристическа агенция" - }, - "shop/tyres": { - "name": "Магазин за автомобилни гуми" - }, - "shop/vacant": { - "name": "Свободна търговска площ" - }, - "shop/variety_store": { - "name": "Смесен магазин" - }, - "shop/video": { - "name": "Видеотека" - }, - "tourism": { - "name": "Туризъм" - }, - "tourism/alpine_hut": { - "name": "Хижа" - }, - "tourism/artwork": { - "name": "Произведение на изкуството" - }, - "tourism/attraction": { - "name": "Туристическа атракция" - }, - "tourism/caravan_site": { - "name": "Паркинг за каравани" - }, - "tourism/guest_house": { - "name": "Къща за гости" - }, - "tourism/hostel": { - "name": "Хостел" - }, - "tourism/hotel": { - "name": "Хотел" - }, - "tourism/information": { - "name": "Информация" - }, - "tourism/motel": { - "name": "Мотел" - }, - "tourism/museum": { - "name": "Музей" - }, - "tourism/picnic_site": { - "name": "Място за пикник" - }, - "tourism/theme_park": { - "name": "Увеселителен парк" - }, - "tourism/viewpoint": { - "name": "Точка с хубава гледка" - }, - "tourism/zoo": { - "name": "Зоологическа градина" - }, - "type/boundary": { - "name": "Граница" - }, - "type/boundary/administrative": { - "name": "Административна граница" - }, - "type/multipolygon": { - "name": "Мултиполигон" - }, - "type/restriction": { - "name": "Ограничение" - }, - "type/restriction/no_right_turn": { - "name": "Без десен завой" - }, - "type/restriction/no_u_turn": { - "name": "Без обратен завой" - }, - "type/restriction/only_left_turn": { - "name": "Завой само на ляво" - }, - "type/restriction/only_right_turn": { - "name": "Завой само на дясно" - }, - "type/restriction/only_straight_on": { - "name": "Без завиване" - }, - "type/route": { - "name": "Маршрут" - }, - "type/route/bicycle": { - "name": "Велосипеден маршрут" - }, - "type/route/bus": { - "name": "Автобусен маршрут" - }, - "type/route/detour": { - "name": "Обходен маршрут" - }, - "type/route/ferry": { - "name": "Фериботна връзка" - }, - "type/route/foot": { - "name": "Пешеходен маршрут" - }, - "type/route/pipeline": { - "name": "Трасе на тръбопровод" - }, - "type/route/power": { - "name": "Трасе на електропровод" - }, - "type/route/road": { - "name": "Път" - }, - "type/route/train": { - "name": "Железопътен маршрут" - }, - "type/route/tram": { - "name": "Трамваен маршрут" - }, - "type/route_master": { - "name": "Маршрутна схема" - }, - "vertex": { - "name": "Друг" - }, - "waterway": { - "name": "Води" - }, - "waterway/canal": { - "name": "Канал" - }, - "waterway/dam": { - "name": "Язовирна стена" - }, - "waterway/ditch": { - "name": "Канавка" - }, - "waterway/drain": { - "name": "Отводнителен канал" - }, - "waterway/river": { - "name": "Река" - }, - "waterway/riverbank": { - "name": "Речен бряг" - }, - "waterway/stream": { - "name": "Поток" - }, - "waterway/weir": { - "name": "Преливник" - } - } - } - } -} \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/bg.json b/vendor/assets/iD/iD/locales/bg.json index c55fe0f1e..2d84d6c89 100644 --- a/vendor/assets/iD/iD/locales/bg.json +++ b/vendor/assets/iD/iD/locales/bg.json @@ -1,5 +1,10 @@ { "bg": { + "icons": { + "information": "Информация", + "remove": "премахване", + "undo": "отмени" + }, "modes": { "add_area": { "title": "Площ", @@ -145,7 +150,9 @@ "vertex": "Свързан е път с друг път.", "line": "Свързан е път с линия.", "area": "Свързан е път с площен обект." - } + }, + "relation": "Тези обекти не могат да бъдат свързани, защото имат различни роли в релация.", + "restriction": "Тези обекти не могат да бъдат свързани, защото това ще повреди релацията \"{relation}\". " }, "disconnect": { "title": "Прекъсване", @@ -163,7 +170,8 @@ "annotation": "Обедини {n} обекти.", "not_eligible": "Тези обекти не могат да бъдат обединени.", "not_adjacent": "Тези обекти не могат да се обединят, защото крайните им точки не са свързани.", - "restriction": "Тези обекти не могат да се обединят, защото поне единият е част от \"{relation}\" връзка.", + "restriction": "Тези обекти не могат да се обединят, защото това ще повреди релацията \"{relation}\"", + "relation": "Тези обекти не могат да се обединят, защото ролите им в релацията са в конфликт.", "incomplete_relation": "Тези обекти не могат да се обединят, защото поне единият не е бил напълно изтеглен.", "conflicting_tags": "Тези обекти не могат да се обединят, защото някои от тях имат противоречиви стойности." }, @@ -291,6 +299,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Разстояние", + "distance_up_to": "До {distance}", + "via": "През", + "via_node_only": "Само възел", + "via_up_to_one": "До 1 път", + "via_up_to_two": "До 2 пътя" + }, + "help": { + "indirect": "(indirect)", + "turn": { + "no_left_turn": "ЗАБРАНЕНО завиването наляво {indirect}", + "no_right_turn": "ЗАБРАНЕНО завиването надясно {indirect}", + "no_u_turn": "ЗАБРАНЕНО завиването в обратна посока {indirect}", + "no_straight_on": "ЗАБРАНЕНО движението направо {indirect}", + "only_left_turn": "САМО ляв завой {indirect}", + "only_right_turn": "САМО десен завой {indirect}", + "only_u_turn": "САМО обратен завой {indirect}", + "only_straight_on": "САМО направо {indirect}", + "allowed_left_turn": "Ляв завой позволен {indirect}", + "allowed_right_turn": "Десен завой позволен {indirect}", + "allowed_u_turn": "Обратен завой позволен {indirect}", + "allowed_straight_on": "Движение направо позволено {indirect}" + }, + "from": "ОТ", + "via": "ПРЕЗ", + "to": "ДО", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Кликнете за да изберете сегмент {from}", + "select_from_name": "Кликнете за да изберете {from} {fromName}", + "toggle": "Кликнете за \"{turn}\"" + } + }, "undo": { "tooltip": "Назад: {action}", "nothing": "Нищо за отменяне." @@ -364,7 +408,37 @@ }, "history": { "key": "H", - "title": "История" + "title": "История", + "selected": "{n} избрани", + "no_history": "Без история (Нова функция)", + "version": "Версия", + "last_edit": "Последна редакция", + "edited_by": "Редактирано от", + "changeset": "Промяна", + "unknown": "Неизвестно", + "link_text": "История на openstreetmap.org" + }, + "location": { + "key": "L", + "title": "Местоположение", + "unknown_location": "Неизвестно местоположение" + }, + "measurement": { + "key": "M", + "title": "Измерване", + "selected": "{n} избрани", + "geometry": "Геометрия", + "closed_line": "затворена линия", + "closed_area": "затворена площ", + "center": "Център", + "perimeter": "Обиколка", + "length": "Дължина", + "area": "Площ", + "centroid": "Центроид", + "location": "Местоположение", + "metric": "Метрична", + "imperial": "Имперска", + "node_count": "Брой възли" } }, "geometry": { @@ -386,6 +460,7 @@ "inspector": { "no_documentation_combination": "Няма налична документация за тази комбинация от тагове", "no_documentation_key": "Няма налична документация за този ключ", + "documentation_redirect": "Тази документация беше пренасочена към нова страница", "show_more": "Покажи още", "view_on_osm": "Вижте на openstreetmap.org", "all_fields": "Всички полета", @@ -400,14 +475,24 @@ "back_tooltip": "Смяна на обект", "remove": "Премахнете", "search": "Търсене", + "multiselect": "Избрани обекти", "unknown": "Неизвестно", "incomplete": "<не е свалено>", "feature_list": "Търсене на обекти", "edit": "Редактиране на обект", "check": { "yes": "Да", - "no": "Не" + "no": "Не", + "reverser": "Смяна на посока" }, + "radio": { + "structure": { + "type": "Вид", + "default": "По подразбиране", + "layer": "Слой" + } + }, + "add": "Добавяне", "none": "Никакъв", "node": "Възел", "way": "Начин", @@ -418,27 +503,58 @@ "background": { "title": "Изображения", "description": "Изображения настройки", + "key": "B", + "backgrounds": "Базови карти", "none": "Никакъв", "best_imagery": "Най-известен източник на изображения за това местоположение", + "switch": "Превключете обратно на тази базова карта", "custom": "Обичаен", - "reset": "презареждане" + "custom_button": "Редактирайте персонализираната базова карта", + "custom_prompt": "Въведете URL шаблон за тайлове. Валидни токени са:\n - {zoom} или {z}, {x}, {y} за Z/X/Y тайл схема\n - {-y} или {ty} за обърнати TMS Y координати\n - {u} за куадтайл схема\n - {switch:a,b,c} за DNS сървърно мултиплексиране\n\nПример:\n{example}", + "overlays": "Подложки", + "imagery_source_faq": "Информация за изображение / Докладвайте проблем", + "reset": "презареждане", + "display_options": "Опции за показване", + "brightness": "Яркост", + "contrast": "Контраст", + "saturation": "Наситеност", + "sharpness": "Острота", + "minimap": { + "description": "Покажи мини карта", + "tooltip": "Покажи мащабирана карта за помощ при локализирането на текущата показана площ.", + "key": "/" + }, + "fix_misalignment": "Коригиране отместването на изображението", + "offset": "Провлачете където и да е в сивата зона отдолу, за да коригирате отместването на изображението или въведете стойността на отместването в метри." }, "map_data": { "title": "Картни Данни", "description": "Картни Данни", + "key": "F", "data_layers": "Слоеве с данни", + "layers": { + "osm": { + "tooltip": "Картографски данни от OpenStreetMap", + "title": "OpenStreetMap данни" + } + }, + "fill_area": "Запълване на площи", "map_features": "Обекти от картата", - "autohidden": "Тези обекти бяха скрити автоматично, защото щяха да са пказани твърде много на екрана. Можете да увеличите, за да ги редактирате." + "autohidden": "Тези обекти бяха скрити автоматично, защото щяха да са пказани твърде много на екрана. Можете да увеличите, за да ги редактирате.", + "osmhidden": "Тези обекти бяха скрити автоматично, защото слоят в OpenStreetMap е скрит." }, "feature": { "points": { - "description": "Точки" + "description": "Точки", + "tooltip": "Точки на интерес" }, "traffic_roads": { + "description": "Пътища с трафик", "tooltip": "Шосета, Улици, и др." }, "service_roads": { - "description": "Обслужващи Улици" + "description": "Обслужващи Улици", + "tooltip": "Обслужващи пътища, пътища в паркинг, полски пътища, и др." }, "paths": { "description": "Пътеки", @@ -457,7 +573,8 @@ "tooltip": "Административни Граници" }, "water": { - "description": "Водни Обекти" + "description": "Водни Обекти", + "tooltip": "Реки, езера, малки езера, язовири, и др." }, "rail": { "description": "Железопътни Обекти", @@ -468,7 +585,8 @@ "tooltip": "Електропроводи , Електроцентрали, Подстанции, и т.н." }, "past_future": { - "description": "Минал/Бъдещ" + "description": "Минал/Бъдещ", + "tooltip": "Проектни, В строеж, Изоставени, Разрушени, и др." }, "others": { "description": "Други", @@ -476,86 +594,225 @@ } }, "area_fill": { + "wireframe": { + "description": "Без запълване (тънки линии)", + "tooltip": "Пускането на режим тънки линии помага да се вижда по-лесно фоновото изображение.", + "key": "W" + }, "partial": { - "description": "Частично Попълнен" + "description": "Частично Попълнен", + "tooltip": "Площите са изобразени със запълване само около вътрешните им ръбове. (Препоръчително за начинаещи картографи)" + }, + "full": { + "description": "Плътно запълване", + "tooltip": "Площите са изобразени плътно запълнени." } }, "restore": { "heading": "Имате незапазени промени", - "description": "Искате ли да възстановите незаписаните промени от предишна сесия?" + "description": "Искате ли да възстановите незаписаните промени от предишна сесия?", + "restore": "Възстанови моите промени", + "reset": "Отмени моите промени" }, "save": { "title": "Запис", + "help": "Прегледайте вашите промени и ги качете в OpenStreetMap, правейки ги видими за другите потребители.", "no_changes": "Няма промени за запис.", "error": "Грешки настъпили докато се опитваме да запазим", "status_code": "Сървърът върна статус с код {code}", "unknown_error_details": "Моля уверете се че сте свързани с интернет.", + "uploading": "Качване на промените в OpenStreetMap...", + "conflict_progress": "Проверка за конфликти: {num} от {total}", "unsaved_changes": "Имате незаписани промени", "conflict": { "header": "Решение на несъвместими редакции.", "count": "Несъвместими {num} от {total}", "previous": "< Предишен", "next": "Следващ >", + "keep_local": "Запази моите", "keep_remote": "Използвай техните", "restore": "Възстанови", "delete": "Остави Изтрито", - "done": "Всички несъответствия са решени!" + "download_changes": "Или свали osmChange файл", + "done": "Всички несъответствия са решени!", + "help": "Друг потребител е променил част от същите обекти, които променихте.\nКликнете на всеки от обектите по-долу за повече информация относно конфликта и изберете дали да запазите\nвашите промени или тези на другия потребител.\n" } }, "merge_remote_changes": { "conflict": { + "deleted": "Този обект беше изтрит от {user}.", + "location": "Този обект беше преместен от вас и {user}.", "nodelist": "Възлите са били променени и от вас и от {user}. ", "memberlist": "Части от връзката бяха променени и от вас и от {user}.", "tags": "Вие променихте {tag} таг на \"{local}\" и {user} се промени на \"{remote}\"." } }, "success": { - "edited_osm": "Редактирахте OSM!", "just_edited": "Вие редактирахте OpenStreetMap!", - "view_on_osm": "Вижте в OSM", - "facebook": "Споделете във Facebook", - "twitter": "Сподели в Twitter", - "google": "Сподели в Google+", - "help_link_text": "Детайли" + "thank_you": "Благодарим ви за подобряването на картата.", + "thank_you_location": "Благодарим ви за подобряването на картата около {where}.", + "help_html": "Вашите промени би трябвало да се появят в OpenStreetMap до няколко минути. При други карти, обновяването може да отнеме по-дълго време.", + "help_link_text": "Детайли", + "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", + "view_on_osm": "Вижте промените в OSM", + "changeset_id": "Вашата промяна #: {changeset_id}", + "like_osm": "Харесвате OpenStreetMap? Свържете се с другите:", + "more": "Още", + "events": "Събития", + "languages": "Езици: {languages}", + "missing": "Липсва ли нещо в този списък?", + "tell_us": "Споделете с нас!" }, "confirm": { + "okay": "OK", "cancel": "Отказ" }, "splash": { "welcome": "Добре дошли в iD редактора за OpenStreetMap", "text": "iD e лесен, но мощен инструмент за попълване на най-добрата свободна карта на света. Това е версия {version}. За повече информация вижте {website} и докладвайте за бъгове в {github}.", - "walkthrough": "Започнете опознавателната обиколка" + "walkthrough": "Започнете опознавателната обиколка", + "start": "Редактиране сега" }, "source_switch": { "live": "live", "lose_changes": "Имате незапазени промени. Смяната на картния сървър ще ги отхвърли. Сигурни ли сте, че искате да смените сървърите?", "dev": "dev" }, + "version": { + "whats_new": "Какво ново в iD {version}" + }, "tag_reference": { "description": "Описание", "on_wiki": "{tag} в wiki.osm.org", "used_with": "използва се с {type}" }, "validations": { + "disconnected_highway": "Прекъснат път", + "disconnected_highway_tooltip": "Пътищата трябва да бъдат свързани с други пътища или входове на сгради.", + "old_multipolygon": "Тагове за мултиполигон на външен път", + "old_multipolygon_tooltip": "Този вид мултиполигон е отхвърлен. Моля, сложете таговете на самия мултиполигон вместо на външния му път. ", "untagged_point": "Точка без тагове.", "untagged_point_tooltip": "Изберете типът обект който описва каква е тази точка.", "untagged_line": "Линия без таг", "untagged_line_tooltip": "Изберете типът обект който описва каква е тази линия.", "untagged_area": "Площен обект без таг", "untagged_area_tooltip": "Изберете типът обект който описва каква е тази площ.", + "untagged_relation": "Релация без тагове", + "untagged_relation_tooltip": "Изберете типът обект, който описва каква е тази релация.", + "many_deletions": "Изтривате {n} обекта: {p} възела, {l} линии, {a} площи, {r} релации. Сигурни ли сте, че искате да направите това? Това ще ги изтрие от картата, която всеки вижда на openstreetmap.org.", "tag_suggests_area": "Тагът {tag} предполага линията да е площен обект, но тя не е", "deprecated_tags": "Отхвърлени тагове: {tags}" }, + "zoom": { + "in": "Навътре", + "out": "Навън" + }, "cannot_zoom": "Не можете да намалявате повече в текущия режим.", "full_screen": "Превключи на Цял Екран", + "gpx": { + "local_layer": "Локален файл", + "drag_drop": "Влачете и пуснете .gpx, .geojson или .kml файл в тази страница или кликнете на бутона в дясно, за да разгледате", + "zoom": "Приближете към слоя", + "browse": "Потърсете файл" + }, "mapillary_images": { - "tooltip": "Снимки за ниво на улицата от Mapillary" + "tooltip": "Снимки за ниво на улицата от Mapillary", + "title": "Фото слой (Mapillary)" + }, + "mapillary_signs": { + "tooltip": "Пътни знаци от Mapillary (трябва да е пуснат Фото слой)", + "title": "Слой пътни знаци (Mapillary)" }, "mapillary": { "view_on_mapillary": "Вижте тази снимка на Mapillary" }, + "openstreetcam_images": { + "tooltip": "Снимки на ниво улица от OpenStreetCam", + "title": "Фото слой (OpenStreetCam)" + }, + "openstreetcam": { + "view_on_openstreetcam": "Вижте това изображение на OpenStreetCam" + }, "help": { - "title": "Помощ" + "title": "Помощ", + "key": "H", + "help": { + "title": "Помощ", + "welcome": "Добре дошли в iD редактора на [OpenStreetMap] (https://www.openstreetmap.org/). С този редактор може да попълвате картата на OpenStreetMap директно от вашия уеб браузър.", + "open_data_h": "Отворени данни", + "open_data": "Промените, които правите в тази карта ще бъдат видим за всеки, който използва OpenStreetMap. Промените ви могат да бъдат базирани на лични сведения, измервания на място, въздушни или на ниво улица изображения. Копирането от комерсиални източници като Google Maps, [е строго забранено] (https://www.openstreetmap.org/copyright).", + "before_start_h": "Преди да започнете", + "before_start": "Трябва да сте запознати с OpenStreetMap и този редактор преди да започнете да редактирате. iD съдържа въвеждащ урок за основните неща при редактирането на OpenStreetMap. Кликнете на \"Стартирай въведението\" на този екран, за да започнете урока - отнема само около 15 минути.", + "open_source_h": "Отворен код", + "open_source": "iD редакторът е съвместен проект с отворен код и в момента използвате версия {version}. Кодът е наличен [в GitHub](https://github.com/openstreetmap/iD).", + "open_source_help": "Може да помогнете на iD с [превод] (https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating) или [докладване на бъгове](https://github.com/openstreetmap/iD/issues)." + }, + "overview": { + "title": "Преглед", + "navigation_h": "Навигация", + "navigation_drag": "Може да влачите картата като задържите {leftclick} левия бутон на мишката и движите мишката. Може също да използвате бутоните със стрелки `↓`, `↑`, `←`, `→` на вашата клавиатура.", + "navigation_zoom": "Може да приближавате и отдалечавате като скролвате с колелото на мишката или чрез кликове върху бутоните {plus} / {minus} отстрани на картата. Може също да използвате бутоните `+`, `-` на вашата клавиатура.", + "features_h": "Обекти от картата", + "features": "Използваме думата \"обекти\", за да опишем неща, които се изобразяват на картата като пътища, сгради и точки на интерес. Всичко в реалния свят може да бъде картографирано като обект в OpenStreetMap. Обектите на картата се представят чрез използването на \"точки\", \"линии\" и \"площи\".", + "nodes_ways": "В OpenStreetmap точките понякога се наричат \"възли\", а линиите понякога се наричат \"пътища\"." + }, + "editing": { + "title": "Редактиране & Запис", + "select_h": "Селектиране", + "select_left_click": "{leftclick} Кликнете с левия бутон върху обект, за да го селектирате. Това ще го открои с пулсиращо сияние, а страничния панел ще покаже подробности за този обект, като име и адрес.", + "select_right_click": "{rightclick} Кликнете с десния бутон върху обект, за да изведете менюто за редакция, което показва действията, които са възможни, като завъртане, преместване и изтриване.", + "multiselect_h": "Селектиране на множество обекти", + "multiselect_shift_click": "`{shift}`+{leftclick} клик с ляв бутон, за да изберете няколко обекта. Това улеснява местенето и изтриването на множество елементи.", + "multiselect_lasso": "Друг начин за селектиране на множество обекти е да задържите клавиша `{shift}` и след това натиснете и задържите левия бутон на мишката, като влачите мишката рисувайки ласо селекция. Всички точки намиращи се вътре в ласото ще бъдат селектирани.", + "undo_redo_h": "Отмени & Повтори", + "undo_redo": "Вашите редакции се съхраняват локално във вашия браузър докато не решите да ги запишете в сървъра на OpenStreetMap. Можете да отменяте редакции като кликнете бутона {undo} **Отмени**, или да ги повторите като кликнете бутона {redo} **Повтори**.", + "save_h": "Запис", + "save": "Кликнете {save} **Запис**, за да завършите редакциите си и да ги изпратите в OpenStreetMap. Не забравяйте да записвате работата си често!", + "save_validation": "На екрана за запис ще имате възможност да прегледате какво сте направили. iD ще извърши също и някои елементарни проверки за липсващи данни и може да предложи полезни препоръки и предупреждения, ако нещо не изглежда правилно.", + "upload_h": "Качване", + "upload": "Преди да качите своите промени трябва да въведете [коментар на промяната](https://wiki.openstreetmap.org/wiki/Good_changeset_comments). След това кликнете **Качи** за да изпратите промените си към OpenStreetMap, където те ще бъдат нанесени в картата и ще бъдат видими за всеки.", + "backups_h": "Автоматично резервно копие", + "backups": "Ако не можете да завършите редакциите си наведнъж, например компютърът ви забие или затворите прозореца на браузера, редакциите ви се запазват във вашия браузър. Можете да се върнете отново по-късно (на същия компютър и браузър) и iD ще ви предложи да възстанови работата ви.", + "keyboard_h": "Клавишни комбинации", + "keyboard": "Може да прегледате списък с клавишните комбинации като натиснете клавиш '?'." + }, + "feature_editor": { + "title": "Редактор на обекти", + "intro": "\"Редакторът на обекти\" се появява отстрани картата и ви позволява да разглеждате и редактирате цялата информация за избрания обект.", + "definitions": "Горната част показва вида на обекта. Средната част съдържа *полета*, които показват атрибутите на обекта, като име и адрес.", + "type_h": "Вид обект", + "type": "Може да кликнете върху вида на обекта за да го промените. Всичко, което съществува в реалния свят може да бъде добавено в OpenStreetMap, така че има хиляди видове обекти, от които може да избирате.", + "type_picker": "Помощникът за избор на вид показва най-често използваните видове, като паркове, болници, ресторанти, пътища и сгради. Може да търсите всичко като напишете какво търсите в търсачката. Може също да кликнете иконата {inspect} **Информация** до вида на обекта, за да научите повече за него. ", + "fields_h": "Полета", + "fields_all_fields": "Секцията \"Всички полета\" съдържа детайлите на всички обекти, които можете да редактирате. В OpenStreetMap, всички полета са незадължителни, така че е OK да оставите поле празно, ако не сте сигурни.", + "fields_example": "Всеки вид обект ще съдържа различни полета. Например обект път може да съдържа полета за повърхност и ограничение на скоростта, докато ресторант може да съдържа полета за вида на храната, която се сервира и работно време.", + "fields_add_field": "Може също да кликнете на падащото меню \"Добави поле\", за да добавите още полета, като описание, Връзка към Wikipedia, достъп за инвалиди и много други.", + "tags_h": "Тагове", + "tags_all_tags": "Под секцията с полета, може да разширите секцията \"Всички тагове\", за да редактирате всеки един от \"таговете\" на OpenStreetMap за дадения обект. Всеки таг съдържа елемент \"ключ\" и \"стойност\", които дефинират всички обекти съхраняващи се в OpenStreetMap.", + "tags_resources": "Редактирането на таговете на обект изисква средно ниво на познаване на OpenStreetMap. Добре е да се консултирате с ресурси като [OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/Main_Page) или [Taginfo](https://taginfo.openstreetmap.org/) , за да научите повече за установените практики при тагването в OpenStreetMap." + }, + "points": { + "title": "Точки", + "intro": "*Точки* могат да бъдат използвани, за да означат обекти като магазини, ресторанти и паметници. Те маркират определено местоположение и описват какво има там.", + "add_point_h": "Добавяне на точки", + "add_point": "За да добавите точка, кликнете бутонът {point} **Точка** в лентата с инструменти над картата или натиснете клавиш `1`. Това ще смени курсора на мишката с кръст.", + "add_point_finish": "За да поставите нова точка на картата, позиционирайте курсора, там където трябва да е точката, след това {leftclick} килкнете с ляв бутон или натиснете `Space`.", + "move_point_h": "Преместване на точки", + "move_point": "За да преместите точка, поставете курсора на мишката над точката и натиснете и задръжте {leftclick} левия бутон на мишката докато провлачвате точката до новото и местоположение.", + "delete_point_h": "Изтриване на точки", + "delete_point": "Окей е да изтривате обекти, които не съществуват на място. Изтриването на обект от OpenStreetMap, го премахва от картата, която всеки използва, така че трябва да бъдете сигурни, че даден обект наистина го няма преди да го изтриете.", + "delete_point_command": "За да изтриете точка, {rightclick} кликнете с десния бутон на мишката, за да я изберете и изведете менюто за редакция, след това използвайте командата {delete} **Изтриване**" + }, + "lines": { + "title": "Линии", + "intro": "*Линии* се използват да представят обекти като пътища, жп линии и реки. Линиите трябва бъдат чертани по средата на обекта, който изобразяват.", + "add_line_h": "Добавяне на линии", + "add_line": "За да добавите линия, кликнете на бутона {line} **Линия** в лентата с инструменти над картата или натиснете бутона `2`. Това ще смени курсора на мишката с кръст.", + "add_line_draw": "След това, позиционирайте курсора, там където линията започва и кликнете с левия бутон или натиснeте `Space`, за да започнете да поставяте възли по продължението на линията. Продължете с поставянето на още възли кликайки или натискайки на `Space`. Докато чертаете, можете да приближавате или отдалечавате изгледа, или да местите изгледа, за да добавяте повече подробности.", + "add_line_finish": "За да завършите линия, натиснете `{return}` или кликнете отново на последния възел.", + "modify_line_h": "Промяна на линии", + "modify_line_dragnode": "Често ще виждате линии, които не с правилна форма, например път, който не съвпада с фоновото изображение. За да оправите формата на линия, първо кликнете с ляв бутон, за да я изберете. Всички възли на линията ще бъдат изобразени като малки кръгове. Можете тогава да провлачвате възлите към по-добри местоположения." + } }, "intro": { "graph": { @@ -1457,7 +1714,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Телефон", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2436,15 +2692,6 @@ "type/restriction/no_u_turn": { "name": "Без обратен завой" }, - "type/restriction/only_left_turn": { - "name": "Завой само на ляво" - }, - "type/restriction/only_right_turn": { - "name": "Завой само на дясно" - }, - "type/restriction/only_straight_on": { - "name": "Без завиване" - }, "type/route": { "name": "Маршрут" }, @@ -2529,7 +2776,7 @@ "attribution": { "text": "Условия & oбратна връзка" }, - "description": "Граници на изображения и дата на заснемане. Надписите се появяват при ниво на увеличение 14 или по-високо.", + "description": "Граници на изображения и дата на заснемане. Надписите се появяват при ниво на увеличение 13 или по-високо.", "name": "Стари DigitalGlobe Премиум изображения" }, "DigitalGlobe-Standard": { @@ -2543,7 +2790,7 @@ "attribution": { "text": "Условия & oбратна връзка" }, - "description": "Граници на изображения и дата на заснемане. Надписите се появяват при ниво на увеличение 14 или по-високо.", + "description": "Граници на изображения и дата на заснемане. Надписите се появяват при ниво на увеличение 13 или по-високо.", "name": "Стари стандартни DigitalGlobe сателитни изображения." }, "EsriWorldImagery": { @@ -2627,6 +2874,10 @@ "description": "Жълто = Публично достъпни картографски данни от US Census. Червено = Данни, които не са нанесени в OpenStreetMap", "name": "TIGER Пътища 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Път: Зелено очертание = некласифициран. Кафяво очертание = track. Повърхност: чакъл = светло кафяво запълване, асфалт = черно, павиран = сиво, земен = бяло, бетон = синьо, трева = зелено. Сезонен = бели черти", + "name": "Слой Горски пътища в САЩ" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" @@ -2723,7 +2974,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Картни тайлове от Stamen Design, под CC BY 3.0" + "text": "Картни тайлове от Stamen Design, под CC BY 3.0. Данни от OpenStreetMap, лиценз ODbL" }, "name": "Stamen Топография" }, @@ -2739,6 +2990,26 @@ }, "name": "Thunderforest Ландшафт" } + }, + "community": { + "Central-Pennsylvania-OSM": { + "name": "Централна Пенсилвания OSM" + }, + "OSM-Chattanooga": { + "name": "OSM Чатануга", + "description": "OpenStreetMap потребителската група за Чатануга" + }, + "OSM-NYC": { + "name": "OpenStreetMap Ню Йорк", + "description": "Картографи и OpenStreetMap потребители, разработчици и ентусиасти в района на Ню Йорк Метрополитън" + }, + "OSM-Portland": { + "name": "OpenStreetMap Портланд", + "description": "Картографи и OpenStreetMap потребители в района на Портланд" + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/bn.json b/vendor/assets/iD/iD/locales/bn.json index 57042c608..02c98a5df 100644 --- a/vendor/assets/iD/iD/locales/bn.json +++ b/vendor/assets/iD/iD/locales/bn.json @@ -1,5 +1,9 @@ { "bn": { + "icons": { + "information": "তথ্য", + "remove": "অপসারণ" + }, "modes": { "add_area": { "title": "এলাকা", @@ -25,6 +29,9 @@ }, "draw_line": { "tail": "রেখাটিতে অারো নোড সংযোজন-এর জন্য ক্লিক করুন। অন্যান্য রেখাগুলির সাথে সংযোজন-এর জন্য তাদের উপর ক্লিক করুন। রেখাটি শেষ করার জন্য দুইবার ক্লিক করুন।" + }, + "drag_node": { + "connected_to_hidden": "এটি সম্পাদনা করা যাবে না কারণ এটি একটি গোপন বৈশিষ্টের সাথে যুক্ত।" } }, "operations": { @@ -94,7 +101,8 @@ "vertex": "একটি গমনপথ থেকে একটি নোড মুছে ফেলা হয়েছে।", "line": "একটি রেখা মুছে ফেলা হয়েছে।", "area": "একটি এলাকা মুছে ফেলা হয়েছে।", - "relation": "একটি সম্পর্ক মুছে ফেলা হয়েছে।" + "relation": "একটি সম্পর্ক মুছে ফেলা হয়েছে।", + "multiple": "{n}টি অপসারিত বৈশিষ্ট।" } }, "add_member": { @@ -302,12 +310,7 @@ "unsaved_changes": "অাপনার কিছু পরিবর্তন সংরক্ষণ করা বাকি অাছে" }, "success": { - "edited_osm": "ওপেনস্ট্রীটম্যাপ সম্পাদিত হয়েছে!", - "just_edited": "অাপনি এইমাত্র ওপেনস্ট্রীটম্যাপ সম্পাদন করলেন!", - "view_on_osm": "ওপেনস্ট্রীটম্যাপে দেখুন", - "facebook": "ফেসবুক-এ জানান", - "twitter": "টুইটার-এ জানান", - "google": "গুগল+ এ জানান" + "just_edited": "অাপনি এইমাত্র ওপেনস্ট্রীটম্যাপ সম্পাদন করলেন!" }, "splash": { "welcome": "iD ওপেনস্ট্রীটম্যাপ সম্পাদকে অাপনাকে স্বাগতম", @@ -641,7 +644,6 @@ "label": "ধরন" }, "phone": { - "label": "ফোন", "placeholder": "+৩১ ৪২ ১২৩ ৪৫৬৭" }, "place": { diff --git a/vendor/assets/iD/iD/locales/bs.json b/vendor/assets/iD/iD/locales/bs.json index 5b925cc05..8e71b80cd 100644 --- a/vendor/assets/iD/iD/locales/bs.json +++ b/vendor/assets/iD/iD/locales/bs.json @@ -253,12 +253,7 @@ "unsaved_changes": "Imate promjene koje nisu spašene" }, "success": { - "edited_osm": "OSM uređen!", - "just_edited": "Upravo ste uredili OpenStreetMap kartu!", - "view_on_osm": "Pogledajte na OSM-u", - "facebook": "Podijeliti na Facebooku", - "twitter": "Podijeliti na Twitteru", - "google": "Podijeliti na Google+" + "just_edited": "Upravo ste uredili OpenStreetMap kartu!" }, "splash": { "welcome": "Dobrodošli u ID - OpenStreetMap uređivač", @@ -582,7 +577,6 @@ "label": "Vrsta" }, "phone": { - "label": "Telefon", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -655,9 +649,6 @@ "trail_visibility": { "label": "Vidljivost traga" }, - "vending": { - "label": "Vrsta dobara" - }, "water": { "label": "Vrsta" }, diff --git a/vendor/assets/iD/iD/locales/ca.json b/vendor/assets/iD/iD/locales/ca.json index 336fc2cc7..026c26a1f 100644 --- a/vendor/assets/iD/iD/locales/ca.json +++ b/vendor/assets/iD/iD/locales/ca.json @@ -1,5 +1,10 @@ { "ca": { + "icons": { + "information": "Informació", + "remove": "Eliminar", + "undo": "Desfer" + }, "modes": { "add_area": { "title": "Àrea", @@ -163,7 +168,6 @@ "annotation": "S'han fusionat {n} objectes.", "not_eligible": "Aquests objectes no es poden fusionar.", "not_adjacent": "Aquests objectes no es poden fusionar perquè els seu extrems no estan connectats.", - "restriction": "Aquests objectes no es poden fusionar ja que com a mínim un de ells és membre de la relació \"{relation}\".", "incomplete_relation": "Aquests objectes no es poden fusionar perquè com a mínim un de ells no s'ha baixat del tot.", "conflicting_tags": "Aquests objectes no es poden fusionar donat que algunes de les seves etiquetes tenen valors diferents." }, @@ -306,8 +310,19 @@ "no_left_turn": "Prohibició del gir a l'esquerra {indirecte}", "no_right_turn": "Prohibició del gir a la dreta {indirecte}", "no_u_turn": "Prohibició del gir total {indirecte}", - "no_straight_on": "Prohibició de seguir recte {indirecte}" - } + "no_straight_on": "Prohibició de seguir recte {indirecte}", + "only_left_turn": "NOMÉS gir a l'esquerra {indirecte}", + "only_right_turn": "NOMÉS gir a la dreta {indirecte}", + "only_u_turn": "NOMÉS gir total {indirecte}", + "only_straight_on": "NOMÉS seguir recte {indirecte}", + "allowed_left_turn": "Gir a l'esquerra permès {indirecte}", + "allowed_right_turn": "Gir a la dreta permès {indirecte}", + "allowed_u_turn": "Gir total permès {indirecte}", + "allowed_straight_on": "Segui recte permès {indirecte}" + }, + "from": "DES DE", + "via": "VIA", + "to": "A" } }, "undo": { @@ -478,6 +493,7 @@ "title": "Fons", "description": "Paràmetres de configuració del fons", "key": "B", + "backgrounds": "Fons", "none": "Cap", "best_imagery": "Font d'imatgeria millor coneguda per a aquesta ubicació", "switch": "Senyals de trànsit ", @@ -620,13 +636,7 @@ } }, "success": { - "edited_osm": "Heu editat l'OSM!", "just_edited": "Acabeu d'editar l'OpenStreetMap!", - "view_on_osm": "Mostra-ho a OSM", - "facebook": "Compartiu-ho a Facebook", - "twitter": "Compartiu-ho al Twitter", - "google": "Compartiu-ho a Google+", - "help_html": "Els vostres canvis s'haurien de veure a la capa \"Estàndard\" en pocs minuts. Altres capes i determinats objectes poden tardar més.", "help_link_text": "Detalls", "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" }, @@ -727,7 +737,8 @@ "save_h": "Desar", "upload_h": "Puja", "backups_h": "Copia de seguretat automàtica", - "keyboard_h": "Dreceres de teclat" + "keyboard_h": "Dreceres de teclat", + "keyboard": "Pots veure una llista de dreceres del teclat prement la tecla `?`." }, "feature_editor": { "title": "Editor de característiques", @@ -1945,7 +1956,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telèfon", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2366,9 +2376,6 @@ "label": "Tipus", "placeholder": "Predeterminat" }, - "vending": { - "label": "Tipus de mercaderies" - }, "visibility": { "label": "Visibilitat", "options": { @@ -4721,18 +4728,6 @@ "name": "Prohibició del gir total", "terms": "Prohibit canviar de sentit" }, - "type/restriction/only_left_turn": { - "name": "Només gir a l'esquerra", - "terms": "Gir a l'esquerra obligatori" - }, - "type/restriction/only_right_turn": { - "name": "Només gir a la dreta", - "terms": "Gir a la dreta obligatori" - }, - "type/restriction/only_straight_on": { - "name": "Prohibició de tots els girs", - "terms": "Prohibit girar, no girs, cap gir, no girar, seguir recte" - }, "type/route": { "name": "Ruta", "terms": "Ruta" @@ -4855,7 +4850,6 @@ "attribution": { "text": "Termes i comentaris" }, - "description": "Limitacions d'imatges i dates de captura. Les etiquetes apareixen al nivell de zoom 14 i superior.", "name": "Imatges de DigitalGlobe Premium Vintage" }, "DigitalGlobe-Standard": { @@ -4869,7 +4863,6 @@ "attribution": { "text": "Termes i comentaris" }, - "description": "Limitacions d'imatges i dates de captura. Les etiquetes apareixen al nivell de zoom 14 i superior.", "name": "Imatges de DigitalGlobe estàndard Vintage" }, "EsriWorldImagery": { @@ -4987,7 +4980,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Mapa Base d'Austria, basat en dades governamentals.", + "description": "Mapa base d'Àustria, basat en dades governamentals.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -5048,9 +5041,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Quadricula de mapes de Stamen Design, sota CC BY 3.0" - }, "name": "Stamen Terrain" }, "tf-cycle": { @@ -5065,6 +5055,39 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "OSM-India-facebook": { + "description": "Millora OpenStreetMap a l'Índia" + }, + "OSM-japan-facebook": { + "name": "Comunitat de Japó d'OpenStreetMap", + "description": "Mapador i usuari d'OpenStreetMap a Japó" + }, + "OSM-japan-twitter": { + "name": "Twitter de Japó d'OpenStreetMap", + "description": "Etiqueta a Twitter: {url}" + }, + "OSM-TW-facebook": { + "name": "Comunitat de Taiwan d'OpenStreetMap", + "description": "Grup de Facebook per mapadors i usuaris d'OpenStreetMap per discutir assumptes sobre Taiwan." + }, + "OSM-SoCal": { + "name": "OpenStreetMap Califòrnia del Sud", + "extendedDescription": "OpenStreetMap (OSM) Califòrnia del Sud és per a tothom interessat en el mapatge que s'uneixi a treballar amb OpenStreetMap. OpenStreetMap, la Viquipèdia dels mapes, és un mapa de codi obert gratuït del món sent creat per més de 1000000 de voluntaris al voltant del món. Tothom és benvingut. Si no coneixes OpenStreetMap, t'ensenyarem. Si tens una idea d'un projecte de mapatge o fins i tot una excursió de camp que el grup pot fer, genial!" + }, + "OSM-AR-telegram": { + "name": "Telegram d'OpenStreetMap Argentina", + "description": "Uneix-te a la comunitat argentina d'OpenStreetMap a Telegram" + }, + "OSM-AR-twitter": { + "name": "Twitter d'Argentina d'OpenStreetMap", + "description": "Segueix-nos a Twitter a {url}" + }, + "OSM-Reddit": { + "name": "OpenStreetMap a Reddit", + "description": "/r/openstreetmap/ és un bon lloc per aprendre més sobre OpenStreetMap. Pregunta'ns qualsevol cosa!" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/ckb.json b/vendor/assets/iD/iD/locales/ckb.json index c4e0968d5..312d5611d 100644 --- a/vendor/assets/iD/iD/locales/ckb.json +++ b/vendor/assets/iD/iD/locales/ckb.json @@ -2,7 +2,8 @@ "ckb": { "modes": { "add_area": { - "title": "ناوچە" + "title": "ناوچە", + "description": "زیادکردنی باخچە و بینا و گۆم و شوێنی تر بۆ سەر نەخشەکە." }, "add_line": { "title": "هێڵ" @@ -11,13 +12,18 @@ "title": "خاڵ" } }, + "operations": { + "continue": { + "title": "بەردەوامبوون" + } + }, "tooltip_keyhint": "کورتبڕ:", "translate": { "translate": "وەرگێڕان", "localized_translation_language": "هەڵبژاردنی زمان", "localized_translation_name": "ناو" }, - "logout": "دەرچوون", + "logout": "چوونە دەرەوە", "report_a_bug": "ناردنی هەڵە", "help_translate": "یارمەتیدان بۆ وەرگێڕان", "commit": { diff --git a/vendor/assets/iD/iD/locales/cs.json b/vendor/assets/iD/iD/locales/cs.json index ae3552878..f62575ebc 100644 --- a/vendor/assets/iD/iD/locales/cs.json +++ b/vendor/assets/iD/iD/locales/cs.json @@ -1,5 +1,10 @@ { "cs": { + "icons": { + "information": "Zobrazit popis z wiki.osm.org", + "remove": "Odstranit", + "undo": "Zpět" + }, "modes": { "add_area": { "title": "Plocha", @@ -7,8 +12,8 @@ "tail": "Klikněte na mapu a začněte tak kreslit plochu, jako třeba park, jezero nebo budovu." }, "add_line": { - "title": "Čára", - "description": "Přidat do mapy silnice, ulice, stezky, potoky či jiné čáry.", + "title": "Linie", + "description": "Přidat do mapy silnice, ulice, stezky, potoky či jiné linie.", "tail": "Klikněte na mapu a začněte tak kreslit silnice, stezky nebo trasy." }, "add_point": { @@ -25,6 +30,9 @@ }, "draw_line": { "tail": "Body k linii přidáte kliknutím. Když kliknete na jinou linii, připojíte linie k sobě. Editaci ukončíte dvojklikem." + }, + "drag_node": { + "connected_to_hidden": "Tento objekt nelze upravit, protože je spojen se skrytým objektem." } }, "operations": { @@ -44,9 +52,9 @@ "continue": { "key": "A", "title": "Pokračovat", - "description": "Navázat na čáru.", - "not_eligible": "Nelze navázat na žádnou čáru.", - "multiple": "Zde je možné navázat na několik čar. Stiskněte klávesu Shift a kliknutím zvolte jednu z čar.", + "description": "Navázat na linii.", + "not_eligible": "Nelze navázat na žádnou linii.", + "multiple": "Zde je možné navázat na několik linií. Stiskněte klávesu Shift a kliknutím zvolte jednu z nich.", "annotation": { "line": "Prodloužena linie.", "area": "Plocha pokračuje." @@ -93,11 +101,11 @@ }, "straighten": { "title": "Narovnat", - "description": "Narovnat tuto čáru.", + "description": "Narovnat tuto linii.", "key": "S", "annotation": "Narovnána linie.", "too_bendy": "Objekt nelze narovnat, protože je příliš zakroucený.", - "connected_to_hidden": "Čáru nelze narovnat, protože je napojená na skrytý objekt." + "connected_to_hidden": "Linii nelze narovnat, protože je napojená na skrytý objekt." }, "delete": { "title": "Smazat", @@ -160,7 +168,6 @@ "annotation": "{n} prvků spojeno.", "not_eligible": "Objekty nelze spojit v jeden.", "not_adjacent": "Objekty nelze spojit, protože jejich koncové body nejsou spojené.", - "restriction": "Objekty nelze spojit, protože aspoň jeden z nich je členem relace \"{relation}\".", "incomplete_relation": "Tyto objekty nelze spojit, protože jsou stažené jen částečně.", "conflicting_tags": "Objekty nelze spojit, protože některé z jejich vlastností kolidují." }, @@ -288,6 +295,25 @@ } } }, + "restriction": { + "controls": { + "distance": "Vzdálenost", + "distance_up_to": "Do max: {distance}", + "via": "Přes", + "via_node_only": "Pouze bod", + "via_up_to_one": "Max 1 cesta", + "via_up_to_two": "Max 2 cesty" + }, + "help": { + "indirect": "(nepřímé)", + "from": "Z", + "via": "PŘES", + "to": "DO", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}" + } + }, "undo": { "tooltip": "Zpět: {action}", "nothing": "Není co vracet." @@ -363,6 +389,7 @@ "key": "H", "title": "Historie", "selected": "{n} vybráno", + "no_history": "Žádná historie (nový prvek)", "version": "Verze", "last_edit": "Poslední úprava", "edited_by": "Upravil(a)", @@ -600,15 +627,17 @@ } }, "success": { - "edited_osm": "OSM upraveno!", "just_edited": "Právě jste upravil/a OpenStreetMap!", - "view_on_osm": "Zobrazit na OSM", - "facebook": "Sdílet na Facebooku", - "twitter": "Sdílet na Twitteru", - "google": "Sdílet na Google+", - "help_html": "Vaše úpravy by se obvykle měly objevit na „Standardní“ vrstvě během několika minut. U rozsáhlejších objektů a ostatních vrstev to může trvat déle.", + "thank_you": "Děkujeme za zlepšení mapy.", + "thank_you_location": "Děkujeme za zlepšení mapy okolo {where}.", + "help_html": "Vaše změny by se měly objevit na \"standardní\" mapě OpenStreetMap během pár minut. Na ostatních mapách to může trvat déle.", "help_link_text": "Více", - "help_link_url": "https://wiki.openstreetmap.org/wiki/Cs:FAQ#Zrovna_jsem_ud.C4.9Blal_n.C4.9Bjak.C3.A9_zm.C4.9Bny_v_map.C4.9B._Jak_uvid.C3.ADm_sv.C3.A9_zm.C4.9Bny.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/Cs:FAQ#Zrovna_jsem_ud.C4.9Blal_n.C4.9Bjak.C3.A9_zm.C4.9Bny_v_map.C4.9B._Jak_uvid.C3.ADm_sv.C3.A9_zm.C4.9Bny.3F", + "view_on_osm": "Zobrazit změny na OSM", + "changeset_id": "Vaše sada změn #: {changeset_id}", + "like_osm": "Líbí se Vám OpenStreetMap? Spojte se s ostatními:", + "languages": "Jazyky: {languages}", + "tell_us": "Řekněte nám o tom!" }, "confirm": { "okay": "OK", @@ -687,8 +716,12 @@ "title": "Nápověda", "welcome": "Vítejte v editoru iD pro [OpenStreetMap](https://www.openstreetmap.org/). Tímto editorem můžete upravovat OpenStreetMap přímo v browseru.", "open_data_h": "Otevřená data", + "open_data": "Editace, které zde uložíte, budou ihned zapsány do ostré databáze!! Ukládajte pouze reálné objekty a to z osobní znalosti, GPS záznamů či volně dostupných leteckých map. Kopírování z komerčních zdrojů je [striktně zakázáno](https://www.openstreetmap.org/copyright).", "before_start_h": "Než začnete", - "open_source_h": "Otevřený kód" + "before_start": "Měli byste být obeznámeni s OpenStreetMap a tímto editorem, než začnete editovat. iD nabítí průvodce, který Vás naučí základy editace OpenStreetMap. Klikněte na \"Začít s procházkou\" na této obrazovce pro spuštení průvodce - zabere jen okolo 15 minut.", + "open_source_h": "Otevřený kód", + "open_source": "Editor iD je společně vytvářený open source projekt a Vy právě používáte verzi {version}. Zdrojový kód je dostupný [na webu GitHub](https://github.com/openstreetmap/iD).", + "open_source_help": "Můžete iD editoru pomoci [překladem](https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating) nebo [hlášením chyb](https://github.com/openstreetmap/iD/issues)." }, "overview": { "title": "Přehled", @@ -910,7 +943,9 @@ }, "areas": { "title": "Plochy", + "add_playground": "*Plochy* používáme pro hranice budov, lesů, jezer apod.{br}Ovšem také jimi můžeme detailně zakreslit prvky, které by normálně byly body.**Přidejte plochu tlačítkem {button} Plocha**", "start_playground": "Pojďme přidat toto dětské hřiště. Plochu vytvoříte naklikáním bodů okolo.\n**Začněte kliknutím do rohu**", + "continue_playground": "Pokračujte přidáváním bodů do rohů hřiště. {br}\nPlochu můžete spojit s existující pěšinou. (Pokud tomu naopak chcete zabránit držte klávesu Alt)\n**Přidejte další body do hřiště**", "finish_playground": "Dokončete plochu kliknutím na první či poslední bod (též lze klávesou Enter).\n**Dokončete obrys hřšitě.**", "search_playground": "**Vyhledejte '{preset}'.**", "choose_playground": "**Zvolte {preset}.**", @@ -952,7 +987,7 @@ }, "buildings": { "title": "Budovy", - "add_building": "OSM je mimojiné také největší databází budov.{br}\nPokud někde budova chybí, můžete přidat její obrys.\n**Přidejte novou plochu tlačítkem {button} Plocha**", + "add_building": "OSM je mimojiné také největší databází budov.{br}\nPokud někde budova chybí, můžete přidat její obrys.{br}\nPozor: letecké snímky v ČR často nesedí - neopravujte, prosím, existující budovy, pokud si nejste jisti.\n**Přidejte novou plochu tlačítkem {button} Plocha**", "start_building": "Pojďme přidat třeba tenhle barák.{br}\nZkuste budovu oklikat co nejpřesněji.\n**Začněte kreslit kliknutím do rohu**", "continue_building": "Přidejte postupně další body do rohů, můžete i přizoomovat.{br}\nZadávání ukončíte kliknutím na první či poslední bod.\n**Dokončete obrys budovy**", "retry_building": "Nějak se vám to asi nezdařilo. Zkuste to prosím znovu.", @@ -975,6 +1010,8 @@ }, "startediting": { "title": "Začít s editací", + "help": "Nyní jste připraveni editovat OpenStreetMap!{br}\nTuto prohlídku si můžete kdykoliv znovu přehrát nebo se podívejte na další dokumentaci stisknutím {button} tlačítka Nápověda.", + "shortcuts": "Seznam příkazů a jejich klávesové zkratky můžete zobrazit stisknutím klávesy `{key}`.", "save": "Nezapomeňte pravidelně ukládat své úpravy!", "start": "Začít mapovat!" } @@ -1012,19 +1049,27 @@ "title": "Procházení", "navigation": { "title": "Navigace", - "zoom": "Přiblížit / /oddálit" + "pan": "Posun mapy", + "pan_more": "Posun mapy o jednu obrazovku", + "zoom": "Přiblížit / /oddálit", + "zoom_more": "Více přiblížit / oddálit" }, "help": { - "title": "Nápověda" + "title": "Nápověda", + "help": "Zobrazit nápovědu", + "keyboard": "Zobrazit klávesové zkratky" }, "display_options": { "title": "Vlastnosti zobrazení", "background": "Zobrazit volby pozadí", + "background_switch": "Zapnout předchozí použité pozadí", "map_data": "Zobrazit volby mapových dat", "fullscreen": "Vstoupit do režimu celé obrazovky", + "wireframe": "Přepnout výplň budov", "minimap": "Přepnout minimapu" }, "selecting": { + "title": "Vybrání prvků", "select_one": "Zvolit jednu vlastnost", "select_multi": "Zvolit více vlastností" } @@ -1059,6 +1104,20 @@ } }, "units": { + "feet": "{quantity} stop", + "miles": "{quantity} mil", + "square_feet": "{quantity} stop²", + "square_miles": "{quantity} mil²", + "acres": "{quantity} arů", + "meters": "{quantity} m", + "kilometers": "{quantity} km", + "square_meters": "{quantity} m²", + "square_kilometers": "{quantity} km²", + "hectares": "{quantity} ha", + "area_pair": "{area1} ({area2})", + "arcdegrees": "{quantity}°", + "arcminutes": "{quantity}′", + "arcseconds": "{quantity}″", "north": "S", "south": "J", "east": "V", @@ -1961,7 +2020,6 @@ "placeholder": "1, 2, 3…" }, "phone": { - "label": "Telefon", "placeholder": "+420 603 123456" }, "piste/difficulty": { @@ -2382,9 +2440,6 @@ "label": "Typ", "placeholder": "Výchozí" }, - "vending": { - "label": "Druh zboží" - }, "visibility": { "label": "Viditelnost", "options": { @@ -3652,6 +3707,9 @@ "name": "Jezdecká stezka", "terms": "jezdecká stezka,jezdecká trasa,stezka pro jezdce,stezka pro koně,koňská stezka" }, + "highway/bus_stop": { + "name": "Zastávka autobusu" + }, "highway/corridor": { "name": "Chodba", "terms": "chodba,koridor" @@ -3681,7 +3739,7 @@ }, "highway/give_way": { "name": "Značka Dej přednost", - "terms": "dej přednost v jízdě,dej přednost,značka přednosti v jízdě,vedlejší silnice,vedlejší ulice" + "terms": "dej přednost v jízdě,dej přednost,značka přednosti v jízdě,vedlejší silnice,vedlejší ulice" }, "highway/living_street": { "name": "Obytná zóna", @@ -3783,7 +3841,7 @@ }, "highway/stop": { "name": "Stopka", - "terms": "stopka,stop,dej přednost v jízdě,přednost,značka,dopravní značka" + "terms": "stopka,stop,stůj,dej přednost v jízdě,přednost,značka,dopravní značka" }, "highway/street_lamp": { "name": "Pouliční lampa", @@ -4723,6 +4781,9 @@ "public_transport/stop_area": { "name": "Oblast zastávky" }, + "public_transport/stop_position": { + "name": "Místo zastavení veřejné dopravy" + }, "public_transport/stop_position_aerialway": { "name": "Místo zastavení lanovky" }, @@ -4796,6 +4857,9 @@ "name": "Úzkorozchodná dráha", "terms": "úzkorozchodná dráha,úzkokolejná dráha,úzkokolejka" }, + "railway/platform": { + "name": "Železniční nástupiště" + }, "railway/rail": { "name": "Kolej", "terms": "koleje,železnice,vlak,trať" @@ -4825,6 +4889,9 @@ "name": "Tramvaj", "terms": "tramvaj,tranvaj,šalina,šmirgl,tramvajka,elektrika,električka,tram" }, + "railway/tram_stop": { + "name": "Zastávka tramvaje" + }, "relation": { "name": "Relace", "terms": "relace,vztah,seznam,objekt" @@ -5475,18 +5542,6 @@ "name": "Zákaz otáčení", "terms": "otáčení,otočit,u-turn" }, - "type/restriction/only_left_turn": { - "name": "Přikázaný směr jízdy vlevo", - "terms": "přikázáno jet vlevo,jen vlevo,pouze vlevo,odbočit vlevo" - }, - "type/restriction/only_right_turn": { - "name": "Přikázaný směr jízdy vpravo", - "terms": "přikázáno jet vpravo,jen vpravo,pouze vpravo,odbočit vpravo" - }, - "type/restriction/only_straight_on": { - "name": "Přikázaný směr jízdy přímo", - "terms": "přikázaný směr jízdy rovně,zákaz odbočit,zákaz zatočit,pouze rovně,pouze přímo,jen rovně,jen přímo" - }, "type/route": { "name": "Trasa", "terms": "trasa,cesta,linka,stopa,značka,spojení" @@ -5825,6 +5880,50 @@ "text": "Mapy © Thunderforest, data © přispěvatelé OpenStreetMap" } } + }, + "community": { + "talk-cz-mailinglist": { + "description": "Talk-cz je hlavní komunikační kanál české komunity" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area OpenStreetMappers", + "description": "Vylepšete OpenStreetMap v Bay Area" + }, + "Central-Pennsylvania-OSM": { + "name": "OSM Střední Pensylvánie" + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM" + }, + "GeoPhilly": { + "name": "GeoPhilly" + }, + "Mapping-DC-meetup": { + "name": "Mapování DC", + "description": "Vylepšete OpenStreetMap na území DC" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "Uživatelská skupina OpenStreetMap pro Chatanoogu" + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland" + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack", + "description": "Všichni jsou vítaní! Přihlaste se na {signupUrl}" + }, + "Maptime-Australia-Slack": { + "name": "Maptime Australia Slack", + "description": "Přihlaste se na {signupUrl}" + }, + "OSM-Reddit": { + "name": "OpenStreetMap na Redditu", + "description": "/r/openstreetmap/ je vynikající místo, kde lze zjistit více o OpenStreetMap. Zeptejte se nás na cokoliv!" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/da.json b/vendor/assets/iD/iD/locales/da.json index bec733df3..fae66d541 100644 --- a/vendor/assets/iD/iD/locales/da.json +++ b/vendor/assets/iD/iD/locales/da.json @@ -1,5 +1,10 @@ { "da": { + "icons": { + "information": "info", + "remove": "fjern", + "undo": "fortryd" + }, "modes": { "add_area": { "title": "Område", @@ -145,7 +150,8 @@ "vertex": "Forbandt en vej til en anden.", "line": "Forbandt en vej til en linje.", "area": "Forbandt en vej til et område." - } + }, + "restriction": "Disse kortobjekter kan ikke forbindes, da det ville skade en \"{relation}\"-relation." }, "disconnect": { "title": "Frakobl", @@ -163,7 +169,6 @@ "annotation": "Fusionerede {n} objekter.", "not_eligible": "Disse objekter kan ikke fusioneres.", "not_adjacent": "Disse objekter kan ikke fusioneres da deres endepunkter ikke er forbundet.", - "restriction": "Disse objekter kan ikke fusioneres da en af dem er medlem af \"{relation}\" relationen.", "incomplete_relation": "Disse objekter kan ikke fusioneres, da mindst et af dem ikke er blevet downloadet helt.", "conflicting_tags": "Disse objekter kan ikke fusioneres fordi nogle af deres tags har konfliktende værdier." }, @@ -196,17 +201,17 @@ }, "reflect": { "title": { - "long": "Reflektere langt", - "short": "Reflektere kort" + "long": "Spejlvend om lang akse", + "short": "Spejlvend om kort akse" }, "description": { "long": { - "single": "Reflekter dette objekt på tværs af dets lange akse.", - "multiple": "Reflekter disse objekter på tværs af deres lange akse." + "single": "Spejlvend dette objekt omkring dets lange akse.", + "multiple": "Spejlvend disse objekter omkring deres lange akse." }, "short": { - "single": "Reflekter dette objekt på tværs af dets kort akse.", - "multiple": "Reflekter disse objekter på tværs af deres korte akse." + "single": "Spejlvend dette objekt omkring dets korte akse.", + "multiple": "Spejlvend disse objekter omkring deres korte akse." } }, "key": { @@ -215,25 +220,25 @@ }, "annotation": { "long": { - "single": "Reflekterede et objekt på tværs af dets lange akse.", - "multiple": "Reflekterede flere objekter på tværs af deres lange akse." + "single": "Spejlvendte et objekt omkring dets lange akse.", + "multiple": "Spejlvendte flere objekter omkring af deres lange akse." }, "short": { - "single": "Reflekterede et objekt på tværs af dets korte akse.", - "multiple": "Reflekterede flere objekter på tværs af deres korte akse." + "single": "Spejlvendte et objekt omkring dets korte akse.", + "multiple": "Spejlvendte flere objekter omkring deres korte akse." } }, "incomplete_relation": { - "single": "Dette objekt kan ikke reflekteres da det ikke er blevet downloadet helt.", - "multiple": "Disse objekter kan ikke reflekteres da de ikke er blevet downloadet helt." + "single": "Dette objekt kan ikke spejlvendes, da det ikke er blevet downloadet helt.", + "multiple": "Disse objekter kan ikke spejlvendes, da de ikke er blevet downloadet helt." }, "too_large": { - "single": "Dette objekt kan ikke reflekteres da der ikke er nok af det synligt i den nuværende visning.", - "multiple": "Disse objekter kan ikke reflekteres da der ikke er nok af dem synligt i den nuværende visning." + "single": "Dette objekt kan ikke spejlvendes, da der ikke er nok af det synligt i den nuværende visning.", + "multiple": "Disse objekter kan ikke spejlvendes, da der ikke er nok af dem synligt i den nuværende visning." }, "connected_to_hidden": { - "single": "Dette objekt kan ikke reflekteres da det er forbundet med et skjult objekt.", - "multiple": "Disse objekter kan ikke reflekteres da nogle af dem er forbundet med skjulte objekter." + "single": "Dette objekt kan ikke spejlvendes, da det er forbundet med et skjult objekt.", + "multiple": "Disse objekter kan ikke spejlvendes, da nogle af dem er forbundet med skjulte objekter." } }, "rotate": { @@ -291,6 +296,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Afstand", + "distance_up_to": "Op til {distance}", + "via": "Via", + "via_node_only": "Kun node", + "via_up_to_one": "Op til 1 vej", + "via_up_to_two": "Op til 2 veje" + }, + "help": { + "indirect": "(indirekte)", + "turn": { + "no_left_turn": "INGEN venstresving {indirect}", + "no_right_turn": "INGEN højresving {indirect}", + "no_u_turn": "INGEN u-vending {indirect}", + "no_straight_on": "INGEN ligeudkørsel {indirect}", + "only_left_turn": "KUN venstresving {indirect}", + "only_right_turn": "KUN højresving {indirect}", + "only_u_turn": "KUN u-vending {indirect}", + "only_straight_on": "KUN ligeudkørsel {indirect}", + "allowed_left_turn": "Venstresving tilladt {indirect}", + "allowed_right_turn": "Højresving tilladt {indirect}", + "allowed_u_turn": "U-vending tilladt {indirect}", + "allowed_straight_on": "Ligeudkørsel tilladt {indirect}" + }, + "from": "FRA", + "via": "VIA", + "to": "TIL", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Klik for at markere et {from}-vejsegment", + "select_from_name": "Klik for at vælge {fromName} som {from}", + "toggle": "Klik for at skifte til \"{turn}\"" + } + }, "undo": { "tooltip": "Fortryd: {action}", "nothing": "Intet at fortryde." @@ -336,7 +377,7 @@ "modified": "Ændret", "deleted": "Slettet", "created": "Oprettet", - "about_changeset_comments": "Vedr. ændringssætkommentarer", + "about_changeset_comments": "Om kommentarer til ændringssæt", "about_changeset_comments_link": "http://wiki.openstreetmap.org/wiki/Good_changeset_comments", "google_warning": "Du nævnte Google i denne kommentar: husk at kopiering fra Google Maps er strengt forbudt.", "google_warning_link": "https://www.openstreetmap.org/copyright" @@ -366,6 +407,7 @@ "key": "H", "title": "Historik", "selected": "{n} markerede", + "no_history": "Ingen historik (ny funktionalitet)", "version": "Version", "last_edit": "Sidst ændret", "edited_by": "Ændret af", @@ -603,15 +645,19 @@ } }, "success": { - "edited_osm": "Redigerede OSM!", "just_edited": "Du har lige redigeret OpenStreetMap!", - "view_on_osm": "Vis på OSM", - "facebook": "Del på Facebook", - "twitter": "Del på Twitter", - "google": "Del på Google+", - "help_html": "Dine ændringer vil komme frem i \"Standard\"-kortlaget om få minutter. Andre kortlag, og specielle objekter, kan tage længere tid.", + "thank_you": "Tak fordi du forbedrede kortet.", + "thank_you_location": "Tak fordi du forbedrede kortet omkring {where}.", + "help_html": "Dine ændringer bør dukke op på OpenStreetMap inden for få minutter. Det kan tage længere tid for andre kort at modtage opdateringer.", "help_link_text": "Detaljer", - "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" + "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", + "view_on_osm": "Vis ændringer på OSM", + "changeset_id": "Dit ændringssætnummer: {changeset_id}", + "like_osm": "Kan du lide OpenStreetMap? Få kontakt med andre:", + "more": "Mere", + "languages": "Sprog: {languages}", + "missing": "Mangler der noget på listen?", + "tell_us": "Fortæl os det!" }, "confirm": { "okay": "OK", @@ -712,7 +758,9 @@ "select_left_click": "{leftclick} Venstre-klik på et kortobjekt for at markere det. Dette vil fremhæve det med en pulserende glød, og i kanten af kortet vises detaljer om objektet, såsom navn og adresse.", "select_right_click": "{rightclick} Højreklik på et kortobjekt for at vise redigeringsmenuen, som viser de mulige værktøjer der kan anvendes, såsom rotation, flytning og sletning.", "multiselect_h": "Multi-markering", - "save_h": "Gem" + "multiselect_shift_click": "`{shift}`+{leftclick} venstreklik for at markere flere kortobjekter ad gangen. Dette gør det nemmere at flytte eller slette flere objekter i en operation.", + "save_h": "Gem", + "upload": "Før du uploader dine ændringer, skal du skrive en [kommentar til ændringssættet](https://wiki.openstreetmap.org/wiki/Good_changeset_comments). Dernæst skal du klikke på **Upload** for at sende dine ændringer til OpenStreetMap, hvor de vil blive føjet til kortet og blive offentligt synlige for alle." }, "feature_editor": { "title": "Redigeringsværktøj til kortobjekter", @@ -741,6 +789,44 @@ "offsets_h": "Justering af luftfoto-offset", "offset": "Den registrerede position for et luftfoto er nogle gange ikke helt korrekt i forhold til kortet. Hvis du ser at bygninger og veje generelt er forskudt mellem kort og luftfoto, kan det være luftfotoet der er unøjagtigt, så i stedet for at flytte alle kortobjekter kan du justere baggrunden så den er samstemmende med kortets data ved at åbne \"Juster luftfoto-offset\" i bunden af Baggrundsindstillinger-fanen.", "offset_change": "Klik på de små trekanter for at justere offset i små intervaller, eller hold venstre musetast nede og træk indenfor den grå firkant for at trække luftfotoet på plads." + }, + "field": { + "restrictions": { + "title": "Hjælp til svingbegrænsninger", + "about": { + "title": "Om", + "about": "Dette felt gør det muligt at inspicere og redigere svingbegrænsninger. Det viser en model af det valgte vejkryds inklusiv forbundne veje i nærheden.", + "from_via_to": "En svingbegrænsning indeholder altid: en **FRA-vej**, en **TIL-vej** og enten en **VIA-node** eller en eller flere **VIA-veje**.", + "maxdist": "Med \"{distField}\"-kontrolelementet indstilles hvor langt omkring der søges efter forbundne veje,", + "maxvia": "Med \"{viaField}\"-kontrolelementet justeres hvor mange VIA-veje der kan inkluderes. (tip: så få som muligt bør foretrækkes)" + }, + "inspecting": { + "title": "Inspektion", + "about": "Før musen over ethvert **FRA**-segment for at se om det har eksisterende svingbegrænsninger. Ethvert muligt **TIL**-segment vil tegnes med en farvet skygge der viser om en begrænsning eksisterer.", + "from_shadow": "{fromShadow} **FRA-segment**", + "allow_shadow": "{allowShadow} **TIL tilladt**", + "restrict_shadow": "{restrictShadow} **TIL begrænset**", + "only_shadow": "{onlyShadow} **TIL kun (påbudt)**", + "restricted": "\"Begrænset\" indikerer at der er en specifik svingbegrænsning, for eksempel \"ingen venstresving\".", + "only": "\"Kun (påbudt)\" indikerer at et køretøj der følger denne rute kun kan vælge denne vej, for eksempel \"kun ligeudkørsel\"." + }, + "modifying": { + "title": "Redigering", + "about": "For at redigere svingbegrænsninger skal du først klikke på det startende **FRA**-segment for at vælge dette. Det valgte segment vil pulsere og alle mulige **TIL**-segmenter vil blive vist med et sving-symbol.", + "indicators": "Klik nu på et dreje-symbol for at skifte det mellem \"tilladt\", \"begrænset\" og \"kun (påbudt)\".", + "allow_turn": "{allowTurn} **TIL tilladt**", + "restrict_turn": "{restrictTurn} **TIL begrænset**", + "only_turn": "{onlyTurn} **TIL kun (påbudt)**" + }, + "tips": { + "title": "Tips", + "simple": "**Foretræk simple begrænsninger i stedet for komplekse.**", + "simple_example": "Undgå for eksempel en begrænsning med en VIA-vej hvis en simplere med en VIA-node ville være tilstrækkeligt.", + "indirect": "**Nogle begrænsninger vises med teksten \"(indirekte)\" og tegnes med en lysere farve.**", + "indirect_example": "Disse begrænsninger eksisterer på grund af andre begrænsninger i nærheden. For eksempel vil en begrænsning med \"kun ligeudkørsel\" i et kryds skabe indirekte \"ingen sving\"-begrænsninger for alle øvrige veje gennem krydset.", + "indirect_noedit": "Du kan ikke redigere indirekte svingbegrænsninger. I stedet skal du redigere den nærtliggende direkte svingbegrænsning." + } + } } }, "intro": { @@ -2027,7 +2113,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telefon", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2448,9 +2533,6 @@ "label": "Type", "placeholder": "Standard" }, - "vending": { - "label": "Varetype" - }, "visibility": { "label": "Synlighed", "options": { @@ -2504,6 +2586,9 @@ "wheelchair": { "label": "Kørestolsadgang" }, + "wholesale": { + "label": "Engros" + }, "width": { "label": "Bredde (meter)" }, @@ -2612,6 +2697,10 @@ "name": "Lufthavnsterminal", "terms": "Lufthavnsterminal" }, + "allotments/plot": { + "name": "Fælleshave", + "terms": "fælleshave,have,fællesskab" + }, "amenity": { "name": "Facilitet" }, @@ -2675,10 +2764,17 @@ "name": "Valutaveksling", "terms": "Valutaveksling" }, + "amenity/bus_station": { + "name": "Busstation/rutebilstation" + }, "amenity/cafe": { "name": "Cafe", "terms": "Cafe, Café" }, + "amenity/car_pooling": { + "name": "Samkørselsplads", + "terms": "samkørsel,bildeling,deling,deleøkonomi" + }, "amenity/car_rental": { "name": "Biludlejning", "terms": "Biludlejning" @@ -2711,6 +2807,14 @@ "name": "Klinik", "terms": "Klinik" }, + "amenity/clinic/abortion": { + "name": "Abortklinik", + "terms": "abort,fosteruddrivelse,provokeret abort,foster," + }, + "amenity/clinic/fertility": { + "name": "Fertilitetsklinik", + "terms": "Fertilitet, børn, graviditet, reagensglas" + }, "amenity/clock": { "name": "Ur", "terms": "Ur" @@ -2766,6 +2870,9 @@ "name": "Fast food", "terms": "Fastfood, Grillbar, Pølsevogn" }, + "amenity/ferry_terminal": { + "name": "Færgeterminal" + }, "amenity/fire_station": { "name": "Brandstation", "terms": "" @@ -2814,16 +2921,25 @@ "name": "Bibliotek", "terms": "" }, + "amenity/love_hotel": { + "name": "Kærlighedshotel", + "terms": "kærlighed, romantik, samvær" + }, "amenity/marketplace": { "name": "Markedsplads", "terms": "Markedsplads" }, + "amenity/monastery": { + "name": "Kloster-område", + "terms": "kloster, nonne, katedral, kapel, kirke, gud, bøn" + }, "amenity/motorcycle_parking": { "name": "Motorcykelparkering", "terms": "Motorcykelparkering" }, "amenity/music_school": { - "name": "Musikskole" + "name": "Musikskole", + "terms": "musik,skole,undervisning" }, "amenity/nightclub": { "name": "Natklub", @@ -2925,7 +3041,8 @@ "terms": "Rangerstation" }, "amenity/recycling": { - "name": "Genbrugscontainer" + "name": "Genbrugscontainer", + "terms": "genbrug, miljø, ressourcer" }, "amenity/recycling_centre": { "name": "Genbrugsplads", @@ -2957,6 +3074,10 @@ "name": "Brusebad", "terms": "bruser,styrtebad" }, + "amenity/smoking_area": { + "name": "Rygeområde", + "terms": "rygning, tobak, røg" + }, "amenity/social_facility": { "name": "Sociale faciliteter", "terms": "Sociale faciliteter" @@ -3402,6 +3523,10 @@ "name": "Urmager", "terms": "Urmager" }, + "craft/confectionery": { + "name": "Slikproducent", + "terms": "slik, sukker, bolcher, chokolade, søde sager" + }, "craft/distillery": { "name": "Distelleri", "terms": "distellering,alkohol,sprit" @@ -3650,6 +3775,14 @@ "name": "Golfvandbunker", "terms": "Golfvandbunker" }, + "healthcare": { + "name": "Sundhedsfacilitet", + "terms": "sundhed, klinik, sygdom, kirurgi" + }, + "healthcare/alternative": { + "name": "Alternativ medicin", + "terms": "alternativ, akupunktur, aromaterapi, urteterapi, urter,hypnose" + }, "healthcare/alternative/chiropractic": { "name": "Kiropraktor" }, @@ -3666,10 +3799,12 @@ "terms": "Blodbank, Donorblodbank" }, "healthcare/hospice": { + "name": "Hospice", "terms": "terminal,død,sygdom" }, "healthcare/midwife": { - "name": "Jordemoder" + "name": "Jordemoder", + "terms": "baby, fødsel, graviditet" }, "healthcare/optometrist": { "name": "Optiker", @@ -3694,6 +3829,9 @@ "name": "Ridesti", "terms": "Ridesti, Hestesti" }, + "highway/bus_stop": { + "name": "Busstop / trinbrædt" + }, "highway/corridor": { "name": "Indendørskorridor", "terms": "Indendørskorridor, Indendørspassage" @@ -4076,6 +4214,10 @@ "name": "Voksen spillecenter", "terms": "Voksen spillecenter, Spillehal" }, + "leisure/amusement_arcade": { + "name": "Spillehal", + "terms": "spil, game, gaming, pinball, flipper, videospil" + }, "leisure/bird_hide": { "name": "Fugletårn", "terms": "Fugletårn" @@ -4092,6 +4234,9 @@ "name": "Dansehal", "terms": "Dansehal, Dansested" }, + "leisure/dancing_school": { + "name": "Danseskole" + }, "leisure/dog_park": { "name": "Hundepark", "terms": "Hundepark" @@ -4140,6 +4285,10 @@ "name": "Naturreservat", "terms": "Naturreservat" }, + "leisure/outdoor_seating": { + "name": "Udendørs siddepladser", + "terms": "siddeplads, udendørs, spise, drikke, cafe, restaurant" + }, "leisure/park": { "name": "Park", "terms": "Park, Parkområde" @@ -4168,6 +4317,10 @@ "name": "Beachvolleybane", "terms": "beachvolley,beach,volley,beach volley" }, + "leisure/pitch/boules": { + "name": "Boules/petanque-bane", + "terms": "petanque, boules" + }, "leisure/pitch/bowls": { "name": "Bowling græsplæne", "terms": "Bowling græsplæne, Keglebane" @@ -4220,6 +4373,10 @@ "name": "Løbebane (Løb)", "terms": "Løbebane (Løb)" }, + "leisure/sauna": { + "name": "Sauna", + "terms": "sauna, varme" + }, "leisure/slipway": { "name": "Bådrampe", "terms": "Bådrampe, Skibsrampe" @@ -4260,6 +4417,10 @@ "name": "Mineindgang", "terms": "Mineindgang" }, + "man_made/antenna": { + "name": "Antenne", + "terms": "antenne, radio, frekvens, kommunikation, tv, fjernsyn" + }, "man_made/breakwater": { "name": "Bølgebryder", "terms": "Bølgebryder" @@ -4272,6 +4433,10 @@ "name": "Skorsten", "terms": "Skorsten" }, + "man_made/crane": { + "name": "Kran", + "terms": "kran, løft, grej" + }, "man_made/cutline": { "name": "Skærelinje", "terms": "Skærelinje" @@ -4303,6 +4468,10 @@ "name": "Observationstårn", "terms": "observationstårn, udkigstårn" }, + "man_made/observatory": { + "name": "Observatorie", + "terms": "astronomi, astrofysik, meteorologi" + }, "man_made/petroleum_well": { "name": "Oliebrønd", "terms": "Oliebrønd" @@ -4423,6 +4592,9 @@ "name": "Hede", "terms": "Hede" }, + "natural/mud": { + "name": "Mudder" + }, "natural/peak": { "name": "Højdedrag", "terms": "Højdedrag, Bakketop, Bjergtop" @@ -4495,9 +4667,25 @@ "name": "Kontor", "terms": "Kontor" }, + "office/accountant": { + "name": "Revisor-kontor", + "terms": "revisor, regnskab, tal, matematik" + }, "office/administrative": { "name": "Administrativt kontor" }, + "office/adoption_agency": { + "name": "Adoptionsbureau", + "terms": "adoption, børn, barnløshed" + }, + "office/advertising_agency": { + "name": "Reklamebureau", + "terms": "reklame, tv, marketing, radio" + }, + "office/architect": { + "name": "Arkitekt-kontor", + "terms": "arkitekt, tegning, bygning" + }, "office/coworking": { "name": "Kontorfællesskab", "terms": "Kontorfællesskab, Fællesskabsarbejdsplads" @@ -5378,18 +5566,6 @@ "name": "Ingen U-vending", "terms": "Ingen U-vending" }, - "type/restriction/only_left_turn": { - "name": "Kun venstresving tilladt", - "terms": "Kun venstresving tilladt" - }, - "type/restriction/only_right_turn": { - "name": "Kun højresving tilladt", - "terms": "Kun højresving tilladt" - }, - "type/restriction/only_straight_on": { - "name": "Ingen sving tilladt", - "terms": "Ingen sving tilladt" - }, "type/route": { "name": "Rute", "terms": "Rute" @@ -5469,7 +5645,7 @@ "terms": "Kanal" }, "waterway/dam": { - "name": "Dam", + "name": "Dæmning", "terms": "Dam" }, "waterway/ditch": { @@ -5525,39 +5701,44 @@ }, "DigitalGlobe-Premium": { "attribution": { - "text": "Betingelser & tilbagemelding" + "text": "Vilkår & tilbagemelding" }, "description": "Premium DigitalGlobe satellitfoto.", "name": "DigitalGlobe Premium fotos" }, "DigitalGlobe-Premium-vintage": { "attribution": { - "text": "Vilkår & Tilbagemelding" + "text": "Vilkår & tilbagemelding" }, - "description": "Luftfoto grænser og optagelsesdatoer. Tekstmærkater optræder ved zoom-niveau 14 og højere.", "name": "DigitalGlobe Premium ældre fotos" }, "DigitalGlobe-Standard": { "attribution": { - "text": "Betingelser & tilbagemelding" + "text": "Vilkår & tilbagemelding" }, "description": "Standard DigitalGlobe satellitfotos.", "name": "DigitalGlobe Standard fotos" }, "DigitalGlobe-Standard-vintage": { "attribution": { - "text": "Vilkår & Tilbagemelding" + "text": "Vilkår & tilbagemelding" }, - "description": "Luftfoto grænser og optagelsesdatoer. Tekstmærkater optræder ved zoom-niveau 14 og højere.", "name": "DigitalGlobe Standard ældre fotos" }, "EsriWorldImagery": { "attribution": { - "text": "Betingelser & tilbegemelding" + "text": "Vilkår & tilbagemelding" }, "description": "Esri World fotos.", "name": "Esri World fotos" }, + "EsriWorldImageryClarity": { + "attribution": { + "text": "Vilkår & tilbagemelding" + }, + "description": "Esri arkivfotos som kan være af bedre kvalitet og mere præcise end standard-laget.", + "name": "Esri World fotos (Clarity) Beta" + }, "MAPNIK": { "attribution": { "text": "© OpenStreetMap bidragsydere, CC BY-SA" @@ -5567,7 +5748,7 @@ }, "Mapbox": { "attribution": { - "text": "Betingelser & tilbegemelding" + "text": "Vilkår & tilbagemelding" }, "description": "Satellit og luft-foto.", "name": "Mapbox Satellite" @@ -5626,25 +5807,40 @@ "name": "TIGER Roads 2017" }, "Waymarked_Trails-Cycling": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap-bidragsydere, CC by-SA 3.0" + }, "name": "Afmærkede spor: Cykling" }, "Waymarked_Trails-Hiking": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap-bidragsydere, CC by-SA 3.0" + }, "name": "Afmærkede spor: Vandring" }, "Waymarked_Trails-MTB": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap-bidragsydere, CC by-SA 3.0" + }, "name": "Afmærkede spor: MTB" }, "Waymarked_Trails-Skating": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap-bidragsydere, CC by-SA 3.0" + }, "name": "Afmærkede spor: Skøjtning" }, "Waymarked_Trails-Winter_Sports": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap-bidragsydere, CC by-SA 3.0" + }, "name": "Afmærkede spor: Vintersport" }, "basemap.at": { "attribution": { "text": "basemap.at" }, - "description": "Basiskort for Østrig, baseret på offentlige data.", + "description": "© waymarkedtrails.org, OpenStreetMap-bidragsydere, CC by-SA 3.0", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -5662,7 +5858,7 @@ }, "mapbox_locator_overlay": { "attribution": { - "text": "Betingelser & tilbagemelding" + "text": "Vilkår & tilbagemelding" }, "description": "Viser større objekter for at hjælpe dig med at finde vej.", "name": "Lokaliserings-overlag" @@ -5705,9 +5901,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Kort-fliser af Stamen Design, under CC BY 3.0" - }, "name": "Stamen Terræn" }, "tf-cycle": { diff --git a/vendor/assets/iD/iD/locales/de.json b/vendor/assets/iD/iD/locales/de.json index 32b760c42..25b9f69c4 100644 --- a/vendor/assets/iD/iD/locales/de.json +++ b/vendor/assets/iD/iD/locales/de.json @@ -1,5 +1,10 @@ { "de": { + "icons": { + "information": "Info", + "remove": "entfernen", + "undo": "rückgängig" + }, "modes": { "add_area": { "title": "Fläche", @@ -145,7 +150,9 @@ "vertex": "Weg mit einem anderem Weg verbunden.", "line": "Weg mit einer Linie / einer Fläche verbunden.", "area": "Weg mit einer Fläche verbunden." - } + }, + "relation": "Diese Objekte können nicht verbunden werden, weil sich Ihre Relations-Rollen widersprechen.", + "restriction": "Diese Objekte können nicht verbunden werden, weil damit eine \"{relation}\" Relation beschädigt werden würde." }, "disconnect": { "title": "Trennen", @@ -163,8 +170,9 @@ "annotation": "{n} Objekte wurden vereinigt.", "not_eligible": "Diese Objekte können nicht vereinigt werden.", "not_adjacent": "Diese Objekte können nicht vereinigt werden, weil ihre Endpunkte nicht verbunden sind.", - "restriction": "Diese Objekte können nicht vereinigt werden, weil zumindest ein Objekt Mitglied der '{relation}' Relation ist.", - "incomplete_relation": "Diese Objekte können nicht zusammengefügt werden, weil mindestens eines noch nicht vollständig heruntergeladen wurde.", + "restriction": "Diese Objekte können nicht vereinigt werden, weil damit eine \"{relation}\" Relation beschädigt werden würde.", + "relation": "Diese Objekte können nicht vereinigt werden, weil sich Ihre Relations-Rollen widersprechen.", + "incomplete_relation": "Diese Objekte können nicht vereinigt werden, weil mindestens eines noch nicht vollständig heruntergeladen wurde.", "conflicting_tags": "Diese Objekte können nicht vereinigt werden, weil es Eigenschaften mit widersprechenden Werten gibt." }, "move": { @@ -357,7 +365,7 @@ "error": "Verbindungsaufbau zur API nicht möglich.", "offline": "Der Server ist offline. Bitte versuche es später noch einmal.", "readonly": "Die API erlaubt nur lesen. Änderungen können zur Zeit nicht gespeichert werden.", - "rateLimit": "Die API beschränkt den Zugriff durch nicht angemeldete Benutzer. Du kannst das Limit durch Anmelden umgehen." + "rateLimit": "Die API beschränkt anonyme Verbindungen. Du kannst die Beschränkung durch Anmelden umgehen." }, "commit": { "title": "Hochladen zu OpenStreetMap", @@ -402,6 +410,7 @@ "key": "C", "title": "Chronik", "selected": "{n} ausgewählt", + "no_history": "Keine Chronik (Neues Objekt)", "version": "Version", "last_edit": "Letzte Bearbeitung", "edited_by": "Bearbeitet von", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "OSM bearbeitet!", - "just_edited": "Du hast gerade OpenStreetMap bearbeitet!", - "view_on_osm": "Auf OpenStreetMap ansehen", - "facebook": "Auf Facebook teilen", - "twitter": "Auf Twitter teilen", - "google": "Auf Google+ teilen", - "help_html": "Deine Änderungen sollten in der \"Standard\"-Ebene in wenigen Minuten erscheinen. Andere Ebenen und bestimmte Objekte können länger dauern.", + "just_edited": "Du hast OpenStreetMap bearbeitet!", + "thank_you": "Danke für die Verbesserung der Karte.", + "thank_you_location": "Danke für die Verbesserung der Karte in {where}.", + "help_html": "Deine Änderungen sollten auf OpenStreetMap innerhalb weniger Minuten auftauchen. Auf anderen Karten könnte die Aktualisierung länger dauern.", "help_link_text": "Details", - "help_link_url": "https://wiki.openstreetmap.org/wiki/DE:FAQ#Wann_werden_meine_.C3.84nderungen_auf_den_Karten_gezeigt.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/DE:FAQ#Wann_werden_meine_.C3.84nderungen_auf_den_Karten_gezeigt.3F", + "view_on_osm": "Zeige Änderungen auf OSM", + "changeset_id": "Dein Änderungssatz #: {changeset_id}", + "like_osm": "Gefällt dir OpenStreetMap? Nimm Kontakt auf:", + "more": "Mehr", + "events": "Veranstaltungen", + "languages": "Sprachen: {languages}", + "missing": "Fehlt etwas auf dieser Liste?", + "tell_us": "Erzähl es uns!" }, "confirm": { "okay": "OK", @@ -673,7 +687,7 @@ "used_with": "benutzt mit {type}" }, "validations": { - "disconnected_highway": "Nicht verbundener Weg", + "disconnected_highway": "Nicht verbundene Straße", "disconnected_highway_tooltip": "Wege sollen mit anderen Wegen oder Gebäudeeingängen verbunden sein.", "old_multipolygon": "Äußere Fläche des Multipolygons hat Eigenschaften", "old_multipolygon_tooltip": "Dieser Multipolygonstil ist veraltet. Bitte trage die Eigenschaften beim übergeordneten Multipolygon und nicht bei der äußeren Fläche ein.", @@ -800,7 +814,7 @@ "modify_line_dragnode": "Häufig siehst du Linien die nicht genau gezeichnet sind, beispielweise eine Straße, die nicht mit dem Hintergrund-Bildmaterial zusammenpasst. Um die Form der Linie anzupassen wählst du sie mit {leftclick} linksklick aus. Alle Knoten der Linie werden als kleine Kreise gezeichnet. Du kannst die Knoten an die richtigen Stellen verschieben.", "modify_line_addnode": "Du kannst neue Knoten in einer Linie auch durch {leftclick}**x2** Doppelklicken auf die Linie oder durch Ziehen der kleinen Dreiecke in der Mitte zwischen zwei Knoten erzeugen.", "connect_line_h": "Linien verbinden", - "connect_line": "Die Verbindung von Straßen ist wichtig für die Karte und notwendig für die Navigation.", + "connect_line": "Die richtige Verbindung von Straßen ist wichtig für die Karte und notwendig für das Bereitstellung von Wegbeschreibungen.", "connect_line_display": "Die Verbindungen von Straßen werden mit kleinen grauen Kreisen gezeichnet. Die Endpunkte von Linien werden mit größeren weisen Kreise gezeichnet, wenn sie nicht mit anderen Objekten verbunden sind.", "connect_line_drag": "Um eine Linie mit einem anderen Objekt zu verbinden, ziehe einen Knoten der Linie auf das andere Objekt bis beide Objekte verbunden sind. Tipp: Du kannst verhindern, dass Knoten mit anderen Objekten verbunden werden, indem du die `{alt}` Taste beim Verschieben gedrückt hältst.", "connect_line_tag": "Wenn du weißt, dass die Kreuzung eine Ampel oder einen Zebrastreifen hat, kannst du diese erfassen, indem du den Knoten an der Kreuzung auswählst und dann im Objekteditor den richtigen Objekttyp auswählst.", @@ -843,7 +857,7 @@ "relation_types_h": "Typen von Relationen", "multipolygon_h": "Multipolygone", "multipolygon": "Eine Relation vom Typ *Multipolygon* ist eine Gruppe von einem oder mehreren *äußeren* Objekten und einem oder mehreren *inneren* Objekten. Die äußeren Objekte beschreiben den äußeren Rand des Multipolygons, die inneren Objekte beschreiben Teilflächen oder Löcher, die aus dem Multipolygon herausgeschnitten sind.", - "multipolygon_create": "Um ein Multipolygon zu erzeugen, beispielweise ein Gebäude mit einem Innenhof, zeichne sowohl das äußere als auch das innere Objekt entlang dem Rand als Fläche. Dann wähle mit `{shift}`+{leftclick} Linksklick beide Objekte aus und {rightclick} rechtsklicke und benutze den {merge} **Verbinden** Befehl aus dem Bearbeitungsmenü.", + "multipolygon_create": "Um ein Multipolygon zu erzeugen, beispielweise ein Gebäude mit einem Innenhof, zeichne sowohl das äußere als auch das innere Objekt entlang dem Rand als Fläche. Dann wähle mit `{shift}`+{leftclick} Linksklick beide Objekte aus und {rightclick} rechtsklicke und benutze den {merge} **Vereinigen** Befehl aus dem Bearbeitungsmenü.", "multipolygon_merge": "Verbinden von mehreren Linien oder Flächen erzeugt ein neues Multipolygon mit allen ausgewählten Objekten als Mitglieder. iD erkennt, welche Objekte in anderen enthalten sind und weist die Rollen innen und außen automatisch zu.", "turn_restriction_h": "Abbiegebeschränkungen", "turn_restriction": "Eine Relation vom Typ *Abbiegebeschränkung* ist eine Gruppe von Straßenabschnitten an einer Kreuzung. Abbiegebeschränkungen bestehen aus einer *von* Straße, einem *via* Knoten und einer *nach* Straße.", @@ -861,7 +875,7 @@ "intro": "Das Hintergrund-Bildmaterial welches unter den Kartendaten erscheint ist eine wichtige Quelle zum Bearbeiten. Dieses Bildmaterial kann aus Luftbildern bestehen, die von Satelliten, Flugzeugen oder Drohnen gesammelt wurde, oder es können eingescannte historische Karten oder andere frei erhältliche Quelldaten sein.", "sources_h": "Bildmaterial-Quellen", "choosing": "Um zu sehen, welche Bildmaterial-Quellen zum Bearbeiten verfügbar sind klicke den {layers} **Hintergrundeinstellungen** Knopf auf der rechten Seite der Karte. ", - "sources": "Als Standard sind die [Bing](https://www.bing.com/maps/) Satellitenbilder als Hintergrundbild ausgewählt. Abhängig von der Gegend sind auch andere Bildmaterial-Quellen verfügbar. Sie können neuer sein oder eine höhere Auflösung haben, daher ist es immer sinnvoll zu prüfen, welches Bildmaterial die beste Referenz zum Bearbeiten ist.", + "sources": "Als Standard sind die [Bing](https://www.bing.com/maps/) Satellitenbilder als Hintergrundbild ausgewählt. Abhängig von der Gegend sind auch andere Bildmaterial-Quellen verfügbar. Sie können neuer sein oder eine höhere Auflösung haben, daher ist es immer sinnvoll zu prüfen, welches Bildmaterial die beste Referenz zum Bearbeiten ist.", "offsets_h": "Bildmaterial-Versatz anpassen", "offset": "Bildmaterial ist manchmal geringfügig zu genauen Kartendaten versetzt. Wenn du feststellst, dass viele Wege oder Gebäude gegenüber dem Hintergrund-Bildmaterial versetzt sind, dann kann es sein, dass das Bildmaterial versetzt ist, also verschiebe nicht alle Objekte damit sie zum Hintergrund passen. Stattdessen kannst du den Hintergrund anpassen, damit es zu den bestehenden Daten passt indem du den Bereich „Bildmaterial-Versatz anpassen“ unten in den Hintergrundeinstellungen aufklappst.", "offset_change": "Klicke auf die kleinen Dreiecke um den Bildmaterial-Versatz in kleinen Schritten anzupassen oder halte den linken Mausknopf gedrückt und ziehe innerhalb des grauen Rechtecks um das Bildmaterial zurechtzurücken." @@ -1114,7 +1128,7 @@ "title": "Linien", "add_line": "*Linien* werden benutzt um Objekt wie Straßen, Eisenbahnschienen oder Flüsse darzustellen. **Klicke auf {button} Linie um eine neue Linie zu zeichnen.**", "start_line": "Hier gibt es eine Straße die in OpenStreetMap fehlt.{br}Zeichne sie ein! In OpenStreetMap soll die Linie in der Mitte der Straße gezeichnet werden. Du kannst die Karte während des Zeichnens verschieben, wenn das notwendig ist. **Beginne die neue Linie durch Klicken auf das obere Ende der fehlenden Straße.**", - "intersect": "Du kannst neue Knoten durch Klicken oder Drücken der Leertaste erzeugen.{br} Straßen und viele andere Typen von Linien sind Teil eines größeren Netzwerks. Es ist wichtig dass diese Linien verbunden sind, damit Routing-Anwendungen funktionieren. **Klicke auf {name} um eine Verbindung zwischen den beiden Linien zu erzeugen.**", + "intersect": "Du kannst neue Knoten durch Klicken oder Drücken der Leertaste erzeugen.{br} Straßen und viele andere Typen von Linien sind Teil eines größeren Netzwerks. Es ist wichtig dass diese Linien verbunden sind, damit Routing-Anwendungen richtig funktionieren. **Klicke auf {name} um eine Kreuzung zu erzeugt, die beide Linien verbindet.**", "retry_intersect": "Diese Straße soll {name} kreuzen. Versuch es nochmals!", "continue_line": "Setze das Zeichnen der Linie für die neue Straße fort. Du kannst die Karte verschieben, wenn das notwendig ist.{br}Wenn du fertig gezeichnet hast klicke nochmals auf den letzten Knoten. **Beende das Zeichnen der Straße.**", "choose_category_road": "**Wähle {category} aus der Liste.**", @@ -1129,7 +1143,7 @@ "start_drag_midpoint": "Kleine Dreiecke werden am *Mittelpunkt* zwischen zwei Knoten angezeigt. Eine weitere Möglichkeit um einen neuen Knoten zu erzeugen ist das Verschieben dieses Mittelpunkts zu einer neuen Lage. **Schiebe den Mittelpunkt und erzeuge damit einen neuen Knoten in der Straßenkurve.**", "continue_drag_midpoint": "Diese Linie sieht viel besser aus! Setze das Anpassen der Linie durch Doppelklicken oder Verschieben von Mittelpunkten fort, bis die Kurve dem Straßenverlauf folgt. **Wenn Dir die Linie gefällt, klicke OK.**", "delete_lines": "Wenn es Straßen in der echten Welt nicht gibt, kannst du die zugehörigen Linien löschen.{br}Hier hat die Stadt eine {street} geplant, aber nie gebaut. Du kannst diesen Teil der Karte verbessern, wenn du die zusätzlichen Linien löschst.", - "rightclick_intersection": "Die letzte bestehende Straße ist {street1}, daher wirst du die {street2} an dieser Kreuzung teilen und alles darüber löschen. **Rechtsklicke auf den Kreuzungs-Knoten.**", + "rightclick_intersection": "Die letzte bestehende Straße ist {street1}, daher wirst du die {street2} an dieser Kreuzung *teilen* und alles darüber löschen. **Rechtsklicke auf den Kreuzungs-Knoten.**", "split_intersection": "**Klicke auf {button} Knopf um die {street} zu teilen.**", "retry_split": "Du hast den Teilen-Knopf nicht gedrückt. Versuch es nochmals.", "did_split_multi": "Gut gemacht! Die {street1} ist jetzt in zwei Teile geteilt, der obere Teil kann gelöscht werden. **Klicke den oberen Teil der {street2} zum Auswählen an.**", @@ -1336,7 +1350,7 @@ "name": "Natürliche Punkte" }, "category-path": { - "name": "Wege" + "name": "Weg, Mehrzweckweg" }, "category-rail": { "name": "Eisenbahnanlagen" @@ -1363,7 +1377,7 @@ "options": { "designated": { "description": "Zugang durch Schilder oder bestimmte lokale Gesetze erlaubt", - "title": "Vorgesehen/Gewidmet" + "title": "
    rechtsverbindlich vorgesehen / gewidmet
    " }, "destination": { "description": "Zugang nur für Anlieger/Anrainer", @@ -1694,7 +1708,7 @@ }, "track": { "description": "Radweg durch physische Barriere vom restlichen Verkehr getrennt", - "title": "Separierter Radweg" + "title": "baulich getrennter Radweg" } }, "placeholder": "nichts", @@ -1774,6 +1788,9 @@ "display": { "label": "Anzeige" }, + "distance": { + "label": "Geamte Distanz" + }, "dock": { "label": "Typ" }, @@ -1814,6 +1831,9 @@ "except": { "label": "Ausnahmen" }, + "faces": { + "label": "Gesichter" + }, "fax": { "label": "Fax", "placeholder": "+31 42 123 4567" @@ -1925,6 +1945,39 @@ "label": "Basketball", "placeholder": "1, 2, 4 ..." }, + "horse_dressage": { + "label": "Dressurreiten", + "options": { + "equestrian": "Ja", + "undefined": "Nein" + } + }, + "horse_riding": { + "label": "Pferdereiten", + "options": { + "horse_riding": "Ja", + "undefined": "Nein" + } + }, + "horse_scale": { + "label": "Schwierigkeit beim Pferdereiten", + "options": { + "common": "Einfach: Keine Probleme oder Schwierigkeiten (Standard)", + "critical": "Grenzfall: Nur für erfahrene Reiter und Pferde passierbar. Größere Hindernissen. Brücken müssen sorgfältig untersucht werden.", + "dangerous": "Gefährlich: Nur für erfahrenen Reiter und Pferde und nur bei gutem Wetter passierbar. Absteigen.", + "demanding": "Mit Vorsicht benutzen: Unebener Weg, teilweise schwierige Passagen.", + "difficult": "Schwierig: Weg schmal und ausgesetzt. Kann Hindernisse zum Übersteigen und schmale Passagen beeinhalten.", + "impossible": "Unpassierbar: Weg oder Brücke für Pferde nicht benützbar. Zu schmal, unzureichende Unterstützung, Hindernisse wie Leitern. Lebensgefahr." + }, + "placeholder": "schwierig, gefährlich ..." + }, + "horse_stables": { + "label": "Reitstall", + "options": { + "stables": "Ja", + "undefined": "Nein" + } + }, "iata": { "label": "IATA" }, @@ -1944,6 +1997,9 @@ "indoor": { "label": "Im Gebäude" }, + "industrial": { + "label": "Typ" + }, "information": { "label": "Typ" }, @@ -2064,6 +2120,10 @@ "label": "Höchstgeschwindigkeit", "placeholder": "40, 50, 60 …" }, + "maxspeed/advisory": { + "label": "Richtgeschwindigkeit", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Maximale Parkzeit" }, @@ -2217,7 +2277,7 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telefonnummer", + "label": "Telefon", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2652,8 +2712,19 @@ "label": "Typ", "placeholder": "Standard" }, + "usage_rail": { + "label": "Nutzungsart", + "options": { + "branch": "Zweigstrecke", + "industrial": "Güterverkehrsstrecke", + "main": "Hauptstrecke", + "military": "Militärische Nutzung", + "test": "Teststrecke", + "tourism": "Touristische Nutzung" + } + }, "vending": { - "label": "Dienstleistung" + "label": "Warentyp" }, "visibility": { "label": "Sichtbarkeit", @@ -2748,6 +2819,10 @@ "name": "Plakatwand", "terms": "Werbetafel,Anschlagtafel,Reklametafel,Anschlagbrett" }, + "advertising/column": { + "name": "Litfaßsäule", + "terms": "Litfaßsäule,Anschlagsäule,Plakatsäule,Anzeigeständer,Plakatträger" + }, "aerialway": { "name": "Seilbahn" }, @@ -2833,6 +2908,10 @@ "name": "Flughafenterminal", "terms": "Flughafenterminal, Flughafen-Abfertigungs-Gebäude, Flughafen-Empfangs-Gebäude" }, + "allotments/plot": { + "name": "Gemeinschaftsgartenparzelle", + "terms": "Gemeinschaftsgartenparzelle, Gartenparzelle, Kleingartenparzelle" + }, "amenity": { "name": "Einrichtung" }, @@ -3014,8 +3093,8 @@ "terms": "Food Court, gemeinsamer Gastronomiebereich, Selbstbedienung- und Sitzbereich für mehrere Lokale" }, "amenity/fountain": { - "name": "Springbrunnen", - "terms": "Springbrunnen, Wasserspiel" + "name": "Springbrunnen, Zierbrunnen", + "terms": "Dorfbrunnen, Marktbrunnen, Wasserspiel, Designerbrunnen" }, "amenity/fuel": { "name": "Tankstelle", @@ -3061,6 +3140,10 @@ "name": "Wochenmarkt", "terms": "Wochenmarkt, Marktverkauf, Markt" }, + "amenity/monastery": { + "name": "Klostergelände", + "terms": "Klostergelände" + }, "amenity/motorcycle_parking": { "name": "Motorradparkplatz", "terms": "Motorrad-Parkplatz" @@ -3181,7 +3264,7 @@ }, "amenity/restaurant": { "name": "Restaurant", - "terms": "Bar,Cafeteria,Café,Kantine,Speisehaus,Coffee-Shop,Kaffeehaus,Imbiss,Speisesaal,Kneipe,Donut Shop,Drive-In,Restaurant,Speiserestaurant,Wirtschaft,Fast-Food-Restaurant,Grill,Hamburgerstand,Hotdogstand,Gasthaus,Gasthof,Wirtshaus,Imbissstube,Imbiss,Pizzeria,Lokal" + "terms": "Bar,Cafeteria,Café,Kantine,Speisehaus,Coffee-Shop,Kaffeehaus,Imbiss,Speisesaal,Kneipe,Donut Shop,Drive-In,Restaurant,Speiserestaurant,Wirtschaft,Fast-Food-Restaurant,Grill,Hamburgerstand,Hotdogstand,Gasthaus,Gasthof,Wirtshaus,Imbissstube,Imbiss,Pizzeria,Lokal,Gastronomiebetrieb" }, "amenity/sanitary_dump_station": { "name": "Campingtoiletten-Entsorgungsanlage", @@ -3265,6 +3348,10 @@ "name": "Zigarettenautomat", "terms": "Zigarettenautomat" }, + "amenity/vending_machine/coffee": { + "name": "Kaffeeautomat", + "terms": "Kaffeeautomat" + }, "amenity/vending_machine/condoms": { "name": "Kondomautomat", "terms": "Kondomautomat" @@ -3273,6 +3360,14 @@ "name": "Getränkeautomat", "terms": "Getränkeautomat, Getränkespender" }, + "amenity/vending_machine/electronics": { + "name": "Elektro-Zubehör-Automat", + "terms": "Elektro-Zubehör-Automat" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Münz-Sourvenir-Präge-Automat", + "terms": "Münz-Sourvenir-Präge-Automat" + }, "amenity/vending_machine/excrement_bags": { "name": "Hundekottütenspender", "terms": "Hundekot-Tütenspender, Kottütenspender, Kottütenautomat, " @@ -3281,6 +3376,18 @@ "name": "Frauenhygiene-Automat", "terms": "Frauenhygiene-Automat" }, + "amenity/vending_machine/food": { + "name": "Lebensmittel-Verkaufs-Automat ", + "terms": "Lebensmittel-Verkaufs-Automat " + }, + "amenity/vending_machine/fuel": { + "name": "Tankautomat", + "terms": "Tankautomat" + }, + "amenity/vending_machine/ice_cream": { + "name": "Speiseeis-Automat", + "terms": "Speiseeis-Automat" + }, "amenity/vending_machine/news_papers": { "name": "Zeitungsautomat" }, @@ -3300,6 +3407,10 @@ "name": "Fahrkartenautomat", "terms": "Fahrkartenautomat" }, + "amenity/vending_machine/stamps": { + "name": "Briefmarkenautomat", + "terms": "Briefmarkenautomat" + }, "amenity/vending_machine/sweets": { "name": "Süßigkeitenautomat", "terms": "Süßigkeitenautomat" @@ -3372,6 +3483,10 @@ "name": "Fallturm", "terms": "Fallturm" }, + "attraction/maze": { + "name": "Labyrinth", + "terms": "Labyrinth, Irrgarten" + }, "attraction/pirate_ship": { "name": "Piratenschiff", "terms": "Piratenschiff" @@ -3553,6 +3668,10 @@ "name": "Mehrfach-/Blockgaragen", "terms": "Mehrfachgaragen, Garagenblock" }, + "building/grandstand": { + "name": "Haupttribüne", + "terms": "Haupttribüne, Ehrentribüne" + }, "building/greenhouse": { "name": "Gewächshaus", "terms": "Glashaus, Gewächshaus, Treibhaus" @@ -3591,7 +3710,7 @@ }, "building/residential": { "name": "Allgemeines Wohngebäude", - "terms": "Wohnhaus,Einfamilienhaus,Mehrfamilienhaus" + "terms": "Wohnhaus, Einfamilienhaus, Mehrfamilienhaus" }, "building/retail": { "name": "Geschäftsgebäude", @@ -3872,7 +3991,7 @@ "terms": "Defibrillator, Defi, Schockgeber" }, "emergency/designated": { - "name": "Notzugang vorgesehen" + "name": "Rettungsweg" }, "emergency/destination": { "name": "Notzufahrt ohne Notdurchfahrt" @@ -4001,6 +4120,10 @@ "name": "Hospiz", "terms": "Sterbeklinik, Hospiz" }, + "healthcare/laboratory": { + "name": "Medizinisches Labor", + "terms": "Medizinisches Labor, Medizinlabor" + }, "healthcare/midwife": { "name": "Hebamme", "terms": "Hebamme, Entbindungspfleger, Geburtshelfer, Geburtshelferin" @@ -4096,16 +4219,20 @@ "terms": "Autobahn, Expressweg" }, "highway/motorway_junction": { - "name": "Autobahnkreuz/-abfahrt", - "terms": "Autobahnkreuz, Autobahnanschluss, Autobahndreieck, Autobahnknoten, Autobahnzubringer, Autobahnabfahrt, Autobahnexit" + "name": "Autobahnkreuzungspunkt", + "terms": "Autobahnkreuz, Autobahnanschluss, Autobahnzubringer, Autobahnabfahrt (Kreuzungspunkt)" }, "highway/motorway_link": { - "name": "Autobahnanschluss", - "terms": "Autobahnanschluss, Autobahnauffahrt, Autobahnabfahrt, Auffahrt, Abfahrt" + "name": "Autobahnauffahrt, Autobahnabfahrt", + "terms": "Autobahnanschluss, Auffahrt, Abfahrt" + }, + "highway/passing_place": { + "name": "Ausweichstelle", + "terms": "Haltebucht" }, "highway/path": { - "name": "Weg", - "terms": "Mehrzweck-Weg, Wanderweg, Reitweg, Radweg, Fußweg, Pfad" + "name": "Weg, Mehrzweck-Weg", + "terms": "Mehrzweck-Weg, Rad- und Fußweg, Rad-/Fußweg, Wanderweg, Reitweg, Radweg, Fußweg, Pfad" }, "highway/pedestrian_area": { "name": "Fußgängerzone", @@ -4128,8 +4255,8 @@ "terms": "Motorsportrennstrecke, Rennstrecke (Motorsport)" }, "highway/residential": { - "name": "Anliegerstraße", - "terms": "Anliegerstraße,Wohngebietsstraße,Siedlungsstraße,Ortsstraße" + "name": "Ortsstraße", + "terms": "Anliegerstraße, Wohngebietsstraße, Siedlungsstraße, innerörtliche Straße" }, "highway/rest_area": { "name": "Rastplatz ohne Tankstelle/Restaurant", @@ -4168,8 +4295,8 @@ "terms": "Rettungsweg, Zufahrtsstraße für Rettungskräfte, Rettungszufahrt, Feuerwehrzufahrt" }, "highway/service/parking_aisle": { - "name": "Parkplatz-Nebenfahrweg", - "terms": "Parkplatzweg, Fahrweg auf Parkplatzflächen" + "name": "Parkplatzweg", + "terms": "Parkplatzfahrgasse, Fahrweg auf Parkplatzflächen" }, "highway/services": { "name": "Raststätte mit Tankstelle/Restaurant", @@ -4439,8 +4566,8 @@ "terms": "Gelände mit religiöser Nutzung" }, "landuse/residential": { - "name": "Wohngebiet", - "terms": "Wohngebiet,Wohnanlage,Wohngegend,Wohnregion,Wohnhäuser,Siedlungsfläche" + "name": "Siedlungsraum", + "terms": "Wohngebiet, Wohngegend, Wohnregion, Siedlungsfläche, Ortslage" }, "landuse/retail": { "name": "Einzelhandel", @@ -4462,6 +4589,10 @@ "name": "Spielhalle", "terms": "Spielhalle" }, + "leisure/beach_resort": { + "name": "Strandresort", + "terms": "Strandresort, Strandhotelanalge, Badestrandresort, Badestrandhotelanlage" + }, "leisure/bird_hide": { "name": "Vogelbeobachtungsturm", "terms": "Vogelbeobachtungsturm, Vogelbeobachtungshütte" @@ -4578,6 +4709,10 @@ "name": "Naturschutzgebiet", "terms": "Naturschutzgebiet, Landschaftsschutzgebiet, Naturreservat, Naturschutzpark" }, + "leisure/outdoor_seating": { + "name": "Außengastronomie", + "terms": "Außengastronomie, Gastgarten, Schanigarten" + }, "leisure/park": { "name": "Park", "terms": "Park, Parkanlage, Esplanade, Lustgarten" @@ -4706,6 +4841,10 @@ "name": "Bergwerk - Stolleneingang", "terms": "Stollen (horizontaler Tunnel im Bergbau), Stollenmundloch" }, + "man_made/antenna": { + "name": "Antennenmast", + "terms": "Antennenanlage, Sendemast " + }, "man_made/breakwater": { "name": "Wellenbrecher", "terms": "Wellenbrecher, Buhnen, Mole" @@ -4718,6 +4857,10 @@ "name": "Schornstein", "terms": "Schornstein, Kamin" }, + "man_made/clearcut": { + "name": "Kahlschlagfläche", + "terms": "Kahlfläche, Waldkahlfläcke, Kahlschlagfläche" + }, "man_made/crane": { "name": "Kran", "terms": "Kran" @@ -4757,6 +4900,10 @@ "name": "Aussichtsturm", "terms": "Ausguck, Ausblick, Beobachtungsstand" }, + "man_made/observatory": { + "name": "Observatorium", + "terms": "Sternenwarte" + }, "man_made/petroleum_well": { "name": "Erdölpumpe", "terms": "Tiefpumpe, Pferdekopfpumpe" @@ -4807,7 +4954,7 @@ }, "man_made/water_well": { "name": "Brunnen zur Wasserförderung", - "terms": "Brunnen,Tiefbrunnen,Trinkwasserbrunnen,Brauchwasserbrunnen" + "terms": "Bohrbrunnen, Schachtbrunnen, Tiefbrunnen, Trinkwasserbrunnen, Brauchwasserbrunnen, " }, "man_made/water_works": { "name": "Wasserwerk", @@ -4881,10 +5028,18 @@ "name": "Heidelandschaft", "terms": "Heidelandschaft, Strauchheiden" }, + "natural/mud": { + "name": "Schlamm", + "terms": "Schlamm, Schlick, Morast" + }, "natural/peak": { "name": "Berggipfel", "terms": "Gipfel,Felsnadel,Hügel,Berg,Bergspitze,Bergkuppe,Zipfel" }, + "natural/reef": { + "name": "Riff", + "terms": "Riff, Korallenriff, Unterwassersandbank, Untiefe" + }, "natural/ridge": { "name": "Höhenrücken", "terms": " Bergrücken,Bergzug,Gebirgsgrat,Grat,Kamm,Naht" @@ -5549,7 +5704,7 @@ }, "shop": { "name": "Laden", - "terms": "Geschäft, Ladenlokal" + "terms": "Laden, Geschäft, Ladenlokal, Shop" }, "shop/agrarian": { "name": "Agrarmarkt", @@ -5592,7 +5747,7 @@ "terms": "Badezimmereinrichtungsgeschäft,Badeinrichtungsgeschäft" }, "shop/beauty": { - "name": "Kosmetikladen", + "name": "Schönheitssalon", "terms": "Schönheits-Salon, Nagelstudio" }, "shop/beauty/nails": { @@ -5684,15 +5839,15 @@ "terms": "Süßigkeitenladen,Süßigkeitengeschäft" }, "shop/convenience": { - "name": "Gemischtwarenhandel", - "terms": "Gemischtwarenladen, Kaufgeschäft" + "name": "Gemischtwarenhandel/ Tante-Emma-Laden", + "terms": "Gemischtwarenladen, Dorfladen, Greißler, Nachbarschaftsladen, Kaufgeschäft" }, "shop/copyshop": { "name": "Kopierladen", "terms": "Kopieranstalt,Copy-Shop" }, "shop/cosmetics": { - "name": "Drogerie", + "name": "Kosmetikladen", "terms": "Drogerie,Kosmetikladen" }, "shop/craft": { @@ -5917,6 +6072,10 @@ "name": "Tierhandlung", "terms": "Tierhandlung, Zoohandlung" }, + "shop/pet_grooming": { + "name": "Tierfriseur", + "terms": "Hundefriseur, Tierfriseur" + }, "shop/photo": { "name": "Fotofachgeschäft", "terms": "Fotoladen, Fotograf, Fotogeschäft" @@ -6013,8 +6172,8 @@ "terms": "Staubsaugergeschäft,Staubsaugerladen" }, "shop/variety_store": { - "name": "Gemischtwarenhandel", - "terms": "Gemischtwarenladen, Kaufgeschäft" + "name": "Billigladen", + "terms": "Ein-Euro-Geschäft, Ein-Euro-Laden, Schnäppchenmarkt, Ramschladen, Sonderpostenmarkt, Restpostenmarkt" }, "shop/video": { "name": "Videothek", @@ -6058,7 +6217,7 @@ }, "tourism/apartment": { "name": "Ferienwohnung", - "terms": "Ferienwohnung, Gästewohnung, Gästeapartment" + "terms": "Ferienwohnung, Gästewohnung, Gästeapartment, Ferienappartement, Gästeappartement" }, "tourism/aquarium": { "name": "Aquarium", @@ -6136,6 +6295,10 @@ "name": "Themenpark", "terms": "Themenpark, Freizeitpark" }, + "tourism/trail_riding_station": { + "name": "Wanderreitstation", + "terms": "Wanderreitstation, Gastpferdeübernachtungsmöglichkeit" + }, "tourism/viewpoint": { "name": "Aussichtspunkt", "terms": "Aussichtspunkt" @@ -6204,11 +6367,11 @@ "terms": "Abbiegebeschränkung, Beschränkung, Einschränkung" }, "type/restriction/no_left_turn": { - "name": "Linksabbiegeverbot", + "name": "Kein Linksabbiegen", "terms": "Linksabbiegeverbot, Linksabbiegen verboten, kein Linksabbiegen, kein Abbiegen nach links" }, "type/restriction/no_right_turn": { - "name": "Rechtsabbiegeverbot", + "name": "Kein Rechtsabbiegen", "terms": "Rechtsabbiegeverbot, Rechtsabbiegen verboten, kein Rechtsabbiegen, kein Abbiegen nach rechts" }, "type/restriction/no_straight_on": { @@ -6216,20 +6379,24 @@ "terms": "Geradeausfahrverbot, Geradeausfahren verboten, geradeaus fahren nicht erlaubt" }, "type/restriction/no_u_turn": { - "name": "Kehrtwendeverbot", - "terms": "Kehrtwendeverbot, Kehrtwende verboten, Umkehren verboten, Umdrehen verboten" + "name": "Keine Kehrtwende", + "terms": "Kehrtwendeverbot, Kehrtwende verboten, Umkehren verboten, Umdrehen verboten, Keine Kehrtwende, Kein Umdrehen, Keine Umkehren" }, "type/restriction/only_left_turn": { - "name": "Linksabbiegegebot", - "terms": "Linksabbiegegebot, Links abbiegen geboten, nur links abbiegen erlaubt" + "name": "Nur Linksabbiegen", + "terms": "Nur Linksabbiegen, Linksabbiegegebot, nur Abbiegen nach Links" }, "type/restriction/only_right_turn": { - "name": "Rechtsabbiegegebot", - "terms": "Rechtsabbiegegebot, Rechts abbiegen geboten, nur rechts abbiegen erlaubt" + "name": "Nur Rechtsabbiegen", + "terms": "Nur Rechtsabbiegen, Rechtsabbiegegebot, Nur Abbiegen nach Rechts" }, "type/restriction/only_straight_on": { - "name": "Kein Abbiegen", - "terms": "Abbiegeverbot, nur geradeaus, Abbiegen verboten" + "name": "Nur geradeaus", + "terms": "Nur geradeaus" + }, + "type/restriction/only_u_turn": { + "name": "Nur Kehrtwende", + "terms": "Nur Kehrtwende, Kehrtwendegebot, Nur Umkehren, Umkehrgebpt" }, "type/route": { "name": "Route", @@ -6392,7 +6559,7 @@ "attribution": { "text": "Bedingungen & Feedback" }, - "description": "Lufbildgrenzen und Aufnahmedaten. Die Beschriftung erscheint auf Zoom Level 14 und höher.", + "description": "Kachelgrenzen und Aufnahmedatum werden bei Zoom-Level 13 und höher angezeigt.", "name": "DigitalGlobe Premium Bildmaterial Klassisch" }, "DigitalGlobe-Standard": { @@ -6406,7 +6573,7 @@ "attribution": { "text": "Bedingungen & Feedback" }, - "description": "Lufbildgrenzen und Aufnahmedaten. Die Beschriftung erscheint auf Zoom Level 14 und höher.", + "description": "Kachelgrenzen und Aufnahmedatum werden bei Zoom-Level 13 und höher angezeigt.", "name": "DigitalGlobe Standard Bildmaterial Klassisch" }, "EsriWorldImagery": { @@ -6490,6 +6657,10 @@ "description": "Gelb = Freie Daten vom US Census. Rot = In OpenStreetMap fehlende Daten", "name": "TIGER Straßen 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Straße: Grüner Rand = Nebenstraße. Brauner Rand = Feldweg/Waldweg. Oberfläche: Schotter = hellbraune Füllung, Asphalt = schwarz, befestigt = grau, ground = weiß, Beton = blau, Gras = grün. Saisonal = weißes Gitter", + "name": "U.S.A. Forststraßen Overlay" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, OpenStreetMap-Mitwirkende, CC BY-SA 3.0" @@ -6524,7 +6695,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Amtliche Verwaltungsgrundkarte von Österreich", + "description": "basemap von Österreich, basiert auf Regierungsdaten", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6586,7 +6757,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Kacheln © Stamen Design, CC-BY 3.0" + "text": "Kacheln © Stamen Design, CC BY 3.0, Kartendaten © OpenStreetMap-Mitwirkende, ODbL 1.0" }, "name": "Stamen Terrain" }, @@ -6602,6 +6773,762 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "Universität von Cape Coast YouthMappers", + "description": "Folge uns auf Twitter {url}", + "extendedDescription": "Das ist der offizielle handle für die Gruppe der Jungen Mapper der Universität von Cape Coast, Ghana. Wir lieben Karten, Offene Daten und Unterstützung für die Schutzlosen" + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana auf Facebook", + "description": "Facebook Grupep für Menschen mit Interesse an OpenStreetMap.", + "extendedDescription": "Gemeischaft der Mapper in Ghana Förderung von OpenStreetMap und den Humanitarian OpenStreetMap Team (HOT) Projecten in Ghana. Schließ dich uns an!" + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana auf Twitter", + "description": "Folge uns auf Twitter {url}" + }, + "talk-gh": { + "name": "Talk-gh Mailing Liste", + "description": "Talk-gh ist die offizielle Mailing Liste für die OSM Gemeinschaft in Ghana." + }, + "osm-mg-facebook": { + "name": "OpenStreetMap Madagaskar Facebook Group", + "description": "Madagaskar Facebook Gruppe für Menschen mit Interessen in OpenStreetMap." + }, + "talk-mg": { + "name": "Talk-mg Mailing Liste", + "description": "Platz für OpenStreetMap Mitwirkende, Gemeinschaften und Benutzer in Madagaskar um zu diskutieren und Ideen zu teilen." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesh", + "description": "Verbessere OpenStreetMap in Bangladesh", + "extendedDescription": "Mappen in Bangladesh? Hast du Fragen, willst du die lokale Gemeinschaft kommunizieren ? Kontaktiere uns auf {url}. Alle sind willkommen!" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap Indien - Nachbarschaftsmapping", + "description": "Verbessere OpenStreetMap in Indien", + "extendedDescription": "Mappen in Indien? Hast du Fragen, willst du mit der Gemeinschaft hier Kontakt aufnehmen? . Schließ dich uns an unter {Url}. Alle sind willkommen!", + "events": { + "sotmasia2018": { + "name": "State of the Map Asien 2018", + "description": "Beteiligte dich an dem 2018 OpenStreetMap Eventu \"State of the Map Asia\" in Indien", + "where": "Indisches Institut für Management, Bangalore, Indien" + } + } + }, + "OSM-india-mailinglist": { + "name": "OpenStreetMap India Mailing Liste", + "description": "Talk-in ist die offizielle Mailing Liste für die Indische Community" + }, + "OSM-india-twitter": { + "name": "OpenStreetMap Indien Twitter", + "description": "Wir sind nur einen Tweet weit weg: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Freie Software Hardware Bewegung - Facebook", + "description": "FSHM Facebook Seite für Veranstaltungen und Aktivitäten der Gemeinschaft", + "extendedDescription": "FSHM organisiert Veranstaltungen für freie Software/Hard, Technologie, Aktivismus für OpenStreetMap. Seine Facebook Seite ist der beste Weg um in Kontakt mit sweinen Veranstaltungen zu bleiben." + }, + "OSM-India-Puducherry-Matrix": { + "name": "Freie Software Hardware Bewegung - Matrix", + "description": "FSHM Riot Gruppe zum diskutieren, plaudern und mehr über Mapping Aktivitäten zu erfahren, Veranstaltungen in und um Puducherry", + "extendedDescription": "Mitglieder der FSHM Gemeinschaft reden über ihre OSM Mapping Updates und Erfahrungen in der Riot.im Gruppe, in dieser Gruppe wird auch über freie Software / Hardware, Technologie und Aktivismus diskutiert." + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonesien", + "description": "Verbessere OpenStreetMap in Indonesien", + "extendedDescription": "Mappen in Indonesien? Hast du Fragen, willst du mit der indonesischen OSM Gemeinschaft Kontakt aufnehmen? . Schließ dich uns an!unter {Url}. Alle sind willkommen!" + }, + "OSM-japan-facebook": { + "name": "OpenStreetMap Gemeinschaft Japan", + "description": "Mapper und OpenStreetMap Benutzer in Japan" + }, + "OSM-japan-mailinglist": { + "name": "OpenStreetMap Japan Mailingliste", + "description": "Talk-ja ist die offizielle Mailingliste für die Japanische OSM-Gemeinschaft" + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap Japan Twitter", + "description": "Hashtag auf Twitter: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap Japan", + "description": "Mapper und OpenStreetMap Benutzer in Japan" + }, + "OSM-korea-telegram": { + "name": "OSM Korea Telegram Channel", + "description": "Inoffizeiller Kanal für OpenStreetMap Mitwirkenden, Gemeinschaft und Benutzer in Korea zum Teilen und Diskutieren." + }, + "OSM-MY-facebook": { + "name": "OpenStreetMap Malaysien auf Facebook", + "description": "Zum Chatten über alles mit Bezug zu OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "OpenStreetMap Malaysien Forum", + "description": "Officielles OpenStreetMap Malaysien Forum" + }, + "OSM-MY-matrix": { + "name": "OpenStreetMap Malaysien Riot channel", + "description": "Alle Mapper sind willkommen, melde dich an: {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongolien", + "description": "Verbessere in der Mongolei", + "extendedDescription": "Mappen in Mongolien? Hast du Fragen, willst du mit der mongolischen OSM Gemeinschaft Kontakt aufnehmen? . Schließ dich uns an unter {Url}. Alle sind willkommen!" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Myanmar", + "description": "Verbessere OpenStreetMap in Myanmar", + "extendedDescription": "Mappst du in Myanmar? Hast du Fragen, willst du mit der OSM-Gemeinschaft Kontakt aufnehmen? . Schließ dich uns an unter {Url}. Alle sind willkommen!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Nepal", + "description": "Verbessere in Nepal", + "extendedDescription": "Mappen in Nepal? Hast du Fragen, willst du mit der nepalesischen OSM Gemeinschaft Kontakt aufnehmen? Schließ dich uns an unter {Url}. Alle sind willkommen!" + }, + "OSM-PH-facebook": { + "name": "OpenStreetMap PH Facebook", + "description": "Willkommen zu OpenStreetMap auf den Philippinen, wo wir alle Filipinos ermutigen zu dem OpenStreetMap Projekt beizutragen." + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph Mailingliste", + "description": "Eine Mailingliste um über OpenStreetMap auf den Philippinen zu diskutieren" + }, + "OSM-PH-slack": { + "name": "OpenStreetMap Philippinen Slack", + "description": "Alle sind willkommen, melde dich an: {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "OpenStreetMap Philippinen Telegram", + "description": "Inoffizielle lokale Telegram Gemeinschaft von OpenStreetMap Mitwirkenden und Freunden auf den Philippinen" + }, + "OSM-RU-forum": { + "name": "OpenStreetMap Russland forum", + "description": "OpenStreetMap Russland web forum" + }, + "OSM-RU-telegram": { + "name": "OpenStreetMap Russland telegram", + "description": "OpenStreetMap Russland telegram chat" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka", + "description": "Verbessere in Sri Lanka", + "extendedDescription": "Mappen in Sri Lanka? Hast du Fragen, willst du mit der sri-lankischen OSM Gemeinschaft Kontakt aufnehmen? Schließ dich uns an unter {Url}. Alle sind willkommen!" + }, + "OSM-TW-facebook": { + "name": "OpenStreetMap Taiwan Gemeinschaft", + "description": "Facebook Gruppe für Mapper und OpenStreetMap Benutzer um über Angelegenheiten für Taiwan zu diskutieren." + }, + "OSM-TW-mailinglist": { + "name": "OpenStreetMap Taiwan Mailingliste", + "description": "Talk-tw is eine offizielle Mailingliste for the Gemeinschaft um über Taiwan-Angelegenheite zu diskutieren" + }, + "OSM-TH-CNX-meetup": { + "name": "OSM Treffen Chiang Mai", + "description": "Unregelmässiges Treffen der OpenStreetMap Gemeinschaft in Chiang Mai", + "extendedDescription": "Mitgieder der OpenStreetMap treffen sich alle paar Monate in Chiang Mai. Nimm Kontakt auch und lies bei {url} um zu sehen wann das nächste Treffen stattfindet." + }, + "OSM-TH-forum": { + "name": "OpenStreetMap TH forum", + "description": "OpenStreetMap Thailand Web Forum" + }, + "al-forum": { + "name": "OSM Albanien Forum", + "description": "OpenStreetMap Albanien Forum" + }, + "al-maptime-tirana": { + "name": "Maptime Tirana", + "description": "Soziale Events zum Mappen werden organisiert -Anfänger sind sehr willkommen!", + "extendedDescription": "Maptime ist eine offene Lernumgebung für alle Erfahrungsstufen und biete internationale Ausbildung für Anfänger. Maptime ist gleichzeitig flexibel und strukturiert, schafft Freiraum für Mapping Einführungen, Workshops, laufende Projekte mit einem gemeinsamen Ziel und unabhängige Gemeinschaftsprojekte." + }, + "al-telegram": { + "name": "OSM Albanien Telegram channel", + "description": "OpenStreetMap Albanien Telegram channel" + }, + "at-forum": { + "name": "OpenStreetmap Österreich Forum", + "description": "Das offizielle Forum für Fragen zu OpenStreetmap in und um Österreich" + }, + "at-mailinglist": { + "name": "Talk-at Mailing Liste", + "description": "Talk-at ist die offizielle Mailing Liste der österreichischen OSM Gemeinschaft" + }, + "at-twitter": { + "name": "OpenStreetMap Österreich Twitter", + "description": "OpenStreetMap Österreich auf Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "OSM Gemeinschaft Treffen Graz", + "description": "Monatliches Treffen der OSM Gemeinschaft in Graz" + }, + "osmgraz-twitter": { + "name": "OSM Gemeinschaft Graz auf Twitter", + "description": "OpenStreetMap Gemeinschaft Graz auf Twitter" + }, + "osm-at": { + "name": "OpenStreetMap Österreich", + "description": "Die Plattform für Information über OpenStreetMap in Österreich" + }, + "byosm": { + "name": "OpenStreetMap Weißrussland", + "description": "OpenStreetMap Weißrussland telegram chat" + }, + "be-facebook": { + "name": "OpenStreetMap Belgien Gemeinschaft", + "description": "Mapper und OpenStreetMap Benutzer auf Facebook in Belgien" + }, + "be-forum": { + "name": "OpenStreetMap Belgien Forum", + "description": "OpenStreetMap Belgien Web Forum" + }, + "be-irc": { + "name": "OpenStreetMap Belgien IRC", + "description": "Beteilige dich bei #osmbe auf irc.oftc.net (Port 6667)", + "extendedDescription": "Beteilige dich bei #osmbe auf irc.oftc.net (Port 6667), es wird auf dem Matrix Chat Kanal gespiegelt" + }, + "be-mailinglist": { + "name": "Talk-be Mailing Liste", + "description": "Talk-be ist die officielle Mailing Liste für die Belgische OSM Gemeinschaf" + }, + "be-maptime": { + "name": "Maptime Belgien", + "description": "Social events organized around mapping - Anfänger besonders willkommean. !", + "extendedDescription": "Maptime ist eine offene Lernumgebung für alle Erfahrungsstufen und bietet internationalen Weiterbildung für Anfänger. Maptime ist zugleich flexibel und strukturiert und bietet Platz für Einführungen ins Mappen, Workshops oder laufende Gemeinschaftsprojekte mit einem gemeinsamen Ziel sowie unaghängige/kollaborative Arbeitszeit." + }, + "be-matrix": { + "name": "OpenStreetMap Belgien Matrix channel", + "description": "Alle Mapper sind willkommen!", + "extendedDescription": "Die meißten Gespräche gibt auf auf dem \"OpenStreetMap Belgium\" Kanal. Du kannst alles fragen! Es gibt andere Räume für spezifische Themen." + }, + "be-meetup": { + "name": "OpenStreetMap Belgien Treffen", + "description": "Persönliche Treffen für alle die an OpenStreetMap interessiert sind", + "extendedDescription": "Du kannst andere Mapper bei persönliche Treffen kennenlernen, mit Ihnen diskutieren und von Ihnen lernen. Neulige sind ausdrücklich willkommen." + }, + "be-twitter": { + "name": "OpenStreetMap Belgien Twitter", + "description": "OSM Belgien auf Twitter: @osm_be" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz Mailingliste", + "description": "Talk-cz is die offizielle Mailingliste for the tschechische OSM-Gemeinschaft" + }, + "dk-forum": { + "name": "OpenStreetMap Dänemark Web Forum", + "description": "OpenStreetMap Dänemark Web Forum" + }, + "dk-irc": { + "name": "OpenStreetMap Dänemark IRC", + "description": "Beteilige dich bei #osm-dk auf irc.oftc.net (Port 6667)" + }, + "dk-mailinglist": { + "name": "Talk-dk Mailing Liste", + "description": "Eine Mailing Liste um über OpenStreetMap in Dänemark zu diskutieren" + }, + "fi-forum": { + "name": "OpenStreetMap FI Forum", + "description": "OpenStreetMap Finnland Web Forum" + }, + "fi-irc": { + "name": "OpenStreetMap Finnland IRC", + "description": "Beteilige dich bei #osm-fi auf irc.oftc.net (Port 6667)" + }, + "fi-mailinglist": { + "name": "Talk-fi Mailing Liste", + "description": "Talk-fi ist die offizielle Mailing Liste für die Finnische OSM Gemeinschaft" + }, + "fr-facebook": { + "name": "OpenStreetMap Frankreich auf Facebook", + "description": "OpenStreetMap Frankreich auf Facebook" + }, + "fr-forum": { + "name": "OpenStreetMap Frankreich Web Forum", + "description": "OpenStreetMap Frankreich Web Forum" + }, + "fr-irc": { + "name": "OpenStreetMap Frankreich auf IRC", + "description": "Beteilige dich bei #osm-fr auf irc.oftc.net (Port 6667)" + }, + "fr-mailinglist": { + "name": "Talk-fr Mailing Liste", + "description": "Talk-fr Mailing Liste" + }, + "fr-twitter": { + "name": "OpenStreetMap Frankreich auf Twitter", + "description": "OpenStreetMap Frankreich auf Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "Berlin Mailing Liste", + "description": "Das ist die Mailing Liste für die Berliner OSM Gemeinschaft" + }, + "de-berlin-meetup": { + "name": "OpenStreetMap Berlin-Brandenburg Treffen", + "description": "Mapper und OpenStreetMap Benutzer in der Berliner Gegend" + }, + "de-berlin-telegram": { + "name": "@osmberlin auf Telegram", + "description": "OpenStreetMap Berlin Telegram chat" + }, + "de-berlin-twitter": { + "name": "OpenStreetMap Berlin Twitter", + "description": "Folge uns auf Twitter: {url}" + }, + "de-forum": { + "name": "OpenStreetMap Deutschland Forum", + "description": "OpenStreetMap Deutschland Web Forum" + }, + "de-irc": { + "name": "OpenStreetMap Deutschland IRC", + "description": "Beteilige dich bei #osm-de auf irc.oftc.net (Port 6667)" + }, + "de-mailinglist": { + "name": "Talk-de Mailing Liste", + "description": "Talk-de ist die offizielle Mailing Liste der bundesdeutschen OSM Gemeinschaft" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "OWL Mailing Liste", + "description": "Das ist die Mailing Liste für die Ostwestfalen-Lippe OSM Gemeinschaft" + }, + "osm-de": { + "name": "OpenStreetMap Deutschland", + "description": "Die Plattform für Informationen über OpenStreetMap in Deutschland" + }, + "hu-facebook": { + "name": "OpenStreetMap HU auf Facebook", + "description": "Mapper und Benutzer von OpenStreetMap Facebook in Ungarn" + }, + "hu-forum": { + "name": "OpenStreetMap Ungarn Forum", + "description": "OpenStreetMap Ungarn Web Forum" + }, + "hu-meetup": { + "name": "OpenStreetMap Ungarn Treffen", + "description": "Die Plattform um Treffen in Ungarn zu organisieren" + }, + "it-facebook": { + "name": "OpenStreetMap Italien Facebook", + "description": "Beteilige dich an der OpenStreetMap Italien Gemeinschaft auf Facebook" + }, + "it-irc": { + "name": "OpenStreetMap Italien IRC", + "description": "Beteilige dich bei #osm-it auf irc.oftc.net (Port6667)" + }, + "it-mailinglist": { + "name": "Talk-it Mailing Liste", + "description": "Talk-it ist die offizielle Mailing Liste für die Italienische OSM Gemeinschaft" + }, + "it-telegram": { + "name": "@OpenStreetMapItalia auf Telegram", + "description": "OpenStreetMap Italien Telegram chat" + }, + "it-twitter": { + "name": "OpenStreetMap Italien Twitter", + "description": "Folge uns auf Twitter auf {url}" + }, + "OSM-Rome-meetup": { + "name": "Einführung für Mapper in Rom", + "description": "Verbessere in Rom und Umgebung", + "extendedDescription": "Wir zielen darauf ab es Menschen zu ermöglichen über geographischen Daten und insbesondere OpenStreetMap zu diskutieren und Wissen zu teilen, ebenso Offene Geospatial Software zum managen, editieren und anzeigen von geographischen Daten sowie Engagement zur Nutzung in Lazio, Italien" + }, + "South-Tyrol-Mailing-List": { + "name": "OpenStreetMap Mailing Liste für Südtirol", + "description": "OpenStreetMap Italien regionales Diskussionsforum für Südtirol" + }, + "talk-it-lazio": { + "name": "OpenStreetMap Lazio (Italien)", + "description": "Alle sind willkommen, melde dich an: {signupUrl}", + "extendedDescription": "Mailing Liste für Rom und das Gebiet von Lazio" + }, + "Trentino-Mailing-List": { + "name": "OpenStreetMap Mailing Liste für das Trentino", + "description": "OpenStreetMap Italien regionales Diskussionsforum für das Trentino" + }, + "no-forum": { + "name": "OpenStreetMap Frankreich Web Forum", + "description": "OpenStreetMap Frankreich Web Forum" + }, + "no-irc": { + "name": "OpenStreetMap Norwegen auf IRC", + "description": "Chat room für Mapper und OpenStreetMap Benutzer, Entwicklung und Enthusiasten in Norwegen" + }, + "no-mailinglist": { + "name": "OpenStreetMap Norwegen Mailing Liste", + "description": "Mailing Liste für Mappen und OpenStreetMap Benutzer, Entwicklung und Enthusiasten in Norwegen" + }, + "OSM-PL-facebook-group": { + "name": "OpenStreetMap Polen auf Facebook", + "description": "Gruppe für Mappers und Benutzer von OpenStreetMap in Polen" + }, + "OSM-PL-forum": { + "name": "OpenStreetMap Polen Web Forum", + "description": "Forum der Polnischen OpenStreetMap Gemeinschaft" + }, + "OSM-ES-mailinglist": { + "name": "Talk-es Mailing Liste", + "description": "Eine Mailing Liste um OpenStreetMap in Spanien zu diskutieren" + }, + "OSM-ES-telegram": { + "name": "@OSMes on Telegram", + "description": "OpenStreetMap Spanien Telegram chat" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "Bereitstellen von OSM Dienstleistungen und Information für die lokale Gemeimschaft in Schweden" + }, + "se-facebook": { + "name": "OpenStreetMap Frankreich auf Facebook", + "description": "OpenStreetMap Frankreich auf Facebook" + }, + "se-forum": { + "name": "OpenStreetMap Schweden Web Forum", + "description": "OpenStreetMap Schweden Web Forum" + }, + "se-irc": { + "name": "OpenStreetMap Schweden auf IRC", + "description": "Beteilige dich bei #osm.se auf irc.oftc.net (Port 6667)" + }, + "se-mailinglist": { + "name": "Talk-se Mailing Liste", + "description": "Eine Mailing Liste um OpenStreetMap in Schweden zu diskutieren" + }, + "se-twitter": { + "name": "OpenStreetMap Schweden auf Twitter", + "description": "Folge uns auf Twitter {url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "East Midlands (Nottingham) monatliches Treffen im Pub", + "description": "Soziales Zusammentreffen für East Midlands Mapper und Benutzer", + "extendedDescription": "Eine Gruppe trifft sich regelmäßig, zuesrt in Notringham, und neustens in Derby, machmal auch an ienme anderen Ort in den East Midlands. es sind Gemeinschaftstreffen, aber ein ausgezeichneter Ort um spezielle Fragen über OSM zu stellen. Im Sommer machen wir einfaches Mappen in der Nähe unseres Treffpunkt. Die Gruppe als Ganzes hat ein hohes Interesse öffentliche Fußwege (right of way) zu mappen u d es gibt immer wieder Mapper-Treffen genau zu diesem Zweck." + }, + "gb-mailinglist": { + "name": "Talk-gb Mailing Liste", + "description": "Talk-gb ist das Hauptkommunikationsforum für die Britische (inklusive Nordirland) OSM Gemeinschaft" + }, + "mappa-mercia-group": { + "name": "Mappa Mercia lokale Gruppe", + "description": "Ein Platz für OpenStreetMap Enthusiasten in den Midlands", + "extendedDescription": "Mappa Mercia ist ein Projekt umOpenStreetMap in tden West Midlands, UK zu Erbessern. Wir veranstalten Gemeinschaftstreffen, Trainings, und unterstützen lokale Organisationen die ihre Daten öffnen wollen." + }, + "gb-irc": { + "name": "OpenStreetMap Vereinigstes Königreich IRC", + "description": "Beteilige dich bei #osm-gb auf irc.oftc.net (Port 6667)", + "extendedDescription": "Beteilige dich bei #osm-gb auf irc.oftc.net (Port 6667), bitte sei geduldig und warte ein paar Minuten nachdem du eine Frage stellst." + }, + "OSM-CA-Slack": { + "name": "OSM Kalifornien USA Slack", + "description": "Alle sind willkommen, melde dich an: {signupUrl}" + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver", + "description": "Mapper und OpenStreetMap Benutzer in Vancouver, Kanada" + }, + "OSM-CU-telegram": { + "name": "OSM Kuba auf Telegram", + "description": "OpenStreetMap Kuba Telegram chat" + }, + "OSM-NI-telegram": { + "name": "OSM Nicaragua auf Telegram", + "description": "OpenStreetMap Nicaragua Telegram chat" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area (San Francisco) OpenStreetMapper", + "description": "Verbessere OpenStreetMap in der Bay Area (San Francisco)", + "extendedDescription": "Diese Gruppe beschäftigt sich mit der Vergrößerung der OpenStreetMap Gemeinschaft hier in der Bay Area (San Francisco). Unsere Veranstaltungen sind für alle offen, sowohl für Open Source Liebhaber, Radfahrenden, GIS Fachleute, Geocachers und alle anderen. Alle die an Karten, Kartenerstellung und freien Karte interessiert sind, sind in unserer Gruppe und bei unseren Veranstaltungen willkommen." + }, + "Central-Pennsylvania-OSM": { + "name": "Zentral-Pennsylvania OSM", + "description": "Online Mapping Gemeinschaft des State College, Pennsylvania" + }, + "Code-for-San-Jose-Slack": { + "name": "Conding für San Jose Slack", + "description": "Alle sind willkommen! Melde dich bei {signupUrl}, dann beteiligte dich am #osm Kanal." + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "Die OpenStreetMap Benutzergruppe für Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth und alle Städte dazwischen are strotzen vor kreativen und computererfahrenen Menschen. Die Vision für diese Benutzergruppe ist das finden von neuen Möglichkeiten die erstaunlichen Ressourcen von OSM zu nutzen." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Treffen für Kartenliebhaber in und um Philadelphia", + "extendedDescription": "GeoPhilly vereinigt Entwickler, Geographen, Data geeks, Open Source Liebhaber, civic hacker und Kartensüchtige in unserer gemeinsamen Leidenschaft für Karten und die Geschichten die sie erzählen. Wenn du Karten in deiner Arbeit benutzte oder einfach nur lernen willst, das ist der Treffpunkt für dich! Unsere Veranstaltungen beabsichtigen offen, freundlichen, lehrreich und sozial zu sein und range from reichen von \"happy hours\" bis \"lightning talks\" oder sogar Workshops. Bilde mit uns eine diverse und inspirierende OSM-Gemeinschaft community in Philadelphia!" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "Mapper und OpenStreetMap Enthusiasten bei den \"Twin Cities\" (Minesota, USA)", + "extendedDescription": "Verbindet OpenStreetMap Liebhaber in Minesota USA und den \"Twin Cities\"" + }, + "Mapping-DC-meetup": { + "name": "Washington DC Mappen", + "description": "Verbessere OpenStreetMap im Gebiet Washington DC", + "extendedDescription": "Wir sind eine Gruppe von ehrenamtlichen Mappern die OpenStreetMap in Washington DC verbessern wollen. Wir wollen unser Wissen über das OSM-Ökosystem, Datanalayse, Kartegraphie und GIS an andere weitergeben. Wir treffen uns jeden Monat bei Veranstaltungen um uns jedes Mal auf einen Teil unsere Stadt zu konzentrieren." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Mapper und OpenStreetMap Benutzer in und um Portland, USA", + "extendedDescription": "Maptime ist - ziemlich wörtlich - Zeit zum Mappen. Unsere Ziel ist die Türen für kartografische Möglichkeiten für alle Interessierten zu öffenen, wir stellen Zeit und Raum zum gemeinschaftlichen Lernen, Erkunden und zur Kartenerzeugung bereit und benutzen gemeinsam Mapping Tools und Technologien." + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Verbessere OpenStreetMap in Cleveland, USA", + "extendedDescription": "Open Geo Cleveland zielt darauf ab es Menschen zu ermöglichen über geographischen Daten und insbesondere OpenStreetMap zu diskutieren und Wissen zu teilen, ebenso Offene Geospatial Software zum managen, editieren und anzeigen von geographischen Daten sowie Engagement zur Nutzung in Nordost Ohio, USA. Wir sind eine Untergruppe von maptime =)" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Mapper und OpenStreetMap Benutzer in Boston, USA", + "extendedDescription": "OpenStreetMap ist die freie und wiki-artige Karte der Welt mit hundertausenden täglich Mitwirkenden wie du. Das verbessern der Karte ist einfach und macht Spaß! Triff uns sowohl bei Veranstaltungen als auch vor Ort bei unseren Bemühungen die beste Karte von Boston und dem Rest der Welt zu machen!" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Central Salish Sea", + "description": "Mapper und OpenStreetMap Benutzer und um Mount Vernon, USA", + "extendedDescription": "OpenStreetMap (OSM) ist die weltweite Karte gemacht von Menschen wie dir. Es ist die Karte zu der du beitragt und die frei zugänglich ist wie Wikipedia. Besuche osm.org für mehr Information. Wir treffen uns immer wieder um über Karten zu reden, zu Mappen und Spaß zu haben!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "Die OpenStreetMap Benutzergruppe für Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "description": "Mapper und OpenStreetMap Benutzer in Colorado, USA", + "extendedDescription": "OpenStreetMap (OSM) Colorado ist die lokale Zusammenarbeiten von Menschen die zu einer freien Karte beitragen wollen. Wir ermutigen unsere Mapper Treffen in ganz Colorado zu organisieren oder vozuschlagen. Treffen können einfach zum Kennenlernen, OSM-Lernen bis zum Fortgeschritenenen Training oder Mapathons (Mapping Parties) sein." + }, + "OSM-NYC": { + "name": "OpenStreetMap New York City", + "description": "Mapper und OpenStreetMap Benutzer, Entwickler und Liebhaber in der Metroplregion New York" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland, USA", + "description": "Mapper und OpenStreetMap Benutzer in Portland", + "extendedDescription": "OpenStreetMap (OSM) ist die weltweite Karte gemacht von Menschen wie dir. Es ist die Karte zu der du beitragt und die frei zugänglich ist wie Wikipedia. Besuche osm.org für mehr Information und komm zu einer unserer Treffen um über Karten zu reden, OSM zu verbessern und Spaß zu haben!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Mapper und OpenStreetMap Benutzer in Seattlem USA" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Süd-Kalifornien, USA", + "description": "Lass uns Spaß haben, etwas zu OSM Los Angeles beitragen und mehr über Mappen lernen!", + "extendedDescription": "OpenStreetMap (OSM) Süd-Kalifornien ist für alle am Mappen interessierte um zusammen zu kommen und mit OpenStreetMap zu arbeiten. OpenStreetMap, das Wikipedia der Karten, ist eine freie weltweite open-source Karte, die von über eine Million von Freiwilligen rund um die Globus erzeugt wird. Wenn du OpenStreetMap nicht kennst, unterstützen wird dich. Wenn du eine Idee für ein Kartenprojekt oder einen Erkundungsrundgang hast, den die Gruppe durchführen kann wäre das großartig!" + }, + "OSM-South-Bay": { + "name": "OSM South Bay", + "description": "Mapping-Nächste veranstalted von \"Code for San Jose\"", + "extendedDescription": "\"Code for San Jose\", die lokale \"Code for America\" Brigade, veransalted monatlichen Mapping-Nächte jeweils Donnerstag abend in Zentrum von San José. Triff andere South Bay Mapper, unterstütze lokale Mapping-Projekte und erfahre von anderen zivilen Technik-Projekten. Du brauchst keine Erfahrung im Programmieren oder mit GIS." + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Tampa Bay", + "description": "Mapper und OpenStreetMap Benutzer in Tampa Bay, USA", + "extendedDescription": "OSM Tampa Bay ist eine Gruppe von Bewohner die sich treffen und die definitiv beste OSM-Karte von Tampa Bay machen, die freie und editierbare Karte der Welt. Wenn du dich für Karten, Open Source, GPS, Wandern, Radfahren oder ähnliches interessierst wirst du OpenStreetMap lieben! Beteilige dich bei uns, wir treffen uns zum Reden und Mappen etwa einmal monatlich." + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack", + "description": "Alle sind willkommen! Melde dich unter {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap US", + "description": "Wir helfen dabei OpenStreetMap in den USA zu verbessern.", + "extendedDescription": "Wir unterstützen OpenStreetMap durch eine jährliche Konferenz, Unterstützung von lokalen OSM-Gruppen, Aufbau von Partnerschaft und durch Verbreitung des Vorteilen von OSM. Beteiligte sich an OpenStreetMap US hier: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah", + "description": "Mapper und OpenStreetMap Benutzer in Salt Lake City, USA", + "extendedDescription": "Activitäten beinhalten Workshop zum Erlernen des Mappens, Mapathong (Mapping Parties und Datensammlung vor Ort. Die Veranstaltungen finden in der SLC area statt, zumindest anfänglichen. Wir suchen erfahrene Mapper und Menschen die OSM kennenlernenn wollen. Beteilige dich und lass und mappen!" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming", + "description": "Mapper und OpenStreetMap Benutzer in Wyoming, USA", + "extendedDescription": "OpenStreetMap (OSM) Wyoming ist eine lokale Gemeinschaftsinitiative von menschen die gerne freie Karten tatkräftig unterstützen wollen. Wir ermuten alle unsere Mappler Veranstaltungen zum Mappen in Wyoming vozuschlagen oder zu veranstalten. Treffen können einfach zum Kennenlerne, zur Erlernenn von OSM-Grundlagen oder Fortgeschrittenem Training oder einfach Mappatons (Mapping Parties) sein." + }, + "PHXGeo-meetup": { + "name": "PHXGeo Treffen", + "description": "Mapper und OpenStreetMap Benutzer in Phoenix, Arizona, USA", + "extendedDescription": "Das ist ein Treffpunkt für alle in Phoenix die Karten, GIS, OpenStreetMap, Kartographie und alle dazwischen mögen." + }, + "PHXGeo-twitter": { + "name": "PHXGeo Twitter", + "description": "Folge uns auf Twitter {url}" + }, + "Western-Slope-facebook": { + "name": "Western Slope OSM Facebook", + "description": "Mapper und OpenStreetMap Benutzer in und um Grand Junction, Colorado, USA" + }, + "Western-Slope-meetup": { + "name": "Western Slope OSM Treffen", + "description": "Mapper und OpenStreetMap Benutzer in und um Grand Junction, Colorado, USA", + "extendedDescription": "Das Ziel dieser Gruppe ist OpenStreetMap in der Region einzuführen, eine Gemeinschaft von Mappern zu entwickeln, die erstaunlichsten Geodaten mit allen zur Verfügung stehenden Mitteln zu erzeugen und diese Daten in der ganzen Gegend bekannt zu machen. Stell dir einen ganz genaue Wanderkarte oder auch genaue Karte der Fahrradwege vor; oder alles andere was du willst, das ist die Freude von OpenStreetMap!" + }, + "Maptime-Australia-Slack": { + "name": "Maptime Australia Slack", + "description": "Beteilige dich unter {signupUrl}" + }, + "talk-au": { + "name": "Talk-au Mailing Liste", + "description": "Mappers in Australien chatten hier" + }, + "OSM-AR-facebook": { + "name": "OpenStreetMap Argentinen Facebook", + "description": "Beteiligte dich bei der argentinischen OpenStreetMap Gemeinschaft auf Facebook", + "extendedDescription": "Nachrichten von der lokalen Gemeinschaft" + }, + "OSM-AR-forum": { + "name": "OpenStreetMap Argentinen web forum", + "description": "Beteilige dich am argentinischen OpenStreetMap web forum", + "extendedDescription": "Ideal für lange oder wichtige Diskussionen. Lansame Reaktionszeit." + }, + "OSM-AR-irc": { + "name": "OpenStreetMap Argentinen IRC", + "description": "Beteilige dich an #osm-ar auf irc.oftc.net (Port 6667)", + "extendedDescription": "Du könntest den sümmsten Benuzter in der Gemeinschaft finden." + }, + "OSM-AR-mailinglist": { + "name": "Talk-ar Mailingiste", + "description": "Historische Mailing Liste, heute fast nicht mehr benutzt." + }, + "OSM-AR-telegram": { + "name": "OpenStreetMap Argentinen Telegram", + "description": "Beteilige dich an der argentinischen OpenStreetMap Gemeinschaft auf Telegram", + "extendedDescription": "Der aktivsten Kanal in der Gemeinschaft, ideals zum Tratschen und um schnell Antworten auf Fragen zu bekommen. Alle sind willkommen!" + }, + "OSM-AR-twitter": { + "name": "OpenStreetMap Argentinen Twitter", + "description": "Folge uns auf Twitter {url}", + "extendedDescription": "Nachrichten von der lokalen Gemeinschaft und OpenStreetMap in Allgemeinen." + }, + "OSM-BO-mailinglist": { + "name": "Talk-bo Mailing Liste", + "description": "Talk-bo ist die offizielle Mailing Liste für die Bolivianische OpenStreetMap Gemeinschaft", + "extendedDescription": "Mappen in Bolivien? Hast du Frage, willlst du mit der OSM gemeinschaft Kontakt aufnehmen? Beteilige dich bei {url}. Alle sind willkommen!" + }, + "Bahia-telegram": { + "name": "OpenStreetMap Bahia (Brasilien) Telegram Gruppe", + "description": "Beteiligte dich an der OpenStreetMap Bahia (Brasislien) Gemeinschaft auf Telegram", + "extendedDescription": "Beteilige dich an der Gemeinschaft um mehr über OpenStreetMap zu lernen, zu fragen oder an unseren Treffen teilzunehmen. Alle sind willkommen!" + }, + "DF-telegram": { + "name": "OpenStreetMap Brasílien Telegram Gruppe", + "description": "Beteiligte dich an der OpenStreetMap Brasílien Gemeinschaft auf Telegram", + "extendedDescription": "Beteiligte dich an der Gemeinschaft um mehr über OpenStreetMap zu lernen, stelle Fragaen oder nimm an unsere Treffen teil." + }, + "OSM-br-mailinglist": { + "name": "Talk-br Mailing List", + "description": "Eine Mailing Liste um OpenStreetMap in Brasilien zu diskutieren" + }, + "OSM-br-telegram": { + "name": "OpenStreetMap Brasilen Telegram", + "description": "Beteiligte dich an der OpenStreetMap Brasilien Gemeinschaft auf Facebook", + "extendedDescription": "Beteilige dich an der Gemeinschaft um mehr über OpenStreetMap zu lernen, zu fragen oder an unseren Treffen teilzunehmen. Alle sind willkommen!" + }, + "OSM-br-twitter": { + "name": "OpenStreetMap Brasilien Twitter", + "description": "Folge uns auf Twitter {url}" + }, + "OSM-CL-facebook": { + "name": "OpenStreetMap Chile Facebook", + "description": "Beteiligte dich an der OpenStreetMap Chile Gemeinschaft auf Facebook", + "extendedDescription": "Beteilige dich an der Gemeinschaft um mehr über OpenStreetMap zu lernen, zu fragen oder an unseren Treffen teilzunehmen. Alle sind willkommen!" + }, + "OSM-CL-mailinglist": { + "name": "Talk-cl Mailing List", + "description": "Eine Mailing Liste um OpenStreetMap in Chile zu diskutieren" + }, + "OSM-CL-telegram": { + "name": "OpenStreetMap Chile Telegram", + "description": "Beteiligte dich an der OpenStreetMap Chile Gemeinschaft auf Telegram", + "extendedDescription": "Beteilige dich an der Gemeinschaft um mehr über OpenStreetMap zu lernen, zu fragen oder an unseren Treffen teilzunehmen. Alle sind willkommen!" + }, + "OSM-CL-twitter": { + "name": "OpenStreetMap Chile Twitter", + "description": "Folge uns auf Twitter {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá", + "description": "Wir sind eine Gruppe von Mappper die sich für Mappen in OpenStreetMap rund um Bogotá interessiert.", + "extendedDescription": "Lerne Daten vor Ort zu erheben und auf OpenStreetMap zu digitalisieren. Du brauchst kein Vorwissen, du musst nur am Miwirken, Lernen und Spaß haben interessiert sein." + }, + "OSM-CO-facebook": { + "name": "OpenStreetMap Kolumbien Facebook", + "description": "Beteiligte dich bei der kolumbianische OpenStreetMap Gemeinschaft auf Facebook", + "extendedDescription": "Beteiligte dich bei der kolumbianische OpenStreetMap Gemeinschaft um zu lernen. Alle sind willkommen!" + }, + "OSM-CO-mailinglist": { + "name": "Talk-co Mailing Liste", + "description": "Eine Mailing Liste zur Diskussion über OpenStreetMap in Kolumbien" + }, + "OSM-CO-telegram": { + "name": "OSM Colombia auf Telegram", + "description": "OpenStreetMap Colombia Telegram chat" + }, + "OSM-CO-twitter": { + "name": "OpenStreetMap Kolumbien Twitter", + "description": "Folge uns auf Twitter {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Kolumbien", + "description": "Nachrichten von der OpenStreetMap Gemeinschaft in Kolumbien und der OSMCo Sitftung" + }, + "OSM-EC-telegram": { + "name": "OSM Ecuador auf Telegram", + "description": "OpenStreetMap Ecuador Telegram chat" + }, + "OSM-PY-telegram": { + "name": "OSM Paraguay auf Telegram", + "description": "OpenStreetMap Paraguay Telegram chat" + }, + "OSM-PE-facebook": { + "name": "OpenStreetMap Peru Facebook", + "description": "Beteiligte dich bei der OpenStreetMap Peru Gemeinschaft auf Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Talk-pe Mailing List", + "description": "Die offizielle Mailing List der OpenStreetMap Peru Gemeinschaft" + }, + "OSM-PE-matrix": { + "name": "OpenStreetMap Peru Matrix Chat", + "description": "Unterhalte dich mit anderen Mitgliedern der OpenStreetmap Peru Gemeinschaft in Matrix." + }, + "OSM-PE-telegram": { + "name": "OpenStreetMap Peru Telegram", + "description": "Beteilige dich bei OpenStreetMap Peru Gemeinschaft in Telegram" + }, + "OSM-PE-twitter": { + "name": "OpenStreetMap Peru Twitter", + "description": "Folge uns auf Twitter unter {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap Peru", + "description": "Neuigkeiten und Quellen für die OpenStreetMap Peru Gemeinschaft" + }, + "OSM-Facebook": { + "name": "OpenStreetMap auf Facebook", + "description": "Like uns auf Facebook für Nachrichten und Updates über OpenStreetMap." + }, + "OSM-help": { + "name": "OpenStreetMap Hilfe", + "description": "Stelle Fragen und erhalte Antworten auf der FAQ-Seite der OSM-Gemeinschaft", + "extendedDescription": "{url} ist für alle die Hilfe mit OpenStreetMap brauchen. Egal ob du zu Mappen beginnst oder eine technische Frage hast, wir sind hier um dir zu helfen!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap in Reddit", + "description": "/r/openstreetmap/ ist ein großartiger Ort um mehr über OpenStreetMap zu lernen. Du kannst jede Frage stellen!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter", + "description": "Folge uns auf Twitter unter {url}" + }, + "OSMF": { + "name": "OpenStreetMap Foundation (OSM Stiftung)", + "description": "OSMF ist eine gemeinnützige Organisation im Sitz im Vereinigten Königreichm die das OpenStreetMap Projekt unterstützt", + "extendedDescription": "OSMF unterstützt OpenStreetMap durch Fundraising, den Betrieb der OSM-Server, die Organisation der jährlichen Konferenz \"State of the Map\" und die Koordination der Freiwilligen die OSM am Laufen halten. Du kannst deine Unterstützung zeigen und eine Stimme für die Richtung der Weiterentwicklung von OpenStreetMap bekommen, indem du der OSMF als Mitglied beitrittst: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Komm für 3 Tage nach Mailand, Italien zur weltweiten jährlichen OpenStreetMap Konferenz, wo sich die gesamte OSM Gemeinschaft sich kennenlernt, austauscht und voneinander lernt.", + "where": "Mailand, Italien" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/el.json b/vendor/assets/iD/iD/locales/el.json index c5ffd6800..5455619f1 100644 --- a/vendor/assets/iD/iD/locales/el.json +++ b/vendor/assets/iD/iD/locales/el.json @@ -1,5 +1,10 @@ { "el": { + "icons": { + "information": "πληροφορία", + "remove": "αφαίρεση", + "undo": "αναίρεση" + }, "modes": { "add_area": { "title": "Περιοχή", @@ -25,6 +30,9 @@ }, "draw_line": { "tail": "Κάντε κλικ για να προσθέσετε περισσότερους κόμβους στη γραμμή. Κλικ σε άλλες γραμμές για να τις συνδέσετε και διπλό κλικ για να τερματίσετε τη γραμμή." + }, + "drag_node": { + "connected_to_hidden": "Αυτό δεν μπορεί να επεξεργαστεί επειδή είναι συνδεμένο με ένα κρυφό χαρακτηριστικό." } }, "operations": { @@ -142,7 +150,9 @@ "vertex": "Συνδέθηκε μια διαδρομή σε μια άλλη.", "line": "Συνδέθηκε μια διαδρομή σε γραμμή.", "area": "Συνδέθηκε μια διαδρομή σε περιοχή." - } + }, + "relation": "Αυτά τα χαρακτηριστικά δεν μπορούν να συνδεθούν επειδή έχουν αντικρουόμενους ρόλους σχέσεων.", + "restriction": "Αυτά τα χαρακτηριστικά δεν μπορούν να συνδεθούν επειδή θα έβλαπταν μια σχέση \"{relation}\"." }, "disconnect": { "title": "Αποσύνδεση", @@ -160,7 +170,8 @@ "annotation": "Συγχωνεύτηκαν {n} χαρακτηριστικά.", "not_eligible": "Αυτά τα χαρακτηριστικά δεν μπορούν να συγχωνευτούν.", "not_adjacent": "Αυτά τα χαρακτηριστικά δεν μπορούν να σθγχωνευτούν επειδή τα ακριανά τους σημεία δεν είναι συνδεδεμένα.", - "restriction": "Αυτά τα χαρακτηριστικά δεν μπορούν να συγχωνευτούν επειδή τουλάχιστον ένα είναι μέλος μίας σχέσης \"{relation}\".", + "restriction": "Αυτά τα χαρακτηριστικά δεν μπορούν να συγχωνευθούν επειδή θα έβλαπταν μια σχέση \"{relation}\".", + "relation": "Αυτά τα χαρακτηριστικά δεν μπορούν να συγχωνευθούν επειδή έχουν αντικρουόμενους ρόλους σχέσεων.", "incomplete_relation": "Αυτά τα χαρακτηριστικά δεν μπορούν να συγχωνευτούν επειδή δεν έχουν μεταφορτωθεί πλήρως.", "conflicting_tags": "Αυτά τα χαρακτηριστικά δεν μπορούν να συγχωνευτούν επειδή κάποιες από τις ετικέτες τους έχουν διαφορετικές τιμές." }, @@ -252,6 +263,39 @@ } } }, + "restriction": { + "controls": { + "distance": "Απόσταση", + "distance_up_to": "Μέχρι το {απόσταση}", + "via": "Μέσω", + "via_node_only": "Μόνο κόμβος", + "via_up_to_one": "Μέχρι 1 δρόμο", + "via_up_to_two": "Μέχρι 2 δρόμους" + }, + "help": { + "indirect": "(έμμεσα)", + "turn": { + "no_left_turn": "ΟΧΙ Αριστερή Στροφή {έμμεσα}", + "no_right_turn": "ΟΧΙ Δεξιά στροφή {έμμεσα}", + "no_u_turn": "ΟΧΙ Αναστροφή {έμμεσα}", + "no_straight_on": "ΟΧΙ Ευθεία {έμμεσα}", + "only_left_turn": "ΜΟΝΟ Αριστερή Στροφή {έμμεσα}", + "only_right_turn": "ΜΟΝΟ Δεξιά στροφή {έμμεσα}", + "only_u_turn": "ΜΟΝΟ Αναστροφή {έμμεσα}", + "only_straight_on": "ΜΟΝΟ Ευθεία {έμμεσα}", + "allowed_left_turn": "Επιτρέπεται η Αριστερή Στροφή {έμμεσα}", + "allowed_right_turn": "Επιτρέπεται η Δεξιά Στροφή {έμμεσα}", + "allowed_u_turn": "Επιτρέπεται η Αναστροφή {έμμεσα}", + "allowed_straight_on": "Επιτρέπεται η Πορεία Ευθεία {έμμεσα}" + }, + "from": "ΑΠΟ", + "via": "ΜΕΣΩ", + "to": "ΓΙΑ", + "select_from": "Κάντε κλικ για να επιλέξετε ένα τμήμα {from}", + "select_from_name": "Κάντε κλικ για να επιλέξετε {from} {fromName}", + "toggle": "Κάντε κλικ για \"{turn}\"" + } + }, "undo": { "tooltip": "Αναίρεση: {action}", "nothing": "Τίποτα προς αναίρεση." @@ -268,6 +312,7 @@ "localized_translation_language": "Επιλογή γλώσσας", "localized_translation_name": "Όνομα" }, + "zoom_in_edit": "Μεγέθυνση για επεξεργασία", "login": "σύνδεση", "logout": "Αποσύνδεση", "loading_auth": "Σύνδεση στο OpenStreetMap...", @@ -280,22 +325,26 @@ "status": { "error": "Αδυναμία σύνδεσης στο API.", "offline": "Το API είναι εκτός σύνδεσης. Παρακαλώ δοκιμάστε επεξεργασία αργότερα.", - "readonly": "Το API είναι μόνο-για-ανάγνωση. Θα χρειαστεί να περιμένετε για να αποθηκεύσετε τις αλλαγές σας." + "readonly": "Το API είναι μόνο-για-ανάγνωση. Θα χρειαστεί να περιμένετε για να αποθηκεύσετε τις αλλαγές σας.", + "rateLimit": "Το API περιορίζει τις ανώνυμες συνδέσεις. Μπορείτε να το διορθώσετε αυτό κάνοντας σύνδεση." }, "commit": { "title": "Μεταφόρτωση στο OpenStreetMap", "upload_explanation": "Οι αλλαγές που θα ανεβάσετε θα είναι ορατές σε όλους τους χάρτες που χρησιμοποιούν δεδομένα OpenStreetMap.", "upload_explanation_with_user": "Οι αλλαγές που θα ανεβάσετε ως {user} θα είναι ορατές σε όλους τους χάρτες που χρησιμοποιούν δεδομένα OpenStreetMap.", + "request_review": "Θα ήθελα κάποιος να ελέγξει τις επεξεργασίες μου.", "save": "Μεταφόρτωση", "cancel": "Ακύρωση", "changes": "{count} Αλλαγές", + "download_changes": "Κατεβάστε το αρχείο osmChange", "warnings": "Προειδοποιήσεις", "modified": "Τροποποιήθηκε", "deleted": "Διαγράφηκε", "created": "Δημιουργήθηκε", "about_changeset_comments": "Σχετικά με τα σχόλια αλλαγών", "about_changeset_comments_link": "//wiki.openstreetmap.org/wiki/El:Good_changeset_comments", - "google_warning": "Αναφέρατε την Google σε αυτό το σχόλιο: θυμηθείτε πως η αντιγραφή από τους Χάρτες Google απαγορεύεται αυστηρά." + "google_warning": "Αναφέρατε την Google σε αυτό το σχόλιο: θυμηθείτε πως η αντιγραφή από τους Χάρτες Google απαγορεύεται αυστηρά.", + "google_warning_link": "https://www.openstreetmap.org/copyright" }, "contributors": { "list": "Επεξεργασίες από {users}", @@ -303,24 +352,48 @@ }, "info_panels": { "background": { - "title": "Υπόβαθρο" + "title": "Υπόβαθρο", + "zoom": "Εστίαση", + "vintage": "Εποχής", + "source": "Πηγή", + "description": "Περιγραφή", + "resolution": "Ανάλυση", + "accuracy": "Ακρίβεια", + "unknown": "Άγνωστο", + "show_tiles": "Εμφάνιση πλακιδίων", + "hide_tiles": "Απόκρυψη πλακιδίων" }, "history": { "title": "Ιστορικό", "selected": "{n} επιλεγμένα", - "version": "Έκδοση" + "no_history": "Κανένα ιστορικό (Νέα Λειτουργία)", + "version": "Έκδοση", + "last_edit": "Τελευταία Επεξεργασία", + "edited_by": "Επεξεργάστηκε από", + "changeset": "Πακέτο αλλαγών", + "unknown": "Άγνωστο", + "link_text": "Ιστορικό στο openstreetmap.org" }, "location": { - "title": "Τοποθεσία" + "title": "Τοποθεσία", + "unknown_location": "Άγνωστη Τοποθεσία" }, "measurement": { + "key": "Μ", "title": "Μέτρηση", + "selected": "{n} επιλεγμένο", "geometry": "Γεωμετρία", + "closed_line": "κλειστή γραμμή", + "closed_area": "κλειστή περιοχή", "center": "Κέντρο", "perimeter": "Περίμετρος", "length": "Μήκος", "area": "Περιοχή", - "location": "Τοποθεσία" + "centroid": "Κεντροϊδές", + "location": "Τοποθεσία", + "metric": "Μετρικό", + "imperial": "Αγγλοσαξονικό", + "node_count": "Αριθμός των κόμβων" } }, "geometry": { @@ -342,6 +415,7 @@ "inspector": { "no_documentation_combination": "Δεν υπάρχει διαθέσιμη τεκμηρίωση για αυτόν τον συνδυασμό ετικετών", "no_documentation_key": "Δεν υπάρχει διαθέσιμη τεκμηρίωση για αυτό το κλειδί", + "documentation_redirect": "Αυτές οι οδηγίες έχουν ανακατευθυνθεί σε μια νέα σελίδα", "show_more": "Εμφάνιση Περισσότερων", "view_on_osm": "Προβολή στο openstreetmap.org", "all_fields": "Όλα τα πεδία", @@ -368,6 +442,7 @@ }, "radio": { "structure": { + "type": "Τύπος", "default": "Προκαθορισμένο", "layer": "Στρώση" } @@ -383,13 +458,22 @@ "background": { "title": "Παρασκήνιο", "description": "Ρυθμίσεις παρασκηνίου", + "backgrounds": "Φόντα", "none": "Κανένα", "best_imagery": "Η καλύτερη γνωστή πηγή εικόνας για αυτήν την τοποθεσία", "switch": "Επέστρεψε σε αυτό το παρασκήνιο", "custom": "Εξατομικευμένο", "custom_button": "Επεξεργασία εξατομικευμένου παρασκηνίου", + "overlays": "Επικαλύψεις", + "imagery_source_faq": "Πληροφορία εικόνας / Αναφορά προβλήματος", "reset": "Μηδενισμός", + "display_options": "Επιλογές Εμφάνισης", + "brightness": "Φωτηνότητα", + "contrast": "Αντίθεση", + "saturation": "Κορεσμός", + "sharpness": "Οξύτητα", "minimap": { + "description": "Εμφάνιση μικρού χάρτη", "tooltip": "Προβολή ενός χάρτη σε σμίκρυνση, για να σας βοηθήσει να εντοπίσετε την περιοχή που εμφανίζεται αυτή τη στιγμή.", "key": "/" }, @@ -400,9 +484,16 @@ "title": "Δεδομένα Χάρτη", "description": "Δεδομένα Χάρτη", "data_layers": "Στρώσεις δεδομένων", + "layers": { + "osm": { + "tooltip": "Δεδομένα χάρτη από το OpenStreetMap", + "title": "Δεδομένα OpenStreetMap" + } + }, "fill_area": "Γέμισμα περιοχών", "map_features": "Χαρακτηριστικά Χάρτη", - "autohidden": "Αυτά τα χαρακτηριστικά έχουν κρυφθεί αυτόματα γιατί θα εμφανίζονταν πάρα πολλά στην οθόνη. Μπορείτε να εστιάσετε για να τα επεξεργαστείτε." + "autohidden": "Αυτά τα χαρακτηριστικά έχουν κρυφθεί αυτόματα γιατί θα εμφανίζονταν πάρα πολλά στην οθόνη. Μπορείτε να εστιάσετε για να τα επεξεργαστείτε.", + "osmhidden": "Αυτά τα χαρακτηριστικά έχουν κρυφτεί αυτόματα επειδή το επίπεδο του OpenStreetMap είναι κρυφό." }, "feature": { "points": { @@ -456,24 +547,32 @@ }, "area_fill": { "wireframe": { - "description": "Χωρίς γέμισμα (Πλαίσια γραμμών)" + "description": "Χωρίς γέμισμα (Πλαίσια γραμμών)", + "tooltip": "Ενεργοποιώντας τη λειτουργία wireframe, μπορείτε να δείτε εύκολα τις εικόνες φόντου." }, "partial": { - "description": "Μερικό γέμισμα" + "description": "Μερικό γέμισμα", + "tooltip": "Οι περιοχές σχεδιάζονται με γέμισμα μόνο γύρω από τις εσωτερικές τους άκρες. (Συνιστάται για αρχάριους χαρτογράφους)" }, "full": { - "description": "Πλήρες γέμισμα" + "description": "Πλήρες γέμισμα", + "tooltip": "Οι περιοχές σχεδιάζονται πλήρως γεμισμένες." } }, "restore": { "heading": "Έχετε μη αποθηκευμένες αλλαγές", - "description": "Θα θέλατε να επαναφέρετε μη αποθηκευμένες αλλαγές από μια προηγούμενη συνεδρία επεξεργασίας;" + "description": "Θα θέλατε να επαναφέρετε μη αποθηκευμένες αλλαγές από μια προηγούμενη συνεδρία επεξεργασίας;", + "restore": "Επαναφέρετε τις αλλαγές μου", + "reset": "Απορρίψτε τις αλλαγές μου" }, "save": { "title": "Αποθήκευση", + "help": "Ελέγξτε τις αλλαγές σας και μεταφορτώστε τις στο OpenStreetMap, καθιστώντας τις ορατές σε άλλους χρήστες.", "no_changes": "Δεν υπάρχουν αλλαγές για αποθήκευση.", + "error": "Παρουσιάστηκαν σφάλματα κατά την προσπάθεια αποθήκευσης", "unknown_error_details": "Παρακαλώ επιβεβαιώστε ότι είστε συνδεδεμένοι στο διαδίκτυο.", "uploading": "Μεταφόρτωση αλλαγών στο OpenStreetMap...", + "conflict_progress": "Έλεγχος για συγκρούσεις: {num} από {total}", "unsaved_changes": "Έχετε μη αποθηκευμένες αλλαγές", "conflict": { "header": "Επίλυση επεξεργασιών σε διένεξη", @@ -484,25 +583,34 @@ "keep_remote": "Χρησιμοποίησε τα δικά τους", "restore": "Επανέφερε", "delete": "Αφήστε Διεγραμμένη", - "done": "Όλες οι διενέξεις επιλύθηκαν!" + "download_changes": "Ή κατεβάστε το αρχείο osmChange", + "done": "Όλες οι διενέξεις επιλύθηκαν!", + "help": "Ένας άλλος χρήστης άλλαξε μερικά από τα ίδια χαρακτηριστικά χάρτη που άλλαξατε. Κάντε κλικ σε καθένα από τα παρακάτω χαρακτηριστικά για περισσότερες λεπτομέρειες σχετικά με τη σύγκρουση και επιλέξτε αν θα διατηρήσει τις αλλαγές σας ή τις αλλαγές του άλλου χρήστη\n" } }, "merge_remote_changes": { "conflict": { + "deleted": "Αυτό το χαρακτηριστικό έχει διαγραφεί από το χρήστη {user}.", + "location": "Αυτή η λειτουργία μετακινήθηκε τόσο από εσάς όσο και από τον {user}.", "nodelist": "Αλλάξανε κόμβοι και από εσάς και από {user}.", "memberlist": "Αλλάξανε μέλη σχέσης και από εσάς και από {user}.", "tags": "Αλλάξατε την ετικέτα {tag} σε \"{local}\" και η/ο {user} την άλλαξε σε \"{remote}\"." } }, "success": { - "edited_osm": "Επεξεργαστήκατε τον OSM", "just_edited": "Μόλις επεξεργαστήκατε το OpenStreetMap!", - "view_on_osm": "Εμφάνιση στο OSM", - "facebook": "Διαμοιρασμός στο Facebook", - "twitter": "Διαμοιρασμός στο Twitter", - "google": "Διαμοιρασμός στο Google+", - "help_html": "Οι αλλαγές σας θα εμφανιστούν στο \"Κανονικό\" στρώμα σε λίγα λεπτά. Στα άλλα στρώματα, και ορισμένα χαρακτηριστικά, ίσως χρειαστούν περισσότερο χρόνο.", - "help_link_text": "Λεπτομέρειες" + "thank_you": "Σας ευχαριστούμε για τη βελτίωση του χάρτη.", + "thank_you_location": "Σας ευχαριστούμε για τη βελτίωση του χάρτη γύρω από το {where}.", + "help_html": "Οι αλλαγές σας θα πρέπει να εμφανιστούν στο OpenStreetMap μέσα σε λίγα λεπτά. Ενδέχεται να χρειαστεί περισσότερος χρόνος για να λάβετε ενημερώσεις από άλλους χάρτες.", + "help_link_text": "Λεπτομέρειες", + "view_on_osm": "Προβολή Αλλαγών στο OSM", + "changeset_id": "Το πακέτο αλλαγών σας #: {changeset_id}", + "like_osm": "Σας αρέσει το OpenStreetMap; Σύνδεση με άλλους:", + "more": "Περισσότερα", + "events": "Εκδηλώσεις", + "languages": "Γλώσσες: {languages}", + "missing": "Λείπει κάτι από αυτόν τον κατάλογο;", + "tell_us": "Πείτε μας!" }, "confirm": { "okay": "Εντάξει", @@ -511,11 +619,16 @@ "splash": { "welcome": "Καλώς ήλθατε στον iD επεξεργαστή για το OpenStreetMap", "text": "Το iD είναι ένα φιλικό αλλά ισχυρό εργαλείο για συνεισφορά στον καλύτερο του κόσμου, ελεύθερο, παγκόσμιο χάρτη. Αυτή είναι η έκδοση {version}. Για περισσότερες πληροφορίες δείτε το {website} και αναφέρετε bugs στο {github}.", - "walkthrough": "Ξεκινήστε την Περιήγηση" + "walkthrough": "Ξεκινήστε την Περιήγηση", + "start": "Επεξεργασία τώρα" }, "source_switch": { + "live": "ζωντανά", "lose_changes": "Έχετε μη αποθηκευμένες αλλαγές. Αλλάζοντας τον διακομιστή χάρτη θα τις απορρίψετε. Είστε σίγουρος/-η ότι θέλετε να αλλάξετε διακομιστή;" }, + "version": { + "whats_new": "Τι νέο υπάρχει στο iD {version}" + }, "tag_reference": { "description": "Περιγραφή", "on_wiki": "{tag} στο wiki.osm.org", @@ -523,30 +636,233 @@ }, "validations": { "disconnected_highway": "Αποσυνδεδεμένη οδός", + "disconnected_highway_tooltip": "Οι δρόμοι θα πρέπει να συνδέονται με άλλους δρόμους ή με εισόδους κτιρίων.", "untagged_point": "Σημείο χωρίς ετικέτα", "untagged_point_tooltip": "Επιλέξτε ένα τύπο χαρακτηριστικού που περιγράφει τι είναι αυτό το σημείο.", "untagged_line": "Γραμμή χωρίς ετικέτα", "untagged_line_tooltip": "Επιλέξτε ένα τύπο χαρακτηριστικού που περιγράφει τι είναι αυτή η γραμμή.", "untagged_area": "Περιοχή χωρίς ετικέτα", "untagged_area_tooltip": "Επιλέξτε ένα τύπο χαρακτηριστικού που περιγράφει τι είναι αυτή η περιοχή.", + "untagged_relation_tooltip": "Επιλέξτε ένα τύπο χαρακτηριστικού που περιγράφει τι είναι αυτή η σχέση.", + "many_deletions": "Διαγράφετε {n} χαρακτηριστικά: {p} κόμβους, {l} γραμμές, {a} περιοχές, {r} σχέσεις. Είστε βέβαιοι ότι θέλετε να το κάνετε αυτό; Αυτό θα τα διαγράψει από το χάρτη που βλέπουν όλοι οι άλλοι στο openstreetmap.org.", "tag_suggests_area": "Η ετικέτα {tag} προτείνει ότι η γραμμή πρέπει να είναι περιοχή, αλλά δεν είναι περιοχή", "deprecated_tags": "Παρωχημένες ετικέτες: {tags}" }, + "zoom": { + "in": "Μεγέθυνση", + "out": "Απομάκρυνση" + }, "cannot_zoom": "Δεν είναι δυνατή μεγαλύτερη σμίκρυνση στην τρέχουσα κατάσταση λειτουργίας.", "full_screen": "Αλλάξτε σε Πλήρη Οθόνη", "gpx": { "local_layer": "Τοπικό αρχείο", - "zoom": "Μεγένθυνε στη στρώση" + "drag_drop": "Σύρετε και αποθέστε ένα αρχείο .gpx, .geojson ή .kml στη σελίδα ή κάντε κλικ στο κουμπί στα δεξιά για να περιηγηθείτε", + "zoom": "Μεγένθυνε στη στρώση", + "browse": "Αναζητήστε ένα αρχείο" + }, + "mapillary_images": { + "tooltip": "Φωτογραφίες στο επίπεδο του δρόμου από το Mapillary", + "title": "Επικάλυψη Φωτογραφιών (Mapillary)" + }, + "mapillary_signs": { + "tooltip": "Ένδειξη κυκλοφορίας από το Mapillary (πρέπει να ενεργοποιήσετε την επικάλυψη Φωτογραφιών)", + "title": "Επικάλυψη Ένδειξης Κυκλοφορίας (Mapillary)" }, "mapillary": { "view_on_mapillary": "Δείτε αυτή τη φωτογραφία στο Mapillary" }, + "openstreetcam_images": { + "tooltip": "Φωτογραφίες στο επίπεδο του δρόμου από το OpenStreetCam", + "title": "Επικάλυψη φωτογραφίας (OpenStreetCam)" + }, + "openstreetcam": { + "view_on_openstreetcam": "Δείτε αυτήν την εικόνα στο OpenStreetCam" + }, "help": { - "title": "Βοήθεια" + "title": "Βοήθεια", + "help": { + "title": "Βοήθεια", + "welcome": "Καλώς ήλθατε στον επεξεργαστή iD για το [OpenStreetMap] (https://www.openstreetmap.org/). Με αυτόν τον επεξεργαστή μπορείτε να ενημερώσετε το OpenStreetMap απευθείας από το πρόγραμμα περιήγησης ιστού σας.", + "open_data_h": "Ανοιχτά Δεδομένα", + "open_data": "Οι επεξεργασίες που κάνετε σε αυτό τον χάρτη θα είναι ορατές σε όλους όσους χρησιμοποιούν το OpenStreetMap. Οι τροποποιήσεις σας μπορούν να βασίζονται σε προσωπικές γνώσεις, σε επιτόπια έρευνα ή εικόνες που συλλέγονται από αεροφωτογραφίες ή φωτογραφίες στο επίπεδο του δρόμου. Αντιγραφή από εμπορικές πηγές, όπως οι Χάρτες Google, [απαγορεύονται αυστηρά] (https://www.openstreetmap.org/copyright).", + "before_start_h": "Πριν ξεκινήσετε", + "before_start": "Θα πρέπει να είστε εξοικειωμένοι με το OpenStreetMap και αυτόν τον επεξεργαστή πριν ξεκινήσετε την επεξεργασία. Το iD περιέχει μια καθοδήγηση για να σας διδάξει τα βασικά της επεξεργασίας του OpenStreetMap. Κάντε κλικ στο \"Εκκίνηση της Καθοδήγησης\" σε αυτήν την οθόνη για να πάρετε το μάθημα - χρειάζονται μόνο 15 λεπτά περίπου.", + "open_source_h": "Ανοιχτά Δεδομένα", + "open_source": "Ο επεξεργαστής iD είναι ένα συλλογικό έργο ανοιχτού κώδικα και τώρα χρησιμοποιείτε την έκδοση {version}. Ο πηγαίος κώδικας είναι διαθέσιμος [στο GitHub] (https://github.com/openstreetmap/iD).", + "open_source_help": "Μπορείτε να βοηθήσετε την iD με την [μετάφραση] (https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating) ή [αναφορά σφαλμάτων] (https://github.com/openstreetmap/iD/issues )." + }, + "overview": { + "title": "Επισκόπηση", + "navigation_h": "Πλοήγηση", + "navigation_drag": "Μπορείτε να σύρετε το χάρτη πιέζοντας και κρατώντας πατημένο το αριστερό πλήκτρο {leftclick} και μετακινώντας τριγύρω το ποντίκι. Μπορείτε επίσης να χρησιμοποιήσετε τα πλήκτρα βέλους `↓`, `↑`, `←`, `→` στο πληκτρολόγιό σας.", + "navigation_zoom": "Μπορείτε να κάνετε μεγέθυνση ή σμίκρυνση γυρίζοντας τον τροχό του ποντικιού ή με το trackpad ή κάνοντας κλικ στα κουμπιά {συν} / {πλην} κατά μήκος της πλευράς του χάρτη. Μπορείτε επίσης να χρησιμοποιήσετε τα πλήκτρα `+`, `-` στο πληκτρολόγιό σας.", + "features_h": "Χαρακτηριστικά Χάρτη", + "features": "Χρησιμοποιούμε τη λέξη * χαρακτηριστικά * για να περιγράψουμε τα πράγματα που εμφανίζονται στο χάρτη, όπως δρόμοι, κτίρια ή σημεία ενδιαφέροντος. Οτιδήποτε στον πραγματικό κόσμο μπορεί να χαρτογραφηθεί ως χαρακτηριστικό στο OpenStreetMap. Τα χαρτογραφικά χαρακτηριστικά απεικονίζονται στο χάρτη χρησιμοποιώντας *σημεία*, *γραμμές*, ή *περιοχές*.", + "nodes_ways": "Στο OpenStreetmap, τα σημεία ονομάζονται μερικές φορές *κόμβοι*, και οι γραμμές και οι περιοχές καλούνται μερικές φορές *διαδρομές*." + }, + "editing": { + "title": "Επεξεργασία & Αποθήκευση", + "select_h": "Επιλογή", + "select_left_click": "{leftclick} Κάντε αριστερό κλικ σε ένα χαρακτηριστικό για να το επιλέξετε. Αυτό θα το επισημάνει με μια παλλόμενη λάμψη και στην πλαϊνή μπάρα θα εμφανιστούν λεπτομέρειες σχετικά με αυτό το χαρακτηριστικό, όπως το όνομα ή η διεύθυνσή του.", + "select_right_click": "{rightclick} Κάντε δεξί κλικ σε ένα χαρακτηριστικό για να εμφανίσετε το μενού επεξεργασίας, το οποίο εμφανίζει τις διαθέσιμες εντολές, όπως την περιστροφή, τη μετακίνηση και τη διαγραφή.", + "multiselect_h": "Πολυεπιλογή", + "multiselect_shift_click": "`{shift}`+{leftclick} αριστερό κλικ επανηλειμμένα για να επιλέξετε μαζί αρκετά χαρακτηριστικά. Αυτό διευκολύνει την μετακίνηση ή τη διαγραφή πολλών στοιχείων.", + "multiselect_lasso": "Ένας άλλος τρόπος για να επιλέξετε πολλαπλά χαρακτηριστικά είναι να κρατήσετε πατημένο το πλήκτρο `{shift} 'και, στη συνέχεια, πατήστε και κρατήστε πατημένο το αριστερό πλήκτρο του ποντικιού {leftclick} και σύρετε το ποντίκι για να σχεδιάσετε μία κλειστή περιοχή. Όλα τα σημεία μέσα στην κλειστή περιοχή θα επιλεγούν.", + "undo_redo_h": "Αναίρεση και επαναφορά", + "undo_redo": "Οι τροποποιήσεις σας αποθηκεύονται τοπικά στο πρόγραμμα περιήγησής σας, μέχρι να επιλέξετε να τις αποθηκεύσετε στο διακομιστή του OpenStreetMap. Μπορείτε να αναιρέσετε τις επεξεργασίες κάνοντας κλικ στο κουμπί {undo} **Αναίρεση** και επαναλάβετε τις αλλαγές κάνοντας κλικ στο κουμπί {redo} **Επανάλειψη**.", + "save_h": "Αποθήκευση", + "save": "Κάντε κλικ στην {save} **Αποθήκευση** για να ολοκληρώσετε τις επεξεργασίες σας και να τις στείλετε στο OpenStreetMap. Θα πρέπει να θυμάστε να αποθηκεύετε συχνά την εργασία σας!", + "save_validation": "Στην οθόνη αποθήκευσης, θα έχετε την ευκαιρία να ελέγξετε τι έχετε κάνει. Το iD θα εκτελέσει επίσης μερικούς βασικούς ελέγχους για δεδομένα που λείπουν και μπορεί να δώσει χρήσιμες προτάσεις και προειδοποιήσεις εάν κάτι δεν φαίνεται σωστό.", + "upload_h": "Μεταφόρτωση", + "upload": "Πριν μεταφορτώσετε τις αλλαγές σας, πρέπει να εισαγάγετε ένα σχόλιο [changeset comment] (https://wiki.openstreetmap.org/wiki/Good_changeset_comments). Στη συνέχεια, κάντε κλικ στο **Ανέβασμα** για να στείλετε τις αλλαγές σας στο OpenStreetMap, όπου θα συγχωνευθούν στον χάρτη και θα είναι ορατές σε όλους.", + "backups_h": "Αυτόματα Αντίγραφα Ασφαλείας", + "backups": "Εάν δεν μπορείτε να ολοκληρώσετε τις αλλαγές σας σε μια συνεδρία, για παράδειγμα εάν ο υπολογιστής σας καταρρεύσει ή κλείσετε την καρτέλα του προγράμματος περιήγησης, οι τροποποιήσεις σας εξακολουθούν να είναι αποθηκευμένες στο χώρο αποθήκευσης του προγράμματος περιήγησης. Μπορείτε να επιστρέψετε αργότερα (στον ίδιο υπολογιστή και πρόγραμμα περιήγησης) και το iD θα σας προτείνει να επαναφέρετε την εργασία σας.", + "keyboard_h": "Συντομεύσεις Πληκτρολογίου", + "keyboard": "Μπορείτε να δείτε την λίστα συντομεύσεων πληκτρολογίου πατώντας το πλήκτρο `?`." + }, + "feature_editor": { + "title": "Επεξεργαστής Χαρακτηριστικών", + "intro": "Ο *επεξεργαστής χαρακτηριστικών* εμφανίζεται δίπλα στο χάρτη και σας επιτρέπει να δείτε και να επεξεργαστείτε όλες τις πληροφορίες για το επιλεγμένο χαρακτηριστικό.", + "definitions": "Στην επάνω ενότητα εμφανίζεται ο τύπος των χαρακτηριστικών. Η μεσαία ενότητα περιέχει *πεδία* που εμφανίζουν τις ιδιότητες των χαρακτηριστικών, όπως το όνομα ή τη διεύθυνση.", + "type_h": "Είδος Χαρακτηριστικών", + "type": "Μπορείτε να κάνετε κλικ στον τύπο του χαρακτηριστικού για να αλλάξετε το χαρακτηριστικό σε ένα διαφορετικό τύπο. Ό, τι υπάρχει στον πραγματικό κόσμο μπορεί να προστεθεί στο OpenStreetMap, έτσι υπάρχουν χιλιάδες τύποι χαρακτηριστικών για να διαλέξετε.", + "fields_h": "Πεδία", + "fields_all_fields": "Η ενότητα \"Όλα τα πεδία\" περιέχει όλες τις λεπτομέρειες των χαρακτηριστικών που μπορείτε να επεξεργαστείτε. Στο OpenStreetMap, όλα τα πεδία είναι προαιρετικά και είναι εντάξει να αφήσετε ένα πεδίο κενό αν δεν είστε σίγουροι.", + "fields_example": "Κάθε τύπος χαρακτηριστικού θα εμφανίζει διαφορετικά πεδία. Για παράδειγμα, ένας δρόμος μπορεί να εμφανίζει πεδία για την επιφανεία και το όριο ταχύτητας, αλλά ένα εστιατόριο μπορεί να εμφανίζει πεδία για τον τύπο της τροφής που σερβίρει και τις ώρες που είναι ανοιχτά.", + "fields_add_field": "Μπορείτε επίσης να κάνετε κλικ στο αναπτυσσόμενο μενού \"Προσθήκη πεδίου\" για να προσθέσετε περισσότερα πεδία, όπως μια περιγραφή, έναν σύνδεσμο Wikipedia, πρόσβαση σε αναπηρική καρέκλα και πολλά άλλα.", + "tags_h": "Ετικέτες", + "tags_all_tags": "Κάτω από την ενότητα πεδίων, μπορείτε να αναπτύξετε την ενότητα \"Όλες οι ετικέτες\" για να επεξεργαστείτε οποιαδήποτε από τις *ετικέτες* του OpenStreetMap για το επιλεγμένο χαρακτηριστικό. Κάθε ετικέτα αποτελείται από στοιχεία δεδομένων με ένα *κλειδί* και μία *τιμή*, που καθορίζουν όλα τα χαρακτηριστικά που είναι αποθηκευμένα στο OpenStreetMap.", + "tags_resources": "Η επεξεργασία των ετικετών ενός στοιχείου απαιτεί ενδιάμεση γνώση σχετικά με το OpenStreetMap. Θα πρέπει να συμβουλευτείτε βοηθήματα όπως το [OpenStreetMap Wiki] (https://wiki.openstreetmap.org/wiki/Main_Page) ή το [Taginfo] (https://taginfo.openstreetmap.org/) για να μάθετε περισσότερα σχετικά με τις αποδεκτές πρακτικές προσθήκης ετικετών στο OpenStreetMap." + }, + "points": { + "title": "Σημεία", + "intro": "Τα *Σημεία* μπορούν να χρησιμοποιηθούν για να απεικονίσουν χαρακτηριστικά όπως καταστήματα, εστιατόρια και μνημεία. Σηματοδοτούν μια συγκεκριμένη τοποθεσία και περιγράφουν τι υπάρχει εκεί.", + "add_point_h": "Προσθέτοντας Σημεία", + "add_point": "Για να προσθέσετε ένα σημείο, κάντε κλικ στο κουμπί {σημείο} **Σημείο** στη γραμμή εργαλείων πάνω από το χάρτη ή πατήστε το πλήκτρο συντόμευσης `1`. Αυτό θα αλλάξει τον κέρσορα του ποντικιού στο σύμβολο ενός σταυρού.", + "add_point_finish": "Για να τοποθετήσετε το νέο σημείο στο χάρτη, τοποθετήστε το δρομέα του ποντικιού εκεί όπου πρέπει να μπει το σημείο, μετά κάντε κλικ στο αριστερό πλήκτρο {leftclick} ή πατήστε το \"Space\".", + "move_point_h": "Μετακινώντας Σημεία", + "move_point": "Για να μετακινήσετε ένα σημείο, τοποθετήστε το δείκτη του ποντικιού πάνω από το σημείο και, στη συνέχεια, πατήστε και κρατήστε πατημένο το αριστερό πλήκτρο του ποντικιού {leftclick} ενώ σύρετε το σημείο στη νέα του θέση.", + "delete_point_h": "Διαγράφοντας Σημεία", + "delete_point": "Είναι εντάξει να διαγράψετε χαρακτηριστικά που δεν υπάρχουν στον πραγματικό κόσμο. Η διαγραφή ενός χαρακτηριστικού από το OpenStreetMap την αφαιρεί από το χάρτη που χρησιμοποιεί ο καθένας, οπότε θα πρέπει να βεβαιωθείτε ότι το χαρακτηριστικό πραγματικά δεν υπάρχει πριν το διαγράψετε.", + "delete_point_command": "Για να διαγράψετε ένα σημείο, κάντε {rightclick} δεξί κλικ στο σημείο για να το επιλέξετε και για να εμφανίσετε το μενού επεξεργασίας, στη συνέχεια χρησιμοποιήστε την εντολή {διαγραφή} **Διαγραφή**." + }, + "lines": { + "title": "Γραμμές", + "add_line_h": "Προσθέτοντας Γραμμές", + "add_line": "Για να προσθέσετε μια γραμμή, κάντε κλικ στο κουμπί {γραμμή} **Γραμμή** στη γραμμή εργαλείων πάνω από το χάρτη ή πατήστε το πλήκτρο συντόμευσης `2`. Αυτό θα αλλάξει τον κέρσορα του ποντικιού σε ένα σταυρό.", + "add_line_draw": "Στη συνέχεια, τοποθετήστε το δρομέα του ποντικιού εκεί όπου πρέπει να ξεκινήσει η γραμμή και πατήστε αριστερό κλικ {leftclick} ή πατήστε 'Space' για να ξεκινήσετε την τοποθέτηση κόμβων κατά μήκος της γραμμής. Συνεχίστε να τοποθετείτε περισσότερους κόμβους κάνοντας κλικ ή πατώντας `Space`. Ενώ σχεδιάζετε, μπορείτε να κάνετε μεγέθυνση ή να σύρετε το χάρτη για να προσθέσετε περισσότερες λεπτομέρειες.", + "add_line_finish": "Για να ολοκληρώσετε μια γραμμή, πατήστε το πλήκτρο `{return} 'ή κάντε ξανά κλικ στον τελευταίο κόμβο.", + "modify_line_h": "Τροποποιώντας Γραμμές", + "modify_line_dragnode": "Συχνά θα δείτε γραμμές που δεν έχουν διαμορφωθεί σωστά, για παράδειγμα έναν δρόμο που δεν ταιριάζει με την εικόνα του φόντου. Για να προσαρμόσετε το σχήμα μιας γραμμής, πατήστε πρώτα το αριστερό κλικ {leftclick} για να το επιλέξετε. Όλοι οι κόμβοι της γραμμής θα σχεδιαστούν ως μικροί κύκλοι. Στη συνέχεια, μπορείτε να σύρετε τους κόμβους σε καλύτερες θέσεις.", + "modify_line_addnode": "Μπορείτε επίσης να δημιουργήσετε νέους κόμβους κατά μήκος μιας γραμμής είτε με {leftclick}**x2** διπλό κλικ στη γραμμή ή σύροντας τα μικρά τρίγωνα στα μεσαία σημεία μεταξύ των κόμβων.", + "connect_line_h": "Σύνδεση Γραμμών", + "connect_line": "Η σωστή σύνδεση των δρόμων είναι σημαντική για τον χάρτη και απαραίτητη για την παροχή οδηγικών διευθύνσεων.", + "connect_line_display": "Οι συνδέσεις μεταξύ δρόμων σχεδιάζονται με γκρι κύκλους. Τα τελικά σημεία μιας γραμμής σχεδιάζονται με μεγαλύτερους λευκούς κύκλους, αν δεν συνδέονται σε τίποτα.", + "connect_line_drag": "Για να συνδέσετε μια γραμμή σε ένα άλλο χαρακτηριστικό, σύρετε έναν από τους κόμβους της γραμμής στο άλλο χαρακτηριστικό μέχρι και τα δύο χαρακτηριστικά να κλειδώσουν μαζί. Συμβουλή: Μπορείτε να κρατήσετε πατημένο το πλήκτρο `{alt}` για να αποτρέψετε τη σύνδεση των κόμβων με άλλα χαρακτηριστικά.", + "connect_line_tag": "Εάν γνωρίζετε ότι η σύνδεση διαθέτει φανάρια ή διαβάσεις, μπορείτε να τα προσθέσετε επιλέγοντας τον κόμβο σύνδεσης και χρησιμοποιώντας τον επεξεργαστή χαρακτηριστικών για να επιλέξετε τον σωστό τύπο του στοιχείου.", + "disconnect_line_h": "Αποσύνδεση Γραμμών", + "disconnect_line_command": "Για να αποσυνδέσετε έναν δρόμο από ένα άλλο χαρακτηριστικό, πατήστε δεξί κλικ {rightclick} στον κόμβο σύνδεσης και επιλέξτε την εντολή {αποσύνδεση} **Αποσύνδεση** από το μενού επεξεργασίας.", + "move_line_h": "Μετακινώντας Γραμμές", + "move_line_command": "Για να μετακινήσετε μια ολόκληρη γραμμή, πατήστε δεξί κλικ {rightclick} στη γραμμή και επιλέξτε την εντολή {μετακίνηση} **Μετακίνηση** από το μενού επεξεργασίας. Στη συνέχεια, μετακινήστε το ποντίκι και πατήστε αριστερό κλικ {leftclick} για να τοποθετήσετε τη γραμμή σε μια νέα θέση.", + "move_line_connected": "Οι γραμμές που είναι συνδεδεμένες με άλλα χαρακτηριστικά θα παραμείνουν συνδεδεμένες καθώς μετακινείτε τη γραμμή σε μια νέα θέση. Το iD ενδέχεται να σας εμποδίσει να μετακινήσετε μια γραμμή σε μια άλλη συνδεδεμένη γραμμή.", + "delete_line_h": "Διαγράφοντας Γραμμές", + "delete_line": "Εάν μια γραμμή είναι εντελώς εσφαλμένη, για παράδειγμα ένας δρόμος που δεν υπάρχει στον πραγματικό κόσμο, είναι εντάξει να τον διαγράψετε. Προσέξτε όταν διαγράφετε χαρακτηριστικά: οι εικόνες φόντου που χρησιμοποιείτε ενδέχεται να είναι αναχρονιστική και ένας δρόμος που φαίνεται λάθος μπορεί απλώς να έχει κατασκευαστεί πρόσφατα.", + "delete_line_command": "Για να διαγράψετε μια γραμμή, κάντε δεξί κλικ {rightclick} στη γραμμή για να την επιλέξετε και για να εμφανιστεί το μενού επεξεργασίας, στη συνέχεια χρησιμοποιήστε την εντολή {διαγραφή} **Διαγραφή**." + }, + "areas": { + "title": "Περιοχές", + "intro": "Οι *Περιοχές* χρησιμοποιούνται για να δείξουν τα όρια των χαρακτηριστικών όπως οι λίμνες, τα κτίρια και οι κατοικημένες περιοχές. Οι περιοχές πρέπει να σχεδιάζονται στην άκρη του χαρακτηριστικού που αντιπροσωπεύουν, για παράδειγμα, γύρω από τη βάση ενός κτιρίου.", + "point_or_area_h": "Σημεία ή περιοχές;", + "point_or_area": "Πολλά χαρακτηριστικά μπορούν να απεικονίζονται ως σημεία ή περιοχές. Θα πρέπει να χαρτογραφείτε τα κτίρια και τα περιγράμματα μιας ιδιοκτησίας ως περιοχές όπου είναι δυνατόν. Τοποθετήστε σημεία εντός του χώρου του κτιρίου για να απεικονίσουν τις επιχειρήσεις, τις υποδομές και άλλα χαρακτηριστικά που βρίσκονται μέσα στο κτίριο.", + "add_area_h": "Προσθέτοντας Περιοχές", + "add_area_command": "Για να προσθέσετε μια περιοχή, κάντε κλικ στο κουμπί {περιοχή} **Περιοχή** στη γραμμή εργαλείων πάνω από το χάρτη ή πατήστε το πλήκτρο συντόμευσης `3`. Αυτό θα αλλάξει τον κέρσορα του ποντικιού σε ένα σταυρό.", + "add_area_draw": "Στη συνέχεια, τοποθετήστε το δρομέα του ποντικιού σε μια από τις γωνίες της δυνατότητας και το πατήστε αριστερό κλικ {leftclick} ή πατήστε το πλήκτρο Space για να ξεκινήσετε την τοποθέτηση κόμβων γύρω από την περίμετρο της περιοχής. Συνεχίστε να τοποθετείτε περισσότερους κόμβους κάνοντας κλικ ή πατώντας `Space`. Ενώ σχεδιάζετε, μπορείτε να κάνετε μεγέθυνση ή να σύρετε το χάρτη για να προσθέσετε περισσότερες λεπτομέρειες.", + "add_area_finish": "Για να ολοκληρώσετε μια περιοχή, πατήστε το πλήκτρο `{return}' ή κάντε ξανά κλικ στον πρώτο ή τον τελευταίο κόμβο.", + "square_area_h": "Τετράγωνες γωνίες", + "square_area_command": "Πολλά χαρακτηριστικά περιοχής, όπως τα κτίρια, έχουν τετράγωνες γωνίες. Για να τετραγωνίσετε τις γωνίες μιας περιοχής, κάντε δεξί κλικ {rightclick} στην άκρη της περιοχής και επιλέξτε την εντολή {ορθογωνισμός} **Τετράγωνο** από το μενού επεξεργασίας.", + "modify_area_h": "Τροποποιώντας Περιοχές", + "modify_area_dragnode": "Συχνά θα δείτε περιοχές που δεν έχουν σωστό σχήμα, για παράδειγμα ένα κτίριο που δεν ταιριάζει με την εικόνα του φόντου. Για να προσαρμόσετε το σχήμα μιας περιοχής, πατήστε το αριστερό πλήκτρο {leftclick} για να το επιλέξετε. Όλοι οι κόμβοι της περιοχής θα σχεδιαστούν ως μικροί κύκλοι. Στη συνέχεια, μπορείτε να σύρετε τους κόμβους σε καλύτερες θέσεις.", + "modify_area_addnode": "Μπορείτε επίσης να δημιουργήσετε νέους κόμβους σε μια περιοχή είτε με {leftclick} **x2** διπλό κλικ στην άκρη της περιοχής είτε σύροντας τα μικρά τρίγωνα στα μεσαία σημεία μεταξύ των κόμβων.", + "delete_area_h": "Διαγράφοντας Περιοχές", + "delete_area": "Αν μια περιοχή είναι εντελώς εσφαλμένη, για παράδειγμα ένα κτίριο που δεν υπάρχει στον πραγματικό κόσμο, είναι εντάξει να το διαγράψετε. Να είστε προσεκτικοί κατά τη διαγραφή χαρακτηριστικών - οι εικόνες φόντου που χρησιμοποιείτε ενδέχεται να είναι αναχρονιστικές και ένα κτίριο που φαίνεται λάθος μπορεί απλώς να είναι νεόδμητο.", + "delete_area_command": "Για να διαγράψετε μια περιοχή, πατήστε {rightclick} δεξί κλικ στην περιοχή για να την επιλέξετε και για να εμφανίσετε το μενού επεξεργασίας, στη συνέχεια χρησιμοποιήστε την εντολή {διαγραφή} **Διαγραφή**." + }, + "relations": { + "title": "Σχέσεις", + "intro": "Η *σχέση* είναι ένας ειδικός τύπος χαρακτηριστικού στο OpenStreetMap που ομαδοποιεί άλλα χαρακτηριστικά. Τα χαρακτηριστικά που ανήκουν σε μια σχέση ονομάζονται *μέλη*, και κάθε μέλος μπορεί να έχει ένα *ρόλο* στη σχέση.", + "edit_relation_h": "Επεξεργασία Σχέσεων", + "edit_relation": "Στοη βάση του επεξεργαστή χαρακτηριστικών, μπορείτε να επεκτείνετε την ενότητα \"Όλες οι σχέσεις\" για να δείτε αν το επιλεγμένο χαρακτηριστικό είναι μέλος σε οποιωνδήποτε σχέσεων. Στη συνέχεια, μπορείτε να κάνετε κλικ στη σχέση για να την επιλέξετε και να την επεξεργαστείτε.", + "edit_relation_add": "Για να προσθέσετε ένα χαρακτηριστικό σε μια σχέση, επιλέξτε το χαρακτηριστικό, και στη συνέχεια, κάντε κλικ στο κουμπί {συν} προσθήκη στο τμήμα \"Όλες οι σχέσεις\" του επεξεργαστή χαρακτηριστικών. Μπορείτε να επιλέξετε από μια λίστα με κοντινές σχέσεις ή να επιλέξετε την επιλογή \"Νέα σχέση ...\".", + "edit_relation_delete": "Μπορείτε επίσης να κάνετε κλικ στο κουμπί {διαγραφή} **Διαγραφή** για να καταργήσετε το επιλεγμένο χαρακτηριστικό από τη σχέση. Αν αφαιρέσετε όλα τα μέλη από μια σχέση, η σχέση θα διαγραφεί αυτόματα.", + "maintain_relation_h": "Διατήρηση Σχέσεων", + "maintain_relation": "Ως επί το πλείστον, το iD θα διατηρεί αυτόματα τις σχέσεις καθώς τις επεξεργάζεστε. Θα πρέπει να προσέχετε όταν αντικαθιστάτε χαρακτηριστικά που μπορεί να είναι μέλη των σχέσεων. Για παράδειγμα, αν διαγράψετε ένα τμήμα δρόμου και σχεδιάσετε ένα νέο τμήμα δρόμου για να το αντικαταστήσετε, θα πρέπει να προσθέσετε το νέο τμήμα στις ίδιες σχέσεις (διαδρομές, περιορισμούς στροφής κ.λπ.) όπως το πρωτότυπο.", + "relation_types_h": "Τύποι Σχέσεων", + "turn_restriction_h": "Περιορισμοί Στροφών", + "turn_restriction_field": "Για να επεξεργαστείτε τους περιορισμούς στροφής, επιλέξτε έναν κόμβο διασταύρωσης όπου συναντώνται δύο ή περισσότεροι δρόμοι. Ο επεξεργαστής χαρακτηριστικών θα εμφανίσει ένα ειδικό πεδίο \"Περιορισμοί Στροφής\" που περιέχει ένα μοντέλο της διασταύρωσης.", + "route_h": "Δρομολόγια", + "route": "Η σχέση *διαδρομής* είναι μια ομάδα από μία ή περισσότερες γραμμές που μαζί σχηματίζουν ένα δίκτυο διαδρομών, όπως μια διαδρομή λεωφορείου, μια διαδρομή τρένου ή μια οδική διαδρομή.", + "route_add": "Για να προσθέσετε ένα χαρακτηριστικό σε μια σχέση διαδρομής, επιλέξτε το χαρακτηριστικό και μετακινηθείτε προς τα κάτω στην ενότητα \"Όλες οι σχέσεις\" του επεξεργαστή χαρακτηριστικών και, στη συνέχεια, κάντε κλικ στο κουμπί {συν} προσθήκη για να προσθέσετε αυτό το χαρακτηριστικό σε μια υπάρχουσα σχέση ή σε μια νέα σχέση.", + "boundary_h": "Όρια", + "boundary": "Η σχέση *όριο* είναι μια ομάδα ενός ή περισσοτέρων χαρακτηριστικών γραμμής που μαζί σχηματίζουν ένα διοικητικό όριο.", + "boundary_add": "Για να προσθέσετε ένα χαρακτηριστικό σε μια σχέση ορίων, επιλέξτε το χαρακτηριστικό και μετακινηθείτε προς τα κάτω στην ενότητα \"Όλες οι σχέσεις\" του επεξεργαστή χαρακτηριστικών, και στη συνέχεια κάντε κλικ στο κουμπί προσθήκης {συν} για να προσθέσετε αυτό το χαρακτηριστικό σε μια υπάρχουσα σχέση ή σε μια νέα σχέση." + }, + "imagery": { + "title": "Εικόνα Φόντου", + "intro": "Οι εικόνες φόντου που εμφανίζονται κάτω από τα δεδομένα χαρτών αποτελούν σημαντική πηγή για τη χαρτογράφηση. Αυτή η εικόνα μπορεί να είναι αεροφωτογραφίες που συλλέγονται από δορυφόρους, αεροπλάνα και drones, ή μπορούν να σαρωθούν ιστορικοί χάρτες ή άλλες ελεύθερες διαθέσιμες πηγές δεδομένων.", + "sources_h": "Πηγές Εικόνων", + "choosing": "Για να δείτε ποιες πηγές εικόνων είναι διαθέσιμες για επεξεργασία, κάντε κλικ στο κουμπί {επίπεδα} **Ρυθμίσεις φόντου** στο πλάι του χάρτη.", + "sources": "Από προεπιλογή, το δορυφορικό επίπεδο [Bing Maps] (https://www.bing.com/maps/) επιλέγεται ως εικόνα φόντου. Ανάλογα με το πού επεξεργάζεστε, θα είναι διαθέσιμες και άλλες πηγές εικόνων. Κάποιοι μπορεί να είναι νεότεροι ή να έχουν υψηλότερη ανάλυση, οπότε είναι πάντα χρήσιμο να ελέγχετε και να δείτε ποιο επίπεδο είναι το καλύτερο που θα χρησιμοποιήσετε ως αναφορά χαρτογράφησης.", + "offsets_h": "Ρύθμιση Μετατόπισης Εικόνων", + "offset": "Οι εικόνες είναι μερικές φορές ελαφρώς μετατοπισμένες από τα ακριβή δεδομένα χάρτη. Αν δείτε πολλούς δρόμους ή κτίρια που μετατοπίζονται από τις εικόνες φόντου, μπορεί να είναι οι εικόνες λανθασμένες, οπότε μην μετακινήσετε τα δεδομένα για να ταιριάζουν με το φόντο. Αντίθετα, μπορείτε να προσαρμόσετε το φόντο έτσι ώστε να ταιριάζει με τα υπάρχοντα δεδομένα, επεκτείνοντας την ενότητα \"Ρύθμιση Μετατόπισης Εικόνων\" στο κάτω μέρος του παραθύρου \"Ρυθμίσεις Φόντου\".", + "offset_change": "Κάντε κλικ στα μικρά τρίγωνα για να προσαρμόσετε την μετατόπιση της εικόνας με μικρά βήματα ή κρατήστε πατημένο το αριστερό πλήκτρο του ποντικιού και σύρετέ το μέσα στο γκρι τετράγωνο για να γλυστρίσει την εικόνα σε ευθυγράμμιση." + }, + "streetlevel": { + "title": "Φωτογραφίες Επιπέδου Δρόμου", + "intro": "Οι φωτογραφίες στο επίπεδο του δρόμου είναι χρήσιμες για τη χαρτογράφηση φαανριών, επιχειρήσεων και άλλων λεπτομερειών που δεν μπορείτε να δείτε από δορυφορικές εικόνες και αεροφωτογραφίες. Ο επεξεργαστής iD υποστηρίζει φωτογραφίες στο επίπεδο του δρόμου από το [Mapillary] (https://www.mapillary.com) και το [OpenStreetCam] (https://www.openstreetcam.org).", + "using_h": "Χρήση Φωτογραφιών Επιπέδου Δρόμου", + "using": "Για να χρησιμοποιήσετε τις φωτογραφίες στο επίπεδο του δρόμου για χαρτογράφηση, κάντε κλικ στον πίνακα {δεδομένα} **Δεδομένα χάρτη** στο πλάι του χάρτη για να ενεργοποιήσετε ή να απενεργοποιήσετε τα διαθέσιμα επίπεδα φωτογραφιών.", + "photos": "Όταν είναι ενεργοποιημένο, το επίπεδο φωτογραφιών εμφανίζει μια γραμμή κατά μήκος της ακολουθίας φωτογραφιών. Σε υψηλότερα επίπεδα μεγέθυνσης, ένας κύκλος σημειώνει την κάθε θέση φωτογραφίας και σε ακόμη υψηλότερα επίπεδα μεγέθυνσης ένας κώνος δείχνει την κατεύθυνση στην οποία βρισκόταν η φωτογραφική μηχανή κατά τη λήψη της φωτογραφίας.", + "viewer": "Όταν κάνετε κλικ σε μία από τις θέσεις φωτογραφιών, στην κάτω γωνία του χάρτη εμφανίζονται οι φωτογραφίες. Η προβολή των φωτογραφιών περιέχουν τον ελέγχο για κίνηση προς τα εμπρός και προς τα πίσω στην ακολουθία εικόνων. Εμφανίζει επίσης το όνομα χρήστη του ατόμου που τράβηξε την εικόνα, την ημερομηνία λήψης και έναν σύνδεσμο για την προβολή της εικόνας στον αρχικό ιστότοπο." + }, + "gps": { + "title": "Ίχνη GPS", + "intro": "Τα συγκεντρωμένα ίχνη GPS αποτελούν πολύτιμη πηγή δεδομένων για το OpenStreetMap. Αυτός ο επεξεργαστής υποστηρίζει αρχεία *.gpx*, *.geojson* και *.kml* στον υπολογιστή σας. Μπορείτε να συλλέξετε ίχνη GPS με ένα smartphone, ένα smartphone ή άλλη συσκευή GPS.", + "survey": "Για πληροφορίες σχετικά με το πως να εκτελέσετε χαρτογράφηση με GPS, διαβάστε [Χαρτογράφηση με smartphone, GPS ή χαρτί] (http://learnosm.org/en/mobile-mapping/).", + "using_h": "Χρήση Ιχνών GPS", + "using": "Για να χρησιμοποιήσετε ένα ίχνος GPS για χαρτογράφηση, μεταφέρετε και αποθέστε το αρχείο δεδομένων στον επεξεργαστή χαρτών. Εάν αναγνωριστεί, θα σχεδιαστεί στο χάρτη ως μια φωτεινή μοβ γραμμή. Κάντε κλικ στον πίνακα {δεδομένα} **Δεδομένα Χάρτη** στο πλάι του χάρτη για να ενεργοποιήσετε, να απενεργοποιήσετε ή να κάνετε μεγέθυνση στα δεδομένα σας GPS.", + "tracing": "Το ίχνος GPS δεν αποστέλλεται στο OpenStreetMap - ο καλύτερος τρόπος για να το χρησιμοποιήσετε είναι να σχεδιάσετε στον χάρτη, χρησιμοποιώντας το ως οδηγό για τα νέα χαρακτηριστικά που προσθέτετε.", + "upload": "Μπορείτε επίσης να [μεταφορτώσετε τα δεδομένα σας GPS στο OpenStreetMap] (https://www.openstreetmap.org/trace/create) για χρήση από άλλους χρήστες." + }, + "field": { + "restrictions": { + "title": "Βοήθεια Περιορισμού Στροφών", + "about": { + "title": "Σχετικά", + "about": "Αυτό το πεδίο σας επιτρέπει να επιθεωρήσετε και να τροποποιήσετε τους περιορισμούς στροφής. Εμφανίζει ένα μοντέλο της επιλεγμένης διασταύρωσης, συμπεριλαμβανομένων άλλων κοντινών συνδεδεμένων δρόμων.", + "maxdist": "Το ρυθμιστικό \"{distField}\" ελέγχει πόσο μακριά πρέπει να αναζητήσετε πρόσθετους συνδεδεμένους δρόμους." + }, + "inspecting": { + "title": "Επιθεώρηση", + "restricted": "\"Περιορισμένη\" σημαίνει ότι υπάρχει περιορισμός στροφής, για παράδειγμα \"Όχι Αριστερή Στροφή\".", + "only": "\"Μόνο\" σημαίνει ότι ένα όχημα που ακολουθεί αυτή τη διαδρομή μπορεί να κάνει μόνο αυτή την επιλογή, για παράδειγμα \"Μόνο ευθεία\"." + }, + "modifying": { + "title": "Τροποποίηση", + "indicators": "Στη συνέχεια, κάντε κλικ σε ένα σύμβολο στροφής για να το αλλάξετε μεταξύ του \"Επιτρέπεται\", του \"Περιορισμένο\" και \"Μόνο\"." + }, + "tips": { + "title": "Συμβουλές", + "simple": "**Προτιμήστε απλούς περιορισμούς περισσότερο από σύνθετους.**" + } + } + } }, "intro": { + "done": "έτοιμο", + "ok": "ΟΚ", "graph": { "block_number": "", + "city": "Τρία Ποτάμια", "county": "", "district": "", "hamlet": "", @@ -557,43 +873,246 @@ "state": "", "subdistrict": "", "suburb": "", - "countrycode": "gr" + "countrycode": "gr", + "name": { + "1st-avenue": "1η Λεωφόρος", + "2nd-avenue": "2η Λεωφόρος", + "4th-avenue": "4η Λεωφόρος", + "5th-avenue": "5η Λεωφόρος", + "6th-avenue": "6η Λεωφόρος", + "6th-street": "6η Οδός", + "7th-avenue": "7η Λεωφόρος", + "8th-avenue": "8η Λεωφόρος", + "9th-avenue": "9η Λεωφόρος", + "10th-avenue": "10η Λεωφόρος", + "11th-avenue": "11η Λεωφόρος", + "12th-avenue": "12η Λεωφόρος", + "adams-street": "Οδός Adams", + "andrews-elementary-school": "Δημοτικό Σχολείο Andrews", + "andrews-street": "Οδός Andrews", + "armitage-street": "Οδός Armitage", + "barrows-school": "Σχολείο Barrows", + "battle-street": "Οδός Battle", + "bennett-street": "Οδός Bennett", + "bowman-park": "Πάρκο Bowman", + "constantine-street": "Οδός Constantine", + "cushman-street": "Οδός Cushman", + "douglas-avenue": "Λεωφόρος Douglas", + "east-street": "Ανατολική Οδός", + "elm-street": "Οδός Elm", + "flower-street": "Οδός Flower", + "foster-street": "Οδός Foster", + "french-street": "Οδός French", + "garden-street": "Οδός Garden", + "gem-pawnbroker": "Ενεχυροδανειστήριο πολύτιμων λίθων", + "hoffman-street": "Οδός Hoffman", + "hook-avenue": "Λεωφόρος Hook", + "jefferson-street": "Οδός Jefferson", + "kelsey-street": "Οδός Kelsey", + "lafayette-park": "Πάρκο LaFayette", + "lincoln-avenue": "Λεωφόρος Lincoln", + "lowrys-books": "Βιβλιοπωλείο του Lowry", + "lynns-garage": "Συνεργείο του Lynn", + "main-street-barbell": "Κεντρική Οδός Barbell", + "main-street-cafe": "Καφέ Κεντρικής Οδού", + "main-street": "Κεντρική Οδός", + "marina-park": "Πάρκο μαρίνας", + "michigan-avenue": "Λεωφόρος Michigan", + "south-street": "Νότια Οδός" + } + }, + "welcome": { + "title": "Καλωσήρθατε", + "welcome": "Καλωσήρθατε! Αυτή η καθοδήγηση θα σας διδάξει τα βασικά της επεξεργασίας στο OpenStreetMap.", + "practice": "Όλα τα δεδομένα σε αυτή την καθοδήγηση είναι μόνο για εξάσκηση, και οποιεσδήποτε επεξεργασίες κάνετε κατά την εκμάθηση δεν θα αποθηκευτεί.", + "words": "Αυτή η καθοδήγηση θα παρουσιάσει μερικές νέες λέξεις και έννοιες. Όταν παρουσιάζουμε μια νέα λέξη, θα χρησιμοποιήσουμε την *πλάγια γραφή*.", + "mouse": "Μπορείτε να χρησιμοποιήσετε οποιαδήποτε συσκευή καταχώρησης για να επεξεργαστείτε το χάρτη, αλλά αυτή η καθοδήγηση υποθέτει ότι έχετε ένα ποντίκι με αριστερό και δεξί κουμπί. **Εάν θέλετε να συνδέσετε ένα ποντίκι, κάντε το τώρα και κάντε κλικ στο OK.**", + "leftclick": "Όταν αυτό τις οδηγίες σας ζητάμε να κάνετε κλικ ή διπλό κλικ, εννοούμε με το αριστερό κουμπί. Σε ένα trackpad μπορεί να είναι μια απλή κίνηση με ένα κλικ ή με ένα χτύπημα δαχτύλου. **Πατήστε αριστερό κλικ {num} φορές.**", + "rightclick": "Μερικές φορές επίσης θα σας ζητήσουμε να πατήσετε δεξί κλικ. Αυτό μπορεί να είναι το ίδιο με το κλικ ελέγχου ή το πάτημα δύο δακτύλων σε ένα trackpad. Το πληκτρολόγιό σας μπορεί ακόμα να έχει και ένα πλήκτρο 'μενού' που λειτουργεί όπως το δεξί κλικ. **Πατήστε δεξί κλικ στο {num} φορές.**", + "chapters": "Μέχρι εδώ καλά! Μπορείτε να χρησιμοποιήσετε τα παρακάτω κουμπιά για να παρακάμψετε κεφάλαια ανά πάσα στιγμή ή για να επανεκκινήσετε ένα κεφάλαιο εάν κολλήσετε. Ας ξεκινήσουμε! **Κάντε κλικ στο '{next}' για να συνεχίσετε.**" }, "navigation": { - "title": "Πλοήγηση" + "title": "Πλοήγηση", + "drag": "Η κύρια περιοχή του χάρτη εμφανίζει τα δεδομένα του OpenStreetMap μπροστά από το φόντο. {Br} Μπορείτε να σύρετε το χάρτη πιέζοντας και κρατώντας πατημένο το αριστερό πλήκτρο του ποντικιού ενώ μετακινείτε το ποντίκι. Μπορείτε επίσης να χρησιμοποιήσετε τα πλήκτρα βέλους στο πληκτρολόγιό σας. ** Σύρετε τον χάρτη! **", + "zoom": "Μπορείτε να κάνετε μεγέθυνση ή σμίκρυνση με γύρισμα του τροχού του ποντικιού ή το trackpad ή κάνοντας κλικ στα κουμπιά {συν} / {πλην}. **Εστίαση του χάρτη**", + "features": "Χρησιμοποιούμε τη λέξη *χαρακτηριστικά* για να περιγράψουμε τα πράγματα που εμφανίζονται στο χάρτη. Οτιδήποτε στον πραγματικό κόσμο μπορεί να χαρτογραφηθεί ως χαρακτηριστικό στο OpenStreetMap.", + "points_lines_areas": "Τα χαρτογραφικά χαρακτηριστικά αντιπροσωπεύονται χρησιμοποιώντας *σημεία, γραμμές ή περιοχές.", + "nodes_ways": "Στο OpenStreetMap, τα σημεία ονομάζονται μερικές φορές *κόμβοι*, και οι γραμμές και οι περιοχές καλούνται μερικές φορές *διαδρομές*.", + "click_townhall": "Όλες τα χαρακτηριστικά του χάρτη μπορούν να επιλεγούν κάνοντας κλικ πάνω τους. **Κάντε κλικ στο σημείο για να το επιλέξετε.**", + "editor_townhall": "Όταν ένα χαρακτηριστικό είναι επιλεγμένο, εμφανίζεται παράλληλα με τον χάρτη ο *επεξεργαστής χαρακτηριστικών*.", + "preset_townhall": "Στο επάνω μέρος του επεξεργαστή χαρακτηριστικών εμφανίζεται το είδος των χαρακτηριστικών. Αυτό το σημείο είναι ένα {preset}.", + "fields_townhall": "Το μεσαίο τμήμα του επεξεργαστή χαρακτηριστικών περιέχει *πεδία* που εμφανίζουν τις ιδιότητες του χαρακτηριστικού, όπως το όνομα και τη διεύθυνσή του.", + "close_townhall": "** Κλείστε τον επεξεργαστή χαρακτηριστικών πατώντας το κουμπί escape ή πατώντας το πλήκτρο {κουμπί} στην επάνω γωνία.**", + "search_street": "Μπορείτε επίσης να ψάξετε για χαρακτηριστικά στην τρέχουσα προβολή ή παγκοσμίως. **Αναζήτηση για '{όνομα}'.**", + "choose_street": "**Επιλέξτε {όνομα} από τη λίστα για να την διαλέξετε. **", + "selected_street": "Εξαιρετικά! {όνομα} έχει τώρα επιλεγεί.", + "play": "Δοκιμάστε να μετακινήσετε τον χάρτη και κάνοντας κλικ σε κάποια άλλα χαρακτηριστικά για να δείτε τι είδους πράγματα μπορούν να προστεθούν στο OpenStreetMap. **Όταν είστε έτοιμοι να συνεχίσετε στο επόμενο κεφάλαιο, κάντε κλικ στο '{επόμενο}'.**" }, "points": { "title": "Σημεία", - "choose_cafe": "**Επιλέξτε {preset} από τη λίστα.**" + "add_point": "Τα *Σημεία* μπορούν να χρησιμοποιηθούν για να συμβολίσουν χαρακτηριστικά όπως καταστήματα, εστιατόρια και μνημεία. {Br} Σηματοδοτούν μια συγκεκριμένη τοποθεσία και περιγράφουν τι υπάρχει εκεί. **Κάντε κλικ στο {κουμπί} Σημείο για να προσθέσετε ένα νέο σημείο.**", + "place_point": "Για να τοποθετήσετε το νέο σημείο στο χάρτη, τοποθετήστε το δρομέα του ποντικιού, εκεί όπου το σημείο πρέπει να πάει, στη συνέχεια κάντε αριστερό κλικ ή πατήστε το πλήκτρο διαστήματος. **Μετακινήστε το δείκτη του ποντικιού πάνω σε αυτό το κτίριο, έπειτα κάντε αριστερό κλικ ή πατήστε το πλήκτρο διαστήματος.**", + "search_cafe": "Υπάρχουν πολλά διαφορετικά χαρακτηριστικά που μπορούν να αναπαρασταθούν από σημεία. Το σημείο που μόλις προσθέσατε είναι μία καφετέρια. **Αναζήτηση για '{preset}'.**", + "choose_cafe": "**Επιλέξτε {preset} από τη λίστα.**", + "feature_editor": "Το σημείο τώρα επισημαίνεται ως καφετέρια. Χρησιμοποιώντας τον επεξεργαστή χαρακτηριστικών, μπορούμε να προσθέσουμε περισσότερες πληροφορίες σχετικά με την καφετέρια.", + "add_name": "Στο OpenStreetMap, όλα τα πεδία είναι προαιρετικά και είναι εντάξει να αφήσετε ένα πεδίο κενό αν δεν είστε βέβαιοι. {Br} Ας υποθέσουμε ότι γνωρίζετε αυτή την καφετέρια, και ξέρετε το όνομά της. **Προσθέστε ένα όνομα για την καφετέρια.**", + "add_close": "Ο επεξεργαστής χαρακτηριστικών θα θυμάται αυτόματα όλες τις αλλαγές σας. ** Όταν ολοκληρώσετε την προσθήκη του ονόματος, πατήστε το escape, το enter ή κάντε κλικ στο πλήκτρο {κουμπί} για να κλείσετε τον επεξεργαστή χαρακτηριστικών. **", + "reselect": "Συχνά, σημεία θα υπάρχουν ήδη, αλλά θα έχουν λάθη ή θα είναι ελλιπή. Μπορούμε να επεξεργαστούμε τα υπάρχοντα σημεία. **Κάντε κλικ για να επιλέξετε την καφετέρια που μόλις δημιουργήσατε.**", + "update": "Ας συμπληρώσουμε κάποιες λεπτομέρειες για αυτή την καφετέρια. Μπορείτε να αλλάξετε το όνομά της, να προσθέσετε την κουζίνα ή να προσθέσετε μια διεύθυνση. **Αλλάξτε τις λεπτομέρειες της καφετέρειας.**", + "update_close": "** Όταν ολοκληρώσετε την ενημέρωση της καφετέριας, πατήστε το escape, το enter ή κάντε κλικ στο κουμπί {button} για να κλείσετε τον επεξεργαστή χαρακτηριστικών. **", + "rightclick": "Μπορείτε να κάνετε δεξί κλικ σε οποιαδήποτε χαρακτηριστικό για να δείτε το \"μενού επεξεργασίας*, το οποίο εμφανίζει μια λίστα με τις λειτουργίες επεξεργασίας που μπορείτε να εκτελέσετε. **Κάντε δεξί κλικ για να επιλέξετε το σημείο που δημιουργήσατε και να εμφανίσετε το μενού επεξεργασίας.**", + "delete": "Είναι εντάξει να διαγράψετε χαρακτηριστικά που δεν υπάρχουν στον πραγματικό κόσμο. {Br} Η διαγραφή ενός χαρακτηριστικού από το OpenStreetMap το αφαιρεί από τον χάρτη που χρησιμοποιεί ο καθένας, οπότε θα πρέπει να βεβαιωθείτε ότι ένα χαρακτηριστικό πραγματικά δεν υπάρχει προτού το διαγράψετε. **Κάντε κλικ στο κουμπί {κουμπί} για να διαγράψετε το σημείο.**", + "undo": "Μπορείτε πάντα να αναιρέσετε τυχόν αλλαγές έως ότου αποθηκεύσετε τις επεξεργασίες σας στο OpenStreetMap. **Κάντε κλικ στο κουμπί {κουμπί} για να αναιρέσετε τη διαγραφή και να πάρετε πίσω το σημείο.**", + "play": "Τώρα που ξέρετε πώς να δημιουργήσετε και να επεξεργαστείτε σημεία, δοκιμάστε να δημιουργήσετε μερικά ακόμα σημεία για εξάσκηση! **Όταν είστε έτοιμοι να συνεχίσετε στο επόμενο κεφάλαιο, κάντε κλικ στο '{επόμενο}'.**" }, "areas": { - "title": "Περιοχές" + "title": "Περιοχές", + "add_playground": "Οι *Περιοχές* χρησιμοποιούνται για να δείξουν τα όρια των χαρακτηριστικών όπως οι λίμνες, τα κτίρια και οι κατοικημένες περιοχές. {br} Μπορούν επίσης να χρησιμοποιηθούν για λεπτομερέστερη χαρτογράφηση πολλών χαρακτηριστικών που μπορεί κανονικά να χαρτογραφηθούν ως σημεία. **Κάντε κλικ στο {κουμπί} πλήκτρο Περιοχή για να προσθέσετε μια νέα περιοχή.**", + "start_playground": "Ας προσθέσουμε αυτή την παιδική χαρά στο χάρτη σχεδιάζοντας μια περιοχή. Οι περιοχές σχεδιάζονται τοποθετώντας *κόμβους* κατά μήκος του εξωτερικού άκρου του χαρακτηριστικού. **Κάντε κλικ ή πατήστε το πλήκτρο διαστήματος για να τοποθετήσετε έναν κόμβο έναρξης σε μια από τις γωνίες της παιδικής χαράς. **", + "continue_playground": "Συνεχίστε να σχεδιάζετε την περιοχή τοποθετώντας περισσότερους κόμβους κατά μήκος της άκρης της παιδικής χαράς. Είναι εντάξει να συνδέσετε την περιοχή με τα υπάρχοντα μονοπάτια πεζοπορίας. {Br} Συμβουλή: Μπορείτε να κρατήσετε πατημένο το πλήκτρο '{alt}' για να αποτρέψετε τη σύνδεση των κόμβων με άλλες λειτουργίες. **Συνεχίστε να σχεδιάζετε την περιοχή για την παιδική χαρά.**", + "finish_playground": "Ολοκληρώστε την περιοχή πατώντας το πλήκτρο enter ή κάνοντας κλικ ξανά τον πρώτο ή τον τελευταίο κόμβο. **Ολοκληρώστε τον σχεδιασμό μια περιοχής για την παιδική χαρά.**", + "search_playground": "**Αναζήτηση για '{preset}'.**", + "choose_playground": "**Επιλέξτε {preset} από τη λίστα.**", + "add_field": "Αυτή η παιδική χαρά δεν έχει επίσημο όνομα, οπότε δεν θα προσθέσουμε τίποτα στο πεδίο Όνομα. {Br} Αντ 'αυτού, ας προσθέσουμε μερικές επιπλέον λεπτομέρειες για την παιδική χαρά στο πεδίο Περιγραφή. **Ανοίξτε τη λίστα Προσθήκη Πεδίων.**", + "choose_field": "**Επιλέξτε {field} από τη λίστα.**", + "retry_add_field": "Δεν επιλέξατε το {field} πεδίο. Ας δοκιμάσουμε ξανά.", + "describe_playground": "**Προσθέστε μια περιγραφή και κάντε κλικ στο {πλήκτρο} πλήκτρο για να κλείσετε τον επεξεργαστή χαρακτηριστικών.**", + "play": "Καλή δουλειά! Δοκιμάστε να σχεδιάσετε μερικές ακόμη περιοχές και δείτε τι άλλα χαρακτηριστικά περιοχών μπορείτε να προσθέσετε στο OpenStreetMap. **Όταν είστε έτοιμοι να συνεχίσετε στο επόμενο κεφάλαιο, κάντε κλικ στο '{επόμενο}'.**" }, "lines": { - "title": "Γραμμές" + "title": "Γραμμές", + "add_line": "Οι *Γραμμές* χρησιμοποιούνται για να αντιπροσωπεύουν χαρακτηριστικά όπως δρόμοι, σιδηρόδρομοι και ποτάμια. **Κάντε κλικ στο κουμπί {κουμπί} Γραμμή για να προσθέσετε μια νέα γραμμή.**", + "start_line": "Εδώ υπάρχει ένας δρόμος που λείπει. Ας τον προσθέσουμε! {Br} Στο OpenStreetMap, οι γραμμές πρέπει να σχεδιαστούν στο κέντρο του δρόμου. Μπορείτε να σύρετε και να μεγεθύνετε το χάρτη ενώ σχεδιάζετε εάν είναι απαραίτητο. **Ξεκινήστε μια νέα γραμμή κάνοντας κλικ στην μία άκρη αυτού του δρόμου που λείπει.**", + "intersect": "Κάντε κλικ ή πατήστε το πλήκτρο διαστήματος για να προσθέσετε περισσότερους κόμβους στη γραμμή. {Br} Οι δρόμοι και πολλοί άλλοι τύποι γραμμών αποτελούν μέρος ενός μεγαλύτερου δικτύου. Είναι σημαντικό οι γραμμές αυτές να συνδεθούν σωστά για να λειτουργήσουν οι εφαρμογές δρομολόγησης. **Κάντε κλικ στο {όνομα} για να δημιουργήσετε μια διασταύρωση που συνδέει τις δύο γραμμές.**", + "retry_intersect": "Ο δρόμος πρέπει να διασταυρωθεί {όνομα}. Ας δοκιμάσουμε ξανά!", + "continue_line": "Συνεχίστε να σχεδιάζετε τη γραμμή για το νέο δρόμο. Θυμηθείτε ότι μπορείτε να σύρετε και να μεγεθύνετε τον χάρτη εάν χρειάζεται. {Br} Όταν ολοκληρώσετε την σχεδίαση, κάντε ξανά κλικ στον τελευταίο κόμβο. **Τελειώστε την σχεδίαση του δρόμου.**", + "choose_category_road": "**Επιλέξτε {κατηγορία} από τη λίστα.**", + "choose_preset_residential": "Υπάρχουν πολλοί διαφορετικοί τύποι δρόμων, αλλά αυτός είναι ένας οικιστικός δρόμος. **Επιλέξτε τον τύπο {preset}.**", + "retry_preset_residential": "Δεν επιλέξατε τον τύπο {preset}. **Κάντε κλικ εδώ για να επιλέξετε ξανά.**", + "name_road": "**Δώστε σε αυτόν το δρόμο ένα όνομα, στη συνέχεια πατήστε το escape, το enter ή κάντε κλικ στο κουμπί {κουμπί} για να κλείσετε τον επεξεργαστή χαρακτηριστικών.**", + "did_name_road": "Φαίνεται καλό! Στη συνέχεια θα μάθουμε πώς να ενημερώσουμε το σχήμα μιας γραμμής.", + "update_line": "Μερικές φορές θα χρειαστεί να αλλάξετε το σχήμα μιας υπάρχουσας γραμμής. Εδώ είναι ένας δρόμος που δεν φαίνεται σωστός.", + "add_node": "Μπορούμε να προσθέσουμε μερικούς κόμβους σε αυτή τη γραμμή για να βελτιώσουμε το σχήμα της. Ένας τρόπος για να προσθέσετε έναν κόμβο είναι να κάνετε διπλό κλικ στη γραμμή εκεί όπου θέλετε να προσθέσετε έναν κόμβο. **Κάντε διπλό κλικ στη γραμμή για να δημιουργήσετε έναν νέο κόμβο.**", + "finish_drag_endpoint": "Αυτό το σημείο φαίνεται καλό. **Αφήστε το αριστερό πλήκτρο του ποντικιού για να ολοκληρώσετε τη μεταφορά.**", + "start_drag_midpoint": "Μικρά τρίγωνα σχεδιάζονται στην *μέση* μεταξύ των κόμβων. Ένας άλλος τρόπος για να δημιουργήσετε ένα νέο κόμβο είναι να σύρετε ένα μεσαίο σημείο σε μια νέα θέση. **Σύρετε το τρίγωνο του μεσαίου σημείου για να δημιουργήσετε έναν νέο κόμβο κατά μήκος της καμπύλης του δρόμου.**", + "continue_drag_midpoint": "Αυτή η γραμμή φαίνεται πολύ καλύτερη! Συνεχίστε να προσαρμόζετε αυτή τη γραμμή κάνοντας διπλό κλικ ή σύροντας τα μεσαία σημεία μέχρι η καμπύλη να ταιριάζει με το σχήμα του δρόμου. **Όταν είστε ικανοποιημένοι με το πώς φαίνεται η γραμμή, κάντε κλικ στο OK.**", + "delete_lines": "Είναι εντάξει να διαγράψετε γραμμές για δρόμους που δεν υπάρχουν στον πραγματικό κόσμο. {Br} Εδώ είναι ένα παράδειγμα όπου η πόλη σχεδίαζε ένα {δρόμο} αλλά ποτέ δεν το κατασκεύασε. Μπορούμε να βελτιώσουμε αυτό το τμήμα του χάρτη διαγράφοντας τις επιπλέον γραμμές.", + "split_intersection": "**Κάντε κλικ στο κουμπί {κουμπί} για να διαχωρίσετε τον {δρόμο}.**", + "retry_split": "Δεν κάνατε κλικ στο κουμπί Διαχωρισμού. Προσπάθησε ξανά.", + "multi_rightclick": "Ωραία! Και οι δύο γραμμές που θέλετε να διαγράψετε έχουν τώρα επιλεγεί. **Κάντε δεξί κλικ σε μία από τις γραμμές για να εμφανιστεί το μενού επεξεργασίας.**", + "multi_delete": "**Κάντε κλικ στο κουμπί {κουμπί} για να διαγράψετε τις επιπλέον γραμμές.**", + "retry_delete": "Δεν κάνατε κλικ στο κουμπί Διαγραφή. Δοκιμάστε πάλι.", + "play": "Εξαιρετικά! Χρησιμοποιήστε τις δεξιότητες που μάθατε σε αυτό το κεφάλαιο για να εξασκηθείτε στην επεξεργασία μερικών ακόμη γραμμών. **Όταν είστε έτοιμοι να συνεχίσετε στο επόμενο κεφάλαιο, κάντε κλικ στο '{επόμενο}'.**" }, "buildings": { - "title": "Κτίρια" + "title": "Κτίρια", + "add_building": "Το OpenStreetMap είναι η μεγαλύτερη βάση δεδομένων των κτιρίων στον κόσμο. {Br} Μπορείτε να βοηθήσετε στην βελτίωση αυτής της βάσης δεδομένων εντοπίζοντας κτίρια που δεν έχουν ακόμα χαρτογραφηθεί. **Κάντε κλικ στο πλήκτρο {κουμπί} Περιοχή για να προσθέσετε μια νέα περιοχή.**", + "start_building": "Ας προσθέσουμε αυτό το σπίτι στο χάρτη αντιγράφοντας το περίγραμμα του. {Br} Τα κτίρια θα πρέπει να αντιγράφονται γύρω από το αποτύπωμα τους όσο το δυνατόν ακριβέστερα. **Κάντε κλικ ή πιέστε το πλήκτρο διαστήματος για να τοποθετήσετε έναν κόμβο εκκίνησης σε μια από τις γωνίες του κτιρίου.**", + "continue_building": "Συνεχίστε να προσθέτετε περισσότερους κόμβους για να αντιγράψετε το περίγραμμα του κτιρίου. Θυμηθείτε ότι μπορείτε να κάνετε μεγέθυνση εάν θέλετε να προσθέσετε περισσότερες λεπτομέρειες. {Br} Ολοκληρώστε το κτίριο πατώντας το enter ή πατώντας ξανά τον πρώτο ή τον τελευταίο κόμβο. **Ολοκληρώστε την αντιγραφή του κτιρίου.**", + "retry_building": "Φαίνεται ότι είχατε κάποιο πρόβλημα να τοποθετήσετε τους κόμβους στις γωνίες του κτιρίου. Προσπάθησε ξανά!", + "choose_category_building": "**Επιλέξτε {κατηγορία} από τη λίστα.**", + "choose_preset_house": "Υπάρχουν πολλοί διαφορετικοί τύποι κτιρίων, αλλά αυτός είναι σαφώς σπίτι. {Br} Εάν δεν είστε σίγουροι για τον τύπο, είναι εντάξει να επιλέξετε μόνο τον γενικό τύπο Κτιρίου. **Επιλέξτε τον {preset} τύπο.**", + "close": "**Πατήστε το escape ή κάντε κλικ στο πλήκτρο {κουμπί} για να κλείσετε τον επεξεργαστή χαρακτηριστικών. **", + "rightclick_building": "**Κάντε δεξί κλικ για να επιλέξετε το κτίριο που δημιουργήσατε και να εμφανιστεί το μενού επεξεργασίας.**", + "square_building": "Το σπίτι που μόλις προσθέσατε θα φαίνεται ακόμα καλύτερα με τέλεια τετραγωνισμένες γωνίες. **Κάντε κλικ στο πλήκτρο {button} για να τετραγωνιστεί το σχήμα του κτιρίου.**", + "retry_square": "Δεν κάνατε κλικ στο κουμπί Τετραγωνισμού. Προσπάθησε ξανά.", + "done_square": "Είδατε πώς οι γωνίες του κτιρίου μετακινήθηκαν στην θέση τους; Ας μάθουμε ένα άλλο χρήσιμο τέχνασμα.", + "add_tank": "Στη συνέχεια θα αντιγράψουμε αυτήν την κυκλική δεξαμενή αποθήκευσης. **Κάντε κλικ στο {κουμπί} πλήκτρο Περιοχή για να προσθέσετε μια νέα περιοχή.**", + "start_tank": "Μην ανησυχείτε, δεν θα χρειαστεί να σχεδιάσετε έναν τέλειο κύκλο. Απλά σχεδιάστε μια περιοχή μέσα στη δεξαμενή που αγγίζει τις άκρες της. **Κάντε κλικ ή πιέστε το πλήκτρο διαστήματος για να τοποθετήσετε τον αρχικό κόμβο στην άκρη της δεξαμενής.**", + "continue_tank": "Προσθέστε μερικούς ακόμη κόμβους γύρω στην άκρη. Ο κύκλος θα δημιουργηθεί εξωτερικά από τους κόμβους που σχεδιάσατε. {Br} Ολοκληρώστε την περιοχή πατώντας το enter ή κάνοντας κλικ ξανά στον πρώτο ή στον τελευταίο κόμβο. **Ολοκληρώστε την αντιγραφή της δεξαμενής.**", + "search_tank": "**Αναζήτηση για '{preset}'.**", + "choose_tank": "**Επιλέξτε {preset} από τη λίστα.**", + "rightclick_tank": "**Κάντε δεξί κλικ για να επιλέξετε την δεξαμενή αποθήκευσης που δημιουργήσατε και να εμφανιστεί το μενού επεξεργασίας.**", + "circle_tank": "**Κάντε κλικ στο {button} πλήκτρο για να φτιάξετε τη δεξαμενή σε κύκλο.**", + "retry_circle": "Δεν κάνατε κλικ στο κουμπί Κυκλοποίησης. Προσπάθησε ξανά.", + "play": "Εξαιρετική δουλειά! Κάντε εξάσκηση αντιγραφής μερικών ακόμη κτιρίων και δοκιμάστε μερικές από τις άλλες εντολές στο μενού επεξεργασίας. **Όταν είστε έτοιμοι να συνεχίσετε στο επόμενο κεφάλαιο, κάντε κλικ στο '{next}'.**" }, "startediting": { "title": "Εκκίνηση Επεξεργασίας", + "help": "Τώρα είστε έτοιμοι να επεξεργαστείτε το OpenStreetMap! {Br} Μπορείτε να επαναλάβετε αυτές τις οδηγίες ανά πάσα στιγμή ή να δείτε περισσότερες οδηγίες κάνοντας κλικ στο {button} Βοήθεια ή πατώντας το πλήκτρο '{key}'.", + "shortcuts": "Μπορείτε να δείτε μια λίστα εντολών μαζί με τις συντομεύσεις τους στο πληκτρολόγιο πατώντας το πλήκτρο '{key}'.", "save": "Μην ξεχνάτε να αποθηκεύετε συχνά τις αλλαγές σας!", "start": "Αρχίστε να χαρτογραφείτε!" } }, "shortcuts": { + "title": "Συντομεύσεις πληκτρολογίου", + "tooltip": "Εμφάνιση της οθόνης συντομεύσεων πληκτρολογίου.", "toggle": { "key": "?" }, + "key": { + "alt": "Alt" + }, "or": "-ή-", "browsing": { + "title": "Περιήγηση", + "navigation": { + "title": "Πλοήγηση", + "pan_more": "Μετακίνηση χάρτη κατά μια οθόνη", + "zoom": "Μεγέθυνση / Απομάκρυνση", + "zoom_more": "Μεγέθυνση / Απομάκρυνση κατά πολύ" + }, "help": { - "title": "Βοήθεια" + "title": "Βοήθεια", + "help": "Εμφάνιση βοήθειας/τεκμηρίωσης", + "keyboard": "Εμφάνιση συντομεύσεων πληκτρολογίου" + }, + "display_options": { + "title": "Εμφάνιση επιλογών", + "background": "Εμφάνιση επιλογών φόντου", + "background_switch": "Επαναφορά στο τελευταίο φόντο", + "map_data": "Εμφάνιση επιλογών δεδομένων χάρτη", + "fullscreen": "Μπείτε στη λειτουργία πλήρους οθόνης" + }, + "selecting": { + "title": "Επιλογή χαρακτηριστικών", + "select_one": "Επιλογή ενός χαρακτηριστικού", + "select_multi": "Επιλογή πολλαπλών χαρακτηριστικών", + "lasso": "Σχεδιάστε μια κλειστή περιοχή γύρω από τα χαρακτηριστικά", + "search": "Βρείτε χαρακτηριστικά που ταιριάζουν με το κείμενο αναζήτησης" + }, + "with_selected": { + "title": "Με το επιλεγμένο χαρακτηριστικό" + }, + "vertex_selected": { + "title": "Με τον επιλεγμένο κόμβο", + "previous": "Μετάβαση στον προηγούμενο κόμβο", + "next": "Μετάβαση στον επόμενο κόμβο", + "first": "Μετάβαση στον πρώτο κόμβο", + "last": "Μετάβαση στον τελευταίο κόμβο" } }, "editing": { + "title": "Επεξεργασία", + "drawing": { + "title": "Σχεδίαση", + "add_point": "Λειτουργία \"Προσθήκη σημείου\"", + "add_line": "Λειτουργία \"Προσθήκη γραμμής\"", + "add_area": "Λειτουργία \"Προσθήκη περιοχής\"", + "place_point": "Τοποθετήστε ένα σημείο", + "stop_line": "Τερματισμός σχεδιασμού μιας γραμμής ή μια περιοχής" + }, + "operations": { + "title": "Λειτουργίες", + "continue_line": "Συνεχίστε μια γραμμή στον επιλεγμένο κόμβο", + "merge": "Συνδυάστε (συγχώνευση) τα επιλεγμένα χαρακτηριστικά", + "disconnect": "Αποσυνδέστε τα χαρακτηριστικά στον επιλεγμένο κόμβο", + "split": "Χωρίστε μια γραμμή σε δύο στον επιλεγμένο κόμβο", + "reverse": "Αντιστρέψτε μια γραμμή", + "move": "Μετακίνηση επιλεγμένων χαρακτηριστικών", + "rotate": "Περιστροφή επιλεγμένων χαρακτηριστικών", + "orthogonalize": "Ευθυγραμμίστε την γραμμή / Τετραγωνίστε τις γωνίες μιας περιοχής", + "circularize": "Κάντε κύκλο μια κλειστή γραμμή ή μια περιοχή", + "delete": "Διαγράψτε τα επιλεγμένα χαρακτηριστικά" + }, "commands": { - "title": "Εντολές" + "title": "Εντολές", + "copy": "Αντιγράψτε τα επιλεγμένα χαρακτηριστικά", + "paste": "Επικολλήστε τα αντεγραμμένα χαρακτηρισιτκά", + "undo": "Αναίρεση τελευταίας ενέργειας", + "redo": "Επανάληψη τελευταίας ενέργειας", + "save": "Αποθήκευση αλλαγών" } }, "tools": { @@ -702,8 +1221,10 @@ "city!vn": "Πόλη", "conscriptionnumber": "123", "country": "Χώρα", + "county": "Επαρχεία", "county!jp": "Περιοχή", "district": "Περιοχή", + "district!vn": "Διαμέρισμα/Πόλη/Περιφέρεια", "floor": "Όροφος", "hamlet": "Οικισμός", "housename": "Όνομα Σπιτιού", @@ -713,6 +1234,8 @@ "place": "Τόπος", "postcode": "Ταχ. Κώδικας", "province": "Επαρχία", + "province!jp": "Νομός", + "quarter": "Συνοικία", "state": "Πολιτεία", "street": "Οδός", "suburb": "Προάστιο" @@ -758,6 +1281,9 @@ "aeroway": { "label": "Είδος" }, + "agrarian": { + "label": "Προϊόντα" + }, "amenity": { "label": "Είδος" }, @@ -798,7 +1324,8 @@ "label": "Ειδικότητα", "options": { "foot_bath": "Ποδόλουτρο", - "hot_spring": "Θερμή Πηγή" + "hot_spring": "Θερμή Πηγή", + "onsen": "Ιαπωνική Onsen" } }, "beauty": { @@ -825,12 +1352,22 @@ "board_type": { "label": "Είδος" }, + "boules": { + "label": "Είδος" + }, "boundary": { "label": "Είδος" }, "brand": { "label": "Επωνυμία" }, + "brewery": { + "label": "Δοκιμάστε τις μπύρες" + }, + "bridge": { + "label": "Είδος", + "placeholder": "Προεπιλεγμένο" + }, "building": { "label": "Κτίριο" }, @@ -840,14 +1377,22 @@ "bunker_type": { "label": "Είδος" }, + "cables": { + "placeholder": "1, 2, 3..." + }, "camera/direction": { "label": "Κατεύθυνση (Μοίρες στη φορά του Ρολογιού)", "placeholder": "45, 90, 180, 270" }, + "camera/mount": { + "label": "Τοποθέτηση κάμερας" + }, "camera/type": { "label": "Είδος Κάμερας", "options": { - "dome": "Θόλος" + "dome": "Θόλος", + "fixed": "Σταθερό", + "panning": "Μετακίνηση" } }, "capacity": { @@ -857,6 +1402,9 @@ "castle_type": { "label": "Είδος" }, + "clothes": { + "label": "Ρούχα" + }, "club": { "label": "Είδος" }, @@ -884,6 +1432,9 @@ "craft": { "label": "Τύπος" }, + "crane/type": { + "label": "Τύπος γερανού" + }, "crop": { "label": "Σπαρτά" }, @@ -896,6 +1447,10 @@ "currency_multi": { "label": "Νομίσματα" }, + "cutting": { + "label": "Είδος", + "placeholder": "Προεπιλεγμένο" + }, "cycle_network": { "label": "Δίκτυο" }, @@ -937,6 +1492,9 @@ "cycleway:right": "Δεξιά πλευρά" } }, + "dance/style": { + "label": "Στυλ Χορού" + }, "date": { "label": "Ημερομηνία" }, @@ -952,16 +1510,65 @@ "description": { "label": "Περιγραφή" }, + "devices": { + "label": "Συσκευές", + "placeholder": "1, 2, 3..." + }, + "direction_cardinal": { + "label": "Κατεύθυνση", + "options": { + "E": "Ανατολικά", + "ENE": "Ανατολικά-βορειοανατολικά", + "ESE": "Ανατολικά-νοτιοανατολικά", + "N": "Βόρεια", + "NE": "Βορειοανατολικά", + "NNE": "Βόρεια-βορειοανατολικά", + "NNW": "Βόρεια-βορειοδυτικά", + "NW": "Βορειοδυτικά", + "S": "Νότια", + "SE": "Νοτιοανατολικά", + "SSE": "Νότια-νοτιοανατολικά", + "SSW": "Νότια-νοτιοδυτικά", + "SW": "Νοτιοδυτικά", + "W": "Δυτικά", + "WNW": "Δυτικά-βορειοδυτικά", + "WSW": "Δυτικά-νοτιοδυτικά" + } + }, + "direction_clock": { + "label": "Κατεύθυνση", + "options": { + "anticlockwise": "Αριστερόστροφα", + "clockwise": "Δεξιόστροφα" + } + }, + "direction_vertex": { + "label": "Κατεύθυνση", + "options": { + "backward": "Ανάποδα", + "both": "Και τα δύο / Όλα", + "forward": "Εμπρός" + } + }, + "distance": { + "label": "Συνολική Απόσταση" + }, "dock": { "label": "Είδος" }, + "duration": { + "label": "Διάρκεια", + "placeholder": "00:00" + }, "electrified": { "label": "Ηλεκτροδότηση", "options": { + "contact_line": "Γραμμή επαφής", "no": "Όχι", "rail": "Ηλεκτροδοτούμενος Σιδηρόδρομος", "yes": "Ναι (ακαθόριστο)" - } + }, + "placeholder": "Γραμμή επαφής, Ηλεκτροδοτούμενος Σιδηρόδρομος..." }, "elevation": { "label": "Υψόμετρο" @@ -970,6 +1577,10 @@ "label": "Διεύθυνση Ηλεκτρονικού Ταχυδρομείου", "placeholder": "example@example.com" }, + "embankment": { + "label": "Είδος", + "placeholder": "Προκαθορισμένο" + }, "emergency": { "label": "Επείγοντα" }, @@ -1001,14 +1612,25 @@ "fire_hydrant/type": { "label": "Τύπος", "options": { + "pillar": "Κολώνα/Υπερυψωμένο", "pond": "Λιμνούλα", "underground": "Υπόγεια", "wall": "Τοίχος" } }, + "fitness_station": { + "label": "Είδος Εξοπλισμού" + }, "fixme": { "label": "Διορθώστε με" }, + "ford": { + "label": "Είδος", + "placeholder": "Προκαθορισμένο" + }, + "frequency": { + "label": "Συχνότητα λειτουργίας" + }, "fuel": { "label": "Καύσιμο" }, @@ -1019,7 +1641,8 @@ "label": "Φύλο", "options": { "female": "Θηλυκό", - "male": "Αρσενικό" + "male": "Αρσενικό", + "unisex": "Unisex" }, "placeholder": "Άγνωστο" }, @@ -1036,6 +1659,9 @@ "generator/type": { "label": "Τύπος" }, + "government": { + "label": "Είδος" + }, "grape_variety": { "label": "Ποικιλία Αμπελιού" }, @@ -1046,6 +1672,15 @@ "handrail": { "label": "Κουπαστή" }, + "hashtags": { + "placeholder": "#παράδειγμα" + }, + "healthcare": { + "label": "Είδος" + }, + "healthcare/speciality": { + "label": "Ειδικότητες" + }, "height": { "label": "Ύψος (Μέτρα)" }, @@ -1062,6 +1697,34 @@ "label": "Ρακέτες", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Επίδειξη Αλόγων", + "options": { + "equestrian": "Ναι", + "undefined": "Όχι" + } + }, + "horse_riding": { + "label": "Ιππασία", + "options": { + "horse_riding": "Ναι", + "undefined": "Όχι" + } + }, + "horse_scale": { + "label": "Δυσκολία Ιππασίας", + "options": { + "common": "Εύκολο: Δεν υπάρχουν προβλήματα ή δυσκολίες. (προκαθορισμένο)" + }, + "placeholder": "Δύσκολο, Επικίνδυνο ..." + }, + "horse_stables": { + "label": "Σταθερή Ιππασία", + "options": { + "stables": "Ναι", + "undefined": "Όχι" + } + }, "iata": { "label": "IATA" }, @@ -1078,12 +1741,21 @@ "up": "Πάνω" } }, + "indoor": { + "label": "Εσωτερικά" + }, + "industrial": { + "label": "Είδος" + }, "information": { "label": "Είδος" }, "inscription": { "label": "Επιγραφή" }, + "intermittent": { + "label": "Διακοπτόμενο" + }, "internet_access": { "label": "Πρόσβαση στο διαδίκτυο", "options": { @@ -1100,6 +1772,9 @@ "internet_access/ssid": { "label": "SSID (Όνομα Δικτύου)" }, + "label": { + "label": "Ετικέτα" + }, "lamp_type": { "label": "Είδος" }, @@ -1169,6 +1844,12 @@ "man_made": { "label": "Είδος" }, + "manhole": { + "label": "Είδος" + }, + "map_size": { + "label": "Κάλυψη" + }, "map_type": { "label": "Είδος" }, @@ -1180,12 +1861,19 @@ "label": "Όριο Ταχύτητας", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "Προειδοποιητικό Όριο Ταχύτητας", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Μέγιστη παραμονή" }, "maxweight": { "label": "Μέγιστο Βάρος" }, + "memorial": { + "label": "Είδος" + }, "mtb/scale": { "label": "Δυσκολία Ορεινής Ποδηλασίας", "options": { @@ -1194,6 +1882,7 @@ "placeholder": "0, 1, 2, 3..." }, "mtb/scale/imba": { + "label": "Επίπεδα Δυσκολίας μονοπατιών του IMBA", "options": { "0": "Πανεύκολο (λευκός κύκλος)", "1": "Εύκολο (πράσινος κύκλος)", @@ -1224,7 +1913,8 @@ "lcn": "Τοπικό", "ncn": "Εθνικό", "rcn": "Περιφερειακό" - } + }, + "placeholder": "Τοπικό, Περιφερειακό, Εθνικό, Διεθνές" }, "network_foot": { "label": "Είδος Δικτύου", @@ -1289,17 +1979,30 @@ "parking": { "label": "Είδος", "options": { + "carports": "Υπόστεγο αυτοκινήτου", "multi-storey": "Πολυεπίπεδο", "surface": "Επιφάνεια", "underground": "Υπόγειο" } }, + "payment_multi": { + "label": "Τρόποι Πληρωμής" + }, + "phases": { + "placeholder": "1, 2, 3..." + }, "phone": { "label": "Τηλέφωνο", "placeholder": "+30 210 1234567" }, "piste/difficulty": { - "label": "Δυσκολία" + "label": "Δυσκολία", + "options": { + "advanced": "Προχωρημένο (μαύρο διαμάντι)", + "easy": "Εύκολο (πράσινος κύκλος)", + "expert": "Έμπειρος (διπλό μαύρο διαμάντι)", + "extreme": "Ακραίο (απαιτείται ορειβατικός εξοπλισμός)" + } }, "piste/grooming": { "options": { @@ -1547,9 +2250,6 @@ "trees": { "label": "Δέντρα" }, - "vending": { - "label": "Είδος αγαθών" - }, "visibility": { "label": "Ορατότητα", "options": { @@ -3466,15 +4166,6 @@ "type/restriction/no_u_turn": { "name": "Όχι Αναστροφή" }, - "type/restriction/only_left_turn": { - "name": "Μόνο Αριστερή Στροφή" - }, - "type/restriction/only_right_turn": { - "name": "Μόνο Δεξιά Στροφή" - }, - "type/restriction/only_straight_on": { - "name": "Όχι Στροφές" - }, "type/route": { "name": "Δρομολόγιο", "terms": "Δρομολόγιο, Διαδρομή" @@ -3564,71 +4255,157 @@ }, "imagery": { "Bing": { - "description": "Δορυφορική και εναέρια εικόνα." + "description": "Δορυφορική και εναέρια εικόνα.", + "name": "Εναέρια Εικόνα Bing" }, "DigitalGlobe-Premium": { "attribution": { "text": "Όροι και σχόλια" }, - "description": "Δορυφορική εικόνα Premium DigitalGlobe." + "description": "Δορυφορική εικόνα Premium DigitalGlobe.", + "name": "Ανώτερες Ψηφιακές Εικόνες της Υδρογείου" + }, + "DigitalGlobe-Premium-vintage": { + "attribution": { + "text": "Όροι και Σχόλια" + }, + "description": "Όρια εικόνων και ημερομηνίες λήψης. Οι ετικέτες εμφανίζονται από το επίπεδο εστίασης 13 και πάνω.", + "name": "Ανώτερες Ψηφιακές Εικόνες Εποχής της Υδρογείου" }, "DigitalGlobe-Standard": { "attribution": { "text": "Όροι και σχόλια" }, - "description": "Δορυφορική εικόνα Standard DigitalGlobe." + "description": "Δορυφορική εικόνα Standard DigitalGlobe.", + "name": "Τυπικές Ψηφιακές Εικόνες της Υδρογείου" + }, + "DigitalGlobe-Standard-vintage": { + "attribution": { + "text": "Όροι και Σχόλια" + }, + "description": "Όρια εικόνων και ημερομηνίες λήψης. Οι ετικέτες εμφανίζονται από το επίπεδο εστίασης 13 και πάνω.", + "name": "Τυπικές Ψηφιακές Εικόνες Εποχής της Υδρογείου" + }, + "EsriWorldImagery": { + "attribution": { + "text": "Όροι και Σχόλια" + }, + "description": "Παγκόσμια εικόνα Esri", + "name": "Παγκόσμια Eικόνα Esri" + }, + "EsriWorldImageryClarity": { + "attribution": { + "text": "Όροι και Σχόλια" + }, + "description": "Οι εικόνες του αρχείου Esri μπορούν να είναι πιο ευδιάκριτες και ακριβέστερες από το προεπιλεγμένηο επίπεδο.", + "name": "Παγκόσμια Eικόνα Esri (Διαύγεια) Beta" }, "MAPNIK": { "attribution": { "text": "© OpenStreetMap contributors, CC-BY-SA" }, - "description": "Η προεπιλεγμένη στρώση του OpenStreetMap." + "description": "Η προεπιλεγμένη στρώση του OpenStreetMap.", + "name": "OpenStreetMap (Τυπικό)" }, "Mapbox": { "attribution": { "text": "Όροι και σχόλια" }, - "description": "Δορυφορική και εναέρια εικόνα." + "description": "Δορυφορική και εναέρια εικόνα.", + "name": "Δορυφορική εικόνα Mapbox" }, "OSM_Inspector-Addresses": { "attribution": { "text": "© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "Επιθεωρητής OSM: Διευθύνσεις" }, "OSM_Inspector-Geometry": { "attribution": { "text": "© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "Επιθεωρητής OSM: Γεωμετρία" }, "OSM_Inspector-Highways": { "attribution": { "text": "© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "Επιθεωρητής OSM: Δρόμοι" }, "OSM_Inspector-Multipolygon": { "attribution": { "text": "© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "Επιθεωρητής OSM: Περιοχή" }, "OSM_Inspector-Places": { "attribution": { "text": "© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "Επιθεωρητής OSM: Τοποθεσίες" }, "OSM_Inspector-Routing": { "attribution": { "text": "© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "Επιθεωρητής OSM: Δρομολόγηση" }, "OSM_Inspector-Tagging": { "attribution": { "text": "© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "Επιθεωρητής OSM: Προσθήκη Ετικέτας" + }, + "US-TIGER-Roads-2012": { + "name": "Δρόμοι TIGER 2012" + }, + "US-TIGER-Roads-2014": { + "description": "Στο επίπεδο εστίασης 16+, είναι τα δεδομένα χάρτη του δημόσιων ιδιοκτησιών από την απογραφή των ΗΠΑ. Στις χαμηλότερες εστιάσεις, μόνο αλλαγές από το 2006 εκτός από αλλαγές που έχουν ήδη ενσωματωθεί στο OpenStreetMap", + "name": "Δρόμοι TIGER 2014" + }, + "US-TIGER-Roads-2017": { + "description": "Κίτρινο = Δεδομένα χάρτη δημόσιων ιδιοκτησιών από την απογραφή των ΗΠΑ. Κόκκινο = Δεδομένα που δεν βρέθηκαν στο OpenStreetMap", + "name": "Δρόμοι TIGER 2017" + }, + "US_Forest_Service_roads_overlay": { + "description": "Δρόμος: Πράσινο περίβλημα = μη ταξινομημένο. Καφέ περίβλημα = ίχνος. Επιφάνεια: χαλίκι = γεμάτο ανοιχτό καφέ, Άσφαλτος = μαύρο, πλακόστρωτο = γκρι, έδαφος = λευκό, τσιμέντο= μπλε, γρασίδι = πράσινο. Εποχιακά = λευκές μπάρες", + "name": "Επικάλυψη Δασικών Δρόμων των ΗΠΑ" + }, + "Waymarked_Trails-Cycling": { + "attribution": { + "text": "© waymarkedtrails.org, συνεισφέροντες στο OpenStreetMap, CC by-SA 3.0" + }, + "name": "Σηματοδοτημένες Διαδρομές: Ποδηλασία" + }, + "Waymarked_Trails-Hiking": { + "attribution": { + "text": "© waymarkedtrails.org, συνεισφέροντες στο OpenStreetMap, CC by-SA 3.0" + }, + "name": "Σηματοδοτημένες Διαδρομές: Πεζοπορία" + }, + "Waymarked_Trails-MTB": { + "attribution": { + "text": "© waymarkedtrails.org, συνεισφέροντες στο OpenStreetMap, CC by-SA 3.0" + }, + "name": "Σηματοδοτημένες Διαδρομές: Ποδήλατο Βουνού" + }, + "Waymarked_Trails-Skating": { + "attribution": { + "text": "© waymarkedtrails.org, συνεισφέροντες στο OpenStreetMap, CC by-SA 3.0" + }, + "name": "Σηματοδοτημένες Διαδρομές: Σκέϊτ" + }, + "Waymarked_Trails-Winter_Sports": { + "attribution": { + "text": "© waymarkedtrails.org, συνεισφέροντες στο OpenStreetMap, CC by-SA 3.0" + }, + "name": "Σηματοδοτημένες Διαδρομές: Χειμερινά Σπορ" }, "basemap.at": { "attribution": { "text": "basemap.at" }, + "description": "Χάρτης βάσης της Αυστρίας, βασισμένος σε κυβερνητικά δεδομένα.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -3641,17 +4418,21 @@ "hike_n_bike": { "attribution": { "text": "© OpenStreetMap contributors" - } + }, + "name": "Πεζοπορία & Ποδήλατο" }, "mapbox_locator_overlay": { "attribution": { "text": "Όροι και σχόλια" - } + }, + "description": "Εμφάνιση σημαντικών χαρακτηριστικών για να σας βοηθήσει να σας προσανατολίσετε.", + "name": "Επικάλυψη Εντοπισμού" }, "openpt_map": { "attribution": { "text": "© OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "Χάρτης OpenPT (επικάλυψη)" }, "osm-gps": { "attribution": { @@ -3663,17 +4444,20 @@ "osm-mapnik-black_and_white": { "attribution": { "text": "© OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "OpenStreetMap (Τυπικό Ασπρόμαυρο)" }, "osm-mapnik-german_style": { "attribution": { "text": "© OpenStreetMap contributors, CC-BY-SA" - } + }, + "name": "OpenStreetMap (Γερμανικό Στυλ)" }, "qa_no_address": { "attribution": { "text": "Simon Poole, Δεδομένα © OpenStreetMap contributors" - } + }, + "name": "QA Καμία Διεύθυνση" }, "skobbler": { "attribution": { @@ -3683,18 +4467,291 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Πλακίδια χάρτη από Stamen Design, υπό CC BY 3.0" - } + "text": "Πλακίδιια χαρτών από το Stamen Design, κάτω από CC BY 3.0. Δεδομένα από το OpenStreetMap, κάτω από ODbL" + }, + "name": "Stamen Εδαφικό" }, "tf-cycle": { "attribution": { "text": "Χάρτες © Thunderforest, Δεδομένα © OpenStreetMap contributors" - } + }, + "name": "Thunderforest OpenCycleMap" }, "tf-landscape": { "attribution": { "text": "Χάρτες © Thunderforest, Δεδομένα © OpenStreetMap contributors" + }, + "name": "Thunderforest Τοπίο" + } + }, + "community": { + "cape-coast-youthmappers": { + "name": "Πανεπιστήμιο του Cape Coast YouthMappers", + "description": "Ακολουθήστε μας στο Twitter: {url}" + }, + "osm-gh-facebook": { + "name": "Το OpenStreetMap της Γκάνα στο Facebook", + "description": "Ομάδα στο Facebook για άτομα που ενδιαφέρονται για το OpenStreetMap.", + "extendedDescription": "Χαρτογράφοι στην κοινότητα της Γκάνα, προωθούν εργασίες του OpenStreetMap και της Ανθρωπιστικής Ομάδας OpenStreetMap (HOT) στην Γκάνα. Ελάτε μαζί μας." + }, + "osm-gh-twitter": { + "name": "Το OpenStreetMap της Γκάνα στο Twitter", + "description": "Ακολουθήστε μας στο Twitter: {url}" + }, + "talk-gh": { + "name": "Ταχυδρομική Λίστα Talk-gh", + "description": "Το Talk-gh είναι η επίσημη ταχυδρομική λίστα για την κοινότητα OSM της Γκάνα." + }, + "osm-mg-facebook": { + "name": "Ομάδα Facebook Μαδαγασκάρης για το OpenStreetMap", + "description": "Ομάδα Facebook Μαδαγασκαριανών για άτομα που ενδιαφέρονται για το OpenStreetMap" + }, + "talk-mg": { + "name": "Ταχυδρομική Λίστα Talk-gh", + "description": "Τοποθεσία για τους συνδρομητές του OpenStreetMap, τις κοινότητες και τους χρήστες στη Μαδαγασκάρη για συμμετοχή και συζήτηση." + }, + "OSM-BGD-facebook": { + "name": "Το OpenStreetMap του Μπαγκλαντές", + "description": "Βελτιώστε το OpenStreetMap στο Μπαγκλαντές", + "extendedDescription": "Χαρτογράφηση στο Μπαγκλαντές; Έχετε ερωτήσεις, θέλετε να συνδεθείτε με την κοινότητα εδώ; Ελάτε μαζί μας στο {url}. Είναι όλοι ευπρόσδεκτοι!" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap της Ινδία - Συμμετοχική χαρτογράφηση γειτονιάς", + "description": "Βελτιώστε το OpenStreetMap στην Ινδία", + "extendedDescription": "Χαρτογράφηση στην Ινδία; Έχετε ερωτήσεις, θέλετε να συνδεθείτε με την κοινότητα εδώ; Ελάτε μαζί μας στο {url}. Είναι όλοι ευπρόσδεκτοι!", + "events": { + "sotmasia2018": { + "description": "Λάβετε μέρος στην εκδήλωση State of the Map Asia 2018 του OpenStreetMap στην ευρύτερη περιοχή της Ινδίας", + "where": "Ινδικό Ινστιτούτο Διοίκησης, Μπανγκαλόρ, Ινδία" + } } + }, + "OSM-india-mailinglist": { + "name": "Κατάλογος Αλληλογραφίας OpenStreetMap της Ινδίας", + "description": "Το Talk-in είναι ο επίσημος κατάλογος Αλληλογραφίας για την Ινδική Κοινότητα" + }, + "OSM-india-twitter": { + "name": "Το Twitter του OpenStreetMap της Ινδίας ", + "description": "Είμαστε απλά ένα tweet μακριά: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "(FSHM) Κίνημα Ελεύθερου Λογισμικού & Υλικού - Facebook", + "description": "Η FSHM Facebook σελίδα για να ξέρετε για εκδηλώσεις & δραστηριότητες της κοινότητας", + "extendedDescription": "Η FSHM διοργανώνει εκδηλώσεις σχετικές με την τεχνολογία ελεύθερου λογισμικού / υλικού, τον ακτιβισμό και το OpenStreetMap. Η σελίδα στο FB είναι ο καλύτερος τρόπος για να διατηρείτε επαφή με τα γεγονότα της." + }, + "OSM-India-Puducherry-Matrix": { + "name": "(FSHM) Κίνημα Ελεύθερου Λογισμικού & Υλικού - Matrix" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap στην Ινδονησία", + "description": "Βελτιώστε το OpenStreetMap στην Ινδονησία", + "extendedDescription": "Χαρτογράφηση στην Ινδονησία; Έχετε ερωτήσεις, θέλετε να συνδεθείτε με την κοινότητα εδώ; Ελάτε μαζί μας στο {url}. Είναι όλοι ευπρόσδεκτοι!" + }, + "OSM-japan-facebook": { + "name": "Ιαπωνική Κοινότητα του OpenStreetMap ", + "description": "Χαρτογράφοι και χρήστες του OpenStreetMap στην Ιαπωνία" + }, + "OSM-japan-mailinglist": { + "name": "Κατάλογος Αλληλογραφίας OpenStreetMap της Ιαπωνίας", + "description": "Το Talk-ja είναι ο επίσημος κατάλογος Αλληλογραφίας για την Ιαπωνική Κοινότητα" + }, + "OSM-japan-twitter": { + "name": "Twitter OpenStreetMap Ιαπωνίας", + "description": "Hashtag στοTwitter: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap στην Ιαπωνία", + "description": "Χαρτογράφοι και χρήστες του OpenStreetMap στην Ιαπωνία" + }, + "OSM-korea-telegram": { + "description": "Ανεπίσημο κανάλι για τους συνεργάτες του OpenStreetMap, τις κοινότητες και τους χρήστες στην Κορέα για μοίρασμα και συζήτηση." + }, + "OSM-MY-facebook": { + "name": "Το OpenStreetMap της Μαλαισίας στο Facebook", + "description": "Για συνομιλία για οτιδήποτε σχετίζεται με το OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "Φόρουμ OpenStreetMap της Μαλαισίας", + "description": "Επίσημο Φόρουμ OpenStreetMap της Μαλαισίας" + }, + "OSM-MY-matrix": { + "description": "Όλοι οι χαρτογράφοι είναι ευπρόσδεκτοι! Εγγραφείτε στο {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap στην Μογγολία", + "description": "Βελτιώστε το OpenStreetMap στην Μογγολία", + "extendedDescription": "Χαρτογράφηση στην Μογγολία; Έχετε ερωτήσεις, θέλετε να συνδεθείτε με την κοινότητα εδώ; Ελάτε μαζί μας στο {url}. Είναι όλοι ευπρόσδεκτοι!" + }, + "OSM-MMR-facebook": { + "name": "Το OpenStreetMap της Μιανμάρ", + "description": "Βελτιώστε το OpenStreetMap στην Μιανμάρ", + "extendedDescription": "Χαρτογράφηση στην Μιανμάρ; Έχετε ερωτήσεις, θέλετε να συνδεθείτε με την κοινότητα εδώ; Ελάτε μαζί μας στο {url}. Είναι όλοι ευπρόσδεκτοι!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap στο Νεπάλ", + "description": "Βελτιώστε το OpenStreetMap στο Νεπάλ", + "extendedDescription": "Χαρτογράφηση στο Νεπάλ; Έχετε ερωτήσεις, θέλετε να συνδεθείτε με την κοινότητα εδώ; Ελάτε μαζί μας στο {url}. Είναι όλοι ευπρόσδεκτοι!" + }, + "OSM-PH-facebook": { + "description": "Καλώς ήρθατε στο OpenStreetMap των Φιλιππίνων, όπου ενθαρρύνουμε όλους τους φιλιππινέζους να συνεισφέρουν στο έργοτου OpenStreetMap." + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph Κατάλογος Αλληλογραφίας", + "description": "Μια λίστα αλληλογραφίας για να συζητήσετε το OpenStreetMap στις Φιλιππίνες" + }, + "OSM-PH-slack": { + "description": "Όλοι είναι ευπρόσδεκτοι! Εγγραφείτε στο {signupUrl}" + }, + "OSM-RU-forum": { + "name": "RU φόρουμ OpenStreetMap", + "description": "Διαδικτυακό φόρουμ OpenStreetMap Ρωσίας" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap στην Σρι Λάνκα", + "description": "Βελτιώστε το OpenStreetMap στην Σρι Λάνκα", + "extendedDescription": "Χαρτογράφηση στην Σρι Λάνκα; Έχετε ερωτήσεις, θέλετε να συνδεθείτε με την κοινότητα εδώ; Ελάτε μαζί μας στο {url}. Είναι όλοι ευπρόσδεκτοι!" + }, + "OSM-TW-facebook": { + "name": "OpenStreetMap Κοινότητα της Ταϊβάν" + }, + "OSM-TW-mailinglist": { + "name": "Κατάλογος Αλληλογραφίας OpenStreetMap της Ταϊβάν" + }, + "al-maptime-tirana": { + "description": "Στις κοινωνικές εκδηλώσεις οργανωμένες γύρω από τη χαρτογράφηση - οι αρχάριοι είναι περισσότερο ευπρόσδεκτοι!" + }, + "at-mailinglist": { + "name": "Talk-at Κατάλογος Αλληλογραφίας", + "description": "Το Talk-at είναι ο επίσημος κατάλογος Αλληλογραφίας για την Αυστριακή Κοινότητα του OSM" + }, + "at-twitter": { + "name": "Το Twitter του OpenStreetMap της Αυστρίας", + "description": "Το OpenStreetMap της Αυστρίας στο Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "Συνάντηση κοινότητας OSM στο Γκρατς", + "description": "Μηνιαία συνάντηση της κοινότητας του OpenStreetMap στο Γκρατς" + }, + "osmgraz-twitter": { + "name": "Η OSM κοινότητα του Γκρατς στο twitter", + "description": "Η OpenStreetMap κοινότητα του Γκρατς στο twitter" + }, + "osm-at": { + "name": "OpenStreetMap στην Αυστρία", + "description": "Η πλατφόρμα για πληροφορίες σχετικά με το OpenStreetMap στην Αυστρία" + }, + "byosm": { + "name": "OpenStreetMap Λευκορωσίας" + }, + "be-facebook": { + "name": "Κοινότητα OpenStreetMap BE", + "description": "Χαρτογράφοι και OpenStreetMap του Βελγίου στο Facebook" + }, + "be-forum": { + "name": "Φόρουμ OpenStreetMap BE", + "description": "Φόρουμ διαδικτύου του OpenStreetMap Βελγίου " + }, + "be-irc": { + "name": "IRC OpenStreetMap Βελγίου" + }, + "be-mailinglist": { + "name": "Talk-be Κατάλογος Αλληλογραφίας", + "description": "Το Talk-be είναι ο επίσημος κατάλογος αλληλογραφίας για την Βελγική Κοινότητα του OSM" + }, + "be-maptime": { + "description": "Στις κοινωνικές εκδηλώσεις οργανωμένες γύρω από τη χαρτογράφηση - οι αρχάριοι είναι περισσότερο ευπρόσδεκτοι!" + }, + "be-matrix": { + "description": "Όλοι οι χαρτογράφοι είναι ευπρόσδεκτοι!" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz Κατάλογος Αλληλογραφίας", + "description": "Το Talk-cz είναι ο επίσημος κατάλογος αλληλογραφίας για την Τσέχικη Κοινότητα" + }, + "dk-mailinglist": { + "name": "Talk-dk Κατάλογος Αλληλογραφίας", + "description": "Μια λίστα αλληλογραφίας συζήτησης για το OpenStreetMap στη Δανία" + }, + "fr-facebook": { + "name": "Σελίδα Facebook του OpenStreetMap στη Γαλλία", + "description": "Σελίδα Facebook του OpenStreetMap στη Γαλλία" + }, + "fr-forum": { + "name": "Διαδικτυακό φόρουμ του OpenStreetMap στη Γαλλία", + "description": "Διαδικτυακό φόρουμ του OpenStreetMap στη Γαλλία" + }, + "fr-mailinglist": { + "name": "Talk-fr Κατάλογος Αλληλογραφίας", + "description": "Talk-fr κατάλογος αλληλογραφίας" + }, + "fr-twitter": { + "name": "Το OpenStreetMap της Γαλλίας στο Twitter", + "description": "Το OpenStreetMap της Γαλλίας στο Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "Κατάλογος Αλληλογραφίας Βερολίνου", + "description": "Αυτή είναι μια λίστα αλληλογραφίας για την κοινότητα OpenStreetMap στο Βερολίνο" + }, + "de-berlin-meetup": { + "description": "Χαρτογράφοι και χρήστες του OpenStreetMap στην περιοχή του Βερολίνου" + }, + "de-berlin-twitter": { + "description": "Ακολουθήστε μας στο Twitter: {url}" + }, + "de-forum": { + "name": "Φόρουμ OpenStreetMap DE", + "description": "Διαδικτυακό φόρουμ OpenStreetMap Γερμανίας" + }, + "de-mailinglist": { + "name": "Talk-de Κατάλογος Αλληλογραφίας", + "description": "Το Talk-de είναι ο επίσημος κατάλογος αλληλογραφίας για την Γερμανική κοινότητα του OSM" + }, + "osm-de": { + "name": "OpenStreetMap Γερμανίας", + "description": "Η πλατφόρμα για πληροφορίες σχετικά με το OpenStreetMap στη Γερμανία" + }, + "hu-facebook": { + "name": "Το OpenStreetMap HU στο Facebook", + "description": "Χαρτογράφοι και Facebook του OpenStreetMap στην Ουγγαρία" + }, + "hu-forum": { + "name": "Φόρουμ του OpenStreetMap HU ", + "description": "Διαδικτυακό φόρουμ OpenStreetMap Ουγγαρίας" + }, + "hu-meetup": { + "name": "Συνάντηση του OpenStreetMap Ουγγαρίας", + "description": "Η πλατφόρμα για τη διοργάνωση συναντήσεων στην Ουγγαρία" + }, + "it-facebook": { + "name": "Το OpenStreetMap Ιταλίας στο Facebook", + "description": "Λάβετε μέρος στην κοινότητα του OpenStreetMap Ιταλίας στο Facebook" + }, + "it-mailinglist": { + "name": "Talk-it Κατάλογος Αλληλογραφίας", + "description": "Το Talk-it είναι ο επίσημος κατάλογος αλληλογραφίας για την Ιταλική κοινότητα του OSM" + }, + "South-Tyrol-Mailing-List": { + "name": "Κατάλογος Αλληλογραφίας OpenStreetMap του Νότιου Τυρόλο" + }, + "Trentino-Mailing-List": { + "name": "Κατάλογος Αλληλογραφίας OpenStreetMap του Τρεντίνο" + }, + "no-irc": { + "description": "Χώρος συζήτησης για τους ζαρτογράφους και τους χρήστες του OpenStreetMap, τους προγραμματιστές και τους λάτρεις στην Νορβηγία" + }, + "no-mailinglist": { + "name": "Κατάλογος Αλληλογραφίας OpenStreetMap της Νορβηγίας" + }, + "OSM-ES-mailinglist": { + "name": "Talk-es κατάλογος αλληλογραφίας", + "description": "Μια λίστα αλληλογραφίας για να συζητήσετε το OpenStreetMap στν Ισπανία" + }, + "se-mailinglist": { + "name": "Talk-se Κατάλογος Αλληλογραφίας", + "description": "Μια λίστα αλληλογραφίας για να συζητήσετε το OpenStreetMap στη Σουηδία" + }, + "gb-mailinglist": { + "name": "Talk-gb Κατάλογος Αλληλογραφίας" } } } diff --git a/vendor/assets/iD/iD/locales/en-GB.json b/vendor/assets/iD/iD/locales/en-GB.json index b84f61a17..838106b9f 100644 --- a/vendor/assets/iD/iD/locales/en-GB.json +++ b/vendor/assets/iD/iD/locales/en-GB.json @@ -1,5 +1,10 @@ { "en-GB": { + "icons": { + "information": "info", + "remove": "remove", + "undo": "undo" + }, "modes": { "add_area": { "title": "Area", @@ -25,6 +30,9 @@ }, "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." + }, + "drag_node": { + "connected_to_hidden": "This can't be edited because it is connected to a hidden feature." } }, "operations": { @@ -142,7 +150,9 @@ "vertex": "Connected a way to another.", "line": "Connected a way to a line.", "area": "Connected a way to an area." - } + }, + "relation": "These features can't be connected because they have conflicting relation roles.", + "restriction": "These features can't be connected because it would damage a \"{relation}\" relation." }, "disconnect": { "title": "Disconnect", @@ -160,7 +170,6 @@ "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." }, @@ -288,6 +297,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Distance", + "distance_up_to": "Up to {distance}", + "via": "Via", + "via_node_only": "Node only", + "via_up_to_one": "Up to 1 way", + "via_up_to_two": "Up to 2 ways" + }, + "help": { + "indirect": "(indirect)", + "turn": { + "no_left_turn": "NO Left Turn {indirect}", + "no_right_turn": "NO Right Turn {indirect}", + "no_u_turn": "NO U-Turn {indirect}", + "no_straight_on": "NO Straight On {indirect}", + "only_left_turn": "ONLY Left Turn {indirect}", + "only_right_turn": "ONLY Right Turn {indirect}", + "only_u_turn": "ONLY U-Turn {indirect}", + "only_straight_on": "ONLY Straight On {indirect}", + "allowed_left_turn": "Left Turn Allowed {indirect}", + "allowed_right_turn": "Right Turn Allowed {indirect}", + "allowed_u_turn": "U-Turn Allowed {indirect}", + "allowed_straight_on": "Straight On Allowed {indirect}" + }, + "from": "FROM", + "via": "VIA", + "to": "TO", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Click to select a {from} segment", + "select_from_name": "Click to select {from} {fromName}", + "toggle": "Click for \"{turn}\"" + } + }, "undo": { "tooltip": "Undo: {action}", "nothing": "Nothing to undo." @@ -363,6 +408,7 @@ "key": "H", "title": "History", "selected": "{n} selected", + "no_history": "No History (New Feature)", "version": "Version", "last_edit": "Last Edit", "edited_by": "Edited By", @@ -380,6 +426,8 @@ "title": "Measurement", "selected": "{n} selected", "geometry": "Geometry", + "closed_line": "closed line", + "closed_area": "closed area", "center": "Centre", "perimeter": "Perimeter", "length": "Length", @@ -387,7 +435,8 @@ "centroid": "Centroid", "location": "Location", "metric": "Metric", - "imperial": "Imperial" + "imperial": "Imperial", + "node_count": "Number of nodes" } }, "geometry": { @@ -453,13 +502,23 @@ "title": "Background", "description": "Background settings", "key": "B", + "backgrounds": "Backgrounds", "none": "None", "best_imagery": "Best known imagery source for this location", "switch": "Switch back to this background", "custom": "Custom", "custom_button": "Edit custom background", + "custom_prompt": "Enter a tile URL template. Valid tokens are:\n - {zoom} or {z}, {x}, {y} for Z/X/Y tile scheme\n - {-y} or {ty} for flipped TMS-style Y coordinates\n - {u} for quadtile scheme\n - {switch:a,b,c} for DNS server multiplexing\n\nExample:\n{example}", + "overlays": "Overlays", + "imagery_source_faq": "Imagery Info / Report a Problem", "reset": "reset", + "display_options": "Display Options", + "brightness": "Brightness", + "contrast": "Contrast", + "saturation": "Saturation", + "sharpness": "Sharpness", "minimap": { + "description": "Show Minimap", "tooltip": "Show a zoomed out map to help locate the area currently displayed.", "key": "/" }, @@ -561,6 +620,7 @@ "status_code": "Server returned status code {code}", "unknown_error_details": "Please ensure you are connected to the Internet.", "uploading": "Uploading changes to OpenStreetMap...", + "conflict_progress": "Checking for conflicts: {num} of {total}", "unsaved_changes": "You have unsaved changes", "conflict": { "header": "Resolve conflicting edits", @@ -586,15 +646,20 @@ } }, "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.", + "thank_you": "Thank you for improving the map.", + "thank_you_location": "Thank you for improving the map around {where}.", + "help_html": "Your changes should appear on OpenStreetMap within a few minutes. It may take longer for maps elsewhere to receive updates.", "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" + "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", + "view_on_osm": "View Changes on OSM", + "changeset_id": "Your changeset #: {changeset_id}", + "like_osm": "Like OpenStreetMap? Connect with others:", + "more": "More", + "events": "Events", + "languages": "Languages: {languages}", + "missing": "Is something missing from this list?", + "tell_us": "Tell us!" }, "confirm": { "okay": "OK", @@ -632,6 +697,7 @@ "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: {p} nodes, {l} lines, {a} areas, {r} relations. 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}" }, @@ -828,6 +894,44 @@ "using": "To use a GPS trace for mapping, drag and drop the data file onto the map editor. If it's recognized, it will be drawn on the map as a bright purple line. Click the {data} **Map data** panel on the side of the map to enable, disable, or zoom to your GPS data.", "tracing": "The GPS track isn't sent to OpenStreetMap - the best way to use it is to draw on the map, using it as a guide for the new features that you add.", "upload": "You can also [upload your GPS data to OpenStreetMap](https://www.openstreetmap.org/trace/create) for other users to use." + }, + "field": { + "restrictions": { + "title": "Turn Restrictions Help", + "about": { + "title": "About", + "about": "This field allows you to inspect and modify turn restrictions. It displays a model of the selected intersection including other nearby connected roads.", + "from_via_to": "A turn restriction always contains: one **FROM way**, one **TO way**, and either one **VIA node** or one or more **VIA ways**.", + "maxdist": "The \"{distField}\" slider controls how far to search for additional connected roads.", + "maxvia": "The \"{viaField}\" slider adjusts how many via ways may be included in the search. (Tip: simple is better)" + }, + "inspecting": { + "title": "Inspecting", + "about": "Hover over any **FROM** segment to see whether it has any turn restrictions. Each possible **TO** destination will be drawn with a colored shadow showing whether a restriction exists.", + "from_shadow": "{fromShadow} **FROM segment**", + "allow_shadow": "{allowShadow} **TO Allowed**", + "restrict_shadow": "{restrictShadow} **TO Restricted**", + "only_shadow": "{onlyShadow} **TO Only**", + "restricted": "\"Restricted\" means that there is a turn restriction, for example \"No Left Turn\".", + "only": "\"Only\" means that a vehicle taking that path may only make that choice, for example \"Only Straight On\"." + }, + "modifying": { + "title": "Modifying", + "about": "To modify turn restrictions, first click on any starting **FROM** segment to select it. The selected segment will pulse, and all possible **TO** destinations will appear as turn symbols.", + "indicators": "Then, click on a turn symbol to toggle it between \"Allowed\", \"Restricted\", and \"Only\".", + "allow_turn": "{allowTurn} **TO Allowed**", + "restrict_turn": "{restrictTurn} **TO Restricted**", + "only_turn": "{onlyTurn} **TO Only**" + }, + "tips": { + "title": "Tips", + "simple": "**Prefer simple restrictions over complex ones.**", + "simple_example": "For example, avoid creating a via-way restriction if a simpler via-node turn restriction will do.", + "indirect": "**Some restrictions display the text \"(indirect)\" and are drawn lighter.**", + "indirect_example": "These restrictions exist because of another nearby restriction. For example, an \"Only Straight On\" restriction will indirectly create \"No Turn\" restrictions for all other paths through the intersection.", + "indirect_noedit": "You may not edit indirect restrictions. Instead, edit the nearby direct restriction." + } + } } }, "intro": { @@ -1135,7 +1239,8 @@ "title": "Selecting features", "select_one": "Select a single feature", "select_multi": "Select multiple features", - "lasso": "Draw a selection lasso around features" + "lasso": "Draw a selection lasso around features", + "search": "Find features matching search text" }, "with_selected": { "title": "With feature selected", @@ -1197,6 +1302,28 @@ } } }, + "units": { + "feet": "{quantity} ft", + "miles": "{quantity} mi", + "square_feet": "{quantity} sq ft", + "square_miles": "{quantity} sq mi", + "acres": "{quantity} ac", + "meters": "{quantity} m", + "kilometers": "{quantity} km", + "square_meters": "{quantity} m²", + "square_kilometers": "{quantity} km²", + "hectares": "{quantity} ha", + "area_pair": "{area1} ({area2})", + "arcdegrees": "{quantity}°", + "arcminutes": "{quantity}′", + "arcseconds": "{quantity}″", + "north": "N", + "south": "S", + "east": "E", + "west": "W", + "coordinate": "{coordinate}{direction}", + "coordinate_pair": "{latitude}, {longitude}" + }, "presets": { "categories": { "category-barrier": { @@ -2049,7 +2176,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telephone", "placeholder": "+44 1632 961234" }, "piste/difficulty": { @@ -2461,9 +2587,6 @@ "label": "Type", "placeholder": "Default" }, - "vending": { - "label": "Type of Goods" - }, "visibility": { "label": "Visibility", "options": { @@ -4956,15 +5079,6 @@ "type/restriction/no_u_turn": { "name": "No U-turn" }, - "type/restriction/only_left_turn": { - "name": "Left Turn Only" - }, - "type/restriction/only_right_turn": { - "name": "Right Turn Only" - }, - "type/restriction/only_straight_on": { - "name": "No Turns" - }, "type/route": { "name": "Route" }, @@ -5082,7 +5196,7 @@ "attribution": { "text": "Terms & Feedback" }, - "description": "Imagery boundaries and capture dates. Labels appear at zoom level 14 and higher.", + "description": "Imagery boundaries and capture dates. Labels appear at zoom level 13 and higher.", "name": "DigitalGlobe Premium Imagery Vintage" }, "DigitalGlobe-Standard": { @@ -5096,7 +5210,7 @@ "attribution": { "text": "Terms & Feedback" }, - "description": "Imagery boundaries and capture dates. Labels appear at zoom level 14 and higher.", + "description": "Imagery boundaries and capture dates. Labels appear at zoom level 13 and higher.", "name": "DigitalGlobe Standard Imagery Vintage" }, "EsriWorldImagery": { @@ -5106,6 +5220,13 @@ "description": "Esri world imagery.", "name": "Esri World Imagery" }, + "EsriWorldImageryClarity": { + "attribution": { + "text": "Terms & Feedback" + }, + "description": "Esri archive imagery that may be clearer and more accurate than the default layer.", + "name": "Esri World Imagery (Clarity) Beta" + }, "MAPNIK": { "attribution": { "text": "© OpenStreetMap contributors, CC-BY-SA" @@ -5173,26 +5294,44 @@ "description": "Yellow = Public domain map data from the US Census. Red = Data not found in OpenStreetMap", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "name": "U.S. Forest Roads Overlay" + }, "Waymarked_Trails-Cycling": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + }, "name": "Waymarked Trails: Cycling" }, "Waymarked_Trails-Hiking": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + }, "name": "Waymarked Trails: Hiking" }, "Waymarked_Trails-MTB": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + }, "name": "Waymarked Trails: MTB" }, "Waymarked_Trails-Skating": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + }, "name": "Waymarked Trails: Skating" }, "Waymarked_Trails-Winter_Sports": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + }, "name": "Waymarked Trails: Winter Sports" }, "basemap.at": { "attribution": { "text": "basemap.at" }, - "description": "Basemap of Austria, based on goverment data.", + "description": "Basemap of Austria, based on government data.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -5254,7 +5393,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Map tiles by Stamen Design, under CC BY 3.0" + "text": "Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL" }, "name": "Stamen Terrain" }, @@ -5270,6 +5409,57 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area OpenStreetMappers", + "description": "Improve OpenStreetMap in the Bay Area", + "extendedDescription": "This group is about growing the OpenStreetMap community here in the Bay Area. Our events are open to everyone, from open source enthusiasts, cyclists, GIS professionals, geocachers, and beyond. Anyone and everyone who is interested in maps, map making and free map data is welcome to join our group as well as attend our events." + }, + "Central-Pennsylvania-OSM": { + "name": "Central Pennsylvania OSM", + "description": "Online mapping community based out of State College, PA" + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "The OpenStreetMap user group for Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth, and all the cities in between are abounding with creative and tech-savvy people. The vision for this usergroup is to find new ways to use the amazing resource of OSM." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Meetup for map enthusiasts in the Philadelphia area", + "extendedDescription": "GeoPhilly unites developers, geographers, data geeks, open source enthusiasts, civic hackers and map addicts in our shared love of maps and the stories they tell. If you use maps as part of your work or just want to learn more, this is the meetup for you! Our events aim to be open, friendly, educational and social and range from happy hours to lightning talks or even workshops. Come create a diverse, inspiring geospatial community in the Philadelphia with us!" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC", + "description": "Improve OpenStreetMap in the DC area", + "extendedDescription": "We are a group of volunteer mappers who aim to improve the OpenStreetMap in the DC area. We also aim to teach others about the OSM ecosystem, data analytics, cartography, and GIS. We gather every other month at meetups to focus on one area of our city." + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "The OpenStreetMap user group for Chattanooga" + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Mappers and OpenStreetMap users, developers and enthusiasts in the New York Metropolitan area" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Mappers and OpenStreetMap users in the Portland area", + "extendedDescription": "OpenStreetMap (OSM) is a map of the world made by people like you. It's a map that you build, that's given away for free like wikipedia. Check out osm.org for more, and come join us at a meetup to talk maps, contribute to OSM, and have fun!" + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack", + "description": "All are welcome! Sign up at {signupUrl}" + }, + "Maptime-Australia-Slack": { + "name": "Maptime Australia Slack", + "description": "Sign up at {signupUrl}" + }, + "OSM-Reddit": { + "name": "OpenStreetMap on Reddit", + "description": "/r/openstreetmap/ is a great place to learn more about OpenStreetMap. Ask us anything!" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/en.json b/vendor/assets/iD/iD/locales/en.json index ca16b9f29..21f290b37 100644 --- a/vendor/assets/iD/iD/locales/en.json +++ b/vendor/assets/iD/iD/locales/en.json @@ -1,5 +1,10 @@ { "en": { + "icons": { + "information": "info", + "remove": "remove", + "undo": "undo" + }, "modes": { "add_area": { "title": "Area", @@ -145,7 +150,9 @@ "vertex": "Connected a way to another.", "line": "Connected a way to a line.", "area": "Connected a way to an area." - } + }, + "relation": "These features can't be connected because they have conflicting relation roles.", + "restriction": "These features can't be connected because it would damage a \"{relation}\" relation." }, "disconnect": { "title": "Disconnect", @@ -163,7 +170,8 @@ "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.", + "restriction": "These features can't be merged because it would damage a \"{relation}\" relation.", + "relation": "These features can't be merged because they have conflicting relation roles.", "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." }, @@ -402,6 +410,7 @@ "key": "H", "title": "History", "selected": "{n} selected", + "no_history": "No History (New Feature)", "version": "Version", "last_edit": "Last Edit", "edited_by": "Edited By", @@ -639,15 +648,20 @@ } }, "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.", + "thank_you": "Thank you for improving the map.", + "thank_you_location": "Thank you for improving the map around {where}.", + "help_html": "Your changes should appear on OpenStreetMap within a few minutes. It may take longer for maps elsewhere to receive updates.", "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" + "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", + "view_on_osm": "View Changes on OSM", + "changeset_id": "Your changeset #: {changeset_id}", + "like_osm": "Like OpenStreetMap? Connect with others:", + "more": "More", + "events": "Events", + "languages": "Languages: {languages}", + "missing": "Is something missing from this list?", + "tell_us": "Tell us!" }, "confirm": { "okay": "OK", @@ -1774,6 +1788,9 @@ "display": { "label": "Display" }, + "distance": { + "label": "Total Distance" + }, "dock": { "label": "Type" }, @@ -1814,6 +1831,9 @@ "except": { "label": "Exceptions" }, + "faces": { + "label": "Faces" + }, "fax": { "label": "Fax", "placeholder": "+31 42 123 4567" @@ -1925,6 +1945,39 @@ "label": "Hoops", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Dressage Riding", + "options": { + "undefined": "No", + "equestrian": "Yes" + } + }, + "horse_riding": { + "label": "Horseback Riding", + "options": { + "undefined": "No", + "horse_riding": "Yes" + } + }, + "horse_scale": { + "label": "Horseback Riding Difficulty", + "placeholder": "Difficult, Dangerous...", + "options": { + "common": "Easy: No problems or difficulties. (default)", + "demanding": "Use with caution: Uneven way, occasional difficult passages.", + "difficult": "Difficult: Way narrow and exposed. May contain obstacles to step over and narrow passages.", + "critical": "Borderline: Passable only for experienced riders and horses. Major obstacles. Bridges should be examined carefully.", + "dangerous": "Dangerous: Passable only for very experienced riders and horses and only in good weather. Dismount.", + "impossible": "Impassable: Way or bridge not passable for horses. Too narrow, insuffient support, obstacles like ladders. Danger of life." + } + }, + "horse_stables": { + "label": "Riding Stable", + "options": { + "undefined": "No", + "stables": "Yes" + } + }, "iata": { "label": "IATA" }, @@ -1944,6 +1997,9 @@ "indoor": { "label": "Indoor" }, + "industrial": { + "label": "Type" + }, "information": { "label": "Type" }, @@ -2064,6 +2120,10 @@ "label": "Speed Limit", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "Advisory Speed Limit", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Max Stay" }, @@ -2217,7 +2277,7 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Phone", + "label": "Telephone", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2652,8 +2712,19 @@ "label": "Type", "placeholder": "Default" }, + "usage_rail": { + "label": "Usage Type", + "options": { + "main": "Main", + "branch": "Branch", + "industrial": "Industrial", + "military": "Military", + "test": "Test", + "tourism": "Tourism" + } + }, "vending": { - "label": "Type of Goods" + "label": "Types of Goods" }, "visibility": { "label": "Visibility", @@ -2788,6 +2859,10 @@ "name": "Billboard", "terms": "" }, + "advertising/column": { + "name": "Advertising Column", + "terms": "" + }, "aerialway/station": { "name": "Aerialway Station", "terms": "" @@ -2868,6 +2943,10 @@ "name": "Airport Terminal", "terms": "airport,aerodrome" }, + "allotments/plot": { + "name": "Community Garden Plot", + "terms": "" + }, "amenity/bus_station": { "name": "Bus Station / Terminal", "terms": "" @@ -3112,6 +3191,10 @@ "name": "Marketplace", "terms": "" }, + "amenity/monastery": { + "name": "Monastery Grounds", + "terms": "abbey,basilica,bethel,cathedral,chancel,chantry,chapel,church,fold,house of God,house of prayer,house of worship,minster,mission,monastery,mosque,oratory,parish,sacellum,sanctuary,shrine,synagogue,tabernacle,temple" + }, "amenity/motorcycle_parking": { "name": "Motorcycle Parking", "terms": "" @@ -3308,6 +3391,10 @@ "name": "Cigarette Vending Machine", "terms": "cigarette" }, + "amenity/vending_machine/coffee": { + "name": "Coffee Vending Machine", + "terms": "coffee" + }, "amenity/vending_machine/condoms": { "name": "Condom Vending Machine", "terms": "condom" @@ -3316,6 +3403,14 @@ "name": "Drink Vending Machine", "terms": "drink,soda,beverage,juice,pop" }, + "amenity/vending_machine/electronics": { + "name": "Electronics Vending Machine", + "terms": "cable,charger,earbud,headphone,phone,tablet" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Flat Coin Vending Machine", + "terms": "coin,crush,elongated,flatten,penny,souvenir" + }, "amenity/vending_machine/excrement_bags": { "name": "Excrement Bag Vending Machine", "terms": "excrement bags,poop,dog,animal" @@ -3324,6 +3419,18 @@ "name": "Feminine Hygiene Vending Machine", "terms": "condom,tampon,pad,woman,women,menstrual hygiene products,personal care" }, + "amenity/vending_machine/food": { + "name": "Food Vending Machine", + "terms": "food" + }, + "amenity/vending_machine/fuel": { + "name": "Gas Pump", + "terms": "petrol,fuel,gasoline,propane,diesel,lng,cng,biodiesel" + }, + "amenity/vending_machine/ice_cream": { + "name": "Ice Cream Vending Machine", + "terms": "chocolate,ice cream,frozen,popsicle,vanilla" + }, "amenity/vending_machine/newspapers": { "name": "Newspaper Vending Machine", "terms": "newspaper" @@ -3340,6 +3447,10 @@ "name": "Transit Ticket Vending Machine", "terms": "bus,train,ferry,rail,ticket,transportation" }, + "amenity/vending_machine/stamps": { + "name": "Postage Vending Machine", + "terms": "mail,postage,stamp" + }, "amenity/vending_machine/sweets": { "name": "Snack Vending Machine", "terms": "candy,gum,chip,pretzel,cookie,cracker" @@ -3412,6 +3523,10 @@ "name": "Drop Tower", "terms": "theme park,amusement ride,gondola,tower,big drop" }, + "attraction/maze": { + "name": "Maze", + "terms": "theme park,amusement ride,labyrinth" + }, "attraction/pirate_ship": { "name": "Pirate Ship", "terms": "theme park,carnival ride,amusement ride" @@ -3600,6 +3715,10 @@ "name": "Garages", "terms": "" }, + "building/grandstand": { + "name": "Grandstand", + "terms": "tribune,stand,stands,bleachers" + }, "building/greenhouse": { "name": "Greenhouse", "terms": "" @@ -4052,6 +4171,10 @@ "name": "Hospice", "terms": "terminal,illness" }, + "healthcare/laboratory": { + "name": "Medical Laboratory", + "terms": "medical_laboratory,medical_lab,blood_check" + }, "healthcare/midwife": { "name": "Midwife", "terms": "baby,childbirth,delivery,labour,labor,pregnancy" @@ -4152,6 +4275,10 @@ "name": "Motorway", "terms": "autobahn,expressway,freeway,highway,interstate,parkway,thruway,turnpike" }, + "highway/passing_place": { + "name": "Passing Place", + "terms": "turnout, pullout" + }, "highway/path": { "name": "Path", "terms": "hike,hiking,trackway,trail,walk" @@ -4298,7 +4425,7 @@ }, "historic/memorial": { "name": "Memorial", - "terms": "" + "terms": "dedicatory,epitaph,remember,remembrance,memory,monument,stolperstein" }, "historic/monument": { "name": "Monument", @@ -4374,7 +4501,7 @@ }, "landuse/forest": { "name": "Forest", - "terms": "tree" + "terms": "cut,forest,lumber,tree" }, "landuse/garages": { "name": "Garage Landuse", @@ -4512,6 +4639,10 @@ "name": "Amusement Arcade", "terms": "pay-to-play games,video games,driving simulators,pinball machines" }, + "leisure/beach_resort": { + "name": "Beach Resort", + "terms": "" + }, "leisure/bird_hide": { "name": "Bird Hide", "terms": "machan,ornithology" @@ -4628,6 +4759,10 @@ "name": "Nature Reserve", "terms": "protected,wildlife" }, + "leisure/outdoor_seating": { + "name": "Outdoor Seating Area", + "terms": "al fresco,beer garden,dining,cafe,restaurant,pub,bar,patio" + }, "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" @@ -4760,6 +4895,10 @@ "name": "Adit", "terms": "entrance,underground,mine,cave" }, + "man_made/antenna": { + "name": "Antenna", + "terms": "broadcast,cell phone,cell,communication,mobile phone,radio,television,transmission,tv" + }, "man_made/breakwater": { "name": "Breakwater", "terms": "" @@ -4772,6 +4911,10 @@ "name": "Chimney", "terms": "" }, + "man_made/clearcut": { + "name": "Clearcut Forest", + "terms": "cut,forest,lumber,tree,wood" + }, "man_made/crane": { "name": "Crane", "terms": "" @@ -4808,6 +4951,10 @@ "name": "Observation Tower", "terms": "lookout tower,fire tower" }, + "man_made/observatory": { + "name": "Observatory", + "terms": "astronomical,meteorological" + }, "man_made/petroleum_well": { "name": "Oil Well", "terms": "drilling rig,oil derrick,oil drill,oil horse,oil rig,oil pump,petroleum well,pumpjack" @@ -4932,10 +5079,18 @@ "name": "Heath", "terms": "" }, + "natural/mud": { + "name": "Mud", + "terms": "wetland" + }, "natural/peak": { "name": "Peak", "terms": "acme,aiguille,alp,climax,crest,crown,hill,mount,mountain,pinnacle,summit,tip,top" }, + "natural/reef": { + "name": "Reef", + "terms": "barrier,coral,ocean,sand,shoal" + }, "natural/ridge": { "name": "Ridge", "terms": "crest" @@ -5968,6 +6123,10 @@ "name": "Perfume Store", "terms": "" }, + "shop/pet_grooming": { + "name": "Pet Grooming Store", + "terms": "dog" + }, "shop/pet": { "name": "Pet Store", "terms": "animal,cat,dog,fish,kitten,puppy,reptile" @@ -6188,6 +6347,10 @@ "name": "Theme Park", "terms": "" }, + "tourism/trail_riding_station": { + "name": "Trail Riding Station", + "terms": "" + }, "tourism/viewpoint": { "name": "Viewpoint", "terms": "" @@ -6273,15 +6436,19 @@ "terms": "" }, "type/restriction/only_left_turn": { - "name": "Left Turn Only", + "name": "Only Left Turn", "terms": "" }, "type/restriction/only_right_turn": { - "name": "Right Turn Only", + "name": "Only Right Turn", "terms": "" }, "type/restriction/only_straight_on": { - "name": "No Turns", + "name": "Only Straight On", + "terms": "" + }, + "type/restriction/only_u_turn": { + "name": "Only U-turn", "terms": "" }, "type/route_master": { @@ -6442,7 +6609,7 @@ "attribution": { "text": "Terms & Feedback" }, - "description": "Imagery boundaries and capture dates. Labels appear at zoom level 14 and higher.", + "description": "Imagery boundaries and capture dates. Labels appear at zoom level 13 and higher.", "name": "DigitalGlobe Premium Imagery Vintage" }, "DigitalGlobe-Standard": { @@ -6456,7 +6623,7 @@ "attribution": { "text": "Terms & Feedback" }, - "description": "Imagery boundaries and capture dates. Labels appear at zoom level 14 and higher.", + "description": "Imagery boundaries and capture dates. Labels appear at zoom level 13 and higher.", "name": "DigitalGlobe Standard Imagery Vintage" }, "EsriWorldImagery": { @@ -6540,6 +6707,10 @@ "description": "Yellow = Public domain map data from the US Census. Red = Data not found in OpenStreetMap", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Highway: Green casing = unclassified. Brown casing = track. Surface: gravel = light brown fill, Asphalt = black, paved = gray, ground =white, concrete = blue, grass = green. Seasonal = white bars", + "name": "U.S. Forest Roads Overlay" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" @@ -6574,7 +6745,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Basemap of Austria, based on goverment data.", + "description": "Basemap of Austria, based on government data.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6636,7 +6807,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Map tiles by Stamen Design, under CC BY 3.0" + "text": "Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL" }, "name": "Stamen Terrain" }, @@ -6652,6 +6823,762 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "University of Cape Coast YouthMappers", + "description": "Follow us on Twitter: {url}", + "extendedDescription": "This is the official handle for the Youth Mappers chapter of the University of Cape Coast, Ghana. we love maps, open data and helping the vulnerable." + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana on Facebook", + "description": "Facebook group for people interested in OpenStreetMap.", + "extendedDescription": "Mappers in Ghana community, promoting OpenStreetMap and Humanitarian OpenStreetMap Team (HOT) projects in Ghana. Join us." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana on Twitter", + "description": "Follow us on Twitter: {url}" + }, + "talk-gh": { + "name": "Talk-gh Mailing List", + "description": "Talk-gh is the official mailing list for Ghana OSM community." + }, + "osm-mg-facebook": { + "name": "OpenStreetMap Madagascar Facebook Group", + "description": "Malagasy Facebook group for people interested in OpenStreetMap." + }, + "talk-mg": { + "name": "Talk-mg Mailing List", + "description": "Place for OpenStreetMap contributors, communities and users in Madagascar to share and discuss." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesh", + "description": "Improve OpenStreetMap in Bangladesh", + "extendedDescription": "Mapping in Bangladesh? Have questions, want to connect with the community here? Join us at {url}. All are welcome!" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap India - Participatory neighborhood mapping", + "description": "Improve OpenStreetMap in India", + "extendedDescription": "Mapping in India? Have questions, want to connect with the community here? Join us at {url}. All are welcome!", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "description": "Join the 2018 OpenStreetMap region-wide event at State of the Map Asia in India", + "where": "Indian Institute of Management, Bangalore, India" + } + } + }, + "OSM-india-mailinglist": { + "name": "OpenStreetMap India Mailinglist", + "description": "Talk-in is the official Mailinglist for Indian Community" + }, + "OSM-india-twitter": { + "name": "OpenStreetMap India Twitter", + "description": "We are just a tweet away: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Free Software Hardware Movement - Facebook", + "description": "FSHM Facebook page to know about community events, activities", + "extendedDescription": "FSHM organizes events relating to free software/hardware, technology, activism and OpenStreetMap. Its FB page is the best way to keep in contact with its events." + }, + "OSM-India-Puducherry-Matrix": { + "name": "Free Software Hardware Movement - Matrix", + "description": "FSHM Riot group to discuss, share and update mapping activities, events in and around Puducherry", + "extendedDescription": "FSHM community members share their OSM mapping updates / experiences through the Riot.im group, this group is also used to discuss things related to free software / hardware, technology and activism." + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonesia", + "description": "Improve OpenStreetMap in Indonesia", + "extendedDescription": "Mapping in Indonesia? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-japan-facebook": { + "name": "OpenStreetMap Japan Community", + "description": "Mappers and OpenStreetMap users in Japan" + }, + "OSM-japan-mailinglist": { + "name": "OpenStreetMap Japan Mailinglist", + "description": "Talk-ja is an Official Mailinglist for Japanese Community" + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap Japan Twitter", + "description": "Hashtag on Twitter: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap Japan", + "description": "Mappers and OpenStreetMap users in Japan" + }, + "OSM-korea-telegram": { + "name": "OSM Korea Telegram Channel", + "description": "Unofficial Channnel for OpenStreetMap contributors, communities and users in Korea to share and discuss." + }, + "OSM-MY-facebook": { + "name": "OpenStreetMap Malaysia on Facebook", + "description": "For chat about anything related to OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "OpenStreetMap Malaysia Forum", + "description": "Official OpenStreetMap Malaysia Forum" + }, + "OSM-MY-matrix": { + "name": "OpenStreetMap Malaysia Riot channel", + "description": "All mappers are welcome! Sign up at {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongolia", + "description": "Improve OpenStreetMap in Mongolia", + "extendedDescription": "Mapping in Mongolia? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Myanmar", + "description": "Improve OpenStreetMap in Myanmar", + "extendedDescription": "Mapping in Myanmar? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Nepal", + "description": "Improve OpenStreetMap in Nepal", + "extendedDescription": "Mapping in Nepal? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-PH-facebook": { + "name": "OpenStreetMap PH Facebook", + "description": "Welcome to OpenStreetMap Philippines, where we encourage all fellow Filipinos to contribute to the OpenStreetMap project." + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph Mailing List", + "description": "A mailing list to discuss OpenStreetMap in the Philippines" + }, + "OSM-PH-slack": { + "name": "OpenStreetMap PH Slack", + "description": "All are welcome! Sign up at {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "OpenStreetMap PH Telegram", + "description": "Un-official, Telegram local community of OpenStreetMap contributors and friends in the Philippines" + }, + "OSM-RU-forum": { + "name": "OpenStreetMap RU forum", + "description": "OpenStreetMap Russia web forum" + }, + "OSM-RU-telegram": { + "name": "OpenStreetMap RU telegram", + "description": "OpenStreetMap Russia telegram chat" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka", + "description": "Improve OpenStreetMap in Sri Lanka", + "extendedDescription": "Mapping in Sri Lanka? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-TW-facebook": { + "name": "OpenStreetMap Taiwan Community", + "description": "Facebook Group for Mappers and OpenStreetMap users to discuss matters about Taiwan." + }, + "OSM-TW-mailinglist": { + "name": "OpenStreetMap Taiwan Mailinglist", + "description": "Talk-tw is an Official Mailinglist for the Communities to dicuss matters about Taiwan" + }, + "OSM-TH-CNX-meetup": { + "name": "OSM Meetup Chiang Mai", + "description": "Irregular meeting of the OpenStreetMap community in Chiang Mai", + "extendedDescription": "Members of the OpenStreetMap community meet every few months in Chiang Mai. Get in contact and check out {url} to see when the next meetup is scheduled" + }, + "OSM-TH-forum": { + "name": "OpenStreetMap TH forum", + "description": "OpenStreetMap Thailand web forum" + }, + "al-forum": { + "name": "OSM Albania Forum", + "description": "OpenStreetMap Albania Forum" + }, + "al-maptime-tirana": { + "name": "Maptime Tirana", + "description": "Social events organized around mapping - beginners most welcome!", + "extendedDescription": "Maptime is an open learning environment for all levels and degrees of knowledge, offering intentional educational support for the beginner. Maptime is simultaneously flexible and structured, creating space for mapping tutorials, workshops, ongoing projects with a shared goal, and independent/collaborative work time." + }, + "al-telegram": { + "name": "OSM Albania Telegram channel", + "description": "OpenStreetMap Albania Telegram channel" + }, + "at-forum": { + "name": "OpenStreetMap Austria Forum", + "description": "The official forum for OpenStreetMap questions in and around Austria" + }, + "at-mailinglist": { + "name": "Talk-at Mailing List", + "description": "Talk-at is the official mailing list for the Austrian OSM community" + }, + "at-twitter": { + "name": "OpenStreetMap Austria Twitter", + "description": "OpenStreetMap Austria On Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "OSM community meetup Graz", + "description": "Monthly meetup of the OpenStreetMap community in Graz" + }, + "osmgraz-twitter": { + "name": "OSM community Graz on twitter", + "description": "OpenStreetMap community in Graz on twitter" + }, + "osm-at": { + "name": "OpenStreetMap Austria", + "description": "The platform for information on OpenStreetMap in Austria" + }, + "byosm": { + "name": "OpenStreetMap Belarus", + "description": "OpenStreetMap Belarus telegram chat" + }, + "be-facebook": { + "name": "OpenStreetMap BE Community", + "description": "Mappers and OpenStreetMap on Facebook in Belgium" + }, + "be-forum": { + "name": "OpenStreetMap BE forum", + "description": "OpenStreetMap Belgium web forum" + }, + "be-irc": { + "name": "OpenStreetMap Belgium IRC", + "description": "Join #osmbe on irc.oftc.net (port 6667)", + "extendedDescription": "Join #osmbe on irc.oftc.net (port 6667), it is bridged with the Matrix chat channel" + }, + "be-mailinglist": { + "name": "Talk-be Mailing List", + "description": "Talk-be is the official mailing list for the Belgian OSM community" + }, + "be-maptime": { + "name": "Maptime Belgium", + "description": "Social events organized around mapping - beginners most welcome!", + "extendedDescription": "Maptime is an open learning environment for all levels and degrees of knowledge, offering intentional educational support for the beginner. Maptime is simultaneously flexible and structured, creating space for mapping tutorials, workshops, ongoing projects with a shared goal, and independent/collaborative work time." + }, + "be-matrix": { + "name": "OpenStreetMap BE Matrix channel", + "description": "All mappers are welcome!", + "extendedDescription": "Most talk is happening at the \"OpenStreetMap Belgium\" channel. You can ask anything there! The other rooms are for specific subjects." + }, + "be-meetup": { + "name": "OpenStreetMap Belgium Meetup", + "description": "Real life meetups of everyone who is interested in OpenStreetMap", + "extendedDescription": "Physical meetups are great to meet other mappers, ask them questions and to learn a lot. Especially new contributors are very welcome!" + }, + "be-twitter": { + "name": "OpenStreetMap Belgium Twitter", + "description": "OSM Belgium on Twitter: @osm_be" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz Mailing List", + "description": "Talk-cz is the official mailing list for Czech community" + }, + "dk-forum": { + "name": "OpenStreetMap Denmark Web Forum", + "description": "OpenStreetMap Denmark web forum" + }, + "dk-irc": { + "name": "OpenStreetMap Denmark IRC", + "description": "Join #osm-dk on irc.oftc.net (port 6667)" + }, + "dk-mailinglist": { + "name": "Talk-dk Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Denmark" + }, + "fi-forum": { + "name": "OpenStreetMap FI forum", + "description": "OpenStreetMap Finland web forum" + }, + "fi-irc": { + "name": "OpenStreetMap Finland IRC", + "description": "Join #osm-fi on irc.oftc.net (port 6667)" + }, + "fi-mailinglist": { + "name": "Talk-fi Mailing List", + "description": "Talk-fi is the official mailing list for the Finnish OSM community" + }, + "fr-facebook": { + "name": "OpenStreetMap France Facebook page", + "description": "OpenStreetMap France Facebook page" + }, + "fr-forum": { + "name": "OpenStreetMap France web forum", + "description": "OpenStreetMap France web forum" + }, + "fr-irc": { + "name": "OpenStreetMap France on IRC", + "description": "Join #osm-fr on irc.oftc.net (port 6667)" + }, + "fr-mailinglist": { + "name": "Talk-fr Mailing List", + "description": "Talk-fr mailing list" + }, + "fr-twitter": { + "name": "OpenStreetMap France on Twitter", + "description": "OpenStreetMap France on Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "Berlin Mailing List", + "description": "This is the mailing list for the Berlin OSM community" + }, + "de-berlin-meetup": { + "name": "OpenStreetMap Berlin-Brandenburg Meetup", + "description": "Mappers and OpenStreetMap users in the Berlin area" + }, + "de-berlin-telegram": { + "name": "@osmberlin on Telegram", + "description": "OpenStreetMap Berlin Telegram chat" + }, + "de-berlin-twitter": { + "name": "OpenStreetMap Berlin Twitter", + "description": "Follow us on Twitter: {url}" + }, + "de-forum": { + "name": "OpenStreetMap DE forum", + "description": "OpenStreetMap Germany web forum" + }, + "de-irc": { + "name": "OpenStreetMap Germany IRC", + "description": "Join #osm-de on irc.oftc.net (port 6667)" + }, + "de-mailinglist": { + "name": "Talk-de Mailing List", + "description": "Talk-de is the official mailing list for the German OSM community" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "OWL Mailing List", + "description": "This is the mailing list for the Ostwestfalen-Lippe OSM community" + }, + "osm-de": { + "name": "OpenStreetMap Germany", + "description": "The platform for information on OpenStreetMap in Germany" + }, + "hu-facebook": { + "name": "OpenStreetMap HU on Facebook", + "description": "Mappers and OpenStreetMap Facebook in Hungary" + }, + "hu-forum": { + "name": "OpenStreetMap HU forum", + "description": "OpenStreetMap Hungary web forum" + }, + "hu-meetup": { + "name": "OpenStreetMap Hungary Meetup", + "description": "The platform for organizing meetups in Hungary" + }, + "it-facebook": { + "name": "OpenStreetMap Italy Facebook", + "description": "Join the OpenStreetMap Italy community on Facebook" + }, + "it-irc": { + "name": "OpenStreetMap Italy IRC", + "description": "Join #osm-it on irc.oftc.net (port 6667)" + }, + "it-mailinglist": { + "name": "Talk-it Mailing List", + "description": "Talk-it is the official mailing list for the Italian OSM community" + }, + "it-telegram": { + "name": "@OpenStreetMapItalia on Telegram", + "description": "OpenStreetMap Italy Telegram chat" + }, + "it-twitter": { + "name": "OpenStreetMap Italy Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSM-Rome-meetup": { + "name": "Incontro Mappatori Romani", + "description": "Improve OpenStreetMap in the Rome area", + "extendedDescription": "We aim to be a resource for people to discuss and share knowledge on utilizing free geographic data sets especially OpenStreetMap, and Open geo-spatial software that manages, edits, and displays geographic data, and advocate for its use in Lazio." + }, + "South-Tyrol-Mailing-List": { + "name": "OpenStreetMap mailing list for South Tyrol", + "description": "OpenStreetMap Italy regional talk list for South Tyrol" + }, + "talk-it-lazio": { + "name": "OpenStreetMap IT Lazio", + "description": "All are welcome! Sign up at {signupUrl}", + "extendedDescription": "Mailinglist for Rome and Lazio area." + }, + "Trentino-Mailing-List": { + "name": "OpenStreetMap mailing list for Trentino", + "description": "OpenStreetMap Italy regional talk list for Trentino" + }, + "no-forum": { + "name": "OpenStreetMap Norway Web Forum", + "description": "OpenStreetMap Norway web forum" + }, + "no-irc": { + "name": "OpenStreetMap Norway on IRC", + "description": "Chat room for mappers and OpenStreetMap users, developers and enthusiasts in Norway" + }, + "no-mailinglist": { + "name": "OpenStreetMap Norway mailing list", + "description": "Mailing list for mappers and OpenStreetMap users, developers and enthusiasts in Norway" + }, + "OSM-PL-facebook-group": { + "name": "OpenStreetMap Poland Facebook group", + "description": "Group for mappers and users of OpenStreetMap in Poland" + }, + "OSM-PL-forum": { + "name": "OpenStreetMap Poland Forum", + "description": "Forum of Polish OpenStreetMap community" + }, + "OSM-ES-mailinglist": { + "name": "Talk-es mailing list", + "description": "A mailing list to discuss OpenStreetMap in Spain" + }, + "OSM-ES-telegram": { + "name": "@OSMes on Telegram", + "description": "OpenStreetMap Spain Telegram chat" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "Provide OSM services and information for the local community in Sweden" + }, + "se-facebook": { + "name": "OpenStreetMap Sweden Facebook", + "description": "OpenStreetMap Sweden on Facebook" + }, + "se-forum": { + "name": "OpenStreetMap Sweden Web Forum", + "description": "OpenStreetMap Sweden web forum" + }, + "se-irc": { + "name": "OpenStreetMap Sweden IRC", + "description": "Join #osm.se on irc.oftc.net (port 6667)" + }, + "se-mailinglist": { + "name": "Talk-se Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Sweden" + }, + "se-twitter": { + "name": "OpenStreetMap Sweden on Twitter", + "description": "Follow us on Twitter: {url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "East Midlands (Nottingham) Monthly pub meet-up", + "description": "Social gathering for East Midlands mappers and users", + "extendedDescription": "A group have been meeting since March 2011, initially in Nottingham, and, more recently in Derby, and from time to time elsewhere in the East Midlands. These are social gatherings, but are an excellent place to come and ask specific questions about OSM either in the area or in general. In the summer months we usually do some light mapping for an hour in the vicinity of our meeting place. The group as a whole has a special interest in mapping public rights of way and from time to time has mapping meetings for this purpose." + }, + "gb-mailinglist": { + "name": "Talk-gb Mailing List", + "description": "Talk-gb is the main communication forum list for the British (including Northern Ireland) OSM community" + }, + "mappa-mercia-group": { + "name": "Mappa Mercia local group", + "description": "A home for OpenStreetMap enthusiasts in the Midlands", + "extendedDescription": "Mappa Mercia is a project to grow OpenStreetMap in the West Midlands, UK. We run community events, provide training and support local organisations wishing to open up their data." + }, + "gb-irc": { + "name": "OpenStreetMap United Kingdom IRC", + "description": "Join #osm-gb on irc.oftc.net (port 6667)", + "extendedDescription": "Join #osm-gb on irc.oftc.net (port 6667), please be patient and wait for a few minutes if you ask a question" + }, + "OSM-CA-Slack": { + "name": "OSM-CA Slack", + "description": "All are welcome! Sign up at {signupUrl}." + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver", + "description": "Mappers and OpenStreetMap users in the Vancouver, BC area" + }, + "OSM-CU-telegram": { + "name": "OSM Cuba on Telegram", + "description": "OpenStreetMap Cuba Telegram chat" + }, + "OSM-NI-telegram": { + "name": "OSM Nicaragua on Telegram", + "description": "OpenStreetMap Nicaragua Telegram chat" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area OpenStreetMappers", + "description": "Improve OpenStreetMap in the Bay Area", + "extendedDescription": "This group is about growing the OpenStreetMap community here in the Bay Area. Our events are open to everyone, from open source enthusiasts, cyclists, GIS professionals, geocachers, and beyond. Anyone and everyone who is interested in maps, map making and free map data is welcome to join our group as well as attend our events." + }, + "Central-Pennsylvania-OSM": { + "name": "Central Pennsylvania OSM", + "description": "Online mapping community based out of State College, PA" + }, + "Code-for-San-Jose-Slack": { + "name": "Code for San Jose Slack", + "description": "All are welcome! Sign up at {signupUrl}, then join the #osm channel." + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "The OpenStreetMap user group for Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth, and all the cities in between are abounding with creative and tech-savvy people. The vision for this usergroup is to find new ways to use the amazing resource of OSM." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Meetup for map enthusiasts in the Philadelphia area", + "extendedDescription": "GeoPhilly unites developers, geographers, data geeks, open source enthusiasts, civic hackers and map addicts in our shared love of maps and the stories they tell. If you use maps as part of your work or just want to learn more, this is the meetup for you! Our events aim to be open, friendly, educational and social and range from happy hours to lightning talks or even workshops. Come create a diverse, inspiring geospatial community in the Philadelphia with us!" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "Mappers and OpenStreetMap enthusiasts in the Twin Cities area", + "extendedDescription": "Connecting OpenStreetMap enthusiasts in Minnesota and the Twin Cities!" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC", + "description": "Improve OpenStreetMap in the DC area", + "extendedDescription": "We are a group of volunteer mappers who aim to improve the OpenStreetMap in the DC area. We also aim to teach others about the OSM ecosystem, data analytics, cartography, and GIS. We gather every other month at meetups to focus on one area of our city." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Mappers and OpenStreetMap users, around Portland, ME", + "extendedDescription": "Maptime is, rather literally, time for mapmaking. Our mission is to open the doors of cartographic possibility to anyone interested by creating a time and space for collaborative learning, exploration, and map creation using mapping tools and technologies." + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Improve OpenStreetMap in the Cleveland area", + "extendedDescription": "Open Geo Cleveland aims to be a resource for people to discuss and share knowledge on utilizing free geographic data sets especially OpenStreetMap, and Open geo-spatial software that manages, edits, and displays geographic data, and advocate for its use in Northeast Ohio. We're also a maptime chapter =)" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Mappers and OpenStreetMap users in the Boston area", + "extendedDescription": "OpenStreetMap is the free and open, wiki-style map of the world, with hundreds of thousands of contributions every day from people like you. Editing the map is simple, and fun! Join us both indoors and outdoors in our effort to create the best map of the Boston area and the rest of the world!" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Central Salish Sea", + "description": "Mappers and OpenStreetMap users around Mount Vernon, WA", + "extendedDescription": "OpenStreetMap is an map of the world made by people like you. It's a map that you build, that's given away for free like wikipedia. Check out osm.org for more. We meet all the time to talk maps, make maps and have fun!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "The OpenStreetMap user group for Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "description": "Mappers and OpenStreetMap users in the state of Colorado, USA", + "extendedDescription": "OpenStreetMap (OSM) Colorado is a local collaboration of people interested in contributing their efforts to create free maps. We encourage all of our mappers to organize or suggest mapping events throughout the state. Meetup activities can be simple social mixers, OSM basic to advanced training, or community mapping parties." + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Mappers and OpenStreetMap users, developers and enthusiasts in the New York Metropolitan area" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Mappers and OpenStreetMap users in the Portland area", + "extendedDescription": "OpenStreetMap (OSM) is a map of the world made by people like you. It's a map that you build, that's given away for free like wikipedia. Check out osm.org for more, and come join us at a meetup to talk maps, contribute to OSM, and have fun!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Mappers and OpenStreetMap users in the Seattle area" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Southern California", + "description": "Let's have some fun, contribute something to Los Angeles, and learn about mapping!", + "extendedDescription": "OpenStreetMap (OSM) Southern California is for anyone interested in mapping to get together to work with OpenStreetMap. OpenStreetMap, the Wikipedia of maps, is a free open-source map of the world being created by more than 1,000,000 volunteers around the globe. Everyone is welcome. If you don't know OpenStreetMap, we'll teach you. If you have an idea for a mapping project or even a field trip that the group can do, great!" + }, + "OSM-South-Bay": { + "name": "OSM South Bay", + "description": "Map Nights hosted by Code for San Jose", + "extendedDescription": "Code for San Jose, the local Code for America brigade, hosts monthly Map Nights on Thursday nights in downtown San José. Meet fellow South Bay mappers, help out with local mapping projects, and hear about other civic tech projects. Programming and GIS skills are not required." + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Tampa Bay", + "description": "Mappers and OpenStreetMap users in the Tampa Bay area", + "extendedDescription": "OSM Tampa Bay group for local residents to get together and build out the definitive map of Tampa Bay with OpenStreetMap, the free and editable map of the world. If you're into maps, data, open source, GPS, hiking, cycling, et cetera, you'll love working with OpenStreetMap -- so join in! We'll get together and map and talk about new topics once-a-month or so." + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack", + "description": "All are welcome! Sign up at {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap US", + "description": "We help grow and improve OpenStreetMap in the United States.", + "extendedDescription": "We support OpenStreetMap by holding annual conferences, providing community resources, building partnerships, and by spreading the word. Join OpenStreetMap US here: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah", + "description": "Mappers and OpenStreetMap users in the Salt Lake City area", + "extendedDescription": "Activities may include things like Learn To Map workshops, mapping parties and outdoor data collection. The events will take place in the SLC area, at least initially. We are looking for seasoned mappers as well as people new to OSM. Join and let's do some mapping!" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming", + "description": "Mappers and OpenStreetMap users in the state of Wyoming", + "extendedDescription": "OpenStreetMap (OSM) Wyoming is a local collaboration of people interested in contributing their efforts to create free maps. We encourage all of our mappers to organize or suggest mapping events throughout the state. Meetup activities can be simple social mixers, OSM basic to advanced training, or community mapping parties." + }, + "PHXGeo-meetup": { + "name": "PHXGeo Meetup", + "description": "Mappers and OpenStreetMap users in the Phoenix, AZ area", + "extendedDescription": "This is a meetup group for those in the Phoenix area who like maps, GIS, OpenStreetMap, cartography and anything in between." + }, + "PHXGeo-twitter": { + "name": "PHXGeo Twitter", + "description": "Follow us on Twitter at {url}" + }, + "Western-Slope-facebook": { + "name": "Western Slope OSM Facebook", + "description": "Mappers and OpenStreetMap users around Grand Junction, CO" + }, + "Western-Slope-meetup": { + "name": "Western Slope OSM Meetup", + "description": "Mappers and OpenStreetMap users around Grand Junction, CO", + "extendedDescription": "The goal of this group is to introduce OpenStreetMap to the community, develop a community of mappers, create the most amazing geodata possible using whatever method we can and finally strategize in order to get this data out into our community. Imagine accurate trail signage! Imagine further development of bike paths! Imagine anything you want, that's the joy of OpenStreetMap!" + }, + "Maptime-Australia-Slack": { + "name": "Maptime Australia Slack", + "description": "Sign up at {signupUrl}" + }, + "talk-au": { + "name": "Talk-au Mailing List", + "description": "Place for Aussie mappers to chat" + }, + "OSM-AR-facebook": { + "name": "OpenStreetMap Argentina Facebook", + "description": "Join the OpenStreetMap Argentina community on Facebook", + "extendedDescription": "News from the local community" + }, + "OSM-AR-forum": { + "name": "OpenStreetMap Argentina web forum", + "description": "Join the OpenStreetMap Argentina web forum", + "extendedDescription": "Ideal for long or important discussions. Slow response time." + }, + "OSM-AR-irc": { + "name": "OpenStreetMap Argentina IRC", + "description": "Join #osm-ar on irc.oftc.net (port 6667)", + "extendedDescription": "You may find the most geeky user in the community." + }, + "OSM-AR-mailinglist": { + "name": "Talk-ar Mailing List", + "description": "Historic mailing list. Almost unused today." + }, + "OSM-AR-telegram": { + "name": "OpenStreetMap Argentina Telegram", + "description": "Join the OpenStreetMap Argentina community on Telegram", + "extendedDescription": "The most active channel in the community, ideal for chatting and getting answers to your questions instantly. Everyone is welcome!" + }, + "OSM-AR-twitter": { + "name": "OpenStreetMap Argentina Twitter", + "description": "Follow us on Twitter at {url}", + "extendedDescription": "News from the local community and OpenStreetMap in general." + }, + "OSM-BO-mailinglist": { + "name": "Talk-bo Mailing List", + "description": "Talk-bo is the official mailing list for the Bolivian OpenStreetMap community", + "extendedDescription": "Mapping in Bolivia? Have questions, want to connect with the community here? Join us at {url}. All are welcome!" + }, + "Bahia-telegram": { + "name": "OpenStreetMap Bahia Telegram Group", + "description": "Join the OpenStreetMap Bahia community on Telegram", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "DF-telegram": { + "name": "OpenStreetMap Brasília Telegram Group", + "description": "Join the OpenStreetMap Brasília community on Telegram", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "OSM-br-mailinglist": { + "name": "Talk-br Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Brazil" + }, + "OSM-br-telegram": { + "name": "OpenStreetMap Brasil Telegram", + "description": "Join the OpenStreetMap Brasil community on Telegram", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "OSM-br-twitter": { + "name": "OpenStreetMap Brasil Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSM-CL-facebook": { + "name": "OpenStreetMap Chile Facebook", + "description": "Join the OpenStreetMap Chile community on Facebook", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "OSM-CL-mailinglist": { + "name": "Talk-cl Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Chile" + }, + "OSM-CL-telegram": { + "name": "OpenStreetMap Chile Telegram", + "description": "Join the OpenStreetMap Chile community on Telegram", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "OSM-CL-twitter": { + "name": "OpenStreetMap Chile Twitter", + "description": "Follow us on Twitter at {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá", + "description": "We're a group of mappers interested in mapping in OpenStreetMap around Bogotá.", + "extendedDescription": "Learn to collect data in the field and digitize onto OpenStreetMap. It is not necessary to have previous knowledge! You just need the desire to participate, learn, and have fun." + }, + "OSM-CO-facebook": { + "name": "OpenStreetMap Colombia Facebook", + "description": "Join the OpenStreetMap Colombia community on Facebook", + "extendedDescription": "Join the community to learn more about OpenStreetMap. Everyone is welcome!" + }, + "OSM-CO-mailinglist": { + "name": "Talk-co Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Colombia" + }, + "OSM-CO-telegram": { + "name": "OSM Colombia on Telegram", + "description": "OpenStreetMap Colombia Telegram chat" + }, + "OSM-CO-twitter": { + "name": "OpenStreetMap Colombia Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Colombia", + "description": "News of the OpenStreetMap Colombia community and the OSMCo Foundation" + }, + "OSM-EC-telegram": { + "name": "OSM Ecuador on Telegram", + "description": "OpenStreetMap Ecuador Telegram chat" + }, + "OSM-PY-telegram": { + "name": "OSM Paraguay on Telegram", + "description": "OpenStreetMap Paraguay Telegram chat" + }, + "OSM-PE-facebook": { + "name": "OpenStreetMap Peru Facebook", + "description": "Join the OpenStreetMap Peru community on Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Talk-pe Mailing List", + "description": "The official mailing list for the OpenStreetMap Peru community" + }, + "OSM-PE-matrix": { + "name": "OpenStreetMap Peru Matrix Chat", + "description": "Chat with other members of the OpenStreetMap Peru community in Matrix." + }, + "OSM-PE-telegram": { + "name": "OpenStreetMap Peru Telegram", + "description": "Join the OpenStreetMap Peru community on Telegram" + }, + "OSM-PE-twitter": { + "name": "OpenStreetMap Peru Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap Peru", + "description": "News and resources for the OpenStreetMap Peru community" + }, + "OSM-Facebook": { + "name": "OpenStreetMap on Facebook", + "description": "Like us on Facebook for news and updates about OpenStreetMap." + }, + "OSM-help": { + "name": "OpenStreetMap Help", + "description": "Ask a question and get answers on OSM's community-driven question and answer site.", + "extendedDescription": "{url} is for everyone who needs help with OpenStreetMap. Whether you are a beginner mapper or have a technical question, we're here to help!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap on Reddit", + "description": "/r/openstreetmap/ is a great place to learn more about OpenStreetMap. Ask us anything!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSMF": { + "name": "OpenStreetMap Foundation", + "description": "OSMF is a UK-based not-for-profit that supports the OpenStreetMap Project", + "extendedDescription": "OSMF supports the OpenStreetMap by fundraising, maintaining the servers which power OSM, organizing the annual State of the Map conference, and coordinating the volunteers who keep OSM running. You can show your support and have a voice in the direction of OpenStreetMap by joining as an OSMF member here: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Join us for 3 days in Milan, Italy for the annual worldwide OpenStreetMap conference, bringing together everyone in the community to socialize, share, and learn.", + "where": "Milan, Italy" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/eo.json b/vendor/assets/iD/iD/locales/eo.json index d7420c034..59a4ca946 100644 --- a/vendor/assets/iD/iD/locales/eo.json +++ b/vendor/assets/iD/iD/locales/eo.json @@ -1,5 +1,10 @@ { "eo": { + "icons": { + "information": "informoj", + "remove": "forigi", + "undo": "malfari" + }, "modes": { "add_area": { "title": "Areo", @@ -145,7 +150,9 @@ "vertex": "Kunigis linion/areon al alia linio.", "line": "Kunigis linion/areon al linio.", "area": "Kunigis linion/areon al areo." - } + }, + "relation": "Ĉi tiuj elementoj ne povas esti konektitaj, ĉar ili havas konfliktajn rolojn de rilatoj.", + "restriction": "Ĉi tiuj elementoj ne povas esti konektitaj, ĉar tio ĉi detruus la rilaton “{relation}”." }, "disconnect": { "title": "Malkunigi", @@ -163,7 +170,8 @@ "annotation": "Kunfandis {n} objektojn.", "not_eligible": "Ĉi tiuj objektoj ne povas esti kunfanditaj.", "not_adjacent": "Ĉi tiuj objektoj ne povas esti kunfanditaj, ĉar iliaj finpunktoj ne estas kunigitaj.", - "restriction": "Ĉi tiuj objektoj ne povas esti kunfanditaj, ĉar almenaŭ unu estas ano de rilato \"{relation}\".", + "restriction": "Ĉi tiuj elementoj ne povas esti kunfanditaj, ĉar tio ĉi detruus la rilaton “{relation}”.", + "relation": "Ĉi tiuj elementoj ne povas esti kunfanditaj, ĉar ili havas konfliktajn rolojn de rilatoj.", "incomplete_relation": "Ĉi tiuj objektoj ne povas esti kunfanditaj, ĉar almenaŭ unu ne estas elŝutita tute.", "conflicting_tags": "Ĉi tiuj objektoj ne povas esti kunfanditaj, ĉar iuj el iliaj etikedoj havas konfliktajn valorojn." }, @@ -401,6 +409,7 @@ "key": "H", "title": "Historio", "selected": "{n} elektitaj", + "no_history": "Neniu historio (nova elemento)", "version": "Versio", "last_edit": "Lasta redakto", "edited_by": "Redaktita de", @@ -638,14 +647,19 @@ } }, "success": { - "edited_osm": "Redaktis OSM!", "just_edited": "Vi ĵus redaktis OpenStreetMap!", - "view_on_osm": "Montri en OSM", - "facebook": "Kunhavigi per Fejsbuko", - "twitter": "Kunhavigi per Twitter", - "google": "Kunhavigi per Google+", - "help_html": "Viaj ŝanĝoj povos aperi en la “Norma” tavolo post kelkaj minutoj. Aktualigo de aliaj tavoloj kaj aliaj elementoj povos okupi pli da tempo.", - "help_link_text": "Detaloj" + "thank_you": "Dankon por plibonigi la mapon.", + "thank_you_location": "Dankon por plibonigi la mapon ĉirkaŭ {where}.", + "help_html": "Viaj ŝanĝoj aperos en OpenStreetMap post kelkaj minutoj. Aktualigo de aliaj mapoj povas okupi pli da tempo.", + "help_link_text": "Detaloj", + "view_on_osm": "Montri ŝanĝoj ĉe OSM", + "changeset_id": "Via ŝanĝaro #: {changeset_id}", + "like_osm": "Ĉu OpenStreetMap plaĉas al vi? Komunikiĝu kun aliaj:", + "more": "Pli", + "events": "Okazaĵoj", + "languages": "Lingvoj: {languages}", + "missing": "Ĉu io mankas en la listo?", + "tell_us": "Sciigu nin!" }, "confirm": { "okay": "Bone", @@ -1772,6 +1786,9 @@ "display": { "label": "Vidigilo" }, + "distance": { + "label": "Tuta distanco" + }, "dock": { "label": "Speco" }, @@ -1812,6 +1829,9 @@ "except": { "label": "Esceptoj" }, + "faces": { + "label": "Flankoj" + }, "fax": { "label": "Telekopiilo", "placeholder": "+31 42 123 45 67" @@ -1923,6 +1943,39 @@ "label": "Korboj", "placeholder": "1, 2, 4…" }, + "horse_dressage": { + "label": "Dresrajdado", + "options": { + "equestrian": "Jes", + "undefined": "Ne" + } + }, + "horse_riding": { + "label": "Ĉeval-rajdado", + "options": { + "horse_riding": "Jes", + "undefined": "Ne" + } + }, + "horse_scale": { + "label": "Ĉeval-rajdada malfacileco", + "options": { + "common": "Facila: neniuj problemoj kaj malfacilaĵoj (implicite).", + "critical": "Malfacilega: transrajdebla nur por spertaj rajdistoj kaj ĉevaloj, grandaj obstakloj, pontoj povas ne subteni vian pezon.", + "dangerous": "Tre malfacilega: transrajdebla nur por tre spertaj rajdistoj kaj ĉevaloj dum bona vetero, deĉevaliĝu.", + "demanding": "Ete malfacila: malebena vojo, kelkaj malfacilaj pasejoj.", + "difficult": "Malfacila: mallarĝa kaj malebena vojo, povas enhavi transsaltendajn baraĵojn kaj mallarĝajn pasejojn.", + "impossible": "Netransrajdebla: vojo aŭ ponto netrairebla por ĉevaloj.; tre mallarĝa, malhelpaĵoj kiel ŝtupetaroj; danĝera por vivo." + }, + "placeholder": "Malfacila, danĝera…" + }, + "horse_stables": { + "label": "Ĉeval-domo", + "options": { + "stables": "Jes", + "undefined": "Ne" + } + }, "iata": { "label": "IATA" }, @@ -1942,6 +1995,9 @@ "indoor": { "label": "Interno" }, + "industrial": { + "label": "Speco" + }, "information": { "label": "Speco" }, @@ -2062,6 +2118,10 @@ "label": "Rapidlimo", "placeholder": "40, 50, 60…" }, + "maxspeed/advisory": { + "label": "Konsilinda rapidlimo", + "placeholder": "40, 50, 60…" + }, "maxstay": { "label": "Maksimuma restad-tempo" }, @@ -2408,7 +2468,7 @@ "label": "Speco de servo", "options": { "crossover": "Trakforko", - "siding": "Preterpasejo", + "siding": "Kromtrako", "spur": "Branĉtrako", "yard": "Ranĝadstaciaj trakoj" } @@ -2650,6 +2710,17 @@ "label": "Speco", "placeholder": "Norma" }, + "usage_rail": { + "label": "Uzo", + "options": { + "branch": "branĉa", + "industrial": "industria", + "main": "ĉefa", + "military": "armea", + "test": "testa", + "tourism": "turisma" + } + }, "vending": { "label": "Specoj de varoj" }, @@ -2746,6 +2817,10 @@ "name": "Anonctabulego", "terms": "anonctabulo,reklamo,spamo,afiŝo,afisho,afisxo" }, + "advertising/column": { + "name": "Reklam-kolono", + "terms": "reklamkolono,kolumno,afiŝkolono" + }, "aerialway": { "name": "Kablotransporto" }, @@ -2831,6 +2906,10 @@ "name": "Flugstacio", "terms": "flughaveno,terminalo" }, + "allotments/plot": { + "name": "Parcelo de familia ĝardeno", + "terms": "terpeco;parcelo;ĝardeno" + }, "amenity": { "name": "Servejo" }, @@ -3059,6 +3138,10 @@ "name": "Bazaro", "terms": "foirejo,foiro,komercejo" }, + "amenity/monastery": { + "name": "Monaĥeja tereno", + "terms": "monahhejo,monahxejo,abatejo,klostro,klaŭstro" + }, "amenity/motorcycle_parking": { "name": "Motorcikla parkumejo", "terms": "motorciklejo,motociklejo" @@ -3263,6 +3346,10 @@ "name": "Vendilo de cigaredoj", "terms": "cigaredo,vendmaŝino" }, + "amenity/vending_machine/coffee": { + "name": "Vendilo de kafo", + "terms": "kafmaŝino,teo" + }, "amenity/vending_machine/condoms": { "name": "Vendilo de kondomoj", "terms": "kondomo,vendmaŝimo,penisingo" @@ -3271,6 +3358,14 @@ "name": "Vendilo de trinkaĵoj", "terms": "vendilo de trinkajxoj,vendilo de trinkajsoj,trinkaĵoj" }, + "amenity/vending_machine/electronics": { + "name": "Vendilo de elektronikaĵoj", + "terms": "ŝargiloj,piloj,kabloj,memoriloj,memorbastonetoj,SD-kartoj,memorkartoj" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Vendilo de etenditaj moneroj", + "terms": "moneretendilo,etendilo,memoraĵoj" + }, "amenity/vending_machine/excrement_bags": { "name": "Vendilo de saketoj por fekaĵoj", "terms": "fekajhoj,fekajxoj,merdo,hundo" @@ -3279,6 +3374,18 @@ "name": "Vendilo de virinaj higienaĵoj", "terms": "menstrusorbiloj,tambonoj,persona higieno" }, + "amenity/vending_machine/food": { + "name": "Vendilo de manĝaĵo", + "terms": "manghajho,mangxajxo" + }, + "amenity/vending_machine/fuel": { + "name": "Vendilo de benzino", + "terms": "benzinstacio,diseloleo,benzino,brulaĵo,LPG,biodisel" + }, + "amenity/vending_machine/ice_cream": { + "name": "Vendilo de glaciaĵoj", + "terms": "glaciaĵo" + }, "amenity/vending_machine/news_papers": { "name": "Vendilo de gazetoj" }, @@ -3298,6 +3405,10 @@ "name": "Vendilo de vojimpostoj", "terms": "vojimposto,vojimpostejo,vojimpostilo" }, + "amenity/vending_machine/stamps": { + "name": "Vendilo de poŝtmarkoj", + "terms": "poŝtmarkoj" + }, "amenity/vending_machine/sweets": { "name": "Vendilo de dolĉaĵoj", "terms": "dolĉaĵoj,dolchajhoj,dolcxajxoj,sukeraĵoj,sukerajhoj,sukerajxoj," @@ -3370,6 +3481,10 @@ "name": "Defala turo (allogaĵo)", "terms": "turo,drop tower" }, + "attraction/maze": { + "name": "Labirinto", + "terms": "vojenigmo,enigmo" + }, "attraction/pirate_ship": { "name": "Pirata ŝipo (allogaĵo)", "terms": "ŝipo,shipo,sxipo,piratŝipo" @@ -3551,6 +3666,10 @@ "name": "Garaĝaro", "terms": "garagharo,garagxaro,garaĝo,aŭtejo,aŭtomobilejo" }, + "building/grandstand": { + "name": "Spektoteraso", + "terms": "tribuno,spektejo,podio,estrado" + }, "building/greenhouse": { "name": "Kultivdomo", "terms": "forcejo,plantdomo,plantodomo" @@ -3999,6 +4118,10 @@ "name": "Hospico", "terms": "hospico,flegejo" }, + "healthcare/laboratory": { + "name": "Medicina laboratorio", + "terms": "medicina labo,labo,sanĝkontrolejo" + }, "healthcare/midwife": { "name": "Akuŝisto", "terms": "akuŝistino,naskiĝcentro,naskiĝdomo,gravedeco" @@ -4101,6 +4224,10 @@ "name": "Aŭtovoja ligilo", "terms": "enveturejo,elveturejo,aŭtoŝoseo,nodo" }, + "highway/passing_place": { + "name": "Preterpasejo", + "terms": "pasejo,preterveturejo" + }, "highway/path": { "name": "Vojeto (piedpremita)", "terms": "vojo,pado,irejo,piedvojeto" @@ -4460,6 +4587,10 @@ "name": "Salono de ludoj", "terms": "ludejo,amuzaparatoj,videoludoj,paĉinko,flipero,bilardo" }, + "leisure/beach_resort": { + "name": "Sablobordo administrata (kun oportunaĵoj)", + "terms": "plaĝo,strando,ripozcentro,sunbanejo" + }, "leisure/bird_hide": { "name": "Bird-observejo", "terms": "birdobservejo" @@ -4576,6 +4707,10 @@ "name": "Natur-rezervejo", "terms": "naturrezervejo,naturprotektejo,rezervejo,naturparko,nacia parko,konservejo" }, + "leisure/outdoor_seating": { + "name": "Seĝoj eksterdome", + "terms": "seghoj,segxoj,benko,altano,teraso" + }, "leisure/park": { "name": "Parko", "terms": "herbejo,ripozejo,verdejo,ĝardenego" @@ -4704,6 +4839,10 @@ "name": "Mineja koridoro", "terms": "minejkoridoro,minejo horizontala,minejgalerio,galerio" }, + "man_made/antenna": { + "name": "Anteno", + "terms": "masto" + }, "man_made/breakwater": { "name": "Ond-rompilo", "terms": "ondorompilo,ondrompilo,digo,ĝeto" @@ -4716,6 +4855,10 @@ "name": "Kamentubo", "terms": "kameno,fumtubo" }, + "man_made/clearcut": { + "name": "Hakita arbaro", + "terms": "malarbaro,dehakita arbaro,senarba areo,senarbigita areo,stumpoj" + }, "man_made/crane": { "name": "Gruo", "terms": "gruo,argano,levmaŝino" @@ -4755,6 +4898,10 @@ "name": "Vidturo", "terms": "observturo,turo" }, + "man_made/observatory": { + "name": "Observejo", + "terms": "astronomia,vetera,teleskopo" + }, "man_made/petroleum_well": { "name": "Puto nafta", "terms": "naftoputo,naftoŝakto,drilplatformo" @@ -4879,10 +5026,18 @@ "name": "Erikejo", "terms": "arbustaro,herbejo" }, + "natural/mud": { + "name": "Kota tereno", + "terms": "koto;malsekejo;ŝlimejo" + }, "natural/peak": { "name": "Montpinto", "terms": "montopinto,monto,supro,kulmino,supraĵo" }, + "natural/reef": { + "name": "Rifo", + "terms": "submara roko,ŝtono" + }, "natural/ridge": { "name": "Montokresto", "terms": "montkresto,montarĉeno,montsistemo" @@ -5360,7 +5515,7 @@ "terms": "stacidomo" }, "public_transport/station_aerialway": { - "name": "Stacio koblovoja", + "name": "Stacio kablovoja", "terms": "telferstacio,telfera stacio" }, "public_transport/station_bus": { @@ -5463,8 +5618,8 @@ "terms": "relŝuo,relfino,finrelo" }, "railway/disused": { - "name": "Forlasita relvojo", - "terms": "eksa fervojlinio,trako,relvojo" + "name": "Neuzata relvojo", + "terms": "eksa fervojlinio,trako,relvojo,forlasita fervojlinio" }, "railway/funicular": { "name": "Funikularo", @@ -5915,6 +6070,10 @@ "name": "Dombesta vendejo", "terms": "dombestoj,hejmbestoj,bestoj,kobajo,kuniklo,papago" }, + "shop/pet_grooming": { + "name": "Dombesta beligejo", + "terms": "frizejo,hartondisto,hundoj,katoj,hejmbestoj" + }, "shop/photo": { "name": "Fotografia vendejo", "terms": "fotografio,fotografarto" @@ -6134,6 +6293,10 @@ "name": "Amuzparko", "terms": "amuzejo,temparko,distroparko" }, + "tourism/trail_riding_station": { + "name": "Pensiono por ĉevalistoj", + "terms": "ĉevalejo,ĉevalhotelo" + }, "tourism/viewpoint": { "name": "Belvidejo", "terms": "videjo,vidindaĵo,rigardejo" @@ -6218,16 +6381,20 @@ "terms": "malpermeso,malantaŭen,U-forma,,Uforma,prohibo" }, "type/restriction/only_left_turn": { - "name": "Turno maldekstren devigita", - "terms": "ordono,devigo,maldekstren" + "name": "Nur turno maldekstren", + "terms": "maldekstren,liven" }, "type/restriction/only_right_turn": { - "name": "Turno dekstren devigita", - "terms": "ordono,devigo,maldekstren" + "name": "Nur turno dekstren", + "terms": "dekstren" }, "type/restriction/only_straight_on": { - "name": "Veturo rekten devigita", - "terms": "ordono,devigo,rekten,antaŭen" + "name": "Nur veturo rekten", + "terms": "rekten,antaŭen" + }, + "type/restriction/only_u_turn": { + "name": "Nur turno malantaŭen", + "terms": "malantaŭen,reveturen,U-turno" }, "type/route": { "name": "Kurso", @@ -6390,7 +6557,7 @@ "attribution": { "text": "Kondiĉoj kaj rimarkoj" }, - "description": "Limoj kaj datoj de fotoj. Etikedoj montriĝas de skal-nivelo 14.", + "description": "Limoj kaj datoj de fotoj. Etikedoj montriĝas de skal-nivelo 13.", "name": "Detala fotaro de DigitalGlobe - fot-dato" }, "DigitalGlobe-Standard": { @@ -6404,7 +6571,7 @@ "attribution": { "text": "Kondiĉoj kaj rimarkoj" }, - "description": "Limoj kaj datoj de fotoj. Etikedoj montriĝas de skal-nivelo 14.", + "description": "Limoj kaj datoj de fotoj. Etikedoj montriĝas de skal-nivelo 13.", "name": "Norma fotaro de DigitalGlobe - fot-dato" }, "EsriWorldImagery": { @@ -6488,6 +6655,10 @@ "description": "Flave = publikaj map-datumoj de Usona popolnombrado. Ruĝe = datumoj ne trovitaj en OpenStreetMap", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Vojo: verda rando = neklasifikita, bruna rando = kampa vojo. Pavimo: helbruna plenigo = sablego, nigra = asfalto, griza = pavimita, blanka = tera, blua = betono, verda = herbo. Blankaj strioj = sezona vojo.", + "name": "Surtavolo de arbar-kultivaj vojoj" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, kontribuintoj de OpenStreetMap, CC by-SA 3.0" @@ -6584,7 +6755,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Map-kaheloj de Stamen Design, laŭ CC BY 3.0" + "text": "Map-kaheloj de Stamen Design, laŭ CC BY 3.0. Datumoj de OpenStreetMap, laŭ ODbL" }, "name": "Stamen Terrain" }, @@ -6600,6 +6771,45 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "OSM-PL-facebook-group": { + "name": "Facebook-grupo OpenStreetMap Polska", + "description": "Grupo por mapigistoj kaj uzantoj de OpenStreetMap en Polujo." + }, + "OSM-PL-forum": { + "name": "Forum-sekcio OpenStreetMap Polska", + "description": "Diskutejo por pola komunumo de OpenStreetMap" + }, + "OSM-Facebook": { + "name": "OpenStreetMap ĉe Facebook", + "description": "Ŝatu nin ĉe Facebook por akiri novaĵojn pri OpenStreetMap." + }, + "OSM-help": { + "name": "Helpo pri OpenStreetMap", + "description": "Demandu kaj akiru respondojn ĉe kreata de komunumo retejo.", + "extendedDescription": "{url} taŭgas por ĉiu, kiu bezonas helpon pri OpenStreetMap. Ne gravas ĉu vi estas komencanta mapisto aŭ havas teĥnikan demandon, ni estas tie ĉi por vin helpi!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap ĉe Reddit", + "description": "/r/openstreetmap/ estas bonega loko por sciiĝi pli pri OpenStreetMap. Demandu pri io ajn!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap ĉe Twitter", + "description": "Sekvi nin ĉe Twitter ĉe {url}" + }, + "OSMF": { + "name": "Fondaĵo OpenStreetMap", + "description": "OSMF estas ne-profit-cela organizaĵo en Britujo, kiu subtenas la projekton OpenStreetMap", + "extendedDescription": "OSMF subtenas OpenStreetMap per regali, prizorgi servilojn gastigatajn OSM, organizi la ĉiujaran konferencon “State of the Map” kaj kunordigi volontulojn, kiuj evoluigas la mapon. Vi povas oferi vian helpon kaj havi opinion pri direkto de la projekto OpenStreetMap per aniĝi OSMF tie ĉi: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Kunigu nin por 3 tagoj en Milano, Italujo por la ĉiujaran internacian konferencon pri OpenStreetMap por kunigi ĉiujn en la komunumo por sociumi, diskonigi kaj lerni.", + "where": "Milano, Italujo" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/es.json b/vendor/assets/iD/iD/locales/es.json index 8bd3bb4ff..c9978ea0f 100644 --- a/vendor/assets/iD/iD/locales/es.json +++ b/vendor/assets/iD/iD/locales/es.json @@ -1,5 +1,10 @@ { "es": { + "icons": { + "information": "información", + "remove": "quitar", + "undo": "deshacer" + }, "modes": { "add_area": { "title": "Área", @@ -145,7 +150,9 @@ "vertex": "Vía conectada a otra.", "line": "Vía conectada a una línea.", "area": "Vía conectada a un área." - } + }, + "relation": "Estos elementos no se pueden conectar porque tienen roles de relación con conflictos.", + "restriction": "Estos elementos no se pueden conectar porque dañarían la relación \"{relation}\"." }, "disconnect": { "title": "Desconectar", @@ -163,7 +170,8 @@ "annotation": "{n} elementos combinados.", "not_eligible": "Estos elementos no se pueden combinar.", "not_adjacent": "Estos elementos no se pueden combinar porque sus extremos no están conectados.", - "restriction": "Estos elementos no se pueden combinar porque al menos uno es miembro de una relación de «{relation}».", + "restriction": "Estos elementos no pueden combinarse porque dañaría una relación \"{relación}\".", + "relation": "Estos elementos no pueden combinarse porque tienen roles de relación con conflicto.", "incomplete_relation": "Estos elementos no se pueden combinar porque al menos uno no ha sido descargado por completo.", "conflicting_tags": "Estos elementos no se pueden combinar porque algunas de sus etiquetas tienen conflictos en sus valores." }, @@ -291,6 +299,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Distancia", + "distance_up_to": "Hasta {distance}", + "via": "Vía", + "via_node_only": "Solo nodo", + "via_up_to_one": "Hasta 1 vía", + "via_up_to_two": "Hasta 2 vías" + }, + "help": { + "indirect": "(indirecto)", + "turn": { + "no_left_turn": "NO giro a la izquierda {indirect}", + "no_right_turn": "NO giro a la derecha {indirect}", + "no_u_turn": "NO giro en U {indirect}", + "no_straight_on": "NO seguir derecho {indirect}", + "only_left_turn": "SOLO giro a la izquierda {indirect}", + "only_right_turn": "SOLO giro a la derecha {indirect}", + "only_u_turn": "SOLO giro en U {indirect}", + "only_straight_on": "SOLO seguir derecho {indirect}", + "allowed_left_turn": "Giro a la izquierda permitido {indirect}", + "allowed_right_turn": "Giro a la derecha permitido {indirect}", + "allowed_u_turn": "Giro en U permitido {indirect}", + "allowed_straight_on": "Seguir derecho permitido {indirect}" + }, + "from": "DESDE", + "via": "VÍA", + "to": "HASTA", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Haga clic para seleccionar un segmento {from}", + "select_from_name": "Haga clic para seleccionar {from} {fromName}", + "toggle": "Haga clic para \"{turn}\"" + } + }, "undo": { "tooltip": "Deshacer: {action}", "nothing": "Nada que deshacer" @@ -366,6 +410,7 @@ "key": "H", "title": "Historial", "selected": "{n} seleccionado", + "no_history": "Sin historial (Nuevo elemento)", "version": "Versión", "last_edit": "Última edición", "edited_by": "Editado por", @@ -603,15 +648,20 @@ } }, "success": { - "edited_osm": "¡OSM editado!", - "just_edited": "¡Acaba de editar OpenStreetMap!", - "view_on_osm": "Ver en OSM", - "facebook": "Compartir en Facebook", - "twitter": "Compartir en Twitter", - "google": "Compartir en Google+", - "help_html": "Sus cambios deberían aparecer en la capa «estándar» en unos pocos minutos. Otras capas, y ciertos elementos, pueden llevar más tiempo.", + "just_edited": "¡Acabas de editar OpenStreetMap!", + "thank_you": "Gracias por mejorar el mapa.", + "thank_you_location": "Gracias por mejorar el mapa alrededor de {where}.", + "help_html": "Los cambios deberían aparecer en OpenStreetMap en unos minutos. Puede llevar más tiempo para que otros mapas reciban las actualizaciones.", "help_link_text": "Detalles", - "help_link_url": "https://wiki.openstreetmap.org/wiki/ES:FAQ#Acabo_de_hacer_algunos_cambios_en_el_mapa._.C2.BFC.C3.B3mo_puedo_ver_mis_modificaciones.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/ES:FAQ#Acabo_de_hacer_algunos_cambios_en_el_mapa._.C2.BFC.C3.B3mo_puedo_ver_mis_modificaciones.3F", + "view_on_osm": "Ver cambios en OSM", + "changeset_id": "Conjunto de cambios #: {changeset_id}", + "like_osm": "¿Te gusta OpenStreetMap? Conéctate con otros:", + "more": "Más", + "events": "Eventos", + "languages": "Idiomas: {languages}", + "missing": "¿Falta algo en esta lista?", + "tell_us": "¡Cuéntanos!" }, "confirm": { "okay": "Aceptar", @@ -846,6 +896,44 @@ "using": "Para usar una traza de GPS para el mapeo, arrastre y suelte el archivo de datos en el editor de mapas. Si lo reconoce, lo dibujará en el mapa como una línea violeta brillante. Haga clic en el panel {data} **Datos del mapa** en el lateral del mapa para habilitar, deshabilitar o ampliar sus datos de GPS.", "tracing": "La traza de GPS no se envía a OpenStreetMap; la mejor manera de usarla es dibujar en el mapa usándola como una guía para los nuevos elementos que agregue.", "upload": "También puede [cargar los datos del GPS a OpenStreetMap](https://www.openstreetmap.org/trace/create) para que los usen otros usuarios." + }, + "field": { + "restrictions": { + "title": "Ayuda sobre restricciones de giro", + "about": { + "title": "Acerca de", + "about": "Este campo permite inspeccionar y modificar restricciones de giro. Muestra un modelo de la intersección seleccionada incluyendo otras vías cercanas conectadas.", + "from_via_to": "Una restricción de giro siempre contiene: una **vía DESDE**, una **vía HASTA**, y un **nodo VÍA** o una o más **vías VÍA**.", + "maxdist": "El control deslizante \"{distField}\" controla qué tan lejos buscar vías adicionales conectadas.", + "maxvia": "El control deslizante \"{viaField}\" ajusta cuántas vías se pueden incluir en la búsqueda. (Consejo: simple es mejor)" + }, + "inspecting": { + "title": "Inspeccionando", + "about": "Desplácese sobre cualquier segmento **DESDE** para ver si tiene restricciones de giro. Cada destino **HASTA** posible se dibujará con una sombra de color que muestra si existe una restricción.", + "from_shadow": "{fromShadow} **segmento DESDE**", + "allow_shadow": "{allowShadow} **HASTA Permitido**", + "restrict_shadow": "{restrictShadow} **HASTA Restringido**", + "only_shadow": "{onlyShadow} **HASTA Solo**", + "restricted": "\"Restringido\" significa que hay una restricción de giro, por ejemplo \"No girar a la izquierda\".", + "only": "\"Solo\" significa que un vehículo que toma ese camino solo puede hacer esa elección, por ejemplo, \"Solo seguir derecho\"." + }, + "modifying": { + "title": "Modificando", + "about": "Para modificar las restricciones de giro, primero haga clic en cualquier segmento de partida **DESDE** para seleccionarlo. El segmento seleccionado emitirá un pulso, y todos los posibles destinos **HASTA** aparecerán como símbolos de giro.", + "indicators": "Luego, haga clic en un símbolo de giro para alternar entre \"Permitido\", \"Restringido\" y \"Solo\".", + "allow_turn": "{allowTurn} **HASTA Permitido**", + "restrict_turn": "{restrictTurn} **HASTA Restringido**", + "only_turn": "{onlyTurn} **HASTA Solo**" + }, + "tips": { + "title": "Consejos", + "simple": "**Prefiera restricciones simples sobre las complejas.**", + "simple_example": "Por ejemplo, evite crear una restricción de vía-vía si una restricción de giro de nodo-vía simple funciona.", + "indirect": "**Algunas restricciones muestran el texto \"(indirecto)\" y se dibujan más claras.**", + "indirect_example": "Estas restricciones existen debido a otra restricción cercana. Por ejemplo, una restricción \"Solo seguir derecho\" creará indirectamente restricciones de \"No giro\" para todos los demás caminos a través de la intersección.", + "indirect_noedit": "No se puede editar restricciones indirectas. En cambio, edite la restricción directa cercana." + } + } } }, "intro": { @@ -1700,6 +1788,9 @@ "display": { "label": "Monitor" }, + "distance": { + "label": "Distancia total" + }, "dock": { "label": "Tipo" }, @@ -1740,6 +1831,9 @@ "except": { "label": "Excepciones" }, + "faces": { + "label": "Caras" + }, "fax": { "label": "Fax", "placeholder": "+31 42 123 4567" @@ -1851,6 +1945,39 @@ "label": "Aros", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Doma clásica", + "options": { + "equestrian": "Sí", + "undefined": "No" + } + }, + "horse_riding": { + "label": "Cabalgatas", + "options": { + "horse_riding": "Sí", + "undefined": "No" + } + }, + "horse_scale": { + "label": "Dificultad para montar a caballo", + "options": { + "common": "Fácil: sin problemas ni dificultades. (Predeterminado)", + "critical": "Límite: solo transitable para jinetes y caballos experimentados. Obstáculos importantes. Los puentes deben examinarse cuidadosamente.", + "dangerous": "Peligroso: solo apto para jinetes y caballos muy experimentados y solo cuando hace buen tiempo. Desmontar.", + "demanding": "Usar con precaución: Vía irregular, pasajes ocasionalmente difíciles.", + "difficult": "Difícil: Camino angosto y expuesto. Puede tener obstáculos para pasar y pasadizos estrechos.", + "impossible": "Imposible: camino o puente no transitable para caballos. Demasiado estrecho, soporte insuficiente, obstáculos como escaleras. Peligro de muerte." + }, + "placeholder": "Difícil, Peligroso..." + }, + "horse_stables": { + "label": "Establo para montar a caballo", + "options": { + "stables": "Sí", + "undefined": "No" + } + }, "iata": { "label": "IATA" }, @@ -1870,6 +1997,9 @@ "indoor": { "label": "Interior" }, + "industrial": { + "label": "Tipo" + }, "information": { "label": "Tipo" }, @@ -1990,6 +2120,10 @@ "label": "Límite de velocidad", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "Límite de velocidad recomendada", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Estadía máxima" }, @@ -2020,7 +2154,7 @@ "options": { "0": "Más fácil (círculo blanco)", "1": "Fácil (círculo verde)", - "2": "Media (círculo azul)", + "2": "Media (cuadrado azul)", "3": "Difícil (diamante negro)", "4": "Extremadamente difícil (doble diamante negro)" }, @@ -2578,8 +2712,19 @@ "label": "Tipo", "placeholder": "Predeterminado" }, + "usage_rail": { + "label": "Tipo de uso", + "options": { + "branch": "Ramal", + "industrial": "Industrial", + "main": "Principal", + "military": "Militar", + "test": "Prueba", + "tourism": "Turismo" + } + }, "vending": { - "label": "Tipo de producto" + "label": "Tipos de bienes" }, "visibility": { "label": "Visibilidad", @@ -2674,6 +2819,10 @@ "name": "Panel publicitario", "terms": "panel, cartel, cartelera, valla, publicitario, publicidad" }, + "advertising/column": { + "name": "Columna publicitaria", + "terms": "Columna publicitaria, publicidad, cartel, propaganda" + }, "aerialway": { "name": "Transporte por cable" }, @@ -2759,6 +2908,10 @@ "name": "Terminal de aeropuerto", "terms": "terminal, pasajeros, aeropuerto" }, + "allotments/plot": { + "name": "Parcela comunitaria", + "terms": "jardín, huerto, huerta, comunitario, comunal, vecindad, huerto urbano, área, terreno, zona" + }, "amenity": { "name": "Servicio" }, @@ -2850,7 +3003,7 @@ "terms": "casino, azar, casa de juego, ruleta, black jack, póquer, tragamoneda" }, "amenity/charging_station": { - "name": "Estación de carga eléctrica", + "name": "Estación de carga para vehículos eléctricos", "terms": "recarga, electricidad, eléctrico, estación de carga para vehículo eléctrico, punto de recarga, electrolinera" }, "amenity/childcare": { @@ -2863,23 +3016,23 @@ }, "amenity/clinic": { "name": "Clínica", - "terms": "clínica, centro médico, hospital, consultorio" + "terms": "clínica, centro médico, consultorio médico, centro de salud" }, "amenity/clinic/abortion": { "name": "Clínica de aborto", - "terms": "aborto, abotar, interrupción, embarazo, interrupción embarazo, clínica de aborto, clinica aborto" + "terms": "aborto, abotar, interrupción, embarazo, interrupción del embarazo, clínica de aborto, clínica de aborto" }, "amenity/clinic/fertility": { "name": "Clínica de fertilidad", - "terms": "clínica de fertilidad, clinica de fertilidad, fertilidad, reproducción, reproduccion, esperma, ovulación, ovulacion" + "terms": "clínica de fertilidad, clínica de fertilidad, fertilidad, reproducción, esperma, ovulación, ovulación, clínica de reproducción" }, "amenity/clock": { "name": "Reloj", "terms": "cronómetro" }, "amenity/college": { - "name": "Instituto / Escuela profesional", - "terms": "instituto, universidad, escuela profesional, educación terceria" + "name": "Terreno de centro educativo superior no universitario", + "terms": "formación profesional, escuela profesional, educación terciaria, post-bachillerato, ciclo formativo de grado superior, FP, conservatorio, Terciario, superior, no universitario, terreno, área, area, suelo, instituto" }, "amenity/community_centre": { "name": "Centro Comunitario", @@ -2906,7 +3059,7 @@ }, "amenity/doctors": { "name": "Doctor", - "terms": "médico, galeno, consultorio" + "terms": "médico, galeno, consultorio médico, ambulatorio médico, consulta médica" }, "amenity/dojo": { "name": "Academia de artes marciales", @@ -2987,6 +3140,10 @@ "name": "Mercado", "terms": "mercado, mercadillo, mercado público, plaza de mercado, feria" }, + "amenity/monastery": { + "name": "Área de Monasterio", + "terms": "área de monasterio, terreno de monasterio, monasterio, terreno sagrado, área religiosa" + }, "amenity/motorcycle_parking": { "name": "Aparcamiento de motocicletas", "terms": "motocicleta, moto, aparcamiento, parking, estacionamiento, parqueadero, parqueo, parqueadero de motocicletas, estacionamiento de motocicletas, parqueo de motocicletas" @@ -3191,6 +3348,10 @@ "name": "Máquina expendedora de cigarrillos", "terms": "tabaco, cigarro, cigarrillo, pucho, expendedor" }, + "amenity/vending_machine/coffee": { + "name": "Máquina expendedora de café", + "terms": "Máquina expendedora de café, café, cafe" + }, "amenity/vending_machine/condoms": { "name": "Máquina expendedora de condones", "terms": "condones, condón, profiláctico, preservativo, expendedor" @@ -3199,6 +3360,14 @@ "name": "Máquina expendedora de bebidas", "terms": "bebida, gaseosa, refresco, expendedor" }, + "amenity/vending_machine/electronics": { + "name": "Máquina expendedora de electrónica", + "terms": "Máquina expendedora de electrónica, cable, cargador, auricular, auriculares, teléfono, telefono, celular, tableta" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Máquina expendedora de monedas planas", + "terms": "Máquina expendedora de monedas planas, moneda, aplastar, alargar, aplanar, penique, recuerdo" + }, "amenity/vending_machine/excrement_bags": { "name": "Máquina expendedora de bolsa para excrementos", "terms": "excremento, caca, bolsa, expendedor" @@ -3207,6 +3376,18 @@ "name": "Máquina expendedora de higiene femenina", "terms": "Máquina expendedora de higiene femenina, maquina expendedora, condón, tampón, tampon, almohadilla, toallita, toalla, mujer, mujeres, productos de higiene menstrual, cuidado personal" }, + "amenity/vending_machine/food": { + "name": "Máquina expendedora de alimentos", + "terms": "Máquina expendedora de alimentos, comida, alimento, comestible, expendedora" + }, + "amenity/vending_machine/fuel": { + "name": "Surtidor de combustible", + "terms": "Surtidor de combustible, gasolina, combustible, biodiesel, gnc" + }, + "amenity/vending_machine/ice_cream": { + "name": "Máquina expendedora de helados", + "terms": "Máquina expendedora de helados, chocolate, helado, helado, paleta, vainilla" + }, "amenity/vending_machine/news_papers": { "name": "Máquina expendedora de periódico" }, @@ -3226,6 +3407,10 @@ "name": "Máquina expendedora del boleto de transporte", "terms": "ticket, boleto, recibo, transporte público, autobús, bus, colectivo, micro, guagua, expendedor" }, + "amenity/vending_machine/stamps": { + "name": "Máquina expendedora del franqueo", + "terms": "Máquina expendedora del franqueo, correo, franqueo, sello, estampillas" + }, "amenity/vending_machine/sweets": { "name": "Máquina expendedora de snacks", "terms": "snack, bocadillo, refrigerio, botanas, expendedor" @@ -3298,6 +3483,10 @@ "name": "Torre de caída", "terms": "torre de caída, pilar de caída, juego mecánico, juego de feria" }, + "attraction/maze": { + "name": "Laberinto", + "terms": "Laberinto, parque temático, parque de diversiones" + }, "attraction/pirate_ship": { "name": "Barco pirata", "terms": "barco pirata, pirata, juego mecánico, juego de feria" @@ -3441,8 +3630,8 @@ "terms": "Edificio cívico, edificio civico, cívico, civico, centro cívico, centro civico, ayuntamiento, biblioteca, piscina" }, "building/college": { - "name": "Edificio instituto", - "terms": "edificio del instituto, edificio instituto, facultad" + "name": "Edificio educativo superior no universitario", + "terms": "edificio del instituto, edificio instituto, centro educativo, centro formativo" }, "building/commercial": { "name": "Edificio comercial", @@ -3464,10 +3653,12 @@ "name": "Entrada/Salida" }, "building/farm": { - "name": "Casa de Campo" + "name": "Casa de campo", + "terms": "Casa de campo, casa, campo, edificio agrícola, edificio agricola, agrícola, agricola, granja" }, "building/farm_auxiliary": { - "name": "Edificio agrícola" + "name": "Edificio agrícola", + "terms": "edificio agrícola, edificio agricola, agrícola, agricola, granja" }, "building/garage": { "name": "Garaje privado", @@ -3477,6 +3668,10 @@ "name": "Garajes", "terms": "garajes, cocheras" }, + "building/grandstand": { + "name": "Tribuna", + "terms": "tribuna, gradas" + }, "building/greenhouse": { "name": "Invernadero", "terms": "Invernadero, Invernáculo" @@ -3925,6 +4120,10 @@ "name": "Hospicio", "terms": "Hospicio, enfermedad, terminal" }, + "healthcare/laboratory": { + "name": "Laboratorio médico", + "terms": "Laboratorio médico, laboratorio, análisis clínicos, analisis clinicos, análisis de sangre, analisis de sangre" + }, "healthcare/midwife": { "name": "Partera", "terms": "Partera, bebé, parto, trabajo de parto, embarazo, nacimiento" @@ -4027,6 +4226,10 @@ "name": "Enlace de autopista", "terms": "enlace, acceso, autopista, autovía, salida" }, + "highway/passing_place": { + "name": "Lugar de paso", + "terms": "lugar de paso, parada, zona de descanso" + }, "highway/path": { "name": "Sendero", "terms": "vereda, sendero, senda, camino, vía, ramal, trocha, atajo, travesía, huella, rastro" @@ -4386,6 +4589,10 @@ "name": "Sala de juegos recreativos", "terms": "juegos, videojuegos, simuladores, máquinas, maquinas, pinball, fichines" }, + "leisure/beach_resort": { + "name": "Balneario", + "terms": "resort, complejo, playa, complejo de playa, balneario" + }, "leisure/bird_hide": { "name": "Observatorio de aves", "terms": "observatorio, refugio, ave, pájaro, vida silvestre, naturaleza" @@ -4403,7 +4610,8 @@ "terms": "sala de baile, pista de baile, baile de salón, bolero, conga, cha-cha-chá, fox-trot, mambo, son cubano, meregue, milonga, pasodoble, polka, rock and roll, rumba, swing, tango, vals, jive" }, "leisure/dancing_school": { - "name": "Escuela de baile" + "name": "Escuela de baile", + "terms": "escuela de baile, escuela de danza, academia de danza, baile, danza, escuela, taller, academia" }, "leisure/dog_park": { "name": "Parque canino", @@ -4501,9 +4709,13 @@ "name": "Reserva natural", "terms": "reserva natural, reserva ecológica, área protegida, conservación, preservación, natural" }, + "leisure/outdoor_seating": { + "name": "Área de asientos al exterior", + "terms": "al aire libre, jardín de cerveza, comedor, cafetería, restaurante, pub, bar, patio" + }, "leisure/park": { - "name": "Parque", - "terms": "parque, plaza, plazuela, parque ecoturístico, área de recreación" + "name": "Parque / Plaza verde", + "terms": "parque, plaza, plazuela, parque ecoturístico, área de recreación, bosque, jardín, jardin, hierba, pasto, verde, césped, cesped, prado, zonas verdes, juegos infantiles, jardín de recreo, arbolado" }, "leisure/picnic_table": { "name": "Mesa de picnic", @@ -4629,6 +4841,10 @@ "name": "Socavón", "terms": "socavón, entrada, mina" }, + "man_made/antenna": { + "name": "Antena", + "terms": "antena, cable, alambre, parabólica, satelital" + }, "man_made/breakwater": { "name": "Rompeolas", "terms": "cortaolas, rompeolas, malecón" @@ -4641,6 +4857,10 @@ "name": "Chimenea", "terms": "chimenea, fogón, fuego" }, + "man_made/clearcut": { + "name": "Bosque talado", + "terms": "bosque talado, bosque, talado, tala, desmonte, madera, árbol" + }, "man_made/crane": { "name": "Grúa", "terms": "elevadora, cabria, cabrestante, trucha, pluma" @@ -4680,6 +4900,10 @@ "name": "Torre de Observación", "terms": "Torre de observación, torre de vigilancia" }, + "man_made/observatory": { + "name": "Observatorio", + "terms": "observatorio, mirador, observador, astronomía, telescopio" + }, "man_made/petroleum_well": { "name": "Pozo de petróleo", "terms": "pozo, petróleo, plataforma de perforación, torre de perforación, perforación de petróleo, plataforma petrolera" @@ -4804,10 +5028,18 @@ "name": "Brezal / Landa", "terms": "brezal, landa, jaral, matorral, llanura, páramo, meseta, arenal, estepa, planicie, descampado, escajo, tojo" }, + "natural/mud": { + "name": "Lodo", + "terms": "lodo, barro, charco, pantano" + }, "natural/peak": { "name": "Pico", "terms": "pico, montaña, cresta, cima, cúspide, cumbre, picacho, aguja, alpes, corona, colina, monte" }, + "natural/reef": { + "name": "Arrecife", + "terms": "Arrecife, barrera, coral, océano, arena, cardumen" + }, "natural/ridge": { "name": "Cresta", "terms": "cresta, montaña, canto, cresta elevada" @@ -5075,7 +5307,7 @@ "terms": "submunicipio, subdistrito, sector, cuadrante, delegación, localidad, barrio, vecindario, quarter" }, "place/square": { - "name": "Plaza", + "name": "Plaza cívica", "terms": "plaza" }, "place/suburb": { @@ -5155,7 +5387,7 @@ }, "power/generator": { "name": "Generador de energía", - "terms": "subestación, generador, generador eléctrico, generador de electricidad, generador de potencia" + "terms": "subestación, generador, generador eléctrico, generador de electricidad, generador de potencia, generador de energía, estación eléctrica, planta de electridad, central elécrica, electricidad, eléctrica, electrica" }, "power/generator/source_nuclear": { "name": "Reactor nuclear", @@ -5840,6 +6072,10 @@ "name": "Tienda de mascotas", "terms": "mascota, animal, tienda de animales" }, + "shop/pet_grooming": { + "name": "Tienda de aseo para mascotas", + "terms": "Tienda de aseo para mascotas, perro" + }, "shop/photo": { "name": "Tienda de fotografía", "terms": "fotografía, fotógrafo, cámara, retratista, revelado, film, rollo, impresión, fotos" @@ -6004,8 +6240,8 @@ "terms": "caravana, remolque, autocaravana, roulotte" }, "tourism/chalet": { - "name": "Cabaña de vacaciones", - "terms": "chalet, bungalow, bungaló, bungalo, turismo, cabaña, complejo de cabañas, vacacional, turístico, turistico, turismo" + "name": "Cabaña vacacional / Bungaló", + "terms": "casa rural, bungalow, bungaló, bungalo, turismo, cabaña, complejo de cabañas, vacacional, turístico, turistico, turismo, cabaña de vacaciones, posada, casa de labranza, casa de campo, alojamiento rural" }, "tourism/gallery": { "name": "Galería de arte", @@ -6059,6 +6295,10 @@ "name": "Parque de atracciones", "terms": "parque temático, parque de atracciones, atracciones" }, + "tourism/trail_riding_station": { + "name": "Estación en sendero de cabalgata", + "terms": "estación, sendero, cabalgata, equitación, equitacion" + }, "tourism/viewpoint": { "name": "Vista panorámica / Mirador", "terms": "oteadero, punto de vista, mirador, vistas, vista panorámica, perspectiva" @@ -6143,16 +6383,20 @@ "terms": "giro en U, cambio de sentido, vuelta en U, no girar en U, prohibido girar en U" }, "type/restriction/only_left_turn": { - "name": "Sólo girar a la izquierda", - "terms": "giro, izquierda" + "name": "Solo giro a la izquierda", + "terms": "Solo giro a la izquierda, giro, izquierda" }, "type/restriction/only_right_turn": { - "name": "Sólo girar a la derecha", - "terms": "giro, derecha" + "name": "Solo giro a la derecha", + "terms": "Solo giro a la derecha, giro, derecha" }, "type/restriction/only_straight_on": { - "name": "No girar", - "terms": "prohibición, giro, no girar, prohibido girar" + "name": "Solo seguir derecho", + "terms": "Solo seguir derecho, derecho, recto" + }, + "type/restriction/only_u_turn": { + "name": "Solo giro en U", + "terms": "Solo giro en U, giro, U, vuelta en U, cambio de sentido" }, "type/route": { "name": "Ruta", @@ -6315,7 +6559,7 @@ "attribution": { "text": "Términos y comentarios" }, - "description": "Límites de imágenes y fechas de captura. Las etiquetas aparecen en el nivel de acercamiento 14 y superior.", + "description": "Límites de imágenes y fechas de captura. Las etiquetas aparecen en el nivel de zoom 13 y superior.", "name": "Imágenes antiguas DigitalGlobe Premium" }, "DigitalGlobe-Standard": { @@ -6329,7 +6573,7 @@ "attribution": { "text": "Términos y comentarios" }, - "description": "Límites de imágenes y fechas de captura. Las etiquetas aparecen en el nivel de acercamiento 14 y superior.", + "description": "Límites de imágenes y fechas de captura. Las etiquetas aparecen en el nivel de zoom 13 y superior.", "name": "Imágenes antiguas DigitalGlobe Standard" }, "EsriWorldImagery": { @@ -6413,6 +6657,10 @@ "description": "Amarillo = Datos del mapa de dominio público desde el US Census. Rojo = Datos no encontrados en OpenStreetMap", "name": "Carreteras TIGER 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Carretera: marco verde = sin clasificar. marco marrón = pista. Superficie: grava = relleno marrón claro, asfalto = negro, pavimentado = gris, tierra = blanco, hormigón = azul, hierba/pasto = verde. Estacional = barras blancas", + "name": "Superposición de carreteras forestales de los EE.UU." + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, colaboradores de OpenStreetMap, CC by-SA 3.0" @@ -6447,7 +6695,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Mapa base de Austria, basado en datos del gobierno.", + "description": "Mapa base de Austria, basado en datos gubernamentales.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6509,7 +6757,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Teselas del mapa por Stamen Design, bajo CC BY 3.0" + "text": "Teselas del mapa de Stamen Design, bajo CC BY 3.0. Datos de OpenStreetMap, bajo ODbL" }, "name": "Stamen Terrain" }, @@ -6525,6 +6773,723 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "Universidad de Cape Coast YouthMappers", + "description": "Síguenos en Twitter en {url}", + "extendedDescription": "Este es el identificador oficial del capítulo de Jóvenes Cartografistas de la Universidad de Cape Coast, Ghana. Nos encantan los mapas, los datos abiertos y ayudar a los vulnerables." + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana en Facebook", + "description": "Grupo de Facebook para personas interesadas en OpenStreetMap.", + "extendedDescription": "Mapeadores en la comunidad de Ghana, promocionando los proyectos OpenStreetMap y Humanitarian OpenStreetMap Team (HOT) en Ghana. Únete a nosotros." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana en Twitter", + "description": "Síguenos en Twitter en {url}" + }, + "talk-gh": { + "name": "Lista de correo Talk-gh", + "description": "Talk-gh es la lista de correo oficial de la comunidad OSM de Ghana." + }, + "osm-mg-facebook": { + "name": "Grupo de Facebook OpenStreetMap Madagascar", + "description": "Grupo de Facebook Malgache para gente interesada en OpenStreetMap" + }, + "talk-mg": { + "name": "Lista de correo Talk-mg", + "description": "Lugar para contribuidores, comunidades y usuarios de OpenStreetMap en Madagascar para compartir y debatir." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesh", + "description": "Mejore OpenStreetMap en Bangladesh", + "extendedDescription": "¿Mapeando en Bangladesh? ¿Tiene alguna pregunta, desea conectarse con la comunidad aquí? Únase a nosotros en {url}. ¡Todos son bienvenidos!" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap India - Mapeo participativo del barrio", + "description": "Mejore OpenStreetMap en India", + "extendedDescription": "¿Mapeando en India? ¿Tiene preguntas, quiere conectarse con la comunidad aquí? Únase a nosotros en {url}. ¡Todos son bienvenidos!", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "description": "Únase al evento regional OpenStreetMap 2018 en el State of the Map Asia en India", + "where": "Instituto Indio de Administración, Bangalore, India" + } + } + }, + "OSM-india-mailinglist": { + "name": "Lista de correo de OpenStreetMap India", + "description": "Talk-in es la lista de correo oficial para la comunidad hindú" + }, + "OSM-india-twitter": { + "name": "Twitter de OpenStreetMap India", + "description": "Estamos a solo un tweet: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Free Software Hardware Movement - Facebook", + "description": "Página de Facebook de FSHM para conocer eventos y actividades de la comunidad", + "extendedDescription": "FSHM organiza eventos relacionados con software/hardware, tecnología, activismo y OpenStreetMap. Su página FB es la mejor manera de mantenerse en contacto con sus eventos." + }, + "OSM-India-Puducherry-Matrix": { + "name": "Free Software Hardware Movement - Matrix", + "description": "Grupo Riot de FSHM para discutir, compartir y actualizar actividades de mapeo, eventos en Puducherry y sus alrededores", + "extendedDescription": "Los miembros de la comunidad FSHM comparten sus actualizaciones / experiencias de mapeo de OSM a través del grupo Riot.im, este grupo también se usa para discutir cosas relacionadas con software / hardware, tecnología y activismo gratuitos." + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonesia", + "description": "Mejore OpenStreetMap en Indonesia", + "extendedDescription": "¿Mapeando en Indonesia? ¿Tiene preguntas, quiere conectarse con la comunidad aquí? Únase a nosotros en {Url}. ¡Todos son bienvenidos!" + }, + "OSM-japan-facebook": { + "name": "Comunidad OpenStreetMap Japón", + "description": "Mapeadores y usuarios de OpenStreetMap en Japón" + }, + "OSM-japan-mailinglist": { + "name": "Lista de correo de OpenStreetMap Japón", + "description": "Talk-ja es una lista de correo oficial para la Comunidad Japonesa" + }, + "OSM-japan-twitter": { + "name": "Twitter de OpenStreetMap Japón", + "description": "Hashtag en Twitter: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap Japón", + "description": "Mapeadores y usuarios de OpenStreetMap en Japón" + }, + "OSM-korea-telegram": { + "name": "Canal en Telegram de OSM Korea", + "description": "Canal no-oficial para contribuidores, comunidades y usuarios de OpenStreetMap en Korea para compartir y discutir." + }, + "OSM-MY-facebook": { + "name": "OpenStreetMap Malaysia en Facebook", + "description": "¡Para conversar sobre cualquier cosa relacionada con OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "Foro de OpenStreetMap Malasia", + "description": "Foro oficial de OpenStreetMap Malaysia" + }, + "OSM-MY-matrix": { + "name": "Canal Riot de OpenStreetMap Malaysia", + "description": "¡Todos los mapeadores son bienvenidos! Regístrese en {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongolia", + "description": "Mejore OpenStreetMap en Mongolia", + "extendedDescription": "¿Mapeando en Mongolia? ¿Tiene preguntas, quiere conectarse con la comunidad aquí? Únase a nosotros en {Url}. ¡Todos son bienvenidos!" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Birmania", + "description": "Mejore OpenStreetMap en Birmania", + "extendedDescription": "¿Mapeando en Birmania? ¿Tienes preguntas, quiere contactarse con la comunidad aquí? Únase a nosotros en {Url}. ¡Todos son bienvenidos!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Nepal", + "description": "Mejore OpenStreetMap en Nepal", + "extendedDescription": "¿Mapeando en Nepal? ¿Tiene preguntas, quiere conectarse con la comunidad aquí? Únase a nosotros en {Url}. ¡Todos son bienvenidos!" + }, + "OSM-PH-facebook": { + "name": "Grupo de Facebook OpenStreetMap PH", + "description": "Bienvenido a OpenStreetMap Filipinas, donde animamos a los Filipinos a contribuir al proyecto OpenStreetMap" + }, + "OSM-PH-mailinglist": { + "name": "Lista de correo Talk-ph", + "description": "Una lista de correo para discutir OpenStreetMap en Filipinas" + }, + "OSM-PH-slack": { + "name": "Slack de OpenStreetMap PH", + "description": "¡Todos son bienvenidos! Regístrate en {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "Telegram de OpenStreetMap PH", + "description": "Comunidad local en Telegram no oficial de contribuidores y amigos de OpenStreetMap en Filipinas" + }, + "OSM-RU-forum": { + "name": "Foro OpenStreetMap RU", + "description": "Foro web de OpenStreetMap Rusia" + }, + "OSM-RU-telegram": { + "name": "Telegram de OpenStreetMap RU", + "description": "Chat de telegram de OpenStreetMap Rusia" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka", + "description": "Mejore OpenStreetMap en Sri Lanka", + "extendedDescription": "¿Mapeando en Sri Lanka? ¿Tiene preguntas, quiere conectarse con la comunidad? Únase a nosotros en {Url}. ¡Todos son bienvenidos!" + }, + "OSM-TW-facebook": { + "name": "Comunidad de OpenStreetMap Taiwan", + "description": "Grupo de Facebook para mapeadores y usuarios de OpenStreetMap para discutir asuntos sobre Taiwán." + }, + "OSM-TW-mailinglist": { + "name": "Lista de correo de OpenStreetMap Taiwán", + "description": "Talk-tw es la lista de correo oficial para que las Comunidades discutan asuntos sobre Taiwán" + }, + "OSM-TH-forum": { + "name": "Foro OpenStreetMap TH", + "description": "Foro web de OpenStreetMap Tailandia" + }, + "at-forum": { + "name": "Foro de OpenStreetMap Austria", + "description": "El foro oficial para preguntas sobre OpenStreetMap en y alrededor de Austria" + }, + "at-mailinglist": { + "name": "Lista de correo Talk-at", + "description": "Talk-at es la lista de correo oficial de la comunidad austríaca de OSM" + }, + "at-twitter": { + "name": "Twitter OpenStreetMap Austria", + "description": "OpenStreetMap Austria en Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "Reunión de la comunidad de OSM en Graz", + "description": "Reunión mensual de la comunidad OpenStreetMap en Graz" + }, + "osmgraz-twitter": { + "name": "Comunidad de OSM Graz en twitter", + "description": "Comunidad de OpenstreetMap en Graz en twitter" + }, + "osm-at": { + "name": "OpenStreetMap Austria", + "description": "La plataforma de información sobre OpenStreetMap en Austria" + }, + "byosm": { + "name": "OpenStreetMap Belarús", + "description": "Grupo de telegram de OpenStreetMap Belarús" + }, + "be-facebook": { + "name": "Comunidad OpenStreetMap BE", + "description": "Mapeadores y OpenStreetMap en Facebook en Bélgica" + }, + "be-forum": { + "name": "Foro de OpenStreetMap BE", + "description": "Foro web de OpenStreetMap Bélgica" + }, + "be-irc": { + "name": "IRC de OpenStreetMap Bélgica", + "description": "Únete a #osmbe en irc.oftc.net (puerto 6667)", + "extendedDescription": "Unirse a #osmbe en irc.oftc.net (puerto 6667), está puenteado con el canal de chat Matrix" + }, + "be-mailinglist": { + "name": "Lista de correo de Talk-be", + "description": "Talk-be es la lista de correo oficial para la comunidad belga de OSM" + }, + "be-matrix": { + "name": "Canal Matrix de OpenStreetMap BE", + "description": "¡Todos los mapeadores son bienvenidos!", + "extendedDescription": "La mayoría de las charlas ocurren en el canal \"OpenStreetMap Belgium\". ¡Puede preguntar cualquier cosa allí! Las otras salas son para temas específicos." + }, + "be-meetup": { + "name": "Grupo de encuentro OpenStreetMap Bélgica", + "description": "Reuniones en la vida real de todos los interesados en OpenStreetMap", + "extendedDescription": "Las reuniones presenciales son geniales para conocer a otros mapeadores, hacerles preguntas y aprender mucho. ¡Son especialmente bienvenidos los nuevos contribuidores!" + }, + "be-twitter": { + "name": "Twitter OpenStreetMap Bélgica", + "description": "OSM Bélgica en Twitter: @osm_be" + }, + "talk-cz-mailinglist": { + "name": "Lista de correo Talk-cz", + "description": "Talk-cz es la lista de correo oficial para la comunidad checa" + }, + "dk-forum": { + "name": "Foro web de OpenStreetMap Dinamarca", + "description": "Foro web de OpenStreetMap Dinamarca" + }, + "dk-irc": { + "name": "IRC de OpenStreetMap Dinamarca", + "description": "Únase a #osm-dk en irc.oftc.net (puerto 6667)" + }, + "dk-mailinglist": { + "name": "Lista de correo Talk-dk", + "description": "Una lista de correo para discutir OpenStreetMap en Dinamarca" + }, + "fr-facebook": { + "name": "Página de Facebook de OpenStreetMap Francia", + "description": "Página de Facebook de OpenStreetMap Francia" + }, + "fr-forum": { + "name": "Foro web de OpenStreetMap Francia", + "description": "Foro web de OpenStreetMap Francia" + }, + "fr-irc": { + "name": "OpenStreetMap Francia en IRC", + "description": "Únase a #osm-fr en irc.oftc.net (puerto 6667)" + }, + "fr-mailinglist": { + "name": "Lista de correo Talk-fr", + "description": "Lista de correo Talk-fr" + }, + "fr-twitter": { + "name": "OpenStreetMap Francia en Twitter", + "description": "OpenStreetMap Francia en Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "Lista de correo de Berlín", + "description": "Esta es la lista de correo de la comunidad de OSM de Berlín" + }, + "de-berlin-meetup": { + "name": "Encuentro de OpenStreetMap Berlín-Brandenburgo", + "description": "Mapeadores y usuarios en OpenStreetMap en el área de Berlín" + }, + "de-berlin-telegram": { + "name": "@osmberlin en Telegram", + "description": "Chat de Telegram de OpenStreetMap Berlín" + }, + "de-berlin-twitter": { + "name": "Twitter de OpenStreetMap Berlín", + "description": "Síguenos en Twitter: {url}" + }, + "de-forum": { + "name": "Foro de OpenStreetMap DE", + "description": "Foro web de OpenStreetMap Alemania" + }, + "de-irc": { + "name": "IRC de OpenStreetMap Alemania", + "description": "Únase a #osm-de en irc.oftc.net (puerto 6667)" + }, + "de-mailinglist": { + "name": "Lista de correo Talk-de", + "description": "Talk-de es la lista de correo oficial para la comunidad alemana de OSM" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "Lista de correo OWL", + "description": "Esta es la lista de correo de la comunidad Ostwestfalen-Lippe de OSM" + }, + "osm-de": { + "name": "OpenStreetMap Alemania", + "description": "La plataforma de información sobre OpenStreetMap en Alemania" + }, + "hu-facebook": { + "name": "Facebook de OpenStreetMap HU", + "description": "Facebook de Mapeadores y OpenStreetMap en Hungría" + }, + "hu-forum": { + "name": "Foro OpenStreetMap HU", + "description": "Foro web de OpenStreetMap Hungría" + }, + "hu-meetup": { + "name": "Meetup de OpenStreetMap Hungría", + "description": "La plataforma para organizar encuentros en Hungría" + }, + "it-facebook": { + "name": "Facebook de OpenStreetMap Italia", + "description": "Únase a la comunidad de OpenStreetMap Italia en Facebook" + }, + "it-irc": { + "name": "IRC de OpenStreetMap Italia", + "description": "Únase a #osm-it en irc.oftc.net (puerto 6667)" + }, + "it-mailinglist": { + "name": "Lista de correo de Talk-it", + "description": "Talk-it es la lista de correo oficial de la comunidad OSM italiana" + }, + "it-twitter": { + "name": "Twitter de OpenStreetMap Italia", + "description": "Síganos en Twitter en {url}" + }, + "OSM-Rome-meetup": { + "name": "Encuentro de mapeadores de Roma", + "description": "Mejore OpenStreetMap en el área de Roma", + "extendedDescription": "Nuestro objetivo es ser un recurso para que las personas discutan y compartan conocimientos sobre la utilización de conjuntos de datos geográficos libres, especialmente OpenStreetMap, y software geoespacial abierto que gestiona, edita y muestra datos geográficos, y aboga por su uso en Lazio." + }, + "South-Tyrol-Mailing-List": { + "name": "Lista de correo de OpenStreetMap para Tirol del Sur", + "description": "Lista de conversaciones regionales de OpenStreetMap Italia para Tirol del Sur" + }, + "talk-it-lazio": { + "name": "OpenStreetMap IT Lazio", + "description": "¡Todos son bienvenidos! Regístrese en {signupUrl}", + "extendedDescription": "Lista de correo para el área de Roma y Lazio." + }, + "Trentino-Mailing-List": { + "name": "Lista de correo de OpenStreetMap para Trentino", + "description": "Lista de conversaciones regionales de OpenStreetMap Italia para Trentino" + }, + "no-forum": { + "name": "Foro web de OpenStreetMap Noruega", + "description": "Foro web de OpenStreetMap Noruega" + }, + "no-irc": { + "name": "OpenStreetMap Norway en IRC", + "description": "Sala de chat para mapeadores y usuarios de OpenStreetMap, desarrolladores y entusiastas en Noruega" + }, + "no-mailinglist": { + "name": "Lista de correo de OpenStreetMap Noruega", + "description": "Lista de correo para mapeadores y usuarios de OpenStreetMap, desarrolladores y entusiastas en Noruega" + }, + "OSM-PL-facebook-group": { + "name": "Grupo de Facebook de OpenStreetMap Polonia", + "description": "Grupo para mapeadores y usuarios de OpenStreetMap en Polonia" + }, + "OSM-PL-forum": { + "name": "Foro de OpenStreetMap Polonia", + "description": "Foro de la comunidad polaca OpenStreetMap" + }, + "OSM-ES-mailinglist": { + "name": "Lista de correo Talk-es", + "description": "Una lista de correo para discutir OpenStreetMap en España" + }, + "OSM-ES-telegram": { + "name": "@OSMes en Telegram", + "description": "Grupo de Telegram de OpenStreetMap España" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "Proporcionar servicios e información OSM para la comunidad local en Suecia" + }, + "se-facebook": { + "name": "Facebook de OpenStreetMap Suecia", + "description": "OpenStreetMap Suecia en Facebook" + }, + "se-forum": { + "name": "Foro Web de OpenStreetMap Suecia", + "description": "Foro Web de OpenStreetMap Suecia" + }, + "se-irc": { + "name": "IRC de OpenStreetMap Suecia", + "description": "Únase a #osm.se en irc.oftc.net (puerto 6667)" + }, + "se-mailinglist": { + "name": "Lista de correo Talk-se", + "description": "Una lista de correo para discutir OpenStreetMap en Suecia" + }, + "se-twitter": { + "name": "OpenStreetMap Suecia en Twitter", + "description": "Síguenos en Twitter en {url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "Reunión mensual pub de East Midlands (Nottingham)", + "description": "Reunión social de mapeadores y usuarios de East Midlands", + "extendedDescription": "Un grupo se ha estado reuniendo desde marzo de 2011, inicialmente en Nottingham, y más recientemente en Derby, y de vez en cuando en otras partes de East Midlands. Estas son reuniones sociales, pero son un excelente lugar para venir y hacer preguntas específicas sobre OSM, ya sea en el área o en general. En los meses de verano usualmente hacemos un mapeo ligero durante una hora en las cercanías de nuestro lugar de reunión. El grupo como un todo tiene un interés especial en el mapeo de los derechos de paso públicos y de vez en cuando tiene reuniones de mapeo para este propósito." + }, + "gb-mailinglist": { + "name": "Lista de correo de Talk-gb", + "description": "Talk-gb es la lista de comunicación principal para la comunidad OSM británica (incluida Irlanda del Norte)" + }, + "mappa-mercia-group": { + "name": "Grupo local Mappa Mercia", + "description": "Un hogar para entusiastas de OpenStreetMap en las Midlands", + "extendedDescription": "Mappa Mercia es un proyecto para hacer crecer OpenStreetMap en West Midlands, Reino Unido. Organizamos eventos comunitarios, proporcionamos capacitación y apoyamos a las organizaciones locales que desean abrir sus datos." + }, + "gb-irc": { + "name": "IRC de OpenStreetMap Reino Unido", + "description": "Únase a #osm-gb en irc.oftc.net (puerto 6667)", + "extendedDescription": "Únase a #osm-gb en irc.oftc.net (puerto 6667), sea paciente y espere unos minutos si hace una pregunta" + }, + "OSM-CA-Slack": { + "name": "Slack de OSM-CA", + "description": "¡Todos son bienvenidos! Regístrese en {signupUrl}." + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver", + "description": "Mapeadores y usuarios de OpenStreetMap en el área de Vancouver, BC" + }, + "OSM-CU-telegram": { + "name": "OSM Cuba en Telegram", + "description": "Chat de Telegram de OpenStreetMap Cuba" + }, + "OSM-NI-telegram": { + "name": "OSM Nicaragua en Telegram", + "description": "Chat de Telegram de OpenStreetMap Nicaragua " + }, + "Bay-Area-OpenStreetMappers": { + "name": "OpenStreetMappers del área de la bahía", + "description": "Mejore OpenStreetMap en el área de la bahía", + "extendedDescription": "En este grupo se trata de hacer crecer la comunidad OpenStreetMap aquí en el Área de la Bahía. Nuestros eventos están abiertos a todos, desde entusiastas del código abierto, ciclistas, profesionales SIG, geocachers y más. Cualquier persona y todos los que estén interesados en mapas, creación de mapas y datos de mapa gratuitos pueden unirse a nuestro grupo y asistir a nuestros eventos." + }, + "Central-Pennsylvania-OSM": { + "name": "OSM Pensilvania Central", + "description": "Comunidad de mapeo en línea con sede en State College, PA" + }, + "Code-for-San-Jose-Slack": { + "name": "Slack de Code for San Jose", + "description": "¡Todos son bienvenidos! Regístrese en {signupUrl}, luego únase al canal #osm channel." + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "El grupo de usuarios de OpenStreetMap para Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth y todas las ciudades en el medio están repletas de gente creativa y conocedora de la tecnología. La visión de este grupo de usuarios es encontrar nuevas formas de utilizar el increíble recurso de OSM." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Encuentro para entusiastas del mapa en el área de Filadelfia", + "extendedDescription": "GeoPhilly une desarrolladores, geógrafos, geeks de datos, entusiastas del código abierto, hackers cívicos y adictos al mapa en nuestro amor compartido por los mapas y las historias que cuentan. Si usa mapas como parte de su trabajo o simplemente quiere aprender más, este es lugar de encuentro para usted. Nuestros eventos apuntan a ser abiertos, amigables, educativos y sociales, y abarcan desde happy hours hasta lightning talk -charla relámpago- o incluso talleres. ¡Ven a crear una comunidad geoespacial diversa e inspiradora en Filadelfia con nosotros!" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "Mapeadores y entusiastas de OpenStreetMap en el área de Twin Cities", + "extendedDescription": "¡Conecta a los entusiastas de OpenStreetMap en Minnesota y Twin Cities!" + }, + "Mapping-DC-meetup": { + "name": "Mapeando DC", + "description": "Mejore OpenStreetMap en el área de DC", + "extendedDescription": "Somos un grupo de cartógrafos voluntarios que buscan mejorar OpenStreetMap en el área de DC. También pretendemos enseñar a otros sobre el ecosistema OSM, análisis de datos, cartografía y SIG. Nos reunimos cada dos meses para enfocarnos en un área de nuestra ciudad." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Mapeadores y usuarios de OpenStreetMap, en Portland, ME", + "extendedDescription": "Maptime es, literalmente, el momento de hacer mapas. Nuestra misión es abrir las puertas de la posibilidad cartográfica a cualquier persona interesada creando un tiempo y espacio para el aprendizaje colaborativo, la exploración y la creación de mapas utilizando herramientas y tecnologías de mapeo." + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Mejore OpenStreetMap en el área de Cleveland", + "extendedDescription": "Open Geo Cleveland pretende ser un recurso para que las personas discutan y compartan conocimientos sobre el uso de conjuntos de datos geográficos libres, especialmente OpenStreetMap, y software geoespacial abierto que gestiona, edita y muestra datos geográficos, y aboga por su uso en el noreste de Ohio. También somos un capítulo maptime =)" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Editores y usuarios de OpenStreetMap en el área de Boston", + "extendedDescription": "OpenStreetMap es el mapa del mundo gratuito y abierto al estilo wiki, con cientos de miles de contribuciones diarias de personas como usted. ¡Editar el mapa es simple y divertido! ¡Únete a nosotros tanto en el interior como en el exterior en nuestro esfuerzo por crear el mejor mapa del área de Boston y el resto del mundo!" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Central Salish Sea", + "description": "Mapeadores y usuarios de OpenStreetMap alrededor de Mount Vernon, WA", + "extendedDescription": "OpenStreetMap es un mapa del mundo hecho por personas como usted. Es un mapa que creas, que se regala gratis como wikipedia. Visite osm.org para obtener más información. ¡Nos reunimos todo el tiempo para hablar de mapas, hacer mapas y divertirnos!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "El grupo de usuarios de OpenStreetMap para Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "description": "Editores y usuarios de OpenStreetMap en el Estado de Colorado, EE.UU.", + "extendedDescription": "OpenStreetMap (OSM) Colorado es una colaboración local de personas interesadas en contribuir con sus esfuerzos para crear mapas gratuitos. Alentamos a todos nuestros cartógrafos a organizar o sugerir eventos de mapeo en todo el estado. Los encuentros pueden ser simples reuniones sociales, entrenamiento básico a avanzado de OSM o actividades de mapeo comunitario." + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Mapeadores y usuarios de OpenStreetMap, desarrolladores y entusiastas en el área Metropolitana de Nueva York" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Mapeadores y usuarios de OpenStreetMap en el área de Portland", + "extendedDescription": "OpenStreetMap (OSM) es un mapa del mundo creado por personas como tú. Es un mapa que tú creas, que se regala gratis como wikipedia. Visita osm.org para obtener más información, ¡y únete a nosotros en un encuentro para hablar de mapas, contribuir con OSM y divertirse!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Editores y usuarios de OpenStreetMap en el área de Seattle" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Southern California", + "description": "¡Divirtámonos, contribuyamos con algo a Los Ángeles y aprendamos a mapear!", + "extendedDescription": "OpenStreetMap (OSM) Southern California es para todos aquellos interesados ​​en mapear para trabajar juntos con OpenStreetMap. OpenStreetMap, la Wikipedia de mapas, es un mapa de código abierto y gratuito creado por más de 1,000,000 de voluntarios en todo el mundo. Todos son bienvenidos. Si no conoce OpenStreetMap, le enseñaremos. Si tiene una idea para un proyecto de mapeo o incluso una excursión que el grupo pueda hacer, ¡genial!" + }, + "OSM-South-Bay": { + "name": "OSM South Bay", + "description": "Noches de mapeo organizadas por Code for San Jose", + "extendedDescription": "Code for San Jose, la brigada local del Code for America, organiza noches de mapeo mensuales los jueves por la noche en el centro de San José. Conozca a otros mapeadores de South Bay, ayude con proyectos de mapeo locales y escuche sobre otros proyectos de tecnología cívica. No se requieren habilidades de programación ni GIS." + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Tampa Bay", + "description": "Editores y usuarios de OpenStreetMap en el área de Tampa Bay", + "extendedDescription": "El grupo OSM de residentes locales de Tampa Bay para reunirnos y construir el mapa definitivo de Tampa Bay con OpenStreetMap, el mapa libre y editable del mundo. Si te van los mapas, el código abierto, GPS, senderismo, ciclismo, etcetera, te encantará trabajar con OpenStreetMap -- ¡así que únete! Nos juntaremos y haremos mapas y hablaremos de nuevos temas una vez al mes o así." + }, + "OSM-US-Slack": { + "name": "Slack de OpenStreetMap EE.UU.", + "description": "¡Todos son bienvenidos! Regístrate en {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap EE.UU.", + "description": "Ayudamos a crecer y mejorar OpenStreetMap en los Estados Unidos.", + "extendedDescription": "Apoyamos OpenStreetMap celebrando conferencias anuales, proporcionando recursos comunitarios, creando alianzas y dando a conocer. Únase a OpenStreetMap EE.UU. aquí: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah", + "description": "Editores y usuarios de OpenStreetMap en el área de Salt Lake City", + "extendedDescription": "Las actividades pueden incluir cosas como talleres para Aprender a Hacer Mapas, actividades de mapeo y recolección de datos al aire libre. Los eventos tendrán lugar en el área de SLC, al menos inicialmente. Estamos buscando mapeadores experimentados, así como personas nuevas en OSM. ¡Únase y mapeemos juntos!" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming", + "description": "Editores y usuarios de OpenStreetMap en el área de Wyoming", + "extendedDescription": "OpenStreetMap (OSM) Wyoming es una colaboración local de personas interesadas en contribuir con sus esfuerzos para crear mapas gratuitos. Alentamos a todos nuestros cartógrafos a organizar o sugerir eventos de mapeo en todo el estado. Las actividades de reunión pueden ser simples reuniones sociales, entrenamiento básico a avanzado de OSM o fiestas de mapeo de la comunidad." + }, + "PHXGeo-meetup": { + "name": "Meetup de PHXGeo", + "description": "Editores y usuarios de OpenStreetMap en el área de Phoenix, AZ", + "extendedDescription": "Este es un grupo de encuentro para aquellos en el área de Phoenix que les gustan los mapas, GIS, OpenStreetMap, cartografía y cualquier cosa similar." + }, + "PHXGeo-twitter": { + "name": "Twitter de PHXGeo", + "description": "Síguenos en Twitter en {url}" + }, + "Western-Slope-facebook": { + "name": "Facebook de Western Slope OSM", + "description": "Editores y usuarios de OpenStreetMap en Grand Junction, CO" + }, + "Western-Slope-meetup": { + "name": "Meetup de Western Slope OSM", + "description": "Editores y usuarios de OpenStreetMap en Grand Junction, CO", + "extendedDescription": "El objetivo de este grupo es presentar OpenStreetMap a la comunidad, desarrollar una comunidad de mapeadores, crear datos geográficos lo más increíble posible utilizando cualquier método que podamos y, finalmente, crear una estrategia con el fin de obtener esta información de nuestra comunidad. ¡Imagine la señalización precisa del sendero! ¡Imagine un mayor desarrollo de las ciclovías! ¡Imagina lo que quieras, esa es la gracia de OpenStreetMap!" + }, + "Maptime-Australia-Slack": { + "name": "Slack de Maptime Australia", + "description": "Regístrate en {signupUrl}" + }, + "talk-au": { + "name": "Lista de correo Talk-au", + "description": "Lugar para que los mapeadores australianos chateen" + }, + "OSM-AR-facebook": { + "name": "Facebook de OpenStreetMap Argentina", + "description": "Unite a la comunidad de OpenStreetMap Argentina en Facebook", + "extendedDescription": "Novedades de la comunidad local" + }, + "OSM-AR-forum": { + "name": "Foro web de OpenStreetMap Argentina", + "description": "Unite al foro web de OpenStreetMap Argentina", + "extendedDescription": "Ideal para discusiones largas o importantes. Tiempo de respuesta lento. " + }, + "OSM-AR-irc": { + "name": "IRC de OpenStreetMap Argentina", + "description": "Unite a #osm-ar en irc.oftc.net (puerto 6667)", + "extendedDescription": "Puede que encuentres al usuario más geek de la comunidad." + }, + "OSM-AR-mailinglist": { + "name": "Lista de correo Talk-ar", + "description": "Lista de correo electrónico histórica. Casi sin uso hoy en día." + }, + "OSM-AR-telegram": { + "name": "Telegram de OpenStreetMap Argentina", + "description": "Unite a la comunidad de OpenStreetMap Argentina en Telegram", + "extendedDescription": "El canal más activo de la comunidad, ideal para charlar y obtener respuestas a tus preguntas al instante. ¡Todos son bienvenidos!" + }, + "OSM-AR-twitter": { + "name": "Twitter de OpenStreetMap Argentina", + "description": "Seguinos en Twitter en {url}", + "extendedDescription": "Novedades de la comunidad local y OpenStreetMap en general. " + }, + "OSM-BO-mailinglist": { + "name": "Lista de correo talk-bo", + "description": "Talk-bo es la lista de correo oficial de la comunidad boliviana de OpenStreetMap", + "extendedDescription": "¿Mapeando en Bolivia? ¿Tiene preguntas, quiere conectarse con la comunidad aquí? Únase a nosotros en {url}. ¡Todos son bienvenidos!" + }, + "Bahia-telegram": { + "name": "Grupo de Telegram de OpenStreetMap Bahia", + "description": "Únete a la comunidad de OpenStreetMap Bahia en Telegram", + "extendedDescription": "Únase a la comunidad para obtener más información sobre OpenStreetMap, hacer preguntas o participar en nuestras reuniones. ¡Todos son bienvenidos!" + }, + "DF-telegram": { + "name": "Grupo de Telegram de OpenStreetMap Brasilia", + "description": "Únase a la comunidad de OpenStreetMap Brasília en Telegram", + "extendedDescription": "Únase a la comunidad para obtener más información sobre OpenStreetMap, hacer preguntas o participar en nuestras reuniones. ¡Todos son bienvenidos!" + }, + "OSM-br-mailinglist": { + "name": "Lista de correo Talk-br", + "description": "Una lista de correo para discutir OpenStreetMap en Brasil" + }, + "OSM-br-telegram": { + "name": "Telegram de OpenStreetMap Brasil", + "description": "Únase a la comunidad de OpenStreetMap Brasil en Telegram", + "extendedDescription": "Únase a la comunidad para obtener más información sobre OpenStreetMap, hacer preguntas o participar en nuestras reuniones. ¡Todos son bienvenidos!" + }, + "OSM-br-twitter": { + "name": "Twitter de OpenStreetMap Brasil", + "description": "Síguenos en Twitter en {url}" + }, + "OSM-CL-facebook": { + "name": "Facebook de OpenStreetMap Chile", + "description": "Únase a la comunidad de OpenStreetMap Chile en Facebook", + "extendedDescription": "Únase a la comunidad para obtener más información sobre OpenStreetMap, hacer preguntas o participar en nuestras reuniones. ¡Todos son bienvenidos!" + }, + "OSM-CL-mailinglist": { + "name": "Lista de correo Talk-br", + "description": "Una lista de correo para discutir OpenStreetMap en Chile" + }, + "OSM-CL-telegram": { + "name": "Telegram de OpenStreetMap Chile", + "description": "Únase a la comunidad de OpenStreetMap Chile en Telegram", + "extendedDescription": "Únase a la comunidad para obtener más información sobre OpenStreetMap, hacer preguntas o participar en nuestras reuniones. ¡Todos son bienvenidos!" + }, + "OSM-CL-twitter": { + "name": "Twitter de OpenStreetMap Chile", + "description": "Síguenos en Twitter en {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá", + "description": "Somos un grupo de mapeadores interesados ​​en mapear en OpenStreetMap alrededor de Bogotá.", + "extendedDescription": "Aprenda a recopilar datos en el campo y digitalice en OpenStreetMap. ¡No es necesario tener conocimiento previo! Solo necesitas el deseo de participar, aprender y divertirte." + }, + "OSM-CO-facebook": { + "name": "Facebook de OpenStreetMap Colombia", + "description": "Únase a la comunidad de OpenStreetMap Colombia en Facebook", + "extendedDescription": "Únase a la comunidad para obtener más información sobre OpenStreetMap. ¡Todos son bienvenidos!" + }, + "OSM-CO-mailinglist": { + "name": "Lista de correo Talk-co", + "description": "Una lista de correo para discutir OpenStreetMap en Colombia" + }, + "OSM-CO-telegram": { + "name": "OSM Colombia en Telegram", + "description": "Chat de Telegram de OpenStreetMap Colombia" + }, + "OSM-CO-twitter": { + "name": "Twitter de OpenStreetMap Colombia", + "description": "Síguenos en Twitter en {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Colombia", + "description": "Noticias de la comunidad OpenStreetMap Colombia y la Fundación OSMCo" + }, + "OSM-EC-telegram": { + "name": "OSM Ecuador en Telegram", + "description": "Chat de Telegram de OpenStreetMap Ecuador" + }, + "OSM-PY-telegram": { + "name": "OSM Paraguay en Telegram", + "description": "Chat de Telegram de OpenStreetMap Paraguay" + }, + "OSM-PE-facebook": { + "name": "Facebook de OpenStreetMap Perú", + "description": "Únase a la comunidad de OpenStreetMap Perú en Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Lista de correo de Talk-pe", + "description": "La lista de correo oficial para la comunidad de OpenStreetMap Perú" + }, + "OSM-PE-matrix": { + "name": "Chat de Matrix de OpenStreetMap Perú", + "description": "Chatea con otros miembros de la comunidad OpenStreetMap Perú en Matrix." + }, + "OSM-PE-telegram": { + "name": "Telegram de OpenStreetMap Perú", + "description": "Únase a la comunidad de OpenStreetMap Perú en Telegram" + }, + "OSM-PE-twitter": { + "name": "Twitter de OpenStreetMap Perú", + "description": "Síganos en Twitter en {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap Perú", + "description": "Noticias y recursos para la comunidad de OpenStreetMap Perú" + }, + "OSM-Facebook": { + "name": "OpenStreetMap en Facebook", + "description": "Dénos me gusta en Facebook para recibir noticias y actualizaciones sobre OpenStreetMap." + }, + "OSM-help": { + "name": "Ayuda de OpenStreetMap", + "description": "Haga una pregunta y obtenga respuestas en el sitio de preguntas y respuestas dirigido por la comunidad de OSM.", + "extendedDescription": "{url} es para todos los que necesitan ayuda con OpenStreetMap. Si usted es un mapeador principiante o tiene una pregunta técnica, ¡estamos aquí para ayudarlo!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap en Reddit", + "description": "/r/openstreetmap/ es un gran lugar para aprender más sobre OpenStreetMap. ¡Pregúntenos cualquier cosa!" + }, + "OSM-Twitter": { + "name": "Twitter de OpenStreetMap", + "description": "Síganos en Twitter en {url}" + }, + "OSMF": { + "name": "Fundación OpenStreetMap", + "description": "OSMF es una organización sin fines de lucro con sede en el Reino Unido que respalda el proyecto OpenStreetMap", + "extendedDescription": "OSMF apoya a OpenStreetMap mediante la recaudación de fondos, el mantenimiento de los servidores que impulsan OSM, la organización de la conferencia anual State of the Map y la coordinación de los voluntarios que mantienen OSM en funcionamiento. Puede mostrar su apoyo y tener una voz en la dirección de OpenStreetMap uniéndose como miembro de OSMF aquí: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Únase a nosotros durante 3 días en Milán, Italia, para la conferencia anual mundial de OpenStreetMap, que reúne a todos en la comunidad para socializar, compartir y aprender.", + "where": "Milán, Italia" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/et.json b/vendor/assets/iD/iD/locales/et.json index a737a8c0b..e732f9d35 100644 --- a/vendor/assets/iD/iD/locales/et.json +++ b/vendor/assets/iD/iD/locales/et.json @@ -155,7 +155,6 @@ "key": "C", "annotation": "Ühendatud {n} objekti.", "not_eligible": "Neid objekte ei saa ühendada.", - "restriction": "Neid objekte ei saa ühendada, kuna vähemalt üks neist on relatsiooni \"{relation}\" liige.", "incomplete_relation": "Neid objekte ei saa ühendada, kuna vähemalt üks neist ei ole täielikult alla laaditud.", "conflicting_tags": "Neid objekte ei saa ühendada, kuna osa nende silte on konfliktsete väärtustega." }, @@ -530,13 +529,7 @@ } }, "success": { - "edited_osm": "Sa täiendasid OSM-i!", "just_edited": "Täiendasid just OpenStreetMapi!", - "view_on_osm": "Vaata OSM-is", - "facebook": "Jaga Facebookis", - "twitter": "Jaga Twitteris", - "google": "Jaga Google+-is", - "help_html": "Sinu muudatused peaksid ilmuma kihil \"Standard\" mõne minuti jooksul. Teiste kihtide ja teatud objektidega võib kauem minna.", "help_link_text": "Üksikasjad" }, "confirm": { @@ -894,6 +887,9 @@ "cycleway:right": "Paremas servas" } }, + "dance/style": { + "label": "Tantsustiilid" + }, "date": { "label": "Kuupäev" }, @@ -903,6 +899,46 @@ "denomination": { "label": "Usulahk" }, + "direction": { + "label": "Suund (kraade päripäeva)", + "placeholder": "45, 90, 180, 270" + }, + "direction_cardinal": { + "label": "Suund", + "options": { + "E": "Ida", + "ENE": "Idakirre", + "ESE": "Idakagu", + "N": "Põhi", + "NE": "Kirre", + "NNE": "Põhjakirre", + "NNW": "Põhjaloe", + "NW": "Loe", + "S": "Lõuna", + "SE": "Kagu", + "SSE": "Lõunakagu", + "SSW": "Lõunaedel", + "SW": "Edel", + "W": "Lääs", + "WNW": "Lääneloe", + "WSW": "Lääneedel" + } + }, + "direction_clock": { + "label": "Suund", + "options": { + "anticlockwise": "Vastupäeva", + "clockwise": "Päripäeva" + } + }, + "direction_vertex": { + "label": "Suund", + "options": { + "backward": "Tagasi", + "both": "Mõlemad / Kõik", + "forward": "Edasi" + } + }, "dock": { "label": "Tüüp" }, @@ -963,6 +999,9 @@ "healthcare/speciality": { "label": "Erialad" }, + "horse_riding": { + "label": "Ratsutamine" + }, "iata": { "label": "IATA" }, @@ -1009,6 +1048,10 @@ "maxspeed": { "label": "Kiiruspiirang" }, + "maxspeed/advisory": { + "label": "Soovitatav suurim kiirus", + "placeholder": "30, 50, 70..." + }, "name": { "label": "Nimi", "placeholder": "Üldlevinud nimi (kui on)" @@ -1061,7 +1104,9 @@ "oneway": { "label": "Ühesuunaline", "options": { + "alternating": "Vahelduv", "no": "Ei", + "reversible": "Ümberpööratav", "undefined": "Eeldatavasti mitte", "yes": "Jah" } @@ -1069,7 +1114,9 @@ "oneway_yes": { "label": "Ühesuunaline", "options": { + "alternating": "Vahelduv", "no": "Ei", + "reversible": "Ümberpööratav", "undefined": "Eeldatavasti Jah", "yes": "Jah" } @@ -1099,7 +1146,6 @@ "label": "Makseviisid" }, "phone": { - "label": "Telefon", "placeholder": "+372 567 8901" }, "population": { @@ -1111,9 +1157,20 @@ "railway": { "label": "Tüüp" }, + "railway/signal/direction": { + "label": "Suund", + "options": { + "backward": "Tagasi", + "both": "Mõlemad / Kõik", + "forward": "Edasi" + } + }, "recycling_accepts": { "label": "Võtab vastu" }, + "ref/isil": { + "label": "ISIL-kood" + }, "relation": { "label": "Tüüp" }, @@ -1260,9 +1317,20 @@ "traffic_signals": { "label": "Tüüp" }, + "traffic_signals/direction": { + "label": "Suund", + "options": { + "backward": "Tagasi", + "both": "Mõlemad / Kõik", + "forward": "Edasi" + } + }, "trees": { "label": "Puud" }, + "usage_rail": { + "label": "Kasutusostarve" + }, "visibility": { "label": "Nähtavus" }, @@ -1288,6 +1356,9 @@ "wheelchair": { "label": "Pääs ratastooliga" }, + "wholesale": { + "label": "Hulgikaubandus" + }, "width": { "label": "Laius (meetrites)" }, @@ -1322,6 +1393,9 @@ "name": "Lennuterminal", "terms": "terminal,lennujaam" }, + "allotments/plot": { + "name": "Ühisaia krunt" + }, "amenity": { "name": "Hüve" }, @@ -1499,6 +1573,9 @@ "name": "Turg", "terms": "Turuplats" }, + "amenity/monastery": { + "name": "Kloostriala" + }, "amenity/motorcycle_parking": { "name": "Mootorratta parkla" }, @@ -1520,7 +1597,8 @@ "terms": "parkla" }, "amenity/pharmacy": { - "name": "Apteek" + "name": "Apteek", + "terms": "ravimid" }, "amenity/place_of_worship": { "name": "Pühakoda", @@ -1590,6 +1668,9 @@ "name": "Varjualune", "terms": "ulualune,räästaalune,peavari" }, + "amenity/smoking_area": { + "name": "Suitsetamise koht" + }, "amenity/social_facility": { "name": "Sotsiaalkeskus", "terms": "Sotsiaalamet" @@ -1706,6 +1787,10 @@ "barrier/hedge": { "name": "Hekk" }, + "barrier/kerb": { + "name": "Kiviääris", + "terms": "ääris" + }, "barrier/kissing_gate": { "name": "Karjavärav" }, @@ -1741,6 +1826,10 @@ "name": "Küün", "terms": "Tall, laut" }, + "building/bungalow": { + "name": "Bangalo", + "terms": "bungalo" + }, "building/bunker": { "name": "Punker" }, @@ -1757,6 +1846,10 @@ "building/church": { "name": "Kirikuhoone" }, + "building/civic": { + "name": "Kultuurihoone", + "terms": "linna,keskus,seltsimaja,rahvamaja" + }, "building/college": { "name": "Kolledžihoone" }, @@ -1775,6 +1868,14 @@ "building/entrance": { "name": "Sissepääs" }, + "building/farm": { + "name": "Maamaja", + "terms": "talumaja,elumaja,elamu,maja,rehi*" + }, + "building/farm_auxiliary": { + "name": "Taluhoone", + "terms": "hoone,ait,abihoone,laut,küün" + }, "building/garage": { "name": "Garaaž", "terms": "Garaaz" @@ -1819,6 +1920,10 @@ "building/roof": { "name": "Katus" }, + "building/ruins": { + "name": "Hoone varemed", + "terms": "varemed,purunenud,maha jäätud" + }, "building/school": { "name": "Koolihoone", "terms": "õppehoone,algkool,keskkool" @@ -1834,16 +1939,26 @@ "name": "Tall", "terms": "Hobusetall" }, + "building/stadium": { + "name": "Staadionihoone" + }, "building/static_caravan": { "name": "Paikne haagismaja", "terms": "Haagiselamu,haagismaja,teisaldatav maja" }, + "building/temple": { + "name": "Templihoone", + "terms": "tempel" + }, "building/terrace": { "name": "Terrassmaja" }, "building/train_station": { "name": "Raudteejaam" }, + "building/transportation": { + "name": "Transpordihoone" + }, "building/university": { "name": "Ülikoolihoone" }, @@ -1854,6 +1969,9 @@ "name": "Kämpingukoht", "terms": "karavaniplats,kämpinguplats,telgiplats,telgikoht" }, + "circular": { + "name": "Liiklusring" + }, "club": { "name": "Klubi" }, @@ -2012,6 +2130,10 @@ "emergency/phone": { "name": "Hädaabi telefon" }, + "emergency/water_tank": { + "name": "Tuletõrjevee mahuti", + "terms": "veevõtukoht,tuletõrjemahuti" + }, "entrance": { "name": "Sisse- ja Väljapääs" }, @@ -2059,6 +2181,10 @@ "name": "Hooldekodu", "terms": "hospiits" }, + "healthcare/laboratory": { + "name": "Meditsiiniline labor", + "terms": "labor*,verelabor*" + }, "healthcare/midwife": { "name": "Ämmaemand" }, @@ -2112,6 +2238,9 @@ "highway/motorway_link": { "name": "Kiirtee ühenduslõik" }, + "highway/passing_place": { + "name": "Möödasõidukoht" + }, "highway/path": { "name": "Rada" }, @@ -2297,6 +2426,10 @@ "landuse/forest": { "name": "Metsamaa" }, + "landuse/garages": { + "name": "Maakasutus garaažidele", + "terms": "garaažid" + }, "landuse/grass": { "name": "Muru" }, @@ -2376,6 +2509,13 @@ "leisure": { "name": "Vaba aeg" }, + "leisure/amusement_arcade": { + "name": "Videomängumasin", + "terms": "telekamäng,mängukonsool" + }, + "leisure/beach_resort": { + "name": "Rannakuurort" + }, "leisure/bowling_alley": { "name": "Boolingusaal", "terms": "bowling,keegel,keeglisaal,hobikeegel" @@ -2384,6 +2524,9 @@ "name": "Tantsusaal", "terms": "tantsuhall" }, + "leisure/dancing_school": { + "name": "Tantsukool" + }, "leisure/dog_park": { "name": "Koerapark" }, @@ -2508,6 +2651,10 @@ "name": "Stoll", "terms": "suue,kaevandus,sissepääs,horisontaalne,kaeveõõne,rõhtkaeve,koobas" }, + "man_made/antenna": { + "name": "Antenn", + "terms": "raadio,saatja,mast,side,televisiooni,edastus,levi,signaal" + }, "man_made/breakwater": { "name": "Lainemurdja", "terms": "sadamatamm,kaitsetamm,tamm" @@ -2541,6 +2688,9 @@ "man_made/observation": { "name": "Vaatlustorn" }, + "man_made/observatory": { + "name": "Observatoorium" + }, "man_made/petroleum_well": { "name": "Nafta puurkaev" }, @@ -2620,6 +2770,10 @@ "natural/heath": { "name": "Nõmm" }, + "natural/mud": { + "name": "Muda", + "terms": "märgala,soo" + }, "natural/peak": { "name": "Mäetipp", "terms": "tipp" @@ -2682,6 +2836,10 @@ "office": { "name": "Kontor" }, + "office/company": { + "name": "Ettevõtte kontor", + "terms": "kontor,firma,korporatiiv" + }, "office/government": { "name": "Valitsuse kontor" }, @@ -2815,6 +2973,10 @@ "name": "Pood", "terms": "kauplus" }, + "shop/agrarian": { + "name": "Põllumajandustarvete kauplus", + "terms": "aiatarbed,talupidamistarbed,põllumasinad,seemned,masinad" + }, "shop/alcohol": { "name": "Alkoholipood" }, @@ -2902,8 +3064,8 @@ "name": "Juustupood" }, "shop/chemist": { - "name": "Apteek", - "terms": "Ravimid" + "name": "Kodukeemia kauplus", + "terms": "puhastus*,ravimid,kemikaal*,pesuvahend*,üldpuhastus*,hügieeni*,tarbed,keemia" }, "shop/chocolate": { "name": "Šokolaadikauplus", @@ -2924,8 +3086,8 @@ "name": "Kommipood" }, "shop/convenience": { - "name": "Esmatarbekauba pood", - "terms": "Kauplus, pood" + "name": "Toidupood", + "terms": "Kauplus,pood,külapood,esmatarbekaup,väike pood" }, "shop/copyshop": { "name": "Koopiateenuse kauplus" @@ -3026,6 +3188,10 @@ "name": "Rauakauplus", "terms": "tööriistad,kinnitusvahendid" }, + "shop/health_food": { + "name": "Tervisliku toidu kauplus", + "terms": "vitamiinid,tervis,terviklikud,mahe,vegan,täistera,toidulisandid" + }, "shop/hearing_aids": { "name": "Kuulmisabipood" }, @@ -3238,6 +3404,10 @@ "shop/weapons": { "name": "Relvapood" }, + "shop/wholesale": { + "name": "Hulgikauplus", + "terms": "hulgikaup" + }, "shop/window_blind": { "name": "Aknakatete kauplus", "terms": "rulood,ribikardinad,lamellkardinad" @@ -3387,16 +3557,16 @@ "name": "Tagasipöörd keelatud" }, "type/restriction/only_left_turn": { - "name": "Ainult vasakpöörd", - "terms": "ainult vasakule,kohustuslik sõidusuund vasakule" + "name": "Ainult vasakpööre" }, "type/restriction/only_right_turn": { - "name": "Ainult parempöörd", - "terms": "ainult paremale,kohustuslik sõidusuund paremale" + "name": "Ainult parempööre" }, "type/restriction/only_straight_on": { - "name": "Pööramine keelatud", - "terms": "Kohustuslik sõidusuund otse,ainult otse" + "name": "Ainult otse" + }, + "type/restriction/only_u_turn": { + "name": "Ainult ümberpöörd" }, "type/route": { "name": "Marsruut" diff --git a/vendor/assets/iD/iD/locales/fa.json b/vendor/assets/iD/iD/locales/fa.json index 10d41c636..47e22d9f2 100644 --- a/vendor/assets/iD/iD/locales/fa.json +++ b/vendor/assets/iD/iD/locales/fa.json @@ -1,5 +1,10 @@ { "fa": { + "icons": { + "information": "اطلاعات", + "remove": "پاک‌کردن", + "undo": "بازگردانی" + }, "modes": { "add_area": { "title": "محدوده", @@ -18,13 +23,13 @@ }, "browse": { "title": "مرور", - "description": "مرور و زوم نقشه." + "description": "زوم کنید و نقشه را تکان دهید." }, "draw_area": { - "tail": "برای افزودن گره به منطقه تان کلیک کنید. برای پایان دادن به منطقه روی اولین گره کلیک کنید." + "tail": "برای افزودن گره به ناحیه کلیک کنید. برای بستن ناحیه روی اولین گره کلیک کنید." }, "draw_line": { - "tail": "برای افزودن گره های بیشتر به خط کلیک کنید. برای اتصال به سایر خطوط روی آنها کلیک کنید، و برای پایان دادن به خط دو بار کلیک کنید." + "tail": "برای افزودن گره‌های بیشتر به خط کلیک کنید. برای اتصال به سایر خطوط روی آن‌ها کلیک کنید، و برای پایان دادن به خط دو بار کلیک کنید." }, "drag_node": { "connected_to_hidden": "این عنصر به دلیل متصل بودن به یک عنصر مخفی قابل تغییر نیست. " @@ -48,10 +53,10 @@ "key": "A", "title": "ادامه", "description": "ادامه این خط.", - "not_eligible": "خط قابل ادامه دادنی اینجا نیست.", + "not_eligible": "اینجا خطی قابل ادامه‌دادن نیست.", "multiple": "اینجا چندین خط قابل ادامه دادن است. برای انتخاب یک خط، کلید Shift را فشار دهید و روی آن کلیک کنید تا انتخاب شود.", "annotation": { - "line": "نقطه‌ای ادامه داده شد.", + "line": "خطی ادامه داده شد.", "area": "محدوده‌ای ادامه داده شد." } }, @@ -163,7 +168,6 @@ "annotation": "{n} عنصر ادغام شده.", "not_eligible": "این عناصر قابل ترکیب نیستند.", "not_adjacent": "امکان ادغام این وبژگی‌ها وجود ندارد زیرا کانکشن آنها قطع است.", - "restriction": "امکان ادغام این عناصر وجود ندارد زیرا حداقل یکی از آن‌ها جزو رابطه \"{relation}\" می‌باشد.", "incomplete_relation": "امکان ادغام این عناصر وجود ندارد زیرا حداقل یکی از آن‌ها کامل دانلود نشده است.", "conflicting_tags": "امکان ادغام این عناصر وجود ندارد زیرا بعضی از آن‌ها دارای برچسب‌هایی با مقادیر مخالف یکدیگر هستند." }, @@ -291,7 +295,8 @@ }, "restriction": { "controls": { - "distance": "مسافت" + "distance": "مسافت", + "via": "از طريق" } }, "undo": { @@ -340,7 +345,8 @@ "created": "ساخته شد", "about_changeset_comments": "درباره توضیحات تغییرات", "about_changeset_comments_link": "//wiki.openstreetmap.org/wiki/Good_changeset_comments", - "google_warning": "شما در توضیحات خود از گوگل نام بردید. لطفا توجه داشته باشید که کپی کردن از نقشه‌های گوگل، ممنوع است." + "google_warning": "شما در توضیحات خود از گوگل نام بردید. لطفا توجه داشته باشید که کپی کردن از نقشه‌های گوگل، ممنوع است.", + "google_warning_link": "https://www.openstreetmap.org/copyright" }, "contributors": { "list": "ویرایش توسط {users}", @@ -467,7 +473,7 @@ "tooltip": "برای پیدا کردن محل منطقه نشان داده شده، یک نقشه کوچک نمایی نشان بده", "key": "/" }, - "fix_misalignment": "تنظیم فاصله تصویری", + "fix_misalignment": "تنظیم جابه‌جایی تصویر", "offset": "برای تنظیم افست تصاویر، محدوده خاکستری زیر را بکشید یا مقادیر را به متر در کادر زیر وارد کنید." }, "map_data": { @@ -580,13 +586,7 @@ } }, "success": { - "edited_osm": "OSMویرایش شد!", "just_edited": "شما OpenStreetMap را ویرایش کردید!", - "view_on_osm": "نمایش در OSM", - "facebook": "اشتراک گذاری در فیسبوک", - "twitter": "اشتراک گذاری در تویتر", - "google": "اشتراک گذاری در Google+", - "help_html": "تغییرات شما در لایه‌ی \"استاندارد\" به زودی قابل رؤیت است. تغیرات در سایر لایه‌ها و عناصر خاص، ممکن است بیشتر طول کشد تا نمایان شوند.", "help_link_text": "جزئیات", "help_link_url": "https://wiki.openstreetmap.org/wiki/Fa:FAQ#.D9.85.D9.86_.D8.AA.D8.BA.DB.8C.DB.8C.D8.B1.D8.A7.D8.AA.DB.8C_.D8.AF.D8.B1_.D9.86.D9.82.D8.B4.D9.87_.D8.A7.DB.8C.D8.AC.D8.A7.D8.AF_.DA.A9.D8.B1.D8.AF.D9.85.D8.8C_.DA.86.D8.B7.D9.88.D8.B1_.D9.85.DB.8C_.D8.AA.D9.88.D8.A7.D9.86.D9.85_.D9.88.DB.8C.D8.B1.D8.A7.DB.8C.D8.B4_.D9.87.D8.A7.DB.8C_.D8.AE.D9.88.D8.AF_.D8.B1.D8.A7_.D8.A8.D8.A8.DB.8C.D9.86.D9.85.D8.9F" }, @@ -792,6 +792,24 @@ } } }, + "units": { + "feet": "{quantity} فوت", + "miles": "{quantity} مایل", + "square_feet": "{quantity} فوت مربع", + "square_miles": "{quantity} مایل مربع", + "meters": "{quantity} متر", + "kilometers": "{quantity} کیلومتر", + "area_pair": "{area1} ({area2})", + "arcdegrees": "{quantity}°", + "arcminutes": "{quantity}′", + "arcseconds": "{quantity}″", + "north": "N", + "south": "S", + "east": "E", + "west": "W", + "coordinate": "{coordinate}{direction}", + "coordinate_pair": "{latitude}, {longitude}" + }, "presets": { "categories": { "category-barrier": { @@ -1269,7 +1287,7 @@ "placeholder": "خط ارتباطی، راه‌آهن برقی..." }, "elevation": { - "label": "ارتفاع" + "label": "ارتفاع از سطح دریا" }, "email": { "label": "ایمیل", @@ -1509,7 +1527,7 @@ "label": "سطح" }, "levels": { - "label": "سطح", + "label": "طبقه", "placeholder": "2, 4, 6..." }, "lit": { @@ -1538,6 +1556,10 @@ "label": "محدودیت سرعت", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "سرعت مجاز توصیه شده", + "placeholder": "۴۰، ۵۰، ۶۰..." + }, "maxstay": { "label": "حداکثر توقف" }, @@ -1691,7 +1713,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "تلفن", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2126,9 +2147,6 @@ "label": "نوع", "placeholder": "پیش فرض" }, - "vending": { - "label": "نوع محموله" - }, "visibility": { "label": "دید", "options": { @@ -2284,7 +2302,8 @@ "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'صحن'، با کاما جدا می‌شوند>" }, "aeroway/gate": { - "name": " دروازه فرودگاه " + "name": " دروازه فرودگاه ", + "terms": "" }, "aeroway/hangar": { "name": "آشیانه هواپیما", @@ -2302,9 +2321,27 @@ "name": "راه فرود به پارکینگ", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'فرود به پارک'، با کاما جدا می‌شوند>" }, + "aeroway/terminal": { + "name": "پایانه فرودگاه", + "terms": "" + }, + "allotments/plot": { + "terms": "" + }, "amenity": { "name": "کاربری" }, + "amenity/animal_boarding": { + "terms": "" + }, + "amenity/animal_breeding": { + "name": "امکانات پرورش حیوانات", + "terms": "" + }, + "amenity/animal_shelter": { + "name": "پناهگاه حیوانات", + "terms": "" + }, "amenity/arts_centre": { "name": "مرکز هنری", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مرکز هنری'، با کاما جدا می‌شوند>" @@ -2353,10 +2390,16 @@ "name": "تبدیل ارز / صرافی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'تبدیل ارز / صرافی'، با کاما جدا می‌شوند>" }, + "amenity/bus_station": { + "name": "پایانه اتوبوس / ترمینال" + }, "amenity/cafe": { "name": "کافه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کافه'، با کاما جدا می‌شوند>" }, + "amenity/car_pooling": { + "terms": "" + }, "amenity/car_rental": { "name": "کرایه ماشین", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کرایه خودرو'، با کاما جدا می‌شوند>" @@ -2389,6 +2432,12 @@ "name": "کلینیک", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'درمانگاه'، با کاما جدا می‌شوند>" }, + "amenity/clinic/abortion": { + "terms": "" + }, + "amenity/clinic/fertility": { + "terms": "" + }, "amenity/clock": { "name": "ساعت", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ساعت'، با کاما جدا می‌شوند>" @@ -2432,6 +2481,10 @@ "name": "آب آشامیدنی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'آب آشامیدنی'، با کاما جدا می‌شوند>" }, + "amenity/driving_school": { + "name": "آموزشگاه رانندگی", + "terms": "" + }, "amenity/embassy": { "name": "سفارت خانه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'سفارت'، با کاما جدا می‌شوند>" @@ -2488,18 +2541,32 @@ "name": "کتابخانه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کتابخانه'، با کاما جدا می‌شوند>" }, + "amenity/love_hotel": { + "name": "هتل عشق", + "terms": "" + }, "amenity/marketplace": { "name": "بازار", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'بازار'، با کاما جدا می‌شوند>" }, + "amenity/monastery": { + "terms": "" + }, "amenity/motorcycle_parking": { "name": "پارکینگ موتور سیکلت", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پارکینگ موتور سیکلت'، با کاما جدا می‌شوند>" }, + "amenity/music_school": { + "name": "آموزشگاه موسیقی", + "terms": "" + }, "amenity/nightclub": { "name": "کلوپ شبانه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کلوپ شبانه'، با کاما جدا می‌شوند>" }, + "amenity/nursing_home": { + "name": "خانه سالمندان" + }, "amenity/parking": { "name": "پارکینگ خودرو", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پارکینگ خودرو'، با کاما جدا می‌شوند>" @@ -2512,6 +2579,9 @@ "name": "جای پارک", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای'جای پارک'، با کاما جدا می‌شوند>" }, + "amenity/pavilion": { + "terms": "" + }, "amenity/pharmacy": { "name": "داروخانه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'داروخانه'، با کاما جدا می‌شوند>" @@ -2528,6 +2598,10 @@ "name": "کلیسا", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کلیسا'، با کاما جدا می‌شوند>" }, + "amenity/place_of_worship/hindu": { + "name": "معبد هندو", + "terms": "" + }, "amenity/place_of_worship/jewish": { "name": "کنیسه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کنیسه'، با کاما جدا می‌شوند>" @@ -2536,6 +2610,17 @@ "name": "مسجد", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسجد'، با کاما جدا می‌شوند>" }, + "amenity/place_of_worship/shinto": { + "name": "معبد شینتویی", + "terms": "" + }, + "amenity/place_of_worship/sikh": { + "terms": "" + }, + "amenity/place_of_worship/taoist": { + "name": "معبد تائو", + "terms": "" + }, "amenity/planetarium": { "name": "آسمان نما", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'آسمان نما'، با کاما جدا میشوند>" @@ -2572,6 +2657,9 @@ "name": "ایستگاه جنگلبانی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ایستگاه جنگلبانی'، با کاما جدا می‌شوند>" }, + "amenity/recycling": { + "terms": "" + }, "amenity/recycling_centre": { "name": "مرکز بازیافت", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مرکز بازیافت'، با کاما جدا می‌شوند>" @@ -2595,12 +2683,20 @@ "name": "پناه گاه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پناهگاه'، با کاما جدا می‌شوند>" }, + "amenity/shower": { + "name": "دوش", + "terms": "" + }, + "amenity/smoking_area": { + "name": "منطقه سیگار کشیدن", + "terms": "" + }, "amenity/social_facility": { "name": "امکانات اجتماعی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'امکانات اجتماعی'، با کاما جدا می‌شوند>" }, "amenity/social_facility/food_bank": { - "name": "فروشگاه مواد غذایی", + "name": "خیریه بانک غذا", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'بانک غذا'، با کاما جدا می‌شوند>" }, "amenity/social_facility/group_home": { @@ -2611,6 +2707,10 @@ "name": "پناهگاه بی خانمان‌ها", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پناهگاه بی‌خانمان‌ها'، با کاما جدا می‌شوند>" }, + "amenity/social_facility/nursing_home": { + "name": "خانه سالمندان", + "terms": "" + }, "amenity/studio": { "name": "استدیو", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'استودیو'، با کاما جدا می‌شوند>" @@ -2642,6 +2742,10 @@ "name": "محیط دانشگاهی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'محیط دانشگاه'، با کاما جدا می‌شوند>" }, + "amenity/vending_machine": { + "name": "دستگاه فروش خودکار", + "terms": "" + }, "amenity/vending_machine/cigarettes": { "name": "دستگاه فروش سیگار", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دستگاه فروش سیگار'، با کاما جدا می‌شوند>" @@ -2658,9 +2762,19 @@ "name": "دستگاه خود توزیع کیسه پسماند", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دستگاه خود توزیع کیسه پسماند'، با کاما جدا می‌شوند>" }, + "amenity/vending_machine/feminine_hygiene": { + "terms": "" + }, + "amenity/vending_machine/ice_cream": { + "name": "دستگاه فروش بستنی" + }, "amenity/vending_machine/news_papers": { "name": "دستگاه خود فروش روزنامه" }, + "amenity/vending_machine/newspapers": { + "name": "دستگاه فروش خودکار روزنامه", + "terms": "" + }, "amenity/vending_machine/parcel_pickup_dropoff": { "name": "سرویس دریافت مرسولات پستی، دستگاه دریافت مرسولات پستی", "terms": "سرویس دریافت امانات پستی، دستگاه دریافت کننده مرسولات پستی " @@ -2681,6 +2795,10 @@ "name": "دامپزشکی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دامپزشکی'، با کاما جدا می‌شوند>" }, + "amenity/waste/dog_excrement": { + "name": "سطل زباله سگ", + "terms": "" + }, "amenity/waste_basket": { "name": "سطل زباله", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'سطل زباله'، با کاما جدا می‌شوند>" @@ -2697,6 +2815,9 @@ "name": "آب قابل شرب RV", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای'آب قابل شرب RV'، با کاما جدا می‌شوند>" }, + "amenity/watering_place": { + "terms": "" + }, "area": { "name": "فضا", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'فضا'، با کاما جدا می‌شوند>" @@ -2705,6 +2826,50 @@ "name": "سطح جاده", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'سطح جاده'، با کاما جدا می‌شوند>" }, + "attraction/amusement_ride": { + "terms": "" + }, + "attraction/animal": { + "terms": "" + }, + "attraction/big_wheel": { + "terms": "" + }, + "attraction/bumper_car": { + "terms": "" + }, + "attraction/bungee_jumping": { + "name": "بانجی جامپینگ", + "terms": "" + }, + "attraction/carousel": { + "name": "چرخ فلک", + "terms": "" + }, + "attraction/dark_ride": { + "terms": "" + }, + "attraction/drop_tower": { + "terms": "" + }, + "attraction/pirate_ship": { + "name": "کشتی دزدان دریایی", + "terms": "" + }, + "attraction/river_rafting": { + "terms": "" + }, + "attraction/roller_coaster": { + "name": "ترن هوایی", + "terms": "" + }, + "attraction/train": { + "terms": "" + }, + "attraction/water_slide": { + "name": "سرسره آبی", + "terms": "" + }, "barrier": { "name": "مانع", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مانع'، با کاما جدا می‌شوند>" @@ -2718,7 +2883,8 @@ "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'بولارد'، با کاما جدا می‌شوند>" }, "barrier/border_control": { - "name": "مرزبانی" + "name": "مرزبانی", + "terms": "" }, "barrier/cattle_grid": { "name": "شبکه آهنی", @@ -2751,6 +2917,9 @@ "name": "پرچین", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'Hedge'، با کاما جدا می‌شوند>" }, + "barrier/kerb": { + "terms": "" + }, "barrier/kissing_gate": { "name": "دروازه مخصوص انسان", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'Kissing Gate'، با کاما جدا می‌شوند>" @@ -2791,6 +2960,13 @@ "name": "انبار غله", "terms": "انبار کاه" }, + "building/boathouse": { + "terms": "" + }, + "building/bungalow": { + "name": "بانگالو", + "terms": "" + }, "building/bunker": { "name": "انباربزرگ" }, @@ -2810,6 +2986,9 @@ "name": "ساختمان کلیسا", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ساختمان کلیسا'، با کاما جدا می‌شوند>" }, + "building/civic": { + "terms": "" + }, "building/college": { "name": "ساختمان دانشکده", "terms": "ساختمان کالج" @@ -2833,6 +3012,12 @@ "building/entrance": { "name": "ورود/خروج" }, + "building/farm": { + "terms": "" + }, + "building/farm_auxiliary": { + "terms": "" + }, "building/garage": { "name": "گاراژ", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'گاراژ'، با کاما جدا می‌شوند>" @@ -2869,6 +3054,9 @@ "name": "پیش دبستانی /ساختمان کودکستان", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پیش دبستانی / ساختمان کودکستان'، با کاما جدا می‌شوند>" }, + "building/mosque": { + "terms": "" + }, "building/public": { "name": "ساختمان عمومی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ساختمان عمومی'، با کاما جدا می‌شوند>" @@ -2885,6 +3073,9 @@ "name": "سقف", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'سقف'، با کاما جدا می‌شوند>" }, + "building/ruins": { + "terms": "" + }, "building/school": { "name": "ساختمان مدرسه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ساختمان مدرسه'، با کاما جدا می‌شوند>" @@ -2893,6 +3084,9 @@ "name": "خانه شبه ویلایی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'خانه شبه ویلایی'، با کاما جدا می‌شوند>" }, + "building/service": { + "terms": "" + }, "building/shed": { "name": "سایبان", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کپر'، با کاما جدا می‌شوند>" @@ -2901,10 +3095,16 @@ "name": "اصطبل", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'اصطبل'، با کاما جدا می‌شوند>" }, + "building/stadium": { + "terms": "" + }, "building/static_caravan": { "name": "خانه از پیش ساخته متحرک", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'خانه از پیش ساخته متحرک'، با کاما جدا می‌شوند>" }, + "building/temple": { + "terms": "" + }, "building/terrace": { "name": "خانه های ردیفی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'خانه های ردیفی'، با کاما جدا می‌شوند>" @@ -2912,6 +3112,9 @@ "building/train_station": { "name": "ایستگاه قطار" }, + "building/transportation": { + "terms": "" + }, "building/university": { "name": "ساختمان دانشگاه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ساختمان دانشگاه'، با کاما جدا می‌شوند>" @@ -2924,6 +3127,9 @@ "name": "مکان برقراری چادر", "terms": "مکان برقراری چادر، مکان قرار دادن خودرو کاروان" }, + "club": { + "terms": "" + }, "craft": { "name": "پیشه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پیشه'، با کاما جدا می‌شوند>" @@ -2964,10 +3170,19 @@ "name": "آذوقه رسان", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'آذوقه رسان'، با کاما جدا می‌شوند>" }, + "craft/chimney_sweeper": { + "terms": "" + }, "craft/clockmaker": { "name": "ساعت سازی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ساعت‌ساز'، با کاما جدا می‌شوند>" }, + "craft/confectionery": { + "terms": "" + }, + "craft/distillery": { + "terms": "" + }, "craft/dressmaker": { "name": "خیاطی زنانه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'خیاط زنانه'، با کاما جدا می‌شوند>" @@ -2976,6 +3191,10 @@ "name": "متخصص برق", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'برقکار'، با کاما جدا می‌شوند>" }, + "craft/electronics_repair": { + "name": "فروشگاه تعمیرات الکترونیک", + "terms": "" + }, "craft/gardener": { "name": "باغبان", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'باغبان'، با کاما جدا می‌شوند>" @@ -3061,6 +3280,9 @@ "name": "داربستی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'داربست'، با کاما جدا می‌شوند>" }, + "craft/sculptor": { + "terms": "" + }, "craft/shoemaker": { "name": "کفاش", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کفاش'، با کاما جدا می‌شوند>" @@ -3118,6 +3340,9 @@ "name": "آتش نشانی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'شیر آتش‌نشانی'، با کاما جدا می‌شوند>" }, + "emergency/life_ring": { + "terms": "" + }, "emergency/no": { "name": "دسترسی اظطراری خیر" }, @@ -3131,6 +3356,10 @@ "emergency/private": { "name": "دسترسی اضطراری شخصی" }, + "emergency/water_tank": { + "name": "مخزن آب اضطراری", + "terms": "" + }, "emergency/yes": { "name": "دسترسی اظطراری بله" }, @@ -3142,10 +3371,16 @@ "name": "تقاطع خیابانی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'تقاطع خیابان'، با کاما جدا می‌شوند>" }, + "footway/crossing-raised": { + "terms": "" + }, "footway/crosswalk": { "name": "محل عبور عابر پیاده", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'محل عبور عابر پیاده'، با کاما جدا می‌شوند>" }, + "footway/crosswalk-raised": { + "terms": "" + }, "footway/sidewalk": { "name": "پیاده رو", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پیاده‌رو'، با کاما جدا می‌شوند>" @@ -3194,10 +3429,53 @@ "name": "خطر آب", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'خطر آب'، با کاما جدا می‌شوند>" }, + "healthcare": { + "terms": "" + }, + "healthcare/alternative": { + "terms": "" + }, + "healthcare/alternative/chiropractic": { + "terms": "" + }, + "healthcare/audiologist": { + "terms": "" + }, + "healthcare/birthing_center": { + "terms": "" + }, "healthcare/blood_donation": { "name": "مرکز اهدای خون", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مرکز اهدای خون'، با کاما جدا می‌شوند>" }, + "healthcare/hospice": { + "terms": "" + }, + "healthcare/midwife": { + "name": "ماما", + "terms": "" + }, + "healthcare/occupational_therapist": { + "terms": "" + }, + "healthcare/optometrist": { + "terms": "" + }, + "healthcare/physiotherapist": { + "terms": "" + }, + "healthcare/podiatrist": { + "terms": "" + }, + "healthcare/psychotherapist": { + "terms": "" + }, + "healthcare/rehabilitation": { + "terms": "" + }, + "healthcare/speech_therapist": { + "terms": "" + }, "highway": { "name": "بزرگراه" }, @@ -3205,6 +3483,9 @@ "name": "مسیر حیوانات اهلی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'Bridle Path'، با کاما جدا می‌شوند>" }, + "highway/bus_guideway": { + "terms": "" + }, "highway/corridor": { "name": "راهروی داخلی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'راهرو داخلی'، با کاما جدا می‌شوند>" @@ -3213,14 +3494,24 @@ "name": "تقاطع خیابانی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'تقاطع خیابان'، با کاما جدا می‌شوند>" }, + "highway/crossing-raised": { + "terms": "" + }, "highway/crosswalk": { "name": "محل عبور عابر پیاده", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'محل عبور عابر پیاده'، با کاما جدا می‌شوند>" }, + "highway/crosswalk-raised": { + "terms": "" + }, "highway/cycleway": { "name": "مسیر دوچرخه سواری", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسیر دوچرخه'، با کاما جدا می‌شوند>" }, + "highway/elevator": { + "name": "آسانسور", + "terms": "" + }, "highway/footway": { "name": "مسیر پیاده روی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسیر پیاده'، با کاما جدا می‌شوند>" @@ -3249,10 +3540,19 @@ "name": "اتصال بزرگراه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پیوستن بزرگراه'، با کاما جدا می‌شوند>" }, + "highway/passing_place": { + "terms": "" + }, "highway/path": { "name": "مسیر", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسیر'، با کاما جدا می‌شوند>" }, + "highway/pedestrian_area": { + "terms": "" + }, + "highway/pedestrian_line": { + "terms": "" + }, "highway/primary": { "name": "جاده اصلی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'راه اصلی'، با کاما جدا می‌شوند>" @@ -3261,6 +3561,9 @@ "name": "اتصال اصلی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پیوستن راه اصلی'، با کاما جدا می‌شوند>" }, + "highway/raceway": { + "terms": "" + }, "highway/residential": { "name": "جاده ی مسکونی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'جاده مسکونی'، با کاما جدا می‌شوند>" @@ -3309,6 +3612,9 @@ "name": "فضای خدماتی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'جایگاه خدماتی'، با کاما جدا می‌شوند>" }, + "highway/speed_camera": { + "terms": "" + }, "highway/steps": { "name": "پله", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پله'، با کاما جدا می‌شوند>" @@ -3389,6 +3695,10 @@ "name": "ویرانه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ویرانه'، با کاما جدا می‌شوند>" }, + "historic/tomb": { + "name": "آرامگاه", + "terms": "" + }, "historic/wayside_cross": { "name": "صلیب کنار جاده", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'صلیب کنار جاده'، با کاما جدا می‌شوند>" @@ -3409,10 +3719,17 @@ "name": "باغچه عمومی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'باغچه عمومی'، با کاما جدا می‌شوند>" }, + "landuse/aquaculture": { + "name": "آبزی‌پروری", + "terms": "" + }, "landuse/basin": { "name": "حوزه رودخانه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'حوضه'، با کاما جدا می‌شوند>" }, + "landuse/brownfield": { + "terms": "" + }, "landuse/cemetery": { "name": "قبرستان", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'قبرستان - آرامگاه'، با کاما جدا می‌شوند>" @@ -3444,14 +3761,34 @@ "name": "جنگل", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'جنگل'، با کاما جدا می‌شوند>" }, + "landuse/garages": { + "terms": "" + }, "landuse/grass": { "name": "علف زار", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'چمن'، با کاما جدا می‌شوند>" }, + "landuse/greenfield": { + "terms": "" + }, + "landuse/greenhouse_horticulture": { + "terms": "" + }, + "landuse/harbour": { + "name": "بندرگاه", + "terms": "" + }, "landuse/industrial": { "name": "محیط صنعتی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'منطقه صنعتی'، با کاما جدا می‌شوند>" }, + "landuse/industrial/scrap_yard": { + "terms": "" + }, + "landuse/industrial/slaughterhouse": { + "name": "کشتارگاه", + "terms": "" + }, "landuse/landfill": { "name": "محل دفن مواد (زباله)", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'محل دفن زباله'، با کاما جدا می‌شوند>" @@ -3465,37 +3802,48 @@ "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'منطقه نظامی'، با کاما جدا می‌شوند>" }, "landuse/military/airfield": { - "name": "پایگاه هوایی نظامی" + "name": "پایگاه هوایی نظامی", + "terms": "" }, "landuse/military/barracks": { - "name": "پادگان" + "name": "پادگان", + "terms": "" }, "landuse/military/bunker": { - "name": "محدوده نظامی" + "name": "محدوده نظامی", + "terms": "" }, "landuse/military/checkpoint": { - "name": "ایست بازرسی" + "name": "ایست بازرسی", + "terms": "" }, "landuse/military/danger_area": { - "name": "محدوده خطرناک" + "name": "محدوده خطرناک", + "terms": "" }, "landuse/military/naval_base": { - "name": "پایگاه نیروی دریایی" + "name": "پایگاه نیروی دریایی", + "terms": "" }, "landuse/military/nuclear_explosion_site": { - "name": "محدوده انفجار اتمی" + "name": "محدوده انفجار اتمی", + "terms": "" }, "landuse/military/obstacle_course": { - "name": "ميدان موانع" + "name": "ميدان موانع", + "terms": "" }, "landuse/military/office": { - "name": "دفتر نظامی" + "name": "دفتر نظامی", + "terms": "" }, "landuse/military/range": { - "name": "محدوده نظامی" + "name": "محدوده نظامی", + "terms": "" }, "landuse/military/training_area": { - "name": "منطقه آموزشی" + "name": "منطقه آموزشی", + "terms": "" }, "landuse/orchard": { "name": "باغ میوه", @@ -3509,10 +3857,16 @@ "name": "معدن سنگ", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'معدن'، با کاما جدا می‌شوند>" }, + "landuse/railway": { + "terms": "" + }, "landuse/recreation_ground": { "name": "محوطه تفریحی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'محوطه تفریحی'، با کاما جدا می‌شوند>" }, + "landuse/religious": { + "terms": "" + }, "landuse/residential": { "name": "منطقه مسکونی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'منطقه مسکونی'، با کاما جدا می‌شوند>" @@ -3533,6 +3887,9 @@ "name": "مرکز بازی بزرگسالان", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مرکز بازی بزرگسالان'، با کاما جدا می‌شوند>" }, + "leisure/amusement_arcade": { + "terms": "" + }, "leisure/bird_hide": { "name": "مکان تماشای پرندگان", "terms": "مخفیگاه تماشای پرندگان" @@ -3549,6 +3906,10 @@ "name": "سالن رقص", "terms": "تالار رقص" }, + "leisure/dancing_school": { + "name": "مدرسه رقص", + "terms": "" + }, "leisure/dog_park": { "name": "پارک سگ", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پارک سگ‌ها'، با کاما جدا می‌شوند>" @@ -3569,6 +3930,39 @@ "name": "ایستگاه ورزشی در فضای باز", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ایستگاه ورزشی در فضای باز'، با کاما جدا می‌شوند>" }, + "leisure/fitness_station/balance_beam": { + "terms": "" + }, + "leisure/fitness_station/box": { + "terms": "" + }, + "leisure/fitness_station/horizontal_bar": { + "terms": "" + }, + "leisure/fitness_station/horizontal_ladder": { + "terms": "" + }, + "leisure/fitness_station/hyperextension": { + "terms": "" + }, + "leisure/fitness_station/parallel_bars": { + "terms": "" + }, + "leisure/fitness_station/push-up": { + "terms": "" + }, + "leisure/fitness_station/rings": { + "terms": "" + }, + "leisure/fitness_station/sign": { + "terms": "" + }, + "leisure/fitness_station/sit-up": { + "terms": "" + }, + "leisure/fitness_station/stairs": { + "terms": "" + }, "leisure/garden": { "name": "باغ", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'باغ'، با کاما جدا می‌شوند>" @@ -3577,8 +3971,13 @@ "name": "زمین گلف", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'زمین گلف'، با کاما جدا می‌شوند>" }, + "leisure/hackerspace": { + "name": "هکراسپیس", + "terms": "" + }, "leisure/horse_riding": { - "name": "باشگاه اسب سواری" + "name": "باشگاه اسب سواری", + "terms": "" }, "leisure/ice_rink": { "name": "یخ بازی", @@ -3596,6 +3995,9 @@ "name": "ذخیره‌گاه طبیعی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'ذخیره‌گاه طبیعی'، با کاما جدا می‌شوند>" }, + "leisure/outdoor_seating": { + "terms": "" + }, "leisure/park": { "name": "پارک", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پارک'، با کاما جدا می‌شوند>" @@ -3620,10 +4022,22 @@ "name": "محوطه بسکتبال", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'زمین بسکتبال'، با کاما جدا می‌شوند>" }, + "leisure/pitch/beachvolleyball": { + "terms": "" + }, + "leisure/pitch/boules": { + "terms": "" + }, "leisure/pitch/bowls": { "name": "چمن مخصوص بولینگ", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'چمن مخصوص بولینگ'، با کاما جدا می‌شوند>" }, + "leisure/pitch/cricket": { + "terms": "" + }, + "leisure/pitch/equestrian": { + "terms": "" + }, "leisure/pitch/rugby_league": { "name": "زمین راگبی ۱۳ نفره", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'زمین راگبی ۱۳ نفره'، با کاما جدا می‌شوند>" @@ -3640,6 +4054,9 @@ "name": "میدان فوتبال", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'زمین فوتبال'، با کاما جدا می‌شوند>" }, + "leisure/pitch/table_tennis": { + "terms": "" + }, "leisure/pitch/tennis": { "name": "محوطه تنیس", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'زمین تنیس'، با کاما جدا می‌شوند>" @@ -3656,6 +4073,13 @@ "name": "پر رفت‌آمد", "terms": "مکان پررفت‌آمد, اماکن پر رفت آمد,مکان‌های مطرح" }, + "leisure/running_track": { + "terms": "" + }, + "leisure/sauna": { + "name": "سونا", + "terms": "" + }, "leisure/slipway": { "name": "قایق ساکن", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسیر لغزشی کشتی'، با کاما جدا می‌شوند>" @@ -3676,6 +4100,9 @@ "name": "استخر شنا", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'استخر شنا'، با کاما جدا می‌شوند>" }, + "leisure/track": { + "terms": "" + }, "leisure/water_park": { "name": "پارک آبی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'پارک آبی'، با کاما جدا می‌شوند>" @@ -3692,6 +4119,10 @@ "name": "گذرگاه افقی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'گذرگاه افقی'، با کاما جدا می‌شوند>" }, + "man_made/antenna": { + "name": "آنتن", + "terms": "" + }, "man_made/breakwater": { "name": "موج شکن", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'موج شکن'، با کاما جدا می‌شوند>" @@ -3704,6 +4135,10 @@ "name": "دودکش", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دودکش'، با کاما جدا می‌شوند>" }, + "man_made/crane": { + "name": "جرثقیل", + "terms": "" + }, "man_made/cutline": { "name": "خط برش", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسیر جنگلی'، با کاما جدا می‌شوند>" @@ -3727,10 +4162,19 @@ "name": "فانوس دریایی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'فانوس دریایی'، با کاما جدا می‌شوند>" }, + "man_made/mast": { + "terms": "" + }, + "man_made/monitoring_station": { + "terms": "" + }, "man_made/observation": { "name": "برج رصد", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دکل دیده‌بانی'، با کاما جدا می‌شوند>" }, + "man_made/observatory": { + "terms": "" + }, "man_made/petroleum_well": { "name": "چاه نفت", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'چاه نفت'، با کاما جدا می‌شوند>" @@ -3787,15 +4231,34 @@ "name": "امور آب", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'تأسیسات آبرسانی'، با کاما جدا می‌شوند>" }, + "man_made/watermill": { + "name": "آسیاب آبی", + "terms": "" + }, + "man_made/windmill": { + "name": "آسیاب بادی", + "terms": "" + }, "man_made/works": { - "name": "کارخانه" + "name": "کارخانه", + "terms": "" + }, + "manhole": { + "terms": "" + }, + "manhole/drain": { + "terms": "" + }, + "manhole/telecom": { + "terms": "" }, "natural": { "name": "طبیعی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'طبیعت'، با کاما جدا می‌شوند>" }, "natural/bare_rock": { - "name": "صخره" + "name": "صخره", + "terms": "" }, "natural/bay": { "name": "خلیج کوچک", @@ -3833,19 +4296,24 @@ "name": "بوته زار", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'بوته زار'، با کاما جدا می‌شوند>" }, + "natural/mud": { + "terms": "" + }, "natural/peak": { "name": "قله", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'قله'، با کاما جدا می‌شوند>" }, "natural/ridge": { - "name": "پرتگاه" + "name": "پرتگاه", + "terms": "" }, "natural/saddle": { "name": "گردنه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'گردنه'، با کاما جدا می‌شوند>" }, "natural/sand": { - "name": "شن" + "name": "شن", + "terms": "" }, "natural/scree": { "name": "سنگ ریزه", @@ -3895,15 +4363,44 @@ "name": "چوب", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'چوب'، با کاما جدا می‌شوند>" }, + "noexit/yes": { + "terms": "" + }, "office": { "name": "اداره", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'اداره'، با کاما جدا می‌شوند>" }, + "office/accountant": { + "terms": "" + }, "office/administrative": { "name": "دفتر اداری" }, + "office/adoption_agency": { + "terms": "" + }, + "office/advertising_agency": { + "name": "آژانس تبلیغاتی", + "terms": "" + }, + "office/architect": { + "name": "دفتر معماری", + "terms": "" + }, + "office/association": { + "name": "دفتر سازمان غیر انتفاعی", + "terms": "" + }, + "office/charity": { + "name": "دفتر خیریه", + "terms": "" + }, + "office/company": { + "terms": "" + }, "office/coworking": { - "name": "فضای کاری مشارکتی" + "name": "فضای کاری مشارکتی", + "terms": "" }, "office/educational_institution": { "name": "مؤسسه آموزشی", @@ -3913,6 +4410,9 @@ "name": "آژانس کاریابی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'آژانس کاریابی'، با کاما جدا می‌شوند>" }, + "office/energy_supplier": { + "terms": "" + }, "office/estate_agent": { "name": "دفتر املاک", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دفتر املاک و مستغلات'، با کاما جدا می‌شوند>" @@ -3921,6 +4421,12 @@ "name": "اداره مالی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دفتر مالی'، با کاما جدا می‌شوند>" }, + "office/forestry": { + "terms": "" + }, + "office/foundation": { + "terms": "" + }, "office/government": { "name": "اداره دولتی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'اداره دولتی'، با کاما جدا می‌شوند>" @@ -3929,18 +4435,44 @@ "name": "اداره ثبت", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'اداره ثبت'، با کاما جدا می‌شوند>" }, + "office/government/tax": { + "name": "اداره مالیات و درآمد", + "terms": "" + }, + "office/guide": { + "name": "دفتر راهنمای تور", + "terms": "" + }, "office/insurance": { "name": "دفتر بیمه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'اداره بیمه'، با کاما جدا می‌شوند>" }, + "office/it": { + "name": "دفتر فناوری اطلاعات", + "terms": "" + }, "office/lawyer": { "name": "دفتر حقوقی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دفتر حقوقی'، با کاما جدا می‌شوند>" }, + "office/lawyer/notary": { + "name": "دفتر اسناد رسمی" + }, + "office/moving_company": { + "terms": "" + }, + "office/newspaper": { + "name": "دفتر روزنامه", + "terms": "" + }, "office/ngo": { "name": "سازمان غیر دولتی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دفتر سازمان غیر دولتی NGO'، با کاما جدا می‌شوند>" }, + "office/notary": { + "name": "دفتر اسناد رسمی", + "terms": "" + }, "office/physician": { "name": "پزشک" }, @@ -3948,10 +4480,24 @@ "name": "حزب سیاسی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'حزب سیاسی'، با کاما جدا می‌شوند>" }, + "office/private_investigator": { + "name": "دفتر تحقیقات خصوصی", + "terms": "" + }, + "office/quango": { + "terms": "" + }, "office/research": { "name": "سازمان تحقیقاتی و پژوهشی", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دفتر تحقیقاتی'، با کاما جدا می‌شوند>" }, + "office/surveyor": { + "terms": "" + }, + "office/tax_advisor": { + "name": "دفتر مشاور مالیاتی", + "terms": "" + }, "office/telecommunication": { "name": "اداره مخابرات", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دفتر مخابراتی '، با کاما جدا می‌شوند>" @@ -4004,6 +4550,9 @@ "name": "روستا", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'روستا'، با کاما جدا می‌شوند>" }, + "playground/slide": { + "name": "سرسره" + }, "point": { "name": "نقطه", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'نقطه'، با کاما جدا می‌شوند>" @@ -4045,6 +4594,12 @@ "name": "مبدل برق", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'کاهنده جریان برق'، با کاما جدا می‌شوند>" }, + "public_transport/linear_platform_bus": { + "name": "ایستگاه اتوبوس" + }, + "public_transport/station_monorail": { + "name": "ایستگاه مونوریل" + }, "railway": { "name": "راه آهن" }, @@ -4069,7 +4624,7 @@ "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'جاده گذرنده از راه‌آهن'، با کاما جدا می‌شوند>" }, "railway/monorail": { - "name": "ترن هوایی", + "name": "مونوریل", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مونوریل'، با کاما جدا می‌شوند>" }, "railway/narrow_gauge": { @@ -4232,7 +4787,7 @@ "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'آبنبات فروشی'، با کاما جدا می‌شوند>" }, "shop/convenience": { - "name": "فروشگاه زنجیره ای", + "name": "فروشگاه کوچک", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'Convenience Store'، با کاما جدا می‌شوند>" }, "shop/copyshop": { @@ -4723,18 +5278,6 @@ "name": "دور زدن ممنوع", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'دور زدن ممنوع'، با کاما جدا می‌شوند>" }, - "type/restriction/only_left_turn": { - "name": "تنها امکان گردش به چپ", - "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'تنها امکان گردش به چپ'، با کاما جدا می‌شوند>" - }, - "type/restriction/only_right_turn": { - "name": "تنها امکان گردش به راست", - "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'تنها امکان گردش به راست'، با کاما جدا می‌شوند>" - }, - "type/restriction/only_straight_on": { - "name": "گردش ممنوع", - "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'گردش ممنوع'، با کاما جدا می‌شوند>" - }, "type/route": { "name": "مسیر", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسیر'، با کاما جدا می‌شوند>" @@ -4779,6 +5322,9 @@ "name": "مسیر جاده", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسیر جاده'، با کاما جدا می‌شوند>" }, + "type/route/subway": { + "name": "خط مترو" + }, "type/route/train": { "name": "مسیر راه آهن", "terms": "<ترجمه با مترادف یا اصطلاحات مشابه برای 'مسیر راه آهن'، با کاما جدا می‌شوند>" @@ -4795,6 +5341,9 @@ "name": "سایت", "terms": "سایت، منطقه" }, + "type/waterway": { + "name": "راه آبی" + }, "vertex": { "name": "سایر", "terms": "دیگر, بقیه, باقی" @@ -4862,145 +5411,149 @@ }, "imagery": { "Bing": { - "description": "نقشه های ماهواره ای aerial", - "name": "نقشه های Bing" + "description": "تصاویر هوایی و ماهواره‌ای", + "name": "تصاویر هوایی بینگ" }, "DigitalGlobe-Premium": { "attribution": { - "text": "ارسال نظرات" + "text": "قوانین و بازخورد" }, - "description": "نقشه های ماهواره ای Premium DigitalGlobe ", - "name": "نقشه های DigitalGlobe Premium" + "description": "تصاویر ماهواره‌ای DigitalGlobe Premium", + "name": "تصوایر DigitalGlobe Premium" }, "DigitalGlobe-Premium-vintage": { "attribution": { - "text": "ارسال نظرات" + "text": "قوانین و بازخورد" }, - "description": "مرزها و تاریخ نقشه ها از زوم 14 به بالا قابل مشاهده هستند", - "name": "فهرست DigitalGlobe Premium" + "description": "محدودهٔ تصاویر و تاریخ عکس‌برداری. برچسب‌ها در زوم ۱۳ و بالاتر ظاهر می‌شود.", + "name": "تصاویر DigitalGlobe Premium Vintage" }, "DigitalGlobe-Standard": { "attribution": { - "text": "ارسال نظرات" + "text": "قوانین و بازخورد" }, - "description": "نقشه های ماهواره ای استاندارد DigitalGlobe Premium", - "name": "نقشه های استاندارد DigitalGlobe Premium" + "description": "تصاویر ماهواره‌ای DigitalGlobe Standard", + "name": "تصاویر DigitalGlobe Standard" }, "DigitalGlobe-Standard-vintage": { "attribution": { - "text": "ارسال نظرات" + "text": "قوانین و بازخورد" }, - "description": "مرزها و تاریخ نقشه ها از زوم 14 به بالا قابل مشاهده هستند", - "name": "فهرست DigitalGlobe Premium" + "description": "محدودهٔ تصاویر و تاریخ عکس‌برداری. برچسب‌ها در زوم ۱۳ و بالاتر ظاهر می‌شود.", + "name": "تصاویر DigitalGlobe Standard Vintage" }, "EsriWorldImagery": { "attribution": { - "text": "ارسال نظرات" + "text": "قوانین و بازخورد" }, - "description": "نقشه های Esri world ", - "name": "نقشه های Esri world " + "description": "تصاویر جهانی Esri", + "name": "تصاویر جهانی Esri" }, "EsriWorldImageryClarity": { "attribution": { - "text": "فید بک" + "text": "قوانین و بازخورد" }, - "description": "تصاویر بایگانی Esri که ممکن است واضح تر و دقیق تر از لایه پیش فرض باشد.", - "name": "Esri World Imagery (Clarity) Beta" + "description": "تصاویر بایگانی Esri که شاید واضح‌تر و دقیق‌تر از لایهٔ پیشفرض باشد.", + "name": "تصاویر جهانی Esri (واضح) - آزمایشی" }, "MAPNIK": { "attribution": { - "text": "©همکاران OSM و CC-BY-SA" + "text": "© مشارکت‌کنندگان OpenStreetMap،‏ CC-BY-SA" }, - "description": "لایه پیش فرض OSM", - "name": "نقشه های OSM ( استاندارد)" + "description": "لایهٔ پیشفرض OSM", + "name": "نقشه‌های OSM (استاندارد)" }, "Mapbox": { "attribution": { - "text": "ارسال نظرات" + "text": "قوانین و بازخورد" }, - "description": "نقشه های ماهواره ای aerial", - "name": "نقشه های ماهواره ای Mapbox" + "description": "تصاویر هوایی و ماهواره‌ای", + "name": "ماهوارهٔ Mapbox" }, "OSM_Inspector-Addresses": { "attribution": { - "text": "مرکز ژئوگرافی GmbH با همکاری OSM و CC-BY-SA" + "text": "© شرکت Geofabrik GmbH، مشارکت‌کنندگان OSM،‏ CC-BY-SA" }, - "name": "بازرسی OSM : آدرسها" + "name": "بازبین OSM: نشانی‌ها" }, "OSM_Inspector-Geometry": { "attribution": { - "text": "مرکز ژئوگرافی GmbH با همکاری OSM و CC-BY-SA" + "text": "© شرکت Geofabrik GmbH، مشارکت‌کنندگان OSM،‏ CC-BY-SA" }, - "name": "بازرسی OSM : ژئومتری" + "name": "بازبین OSM: هندسی" }, "OSM_Inspector-Highways": { "attribution": { - "text": "مرکز ژئوگرافی GmbH با همکاری OSM و CC-BY-SA" + "text": "© شرکت Geofabrik GmbH، مشارکت‌کنندگان OSM،‏ CC-BY-SA" }, - "name": "بازرسی OSM : اتوبانها" + "name": "بازبین OSM: راه‌ها" }, "OSM_Inspector-Multipolygon": { "attribution": { - "text": "مرکز ژئوگرافی GmbH با همکاری OSM و CC-BY-SA" + "text": "© شرکت Geofabrik GmbH، مشارکت‌کنندگان OSM،‏ CC-BY-SA" }, - "name": "بازرسی OSM : محدوده" + "name": "بازبین OSM: محوطه" }, "OSM_Inspector-Places": { "attribution": { - "text": "مرکز ژئوگرافی GmbH با همکاری OSM و CC-BY-SA" + "text": "© شرکت Geofabrik GmbH، مشارکت‌کنندگان OSM،‏ CC-BY-SA" }, - "name": "بازرسی OSM : مکانها" + "name": "بازبین OSM: مکان‌ها" }, "OSM_Inspector-Routing": { "attribution": { - "text": "مرکز ژئوگرافی GmbH با همکاری OSM و CC-BY-SA" + "text": "© شرکت Geofabrik GmbH، مشارکت‌کنندگان OSM،‏ CC-BY-SA" }, - "name": "بازرسی OSM : خطوط" + "name": "بازبین OSM: مسیریابی" }, "OSM_Inspector-Tagging": { "attribution": { - "text": "مرکز ژئوگرافی GmbH با همکاری OSM و CC-BY-SA" + "text": "© شرکت Geofabrik GmbH، مشارکت‌کنندگان OSM،‏ CC-BY-SA" }, - "name": "بازرسی OSM : برچسبها" + "name": "بازبین OSM: تگ‌گذاری" }, "US-TIGER-Roads-2012": { "name": "جاده های TIGER 2012" }, "US-TIGER-Roads-2014": { - "description": "از زوم +16 به بعد اطلاعات مالکیت ملکی در آمریکا دیده میشود.از زومهای کمتر فقط تغییراتی که در OSM مربوط به سال 2006 ثبت شده است قابل دیدن است", + "description": "در زوم ۱۶‎+‎، اطلاعات مالکیت عمومی از سرشماری آمریکاست. در زوم‌های کمتر، فقط تغییراتی که از سال ۲۰۰۶ ایجاد شده منهای تغییراتی که قبلاً در OSM آمده", "name": "جاده های TIGER 2014" }, "US-TIGER-Roads-2017": { - "description": "زود = داده های دولتی سرشماری آمریکا. قرمز : داده های بدون منبع در OSM", + "description": "زرد = داده‌های دولتی سرشماری آمریکا. قرمز: داده‌هایی که در OSM پیدا نشد", "name": "جاده های TIGER 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "راه: سبزرنگ = دسته‌بندی‌نشده. قهوه‌ای‌رنگ = رد چرخ. سطح: شن‌ریزه = قهوه‌ای روشن توپر، آسفالت = سیاه، روسازی‌شده = خاکستری، زمین = سفید، بتن = آبی، چمن = سبز. فصلی = سفید", + "name": "رولایهٔ راه‌های جنگلی آمریکا" + }, "Waymarked_Trails-Cycling": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + "text": "© waymarkedtrails.org، مشارکت‌کنندگان OpenStreetMap،‏ CC by-SA 3.0" }, "name": "مسیرهای مشخص شده: دوچرخه سواری" }, "Waymarked_Trails-Hiking": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + "text": "© waymarkedtrails.org، مشارکت‌کنندگان OpenStreetMap،‏ CC by-SA 3.0" }, "name": "مسیرهای مشخص شده: پیاده روی" }, "Waymarked_Trails-MTB": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + "text": "© waymarkedtrails.org، مشارکت‌کنندگان OpenStreetMap،‏ CC by-SA 3.0" }, "name": "مسیرهای مشخص شده: MTB" }, "Waymarked_Trails-Skating": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + "text": "© waymarkedtrails.org، مشارکت‌کنندگان OpenStreetMap،‏ CC by-SA 3.0" }, "name": "مسیرهای مشخص شده: اسکیت" }, "Waymarked_Trails-Winter_Sports": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" + "text": "© waymarkedtrails.org، مشارکت‌کنندگان OpenStreetMap،‏ CC by-SA 3.0" }, "name": "مسیرهای مشخص شده: ورزشهای زمستانی" }, @@ -5008,83 +5561,118 @@ "attribution": { "text": "basemap.at" }, - "description": "نقشه اصلی استرالیا، نقشه ثبت شده دولتی", + "description": "نقشهٔ پایهٔ اتریش، بر اساس اطلاعات دولت است.", "name": "basemap.at" }, "basemap.at-orthofoto": { "attribution": { "text": "basemap.at" }, - "description": "Orthofoto layer provided by basemap.at. \"Successor\" of geoimage.at imagery.", + "description": "لایهٔ Orthofoto را basemap.at فراهم کرده است. «جایگزین» تصاویر geoimage.at.", "name": "basemap.at Orthofoto" }, "hike_n_bike": { "attribution": { - "text": "© OpenStreetMap contributors" + "text": "© مشارکت‌کنندگان OpenStreetMap " }, - "name": "پیاده روی و دوچرخه سواری" + "name": "پیاده‌روی و دوچرخه‌سواری" }, "mapbox_locator_overlay": { "attribution": { - "text": "ارسال نظرات" + "text": "قوانین و بازخورد" }, - "description": "برای کمک به شما ویژگی های اصلی نمایش میدهد.", + "description": "برای کمک به شما ویژگی‌های اصلی را نمایش می‌دهد.", "name": "لایه یاب" }, "openpt_map": { "attribution": { - "text": "© OpenStreetMap contributors, CC-BY-SA" + "text": "© مشارکت‌کنندگان OpenStreetMap،‏ CC-BY-SA" }, - "name": "OpenPT Map (overlay)" + "name": "نقشهٔ OpenPT (رولایه)" }, "osm-gps": { "attribution": { - "text": "© OpenStreetMap contributors" + "text": "© مشارکت‌کنندگان OpenStreetMap " }, - "description": "آپلود GPSهای عمومی در OSM", - "name": "ظبط مسیر در OSM" + "description": "مسیرهای GPS عمومی آپلودشده در OSM.", + "name": "مسیرهای GPS متعلق به OSM" }, "osm-mapnik-black_and_white": { "attribution": { - "text": "© OpenStreetMap contributors, CC-BY-SA" + "text": "© مشارکت‌کنندگان OSM،‏ CC-BY-SA" }, - "name": "OSM ( استاندارد سیاه و سفید )" + "name": "OSM (سیاه و سفید استاندارد)" }, "osm-mapnik-german_style": { "attribution": { - "text": "© OpenStreetMap contributors, CC-BY-SA" + "text": "© مشارکت‌کنندگان OpenStreetMap،‏ CC-BY-SA" }, - "name": "SOM (نمای آلمانی)" + "name": "OSM (سبک آلمانی)" }, "qa_no_address": { "attribution": { - "text": "Simon Poole, Data ©OpenStreetMap contributors" + "text": "Simon Poole، داده‌ها © مشارکت‌کنندگان OpenStreetMap" }, "name": "س/ج بدون آدرس" }, "skobbler": { "attribution": { - "text": "© Tiles: skobbler Map data: OpenStreetMap contributors" - } + "text": "© کاشی‌ها: skobbler داده‌های نقشه: مشارکت‌کنندگان OpenStreetMap " + }, + "name": "skobbler" }, "stamen-terrain-background": { "attribution": { - "text": "Map tiles by Stamen Design, under CC BY 3.0" + "text": "کاشی‌های نقشه از Stamen Design، تحت مجوز CC BY 3.0. داده‌ها از OpenStreetMap، تحت مجوز ODbL" }, - "name": "لجن زار" + "name": "Stamen Terrain" }, "tf-cycle": { "attribution": { - "text": "Maps © Thunderforest, Data © OpenStreetMap contributors" + "text": "نقشه‌ها © Thunderforest،‏ داده‌ها © مشارکت‌کنندگان OpenStreetMap" }, "name": "Thunderforest OpenCycleMap" }, "tf-landscape": { "attribution": { - "text": "Maps © Thunderforest, Data © OpenStreetMap contributors" + "text": "نقشه‌ها © Thunderforest،‏ داده‌ها © مشارکت‌کنندگان OpenStreetMap " }, "name": "Thunderforest Landscape" } + }, + "community": { + "Central-Pennsylvania-OSM": { + "name": "پنسیلوانیا مرکزی OSM", + "description": "جامعه نقشه برداری آنلاین بر اساس کالج ایالتی، پنسیلوانیا" + }, + "Dallas-Fort-Worth-OSM": { + "name": "دالاس‌فورت وورث OSM", + "description": "گروه کاربران OpenStreetMap برای دالاس‌فورت وورث" + }, + "GeoPhilly": { + "name": "ژئوفیلی", + "description": "Meetup برای علاقمندان به نقشه در منطقه فیلادلفیا" + }, + "OSM-Chattanooga": { + "name": "OSM چاتانوگا", + "description": "گروه کاربران OpenStreetMap برای چاتانوگا" + }, + "OSM-NYC": { + "name": "OpenStreetMap نیویورک" + }, + "OSM-Portland": { + "name": "پورتلند OpenStreetMap" + }, + "OSM-US-Slack": { + "description": "همگی خوش آمدید! ثبت نام کنید در {signupUrl}" + }, + "Maptime-Australia-Slack": { + "description": "ثبت نام کنید در {signupUrl}" + }, + "OSM-Reddit": { + "name": "OpenStreetMap در ردیت", + "description": "/r/openstreetmap/ یک مکان عالی برای کسب اطلاعات بیشتر در مورد OpenStreetMap است. از ما چیزی بپرسید!" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/fi.json b/vendor/assets/iD/iD/locales/fi.json index a8bef8e0a..3d65e6e68 100644 --- a/vendor/assets/iD/iD/locales/fi.json +++ b/vendor/assets/iD/iD/locales/fi.json @@ -1,5 +1,10 @@ { "fi": { + "icons": { + "information": "Tietoa", + "remove": "Poista", + "undo": "Peru" + }, "modes": { "add_area": { "title": "Alue", @@ -163,7 +168,6 @@ "annotation": "Yhdistetty {n} kohdetta.", "not_eligible": "Näitä ominaisuuksia ei voi sulauttaa yhteen.", "not_adjacent": "Näitä karttapisteitä ei voi yhdistää, sillä niiden päätepisteitä ei ole yhdistetty toisiinsa.", - "restriction": "Näitä kohteita ei voi yhdistää, koska ainakin yksi on on liitettynä relaatioon \"{relation}\" .", "incomplete_relation": "Näitä karttakohteita ei voi yhdistää, sillä ainakin yhden tietoja ei ole täysin ladattu.", "conflicting_tags": "Näitä kohteita ei voi yhdistää, koska joidenkin niiden ominaisuustiedoissa on ristiriitaisia arvoja. " }, @@ -291,6 +295,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Etäisyys", + "distance_up_to": "Enintään {distance}", + "via": "Kautta", + "via_node_only": "Vain yksi viivapiste", + "via_up_to_one": "Enintään yksi viiva", + "via_up_to_two": "Enintään kaksi viivaa" + }, + "help": { + "indirect": "(epäsuora)", + "turn": { + "no_left_turn": "EI vasemmalle (epäsuora)", + "no_right_turn": "EI oikealle (epäsuora)", + "no_u_turn": "EI U-käännöstä (epäsuora)", + "no_straight_on": "EI suoraan (epäsuora)", + "only_left_turn": "VAIN vasemmalle (epäsuora)", + "only_right_turn": "VAIN oikealle (epäsuora)", + "only_u_turn": "VAIN U-käännös (epäsuora)", + "only_straight_on": "VAIN suoraan (epäsuora)", + "allowed_left_turn": "SALLITTU vasemmalle (epäsuora)", + "allowed_right_turn": "SALLITTU oikealle (epäsuora)", + "allowed_u_turn": "SALLITTU U-käännös (epäsuora)", + "allowed_straight_on": "SALLITTU suoraan (epäsuora)" + }, + "from": "MISTÄ", + "via": "KAUTTA", + "to": "MIHIN", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Valitse {from}-väylä napsauttamalla sitä", + "select_from_name": "Valitse {from}-väyläksi {fromName} napsauttamalla", + "toggle": "Aseta \"{turn}\" napsauttamalla" + } + }, "undo": { "tooltip": "Kumoa: {action}", "nothing": "Ei muokkaushistoriaa." @@ -574,7 +614,7 @@ "status_code": "Palvelimen virhekoodi {code}", "unknown_error_details": "Varmista, että Internet-yhteys on käytössä.", "uploading": "Tallennetaan muutoksia OpenStreetMapiin...", - "conflict_progress": "Tarkista ristiriita: {num}/{total}", + "conflict_progress": "Tarkistetaan ristiriita {num}/{total}", "unsaved_changes": "Kaikkia muutoksia ei ole tallennettu", "conflict": { "header": "Ratkaise muokkausristiriidat", @@ -600,15 +640,20 @@ } }, "success": { - "edited_osm": "OSM:ia muokattu!", "just_edited": "Muokkasit juuri OpenStreetMapia!", - "view_on_osm": "Näytä OSM-kartalla", - "facebook": "Jaa Facebookissa", - "twitter": "Jaa Twitterissä", - "google": "Jaa Google+-palvelussa", + "thank_you": "Kiitos avustasi!", + "thank_you_location": "Kiitos, että paransit karttaa alueella {where}.", "help_html": "Karttaan tehdyt muutokset ilmestyvät perinteiseen karttanäkymään muutaman minuutin kuluessa. Joidenkin ominaisuuksien ilmestyminen kartalle ja muutokset joihinkin karttanäkymiin voivat viedä kauemmin.", - "help_link_text": "Tiedot", - "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" + "help_link_text": "Lisätietoja", + "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", + "view_on_osm": "Näytä muutokset OSM-kartalla", + "changeset_id": "Muutoskokoelman seurantatunnus: {changeset_id}", + "like_osm": "Tykkäätkö meistä? Kerro se muille:", + "more": "Lisää", + "events": "Tapahtumat", + "languages": "Kielet: {languages}", + "missing": "Puuttuuko listalta jotain?", + "tell_us": "Kerro meille!" }, "confirm": { "okay": "OK", @@ -726,11 +771,115 @@ "feature_editor": { "title": "Kohdemuokkain", "intro": "*Kohdemuokkain* näkyy muokkausnäkymän vasemmassa laidassa. Sitä käytetään karttakohteen ominaisuuksien tarkasteluun ja muokkaamiseen.", - "type_h": "Ominisuustyyppi", + "definitions": "Yläosassa näkyy karttakohteen tyyppi. Keskiosa sisältää *kenttiä*, jotka kuvaavat kohteen ominaisuuksia, kuten nimen ja osoitteen. ", + "type_h": "Ominaisuustyyppi", + "type": "Voit klikata karttakohteen tyyppiä vaihtaaksesi kohteen eri tyyppiseksi. Kaikki, mikä on olemassa, voidaan lisätä OpenStreetMapiin, joten on olemassa tuhansia kohdetyyppejä joista valita.", + "type_picker": "Kohdemuokkain näyttää kaikkein tavallisimmat kohdetyypit kuten puistot, sairaalat, ravintolat, tiet ja rakennukset. Voit hakea mitä tyyppiä tahansa kirjoittamalla hakulaatikkoon, mitä olet etsimässä. Voit myös klikata {inspect} **Tietoa** -ikonia kohteen tyypin vieressä saadaksesi kohdetyypistä lisätietoa.", + "fields_h": "Kentät", + "fields_all_fields": "\"Kaikki kentät\" -osa sisältää kaikki karttakohteen tiedot, joita voit muokata. OpenStreetMapissa kaikkien kenttien täyttäminen on vapaavalintaista, ja voit jättää kentän tyhjäksi jos olet epävarma.", + "fields_example": "Eri tyyppisille karttakohteille näkyy erilaiset kentät. Esimerkiksi tien kohdalla näkyy kentät tien päällysteelle ja nopeusrajoitukselle, kun taas ravintolan kohdalla näkyy kentät aukioloajoille ja sille, millaista ruokaa ravintola tarjoaa.", + "fields_add_field": "Voit klikata myös \"Lisää kenttä\" -pudotusvalikkoa lisätäksesi uusia kenttiä, kuten kuvauksen, Wikipedia-linkin, esteettömyyden pyörätuolin käyttäjille ja niin edelleen. ", + "tags_h": "Tägit eli ominaisuustiedot", + "tags_all_tags": "Voit laajentaa kenttien alapuolella olevan \"Kaikki ominaisuustiedot\" -osan lisätäksesi karttakohteelle mitä tahansa OpenStreetMapin *tägejä* ja muokataksesi niitä. Jokainen tägi sisältää *avaimen* ja *arvon*, tietotyypit jotka määrittävät kaikki OpenStreetMapiin tallennetut karttakohteet.", "tags_resources": "Karttakohteiden muokkaaminen edellyttää perustason osaamista OpenStreetMapin ominaisuuksista. Lisätietoa erilaisista ominaisuuksista ja karttakohteista on saatavilla esimerkiksi [OpenStreetMapin Wikistä](https://wiki.openstreetmap.org/wiki/Fi:Main_Page) tai [Taginfo-sivustolla](https://taginfo.openstreetmap.org/)." }, + "points": { + "title": "Paikkapisteet", + "intro": "*Paikkapisteillä* voidaan merkitä kauppojen, ravintoloiden ja patsaiden kaltaisia karttakohteita. Niillä on yksittäinen sijainti ja ne kertovat, mitä siellä on.", + "add_point_h": "Paikkapisteiden lisääminen", + "add_point": "Lisätäksesi paikkapisteen, klikkaa {point} **Paikkapiste** -painiketta työkalupalkissa kartan yläpuolella, tai paina pikanäppäintä `1`. Tämä muuttaa hiiren osoittimen ristimäiseksi.", + "add_point_finish": "Sijoittaaksesi uuden paikkapisteen kartalle, vie hiiri sinne, mihin haluat paikkapisteen, ja paina {leftclick} hiiren vasenta painiketta tai `Välilyönti` -näppäintä.", + "move_point_h": "Paikkapisteiden liikuttaminen", + "move_point": "Liikuttaaksesi paikkapistettä, aseta hiiren osoitin pisteen päälle ja paina {leftclick} hiiren vasenta painiketta. Pidä painike pohjassa ja raahaa paikkapiste uuteen sijaintiin.", + "delete_point_h": "Paikkapisteiden poistaminen", + "delete_point": "Voit poistaa kohteita, joita ei ole oikeasti olemassa. Kohteen poistaminen poistaa sen muidenkin kartalta, joten varmista ennen poistamista, että kohdetta ei todella ole.", + "delete_point_command": "Poistaaksesi pisteen, klikkaa pistettä {rightclick} hiiren oikealla näppäimellä ja valitse avautuvasta pikavalikosta {delete} **Poista**." + }, + "lines": { + "title": "Viivat", + "intro": "*Viivoilla* merkitään esimerkiksi katuja, rautateitä ja jokia. Viivat pitäisi piirtää niiden esittämän kohteen keskilinjaa pitkin.", + "add_line_h": "Viivojen lisääminen", + "add_line": "Lisätäksesi viivan, klikkaa {line} **Viiva** -painiketta työkalupalkissa kartan yläpuolella, tai paina pikanäppäintä `2`. Tämä muuttaa hiiren osoittimen ristimäiseksi.", + "add_line_draw": "Seuraavaksi siirrä hiiren osoitin sinne, mistä haluat viivan alkavan, ja paina {leftclick} hiiren vasenta painiketta tai `Välilyönti` -näppäintä. Lisää viivan loput pisteet klikkaamalla tai `Välilyönti` -näppäimellä. Voit lähentää, loitontaa tai raahata karttaa piirtäessäsi.", + "add_line_finish": "Lopettaaksesi viivan piirtämisen, paina `{Enter}` tai klikkaa viivan viimeistä pistettä uudestaan.", + "modify_line_h": "Viivojen muokkaaminen", + "modify_line_dragnode": "Viivat eivät usein ole oikean muotoisia, esimerkiksi tie ei vastaa ilmakuvaa. Muokataksesi viivan muotoa, ensin valitse viiva {leftclick} hiiren vasemmalla painikkeella. Tämä saa viivan pisteet näkymään pieninä ympyröinä. Sitten voit raahata pisteet parempiin sijainteihin.", + "modify_line_addnode": "Voit myös luoda viivaan uusia pisteitä joko {leftclick}**x2** kaksoisklikkaamalla viivaa tai raahamalla viivan pisteiden välissä olevaa pikkukolmiota.", + "connect_line_h": "Viivojen yhdistäminen", + "connect_line": "Teiden yhdistyminen oikein on tärkeää kartalla ja välttämätöntä ajo-ohjeiden tarjoamisessa.", + "connect_line_display": "Teiden risteykset näkyvät harmaina ympyröinä. Jos viivojen päätepisteet eivät yhdisty mihinkään, ne näkyvät suurempina valkoisina ympyröinä.", + "connect_line_drag": "Yhdistääksesi viivan toiseen kohteeseen, raahaa yksi viivan pisteistä toisen kohteen päälle, kunnes kohteet tarttuvat yhteen. Vinkki: Voit estää karttakohteen yhdistymisen muihin kohteisiin pitämällä `{alt}`-painiketta pohjassa.", + "connect_line_tag": "Jos tiedät, että risteyksessä on liikennevalot tai suojatie, voit lisätä ne valitsemalla tiet yhdistävän pisteen ja käyttämällä kohdemuokkainta.", + "disconnect_line_h": "Viivojen erottaminen", + "disconnect_line_command": "Erottaaksesi tien toisesta kohteesta, klikkaa kohteet yhdistävää pistettä {rightclick} hiiren oikealla näppäimellä ja valitse avautuvasta pikavalikosta {disconnect} **Erota**.", + "move_line_h": "Viivojen liikuttaminen", + "move_line_command": "Liikuttaaksesi kokonaista viivaa, klikkaa viivaa {rightclick} hiiren oikealla näppäimellä ja valitse avautuvasta pikavalikosta {move} **Siirrä**. Sitten liikuta hiirtä ja paina {leftclick} hiiren vasenta painiketta asettaaksesi viivan uuteen paikkaan.", + "move_line_connected": "Viivat, jotka ovat yhdistyneinä toisiin kohteisiin, pysyvät yhdistyneinä, kun liikutat viivan uuteen paikkaan. iD estää sinua siirtämästä viivaa toisen yhdistetyn viivan yli.", + "delete_line_h": "Viivojen poistaminen", + "delete_line": "Voit poistaa viivan jos se on täysin virheellinen, esimerkiksi tien jota ei ole oikeasti olemassa. Ole varovainen poistaessasi kohteita: ilmakuva saattaa olla vanhentunut ja virheelliseltä näyttävä tie taas uusi.", + "delete_line_command": "Poistaaksesi viivan, klikkaa viivaa {rightclick} hiiren oikealla näppäimellä ja valitse avautuvasta pikavalikosta {delete} **Poista**." + }, + "areas": { + "title": "Alueet", + "intro": "*Alueilla* kuvataan sellaisten kohteiden kuin järvien, rakennusten ja asuinalueiden rajoja. Alueet pitäisi piirtää kulkemaan niiden esittämän kohteen rajaa pitkin, esimerkiksi rakennuksen pohjan ympäri.", + "point_or_area_h": "Paikkapiste vai alue?", + "point_or_area": "Monet kohteet voi esittää niin paikkapisteinä kuin alueinakin. Sinun pitäisi kartoittaa esimerkiksi rakennukset ja maankäytölliset rajat alueiksi aina kun mahdollista. Voit sijoittaa paikkapisteitä rakennuksen alueen sisäpuolelle esittämään yrityksiä, palveluita ja muita rakennuksen sisällä olevia kohteita.", + "add_area_h": "Alueiden lisääminen", + "add_area_command": "Lisätäksesi alueen, klikkaa {area} **Alue** -painiketta työkalupalkissa kartan yläpuolella, tai paina pikanäppäintä `3`. Tämä muuttaa hiiren kursorin ristimäiseksi.", + "add_area_draw": "Seuraavaksi siirrä hiiren kursori yhteen alueen kulmista, ja paina {leftclick} hiiren vasenta painiketta tai `Välilyönti` -näppäintä. Lisää alueen rajan loput pisteet klikkaamalla tai `Välilyönti` -näppäimellä. Voit lähentää, loitontaa tai raahata karttaa piirtäessäsi.", + "add_area_finish": "Lopettaaksesi alueen piirtämisen, paina `{Enter}` tai klikkaa alueen rajan ensimmäistä tai viimeistä pistettä uudestaan.", + "square_area_h": "Muuttaminen suorakulmaiseksi", + "square_area_command": "Monilla aluemaisilla kohteilla kuten rakennuksilla on suorat kulmat. Muuttaaksesi alueen kulmat suoriksi, klikkaa alueen reunaa {rightclick} hiiren oikealla näppäimellä ja valitse avautuvasta pikavalikosta {orthogonalize} **Muuta suorakulmaiseksi**.", + "modify_area_h": "Alueiden muokkaaminen", + "modify_area_dragnode": "Alueet eivät usein ole oikean muotoisia, esimerkiksi rakennus ei vastaa ilmakuvaa. Muokataksesi alueen muotoa, ensin valitse alue {leftclick} hiiren vasemmalla painikkeella. Tämä saa alueen pisteet näkymään pieninä ympyröinä. Sitten voit raahata pisteet parempiin sijainteihin.", + "modify_area_addnode": "Voit myös luoda alueeseen uusia pisteitä joko {leftclick}**x2** kaksoisklikkaamalla alueen reunaa tai raahamalla alueen reunan pisteiden välissä olevia pikkukolmioita.", + "delete_area_h": "Alueiden poistaminen", + "delete_area": "Voit poistaa alueen jos se on täysin virheellinen, esimerkiksi rakennuksen jota ei ole oikeasti olemassa. Ole varovainen poistaessasi kohteita: ilmakuva saattaa olla vanhentunut ja virheelliseltä näyttävä rakennus taas uusi.", + "delete_area_command": "Poistaaksesi alueen, klikkaa aluetta {rightclick} hiiren oikealla näppäimellä ja valitse avautuvasta pikavalikosta {delete} **Poista**." + }, "relations": { - "relation_types_h": "Relaatiot" + "relation_types_h": "Relaatiotyypit" + }, + "gps": { + "title": "GPS-jäljet" + }, + "field": { + "restrictions": { + "title": "Kääntymisrajoitusten ohje", + "about": { + "title": "Yleistä", + "about": "Toiminnon avulla voit muokata kääntymisrajoituksia. Se näyttää mallin valitusta risteyksestä ja siihen yhdistetyistä teistä.", + "from_via_to": "Kääntymisrajoitus koostuu yhdestä \"MISTÄ-tiestä\", \"MIHIN-tiestä\" ja joko yhdestä \"KAUTTA-viivapisteestä\" tai yhdestä tai useammasta \"KAUTTA-tiestä\".", + "maxdist": "\"{distField}\"-liukusäätimellä voit valita, kuinka kaukaa haluat hakea yhdistyviä teitä.", + "maxvia": "\"{viaField}\"-liukusäätimellä voit valita, kuinka monta KAUTTA-väylää kääntymisrajoitukseen voi sisältyä (lähtökohtaisesti mahdollisimman vähän)." + }, + "inspecting": { + "title": "Tutkiminen", + "about": "Tarkista jonkin **MISTÄ**-väylän kääntymisrajoitukset viemällä hiiri sen päälle. Kaikki mahdolliset **MIHIN**-väylät korostetaan eri väreillä kääntymisrajoitusten tyypistä riippuen.", + "from_shadow": "{fromShadow} **MISTÄ-väylä**", + "allow_shadow": "{allowShadow} **MIHIN Sallittu**", + "restrict_shadow": "{restrictShadow} **MIHIN Rajoitettu**", + "only_shadow": "{onlyShadow} **MIHIN Vain**", + "restricted": "\"Rajoitettu\" tarkoittaa kääntymisrajoitusta, esimerkiksi \"Ei vasemmalle\".", + "only": "\"Vain\" tarkoittaa ainoaa sallittua ajosuuntaa, esimerkiksi \"Vain suoraan\"." + }, + "modifying": { + "title": "Muokkaaminen", + "about": "Aloita kääntymisrajoitusten muokkaaminen valitsemalla \"MISTÄ\"-väylä napsauttamalla sitä. Valittu väylä hehkuu sykkivästi ja mahdolliset **MIHIN**-kääntymissuunnat korostetaan nuolikuvakkeilla.", + "indicators": "Valitse sitten vaihtoehtojen sallittu, rajoitettu ja vain välillä napsauttamalla nuolikuvaketta.", + "allow_turn": "{allowTurn} **MIHIN Sallittu**", + "restrict_turn": "{restrictTurn} **MIHIN Rajoitettu**", + "only_turn": "{onlyTurn} **MIHIN Vain**" + }, + "tips": { + "title": "Vinkkejä", + "simple": "**Suosi yksinkertaisia rajoituksia**", + "simple_example": "Pyri välttämään monen väylän kautta kulkevia rajoituksia, jos sama rajoitus voidaan osoittaa pelkällä yhteen pisteeseen sidotulla rajoituksella.", + "indirect": "**Osa rajoituksista näkyy haaleampina ja epäsuora-merkinnällä**", + "indirect_example": "Rajoitukset johtuvat epäsuorasti toisesta rajoituksesta. Esimerkiksi \"Vain suoraan\" asettaa \"Ei käännöstä\" kaikkiin muihin suuntiin.", + "indirect_noedit": "Epäsuoria rajoituksia ei voi muokata. Muokkaa sen sijaan sen aiheuttavaa rajoitusta." + } + } } }, "intro": { @@ -785,6 +934,7 @@ "choose_cafe": "**Valitse {preset} listalta.**", "feature_editor": "Piste on nyt merkitty kahvilaksi. Kohdemuokkaimella voi täydentää sen tietoja.", "add_name": "OpenStreetMapissa minkään kentän täyttäminen ei ole pakollista, ja voit jättää kenttiä tyhjäksi.{br}Kuvitellaan, että tunnet tämän kahvilan paikallistuntemukselta ja muistat sen nimen. **Kirjoita kahvilalle nimi.**", + "add_close": "Kohdemuokkain tallentaa muutokset automaattisesti. **Kun olet kirjoittanut nimen, sulje kohdemuokkain painamalla Esc- tai Enter-näppäintä tai napsauttamalla {button}-painiketta.**", "reselect": "Usein paikkapisteet on jo lisätty kartalle, mutta niiden tiedot voivat olla vanhentuneita tai puutteellisia. Näitä tietoja voi korjata tai täydentää. **Valitse äsken luomasi kahvila napsauttamalla sitä.**", "update": "Lisätään kahvilalle tietoja. Voit vaihtaa nimen, lisätä keittiökulttuurin tai osoitteen. **Muuta kahvilan tietoja.**", "rightclick": "Napsauttamalla karttakohdetta hiiren oikealla painikkeella näkyviin tulee pikavalikko, jossa näytetään käytettävissä olevat muokkaustoiminnot. **Avaa pikavalikko napsauttamalla paikkapistettä hiiren oikealla painikkeella.**", @@ -955,6 +1105,12 @@ } } }, + "units": { + "meters": "{quantity} m", + "kilometers": "{quantity} km", + "square_meters": "{quantity} m²", + "square_kilometers": "{quantity} km²" + }, "presets": { "categories": { "category-barrier": { @@ -1340,6 +1496,9 @@ "cycleway:right": "Oikealla puolella" } }, + "dance/style": { + "label": "Tanssityylit" + }, "date": { "label": "Päivämäärä" }, @@ -1520,6 +1679,9 @@ "government": { "label": "Tyyppi" }, + "grape_variety": { + "label": "Rypälelajikkeet" + }, "handicap": { "label": "Tasoitussuositus (HCP)", "placeholder": "1-18" @@ -1533,6 +1695,9 @@ "healthcare": { "label": "Tyyppi" }, + "healthcare/speciality": { + "label": "Erikoisalat" + }, "height": { "label": "Korkeus (metreinä)" }, @@ -1571,6 +1736,12 @@ "information": { "label": "Tyyppi" }, + "inscription": { + "label": "Sisältyvä kaiverrus/kirjoitus" + }, + "intermittent": { + "label": "Kuivuminen ajoittain" + }, "internet_access": { "label": "Internet-yhteys", "options": { @@ -1587,6 +1758,9 @@ "internet_access/ssid": { "label": "SSID-verkkonimi" }, + "kerb": { + "label": "Reunakiveyksen muoto" + }, "lamp_type": { "label": "Tyyppi" }, @@ -1675,6 +1849,9 @@ "label": "Nopeusrajoitus", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "Suositusnopeus" + }, "maxstay": { "label": "Sallittu enimmäisaika" }, @@ -1773,6 +1950,7 @@ "label": "Yksisuuntaisuus", "options": { "no": "Ei", + "reversible": "Epäsäännöllisesti vaihtuva", "undefined": "Oletettavasti ei", "yes": "Kyllä" } @@ -1780,7 +1958,9 @@ "oneway_yes": { "label": "Yksisuuntaisuus", "options": { + "alternating": "Säännöllisesti vaihtuva", "no": "Ei", + "reversible": "Epäsäännöllisesti vaihtuva", "undefined": "Oletettavasti kyllä", "yes": "Kyllä" } @@ -1817,7 +1997,6 @@ "label": "Maksutavat" }, "phone": { - "label": "Puhelinnumero", "placeholder": "+358 40 123 4567" }, "piste/difficulty": { @@ -1864,6 +2043,10 @@ "plant": { "label": "Kasvi" }, + "plant/output/electricity": { + "label": "Voiman ulostulo", + "placeholder": "500 MW, 1000 MW, 2000 MW..." + }, "playground/max_age": { "label": "Yläikäraja" }, @@ -1902,6 +2085,9 @@ "recycling_accepts": { "label": "Keräys" }, + "ref/isil": { + "label": "ISIL-tunnus" + }, "ref_aeroway_gate": { "label": "Porttinumero" }, @@ -2047,6 +2233,18 @@ "source": { "label": "Lähteet" }, + "sport": { + "label": "Urheilulajit" + }, + "sport_ice": { + "label": "Urheilulajit" + }, + "sport_racing_motor": { + "label": "Urheilulajit" + }, + "sport_racing_nonmotor": { + "label": "Urheilulajit" + }, "stars": { "label": "Tähdet" }, @@ -2084,12 +2282,18 @@ "studio": { "label": "Tyyppi" }, + "substance": { + "label": "Sisältö" + }, "substation": { "label": "Tyyppi" }, "supervised": { "label": "Valvonta" }, + "support": { + "label": "Pidike" + }, "surface": { "label": "Päällyste" }, @@ -2108,7 +2312,13 @@ "label": "Valvontavyöhyke" }, "switch": { - "label": "Tyyppi" + "label": "Tyyppi", + "options": { + "circuit_breaker": "Sulake", + "disconnector": "Erotin", + "earthing": "Maadoitus", + "mechanical": "Mekaaninen kytkin" + } }, "tactile_paving": { "label": "Huomioreuna näkövammaisille" @@ -2125,6 +2335,7 @@ "toilets/disposal": { "label": "Tyhjennystekniikka", "options": { + "bucket": "Ämpäri", "chemical": "Kemikaalinen", "flush": "Huuhtelu", "pitlatrine": "Peittoaines" @@ -2139,11 +2350,26 @@ "tourism": { "label": "Tyyppi" }, + "tourism_attraction": { + "label": "Tyyppi" + }, + "tower/construction": { + "label": "Rakenne", + "placeholder": "Harusvaijerit, Ristikko..." + }, "tower/type": { "label": "Tyyppi" }, "tracktype": { - "label": "Raidetyyppi" + "label": "Raidetyyppi", + "options": { + "grade1": "Kiinteä: päällystetty tai voimakkaasti pakkaantunut, kova pinta", + "grade2": "Enimmäkseen kiinteä: soraa/kiveä johon sekoittunut hieman pehmeää maa-ainesta", + "grade3": "Sekoitus kovaa ja pehmeää maa-ainesta", + "grade4": "Enimmäkseen pehmeä: multaa/hiekkaa/ruohoa johon sekoittunut hieman kovaa maa-ainesta", + "grade5": "Pehmeä: multaa/hiekkaa/ruohoa" + }, + "placeholder": "Kiinteä, Enimmäkseen kiinteä, Pehmeä..." }, "trade": { "label": "Tyyppi" @@ -2183,9 +2409,6 @@ "tunnel": { "label": "Tyyppi" }, - "vending": { - "label": "Tavaroiden tyyppi" - }, "visibility": { "label": "Näkyvyys", "options": { @@ -2205,6 +2428,7 @@ "volcano/type": { "label": "Tulivuorilaji", "options": { + "scoria": "Tuhkakartio", "shield": "Kilpitulivuori", "stratovolcano": "Kerrostulivuori" } @@ -2364,7 +2588,8 @@ "name": "Eläinkatos" }, "amenity/arts_centre": { - "name": "Taidekeskus" + "name": "Taidekeskus", + "terms": "taidekeskus, taidetalo, taidekoulu, kulttuurikeskus, kulttuuritalo, esityspaikka, esiintymispaikka, näytöspaikka, poikkitaiteellinen, teatteri, live, stand-up, konsertti, galleria, näyttely, nykytaide" }, "amenity/atm": { "name": "Pankkiautomaatti", @@ -2461,7 +2686,8 @@ "name": "Korkeakoulualue (college)" }, "amenity/community_centre": { - "name": "Yhteisökeskus" + "name": "Yhteisökeskus", + "terms": "yhteisökeskus, yhdistys, järjestö, kylätalo, kyläkeskus, seurantalo, seurojentalo, työväentalo, kerhotalo, kerhohuoneisto, kerhokeskus, klubi, monitoimitalo, nuorisotila, nuorisotalo, kokoontumispaikka, kokouspaikka, kokoustila, konferenssi, palaveri, neuvottelu, tapahtumapaikka, juhlatila, hääpaikka, sosiaalitila, avoin, julkinen" }, "amenity/compressed_air": { "name": "Ilmanpainepiste", @@ -2490,7 +2716,8 @@ "terms": "taistelulaji, taistelu, itsepuolustus, laji, lajit, urheilu, kamppailu, kamppailulaji, itsepuolustuslaji, taekwondo, taekwon-do, judo, karate, taiji, jujutsu, aikido, kravmaga, krav maga, hapkido" }, "amenity/drinking_water": { - "name": "Juomavesipiste" + "name": "Juomavesipiste", + "terms": "juomavesi, juoma-automaatti, juomapaikka, vesipiste, vesiautomaatti, vedenjakelu, hana, kaivo" }, "amenity/driving_school": { "name": "Autokoulu", @@ -2540,7 +2767,8 @@ "terms": "jäätelö, pehmis, jäätelön, pehmiksen, jäätelökioski, jätskikioski, jäätelöbaari, kioski, puoti, kauppa, liike, myymälä, putiikki, baari" }, "amenity/internet_cafe": { - "name": "Internetkahvila" + "name": "Internetkahvila", + "terms": "nettikahvila, wlan, wifi" }, "amenity/kindergarten": { "name": "Esikoulu", @@ -2561,7 +2789,8 @@ "name": "Moottoripyöräpysäköinti" }, "amenity/music_school": { - "name": "Musiikkikoulu" + "name": "Musiikkikoulu", + "terms": "musiikkikoulu, musiikkileikkikoulu, musiikkiopetus, musiikkiopettaja, musiikkioppilaitos, musiikkiopisto, muskari, soitonopetus, laulunopetus, konservatorio, taideakatemia, kuoro, yhtye, bändi, orkesteri, kitara, piano" }, "amenity/nightclub": { "name": "Yökerho" @@ -2578,7 +2807,8 @@ "terms": "pysäköinti, parkkipaikka, pysäköintipaikka, parkki, pysäköintitalo, parkkitalo, ulosajo, sisäänajo, ajo, ulos, sisään, ramppi" }, "amenity/parking_space": { - "name": "Pysäköintitila" + "name": "Pysäköintitila", + "terms": "pysäköinti, pysäköintipaikka, pysäköintiruutu, parkkipaikka, parkkeeraus, autopysäköinti, autopaikka" }, "amenity/pavilion": { "name": "Paviljonki" @@ -2589,29 +2819,39 @@ }, "amenity/place_of_worship": { "name": "Rukoilupaikka", - "terms": "Uskonnollinen rakennus, Kirkkorakennus" + "terms": "Uskonnollinen rakennus, Kirkkorakennus, seurakuntatalo, temppeli, luostari, munkki, nunna, katedraali, kappeli, uhrauspaikka, uhripaikka, kulttipaikka, pyhäkkö, pyhättö, pyhä, jumalanpalvelus, rukoushuone, valtakunnansali, loosi, seita, keskus" }, "amenity/place_of_worship/buddhist": { - "name": "Buddhalaistemppeli" + "name": "Buddhalaistemppeli", + "terms": "buddhalainen, stupa, pagoda, luostari, zendo, dojo, meditaatio" }, "amenity/place_of_worship/christian": { "name": "Kirkko", - "terms": "Kirkko, Pyhäkkö, pyhättö, Rukoushuone, Stupa, Tsasouna, Moskeija, Temppeli" + "terms": "Kirkko, kirkkosali, tuomiokirkko, kappeli, kotikirkko, leirikirkko, katedraali, Pyhäkkö, pyhättö, Rukoushuone, Tsasouna, Temppeli, seurakunta" }, "amenity/place_of_worship/hindu": { "name": "Hindutemppeli", - "terms": "hindulaisuus, hindut, hindu, temppeli, uskonto, uskonnollinen, rukoilu, intia" + "terms": "hindulaisuus, hindut, hindu, temppeli, uskonto, uskonnollinen, rukoilu, intia, jooga" }, "amenity/place_of_worship/jewish": { "name": "Synagoga", - "terms": "synagooga" + "terms": "synagooga, juutalainen" }, "amenity/place_of_worship/muslim": { "name": "Moskeija", - "terms": "Moskeija" + "terms": "minareetti, islam, islamilainen, muslimi" }, "amenity/place_of_worship/shinto": { - "name": "Šintolainen pyhäkkö" + "name": "Šintolainen pyhäkkö", + "terms": "Šintopyhäkkö, pyhättö, shintolainen, japanilainen, kami, asuinpaikka, jumala, henki, torii, honden, shinden, haiden, heiden, seremonia, uhrihalli" + }, + "amenity/place_of_worship/sikh": { + "name": "Sikhitemppeli", + "terms": "sikhiläinen, gurdwara, gurudwara" + }, + "amenity/place_of_worship/taoist": { + "name": "Taolainen temppeli", + "terms": "taolaistemppeli, kungfutselainen, kiinalainen, luostari" }, "amenity/planetarium": { "name": "Planetaario" @@ -2632,7 +2872,8 @@ "name": "Vankila-alue" }, "amenity/pub": { - "name": "Pubi" + "name": "Pubi", + "terms": "pubi, pub, kapakka, saluuna, kievari, taverna, krouvi, yöravintola, olutravintola, oluttupa, kaljaravintola, alkoholi, baari" }, "amenity/public_bath": { "name": "Kylpylaitos" @@ -2655,7 +2896,7 @@ }, "amenity/restaurant": { "name": "Ravintola", - "terms": "Ravintola, Ruokaravintola, Bistro, Krouvi, Pizzeria, Ruokala" + "terms": "Ravintola, Ruokaravintola, Bistro, Krouvi, Pizzeria, Pitseria, Ruokala" }, "amenity/sanitary_dump_station": { "name": "Asuntoautojen jäteveden tyhjennyspiste" @@ -2668,19 +2909,22 @@ "name": "Autonromuttamo" }, "amenity/shelter": { - "name": "Katos" + "name": "Katos", + "terms": "katos, katettu, kota, kotus, korsu, laavu, maja, koppi, suoja, tauko, taukopaikka, taukokatos, piknik, picnic, retki, lepo, lepääminen, pukukoppi, pukeutuminen, bussi, linja-auto, kalliolippa" }, "amenity/shower": { "name": "Suihku" }, "amenity/smoking_area": { - "name": "Tupakointialue" + "name": "Tupakointialue", + "terms": "tupakkapaikka" }, "amenity/social_facility": { "name": "Sosiaalipalvelu" }, "amenity/social_facility/food_bank": { - "name": "Ruokapankki" + "name": "Ruokapankki", + "terms": "ruokajako, ruokajakelu, leipäjono" }, "amenity/social_facility/group_home": { "name": "Vanhainkoti", @@ -2723,7 +2967,8 @@ "name": "Yliopistoalue" }, "amenity/vending_machine": { - "name": "Myyntiautomaatti" + "name": "Myyntiautomaatti", + "terms": "automaatti, myyntiautomaatti, jakeluautomaatti, palautusautomaatti, pullonpalautus" }, "amenity/vending_machine/cigarettes": { "name": "Tupakka-automaatti", @@ -2795,14 +3040,16 @@ "name": "Alue" }, "area/highway": { - "name": "Tien päällyste" + "name": "Tien päällyste", + "terms": "pinnoite, pinta" }, "attraction/amusement_ride": { "name": "Huvipuistolaite", "terms": "huvipuisto, elämyspuisto, laite, härveli, vuoristorata, karuselli, vimpain, vitkutin, huvilaite" }, "attraction/animal": { - "name": "Eläin" + "name": "Eläin", + "terms": "eläintarha, eläinpuisto, teemapuisto, leijona, tiikeri, karhu" }, "attraction/big_wheel": { "name": "Maailmanpyörä", @@ -2851,7 +3098,8 @@ "name": "Muuri" }, "barrier/block": { - "name": "Este" + "name": "Este", + "terms": "betoniporsas" }, "barrier/bollard": { "name": "Sulkutolppa", @@ -2913,7 +3161,8 @@ "name": "Hallinnollinen raja" }, "building": { - "name": "Rakennus" + "name": "Rakennus", + "terms": "talo" }, "building/apartments": { "name": "Kerrostalo" @@ -2936,6 +3185,9 @@ "building/church": { "name": "Kirkkorakennus" }, + "building/civic": { + "name": "Kunnallinen rakennus" + }, "building/college": { "name": "Korkeakoulurakennus (college)" }, @@ -2955,6 +3207,12 @@ "building/entrance": { "name": "Sisään- tai uloskäynti" }, + "building/farm": { + "name": "Maatilan asuinrakennus" + }, + "building/farm_auxiliary": { + "name": "Maatilarakennus" + }, "building/garage": { "name": "Autotalli", "terms": "autotalli, autonsäilytys, autohalli, autovarasto, auto" @@ -2988,13 +3246,15 @@ "name": "Esikoulurakennus" }, "building/mosque": { - "name": "Moskeijarakennus" + "name": "Moskeijarakennus", + "terms": "islamilainen, muslimi" }, "building/public": { "name": "Julkinen rakennus" }, "building/residential": { - "name": "Asuinrakennus" + "name": "Asuinrakennus", + "terms": "asuintalo" }, "building/retail": { "name": "Liikerakennus" @@ -3012,6 +3272,9 @@ "building/semidetached_house": { "name": "Paritalo" }, + "building/service": { + "name": "Palvelurakennus" + }, "building/shed": { "name": "Vaja", "terms": "vaja, mökki, liiteri" @@ -3085,20 +3348,23 @@ "name": "Kelloseppä" }, "craft/confectionery": { - "name": "Makeiskonditoria" + "name": "Makeiskonditoria", + "terms": "karkkitehdas, karkki, karamelli" }, "craft/distillery": { - "name": "Tislaam", + "name": "Tislaamo", "terms": "viina, viini, alkoholi, polttaa, poltto, polttamo, tynnyri, juoma" }, "craft/dressmaker": { - "name": "ompelija" + "name": "ompelija", + "terms": "ompelimo" }, "craft/electrician": { "name": "Sähköasentaja" }, "craft/gardener": { - "name": "Puutarhuri" + "name": "Puutarhuri", + "terms": "puutarhan hoitaja, puutarha, hoitaja" }, "craft/glaziery": { "name": "Lasinpuhallus" @@ -3132,7 +3398,8 @@ "name": "optikko" }, "craft/painter": { - "name": "Maalari" + "name": "Maalari", + "terms": "maalaaja" }, "craft/photographer": { "name": "Valokuvaaja" @@ -3309,7 +3576,8 @@ "name": "Terveyspalvelu" }, "healthcare/alternative": { - "name": "Vaihtoehtolääketiede" + "name": "Vaihtoehtolääketiede", + "terms": "näennäishoito, vaihtoehto, vaihtoehtoinen, lääketiede, hoito" }, "healthcare/alternative/chiropractic": { "name": "Kiropraktikko" @@ -3339,7 +3607,8 @@ "name": "Optometri" }, "healthcare/physiotherapist": { - "name": "Fysioterapeutti" + "name": "Fysioterapeutti", + "terms": "fysioterapia" }, "healthcare/podiatrist": { "name": "Jalkaterapeutti" @@ -3488,7 +3757,8 @@ "name": "Yhdystien ramppi" }, "highway/track": { - "name": "Huoltamaton pikkutie" + "name": "Huoltamaton pikkutie", + "terms": "pikkutie, hiekkatie, metsätie, metsäkonetie, metsä, metsäkone, ura, ajoväylä" }, "highway/traffic_mirror": { "name": "Tiepeili", @@ -3514,7 +3784,8 @@ "name": "Syrjätie/luokittelematon tie" }, "historic": { - "name": "Historiallinen paikka" + "name": "Historiallinen paikka", + "terms": "historia, historiallinen, muinainen, arkeologinen, vanha, raunio, rauniot, raunioitunut, hauta, hautapaikka, muinaishauta, asuinpaikka, löytöpaikka, rajakivi, kartano, tienvarsiristi, hylky, maanmittaus, monumentti, muistomerkki, kivikautinen, pronssikautinen, rautakautinen, keskiaikainen" }, "historic/archaeological_site": { "name": "Arkeologinen paikka" @@ -3532,17 +3803,19 @@ "name": "Iso muistomerkki" }, "historic/ruins": { - "name": "Rauniot" + "name": "Rauniot", + "terms": "raunio, raunioitunut, käyttämätön, historiallinen" }, "historic/tomb": { "name": "Hautakammio" }, "historic/wayside_cross": { - "name": "Tienvarren risti" + "name": "Tienvarsiristi", + "terms": "tienvarren risti, tienvarren, risti, tienvarsi, piennar, kristillinen" }, "historic/wayside_shrine": { "name": "Tienvarsialttari", - "terms": "tienvarsi, kadunvarsi, varsi, tie, katu, rukoilupaikka, pyhättö, uskonnot, uskonto, kirkko, pyhä, uhripaikka, uhrauspaikka, uhrilahja" + "terms": "tienvarsi, kadunvarsi, varsi, tie, katu, rukoilupaikka, pyhättö, uskonnot, uskonto, kirkko, pyhä, uhripaikka, uhrauspaikka, uhrilahja, alttari" }, "junction": { "name": "Risteys" @@ -3551,10 +3824,12 @@ "name": "Maankäyttö" }, "landuse/allotments": { - "name": "Yhteisöpuutarha" + "name": "Yhteisöpuutarha", + "terms": "siirtolapuutarha" }, "landuse/aquaculture": { - "name": "Vesiviljely" + "name": "Vesiviljely", + "terms": "akvakulttuuri" }, "landuse/basin": { "name": "Vesiallas" @@ -3607,7 +3882,7 @@ }, "landuse/meadow": { "name": "Niitty", - "terms": "heinämaa, aukio" + "terms": "heinämaa, aukio, keto, aho, kesanto, kukka, luonto, luonnon, luonnollinen" }, "landuse/military": { "name": "Sotilasalue" @@ -3699,6 +3974,10 @@ "name": "Tanssipaikka", "terms": "tanssilava, tanssilavat, lavatanssi, lavatanssiminen, tanssi, tanssit, tanssiminen" }, + "leisure/dancing_school": { + "name": "Tanssikoulu", + "terms": "tanssiopisto" + }, "leisure/dog_park": { "name": "Koirapuisto", "terms": "koira, koirat, koira-alue, koiranulkoilutusalue, koirahäkki, koirapuisto" @@ -3726,7 +4005,8 @@ "name": "Golfkenttä" }, "leisure/hackerspace": { - "name": "Koodausnurkkaus" + "name": "Koodausnurkkaus", + "terms": "hackerspace, hackspace, makerspace, hacklab, häckläb, ohjelmointi, ohjelmoija, koodaus, koodaaja, teknologia, rakentelu, värkkäys, värkkäily, paja, työpaja, tila, julkinen, labra, verstas, kaupunkiverstas" }, "leisure/horse_riding": { "name": "Ratsastusalue", @@ -3755,7 +4035,8 @@ "terms": "piknik, eväsretki, ulkoilu, ulkopöytä, pöytä, puupöytä, penkki, ruokailu, ulkoruokailu, ulkoruokailupöytä, ulkoruokapöytä" }, "leisure/pitch": { - "name": "Urheilukenttä" + "name": "Urheilukenttä", + "terms": "pallokenttä, palloilukenttä, hiekkakenttä, nurmikenttä" }, "leisure/pitch/american_football": { "name": "Amerikkalainen jalkapallo -kenttä" @@ -3821,6 +4102,10 @@ "name": "Veneramppi", "terms": "veneramppi, vesillelaskupaikka, veneenlaskupaikka, vene, järveenlaskupaikka, järviramppi" }, + "leisure/sports_centre": { + "name": "Liikuntakeskus", + "terms": "kuntokeskus, urheilukeskus, urheiluhalli, halli, kompleksi, kokonaisuus, monilajinen" + }, "leisure/sports_centre/swimming": { "name": "Uimahalli", "terms": "uimahalli, kylpylä, uima-allas, uintikeskus, uinti, uiminen, vesi, vesiurheilu, urheilu, vesiurheilukeskus, vesiurheiluhalli" @@ -3836,13 +4121,15 @@ "name": "Kilparata (ei moottoriurheilu)" }, "leisure/water_park": { - "name": "Vesipuisto" + "name": "Vesipuisto", + "terms": "uinti, kylpylä" }, "line": { "name": "Viiva" }, "man_made": { - "name": "Ihmisen tekemä" + "name": "Ihmisen tekemä", + "terms": "keinotekoinen" }, "man_made/adit": { "name": "Vaakasuoran tunnelin suuaukko" @@ -3860,7 +4147,8 @@ "name": "Nosturi" }, "man_made/cutline": { - "name": "Metsänraja" + "name": "Metsänraja", + "terms": "hakkuuraja" }, "man_made/embankment": { "name": "Penkere" @@ -3882,6 +4170,9 @@ "man_made/mast": { "name": "Masto" }, + "man_made/monitoring_station": { + "name": "Havaintoasema" + }, "man_made/observation": { "name": "Näkötorni", "terms": "observatorio, näköalatasanne, näköala, maisema, maisematorni" @@ -3961,7 +4252,8 @@ "name": "Luolan suuaukko" }, "natural/cliff": { - "name": "Kallionjyrkänne" + "name": "Kallionjyrkänne", + "terms": "kallio, jyrkänne, kallioseinämä, seinämä, pystyseinämä, jyrkkä rinne, rinne, pudotus, mäki, penger, törmä, töyräs" }, "natural/coastline": { "name": "Rannikko", @@ -3984,7 +4276,8 @@ "terms": "Huippu, Vuorenhuippu, Korkein kohta, Vuoren huippu" }, "natural/ridge": { - "name": "Harju" + "name": "Harju", + "terms": "harju, reunamuodostuma, salpausselkä, harjanne, selänne, mäki" }, "natural/saddle": { "name": "Sola", @@ -4036,7 +4329,8 @@ "name": "Ei uloskäyntiä" }, "office": { - "name": "Toimisto" + "name": "Toimisto", + "terms": "konttori, toimipaikka, liikehuoneisto, virasto" }, "office/accountant": { "name": "Tilintarkastustoimisto", @@ -4064,7 +4358,8 @@ "name": "Hyväntekeväisyysjärjestö" }, "office/company": { - "name": "Yritystoimisto" + "name": "Yritystoimisto", + "terms": "yritys, yrittäjä, yhtiö, firma, oy, osakeyhtiö, kommandiittiyhtiö, tmi, toiminimi, analyytikko, edustusliike, finanssipalvelu, holdingyhtiö, henkilöstöyhtiö, isännöinti, isännöijä, jätehuoltoyhtiö, kahvipaahtamo, konsultti, konsultointi, koulutusyritys, kultaseppä, käännöstoimisto, liikenneyhtiö, taksiyritys, markkinatutkimus, meklari, muotoilu, musiikkistudio, pörssi, pörssiyhtiö, rakennusliike, rakentaja, treidaaja, yritysrahoitus, sijoitusyhtiö, sijoittaja, teollisuusyritys, uutistoimisto, vartiointiliike, viestintä, yritysviestintä, välittäjä" }, "office/coworking": { "name": "Yhteistyöskentelytila" @@ -4129,7 +4424,10 @@ }, "office/ngo": { "name": "Kansalaisjärjestö", - "terms": "kansalaisjärjestö, järjestö, kansanliike, kansanjärjestö, kansalaisjärjestötoimisto, toimisto" + "terms": "kansalaisjärjestö, järjestö, kansanliike, kansanjärjestö, kansalaisjärjestötoimisto, toimisto, kolmas sektori, kolmannen sektorin, vapaaehtois" + }, + "office/notary": { + "name": "Notaari" }, "office/physician": { "name": "Lääkäri" @@ -4159,6 +4457,10 @@ "office/travel_agent": { "name": "Matkatoimisto" }, + "office/water_utility": { + "name": "Vesilaitos", + "terms": "vesipalvelu, vesihuoltolaitos, vesihuolto, vedenjakelu, vesiosuuskunta, vesikunta, viemäröintilaitos, vesi, toimisto" + }, "piste": { "name": "Laskettelurinne/hiihtolatu", "terms": "laskettelu, alamäki, mäki, laskettelumäki, rinne, latu, hiihtolatu, urheilu, kuntoilu, liikunta, talvi, talviliikunta, talviurheilu, talvikuntoilu" @@ -4174,7 +4476,8 @@ "name": "Maatila" }, "place/hamlet": { - "name": "Pikkukylä" + "name": "Pikkukylä", + "terms": "kulmakunta, pieni kylä, sivukylä, kylä, paikkakunta, paikannimi, takamaa, seutu, naapurusto, taloryhmä, taajama, haja-asutus" }, "place/island": { "name": "Saari", @@ -4209,12 +4512,33 @@ "place/village": { "name": "Kylä" }, + "playground/balance_beam": { + "name": "Nuorallakävely" + }, + "playground/basket_swing": { + "name": "Korikeinu" + }, + "playground/rocker": { + "name": "Keinuhevonen" + }, + "playground/roundabout": { + "name": "Karuselli" + }, "playground/sandpit": { "name": "Hiekkalaatikko" }, + "playground/seesaw": { + "name": "Keinulauta" + }, "playground/slide": { "name": "Liukumäki" }, + "playground/structure": { + "name": "Kiipeilyteline" + }, + "playground/swing": { + "name": "Keinu" + }, "point": { "name": "Paikkapiste" }, @@ -4260,7 +4584,8 @@ "terms": "ilmarata, köysirata, gondoli, hissi, laituri, pysäkki, alue" }, "public_transport/linear_platform_bus": { - "name": "Linja-autopysäkki/-laituri" + "name": "Linja-autopysäkki/-laituri", + "terms": "linja-autopysäkki, bussipysäkki, pysäkki, pysähdyspaikka, odotuspaikka, linja-auto, bussi, dösis, dösäri, levennys, pysäkkimerkki, katos, pikavuoro, linja-autolaituri, bussilaituri, laituri, joukkoliikenne" }, "public_transport/linear_platform_ferry": { "name": "Laivapaikka/-matkustajalaituri" @@ -4289,7 +4614,8 @@ "terms": "ilmarata, gondoli, hissi, laituri, pysäkki, alue" }, "public_transport/platform_bus": { - "name": "Linja-autopysäkki/-laituri" + "name": "Linja-autopysäkki/-laituri", + "terms": "linja-autopysäkki, bussipysäkki, pysäkki, pysähdyspaikka, odotuspaikka, linja-auto, bussi, dösis, dösäri, levennys, pysäkkimerkki, katos, pikavuoro, linja-autolaituri, bussilaituri, laituri, joukkoliikenne" }, "public_transport/platform_ferry": { "name": "Laivapaikka/-matkustajalaituri" @@ -4456,10 +4782,12 @@ "name": "Lauttareitti" }, "shop": { - "name": "Kauppa" + "name": "Kauppa", + "terms": "myymälä, liike, market, marketti, puoti, putiikki, tavaratalo" }, "shop/alcohol": { - "name": "Alkoholimyymälä" + "name": "Alkoholimyymälä", + "terms": "viina, olut, viini, viinikellari, juoma" }, "shop/anime": { "name": "Anime-myymälä", @@ -4519,7 +4847,8 @@ "name": "Kirjakauppa" }, "shop/boutique": { - "name": "Muotiliike" + "name": "Muotiliike", + "terms": "vaate, asuste" }, "shop/butcher": { "name": "Lihakauppias" @@ -4548,7 +4877,8 @@ "name": "Juustopuoti" }, "shop/chemist": { - "name": "Apteekki-luontaistuotemyymälä" + "name": "Apteekki-luontaistuotemyymälä", + "terms": "lääke, luontaislääkintä, terveys" }, "shop/chocolate": { "name": "Suklaapuoti" @@ -4675,7 +5005,8 @@ "name": "Hifi-myymälä" }, "shop/interior_decoration": { - "name": "Sisustusmyymälä" + "name": "Sisustusmyymälä", + "terms": "huonekalu, kalustus, kaluste, koriste, esine, kauppa, liike" }, "shop/jewelry": { "name": "Jalokiviliike" @@ -4738,7 +5069,7 @@ }, "shop/organic": { "name": "Luomumyymälä", - "terms": "luomu, luomuruoka, ympäristö, ympäristöystävällisyys, ruoka, ruokakauppa" + "terms": "luomu, luomuruoka, ympäristö, ympäristöystävällisyys, ruoka, ruokakauppa, luonnonmukainen" }, "shop/outdoor": { "name": "Ulkoilmamyymälä" @@ -4772,7 +5103,8 @@ "terms": "radio, elektroniikka, komponentti, tekninen, tekniikka, osa, osat, varaosa" }, "shop/religion": { - "name": "Uskonnollinen myymälä" + "name": "Uskonnollinen myymälä", + "terms": "kristillinen, kauppa, hengellinen, henkinen" }, "shop/scuba_diving": { "name": "Sukellusliike", @@ -4783,7 +5115,7 @@ }, "shop/second_hand": { "name": "Käytetyn tavaran kauppa", - "terms": "kirpputori, myymälä, liike, kauppa, second hand, käytetty, käytettyä, käytetyn, tavara, jälleenmyynti, vertaiskauppa" + "terms": "kirpputori, myymälä, liike, kauppa, second hand, käytetty, käytettyä, käytetyn, tavara, jälleenmyynti, vertaiskauppa, osto- ja myyntiliike" }, "shop/shoes": { "name": "Kenkäkauppa" @@ -4877,13 +5209,14 @@ }, "tourism/artwork": { "name": "Taideteos", - "terms": "taideteos, patsas, veistos, taide, taiteellinen, teos" + "terms": "taideteos, patsas, veistos, taide, taiteellinen, teos, installaatio" }, "tourism/attraction": { "name": "Turistikohde" }, "tourism/camp_site": { - "name": "Leirintäalue" + "name": "Leirintäalue", + "terms": "leiripaikka, karavaanialue, caravan park, matkailuvaunualue, telttailualue, camping " }, "tourism/caravan_site": { "name": "Asuntoautopysäköinti" @@ -4893,7 +5226,8 @@ "terms": "kesämökki, lomamökki, mökki, asunto, talo, kesä, vapaa-ajan, vapaa-aika" }, "tourism/gallery": { - "name": "Taidegalleria" + "name": "Taidegalleria", + "terms": "taidenäyttely, taide, näyttely, näyttelytila, galleria, galleriatila, kokoelma, maalaus, valokuva" }, "tourism/guest_house": { "name": "Majatalo" @@ -4908,13 +5242,15 @@ "name": "Infopiste" }, "tourism/information/board": { - "name": "Opastaulu" + "name": "Opastaulu", + "terms": "opastaulu, opaskartta, opaste, kartta, ilmoitustaulu, kiinteistötaulu, nimikilpi, aikataulu, bussi, juna, historia, luonto, kuulutukset" }, "tourism/information/guidepost": { "name": "Tienviitta" }, "tourism/information/map": { - "name": "Kartta" + "name": "Kartta", + "terms": "opaskartta, maastokartta, topografia, katukartta, karttataulu, pohjapiirros, opastaulu, reittiohje, havainnekuva, kuva, grafiikka, taulu" }, "tourism/information/office": { "name": "Matkailuneuvonta", @@ -4936,8 +5272,13 @@ "tourism/viewpoint": { "name": "Näköalapaikka" }, + "tourism/wilderness_hut": { + "name": "Autiotupa", + "terms": "tupa, kota, mökki, maja, kämppä, kammi, pirtti, autiotupa, vuokra, vuokraus, varaus, kota, erä, erämaa, eräkämppä, yö, yöpaikka, yöpymispaikka, leiripaikka, retki, vaellus, luonto, metsä" + }, "tourism/zoo": { - "name": "Eläintarha" + "name": "Eläintarha", + "terms": "eläinpuisto, kotieläinpiha" }, "traffic_calming": { "name": "Hidaste", @@ -4994,17 +5335,9 @@ "type/restriction/no_u_turn": { "name": "Ei saa tehdä U-käännöstä" }, - "type/restriction/only_left_turn": { - "name": "Saa kääntyä vain vasemmalle" - }, - "type/restriction/only_right_turn": { - "name": "Saa kääntyä vain oikealle" - }, - "type/restriction/only_straight_on": { - "name": "Ei saa kääntyä lainkaan" - }, "type/route": { - "name": "Reitti" + "name": "Reitti", + "terms": "matkareitti, rengasreitti, lenkki, kulkuohjeet, ohjaus, reititys, navigointi, kurssi, traili" }, "type/route/bicycle": { "name": "Pyöräilyreitti" @@ -5023,7 +5356,8 @@ "name": "Kävelyreitti" }, "type/route/hiking": { - "name": "Vaellusreitti" + "name": "Vaellusreitti", + "terms": "vaellus, patikointi, patikka, maasto, retkeily, samoilu, reitti" }, "type/route/horse": { "name": "Ratsastusreitti" @@ -5035,7 +5369,8 @@ "name": "Putkilinja" }, "type/route/piste": { - "name": "Hiihtoreitti" + "name": "Hiihtoreitti", + "terms": "latu, latureitti, talviurheilu, reitistö, hiihtolenkki, hiihtäminen" }, "type/route/power": { "name": "Voimalinja" @@ -5130,8 +5465,7 @@ "DigitalGlobe-Premium-vintage": { "attribution": { "text": "Käyttöehdot ja palaute" - }, - "description": "Kuva-alueet ja kuvauspäivämäärät. Aineisto on käytettävissä suurennostasolla 14 ja lähempänä." + } }, "DigitalGlobe-Standard": { "attribution": { @@ -5143,8 +5477,7 @@ "DigitalGlobe-Standard-vintage": { "attribution": { "text": "Käyttöehdot ja palaute" - }, - "description": "Kuvien rajat ja kuvauspäivät. Merkit näkyvät zoomaus tasolla 14 tai isommalla. " + } }, "EsriWorldImagery": { "attribution": { @@ -5260,7 +5593,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Taustakartta perustuu Itävallan hallinnon julkaisemaan aineistoon.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -5318,6 +5650,9 @@ } }, "tf-cycle": { + "attribution": { + "text": "Kartat © Thunderforest, Aineisto © OpenStreetMapin tekijät" + }, "name": "Thunderforest OpenCycleMap" }, "tf-landscape": { @@ -5326,6 +5661,50 @@ }, "name": "Thunderforest-maisema" } + }, + "community": { + "it-twitter": { + "description": "Seuraa Twitter-tiliämme osoitteessa {url}" + }, + "se-facebook": { + "description": "OpenStreetMap Ruotsi Facebookissa" + }, + "PHXGeo-twitter": { + "description": "Seuraa Twitter-tiliämme osoitteessa {url}" + }, + "OSM-AR-twitter": { + "description": "Seuraa Twitter-tiliämme osoitteessa {url}" + }, + "OSM-br-twitter": { + "description": "Seuraa Twitter-tiliämme osoitteessa {url}" + }, + "OSM-CL-twitter": { + "description": "Seuraa Twitter-tiliämme osoitteessa {url}" + }, + "OSM-CO-twitter": { + "description": "Seuraa Twitter-tiliämme osoitteessa {url}" + }, + "OSM-PE-twitter": { + "description": "Seuraa Twitter-tiliämme osoitteessa {url}" + }, + "OSM-Facebook": { + "name": "OpenStreetMap Facebookissa", + "description": "Pysy ajan tasalla tuoreimmista OpenStreetMap-uutisista tykkäämällä meistä Facebookissa." + }, + "OSM-help": { + "description": "Hanki vastauksia kysymyksiisi OpenStreetMapin yhteisön ylläpitämällä vastausfoorumilla." + }, + "OSM-Reddit": { + "name": "OpenStreetMap Redditissä", + "description": "/r/openstreetmap/ on näppärä tapa oppia lisää OpenStreetMapista. Kysy mitä tahansa!" + }, + "OSM-Twitter": { + "description": "Seuraa Twitter-tiliämme osoitteessa {url}" + }, + "OSMF": { + "name": "OpenStreetMap-säätiö", + "description": "OSMF on Iso-Britanniasta toimiva voittoa tavoittelematon, OpenStreetMapin toimintaa edistävä säätiö" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/fr.json b/vendor/assets/iD/iD/locales/fr.json index a212982ac..7a7d09be5 100644 --- a/vendor/assets/iD/iD/locales/fr.json +++ b/vendor/assets/iD/iD/locales/fr.json @@ -1,5 +1,10 @@ { "fr": { + "icons": { + "information": "info", + "remove": "supprimer", + "undo": "annuler" + }, "modes": { "add_area": { "title": "Polygone", @@ -9,7 +14,7 @@ "add_line": { "title": "Ligne", "description": "Ajouter des routes, des rues, des chemins, des canaux ou d'autres lignes à la carte.", - "tail": "Cliquez sur la carte pour ajouter une nouvelle ligne telle qu'une route ou un chemin." + "tail": "Cliquez sur la carte pour ajouter une nouvelle ligne telle qu'une route ou un itinéraire." }, "add_point": { "title": "Point", @@ -145,7 +150,9 @@ "vertex": "connexion d'un chemin à un autre chemin.", "line": "connexion d'un chemin à une ligne.", "area": "connexion d'un chemin à un polygone." - } + }, + "relation": "Ces éléments ne peuvent être connectés car ils ont des rôles de relations conflictuels.", + "restriction": "Ces éléments ne peuvent être connectés car cela endommagerait une relation \"{relation}\"." }, "disconnect": { "title": "Séparer", @@ -163,7 +170,8 @@ "annotation": "fusion de {n} éléments.", "not_eligible": "Ces éléments ne peuvent pas être fusionnés.", "not_adjacent": "Ces éléments ne peuvent être fusionnés car leurs extrémités ne sont pas connectés.", - "restriction": "Ces éléments ne peuvent être fusionnés car au moins l'un d'entre eux est membre de la relation \"{relation}\".", + "restriction": "Ces éléments ne peuvent être fusionnés car cela endommagerait une relation \"{relation}\".", + "relation": "Ces éléments ne peuvent être fusionnés car leurs rôles sont incompatibles dans une relation.", "incomplete_relation": "Ces éléments ne peuvent pas être fusionnés parce qu'au moins l'un d'entre eux n'a pas été complètement téléchargé.", "conflicting_tags": "Ces éléments ne peuvent être fusionnés car certains de leurs tags ont des valeurs conflictuelles." }, @@ -402,6 +410,7 @@ "key": "H", "title": "Historique", "selected": "{n} dans la sélection", + "no_history": "Pas d'historique (Nouvel élément)", "version": "Version", "last_edit": "Dernière édition", "edited_by": "Edité par", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "OSM modifié !", "just_edited": "Vous avez participé à OpenStreetMap !", - "view_on_osm": "Visualiser sur OSM", - "facebook": "Partager sur Facebook", - "twitter": "Partager sur Twitter", - "google": "Partager sur Google+", - "help_html": "Vos changements devraient apparaître dans le calque \"Standard\" d'ici quelques minutes. Pour d'autres calques et certains éléments, cela peut prendre plus de temps.", + "thank_you": "Merci d'avoir amélioré la carte.", + "thank_you_location": "Merci d'avoir amélioré la carte autour de {where}.", + "help_html": "Vos changements devraient apparaître sur OpenStreetMap dans quelques instants. La mise à jour des cartes sur d'autres supports devrait prendre davantage de temps.", "help_link_text": "Détails", - "help_link_url": "https://wiki.openstreetmap.org/wiki/FR:FAQ#Je_viens_juste_de_faire_quelques_changements_sur_la_carte._Comment_puis-je_les_voir_.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/FR:FAQ#Je_viens_juste_de_faire_quelques_changements_sur_la_carte._Comment_puis-je_les_voir_.3F", + "view_on_osm": "Voir les changements sur OSM", + "changeset_id": "Votre numéro d'ensemble de modification : {changeset_id}", + "like_osm": "Vous aimez OpenStreetMap ? Retrouvez d'autres contributeurs :", + "more": "Plus", + "events": "Événements", + "languages": "Langues: {languages}", + "missing": "Quelque chose manque-t-il dans cette liste?", + "tell_us": "Dîtes-nous en plus !" }, "confirm": { "okay": "OK", @@ -760,7 +774,7 @@ "backups_h": "Sauvegarde automatique", "backups": "Si vous ne pouvez pas terminer vos modifications tout de suite, par exemple si votre ordinateur s’éteint ou si vous fermez votre navigateur, votre travail est enregistré. Vous pouvez revenir plus tard (avec le même navigateur, sur la même ordinateur) et iD vous proposera de reprendre là où vous vous étiez arrêté.", "keyboard_h": "Raccourcis clavier", - "keyboard": "Vous pouvez voir une liste de raccourcis clavier en pressant la touche `?`." + "keyboard": "Vous pouvez voir une liste de raccourcis clavier en appuyant sur la touche `?`." }, "feature_editor": { "title": "Éditeur d'élément", @@ -779,46 +793,147 @@ }, "points": { "title": "Points", + "intro": "Les *points* peuvent être utilisés pour représenter des éléments comme des magasins, restaurants ou monuments. Ils indiquent une position précise et décrivent ce qu'il y a à cet endroit. ", "add_point_h": "Ajouter des Points", + "add_point": "Pour ajouter un point, cliquez sur le bouton **Point** {point} de la barre d'outils au-dessus de la carte, ou pressez la touche `1`. Cela transformera le curseur de la souris en une croix.", + "add_point_finish": "Pour placer un nouveau point sur la carte, placer le curseur de la souris où le point doit aller, puis effectuer un {leftclick} clic gauche ou un appui sur la barre d'Espace.", "move_point_h": "Déplacer des Points", - "delete_point_h": "Supprimer des Points " + "move_point": "Pour déplacer un point, placez le curseur sur ce point, puis pressez et maintenez enfoncé le bouton gauche de la souris {leftclick} jusqu'au nouveau lieu du point.", + "delete_point_h": "Supprimer des Points ", + "delete_point": "Vous pouvez supprimer des éléments qui n'existent pas dans le monde réel. Supprimer un élément d'OpenStreetMap l'efface de la carte que tout le monde utilise, aussi vous devez être absolument sûr que cet élément n'existe pas sur le terrain avant de le supprimer.", + "delete_point_command": "Pour supprimer un point, faites un clic droit {rightclick} sur ce point pour le sélectionner et voir le menu d'édition, puis utilisez la commande **Supprimer** {delete}." }, "lines": { "title": "Lignes", + "intro": "Les *lignes* sont utilisées pour représenter des éléments comme des routes, des voies ferrées ou des rivières. Les lignes doivent être dessinées au centre de l'élément qu'elles représentent.", "add_line_h": "Ajouter des Lignes", + "add_line": "Pour ajouter une ligne, cliquez sur le bouton **Ligne** {line} de la barre d'outils au-dessus de la carte, ou pressez la touche `2`. Cela transformera le curseur de la souris en une croix.", + "add_line_draw": "Puis, positionnez le curseur à l'endroit où doit commencer la ligne et faites un clic gauche {leftclick} ou pressez la barre d'espace `Space` pour placer des nœuds le long de la ligne. Continuez à placer des nœuds en cliquant ou en pressant la barre d'espace `Space`. Lorsque vous tracez la ligne, vous pouvez zoomer ou déplacer la carte afin d'ajouter davantage de détails.", + "add_line_finish": "Pour terminer une ligne, pressez la touche `{return}` ou cliquez une seconde fois sur le dernier nœud.", "modify_line_h": "Modifier des Lignes", + "modify_line_dragnode": "Souvent, vous verrez que les lignes ne sont pas formées correctement, par exemple une route qui ne correspond pas à l'imagerie utilisée en fond. Pour ajuster la forme d'une ligne, faites d'abord un clic gauche {leftclick} pour la sélectionner. Tous les nœuds de la ligne apparaîtront comme des petits cercles. Vous pourrez alors les déplacer.", + "modify_line_addnode": "Vous pouvez aussi créer de nouveaux nœuds le long d'une ligne en faisant un double-clic {leftclick}**x2** sur cette ligne ou en déplaçant les petits triangles situés sur la ligne entre deux nœuds existants.", + "connect_line_h": "Connecter des lignes", + "connect_line": "Il est important que les routes soient connectées correctement pour la carte, et essentiel pour la navigation.", + "connect_line_display": "Les connexions entre plusieurs routes sont matérialisées avec des cercles gris. Les points d'une ligne qui ne sont connectés à rien apparaissent comme des cercles blancs, plus grands.", + "connect_line_drag": "Pour connecter une ligne à un autre élément, faites glisser l'un des nœuds de la ligne vers cet élément jusqu'à ce qu'ils s'accrochent ensemble. Astuce: vous pouvez maintenir la touche `{alt}` enfoncée pour empêcher les nœuds de se connecter à d'autres éléments.", + "connect_line_tag": "Si le croisement a un feu de signalisation ou un passage pour piétons, vous pouvez l'ajouter en sélectionnant le nœud de connexion et en utilisant l'éditeur d'élément pour choisir le type d'élément correct.", + "disconnect_line_h": "Séparer des lignes", + "disconnect_line_command": "Pour déconnecter une route d'un autre élément, faites un clic droit {rightclick} sur le nœud de connexion et sélectionnez la commande **Déconnecter** {disconnect} dans le menu d'édition.", "move_line_h": "Déplacer des Lignes", - "delete_line_h": "Supprimer des lignes" + "move_line_command": "Pour déplacer une ligne entière, faites un clic droit {rightclick} sur cette ligne et sélectionnez la commande **Déplacer** {move} dans le menu d'édition. Puis déplacez la souris, et faites un clic gauche {leftclick} à l'endroit où vous souhaitez laisser la ligne..", + "move_line_connected": "Les lignes qui sont connectées à d'autres éléments resteront connectées lorsque vous la déplacerez à un autre endroit. iD peut vous empêcher de déplacer une ligne à travers une autre ligne connectées.", + "delete_line_h": "Supprimer des lignes", + "delete_line": "Si une ligne est entièrement erronée, comme une route qui n'existe pas, vous pouvez l'effacer. Faites attention en supprimant des éléments car l'imagerie que vous utilisez n'est pas forcément à jour, et une route nouvellement construite peut être manquante sur des images trop anciennes.", + "delete_line_command": "Pour supprimer une ligne, faites un clic droit {rightclick} sur cette ligne pour la sélectionner et voir le menu d'édition, puis utilisez la commande **Supprimer** {delete}." }, "areas": { + "title": "Polygones", + "intro": "Les *polygones* sont utilisés pour montrer les délimitations d'éléments comme des lacs, des bâtiments et des zones résidentielles. Les polygones doivent être dessinés le long du bord des éléments qu'ils représentent, par exemple autour du pied d'un bâtiment.", + "point_or_area_h": "Des points ou un polygone ?", + "point_or_area": "De nombreux éléments peuvent être représentés par des points ou des polygones. Vous devriez cartographier les bâtiments et les contours de propriétés avec des polygones lorsque c'est possible. Placez des points à l'intérieur d'un bâtiment pour représenter des entreprises, des équipements et d'autres éléments se trouvant à l'intérieur.", "add_area_h": "Ajouter des polygones", - "square_area_h": "Donner une forme orthogonale.", - "modify_area_h": "Modifier des polyognes", - "delete_area_h": "Supprimer des polygones" + "add_area_command": "Pour ajouter un polygone, cliquez sur le bouton **Polygone** {area} de la barre d'outils au-dessus de la carte, ou pressez la touche `3`. Cela transformera le curseur de la souris en une croix.", + "add_area_draw": "Puis, positionnez le curseur à l'endroit de l'un des coins de l'élément à tracer et faites un clic gauche {leftclick} ou pressez la barre d'espace `Space` pour placer des nœuds sur les bords extérieurs du polygone. Continuez à placer des nœuds en cliquant ou en pressant la barre d'espace `Space`. Lorsque vous tracez le polygone, vous pouvez zoomer ou déplacer la carte afin d'ajouter davantage de détails.", + "add_area_finish": "Pour terminer un polygone, pressez la touche `{return}` ou cliquez une seconde fois sur le premier ou le dernier nœud.", + "square_area_h": "Donner une forme orthogonale", + "square_area_command": "De nombreux éléments comme les bâtiments ont les coins carrés. Pour rendre carrés les coins d'un polygone, faites un clic droit {rightclick} sur un bord du polygone et sélectionnez la commande **Carré** {orthogonalize} du menu d'édition.", + "modify_area_h": "Modifier des polygones", + "modify_area_dragnode": "Souvent, vous verrez que les polygones ne sont pas formés correctement, par exemple un bâtiment qui ne correspond pas à l'imagerie utilisée en fond. Pour ajuster la forme d'un polygone, faites d'abord un clic gauche {leftclick} pour le sélectionner. Tous les nœuds du polygone apparaîtront comme des petits cercles. Vous pourrez alors les déplacer.", + "modify_area_addnode": "Vous pouvez aussi créer de nouveaux nœuds le long d'un polygone soit en double-cliquant {leftclick}**x2** sur le bord de ce polygone, soit en déplaçant les petits triangles situés entre deux nœuds existants.", + "delete_area_h": "Supprimer des polygones", + "delete_area": "Si un polygone est entièrement erroné, comme un bâtiment qui n'existe pas, vous pouvez l'effacer. Faites attention en supprimant des éléments car l'imagerie que vous utilisez n'est pas forcément à jour, et un bâtiment nouvellement construit peut être manquant sur des images trop anciennes.", + "delete_area_command": "Pour supprimer un polygone, faites un clic droit {rightclick} sur ce polygone pour le sélectionner et voir le menu d'édition, puis utilisez la commande **Supprimer** {delete}." }, "relations": { "title": "Relations", + "intro": "Une *relation* est un élément spécial dans OpenStreetMap qui regroupe ensemble d'autres éléments. Les éléments qui appartiennent à une relation sont appelés *membres*, et chacun de ces membres peut avoir un *rôle* dans la relation.", "edit_relation_h": "Éditer des Relations", + "edit_relation": "Au bas de l'éditeur d'éléments, vous pouvez développer la section \"Toutes les relations\" pour voir si l'élément sélectionné est membre d'une ou plusieurs relations. Vous pouvez alors cliquer sur la relation pour la sélectionner et l'éditer.", + "edit_relation_add": "Pour ajouter un élément à une relation, sélectionnez cet élément, puis cliquez sur le bouton d'ajout {plus} dans la section \"Toutes les relations\" de l'éditeur d'éléments. Vous pouvez choisir la relation dans une liste contenant les relations présentes aux environs, ou bien en créer une nouvelle avec l'option \"Nouvelle relation...\".", + "edit_relation_delete": "Vous pouvez également cliquer sur le bouton **Supprimer** {delete} pour supprimer un élément d'une relation. Si vous supprimez tous les éléments d'une relation, celle-ci sera automatiquement supprimée.", + "maintain_relation_h": "Maintenir des Relations", + "maintain_relation": "La plupart du temps, iD maintient automatiquement les relations lorsque vous éditez.\nVous devez toutefois faire attention quand vous remplacez des éléments qui sont membres de relations. Par exemple, si vous supprimez la section d'une route et que vous en créez une nouvelle pour la remplacer, vous devez impérativement ajouter la nouvelle section aux mêmes relations que l'ancienne (itinéraires, interdictions de tourner, etc...).", "relation_types_h": "Types de Relation", + "multipolygon_h": "Multipolygones", + "multipolygon": "Une relation *multipolygone* est un groupe d'un ou plusieurs éléments *extérieurs* et d'un ou plusieurs éléments intérieurs. Les éléments extérieurs définissent les bords extérieurs du multipolygone, et les éléments intérieurs définissent les sous-polygones ou les trous à l'intérieur du multipolygone.", + "multipolygon_create": "Pour créer un multipolygone, par exemple un bâtiment avec un trou au milieu, dessinez le bord externe comme une aire et le bord intérieur comme une ligne ou un autre type d'aire. Ensuite, `{shift}`+{leftclick} cliquez-gauche pour sélectionner les deux éléments, {rightclick} cliquez-droit pour ouvrir le menu d'édition et sélectionnez la commande {merge} **Fusionner**.", + "multipolygon_merge": "La fusion de plusieurs lignes ou polygones créera une nouvelle relation multipolygone avec comme membres tous les polygones sélectionnés. iD choisira automatiquement les rôles intérieur et extérieur, en fonction des éléments contenus à l'intérieur d'autres éléments.", "turn_restriction_h": "Interdictions de tourner", - "route_h": "Chemins", - "boundary_h": "Frontières" + "turn_restriction": "Une relation *restriction de tourner* est un groupe formé de plusieurs segments de routes à une intersection. Elle comporte une route *depuis*, un nœud ou des routes *via*, et une route *vers*.", + "turn_restriction_field": "Pour éditer les restrictions de tourner, sélectionnez un nœud où se croisent au moins deux routes. L'éditeur d'élément affichera alors un champ spécial \"Interdictions de tourner\" contenant un modèle de l'intersection.", + "turn_restriction_editing": "Dans le champ \"restrictions de tourner\", cliquez pour sélectionner une route \"depuis\", et voyez s'il est autorisé ou non de tourner sur une ou plusieurs routes \"vers\". Vous pouvez cliquer sur l'icône de direction pour basculer la position entre autorisé et interdit. iD créera automatiquement les relations et mettra à jour les rôles selon votre saisie.", + "route_h": "Itinéraires", + "route": "Une relation *itinéraire* est un groupe d'une ou plusieurs lignes formant ensemble un réseau, comme un itinéraire de bus, un itinéraire ferroviaire, ou un itinéraire routier.", + "route_add": "Pour ajouter un élément à une relation itinéraire, sélectionnez cet élément, puis cliquez sur le bouton d'ajout {plus} dans la section \"Toutes les relations\" de l'éditeur d'éléments. Vous pouvez choisir la relation parmi celles présentes aux environs, ou bien en créer une nouvelle.", + "boundary_h": "Frontières", + "boundary": "Une relation *frontière* est un groupe d'une ou plusieurs lignes formant ensemble une frontière administrative.", + "boundary_add": "Pour ajouter un élément à une relation frontière, sélectionnez cet élément, puis cliquez sur le bouton d'ajout {plus} dans la section \"Toutes les relations\" de l'éditeur d'éléments. Vous pouvez choisir la relation parmi celles présentes aux environs, ou bien en créer une nouvelle." }, "imagery": { "title": "Fond de carte", + "intro": "Le fond de carte qui apparaît sous les données est un élément important pour cartographier. Il peut s'agir de photos aériennes émanant de satellites, d'avions, et de drones, ou de cartes historiques scannées, ou encore de toute autre source de données libre.", "sources_h": "Sources des images", - "offsets_h": "Ajustement du fond de carte" + "choosing": "Pour voir quelles sources sont disponibles pour éditer, cliquez sur le bouton **Paramètres du fond de carte** {layers} sur le côté de la carte.", + "sources": "Par défaut, une image satellite [Bing Maps](https://www.bing.com/maps/) est affichée en arrière-plan. Selon le lieu où vous éditez, d'autres images peuvent être disponibles. Certaines peuvent être plus récentes ou avec une meilleure résolution, si bien qu'il est utile de vérifier quelle est la meilleure image à utiliser pour cartographier.", + "offsets_h": "Ajustement du fond de carte", + "offset": "L'imagerie est parfois légèrement décalée par rapport aux données précises de la carte. Si vous constatez que de nombreuses routes ou de nombreux bâtiments sont décalés par rapport au fond de carte, c'est peut-être que l'imagerie n'est pas correctement alignée. Plutôt que de déplacer à tort les éléments de la carte, vous pouvez ajuster le fond de carte en utilisant la section \"Ajuster le décalage du fond de carte\" en bas du panneau Paramètres du fond de carte.", + "offset_change": "Cliquez sur les petits triangles pour ajuster finement le décalage de l'imagerie, ou maintenez enfoncé le bouton gauche de la souris et faites glisser l'image jusqu'à ce qu'elle soit correctement alignée." }, "streetlevel": { "title": "Photos de la rue", - "using_h": "Utiliser des photos de la rue." + "intro": "Les photos de la rue sont utiles pour cartographier la signalisation routière, les commerces, et d'autres détails que l'on ne peut pas voir sur l'imagerie aérienne. L'éditeur iD prend en charge les photos de la rue de [Mapillary](https://www.mapillary.com) et [OpenStreetCam](https://www.openstreetcam.org).", + "using_h": "Utiliser des photos de la rue.", + "using": "Pour utiliser les photos de la rue, cliquez sur le bouton **Données cartographiques** {data} sur le bord de la carte. Cela permettra d'activer ou de désactiver les surcouches photographiques disponibles.", + "photos": "Lorsque cela est activé, la couche photo montre une ligne entre les séquences de photo. Aux niveaux de zoom élevés, un cercle marque l'emplacement de chaque photo et aux zooms encore plus élevés, un cône indique la direction de l'appareil photo lorsque la photo a été prise.", + "viewer": "Lorsque vous cliquez sur l'un des emplacements de la photo, une visionneuse de photo apparaît dans le bord bas de la carte. La visionneuse contient des contrôles pour avancer et reculer dans la séquence de photos. Elle montre aussi le nom d'utilisateur de la personne qui a pris l'image, la date de capture et un lien pour voir l'image sur le site d'origine." }, "gps": { "title": "Traces GPS", + "intro": "Les traces GPS collectées sont une source précieuse de données pour OpenStreetMap. Cet éditeur accepte les fichiers de formats *.gpx*, *.geojson*, et *.kml*. Vous pouvez collecter des traces GPS à partir d'un smartphone, d'une montre connectée, ou de tout appareil muni d'une puce GPS.", + "survey": "Pour plus d'information sur la conduite d'étude de terrain au GPS, vous pouvez lire [Cartographier avec un smartphone, un GPS ou sur papier](http://learnosm.org/fr/mobile-mapping/).", "using_h": "Utilisation des traces GPS", "using": "Pour utiliser une trace GPS, faites la glisser dans l'éditeur. Si elle est reconnue, elle apparaîtra en violet sur la carte. Cliquez sur {data} **Données Carte** pour montrer, cacher ou zoomer sur la trace GPS.", "tracing": "La trace GPS n'est pas envoyée à OpenStreetMap. Le meilleur moyen de l'utiliser est de dessiner sur la carte en s'en servant de modèle.", "upload": "Vous pouvez aussi [uploader vos données GPS sur OpenStreetMap](https://www.openstreetmap.org/trace/create) pour que d'autres utilisateurs puissent les utiliser." + }, + "field": { + "restrictions": { + "title": "Aide des restrictions de tourner", + "about": { + "title": "À propos", + "about": "Ce champ vous permet d'inspecter et de modifier les restrictions de tourner. Il affiche un modèle de l'intersection sélectionnée avec les routes connectées proches.", + "from_via_to": "Une restriction de tourner contient toujours: un **chemin DEPUIS**, un **chemin VERS**, et soit un **nœud VIA**, soit un ou plusieurs **chemins VIA**.", + "maxdist": "Le curseur \"{distField}\" contrôle la distance jusqu'à laquelle chercher des routes connectées supplémentaires.", + "maxvia": "Le curseur \"{viaField}\" ajuste le nombre de chemins via à inclure dans la recherche. (Astuce: plus c'est simple, mieux c'est)" + }, + "inspecting": { + "title": "Inspecter", + "about": "Survolez avec le curseur un segment **DEPUIS** pour voir s'il est soumis à des restrictions de tourner. Toutes les destinations possibles **VERS** seront ombrées et montreront si une restriction existe.", + "from_shadow": "{fromShadow} **DEPUIS le segment**", + "allow_shadow": "{allowShadow} **VERS autorisé**", + "restrict_shadow": "{restrictShadow} **VERS interdit**", + "only_shadow": "{onlyShadow} **VERS uniquement**", + "restricted": "\"Interdit\" signifie qu'il y a une restriction de direction, par exemple \"Interdit de tourner à gauche\".", + "only": "\"Uniquement\" signifie qu'un véhicule empruntant ce chemin n'a pas d'autre choix de direction, par exemple \"Direction obligatoire\"." + }, + "modifying": { + "title": "Modifier", + "about": "Pour modifier les restrictions de tourner, commencez par cliquer sur l'un des segments **DEPUIS** pour le sélectionner. Celui-ci va clignoter, et toutes les directions possibles **VERS** vont apparaître avec un symbole.", + "indicators": "Puis cliquez sur un symbole de direction pour le basculer entre \"autorisé\", \"interdit\", et \"uniquement\".", + "allow_turn": "{allowTurn} **VERS autorisé**", + "restrict_turn": "{restrictTurn} **VERS interdit**", + "only_turn": "{onlyTurn} **VERS uniquement**" + }, + "tips": { + "title": "Astuces", + "simple": "**Privilégiez les restrictions simples plutôt que les complexes.**", + "simple_example": "Par exemple, évitez de créer une restriction par un chemin via si un simple nœud via est suffisant.", + "indirect": "**Certaines restrictions affichent le texte \"(indirect)\" et sont dessinées en transparence.**", + "indirect_example": "Ces restrictions existent à cause d'une autre restriction proche. Par exemple, une restriction \"Obligation d'aller tout droit\" créera indirectement des restrictions \"Interdiction de tourner\" pour tous les autres chemins de l'intersection.", + "indirect_noedit": "Vous ne pouvez pas éditer les restrictions indirectes. À la place, éditez la restriction directe la plus proche." + } + } } }, "intro": { @@ -997,6 +1112,7 @@ }, "areas": { "title": "Polygones", + "add_playground": "Les *Polygones* sont utilisés pour montrer les limites d'éléments comme les lacs, les bâtiments, et les zones résidentielles. {br}Ils peuvent aussi être utilisés pour cartographier finement des éléments représentés normalement par des points. **Cliquez sur le bouton Polygone {button} pour ajouter un nouveau polygone.**", "start_playground": "Ajoutons une aire de jeu pour enfant sur la carte en dessinant un polygone. Les polygones sont dessinés en plaçant des *nœuds* pour définir les bords de l'élément. **Cliquez ou appuyez sur la barre d'espace pour placer le premier nœud sur l'un des angles de l'aire de jeu.**", "continue_playground": "Continuez à dessiner le polygone en plaçant d'autres nœuds le long de l'aire de jeu. Vous pouvez connecter le polygone au chemin piéton existant. {br} Astuce : Vous pouvez maintenir la touche {Alt} pour éviter aux nœuds de se connecter à d'autres éléments. ** continuez à dessiner le polygone de l'aire de jeux **", "finish_playground": "Terminez le polygone avec la touche Entrée ou en cliquant une nouvelle fois sur son premier ou son dernier nœud. **Terminez le polygone d'aire de jeu.**", @@ -1063,8 +1179,8 @@ }, "startediting": { "title": "Sortir du tutoriel et contribuer", - "help": "Vous êtes maintenant prêt pour contribuer à OpenStreetMap !{br}Vous pouvez recommencer ce tutorial à tout moment ou lire plus de documentation en cliquant sur le {button} bouton Aide ou en pressant la touche '{key}'.", - "shortcuts": "Vous pouvez voir une liste des commandes avec leur raccourci clavier en pressant la touche '{key}'.", + "help": "Vous êtes maintenant prêt pour contribuer à OpenStreetMap !{br}Vous pouvez recommencer ce tutorial à tout moment ou lire plus de documentation en cliquant sur le bouton Aide {button} ou en appuyant sur la touche '{key}'.", + "shortcuts": "Vous pouvez voir une liste des commandes avec leurs raccourcis claviers en appuyant sur la touche '{key}'.", "save": "N'oubliez pas de sauver régulièrement vos modifications !", "start": "Commencer à cartographier !" } @@ -1672,6 +1788,9 @@ "display": { "label": "Affichage" }, + "distance": { + "label": "Distance totale" + }, "dock": { "label": "Type" }, @@ -1712,6 +1831,9 @@ "except": { "label": "Exceptions" }, + "faces": { + "label": "Faces" + }, "fax": { "label": "Fax", "placeholder": "+33 1 23 45 67 89" @@ -1823,6 +1945,39 @@ "label": "Nombre d'arceaux", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Dressage", + "options": { + "equestrian": "Oui", + "undefined": "Non" + } + }, + "horse_riding": { + "label": "Équitation", + "options": { + "horse_riding": "Oui", + "undefined": "Non" + } + }, + "horse_scale": { + "label": "Difficulté à cheval", + "options": { + "common": "Facile : pas de problème ou de difficulté. (par défaut)", + "critical": "Limite : passable uniquement pour des cavaliers et des chevaux expérimentés. Obstacles majeurs. Les ponts devraient être examinés avec attention.", + "dangerous": "Dangereux : passable uniquement pour des cavaliers et des chevaux très expérimentés et seulement par beau temps. Descendre du cheval.", + "demanding": "Utiliser avec prudence : voie inégale, passages difficiles occasionnels.", + "difficult": "Difficile : voie étroite et exposée. Peut contenir des obstacles par dessus lesquels passer et des passages étroits.", + "impossible": "Impossible : Vois ou pont impossible à franchir pour les chevaux. Trop étroit, support insuffisant, obstacles comme des échelles. Danger de mort." + }, + "placeholder": "Difficile, Dangereux..." + }, + "horse_stables": { + "label": "Étable pour cavaliers", + "options": { + "stables": "Oui", + "undefined": "Non" + } + }, "iata": { "label": "Code AITA (*IATA*)" }, @@ -1842,6 +1997,9 @@ "indoor": { "label": "Intérieur" }, + "industrial": { + "label": "Type" + }, "information": { "label": "Type" }, @@ -1962,6 +2120,10 @@ "label": "Vitesse maximale autorisée", "placeholder": "30, 50, 70, 90, etc." }, + "maxspeed/advisory": { + "label": "Vitesse conseillée", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Durée maximale" }, @@ -2115,7 +2277,7 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Téléphone ", + "label": "Téléphone", "placeholder": "+33 1 23 45 67 89" }, "piste/difficulty": { @@ -2550,6 +2712,17 @@ "label": "Type", "placeholder": "Défaut" }, + "usage_rail": { + "label": "Utilisation", + "options": { + "branch": "Secondaire", + "industrial": "Industrielle", + "main": "Principale", + "military": "Militaire", + "test": " Voie de test pour les nouveaux trains", + "tourism": "Touristique" + } + }, "vending": { "label": "Marchandise proposée" }, @@ -2646,6 +2819,10 @@ "name": "Panneau publicitaire", "terms": "publicité, 4x3, affiche, panneau d'affichage, billboard, advertising, advertisement" }, + "advertising/column": { + "name": "Colonne Morris", + "terms": "Colonne Morris, Publicité" + }, "aerialway": { "name": "Transport par câble aérien" }, @@ -2731,6 +2908,10 @@ "name": "Terminal d'aéroport", "terms": "Terminal" }, + "allotments/plot": { + "name": "Parcelle dans un jardin familial", + "terms": "" + }, "amenity": { "name": "Équipement" }, @@ -2959,6 +3140,10 @@ "name": "Marché", "terms": "Marché, Place de marché" }, + "amenity/monastery": { + "name": "Terrain de monastère", + "terms": "" + }, "amenity/motorcycle_parking": { "name": "Parking pour motocyclettes", "terms": "Parc à motos,Stationnement motos" @@ -3163,6 +3348,10 @@ "name": "Distributeur de cigarettes", "terms": "distributeur de cigarettes, distributeur à cigarettes, cigarettes, distributeur automatique de cigarettes, machine à cigarettes, vente automatique de cigarettes, vente de cigarettes, vente cigarettes, vending machine cigarettes" }, + "amenity/vending_machine/coffee": { + "name": "Distributeur de café", + "terms": "Distributeur de café" + }, "amenity/vending_machine/condoms": { "name": "Distributeur de préservatifs", "terms": "distributeur de préservatifs, distributeur à préservatifs, préservatifs, distributeur automatique de préservatifs, machine à préservatifs, vente automatique de préservatifs, vente de préservatifs, vente préservatifs, vending machine condoms, capotes, condoms" @@ -3171,6 +3360,14 @@ "name": "Distributeur de boissons", "terms": "distributeur de boissons, distributeur à boissons, boissons, distributeur automatique de boissons, machine à boissons, machine à café, vente automatique de boissons, vente de boissons, vente boissons, eau, café, thé, soda, jus de fruit, vending machine drinks, drinks" }, + "amenity/vending_machine/electronics": { + "name": "Distributeur de matériel éléctronique", + "terms": "" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Distributeur de pièces", + "terms": "" + }, "amenity/vending_machine/excrement_bags": { "name": "Distributeur de sacs pour excréments d'animaux", "terms": "distributeur de sacs pour excréments d'animaux, distributeur à sacs pour excréments d'animaux, sacs pour excréments d'animaux, sacs à excréments d'animaux, sacs à crottes, distributeur automatique de sacs pour excréments d'animaux, distributeur automatique de sacs à crottes, machine à sacs pour excréments d'animaux, machine à sacs à crottes, vente de sacs pour excréments d'animaux, vente de sacs à crottes, vente sacs pour excréments d'animaux, vente sacs à crottes, vending machine excrement bags, excrement bags" @@ -3179,6 +3376,18 @@ "name": "Distributeur de produits d'hygiène féminine", "terms": "machine distributrice de produits d'hygiène féminine, distributeur de serviettes hygiéniques, distributeur de tampons, distributeur de tampon, serviette, tampon, cup, distributeur de cup, menstruations" }, + "amenity/vending_machine/food": { + "name": "Distributeur d'aliments", + "terms": "Distributeur d'aliments" + }, + "amenity/vending_machine/fuel": { + "name": "Pompe à essence", + "terms": "Distributeur de carburant" + }, + "amenity/vending_machine/ice_cream": { + "name": "Distributeur de glace", + "terms": "Distributeur de glace" + }, "amenity/vending_machine/news_papers": { "name": "Distributeur de journaux" }, @@ -3198,6 +3407,10 @@ "name": "Distributeur de titres de transport", "terms": "distributeur de titres de transport, distributeur à titres de transport, titres de transport, tickets de transport, distributeur automatique de titres de transport, guichet automatique, machine à titres de transport, vente automatique de titres de transport, vente de titres de transport, vente titres de transport, tickets de train, tickets de bus, tickets de métro, tickets de RER, tickets train, tickets bus, tickets métro, tickets RER, billets de train, billets de bus, billets de métro, billets de RER, billets train, billets bus, billets métro, billets RER, titres de train, titres de bus, titres de métro, titres de RER, vending machine public transport tickets, public transport tickets, tickets, billets, train, bus, métro, RER" }, + "amenity/vending_machine/stamps": { + "name": "Distributeur de timbres", + "terms": "" + }, "amenity/vending_machine/sweets": { "name": "Distributeur de snacks", "terms": "distributeur de snacks, distributeur à snacks, distributeur automatique de snacks, machine à snacks, vente automatique de snacks, vente de snacks, vente snacks, snacks, sucreries, bonbons, chips, cookie, chocolat, cracker, chewing-gum, vending machine sweets, sweets" @@ -3270,6 +3483,10 @@ "name": "Tour de chute", "terms": "" }, + "attraction/maze": { + "name": "Labyrinthe", + "terms": "Labyrinthe" + }, "attraction/pirate_ship": { "name": "Bateau pirate", "terms": "" @@ -3451,6 +3668,10 @@ "name": "Bloc de garages", "terms": "garages, bloc de garages, boxes, box, hangar, parcages, parkings, voitures, parc de stationnement couvert" }, + "building/grandstand": { + "name": "tribune", + "terms": "" + }, "building/greenhouse": { "name": "Serre", "terms": "serre, culture sous serre, serriculture, serre-tunnel, tunnel serre, jardin d'hiver, orangerie, verrière, véranda, structure en verre, greenhouse, glasshouse" @@ -3525,7 +3746,7 @@ }, "building/stadium": { "name": "Bâtiment du stade", - "terms": "" + "terms": "Stade, Tribune." }, "building/static_caravan": { "name": "Mobil home fixe", @@ -3899,6 +4120,10 @@ "name": "Hospice", "terms": "Hôpital, clinique, établissement de santé, chr, chu, chic, ch" }, + "healthcare/laboratory": { + "name": "Laboratoire d'analyses médicale", + "terms": "Laboratoire de biologie médicale, Laboratoire d'analyses médicale" + }, "healthcare/midwife": { "name": "Sage-femme", "terms": "Sage-femme, maïeuticienne" @@ -4001,6 +4226,10 @@ "name": "Bretelle d'autoroute", "terms": "Bretelle d'autoroute" }, + "highway/passing_place": { + "name": "Aire de croisement", + "terms": "Aire de croisement" + }, "highway/path": { "name": "Chemin non carrossable", "terms": "Chemin" @@ -4360,6 +4589,10 @@ "name": "Salle de jeux", "terms": "" }, + "leisure/beach_resort": { + "name": "Station balnéaire", + "terms": "Station balnéaire, plage." + }, "leisure/bird_hide": { "name": "Observatoire ornithologique", "terms": "Observatoire d'oiseaux" @@ -4476,6 +4709,10 @@ "name": "Réserve naturelle", "terms": "Zone protégée" }, + "leisure/outdoor_seating": { + "name": "Aire des places en terrasse", + "terms": "" + }, "leisure/park": { "name": "Parc", "terms": "Parc" @@ -4554,7 +4791,7 @@ }, "leisure/resort": { "name": "Complexe touristique , Village de vacances", - "terms": "Complexe hôtelier, Complexe touristique, Village de vacances, Spa, détente, Relaxation, Station thermale." + "terms": "Complexe hôtelier, Complexe touristique, Village de vacances, Spa, détente, Relaxation, Station thermale, Lieu de séjour, Hôtel." }, "leisure/running_track": { "name": "Piste de course (à pieds)", @@ -4604,6 +4841,10 @@ "name": "Entrée de mine", "terms": "Entrée de galerie de mine,Entrée de galerie" }, + "man_made/antenna": { + "name": "Antenne radioélectrique", + "terms": "Antenne radioélectrique" + }, "man_made/breakwater": { "name": "Brise-lames", "terms": "Brise-lames" @@ -4616,6 +4857,10 @@ "name": "Cheminée", "terms": "Cheminée" }, + "man_made/clearcut": { + "name": "Coupe rase forestière", + "terms": "" + }, "man_made/crane": { "name": "Grue", "terms": "Grue" @@ -4655,13 +4900,17 @@ "name": "Tour d'observation", "terms": "Tour d'observation, Mirador" }, + "man_made/observatory": { + "name": "Observatoire", + "terms": "Observatoire" + }, "man_made/petroleum_well": { "name": "Puits de pétrole", - "terms": "Puits de forage, derrick, chevalet de pompage, ..." + "terms": "Puits de forage, derrick, chevalet de pompage" }, "man_made/pier": { "name": "Jetée", - "terms": "Quai" + "terms": "Quai,arrêt" }, "man_made/pipeline": { "name": "Pipeline", @@ -4779,10 +5028,18 @@ "name": "Lande", "terms": "Bruyère" }, + "natural/mud": { + "name": "Boue", + "terms": "Boue" + }, "natural/peak": { "name": "Sommet", "terms": "Pic, Mont" }, + "natural/reef": { + "name": "Récif", + "terms": "barrière, barriere, corail, océan, haut fond, récif, recif, ocean, rocher, coralien" + }, "natural/ridge": { "name": "Ligne de crête", "terms": "Crête" @@ -4880,7 +5137,7 @@ }, "office/company": { "name": "Bureau d'entreprise", - "terms": "" + "terms": "Bureau d'entreprise, Entreprise" }, "office/coworking": { "name": "Espace de coworking", @@ -4903,7 +5160,7 @@ "terms": "Agence immobilière" }, "office/financial": { - "name": "Bureau d'entreprise financière  ", + "name": "Bureau d'entreprise financière", "terms": "Bureau financier,Établissement financier" }, "office/forestry": { @@ -5018,8 +5275,8 @@ "name": "Ferme isolée" }, "place/hamlet": { - "name": "Hameau (moins de 100 habitants)", - "terms": "Hameau" + "name": "Lieu-dit ou hameau", + "terms": "Hameau,lieu dit,lieu-dit" }, "place/island": { "name": "Île", @@ -5035,7 +5292,7 @@ }, "place/locality": { "name": "Lieu-dit sans habitation", - "terms": "Localité" + "terms": "lieu-dit" }, "place/neighbourhood": { "name": "Voisinage", @@ -5176,7 +5433,7 @@ "terms": "Transformateur" }, "public_transport/linear_platform": { - "name": "Quai", + "name": "Quai de transport en commun", "terms": "" }, "public_transport/linear_platform_aerialway": { @@ -5192,7 +5449,7 @@ "terms": "" }, "public_transport/linear_platform_light_rail": { - "name": "Station de tramway", + "name": "Station de métro léger", "terms": "" }, "public_transport/linear_platform_monorail": { @@ -5204,11 +5461,11 @@ "terms": "" }, "public_transport/linear_platform_train": { - "name": "Gare ferroviaire", + "name": "Quai de gare ferroviaire", "terms": "" }, "public_transport/linear_platform_tram": { - "name": "Station de tramway", + "name": "Quai pour tramway", "terms": "" }, "public_transport/linear_platform_trolleybus": { @@ -5216,7 +5473,7 @@ "terms": "" }, "public_transport/platform": { - "name": "Quai", + "name": "Quai de transport en commun", "terms": "" }, "public_transport/platform_aerialway": { @@ -5232,7 +5489,7 @@ "terms": "" }, "public_transport/platform_light_rail": { - "name": "Station de tramway", + "name": "Station de métro léger", "terms": "" }, "public_transport/platform_monorail": { @@ -5244,11 +5501,11 @@ "terms": "" }, "public_transport/platform_train": { - "name": "Gare ferroviaire", + "name": "Quai de gare ferroviaire", "terms": "" }, "public_transport/platform_tram": { - "name": "Station de tramway", + "name": "Quai pour tramway", "terms": "" }, "public_transport/platform_trolleybus": { @@ -5398,7 +5655,7 @@ "terms": "Voie ferrée étroite" }, "railway/platform": { - "name": "Gare ferroviaire" + "name": "Quai de gare ferroviaire" }, "railway/rail": { "name": "Voie ferrée", @@ -5815,6 +6072,10 @@ "name": "Animalerie", "terms": "Animalerie" }, + "shop/pet_grooming": { + "name": "Salon de toilettage", + "terms": "Salon de toilettage" + }, "shop/photo": { "name": "Tirage de photos", "terms": "Photographe, Tirage de photos" @@ -6034,6 +6295,10 @@ "name": "Parc d'attraction", "terms": "Parc à thème, parc d'attractions" }, + "tourism/trail_riding_station": { + "name": "Station équestre", + "terms": "" + }, "tourism/viewpoint": { "name": "Point de vue", "terms": "Point de vue, observatoire, mirador" @@ -6129,6 +6394,10 @@ "name": "Interdiction de bifurquer", "terms": "Interdiction de bifurquer" }, + "type/restriction/only_u_turn": { + "name": "Demi-tour obligatoire", + "terms": "Demi-tour obligatoire" + }, "type/route": { "name": "Itinéraire", "terms": "Route, rue, chemin, sentier" @@ -6290,7 +6559,7 @@ "attribution": { "text": "Termes & commentaires" }, - "description": "Limites et dates des images. Les textes sont visibles à partir du niveau de zoom 14", + "description": "Limites et dates des images. Les textes sont visibles à partir du niveau de zoom 13.", "name": "Images DigitalGlobe Premium Vintage" }, "DigitalGlobe-Standard": { @@ -6304,7 +6573,7 @@ "attribution": { "text": "Termes & commentaires" }, - "description": "Limites et dates des images. Les textes sont visibles à partir du niveau de zoom 14", + "description": "Limites et dates des images. Les textes sont visibles à partir du niveau de zoom 13.", "name": "Images DigitalGlobe Standard Vintage" }, "EsriWorldImagery": { @@ -6319,7 +6588,7 @@ "text": "Termes & commentaires" }, "description": "Images Esri archivées qui peut être plus propre et plus précise que la couche par défaut", - "name": "Images Esri mondiales (clarifiées) bêta" + "name": "Images mondiales Esri (clarifiées) bêta" }, "MAPNIK": { "attribution": { @@ -6388,6 +6657,10 @@ "description": "Le jaune correspond aux données des cartes du domaine public issues du recensement américain, le rouge à des données non trouvées dans OpenStreetMap", "name": "Données géographiques et topologiques intégrées et encodées 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Voies : en vert route non classifiée, en marron piste. Surface : les graviers sont représentés par un remplissage marron, l'asphalte par du noir, les pavés par du gris, la terre par du blanc, le béton par du bleu, l'herbe par du vert. Les voies saisonnières ont des barres blanches.", + "name": "Surcouche des routes forestières états-uniennes" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, contributeurs OpenStreetMap, CC by-SA 3.0" @@ -6484,7 +6757,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Map tiles par Stamen Design, sous CC BY 3.0" + "text": "Tuiles par Stamen Design, sous CC-BY 3.0. Données par OpenStreetMap, sous ODbL" }, "name": "Stamen Terrain" }, @@ -6500,6 +6773,762 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "YouthMappers de l'université de Cape Coast", + "description": "Suivez-nous sur Twitter: {url}", + "extendedDescription": "C'est le compte officiel du cahpitre Youth Mappers de l'université de Cape Coast, au Ghana. Nous aimons les cartes, la donnée libre et aider les communautés vulnérables." + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana sur Facebook", + "description": "Groupe Facebook pour les gens intéressés par OpenStreetMap.", + "extendedDescription": "Cartographes de la communauté du Ghana qui promeuvent les projets OpenStreetMap et Humanitarian OpenStreetMap Team (HOT) au Ghana. Rejoignez-nous." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana sur Twitter", + "description": "Suivez-nous sur Twitter: {url}" + }, + "talk-gh": { + "name": "Liste de diffusion Talk-gh", + "description": "Talk-gh est la liste de diffusion officielle de la communauté d'OSM au Ghana." + }, + "osm-mg-facebook": { + "name": "Groupe Facebook OpenStreetMap Madagascar", + "description": "Groupe Facebook malgache pour les gens intéressé par OpenStreetMap." + }, + "talk-mg": { + "name": "Liste de diffusion talk-mg", + "description": "Le lieu de rencontre des contributeurs OpenStreetMap, des communautés et des utilisateurs à Madagascar où partager et discuter." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesh", + "description": "Améliorez OpenStreetMap au Bangladesh", + "extendedDescription": "Vous cartographiez au Bangladesh ? Vous avez des questions, souhaitez entrer en contact avec la communauté ici ? Rejoignez-nous sur {url}. Vous êtes tous les bienvenus !" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap Inde - cartographie participative du voisinage", + "description": "Améliorez OpenStreetMap en Inde", + "extendedDescription": "Vous cartographiez en Inde ? Vous avez des questions, vous souhaitez rencontrer la communauté ? Rejoignez-nous sur {url}. Vous êtes tous les bienvenus !", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "description": "Rejoignez l'événement régional OpenStreetMap 2018 au State of the Map Asion en Inde", + "where": "Indian Institute of Management, Bangalore, India" + } + } + }, + "OSM-india-mailinglist": { + "name": "Liste de diffusion OpenStreetMap Inde", + "description": "Talk-in est la liste de diffusion officielle pour la communauté OSM d'Inde" + }, + "OSM-india-twitter": { + "name": "Fil Twitter d'OpenStreetMap Inde", + "description": "Nous ne sommes qu'à un tweet : {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Mouvement logiciel libre et matériel (Free Software Hardware Movement, FSHM) - Facebook", + "description": "Page Facebook de FSHM pour en connaître plus sur les événements communautaires et les activités", + "extendedDescription": "FSHM organise des événements liés au logiciel et au matériel libre, les technologies, l'activisme et OpenStreetMap. Sa page FB est le meilleur moyen de rester en contact avec ses événements" + }, + "OSM-India-Puducherry-Matrix": { + "name": "Mouvement logiciel libre et matériel (Free Software Hardware Movement, FSHM) - Matrix", + "description": "Group riot FSHM pour discutter, partager et mettre à jour les activités de cartographie, les événements à et autour de Puducherry", + "extendedDescription": "Les membres de la communauté FSHM partagent leur mises à jour et expériences sur OSM à travers le groupe riot.im. Ce groupe est aussi utilisé pour discutter de choses liées au logiciel et matériel libre, les technologies et l'activisme." + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonésie", + "description": "Améliorez OpenStreetMap en Indonésie", + "extendedDescription": "Vous cartographiez en Indonésie ? Vous avez des questions, vous souhaitez rencontrer la communauté ? Rejoignez-nous sur {Url}. Vous êtes tous les bienvenus !" + }, + "OSM-japan-facebook": { + "name": "Communauté OpenStreetMap japonaise", + "description": "Cartographes et utilisateurs d'OpenStreetMap au Japon" + }, + "OSM-japan-mailinglist": { + "name": "Liste de diffusion OpenStreetMap Japon", + "description": "Talk-ja est la liste de diffusion officielle pour la communauté OSM du Japon" + }, + "OSM-japan-twitter": { + "name": "Fil Twitter d'OpenStreetMap Japon", + "description": "Hashtag sur Twitter: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap Japon", + "description": "Cartographes et utilisateurs d'OpenStreetMap au Japon" + }, + "OSM-korea-telegram": { + "name": "Canal telegram d'OSM Corée", + "description": "Canal non officiel des contributeurs d'OpenStreetMap, des communautés et des utilisateurs en Corée pour partager et discuter." + }, + "OSM-MY-facebook": { + "name": "OpenStreetMap Malaisie sur Facebook", + "description": "Pour discuter de tout ce qui concerne OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "Forum d'OpenStreetMap Malaisie", + "description": "Forum officiel d'OpenStreetMap Malaisie" + }, + "OSM-MY-matrix": { + "name": "Canal riot d'OpenStreetMap Malaisie", + "description": "Tous les cartographes sont les bienvenus ! Enregistrez-vous sur {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongolie", + "description": "Améliorez OpenStreetMap en Mongolie", + "extendedDescription": "Vous cartographiez en Mongolie ? Vous avez des questions, vous souhaitez rencontrer la communauté ? Rejoignez-nous sur {Url}. Vous êtes tous les bienvenus !" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Birmanie", + "description": "Améliorez OpenStreetMap en Birmanie", + "extendedDescription": "Vous cartographiez en Birmanie ? Vous avez des questions, vous souhaitez rencontrer la communauté ? Rejoignez-nous sur {Url}. Vous êtes tous les bienvenus !" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Népal", + "description": "Améliorez OpenStreetMap au Népal", + "extendedDescription": "Vous cartographiez au Népal ? Vous avez des questions, vous souhaitez rencontrer la communauté ? Rejoignez-nous sur {Url}. Vous êtes tous les bienvenus !" + }, + "OSM-PH-facebook": { + "name": "Page Facebook d'OpenStreetMap PH", + "description": "Bienvenue sur OpenStreetMap Philippines, où nous encourageons tous les philippins à contribuer au projet OpenStreetMap." + }, + "OSM-PH-mailinglist": { + "name": "Liste de diffusion talk-ph", + "description": "Une liste de diffusion pour discuter d'OpenStreetMap aux Philippines" + }, + "OSM-PH-slack": { + "name": "Slack OpenStreetMap PH", + "description": "Vous êtes tous les bienvenus ! Enregistrez-vous sur {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "Groupe telegram OpenStreetMap PH", + "description": "Communauté telegram locale non officielle des contributeurs d'OpenStreetMap et amis aux Philippines" + }, + "OSM-RU-forum": { + "name": "Forum OpenStreetMap RU", + "description": "Forum web OpenStreetMap Russie" + }, + "OSM-RU-telegram": { + "name": "Groupe telegram OpenStreetMap RU", + "description": "Chat telegram d'OpenStreetMap Russie" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka", + "description": "Améliorez OpenStreetMap au Sri Lanka", + "extendedDescription": "Vous cartographiez au Sri Lanka ? Vous avez des questions, vous souhaitez rencontrer la communauté ? Rejoignez-nous sur {Url}. Vous êtes tous les bienvenus !" + }, + "OSM-TW-facebook": { + "name": "OpenStreetMap Taïwan", + "description": "Groupe Facebook pour que les cartographes et les utilisateurs d'OpenStreetMap discuttent de Taïwan." + }, + "OSM-TW-mailinglist": { + "name": "Liste de diffusion OpenStreetMap Taïwan", + "description": "Talk-tw est la liste de diffusion officielle pour la communauté OSM de Taïwan" + }, + "OSM-TH-CNX-meetup": { + "name": "Rencontres OSM Chiang Mai", + "description": "Rencontres irrégulières de la communauté OpenStreetMap à Chiang Mai", + "extendedDescription": "Les membres de la communauté OpenStreetMap se rencontrent tous les quelques mois à Chiang Mai. Contactez-nous et regardez {url} pour voir quand notre prochaine rencontre est prévue" + }, + "OSM-TH-forum": { + "name": "Forum OpenStreetMap TH", + "description": "Forum web d'OpenStreetMap Thaïlande" + }, + "al-forum": { + "name": "Forum d'OSM Albanie", + "description": "Forum d'OpenStreetMap Albanie" + }, + "al-maptime-tirana": { + "name": "Maptime Tirana", + "description": "Événements sociaux organisés autour de la cartographie — les débutants sont les bienvenus !", + "extendedDescription": "Maptime est un environnement d'apprentissage ouvert pour tous les niveaux et degrés de connaissance, offrant un support éducatif volontaire pour le débutant. Maptime est aussi flexible que structuré, créant un espace pour les tutoriels de cartographie, les ateliers, les projets en cours avec un but commun et des temps de travail indépendants ou communs." + }, + "al-telegram": { + "name": "Canal Telegram d'OSM Albanie", + "description": "Canal Telegram d'OpenStreetMap Albanie" + }, + "at-forum": { + "name": "Forum d'OpenStreetMap Autriche", + "description": "Le forum officiel pour les questions sur OpenStreetMap en Autriche et autour" + }, + "at-mailinglist": { + "name": "Liste de diffusion talk-at", + "description": "Talk-at est la liste de diffusion officielle pour la communauté OSM d'Autriche" + }, + "at-twitter": { + "name": "Fil Twitter d'OpenStreetMap Autriche", + "description": "OpenStreetMap Autriche sur Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "Rencontres OSM communautaires de Graz", + "description": "Rencontres mensuelles de la communauté OpenStreetMap à Graz" + }, + "osmgraz-twitter": { + "name": "Communauté OSM de Graz sur twitter", + "description": "Communauté OpenStreetMap de Graz sur twitter" + }, + "osm-at": { + "name": "OpenStreetMap Autriche", + "description": "La plateforme pour obtenir des informations sur OpenStreetMap en Autriche" + }, + "byosm": { + "name": "OpenStreetMap Biélorussie", + "description": "Chat telegram OpenStreetMap Biélorussie" + }, + "be-facebook": { + "name": "OpenStreetMap Belgique", + "description": "Cartographes et OpenStreetMap sur Facebook en Belgique" + }, + "be-forum": { + "name": "Forum OpenStreetMap BE", + "description": "Forum web d'OpenStreetMap Belgique" + }, + "be-irc": { + "name": "IRC d'OpenStreetMap Belgique", + "description": "Rejoignez #osmbe sur irc.oftc.net (port 6667)", + "extendedDescription": "Rejoignez #osmbe sur irc.oftc.net (port 6667), il y a un pont avec le canal matrix" + }, + "be-mailinglist": { + "name": "Liste de diffusion talk-be", + "description": "Talk-be est la liste de diffusion officielle pour la communauté belge d'OSM" + }, + "be-maptime": { + "name": "Maptime Belgique", + "description": "Événements sociaux organisés autour de la cartographie — les débutants sont les bienvenus !", + "extendedDescription": "Maptime est un environnement d'apprentissage ouvert pour tous les niveaux et degrés de connaissance, offrant un support éducatif volontaire pour le débutant. Maptime est aussi flexible que structuré, créant un espace pour les tutoriels de cartographie, les ateliers, les projets en cours avec un but commun et des temps de travail indépendants ou communs." + }, + "be-matrix": { + "name": "Canal Matrix d'OpenStreetMap BE", + "description": "Tous les cartographes sont les bienvenus !", + "extendedDescription": "La plupart des discussions ont lieu sur le canal « OpenStreetMap Belgium ». Vous pouvez y demander tout ce que vous voulez ! Les autres canaux sont là pour des sujets spécifiques." + }, + "be-meetup": { + "name": "Réunion d'OpenStreetMap Belgique", + "description": "Rencontres pour tous ceux qui sont intéressés par OpenStreetMap", + "extendedDescription": "Les rencontres physiques sont un bon moyen de rencontrer d'autres cartographes, leur poser des questions et apprendre plein de choses. Les nouveaux contributeurs sont particulièrement les bienvenus !" + }, + "be-twitter": { + "name": "Fil Twitter d'OpenStreetMap Belgique", + "description": "OSM Belgique sur Twitter: @osm_be" + }, + "talk-cz-mailinglist": { + "name": "Liste de diffusion talk-cz", + "description": "Talk-cz est la liste de diffusion officielle pour la communauté tchèque" + }, + "dk-forum": { + "name": "Forum web d'OpenStreetMap Danemark", + "description": "Forum web d'OpenStreetMap Danemark" + }, + "dk-irc": { + "name": "IRC d'OpenStreetMap Danemark", + "description": "Rejoignez #osm-dk sur irc.oftc.net (port 6667)" + }, + "dk-mailinglist": { + "name": "Liste de diffusion Talk-dk", + "description": "Une liste de diffusion pour discuter d'OpenStreetMap au Danemark" + }, + "fi-forum": { + "name": "Forum OpenStreetMap FI", + "description": "Forum web d'OpenStreetMap Finlande" + }, + "fi-irc": { + "name": "IRC d'OpenStreetMap Finlande", + "description": "Rejoignez #osm-fi sur irc.oftc.net (port 6667)" + }, + "fi-mailinglist": { + "name": "Liste de diffusion Talk-fi", + "description": "Talk-fi est la liste de diffusion officielle de la communauté d'OSM en Finlande" + }, + "fr-facebook": { + "name": "Page Facebook d'OpenStreetMap France", + "description": "Page Facebook d'OpenStreetMap France" + }, + "fr-forum": { + "name": "Forum web d'OpenStreetMap France", + "description": "Forum web d'OpenStreetMap France" + }, + "fr-irc": { + "name": "IRC d'OpenStreetMap France", + "description": "Rejoignez #osm-fr sur irc.oftc.net (port 6667)" + }, + "fr-mailinglist": { + "name": "Liste de diffusion Talk-fr", + "description": "Liste de diffusion Talk-fr" + }, + "fr-twitter": { + "name": "OpenStreetMap France sur Twitter", + "description": "OpenStreetMap France sur Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "Liste de diffusion pour Berlin", + "description": "Il s'agit de la liste de diffusion pour la communauté berlinoise d'OSM" + }, + "de-berlin-meetup": { + "name": "Recontres OpenStreetMap de Berlin-Brandenburg", + "description": "Cartographes et utilisateurs OpenStreetMap dans la région de Berlin" + }, + "de-berlin-telegram": { + "name": "@osmberlin sur Telegram", + "description": "Chat Telegram d'OpenStreetMap Berlin" + }, + "de-berlin-twitter": { + "name": "Fil Twitter d'OpenStreetMap Berlin", + "description": "Suivez-nous sur Twitter: {url}" + }, + "de-forum": { + "name": "Forum d'OpenStreetMap DE", + "description": "Forum web d'OpenStreetMap Allemagne" + }, + "de-irc": { + "name": "IRC d'OpenStreetMap Allemagne", + "description": "Rejoignez #osm-de sur irc.oftc.net (port 6667)" + }, + "de-mailinglist": { + "name": "Liste de diffusion Talk-de", + "description": "Talk-de est la liste de diffusion officielle pour la communauté allemande d'OSM" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "Liste de diffusion OWL", + "description": "Il s'agit de la liste de diffusion pour la communauté OSM en Westphalie Est-Lippe" + }, + "osm-de": { + "name": "OpenStreetMap Allemagne", + "description": "La plate-forme pour l'information sur OpenStreetMap en Allemagne" + }, + "hu-facebook": { + "name": "OpenStreetMap HU sur Facebook", + "description": "Page Facebook des cartographes et d'OpenStreetMap en Hongrie" + }, + "hu-forum": { + "name": "Forum OpenStreetMap HU", + "description": "Forum web d'OpenStreetMap Hongrie" + }, + "hu-meetup": { + "name": "Réunion d'OpenStreetMap Hongrie", + "description": "La plate-forme pour l'organisation des réunions en Hongrie" + }, + "it-facebook": { + "name": "Facebook d'OpenStreetMap Italie", + "description": "Rejoignez la communauté italienne d'OpenStreetMap sur Facebook" + }, + "it-irc": { + "name": "IRC d'OpenStreetMap Italie", + "description": "Rejoignez #osm-it sur irc.oftc.net (port 6667)" + }, + "it-mailinglist": { + "name": "Liste de diffusion Talk-it", + "description": "Talk-it est la liste de diffusion officielle pour la communauté italienne d'OSM" + }, + "it-telegram": { + "name": "@OpenStreetMapItalia sur Telegram", + "description": "Chat Telegram d'OpenStreetMap Italie" + }, + "it-twitter": { + "name": "Fil Twitter d'OpenStreetMap Italie", + "description": "Suivez-nous sur Twitter à l'adresse {url}" + }, + "OSM-Rome-meetup": { + "name": "Incontro Mappatori Romani", + "description": "Améliorez OpenStreetMap dans la région de Rome", + "extendedDescription": "Nous souhaitons être une ressource pour les gens où discuter et partager notre connaissance sur l'utilisation des données géographiques libres, en particulier OpenStreetMap, et des logiciels géospatiaux qui gèrent, modifient et affichent des données géographiques et militons pour leur utilisation à Lazio." + }, + "South-Tyrol-Mailing-List": { + "name": "Liste de diffusion OpenStreetMap pour le Haut-Adige", + "description": "Liste de discussion OpenStreetMap Italie régionale pour le Haut-Adige." + }, + "talk-it-lazio": { + "name": "OpenStreetMap Italie Lazio", + "description": "Vous êtes tous les bienvenus ! Enregistrez-vous sur {signupUrl}", + "extendedDescription": "Liste de diffusion pour Rome et la région du Lazio" + }, + "Trentino-Mailing-List": { + "name": "Liste de diffusion OpenStreetMap pour le Trentin", + "description": "Liste de discussion OpenStreetMap Italie régionale pour Trentino." + }, + "no-forum": { + "name": "Forum web d'OpenStreetMap Norvège", + "description": "Forum web d'OpenStreetMap Norvège" + }, + "no-irc": { + "name": "IRC d'OpenStreetMap Norvège", + "description": "Salon de discussion pour les cartographes et les utilisateurs, les développeurs et les amateurs d'OpenStreetMap en Norvège" + }, + "no-mailinglist": { + "name": "Liste de diffusion d'OpenStreetMap Norvège", + "description": "Liste de diffusion pour les cartographes et les utilisateurs, développeurs et amateurs d'OpenStreetmap en Norvège" + }, + "OSM-PL-facebook-group": { + "name": "Groupe Facebook d'OpenStreetMap Pologne", + "description": "Groupe pour les cartographes et les utilisateurs d'OpenStreetMap en Pologne" + }, + "OSM-PL-forum": { + "name": "Forum d'OpenStreetMap Pologne", + "description": "Forum de la communauté polonaise d'OpenStreetMap" + }, + "OSM-ES-mailinglist": { + "name": "Liste de diffusion Talk-es", + "description": "Une liste de diffusion pour discuter d'OpenStreetMap en Espagne" + }, + "OSM-ES-telegram": { + "name": "@OSMes sur Telegram", + "description": "Chat Telegram d'OpenStreetMap Espagne" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "Des nouvelles de la communauté OpenStreetMap suédoise" + }, + "se-facebook": { + "name": "Facebook d'OpenStreetMap Suède", + "description": "OpenStreetMap Suède sur Facebook" + }, + "se-forum": { + "name": "Forum web d'OpenStreetMap Suède", + "description": "Forum web d'OpenStreetMap Suède" + }, + "se-irc": { + "name": "IRC d'OpenStreetMap Suède", + "description": "Rejoignez #osm.se sur irc.oftc.net (port 6667)" + }, + "se-mailinglist": { + "name": "Liste de diffusion Talk-se", + "description": "Une liste de diffusion pour discuter d'OpenStreetMap en Suède" + }, + "se-twitter": { + "name": "OpenStreetMap Suède sur Twitter", + "description": "Suivez-nous sur Twitter: {url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "Rencontres mensuelles dans un pub de East Midlands (Nottingham)", + "description": "Rassemblement social pour les cartographes et les utilisateur d'East Midlands", + "extendedDescription": "Un groupe se rencontre depuis Mars 2011, au début à Nottingham et plus récemment à Derby et de temps en temps autre part dans les East Midlands. Ce sont des rencontres sociales mais sont des moments privilégiés pour poser des questions spécifiques sur OSM dans la région et en général. Pendant les mois d'été nous cartographions rapidement pendant une heure autour du lieu de réunion. Le groupe est particulièrement intéressé par la cartographie des droits de passage et organise parfois des cartoparties dans ce but." + }, + "gb-mailinglist": { + "name": "Liste de diffusion Talk-gb", + "description": "Talk-gb est la liste principale pour la communauté OSM anglaise (dont fait partie l'Irlande du Nord)" + }, + "mappa-mercia-group": { + "name": "Groupe local Mappa Mercia", + "description": "Un endroit pour les amateurs d'OpenStreetMap dans les Midlands", + "extendedDescription": "Mappa Mercia est un projet pour faire grandir OpenStreetMap dans les West Midlands au Royaume-Uni. Nous organisons des événements communautaires, fournissons de l'aide et du support aux organisations locales qui veulent libérer leurs données." + }, + "gb-irc": { + "name": "IRC d'OpenStreetMap Royaume-Uni", + "description": "Rejoignez #osm-gb sur irc.oftc.net (port 6667)", + "extendedDescription": "Rejoignez #osm-gb sur irc.oftc.net (port 6667), soyez patient SVP et attendez quelques minutes si vous posez une question" + }, + "OSM-CA-Slack": { + "name": "Slack OSM-CA", + "description": "Vous êtes tous les bienvenus ! Enregistrez-vous sur {signupUrl}." + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver", + "description": "Cartographes et utilisateurs d'OpenStreetMap à Vancouver" + }, + "OSM-CU-telegram": { + "name": "OSM Cuba sur Telegram", + "description": "Chat Telegram d'OpenStreetMap Cuba" + }, + "OSM-NI-telegram": { + "name": "OSM Nicaragua sur Telegram", + "description": "Chat Telegram d'OpenStreetMap Nicaragua" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area OpenStreetMappers", + "description": "Améliorez OpenStreetMap dans la Bay Area", + "extendedDescription": "Ce groupe a pour objectif de développer la communauté OpenStreetMap dans le secteur de la Région de la baie de San Francisco. Nos événements sont ouverts à tout le monde, passionné.e.s de l'Open Source, cyclistes, professionnel.le.s de la géomatique, geocachers, ou d'autres encore. Quiconque est intéressé.e par les cartes, la cartographie et les données cartographiques libres est invité.e à rejoindre le groupe et à participer aux événements." + }, + "Central-Pennsylvania-OSM": { + "name": "Central Pennsylvania OSM", + "description": "Communauté de cartographie en ligne de State College, Pennsylvanie" + }, + "Code-for-San-Jose-Slack": { + "name": "Slack de Code for San Jose", + "description": "Tout le monde est le bienvenu! Inscrivez-vous sur {signupUrl} et rejoignez le canal #osm." + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "Groupe d'utilisateurs OpenStreetMap de Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth et les villes au milieu abondent de personnes créatives et douées en informatique. La volonté de ce groupe est de trouver de nouvelles manières d'utiliser les supers ressources d'OSM." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Réunion pour les passionnés de cartographie dans la région de Philadelphie", + "extendedDescription": "GeoPhilly unit les développeurs, les géographes, les passionnés de données et d'open source, les hackers civiques et les drogués de la carte dans l'amour partagé pour les cartes et les histoires qu'elles racontent. Que vous utilisiez des cartes dans votre travail ou que vous souhaitiez en savoir plus, c'est la bonne réunion ! Nos événements essayent d'être ouverts, amicaux, éducatifs et sociaux et vont des happy hours aux présentations rapides voire aux ateliers. Venez créer une communauté géospatiale diversifiée et inspirante à Philadelphie avec nous !" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "Cartographes et amateurs d'OpenStreetMap dans la région des villes jumelles", + "extendedDescription": "Nous connectons les amateurs d'OpenStreetMap au Minnesota et dans les villes jumelles !" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC", + "description": "Améliorez OpenStreetMap dans la région de DC", + "extendedDescription": "Nous sommes un groupe de cartographes volontaires qui cherchons à améliorer OpenStreetMap dans la région de DC. Nous essayons aussi de montrer aux autres ce qu'est l'écosystème OSM, l'analyse de données, la cartographie et les SIG. Nous nous réunissons tous les mois à des réunions pour nous concentrer sur une partie de notre ville." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Cartographes et utilisateurs d'OpenStreetMap autour de Portland, ME", + "extendedDescription": "Maptime est, plutôt littéralement, l'heure de cartographier. Notre mission est d'ouvrir les portes des possibilités cartographiques à tous ceux qui sont intéressés par la création d'un temps et d'un espace collaboratif d'apprentissage, d'exploration et de création de cartes avec des outils et des technologies de cartographie." + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Améliorez OpenStreetMap dans la région de Cleveland", + "extendedDescription": "Open Geo Cleveland souhaite être une ressource pour les gens où discuter et partager notre connaissance sur l'utilisation des données géographiques libres, en particulier OpenStreetMap, et des logiciels géospatiaux qui gèrent, modifient et affichent des données géographiques et militons pour leur utilisation au nord-est de l'Ohio. Nous sommes aussi un chapitre maptime =)" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Cartographes et utilisateurs d'OpenStreetMap dans la région de Boston", + "extendedDescription": "OpenStreetMap est la carte du monde libre et ouverte comme un wiki avec des centaines de milliers de contributions chaque jour par des personnes comme vous. Modifier la carte est simple et amusant ! Rejoignez-nous aussi bien en intérieur qu'en extérieur dans notre effort pour créer la meilleure carte de la région de Boston et du reste du monde !" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Mer de Salish", + "description": "Cartographes et utilisateurs d'OpenStreetMap autour de Mount Vernon, WA", + "extendedDescription": "OpenStreetMap est une carte du monde faite par des gens comme vous. C'est une carte que vous construisez et qui est libre comme wikipédia. Voyez osm.org pour plus d'informations. Nous nous rencontrons pour parler de cartes, contribuer à OSM et s'amuser !" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "Le groupe d'utilisateurs d'OSM de Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "description": "Cartographes et utilisateurs d'OpenStreetMap dans l'état du Colorado aux USA", + "extendedDescription": "OpenStreetMap (OSM) Colorado est une collaboration locale de personnes intéressées par la contribution de leurs efforts pour créer des cartes libres. Nous encourageons tous les cartographes à organiser ou suggérer des événements cartographiques dans tout l'état. Des rencontres peuvent simplement tisser des liens sociaux, consister en des cours de base ou avancés sur OSM ou des cartoparties communautaires." + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Cartographes et utilisateurs d'OpenStreetMap, développeurs et passionnés dans la région métropolitaine de New York" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Cartographes et utilisateurs d'OpenStreetMap dans la région de Portland", + "extendedDescription": "OpenStreetMap (OSM) est une carte du monde faite par des gens comme vous. C'est une carte que vous construisez et qui est libre comme wikipédia. Voyez osm.org pour plus d'informations et rejoignez-nous à une rencontre pour parler de cartes, contribuer à OSM et s'amuser !" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Cartographes et utilisateurs d'OpenStreetMap dans la région de Seattle" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Californie du sud", + "description": "Amusons-nous, contribuons quelque chose pour Los Angeles et apprenons à cartographier !", + "extendedDescription": "OpenStreetMap (OSM) Californie du sud réuni tous les gens intéressés par la cartographie pour travailler sur OpenStreetMap. OpenStreetMap, le Wikipédia des cartes, est une carte libre du monde créée par plus de 1 000 000 de volontaires autour du monde. Tout le monde est le bienvenu. Si vous ne connaissez pas OpenStreetMap, nous vous apprendrons. Si vous avez une idée de projet de cartographie ou même d'une excursion à laquelle le groupe pourrait participer, super !" + }, + "OSM-South-Bay": { + "name": "OSM South Bay", + "description": "Nuits de la cartographie hébergées par Code for San Jose", + "extendedDescription": "Code for San Jose, la brigade Code for America locale, héberge des nuits de la cartographie mensuelles les jeudi soirs à San José. Rencontrez d'autres cartographes de South Bay, aidez les projets de cartographie locaux et apprenez-en plus sur les autres projets civiques techniques. Vous n'avez pas besoin de connaître la programmation ou les SIG." + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap baie de Tampa", + "description": "Cartographes et utilisateurs d'OpenStreetMap dans la région de la baie de Tampa", + "extendedDescription": "Le groupe OpenStreetMap baie de Tampa pour que les locaux se rencontrent et construisent la carte complète de la baie de Tampa avec OpenStreetMap, la carte du monde libre et modifiable. Si vous aimez les cartes, les données, l'open source, le GPS, la randonnée, le vélo et cætera, vous allez aimer travailler avec OpenStreetMap – alors rejoinez-nous ! Nous nous rencontrerons pour cartographier et parler de nouveaux sujets environ une fois par mois." + }, + "OSM-US-Slack": { + "name": "Slack d'OpenStreetMap US", + "description": "Vous êtes tous les bienvenus ! Enregistrez-vous sur {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap États-Unis", + "description": "Nous aidons OpenStreetMap à grandir et à s'améliorer aux États-Unis.", + "extendedDescription": "Nous soutenons OpenStreetMap en organisant des conférences annuelles, en fournissant des moyens à la communauté, en établissant des partenariats, et en relayant les informations. Rejoignez OpenStreetMap États-Unis ici: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah", + "description": "Cartographes et utilisateurs d'OpenStreetMap dans la région de Salt Lake City", + "extendedDescription": "Les activités peuvent être des ateliers pour apprendre à cartographier, des cartoparties et des collectes de données en extérieur. Les événement se déroulent dans la zone de SLC au moins au départ. Nous cherchons des cartographes chevronnés ainsi que des nouveaux sur OSM. Rejoignez-nous et cartographions !" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming", + "description": "Cartographes et utilisateurs d'OpenStreetMap dans la région de Wyoming", + "extendedDescription": "OpenStreetMap (OSM) Wyoming est une collaboration locale de gens intéressés par la contribution de leurs efforts pour créer des cartes libres. Nous encourageons tous nos cartographes à organiser ou suggérer des événement cartographiques dans tout l'état. Les rencontres peuvent consister en de simples événements sociaux, des sessions d'apprentissage des bases ou avancées, ou des cartoparties communautaires." + }, + "PHXGeo-meetup": { + "name": "Rencontres PHXGeo", + "description": "Cartographes et utilisateurs d'OpenStreetMap dans la région de Phoenix, AZ", + "extendedDescription": "C'est un groupe de rencontre pour les gens de la zone de Phoenix qui aiment les cartes, les SIG, OpenStreetMap et tout le reste." + }, + "PHXGeo-twitter": { + "name": "Fil Twitter de PHXGeo", + "description": "Suivez-nous sur Twitter à l'adresse {url}" + }, + "Western-Slope-facebook": { + "name": "Facebook de Western Slope", + "description": "Cartographes et utilisateurs d'OpenStreetMap autour de Grand Junction, CO" + }, + "Western-Slope-meetup": { + "name": "Recontres de Wester Slope OSM", + "description": "Cartographes et utilisateurs d'OpenStreetMap autour de Grand Junction, CO", + "extendedDescription": "Le but de ce groupe est de présenter OpenStreetMap aux communautés, développer une communauté de cartographes, créer la meilleure donnée géographique possible par n'importe quel moyen et finalement d'élaborer une stratégie pour communiquer cette donnée aux communautés. Imaginez des panneaux indicatifs sur les chemins de randonnées ! Imaginez un meilleur développement des voies cyclables ! Imaginez tout ce que vous voulez, c'est le plaisir d'OpenStreetMap !" + }, + "Maptime-Australia-Slack": { + "name": "Slack de Maptime Australia", + "description": "Enregistrez-vous sur {signupUrl}" + }, + "talk-au": { + "name": "Liste de diffusion talk-au", + "description": "Lieu de discussion pour les cartographes australiens" + }, + "OSM-AR-facebook": { + "name": "Page Facebook d'OpenStreetMap Argentine", + "description": "Rejoignez la communauté d'OpenStreetMap Argentine sur Facebook", + "extendedDescription": "Des nouvelles de la communauté locale" + }, + "OSM-AR-forum": { + "name": "Forum web d'OpenStreetMap Argentine", + "description": "Rejoignez le forum web d'OpenStreetMap Argentine", + "extendedDescription": "Idéal pour des discussions longues et importantes. Temps de réponse élevé." + }, + "OSM-AR-irc": { + "name": "IRC d'OpenStreetMap Argentine", + "description": "Rejoignez #osm-ar sur irc.oftc.net (port 6667)", + "extendedDescription": "Vous pouvez trouver les utilisateurs les plus geek de la communauté." + }, + "OSM-AR-mailinglist": { + "name": "Liste de diffusion talk-ar", + "description": "Liste de diffusion historique. Presque inutilisée aujourd'hui." + }, + "OSM-AR-telegram": { + "name": "Telegram d'OpenStreetMap Argentine", + "description": "Rejoignez la communauté d'OpenStreetMap Argentine sur Telegram", + "extendedDescription": "Le canal le plus actif dans la communauté, idéal pour papoter et obtenir des réponses à vos questions instantanément. Tout le monde est le bienvenu !" + }, + "OSM-AR-twitter": { + "name": "Fil Twitter d'OpenStreetMap Argentine", + "description": "Suivez-nous sur Twitter à l'adresse {url}", + "extendedDescription": "Des nouvelles de la communauté locale et d'OpenStreetMap en général." + }, + "OSM-BO-mailinglist": { + "name": "Liste de diffusion Talk-bo", + "description": "Talk-bo est la liste de diffusion officielle pour la communauté bolivienne d'OpenStreetMap", + "extendedDescription": "Vous cartographiez en Bolivie ? Vous avez des questions, vous souhaitez rencontrer la communauté ? Rejoignez-nous sur {url}. Vous êtes tous les bienvenus !" + }, + "Bahia-telegram": { + "name": "Groupe Telegram d'OpenStreetMap Bahia", + "description": "Rejoignez la communauté d'OpenStreetMap Bahia sur Telegram", + "extendedDescription": "Rejoignez la communauté pour en apprendre plus sur OpenStreetMap, pour poser des questions ou participer à nos rencontres. Tout le monde est le bienvenu!" + }, + "DF-telegram": { + "name": "Groupe Telegram d'OpenStreetMap Brésil", + "description": "Rejoignez la communauté d'OpenStreetMap Brasilia sur Telegram", + "extendedDescription": "Rejoignez la communauté pour en apprendre plus sur OpenStreetMap, pour poser des questions ou participer à nos rencontres. Tout le monde est le bienvenu!" + }, + "OSM-br-mailinglist": { + "name": "Liste de diffusion talk-br", + "description": "Une liste de diffusion pour discuter d'OpenStreetMap au Brézil" + }, + "OSM-br-telegram": { + "name": "Telegram d'OpenStreetMap Brésil", + "description": "Rejoignez la communauté d'OpenStreetMap Brésil sur Telegram", + "extendedDescription": "Rejoignez la communauté pour en apprendre plus sur OpenStreetMap, pour poser des questions ou participer à nos rencontres. Tout le monde est le bienvenu!" + }, + "OSM-br-twitter": { + "name": "Fil Twitter d'OpenStreetMap Brésil", + "description": "Suivez-nous sur Twitter à l'adresse {url}" + }, + "OSM-CL-facebook": { + "name": "Page Facebook d'OpenStreetMap Chili", + "description": "Rejoignez la communauté d'OpenStreetMap Chili sur Facebook", + "extendedDescription": "Rejoignez la communauté pour en apprendre plus sur OpenStreetMap, pour poser des questions ou participer à nos rencontres. Tout le monde est le bienvenu!" + }, + "OSM-CL-mailinglist": { + "name": "Liste de diffusion talk-cl", + "description": "Une liste de diffusion pour discuter d'OpenStreetMap au Chili" + }, + "OSM-CL-telegram": { + "name": "Telegram d'OpenStreetMap Chili ", + "description": "Rejoignez la communauté d'OpenStreetMap Chili sur Telegram", + "extendedDescription": "Rejoignez la communauté pour en apprendre plus sur OpenStreetMap, pour poser des questions ou participer à nos rencontres. Tout le monde est le bienvenu!" + }, + "OSM-CL-twitter": { + "name": "Fil Twitter d'OpenStreetMap Chili", + "description": "Suivez-nous sur Twitter à l'adresse {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá", + "description": "Nous sommes un groupe de cartographes intéressés par la cartographie et OpenStreetMap autour de Bogotá.", + "extendedDescription": "Apprenez à collecter des données sur le terrain et les numériser sur OpenStreetMap. Aucune connaissance préalable n'est requise ! Vous avez seulement besoin de vouloir participer, apprendre et vous amuser." + }, + "OSM-CO-facebook": { + "name": "Facbebook OpenStreetMap Colombie", + "description": "Rejoignez la communauté OpenStreetMap Colombie sur Facebook", + "extendedDescription": "Rejoignez la communauté pour en apprendre plus sur OpenStreetMap. Tout le monde est le bienvenu!" + }, + "OSM-CO-mailinglist": { + "name": "Liste de diffusion Talk-co", + "description": "Une liste de diffusion pour discuter d'OpenStreetMap en Colombie" + }, + "OSM-CO-telegram": { + "name": "OSM Colombie sur Telegram", + "description": "Chat Telegram d'OpenStreetMap Colombie" + }, + "OSM-CO-twitter": { + "name": "Fil Twitter d'OpenStreetMap Colombie", + "description": "Suivez-nous sur Twitter à l'adresse {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Colombie", + "description": "Des nouvelles de la communauté d'OpenStreetMap Colombie et de la fondation OSMCo" + }, + "OSM-EC-telegram": { + "name": "OSM Équateur sur Telegram", + "description": "Chat Telegram d'OpenStreetMap Équateur" + }, + "OSM-PY-telegram": { + "name": "OSM Paraguay sur Telegram", + "description": "Chat Telegram d'OpenStreetMap Paraguay" + }, + "OSM-PE-facebook": { + "name": "Facebook d'OpenStreetMap Pérou", + "description": "Rejoignez la communauté d'OpenStreetMap Pérou sur Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Liste de diffusion Talk-pe", + "description": "La liste de diffusion officielle pour la communauté d'OpenStreetMap au Pérou" + }, + "OSM-PE-matrix": { + "name": "Le salon de discussion d'OpenStreetMap Pérou sur Matrix", + "description": "Discutez avec d'autres membres de la communauté d'OpenStreetMap au Pérou sur Matrix." + }, + "OSM-PE-telegram": { + "name": "Telegram d'OpenStreetMap Pérou", + "description": "Rejoignez la communauté d'OpenStreetMap Pérou sur Telegram" + }, + "OSM-PE-twitter": { + "name": "Fil Twitter d'OpenStreetMap Pérou", + "description": "Suivez-nous sur Twitter à l'adresse {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap Pérou", + "description": "Nouvelles et ressources pour la communauté d'OpenStreetMap au Pérou" + }, + "OSM-Facebook": { + "name": "OpenStreetMap sur Facebook", + "description": "Mettez-nous un « j'aime » sur Facebook pour recevoir des nouvelles d'OpenStreetMap." + }, + "OSM-help": { + "name": "Aide d'OpenStreetMap", + "description": "Posez des questions et recevez des réponses sur le site de question-réponse de la communauté OSM.", + "extendedDescription": "Le site {url} s'adresse à tous ceux qui ont besoin d'aide sur OpenStreetMap. Que vous soyez un débutant ou que vous ayez une question technique, nous sommes là pour vous aider !" + }, + "OSM-Reddit": { + "name": "OpenStreetMap sur Reddit", + "description": "/r/openstreetmap/ est un super endroit pour en apprendre plus sur OpenStreetMap. Demandez-nous tout ce que vous voulez !" + }, + "OSM-Twitter": { + "name": "Fil Twitter d'OpenStreetMap", + "description": "Suivez-nous sur Twitter à l'adresse {url}" + }, + "OSMF": { + "name": "Fondation OpenStreetMap", + "description": "OSMF est une organisation à but non lucratif de droit britannique qui soutient le projet OpenStreetMap", + "extendedDescription": "OSMF supporte le projet OpenStreetMap en levant des fonds, en maintenant les serveurs d'OSM, en organisant la conférence annuelle State of the Map, et en coordonnant les volontaires qui permettent à OSM de fonctionner. Vous pouvez apporter votre aide et faire entendre votre voix dans OpenStreetMap en devenant membre d'OSMF ici: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Rejoignez-nous pendant 3 jours à Milan, Italie, pour la conférence mondiale annuelle d'OpenStreetMap, rassemblant toute la communauté pour discuter, partager et apprendre.", + "where": "Milan, Italie" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/gl.json b/vendor/assets/iD/iD/locales/gl.json index ce3d70b3a..25b73623d 100644 --- a/vendor/assets/iD/iD/locales/gl.json +++ b/vendor/assets/iD/iD/locales/gl.json @@ -1,5 +1,10 @@ { "gl": { + "icons": { + "information": "información", + "remove": "quitar", + "undo": "desfacer" + }, "modes": { "add_area": { "title": "Área", @@ -145,7 +150,9 @@ "vertex": "Conectada unha vía a outra.", "line": "Conectada unha vía a unha liña.", "area": "Conectada unha vía a unha área." - } + }, + "relation": "Estes elementos non se poden conectar porque teñen roles de relación contraditorios.", + "restriction": "Estes elementos non se poden conectar porque se danaría a relación \"{relation}\"." }, "disconnect": { "title": "Desconectar", @@ -163,7 +170,8 @@ "annotation": "Unidos {n} elementos.", "not_eligible": "Estes elementos non se poden unir.", "not_adjacent": "Estos elementos non se poden fusionar porque os seus extremos non están ligados.", - "restriction": "Estes elementos non se poden unir porque polo menos un delees é un membro dunha relación \"{relation}\".", + "restriction": "Estes elementos non se poden combinar porque se danaría a relación \"{relation}\".", + "relation": "Estes elementos non se poden combinar porque teñen roles de relación contraditorios.", "incomplete_relation": "Estes elementos non se poden unir porque cando menos un deles non se descargou completamente.", "conflicting_tags": "Estes elementos non se poden unir porque algunhas das súas etiquetas teñen valores contraditorios." }, @@ -291,6 +299,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Distancia", + "distance_up_to": "Ata {distance}", + "via": "A través de", + "via_node_only": "Só nodo", + "via_up_to_one": "Ata 1 vía", + "via_up_to_two": "Ata 2 vías" + }, + "help": { + "indirect": "(indirecta)", + "turn": { + "no_left_turn": "Prohibido xirar á esquerda {indirect}", + "no_right_turn": "Prohibido xirar á dereita {indirect}", + "no_u_turn": "Prohibido cambiar de sentido {indirect}", + "no_straight_on": "Prohibido seguir recto {indirect}", + "only_left_turn": "Obrigatorio xirar á esquerda {indirect}", + "only_right_turn": "Obrigatorio xirar á dereita {indirect}", + "only_u_turn": "Obrigatorio cambiar de sentido {indirect}", + "only_straight_on": "Obrigatorio seguir recto {indirect}", + "allowed_left_turn": "Permitido xirar á esquerda {indirect}", + "allowed_right_turn": "Permitido xirar á dereita {indirect}", + "allowed_u_turn": "Permitido cambiar de sentido {indirect}", + "allowed_straight_on": "Permitido seguir recto {indirect}" + }, + "from": "DESDE", + "via": "A TRAVÉS DE", + "to": "CARA A", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Fai clic para seleccionar un segmento {from}", + "select_from_name": "Fai clic para seleccionar {from} {fromName}", + "toggle": "Fai clic para \"{turn}\"" + } + }, "undo": { "tooltip": "Desfacer: {action}", "nothing": "Nada para desfacer." @@ -366,6 +410,7 @@ "key": "H", "title": "Historial", "selected": "{n} seleccionados", + "no_history": "Sen historial (elemento novo)", "version": "Versión", "last_edit": "Última edición", "edited_by": "Editado por", @@ -603,15 +648,20 @@ } }, "success": { - "edited_osm": "OSM editado!", "just_edited": "Acabas de editar OpenStreetMap!", - "view_on_osm": "Ver en OSM", - "facebook": "Compartir no Facebook", - "twitter": "Compartir no Twitter", - "google": "Compartir no Google+", - "help_html": "Os teus cambios deberían aparecer na capa \"Estándar\" nuns minutos. Outras capas, e determinados elementos, poden tardar máis tempo.", + "thank_you": "Grazas por mellorar o mapa", + "thank_you_location": "Grazas por mellorar o mapa por {where}", + "help_html": "Os teus cambios deberían aparecer na capa estándar de OpenStreetMap nuns minutos. Pódelle levar máis tempo actualizarse a outras capas e mapas de outros sitios.", "help_link_text": "Detalles", - "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" + "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", + "view_on_osm": "Ver cambios en OSM", + "changeset_id": "O teu conxunto de cambios é o {changeset_id}", + "like_osm": "Gústache OpenStreetMap? Comunícate con outras persoas:", + "more": "Máis", + "events": "Eventos", + "languages": "Idiomas: {languages}", + "missing": "Falta algo nesta lista?", + "tell_us": "Cóntanos!" }, "confirm": { "okay": "OK", @@ -689,6 +739,44 @@ "help": { "title": "Axuda", "welcome": "Benvido ao editor iD para [OpenStreetMap] (https://www.openstreetmap.org/). Con este editor podes actualizar OpenStreetMap directamente desde o teu navegador." + }, + "field": { + "restrictions": { + "title": "Axuda das restricións de xiro", + "about": { + "title": "Acerca de", + "about": "Este campo permíteche inspecionar e modificar restricións de xiro. Mostra un modelo da intersección seleccionada, incluíndo outras estradas conectadas próximas.", + "from_via_to": "Unha restrición de xiro sempre contén: unha **vía DESDE**, unha **vía CARA A** e un **nodo A TRAVÉS DE** ou unha ou varias **vías A TRAVÉS DE**.", + "maxdist": "A barra de desprazamento \"{distField}\" controla ata onde se vai buscar por máis estradas conectadas.", + "maxvia": "A barra de desprazamento \"{viaField}\" axusta cántas vías intermedias poden ser incluídas na busca. (Consello: canto máis simple, mellor)" + }, + "inspecting": { + "title": "Inspecionar", + "about": "Sitúate sobre calquera segmento **DESDE** para ver se ten restricións de xiro. Cada destino **CARA A** posible debuxarase cunha sombra coloreada indicando se existe algunha restrición de xiro.", + "from_shadow": "{fromShadow} **segmento DESDE**", + "allow_shadow": "{allowShadow} **CARA A permitido**", + "restrict_shadow": "{restrictShadow} **CARA A prohibido**", + "only_shadow": "{onlyShadow} **CARA A obrigatorio**", + "restricted": "\"Prohibido\" significa que hai unha restrición de xiro, por exemplo \"Prohibido xirar á esquerda\".", + "only": "\"Obrigatorio\" significa que un vehículo que entre na intersección só poderá ir por esa ruta, por exemplo \"Obrigatorio seguir recto\"." + }, + "modifying": { + "title": "Modificar", + "about": "Para modificar restricións de xiro, primeiro fai clic en calquera segmento **DESDE** para selecionalo. O segmento selecionado parpadeará, e todos os destinos **CARA A** posibles mostraranse como símbolos de xiro.", + "indicators": "Logo, fai clic nun símbolo de xiro para alternalo entre \"Permitido, \"Prohibido\" e \"Obrigatorio\".", + "allow_turn": "{allowTurn} **CARA A permitido**", + "restrict_turn": "{restrictTurn} **CARA A prohibido**", + "only_turn": "{onlyTurn} **CARA A obrigatorio**" + }, + "tips": { + "title": "Consellos", + "simple": "**Intenta usar restricións simples en lugar de restricións máis complexas.**", + "simple_example": "Por exemplo, se podes establecer o elemento intermedio simplemente cun nodo, evita facelo cunha vía.", + "indirect": "**Algunhas restricións mostran o texto \"(indirecta)\" e aparecen cunha cor máis tenue.**", + "indirect_example": "Estas restricións existen debido a outra restrición cercana. Por exemplo, unha restrición de \"Obrigatorio seguir recto\" creará indirectamente restricións de \"Prohibido xirar\" para tódalas demáis rutas da intersección.", + "indirect_noedit": "Non podes modificar restricións indirectas. En lugar diso, modifica a restrición directa cercana." + } + } } }, "intro": { @@ -1250,6 +1338,9 @@ "aeroway": { "label": "Tipo" }, + "agrarian": { + "label": "Produtos" + }, "amenity": { "label": "Tipo" }, @@ -1340,6 +1431,10 @@ "bunker_type": { "label": "Tipo" }, + "cables": { + "label": "Cables", + "placeholder": "1, 2, 3..." + }, "camera/direction": { "label": "Dirección (Grados en sentido horario)", "placeholder": "45, 90, 180, 270" @@ -1457,6 +1552,9 @@ "cycleway:right": "Lado dereito" } }, + "dance/style": { + "label": "Estilos de baile" + }, "date": { "label": "Data" }, @@ -1473,14 +1571,58 @@ "label": "Descrición completa" }, "devices": { + "label": "Dispositivos", "placeholder": "1, 2, 3..." }, "diaper": { "label": "Con área de cambia-cueiros " }, + "direction": { + "label": "Dirección (Graos en sentido horario)", + "placeholder": "45, 90, 180, 270" + }, + "direction_cardinal": { + "label": "Dirección", + "options": { + "E": "Leste", + "ENE": "Les-nordeste", + "ESE": "Les-sueste", + "N": "Norte", + "NE": "Nordeste", + "NNE": "Nor-nordeste", + "NNW": "Nor-noroeste", + "NW": "Noroeste", + "S": "Sur", + "SE": "Sueste", + "SSE": "Sur-sueste", + "SSW": "Sur-suroeste", + "SW": "Suroeste", + "W": "Oeste", + "WNW": "Oés-noroeste", + "WSW": "Oés-suroeste" + } + }, + "direction_clock": { + "label": "Sentido", + "options": { + "anticlockwise": "Sentido antihorario", + "clockwise": "Sentido horario" + } + }, + "direction_vertex": { + "label": "Sentido", + "options": { + "backward": "Atrás", + "both": "Ambos/todos", + "forward": "Adiante" + } + }, "display": { "label": "Presentación" }, + "distance": { + "label": "Distancia total" + }, "dock": { "label": "Tipo" }, @@ -1521,6 +1663,9 @@ "except": { "label": "Excepcións" }, + "faces": { + "label": "Caras" + }, "fax": { "label": "Fax", "placeholder": "+34 989 12 34 56" @@ -1549,6 +1694,9 @@ "wall": "Parede" } }, + "fitness_station": { + "label": "Tipo de equipamento" + }, "fixme": { "label": "Amáñame" }, @@ -1590,6 +1738,9 @@ "generator/type": { "label": "Tipo" }, + "government": { + "label": "Tipo" + }, "grape_variety": { "label": "Variedades de Uvas" }, @@ -1598,7 +1749,7 @@ "placeholder": "1-18" }, "handrail": { - "label": "Carretilla" + "label": "Pasamáns" }, "hashtags": { "label": "Cancelos suxeridos", @@ -1626,6 +1777,28 @@ "label": "Canastras", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "options": { + "equestrian": "Si", + "undefined": "Non" + } + }, + "horse_riding": { + "label": "Centro de equitación", + "options": { + "horse_riding": "Si", + "undefined": "Non" + } + }, + "horse_scale": { + "placeholder": "Difícil, perigoso..." + }, + "horse_stables": { + "options": { + "stables": "Si", + "undefined": "Non" + } + }, "iata": { "label": "IATA" }, @@ -1645,6 +1818,9 @@ "indoor": { "label": "Dentro" }, + "industrial": { + "label": "Tipo" + }, "information": { "label": "Tipo" }, @@ -1765,6 +1941,10 @@ "label": "Límite de velocidade", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "Límite de velocidade recomendado", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Estancia Máxima" }, @@ -1862,7 +2042,9 @@ "oneway": { "label": "Sentido único", "options": { + "alternating": "Alterno", "no": "Non", + "reversible": "Reversible", "undefined": "Suponse «Non»", "yes": "Si" } @@ -1870,7 +2052,9 @@ "oneway_yes": { "label": "Sentido único", "options": { + "alternating": "Alterno", "no": "Non", + "reversible": "Reversible", "undefined": "Suponse «Si»", "yes": "Si" } @@ -1907,10 +2091,10 @@ "label": "Tipos de pagamento" }, "phases": { + "label": "Fases", "placeholder": "1, 2, 3..." }, "phone": { - "label": "Teléfono", "placeholder": "+34 989 12 34 56" }, "piste/difficulty": { @@ -2218,6 +2402,9 @@ "surveillance/zone": { "label": "Zona de Vixilancia" }, + "switch": { + "label": "Tipo" + }, "tactile_paving": { "label": "Pavimento táctil" }, @@ -2278,6 +2465,14 @@ "traffic_signals": { "label": "Tipo" }, + "traffic_signals/direction": { + "label": "Sentido", + "options": { + "backward": "Atrás", + "both": "Ambos/todos", + "forward": "Adiante" + } + }, "trail_visibility": { "label": "Visibilidade do sendeiro", "options": { @@ -2291,6 +2486,7 @@ "placeholder": "Excelente, bo, malo..." }, "transformer": { + "label": "Tipo", "options": { "auto": "Autotransformador", "converter": "Conversor", @@ -2308,8 +2504,8 @@ "label": "Tipo", "placeholder": "Por defecto" }, - "vending": { - "label": "Tipo de Bens" + "usage_rail": { + "label": "Tipo de uso" }, "visibility": { "label": "Visibilidade", @@ -2328,6 +2524,18 @@ "volcano/type": { "label": "Tipo de volcán" }, + "voltage": { + "label": "Tensión" + }, + "voltage/primary": { + "label": "Tensión do primario" + }, + "voltage/secondary": { + "label": "Tensión do secundario" + }, + "voltage/tertiary": { + "label": "Tensión do terciario" + }, "wall": { "label": "Tipo" }, @@ -2357,6 +2565,7 @@ "label": "Wikipedia" }, "windings": { + "label": "Devanados", "placeholder": "1, 2, 3..." }, "windings/configuration": { @@ -2381,6 +2590,10 @@ "name": "Carteleira", "terms": "anuncio, publicidade, carteleira" }, + "advertising/column": { + "name": "Columna de publicidade", + "terms": "columna, publicidade, anuncios, cilindro" + }, "aerialway": { "name": "Vía aérea" }, @@ -2450,6 +2663,10 @@ "aeroway/terminal": { "name": "Terminal de aeroporto" }, + "allotments/plot": { + "name": "Parcela de horto urbano", + "terms": "horto urbano, horta urbana, horto, horta, parcela, cultivo, horta comunitaria, horto comunitario, terreo" + }, "amenity": { "name": "Instalacións" }, @@ -2479,7 +2696,7 @@ }, "amenity/bar": { "name": "Bar de copas", - "terms": "pub, bar, bar de copas, bebidas, alcohol" + "terms": "pub, bar, bar de copas, bebidas, alcohol, cantina, taberna, cervexa" }, "amenity/bbq": { "name": "Barbacoa/Grella", @@ -2502,15 +2719,20 @@ "terms": "bici, bicicleta, reparación, inchar" }, "amenity/biergarten": { - "name": "Xardín da cervexa" + "name": "Xardín da cervexa", + "terms": "cervexa, alcohol, biergarten" }, "amenity/boat_rental": { - "name": "Aluguer de botes" + "name": "Aluguer de botes", + "terms": "aluguer, bote, barca, lancha" }, "amenity/bureau_de_change": { "name": "Troco de divisas", "terms": "troco, cambio, divisa, moeda" }, + "amenity/bus_station": { + "name": "Estación de autobuses" + }, "amenity/cafe": { "name": "Cafetería", "terms": "cafetería, café, bar, tetería" @@ -2583,7 +2805,7 @@ "terms": "doutor, médico, clínica, saúde" }, "amenity/dojo": { - "name": "Dojo/academia de artes aarciais" + "name": "Dojo/academia de artes marciais" }, "amenity/drinking_water": { "name": "Fonte", @@ -2599,6 +2821,9 @@ "amenity/fast_food": { "name": "Comida rápida" }, + "amenity/ferry_terminal": { + "name": "Estación de ferry" + }, "amenity/fire_station": { "name": "Parque de bombeiros" }, @@ -2611,16 +2836,18 @@ }, "amenity/fuel": { "name": "Gasolineira", - "terms": "gasolineira, gasolina, gasoil, diésel, combustible, estación de servicio" + "terms": "gasolineira, gasolina, gasoil, diésel, combustible, estación de servicio, área de servicio" }, "amenity/grave_yard": { - "name": "Cemiterio" + "name": "Cemiterio", + "terms": "cemitero, cementerio, tumbas, panteón" }, "amenity/grit_bin": { "name": "Contenedor de sal" }, "amenity/hospital": { - "name": "Hospital" + "name": "Hospital", + "terms": "hospital, clínica, urxencias, sanidade, saúde, médico" }, "amenity/hunting_stand": { "name": "Stand de Caza" @@ -2642,15 +2869,24 @@ "terms": "biblioteca, libros, lectura" }, "amenity/marketplace": { - "name": "Mercado" + "name": "Mercado", + "terms": "mercado, mercadillo, plaza" + }, + "amenity/monastery": { + "name": "Zona de monasterio", + "terms": "monasterio, área de monasterio, igrexa, capela" }, "amenity/motorcycle_parking": { "name": "Aparcamento de motos", "terms": "aparcamento, aparcadoiro, parking, motos, motocicletas, ciclomotores" }, + "amenity/music_school": { + "name": "Escola de música", + "terms": "escola de música, conservatorio, academia, música, instrumentos" + }, "amenity/nightclub": { "name": "Pub", - "terms": "Pub, Discoteca, After, Sala de baile" + "terms": "Pub, Discoteca, After, Sala de baile, bailar, bebidas, alcohol, música" }, "amenity/nursing_home": { "name": "Residencia de anciáns" @@ -2663,7 +2899,7 @@ "name": "Entrada/Saída a garaxe de aparcamento" }, "amenity/parking_space": { - "name": "Espazo de Aparcamento" + "name": "Praza de aparcamento" }, "amenity/pavilion": { "name": "Pavillón" @@ -2722,7 +2958,7 @@ }, "amenity/pub": { "name": "Bar", - "terms": "Pub, bar, café, cafetería" + "terms": "Pub, bar, café, cafetería, bebidas, alcohol, cervexa, bar de tapas, pinchos" }, "amenity/public_bath": { "name": "Baño público", @@ -2735,12 +2971,16 @@ "amenity/ranger_station": { "name": "Estación de gardabosques" }, + "amenity/recycling": { + "name": "Contenedor de reciclaxe", + "terms": "reciclaxe, contenedor, lixo, basura, orgánico, plásticos, vidrio, punto limpo" + }, "amenity/recycling_centre": { "name": "Centro de Reciclaxe", "terms": "centro de reciclaxe, punto limpo" }, "amenity/register_office": { - "name": "Oficina de Rexistro" + "name": "Oficina do rexistro" }, "amenity/restaurant": { "name": "Restaurante", @@ -2757,10 +2997,12 @@ "name": "Depósito de chatarra" }, "amenity/shelter": { - "name": "Abrigo" + "name": "Abrigo", + "terms": "abrigo, refuxio, cuberto, gazebo" }, "amenity/shower": { - "name": "Ducha" + "name": "Ducha", + "terms": "duchas, baño, auga" }, "amenity/social_facility": { "name": "Axuda Social" @@ -2812,6 +3054,10 @@ "amenity/vending_machine/cigarettes": { "name": "Expendedora de tabaco" }, + "amenity/vending_machine/coffee": { + "name": "Máquina do café", + "terms": "café, máquina, expendedora, cafetera" + }, "amenity/vending_machine/condoms": { "name": "Expendedora de condóns" }, @@ -2821,17 +3067,25 @@ "amenity/vending_machine/excrement_bags": { "name": "Caca Can" }, + "amenity/vending_machine/food": { + "name": "Expendedora de comida" + }, + "amenity/vending_machine/ice_cream": { + "name": "Expendedora de xeados" + }, "amenity/vending_machine/news_papers": { "name": "Expendedora de xornais" }, "amenity/vending_machine/newspapers": { - "name": "Expendedora de xornais" + "name": "Expendedora de xornais", + "terms": "expendedora, xornais, revistas, periódicos" }, "amenity/vending_machine/parcel_pickup_dropoff": { "name": "Máquina expendedora de recollida/entrega de paquetes" }, "amenity/vending_machine/parking_tickets": { - "name": "Parquímetro" + "name": "Parquímetro", + "terms": "parquímetro, aparcamento, parking" }, "amenity/vending_machine/public_transport_tickets": { "name": "Expendedora de billetes de transporte público" @@ -2895,6 +3149,9 @@ "name": "Torre de caída", "terms": "caída, torre, atracción" }, + "attraction/maze": { + "name": "Laberinto" + }, "attraction/pirate_ship": { "name": "Barco pirata", "terms": "barco pirata, atracción" @@ -2951,7 +3208,7 @@ }, "barrier/fence": { "name": "Valado", - "terms": "Valado, reixa, valo, cercado" + "terms": "Valado, reixa, valo, cercado, alambrada, cerca" }, "barrier/gate": { "name": "Porta", @@ -2961,6 +3218,9 @@ "name": "Cobertura", "terms": "cobertura, seto, liña de arbustos" }, + "barrier/kerb": { + "name": "Bordillo" + }, "barrier/kissing_gate": { "name": "Porta Kissing" }, @@ -2975,25 +3235,31 @@ "terms": "escada, escaleira, valado, cerca, reixa" }, "barrier/toll_booth": { - "name": "Peaxe" + "name": "Peaxe", + "terms": "peaxe, cabina de peaxe, cabina de cobro" }, "barrier/wall": { "name": "Muro" }, "boundary/administrative": { - "name": "Límite administrativo" + "name": "Límite administrativo", + "terms": "límite administrativo, fronteira, término municipal" }, "building": { "name": "Edificio", "terms": "edificio, casa, inmoble, vivenda" }, "building/apartments": { - "name": "Apartamentos" + "name": "Apartamentos", + "terms": "apartamento, piso, vivenda, aloxamento" }, "building/barn": { "name": "Celeiro/Hórreo", "terms": "celeiro, hórreo, cabazo, cabaceiro, cabaceira, piorno" }, + "building/bungalow": { + "name": "Bungaló" + }, "building/bunker": { "name": "Bunker" }, @@ -3010,6 +3276,9 @@ "building/church": { "name": "Edificio de igrexa" }, + "building/civic": { + "name": "Edificio cívico" + }, "building/college": { "name": "Instituto de educación superior", "terms": "universidade, educación superior, facultade, colexio, escola, instituto, FP, formación profesional" @@ -3370,6 +3639,9 @@ "healthcare/blood_donation": { "name": "Doación de sangue" }, + "healthcare/laboratory": { + "name": "Laboratorio médico" + }, "highway": { "name": "Estrada" }, @@ -3619,7 +3891,8 @@ "terms": "vertedoiro, lixo, escombrera, basurero" }, "landuse/meadow": { - "name": "Prado" + "name": "Prado", + "terms": "prado, pasto, pradeira, herba" }, "landuse/military": { "name": "Zona militar" @@ -3667,7 +3940,7 @@ }, "landuse/quarry": { "name": "Canteira", - "terms": "canteira, pedra, minería" + "terms": "canteira, pedra, minería, mina, pedra, rocha, minerais" }, "landuse/railway": { "name": "Corredor ferroviario" @@ -3995,7 +4268,7 @@ }, "natural/heath": { "name": "Uceira", - "terms": "uceira, breixeira, moural, urceira, uzal, herba" + "terms": "uceira, breixeira, moural, urceira, uzal, herba, arbustos, gamallos" }, "natural/peak": { "name": "Cume", @@ -4016,7 +4289,8 @@ "terms": "pedregal, laxas, laxes, pedras, rochas" }, "natural/scrub": { - "name": "Matogueira" + "name": "Matogueira", + "terms": "matogueira, arbustos, toxeira, toxos, silveira, breña, coucheira, fraguiza, vedramio" }, "natural/spring": { "name": "Manancial", @@ -4052,7 +4326,7 @@ }, "natural/wood": { "name": "Bosque", - "terms": "bosque, fraga, foresta, monte" + "terms": "bosque, fraga, foresta, monte, árbores" }, "noexit/yes": { "name": "Sen saída" @@ -4158,6 +4432,10 @@ "place/village": { "name": "Vila" }, + "playground/sandpit": { + "name": "Areeiro", + "terms": "areeiro, areal, area, caixón de area" + }, "point": { "name": "Punto" }, @@ -4754,15 +5032,6 @@ "type/restriction/no_u_turn": { "name": "Prohibido o cambio de sentido" }, - "type/restriction/only_left_turn": { - "name": "Obrigatorio xirar á esquerda" - }, - "type/restriction/only_right_turn": { - "name": "Obrigatorio xirar á dereita" - }, - "type/restriction/only_straight_on": { - "name": "Obrigatorio continuar recto" - }, "type/route": { "name": "Ruta" }, @@ -4867,25 +5136,46 @@ }, "DigitalGlobe-Premium": { "attribution": { - "text": "Termos & Autoachegas" + "text": "Termos e comentarios" }, "description": "Imaxes de satélite Premium DigitalGlobe.", "name": "Imaxes DigitalGlobe Premium" }, + "DigitalGlobe-Premium-vintage": { + "attribution": { + "text": "Termos e comentarios" + }, + "description": "Límites das imaxes e datas de captura. As etiquetas aparecen a un nivel de zoom de 13 e superior.", + "name": "Antigüidade das imaxes DigitalGlobe Premium" + }, "DigitalGlobe-Standard": { "attribution": { - "text": "Termos & Autoachegas" + "text": "Termos e comentarios" }, - "description": "Imaxes de satélite Standard DigitalGlobe.", + "description": "Imaxes de satélite DigitalGlobe estándar.", "name": "Imaxes DigitalGlobe Standard" }, + "DigitalGlobe-Standard-vintage": { + "attribution": { + "text": "Termos e comentarios" + }, + "description": "Límites das imaxes e datas de captura. As etiquetas aparecen a un nivel de zoom de 13 e superior.", + "name": "Antigüidade das imaxes DigitalGlobe Standard" + }, "EsriWorldImagery": { "attribution": { - "text": "Termos & Autoachegas" + "text": "Termos e comentarios" }, - "description": "Imaxes mundiais Esri", + "description": "Imaxes mundiais Esri.", "name": "Imaxes mundiais Esri" }, + "EsriWorldImageryClarity": { + "attribution": { + "text": "Termos e comentarios" + }, + "description": "Arquivo de imaxes de Esri que pode que sexan máis claras e máis precisas que a súa capa por defecto.", + "name": "Imaxes mundiais Esri (Clarity) Beta" + }, "MAPNIK": { "attribution": { "text": "© contribuidores do OpenStreetMap, CC-BY-SA" @@ -4895,7 +5185,7 @@ }, "Mapbox": { "attribution": { - "text": "Termos & Autoachegas" + "text": "Termos e comentarios" }, "description": "Imaxes satélite e aéreas.", "name": "Mapbox Satélite" @@ -4916,7 +5206,7 @@ "attribution": { "text": "© Geofabrik GmbH, contribuidores do OpenStreetMap, CC-BY-SA" }, - "name": "OSM Inspector: Autoestradas" + "name": "OSM Inspector: Estradas" }, "OSM_Inspector-Multipolygon": { "attribution": { @@ -4940,7 +5230,7 @@ "attribution": { "text": "© Geofabrik GmbH, contribuidores do OpenStreetMap, CC-BY-SA" }, - "name": "OSM Inspector: Lapelas" + "name": "OSM Inspector: Etiquetado" }, "Waymarked_Trails-Cycling": { "name": "Marcador de Pistas: Ciclismo" @@ -4961,7 +5251,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Mapa base para Austria, baseado en datos do goberno.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -4979,7 +5268,7 @@ }, "mapbox_locator_overlay": { "attribution": { - "text": "Termos & Autoachegas" + "text": "Termos e comentarios" }, "description": "Amosa os elementos importantes para axudarche a orientarte.", "name": "Superposición de Localizador" @@ -5011,33 +5300,56 @@ }, "qa_no_address": { "attribution": { - "text": "Simon Poole, Achegas ©contribuidores do OpenStreetMap" + "text": "Simon Poole, Datos ©contribuidores do OpenStreetMap" }, "name": "QA Sen Enderezos" }, "skobbler": { "attribution": { - "text": "© Tiles: skobbler información Mapa: contribuidores do OpenStreetMap" + "text": "© Teselas: skobbler Datos do mapa: contribuidores do OpenStreetMap" }, "name": "skobbler" }, "stamen-terrain-background": { "attribution": { - "text": "Tiles do mapa por Stamen Design, baixo CC BY 3.0" + "text": "Teselas do mapa por Stamen Design, baixo CC BY 3.0. Datos por OpenStreetMap, baixo ODbL" }, "name": "Terreo Stamen" }, "tf-cycle": { "attribution": { - "text": "Mapas © Thunderforest, Información © contribuidores do OpenStreetMap" + "text": "Mapas © Thunderforest, Datos © contribuidores do OpenStreetMap" }, - "name": "Thunderforest OpenCycleMap" + "name": "OpenCycleMap de Thunderforest" }, "tf-landscape": { "attribution": { - "text": "Mapas © Thunderforest, Información © contribuidores do OpenStreetMap" + "text": "Mapas © Thunderforest, Datos © contribuidores do OpenStreetMap" }, - "name": "Paisaxe Thunderforest" + "name": "Landscape de Thunderforest" + } + }, + "community": { + "osm-mg-facebook": { + "name": "Grupo de Facebook do OpenStreetMap na illa de Madagascar" + }, + "OSM-ES-mailinglist": { + "name": "Lista de correo talk-es", + "description": "Unha lista de correo para debatir sobre o OpenStreetMap en España" + }, + "OSM-ES-telegram": { + "name": "@OSMes no Telegram", + "description": "Chat de Telegram do OpenStreetMap España" + }, + "OSM-AR-twitter": { + "description": "Seguenos no Twitter na seguinte ligazón {url}" + }, + "OSM-br-twitter": { + "description": "Seguenos no Twitter na seguinte ligazón {url}" + }, + "OSM-Reddit": { + "name": "OpenStreetMap no Reddit", + "description": "/r/openstreetmap/ é un bo sitio para aprender máis sobre OpenStreetMap. Pregúntanos calquera cousa!" } } } diff --git a/vendor/assets/iD/iD/locales/he.json b/vendor/assets/iD/iD/locales/he.json index bb895bab1..1d506872b 100644 --- a/vendor/assets/iD/iD/locales/he.json +++ b/vendor/assets/iD/iD/locales/he.json @@ -1,5 +1,10 @@ { "he": { + "icons": { + "information": "מידע", + "remove": "הסר", + "undo": "בטל" + }, "modes": { "add_area": { "title": "שטח", @@ -70,7 +75,7 @@ "line": "להפוך קו זה למעגלי.", "area": "להפוך איזור זה למעגלי." }, - "key": "ע", + "key": "O", "annotation": { "line": "הקו עוגל", "area": "האיזור עוגל." @@ -85,7 +90,7 @@ "line": "ריבוע פינות בקו זה", "area": "ריבוע פינות באיזור זה" }, - "key": "ר", + "key": "S", "annotation": { "line": "הפיכת הקצוות של קו לריבוע.", "area": "הפיכת הקצוות של שטח לריבוע." @@ -97,7 +102,7 @@ "straighten": { "title": "יישור", "description": "יישור הקו הזה.", - "key": "ש", + "key": "S", "annotation": "יישור קו.", "too_bendy": "אי אפשר ליישר את הקו הזה כיוון שהוא יותר מדי מכופף.", "connected_to_hidden": "אי אפשר ליישר את הקו הזה כי הוא מחובר לתכונה נסתרת." @@ -145,12 +150,14 @@ "vertex": "חיבור של דרך לדרך אחרת.", "line": "חיבור של דרך לקו.", "area": "חיבור של דרך לשטח." - } + }, + "relation": "לא ניתן לחבר תכונות אלה כיוון שיש להן תפקידים סותרים ביחס.", + "restriction": "לא ניתן לחבר תכונות אלה כיוון שזה עשוי להרוס יחס מסוג „{relation}”." }, "disconnect": { "title": "ניתוק", "description": "ניתוק הקווים/השטחים האלה זה מזה.", - "key": "נ", + "key": "D", "annotation": "קווים/שטחים מנותקים.", "not_connected": "אין כאן מספיק קווים/שטחים לניתוק.", "connected_to_hidden": "אי אפשר לנתק את זה עקב החיבור לתכונה נסתרת.", @@ -159,11 +166,12 @@ "merge": { "title": "מיזוג", "description": "מיזוג התכונות האלה.", - "key": "ז", + "key": "C", "annotation": "{n} תכונות מוזגו.", "not_eligible": "אי אפשר למזג תכונות אלו.", "not_adjacent": "אי אפשר למזג את התכונות האלו כיוון שנקודות הקצה שלהן אינן מחוברות.", - "restriction": "אי אפשר למזג את התכונות האלה כיוון שלפחות אחת מהן חברה ביחס „{relation}”.", + "restriction": "לא ניתן למזג תכונות אלו כיוון שהמיזוג יפגע ביחס „{relation}”.", + "relation": "לא ניתן למזג תכונות אלו כיוון שיש להן תפקידים סותרים ביחס.", "incomplete_relation": "אי אפשר למזג את התכונות האלו כיוון שלפחות אחת מהן לא התקבלה לחלוטין.", "conflicting_tags": "אי אפשר למזג את התכונות האלה כיוון שלחלק מהתגיות שלהן יש ערכים סותרים." }, @@ -173,7 +181,7 @@ "single": "העברת התכונה הזאת למיקום שונה.", "multiple": "העברת התכונות האלו למיקום שונה." }, - "key": "ע", + "key": "M", "annotation": { "point": "העברת נקודה.", "vertex": "העברת מפרק בדרך.", @@ -196,8 +204,8 @@ }, "reflect": { "title": { - "long": "שקף לאורך", - "short": "שקף לרוחב" + "long": "שקף את הארוך", + "short": "שקף את הקצר" }, "description": { "long": { @@ -212,6 +220,28 @@ "key": { "long": "T", "short": "Y" + }, + "annotation": { + "long": { + "single": "תכונה התהפכה לאורך הציר הארוך שלה.", + "multiple": "מספר תכונות התהפכו סביב הציר הארוך שלהן." + }, + "short": { + "single": "תכונה התהפכה לאורך הציר הארוך שלה.", + "multiple": "מספר תכונות התהפכו לאורך הציר הקצר שלהן." + } + }, + "incomplete_relation": { + "single": "לא ניתן להפוך תכונה זו כיוון שטרם התקבלה לחלוטין.", + "multiple": "לא ניתן להפוך תכונות אלו כיוון שטרם התקבלו לחלוטין." + }, + "too_large": { + "single": "לא ניתן להפוך תכונה זו כיוון שאין די שטח גלוי ממנה.", + "multiple": "לא ניתן להפוך תכונות אלו כיוון שאין די שטח גלוי מהן." + }, + "connected_to_hidden": { + "single": "לא ניתן להפוך תכונה זו כיוון שהיא מקושרת לתכונה נסתרת.", + "multiple": "לא ניתן להפוך תכונות אלו כיוון שחלקן מקושרות לתכונות נסתרות." } }, "rotate": { @@ -220,7 +250,7 @@ "single": "הטיית התכונה הזאת מסביב לנקודת המרכז שלה.", "multiple": "הטיית התכונות האלו סביב נקודות המרכז שלהן." }, - "key": "ט", + "key": "R", "annotation": { "line": "הטיית קו.", "area": "הטיית שטח.", @@ -242,7 +272,7 @@ "reverse": { "title": "היפוך", "description": "הפיכת הכיוון של הקו הזה.", - "key": "פ", + "key": "V", "annotation": "קו התהפך." }, "split": { @@ -252,7 +282,7 @@ "area": "פיצול הגבול של השטח הזה לשניים.", "multiple": "פיצול הקווים/שטח של המפרק הזה לשניים." }, - "key": "צ", + "key": "X", "annotation": { "line": "פיצול קו.", "area": "פיצול גבול שטח.", @@ -275,7 +305,7 @@ "distance_up_to": "עד {distance}", "via": "דרך", "via_node_only": "מפרק בלבד", - "via_up_to_one": "עד דרך אחת", + "via_up_to_one": "עד דרך 1", "via_up_to_two": "עד 2 דרכים" }, "help": { @@ -297,6 +327,9 @@ "from": "מכיוון", "via": "דרך", "to": "אל", + "from_name": "{from}: {fromName}", + "from_name_to_name": "{from}: {fromName}, {to}: {toName}", + "via_names": "{via}: {viaNames}", "select_from": "יש ללחוץ כדי לבחור מקטע {from}", "select_from_name": "יש ללחוץ כדי לבחור {from} {fromName}", "toggle": "יש ללחוץ לטובת „{turn}”" @@ -357,9 +390,9 @@ "truncated_list": "עריכות מאת {users} ו־{count} נוספים" }, "info_panels": { - "key": "ח", + "key": "I", "background": { - "key": "ר", + "key": "B", "title": "רקע", "zoom": "תקריב", "vintage": "סגנון מיושן", @@ -374,9 +407,10 @@ "hide_vintage": "הסתרת סגנון מיושן" }, "history": { - "key": "ה", + "key": "H", "title": "היסטוריה", "selected": "{n} נבחרו", + "no_history": "ללא היסטוריה (תכונה חדשה)", "version": "גרסה", "last_edit": "עריכה אחרונה", "edited_by": "נערך על ידי", @@ -385,12 +419,12 @@ "link_text": "היסטוריה ב־openstreetmap.org" }, "location": { - "key": "ק", + "key": "L", "title": "מיקום", "unknown_location": "מיקום לא ידוע" }, "measurement": { - "key": "ד", + "key": "M", "title": "מדידה", "selected": "{n} נבחרו", "geometry": "צורה", @@ -469,13 +503,14 @@ "background": { "title": "רקע", "description": "הגדרות רקע", - "key": "ר", + "key": "B", "backgrounds": "רקעים", "none": "אין", "best_imagery": "מקור התמונה המוכר והטוב ביותר למיקום זה", "switch": "חזרה לרקע זה", "custom": "התאמה אישית", "custom_button": "עריכת רקע בהתאמה אישית", + "custom_prompt": "נא להקליד כתובת תבנית. האסימונים התקניים הם:\n - {zoom} או {z}, {x}, {y} לסכימת אריחים מסוג Z/X/Y\n - {‎-y} או {ty} לנקודות ציון הפוכות בציר Y בסגנון TMS\n - {u} לסכימת אריחים מרובעת (QuadTile)\n - {switch:a,b,c} למעבר בין DNS של שרתים\n\nדוגמה:\n{example}", "overlays": "שכבות על", "imagery_source_faq": "פרטי צילום / דיווח על תקלה", "reset": "איפוס", @@ -495,7 +530,7 @@ "map_data": { "title": "נתוני מפה", "description": "נתוני מפה", - "key": "נ", + "key": "F", "data_layers": "שכבות נתונים", "layers": { "osm": { @@ -562,7 +597,7 @@ "wireframe": { "description": "ללא מילוי (מסגרת דקיקה)", "tooltip": "הפעלת מצב מסגרת דקיקה מאפשר לך לראות בקלות את התמונה ברקע.", - "key": "ד" + "key": "W" }, "partial": { "description": "מילוי חלקי", @@ -613,14 +648,20 @@ } }, "success": { - "edited_osm": "בוצעה עריכה ב־OSM!", "just_edited": "הרגע ערכת את OpenStreetMap!", - "view_on_osm": "צפייה ב־OSM", - "facebook": "שיתוף בפייסבוק", - "twitter": "שיתוף בטוויטר", - "google": "שיתוף ב־Google+‎", - "help_html": "השינויים שלך אמורים להופיע בשכבה ה„תקנית” בעוד מספר דקות. שכבות אחרות ותכונות מסוימות עשויות לארוך זמן רב יותר.", - "help_link_text": "פרטים" + "thank_you": "תודה לך על שיפור המפה.", + "thank_you_location": "תודה לך על שיפור המפה באזור {where}.", + "help_html": "השינויים שלך אמורים להופיע ב־OpenStreetMap בעוד מספר דקות. במפות אחרות השינויים עשויים להופיע בעיכוב קל.", + "help_link_text": "פרטים", + "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", + "view_on_osm": "הצגת השינויים ב־OSM", + "changeset_id": "ערכת השינויים שלך מס׳: {changeset_id}", + "like_osm": "OpenStreetMap אתה אוהבך? ניתן להתחבר לחברים נוספים:", + "more": "עוד", + "events": "אירועים", + "languages": "שפות: {languages}", + "missing": "משהו חסר ברשימה הזו?", + "tell_us": "נשמח לשמוע!" }, "confirm": { "okay": "אישור", @@ -687,14 +728,14 @@ }, "openstreetcam_images": { "tooltip": "תמונות בהתמקדות על רחובות מ־OpenStreetCam", - "title": "שכבת תמרורים (OpenStreetCam)" + "title": "שכבת תמונות קרקע (OpenStreetCam)" }, "openstreetcam": { "view_on_openstreetcam": "צפייה בתמונה הזאת ב־OpenStreetCam" }, "help": { "title": "עזרה", - "key": "ע", + "key": "H", "help": { "title": "עזרה", "welcome": "ברוך בואך לעורך iD עבור [OpenStreetMap](https://www.openstreetmap.org/). עם העורך הזה ניתן לעדכן את OpenStreetMap ישירות מהדפדפן שלך.", @@ -722,11 +763,16 @@ "select_right_click": "יש ללחוץ {rightclick} לחיצה ימנית על תכונה כדי להציג את תפריט העריכה, שמציג את הפקודות הזמינות, כגון הטיה, הזזה ומחיקה.", "multiselect_h": "בחירה במגוון", "multiselect_shift_click": "`{shift}`+{leftclick} לחיצה שמאלית כדי לבחור כמה תכונות יחדיו. אפשרות זו מקלה על העברה או מחיקה של מגוון פריטים.", + "multiselect_lasso": "דרך נוספת לבחור מספר תכונות היא להחזיק את המקש `{shift}` ואז ללחוץ להחזיק את כפתור העכבר השמאלי ולגרור את העכבר כדי לצייר בחירה בצורת פלצור. כל הנקודות בתוך אזור הפלצור תיבחרנה.", "undo_redo_h": "ביטול ושחזור ביטול", + "undo_redo": "העריכות שלך נשמרות מקומית בדפדפן שלך עד לבחירתך בשמירתן לשרת של OpenStreetMap. ניתן לבטל עריכות על ידי לחיצה על הכפתור {undo} **ביטול** וניתן ", "save_h": "שמירה", "save": "יש ללחוץ על {save} **שמירה** כדי לסיים את העריכות שלך ולשלוח אותן ל־OpenStreetMap. מומלץ לזכור לשמור את עבודתך לעתים תכופות!", + "save_validation": "במסך השמירה תהיה לך אפשרות לסקור את מה שעשית. iD יבצע בדיקות בסיסיות לאיתור מידע וחסר ועשוי גם להציג הצעות ואזהרות מועילות אם משהו לא נראה כשורה.", "upload_h": "העלאה", + "upload": "בטרם העלאת השינויים שלך עליך לכתוב [הערה לערכת השינויים](https://wiki.openstreetmap.org/wiki/Good_changeset_comments). לאחר מכן יש ללחוץ על **העלאה** כדי לשלוח את השינויים שלך ל־OpenStreetMap, שם הם ימוזגו למפה ויהיו גלויים לעיני כל.", "backups_h": "גיבויים אוטומטיים", + "backups": "אם אין לך אפשרות לסיים את העריכות שלך בבת אחת, למשל: המחשב קרס או שלשונית הדפדפן שלך נסגרה, העריכות שלך עדיין נשמרות באזור האחסון שבדפדפן שלך. ניתן לחזור בהמשך (באותו הדפדפן והמחשב) ו־iD יציע לך לשחזר את עבודתך.", "keyboard_h": "קיצורי מקלדת", "keyboard": "ניתן לצפות ברשימה של קיצורי המקלדת על ידי לחיצה על המקש ‚?’." }, @@ -765,16 +811,25 @@ "add_line_draw": "עכשיו, עליך להציב את סמן העכבר על מיקום תחילת הקו המיועד {leftclick} וללחוץ עם המקש השמאלי או ללחוץ על המקש ‚רווח’ כדי להתחיל להציב מפרקים לאורך הקו. ניתן להמשיך ולהוסיף עוד מפרקים על ידי לחיצה עם העכבר או על מקש ה‚רווח’. בעת הציור, ניתן להתקרב או לגרור את המפה כדי להוסיף עוד פרטים.", "add_line_finish": "כדי לסיים ציור קו, יש ללחוץ על `{return}` או ללחוץ שוב על המפרק האחרון.", "modify_line_h": "עריכת קווים", + "modify_line_dragnode": "לעתים מופיעים קווים בעלי צורה שגויה, למשל, דרך שאינה תואמת לצילום הרקע. כדי לערוך את צורת הקו, ראשית יש ללחוץ {leftclick} לחיצה שמאלית כדי לבחור אותו. כל מפרקי הקו יופיעו בתור עיגולים קטנים. כעת ניתן לגרור את המפרקים האלה למיקומים נכונים יותר.", + "modify_line_addnode": "ניתן גם ליצור מפרקים חדשים לאורכו של קו בין אם על ידי {leftclick}**x2** לחיצה כפולה על הקו כולו או על ידי גרירת המשולשים הקטנים בנקודות האמצע שבין המפרקים.", "connect_line_h": "חיבור קווים", "connect_line": "חיבור כבישים כראוי חשוב לתפעול המפה וגם כדי לספק הנחיות לנהיגה בעזרת המפה.", "connect_line_display": "החיבורים בין כבישים מסומנים בעיגול אפור. נקודות הקצה של הקווים מסומנים בעיגולים לבנים גדולים יותר אם הם לא מחוברים לשום דבר.", + "connect_line_drag": "כדי לחבר קו לתכונה אחרת, יש לגרור את אחד ממפרקי הקו לתכונה האחרת עד שהתכונות נצמדות זו לזו. עצה: ניתן להחזיק את המקש `{alt}` כדי למנוע מהמפרקים להתחבר לתכונות אחרות.", "connect_line_tag": "אם ידוע לך שבנקודת החיבור יש רמזורים או מעברי חציה, ניתן להוסיף אותם על ידי בחירת הצומת המחבר ובחירת סוג התכונה המתאים באמצעות עורך התכונות.", "disconnect_line_h": "ניתוק קווים", + "disconnect_line_command": "כדי לנתק דרך מתכונה אחרת, יש ללחוץ עם {rightclick} מקש ימני על המפגש ביניהם ולבחור בפקודה {disconnect} **ניתוק** מתפריט העריכה.", "move_line_h": "הזזת קווים", - "delete_line_h": "מחיקת קווים" + "move_line_command": "כדי להעביר קו שלם, יש ללחוץ עם {rightclick} כפתור ימני על הקו ולבחור בפקודה **העברה** מתפריט העריכה. לאחר מכן יש להעביר את העכבר וללחוץ {leftclick} לחיצה שמאלית כדי להציב את הקו במיקום חדש.", + "move_line_connected": "קווים שמחוברים לתכונות אחרות יוסיפו להיות מחוברים גם עם העברת הקו למיקום החדש. יתכן ש־iD ימנע ממך להעביר קו דרך קו מחובר אחר.", + "delete_line_h": "מחיקת קווים", + "delete_line": "אם קיים קו שגוי לחלוטין, למשל דרך שאינה קיימת במציאות, אין שום מניעה למחוק אותה. כדאי לנקוט משנה זהירות בעת מחיקת תכונות: צילומי הרקע המופיעים עשויים להיות בלתי עדכניים וכביש שנראה שגוי יכול להיות פשוט חדש.", + "delete_line_command": "כדי למחוק קו, יש ללחוץ עם {rightclick} מקש ימני על הקו כדי לבחור אותו ולהציג את תפריט העריכה, לאחר מכן יש להשתמש בפקודה {delete} **מחיקה**." }, "areas": { "title": "שטחים", + "intro": "*שטחים* משמשים להצגת גבולות של תכונות כגון אגמים, בניינים ואזורי מגורים. יש לסמן שטחים לאורך גבולות התכונה המיוצגת, למשל, מסביב לבסיס הבניין.", "point_or_area_h": "נקודות או שטחים?", "point_or_area": "תכונות רבות ניתנות לייצוג כנקודות או שטחים. עליך למפות מבנים וקווי מתאר של נכסים כשטחים ככל הניתן. יש להציב נקודות בתוך שטח בניין כדי לייצג עסקים, שירותים ותכונות נוספות שנמצאות בתוך הבניין.", "add_area_h": "הוספת שטחים", @@ -782,51 +837,101 @@ "add_area_draw": "עכשיו, עליך להציב את סמן העכבר על אחת מהפינות של התכונה {leftclick} וללחוץ עם המקש השמאלי או ללחוץ על המקש ‚רווח’ כדי להתחיל להציב מפרקים מסביב למסגרת החיצונית של האזור. ניתן להמשיך ולהוסיף עוד מפרקים על ידי לחיצה עם העכבר או על מקש ה‚רווח’. בעת הציור, ניתן להתקרב או לגרור את המפה כדי להוסיף עוד פרטים.", "add_area_finish": "כדי לסיים ציור שטח, יש ללחוץ על `{return}` או ללחוץ שוב על המפרק הראשון או האחרון.", "square_area_h": "ריבוע פינות", + "square_area_command": "לתכונות שטח רבות כגון בניינים יש פינות מרובעות. כדי לשנות פינות של שטח, יש ללחוץ עם {rightclick} כפתור ימני על קצה השטח ולבחור בפקודה {orthogonalize} **ריבוע** מתפריט העריכה.", "modify_area_h": "שינוי שטחים", - "delete_area_h": "מחיקת שטחים" + "modify_area_dragnode": "לעתים מופיעים שטחים בעלי צורה שגויה, למשל, בניין שאינו תואם לצילום הרקע. כדי לערוך את צורת השטח, ראשית יש ללחוץ {leftclick} לחיצה שמאלית כדי לבחור אותו. כל מפרקי השטח יופיעו בתור עיגולים קטנים. כעת ניתן לגרור את המפרקים האלה למיקומים נכונים יותר.", + "modify_area_addnode": "ניתן ליצור מפרקים חדשים לאורך שטח מסוים או עם {leftclick}**×2** לחיצה כפולה על מסגרת השטח או על ידי גרירת המשולשים הקטנים בנקודות המרכז בין המפרקים.", + "delete_area_h": "מחיקת שטחים", + "delete_area": "אם קיים שטח שלם שגוי, למשל בניין שלא קיים במציאות, אפשר למחוק אותו. יש לנקוט במשנה זהירות בעת מחיקת תכונות - תמונות הרקע בהן נעשה שימוש עשויות להיות מיושנות ובניינים שנראים בעייתיים עשויים להיות חדשים.", + "delete_area_command": "כדי למחוק שטח, יש ללחוץ עם {rightclick} כפתור ימני על השטח כדי לבחור אותו ולהציג את תפריט העריכה, לאחר מכן יש להשתמש בפקודה {delete} **מחיקה**." }, "relations": { "title": "יחסים", "intro": "*יחס* הוא סוג מיוחד של תכונה ב־OpenStreetMap המקבצת תחתיה תכונות אחרות. התכונות ששייכות ליחס נקראות *חברות* ולכל חברה יכול להיות *תפקיד* ביחס.", "edit_relation_h": "עריכת יחסים", + "edit_relation": "בתחתית עורך התכונות, ניתן להרחיב את האגף „כל היחסים” כדי לראות אם התכונה הנבחרת חברה בקשרים כלשהם. לאחר מגן ניתן ללחוץ על היחס כדי לבחור ולערוך אותו.", + "edit_relation_add": "כדי להוסיף תכונה ליחס, יש לבחור את התכונה ואז ללחוץ על הכפתור {add} הוספה באגף „כל היחסים” של עורך התכונות. ניתן לבחור מרשימה של יחסים קרובים או לבחור באפשרות „יחס חדש…”.", + "edit_relation_delete": "ניתן ללחוץ על הכפתור {delete} **מחיקה** כדי להסיר את התכונה הנבחרת מהיחס, היחס יימחק אוטומטית.", "maintain_relation_h": "שימור יחסים", + "maintain_relation": "על פי רוב, iD ישמור על הקשרים אוטומטית בזמן העריכה. עליך לטפל במצבים בהם ישנן תכונות שהוחלפו שהן חלק מיחסים. למשל, מחיקת קטע מדרך וציור קטע דרך חדש שיחליף אותו, עליך להוסיף את הקטע החדש לאותם היחסים (נתיבים, הגבלות פניה וכו׳) כמו המקור.", "relation_types_h": "סוגי יחסים", "multipolygon_h": "רבי־מצולעים", "multipolygon": "יחס *רב־מצולע* הוא קבוצה של תכונה *חיצונית* אחת או יותר ותכונה פנימית אחת או יותר. התכונות החיצוניות מגדירות את הגבולות החיצוניים של הרב־מצולע ואילו התכונות הפנימיות מגדירות תת־שטחים או חורים שנחתכו מחוץ לרב־מצולע.", "multipolygon_create": "כדי ליצור רב־מצולע, למשל: בניין עם חור, יש לצייר את הגבולות החיצוניים של השטח ואת הגבול הפנימי כקו או סוג אחר של שטח. לאחר מכן `{shift}`+{leftclick} עם לחיצה שמאלית כדי לבחור את שתי התכונות, {rightclick} לחיצה ימנית כדי להציג את תפריט העריכה ואז לבחור את הפקודה {merge} **מיזוג**.", "multipolygon_merge": "מיזוג מגוון קווים או שטחים יגרום ליצירת קשר רב־מצולע חדש שמכיל בתוכו את כל השטחים הנבחרים כחברים בו. iD יבחר את התפקידים הפנימיים והחיצוניים אוטומטית בהתחשב באילו תכונות כלולות בתוך תכונות אחרות.", "turn_restriction_h": "הגבלות פנייה", + "turn_restriction": "יחס *הגבלת פנייה* הוא קבוצה של מגוון מקטעי דרך שנפגשים. הגבלות פנייה מורכבות מדרך ה*מוצא*, מפרק או דרכי *מעבר* ודרך *יעד*.", + "turn_restriction_field": "כדי לערוך הגבלות פנייה, יש לבחור את הצומת בה דרך אחת או יותר נפגשות. עורך התכונות יציג שדה „הגבלות פנייה” שמכיל את דגם הצומת.", + "turn_restriction_editing": "בשדה „הגבלות פנייה” יש ללחוץ על דרך ה„מוצא” ולראות האם פניות מותרות או מוגבלות לכל אחת מדרכי ה„יעד”. ניתן ללחוץ על סמלי הפנייה כדי להחליף בין מורשה למוגבל. iD ייצור קשרים אוטומטית ויגדיר מוצא, מעבר ויעד לכללים בהתאם לבחירותיך.", "route_h": "נתיבים", - "boundary_h": "גבולות" + "route": "יחס *מסלול* הוא קבוצה של תכונה אחת או יותר מסוג קו שמייצרות רשת של מסלולים, כגון מסלולי אוטובוס, מסלול רכבת או כביש מהיר.", + "route_add": "כדי להוסיף תכונה ליחס מסלול, יש לבחור את התכונה ולגלול למטה לאגף „כל היחסים” בעורך התכונות ואז ללחוץ על הכפתור {plus} הוספה כדי להוסיף את התכונה הזאת ליחס קיים בסביבה או ליחס חדש.", + "boundary_h": "גבולות", + "boundary": "יחס *גבול* הוא קבוצה של תכונה אחת או יותר מסוג קו שמייצרות גבול מנהלי יחד.", + "boundary_add": "כדי להוסיף תכונה ליחס גבול, יש לבחור את התכונה ולגלול לאגף „כל היחסים” בעורך התכונות ואז ללחוץ על {plus} כפתור ההוספה כדי להוסיף את התכונה הזאת ליחס קרוב נוכחי או ליחס חדש." }, "imagery": { "title": "תמונות רקע", + "intro": "צילום הרקע שמופיע מתחת לנתוני המפה הוא מקור חשוב למיפוי. התמונה הזאת יכולה להיות צילומי אוויר שנאספו דרך לוויינים, מטוסים ורחפנים או סריקת מפות היסטוריות או נתוני מקור חופשיים שזמינים לציבור הרחב.", "sources_h": "מקורות תמונה", "choosing": "כדי לראות אילו מקורות מפות זמינים לעריכה, יש ללחוץ על הכפתור {layers} **הגדרות רקע** לצד המפה.", + "sources": "כבררת מחדל נבחרת שכבת לוויין של [מפות Bing](https://www.bing.com/maps/) כתמונת הרקע. בהתאם למיקום העריכה ישנם מקורות צילומי אוויר אחרות. חלקן עשויות להיות חדשות יותר או באיכות גבוהה יותר כך שתמיד כדאי לבדוק ולראות איזו שכבה מעניקה את נוחות המיפוי המרבית.", "offsets_h": "שינוי היסט תמונה", + "offset": "צילומי הרקע לעתים חוטאים לדיוק נתוני המפה. אם דרכים ובניינים רבים סוטים מעט הצידה, כנראה שהצילום שגוי, לכן, לא כדאי להעביר את כולם כדי להתאים לרקע. במקום, ניתן להתאים את הרקע כדי שיתאים לנתונים הקיימים על ידי הרחבת האגף „שינוי היסט תמונה” בתחתית חלונית הגדרות הרקע.", "offset_change": "יש ללחוץ על המשולשים הקטנים כדי להתאים את היסט תמונת הרקע בצעדים קטנים, לחלופין להחזיק את סמן העכבר השמאלי ולגרור עם הריבוע האפור כדי לגלול להתאמת תמונת הרקע." }, "streetlevel": { "title": "תמונות ברמת רחוב", + "intro": "תמונות ברמת רחוב שימושיות למיפוי תמרורים, בתי עסק ופרטים נוספים שלא ניתן לראות מהלוויין ובצילום אווירי. עורך iD תומך בתמונות ברמת רחוב בעזרת [Mapillary](https://www.mapillary.com) ו־[OpenStreetCam](https://www.openstreetcam.org).", "using_h": "שימוש בתמונות ברמת רחוב", - "using": "כדי להשתמש בתמונות ברמת רחוב לטובת מיפוי, יש ללחוץ על הלוח {data} **נתוני מפה**  לצד המפה כדי להפעיל או להשבית את שכבות התמונות הזמינות." + "using": "כדי להשתמש בתמונות ברמת רחוב לטובת מיפוי, יש ללחוץ על הלוח {data} **נתוני מפה**  לצד המפה כדי להפעיל או להשבית את שכבות התמונות הזמינות.", + "photos": "כשאפשרות זו פעילה, שכבת התמונה מציגה קו לאורך סדרה של תמונות. ברמות תקריב גבוהות יותר, עיגול מסמן כל מיקום של תמונה, וברמות תקריב יותר גדולות, חרוט מציין את המיקום אליו פנתה המצלמה כאשר התמונה צולמה.", + "viewer": "בעת לחיצה על מיקומי תמונות, מציג תמונות יופיע בפינה תחתונה במסך. מציג התמונות מכיל פקדים לצורך צעידה קדימה ואחורה ברצף התמונות. במציג יופיע גם שם המשתמש של מי שצילם את התמונה, התאריך בו היא צולמה וקישור לצפות בתמונה באתר המקורי." }, "gps": { "title": "עקבות GPS", + "intro": "עקבות ה־GPS הן מקור נתונים רב ערך עבור OpenStreetMap. עורך זה תומך בקובצי *‎.gpx*,‏ *‎.geojson*,‏ ו־*‎.kml* שבמחשב המקומי שלך. ניתן לאסוף עקבות GPS בעזרת טלפון חכם, צמידי כושר או התקני GPS אחרים.", "survey": "למידע על כיצד לבצע סקר GPS, יש לקרוא את [מיפוי עם טלפון חכם, GPS או דף](http://learnosm.org/en/mobile-mapping/).", "using_h": "שימוש בעקבות GPS", + "using": "כדי להשתמש בעקבות GPS לטובת מיפוי, יש לגרור ולשחרר את קובץ הנתונים לעורך המפות. אם הקובץ יזוהה, הוא יצויר על המפה בקו סגול בהיר. יש ללחוץ על חלונית {data} **נתוני המפה** לצד המפה כדי להפעיל, להשבית או לקרב את התצוגה אל נתוני ה־GPS שלך.", "tracing": "מסלול ה־GPS לא נשלח אל OpenStreetMap - הדרך הטובה ביותר להשתמש בו היא לצייר על המפה, תוך שימוש במסלול כהנחיה להוספת תכונות חדשות.", "upload": "באפשרותך [להעלות את נתוני ה־GPS שלך ל־OpenStreetMap](https://www.openstreetmap.org/trace/create) לטובת משתמשים אחרים." }, "field": { "restrictions": { + "title": "עזרה בהגבלת פניות", "about": { "title": "על אודות", - "about": "שדה זה מאפשר לך לחקור ולשנות את מגבלות הפנייה. השדה מציג את דגם הצומת הנבחר לרבות דרכים קרובות שמחוברות אליו." + "about": "שדה זה מאפשר לך לחקור ולשנות את מגבלות הפנייה. השדה מציג את דגם הצומת הנבחר לרבות דרכים קרובות שמחוברות אליו.", + "from_via_to": "הגבלת פנייה תמיד מכילה את אחד מהבאים: **דרך מוצא** אחת, **דרך יעד** אחת וגם **מפרק מעבר** אחד או מספר **דרכי מעבר**.", + "maxdist": "הסרגל „{distField}” שולט עד לאיזה מרחק לחפש דרכים נוספות מחוברות.", + "maxvia": "הסרגל „{viaField}” שולט כמה דרכי ביניים יכללו בחיפוש. (עצה: כמה שיותר פשוט יותר טוב)" }, "inspecting": { + "title": "חקירה", + "about": "יש לעבור מעל כל מקטע **מוצא** כדי לצפות האם קיימות מגבלות פנייה. כל **יעד** יצויר בהצללה צבעונית שתסמן האם קיימת מגבלה.", + "from_shadow": "{fromShadow} **מקטע מוצא**", + "allow_shadow": "{allowShadow} **יעד מורשה**", + "restrict_shadow": "{restrictShadow} **יעד מוגבל**", + "only_shadow": "{onlyShadow} **יעד בלעדי**", "restricted": "משמעות הביטוי „מוגבלת” היא שיש מגבלת פנייה, למשל: „אסור לפנות שמאלה”.", "only": "משמעות הביטוי „בלבד” היא שרכב שנוסע בנתיב הזה יכול לבצע בחירה אחת בלבד, למשל „להמשיך ישר בלבד”." + }, + "modifying": { + "title": "עריכה", + "about": "כדי לערוך הגבלות פנייה, ראשית עליך ללחוץ על מקטע **מוצא** כדי לבחור אותו. המקטע הנבחר יהבהב וכל דרכי ה**יעד** האפשריות תופענה עם סמלי פנייה.", + "indicators": "לאחר מכן, יש ללחוץ על סמל פנייה כדי לעבור בין „מורשה”, „מוגבל” ו„בלעדי”.", + "allow_turn": "{allowTurn} **יעד מורשה**", + "restrict_turn": "{restrictTurn} **יעד מוגבל**", + "only_turn": "{onlyTurn} **יעד בלעדי**" + }, + "tips": { + "title": "עצות", + "simple": "**להעדיף הגבלות פשוטות על פני הגבלות מורכבות.**", + "simple_example": "למשל, יש להימנע מהגבלת פנייה בדרך ביניים במקרה שהגבלת פנייה בצומת מספיקה.", + "indirect": "**חלק מההגבלות מציגות את הטקסט „(עקיף)” והן מוצגות בצבע יותר בהיר.**", + "indirect_example": "הגבלות אלו קיימות עקב הגבלה אחרת בקרבת מקום. למשל, הגבלת „ישר בלבד” תיצור הגבלות „אין פנייה” לכל שאר הנתיבים שעוברים בצומת.", + "indirect_noedit": "לא ניתן לערוך הגבלות עקיפות. במקום, יש לערוך את המגבלה הישירה הקרובה." } } } @@ -835,7 +940,7 @@ "done": "סיום", "ok": "אישור", "graph": { - "block_number": "", + "block_number": "אישור", "city": "קריית שלושה", "county": "", "district": "", @@ -850,7 +955,7 @@ "countrycode": "il", "name": { "1st-avenue": "אחד העם", - "2nd-avenue": "שדרת הדודאים", + "2nd-avenue": "שדרת בן גוריון", "4th-avenue": "שדרות הארבעה", "5th-avenue": "שדרת החמישה", "6th-avenue": "שד׳ שש", @@ -863,14 +968,14 @@ "12th-avenue": "שד׳ תרי עשר", "access-point-employment": "מעוף משאבי אנוש", "adams-street": "רח׳ המלך ג׳ורג׳", - "andrews-elementary-school": "בית ספר יסודי קינג ג׳ורג׳", - "andrews-street": "רח׳ יהודה המכבי", + "andrews-elementary-school": "בית ספר יסודי נהלל", + "andrews-street": "רח׳ נהלל", "armitage-street": "רחוב הארמונות", "barrows-school": "בית ספר ברוש", "battle-street": "רח׳ הקרב", "bennett-street": "רב בנטל", "bowman-park": "פארק באום", - "collins-drive": "דרך קוליץ", + "collins-drive": "דרך קולין", "conrail-railroad": "מסילת רכבת", "conservation-park": "פארק שימור", "constantine-street": "רחוב קונדר", @@ -966,6 +1071,7 @@ "words": "המדריך הזה יציג מספר מילים ורעיונות חדשים. בעת הצגת מילה חדשה נשתמש בכתב *נטוי*.", "mouse": "ניתן להשתמש בכל התקן קלט כדי לערוך את המפה אך מדריך זה יוצא מנקודת הנחה שיש לך עכבר עם שני כפתורים. **אם ברצונך לחבר עכבר כדאי לעשות זאת ואז ללחוץ על אישור.**", "leftclick": "כשהמדריך הזה מבקש ממך ללחוץ לחיצה כפולה, כוונתנו היא לכפתור השמאלי. במשטח מגע יכול להיות שמדובר בלחיצה בודדת או בהקשה באצבע אחת. **יש ללחוץ לחיצה שמאלית {num} פעמים.**", + "rightclick": "לעתים נבקש ממך ללחוץ עם כפתור ימני. יכול להיות שמדובר בפעולה זהה ל־Ctrl עם לחיצה או לחיצה בשתי אצבעות על משטח מעקב. יכול להיות שבמקלדת שלך יש אפילו כפתור ‚תפריט’ שעובד כמו מקש ימני. **יש ללחוץ עם הכפתור הימני {num} פעמים.**", "chapters": "צלחנו את זה! ניתן להשתמש בכפתורים שלהלן כדי לדלג על פרקים בכל עת או כדי להתחיל פרק מחדש אם נתקעת. בואו נתחיל! **יש ללחוץ על ‚{next}’ כדי להמשיך.**" }, "navigation": { @@ -984,11 +1090,13 @@ "search_street": "ניתן גם לחפש תכונות בתצוגה הנוכחית או בכל רחבי העולם. **חיפוש אחר ‚{name}’.**", "choose_street": "**יש לבחור {name} מהרשימה כדי לבחור אותו.**", "selected_street": "מצוין! בחרת את {name}.", - "editor_street": "השדות שמופיעים לייצוג רחוב הם שונים מאלו שמופיעים על בניין העירייה.{br}לרחוב הנבחר הזה, עורך התכונות מציג שדות כמו ‏‚{field1}’ ו־‏‚{field2}’. **ניתן לסגור את עורך התכונות בלחיצה על escape או על הכפתור {button}.**" + "editor_street": "השדות שמופיעים לייצוג רחוב הם שונים מאלו שמופיעים על בניין העירייה.{br}לרחוב הנבחר הזה, עורך התכונות מציג שדות כמו ‏‚{field1}’ ו־‏‚{field2}’. **ניתן לסגור את עורך התכונות בלחיצה על escape או על הכפתור {button}.**", + "play": "כדי לנסות להזיז את המפה וללחוץ על כמה תכונות אחרות כדי לראות מה ניתן להוסיף ל־OpenStreetMap. **כשסיימת להתאמן וניתן להמשיך לפרק הבא יש ללחוץ על ‚{next}’.**" }, "points": { "title": "נקודות", "add_point": "*נקודות* יכולות לציין תכונות כגון חנויות, מסעדות ואנדרטות.{br}הן מסמנות מיקום מסוים ומציינות מה יש באותו המיקום. **יש ללחוץ על הכפתור {button} נקודה כדי להוסיף נקודה חדשה.**", + "place_point": "כדי להציב את הנקודה החדשה על המפה, עליך להציב את סמן העכבר שלך במיקום הייעודי של הנקודה ולאחר מכן עליך ללחוץ עם הכפתור השמאלי או ללחוץ על רווח. **יש להעביר את סמן העכבר מעבר לבניין הזה וללחוץ עם הכפתור השמאלי או הרווח.**", "search_cafe": "ישנן מגוון תכונות שניתן לייצג בנקודות. הנקודה שהרגע הוספת היא בית קפה. **חיפוש אחר ‚{preset}’.**", "choose_cafe": "**יש לבחור {preset} מהרשימה.**", "feature_editor": "הנקודה מסומנת כעת כבית קפה. באמצעות עורך התכונות, ניתן להוסיף מידע נוסף על בית הקפה.", @@ -1005,6 +1113,8 @@ "areas": { "title": "אזורים", "add_playground": "*שטחים* משמשים להצגת הגבולות של מאפיינים כגון אגמים, בניינים ושטחי מגורים.{br}ניתן גם להשתמש בהם לטובת מיפוי מפורט יותר של תכונות רבות שבדרך כלל ימופו כנקודות. **יש ללחוץ על הכפתור {button} שטח כדי להוסיף שטח חדש.**", + "start_playground": "בואו נוסיף את מגרש המשחקים הזה לאזור ציור המפה. ציור השטחים נעשה על ידי הצבת *מפרקים* לאורך הגבול החיצוני של התכונה. **יש להקיש על רווח כדי להציב מפרק התחלתי בכל אחת מפינות מגרש המשחקים.**", + "continue_playground": "ניתן להמשיך לצייר את השטח על ידי הצבת מפרקים נוספים לאורך קצוות מגרש המשחקים. זה בסדר לחבר את השטח לנתיבי הליכה קיימים.{br}עצה: ניתן להחזיק את המקש ‚{alt}’ כדי למנוע מהמפרקים להתחבר לתכונות. **נא להמשיך לצייר את השטח של מגרש המשחקים.**", "finish_playground": "יש לסיים את ציור השטח על ידי לחיצה על enter, או על ידי לחיצה על המפרק הראשון או האחרון. **יש לסיים ציור שטח למגרש המשחקים.**", "search_playground": "**חיפוש אחר ‚{preset}’.**", "choose_playground": "**יש לבחור {preset} מהרשימה.**", @@ -1135,9 +1245,11 @@ "search": "חיפוש תכונות שתואמות את טקסט החיפוש" }, "with_selected": { + "title": "לאחר בחירת התכונה", "edit_menu": "החלפת תצוגה של תפריט עריכה" }, "vertex_selected": { + "title": "עם מפרק שנבחר", "previous": "קפיצה למפרק הקודם", "next": "קפיצה למפרק הבא", "first": "קפיצה למפרק הראשון", @@ -1151,7 +1263,7 @@ "title": "ציור", "add_point": "מצב ‚הוספת נקודה’", "add_line": "מצב ‚הוספת קו’", - "add_area": "מצב ‚הוספת שטח’", + "add_area": "מצב ’הוספת שטח’", "place_point": "הצבת נקודה", "disable_snap": "יש להחזיק כדי להשבית הצמדת נקודות", "stop_line": "סיום ציור קו או שטח" @@ -1162,11 +1274,13 @@ "merge": "שילוב (מיזוג) התכונות הנבחרות", "disconnect": "ניתוק תכונות במפרק הנבחר", "split": "פיצול קו לשניים במפרק הנבחר", - "reverse": "ביפוך כיוון קו", + "reverse": "היפוך כיוון קו", "move": "העברת התכונות הנבחרות", "rotate": "הטיית התכונות הנבחרות", "orthogonalize": "יישור קו / פינות של איזור ריבועי", "circularize": "עיגול פינות של קו סגור או שטח", + "reflect_long": "היפוך תכונות לאורך הציר הארוך", + "reflect_short": "היפוך תכונות לאורך הציר הקצר", "delete": "מחיקת התכונות הנבחרות" }, "commands": { @@ -1192,12 +1306,19 @@ }, "units": { "feet": "{quantity} רגל", - "miles": "{quantity} מיל", + "miles": "{quantity} מייל", + "square_feet": "{quantity} רגל רבוע", + "square_miles": "{quantity} מייל רבוע", + "acres": "{quantity} אקר", "meters": "{quantity} מ׳", "kilometers": "{quantity} ק״מ", "square_meters": "{quantity} מ׳²", "square_kilometers": "{quantity} ק״מ²", + "hectares": "{quantity} הקטאר", + "area_pair": "{area1} ({area2})", "arcdegrees": "{quantity}°", + "arcminutes": "{quantity}′", + "arcseconds": "{quantity}″", "north": "צפ׳", "south": "דר׳", "east": "מז׳", @@ -1532,7 +1653,12 @@ "label": "סוג" }, "crane/type": { - "label": "סוג עגורן" + "label": "סוג עגורן", + "options": { + "floor-mounted_crane": "עגורן מקובע", + "portal_crane": "עגורן נייד", + "travel_lift": "עגורן מכולות" + } }, "crop": { "label": "יבול" @@ -1656,9 +1782,15 @@ "forward": "קדימה" } }, + "dispensing": { + "label": "מחלק מרשמים" + }, "display": { "label": "הצגה" }, + "distance": { + "label": "סך כל המרחק" + }, "dock": { "label": "סוג" }, @@ -1676,7 +1808,8 @@ "no": "אין", "rail": "מסילה מחושמלת", "yes": "יש (לא צוין)" - } + }, + "placeholder": "מסילה מחושמלת" }, "elevation": { "label": "גובה" @@ -1698,6 +1831,9 @@ "except": { "label": "חריגות" }, + "faces": { + "label": "פרצופים" + }, "fax": { "label": "פקס", "placeholder": "‎+972 3 777 777" @@ -1720,6 +1856,7 @@ "fire_hydrant/type": { "label": "סוג", "options": { + "pillar": "עמוד\\מעל האדמה", "pond": "בריכת דגים\\נוי", "underground": "תת־קרקעי", "wall": "קיר" @@ -1744,6 +1881,9 @@ "fuel_multi": { "label": "סוגי דלק" }, + "gauge": { + "label": "מדד" + }, "gender": { "label": "מגדר", "options": { @@ -1780,6 +1920,7 @@ "label": "מעקה" }, "hashtags": { + "label": "Hashtag מומלץ", "placeholder": "#דוגמא" }, "healthcare": { @@ -1804,6 +1945,33 @@ "label": "סלים", "placeholder": "1, 2, 4" }, + "horse_dressage": { + "label": "רכיבה אומנותית", + "options": { + "equestrian": "כן", + "undefined": "לא" + } + }, + "horse_riding": { + "label": "רכיבה על סוסים", + "options": { + "horse_riding": "כן", + "undefined": "לא" + } + }, + "horse_scale": { + "label": "קושי הרכיבה על סוסים", + "options": { + "common": "קל: אין בעיות או קשיים. (בררת מחדל)" + } + }, + "horse_stables": { + "label": "אורוות רכיבה", + "options": { + "stables": "יש", + "undefined": "אין" + } + }, "iata": { "label": "IATA" }, @@ -1823,9 +1991,18 @@ "indoor": { "label": "בפנים" }, + "industrial": { + "label": "סוג" + }, "information": { "label": "סוג" }, + "inscription": { + "label": "הקדשה" + }, + "intermittent": { + "label": "תקופתי" + }, "internet_access": { "label": "גישה לאינטרנט", "options": { @@ -1862,22 +2039,40 @@ "label": "שכבה", "placeholder": "0" }, + "leaf_cycle": { + "label": "מחזו עלים", + "options": { + "deciduous": "נשירים", + "evergreen": "ירוק-עד", + "mixed": "מעורב", + "semi_deciduous": "חצי נשירים", + "semi_evergreen": "חצי ירוק-עד" + } + }, "leaf_cycle_singular": { + "label": "מחזו עלים", "options": { + "deciduous": "נשירים", "evergreen": "ירוק-עד", + "semi_deciduous": "חצי נשירים", "semi_evergreen": "חצי ירוק-עד" } }, "leaf_type": { + "label": "סוג עלה", "options": { + "broadleaved": "עלים רחבים", "leafless": "ללא עלים", - "mixed": "מעורב" + "mixed": "מעורב", + "needleleaved": "עלים מחטניים" } }, "leaf_type_singular": { "label": "סוג עלה", "options": { - "leafless": "ללא עלה" + "broadleaved": "עלים רחבים", + "leafless": "ללא עלה", + "needleleaved": "עלים מחטניים" } }, "leisure": { @@ -1919,6 +2114,10 @@ "label": "מגבלת מהירות", "placeholder": "40, 50, 60" }, + "maxspeed/advisory": { + "label": "מהירות מותרת", + "placeholder": "40, 50, 60" + }, "maxstay": { "label": "זמן המותר להישאר" }, @@ -2040,12 +2239,20 @@ "label": "חנה וסע" }, "parking": { - "label": "סוג" + "label": "סוג", + "options": { + "carports": "אחסון מכוניות", + "multi-storey": "רב-קומתי", + "sheds": "מחסן", + "surface": "משטח", + "underground": "תת־קרקעי" + } }, "payment_multi": { "label": "צורות תשלום" }, "phases": { + "label": "שלבים", "placeholder": "1, 2, 3..." }, "phone": { @@ -2055,6 +2262,7 @@ "piste/difficulty": { "label": "דרגת קושי", "options": { + "advanced": "מתקדם (יהלום שחור)", "easy": "קל (עיגול ירוק)", "expert": "קשה מאוד (שני יהלומים שחורים)", "extreme": "קיצוני (דורש ציוד טיפוס)", @@ -2076,7 +2284,13 @@ "label": "סוג", "options": { "downhill": "מורד", + "hike": "טיול רגל", "ice_skate": "החלקרח", + "nordic": "נורדי", + "playground": "גן שעשועים", + "skitour": "סיור סקי", + "sled": "מזחלת", + "sleigh": "מזחלת", "snow_park": "פארק שלג" } }, @@ -2117,11 +2331,30 @@ "railway": { "label": "סוג" }, + "railway/position": { + "label": "אבן דרך", + "placeholder": "מרחק עד עשרון (123.4)" + }, "railway/signal/direction": { + "label": "כיוון", "options": { + "backward": "אחורה", + "both": "שניהם \\ כולם", "forward": "קדימה" } }, + "rating": { + "label": "דירוג חשמל" + }, + "recycling_accepts": { + "label": "מסכים" + }, + "ref": { + "label": "מספר הפניה" + }, + "ref/isil": { + "label": "קוד ISIL" + }, "ref_aeroway_gate": { "label": "מספר שער" }, @@ -2173,10 +2406,26 @@ "route_master": { "label": "סוג" }, + "sac_scale": { + "label": "דרגת קושי", + "options": { + "alpine_hiking": "T4: טיול אלפי", + "demanding_alpine_hiking": "T5: טיול אלפי קשה", + "demanding_mountain_hiking": "T3: טיול הרים קשה", + "difficult_alpine_hiking": "T6: טיול אלפי קשה מאוד", + "hiking": "T1: טיול רגל", + "mountain_hiking": "T2: טיול הרים" + }, + "placeholder": "טיול הרים, טיול אלפים" + }, + "sanitary_dump_station": { + "label": "תחנת סילוק" + }, "seasonal": { "label": "עונתי" }, "second_hand": { + "label": "מכירת משומשים", "options": { "no": "אין", "only": "בלבד", @@ -2194,7 +2443,11 @@ "label": "שירותים" }, "service_rail": { - "label": "סוג שירות" + "label": "סוג שירות", + "options": { + "spur": "דורבן", + "yard": "גינה" + } }, "service_times": { "label": "שעות השירות" @@ -2222,9 +2475,15 @@ }, "placeholder": "אין, הפרדה, יש…" }, + "smoothness": { + "label": "חלקות" + }, "social_facility": { "label": "סוג" }, + "social_facility_for": { + "label": "כמות אנשים שניתן לשרת" + }, "source": { "label": "מקורות" }, @@ -2296,7 +2555,7 @@ "surveillance/type": { "label": "סוג המעקב", "options": { - "ALPR": "קריאת לוחית רעשוי אוטומטית", + "ALPR": "קריאת לוחית רישוי אוטומטית", "camera": "מצלמה", "guard": "שמירה" } @@ -2320,6 +2579,7 @@ "placeholder": "יש, אין, איסוף עצמי בלבד…" }, "toilets/disposal": { + "label": "סילוק", "options": { "bucket": "דלי", "chemical": "כימיים", @@ -2356,15 +2616,19 @@ "traffic_signals/direction": { "label": "כיוון", "options": { - "backward": "אחורה" + "backward": "אחורה", + "both": "שניהם \\ כולם", + "forward": "קדימה" } }, "trail_visibility": { + "label": "ראות שביל", "placeholder": "מצוין, טוב, רע..." }, "transformer": { "label": "סוג", "options": { + "auxiliary": "משני", "generator": "גנרטור", "yes": "לא ידוע" } @@ -2376,8 +2640,14 @@ "label": "סוג", "placeholder": "בררת מחדל" }, - "vending": { - "label": "סוגי הטובין" + "usage_rail": { + "options": { + "industrial": "תעשייתי", + "main": "ראשי", + "military": "צבאי", + "test": "מבחן", + "tourism": "תיירות" + } }, "visibility": { "label": "ראות", @@ -2452,6 +2722,7 @@ "windings/configuration": { "options": { "delta": "דלטא", + "leblanc": "Leblanc", "open": "פתוח", "open-delta": "דלטא פתוח", "zigzag": "זיגזג" @@ -2938,6 +3209,14 @@ "name": "אוטומט מכירת שתיה", "terms": "אוטומט מכירת שתיה" }, + "amenity/vending_machine/electronics": { + "name": "אוטומט מכירת אלקטרוניקה", + "terms": "אוטומט מכירת אלקטרוניקה" + }, + "amenity/vending_machine/elongated_coin": { + "name": "אוטומט השטחת מטבעות", + "terms": "אוטומט השטחת מטבעות" + }, "amenity/vending_machine/excrement_bags": { "name": "אוטומט מכירת שקיות פסולת", "terms": "אוטומט מכירת שקיות פסולת" @@ -2946,6 +3225,10 @@ "name": "אוטומט מכירת היגינה נשית", "terms": "אוטומט מכירת היגינה נשית" }, + "amenity/vending_machine/food": { + "name": "אוטומט אוכל", + "terms": "אוטומט אוכל" + }, "amenity/vending_machine/news_papers": { "name": "עמדת חלוקת עיתונים" }, @@ -2985,6 +3268,10 @@ "name": "פח אשפה", "terms": "פח אשפה" }, + "amenity/water_point": { + "name": "מי שתייה לקרון", + "terms": "מי שתייה לקרון" + }, "area": { "name": "שטח", "terms": "שטח" @@ -3017,6 +3304,10 @@ "name": "קרוסלה", "terms": "קרוסלה" }, + "attraction/maze": { + "name": "מבוך", + "terms": "מבוך" + }, "attraction/pirate_ship": { "name": "ספינת פיראטים", "terms": "ספינת פיראטים" @@ -3135,9 +3426,33 @@ "name": "כניסיה", "terms": "כניסיה" }, + "building/college": { + "name": "בניין מכללה", + "terms": "בניין מכללה" + }, + "building/commercial": { + "name": "בניין מסחרי", + "terms": "בניין מסחרי" + }, + "building/construction": { + "name": "מבנה בבנייה", + "terms": "מבנה בבנייה" + }, + "building/dormitory": { + "name": "מעונות", + "terms": "מעונות" + }, "building/entrance": { "name": "כניסה\\יציאה" }, + "building/farm": { + "name": "בית חווה", + "terms": "בית חווה" + }, + "building/farm_auxiliary": { + "name": "חווה", + "terms": "חווה" + }, "building/garage": { "name": "מוסך", "terms": "מוסך" @@ -3182,14 +3497,34 @@ "name": "מבנה ציבור", "terms": "בניין ציבורי" }, + "building/residential": { + "name": "בניין מגורים", + "terms": "בניין מגורים" + }, + "building/retail": { + "name": "בניין קמעוני", + "terms": "בניין קמעוני" + }, "building/roof": { "name": "גג", "terms": "גג" }, + "building/ruins": { + "name": "בניין הרוס", + "terms": "בניין הרוס" + }, "building/school": { "name": "בניין בית ספר", "terms": "מבנה בית ספר, בניין ביצפר, מבנה ביצפר" }, + "building/service": { + "name": "בניין שירות", + "terms": "בניין שירות" + }, + "building/shed": { + "name": "צריף", + "terms": "צריף" + }, "building/stable": { "name": "אורווה", "terms": "אורווה" @@ -3198,9 +3533,21 @@ "name": "אצטדיון", "terms": "אצטדיון" }, + "building/static_caravan": { + "name": "RV סטטי", + "terms": "RV סטטי" + }, + "building/temple": { + "name": "מקדש", + "terms": "מקדש" + }, "building/train_station": { "name": "תחנת רכבת" }, + "building/transportation": { + "name": "מבנה תחבורה", + "terms": "מבנה תחבורה" + }, "building/university": { "name": "בניין אוניברסיטה", "terms": "בניין אוניברסיטה" @@ -3232,10 +3579,22 @@ "name": "בונה סירות", "terms": "בונה סירות" }, + "craft/bookbinder": { + "name": "כורך ספרים", + "terms": "כורך ספרים" + }, "craft/brewery": { "name": "מבשלת בירה", "terms": "מבשלת בירה" }, + "craft/carpenter": { + "name": "נגר", + "terms": "נגר" + }, + "craft/carpet_layer": { + "name": "מתקין שטיחים", + "terms": "מתקין שטיחים" + }, "craft/caterer": { "name": "הסעדה", "terms": "הסעדה" @@ -3256,10 +3615,18 @@ "name": "מזקקה", "terms": "מזקקה" }, + "craft/dressmaker": { + "name": "תופרת", + "terms": "תופרת" + }, "craft/electrician": { "name": "חשמלאי", "terms": "חשמלאי" }, + "craft/electronics_repair": { + "name": "חנות תיקון אלקטרוניקה", + "terms": "חנות תיקון אלקטרוניקה" + }, "craft/gardener": { "name": "גנן", "terms": "גנן" @@ -3268,10 +3635,24 @@ "name": "שירות מיזוג מרכזי", "terms": "שירות מיזוג מרכזי" }, + "craft/insulator": { + "name": "מבודד", + "terms": "מבודד" + }, + "craft/jeweler": { + "name": "תכשיטן" + }, "craft/key_cutter": { "name": "שכפול מפתחות", "terms": "שכפול מפתחות" }, + "craft/locksmith": { + "name": "מנעולן" + }, + "craft/metal_construction": { + "name": "נפח", + "terms": "נפח" + }, "craft/optician": { "name": "אופטיקאי" }, @@ -3291,10 +3672,53 @@ "name": "שרברב", "terms": "שרברב" }, + "craft/pottery": { + "name": "כלי חרס", + "terms": "כלי חרס" + }, + "craft/roofer": { + "name": "מתקין גגות", + "terms": "מתקין גגות" + }, + "craft/sawmill": { + "name": "מנסרה", + "terms": "מנסרה" + }, "craft/sculptor": { "name": "פסל", "terms": "פסל" }, + "craft/shoemaker": { + "name": "סנדלר", + "terms": "סנדלר" + }, + "craft/stonemason": { + "name": "סתת", + "terms": "סתת" + }, + "craft/tailor": { + "name": "חיט" + }, + "craft/tiler": { + "name": "מתקין אריחים", + "terms": "מתקין אריחים" + }, + "craft/tinsmith": { + "name": "פחח", + "terms": "פחח" + }, + "craft/upholsterer": { + "name": "רפד", + "terms": "רפד" + }, + "craft/watchmaker": { + "name": "שען", + "terms": "שען" + }, + "craft/window_construction": { + "name": "הרכבת חלונות", + "terms": "הרכבת חלונות" + }, "craft/winery": { "name": "יקב", "terms": "יקב" @@ -3303,10 +3727,126 @@ "name": "תחנת אמבולנס", "terms": "תחנת אמבולנס" }, + "emergency/defibrillator": { + "name": "דפיברילטור", + "terms": "דפיברילטור" + }, + "emergency/designated": { + "name": "גישת חירום" + }, + "emergency/destination": { + "name": "גישת חירום" + }, "emergency/fire_hydrant": { "name": "ברז כיבוי אש", "terms": "ברז כיבוי אש" }, + "emergency/no": { + "name": "אין גישת חירום" + }, + "emergency/phone": { + "name": "טלפון חרום", + "terms": "טלפון חרום" + }, + "emergency/water_tank": { + "name": "מיכל מים חרום", + "terms": "מיכל מים חרום" + }, + "emergency/yes": { + "name": "כניסת חירום" + }, + "entrance": { + "name": "כניסה\\יציאה", + "terms": "כניסה\\יציאה" + }, + "footway/crossing": { + "name": "מעבר חציה מוגבה", + "terms": "מעבר חציה מוגבה" + }, + "footway/crossing-raised": { + "name": "מעבר חציה מוגבה", + "terms": "מעבר חציה מוגבה" + }, + "footway/crosswalk": { + "name": "מעבר חציה", + "terms": "מעבר חציה" + }, + "footway/crosswalk-raised": { + "name": "מעבר חציה מוגבה", + "terms": "מעבר חציה מוגבה" + }, + "footway/sidewalk": { + "name": "מדרכה", + "terms": "מדרכה" + }, + "ford": { + "name": "מקום צליחה", + "terms": "מקום צליחה" + }, + "golf/bunker": { + "name": "מכשול חול", + "terms": "מכשול חול" + }, + "golf/fairway": { + "name": "אזור פתוח בגולף", + "terms": "אזור פתוח בגולף" + }, + "golf/green": { + "name": "דשא סביב חור גולף", + "terms": "דשא סביב חור גולף" + }, + "golf/hole": { + "name": "חור גוף", + "terms": "חור גוף" + }, + "golf/lateral_water_hazard_area": { + "name": "מכשול מים", + "terms": "מכשול מים" + }, + "golf/lateral_water_hazard_line": { + "name": "מכשול מים", + "terms": "מכשול מים" + }, + "golf/rough": { + "name": "שטח קשה בגולף", + "terms": "שטח קשה בגולף" + }, + "golf/tee": { + "name": "עמדת חביטה בגולף", + "terms": "עמדת חביטה בגולף" + }, + "golf/water_hazard_area": { + "name": "מכשול מים", + "terms": "מכשול מים" + }, + "golf/water_hazard_line": { + "name": "מכשול מים", + "terms": "מכשול מים" + }, + "healthcare": { + "name": "מוסד טיפול בריאותי", + "terms": "מוסד טיפול בריאותי" + }, + "healthcare/alternative": { + "name": "בריאות אלטרנטיבי", + "terms": "בריאות אלטרנטיבי" + }, + "healthcare/alternative/chiropractic": { + "name": "כירופרקט", + "terms": "כירופרקט" + }, + "healthcare/audiologist": { + "name": "אודיולוג", + "terms": "אודיולוג" + }, + "healthcare/birthing_center": { + "name": "מתקן לידה", + "terms": "מתקן לידה" + }, + "healthcare/blood_donation": { + "name": "מרכז תרומת דם", + "terms": "מרכז תרומת דם" + }, "healthcare/hospice": { "name": "הוספיס", "terms": "הוספיס" @@ -3315,10 +3855,22 @@ "name": "מיילדת", "terms": "מיילדת" }, + "healthcare/occupational_therapist": { + "name": "מרפא בעיסוק", + "terms": "מרפא בעיסוק" + }, + "healthcare/optometrist": { + "name": "אופטומטריסט", + "terms": "אופטומטריסט" + }, "healthcare/physiotherapist": { "name": "פזיווטרפיה", "terms": "פזיווטרפיה" }, + "healthcare/podiatrist": { + "name": "פודיאטר", + "terms": "פודיאטר" + }, "healthcare/psychotherapist": { "name": "פסיכוטרפיסט", "terms": "פסיכוטרפיסט" @@ -3327,21 +3879,160 @@ "name": "מוסד שיקומי", "terms": "מוסד שיקומי" }, + "healthcare/speech_therapist": { + "name": "קלינאית תקשורת", + "terms": "קלינאית תקשורת" + }, "highway": { "name": "כביש בין-עירוני" }, + "highway/bus_stop": { + "name": "תחנת אוטובוס \\ רציף" + }, + "highway/corridor": { + "name": "מזדרון", + "terms": "מזדרון" + }, + "highway/crossing": { + "name": "מעבר חציה", + "terms": "מעבר חציה" + }, + "highway/crossing-raised": { + "name": "מעבר חציה מוגבה", + "terms": "מעבר חציה מוגבה" + }, + "highway/crosswalk": { + "name": "מעבר חציה", + "terms": "מעבר חציה" + }, + "highway/crosswalk-raised": { + "name": "מעבר חציה מוגבה", + "terms": "מעבר חציה מוגבה" + }, + "highway/cycleway": { + "name": "מסלול אופניים", + "terms": "מסלול אופניים" + }, + "highway/elevator": { + "name": "מעלית", + "terms": "מעלית" + }, "highway/footway": { "name": "דרך רגל", "terms": "דרך רגל" }, + "highway/give_way": { + "name": "תן זכות קדימה", + "terms": "תן זכות קדימה" + }, + "highway/mini_roundabout": { + "name": "מעגל תנועה קטן", + "terms": "מעגל תנועה קטן" + }, "highway/path": { "name": "שביל", "terms": "שביל" }, + "highway/pedestrian_area": { + "name": "אזור רק עם תנועה רגלית", + "terms": "אזור רק עם תנועה רגלית" + }, + "highway/pedestrian_line": { + "name": "רחוב רק עם תנועה רגלית", + "terms": "רחוב רק עם תנועה רגלית" + }, + "highway/primary": { + "name": "כביש ראשי", + "terms": "כביש ראשי" + }, + "highway/primary_link": { + "name": "חיבור ראשי", + "terms": "חיבור ראשי" + }, + "highway/raceway": { + "name": "מסלול מרוצים (מונע)", + "terms": "מסלול מרוצים (מונע)" + }, + "highway/residential": { + "name": "כביש באזור מגורים", + "terms": "כביש באזור מגורים" + }, + "highway/rest_area": { + "name": "אזור מנוחה", + "terms": "אזור מנוחה" + }, + "highway/road": { + "name": "כביש לא ידוע", + "terms": "כביש לא ידוע" + }, + "highway/secondary": { + "name": "כביש משני", + "terms": "כביש משני" + }, + "highway/secondary_link": { + "name": "חיבור משני", + "terms": "חיבור משני" + }, + "highway/service": { + "name": "כבישי שירות", + "terms": "כבישי שירות" + }, + "highway/service/alley": { + "name": "סמטה", + "terms": "סמטה" + }, + "highway/service/emergency_access": { + "name": "גישת חירום", + "terms": "גישת חירום" + }, + "highway/speed_camera": { + "name": "מצלמת מהירות", + "terms": "מצלמת מהירות" + }, + "highway/stop": { + "name": "תמרור עצור", + "terms": "תמרור עצור" + }, + "highway/turning_circle": { + "name": "מעגל תנועה", + "terms": "מעגל תנועה" + }, + "historic": { + "name": "אתר היסטורי", + "terms": "אתר היסטורי" + }, + "historic/archaeological_site": { + "name": "אתר ארכיאולוגי", + "terms": "אתר ארכיאולוגי" + }, + "historic/boundary_stone": { + "name": "אבן גבול", + "terms": "אבן גבול" + }, "historic/castle": { "name": "טירה", "terms": "טירה" }, + "historic/memorial": { + "name": "אתר הנצחה", + "terms": "אתר הנצחה" + }, + "historic/monument": { + "name": "מונומנט", + "terms": "מונומנט" + }, + "historic/ruins": { + "name": "אתר חורבן", + "terms": "אתר חורבן" + }, + "historic/tomb": { + "name": "קבר", + "terms": "קבר" + }, + "junction": { + "name": "צומת", + "terms": "צומת" + }, "landuse/allotments": { "name": "גינה קהילתית" }, @@ -3349,6 +4040,101 @@ "name": "בית קברות", "terms": "בית קברות" }, + "landuse/commercial": { + "name": "אזור מסחרי", + "terms": "אזור מסחרי" + }, + "landuse/farm": { + "name": "אזור חקלאי" + }, + "landuse/farmland": { + "name": "אזור חקלאי", + "terms": "אזור חקלאי" + }, + "landuse/farmyard": { + "name": "אזור חקלאי", + "terms": "אזור חקלאי" + }, + "landuse/forest": { + "name": "יער", + "terms": "יער" + }, + "landuse/garages": { + "name": "אזור אחסון", + "terms": "אזור אחסון" + }, + "landuse/grass": { + "name": "דשא", + "terms": "דשא" + }, + "landuse/harbour": { + "name": "מזח", + "terms": "מזח" + }, + "landuse/industrial": { + "name": "אזור תעשיה", + "terms": "אזור תעשיה" + }, + "landuse/industrial/slaughterhouse": { + "name": "משחטה", + "terms": "משחטה" + }, + "landuse/landfill": { + "name": "מטמנה", + "terms": "מטמנה" + }, + "landuse/meadow": { + "name": "אחו", + "terms": "אחו" + }, + "landuse/military": { + "name": "אזור צבאי", + "terms": "אזור צבאי" + }, + "landuse/military/airfield": { + "name": "שדה תעופה צבאי", + "terms": "שדה תעופה צבאי" + }, + "landuse/military/barracks": { + "name": "בסיס צבאי", + "terms": "בסיס צבאי" + }, + "landuse/military/bunker": { + "name": "בונקר צבאי", + "terms": "בונקר צבאי" + }, + "landuse/military/checkpoint": { + "name": "נקודת ביקורת", + "terms": "נקודת ביקורת" + }, + "landuse/military/danger_area": { + "name": "אזור מסוכן", + "terms": "אזור מסוכן" + }, + "landuse/military/naval_base": { + "name": "בסיס חיל ים", + "terms": "בסיס חיל ים" + }, + "landuse/military/nuclear_explosion_site": { + "name": "אתר פיצוץ גרעיני", + "terms": "אתר פיצוץ גרעיני" + }, + "landuse/military/obstacle_course": { + "name": "מסלול מכשולים", + "terms": "מסלול מכשולים" + }, + "landuse/military/office": { + "name": "משרד צבאי", + "terms": "משרד צבאי" + }, + "landuse/military/range": { + "name": "אזור ירי צבאי", + "terms": "אזור ירי צבאי" + }, + "landuse/military/training_area": { + "name": "אזור אימונים", + "terms": "אזור אימונים" + }, "landuse/orchard": { "name": "פרדס", "terms": "פרדס" @@ -3357,6 +4143,22 @@ "name": "מחצבה", "terms": "מחצבה" }, + "landuse/religious": { + "name": "אזור דתי", + "terms": "אזור דתי" + }, + "landuse/residential": { + "name": " אזור מגורים", + "terms": " אזור מגורים" + }, + "landuse/retail": { + "name": "אזור מסחרי", + "terms": "אזור מסחרי" + }, + "landuse/vineyard": { + "name": "כרם", + "terms": "כרם" + }, "leisure/bowling_alley": { "name": "אולם כדורת", "terms": "אולם כדורת" @@ -3377,6 +4179,13 @@ "name": "מכון יוגה", "terms": "מכון יוגה" }, + "leisure/fitness_station": { + "name": "תחנת כושר", + "terms": "תחנת כושר" + }, + "leisure/fitness_station/stairs": { + "name": "מדרגות התעמלות" + }, "leisure/garden": { "name": "גן", "terms": "גן" @@ -3409,6 +4218,9 @@ "name": "שמורת טבע", "terms": "שמורת טבע" }, + "leisure/outdoor_seating": { + "name": "אזור ישיבה בחוץ" + }, "leisure/park": { "name": "פארק", "terms": "פארק" @@ -3457,6 +4269,12 @@ "name": "שולחן פינג פונג", "terms": "שולחן פינג פונג" }, + "leisure/pitch/tennis": { + "name": "מגרש טניס" + }, + "leisure/pitch/volleyball": { + "name": "מגרש כדורעף" + }, "leisure/playground": { "name": "גן שעשועים", "terms": "גן שעשועים" @@ -3493,6 +4311,15 @@ "name": "קו", "terms": "קו" }, + "man_made": { + "name": "מעשה ידי אדם" + }, + "man_made/antenna": { + "name": "אנטנה" + }, + "man_made/breakwater": { + "name": "שובר גלים" + }, "man_made/bridge": { "name": "גשר", "terms": "גשר" @@ -3505,10 +4332,22 @@ "name": "מנוף", "terms": "מנוף" }, + "man_made/embankment": { + "name": "סוללה" + }, + "man_made/flagpole": { + "name": "עמוד דגל" + }, "man_made/lighthouse": { "name": "מגדלור", "terms": "מגדלור" }, + "man_made/monitoring_station": { + "name": "תחנת ניטור" + }, + "man_made/observation": { + "name": "מגדל תצפית" + }, "man_made/petroleum_well": { "name": "באר נפט", "terms": "באר נפט" @@ -3521,6 +4360,12 @@ "name": "סילו", "terms": "סילו" }, + "man_made/surveillance": { + "name": "מעקב" + }, + "man_made/surveillance_camera": { + "name": "מצלמת מעקב" + }, "man_made/tower": { "name": "מגדל", "terms": "מגדל" @@ -3601,18 +4446,39 @@ "name": "קרחון", "terms": "קרחון" }, + "natural/grassland": { + "name": "דשא", + "terms": "דשא" + }, "natural/heath": { "name": "שדה בור", "terms": "שדה בור" }, + "natural/mud": { + "name": "בוץ", + "terms": "בוץ" + }, "natural/peak": { "name": "פסגה", "terms": "פסגה" }, + "natural/saddle": { + "name": "אוכף", + "terms": "אוכף" + }, "natural/sand": { "name": "חול", "terms": "חול" }, + "natural/scree": { + "name": "חלוקי נחל" + }, + "natural/scrub": { + "name": "עשביה" + }, + "natural/spring": { + "name": "מעיין" + }, "natural/tree": { "name": "עץ", "terms": "עץ" @@ -3903,6 +4769,12 @@ "name": "אומגה", "terms": "אומגה" }, + "point": { + "name": "נקודה" + }, + "power": { + "name": "חשמל" + }, "power/generator": { "name": "גנרטור", "terms": "גנרטור" @@ -3915,10 +4787,31 @@ "name": "טורבינת רוח", "terms": "טורבינת רוח" }, + "power/line": { + "name": "קו מתח" + }, + "power/minor_line": { + "name": "קו מתח משני" + }, + "power/plant": { + "name": "תחנת כוח" + }, + "power/pole": { + "name": "עמוד חשמל" + }, + "power/sub_station": { + "name": "תחנה תת קרקעית" + }, + "power/substation": { + "name": "תחנה תת קרקעית" + }, "power/switch": { "name": "מתג חשמל", "terms": "מתג חשמל" }, + "power/tower": { + "name": "מגדל מתח גבוה" + }, "public_transport/linear_platform": { "name": "תחנת רכבת \\ רציף", "terms": "תחנת רכבת \\ רציף" @@ -4035,20 +4928,52 @@ "name": "תחנת רכבת", "terms": "תחנת רכבת" }, + "public_transport/stop_position_tram": { + "name": "תחנת חשמלית", + "terms": "תחנת חשמלית" + }, + "public_transport/stop_position_trolleybus": { + "name": "תחנת חשמלית", + "terms": "תחנת חשמלית" + }, "railway": { "name": "מסילת רכבת" }, "railway/abandoned": { - "name": "מסילת רכבת לא בשימוש" + "name": "מסילת רכבת לא בשימוש", + "terms": "מסילת רכבת לא בשימוש" + }, + "railway/buffer_stop": { + "name": "אוטם מסילה", + "terms": "אוטם מסילה" }, "railway/disused": { "name": "מסילת רכבת לא בשימוש", "terms": "מסילת רכבת לא בשימוש" }, + "railway/funicular": { + "name": "רכבל", + "terms": "רכבל" + }, + "railway/halt": { + "name": "תחנת רכבת (עצירה בלבד)" + }, + "railway/level_crossing": { + "name": "חציית מסילת רכבת (כביש)", + "terms": "חציית מסילת רכבת (כביש)" + }, "railway/light_rail": { "name": "רכבת קלה", "terms": "רכבת קלה" }, + "railway/milestone": { + "name": "אבן דרך", + "terms": "אבן דרך" + }, + "railway/miniature": { + "name": "מסילת רכבת זעיר", + "terms": "מסילת רכבת זעיר" + }, "railway/monorail": { "name": "מונורייל", "terms": "מונורייל" @@ -4060,6 +4985,10 @@ "name": "מסילת רכבת", "terms": "מסילת רכבת" }, + "railway/signal": { + "name": "תמרור רכבת", + "terms": "תמרור רכבת" + }, "railway/station": { "name": "תחנת רכבת" }, @@ -4086,6 +5015,10 @@ "railway/tram_stop": { "name": "תחנת חשמלית" }, + "relation": { + "name": "יחס", + "terms": "יחס" + }, "roundabout": { "name": "מעגל תנועה" }, @@ -4161,10 +5094,18 @@ "name": "חנות אופניים", "terms": "חנות אופניים" }, + "shop/bookmaker": { + "name": "כורך ספרים", + "terms": "כורך ספרים" + }, "shop/books": { "name": "חנות ספרים", "terms": "חנות ספרים" }, + "shop/boutique": { + "name": "בוטיק", + "terms": "בוטיק" + }, "shop/butcher": { "name": "קצב", "terms": "קצב" @@ -4343,6 +5284,14 @@ "name": "הרבליסט", "terms": "הרבליסט" }, + "shop/houseware": { + "name": "חנות כלי בית", + "terms": "חנות כלי בית" + }, + "shop/interior_decoration": { + "name": "חנות עיצוב פנים", + "terms": "חנות עיצוב פנים" + }, "shop/jewelry": { "name": "תכשיטן", "terms": "תכשיטן" @@ -4443,6 +5392,10 @@ "name": "חנות לחיות מחמד", "terms": "חנות לחיות מחמד" }, + "shop/pet_grooming": { + "name": "חנות לטיפוח חיות מחמד", + "terms": "חנות לטיפוח חיות מחמד" + }, "shop/photo": { "name": "חנות צילום", "terms": "חנות צילום" @@ -4754,8 +5707,12 @@ "terms": "פנייה ימינה בלבד" }, "type/restriction/only_straight_on": { - "name": "אין פניות", - "terms": "אין פניות" + "name": "ישר בלבד", + "terms": "ישר בלבד" + }, + "type/restriction/only_u_turn": { + "name": "פרסה בלבד", + "terms": "פרסה בלבד" }, "type/route": { "name": "נתיב", @@ -4918,7 +5875,7 @@ "attribution": { "text": "תנאים ומשוב" }, - "description": "גבולות ומועדי צילום. תוויות מופיעות ברמות תקריב של 14 ומעלה.", + "description": " גבולות ומועדי צילום. תוויות מופיעות ברמות תקריב של 13 ומעלה. ", "name": "דיגיטל גלוב' תצלומי אוויר פרמיום" }, "DigitalGlobe-Standard": { @@ -4932,7 +5889,7 @@ "attribution": { "text": "תנאים ומשוב" }, - "description": "גבולות ומועדי צילום. תוויות מופיעות ברמות תקריב של 14 ומעלה.", + "description": "גבולות תמונות רקע ותאריכי צילום. תוויות מופיעות בתקריב ברמה 13 ומעלה.", "name": "דיגיטל גלוב' תצלומי אוויר" }, "EsriWorldImagery": { @@ -5016,6 +5973,10 @@ "description": "צהוב = מידע ציבורי מממשלת ארה\"ב\nאדום = מידע שלא נמצא בOSM", "name": "מידע טופולוגי ארה\"ב 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "כביש מהיר: תחימה ירוקה = ללא סיווג. תחימה חומה = מסלול. פני שטח: חצץ = מילוי חום בהיר, אספלט = שחור, מרוצף = אפור, אדמה =לבן, בטון = כחול, דשא = ירוק. עונתי = פסים לבנים", + "name": "שכבת דרכי יערות בארה״ב" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" @@ -5050,7 +6011,7 @@ "attribution": { "text": "basemap.at" }, - "description": "מפת אוסטריה מבוסס על מידע ממשלתי", + "description": " מפת אוסטריה מבוסס על מידע ממשלתי", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -5112,7 +6073,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "אריחי מפה מאת Stamen Design, תחת הרשיון CC BY 3.0" + "text": "אריחי מפה מאת Stamen Design, ברישיון CC BY 3.0. הנתונים מאת OpenStreetMap, תחת ODbL" }, "name": "תווי שטח מסטודיו Stamen" }, @@ -5128,6 +6089,718 @@ }, "name": "תווי שטח מThunderforest" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "הממפים הצעירים של אוניברסיטת קייפ קוסט", + "description": "ניתן לעקוב אחרינו בטוויטר: {url}", + "extendedDescription": "זה הכינוי הרשמי של אגף הממפים הצעירים באוניברסיטת קייפ קוסט, גאנה. אנו אוהבים מפות, נתונים פתוחים וגם לעזור לחלשים." + }, + "osm-gh-facebook": { + "name": "הפייסבוק של OpenStreetMap גאנה", + "description": "קבוצת פייסבוק לאנשים שמתעניינים ב־OpenStreetMap.", + "extendedDescription": "ממפים בקהילת גאנה, מקדמים את OpenStreetMap ואת מיזמי צוות OpenStreetMap ההומניטרי (HOT) בגאנה. אפשר להצטרף אלינו." + }, + "osm-gh-twitter": { + "name": "הטוויטר של OpenStreetMap גאנה", + "description": "ניתן לעקוב אחרינו בטוויטר: {url}" + }, + "talk-gh": { + "name": "קבוצת הדיוור Talk-gh", + "description": "Talk-gh היא קבוצת הדיוור הרשמית של קהילת OSM בגאנה" + }, + "osm-mg-facebook": { + "name": "קבוצת הפייסבוק של OpenStreetMap במדגסקר ", + "description": "קבוצת פייסבוק במלגשי לאנשים שמתעניינים ב־OpenStreetMap." + }, + "talk-mg": { + "name": "קבוצת הדיוור Talk-mg", + "description": "מקום לתורמים, קהילות ומשתמשי OpenStreetMap במדגסקר לשתף ולדון זה עם זה." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap בנגלדש", + "description": "שיפור OpenStreetMap בבנגלדש", + "extendedDescription": "מעניין אותך מיפוי בבנגלדש? יש לך שאלות? אולי ליצור קשר עם הקהילה המקומית? ניתן להצטרף אלינו ב־{url}. כולם מוזמנים!" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap הודו - מיפוי שכונות התנדבותי", + "description": "שיפור OpenStreetMap בהודו", + "extendedDescription": "מעניין אותך מיפוי בהודו? יש לך שאלות? אולי ליצור קשר עם הקהילה המקומית? ניתן להצטרף אלינו ב־{url}. כולם מוזמנים!", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "description": "ניתן להצטרף לאירוע חוצה הגבולות של OpenStreetMap לשנת 2018: State of the Map Asia בהודו", + "where": "המכללה ההודית לניהול, בנגלור, הודו" + } + } + }, + "OSM-india-mailinglist": { + "name": "קבוצת הדיוור של OpenStreetMap הודו", + "description": "Talk-in היא קבוצת הדיוור הרשמית של הקהילה ההודית" + }, + "OSM-india-twitter": { + "name": "הטוויטר של OpenStreetMap הודו", + "description": "אנחנו במרחק ציוץ: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "תנועת החומרה והתכנה החופשית - פייסבוק" + }, + "OSM-India-Puducherry-Matrix": { + "name": "תנועת החומרה והתכנה החופשית - Matrix" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap אינדונזיה", + "description": "שיפור OpenStreetMap באינדונזיה", + "extendedDescription": "מעניין אותך מיפוי באינדונזיה? יש לך שאלות? אולי ליצור קשר עם הקהילה המקומית? ניתן להצטרף אלינו ב־{Url}. כולם מוזמנים!" + }, + "OSM-japan-facebook": { + "name": "קהילת OpenStreetMap יפן", + "description": "ממפים ומשתמשים OpenStreetMap ביפן" + }, + "OSM-japan-mailinglist": { + "name": "קבוצת הדיוור של OpenStreetMap יפן", + "description": "Talk-ja היא קבוצת הדיוור הרשמית של הקהילה היפנית" + }, + "OSM-japan-twitter": { + "name": "הטוויטר של OpenStreetMap יפן", + "description": "תגית הקבץ בטוויטר: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap יפן", + "description": "ממפים ומשתמשים OpenStreetMap ביפן" + }, + "OSM-korea-telegram": { + "name": "ערוץ הטלגרם של OSM קוריאה", + "description": "ערוץ בלתי רשמי לקהילות, משתמשי ותורמי OpenStreetMap בקוריאה לטובת שיתוף ודיונים." + }, + "OSM-MY-facebook": { + "name": "הפייסבוק של OpenStreetMap מלזיה", + "description": "לשיחות על כל מה שקשור ב־OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "הפורום של OpenStreetMap מלזיה", + "description": "הפורום הרשמי של OpenStreetMap מלזיה" + }, + "OSM-MY-matrix": { + "name": "ערוץ ה־Riot של OpenStreetMap מלזיה", + "description": "כל הממפים מוזמנים! ניתן להירשם בכתובת {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap מונגוליה", + "description": "שיפור OpenStreetMap במונגוליה", + "extendedDescription": "מעניין אותך מיפוי במונגוליה? יש לך שאלות? אולי ליצור קשר עם הקהילה המקומית? ניתן להצטרף אלינו ב־{Url}. כולם מוזמנים!" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap מיאנמר", + "description": "שיפור OpenStreetMap במיאנמר", + "extendedDescription": "מעניין אותך מיפוי במיאנמר? יש לך שאלות? אולי ליצור קשר עם הקהילה המקומית? ניתן להצטרף אלינו ב־{Url}. כולם מוזמנים!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap נפאל", + "description": "שיפור OpenStreetMap בנפאל", + "extendedDescription": "מעניין אותך מיפוי בנפאל? יש לך שאלות? אולי ליצור קשר עם הקהילה המקומית? ניתן להצטרף אלינו ב־{Url}. כולם מוזמנים!" + }, + "OSM-PH-facebook": { + "name": "הפייסבוק של OpenStreetMap PH (הפיליפינים)", + "description": "ברוך בואך ל־OpenStreetMap הפיליפינים, פה אנו מעודדים את כל הפיליפינים באשר הם לתרום למיזם OpenStreetMap." + }, + "OSM-PH-mailinglist": { + "name": "קבוצת הדיוור Talk-ph", + "description": "קבוצת דיוור לדיונים על OpenStreetMap בפיליפינים" + }, + "OSM-PH-slack": { + "name": "ה־Slack של OpenStreetMap PH (הפיליפינים)", + "description": "כולם מוזמנים! ניתן להירשם בכתובת {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "הטלגרם של OpenStreetMap PH (הפיליפינים)", + "description": "קהילת טלגרם בלתי רשמית ומקומית של תורמים וחברים של OpenStreetMap בפיליפינים" + }, + "OSM-RU-forum": { + "name": "הפורום של OpenStreetMap רוסיה", + "description": "הפורום המקוון של OpenStreetMap רוסיה" + }, + "OSM-RU-telegram": { + "name": "הטלגרם של OpenStreetMap רוסיה", + "description": "קבוצת הטלגרם של OpenStreetMap רוסיה" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap סרי לנקה", + "description": "שיפור OpenStreetMap בסרי לנקה", + "extendedDescription": "מעניין אותך מיפוי בסרי לנקה? יש לך שאלות? אולי ליצור קשר עם הקהילה המקומית? ניתן להצטרף אלינו ב־{Url}. כולם מוזמנים!" + }, + "OSM-TW-facebook": { + "name": "קהילת OpenStreetMap טאיוואן", + "description": "קבוצת פייסבוק לממפים ומשתמשים ב־OpenStreetMap לטובת דיונים בנוגע לטאיוואן." + }, + "OSM-TW-mailinglist": { + "name": "קבוצת הדיוור של OpenStreetMap טאיוואן", + "description": "Talk-tw היא קבוצת הדיוור הרשמית לקהילות לטובת דיונים בנושא טאיוואן" + }, + "OSM-TH-CNX-meetup": { + "name": "מפגשי OSM צ׳אנג מאי", + "description": "מפגשים בתדירות בלתי קבועה של קהילת OpenStreetMap של צ׳אנג מאי" + }, + "OSM-TH-forum": { + "name": "הפורום של OpenStreetMap תאילנד", + "description": "הפורום המקוון של OpenStreetMap תאילנד" + }, + "al-forum": { + "name": "פורום OSM אלבניה", + "description": "פורום OpenStreetMap אלבניה" + }, + "al-maptime-tirana": { + "name": "Maptime טירנה", + "description": "אירועים חברתיים שמתגבשים סביב מיפוי - מתחילים מוזמנים בהחלט!" + }, + "al-telegram": { + "name": "ערוץ הטלגרם של OSM אלבניה", + "description": "ערוץ הטלגרם של OpenStreetMap אלבניה" + }, + "at-forum": { + "name": "הפורום של OpenStreetMap אוסטריה", + "description": "הפורום הרשמי לשאלות על OpenStreetMap בתוך וסביב אוסטריה" + }, + "at-mailinglist": { + "name": "קבוצת הדיוור Talk-at", + "description": "Talk-at היא קבוצת הדיוור הרשמית של קהילת OSM האוסטרית" + }, + "at-twitter": { + "name": "הטוויטר של OpenStreetMap אוסטריה", + "description": "הטוויטר של OpenStreetMap אוסטריה: {url}" + }, + "osmgraz-meetup": { + "name": "מפגש קהילת OSM גראץ", + "description": "מפגש חודשי של קהילת OpenStreetMap בגראץ" + }, + "osmgraz-twitter": { + "name": "הטוויטר של קהילת OSM בגראץ", + "description": "הטוויטר של קהילת OpenStreetMap בגראץ" + }, + "osm-at": { + "name": "OpenStreetMap אוסטריה", + "description": "מאגר למידע על OpenStreetMap באוסטריה" + }, + "byosm": { + "name": "OpenStreetMap בלרוס", + "description": "קבוצת הטלגרם של OpenStreetMap בלארוס" + }, + "be-facebook": { + "name": "קהילת OpenStreetMap בלגיה", + "description": "ממפים ומשתמשים ב־OpenStreetMap בבלגיה בפייסבוק" + }, + "be-forum": { + "name": "הפורום של OpenStreetMap בלגיה", + "description": "הפורום המקוון של OpenStreetMap בלגיה" + }, + "be-irc": { + "name": "ה־IRC של OpenStreetMap בלגיה", + "description": "ניתן להצטרף ל־‎#osmbe תחת irc.oftc.net (פתחה 6667)", + "extendedDescription": "ניתן להצטרף ל־‎#osmbe תחת irc.oftc.net (פתחה 6667), הוא מקושר לערוץ הצ׳אט ב־Matrix" + }, + "be-mailinglist": { + "name": "קבוצת הדיוור Talk-be", + "description": "Talk-be היא קבוצת הדיוור הרשמית של קהילת OSM הבלגית" + }, + "be-maptime": { + "name": "Maptime בלגיה", + "description": "אירועים חברתיים סביב מיפוי - מתחילים מוזמנים!" + }, + "be-matrix": { + "name": "ערוץ ה־Matrix של OpenStreetMap בלגיה", + "description": "כל הממפים מוזמנים!", + "extendedDescription": "רוב הדיונים מתרחשים בערוץ „OpenStreetMap בלגיה”. ניתן לשאול כאן הכול! החדרים האחרים מתמקדים בנושאים נקודתיים." + }, + "be-meetup": { + "name": "קבוצת המפגשים של OpenStreetMap בלגיה", + "description": "מפגשים פנים אל פנים של כל מי שמעוניין ב־OpenStreetMap." + }, + "be-twitter": { + "name": "הטוויטר של OpenStreetMap בלגיה", + "description": "OSM בלגיה בטווויטר: ‎@osm_be" + }, + "talk-cz-mailinglist": { + "name": "קבוצת הדיוור Talk-cz", + "description": "Talk-cz היא קבוצת הדיוור הרשמית של הקהילה הצ׳כית" + }, + "dk-forum": { + "name": "הפורום המקוון של OpenStreetMap דנמרק", + "description": "הפורום המקוון של OpenStreetMap דנמרק" + }, + "dk-irc": { + "name": "OpenStreetMap דנמרק ב־IRC", + "description": "ניתן להצטרף ל־‎#osm-dk תחת irc.oftc.net (פתחה 6667)" + }, + "dk-mailinglist": { + "name": "קבוצת הדיוור Talk-dk", + "description": "קבוצת דיוור לדיונים על OpenStreetMap בדנמרק" + }, + "fi-forum": { + "name": "פורום OpenStreetMap פינלנד", + "description": "הפורום המקוון של OpenStreetMap פינלנד" + }, + "fi-irc": { + "name": "OpenStreetMap פינלנד ב־IRC", + "description": "ניתן להצטרף ל־‎#osm-fi תחת irc.oftc.net (פתחה 6667)" + }, + "fi-mailinglist": { + "name": "קבוצת הדיוור Talk-fi", + "description": "Talk-fi היא קבוצת הדיוור הרשמית של קהילת OSM הפינית" + }, + "fr-facebook": { + "name": "הפייסבוק של OpenStreetMap צרפת", + "description": "הפייסבוק של OpenStreetMap צרפת" + }, + "fr-forum": { + "name": "הפורום המקוון של OpenStreetMap צרפת", + "description": "הפורום המקוון של OpenStreetMap צרפת" + }, + "fr-irc": { + "name": "OpenStreetMap צרפת ב־IRC", + "description": "ניתן להצטרף ל־‎#osm-fr תחת irc.oftc.net (פתחה 6667)" + }, + "fr-mailinglist": { + "name": "קבוצת הדיוור Talk-fr", + "description": "קבוצת הדיוור Talk-fr" + }, + "fr-twitter": { + "name": "הטוויטר של OpenStreetMap צרפת", + "description": "הטוויטר של OpenStreetMap צרפת: {url}" + }, + "de-berlin-mailinglist": { + "name": "קבוצת הדיוור של ברלין", + "description": "זאת רשימת הדיוור לקהילת OSM בברלין" + }, + "de-berlin-meetup": { + "name": "קבוצת המפגשים של OpenStreetMap ברלין-ברנדנבורג", + "description": "ממפי ומשתמשי OpenStreetMap באזור ברלין" + }, + "de-berlin-telegram": { + "name": "‎@osmberlin בטלגרם", + "description": "הטלגרם של OpenStreetMap ברלין" + }, + "de-berlin-twitter": { + "name": "הטוויטר של OpenStreetMap ברלין", + "description": "ניתן לעקוב אחרינו בטוויטר: {url}" + }, + "de-forum": { + "name": "הפורום של OpenStreetMap גרמניה", + "description": "הפורום המקוון של OpenStreetMap גרמניה" + }, + "de-irc": { + "name": "OpenStreetMap גרמניה ב־IRC", + "description": "ניתן להצטרף ל־‎#osm-de תחת irc.oftc.net (פתחה 6667)" + }, + "de-mailinglist": { + "name": "קבוצת הדיוור Talk-de", + "description": "Talk-de היא קבוצת הדיוור הרשמית של קהילת OSM הגרמנית" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "קבוצת הדיוור OWL", + "description": "זאת רשימת הדיוור לקהילת OSM במזרח וסטפליה-ליפה" + }, + "osm-de": { + "name": "OpenStreetMap גרמניה", + "description": "הפלטפורמה למידע על OpenStreetMap בגרמניה" + }, + "hu-facebook": { + "name": "הפייסבוק של OpenStreetMap הונגריה", + "description": "ממפים וקבוצת פייסבוק של OpenStreetMap בהונגריה" + }, + "hu-forum": { + "name": "הפורום של OpenStreetMap הונגריה", + "description": "הפורום המקוון של OpenStreetMap הונגריה" + }, + "hu-meetup": { + "name": "קבוצת המפגשים של OpenStreetMap הונגרי", + "description": "הפלטפורמה לכינוס מפגשים בהונגריה" + }, + "it-facebook": { + "name": "הפייסבוק של OpenStreetMap איטליה", + "description": "ניתן להצטרף לקהילה של OpenStreetMap איטליה בפייסבוק" + }, + "it-irc": { + "name": "ה־IRC של OpenStreetMap איטליה", + "description": "ניתן להצטרף ל־‎#osm-it תחת irc.oftc.net (פתחה 6667)" + }, + "it-mailinglist": { + "name": "קבוצת הדיוור Talk-it", + "description": "Talk-at היא קבוצת הדיוור הרשמית של קהילת OSM האיטלקית" + }, + "it-telegram": { + "name": "‎@OpenStreetMapItalia בטלגרם", + "description": "הטלגרם של OpenStreetMap איטליה" + }, + "it-twitter": { + "name": "הטוויטר של OpenStreetMap איטליה", + "description": "ניתן לעקוב אחרינו בטוויטר בכתובת {url}" + }, + "OSM-Rome-meetup": { + "name": "מפגש המיפוי של רומא - Incontro Mappatori Romani", + "description": "שיפור OpenStreetMap באזור רומא" + }, + "South-Tyrol-Mailing-List": { + "name": "קבוצת הדיוור של OpenStreetMap לדרום טירול" + }, + "talk-it-lazio": { + "name": "OpenStreetMap לאציו, איטליה", + "description": "כולם מוזמנים! ניתן להירשם בכתובת {signupUrl}", + "extendedDescription": "קבוצת דיוור לאזורי רומא ולאציו." + }, + "Trentino-Mailing-List": { + "name": "קבוצת הדיוור של OpenStreetMap טרנטינו" + }, + "no-forum": { + "name": "הפורום המקוון של OpenStreetMap נורווגיה", + "description": "הפורום המקוון של OpenStreetMap נורווגיה" + }, + "no-irc": { + "name": "OpenStreetMap נורווגיה ב־IRC" + }, + "no-mailinglist": { + "name": "קבוצת הדיוור של OpenStreetMap נורווגיה" + }, + "OSM-PL-facebook-group": { + "name": "קבוצת הפייסבוק של OpenStreetMap פולין", + "description": "קבוצה של ממפים ומשתמשים ב־OpenStreetMap בפולין" + }, + "OSM-PL-forum": { + "name": "הפורום של OpenStreetMap פולין", + "description": "הפורום של קהילת OpenStreetMap הפולנית" + }, + "OSM-ES-mailinglist": { + "name": "קבוצת הדיוור Talk-es", + "description": "קבוצת דיוור לדיונים על OpenStreetMap בספרד" + }, + "OSM-ES-telegram": { + "name": "@OSMes ב־Telegram", + "description": "הטלגרם של OpenStreetMap ספרד" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "אספקת שירותים ומידע על OSM עבור הקהילה המקומית בשוודיה" + }, + "se-facebook": { + "name": "הפייסבוק של OpenStreetMap שוודיה", + "description": "הפייסבוק של OpenStreetMap נורווגיה" + }, + "se-forum": { + "name": "הפורום המקוון של OpenStreetMap שוודיה", + "description": "הפורום המקוון של OpenStreetMap שוודיה" + }, + "se-irc": { + "name": "OpenStreetMap שוודיה ב־IRC", + "description": "ניתן להצטרף ל־‎#osm.se תחת irc.oftc.net (פתחה 6667)" + }, + "se-mailinglist": { + "name": "קבוצת הדיוור Talk-se", + "description": "קבוצת דיוור לדיונים על OpenStreetMap בשוודיה" + }, + "se-twitter": { + "name": "הטוויטר של OpenStreetMap שוודיה", + "description": "ניתן לעקוב אחרינו בטוויטר: {url}" + }, + "gb-mailinglist": { + "name": "קבוצת הדיוור Talk-gb", + "description": "Talk-gb היא קבוצת הדיוור הרשמית של קהילת OSM הבריטית (כולל צפון אירלנד)" + }, + "gb-irc": { + "name": "OpenStreetMap המלכה המאוחדת ב־IRC", + "description": "ניתן להצטרף ל־‎#osm-gb תחת irc.oftc.net (פתחה 6667)", + "extendedDescription": "ניתן להצטרף ל־‎#osm-gb תחת irc.oftc.net (פתחה 6667), נא להתאזר בסבלנות ולחכות מספר דקות לאחר פרסום שאלה" + }, + "OSM-CA-Slack": { + "name": "ה־Slack של OSM קנדה", + "description": "כולם מוזמנים! ניתן להירשם בכתובת {signupUrl}." + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap ונקובר", + "description": "ממפים ומשתמשים ב־OpenStreetMap בוונקובר, קולומביה הבריטית" + }, + "OSM-CU-telegram": { + "name": "ערוץ הטלגרם של OSM קובה", + "description": "הטלגרם של OpenStreetMap קובה" + }, + "OSM-NI-telegram": { + "name": "ערוץ הטלגרם של OSM ניקרגואה", + "description": "הטלגרם של OpenStreetMap ניקרגואה" + }, + "Bay-Area-OpenStreetMappers": { + "name": "ממפי OpenStreetMap באזור מפרץ סן פרנסיסקו", + "description": "שיפור OpenStreetMap באזור מפרץ סן פרנסיסקו" + }, + "Central-Pennsylvania-OSM": { + "name": "OSM מרכז פנסילבניה", + "description": "קהילת מיפוי מקוון שבסיסה הוא בסטייט קולג׳, פנסילבניה" + }, + "Code-for-San-Jose-Slack": { + "name": "קוד ל־Slack של סן חוזה", + "description": "כולם מוזמנים! ניתן להירשם בכתובת {signupUrl} ואז להצטרף לערוץ ‎#osm." + }, + "Dallas-Fort-Worth-OSM": { + "name": "OSM דלאס-פורט וורת׳", + "description": "קבוצת משתמשי OpenStreetMap בדלאס-פורט וורת׳", + "extendedDescription": "דלאס, פורט וורת׳ וכל הערים שביניהן שופעות באנשים יצירתיים ומוכשרים טכנולוגית. החזון של קבוצת המשתמשים הזאת היא למצוא דרכים חדשות להשתמש במשאב המדהים שנקרא OSM." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "קבוצת מפגשים לחובבי מפות באזור פילדלפיה" + }, + "MapMinnesota": { + "name": "MapMinnesota" + }, + "Mapping-DC-meetup": { + "name": "מיפוי וושינגטון הבירה", + "description": "שיפור OpenStreetMap באיזור וושינגטון הבירה", + "extendedDescription": "אנו קבוצה של ממפים מתנדבים שחותרים לשפר את OpenStreetMap באיזור וושינגטון הבירה. אנו גם חותרים ללמד אנשים נוספים על הסביבה המקיפה את OSM, ניתוח מידע, מיפוי ומערכות מידע גאוגרפיות. אנו נפגשים אחת לחודשיים כדי להתמקד על אזור מסוים בעיר שלנו." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "ממפים ומשתמשי OpenStreetMap סביב פורטלנד, מיין", + "extendedDescription": "Maptime כשמו כן הוא, זמן ליצירת מפות. המטרה שלנו היא לפתוח את הדלת לאפשרויות מגוונות ליצירת מפות לכל מי שמעוניין על ידי יצירת מקום ללמידה שיתופית, חקירה ויצירת מפות באמצעות כלים וטכנולוגיות למיפוי." + }, + "OpenCleveland-meetup": { + "name": "קליבלנד פתוחה", + "description": "שיפור OpenStreetMap באזור קליבלנד" + }, + "OSM-Boston": { + "name": "OpenStreetMap בוסטון", + "description": "ממפים ומשתמשים ב־OpenStreetMap באזור בוסטון", + "extendedDescription": "OpenStreetMap היא מפת העולם פתוחה בסגנון ויקי, מורכבת ממאות אלפי תרומות כל יום שנתרמות על ידי אנשים כמוך. עריכת המפה היא תהליך פשוט ומהנה! מזמינים אותך להצטרף אלינו בפעילויות הפנים והחוץ כחלק מהניסיון שלנו ליצור את המפה הטובה ביותר של אזור בוסטון ושאר העולם!" + }, + "OSM-Central-Salish-Sea": { + "description": "ממפים ומשתמשי OpenStreetMap סביב מאונט ורנון, וירג׳יניה", + "extendedDescription": "OpenStreetMap היא מפת העולם שנוצרת על ידי אנשים כמוך. זו מפה בהרכבתך, שמוגשת לציבור בחינם כמו ויקיפדיה. כדאי לבקר ב־osm.org למידע נוסף. אנו נפגשים כל הזמן ומדברים על מפות, ממפים ונהנים!" + }, + "OSM-Chattanooga": { + "name": "OSM צ׳טנוגה", + "description": "קבוצת משתמשי OpenStreetMap בצ׳טנוגה" + }, + "OSM-Colorado": { + "name": "OpenStreetMap קולורדו", + "description": "ממפים ומשתמשים ב־OpenStreetMap במדינת קולורדו, ארה״ב" + }, + "OSM-NYC": { + "name": "OpenStreetMap העיר ניו יורק" + }, + "OSM-Portland": { + "name": "OpenStreetMap פורטלנד", + "description": "ממפים ומשתמשים ב־OpenStreetMap באזור פורטלנד" + }, + "OSM-Seattle": { + "name": "OpenStreetMap סיאטל", + "description": "ממפים ומשתמשים ב־OpenStreetMap באזור סיאטל" + }, + "OSM-SoCal": { + "name": "OpenStreetMap דרום קליפורניה", + "description": "בואו נהנה, נתרום משהו ללוס אנג׳לס ונלמד על מיפוי!" + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap מפרץ טמפה", + "description": "ממפים ומשתמשים ב־OpenStreetMap באזור מפרץ טמפה" + }, + "OSM-US-Slack": { + "name": "ה־Slack של OpenStreetMap ארה״ב", + "description": "כולם מוזמנים! ניתן להירשם בכתובת {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap ארה״ב", + "description": "אנו מסייעים להצמיח ולשפר את OpenStreetMap בארצות הברית.", + "extendedDescription": "אנו תומכים ב־OpenStreetMap על ידי אירוח של כנסים שנתיים, אספקת משאבים קהילתיים, בניית שותפויות והפצה ברבים. ניתן להצטרף ל־OpenStreetMap ארה״ב כאן: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap יוטה", + "description": "ממפים ומשתמשים ב־OpenStreetMap באזור סולט לייק סיטי" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap ויומינג", + "description": "ממפים ומשתמשים ב־OpenStreetMap במדינת ויומינג" + }, + "PHXGeo-meetup": { + "name": "קבוצת המפגשים של PHXGeo", + "description": "ממפי ומשתמשי OpenStreetMap באזור פיניקס, אריזונה", + "extendedDescription": "זו קבוצת מפגשים לאלו מאזור פיניקס שאוהבים מיפוי, נתונים גאוגרפיים, OpenStreetMap, חיבור מפות וכל מה שביניהם." + }, + "PHXGeo-twitter": { + "name": "הטוויטר של PHXGeo", + "description": "ניתן לעקוב אחרינו בטוויטר בכתובת {url}" + }, + "Western-Slope-facebook": { + "description": "ממפי ומשתמשי OpenStreetMap סביב גרנד ג׳נקשן, קולורדו" + }, + "Western-Slope-meetup": { + "description": "ממפי ומשתמשי OpenStreetMap סביב גרנד ג׳נקשן, קולורדו" + }, + "Maptime-Australia-Slack": { + "name": "ה־Slack של Maptime אוסטרליה", + "description": "ניתן להירשם בכתובת {signupUrl}" + }, + "talk-au": { + "name": "קבוצת הדיוור Talk-au", + "description": "מקום לשיחות בין ממפים אוסטרליים" + }, + "OSM-AR-facebook": { + "name": "הפייסבוק של OpenStreetMap ארגנטינה", + "description": "ניתן להצטרף לקהילה של OpenStreetMap ארגנטינה בפייסבוק", + "extendedDescription": "חדשות מהקהילה המקומית" + }, + "OSM-AR-forum": { + "name": "הפורום המקוון של OpenStreetMap ארגנטינה", + "description": "ניתן להצטרף לפורום המקוון של OpenStreetMap ארגנטינה", + "extendedDescription": "מצוין לדיונים ארוכים או חשובים. זמן תגובה ארוך." + }, + "OSM-AR-irc": { + "name": "OpenStreetMap ארגנטינה ב־IRC", + "description": "ניתן להצטרף ל־‎#osm-ar תחת irc.oftc.net (פתחה 6667)", + "extendedDescription": "שם ניתן למצוא את המשתמש החנון ביותר בקהילה." + }, + "OSM-AR-mailinglist": { + "name": "קבוצת הדיוור Talk-ar", + "description": "קבוצת דיוור היסטורית. כמעט לא בשימוש כיום." + }, + "OSM-AR-telegram": { + "name": "הטלגרם של OpenStreetMap ארגנטינה", + "description": "ניתן להצטרף לקהילת OpenStreetMap ארגנטינה בטלגרם", + "extendedDescription": "הערוץ הפעיל ביותר בקהילה, מומלץ לשיחות ולקבלת תשובות לשאלות שלך במהרה. כולם מוזמנים!" + }, + "OSM-AR-twitter": { + "name": "הטוויטר של OpenStreetMap ארגנטינה", + "description": "ניתן לעקוב אחרינו בטוויטר בכתובת {url}", + "extendedDescription": "חדשות מהקהילה המקומית ומ־OpenStreetMap באופן כללי." + }, + "OSM-BO-mailinglist": { + "name": "קבוצת הדיוור Talk-bo", + "description": "Talk-bo היא קבוצת הדיוור הרשמית של קהילת OpenStreetMap הבוליביאנית", + "extendedDescription": "מעניין אותך מיפוי בבוליביה? יש לך שאלות? אולי ליצור קשר עם הקהילה המקומית? ניתן להצטרף אלינו ב־{url}. כולם מוזמנים!" + }, + "Bahia-telegram": { + "name": "קבוצת הטלגרם של OpenStreetMap באהיה", + "description": "ניתן להצטרף לקהילת OpenStreetMap באהיה בטלגרם", + "extendedDescription": "ניתן להצטרף לקהילה שלנו כדי ללמוד עוד על OpenStreetMap, לשאול שאלות או להשתתף במפגשים שלנו. כולם מוזמנים!" + }, + "DF-telegram": { + "name": "קבוצת הטלגרם של OpenStreetMap ברזיליה", + "description": "ניתן להצטרף לקהילת OpenStreetMap ברזיליה בטלגרם", + "extendedDescription": "ניתן להצטרף לקהילה וללמוד עוד על OpenStreetMap, לשאול שאלות או להשתתף במפגשים שלנו. כולם מוזמנים!" + }, + "OSM-br-mailinglist": { + "name": "קבוצת הדיוור Talk-br", + "description": "קבוצת דיוור לדיונים על OpenStreetMap בברזיל" + }, + "OSM-br-telegram": { + "name": "הטלגרם של OpenStreetMap ברזיל", + "description": "ניתן להצטרף לקהילת OpenStreetMap ברזיל בטלגרם", + "extendedDescription": "ניתן להצטרף לקהילה שלנו כדי ללמוד עוד על OpenStreetMap, לשאול שאלות או להשתתף במפגשים שלנו. כולם מוזמנים!" + }, + "OSM-br-twitter": { + "name": "הטוויטר של OpenStreetMap ברזיל", + "description": "ניתן לעקוב אחרינו בטוויטר בכתובת {url}" + }, + "OSM-CL-facebook": { + "name": "הפייסבוק של OpenStreetMap צ׳ילה", + "description": "ניתן להצטרף לקהילה של OpenStreetMap צ׳ילה בפייסבוק", + "extendedDescription": "ניתן להצטרף לקהילה שלנו כדי ללמוד עוד על OpenStreetMap, לשאול שאלות או להשתתף במפגשים שלנו. כולם מוזמנים!" + }, + "OSM-CL-mailinglist": { + "name": "קבוצת הדיוור Talk-cl", + "description": "קבוצת דיוור לדיונים על OpenStreetMap בצ׳ילה" + }, + "OSM-CL-telegram": { + "name": "הטלגרם של OpenStreetMap צ׳ילה", + "description": "ניתן להצטרף לקהילת OpenStreetMap צ׳ילה בטלגרם", + "extendedDescription": "ניתן להצטרף לקהילה שלנו כדי ללמוד עוד על OpenStreetMap, לשאול שאלות או להשתתף במפגשים שלנו. כולם מוזמנים!" + }, + "OSM-CL-twitter": { + "name": "הטוויטר של OpenStreetMap צ׳ילה", + "description": "ניתן לעקוב אחרינו בטוויטר בכתובת {url}" + }, + "Maptime-Bogota": { + "name": "Maptime בוגוטה", + "description": "אנו קבוצה של ממפים שמעוניים למפות ב־OpenStreetMap סביב בוגוטה.", + "extendedDescription": "מידע על איסוף נתונים בשטח והמרתם לנתונים דיגיטליים ב־OpenStreetMap. אין צורך בידע קודם! נדרש רק רצון עז להשתתף, ללמוד וליהנות." + }, + "OSM-CO-facebook": { + "name": "הפייסבוק של OpenStreetMap קולומביה", + "description": "ניתן להצטרף לקהילה של OpenStreetMap קולומביה בפייסבוק", + "extendedDescription": "ניתן להצטרף לקהילה שלנו כדי ללמוד עוד על OpenStreetMap. כולם מוזמנים!" + }, + "OSM-CO-mailinglist": { + "name": "קבוצת הדיוור Talk-co", + "description": "קבוצת דיוור לדיונים על OpenStreetMap בקולומביה" + }, + "OSM-CO-telegram": { + "name": "ערוץ הטלגרם של OSM קולומביה", + "description": "הטלגרם של OpenStreetMap קולומביה" + }, + "OSM-CO-twitter": { + "name": "הטוויטר של OpenStreetMap קולומביה", + "description": "ניתן לעקוב אחרינו בטוויטר בכתובת {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap קולומביה", + "description": "חדשות על קהילת OpenStreetMap קולומביה ועל קרן OSMCo" + }, + "OSM-EC-telegram": { + "name": "ערוץ הטלגרם של OSM אקוודור", + "description": "הטלגרם של OpenStreetMap אקוודור" + }, + "OSM-PY-telegram": { + "name": "ערוץ הטלגרם של OSM פרגוואי", + "description": "הטלגרם של OpenStreetMap פרגוואי" + }, + "OSM-PE-facebook": { + "name": "הפייסבוק של OpenStreetMap פרו", + "description": "ניתן להצטרף לקהילה של OpenStreetMap פרו בפייסבוק" + }, + "OSM-PE-mailinglist": { + "name": "קבוצת הדיוור Talk-pe", + "description": "קבוצת הדיוור הרשמית ל־OpenStreetMap פרו" + }, + "OSM-PE-matrix": { + "name": "ערוץ ה־Matrix של OpenStreetMap פרו", + "description": "ניתן לשוחח עם חברים נוספים בקהילת OpenStreetMap פרו דרך Matrix." + }, + "OSM-PE-telegram": { + "name": "הטלגרם של OpenStreetMap פרו", + "description": "ניתן להצטרף לקהילת OpenStreetMap פרו בטלגרם" + }, + "OSM-PE-twitter": { + "name": "הטוויטר של OpenStreetMap פרו", + "description": "ניתן לעקוב אחרינו בטוויטר בכתובת {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap פרו", + "description": "חדשות ומשאבים לקהילת OpenStreetMap פרו" + }, + "OSM-Facebook": { + "name": "OpenStreetMap בפייסבוק", + "description": "ניתן לעשות לנו ‚לייק’ בפייסבוק כדי לקבל חדשות ועדכונים על OpenStreetMap." + }, + "OSM-help": { + "name": "העזרה של OpenStreetMap", + "description": "ניתן לשאול שאלות ולקבל תשובות באתר השאלות והתשובות בשיתוף קהילת OSM.", + "extendedDescription": "{url} מיועד לכל מי שצריך עזרה עם OpenStreetMap. בין אם עזרה לממפים מתחילים או שאלה טכנית, אנחנו כאן כדי לעזור!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap ב־Reddit", + "description": "/r/openstreetmap/ הוא מקום נהדר ללמוד עוד על OpenStreetMap. מצפים לשאלות שלכם בכל נושא שהוא!" + }, + "OSM-Twitter": { + "name": "הטוויטר של OpenStreetMap", + "description": "ניתן לעקוב אחרינו בטוויטר בכתובת {url}" + }, + "OSMF": { + "name": "קרן OpenStreetMap", + "description": "OSMF הוא ארגון בריטי ללא מטרות רווח שתומך במיזם OpenStreetMap", + "extendedDescription": "OSMF תומך ב־OpenStreetMap על ידי תרומה, תחזוקת השרתים שעליהם פועלת מערכת OSM, ארגון הכנס State of the Map ותיאום בין המתנדבים שדואגים ש־OSM ימשיך להכות גלים. ניתן להראות את תמיכתך ולתת את קולך ל־OpenStreetMap על ידי הצטרפות לחברות ב־OSMF דרך כאן: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "מזמינים אותך להצטרף אלינו ל־3 ימים במילאנו שבאיטליה לכנס השנתי הכלל עולמי של OpenStreetMap, שמקבץ יחד את כל הקהילה לטובת קשרים חברתיים, שיתוף ולמידה.", + "where": "מילאנו, איטליה" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/hr.json b/vendor/assets/iD/iD/locales/hr.json index 5142b1822..e4c439a00 100644 --- a/vendor/assets/iD/iD/locales/hr.json +++ b/vendor/assets/iD/iD/locales/hr.json @@ -160,7 +160,6 @@ "annotation": "{n} elemenata je spojeno.", "not_eligible": "Ovi elementi se ne mogu spojiti.", "not_adjacent": "Ovi elementi se ne mogu spojiti jer njihove krajnje točke nisu spojene.", - "restriction": "Ovi elementi se ne mogu spojiti jer je barem jedan dio \"{relation}\" relacije.", "incomplete_relation": "Ovi se elementi ne mogu spojiti jer bar jedan od njih nije potpuno preuzet s interneta.", "conflicting_tags": "Ovi elementi se ne mogu spojiti jer se neke njihove oznake ne podudaraju." }, @@ -520,13 +519,7 @@ } }, "success": { - "edited_osm": "Uređen OSM!", "just_edited": "Upravo si uredio/la OpenStreetMap!", - "view_on_osm": "Pogledaj na OSM", - "facebook": "Podijeli na mreži Facebook", - "twitter": "Podijeli na mreži Twitter", - "google": "Podijeli na mreži Google+", - "help_html": "Tvoje promjene bi se trebale pojaviti u sloju \"Standard\" kroz par minuta. Za druge slojeve i određene elemente trebati će više vremena.", "help_link_text": "Detalji", "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" }, @@ -1134,6 +1127,9 @@ "bicycle_parking": { "label": "Vrsta" }, + "bin": { + "label": "Kanta za smeće" + }, "boundary": { "label": "Vrsta" }, @@ -1516,7 +1512,6 @@ } }, "phone": { - "label": "Telefon", "placeholder": "+385 01 123 4567" }, "piste/difficulty": { @@ -1731,9 +1726,6 @@ "trees": { "label": "Drveće" }, - "vending": { - "label": "Vrsta robe" - }, "water": { "label": "Vrsta" }, @@ -2343,9 +2335,15 @@ "craft/caterer": { "name": "Dostavljač" }, + "craft/chimney_sweeper": { + "name": "Dimnjačar" + }, "craft/clockmaker": { "name": "Urar (ručni satovi)" }, + "craft/distillery": { + "name": "Destilerija" + }, "craft/dressmaker": { "name": "Krojač" }, @@ -3165,6 +3163,9 @@ "name": "Kozmetički salon", "terms": "kozmetički salon,solarij,salon ljepote,pediker,beauty centar" }, + "shop/beauty/nails": { + "name": "Studio za nokte" + }, "shop/bed": { "name": "Trgovina opreme za krevete", "terms": "madrac, madraci, podnica, podnice, posteljina, jastuk, jastuci" @@ -3177,6 +3178,9 @@ "name": "prodavaonica bicikala", "terms": "trgovina biciklima" }, + "shop/bookmaker": { + "name": "Kladioničar" + }, "shop/books": { "name": "Knjižara" }, @@ -3209,6 +3213,9 @@ "shop/cheese": { "name": "Prodavaonica sira" }, + "shop/chemist": { + "name": "Drogerija" + }, "shop/chocolate": { "name": "Prodavaonica čokolade" }, @@ -3328,6 +3335,9 @@ "name": "Zlatarnica", "terms": "zlatarna,zlatara,zlatar" }, + "shop/kiosk": { + "name": "Kiosk" + }, "shop/kitchen": { "name": "Trgovina kuhinjskog namještaja", "terms": "kuhinje, pećnice, hladnjak" @@ -3397,6 +3407,9 @@ "shop/pawnbroker": { "name": "Zalagaonica" }, + "shop/perfumery": { + "name": "Parfimerija" + }, "shop/pet": { "name": "Prodavaonica kućnim ljubimcima", "terms": "dućan za kućne ljubimce,dućan s kućnim ljubimcima,pet store,pet shop,trgovina kućnim ljubimcima,trgovina za kućne ljubimce,prodavaonica kućnih ljubimaca,prodavaonica ljubimaca,prodavaonica za kućne ljubimce" @@ -3483,6 +3496,9 @@ "name": "Prodavaonica video igara", "terms": "računalne igre, igrice" }, + "shop/watches": { + "name": "Trgovina Satovima" + }, "shop/water_sports": { "name": "Trgovina za vodene sportove", "terms": "plivanje, ronjenje" @@ -3594,15 +3610,6 @@ "type/restriction/no_u_turn": { "name": "Zabranjeno polukružno okretanje" }, - "type/restriction/only_left_turn": { - "name": "Obavezno lijevo skretanje" - }, - "type/restriction/only_right_turn": { - "name": "Obavezno desno skretanje" - }, - "type/restriction/only_straight_on": { - "name": "Zabranjena sva skretanja" - }, "type/route": { "name": "Ruta", "terms": "ruta,linija,pravac" @@ -3795,7 +3802,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Osnovna karta Austrije, bazirano na vladinim podacima.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -3856,9 +3862,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Sličice karte od Stamen Design, pod CC BY 3.0" - }, "name": "Stamen Terrain" }, "tf-cycle": { diff --git a/vendor/assets/iD/iD/locales/hu.json b/vendor/assets/iD/iD/locales/hu.json index b21bc7e14..da794e87d 100644 --- a/vendor/assets/iD/iD/locales/hu.json +++ b/vendor/assets/iD/iD/locales/hu.json @@ -1,5 +1,10 @@ { "hu": { + "icons": { + "information": "infó", + "remove": "eltávolítás", + "undo": "visszavonás" + }, "modes": { "add_area": { "title": "Terület", @@ -163,7 +168,6 @@ "annotation": "{n} elem egyesítve.", "not_eligible": "Az elemek nem egyesíthetőek.", "not_adjacent": "Az elemek nem egyesíthetőek, mert a végpontjaik nincsenek összekötve.", - "restriction": "Az elemek nem egyesíthetőek, mert legalább az egyik tagja egy „{relation}” kapcsolatnak.", "incomplete_relation": "Nem sikerült az egyesítés, mert legalább egy elem nincs teljesen letöltve.", "conflicting_tags": "Az elemek nem egyesíthetőek, mert néhány címke értéke ütközik." }, @@ -291,6 +295,21 @@ } } }, + "restriction": { + "controls": { + "distance": "Távolság", + "via_node_only": "Csak csomópont" + }, + "help": { + "indirect": "(indirekt)", + "from": "INNEN", + "via": "EZEN ÁT", + "to": "IDE", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}" + } + }, "undo": { "tooltip": "Visszavonás: {action}", "nothing": "Nincs mit visszavonni." @@ -602,15 +621,14 @@ } }, "success": { - "edited_osm": "OSM szerkesztve!", "just_edited": "Szerkesztetted az OpenStreetMapet!", - "view_on_osm": "Megtekintés OSM-en", - "facebook": "Megosztás Facebookon", - "twitter": "Megosztás Twitteren", - "google": "Megosztás Google+-on", - "help_html": "A változtatásaid néhány percen belül megjelennek az alapértelmezett rétegen. Ez a többi rétegnél és bizonyos funkcióknál több ideig is tarthat.", "help_link_text": "Részletek", - "help_link_url": "https://wiki.openstreetmap.org/wiki/Hu:FAQ#V.C3.A1ltoztat.C3.A1sokat_eszk.C3.B6z.C3.B6ltem_a_t.C3.A9rk.C3.A9pen.2C_hogyan_l.C3.A1thatom_ezeket.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/Hu:FAQ#V.C3.A1ltoztat.C3.A1sokat_eszk.C3.B6z.C3.B6ltem_a_t.C3.A9rk.C3.A9pen.2C_hogyan_l.C3.A1thatom_ezeket.3F", + "more": "Több", + "events": "Események", + "languages": "Nyelvek: {languages}", + "missing": "Valami hiányzik a listáról?", + "tell_us": "Mondd el!" }, "confirm": { "okay": "OK", @@ -759,6 +777,16 @@ "gps": { "title": "GPS nyomvonalok", "using_h": "GPS nyomvonal használata" + }, + "field": { + "restrictions": { + "about": { + "title": "Névjegy" + }, + "modifying": { + "title": "Módosítás" + } + } } }, "intro": { @@ -1129,6 +1157,11 @@ } }, "units": { + "feet": "{quantity} láb", + "miles": "{quantity} mérföld", + "square_feet": "{quantity} négyzetláb", + "square_miles": "{quantity} négyzet mérföld", + "acres": "{quantity} hektár", "meters": "{quantity} m", "kilometers": "{quantity} km", "square_meters": "{quantity} m²", @@ -1394,6 +1427,9 @@ "brand": { "label": "Márka" }, + "brewery": { + "label": "Csapolt sörök" + }, "bridge": { "label": "Típus", "placeholder": "Alapértelmezett" @@ -1408,6 +1444,7 @@ "label": "Típus" }, "cables": { + "label": "Kábelek", "placeholder": "1, 2, 3..." }, "camera/direction": { @@ -1468,7 +1505,12 @@ "label": "Típus" }, "crane/type": { - "label": "Daru típus" + "label": "Daru típus", + "options": { + "floor-mounted_crane": "Bakdaru", + "portal_crane": "Portáldaru", + "travel_lift": "Futódaru" + } }, "crop": { "label": "Termények" @@ -1527,6 +1569,9 @@ "cycleway:right": "Jobb oldal" } }, + "dance/style": { + "label": "Táncstílusok" + }, "date": { "label": "Dátum" }, @@ -1585,12 +1630,16 @@ "label": "Irány", "options": { "backward": "Hátra", + "both": "Mindkettő / Összes", "forward": "Előre" } }, "display": { "label": "Kijelző" }, + "distance": { + "label": "Teljes távolság" + }, "dock": { "label": "Típus" }, @@ -1659,6 +1708,9 @@ "wall": "Fali" } }, + "fitness_station": { + "label": "Felszereléstípus" + }, "fixme": { "label": "JavítsKi" }, @@ -1739,6 +1791,27 @@ "label": "Kosárlabdapalánk", "placeholder": "1, 2, 4…" }, + "horse_dressage": { + "options": { + "equestrian": "Igen", + "undefined": "Nem" + } + }, + "horse_riding": { + "options": { + "horse_riding": "Igen", + "undefined": "Nem" + } + }, + "horse_scale": { + "placeholder": "Nehéz, veszélyes…" + }, + "horse_stables": { + "options": { + "stables": "Igen", + "undefined": "Nem" + } + }, "iata": { "label": "IATA" }, @@ -1758,6 +1831,9 @@ "indoor": { "label": "Beltéri" }, + "industrial": { + "label": "Típus" + }, "information": { "label": "Típus" }, @@ -1878,6 +1954,10 @@ "label": "Sebességkorlátozás", "placeholder": "30, 50, 70…" }, + "maxspeed/advisory": { + "label": "Ajánlott sebességkorlátozás", + "placeholder": "40, 50, 60…" + }, "maxstay": { "label": "Leghosszabb várakozási idő" }, @@ -1996,7 +2076,7 @@ } }, "opening_hours": { - "label": "Nyitva tartás" + "label": "Nyitvatartás" }, "operator": { "label": "Üzemeltető" @@ -2031,7 +2111,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telefonszám", "placeholder": "+36 1 123 45 67" }, "piste/difficulty": { @@ -2116,7 +2195,9 @@ "railway/signal/direction": { "label": "Irány", "options": { - "backward": "Hátra" + "backward": "Hátra", + "both": "Mindkettő / Összes", + "forward": "Előre" } }, "rating": { @@ -2359,7 +2440,8 @@ "label": "Típus", "options": { "circuit_breaker": "Áramkör megszakító", - "earthing": "Földelés" + "earthing": "Földelés", + "mechanical": "Mechanikus" } }, "tactile_paving": { @@ -2426,6 +2508,7 @@ "label": "Irány", "options": { "backward": "Hátra", + "both": "Mindkettő / Összes", "forward": "Előre" } }, @@ -2460,8 +2543,18 @@ "label": "Típus", "placeholder": "Alapértelmezett" }, + "usage_rail": { + "options": { + "branch": "Ág", + "industrial": "Ipari", + "main": "Fő", + "military": "Katonai", + "test": "Teszt", + "tourism": "Turisztikai" + } + }, "vending": { - "label": "Termékek típusa" + "label": "Áruk típusa" }, "visibility": { "label": "Láthatóság", @@ -2521,6 +2614,9 @@ "wheelchair": { "label": "Akadálymentesség" }, + "wholesale": { + "label": "Nagykereskedelem" + }, "width": { "label": "Szélesség (méter)" }, @@ -2530,6 +2626,16 @@ "windings": { "label": "Tekercsek", "placeholder": "1, 2, 3..." + }, + "windings/configuration": { + "options": { + "delta": "Delta", + "leblanc": "Leblanc", + "open": "Nyitott", + "open-delta": "Nyitott delta", + "scott": "Scott", + "zigzag": "Cikk-cakk" + } } }, "presets": { @@ -2541,6 +2647,9 @@ "name": "Óriásplakát", "terms": "plakát,óriásplakát,reklámtábla,poszter, óriásposzter" }, + "advertising/column": { + "name": "Hirdetőoszlop" + }, "aerialway": { "name": "Drótkötélpálya" }, @@ -4471,7 +4580,7 @@ "terms": "gazométer" }, "man_made/groyne": { - "name": "Sarkantyú", + "name": "Keresztgát", "terms": "védőgát, hullámtörő" }, "man_made/lighthouse": { @@ -5830,18 +5939,6 @@ "name": "Megfordulni tilos", "terms": "Tilos megfordulni" }, - "type/restriction/only_left_turn": { - "name": "Kötelező haladási irány: balra", - "terms": "Csak balra szabad fordulni" - }, - "type/restriction/only_right_turn": { - "name": "Kötelező haladási irány: jobbra", - "terms": "Csak jobbra kanyarodás" - }, - "type/restriction/only_straight_on": { - "name": "Kötelező haladási irány: egyenesen tovább", - "terms": "Tilos kanyarodni" - }, "type/route": { "name": "Útvonal", "terms": "útvonal, nyomvonal" @@ -6126,7 +6223,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Osztrák Basemap, kormányzati adatok alapján.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6187,9 +6283,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Térképcsempék: Stamen Design, CC BY 3.0 szerint" - }, "name": "Stamen Terrain (terep)" }, "tf-cycle": { @@ -6204,6 +6297,26 @@ }, "name": "Thunderforest Landscape (táj)" } + }, + "community": { + "Bay-Area-OpenStreetMappers": { + "name": "A San Francisco-öböl környéki (Bay Area) OpenStreetMap-szerkesztők", + "description": "Az OpenStreetMap tökéletesítése a San Francisco-öböl környékén", + "extendedDescription": "Ez a csoport az itteni, öbölkörnyéki OpenStreetMap-közösség gyarapításával foglalkozik. Rendezvényeink mindenki számára nyitottak a nyílt forráskódú szoftverek híveitől kezdve a kerékpárosokon, térinformatikusokon és geocaching-játékosokon át bárki másig. Örömmel látunk mindenkit, akit érdekelnek a térképek, a térképészet és a nyílt térképadatok, hogy csatlakozzék csoportunkhoz és részt vegyen a rendezvényeinken." + }, + "Central-Pennsylvania-OSM": { + "name": "Közép-Pennsylvania OSM", + "description": "A Pennsylvania State College főiskolából kinövő online térképészközösség" + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "A Dallas-Fort Worth-ban működő OpenStreetMap felhasználói csoport", + "extendedDescription": "Dallas, Fort Worth és a köztük lévő városok bővelkednek kreatív, műszakilag jártas emberekben. A felhasználói csoport jövőképe, hogy új utakat találjon az OSM lenyűgöző erőforrásainak kihasználásra." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Térképrajongók találkozója Philadelphia térségében" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/hy.json b/vendor/assets/iD/iD/locales/hy.json index 7c4f39174..0e66fa737 100644 --- a/vendor/assets/iD/iD/locales/hy.json +++ b/vendor/assets/iD/iD/locales/hy.json @@ -137,7 +137,6 @@ "key": "Ց", "annotation": "{n} յատկութիւնները միաւորուել են։", "not_eligible": "Այս յատկութիւնները չենկարող միաւորուել։", - "restriction": "Այս յատկութիւնները չեն կարող միաւորուել, քանի որ դրանցից առնուազն մէկը՝ «{relation}» յարաբերութեան անդամ է։", "incomplete_relation": "Այս յատկութիւնները չեն կարող միաւորուել, քանի որ դրանցից առնուազն մէկը ամբողջովին ներբեռնուած չէ։", "conflicting_tags": "Այս յատկութիւնները չեն կարող միաւորուել, քանի որ դրանց պիտակներից որոշներն ունեն հակասող արժէքներ։" }, @@ -386,12 +385,7 @@ } }, "success": { - "edited_osm": "ՕՍՄ֊ը խմբագրո՛ւած է։", - "just_edited": "Դու նոր խմբագրեցի՛ր ՕփենՍթրիթՄէփը։", - "view_on_osm": "Դիտել ՕՍՄ֊ում։", - "facebook": "Տարածել Ֆեյսբուքում", - "twitter": "Տարածել Թուիթերում", - "google": "Տարածել Գուգլ+֊ում" + "just_edited": "Դու նոր խմբագրեցի՛ր ՕփենՍթրիթՄէփը։" }, "confirm": { "cancel": "Չեղարկել" @@ -781,9 +775,6 @@ "parking": { "label": "Տեսակ" }, - "phone": { - "label": "Հեռախոս" - }, "piste/type": { "label": "Տեսակ" }, @@ -844,9 +835,6 @@ "traffic_signals": { "label": "Տեսակ" }, - "vending": { - "label": "Գոյքի Տեսակ" - }, "water": { "label": "Տեսակ" }, diff --git a/vendor/assets/iD/iD/locales/id.json b/vendor/assets/iD/iD/locales/id.json index d7f38b418..8404b1d0f 100644 --- a/vendor/assets/iD/iD/locales/id.json +++ b/vendor/assets/iD/iD/locales/id.json @@ -1,5 +1,9 @@ { "id": { + "icons": { + "information": "info", + "remove": "hapus" + }, "modes": { "add_area": { "title": "Wilayah", @@ -137,7 +141,6 @@ "key": "C", "annotation": "Satukan {n} fitur.", "not_eligible": "Fitur-fitur ini tidak bisa digabung.", - "restriction": "Fitur-fitur ini tidak bisa disatukan karena ada setidaknya satu yang merupakan bagian dari relasi \"{relation}\".", "incomplete_relation": "Fitur ini tidak bisa digabungkan karena belum sepenuhnya terunduh.", "conflicting_tags": "Fitur-fitur ini tidak bisa disatukan karena beberapa nilai dari tagnya ada yang bertolak belakang." }, @@ -189,6 +192,11 @@ } } }, + "restriction": { + "controls": { + "distance": "Jarak" + } + }, "undo": { "tooltip": "Batalkan: {action}", "nothing": "Tak ada yang bisa dibatalkan." @@ -218,8 +226,10 @@ "readonly": "API dalam kondisi hanya-baca. Anda perlu menunggu untuk menyimpan perubahan." }, "commit": { + "title": "Unggah ke OpenStreetMap", "upload_explanation": "Perubahan yang anda unggah akan tampil di seluruh peta yang menggunakan data OpenStreetMap.", "upload_explanation_with_user": "Perubahan yang anda unggah sebagai {user} akan tampil di seluruh peta yang menggunakan data OpenStreetMap.", + "save": "Unggah", "cancel": "Batal", "changes": "{count} Perubahan", "warnings": "Peringatan", @@ -397,12 +407,7 @@ } }, "success": { - "edited_osm": "OSM tersunting!", "just_edited": "Anda baru saja menyunting OpenStreetMap!", - "view_on_osm": "Lihat di OSM", - "facebook": "Bagikan di Facebook", - "twitter": "Bagikan di Twitter", - "google": "Bagikan di Google+", "help_link_text": "detail" }, "confirm": { @@ -439,7 +444,10 @@ "view_on_mapillary": "Lihat gambar ini di Mapillary" }, "help": { - "title": "Bantuan" + "title": "Bantuan", + "help": { + "open_source_h": "Sumber Terbuka" + } }, "intro": { "done": "selesai", @@ -879,7 +887,6 @@ } }, "phone": { - "label": "Telepon", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2556,15 +2563,6 @@ "type/restriction/no_u_turn": { "name": "Dilarang Putar Balik" }, - "type/restriction/only_left_turn": { - "name": "Belok Kiri Saja" - }, - "type/restriction/only_right_turn": { - "name": "Belok Kanan Saja" - }, - "type/restriction/only_straight_on": { - "name": "Dilarang Berbelok" - }, "type/route": { "name": "Rute" }, diff --git a/vendor/assets/iD/iD/locales/is.json b/vendor/assets/iD/iD/locales/is.json index b67cfcda1..006255e6d 100644 --- a/vendor/assets/iD/iD/locales/is.json +++ b/vendor/assets/iD/iD/locales/is.json @@ -1,5 +1,10 @@ { "is": { + "icons": { + "information": "upplýsingar", + "remove": "fjarlægja", + "undo": "afturkalla" + }, "modes": { "add_area": { "title": "Svæði", @@ -163,7 +168,6 @@ "annotation": "Sameinaði {n} fitjur.", "not_eligible": "Það er ekki hægt að sameina þessa hluti.", "not_adjacent": "Það er ekki hægt að sameina þessi atriði því endapunktar þeirra eru ekki tengdir.", - "restriction": "Það er ekki hægt að sameina þessi atriði því a.m.k. eitt þeirra er hluti af \"{relation}\" venslum.", "incomplete_relation": "Það er ekki hægt að sameina þessi atriði því ekki er búið að hlaða inn að fullu a.m.k. einu þeirra.", "conflicting_tags": "Það er ekki hægt að sameina þessi atriði því sum merki þeirra eru ekki með samstæð gildi." }, @@ -291,6 +295,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Fjarlægð", + "distance_up_to": "Allt að {distance}", + "via": "Í gegnum", + "via_node_only": "Einungis hnútur", + "via_up_to_one": "Allt að 1 leið", + "via_up_to_two": "Allt að 2 leiðum" + }, + "help": { + "indirect": "(óbeint)", + "turn": { + "no_left_turn": "EKKI vinstri beygja {indirect}", + "no_right_turn": "EKKI hægri beygja {indirect}", + "no_u_turn": "EKKI U-beygja {indirect}", + "no_straight_on": "EKKI beint áfram {indirect}", + "only_left_turn": "EINUNGIS vinstri beygja {indirect}", + "only_right_turn": "EINUNGIS hægri beygja {indirect}", + "only_u_turn": "EINUNGIS U-beygja {indirect}", + "only_straight_on": "EINUNGIS beint áfram {indirect}", + "allowed_left_turn": "Vinstri beygja leyfð {indirect}", + "allowed_right_turn": "Hægri beygja leyfð {indirect}", + "allowed_u_turn": "U-beygja leyfð {indirect}", + "allowed_straight_on": "Beint áfram leyft {indirect}" + }, + "from": "FRÁ", + "via": "Í GEGNUM", + "to": "TIL", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Smelltu til að velja {from} bút", + "select_from_name": "Smelltu til að velja {from} {fromName}", + "toggle": "Smelltu til að \"{turn}\"" + } + }, "undo": { "tooltip": "Afturkalla: {action}", "nothing": "Ekkert til að afturkalla." @@ -603,13 +643,7 @@ } }, "success": { - "edited_osm": "Þú breyttir OSM!", "just_edited": "Þú hefur breytt OpenStreetMap!", - "view_on_osm": "Skoða á OSM", - "facebook": "Deila á Facebook", - "twitter": "Deila á Twitter", - "google": "Deila á Google+", - "help_html": "Breytingarnar þínar ættu að birtast á \"staðlaða\" laginu innan skamms. Breytingar á öðrum lögum og ákveðnum eigindum gætu tekið lengri tíma.", "help_link_text": "Nánar", "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" }, @@ -846,6 +880,44 @@ "using": "Til að nota GPS-feril til kortagerðar, dragðu og slepptu gagnaskrána yfir í kortaritilinn. Ef hún er metin gild, verður ferillinn teiknaður á kortið með ljósfjólublárri línu. Smelltu á {data} **Kortagögn** spjaldið við hlið kortsins til að virkja, gera óvirkt eða renna inn að GPS-gögnunum þínum.", "tracing": "GPS-ferillinn er ekki sendur til OpenStreetMap - besta leiðin til að nota hann er við teikningu á kortið, nota hann til stuðnungs við fitjur eða eigindi sem þú setur inn.", "upload": "Þú getur líka [sent GPS-gögnin þín inn á OpenStreetMap](https://www.openstreetmap.org/trace/create) svo að aðrir notendur geti stuðst við þau." + }, + "field": { + "restrictions": { + "title": "Hjálp fyrir takmarkanir á beygjum", + "about": { + "title": "Um", + "about": "Þessi reitur gerir þér kleift að yfirfara og breyta takmörkunum á beygjum. Hann birtir líkan af völdum gatnamótum ásamt nálægum tengdum vegum.", + "from_via_to": "Takmörkun á beygju inniheldur alltaf: eina **FRÁ leið**, eina **TIL leið**, og annað hvort einn **Í GEGNUM hnút** eða eina eða fleiri **Í GEGNUM leiðir**.", + "maxdist": "Sleðinn \"{distField}\" stýrir hve langt eigi að leita að tengdum vegum í viðbót.", + "maxvia": "Sleðinn \"{viaField}\" stýrir hve margar gegnumstreymisleiðir eigi að hafa með í leitinni. (Ábending: einfalt er betra)" + }, + "inspecting": { + "title": "Yfirferð", + "about": "Láttu bendilinn svífa yfir einhverjum **FRÁ** bút til að skoða hvort hann sé með nokkrar takmarkanir á beygjum. Allir mögulegir **TIL** úttakspunktar verða teiknaðir með litaðri skyggingu til að sýna hvort takmörkun sé fyrir hendi.", + "from_shadow": "{fromShadow} **FRÁ bútur**", + "allow_shadow": "{allowShadow} **TIL leyft**", + "restrict_shadow": "{restrictShadow} **TIL takmarkað**", + "only_shadow": "{onlyShadow} **TIL einungis**", + "restricted": "\"Takmarkað\" þýðir að þar er takmörkun á beygjum, til dæmis \"Ekki vinstri beygja\".", + "only": "\"Einungis\" þýðir að farartæki á þessari leið getur einungis valið þessa leið, til dæmis \"Einungis beint áfram\"." + }, + "modifying": { + "title": "Breytingar", + "about": "Til að breyta takmörkunum á beygjum, smelltu þá fyrst á einhvern upphafs-**FRÁ** bút til að velja hann. Valdi búturinn mun sýnast slá í púls, og allir mögulegir **TIL** úttakspunktar munu birtast sem beygjutákn.", + "indicators": "Síðan geturðu smellt á beygjutákn til að víxla því á milli \"Leyft\", \"Takmarkað\" og \"Einungis\".", + "allow_turn": "{allowTurn} **TIL leyft**", + "restrict_turn": "{restrictTurn} **TIL takmarkað**", + "only_turn": "{onlyTurn} **TIL einungis**" + }, + "tips": { + "title": "Ábendingar", + "simple": "**Kjóstu einfaldar takmarkanir fram yfir flóknar.**", + "simple_example": "Sem dæmi, forðastu að útbúa gegnumstreymisleið ef hægt er að komast af með einfaldari takmörkun á beygju með 'í gegnum'-hnúti.", + "indirect": "**Sumar takmarkanir eru birtar með textanum \"(óbeint)\" og eru teiknaðar ljósari.**", + "indirect_example": "Slíkar takmarkanir eru til staðar vegna annarra takmarkana í grenndinni. Til dæmis mun \"Einungis beint áfram\" takmörkun útbúa óbeint aðrar \"Ekki beygja\" takmarkanir fyrir allar aðrar leiðir í gegnum gatnamótin.", + "indirect_noedit": "Þú getur ekki breytt óbeinum takmörkunum. Í staðinn þarftu að breyta öðrum nálægum takmörkunum." + } + } } }, "intro": { @@ -1629,6 +1701,9 @@ "cycleway:right": "Hægra megin" } }, + "dance/style": { + "label": "Dansstílar" + }, "date": { "label": "Dagsetning" }, @@ -1867,6 +1942,9 @@ "indoor": { "label": "Innanhúss" }, + "industrial": { + "label": "Tegund" + }, "information": { "label": "Tegund" }, @@ -1987,6 +2065,10 @@ "label": "Hraðatakmörkun", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "Ráðlögð hraðatakmörkun", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Hámarksdvöl" }, @@ -2140,7 +2222,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Sími", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2573,8 +2654,19 @@ "label": "Tegund", "placeholder": "Sjálfgefið" }, + "usage_rail": { + "label": "Tegund notkunar", + "options": { + "branch": "Grein", + "industrial": "Iðnaður", + "main": "Aðal", + "military": "Hernaður", + "test": "Prófanir", + "tourism": "Ferðaþjónusta" + } + }, "vending": { - "label": "Sýnileiki vöru" + "label": "Vörutegundir" }, "visibility": { "label": "Sýnileiki", @@ -2606,6 +2698,12 @@ "voltage/primary": { "label": "Aðalspenna" }, + "voltage/secondary": { + "label": "Eftirspenna" + }, + "voltage/tertiary": { + "label": "Aukaspenna" + }, "wall": { "label": "Tegund" }, @@ -2731,6 +2829,9 @@ "aeroway/terminal": { "name": "Flugstöð" }, + "allotments/plot": { + "name": "Samfélagsgarðskikar" + }, "amenity": { "name": "Þjónusta" }, @@ -2908,6 +3009,9 @@ "amenity/marketplace": { "name": "Markaður" }, + "amenity/monastery": { + "name": "Klausturlóð" + }, "amenity/motorcycle_parking": { "name": "Mótorhjólastæði" }, @@ -3067,18 +3171,36 @@ "amenity/vending_machine/cigarettes": { "name": "Sígarettusjálfsali" }, + "amenity/vending_machine/coffee": { + "name": "Kaffisjálfsali" + }, "amenity/vending_machine/condoms": { "name": "Smokkasjálfsali" }, "amenity/vending_machine/drinks": { "name": "Drykkjasjálfsali" }, + "amenity/vending_machine/electronics": { + "name": "Rafeindatækjasjálfsali" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Sjálfsali fyrir flatta/stimplaða mynt" + }, "amenity/vending_machine/excrement_bags": { "name": "Sjálfsali með úrgangspokum" }, "amenity/vending_machine/feminine_hygiene": { "name": "Sjálfsali með dömusnyrtivörum" }, + "amenity/vending_machine/food": { + "name": "Matarsjálfsali" + }, + "amenity/vending_machine/fuel": { + "name": "Eldsneytisdæla" + }, + "amenity/vending_machine/ice_cream": { + "name": "Íssjálfsali" + }, "amenity/vending_machine/news_papers": { "name": "Dagblaðasjálfsali" }, @@ -3094,6 +3216,9 @@ "amenity/vending_machine/public_transport_tickets": { "name": "Miðasjálfsali í almenningssamgöngur" }, + "amenity/vending_machine/stamps": { + "name": "Póstsjálfsali" + }, "amenity/vending_machine/sweets": { "name": "Snakksjálfsali" }, @@ -3275,6 +3400,12 @@ "building/entrance": { "name": "Inngangur/Útgangur" }, + "building/farm": { + "name": "Íbúðarhús á býli" + }, + "building/farm_auxiliary": { + "name": "Landbúnaðarbygging" + }, "building/garage": { "name": "Bílskúr" }, @@ -3705,6 +3836,9 @@ "highway/motorway_link": { "name": "Hraðbrautarrein" }, + "highway/passing_place": { + "name": "Framúrakstur" + }, "highway/path": { "name": "Stígur" }, @@ -3724,7 +3858,7 @@ "name": "Keppnisbraut (mótorsport)" }, "highway/residential": { - "name": "Íbúagata" + "name": "Íbúðagata" }, "highway/rest_area": { "name": "Hvíldarsvæði" @@ -3976,6 +4110,9 @@ "leisure/amusement_arcade": { "name": "Spilasalur" }, + "leisure/beach_resort": { + "name": "Strandbær" + }, "leisure/bird_hide": { "name": "Fuglaskoðunarskýli" }, @@ -3988,6 +4125,9 @@ "leisure/dance": { "name": "Danssalur" }, + "leisure/dancing_school": { + "name": "Dansskóli" + }, "leisure/dog_park": { "name": "Hundagarður" }, @@ -4060,6 +4200,9 @@ "leisure/nature_reserve": { "name": "Friðland" }, + "leisure/outdoor_seating": { + "name": "Svæði fyrir sæti utandyra" + }, "leisure/park": { "name": "Garður" }, @@ -4156,6 +4299,9 @@ "man_made/adit": { "name": "Námuinngangur" }, + "man_made/antenna": { + "name": "Loftnet" + }, "man_made/breakwater": { "name": "Sjóvarnargarður" }, @@ -4195,6 +4341,9 @@ "man_made/observation": { "name": "Varðturn" }, + "man_made/observatory": { + "name": "Skoðunarstöð" + }, "man_made/petroleum_well": { "name": "Olíulind" }, @@ -4289,6 +4438,9 @@ "natural/heath": { "name": "Mói" }, + "natural/mud": { + "name": "Leðja" + }, "natural/peak": { "name": "Tindur" }, @@ -4415,6 +4567,9 @@ "office/lawyer/notary": { "name": "Skrifstofa lögbókanda" }, + "office/moving_company": { + "name": "Skrifstofa flutningafyrirtækis" + }, "office/newspaper": { "name": "Skrifstofur fréttablaðs" }, @@ -5079,6 +5234,9 @@ "shop/pet": { "name": "Dýrabúð" }, + "shop/pet_grooming": { + "name": "Dýrasnyrtiverslun" + }, "shop/photo": { "name": "Ljósmyndavöruverslun" }, @@ -5309,13 +5467,16 @@ "name": "Engin U-beygja" }, "type/restriction/only_left_turn": { - "name": "Einungis vinstri beygja" + "name": "Aðeins vinstri beygja" }, "type/restriction/only_right_turn": { - "name": "Einungis hægri beygja" + "name": "Aðeins hægri beygja" }, "type/restriction/only_straight_on": { - "name": "Engar beygjur" + "name": "Aðeins beint áfram" + }, + "type/restriction/only_u_turn": { + "name": "Aðeins U-beygja" }, "type/route": { "name": "Leið" @@ -5368,6 +5529,9 @@ "type/route_master": { "name": "Leiðastjóri" }, + "type/site": { + "name": "Stæði" + }, "type/waterway": { "name": "Siglingaleið" }, @@ -5440,7 +5604,6 @@ "attribution": { "text": "Skilmálar og umsagnir" }, - "description": "Útjaðar myndefnis og tökudagsetningar. Merkingar birtast við aðdráttarstig 14 og hærra.", "name": "Eldri myndir frá DigitalGlobe (Premium Vintage)" }, "DigitalGlobe-Standard": { @@ -5454,7 +5617,6 @@ "attribution": { "text": "Skilmálar og umsagnir" }, - "description": "Útjaðar myndefnis og tökudagsetningar. Merkingar birtast við aðdráttarstig 14 og hærra.", "name": "Eldri myndir frá DigitalGlobe (Standard Vintage)" }, "EsriWorldImagery": { @@ -5634,7 +5796,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Kortaflísar frá Stamen Design, með CC BY 3.0 notkunarleyfi" + "text": "Kortaflísar frá Stamen Design, með CC BY 3.0 notkunarleyfi. Gögn frá OpenStreetMap, með ODbL notkunarleyfi" }, "name": "Stamen landsyfirborð" }, @@ -5650,6 +5812,200 @@ }, "name": "Thunderforest landslag" } + }, + "community": { + "OSM-India-facebook": { + "name": "OpenStreetMap India - Kortagerð með þáttöku nágranna", + "description": "Bætum OpenStreetMap-gögn á Indlandi" + }, + "OSM-japan-facebook": { + "name": "OpenStreetMap Japan samfélagið", + "description": "Kortagerðarfólk og notendur OpenStreetMap í Japan" + }, + "OSM-japan-mailinglist": { + "name": "Póstlisti OpenStreetMap Japan", + "description": "Talk-ja er opinber póstlisti japanska OSM-hópsins" + }, + "OSM-japan-twitter": { + "name": "Twitter-hópur OpenStreetMap Japan", + "description": "Myllumerki á Twitter á {url}" + }, + "OSM-PH-facebook": { + "name": "Facebook-hópur OpenStreetMap PH", + "description": "Velkomin í filipeyska OpenStreetMap hópinn, þar sem við hvetjum alla aðra filipseyinga til að taka þátt í OpenStreetMap-verkefninu." + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph póstlistinn", + "description": "Póstlisti til að ræða OpenStreetMap á Filipseyjum" + }, + "OSM-PH-slack": { + "name": "OpenStreetMap PH Slack", + "description": "Allir velkomnir! Skráðu þig á {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "Telegram-hópur OpenStreetMap PH", + "description": "Óopinber staðvær Telegram-hópur OpenStreetMap þátttakenda og vina á Filipseyjum" + }, + "OSM-RU-forum": { + "name": "OpenStreetMap RU vefspjall", + "description": "Vefspjall (forum) OpenStreetMap Rússland" + }, + "OSM-RU-telegram": { + "name": "Telegram-hópur OpenStreetMap RU", + "description": "Telegram-hópur OpenStreetMap Rússland" + }, + "OSM-TW-facebook": { + "name": "OpenStreetMap Tævan samfélagið", + "description": "Facebook-hópur fyrir kortagerðarfólk og notendur OpenStreetMap í Tævan" + }, + "OSM-TW-mailinglist": { + "name": "Póstlisti OpenStreetMap Tævan", + "description": "Talk-ja er opinber póstlisti tævanska OSM-hópsins" + }, + "byosm": { + "name": "OpenStreetMap Hvítarússland", + "description": "Telegram-hópur OpenStreetMap Hvítarússlands" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz póstlistinn", + "description": "Talk-ja er opinber póstlisti tékkneska OSM-hópsins" + }, + "OSM-ES-telegram": { + "name": "@OSMes á Telegram", + "description": "Telegram-hópur OpenStreetMap Spánn" + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver", + "description": "Kortagerðarfólk og notendur OpenStreetMap í Vancouver, BC-svæðinu" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area OpenStreetMappers", + "description": "Bætum OpenStreetMap-gögn á Bay Area" + }, + "Central-Pennsylvania-OSM": { + "name": "Central Pennsylvania OSM" + }, + "Code-for-San-Jose-Slack": { + "description": "Allir eru velkomnir! Skráðu þig á {signupUrl}, taktu síðan þátt á #osm IRC-rásinni" + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "Notendahópur OpenStreetMap í Dallas-Fort Worth" + }, + "GeoPhilly": { + "name": "GeoPhilly" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC", + "description": "Bætum OpenStreetMap-gögn á DC-svæðinu" + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Kortagerðarfólk og notendur OpenStreetMap í kringum Portland, ME" + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Bætum OpenStreetMap-gögn á Cleveland-svæðinu" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Kortagerðarfólk og notendur OpenStreetMap á Boston-svæðinu" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Central Salish Sea", + "description": "Kortagerðarfólk og notendur OpenStreetMap í kringum Mount Vernon, WA", + "extendedDescription": "OpenStreetMap er landakort af heiminum gert af fólki eins og þér. Kort sem þú byggir upp, sem er öllum frjálst, rétt eins og Wikipedia. Skoðaðu osm.org til að sjá nánari upplýsingar. Við hittumst mjög oft til að tala um kort, gera kort, og skemmta okkur!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "Notendur OpenStreetMap í Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "description": "Kortagerðarfólk og notendur OpenStreetMap í Colorado-fylki, BNA" + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Kortagerðarfólk og notendur OpenStreetMap, forritarar og áhugafólk á New York Metropolitan-svæðinu" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Kortagerðarfólk og notendur OpenStreetMap á Portland-svæðinu", + "extendedDescription": "OpenStreetMap (OSM) er landakort af heiminum gert af fólki eins og þér. Kort sem þú byggir upp, sem er öllum frjálst, rétt eins og Wikipedia. Skoðaðu osm.org til að sjá nánari upplýsingar, og kíktu við á fundum til að tala um kort, gera OSM-kort, og skemmta þér!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Kortagerðarfólk og notendur OpenStreetMap á Seattle-svæðinu" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Southern California", + "description": "Skemmtum okkur, gerum eitthvað fyrir Los Angeles, og lærum í leiðinni um kortagerð!" + }, + "OSM-South-Bay": { + "name": "OSM South Bay" + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Tampa Bay", + "description": "Kortagerðarfólk og notendur OpenStreetMap á Tampa Bay-svæðinu" + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack", + "description": "Allir velkomnir! Skráðu þig á {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap US", + "description": "Við hjálpum til við að auka og bæta OpenStreetMap-gögn í Bandaríkjunum" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah", + "description": "Kortagerðarfólk og notendur OpenStreetMap á Salt Lake City-svæðinu" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming", + "description": "Kortagerðarfólk og notendur OpenStreetMap í Wyoming-fylki, BNA" + }, + "PHXGeo-meetup": { + "description": "Kortagerðarfólk og notendur OpenStreetMap á Phoenix, AZ-svæðinu" + }, + "PHXGeo-twitter": { + "description": "Fylgstu með okkur á Twitter á {url}" + }, + "Western-Slope-facebook": { + "description": "Kortagerðarfólk og notendur OpenStreetMap í kringum Grand Junction, CO" + }, + "Western-Slope-meetup": { + "description": "Kortagerðarfólk og notendur OpenStreetMap í kringum Grand Junction, CO" + }, + "Maptime-Australia-Slack": { + "description": "Skráðu þig á {signupUrl}" + }, + "OSM-AR-facebook": { + "name": "Facebook-hópur OpenStreetMap Argentína", + "description": "Gakktu til liðs við OpenStreetMap Argentína hópinn á Facebook" + }, + "OSM-AR-forum": { + "name": "Vefspjall (forum) OpenStreetMap Argentína", + "description": "Gakktu til liðs við OpenStreetMap Argentína vefspjallið" + }, + "OSM-AR-irc": { + "name": "IRC-rás OpenStreetMap Argentína", + "description": "Taktu þátt á #osm-ar á irc.oftc.net (gátt 6667)" + }, + "OSM-AR-mailinglist": { + "name": "Talk-ar póstlistinn" + }, + "OSM-AR-telegram": { + "name": "Telegram-hópur OpenStreetMap Argentína", + "description": "Gakktu til liðs við OpenStreetMap Argentína hópinn á Telegram" + }, + "OSM-AR-twitter": { + "name": "Twitter-hópur OpenStreetMap Argentína", + "description": "Fylgstu með okkur á Twitter á {url}" + }, + "OSM-Reddit": { + "name": "OpenStreetMap á Reddit", + "description": "/r/openstreetmap/ er góður staður til að læra meira um OpenStreetMap. Spurðu okkur um allt milli himins og jarðar!" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/it.json b/vendor/assets/iD/iD/locales/it.json index b82c93dc5..87287a9a9 100644 --- a/vendor/assets/iD/iD/locales/it.json +++ b/vendor/assets/iD/iD/locales/it.json @@ -1,5 +1,10 @@ { "it": { + "icons": { + "information": "info", + "remove": "rimuovi", + "undo": "annulla" + }, "modes": { "add_area": { "title": "Area", @@ -145,7 +150,9 @@ "vertex": "Connessa una linea ad un'altra.", "line": "Connessa una strada ad una linea.", "area": "Connessa una linea ad un'area." - } + }, + "relation": "Questi elementi non possono essere collegati tra loro perché ci sono conflitti nei ruoli della relazione.", + "restriction": "Questi elementi non possono essere connessi tra loro perché ciò danneggerebbe la relazione “{relation}”" }, "disconnect": { "title": "Disconnetti", @@ -163,7 +170,8 @@ "annotation": "Uniti {n} elementi.", "not_eligible": "Questi elementi non possono essere uniti.", "not_adjacent": "Questi elementi non possono essere uniti perché i loro estremi non sono connessi.", - "restriction": "Questi elementi non possono essere uniti perché almeno uno è membro di una relazione \"{relation}\".", + "restriction": "Questi elementi non possono essere uniti perché ciò danneggerebbe la relazione “{relation}”.", + "relation": "Questi elementi non possono essere uniti perché hanno dei ruoli di relazione tra loro in conflitto.", "incomplete_relation": "Questi elementi non posso essere uniti perché almeno uno di loro non è stato completamente scaricato.", "conflicting_tags": "Questi elementi non possono essere uniti perché alcuni dei loro tag sono in conflitto tra loro." }, @@ -402,6 +410,7 @@ "key": "H", "title": "Storico", "selected": "{n} selezionato/i", + "no_history": "Nessuna cronologia (nuovo elemento)", "version": "Versione", "last_edit": "Ultima modifica", "edited_by": "Modificato da", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "OSMI Modificato", "just_edited": "Hai appena modificato OpenStreetMap!", - "view_on_osm": "Vedi su OSM", - "facebook": "Condividi su Facebook", - "twitter": "Condividi su Twitter", - "google": "Condividi su Google+", - "help_html": "Le tue modifiche appariranno nel livello \"Standard\" tra qualche minuto. Per gli altri livelli e per certi elementi potrebbe essere necessario più tempo.", + "thank_you": "Ti ringraziamo per aver migliorato la mappa.", + "thank_you_location": "Grazie per aver migliorato la mappa attorno a {where}.", + "help_html": "Le tue modifiche dovrebbero apparire su OpenStreetMap entro pochi minuti. Per le altre mappe che usano OpenStreetMap occorrerà attendere po’ di più.", "help_link_text": "Dettagli", - "help_link_url": "https://wiki.openstreetmap.org/wiki/IT:FAQ#Ho_editato_i_dati_tutto_il_giorno.2C_ma_le_mie_modifiche_non_appaiono_nel_viewer.21" + "help_link_url": "https://wiki.openstreetmap.org/wiki/IT:FAQ#Ho_editato_i_dati_tutto_il_giorno.2C_ma_le_mie_modifiche_non_appaiono_nel_viewer.21", + "view_on_osm": "Vedi le modifiche su OSM", + "changeset_id": "Il tuo gruppo di modifiche #: {changeset_id}", + "like_osm": "Ti piace OpenStreetMap? Unisciti agli altri:", + "more": "Altro", + "events": "Eventi", + "languages": "Lingue: {languages}", + "missing": "Manca qualcosa da questa lista?", + "tell_us": "Segnalacelo!" }, "confirm": { "okay": "OK", @@ -730,7 +744,7 @@ "before_start_h": "Prima di iniziare", "before_start": "Prima di iniziare ad effettuare modifiche dovresti essere a conoscenza delle funzioni principali di questo editor e di come funziona OpenstreetMap. In iD è stata integrata una guida interattiva, con lo scopo di insegnare le funzioni indispensabili per la mappatura. Clicca \"Avvia il tutorial\" su questa schermata per iniziare - richiede circa 15 minuti.", "open_source_h": "Open Source", - "open_source": "L'editor iD è un progetto collaborativo open source, tu ora stai usando la versione {versione}. Il codice sorgente è disponibile [su GitHub](https://github.com/openstreetmap/iD).", + "open_source": "L'editor iD è un progetto collaborativo open source, ora stai usando la versione {version}. Il codice sorgente è disponibile [su GitHub](https://github.com/openstreetmap/iD).", "open_source_help": "Puoi contribuire nella [traduzione](https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating) di iD oppure [segnalare problemi](https://github.com/openstreetmap/iD/issues)." }, "overview": { @@ -915,7 +929,7 @@ "title": "Suggerimenti", "simple": "**Preferisci obblighi di svolta semplici invece di altri più complessi.**", "simple_example": "Ad esempio, evita di creare un obbligo di svolta che utilizza un percorso di topo VIA se basta usare un nodo per lo stesso ruolo.", - "indirect": "**Alcuni obblighi di svolta sono segnati con il testo \"{indirect}\" e sono colorati più chiari.**", + "indirect": "**Alcuni obblighi di svolta sono segnati con il testo \"(indiretto)\" e sono colorati più chiari.**", "indirect_example": "Questi obblighi di svolta esistono come conseguenza di un altro obbligo nei dintorni. Ad esempio, un \"obbligo di direzione obbligatoria\" genererà automaticamente un \"divieto di inversione di marcia\" per tutti gli altri percorsi che attraversano l'intersezione.", "indirect_noedit": "Non puoi modificare gli obblighi di svolta indiretti. Al loro posto, modifica i normali obblighi di svolta vicini." } @@ -1396,7 +1410,7 @@ "bicycle": "Biciclette", "foot": "A piedi", "horse": "Cavalli", - "motor_vehicle": "Veicoli a Motore" + "motor_vehicle": "Veicoli a motore" } }, "access_simple": { @@ -1579,7 +1593,7 @@ }, "cables": { "label": "Cavi", - "placeholder": "1, 2, 3,..." + "placeholder": "1, 2, 3..." }, "camera/direction": { "label": "Direzione (gradi in senso orario)", @@ -1666,7 +1680,7 @@ "label": "Rete" }, "cycleway": { - "label": "Corsie Ciclabili", + "label": "Corsie ciclabili", "options": { "lane": { "description": "Una corsia ciclabile separata dal traffico motorizzato da una linea disegnata", @@ -1723,7 +1737,7 @@ }, "devices": { "label": "Dispositivi", - "placeholder": "1, 2, 3,..." + "placeholder": "1, 2, 3..." }, "diaper": { "label": "Fasciatoio" @@ -1774,6 +1788,9 @@ "display": { "label": "Display" }, + "distance": { + "label": "Distanza totale" + }, "dock": { "label": "Tipologia" }, @@ -1789,10 +1806,10 @@ "options": { "contact_line": "Linea Aerea di Contatto", "no": "No", - "rail": "Rotaia Elettrificata", + "rail": "Rotaia elettrificata", "yes": "Sì (non specificato)" }, - "placeholder": "Linea Aerea, Rotaia Elettrificata..." + "placeholder": "Linea aerea, rotaia elettrificata..." }, "elevation": { "label": "Altitudine" @@ -1814,6 +1831,9 @@ "except": { "label": "Eccezioni" }, + "faces": { + "label": "Facciate" + }, "fax": { "label": "Fax", "placeholder": "+39 01 123 456" @@ -1925,6 +1945,39 @@ "label": "Canestri", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Dressage", + "options": { + "equestrian": "Sì", + "undefined": "No" + } + }, + "horse_riding": { + "label": "Cavalcata", + "options": { + "horse_riding": "Sì", + "undefined": "No" + } + }, + "horse_scale": { + "label": "Livello di difficoltà della cavalcata", + "options": { + "common": "Facile: nessun ostacolo o difficoltà. (predefinito)", + "critical": "Intermedio: effettuabile solo da cavalieri esperti e cavalli in forma. Ostacoli importanti. I ponti vanno esaminati accuratamente.", + "dangerous": "Pericoloso: solo per cavalieri molto esperti e cavalli in forma se le condizioni meteo lo permettono. È necessario scendere da cavallo.", + "demanding": "Da praticare con cautela: strada disconnessa con passaggi occasionalmente difficili.", + "difficult": "Difficile: percorso stretto ed esposto. Possono esserci ostacoli da saltare e passaggi stretti.", + "impossible": "Impraticabile: il percorso/ponte non è adatto ai cavalli. Troppo stretto, non può tenere il peso dell’animale oppure ci sono ostacoli come scale. Pericolo di vita." + }, + "placeholder": "Difficile, pericoloso..." + }, + "horse_stables": { + "label": "Scuderia ippica", + "options": { + "stables": "Sì", + "undefined": "No" + } + }, "iata": { "label": "IATA" }, @@ -1944,6 +1997,9 @@ "indoor": { "label": "Al chiuso" }, + "industrial": { + "label": "Tipo" + }, "information": { "label": "Tipo" }, @@ -2058,12 +2114,16 @@ }, "maxheight": { "label": "Altezza massima", - "placeholder": "4, 4.5, 5, 14'0\", 14'6\", 15'0\", ..." + "placeholder": "4, 4.5, 5, 14'0\", 14'6\", 15'0\"" }, "maxspeed": { "label": "Limite di velocità", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "Limite di velocità consigliata", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Limite orario" }, @@ -2077,7 +2137,7 @@ "label": "Controllo" }, "mtb/scale": { - "label": "Difficoltà Mountain Bike", + "label": "Difficoltà mountain bike", "options": { "0": "0: Ghiaia solida/terra battuta, nessun ostacolo, curve ampie", "1": "1: Un po' di terriccio, piccoli ostacoli, curve ampie", @@ -2105,10 +2165,10 @@ "options": { "0": "0: Pendenza media <10%, ghiaia/terra battuta, nessun ostacolo", "1": "1: Pendenza media <15%, ghiaia/terra battuta, ostacoli rari e piccoli", - "2": "2: Pendenza media <20%, superficie stabile, radici/roccie grandi come un pugno", - "3": "3: Pendenza media <25%, superficie varia, rami/roccie grandi come un pugno", - "4": "4: Pendenza media <30%, in cattive condizioni, rami/roccie grandi", - "5": "5: Pendenza estrema, in genere è necessario spigere o sollevare la bici" + "2": "2: Pendenza media <20%, superficie stabile, radici/rocce grandi come un pugno", + "3": "3: Pendenza media <25%, superficie varia, rami/rocce grandi come un pugno", + "4": "4: Pendenza media <30%, in cattive condizioni, rami/rocce grandi", + "5": "5: Pendenza estrema, in genere è necessario spingere o sollevare la bici" }, "placeholder": "0, 1, 2, 3..." }, @@ -2296,6 +2356,7 @@ "label": "Tipo" }, "railway/position": { + "label": "Posizione della pietra miliare", "placeholder": "Distanza ad una cifra decimale (123.4)" }, "railway/signal/direction": { @@ -2545,6 +2606,9 @@ "switch": { "label": "Tipo", "options": { + "circuit_breaker": "Interruttore automatico", + "disconnector": "Sezionatore", + "earthing": "Sezionatore di terra", "mechanical": "Meccanico" } }, @@ -2648,8 +2712,19 @@ "label": "Tipo", "placeholder": "Default" }, + "usage_rail": { + "label": "Tipo di utilizzo", + "options": { + "branch": "Secondario", + "industrial": "Industriale", + "main": "Principale", + "military": "Militare", + "test": "Per collaudi", + "tourism": "Turismo" + } + }, "vending": { - "label": "Beni venduti" + "label": "Tipi di prodotti" }, "visibility": { "label": "Visibilità", @@ -2709,6 +2784,9 @@ "wheelchair": { "label": "Accesso in carrozzina" }, + "wholesale": { + "label": "Vendita all’ingrosso" + }, "width": { "label": "Larghezza (Metri)" }, @@ -2717,7 +2795,7 @@ }, "windings": { "label": "Avvolgimenti", - "placeholder": "1, 2, 3,..." + "placeholder": "1, 2, 3..." }, "windings/configuration": { "label": "Configurazione degli avvolgimenti", @@ -2741,6 +2819,10 @@ "name": "Cartellone pubblicitario", "terms": "pubblicità,cartellone,promozione,propaganda,réclame,manifesto" }, + "advertising/column": { + "name": "Espositore pubblicitario cilindrico", + "terms": "espositore pubblicitario,espositori,cilindro,cilindrico,pubblicità,cartellone,totem" + }, "aerialway": { "name": "Trasporto a fune" }, @@ -2826,20 +2908,24 @@ "name": "Terminal aeroportuale", "terms": "aeroporto,aerodromo,terminale" }, + "allotments/plot": { + "name": "Orto pubblico", + "terms": "orto pubblico,anziano,anziani,orti urbani,orto,orti,orto per anziani" + }, "amenity": { "name": "Servizi" }, "amenity/animal_boarding": { "name": "Pensione per animali", - "terms": "pet,resort,hotel,rifugio,can*,gatt*,cavall*,cucciol*,rettil*" + "terms": "pet,resort,hotel,rifugio,pensione,cane,cani,gatto,gatti,cavallo,cavalli,cucciolo,cuccioli,rettile,rettili" }, "amenity/animal_breeding": { "name": "Allevamento", - "terms": "tor*,gatt*,vivaio,can*,mucc*,cavall*,cucciol*,rettil*,allevatore" + "terms": "toro,tori,gatto,gatti,vivaio,cane,cani,mucca,mucche,cavallo,cavalli,cavalle,cucciolo,cuccioli,rettile,rettili,allevatore" }, "amenity/animal_shelter": { "name": "Rifugio per animali", - "terms": "adozion*,gatt*,can*,cucciol*,rettil*,ricovero,riparo" + "terms": "adozione,adozioni,gatto,gatti,micio,cane,cani,cucciolo,cuccioli,rettile,rettili,ricovero,riparo" }, "amenity/arts_centre": { "name": "Centro Culturale", @@ -2871,7 +2957,7 @@ }, "amenity/bicycle_rental": { "name": "Stazione del Bike Sharing", - "terms": "" + "terms": "noleggio bici,noleggio biciclette,nolo bici,nolo biciclette,noleggio velocipedi,prestito biciclette,bike sharing" }, "amenity/bicycle_repair_station": { "name": "Stazione di riparazione biciclette", @@ -2890,7 +2976,7 @@ "terms": "cambi,ufficio cambi,cambio,valuta,cambiovaluta" }, "amenity/bus_station": { - "name": "Stazione autobus" + "name": "Stazione /Terminal degli autobus" }, "amenity/cafe": { "name": "Caffè", @@ -2898,7 +2984,7 @@ }, "amenity/car_pooling": { "name": "Condivisione automobile", - "terms": "" + "terms": "car pooling,auto di gruppo,concarreggio,condivisione auto" }, "amenity/car_rental": { "name": "Noleggio auto", @@ -2934,11 +3020,11 @@ }, "amenity/clinic/abortion": { "name": "Clinica per aborti", - "terms": "" + "terms": "clinica abortiva,clinica per l’aborto,ospedale per l’aborto,centro per l’aborto,centro abortivo" }, "amenity/clinic/fertility": { "name": "Centro fecondazione assistita", - "terms": "" + "terms": "clinica fertilità,clinica della fertilità,centro fertilità,centro fecondazione assistita,centro della fecondazione assistita,clinica della fecondazione assistita,clinica fecondazione assistita,centro di procreazione assistita,clinica di procreazione assistita" }, "amenity/clock": { "name": "Orologio", @@ -2985,7 +3071,7 @@ }, "amenity/driving_school": { "name": "Scuola guida", - "terms": "autoscuola,auto*,macchina,guida,scuola" + "terms": "autoscuola,auto,macchina,guida,scuola,scuolaguida,autobus,ambulanze,camion" }, "amenity/embassy": { "name": "Ambasciata", @@ -2996,7 +3082,7 @@ "terms": "Fast Food" }, "amenity/ferry_terminal": { - "name": "Stazione battelli" + "name": "Stazione / Terminal dei battelli" }, "amenity/fire_station": { "name": "Caserma dei pompieri", @@ -3004,7 +3090,7 @@ }, "amenity/food_court": { "name": "Zona ristorazione", - "terms": "" + "terms": "food court,zona ristorazione,area cibo,ristoranti,cibo" }, "amenity/fountain": { "name": "Fontana", @@ -3023,7 +3109,7 @@ "terms": "spandisale,sale,ghiaccio,inverno,salare" }, "amenity/hospital": { - "name": "Area Ospedaliera", + "name": "Area ospedaliera", "terms": "ospedale,clinica,pronto soccorso,servizio sanitario,salute,hospice,ospizio,infermeria,istituzione,casa di cura,casa di riposo,sanatorio,ambulatorio,chirurgia,reparto" }, "amenity/hunting_stand": { @@ -3032,7 +3118,7 @@ }, "amenity/ice_cream": { "name": "Gelateria", - "terms": "gelat*,semifredd*,yogurt,sorbett*,ghiacciol*" + "terms": "gelato,gelati,gelataio,semifreddo,semifreddi,yogurt,sorbetto,sorbetti,ghiacciolo,ghiaccoli,grattachecca,sorbetteria,gelateria" }, "amenity/internet_cafe": { "name": "Internet Cafe", @@ -3048,19 +3134,23 @@ }, "amenity/love_hotel": { "name": "Love Hotel", - "terms": "" + "terms": "hotel per coppie,motel per coppie,hotel a ore,sexy motel" }, "amenity/marketplace": { "name": "Mercato", "terms": "Mercato" }, + "amenity/monastery": { + "name": "Montastero", + "terms": "monastero,abbazia,badia" + }, "amenity/motorcycle_parking": { "name": "Parcheggio moto", "terms": "parcheggio scooter,moto,scooter" }, "amenity/music_school": { "name": "Scuola di musica", - "terms": "" + "terms": "scuola di musica,lezioni di musica,scuola di piano,scuola di violino,scuola di batteria,educazione musicale,lezioni di musica" }, "amenity/nightclub": { "name": "Discoteca", @@ -3083,7 +3173,7 @@ }, "amenity/pavilion": { "name": "Tendone", - "terms": "padiglione,tend*" + "terms": "padiglione,tenda,tende" }, "amenity/pharmacy": { "name": "Farmacia", @@ -3103,7 +3193,7 @@ }, "amenity/place_of_worship/hindu": { "name": "Tempio Hindu", - "terms": "" + "terms": "tempio indiano,tempio indù,tempio induista,mandir" }, "amenity/place_of_worship/jewish": { "name": "Sinagoga", @@ -3115,15 +3205,15 @@ }, "amenity/place_of_worship/shinto": { "name": "Tempio Shintoista", - "terms": "" + "terms": "jinja,tempio giapponese,tempio shintoista,santuario shintoista" }, "amenity/place_of_worship/sikh": { "name": "Tempio Sikh", - "terms": "" + "terms": "tempio indiano,tempio sikh" }, "amenity/place_of_worship/taoist": { "name": "Tempio Taoista", - "terms": "" + "terms": "tempio taoista,tempio daoista,tempio cinese,dàoguàn" }, "amenity/planetarium": { "name": "Planetario", @@ -3151,7 +3241,7 @@ }, "amenity/public_bath": { "name": "Bagni Pubblici", - "terms": "" + "terms": "bagni,bagno,bagno turco,sorgenti calde,terme,bagni termali,onsen,hammam,vasca delle abluzioni,lavacro" }, "amenity/public_bookcase": { "name": "Libreria pubblica", @@ -3163,7 +3253,7 @@ }, "amenity/recycling": { "name": "Cassonetto per raccolta differenziata", - "terms": "" + "terms": "contenitore del riciclaggio,riciclaggio,vetro,plastica,bottiglie,alluminio" }, "amenity/recycling_centre": { "name": "Centro di riciclaggio", @@ -3193,11 +3283,11 @@ }, "amenity/shower": { "name": "Doccia", - "terms": "" + "terms": "docce,doccia,doccia calda,doccia fredda, doccia pubblica" }, "amenity/smoking_area": { "name": "Area fumatori", - "terms": "" + "terms": "area per fumatori,fumare,fumatori,fumatore,sigarette" }, "amenity/social_facility": { "name": "Centro socio-assistenziale", @@ -3258,6 +3348,10 @@ "name": "Distributore automatico di sigarette", "terms": "distributore automatico,macchinetta,sigarette,tabacco,cartine,accendini" }, + "amenity/vending_machine/coffee": { + "name": "Macchinetta del caffè", + "terms": "caffè,cafe,coffee,moka,cappuccino,latte,espresso,tazzina,macchiato" + }, "amenity/vending_machine/condoms": { "name": "Distributore automatico di preservativi", "terms": "distributore automatico,macchinetta,preservativi" @@ -3266,13 +3360,33 @@ "name": "Distributore automatico di bevande", "terms": "distributore automatico,macchinetta,bevande,bottiglie,bottigliette" }, + "amenity/vending_machine/electronics": { + "name": "Macchinetta accessori elettrici", + "terms": "cavi,caricabatterie,cuffie,cuffiette,telefono,smartphone,tablet,usb" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Macchinetta di monete da souvenir", + "terms": "moneta,monete,appiatita,appiattite,schiacciata,schiacciate,allungata,allungate,penny,souvenir,turismo,ricordo,commemorativa,commemorative" + }, "amenity/vending_machine/excrement_bags": { "name": "Distributore automatico di sacchetti per escrementi", "terms": "distributore automatico,macchinetta,cacca,cane" }, "amenity/vending_machine/feminine_hygiene": { "name": "Distributore automatico di prodotti per l'igiene femminile", - "terms": "" + "terms": "preservativo,preservativi,pillola,coppetta,spirale,profilattico,profilattici,tampone,tamponi,assorbente,assorbenti,assorbente interno,assorbenti interni,donna,donne,femmina,femmine,femminilità,sviluppo,mestruazioni,ciclo,mestruale,prodotti di igiene,prodotti per la persona,cura della persona" + }, + "amenity/vending_machine/food": { + "name": "Macchinetta del cibo", + "terms": "cibo,barrette,sandwich,panini,cioccolata,tramezzini" + }, + "amenity/vending_machine/fuel": { + "name": "Pompa della benzina", + "terms": "benzina,petrolio,propano,diesel,benzene,ottani,verde,senza piombo,gpl,metano,bioetanolo,biodiesel," + }, + "amenity/vending_machine/ice_cream": { + "name": "Macchinetta del gelato", + "terms": "gelato,cioccolata,ghiaccoli,ghiacciato,vaniglia,grattachecca,gelati,panna,fragola,pistacchio" }, "amenity/vending_machine/news_papers": { "name": "Distributore automatico di giornali" @@ -3293,6 +3407,10 @@ "name": "Distributore automatico di biglietti per trasporto pubblico", "terms": "distributore automatico,macchinetta,biglietti,bus,metro,tram" }, + "amenity/vending_machine/stamps": { + "name": "Macchinetta dei francobolli", + "terms": "posta,spedizione,invio,francobollo,francobolli,marca da bollo" + }, "amenity/vending_machine/sweets": { "name": "Distributore automatico di snack", "terms": "distributore automatico,macchinetta,snack,cibo" @@ -3303,7 +3421,7 @@ }, "amenity/waste/dog_excrement": { "name": "Cestino per escrementi animali", - "terms": "" + "terms": "cestino deiezioni canine,cacca,popò,cane,cani,deiezioni,sacchetti" }, "amenity/waste_basket": { "name": "Cestino della spazzatura", @@ -3323,7 +3441,7 @@ }, "amenity/watering_place": { "name": "Abbeveratoio", - "terms": "acqua,fontan*,abbever*,animal*" + "terms": "acqua,fontana,fontanella,abbeveratoio,animale,animali" }, "area": { "name": "Area", @@ -3335,11 +3453,11 @@ }, "attraction/amusement_ride": { "name": "Parco divertimenti", - "terms": "" + "terms": "parco a tema,parco tematico,parco di divertimento,parco divertimenti,parco dei divertimenti,giostra,giostre,attrazione,ruota panoramica" }, "attraction/animal": { "name": "Animale", - "terms": "" + "terms": "zoo,zoo safari,safari,parco animali,gabbia,gabbie,leone,leoni,tigre,tigri,orso,orsi,giraffa,giraffe,elefante,elefanti,zebra,zebre" }, "attraction/big_wheel": { "name": "Ruota panoramica", @@ -3362,8 +3480,13 @@ "terms": "" }, "attraction/drop_tower": { + "name": "Torre a caduta libera", "terms": "" }, + "attraction/maze": { + "name": "Labirinto", + "terms": "parco a tema,parco tematico,parco di divertimento,parco divertimenti,parco dei divertimenti,giostra,giostre,attrazione,divertimento,labirinto,dedalo" + }, "attraction/pirate_ship": { "name": "Nave dei pirati", "terms": "" @@ -3481,7 +3604,7 @@ }, "building/bungalow": { "name": "Bungalow", - "terms": "" + "terms": "bungalow,campeggio,alloggio,residence" }, "building/bunker": { "name": "Bunker" @@ -3504,7 +3627,7 @@ }, "building/civic": { "name": "Edificio comunale", - "terms": "" + "terms": "civico,municipale,pubblico,cittadino" }, "building/college": { "name": "Edificio di un College", @@ -3529,14 +3652,26 @@ "building/entrance": { "name": "Entrata/Uscita" }, + "building/farm": { + "name": "Residenza della fattoria", + "terms": "fattoria,casa del fattore,casa del contadino,residenza del contadino,residenza del fattore,dimora del contadino,dimora del fattore,casa colonica" + }, + "building/farm_auxiliary": { + "name": "Edificio della fattoria non abitato", + "terms": "fattoria,casa di campagna,rudere,cascinale,casale,casolare,rustico,casa rurale,capanno,magazzino" + }, "building/garage": { "name": "Garage", - "terms": "Garage" + "terms": "garage,posto auto,auto,box" }, "building/garages": { "name": "Garage", "terms": "Garage,rimesse" }, + "building/grandstand": { + "name": "Tribuna", + "terms": "tribuna,gradinata,gradinate,curva,curve,spalto,spalti" + }, "building/greenhouse": { "name": "Serra", "terms": "serra,coltivazione,piante,orto,coltivazione,vegetali" @@ -3567,7 +3702,7 @@ }, "building/mosque": { "name": "Moschea (edificio)", - "terms": "" + "terms": "moschea,moschee,islam,sala della preghiera,preghiera,minareto" }, "building/public": { "name": "Edificio pubblico", @@ -3587,7 +3722,7 @@ }, "building/ruins": { "name": "Edificio in rovina", - "terms": "" + "terms": "rovina,rovine,distrutto,pericolante,pericolo,crollo,crolli,crollato,collassato,collasso" }, "building/school": { "name": "Edificio scolastico", @@ -3599,7 +3734,7 @@ }, "building/service": { "name": "Edificio di servizio", - "terms": "" + "terms": "servizio,stazione di servizio,sottostazione,sala,sala trasformatori,sala pompe,pompa" }, "building/shed": { "name": "Capanno", @@ -3611,7 +3746,7 @@ }, "building/stadium": { "name": "Stadio", - "terms": "" + "terms": "stadio,stadio olimpico,olimpico,stadio di calcio,stadio del ghiaccio,stadio sportivo,sport,sportivo,arena,palazzetto" }, "building/static_caravan": { "name": "Roulotte stazionaria", @@ -3619,7 +3754,7 @@ }, "building/temple": { "name": "Tempio", - "terms": "" + "terms": "tempio,templi,luogo di preghiera" }, "building/terrace": { "name": "Villette a schiera", @@ -3644,9 +3779,12 @@ "name": "Piazzola", "terms": "Piazzola,lotto" }, + "circular": { + "name": "Strada rotonda senza precedenza" + }, "club": { "name": "Club", - "terms": "social*,centr*" + "terms": "sociale,centro,centro sociale,centro aggregazione,centro culturale" }, "craft": { "name": "Mestiere", @@ -3956,7 +4094,7 @@ }, "healthcare": { "name": "Clinica", - "terms": "" + "terms": "clinica,ospedale,clinica ospedaliera,dottori,studio dottori,medicina,aiuto medico,guardia medica,centro igiene mentale,pediatra,medico,oftalmologo,dentista,ginecologo,andrologo,geriatra,medico dello sport" }, "healthcare/alternative": { "name": "Medicina alternativa", @@ -3982,11 +4120,16 @@ "name": "Ospizio", "terms": "" }, + "healthcare/laboratory": { + "name": "Laboratorio medico", + "terms": "laboratorio,clinica,medico,medica,medicina,esame del sangue,esami del sangue,laboratorio medico,controllo medico,controlli medici" + }, "healthcare/midwife": { "name": "Clinica prenatale", "terms": "" }, "healthcare/occupational_therapist": { + "name": "Medico del lavoro", "terms": "" }, "healthcare/optometrist": { @@ -4083,6 +4226,10 @@ "name": "Svincolo autostradale", "terms": "Svincolo autostradale" }, + "highway/passing_place": { + "name": "Slargo per passaggio", + "terms": "slargo,sorpasso,zona,incrocio,area di sorpasso,area di incrocio,slargo di sorpasso,slargo di incrocio" + }, "highway/path": { "name": "Sentiero", "terms": "Sentiero" @@ -4105,7 +4252,7 @@ }, "highway/raceway": { "name": "Circuito (Motoristico)", - "terms": "pista,autodromo,pista automobilistica,pista motoristica,auto*,moto*" + "terms": "pista,autodromo,pista automobilistica,pista motoristica,auto,moto,motori,nascar,corsa,formula uno" }, "highway/residential": { "name": "Residenziale", @@ -4265,7 +4412,7 @@ }, "landuse/aquaculture": { "name": "Acquacoltura", - "terms": "pesci,crostacei,alghe,gamber*,maricoltura,algacoltura" + "terms": "pesci,crostacei,alghe,gambero,gamberi,gamberetti,aragoste,maricoltura,algacoltura,allevamento,molluschi,cozze,ostriche,orate" }, "landuse/basin": { "name": "Bacino", @@ -4336,7 +4483,7 @@ }, "landuse/industrial/slaughterhouse": { "name": "Macello", - "terms": "macello,mattatoio,abbattimento,macelleria,macellaio,gallin*,mucc*,carne,suin*,maial*,animali" + "terms": "macello,mattatoio,abbattimento,macelleria,macellaio,galline,gallina,mucca,mucche,carne,suino,suini,maiale,maiali,tacchino,tacchini,animali" }, "landuse/landfill": { "name": "Discarica", @@ -4376,7 +4523,7 @@ }, "landuse/military/nuclear_explosion_site": { "name": "Sito per esplosioni nucleari", - "terms": "bomba,atomica,poligono,tiro,lancio,missil*,test,nucleare" + "terms": "bomba,atomica,poligono,tiro,lancio,missile,missili,nucleare,test,nucleare" }, "landuse/military/obstacle_course": { "name": "Percorso ad ostacoli", @@ -4388,7 +4535,7 @@ }, "landuse/military/range": { "name": "Poligono di tiro militare", - "terms": "poligono,militare,tiro,lancio,bombe,missil*" + "terms": "poligono,militare,militari,tiro,lancio,bombe,missile,missili,forze militari,forza aerea,forza,guardia,armi,fuoco,marina,fucile,cecchino,cecchini,truppe,truppa,addestramento,guerra,battaglia,battaglione" }, "landuse/military/training_area": { "name": "Area di addestramento", @@ -4442,6 +4589,10 @@ "name": "Sala giochi", "terms": "Videogiochi" }, + "leisure/beach_resort": { + "name": "Stabilimento balnerare", + "terms": "spiaggia,spiaggia attrezzata,bagni,bagno,stabilimento balneare" + }, "leisure/bird_hide": { "name": "osservazione uccelli", "terms": "Capanno di osservazione" @@ -4459,7 +4610,8 @@ "terms": "ballo,danza,jive,swing,tango,valzer,balera" }, "leisure/dancing_school": { - "name": "Scuola di danza" + "name": "Scuola di danza", + "terms": "scuola di danza,danza,lezioni di danza,imparare a danzare,danzare,maestro di danza" }, "leisure/dog_park": { "name": "Area per cani", @@ -4494,6 +4646,7 @@ "terms": "" }, "leisure/fitness_station/horizontal_ladder": { + "name": "Scala orizzontale", "terms": "" }, "leisure/fitness_station/hyperextension": { @@ -4502,7 +4655,7 @@ }, "leisure/fitness_station/parallel_bars": { "name": "Barre Parallele", - "terms": "barr*,esercizi,fitness,palestra,percorso" + "terms": "barra,trazioni,barre,esercizi,fitness,palestra,percorso" }, "leisure/fitness_station/push-up": { "name": "Stazione per piegamenti sulle braccia", @@ -4533,11 +4686,12 @@ "terms": "Campo da golf" }, "leisure/hackerspace": { + "name": "Spazio hacker", "terms": "" }, "leisure/horse_riding": { "name": "Centro equestre", - "terms": "cavall*,equestre,circolo,ippica,club" + "terms": "cavallo,cavalli,equestre,circolo,ippica,club,destrieri,stalla,stalle" }, "leisure/ice_rink": { "name": "Pista di Ghiaccio", @@ -4555,6 +4709,10 @@ "name": "Riserva naturale", "terms": "riserva,natura,parco,naturale" }, + "leisure/outdoor_seating": { + "name": "Posti a sedere all’esterno", + "terms": "giardino,patio,esterno,aperto,all’aperto,cena,caffè,merenda,pub,ristorante,bar,veranda,dehors" + }, "leisure/park": { "name": "Parco", "terms": "lungomare,tenuta,foresta,giardino,prato,verde,terreni,lotto,pascolo,parco,parco giochi,area ricreativa,piazza,giardino pubblico,bosco" @@ -4597,7 +4755,7 @@ }, "leisure/pitch/equestrian": { "name": "Maneggio", - "terms": "dressage,equestre,cavall*,cavalcat*" + "terms": "dressage,equestre,cavallo,cavalli,cavalcata,cavalcate" }, "leisure/pitch/rugby_league": { "name": "Campo di rugby a 13", @@ -4683,6 +4841,10 @@ "name": "Cunicolo", "terms": "adito,miniera,ingresso" }, + "man_made/antenna": { + "name": "Antenna", + "terms": "cella,stazione,trasmissione,trasmissioni,comunicazione,comunicazioni,telecomunicazione,cellulare,cellulari,smartphone,gsm,telefono,telefoni,telefonia,telefonica,radio,televisione,tv,etere" + }, "man_made/breakwater": { "name": "Frangiflutti", "terms": "Frangifrutti" @@ -4695,6 +4857,10 @@ "name": "Ciminiera", "terms": "torre,camino" }, + "man_made/clearcut": { + "name": "Area disboscata", + "terms": "taglio,bosco,foresta,legna,legname,legno,albero,alberi,tronchi,disboscamento,deforestazione,selvicoltura" + }, "man_made/crane": { "name": "Gru", "terms": "" @@ -4734,6 +4900,10 @@ "name": "Torre di osservazione", "terms": "torre,osservazione,osservatorio,piattaforma,osservativa,antincendio,panorama" }, + "man_made/observatory": { + "name": "Osservatorio", + "terms": "osservatorio,astronomico,meteorologico,vulcanologico,osservatorio meteorologico,osservatorio astronomico,radiotelescopio" + }, "man_made/petroleum_well": { "name": "Pozzo petrolifero", "terms": "petrolio,bitume,pozzo" @@ -4835,8 +5005,8 @@ "terms": "grotta,caverna,anfratto,dolina" }, "natural/cliff": { - "name": "Scogliera", - "terms": "Rupe" + "name": "Rupe", + "terms": "Rupe,parete,dirupo,scogliera,scogliera a picco" }, "natural/coastline": { "name": "Linea di costa", @@ -4858,10 +5028,18 @@ "name": "Brughiera", "terms": "Brughiera" }, + "natural/mud": { + "name": "Fango", + "terms": "fango,fangoso,umido,bagnato,terra bagnata,melmoso,paludoso,palude" + }, "natural/peak": { "name": "Picco", "terms": "culmine,guglia,alpe,apice,cresta,sommità,cima,cocuzzolo,collina,monte,montagna,pinnacolo,estremità,vertice,vetta,piz" }, + "natural/reef": { + "name": "Scogliera", + "terms": "barriera,corallo,coralli,barriera corallina,reef,scogli,sommerso,subacqueo" + }, "natural/ridge": { "name": "Crinale", "terms": "cresta" @@ -4924,7 +5102,7 @@ }, "noexit/yes": { "name": "Senza uscita", - "terms": "strada,senza,uscita,fine,punto,mort*" + "terms": "strada,senza,uscita,fine,punto,morto,strada senza uscita" }, "office": { "name": "Uffici", @@ -4986,6 +5164,7 @@ "terms": "finanza,finanziaria,fiduciaria,mag" }, "office/forestry": { + "name": "Ufficio forestale", "terms": "" }, "office/foundation": { @@ -5051,6 +5230,7 @@ "terms": "" }, "office/quango": { + "name": "Ufficio di una simil ONG", "terms": "" }, "office/research": { @@ -5119,6 +5299,7 @@ "terms": "Quartiere,Zona" }, "place/plot": { + "name": "Particella catastale", "terms": "" }, "place/quarter": { @@ -5127,7 +5308,7 @@ }, "place/square": { "name": "Piazza", - "terms": "piazz*,spiazzo,slargo" + "terms": "piazza,piazze,piazzale,spiazzo,slargo,largo" }, "place/suburb": { "name": "Sobborgo", @@ -5162,6 +5343,7 @@ "terms": "" }, "playground/horizontal_bar": { + "name": "Barra per trazioni", "terms": "" }, "playground/rocker": { @@ -5225,7 +5407,7 @@ }, "power/plant": { "name": "Area della Centrale elettrica", - "terms": "carbone,gas,generatore,idroelettrico,nucleare,energia,elettric*,centrale" + "terms": "carbone,gas,generatore,idroelettrico,nucleare,energia,elettrica,elittricità,elettrico,centrale,produzione" }, "power/pole": { "name": "Palo della luce", @@ -5251,6 +5433,7 @@ "terms": "Trasformatore" }, "public_transport/linear_platform": { + "name": "Fermata / Banchina del trasporto pubblico", "terms": "" }, "public_transport/linear_platform_aerialway": { @@ -5286,9 +5469,11 @@ "terms": "" }, "public_transport/linear_platform_trolleybus": { + "name": "Fermata / Banchina del filobus", "terms": "" }, "public_transport/platform": { + "name": "Fermata / Banchina del trasporto pubblico", "terms": "" }, "public_transport/platform_aerialway": { @@ -5324,9 +5509,11 @@ "terms": "" }, "public_transport/platform_trolleybus": { + "name": "Fermata / Banchina del filobus", "terms": "" }, "public_transport/station": { + "name": "Stazione del trasporto pubblico", "terms": "" }, "public_transport/station_aerialway": { @@ -5342,7 +5529,7 @@ "terms": "" }, "public_transport/station_light_rail": { - "name": "Stazione del tram", + "name": "Stazione della metropolitana di superficie", "terms": "" }, "public_transport/station_monorail": { @@ -5366,15 +5553,19 @@ "terms": "" }, "public_transport/station_trolleybus": { + "name": "Stazione / Terminal dei filobus", "terms": "" }, "public_transport/stop_area": { + "name": "Area della fermata del trasporto pubblico", "terms": "" }, "public_transport/stop_position": { + "name": "Punto di stop del trasporto pubblico", "terms": "" }, "public_transport/stop_position_aerialway": { + "name": "Punto di stop del trasporto a fune", "terms": "" }, "public_transport/stop_position_bus": { @@ -5386,12 +5577,15 @@ "terms": "" }, "public_transport/stop_position_light_rail": { + "name": "Punto di stop della metropolitana di superficie", "terms": "" }, "public_transport/stop_position_monorail": { + "name": "Punto di stop della monorotaia", "terms": "" }, "public_transport/stop_position_subway": { + "name": "Punto di stop della metropolitana", "terms": "" }, "public_transport/stop_position_train": { @@ -5399,9 +5593,11 @@ "terms": "" }, "public_transport/stop_position_tram": { + "name": "Punto di stop del tram", "terms": "" }, "public_transport/stop_position_trolleybus": { + "name": "Punto di stop del filobus", "terms": "" }, "railway": { @@ -5412,7 +5608,8 @@ "terms": "Ferrovia abbandonata" }, "railway/buffer_stop": { - "terms": "" + "name": "Respingente", + "terms": "respingente,stop,ammortizzatore,fine linea" }, "railway/crossing": { "name": "Passaggio a livello (sentiero)", @@ -5438,8 +5635,8 @@ "terms": "passaggio a livello,incrocio ferroviario,attraversamento" }, "railway/light_rail": { - "name": "Tram", - "terms": "" + "name": "Metropolitana di superficie", + "terms": "tranvia,metrotranvia,metropolitana,metropolitana di superficie" }, "railway/milestone": { "name": "Pietra miliare ferroviaria", @@ -5447,7 +5644,7 @@ }, "railway/miniature": { "name": "Ferrovia in miniatura", - "terms": "" + "terms": "trenino,treno in miniatura,scartamento ridotto,scartamento minimo,ferrovia,binario" }, "railway/monorail": { "name": "Monorotaia", @@ -5485,7 +5682,7 @@ }, "railway/train_wash": { "name": "Lavaggio treni", - "terms": "" + "terms": "lavaggio,pulizia,treni,treno" }, "railway/tram": { "name": "Tram", @@ -5519,7 +5716,7 @@ }, "shop/anime": { "name": "Negozio di manga", - "terms": "Negozio di anime" + "terms": "negozio di anime,anime,manga,Giappone,cosplay,figurine,fumetti,costumi" }, "shop/antiques": { "name": "Antiquario", @@ -5531,7 +5728,7 @@ }, "shop/art": { "name": "Negozio di opere d'arte", - "terms": "opere d'arte,quadri,sculture,galleria,art*" + "terms": "opere d'arte,quadri,sculture,galleria,arte,esibizione,mostra" }, "shop/baby_goods": { "name": "Negozio di prodotti per l'infanzia", @@ -5733,7 +5930,7 @@ }, "shop/gas": { "name": "Bombolaio", - "terms": "gas,bombol*,gpl,metano,lpg,cng,gas naturale,propano" + "terms": "gas,bombole,bombola,gpl,metano,lpg,cng,gas naturale,propano,ricarica bombole,ricarica" }, "shop/gift": { "name": "Negozio souvenir", @@ -5751,6 +5948,10 @@ "name": "Ferramenta", "terms": "Negozio di Ferramenta" }, + "shop/health_food": { + "name": "Prodotti per il benessere", + "terms": "prodotti genuini,benessere,negozio di prodotti biologici,negozio di prodotti per la salute,prodotti per la salute" + }, "shop/hearing_aids": { "name": "Negozio di apparecchi acustici", "terms": "Apparecchi acustici,Negozio di apparecchi acustici" @@ -5777,7 +5978,7 @@ }, "shop/kiosk": { "name": "Chiosco", - "terms": "" + "terms": "chiosco,edicola,tabacchi,dolciumi,snack" }, "shop/kitchen": { "name": "Negozio di cucine", @@ -5793,7 +5994,7 @@ }, "shop/locksmith": { "name": "Fabbro", - "terms": "" + "terms": "fabbro,ferraio,serrature,chiavi,ferro battuto" }, "shop/lottery": { "name": "Ricevitoria", @@ -5865,12 +6066,16 @@ }, "shop/perfumery": { "name": "Profumeria", - "terms": "profum*" + "terms": "profumi,profumo,profumeria" }, "shop/pet": { "name": "Negozio di animali", "terms": "Negozio di animali" }, + "shop/pet_grooming": { + "name": "Toelettatura per animali", + "terms": "cane,gatto,cani,gatti,toilette,toletta,tolettatura,toelettatura,parrucchiere,unghie,shampoo," + }, "shop/photo": { "name": "Fotografo", "terms": "fotografia,fotografico,fotografo,foto,diapositive,rullini,macchine fotografiche" @@ -5912,7 +6117,7 @@ "terms": "Cartoleria" }, "shop/storage_rental": { - "name": "Noleggio", + "name": "Box a noleggio", "terms": "noleggio" }, "shop/supermarket": { @@ -5937,7 +6142,7 @@ }, "shop/tiles": { "name": "Negozio di piastrelle", - "terms": "" + "terms": "piastrelle,mattonelle,pavimento,pavimenti,ceramica,pietra" }, "shop/tobacco": { "name": "Tabacchino", @@ -5948,7 +6153,8 @@ "terms": "Negozio giocattoli" }, "shop/trade": { - "terms": "" + "name": "Materiali da edilizia", + "terms": "materiali edilizi,edilizia,mattoni,cemento,stucco,gesso" }, "shop/travel_agency": { "name": "Agenzia di viaggi", @@ -5979,7 +6185,7 @@ }, "shop/watches": { "name": "Negozio di orologi", - "terms": "orolog*" + "terms": "orologio,orologi,negozio orologi,sveglia,sveglie,orologio a cipolla,cronografo,cronometro" }, "shop/water_sports": { "name": "Negozio per sport acquatici", @@ -6039,10 +6245,10 @@ }, "tourism/gallery": { "name": "Galleria d'arte", - "terms": "opere d'arte,quadri,sculture,galleria,fotografie,dipinti,art*" + "terms": "opere d'arte,quadri,sculture,galleria,foto,fotografia,fotografie,dipinti,arte,artistica,esibizione,mostra" }, "tourism/guest_house": { - "name": "Affittacamere/Bed & Breakfast", + "name": "Bed & Breakfast", "terms": "B&B,Bed & Breakfast,Bed and Breakfast" }, "tourism/hostel": { @@ -6089,13 +6295,17 @@ "name": "Parco a tema", "terms": "Parco a tema" }, + "tourism/trail_riding_station": { + "name": "Stazione di sosta per cavalli", + "terms": "stazione,stop,sosta,cavallo,cavalli,cavalcatura,rifornimento,abbeveratoio,pausa,riposo" + }, "tourism/viewpoint": { "name": "Punto panoramico", "terms": " Punto panoramico " }, "tourism/wilderness_hut": { "name": "Bivacco", - "terms": "" + "terms": "bivacco,baito,struttura incustodita,casetta,piccolo rifugio" }, "tourism/zoo": { "name": "Zoo", @@ -6139,7 +6349,7 @@ }, "traffic_calming/table": { "name": "Dosso", - "terms": "" + "terms": "veloce,lento,piano,velocità,dosso,dossi,rallentatore,tabellone,tabella,cuscino sonoro,banda sonora,cuscini sonori,bande sonore" }, "type/boundary": { "name": "Confine", @@ -6174,15 +6384,19 @@ }, "type/restriction/only_left_turn": { "name": "Obbligo di svolta a sinistra", - "terms": "obbligo,curva,sinistra" + "terms": "svolta a sinistra,divieto di svolta a destra,divieto di andare diritto,obbligo" }, "type/restriction/only_right_turn": { "name": "Obbligo di svolta a destra", - "terms": "obbligo,curva,destra" + "terms": "svolta a destra,divieto di svolta sinistra,divieto di andare diritto,obbligo" }, "type/restriction/only_straight_on": { - "name": "Direzione obbligatoria dritto", - "terms": "obbligo,dritto,diritto,divieto di svolta" + "name": "Obbligo di andare diritto", + "terms": "diritto,dritto,proseguire diritto,obbligo,divieto di svolta" + }, + "type/restriction/only_u_turn": { + "name": "Obbligo di inversione di marcia", + "terms": "Svolta a U,inversione,inversione di marcia,tornare indietro,torna indietro,curva a U" }, "type/route": { "name": "Percorso", @@ -6217,8 +6431,8 @@ "terms": "cavallo,strada,ippica,sentiero,equitazione" }, "type/route/light_rail": { - "name": "Linea tramviaria", - "terms": "" + "name": "Linea della metropolitana di superficie", + "terms": "tranvia,metrotranvia,leggera,metro leggera,metropolitana leggera,linea tranvia,linea del tranvia" }, "type/route/pipeline": { "name": "Condotta", @@ -6226,7 +6440,7 @@ }, "type/route/piste": { "name": "Pista da sci", - "terms": "" + "terms": "pista,piste,pista da sci,piste da sci,rossa,blu,nera,pista blu,pista rossa,pista nera,discesa" }, "type/route/power": { "name": "Linea elettrica", @@ -6238,7 +6452,7 @@ }, "type/route/subway": { "name": "Linea metropolitana", - "terms": "" + "terms": "metro,metropolitana,subway,linea,linea della metro" }, "type/route/train": { "name": "Linea ferroviaria", @@ -6345,7 +6559,7 @@ "attribution": { "text": "Termini & Feedback" }, - "description": "Immagini dei confini e data di riferimento. Le etichette vengono mostrate a livelli di zoom maggiori o uguali a 14.", + "description": "Confini delle immagini e data di acquisizione. Le etichette appaiono a livelli di ingrandimento 13 e successivi.", "name": "DigitalGlobe Premium Imagery Vintage" }, "DigitalGlobe-Standard": { @@ -6359,7 +6573,7 @@ "attribution": { "text": "Termini & Feedback" }, - "description": "Immagini dei confini e data di riferimento. Le etichette vengono mostrate a livelli di zoom maggiori o uguali a 14.", + "description": "Confini delle immagini e data di acquisizione. Le etichette appaiono a livelli di ingrandimento 13 e successivi.", "name": "DigitalGlobe Standard Imagery Vintage" }, "EsriWorldImagery": { @@ -6443,6 +6657,10 @@ "description": "Giallo = Dati pubblici forniti da enti statali Statunitensi.", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Strada: bordo verde = non classificata. Bordo marrone = carrareccia. Manto in ghiaia = colore diriempimento marrone chiaro, asfaltato = nero, pavimentato = grigio, terra = bianco, cemento = blu, erboso = verde. Stagionale = con barre bianche", + "name": "Strade forestali U.S. (sovrapposta)" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, collaboratori OpenStreetMap, CC by-SA 3.0" @@ -6477,7 +6695,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Basemap of Austria, basati su dati governativi.", + "description": "mappa di base, ottenuta da dati del governo.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6539,7 +6757,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Map tiles by Stamen Design, under CC BY 3.0" + "text": "Tasselli della mappa di Stamen Design con licenza CC-BY 3.0. Dati di OpenStreetMap com licenza ODbL" }, "name": "Stamen Terrain" }, @@ -6555,6 +6773,762 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "Giovani mappatori dell’università di Cape Coast", + "description": "Seguici su Twitter: {url}", + "extendedDescription": "Questo è il punto d’incontro del capitolo dei Giovani Mappatori dell’università di Cape Coast in Ghana. Amiamo le mappe, i dati aperti e aiutare i più vulnerabili." + }, + "osm-gh-facebook": { + "name": "OpenStreetMap del Ghana su Facebook", + "description": "Gruppo Facebook per persone interessate a OpenStreetMap.", + "extendedDescription": "Mappatori nella comunità del Ghana, promuoviamo OpenStreetMap e i progetti della squadra umanitaria di OpenStreetMap (HOT) in Ghana. Unisciti a noi." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap del Ghana su Twitter", + "description": "Seguici su Twitter: {url}" + }, + "talk-gh": { + "name": "Mailinglist talk-gh", + "description": "Talk-gh è la mailinglist ufficiale della comunità OSM del Ghana." + }, + "osm-mg-facebook": { + "name": "Gruppo Facebook di OpenStreetMap del Madagascar", + "description": "Gruppo Facebook malgascio per persone interessate a OpenStreetMap." + }, + "talk-mg": { + "name": "Mailinglist talk-mg", + "description": "Un posto dove i collaboratori, le comunità e gli utenti di OpenStreetMap del Madagascar possono condividere e discutere." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap del Bangladesh", + "description": "Migliora OpenStreetMap nel Bangladesh", + "extendedDescription": "Mappi in Bangladesh? Hai delle domande oppure vuoi connetterti alla comunità di qua? Unisciti a noi all’indirizzo {url}. Tutti sono i benvenuti!" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap India - mappatura di quartiere partecipativa", + "description": "Miglioriamo OpenStreetMap in India", + "extendedDescription": "Mappi in India? Hai domande o vuoi connetterti alla comunità locale? Unisciti a noi su {url}. Tutti sono i benvenuti!", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "description": "Unisciti a State of the Map Asia di OpenStreetMap, un evento che si terrà in India nel 2018", + "where": "Indian Institute of Management, Bangalore, India" + } + } + }, + "OSM-india-mailinglist": { + "name": "Mailinglist di OpenStreetMap dell’India", + "description": "Talk-in è la mailinglist ufficiale della comunità indiana" + }, + "OSM-india-twitter": { + "name": "Twitter di OpenStreetMap dell’India", + "description": "Siamo solo ad un cinguettio di distanza: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Movimento del software e hardware liberi su Facebook", + "description": "Pagina Facebook di FSHM per conoscere gli eventi e le attività della comunità", + "extendedDescription": "FSHM organizza eventi che riguardano il software e l’hardware liberi, la tecnologia, l’attivismo e OpenStreetMap. La sua pagina Facebook è il posto migliore per rimanere in contatto con i suoi eventi." + }, + "OSM-India-Puducherry-Matrix": { + "name": "Movimento del software e hardware liberi su Matrix", + "description": "Gruppo FSHM di Riot per discutere, condividere e aggiornare le attività di mappatura, gli eventi si terranno nei dintorni di Pondicherry", + "extendedDescription": "I membri della comunità FSHM condividono le loro esperienze / novità sulla mappatura in OSM attraverso il gruppo Riot.im, questo gruppo è anche usato per discutere di argomenti relativi al software e all’hardware liberi, la tecnologia e l’attivismo." + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap dell’Indonesia", + "description": "Migliora OpenStreetMap in Indonesia", + "extendedDescription": "Stai mappando in Indonesia? Hai domande o vuoi connetterti alla comunità locale? Unisci a a noi su {Url}. Tutti sono i benvenuti!" + }, + "OSM-japan-facebook": { + "name": "Comunità OpenStreetMap del Giappone", + "description": "Mappatori e utenti OpenStreetMap del Giappone" + }, + "OSM-japan-mailinglist": { + "name": "Mailinglist di OpenStreetMap Giappone", + "description": "Talk-ja è la mailinglist ufficiale della comunità giapponese" + }, + "OSM-japan-twitter": { + "name": "Twitter OpenStreetMap Giappone", + "description": "Hashtag su Twitter: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap del Giappone", + "description": "Mappatori e utenti di OpenStreetMap in Giappone" + }, + "OSM-korea-telegram": { + "name": "Canale Telegram di OSM della Corea", + "description": "Canale non ufficiale per discutere e condividere per i contribuenti, le comunità e gli utenti di OpenStreetMap in Corea." + }, + "OSM-MY-facebook": { + "name": "OpenStreetMap della Malaysia su Facebook", + "description": "Per chiacchierare su tutto ciò che è inerente a OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "Forum web di OpenStreetMap della Malaysia", + "description": "Forum web ufficiale di OpenStreetMap della Malaysia" + }, + "OSM-MY-matrix": { + "name": "Canale Riot di OpenStreetMap della Malaysia", + "description": "Tutti i mappatori sono i benvenuti! Iscriviti su {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap della Mongolia", + "description": "Migliora OpenStreetMap in Mongolia", + "extendedDescription": "Stai mappando in Mongolia? Hai domande o vuoi connetterti alla comunità locale? Unisci a noi su {Url}. Tutti sono i benvenuti!" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Myanmar", + "description": "Contribuisci a migliorare OpenStreetMap in Myanmar", + "extendedDescription": "Mappi in Myanmar? Hai domande oppure vuoi connetterti alla comunità di quaggiù? Unisciti a noi all’indirizzo {Url}. Tutti sono i benvenuti!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap del Nepal", + "description": "Migliora OpenStreetMap in Nepal", + "extendedDescription": "Stai mappando in Nepal? Hai domande o vuoi connetterti alla comunità locale? Unisciti a noi su {Url}. Tutti sono i benvenuti!" + }, + "OSM-PH-facebook": { + "name": "Facebook di OpenStreetMap delle Filippine", + "description": "Benvenuta/o in OpenStreetMap delle Filippine, un posto dove i nostri amici filippini vengono incoraggiati a contribuire al progetto OpenStreetMap." + }, + "OSM-PH-mailinglist": { + "name": "Mailing list Talk-ph", + "description": "Una mailinglist per discutere OpenStreetMap nelle Filippine" + }, + "OSM-PH-slack": { + "name": "Slack di OpenStreetMap delle Filippine", + "description": "Tutti sono i benvenuti! Registrati su {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "Telegram di OpenStreetMap delle Filippine", + "description": "Non ufficiale, comunità locale su Telegram di utenti OpenStreetMap e amici nelle Filippine." + }, + "OSM-RU-forum": { + "name": "Forum di OpenStreetMap della Russia", + "description": "Forum web di OpenStreetMap della Russia" + }, + "OSM-RU-telegram": { + "name": "Telegram di OpenStreetMap della Russia", + "description": "Chat Telegram di OpenStreetMap della Russia" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap dello Sri Lanka", + "description": "Migliora OpenStreetMap nello Sri Lanka", + "extendedDescription": "Stai mappando lo Sri Lanka? Hai domande o vuoi connetterti alla comunità locale? Unisciti a noi su {Url}. Tutti sono i benvenuti!" + }, + "OSM-TW-facebook": { + "name": "Comunità di OpenStreetMap di Taiwan", + "description": "Gruppo di Facebook per mappatori e utenti OpenStreetMap che vogliono discutere su argomenti inerenti Taiwan." + }, + "OSM-TW-mailinglist": { + "name": "Mailinglist di OpenStreetMap di Taiwan", + "description": "Talk-tw è la mailinglist ufficiale delle comunità per discutere su argomenti inerenti Taiwan." + }, + "OSM-TH-CNX-meetup": { + "name": "Meetup OSM di Chiang Mai", + "description": "Riunioni con cadenza irregolare della comunità OpenStreetMap a Chiang Mai", + "extendedDescription": "I membri della comunità di OpenStreetMap si incontrano ogni qualche mese a Chiang Mai. Contattaci all’indirizzo {url} per sapere quando avverrà il prossimo ‘meetup’." + }, + "OSM-TH-forum": { + "name": "Forum di OpenStreetMap della Thailandia", + "description": "Forum web di OpenStreetMap della Thailandia" + }, + "al-forum": { + "name": "Forum di OSM dell’Albania", + "description": "Forum di OpenStreetMap dell’Albania" + }, + "al-maptime-tirana": { + "name": "Maptime di Tirana", + "description": "Eventi sociali centrati sulla mappatura—i principianti sono più che benvenuti!", + "extendedDescription": "Maptime è un ambiente di apprendimento libero per tutti i livelli e gradi di conoscenza, che offre supporto educativo in particolare ai principianti. Maptime è allo stesso tempo flessibile e strutturato, rendendo in questo modo possibile l’organizzazione di lezioni di mappatura, corsi di specializzazione, lavori a progetto indipendenti e/o collaborativi." + }, + "al-telegram": { + "name": "Canale su Telegram di OSM dell’Albania", + "description": "Canale su Telegram di OpenStreetMap dell’Albania" + }, + "at-forum": { + "name": "Forum web di OpenStreetMap dell’Austria", + "description": "Il forum ufficiale di OpenStreetMap per fare domande sull’Austria e nei suoi dintorni." + }, + "at-mailinglist": { + "name": "Mailinglist talk-at", + "description": "Talk-at è la mailinglist ufficiale della comunità austriaca di OpenStreetMap" + }, + "at-twitter": { + "name": "Twitter di OpenStreetMap dell’Austria", + "description": "OpenStreetMap dell’Austria su Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "Comunità OSM di Graz Meetup", + "description": "Meetup mensile della comunità OpenStreetMap in Graz" + }, + "osmgraz-twitter": { + "name": "Comunità OSM di Graz su Twitter", + "description": "Comunità OpenStreetMap in Graz su Twitter" + }, + "osm-at": { + "name": "OpenStreetMap dell’Austria", + "description": "La piattaforma per informazioni su OpenStreetMap in Austria" + }, + "byosm": { + "name": "OpenStreetMap della Bielorussia", + "description": "Chat telegram di OpenStreetMap della Bielorussia" + }, + "be-facebook": { + "name": "Comunità belga di OpenStreetMap", + "description": "Facebook dei mappatori e OpenStreetMap in Belgio" + }, + "be-forum": { + "name": "Forum belga di OpenStreetMap", + "description": "Forum web belga di OpenStreetMap" + }, + "be-irc": { + "name": "Canale IRC di OpenStreetMap del Belgio", + "description": "Entra in #osmbe su irc.oftc.net (porta 6667)", + "extendedDescription": "Entra in #osmbe su irc.oftc.net (porta 6667), è unito al canale di chat Matrix" + }, + "be-mailinglist": { + "name": "Mailinglist talk-be", + "description": "Talk-be è la mailinglist ufficiale della comunità belga su OSM" + }, + "be-maptime": { + "name": "Maptime del Belgio", + "description": "Eventi sociali organizzati con argomento la mappatura—i principianti sono più che benvenuti!", + "extendedDescription": "Maptime è un ambiente di apprendimento libero per tutti i livelli e gradi di conoscenza, che offre supporto educativo in particolare ai principianti. Maptime è allo stesso tempo flessibile e strutturato, rendendo in questo modo possibile l’organizzazione di lezioni di mappatura, corsi di specializzazione, lavori a progetto indipendenti e/o collaborativi." + }, + "be-matrix": { + "name": "Canale Matrix di OpenStreetMap del Belgio", + "description": "Tutti i mappatori sono benvenuti!", + "extendedDescription": "La maggior parte delle discussioni avviene nel canale “OpenStreetMap del Belgio”. Puoi chiedere qualsiasi cosa lì! Le altre stanze sono per argomenti specifici." + }, + "be-meetup": { + "name": "Meetup di OpenStreetMap del Belgio", + "description": "Incontri dal vivo per chiunque sia interessato a OpenStreetMap", + "extendedDescription": "Incontrarsi di persona è una grande occasione per conoscere altri mappatori, fare domande e imparare un sacco di cose. I nuovi utenti sono in special modo i benvenuti!" + }, + "be-twitter": { + "name": "Twitter di OpenStreetMap del Belgio", + "description": "OSM del Belgio su Twitter: @osm_be" + }, + "talk-cz-mailinglist": { + "name": "Mailinglist Talk-cz", + "description": "Talk-cz è la mailinglist ufficiale della comunità ceca" + }, + "dk-forum": { + "name": "Forum web di OpenStreetMap della Danimarca", + "description": "Forum web di OpenStreetMap della Danimarca" + }, + "dk-irc": { + "name": "Canale IRC di OpenStreetMap della Danimarca", + "description": "Entra in #osm-dk su irc.oftc.net (porta 6667)" + }, + "dk-mailinglist": { + "name": "Mailinglist talk-dk", + "description": "Una mailinglist per discutere di OpenStreetMap in Danimarca" + }, + "fi-forum": { + "name": "Forum di OpenStreetMap della Finlandia", + "description": "Forum web di OpenStreetMap della Finlandia" + }, + "fi-irc": { + "name": "Canale IRC di OpenStreetMap della Finlandia", + "description": "Entra in #osm-fi su irc.oftc.net (porta 6667)" + }, + "fi-mailinglist": { + "name": "Mailinglist talk-fi", + "description": "Talk-fi è la mailinglist ufficiale della comunità OSM finlandese" + }, + "fr-facebook": { + "name": "Pagina Facebook di OpenStreetMap della Francia", + "description": "Pagina Facebook di OpenStreetMap della Francia" + }, + "fr-forum": { + "name": "Forum web di OpenStreetMap della Francia", + "description": "Forum web di OpenStreetMap della Francia" + }, + "fr-irc": { + "name": "Canale IRC di OpenStreetMap della Francia", + "description": "Entra in #osm-fr su irc.oftc.net (porta 6667)" + }, + "fr-mailinglist": { + "name": "Mailinglist talk-fr", + "description": "Mailinglist talk-fr" + }, + "fr-twitter": { + "name": "OpenStreetMap della Francia su Twitter", + "description": "OpenStreetMap della Francia su Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "Mailinglist di Berlino", + "description": "Questa è la mailinglist per la comunità OSM di Berlino" + }, + "de-berlin-meetup": { + "name": "Meetup di OpenStreetMap di Berlino-Brandeburgo", + "description": "Mappatori e utenti di OpenStreetMap dell’area berlinese" + }, + "de-berlin-telegram": { + "name": "@osmberlin su Telegram", + "description": "Chat Telegram di OpenStreetMap di Berlino" + }, + "de-berlin-twitter": { + "name": "Twitter di OpenStreetMap di Berlino", + "description": "seguici su Twitter: {url}" + }, + "de-forum": { + "name": "Forum OpenStreetMap della Germania", + "description": "Forum web di OpenStreetMap della Germania" + }, + "de-irc": { + "name": "Canale IRC di OpenStreetMap della Germania", + "description": "Entra in #osm-de su irc.oftc.net (porta 6667)" + }, + "de-mailinglist": { + "name": "Mailinglist talk-de", + "description": "Talk-de è la mailinglist ufficiale della comunità OSM della Germania" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "Mailinglist OWL", + "description": "Questa è la mailinglist della comunità OSM nella regione di Ostwestfalen-Lippe" + }, + "osm-de": { + "name": "OpenStreetMap della Germania", + "description": "La piattaforma d’informazione per OpenStreetMap in Germania" + }, + "hu-facebook": { + "name": "OpenStreetMap dell’Ungheria su Facebook", + "description": "Facebook dei mappatori e OpenStreetMap in Ungheria" + }, + "hu-forum": { + "name": "Forum web di OpenStreetMap in Ungheria", + "description": "Forum web di OpenStreetMap in Ungheria" + }, + "hu-meetup": { + "name": "Meetup di OpenStreetMap in Ungheria", + "description": "La piattaforma per organizzare incontri in Ungheria" + }, + "it-facebook": { + "name": "Facebook di OpenStreetMap dell’Italia", + "description": "Unisciti alla comunità italiana di OpenStreetMap su Facebook" + }, + "it-irc": { + "name": "Canale IRC di OpenStreetMap dell’Italia", + "description": "Entra in #osm-it su irc.oftc.net (porta 6667)" + }, + "it-mailinglist": { + "name": "Mailinglist talk-it", + "description": "Talk-it è la mailinglist ufficiale della comunità OSM italiana" + }, + "it-telegram": { + "name": "@OpenStreetMapItalia su Telegram", + "description": "Chat su Telegram di OpenStreetMap dell’Italia" + }, + "it-twitter": { + "name": "Twitter di OpenStreetMap dell’Italia", + "description": "Seguici su Twitter all’indirizzo {url}" + }, + "OSM-Rome-meetup": { + "name": "Incontro Mappatori Romani", + "description": "Miglioriamo OpenStreetMap nell’area attorno a Roma", + "extendedDescription": "Puntiamo ad aiutare le persone a discutere e a condividere le loro conoscenze nell’utilizzo dei dati geografici, in particolar modo quelli di OpenStreetMap, in quello di software geo-spaziale che gestisce, modifica e visualizza dati geografici e promuoviamo il suo uso nel Lazio." + }, + "South-Tyrol-Mailing-List": { + "name": "Mailinglist di OpenStreetMap del Sud Tirolo", + "description": "Mailinglist di OpenStreetMap Italia dell’area del Sud Tirolo," + }, + "talk-it-lazio": { + "name": "OpenStreetMap Italy del Lazio", + "description": "Tutti sono i benvenuti! Iscriviti su {signupUrl}", + "extendedDescription": "Mailinglist di Roma e del Lazio." + }, + "Trentino-Mailing-List": { + "name": "Mailinglist di OpenStreetMap per il Trentino", + "description": "Mailinglist di OpenStreetMap Italia del Trentino" + }, + "no-forum": { + "name": "Forum web di OpenStreetMap della Norvegia", + "description": "Forum web di OpenStreetMap della Norvegia" + }, + "no-irc": { + "name": "OpenStreetMap della Norvegia su IRC", + "description": "Stanza della chat per mappatori e utenti di OpenStreetMap, sviluppatori ed appassionati in Norvegia" + }, + "no-mailinglist": { + "name": "Mailinglist di OpenStreetMap della Norvegia", + "description": "Mailinglist per mappatori e utenti di OpenStreetMap, sviluppatori ed appassionati in Norvegia" + }, + "OSM-PL-facebook-group": { + "name": "Gruppo Facebook di OpenStreetMap della Polonia", + "description": "Gruppo per mappatori e utenti di OpenStreetMap in Polonia" + }, + "OSM-PL-forum": { + "name": "Forum web di OpenStreetMap della Polonia", + "description": "Forum web della comunità polacca di OpenStreetMap" + }, + "OSM-ES-mailinglist": { + "name": "Mailinglist talk-es", + "description": "Una mailinglist per discutere su OpenStreetMap della Spagna" + }, + "OSM-ES-telegram": { + "name": "@OSMes su Telegram", + "description": "Chat Telegram di OpenStreetMap della Spagna" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "Offriamo servizi OSM e informazioni per la comunità locale in Svezia" + }, + "se-facebook": { + "name": "Facebook di OpenStreetMap della Svezia", + "description": "OpenStreetMap della Svezia su Facebook" + }, + "se-forum": { + "name": "Forum web di OpenStreetMap della Svezia", + "description": "Forum web di OpenStreetMap della Svezia" + }, + "se-irc": { + "name": "Canale IRC di OpenStreetMap della Svezia", + "description": "Entra in #osm.se su irc.oftc.net (porta 6667)" + }, + "se-mailinglist": { + "name": "Mailinglist talk-se", + "description": "Una mailinglist per discutere di OpenStreetMap in Svezia" + }, + "se-twitter": { + "name": "OpenStreetMap della Svezia su Twitter", + "description": "Seguici su Twitter: {url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "Meetup mensili pubblici di Nottingham e East Midlands", + "description": "Incontri sociali per i mappatori e utenti delle East Midlands", + "extendedDescription": "Un gruppo che da marzo 2011 si riunisce, inizialmente a Nottingham, più recentemente a Derby e di tanto in tanto da qualche altra parte nelle East Midlands. Si tratta di incontri sociali, ma sono anche dei momenti eccellenti per venire a fare delle domande specifiche su OSM nella nostra zona o in generale. Nei mesi estivi facciamo solitamente delle sessioni leggere di mappatura nei dintorni del punto d’incontro. Il gruppo ha come interesse speciale quello di mappare le precedenze nelle strade pubbliche e di tanto in tanto ci incontriamo proprio per questo scopo." + }, + "gb-mailinglist": { + "name": "Mailinglist talk-gb", + "description": "Talk-gb è la principale piattaforma di comunicazione della comunità OSM britannica (Irlanda del Nord inclusa)" + }, + "mappa-mercia-group": { + "name": "Gruppo locale Mappa Mercia", + "description": "Un posto per gli appassionati di OpenStreetMap nelle Midlands", + "extendedDescription": "Mappa Mercia è un progetto per sviluppare OpenStreetMap nelle West Midlands nel Regno Unito. Organizziamo eventi per la comunità, lezioni e supportiamo gli enti locali che vogliano rendere aperti i dati in loro possesso." + }, + "gb-irc": { + "name": "Canale IRC di OpenStreetMap del Regno Unito", + "description": "Entra in #osm-gb su irc.oftc.net (porta 6667)", + "extendedDescription": "Entra in #osm-gb su irc.oftc.net (porta 6667), cerca di essere paziente e aspetta almeno qualche minuto se chiedi qualcosa" + }, + "OSM-CA-Slack": { + "name": "Slack di OSM-CA", + "description": "Tutti sono i benvenuti! Iscriviti su {signupUrl}." + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap di Vancouver", + "description": "Mappatori e utenti OpenStreetMap di Vancouver, area Colombia Britannica" + }, + "OSM-CU-telegram": { + "name": "OSM di Cuba su Telegram", + "description": "La chat su Telegram di OpenStreetMap di Cuba" + }, + "OSM-NI-telegram": { + "name": "OSM Nicaragua su Telegram", + "description": "La chat su Telegram di OpenStreetMap del Nicaragua" + }, + "Bay-Area-OpenStreetMappers": { + "name": "OpenStreetMappers a Bay Area", + "description": "Migliora OpenStreetMap a Bay Area", + "extendedDescription": "Il nostro gruppo vuole far crescere la community OpenStreetMap qui nella zona di Bay Area. I nostri eventi sono aperti a chiunque, dall'appassionato di open source, al ciclista, al professionista GIS, al geocacher e oltre. Qualunque persona appassionata di mappe, cartografia o analisi geografica è la benvenuta a unirsi al nostro gruppo e partecipare ai nostri eventi. " + }, + "Central-Pennsylvania-OSM": { + "name": "OSM Pennsylvania Centrale", + "description": "Community online di mapping con base presso State College, PA" + }, + "Code-for-San-Jose-Slack": { + "name": "Slack di Programmare per San Jose", + "description": "Tutti sono benvenuti! Iscriviti su {signupUrl}, e dopo collegati al canale \"osm su IRC." + }, + "Dallas-Fort-Worth-OSM": { + "name": "OSM Dallas-Fort Worth", + "description": "Gruppo OpenStreetMap di Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Work, e tutte le città limitrofe abbondano di persone creative ed esperte di tecnologia. La nostra vision è quella di cercare in questo gruppo nuove vie di utilizzare le fantastiche risorse offerte da OSM." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Meetup per appassionati di mappe nella zona di Philadelphia", + "extendedDescription": "Geophilly unisce sviluppatori, geografi, data geek, appassionati open source, civic hacker e drogati di mappe nella comune passione passione per le mappe e delle storie che possono raccontare. Se usate delle mappe nel vostro lavoro o se voltete soltanto saperne di più, questo è il meetup adatto per voi! I nostri eventi mirano a essere aperti, amichevoli, educativi e sociali, e spaziano dalle piacevoli chiacchierate agli incontri lampo e perfino agli workshop. Venite a creare una community geospaziale variegata e ispirativa con noi a Philadelphia!" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "Mappatori e appassionati di OpenStreetMap nell’area delle Twin Cities.", + "extendedDescription": "Un punto di contatto per gli appassionati di OpenStreetMap del Minnesota e delle Twin Cities!" + }, + "Mapping-DC-meetup": { + "name": "Mappando DC", + "description": "Migliora OpenStreetMap nell'area di DC", + "extendedDescription": "Siamo un gruppo di mappatori volontari con l'obiettivo di migliorare OpenStreetMap nell'area di DC. Puntiamo anche a insegnare agli altri l'ecosistema OSM, l'analisi dei dati, la cartografia e GIS. Ci raduniamo ogni altro mese ai meetup per concentrarci su una zona della nostra città." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Mappatori e utenti OpenStreetMap nei dintorni di Portland, Maine", + "extendedDescription": "Maptime è letteralmente tempo per la mappatura. La nostra missione è quella di aprire le porte della cartografia a chiunque sia interessato, creando un posto e dei momenti per l’apprendimento collaborativo, l’esplorazione, la creazione di mappe usando strumenti e tecnologie per la mappatura." + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Miglioriamo OpenStreetMap nell’area di Cleveland", + "extendedDescription": "Open Geo Cleveland mira a diventare una risorsa per le persone che vogliano discutere e condividere le proprie conoscenze su come utilizzare i dati geografici liberi, nella fattispecie OpenStreetMap, e di software geo-spaziale aperto che gestisce, modifica e mostra su schermo dati geografici, e spingiamo per il suo uso nell’Ohio del nord-est. Siamo anche un chapter di maptime =)" + }, + "OSM-Boston": { + "name": "OpenStreetMap di Boston", + "description": "Mappatori e utenti di OpenStreetMap che risiedono nell’area di Boston", + "extendedDescription": "OpenStreetMap è una mappa libera e aperta, simile ad una mappa del mondo in stile Wikipedia, con centinaia di migliaia di contributi ogni giorno da persone come te. Modificare la mappa è semplice e divertente! Unisciti a noi sia da casa che all’aperto, nel nostro obiettivo di creare la miglior mappa dell’area di Boston e del resto del mondo!" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap, mar dei Salish centrale", + "description": "Mappatori e utenti di OpenStreetMap nei dintorni di Mount Vernon, nello stato di Washington", + "extendedDescription": "OpenStreetMap è la mappa del mondo creata da persone come te. È una mappa che tu puoi costruire e che è gratis come Wikipedia. Vai su osm.org per altre informazioni. Noi ci riuniamo sempre per parlare di mappe, mappare e divertirci!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "Gruppo utenti OpenStreetMap di Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap del Colorado", + "description": "Mappatori e utenti OpenStreetMap dello stato del Colorado, USA", + "extendedDescription": "OpenStreetMap (OSM) del Colorado è una collaborazione locale di persone interessate a usare le proprie forze per creare mappe libere. Noi incoraggiamo i nostri mappatori ad organizzare e suggerire eventi di mappatura ovunque nel nostro stato. Attività di incontro come per esempio semplici riunioni, lezioni di OSM dal principiante all’intermedio oppure feste di mappatura in compagnia." + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Mappatori e utenti OpenStreetMap, sviluppatori e appassionati nell'area Metropolitana di New York" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Mappatori e utenti OpenStreetMap nell'area di Portland", + "extendedDescription": "OpenStreetMap (OSM) è una cartina del pianeta costruita da persone come te. È una mappa che puoi modificare, distribuita gratuitamente come Wikipedia. Vai su osm.org per saperne di più e vieni ai nostri meetup per discutere di mappe, contribuire a OSM e divertirti!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap di Seattle", + "description": "Mappatori e utenti OpenStreetMap nell’area di Seattle" + }, + "OSM-SoCal": { + "name": "OpenStreetMap della California del sud", + "description": "Divertiamoci, contribuiamo con qualunque cosa a Los Angeles e impariamo a mappare!", + "extendedDescription": "OpenStreetMap (OSM) della California del sud è per chiunque sia interessato a mappare insieme agli altri lavorando con OpenStreetMap. OpenStreetMap, la Wikipedia delle mappe, è la mappa del mondo open-source libera creata da più di un milione di volontari per tutto il globo. Chiunque è ben accetto. Se non conosci OpenStreetMap, te la insegneremo noi. Se hai un’idea per un progetto di mappatura oppure una gita sul campo che il nostro gruppo può effettuare, perfetto!" + }, + "OSM-South-Bay": { + "name": "OSM di South Bay", + "description": "Serate della mappa ospitate da \"Programmare per San Jose\"", + "extendedDescription": "Programmare per San Jose, la filiale locale della brigata di Programmare per l’America, ospita ogni mese di giovedì una serata per la mappa nei sobborghi di San José. Incontra altri mappatori della South Bay, aiutaci con i progetti di mappatura locale e vieni a conoscenza di altri progetti di tecnologia civica. Non è richiesto né saper programmare né sapere cosa sia un GIS." + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap di Tampa Bay", + "description": "Mappatori e utenti OpenStreetMap dell’area di Tampa Bay", + "extendedDescription": "Gruppo OSM di Tampa Bay per riunire residenti locali e riuscire a costruire la mappa definitiva di Tampa Bay con OpenStreetMap, la mappa del mondo libera e modificabile. Se ti interessano le mappe, i dati, l’open source, il GPS, le passeggiate, pedalare, etc., ti piacerà da impazzire lavorare con OpenStreetMap - perciò unisciti a noi! Ci incontreremo e mapperemo e discuteremo di nuovi argomenti più o meno una volta al mese." + }, + "OSM-US-Slack": { + "name": "Slack Americano di OpenStreetMap", + "description": "Sono tutti i benvenuti! Registrati all'indirizzo {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap degli Stati Uniti", + "description": "Aiutiamo a crescere e migliorare OpenStreetMap negli Stati Uniti.", + "extendedDescription": "Supportiamo OpenStreetMap organizzando conferenze annuali, producendo risorse per la comunità, costruendo relazioni e diffondendo la voce. Unisciti a OpenStreetMap degli Stati Uniti qui: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap dello Utah", + "description": "Mappaori e utenti OpenStreetMap dell’area di Salt Lake City", + "extendedDescription": "Le attività comprendono cose come lezioni per imparare a mappare, feste di mappatura e uscite all’aperto per la raccolta di dati. Gli eventi avverranno nell’area SLC, almemmo all’inizio. Stiamo cercando sia mappatori esperti che alle prime armi. Unisciti e andiamo a mappare!" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap del Wyoming", + "description": "Mappatori e utenti OpenStreetMap dello stato del Wyoming", + "extendedDescription": "OpenStreetMap (OSM) del Wyoming è una collaborazione local formata da perrsone interessate a unire i loro sforzi per creare mappe libere. Incoraggiamo tutti i nostri mappatori a organizzare o suggerire eventi di mappatura ovunque nello stato. Attività di gruppo sono per esempio incontri, lezioni di OSM dal principiante all’intrmedio, oppure feste di mappatura in compagnia." + }, + "PHXGeo-meetup": { + "name": "Meetup PHXGeo", + "description": "Mappatori e utenti OpenStreetMap di Phoenix (area Arizona)", + "extendedDescription": "Questo è un gruppo meetup per i residenti nell’area di Phoenix a cui piacciono le mappe, GIS, OpenStreetMap e cartografia in tutte le loro combinazioni." + }, + "PHXGeo-twitter": { + "name": "Twitter PHXGeo", + "description": "Seguici su Twitter all’indirizzo {url}" + }, + "Western-Slope-facebook": { + "name": "Facebook di OSM Western Slope", + "description": "Mappatori e utenti OpenStreetMap attorno a Grand Junction (Colorado)" + }, + "Western-Slope-meetup": { + "name": "Meetup di OSM di Western Slope", + "description": "Mappatori e utenti OpenStreetMap intorno a Grand Junction (Colorado)", + "extendedDescription": "L’obiettivo di questo gruppo è quello di introdurre la comunità a OpenStreetMap, sviluppare una gruppo di mappatori, creare i più strabilianti dati georiferiti utilizzando qualsiasi metodo possibile e infine studiare dei metodi che permettano a questi dati di ritornare nella nostra comunità. Immagina un segnale dei percorsi accurato! Immagine un’ulteriore sviluppo delle piste ciclabili! Immagina qualsiasi cosa, quello è il bello di OpenStreetMap!" + }, + "Maptime-Australia-Slack": { + "name": "Slack di Australia Maptime", + "description": "Registrati all'indirizzo {signupUrl}" + }, + "talk-au": { + "name": "Mailinglist talk-au", + "description": "Un posto dove i mappatori australiani possono conversare liberamente" + }, + "OSM-AR-facebook": { + "name": "Facebook di OpenStreetMap dell’Argentina", + "description": "Unisciti alla comunità su Facebook di OpenStreetMap dell’Argentina", + "extendedDescription": "Novità della comunità locale" + }, + "OSM-AR-forum": { + "name": "Forum web di OpenStreetMap dell’Argentina", + "description": "Unisciti al forum web di OpenStreetMap dell’Argentina", + "extendedDescription": "Ideale per discussioni lunghe e profonde. Tempi di risposta lenti." + }, + "OSM-AR-irc": { + "name": "IRC di OpenStreetMap dell’Argentina", + "description": "Entra su #osm-ar nel server irc.oftc.net (porta 6667)", + "extendedDescription": "Potresti trovarvi gli utenti più nerd della comunità." + }, + "OSM-AR-mailinglist": { + "name": "Mailinglist talk-ar", + "description": "Vecchia mailinglist. Praticamente inutilizzata al giorno d’oggi." + }, + "OSM-AR-telegram": { + "name": "Telegram di OpenStreetMap dell’Argentina", + "description": "Unisciti alla comunità su Telegram di OpenStreetMap dell’Argentina", + "extendedDescription": "Il canale più attivo della comunità, ideale per chiacchierare e ricevere risposte alle proprie domande praticamente in tempo reale. Tutti sono i benvenuti!" + }, + "OSM-AR-twitter": { + "name": "Twitter di OpenStreetMap dell’Argentina", + "description": "Seguici su Twitter all’indirizzo {url}", + "extendedDescription": "Novità dalla comunità locale e OpenStreetMap in generale." + }, + "OSM-BO-mailinglist": { + "name": "Mailinglist talk-bo", + "description": "Talk-bo è la mailinglist ufficiale della comunità OpenStreetMap boliviana", + "extendedDescription": "Mappi in Bolivia? Hai domande o vuoi connetterti con la comunità di quaggiù? Unisciti a noi all’indirizzo {url}. Tutti sono i benvenuti!" + }, + "Bahia-telegram": { + "name": "Gruppo Telegram di OpenStreetMap di Bahia", + "description": "Unisciti alla comunità OpenStreetMap di Bahia su Telegram", + "extendedDescription": "Unisciti alla comunità per saperne di più su OpenStreetMap, fare domande e partecipare alle nostre riunioni. Chiunque è il benvenuto!" + }, + "DF-telegram": { + "name": "Gruppo Telegram di OpenStreetMap di Brasilia", + "description": "Unisciti alla comunità di OpenStreetMap di Brasilia su Telegram", + "extendedDescription": "Unisciti alla comunità per saperne di più su OpenStreetMap, fare domande e partecipare alle nostre riunioni. Tutti sono i benvenuti!" + }, + "OSM-br-mailinglist": { + "name": "Mailinglist talk-br", + "description": "Una mailinglist per discutere di OpenStreetMap in Brasile" + }, + "OSM-br-telegram": { + "name": "Telegram di OpenStreetMap del Brasile", + "description": "Unisciti alla comunità brasiliana di OpenStreetMap su Telegram", + "extendedDescription": "Unisciti alla comunità per saperne di più su OpenStreetMap, fare domande e partecipare alle nostre riunioni. Chiunque è il benvenuto!" + }, + "OSM-br-twitter": { + "name": "Twitter di OpenStreetMap del Brasile", + "description": "Seguici su Twitter all’indirizzo {url}" + }, + "OSM-CL-facebook": { + "name": "Facebook di OpenStreetMap del Cile", + "description": "Unisciti alla comunità OpenStreetMap del Cile su Facebook", + "extendedDescription": "Unisciti alla comunità per saperne di più su OpenStreetMap, fare domande e partecipare alle nostre riunioni. Tutti sono i benvenuti!" + }, + "OSM-CL-mailinglist": { + "name": "Mailinglist talk-cl", + "description": "Una mailinglist per discutere su OpenStreetMap del Cile" + }, + "OSM-CL-telegram": { + "name": "Telegram di OpenStreetMap del Cile", + "description": "Unisciti alla comunità di OpenStreetMap del Cile su Telegram", + "extendedDescription": "Unisciti alla comunità per saperne di più su OpenStreetMap, fare domande e partecipare alle nostre riunioni. Tutti sono i benvenuti!" + }, + "OSM-CL-twitter": { + "name": "Twitter di OpenStreetMap del Cile", + "description": "Seguici su Twitter all’indirizzo {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotà", + "description": "Siamo un gruppo di mappatori interessati a mappare su OpenStreetMap nei dintorni di Bogotà", + "extendedDescription": "Impara a raccogliere dati sul campo e a inserirli in OpenStreetMap. Non importa avere delle conoscenze pregresse! È solo necessario voler partecipare, imparare e divertirsi." + }, + "OSM-CO-facebook": { + "name": "Facebook di OpenStreetMap della Colombia", + "description": "Unisciti alla comunità di OpenStreetMap della Colombia su Facebook", + "extendedDescription": "Unisciti alla comunità per saperne di più su OpenStreetMap. Tutti sono i benvenuti!" + }, + "OSM-CO-mailinglist": { + "name": "Mailinglist talk-co", + "description": "Una mailinglist per discutere di OpenStreetMap in Colombia" + }, + "OSM-CO-telegram": { + "name": "OSM Colombia su Telegram", + "description": "La chat su Telegram di OpenStreetMap della Colombia" + }, + "OSM-CO-twitter": { + "name": "Twitter di OpenStreetMap della Colombia", + "description": "Seguici su Twitter all’indirizzo {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap della Colombia", + "description": "Novità della comunità di OpenStreetMap della Colombia e della fondazione OSMCo" + }, + "OSM-EC-telegram": { + "name": "OSM Ecuador su Telegram", + "description": "La chat su Telegram di OpenStreetMap dell’Ecuador" + }, + "OSM-PY-telegram": { + "name": "OSM Paraguay su Telegram", + "description": "La chat su Telegram di OpenStreetMap del Paraguay" + }, + "OSM-PE-facebook": { + "name": "Facebook di OpenStreetMap del Perù", + "description": "Unisciti alla comunità di OpenStreetMap del Perù su Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Mailinglist talk-pe", + "description": "La mailinglist ufficiale della comunità di OpenStreetMap del Perù" + }, + "OSM-PE-matrix": { + "name": "Chat Matrix di OpenStreetMap del Perù", + "description": "Parla su Matrix con gli altri membri della comunità di OpenStreetMap del Perù" + }, + "OSM-PE-telegram": { + "name": "Telegram di OpenStreetMap del Perù", + "description": "Unisciti alla comunità di OpenStreetMap del Perù su Telegram" + }, + "OSM-PE-twitter": { + "name": "Twitter di OpenStreetMap del Perù", + "description": "Seguici su Twitter all’indirizzo {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap del Perù", + "description": "Novità e risorse per la comunità di OpenStreetMap del Perù" + }, + "OSM-Facebook": { + "name": "OpenStreetMap su Facebook", + "description": "Metti “Mi piace” su Facebook per notizie e aggiornamenti su OpenStreetMap" + }, + "OSM-help": { + "name": "Assistenza OpenStreetMap", + "description": "Fai domande e ricevi risposte nel sito di domande e risposte gestito dalla comunità OSM.", + "extendedDescription": "{url} è per tutti quelli che hanno bisogno di aiuto con OpenStreetMap. Sia che tu sia un principiante o che tu abbia una domanda tecnica, siamo qui per aiutarti!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap su Reddit", + "description": "/r/openstreetmap/ è il posto perfetto per imparare di più su OpenStreetMap. Chiedici di tutto!" + }, + "OSM-Twitter": { + "name": "Twitter di OpenStreetMap", + "description": "Seguici su Twitter all’indirizzo {url}" + }, + "OSMF": { + "name": "OpenStreetMap Foundation", + "description": "OSMF è una organizzazione non a scopo di lucro che ha sede nel Regno Unito e che supporta il progetto OpenStreetMap", + "extendedDescription": "OSMF supporta OpenStreetMap con la raccolta fondi, la manutenzione dei server che danno energia a OSM, l’organizzazione dell’annuale conferenza State of the Map e la coordinazione dei volontari che tengono in vita OSM. Puoi dare il tuo contributo e avere una voce in capitolo nella direzione di OpenStreetMap unendoti alla OSMF come membro andando a questo indirizzo: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Unisciti a noi per 3 giorni a Milano (Italia), alla conferenza mondiale annuale di OpenStreetMap, in cui tutti i membri della comunità potranno incontrarsi per socializzare, condividere ed imparare.", + "where": "Milano, Italia" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/ja.json b/vendor/assets/iD/iD/locales/ja.json index c453c1a77..4787b5052 100644 --- a/vendor/assets/iD/iD/locales/ja.json +++ b/vendor/assets/iD/iD/locales/ja.json @@ -1,5 +1,10 @@ { "ja": { + "icons": { + "information": "情報", + "remove": "削除", + "undo": "もとに戻す" + }, "modes": { "add_area": { "title": "エリア", @@ -145,7 +150,9 @@ "vertex": "ウェイを他のウェイと接続", "line": "ウェイとラインを接続", "area": "ウェイとエリアを接続" - } + }, + "relation": "リレーションのロールが競合しているため、地物を接続できません", + "restriction": "\"{relation}\" リレーションを壊してしまうため、これらの地物は接続できません。" }, "disconnect": { "title": "接続解除", @@ -163,7 +170,8 @@ "annotation": "{n} 個の地物をマージ", "not_eligible": "地物情報がマージできません", "not_adjacent": "短点が接続されていないため、地物をマージできません。", - "restriction": "\"{relation}\" リレーションに所属している地物が含まれているため、マージすることができません", + "restriction": "\"{relation}\" リレーションを壊してしまうため、これらの地物はマージできません。", + "relation": "リレーションのロールが競合しているため、地物をマージできません", "incomplete_relation": "地物全体がダウンロードされていないため、マージさせることができません。", "conflicting_tags": "タグの値が競合しているため、地物をマージできません" }, @@ -402,6 +410,7 @@ "key": "H", "title": "編集履歴", "selected": "{n} 個を選択中", + "no_history": "履歴なし(新しい地物)", "version": "バージョン", "last_edit": "最新の編集", "edited_by": "編集者", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "OSM編集完了!", "just_edited": "OpenStreetMap編集完了!", - "view_on_osm": "詳細情報確認", - "facebook": "Facebookでシェア", - "twitter": "Twitterでシェア", - "google": "Google+でシェア", - "help_html": "あなたが投稿した内容は数分で\"標準\"レイヤーに反映されます。その他のレイヤーへの適用や、記述した地物によっては反映にさらに時間がかかる場合があります。", + "thank_you": "マップの改善ありがとうございます。", + "thank_you_location": "{where}付近でのマップ改善への協力ありがとうございます。", + "help_html": "あなたが投稿した内容は(サーバーの状況にもよりますが)数分で標準レイヤーに反映されます。その他のレイヤーなどでは反映にさらに時間がかかる場合があります。", "help_link_text": "詳細", - "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" + "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", + "view_on_osm": "OSM上で変更内容を閲覧", + "changeset_id": "あなたの変更セット #: {changeset_id}", + "like_osm": "OpenStreetMapが気に入ったら仲間とつながってみませんか?", + "more": "詳細", + "events": "イベント", + "languages": "言語: {languages}", + "missing": "リストに漏れがありますか?", + "tell_us": "教えてください!" }, "confirm": { "okay": "OK", @@ -1774,6 +1788,9 @@ "display": { "label": "表示盤の種類" }, + "distance": { + "label": "総距離" + }, "dock": { "label": "種類" }, @@ -1802,7 +1819,7 @@ "placeholder": "example@example.com" }, "embankment": { - "label": "種別", + "label": "種類", "placeholder": "デフォルト" }, "emergency": { @@ -1814,6 +1831,9 @@ "except": { "label": "例外" }, + "faces": { + "label": "面数" + }, "fax": { "label": "FAX", "placeholder": "+31 42 123 4567" @@ -1925,6 +1945,23 @@ "label": "輪の数", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "馬場馬術乗馬", + "options": { + "equestrian": "あり", + "undefined": "なし" + } + }, + "horse_riding": { + "label": "乗馬", + "options": { + "horse_riding": "あり", + "undefined": "なし" + } + }, + "horse_scale": { + "label": "乗馬の難易度" + }, "iata": { "label": "IATA" }, @@ -1944,6 +1981,9 @@ "indoor": { "label": "室内" }, + "industrial": { + "label": "種類" + }, "information": { "label": "種類" }, @@ -2064,6 +2104,10 @@ "label": "最高速度", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "安全速度", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "最大利用時間" }, @@ -2505,7 +2549,7 @@ "placeholder": "不明" }, "structure_waterway": { - "label": "トンネルの種別", + "label": "トンネルの種類", "options": { "tunnel": "トンネル" }, @@ -2652,8 +2696,19 @@ "label": "種類", "placeholder": "デフォルト" }, + "usage_rail": { + "label": "用途の種類", + "options": { + "branch": "支線", + "industrial": "産業貨物用", + "main": "幹線", + "military": "軍事用", + "test": "試験用", + "tourism": "観光用" + } + }, "vending": { - "label": "販売商品の種類" + "label": "商品の種類" }, "visibility": { "label": "見える範囲", @@ -2748,6 +2803,10 @@ "name": "広告用看板", "terms": "掲示板, 看板, 広告, 宣伝, 屋外広告" }, + "advertising/column": { + "name": "リトファスゾイレ", + "terms": "リトファスゾイレ, ポスター掲示柱, 広告" + }, "aerialway": { "name": "索道" }, @@ -2833,6 +2892,10 @@ "name": "空港ターミナル", "terms": "空港ターミナル" }, + "allotments/plot": { + "name": "市民農園の区画", + "terms": "区画, 市民農園, 市民農園の区画, 一画, 農園, 菜園, 市民菜園, 農業, 畑, 農園, コミュニティガーデン" + }, "amenity": { "name": "施設" }, @@ -2957,7 +3020,7 @@ }, "amenity/community_centre": { "name": "コミュニティセンター", - "terms": "公民館, 市民センター, 市民活動" + "terms": "公民館, 市民センター, 市民活動, コミュニティセンター, 集会所" }, "amenity/compressed_air": { "name": "空気入れ", @@ -2965,7 +3028,7 @@ }, "amenity/courthouse": { "name": "裁判所", - "terms": "裁判所, 法廷" + "terms": "裁判所, 法廷, 法律, 司法" }, "amenity/coworking_space": { "name": "コワーキングスペース" @@ -3061,6 +3124,10 @@ "name": "市場", "terms": "市場, マーケット, 朝市, マルシェ, 食品, 雑貨, 買い物, ショッピング, 食べ物" }, + "amenity/monastery": { + "name": "修道院", + "terms": "修道院, 宗教, 僧院, 信仰" + }, "amenity/motorcycle_parking": { "name": "オートバイの駐車場", "terms": "バイクの駐車場, 二輪駐車場, 二輪駐輪場, 駐車場, 駐輪場" @@ -3265,6 +3332,10 @@ "name": "たばこ自動販売機", "terms": "たばこ, 自動販売機, 自販機, 嗜好品, タバコ" }, + "amenity/vending_machine/coffee": { + "name": "コーヒー自販機", + "terms": "コーヒー, 珈琲, 自販機, 自動販売機" + }, "amenity/vending_machine/condoms": { "name": "コンドーム自動販売機", "terms": "コンドーム, 自動販売機, 自販機" @@ -3273,6 +3344,14 @@ "name": "飲料自動販売機", "terms": "飲料, ジュース, 酒, 飲み物, 自動販売機, 自販機" }, + "amenity/vending_machine/electronics": { + "name": "電子機器自販機", + "terms": "電子機器, チャージャー, ケーブル, ヘッドフォン, 自販機, 自動販売機" + }, + "amenity/vending_machine/elongated_coin": { + "name": "記念コイン自販機", + "terms": "記念コイン, 自販機, 自動販売機" + }, "amenity/vending_machine/excrement_bags": { "name": "犬の糞入れ自動販売機", "terms": "犬の糞入れ, 自動販売機, 自販機" @@ -3281,6 +3360,18 @@ "name": "生理用品自動販売機", "terms": "生理用品自動販売機, 自販機, 自動販売機" }, + "amenity/vending_machine/food": { + "name": "食品自販機", + "terms": "食品, 食べ物, 自販機, 自動販売機" + }, + "amenity/vending_machine/fuel": { + "name": "自動車用燃料自販機", + "terms": "自動車用燃料, 燃料, 自販機, 自動販売機, ガソリン, プロパン, 液化ガス, 軽油" + }, + "amenity/vending_machine/ice_cream": { + "name": "アイスクリーム自販機", + "terms": "アイスクリーム, 自販機, 自動販売機" + }, "amenity/vending_machine/news_papers": { "name": "新聞自動販売機" }, @@ -3300,6 +3391,10 @@ "name": "切符販売機", "terms": "券売機, 自動券売機, 自動販売機, 自販機, 自動発券機, 発券機" }, + "amenity/vending_machine/stamps": { + "name": "切手自販機", + "terms": "切手, 自販機, 自動販売機, 郵便" + }, "amenity/vending_machine/sweets": { "name": "菓子販売機", "terms": "菓子,お菓子, スナック, 自動販売機, 自販機" @@ -3372,6 +3467,10 @@ "name": "落下塔", "terms": "落下塔, アトラクション" }, + "attraction/maze": { + "name": "迷路", + "terms": "迷路, テーマパーク, アトラクション" + }, "attraction/pirate_ship": { "name": "海賊船", "terms": "海賊船, アトラクション" @@ -3553,6 +3652,10 @@ "name": "集合車庫(建物、大)", "terms": "集合車庫, 車庫, ガレージ" }, + "building/grandstand": { + "name": "メインスタンド", + "terms": "メインスタンド, 正面スタンド" + }, "building/greenhouse": { "name": "温室(建物)", "terms": "温室, ビニールハウス, 農業, 野菜" @@ -4001,6 +4104,10 @@ "name": "ホスピス", "terms": "ホスピス, 医療, 福祉" }, + "healthcare/laboratory": { + "name": "医学研究室", + "terms": "医学研究室, 医療研究室, 研究室, 健康, 医療" + }, "healthcare/midwife": { "name": "助産婦", "terms": "助産婦, 産婆, 医療" @@ -4103,6 +4210,10 @@ "name": "自動車専用道路の接続路", "terms": "自動車専用道路, 接続路, 車道, 幹線, 公道" }, + "highway/passing_place": { + "name": "待避所", + "terms": "待避所, 退避エリア" + }, "highway/path": { "name": "小道(自動車通行不可)", "terms": "小道, 歩道, 自転車道, バイク" @@ -4462,6 +4573,10 @@ "name": "ゲームセンター", "terms": "ゲームセンター, ゲーセン, 娯楽, レジャー, 遊技, ゲーム, 遊戯" }, + "leisure/beach_resort": { + "name": "ビーチリゾート", + "terms": "ビーチリゾート, 行楽地, 観光, 保養, レジャー, 娯楽, リゾート, 海辺, 砂浜" + }, "leisure/bird_hide": { "name": "野鳥観察舎", "terms": "ハイド, 野鳥観察小屋, アウトドア" @@ -4578,6 +4693,10 @@ "name": "自然保護区", "terms": "自然保護区" }, + "leisure/outdoor_seating": { + "name": "屋外食事席エリア", + "terms": "屋外席エリア, 屋外席, テラス, 食事, 屋外食事席エリア" + }, "leisure/park": { "name": "公園", "terms": "公園, アウトドア, 広場, 運動公園" @@ -4604,7 +4723,7 @@ }, "leisure/pitch/beachvolleyball": { "name": "ビーチバレーコート", - "terms": "ビーチバレーコート, スポーツ, 運動, 競技" + "terms": "ビーチバレーコート, スポーツ, 運動, 競技, 砂浜" }, "leisure/pitch/boules": { "name": "ブールスポーツ", @@ -4706,6 +4825,10 @@ "name": "坑口", "terms": "坑口, 坑道" }, + "man_made/antenna": { + "name": "アンテナ", + "terms": "アンテナ, 通信, テレビ" + }, "man_made/breakwater": { "name": "防波堤", "terms": "防波堤" @@ -4718,6 +4841,10 @@ "name": "煙突", "terms": "煙突" }, + "man_made/clearcut": { + "name": "皆伐地", + "terms": "皆伐, 伐採" + }, "man_made/crane": { "name": "クレーン", "terms": "クレーン" @@ -4757,6 +4884,10 @@ "name": "監視塔", "terms": "監視塔" }, + "man_made/observatory": { + "name": "観測ドーム", + "terms": "観測ドーム, 観測所" + }, "man_made/petroleum_well": { "name": "油田", "terms": "油田" @@ -4881,10 +5012,18 @@ "name": "荒地", "terms": "荒地, 植物" }, + "natural/mud": { + "name": "泥地", + "terms": "泥地, 泥" + }, "natural/peak": { "name": "山頂", "terms": "山頂, 頂" }, + "natural/reef": { + "name": "礁", + "terms": "礁, 岩礁, サンゴ礁, 砂礁, 暗礁, 海" + }, "natural/ridge": { "name": "尾根", "terms": "尾根, 稜線" @@ -5148,8 +5287,8 @@ "terms": " 小区画, プロット" }, "place/quarter": { - "name": "Sub-Borough / Quarter", - "terms": "Sub-Borough / Quarter" + "name": "大字 / (市内の)町", + "terms": "大字, 字, 町, 地名" }, "place/square": { "name": "広場(都心部)", @@ -5917,6 +6056,10 @@ "name": "ペットショップ", "terms": "ペット売り場, ペット, 家禽, ペットショップ, 動物" }, + "shop/pet_grooming": { + "name": "ペット美容室", + "terms": "ペット美容室, 動物美容, ペット, 美容, 犬の美容室, 愛犬美容, 犬, 猫" + }, "shop/photo": { "name": "写真店", "terms": "写真屋, 写真店, 現像, ビデオ, デジカメ" @@ -6136,6 +6279,10 @@ "name": "テーマパーク", "terms": "テーマパーク, 遊園地, 娯楽" }, + "tourism/trail_riding_station": { + "name": "乗馬トレール乗り場", + "terms": "乗馬トレール乗り場" + }, "tourism/viewpoint": { "name": "展望台", "terms": "展望台, 観光, 展望所, 名勝, 景色, 風景, パノラマ, 景勝" @@ -6228,8 +6375,12 @@ "terms": "右折専用, 右折のみ" }, "type/restriction/only_straight_on": { - "name": "直進のみ可", - "terms": "直進のみ可" + "name": "直進専用", + "terms": "直進専用, 直進のみ" + }, + "type/restriction/only_u_turn": { + "name": "Uターン専用", + "terms": "Uターン専用, Uターンのみ" }, "type/route": { "name": "ルート", @@ -6392,7 +6543,7 @@ "attribution": { "text": "規約&フィードバック" }, - "description": "画像の境界と取得日付。ラベルはズームレベル14以上で表示。", + "description": "画像の境界と取得日付。ラベルはズームレベル13以上で表示。", "name": "DigitalGlobeプレミアム画像撮影日" }, "DigitalGlobe-Standard": { @@ -6406,7 +6557,7 @@ "attribution": { "text": "規約&フィードバック" }, - "description": "画像の境界と取得日付。ラベルはズームレベル14以上で表示。", + "description": "画像の境界と取得日付。ラベルはズームレベル13以上で表示。", "name": "DigitalGlobe標準画像撮影日" }, "EsriWorldImagery": { @@ -6421,7 +6572,7 @@ "text": "規約 & フィードバック" }, "description": "おそらくEsriデフォルトのレイヤより明瞭で正確、しかしやや古いEsriアーカイブ画像。(日本での違いは不明)", - "name": "Esri World Imagery(鮮明版)ベータ" + "name": "Esri World Imagery(精細版)ベータ" }, "MAPNIK": { "attribution": { @@ -6490,6 +6641,10 @@ "description": "黄 = US Censusからのパブリックドメインの地図データ。赤 = penStreetMapに無いデータ。", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Highway: 緑枠 = unclassified.ブラウン枠 = track. Surface: gravel = ライトブラウン, Asphalt = 黒, paved = グレイ, ground =白, concrete = 青, grass = 緑. Seasonal = 白棒", + "name": "U.S. Forest Roads Overlay" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0" @@ -6524,7 +6679,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Basemap of Austria, based on goverment data.", + "description": "オーストリアのベースマップ、政府データに基づく。", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6586,7 +6741,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Map tiles by Stamen Design, under CC BY 3.0" + "text": "Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL" }, "name": "Stamen 地形図" }, @@ -6602,6 +6757,733 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "University of Cape Coast YouthMappers", + "description": "Follow us on Twitter: {url}", + "extendedDescription": "This is the official handle for the Youth Mappers chapter of the University of Cape Coast, Ghana. we love maps, open data and helping the vulnerable." + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana on Facebook", + "description": "Facebook group for people interested in OpenStreetMap.", + "extendedDescription": "Mappers in Ghana community, promoting OpenStreetMap and Humanitarian OpenStreetMap Team (HOT) projects in Ghana. Join us." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana on Twitter", + "description": "Follow us on Twitter: {url}" + }, + "talk-gh": { + "name": "Talk-gh Mailing List", + "description": "Talk-gh is the official mailing list for Ghana OSM community." + }, + "osm-mg-facebook": { + "name": "OpenStreetMap Madagascar Facebook Group", + "description": "Malagasy Facebook group for people interested in OpenStreetMap." + }, + "talk-mg": { + "name": "Talk-mg Mailing List", + "description": "Place for OpenStreetMap contributors, communities and users in Madagascar to share and discuss." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesh", + "description": "Improve OpenStreetMap in Bangladesh", + "extendedDescription": "Mapping in Bangladesh? Have questions, want to connect with the community here? Join us at {url}. All are welcome!" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap India - Participatory neighborhood mapping", + "description": "Improve OpenStreetMap in India", + "extendedDescription": "Mapping in India? Have questions, want to connect with the community here? Join us at {url}. All are welcome!", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "description": "Join the 2018 OpenStreetMap region-wide event at State of the Map Asia in India", + "where": "Indian Institute of Management, Bangalore, India" + } + } + }, + "OSM-india-mailinglist": { + "name": "OpenStreetMap India Mailinglist", + "description": "Talk-in is the official Mailinglist for Indian Community" + }, + "OSM-india-twitter": { + "name": "OpenStreetMap India Twitter", + "description": "We are just a tweet away: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Free Software Hardware Movement - Facebook", + "description": "FSHM Facebook page to know about community events, activities", + "extendedDescription": "FSHM organizes events relating to free software/hardware, technology, activism and OpenStreetMap. Its FB page is the best way to keep in contact with its events." + }, + "OSM-India-Puducherry-Matrix": { + "name": "Free Software Hardware Movement - Matrix", + "description": "FSHM Riot group to discuss, share and update mapping activities, events in and around Puducherry", + "extendedDescription": "FSHM community members share their OSM mapping updates / experiences through the Riot.im group, this group is also used to discuss things related to free software / hardware, technology and activism." + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonesia", + "description": "Improve OpenStreetMap in Indonesia", + "extendedDescription": "Mapping in Indonesia? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-japan-facebook": { + "name": "OpenStreetMap 日本コミュニティ", + "description": "日本のマッパーとOpenStreetMap ユーザー" + }, + "OSM-japan-mailinglist": { + "name": "OpenStreetMap 日本メーリングリスト", + "description": "Talk-ja は日本コミュニティ向けの公式メーリングリストです" + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap 日本のTwitter", + "description": "Twitterでのハッシュタグ: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap 日本", + "description": "日本のマッパーとOpenStreetMap ユーザー" + }, + "OSM-korea-telegram": { + "name": "OSM Korea Telegram Channel", + "description": "Unofficial Channnel for OpenStreetMap contributors, communities and users in Korea to share and discuss." + }, + "OSM-MY-facebook": { + "name": "OpenStreetMap Malaysia on Facebook", + "description": "For chat about anything related to OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "OpenStreetMap Malaysia Forum", + "description": "Official OpenStreetMap Malaysia Forum" + }, + "OSM-MY-matrix": { + "name": "OpenStreetMap Malaysia Riot channel", + "description": "All mappers are welcome! Sign up at {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongolia", + "description": "Improve OpenStreetMap in Mongolia", + "extendedDescription": "Mapping in Mongolia? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Myanmar", + "description": "Improve OpenStreetMap in Myanmar", + "extendedDescription": "Mapping in Myanmar? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Nepal", + "description": "Improve OpenStreetMap in Nepal", + "extendedDescription": "Mapping in Nepal? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-PH-facebook": { + "name": "OpenStreetMap PH Facebook", + "description": "Welcome to OpenStreetMap Philippines, where we encourage all fellow Filipinos to contribute to the OpenStreetMap project." + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph Mailing List", + "description": "A mailing list to discuss OpenStreetMap in the Philippines" + }, + "OSM-PH-slack": { + "name": "OpenStreetMap PH Slack", + "description": "All are welcome! Sign up at {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "OpenStreetMap PH Telegram", + "description": "Un-official, Telegram local community of OpenStreetMap contributors and friends in the Philippines" + }, + "OSM-RU-forum": { + "name": "OpenStreetMap RU forum", + "description": "OpenStreetMap Russia web forum" + }, + "OSM-RU-telegram": { + "name": "OpenStreetMap RU telegram", + "description": "OpenStreetMap Russia telegram chat" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka", + "description": "Improve OpenStreetMap in Sri Lanka", + "extendedDescription": "Mapping in Sri Lanka? Have questions, want to connect with the community here? Join us at {Url}. All are welcome!" + }, + "OSM-TW-facebook": { + "name": "OpenStreetMap Taiwan Community", + "description": "Facebook Group for Mappers and OpenStreetMap users to discuss matters about Taiwan." + }, + "OSM-TW-mailinglist": { + "name": "OpenStreetMap Taiwan Mailinglist", + "description": "Talk-tw is an Official Mailinglist for the Communities to dicuss matters about Taiwan" + }, + "OSM-TH-CNX-meetup": { + "name": "OSM Meetup Chiang Mai", + "description": "Irregular meeting of the OpenStreetMap community in Chiang Mai", + "extendedDescription": "Members of the OpenStreetMap community meet every few months in Chiang Mai. Get in contact and check out {url} to see when the next meetup is scheduled" + }, + "OSM-TH-forum": { + "name": "OpenStreetMap TH forum", + "description": "OpenStreetMap Thailand web forum" + }, + "at-forum": { + "name": "OpenStreetMap Austria Forum", + "description": "The official forum for OpenStreetMap questions in and around Austria" + }, + "at-mailinglist": { + "name": "Talk-at Mailing List", + "description": "Talk-at is the official mailing list for the Austrian OSM community" + }, + "at-twitter": { + "name": "OpenStreetMap Austria Twitter", + "description": "OpenStreetMap Austria On Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "OSM community meetup Graz", + "description": "Monthly meetup of the OpenStreetMap community in Graz" + }, + "osmgraz-twitter": { + "name": "OSM community Graz on twitter", + "description": "OpenStreetMap community in Graz on twitter" + }, + "osm-at": { + "name": "OpenStreetMap Austria", + "description": "The platform for information on OpenStreetMap in Austria" + }, + "byosm": { + "name": "OpenStreetMap Belarus", + "description": "OpenStreetMap Belarus telegram chat" + }, + "be-facebook": { + "name": "OpenStreetMap BE Community", + "description": "Mappers and OpenStreetMap on Facebook in Belgium" + }, + "be-forum": { + "name": "OpenStreetMap BE forum", + "description": "OpenStreetMap Belgium web forum" + }, + "be-irc": { + "name": "OpenStreetMap Belgium IRC", + "description": "Join #osmbe on irc.oftc.net (port 6667)", + "extendedDescription": "Join #osmbe on irc.oftc.net (port 6667), it is bridged with the Matrix chat channel" + }, + "be-mailinglist": { + "name": "Talk-be Mailing List", + "description": "Talk-be is the official mailing list for the Belgian OSM community" + }, + "be-maptime": { + "name": "Maptime Belgium", + "description": "Social events organized around mapping - beginners most welcome!", + "extendedDescription": "Maptime is an open learning environment for all levels and degrees of knowledge, offering intentional educational support for the beginner. Maptime is simultaneously flexible and structured, creating space for mapping tutorials, workshops, ongoing projects with a shared goal, and independent/collaborative work time." + }, + "be-matrix": { + "name": "OpenStreetMap BE Matrix channel", + "description": "All mappers are welcome!", + "extendedDescription": "Most talk is happening at the \"OpenStreetMap Belgium\" channel. You can ask anything there! The other rooms are for specific subjects." + }, + "be-meetup": { + "name": "OpenStreetMap Belgium Meetup", + "description": "Real life meetups of everyone who is interested in OpenStreetMap", + "extendedDescription": "Physical meetups are great to meet other mappers, ask them questions and to learn a lot. Especially new contributors are very welcome!" + }, + "be-twitter": { + "name": "OpenStreetMap Belgium Twitter", + "description": "OSM Belgium on Twitter: @osm_be" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz Mailing List", + "description": "Talk-cz is the official mailing list for Czech community" + }, + "dk-forum": { + "name": "OpenStreetMap Denmark Web Forum", + "description": "OpenStreetMap Denmark web forum" + }, + "dk-irc": { + "name": "OpenStreetMap Denmark IRC", + "description": "Join #osm-dk on irc.oftc.net (port 6667)" + }, + "dk-mailinglist": { + "name": "Talk-dk Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Denmark" + }, + "fr-facebook": { + "name": "OpenStreetMap France Facebook page", + "description": "OpenStreetMap France Facebook page" + }, + "fr-forum": { + "name": "OpenStreetMap France web forum", + "description": "OpenStreetMap France web forum" + }, + "fr-irc": { + "name": "OpenStreetMap France on IRC", + "description": "Join #osm-fr on irc.oftc.net (port 6667)" + }, + "fr-mailinglist": { + "name": "Talk-fr Mailing List", + "description": "Talk-fr mailing list" + }, + "fr-twitter": { + "name": "OpenStreetMap France on Twitter", + "description": "OpenStreetMap France on Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "Berlin Mailing List", + "description": "This is the mailing list for the Berlin OSM community" + }, + "de-berlin-meetup": { + "name": "OpenStreetMap Berlin-Brandenburg Meetup", + "description": "Mappers and OpenStreetMap users in the Berlin area" + }, + "de-berlin-telegram": { + "name": "@osmberlin on Telegram", + "description": "OpenStreetMap Berlin Telegram chat" + }, + "de-berlin-twitter": { + "name": "OpenStreetMap Berlin Twitter", + "description": "Follow us on Twitter: {url}" + }, + "de-forum": { + "name": "OpenStreetMap DE forum", + "description": "OpenStreetMap Germany web forum" + }, + "de-irc": { + "name": "OpenStreetMap Germany IRC", + "description": "Join #osm-de on irc.oftc.net (port 6667)" + }, + "de-mailinglist": { + "name": "Talk-de Mailing List", + "description": "Talk-de is the official mailing list for the German OSM community" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "OWL Mailing List", + "description": "This is the mailing list for the Ostwestfalen-Lippe OSM community" + }, + "osm-de": { + "name": "OpenStreetMap Germany", + "description": "The platform for information on OpenStreetMap in Germany" + }, + "hu-facebook": { + "name": "OpenStreetMap HU on Facebook", + "description": "Mappers and OpenStreetMap Facebook in Hungary" + }, + "hu-forum": { + "name": "OpenStreetMap HU forum", + "description": "OpenStreetMap Hungary web forum" + }, + "hu-meetup": { + "name": "OpenStreetMap Hungary Meetup", + "description": "The platform for organizing meetups in Hungary" + }, + "it-facebook": { + "name": "OpenStreetMap Italy Facebook", + "description": "Join the OpenStreetMap Italy community on Facebook" + }, + "it-irc": { + "name": "OpenStreetMap Italy IRC", + "description": "Join #osm-it on irc.oftc.net (port 6667)" + }, + "it-mailinglist": { + "name": "Talk-it Mailing List", + "description": "Talk-it is the official mailing list for the Italian OSM community" + }, + "it-twitter": { + "name": "OpenStreetMap Italy Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSM-Rome-meetup": { + "name": "Incontro Mappatori Romani", + "description": "Improve OpenStreetMap in the Rome area", + "extendedDescription": "We aim to be a resource for people to discuss and share knowledge on utilizing free geographic data sets especially OpenStreetMap, and Open geo-spatial software that manages, edits, and displays geographic data, and advocate for its use in Lazio." + }, + "South-Tyrol-Mailing-List": { + "name": "OpenStreetMap mailing list for South Tyrol", + "description": "OpenStreetMap Italy regional talk list for South Tyrol" + }, + "talk-it-lazio": { + "name": "OpenStreetMap IT Lazio", + "description": "All are welcome! Sign up at {signupUrl}", + "extendedDescription": "Mailinglist for Rome and Lazio area." + }, + "Trentino-Mailing-List": { + "name": "OpenStreetMap mailing list for Trentino", + "description": "OpenStreetMap Italy regional talk list for Trentino" + }, + "no-forum": { + "name": "OpenStreetMap Norway Web Forum", + "description": "OpenStreetMap Norway web forum" + }, + "no-irc": { + "name": "OpenStreetMap Norway on IRC", + "description": "Chat room for mappers and OpenStreetMap users, developers and enthusiasts in Norway" + }, + "no-mailinglist": { + "name": "OpenStreetMap Norway mailing list", + "description": "Mailing list for mappers and OpenStreetMap users, developers and enthusiasts in Norway" + }, + "OSM-PL-facebook-group": { + "name": "OpenStreetMap Poland Facebook group", + "description": "Group for mappers and users of OpenStreetMap in Poland" + }, + "OSM-PL-forum": { + "name": "OpenStreetMap Poland Forum", + "description": "Forum of Polish OpenStreetMap community" + }, + "OSM-ES-mailinglist": { + "name": "Talk-es mailing list", + "description": "A mailing list to discuss OpenStreetMap in Spain" + }, + "OSM-ES-telegram": { + "name": "@OSMes on Telegram", + "description": "OpenStreetMap Spain Telegram chat" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "Provide OSM services and information for the local community in Sweden" + }, + "se-facebook": { + "name": "OpenStreetMap Sweden Facebook", + "description": "OpenStreetMap Sweden on Facebook" + }, + "se-forum": { + "name": "OpenStreetMap Sweden Web Forum", + "description": "OpenStreetMap Sweden web forum" + }, + "se-irc": { + "name": "OpenStreetMap Sweden IRC", + "description": "Join #osm.se on irc.oftc.net (port 6667)" + }, + "se-mailinglist": { + "name": "Talk-se Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Sweden" + }, + "se-twitter": { + "name": "OpenStreetMap Sweden on Twitter", + "description": "Follow us on Twitter: {url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "East Midlands (Nottingham) Monthly pub meet-up", + "description": "Social gathering for East Midlands mappers and users", + "extendedDescription": "A group have been meeting since March 2011, initially in Nottingham, and, more recently in Derby, and from time to time elsewhere in the East Midlands. These are social gatherings, but are an excellent place to come and ask specific questions about OSM either in the area or in general. In the summer months we usually do some light mapping for an hour in the vicinity of our meeting place. The group as a whole has a special interest in mapping public rights of way and from time to time has mapping meetings for this purpose." + }, + "gb-mailinglist": { + "name": "Talk-gb Mailing List", + "description": "Talk-gb is the main communication forum list for the British (including Northern Ireland) OSM community" + }, + "mappa-mercia-group": { + "name": "Mappa Mercia local group", + "description": "A home for OpenStreetMap enthusiasts in the Midlands", + "extendedDescription": "Mappa Mercia is a project to grow OpenStreetMap in the West Midlands, UK. We run community events, provide training and support local organisations wishing to open up their data." + }, + "gb-irc": { + "name": "OpenStreetMap United Kingdom IRC", + "description": "Join #osm-gb on irc.oftc.net (port 6667)", + "extendedDescription": "Join #osm-gb on irc.oftc.net (port 6667), please be patient and wait for a few minutes if you ask a question" + }, + "OSM-CA-Slack": { + "name": "OSM-CA Slack", + "description": "All are welcome! Sign up at {signupUrl}." + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver", + "description": "Mappers and OpenStreetMap users in the Vancouver, BC area" + }, + "OSM-CU-telegram": { + "name": "OSM Cuba on Telegram", + "description": "OpenStreetMap Cuba Telegram chat" + }, + "OSM-NI-telegram": { + "name": "OSM Nicaragua on Telegram", + "description": "OpenStreetMap Nicaragua Telegram chat" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area OpenStreetMappers", + "description": "Improve OpenStreetMap in the Bay Area", + "extendedDescription": "This group is about growing the OpenStreetMap community here in the Bay Area. Our events are open to everyone, from open source enthusiasts, cyclists, GIS professionals, geocachers, and beyond. Anyone and everyone who is interested in maps, map making and free map data is welcome to join our group as well as attend our events." + }, + "Central-Pennsylvania-OSM": { + "name": "Central Pennsylvania OSM", + "description": "Online mapping community based out of State College, PA" + }, + "Code-for-San-Jose-Slack": { + "name": "Code for San Jose Slack", + "description": "All are welcome! Sign up at {signupUrl}, then join the #osm channel." + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "The OpenStreetMap user group for Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth, and all the cities in between are abounding with creative and tech-savvy people. The vision for this usergroup is to find new ways to use the amazing resource of OSM." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Meetup for map enthusiasts in the Philadelphia area", + "extendedDescription": "GeoPhilly unites developers, geographers, data geeks, open source enthusiasts, civic hackers and map addicts in our shared love of maps and the stories they tell. If you use maps as part of your work or just want to learn more, this is the meetup for you! Our events aim to be open, friendly, educational and social and range from happy hours to lightning talks or even workshops. Come create a diverse, inspiring geospatial community in the Philadelphia with us!" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "Mappers and OpenStreetMap enthusiasts in the Twin Cities area", + "extendedDescription": "Connecting OpenStreetMap enthusiasts in Minnesota and the Twin Cities!" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC", + "description": "Improve OpenStreetMap in the DC area", + "extendedDescription": "We are a group of volunteer mappers who aim to improve the OpenStreetMap in the DC area. We also aim to teach others about the OSM ecosystem, data analytics, cartography, and GIS. We gather every other month at meetups to focus on one area of our city." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Mappers and OpenStreetMap users, around Portland, ME", + "extendedDescription": "Maptime is, rather literally, time for mapmaking. Our mission is to open the doors of cartographic possibility to anyone interested by creating a time and space for collaborative learning, exploration, and map creation using mapping tools and technologies." + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Improve OpenStreetMap in the Cleveland area", + "extendedDescription": "Open Geo Cleveland aims to be a resource for people to discuss and share knowledge on utilizing free geographic data sets especially OpenStreetMap, and Open geo-spatial software that manages, edits, and displays geographic data, and advocate for its use in Northeast Ohio. We're also a maptime chapter =)" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Mappers and OpenStreetMap users in the Boston area", + "extendedDescription": "OpenStreetMap is the free and open, wiki-style map of the world, with hundreds of thousands of contributions every day from people like you. Editing the map is simple, and fun! Join us both indoors and outdoors in our effort to create the best map of the Boston area and the rest of the world!" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Central Salish Sea", + "description": "Mappers and OpenStreetMap users around Mount Vernon, WA", + "extendedDescription": "OpenStreetMap is an map of the world made by people like you. It's a map that you build, that's given away for free like wikipedia. Check out osm.org for more. We meet all the time to talk maps, make maps and have fun!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "The OpenStreetMap user group for Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "description": "Mappers and OpenStreetMap users in the state of Colorado, USA", + "extendedDescription": "OpenStreetMap (OSM) Colorado is a local collaboration of people interested in contributing their efforts to create free maps. We encourage all of our mappers to organize or suggest mapping events throughout the state. Meetup activities can be simple social mixers, OSM basic to advanced training, or community mapping parties." + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Mappers and OpenStreetMap users, developers and enthusiasts in the New York Metropolitan area" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Mappers and OpenStreetMap users in the Portland area", + "extendedDescription": "OpenStreetMap (OSM) is a map of the world made by people like you. It's a map that you build, that's given away for free like wikipedia. Check out osm.org for more, and come join us at a meetup to talk maps, contribute to OSM, and have fun!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Mappers and OpenStreetMap users in the Seattle area" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Southern California", + "description": "Let's have some fun, contribute something to Los Angeles, and learn about mapping!", + "extendedDescription": "OpenStreetMap (OSM) Southern California is for anyone interested in mapping to get together to work with OpenStreetMap. OpenStreetMap, the Wikipedia of maps, is a free open-source map of the world being created by more than 1,000,000 volunteers around the globe. Everyone is welcome. If you don't know OpenStreetMap, we'll teach you. If you have an idea for a mapping project or even a field trip that the group can do, great!" + }, + "OSM-South-Bay": { + "name": "OSM South Bay", + "description": "Map Nights hosted by Code for San Jose", + "extendedDescription": "Code for San Jose, the local Code for America brigade, hosts monthly Map Nights on Thursday nights in downtown San José. Meet fellow South Bay mappers, help out with local mapping projects, and hear about other civic tech projects. Programming and GIS skills are not required." + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Tampa Bay", + "description": "Mappers and OpenStreetMap users in the Tampa Bay area", + "extendedDescription": "OSM Tampa Bay group for local residents to get together and build out the definitive map of Tampa Bay with OpenStreetMap, the free and editable map of the world. If you're into maps, data, open source, GPS, hiking, cycling, et cetera, you'll love working with OpenStreetMap -- so join in! We'll get together and map and talk about new topics once-a-month or so." + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack", + "description": "All are welcome! Sign up at {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap US", + "description": "We help grow and improve OpenStreetMap in the United States.", + "extendedDescription": "We support OpenStreetMap by holding annual conferences, providing community resources, building partnerships, and by spreading the word. Join OpenStreetMap US here: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah", + "description": "Mappers and OpenStreetMap users in the Salt Lake City area", + "extendedDescription": "Activities may include things like Learn To Map workshops, mapping parties and outdoor data collection. The events will take place in the SLC area, at least initially. We are looking for seasoned mappers as well as people new to OSM. Join and let's do some mapping!" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming", + "description": "Mappers and OpenStreetMap users in the state of Wyoming", + "extendedDescription": "OpenStreetMap (OSM) Wyoming is a local collaboration of people interested in contributing their efforts to create free maps. We encourage all of our mappers to organize or suggest mapping events throughout the state. Meetup activities can be simple social mixers, OSM basic to advanced training, or community mapping parties." + }, + "PHXGeo-meetup": { + "name": "PHXGeo Meetup", + "description": "Mappers and OpenStreetMap users in the Phoenix, AZ area", + "extendedDescription": "This is a meetup group for those in the Phoenix area who like maps, GIS, OpenStreetMap, cartography and anything in between." + }, + "PHXGeo-twitter": { + "name": "PHXGeo Twitter", + "description": "Follow us on Twitter at {url}" + }, + "Western-Slope-facebook": { + "name": "Western Slope OSM Facebook", + "description": "Mappers and OpenStreetMap users around Grand Junction, CO" + }, + "Western-Slope-meetup": { + "name": "Western Slope OSM Meetup", + "description": "Mappers and OpenStreetMap users around Grand Junction, CO", + "extendedDescription": "The goal of this group is to introduce OpenStreetMap to the community, develop a community of mappers, create the most amazing geodata possible using whatever method we can and finally strategize in order to get this data out into our community. Imagine accurate trail signage! Imagine further development of bike paths! Imagine anything you want, that's the joy of OpenStreetMap!" + }, + "Maptime-Australia-Slack": { + "name": "Maptime Australia Slack", + "description": "Sign up at {signupUrl}" + }, + "talk-au": { + "name": "Talk-au Mailing List", + "description": "Place for Aussie mappers to chat" + }, + "OSM-AR-facebook": { + "name": "OpenStreetMap Argentina Facebook", + "description": "Join the OpenStreetMap Argentina community on Facebook", + "extendedDescription": "News from the local community" + }, + "OSM-AR-forum": { + "name": "OpenStreetMap Argentina web forum", + "description": "Join the OpenStreetMap Argentina web forum", + "extendedDescription": "Ideal for long or important discussions. Slow response time." + }, + "OSM-AR-irc": { + "name": "OpenStreetMap Argentina IRC", + "description": "Join #osm-ar on irc.oftc.net (port 6667)", + "extendedDescription": "You may find the most geeky user in the community." + }, + "OSM-AR-mailinglist": { + "name": "Talk-ar Mailing List", + "description": "Historic mailing list. Almost unused today." + }, + "OSM-AR-telegram": { + "name": "OpenStreetMap Argentina Telegram", + "description": "Join the OpenStreetMap Argentina community on Telegram", + "extendedDescription": "The most active channel in the community, ideal for chatting and getting answers to your questions instantly. Everyone is welcome!" + }, + "OSM-AR-twitter": { + "name": "OpenStreetMap Argentina Twitter", + "description": "Follow us on Twitter at {url}", + "extendedDescription": "News from the local community and OpenStreetMap in general." + }, + "OSM-BO-mailinglist": { + "name": "Talk-bo Mailing List", + "description": "Talk-bo is the official mailing list for the Bolivian OpenStreetMap community", + "extendedDescription": "Mapping in Bolivia? Have questions, want to connect with the community here? Join us at {url}. All are welcome!" + }, + "Bahia-telegram": { + "name": "OpenStreetMap Bahia Telegram Group", + "description": "Join the OpenStreetMap Bahia community on Telegram", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "DF-telegram": { + "name": "OpenStreetMap Brasília Telegram Group", + "description": "Join the OpenStreetMap Brasília community on Telegram", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "OSM-br-mailinglist": { + "name": "Talk-br Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Brazil" + }, + "OSM-br-telegram": { + "name": "OpenStreetMap Brasil Telegram", + "description": "Join the OpenStreetMap Brasil community on Telegram", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "OSM-br-twitter": { + "name": "OpenStreetMap Brasil Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSM-CL-facebook": { + "name": "OpenStreetMap Chile Facebook", + "description": "Join the OpenStreetMap Chile community on Facebook", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "OSM-CL-mailinglist": { + "name": "Talk-cl Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Chile" + }, + "OSM-CL-telegram": { + "name": "OpenStreetMap Chile Telegram", + "description": "Join the OpenStreetMap Chile community on Telegram", + "extendedDescription": "Join the community to learn more about OpenStreetMap, ask questions or participate in our meetings. Everyone is welcome!" + }, + "OSM-CL-twitter": { + "name": "OpenStreetMap Chile Twitter", + "description": "Follow us on Twitter at {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá", + "description": "We're a group of mappers interested in mapping in OpenStreetMap around Bogotá.", + "extendedDescription": "Learn to collect data in the field and digitize onto OpenStreetMap. It is not necessary to have previous knowledge! You just need the desire to participate, learn, and have fun." + }, + "OSM-CO-facebook": { + "name": "OpenStreetMap Colombia Facebook", + "description": "Join the OpenStreetMap Colombia community on Facebook", + "extendedDescription": "Join the community to learn more about OpenStreetMap. Everyone is welcome!" + }, + "OSM-CO-mailinglist": { + "name": "Talk-co Mailing List", + "description": "A mailing list to discuss OpenStreetMap in Colombia" + }, + "OSM-CO-telegram": { + "name": "OSM Colombia on Telegram", + "description": "OpenStreetMap Colombia Telegram chat" + }, + "OSM-CO-twitter": { + "name": "OpenStreetMap Colombia Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Colombia", + "description": "News of the OpenStreetMap Colombia community and the OSMCo Foundation" + }, + "OSM-EC-telegram": { + "name": "OSM Ecuador on Telegram", + "description": "OpenStreetMap Ecuador Telegram chat" + }, + "OSM-PY-telegram": { + "name": "OSM Paraguay on Telegram", + "description": "OpenStreetMap Paraguay Telegram chat" + }, + "OSM-PE-facebook": { + "name": "OpenStreetMap Peru Facebook", + "description": "Join the OpenStreetMap Peru community on Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Talk-pe Mailing List", + "description": "The official mailing list for the OpenStreetMap Peru community" + }, + "OSM-PE-matrix": { + "name": "OpenStreetMap Peru Matrix Chat", + "description": "Chat with other members of the OpenStreetMap Peru community in Matrix." + }, + "OSM-PE-telegram": { + "name": "OpenStreetMap Peru Telegram", + "description": "Join the OpenStreetMap Peru community on Telegram" + }, + "OSM-PE-twitter": { + "name": "OpenStreetMap Peru Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap Peru", + "description": "News and resources for the OpenStreetMap Peru community" + }, + "OSM-Facebook": { + "name": "Facebook上のOpenStreetMap", + "description": "Like us on Facebook for news and updates about OpenStreetMap." + }, + "OSM-help": { + "name": "OpenStreetMap ヘルプ", + "description": "OSMのコミュニティが運営しているQAサイトで質問して答えをもらいましょう。", + "extendedDescription": "{url} はOpenStreetMapについて知りたいことがある人みんなのためのものです。初心者マッパーでも技術的な質問でも、ぜひどうぞ。" + }, + "OSM-Reddit": { + "name": "Reddit上のOpenStreetMap", + "description": "/r/openstreetmap/ is a great place to learn more about OpenStreetMap. Ask us anything!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter", + "description": "Follow us on Twitter at {url}" + }, + "OSMF": { + "name": "OpenStreetMap ファウンデーション", + "description": "OSMF は英国に拠点を置くOpenStreetMapプロジェクトをサポートする非営利組織です", + "extendedDescription": "OSMF supports the OpenStreetMap by fundraising, maintaining the servers which power OSM, organizing the annual State of the Map conference, and coordinating the volunteers who keep OSM running. You can show your support and have a voice in the direction of OpenStreetMap by joining as an OSMF member here: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Join us for 3 days in Milan, Italy for the annual worldwide OpenStreetMap conference, bringing together everyone in the community to socialize, share, and learn.", + "where": "Milan, Italy" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/kn.json b/vendor/assets/iD/iD/locales/kn.json index c300009f2..b3e555336 100644 --- a/vendor/assets/iD/iD/locales/kn.json +++ b/vendor/assets/iD/iD/locales/kn.json @@ -163,7 +163,6 @@ "annotation": "{ನ} ವಸ್ತುಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ. ", "not_eligible": "ಈ ವಸ್ತುಗಳನ್ನು ಸೇರಿಸಲಾಗುವುದಿಲ್ಲ.", "not_adjacent": "ಈ ವಸ್ತುಗಳನ್ನು ಸೇರಿಸಲಾಗುವುದಿಲ್ಲ ಏಕೆಂದರೆ ಇವುಗಳ ಕೊನೆಗಳು ಒಂದಕ್ಕೊಂಡಕ್ಕೆ ಸೇರಿಕೊಂಡಿಲ್ಲ. ", - "restriction": "ಈ ವಸ್ತುಗಳನ್ನು ಸೇರಿಸಲಾಗುವುದಿಲ್ಲ ಏಕೆಂದರೆ ಕನಿಷ್ಟ ಒಂದು ವಸ್ತು ಒಂದು {ಸಂಬಂಧಕ್ಕೆ} ಸೇರಿದೆ. ", "incomplete_relation": "ಈ ವಸ್ತುಗಳನ್ನು ಸೇರಿಸಲಾಗುವುದಿಲ್ಲ ಏಕೆಂದರೆ ಇವುಗಳಲ್ಲಿ ಕನಿಷ್ಟಪಕ್ಷ ಒಂದಾದರೂ ಸಂಪೂರ್ಣವಾಗಿ ನಕಲಿಳಿಸಿಲ್ಲ. ", "conflicting_tags": "ಈ ವಸ್ತುಗಳನ್ನು ಸೇರಿಸಲಾಗುವುದಿಲ್ಲ ಏಕೆಂದರೆ ಇವುಗಳಲ್ಲಿ ಕೆಲವು ವಸ್ತುಗಳ ಗುರುತುಪಟ್ಟಿಗಳ ನಡುವೆ ಸಂಘರ್ಷವಿದೆ. " }, @@ -535,12 +534,7 @@ } }, "success": { - "edited_osm": "‍ಓಎಸ್‌ಎಂ ಸಂಪಾದಿಸಲಾಗಿದೆ!", "just_edited": "ನೀವು ಈಗ ಓಪನ್‍ ಸ್ಟ್ರೀಟ್ ಮ್ಯಾಪ್ ಸಂಪಾದಿಸಿದಿರಿ.", - "view_on_osm": "ಓ ಎಸ್ ಎಂ ನಲ್ಲಿ ನೋಡಿ. ", - "facebook": "ಫೇಸ್ ಬುಕ್ ನಲ್ಲಿ ಹಂಚಿಕೊಳ್ಳಿರಿ", - "twitter": "ಟ್ವಿಟರ ನಲ್ಲಿ ಹಂಚಿಕೊಳ್ಳಿರಿ", - "google": "ಗೂಗಲ್+ ನಲ್ಲಿ ಹಂಚಿಕೊಳ್ಳಿರಿ", "help_link_text": "ವಿವರಗಳು" }, "confirm": { @@ -1289,7 +1283,6 @@ } }, "phone": { - "label": "ದೂರವಾಣಿ", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { diff --git a/vendor/assets/iD/iD/locales/ko.json b/vendor/assets/iD/iD/locales/ko.json index a44710b61..2a072272e 100644 --- a/vendor/assets/iD/iD/locales/ko.json +++ b/vendor/assets/iD/iD/locales/ko.json @@ -1,5 +1,10 @@ { "ko": { + "icons": { + "information": "정보", + "remove": "제거", + "undo": "실행 취소" + }, "modes": { "add_area": { "title": "공간", @@ -25,6 +30,9 @@ }, "draw_line": { "tail": "선에 더 많은 노드를 추가하려면 클릭하세요. 다른 선을 노드로 연결하려면 다른 선을 클릭하고 선을 끝내려면 더블 클릭하세요." + }, + "drag_node": { + "connected_to_hidden": "이것은 숨겨진 지뭃에 연결되어 있기 때문에 편집할 수 없습니다." } }, "operations": { @@ -160,7 +168,6 @@ "annotation": "지물 {n}개를 병합했습니다.", "not_eligible": "이 지물은 병합할 수 없습니다.", "not_adjacent": "이 지물은 끝선이 연결되어 있지 않기 때문에 병합할 수 없습니다.", - "restriction": "이 지물은 적어도 하나가 \"{relation}\" 관계의 구성원이기 때문에 병합할 수 없습니다.", "incomplete_relation": "이 지물은 완전히 다운로드되어 있지 않기 때문에 병합할 수 없습니다.", "conflicting_tags": "이 지물은 일부 태그의 값이 상반되어 병합할 수 없습니다." }, @@ -288,6 +295,16 @@ } } }, + "restriction": { + "controls": { + "distance": "거리", + "via_node_only": "노드 전용" + }, + "help": { + "select_from": "{from} 분절을 선택하려면 클릭하세요.", + "select_from_name": "{from}{fromName}을(를) 선택하려면 클릭하십시요" + } + }, "undo": { "tooltip": "실행 취소: {action}", "nothing": "실행 취소할 것이 없습니다." @@ -599,15 +616,17 @@ } }, "success": { - "edited_osm": "OSM을 편집했습니다!", "just_edited": "오픈스트리트맵을 편집했습니다!", - "view_on_osm": "OSM에서 보기", - "facebook": "페이스북에 공유", - "twitter": "트위터에 공유", - "google": "Google+에 공유", - "help_html": "변경사항은 몇 분 후에 \"표준\" 레이어에서 보여집니다. 다른 레이어와 특정 지물은 더 오래 걸릴 수 있습니다.", + "thank_you_location": "{where} 주변의 지도에 기여해 주셔서 감사합니다.", + "help_html": "변경 내역은 몇 분 후에 OpenStreetMap에 보여집니다. 지도의 몇몇 부분은 업데이트 되기에 더 오래 걸릴 수 있습니다.", "help_link_text": "자세한 정보", - "help_link_url": "https://wiki.openstreetmap.org/wiki/Ko:FAQ#.EB.82.98.EB.8A.94_.EC.A7.80.EB.8F.84.EC.97.90_.EC.95.BD.EA.B0.84.EC.9D.98_.EB.B3.80.EA.B2.BD.EC.9D.84_.EA.B0.80.ED.96.88.EB.8B.A4._.EB.82.B4.EA.B0.80_.EC.96.B4.EB.96.BB.EA.B2.8C_.EB.82.98.EC.9D.98_.EB.B3.80.EA.B2.BD.EC.82.AC.ED.95.AD.EC.9D.84_.EB.B3.BC_.EC.88.98_.EC.9E.88.EB.82.98.EC.9A.94.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/Ko:FAQ#.EB.82.98.EB.8A.94_.EC.A7.80.EB.8F.84.EC.97.90_.EC.95.BD.EA.B0.84.EC.9D.98_.EB.B3.80.EA.B2.BD.EC.9D.84_.EA.B0.80.ED.96.88.EB.8B.A4._.EB.82.B4.EA.B0.80_.EC.96.B4.EB.96.BB.EA.B2.8C_.EB.82.98.EC.9D.98_.EB.B3.80.EA.B2.BD.EC.82.AC.ED.95.AD.EC.9D.84_.EB.B3.BC_.EC.88.98_.EC.9E.88.EB.82.98.EC.9A.94.3F", + "view_on_osm": "OSM에서 변경점 보기", + "changeset_id": "당신의 바뀜기록 번호: {changeset_id}", + "like_osm": "OpenStreetMap을 좋아하시나요? 다른 사람들과 만나세요:", + "languages": "언어: {languages}", + "missing": "목록에 무언가 빠졌나요?", + "tell_us": "말해주세요!" }, "confirm": { "okay": "확인", @@ -673,7 +692,8 @@ "view_on_mapillary": "Mapillary에서 이 그림 보기" }, "openstreetcam_images": { - "tooltip": "OpenStreetCam의 거리수준 사진" + "tooltip": "OpenStreetCam의 거리수준 사진", + "title": "사진 겹치기 (OpenStreetCam)" }, "openstreetcam": { "view_on_openstreetcam": "OpenStreetCam에서 이 사진 보기" @@ -704,8 +724,13 @@ "editing": { "title": "편집 & 저장하기", "select_h": "선택", + "select_left_click": "{leftclick}마우스 왼쪽키는 지물을 선택할 때 사용합니다. 선택됬을경우, 지물이 강조처리되고, 이름이나 주소와 같은 지물에 대한 정보가 사이드바에 표시됩니다. ", + "select_right_click": "{rightclick} 마우스 오른쪽 키는 회전, 이동, 삭제와 같은 지물에 대한 편집 메뉴를 표시합니다. ", "multiselect_h": "여러 선택", + "multiselect_shift_click": "`{shift}`+{leftclick} 여러 지물들을 같이 선택합니다. 여러 물체들을 쉽게 삭제하거나 옮길 수 있습니다.", + "multiselect_lasso": "여러 지물들을 선택할 수 있는 다른 방법은 `{shift}`키를 누른 상태로 {leftclick} 마우스 왼쪽 버튼으로 선택할 지물들을 묶는 것입니다. 이 경우, 올가미 내의 모든 점들이 선택됩니다.", "undo_redo_h": "되돌리기 & 복구하기", + "undo_redo": "변경 사항은 OpenStreetMap에 저장되기 전까지 로컬 브라우저에 저장됩니다. 이때에는 {undo}**실행취소**버튼으로 되돌릴 수 있고, {redo}**다시실행**버튼으로 복구할 수 있습니다.", "save_h": "저장", "upload_h": "업로드", "backups_h": "자동 백업", @@ -1492,6 +1517,9 @@ "display": { "label": "표시" }, + "distance": { + "label": "총 거리" + }, "dock": { "label": "유형" }, @@ -1643,6 +1671,24 @@ "label": "후프", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "options": { + "equestrian": "예", + "undefined": "아니오" + } + }, + "horse_riding": { + "options": { + "horse_riding": "예", + "undefined": "아니오" + } + }, + "horse_stables": { + "options": { + "stables": "예", + "undefined": "아니오" + } + }, "iata": { "label": "IATA" }, @@ -1782,6 +1828,9 @@ "label": "제한 속도", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "최대 투숙일수" }, @@ -1932,7 +1981,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "전화", "placeholder": "+82 2 123 4567" }, "piste/difficulty": { @@ -2328,6 +2376,7 @@ "label": "유형" }, "traffic_signals/direction": { + "label": "방향", "options": { "backward": "역방향", "both": "둘 다 / 모두", @@ -2366,6 +2415,9 @@ "label": "유형", "placeholder": "기본값" }, + "usage_rail": { + "label": "용도" + }, "vending": { "label": "상품 종류" }, @@ -2767,6 +2819,9 @@ "name": "시장", "terms": "시장" }, + "amenity/monastery": { + "name": "수도원 부지" + }, "amenity/motorcycle_parking": { "name": "오토바이 주차장", "terms": "모터사이클 주차장" @@ -2967,6 +3022,9 @@ "name": "담배 자판기", "terms": "담배 자판기, 담배 자동 판매기" }, + "amenity/vending_machine/coffee": { + "name": "커피 자판기" + }, "amenity/vending_machine/condoms": { "name": "콘돔 자판기", "terms": "콘돔 자판기, 콘돔 자동 판매기" @@ -2975,10 +3033,19 @@ "name": "음료 자판기", "terms": "음료 자판기, 음료 자동 판매기" }, + "amenity/vending_machine/electronics": { + "name": "전자 제품 자판기" + }, "amenity/vending_machine/excrement_bags": { "name": "쓰레기 봉투 자판기", "terms": "쓰레기 봉투 자판기, 쓰레기 봉투 자동 판매기" }, + "amenity/vending_machine/food": { + "name": "식품 자판기" + }, + "amenity/vending_machine/ice_cream": { + "name": "아이스크림 자판기" + }, "amenity/vending_machine/news_papers": { "name": "신문 자동판매기" }, @@ -2998,6 +3065,9 @@ "name": "1회용 교통카드·승차권 판매기", "terms": "1회용 교통카드·승차권 판매기, 대중교통 티켓 발권기" }, + "amenity/vending_machine/stamps": { + "name": "우표 자판기" + }, "amenity/vending_machine/sweets": { "name": "간식 자판기", "terms": "간식 자판기, 과자 자판기" @@ -3066,6 +3136,9 @@ "name": "자이로드롭", "terms": "자이로드롭" }, + "attraction/maze": { + "name": "미로" + }, "attraction/pirate_ship": { "name": "바이킹", "terms": "바이킹" @@ -3217,6 +3290,12 @@ "building/entrance": { "name": "입구/출구" }, + "building/farm": { + "name": "농가" + }, + "building/farm_auxiliary": { + "name": "농장 건물" + }, "building/garage": { "name": "차고", "terms": "차고" @@ -3373,6 +3452,9 @@ "name": "요리 조달자", "terms": "요리 조달자" }, + "craft/chimney_sweeper": { + "name": "굴뚝 청소부" + }, "craft/clockmaker": { "name": "시계공", "terms": "시계 제작자" @@ -3649,6 +3731,9 @@ "healthcare/hospice": { "name": "호스피스" }, + "healthcare/laboratory": { + "name": "의학 연구소" + }, "healthcare/midwife": { "name": "조산사", "terms": "산파" @@ -4085,6 +4170,12 @@ "name": "성인용 게임방", "terms": "도박,노름,슬롯머신" }, + "leisure/amusement_arcade": { + "name": "오락실" + }, + "leisure/beach_resort": { + "name": "해변 리조트" + }, "leisure/bird_hide": { "name": "탐조대", "terms": "감시대,전망대,조망대,새,조류" @@ -4156,6 +4247,9 @@ "name": "자연 보호 구역", "terms": "자연 보호 구역, 개발 제한 구역" }, + "leisure/outdoor_seating": { + "name": "야외 좌석 구역" + }, "leisure/park": { "name": "공원", "terms": "공원" @@ -4283,6 +4377,9 @@ "name": "수평갱", "terms": "횡갱" }, + "man_made/antenna": { + "name": "안테나" + }, "man_made/breakwater": { "name": "방파제", "terms": "방파제" @@ -4334,6 +4431,10 @@ "name": "전망대", "terms": "관찰탑, 감시탑" }, + "man_made/observatory": { + "name": "관측소", + "terms": "천문대,기상대" + }, "man_made/petroleum_well": { "name": "유정", "terms": "유정" @@ -4458,10 +4559,16 @@ "name": "황무지", "terms": "황무지" }, + "natural/mud": { + "name": "진흙" + }, "natural/peak": { "name": "정상", "terms": "봉우리,산꼭대기,정점,첨봉,언덕,산" }, + "natural/reef": { + "name": "암초" + }, "natural/ridge": { "name": "산등성이", "terms": "산등성이" @@ -5032,6 +5139,10 @@ "name": "상점", "terms": "가게" }, + "shop/agrarian": { + "name": "농업 용품 가게", + "terms": "농기계,씨앗,종자,농약,살충제,비료,농기구" + }, "shop/alcohol": { "name": "주류 상점", "terms": "알코올,술,맥주,와인,포도주" @@ -5625,18 +5736,6 @@ "name": "유턴 금지", "terms": "유턴 금지" }, - "type/restriction/only_left_turn": { - "name": "좌회전 전용", - "terms": "좌회전 전용" - }, - "type/restriction/only_right_turn": { - "name": "우회전 전용", - "terms": "우회전 전용" - }, - "type/restriction/only_straight_on": { - "name": "회전 금지", - "terms": "회전 금지" - }, "type/route": { "name": "노선", "terms": "경로, 노선" @@ -5663,10 +5762,16 @@ "type/route/horse": { "name": "승마 노선" }, + "type/route/light_rail": { + "name": "경전철 노선" + }, "type/route/pipeline": { "name": "파이프라인 노선", "terms": "관로 노선,도관 노선" }, + "type/route/piste": { + "name": "피스트/스키 노선" + }, "type/route/power": { "name": "전력 노선" }, @@ -5957,9 +6062,6 @@ } }, "stamen-terrain-background": { - "attribution": { - "text": "맵 타일 by Stamen Design, CC BY 3.0 이하" - }, "name": "Stamen 지형" }, "tf-cycle": { @@ -5974,6 +6076,39 @@ }, "name": "Thunderforest 풍경" } + }, + "community": { + "osm-gh-facebook": { + "description": "OpenStreetMap에 관심 있는 사람들을 위한 Facebook그룹." + }, + "osm-gh-twitter": { + "description": "트위터에서 우리를 팔로우해주세요: {url}" + }, + "OSM-japan-facebook": { + "name": "OpenStreetMap 일본 커뮤니티", + "description": "일본의 OpenStreetMap 사용자와 맵퍼들" + }, + "OSM-japan-mailinglist": { + "name": "OpenStreetMap 일본 메일링리스트", + "description": "Talk-ja는 일본 커뮤니티의 공식 메일링리스트입니다." + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap 일본 트위터" + }, + "OSM-korea-telegram": { + "name": "OSM 한국 텔레그램 채널", + "description": "OpenStreetMap 한국 사용자들이 정보를 공유하고 토론하는 비공식 채널입니다." + }, + "OSM-Reddit": { + "description": "/r/openstreetmap/ 은 OpenStreetMap에 대해서 물어보기에 가장 좋은 곳입니다. 무엇이든지 물어보세요!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap 트위터" + }, + "OSMF": { + "name": "OpenStreetMap 재단", + "description": "OSMF는 OpenStreetMap을 운영하는 영국 기반의 비영리 재단입니다." + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/ku.json b/vendor/assets/iD/iD/locales/ku.json index cb12885d0..cfb02583f 100644 --- a/vendor/assets/iD/iD/locales/ku.json +++ b/vendor/assets/iD/iD/locales/ku.json @@ -2,7 +2,7 @@ "ku": { "modes": { "add_area": { - "title": "Herêm" + "title": "Qad" }, "add_line": { "title": "Xêz" @@ -23,31 +23,86 @@ "title": "Çarçik", "key": "S" }, + "straighten": { + "key": "S" + }, "delete": { "title": "Jê bibe" + }, + "disconnect": { + "key": "D" + }, + "merge": { + "key": "C" + }, + "move": { + "key": "M" + }, + "reflect": { + "key": { + "long": "T", + "short": "Y" + } } }, "translate": { "localized_translation_name": "Nav" }, + "zoom_in_edit": "Ji bo guherandinê nêzîk bike", "login": "têkeve", "logout": "derkeve", "commit": { - "save": "Bar bike", - "cancel": "Betal bike" + "save": "Bişîne", + "cancel": "Betal bike", + "deleted": "Hate jêbirin", + "created": "Hate afirandin" + }, + "contributors": { + "list": "Guherînên {users}", + "truncated_list": "Guherînên {users} û {count} yên din" }, "info_panels": { + "key": "I", + "background": { + "key": "B", + "source": "Çavkanî", + "description": "Danasîn" + }, "history": { - "title": "Dîrok" + "key": "H", + "title": "Dîrok", + "version": "Guherto", + "edited_by": "Hat guherîn ji alî" + }, + "measurement": { + "area": "Qad" } }, + "geometry": { + "area": "qad" + }, + "geolocate": { + "title": "Cihê min nîşan bide" + }, "inspector": { "search": "Lêbigere", + "feature_list": "Li bireseran bigere", "check": { "yes": "Erê", "no": "Na" } }, + "map_data": { + "title": "Daneyên nexşeyê", + "description": "Daneyên nexşeyê" + }, + "save": { + "title": "Qeyd bike" + }, + "zoom": { + "in": "Nêzîk bike", + "out": "Dûr bike" + }, "help": { "title": "Alîkarî", "help": { @@ -60,6 +115,232 @@ "points": { "title": "Nuqte" } + }, + "shortcuts": { + "key": { + "delete": "Jê bibe" + }, + "editing": { + "commands": { + "save": "Guherandinan qeyd bike" + } + } + }, + "presets": { + "fields": { + "access": { + "types": { + "access": "Hemû" + } + }, + "address": { + "label": "Adrês", + "placeholders": { + "city": "Bajar", + "city!vn": "Bajar/Bajarok", + "conscriptionnumber": "123", + "country": "Welat", + "county!jp": "Navçe", + "district": "Navçe", + "hamlet": "Mezra", + "housenumber": "123", + "province": "Parêzgeh", + "state": "Dewlet", + "street": "Kolan" + } + }, + "aerialway": { + "label": "Cûre" + }, + "aerialway/summer/access": { + "options": { + "exit": "Derkeve" + } + }, + "aeroway": { + "label": "Cûre" + }, + "amenity": { + "label": "Cûre" + }, + "area/highway": { + "label": "Cûre" + }, + "artwork_type": { + "label": "Cûre" + }, + "barrier": { + "label": "Cûre" + }, + "bicycle_parking": { + "label": "Cûre" + }, + "board_type": { + "label": "Cûre" + }, + "boules": { + "label": "Cûre" + }, + "boundary": { + "label": "Cûre" + }, + "bridge": { + "label": "Cûre" + }, + "bunker_type": { + "label": "Cûre" + }, + "castle_type": { + "label": "Cûre" + }, + "club": { + "label": "Cûre" + }, + "construction": { + "label": "Cûre" + }, + "country": { + "label": "Welat" + }, + "craft": { + "label": "Cûre" + }, + "crossing": { + "label": "Cûre" + }, + "cutting": { + "label": "Cûre" + }, + "direction_cardinal": { + "options": { + "E": "Rojhilat", + "ENE": "Rojhilat-bakurê rojhilat", + "ESE": "Rojhilat-başûrê rojhilat", + "N": "Bakur", + "NE": "Bakurê rojava", + "NNE": "Bakur-bakurê rojhilat", + "NNW": "Bakur-bakurê rojava", + "NW": "Bakurê rojava", + "S": "Başûr", + "SE": "Başûrê rojhilat", + "SSE": "Başûr-başûrê rojhilat", + "SSW": "Başûr-başûrê rojava", + "SW": "Başûrê rojava", + "W": "Rojava", + "WNW": "Rojava-bakurê rojava", + "WSW": "Rojava-başûrê rojava" + } + }, + "electrified": { + "options": { + "no": "Na" + } + }, + "embankment": { + "label": "Cûre" + }, + "entrance": { + "label": "Cûre" + }, + "fax": { + "label": "Faks" + }, + "fire_hydrant/type": { + "label": "Cûre", + "options": { + "wall": "Dîwar" + } + }, + "ford": { + "label": "Cûre" + }, + "generator/source": { + "label": "Çavkanî" + }, + "generator/type": { + "label": "Cûre" + }, + "government": { + "label": "Cûre" + }, + "highway": { + "label": "Cûre" + }, + "historic": { + "label": "Cûre" + }, + "information": { + "label": "Cûre" + }, + "internet_access": { + "options": { + "no": "Na", + "yes": "Erê" + } + }, + "lamp_type": { + "label": "Cûre" + }, + "landuse": { + "label": "Cûre" + }, + "leisure": { + "label": "Cûre" + }, + "man_made": { + "label": "Cûre" + }, + "manhole": { + "label": "Cûre" + }, + "map_type": { + "label": "Cûre" + }, + "memorial": { + "label": "Cûre" + }, + "name": { + "label": "Nav" + }, + "oneway_yes": { + "options": { + "no": "Na", + "yes": "Erê" + } + }, + "parking": { + "label": "Cûre" + }, + "place": { + "label": "Cûre" + }, + "power": { + "label": "Cûre" + }, + "second_hand": { + "options": { + "no": "Na", + "yes": "Erê" + } + }, + "takeaway": { + "options": { + "no": "Na", + "yes": "Erê" + } + }, + "trees": { + "label": "Dar" + }, + "wikipedia": { + "label": "Wîkîpediya" + } + }, + "presets": { + "landuse/forest": { + "name": "Daristan" + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/lt.json b/vendor/assets/iD/iD/locales/lt.json index 954d40e7c..102647df9 100644 --- a/vendor/assets/iD/iD/locales/lt.json +++ b/vendor/assets/iD/iD/locales/lt.json @@ -160,7 +160,6 @@ "annotation": "Sulieti {n} objektai.", "not_eligible": "Šie geoobjektai negali būti sulieti.", "not_adjacent": "Šių objektų negalima sulieti, nes jų pabaigos taškai nėra sujungti.", - "restriction": "Šių objektų negalima sulieti, nes bent vienas iš jų yra ryšyje „{relation}“,", "incomplete_relation": "Šie objektai negali būti sujungti, nes ne visi pilnai atsiųsti.", "conflicting_tags": "Šių objektų negalima sulieti, nes kai kurios iš jų žymų turi nesuderinamas reikšmes." }, @@ -520,13 +519,7 @@ } }, "success": { - "edited_osm": "Pakeitėte OSM!", "just_edited": "Jūs ką tik pakeitėte OpenStreetMap!", - "view_on_osm": "Žiūrėti OSM žemėlapyje", - "facebook": "Pasidalinti Facebook'e", - "twitter": "Pasidalinti Twitter'yje", - "google": "Pasidalinti Google+", - "help_html": "Jūsų pakeitimai turėtų būti matomi „Standartiniame“ sluoksnyje po kelių minučių. Kituose sluoksniuose ir kai kurios savybės gali pasirodyti vėliau.", "help_link_text": "Detalės", "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" }, @@ -1319,7 +1312,6 @@ "label": "Mokėjimo tipai" }, "phone": { - "label": "Telefonas", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -1538,9 +1530,6 @@ "trees": { "label": "Medžiai" }, - "vending": { - "label": "Prekių tipas" - }, "visibility": { "label": "Matomumas" }, @@ -3165,18 +3154,6 @@ "name": "Jokio apsisukimo", "terms": "Negalima apsisukti" }, - "type/restriction/only_left_turn": { - "name": "Sukimas tik į kairę", - "terms": "Tik į kairę" - }, - "type/restriction/only_right_turn": { - "name": "Sukimas tik į dešinę", - "terms": "Tik į dešinę" - }, - "type/restriction/only_straight_on": { - "name": "Jokių posūkių", - "terms": "Nėra posūkių" - }, "type/route": { "name": "Maršrutas", "terms": "Maršrutas" diff --git a/vendor/assets/iD/iD/locales/lv.json b/vendor/assets/iD/iD/locales/lv.json index 8cb5b56f6..572edb04b 100644 --- a/vendor/assets/iD/iD/locales/lv.json +++ b/vendor/assets/iD/iD/locales/lv.json @@ -217,12 +217,7 @@ } }, "success": { - "edited_osm": "Jūs izmainījāt OSM!", - "just_edited": "Jūs nupat rediģējāt OpenStreetMap", - "view_on_osm": "Apskatīt OSM", - "facebook": "Dalīties Facebook", - "twitter": "Dalīties uz Facebook", - "google": "Dalīties uz Google+" + "just_edited": "Jūs nupat rediģējāt OpenStreetMap" }, "confirm": { "cancel": "Atcelt" @@ -437,9 +432,6 @@ "parking": { "label": "Tips" }, - "phone": { - "label": "Telefons" - }, "place": { "label": "Tips" }, diff --git a/vendor/assets/iD/iD/locales/mg.json b/vendor/assets/iD/iD/locales/mg.json index 106a82ffd..920ca0ce3 100644 --- a/vendor/assets/iD/iD/locales/mg.json +++ b/vendor/assets/iD/iD/locales/mg.json @@ -17,7 +17,7 @@ }, "browse": { "title": "Hisava.", - "description": "Akisaho ary hangezao ny sarintany." + "description": "Akisaho ary hakaikezo ny sarintany." }, "draw_area": { "tail": "Tsindrio raha hampiditra vona eo faritra misy anao. Tsindrio ilay teboka voalohany raha hamarana ny fanoritana faritra." @@ -204,6 +204,20 @@ } } }, + "zoom_in_edit": "Hakaikezo raha hanova", + "info_panels": { + "background": { + "zoom": "Hakaiky" + } + }, + "zoom": { + "in": "Hanakaiky", + "out": "Hanalavitra" + }, + "cannot_zoom": "Tsy afaka manalavitra noho izao intsony amin'ity maody ity.", + "gpx": { + "zoom": "Hanangeza araky ny sosona" + }, "intro": { "graph": { "block_number": "", @@ -218,6 +232,13 @@ "suburb": "", "countrycode": "mg" } + }, + "shortcuts": { + "browsing": { + "navigation": { + "zoom": "Hanakaiky / Hanalavitra" + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/mk.json b/vendor/assets/iD/iD/locales/mk.json index cd42f8143..cdb7ead43 100644 --- a/vendor/assets/iD/iD/locales/mk.json +++ b/vendor/assets/iD/iD/locales/mk.json @@ -138,7 +138,6 @@ "key": "C", "annotation": "Споени {n} елементи.", "not_eligible": "Овие елементи не можат да се спојат.", - "restriction": "Овие елементи не можат да се спојат бидејќи барем еден од нив членува во односот „{relation}“.", "incomplete_relation": "Овие елементи не можат да се спојат бидејќи барем еден од нив не е наполно преземен.", "conflicting_tags": "Овие елементи не можат да се спојат бидејќи некои од нивните ознаки имаат спротиставени вредности." }, @@ -412,13 +411,7 @@ } }, "success": { - "edited_osm": "Уреден OSM!", "just_edited": "Штотуку го уредивте OpenStreetMap!", - "view_on_osm": "Погл. на OSM", - "facebook": "Сподели на Фејсбук", - "twitter": "Сподели на Твитер", - "google": "Сподели на Гугл+", - "help_html": "Вашите промени треба да се појават во слојот „Стандарден“ за некоја минута. На другите слоеви и извесни елементи може да им треба повеќе време.", "help_link_text": "Подробно", "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" }, @@ -1181,7 +1174,6 @@ "label": "Видови плаќање" }, "phone": { - "label": "Телефонско", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -1457,9 +1449,6 @@ "trees": { "label": "Дрва" }, - "vending": { - "label": "Вид стока" - }, "visibility": { "label": "Видливост", "options": { @@ -3993,18 +3982,6 @@ "name": "Забранет пресврт", "terms": "<преведете со истозначници или сродни поими на „Забранет пресврт“, одделени со запирки>" }, - "type/restriction/only_left_turn": { - "name": "Дозволено вртење само лево", - "terms": "<преведете со истозначници или сродни поими на „Дозволено вртење само лево“, одделени со запирки>" - }, - "type/restriction/only_right_turn": { - "name": "Дозволено вртење само десно", - "terms": "<преведете со истозначници или сродни поими на „Дозволено вртење само десно“, одделени со запирки>" - }, - "type/restriction/only_straight_on": { - "name": "Забрането вртење", - "terms": "<преведете со истозначници или сродни поими на „Забрането вртење“, одделени со запирки>" - }, "type/route": { "name": "Правец", "terms": "<преведете со истозначници или сродни поими на „Правец“, одделени со запирки>" diff --git a/vendor/assets/iD/iD/locales/ms.json b/vendor/assets/iD/iD/locales/ms.json index 179c3192c..05dfe5700 100644 --- a/vendor/assets/iD/iD/locales/ms.json +++ b/vendor/assets/iD/iD/locales/ms.json @@ -160,7 +160,6 @@ "annotation": "{n} gambaran telah digabung.", "not_eligible": "Gambaran-gambaran ini tidak dapat digabungkan.", "not_adjacent": "Ciri-ciri ini tidak dapat digabungkan kerana titik hujung mereka tidak bersambung.", - "restriction": "Ciri-ciri ini tidak dapat digabungkan kerana sekurang-kurangnya satu adalah ahli hubungan \"{relation}\".", "incomplete_relation": "Ciri-ciri ini tidak dapat digabungkan kerana sekurang-kurangnya satu belum sepenuhnya dimuat turun.", "conflicting_tags": "Ciri-ciri ini tidak dapat digabungkan kerana beberapa penanda mereka mempunyai nilai yang bercanggah." }, @@ -577,13 +576,7 @@ } }, "success": { - "edited_osm": "OSM telah Disunting!", "just_edited": "Anda baru sahaja telah menyunting OpenStreetMap!", - "view_on_osm": "Lihat dalam OSM", - "facebook": "Kongsi melalui Facebook", - "twitter": "Kongsi melalui Twitter", - "google": "Kongsi melalui Google+", - "help_html": "Perubahan anda akan muncul pada lapisan \"Standard\" dalam beberapa minit. Lapisan lain, dan ciri-ciri tertentu, mungkin mengambil masa yang lebih lama.", "help_link_text": "Butiran", "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" }, @@ -1625,7 +1618,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telefon", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2773,7 +2765,6 @@ "attribution": { "text": "Terma & Maklum Balas" }, - "description": "Had-had imejan dan tarikh rakaman dibuat. Label hanya kelihatan pada paras zum 14 dan lebih tinggi.", "name": "Vintaj Imejan Satelit Premium DigitalGlobe" }, "DigitalGlobe-Standard": { @@ -2787,7 +2778,6 @@ "attribution": { "text": "Terma & Maklum Balas" }, - "description": "Had-had imejan dan tarikh rakaman dibuat. Label hanya kelihatan pada paras zum 14 dan lebih tinggi.", "name": "Vintaj Imejan Satelit Standard DigitalGlobe" }, "EsriWorldImagery": { @@ -2883,7 +2873,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Petaasas Austria, berdasarkan data kerajaan.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -2944,9 +2933,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Jubin peta oleh Stamen Design, di bawah CC BY 3.0" - }, "name": "Rupa Bumi Stamen" }, "tf-cycle": { @@ -2961,6 +2947,57 @@ }, "name": "Landskap Thunderforest" } + }, + "community": { + "Bay-Area-OpenStreetMappers": { + "name": "OpenStreetMappers Kawasan Teluk", + "description": "Perbaiki OpenStreetMap di Kawasan Teluk", + "extendedDescription": "Kumpulan ini ialah mengenai memperkembangkan komuniti OpenStreetMap di Kawasan Teluk ini. Acara-acara kami adalah terbuka kepada sesiapa sahaja, dari peminat sumber terbuka, penunggang basikal, profesional GIS, pengcache geo, dan sebagainya. Sesiapa sahaja dan semua orang yang berminat dalam peta, membuat peta, dan data peta percuma adalah dialu-alukan untuk menyertai kumpulan kami serta menghadiri acara-acara kami." + }, + "Central-Pennsylvania-OSM": { + "name": "OSM Pennsylvania Pusat", + "description": "Komuniti pemetaan atas talian yang berpusat di luar State College, PA" + }, + "Dallas-Fort-Worth-OSM": { + "name": "OSM Dallas-Fort Worth", + "description": "Kumpulan pengguna OpenStreetMap bagi Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth, dan kesemua bandar di antaranya adalah berlimpah dengan orang-orang yang kreatif dan celik teknologi. Visi kumpulan pengguna ini ialah untuk mencari cara-cara yang baru untuk menggunakan sumber OSM yang hebat." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Pertemuan untuk peminat-peminat peta di kawasan Philadelphia", + "extendedDescription": "GeoPhilly menyatukan pemaju, ahli geografi, gek data, peminat sumber terbuka, penggodam awam dan kaki peta dalam perkongsian minat kita tentang peta dan cerita-cerita yang dikongsi sama. Jika anda menggunakan peta sebagai sebahagian dari kerja anda atau hanya untuk mempelajari dengan lebih lanjut, ini ialah pertemuan untuk anda! Acara kami bertujuan untuk menjadi terbuka, mesra, berpendidikan dan bersosial dan berjulat dari jam gembira kepada ceramah kilat atau malah bengkel. Datanglah untuk mencipta komuniti yang berpelbagai, berinspirasi di Philadelphia dengan kami!" + }, + "Mapping-DC-meetup": { + "name": "Memeta DC", + "description": "Perbaiki OpenStreetMap di kawasan DC", + "extendedDescription": "Kami ialah sebuah kumpulan pemeta sukarela yang bertujuan untuk memperbaiki OpenStreetMap di kawasan DC. Kami juga berhasrat untuk mengajar yang lain tentang ekosistem OSM, penganalisaan data, kartografi, dan GIS. Kami berkumpul setiap bulan yang lain dalam pertemuan untuk memfokuskan pada satu kawasan bandar kami." + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "Kumpulan pengguna OpenStreetMap bagi Chattanooga" + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Pemeta dan pengguna OpenStreetMap, pemaju dan peminat di kawasan Metropolitan New York" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Pemeta dan pengguna OpenStreetMap di kawasan Portland", + "extendedDescription": "OpenStreetMap (OSM) ialah sebuah peta dunia yang dibuat oleh orang-orang seperti anda. Ianya sebuah peta yang anda buat, diberi secara percuma seperti wikipedia. Lihat osm.org bagi yang lanjut, dan datang sertai kami pada pertemuan untuk berbincang tentang peta, menyumbang ke OSM, dan berseronok!" + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack", + "description": "Semua dialu-alukan hadir! Daftar di {signupUrl}" + }, + "Maptime-Australia-Slack": { + "name": "Maptime Australia Slack", + "description": "Daftar di {signupUrl}" + }, + "OSM-Reddit": { + "name": "OpenStreetMap di Reddit", + "description": "/r/openstreetmap/ ialah sebuah tempat yang hebat untuk mempelajari lebih lanjut tentang OpenStreetMap. Tanya apa sahaja kepada kami!" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/nl.json b/vendor/assets/iD/iD/locales/nl.json index b356713d1..900ad6363 100644 --- a/vendor/assets/iD/iD/locales/nl.json +++ b/vendor/assets/iD/iD/locales/nl.json @@ -1,5 +1,10 @@ { "nl": { + "icons": { + "information": "info", + "remove": "verwijder", + "undo": "ongedaan maken" + }, "modes": { "add_area": { "title": "Vlak", @@ -27,7 +32,7 @@ "tail": "Klik om meer knooppunten aan de lijn toe te voegen. Klik op een andere lijn om er een verbinding te maken en dubbelklik om de lijn af te sluiten." }, "drag_node": { - "connected_to_hidden": "Dit kan niet bewerkt worden, omdat het verbonden is met een verborgen object." + "connected_to_hidden": "Dit kan niet bewerkt worden omdat het verbonden is met een verborgen object." } }, "operations": { @@ -145,7 +150,9 @@ "vertex": "Weg aan andere weg verbonden.", "line": "Weg aan lijn verbonden.", "area": "Weg aan vlak verbonden." - } + }, + "relation": "Deze objecten kunnen niet verbonden worden omdat ze andere rollen in een relatie hebben.", + "restriction": "Deze objecten kunnen niet verbonden worden omdat dat een \"{relation}\"-relatie zou beschadigen." }, "disconnect": { "title": "Maak los", @@ -163,7 +170,8 @@ "annotation": "{n} objecten samengevoegd.", "not_eligible": "Deze objecten kunnen niet samengevoegd worden.", "not_adjacent": "Deze objecten kunnen niet samengevoegd worden omdat hun uiteinden niet verbonden zijn.", - "restriction": "Deze objecten kunnen niet samengevoegd worden omdat minstens één ervan lid is van een \"{relation}\"-relatie.", + "restriction": "Deze objecten kunnen niet samengevoegd worden omdat dat een \"{relation}\"-relatie zou beschadigen.", + "relation": "Deze objecten kunnen niet verbonden worden omdat ze andere rollen in een relatie hebben.", "incomplete_relation": "Deze objecten kunnen niet samengevoegd worden omdat minstens één ervan niet volledig gedownload is.", "conflicting_tags": "Deze objecten kunnen niet samengevoegd worden omdat sommige van hun tags conflicteren." }, @@ -291,6 +299,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Afstand", + "distance_up_to": "Tot en met {distance}", + "via": "Via", + "via_node_only": "Enkel knooppunt", + "via_up_to_one": "Tot en met 1 weg", + "via_up_to_two": "Tot en met 2 wegen" + }, + "help": { + "indirect": "(indirect)", + "turn": { + "no_left_turn": "NIET links afslaan {indirect}", + "no_right_turn": "NIET rechts afslaan {indirect}", + "no_u_turn": "NIET omkeren {indirect}", + "no_straight_on": "NIET rechtdoor gaan {indirect}", + "only_left_turn": "ALLEEN links afslaan {indirect}", + "only_right_turn": "ALLEEN rechts afslaan {indirect}", + "only_u_turn": "ALLEEN omkeren {indirect}", + "only_straight_on": "ALLEEN rechtdoor gaan {indirect}", + "allowed_left_turn": "Links afslaan toegestaan {indirect}", + "allowed_right_turn": "Rechts afslaan toegestaan {indirect}", + "allowed_u_turn": "Omkeren toegestaan {indirect}", + "allowed_straight_on": "Rechtdoor gaan toegestaan {indirect}" + }, + "from": "VAN", + "via": "VIA", + "to": "NAAR", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Klik om een {from}-segment te selecteren", + "select_from_name": "Klik om {from} {fromName} te selecteren", + "toggle": "Klik voor \"{turn}\"" + } + }, "undo": { "tooltip": "Ongedaan maken: {action}", "nothing": "Niets om ongedaan te maken." @@ -366,6 +410,7 @@ "key": "H", "title": "Geschiedenis", "selected": "{n} geselecteerd", + "no_history": "Geen geschiedenis (nieuw object)", "version": "Versie", "last_edit": "Laatste aanpassing", "edited_by": "Aangepast door", @@ -465,9 +510,9 @@ "switch": "Selecteer terug deze achtergrond", "custom": "Aangepast", "custom_button": "Tegel-URL-sjabloon aanpassen", - "custom_prompt": "Geef een tegel-URL-sjabloon op. Geldige placeholders zijn:\n - {zoom}/{z}, {x}, {y} voor het Z/X/Y-schema\n - {ty} voor omgekeerde Y-coördinaten in TMS-stijl\n - {u} voor het quadtile-schema\n - {switch:a,b,c} voor DNS-server-multiplexing\n\nVoorbeeld:\n{example}", + "custom_prompt": "Geef een tegel-URL-sjabloon op. Geldige placeholders zijn:\n - {zoom}/{z}, {x}, {y} voor het Z/X/Y-schema\n - {-y} of {ty} voor omgekeerde Y-coördinaten in TMS-stijl\n - {u} voor het quadtile-schema\n - {switch:a,b,c} voor DNS-server-multiplexing\n\nVoorbeeld:\n{example}", "overlays": "Lagen", - "imagery_source_faq": "Beeldopnameinfo / Rapporteer een probleem", + "imagery_source_faq": "Beeldopname-info / Meld een probleem", "reset": "Standaard herstellen", "display_options": "Weergaveopties", "brightness": "Helderheid", @@ -577,7 +622,7 @@ "status_code": "Server gaf volgende statuscode terug: {code}", "unknown_error_details": "Controleer of je bent verbonden met het internet.", "uploading": "Bezig met uploaden naar OpenStreetMap …", - "conflict_progress": "Controleren op conflicten: {num} van {total}", + "conflict_progress": "Bezig met controleren op conflicten: {num} van {total}", "unsaved_changes": "Je hebt niet-opgeslagen aanpassingen", "conflict": { "header": "Los bewerkingsconflicten op", @@ -603,15 +648,20 @@ } }, "success": { - "edited_osm": "OSM aangepast!", "just_edited": "Je hebt OpenStreetMap bewerkt!", - "view_on_osm": "Bekijk op OSM", - "facebook": "Deel op Facebook", - "twitter": "Deel op Twitter", - "google": "Deel op Google+", - "help_html": "Je wijzigingen zouden binnen enkele minuten zichtbaar moeten zijn in de \"Standaard\"-laag. Het updaten van sommige soorten objecten kan langer duren. Andere lagen dan de \"Standaard\"-laag worden minder vaak bijgewerkt.", + "thank_you": "Bedankt om OpenStreetMap te verbeteren.", + "thank_you_location": "Bedankt om de kaart bij te werken bij {where}.", + "help_html": "Je wijzigingen zouden binnen enkele minuten zichtbaar moeten zijn in de \"Standaard\"-laag op openstreetmap.org. Het updaten van sommige soorten objecten kan langer duren. Andere kaarten op basis van OSM worden minder vaak bijgewerkt.", "help_link_text": "Meer hierover, in het Engels", - "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" + "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", + "view_on_osm": "Bekijk wijzigingen op OSM", + "changeset_id": "Je wijzigingenset is nummer {changeset_id}", + "like_osm": "Vind je OpenStreetMap leuk? Treed in contact met andere mappers:", + "more": "Meer", + "events": "Evenementen", + "languages": "Talen: {languages}", + "missing": "Mist er iets in deze lijst?", + "tell_us": "Vertel het ons!" }, "confirm": { "okay": "Oké", @@ -649,7 +699,7 @@ "untagged_area_tooltip": "Selecteer een objecttype dat beschrijft wat dit vlak is.", "untagged_relation": "Relatie zonder tags", "untagged_relation_tooltip": "Selecteer een objecttype dat beschrijft wat deze relatie is.", - "many_deletions": "Je verwijdert {n} objecten. Weet je zeker dat je dit wil doen? Dit zal ze verwijderen van de kaart die iedereen ziet op openstreetmap.org.", + "many_deletions": "Je verwijdert {n} objecten: {p} (knoop)punten, {l} lijnen, {a} vlakken en {r} relaties. Weet je zeker dat je dit wil doen? Dit zal ze verwijderen van de kaart die iedereen ziet op openstreetmap.org.", "tag_suggests_area": "De tag {tag} suggereert dat de lijn een vlak is, maar het is geen vlak", "deprecated_tags": "Afgeschafte tags: {tags}" }, @@ -783,7 +833,7 @@ "point_or_area_h": "Punten of vlakken?", "point_or_area": "Veel objecten kunnen worden gerepresenteerd worden als punt of vlak. Je voegt gebouwen en gebieden toe als vlakken wanneer dit mogelijk is.\n\nEr is geen internationale consensus over hoe bedrijven, voorzieningen en andere objecten binnen een gebouw gerepresenteerd moeten worden: op het vlak dat het gebouw voorsteld of als apart punt. Als je zoiets nieuw toevoegt, teken het dan als een punt binnen het gebouw. Als het object al in OpenStreetMap op het gebouw stond, verander het dan niet zomaar naar een apart punt.", "add_area_h": "Vlakken toevoegen", - "add_area_command": "Om een punt toe te voegen, klik je op de \"{area} **Vlak**\"-knop in de \nwerkbalk boven de kaart, of gebruik je de sneltoets `3`. De \nmuisaanwijzer verandert in een kruissymbool.", + "add_area_command": "Om een punt toe te voegen, klik je op de \"{area} **Vlak**\"-knop in de werkbalk boven de kaart, of gebruik je de sneltoets `3`. De muisaanwijzer verandert in een kruissymbool.", "add_area_draw": "Teken vervolgens de knooppunten van het vlak net zoals bij een lijn.", "add_area_finish": "Om een vlak te voltooien, klik je nogmaals op de laatste node of druk je op `{return}`.", "square_area_h": "Hoeken haaks maken", @@ -846,6 +896,44 @@ "using": "Om een GPS-track te gebruiken voor het bewerken, sleep je een bestand naar dit kaartbewerkingsprogramma. Als het herkend wordt, zal het getekend worden als een heldere paarse lijn. Open het \"{data} **Kaartgegevens**\"-paneel naast de kaart om je GPS-data aan of uit te zetten of er op in te zoomen.", "tracing": "De GPS-track wordt niet automatisch verzonden naar OpenStreetMap. De beste manier om het te gebruiken is als referentie voor nieuwe objecten die je toevoegt.", "upload": "Je kan ook [je GPS-data uploaden naar OpenStreetMap](https://www.openstreetmap.org/trace/create) zodat andere gebruikers hen ook kunnen gebruiken." + }, + "field": { + "restrictions": { + "title": "Hulp bij afslagbeperkingen", + "about": { + "title": "Over", + "about": "Dit veld laat je toe afslagbeperkingen te zien en bwerken. Het toont een schema van het geselecteerde kruispunt met aangesloten wegen dichtbij.", + "from_via_to": "Een afslagbeperking bestaat steeds uit één **VAN-weg**, één **NAAR-weg**, en ofwel één **VIA-knooppunt** of een of meer **VIA-wegen**.", + "maxdist": "De \"{distField}\"-schuifbalk bepaalt hoe ver er naar meer aangesloten wegen gezocht moet worden.", + "maxvia": "De \"{viaField}\"-schuifbalk bepaald hoeveel wegen er maximaal als VIA-weg voorgesteld worden. (Tip: zo weinig mogelijk VIA-wegen gebruiken is goed)" + }, + "inspecting": { + "title": "Bekijken", + "about": "Ga met je muis over een **VAN**-segment om eventuele afslagbeperkingen te zien. Elke mogelijke **NAAR**-bestemming wordt getoond met een gekleurde schaduw die aangeeft of er een beperking is.", + "from_shadow": "{fromShadow} **VAN-segment**", + "allow_shadow": "{allowShadow} **NAAR toegestaan**", + "restrict_shadow": "{restrictShadow} **NAAR verboden**", + "only_shadow": "{onlyShadow} **alleen NAAR hier**", + "restricted": "\"Verboden\" betekent dat er een afslagbeperking is, zoals \"niet links afslaan\".", + "only": "\"Alleen naar hier\" betekent dat een voertuig langs dat pad alleen die keuze mag maken, zoals \"alleen rechtdoor gaan\"." + }, + "modifying": { + "title": "Bewerken", + "about": "Om afslagbeperkingen te bewerken, klik je eerst op een **VAN**-segment om het te selecteren. De schaduw rond het geselecteerde segment beweegt, en alle mogelijke **NAAR**-bestemmingen verschijnen als afslagsymbooltjes.", + "indicators": "Klik herhaaldelijk op zo'n symbooltje om te wisselen tussen \"toegestaan\", \"verboden\" en \"alleen naar hier\".", + "allow_turn": "{allowTurn} **NAAR toegestaan**", + "restrict_turn": "{restrictTurn} **NAAR verboden**", + "only_turn": "{onlyTurn} **alleen NAAR hier**" + }, + "tips": { + "title": "Tips", + "simple": "**Verkies simpele afslagbeperkingen boven complexe.**", + "simple_example": "Vermijd bijvoorbeeld via-wegen te gebruiken als een beperking met enkel een knooppunt volstaat.", + "indirect": "**Sommige beperkingen tonen de tekst \"(indirect)\" en zijn lichter van kleur.**", + "indirect_example": "Deze beperkingen zijn er door een andere, nabijgelegen afslagbeperking. Bijvoorbeeld: een \"alleen rechtdoor gaan\"-beperking zal indirect een \"niet afslaan\"-beperking tot gevolg hebben voor alle andere mogelijke paden op het kruispunt.", + "indirect_noedit": "Je kan indirecte afslagbeperkingen niet bewerken. In de plaats daarvan moet je de expliciete afslagbeperking aanpassen." + } + } } }, "intro": { @@ -1026,7 +1114,7 @@ "title": "Vlakken", "add_playground": "*Vlakken* worden gebruikt om de grenzen van objecten als meren, gebouwen en woonwijken te tonen.{br}Ze kunnen ook gebruikt worden voor het meer gedetailleerd in kaart brengen van veel objecten die je anders als punten zou toevoegen. **Klik op de knop \"{button} Vlak\" om een nieuw vlak toe te voegen.**", "start_playground": "Laten we deze speeltuin intekenen als een vlak. Vlakken worden gemaakt door *knooppunten* aan hun omtrek te zetten. **Klik, of druk op de spatiebalk, om het eerste knooppunt in een van de hoeken van het speelplein te zetten.**", - "continue_playground": "Teken het vlak verder door meer knooppunten op de omtrek van de \nspeeltuin te zetten.{br}Tip: Je kan de {alt}-toets indrukken terwijl je \neen knooppunt zet om te vermijden dat ze verbinden met andere objecten. **Ga door met het tekenen van het vlak voor de speeltuin.**", + "continue_playground": "Teken het vlak verder door meer knooppunten op de omtrek van de speeltuin te zetten.{br}Tip: Je kan de {alt}-toets indrukken terwijl je een knooppunt zet om te vermijden dat ze verbinden met andere objecten. **Ga door met het tekenen van het vlak voor de speeltuin.**", "finish_playground": "Sluit het vlak door op enter te drukken, of opnieuw te klikken op het eerste of het laatste knooppunt. **Sluit het vlak voor de speeltuin.**", "search_playground": "**Zoek naar '{preset}'.**", "choose_playground": "**Kies {preset} uit de lijst.**", @@ -1091,8 +1179,8 @@ }, "startediting": { "title": "Begin met aanpassen", - "help": "Je bent nu klaar om OpenStreetMap te bewerken!{br}Je kan deze rondleiding steeds opnieuw volgen en meer documentatie bekijken door op de knop \"{button} Hulp\" te klikken of op de toets '{toets}' te drukken.", - "shortcuts": "Je kan een lijst met opdrachten samen met hun toetsenbordkoppelingen bekijken door op de toets '{toets}' te drukken.", + "help": "Je bent nu klaar om OpenStreetMap te bewerken!{br}Je kan deze rondleiding steeds opnieuw volgen en meer documentatie bekijken door op de knop \"{button} Hulp\" te klikken of op de toets '{key}' te drukken.", + "shortcuts": "Je kan een lijst met opdrachten samen met hun toetsenbordkoppelingen bekijken door op de toets '{key}' te drukken.", "save": "Sla je aanpassingen regelmatig op, bijvoorbeeld als je klaar bent in een bepaald gebied!", "start": "Karteer de wereld!" } @@ -1222,8 +1310,15 @@ "square_feet": "{quantity} sq ft", "square_miles": "{quantity} sq mi", "acres": "{quantity} ac", + "meters": "{quantity} m", "kilometers": "{quantity} km", "square_meters": "{quantity} m²", + "square_kilometers": "{quantity} km²", + "hectares": "{quantity} ha", + "area_pair": "{area1} ({area2})", + "arcdegrees": "{quantity}°", + "arcminutes": "{quantity}′", + "arcseconds": "{quantity}″", "north": "N", "south": "Z", "east": "O", @@ -1622,6 +1717,9 @@ "cycleway:right": "Rechterkant" } }, + "dance/style": { + "label": "Dansstijlen" + }, "date": { "label": "Datum" }, @@ -1684,9 +1782,15 @@ "forward": "Voorwaarts" } }, + "dispensing": { + "label": "Verkoopt geneesmiddelen op voorschrift" + }, "display": { "label": "Weergave" }, + "distance": { + "label": "Totale afstand" + }, "dock": { "label": "Type" }, @@ -1727,6 +1831,9 @@ "except": { "label": "Uitzonderingen" }, + "faces": { + "label": "Aantal kanten" + }, "fax": { "label": "Fax", "placeholder": "+31 42 123 4567" @@ -1838,6 +1945,39 @@ "label": "Lussen", "placeholder": "1, 2, 4 …" }, + "horse_dressage": { + "label": "Dressuur", + "options": { + "equestrian": "Ja", + "undefined": "Nee" + } + }, + "horse_riding": { + "label": "Paardrijden", + "options": { + "horse_riding": "Ja", + "undefined": "Nee" + } + }, + "horse_scale": { + "label": "Moeilijkheidsgraad paardrijden", + "options": { + "common": "Makkelijk: Geen problemen of moeilijkheden. (standaard)", + "critical": "Op het randje: Enkel toegankelijk voor ervaren ruiters en paarden. Grote obstakels. Bruggen moeten zorgvuldig geïnspecteerd worden.", + "dangerous": "Gevaarlijk: Enkel toegankelijk voor zeer ervaren ruiters en paarden en enkel onder gunstige weersomstandigheden. Afstijgen noodzakelijk.", + "demanding": "Pas op: oneffen weg, af en toe moeilijke stukken.", + "difficult": "Moeilijk: Smalle en onbeschutte weg. Er kunnen obstakels en nauwe passages zijn.", + "impossible": "Ondoordringbaar: Weg of brug niet toegankelijk voor paarden. Te smal, niet genoeg draagkracht, obstakels zoals ladders. Levensgevaar." + }, + "placeholder": "Moeilijk, Gevaarlijk …" + }, + "horse_stables": { + "label": "Rijstal", + "options": { + "stables": "Ja", + "undefined": "Nee" + } + }, "iata": { "label": "IATA" }, @@ -1857,6 +1997,9 @@ "indoor": { "label": "Binnen" }, + "industrial": { + "label": "Type" + }, "information": { "label": "Type" }, @@ -1977,6 +2120,10 @@ "label": "Snelheidsbeperking", "placeholder": "40, 50, 60 …" }, + "maxspeed/advisory": { + "label": "Adviessnelheid", + "placeholder": "40, 50, 70 …" + }, "maxstay": { "label": "Maximale verblijftijd" }, @@ -2130,7 +2277,6 @@ "placeholder": "1, 2, 3 …" }, "phone": { - "label": "Telefoonnummer", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2565,8 +2711,19 @@ "label": "Type", "placeholder": "Standaard" }, + "usage_rail": { + "label": "Gebruikstype", + "options": { + "branch": "Zijspoor", + "industrial": "Industrieel", + "main": "Hoofdlijn", + "military": "Militair", + "test": "Test", + "tourism": "Toerisme" + } + }, "vending": { - "label": "Soort waren" + "label": "Soorten waren" }, "visibility": { "label": "Zichtbaarheid", @@ -2661,6 +2818,10 @@ "name": "Reclamebord", "terms": "billboard" }, + "advertising/column": { + "name": "Reclamezuil", + "terms": "reclamepaal,advertentiezuil,advertentiepaal" + }, "aerialway": { "name": "Kabelbaan" }, @@ -2746,6 +2907,10 @@ "name": "Luchthaventerminal", "terms": "vertrekhal,aankomsthal,terminal,gate,vliegveld" }, + "allotments/plot": { + "name": "Tuintje in volkstuin", + "terms": "volkstuinplot,volkstuinlot,volkstuindeel" + }, "amenity": { "name": "Voorziening" }, @@ -2974,6 +3139,10 @@ "name": "Marktplaats", "terms": "groenten,vis,groentemarkt" }, + "amenity/monastery": { + "name": "Kloostergebied", + "terms": "abdijgebied" + }, "amenity/motorcycle_parking": { "name": "Motorfietsparking", "terms": "motorparking,motoparking,motostalling,motorstalling,motorfietsparking,motoren,moto's,parking voor motoren,parking voor moto's,parking voor motorfietsen" @@ -3115,7 +3284,8 @@ "terms": "stortbad,waterkraan,kraan" }, "amenity/smoking_area": { - "name": "Rookgebied" + "name": "Rookgebied", + "terms": "rookzone,kankerzone" }, "amenity/social_facility": { "name": "Sociale Faciliteit", @@ -3176,6 +3346,10 @@ "name": "Sigarettenautomaat", "terms": "sigarettenautomaat,tabakautomaat" }, + "amenity/vending_machine/coffee": { + "name": "Koffieautomaat", + "terms": "koffiezetmachine" + }, "amenity/vending_machine/condoms": { "name": "Condoomautomaat", "terms": "automaat" @@ -3184,6 +3358,14 @@ "name": "Drankautomaat", "terms": "drinken,waterautomaat,automaat" }, + "amenity/vending_machine/electronics": { + "name": "Electronica-automaat", + "terms": "automaat" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Souvenirsmuntautomaat", + "terms": "muntautomaat,iconische munt,muntvervormer" + }, "amenity/vending_machine/excrement_bags": { "name": "Strontzakjesautomaat", "terms": "poepzakjesautomaat,hondenstrontzakjesautomaat,hondenpoepzakjesautomaat,dierenstront,automaat" @@ -3192,6 +3374,18 @@ "name": "Menstruatieproductautomaat", "terms": "maandverbandautomaat,tamponautomaat,menstruatie,vrouwelijke hygiëne,vrouwencondooms" }, + "amenity/vending_machine/food": { + "name": "Voedselautomaat", + "terms": "etenautomaat,automaat met eten,voedingsautomaat" + }, + "amenity/vending_machine/fuel": { + "name": "Brandstofpomp", + "terms": "benzinepomp,dieselpomp,gaspomp,lng-pomp,cng-pomp,biodieselpomp" + }, + "amenity/vending_machine/ice_cream": { + "name": "IJs-automaat", + "terms": "friscoautomaat,ijsjesautomaat" + }, "amenity/vending_machine/news_papers": { "name": "krantenautomaat" }, @@ -3211,6 +3405,10 @@ "name": "Automaat voor tickets voor openbaar vervoer", "terms": "openbaarvervoerticketautomaat,ticketautomaat,automaat,OV-ticketautomaat,OV-kaartjesautomaat,tramkaartautomaat,buskaartautomaat,treinbiljetautomaat,biljetautomaat" }, + "amenity/vending_machine/stamps": { + "name": "Postzegelautomaat", + "terms": "postautomaat,zegelautomaat" + }, "amenity/vending_machine/sweets": { "name": "Snackautomaat", "terms": "etenautomaat,automaat" @@ -3283,6 +3481,10 @@ "name": "Valtoren", "terms": "valattractie,grote val" }, + "attraction/maze": { + "name": "Doolhof", + "terms": "labyrint" + }, "attraction/pirate_ship": { "name": "Piratenschip", "terms": "piratenboot" @@ -3351,7 +3553,8 @@ "terms": "heg,haag" }, "barrier/kerb": { - "name": "Stoeprand" + "name": "Stoeprand", + "terms": "trottoirband,boordsteen,borduur" }, "barrier/kissing_gate": { "name": "Voetgangershek", @@ -3442,6 +3645,14 @@ "building/entrance": { "name": "Ingang/Uitgang" }, + "building/farm": { + "name": "Boerderijhuis", + "terms": "gebouw van boerderij,boerderijgebouw" + }, + "building/farm_auxiliary": { + "name": "Boerderijgebouw", + "terms": "gebouw van boerderij" + }, "building/garage": { "name": "Garage (privéstalling voor voertuigen)", "terms": "autogarage" @@ -3499,7 +3710,8 @@ "terms": "afdak" }, "building/ruins": { - "name": "Gebouwruïnes" + "name": "Gebouwruïnes", + "terms": "ruïnes,ingestort gebouw,vervallen gebouw" }, "building/school": { "name": "Schoolgebouw", @@ -3509,7 +3721,8 @@ "name": "Niet gebruiken – niet-gestandardiseerde tag" }, "building/service": { - "name": "Klein machinegebouw (pomp, onderstation …)" + "name": "Klein machinegebouw (pomp, onderstation …)", + "terms": "dienstgebouw,machinegebouw,machinekamer" }, "building/shed": { "name": "Schuurtje", @@ -3520,7 +3733,8 @@ "terms": "dieren,paarden,vee,stalling" }, "building/stadium": { - "name": "Stadiongebouw" + "name": "Stadiongebouw", + "terms": "stadiumgebouw" }, "building/static_caravan": { "name": "Stacaravan", @@ -3789,7 +4003,8 @@ "name": "Toegang voor hulpdiensten: privé" }, "emergency/water_tank": { - "name": "Noodwatertank" + "name": "Noodwatertank", + "terms": "watertank,wateropslag,noodwateropslag,reservoir,noodreservoir" }, "emergency/yes": { "name": "Toegang voor hulpdiensten: ja" @@ -3890,6 +4105,10 @@ "name": "Palliatievezorgcentrum", "terms": "hospice,hospitium,terminale zorg,terminaal,ongeneeslijk ziek,terminaal ziek,hospicezorg,palliatieve zorg,palliatievezorgeenheid" }, + "healthcare/laboratory": { + "name": "Medisch laboratorium", + "terms": "laboratorium" + }, "healthcare/midwife": { "name": "Verloskundige", "terms": "vroedkundige,vroedvrouw" @@ -3991,6 +4210,10 @@ "name": "Verbindingsweg van autosnelweg", "terms": "autostrade,snelweg,autosnelweg,link,invoegstrook,afslag" }, + "highway/passing_place": { + "name": "Passeerplaats", + "terms": "uitwijkplaats,kruisplaats" + }, "highway/path": { "name": "Pad", "terms": "wandelpad,fietspad,gemengd wandelpad en fietspad,hikepad,fietsoversteekplaats" @@ -4215,7 +4438,8 @@ "terms": "bos,woud,bomen,boom" }, "landuse/garages": { - "name": "Garages (privéstalling voor voertuigen)" + "name": "Garages (privéstalling voor voertuigen)", + "terms": "autogarage" }, "landuse/grass": { "name": "Grasland", @@ -4344,7 +4568,12 @@ "terms": "casino,slot machine,slots,gokken,slotmachine" }, "leisure/amusement_arcade": { - "name": "Speelhal" + "name": "Speelhal", + "terms": "lunapark" + }, + "leisure/beach_resort": { + "name": "Strandoord", + "terms": "strandresort,strandhotel" }, "leisure/bird_hide": { "name": "Vogelkijkscherm of -hut", @@ -4362,6 +4591,10 @@ "name": "Danszaal", "terms": "ballroom,jive,swing,tango,wals" }, + "leisure/dancing_school": { + "name": "Dansschool", + "terms": "dansonderwijs,dansconservatorium,conservatorium" + }, "leisure/dog_park": { "name": "Hondenpark", "terms": "losloopgebied voor honden" @@ -4455,6 +4688,10 @@ "leisure/nature_reserve": { "name": "Natuurreservaat" }, + "leisure/outdoor_seating": { + "name": "Terras (horeca)", + "terms": "buiten zitten,buitenzitjes,buitenstoeltjes,buitenterras,horecaterras" + }, "leisure/park": { "name": "Park", "terms": "park" @@ -4577,6 +4814,10 @@ "name": "Horizontale mijn- of grotingang", "terms": "ingang,ondergronds,grot,mijn,adit" }, + "man_made/antenna": { + "name": "Antenne", + "terms": "zender,ontvanger,radio" + }, "man_made/breakwater": { "name": "Golfbreker", "terms": "golven,havenbescherming,kustbescherming,stortsteengolfbreker,caissongolfbreker,drijvende golfbreker,palengolfbreker,havengolfbreker,strekdammen" @@ -4627,6 +4868,10 @@ "man_made/observation": { "name": "Uitkijktoren" }, + "man_made/observatory": { + "name": "Observatorium", + "terms": "sterrenwacht,astronomisch observatorium,meteorologisch observatorium" + }, "man_made/petroleum_well": { "name": "Oliebron", "terms": "olieput,gasbron" @@ -4742,10 +4987,18 @@ "natural/heath": { "name": "Heideveld" }, + "natural/mud": { + "name": "Modder", + "terms": "slijk,modderpoel,drassig gebied,moeras,drasland" + }, "natural/peak": { "name": "Top", "terms": "bergtop,heuveltop" }, + "natural/reef": { + "name": "Rif", + "terms": "ondiepte,koraalrif,zandbank" + }, "natural/ridge": { "name": "Bergkam", "terms": "kam,bergtop,top" @@ -5375,7 +5628,8 @@ "terms": "handelszaak" }, "shop/agrarian": { - "name": "Landbouwwinkel" + "name": "Landbouwbenodigdhedenwinkel", + "terms": "landbouwwinkel,landbouwzaak,landbouwerswinkel,landbouwerszaak,pesticidenwinkel,meststoffenwinkel,zadenwinkel,tractorwinkel,voerwinkel,veevoerwinkel,landbouwgereedschapswinkel,landbouwwerktuigenwinkel" }, "shop/alcohol": { "name": "Slijterij", @@ -5614,6 +5868,9 @@ "name": "Bouwmarkt", "terms": "bouwcentrum,bouwmaterialenspeciaalzaak" }, + "shop/health_food": { + "terms": "supervoedselwinkel,superfoodwinkel" + }, "shop/hearing_aids": { "name": "Hoorapparatenwinkel", "terms": "doof,slechthorend,oor,oren,hoorhulp" @@ -5728,6 +5985,9 @@ "name": "Dierenwinkel", "terms": "dierenzaak,dierenwinkel,huisdieren" }, + "shop/pet_grooming": { + "name": "Huisdierenverzorgingswinkel" + }, "shop/photo": { "name": "Fotowinkel" }, @@ -5935,6 +6195,10 @@ "name": "Themapark", "terms": "pretpark" }, + "tourism/trail_riding_station": { + "name": "Ruiterlogies", + "terms": "paardrijdhotel,ruiterhotel,paardrijdlogies,paardrijdaccomodatie,ruiteraccomodatie" + }, "tourism/viewpoint": { "name": "Uitzichtpunt", "terms": "zicht,uitkijkpunt" @@ -6008,19 +6272,23 @@ }, "type/restriction/no_u_turn": { "name": "Niet omkeren", - "terms": "geen U-bocht,U-bocht verboden,omkeren verboden,omdraaien verboden,verboden om te draaien,verboden om te keren,niet omdraaien,niet keren,verboden te keren,keren verboden" + "terms": "geen U-bocht,U-bocht verboden,omkeren verboden,omdraaien verboden,verboden om te draaien,verboden om te keren,niet omdraaien,niet keren,verboden te keren,keren verboden,niet keren,niet draaien" }, "type/restriction/only_left_turn": { - "name": "Enkel links afslaan", - "terms": "verplicht links afslaan,links afslaan verplicht,enkel links inslaan,verplicht links inslaan,links inslaan verplicht" + "name": "Alleen links afslaan", + "terms": "enkel links afslaan,verplicht links afslaan,links afslaan verplicht,enkel links inslaan,alleen links inslaan,verplicht links inslaan,links inslaan verplicht" }, "type/restriction/only_right_turn": { - "name": "Enkel rechts afslaan", - "terms": "verplicht rechts afslaan,rechts afslaan verplicht,enkel rechts inslaan,verplicht rechts inslaan,rechts inslaan verplicht" + "name": "Alleen rechts afslaan", + "terms": "enkel rechts afslaan,verplicht rechts afslaan,rechts afslaan verplicht,enkel rechts inslaan,alleen rechts inslaan,verplicht rechts inslaan,rechts inslaan verplicht" }, "type/restriction/only_straight_on": { - "name": "Enkel rechtdoor", - "terms": "rechtdoor,niet draaien,niet afslaan,niet inslaan,draaien verboden,afslaan verboden,draaien verboden" + "name": "Alleen rechtdoor", + "terms": "enkel rechtdoor,rechtdoor,niet draaien,niet afslaan,niet inslaan,draaien verboden,afslaan verboden,draaien verboden" + }, + "type/restriction/only_u_turn": { + "name": "Alleen omkeren", + "terms": "alleen U-bocht,U-bocht verplicht,omkeren verplicht,omdraaien verplicht,verplicht om te draaien,verplicht om te keren,enkel omdraaien,enkel omkeren,verplicht te keren,keren verplicht,enkel keren,alleen omdraaien,alleen draaien,alleen keren" }, "type/route": { "name": "Route" @@ -6181,7 +6449,7 @@ "attribution": { "text": "Gebruiksvoorwaarden & feedback" }, - "description": "Luchtfoto grenzen en opnamedatum. Labels verschijnen bij zoomniveau 14 en hoger.", + "description": "Beeldgrenzen en opnamedata. Labels verschijnen op zoomniveau 13 en hoger.", "name": "DigitalGlobe-premiumbeelden Vintage" }, "DigitalGlobe-Standard": { @@ -6195,21 +6463,21 @@ "attribution": { "text": "Gebruiksvoorwaarden & feedback" }, - "description": "Luchtfoto grenzen en opnamedatum. Labels verschijnen bij zoomniveau 14 en hoger.", + "description": "Beeldgrenzen en opnamedata. Labels verschijnen op zoomniveau 13 en hoger.", "name": "DigitalGlobe-premiumbeelden Vintage" }, "EsriWorldImagery": { "attribution": { "text": "Voorwaarden & Terugkoppeling" }, - "description": "Esri world imagery", + "description": "Esri world imagery.", "name": "Esri World Imagery" }, "EsriWorldImageryClarity": { "attribution": { "text": "Gebruiksvoorwaarden & feedback" }, - "description": "Esri archiefbeelden kunnen duidelijker en accurater zijn dan de standaard achtergrondbeelden.", + "description": "Esri-archiefbeelden kunnen duidelijker en accurater zijn dan de standaard achtergrondbeelden.", "name": "Esri World Imagery (Clarity) Beta" }, "MAPNIK": { @@ -6279,33 +6547,37 @@ "description": "Geel = Publiek domein kaartgegevens van de US Census. Rood = data niet gevonden in OpenStreetMap", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Wegen: Groene omlijning = ongeclassificeerd. Bruine omlijning = veldweg. Oppervlak: grind = lichtbruin gevuld, asfalt = zwart, bestraat = grijs, grond = wit, beton = blauw, gras = groen. Seizoensgebonden = witte balken", + "name": "U.S. Forest Roads-laag" + }, "Waymarked_Trails-Cycling": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap bijdragers, CC by-SA 3.0" + "text": "© waymarkedtrails.org, OpenStreetMap-bijdragers, CC BY-SA 3.0" }, "name": "Waymarked Trails: Fietsen" }, "Waymarked_Trails-Hiking": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap bijdragers, CC by-SA 3.0" + "text": "© waymarkedtrails.org, OpenStreetMap-bijdragers, CC BY-SA 3.0" }, "name": "Waymarked Trails: Wandelen" }, "Waymarked_Trails-MTB": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap bijdragers, CC by-SA 3.0" + "text": "© waymarkedtrails.org, OpenStreetMap-bijdragers, CC BY-SA 3.0" }, "name": "Waymarked Trails: Mountainbiken" }, "Waymarked_Trails-Skating": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap bijdragers, CC by-SA 3.0" + "text": "© waymarkedtrails.org, OpenStreetMap-bijdragers, CC BY-SA 3.0" }, "name": "Waymarked Trails: Inline skaten" }, "Waymarked_Trails-Winter_Sports": { "attribution": { - "text": "© waymarkedtrails.org, OpenStreetMap bijdragers, CC by-SA 3.0" + "text": "© waymarkedtrails.org, OpenStreetMap-bijdragers, CC BY-SA 3.0" }, "name": "Waymarked Trails: Wintersportpistes" }, @@ -6320,7 +6592,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Orthofotolaag voorzien door basemap.at. 'Opvolger' van beelden van geoimage.at.", + "description": "Orthofoto-laag voorzien door basemap.at. 'Opvolger' van geoimage.at.", "name": "basemap.at Orthofoto" }, "hike_n_bike": { @@ -6375,7 +6647,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Kaarttegels door Stamen Design, onder CC BY 3.0" + "text": "Kaarttegels van Stamen Design, onder CC BY 3.0. Gegevens van OpenStreetMap, onder ODbL" }, "name": "Stamen Terrein" }, @@ -6391,6 +6663,374 @@ }, "name": "Thunderforest Landschap" } + }, + "community": { + "cape-coast-youthmappers": { + "description": "Volg ons op Twitter: {url}" + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana op Facebook", + "description": "Facebook-groep voor mensen met interesse in OpenStreetMap." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana op Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "talk-gh": { + "name": "Talk-gh mailinglijst" + }, + "osm-mg-facebook": { + "name": "OpenStreetMap Madagascar-Facebookgroep", + "description": "Malagasi-Facebookgroep voor mensen geïnteresseerd in OpenStreetMap." + }, + "talk-mg": { + "name": "Talk-mg-mailinglijst", + "description": "Plek voor OpenStreetMap-bijdragers, -gemeenschappen en -gebruikers in Madagascar om te delen en voor overleg." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesh", + "description": "Verbeter OpenStreetMap in Bangladesh" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap India", + "description": "Verbeter OpenStreetMap in India", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "where": "Indian Institute of Management, Bangalore, India" + } + } + }, + "OSM-india-mailinglist": { + "name": "OpenStreetMap India Mailinglijst", + "description": "Talk-in is de officiële Mailinglijst voor de India" + }, + "OSM-india-twitter": { + "name": "OpenStreetMap India Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Free Software Hardware Movement – Facebook", + "description": "FSHM Facebook-pagina om op de hoogte te blijven van community-evenementen, -activiteiten" + }, + "OSM-India-Puducherry-Matrix": { + "name": "Free Software Hardware Movement – Matrix" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonesië", + "description": "Verbeter OpenStreetMap in Indonesië" + }, + "OSM-japan-facebook": { + "name": "OpenStreetMap Japan" + }, + "OSM-japan-mailinglist": { + "name": "OpenStreetMap Japan Mailinglijst", + "description": "Talk-ja is de officiële Mailinglijst voor Japan" + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap Japan Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "OSM-MY-forum": { + "name": "OpenStreetMap Maleisië Forum", + "description": "Officiële OpenStreetMap Maleisië Forum" + }, + "OSM-MY-matrix": { + "name": "OpenStreetMap Maleisië Riot-kanaal" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongolië", + "description": "Verbeter OpenStreetMap in Mongolia" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Myanmar", + "description": "Verbeter OpenStreetMap in Myanmar" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Nepal", + "description": "Verbeter OpenStreetMap in Nepal" + }, + "OSM-PH-facebook": { + "name": "Facebook" + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph Mailinglijst", + "description": "Talk-ph is de officiële Mailinglijst voor de Filipijnen" + }, + "OSM-PH-slack": { + "name": "Slack" + }, + "OSM-PH-telegram": { + "name": "Telegram", + "description": "OpenStreetMap Filipijnen op Telegram" + }, + "OSM-RU-forum": { + "name": "OpenStreetMap RU forum", + "description": "OpenStreetMap Rusland webforum" + }, + "OSM-RU-telegram": { + "name": "Telegram", + "description": "OpenStreetMap Rusland op Telegram" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka", + "description": "Verbeter OpenStreetMap in Sri Lanka" + }, + "OSM-TW-facebook": { + "name": "OpenStreetMap Taiwan", + "description": "Neem deel aan de OpenStreetMap Taiwan community op Facebook" + }, + "OSM-TW-mailinglist": { + "name": "OpenStreetMap Taiwan Mailinglijst", + "description": "Talk-tw is de officiële Mailinglijst voor Taiwan" + }, + "at-mailinglist": { + "name": "Talk-at Mailinglijst", + "description": "Talk-at is de officiële Mailinglijst voor Oostenrijk" + }, + "at-twitter": { + "name": "OpenStreetMap Oostenrijk Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "osm-at": { + "name": "OpenStreetMap Oostenrijk" + }, + "byosm": { + "name": "OpenStreetMap Wit-Rusland", + "description": "OpenStreetMap Wit-Rusland op Telegram" + }, + "be-facebook": { + "name": "OpenStreetMap BE", + "description": "Mappers en OpenStreetMap op Facebook in België" + }, + "be-forum": { + "name": "OpenStreetMap BE forum", + "description": "Webforum van OpenStreetMap in België" + }, + "be-irc": { + "name": "OpenStreetMap België IRC", + "description": "Kom erbij op #osmbe op irc.oftc.net (poort 6667)", + "extendedDescription": "Kom erbij op #osmbe op irc.oftc.net (poort 6667), het kanaal is gekoppeld aan de Matrix-chatruimte" + }, + "be-mailinglist": { + "name": "Talk-be-mailinglijst", + "description": "Talk-be is de officiële mailinglijst voor de Belgische OpenStreetMapgemeenschap" + }, + "be-matrix": { + "name": "OpenStreetMap BE Matrix-kanaal", + "description": "Alle mappers zijn welkom!" + }, + "be-meetup": { + "name": "OpenStreetMap België Meetup", + "description": "Bijeenkomsten in het echte leven van iedereen die geïnteresseerd is in OpenStreetMap", + "extendedDescription": "Fysieke bijeenkomsten zijn fantastisch om andere mappers te leren kennen, hen vragen te stellen, en veel bij te leren. In het bijzonder zijn nieuwe bijdragers van harte welkom!" + }, + "be-twitter": { + "name": "OpenStreetMap België Twitter" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz Mailinglijst", + "description": "Talk-cz is de officiële Mailinglijst voor Tsjechië" + }, + "fr-facebook": { + "name": "OpenStreetMap Frankrijk Facebook-pagina", + "description": "OpenStreetMap Frankrijk Facebook-pagina" + }, + "fr-twitter": { + "name": "OpenStreetMap Frankrijk op Twitter", + "description": "OpenStreetMap Frankrijk op Twitter: {url}" + }, + "de-irc": { + "name": "OpenStreetMap Duitsland IRC" + }, + "de-mailinglist": { + "name": "Talk-de Mailinglijst", + "description": "Talk-de is de officiële Mailinglijst voor Duitsland" + }, + "osm-de": { + "name": "OpenStreetMap Duitsland", + "description": "Het platform voor informatie over OpenStreetMap in Duitsland" + }, + "OSM-Rome-meetup": { + "name": "Incontro Mappatori Romani", + "description": "Verbeter OpenStreetMap in Rome" + }, + "talk-it-lazio": { + "name": "OpenStreetMap IT Lazio", + "extendedDescription": "Mailinglijst voor Rome en Lazio." + }, + "OSM-PL-facebook-group": { + "name": "OpenStreetMap Polen Facebook-groep" + }, + "OSM-ES-telegram": { + "name": "Telegram", + "description": "OpenStreetMap Spanje op Telegram" + }, + "se-facebook": { + "name": "OpenStreetMap Zweden Facebook-pagina", + "description": "OpenStreetMap Zweden op Facebook" + }, + "se-twitter": { + "name": "OpenStreetMap Zweden op Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "OSM-CA-Slack": { + "name": "Slack" + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area OpenStreetMappers", + "description": "Verbeter OpenStreetMap in de Bay Area" + }, + "Central-Pennsylvania-OSM": { + "name": "OpenStreetMap Central Pennsylvania" + }, + "Code-for-San-Jose-Slack": { + "name": "Slack" + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM" + }, + "GeoPhilly": { + "name": "GeoPhilly" + }, + "MapMinnesota": { + "name": "MapMinnesota" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC", + "description": "Verbeter OpenStreetMap in District Columbia" + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Verbeter OpenStreetMap in de regio Cleveland" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Central Salish Sea" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "De OpenStreetMap-gebruikersgroep voor Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado" + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Zuid Californië" + }, + "OSM-South-Bay": { + "name": "OSM South Bay" + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Tampa Bay" + }, + "OSM-US-Slack": { + "name": "Slack" + }, + "OSM-US": { + "name": "OpenStreetMap Verenigde Staten" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming" + }, + "PHXGeo-meetup": { + "name": "PHXGeo Meetup" + }, + "PHXGeo-twitter": { + "name": "PHXGeo Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "Western-Slope-facebook": { + "name": "Facebook" + }, + "Maptime-Australia-Slack": { + "name": "Slack" + }, + "talk-au": { + "name": "Talk-au Mailinglijst" + }, + "OSM-AR-facebook": { + "name": "Facebook", + "description": "Neem deel aan de OpenStreetMap Argentinië community op Facebook" + }, + "OSM-AR-mailinglist": { + "name": "Talk-ar Mailinglijst" + }, + "OSM-AR-telegram": { + "name": "Telegram", + "description": "OpenStreetMap Argentinië op Telegram" + }, + "OSM-AR-twitter": { + "name": "OpenStreetMap Argentinië Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "Bahia-telegram": { + "name": "Telegram", + "description": "OpenStreetMap Bahia op Telegram" + }, + "OSM-br-mailinglist": { + "name": "Talk-br Mailinglijst", + "description": "Talk-br is de officiële Mailinglijst voor Brazilië" + }, + "OSM-br-telegram": { + "name": "Telegram", + "description": "OpenStreetMap Brazilië op Telegram" + }, + "OSM-br-twitter": { + "name": "OpenStreetMap Brazilië Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "OSM-CL-facebook": { + "name": "Facebook", + "description": "Neem deel aan de OpenStreetMap Chili community op Facebook" + }, + "OSM-CL-mailinglist": { + "name": "Talk-cl Mailinglijst", + "description": "Talk-cl is de officiële Mailinglijst voor Chili" + }, + "OSM-CL-telegram": { + "name": "Telegram", + "description": "OpenStreetMap Chili op Telegram" + }, + "OSM-CL-twitter": { + "name": "OpenStreetMap Chili Twitter", + "description": "Volg ons op Twitter: {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogota" + }, + "OSM-CO-facebook": { + "name": "OpenStreetMap Colombia Facebook", + "description": "Wordt lid van de OpenStreetMap Colombia community op Facebook" + }, + "OSM-CO-twitter": { + "name": "OpenStreetMap Colombia Twitter", + "description": "Volg ons op Twitter at {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Colombia" + }, + "OSM-Reddit": { + "name": "OpenStreetMap op Reddit", + "description": "Op /r/openstreetmap/ vind een levendige dialoog plaats over OpenStreetMap. Hier kun je alles vragen!" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/no.json b/vendor/assets/iD/iD/locales/no.json index 180409044..47ca0725d 100644 --- a/vendor/assets/iD/iD/locales/no.json +++ b/vendor/assets/iD/iD/locales/no.json @@ -1,5 +1,10 @@ { "no": { + "icons": { + "information": "info", + "remove": "fjern", + "undo": "angre" + }, "modes": { "add_area": { "title": "Område", @@ -34,7 +39,7 @@ "add": { "annotation": { "point": "La til et punkt.", - "vertex": "La til et punkt til veien.", + "vertex": "La til et punkt til linjen.", "relation": "La til en relasjon." } }, @@ -110,7 +115,7 @@ }, "annotation": { "point": "Slettet et punkt.", - "vertex": "Slett en node fra en vei.", + "vertex": "Slettet et punkt fra en linje.", "line": "Slettet en linje.", "area": "Slettet et område.", "relation": "Slettet en relasjon.", @@ -141,10 +146,10 @@ }, "connect": { "annotation": { - "point": "Koblet en vei til et punkt.", - "vertex": "Koblet en vei til en annen.", - "line": "Koblet en vei til en linje.", - "area": "Koblet en vei til et område." + "point": "Koblet en linje til et punkt.", + "vertex": "Koblet en linje til en annen.", + "line": "Koblet en linje til en annen linje.", + "area": "Koblet en linje til et område." } }, "disconnect": { @@ -163,7 +168,6 @@ "annotation": "{n} kartegenskaper er slått sammen.", "not_eligible": "Disse kartegenskapene kan ikke bli slått sammen.", "not_adjacent": "Disse objektene kan ikke bli slått sammen da endepunktene ikke er sammenkoblet.", - "restriction": "Disse kartegenskapene kan ikke bli slått sammen fordi minst en er et medlem av en \"{relation}\" relasjon.", "incomplete_relation": "Disse kartegenskapene kan ikke bli slått sammen fordi minst én av dem er ikke ferdig nedlastet.", "conflicting_tags": "Disse kartegenskapene kan ikke bli slått sammen fordi noen av deres merker har konfliktskapende verdier." }, @@ -176,7 +180,7 @@ "key": "M", "annotation": { "point": "Flyttet et punkt.", - "vertex": "Flyttet en node i en vei.", + "vertex": "Flyttet et punkt på en linje.", "line": "Flyttet en linje.", "area": "Flyttet et område.", "multiple": "Flyttet flere kartegenskaper." @@ -291,6 +295,20 @@ } } }, + "restriction": { + "controls": { + "distance": "Distanse", + "via": "Via" + }, + "help": { + "from": "FRA", + "via": "VIA", + "to": "TIL", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}" + } + }, "undo": { "tooltip": "Angre: {action}", "nothing": "Ingen ting å gjøre." @@ -331,6 +349,7 @@ "save": "Last opp", "cancel": "Avbryt", "changes": "{count} endringer", + "download_changes": "Last ned osmChange-fil", "warnings": "Advarsler", "modified": "Endret", "deleted": "Slettet", @@ -361,6 +380,7 @@ "key": "H", "title": "Historik", "selected": "{n} valgt", + "no_history": "Ingen Historikk (Ny Egenskap)", "version": "Versjon", "last_edit": "Siste endring", "edited_by": "Endret av", @@ -378,6 +398,7 @@ "title": "Måling", "selected": "{n} valgt", "geometry": "Geometri", + "closed_line": "lukket linje", "length": "Lengde", "area": "Område", "location": "Sted", @@ -439,7 +460,7 @@ "add": "Legg til", "none": "Ingen", "node": "Node", - "way": "Vei", + "way": "Linje", "relation": "Relasjon", "location": "Sted", "add_fields": "Legg til felt:" @@ -575,13 +596,7 @@ } }, "success": { - "edited_osm": "Redigert OSM!", "just_edited": "Du har akkurat endret OpenStreetMap!", - "view_on_osm": "Vis på OSM", - "facebook": "Del på Facebook", - "twitter": "Del på Twitter", - "google": "Del på Google+", - "help_html": "Endringene dine burde vises i \"standard\"-laget om et par minutter. Andre lag, og visse kartegenskaper, kan ta litt lengre tid.", "help_link_text": "Detaljer" }, "confirm": { @@ -652,7 +667,59 @@ }, "overview": { "title": "Oversikt", - "navigation_h": "Navigasjon" + "navigation_h": "Navigasjon", + "nodes_ways": "I OpenStreetMap kaller vi av og til punkter for *noder*, og linjer og områder for *veier*." + }, + "editing": { + "save_h": "Lagre", + "upload_h": "Last opp", + "keyboard_h": "Tastatursnarveier" + }, + "points": { + "title": "Punkter", + "add_point_h": "Legge til Punkter", + "move_point_h": "Flytte Punkter", + "delete_point_h": "Slette Punkter" + }, + "lines": { + "title": "Linjer", + "add_line_h": "Legge til Linjer", + "modify_line_h": "Endre Linjer", + "connect_line_h": "Koble sammen Linjer", + "disconnect_line_h": "Koble Linjer fra Hverandre", + "move_line_h": "Flytte Linjer", + "delete_line_h": "Slette Linjer" + }, + "areas": { + "title": "Områder", + "point_or_area_h": "Punkter eller Områder?", + "add_area_h": "Legge til Områder", + "square_area_h": "Rette ut Vinkler", + "modify_area_h": "Endre Områder", + "delete_area_h": "Slette Områder" + }, + "relations": { + "title": "Relasjoner", + "edit_relation_h": "Endre Relasjoner", + "relation_types_h": "Typer Relasjoner", + "multipolygon_h": "Multipolygoner", + "turn_restriction_h": "Sving-begrensing", + "route_h": "Ruter", + "boundary_h": "Grenser" + }, + "gps": { + "title": "GPS-spor", + "using_h": "Bruke GPS-spor" + }, + "field": { + "restrictions": { + "about": { + "title": "Om" + }, + "tips": { + "title": "Tips" + } + } } }, "intro": { @@ -919,6 +986,15 @@ "category-landuse": { "name": "Arealbrukrelaterte egenskaper" }, + "category-natural-area": { + "name": "Naturrelatert" + }, + "category-natural-line": { + "name": "Naturrelatert" + }, + "category-natural-point": { + "name": "Naturrelatert" + }, "category-path": { "name": "Stirelaterte egenskaper" }, @@ -986,6 +1062,7 @@ "label": "Adresse", "placeholders": { "city": "By", + "city!vn": "By/Tettsted", "conscriptionnumber": "123", "country": "Land", "district": "Distrikt", @@ -1044,9 +1121,21 @@ "aeroway": { "label": "Type" }, + "agrarian": { + "label": "Produkter" + }, "amenity": { "label": "Type" }, + "animal_boarding": { + "label": "For Dyr" + }, + "animal_breeding": { + "label": "For Dyr" + }, + "animal_shelter": { + "label": "For Dyr" + }, "area/highway": { "label": "Type" }, @@ -1101,6 +1190,10 @@ "building_area": { "label": "Bygning" }, + "cables": { + "label": "Kabler", + "placeholder": "1, 2, 3..." + }, "camera/direction": { "label": "Retning (Grader med klokken)", "placeholder": "45, 90, 180, 270" @@ -1108,19 +1201,31 @@ "camera/type": { "label": "Kameratype", "options": { - "fixed": "Fikset" + "dome": "Kuppel", + "fixed": "Fikset", + "panning": "Panorerende" } }, "capacity": { "label": "Kapasitet", "placeholder": "50, 100, 200..." }, + "clothes": { + "label": "Klær" + }, "collection_times": { "label": "Hentetider" }, + "comment": { + "label": "Kommentar til endringssettet" + }, "construction": { "label": "Type" }, + "contact/webcam": { + "label": "Webkamera-URL", + "placeholder": "http://eksempel.no/" + }, "country": { "label": "Land" }, @@ -1130,6 +1235,9 @@ "crossing": { "label": "Type" }, + "cycle_network": { + "label": "Nettverk" + }, "cycleway": { "label": "Sykkelfelter", "options": { @@ -1157,12 +1265,58 @@ "description": { "label": "Beskrivelse" }, + "devices": { + "placeholder": "1, 2, 3..." + }, + "direction": { + "placeholder": "45, 90, 180, 270" + }, + "direction_cardinal": { + "label": "Retning", + "options": { + "E": "Øst", + "ENE": "Øst-nordøst", + "ESE": "Øst-sørøst", + "N": "Nord", + "NE": "Nordøst", + "NNE": "Nord-nordøst", + "NNW": "Nord-nordvest", + "NW": "Nordvest", + "S": "Sør", + "SE": "Sørøst", + "SSE": "Sør-sørøst", + "SSW": "Sør-sørvest", + "SW": "Sørvest", + "W": "Vest", + "WNW": "Vest-nordvest", + "WSW": "Vest-sørvest" + } + }, + "direction_clock": { + "label": "Retning", + "options": { + "anticlockwise": "Mot klokken", + "clockwise": "Med klokken" + } + }, + "direction_vertex": { + "label": "Retning", + "options": { + "backward": "Bakover", + "both": "Begge / Alle", + "forward": "Fremover" + } + }, "dock": { "label": "Type" }, "drive_through": { "label": "Gjennomkjøring" }, + "duration": { + "label": "Varighet", + "placeholder": "00:00" + }, "electrified": { "label": "Elektrifisering", "options": { @@ -1174,6 +1328,10 @@ "elevation": { "label": "Høyde over havet" }, + "email": { + "label": "E-post", + "placeholder": "eksempel@eksempel.no" + }, "emergency": { "label": "Nød" }, @@ -1233,6 +1391,9 @@ "handrail": { "label": "Gelender" }, + "hashtags": { + "placeholder": "#eksempel" + }, "height": { "label": "Høyde (meter)" }, @@ -1245,6 +1406,23 @@ "hoops": { "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "options": { + "equestrian": "Ja", + "undefined": "Nei" + } + }, + "horse_riding": { + "label": "Hesteridning", + "options": { + "horse_riding": "Ja" + } + }, + "horse_stables": { + "options": { + "stables": "Ja" + } + }, "iata": { "label": "IATA" }, @@ -1471,7 +1649,6 @@ "label": "Betalingstyper" }, "phone": { - "label": "Telefon", "placeholder": "+47 22 12 34 56" }, "piste/difficulty": { @@ -1508,6 +1685,11 @@ "route_master": { "label": "Type" }, + "second_hand": { + "options": { + "yes": "Ja" + } + }, "service": { "label": "Type" }, @@ -2917,15 +3099,6 @@ "type/restriction/no_u_turn": { "name": "Ingen U-sving" }, - "type/restriction/only_left_turn": { - "name": "Påbudt venstresving" - }, - "type/restriction/only_right_turn": { - "name": "Påbudt høyresving" - }, - "type/restriction/only_straight_on": { - "name": "Ikke tillatt å snu" - }, "type/route": { "name": "Rute" }, @@ -3003,6 +3176,126 @@ "attribution": { "text": "Vilkår og tilbakemelding" } + }, + "osm-gps": { + "attribution": { + "text": "© OpenStreetMap bidragsytere" + } + } + }, + "community": { + "cape-coast-youthmappers": { + "description": "Følg oss på Twitter: {url}" + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana på Twitter", + "description": "Følg oss på Twitter: {url}" + }, + "OSM-BGD-facebook": { + "description": "Forbedre OpenStreetMap i Bangladesh" + }, + "OSM-India-facebook": { + "description": "Forbedre OpenStreetMap i India" + }, + "OSM-india-twitter": { + "name": "OpenStreetMap India Twitter" + }, + "OSM-IDN-facebook": { + "description": "Forbedre OpenStreetMap i Indonesia" + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap Japan Twitter", + "description": "Hashtag på Twitter: {url}" + }, + "OSM-MNG-facebook": { + "description": "Forbedre OpenStreetMap i Mongolia" + }, + "OSM-MMR-facebook": { + "description": "Forbedre OpenStreetMap i Myanmar" + }, + "OSM-Nepal-facebook": { + "description": "Forbedre OpenStreetMap i Nepal" + }, + "OSM-LKA-facebook": { + "description": "Forbedre OpenStreetMap i Sri Lanka" + }, + "at-twitter": { + "name": "OpenStreetMap Østerrike Twitter", + "description": "OpenStreetMap Østerrike på Twitter: {url}" + }, + "osmgraz-twitter": { + "name": "OSM-samfunnet i Graz på Twitter", + "description": "OpenStreetMap-samfunnet i Graz på Twitter" + }, + "osm-at": { + "name": "OpenStreetMap Østerrike" + }, + "be-twitter": { + "name": "OpenStreetMap Belgia Twitter" + }, + "fr-twitter": { + "name": "OpenStreetMap Frankrike på Twitter", + "description": "OpenStreetMap Frankrike på Twitter: {url}" + }, + "de-berlin-twitter": { + "name": "OpenStreetMap Berlin Twitter", + "description": "Følg oss på Twitter: {url}" + }, + "it-twitter": { + "name": "OpenStreetMap Italia Twitter", + "description": "Følg oss på Twitter på {url}" + }, + "talk-it-lazio": { + "description": "Alle er velkomne! Registrer deg på {signupUrl}" + }, + "no-forum": { + "name": "OpenStreetMap Norge Nettforum", + "description": "OpenStreetMap Norge Nettforum" + }, + "no-irc": { + "name": "OpenStreetMap Norge på IRC", + "description": "Chatterom for kartleggere og OpenStreetMap-brukere, utviklere og entusiaster i Norge" + }, + "no-mailinglist": { + "name": "OpenStreetMap Norge e-postliste", + "description": "E-postliste for kartleggere og OpenStreetMap-brukere, utviklere og entusiaster i Norge" + }, + "se-twitter": { + "name": "OpenStreetMap Sverige på Twitter", + "description": "Følg oss på Twitter: {url}" + }, + "OSM-CA-Slack": { + "description": "Alle er velkomne! Registrer deg på {signupUrl}." + }, + "OSM-US-Slack": { + "description": "Alle er velkomne! Registrer deg på {signupUrl}" + }, + "PHXGeo-twitter": { + "description": "Følg oss på Twitter på {url}" + }, + "OSM-AR-twitter": { + "name": "OpenStreetMap Argentina Twitter", + "description": "Følg oss på Twitter på {url}" + }, + "OSM-br-twitter": { + "name": "OpenStreetMap Brasil Twitter", + "description": "Følg oss på Twitter på {url}" + }, + "OSM-CL-twitter": { + "name": "OpenStreetMap Chile Twitter", + "description": "Følg oss på Twitter på {url}" + }, + "OSM-CO-twitter": { + "name": "OpenStreetMap Colombia Twitter", + "description": "Følg oss på Twitter på {url}" + }, + "OSM-PE-twitter": { + "name": "OpenStreetMap Peru Twitter", + "description": "Følg oss på Twitter på {url}" + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter", + "description": "Følg oss på Twitter på {url}" } } } diff --git a/vendor/assets/iD/iD/locales/pl.json b/vendor/assets/iD/iD/locales/pl.json index 1a315e533..22814b9e2 100644 --- a/vendor/assets/iD/iD/locales/pl.json +++ b/vendor/assets/iD/iD/locales/pl.json @@ -1,5 +1,8 @@ { "pl": { + "icons": { + "undo": "Cofnij" + }, "modes": { "add_area": { "title": "Obszar", @@ -25,6 +28,9 @@ }, "draw_line": { "tail": "Kliknij, aby dodać więcej punktów do linii. Kliknij inne linie, aby je połączyć lub użyj dwukliku, aby zakończyć rysowanie." + }, + "drag_node": { + "connected_to_hidden": "Tego obiektu nie można edytować, ponieważ jest połączony z innym niewidocznym obiektem." } }, "operations": { @@ -160,7 +166,6 @@ "annotation": "Scal {n} obiektów.", "not_eligible": "Te obiekty nie mogą zostać scalone.", "not_adjacent": "Tych obiektów nie można scalić, ponieważ ich węzły nie są połączone.", - "restriction": "Tego obiektu nie można scalić, ponieważ przynajmniej jeden z nich jest członkiem relacji - \"{relation}\".", "incomplete_relation": "Tych obiektów nie można scalić, ponieważ przynajmniej jeden z nich nie został w pełni pobrany.", "conflicting_tags": "Tego obiektu nie można scalić, ponieważ ich tagi mają sprzeczne wartości." }, @@ -288,6 +293,17 @@ } } }, + "restriction": { + "controls": { + "distance": "Odległość", + "via": "Przez" + }, + "help": { + "from": "Z", + "via": "PRZEZ", + "to": "DO" + } + }, "undo": { "tooltip": "Cofnij: {action}", "nothing": "Nie ma nic do cofnięcia." @@ -363,6 +379,7 @@ "key": "H", "title": "Historia", "selected": "{n} wybrano", + "no_history": "Brak Historii (nowy obiekt)", "version": "Wersja", "last_edit": "Ostatnia edycja", "edited_by": "Edytowane przez", @@ -495,7 +512,7 @@ }, "feature": { "points": { - "description": "Punkty", + "description": "Punkty (POI)", "tooltip": "Użyteczne miejsca" }, "traffic_roads": { @@ -508,15 +525,15 @@ }, "paths": { "description": "Ścieżki", - "tooltip": "Chodniki, ścieżki dla pieszych, ścieżki rowerowe, etc." + "tooltip": "Chodniki, ścieżki dla pieszych, ścieżki rowerowe etc." }, "buildings": { "description": "Budynki", - "tooltip": "Budynki, wiaty, garaże, etc." + "tooltip": "Budynki, wiaty, garaże etc." }, "landuse": { "description": "Obiekty użytkowania terenów", - "tooltip": "Lasy, pola, parki, osiedla mieszkaniowe, obszary komercyjne, etc." + "tooltip": "Lasy, pola, parki, osiedla mieszkaniowe, obszary handlowe, biurowe etc." }, "boundaries": { "description": "Granice", @@ -524,19 +541,19 @@ }, "water": { "description": "Obiekty wodne", - "tooltip": "Rzeki, jeziora, stawy, dorzecza, etc." + "tooltip": "Rzeki, jeziora, stawy, dorzecza etc." }, "rail": { "description": "Obiekty kolejowe", "tooltip": "Tory kolejowe" }, "power": { - "description": "Obiekty związane z dystrybucją prądu elektrycznego.", - "tooltip": "Linie energetyczne, elektrownie, podstacje, etc." + "description": "Obiekty dystrybucji prądu elektrycznego", + "tooltip": "Linie energetyczne, elektrownie, podstacje etc." }, "past_future": { "description": "Przeszłość/przyszłość", - "tooltip": "Projektowane, w czasie budowy, opuszczone, wyburzone, etc." + "tooltip": "Obiekty projektowane, w czasie budowy, opuszczone, wyburzone etc." }, "others": { "description": "Inne", @@ -598,15 +615,19 @@ } }, "success": { - "edited_osm": "Zmiany zostały wprowadzone do OSM!", - "just_edited": "Właśnie wprowadziłeś zmiany w OpenStreetMap!", - "view_on_osm": "Wyświetl na OSM", - "facebook": "Podziel się na Facebooku", - "twitter": "Podziel się na Twitterze", - "google": "Podziel się na Google+", - "help_html": "Zmiany powinny pojawić się na warstwie podstawowej mapy w ciągu kilku minut. Inne warstwy mogą odświeżać się dłużej.", + "just_edited": "Właśnie zmieniłeś OpenStreetMap!", + "thank_you": "Dziękujemy za ulepszanie mapy.", + "thank_you_location": "Dziękujemy za ulepszanie mapy w: {where}.", + "help_html": "Zmiany powinny pojawić się na warstwie standardowej mapy w ciągu kilku minut. Inne warstwy mogą odświeżać się dłużej.", "help_link_text": "Więcej informacji", - "help_link_url": "http://wiki.openstreetmap.org/wiki/Pl:FAQ#Kiedy_wprowadzone_przeze_mnie_zmiany_poka.C5.BCa_si.C4.99_na_mapie.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/Pl:FAQ#Kiedy_wprowadzone_przeze_mnie_zmiany_poka.C5.BCa_si.C4.99_na_mapie.3F", + "view_on_osm": "Zobacz zmiany na OSM", + "changeset_id": "Twój zestaw zmian: #{changeset_id}", + "like_osm": "Podoba Ci się OpenStreetMap? Skontaktuj się z innymi mapującymi:", + "more": "Więcej", + "languages": "Języki: {languages}", + "missing": "Brakuje czegoś na tej liście?", + "tell_us": "Daj nam znać!" }, "confirm": { "okay": "OK", @@ -708,7 +729,8 @@ "save_h": "Zapisz", "upload_h": "Wyślij", "backups_h": "Automatyczne kopie zapasowe", - "keyboard_h": "Skróty klawiszowe" + "keyboard_h": "Skróty klawiszowe", + "keyboard": "Możesz zobaczyć listę skrótów klawiaturowych po naciśnięciu klawisza `?`." }, "feature_editor": { "title": "Edytor Obiektu", @@ -765,6 +787,13 @@ "using": "By użyć śladu GPS do mapowania, przeciągnij i upuść plik GPX na mapę edytora. Jeśli zostanie on rozpoznany, pojawi się na niej jako jasno-purpurowa linia. Kliknij na {data} **Dane mapy** po prawej stronie by włączyć, wyłączyć lub przybliżyć widok twojego śladu GPS.", "tracing": "Ślad GPS nie jest bezpośrednio zapisywany na serwerach OpenStreetMap - najlepszym sposobem na wykorzystanie go jest rysowanie mapy na jego podstawie.", "upload": "Możesz także wysłać [swój ślad GPS na serwery OpenStreetMap](https://www.openstreetmap.org/trace/create), pozwalając tym samym innym użytkownikom na korzystanie z niego." + }, + "field": { + "restrictions": { + "tips": { + "title": "Wskazówki" + } + } } }, "intro": { @@ -1251,7 +1280,7 @@ "placeholders": { "block_number": "Kwartał", "block_number!jp": "Kwartał", - "city": "Miejsc. (adres bez ulicy)", + "city": "Miejsc. (adres z ulicą)", "city!jp": "Miasto/Wieś/Okręg specjalny Tokio", "city!vn": "Miasto", "conscriptionnumber": "123", @@ -1267,7 +1296,7 @@ "housenumber!jp": "Nr budynku/działki", "neighbourhood": "Okręg", "neighbourhood!jp": "Chōme/Aza/Koaza", - "place": "Miejsc. (adres z ulicą)", + "place": "Miejsc. (adres bez ulicy)", "postcode": "Kod pocztowy", "province": "Prowincja/województwo", "province!jp": "Prefektura", @@ -1547,6 +1576,9 @@ "cycleway:right": "Prawa strona" } }, + "dance/style": { + "label": "Style taneczne" + }, "date": { "label": "Data" }, @@ -1615,6 +1647,9 @@ "display": { "label": "Typ wyświetlacza" }, + "distance": { + "label": "Całkowita Odległość" + }, "dock": { "label": "Typ" }, @@ -1655,6 +1690,9 @@ "except": { "label": "Wyjątki" }, + "faces": { + "label": "Liczba powierzchni" + }, "fax": { "label": "Faks", "placeholder": "+48 42 123 45 67" @@ -1760,12 +1798,37 @@ "label": "Rodzaj" }, "historic/civilization": { - "label": "Historyczna cywilizacja" + "label": "Cywilizacja historyczna" }, "hoops": { "label": "Kosz", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Dresaż", + "options": { + "equestrian": "Tak", + "undefined": "Nie" + } + }, + "horse_riding": { + "label": "Jeździectwo", + "options": { + "horse_riding": "Tak", + "undefined": "Nie" + } + }, + "horse_scale": { + "options": { + "common": "Łatwe: Brak przeszkód, problemów. (domyślnie)" + } + }, + "horse_stables": { + "options": { + "stables": "Tak", + "undefined": "Nie" + } + }, "iata": { "label": "IATA" }, @@ -1785,6 +1848,9 @@ "indoor": { "label": "Wnętrze" }, + "industrial": { + "label": "Typ" + }, "information": { "label": "Typ" }, @@ -1905,6 +1971,9 @@ "label": "Ograniczenie prędkości", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Maksymalny czas postoju" }, @@ -2058,7 +2127,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telefon", "placeholder": "+48 42 123 4567" }, "piste/difficulty": { @@ -2493,8 +2561,8 @@ "label": "Rodzaj", "placeholder": "Domyślny" }, - "vending": { - "label": "Rodzaje towarów" + "usage_rail": { + "label": "Sposób użytkowania" }, "visibility": { "label": "Widoczność", @@ -2589,6 +2657,10 @@ "name": "Billboard", "terms": "Reklama" }, + "advertising/column": { + "name": "Słup z ogłoszeniami/reklamami", + "terms": "reklamy,ogłoszenia" + }, "aerialway": { "name": "Wyciąg narciarski" }, @@ -2902,6 +2974,10 @@ "name": "Targowisko", "terms": "targowisko,targ,rynek,giełda" }, + "amenity/monastery": { + "name": "Teren klasztoru", + "terms": "klasztor" + }, "amenity/motorcycle_parking": { "name": "Parking dla motocyklów", "terms": "miejsce postojowe dla motocyklów" @@ -3106,6 +3182,10 @@ "name": "Automat z papierosami", "terms": "Automat z papierosami" }, + "amenity/vending_machine/coffee": { + "name": "Automat do sprzedaży kawy", + "terms": "automat do sprzedaży kawy, kawiarka" + }, "amenity/vending_machine/condoms": { "name": "Automat z prezerwatywami", "terms": "Automat z prezerwatywami" @@ -3114,6 +3194,14 @@ "name": "Automat z napojami", "terms": "Automat z napojami" }, + "amenity/vending_machine/electronics": { + "name": "Automat do sprzedaży urządzeń elektronicznych", + "terms": "automat do sprzedaży urządzeń elektronicznych, małe agd" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Automat do sprzedaży monet pamiątkowych", + "terms": "automat do sprzedaży monet pamiątkowych,moneta pamiątkowa" + }, "amenity/vending_machine/excrement_bags": { "name": "Dozownik z workami na psie odchody", "terms": "woreczki na psie odchody" @@ -3122,6 +3210,14 @@ "name": "Automat z produktami higieny kobiecej", "terms": "podpaski,tampony" }, + "amenity/vending_machine/food": { + "name": "Automat do sprzedaży jedzenia", + "terms": "automat do sprzedaży jedzenia,jedzenie,pożywienie" + }, + "amenity/vending_machine/ice_cream": { + "name": "Automat do sprzedaży lodów", + "terms": "automat do sprzedaży lodów,lody" + }, "amenity/vending_machine/news_papers": { "name": "Automat z gazetami" }, @@ -3141,6 +3237,10 @@ "name": "Automat z biletami komunikacji publicznej", "terms": "bilety komunikacji publicznej" }, + "amenity/vending_machine/stamps": { + "name": "Automat do sprzedaży znaczków pocztowych", + "terms": "automat do sprzedaży znaczków pocztowych, znaczki pocztowe" + }, "amenity/vending_machine/sweets": { "name": "Automat z przekąskami", "terms": "Automat z przekąskami" @@ -3213,6 +3313,10 @@ "name": "Wieża Swobodnego Spadania", "terms": "wieża spadania" }, + "attraction/maze": { + "name": "Labirynt", + "terms": "labirynt" + }, "attraction/pirate_ship": { "name": "Statek piracki", "terms": "statek piracki" @@ -3378,6 +3482,14 @@ "building/entrance": { "name": "Wejście/wyjście" }, + "building/farm": { + "name": "Gospodarstwo (mieszkalny)", + "terms": "Farma" + }, + "building/farm_auxiliary": { + "name": "Budynek gospodarczy", + "terms": "Gospodarstwo (niemieszkalny), Farma" + }, "building/garage": { "name": "Garaż", "terms": "garaż" @@ -3936,6 +4048,10 @@ "name": "Autostrada - wjazd/zjazd", "terms": "rampa,wjazd,wyjazd,zjazd" }, + "highway/passing_place": { + "name": "Mijanka", + "terms": "mijanka" + }, "highway/path": { "name": "Ścieżka/droga ", "terms": "ścieżka,dróżka" @@ -4157,14 +4273,14 @@ }, "landuse/forest": { "name": "Las", - "terms": "las,drzewa" + "terms": "las,puszcza" }, "landuse/garages": { "name": "Teren z garażami", "terms": "garaże,garażowisko,obszar garaży,wiaty" }, "landuse/grass": { - "name": "Trawa", + "name": "Trawa/trawnik", "terms": "trawa, trawnik, skwer,klomb" }, "landuse/greenfield": { @@ -4195,7 +4311,7 @@ "terms": "składowisko odpadów,śmieci" }, "landuse/meadow": { - "name": "Łąka", + "name": "Łąka/pastwisko", "terms": "łąka,pastwisko" }, "landuse/military": { @@ -4263,7 +4379,7 @@ "terms": "torowisko" }, "landuse/recreation_ground": { - "name": "Tereny rekreacyjne", + "name": "Park rekreacyjno-sportowy", "terms": "rekreacja,odpoczynek,sporty,zabawy" }, "landuse/religious": { @@ -4306,9 +4422,13 @@ "name": "Sala Taneczna", "terms": "dyskoteka" }, + "leisure/dancing_school": { + "name": "Szkoła tańca", + "terms": "szkoła tańca,tańce,tańczenie,taniec" + }, "leisure/dog_park": { - "name": "Park dla psów", - "terms": "psi park, wybieg dla psów" + "name": "Wybieg dla psów", + "terms": "psi park, wybieg dla psów, park dla psów" }, "leisure/firepit": { "name": "Miejsce na ognisko", @@ -4399,8 +4519,8 @@ "terms": "rezerwat" }, "leisure/park": { - "name": "Park", - "terms": "las,plac,teren rekreacyjny" + "name": "Park rekreacyjno-wypoczynkowy", + "terms": "park,wypoczynek,rekreacja,teren rekreacyjny" }, "leisure/picnic_table": { "name": "Stół piknikowy", @@ -4512,7 +4632,7 @@ }, "leisure/water_park": { "name": "Park wodny", - "terms": "aquapark, cieplice" + "terms": "aquapark, cieplice,akwapark" }, "line": { "name": "Linia", @@ -4577,6 +4697,10 @@ "name": "Wieża obserwacyjna", "terms": "wieża obserwacyjna" }, + "man_made/observatory": { + "name": "Obserwatorium", + "terms": "obserwatorium astronomiczne" + }, "man_made/petroleum_well": { "name": "Szyb naftowy", "terms": "kopalnia ropy" @@ -4694,13 +4818,17 @@ "terms": "lodowiec, lądolód, jęzor lodowcowy" }, "natural/grassland": { - "name": "Łąka", - "terms": "Teren trawiasty" + "name": "Łąka/sawanna/step/preria", + "terms": "teren trawiasty,sawanna,step,preria" }, "natural/heath": { "name": "Wrzosowisko", "terms": "Zdrowie, medycyna, szpital," }, + "natural/mud": { + "name": "Błoto", + "terms": "błotne" + }, "natural/peak": { "name": "Szczyt", "terms": "szczyt,wierzchołek" @@ -4762,8 +4890,8 @@ "terms": "bagna, bagno, mokradło, mokradła" }, "natural/wood": { - "name": "Las/puszcza", - "terms": "las,puszcza,zalesienie" + "name": "Drzewa", + "terms": "zadrzewienie,las,zalesienie" }, "noexit/yes": { "name": "Brak przejścia/przejazdu", @@ -5180,7 +5308,7 @@ "name": "Peron kolejowy" }, "railway/rail": { - "name": "Tor", + "name": "Tor kolejowy", "terms": "tory, torowisko" }, "railway/signal": { @@ -5893,16 +6021,20 @@ "terms": "zakaz,zawracanie" }, "type/restriction/only_left_turn": { - "name": "Nakaz skrętu w lewo", - "terms": "nakaz,lewoskręt" + "name": "Tylko skręt w lewo", + "terms": "tylko w lewo,nakaz skrętu w lewo" }, "type/restriction/only_right_turn": { - "name": "Nakaz skrętu w prawo", - "terms": "nakaz,prawoskręt" + "name": "Tylko skręt w prawo", + "terms": "tylko w prawo, nakaz skrętu w prawo" }, "type/restriction/only_straight_on": { - "name": "Nakaz jazdy prosto", - "terms": "zakaz,nakręcanie,wykręcanie,skręt" + "name": "Tylko jazda prosto", + "terms": "tylko prosto, nakaz jazdy na wprost" + }, + "type/restriction/only_u_turn": { + "name": "Tylko zawracanie", + "terms": "tylko zawracanie, nakaz zawracania" }, "type/route": { "name": "Trasa/linia", @@ -6057,7 +6189,7 @@ "attribution": { "text": "Warunki użytkowania i opinia" }, - "description": "Granice zdjęć i data ich wykonania. Opisy są widoczne na poziomie powiększenia 14 i wyższym.", + "description": "Granice zdjęć i data ich wykonania. Opisy są widoczne na poziomie powiększenia 13 i wyższym.", "name": "Datowanie zdjęć DigitalGlobe Premium " }, "DigitalGlobe-Standard": { @@ -6071,7 +6203,7 @@ "attribution": { "text": "Warunki użytkowania i opinia" }, - "description": "Granice zdjęć i data ich wykonania. Opisy są widoczne na poziomie powiększenia 14 i wyższym.", + "description": "Granice zdjęć i data ich wykonania. Opisy są widoczne na poziomie powiększenia 13 i wyższym.", "name": "Datowanie zdjęć DigitalGlobe Standard" }, "EsriWorldImagery": { @@ -6155,6 +6287,10 @@ "description": "Żółty = Dane public domain od US Census. Czerwony = Brak danych w OpenStreetMap", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Drogi: Zielone obramowanie = czwartorzędna. Brązowe obramowanie = polna/leśna. Nawierzchnia: żwir = jasno-brązowe wypełnienie, asfalt = czarny, twarda = szary, grunt = biały, beton = niebieski, trawa = zielony. Dostępna sezonowo = białe paski", + "name": "Nakładka z drogami z U.S. Forest" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, autorzy OpenStreetMap, CC by-SA 3.0" @@ -6189,7 +6325,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Mapa bazowa Austrii, oparta o dane rządowe.", + "description": "Mapa bazowa Austrii, na podstawie danych rządowych", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6251,7 +6387,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Kafelki mapowe Stamen Design, licencja CC BY 3.0" + "text": "Kafle mapy od Stamen Design, licencja CC BY 3.0. Dane z OpenStreetMap, licencja ODbL" }, "name": "Stamen - Teren" }, @@ -6267,6 +6403,299 @@ }, "name": "Thunderforest Krajobraz" } + }, + "community": { + "cape-coast-youthmappers": { + "description": "Obserwuj nas na Twitterze: {url}" + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana na Facebook'u" + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana na Twitter'rze", + "description": "Obserwuj nas na Twitterze: {url}" + }, + "talk-gh": { + "name": "Lista dyskusyjna Talk-gh", + "description": "Talk-gh to oficjalna mailingowa lista dyskusyjna społeczności OSM w Ghanie" + }, + "talk-mg": { + "name": "Lista dyskusyjna Talk-mg" + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesz" + }, + "OSM-india-mailinglist": { + "name": "Lista dyskusyjna OpenStreetMap Indie", + "description": "Talk-in to oficjalna mailingowa lista dyskusyjna społeczności OSM w Indiach" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonezja" + }, + "OSM-japan-mailinglist": { + "name": "Lista dyskusyjna OpenStreetMap Japonia" + }, + "OSM-japan-twitter": { + "description": "Hashtag na Twitterze: {url}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongolia" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Mjanma" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Nepal" + }, + "OSM-PH-mailinglist": { + "name": "Lista dyskusyjna Talk-ph", + "description": "Mailingowa lista dyskusyjna OpenStreetMap na Filipinach" + }, + "OSM-RU-forum": { + "name": "OpenStreetMap RU forum", + "description": "OpenStreetMap Rosja forum www" + }, + "OSM-RU-telegram": { + "name": "OpenStreetMap RU telegram" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka" + }, + "OSM-TW-mailinglist": { + "name": "Lista dyskusyjna OpenStreetMap Tajwan", + "description": "Talk-tw to oficjalna mailingowa lista dyskusyjna społeczności w kwestii Tajwanu" + }, + "at-mailinglist": { + "name": "Lista dyskusyjna Talk-at", + "description": "Talk-at to oficjalna mailingowa lista dyskusyjna austriackiej społeczności OSM" + }, + "osm-at": { + "name": "OpenStreetMap Austria" + }, + "byosm": { + "name": "OpenStreetMap Białoruś", + "description": "OpenStreetMap Białoruś - czat na Telegramie" + }, + "be-forum": { + "description": "Forum OpenStreetMap Belgium " + }, + "be-mailinglist": { + "name": "Lista dyskusyjna Talk-be", + "description": "Talk-be to oficjalna mailingowa lista dyskusyjna belgijskiej społeczności OSM " + }, + "talk-cz-mailinglist": { + "name": "Lista dyskusyjna Talk-cz", + "description": "Talk-cz to oficjalna mailingowa lista dyskusyjna czeskiej społeczności OSM" + }, + "dk-mailinglist": { + "name": "Lista dyskusyjna Talk-dk" + }, + "fr-mailinglist": { + "name": "Lista dyskusyjna Talk-fr", + "description": "Lista dyskusyjna Talk-fr" + }, + "de-berlin-mailinglist": { + "name": "Lista dyskusyjna dla Berlina" + }, + "de-berlin-twitter": { + "description": "Obserwuj nas na Twitterze: {url}" + }, + "de-forum": { + "name": "OpenStreetMap DE forum", + "description": "OpenStreetMap Niemcy - forum www" + }, + "de-irc": { + "name": "OpenStreetMap Niemcy - IRC", + "description": "Dołącza do #osm-de na irc.oftc.net (port 6667)" + }, + "de-mailinglist": { + "name": "Talk-de mailingowa lista dyskusyjna", + "description": "Talk-de to oficjalna lista dyskusyjna dla społeczności OSM w Niemczech" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "Lista dyskusyjna OWL" + }, + "osm-de": { + "name": "OpenStreetMap Niemcy" + }, + "it-mailinglist": { + "name": "Lista dyskusyjna Talk-it" + }, + "it-twitter": { + "description": "Obserwuj nas na Twitterze: {url}" + }, + "South-Tyrol-Mailing-List": { + "name": "Lista dyskusyjna OpenStreetMap dla Południowego Tyrolu" + }, + "no-mailinglist": { + "name": "Lista dyskusyjna OpenStreetMap Norwegia" + }, + "OSM-PL-facebook-group": { + "name": "OpenStreetMap Polska na Facebooku", + "description": "Mapujący i użytkownicy OpenStreetMap w Polsce" + }, + "OSM-PL-forum": { + "name": "Forum OpenStreetMap Polska", + "description": "Forum dyskusyjne polskiej społeczności OpenStreetMap" + }, + "OSM-ES-mailinglist": { + "name": "Lista dyskusyjna Talk-es" + }, + "osm-se": { + "name": "OpenStreetMap.se" + }, + "se-mailinglist": { + "name": "Lista dyskusyjna Talk-se" + }, + "se-twitter": { + "description": "Obserwuj nas na Twitterze: {url}" + }, + "gb-mailinglist": { + "name": "Lista dyskusyjna Talk-gb" + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver" + }, + "Central-Pennsylvania-OSM": { + "name": "OSM Centralna Pensylwania" + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM" + }, + "GeoPhilly": { + "name": "GeoPhilly" + }, + "MapMinnesota": { + "name": "MapMinnesota" + }, + "Maptime-ME-meetup": { + "name": "MaptimeME" + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado" + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Southern California" + }, + "OSM-South-Bay": { + "name": "OSM South Bay" + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Tampa Bay" + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack" + }, + "OSM-US": { + "name": "OpenStreetMap US" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming" + }, + "PHXGeo-meetup": { + "name": "PHXGeo Meetup" + }, + "PHXGeo-twitter": { + "name": "PHXGeo Twitter", + "description": "Obserwuj nas na Twitterze: {url}" + }, + "talk-au": { + "name": "Lista dyskusyjna Talk-au" + }, + "OSM-AR-mailinglist": { + "name": "Lista dyskusyjna Talk-ar" + }, + "OSM-AR-twitter": { + "description": "Obserwuj nas na Twitterze: {url}" + }, + "OSM-BO-mailinglist": { + "name": "Lista dyskusyjna Talk-bo" + }, + "OSM-br-mailinglist": { + "name": "Lista dyskusyjna Talk-br" + }, + "OSM-br-twitter": { + "description": "Obserwuj nas na Twitterze: {url}" + }, + "OSM-CL-mailinglist": { + "name": "Lista dyskusyjna Talk-cl" + }, + "OSM-CL-twitter": { + "description": "Obserwuj nas na Twitterze: {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá" + }, + "OSM-CO-mailinglist": { + "name": "Lista dyskusyjna Talk-co" + }, + "OSM-CO-twitter": { + "name": "OpenStreetMap KolumbiaTwitter", + "description": "Obserwuj nas na Twitterze: {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Kolumbia" + }, + "OSM-PE-facebook": { + "name": "OpenStreetMap Peru Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Lista dyskusyjna Talk-pe" + }, + "OSM-PE-telegram": { + "name": "OpenStreetMap Peru Telegram", + "description": "Dołącz do społeczności OpenStreetMap Peru na Telegramie" + }, + "OSM-PE-twitter": { + "name": "OpenStreetMap Peru Twitter", + "description": "Obserwuj nas na Twitterze: {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap Peru" + }, + "OSM-Facebook": { + "name": "OpenStreetMap na Facebook'u" + }, + "OSM-help": { + "name": "Pomoc OpenStreetMap" + }, + "OSM-Reddit": { + "name": "OpenStreetMap na Reddit", + "description": "/r/openstreetmap/ jest wspaniałym miejscem by dowiedzieć się więcej o OpenStreetMap." + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter", + "description": "Obserwuj nas na Twitterze: {url}" + }, + "OSMF": { + "name": "Fundacja OpenStreetMap ", + "events": { + "sotm2018": { + "name": "State of the Map 2018" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/pt-BR.json b/vendor/assets/iD/iD/locales/pt-BR.json index e650f5094..2a43f7ee4 100644 --- a/vendor/assets/iD/iD/locales/pt-BR.json +++ b/vendor/assets/iD/iD/locales/pt-BR.json @@ -1,5 +1,10 @@ { "pt-BR": { + "icons": { + "information": "informações", + "remove": "remover", + "undo": "desfazer" + }, "modes": { "add_area": { "title": "Área", @@ -145,7 +150,9 @@ "vertex": "Conectou uma linha a outra.", "line": "Conectou uma via a uma linha.", "area": "Conectou uma linha a uma área." - } + }, + "relation": "Esses recursos não podem ser conectados porque eles têm funções de relação conflitantes.", + "restriction": "Estes elementos não podem ser conectados porque isto danificaria uma relação \"{relation}\"." }, "disconnect": { "title": "Desconectar", @@ -163,7 +170,8 @@ "annotation": "Mesclar {n} elementos.", "not_eligible": "Esses elementos não podem ser mesclados.", "not_adjacent": "Estes elementos não podem ser mesclados porque suas extremidades não estão conectadas.", - "restriction": "Estes elementos não podem ser mesclados porque pelo menos um deles é membro de uma relação \"{relation}\".", + "restriction": "Esses recursos não podem ser mesclados porque isso danificaria uma relação \"{relation}\".", + "relation": "Esses recursos não podem ser mesclados porque possuem funções de relação conflitantes.", "incomplete_relation": "Estes elementos não podem ser mesclados porque pelo menos um deles não foi transferido completamente.", "conflicting_tags": "Estes elementos não podem ser mesclados porque algumas de suas etiquetas têm valores conflitantes." }, @@ -291,6 +299,42 @@ } } }, + "restriction": { + "controls": { + "distance": "Distância", + "distance_up_to": "Até {distance}", + "via": "Via", + "via_node_only": "Apenas nó", + "via_up_to_one": "Até 1 caminho", + "via_up_to_two": "Até 2 caminhos" + }, + "help": { + "indirect": "(indireto)", + "turn": { + "no_left_turn": "PROIBIDA conversão à esquerda {indirect}", + "no_right_turn": "PROIBIDA conversão à direita {indirect}", + "no_u_turn": "PROIBIDO retorno {indirect}", + "no_straight_on": "PROIBIDO seguir em frente {indirect}", + "only_left_turn": "SOMENTE conversão à esquerda {indirect}", + "only_right_turn": "SOMENTE conversão à direita {indirect}", + "only_u_turn": "SOMENTE retorno {indirect}", + "only_straight_on": "SOMENTE seguir em frente {indirect}", + "allowed_left_turn": "Permitida conversão à esquerda {indirect}", + "allowed_right_turn": "Permitida conversão à direita {indirect}", + "allowed_u_turn": "Permitido retorno {indirect}", + "allowed_straight_on": "Permitido seguir em frente {indirect}" + }, + "from": "A PARTIR DE", + "via": "VIA", + "to": "PARA", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Clique para escolher {from} que segmento", + "select_from_name": "Clique para selecionar {from} {fromName}", + "toggle": "Clique para \"{turn}\"" + } + }, "undo": { "tooltip": "Desfazer: {action}", "nothing": "Nada para desfazer." @@ -366,6 +410,7 @@ "key": "H", "title": "Histórico", "selected": "{n} selecionado", + "no_history": "Sem histórico (elemento novo)", "version": "Versão", "last_edit": "Última Edição", "edited_by": "Editado por", @@ -465,6 +510,7 @@ "switch": "Voltar para este fundo de tela", "custom": "Customizado", "custom_button": "Editar fundo de tela personalizado", + "custom_prompt": "Insira um modelo de URL de quadros. Tokens válidos são:\n - {zoom} ou {z}, {x}, {y} para o esquema Z/X/Y dos quadros\n - {-y} ou {ty} para coordenadas invertidas, estilo TMS\n - {u} para esquema quadtile\n - {switch:a,b,c} para multiplexação de servidor DNS\n\nExemplo:\n{example}", "overlays": "Sobreposições", "imagery_source_faq": "Informações sobre imagens / Relatar um problema", "reset": "redefinir", @@ -602,15 +648,20 @@ } }, "success": { - "edited_osm": "OSM editado!", "just_edited": "Você acaba de editar o OpenStreetMap!", - "view_on_osm": "Ver no OSM", - "facebook": "Compartilhar no Facebook", - "twitter": "Compartilhar no Twitter", - "google": "Compartilhar Google+", - "help_html": "Suas modificações devem aparecer na camada \"Padrão\" dentro de alguns minutos. Alguns elementos e outras camadas podem demorar mais para serem atualizadas.", + "thank_you": "Obrigado por aprimorar o mapa.", + "thank_you_location": "Obrigado por aprimorar o mapa ao redor de {where}.", + "help_html": "Suas alterações devem aparecer no OpenStreetMap dentro de alguns minutos. Os mapas em outros lugares podem demorar mais para serem atualizados.", "help_link_text": "Detalhes", - "help_link_url": "https://wiki.openstreetmap.org/wiki/Pt:Perguntas_frequentes#Eu_acabei_de_alterar_o_mapa._Como_eu_fa.C3.A7o_para_visualizar_minhas_altera.C3.A7.C3.B5es.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/Pt:Perguntas_frequentes#Eu_acabei_de_alterar_o_mapa._Como_eu_fa.C3.A7o_para_visualizar_minhas_altera.C3.A7.C3.B5es.3F", + "view_on_osm": "Ver alterações no OSM", + "changeset_id": "Seu conjunto de alterações #: {changeset_id}", + "like_osm": "Gosta do OpenStreetMap? Conecte-se com outros:", + "more": "Mais", + "events": "Eventos", + "languages": "Idiomas: {languages}", + "missing": "Há algo faltando nesta lista?", + "tell_us": "Conte-nos!" }, "confirm": { "okay": "OK", @@ -648,6 +699,7 @@ "untagged_area_tooltip": "Selecionar um tipo de elemento que descreva o que esta área é.", "untagged_relation": "Relação sem etiquetas", "untagged_relation_tooltip": "Selecionar um tipo de elemento que descreva o que esta relação é.", + "many_deletions": "Você está apagando {n} feições: {p} nós, {l} linhas, {a} áreas, {r} relações. Você ter certeza que quer executar esta ação? Ela irá apagar estes elementos para todas as pessoas que acessam o openstreetmap.org.", "tag_suggests_area": "A etiqueta {tag} sugere que seja utilizada numa área, mas essa linha não é uma área", "deprecated_tags": "Etiquetas obsoletas: {tags}" }, @@ -767,31 +819,47 @@ "connect_line_drag": "Para conectar uma linha a algum outro elemento, arraste um dos nós das linhas a outro elemento até que ambos os elementos estejam unidos. Dica: você pode segurar a tecla `{alt}` caso não deseje que um nó se conecte a outros elementos enquanto o arrasta.", "connect_line_tag": "Se você sabe que um cruzamento tem semáforos ou faixas de pedestre, você pode adicioná-los selecionando o nó do cruzamento e utilizando o editor de elementos para selecionar o tipo correto de elemento.", "disconnect_line_h": "Desconectando Linhas", + "disconnect_line_command": "Para desconectar uma rua de outro elemento, clique com o {rightclick} botão direito no nó conectado, e selecione o comando {disconnect} **Desconectar** no menu de edição.", "move_line_h": "Movendo Linhas", - "delete_line_h": "Removendo Linhas" + "move_line_connected": "Linhas conectadas a outros recursos permanecerão conectadas conforme você move a linha para um novo local. O iD pode impedir que você mova uma linha através de outra linha conectada.", + "delete_line_h": "Removendo Linhas", + "delete_line": "Se uma linha estiver totalmente incorreta, por exemplo, uma estrada que não existe no mundo real, não há problema em excluí-la. Tenha cuidado ao excluir recursos: as imagens de plano de fundo que você está usando podem estar desatualizadas e uma estrada que parece estar errada pode simplesmente ser recém-criada." }, "areas": { "title": "Áreas", + "intro": "*Áreas* são usadas para mostrar os limites de recursos como lagos, edifícios e áreas residenciais. As áreas devem ser rastreadas em torno da borda do recurso que elas representam, por exemplo, ao redor da base de um edifício.", "point_or_area_h": "Pontos ou Áreas", + "point_or_area": "Muitos recursos podem ser representados como pontos ou áreas. Você deve mapear contornos de edifícios e propriedades como áreas sempre que possível. Coloque pontos dentro de uma área de construção para representar empresas, comodidades e outros recursos localizados dentro do prédio.", "add_area_h": "Adicionando Áreas", "square_area_h": "Alinhar Cantos", "modify_area_h": "Modificando Áreas", - "delete_area_h": "Removendo Áreas" + "delete_area_h": "Removendo Áreas", + "delete_area": "Se uma área estiver totalmente incorreta, por exemplo, um prédio que não existe no mundo real, não há problema em excluí-lo. Seja cauteloso ao excluir recursos - as imagens de plano de fundo que você está usando podem estar desatualizadas e um edifício que parece estar errado pode simplesmente ser recém-construído." }, "relations": { "title": "Relações", + "intro": "Uma *relação* é um tipo especial de recurso no OpenStreetMap que agrupa outros recursos. Os recursos que pertencem a uma relação são chamados de *membros*, e cada membro pode ter uma *função* na relação.", "edit_relation_h": "Editando Relações", + "edit_relation": "Na parte inferior do editor de recursos, você pode expandir a seção \"Todas as relações\" para ver se o recurso selecionado é um membro de qualquer relação. Você pode clicar na relação para selecioná-la e editá-la.", "maintain_relation_h": "Mantendo Relações", + "maintain_relation": "Na maioria das vezes, o iD manterá as relações automaticamente conforme você edita. Você deve tomar cuidado ao substituir recursos que possam ser membros de relações. Por exemplo, se você excluir uma seção da estrada e desenhar uma nova seção da estrada para substituí-la, adicione a nova seção às mesmas relações (rotas, restrições de rotação, etc.) do original.", "relation_types_h": "Tipos de Relações", "multipolygon_h": "Multipolígonos", "turn_restriction_h": "Restrições de Manobra", + "turn_restriction": "Uma relação de restrição de giro é um grupo de vários segmentos de estrada em uma interseção. As restrições de curva consistem em um *de* estrada, *via* nó ou estradas e uma *para* estrada.", + "turn_restriction_field": "Para editar as restrições de curva, selecione um nó de junção onde duas ou mais estradas se encontram. O editor de recursos exibirá um campo especial \"Ativar restrições\" contendo um modelo da interseção.", + "turn_restriction_editing": "No campo \"Ativar restrições\", clique para selecionar uma estrada \"de\" e veja se as curvas são permitidas ou restritas a qualquer uma das estradas \"para\". Você pode clicar nos ícones de turno para alterná-los entre permitido e restrito. O iD criará relações automaticamente e definirá as funções de, para e com base nas suas escolhas.", "route_h": "Rotas", - "boundary_h": "Fronteiras" + "route": "Uma relação *rota* é um grupo de um ou mais recursos de linha que juntos formam uma rede de rotas, como uma rota de ônibus, rota de trem ou rota de rodovia.", + "boundary_h": "Fronteiras", + "boundary": "Uma relação *limite* é um grupo de um ou mais recursos de linha que juntos formam um limite administrativo." }, "imagery": { "title": "Imagens de Fundo", + "intro": "As imagens de fundo que aparecem abaixo dos dados do mapa são um recurso importante para o mapeamento. Essas imagens podem ser fotos aéreas coletadas de satélites, aviões e drones, ou podem ser mapas históricos digitalizados ou outros dados de fonte disponíveis gratuitamente.", "sources_h": "Fontes de Imagens", "offsets_h": "Ajustando o Deslocamento das Imagens de Fundo", + "offset": "Às vezes, as imagens são ligeiramente compensadas pelos dados precisos do mapa. Se você vir muitas estradas ou edifícios deslocados das imagens de plano de fundo, pode ser que as imagens estejam incorretas, por isso não mova todas elas para corresponder ao plano de fundo. Em vez disso, você pode ajustar o plano de fundo para que ele corresponda aos dados existentes, expandindo a seção \"Ajustar contorno da imagem\" na parte inferior do painel Configurações do plano de fundo.", "offset_change": "Clique nos pequenos triângulos para ajustar o deslocamento de imagens em pequenos passos, ou segure o botão esquerdo do mouse e arraste no quadrado cinzento para deslizar a imagem para o alinhamento." }, "streetlevel": { @@ -806,6 +874,41 @@ "using_h": "Usando Traçados de GPS", "tracing": "A trilha GPX não está sendo enviada ao OpenStreetMap - a melhor maneira de usá-la é desenhar no mapa, usando-a como um guia para os novos elementos que você adicionar.", "upload": "Você também pode [enviá-la ao OpenStreetMap](https://www.openstreetmap.org/trace/create) para que outros usuários possam utilizá-la." + }, + "field": { + "restrictions": { + "title": "Ajuda das Restrições de curva", + "about": { + "title": "Sobre", + "about": "Este campo permite que você inspecione e modifique restrições de curva. Ele mostra um modelo da interseção selecionada, incluindo outras ruas próximas conectadas.", + "from_via_to": "Uma restrição de viragem contém sempre: uma linha **FROM**(de), uma linha **TO**(para), e um nó ou linha **VIA**(através de).", + "maxdist": "O controle deslizante \"{distField}\" define a distância que se deve procurar por ruas conectadas adicionais.", + "maxvia": "O controle deslizante \"{viaField}\" ajusta quantos caminhos serão incluídos na busca. (Dica: quanto mais simples, melhor)" + }, + "inspecting": { + "title": "Inspecionar", + "about": "Passe o mouse sobre qualquer segmento **DE** para ver se há restrições de turno. Cada possível destino ** PARA ** será desenhado com uma sombra colorida mostrando se existe uma restrição.", + "from_shadow": "{fromShadow} segmento **FROM** (de)", + "allow_shadow": "{allowShadow} **TO** (para) permitido", + "restrict_shadow": "{restrictShadow} **TO** (para) não permitido", + "only_shadow": "{onlyShadow} **TO** (para) apenas", + "restricted": "\"Restrito\" significa que existe uma restrição de turno, por exemplo, \"Sem curvas à esquerda\".", + "only": "\"Apenas\" significa que um veículo que leva esse caminho só pode fazer essa escolha, por exemplo, \"Somente Direto\"." + }, + "modifying": { + "title": "Modificar", + "about": "Para modificar as restrições de curva, primeiro clique em qualquer segmento inicial de **DE** para selecioná-lo. O segmento selecionado será pulsado e todos os destinos possíveis do **PARA** aparecerão como símbolos de virada.", + "indicators": "Em seguida, clique em um símbolo de turno para alterná-lo entre \"Permitido\", \"Restrito\" e \"Somente\".", + "allow_turn": "{allowTurn} **TO** (para) permitido", + "restrict_turn": "{restrictTurn} **TO** (para) não permitido", + "only_turn": "{onlyTurn} **TO** (para) apenas" + }, + "tips": { + "title": "Dicas", + "simple": "**Prefira restrições simples ao invés de complexas**", + "indirect_noedit": "Você não pode editar restrições indiretas. Ao invés disso, tente editar uma relação direta próxima." + } + } } }, "intro": { @@ -1588,6 +1691,9 @@ "cycleway:right": "Lado direito" } }, + "dance/style": { + "label": "Estilos de Dança" + }, "date": { "label": "Data" }, @@ -1656,6 +1762,9 @@ "display": { "label": "Mostrador" }, + "distance": { + "label": "Distância total" + }, "dock": { "label": "Tipo" }, @@ -1696,6 +1805,9 @@ "except": { "label": "Exceções" }, + "faces": { + "label": "Faces" + }, "fax": { "label": "Fax", "placeholder": "+55 11 0982 1098" @@ -1807,6 +1919,39 @@ "label": "Aros de Tabela", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Equitação de Adestramento", + "options": { + "equestrian": "Sim", + "undefined": "Não" + } + }, + "horse_riding": { + "label": "Hipismo", + "options": { + "horse_riding": "Sim", + "undefined": "Não" + } + }, + "horse_scale": { + "label": "Dificuldade no hipismo", + "options": { + "common": "Fácil: sem problemas ou dificuldades. (padrão)", + "critical": "Borderline: Passável apenas para cavaleiros experientes e cavalos. Principais obstáculos. Pontes devem ser examinadas com cuidado.", + "dangerous": "Perigoso: Passível apenas para cavaleiros e cavalos experientes e apenas quando o tempo estiver bom. Desmontar.", + "demanding": "Use com cautela: maneira irregular, passagens difíceis ocasionais.", + "difficult": "Difícil: Maneira estreita e exposta. Pode conter obstáculos para passar por cima e estreitar passagens.", + "impossible": "Intransitável: Caminho ou ponte não passável para cavalos. Suporte muito estreito e insuficiente, obstáculos como escadas. Perigo de vida." + }, + "placeholder": "Difícil, Perigoso..." + }, + "horse_stables": { + "label": "Hipismo estável", + "options": { + "stables": "Sim", + "undefined": "Não" + } + }, "iata": { "label": "Código IATA" }, @@ -1826,6 +1971,9 @@ "indoor": { "label": "Interior" }, + "industrial": { + "label": "Tipo" + }, "information": { "label": "Tipo" }, @@ -1946,6 +2094,10 @@ "label": "Limite de Velocidade", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "Limite de Velocidade Consultivo", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Permanência máxima" }, @@ -2534,8 +2686,19 @@ "label": "Tipo", "placeholder": "Padrão" }, + "usage_rail": { + "label": "Tipo de Utilização", + "options": { + "branch": "Filial", + "industrial": "Industrial", + "main": "Principal", + "military": "Militar", + "test": "Teste", + "tourism": "Turismo" + } + }, "vending": { - "label": "Tipo de Produtos" + "label": "Tipos de Produtos" }, "visibility": { "label": "Visibilidade", @@ -2613,6 +2776,8 @@ "options": { "delta": "Delta", "open": "Aberta", + "open-delta": "Delta Aberto", + "star": "Estrela / Y", "zigzag": "Zig Zag" } } @@ -2626,6 +2791,10 @@ "name": "Outdoor", "terms": "Publicidade, letreiro, placa de publicidade" }, + "advertising/column": { + "name": "Coluna de publicidade", + "terms": "" + }, "aerialway": { "name": "Teleférico do tipo cabine" }, @@ -2711,6 +2880,10 @@ "name": "Terminal de Aeroporto", "terms": "aeroporto, edifício, terminal aeroportuário, embarque, desembarque, viagem, turismo, avião, helicóptero" }, + "allotments/plot": { + "name": "Parcela de Jardim Comunitário", + "terms": "" + }, "amenity": { "name": "Serviço" }, @@ -2939,6 +3112,10 @@ "name": "Mercado ou feira", "terms": "Feira, mercado, mercado municipal, feirinha" }, + "amenity/monastery": { + "name": "Jardins do mosteiro", + "terms": "" + }, "amenity/motorcycle_parking": { "name": "Estacionamento de motos", "terms": "Estacionamento de motocicletas, estacionamento de motos, estacionamento" @@ -3081,7 +3258,8 @@ "terms": "ducha, chuveiro, banheiro, banho público, banho" }, "amenity/smoking_area": { - "name": "Área de fumantes" + "name": "Área de fumantes", + "terms": "" }, "amenity/social_facility": { "name": "Unidade de Assistência Social", @@ -3142,6 +3320,10 @@ "name": "Máquina de Venda de Cigarros", "terms": "cigarro, venda de cigarro" }, + "amenity/vending_machine/coffee": { + "name": "Máquina de Venda de Café", + "terms": "" + }, "amenity/vending_machine/condoms": { "name": "Máquina de Venda de Preservativos", "terms": "máquina de venda de camisinhas, preservativos, camisinha" @@ -3150,6 +3332,12 @@ "name": "Máquina de Venda de Bebidas", "terms": "Máquina de Venda de Bebidas, máquina de refrigerante, refrigerante, lata, latinha" }, + "amenity/vending_machine/electronics": { + "name": "Máquina de Venda de Eletrônicos" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Máquina de Venda de Moedas Achatadas" + }, "amenity/vending_machine/excrement_bags": { "name": "Máquina de Vendas de Sacola de Excrementos", "terms": "sacos de excremento, cocô, fezes, dejetos, animal, cachorro, animal de estimação, pet, sacola" @@ -3158,6 +3346,15 @@ "name": "Máquina de Vendas - Higiene Feminina", "terms": "produtos de higiene feminina, camisinha, preservativo, absorvente, tampão, cuidados pessoais, higiene, mulher" }, + "amenity/vending_machine/food": { + "name": "Máquina de Venda de Comida" + }, + "amenity/vending_machine/fuel": { + "name": "Bomba de Gasolina" + }, + "amenity/vending_machine/ice_cream": { + "name": "Máquina de Venda de Sorvete" + }, "amenity/vending_machine/news_papers": { "name": "Máquina de Venda de Jornais" }, @@ -3177,6 +3374,9 @@ "name": "Máquina de Vendas de Bilhete de Transporte", "terms": "Transporte público, ônibus, Trem, Metrô, Ticket, Bilhete" }, + "amenity/vending_machine/stamps": { + "name": "Máquina de Venda de Selos" + }, "amenity/vending_machine/sweets": { "name": "Máquina de Venda de Lanches", "terms": "salgados, doces, petiscos, salgadinhos, snacks, chicletes, biscoitos, balas" @@ -3249,6 +3449,9 @@ "name": "Torre de Queda Livre", "terms": "big tower" }, + "attraction/maze": { + "name": "Labirinto" + }, "attraction/pirate_ship": { "name": "Navio Pirata", "terms": "brinquedo, parque temático, barco, parque de diversões, parque de diversão" @@ -3406,6 +3609,12 @@ "building/entrance": { "name": "Entrada/Saída" }, + "building/farm": { + "name": "Casa de fazenda" + }, + "building/farm_auxiliary": { + "name": "Edifício da Fazenda" + }, "building/garage": { "name": "Garagem", "terms": "Garagem" @@ -3505,6 +3714,9 @@ "building/train_station": { "name": "Estação Ferroviária" }, + "building/transportation": { + "name": "Edifício de transporte" + }, "building/university": { "name": "Edifício Universitário", "terms": "Edifício Universitário, Faculdade, Edifício de Faculdade, prédio universitário, bloco universitário, prédio de faculdade, prédio de universidade, edifício de universidade" @@ -3755,6 +3967,9 @@ "emergency/private": { "name": "Acesso de Emergência Privado" }, + "emergency/water_tank": { + "name": "Tanque de água de emergência" + }, "emergency/yes": { "name": "Acesso de Emergência" }, @@ -3763,11 +3978,11 @@ "terms": "Entrada/Saída, Porta, " }, "footway/crossing": { - "name": "Travessia em Rua", + "name": "Faixa para travessia de pedestres", "terms": "Faixa de cruzamento" }, "footway/crossing-raised": { - "name": "Travessia em via elevada", + "name": "Faixa elevada para travessia de pedestres", "terms": "quebra mola, quebra-molas, redutor de velocidade, faixa de pedestres" }, "footway/crosswalk": { @@ -3854,6 +4069,9 @@ "name": "Unidades de Cuidados Paliativos", "terms": "doença, terminal, tratamento" }, + "healthcare/laboratory": { + "name": "Laboratório médico" + }, "healthcare/midwife": { "name": "Parteira", "terms": "obstetra, obstetrícia, parteira, parto, clínica de obstetrícia, gravidez, gestante, gestação" @@ -3893,6 +4111,9 @@ "name": "Hipovia", "terms": "Hipovia, Picadeiro, Caminho para Cavalgada, calvagada, Trilha de Equitação, cavalo, hipismo" }, + "highway/bus_guideway": { + "name": "Guideway de ônibus" + }, "highway/bus_stop": { "name": "Parada de ônibus / Plataforma" }, @@ -3952,6 +4173,9 @@ "name": "Ligação de Autoestrada", "terms": "acesso a autoestrada, acesso a via expressa, ligação de via expressa" }, + "highway/passing_place": { + "name": "Lugar de passagem" + }, "highway/path": { "name": "Caminho Informal", "terms": "trilha, caminho, caminhada" @@ -4025,7 +4249,7 @@ "terms": "Área de Serviço, Posto de combustíveis, posto de gasolina, combustíveis, borracharia, lava jato, serviços, loja de conveniências" }, "highway/speed_camera": { - "name": "Sensor de Velocidade", + "name": "Câmera de Controle de Velocidade", "terms": "câmera de velocidade, radar, pardal, foto-sensor, foto sensor, fotossensor, sinal de trânsito, fiscalização eletrônica de velocidade" }, "highway/steps": { @@ -4141,6 +4365,7 @@ "terms": "Bacia" }, "landuse/brownfield": { + "name": "Área contaminada", "terms": "Terreno industrial abandonado, área em revitalização, área abandonada, terreno em revitalização, zona industrial abandonada, desenvolvimento" }, "landuse/cemetery": { @@ -4315,6 +4540,9 @@ "name": "Danceteria", "terms": "salão de dança, balada, boate, clube de dança, salsa, tango" }, + "leisure/dancing_school": { + "name": "Escola de Dança" + }, "leisure/dog_park": { "name": "Cachorródromo", "terms": "Canódromo, Cachorródromo, Parque Canino, Parque de Cachorros, cães, cão, cachorros" @@ -4328,7 +4556,7 @@ "terms": "Academia de Musculação, Academia de Ginástica" }, "leisure/fitness_centre/yoga": { - "name": "Estúdio de Ioga", + "name": "Estúdio de Yôga", "terms": "Estúdio de Yoga, Academia de Ioga, Academia de Yoga, Yôga, Ioga, Yoga" }, "leisure/fitness_station": { @@ -4338,12 +4566,18 @@ "leisure/fitness_station/balance_beam": { "name": "Trave de Equilíbrio" }, + "leisure/fitness_station/horizontal_bar": { + "name": "Barra Fixa Horizontal" + }, "leisure/fitness_station/hyperextension": { "name": "Estação de Hiperextensão" }, "leisure/fitness_station/parallel_bars": { "name": "Barras Paralelas" }, + "leisure/fitness_station/sit-up": { + "name": "Prancha para Abdominais" + }, "leisure/fitness_station/stairs": { "name": "Escadas de Exercício" }, @@ -4507,6 +4741,9 @@ "name": "Ádito de Mineração", "terms": "Entrada, Passagem, Mina, Acesso" }, + "man_made/antenna": { + "name": "Antena" + }, "man_made/breakwater": { "name": "Molhe/Quebra-Mar", "terms": "Molhe, Quebra-Mar" @@ -4557,6 +4794,9 @@ "name": "Torre de Observação", "terms": "torre de observação, observação, ponto de observação, torre de incêndio, incêndio florestal" }, + "man_made/observatory": { + "name": "Observatório" + }, "man_made/petroleum_well": { "name": "Poço de Petróleo", "terms": "Cavalo mecânico, Poço de extração de petróleo, petróleo, Óleo" @@ -4681,6 +4921,9 @@ "name": "Urzal", "terms": "Urzal" }, + "natural/mud": { + "name": "Lama" + }, "natural/peak": { "name": "Cume", "terms": "Pico, Topo de Montanha, Serra, Montanha, Monte" @@ -5049,6 +5292,9 @@ "name": "Parada de Ônibus / Plataforma", "terms": "ônibus, ponto de ônibus, transporte público, plataforma, trânsito" }, + "public_transport/linear_platform_ferry": { + "name": "Parada de Balsa / Plataforma" + }, "public_transport/linear_platform_light_rail": { "name": "Parada de VLT / Plataforma", "terms": "veículo leve sobre trilhos, VLT, bonde, transporte público, trânsito, transporte, coletivo" @@ -5077,6 +5323,9 @@ "name": "Parada de ônibus / Plataforma", "terms": "ônibus, ponto de ônibus, transporte público, plataforma, trânsito" }, + "public_transport/platform_ferry": { + "name": "Parada de Balsa / Plataforma" + }, "public_transport/platform_light_rail": { "name": "Parada de VLT / Plataforma", "terms": "veículo leve sobre trilhos, VLT, bonde, transporte público, trânsito, transporte, coletivo" @@ -5141,12 +5390,24 @@ "public_transport/stop_position_bus": { "name": "Local de parada de ônibus" }, + "public_transport/stop_position_light_rail": { + "name": "Local de parada do VLT" + }, + "public_transport/stop_position_monorail": { + "name": "Localização de parada do monotrilho" + }, "public_transport/stop_position_subway": { "name": "Local de parada de metrô" }, "public_transport/stop_position_train": { "name": "Local de parada de trem" }, + "public_transport/stop_position_tram": { + "name": "Localização de parada do bonde" + }, + "public_transport/stop_position_trolleybus": { + "name": "Trólebus parando local" + }, "railway": { "name": "Ferrovia" }, @@ -5174,6 +5435,9 @@ "name": "Funicular", "terms": "Funicular, Plano Inclinado" }, + "railway/halt": { + "name": "Estação de trem (parada / pedido)" + }, "railway/level_crossing": { "name": "Cruzamento de Ferrovia (Estrada)", "terms": "Passagem de Nível (Estrada)" @@ -5232,6 +5496,9 @@ "name": "Trilho de bonde", "terms": "Bonde, VLT, Veículo leve sobre trilhos" }, + "railway/tram_stop": { + "name": "Posição de parada do bonde" + }, "relation": { "name": "Relação", "terms": "Relação" @@ -5485,6 +5752,10 @@ "name": "Loja de Material de Construção", "terms": "Loja de Ferragens, Material de Construção, Loja de Tintas, Loja de Parafusos, Madeireira" }, + "shop/health_food": { + "name": "Loja de Alimentos Saudáveis", + "terms": "loja de produtos naturais, comida saudável, alimentação saudável, natureba" + }, "shop/hearing_aids": { "name": "Loja de Aparelhos Auditivos", "terms": "farmácia" @@ -5724,6 +5995,10 @@ "name": "Loja de Armas", "terms": "Loja de Tiro, Loja de Equipamentos de Tiro" }, + "shop/wholesale": { + "name": "Atacadista", + "terms": "atacadão, loja de atacados, " + }, "shop/window_blind": { "name": "Loja de Persianas", "terms": "Loja de Vidros Blindados, Cortinas" @@ -5819,12 +6094,17 @@ "name": "Parque Temático", "terms": "Parque Temático" }, + "tourism/trail_riding_station": { + "name": "Estação de Hipismo de Trilha", + "terms": "" + }, "tourism/viewpoint": { "name": "Mirante", "terms": "Mirante" }, "tourism/wilderness_hut": { - "name": "Abrigo Isolado" + "name": "Abrigo Isolado", + "terms": "" }, "tourism/zoo": { "name": "Zoológico", @@ -5867,7 +6147,8 @@ "terms": "sonorizador" }, "traffic_calming/table": { - "name": "Redutor de Velocidade Elevado" + "name": "Redutor de Velocidade Elevado", + "terms": "" }, "type/boundary": { "name": "Fronteira", @@ -5901,16 +6182,20 @@ "terms": "Proibido Retornar" }, "type/restriction/only_left_turn": { - "name": "Obrigatório Virar à Esquerda", - "terms": "Obrigatório Virar à Esquerda" + "name": "Apenas curva à esquerda", + "terms": "curva à esquerda obrigatória, conversão à esquerda" }, "type/restriction/only_right_turn": { - "name": "Obrigatório Virar à Direita", - "terms": "Obrigatório Virar à Direita" + "name": "Apenas curva à direita", + "terms": "curva à direita obrigatória, conversão à direita" }, "type/restriction/only_straight_on": { - "name": "Obrigatório Seguir em Frente", - "terms": "Obrigatório Seguir em Frente" + "name": "Apenas seguir em frente", + "terms": "somente seguir em frente" + }, + "type/restriction/only_u_turn": { + "name": "Apenas retorno", + "terms": "somente retornar, retorno obrigatório" }, "type/route": { "name": "Rota", @@ -6073,7 +6358,7 @@ "attribution": { "text": "Termos e Comentários" }, - "description": "Limites de imagens de satélite e datas de captura. Etiquetas aparecerão no nível de zoom 14 ou acima.", + "description": "Limites de imagens e datas de captura. Os rótulos aparecem no nível de zoom 13 e superior.", "name": "Bordas das Imagens de Satélite DigitalGlobe Premium" }, "DigitalGlobe-Standard": { @@ -6087,7 +6372,7 @@ "attribution": { "text": "Termos e Comentários" }, - "description": "Limites de imagens de satélite e datas de captura. Etiquetas aparecerão no nível de zoom 14 ou acima.", + "description": "Limites de imagens e datas de captura. Os rótulos aparecem no nível de zoom 13 e superior.", "name": "Boradas das Imagens de Satélite DigitalGlobe Standard" }, "EsriWorldImagery": { @@ -6171,6 +6456,10 @@ "description": "Amarelo = Dados de mapa de domínio público do Censo dos EUA. Vermelho = Dados não encontrados no OpenStreetMap", "name": "Estradas TIGER 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Estrada: Cobertura verde = não classificada. Cobertura marrom = trilha. Superfície: cascalho = preenchimento marrom claro, Asfalto = preto, Pavimentado = cinza, Terra = branco, Concreto = azul, Grama = verde. Sazonal = barras brancas", + "name": "Sobreposição de estradas florestais dos EUA" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, colaboradores do OpenStreetMap, CC by-SA 3.0" @@ -6205,7 +6494,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Mapa base da Áustria, baseado em dados governamentais.", + "description": "Dados de mapas da Áustria, com base em dados do governo.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6267,7 +6556,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Quadros do mapa de Stamen Design, sob CC BY 3.0" + "text": "Quadros do mapa de Stamen Design, sob CC BY 3.0. Dados por OpenStreetMap, sob ODbL" }, "name": "Stamen, Terreno" }, @@ -6283,6 +6572,167 @@ }, "name": "Paisagens Thunderforest" } + }, + "community": { + "cape-coast-youthmappers": { + "description": "Siga-nos no Twitter: {url}" + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Gana no Facebook", + "description": "Grupo no Facebook para pessoas interessadas no OpenStreetMap." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Gana no Twitter", + "description": "Siga-nos no Twitter: {url}" + }, + "talk-gh": { + "name": "Lista de Discussão Talk-gh" + }, + "talk-mg": { + "name": "Lista de Discussão Talk-mg" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap Índia - Mapeamento de vizinhança participativa", + "description": "Melhorar o OpenStreetMap na Índia" + }, + "OSM-india-mailinglist": { + "name": "Lista de Discussão do OpenStreetMap na Índia", + "description": "Talk-in é a lista de discussão oficial para a comunidade indiana" + }, + "OSM-india-twitter": { + "description": "Estamos a um tweet de distância: {url}" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonésia" + }, + "OSM-japan-mailinglist": { + "name": "Lista de Discussão do OpenStreetMap Japão", + "description": "Talk-ja é a lista de discussão oficial para a Comunidade Japonesa" + }, + "OSM-japan-twitter": { + "description": "Hashtag no Twitter: {url}" + }, + "OSM-PH-mailinglist": { + "name": "Lista de Discussão Talk-ph", + "description": "Uma lista de discussão para falar sobre o OpenStreetMap nas Filipinas" + }, + "de-berlin-twitter": { + "description": "Siga-nos no Twitter: {url}" + }, + "se-twitter": { + "description": "Siga-nos no Twitter: {url}" + }, + "Bay-Area-OpenStreetMappers": { + "name": "OpenStreetMappers da Bay Area", + "description": "Melhorar o OpenStreetMap na área da baía", + "extendedDescription": "Este grupo é sobre crescer a comunidade do OpenStreetMap aqui na Área da Baía de São Francisco. Nossos eventos são abertos para todos, desde entusiastas open-source, ciclistas, profissionais GIS, geocachers, e além. Todos e quaisquer pessoas interessadas em mapas, cartografia e dados de mapa livres são bem-vindas a se juntar ao nosso grupo e participar dos nossos eventos." + }, + "Central-Pennsylvania-OSM": { + "name": "Pensilvânia central OSM", + "description": "Comunidade de mapeamento on-line baseada no State College, PA" + }, + "Code-for-San-Jose-Slack": { + "name": "Código para San Jose Slack", + "description": "São todos bem-vindos! Inscreva-se em {signupUrl}, então junte-se ao canal #osm." + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "O grupo de usuários do OpenStreetMap para Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth e todas as cidades estão repletas de pessoas criativas e conhecedoras de tecnologia. A visão deste grupo de usuários é encontrar novas maneiras de usar o incrível recurso do OSM." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Meetup para entusiastas do mapa na área de Filadélfia", + "extendedDescription": "A GeoPhilly une desenvolvedores, geógrafos, geeks de dados, entusiastas do código aberto, hackers cívicos e viciados em mapas em nosso amor compartilhado pelos mapas e pelas histórias que contam. Se você usa mapas como parte do seu trabalho ou apenas quer aprender mais, este é o encontro para você! Nossos eventos visam ser abertos, amigáveis, educacionais e sociais e vão desde happy hours até palestras relâmpago ou até workshops. Venha criar uma comunidade geoespacial diversificada e inspiradora na Filadélfia conosco!" + }, + "Mapping-DC-meetup": { + "name": "Mapeamneto de DC", + "description": "Melhore o OpenStreetMap na área de DC", + "extendedDescription": "Somos um grupo de mapeadores voluntários que visam melhorar o OpenStreetMap na área de DC. Também pretendemos ensinar aos outros sobre o ecossistema OSM, análise de dados, cartografia e GIS. Nós nos reunimos a cada dois meses nos encontros para nos concentrar em uma área da nossa cidade." + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Mapeadores e usuários do OpenStreetMap na área de Boston", + "extendedDescription": "OpenStreetMap é o mapa gratuito e aberto do mundo, com centenas de milhares de contribuições diárias de pessoas como você. Editar o mapa é simples e divertido! Junte-se a nós em ambientes internos e externos em nosso esforço para criar o melhor mapa da área de Boston e do resto do mundo!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "O grupo de usuários do OpenStreetMap para o Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "extendedDescription": "OpenStreetMap (OSM) Colorado é uma colaboração local de pessoas interessadas em contribuir com seus esforços para criar mapas gratuitos. Encorajamos todos os nossos mapeadores a organizar ou sugerir o mapeamento de eventos em todo o estado. As atividades do Meetup podem ser simples mixers sociais, treinamento básico e avançado do OSM ou partes de mapeamento da comunidade." + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Usuários e Mapeadores do OpenStreetMap, desenvolvedores e entusiastas da área metropolitana de Nova York" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Mapeadores e usuários do OpenStreetMap na área de Portland", + "extendedDescription": "OpenStreetMap (OSM) é um mapa do mundo feito por pessoas como você. É um mapa que você constrói, que é dado de graça, como na Wikipédia. Confira osm.org para mais, e junte-se a nós em um meetup para conversar sobre mapas, contribuir para o OSM e se divertir!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Mapeadores e usuários do OpenStreetMap na área de Seattle" + }, + "OSM-South-Bay": { + "name": "OSM South Bay", + "description": "Noites do Mapa hospedado por Code for San Jose" + }, + "OSM-US-Slack": { + "description": "Todos são bem-vindos! Se inscreva em {signupUrl}" + }, + "PHXGeo-twitter": { + "description": "Siga-nos no Twitter em {url}" + }, + "Maptime-Australia-Slack": { + "description": "Se inscreva em {signupUrl}" + }, + "OSM-AR-twitter": { + "description": "Siga-nos no Twitter em {url}" + }, + "Bahia-telegram": { + "name": "Grupo Telegram OpenStreetMap Bahia", + "description": "Participe da comunidade OpenStreetMap Bahia no Telegram" + }, + "OSM-br-mailinglist": { + "name": "Talk-br Mailing List", + "description": "Uma lista de e-mail de discussão sobre o OpenStreetMap no Brasil" + }, + "OSM-br-telegram": { + "name": "Telegram OpenStreetMap Brasil", + "description": "Participe da comunidade OpenStreetMap Brasil no Telegram", + "extendedDescription": "Entre na comunidade para aprender mais sobre o OpenStreetMap, fazer perguntas ou participar das nossas reuniões. Todos são bem-vindos!" + }, + "OSM-br-twitter": { + "name": "Twitter OpenStreetMap Brasil", + "description": "Nos siga no Twitter em {url}" + }, + "OSM-CL-twitter": { + "description": "Siga-nos no Twitter: {url}" + }, + "OSM-CO-twitter": { + "description": "Siga-nos no Twitter: {url}" + }, + "OSM-PE-twitter": { + "description": "Siga-nos no Twitter: {url}" + }, + "OSM-Reddit": { + "name": "OpenStreetMap no Reddit", + "description": "/r/openstreetmap/ é um ótimo lugar para aprender mais sobre o OpenStreetMap. Pergunte-nos qualquer coisa!" + }, + "OSM-Twitter": { + "name": "Twitter OpenStreetMap", + "description": "Siga-nos no Twitter: {url}" + }, + "OSMF": { + "events": { + "sotm2018": { + "description": "Participe da conferência global do OpenStreetMap em Milão (Itália), evento que irá reunir por três dias toda a comunidade OSM para socializar, compartilhar e aprender juntos." + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/pt.json b/vendor/assets/iD/iD/locales/pt.json index 0ef0e047e..eed460051 100644 --- a/vendor/assets/iD/iD/locales/pt.json +++ b/vendor/assets/iD/iD/locales/pt.json @@ -1,5 +1,10 @@ { "pt": { + "icons": { + "information": "info", + "remove": "remover", + "undo": "desfazer" + }, "modes": { "add_area": { "title": "Área", @@ -145,7 +150,9 @@ "vertex": "Linha conectada a outra.", "line": "Linha ou área conectada a outra linha.", "area": "Linha conectada a uma área." - } + }, + "relation": "Estes elementos não podem ser conectados porque eles têm funções de relação em conflito.", + "restriction": "Estes elementos não podem ser conectados porque iriam danificar a relação \"{relation}\"." }, "disconnect": { "title": "Desconectar", @@ -163,7 +170,8 @@ "annotation": "{n} elementos combinados.", "not_eligible": "Estes elementos não podem ser combinados.", "not_adjacent": "Estes elementos não podem ser unidos porque as suas extremidades não estão conectadas.", - "restriction": "Estes elementos não podem ser combinados porque pelo menos um deles é membro da relação \"{relation}\".", + "restriction": "Estes elementos não podem ser unidos porque iriam danificar a relação \"{relation}\".", + "relation": "Estes elementos não podem ser unidos porque eles têm funções de relação em conflito.", "incomplete_relation": "Estes elementos não podem ser combinados porque pelo menos um deles não está completamente descarregado no mapa.", "conflicting_tags": "Estes elementos não podem ser combinados porque algumas das suas etiquetas entram em conflito." }, @@ -402,6 +410,7 @@ "key": "H", "title": "Histórico", "selected": "{n} selecionado", + "no_history": "Sem histórico (elemento novo)", "version": "Versão", "last_edit": "Última edição", "edited_by": "Editado por", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "Acabou de editar o OpenStreetMap!", "just_edited": "Acaba de editar o OpenStreetMap!", - "view_on_osm": "Ver no OpenStreetMap", - "facebook": "Partilhar no Facebook", - "twitter": "Partilhar no Twitter", - "google": "Partilhar no Google+", - "help_html": "As suas alterações devem aparecer na \"Camada Padrão\" em poucos minutos. Outras camadas e determinados elementos podem demorar mais tempo.", + "thank_you": "Obrigado por melhorares o mapa.", + "thank_you_location": "Obrigado por melhorares o mapa em {where}.", + "help_html": "As tuas alterações devem aparecer no OpenStreetMap dentro de poucos minutos. Pode demorar mais tempo se for um mapa noutro site dependente do OSM.", "help_link_text": "Detalhes", - "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" + "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", + "view_on_osm": "Ver alterações no OSM", + "changeset_id": "O teu conjunto de alterações #: {changeset_id}", + "like_osm": "Gostas do OpenStreetMap? Liga-te a outros:", + "more": "Mais", + "events": "Eventos", + "languages": "Línguas: {languages}", + "missing": "Falta algo na lista?", + "tell_us": "Diz-nos!" }, "confirm": { "okay": "Ok", @@ -888,16 +902,28 @@ "title": "Ajuda da restrições de viragem", "about": { "title": "Sobre", - "about": "Este campo permite-lhe inspeccionar e modificar as restrições de viragem. É mostrado um modelo da intersecção seleccionada incluindo as estradas que estão conectadas." + "about": "Este campo permite-lhe inspeccionar e modificar as restrições de viragem. É mostrado um modelo da intersecção seleccionada incluindo as estradas que estão conectadas.", + "from_via_to": "Uma restrição de viragem contém sempre: uma linha **FROM**(de), uma linha **TO**(para), e um nó ou linha **VIA**(através de).", + "maxdist": "Os deslizador \"{distField}\" controla quão longe deve procurar por estradas adicionais ligadas.", + "maxvia": "O deslizador \"{viaField}\" ajusta quantas linhas via podem ser incluídas na pesquisa. (Dica: quanto mais simples, melhor)" }, "inspecting": { - "title": "Inspeccionando" + "title": "Inspeccionando", + "from_shadow": "{fromShadow} segmento **FROM** (de)", + "allow_shadow": "{allowShadow} **TO** (para) permitido", + "restrict_shadow": "{restrictShadow} **TO** (para) não permitido", + "only_shadow": "{onlyShadow} **TO** (para) apenas" }, "modifying": { - "title": "Modificando" + "title": "Modificando", + "allow_turn": "{allowTurn} **TO** (para) permitido", + "restrict_turn": "{restrictTurn} **TO** (para) não permitido", + "only_turn": "{onlyTurn} **TO** (para) apenas" }, "tips": { - "title": "Dicas" + "title": "Dicas", + "simple": "**Prefere restrições simples em vez de complicadas.**", + "indirect_noedit": "Não deverá editar restrições indiretas. Opte por editar a restrição direta mais próxima." } } } @@ -1683,6 +1709,9 @@ "cycleway:right": "Lado direito" } }, + "dance/style": { + "label": "Estilos de Dança" + }, "date": { "label": "Data" }, @@ -1748,6 +1777,9 @@ "display": { "label": "Mostrador" }, + "distance": { + "label": "Distância total" + }, "dock": { "label": "Tipo" }, @@ -1802,7 +1834,7 @@ "label": "Posição", "options": { "green": "Relvado", - "lane": "Via de trânsito", + "lane": "Faixa de rodagem", "parking_lot": "Estacionamento", "sidewalk": "Passeio" } @@ -1810,10 +1842,10 @@ "fire_hydrant/type": { "label": "Tipo", "options": { - "pillar": "Superfície ", + "pillar": "Marco de incêndio no solo", "pond": "Poça de água", - "underground": "Subterrâneo ", - "wall": "Muro" + "underground": "Boca de incêndio tradicional com portinholas", + "wall": "Marco de incêndio na parede" } }, "fitness_station": { @@ -1899,6 +1931,27 @@ "label": "Cestos", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "options": { + "equestrian": "Sim", + "undefined": "Não" + } + }, + "horse_riding": { + "options": { + "horse_riding": "Sim", + "undefined": "Não" + } + }, + "horse_scale": { + "placeholder": "Difícil, perigoso..." + }, + "horse_stables": { + "options": { + "stables": "Sim", + "undefined": "Não" + } + }, "iata": { "label": "IATA" }, @@ -1918,6 +1971,9 @@ "indoor": { "label": "Interior" }, + "industrial": { + "label": "Tipo" + }, "information": { "label": "Tipo" }, @@ -1956,7 +2012,7 @@ "label": "Tipo" }, "lanes": { - "label": "Número de vias de trânsito", + "label": "Número de faixas de rodagem", "placeholder": "1, 2, 3..." }, "layer": { @@ -2038,6 +2094,9 @@ "label": "Limite de velocidade", "placeholder": "50, 90, 100, 120..." }, + "maxspeed/advisory": { + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Tempo máximo" }, @@ -2191,7 +2250,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telefone / Telemóvel", "placeholder": "+351 211 123456" }, "piste/difficulty": { @@ -2290,6 +2348,9 @@ "ref": { "label": "Código de Referência" }, + "ref/isil": { + "label": "Código ISIL" + }, "ref_aeroway_gate": { "label": "Número da Porta" }, @@ -2623,8 +2684,17 @@ "label": "Tipo", "placeholder": "Padrão" }, + "usage_rail": { + "label": "Tipo de Utilização", + "options": { + "industrial": "Industrial", + "military": "Militar", + "test": "Testes", + "tourism": "Turismo" + } + }, "vending": { - "label": "Tipo de produtos" + "label": "Tipos de Produtos" }, "visibility": { "label": "Visibilidade", @@ -2684,6 +2754,9 @@ "wheelchair": { "label": "Acesso cadeira rodas" }, + "wholesale": { + "label": "Grossista" + }, "width": { "label": "Largura (metros)" }, @@ -3162,6 +3235,10 @@ "name": "Chuveiro", "terms": "Shower, chuveiro público, shuveiro, xuveiro, chubeiro, xubeiro, shubeiro, banho" }, + "amenity/smoking_area": { + "name": "Área para Fumadores", + "terms": "fumadores, fumar" + }, "amenity/social_facility": { "name": "Centro social", "terms": "Social Facility, Casa do Povo" @@ -3788,7 +3865,7 @@ }, "emergency/fire_hydrant": { "name": "Boca de incêndio", - "terms": "Fire Hydrant, Hidrante, Marco de Água, Marco de Incêndio" + "terms": "Hidrate, Marco de Água, Marco de Incêndio, boca de incêndio" }, "emergency/life_ring": { "name": "Boia de Salvamento", @@ -4336,7 +4413,7 @@ "terms": "" }, "landuse/residential": { - "name": "Zona residencial", + "name": "Área residencial", "terms": "Residencial, Urbano, Antrópico, Residential" }, "landuse/retail": { @@ -4371,6 +4448,10 @@ "name": "Salão de dança", "terms": "Dance Hall" }, + "leisure/dancing_school": { + "name": "Escola de Dança", + "terms": "dança, dançar, bailado, bailarina, bailarino" + }, "leisure/dog_park": { "name": "Parque para cães", "terms": "Parque para Cães, Dog Park" @@ -4646,6 +4727,10 @@ "name": "Torre de observação", "terms": "Observatório Tower, Miradouro" }, + "man_made/observatory": { + "name": "Observatório", + "terms": "Observatório Astronómico, Observação, Observações, Astronomia" + }, "man_made/petroleum_well": { "name": "Poço de petróleo", "terms": "Oil Well" @@ -5166,6 +5251,42 @@ "name": "Paragem de autocarro / plataforma", "terms": "Paragem, terminal, autocarro, bus stop, bus, abrigo paragem" }, + "public_transport/linear_platform_ferry": { + "name": "Paragem de Ferry / Plataforma", + "terms": "Ferry, Plataforma de Ferry" + }, + "public_transport/linear_platform_train": { + "name": "Paragem de Comboio / Plataforma", + "terms": "Paragem de Comboio, Plataforma de Comboio" + }, + "public_transport/platform_ferry": { + "name": "Paragem de Ferry / Plataforma", + "terms": "Ferry, Plataforma de Ferry" + }, + "public_transport/platform_train": { + "name": "Paragem de Comboio / Plataforma", + "terms": "Paragem de Comboio, Plataforma de Comboio" + }, + "public_transport/station_ferry": { + "name": "Estação de Ferry / Terminal", + "terms": "Ferry, Terminal de Ferry" + }, + "public_transport/station_train": { + "name": "Estação de Comboios", + "terms": "Estação Ferroviária, Estação dos Caminhos de Ferro" + }, + "public_transport/station_train_halt": { + "name": "Apeadeiro Ferroviário", + "terms": "Apeadeiro, Paragem de Comboio" + }, + "public_transport/stop_position_ferry": { + "name": "Localização de Paragem do Ferry", + "terms": "Ferry, Paragem do Ferry" + }, + "public_transport/stop_position_train": { + "name": "Localização de Paragem do Comboio", + "terms": "Comboio, Paragem do Comboio" + }, "railway": { "name": "Ferrovia" }, @@ -5740,6 +5861,10 @@ "name": "Loja de armas", "terms": "espingardaria, Loja de Armas, Caça" }, + "shop/wholesale": { + "name": "Loja Grossista", + "terms": "grossista, atacado, revendedor, revenda" + }, "shop/window_blind": { "name": "Loja de estores", "terms": "Estores, Estor" @@ -5790,7 +5915,7 @@ }, "tourism/guest_house": { "name": "Hospedagem Domiciliar/Casa de Hóspedes", - "terms": "casa se hóspedes, Cama e Pequeno Almoço, Cama e Peq. Almoço, Cama e Almoço" + "terms": "casa de hóspedes, Cama e Pequeno Almoço, Cama e Peq. Almoço, Cama e Almoço, albergaria, hospedaria, pensão" }, "tourism/hostel": { "name": "Pousada / Hostel", @@ -5822,7 +5947,7 @@ }, "tourism/motel": { "name": "Motel", - "terms": "Albergaria " + "terms": "quartos de motel, albergue, parador, paradores" }, "tourism/museum": { "name": "Museu", @@ -5919,18 +6044,6 @@ "name": "Proibição de inversão de marcha", "terms": "Não Inverter o Sentido, inversão de marcha proibida, proibida a inversão de marcha, não fazer inversão de marcha" }, - "type/restriction/only_left_turn": { - "name": "Sentido obrigatório para a esquerda", - "terms": "obrigatoriedade de virar à esquerda, virar para a esquerda," - }, - "type/restriction/only_right_turn": { - "name": "Sentido obrigatório para a direita", - "terms": "obrigatoriedade de virar à direita, virar para a direita," - }, - "type/restriction/only_straight_on": { - "name": "Sentido obrigatório para a frente", - "terms": "Proibido Virar, seguir em frente" - }, "type/route": { "name": "Rota", "terms": "Rota, Linha, circuito, percursos, percurso, circuitos" @@ -6092,7 +6205,7 @@ "attribution": { "text": "Termos e Opinião" }, - "description": "Limites das imagens e datas de captura. As etiquetas aparecem no nível de aproximação 14 ou superior.", + "description": "Limites das imagens aéreas e datas de captura. As etiquetas aparecem no nível de magnificação 13 e superiores.", "name": "Imagens DigitalGlobe Premium antigas" }, "DigitalGlobe-Standard": { @@ -6106,7 +6219,7 @@ "attribution": { "text": "Termos e Opinião" }, - "description": "Limites das imagens e datas de captura. As etiquetas aparecem no nível de aproximação 14 ou superior.", + "description": "Limites das imagens aéreas e datas de captura. As etiquetas aparecem no nível de magnificação 13 e superiores.", "name": "Imagens DigitalGlobe Standard antigaas" }, "EsriWorldImagery": { @@ -6190,6 +6303,10 @@ "description": "Amarelo = Informação de mapa em domínio público dos Censos dos EUA. Vermelho = Informação não existente no OpenStreetMap", "name": "Estradas TIGER 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Estrada: cobertura verde = não classificada. cobertura castanha = trilho. Superfície: gravilha = preenchimento castanho claro, asfalto = preto, pavimentado = cinza, terra = branco, cimento = azul, erva = verde. Sazonal = barras brancas", + "name": "Sobreposição Estradas Florestais E.U.A." + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, contribuidores OpenStreetMap, CC by-SA 3.0" @@ -6224,7 +6341,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Mapa base Áustria, baseado em informação govenamental ", + "description": "Mapa Base da Áustria, baseado em dados do governo", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6280,13 +6397,13 @@ }, "skobbler": { "attribution": { - "text": "© Telas: skobbler, dados do mapa © contribuidores OpenStreetMap" + "text": "© Mosaico: skobbler, dados do mapa © contribuidores OpenStreetMap" }, "name": "skobbler" }, "stamen-terrain-background": { "attribution": { - "text": "Telas do mapa por Stamen Design, sob licença CC BY 3.0" + "text": "Mosaico do mapa por Stamen Design, sob CC BY 3.0. Dados por OpenStreetMap, sob ODbL" }, "name": "Terreno Stamen" }, @@ -6302,6 +6419,111 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "description": "Segue-nos no Twitter: {url}" + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Gana no Facebook", + "description": "Grupo no Facebook para pessoas interessadas no OpenStreetMap." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Gana no Twitter", + "description": "Segue-nos no Twitter: {url}" + }, + "talk-gh": { + "name": "Lista de Discussão Talk-gh" + }, + "talk-mg": { + "name": "Lista de Discussão Talk-mg" + }, + "OSM-india-mailinglist": { + "name": "Lista de Discussão do OpenStreetMap na Índia", + "description": "Talk-in é a lista de discussão oficial para a comunidade indiana" + }, + "OSM-india-twitter": { + "description": "Estamos a um tweet de distância: {url}" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonésia" + }, + "OSM-japan-mailinglist": { + "name": "Lista de Discussão do OpenStreetMap Japão", + "description": "Talk-ja é a lista de discussão oficial para a comunidade japonesa" + }, + "OSM-japan-twitter": { + "description": "Hashtag no Twitter: {url}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongólia" + }, + "OSM-PH-mailinglist": { + "name": "Lista de Discussão Talk-ph", + "description": "Uma lista de discussão para falar sobre o OpenStreetMap nas Filipinas" + }, + "at-mailinglist": { + "name": "Lista de Discussão Talk-at" + }, + "be-mailinglist": { + "name": "Lista de Discussão Talk-be" + }, + "talk-cz-mailinglist": { + "name": "Lista de Discussão Talk-cz" + }, + "dk-mailinglist": { + "name": "Lista de Discussão Talk-dk" + }, + "fr-mailinglist": { + "name": "Lista de Discussão Talk-fr", + "description": "Lista de Discussão Talk-fr" + }, + "de-berlin-mailinglist": { + "name": "Lista de Discussão Berlim" + }, + "de-mailinglist": { + "name": "Lista de Discussão Talk-de" + }, + "it-mailinglist": { + "name": "Lista de Discussão Talk-it" + }, + "talk-it-lazio": { + "extendedDescription": "Lista de Discussão para a área de Roma e Lázio" + }, + "OSM-ES-mailinglist": { + "name": "Lista de Discussão Talk-es" + }, + "gb-mailinglist": { + "name": "Lista de Discussão Talk-gb" + }, + "GeoPhilly": { + "name": "GeoPhilly" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC" + }, + "talk-au": { + "name": "Lista de Discussão Talk-au" + }, + "OSM-AR-mailinglist": { + "name": "Lista de Discussão Talk-ar" + }, + "OSM-BO-mailinglist": { + "name": "Lista de Discussão Talk-bo" + }, + "OSM-br-mailinglist": { + "name": "Lista de Discussão Talk-br", + "description": "Uma lista de discussão para falar sobre o OpenStreetMap no Brasil" + }, + "OSM-CL-mailinglist": { + "name": "Lista de Discussão Talk-cl" + }, + "OSM-CO-mailinglist": { + "name": "Lista de Discussão Talk-co" + }, + "OSM-PE-mailinglist": { + "name": "Lista de Discussão Talk-pe" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/ro.json b/vendor/assets/iD/iD/locales/ro.json index 12a296248..9af1da1d6 100644 --- a/vendor/assets/iD/iD/locales/ro.json +++ b/vendor/assets/iD/iD/locales/ro.json @@ -1,5 +1,9 @@ { "ro": { + "icons": { + "information": "informaÅ£ii", + "remove": "Şterge" + }, "modes": { "add_area": { "title": "Suprafață", @@ -197,6 +201,17 @@ } } }, + "restriction": { + "controls": { + "distance": "Distanţă", + "via": "Prin" + }, + "help": { + "from": "DIN", + "via": "PRIN", + "to": "LA" + } + }, "undo": { "tooltip": "Înapoi: {action}", "nothing": "Nu există nimic de refăcut." @@ -443,12 +458,7 @@ } }, "success": { - "edited_osm": "Ai editat OSM!", "just_edited": "Tocmai ai editat OpenStreetMap!", - "view_on_osm": "Vezi pe OSM", - "facebook": "Distribuie pe Facebook", - "twitter": "Distribuie pe Twitter", - "google": "Distribuie pe Google+", "help_link_text": "Detalii" }, "confirm": { @@ -601,7 +611,14 @@ } }, "welcome": { - "title": "Bun Venit" + "title": "Bun Venit", + "welcome": "Bine ați venit! Acest ghid vă va învăța elementele de bază ale editării pe OpenStreetMap.", + "practice": "Toate datele din acest ghid sunt doar pentru practicare, și orice modificări pe care le faceți în ghid nu vor fi salvate.", + "words": "Acest ghid va introduce câteva cuvinte și concepte noi. Când introducem un cuvânt nou, vom folosi *italics*.", + "mouse": "Puteți utiliza orice dispozitiv de intrare pentru a edita harta, însă acest ghid presupune că aveți un mouse cu butoane stânga și dreapta. ** Dacă doriți să atașați un mouse, faceți acest lucru acum, apoi apăsați pe OK. **", + "leftclick": "Când acest tutorial vă solicită să apăsați odată sau să apăsați de două ori, înseamnă cu butonul din stânga. Pe un trackpad este posibil să fie o atingere cu o singură apăsare sau cu un singur deget. ** Apăsați pe stânga de {num} ori. **", + "rightclick": "Uneori vă vom cere să apăsați dreapta. Acest lucru ar putea fi același lucru cu clic-control sau atingeți cu două degete pe un trackpad. Tastatura poate avea chiar și o tastă de \"meniu\" care funcționează ca și apăsat dreapta. ** Apăsați dreapta de {num} ori. **", + "chapters": "Până acum, este bine! Puteți utiliza butoanele de mai jos pentru a trece peste capitole în orice moment sau pentru a reporni un capitol dacă rămâneți blocat. Să începem! ** Apăsați pe '{next}' pentru a continua. **" }, "navigation": { "title": "Navigare" @@ -1315,7 +1332,6 @@ "label": "Tip" }, "phone": { - "label": "Telefon", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -1530,9 +1546,6 @@ "trees": { "label": "Copaci" }, - "vending": { - "label": "Tip de Bunuri" - }, "visibility": { "label": "Vizibilitate" }, @@ -4057,18 +4070,6 @@ "name": "Fără Întoarcere", "terms": "" }, - "type/restriction/only_left_turn": { - "name": "Întoarcere doar la Stânga", - "terms": "" - }, - "type/restriction/only_right_turn": { - "name": "Întoarcere doar la Dreapta", - "terms": "" - }, - "type/restriction/only_straight_on": { - "name": "Fără Întoarcere", - "terms": "" - }, "type/route": { "name": "Rută", "terms": "" @@ -4203,6 +4204,11 @@ "description": "Imagini de satelit DigitalGlobe standard.", "name": "Imagini DigitalGlobe Standard" }, + "DigitalGlobe-Standard-vintage": { + "attribution": { + "text": "Termeni & Feedback" + } + }, "MAPNIK": { "attribution": { "text": "© Contribuitori OpenStreetMap, CC-BY-SA" @@ -4278,7 +4284,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Basemap de Austria, bazat pe date ale guvernamentului.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -4339,9 +4344,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Plăci de hartă de Stamen Design, sub CC BY 3.0" - }, "name": "Teren Stamen" }, "tf-cycle": { @@ -4356,6 +4358,11 @@ }, "name": "Peisaj Thunderforest " } + }, + "community": { + "Bay-Area-OpenStreetMappers": { + "description": "Îmbunătățește OpenStreetMap în Bay Area" + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/ru.json b/vendor/assets/iD/iD/locales/ru.json index 2630a4b89..9c4b4bc04 100644 --- a/vendor/assets/iD/iD/locales/ru.json +++ b/vendor/assets/iD/iD/locales/ru.json @@ -1,30 +1,35 @@ { "ru": { + "icons": { + "information": "инфо", + "remove": "удалить", + "undo": "отмена" + }, "modes": { "add_area": { "title": "Полигон", "description": "Нанести на карту парки, здания, озёра и другие площадные объекты.", - "tail": "Щёлкните по карте, чтобы начать рисовать полигон: парк, озеро, здание и т. п." + "tail": "Нажмите на карту, чтобы начать рисовать полигон: парк, озеро, здание и т. п." }, "add_line": { "title": "Линия", "description": "Нанести на карту дороги, улицы, тропинки, каналы или другие линии.", - "tail": "Щёлкните по карте, чтобы начать рисовать дорогу, тропинку, ручей и т.п." + "tail": "Нажмите на карту, чтобы начать рисовать дорогу, тропинку, ручей и т.п." }, "add_point": { "title": "Точка", "description": "Нанести на карту рестораны, памятники, почтовые ящики или другие точки.", - "tail": "Щёлкните по карте, чтобы добавить точку." + "tail": "Нажмите на карту, чтобы добавить точку." }, "browse": { "title": "Обзор", "description": "Двигать и масштабировать карту." }, "draw_area": { - "tail": "Щёлкните, чтобы добавить точки в полигон. Чтобы завершить полигон, щёлкните по начальной точке." + "tail": "Продолжайте нажимать на карту, чтобы добавить точки в полигон. Чтобы завершить полигон, нажмите начальную точку." }, "draw_line": { - "tail": "Щёлкните по линии, чтобы добавить в неё точки. Щелчок по другой линии соединит их, а двойной щелчок завершит рисование." + "tail": "Нажмите на линию, чтобы добавить в неё точки. Нажатие на другой линии соединит их, а двойное нажатие завершит рисование." }, "drag_node": { "connected_to_hidden": "Невозможно отредактировать, имеется соединение со скрытым объектом." @@ -49,7 +54,7 @@ "title": "Продолжить", "description": "Продолжить эту линию.", "not_eligible": "Здесь нет линий, которые могут быть продолжены.", - "multiple": "Здесь могут быть продолжены несколько линий. Чтобы выбрать нужную, нажмите Shift и щёлкните по ней.", + "multiple": "Здесь могут быть продолжены несколько линий. Чтобы выбрать нужную, зажмите Shift и нажмите её.", "annotation": { "line": "Продлена линия.", "area": "Дополнен полигон." @@ -145,7 +150,9 @@ "vertex": "Одна линия присоединена к другой.", "line": "Линия соединена с другой линией.", "area": "Линия присоединена к полигону." - } + }, + "relation": "Эти объекты нельзя соединить, потому что у них конфликтуют роли в отношении.", + "restriction": "Эти объекты нельзя соединить, потому что это повредит отношение \"{relation}\"." }, "disconnect": { "title": "Разъединить", @@ -163,7 +170,8 @@ "annotation": "Объединено {n} объектов.", "not_eligible": "Эти объекты нельзя объединить.", "not_adjacent": "Эти объекты нельзя объединить, так как их конечные точки не соединены.", - "restriction": "Эти объекты нельзя объединить, так как хотя бы один из них — участник «{relation}» отношения.", + "restriction": "Эти объекты нельзя объединить, потому что это повредит отношение \"{relation}\".", + "relation": "Эти объекты нельзя объединить, потому что их роли в отношении конфликтуют друг с другом.", "incomplete_relation": "Эти объекты нельзя объединить, так как хотя бы один из них не был загружен целиком.", "conflicting_tags": "Эти объекты нельзя объединить, так как некоторые из их тегов содержат конфликтующие значения." }, @@ -322,9 +330,9 @@ "from_name": "{from} {fromName}", "from_name_to_name": "{from} {fromName} {to} {toName}", "via_names": "{via} {viaNames}", - "select_from": "Щёлкните для выбора {from} участка", - "select_from_name": "Щёлкните для выбора {from} {fromName}", - "toggle": "Щёлкните для \"{turn}\"" + "select_from": "Нажмите для выбора {from} участка", + "select_from_name": "Нажмите для выбора {from} {fromName}", + "toggle": "Нажмите для \"{turn}\"" } }, "undo": { @@ -363,7 +371,7 @@ "title": "Загрузить в OpenStreetMap", "upload_explanation": "Сделанные вами изменения появятся на всех картах, использующих данные OpenStreetMap.", "upload_explanation_with_user": "Изменения, сделанные вами под именем {user}, появятся на всех картах, использующих данные OpenStreetMap.", - "request_review": "Прошу кого-нибудь проверить мои правки.", + "request_review": "Прошу кого-нибудь проверить мои изменения.", "save": "Сохранить", "cancel": "Отменить", "changes": "Правок: {count}", @@ -402,6 +410,7 @@ "key": "H", "title": "История", "selected": "выбрано {n}", + "no_history": "История отсутствует (новый объект)", "version": "Версия", "last_edit": "Последняя правка", "edited_by": "Отредактировано", @@ -600,10 +609,10 @@ } }, "restore": { - "heading": "У вас есть несохранённые правки", - "description": "Имеются несохранённые правки с прошлого сеанса. Восстановить их?", - "restore": "Восстановить мои правки", - "reset": "Отменить мои правки" + "heading": "У вас есть несохранённые изменения", + "description": "Вы хотите восстановить несохранённые изменения с прошлого сеанса?", + "restore": "Восстановить мои изменения", + "reset": "Отменить мои изменения" }, "save": { "title": "Сохранить", @@ -614,7 +623,7 @@ "unknown_error_details": "Проверьте наличие подключения к Интернету.", "uploading": "Передать изменения на сервер OpenStreetMap...", "conflict_progress": "Проверка на наличие конфликов: {num} из {total}", - "unsaved_changes": "У вас есть несохранённые правки", + "unsaved_changes": "У вас есть несохранённые изменения", "conflict": { "header": "Разрешение конфликтов правок", "count": "Конфликт {num} из {total}", @@ -626,7 +635,7 @@ "delete": "Оставить удалённым", "download_changes": "Или скачать osmChange файл", "done": "Все конфликты устранены!", - "help": "Кто-то из участников OSM изменил те же объекты, что изменили вы.\nПросмотрите каждый конфликт в списке ниже и решите, оставить ваши\nправки или принять правки другого участника.\n" + "help": "Кто-то из участников OSM изменил те же объекты, что изменили вы.\nПросмотрите каждый конфликт в списке ниже и решите, оставить ваши\nизменения или принять правки другого участника.\n" } }, "merge_remote_changes": { @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": " OSM отредактирован!", "just_edited": "Вы только что отредактировали карту OpenStreetMap!", - "view_on_osm": "Посмотреть в OSM", - "facebook": "Поделиться на Facebook", - "twitter": "Поделиться через Twitter", - "google": "Поделиться через Google+", - "help_html": "Ваши изменения должны появиться на «Стандартном» слое в течение нескольких минут. Остальные слои и отдельные объекты могут занять больше времени.", + "thank_you": "Благодарим за улучшение карты.", + "thank_you_location": "Благодарим за улучшение карты в районе {where}.", + "help_html": "Сделанные вами изменения отобразятся в OpenStreetMap в течение нескольких минут. На другие карты они могут попасть не так быстро.", "help_link_text": "Подробности", - "help_link_url": "https://wiki.openstreetmap.org/wiki/RU:FAQ#.D0.AF_.D0.BD.D0.B0.D0.BD.D1.91.D1.81_.D0.BD.D0.B5.D1.81.D0.BA.D0.BE.D0.BB.D1.8C.D0.BA.D0.BE_.D0.BE.D0.B1.D1.8A.D0.B5.D0.BA.D1.82.D0.BE.D0.B2_.D0.BD.D0.B0_.D0.BA.D0.B0.D1.80.D1.82.D1.83.2C_.D0.BD.D0.BE_.D0.BE.D0.BD.D0.B8_.D0.BD.D0.B5_.D0.BE.D1.82.D0.BE.D0.B1.D1.80.D0.B0.D0.B6.D0.B0.D1.8E.D1.82.D1.81.D1.8F._.D0.9F.D0.BE.D1.87.D0.B5.D0.BC.D1.83.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/RU:FAQ#.D0.AF_.D0.BD.D0.B0.D0.BD.D1.91.D1.81_.D0.BD.D0.B5.D1.81.D0.BA.D0.BE.D0.BB.D1.8C.D0.BA.D0.BE_.D0.BE.D0.B1.D1.8A.D0.B5.D0.BA.D1.82.D0.BE.D0.B2_.D0.BD.D0.B0_.D0.BA.D0.B0.D1.80.D1.82.D1.83.2C_.D0.BD.D0.BE_.D0.BE.D0.BD.D0.B8_.D0.BD.D0.B5_.D0.BE.D1.82.D0.BE.D0.B1.D1.80.D0.B0.D0.B6.D0.B0.D1.8E.D1.82.D1.81.D1.8F._.D0.9F.D0.BE.D1.87.D0.B5.D0.BC.D1.83.3F", + "view_on_osm": "Посмотреть изменения на OSM", + "changeset_id": "Ваш пакет правок #: {changeset_id}", + "like_osm": "Нравится OpenStreetMap? Объединяйтесь с другими:", + "more": "Показать больше", + "events": "События", + "languages": "Яызки: {languages}", + "missing": "Чего-нибудь не хватает в списке?", + "tell_us": "Сообщите нам!" }, "confirm": { "okay": "OK", @@ -661,7 +675,7 @@ }, "source_switch": { "live": "основной", - "lose_changes": "У вас есть несохранённые правки. При смене сервера они будут удалены. Вы уверены, что хотите сменить сервер?", + "lose_changes": "У вас есть несохранённые изменения. При смене сервера они будут потеряны. Вы уверены, что хотите сменить сервер?", "dev": "тест" }, "version": { @@ -726,9 +740,9 @@ "title": "Справка", "welcome": "Добро пожаловать в редактор iD для [OpenStreetMap](https://www.openstreetmap.org/). С этим редактором вы можете обновлять OpenStreetMap прямо из вашего браузера.", "open_data_h": "Открытые данные", - "open_data": "Правки, что вы делает на этой карте будут видны всем, кто использует OpenStreetMap. Ваши правки могут основываться на личных знаниях, исследовании на местности, или изображениях, сделанных с воздуха, или с уличных фотографий. Использовать коммерческие источники, такие как Google Карты, 2GIS, Яндекса Карт (ЯК: за исключением панорам) [строго запрещено](https://www.openstreetmap.org/copyright).", + "open_data": "Ваши изменения на этой карте будут видны всем, кто использует OpenStreetMap. Ваши изменения могут основываться на личных знаниях, исследовании на местности, или изображениях, сделанных с воздуха, или с уличных фотографий. Использовать коммерческие источники, такие как Google Карты, 2GIS, Яндекса Карт (ЯК: за исключением панорам) [строго запрещено](https://www.openstreetmap.org/copyright).", "before_start_h": "Прежде чем начать", - "before_start": "Вам следует немного разобраться в OpenStreetMap и в этом редакторе перед тем как делать правки. iD содержит пошаговый учебник, чтобы обучить вас основам редактирование OpenStreetMap. Щёлкните \"Начать обучение\" на экране — это займет всего лишь 15 минут.", + "before_start": "Вам следует немного разобраться в OpenStreetMap и в этом редакторе перед тем, как начать вносить изменения. iD содержит пошаговый учебник, чтобы обучить вас основам редактирование OpenStreetMap. Выберите \"Начать обучение\" на экране — это займет всего лишь 15 минут.", "open_source_h": "Открытый исходный код", "open_source": "Редактор iD — коллективный проект с открытым исходным кодом, используемая здесь версия {version}. Исходный код достпуен [на GitHub](https://github.com/openstreetmap/iD).", "open_source_help": "Вы можете помочь iD [переводя его](https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating) или [сообщая об ошибках](https://github.com/openstreetmap/iD/issues)." @@ -737,7 +751,7 @@ "title": "Основное", "navigation_h": "Перемещение по карте", "navigation_drag": "Вы можете перетаскивать карту, удерживая нажатой {leftclick} левую кнопку мыши, передвигая саму мышь. Вы также можете использовать `↓`, `↑`, `←`, `→` клавиши со стрелками на клавиатуре.", - "navigation_zoom": "Вы можете приближать или отдалять при помощи прокурчивания колесика мышки или трекпада, или щёлкая по {plus} / {minus} кнопкам с краю от карты. Вы также можете использовать клавиши `+`, `-` на клавиатуре.", + "navigation_zoom": "Вы можете приближать или отдалять при помощи прокручивания колёсика мышки или трекпада, или нажимая кнопки {plus} / {minus} на краю карты. Вы также можете использовать клавиши `+`, `-` на клавиатуре.", "features_h": "Объекты на карте", "features": "Мы используем слово *объекты* для описания вещей, которые отображаются на карте, такие как: дороги, здания или точки интереса (POI). Всё что угодно из реального мира может быть отражено в виде объекта в OpenStreetMap. Объекты карты представлены на карте при помощи *точек*, *линий* или *полигонов*.", "nodes_ways": "В OpenStreetMap, точки иногда называют *узлами*, а линии и полигоны иногда называют *путями*." @@ -745,20 +759,20 @@ "editing": { "title": "Редактирование и Сохранение", "select_h": "Выбрать", - "select_left_click": "{leftclick} Щёлкните по объекту, чтобы выбрать его. Это подсветит объект и заставит его обводку пульсировать, боковая панель при этом отобразит подробности объекта, такие как его имя и адрес.", + "select_left_click": "{leftclick} выбирает объект. Это подсветит объект и заставит его обводку пульсировать, боковая панель при этом отобразит свойства объекта, такие, как его название и адрес.", "select_right_click": "{rightclick} Щелчок правой кнопкой на объекте отобразит меню редактирования, которое покажет доступные команды, такие как: разворот, перемещние и удаление.", "multiselect_h": "Мультивыбор", - "multiselect_shift_click": "`{shift}`+{leftclick} щёлкните для выбора нескольких объектов одновременно. Это облегчит перемещение или удаление нескольких предметов.", + "multiselect_shift_click": "`{shift}`+{leftclick} выбирает нескольких объектов одновременно. Это облегчит перемещение или удаление нескольких предметов.", "multiselect_lasso": "Ещё один способ выбрать несколько объектов — удерживая клавишу `{shift}`, зажать {leftclick} левую кнопку мыши и перемещать курсор, чтобы обрисовать выделение при помощи лассо. Все точки внутри области лассо станут выделенными.", "undo_redo_h": "Отмена и Повтор", - "undo_redo": "Ваши правки хранятся локально, в вашем браузере, пока вы не отрпавите их на сервер OpenStreetMap. Вы можете отменить правки, щёлкнув кнопку {undo} **Отмена**, и повторить — щёлкнув кнопку {redo} **Повтор**.", + "undo_redo": "Ваши изменения хранятся локально в вашем браузере, пока вы не отправите их на сервер OpenStreetMap. Вы можете их отменить, нажав на кнопку {undo} **Отмена**, или применить снова кнопкой {redo} **Повтор**.", "save_h": "Сохранить", - "save": "Щёлкните {save} **Сохранить**, чтобы закончить редактирование и отправить изменения в OpenStreetMap. Стоит не забывать сохранять свою работу регулярно!", + "save": "Нажмите {save} **Сохранить**, чтобы закончить редактирование и отправить изменения в OpenStreetMap. Стоит не забывать сохранять свою работу регулярно!", "save_validation": "На экране сохранения у вас будет возможность проверить то, что вы сделали. iD также проведёт некоторые простые проверки отсутствующей информации и может предоставить полезные подсказки и предупреждения, если что-то не так.", "upload_h": "Передать на сервер", - "upload": "Перед отправкой измеений вам нужно ввести [комментарий к пакету правок](https://wiki.openstreetmap.org/wiki/RU:Good_changeset_comments). Затем щёлкнуть **Сохранить** для отправки изменений в OpenStreetMap, где они объединятся с картой и будут видны всем.", + "upload": "Перед отправкой изменений вам нужно ввести [комментарий к пакету правок](https://wiki.openstreetmap.org/wiki/RU:Good_changeset_comments). Затем нажмите **Сохранить** для отправки изменений в OpenStreetMap, где они объединятся с картой и будут видны всем.", "backups_h": "Автоматические резервные копии", - "backups": "Если у вас не получается завершить правки в один присест, например ваш компьютер завис или вы закрыли вкладку в браузере, ваши правки останутся сохранёнными в хранилище вашего браузера. Вы можете вернуться позже (на том же браузере и компьютере), и iD предложит восстановить ваши труды.", + "backups": "Если у вас не получается завершить редактирование за один раз - например, ваш компьютер завис или вы закрыли вкладку в браузере - ваши правки останутся сохранёнными в хранилище вашего браузера. Вы можете вернуться позже (на том же браузере и компьютере), и iD предложит восстановить вашу работу.", "keyboard_h": "Горячие клавиши", "keyboard": "Вы можете посмотреть список горячих клавиш, нажав на клавишу `?`." }, @@ -767,12 +781,12 @@ "intro": "*Редактор объектов* находится сбоку от карты и позволяет вам видеть и редактировать всю информацию о выбранном объекте.", "definitions": "Верхняя область отображает тип объекта. Средняя — содержит *поля*, отображающие аттрибуты объекта, такие как его название или адрес.", "type_h": "Тип объекта", - "type": "Вы можете щёлкнуть по типу объекта, чтобы изменить тип у объекта на другой. Всё, что существует в реальном мире, может быть добавлено в OpenStreetMap, так что в списке тысячи типов объектов для выбора.", - "type_picker": "В списке типов отображаются наиболее распространённые типы объектов, такие как: парки, больницы, рестораны, дороги и здания. Вы можете использовать поиск, напечатав то, что хотите найти, в поле для поиска. Вы также можете щёлкнуть по иконке {inspect} **Инфо** рядом с типом объекта, чтобы узнать подробности о нём.", + "type": "Нажмите на тип объекта, чтобы изменить его на другой. Всё, что существует в реальном мире, может быть добавлено в OpenStreetMap, так что в списке могут быть тысячи типов объектов для выбора.", + "type_picker": "В списке типов отображаются наиболее распространённые типы объектов, такие, как парки, больницы, рестораны, дороги и здания. Вы можете использовать поиск, напечатав в поле поиска то, что хотите найти. Вы также можете нажать на значок {inspect} **Инфо** рядом с типом объекта, чтобы узнать его свойства.", "fields_h": "Поля", "fields_all_fields": "Область \"Все поля\" содержит все детали объекта, которые можно отредактировать. В OpenStreetMap, все поля необязательные, и это нормально оставить их пустыми, если вы неуверенны.", "fields_example": "У каждого типа объекта отображается свой набор полей. Например, у дорог отображается поле о дорожном покрытии и ограничении скорости, а у ресторанов могут отображаться поля о кухне, услугах и времени работы.", - "fields_add_field": "Вы можете щёлкнуть по выпадающему списку \"Добавить поле\", чтобы добавить ещё полей, таких как: описание, ссылка на Википедию, доступ маломобильным людям и многое другое.", + "fields_add_field": "Вы можете нажать на выпадающий список \"Добавить поле\", чтобы добавить ещё полей, таких, как описание, ссылка на Википедию, доступ маломобильным людям и других.", "tags_h": "Теги", "tags_all_tags": "Ниже области с полями вы можете развернуть область \"Все теги\", чтобы отредактировать *теги* OpenStreetMap для выбранного объекта. Каждый тег состоит из *ключа* и его *значения* (тег — это ключ=значение) — элементов данных, определяющих объекты, хранящиеся в OpenStreetMap.", "tags_resources": "Редактирование тегов объекта требует более серьёзного понимания OpenStreetMap. Вам следует ознакомиться с такими ресурсами как [OpenStreetMap вики](https://wiki.openstreetmap.org/wiki/Main_Page) или [Taginfo](https://taginfo.openstreetmap.org/), чтобы узнать больше о применяемых в OpenStreetMap практиках тегирования." @@ -781,37 +795,37 @@ "title": "Точки", "intro": "*Точки* могут использоваться для отображения таких объектов как: магазины, рестораны и монументы. Они отмечают определенное местоположение и описывают, что находится в нём.", "add_point_h": "Создание точек", - "add_point": "Чтобы добавить точку, щёлкинте по кнопку {point} **Точка** на панели инструментов вверху карту или нажмите клавишу `1` на клавиатуре. Это изменит курсор мыши на символ перекрестия.", - "add_point_finish": "Чтобы разместить новую точку на карте, поместите курсор мыши в место, где будет располагаться точка. Затем щёлкните левой кнопкой мыши {leftclick} или нажмите `Пробел`.", + "add_point": "Чтобы добавить точку, нажмите на кнопку {point} **Точка** на панели инструментов вверху карты или нажмите клавишу `1` на клавиатуре. Это изменит курсор мыши на символ перекрестия.", + "add_point_finish": "Чтобы разместить новую точку, поместите курсор мыши над нужным местом на карте. Затем нажмите левой кнопкой мыши {leftclick} или нажмите `Пробел`.", "move_point_h": "Перемещение точек", "move_point": "Чтобы переместить точку, поместите курсор мыши над точкой, зажмите левую кнопку мыши {leftclick} и перетащите точку на новое место.", "delete_point_h": "Удаление точек", "delete_point": "Нет ничего плохого в том, чтобы удалить объекты, которых не существует в реальном мире. Удаление объекта из OpenStreetMap удаляет его с общей карты, так что вам следует быть уверенным, действительно ли объекта больше не существует перед тем, как удалять его.", - "delete_point_command": "Чтобы удалить точку, щёлкните правой кнопкой {rightclick} по точке, чтобы выбрать её и отобразить меню редактирования. Затем используйте команду {delete} **Удалить**." + "delete_point_command": "Чтобы удалить точку, нажмите правой кнопкой {rightclick} на точку, чтобы выбрать её и отобразить меню редактирования. Затем выберите команду {delete} **Удалить**." }, "lines": { "title": "Линии", "intro": "*Линии* используются для отображения такие объектов как: автомобильные дороги, железные дорогие и реки. Линии должны быть нарисованы по центру объектов, которые они отражают.", "add_line_h": "Создание линий", "add_line": "Чтобы добавить линию, нажмите кнопку {line} **Линия** на панели инструментов вверху карты, или используйте сочетание клавиш `2`. Это изменит курсор мыши на символ перекрестия.", - "add_line_draw": "Теперь поместите курсор мыши туда, где линия должна начаться и щёлкните мышью {leftclick} или нажмите `Пробел`, чтобы разместить первую точку линии. Продолжайте добавлять точки, щёлкая мышью или нажимая `Пробел`. Во время рисования вы можете приближать или перемещаться по карте, чтобы добиться большей детальности.", - "add_line_finish": "Чтобы завершить линию, нажмите `{return}` или щёлкните ещё раз по последней точке.", + "add_line_draw": "Теперь поместите курсор мыши туда, где должна начаться линия и нажмите мышью {leftclick} или нажмите `Пробел` на клавиатуре, чтобы отметить первую точку линии. Продолжайте добавлять точки, нажимая на мышь или нажимая `Пробел`. Во время рисования вы можете приближать или перемещаться по карте, чтобы добиться большей точности.", + "add_line_finish": "Чтобы завершить линию, нажмите `{return}` или нажмите ещё раз на последнюю точку.", "modify_line_h": "Изменение линий", - "modify_line_dragnode": "Часто вы можете видеть, что форма линии неточна. Например, дорога не совпадает с тем, что видно на спутниковом снимке. Чтобы скорректровать форму линии для начала выберете линию, щёлкнув {leftclick} по ней. Точки на линии отобразятся как маленькие кружки. Их можно перетаскивать, чтобы сделать линию точнее.", - "modify_line_addnode": "Вы также можете создать новые точки на линии, или щёлкнув по ней дважды {leftclick}**x2**, или потянув за маленький треугольник посредине между точками.", + "modify_line_dragnode": "Часто вы можете видеть, что форма линии неточна. Например, дорога не совпадает с тем, что видно на спутниковом снимке. Чтобы скорректровать форму линии для начала выберете линию, нажав {leftclick} на неё. Точки на линии отобразятся как маленькие кружки. Их можно перетаскивать, чтобы сделать линию точнее.", + "modify_line_addnode": "Вы также можете создать новые точки на линии, или нажав на ней дважды {leftclick}**x2**, или потянув за маленький треугольник посредине между точками.", "connect_line_h": "Соединение линий", "connect_line": "Связность дорожного графа — важно и необходимо для получения информации о возможности проехать по дороге.", "connect_line_display": "Соединения дорог отображаются в виде серых кружков. Крайние точки линии отображаются более крупными белыми кружками, если они не соединены ни с чем другим.", "connect_line_drag": "Чтобы соединить линию с другим объектом, перетащите одну из точек линии на другой объект, пока оба объекта не притянутся друг к другу. Совет: вы можете удерживать клавишу `{alt}`, чтобы предотвратить присоединение точек к другим объектам.", "connect_line_tag": "Если вам известно, что в месте соединения есть светофор или пешеходный переход, вы можете обозначить их, выбрав точку соединения и используя редактор объектов для выбора подходящего типа объекта.", "disconnect_line_h": "Разъединение линий", - "disconnect_line_command": "Чтобы отсоединить дорогу от другого объекта щёлкните правой кнопкой мыши {rightclick} на точку присоединения и выберите команду **Разъединить** {disconnect} в меню редактирования.", + "disconnect_line_command": "Чтобы отсоединить дорогу от другого объекта, нажмите правой кнопкой мыши {rightclick} на точку присоединения и выберите команду **Разъединить** {disconnect} в меню редактирования.", "move_line_h": "Перемещение линий", - "move_line_command": "Для перемещения линии целиком щёлкните правой кнопкой {rightclick} на линию и выберетие команду **Переместить** {move} в меню редактирования. Затем переместите курсор и щёлкните левой кнопкой {leftclick}, чтобы разместить линию в новом месте.", + "move_line_command": "Для перемещения линии целиком, нажмите правой кнопкой {rightclick} на линию и выберетие команду **Переместить** {move} в меню редактирования. Затем переместите курсор и нажмите левой кнопкой {leftclick}, чтобы разместить линию в новом месте.", "move_line_connected": "Линии, присоединённые к другим объектам, останутся присоединёнными к ним, когда вы перемещаете линию на новое место. iD может предотвратить перемещение линии через другую присоединённую линию.", "delete_line_h": "Удаление линий", "delete_line": "Если линия полностью неверна, например дорога, не существующая в реальном мире, такую линию можно смело удалять. Но будьте осторожны, когда удаляете объекты: спутниковые снимки могут быть устарелые, и дорога, которая выглядит неправильной, может быть попросту построена недавно.", - "delete_line_command": "Чтобы удалить линию щёлкните правой кнопкой {rightclick} по линии, чтобы выбрать её и отобразить меню редактирования, затем выберите команду **Удалить** {delete}." + "delete_line_command": "Чтобы удалить линию, нажмите правой кнопкой {rightclick} по линии, чтобы выбрать её и отобразить меню редактирования, затем выберите команду **Удалить** {delete}." }, "areas": { "title": "Полигоны", @@ -819,67 +833,67 @@ "point_or_area_h": "Точки или полигоны?", "point_or_area": "Существует множество объектов, которые можно описать и при помощи точек и при помощи полигонов. Здания следует отрисовывать при помощи полигона, если это возможно сделать. Кафе, офисы и прочие объекты внутри здания стоит отметить при помощи точек, расположенных внутри полигона здания.", "add_area_h": "Добавление полигонов", - "add_area_command": "Чтобы добавить полигон щёлкните по кнопке {area} **Полигон** на панели инструментов вверху карты или нажмите клавишу `3`. Курсор приобретёт вид перекрестия.", - "add_area_draw": "Затем разместите курсор мыши на углу объекта и щёлкните левой кнопкой {leftclick} или нажмите `Пробел`, чтобы начать расставлять точки по периметру области. Продолжайте добавлять новые точки, щёлкая левой кнопкой или нажимая `Пробел`. Во время рисования, вы можете приближать или перемещать карту, чтобы добиться большей детализованности.", - "add_area_finish": "Чтобы завершить полигон, нажмите `{return}` или щёлкните ещё раз по первой или последней точке.", + "add_area_command": "Чтобы добавить полигон, нажмите на кнопку {area} **Полигон** на панели инструментов вверху карты или нажмите клавишу `3`. Курсор приобретёт вид перекрестия.", + "add_area_draw": "Затем разместите курсор мыши на углу объекта и нажмите левой кнопкой {leftclick} или `Пробел` на клавиатуре, чтобы начать расставлять точки по периметру области. Продолжайте добавлять новые точки, нажимая левой кнопкой мыши или `Пробел`. Во время рисования вы можете приближать или перемещать карту, чтобы добиться большей точности.", + "add_area_finish": "Чтобы завершить полигон, нажмите `{return}` или нажмите ещё раз на первую или последнюю точку.", "square_area_h": "Спрямление углов", - "square_area_command": "Многие полигоны, такие как здания, имеют прямые углы. Чтобы сделать углыми полигона прямыми щёлкните правой кнопкой {rightclick} по краю полигона и выберите команду **Спрямить углы** {orthogonalize} в меню редактирования.", + "square_area_command": "Многие полигоны, такие как здания, имеют прямые углы. Чтобы сделать углыми полигона прямыми, нажмите правой кнопкой {rightclick} на край полигона и выберите команду **Спрямить углы** {orthogonalize} в меню редактирования.", "modify_area_h": "Изменение полигонов", - "modify_area_dragnode": "Часто вы будете замечать полигоны, форма которых не верна. Например, здание не соответствует тому, что на спутниковом снимке. Чтобы скорректировать форму полигона сначала выделите его, щёлкнув по нему {leftclick}. Все точки, принадлежащие полигону, станут отражены небольшими кружчкми. Вы можете перетащить точки в более подходящие места.", - "modify_area_addnode": "Вы также можете создать новые точки в полигоне, щёлкнув дважды {leftclick}**x2** по краю полигона или потянув за маленький треугольник посредине между точками.", + "modify_area_dragnode": "Часто вы будете замечать полигоны, форма которых неверна. Например, здание не соответствует тому, что видно на спутниковом снимке. Чтобы скорректировать форму полигона, сначала выделите его, нажав на нём {leftclick}. Все точки, принадлежащие полигону, будут отображены небольшими кружочками. Вы можете перетащить их в более подходящие места.", + "modify_area_addnode": "Вы также можете создать новые точки в полигоне, нажав дважды {leftclick}**x2** на край полигона или потянув за маленький треугольник посредине между точками.", "delete_area_h": "Удаление полигонов", "delete_area": "Если полигон неверен полностью, например, здания больше не существует в реальном мире, такой полигон можно удалить. Но будьте осторожны, удаляя объекты — спутниковое изображение может быть устарелым, а здание, казавшееся неверным, недавно построено.", - "delete_area_command": "Чтобы удалить полигон, щёлкните правой кнопкой {rightclick} по полигону, чтобы выбрать его и отобразить меню редактирования, затем примените команду **Удалить** {delete}." + "delete_area_command": "Чтобы удалить полигон, нажмите правой кнопкой {rightclick} по полигону, чтобы выбрать его и отобразить меню редактирования, затем выберите команду **Удалить** {delete}." }, "relations": { "title": "Отношения", "intro": "*Отношение* — это специальный тип объекта OpenStreetMap для объединения других объектов. Объекты, входящие в отношение, называются *участниками отношения*, а каждый из участников отношения может иметь *роль* в отношении.", "edit_relation_h": "Редактирование отношений", - "edit_relation": "В нижней части редактора объектов вы можете раскрыть область \"Все отношения\", чтобы посмотреть, является ли выбранный объект участником какого-либо отношения. Вы можете щёлкнуть по отношению, чтобы выбрать и отредактировать его.", - "edit_relation_add": "Чтобы добавить объект к отношению, выберите объект, затем щёлкните по кнопке {plus} в разделе \"Все отношения\" редактора объектов. Вы можете выбрать из списка ближайщих к выбранному объекту отношений или же вариант \"Новое отношение...\".", - "edit_relation_delete": "Вы можете щёлкнуть по кнопке **Удалить** {delete}, чтобы удалить выбранный объект из отношения. Если из отношения удалить всех его участников, само отношение автоматически удалится.", + "edit_relation": "В нижней части редактора объектов вы можете раскрыть область \"Все отношения\", чтобы посмотреть, является ли выбранный объект участником какого-либо отношения. Вы можете нажать на отношение, чтобы выбрать и отредактировать его.", + "edit_relation_add": "Чтобы добавить объект к отношению, выберите объект, затем нажмите на кнопку {plus} в разделе \"Все отношения\" редактора объектов. Вы можете выбрать нужное из списка ближайщих к выбранному объекту отношений или создать новое пунктом \"Новое отношение...\".", + "edit_relation_delete": "Вы можете нажать на кнопку **Удалить** {delete}, чтобы удалить выбранный объект из отношения. Если из отношения удалить всех его участников, само отношение тоже автоматически удалится.", "maintain_relation_h": "Поддерживание отношений в порядке", "maintain_relation": "В большинстве случаев iD будет поддерживать в порядке отношения автоматически, пока вы редактируете. Но вам стоит быть внимательным, когда вы заменяете объекты, которые могут быть участинками отношений. Например, вы удаляете участок дороги и рисуете его заново взамен удаленного, в таком случае вам следует добавить вновь отрисованный участок дороги к тем же отношениям, в которых числился удалённый (маршруты, ограничения на поворт и тому подобное).", "relation_types_h": "Типы отношений", "multipolygon_h": "Мультиполигоны", "multipolygon": "Отношение типа *мультиполигон* — это объединение из одного и более *внешнего* объекта и одного и более внутреннего объекта. Внешние объекты определяют внешние границы мультиполигона, а внутренние объекты определяют под-области или дырки, вырезанные внутри мультиполигона.", - "multipolygon_create": "Чтобы создать мультиполигон, например здание с дыркой в нём, нарисуйте внешнюю границу как полигон, а внутреннюю границу как линию или как полигон с другим типом. Затем щёлкните `{shift}`+{leftclick}, чтобы выбрать сразу оба объекта, щёлкните правой кнопкой {rightclick} чтобы отобразить меню редактирования и выберите команду **Объединить** {merge}.", + "multipolygon_create": "Чтобы создать мультиполигон, например, здание с дыркой в нём, нарисуйте внешнюю границу как полигон, а внутреннюю границу как линию, или как полигон с другим типом. Затем нажмите `{shift}`+{leftclick}, чтобы выбрать сразу оба этих объекта, нажмите правой кнопкой {rightclick}, чтобы отобразить меню редактирования и выберите команду **Объединить** {merge}.", "multipolygon_merge": "Объединение несколько линий или полигонов приведёт к созданию нового мультиполигона со всеми выделенными объектами в виде его участников. iD расставит роли inner и outer автоматически, основываясь на том, какой объект внутри какого.", "turn_restriction_h": "Запрет манёвров", "turn_restriction": "Отношение *запрет манёвра* — это группа из нескольких пересекающихся участков (сегментов) дорог. Запрет манёвров состоит из *from* участка, *via* точки пересечения дорог, и *to* участка дороги.", "turn_restriction_field": "Чтобы отредактировать запрет манёвров, выберите точку, в которой пересекаются две и более автомобильные дороги. Редактор объектов отобразит особое поле \"Запрет манёвров\", содержащее модель перекрёстка.", - "turn_restriction_editing": "В поле \"Запрет манёвров\" щёлкните, чтобы выборать \"from\" дорогу, в модели отобразится, доступен ли манёвр или нет для любой из \"to\" дороги. Вы можете щёлкнуть по уконке манёвра, чтобы изменять состояние запрета между \"разрешено\" и \"запрещено\". iD автоматически создаст отношения и укажет в них роли from, via и to, основываясь на ваших действиях.", + "turn_restriction_editing": "Нажмите на поле \"Запрет манёвров\", чтобы выбрать дорогу \"from\" (\"откуда\"), в окне отобразится, доступен ли манёвр или нет для любой дороги \"to\" (\"куда\"). Вы можете нажимать на значок манёвра, чтобы изменять состояние запрета между \"разрешено\" и \"запрещено\". iD автоматически создаст отношения и укажет в них роли from, via и to, основываясь на ваших действиях.", "route_h": "Маршруты", "route": "Отношение *маршрут* — группа из одного и более линейного объекта, образующих вместе маршрутную сеть, такую как: автобусный маршрут, железнодорожный маршрут или автомобильный маршрут.", - "route_add": "Чтобы добавить объект к отношению маршрута, выберите объект и прокрутите вниз до секции \"Все отношения\" в редакторе объектов, затем щёлкните по {plus} кнопке добавить, чтобы добавить выбранный объект к ближайшим существующим или новому отношению.", + "route_add": "Чтобы добавить объект к отношению маршрута, выберите объект и прокрутите вниз до секции \"Все отношения\" в редакторе объектов, затем нажмите на кнопку {plus}, чтобы добавить выбранный объект к ближайшим существующим или новому отношению.", "boundary_h": "Границы", "boundary": "Отношение *граница* — это группа из одного и более линейного объекта, которые вместе образуют административную границу.", - "boundary_add": "Чтобы добавить объект к отношению границы, выберите объект и прокрутите вниз до секции \"Все отношения\" в редакторе объектов, затем щёлкните по {plus} кнопке добавить, чтобы добавить выбранный объект к ближайшим существующим или новому отношению." + "boundary_add": "Чтобы добавить объект к отношению границы, выберите объект и прокрутите вниз до секции \"Все отношения\" в редакторе объектов, затем нажмите на кнопку {plus}, чтобы добавить выбранный объект к ближайшим существующим или новому отношению." }, "imagery": { "title": "Фоновые изображения", "intro": "Фоновые изображения, отображаемые под картографическими данными, — важный источник для картографирования. Этими изображениями могут быть снимки с воздуха, собранные спутниками, самолетами или беспилотными летательными аппаратами, или это может быть отсканированная историческая карта или любой другой свободно распростаняемый источник информации.", "sources_h": "Источники подложек", - "choosing": "Чтобы узнать, какие подложки доступны для редактирования, щёлкните на {layers} **Настройка фонового изображения** кнопку сбоку от карты.", + "choosing": "Чтобы узнать, какие подложки доступны для редактирования, нажмите на кнопку {layers} **Настройка фонового изображения** сбоку от карты.", "sources": "По умолчанию фоновым изображением является слой спутниковых снимков из [Карт Bing](https://www.bing.com/maps/). В зависимости от того, где вы редактируете, могут быть доступны другие источники подложек. Некоторые из них могут оказаться новее или иметь более высокое разрешение, так что всегда полезно проверить и посмотреть, какая из подложек наиболее подходит для обрисовки.", "offsets_h": "Настройка смещения подложки", "offset": "Подложка часто имеет небольшой сдвиг (смещение) относительно объектов в реальности. Если вы видите множество дорог или зданий, сдвинутых относительно изображения с подложки, возможно это потому что изображение некорректно. В таком случае не сдвигайте отрисованные объекты под изображение с подложки. Вместо этого, убедитесь, что нет необходимости выставить смещение спутниковому снимку. Скорректировать фоновое изображение можно, раскрыв область \"Установка смещения слоя\" внизу панели настройки фоновых изображений.", - "offset_change": "Щёлкните на маленькие треугольники, чтобы скорректировать сдвиг подложики небольшими шагами, или зажмите левую кнопку мыши и перетаскивайте внутри серого квадрата, чтобы сдвинуть подложку до сопоставления с данными." + "offset_change": "Нажмите на маленькие треугольники, чтобы скорректировать сдвиг подложики небольшими шагами, или зажмите левую кнопку мыши и перетаскивайте внутри серого квадрата, чтобы сдвинуть подложку до сопоставления с данными." }, "streetlevel": { "title": "Панорамы улиц", "intro": "Уличные панорамы полезны для картографирования дорожных знаков, бизнесов и других подробностей, которых не видно на спутниковых снимках и снимках с воздуха. Редактор iD поддерживает панорамы из [Mapillary](https://www.mapillary.com) и [OpenStreetCam](https://www.openstreetcam.org).", "using_h": "Использование панорам улиц", - "using": "Для использования уличных панорам для картографирования щёлкните по панели {data} **Данные карты** сбоку от карты, чтобы включить или выключить слой с доступными фотографиями.", + "using": "Для использования уличных панорам для картографирования нажмите на панель {data} **Данные карты** сбоку от карты, чтобы включить или выключить слой с доступными фотографиями.", "photos": "Когда включён, слой фото отображает линию вдоль череды фотографий. На крупных зумах видны круглые отметки в месте каждой фотографии, а на ещё более крупных зумах — индикатор в виде конуса, отображающий направление камеры во время съёмки.", - "viewer": "Когда вы щёлкните по местоположению фотографии, в нижнем углу карты откроется просмотрщик фотографий. Просмотрщик фотографий содержит элементы управления, чтобы перемещаться вперёд и назад по последовательности изображений. Он также отображает имя пользователя человека, сделавшего фото, дату фотографии и ссылку на фотографию на оригинальном веб-сайте." + "viewer": "Когда вы нажмёте на местоположение фотографии, в нижнем углу карты откроется просмотрщик фотографий. Просмотр фотографий содержит элементы управления, чтобы перемещаться вперёд и назад по последовательности изображений. Он также отображает имя пользователя, сделавшего фото, дату и ссылку на фотографию на оригинальном веб-сайте." }, "gps": { "title": "GPS треки", "intro": "Собранные GPS треки — ценный источник данных для OpenStreetMap. Данные редактор поддерживает *.gpx*, *.geojson* и *.kml* файлы с вашего компьютера. Вы можете записывать GPS треки при помощи смартфона, спортивных часов или любого другого GPS устройства.", "survey": "Об информации о тому, как проводить GPS разведку, прочтите [Mapping with a smartphone, GPS, or paper](http://learnosm.org/en/mobile-mapping/).", "using_h": "Использование GPS треков", - "using": "Для использование GPS треков с целью картографирования перетащите файл с треком в окно редактора карты. Если файл подходящий, трек будет отображен на карте яркой фиолетовой линией. Щёлкните на панель {data} **Данные карты** сбоку от карты, чтобы выключить, выключить или приблизить ваши GPS данные.", + "using": "Для использование GPS треков с целью картографирования перетащите файл с треком в окно редактора карты. Если файл подходящий, трек будет отображен на карте яркой фиолетовой линией. Нажмите на панель {data} **Данные карты** сбоку от карты, чтобы выключить, выключить или приблизить ваши GPS данные.", "tracing": "GPS трек не передаётся в OpenStreetMap. Лучший способ использовать его — это отрисовать по нему карту, используя его как подсказку для новых объектов, что вы добавляете.", "upload": "Вы также можете [загрузить ваши GPS треки в OpenStreetMap](https://www.openstreetmap.org/trace/create), чтобы и другие участники смогли ими пользоваться." }, @@ -905,8 +919,8 @@ }, "modifying": { "title": "Редактирование", - "about": "Для редактирования запрета манёвров сперва щёлкните по любому начальному **ИЗ** участку, чтобы выбрать его. Выбранный участок начнёт пульсировать, и все возможные **В** направления обозначатся символами поворотов.", - "indicators": "Затем щёлкниет по символову поворота, чтобы переключить его между \"Разрешено\", \"Запрещено\" и \"Только\".", + "about": "Для редактирования запрета манёвров сперва нажмите на любой начальный участок **ИЗ**, чтобы выбрать его. Выбранный участок начнёт пульсировать, и все возможные направления **В** обозначатся символами поворотов.", + "indicators": "Затем нажмите на символ поворота, чтобы переключить его между \"Разрешено\", \"Запрещено\" или \"Только\".", "allow_turn": "{allowTurn} **В разрешено**", "restrict_turn": "{restrictTurn} **В запрещено**", "only_turn": "{onlyTurn} **В только**" @@ -1053,9 +1067,9 @@ "practice": "Все данные в течение этого обучения предназначены только для тренировки. Никакие изменения не будут сохранены.", "words": "В процессе обучения мы введём новые слова и термины. Все новые слова будут отмечены *курсивом*.", "mouse": "Вы можете редактировать карту на любом устройстве. Но для данного обучения у Вас должна быть мышка с двумя кнопками. **Если хотите подключить мышь, то сделайте это сейчас и нажмите OK.**", - "leftclick": "Когда в процессе обучения Вас попросят щёлкнуть или щёлкнуть дважды, мы имеем в виду нажать левую кнопку мыши. При использовании сенсорной панели (тачпада) это означает одиночное нажатие или касание одним пальцем. **Щёлкните {num} раз(а).**", - "rightclick": "Иногда мы попросим Вас нажать правую кнопку мыши. Это может означать щелчок с зажатой клавишей Control или касание сенсорной панели двумя пальцами. Возможно у Вас на клавиатуре есть кнопка 'Menu', которая работает как щелчок правой кнопкой мышки. **Щёлкните правой кнопкой {num} раз(а).**", - "chapters": "Пока всё хорошо! Вы можете использовать кнопки ниже, чтобы в любой момент пропустить главы обучения или начать главу заново, если Вы столкнулись с проблемой. Начнём! **Щёлкните '{next}' чтобы продолжить.**" + "leftclick": "Когда в процессе обучения Вас попросят нажать или нажать дважды, имеется в виду нажать левую кнопку мыши. При использовании сенсорной панели (тачпада) это означает одиночное нажатие или касание одним пальцем. **Нажмите {num} раз(а).**", + "rightclick": "Иногда мы попросим Вас нажать правую кнопку мыши. Это может означать нажатие с зажатой клавишей Control или касание сенсорной панели двумя пальцами. Возможно, у Вас на клавиатуре есть кнопка 'Menu', которая работает как нажатие правой кнопкой мышки. **Нажмите правой кнопкой {num} раз(а).**", + "chapters": "Пока всё хорошо! Вы можете использовать кнопки ниже, чтобы в любой момент пропустить главы обучения или начать главу заново, если Вы столкнулись с проблемой. Начнём! **Нажмите '{next}' чтобы продолжить.**" }, "navigation": { "title": "Перемещение", @@ -1074,7 +1088,7 @@ "choose_street": "**Выберите {name} из списка чтобы выбрать его.**", "selected_street": "Отлично! Теперь {name} выбрана.", "editor_street": "Поля, отображаемые для улицы, отличаются от полей показываемых для здания администрации.{br}Для выбранной улицы редактор объектов покажет поля, характерные для дорог: '{field1}' и '{field2}'. **Закройте редактор объектов, нажав escape или кнопку {button}.**", - "play": "Попробуйте подвигать карту и щёлкнуть на какие-нибудь другие объекты, чтобы узнать, какие виды объектов могут быть добавлены на OpenStreetMap. **Когда вы будете готовы перейти к следующей главе, нажмите '{next}'.**" + "play": "Попробуйте подвигать карту и нажать на какие-нибудь другие объекты, чтобы узнать, какие виды объектов могут быть добавлены на OpenStreetMap. **Когда вы будете готовы перейти к следующей главе, нажмите '{next}'.**" }, "points": { "title": "Точки", @@ -1084,11 +1098,11 @@ "choose_cafe": "**Выберите {preset} из списка.**", "feature_editor": "Вы пометили точку как кафе. Используя редактор объектов, можно добавить больше сведений об этом кафе.", "add_name": "В OpenStreetMap все поля необязательные, и это нормально оставить поле пустым, если вы не уверены в его значении.{br}Предположим, у вас есть местное знание об этом кафе и вы знаете его название. **Добавьте название этого кафе.**", - "add_close": "Редактор объектов запомнит все правки автоматически. **Когда вы добавили имя, нажмите Esc, Ввод, или кнопку {button} чтобы закрыть редактор объектов.**", + "add_close": "Редактор объектов запоминает все изменения автоматически. **Когда вы добавили имя, нажмите Esc, Ввод, или кнопку {button} чтобы закрыть редактор объектов.**", "reselect": "Часто точки уже нарисованы на карте, но неточно или с ошибками. Мы можем их поправить. **Нажмите на точку кафе, которые вы создали.**", "update": "Давайте добавим значений свойствам этого кафе. Заполните его название, укажите кухню или добавьте адрес. **Заполните свойства кафе.**", "update_close": "**Когда вы закончите обновлять кафе, нажмите Esc, Ввод, или кнопку {button} чтобы закрыть редактор объектов.**", - "rightclick": "Вы можете щёлкнуть правой кнопкой мыши по любому объекту, чтобы увидеть *меню редактирования*, в котором показан список операций редактирования, которые могут быть выполнены. **Щёлкните правой кнопкой мыши, чтобы выбрать созданную вами точку и показать меню редактирования.**", + "rightclick": "Вы можете нажать правой кнопкой мыши по любому объекту, чтобы увидеть *меню редактирования*, в котором показан список операций, которые могут быть выполнены. **Нажмите правой кнопкой мыши, чтобы выбрать созданную вами точку и показать меню редактирования.**", "delete": "Не бойтесь удалять объекты, которых нет в реальном мире.{br}Удаление объекта с OpenStreetMap удаляет его с карты, которой все пользуются, поэтому вы должны убедиться, что объект действительно исчез, прежде чем удалить его. **Нажмите кнопку {button}, чтобы удалить точку.**", "undo": "Вы всегда можете отменить все изменения перед сохранением Ваших правок в OpenStreetMap. **Нажмите кнопку {button} для отмены удаления точки **.", "play": "Теперь, когда вы знаете, как добавлять и править точки, попробуйте попрактиковаться и создать ещё немного точек! **Когда вы будете готовы перейти к следующей главе, нажмите '{next}'.**" @@ -1096,9 +1110,9 @@ "areas": { "title": "Полигоны", "add_playground": "*Полигоны* используются для отображения границ объектов, таких как: озёра, здания и жилые зоны.{br}Их также можно применять для более детального отображения объектов, которые обычно указываются точками. **Нажмите кнопку Полигон {button} для создания нового полигона.**", - "start_playground": "Давайте добавим игровую площадку на карту в виде полигона. Полигон рисуется размещением *точек* по периметру объекта. **Щёлкните мышью или нажмите пробел для размещения первой точки на одном из углов площадки.**", + "start_playground": "Давайте добавим игровую площадку на карту в виде полигона. Полигон рисуется размещением *точек* по периметру объекта. **Нажмите на мышь или нажмите Пробел на клавиатуре для размещения первой точки на одном из углов площадки.**", "continue_playground": "Продолжайте обводить полигон, размещая узлы вдоль краёв детской площадки. Это ничего, если вы соедините полигон к уже нарисованным пешеходным дорожкам.{br}Совет: вы можете держать клавишу '{alt}', чтобы предотвратить привязку к другим элементам. **Продолжайте обводить полигон детской площадки.**", - "finish_playground": "Завершите полигон, нажав enter или щёлкнув на первом или последнем узле. **Завершите обводку полигона детской площадки.**", + "finish_playground": "Завершите полигон, нажав Enter на клавиатуре или мышью на первой или последней точке. **Завершите контур полигона детской площадки.**", "search_playground": "**Искать '{preset}'.**", "choose_playground": "**Выберите {preset} из списка.**", "add_field": "Эта детская площадка не имеет официального названия, поэтому мы не будем добавлять ничего в поле Название.{br}Вместо этого давайте добавим больше подробностей об этой детской площадке в поле Описание. **Откройте список «Добавить поле».**", @@ -1110,54 +1124,54 @@ "lines": { "title": "Линии", "add_line": "*Линии* используются для обозначения таких объектов как дороги, железные дороги и реки. **Нажми {button} кнопку Линия, чтобы добавить новую линию.**", - "start_line": "Вот дорога, которая не нарисована. Давайте добавим её!{br}В OpenStreetMap линии должны быть нарисованы по центру дороги. Вы можете перетаскивать и масштабировать карту во время рисования, если это необходимо. **Начните новую линию, щёлкнув по верхнему концу этой отсутствующей дороги.**", - "intersect": "Щёлкните или нажмите пробел для добавления сегментов к линии.{br}Дороги, и многие другие типы линий являются частью более крупной сети. Важно, чтобы эти линии были соединены в правильном порядке для работы приложений навигации. **Щёлкните на {name} для создания точки пересечения двух линий.**", + "start_line": "Вот дорога, которая ещё не нарисована. Давайте добавим её!{br}В OpenStreetMap линии должны быть нарисованы по центру дороги. Вы можете перетаскивать и масштабировать карту во время рисования, если это необходимо. **Начните новую линию, нажав на верхний конец этой отсутствующей дороги.**", + "intersect": "Нажмите на мышь или нажмите Пробел на клавиатуре для добавления сегментов к линии.{br}Дороги, и многие другие типы линий являются частью более крупной сети. Важно, чтобы эти линии были соединены в правильном порядке для работы приложений навигации. **Нажмите на {name} для создания точки пересечения двух линий.**", "retry_intersect": "Эта дорога должна пересекаться с {name}. Попробуй ещё раз!", - "continue_line": "Продолжайте рисовать линию для новой дороги. Помните, что Вы можете при необходимости перетаскивать и изменять масштаб карты.{br}Когда закончите рисовать, щёлкните на последнем сегменте снова. **Завершить рисование дороги.**", + "continue_line": "Продолжайте рисовать линию для новой дороги. Помните, что Вы можете при необходимости перетаскивать и изменять масштаб карты.{br}Когда закончите рисовать, снова нажмите на последний сегмент. **Завершить рисование дороги.**", "choose_category_road": "**Выберите {category} из списка.**", "choose_preset_residential": "Существует много различных типов дорог, но в данном случае это дорога вдоль жилых зон. **Выберите тип дороги «{preset}»**", - "retry_preset_residential": "Вы не выбрали тип {preset}. **Щёлкните здесь, чтобы выбрать заново.**", - "name_road": "**Дайте этой дороге название, затем нажмите escape, enter или щёлкните кнопку {button}, чтобы закрыть редактор объектов.**", + "retry_preset_residential": "Вы не выбрали тип {preset}. **Нажмите здесь, чтобы выбрать заново.**", + "name_road": "**Дайте этой дороге название, затем нажмите Escape, Enter или кнопку {button}, чтобы закрыть редактор объектов.**", "did_name_road": "Замечательно! Теперь мы изучим как изменить форму линии.", "update_line": "Иногда вам потребуется изменить форму существующей линии. Вот эта дорога явно выглядит не совсем правильно.", "add_node": "Мы можем ещё добавить точек к этой линии, чтобы улучшить её форму. Один из способов добавить точку — это двойной щелчок по линии там, где вы хотите её добавить. **Двойной щелчок по линии, чтобы добавить новую точку.**", - "start_drag_endpoint": "Когда линия выделена, можно перетаскивать любую её точку, щёлкнув и удерживая левую кнопку мыши. **Перетащите конечную точку к месту, где эти дороги должны пересекаться.**", + "start_drag_endpoint": "Когда линия выделена, можно перетаскивать любую её точку, нажав и удерживая левую кнопку мыши. **Перетащите конечную точку к месту, где эти дороги должны пересекаться.**", "finish_drag_endpoint": "Вот неплохое место. **Отпустите левую кнопку мыши чтобы завершить перемещение.**", "start_drag_midpoint": "Маленькие треугольники нарисованы *посредине* между точками. Другой способ создать новую точку — это перетащить точку посредине сегмента на новую позицию. **Перетащите треугольник посредине сегмента для создания новой точки вдоль изгиба дороги.**", "continue_drag_midpoint": "Линия выглядит намного лучше! Продолжайте уточнять линию двойным щелчком или перетаскиванием серединных точек, пока кривая не совпадёт с формой дороги. **Когда вы будете удовлетворены формой линии, нажмите ОК**", "delete_lines": "Удалять линии дорог, которых не существуют в реальным мире — нормально.{br}Здесь вы видите пример того, что город планировал {street}, но так и не построил. Мы можем улучшить эту часть карты, удалив лишние линии.", "rightclick_intersection": "Последняя построенная улица — {street1}, поэтому мы *разрежем* {street2} в точке пересечения и удалим всё сверху от неё. **Нажмите правой кнопкой на точке пересечения.**", - "split_intersection": "**Щёлкните кнопку {button} чтобы разрезать {street}.**", - "retry_split": "Вы не щёлкнули кнопку «Разрезать». Попробуйте снова.", - "did_split_multi": "Отличная работа! {street1} теперь разрезана на две части. Верхнюю часть можно удалить. **Щёлкните на верхней части {street2}, чтобы выделить её.**", - "did_split_single": "**Щёлкните на верхней части {street2} чтобы выделить её.**", - "multi_select": "Линия {selected} теперь выбрана. Давайте выделим ещё и {other1}. Вы можете выделять несколько линий щелчком с нажатой клавишей Shift. **Нажмите Shift и щёлкните на {other2}.**", + "split_intersection": "**Нажмите кнопку {button} чтобы разрезать {street}.**", + "retry_split": "Вы не нажали на кнопку «Разрезать». Попробуйте снова.", + "did_split_multi": "Отличная работа! {street1} теперь разрезана на две части. Верхнюю часть можно удалить. **Нажмите на верхнюю часть {street2}, чтобы выделить её.**", + "did_split_single": "**Нажмите на верхнюю часть {street2} чтобы выделить её.**", + "multi_select": "Линия {selected} теперь выбрана. Давайте выделим ещё и {other1}. Вы можете выделять несколько линий нажатием мыши с зажатой клавишей Shift. **Зажмите Shift и нажмите на {other2}.**", "multi_rightclick": "Хорошо! Теперь выделены обе линии, которые нужно удалить. **Нажмите правой кнопкой мыши на любой из этих линий, чтобы перейти к меню редактирования объекта.**", - "multi_delete": "**Щёлкните по кнопке {button} чтобы удалить эти линии.**", - "retry_delete": "Вы не щёлкнули кнопку «Удалить». Попробуйте снова.", + "multi_delete": "**Нажмите на кнопку {button} чтобы удалить эти линии.**", + "retry_delete": "Вы не нажали на кнопку «Удалить». Попробуйте снова.", "play": "Великолепно! Используя полученные навыки, потренируйтесь в редактировании других линий. **Когда будете готовы перейти к следующей главе, нажмите '{next}'.**" }, "buildings": { "title": "Здания", "add_building": "OpenStreetMap — крупнейшая в мире база данных о зданиях.{br}Вы можете добавить ещё не внесённые здания. **Нажмите кнопку {button} Полигон, чтобы добавить новый полигон**", - "start_building": "Давайте обведём контур этого дома, чтобы добавить его на карту.{br}Здания нужно обводить по фундаменту с максимальной точностью. **Щёлкните или нажмите пробел на одном из углов здания, чтобы создать первую точку.**", - "continue_building": "Добавьте точки на остальные углы дома. Можете увеличить изображение, чтобы видеть больше деталей.{br}Нажмите пробел или ещё раз щёлкните на первой или последней точке контура чтобы завершить здание. **Завершите рисование здания.**", + "start_building": "Давайте обведём контур этого дома, чтобы добавить его на карту.{br}Здания нужно обводить по фундаменту с максимальной точностью. **Нажмите мышью или нажмите Пробел на клавиатуре на месте одного из углов здания, чтобы создать первую точку.**", + "continue_building": "Добавьте точки для остальных углов дома. Можете увеличить изображение, чтобы увидеть больше деталей.{br}Нажмите Пробел или ещё раз нажмите мышью на первую или последнюю точку контура, чтобы завершить рисование здания. **Завершите рисование здания.**", "retry_building": "Похоже, что Вы отметили не все углы здания. Попробуйте ещё раз!", "choose_category_building": "**Выберите {category} из списка.**", "choose_preset_house": "Существует много типов зданий, но этот дом точно частный жилой.{br}Если Вы точно не знаете тип дома, можно выбирать *Здание без конкретного типа*. **Выберите тип {preset}.**", "close": "**Нажмите Esc или кнопку {button} , чтобы закрыть редактор объектов.**", "rightclick_building": "**Нажмите правой кнопкой мыши на добавленном здании, чтобы перейти к меню редактирования объекта.**", "square_building": "Дом, который вы только что добавили, будет выглядеть ещё лучше с идеально прямыми углами. **Нажмите кнопку {button} чтобы спрямить форму здания.**", - "retry_square": "Вы не щёлкнули кнопку «Спрямить углы». Попробуйте снова.", + "retry_square": "Вы не нажали на кнопку «Спрямить углы». Попробуйте снова.", "done_square": "Видите, как углы здания передвинулись на другое место? Давайте освоим ещё один полезный приём.", "add_tank": "Теперь мы обрисуем этот круглый резервуар. **Нажмите {button} кнопку «Полигон» чтобы добавить новый полигон.**", - "start_tank": "Не волнуйтесь, не придётся рисовать идеальный круг. Просто нарисуйте полигон с точками, касающимися края резервуара. **Щёлкните или нажмите пробел на контуре резервуара, чтобы создать первую точку.**", - "continue_tank": "Добавьте ещё несколько точек на контуре. Круг будет создан снаружи обрисованных точек.{br}Нажмите Enter или щёлкните ещё раз на первой или последней точке, чтобы закончить рисование. **Завершите обведение резервуара.**", + "start_tank": "Не волнуйтесь, Вам не придётся рисовать идеальный круг самостоятельно. Просто нарисуйте полигон с точками, касающимися края резервуара. **Нажмите мышью или нажмите Пробел на клавиатуре в любом месте контура резервуара, чтобы создать первую точку.**", + "continue_tank": "Добавьте ещё несколько точек на контуре. Круг будет создан вокруг обрисованных точек.{br}Нажмите Enter или нажмите мышью ещё раз на первой или последней точке контура, чтобы закончить рисование. **Завершите обводку резервуара.**", "search_tank": "**Искать '{preset}'.**", "choose_tank": "**Выберите {preset} из списка**", "rightclick_tank": "**Нажмите правой кнопкой мыши на добавленном резервуаре, чтобы перейти к меню редактирования объекта.**", "circle_tank": "**Нажмите кнопку {button}, чтобы сделать резервуар круглым.**", - "retry_circle": "Вы не щёлкнули кнопку «Скруглить». Попробуйте снова.", + "retry_circle": "Вы не нажали на кнопку «Скруглить». Попробуйте снова.", "play": "Замечательно! Потренируйтесь обводить ещё несколько зданий, и попробуйте другие команды в меню редактирования. **Нажмите '{next}' когда будете готовы перейти к следующей главе.**" }, "startediting": { @@ -1318,7 +1332,7 @@ "name": "Здания" }, "category-golf": { - "name": "Гольф объекты" + "name": "Гольф-объекты" }, "category-landuse": { "name": "Объекты землепользования" @@ -1397,7 +1411,7 @@ } }, "access_simple": { - "label": "Общий доступ" + "label": "Доступ для всех" }, "address": { "label": "Адресная информация", @@ -1629,7 +1643,7 @@ "label": "Страна" }, "covered": { - "label": "Крытое" + "label": "Крытое(-ая)" }, "craft": { "label": "Тип мастерской" @@ -1769,6 +1783,9 @@ "display": { "label": "Циферблат" }, + "distance": { + "label": "Расстояние" + }, "dock": { "label": "Тип" }, @@ -1809,12 +1826,15 @@ "except": { "label": "Не действует для" }, + "faces": { + "label": "Количество сторон" + }, "fax": { "label": "Факс", "placeholder": "+7 495 1234567" }, "fee": { - "label": "Есть оплата" + "label": "Платная (-ый)" }, "fence_type": { "label": "Тип" @@ -1920,6 +1940,39 @@ "label": "Число колец", "placeholder": "1, 2, 4…" }, + "horse_dressage": { + "label": "Выездка (дрессура)", + "options": { + "equestrian": "Да", + "undefined": "Нет" + } + }, + "horse_riding": { + "label": "Верховая езда", + "options": { + "horse_riding": "Да", + "undefined": "Нет" + } + }, + "horse_scale": { + "label": "Сложность для верховой езды", + "options": { + "common": "Легая. Отсутствуют проблемы или сложности.", + "critical": "На грани: Проходимо только для опытных наездников и лошадей. Серьёзные препятствия. Мосты следуют хорошенько изучить.", + "dangerous": "Опасно: Проходимо только очень опытными наездниками и лошадьми и только в хорошую погоду. Необходимость спешиваться.", + "demanding": "Будьте внимательны: неровная дорога, иногда сложные участки", + "difficult": "Сложно: узкий путь. Встречаются препятствия, которые необходимо перепрыгнуть.", + "impossible": "Непроходимо: Путь или мость не проходим для лошадей. Слишком узок, недостаточно прочен, встречаются лестницы. Опасно для жизни." + }, + "placeholder": "Сложность, опасность..." + }, + "horse_stables": { + "label": "Конюшня", + "options": { + "stables": "Да", + "undefined": "Нет" + } + }, "iata": { "label": "IATA" }, @@ -1939,6 +1992,9 @@ "indoor": { "label": "План помещения" }, + "industrial": { + "label": "Тип" + }, "information": { "label": "Тип" }, @@ -2059,6 +2115,10 @@ "label": "Ограничение скорости", "placeholder": "40, 50, 60…" }, + "maxspeed/advisory": { + "label": "Рекомендуемая скорость", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Максимальное время остановки" }, @@ -2195,11 +2255,11 @@ "parking": { "label": "Тип", "options": { - "carports": "Автомобильный навес", + "carports": "Навес", "garage_boxes": "Одноярусные гаражи", - "lane": "Полоса вдоль дороги", + "lane": "Уличная парковка", "multi-storey": "Многоярусная", - "sheds": "Сараи рядом с домом", + "sheds": "Козырёк", "surface": "Наземная", "underground": "Подземная" } @@ -2212,7 +2272,6 @@ "placeholder": "1, 2, 3…" }, "phone": { - "label": "Телефон", "placeholder": "+7 495 1234567" }, "piste/difficulty": { @@ -2516,13 +2575,13 @@ "label": "Тип" }, "supervised": { - "label": "Наблюдение" + "label": "Охраняемая(-ый)" }, "support": { "label": "Находится на" }, "surface": { - "label": "Покрытие" + "label": "Дорожное покрытие" }, "surveillance": { "label": "Тип наблюдения" @@ -2647,8 +2706,19 @@ "label": "Тип тоннеля", "placeholder": "По умолчанию" }, + "usage_rail": { + "label": "Тип использования", + "options": { + "branch": "Ветка", + "industrial": "Промышленное", + "main": "Основное", + "military": "Военное", + "test": "Тестовое", + "tourism": "Туризм" + } + }, "vending": { - "label": "Тип товаров" + "label": "Тип автомата" }, "visibility": { "label": "Видимость", @@ -2741,6 +2811,10 @@ "name": "Рекламный щит", "terms": "реклама,объявление,щит,билборд,информация,транспорант,постер,растяжка" }, + "advertising/column": { + "name": "Афишная тумба Морриса", + "terms": "тумба моририса, колонна, рекламная, реклама, афиша" + }, "aerialway": { "name": "Подъёмник" }, @@ -2825,6 +2899,10 @@ "name": "Терминал аэропорта", "terms": "Терминал аэропорта" }, + "allotments/plot": { + "name": "Садовый участок", + "terms": "огород, садовый участок" + }, "amenity": { "name": "Инфраструктура" }, @@ -2966,12 +3044,12 @@ "terms": "крематорий,захоронение,услуги,церемония,мертвец,покойник,кладбище,обряд,служба,прах,колумбарий" }, "amenity/dentist": { - "name": "Дантист", - "terms": "стоматолог, дантист, зубной врач" + "name": "Стоматология", + "terms": "стоматолог, стоматология, дантист, зубной врач" }, "amenity/doctors": { "name": "Кабинет врача", - "terms": "врач, доктор,фельдшер,медик, небольшая клиника, клиника" + "terms": "врач, доктор,фельдшер,медик, небольшая клиника, клиника, медпункт, медицинский кабинет, здравпункт" }, "amenity/dojo": { "name": "Додзё / Школа боевых искусств", @@ -2991,7 +3069,7 @@ }, "amenity/fast_food": { "name": "Фаст-фуд", - "terms": "фастфуд, фаст-фуд, быстрое питание, ресторан быстрого питания, столовая, бистро" + "terms": "фастфуд, фаст-фуд, быстрое питание, ресторан быстрого питания, столовая, бистро, кафетерий" }, "amenity/ferry_terminal": { "name": "Пристань/терминал для парома" @@ -3002,7 +3080,7 @@ }, "amenity/food_court": { "name": "Ресторанный дворик", - "terms": "фудкорт,забегаловка,кафе,быстро,еда,центр,торговый,развлекательный,кино, отдых,досуг,ресторан,суши,пицца,кофе,напитки,пирожные" + "terms": "фудкорт, ресторанный дворик" }, "amenity/fountain": { "name": "Фонтан", @@ -3051,6 +3129,9 @@ "name": "Рынок", "terms": "Рынок" }, + "amenity/monastery": { + "name": "Монастырь" + }, "amenity/motorcycle_parking": { "name": "Парковка для мотоциклов", "terms": "мотопарковка, мотопаркинг, парковка для мотоциклов, паркинг для мотоциклов, мотостоянка" @@ -3099,7 +3180,8 @@ "terms": "храм, часовня, молельня, дом божий, капелла, церковь, кафедрарий, место поклонения, культовое сооружение, святое место, мечеть, собор, синагога" }, "amenity/place_of_worship/hindu": { - "name": "Индуистский храм" + "name": "Индуистский храм", + "terms": "индуистский храм, мандир" }, "amenity/place_of_worship/jewish": { "name": "Синагога", @@ -3113,7 +3195,8 @@ "name": "Дзиндзя" }, "amenity/place_of_worship/sikh": { - "name": "Гурдвара" + "name": "Гурдвара", + "terms": "сикхский храм, гурдвара" }, "amenity/place_of_worship/taoist": { "name": "Даосский храм", @@ -3252,6 +3335,10 @@ "name": "Автомат по продаже сигарет", "terms": "Автомат по продаже сигарет" }, + "amenity/vending_machine/coffee": { + "name": "Кофе", + "terms": "кофейный автомат, кофемашина" + }, "amenity/vending_machine/condoms": { "name": "Автомат по продаже презервативов", "terms": "Автомат по продаже презервативов" @@ -3260,6 +3347,12 @@ "name": "Автомат по продаже напитков", "terms": "газировка, напитки, вода" }, + "amenity/vending_machine/electronics": { + "name": "Электронные устройства" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Удлинённая монета" + }, "amenity/vending_machine/excrement_bags": { "name": "Автомат по продаже мешков для экскрементов", "terms": "экскременты, животные" @@ -3267,6 +3360,18 @@ "amenity/vending_machine/feminine_hygiene": { "name": "Автомат для продажи средств женской гигиены" }, + "amenity/vending_machine/food": { + "name": "Продукты питания", + "terms": "Продуктовый автомат, автомат с закусками" + }, + "amenity/vending_machine/fuel": { + "name": "Заправка", + "terms": "азс, бензин, дизель, автозаправка, газ, пропан, бутан" + }, + "amenity/vending_machine/ice_cream": { + "name": "Мороженое", + "terms": "автомат с мороженым, мороженое" + }, "amenity/vending_machine/news_papers": { "name": "Автомат по продаже газет (ошибочный тег)" }, @@ -3283,11 +3388,16 @@ "terms": "паркомат" }, "amenity/vending_machine/public_transport_tickets": { - "name": "Автомат по продаже проездных билетов" + "name": "Автомат по продаже проездных билетов", + "terms": "автомат с билетами, билетный автомат" + }, + "amenity/vending_machine/stamps": { + "name": "Почтовый автомат", + "terms": "письма, почта, марки" }, "amenity/vending_machine/sweets": { "name": "Автомат по продаже батончиков", - "terms": "Автомат по прожае снеков, торговый автомат" + "terms": "Автомат продажи, торговый автомат" }, "amenity/veterinary": { "name": "Ветеринар", @@ -3352,6 +3462,10 @@ "attraction/drop_tower": { "name": "Аттракцион \"Свободное падение\"" }, + "attraction/maze": { + "name": "Лабиринт", + "terms": "аттракцион, головоломка, загадка, лабиринт" + }, "attraction/pirate_ship": { "name": "Пиратский корабль" }, @@ -3515,7 +3629,8 @@ "name": "Жилое здание на ферме" }, "building/farm_auxiliary": { - "name": "Нежилое здание на ферме" + "name": "Нежилое здание на ферме", + "terms": "хлев, рига, сарай" }, "building/garage": { "name": "Гараж", @@ -3525,6 +3640,10 @@ "name": "Гаражи", "terms": "Гаражи, ракушки" }, + "building/grandstand": { + "name": "Трибуна", + "terms": "трибуна, подмостки" + }, "building/greenhouse": { "name": "Теплица", "terms": "оранжерея, растения" @@ -3606,7 +3725,8 @@ "terms": "дом на колёсах" }, "building/temple": { - "name": "Здание храма" + "name": "Здание храма", + "terms": "Здание храма, здание церкви" }, "building/terrace": { "name": "Ряд из примыкающих домов", @@ -3630,6 +3750,9 @@ "name": "Поляна для кемпинга", "terms": "тент, палатка, кемпинг" }, + "circular": { + "name": "Круговое движение со въездами разного приоритета" + }, "club": { "name": "Клуб", "terms": "Клуб по интересам, фан-клуб, кружок" @@ -3952,6 +4075,10 @@ "healthcare/hospice": { "name": "Хоспис" }, + "healthcare/laboratory": { + "name": "Медицинская лаборатория", + "terms": "лаборатория, анализы, медицина, кровь, моча" + }, "healthcare/midwife": { "name": "Акушерство" }, @@ -4035,13 +4162,17 @@ "terms": "Автомагистраль, Скоростная автострада, Скоростное шоссе, Автобан, Скоростная автодорога, Хайвэй, Скоростна автотрасса" }, "highway/motorway_junction": { - "name": "Развязка / съезд", - "terms": "развязка, съезд" + "name": "Магистральная развязка / съезд", + "terms": "магистральная развязка, съезд" }, "highway/motorway_link": { "name": "Съезд с автомагистрали", "terms": "Съезд с автомагистрали, Съезд со скоростной автострады, Съезд со скоростного шоссе, Съезд с автобана, Съезд со скоростной автодороги, Съезд с хайвэя, Съезд со скоростной автотрассы" }, + "highway/passing_place": { + "name": "Место разъезда", + "terms": "разъезд, разъехаться, карман, узкая дорога, уширение" + }, "highway/path": { "name": "Тропа", "terms": "Тропа, Тропинка, Тропка, пешеходная дорога для немоторизованного траспорта" @@ -4084,11 +4215,11 @@ "terms": "съезд, съезд с важной дороги" }, "highway/service": { - "name": "Проезд", + "name": "Служебная дорога", "terms": "Проезд, Автопроезд" }, "highway/service/alley": { - "name": "Служебный проезд", + "name": "Дорога на задворках", "terms": "Служебный проезд, Сервисный проезд, Второстепенный проезд" }, "highway/service/drive-through": { @@ -4096,7 +4227,7 @@ "terms": "Сервис не выходя из машины, Обслуживание не выходя из машины" }, "highway/service/driveway": { - "name": "Подъездная дорожка", + "name": "Подъездная дорога", "terms": "Подъездная дорога, Подъезд к чему-либо" }, "highway/service/emergency_access": { @@ -4104,7 +4235,7 @@ "terms": "Эвакуационный выход, Аварийный выход" }, "highway/service/parking_aisle": { - "name": "Парковочный проезд", + "name": "Между рядами парковки", "terms": "парковочный проезд, проезд на парковке" }, "highway/services": { @@ -4140,7 +4271,8 @@ "terms": "полевая, грунтовка, сельскохозяйственная" }, "highway/traffic_mirror": { - "name": "Дорожное зеркало" + "name": "Дорожное зеркало", + "terms": "зеркало, дорожный экран" }, "highway/traffic_signals": { "name": "Светофор", @@ -4213,7 +4345,7 @@ }, "landuse/allotments": { "name": "Садовые участки", - "terms": "Участки садов и огородов, Сады и огороды, СОТ, СНТ, Дачи" + "terms": "Участки садов и огородов, Сады и огороды, СОТ, СНТ, Дачи, огороды" }, "landuse/aquaculture": { "name": "Аквакультура", @@ -4380,6 +4512,10 @@ "leisure/amusement_arcade": { "name": "Игровые автоматы" }, + "leisure/beach_resort": { + "name": "Пляжный курорт", + "terms": "пляж, курорт" + }, "leisure/bird_hide": { "name": "Пункт наблюдения за птицами" }, @@ -4474,6 +4610,10 @@ "name": "Заповедник", "terms": "заказник" }, + "leisure/outdoor_seating": { + "name": "Столики на улице (площадка)", + "terms": "на улице, кафе на улице, стол, столики, уличное" + }, "leisure/park": { "name": "Парк отдыха", "terms": "парк, рекреация, место для отдыха" @@ -4599,6 +4739,9 @@ "name": "Штольня", "terms": "штольня" }, + "man_made/antenna": { + "name": "Антенна" + }, "man_made/breakwater": { "name": "Волнорез", "terms": "Мол, Оградительное гидросооружение" @@ -4649,6 +4792,10 @@ "name": "Смотровая башня", "terms": "Смотровая башня, Обзорная башня" }, + "man_made/observatory": { + "name": "Обсерватория", + "terms": "астрономия, небо, звезды, наблюдение, телескоп" + }, "man_made/petroleum_well": { "name": "Нефтяная скважина", "terms": "скважина, нефть" @@ -4767,10 +4914,17 @@ "name": "Вересковая пустошь", "terms": "Вереск, пустошь" }, + "natural/mud": { + "name": "Грязь", + "terms": "вода с землей, земля" + }, "natural/peak": { "name": "Вершина", "terms": "пик, гора" }, + "natural/reef": { + "name": "Риф" + }, "natural/ridge": { "name": "Хребет" }, @@ -5368,7 +5522,8 @@ "terms": "Магазин, Торговая лавка, Точка продаж" }, "shop/agrarian": { - "name": "Сельскохозяйственный магазин" + "name": "Сельскохозяйственный магазин", + "terms": "семена, сельхозтехника, удобрения, пестициды" }, "shop/alcohol": { "name": "Алкогольный магазин", @@ -5506,7 +5661,7 @@ }, "shop/cosmetics": { "name": "Магазин косметики", - "terms": "косметика" + "terms": "косметика, бижутерия" }, "shop/craft": { "name": "Магазин художественных принадлежностей", @@ -5526,7 +5681,7 @@ }, "shop/department_store": { "name": "Универсальный магазин (с отделами)", - "terms": "торговый центр, дом быта, тц, универсальный магазин" + "terms": "дом быта, универсальный магазин, универсам" }, "shop/doityourself": { "name": "Строительный гипермаркет", @@ -5722,12 +5877,17 @@ "terms": "ломбард" }, "shop/perfumery": { - "name": "Парфюмерный" + "name": "Парфюмерия", + "terms": "духи, парфюм, парфюмерия" }, "shop/pet": { "name": "Зоомагазин", "terms": "зоомагазин, для животных" }, + "shop/pet_grooming": { + "name": "Парикмахерская для животных", + "terms": "зоосалон, салон красоты для животных, собак, кошек, стрижка, уход, мытьё" + }, "shop/photo": { "name": "Фототовары", "terms": "Фототовары, Фототехника, фото на паспорт, паспорт, фото" @@ -5750,15 +5910,15 @@ }, "shop/seafood": { "name": "Магазин морепродуктов", - "terms": "Морепродукты, Суши, Рыба, Рыбный" + "terms": "Морепродукты, Рыба, Рыбный" }, "shop/second_hand": { "name": "Магазин секонд хенда", "terms": "секондхенд, секонд хенд, секонд, комиссионный" }, "shop/shoes": { - "name": "Обувной", - "terms": "Обувной магазин" + "name": "Обувь", + "terms": "обувь, обувной магазин" }, "shop/sports": { "name": "Спорттовары", @@ -5773,7 +5933,7 @@ }, "shop/supermarket": { "name": "Супермаркет", - "terms": "гипермаркет" + "terms": "гипермаркет, сумермаркет" }, "shop/tailor": { "name": "Портной", @@ -5810,8 +5970,8 @@ "terms": "Турагенство" }, "shop/tyres": { - "name": "Шины, покрышки", - "terms": "Шины, Покрышки, Автопокрышки, Автошины" + "name": "Шины", + "terms": "автопокрышки, автошины, покрышки, шины" }, "shop/vacant": { "name": "Помещение под открытие магазина" @@ -5940,6 +6100,10 @@ "name": "Парк развлечений", "terms": "парк, отдых, развлечения, тематический парк, парк аттракционов, аттракционы" }, + "tourism/trail_riding_station": { + "name": "Временное жильё для лошадей и наездников", + "terms": "верховая езда, проживание, жилье, лошадиный, лошадь, кони, конный" + }, "tourism/viewpoint": { "name": "Обзорная точка", "terms": "площадка, обозрение, точка обзора, смотровая площадка, хороший вид" @@ -6004,7 +6168,7 @@ }, "type/restriction": { "name": "Ограничение манёвра", - "terms": "Ограничение, Ограничение направлений движения, Ограничение манёвра, Запрет на поворот, Запрет поворота, манёвра" + "terms": "ограничение, ограничение направлений движения, ограничение манёвра, запрет на поворот, запрет поворота, манёвра" }, "type/restriction/no_left_turn": { "name": "Поворот налево запрещён (3.18.2)", @@ -6016,23 +6180,23 @@ }, "type/restriction/no_straight_on": { "name": "Движение направо или налево (4.1.4)", - "terms": "Движение прямо запрещено, Движение налево или направо, 4.1.4" + "terms": "движение прямо запрещено, движение налево или направо, 4.1.4" }, "type/restriction/no_u_turn": { "name": "Разворот запрещён (3.19)", "terms": "Разворот запрещён, Без разворотов, Запрещён разворот" }, "type/restriction/only_left_turn": { - "name": "Движение налево (4.1.3)", - "terms": "Только поворот налево, Движение налево, 4.1.3" + "name": "Только поворот налево" }, "type/restriction/only_right_turn": { - "name": "Движение направо (4.1.2)", - "terms": "Только поворот направо, Движение направо, 4.1.2" + "name": "Только поворот направо" }, "type/restriction/only_straight_on": { - "name": "Движение прямо (4.1.1)", - "terms": "Движение прямо, повороты запрещены, только прямо, запрет поворотов, 4.1.1" + "name": "Только прямо" + }, + "type/restriction/only_u_turn": { + "name": "Только разворот" }, "type/route": { "name": "Маршрут", @@ -6188,7 +6352,7 @@ "attribution": { "text": "Условия и обратная связь" }, - "description": "Границы подложек и даты съемки. Надписи появляются на 14 зуме и выше.", + "description": "Границы подложек и даты съемки. Надписи появляются на 13 масштабе и выше.", "name": "Премиум снимки DigitalGlobe (Vintage)." }, "DigitalGlobe-Standard": { @@ -6202,7 +6366,7 @@ "attribution": { "text": "Условия и обратная связь" }, - "description": "Границы подложек и даты съемки. Надписи появляются на 14 зуме и выше.", + "description": "Границы подложек и даты съемки. Надписи появляются на 13 масштабе и выше.", "name": "Стандартные снимки DigitalGlobe (Vintage)" }, "EsriWorldImagery": { @@ -6216,7 +6380,7 @@ "attribution": { "text": "Условия и обратная связь" }, - "description": "Архивная подложка Esri, может быть чище и аккуратнее чем не-архивная.", + "description": "Архивная подложка Esri, может быть чище и аккуратнее, чем актуальная.", "name": "Всемирные снимки Esri (Clarity)" }, "MAPNIK": { @@ -6279,12 +6443,16 @@ "name": "TIGER дороги 2012" }, "US-TIGER-Roads-2014": { - "description": "На зумах 16+ — общедостпуные картографические данные от US Census. На меньших зумах — только изменения с 2006 за вычетом изменений, включённых в OpenStreetMap", - "name": "TIGER дороги 2014" + "description": "На масштабах 16+ — общедостпуные картографические данные от US Census. На меньших масштабах — только изменения с 2006 за вычетом изменений, включённых в OpenStreetMap", + "name": "Дороги TIGER 2014" }, "US-TIGER-Roads-2017": { "description": "Жёлтым = общедоступные картографические данные от US Census. Красным = данные, отсутствующие в OpenStreetMap", - "name": "TIGER дороги 2017" + "name": "Дороги TIGER 2017" + }, + "US_Forest_Service_roads_overlay": { + "description": "Дороги: зелёный контур = без классификации; коричневый = просёлочные. Покрытие: гравий = светло-коричневый цвет; асфальт = чёрный; другое покрытие = серый; земля = белый; бетон = синий; трава = зелёный. Сезонные дороги = белые штрихи", + "name": "Лесные дороги США" }, "Waymarked_Trails-Cycling": { "attribution": { @@ -6382,7 +6550,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Тайлы: Stamen Design, под CC BY 3.0" + "text": "Тайлы: Stamen Design, под CC BY 3.0. Данные: OpenStreetMap, под ODbL" }, "name": "Stamen Ландшафт" }, @@ -6398,6 +6566,92 @@ }, "name": "Thunderforest Ландшафт" } + }, + "community": { + "cape-coast-youthmappers": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "osm-gh-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "OSM-RU-forum": { + "name": "Форум русскоязычного сообщества OSM", + "description": "Дискуссии, вопросы, голосования, проблемы и их решения — вам сюда." + }, + "OSM-RU-telegram": { + "name": "Telegram-чат русскоязычного сообщества OSM", + "description": "Участники рады ответить на любой вопрос, связанный с использованием или рисованием карт, и готовы обсудить любую релевантную новость. Да, мы любим аниме и умеем устанавливать KDE на FreeBSD." + }, + "byosm": { + "name": "OpenStreetMap Беларусь", + "description": "Telegram-чат OpenStreetMap Буларусь" + }, + "de-berlin-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "it-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "se-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "Bay-Area-OpenStreetMappers": { + "description": "Улучшить перевод OpenStreetMap в Bay Area" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "Группа пользователей OpenStreetMap в Chattanooga" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Мапперы и пользователи OpenStreetMap в Portland area" + }, + "OSM-US-Slack": { + "name": "Slack OpenStreetMap US", + "description": "Приглашаются все! Регистрация на {signupUrl}" + }, + "PHXGeo-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "Maptime-Australia-Slack": { + "name": "Slack \"Maptime Australia\"", + "description": "Регистрация на {signupUrl}" + }, + "OSM-AR-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "OSM-br-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "OSM-CL-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "OSM-CO-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "OSM-PE-twitter": { + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "OSM-Facebook": { + "name": "OpenStreetMap в Facebook", + "description": "Нажмите Like на нашей странице в Facebook, чтобы подписаться на новости и обновления про OpenStreetMap." + }, + "OSM-help": { + "name": "OpenStreetMap Помощь", + "description": "Задайте вопрос и получите ответы на сайте вопросов и ответов, поддерживаемом OSM сообществом." + }, + "OSM-Reddit": { + "name": "OpenStreetMap на Reddit", + "description": "/r/openstreetmap/ — прекрасное место, чтобы узнать что-нибудь про OpenStreetMap. Задавайте любые вопросы!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter", + "description": "Подписывайтесь на нас в Twitter {url}" + }, + "OSMF": { + "name": "Фонд OpenStreetMap", + "description": "OSMF — это зарегистрированная в Великобритании бесприбыльная организация, поддерживающая проект OpenStreetMap." + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/si.json b/vendor/assets/iD/iD/locales/si.json index 2c6fa87bc..92f64f921 100644 --- a/vendor/assets/iD/iD/locales/si.json +++ b/vendor/assets/iD/iD/locales/si.json @@ -352,12 +352,7 @@ } }, "success": { - "edited_osm": "OSM සංස්කරණය කරන ලදී!", - "just_edited": "ඔබ මේ මොහොතේ OpenStreetMap සංස්කරණය කරන ලදී", - "view_on_osm": "OSM මත දක්වන්න", - "facebook": "Facebook හි බෙදාහරින්න", - "twitter": "Twitter හි බෙදා හරින්න", - "google": "Google+ හි බෙදා හරින්න" + "just_edited": "ඔබ මේ මොහොතේ OpenStreetMap සංස්කරණය කරන ලදී" }, "confirm": { "cancel": "අහෝසි කරන්න" @@ -525,9 +520,6 @@ "tracktype": { "label": "වර්ගය" }, - "vending": { - "label": "වර්ගය" - }, "water": { "label": "වර්ගය" }, diff --git a/vendor/assets/iD/iD/locales/sk.json b/vendor/assets/iD/iD/locales/sk.json index 92c8e3860..8231b5722 100644 --- a/vendor/assets/iD/iD/locales/sk.json +++ b/vendor/assets/iD/iD/locales/sk.json @@ -160,7 +160,6 @@ "annotation": "ZlúčiÅ¥ {n} objektov.", "not_eligible": "Tieto objekty nemôžno zlúčiÅ¥.", "not_adjacent": "Tieto objekty nemôžno zlúčiÅ¥, pretože ich koncové body nie sú spojené.", - "restriction": "Tieto objekty nemôžno zlúčiÅ¥, pretože aspoň jeden je členom relácie \"{relation}\".", "incomplete_relation": "Tieto objekty nemôžno zlúčiÅ¥, pretože aspoň jeden z nich nebol úplne stiahnutý.", "conflicting_tags": "Tieto objekty nemôžno zlúčiÅ¥, pretože niktoré ich označenia majú odporujúce si hodnoty." }, @@ -582,13 +581,7 @@ } }, "success": { - "edited_osm": "OSM bol upravený!", "just_edited": "Práve ste upravili OpenStreetMap!", - "view_on_osm": "ZobraziÅ¥ na OSM", - "facebook": "Zdieľaj na Facebooku", - "twitter": "Zdieľaj na Twitteri", - "google": "Zdieľaj na Google+", - "help_html": "VaÅ¡e zmeny by sa mali objaviÅ¥ na \"Základnej\" vrstve v priebehu niekoľkých minút. Ostatným vrstvám a niektorým objektom to môže trvaÅ¥ dlhÅ¡ie.", "help_link_text": "Podrobnosti", "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" }, @@ -1820,7 +1813,6 @@ "label": "Typy platieb" }, "phone": { - "label": "Telefón", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2182,9 +2174,6 @@ "label": "Typ", "placeholder": "Prednastavené" }, - "vending": { - "label": "Typ tovaru" - }, "visibility": { "label": "ViditeľnosÅ¥", "options": { @@ -4612,18 +4601,6 @@ "name": "Zákaz otáčania", "terms": "zakaz otacania" }, - "type/restriction/only_left_turn": { - "name": "Prikázaný smer jazdy vľavo", - "terms": "Prikazany smer jazdy vlavo" - }, - "type/restriction/only_right_turn": { - "name": "Prikázaný smer jazdy vpravo", - "terms": "prikazany smer jazdy vpravo" - }, - "type/restriction/only_straight_on": { - "name": "Prikázaný smer jazdy priamo", - "terms": "prikazany smer jazdy priamo" - }, "type/route": { "name": "Trasa", "terms": "trasa,linka,trat,traÅ¥" @@ -4838,7 +4815,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Základná mapa Rakúska, odvodená z vládnych dát.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -4899,9 +4875,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Mapové dlaždice od Stamen Design, pod CC BY 3.0" - }, "name": "Stamen terén" }, "tf-cycle": { diff --git a/vendor/assets/iD/iD/locales/sl.json b/vendor/assets/iD/iD/locales/sl.json index 6290f19ed..a3f7d03bc 100644 --- a/vendor/assets/iD/iD/locales/sl.json +++ b/vendor/assets/iD/iD/locales/sl.json @@ -1,5 +1,10 @@ { "sl": { + "icons": { + "information": "podrobnosti", + "remove": "odstrani", + "undo": "razveljavi" + }, "modes": { "add_area": { "title": "Mnogokotnik", @@ -160,7 +165,6 @@ "annotation": "združevanje {n} predmetov ×", "not_eligible": "Izbranih predmetov ni mogoče združiti.", "not_adjacent": "Predmetov ni mogoče združiti, ker končne točke niso povezane.", - "restriction": "Predmetov ni mogoče združiti, ker je vsaj en vključen v povezavo »{relation}«.", "incomplete_relation": "Teh predmetov ni mogoče združiti, ker vsaj en ni v celoti prejet.", "conflicting_tags": "Predmetov ni mogoče združiti, ker so v njihovih oznakah neskladne vrednosti." }, @@ -288,6 +292,11 @@ } } }, + "restriction": { + "controls": { + "distance": "Razdalja" + } + }, "undo": { "tooltip": "Razveljavi: {action}", "nothing": "Ni razveljavitev" @@ -592,15 +601,14 @@ } }, "success": { - "edited_osm": "OSM je posodobljen!", "just_edited": "Zemljevid OSM je posodobljen!", - "view_on_osm": "Pokaži spremembe na OSM", - "facebook": "Objavi na Facebook", - "twitter": "Objavi na Twitter", - "google": "Objavi na Google+", - "help_html": "Spremembe na »osnovni plasti« se bodo na zemljevidu pojavile čez nekaj minut. Dodatne plasti in nekatere značilnosti se lahko posodabljajo dlje.", "help_link_text": "Podrobnosti", - "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" + "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", + "more": "Več", + "events": "Dogodki", + "languages": "Jeziki: {languages}", + "missing": "Ali na seznamu kaj manjka?", + "tell_us": "Sporočite nam!" }, "confirm": { "okay": "V redu", @@ -680,6 +688,16 @@ }, "overview": { "features_h": "Značilnosti zemljevida" + }, + "field": { + "restrictions": { + "about": { + "title": "O programu" + }, + "tips": { + "title": "Namigi" + } + } } }, "intro": { @@ -1048,6 +1066,23 @@ } } }, + "units": { + "meters": "{quantity} m", + "kilometers": "{quantity} km", + "square_meters": "{quantity} m²", + "square_kilometers": "{quantity} km²", + "hectares": "{quantity} ha", + "area_pair": "{area1} ({area2})", + "arcdegrees": "{quantity}°", + "arcminutes": "{quantity}′", + "arcseconds": "{quantity}″", + "north": "S", + "south": "J", + "east": "V", + "west": "Z", + "coordinate": "{coordinate}{direction}", + "coordinate_pair": "{latitude}, {longitude}" + }, "presets": { "categories": { "category-barrier": { @@ -1087,10 +1122,10 @@ "name": "Značilnosti cest" }, "category-water-area": { - "name": "Vrste voda" + "name": "Značilnosti voda" }, "category-water-line": { - "name": "Vrste voda" + "name": "Značilnosti voda" } }, "fields": { @@ -1170,7 +1205,8 @@ "subdistrict": "Okraj", "subdistrict!vn": "Okraj/Komuna/Mestece", "suburb": "Predmestje", - "suburb!jp": "Okraj" + "suburb!jp": "Okraj", + "unit": "Enota" } }, "admin_level": { @@ -1216,6 +1252,9 @@ "aeroway": { "label": "Vrsta" }, + "agrarian": { + "label": "Izdelki" + }, "amenity": { "label": "Vrsta" }, @@ -1306,6 +1345,9 @@ "bunker_type": { "label": "Vrsta" }, + "cables": { + "placeholder": "1, 2, 3 ..." + }, "camera/direction": { "label": "Smer (v stopinjah v smeri ur. kazalca)", "placeholder": "45, 90, 180, 270" @@ -1443,9 +1485,48 @@ "description": { "label": "Opis" }, + "devices": { + "label": "naprave", + "placeholder": "1, 2, 3 ..." + }, "diaper": { "label": "Previjalnica" }, + "direction": { + "label": "Smer (v stopinjah v smeri ur. kazalca)", + "placeholder": "45, 90, 180, 270" + }, + "direction_cardinal": { + "label": "Direction", + "options": { + "E": "Vzhod", + "ENE": "Vzhod-severovzhod", + "ESE": "Vzhod-jugovzhod", + "N": "Sever", + "NE": "Severovzhod", + "NNE": "Sever-severovzhod", + "NNW": "Sever-severozahod", + "NW": "Severozahod", + "S": "Jug", + "SE": "Jugovzhod", + "SSE": "Jug-jugovzhod", + "SSW": "Jug-jugozahod", + "SW": "Jugozahod", + "W": "Zahod", + "WNW": "Zahod-severozahod", + "WSW": "Zahod-jugozahod" + } + }, + "direction_clock": { + "label": "Smer", + "options": { + "anticlockwise": "V obratni smeri urinega kazalca", + "clockwise": "V smeri urinega kazalca" + } + }, + "direction_vertex": { + "label": "Smer" + }, "display": { "label": "Zaslon" }, @@ -1455,6 +1536,10 @@ "drive_through": { "label": "Storitev za avtomobile" }, + "duration": { + "label": "Trajanje", + "placeholder": "00:00" + }, "electrified": { "label": "Elektrifikacija", "options": { @@ -1472,6 +1557,10 @@ "label": "Elektronski naslov", "placeholder": "ime.naziv@naziv.domene.si" }, + "embankment": { + "label": "Vrsta", + "placeholder": "Privzeto" + }, "emergency": { "label": "Urgenca" }, @@ -1836,7 +1925,6 @@ "label": "Vrste plačila" }, "phone": { - "label": "Telefon", "placeholder": "+386 1 234 5678" }, "piste/difficulty": { @@ -2163,9 +2251,6 @@ "trees": { "label": "Drevesa" }, - "vending": { - "label": "Vrsta dobrin" - }, "visibility": { "label": "Vidnost", "options": { @@ -4703,18 +4788,6 @@ "name": "Ni mogoče polkrožno obrniti", "terms": "Polkrožno obračanje ni dovoljeno" }, - "type/restriction/only_left_turn": { - "name": "Možno je zaviti samo levo", - "terms": "Dovoljeno je zaviti samo levo." - }, - "type/restriction/only_right_turn": { - "name": "Možno je zaviti samo desno", - "terms": "Dovoljeno je zaviti samo desn" - }, - "type/restriction/only_straight_on": { - "name": "Možno je samo nadaljevati naravnost", - "terms": "Zavijanje ni dovoljeno." - }, "type/route": { "name": "Proga", "terms": "cesta,letalska linija,kolesarska pot,pohodniÅ¡ka pot,linija,pot" @@ -4846,8 +4919,7 @@ "DigitalGlobe-Premium-vintage": { "attribution": { "text": "Pogoji uporabe in odziv" - }, - "description": "Meje posnetkov in datumi zajema. Oznake se pojavijo na ravni povečave 14 in viÅ¡jih." + } }, "DigitalGlobe-Standard": { "attribution": { @@ -4859,16 +4931,20 @@ "DigitalGlobe-Standard-vintage": { "attribution": { "text": "Pogoji uporabe in odziv" - }, - "description": "Meje posnetkov in datumi zajema. Oznake se pojavijo na ravni povečave 14 in viÅ¡jih." + } }, "EsriWorldImagery": { "attribution": { "text": "Pogoji uporabe in odziv" }, - "description": "Posnetki sveta Esri", + "description": "Posnetki sveta Esri.", "name": "Posnetki sveta Esri" }, + "EsriWorldImageryClarity": { + "attribution": { + "text": "Pogoji uporabe in odziv" + } + }, "MAPNIK": { "attribution": { "text": "Skupnost © OpenStreetMap z dovoljenjem CC-BY-SA" @@ -4944,7 +5020,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Osnovni zemljevid Avstrije, ki temelji na uradnih podatkih", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -4997,6 +5072,23 @@ "tf-landscape": { "name": "Thunderforest Landscape" } + }, + "community": { + "OSM-help": { + "name": "Pomoč OpenStreetMap" + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter" + }, + "OSMF": { + "name": "Fundacija OpenStreetMap", + "events": { + "sotm2018": { + "name": "Stanje zemljevida 2018", + "where": "Milano, Italija" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/so.json b/vendor/assets/iD/iD/locales/so.json index 52c4ba85a..0460f239a 100644 --- a/vendor/assets/iD/iD/locales/so.json +++ b/vendor/assets/iD/iD/locales/so.json @@ -20,6 +20,12 @@ "point": "Ku daray bar." } }, + "start": { + "annotation": { + "line": "Bilaabay xariiq.", + "area": "Bilaabay goob." + } + }, "continue": { "title": "Sii wad", "description": "Sii wad khadkanan.", @@ -36,7 +42,14 @@ "title": "Goobo geli", "description": { "line": "Ka dhig khadkan wareeg." - } + }, + "not_closed": "Tani lagama dhigi karo wareeg maxaa yeelay ma aha duub" + }, + "orthogonalize": { + "description": { + "area": "Afar geesood ka dhig qararka goobtan." + }, + "not_squarish": "Tani lagama dhigi karo afar gees, sababtoo ah ma aha mid afar gees ah" }, "delete": { "title": "Tirtir", @@ -46,7 +59,8 @@ }, "disconnect": { "title": "Jar Xiriirka", - "description": "Ka jar xiriirka khadadkan/goobahan midba midka kale." + "description": "Ka jar xiriirka khadadkan/goobahan midba midka kale.", + "not_connected": "Ma jiraan khadad/goobo ku filan halkan ku yaalo si loo joojiyo" }, "move": { "title": "Dhaqaaji", @@ -96,16 +110,20 @@ }, "tooltip_keyhint": "Af-goys:", "translate": { + "translate": "Turjum", "localized_translation_label": "Magaca luqadaha badan", "localized_translation_language": "Dooro luuqada", "localized_translation_name": "Magaca" }, + "zoom_in_edit": "Soo dhawee si aad u tifaftirto khariidada", + "help_translate": "Turjum", "commit": { "created": "Lagu suurtogeliyay" }, "info_panels": { "background": { "title": "Hagaajinta", + "zoom": "Soo dhawee", "description": "Sharaxaad" }, "history": { @@ -126,14 +144,18 @@ "title": "Muuji Goobtayda" }, "inspector": { + "view_on_osm": "Ka eeg openstreetmap.org", "all_fields": "Dhammaan goobaha", "all_tags": "Dhammaan taxanbayaasha", "all_relations": "Dhammaan xiriirada", "choose": "Dooro nooca tilmaamaha", + "reference": "Ka eeg Wiki OpenStreetMap", "search": "Raadi", "feature_list": "Tilmaamaha Waydiimaha", + "edit": "Tifaftir tilmaamaha", "radio": { "structure": { + "type": "Nooca", "layer": "Lakabka" } }, @@ -168,14 +190,16 @@ "next": "Xiga >" } }, - "success": { - "facebook": "Faafi Facebook", - "twitter": "Faafi Twitter", - "google": "Faafi Google+" + "splash": { + "welcome": "Ku soo dhowow id OpenStreetMap editor" }, "tag_reference": { "description": "Sharaxaad" }, + "zoom": { + "in": "Soo dhawee", + "out": "Fogee" + }, "help": { "title": "Caawin", "help": { @@ -202,12 +226,23 @@ } } }, + "intro": { + "welcome": { + "title": "Ku soo dhowow" + }, + "startediting": { + "start": "Bilow Jihaynta!" + } + }, "shortcuts": { "title": "Af-goys", "key": { "delete": "Tirtir" }, "browsing": { + "navigation": { + "zoom": "Soo dhawee / Fogee" + }, "help": { "title": "Caawin" } @@ -251,6 +286,12 @@ }, "category-road": { "name": "Tilmaamaha Wadooyinka" + }, + "category-water-area": { + "name": "Tilmaamaha Biyaha" + }, + "category-water-line": { + "name": "Tilmaamaha Biyaha" } }, "fields": { @@ -263,23 +304,80 @@ } }, "address": { + "label": "Cinwaanka", "placeholders": { "city": "Magaalo", - "place": "Goob" + "city!vn": "Magaalo", + "place": "Goob", + "street": "Wadada" } }, + "aerialway": { + "label": "Nooca" + }, + "aeroway": { + "label": "Nooca" + }, + "amenity": { + "label": "Nooca" + }, + "area/highway": { + "label": "Nooca" + }, + "artwork_type": { + "label": "Nooca" + }, + "barrier": { + "label": "Nooca" + }, + "bicycle_parking": { + "label": "Nooca" + }, + "board_type": { + "label": "Nooca" + }, + "boules": { + "label": "Nooca" + }, + "boundary": { + "label": "Nooca" + }, + "bridge": { + "label": "Nooca" + }, "building": { "label": "Dhismo" }, "building_area": { "label": "Dhismo" }, + "bunker_type": { + "label": "Nooca" + }, "capacity": { "label": "Mug" }, + "castle_type": { + "label": "Nooca" + }, + "club": { + "label": "Nooca" + }, + "construction": { + "label": "Nooca" + }, + "craft": { + "label": "Nooca" + }, + "crossing": { + "label": "Nooca" + }, "cuisine": { "label": "Cunnada" }, + "cutting": { + "label": "Nooca" + }, "cycleway": { "label": "Dhabbaha Baaskiilada", "types": { @@ -296,32 +394,97 @@ "description": { "label": "Sharaxaad" }, + "dock": { + "label": "Nooca" + }, + "electrified": { + "options": { + "no": "Maya", + "yes": "Haa (unspecified)" + } + }, + "embankment": { + "label": "Nooca" + }, + "entrance": { + "label": "Nooca" + }, + "fence_type": { + "label": "Nooca" + }, "fire_hydrant/type": { + "label": "Nooca", "options": { "pond": "Balli" } }, + "ford": { + "label": "Nooca" + }, "generator/source": { "label": "Bilowga xogta" }, + "generator/type": { + "label": "Nooca" + }, + "government": { + "label": "Nooca" + }, + "healthcare": { + "label": "Nooca" + }, + "highway": { + "label": "Nooca" + }, + "historic": { + "label": "Nooca" + }, + "information": { + "label": "Nooca" + }, "internet_access": { - "label": "Helitaanka Internet-ka" + "label": "Helitaanka Internet-ka", + "options": { + "no": "Maya", + "yes": "Haa" + } }, "internet_access/ssid": { "label": "SSID (Magaca Network)" }, + "lamp_type": { + "label": "Nooca" + }, + "landuse": { + "label": "Nooca" + }, "lanes": { "label": "Tirada Dhabbooyinka" }, + "leisure": { + "label": "Nooca" + }, "levels": { "label": "Heerarka" }, + "man_made": { + "label": "Nooca" + }, + "manhole": { + "label": "Nooca" + }, + "map_type": { + "label": "Nooca" + }, "maxheight": { "label": "Dhererka ugu Sareeya" }, "maxspeed": { "label": "Xadka Xawaaraha" }, + "memorial": { + "label": "Nooca" + }, "name": { "label": "Magaca", "placeholder": "Magaca guud (haddii uu jiro)" @@ -329,11 +492,25 @@ "natural": { "label": "Dabiiciga" }, + "note": { + "label": "Qoraal" + }, + "office": { + "label": "Nooca" + }, "oneway": { - "label": "Hal Wado" + "label": "Hal Wado", + "options": { + "no": "Maya", + "yes": "Haa" + } }, "oneway_yes": { - "label": "Hal Wado" + "label": "Hal Wado", + "options": { + "no": "Maya", + "yes": "Haa" + } }, "opening_hours": { "label": "Saacado" @@ -344,23 +521,157 @@ "outdoor_seating": { "label": "Fadhiga Banaanka" }, + "parking": { + "label": "Nooca", + "options": { + "surface": "Sagxada" + } + }, + "piste/type": { + "label": "Nooca" + }, + "place": { + "label": "Nooca" + }, + "power": { + "label": "Nooca" + }, + "railway": { + "label": "Nooca" + }, + "relation": { + "label": "Nooca" + }, + "religion": { + "label": "Diinta" + }, + "restriction": { + "label": "Nooca" + }, + "route": { + "label": "Nooca" + }, + "route_master": { + "label": "Nooca" + }, + "second_hand": { + "options": { + "no": "Maya", + "yes": "Haa" + } + }, + "service": { + "label": "Nooca" + }, + "shelter_type": { + "label": "Nooca" + }, + "shop": { + "label": "Nooca" + }, + "site": { + "label": "Nooca" + }, "smoking": { "label": "Sigaar-cabbista waa la oggolyahay" }, + "social_facility": { + "label": "Nooca" + }, "source": { "label": "Bilowga xogta" }, "sport": { "label": "Cayaaraha" }, + "sport_ice": { + "label": "Cayaaraha" + }, + "sport_racing_motor": { + "label": "Cayaaraha" + }, + "sport_racing_nonmotor": { + "label": "Cayaaraha" + }, "structure": { + "label": "Dhismo", "options": { "bridge": "Buundo", - "ford": "Tog" + "ford": "Tog", + "tunnel": "Jid Dalool" + } + }, + "structure_waterway": { + "label": "Dhismo", + "options": { + "tunnel": "Jid Dalool" + } + }, + "studio": { + "label": "Nooca" + }, + "substation": { + "label": "Nooca" + }, + "surface": { + "label": "Sagxada" + }, + "switch": { + "label": "Nooca" + }, + "takeaway": { + "label": "Qaadasho", + "options": { + "no": "Maya", + "yes": "Haa" + } + }, + "toilets/disposal": { + "options": { + "pitlatrine": "Musqulo" } + }, + "tomb": { + "label": "Nooca" + }, + "tourism": { + "label": "Nooca" + }, + "tower/type": { + "label": "Nooca" + }, + "trade": { + "label": "Nooca" + }, + "traffic_calming": { + "label": "Nooca" + }, + "traffic_signals": { + "label": "Nooca" + }, + "transformer": { + "label": "Nooca" + }, + "tunnel": { + "label": "Nooca" + }, + "wall": { + "label": "Nooca" + }, + "water": { + "label": "Nooca" + }, + "waterway": { + "label": "Nooca" + }, + "wetland": { + "label": "Nooca" } }, "presets": { + "address": { + "name": "Cinwaanka" + }, "aeroway/runway": { "name": "Gegada diyaaradaha" }, @@ -403,6 +714,12 @@ "amenity/school": { "name": "Goobaha Dugsiyada" }, + "amenity/toilets": { + "name": "Musqulo" + }, + "area/highway": { + "name": "Sagxada" + }, "barrier": { "name": "Xannibaadaha" }, @@ -433,6 +750,9 @@ "building/school": { "name": "Dhismo Dugsiyada" }, + "building/stadium": { + "name": "Dhismo Garoon" + }, "footway/crosswalk": { "name": "Isgoyska Socotada" }, @@ -460,6 +780,12 @@ "highway/service": { "name": "Jidka Shaqaalaha" }, + "highway/tertiary": { + "name": "Waddada Sarre" + }, + "highway/track": { + "name": "Jidka Jayga aan la Dayactirin" + }, "highway/unclassified": { "name": "Waddo Yar/La cayimin" }, @@ -514,6 +840,12 @@ "leisure/pitch/cricket": { "name": "Garoon Kiriket" }, + "leisure/sports_centre": { + "name": "Xarunta Cayaaraha" + }, + "leisure/stadium": { + "name": "Garoon" + }, "line": { "name": "Khad" }, @@ -535,15 +867,27 @@ "natural/coastline": { "name": "Xeeb" }, + "natural/water": { + "name": "Biyaha" + }, "natural/water/lake": { "name": "Haro" }, "natural/water/pond": { "name": "Balli" }, + "natural/wetland": { + "name": "Dhul biyo-fadhiyaan" + }, + "natural/wood": { + "name": "Duur" + }, "office/government": { "name": "Xafiis Dowladeed" }, + "office/travel_agent": { + "name": "Wakaalad Socdaal" + }, "place": { "name": "Goob" }, @@ -556,6 +900,9 @@ "place/locality": { "name": "Deegaanka" }, + "place/town": { + "name": "Magaalo" + }, "power/line": { "name": "Khadka Korantada" }, @@ -580,14 +927,29 @@ "shop/mobile_phone": { "name": "Dukaanka Taleefoonka Gacanta" }, + "shop/supermarket": { + "name": "Suuq-weyne" + }, + "shop/travel_agency": { + "name": "Wakaalad Socdaal" + }, "tourism/hotel": { "name": "Huteel" }, "type/route/ferry": { "name": "Wadada Doonta" }, + "type/waterway": { + "name": "Biyo Mareen" + }, + "waterway": { + "name": "Biyo Mareen" + }, "waterway/canal": { "name": "Kanaal" + }, + "waterway/dock": { + "name": "Kaabi qoyan / Kaabi qallalan" } } } diff --git a/vendor/assets/iD/iD/locales/sr.json b/vendor/assets/iD/iD/locales/sr.json index 63b076d67..3727760ce 100644 --- a/vendor/assets/iD/iD/locales/sr.json +++ b/vendor/assets/iD/iD/locales/sr.json @@ -160,7 +160,6 @@ "annotation": "Спојено {n} обележја.", "not_eligible": "Ова обележја не могу бити спојена.", "not_adjacent": "Ова обележја не могу бити спојена, јер њихове крајње тачке нису повезане.", - "restriction": "Ова обележја не могу бити спојена, јер барем једно је од њих је члан \"{relation}\" односа.", "incomplete_relation": "Ова обележја не могу бити спојена, јер барем једно од њих није у потпуности учитано.", "conflicting_tags": "Ова обележја не могу бити спојена, јер нека од њихових ознака имају сукобљене вредности." }, @@ -580,13 +579,7 @@ } }, "success": { - "edited_osm": "Уреди ОСМ!", "just_edited": "Управо сте уређивали OpenStreetMap!", - "view_on_osm": "Преглед на OSM", - "facebook": "Подели на Фејсбуку", - "twitter": "Подели на Твитеру", - "google": "Подели на Гугл+", - "help_html": "Ваше измене требало би да се појаве у „Стандардном“ слоју за неколико минута. За остале слојеве и одређене функције то може трајати дуже.", "help_link_text": "Детаљи" }, "confirm": { @@ -1579,7 +1572,6 @@ "label": "Врсте плаћања" }, "phone": { - "label": "Телефон", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -1849,9 +1841,6 @@ "label": "Врста", "placeholder": "Подразумевано" }, - "vending": { - "label": "Врста добара" - }, "visibility": { "label": "Видљивост", "options": { @@ -3662,15 +3651,6 @@ "type/restriction/no_u_turn": { "name": "Забрана полукружног окретања" }, - "type/restriction/only_left_turn": { - "name": "Обавезан смер - лево" - }, - "type/restriction/only_right_turn": { - "name": "Обавезан смер - десно" - }, - "type/restriction/only_straight_on": { - "name": "Обавезан смер - право" - }, "type/route": { "name": "Путања" }, diff --git a/vendor/assets/iD/iD/locales/sv.json b/vendor/assets/iD/iD/locales/sv.json index 50ac65fa7..306a3c7e5 100644 --- a/vendor/assets/iD/iD/locales/sv.json +++ b/vendor/assets/iD/iD/locales/sv.json @@ -1,5 +1,10 @@ { "sv": { + "icons": { + "information": "info", + "remove": "radera", + "undo": "Ã¥ngra" + }, "modes": { "add_area": { "title": "OmrÃ¥de", @@ -145,7 +150,9 @@ "vertex": "Kopplade en väg till en annan väg.", "line": "Kopplade en väg till en linje.", "area": "Kopplade en väg till ett omrÃ¥de." - } + }, + "relation": "Dessa objekt kan inte kopplas ihop dÃ¥ de har motstridiga relationsroller.", + "restriction": "Dessa objekt kan inte kopplas ihop dÃ¥ det skulle skada en relation av typen \"{relation}\"." }, "disconnect": { "title": "Koppla isär", @@ -163,7 +170,8 @@ "annotation": "Sammanfogade {n} objekt.", "not_eligible": "Dessa objekt kan inte sammanfogas.", "not_adjacent": "Dessa objekt kan inte sammanfogas dÃ¥ deras ändar inte är sammankopplade.", - "restriction": "Dessa objekt kan inte sammanfogas dÃ¥ minst en av dem tillhör relationenen \"{relation}\".", + "restriction": "Dessa objekt kan inte sammanfogas dÃ¥ det kommer att skada en relation av typen \"{relation}\".", + "relation": "Dessa objekt kan inte sammanfogas dÃ¥ de har motstridiga relationsroller.", "incomplete_relation": "Dessa objekt kan inte sammanfogas dÃ¥ Ã¥tminstone ett inte är fullständigt nedladdat.", "conflicting_tags": "Dessa objekt kan inte sammanfogas dÃ¥ nÃ¥gra av dess taggar har motstridiga värden." }, @@ -287,10 +295,46 @@ "restriction": { "annotation": { "create": "Lade till en svängrestriktion", - "delete": "Tog bort en svängrestriktion" + "delete": "Raderade en svängrestriktion" } } }, + "restriction": { + "controls": { + "distance": "Distans", + "distance_up_to": "Upp till (distans)", + "via": "Via", + "via_node_only": "Enbart nod", + "via_up_to_one": "Upp till 1 väg", + "via_up_to_two": "Upp till 2 vägar" + }, + "help": { + "indirect": "(indirekt)", + "turn": { + "no_left_turn": "INGEN vänstersväng (indirekt)", + "no_right_turn": "INGEN högersväng (indirekt)", + "no_u_turn": "INGEN U-sväng (indirekt)", + "no_straight_on": "INTE rakt fram (indirekt) ", + "only_left_turn": "ENBART vänstersväng (indirekt)", + "only_right_turn": "ENBART högersväng (indirekt)", + "only_u_turn": "ENBART U-sväng (indirekt)", + "only_straight_on": "ENBART rakt fram (indirekt)", + "allowed_left_turn": "Vänstersväng tillÃ¥ten (indirekt)", + "allowed_right_turn": "Högersväng tillÃ¥ten (indirekt)", + "allowed_u_turn": "U-sväng tillÃ¥ten (indirekt)", + "allowed_straight_on": "Rakt fram tillÃ¥tet (indirekt)" + }, + "from": "FRÅN", + "via": "VIA", + "to": "TILL", + "from_name": "{from} {fromName}", + "from_name_to_name": "{from} {fromName} {to} {toName}", + "via_names": "{via} {viaNames}", + "select_from": "Klicka för att välja ett {from}-segment", + "select_from_name": "Klicka för att välja {from} {fromName}", + "toggle": "Klicka för \"{turn}\"" + } + }, "undo": { "tooltip": "Ångra: {action}", "nothing": "Inget att Ã¥ngra." @@ -366,6 +410,7 @@ "key": "H", "title": "Historik", "selected": "{n} markerad(e)", + "no_history": "Ingen historik (nytt objekt)", "version": "Version", "last_edit": "Senast redigerad", "edited_by": "Redigerad av", @@ -383,6 +428,8 @@ "title": "Mätning", "selected": "{n} markerad(e)", "geometry": "Geometri", + "closed_line": "Stängd linje", + "closed_area": "Stängt omrÃ¥de", "center": "Centrum", "perimeter": "Omkrets", "length": "Längd", @@ -451,7 +498,7 @@ "way": "Väg", "relation": "Relation", "location": "Plats", - "add_fields": "Lägg till fält:" + "add_fields": "Lägg till egenskap:" }, "background": { "title": "Bakgrund", @@ -463,6 +510,7 @@ "switch": "Växla tillbaka till denna bakgrund", "custom": "Anpassa", "custom_button": "Ändra anpassad bakgrund", + "custom_prompt": "Ange en URL-mall för plattor. Giltiga nycklar är:\n  - {zoom} eller {z}, {x}, {y} enligt Z/X/Y-schema\n  - {-y} eller {ty} för Y-koordinat enligt omvänd TMS-stil\n  - {u} för QuadTile-scheman\n  - {switch:a,b,c} för multiplex mot DNS-server\n\nExempel:\n{example}", "overlays": "Bildlager", "imagery_source_faq": "Info om flygfotot / Rapportera ett problem", "reset": "ta bort", @@ -574,6 +622,7 @@ "status_code": "Servern returnerade statuskoden {code}", "unknown_error_details": "Kontrollera att du är ansluten till Internet.", "uploading": "Laddar upp ändringar till OpenStreetMap...", + "conflict_progress": "Söker efter konflikter: {num} av {total}", "unsaved_changes": "Du har osparade ändringar.", "conflict": { "header": "Lös motstridiga ändringar", @@ -599,15 +648,20 @@ } }, "success": { - "edited_osm": "Redigerade OSM!", "just_edited": "Du har nu redigerat OpenStreetMap!", - "view_on_osm": "Visa pÃ¥ OSM", - "facebook": "Dela pÃ¥ Facebook", - "twitter": "Dela pÃ¥ Twitter", - "google": "Dela pÃ¥ Google+", - "help_html": "Dina ändringar borde synas i standardvyn om nÃ¥gra minuter. Andra vyer och vissa objekttyper kan ta lite längre tid.", + "thank_you": "Tack för att du förbättrade kartan.", + "thank_you_location": "Tack för att du förbättrade kartan kring {where}.", + "help_html": "Dina ändringar borde synas pÃ¥ OpenStreetMap om nÃ¥gra minuter. Det kan ta längre tid för andra kartor att fÃ¥ uppdateringar.", "help_link_text": "Detaljer", - "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" + "help_link_url": "https://wiki.openstreetmap.org/wiki/Sv:FAQ#I_have_just_made_some_changes_to_the_map._How_do_I_get_to_see_my_changes.3F", + "view_on_osm": "Visa ändringar pÃ¥ OSM", + "changeset_id": "Ditt ändringsset #: {changeset_id}", + "like_osm": "Gillar OpenStreetMap? Kom i kontakt med andra:", + "more": "Mer", + "events": "Händelser", + "languages": "SprÃ¥k: {languages}", + "missing": "Är det nÃ¥got som saknas i den här listan?", + "tell_us": "Berätta för oss!" }, "confirm": { "okay": "OK", @@ -645,6 +699,7 @@ "untagged_area_tooltip": "Välj en typ som beskriver vad detta omrÃ¥de är.", "untagged_relation": "Otaggad relation", "untagged_relation_tooltip": "Välj en typ som beskriver vad denna relation är.", + "many_deletions": "Du hÃ¥ller pÃ¥ att radera {n} objekt: {p} noder, {l} linjer, {a} omrÃ¥den, {r} relationer Är du helt säker pÃ¥ att du vill göra detta? Detta raderar dem frÃ¥n kartan som alla andra ser pÃ¥ openstreetmap.org.", "tag_suggests_area": "Taggen {tag} indikerar att detta borde vara ett omrÃ¥de istället för en linje", "deprecated_tags": "FörÃ¥ldrade taggar: {tags}" }, @@ -705,11 +760,180 @@ "title": "Redigera & spara", "select_h": "Markera", "select_left_click": "{leftclick} Vänsterklicka pÃ¥ ett objekt för att markera det. Markeringen kommer att synas med ett pulserande glöd, och sidopanelen kommer att visa detaljer om objektet, sÃ¥ som namn och adress.", - "select_right_click": "{rightclick} Högerklicka pÃ¥ ett objekt för att visa redigerarmenyn vilken innehÃ¥ller kommandon som är tillgängliga, sÃ¥ som rotera, flytta och ta bort. ", + "select_right_click": "{rightclick} Högerklicka pÃ¥ ett objekt för att visa redigerarmenyn vilken innehÃ¥ller kommandon som är tillgängliga, sÃ¥ som rotera, flytta och radera. ", "multiselect_h": "Markera flera", - "multiselect_shift_click": "`{shift}`+{leftclick} Vänsterklicka för att markera flera objekt tillsammans. Detta gör det enkelt att flytta och ta bort flera objekt samtidigt.", + "multiselect_shift_click": "`{shift}`+{leftclick} Vänsterklicka för att markera flera objekt tillsammans. Detta gör det enkelt att flytta och radera flera objekt samtidigt.", "multiselect_lasso": "Ett annat sätt att markera flera objekt är att hÃ¥lla ned `{shift}`-tangenten, trycka och hÃ¥lla ned {leftclick} vänster musknapp och sedan dra med musen för att rita ett markeringslasso. Alla punkter inuti lassot kommer att markeras.", - "undo_redo_h": "Ångra & gör om" + "undo_redo_h": "Ångra & gör om", + "undo_redo": "Dina ändringar lagras lokalt i din webbläsare tills dess att du väljer att spara dem pÃ¥ OpenStreetMaps server. Du kan Ã¥ngra ändringar genom att klicka pÃ¥ {undo} **Ångra**-knappen, och göra om dem genom att klicka pÃ¥ {redo} **Gör om**-knappen.", + "save_h": "Spara", + "save": "Klicka pÃ¥ {save} **Spara** för att slutföra dina redigeringar och skicka dem till OpenStreetMap. Du bör komma ihÃ¥g att spara ditt arbete regelbundet!", + "save_validation": "I sparapanelen har du möjlighet att granska vad du har gjort. iD kommer även att utföra nÃ¥gra enkla kontroller av saknad data och kommer att ge hjälpsamma förslag och varningar om nÃ¥got inte verka rätt.", + "upload_h": "Ladda upp", + "upload": "Innan du kan ladda upp dina ändringar mÃ¥ste du ange en [ändringskommentar](https://wiki.openstreetmap.org/wiki/Good_changeset_comments). Klicka sedan pÃ¥ **Ladda upp** för att skicka dina ändringar till OpenStreetMap, där de kommer att införas i kartan och bli publikt synliga för alla.", + "backups_h": "Automatisk backup", + "backups": "Om du inte kan slutföra din redigering pÃ¥ en gÃ¥ng, t.ex. om din dator kraschar eller om du stänger fliken i webbläsaren, är dina ändringar ändÃ¥ sparade i din webbläsare. Du kan komma tillbaka senare (med samma webbläsare och dator) och iD kommer dÃ¥ att erbjuda dig att Ã¥terskapa ditt arbete. ", + "keyboard_h": "Kortokmmandon", + "keyboard": "Du kan visa en lista med kortokmmandon genom att trycka pÃ¥ tangenten `?`." + }, + "feature_editor": { + "title": "Objektredigeraren", + "intro": "*Objektredigeraren* visas bredvid kartan, och lÃ¥ter dig se och ändra all information för valt objekt.", + "definitions": "Den översta sektionen visar objektets typ. Mittsektionen innehÃ¥ller *egenskaper* som visar objektets attribut, sÃ¥ som namn och adress.", + "type_h": "Objekttyp", + "type": "Du kan klicka pÃ¥ objekttyp för att ändra objektet till en annan typ. Allt som finns i den verkliga världen kan läggas till i OpenStreetMap, sÃ¥ det finns tusentals objekttyper att välja bland.", + "type_picker": "Typväljaren visar de vanligaste objekttyperna, sÃ¥ som parker, sjukhus, restauranger, vägar och byggnader. Du kan söka efter vad som helst genom att skriva vad du söker efter i sökrutan. Du kan ocksÃ¥ klicka pÃ¥ {inspect} **Info**-ikonen bredvid en objekttyp för att lära dig mer om den.", + "fields_h": "Egenskaper", + "fields_all_fields": "Sektionen \"Alla egenskaper\" innehÃ¥ller alla objektets detaljer som du kan redigera. I OpenStreetMap är alla egenskaper valfria, och det är ok att lämna en egenskap blank om du är osäker.", + "fields_example": "Varje objekttyp kommer att visa olika egenskaper. En väg t.ex. kan ha egenskaper om dess ytbeläggning och hastighetsbegränsning, medan en restaurang kan har egenskaper om vilken typ av mat de serverar och öppettider. ", + "fields_add_field": "Du kan även klicka pÃ¥ \"Lägg till egenskap\" för att lägga till fler egenskaper, sÃ¥ som beskrivning, Wikipedia-länk, handikappanpassning m.m.", + "tags_h": "Taggar", + "tags_all_tags": "Under sektionen egenskaper kan du trycka pÃ¥ \"Alla taggar\" för att redigera nÃ¥gon av OpenStreetMaps *taggar* för valt objekt. Varje tagg bestÃ¥r av *nyckel* och *värde*, och är dataelement som definierar egenskaper för objektet lagrat pÃ¥ OpenStreetMap.", + "tags_resources": "Att redigera ett objekts taggar kräver viss kunskap om OpenStreetMap. Du bör ta en titt pÃ¥ sidor sÃ¥ som [OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/Main_Page) eller [Taginfo](https://taginfo.openstreetmap.org/) för att lära dig mer om accepterade taggnings-principer pÃ¥ OpenStreetMap." + }, + "points": { + "title": "Punkter", + "intro": "*Punkter* kan användas för att representera objekt sÃ¥ som affärer, restauranger och monument. De markerar en specifik plats och beskriver vad det är.", + "add_point_h": "Lägg till punkter", + "add_point": "För att lägga till en punkt, klicka pÃ¥ knappen {point} **Punkt** i verktygsraden ovanför kartan, eller tryck pÃ¥ kortkommandot `1`. Detta kommer att ändra muspekaren till ett kryss.", + "add_point_finish": "För att placera en ny punkt pÃ¥ kartan, placera muspekaren där den nya punkten ska vara och tryck pÃ¥ {leftclick} vänster musknapp eller `mellanslag`.", + "move_point_h": "Flytta punkter", + "move_point": "För att flytta en punkt, placera muspekaren över punkten och hÃ¥ll ned {leftclick} vänster musknapp medan du drar punkten till dess nya position.", + "delete_point_h": "Radera punkter", + "delete_point": "Det är ok att radera objekt som inte existerar i den verkliga världen. Genom att radera ett objekt frÃ¥n OpenStreetMap raderas det frÃ¥n kartan som alla användare ser, sÃ¥ du bör försäkra dig om att objektet verkligen inte finns i verkligheten innan du raderar det.", + "delete_point_command": "För att radera en punkt, {rightclick} högerklicka pÃ¥ punkten för att markera det och visa redigeramenyn. Använd sedan kommandot {delete} **Radera**." + }, + "lines": { + "title": "Linjer", + "intro": "*Linjer* används för att representera objekt sÃ¥ som vägar, järnvägar och floder. Linjer bör ritas längst mitten av objektet de representerar.", + "add_line_h": "Lägg till linjer", + "add_line": "För att lägga till en linje, klicka pÃ¥ knappen {line} **Linje** i verktygsraden ovanför kartan, eller tryck pÃ¥ kortkommandot `2`. Detta kommer att ändra muspekaren till ett kryss.", + "add_line_draw": "Positionera sedan muspekaren där linjen ska starta och {leftclick} vänsterklicka eller tryck `mellanslag` för att börja placera noder längst linjen. Fortsätt placera noder genom att klicka eller trycka `mellanslag`. Medan du rita kan du zooma in eller flytta kartan för att lägg till fler detaljer. ", + "add_line_finish": "För att slutföra linjen, tryck `{return}` eller klicka igen pÃ¥ senaste noden.", + "modify_line_h": "Modifiera linjer", + "modify_line_dragnode": "Ofta ser du linjer som inte har korrekt form, t.ex. vägar som inte helt matchar med bakgrundsbilden. För att justera formen pÃ¥ en linje, {leftclick} vänsterklicka först pÃ¥ den för att markera den. Alla noder längst linjen kommer att visas som smÃ¥ cirklar. Du kan dra och flytta noderna till bättre platser.", + "modify_line_addnode": "Du kan även skapa nya noder längst en linje genom att {leftclick}**x2** dubbelklicka pÃ¥ linjen eller genom att dra i den lilla triangeln mellan noder.", + "connect_line_h": "Koppla ihop linjer", + "connect_line": "Att ha vägar sammankopplade korrekt är viktigt för kartan, och en förutsättning för att kunna ge navigeringsanvisningar.", + "connect_line_display": "Sammankopplade vägar visas med grÃ¥a cirklar. Ändpunkten av en linje ritas med en stor vit cirkel om den inte är ansluten till nÃ¥got.", + "connect_line_drag": "För att sammankoppla en linje till ett annat objekt, dra en av linjens noder över det andra objektet tills bÃ¥da objekten kopplas ihop. Tips: Du kan hÃ¥lla ned tangenten `{alt}` för att förhindra att noder kopplas ihop med andra objekt. ", + "connect_line_tag": "Om du vet att anslutningen har trafikljus eller övergÃ¥ngsställe kan du lägga till det genom att markera den anslutna noden och använda objektredigeraren för att välja objekttyp.", + "disconnect_line_h": "Koppla isär linjer", + "disconnect_line_command": "För att koppla isär vägar frÃ¥n andra objekt, {rightclick} högerklicka pÃ¥ den anslutna noden och välj kommandot {disconnect} **Koppla isär** i redigeringsmeny. ", + "move_line_h": "Flytta linjer", + "move_line_command": "För att flytta en hel linje, {rightclick} högerklicka pÃ¥ linjen och välj kommandot {move} **Flytta** i redigeringsmeny. Flytta sedan musen och {leftclick} vänsterklicka för att placera linjen pÃ¥ dess nya placering. ", + "move_line_connected": "Linjer som är sammankopplade med andra objekt kommer att förbli sammankopplad när du flyttar linjen till dess nya placering. iD kan förhindra dig att flytta en linje förbi en annan sammankopplad linje.", + "delete_line_h": "Radera linjer", + "delete_line": "Om en linje är helt fel, t.ex. om en väg inte existerar i verkligheten, är det ok att radera den. Var försiktig när du radera objekt: bakgrundsbilden du använder kan vara förÃ¥ldrad, och en väg som ser fel ut kan helt enkelt vara nybyggd.", + "delete_line_command": "För att radera en linje, {rightclick} högerklicka pÃ¥ linjen för att markera den och visa redigeramenyn. Använd sedan kommandot {delete} **Radera**." + }, + "areas": { + "title": "OmrÃ¥den", + "intro": "*OmrÃ¥den* används för att visa utbredningen för objekt sÃ¥ som sjöar, byggnader och bostadsomrÃ¥den. OmrÃ¥den bör ritas längst kanten av objektet de representerar, t.ex. runt en byggnads bottenvÃ¥ning.", + "point_or_area_h": "Punkter eller omrÃ¥den?", + "point_or_area": "MÃ¥nga objekt kan representeras bÃ¥de som punkter och som omrÃ¥den. Du bör rita konturen av byggnader och fastigheter som omrÃ¥den när det är möjligt. Placera punkter inuti en byggnads omrÃ¥de för att representera företag, faciliteter och andra objekt lokaliserade inuti byggnaden.", + "add_area_h": "Lägg till omrÃ¥den", + "add_area_command": "För att lägga till ett omrÃ¥de, klicka pÃ¥ knappen {area} **OmrÃ¥de** i verktygsraden ovanför kartan, eller tryck pÃ¥ kortkommandot `3`. Detta kommer att ändra muspekaren till ett kryss.", + "add_area_draw": "Positionera sedan muspekaren i ett av hörnen för objektet och {leftclick} vänsterklicka eller tryck `mellanslag` för att börja placera noder runt den yttre kanten för omrÃ¥det. Fortsätt placera noder genom att klicka eller trycka `mellanslag`. Medan du rita kan du zooma in eller flytta kartan för att lägg till fler detaljer. ", + "add_area_finish": "För att slutföra ett omrÃ¥de, tryck `{return}` eller klicka igen pÃ¥ antingen första eller senaste noden.", + "square_area_h": "Räta upp hörn", + "square_area_command": "MÃ¥nga omrÃ¥desobjekt sÃ¥ som byggnader har vinkelräta hörn. För att räta upp hörnen för ett omrÃ¥de, {rightclick} högerklicka pÃ¥ kanten för omrÃ¥det och välj kommandot {orthogonalize} **Räta upp** i redigeringsmenyn.", + "modify_area_h": "Modifiera omrÃ¥den", + "modify_area_dragnode": "Ofta ser du omrÃ¥den som inte har korrekt form, t.ex. en byggnad som inte helt matchar med bakgrundsbilden. För att justera formen pÃ¥ ett omrÃ¥de, {leftclick} vänsterklicka först pÃ¥ den för att markera den. Alla noder längst omrÃ¥det kommer att visas som smÃ¥ cirklar. Du kan dra och flytta noderna till bättre platser.", + "modify_area_addnode": "Du kan även skapa nya noder längst ett omrÃ¥de genom att {leftclick}**x2** dubbelklicka pÃ¥ kanten till omrÃ¥det eller genom att dra i den lilla triangeln mellan noder.", + "delete_area_h": "Radera omrÃ¥den", + "delete_area": "Om ett omrÃ¥de är helt fel, t.ex. om en byggnad inte existerar i verkligheten, är det ok att radera den. Var försiktig när du radera objekt - bakgrundsbilden du använder kan vara förÃ¥ldrad, och en byggnad som ser fel ut kan helt enkelt vara nybyggd.", + "delete_area_command": "För att radera ett omrÃ¥de, {rightclick} högerklicka pÃ¥ omrÃ¥det för att markera det och visa redigeramenyn. Använd sedan kommandot {delete} **Radera**." + }, + "relations": { + "title": "Relationer", + "intro": "En *relation* är en speciell typ av objekt i OpenStreetMap som grupperar ihop andra objekt. Objekten som ingÃ¥r i en relation kallas *medlemmar*, och varje medlem har en *roll* i relationen.", + "edit_relation_h": "Redigera relationer", + "edit_relation": "Längst ned i objektredigeraren kan du expandera sektionen \"Alla relationer\" för att se om valt objekt är medlem i nÃ¥gon relation. Du kan sedan klicka pÃ¥ en relation för att redigera den.", + "edit_relation_add": "För att lägga till ett objekt till en relation, markera objektet och klicka pÃ¥ knappen {plus} **Lägg till** längst ned i sektionen \"Alla relationer\" i objektredigeraren. Du kan välja frÃ¥n en lista över närliggande relationer, eller välja \"Ny relation...\".", + "edit_relation_delete": "Du kan även klicka pÃ¥ knappen {delete} **Radera** för att radera valt objekt frÃ¥n relationen. Om du raderar alla medlemmar frÃ¥n en relation kommer relationen automatiskt att raderas. ", + "maintain_relation_h": "Hantera relationer", + "maintain_relation": "För det mesta hanterar iD relationerna automatiskt när du redigerar. Du bör vara försiktig när du ersätter objekt som kan vara medlemmar i relationer. Om du t.ex. raderar en sektion av en väg och ritar en ny sektion för att ersätta den, bör du lägga till den nya sektionen till samma relationer (rutter, svängrestriktioner, etc.) som den ursprungliga vägen.", + "relation_types_h": "Typer av relationer", + "multipolygon_h": "Multipolygoner", + "multipolygon": "En *multipolygon*-relation är en grupp av en eller flera *yttre* objekt och en eller flera *inre* objekt. De yttre objekten definierar den yttre kanten av av multipolygonen, och de inre objekten definierar delomrÃ¥den eller hÃ¥l utklippta inuti multipolygonen.", + "multipolygon_create": "För att skapa en multipolygon, t.ex. en byggnad med hÃ¥l i sig, rita den yttre gränsen som ett omrÃ¥de och den inre gränsen som en linje eller annan typ av omrÃ¥de. `{shift}`+{leftclick} vänsterklicka sedan för att markera bÃ¥da objekten, {rightclick} högerklicka för att visa redigeringsmeny och välj kommandot {merge} **Sammanfoga**.", + "multipolygon_merge": "Sammanfogning av flera linjer eller omrÃ¥den skapar en ny multipolygon-relation med alla markerade omrÃ¥den som medlemmar. iD kommer automatiskt välja rollerna inre och yttre baserat pÃ¥ vilka objekt som finns inuti andra objekt.", + "turn_restriction_h": "Svängrestriktioner ", + "turn_restriction": "En *svängrestriktion*-relation är en grupp av flera vägsegment i en korsning. Svängrestriktioner bestÃ¥r av en *frÃ¥n*-väg, en *via*-nod eller -vägar, och en *till*-väg.", + "turn_restriction_field": "För att redigera svängrestriktioner, markera en korsningsnod där tvÃ¥ eller fler vägar möts. Objektredigeraren kommer att visa en speciell egenskap för svängrestriktioner med en visualisering av korsningen.", + "turn_restriction_editing": "I egenskapen \"Svängrestriktioner\", klicka pÃ¥ en \"frÃ¥n\"-väg för att se om det är tillÃ¥tet eller förbjudet att svänga in pÃ¥ nÃ¥gon av \"till\"-vägarna. Du kan klicka pÃ¥ sväng-ikonerna för att växla dem mellan tillÃ¥tet och förbjudet. iD kommer automatiskt skapa relationer och sätta rollerna \"frÃ¥n\", \"via\" och \"till\" baserat pÃ¥ dina val.", + "route_h": "Rutter", + "route": "En *rutt*-relation är en grupp av en eller flera linjer som tillsammans formar ett ruttnätverk, sÃ¥ som buss-rutter, tÃ¥g-rutter eller väg-rutt.", + "route_add": "För att lägga till ett objekt till en rutt-relation, välj objektet och bläddra ned till sektionen \"Alla relationer\" i objektredigeraren. Klicka sedan pÃ¥ knappen {plus} **Lägg till** för att lägga till detta objekt till en närliggande existerande relation eller en ny relation.", + "boundary_h": "Gränser", + "boundary": "En *gräns*-relation är en grupp av en eller flera linjer som tillsammans formar en administrativ gräns.", + "boundary_add": "För att lägga till ett objekt till en gräns-relation, välj objektet och bläddra ned till sektionen \"Alla relationer\" i objektredigeraren. Klicka sedan pÃ¥ knappen {plus} **Lägg till** för att lägga till detta objekt till en närliggande existerande relation eller en ny relation." + }, + "imagery": { + "title": "Bakgrundsbilder", + "intro": "Bakgrundsbilderna som visas under kartdata är en viktig källa vid kartläggning. Dessa bilder kan vara flygfoton insamlade med satellit, flygplan eller drönare, eller sÃ¥ kan det vara inskannade historiska kartor eller andra fritt tillgängliga källor.", + "sources_h": "Bildkällor", + "choosing": "För att se vilka bildkällor som finns tillgängliga vid redigering, klicka pÃ¥ knappen {layers} **Bakgrundsinställningar** vid sidan av kartan.", + "sources": "Som standard är satellitelagret [Bing Maps](https://www.bing.com/maps/) valt som bakgrundsbild. Beroende pÃ¥ var du redigerar, finns andra bildkällor tillgängliga. Vissa kan vara nyare eller har bättre upplösning, sÃ¥ det är alltid klokt att kontrollera vilket lager som är bäst som referens vid kartering.", + "offsets_h": "Justera bildplacering", + "offset": "Bilder är ibland förskjutna lite i förhÃ¥llande till korrekt kartdata. Om du ser att mÃ¥nga vägar eller byggnader är förskjutna i förhÃ¥llande till bakgrundsbilden kan det vara bakgrundsbilden som är felaktig, sÃ¥ flytta dem inte bara för att matcha bakgrunden. Justera istället bakgrunden sÃ¥ att den matchar med existerande data genom att expandera sektionen \"Justera bildplacering\" längst ned i panelen Bakgrundsinställningar.", + "offset_change": "Klicka pÃ¥ de smÃ¥ trianglarna för att justera bildplaceringen i smÃ¥ steg, eller hÃ¥ll ned vänster musknapp och dra i den grÃ¥ rutan för att dra bilden till korrekt placering." + }, + "streetlevel": { + "title": "Gatubilder", + "intro": "Gatubilder är användbart vid kartläggning av trafikmärken, företag och andra detaljer som du inte kan se frÃ¥n satellit- eller flygbilder. iD stöder gatubilder frÃ¥n [Mapillary](https://www.mapillary.com) och [OpenStreetCam](https://www.openstreetcam.org).", + "using_h": "Använda gatubilder", + "using": "För att använda gatubilder för kartläggning, klicka pÃ¥ panelen {data} **Kartdata** vid sidan av kartan för att aktivera eller avaktivera tillgängliga bildlager.", + "photos": "När aktiverad visar bildlagret en linje längst sekvensen av bilder. Vid högre inzoomning visas en cirkel för varje bild, och vid ännu högre zoom-nivÃ¥ visar en kon riktningen kameran hade när bilden togs.", + "viewer": "När du klickar pÃ¥ en av bildernas placering visas en bildvisare i det nedre vänstra hörnet av kartan. Bildvisaren innehÃ¥ller kontroller för att stega framÃ¥t eller bakÃ¥t i bildsekvensen. Den visar även användarnamn pÃ¥ personen som tog bilden, datum dÃ¥ den togs och en länk för att visa bilden pÃ¥ originalsidan." + }, + "gps": { + "title": "GPS-spÃ¥r", + "intro": "Insamlade GPS-spÃ¥r är en värdefull datakälla för OpenStreetMap. Denna redigerare stöder filtyperna *.gpx*, *.geojson* och *.kml* pÃ¥ din lokala dator. Du kan samla in GPS-spÃ¥r med en smartmobil, sportklocka eller andra GPS-enheter.", + "survey": "För information om hur du utför en GPS-uppmätning, läs [Kartlägg med en smartmobil, GPS eller papper](http://learnosm.org/en/mobile-mapping/).", + "using_h": "Använda GPS-spÃ¥r", + "using": "För att använda ett GPS-spÃ¥r vid kartläggning, dra och släpp datafilen pÃ¥ kartredigeraren. Om den har ett känt format kommer den att ritas pÃ¥ kartan med en ljus lila linje. Klicka pÃ¥ panelen {data} **Kartdata** vid sidan av kartan för att aktivera, avaktivera eller zooma din GPS-data.", + "tracing": "GPS-spÃ¥ret skickas inte till OpenStreetMap - bästa sättet att använda den är att rita pÃ¥ kartan användandes den som guide för nya objekt du lägger till.", + "upload": "Du kan även [ladda upp dina GPS-data till OpenStreetMap](https://www.openstreetmap.org/trace/create) sÃ¥ att andra kan använda det." + }, + "field": { + "restrictions": { + "title": "Hjälp för svängrestriktioner ", + "about": { + "title": "Om", + "about": "Denna egenskap lÃ¥ter dig inspektera och ändra svängrestriktioner. Den visar en modell över vald korsning inklusive närliggande anslutande vägar.", + "from_via_to": "En svängrestriktion innehÃ¥ller alltid: en **FRÅN-väg**, en **TILL-väg** och antingen en **VIA-nod** eller en eller flera **VIA-vägar**.", + "maxdist": "\"{distField}\"-reglaget kontrollerar hur lÃ¥ngt den ska söka för ytterligare anslutande vägar.", + "maxvia": "\"{viaField}\"-reglaget justerar hur mÃ¥nga vägar som kan ingÃ¥ i sökningen. (Tips: enkelhet är bättre)" + }, + "inspecting": { + "title": "Inspektera", + "about": "HÃ¥ll musen över ett **FRÅN**-segment för att se om den har nÃ¥gra svängrestriktioner. Varje möjlig **TILL**-destination kommer att visas med en färglagd skugga om restriktioner finns.", + "from_shadow": "{fromShadow} **FRÅN-segment**", + "allow_shadow": "{allowShadow} **TILL tillÃ¥ten**", + "restrict_shadow": "{restrictShadow} **TILL förbjuden**", + "only_shadow": "{onlyShadow} **TILL enbart**", + "restricted": "\"Förbjuden\" betyder att det finns en svängrestriktion, t.ex. \"Ingen vänstersväng\".", + "only": "\"Enbart\" betyder att ett fordon som tar den vägen enbart kan göra det valet, t.ex. \"Enbart rakt fram\"." + }, + "modifying": { + "title": "Ändra", + "about": "För att ändra svängrestriktioner, klicka först pÃ¥ ett **FRÅN**-segment att starta frÃ¥n. Det valda segmentet kommer att pulsera, och alla möjliga **TILL**-destinationer kommer att visas med svängsymboler.", + "indicators": "Klicka sedan pÃ¥ en svängsymbol för att växla den mellan \"TillÃ¥ten\", \"Förbjuden\" och \"Enbart\"", + "allow_turn": "{allowTurn} **TILL tillÃ¥ten**", + "restrict_turn": "{restrictTurn} **TILL förbjuden**", + "only_turn": "{onlyTurn} **TILL enbart**" + }, + "tips": { + "title": "Tips", + "simple": "**Föredra enkla restriktioner över komplexa.**", + "simple_example": "Undvik t.ex. att skapa en \"via väg\"-restriktion om en simpel \"via nod\"-restriktion räcker.", + "indirect": "**Vissa restriktioner visar texten \"(indirekt)\" och ritas lätt transparenta.**", + "indirect_example": "Dessa restriktioner existerar tack vare en annan närliggande restriktion. T.ex. en \"Enbart rakt fram\"-restriktion kommer indirekt skapa \"Ingen sväng\"-restriktioner för alla andra vägar genom korsningen.", + "indirect_noedit": "Du bör inte redigera indirekta restriktioner. Ändra istället den närliggande direkta restriktionen." + } + } } }, "intro": { @@ -861,12 +1085,12 @@ "selected_townhall": "Vad bra! Punkten är nu markerad. Markerade objekt visas med en pulserande glödande ram.", "editor_townhall": "När ett objekt är markerat visas *objektredigeraren* bredvid kartan.", "preset_townhall": "Högst upp i objektredigeraren visas objekttyp. Denna punkt representerar ett {preset}.", - "fields_townhall": "Mittdelen av objektredigeraren innehÃ¥ller *fält* som visar objektets attribut, sÃ¥som namn och adress. ", + "fields_townhall": "Mittdelen av objektredigeraren innehÃ¥ller *egenskaper* som visar objektets attribut, sÃ¥som namn och adress. ", "close_townhall": "**Stäng objektredigeraren genom att trycka pÃ¥ Escape pÃ¥ tangentbordet eller genom att trycka pÃ¥ knappen {button} i övre högra hörnet. ", "search_street": "Du kan ocksÃ¥ söka efter objekt i aktuell vy eller globalt. **Sök efter '{name}'.**", "choose_street": "**Välj {name} i listan för att markera den.**", "selected_street": "Vad bra! {name} är nu markerad.", - "editor_street": "Fälten som visas för en väg är annorlunda mot fälten som visades för kommunhuset.{br}För markerad gata visar objektredigeraren fält som '{field1}' och '{field2}'. **Stäng objektredigeraren genom att trycka Escape eller trycka pÃ¥ knappen {button}.", + "editor_street": "Egenskaperna som visas för en väg är annorlunda mot egenskaperna som visades för kommunhuset.{br}För markerad gata visar objektredigeraren egenskaper som '{field1}' och '{field2}'. **Stäng objektredigeraren genom att trycka Escape eller trycka pÃ¥ knappen {button}.", "play": "Prova att flytta runt pÃ¥ kartan och klicka pÃ¥ nÃ¥gra andra objekt för att se vad för typ av saker som kan läggas till i OpenStreetMap. **När du är redo att fortsätta till nästa kapitel, tryck '{next}'.**" }, "points": { @@ -876,7 +1100,7 @@ "search_cafe": "Det finns mÃ¥nga olika typer av objekt som kan representeras med punkter. Punkten du just lade till är ett café. **Sök efter '{preset}'.**", "choose_cafe": "**Välj {preset} i listan.**", "feature_editor": "Punkten är nu markerad som ett café. Med hjälp av objektredigeraren kan vi lägga till mer information om caféet. ", - "add_name": "PÃ¥ OpenStreetMap är alla fält valfria, och det är ok att lämna ett fält tomt om du är osäker.{br}LÃ¥t oss lÃ¥tsas att du har lokalkännedom om caféet och vet dess namn. **Lägg till ett namn pÃ¥ caféet.**", + "add_name": "PÃ¥ OpenStreetMap är alla egenskaper valfria, och det är ok att lämna en egenskap tomt om du är osäker.{br}LÃ¥t oss lÃ¥tsas att du har lokalkännedom om caféet och vet dess namn. **Lägg till ett namn pÃ¥ caféet.**", "add_close": "Objektredigeraren kommer ihÃ¥g alla dina ändringar automatiskt. **När du är klar med att lägga till ett namn, tryck Escape, Enter eller klicka pÃ¥ knappen {button} för att stänga objektredigeraren.**", "reselect": "Ofta existerar redan punkter men är felaktiga eller ofullständiga. Vi kan ändra redan existerande punkter. **Klicka för att markera caféet du just skapade.**", "update": "LÃ¥t oss fylla i lite mer information om caféet. Du kan ändra dess namn, ange vad för typ av mat som serveras eller lägga till en adress. **Ändra information om caféet.**", @@ -888,14 +1112,15 @@ }, "areas": { "title": "OmrÃ¥den", + "add_playground": "*OmrÃ¥den* används för att visa avgränsningar för objekt sÃ¥ som sjöar, byggnader och bostadsomrÃ¥den.{br}De kan ocksÃ¥ användas för mer detaljerad kartläggning av mÃ¥nga objekt som du kanske normalt skulle kartlägga som punkter. **Klicka pÃ¥ knappen {button} OmrÃ¥de för att skapa ett nytt omrÃ¥de.**", "start_playground": "LÃ¥t oss lägga till denna lekplats pÃ¥ kartan genom att rita ett omrÃ¥de. OmrÃ¥den ritas genom att placera *noder* längs yttre kanten av objektet. **Klicka eller tryck mellanslag för att placera en startnod pÃ¥ ett av hörnen av lekplatsen.**", "continue_playground": "Fortsätt rita omrÃ¥det genom att placera noder längs kanten pÃ¥ lekplatsen. Det är ok att ansluta omrÃ¥det till existerande gÃ¥ngvägar.{br}Tips: Du kan hÃ¥lla ned '{alt}'-tangenten för att förhindra att noder kopplas ihop med andra objekt. **Fortsätt att rita ett omrÃ¥de runt lekplatsen.**", "finish_playground": "Slutför omrÃ¥det genom att trycka Enter eller genom att trycka igen pÃ¥ antingen första eller sista noden. **Rita färdigt omrÃ¥det för lekplatsen.**", "search_playground": "**Sök efter '{preset}'.**", "choose_playground": "**Välj {preset} i listan.**", - "add_field": "Denna lekplats har inget officiellt namn, sÃ¥ vi anger inget i namnfältet.{br}LÃ¥t oss lägga till lite andra detaljer om lekplatsen i fältet Beskrivning. **Öppna listan för Lägg till fält.**", + "add_field": "Denna lekplats har inget officiellt namn, sÃ¥ vi anger inget för egenskapen namn.{br}LÃ¥t oss lägga till lite andra detaljer om lekplatsen i egenskapen Beskrivning. **Öppna listan för Lägg till egenskap.**", "choose_field": "**Välj {field} i listan.**", - "retry_add_field": "Du valde inte fältet {field}. LÃ¥t oss försöka igen.", + "retry_add_field": "Du valde inte egenskapen {field}. LÃ¥t oss försöka igen.", "describe_playground": "**Ange en beskrivning och klicka sedan pÃ¥ knappen {button} för att stänga objektredigeraren.**", "play": "Bra jobbat! Prova att rita lite fler omrÃ¥den för att se vad för typ av omrÃ¥den du kan lägga till pÃ¥ OpenStreetMap. **När du är redo att fortsätta till nästa kapitel, klicka pÃ¥ '{next}'.**" }, @@ -1016,7 +1241,8 @@ "title": "Markera objekt", "select_one": "Markera ett enskilt objekt", "select_multi": "Markera flera objekt", - "lasso": "Rita en markeringslasso runt objekt" + "lasso": "Rita en markeringslasso runt objekt", + "search": "Hitta objekt som matchar söktext" }, "with_selected": { "title": "Med objekt markerat", @@ -1562,6 +1788,9 @@ "display": { "label": "Visning" }, + "distance": { + "label": "Distans totalt" + }, "dock": { "label": "Typ" }, @@ -1602,6 +1831,9 @@ "except": { "label": "Undantag" }, + "faces": { + "label": "Sidor" + }, "fax": { "label": "Fax", "placeholder": "+46 31 123 4567" @@ -1713,6 +1945,39 @@ "label": "Basketkorgar", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Dressyrriding", + "options": { + "equestrian": "Ja", + "undefined": "Nej" + } + }, + "horse_riding": { + "label": "Ridning", + "options": { + "horse_riding": "Ja", + "undefined": "Nej" + } + }, + "horse_scale": { + "label": "SvÃ¥righetsgrad - Ridning", + "options": { + "common": "Lätt: Inga problem eller svÃ¥righeter (standard).", + "critical": "Gränsfall: Passar endast för erfarna ryttare och hästar. Större hinder. Broar bör undersökas noggrant.", + "dangerous": "Farligt: Passar endast för mycket erfarna ryttare och hästar och endast i gott väder. Sitt av.", + "demanding": "Används med försiktighet: Ojämnt underlag, ibland svÃ¥ra passager.", + "difficult": "SvÃ¥rt: Smal och utsatt väg. Kan ha hinder att gÃ¥ över och smala passager.", + "impossible": "Oframkomlig: Väg eller bro som inte är lämplig för hästar. För smal, har otillräckligt stöd, hinder (t.ex. stegar). Livsfara." + }, + "placeholder": "SvÃ¥rt, farligt..." + }, + "horse_stables": { + "label": "Ridstall", + "options": { + "stables": "Ja", + "undefined": "Nej" + } + }, "iata": { "label": "IATA" }, @@ -1725,13 +1990,16 @@ "incline_steps": { "label": "Lutning", "options": { - "down": "Ner", + "down": "Ned", "up": "Upp" } }, "indoor": { "label": "Inomhus" }, + "industrial": { + "label": "Typ" + }, "information": { "label": "Typ" }, @@ -1852,6 +2120,10 @@ "label": "Hastighetsbegränsning", "placeholder": "50, 70, 90..." }, + "maxspeed/advisory": { + "label": "Rekommenderad lägre hastighet", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "Maxtid" }, @@ -1865,7 +2137,7 @@ "label": "Mäter" }, "mtb/scale": { - "label": "Mountainbike-svÃ¥righet", + "label": "SvÃ¥righetsgrad - Mountainbike", "options": { "0": "0: Fast grus/packad jord, inga hinder, breda kurvor", "1": "1: Delvis löst underlag, smÃ¥ hinder, breda kurvor", @@ -1889,7 +2161,7 @@ "placeholder": "Enkel, medel, svÃ¥r..." }, "mtb/scale/uphill": { - "label": "Mountainbike svÃ¥righetsgrad uppför", + "label": "SvÃ¥righetsgrad - Mountainbike uppför", "options": { "0": "0: Genomsnittlig lutning <10%, grus/packad jord, inga hinder", "1": "1: Genomsnittlig lutning <15%, grus/packad jord, fÃ¥ smÃ¥ hinder", @@ -2159,7 +2431,7 @@ "label": "Typ" }, "sac_scale": { - "label": "SvÃ¥righetsgrad", + "label": "SvÃ¥righetsgrad - Vandring", "options": { "alpine_hiking": "T4: Alpin vandring", "demanding_alpine_hiking": "T5: Krävande alpin vandring", @@ -2440,8 +2712,19 @@ "label": "Typ", "placeholder": "Standard" }, + "usage_rail": { + "label": "AnvändningsomrÃ¥de", + "options": { + "branch": "SidospÃ¥r", + "industrial": "IndustrispÃ¥r", + "main": "HuvudspÃ¥r", + "military": "Militärt spÃ¥r", + "test": "TestspÃ¥r", + "tourism": "Museijärnväg" + } + }, "vending": { - "label": "Typ av varor" + "label": "Typ av gods" }, "visibility": { "label": "Synlighet", @@ -2536,6 +2819,10 @@ "name": "Annonstavla", "terms": "Annonstavla, reklamtavla, reklam, reklamskylt, affisch, affischtavla" }, + "advertising/column": { + "name": "Reklampelare", + "terms": "reklampelare, affischpelare, billboard, annonspelare, annonstavla, annonsering, marknadsföring, reklam, annons, affisch, annons, reklamplats" + }, "aerialway": { "name": "Linbana" }, @@ -2621,6 +2908,10 @@ "name": "Flygterminal", "terms": "Flygplatsterminal, terminal, avgÃ¥ngshall, ankomsthall, flygterminal, flygplats" }, + "allotments/plot": { + "name": "Kolonilott", + "terms": "Kolonilott, lott, täppa, koloniträdgÃ¥rd, odlingslott, koloniomrÃ¥de, koloni" + }, "amenity": { "name": "Facilitet" }, @@ -2849,6 +3140,10 @@ "name": "Marknadsplats", "terms": "Saluhall, torg, marknad, salutorg" }, + "amenity/monastery": { + "name": "KlosteromrÃ¥de", + "terms": "allah, andaktslokal, andaktsrum, andaktssal, andligt omrÃ¥de, annexkyrka, basilika, begravningskapell, betel, bönehus, böneplats, bönhus, dom, dopkapell, dyrkan, fristad, församling, gravkapell, gud, guds hus, gudshus, gudstjänst, gudstjänstlokal, gudstjänstslokal, helgedom, kapell, katedral, kloster, kor, korkapell, kranskapell, kristen, kristendom, kyrka, kyrkbyggnad, kyrkobyggnad, kyrkogÃ¥rd, kyrkorum, kyrksal, mission, missionshus, moske, moské, mässkapell, predikan, religion, religiös, religiös anläggning, religiöst omrÃ¥de, sanktuarium, sidokapell, synagoga, tabernakel, tempel, tempelomrÃ¥de, tillbedjan, tro, vallfärdsort, vallfärgsplats" + }, "amenity/motorcycle_parking": { "name": "Motorcykelparkering", "terms": "Motorcykelparkering, parkering motorcykel, ställplats, motorcykelställ, parkering, motorcykel, parkeringsplats, parkeringsplats motorcykel" @@ -2886,7 +3181,7 @@ }, "amenity/place_of_worship": { "name": "Plats för tillbedjan", - "terms": "allah,basilika,betel,bönehus,böneplats,dom,dyrkan,fristad,församling,gud,guds hus,gudshus,gudstjänstlokal,helgedom,kapell,katedral,kloster,kor,kyrka,kyrkobyggnad,mission,missionshus,moske,moské,mässkapell,pastorat,predikan,religion,sanktuarium,socken,synagoga,tabernakel,tempel,tillbedjan,tro,vallfärgsplats,vallfärdsort" + "terms": "allah, andaktslokal, andaktsrum, andaktssal, andligt omrÃ¥de, annexkyrka, basilika, begravningskapell, betel, bönehus, böneplats, bönhus, dom, dopkapell, dyrkan, fristad, församling, gravkapell, gud, guds hus, gudshus, gudstjänst, gudstjänstlokal, gudstjänstslokal, helgedom, kapell, katedral, kloster, kor, korkapell, kranskapell, kristen, kristendom, kyrka, kyrkbyggnad, kyrkobyggnad, kyrkogÃ¥rd, kyrkorum, kyrksal, mission, missionshus, moske, moské, mässkapell, pastorat, predikan, religion, religiös, religiös anläggning, religiöst omrÃ¥de, sanktuarium, sidokapell, slottskapell, socken, synagoga, tabernakel, tempel, tempelomrÃ¥de, tillbedjan, tro, vallfärdsort, vallfärgsplats" }, "amenity/place_of_worship/buddhist": { "name": "Buddhisttempel", @@ -2894,7 +3189,7 @@ }, "amenity/place_of_worship/christian": { "name": "Kyrka", - "terms": "Kyrka, tempel, gudshus, kyrkobyggnad, kapell, bönehus, böneplats, missionshus, dom, katedral, helgedom, gudstjänstlokal,tro, religion, helgedom, kristen, kristendom, församling, tillbedjan, predikan, katedral, kor, kapell, guds hus, gud, bönehus, socken, helgedom, tempel" + "terms": "andaktslokal, andaktsrum, andaktssal, andligt omrÃ¥de, annexkyrka, basilika, begravningskapell, betel, bönehus, böneplats, bönhus, dom, dopkapell, dyrkan, fristad, församling, gravkapell, gud, guds hus, gudshus, gudstjänst, gudstjänstlokal, gudstjänstslokal, helgedom, kapell, katedral, kloster, kor, korkapell, kranskapell, kristen, kristendom, kyrka, kyrkbyggnad, kyrkobyggnad, kyrkogÃ¥rd, kyrkorum, kyrksal, mission, missionshus, mässkapell, pastorat, predikan, religion, religiös, religiös anläggning, religiöst omrÃ¥de, sanktuarium, sidokapell, slottskapell, socken, tabernakel, tempel, tempelomrÃ¥de, tillbedjan, tro, vallfärdsort, vallfärgsplats" }, "amenity/place_of_worship/hindu": { "name": "Hindutempel", @@ -3053,6 +3348,10 @@ "name": "Cigarettautomat", "terms": "Cigarettautomat, cigaretter, snusautomat, tobaksautomat" }, + "amenity/vending_machine/coffee": { + "name": "Kaffeautomat", + "terms": "Kaffeautomat, kaffe, Espresso, expresso, te, the, Varuautomat, varumaskin" + }, "amenity/vending_machine/condoms": { "name": "Kondomautomat", "terms": "Kondomautomat, kondomomat, kondomer" @@ -3061,6 +3360,14 @@ "name": "Dryckesautomat ", "terms": "dryckesautomat, dryckautomat, drickautomat, läskautomat, kaffemaskin, kaffeautomat, läsk, kaffe, dryck, juice" }, + "amenity/vending_machine/electronics": { + "name": "Varumaskin för elektronik", + "terms": "Varumaskin för elektronik, varumaskin, varuautomat, elektronik, kablar, laddkablar, laddkabel, kabel, laddare, öronsnäckor, hörlurar, telefon, mobiltelefon, pekplatta, surfplatta" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Elongated coin-maskin (myntpressmaskin)", + "terms": "elongated coin, souvenirmynt, minnesmynt, souvenir, minne, mynt, elongated coin-maskin, myntpressmaskin, minnesmyntmaskin, ECM, Penny Press, elongated penny, coin maskin" + }, "amenity/vending_machine/excrement_bags": { "name": "BajspÃ¥sar", "terms": "BajspÃ¥sar, hundbajspÃ¥sar, hundpÃ¥sar, hundbajs, hundskit, skitpÃ¥se, avföringspÃ¥se, bajs, hund, djur" @@ -3069,6 +3376,18 @@ "name": "Varumaskin för mensskydd", "terms": "Varumaskin för mensskydd, mensskydd, kondom, tampong, bindor, binda, kvinna, kvinnor, mens, menstruation" }, + "amenity/vending_machine/food": { + "name": "Matvaruautomat", + "terms": "Matvaruautomat, mat, matautomat, matvarumaskin, Varuautomat, varumaskin, mellanmÃ¥l" + }, + "amenity/vending_machine/fuel": { + "name": "Bränslepump", + "terms": "Bränslepump, bensin, etanol, diesel, bränsle, propan, ing, cng, biodiesel, pump, tapp, tanka, tankomat, tankstation, mack, bensinstation" + }, + "amenity/vending_machine/ice_cream": { + "name": "Glassautomat", + "terms": "Glassautomat, glass, isglass, Varuautomat, varumaskin" + }, "amenity/vending_machine/news_papers": { "name": "Tidningsautomat" }, @@ -3288,15 +3607,15 @@ }, "building/cathedral": { "name": "Katedral", - "terms": "Katedral, domkyrka, biskop, dom, biskopskyrka, kyrka, Huvudkyrka, stiftskyrka" + "terms": "Katedral, domkyrka, biskop, dom, biskopskyrka, kyrka, Huvudkyrka, stiftskyrka, andligt omrÃ¥de, basilika, dyrkan, fristad, gud, guds hus, gudshus, gudstjänst, helgedom, kloster, kristen, kristendom, kyrkbyggnad, kyrkobyggnad, kyrkogÃ¥rd, kyrkorum, kyrksal, predikan, religion, religiös, religiös anläggning, religiöst omrÃ¥de, tillbedjan, tro, vallfärdsort, vallfärgsplats" }, "building/chapel": { "name": "Kapell", - "terms": "Kapell, kyrkobyggnad, sidokapell, Kranskapell, gudstjänstlokal, korkapell, slottskapell, begravningskapell, gravkapell, dopkapell, andaktsrum, annexkyrka, bönhus, bönehus, kyrkorum" + "terms": "Kapell, kyrkobyggnad, sidokapell, Kranskapell, gudstjänstlokal, korkapell, slottskapell, begravningskapell, gravkapell, dopkapell, andaktsrum, annexkyrka, bönhus, bönehus, kyrkorum, andaktslokal, andaktssal, böneplats, dyrkan, fristad, gud, guds hus, gudshus, gudstjänst, gudstjänstlokal, helgedom, kor, kristen, kristendom, kyrka, kyrkbyggnad, kyrkogÃ¥rd, kyrksal, mission, missionshus, mässkapell, predikan, religion, religiös, religiös anläggning, religiöst omrÃ¥de, sanktuarium, socken, tempel, tempelomrÃ¥de, tillbedjan, tro" }, "building/church": { "name": "Kyrkobyggnad", - "terms": "Kyrka, kyrkobyggnad, kyrkbyggnad, kyrksal, andaktssal, missionshus, gudstjänst, gudstjänstslokal, andaktslokal, gudshus" + "terms": "Kyrka, kyrkobyggnad, kyrkbyggnad, kyrksal, andaktssal, missionshus, gudstjänst, gudstjänstslokal, andaktslokal, gudshus, andaktsrum, andligt omrÃ¥de, annexkyrka, basilika, begravningskapell, betel, bönehus, böneplats, bönhus, dom, dopkapell, dyrkan, fristad, församling, gravkapell, gud, guds hus, gudstjänstslokal, helgedom, kapell, katedral, kloster, kor, korkapell, kranskapell, kristen, kristendom, kyrkogÃ¥rd, kyrkorum, mission, mässkapell, pastorat, predikan, religion, religiös, religiös anläggning, religiöst omrÃ¥de, sanktuarium, sidokapell, slottskapell, socken, tabernakel, tempel, tempelomrÃ¥de, tillbedjan, tro, vallfärdsort, vallfärgsplats" }, "building/civic": { "name": "Kommunal byggnad", @@ -3307,11 +3626,11 @@ "terms": "Gymnasie, gymnasium, gymnasiebyggnad, universitet" }, "building/commercial": { - "name": "Kommersiell byggnad", + "name": "Kontorsbyggnad", "terms": "Kommersiell byggnad, kommersiellt, affärsbyggnad, handelsbyggnad" }, "building/construction": { - "name": "Byggnad under konstruktion", + "name": "Byggnad under uppförande", "terms": "Byggnad under konstruktion, Byggnad under uppförande, byggarbete, bygge, byggarbetsplats, byggnation, byggnadsplats" }, "building/detached": { @@ -3409,10 +3728,17 @@ "name": "Stall", "terms": "Stall, hästar, häst, stallbyggnad, ridhus, ridhusanläggning" }, + "building/stadium": { + "name": "Stadionbyggnad", + "terms": "stadium, Stadion, arena, Stadionbyggnad, arenabyggnad, byggnad, stadion, friidrottsstadion" + }, "building/static_caravan": { "name": "Villavagn", "terms": "Villavagn, husvagn, campingvagn" }, + "building/temple": { + "name": "Tempelbyggnad" + }, "building/terrace": { "name": "Terrasshus", "terms": "Terrasshus" @@ -3432,6 +3758,9 @@ "name": "Tältplats/husvagnsplats", "terms": "Tältplats, husvagnsplats, camping, Campingplats, camping, husvagn, tält" }, + "circular": { + "name": "Trafikcirkel" + }, "club": { "name": "Klubb", "terms": "klubb, socialt, förening, klubblokal, föreningslokal, sällskap, sammanslutning" @@ -3805,6 +4134,10 @@ "name": "Ridväg", "terms": "Ridväg, ridstig, häst, rida, ridning, ryttare, " }, + "highway/bus_guideway": { + "name": "SpÃ¥rbuss", + "terms": "SpÃ¥rbuss, buss, guidad buss" + }, "highway/bus_stop": { "name": "BusshÃ¥llplats / Bussplattform" }, @@ -3864,6 +4197,10 @@ "name": "Anslutning, motorväg", "terms": "Anslutning, motorvägsanslutning, pÃ¥fart, avfart, trafikplats" }, + "highway/passing_place": { + "name": "Mötesplats", + "terms": "Mötesplats, passage, passeringsplats, möte" + }, "highway/path": { "name": "Stig", "terms": "Stig, gÃ¥ng, led, spÃ¥r, gÃ¥ngväg, vandringsled, vandra, vandring, promenad, löparbana, motionsspÃ¥r" @@ -4062,7 +4399,7 @@ }, "landuse/churchyard": { "name": "KyrkogÃ¥rd (utan gravar)", - "terms": "KyrkogÃ¥rd, kyrka, kyrkomrÃ¥de" + "terms": "KyrkogÃ¥rd, kyrka, kyrkomrÃ¥de, andligt omrÃ¥de, begravningskapell, gravkapell, kristen, kristendom, religion, religiös, religiöst omrÃ¥de" }, "landuse/commercial": { "name": "Kommersiell omrÃ¥de", @@ -4087,6 +4424,10 @@ "name": "Skog (brukad)", "terms": "Skog, skogsvÃ¥rd, skogsomrÃ¥de, skogstrakt, träd, skogsdunge, dunge, lund, skogsplantering" }, + "landuse/garages": { + "name": "GarageomrÃ¥de", + "terms": "GarageomrÃ¥de, garage, bilstall, bilskjul, carport, varmgarage, kallgarage, bilplatser, parking" + }, "landuse/grass": { "name": "Gräs", "terms": "Gräs, klippt gräs, refug, rondell, mittremsa" @@ -4193,7 +4534,7 @@ }, "landuse/religious": { "name": "Religiöst omrÃ¥de", - "terms": "Religiöst omrÃ¥de, religiös, religion, tillbedjan, kyrka, moské, synagoga, kyrkogÃ¥rd, religiös anläggning, tempelomrÃ¥de, tempel, böneplats, andligt omrÃ¥de" + "terms": "Religiöst omrÃ¥de, religiös, religion, tillbedjan, kyrka, moske, moské, synagoga, kyrkogÃ¥rd, religiös anläggning, tempelomrÃ¥de, tempel, böneplats, andligt omrÃ¥de, dyrkan, gud, helgedom, kristen, kristendom, tro, vallfärdsort, vallfärgsplats" }, "landuse/residential": { "name": "BostadsomrÃ¥de", @@ -4215,6 +4556,14 @@ "name": "Center för vuxenspel", "terms": "Center för vuxenspel, vuxenspel, spelmaskiner, spel, spelmaskin, flipperspel, flipper" }, + "leisure/amusement_arcade": { + "name": "Arkadhall", + "terms": "arkadhall, spelhall, spelhus, arkad, arkadspel, arkadmaskin,spel, pay-to-play-spel, videospel, Spelkonsol, körsimulatorer, flipperspel, flipper" + }, + "leisure/beach_resort": { + "name": "Strandresort", + "terms": "Strandresort, strand, Resort, turistanläggning, hotellanläggning, semesterresort, semesteranläggning, rekreationsort, kurort, badort, turist, turism, hotell" + }, "leisure/bird_hide": { "name": "Torn/gömsle för fÃ¥gelskÃ¥dning", "terms": "FÃ¥gelskÃ¥dning, fÃ¥gelskÃ¥dare, fÃ¥gelskÃ¥dartorn, vilttorn, fÃ¥geltorn, fÃ¥gelskÃ¥dargömsel, utsiktstorn, fÃ¥gelskÃ¥dningstorn" @@ -4331,6 +4680,10 @@ "name": "Naturreservat", "terms": "naturreservat, nationalpark, naturpark, naturomrÃ¥de, reservat, naturskyddsomrÃ¥de" }, + "leisure/outdoor_seating": { + "name": "Uteservering", + "terms": "Uteservering, servering, al fresco, beer garden, ölträdgÃ¥rd, café, restaurang, pub, bar, utomhusmatsal, terrass, utomhus, glassbar" + }, "leisure/park": { "name": "Park", "terms": "rekreationsomrÃ¥de, friluftsomrÃ¥de, trädgÃ¥rd, plantering, grönomrÃ¥de, lund, stadsoas, oas, esplanad, skog, park, gräs, gräsmatta, äng, lekplats, nöjesträdgÃ¥rd, plaza, skogsmark" @@ -4405,7 +4758,7 @@ }, "leisure/playground": { "name": "Lekplats", - "terms": "Lekplats, lekomrÃ¥de, lekpark, klätterställning, gunga" + "terms": "Lekplats, lekomrÃ¥de, lekpark, lek, klätterställning, gunga" }, "leisure/resort": { "name": "Resort", @@ -4459,6 +4812,10 @@ "name": "Horisontell gruvgÃ¥ng (Stoll)", "terms": "stoll, gruva, gruvgÃ¥ng, horisontell gruvgÃ¥ng, gruvgÃ¥ng, gruvingÃ¥ng, gruvhÃ¥l, dagort, sidoort, Stollen, lichtloch" }, + "man_made/antenna": { + "name": "Antenn", + "terms": "Antenn, mast, sändning, mobil, mobilmast, kommunikation, radio, tv, radiomast, tv-mast, överföring" + }, "man_made/breakwater": { "name": "VÃ¥gbrytare", "terms": "VÃ¥gbrytare, pir, hamnarm, vÃ¥gskydd, fördämning, hamnpir" @@ -4510,6 +4867,10 @@ "name": "Utkikstorn", "terms": "Utkikstorn, utsiktstorn, observationstorn, utsiktspost, observationspost, brandtorn" }, + "man_made/observatory": { + "name": "Observatorium", + "terms": "Observatorium, astronomisk, meteorologisk, teleskop, astronom, rymd" + }, "man_made/petroleum_well": { "name": "Oljeborr", "terms": "Oljeborr, olja, petroleum, Oljeborrning, oljetorn, oljepump" @@ -4634,6 +4995,10 @@ "name": "Hed", "terms": "hed, äng, gräs, slättmark, slätt, tundra, stäpp, alvar, kalmark" }, + "natural/mud": { + "name": "Lera", + "terms": "Lera, vÃ¥tmark, sankmark och sumpmark, lerigt, gyttja, dy, sörja, gegga" + }, "natural/peak": { "name": "Bergstopp", "terms": "Bergstopp, berg, alp, hjässa, kalott, klack, klint, klätt, kulle, höjdpunkt, höjd, topp" @@ -4714,19 +5079,28 @@ "name": "Lokal myndighet" }, "office/adoption_agency": { - "name": "AdoptionsbyrÃ¥" + "name": "AdoptionsbyrÃ¥", + "terms": "AdoptionsbyrÃ¥, Adoption, barnupptagande, adoptering, adoptera" }, "office/advertising_agency": { - "name": "ReklambyrÃ¥" + "name": "ReklambyrÃ¥", + "terms": "ReklambyrÃ¥, reklam, annons, annonsbyrÃ¥, annonsering, marknadsföring" }, "office/architect": { - "name": "ArkitektbyrÃ¥" + "name": "ArkitektbyrÃ¥", + "terms": "ArkitektbyrÃ¥, arkitektkontor, Arkitekt, byggnadskonstnär, byggnadskonst, ritningar" }, "office/association": { - "name": "Frivilligorganisation" + "name": "Frivilligorganisation", + "terms": "Frivilligorganisation, Frivillig, volontär, frivilligarbetare, bistÃ¥ndsarbetare, förening, ideell, icke vinstdrivande, organisation, samhälle" }, "office/charity": { - "name": "Välgörenhetsorganisation" + "name": "Välgörenhetsorganisation", + "terms": "Välgörenhetsorganisation, Välgörenhet, hjälpverksamhet, bistÃ¥nd, bistÃ¥ndsorganisation" + }, + "office/company": { + "name": "Företagskontor", + "terms": "Företagskontor, kontor, företag, expedition, kundmottagning" }, "office/coworking": { "name": "Dagkontor", @@ -4753,10 +5127,12 @@ "terms": "Bankkontor, finanskontor, ekonomi, finans, bank, ekonomisk" }, "office/forestry": { - "name": "Skogsbolag" + "name": "Skogsbolag", + "terms": "Skogsbolag, skog, skogsvaktare" }, "office/foundation": { - "name": "Stiftelse" + "name": "Stiftelse", + "terms": "Stiftelse, fond, donation" }, "office/government": { "name": "Myndighet", @@ -4767,7 +5143,8 @@ "terms": "RegistreringsbyrÃ¥, borgerlig vigsel, stadshus, registrerade enhet, inskrivningskontor, registreringskontor, Folkbokföring, Skattemyndigheten, mantalslängder" }, "office/government/tax": { - "name": "Skattekontor" + "name": "Skattekontor", + "terms": "Skattekontor, skatt, skattemyndigheten, myndighet" }, "office/guide": { "name": "Guidekontor", @@ -4869,7 +5246,8 @@ "terms": "ö, holme, skär, kobbe, klippa, rev, atoll, skärgÃ¥rd, rev" }, "place/islet": { - "name": "Holme" + "name": "Holme", + "terms": "holme, skärgÃ¥rd, atoll, ö, rev, kobbe, liten ö, skär, grynna, havsklippa, grund" }, "place/isolated_dwelling": { "name": "Isolerad boplats", @@ -4909,49 +5287,59 @@ }, "playground/balance_beam": { "name": "Balansbom (lekplats)", - "terms": "balansbom, balans, bom" + "terms": "balansbom, balans, bom, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/basket_spinner": { - "name": "Korgkarusell" + "name": "Korgkarusell", + "terms": "Korgkarusell, karusell, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/basket_swing": { - "name": "Korggunga" + "name": "Korggunga", + "terms": "Korggunga, korg, gunga, gungställning, kompisgunga, fÃ¥gelbogunga, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/climbing_frame": { - "name": "Klätterställning" + "name": "Klätterställning", + "terms": "Klätterställning, klättra, klättring, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/cushion": { - "name": "Hoppkudde" + "name": "Hoppkudde", + "terms": "hoppkudde, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/horizontal_bar": { "name": "Räck (lekplats)", - "terms": "bar, räck, lekplats" + "terms": "bar, räck, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/rocker": { "name": "Fjädergunga", - "terms": "Gungdjur,Fjädergunga" + "terms": "Gungdjur,Fjädergunga, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/roundabout": { - "name": "Karusell" + "name": "Karusell (lekplats)", + "terms": "karusell, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/sandpit": { - "name": "SandlÃ¥da" + "name": "SandlÃ¥da", + "terms": "sandlÃ¥da, sand, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/seesaw": { - "name": "Gungbräda" + "name": "Gungbräda", + "terms": "gungbräda, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/slide": { - "name": "Rutschkana" + "name": "Rutschkana", + "terms": "Rutschkana, rutschbana, rutchelbana, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/structure": { - "name": "Lekslott" + "name": "Lekhus", + "terms": "Lekslott, lekhus, lekstuga, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/swing": { "name": "Gungställning", - "terms": "Gunga,Gungställning" + "terms": "Gunga,Gungställning, lekplats, lekomrÃ¥de, lekpark, lek" }, "playground/zipwire": { - "name": "Linbana" + "name": "Linbana (lekplats)", + "terms": "linbana, lekplats, lekomrÃ¥de, lekpark, lek" }, "point": { "name": "Punkt", @@ -5012,20 +5400,129 @@ "terms": "HÃ¥llplats, Plattform, kollektivtrafik, linjetrafik, transport" }, "public_transport/linear_platform_aerialway": { - "name": "HÃ¥llplats / Plattform för linbana" + "name": "HÃ¥llplats / Plattform för linbana", + "terms": "linbana, aerialway, LinbanehÃ¥llplats, linbaneplattform, linbaneterminal, linbanestopp, hÃ¥llplats, plattform, terminal, stopp, kollektivtrafik, linjetrafik, transit, transport" + }, + "public_transport/linear_platform_bus": { + "name": "Bussplattform", + "terms": "buss, plattform, kollektivtrafik, transport, transit, hÃ¥llplats, busshÃ¥llplats, bussplattform, linjetrafik" + }, + "public_transport/linear_platform_ferry": { + "name": "Stop / plattform för färja", + "terms": "färjeplattform, plattform, stopp, bÃ¥tstopp, färjestopp, bÃ¥thÃ¥llplats, Färjeterminal, terminal, färja, bÃ¥tterminal, bÃ¥thÃ¥llplats, FärjehÃ¥llplats, Färjestation, bÃ¥t, brygga, pir, kollektivtrafik, linjetrafik, station, transit, transport" + }, + "public_transport/linear_platform_light_rail": { + "name": "HÃ¥llplats för snabbspÃ¥rväg / stadsbana", + "terms": "SpÃ¥rvägshÃ¥llplats, hÃ¥llplats, spÃ¥rvagnsplattform, plattform, spÃ¥rvagn, spÃ¥rväg, spÃ¥rvagnsterminal, terminal, järnväg, kollektivtrafik, kollektivtrafik, vagn, transit, transport, snabbspÃ¥rväg, stadsbana, light rail, spÃ¥r, järnväg" + }, + "public_transport/linear_platform_monorail": { + "name": "Stopp / plattform för monorail", + "terms": "monorailstopp, monorailplattform, stopp, plattform, monorail, plattform, kollektivtrafik, linjetrafik, enskensbana, balkbana, räls, spÃ¥r, transport" }, "public_transport/linear_platform_subway": { "name": "Tunnelbanestopp / -plattform", "terms": "Tunnelbanestopp, Tunnelbaneplattform, tunnelbana, metro, plattform, kollektivtrafik, järnväg, spÃ¥r, transport, tunnelbana, underjordisk" }, + "public_transport/linear_platform_train": { + "name": "Järnvägsstopp / -perrong", + "terms": "TÃ¥gstopp, Perrong, järnvägsperrong, plattform, järnvägsplattform, järnväg, tÃ¥g, stopp, kollektivtrafik, linjetrafik, spÃ¥r, transit, transport" + }, + "public_transport/linear_platform_tram": { + "name": "SpÃ¥rvagnshÃ¥llplats / -plattform", + "terms": "SpÃ¥rvägshÃ¥llplats, spÃ¥rvagnshÃ¥llplats, hÃ¥llplats, spÃ¥rvagnsplattform, plattform, spÃ¥rvagn, spÃ¥rväg, spÃ¥rvagnsterminal, terminal, järnväg, kollektivtrafik, kollektivtrafik, vagn, transit, transport" + }, + "public_transport/linear_platform_trolleybus": { + "name": "BusshÃ¥llplats / plattform för trÃ¥dbuss", + "terms": "BusshÃ¥llplats, bussplattform, plattform, trÃ¥dbuss, hÃ¥llplats, buss, kollektivtrafik, spÃ¥rlös, spÃ¥rvagn, vagn, transit, transport" + }, + "public_transport/platform": { + "name": "Stopp / Plattform för kollektivtrafik", + "terms": "Plattform, väntplats, pÃ¥stigningsplats, avsats, perrong" + }, + "public_transport/platform_aerialway": { + "name": "HÃ¥llplats / Plattform för linbana", + "terms": "linbana, aerialway, LinbanehÃ¥llplats, linbaneplattform, linbaneterminal, linbanestopp, hÃ¥llplats, plattform, terminal, stopp, kollektivtrafik, linjetrafik, transit, transport" + }, + "public_transport/platform_bus": { + "name": "BusshÃ¥llplats / Bussplattform", + "terms": "buss, plattform, kollektivtrafik, transport, transit, hÃ¥llplats, busshÃ¥llplats, bussplattform, linjetrafik" + }, + "public_transport/platform_ferry": { + "name": "Stop / plattform för färja", + "terms": "färjeplattform, plattform, stopp, bÃ¥tstopp, färjestopp, bÃ¥thÃ¥llplats, Färjeterminal, terminal, färja, bÃ¥tterminal, bÃ¥thÃ¥llplats, FärjehÃ¥llplats, Färjestation, bÃ¥t, brygga, pir, kollektivtrafik, linjetrafik, station, transit, transport" + }, + "public_transport/platform_light_rail": { + "name": "HÃ¥llplats för snabbspÃ¥rväg / stadsbana", + "terms": "SpÃ¥rvägshÃ¥llplats, hÃ¥llplats, spÃ¥rvagnsplattform, plattform, spÃ¥rvagn, spÃ¥rväg, spÃ¥rvagnsterminal, terminal, järnväg, kollektivtrafik, kollektivtrafik, vagn, transit, transport, snabbspÃ¥rväg, stadsbana, light rail, spÃ¥r, järnväg" + }, + "public_transport/platform_monorail": { + "name": "Stopp / plattform för monorail", + "terms": "monorailstopp, monorailplattform, stopp, plattform, monorail, plattform, kollektivtrafik, linjetrafik, enskensbana, balkbana, räls, spÃ¥r, transport" + }, "public_transport/platform_subway": { "name": "Tunnelbanestopp / -plattform", "terms": "Tunnelbanestopp, Tunnelbaneplattform, tunnelbana, metro, plattform, kollektivtrafik, järnväg, spÃ¥r, transport, tunnelbana, underjordisk" }, + "public_transport/platform_train": { + "name": "Järnvägsstopp / -perrong", + "terms": "TÃ¥gstopp, Perrong, järnvägsperrong, plattform, järnvägsplattform, järnväg, tÃ¥g, stopp, kollektivtrafik, linjetrafik, spÃ¥r, transit, transport" + }, + "public_transport/platform_tram": { + "name": "SpÃ¥rvagnshÃ¥llplats / -plattform", + "terms": "SpÃ¥rvägshÃ¥llplats, spÃ¥rvagnshÃ¥llplats, hÃ¥llplats, spÃ¥rvagnsplattform, plattform, spÃ¥rvagn, spÃ¥rväg, spÃ¥rvagnsterminal, terminal, järnväg, kollektivtrafik, kollektivtrafik, vagn, transit, transport" + }, + "public_transport/platform_trolleybus": { + "name": "BusshÃ¥llplats / plattform för trÃ¥dbuss", + "terms": "BusshÃ¥llplats, bussplattform, plattform, trÃ¥dbuss, hÃ¥llplats, buss, kollektivtrafik, spÃ¥rlös, spÃ¥rvagn, vagn, transit, transport" + }, + "public_transport/station": { + "name": "Station för kollektivtrafik", + "terms": "Station för kollektivtrafik, station, kollektivtrafik, terminal, resecenter, bytespunkt, transport" + }, + "public_transport/station_aerialway": { + "name": "Linbanestation", + "terms": "Linbanestation, station, linbana, aerialway, kollektivtrafik, terminal, transit, transport" + }, + "public_transport/station_bus": { + "name": "Busstation / Bussterminal", + "terms": "Busstation, Bussterminal, buss, kollektivtrafik, station, terminal, transit, transport, terminal, BusshÃ¥llplats, resecenter, reseterminal" + }, + "public_transport/station_ferry": { + "name": "Färjeterminal / FärjehÃ¥llplats / Färjestation", + "terms": "Färjeterminal, terminal, färja, bÃ¥tterminal, bÃ¥thÃ¥llplats, FärjehÃ¥llplats, Färjestation, bÃ¥t, brygga, pir, kollektivtrafik, station, transit, transport" + }, + "public_transport/station_light_rail": { + "name": "Station för snabbspÃ¥rväg / stadsbana", + "terms": "Station för snabbspÃ¥rväg, Station för light rail, snabbspÃ¥rväg, light rail, lättbana, spÃ¥rväg, kollektivtrafik, järnväg, spÃ¥r, spÃ¥rvagn, transport, spÃ¥rvagn, linjetrafik, hÃ¥llplats, spÃ¥rvagnshÃ¥llplats, spÃ¥rvagnstopp, spÃ¥rvagnsterminal, station, terminal, spÃ¥rväg, transport, stadsbana" + }, + "public_transport/station_monorail": { + "name": "Monorailstation", + "terms": "monorailstation, station, terminal, monorail, plattform, räls, spÃ¥r, kollektivtrafik, linjetrafik, enskensbana, balkbana, transport" + }, "public_transport/station_subway": { "name": "Tunnelbanestation", "terms": "Tunnelbanestation, tunnelbana, metro, , kollektivtrafik, järnväg, spÃ¥r, transport, tunnelbana, underjordisk, station, terminal" }, + "public_transport/station_train": { + "name": "Järnvägsstation", + "terms": "Järnvägsstation, centralstation, central, huvudbangÃ¥rd, tÃ¥gstation, järnvägshÃ¥llplats, tÃ¥ghÃ¥llplats, trafikplats, hÃ¥llställe, linjeplats, hÃ¥llplats, " + }, + "public_transport/station_train_halt": { + "name": "Mindre järnvägshÃ¥llplats", + "terms": "Mindre järnvägshÃ¥llplats, järnvägshÃ¥llplats, hÃ¥llplats, järnvägsstation, station, plattform, avstigning, pÃ¥stigning, kollektivtrafik, järnväg, spÃ¥r, tÃ¥g, transit, transport, hÃ¥llställe" + }, + "public_transport/station_tram": { + "name": "SpÃ¥rvagnsstation", + "terms": "SpÃ¥rvagnsstation, spÃ¥rvagn, station, spÃ¥rväg, spÃ¥rvägshÃ¥llplats, spÃ¥rvagnsterminal" + }, + "public_transport/station_trolleybus": { + "name": "Station / Terminal för trÃ¥dbuss", + "terms": "Station / Terminal för trÃ¥dbuss, station, terminal, trÃ¥dbuss, buss, kollektivtrafik, linjetrafik, transport, hÃ¥llplats, trÃ¥dbusshÃ¥llplats, trÃ¥dbusstopp, trÃ¥dbussterminal, busshÃ¥llplats, busstopp, bussterminal" + }, + "public_transport/stop_area": { + "name": "Bytespunkt / knutpunkt", + "terms": "bytespunkt, transit, resecenter, station, terminal, byte, kollektivtrafik, linjetrafik, transport, hÃ¥llplats, knutpunkt" + }, "public_transport/stop_position": { "name": "Stopposition för kollektivtrafik", "terms": "Stopposition för kollektivtrafik, stopposition, kollektivtrafik, linjetrafik, transport, hÃ¥llplats" @@ -5043,12 +5540,12 @@ "terms": "Stopposition för färja, stopposition, färja, bÃ¥t, linjetrafik, kollektivtrafik, transport, hÃ¥llplats, busshÃ¥llplats, busstopp, bussterminal" }, "public_transport/stop_position_light_rail": { - "name": "Stopposition för snabbspÃ¥rväg / light rail", - "terms": "Stopposition för snabbspÃ¥rväg, snabbspÃ¥rväg, light rail, lättbana, spÃ¥rväg, kollektivtrafik, järnväg, spÃ¥r, spÃ¥rvagn, transport, stopposition, spÃ¥rvagn, linjetrafik, hÃ¥llplats, spÃ¥rvagnshÃ¥llplats, spÃ¥rvagnstopp, spÃ¥rvagnsterminal" + "name": "Stopposition för snabbspÃ¥rväg / stadsbana", + "terms": "Stopposition för snabbspÃ¥rväg, snabbspÃ¥rväg, light rail, lättbana, spÃ¥rväg, kollektivtrafik, järnväg, spÃ¥r, spÃ¥rvagn, transport, stopposition, spÃ¥rvagn, linjetrafik, hÃ¥llplats, spÃ¥rvagnshÃ¥llplats, spÃ¥rvagnstopp, spÃ¥rvagnsterminal, stadsbana" }, "public_transport/stop_position_monorail": { "name": "Stopposition för monorail", - "terms": "Stopposition för monorail, stopposition, monorail, enskensbana, balkbana, kollektivtrafik, linjetrafik, transport, hÃ¥llplats" + "terms": "Stopposition för monorail, stopposition, monorail, enskensbana, balkbana, räls, spÃ¥r, kollektivtrafik, linjetrafik, transport, hÃ¥llplats" }, "public_transport/stop_position_subway": { "name": "Stopposition för tunnelbana", @@ -5093,22 +5590,36 @@ "name": "Bergbana ", "terms": "Bergbana, linbana" }, + "railway/halt": { + "name": "Mindre järnvägshÃ¥llplats" + }, "railway/level_crossing": { "name": "Järnvägskorsning (väg)", "terms": "korsning, järnvägskorsning, järnvägsövergÃ¥ng, järnvägspassage, plankorsning, spÃ¥rpassage, tÃ¥gövergÃ¥ng, tÃ¥gkorsning, tÃ¥gpassage" }, + "railway/light_rail": { + "name": "SnabbspÃ¥rväg / stadsbana", + "terms": "smalspÃ¥rig järnväg, smalspÃ¥r, järnväg, snabbspÃ¥rväg, stadsbana" + }, "railway/milestone": { "name": "Kilometerstolpe vid järnväg", "terms": "Kilometerstolpe, kilometertavla, avstÃ¥ndsmärke, milsten, referenstavla, kilometerpÃ¥le" }, + "railway/miniature": { + "name": "Miniatyrjärnväg", + "terms": "Miniatyrjärnväg, Åkbar miniatyrjärnväg, smalspÃ¥rig järnväg, smalspÃ¥r, trädgÃ¥rdsjärnväg" + }, "railway/monorail": { "name": "Monorail", - "terms": "Monorail, enskensbana, balkbana" + "terms": "Monorail, enskensbana, balkbana, räls, spÃ¥r, kollektivtrafik, linjetrafik, transport" }, "railway/narrow_gauge": { "name": "SmalspÃ¥rbana", "terms": "SmalspÃ¥rbana, smalspÃ¥r" }, + "railway/platform": { + "name": "Järnvägsstopp / -perrong" + }, "railway/rail": { "name": "Räls", "terms": "Räls, järnvägsspÃ¥r, spÃ¥r, bana" @@ -5117,6 +5628,9 @@ "name": "Järnvägssignal", "terms": "järnvägssignal, signal, ljus, järnvägsljus, semafor, försignal, huvudsignal, dvärgsignal" }, + "railway/station": { + "name": "Järnvägsstation" + }, "railway/subway": { "name": "Tunnelbana", "terms": "Tunnelbana, T-bana, metro" @@ -5137,6 +5651,9 @@ "name": "SpÃ¥rvagn", "terms": "SpÃ¥rvagn, spÃ¥rväg, motorvagn" }, + "railway/tram_stop": { + "name": "Stopposition för spÃ¥rvagn" + }, "relation": { "name": "Relation", "terms": "Relation, relaterat, förbindelse, förhÃ¥llande, samband, anknytning, koppling, kontext" @@ -5152,6 +5669,10 @@ "name": "Affär", "terms": "Affär, shop, butik" }, + "shop/agrarian": { + "name": "Jordbruksaffär", + "terms": "Jordbruksaffär, Jordbruk, jordbruksmaskiner, frön, utsäde, bekämpningsmedel, gödningsmedel, gödsel, jordbruksverktyg, utsäde, djurmat, jordbruksutrustning, lantmannaföreningen" + }, "shop/alcohol": { "name": "Vin-och-spritaffär", "terms": "Vinaffär, spritaffär, vin- och sprit, vin- och spritaffär, systemet, systembolaget, bolaget, alkohol, öl, vin, sprit" @@ -5390,6 +5911,10 @@ "name": "Järnaffär", "terms": "Järnaffär, järnhandlare, skruv, skruvar, bult, bultar, spik, krokar, järnbeslag, järntillbehör, metallverktyg, verktyg, bygg, el, vvs, trädgÃ¥rdsredskap, redskap, handverktyg, elverktyg, köksutrustning, badrum, kök, hushÃ¥llsprodukter, lÃ¥s, nycklar, nyckeltillverkning" }, + "shop/health_food": { + "name": "Hälsokostbutik", + "terms": "Hälsokostbutik, hälsokost, hälsomat, organisk, organist, vitaminer, vegetarian, vegan, naturligt, kosttillskott, köttersättning, mjölkersättning" + }, "shop/hearing_aids": { "name": "Hörapparater", "terms": "Hörapparater, hörselskada, hörselskadade, hörhjälpmedel, hörsel" @@ -5414,6 +5939,10 @@ "name": "Juvelerare", "terms": "Juvelerare, smycken, halsband, ring, ringar, örhänge, örhängen, klocka, klockor, guld, silver, diamant, pärla, pärlor" }, + "shop/kiosk": { + "name": "Kiosk", + "terms": "Kiosk, gatukök, tidningar, godis, cigaretter, tobak, snus, dryck, läsk, butik, snabbmat, glass, korv" + }, "shop/kitchen": { "name": "Köksinredning", "terms": "Köksinredning, kök, bänkskivor, köksskÃ¥p, skÃ¥pluckor" @@ -5506,6 +6035,10 @@ "name": "Djurbutik", "terms": "Djuraffär, djur, husdjur, hund, hundar, katt, katter, djurmat, djurtillbehör, djurburar, akvarium, hund, fisk" }, + "shop/pet_grooming": { + "name": "PälsvÃ¥rd för husdjur", + "terms": "PälsvÃ¥rd för husdjur, pälsvÃ¥rd, husdjur, hund, Trimning, hundvÃ¥rd" + }, "shop/photo": { "name": "Fotoaffär ", "terms": "fotoaffär, bild, foto, video, fotografi, fotoredigering, framkallning, ram, kameratillbehör, kamera, kameror, filmkamera, fotokamera, konvertering, film" @@ -5583,7 +6116,8 @@ "terms": "Leksaksaffär, leksaker, barnsaker" }, "shop/trade": { - "name": "Proffshandel" + "name": "Proffshandel", + "terms": "Proffshandel, proffsmarknad, proffs, byggnadsmaterial, byggmaterial, brädgÃ¥rd, brädor, Trähandel, trävaror, VVS-specialist, VVS, jordbruksprodukter, jordbruk, lantmannaföreningen, granngÃ¥rden, kakel, fönster" }, "shop/travel_agency": { "name": "ResebyrÃ¥", @@ -5624,6 +6158,10 @@ "name": "Vapenaffär", "terms": "Vapenaffär, vapen, ammunition, jakt, skjutvapen, kniv, knivar, pistol" }, + "shop/wholesale": { + "name": "Grosistaffär", + "terms": "grosist, Grosistaffär, Partihandel, grosshandel, grossistverksamhet, grosshandel, engros, mängdhandel, grossistlager, lagerklubb, grossistklubb" + }, "shop/window_blind": { "name": "Persienner", "terms": "Persienner, spjälgardin, jalusi, markis, rullgardin, spjäljalusi" @@ -5665,7 +6203,8 @@ "terms": "Ställplats, campingplats, camping, husvagnscamping, husbilscamping, fricamping" }, "tourism/chalet": { - "name": "Stuga" + "name": "Stuga", + "terms": "Campingstuga, stuga, sommarstuga, ledighet, helg, helgboende, semester, semesterboende, semesterstuga, camping" }, "tourism/gallery": { "name": "Konstgalleri", @@ -5724,7 +6263,8 @@ "terms": "Utsiktsplats, utsikt, vy" }, "tourism/wilderness_hut": { - "name": "Stuga (för vandrare o.d.)" + "name": "Stuga (för vandrare o.d.)", + "terms": "Stuga (för vandrare o.d.), stuga, fjällstuga, fjällstation, koja, skydd, hydda, kyffe, barack, vildmarksstuga, vandring, hajk, övernattning, Ödestuga" }, "tourism/zoo": { "name": "Zoo", @@ -5767,7 +6307,8 @@ "terms": "Bullerräfflor, Pennsylvaniaräfflor" }, "traffic_calming/table": { - "name": "Fartgupp (lÃ¥ngt)" + "name": "Fartgupp (lÃ¥ngt)", + "terms": "PlatÃ¥gupp, gupp, farthinder, fartgupp, Fartgupp (lÃ¥ngt), lÃ¥ngt fartgupp" }, "type/boundary": { "name": "Gräns", @@ -5802,15 +6343,19 @@ }, "type/restriction/only_left_turn": { "name": "Enbart vänstersväng", - "terms": "Enbart vänstersväng, bara vänstersväng, endast vänstersväng" + "terms": "Enbart vänstersväng, vänstersväng, vänster" }, "type/restriction/only_right_turn": { "name": "Enbart högersväng", - "terms": "enbart högersväng, endast högersväng, bara högersväng" + "terms": "Enbart högersväng, högersväng, höger" }, "type/restriction/only_straight_on": { - "name": "Inga svängar", - "terms": "Inga svängar, rakt fram, ingen sväng" + "name": "Enbart rakt fram", + "terms": "Enbart rakt fram, fortsätt framÃ¥t, fÃ¥r ej svänga" + }, + "type/restriction/only_u_turn": { + "name": "Enbart U-sväng", + "terms": "Enbart U-sväng, mÃ¥ste vända, U-sväng" }, "type/route": { "name": "Rutt", @@ -5844,10 +6389,18 @@ "name": "HästspÃ¥r", "terms": "Ridrutt, ridning, rida, häst, hästrutt, hästspÃ¥r, ridspÃ¥r" }, + "type/route/light_rail": { + "name": "Rutt pÃ¥ snabbspÃ¥rväg / stadsbana", + "terms": "Rutt pÃ¥ smalspÃ¥rig järnväg, smalspÃ¥rig järnväg, smalspÃ¥r, järnväg, järnvägsrutt, tÃ¥grutt, tÃ¥gnät, järnvägsförbindelse, snabbspÃ¥rväg, stadsbana, rutt för snabbspÃ¥rväg, rutt för stadsbana" + }, "type/route/pipeline": { "name": "Rörledningsrutt", "terms": "Rörledningsrutt, rörledning, pipeline, oljeledning, vattenledning, avloppsledning" }, + "type/route/piste": { + "name": "Pist/skidspÃ¥r", + "terms": "Pist, pistspÃ¥r, skidor, skidspÃ¥r, skidrutt, skidor, skidbacke, slalombacke, skidbana, utförsÃ¥kning, längdskidÃ¥kning, längdskidspÃ¥r, skidtur, slädspÃ¥r, skridskospÃ¥r, skridskobana, skridskorutt, snöpark, slädspÃ¥r" + }, "type/route/power": { "name": "Kraftledningsrutt", "terms": "Kraftledningsrutt, kraftledning, elförsörjning, elnät" @@ -5877,7 +6430,8 @@ "terms": "Plats, ställe, läge, anläggning" }, "type/waterway": { - "name": "Vattendrag" + "name": "Vattendrag", + "terms": "Vattenväg, vattenflöde, vattendrag" }, "vertex": { "name": "Annat", @@ -5931,7 +6485,8 @@ "terms": "vattendrag, bäck, dike, biflöde, flöde, ström, flod, flöde, rännil, biflod" }, "waterway/stream_intermittent": { - "name": "Tillfälligt vattendrag" + "name": "Periodiskt vattendrag", + "terms": "Periodiskt vattendrag, tillfälligt vattendrag, periodiskt, tillfälligt, Arroyo, bäck, avrinning, dränering, översvämning, rännil, biflöde, vattendrag, dike, dagvatten, dränering, avrinning" }, "waterway/water_point": { "name": "Dricksvatten för bÃ¥t", @@ -5963,7 +6518,7 @@ "attribution": { "text": "Villkor & Ã¥terkoppling" }, - "description": "Gränser för flygfoto och fotograferingsdatum. Etiketter visas vid zoomnivÃ¥ 14 och upp.", + "description": "Gränser för flygfoto och fotograferingsdatum. Etiketter visas vid zoomnivÃ¥ 13 och upp.", "name": "DigitalGlobe Premium flygfotoÃ¥lder" }, "DigitalGlobe-Standard": { @@ -5977,7 +6532,7 @@ "attribution": { "text": "Villkor & Ã¥terkoppling" }, - "description": "Gränser för flygfoto och fotograferingsdatum. Etiketter visas vid zoomnivÃ¥ 14 och upp.", + "description": "Gränser för flygfoto och fotograferingsdatum. Etiketter visas vid zoomnivÃ¥ 13 och upp.", "name": "DigitalGlobe Standard flygfotoÃ¥lder" }, "EsriWorldImagery": { @@ -5987,6 +6542,13 @@ "description": "Esri världsflygfoto.", "name": "Esri världsflygfoto" }, + "EsriWorldImageryClarity": { + "attribution": { + "text": "Villkor & Ã¥terkoppling" + }, + "description": "Arkivbilder frÃ¥n Esri som kan vara tydligare och mer korrekta än det normala lagret.", + "name": "Esri världsflygfoto (Clarity) Beta" + }, "MAPNIK": { "attribution": { "text": "© OpenStreetMaps bidragsgivare, CC-BY-SA" @@ -6054,19 +6616,38 @@ "description": "Gul = Fritt tillgänglig kartdata (public domain) frÃ¥n US Census. Röd = Data ej hittad i OpenStreetMap", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Väg: Grön ram = oklassificerad. Brun ram = bruksväg. Underlag: grus = ljusbrun fyllning, asfalt = svart, belagd = grÃ¥, mark = vit, betong = blÃ¥, gräs = grön. Säsongsöppen = vita streck", + "name": "Bildlager för Skogsvägar i USA" + }, "Waymarked_Trails-Cycling": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMaps bidragsgivare, CC by-SA 3.0" + }, "name": "Waymarked Trails: Cykel" }, "Waymarked_Trails-Hiking": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMaps bidragsgivare, CC by-SA 3.0" + }, "name": "Waymarked Trails: Vandring" }, "Waymarked_Trails-MTB": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMaps bidragsgivare, CC by-SA 3.0" + }, "name": "Waymarked Trails: Mountainbike" }, "Waymarked_Trails-Skating": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMaps bidragsgivare, CC by-SA 3.0" + }, "name": "Waymarked Trails: Inline skating" }, "Waymarked_Trails-Winter_Sports": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMaps bidragsgivare, CC by-SA 3.0" + }, "name": "Waymarked Trails: Vintersport" }, "basemap.at": { @@ -6100,7 +6681,7 @@ "attribution": { "text": "© OpenStreetMaps bidragsgivare, CC-BY-SA" }, - "name": "OpenP-karta (bildlager)" + "name": "OpenPT-karta (bildlager)" }, "osm-gps": { "attribution": { @@ -6135,7 +6716,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Kartplattor av Stamen Design, under CC BY 3.0" + "text": "Kartplattor av Stamen Design, under CC BY 3.0. Data frÃ¥n OpenStreetMap, under ODbL " }, "name": "Stamen terräng" }, @@ -6151,6 +6732,758 @@ }, "name": "Thunderforest landskap" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "University of Cape Coast YouthMappers", + "description": "Följ oss pÃ¥ Twitter: {url}", + "extendedDescription": "Detta är den officiella hÃ¥llpunkten för Youth Mappers chapter pÃ¥ University of Cape Coast, Ghana. Vi älskar kartor, öppen data och att hjälpa de fattiga." + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana pÃ¥ Facebook", + "description": "Facebook-grupp för folk intresserade av OpenStreetMap", + "extendedDescription": "Kartläggare i Ghana-gemenskapen, marknadsför OpenStreetMap projektet Humanitarian OpenStreetMap Team (HOT) i Ghana. GÃ¥ med oss." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter: {url}" + }, + "talk-gh": { + "name": "E-postlistan Talk-gh", + "description": "Talk-gh är den officiella e-postlistan för OSM-gemenskapen i Ghana" + }, + "osm-mg-facebook": { + "name": "Facebook-grupp för OpenStreetMap Madagaskar", + "description": "Malagasy Facebook-grupp för personer intresserade av OpenStreetMap." + }, + "talk-mg": { + "name": "E-postlistan Talk-mg", + "description": "Plats för bidragsgivare till OpenStreetMap, sammanslutningar och användare i Madagaskar för att dela och diskutera." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesh", + "description": "Förbättra OpenStreetMap i Bangladesh", + "extendedDescription": "Kartlägger i Bangladesh? Har du frÃ¥gor, vill du ansluta till gemenskapen här? Anslut dig pÃ¥ {url}. Alla är välkomna!" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap Indien - Användarstödd kartläggning av grannskapet", + "description": "Förbättra OpenStreetMap i Indien", + "extendedDescription": "Kartlägger i Indien? Har du frÃ¥gor, vill komma i kontakt med gemenskapen här? GÃ¥ med pÃ¥ {url}. Alla är välkomna!", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "description": "Kom till 2018 Ã¥rs upplaga av OpenStreetMaps regiontäckande evenemang State of the Map Asia i Indien", + "where": "Indiska institutet för förvaltning, Bangalore, Indien" + } + } + }, + "OSM-india-mailinglist": { + "name": "E-postlista för OpenStreetMap Indien", + "description": "Talk-in är den officiella e-postlistan för den indiska gemenskapen" + }, + "OSM-india-twitter": { + "name": "OpenStreetMap Indien pÃ¥ Twitter", + "description": "Vi är bara ett tweet iväg: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Rörelsen för fri mjukvara och hÃ¥rdvara - Facebook", + "description": "Facebook-sidan FSHM för att fÃ¥ veta om evenemang och aktiviteter", + "extendedDescription": "FSHM organiserar evenemang relaterade till gratis mjukvara/hÃ¥rdvara, teknologi, aktivism och OpenStreetMap. Dess Facebook-sida är det bästa vägen att hÃ¥lla kontakten med dess evenemang." + }, + "OSM-India-Puducherry-Matrix": { + "name": "Rörelsen för fri mjukvara och hÃ¥rdvara - Matrix", + "description": "FSHM:s Riot-grupp för att diskutera, dela och uppdatera om kartläggningsaktiviteter och evenemang i och omkring Puducherry", + "extendedDescription": "FSHM:s medlemmar delar sina kartläggningsuppdateringar / -erfarenheter i OSM genom Riot.im-gruppen, denna grupp används även för att diskutera saker relaterade till fri mjukvara / hÃ¥rdvara, teknologi och aktivism." + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonesien", + "description": "Förbättra OpenStreetMap i Indonesien", + "extendedDescription": "Kartlägger i Indonesien? Har du frÃ¥gor, vill du ansluta till gemenskapen här? Anslut dig pÃ¥ {Url}. Alla är välkomna!" + }, + "OSM-japan-facebook": { + "name": "Gemenskap för OpenStreetMap Japan", + "description": "Kartläggare och OpenStreetMap-användare i Japan" + }, + "OSM-japan-mailinglist": { + "name": "E-postlista för OpenStreetMap Japan", + "description": "Talk-ja är en officiell e-postlista för den japanska gemenskapen" + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap Japan pÃ¥ Twitter", + "description": "Hashtag pÃ¥ Twitter: {url}" + }, + "OSM-japan-website": { + "name": "OpenStreetMap Japan", + "description": "Kartläggare och OpenStreetMap-användare i Japan" + }, + "OSM-korea-telegram": { + "name": "Telegram-kanal för OSM Korea", + "description": "Inofficiell kanal för bidragsgivare till OpenStreetMap, sammanslutningar och användare i Korea för att dela och diskutera." + }, + "OSM-MY-facebook": { + "name": "OpenStreetMap Malaysia pÃ¥ Facebook", + "description": "För chatt om allt som rör OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "Forum för OpenStreetMap Malaysia", + "description": "Officiellt forum för OpenStreetMap Malaysia" + }, + "OSM-MY-matrix": { + "name": "Riot-kanal för OpenStreetMap Malaysia", + "description": "Alla kartläggare är välkomna! Registrera dig pÃ¥ {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mongoliet", + "description": "Förbättra OpenStreetMap i Mongoliet", + "extendedDescription": "Kartlägger i Mongoliet? Har du frÃ¥gor, vill du ansluta till gemenskapen här? Anslut dig pÃ¥ {Url}. Alla är välkomna!" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Burma", + "description": "Förbättra OpenStreetMap i Burma", + "extendedDescription": "Kartlägger i Burma? Har du frÃ¥gor, vill du ansluta till gemenskapen här? Anslut dig pÃ¥ {Url}. Alla är välkomna!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Nepal", + "description": "Förbättra OpenStreetMap i Nepal", + "extendedDescription": "Kartlägger i Nepal? Har du frÃ¥gor, vill du ansluta till gemenskapen här? Anslut dig pÃ¥ {Url}. Alla är välkomna!" + }, + "OSM-PH-facebook": { + "name": "OpenStreetMap PH pÃ¥ Facebook", + "description": "Välkommen till OpenStreetMap Filippinerna, där vi uppmuntrar alla filippiner att bidra till OpenStreetMap-projektet." + }, + "OSM-PH-mailinglist": { + "name": "E-postlistan Talk-ph", + "description": "En epostlista för att diskutera OpenStreetMap pÃ¥ Filippinerna" + }, + "OSM-PH-slack": { + "name": "OpenStreetMap PH pÃ¥ Slack", + "description": "Alla är välkomna! Registrera dig pÃ¥ {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "Telegram för OpenStreetMap PH", + "description": "Inofficiell, lokal gemenskap pÃ¥ Telegram för OpenStreetMaps bidragsgivare och vänner pÃ¥ Filippinerna" + }, + "OSM-RU-forum": { + "name": "Forum för OpenStreetMap RU", + "description": "Webbforum för OpenStreetMap Ryssland" + }, + "OSM-RU-telegram": { + "name": "Telegram för OpenStreetMap RU", + "description": "Telegram-chatt för OpenStreetMap Rysland" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka", + "description": "Förbättra OpenStreetMap i Sri Lanka", + "extendedDescription": "Kartlägger i Sir Lanka? Har du frÃ¥gor, vill du ansluta till gemenskapen här? Anslut dig pÃ¥ {Url}. Alla är välkomna!" + }, + "OSM-TW-facebook": { + "name": "Gemenskap för OpenStreetMap Taiwan", + "description": "Facebook-grupp för kartläggare och OpenStreetMap-användare för att diskutera frÃ¥gor rörande Taiwan." + }, + "OSM-TW-mailinglist": { + "name": "E-postlista för OpenStreetMap Taiwan", + "description": "Talk-tw är en officiell e-postlista för att diskutera frÃ¥gor som rör Taiwan" + }, + "OSM-TH-CNX-meetup": { + "name": "OSM Meetup Chiang Mai", + "description": "Oregelbundna träffar för OpenStreetMap-gemenskapen i Chiang Mai" + }, + "OSM-TH-forum": { + "name": "Forum för OpenStreetMap TH", + "description": "Webbforum för OpenStreetMap Thailand" + }, + "al-forum": { + "name": "Forum för OSM Albanien", + "description": "Forum för OpenStreetMap Albanien" + }, + "al-maptime-tirana": { + "description": "Sociala evenemang organiserade runt kartläggning - nybörjare är varmt välkomna!" + }, + "al-telegram": { + "name": "Telegram-kanal för OSM Albanien", + "description": "Telegram-chatt för OpenStreetMap Albanien " + }, + "at-forum": { + "name": "Forum för OpenStreetMap Österrike", + "description": "Det officiella forumet för OpenStreetMap-frÃ¥gor i och runt Österrike" + }, + "at-mailinglist": { + "name": "E-postlistan Talk-at", + "description": "Talk-at är den officiella e-postlistan för den österrikiska OSM-gemenskapen" + }, + "at-twitter": { + "name": "OpenStreetMap Österrike pÃ¥ Twitter", + "description": "OpenStreetMap Österrike pÃ¥ Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "OSM-gemenskapsträffar i Graz", + "description": "Träffar en gÃ¥ng i mÃ¥naden för OpenStreetMap-gemenskapen i Graz" + }, + "osmgraz-twitter": { + "name": "OSM-gemenskapen i Graz pÃ¥ Twitter", + "description": "OpenStreetMap-gemenskapen i Graz pÃ¥ Twitter" + }, + "osm-at": { + "name": "OpenStreetMap Österrike", + "description": "Plattformen för information om OpenStreetMap i Österrike" + }, + "byosm": { + "name": "OpenStreetMap Vitryssland", + "description": "Telegram-chatt för OpenStreetMap Vitryssland" + }, + "be-facebook": { + "name": "OpenStreetMap BE-gemenskap", + "description": "Kartläggare och OpenStreetMap pÃ¥ Facebook i Belgien" + }, + "be-forum": { + "name": "Forum för OpenStreetMap BE", + "description": "Webbforum för OpenStreetMap Belgien" + }, + "be-irc": { + "name": "IRC för OpenStreetMap Belgien", + "description": "Anslut #osmbe pÃ¥ irc.oftc.net (port 6667)", + "extendedDescription": "Anslut #osmbe pÃ¥ irc.oftc.net (port 6667), den är bryggad med chatt-kanalen Matrix" + }, + "be-mailinglist": { + "name": "E-postlistan Talk-be", + "description": "Talk-be är den officiella e-postlistan för den belgiska OSM-gemenskapen" + }, + "be-maptime": { + "name": "Maptime Belgien", + "description": "Sociala evenemang organiserade runt kartläggning - nybörjare är varmt välkomna!" + }, + "be-matrix": { + "name": "Matrix-kanal för OpenStreetMap BE", + "description": "Alla kartläggare är välkomna!", + "extendedDescription": "De flesta diskussionerna sker i kanalen \"OpenStreetMap Belgium\". Du kan frÃ¥ga vad som helst där! De andra rummen är för specifika ämnen." + }, + "be-meetup": { + "name": "OpenStreetMap Belgien pÃ¥ Meetup", + "description": "Träffa alla som är intresserade av OpenStreetMap i verkligheten", + "extendedDescription": "Fysiska träffar är ett bra sätt att träffa andra kartläggare, ställa frÃ¥gor till dem och lära dig jättemycket. Speciellt nya bidragsgivare är varmt välkomna!" + }, + "be-twitter": { + "name": "OpenStreetMap Belgium pÃ¥ Twitter", + "description": "OSM Belgien pÃ¥ Twitter: @osm_be" + }, + "talk-cz-mailinglist": { + "name": "E-postlistan Talk-cz", + "description": "Talk-cz är den officiella e-postlistan för den tjeckiska gemenskapen" + }, + "dk-forum": { + "name": "Webbforum för OpenStreetMap Danmark", + "description": "Webbforum för OpenStreetMap Danmark" + }, + "dk-irc": { + "name": "IRC för OpenStreetMap Danmark", + "description": "Anslut #osm-dk pÃ¥ irc.oftc.net (port 6667)" + }, + "dk-mailinglist": { + "name": "E-postlistan Talk-dk", + "description": "En e-postlista för att diskutera OpenStreetMap i Danmark" + }, + "fi-forum": { + "name": "Forum för OpenStreetMap FI", + "description": "Webbforum för OpenStreetMap Finland" + }, + "fi-irc": { + "name": "IRC för OpenStreetMap Finland", + "description": "Anslut #osm-fi pÃ¥ irc.oftc.net (port 6667)" + }, + "fi-mailinglist": { + "name": "E-postlistan Talk-fi", + "description": "Talk-fi är den officiella e-postlistan för den finska OSM-gemenskapen" + }, + "fr-facebook": { + "name": "OpenStreetMap Frankrikes Facebook-sida", + "description": "OpenStreetMap Frankrikes Facebook-sida" + }, + "fr-forum": { + "name": "Webbforum för OpenStreetMap Frankrike ", + "description": "Webbforum för OpenStreetMap Frankrike" + }, + "fr-irc": { + "name": "IRC för OpenStreetMap Frankrike", + "description": "Anslut #osm-fr pÃ¥ irc.oftc.net (port 6667)" + }, + "fr-mailinglist": { + "name": "E-postlistan Talk-fr", + "description": "E-postlistan Talk-fr" + }, + "fr-twitter": { + "name": "OpenStreetMap Frankrike pÃ¥ Twitter", + "description": "OpenStreetMap Frankrike pÃ¥ Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "E-postlista för Berlin", + "description": "Detta är e-postlistan för Berlins OSM-gemenskap" + }, + "de-berlin-meetup": { + "name": "OpenStreetMap Berlin-Brandenburg pÃ¥ Meetup", + "description": "Kartläggare och OpenStreetMap-användare runt Berlin" + }, + "de-berlin-telegram": { + "name": "@osmberlin pÃ¥ Telegram", + "description": "Telegram-chatt för OpenStreetMap Berlin" + }, + "de-berlin-twitter": { + "name": "OpenStreetMap Berlin pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter: {url}" + }, + "de-forum": { + "name": "Forum för OpenStreetMap DE", + "description": "Webbforum för OpenStreetMap Tyskland" + }, + "de-irc": { + "name": "IRC för OpenStreetMap Tyskland", + "description": "Anslut #osm-de pÃ¥ irc.oftc.net (port 6667)" + }, + "de-mailinglist": { + "name": "E-postlistan Talk-de", + "description": "Talk-de är den officiella e-postlistan för den tyska OSM-gemenskapen" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "E-postlista för OWL", + "description": "Detta är e-postlistan för OSM-gemenskap i Ostwestfalen-Lippe" + }, + "osm-de": { + "name": "OpenStreetMap Tyskland", + "description": "Plattformen för information om OpenStreetMap i Tyskland" + }, + "hu-facebook": { + "name": "OpenStreetMap HU pÃ¥ Facebook", + "description": "Kartläggar- och OpenStreetMap-facebook i Ungern" + }, + "hu-forum": { + "name": "Forum för OpenStreetMap HU", + "description": "Webbforum för OpenStreetMap Ungern" + }, + "hu-meetup": { + "name": "OpenStreetMap Ungern pÃ¥ Meetup", + "description": "Plattformen för att organisera träffar i Ungen" + }, + "it-facebook": { + "name": "OpenStreetMap Italien pÃ¥ Facebook", + "description": "Anslut till gemenskapen i OpenStreetMap Italien via Facebook" + }, + "it-irc": { + "name": "IRC för OpenStreetMap Italien", + "description": "Anslut #osm-it pÃ¥ irc.oftc.net (port 6667)" + }, + "it-mailinglist": { + "name": "E-postlistan Talk-it", + "description": "Talk-it är den officiella e-postlistan för den italienske OSM-gemenskapen" + }, + "it-telegram": { + "name": "@OpenStreetMapItalia pÃ¥ Telegram", + "description": "Telegram-chatt för OpenStreetMap Italien" + }, + "it-twitter": { + "name": "OpenStreetMap Italien pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter pÃ¥ {url}" + }, + "OSM-Rome-meetup": { + "name": "Incontro Mappatori Romani", + "description": "Förbättra OpenStreetMap kring Rom", + "extendedDescription": "Vi siktar pÃ¥ att vara en resurs för människor att diskutera och dela kunskaper om hur man använder fri geografiska datasamlingar, speciellt OpenStreetMap, och öppen geo-mjukvara som hanterar, redigerar och visar geografiska data och föresprÃ¥kar för dess användning i Lazio." + }, + "South-Tyrol-Mailing-List": { + "name": "E-postlista för OpenStreetMap i Sydtyrolen", + "description": "Regional e-postlista för OpenStreetMap Italien i Sydtyrolen" + }, + "talk-it-lazio": { + "name": "OpenStreetMap IT Lazio", + "description": "Alla är välkomna! Registrera dig pÃ¥ {signupUrl}", + "extendedDescription": "E-postlista för omrÃ¥det kring Rom och Lazio." + }, + "Trentino-Mailing-List": { + "name": "E-postlista för OpenStreetMap i Trento", + "description": "Regional e-postlista för OpenStreetMap Italien i Trentino" + }, + "no-forum": { + "name": "Webbforum för OpenStreetMap Norge", + "description": "Webbforum för OpenStreetMap Norge" + }, + "no-irc": { + "name": "IRC för OpenStreetMap Norge", + "description": "Chattrum för kartläggare och OpenStreetMap-användare, utvecklare och entusiaster i Norge" + }, + "no-mailinglist": { + "name": "E-postlista för OpenStreetMap i Norge", + "description": "E-postlista för kartläggare och OpenStreetMap-användare, utvecklare och entusiaster i Norge" + }, + "OSM-PL-facebook-group": { + "name": "OpenStreetMap Polens Facebook-grupp", + "description": "Grupp för kartläggare och användare av OpenStreetMap i Polen" + }, + "OSM-PL-forum": { + "name": "Forum för OpenStreetMap Polen", + "description": "Forum för den polska OpenStreetMap-gemenskapen" + }, + "OSM-ES-mailinglist": { + "name": "E-postlistan Talk-es", + "description": "En e-postlista för att diskutera OpenStreetMap i Spanien" + }, + "OSM-ES-telegram": { + "name": "@OSMes pÃ¥ Telegram", + "description": "Telegram-chatt för OpenStreetMap Spanien" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "TillhandahÃ¥ller OSM-tjänster och information för den svenska gemenskapen" + }, + "se-facebook": { + "name": "OpenStreetMap Sverige pÃ¥ Facebook", + "description": "OpenStreetMap Sverige pÃ¥ Facebook" + }, + "se-forum": { + "name": "Webbforum för OpenStreetMap Sverige", + "description": "Webbforum för OpenStreetMap Sverige" + }, + "se-irc": { + "name": "IRC för OpenStreetMap Sverige", + "description": "Anslut #osm.se pÃ¥ irc.oftc.net (port 6667)" + }, + "se-mailinglist": { + "name": "E-postlistan Talk-se", + "description": "En e-postlista för att diskutera OpenStreetMap i Sverige" + }, + "se-twitter": { + "name": "OpenStreetMap Sverige pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter: {url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "Pub-möte en gÃ¥ng i mÃ¥naden i East Midlands (Nottingham)", + "description": "Social sammankomst för kartläggare och användare i East Midlands", + "extendedDescription": "En grupp har träffats sedan mars 2011, ursprungligen i Nottingham, och senare i Derby och ibland nÃ¥gon annanstans i East Midlands. Det är sociala träffar, men det är en utmärkt plats att komma till för att ställa specifika frÃ¥gor om OSM, antingen i näromrÃ¥det eller i allmänhet. Under sommarmÃ¥naderna brukar vi göra lite lätt kartläggning i en timme i närheten av vÃ¥r mötesplats. Gruppen som helhet har ett särskilt intresse för att kartlägga vägrestriktioner och dÃ¥ och dÃ¥ har vi kartläggningsmöten för detta ändamÃ¥l." + }, + "gb-mailinglist": { + "name": "E-postlistan Talk-gb", + "description": "Talk-be är den officiella kommunikationslistan för den brittiska (inklusive nordirländska) OSM-gemenskapen" + }, + "mappa-mercia-group": { + "name": "Lokalgrupp Mappa Mercia", + "description": "Ett hem för OpenStreetMap-entusiaster i Midlands", + "extendedDescription": "Mappa Mercia är ett projekt att förbättra OpenStreetMap i West Midlands, Storbritannien. Vi har gemenskapsevenemang, tillhandahÃ¥ller upplärning och ger support till lokala organisationer som vill öppna upp sin data." + }, + "gb-irc": { + "name": "IRC för OpenStreetMap Storbritannien", + "description": "Anslut #osm-gb pÃ¥ irc.oftc.net (port 6667)", + "extendedDescription": "Anslut #osm-gb pÃ¥ irc.oftc.net (port 6667). Ha tÃ¥lamod och vänta nÃ¥gra minuter om du ställer en frÃ¥ga" + }, + "OSM-CA-Slack": { + "name": "OSM-CA pÃ¥ Slack", + "description": "Alla är välkomna! Registrera dig pÃ¥ {signupUrl}." + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver", + "description": "Kartläggare och OpenStreetMap-användare i Vancouver, BC-omrÃ¥det" + }, + "OSM-CU-telegram": { + "name": "OSM Kuba pÃ¥ Telegram", + "description": "Telegram-chatt för OpenStreetMap Kuba" + }, + "OSM-NI-telegram": { + "name": "OSM Nicaragua pÃ¥ Telegram", + "description": "Telegram-chatt för OpenStreetMap Nicaragua" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Bay Area OpenStreetMappers", + "description": "Förbättra OpenStreetMap i San Francisco Bay Area", + "extendedDescription": "Den här gruppen handlar om att odla OpenStreetMap-gemenskapen här i San Francisco Bay Area. VÃ¥ra evenemang är öppna för alla, frÃ¥n open source-entusiaster, cyklister, GIS-proffs, geocachare m.m. Precis alla som är intresserade av kartor, kartläggning och gratis kartdata är välkomna att delta i vÃ¥r grupp samt delta i vÃ¥ra evenemang." + }, + "Central-Pennsylvania-OSM": { + "name": "Central Pennsylvania OSM", + "description": "Online-kartläggningsgemenskap baserat pÃ¥ State College, PA" + }, + "Code-for-San-Jose-Slack": { + "name": "Kod för San Jose pÃ¥ Slack", + "description": "Alla är välkomna! Registrera dig pÃ¥ {signupUrl} och anslut sedan till #osm-kanalen." + }, + "Dallas-Fort-Worth-OSM": { + "name": "Dallas-Fort Worth OSM", + "description": "OpenStreetMap-användargruppen för Dallas-Fort Worth", + "extendedDescription": "Dallas, Fort Worth och alla städer däremellan är överfulla med kreativa och tekniskt kunniga människor. Visionen för den här användargruppen är att hitta nya sätt att använda OSM:s fantastiska resurser." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Träffar för kart-entusiaster kring Philadelphia", + "extendedDescription": "GeoPhilly förenar utvecklare, geografer, data-nördar, open source-entusiaster, civila hackare och kartmissbrukare i vÃ¥r gemensamma kärlek för kartor och vad de berättar för oss. Om du använder kartor som en del av ditt arbete eller bara vill lära dig mer, är det här samlingspunkten för dig! VÃ¥ra aktiviteter syftar till att vara öppna, vänliga, pedagogiska och sociala och spänna allt frÃ¥n roliga stunder till korta föreläsningar eller till och med workshops. Kom och skapa en varierad, inspirerande geo-gemenskap i Philadelphia med oss!" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "Kartläggare och OpenStreetMap-användare kring Minneapolis–Saint Paul", + "extendedDescription": "Kartläggare och OpenStreetMap-användare kring Minneapolis–Saint Paul" + }, + "Mapping-DC-meetup": { + "name": "Kartlägg Washington, D.C.", + "description": "Förbättra OpenStreetMap kring Washington, D.C.", + "extendedDescription": "Vi är en grupp volontär-kartläggare med syfte att förbättra OpenStreetMap kring Washington, D.C. Vi strävar även efter att lära andra om ekosystemet i OSM, dataanalys, kartografi och GIS. Vi samlas varannan mÃ¥nad för att fokusera pÃ¥ ett omrÃ¥de i vÃ¥r stad." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Kartläggare och OpenStreetMap-användare runt Portland, Maine", + "extendedDescription": "Maptime ger, ganska bokstavligen, tid för kartläggning. VÃ¥rt uppdrag är att öppna dörrarna för kartografiska möjligheter för alla som är intresserade av att skapa tid och utrymme för samarbete, utforskning och kartskapande med hjälp av kartläggningsverktyg och -teknik." + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Förbättra OpenStreetMap kring Cleveland", + "extendedDescription": "Open Geo Cleveland syftar till att vara en resurs för människor att diskutera och dela kunskaper om hur man använder fri geografiska datasamlingar, speciellt OpenStreetMap, och öppen geo-mjukvara som hanterar, redigerar och visar geografiska data och föresprÃ¥kar för dess användning i nordöstra Ohio. Vi är ocksÃ¥ en maptime-filial =)" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Kartläggare och OpenStreetMap-användare runt Boston", + "extendedDescription": "OpenStreetMap är en fria och öppna, wiki-liknande världskarta med hundratusentals bidrag varje dag frÃ¥n människor precis som du. Redigering av kartan är enkelt och roligt! Följ med oss bÃ¥de inomhus och utomhus i vÃ¥rt försök att skapa den bästa kartan över Boston-omrÃ¥det och resten av världen!" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Central Salish Sea", + "description": "Kartläggare och OpenStreetMap-användare runt Mount Vernon, Washington", + "extendedDescription": "OpenStreetMap är en världskarta skapad av människor precis som du. Det är en karta du bygger och ger bort gratis, precis som Wikipedia. Ta en titt pÃ¥ osm.org för mer information. Vi träffas hela tiden för att prata om kartor, skapar kartor och har kul!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "OpenStreetMap-användargruppen för Chattanooga, Tennessee" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "description": "Kartläggare och OpenStreetMap-användare i staten Colorado, USA", + "extendedDescription": "OpenStreetMap (OSM) Colorado är en lokal gemenskap med personer som är intresserade av att bidra till att skapa gratiskartor. Vi uppmuntrar alla vÃ¥ra kartläggare att organisera eller föreslÃ¥ kartläggningsevenemang i hela staten. Meetup-aktiviteter kan vara enkla sociala träffar, enkla eller avancerade utbildningar kring OSM eller gemensamma kartläggningsatsningar." + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "Kartläggare och OpenStreetMap-användare, utvecklare och entusiaster runt storstadsregionen New Yorks." + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Kartläggare och OpenStreetMap-användare runt Portland", + "extendedDescription": "OpenStreetMap (OSM) är en världskarta skapad av människor precis som du. Det är en karta du bygger och ger bort gratis, precis som Wikipedia. Ta en titt pÃ¥ osm.org för mer information, och kom med pÃ¥ ett meetup för att prata om kartor, bidra till OSM och ha kul!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Kartläggare och OpenStreetMap-användare runt Seattle" + }, + "OSM-SoCal": { + "name": "OpenStreetMap södra Kalifornien", + "description": "LÃ¥t oss ha lite kul, bidra med nÃ¥got till Los Angeles och lär dig om kartläggning!", + "extendedDescription": "OpenStreetMap (SOM) Södra Kalifornien är för alla intresserade av kartläggning för att komma tillsammans för att arbeta med OpenStreetMap. OpenStreetMap, Wikipedia för kartor, är en gratis open source-karta över hela världen som skapats av mer än 1 000 000 volontärer runt hela världen. Alla är välkomna. Om du inte känner till OpenStreetMap lär vi dig. Om du har en idé kring ett kartläggningsprojekt, eller en t.o.m. en studieresa som en grupp människor kan göra, har du fullt stöd frÃ¥n oss!" + }, + "OSM-South-Bay": { + "name": "OSM South Bay", + "description": "Kartkvällar arrangerade av Code for San Jose", + "extendedDescription": "Code for San Jose, den lokala Code for America-brigaden, arrangerar en gÃ¥ng i mÃ¥naden kart-kvällar pÃ¥ en torsdag kväll i centrala San José. Träffa andra kartläggare frÃ¥n South Bay, hjälp till i kartläggningsprojekt och hör om andra medborgarorienterade teknikprojekt. Programmerings- och GIS-kunskap är inget krav." + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Tampa Bay", + "description": "Kartläggare och OpenStreetMap-användare runt Tampa Bay", + "extendedDescription": "Gruppen OSM Tampa Bay är till för att lokalinvÃ¥nare ska förenas och bygga upp den optimala kartan över Tampa Bay med OpenStreetMap, den fria och redigerbara kartan över världen. Om du gillar kartor, data, open source, GPS, vandring, cykling, etc., kommer du att älska att arbeta med OpenStreetMap\n-- sÃ¥ gÃ¥ med! Vi kommer samman, kartlägger och pratar om nya ämnen ungefär en gÃ¥ng i mÃ¥naden." + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US pÃ¥ Slack", + "description": "Alla är välkomna! Registrera dig pÃ¥ {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap US", + "description": "Vi hjälper till att utöka och förbättra OpenStreetMap i USA.", + "extendedDescription": "Vi stöder OpenStreetMap genom att ha Ã¥rliga konferencier, tillhandahÃ¥ller resurser för gemenskapen, bygger nätverk och genom att sprida ordet. GÃ¥ med i OpenStreetMap USA här: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah", + "description": "Kartläggare och OpenStreetMap-användare runt Salt Lake City", + "extendedDescription": "Aktiviteter kan vara saker sÃ¥ som workshops där man lär sig att kartlägga, kartläggningsfester och datainsamling utomhus. Aktiviteterna kommer äga rum kring Salt Lake City, Ã¥tminstone initialt. Vi söker bÃ¥de efter erfarna kartläggare och nybörjare. GÃ¥ med och lÃ¥t oss göra lite kartläggning!" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming", + "description": "Kartläggare och OpenStreetMap-användare i staten Wyoming", + "extendedDescription": "OpenStreetMap (OSM) Wyoming är en lokal gemenskap med personer som är intresserade av att bidra till att skapa gratiskartor. Vi uppmuntrar alla vÃ¥ra kartläggare att organisera eller föreslÃ¥ kartläggningsevenemang i hela staten. Meetup-aktiviteter kan vara enkla sociala träffar, enkla eller avancerade utbildningar kring OSM eller gemensamma kartläggningsatsningar." + }, + "PHXGeo-meetup": { + "name": "PHXGeo pÃ¥ Meetup", + "description": "Kartläggare och OpenStreetMap-användare kring Phoenix, Arizona", + "extendedDescription": "Detta är en meetup-grupp för de kring Phoenix som gillar kartläggning, GIS, OpenStreetMap, kartografi och allt däremellan. " + }, + "PHXGeo-twitter": { + "name": "PHXGeo pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter pÃ¥ {url}" + }, + "Western-Slope-facebook": { + "name": "OSM-Facebook för Western Slope ", + "description": "Kartläggare och OpenStreetMap-användare runt Grand Junction, Colorado" + }, + "Western-Slope-meetup": { + "name": "Western Slope (Colorado) pÃ¥ Meetup", + "description": "Kartläggare och OpenStreetMap-användare kring Grand Junction, Colorado", + "extendedDescription": "MÃ¥let med denna grupp är att introducera OpenStreetMap för allmänheten, utveckla en gemenskap av kartläggare, skapa den bästa möjliga geodatan med alla till buds stÃ¥ende medel och därefter fÃ¥ ut denna data i samhället. Föreställ dig korrekta vägskyltar! Föreställ dig ytterligare förbättring av cykelvägar! Föreställ dig precis vad som helst, det är det som är glädjen med OpenStreetMap!" + }, + "Maptime-Australia-Slack": { + "name": "Maptime Australien pÃ¥ Slack", + "description": "Registrera dig pÃ¥ {signupUrl}" + }, + "talk-au": { + "name": "E-postlistan Talk-au", + "description": "Plats där australienska användare kan chatta" + }, + "OSM-AR-facebook": { + "name": "OpenStreetMap Argentina pÃ¥ Facebook", + "description": "Anslut till gemenskapen pÃ¥ OpenStreetMap Argentina via Facebook", + "extendedDescription": "Nyheter frÃ¥n den lokala gemenskapen" + }, + "OSM-AR-forum": { + "name": "Webbforum för OpenStreetMap Argentinska", + "description": "Anslut till OpenStreetMap argentinska webbforum", + "extendedDescription": "Ideal för lÃ¥nga eller viktiga diskussioner. LÃ¥ng svarstid." + }, + "OSM-AR-irc": { + "name": "IRC för OpenStreetMap Argentina", + "description": "Anslut #osm-ar pÃ¥ irc.oftc.net (port 6667)", + "extendedDescription": "Du kan stöta pÃ¥ den mest nördiga användaren i gemenskapen." + }, + "OSM-AR-mailinglist": { + "name": "E-postlistan Talk-ar", + "description": "Historisk e-postlista. Knappt använd idag." + }, + "OSM-AR-telegram": { + "name": "Telegram för OpenStreetMap Argentina", + "description": "Anslut till gemenskapen pÃ¥ OpenStreetMap Argentina via Telegram", + "extendedDescription": "Den mest aktiva kanalen i gemenskapen, ideal för att chatta och fÃ¥ svar pÃ¥ dina frÃ¥gor snabbt. Alla är välkomna!" + }, + "OSM-AR-twitter": { + "name": "OpenStreetMap Argentina pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter pÃ¥ {url}", + "extendedDescription": "Nyheter frÃ¥n den lokala gemenskapen och OpenStreetMap i allmänhet." + }, + "OSM-BO-mailinglist": { + "name": "E-postlistan Talk-bo", + "description": "Talk-bo är den officiella e-postlistan för den bolivianska OSM-gemenskapen", + "extendedDescription": "Kartlägger i Bolivia? Har du frÃ¥gor, vill komma i kontakt med gemenskapen här? GÃ¥ med pÃ¥ {url}. Alla är välkomna!" + }, + "Bahia-telegram": { + "name": "Telegram för OpenStreetMap Bahia", + "description": "Anslut till gemenskapen pÃ¥ OpenStreetMap Bahia via Telegram", + "extendedDescription": "Anslut till gemenskapen för att lära dig mer om OpenStreetMap, ställa frÃ¥gor eller delta pÃ¥ vÃ¥ra möten. Alla är välkomna!" + }, + "DF-telegram": { + "name": "Telegram för OpenStreetMap Brasília", + "description": "Anslut till gemenskapen pÃ¥ OpenStreetMap Brasília via Telegram", + "extendedDescription": "Anslut till gemenskapen för att lära dig mer om OpenStreetMap, ställa frÃ¥gor eller delta pÃ¥ vÃ¥ra möten. Alla är välkomna!" + }, + "OSM-br-mailinglist": { + "name": "E-postlistan Talk-br", + "description": "En e-postlista för att diskutera OpenStreetMap i Brasilien" + }, + "OSM-br-telegram": { + "name": "Telegram för OpenStreetMap Brasilien", + "description": "Anslut till gemenskapen pÃ¥ OpenStreetMap Brasilien via Telegram", + "extendedDescription": "Anslut till gemenskapen för att lära dig mer om OpenStreetMap, ställa frÃ¥gor eller delta pÃ¥ vÃ¥ra möten. Alla är välkomna!" + }, + "OSM-br-twitter": { + "name": "OpenStreetMap Brasilien pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter pÃ¥ {url}" + }, + "OSM-CL-facebook": { + "name": "OpenStreetMap Chile pÃ¥ Facebook", + "description": "Anslut till gemenskapen i OpenStreetMap Child via Facebook", + "extendedDescription": "Anslut till gemenskapen för att lära dig mer om OpenStreetMap, ställa frÃ¥gor eller delta pÃ¥ vÃ¥ra möten. Alla är välkomna!" + }, + "OSM-CL-mailinglist": { + "name": "E-postlista Talk-cl", + "description": "En e-postlista för att diskutera OpenStreetMap i Chile" + }, + "OSM-CL-telegram": { + "name": "Telegram för OpenStreetMap Chile", + "description": "Anslut till gemenskapen i OpenStreetMap Child via Telegram", + "extendedDescription": "Anslut till gemenskapen för att lära dig mer om OpenStreetMap, ställa frÃ¥gor eller delta pÃ¥ vÃ¥ra möten. Alla är välkomna!" + }, + "OSM-CL-twitter": { + "name": "OpenStreetMap Chile pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter pÃ¥ {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá", + "description": "Vi är en grupp av kartläggare intresserade av OpenStreetMap kring Bogotá.", + "extendedDescription": "Lär dig att samla in data pÃ¥ fältet och digitalisera det i OpenStreetMap. Det finns inga krav pÃ¥ förkunskaper! Du behöver bara lusten att delta, lära dig och ha kul." + }, + "OSM-CO-facebook": { + "name": "OpenStreetMap Colombia pÃ¥ Facebook", + "description": "Anslut till gemenskapen i OpenStreetMap Columbia via Facebook", + "extendedDescription": "Anslut till gemenskapen för att lära dig mer om OpenStreetMap. Alla är välkomna!" + }, + "OSM-CO-mailinglist": { + "name": "E-postlistan Talk-co", + "description": "En e-postlista för att diskutera OpenStreetMap i Colombia" + }, + "OSM-CO-telegram": { + "name": "OSM Colombia pÃ¥ Telegram", + "description": "Telegram-chatt för OpenStreetMap Colombia " + }, + "OSM-CO-twitter": { + "name": "OpenStreetMap Colombia pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter pÃ¥ {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Colombia", + "description": "Nyheter om OpenStreetMap Colombia-gemenskapen och OSMCo Foundation" + }, + "OSM-EC-telegram": { + "name": "OSM Ecuador pÃ¥ Telegram", + "description": "Telegram-chatt för OpenStreetMap Ecuador" + }, + "OSM-PY-telegram": { + "name": "OSM Paraguay pÃ¥ Telegram", + "description": "Telegram-chatt för OpenStreetMap Paraguay" + }, + "OSM-PE-facebook": { + "name": "OpenStreetMap Peru pÃ¥ Facebook", + "description": "Anslut till gemenskapen i OpenStreetMap Peru via Facebook" + }, + "OSM-PE-mailinglist": { + "name": "E-postlistan Talk-pe", + "description": "Den officiella e-postlistan för OpenStreetMap-gemenskapen i Peru" + }, + "OSM-PE-matrix": { + "name": "Matrix-chat för OpenStreetMap Peru", + "description": "Chatta med andra medlemmar i OpenStreetMap Peru-gemenskapen via Matrix." + }, + "OSM-PE-telegram": { + "name": "Telegram för OpenStreetMap Peru", + "description": "Anslut till gemenskapen i OpenStreetMap Peru via Telegram" + }, + "OSM-PE-twitter": { + "name": "OpenStreetMap Peru pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter pÃ¥ {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap Peru", + "description": "Nyheter och resurser för OpenStreetMap Peru-gemenskapen" + }, + "OSM-Facebook": { + "name": "OpenStreetMap pÃ¥ Facebook", + "description": "Gilla oss pÃ¥ Facebook för nyheter och uppdateringar om OpenStreetMap" + }, + "OSM-help": { + "name": "OpenStreetMap-hjälp", + "description": "Ställ en frÃ¥ga och fÃ¥ svar pÃ¥ OSM:s användardrivna frÃ¥gor och svar-sida.", + "extendedDescription": "{url} är för alla som behöver hjälp med OpenStreetMap. Oavsett om du är en nybörjarkartläggare eller har tekniska frÃ¥gor, är vi här för att hjälpa dig!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap pÃ¥ Reddit", + "description": "/r/openstreetmap/ är ett bra ställe att lära sig mer om OpenStreetMap. FrÃ¥ga om vad som helst!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap pÃ¥ Twitter", + "description": "Följ oss pÃ¥ Twitter pÃ¥ {url}" + }, + "OSMF": { + "name": "OpenStreetMap Foundation", + "description": "OSMF är en ideell organisation baserat i Storbritannien som stöttar OpenStreetMap-projekt.", + "extendedDescription": "OSMF stöder OpenStreetMap genom insamling, underhÃ¥ll av servrarna som driver OSM, organiserar den Ã¥rliga State of the Map-konferensen och samordnar de volontärer som hÃ¥ller OSM igÃ¥ng. Du kan visa ditt stöd och göra din röst hörd för OpenStreetMap genom att bli medlem i OSMF här: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Delta pÃ¥ den 3 dagar lÃ¥nga Ã¥rliga världsomspännande OpenStreetMap-konferensen i Milano, Italien, vilken sammanför alla i gemenskapen för att umgÃ¥s, dela med sig och lära.", + "where": "Milan, Italien" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/ta.json b/vendor/assets/iD/iD/locales/ta.json index fd21159b4..a34da8f31 100644 --- a/vendor/assets/iD/iD/locales/ta.json +++ b/vendor/assets/iD/iD/locales/ta.json @@ -209,10 +209,6 @@ } }, "success": { - "view_on_osm": "OSM இல் பார்", - "facebook": "Facebook இல் பகிர்ந்து கொள்ள", - "twitter": "Twitter இல் பகிர்ந்து கொள்ள", - "google": "Google+ இல் பகிர்ந்து கொள்ள", "help_link_text": "விவரங்கள்" }, "confirm": { @@ -783,7 +779,6 @@ } }, "phone": { - "label": "தொலைபேசி", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { diff --git a/vendor/assets/iD/iD/locales/te.json b/vendor/assets/iD/iD/locales/te.json index 39729472c..ccef0a449 100644 --- a/vendor/assets/iD/iD/locales/te.json +++ b/vendor/assets/iD/iD/locales/te.json @@ -147,7 +147,6 @@ "key": "సీ", "annotation": "{n} లక్షణాలు విలీనించబడ్డాయి.", "not_eligible": "ఈ విశేషాలు విలీనానికి చేయబడలేవు", - "restriction": "ఈ లక్షణాలు విలీనింపబడవు ఎందుకంటే కనీసం ఒకటి \"{relation}\" సంబంధంలో అంశం.", "incomplete_relation": "ఈ లక్షణాలు విలీనింపబడవు ఎందుకంటే కనీసం ఒక లక్షణం పూర్తిగా డౌన్‌లోడ్ కాలేదు.", "conflicting_tags": "ఈ లక్షణాలు విలీనింపబడవు ఎందుకంటే వాటిలో కొన్ని ట్యాగ్‌లకు విలువలు విరుద్ధంగా ఉన్నాయి. " }, @@ -326,10 +325,6 @@ }, "success": { "just_edited": "మీరు ఇప్పుడే OpenStreetMapను మార్చారు", - "view_on_osm": "OSM/ఓఎస్ఎం లో వీక్షించు", - "facebook": "ఫేస్‌బుక్‌లో పంచుకోండి", - "twitter": "ట్విట్టర్లో పంచుకోండి", - "google": "గూగుల్+లో పంచుకోండి", "help_link_text": "వివరాలు" }, "confirm": { @@ -488,9 +483,6 @@ "parking": { "label": "రకం" }, - "phone": { - "label": "ఫోన్" - }, "place": { "label": "రకం" }, diff --git a/vendor/assets/iD/iD/locales/tl.json b/vendor/assets/iD/iD/locales/tl.json index 3210ccac7..d5a8b1b91 100644 --- a/vendor/assets/iD/iD/locales/tl.json +++ b/vendor/assets/iD/iD/locales/tl.json @@ -1,5 +1,8 @@ { "tl": { + "icons": { + "remove": "tanggalin" + }, "modes": { "add_area": { "title": "Poligon", @@ -38,11 +41,11 @@ "start": { "annotation": { "line": "Nagsimula ng isang linya.", - "area": "Nagsimula sa isang area o polygon." + "area": "Nagsimula ng isang area o polygon." } }, "continue": { - "key": "a", + "key": "A", "title": "Ipagpatuloy", "description": "Ipagpatuloy ang linyang ito.", "not_eligible": "Walang linyang maaring ipagpatuloy dito.", @@ -155,7 +158,6 @@ "key": "C", "annotation": "Pinagsama ang {n} features.", "not_eligible": "Ang mga bagay na ito ay hindi maaaring pagsamahin.", - "restriction": "Hindi maaring pagsamahin dahil may isang o higit pang feature na bahagi ng \"{relation}\" relation.", "incomplete_relation": "Hindi maaaring ipagsama o i-merge dahil ang isa sa mga ito ay hindi pa ganap na nai-download.", "conflicting_tags": "Hindi maaring pagsamahin dahil may magkakaibang mga tags ang bawat isa." }, @@ -264,6 +266,14 @@ } } }, + "restriction": { + "controls": { + "distance": "Distansya" + }, + "help": { + "from": "GALING" + } + }, "undo": { "tooltip": "I-undo:{action}", "nothing": "Walang ma-undo" @@ -313,6 +323,24 @@ "list": "Edits nina {users}", "truncated_list": "Edits nina {users} at {count} iba pa" }, + "info_panels": { + "key": "I", + "background": { + "key": "B", + "source": "Pinagmulan", + "description": "Paglalarawan" + }, + "history": { + "key": "H", + "title": "Bersyon" + }, + "location": { + "title": "Lokasyon" + }, + "measurement": { + "location": "Lokasyon" + } + }, "geometry": { "point": "tuldok", "vertex": "tuluktok", @@ -451,12 +479,7 @@ } }, "success": { - "edited_osm": "Nag-edit sa OSM!", "just_edited": "Nag-edit ka sa OpenStreetMap!", - "view_on_osm": "Tingnan sa OSM", - "facebook": "I-share sa Facebook", - "twitter": "I-share sa Twitter", - "google": "I-share sa Google+", "help_link_text": "Mga detalye", "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" }, @@ -698,6 +721,15 @@ "amenity": { "label": "Uri" }, + "animal_boarding": { + "label": "Para sa hayop" + }, + "animal_breeding": { + "label": "Para sa hayop" + }, + "animal_shelter": { + "label": "Para sa hayop" + }, "area/highway": { "label": "Uri" }, @@ -754,12 +786,18 @@ "board_type": { "label": "uri" }, + "boules": { + "label": "Uri" + }, "boundary": { "label": "Uri" }, "brand": { "label": "tatak" }, + "bridge": { + "label": "Uri" + }, "building": { "label": "Gusali" }, @@ -769,6 +807,10 @@ "bunker_type": { "label": "uri" }, + "cables": { + "label": "Mga kable", + "placeholder": "1, 2, 3..." + }, "camera/direction": { "label": "Direksyon (Paikot sa kanan)", "placeholder": "45, 90, 180, 270" @@ -791,9 +833,18 @@ "castle_type": { "label": "uri" }, + "clothes": { + "label": "Mga damit" + }, + "club": { + "label": "Uri" + }, "collection_times": { "label": "Mga oras ng koleksyon" }, + "communication_multi": { + "label": "Mga uri ng komunikasyon" + }, "construction": { "label": "Uri" }, @@ -801,6 +852,9 @@ "label": "URL ng webcam", "placeholder": "http://example.com/" }, + "content": { + "label": "Nilalaman" + }, "country": { "label": "bansa" }, @@ -816,6 +870,9 @@ "currency_multi": { "label": "Uri ng pera" }, + "cutting": { + "label": "Uri" + }, "cycle_network": { "label": "Network" }, @@ -861,12 +918,56 @@ "denotation": { "label": "denotasyon" }, + "description": { + "label": "Paglalarawan" + }, + "devices": { + "label": "Mga aparato", + "placeholder": "1, 2, 3..." + }, + "direction": { + "label": "Direksyon (Degrees Clockwise)", + "placeholder": "45, 90, 180, 270" + }, + "direction_cardinal": { + "label": "Direksyon", + "options": { + "E": "Silangan", + "ENE": "Silangan-Hilagang-silangan", + "ESE": "Silangan-Timog-silangan", + "N": "Hilaga", + "NE": "Hilagang-silangan", + "NNE": "Hilaga-Hiligang-silangan", + "NNW": "Hilaga-Hilagang-kanluran", + "NW": "Hilagang-kanluran", + "S": "Timog", + "SE": "Timog-silangan", + "SSE": "Timog-Timog-silangan", + "SSW": "Timog-Timog-kanluran", + "SW": "Timog-kanluran", + "W": "Kanluran", + "WNW": "Kanluran-Hilagang-kanluran", + "WSW": "Kanluran-Timog-kanluran" + } + }, + "direction_clock": { + "label": "Direksyon" + }, + "direction_vertex": { + "label": "Direksyon", + "options": { + "both": "Pareho / Lahat" + } + }, "display": { "label": "Ipakita" }, "dock": { "label": "uri" }, + "duration": { + "placeholder": "00:00" + }, "electrified": { "options": { "no": "Hindi", @@ -876,6 +977,9 @@ "email": { "placeholder": "example@example.com" }, + "emergency": { + "label": "Kagipitan" + }, "entrance": { "label": "Uri" }, @@ -896,28 +1000,86 @@ } }, "fire_hydrant/type": { + "label": "Uri", + "options": { + "wall": "Pader" + } + }, + "fixme": { + "label": "Ayusin Mo Ako" + }, + "ford": { "label": "Uri" }, + "gender": { + "label": "Kasarian", + "options": { + "female": "Babae", + "male": "Lalaki" + }, + "placeholder": "Hindi alam" + }, + "generator/method": { + "label": "Paraan" + }, + "generator/source": { + "label": "Pinagmulan" + }, "generator/type": { "label": "Uri" }, + "government": { + "label": "Uri" + }, + "hashtags": { + "placeholder": "#halimbawa" + }, + "healthcare": { + "label": "Uri" + }, "highway": { "label": "Uri" }, "historic": { "label": "Uri" }, + "hoops": { + "placeholder": "1, 2, 4..." + }, + "iata": { + "label": "IATA" + }, + "icao": { + "label": "ICAO" + }, + "incline_steps": { + "options": { + "down": "Baba", + "up": "Taas" + } + }, + "industrial": { + "label": "Uri" + }, "information": { "label": "Uri" }, "internet_access": { "options": { - "wlan": "Wifi" + "no": "Hindi", + "wlan": "Wifi", + "yes": "Oo" } }, "landuse": { "label": "Uri" }, + "lanes": { + "placeholder": "1, 2, 3..." + }, + "layer": { + "placeholder": "0" + }, "leisure": { "label": "Uri" }, diff --git a/vendor/assets/iD/iD/locales/tr.json b/vendor/assets/iD/iD/locales/tr.json index 4dbdb85c9..68e9782af 100644 --- a/vendor/assets/iD/iD/locales/tr.json +++ b/vendor/assets/iD/iD/locales/tr.json @@ -163,7 +163,6 @@ "annotation": "{n} nesne birleştirildi.", "not_eligible": "Bu nesneler birleştirilemez.", "not_adjacent": "Bu nesneler birleştirilemez, çünkü birbirleriyle bağlı değiller.", - "restriction": "Bu nesneler birleştirilemez, çünkü en az bir tanesi \"{relation}\" kümesinin üyesi.", "incomplete_relation": "Bu nesneler birleştirilemez, çünkü içlerinden en az biri henüz tamamen indirilmedi.", "conflicting_tags": "Bu nesneler birleştirilemez, çünkü bazı etiketleri birbiriyle çelişkili değerlere sahip." }, @@ -601,13 +600,7 @@ } }, "success": { - "edited_osm": "OSM güncellendi!", "just_edited": "OpenStreetMap'te bir değişiklik yaptın!", - "view_on_osm": "OSM'de gör", - "facebook": "Facebook'ta Paylaş", - "twitter": "Twitter'da Paylaş", - "google": "Google+'ta Paylaş", - "help_html": "Yaptığın değişiklikleri \"Standard\" harita katmanında birkaç dakika içerinde görebilirsin. Diğer katmanlar ve nesnelerin güncellenmesi biraz zaman alabilir.", "help_link_text": "Detaylar", "help_link_url": "Yaptığın değişiklikleri nasıl görebileceğine dair detaylı bilgiyi şu adreste bulabilirsin - Ä°ngilizce: https://wiki.openstreetmap.org/wiki/FAQ#I_have_just_made_some_changes_to_the_map._How_do_I_get_to_see_my_changes.3F" }, @@ -1994,7 +1987,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "Telefon", "placeholder": "+31 42 123 4567" }, "piste/difficulty": { @@ -2413,9 +2405,6 @@ "label": "Tür", "placeholder": "Varsayılan" }, - "vending": { - "label": "Ürün Çeşidi" - }, "visibility": { "label": "Görüş", "options": { @@ -5705,18 +5694,6 @@ "name": "U-dönüşü Yasak", "terms": "U-dönüşü Yasak" }, - "type/restriction/only_left_turn": { - "name": "Sola Dönüş Zorunlu", - "terms": "Sola Dönüş Zorunlu" - }, - "type/restriction/only_right_turn": { - "name": "Sağa Dönüş Zorunlu", - "terms": "Sağa Dönüş Zorunlu" - }, - "type/restriction/only_straight_on": { - "name": "Dönüş Yasak", - "terms": "Dönüş Yasak" - }, "type/route": { "name": "Güzergah", "terms": "Güzergah, Rota" @@ -5866,7 +5843,6 @@ "attribution": { "text": "Şartlar ve Geri Bildirim" }, - "description": "Görüntü sınırları ve çekilme tarihleri. Etiketler yakınlaştırma düzeyi 14 veya daha üstünde gösterilir.", "name": "DigitalGlobe Özel Görüntü Dönemi Ürünü" }, "DigitalGlobe-Standard": { @@ -5880,7 +5856,6 @@ "attribution": { "text": "Şartlar ve Geri Bildirim" }, - "description": "Görüntü sınırları ve çekilme tarihleri. Etiketler yakınlaştırma düzeyi 14 veya daha üstünde gösterilir.", "name": "DigitalGlobe Standard Görüntü Dönemi Ürünü" }, "EsriWorldImagery": { @@ -5996,7 +5971,6 @@ "attribution": { "text": "basemap.at" }, - "description": "Hükümet verilerinden oluşturulmuş Avusturya haritası", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6057,9 +6031,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Harita Stamen Design, CC BY 3.0" - }, "name": "Stamen Arazi" }, "tf-cycle": { diff --git a/vendor/assets/iD/iD/locales/uk.json b/vendor/assets/iD/iD/locales/uk.json index 2e33f1a75..03a29839b 100644 --- a/vendor/assets/iD/iD/locales/uk.json +++ b/vendor/assets/iD/iD/locales/uk.json @@ -1,5 +1,10 @@ { "uk": { + "icons": { + "information": "інформація", + "remove": "вилучити", + "undo": "відмінити" + }, "modes": { "add_area": { "title": "Полігон", @@ -145,7 +150,9 @@ "vertex": "Лінію приєднано до іншої лінії.", "line": "Лінія з’єднана з іншою лінією.", "area": "Лінія з’єднана з полігоном." - } + }, + "relation": "Ці обʼєкти не можуть бути зʼєднані, бо вони мають ролі, значення яких конфліктують між собою.", + "restriction": "Ці об’єкти не можуть бути з’єднані, це може зруйнувати звʼязок \"{relation}\"." }, "disconnect": { "title": "Від’єднати", @@ -163,7 +170,8 @@ "annotation": "Обʼєднано {n} обʼєктів.", "not_eligible": "Ці об’єкти неможливо об’єднати.", "not_adjacent": "Ці обʼєкти не можуть бути обʼєднані, бо їх кінцеві точки не зʼєднані.", - "restriction": "Ці об’єкти не можуть бути об’єднані, принаймні один з них є членом звʼязку \"{relation}\".", + "restriction": "Ці об’єкти не можуть бути об’єднані, це може пошкодити звʼязок \"{relation}\".", + "relation": "Ці об’єкти не можуть бути об’єднані, вони мають ролі, що конфліктують друг з другом.", "incomplete_relation": "Ці об’єкти не можуть бути об’єднані, принаймні один з них завантажений не повністю.", "conflicting_tags": "Ці обʼєкти не можуть бути обʼєднані, бо вони мають теґи, значення яких не збігаються." }, @@ -402,6 +410,7 @@ "key": "H", "title": "Історія", "selected": "{n} виділено", + "no_history": "Історія відсутня (Новий об'єкт)", "version": "Версія", "last_edit": "Останні зміни", "edited_by": "Змінено: ", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "OSM змінено!", "just_edited": "Ви щойно внесли зміни на мапу OpenStreetMap!", - "view_on_osm": "Подивитись в OSM", - "facebook": "Поділитись у Facebook", - "twitter": "Поділитись у Twitter", - "google": "Поділитись у Google+", - "help_html": "Ваші зміни зʼявляться на \"Стандартному\" шарі через кілька хвилин. На інших шарах зміни зʼявляться згодом.", + "thank_you": "Дякуємо за вдосконалення мапи.", + "thank_you_location": "Дякуємо вам з вдосконалення мапи навколо {where}.", + "help_html": "Ваші зміни зʼявляться на OpenStreetMap через кілька хвилин. На інших шарах зміни зʼявляться згодом.", "help_link_text": "Деталі", - "help_link_url": "https://wiki.openstreetmap.org/wiki/Uk:ЧаПи#.D0.AF_.D1.89.D0.BE.D0.B9.D0.BD.D0.BE_.D0.B7.D1.80.D0.BE.D0.B1.D0.B8.D0.B2_.D0.B4.D0.B5.D1.8F.D0.BA.D1.96_.D0.B7.D0.BC.D1.96.D0.BD.D0.B8_.D0.BD.D0.B0_.D0.BC.D0.B0.D0.BF.D1.96._.D0.AF.D0.BA_.D0.BC.D0.B5.D0.BD.D1.96_.D1.97.D1.85_.D0.BF.D0.BE.D0.B1.D0.B0.D1.87.D0.B8.D1.82.D0.B8.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/Uk:ЧаПи#.D0.AF_.D1.89.D0.BE.D0.B9.D0.BD.D0.BE_.D0.B7.D1.80.D0.BE.D0.B1.D0.B8.D0.B2_.D0.B4.D0.B5.D1.8F.D0.BA.D1.96_.D0.B7.D0.BC.D1.96.D0.BD.D0.B8_.D0.BD.D0.B0_.D0.BC.D0.B0.D0.BF.D1.96._.D0.AF.D0.BA_.D0.BC.D0.B5.D0.BD.D1.96_.D1.97.D1.85_.D0.BF.D0.BE.D0.B1.D0.B0.D1.87.D0.B8.D1.82.D0.B8.3F", + "view_on_osm": "Подивтись зміни в ОСМ", + "changeset_id": "Номер вашого набору змін: {changeset_id}", + "like_osm": "Подобається OpenStreetMap? Приєднайтесь до:", + "more": "Ще", + "events": "Події", + "languages": "Мови: {languages}", + "missing": "Щось з цього переліку відсутнє?", + "tell_us": "Розкажіть нам!" }, "confirm": { "okay": "Так", @@ -1703,6 +1717,9 @@ "cycleway:right": "Праворуч" } }, + "dance/style": { + "label": "Види танців" + }, "date": { "label": "Дата" }, @@ -1771,6 +1788,9 @@ "display": { "label": "Циферблат" }, + "distance": { + "label": "Відстань" + }, "dock": { "label": "Тип" }, @@ -1811,6 +1831,9 @@ "except": { "label": "Винятки" }, + "faces": { + "label": "Сторони" + }, "fax": { "label": "Факс", "placeholder": "+31 42 123 4567" @@ -1922,6 +1945,39 @@ "label": "Кільця", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "Виїздка", + "options": { + "equestrian": "Так", + "undefined": "Ні" + } + }, + "horse_riding": { + "label": "Верхова їзда", + "options": { + "horse_riding": "Так", + "undefined": "Ні" + } + }, + "horse_scale": { + "label": "Складність маршруту", + "options": { + "common": "Легкий: жодних складностпей. (типовий)", + "critical": "Дуже складний: тільки для досвідчених вершників та їх коней. Багато перешкод. Мости вимагають попереднього огляду на придатність рухатись по ним коням.", + "dangerous": "Небезпечний: тільки для дуже досвідчених вершників та їх коней і тільки за сприятливих погодних умов. Пересування тільки спішившись.", + "demanding": "Будьте обережні: нерівний шлях, іноді складні переходи.", + "difficult": "Складний: Шлях вузький і незахищений. Може містити перешкоди, які треба долати, та вузькі проходи.", + "impossible": "Неможливий: Шлях чи міст не придатні для коней. Завузький, недостатня підтримка, перешкоди, такі як драбини. Небезпека життю." + }, + "placeholder": "Складно, Небезпечно…" + }, + "horse_stables": { + "label": "Стайня", + "options": { + "stables": "Так", + "undefined": "Ні" + } + }, "iata": { "label": "IATA" }, @@ -1941,6 +1997,9 @@ "indoor": { "label": "План приміщення" }, + "industrial": { + "label": "Тип" + }, "information": { "label": "Тип" }, @@ -2061,6 +2120,10 @@ "label": "Обмеження швидкості", "placeholder": "40, 50, 60…" }, + "maxspeed/advisory": { + "label": "Рекомендована швидкість", + "placeholder": "40, 50, 60…" + }, "maxstay": { "label": "Максимальний час" }, @@ -2649,8 +2712,19 @@ "label": "Тип", "placeholder": "Типово" }, + "usage_rail": { + "label": "Тіп колії", + "options": { + "branch": "Гілка", + "industrial": "Промислова", + "main": "Основний путь", + "military": "Військова", + "test": "Випробувальна", + "tourism": "Туристична" + } + }, "vending": { - "label": "Тип товарів" + "label": "Товари" }, "visibility": { "label": "Видно з", @@ -2745,6 +2819,10 @@ "name": "Рекламний щит", "terms": "реклама,оголошення,щит,бігборд,борд,інформація" }, + "advertising/column": { + "name": "Тумба для оголошень", + "terms": "реклама,сітілайт,лайтбокс,оголошення,конструкція,колона,тумба" + }, "aerialway": { "name": "Канатна дорога" }, @@ -2830,6 +2908,10 @@ "name": "Термінал", "terms": "аеропорт,термінал,літак,очікування,duty-free,дьюті-фрі,зала" }, + "allotments/plot": { + "name": "Дачна ділянка", + "terms": "дача,город,сад,ділянка,участок" + }, "amenity": { "name": "Зручності" }, @@ -3058,6 +3140,10 @@ "name": "Ринок", "terms": "Marketplace, hbyjr, базар, базарна площа" }, + "amenity/monastery": { + "name": "Територія монастиря", + "terms": "абатство,базиліка,моелельня,собор,вівтар,каплиця,церква,дім божий,молитовний дім,обрядовий дім,міссія,монастир,мечеть,приход,святилище,рака,святиня,синагога,храм" + }, "amenity/motorcycle_parking": { "name": "Стоянка для мотоциклів", "terms": "стоянка,мотоцикл" @@ -3262,6 +3348,10 @@ "name": "Автомат продажу цигарок", "terms": "циграки,торгівля,тютюн,палити,автомат,кіоск" }, + "amenity/vending_machine/coffee": { + "name": "Каво-машина", + "terms": "кава,лате,капучіно,амерікано,напій,гарячий" + }, "amenity/vending_machine/condoms": { "name": "Автомат продажу нацюцюрників", "terms": "перезерватив,кондом,гандон,секс,захист,атомат,торгівля" @@ -3270,6 +3360,14 @@ "name": "Автомат продажу напоїв", "terms": "напої,газована вода,вода,сік,автомат,продаж,кіоск" }, + "amenity/vending_machine/electronics": { + "name": "Автомат продажу електроприладів", + "terms": "кабель,зарядний пристрій,навушники,хендс-фрі,телефон,смартфон,планшет" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Автомат продажу сувенірних монет", + "terms": "монета,сувенір,витягнута,сплюснута,копійка" + }, "amenity/vending_machine/excrement_bags": { "name": "Автомат пакетів для екскрементів", "terms": "лайно,собака,тварина,кішка,пакет" @@ -3278,6 +3376,18 @@ "name": "Автомат з продажу засобів жіночої гігієни", "terms": "презерватив,тампон,прокладка,жінка,жінки,засоби,гігієна,менструація,циклу,догляд,особистий" }, + "amenity/vending_machine/food": { + "name": "Автомат продажу їжі", + "terms": "їжа,сир,молоко,картопля,макарони,ковбаса,сосиски" + }, + "amenity/vending_machine/fuel": { + "name": "Автомат продажу палива", + "terms": "паливо,бензин,газ,пропан,бутан,дизель,скраплений газ,керосин,біодизель" + }, + "amenity/vending_machine/ice_cream": { + "name": "Автомат морозива", + "terms": "морозиво,шоколадне,ванільне,фруктове" + }, "amenity/vending_machine/news_papers": { "name": "Автомат продажу газет" }, @@ -3297,6 +3407,10 @@ "name": "Автомат продажу проїзних квитків", "terms": "автобус,трамвай,тролейбус,паром,електричка,квиток,транспорт,громадський,проїзд" }, + "amenity/vending_machine/stamps": { + "name": "Автомат продажу поштових марок", + "terms": "лист,марка,пошта,відправлення" + }, "amenity/vending_machine/sweets": { "name": "Автомат продажу солодощів", "terms": "цукерки,жувальна гумка,чіпси,печиво,крекери" @@ -3369,6 +3483,10 @@ "name": "Падіння з вежі", "terms": "парк,атракціони,вежа,вільне,падіння,кидок" }, + "attraction/maze": { + "name": "Лабіринт", + "terms": "лабіринт,парк,розваги" + }, "attraction/pirate_ship": { "name": "Піратській корабель", "terms": "парк,розваги,корабель,човен,пірати,велика,гойдалка" @@ -3998,6 +4116,10 @@ "name": "Хоспіс", "terms": "хвороба,хоспіс,невіліковна,допомога" }, + "healthcare/laboratory": { + "name": "Медична лабораторія", + "terms": "лабораторія,аналізи,кров,інсулін,цукор,сеча,кал,тиск,гормони" + }, "healthcare/midwife": { "name": "Акушерка", "terms": "повитуха,пологи,дитина,вагітність" @@ -4100,6 +4222,10 @@ "name": "З’їзд з/на автомагістраль", "terms": "Motorway Link, ppl fdnjvfuscnhfkm, естакада, виїзд з, виїзд на, з’їзд з, з’їзд на" }, + "highway/passing_place": { + "name": "Місце для роз'їзду", + "terms": "дорога,дати шлях,роз'їзд,переваги,рух,зустрічний рух" + }, "highway/path": { "name": "Стежка", "terms": "Path, cntrf, тропа" @@ -4459,6 +4585,10 @@ "name": "Ігрові автомати", "terms": "один-на-один,ігра,автомат,відео,симулятор,пінбол" }, + "leisure/beach_resort": { + "name": "Пляжний курорт", + "terms": "курорт,відпочинок,пляж,вода,дозвілля,розваги,готель,житло" + }, "leisure/bird_hide": { "name": "Пункт спостереження", "terms": "птахи,звіри,природа,тварини" @@ -4475,6 +4605,10 @@ "name": "Зала для танців", "terms": "танці,зала,бальні танці,розваги,дозвілля,клуб,інтереси,тренування" }, + "leisure/dancing_school": { + "name": "Школа танців", + "terms": "школа,клуб,танці,танцювальна,танго,модерн,вальс,ча-ча-ча,латино,сучасні,хіп-хоп" + }, "leisure/dog_park": { "name": "Парк для собак", "terms": "Dog Park, gfhr lkz cjfr, парк для собак" @@ -4571,6 +4705,10 @@ "name": "Заповідник", "terms": "заповідник, заказник, охорона, природа, територія, акваторія, природний парк" }, + "leisure/outdoor_seating": { + "name": "Місця на свіжому повітрі", + "terms": "кафе,шинок,сніданок,обід,вечера,їжа,страви,напої,пиво,вино,горілка,віски,коньяк,алкоголь,ресторан,бар,паб,веренда,майданчик" + }, "leisure/park": { "name": "Парк", "terms": "Park, gfhr, парк" @@ -4699,6 +4837,10 @@ "name": "Штольня", "terms": "entrance,underground,mine, cave,печера,шахта,вхід,вихід,підземелля" }, + "man_made/antenna": { + "name": "Антена", + "terms": "антена,сигнал,зв'язок,мобільний,телефон,телесигнал,передача" + }, "man_made/breakwater": { "name": "Хвилеріз", "terms": "Breakwater, dbkthsp, хвилеріз" @@ -4750,6 +4892,10 @@ "name": "Оглядова вежа", "terms": "Observation tower, jukzljdf dtf, пожежна вежа, вежа спостереження" }, + "man_made/observatory": { + "name": "Обсерваторія", + "terms": "астрономія,метеорологія,спостереження,зірки,погода" + }, "man_made/petroleum_well": { "name": "Нафтова свердловина", "terms": "drilling rig,oil derrick,oil drill,oil horse,oil rig,oil pump,petroleum well,pumpjack,нафта,насос,свердловина,викачування нафти" @@ -4874,10 +5020,18 @@ "name": "Пустир/вереск", "terms": "Heath, gecnbh, степ, верес, пустище" }, + "natural/mud": { + "name": "Багно", + "terms": "багно,багнюка,грязь" + }, "natural/peak": { "name": "Пік", "terms": "Peak, gsr, пагорб, круча, вершина, гора, найвища точка, гребінь, узгір’я" }, + "natural/reef": { + "name": "Риф", + "terms": "риф,корал,бар'єр,окена,пісок,мілина" + }, "natural/ridge": { "name": "Гірський хребет", "terms": "гори,скелі,хребет,перевал,гребінь" @@ -5469,7 +5623,7 @@ "name": "Полустанок (на вимогу)" }, "railway/level_crossing": { - "name": "Залізничний переїзд (автомобілний)", + "name": "Залізничний переїзд (автомобільний)", "terms": "залізниця,потяг,рейки,автомобіль,перехід,шлагбаум,світлофор,поїзд,(автомобільний),дорога,шлях" }, "railway/light_rail": { @@ -5910,6 +6064,10 @@ "name": "Товари для тварин", "terms": "Pet Store,njdfhb lkz ndfhby, зоомагазин" }, + "shop/pet_grooming": { + "name": "Салон догляду за тваринами", + "terms": "собака,кіт,стрижка,підрізка кігтів,купання,мийка" + }, "shop/photo": { "name": "Фототовари", "terms": "Photography Store, ajnjnjdfhb, фотограф" @@ -6129,6 +6287,10 @@ "name": "Тематичний парк", "terms": "Theme Park, ntvfnbxybq gfhr, тематичний парк" }, + "tourism/trail_riding_station": { + "name": "Місце відпочинку для коней та вершників", + "terms": "станція,відпочинок,коні,кінь,вершник,туризм" + }, "tourism/viewpoint": { "name": "Оглядовий майданчик", "terms": "Viewpoint, jukzljddbq vfqlfyxbr, оглядовий майданчик" @@ -6213,16 +6375,20 @@ "terms": "знак, обмеження, розворот, немає, заборона" }, "type/restriction/only_left_turn": { - "name": "Поворот тільки праворуч", - "terms": "знак, обмеження, поворот, праворуч, тільки" + "name": "Тільки ліворуч", + "terms": "поворот,рух,ліворуч,заборона" }, "type/restriction/only_right_turn": { - "name": "Поворот тільки ліворуч", - "terms": "знак, обмеження, ліворуч, поворот, тільки" + "name": "Тільки праворуч", + "terms": "поворот,рух,праворуч,заборона" }, "type/restriction/only_straight_on": { - "name": "Тільки прямо", - "terms": "знак, обмеження, тільки прямо, поворота немає" + "name": "ТІльки прямо", + "terms": "рух,прямо,заборона" + }, + "type/restriction/only_u_turn": { + "name": "Тільки розворот", + "terms": "рух,розворот,заборона" }, "type/route": { "name": "Маршрут", @@ -6385,7 +6551,7 @@ "attribution": { "text": "Умови використання та Відгуки" }, - "description": "Межі та дати знімків. Підписи з'являються з 14 рівня масштабування. ", + "description": "Межі та дати знімків. Підписи з'являються з 13 рівня масштабування. ", "name": "Період знімків DigitalGlobe Premium" }, "DigitalGlobe-Standard": { @@ -6399,7 +6565,7 @@ "attribution": { "text": "Умови використання та Відгуки" }, - "description": "Межі та дати знімків. Підписи з'являються з 14 рівня масштабування. ", + "description": "Межі та дати знімків. Підписи з'являються з 13 рівня масштабування. ", "name": "Період знімків DigitalGlobe Standard" }, "EsriWorldImagery": { @@ -6483,6 +6649,10 @@ "description": "Жовтий = Дані, що розповсюджуються US Census на умовах суспільного надбання. Червоний = Дані, відсутні в OpenStreetMap", "name": "TIGER Roads 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Дороги: Зелений контур = unclassified. Коричневий контур = track. Покриття: gravel = світло-коричневе заповнення, asphalt = чорне, paved = сіре, ground = біле, concrete = синє, grass = зелене. Seasonal = білі смуги", + "name": "U.S. Forest Roads, додатковий шар" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, Учасники OpenStreetMap, CC by-SA 3.0" @@ -6517,7 +6687,7 @@ "attribution": { "text": "basemap.at" }, - "description": "Базова мапа Австрії, на основі урядових даних.", + "description": "Мапа Австрії, на основі урядових даних.", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6579,7 +6749,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Тайли мапи від Stamen Design, CC BY 3.0" + "text": "Тайли мапи від Stamen Design, CC BY 3.0. Дані OpenStreetMap, ODbL." }, "name": "Stamen Terrain" }, @@ -6595,6 +6765,225 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "Університет Кейп-Кост - YouthMappers", + "description": "Приєднуйтесь до нас у Twitter: {url}", + "extendedDescription": "Це офіційний провід відділення Youth Mappers Університету Кейп-Кост, Гана. Ми любимо карти, відкриваємо дані та допомагаємо вразливим." + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Гана у Facebook", + "description": "Група у Facebook для тих, хто цікавиться OpenStreetMap.", + "extendedDescription": "Місцева спільнота маперів Гани, розповсюджуємо інформацію про проекти OpenStreetMap та Humanitarian OpenStreetMap Team (HOT) в Гані. Приєднуйтесь до нас." + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Гана у Twitter", + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "talk-gh": { + "name": "Talk-gh Список розсилки", + "description": "Talk-gh – офіційний список розсилки OSM спільноти Гани." + }, + "osm-mg-facebook": { + "name": "OpenStreetMap Madagascar група у Facebook", + "description": "Малагасійська група у Facebook для тих, хто цікавиться OpenStreetMap." + }, + "talk-mg": { + "name": "Talk-mg Список розсилки", + "description": "Місце, де учасники OpenStreetMap, спільнота та користувачі з Мадагаскару поширюють інформацію та обмінюються думками" + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Бангладеш", + "description": "Покращити OpenStreetMap в Бангладеш" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap Індія - участь в мапінгу поселень", + "description": "Покращити OpenStreetMap в Індії", + "extendedDescription": "Мапите в Індії? Маєте питання чи бажаєте поспілкуватись зі спільнотою тут? Приєднуйтесь до нас - {url}. Ласкаво просимо!", + "events": { + "sotmasia2018": { + "name": "State of the Map Азія 2018", + "description": "Відвідайте регіональну конференцію State of the Map 2018 в Індії", + "where": "Індійський інститут управління, Бангалор, Індія" + } + } + }, + "OSM-india-mailinglist": { + "name": "OpenStreetMap Індія, список розсилки", + "description": "Talk-in – офіційний список розсилки Індійської спільноти" + }, + "OSM-india-twitter": { + "name": "OpenStreetMap Індія Twitter", + "description": "Ми просто в твітемо: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Free Software Hardware Movement - Facebook", + "description": "Відвідайте сторінку FSHM у Facebook, щоб дізнатись про події та заходи", + "extendedDescription": "FSHM організовує події пов'язані з вільним програмним та апаратним забезпечення, технологіями, розповсюдженням інформації про них та OpenStreetMap. На цій сторінці у FB ви завжди знайдете свіжу інформацію про події." + }, + "OSM-India-Puducherry-Matrix": { + "name": "Free Software Hardware Movement - Matrix" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Індонезія", + "description": "Покращити OpenStreetMap в Індонезії", + "extendedDescription": "Мапите в Індонезії? Маєте питання, бажаєте зв'язатись зі спільнотою? Приєднуйтесь до нас за адресою {Url}. Ласкаво просимо!" + }, + "OSM-japan-facebook": { + "name": "Японська спільнота OpenStreetMap", + "description": "Учасники та користувачі OpenStreetMap в Японії" + }, + "OSM-japan-mailinglist": { + "name": "OpenStreetMap Японія, список розсилки", + "description": "Talk-ja – офіційний список розсилки Японської спільноти" + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap Японія Twitter", + "description": "Хеш-теґ у Twitter: {url}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Монголія", + "description": "Покращити OpenStreetMap в Монголії", + "extendedDescription": "Мапите в Монголії? Маєте питання, бажаєте зв'язатись зі спільнотою? Приєднуйтесь до нас за адресою {Url}. Ласкаво просимо!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Непал", + "description": "Покращити OpenStreetMap в Непалі", + "extendedDescription": "Мапите в Непалі? Маєте питання, бажаєте зв'язатись зі спільнотою? Приєднуйтесь до нас за адресою {Url}. Ласкаво просимо!" + }, + "OSM-PH-facebook": { + "name": "OpenStreetMap Філіппіни у Facebook" + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph Список розсилки" + }, + "OSM-LKA-facebook": { + "description": "Покращити OpenStreetMap у Шрі-Ланці", + "extendedDescription": "Мапите у Шрі-Ланці? Маєте питання, бажаєте зв'язатись зі спільнотою? Приєднуйтесь до нас за адресою {Url}. Ласкаво просимо!" + }, + "OSM-TW-mailinglist": { + "name": "OpenStreetMap Тайвань, список розсилки", + "description": "Talk-tw – офіційний список розсилки спільноти для обговорення питань пов'язаних з Тайванем" + }, + "at-mailinglist": { + "name": "Talk-at Список розсилки", + "description": "Talk-at – офіційний список розсилки OSM спільноти Австрії." + }, + "be-mailinglist": { + "name": "Talk-be Список розсилки" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz Список розсилки", + "description": "Talk-cz – офіційний список розсилки OSM спільноти Чехії." + }, + "fr-mailinglist": { + "name": "Talk-fr Список розсилки", + "description": "Talk-fr Список розсилки" + }, + "de-berlin-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "de-mailinglist": { + "name": "Talk-de Список розсилки", + "description": "Talk-de – офіційний список розсилки OSM спільноти Німеччини." + }, + "it-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "OSM-Rome-meetup": { + "description": "Покращити OpenStreetMap навкруги Риму" + }, + "talk-it-lazio": { + "extendedDescription": "Список розсилки спільноти Риму та Лаціо" + }, + "OSM-ES-mailinglist": { + "name": "Talk-es Список розсилки" + }, + "se-mailinglist": { + "name": "Talk-se Список розсилки" + }, + "se-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "Bay-Area-OpenStreetMappers": { + "description": "Покращити OpenStreetMap в районі Затоки Сан-Франциско" + }, + "Mapping-DC-meetup": { + "description": "Покращити OpenStreetMap навколо Вашингтона, округ Колумбія", + "extendedDescription": "Ми є групою маперів-волонтерів, які прагнуть вдосконалити OpenStreetMap в окрузі Колумбія. Ми також намагаємось поширити інформацію про екосистему OSM, аналізі даних, картографію та ГІС серед зацікавлених осіб. Ми збираємося щомісяця на зустрічах, щоб покращити якусь частину нашого міста." + }, + "OpenCleveland-meetup": { + "description": "Покращити OpenStreetMap навколо Клівленда" + }, + "OSM-US": { + "description": "Ми допомагаємо розвивати та вдосконалювати OpenStreetMap у Сполучених Штатах." + }, + "PHXGeo-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "talk-au": { + "name": "Talk-au Список розсилки" + }, + "OSM-AR-mailinglist": { + "name": "Talk-ar Список розсилки" + }, + "OSM-AR-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "OSM-br-mailinglist": { + "name": "Talk-br Список розсилки" + }, + "OSM-br-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "OSM-CL-mailinglist": { + "name": "Talk-cl Список розсилки" + }, + "OSM-CL-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "OSM-CO-mailinglist": { + "name": "Talk-co Список розсилки" + }, + "OSM-CO-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "OSM-PE-mailinglist": { + "name": "Talk-pe Список розсилки" + }, + "OSM-PE-twitter": { + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "OSM-Facebook": { + "name": "OpenStreetMap у Facebook", + "description": "Вподобайте нашу сторінку на Facebook, щоб отримувати новини про OpenStreetMap." + }, + "OSM-help": { + "name": "OpenStreetMap Help", + "description": "Поставте питання та отримайте відповіді на веб-сайті із запитаннями і відповідями що підтримується спільнотою OSM.", + "extendedDescription": "{url} для всіх, хто потребує допомоги в OpenStreetMap. Неважливо, або ви новачок в мапінгу або вам потрібна відповідь на суто технічне питання, ми тут, щоб допомогти вам!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap на Reddit", + "description": "/r/openstreetmap/ чудове місце, щоб дізнатись більше про OpenStreetMap. Можете питати про будь-що!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter", + "description": "Приєднуйтесь до нас у Twitter: {url}" + }, + "OSMF": { + "name": "Фундація OpenStreetMap", + "description": "OSMF, зареєстрована у Великий Британії, неприбуткова організація, що опікується проектом OpenStreetMap", + "extendedDescription": "OSMF підтримує OpenStreetMap організовуючи збір коштів, опікуючись роботою серверів, на яких розташовано OSM, організовуючи щорічні конференції State of the Map, координуючи зусилля волонтерів, що допомагають роботі OSM. Ви можете також показати свою підтримку та мати вплив на подальший розвиток проекту, ставши членом OSMF: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Приєднайтесь до нас в Мілані, Італія на 3 дні на щорічній всесвітній конференції OpenStreetMap, на якій збираються представники спільноти для спілкування, обміну досвідом та навчання.", + "where": "Мілан, Італія" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/vi.json b/vendor/assets/iD/iD/locales/vi.json index 80f81b39e..7da36110e 100644 --- a/vendor/assets/iD/iD/locales/vi.json +++ b/vendor/assets/iD/iD/locales/vi.json @@ -1,5 +1,10 @@ { "vi": { + "icons": { + "information": "thông tin", + "remove": "xóa", + "undo": "hoàn tác" + }, "modes": { "add_area": { "title": "Vùng", @@ -145,7 +150,9 @@ "vertex": "nối liền đường kẻ với đường khác", "line": "nối liền lối với đường kẻ", "area": "nối liền đường kẻ với vùng" - } + }, + "relation": "Không thể nối liền các đối tượng này vì có vai trò quan hệ xung đột.", + "restriction": "Không thể nối liền các đối tượng này vì sẽ làm hÆ° một quan hệ “{relation}”." }, "disconnect": { "title": "Tháo gỡ", @@ -163,7 +170,8 @@ "annotation": "gộp {n} đối tượng", "not_eligible": "Không thể gộp các đối tượng này.", "not_adjacent": "Không thể gộp các đối tượng này vì chúng không nối liền với nhau.", - "restriction": "Không thể gộp các đối tượng này vì ít nhất một trong những đối tượng trá»±c thuộc quan hệ “{relation}”.", + "restriction": "Không thể gộp các đối tượng này vì sẽ làm hÆ° một quan hệ “{relation}”.", + "relation": "Không thể gộp các đối tượng này vì có vai trò quan hệ xung đột.", "incomplete_relation": "Không thể gộp vì một trong số đối tượng này chÆ°a được tải về hoàn toàn.", "conflicting_tags": "Không thể gộp các đối tượng này vì một số thẻ có giá trị xung đột." }, @@ -402,6 +410,7 @@ "key": "L", "title": "Lịch sá»­", "selected": "{n} được chọn", + "no_history": "Không có Lịch sá»­ (Đối tượng Mới Tạo)", "version": "Phiên bản", "last_edit": "Sá»­a đổi Cuối cùng", "edited_by": "Người Sá»­a đổi", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "Bạn đã sá»­a đổi OSM!", "just_edited": "Bạn vừa sá»­a đổi OpenStreetMap!", - "view_on_osm": "Xem tại OSM", - "facebook": "Chia sẻ trên Facebook", - "twitter": "Chia sẻ trên Twitter", - "google": "Chia sẻ trên Google+", - "help_html": "Các thay đổi của bạn sẽ xuất hiện trên lớp “Chuẩn” trong vòng vài phút. Một số lớp và tính năng khác có thể được cập nhật chậm hÆ¡n.", + "thank_you": "Cảm Æ¡n bạn đã cải thiện bản đồ!", + "thank_you_location": "Cảm Æ¡n bạn đã cải thiện bản đồ {where}.", + "help_html": "Các thay đổi của bạn sẽ xuất hiện tại OpenStreetMap trong vòng vài phút. Các bản đồ tại trang khác có thể được cập nhật chậm hÆ¡n.", "help_link_text": "Chi tiết", - "help_link_url": "https://wiki.openstreetmap.org/wiki/Vi:FAQ?setlang=vi#T.C3.B4i_v.E1.BB.ABa_thay_.C4.91.E1.BB.95i_b.E1.BA.A3n_.C4.91.E1.BB.93._L.C3.A0m_sao_xem_.C4.91.C6.B0.E1.BB.A3c_c.C3.A1c_thay_.C4.91.E1.BB.95i_c.E1.BB.A7a_t.C3.B4i.3F" + "help_link_url": "https://wiki.openstreetmap.org/wiki/Vi:FAQ?setlang=vi#T.C3.B4i_v.E1.BB.ABa_thay_.C4.91.E1.BB.95i_b.E1.BA.A3n_.C4.91.E1.BB.93._L.C3.A0m_sao_xem_.C4.91.C6.B0.E1.BB.A3c_c.C3.A1c_thay_.C4.91.E1.BB.95i_c.E1.BB.A7a_t.C3.B4i.3F", + "view_on_osm": "Xem các Thay đổi tại OSM", + "changeset_id": "Số bộ thay đổi của bạn: {changeset_id}", + "like_osm": "Bạn có ham mê OpenStreetMap chÆ°a? Hãy liên hệ với cộng đồng:", + "more": "Thêm nữa", + "events": "Sá»± kiện", + "languages": "Ngôn ngữ: {languages}", + "missing": "Danh sách này thiếu gì không?", + "tell_us": "Báo cho chúng tôi biết!" }, "confirm": { "okay": "OK", @@ -1774,6 +1788,9 @@ "display": { "label": "Kiểu Hiển thị" }, + "distance": { + "label": "Tầm xa Tổng cộng" + }, "dock": { "label": "Loại" }, @@ -1814,6 +1831,9 @@ "except": { "label": "Ngoại lệ" }, + "faces": { + "label": "Số Mặt" + }, "fax": { "label": "Số Fax", "placeholder": "+84 1 234 5678" @@ -1925,6 +1945,39 @@ "label": "Số Vòng", "placeholder": "1, 2, 4…" }, + "horse_dressage": { + "label": "Cưỡi ngá»±a Biểu diễn", + "options": { + "equestrian": "Có", + "undefined": "Không" + } + }, + "horse_riding": { + "label": "Cưỡi ngá»±a", + "options": { + "horse_riding": "Có", + "undefined": "Không" + } + }, + "horse_scale": { + "label": "Trình độ Cưỡi ngá»±a", + "options": { + "common": "Dễ: Không có trở ngại. (mặc định)", + "critical": "Rất Khó: Chỉ có những ngá»±a và người cưỡi ngá»±a có nhiều khả năng có thể qua lại. Có trở ngại lớn. Cần phải xem xét kỹ càng các cầu.", + "dangerous": "Nguy hiểm: Chỉ có những ngá»±a và người cưỡi ngá»±a có rất nhiều khả năng có thể qua lại được khi trời đẹp. Nên xuống ngá»±a.", + "demanding": "Xấu: Lối gồ ghề, đôi khi có quãng khó đi qua.", + "difficult": "Khó: Lối hẹp có thể có trở ngại làm dễ bị té.", + "impossible": "Hiểm nghèo: Ngá»±a không qua được lối hoặc cầu quá hẹp, thiếu cột chống, có trở ngại nhÆ° thang." + }, + "placeholder": "Khó, Nguy hiểm…" + }, + "horse_stables": { + "label": "Chuồng Ngá»±a", + "options": { + "stables": "Có", + "undefined": "Không" + } + }, "iata": { "label": "IATA" }, @@ -1944,6 +1997,9 @@ "indoor": { "label": "Trong Nhà" }, + "industrial": { + "label": "Kiểu" + }, "information": { "label": "Kiểu" }, @@ -2064,6 +2120,10 @@ "label": "Tốc độ Tối đa", "placeholder": "40, 50, 60…" }, + "maxspeed/advisory": { + "label": "Tốc độ Tối đa Khuyến cáo", + "placeholder": "40, 50, 60…" + }, "maxstay": { "label": "Thời gian Ở Tối đa" }, @@ -2188,7 +2248,7 @@ "label": "CÆ¡ quan Chủ quản" }, "outdoor_seating": { - "label": "Ngồi ở Ngoài" + "label": "Ngồi Ngoài trời" }, "par": { "label": "Điểm chuẩn", @@ -2217,7 +2277,6 @@ "placeholder": "1, 2, 3…" }, "phone": { - "label": "Số Điện thoại", "placeholder": "+84 1 234 5678" }, "piste/difficulty": { @@ -2652,6 +2711,17 @@ "label": "Kiểu", "placeholder": "Bình thường" }, + "usage_rail": { + "label": "Kiểu Sá»­ dụng", + "options": { + "branch": "Nhánh", + "industrial": "Công nghiệp", + "main": "Chính", + "military": "Quân sá»±", + "test": "Thá»­ nghiệm", + "tourism": "Du lịch" + } + }, "vending": { "label": "Loại Hàng hóa" }, @@ -2748,6 +2818,10 @@ "name": "Bảng Quảng cáo", "terms": "bảng quảng cáo, biển quảng cáo, panô quảng cáo, pano quảng cáo, pa-nô quảng cáo, pa nô quảng cáo, bang quang cao, bien quang cao, pano quang cao, pa-no quang cao, pa no quang cao" }, + "advertising/column": { + "name": "Cột Quảng cáo", + "terms": "cột quảng cáo, cột morris, cột áp phích, cot quang cao, cot morris, cot ap phich" + }, "aerialway": { "name": "Cáp treo" }, @@ -2833,6 +2907,10 @@ "name": "Ga Sân bay", "terms": "ga sân bay, ga phi trường, nhà ga sân bay, nhà ga phi trường, ga san bay, ga phi truong, nha ga san bay, nha ga phi truong" }, + "allotments/plot": { + "name": "Mảnh Vườn Gia đình", + "terms": "mảnh vườn gia đình, miếng vườn gia đình, mảnh đất trong khu vườn gia đình, miếng đất trong khu vườn gia đình, manh vuon dia dinh, mieng vuon gia dinh, manh dat trong khu vuon gia dinh, mieng dat trong khu vuon gia dinh" + }, "amenity": { "name": "Tiện nghi" }, @@ -3061,6 +3139,10 @@ "name": "Chợ phiên", "terms": "chợ phiên, chợ trời, chợ xổm, chợ, cho phien, cho troi, cho xom, cho" }, + "amenity/monastery": { + "name": "Sân Tu viện", + "terms": "sân tu viện, san tu vien" + }, "amenity/motorcycle_parking": { "name": "Chỗ Đậu Xe máy", "terms": "chỗ đậu xe máy, đậu xe máy, chỗ đậu mô-tô, chỗ đậu mô tô, đậu mô-tô, chỗ đậu mô tô, chỗ đậu xe hai bánh, đậu xe hai bánh, chỗ đậu xe ba bánh, đậu xe ba bánh, cho dau xe may, dau xe may, cho dau mo-to, cho dau mo to, dau mo-to, dau mo to, cho dau xe hai banh, dau xe hai banh, cho dau xe ba banh, dau xe ba banh" @@ -3265,6 +3347,10 @@ "name": "Máy Bán Thuốc lá", "terms": "máy bán thuốc lá, may ban thuoc la" }, + "amenity/vending_machine/coffee": { + "name": "Máy Bán Cà phê", + "terms": "máy bán cà phê, máy bán cà-phê, may ban ca phe, may ban ca-phe" + }, "amenity/vending_machine/condoms": { "name": "Máy Bán Bao Cao su", "terms": "máy bán bao cao su, máy phát bao cao su, máy bán bao dÆ°Æ¡ng vật, máy phát bao dÆ°Æ¡ng vật, máy bán túi cao su, máy phát túi cao su, máy bán ca pốt, máy phát ca pốt, máy bán ca-pốt, máy phát ca-pốt, may ban bao cao su, may phat bao cao su, may ban bao duong vat, may phat bao duong vat, may ban tui cao su, may phat tui cao su, may ban ca pot, may phat ca pot, may ban ca-pot, may phat ca-pot" @@ -3273,6 +3359,14 @@ "name": "Máy Bán Nước uống", "terms": "máy bán nước uống, may ban nuoc uong" }, + "amenity/vending_machine/electronics": { + "name": "Máy Bán Thiết bị Điện tá»­", + "terms": "máy bán thiết bị điện tá»­, máy bán điện tá»­, điện thoại, điện thoại di động, cáp, bộ sạc điện, bộ nạp điện, máy sạc điện, máy nạp điện, tai nghe, máy tính bảng, may ban thiet bi dien tu, may ban dien tu, dien thoai, dien thoai di dong, cap, bo sac dien, bo nap dien, may sac dien, may nap dien, tai nghe, may tinh bang" + }, + "amenity/vending_machine/elongated_coin": { + "name": "Máy In dấu vào Tiền", + "terms": "máy in dấu vào tiền, máy đóng dấu vào tiền, máy in tiền, xu, đồng xu, tiền ká»· niệm, tiền kỉ niệm, may in dau vao tien, may dong dau vao tien, may in tien, xu, dong xu, tien ky niem, tien ki niem" + }, "amenity/vending_machine/excrement_bags": { "name": "Máy Phát Bao Cứt Chó", "terms": "máy phát bao cứt chó, may phat bao cut cho" @@ -3281,6 +3375,18 @@ "name": "Máy Bán Sản phẩm Vệ sinh Nữ giới", "terms": "máy bán sản phẩm vệ sinh nữ giới, máy bán sản phẩm vệ sinh phụ nữ, máy bán băng vệ sinh, máy bán băng vệ sinh dạng ống, may ban san pham ve sinh nu gioi, may ban san pham ve sinh phu nu, may ban bang ve sinh, may ban ban ve sinh dang ong" }, + "amenity/vending_machine/food": { + "name": "Máy Bán Đồ ăn", + "terms": "máy bán đồ ăn, máy bán thức ăn, máy bán đồ ăn nhanh, máy bán đồ ăn tá»± động, khoai tây chiên, bánh quy, bánh ngọt, kẹo, nước ngọt, nước giải khát, nước ngọt có ga, cô ca cô la, cô-ca cô-la, cô-ca-cô-la, côcacôla, kẹo nhai, kẹo cao su, gum, kẹo gum, kẹo sinh-gum, kẹo sinh gum, sinh-gum, sinh gum, may ban do an, may ban thuc an, may ban do an nhanh, may ban do an tu dong, khoai tay chian, banh quy, banh ngot, keo, nuoc ngot, nuoc giai khat, nuoc ngot co ga, co ca co la, co-ca co-la, co-ca-co-la, cocacola, keo nhai, keo cao su, keo gum, keo sinh-gum, keo sinh gum" + }, + "amenity/vending_machine/fuel": { + "name": "Trụ BÆ¡m Xăng", + "terms": "trụ bÆ¡m xăng, trụ bÆ¡m xăng dầu, cây xăng, cột xăng, xăng ét xăng, ét-xăng, nhiên liệu, diesel, gazole, khí hóa lỏng, khí hoá lỏng, khí thiên nhiên lỏng, khí ga lỏng, khí gas lỏng, tru bom xang, tru bom xang dau, cay xang, cot xang, xang et xang, et-xang, nhien lieu, khi hoa long, khi thien nhien long, khi ga long, khi gas long" + }, + "amenity/vending_machine/ice_cream": { + "name": "Máy Bán Kem", + "terms": "máy bán kem, máy bán kem tá»± động, máy bán cà rem, máy bán cà-rem, kem que, may ban kem, may ban kem tu dong, may ban ca rem, may ban ca-rem" + }, "amenity/vending_machine/news_papers": { "name": "Máy Bán Báo" }, @@ -3300,6 +3406,10 @@ "name": "Máy Bán Vé PhÆ°Æ¡ng tiện Công cộng", "terms": "máy bán vé, máy bán vé phÆ°Æ¡ng tiện công cộng, máy bán vé xe buýt, máy bán vé xe điện, máy bán vé xe lá»­a, may ban ve, may ban ve phuong tien cong cong, may ban ve xe buyt, may ban ve xe dien, may ban ve xe lua" }, + "amenity/vending_machine/stamps": { + "name": "Máy Bán Tem", + "terms": "máy bán tem, máy ban tem tá»± động, tem thÆ°, tem bÆ°u chính, may ban tem, may ban tem tu dong, tem thu, tem buu chinh" + }, "amenity/vending_machine/sweets": { "name": "Máy Bán Kẹo", "terms": "máy bán kẹo, may ban keo" @@ -3372,6 +3482,10 @@ "name": "Tháp RÆ¡i Tá»± do", "terms": "tháp rÆ¡i tá»± do, thap roi tu do" }, + "attraction/maze": { + "name": "Mê cung", + "terms": "mê cung, cung mê, mê lộ, mê đạo, me cung, cung me, me lo, me dao" + }, "attraction/pirate_ship": { "name": "Thuyền Cướp biển", "terms": "thuyền cướp biển, thuyen cuop bien" @@ -4001,6 +4115,10 @@ "name": "Nhà An dưỡng Cuối đời", "terms": "nhà an dưỡng cuối đời, nha an duong cuoi doi" }, + "healthcare/laboratory": { + "name": "Phòng Thí nghiệm Y tế", + "terms": "phòng thí nghiệm y tế, phòng thá»­ nghiệm y tế, phòng xét nghiệm y tế, phòng thí nghiệm lâm sàng, phòng thá»­ nghiệm lâm sàng, phòng xét nghiệm lâm sàng, phòng thá»­ máu, phong thi nghiem y te, phong thu nghiem y te, phong xet nghiem y te, phong thi nghiem lam sang, phong thu nghiem lam sang, phong xet nghiem lam sang, phong thu mau" + }, "healthcare/midwife": { "name": "Bà đỡ", "terms": "bà đỡ, bà đỡ đẻ, ba do, ba do de" @@ -4103,6 +4221,10 @@ "name": "Nhánh Ra vào Đường Cao tốc", "terms": "đường nhánh cao tốc, đoạn nhánh cao tốc, đường nhánh rẽ cao tốc, đoạn nhánh rẽ cao tốc, đường nhánh chuyển đường cao tốc, nhánh chuyển đường cao tốc, lối ra vào đường cao tốc, lối ra đường cao tốc, lối vào đường cao tốc, nhánh ra đường cao tốc, nhánh vào đường cao tốc, đường nối đường cao tốc, duong nhanh cao toc, doan nhanh cao toc, duong nhanh re cao toc, doan nhanh re cao toc, duong nhanh chuyen duong cao toc, nhanh chuyen duong cao toc, loi ra vao duong cao toc, loi ra duong cao toc, loi vao duong cao toc, nhanh ra duong cao toc, nhanh vao duong cao toc, duong noi duong cao toc" }, + "highway/passing_place": { + "name": "Chỗ Tránh Xe", + "terms": "chỗ tránh xe, vị trí tránh xe, nÆ¡i tránh xe, cho tranh xe, vi tri tranh xe, noi tranh xe" + }, "highway/path": { "name": "Lối", "terms": "đường mòn, duong mon" @@ -4132,8 +4254,8 @@ "terms": "ngõ dân cÆ°, ngõ dân sinh, ngõ, đường dân cÆ°, dân cÆ°, đường dân sinh, dân sinh, kiệt, ngo dan cu, ngo dan sinh, ngo, duong dan cu, dan cu, duong dan sinh, dan sinh, kiet" }, "highway/rest_area": { - "name": "Khu Vệ sinh và NÆ¡i Nghỉ ngÆ¡i", - "terms": "khu vệ sinh, phòng vệ sinh, nÆ¡i nghỉ ngÆ¡i, chỗ nghỉ ngÆ¡i, trạm thông tin, khu ve sinh, phong ve sinh, noi nghi ngoi, cho nghi ngoi, tram thong tin" + "name": "Trạm Dừng Nghỉ", + "terms": "trạm dừng nghỉ, khu vệ sinh, phòng vệ sinh, nÆ¡i nghỉ ngÆ¡i, chỗ nghỉ ngÆ¡i, trạm thông tin, tram dung nghi, khu ve sinh, phong ve sinh, noi nghi ngoi, cho nghi ngoi, tram thong tin" }, "highway/road": { "name": "Đường Nói chung", @@ -4462,6 +4584,10 @@ "name": "Khu Trò chÆ¡i Điện tá»­", "terms": "khu trò chÆ¡i điện tá»­, trung tâm trò chÆ¡i điện tá»­, trò chÆ¡i cảm giác mạnh, trò chÆ¡i video, trò chÆ¡i bắn bóng, pinball, trò chÆ¡i lái xe ảo, khu tro choi dien tu, trung tam tro choi dien tu, tro choi cam giac manh, tro choi video, tro choi ban bong, tro choi lai xe ao" }, + "leisure/beach_resort": { + "name": "Bãi biển Nghỉ dưỡng", + "terms": "bãi biển nghỉ dưỡng, bãi biển nghỉ ngÆ¡i, bãi biển nghỉ hè, bai bien nghi duong, bai bien nghi ngoi, bai bien nghi he" + }, "leisure/bird_hide": { "name": "Căn nhà Quan sát Chim", "terms": "căn nhà quan sát chim, căn nhà quan sát động vật, can nha quan sat chim, can nha quan sat dong vat" @@ -4578,6 +4704,10 @@ "name": "Khu Bảo tồn Thiên nhiên", "terms": "khu bảo tồn thiên nhiên, khu vá»±c bảo tồn thiên nhiên, khu cấm săn bắn, khu vá»±c cấm săn bắn, khu cấm câu cá, khu vá»±c cấm câu cá, khu bao ton thien nhien, khu vuc bao ton thien nhien, khu cam san ban, khu vuc cam san ban, khu cam cau ca, khu vuc cam cau ca" }, + "leisure/outdoor_seating": { + "name": "Khu Ăn uống Ngoài trời", + "terms": "khu ăn uống ngoài trời, điểm ăn uống ngoài trời, không gian ngoài trời, không gian giữa trời, bàn ăn ngoài trời, quán rượu ngoài trời, quán bia ngoài trời" + }, "leisure/park": { "name": "Công viên", "terms": "công viên, vườn, vườn hoa, vườn cây, bãi cỏ, bãi cỏ xanh, thảm cỏ xanh, vành đai xanh, khu vui chÆ¡i, khu vui chÆ¡i trẻ em, khu chÆ¡i trẻ em, sân chÆ¡i, quảng trường, rừng, cong vien, vuon, vuon hoa, vuon cay, bai co, bai co xanh, tham co xanh, vanh dai xanh, khu vui choi, khu vui choi tre em, khu choi tre em, san choi, quang truong, rung" @@ -4706,6 +4836,10 @@ "name": "Lối vào Mỏ", "terms": "lối vào mỏ, đường vào mỏ, loi vao mo, duong vao mo" }, + "man_made/antenna": { + "name": "Ăngten", + "terms": "ăngten, ăng-ten, ăng ten, anten, an-ten, radio, rađiô, ra-đi-ô, vô tuyến, anten radio, anten rađiô, an-ten ra-đi-ô, tv, tivi, anten tv, anten tivi, angten, ang-ten, ang ten, anten, an-ten, ra-di-o, vo tuyen, anten ra-di-o" + }, "man_made/breakwater": { "name": "Đê Chắn Sóng", "terms": "đê chắn sóng, de chan song" @@ -4747,7 +4881,7 @@ }, "man_made/mast": { "name": "Cột Ăngten", - "terms": "cột ăngten, cột ăng-ten, cột ăng ten, cột anten, cột an-ten, cột radio, cột rađiô, cột ra-đi-ô, cột vô tuyến, tháp radio, tháp rađiô, tháp ra-đi-ô, tháp vô tuyến, anten radio, anten rađiô, an-ten ra-đi-ô, cột tv, cột tivi, tháp tv, tháp tivi, anten tv, anten tivi, cot angten, cot ang-ten, cot ang ten, cot anten, cot an-ten, cot radio, cot ra-di-o, cot vo tuyen, thap radio, thap ra-di-o, thap vo tuyen, anten radio, anten ra-di-o, cot tv, cot vivi, thap tv, thap tivi, anten tv, anten tivi" + "terms": "cột ăngten, cột ăng-ten, cột ăng ten, cột anten, cột an-ten, cột radio, cột rađiô, cột ra-đi-ô, cột vô tuyến, tháp radio, tháp rađiô, tháp ra-đi-ô, tháp vô tuyến, anten radio, anten rađiô, an-ten ra-đi-ô, cột tv, cột tivi, tháp tv, tháp tivi, anten tv, anten tivi, cot angten, cot ang-ten, cot ang ten, cot anten, cot an-ten, cot radio, cot ra-di-o, cot vo tuyen, thap radio, thap ra-di-o, thap vo tuyen, anten radio, anten ra-di-o, cot tv, cot tivi, thap tv, thap tivi, anten tv, anten tivi" }, "man_made/monitoring_station": { "name": "Trạm Giám sát", @@ -4757,6 +4891,10 @@ "name": "Tháp Quan sát", "terms": "tháp quan sát, trạm quan sát, tầng quan sát, thap quan sat, tram quan sat, tang quan sat" }, + "man_made/observatory": { + "name": "Đài Quan sát", + "terms": "đài quan sát, đài thiên văn, đài quan sát thiên văn, kính thiên văn, kiếng thiên văn, đài quan sát khí tượng, đài quan sát núi lá»­a, dai quan sat, dai thien van, dai quan sat thien van, kinh thien van, kieng thien van, dai quan sat khi tuong, dai quan sat nui lua" + }, "man_made/petroleum_well": { "name": "Giếng Dầu", "terms": "giếng dầu, gieng dau" @@ -4881,10 +5019,18 @@ "name": "Bãi hoang", "terms": "bãi hoang, bai hoang" }, + "natural/mud": { + "name": "Bùn", + "terms": "bùn, bùn lầy, bun, bun lay" + }, "natural/peak": { "name": "Đỉnh núi", "terms": "đồi, núi, đỉnh núi, đỉnh, chỏm núi, chỏm, chóp núi, chóp, chỏm chóp, doi, nui, dinh nui, dinh, chom nui, chom, chop nui, chop, chom chop" }, + "natural/reef": { + "name": "Đá ngầm", + "terms": "đá ngầm, rạn san hô, ám tiêu san hô, cồn cát, đê cát, bãi cạn, cụm bãi cạn, bãi nông, bãi cát, da ngam, ran san ho, am tieu san ho, con cat, de cat, bai can, cum bai can, bai nong, bai cat" + }, "natural/ridge": { "name": "Dãy đồi", "terms": "dãy đồi, dãy núi, dãy gò, day doi, day noi, day go" @@ -5917,6 +6063,10 @@ "name": "Tiệm Vật nuôi", "terms": "tiệm bán vật nuôi, tiệm bán đồ nuôi thú vật, cá»­a hàng vật nuôi, cá»­a hiệu thú vật, đồ ăn thú vật, chó, mèo, tiem ban vat nuoi, tiem ban do nuoi thu vat, cua hang vat nuoi, cua hieu thu vat, do an thu vat, cho, meo" }, + "shop/pet_grooming": { + "name": "Dịch vụ Tỉa lông", + "terms": "dịch vụ tỉa lông, tỉa lông thú cÆ°ng, tỉa lông chó, tỉa lông mèo, tỉa lông ngá»±a, dich vu tia long, tia long thu cung, tia long cho, tia long meo, tia long ngua" + }, "shop/photo": { "name": "Tiệm Chụp Hình", "terms": "tiệm chụp hình, tiệm lấy hình, tiệm lấy ảnh, tiệm nhiếp ảnh, cá»­a hàng chụp hình, cá»­a hàng lấy hình, cá»­a hàng lấy ảnh, cá»­a hàng nhiếp ảnh, tiem chup hinh, tiem lay hinh, tiem lay anh, tiem nhiep anh, cua hang chup hinh, cua hang lay hinh, cua hang lay anh, cua hang nhiep anh" @@ -6136,6 +6286,10 @@ "name": "Công viên Chủ đề", "terms": "công viên chủ đề, công viên vui chÆ¡i giả trí, tàu lượn siêu tốc, vòi nước, cong vien chu de, cong vien vui choi gia tri, tau luon sieu toc, voi nuoc" }, + "tourism/trail_riding_station": { + "name": "Chuồng Ngá»±a Tạm thời", + "terms": "chuồng ngá»±a tạm thời, chuong ngua tam thoi" + }, "tourism/viewpoint": { "name": "Điểm Ngắm cảnh", "terms": "điểm ngắm cảnh, nÆ¡i ngắm cảnh, kính viễn vọng, kiếng viễn vọng, kính nhìn từ xa, kiếng nhìn từ xa, thắng cảnh, diem ngam canh, noi ngam canh, kinh vien vong, kieng vien vong, kinh nhin tu xa, kieng nhin tu xa, thang canh" @@ -6220,16 +6374,20 @@ "terms": "cấm quay ngược trở lại, không quay ngược trở lại, đừng quay ngược trở lại, cam quay nguoc tro lai, khong quay nguoc tro lai, dung quay nguoc tro lai, cam quay nguoc tro lai" }, "type/restriction/only_left_turn": { - "name": "Chỉ Rẽ Trái", - "terms": "chỉ rẽ trái, chỉ cho phép rẽ trái, chỉ quẹo trái, chỉ cho phép quẹo trái, chỉ ngoặt trái, chỉ cho phép ngoặt trái, chỉ ngoắt trái, chỉ cho phép ngoắt trái, chỉ quặt trái, chỉ cho phép quặt trái, chi re trai, chi cho phep re trai, chi queo trai, chi cho phep queo trai, chi ngoat trai, chi cho phep ngoat trai, chi ngoat trai, chi cho phep ngoat trai, chi quat trai, chi cho phep quat trai" + "name": "Chỉ Rẽ trái", + "terms": "chỉ quẹo trái, chỉ cho phép quẹo trái, chỉ rẽ trái, chỉ cho phép rẽ trái, chi queo trai, chi cho phep queo trai, chi re trai, chi cho phep re trai" }, "type/restriction/only_right_turn": { "name": "Chỉ Rẽ Phải", - "terms": "chỉ rẽ phải, chỉ cho phép rẽ phải, chỉ quẹo phải, chỉ cho phép quẹo phải, chỉ ngoặt phải, chỉ cho phép ngoặt phải, chỉ ngoắt phải, chỉ cho phép ngoắt phải, chỉ quặt phải, chỉ cho phép quặt phải, chi re phai, chi cho phep re phai, chi queo phai, chi cho phep queo phai, chi ngoat phai, chi cho phep ngoat phai, chi ngoat phai, chi cho phep ngoat phai, chi quat phai, chi cho phep quat phai" + "terms": "chỉ quẹo phải, chỉ cho phép quẹo phải, chỉ rẽ phải, chỉ cho phép rẽ phải, chi queo phai, chi cho phep queo phai, chi re phai, chi cho phep re phai" }, "type/restriction/only_straight_on": { - "name": "Cấm Rẽ Trái/Phải", - "terms": "cấm rẽ trái phải, không rẽ trái phải, đừng rẽ trái phải, cấm quẹo trái phải, không quẹo trái phải, đừng quẹo trái phải, chỉ chạy thẳng, chỉ cho phép chạy thẳng, cam re trai phai, khong re trai phai, dung re trai phai, cam queo trai phai, khong queo trai phai, dung queo trai phai, chi chay thang, chi cho phep chay thang" + "name": "Chỉ Chạy Thẳng", + "terms": "chỉ chạy thẳng, chỉ đi thẳng, chỉ cho phép chạy thẳng, chỉ cho phép đi thẳng, cấm quẹo, cấm rẽ, không quẹo, không rẽ, đừng quẹo, đừng rẽ, chi chay thang, chi di thang, chi cho phep chay thang, chi cho phep di thang, cam queo, cam re, khong queo, khong re, dung queo, dung re" + }, + "type/restriction/only_u_turn": { + "name": "Chỉ Quay Ngược", + "terms": "chỉ quay ngược, chỉ quay vòng lại, chỉ vòng ngược lại, chỉ cho phép quay ngược, chỉ cho phép quay vòng lại, chỉ cho phép vòng ngược lại, chi quay nguoc, chi quay vong lai, chi vong nguoc lai, chi cho phep quay nguoc, chi cho phep quay vong lai, chi cho phep vong nguoc lai" }, "type/route": { "name": "Tuyến đường", @@ -6392,7 +6550,7 @@ "attribution": { "text": "Điều khoản & Phản hồi" }, - "description": "Biên giới và ngày tháng chụp. Các nhãn xuất hiện tại mức thu phóng 14 trở lên.", + "description": "Biên giới và ngày tháng chụp. Các nhãn xuất hiện tại mức thu phóng 13 trở lên.", "name": "Lúc chụp DigitalGlobe Thượng hạng" }, "DigitalGlobe-Standard": { @@ -6406,7 +6564,7 @@ "attribution": { "text": "Điều khoản & Phản hồi" }, - "description": "Biên giới và ngày tháng chụp. Các nhãn xuất hiện tại mức thu phóng 14 trở lên.", + "description": "Biên giới và ngày tháng chụp. Các nhãn xuất hiện tại mức thu phóng 13 trở lên.", "name": "Lúc chụp DigitalGlobe Tiêu chuẩn" }, "EsriWorldImagery": { @@ -6490,6 +6648,10 @@ "description": "Màu vàng là dữ liệu bản đồ thuộc phạm vi công cộng do Điều tra dân số Hoa Kỳ cung cấp. Màu đỏ là dữ liệu chÆ°a xuất hiện trong OpenStreetMap.", "name": "Đường sá TIGER 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "Đường sá: vỏ xanh là ngõ; vỏ nâu là đường mòn.\nMặt đường: sỏi đá được tô màu nâu nhạt; nhá»±a là màu đen, mặt lát là màu xám; đất là màu trắng; bê tông là màu xanh lam; cỏ là màu xanh lá cây.\nTùy mùa có vạch màu trắng.", + "name": "Lớp phủ Đường Lâm nghiệp Hoa Kỳ" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, những người đóng góp vào OpenStreetMap, CC BY-SA 3.0" @@ -6586,7 +6748,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Hình bản đồ do Stamen Design cung cấp dưới CC BY 3.0" + "text": "Hình bản đồ do Stamen Design cung cấp dưới CC BY 3.0. Dữ liệu do OpenStreetMap cung cấp dưới ODbL." }, "name": "Địa thế Stamen" }, @@ -6602,6 +6764,672 @@ }, "name": "Phong cảnh Thunderforest" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "YouthMappers Đại học Cape Coast", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "osm-gh-facebook": { + "name": "OpenStreetMap Ghana tại Facebook", + "description": "Nhóm Facebook dành cho những người quan tâm đến OpenStreetMap.", + "extendedDescription": "Những người lập bản đồ trong cộng đồng tại Ghana, ủng hộ OpenStreetMap và các dá»± án Nhóm Nhân đạo OpenStreetMap (HOT) tại Ghana. Mời bạn tham gia!" + }, + "osm-gh-twitter": { + "name": "OpenStreetMap Ghana tại Twitter", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "talk-gh": { + "name": "Danh sách thÆ° talk-gh", + "description": "talk-gh là danh sách thÆ° chính thức của cộng đồng Ghana." + }, + "osm-mg-facebook": { + "name": "Nhóm Facebook OpenStreetMap Madagascar", + "description": "Nhóm Facebook dành cho những người Madagascar quan tâm đến OpenStreetMap." + }, + "talk-mg": { + "name": "Danh sách thÆ° talk-mg", + "description": "NÆ¡i để những người đóng góp, cộng đồng, và người dùng OpenStreetMap chia sẻ và thảo luận." + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap Bangladesh", + "description": "Cải thiện OpenStreetMap tại Bangladesh" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap Ấn Độ – tham gia lập bản đồ hàng xóm", + "description": "Cải thiện OpenStreetMap tại Ấn Độ", + "extendedDescription": "Bạn có lập bản đồ tại Ấn Độ? Bạn có thắc mắc, muốn liên hệ với cộng đồng tại đây? Mời bạn tham gia tại {url}.", + "events": { + "sotmasia2018": { + "name": "State of the Map châu Á 2018", + "description": "Tham dá»± sá»± kiện khắp miền OpenStreetMap năm 2018, State of the Map châu Á tại Ấn Độ", + "where": "Học viện Quản lý Ấn Độ, Bengaluru, Ấn Độ" + } + } + }, + "OSM-india-mailinglist": { + "name": "Danh sách thÆ° OpenStreetMap Ấn Độ", + "description": "talk-in là danh sách thÆ° chính thức của cộng đồng Ấn Độ" + }, + "OSM-india-twitter": { + "name": "Twitter OpenStreetMap Ấn Độ", + "description": "Chúng tôi chỉ cách bạn một tweet: {url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Phong trào Phần cứng Phần mềm Nguồn mở – Facebook" + }, + "OSM-India-Puducherry-Matrix": { + "name": "Phong trào Phần cứng Phần mềm Nguồn mở – Matrix" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap Indonesia", + "description": "Cải thiện OpenStreetMap tại Indonesia", + "extendedDescription": "Bạn có lập bản đồ tại Indonesia? Bạn có thắc mắc, muốn liên hệ với cộng đồng tại đây? Mời bạn tham gia tại {Url}." + }, + "OSM-japan-facebook": { + "name": "Cộng đồng OpenStreetMap Nhật Bản", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở Nhật Bản" + }, + "OSM-japan-mailinglist": { + "name": "Danh sách thÆ° OpenStreetMap Nhật Bản", + "description": "talk-ja là danh sách thÆ° chính thức của cộng đồng Nhật Bản" + }, + "OSM-japan-twitter": { + "name": "Twitter OpenStreetMap Nhật Bản", + "description": "Thẻ băm tại Twitter: {url}" + }, + "OSM-korea-telegram": { + "name": "Kênh Telegram OSM Hàn Quốc", + "description": "Kênh không chính chức cho phép những người đóng góp, cộng đồng, và người dùng OpenStreetMap tại Hàn Quốc chia sẻ và thảo luận." + }, + "OSM-MY-facebook": { + "name": "OpenStreetMap Malaysia tại Facebook", + "description": "Trò chuyện về bất cứ mọi điều có liên quan đến OpenStreetMap!" + }, + "OSM-MY-forum": { + "name": "Diễn đàn OpenStreetMap Malaysia", + "description": "Diễn đàn OpenStreetMap Malaysia chính thức" + }, + "OSM-MY-matrix": { + "name": "Kênh Riot OpenStreetMap Malaysia", + "description": "Mời bạn tham gia tại {signupUrl}" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap Mông Cổ", + "description": "Cải thiện OpenStreetMap tại Mông Cổ", + "extendedDescription": "Bạn có lập bản đồ tại Mông Cổ? Bạn có thắc mắc, muốn liên hệ với cộng đồng tại đây? Mời bạn tham gia tại {Url}." + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap Miến Điện", + "description": "Cải thiện OpenStreetMap tại Miến Điện", + "extendedDescription": "Bạn có lập bản đồ tại Miến Điện? Bạn có thắc mắc, muốn liên hệ với cộng đồng tại đây? Mời bạn tham gia tại {Url}." + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap Nepal", + "description": "Cải thiện OpenStreetMap tại Nepal", + "extendedDescription": "Bạn có lập bản đồ tại Nepal? Bạn có thắc mắc, muốn liên hệ với cộng đồng tại đây? Mời bạn tham gia tại {Url}." + }, + "OSM-PH-facebook": { + "name": "Facebook OpenStreetMap Philippines", + "description": "OpenStreetMap Philippines khuyến khích mọi người Philippines đóng góp vào dá»± án OpenStreetMap." + }, + "OSM-PH-mailinglist": { + "name": "Danh sách thÆ° talk-ph", + "description": "Danh sách thÆ° để thảo luận về OpenStreetMap tại Philippines" + }, + "OSM-PH-slack": { + "name": "Slack OpenStreetMap Philippines", + "description": "Mời bạn tham gia tại {signupUrl}" + }, + "OSM-PH-telegram": { + "name": "Telegram OpenStreetMap Philippines", + "description": "Cộng đồng địa phÆ°Æ¡ng Telegram không chính thức dành cho những người đóng góp vào OpenStreetMap và bạn bè ở Philippines" + }, + "OSM-RU-forum": { + "name": "Diễn đàn OpenStreetMap Nga", + "description": "Diễn đàn Web của OpenStreetMap Nga" + }, + "OSM-RU-telegram": { + "name": "Telegram OpenStreetMap Nga", + "description": "Trò chuyện Telegram của OpenStreetMap Nga" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap Sri Lanka", + "description": "Cải thiện OpenStreetMap tại Sri Lanka", + "extendedDescription": "Bạn có lập bản đồ tại Sri Lanka? Bạn có thắc mắc, muốn liên hệ với cộng đồng tại đây? Mời bạn tham gia tại {Url}." + }, + "OSM-TW-facebook": { + "name": "Cộng đồng OpenStreetMap Đài Loan", + "description": "Nhóm Facebook cho phép những người lập bản đồ và người dùng OpenStreetMap để thảo luận về Đài Loan." + }, + "OSM-TW-mailinglist": { + "name": "Danh sách thÆ° OpenStreetMap Đài Loan", + "description": "talk-tw là danh sách thÆ° chính thức của cộng đồng Đài Loan" + }, + "at-forum": { + "name": "Diễn đàn OpenStreetMap Áo", + "description": "Diễn đàn chính thức dành cho các câu hỏi về OpenStreetMap trong và chung quanh nước Áo" + }, + "at-mailinglist": { + "name": "Danh sách thÆ° talk-at", + "description": "talk-at là danh sách thÆ° chính thức của cộng đồng Áo" + }, + "at-twitter": { + "name": "Twitter OpenStreetMap Áo", + "description": "OpenStreetMap Áo tại Twitter: {url}" + }, + "osmgraz-meetup": { + "name": "Họp mặt cộng đồng OSM tại Graz", + "description": "Họp mặt hàng tháng của cộng đồng OpenStreetMap tại Graz" + }, + "osmgraz-twitter": { + "name": "Cộng đồng OSM tại Graz tại Twitter", + "description": "Cộng đồng OpenStreetMap tại Graz tại twitter" + }, + "osm-at": { + "name": "OpenStreetMap Áo", + "description": "Trang thông tin về OpenStreetMap tại Áo" + }, + "byosm": { + "name": "OpenStreetMap Belarus", + "description": "Trò chuyện Telegram OpenStreetMap Belarus" + }, + "be-facebook": { + "name": "Cộng đồng OpenStreetMap Bỉ", + "description": "Nhóm Facebook của những người lập bản đồ OpenStreetMap ở Bỉ" + }, + "be-forum": { + "name": "Diễn đàn OpenStreetMap Bỉ", + "description": "Diễn đàn Web của OpenStreetMap Bỉ" + }, + "be-irc": { + "name": "IRC OpenStreetMap Bỉ", + "description": "Hãy tham gia #osmbe tại irc.oftc.net (cổng 6667)", + "extendedDescription": "Hãy tham gia #osmbe tại irc.oftc.net (cổng 6667), kênh này có cầu nối với kênh trò chuyện Matrix" + }, + "be-mailinglist": { + "name": "Danh sách thÆ° talk-be", + "description": "talk-be là danh sách thÆ° chính thức của cộng đồng OSM tại Bỉ" + }, + "be-matrix": { + "name": "Kênh Matrix OpenStreetMap Bỉ", + "description": "Mời mọi người tham gia!" + }, + "be-meetup": { + "name": "Họp mặt OpenStreetMap Bỉ", + "description": "Họp mặt dành cho mọi người quan tâm đến OpenStreetMap" + }, + "be-twitter": { + "name": "Twitter OpenStreetMap Bỉ" + }, + "talk-cz-mailinglist": { + "name": "Danh sách thÆ° talk-cz", + "description": "talk-cz là danh sách thÆ° chính thức của cộng đồng Séc" + }, + "dk-forum": { + "name": "Diễn đàn Web của OpenStreetMap Đan Mạch", + "description": "Diễn đàn Web của OpenStreetMap Đan Mạch" + }, + "dk-irc": { + "name": "IRC OpenStreetMap Đan Mạch", + "description": "Hãy tham gia #osm-dk tại irc.oftc.net (cổng 6667)" + }, + "dk-mailinglist": { + "name": "Danh sách thÆ° talk-dk", + "description": "Danh sách thÆ° để thảo luận về OpenStreetMap tại Đan Mạch" + }, + "fr-facebook": { + "name": "Trang Facebook của OpenStreetMap Pháp", + "description": "Trang Facebook của OpenStreetMap Pháp" + }, + "fr-forum": { + "name": "Diễn đàn Web của OpenStreetMap Pháp", + "description": "Diễn đàn Web của OpenStreetMap Pháp" + }, + "fr-irc": { + "name": "IRC OpenStreetMap Pháp", + "description": "Hãy tham gia #osm-fr tại irc.oftc.net (cổng 6667)" + }, + "fr-mailinglist": { + "name": "Danh sách thÆ° talk-fr", + "description": "Danh sách thÆ° talk-fr" + }, + "fr-twitter": { + "name": "OpenStreetMap Pháp tại Twitter", + "description": "OpenStreetMap Pháp tại Twitter: {url}" + }, + "de-berlin-mailinglist": { + "name": "Danh sách thÆ° Berlin", + "description": "Đây là danh sách thÆ° của cộng đồng OSM tại Berlin" + }, + "de-berlin-meetup": { + "name": "Họp mặt OpenStreetMap Berlin-Brandenburg", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Berlin" + }, + "de-berlin-telegram": { + "name": "@osmberlin tại Telegram", + "description": "Trò chuyện Telegram của OpenStreetMap Berlin" + }, + "de-berlin-twitter": { + "name": "Twitter OpenStreetMap Berlin", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "de-forum": { + "name": "Diễn đàn OpenStreetMap Đức", + "description": "Diễn đàn Web của OpenStreetMap Đức" + }, + "de-irc": { + "name": "IRC OpenStreetMap Đức", + "description": "Hãy tham gia #osm-de tại irc.oftc.net (cổng 6667)" + }, + "de-mailinglist": { + "name": "Danh sách thÆ° talk-de", + "description": "talk-de là danh sách thÆ° chính thức của cộng đồng Đức" + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "Danh sách OWL", + "description": "Đây là danh sách thÆ° của cộng đồng OSM tại Ostwestfalen-Lippe" + }, + "osm-de": { + "name": "OpenStreetMap Đức", + "description": "Trang thông tin về OpenStreetMap tại Đức" + }, + "hu-facebook": { + "name": "OpenStreetMap Hungary tại Facebook", + "description": "Nhóm Facebook của những người lập bản đồ và người dùng OpenStreetMap ở Hungary" + }, + "hu-forum": { + "name": "Diễn đàn OpenStreetMap Hungary", + "description": "Diễn đàn Web của OpenStreetMap Hungary" + }, + "hu-meetup": { + "name": "Họp mặt OpenStreetMap Hungary" + }, + "it-facebook": { + "name": "Facebook OpenStreetMap Ý", + "description": "Hãy tham gia cộng đồng OpenStreetMap Ý tại Facebook" + }, + "it-irc": { + "name": "IRC OpenStreetMap Ý", + "description": "Hãy tham gia #osm-it tại irc.oftc.net (cổng 6667)" + }, + "it-mailinglist": { + "name": "Danh sách thÆ° talk-it", + "description": "talk-it là danh sách thÆ° chính thức của cộng đồng Ý" + }, + "it-twitter": { + "name": "Twitter OpenStreetMap Ý", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "OSM-Rome-meetup": { + "name": "Incontro Mappatori Romani", + "description": "Cải thiện OpenStreetMap tại khu vá»±c Rôma", + "extendedDescription": "Chúng ta nhằm mục đích cho phép thảo luận và chia sẻ kiến thức về cách sá»­ dụng kho dữ liệu địa lý mở, nhất là OpenStreetMap, cÅ©ng nhÆ° cách sá»­ dụng phần mềm không gian địa lý mở để quản lý, sá»­a đổi, và hiển thị dữ liệu địa lý. Chúng ta ủng hộ sá»­ dụng dữ liệu mở và phần mềm không gian địa lý mở tại miền Đông Bắc Lazio." + }, + "South-Tyrol-Mailing-List": { + "name": "Danh sách thÆ° OpenStreetMap cho Nam Tirol", + "description": "Danh sách thÆ° OpenStreetMap Ý thảo luận về Nam Tirol" + }, + "talk-it-lazio": { + "name": "OpenStreetMap Ý-Lazio", + "description": "Mời bạn tham gia tại {signupUrl}", + "extendedDescription": "Danh sách thÆ° cho khu vá»±c Rôma và Lazio." + }, + "Trentino-Mailing-List": { + "name": "Danh sách thÆ° OpenStreetMap cho Trentino", + "description": "Danh sách thÆ° OpenStreetMap Ý thảo luận về Trentino" + }, + "no-forum": { + "name": "Diễn đàn Web của OpenStreetMap Na Uy", + "description": "Diễn đàn Web của OpenStreetMap Na Uy" + }, + "no-irc": { + "name": "IRC OpenStreetMap Na Uy", + "description": "Phòng trò chuyện của những người lập bản đồ và những người sá»­ dụng, nhà phát triển, và người hâm mộ OpenStreetMap ở Na Uy" + }, + "no-mailinglist": { + "name": "Danh sách thÆ° OpenStreetMap Na Uy", + "description": "Danh sách thÆ° dành cho những người lập bản đồ và những người sá»­ dụng, nhà phát triển, và người hâm mộ OpenStreetMap ở Na Uy" + }, + "OSM-PL-facebook-group": { + "name": "Nhóm Facebook OpenStreetMap Ba Lan", + "description": "Nhóm dành cho những người lập bản đồ và người dùng OpenStreetMap ở Ba Lan" + }, + "OSM-PL-forum": { + "name": "Diễn đàn OpenStreetMap Ba Lan", + "description": "Diễn đàn của cộng đồng OpenStreetMap Ba Lan" + }, + "OSM-ES-mailinglist": { + "name": "Danh sách thÆ° talk-es", + "description": "Danh sách thÆ° để thảo luận về OpenStreetMap tại Tây Ban Nha" + }, + "OSM-ES-telegram": { + "name": "@OSMes tại Telegram", + "description": "Trò chuyện Telegram của OpenStreetMap Tây Ban Nha" + }, + "osm-se": { + "name": "OpenStreetMap.se", + "description": "Cung cấp dịch vụ và thông tin về OpenStreetMap cho cộng đồng địa phÆ°Æ¡ng tại Thụy Điển" + }, + "se-facebook": { + "name": "Facebook OpenStreetMap Thụy Điển", + "description": "OpenStreetMap Thụy Điển tại Facebook" + }, + "se-forum": { + "name": "Diễn đàn Web của OpenStreetMap Thụy Điển", + "description": "Diễn đàn Web của OpenStreetMap Thụy Điển" + }, + "se-irc": { + "name": "IRC OpenStreetMap Thụy Điển", + "description": "Hãy tham gia #osm.se tại irc.oftc.net (cổng 6667)" + }, + "se-mailinglist": { + "name": "Danh sách thÆ° talk-se", + "description": "Danh sách thÆ° để thảo luận về OpenStreetMap tại Thụy Điển" + }, + "se-twitter": { + "name": "OpenStreetMap Thụy Điển tại Twitter", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "Họp mặt Đông Midlands (Nottingham) hàng tháng tại quán rượu" + }, + "gb-mailinglist": { + "name": "Danh sách thÆ° talk-gb", + "description": "talk-gb là danh sách thÆ° chính thức của cộng đồng OSM tại Anh (bao gồm Bắc Ireland)" + }, + "mappa-mercia-group": { + "name": "Nhóm địa phÆ°Æ¡ng Mappa Mercia" + }, + "gb-irc": { + "name": "IRC OpenStreetMap VÆ°Æ¡ng quốc Anh", + "description": "Hãy tham gia #osm-gb tại irc.oftc.net (cổng 6667)", + "extendedDescription": "Hãy tham gia #osm-gb tại irc.oftc.net (cổng 6667). Xin vui lòng kiên nhẫn chờ đợi vài phút nếu hỏi câu hỏi." + }, + "OSM-CA-Slack": { + "name": "Slack OSM Canada", + "description": "Mời bạn tham gia tại {signupUrl}" + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap Vancouver", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Vancouver, British Columbia" + }, + "Bay-Area-OpenStreetMappers": { + "name": "Cộng đồng OpenStreetMap tại Khu vá»±c vịnh", + "description": "Cải thiện OpenStreetMap tại Khu vá»±c Vịnh San Francisco", + "extendedDescription": "Nhóm này ủng hộ cộng đồng OpenStreetMap của chúng ta ở Khu vá»±c Vịnh San Francisco. Ai cÅ©ng tham gia được các sá»± kiện của chúng ta, kể cả người hâm mộ phần mềm nguồn mở, người đi xe đạp, chuyên gia GIS, người hâm mộ geocaching, và hÆ¡n nữa. Mời mọi người quan tâm về sá»­ dụng bản đồ, xây dá»±ng bản đồ, và dữ liệu bản đồ tham gia nhóm và các sá»± kiện của chúng ta." + }, + "Central-Pennsylvania-OSM": { + "name": "OSM Miền trung Pennsylvania", + "description": "Cộng đồng xây dá»±ng bản đồ trá»±c tuyến ở State College, Pennsylvania" + }, + "Code-for-San-Jose-Slack": { + "name": "Slack Code for San Jose", + "description": "Mời bạn tham gia tại {signupUrl}, rồi tham gia kênh #osm." + }, + "Dallas-Fort-Worth-OSM": { + "name": "OSM Dallas–Fort Worth", + "description": "Nhóm người dùng OpenStreetMap ở vùng Dallas–Fort Worth", + "extendedDescription": "Dallas, Fort Worth, và các thành phố ở giữa có rất nhiều người sáng tạo và khéo léo về công nghệ thông tin. Nhóm người dùng này nhằm mục đích tìm ra những cách mới để sá»­ dụng tài nguyên OSM khá tốt." + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "Cuộc họp mặt cho những người hâm mộ bản đồ ở khu vá»±c Philadelphia", + "extendedDescription": "GeoPhilly liên hiệp các nhà phát triển, nhà địa lý học, người hâm mộ về dữ liệu và dữ liệu mở, “civic hacker”, và người nghiện bản đồ để bày tỏ say mê bản đồ và chia sẻ các câu chuyện trong bản đồ. Nếu bạn sá»­ dụng bản đồ trong việc làm hoặc chỉ muốn tìm hiểu thêm, bạn nên tham gia cuộc họp mặt này! Chúng ta cố gắng tổ chức các sá»± kiện mở rộng, thân thiện, cùng giáo dục cùng giải trí, bao gồm họp mặt tại quán rượu, bài thuyết trình nhanh chóng, và workshop. Mời bạn cùng xây dá»±ng một cộng đồng không gian địa lý đa dạng văn hóa và gây cảm hứng tại Philadelphia!" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "Những người lập bản đồ và người hâm mộ OpenStreetMap ở vùng Thành phố Đôi", + "extendedDescription": "NÆ¡i liên hệ của những người hâm mộ OpenStreetMap ở Minnesota và vùng Thành phố Đôi!" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC", + "description": "Cải thiện OpenStreetMap tại khu vá»±c Washington, D.C.", + "extendedDescription": "Chúng ta tình nguyện xây dá»±ng bản đồ OpenStreetMap tại khu vá»±c Washington, D.C. Nhóm này cÅ©ng nhằm mục đích dạy người khác về hệ sinh thái OSM, môn phân tích dữ liệu, bản đồ học, và GIS. Chúng ta họp mặt hai tháng một lần để tập trung chú ý vào một phần của thành phố này." + }, + "Maptime-ME-meetup": { + "name": "MaptimeME", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Portland, Maine", + "extendedDescription": "Maptime đúng là thì giờ để lập bản đồ. Chúng ta nhằm mục đích mở cá»­a bản đồ học để cho mọi người có quan tâm có thể lập bản đồ, bằng cách để dành thì giờ và không gian để cộng tác tìm hiểu, khám phá, và lập bản đồ dùng công cụ và công nghệ bản đồ." + }, + "OpenCleveland-meetup": { + "name": "Open Cleveland", + "description": "Cải thiện OpenStreetMap tại khu vá»±c Cleveland", + "extendedDescription": "Open Geo Cleveland nhằm mục đích cho phép thảo luận và chia sẻ kiến thức về cách sá»­ dụng kho dữ liệu địa lý mở, nhất là OpenStreetMap, cÅ©ng nhÆ° cách sá»­ dụng phần mềm không gian địa lý mở để quản lý, sá»­a đổi, và hiển thị dữ liệu địa lý. Chúng ta ủng hộ sá»­ dụng dữ liệu mở và phần mềm không gian địa lý mở tại miền Đông Bắc Ohio. Chúng ta cÅ©ng là một nhánh Maptime. =)" + }, + "OSM-Boston": { + "name": "OpenStreetMap Boston", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Boston", + "extendedDescription": "OpenStreetMap là bản đồ thế giới mở kiểu wiki nhờ những người nhÆ° bạn đóng góp mỗi ngày hàng trăm ngàn lần. Sá»­a đổi bản đồ là điều đơn giản và thú vị! Hãy tham gia chúng tôi trong nhà và ngoài đường để cùng xây dá»±ng bản đồ đầy đủ nhất của vùng Boston và cả thế giới!" + }, + "OSM-Central-Salish-Sea": { + "name": "OpenStreetMap Biển Salish Trung", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Mount Vernon, Washington", + "extendedDescription": "OpenStreetMap (OSM) là bản đồ thế giới do những người nhÆ° bạn xây dá»±ng và cho phép mọi người sá»­ dụng miễn phí và vô hạn chế giống nhÆ° Wikipedia. Chúng tôi gặp mặt thường xuyên để nói chuyện vui vẻ về bản đồ và lập bản đồ!" + }, + "OSM-Chattanooga": { + "name": "OSM Chattanooga", + "description": "Nhóm người dùng OpenStreetMap ở Chattanooga" + }, + "OSM-Colorado": { + "name": "OpenStreetMap Colorado", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở tiểu bang Colorado, Hoa Kỳ", + "extendedDescription": "OpenStreetMap Colorado là nhóm địa phÆ°Æ¡ng cố gắng xây dá»±ng bản đồ mở. Chúng tôi khuyên khích mọi thành viên tổ chức hoặc gợi ý các sá»± kiện lập bản đồ ở khắp tiểu bang. Các hoạt động gặp mặt có thể là buổi liên hoan khiêu vÅ© đơn giản, chÆ°Æ¡ng trình huấn luyện về OSM từ căn bản đến nâng cao, hoặc tiệc vẽ bản đồ của cộng đồng." + }, + "OSM-NYC": { + "name": "OpenStreetMap Thành phố New York", + "description": "Những người lập bản đồ và những người sá»­ dụng, nhà phát triển, và người hâm mộ OpenStreetMap ở khu vá»±c đô thị New York" + }, + "OSM-Portland": { + "name": "OpenStreetMap Portland", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Portland", + "extendedDescription": "OpenStreetMap (OSM) là bản đồ thế giới do những người nhÆ° bạn xây dá»±ng và cho phép mọi người sá»­ dụng miễn phí và vô hạn chế giống nhÆ° Wikipedia. Hãy ghé vào osm.org và gặp mặt chúng ta để nói chuyện vui vẻ về bản đồ và đóng góp vào OSM cùng nhau!" + }, + "OSM-Seattle": { + "name": "OpenStreetMap Seattle", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Seattle" + }, + "OSM-SoCal": { + "name": "OpenStreetMap Nam Ca Li", + "description": "Hãy vui vẻ đóng góp vào Los Angeles và tìm hiểu cách xây dá»±ng bản đồ!", + "extendedDescription": "OpenStreetMap Nam Ca Li liên hiệp những người nào quan tâm về bản đồ để ủng hộ OpenStreetMap. OSM là Wikipedia của bản đồ, tức bản đồ thế giới mở do hÆ¡n một triệu người tình nguyện xây dá»±ng ở khắp thế giới. Mời mọi người tham gia. Nếu bạn chÆ°a biết đến OpenStreetMap, chúng tôi sẽ giới thiệu cho bạn. Nếu bạn có ý niệm bắt đầu dá»± án bản đồ hoặc dẫn nhóm đi nÆ¡i nào, tuyệt vời!" + }, + "OSM-South-Bay": { + "name": "OSM Miền Nam Vùng Vịnh", + "description": "Buổi tối Bản đồ do Code for San Jose tổ chức", + "extendedDescription": "Code for San Jose là nhánh Code for America địa phÆ°Æ¡ng tổ chức các Buổi tối Bản đồ hàng tháng vào tối thứ 5 dưới phố San José. Gặp mặt những người cùng lập bản đồ ở miền Nam Vùng Vịnh, giúp đỡ các dá»± án xây dá»±ng bản đồ địa phÆ°Æ¡ng, và tìm hiểu về các dá»± án công nghệ công dân (civic tech) khác. Không nhất thiết phải có kinh nghiệm lập trình hoặc GIS." + }, + "OSM-Tampa-Bay": { + "name": "OpenStreetMap Vịnh Tampa", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng vịnh Tampa" + }, + "OSM-US-Slack": { + "name": "Slack OpenStreetMap Hoa Kỳ", + "description": "Mời bạn tham gia tại {signupUrl}" + }, + "OSM-US": { + "name": "OpenStreetMap Hoa Kỳ", + "description": "Chúng ta giúp phát triển và cải thiện OpenStreetMap tại Hoa Kỳ.", + "extendedDescription": "Chúng ta giúp OpenStreetMap bằng cách tổ chức các hội nghị hàng năm, cung cấp tài nguyên cộng đồng, tạo quan hệ đối tác, và truyền bá dá»± án. Mời tham gia OpenStreetMap Hoa Kỳ tại đây: {signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap Utah", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Thành phố Salt Lake" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap Wyoming", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở tiểu bang Wyoming, Hoa Kỳ", + "extendedDescription": "OpenStreetMap Wyoming là nhóm địa phÆ°Æ¡ng cố gắng xây dá»±ng bản đồ mở. Chúng tôi khuyên khích mọi thành viên tổ chức hoặc gợi ý các sá»± kiện lập bản đồ ở khắp tiểu bang. Các hoạt động gặp mặt có thể là buổi liên hoan khiêu vÅ© đơn giản, chÆ°Æ¡ng trình huấn luyện về OSM từ căn bản đến nâng cao, hoặc tiệc vẽ bản đồ của cộng đồng." + }, + "PHXGeo-meetup": { + "name": "Họp mặt PHXGeo", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Phoenix, Arizona", + "extendedDescription": "Nhóm họp mặt dành cho những người ở vùng Phoenix thích bản đồ, GIS, OpenStreetMap, bản đồ học, và đủ mọi thứ." + }, + "PHXGeo-twitter": { + "name": "Twitter PHXGeo", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "Western-Slope-facebook": { + "name": "Facebook OSM Sườn Tây", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Grand Junction, Colorado" + }, + "Western-Slope-meetup": { + "name": "Họp mặt OSM Sườn Tây", + "description": "Những người lập bản đồ và người dùng OpenStreetMap ở vùng Grand Junction, Colorado" + }, + "Maptime-Australia-Slack": { + "name": "Slack Maptime Úc", + "description": "Mời bạn tham gia tại {signupUrl}" + }, + "talk-au": { + "name": "Danh sách thÆ° talk-au", + "description": "NÆ¡i trò chuyện của những người Úc lập bản đồ" + }, + "OSM-AR-facebook": { + "name": "Facebook OpenStreetMap Argentina", + "description": "Hãy tham gia cộng đồng OpenStreetMap Argentina tại Facebook", + "extendedDescription": "Tin tức về cộng đồng địa phÆ°Æ¡ng" + }, + "OSM-AR-forum": { + "name": "Diễn đàn Web của OpenStreetMap Argentina", + "description": "Hãy tham gia diễn đàn Web của OpenStreetMap Argentina" + }, + "OSM-AR-irc": { + "name": "IRC OpenStreetMap Argentina", + "description": "Hãy tham gia #osm-ar tại irc.oftc.net (cổng 6667)" + }, + "OSM-AR-mailinglist": { + "name": "Danh sách thÆ° talk-ar" + }, + "OSM-AR-telegram": { + "name": "Telegram OpenStreetMap Argentina", + "description": "Hãy tham gia cộng đồng OpenStreetMap Argentina tại Telegram" + }, + "OSM-AR-twitter": { + "name": "Twitter OpenStreetMap Argentina", + "description": "Theo dõi chúng tôi trên Twitter: {url}", + "extendedDescription": "Tin tức về cộng đồng địa phÆ°Æ¡ng và OpenStreetMap nói chung." + }, + "OSM-BO-mailinglist": { + "name": "Danh sách thÆ° talk-bo", + "description": "talk-bo là danh sách thÆ° chính thức của cộng đồng OSM tại Bolivia", + "extendedDescription": "Bạn có lập bản đồ tại Bolivia? Bạn có thắc mắc, muốn liên hệ với cộng đồng tại đây? Mời bạn tham gia tại {url}." + }, + "Bahia-telegram": { + "name": "Nhóm Telegram OpenStreetMap Bahia", + "description": "Hãy tham gia cộng đồng OpenStreetMap Bahia tại Telegram", + "extendedDescription": "Mời mọi người tham gia cộng đồng để tìm hiểu thêm về OpenStreetMap, hỏi đáp, và tham dá»± các cuộc họp mặt của chúng ta." + }, + "DF-telegram": { + "name": "Nhóm Telegram OpenStreetMap Brasília", + "description": "Hãy tham gia cộng đồng OpenStreetMap Brasília tại Telegram", + "extendedDescription": "Mời mọi người tham gia cộng đồng để tìm hiểu thêm về OpenStreetMap, hỏi đáp, và tham dá»± các cuộc họp mặt của chúng ta." + }, + "OSM-br-mailinglist": { + "name": "Danh sách thÆ° talk-br", + "description": "Danh sách thÆ° để thảo luận về OpenStreetMap tại Brasil" + }, + "OSM-br-telegram": { + "name": "Telegram OpenStreetMap Brasil", + "description": "Hãy tham gia cộng đồng OpenStreetMap Brasil tại Telegram", + "extendedDescription": "Mời mọi người tham gia cộng đồng để tìm hiểu thêm về OpenStreetMap, hỏi đáp, và tham dá»± các cuộc họp mặt của chúng ta." + }, + "OSM-br-twitter": { + "name": "Twitter OpenStreetMap Brasil", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "OSM-CL-facebook": { + "name": "Facebook OpenStreetMap Chile", + "description": "Hãy tham gia cộng đồng OpenStreetMap Chile tại Facebook", + "extendedDescription": "Mời mọi người tham gia cộng đồng để tìm hiểu thêm về OpenStreetMap, hỏi đáp, và tham dá»± các cuộc họp mặt của chúng ta." + }, + "OSM-CL-mailinglist": { + "name": "Danh sách thÆ° talk-cl", + "description": "Danh sách thÆ° để thảo luận về OpenStreetMap tại Chile" + }, + "OSM-CL-telegram": { + "name": "Telegram OpenStreetMap Chile", + "description": "Hãy tham gia cộng đồng OpenStreetMap Chile tại Telegram", + "extendedDescription": "Mời mọi người tham gia cộng đồng để tìm hiểu thêm về OpenStreetMap, hỏi đáp, và tham dá»± các cuộc họp mặt của chúng ta." + }, + "OSM-CL-twitter": { + "name": "Twitter OpenStreetMap Chile", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá" + }, + "OSM-CO-facebook": { + "name": "Facebook OpenStreetMap Colombia", + "description": "Hãy tham gia cộng đồng OpenStreetMap Colombia tại Facebook", + "extendedDescription": "Mời mọi người tham gia cộng đồng để tìm hiểu thêm về OpenStreetMap. Mời mọi người tham gia!" + }, + "OSM-CO-mailinglist": { + "name": "Danh sách thÆ° talk-co", + "description": "Danh sách thÆ° để thảo luận về OpenStreetMap tại Colombia" + }, + "OSM-CO-twitter": { + "name": "Twitter OpenStreetMap Colombia", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "OSM-CO": { + "name": "OpenStreetMap Colombia", + "description": "Tin tức về cộng đồng OpenStreetMap Colombia và Quỹ OSMCo" + }, + "OSM-PE-facebook": { + "name": "Facebook OpenStreetMap Peru", + "description": "Hãy tham gia cộng đồng OpenStreetMap Peru tại Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Danh sách thÆ° talk-pe", + "description": "Danh sách thÆ° chính thức của cộng đồng OSM tại Peru" + }, + "OSM-PE-matrix": { + "name": "Trò chuyện Matrix OpenStreetMap Peru", + "description": "Trò chuyện với cộng đồng OpenStreetMap Peru trong Matrix." + }, + "OSM-PE-telegram": { + "name": "Telegram OpenStreetMap Peru", + "description": "Hãy tham gia cộng đồng OpenStreetMap Peru tại Telegram" + }, + "OSM-PE-twitter": { + "name": "Twitter OpenStreetMap Peru", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "OSM-PE": { + "name": "OpenStreetMap Peru", + "description": "Tin tức về và tài nguyên cho cộng đồng OpenStreetMap Peru" + }, + "OSM-Facebook": { + "name": "OpenStreetMap tại Facebook", + "description": "Thích chúng tôi tại Facebook để nhận tin tức và cập nhật về OpenStreetMap." + }, + "OSM-help": { + "name": "Trợ giúp OpenStreetMap", + "description": "Hỏi han và nhận câu trả lời tại trang hỏi đáp của cộng đồng OpenStreetMap.", + "extendedDescription": "{url} dành cho mọi người cần giúp đỡ sá»­ dụng OpenStreetMap. Mới bắt đầu vẽ bản đồ hoặc có câu hỏi về kỹ thuật, chúng tôi sẵn sàng giúp đỡ!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap tại Reddit", + "description": "/r/openstreetmap/ là nÆ¡i để tìm hiểu thêm về OpenStreetMap. Có thắc mắc thì hỏi ở đây!" + }, + "OSM-Twitter": { + "name": "Twitter OpenStreetMap", + "description": "Theo dõi chúng tôi trên Twitter: {url}" + }, + "OSMF": { + "name": "Quỹ OpenStreetMap", + "description": "Quỹ OpenStreetMap là một tổ chức phi lợi nhận tại VÆ°Æ¡ng quốc Anh hỗ trợ dá»± án OpenStreetMap", + "extendedDescription": "Quỹ OSM hỗ trợ OpenStreetMap bằng cách gây quỹ, quản trị các máy chủ OSM, tổ chức hội nghị State of the Map hàng năm, và phối hợp những người tình nguyện bảo trì OSM. Bạn có thể ủng hộ OpenStreetMap và có tiếng nói về tÆ°Æ¡ng lai của đến dá»± án bằng cách trở thành một thành viên Quỹ OSM: {signupUrl}", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "Qua ba ngày tại Milano, Ý, tham dá»± hội nghị OpenStreetMap toàn cầu hàng năm, tụ họp mọi người trong cộng đồng để xã hội hóa, chia sẻ kinh nghiệm, và học tập.", + "where": "Milano, Ý" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/yue.json b/vendor/assets/iD/iD/locales/yue.json index 2874ca4d8..db828c131 100644 --- a/vendor/assets/iD/iD/locales/yue.json +++ b/vendor/assets/iD/iD/locales/yue.json @@ -151,7 +151,6 @@ "key": "C", "annotation": "拼咗地貌 {n} 個", "not_eligible": "爾啲地貌,無得併埋。", - "restriction": "地貌無得拼,佢哋至少一個,屬於 {relation} 關聯。", "incomplete_relation": "地貌無得拼,佢哋至少一個未傳晒落來。", "conflicting_tags": "地貌無得拼,佢哋籤中內有矛盾。" }, @@ -441,13 +440,7 @@ } }, "success": { - "edited_osm": "改掂公家街圖!", "just_edited": "你啱啱改咗公家街圖!", - "view_on_osm": "入公家街圖睇", - "facebook": "放上Facebook", - "twitter": "放上Twitter", - "google": "放上Google+", - "help_html": "你改過嘅,幾分鐘就會見到喺「普通」層。其他層,咁啲地貌,就會耐啲。", "help_link_text": "明細", "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" }, @@ -1198,7 +1191,6 @@ "label": "畀錢方式" }, "phone": { - "label": "電話", "placeholder": "+852 12345678" }, "piste/difficulty": { @@ -1444,9 +1436,6 @@ "trees": { "label": "樹" }, - "vending": { - "label": "貨類" - }, "visibility": { "label": "顯隱", "options": { diff --git a/vendor/assets/iD/iD/locales/zh-CN.json b/vendor/assets/iD/iD/locales/zh-CN.json index e9155a366..19f330ec2 100644 --- a/vendor/assets/iD/iD/locales/zh-CN.json +++ b/vendor/assets/iD/iD/locales/zh-CN.json @@ -1,5 +1,10 @@ { "zh-CN": { + "icons": { + "information": "信息", + "remove": "删除", + "undo": "复原" + }, "modes": { "add_area": { "title": "区域", @@ -41,7 +46,7 @@ "start": { "annotation": { "line": "开始绘制线。", - "area": "开始绘制面状要素。" + "area": "开始绘制区域。" } }, "continue": { @@ -145,14 +150,16 @@ "vertex": "已连接路径到另一路径。", "line": "已连接路径到一线段。", "area": "已连接路径到一区域。" - } + }, + "relation": "这些要素不能被连接,因为其有冲突的关系成员。", + "restriction": "这些要素不能被连接,因为这样会破坏 “{relation}” 关系。" }, "disconnect": { "title": "分离", "description": "将这些线/区域相互分离。", "key": "D", "annotation": "将线或区域分离。", - "not_connected": "没有足够的线/面来分离。", + "not_connected": "没有足够的线/区域来分离。", "connected_to_hidden": "无法分离,因为其与一隐藏要素相连。", "relation": "无法分离,因为它与一个关系的成员间相连。" }, @@ -163,7 +170,8 @@ "annotation": "已合并 {n} 个要素。", "not_eligible": "这些要素不可以合并。", "not_adjacent": "这些要素的结束节点并未相连,无法将其合并。", - "restriction": "这些要素不能被合并,因为其中至少有一个要素是某个“{relation}”关系的成员。", + "restriction": "这些要素不能被合并,因为这样会破坏 “{relation}” 关系。", + "relation": "这些要素不能被合并,因为其有冲突的关系成员。", "incomplete_relation": "此要素暂未下载完成,无法合并。", "conflicting_tags": "这些要素不能被合并,因为它们的某些标签具有冲突的值。" }, @@ -271,14 +279,14 @@ "title": "分割", "description": { "line": "在此节点上将这条线分割成两条线。", - "area": "将这个面的边界一分为二。", - "multiple": "在这一节点将线/面的边界一分为二。" + "area": "将这个区域的边界一分为二。", + "multiple": "在这一节点将线/区域的边界一分为二。" }, "key": "X", "annotation": { "line": "切割一条线。", - "area": "分割面要素的边界。", - "multiple": "分割{n}项线段/面的边界。" + "area": "分割区域的边界。", + "multiple": "分割{n}个线/区域的边界。" }, "not_eligible": "不能在线段的首尾进行分割。", "multiple_ways": "太多线段,未能进行分割。", @@ -361,12 +369,12 @@ }, "commit": { "title": "上传至 OpenStreetMap", - "upload_explanation": "您上传的修改将会在所有使用 OpenStreetMap 数据的地图上可见。", - "upload_explanation_with_user": "{user},您上传的修改将会在所有使用 OpenStreetMap 数据的地图上可见。", + "upload_explanation": "您上传的更改将会在所有使用 OpenStreetMap 数据的地图上可见。", + "upload_explanation_with_user": "{user},您上传的更改将会在所有使用 OpenStreetMap 数据的地图上可见。", "request_review": "我想要让其他人复核我的编辑。", "save": "上传", "cancel": "取消", - "changes": "{count}个变更", + "changes": "{count} 个更改", "download_changes": "下载 osmChange 文件", "warnings": "警告", "modified": "已更改", @@ -402,6 +410,7 @@ "key": "H", "title": "历史", "selected": "已选择 {n} 个", + "no_history": "无历史记录(新要素)", "version": "版本", "last_edit": "最近编辑", "edited_by": "编辑者", @@ -592,11 +601,11 @@ }, "partial": { "description": "部分填充", - "tooltip": "仅在面的内部边界附近填充区域。(推荐初学者使用)" + "tooltip": "仅在区域内的边界附近填充。(推荐初学者使用)" }, "full": { "description": "全部填充", - "tooltip": "区域全部填充绘制。" + "tooltip": "在区域内全部填充。" } }, "restore": { @@ -614,7 +623,7 @@ "unknown_error_details": "请确保您已连接到互联网。", "uploading": "正在向 OpenStreetMap 上传更改……", "conflict_progress": "正在检查冲突:第 {num} / {total} 处", - "unsaved_changes": "您有未保存的修改", + "unsaved_changes": "您有未保存的更改", "conflict": { "header": "调解编辑冲突", "count": "第{num}处冲突,共{total}处", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "编辑了 OSM!", "just_edited": "您刚刚编辑了 OpenStreetMap!", - "view_on_osm": "在 OSM 上查看", - "facebook": "分享到Facebook", - "twitter": "分享到 Twitter", - "google": "分享到 Google+", - "help_html": "您的修改将会在几分钟内出现在“标准”图层上,其他图层和某些要素可能需要更长的处理时间。", + "thank_you": "感谢您改进地图。", + "thank_you_location": "感谢您改进 {where} 周边的地图。", + "help_html": "您的更改将会在几分钟内于 OpenStreetMap 上显示。其他地图可能需要更长的时间接收更新。 ", "help_link_text": "详情", - "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" + "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", + "view_on_osm": "在 OSM 上查看更改", + "changeset_id": "您的变更集合 #: {changeset_id}", + "like_osm": "喜欢 OpenStreetMap 吗?不妨与更多人联系:", + "more": "更多", + "events": "事件", + "languages": "语言:{languages}", + "missing": "该列表里有遗漏的信息吗?", + "tell_us": "告诉我们!" }, "confirm": { "okay": "确定", @@ -756,7 +770,7 @@ "save": "点击 {save} **保存** 以完成您的编辑并发送至 OpenStreetMap。请您牢记:要经常保存您的编辑!", "save_validation": "在保存界面,您有机会再次检查您所做的编辑。iD 也会做相应的基本检查确保无数据缺失,并且会在不适当的地方提供有用的建议或警告。", "upload_h": "上传", - "upload": "在上传您所做的修改之前,您必须输入一段 [修改集合注释](https://wiki.openstreetmap.org/wiki/Good_changeset_comments) 。接着点击 **上传** 将您的编辑发送至 OpenStreetMap,之后它们将会被合并到地图并且对所有人公开可见。", + "upload": "在上传您所做的更改之前,您必须输入一段 [变更集合注释](https://wiki.openstreetmap.org/wiki/Good_changeset_comments)。接着点击 **上传** 将您的编辑发送至 OpenStreetMap,之后它们将会被合并到地图并且对所有人公开可见。", "backups_h": "自动备份", "backups": "如果您一时无法结束您的编辑,例如您的计算机宕机或者关闭了浏览器标签页,您所做的编辑仍会被保存在浏览器存储中。您可以稍后回来(在相同的计算机和浏览器上),然后由 iD 恢复您之前的编辑。", "keyboard_h": "键盘快捷键", @@ -972,7 +986,7 @@ "add_name": "在 OpenStreetMap 中,所有的字段都是选填的,如果您不确定的话,让字段留空也是可以的。{br}让我们假设您对当地这间咖啡馆有所了解,并且知道它的名称。 **为这间咖啡馆添加名称。**", "add_close": "要素编辑器会自动记住您所有的改动。 **当您添加了名称后,按下 Esc 键、回车键或点击 {button} 按钮来关闭要素编辑器。**", "reselect": "很多时候,点会已经存在,但是信息有错误或不完整。我们可以编辑已经存在的点。 **点击选中您刚才创建的咖啡馆。**", - "update": "让我们给这间咖啡馆加入更多的细节。您可以更改它的名称、添加菜肴或填写地址。 **更改咖啡馆的细节。**", + "update": "让我们给这间咖啡馆加入更多的细节。您可以更改它的名称、添加菜系或填写地址。 **更改咖啡馆的细节。**", "update_close": "**当您完成更新咖啡馆后,按下 Esc 键、回车键或点击 {button} 按钮来关闭要素编辑器。**", "rightclick": "您可以右键点击任意要素来显示 *编辑菜单* ,它显示可以使用的编辑操作列表。 **右键点击您创建的点来显示编辑菜单。**", "delete": "删除现实世界中不存在的要素是被允许的。{br}在 OpenStreetMap 中删除要素意味着它将会从每个人使用的地图中移除,所以您应该在删除前确保它真的已不复存在。 **点击 {button} 按钮来删除该点。**", @@ -981,9 +995,9 @@ }, "areas": { "title": "区域", - "add_playground": "*区域* 用来显示诸如湖泊、建筑物或居民区等要素的边界。{br}他们亦可作为一种更细致的绘制方式,以替代普通地用点来标记的方式。 **点击 {button} 区域按钮来添加一个新的区域。**", + "add_playground": "*区域* 用来显示诸如湖泊、建筑物或居民区等要素的边界。{br}他们亦可作为相较于用点来标记要素而言更为细致的绘制方式。 **点击 {button} 区域按钮来添加一个新的区域。**", "start_playground": "让我们用描绘一个区域的方式来添加这个游乐场吧。区域是通过在要素的外部轮廓上放置若干 *节点* 来描绘。 **点击或按空格键,在游乐场的其中一角放置一个起始节点。**", - "continue_playground": "继续在游乐场的轮廓上放置更多的节点来绘制该区域。如果遇到既有的人行道,你也可以将区域连接到人行道上。{br}提示:您可以按下{alt}键以防止节点连接到其他要素上。 **继续绘制游乐场区域。**", + "continue_playground": "继续在游乐场的轮廓上放置更多的节点来绘制该区域。如果遇到既有的人行道,您也可以将区域连接到人行道上。{br}提示:您可以按下{alt}键以防止节点连接到其他要素上。 **继续绘制游乐场区域。**", "finish_playground": "按回车键、或再次点击起始/结束节点来结束绘制该区域。 **完成勾画该游乐场的轮廓。**", "search_playground": "**搜索 '{preset}' 。**", "choose_playground": "**在列表中选择 {preset} 。**", @@ -1025,7 +1039,7 @@ }, "buildings": { "title": "建筑物", - "add_building": "OpenStreetMap 是世界上最大的建筑物数据库。{br}您可以通过勾画未被标记的建筑物来帮助改进该数据库。 **点击 {button} 面按钮来添加一个新的区域。**", + "add_building": "OpenStreetMap 是世界上最大的建筑物数据库。{br}您可以通过勾画未被标记的建筑物来帮助改进该数据库。 **点击 {button} 区域按钮来添加一个新的区域。**", "start_building": "让我们通过勾画这个房屋的轮廓来添加它。{br}建筑物应该尽可能准确地勾画在他们的底部周围。 **点击或按空格键,在建筑物的一处角落放置一个起始节点。**", "continue_building": "继续在建筑物的轮廓上添加一些更多的节点。别忘您还可以放大地图来添加更多细节。{br}按回车键、或再次点击起始/结束节点来结束绘制建筑物。 **完成勾画建筑物的轮廓。**", "retry_building": "看起来您在建筑物角落上放置节点时遇到了困难。请重试!", @@ -1036,7 +1050,7 @@ "square_building": "如果能使您刚才创建的房屋拥有完美的直角那就更好了。 **点击 {button} 按钮使建筑物轮廓直角化。**", "retry_square": "您并未点击直角化按钮。请重试。", "done_square": "看见了建筑物的边角是如何规整的吗?让我们学习另一个有用的小技巧。", - "add_tank": "接下来我们将勾画这个圆形储罐的轮廓。 **点击 {button} 面按钮来添加一个新的区域。**", + "add_tank": "接下来我们将勾画这个圆形储罐的轮廓。 **点击 {button} 区域按钮来添加一个新的区域。**", "start_tank": "不用担心,您不需要画出一个完美的圆。只需要在储罐上画一个区域,使其节点接触到储罐的边缘。 **点击或按空格键,在储罐的边缘处放置一个起始节点。**", "continue_tank": "在其边缘处添加一些更多的节点。之后圆将会创建在您勾画的节点外部。{br}按回车键、或再次点击起始/结束节点来结束绘制该区域。 **完成勾画该储罐的轮廓。**", "search_tank": "**搜索 '{preset}' 。**", @@ -1496,7 +1510,7 @@ "label": "收取时间" }, "comment": { - "label": "修改集合注释", + "label": "变更集合注释", "placeholder": "请简要说明您的贡献 (必填)" }, "communication_multi": { @@ -1586,6 +1600,9 @@ "cycleway:right": "右侧" } }, + "dance/style": { + "label": "舞蹈类型" + }, "date": { "label": "日期" }, @@ -1648,9 +1665,15 @@ "forward": "向前" } }, + "dispensing": { + "label": "开处方药" + }, "display": { "label": "表盘显示类型" }, + "distance": { + "label": "总距离" + }, "dock": { "label": "类型" }, @@ -1691,6 +1714,9 @@ "except": { "label": "异常" }, + "faces": { + "label": "面数" + }, "fax": { "label": "传真", "placeholder": "+31 42 123 4567" @@ -1802,6 +1828,39 @@ "label": "篮圈数", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "花式骑术", + "options": { + "equestrian": "是", + "undefined": "否" + } + }, + "horse_riding": { + "label": "马背骑行", + "options": { + "horse_riding": "是", + "undefined": "否" + } + }, + "horse_scale": { + "label": "马背骑行难度", + "options": { + "common": "简单:没有难度或障碍。(默认)", + "critical": "临界:仅适用于有经验的骑手和马匹。有主要的障碍。需要仔细检查桥梁。", + "dangerous": "危险:仅适用于在天气好的时候,非常有经验的骑手和马匹。需要下马。", + "demanding": "谨慎:不平缓的路面,偶尔有困难的路径。", + "difficult": "困难:狭窄并裸露的路径。可能有需要跨越的障碍物和狭窄的通道。", + "impossible": "无法通行:不适合马匹的路径或桥梁。路径太过狭窄,有不足的支撑物,和如梯子般的障碍。会有生命危险。" + }, + "placeholder": "简单, 困难, 危险..." + }, + "horse_stables": { + "label": "骑马练习", + "options": { + "stables": "是", + "undefined": "否" + } + }, "iata": { "label": "IATA(国际航空运输协会)" }, @@ -1821,6 +1880,9 @@ "indoor": { "label": "室内" }, + "industrial": { + "label": "类型" + }, "information": { "label": "类型" }, @@ -1941,6 +2003,10 @@ "label": "限制速度", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "建议限速", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "可停留时间" }, @@ -1972,16 +2038,16 @@ "3": "困难(黑色钻石型)", "4": "极端困难(双重黑色钻石型)" }, - "placeholder": "简单,中等,困难..." + "placeholder": "简单, 中等, 困难..." }, "mtb/scale/uphill": { "label": "山地自行车上坡难度", "options": { - "0": "0:平均坡度小于10%时,有碎石/夯实的地面,没有障碍物", + "0": "0:平均坡度小于10%,有碎石/夯实的地面,没有障碍物", "1": "1:平均坡度小于15%,有碎石/夯实的地面,有些许障碍物", - "2": "2:平均坡度小于20,坚实的地面,拳头大的石头/树根", - "3": "3:平均坡度25%,多变的平面,拳头大的石头/树墙", - "4": "4:平均坡度小于30%时,很糟的路面状况,大石头/树墙", + "2": "2:平均坡度小于20%,坚实的地面,拳头大的石头/树根", + "3": "3:平均坡度小于25%,多变的平面,拳头大的石头/树墙", + "4": "4:平均坡度小于30%,很糟的路面状况,大石头/树墙", "5": "5:很陡,单车得牵行或扛车" }, "placeholder": "0, 1, 2, 3..." @@ -2321,7 +2387,7 @@ "very_bad": "轻量化:低负重越野车辆", "very_horrible": "越野专用:拖拉机,全地形越野车" }, - "placeholder": "轴承,轮胎,越野" + "placeholder": "轴承, 轮胎, 越野..." }, "social_facility": { "label": "类型" @@ -2462,7 +2528,7 @@ "grade4": "近柔性铺面:土壤,砂土与草地混合其他刚性材质", "grade5": "柔性铺面:只有土壤,砂土与草地" }, - "placeholder": "坚硬地面,硬物铺面,软铺面" + "placeholder": "坚硬地面, 硬物铺面, 软铺面..." }, "trade": { "label": "类型" @@ -2513,8 +2579,16 @@ "label": "类型", "placeholder": "默认" }, - "vending": { - "label": "商品类型" + "usage_rail": { + "label": "使用类型", + "options": { + "branch": "支线", + "industrial": "工业", + "main": "主线", + "military": "军用", + "test": "测试线", + "tourism": "观光线" + } }, "visibility": { "label": "能见度", @@ -2609,6 +2683,10 @@ "name": "广告牌", "terms": "广告牌,广告,牌" }, + "advertising/column": { + "name": "广告柱", + "terms": "广告,广告柱,广告亭,广告牌,柱" + }, "aerialway": { "name": "缆车线路" }, @@ -2755,14 +2833,14 @@ }, "amenity/bureau_de_change": { "name": "货币兑换", - "terms": "货币兑换" + "terms": "货币兑换,货币,兑换,外币,人民币,银行,钱,汇率,牌价" }, "amenity/bus_station": { "name": "公交车站 / 枢纽站" }, "amenity/cafe": { "name": "咖啡馆", - "terms": "咖啡厅,茶座,小餐馆,咖啡,小餐厅" + "terms": "咖啡,茶,咖啡厅,咖啡馆,茶座,摩卡,拿铁,馥芮白,玛奇朵,卡布奇诺,红茶,黄茶,清茶,青茶,绿茶,花茶,黑茶,白茶,乌龙,咖啡豆,餐馆,餐厅" }, "amenity/car_rental": { "name": "汽车租赁", @@ -2910,6 +2988,10 @@ "name": "图书馆", "terms": "图书馆" }, + "amenity/love_hotel": { + "name": "爱情宾馆", + "terms": "爱情,情趣,性爱,寻欢,爱情宾馆" + }, "amenity/marketplace": { "name": "市场", "terms": "市场,菜市场" @@ -2920,7 +3002,7 @@ }, "amenity/music_school": { "name": "音乐学校", - "terms": "音乐学校,艺术学校" + "terms": "音乐,乐曲,歌唱,唱歌,合唱,学校,学院,培训,艺术,学习" }, "amenity/nightclub": { "name": "夜总会", @@ -3112,46 +3194,70 @@ }, "amenity/vending_machine/cigarettes": { "name": "香烟售货机", - "terms": "香烟售货机,香烟贩卖机" + "terms": "香烟,烟草,售货,售卖,自助,付货,零售,贩卖,售货机,贩卖机" + }, + "amenity/vending_machine/coffee": { + "name": "咖啡售货机", + "terms": "咖啡,摩卡,拿铁,馥芮白,玛奇朵,卡布奇诺,咖啡豆,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机,饮品,饮料,æ°´" }, "amenity/vending_machine/condoms": { "name": "避孕套售货机", - "terms": "避孕套售货机,避孕套贩卖机" + "terms": "避孕套,安全套,避孕,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机" }, "amenity/vending_machine/drinks": { "name": "饮料售货机", - "terms": "饮料售货机,饮品售货机,饮品贩卖机" + "terms": "饮料,饮品,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机,æ°´,果汁,汽水,咖啡,奶茶,茶" + }, + "amenity/vending_machine/electronics": { + "name": "电器售货机", + "terms": "电器,电子,元件,器件,充电器,电线,充电线,插头,耳机,手机,平板,插头,插座,接口,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机" + }, + "amenity/vending_machine/elongated_coin": { + "name": "纪念币压制机", + "terms": "纪念币,硬币,压制,纪念品,零钱,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机" }, "amenity/vending_machine/excrement_bags": { "name": "粪便袋售货机", - "terms": "粪便袋售货机" + "terms": "粪便袋,粪便,屎,狗屎,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机" }, "amenity/vending_machine/feminine_hygiene": { "name": "女性卫生用品售货机", - "terms": "女,女性,避孕套,安全套,月经,棉条,卫生巾,卫生,私人,售货,售卖,贩卖,自助,自动,付货,零售" + "terms": "女,女性,避孕套,安全套,月经,棉条,卫生巾,卫生,私人,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机" + }, + "amenity/vending_machine/food": { + "name": "食物售货机", + "terms": "食物,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机,吃,食" + }, + "amenity/vending_machine/ice_cream": { + "name": "冰淇淋售货机", + "terms": "冰淇淋,冰激淋,冰激凌,冰淇凌,冷饮,雪糕,冰沙,冰砖,冰棒,棒冰,售货,售卖,贩卖,售货机,自助,自动,付货,零售" }, "amenity/vending_machine/news_papers": { "name": "报纸售货机" }, "amenity/vending_machine/newspapers": { - "name": "自动售报机", - "terms": "报,报纸,售货,售卖,自助,自动,付货,零售" + "name": "报纸售货机", + "terms": "报,报纸,售货,售卖,自助,自动,付货,零售,贩卖,售货机,贩卖机" }, "amenity/vending_machine/parcel_pickup_dropoff": { "name": "行李提取/装卸机", - "terms": "行李提取机,行李装卸机" + "terms": "行李,包裹,背包,提取,装卸,提取机,装卸机" }, "amenity/vending_machine/parking_tickets": { "name": "停车缴费机", - "terms": "停车缴费机,停车售票机" + "terms": "停车,停车场,ç¼´è´¹,售票,缴费机,售票机" }, "amenity/vending_machine/public_transport_tickets": { "name": "公共交通售票机", - "terms": "公共交通售票机" + "terms": "售票,车票,售票处,贩卖,售票机,售货机,自助,自动,票,票务,公共交通,公交,巴士,地铁,火车,电车,轮船,渡轮" + }, + "amenity/vending_machine/stamps": { + "name": "邮票售货机", + "terms": "邮票,邮局,邮费,售货,售卖,贩卖,售货机,自助,自动,付货,零售" }, "amenity/vending_machine/sweets": { "name": "零食售货机", - "terms": "零食贩卖机" + "terms": "零食,点心,小食,售货,售卖,贩卖,售货机,自助,自动,付货,零售,食物" }, "amenity/veterinary": { "name": "动物医院", @@ -3221,6 +3327,10 @@ "name": "跳楼机", "terms": "跳楼机,跳楼,自由落体,蹦极,太空梭,垂直极限,天地双雄,穿越云霄,大怒神,下落,下坠,坠落,跌落,高塔,飞天,游乐设施,游乐,游艺,娱乐,乐园,游乐园,主题乐园,儿童乐园,景点" }, + "attraction/maze": { + "name": "迷宫", + "terms": "迷宫,景点,旅游,游乐设施,游乐" + }, "attraction/pirate_ship": { "name": "海盗船", "terms": "海盗船,海盗,鬼魂,摆动,谷底,游乐设施,游乐,游艺,娱乐,乐园,游乐园,主题乐园,儿童乐园,景点" @@ -3288,6 +3398,10 @@ "name": "树篱", "terms": "树篱" }, + "barrier/kerb": { + "name": "路缘", + "terms": "路缘,路缘带,路肩,边缘,行车带,人行道,无障碍,公路,马路" + }, "barrier/kissing_gate": { "name": "单人转门", "terms": "单人转门" @@ -3328,6 +3442,10 @@ "name": "谷仓", "terms": "粮仓,畜棚,库房" }, + "building/boathouse": { + "name": "船库", + "terms": "船,船库,船坞,船屋,停船,仓库,码头,避风塘" + }, "building/bunker": { "name": "煤仓" }, @@ -3453,6 +3571,10 @@ "building/train_station": { "name": "列车站" }, + "building/transportation": { + "name": "公共交通建筑", + "terms": "公交,公共交通,终点站,总站,火车站,车站,交通,运输,大楼,建筑,建筑物" + }, "building/university": { "name": "大学建筑", "terms": "大学,建筑,教学楼,实验室,校舍,宿舍,学院,院校,大专,校园,学校,学习" @@ -3465,6 +3587,9 @@ "name": "宿营位", "terms": "宿营位,露营位,野营位,露营地,野营地,露营场,野营场,露营,野营,野营场地,露营场地,宿营地,宿营,扎营,帐篷,野外,荒野,郊野,郊外,度假" }, + "circular": { + "name": "信号控制环岛" + }, "club": { "name": "俱乐部", "terms": "俱乐部,社团,夜总会,会所,可乐部,社交,组织,娱乐,社区,会议,驿站,平台,会,汇,社会,文化,团体,会员" @@ -3618,6 +3743,10 @@ "name": "脚手架搭建工", "terms": "脚手架搭建工,搭脚手架的人" }, + "craft/sculptor": { + "name": "雕塑工作室", + "terms": "雕塑,雕塑家,工作室,手艺,工艺,艺术,艺术品,雕刻,石膏,树脂,粘土,黏土" + }, "craft/shoemaker": { "name": "鞋匠", "terms": "鞋匠,制鞋店" @@ -3791,6 +3920,10 @@ "name": "临终安养院", "terms": "临终,善终,安宁,宁养,安养,关怀,保守,疾病,病房,垂死,致命,癌症,晚期,末期,死亡,诊所,医院,医学,医疗,疗法,卫生" }, + "healthcare/laboratory": { + "name": "医学实验室", + "terms": "医学,医学院,实验室,实验,研究所,研究院,医疗,血" + }, "healthcare/midwife": { "name": "助产士", "terms": "接产,看产,助产,生育,妊娠,分娩,孕,产妇,稳婆,产婆,收生,执妈,婴儿,妇科,妇产科,诊所,医院,医学,医疗,疗法,卫生,护士" @@ -3902,7 +4035,8 @@ "terms": "公交,公交站,公交车,巴士,大巴,客车,车站,站台" }, "highway/pedestrian_line": { - "name": "步行街" + "name": "步行街", + "terms": "步行街,广场,人行道,步道,购物中心" }, "highway/primary": { "name": "主要道路", @@ -4136,7 +4270,8 @@ "terms": "废料场" }, "landuse/industrial/slaughterhouse": { - "name": "屠宰场" + "name": "屠宰场", + "terms": "å± å®°,屠宰场,宰杀,牲畜,牛,猪,鸡,羊,肉,禽" }, "landuse/landfill": { "name": "垃圾填埋区", @@ -4167,7 +4302,7 @@ "terms": "检查点,检查站,检查,边检" }, "landuse/military/danger_area": { - "name": "危险区域", + "name": "军事危险区域", "terms": "危险区" }, "landuse/military/naval_base": { @@ -4215,7 +4350,8 @@ "terms": "绿地" }, "landuse/religious": { - "name": "宗教场所" + "name": "宗教场所", + "terms": "宗教,国教,ä¿¡ä»°,崇拜,基督教,天主教,东正教,佛教,伊斯兰教,印度教,儒教,道教,神道教,本教,锡克教,场所" }, "landuse/residential": { "name": "居民区", @@ -4237,6 +4373,10 @@ "name": "成人街机厅", "terms": "成人街机厅,成人街机店" }, + "leisure/beach_resort": { + "name": "海滩度假区", + "terms": "海滩,沙滩,海岸,河滩,湖滨,沙子,沙,度假,度假区,游泳,冲浪" + }, "leisure/bird_hide": { "name": "观鸟点", "terms": "观鸟点,观鸟屋,鸟屋" @@ -4253,6 +4393,10 @@ "name": "舞厅", "terms": "舞厅,舞蹈,舞蹈房,舞池,跳舞" }, + "leisure/dancing_school": { + "name": "舞蹈学校", + "terms": "舞蹈,跳舞,舞,芭蕾,探戈,爵士,学校,学院,培训,拉丁舞,艺术,学习" + }, "leisure/dog_park": { "name": "狗公园", "terms": "狗公园,狗狗公园" @@ -4386,7 +4530,8 @@ "terms": "跑步,跑道,操场,跑" }, "leisure/sauna": { - "name": "桑拿" + "name": "桑拿", + "terms": "桑拿,桑拿房,桑拿浴,浴室,蒸汽,按摩" }, "leisure/slipway": { "name": "船台", @@ -4428,6 +4573,10 @@ "name": "坑道入口", "terms": "坑道入口,矿道入口" }, + "man_made/antenna": { + "name": "天线杆塔", + "terms": "天线,天线杆,天线塔,电话,通讯,手机,无线电,电视,广播,频道,电台,信号塔" + }, "man_made/breakwater": { "name": "防波堤", "terms": "避风塘,避风港" @@ -4475,6 +4624,10 @@ "name": "瞭望塔", "terms": "瞭望塔" }, + "man_made/observatory": { + "name": "天文台", + "terms": "天文台,天文,天象,天体,观测,气象台,瞭望台,望远镜,观星,星星,光学,射电" + }, "man_made/petroleum_well": { "name": "油井", "terms": "油井" @@ -4599,6 +4752,10 @@ "name": "荒野", "terms": "荒野" }, + "natural/mud": { + "name": "淤泥", + "terms": "æ³¥,淤泥,泥土,湿地,泥巴,淤渣,烂泥,土" + }, "natural/peak": { "name": "山峰", "terms": "山峰" @@ -4672,16 +4829,19 @@ "terms": "办公室,写字楼" }, "office/accountant": { - "name": "会计师事务所" + "name": "会计师事务所", + "terms": "会计,事务所,会计师,审计,会计,咨询,税务,è´¦" }, "office/administrative": { "name": "行政楼" }, "office/adoption_agency": { - "name": "领养中介" + "name": "领养中介", + "terms": "领养,收养,孤儿,孤儿院,留守" }, "office/advertising_agency": { - "name": "广告中介" + "name": "广告中介", + "terms": "广告,营销,中介,机构,市场营销,盈利,营利,传媒" }, "office/architect": { "name": "建筑事务所", @@ -4692,7 +4852,12 @@ "terms": "非盈利机构办公室" }, "office/charity": { - "name": "慈善机构" + "name": "慈善机构", + "terms": "慈善,公益,基金,基金会,捐款,机构,组织,非营利,非盈利,非公募" + }, + "office/company": { + "name": "企业公司", + "terms": "公司,企业,办公室" }, "office/coworking": { "name": "共享办公空间", @@ -4707,7 +4872,8 @@ "terms": "就业机构" }, "office/energy_supplier": { - "name": "电力公司" + "name": "电力公司", + "terms": "电力,电源,电,能源,煤气,天然气,电网,公司" }, "office/estate_agent": { "name": "地产代理", @@ -4718,7 +4884,8 @@ "terms": "金融机构" }, "office/forestry": { - "name": "林务管理" + "name": "林务管理", + "terms": "护林,林务,保护,林业,树林,森林,巡逻,林" }, "office/foundation": { "name": "基金办公室", @@ -4737,14 +4904,16 @@ "terms": "税局" }, "office/guide": { - "name": "导游机构" + "name": "导游机构", + "terms": "导游,旅行,旅行社,旅游,游览,潜水,登山,爬山" }, "office/insurance": { "name": "保险公司", "terms": "保险公司" }, "office/it": { - "name": "IT公司" + "name": "IT公司", + "terms": "电脑,信息,科技,信息科技,软件,工程,编程,计算机,公司,it" }, "office/lawyer": { "name": "律师事务所", @@ -4754,7 +4923,8 @@ "name": "公证处" }, "office/moving_company": { - "name": "搬家公司" + "name": "搬家公司", + "terms": "搬家,搬床,搬场,动迁,装修" }, "office/newspaper": { "name": "报社", @@ -4765,7 +4935,8 @@ "terms": "非政府组织" }, "office/notary": { - "name": "公证处" + "name": "公证处", + "terms": "公证,公证处,契约,保证,签名,学历,学位,成绩,刑事,婚姻,出生,委托,遗嘱,遗产,继承,声明,机构,抽奖,拍卖,证据" }, "office/physician": { "name": "医生" @@ -4775,17 +4946,20 @@ "terms": "政党" }, "office/private_investigator": { - "name": "私家侦探事务所" + "name": "私家侦探事务所", + "terms": "侦探,私家,私家侦探,私人,侦查,侦察,民商,调查,推理,行踪,诈骗,取证,警察,警官" }, "office/quango": { - "name": "准非政府组织" + "name": "准非政府组织", + "terms": "非政府,民意,民间,政府,组织,自治,自主,非盈利,非营利" }, "office/research": { "name": "研究所", "terms": "研究所" }, "office/tax_advisor": { - "name": "税务顾问机构" + "name": "税务顾问机构", + "terms": "税,税务,税收,经济,顾问,机构" }, "office/telecommunication": { "name": "电信办公室", @@ -4799,7 +4973,8 @@ "name": "旅行社" }, "office/water_utility": { - "name": "水务设施机构" + "name": "水务设施机构", + "terms": "水务,水源,设施,机构,æ°´,自来水,废水,污水" }, "piste": { "name": "滑雪道", @@ -5357,7 +5532,7 @@ }, "shop/coffee": { "name": "咖啡豆/粉店", - "terms": "咖啡豆店,咖啡粉店" + "terms": "咖啡,咖啡豆,咖啡粉,商店,摩卡,拿铁,馥芮白,玛奇朵,卡布奇诺" }, "shop/computer": { "name": "电脑店", @@ -5655,7 +5830,7 @@ }, "shop/tea": { "name": "茶叶商店", - "terms": "茶叶商店,茶店" + "terms": "茶,茶叶,茶店,茶品,红茶,黄茶,清茶,青茶,绿茶,花茶,黑茶,白茶,乌龙,商店" }, "shop/ticket": { "name": "售票处", @@ -5717,7 +5892,8 @@ "terms": "武器店" }, "shop/wholesale": { - "name": "批发市场" + "name": "批发市场", + "terms": "批发,市场,超市,商业,零售,商场,卖场,商城,商品,百货,服装,农贸,菜场,农场" }, "shop/window_blind": { "name": "百叶窗店", @@ -5820,7 +5996,8 @@ "terms": "景点" }, "tourism/wilderness_hut": { - "name": "野外住宿小屋" + "name": "野外住宿小屋", + "terms": "野外,郊野,荒郊,野营,宿营,营地,探险,旅游,小屋,木屋,草屋,屋,住宿" }, "tourism/zoo": { "name": "动物园", @@ -5883,31 +6060,35 @@ }, "type/restriction/no_left_turn": { "name": "禁止左转", - "terms": "禁止左转弯" + "terms": "左转,禁止左转,不许左转,允许右转,允许直行,允许掉头" }, "type/restriction/no_right_turn": { "name": "禁止右转", - "terms": "禁止右转弯" + "terms": "右转,禁止右转,不许右转,允许左转,允许直行,允许掉头" }, "type/restriction/no_straight_on": { "name": "禁止直行", - "terms": "禁止直行" + "terms": "直行,禁止直行,不许直行,允许左转,允许掉头,允许右转" }, "type/restriction/no_u_turn": { "name": "禁止掉头", - "terms": "禁止掉头" + "terms": "掉头,禁止掉头,不许掉头,允许左转,允许直行,允许右转" }, "type/restriction/only_left_turn": { - "name": "仅左转", - "terms": "仅左转" + "name": "仅限左转", + "terms": "左转,仅左转,大转,禁止右转,禁止直行,禁止掉头" }, "type/restriction/only_right_turn": { - "name": "仅右转", - "terms": "仅右转" + "name": "仅限右转", + "terms": "右转,仅右转,小转,禁止左转,禁止直行,禁止掉头" }, "type/restriction/only_straight_on": { - "name": "禁止转向", - "terms": "禁止转向" + "name": "仅限直行", + "terms": "直行,仅直行,禁止左转,禁止右转,禁止掉头" + }, + "type/restriction/only_u_turn": { + "name": "仅限掉头", + "terms": "掉头,仅掉头,禁止左转,禁止直行,禁止右转" }, "type/route": { "name": "线路", @@ -6070,7 +6251,7 @@ "attribution": { "text": "使用条款与意见反馈" }, - "description": "影像边界和拍摄日期。标签会在缩放到14层级或更高时显示。", + "description": "影像边界和拍摄日期。标签会在缩放到13层级或更高时显示。", "name": "DigitalGlobe 优质影像年份" }, "DigitalGlobe-Standard": { @@ -6084,7 +6265,7 @@ "attribution": { "text": "使用条款与意见反馈" }, - "description": "影像边界和拍摄日期。标签会在缩放到14层级或更高时显示。", + "description": "影像边界和拍摄日期。标签会在缩放到13层级或更高时显示。", "name": "DigitalGlobe 标准影像年份" }, "EsriWorldImagery": { @@ -6168,6 +6349,10 @@ "description": "黄色 = 来自美国人口调查局的公共领域地图数据。红色 = 在 OpenStreetMap 中找不到数据。", "name": "TIGER 道路 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "公路:绿色线框 = 未分级。棕色线框 = 未铺设路面。表面:沙砾 = 浅棕色填充,沥青 = 黑色,已铺设 = 灰色,土地 = 白色,混凝土 = 蓝色,草地 = 绿色。季节性 = 白色条状", + "name": "美国森林道路叠加层" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org, OpenStreetMap 贡献者, 署名-相同方式共享 3.0" @@ -6202,7 +6387,7 @@ "attribution": { "text": "basemap.at" }, - "description": "基于政府数据的奥地利底图", + "description": "基于政府数据的奥地利底图。", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6264,7 +6449,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "地图瓦片由 Stamen 设计,并以 署名 3.0 协议授权" + "text": "地图瓦片由 Stamen 设计,并以 署名 3.0 协议授权。数据由 OpenStreetMap 提供并采用开放数据共享开放数据库许可协议 (ODbL) 授权。" }, "name": "Stamen 地形" }, @@ -6280,6 +6465,499 @@ }, "name": "Thunderforest 地貌" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "海岸角大学 YouthMappers", + "description": "在 Twitter 上关注我们:{url}", + "extendedDescription": "此为加纳海岸角大学在 Youth Mappers 上的官方章节。我们热爱地图、开放数据以及帮助弱势群体。" + }, + "osm-gh-facebook": { + "name": "OpenStreetMap 加纳 Facebook 主页", + "description": "为对 OpenStreetMap 感兴趣的用户准备的 Facebook 小组。", + "extendedDescription": "位于加纳的绘图者社区,在加纳宣传 OpenStreetMap 以及人道主义 OpenStreetMap 团队 (HOT) 项目。加入我们。" + }, + "osm-gh-twitter": { + "name": "OpenStreetMap 加纳 Twitter 主页", + "description": "在 Twitter 上关注我们:{url}" + }, + "talk-gh": { + "name": "Talk-gh 邮件列表", + "description": "Talk-gh 是为加纳 OSM 社区准备的官方邮件列表" + }, + "osm-mg-facebook": { + "name": "OpenStreetMap 马达加斯加 Facebook 小组", + "description": "为对 OpenStreetMap 感兴趣的用户准备的马达加斯加 Facebook 小组。" + }, + "talk-mg": { + "name": "Talk-mg 邮件列表", + "description": "位于马达加斯加的 OpenStreetMap 贡献者、社区和用户分享和讨论的地方。" + }, + "OSM-BGD-facebook": { + "name": "OpenStreetMap 孟加拉国", + "description": "改进位于孟加拉国的 OpenStreetMap" + }, + "OSM-India-facebook": { + "name": "OpenStreetMap 印度 - 共同参与的街区绘图", + "description": "改进位于印度的 OpenStreetMap", + "extendedDescription": "在印度绘图?有任何疑问,想要与当地的社区交流?在 {Url} 加入我们。欢迎所有人!", + "events": { + "sotmasia2018": { + "name": "State of the Map 亚洲 2018", + "description": "加入位于印度的 State of the Map 亚洲的2018å¹´ OpenStreetMap 地区活动。", + "where": "印度管理学院,印度班加罗尔" + } + } + }, + "OSM-india-mailinglist": { + "name": "OpenStreetMap 印度邮件列表", + "description": "Talk-in 是为印度社区准备的官方邮件列表" + }, + "OSM-india-twitter": { + "name": "OpenStreetMap 印度 Twitter", + "description": "我们之间仅差一条推文:{url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "自由软硬件运动 (FSHM) - Facebook", + "description": "在 FSHM Facebook 主页上了解更多社区事件和活动" + }, + "OSM-India-Puducherry-Matrix": { + "name": "自由软硬件运动 (FSHM) - Matrix" + }, + "OSM-IDN-facebook": { + "name": "OpenStreetMap 印度尼西亚", + "description": "改进位于印度尼西亚的 OpenStreetMap", + "extendedDescription": "在印度尼西亚绘图?有任何疑问,想要与当地的社区交流?在 {Url} 加入我们。欢迎所有人!" + }, + "OSM-japan-facebook": { + "name": "OpenStreetMap 日本社区", + "description": "在日本的绘图者和 OpenStreetMap 用户" + }, + "OSM-japan-mailinglist": { + "name": "OpenStreetMap 日本邮件列表", + "description": "Talk-ja 是为日本社区准备的官方邮件列表" + }, + "OSM-japan-twitter": { + "name": "OpenStreetMap 日本 Twitter", + "description": "Twitter 上的#标签:{url}" + }, + "OSM-MY-forum": { + "name": "OpenStreetMap 马来西亚论坛", + "description": "官方 OpenStreetMap 马来西亚论坛" + }, + "OSM-MY-matrix": { + "name": "OpenStreetMap 马来西亚 Riot 频道", + "description": "欢迎所有的绘图者!在 {signupUrl} 上注册。" + }, + "OSM-MNG-facebook": { + "name": "OpenStreetMap 蒙古", + "description": "改进位于蒙古的 OpenStreetMap", + "extendedDescription": "在蒙古绘图?有任何疑问,想要与当地的社区交流?在 {Url} 加入我们。欢迎所有人!" + }, + "OSM-MMR-facebook": { + "name": "OpenStreetMap 缅甸", + "description": "改进位于缅甸的 OpenStreetMap", + "extendedDescription": "在缅甸绘图?有任何疑问,想要与当地的社区交流?在 {Url} 加入我们。欢迎所有人!" + }, + "OSM-Nepal-facebook": { + "name": "OpenStreetMap 尼泊尔", + "description": "改进位于尼泊尔的 OpenStreetMap", + "extendedDescription": "在尼泊尔绘图?有任何疑问,想要与当地的社区交流?在 {Url} 加入我们。欢迎所有人!" + }, + "OSM-PH-facebook": { + "name": "OpenStreetMap 菲律宾 Facebook" + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph 邮件列表", + "description": "讨论在菲律宾 OpenStreetMap 的邮件列表" + }, + "OSM-PH-slack": { + "name": "OpenStreetMap 菲律宾 Slack", + "description": "欢迎所有人加入!在 {signupUrl} 上注册。" + }, + "OSM-PH-telegram": { + "name": "OpenStreetMap 菲律宾 Telegram", + "description": "为在菲律宾的 OpenStreetMap 贡献者和伙伴们准备的非官方 Telegram 本地社区" + }, + "OSM-RU-forum": { + "name": "OpenStreetMap 俄罗斯论坛", + "description": "OpenStreetMap 俄罗斯网络论坛" + }, + "OSM-RU-telegram": { + "name": "OpenStreetMap 俄罗斯 Telegram", + "description": "OpenStreetMap 俄罗斯 Telegram 交流" + }, + "OSM-LKA-facebook": { + "name": "OpenStreetMap 斯里兰卡", + "description": "改进位于斯里兰卡的 OpenStreetMap", + "extendedDescription": "在斯里兰卡绘图?有任何疑问,想要与当地的社区交流?在 {Url} 加入我们。欢迎所有人!" + }, + "OSM-TW-facebook": { + "name": "OpenStreetMap 台湾社区", + "description": "绘图者和 OpenStreetMap 用户用以讨论中国台湾省事务的 Facebook 小组。" + }, + "OSM-TW-mailinglist": { + "name": "OpenStreetMap 台湾邮件列表", + "description": "Talk-tw 是社区讨论关于中国台湾省事务的官方邮件列表" + }, + "at-forum": { + "name": "OpenStreetMap 奥地利论坛" + }, + "at-mailinglist": { + "name": "Talk-at 邮件列表", + "description": "Talk-at 是奥地利 OpenStreetMap 社区的官方邮件列表" + }, + "at-twitter": { + "name": "OpenStreetMap 奥地利 Twitter", + "description": "OpenStreetMap 奥地利 Twitter 主页:{url}" + }, + "osmgraz-twitter": { + "name": "OSM 格拉茨社区 Twitter 主页", + "description": "OpenStreetMap 格拉茨社区 Twitter 主页" + }, + "osm-at": { + "name": "OpenStreetMap 奥地利", + "description": "位于奥地利的 OpenStreetMap 信息平台" + }, + "byosm": { + "name": "OpenStreetMap 白俄罗斯", + "description": "OpenStreetMap 白俄罗斯 Telegram 交流" + }, + "be-facebook": { + "name": "OpenStreetMap 比利时社区" + }, + "be-forum": { + "name": "OpenStreetMap 比利时论坛", + "description": "OpenStreetMap 比利时网络论坛" + }, + "be-mailinglist": { + "name": "Talk-be 邮件列表" + }, + "be-twitter": { + "name": "OpenStreetMap 比利时 Twitter" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz 邮件列表", + "description": "Talk-cz 是捷克 OpenStreetMap 社区的官方邮件列表" + }, + "fr-facebook": { + "name": "OpenStreetMap 法国 Facebook 主页", + "description": "OpenStreetMap 法国 Facebook 主页" + }, + "fr-forum": { + "name": "OpenStreetMap 法国网络论坛", + "description": "OpenStreetMap 法国网络论坛" + }, + "fr-irc": { + "name": "OpenStreetMap 法国 IRC", + "description": "在 irc.oftc.net (端口 6667) 加入 #osm-fr" + }, + "fr-mailinglist": { + "name": "Talk-fr 邮件列表", + "description": "Talk-fr 邮件列表" + }, + "fr-twitter": { + "name": "OpenStreetMap 法国 Twitter 主页", + "description": "OpenStreetMap 法国 Twitter 主页:{url}" + }, + "de-berlin-mailinglist": { + "name": "柏林邮件列表", + "description": "此为柏林 OSM 社区的邮件列表" + }, + "de-berlin-meetup": { + "name": "OpenStreetMap 柏林-勃兰登堡见面会", + "description": "位于柏林区域的绘图者和 OpenStreetMap 用户" + }, + "de-berlin-telegram": { + "name": "@osmberlin Telegram 主页", + "description": "OpenStreetMap 柏林 Telegram 交流" + }, + "de-berlin-twitter": { + "name": "OpenStreetMap 柏林 Twitter", + "description": "在 Twitter 上关注我们:{url}" + }, + "de-forum": { + "name": "OpenStreetMap 德国论坛", + "description": "OpenStreetMap 德国网络论坛" + }, + "de-irc": { + "name": "OpenStreetMap 德国 IRC", + "description": "在 irc.oftc.net (端口 6667) 加入 #osm-de" + }, + "de-mailinglist": { + "name": "Talk-de 邮件列表", + "description": "Talk-de 是德国 OpenStreetMap 社区的官方邮件列表" + }, + "osm-de": { + "name": "OpenStreetMap 德国", + "description": "位于德国的 OpenStreetMap 信息平台" + }, + "it-facebook": { + "name": "OpenStreetMap 意大利 Facebook", + "description": "在 Facebook 上加入 OpenStreetMap 意大利社区" + }, + "it-irc": { + "name": "OpenStreetMap 意大利 IRC", + "description": "在 irc.oftc.net (端口 6667) 加入 #osm-it" + }, + "it-mailinglist": { + "name": "Talk-it 邮件列表", + "description": "Talk-it 是意大利 OpenStreetMap 社区的官方邮件列表" + }, + "it-twitter": { + "name": "OpenStreetMap 意大利 Twitter", + "description": "在 Twitter 上关注我们:{url}" + }, + "OSM-Rome-meetup": { + "description": "在罗马地区改进 OpenStreetMap" + }, + "South-Tyrol-Mailing-List": { + "name": "南蒂罗尔 OpenStreetMap 邮件列表" + }, + "talk-it-lazio": { + "name": "OpenStreetMap 意大利拉齐奥", + "description": "欢迎所有人加入!在 {signupUrl} 上注册。", + "extendedDescription": "罗马和拉齐奥大区的邮件列表" + }, + "Trentino-Mailing-List": { + "name": "特伦蒂诺 OpenStreetMap 邮件列表" + }, + "no-forum": { + "name": "OpenStreetMap 挪威网络论坛", + "description": "OpenStreetMap 挪威网络论坛" + }, + "no-irc": { + "name": "OpenStreetMap 挪威 IRC" + }, + "no-mailinglist": { + "name": "OpenStreetMap 挪威邮件列表", + "description": "为位于挪威的绘图者和 OpenStreetMap 用户、开发者与爱好者准备的邮件列表" + }, + "OSM-PL-facebook-group": { + "name": "OpenStreetMap 波兰 Facebook 小组" + }, + "OSM-ES-mailinglist": { + "name": "Talk-es 邮件列表", + "description": "讨论在西班牙 OpenStreetMap 的邮件列表" + }, + "OSM-ES-telegram": { + "name": "@OSMes Telegram 主页", + "description": "OpenStreetMap 西班牙 Telegram 交流" + }, + "osm-se": { + "name": "OpenStreetMap.se" + }, + "se-facebook": { + "name": "OpenStreetMap 瑞典 Facebook", + "description": "OpenStreetMap 瑞典 Facebook 主页" + }, + "se-forum": { + "name": "OpenStreetMap 瑞典网络论坛", + "description": "OpenStreetMap 瑞典网络论坛" + }, + "se-irc": { + "name": "OpenStreetMap 瑞典 IRC", + "description": "在 irc.oftc.net (端口 6667) 加入 #osm.se" + }, + "se-mailinglist": { + "name": "Talk-se 邮件列表", + "description": "讨论在瑞典 OpenStreetMap 的邮件列表" + }, + "se-twitter": { + "name": "OpenStreetMap 瑞典 Twitter 页面", + "description": "在 Twitter 上关注我们:{url}" + }, + "Nottingham-OSM-pub-meetup": { + "name": "东米德兰(诺丁汉)月度酒吧见面会", + "description": "东米德兰绘图者和用户的社交聚会", + "extendedDescription": "该小组自2011å¹´3月开始举行会议,地点最初在诺丁汉,近几年在德比,或不时在东米德兰的其他地方举行。这些虽是社交聚会,但却是来询问涉及地区或只是普通的 OSM 特定问题的好地方。在夏季,我们通常会在会场附近进行一小时的小型测绘。整个团队都对关于公共优先权的测绘有着特殊的兴趣,并且不时为此而召开绘图会议。" + }, + "gb-mailinglist": { + "name": "Talk-gb 邮件列表", + "description": "Talk-gb 是英国(包括北爱尔兰) OSM 社区的主要交流论坛" + }, + "gb-irc": { + "name": "OpenStreetMap 英国 IRC", + "description": "在 irc.oftc.net (端口 6667) 加入 #osm-gb" + }, + "OSM-CA-Slack": { + "name": "OSM-CA Slack", + "description": "欢迎所有人加入!在 {signupUrl} 上注册。" + }, + "OSM-Vancouver-meetup": { + "name": "OpenStreetMap 温哥华", + "description": "位于不列颠哥伦比亚省温哥华的绘图者和 OpenStreetMap 用户" + }, + "OSM-US-Slack": { + "name": "OpenStreetMap 美国 Slack", + "description": "欢迎所有人加入!在 {signupUrl} 上注册。" + }, + "OSM-US": { + "name": "OpenStreetMap 美国", + "description": "我们助长并改善位于美国的 OpenStreetMap。", + "extendedDescription": "我们通过召开年度会议、提供社区资源、建立合伙关系以及推广来支持 OpenStreetMap。在此处加入 OpenStreetMap 美国:{signupUrl}" + }, + "OSM-Utah": { + "name": "OpenStreetMap 犹他州", + "description": "位于盐湖城区域的绘图者和 OpenStreetMap 用户" + }, + "OSM-Wyoming": { + "name": "OpenStreetMap 怀俄明州", + "description": "位于怀俄明州的绘图者和 OpenStreetMap 用户" + }, + "PHXGeo-twitter": { + "name": "PHXGeo Twitter", + "description": "在 Twitter 上关注我们:{url}" + }, + "Western-Slope-facebook": { + "name": "西坡 OSM Facebook" + }, + "Maptime-Australia-Slack": { + "name": "Maptime 澳大利亚 Slack", + "description": "在 {signupUrl} 上注册" + }, + "talk-au": { + "name": "Talk-au 邮件列表", + "description": "澳大利亚绘图者交流的地方" + }, + "OSM-AR-facebook": { + "name": "OpenStreetMap 阿根廷 Facebook", + "description": "在 Facebook 上加入 OpenStreetMap 阿根廷社区", + "extendedDescription": "当地社区的新闻" + }, + "OSM-AR-forum": { + "name": "OpenStreetMap 阿根廷网络论坛", + "description": "加入 OpenStreetMap 阿根廷网络论坛", + "extendedDescription": "长篇或重要讨论的理想地。回应时间较慢。" + }, + "OSM-AR-irc": { + "name": "OpenStreetMap 阿根廷 IRC", + "description": "在 irc.oftc.net (端口 6667) 加入 #osm-ar", + "extendedDescription": "您可以在社区中找到最为极客的用户。" + }, + "OSM-AR-mailinglist": { + "name": "Talk-ar 邮件列表", + "description": "历史邮件列表。如今几乎不再使用。" + }, + "OSM-AR-telegram": { + "name": "OpenStreetMap 阿根廷 Telegram", + "description": "在 Telegram 上加入 OpenStreetMap 阿根廷社区", + "extendedDescription": "全社区最活跃的频道,专为聊天和问题速答而准备。欢迎每个人加入!" + }, + "OSM-AR-twitter": { + "name": "OpenStreetMap 阿根廷 Twitter", + "description": "在 Twitter 上关注我们:{url}", + "extendedDescription": "当地社区和 OpenStreetMap 大体的新闻" + }, + "OSM-BO-mailinglist": { + "name": "Talk-bo 邮件列表", + "description": "Talk-bo 是玻利维亚 OpenStreetMap 社区的官方邮件列表", + "extendedDescription": "在玻利维亚绘图?有任何疑问,想要与当地的社区交流?在 {Url} 加入我们。欢迎所有人!" + }, + "Bahia-telegram": { + "name": "OpenStreetMap 巴伊亚 Telegram 小组", + "description": "在 Telegram 上加入 OpenStreetMap 巴伊亚社区", + "extendedDescription": "加入社区来了解更多 OpenStreetMap,在会议中提问或者参与。欢迎每个人的到来!" + }, + "OSM-br-mailinglist": { + "name": "Talk-br 邮件列表", + "description": "讨论在巴西 OpenStreetMap 的邮件列表" + }, + "OSM-br-telegram": { + "name": "OpenStreetMap 巴西 Telegram", + "description": "在 Telegram 上加入 OpenStreetMap 巴西社区", + "extendedDescription": "加入社区来了解更多 OpenStreetMap,在会议中提问或者参与。欢迎每个人的到来!" + }, + "OSM-br-twitter": { + "name": "OpenStreetMap 巴西 Twitter", + "description": "在 Twitter 上关注我们:{url}" + }, + "OSM-CL-facebook": { + "name": "OpenStreetMap 智利 Facebook", + "description": "在 Facebook 上加入 OpenStreetMap 智利社区", + "extendedDescription": "加入社区来了解更多 OpenStreetMap,在会议中提问或者参与。欢迎每个人的到来!" + }, + "OSM-CL-mailinglist": { + "name": "Talk-cl 邮件列表", + "description": "讨论在智利 OpenStreetMap 的邮件列表" + }, + "OSM-CL-telegram": { + "name": "OpenStreetMap 智利 Telegram", + "description": "在 Telegram 上加入 OpenStreetMap 智利社区", + "extendedDescription": "加入社区来了解更多 OpenStreetMap,在会议中提问或者参与。欢迎每个人的到来!" + }, + "OSM-CL-twitter": { + "name": "OpenStreetMap 智利 Twitter", + "description": "在 Twitter 上关注我们:{url}" + }, + "OSM-CO-facebook": { + "name": "OpenStreetMap 哥伦比亚 Facebook", + "description": "在 Facebook 上加入 OpenStreetMap 哥伦比亚社区", + "extendedDescription": "加入社区来了解更多 OpenStreetMap。欢迎每个人的到来!" + }, + "OSM-CO-mailinglist": { + "name": "Talk-co 邮件列表", + "description": "讨论在哥伦比亚 OpenStreetMap 的邮件列表" + }, + "OSM-CO-twitter": { + "name": "OpenStreetMap 哥伦比亚 Twitter", + "description": "在 Twitter 上关注我们:{url}" + }, + "OSM-CO": { + "name": "OpenStreetMap 哥伦比亚", + "description": "关于 OpenStreetMap 哥伦比亚社区和 OSMCo 基金会的新闻" + }, + "OSM-PE-facebook": { + "name": "OpenStreetMap 秘鲁 Facebook", + "description": "在 Facebook 上加入 OpenStreetMap 秘鲁社区" + }, + "OSM-PE-mailinglist": { + "name": "Talk-pe 邮件列表", + "description": "OpenStreetMap 秘鲁社区官方邮件列表" + }, + "OSM-PE-matrix": { + "name": "OpenStreetMap 秘鲁 Matrix 交流", + "description": "在 Matrix 上与 OpenStreetMap 秘鲁社区的其他成员交流。" + }, + "OSM-PE-telegram": { + "name": "OpenStreetMap 秘鲁 Telegram", + "description": "在 Telegram 上加入 OpenStreetMap 秘鲁社区" + }, + "OSM-PE-twitter": { + "name": "OpenStreetMap 秘鲁 Twitter", + "description": "在 Twitter 上关注我们:{url}" + }, + "OSM-PE": { + "name": "OpenStreetMap 秘鲁", + "description": "关于 OpenStreetMap 秘鲁社区的新闻和资源" + }, + "OSM-Facebook": { + "name": "OpenStreetMap Facebook 主页", + "description": "在 Facebook 上喜欢我们并接收关于 OpenStreetMap 新闻和更新。" + }, + "OSM-help": { + "name": "OpenStreetMap 帮助", + "description": "在 OSM 社区驱动的问答网站上提问并得到解答。", + "extendedDescription": "{url} 为所有人提供关于 OpenStreetMap 的帮助。无论您是新手绘图者或者有任何技术问题,都来找我们帮助吧!" + }, + "OSM-Reddit": { + "name": "OpenStreetMap Reddit 社区", + "description": "/r/openstreetmap/ 是了解更多关于 OpenStreetMap 的好地方。来尽管问我们吧!" + }, + "OSM-Twitter": { + "name": "OpenStreetMap Twitter 主页", + "description": "在 Twitter 上关注我们:{url}" + }, + "OSMF": { + "name": "OpenStreetMap 基金会 (OSMF)", + "description": "OSMF 是总部位于英国的非盈利组织,用于支持 OpenStreetMap 项目。", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "where": "意大利米兰" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/zh-HK.json b/vendor/assets/iD/iD/locales/zh-HK.json index b5ce2e54c..4b2c9d851 100644 --- a/vendor/assets/iD/iD/locales/zh-HK.json +++ b/vendor/assets/iD/iD/locales/zh-HK.json @@ -1,5 +1,8 @@ { "zh-HK": { + "icons": { + "information": "資訊" + }, "modes": { "add_area": { "title": "範圍", @@ -160,7 +163,6 @@ "annotation": "合併{n}個特徵。", "not_eligible": "不能合併這些特徵。", "not_adjacent": "這些特徵不能合併因為它們的端點不是連接在一起。", - "restriction": "這些特徵不能合併因為最少一個是\"{relation}\" 關係的構件。", "incomplete_relation": "這些特徵不能合併因為最少一個尚未完全下載。", "conflicting_tags": "這些特徵不能合併因為當中一些標籤的數值有衝突。" }, @@ -288,6 +290,21 @@ } } }, + "restriction": { + "help": { + "indirect": "(間接)", + "turn": { + "no_left_turn": "不准左轉 {indirect}", + "no_right_turn": "不准右轉 {indirect}", + "no_u_turn": "不准掉頭 {indirect}", + "no_straight_on": "不准直行 {indirect}", + "only_left_turn": "只准左轉 {indirect}", + "only_right_turn": "只准右轉 {indirect}", + "only_u_turn": "只准掉頭 {indirect}", + "only_straight_on": "只准直行 {indirect}" + } + } + }, "undo": { "tooltip": "還原:{action}", "nothing": "沒有可還原的動作。" @@ -456,8 +473,15 @@ "switch": "切換回這個背景", "custom": "自訂", "custom_button": "編輯自訂背景", + "overlays": "覆蓋層", "reset": "重設", + "display_options": "顯示選項", + "brightness": "亮度", + "contrast": "對比", + "saturation": "飽和度", + "sharpness": "銳利度", "minimap": { + "description": "顯示小地圖", "tooltip": "顯示縮小地圖以確定現在被顯示範圍的位置", "key": "/" }, @@ -582,13 +606,7 @@ } }, "success": { - "edited_osm": "已編輯了OSM!", "just_edited": "你剛剛編輯了OpenStreetMap!", - "view_on_osm": "於OSM上顯示", - "facebook": "分享至 Facebook", - "twitter": "分享至 Twitter", - "google": "分享至 Google+", - "help_html": "你的變更會在幾分鐘後出現在標準圖層。其他圖層或某些特徵可能需要多些時間。", "help_link_text": "詳細資料", "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" }, @@ -654,6 +672,9 @@ "mapillary": { "view_on_mapillary": "在Mapillary上觀看這影像" }, + "openstreetcam_images": { + "title": "相片重疊 (OpenStreetCam)" + }, "openstreetcam": { "view_on_openstreetcam": "在 OpenStreetCam 上觀看這影像" }, @@ -1311,6 +1332,9 @@ "brand": { "label": "品牌" }, + "brewery": { + "label": "生啤" + }, "bridge": { "label": "種類", "placeholder": "預設" @@ -1450,6 +1474,9 @@ "cycleway:right": "右側" } }, + "dance/style": { + "label": "舞蹈風格" + }, "date": { "label": "日期" }, @@ -1472,6 +1499,41 @@ "diaper": { "label": "設有換片設備" }, + "direction": { + "label": "方向 (順時針度數)", + "placeholder": "45, 90, 180, 270" + }, + "direction_cardinal": { + "label": "方向", + "options": { + "E": "東", + "ENE": "東北偏東", + "ESE": "東南偏東", + "N": "北", + "NE": "東北", + "NNE": "東北偏北", + "NNW": "西北偏北", + "NW": "西北", + "S": "南", + "SE": "東南", + "SSE": "東南偏南", + "SSW": "西南偏南", + "SW": "西南", + "W": "西", + "WNW": "西北偏西", + "WSW": "西南偏西" + } + }, + "direction_clock": { + "label": "方向", + "options": { + "anticlockwise": "逆時針", + "clockwise": "順時針" + } + }, + "direction_vertex": { + "label": "方向" + }, "display": { "label": "顯示" }, @@ -1765,6 +1827,9 @@ "label": "速度限制", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "可停留時間" }, @@ -1914,7 +1979,6 @@ "placeholder": "1, 2, 3..." }, "phone": { - "label": "電話", "placeholder": "+852 12345678" }, "piste/difficulty": { @@ -2309,9 +2373,6 @@ "label": "種類", "placeholder": "預設" }, - "vending": { - "label": "貨品種類" - }, "visibility": { "label": "可見度", "options": { @@ -2519,6 +2580,10 @@ "name": "茶座", "terms": "Cafe,㗎啡室,㗎啡廳,咖啡,咖啡室,咖啡廳,茶座" }, + "amenity/car_pooling": { + "name": "汽車共乘", + "terms": "Car Pooling, 汽車共乘" + }, "amenity/car_rental": { "name": "汽車租賃", "terms": "Car Rental,汽車租賃處,租車,租車店,租車舖" @@ -2665,6 +2730,10 @@ "name": "圖書館", "terms": "Library,圖書館" }, + "amenity/love_hotel": { + "name": "愛情酒店", + "terms": "Love Hotel, 時鐘酒店" + }, "amenity/marketplace": { "name": "街市", "terms": "Marketplace,市場,菜市場,街市" @@ -2673,6 +2742,10 @@ "name": "電單車停車位", "terms": "摩托車停車場,電單車停車場" }, + "amenity/music_school": { + "name": "音樂學校", + "terms": "Music School, 音樂學校" + }, "amenity/nightclub": { "name": "夜總會", "terms": "夜店" @@ -2772,6 +2845,10 @@ "name": "郊野公園遊客中心", "terms": "Ranger Station,郊野公園管理站,郊野公園訪客中心" }, + "amenity/recycling": { + "name": "回收桶", + "terms": "Recycling Container, 回收箱" + }, "amenity/recycling_centre": { "name": "回收中心", "terms": "Recycling Center, 廢物回收中心, 資源回收中心" @@ -2802,6 +2879,10 @@ "name": "淋浴處", "terms": "Shower,淋浴間,沖浴間" }, + "amenity/smoking_area": { + "name": "吸煙區", + "terms": "Smoking Area, 食煙區" + }, "amenity/social_facility": { "name": "社會服務設施", "terms": "社福設施" @@ -3035,6 +3116,10 @@ "name": "樹籬", "terms": "Hedge,樹籬" }, + "barrier/kerb": { + "name": "路緣", + "terms": "Kerb, 路邊石, 路緣石, 路邊" + }, "barrier/kissing_gate": { "name": "單人轉門 ", "terms": "Kissing Gate,單人轉門" @@ -3075,6 +3160,14 @@ "name": "穀倉", "terms": "穀倉,糧倉" }, + "building/boathouse": { + "name": "船屋", + "terms": "Boathouse, 船屋" + }, + "building/bungalow": { + "name": "平房", + "terms": "Bungalow, 平房, 別墅" + }, "building/bunker": { "name": "地堡" }, @@ -3094,6 +3187,10 @@ "name": "教堂建築物", "terms": "教堂,聖堂" }, + "building/civic": { + "name": "公民建築物", + "terms": "Civic Building, 市民建築物" + }, "building/college": { "name": "學院校舍", "terms": "學院建築,學院建築物,技術學院建築" @@ -3117,6 +3214,14 @@ "building/entrance": { "name": "入口/出口" }, + "building/farm": { + "name": "農舍", + "terms": "Farm House, 農莊" + }, + "building/farm_auxiliary": { + "name": "農場建築物", + "terms": "Farm Building, 農場建築物" + }, "building/garage": { "name": "車庫", "terms": "Garage,車房" @@ -3153,6 +3258,10 @@ "name": "學前照顧/幼稚園建築物", "terms": "幼兒園校舍,幼稚園校舍" }, + "building/mosque": { + "name": "清真寺建築物", + "terms": "Mosque Building, 清真寺建築物" + }, "building/public": { "name": "公共建築物", "terms": "公用建築物" @@ -3169,6 +3278,10 @@ "name": "上蓋", "terms": "屋頂" }, + "building/ruins": { + "name": "建築物遺蹟", + "terms": "Building Ruins, 建築物遺址" + }, "building/school": { "name": "校舍", "terms": "學校建築物,小學建築物,中學建築物" @@ -4582,6 +4695,38 @@ "name": "變壓器", "terms": "Transformer,火牛房,變電所" }, + "public_transport/station_tram": { + "name": "電車站", + "terms": "Tram Station, 電車大站" + }, + "public_transport/stop_area": { + "name": "交通工具停站範圍", + "terms": "Transit Stop Area, 交通工具停站範圍" + }, + "public_transport/stop_position": { + "name": "交通工具停止位置", + "terms": "Transit Stopping Location, 交通工具停止位置" + }, + "public_transport/stop_position_aerialway": { + "name": "纜車停止位置", + "terms": "Aerialway Stopping Location, 纜車停止位置" + }, + "public_transport/stop_position_bus": { + "name": "巴士停止位置", + "terms": "Bus Stopping Location, 巴士停止位置" + }, + "public_transport/stop_position_ferry": { + "name": "渡輪停止位置", + "terms": "Ferry Stopping Location, 小輪停止位置" + }, + "public_transport/stop_position_light_rail": { + "name": "輕鐵停止位置", + "terms": "Light Rail Stopping Location, 輕鐵停止位置" + }, + "public_transport/stop_position_monorail": { + "name": "單軌電車停止位置", + "terms": "Monorail Stopping Location, 單軌電車停止位置" + }, "railway": { "name": "鐵路" }, @@ -5300,18 +5445,6 @@ "name": "不准掉頭", "terms": "禁止掉頭" }, - "type/restriction/only_left_turn": { - "name": "只准左轉", - "terms": "只能左轉" - }, - "type/restriction/only_right_turn": { - "name": "只准右轉", - "terms": "只准右轉" - }, - "type/restriction/only_straight_on": { - "name": "只准直駛", - "terms": "禁止轉彎" - }, "type/route": { "name": "路綫", "terms": "Route,路綫,路線" @@ -5344,6 +5477,10 @@ "name": "策騎路線", "terms": "騎馬路線" }, + "type/route/light_rail": { + "name": "輕鐵路綫", + "terms": "Light Rail Route, 輕鐵路線" + }, "type/route/pipeline": { "name": "管道路綫", "terms": "Pipeline Route,供水路綫,供水路線,水管路綫,管道路線" @@ -5453,7 +5590,6 @@ "attribution": { "text": "條款和意見" }, - "description": "航攝邊界及拍攝日期。標籤會在縮放第14級或更高時顯示。", "name": "DigitalGlobe Premium 舊航攝圖" }, "DigitalGlobe-Standard": { @@ -5467,7 +5603,6 @@ "attribution": { "text": "條款和意見" }, - "description": "航攝邊界及拍攝日期。標籤會在縮放水平14或以上時顯示。", "name": "DigitalGlobe Standard 舊航攝圖" }, "EsriWorldImagery": { @@ -5477,6 +5612,13 @@ "description": "Esri world 世界航攝圖", "name": "Esri world 世界航攝圖" }, + "EsriWorldImageryClarity": { + "attribution": { + "text": "條款和意見" + }, + "description": "Esri 之前的航攝圖可能比預設圖層會更清楚和更準確。", + "name": "Esri World (Clarity) Beta 航攝圖" + }, "MAPNIK": { "attribution": { "text": "© OpenStreetMap 貢獻者,CC-BY-SA" @@ -5545,25 +5687,39 @@ "name": "TIGER Roads 2017" }, "Waymarked_Trails-Cycling": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap 貢獻者,CC by-SA 3.0" + }, "name": "Waymarked Trails: 單車" }, "Waymarked_Trails-Hiking": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap 貢獻者,CC by-SA 3.0" + }, "name": "Waymarked Trails: 遠足" }, "Waymarked_Trails-MTB": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap 貢獻者,CC by-SA 3.0" + }, "name": "Waymarked Trails: 越野單車" }, "Waymarked_Trails-Skating": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap 貢獻者,CC by-SA 3.0" + }, "name": "Waymarked Trails: 溜冰" }, "Waymarked_Trails-Winter_Sports": { + "attribution": { + "text": "© waymarkedtrails.org, OpenStreetMap 貢獻者,CC by-SA 3.0" + }, "name": "Waymarked Trails: 冬季運動" }, "basemap.at": { "attribution": { "text": "basemap.at" }, - "description": "基於政府資料的奧地利底圖。", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -5624,9 +5780,6 @@ "name": "skobbler" }, "stamen-terrain-background": { - "attribution": { - "text": "Stamen 設計的區塊,以 CC-BY 3.0 授權" - }, "name": "Stamen 地形" }, "tf-cycle": { diff --git a/vendor/assets/iD/iD/locales/zh-TW.json b/vendor/assets/iD/iD/locales/zh-TW.json index 80860cde6..b57e420c1 100644 --- a/vendor/assets/iD/iD/locales/zh-TW.json +++ b/vendor/assets/iD/iD/locales/zh-TW.json @@ -1,5 +1,10 @@ { "zh-TW": { + "icons": { + "information": "資訊", + "remove": "移除", + "undo": "復原" + }, "modes": { "add_area": { "title": "區域", @@ -145,7 +150,9 @@ "vertex": "已連接路徑到另一路徑。", "line": "已連接路徑到一線段。", "area": "已連接路徑到一區域。" - } + }, + "relation": "這些特徵並不能連結,因為它們的關聯角色有衝突。", + "restriction": "這些特徵並不能連結,因為會破壞 \"{relation}\" 關聯。" }, "disconnect": { "title": "斷開", @@ -163,7 +170,8 @@ "annotation": "合併 {n} 個特徵", "not_eligible": "不能合併這些物件。", "not_adjacent": "這些特徵並不能合併,因為它們的端點並不相連。", - "restriction": "這些特徵並不能合併,因為其中一個是關聯 \"{relation}\" 成員。", + "restriction": "這些圖徽無法合併,因為它會危害到「{relation}」關係。", + "relation": "這些圖徽無法合併,因為它們有衝突的關係。", "incomplete_relation": "這些物件不能合併,因為其中最少有一件未有完全下載。", "conflicting_tags": "這些特徵並不能合儀,因為它們有彼此衝突的標籤。" }, @@ -402,6 +410,7 @@ "key": "H", "title": "歷史", "selected": "{n} 被選擇", + "no_history": "無歷史 (新功能)", "version": "版本", "last_edit": "最近編輯", "edited_by": "編輯由", @@ -639,15 +648,20 @@ } }, "success": { - "edited_osm": "已編輯了OSM!", "just_edited": "您剛剛編輯了OpenStreetMap!", - "view_on_osm": "於OSM上顯示", - "facebook": "分享至 Facebook", - "twitter": "分享至 Twitter", - "google": "分享至 Google+", - "help_html": "你編輯的變動應該過幾分會出現在\"標準圖層\"。其他圖層和特定圖徵,則需要久一點。", + "thank_you": "感謝你改進地圖。", + "thank_you_location": "感謝你改進 {where} 週遭的地圖。", + "help_html": "你編輯的變動應該過幾分會出現在開放街圖裡。其他的地圖更新需要花久一點時間。", "help_link_text": "詳細資料", - "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" + "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", + "view_on_osm": "在OSM上顯示變動", + "changeset_id": "你的變更集 #:{changeset_id}", + "like_osm": "喜歡開放街圖嗎?與其他人聯繫:", + "more": "更多", + "events": "活動", + "languages": "語言:{languages}", + "missing": "清單上仍有遺漏資訊?", + "tell_us": "告訴我們!" }, "confirm": { "okay": "OK", @@ -889,16 +903,35 @@ "about": { "title": "關於", "about": "這個欄位允許你偵測和變動轉彎限制,顯示選取的交叉路口的模型,以及鄰近連結的道路。", - "from_via_to": "轉彎限制總是有:一個**從路徑**,一個**到路徑**,以及一個**經由節點*,或一個或多個**經由路徑**。" + "from_via_to": "轉彎限制總是有:一個**從路徑**,一個**到路徑**,以及一個**經由節點*,或一個或多個**經由路徑**。", + "maxdist": "\"{distField}\" 滑塊控制怎麼搜尋額外連結的道路。", + "maxvia": "\"{viaField}\" 滑塊調整搜尋時包括有多少經由路徑 (技巧:越簡單越好)" }, "inspecting": { - "title": "偵測" + "title": "偵測", + "about": "飄浮過任何 **FROM** 片段來看轉彎限制,每個可能的 **TO** 目標會用上色的陰影包住,顯示關聯是否存在。", + "from_shadow": "{fromShadow} **從片段**", + "allow_shadow": "{allowShadow} **允許到**", + "restrict_shadow": "{restrictShadow} **禁止到**", + "only_shadow": "{onlyShadow} **只有到**", + "restricted": "\"限制\"意著有轉彎限制,例如說\"禁止左轉\"。", + "only": "\"只有\"意味著汽車從這條路來的時候,只能做這項選擇,例如說,\"只淮直行\"。" }, "modifying": { - "title": "變動" + "title": "變動", + "about": "要變動轉彎限制,請先檢查先選取起始的 **FROM** 片段,選取的片段會放大,然後任何可能的 **TO** 目的地會以轉彎符號顯示。", + "indicators": "接著,點選轉彎符號切換為\"允許\",\"限制\",和\"只有\"。", + "allow_turn": "{allowTurn} **到允許**", + "restrict_turn": "{restrictTurn} **到限制**", + "only_turn": "{onlyTurn} **只有到**" }, "tips": { - "title": "技巧" + "title": "技巧", + "simple": "**偏好簡單限制而不是複雜的限制。**", + "simple_example": "舉例來說,如果有簡單的經由點轉彎限制的話,避免創建經由道路限制。", + "indirect": "**一些限制會顯示 \"(indirect)\" 文字,並且畫得比較淡。**", + "indirect_example": "這此限制存在,因為其他鄰近的限制。舉例來說,一個**只允許直行**的限制會間接為其他經過的道路創建\"不允許轉彎\"限制。", + "indirect_noedit": "你並不允許編輯間接限制,做為替代,你可以編輯鄰近的方向限制。" } } } @@ -1755,6 +1788,9 @@ "display": { "label": "顯示" }, + "distance": { + "label": "全部距離" + }, "dock": { "label": "碼頭種類" }, @@ -1795,6 +1831,9 @@ "except": { "label": "例外" }, + "faces": { + "label": "面" + }, "fax": { "label": "傳真", "placeholder": "+31 42 123 4567" @@ -1906,6 +1945,39 @@ "label": "藍框數量", "placeholder": "1, 2, 4..." }, + "horse_dressage": { + "label": "馬場馬術", + "options": { + "equestrian": "是", + "undefined": "否" + } + }, + "horse_riding": { + "label": "馬背騎乘", + "options": { + "horse_riding": "是", + "undefined": "否" + } + }, + "horse_scale": { + "label": "騎馬難度", + "options": { + "common": "容易:沒有問題或困難度。(預設)", + "critical": "邊緣:有經驗騎士和馬匹可通行,主要障礙,橋樑要小心檢驗。", + "dangerous": "危險:只適合非常有經驗的騎士和馬匹通行,而且只在天氣好的狀況,下馬狀況。", + "demanding": "小心使用:不平的道路,時常有難以通行的通道。", + "difficult": "困難:狹窄和裸露的道路,也許需要踩過障礙物和通過狹窄通道。", + "impossible": "不可能:道路或橋樑馬匹不可能通行,太狹窄,沒有足夠的支援,有障礙物像是梯子,有生命危險。" + }, + "placeholder": "危險,困難..." + }, + "horse_stables": { + "label": "騎馬馬房", + "options": { + "stables": "是", + "undefined": "否" + } + }, "iata": { "label": "IATA" }, @@ -1925,6 +1997,9 @@ "indoor": { "label": "室內" }, + "industrial": { + "label": "類型" + }, "information": { "label": "種類" }, @@ -2045,6 +2120,10 @@ "label": "速度限制", "placeholder": "40, 50, 60..." }, + "maxspeed/advisory": { + "label": "建議速限", + "placeholder": "40, 50, 60..." + }, "maxstay": { "label": "可停留時間" }, @@ -2633,8 +2712,19 @@ "label": "類型", "placeholder": "預設" }, + "usage_rail": { + "label": "用途類型", + "options": { + "branch": "支線", + "industrial": "工業用", + "main": "主線", + "military": "軍事用", + "test": "測試", + "tourism": "觀光" + } + }, "vending": { - "label": "貨品種類" + "label": "貨物類型" }, "visibility": { "label": "可見度", @@ -2729,6 +2819,10 @@ "name": "廣告牌", "terms": "廣告看板" }, + "advertising/column": { + "name": "廣告看板", + "terms": "廣告看板,廣告欄" + }, "aerialway": { "name": "纜車路線" }, @@ -2814,6 +2908,10 @@ "name": "機場航廈", "terms": "航廈,機場大堂" }, + "allotments/plot": { + "name": "社區園圃", + "terms": "社區園圃,社區農圃,社區花園" + }, "amenity": { "name": "便利設施" }, @@ -3042,6 +3140,10 @@ "name": "市場", "terms": "市集,傳統市場,marketplace" }, + "amenity/monastery": { + "name": "修道院", + "terms": "修道院" + }, "amenity/motorcycle_parking": { "name": "機車停車場", "terms": "機車停車場,速克達停車場,摩托車停車場" @@ -3246,6 +3348,10 @@ "name": "香菸販賣機", "terms": "香菸自動販賣機,販賣機" }, + "amenity/vending_machine/coffee": { + "name": "咖啡販賣機", + "terms": "咖啡販賣機,咖啡自動販賣機" + }, "amenity/vending_machine/condoms": { "name": "保險套販賣機", "terms": "保險套自動販賣機,販賣機" @@ -3254,6 +3360,14 @@ "name": "飲料販賣機", "terms": "飲料自動販賣機,販賣機" }, + "amenity/vending_machine/electronics": { + "name": "電子設備販賣機", + "terms": "電子設備販賣機,電子設備自動販賣機" + }, + "amenity/vending_machine/elongated_coin": { + "name": "扁平紀念幣販賣機", + "terms": "扁平紀念幣販賣機,扁平紀念幣自動販賣機" + }, "amenity/vending_machine/excrement_bags": { "name": "糞便袋販賣機", "terms": "糞便袋自動販賣機,販賣機" @@ -3262,6 +3376,18 @@ "name": "女性衛生用品自動販賣機", "terms": "女性衛生用品自動販賣機,衛生棉自動販賣機,棉條自動販賣機" }, + "amenity/vending_machine/food": { + "name": "食物販賣機", + "terms": "食物販賣機,食物自動販賣機" + }, + "amenity/vending_machine/fuel": { + "name": "自助加油機", + "terms": "自助加油機" + }, + "amenity/vending_machine/ice_cream": { + "name": "冰淇淋販賣機", + "terms": "冰淇淋販賣機,冰淇淋自動販賣機" + }, "amenity/vending_machine/news_papers": { "name": "報紙販賣機" }, @@ -3281,6 +3407,10 @@ "name": "車票販賣機", "terms": "車票自動販賣機,交通票券販賣機" }, + "amenity/vending_machine/stamps": { + "name": "郵票販賣機", + "terms": "郵票販賣機,郵票自動販賣機" + }, "amenity/vending_machine/sweets": { "name": "零食販賣機", "terms": "點心販賣機,販 賣機" @@ -3353,6 +3483,10 @@ "name": "自由落體", "terms": "大怒神" }, + "attraction/maze": { + "name": "è¿·å®®", + "terms": "è¿·å®®" + }, "attraction/pirate_ship": { "name": "海盜船", "terms": "海盜船" @@ -3534,6 +3668,10 @@ "name": "車庫", "terms": "車庫" }, + "building/grandstand": { + "name": "正面看臺", + "terms": "正面看臺,看臺" + }, "building/greenhouse": { "name": "溫室", "terms": "溫室" @@ -3982,6 +4120,10 @@ "name": "安養院", "terms": "安養院" }, + "healthcare/laboratory": { + "name": "醫事檢驗所", + "terms": "醫檢" + }, "healthcare/midwife": { "name": "助產士", "terms": "助產士" @@ -4084,6 +4226,10 @@ "name": "高速公路引道", "terms": "高速公路引道" }, + "highway/passing_place": { + "name": "避車彎", + "terms": "避車彎" + }, "highway/path": { "name": "路徑", "terms": "路徑" @@ -4443,6 +4589,10 @@ "name": "遊樂場", "terms": "遊樂場" }, + "leisure/beach_resort": { + "name": "海灘渡假村", + "terms": "海灘渡假村,海濱渡假村" + }, "leisure/bird_hide": { "name": "鳥類棲息處", "terms": "鳥類棲息處,鳥類棲地,鳥類藏身處" @@ -4559,6 +4709,10 @@ "name": "自然保留區", "terms": "自然保護區" }, + "leisure/outdoor_seating": { + "name": "戶外座位區", + "terms": "戶外座位區,戶外座位" + }, "leisure/park": { "name": "公園", "terms": "綠地,遊樂場" @@ -4687,6 +4841,10 @@ "name": "坑口", "terms": "坑道口,礦坑口" }, + "man_made/antenna": { + "name": "天線", + "terms": "天線" + }, "man_made/breakwater": { "name": "防波堤", "terms": "防波堤" @@ -4738,6 +4896,10 @@ "name": "瞭望塔", "terms": "瞭望塔" }, + "man_made/observatory": { + "name": "天文台", + "terms": "天文館" + }, "man_made/petroleum_well": { "name": "油井", "terms": "油井" @@ -4862,10 +5024,18 @@ "name": "荒地", "terms": "荒地" }, + "natural/mud": { + "name": "泥地", + "terms": "泥地" + }, "natural/peak": { "name": "山頂", "terms": "山峰,山巔" }, + "natural/reef": { + "name": "暗礁", + "terms": "暗礁,礁" + }, "natural/ridge": { "name": "山脊", "terms": "山陵" @@ -5898,6 +6068,10 @@ "name": "寵物店", "terms": "寵物用品店" }, + "shop/pet_grooming": { + "name": "寵物美容店", + "terms": "寵物美容店" + }, "shop/photo": { "name": "攝影用品店", "terms": "照相店" @@ -6117,6 +6291,10 @@ "name": "主題公園", "terms": "主題樂園" }, + "tourism/trail_riding_station": { + "name": "騎馬車站", + "terms": "騎馬車站" + }, "tourism/viewpoint": { "name": "觀景點", "terms": "風景點" @@ -6201,16 +6379,20 @@ "terms": "禁止迴轉" }, "type/restriction/only_left_turn": { - "name": "只准左轉", + "name": "只能左轉", "terms": "只能左轉" }, "type/restriction/only_right_turn": { - "name": "只准右轉", + "name": "只能右轉", "terms": "只能右轉" }, "type/restriction/only_straight_on": { - "name": "只准直駛", - "terms": "禁止轉彎" + "name": "只能直行", + "terms": "只能直行" + }, + "type/restriction/only_u_turn": { + "name": "只能迴轉", + "terms": "只能迴轉" }, "type/route": { "name": "路線", @@ -6373,7 +6555,7 @@ "attribution": { "text": "使用條款與意見回饋" }, - "description": "影像邊界與取得時間。標籤會在縮放14層級或更高時顯示。", + "description": "影像邊界與拍攝日期。標籤將會在縮放等級大於等於 13 時出現。", "name": "DigitalGlobe Premium 空照圖年份" }, "DigitalGlobe-Standard": { @@ -6387,7 +6569,7 @@ "attribution": { "text": "使用條款與意見回饋" }, - "description": "影像邊界與取得時間。標籤會在縮放14層級或更高時顯示。", + "description": "影像邊界與拍攝日期。標籤將會在縮放等級大於等於 13 時出現。", "name": "DigitalGlobe Standard 空照圖年份" }, "EsriWorldImagery": { @@ -6471,6 +6653,10 @@ "description": "黃 = 自美國人口普查局的公共領域地圖資料取得。紅 = 在開放街圖上找不到資料", "name": "TIGER 道路 2017" }, + "US_Forest_Service_roads_overlay": { + "description": "道路:綠色外框 = 非分類道路。棕色外框 = 土路。路面:碎石路 = 亮棕色實心填滿,柏油 = 黑色,有舖面 = 灰色,地面 = 白色,水泥 = 藍色,草地 = 綠色。季節性 = 白色條紋", + "name": "美國森林道路覆蓋層" + }, "Waymarked_Trails-Cycling": { "attribution": { "text": "© waymarkedtrails.org,OpenStreetMap 貢獻者,,CC by-SA 3.0" @@ -6505,7 +6691,7 @@ "attribution": { "text": "basemap.at" }, - "description": "基於政府資料的奧地利底圖。", + "description": "奧地利的底圖,基於政府資料。", "name": "basemap.at" }, "basemap.at-orthofoto": { @@ -6567,7 +6753,7 @@ }, "stamen-terrain-background": { "attribution": { - "text": "Stamen 設計的圖磚,以 CC-BY 3.0 授權" + "text": "Stamen Design 的圖磚,以 CC BY 3.0 授權。資料自 OpenStreetMap 處取得,以 ODbL 授權" }, "name": "Stamen Terrain" }, @@ -6583,6 +6769,467 @@ }, "name": "Thunderforest Landscape" } + }, + "community": { + "cape-coast-youthmappers": { + "name": "University of Cape Coast YouthMappers", + "description": "追隨我們的 Twitter: {url} ", + "extendedDescription": "這是迦納 University of Cape Coast Youth Mappers 分會的官方頻道,我們愛地圖、開放資料和幫助別人。" + }, + "osm-gh-facebook": { + "name": "開放街圖迦納 Facebook", + "description": "迦納對開放街圖有興趣的人參與的 Facebook 社團。", + "extendedDescription": " 迦納社群中的圖客,推廣迦納開放街圖和人道救援開放街圖計畫。加入我們吧!" + }, + "osm-gh-twitter": { + "name": "開放街圖迦納 Twitter", + "description": "追隨我們的 Twitter: {url} " + }, + "talk-gh": { + "name": "Talk-gh 郵件論壇", + "description": "Talk-gh 是迦納社群的官方郵件論壇 " + }, + "osm-mg-facebook": { + "name": "開放街圖馬達加斯加 Facebook 社團", + "description": "馬達加斯加對開放街圖有興趣的人參與的 Facebook 社團。" + }, + "talk-mg": { + "name": "Talk-m 郵件論壇", + "description": "馬達加斯加開放街圖貢獻者、社群和使用者分享和討論的園地" + }, + "OSM-BGD-facebook": { + "name": "開放街圖孟加拉", + "description": "改進孟加拉的開放街圖" + }, + "OSM-India-facebook": { + "name": "開放街圖印度 - 參與社區畫圖", + "description": "改善印度的 OpenStreetMap", + "extendedDescription": "在印度畫地圖嗎?想要問問題,想要與社群連結?請加入 {Url},所有人都歡迎噢!", + "events": { + "sotmasia2018": { + "name": "State of the Map Asia 2018", + "description": "加入 2018 開放街圖在印度的亞洲地區性的大會活動", + "where": "印度班加羅爾,印度管理學院" + } + } + }, + "OSM-india-mailinglist": { + "name": "開放街圖印度郵件論壇", + "description": "Talk-in 是印度社群的官方郵件論壇" + }, + "OSM-india-twitter": { + "name": "開放街圖印度 Twitter", + "description": "我們只是喜歡 tweet:{url}" + }, + "OSM-India-Puducherry-Facebook": { + "name": "Free Software Hardware Movement - Facebook", + "description": "FSHM Facebook 粉絲頁讓你知道社群活動", + "extendedDescription": "FSHM 組織跟自由軟體/硬體、科技、倡議和開放街圖的活動。FSHM Facebook 粉絲頁是最好跟他們活動保持聯繫的方式。" + }, + "OSM-India-Puducherry-Matrix": { + "name": "自由軟體硬體運動 - Matrix", + "description": "FSHM Riot 小組討論、分享和更新本地治里一帶畫地圖活動", + "extendedDescription": "FSHM 社群成員經由 Riot.im 群組分享他們的開放街圖畫地圖狀況 / 經驗,社群也會討論與自由軟體 / 硬體、科技和行動主義。" + }, + "OSM-IDN-facebook": { + "name": "開放街圖印尼", + "description": "改進印尼的開放街圖", + "extendedDescription": "在印尼畫地圖嗎?有問題,想要與社群互動?來 {Url} 加入我們,歡迎所有人。" + }, + "OSM-japan-facebook": { + "name": "開放街圖日本社群", + "description": "日本圖客和開放街圖使用者" + }, + "OSM-japan-mailinglist": { + "name": "開放街圖日本郵件論壇", + "description": "Talk-ja 是日本社群官方的郵件論壇" + }, + "OSM-japan-twitter": { + "name": "開放街圖日本 Twitter", + "description": "Twitter 的標籤:{url}" + }, + "OSM-japan-website": { + "name": "開放街圖日本", + "description": "日本圖客和開放街圖使用者" + }, + "OSM-korea-telegram": { + "name": "開放街圖南韓 Telegram 頻道", + "description": "南韓開放街圖貢獻者、社群和使用者分享和討論的非官方頻道。" + }, + "OSM-MY-facebook": { + "name": "開放街圖馬來西亞 Facebook", + "description": "討論任何跟開放街圖相關的事物!" + }, + "OSM-MY-forum": { + "name": "開放街圖馬來西亞論壇", + "description": "官方開放街圖馬來西亞論壇" + }, + "OSM-MY-matrix": { + "name": "OpenStreetMap 馬來西亞 Riot channel", + "description": "歡迎所有圖客!在 {signupUrl} 註冊" + }, + "OSM-MNG-facebook": { + "name": "開放街圖蒙古", + "description": "改進蒙古的開放街圖", + "extendedDescription": "在蒙古畫地圖嗎?有問題,想要與社群互動?來 {Url} 加入我們,歡迎所有人。" + }, + "OSM-MMR-facebook": { + "name": "開放街圖緬甸", + "description": "改進緬甸的開放街圖", + "extendedDescription": "在緬甸畫地圖嗎?有問題,想要與社群互動?來 {Url} 加入我們,歡迎所有人。" + }, + "OSM-Nepal-facebook": { + "name": "開放街圖尼泊爾", + "description": "改進尼泊爾的開放街圖", + "extendedDescription": "在尼泊爾畫地圖嗎?有問題,想要與社群互動?來 {Url} 加入我們,歡迎所有人。" + }, + "OSM-PH-facebook": { + "name": "開放街圖菲律賓 Facebook", + "description": "歡迎來到開放街圖菲律賓,我們歡迎所有菲律賓人貢獻一己之力到開放街圖計畫。" + }, + "OSM-PH-mailinglist": { + "name": "Talk-ph 郵件論壇", + "description": "討論開放街圖在菲律賓事物的郵件論壇" + }, + "OSM-PH-slack": { + "name": "開放街圖 PH Slack", + "description": "歡迎所有人加入!在 {signupUrl} 註冊" + }, + "OSM-PH-telegram": { + "name": "開放街圖 PH Telegram", + "description": "非官方的菲律賓貢獻者和友好者的 Telegram 群組。" + }, + "OSM-RU-forum": { + "name": "開放街圖俄羅斯論壇", + "description": "開放街圖俄羅斯網頁論壇" + }, + "OSM-RU-telegram": { + "name": "開放街圖 RU Telegram", + "description": "開放街圖俄羅斯 Telegram 聊天群組" + }, + "OSM-LKA-facebook": { + "name": "開放街圖斯里蘭卡", + "description": "改進斯里蘭卡的開放街圖", + "extendedDescription": "在斯里蘭卡畫地圖嗎?有問題,想要與社群互動?來 {Url} 加入我們,歡迎所有人。" + }, + "OSM-TW-facebook": { + "name": "開放街圖台灣社群", + "description": "台灣社群專門討論有關台灣圖資的臉書社團" + }, + "OSM-TW-mailinglist": { + "name": "開放街圖台灣郵件論壇", + "description": "Talk-tw 是台灣社群專門討論有關台灣圖資的官方郵件論壇" + }, + "at-forum": { + "name": "開放街圖奧地利論壇", + "description": "開放街圖在奧地利問答的官方論壇" + }, + "at-mailinglist": { + "name": "Talk-at 郵件論壇", + "description": "Talk-at 是奧地利社群的官方郵件論壇 " + }, + "at-twitter": { + "name": "開放街圖奧地利 Twitter", + "description": "開放街圖奧地利 Twitter:{url}" + }, + "osmgraz-meetup": { + "name": "OSM community meetup Graz", + "description": "開放街圖格拉茨社群的每月聚會" + }, + "osmgraz-twitter": { + "name": "OSM community Graz Twitter", + "description": "開放街圖格拉茨社群的 Twitter" + }, + "osm-at": { + "name": "開放街圖奧地利", + "description": "開放街圖在奧地利交流資訊的平台" + }, + "byosm": { + "name": "開放街圖白羅斯", + "description": "開放街圖白羅斯 Telegram 聊天室" + }, + "be-facebook": { + "name": "開放街圖比利時社群", + "description": "比利時圖客和開放街圖 Facebook" + }, + "be-forum": { + "name": "開放街圖比利時論壇", + "description": "開放街圖比利時網頁論壇" + }, + "be-irc": { + "name": "開放街圖奧地利 IRC", + "description": "在 irc.oftc.net (port 6667) 上面加入 #osmbe", + "extendedDescription": "運用 Matrix chat channel,在 irc.oftc.net (port 6667) 上面加入 #osmbe" + }, + "be-mailinglist": { + "name": "Talk-be 郵件論壇", + "description": "Talk-be 是比利時社群的官方郵件論壇 " + }, + "be-matrix": { + "name": "OpenStreetMap BE Matrix channel", + "description": "歡迎所有圖客!" + }, + "be-meetup": { + "name": "開放街圖比利時聚會", + "description": "實體聚會中見到每一位對開放街圖有興趣的人", + "extendedDescription": "實體的聚會是與其他圖客碰面的好機會,能夠論論問題,學到很多事情,特別是歡迎新的貢獻者。" + }, + "be-twitter": { + "name": "開放街圖比利時 Twitter" + }, + "talk-cz-mailinglist": { + "name": "Talk-cz 郵件論壇", + "description": "Talk-cz 是捷克社群的官方郵件論壇 " + }, + "dk-forum": { + "name": "開放街圖丹麥網頁論壇", + "description": "開放街圖丹麥的網頁論壇" + }, + "dk-irc": { + "name": "OpenStreetMap Denmark IRC", + "description": "在 irc.oftc.net (port 6667) 上面加入 #osm-dk" + }, + "dk-mailinglist": { + "name": "Talk-dk 郵件論壇", + "description": "討論開放街圖在丹麥事物的郵件論壇" + }, + "fr-facebook": { + "name": "開放街圖法國 Facebook 頁面", + "description": "開放街圖法國 Facebook 頁面" + }, + "fr-forum": { + "name": "開放街圖法國網頁論壇", + "description": "開放街圖法國網頁論壇" + }, + "fr-irc": { + "name": "開放街圖法國 IRC", + "description": "在 irc.oftc.net (port 6667) 上面加入 #osm-fr" + }, + "fr-mailinglist": { + "name": "Talk-fr 郵件論壇", + "description": "Talk-fr 郵件論壇" + }, + "fr-twitter": { + "name": "開放街圖法國 Twitter", + "description": "開放街圖法國 Twitter:{url}" + }, + "de-berlin-mailinglist": { + "name": "柏林郵件論壇", + "description": "這是柏林開放街圖社群的郵件論壇" + }, + "de-berlin-meetup": { + "name": "OpenStreetMap Berlin-Brandenburg Meetup", + "description": "柏林和布蘭登堡一帶的圖客與開放街圖使用者" + }, + "de-berlin-telegram": { + "name": "Telegram 上的 @osmberlin", + "description": "開放街圖柏林 Telegram 聊天室" + }, + "de-berlin-twitter": { + "name": "開放街圖柏林 Twitter", + "description": "追隨我們的 Twitter: {url}" + }, + "de-forum": { + "name": "OpenStreetMap DE forum", + "description": "開放街圖德國網頁論壇" + }, + "de-irc": { + "name": "OpenStreetMap Germany IRC", + "description": "在 irc.oftc.net (port 6667) 上面加入 #osm-de" + }, + "de-mailinglist": { + "name": "Talk-de 郵件論壇", + "description": "Talk-de 是德國開放街圖社群的郵件論壇 " + }, + "de-ostwestfalen-lippe-mailinglist": { + "name": "OWL 郵件論壇", + "description": "這是東威斯特法倫 - 利普開放街圖社群的郵件論壇" + }, + "osm-de": { + "name": "開放街圖德國", + "description": "開放街圖在德國交流資訊的平台" + }, + "OSM-ES-mailinglist": { + "name": "Talk-es 郵件論壇", + "description": "討論開放街圖在西班牙事物的郵件論壇" + }, + "OSM-ES-telegram": { + "name": "Telegram 上的 @OSMes", + "description": "開放街圖西班牙 Telegram 聊天室" + }, + "Nottingham-OSM-pub-meetup": { + "name": "East Midlands (諾丁漢) 酒吧每月聚會", + "description": "East Midlands 圖客和使用者的社交聚會" + }, + "Bay-Area-OpenStreetMappers": { + "name": "灣區的 OpenStreetMap 圖客", + "description": "改善在灣區的 OpenStreetMap", + "extendedDescription": "這個群組是為了讓灣區的 OpenStreetMap 社群成長茁壯而設立。我們的活動開放給所有人參與,開放原始碼支持者、自行車騎士、地理資訊系統 (GIS) 專家、地理藏寶者都可以。只要對地圖、地圖製作與自由地圖資料有興趣的人都歡迎加入我們的群組,以及參與我們的活動。" + }, + "Central-Pennsylvania-OSM": { + "name": "賓州中部 OSM", + "description": "位於賓州州立大學的線上製圖社群" + }, + "Code-for-San-Jose-Slack": { + "name": "Code for San Jose Slack", + "description": "歡迎所有人加入!在 {signupUrl} 註冊,並加入 #osm 頻道。" + }, + "Dallas-Fort-Worth-OSM": { + "name": "達拉斯—沃斯堡 OSM", + "description": "達拉斯—沃斯堡的 OpenStreetMap 使用者群組", + "extendedDescription": "達拉斯、沃斯堡與其間的所有城市都充滿了極具創造力且技術精湛的人才。這個使用者群組的願景是找出新的方法來使用 OSM 上的驚人資源。" + }, + "GeoPhilly": { + "name": "GeoPhilly", + "description": "費城地區的地圖愛好者聚會", + "extendedDescription": "GeoPhilly 將開發者、地理學家、資料極客、開放原始碼愛好者、公民駭客與地圖愛好者聯合起來,並將我們對地圖的熱愛與他們的故事連結起來。如果你在工作中會用到地圖,或僅僅只是想要了解更多,這就是為你而辦的聚會!我們的活動旨在開放、友好、教育與社交,從歡樂時光到閃電講,甚至是工作坊都有。跟我們一起在費城建立一個多元化且激勵人心的地理空間社群!" + }, + "MapMinnesota": { + "name": "MapMinnesota", + "description": "在雙城區一帶的圖客與開放街圖使用者", + "extendedDescription": "接觸明尼蘇達和雙城區一帶開放街圖熱情參與者!" + }, + "Mapping-DC-meetup": { + "name": "Mapping DC", + "description": "改善華府區域的 OpenStreetMap", + "extendedDescription": "我們是一群致力於改善華府區域的 OpenStreetMap 的群組。我們也努力教導其他人關於 OSM 的生態系、資料分析、製圖與 GIS。我們每隔一個月聚會一次,每次僅聚焦在我們的城市中的一個地區。" + }, + "OSM-Boston": { + "name": "開放街圖波士頓", + "description": "波士頓的圖客與開放街圖使用者", + "extendedDescription": "開放街圖是一份自由開放的維基風格世界地圖,每天都有數十萬像您這樣的人們做出貢獻。編輯地圖很簡單,而且很有趣!不管是在戶內或是戶外都可以加入我們,來建立波士頓地區與世界其他地方最好的地圖吧!" + }, + "OSM-Chattanooga": { + "name": "OSM 查塔努加", + "description": "查塔努加的 OpenStreetMap 使用者群組" + }, + "OSM-Colorado": { + "name": "開放街圖科羅拉多", + "description": "在美國科羅拉多州的圖客與開放街圖使用者", + "extendedDescription": "開放街圖 (OpenStreetMap, OSM) 科羅拉多是一個喜歡貢獻他們的心力建立自由地圖的一群地區協作夥伴。我們鼓勵我們所有的圖客組織或建議橫跨整個州的製圖活動。會面活動可以是簡單的社交活動、OSM 基礎到進階訓練,或是社群製圖派對。" + }, + "OSM-NYC": { + "name": "OpenStreetMap NYC", + "description": "在紐約都會區的圖客與 OpenStreetMap 使用者、開發者與愛好者" + }, + "OSM-Portland": { + "name": "OpenStreetMap 波特蘭", + "description": "波特蘭區域的圖客與 OpenStreetMap 使用者", + "extendedDescription": "OpenStreetMap (OSM) 是一幅由像你這樣的人所製作的世界地圖。它是由你所建構,並如同維基百科那樣自由提供給所有人的地圖。看看 osm.org 以取得更多資訊,然後在聚會上加入我們來說說地圖的故事、對 OSM 貢獻然後玩得開心!" + }, + "OSM-Seattle": { + "name": "開放街圖西雅圖", + "description": "在西雅圖的圖客與開放街圖使用者" + }, + "OSM-South-Bay": { + "name": "OSM South Bay", + "description": "由為聖荷西寫程式主辦的地圖之夜", + "extendedDescription": "為聖荷西寫程式是為美國寫程式的地區分支,週四晚上在聖荷西市中心舉辦每月地圖之夜。結識南灣區的圖客,與當地的製圖專案交流,聽聽其他的公民科技專案。寫程式或 GIS 相關技能都並非必要。" + }, + "OSM-Tampa-Bay": { + "name": "開放街圖坦帕灣", + "description": "坦帕灣的圖客與開放街圖使用者", + "extendedDescription": "OSM 坦帕灣群組讓當地居民聚在一起,用開放街圖建立坦帕灣的準確地圖。如果您使用地圖、資料、開放原始碼、GPS、徒步旅行或是騎腳踏車等等,您將會很喜歡與 OSM 合作,所以請加入吧!我們會聚在一起,製圖並討論每月的新主題。" + }, + "OSM-US-Slack": { + "name": "OpenStreetMap US Slack", + "description": "歡迎所有人加入!在 {signupUrl} 註冊" + }, + "OSM-US": { + "name": "開放街圖美國", + "description": "我們協助美國的開放街圖成長茁壯並改善它。", + "extendedDescription": "我們透過舉辦年度研討會、提供社群資源、建立合作關係以及推廣來支援開放街圖。在此加入開放街圖美國:{signupUrl}" + }, + "OSM-Utah": { + "name": "開放街圖猶他", + "description": "在鹽湖城區域的圖客與開放街圖使用者", + "extendedDescription": "我們可能會舉辦的活動有:學習製圖工作坊、製圖派對與戶外資料蒐集。活動將會在鹽湖城區舉辦,至少一開始是這樣。我們正在尋找經驗豐富的圖客與 OSM 新手。加入我們,一起來製圖吧!" + }, + "OSM-Wyoming": { + "name": "開放街圖懷俄明", + "description": "在懷俄明州的圖客與開放街圖使用者", + "extendedDescription": "開放街圖 (OpenStreetMap, OSM) 懷俄明是一個喜歡貢獻他們的心力建立自由地圖的一群地區協作夥伴。我們鼓勵我們所有的圖客組織或建議橫跨整個州的製圖活動。會面活動可以是簡單的社交活動、OSM 基礎到進階訓練,或是社群製圖派對。" + }, + "PHXGeo-meetup": { + "name": "PHXGeo Meetup", + "description": "在亞利桑那州鳳凰城的圖客與開放街圖使用者", + "extendedDescription": "這是一個給住在鳳凰城,喜歡地圖、GIS、開放街圖、製圖與其他東西的群組。" + }, + "PHXGeo-twitter": { + "name": "PHXGeo Twitter", + "description": "在 {url} 上追隨我們的 Twitter" + }, + "Western-Slope-facebook": { + "name": "Western Slope OSM Facebook", + "description": "在科羅拉多州大章克申的圖客與開放街圖使用者" + }, + "Western-Slope-meetup": { + "name": "Western Slope OSM Meetup", + "description": "在科羅拉多州大章克申的圖客與開放街圖使用者", + "extendedDescription": "此群組的目標是介紹開放街圖給社群知道,並發展圖客社群、利用任何方法建立盡可能多的地理資料並把這些資料提供給社群。想像準確的線索標示!想像自行車道的進一步發展!想像您想要什麼,這就是開放街圖的有趣之處!" + }, + "Maptime-Australia-Slack": { + "name": "Maptime Australia Slack", + "description": "在 {signupUrl} 註冊" + }, + "Maptime-Bogota": { + "name": "Maptime Bogotá", + "description": "我們是一群關心波哥大一帶開放街圖狀況的圖客。", + "extendedDescription": "學習在現場收集資料,然後在開放街圖上面數位位。你不需要有先備知識!你只要有心參與、學習以及好好玩。" + }, + "OSM-CO-facebook": { + "name": "開放街圖哥倫比亞 Facebook", + "description": "加入開放街圖哥倫比亞社群 Facebook" + }, + "OSM-PE-mailinglist": { + "name": "Talk-pe 郵件論壇", + "description": "Talk-be 是開放街圖祕魯社群的官方郵件論壇 " + }, + "OSM-PE-matrix": { + "name": "OpenStreetMap 祕魯 Matrix 頻道", + "description": "在開放街圖祕魯社群的 Matrix 與其他成員聊天。" + }, + "OSM-PE-telegram": { + "name": "開放街圖祕魯 Telegram", + "description": "加入開放街圖祕魯 Telegram 聊天室" + }, + "OSM-PE-twitter": { + "name": "開放街圖祕魯 Twitter", + "description": "在 {url} 上追隨我們的 Twitter " + }, + "OSM-PE": { + "name": "開放街圖祕魯", + "description": "開放街圖社群的新聞和資源頁面" + }, + "OSM-Facebook": { + "name": "開放街圖 Facebook", + "description": "在 Facebook 為我們按讚,追蹤開放街圖相關的新聞和動態。" + }, + "OSM-help": { + "name": "開放街圖幫助論壇", + "description": "在開放街圖社群驅動的問答站,詢問問題以及得到答案。", + "extendedDescription": "{url} 是讓對開放街圖有需要幫助的人,無論你是初學者,或是有技術問題,來到這邊尋求協助吧!" + }, + "OSM-Reddit": { + "name": "在 Reddit 上的 OpenStreetMap", + "description": "/r/openstreetmap/ 是一個取得更多關於 OpenStreetMap 資訊的好地方。什麼事都能問!" + }, + "OSM-Twitter": { + "name": "開放街圖 Twitter", + "description": "在 {url} 上追隨我們的 Twitter" + }, + "OSMF": { + "name": "開放街圖基金會", + "description": "開放街圖基金會是位於英國,支持開放街圖計劃的非營利組織", + "extendedDescription": "開放街圖基金會藉由募款,維持開放街圖背後的伺服器,舉行年度 State of the Map 大會,以及協調志工維持開放街圖運作,支援開放街圖計畫。你可以在這裡藉由加入開放街圖基金會成為會員:{signupUrl},顯示你的支持,還有在開放街圖中帶進你的聲音,指導開放街圖的發展方向。", + "events": { + "sotm2018": { + "name": "State of the Map 2018", + "description": "加入我們這三天在義大利米蘭的年度全球尺度的開放街圖大會,讓社群中的每一個人彼此社交、分享和學習。", + "where": "義大利米蘭" + } + } + } } } } \ No newline at end of file diff --git a/vendor/assets/iD/iD/locales/zh.json b/vendor/assets/iD/iD/locales/zh.json index 5dc792319..84c71a9fb 100644 --- a/vendor/assets/iD/iD/locales/zh.json +++ b/vendor/assets/iD/iD/locales/zh.json @@ -221,10 +221,7 @@ "unsaved_changes": "您有未保存的更改" }, "success": { - "edited_osm": "编辑OSM!", - "just_edited": "你正在编辑的OpenStreetMap!", - "view_on_osm": "在OSM上查看", - "facebook": "在Facebook上分享" + "just_edited": "你正在编辑的OpenStreetMap!" }, "splash": { "welcome": "欢迎使用OpenStreetMap编辑器iD", @@ -480,7 +477,6 @@ "label": "类型" }, "phone": { - "label": "手机", "placeholder": "+31 42 123 4567" }, "place": { diff --git a/vendor/assets/javascripts/bowser.js b/vendor/assets/javascripts/bowser.js new file mode 100644 index 000000000..2ec17fb4b --- /dev/null +++ b/vendor/assets/javascripts/bowser.js @@ -0,0 +1,620 @@ +/*! + * Bowser - a browser detector + * https://github.com/ded/bowser + * MIT License | (c) Dustin Diaz 2015 + */ + +!function (root, name, definition) { + if (typeof module != 'undefined' && module.exports) module.exports = definition() + else if (typeof define == 'function' && define.amd) define(name, definition) + else root[name] = definition() +}(this, 'bowser', function () { + /** + * See useragents.js for examples of navigator.userAgent + */ + + var t = true + + function detect(ua) { + + function getFirstMatch(regex) { + var match = ua.match(regex); + return (match && match.length > 1 && match[1]) || ''; + } + + function getSecondMatch(regex) { + var match = ua.match(regex); + return (match && match.length > 1 && match[2]) || ''; + } + + var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase() + , likeAndroid = /like android/i.test(ua) + , android = !likeAndroid && /android/i.test(ua) + , nexusMobile = /nexus\s*[0-6]\s*/i.test(ua) + , nexusTablet = !nexusMobile && /nexus\s*[0-9]+/i.test(ua) + , chromeos = /CrOS/.test(ua) + , silk = /silk/i.test(ua) + , sailfish = /sailfish/i.test(ua) + , tizen = /tizen/i.test(ua) + , webos = /(web|hpw)os/i.test(ua) + , windowsphone = /windows phone/i.test(ua) + , samsungBrowser = /SamsungBrowser/i.test(ua) + , windows = !windowsphone && /windows/i.test(ua) + , mac = !iosdevice && !silk && /macintosh/i.test(ua) + , linux = !android && !sailfish && !tizen && !webos && /linux/i.test(ua) + , edgeVersion = getSecondMatch(/edg([ea]|ios)\/(\d+(\.\d+)?)/i) + , versionIdentifier = getFirstMatch(/version\/(\d+(\.\d+)?)/i) + , tablet = /tablet/i.test(ua) && !/tablet pc/i.test(ua) + , mobile = !tablet && /[^-]mobi/i.test(ua) + , xbox = /xbox/i.test(ua) + , result + + if (/opera/i.test(ua)) { + // an old Opera + result = { + name: 'Opera' + , opera: t + , version: versionIdentifier || getFirstMatch(/(?:opera|opr|opios)[\s\/](\d+(\.\d+)?)/i) + } + } else if (/opr\/|opios/i.test(ua)) { + // a new Opera + result = { + name: 'Opera' + , opera: t + , version: getFirstMatch(/(?:opr|opios)[\s\/](\d+(\.\d+)?)/i) || versionIdentifier + } + } + else if (/SamsungBrowser/i.test(ua)) { + result = { + name: 'Samsung Internet for Android' + , samsungBrowser: t + , version: versionIdentifier || getFirstMatch(/(?:SamsungBrowser)[\s\/](\d+(\.\d+)?)/i) + } + } + else if (/coast/i.test(ua)) { + result = { + name: 'Opera Coast' + , coast: t + , version: versionIdentifier || getFirstMatch(/(?:coast)[\s\/](\d+(\.\d+)?)/i) + } + } + else if (/yabrowser/i.test(ua)) { + result = { + name: 'Yandex Browser' + , yandexbrowser: t + , version: versionIdentifier || getFirstMatch(/(?:yabrowser)[\s\/](\d+(\.\d+)?)/i) + } + } + else if (/ucbrowser/i.test(ua)) { + result = { + name: 'UC Browser' + , ucbrowser: t + , version: getFirstMatch(/(?:ucbrowser)[\s\/](\d+(?:\.\d+)+)/i) + } + } + else if (/mxios/i.test(ua)) { + result = { + name: 'Maxthon' + , maxthon: t + , version: getFirstMatch(/(?:mxios)[\s\/](\d+(?:\.\d+)+)/i) + } + } + else if (/epiphany/i.test(ua)) { + result = { + name: 'Epiphany' + , epiphany: t + , version: getFirstMatch(/(?:epiphany)[\s\/](\d+(?:\.\d+)+)/i) + } + } + else if (/puffin/i.test(ua)) { + result = { + name: 'Puffin' + , puffin: t + , version: getFirstMatch(/(?:puffin)[\s\/](\d+(?:\.\d+)?)/i) + } + } + else if (/sleipnir/i.test(ua)) { + result = { + name: 'Sleipnir' + , sleipnir: t + , version: getFirstMatch(/(?:sleipnir)[\s\/](\d+(?:\.\d+)+)/i) + } + } + else if (/k-meleon/i.test(ua)) { + result = { + name: 'K-Meleon' + , kMeleon: t + , version: getFirstMatch(/(?:k-meleon)[\s\/](\d+(?:\.\d+)+)/i) + } + } + else if (windowsphone) { + result = { + name: 'Windows Phone' + , osname: 'Windows Phone' + , windowsphone: t + } + if (edgeVersion) { + result.msedge = t + result.version = edgeVersion + } + else { + result.msie = t + result.version = getFirstMatch(/iemobile\/(\d+(\.\d+)?)/i) + } + } + else if (/msie|trident/i.test(ua)) { + result = { + name: 'Internet Explorer' + , msie: t + , version: getFirstMatch(/(?:msie |rv:)(\d+(\.\d+)?)/i) + } + } else if (chromeos) { + result = { + name: 'Chrome' + , osname: 'Chrome OS' + , chromeos: t + , chromeBook: t + , chrome: t + , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i) + } + } else if (/edg([ea]|ios)/i.test(ua)) { + result = { + name: 'Microsoft Edge' + , msedge: t + , version: edgeVersion + } + } + else if (/vivaldi/i.test(ua)) { + result = { + name: 'Vivaldi' + , vivaldi: t + , version: getFirstMatch(/vivaldi\/(\d+(\.\d+)?)/i) || versionIdentifier + } + } + else if (sailfish) { + result = { + name: 'Sailfish' + , osname: 'Sailfish OS' + , sailfish: t + , version: getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i) + } + } + else if (/seamonkey\//i.test(ua)) { + result = { + name: 'SeaMonkey' + , seamonkey: t + , version: getFirstMatch(/seamonkey\/(\d+(\.\d+)?)/i) + } + } + else if (/firefox|iceweasel|fxios/i.test(ua)) { + result = { + name: 'Firefox' + , firefox: t + , version: getFirstMatch(/(?:firefox|iceweasel|fxios)[ \/](\d+(\.\d+)?)/i) + } + if (/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(ua)) { + result.firefoxos = t + result.osname = 'Firefox OS' + } + } + else if (silk) { + result = { + name: 'Amazon Silk' + , silk: t + , version : getFirstMatch(/silk\/(\d+(\.\d+)?)/i) + } + } + else if (/phantom/i.test(ua)) { + result = { + name: 'PhantomJS' + , phantom: t + , version: getFirstMatch(/phantomjs\/(\d+(\.\d+)?)/i) + } + } + else if (/slimerjs/i.test(ua)) { + result = { + name: 'SlimerJS' + , slimer: t + , version: getFirstMatch(/slimerjs\/(\d+(\.\d+)?)/i) + } + } + else if (/blackberry|\bbb\d+/i.test(ua) || /rim\stablet/i.test(ua)) { + result = { + name: 'BlackBerry' + , osname: 'BlackBerry OS' + , blackberry: t + , version: versionIdentifier || getFirstMatch(/blackberry[\d]+\/(\d+(\.\d+)?)/i) + } + } + else if (webos) { + result = { + name: 'WebOS' + , osname: 'WebOS' + , webos: t + , version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i) + }; + /touchpad\//i.test(ua) && (result.touchpad = t) + } + else if (/bada/i.test(ua)) { + result = { + name: 'Bada' + , osname: 'Bada' + , bada: t + , version: getFirstMatch(/dolfin\/(\d+(\.\d+)?)/i) + }; + } + else if (tizen) { + result = { + name: 'Tizen' + , osname: 'Tizen' + , tizen: t + , version: getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i) || versionIdentifier + }; + } + else if (/qupzilla/i.test(ua)) { + result = { + name: 'QupZilla' + , qupzilla: t + , version: getFirstMatch(/(?:qupzilla)[\s\/](\d+(?:\.\d+)+)/i) || versionIdentifier + } + } + else if (/chromium/i.test(ua)) { + result = { + name: 'Chromium' + , chromium: t + , version: getFirstMatch(/(?:chromium)[\s\/](\d+(?:\.\d+)?)/i) || versionIdentifier + } + } + else if (/chrome|crios|crmo/i.test(ua)) { + result = { + name: 'Chrome' + , chrome: t + , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i) + } + } + else if (android) { + result = { + name: 'Android' + , version: versionIdentifier + } + } + else if (/safari|applewebkit/i.test(ua)) { + result = { + name: 'Safari' + , safari: t + } + if (versionIdentifier) { + result.version = versionIdentifier + } + } + else if (iosdevice) { + result = { + name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod' + } + // WTF: version is not part of user agent in web apps + if (versionIdentifier) { + result.version = versionIdentifier + } + } + else if(/googlebot/i.test(ua)) { + result = { + name: 'Googlebot' + , googlebot: t + , version: getFirstMatch(/googlebot\/(\d+(\.\d+))/i) || versionIdentifier + } + } + else { + result = { + name: getFirstMatch(/^(.*)\/(.*) /), + version: getSecondMatch(/^(.*)\/(.*) /) + }; + } + + // set webkit or gecko flag for browsers based on these engines + if (!result.msedge && /(apple)?webkit/i.test(ua)) { + if (/(apple)?webkit\/537\.36/i.test(ua)) { + result.name = result.name || "Blink" + result.blink = t + } else { + result.name = result.name || "Webkit" + result.webkit = t + } + if (!result.version && versionIdentifier) { + result.version = versionIdentifier + } + } else if (!result.opera && /gecko\//i.test(ua)) { + result.name = result.name || "Gecko" + result.gecko = t + result.version = result.version || getFirstMatch(/gecko\/(\d+(\.\d+)?)/i) + } + + // set OS flags for platforms that have multiple browsers + if (!result.windowsphone && (android || result.silk)) { + result.android = t + result.osname = 'Android' + } else if (!result.windowsphone && iosdevice) { + result[iosdevice] = t + result.ios = t + result.osname = 'iOS' + } else if (mac) { + result.mac = t + result.osname = 'macOS' + } else if (xbox) { + result.xbox = t + result.osname = 'Xbox' + } else if (windows) { + result.windows = t + result.osname = 'Windows' + } else if (linux) { + result.linux = t + result.osname = 'Linux' + } + + function getWindowsVersion (s) { + switch (s) { + case 'NT': return 'NT' + case 'XP': return 'XP' + case 'NT 5.0': return '2000' + case 'NT 5.1': return 'XP' + case 'NT 5.2': return '2003' + case 'NT 6.0': return 'Vista' + case 'NT 6.1': return '7' + case 'NT 6.2': return '8' + case 'NT 6.3': return '8.1' + case 'NT 10.0': return '10' + default: return undefined + } + } + + // OS version extraction + var osVersion = ''; + if (result.windows) { + osVersion = getWindowsVersion(getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i)) + } else if (result.windowsphone) { + osVersion = getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i); + } else if (result.mac) { + osVersion = getFirstMatch(/Mac OS X (\d+([_\.\s]\d+)*)/i); + osVersion = osVersion.replace(/[_\s]/g, '.'); + } else if (iosdevice) { + osVersion = getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i); + osVersion = osVersion.replace(/[_\s]/g, '.'); + } else if (android) { + osVersion = getFirstMatch(/android[ \/-](\d+(\.\d+)*)/i); + } else if (result.webos) { + osVersion = getFirstMatch(/(?:web|hpw)os\/(\d+(\.\d+)*)/i); + } else if (result.blackberry) { + osVersion = getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i); + } else if (result.bada) { + osVersion = getFirstMatch(/bada\/(\d+(\.\d+)*)/i); + } else if (result.tizen) { + osVersion = getFirstMatch(/tizen[\/\s](\d+(\.\d+)*)/i); + } + if (osVersion) { + result.osversion = osVersion; + } + + // device type extraction + var osMajorVersion = !result.windows && osVersion.split('.')[0]; + if ( + tablet + || nexusTablet + || iosdevice == 'ipad' + || (android && (osMajorVersion == 3 || (osMajorVersion >= 4 && !mobile))) + || result.silk + ) { + result.tablet = t + } else if ( + mobile + || iosdevice == 'iphone' + || iosdevice == 'ipod' + || android + || nexusMobile + || result.blackberry + || result.webos + || result.bada + ) { + result.mobile = t + } + + // Graded Browser Support + // http://developer.yahoo.com/yui/articles/gbs + if (result.msedge || + (result.msie && result.version >= 10) || + (result.yandexbrowser && result.version >= 15) || + (result.vivaldi && result.version >= 1.0) || + (result.chrome && result.version >= 20) || + (result.samsungBrowser && result.version >= 4) || + (result.firefox && result.version >= 20.0) || + (result.safari && result.version >= 6) || + (result.opera && result.version >= 10.0) || + (result.ios && result.osversion && result.osversion.split(".")[0] >= 6) || + (result.blackberry && result.version >= 10.1) + || (result.chromium && result.version >= 20) + ) { + result.a = t; + } + else if ((result.msie && result.version < 10) || + (result.chrome && result.version < 20) || + (result.firefox && result.version < 20.0) || + (result.safari && result.version < 6) || + (result.opera && result.version < 10.0) || + (result.ios && result.osversion && result.osversion.split(".")[0] < 6) + || (result.chromium && result.version < 20) + ) { + result.c = t + } else result.x = t + + return result + } + + var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent || '' : '') + + bowser.test = function (browserList) { + for (var i = 0; i < browserList.length; ++i) { + var browserItem = browserList[i]; + if (typeof browserItem=== 'string') { + if (browserItem in bowser) { + return true; + } + } + } + return false; + } + + /** + * Get version precisions count + * + * @example + * getVersionPrecision("1.10.3") // 3 + * + * @param {string} version + * @return {number} + */ + function getVersionPrecision(version) { + return version.split(".").length; + } + + /** + * Array::map polyfill + * + * @param {Array} arr + * @param {Function} iterator + * @return {Array} + */ + function map(arr, iterator) { + var result = [], i; + if (Array.prototype.map) { + return Array.prototype.map.call(arr, iterator); + } + for (i = 0; i < arr.length; i++) { + result.push(iterator(arr[i])); + } + return result; + } + + /** + * Calculate browser version weight + * + * @example + * compareVersions(['1.10.2.1', '1.8.2.1.90']) // 1 + * compareVersions(['1.010.2.1', '1.09.2.1.90']); // 1 + * compareVersions(['1.10.2.1', '1.10.2.1']); // 0 + * compareVersions(['1.10.2.1', '1.0800.2']); // -1 + * + * @param {Array} versions versions to compare + * @return {Number} comparison result + */ + function compareVersions(versions) { + // 1) get common precision for both versions, for example for "10.0" and "9" it should be 2 + var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1])); + var chunks = map(versions, function (version) { + var delta = precision - getVersionPrecision(version); + + // 2) "9" -> "9.0" (for precision = 2) + version = version + new Array(delta + 1).join(".0"); + + // 3) "9.0" -> ["000000000"", "000000009"] + return map(version.split("."), function (chunk) { + return new Array(20 - chunk.length).join("0") + chunk; + }).reverse(); + }); + + // iterate in reverse order by reversed chunks array + while (--precision >= 0) { + // 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true) + if (chunks[0][precision] > chunks[1][precision]) { + return 1; + } + else if (chunks[0][precision] === chunks[1][precision]) { + if (precision === 0) { + // all version chunks are same + return 0; + } + } + else { + return -1; + } + } + } + + /** + * Check if browser is unsupported + * + * @example + * bowser.isUnsupportedBrowser({ + * msie: "10", + * firefox: "23", + * chrome: "29", + * safari: "5.1", + * opera: "16", + * phantom: "534" + * }); + * + * @param {Object} minVersions map of minimal version to browser + * @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map + * @param {String} [ua] user agent string + * @return {Boolean} + */ + function isUnsupportedBrowser(minVersions, strictMode, ua) { + var _bowser = bowser; + + // make strictMode param optional with ua param usage + if (typeof strictMode === 'string') { + ua = strictMode; + strictMode = void(0); + } + + if (strictMode === void(0)) { + strictMode = false; + } + if (ua) { + _bowser = detect(ua); + } + + var version = "" + _bowser.version; + for (var browser in minVersions) { + if (minVersions.hasOwnProperty(browser)) { + if (_bowser[browser]) { + if (typeof minVersions[browser] !== 'string') { + throw new Error('Browser version in the minVersion map should be a string: ' + browser + ': ' + String(minVersions)); + } + + // browser version and min supported version. + return compareVersions([version, minVersions[browser]]) < 0; + } + } + } + + return strictMode; // not found + } + + /** + * Check if browser is supported + * + * @param {Object} minVersions map of minimal version to browser + * @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map + * @param {String} [ua] user agent string + * @return {Boolean} + */ + function check(minVersions, strictMode, ua) { + return !isUnsupportedBrowser(minVersions, strictMode, ua); + } + + bowser.isUnsupportedBrowser = isUnsupportedBrowser; + bowser.compareVersions = compareVersions; + bowser.check = check; + + /* + * Set our detect method to the main bowser object so we can + * reuse it to test other user agents. + * This is needed to implement future tests. + */ + bowser._detect = detect; + + /* + * Set our detect public method to the main bowser object + * This is needed to implement bowser in server side + */ + bowser.detect = detect; + return bowser +}); diff --git a/vendor/assets/leaflet/leaflet.locationfilter.css b/vendor/assets/leaflet/leaflet.locationfilter.css index 2698d7878..a8e8f72b3 100644 --- a/vendor/assets/leaflet/leaflet.locationfilter.css +++ b/vendor/assets/leaflet/leaflet.locationfilter.css @@ -32,43 +32,43 @@ div.location-filter.button-container { background: #c4e3b9; background: rgba(218, 252, 205, 0.9); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(218, 252, 205, 0.9)), color-stop(100%, rgba(173, 226, 176, 0.9))); - background: -webkit-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); - background: -moz-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); - background: -ms-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); - background: -o-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); - background: linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background: -webkit-linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background: -moz-linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background: -ms-linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background: -o-linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background: linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); } .leaflet-container div.location-filter.button-container a:hover { color: #263F1C; background: #dde6d8; background: rgba(245, 255, 240, 0.9); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(245, 255, 240, 0.9)), color-stop(100%, rgba(203, 228, 205, 0.9))); - background: -webkit-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); - background: -moz-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); - background: -ms-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); - background: -o-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); - background: linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background: -webkit-linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background: -moz-linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background: -ms-linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background: -o-linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background: linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); } .leaflet-container div.location-filter.button-container a.enable-button { padding: 6px 7px 6px 25px; background-image: url( img/filter-icon.png ), -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(218, 252, 205, 0.9)), color-stop(100%, rgba(173, 226, 176, 0.9))); - background-image: url( img/filter-icon.png ), -webkit-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); - background-image: url( img/filter-icon.png ), -moz-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); - background-image: url( img/filter-icon.png ), -ms-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); - background-image: url( img/filter-icon.png ), -o-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); - background-image: url( img/filter-icon.png ), linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background-image: url( img/filter-icon.png ), -webkit-linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background-image: url( img/filter-icon.png ), -moz-linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background-image: url( img/filter-icon.png ), -ms-linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background-image: url( img/filter-icon.png ), -o-linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); + background-image: url( img/filter-icon.png ), linear-gradient(to top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); background-repeat: no-repeat; background-position: left center; } .leaflet-container div.location-filter.button-container a.enable-button:hover, .leaflet-container div.location-filter.button-container.enabled a.enable-button { background-image: url( img/filter-icon.png ), -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(245, 255, 240, 0.9)), color-stop(100%, rgba(203, 228, 205, 0.9))); - background-image: url( img/filter-icon.png ), -webkit-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); - background-image: url( img/filter-icon.png ), -moz-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); - background-image: url( img/filter-icon.png ), -ms-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); - background-image: url( img/filter-icon.png ), -o-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); - background-image: url( img/filter-icon.png ), linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background-image: url( img/filter-icon.png ), -webkit-linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background-image: url( img/filter-icon.png ), -moz-linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background-image: url( img/filter-icon.png ), -ms-linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background-image: url( img/filter-icon.png ), -o-linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); + background-image: url( img/filter-icon.png ), linear-gradient(to top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); background-repeat: no-repeat; background-position: left center; } diff --git a/vendor/assets/leaflet/leaflet.locationfilter.js b/vendor/assets/leaflet/leaflet.locationfilter.js index 0a977ed41..64ca34712 100644 --- a/vendor/assets/leaflet/leaflet.locationfilter.js +++ b/vendor/assets/leaflet/leaflet.locationfilter.js @@ -91,8 +91,6 @@ L.Control.ButtonContainer = L.Control.extend({ }); L.LocationFilter = L.Layer.extend({ - includes: L.Mixin.Events, - options: { enableButton: { enableText: "Select area", diff --git a/vendor/assets/potlatch2/potlatch2.swf b/vendor/assets/potlatch2/potlatch2.swf index 0d52185e2..d5abb9ae0 100644 Binary files a/vendor/assets/potlatch2/potlatch2.swf and b/vendor/assets/potlatch2/potlatch2.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/assets.zip b/vendor/assets/potlatch2/potlatch2/assets.zip index c47ee6e6f..313670722 100644 Binary files a/vendor/assets/potlatch2/potlatch2/assets.zip and b/vendor/assets/potlatch2/potlatch2/assets.zip differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/af.swf b/vendor/assets/potlatch2/potlatch2/locales/af.swf index 2cb592f3d..58bd8ab5d 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/af.swf and b/vendor/assets/potlatch2/potlatch2/locales/af.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ar.swf b/vendor/assets/potlatch2/potlatch2/locales/ar.swf index 794a47c02..183a33ec1 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ar.swf and b/vendor/assets/potlatch2/potlatch2/locales/ar.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/arc.swf b/vendor/assets/potlatch2/potlatch2/locales/arc.swf index 1962ca34c..36d42b835 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/arc.swf and b/vendor/assets/potlatch2/potlatch2/locales/arc.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ast.swf b/vendor/assets/potlatch2/potlatch2/locales/ast.swf index baad54eb0..f167ec4a4 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ast.swf and b/vendor/assets/potlatch2/potlatch2/locales/ast.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/az.swf b/vendor/assets/potlatch2/potlatch2/locales/az.swf index e3386de06..49ea1aba8 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/az.swf and b/vendor/assets/potlatch2/potlatch2/locales/az.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ba.swf b/vendor/assets/potlatch2/potlatch2/locales/ba.swf index 3f289fdb7..b708cccae 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ba.swf and b/vendor/assets/potlatch2/potlatch2/locales/ba.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/be-tarask.swf b/vendor/assets/potlatch2/potlatch2/locales/be-tarask.swf index e0e6348bc..93b0c405d 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/be-tarask.swf and b/vendor/assets/potlatch2/potlatch2/locales/be-tarask.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/be.swf b/vendor/assets/potlatch2/potlatch2/locales/be.swf index f2efc2efe..33ea44673 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/be.swf and b/vendor/assets/potlatch2/potlatch2/locales/be.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/bg.swf b/vendor/assets/potlatch2/potlatch2/locales/bg.swf index fe48a07c7..a147e0e7c 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/bg.swf and b/vendor/assets/potlatch2/potlatch2/locales/bg.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/bn.swf b/vendor/assets/potlatch2/potlatch2/locales/bn.swf index e7d64e612..b30c68b01 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/bn.swf and b/vendor/assets/potlatch2/potlatch2/locales/bn.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/br.swf b/vendor/assets/potlatch2/potlatch2/locales/br.swf index 7637432b7..2e51d91fc 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/br.swf and b/vendor/assets/potlatch2/potlatch2/locales/br.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/bs.swf b/vendor/assets/potlatch2/potlatch2/locales/bs.swf index cb00ca024..ee31f1468 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/bs.swf and b/vendor/assets/potlatch2/potlatch2/locales/bs.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ca.swf b/vendor/assets/potlatch2/potlatch2/locales/ca.swf index ce9139924..3d10696a0 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ca.swf and b/vendor/assets/potlatch2/potlatch2/locales/ca.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ce.swf b/vendor/assets/potlatch2/potlatch2/locales/ce.swf index 886d062a9..502338625 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ce.swf and b/vendor/assets/potlatch2/potlatch2/locales/ce.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/cs_CZ.swf b/vendor/assets/potlatch2/potlatch2/locales/cs_CZ.swf index 72ad6dcfe..e821b85a7 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/cs_CZ.swf and b/vendor/assets/potlatch2/potlatch2/locales/cs_CZ.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/cy.swf b/vendor/assets/potlatch2/potlatch2/locales/cy.swf index 9202bb135..a3a05f5a6 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/cy.swf and b/vendor/assets/potlatch2/potlatch2/locales/cy.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/da.swf b/vendor/assets/potlatch2/potlatch2/locales/da.swf index 5e55ab458..97ddb9ffc 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/da.swf and b/vendor/assets/potlatch2/potlatch2/locales/da.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/de-formal.swf b/vendor/assets/potlatch2/potlatch2/locales/de-formal.swf index 41c137bde..fd203b3fa 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/de-formal.swf and b/vendor/assets/potlatch2/potlatch2/locales/de-formal.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/de_DE.swf b/vendor/assets/potlatch2/potlatch2/locales/de_DE.swf index af99095bd..7a23936c2 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/de_DE.swf and b/vendor/assets/potlatch2/potlatch2/locales/de_DE.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/diq.swf b/vendor/assets/potlatch2/potlatch2/locales/diq.swf index 8a3339b8a..ccdbfb1bf 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/diq.swf and b/vendor/assets/potlatch2/potlatch2/locales/diq.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/dsb.swf b/vendor/assets/potlatch2/potlatch2/locales/dsb.swf index d31c26f71..83a853623 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/dsb.swf and b/vendor/assets/potlatch2/potlatch2/locales/dsb.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/el.swf b/vendor/assets/potlatch2/potlatch2/locales/el.swf index 8840d9376..79902e5c4 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/el.swf and b/vendor/assets/potlatch2/potlatch2/locales/el.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/en_GB.swf b/vendor/assets/potlatch2/potlatch2/locales/en_GB.swf index 7044c7df3..577af4a88 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/en_GB.swf and b/vendor/assets/potlatch2/potlatch2/locales/en_GB.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/en_US.swf b/vendor/assets/potlatch2/potlatch2/locales/en_US.swf index dafd55148..86b6f28be 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/en_US.swf and b/vendor/assets/potlatch2/potlatch2/locales/en_US.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/eo.swf b/vendor/assets/potlatch2/potlatch2/locales/eo.swf index 8a4a62986..8e4bbc382 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/eo.swf and b/vendor/assets/potlatch2/potlatch2/locales/eo.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/es_ES.swf b/vendor/assets/potlatch2/potlatch2/locales/es_ES.swf index d40c8760d..b50a2adb5 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/es_ES.swf and b/vendor/assets/potlatch2/potlatch2/locales/es_ES.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/et.swf b/vendor/assets/potlatch2/potlatch2/locales/et.swf index 7bb1f2305..e65dd758b 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/et.swf and b/vendor/assets/potlatch2/potlatch2/locales/et.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/eu.swf b/vendor/assets/potlatch2/potlatch2/locales/eu.swf index 280527b7c..91d10a4a6 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/eu.swf and b/vendor/assets/potlatch2/potlatch2/locales/eu.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/fa.swf b/vendor/assets/potlatch2/potlatch2/locales/fa.swf index acc3f1f29..7b9b1385f 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/fa.swf and b/vendor/assets/potlatch2/potlatch2/locales/fa.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/fi.swf b/vendor/assets/potlatch2/potlatch2/locales/fi.swf index 9dde244e8..f5ea48660 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/fi.swf and b/vendor/assets/potlatch2/potlatch2/locales/fi.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/fo.swf b/vendor/assets/potlatch2/potlatch2/locales/fo.swf index a636f7263..67a149542 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/fo.swf and b/vendor/assets/potlatch2/potlatch2/locales/fo.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/fr_FR.swf b/vendor/assets/potlatch2/potlatch2/locales/fr_FR.swf index 37423d139..ee73d8b2d 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/fr_FR.swf and b/vendor/assets/potlatch2/potlatch2/locales/fr_FR.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/fur.swf b/vendor/assets/potlatch2/potlatch2/locales/fur.swf index c0e0a4c81..5a5ac5101 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/fur.swf and b/vendor/assets/potlatch2/potlatch2/locales/fur.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/fy.swf b/vendor/assets/potlatch2/potlatch2/locales/fy.swf new file mode 100644 index 000000000..89e003802 Binary files /dev/null and b/vendor/assets/potlatch2/potlatch2/locales/fy.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ga.swf b/vendor/assets/potlatch2/potlatch2/locales/ga.swf index 9cf693561..bbea73d7c 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ga.swf and b/vendor/assets/potlatch2/potlatch2/locales/ga.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/gd.swf b/vendor/assets/potlatch2/potlatch2/locales/gd.swf index bed95e439..f5f873130 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/gd.swf and b/vendor/assets/potlatch2/potlatch2/locales/gd.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/gl.swf b/vendor/assets/potlatch2/potlatch2/locales/gl.swf index dad0c2b14..c28d49227 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/gl.swf and b/vendor/assets/potlatch2/potlatch2/locales/gl.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/grc.swf b/vendor/assets/potlatch2/potlatch2/locales/grc.swf index 2141dfb0c..455dd550b 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/grc.swf and b/vendor/assets/potlatch2/potlatch2/locales/grc.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/he.swf b/vendor/assets/potlatch2/potlatch2/locales/he.swf index d52f328cf..41f50ef13 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/he.swf and b/vendor/assets/potlatch2/potlatch2/locales/he.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/hr.swf b/vendor/assets/potlatch2/potlatch2/locales/hr.swf index 6be823004..55d33456e 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/hr.swf and b/vendor/assets/potlatch2/potlatch2/locales/hr.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/hsb.swf b/vendor/assets/potlatch2/potlatch2/locales/hsb.swf index d2856baf8..cb1c5270c 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/hsb.swf and b/vendor/assets/potlatch2/potlatch2/locales/hsb.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/hu.swf b/vendor/assets/potlatch2/potlatch2/locales/hu.swf index 54bc6d3a7..bd4551a05 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/hu.swf and b/vendor/assets/potlatch2/potlatch2/locales/hu.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ia.swf b/vendor/assets/potlatch2/potlatch2/locales/ia.swf index 3dcda7ff4..7500b7ea2 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ia.swf and b/vendor/assets/potlatch2/potlatch2/locales/ia.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/id.swf b/vendor/assets/potlatch2/potlatch2/locales/id.swf index 177c2ee35..e2d121bf3 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/id.swf and b/vendor/assets/potlatch2/potlatch2/locales/id.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/is.swf b/vendor/assets/potlatch2/potlatch2/locales/is.swf index 36b9a2c05..f32b92571 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/is.swf and b/vendor/assets/potlatch2/potlatch2/locales/is.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/it_IT.swf b/vendor/assets/potlatch2/potlatch2/locales/it_IT.swf index f0d9d67d0..c6e54841a 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/it_IT.swf and b/vendor/assets/potlatch2/potlatch2/locales/it_IT.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ja_JP.swf b/vendor/assets/potlatch2/potlatch2/locales/ja_JP.swf index 11e99cf70..f180598be 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ja_JP.swf and b/vendor/assets/potlatch2/potlatch2/locales/ja_JP.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ka.swf b/vendor/assets/potlatch2/potlatch2/locales/ka.swf index 8ed169cc3..f59002a20 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ka.swf and b/vendor/assets/potlatch2/potlatch2/locales/ka.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/kab.swf b/vendor/assets/potlatch2/potlatch2/locales/kab.swf index 6fc598f93..32244ea5b 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/kab.swf and b/vendor/assets/potlatch2/potlatch2/locales/kab.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/km.swf b/vendor/assets/potlatch2/potlatch2/locales/km.swf index eb5e6d468..4c5c8248e 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/km.swf and b/vendor/assets/potlatch2/potlatch2/locales/km.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/kn.swf b/vendor/assets/potlatch2/potlatch2/locales/kn.swf index cec9b4f8c..ba3076ee5 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/kn.swf and b/vendor/assets/potlatch2/potlatch2/locales/kn.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ko.swf b/vendor/assets/potlatch2/potlatch2/locales/ko.swf index 3947beb8e..02d596fe9 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ko.swf and b/vendor/assets/potlatch2/potlatch2/locales/ko.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/krc.swf b/vendor/assets/potlatch2/potlatch2/locales/krc.swf index 6c769d4c7..c7966c1e9 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/krc.swf and b/vendor/assets/potlatch2/potlatch2/locales/krc.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ksh.swf b/vendor/assets/potlatch2/potlatch2/locales/ksh.swf index 70ab863b1..4ebcf5743 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ksh.swf and b/vendor/assets/potlatch2/potlatch2/locales/ksh.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ku-latn.swf b/vendor/assets/potlatch2/potlatch2/locales/ku-latn.swf index 7c0a1edeb..eeeeb12f4 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ku-latn.swf and b/vendor/assets/potlatch2/potlatch2/locales/ku-latn.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ky.swf b/vendor/assets/potlatch2/potlatch2/locales/ky.swf index 88222052c..a54a23f74 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ky.swf and b/vendor/assets/potlatch2/potlatch2/locales/ky.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/lb.swf b/vendor/assets/potlatch2/potlatch2/locales/lb.swf index a2e5820ef..c7293536e 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/lb.swf and b/vendor/assets/potlatch2/potlatch2/locales/lb.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/lez.swf b/vendor/assets/potlatch2/potlatch2/locales/lez.swf index 4178ffd4e..bf78c2ec9 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/lez.swf and b/vendor/assets/potlatch2/potlatch2/locales/lez.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/lt.swf b/vendor/assets/potlatch2/potlatch2/locales/lt.swf index 89161cca0..91cb26ec4 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/lt.swf and b/vendor/assets/potlatch2/potlatch2/locales/lt.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/lv.swf b/vendor/assets/potlatch2/potlatch2/locales/lv.swf index c8b44ddd4..e6eb43418 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/lv.swf and b/vendor/assets/potlatch2/potlatch2/locales/lv.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/lzz.swf b/vendor/assets/potlatch2/potlatch2/locales/lzz.swf index 3bfa7af62..d01562775 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/lzz.swf and b/vendor/assets/potlatch2/potlatch2/locales/lzz.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/mg.swf b/vendor/assets/potlatch2/potlatch2/locales/mg.swf index 4a6866927..243138d82 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/mg.swf and b/vendor/assets/potlatch2/potlatch2/locales/mg.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/mk.swf b/vendor/assets/potlatch2/potlatch2/locales/mk.swf index 6811a0bd8..1f8b9c94f 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/mk.swf and b/vendor/assets/potlatch2/potlatch2/locales/mk.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/mr.swf b/vendor/assets/potlatch2/potlatch2/locales/mr.swf index 2a047b66c..8df83f3c3 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/mr.swf and b/vendor/assets/potlatch2/potlatch2/locales/mr.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ms.swf b/vendor/assets/potlatch2/potlatch2/locales/ms.swf index 22b8864c5..760d095db 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ms.swf and b/vendor/assets/potlatch2/potlatch2/locales/ms.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/nb_NO.swf b/vendor/assets/potlatch2/potlatch2/locales/nb_NO.swf index 17a9aeabc..1c10cd466 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/nb_NO.swf and b/vendor/assets/potlatch2/potlatch2/locales/nb_NO.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ne.swf b/vendor/assets/potlatch2/potlatch2/locales/ne.swf new file mode 100644 index 000000000..c164b28a5 Binary files /dev/null and b/vendor/assets/potlatch2/potlatch2/locales/ne.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/nl_NL.swf b/vendor/assets/potlatch2/potlatch2/locales/nl_NL.swf index 9a8e78bdd..394648013 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/nl_NL.swf and b/vendor/assets/potlatch2/potlatch2/locales/nl_NL.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/nn_NO.swf b/vendor/assets/potlatch2/potlatch2/locales/nn_NO.swf index ed1075ce3..366a24678 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/nn_NO.swf and b/vendor/assets/potlatch2/potlatch2/locales/nn_NO.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/oc.swf b/vendor/assets/potlatch2/potlatch2/locales/oc.swf index 8276fc08a..7b5255b9e 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/oc.swf and b/vendor/assets/potlatch2/potlatch2/locales/oc.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/pa.swf b/vendor/assets/potlatch2/potlatch2/locales/pa.swf index 9ecc5b599..190604b33 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/pa.swf and b/vendor/assets/potlatch2/potlatch2/locales/pa.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/pl_PL.swf b/vendor/assets/potlatch2/potlatch2/locales/pl_PL.swf index 236d44e0e..b3e121caa 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/pl_PL.swf and b/vendor/assets/potlatch2/potlatch2/locales/pl_PL.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ps.swf b/vendor/assets/potlatch2/potlatch2/locales/ps.swf index 928c85439..147546258 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ps.swf and b/vendor/assets/potlatch2/potlatch2/locales/ps.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/pt_BR.swf b/vendor/assets/potlatch2/potlatch2/locales/pt_BR.swf index 40560d901..481e1d762 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/pt_BR.swf and b/vendor/assets/potlatch2/potlatch2/locales/pt_BR.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/pt_PT.swf b/vendor/assets/potlatch2/potlatch2/locales/pt_PT.swf index fde148a9d..7f127065c 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/pt_PT.swf and b/vendor/assets/potlatch2/potlatch2/locales/pt_PT.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ro.swf b/vendor/assets/potlatch2/potlatch2/locales/ro.swf index ba646bc6f..f0a092b6a 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ro.swf and b/vendor/assets/potlatch2/potlatch2/locales/ro.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ru.swf b/vendor/assets/potlatch2/potlatch2/locales/ru.swf index 0eafb3b60..f3127e562 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ru.swf and b/vendor/assets/potlatch2/potlatch2/locales/ru.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/rue.swf b/vendor/assets/potlatch2/potlatch2/locales/rue.swf index 344ad55d8..26b3b11ae 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/rue.swf and b/vendor/assets/potlatch2/potlatch2/locales/rue.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/sah.swf b/vendor/assets/potlatch2/potlatch2/locales/sah.swf index 0fa7d06ea..18ba7953f 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/sah.swf and b/vendor/assets/potlatch2/potlatch2/locales/sah.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/scn.swf b/vendor/assets/potlatch2/potlatch2/locales/scn.swf index aa83ad460..f37f00e76 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/scn.swf and b/vendor/assets/potlatch2/potlatch2/locales/scn.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/shn.swf b/vendor/assets/potlatch2/potlatch2/locales/shn.swf new file mode 100644 index 000000000..b06b3aac1 Binary files /dev/null and b/vendor/assets/potlatch2/potlatch2/locales/shn.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/sk.swf b/vendor/assets/potlatch2/potlatch2/locales/sk.swf index c127129da..9dbb7b5c3 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/sk.swf and b/vendor/assets/potlatch2/potlatch2/locales/sk.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/skr-arab.swf b/vendor/assets/potlatch2/potlatch2/locales/skr-arab.swf index 6bfa6ffaa..66a64341b 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/skr-arab.swf and b/vendor/assets/potlatch2/potlatch2/locales/skr-arab.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/sl.swf b/vendor/assets/potlatch2/potlatch2/locales/sl.swf index dc877c572..5e14cd93d 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/sl.swf and b/vendor/assets/potlatch2/potlatch2/locales/sl.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/sq.swf b/vendor/assets/potlatch2/potlatch2/locales/sq.swf index 129fbb76b..381a6b0f2 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/sq.swf and b/vendor/assets/potlatch2/potlatch2/locales/sq.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/sr-ec.swf b/vendor/assets/potlatch2/potlatch2/locales/sr-ec.swf index d20f5703a..ac984efb3 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/sr-ec.swf and b/vendor/assets/potlatch2/potlatch2/locales/sr-ec.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/sr-el.swf b/vendor/assets/potlatch2/potlatch2/locales/sr-el.swf index dc409a197..6645dc112 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/sr-el.swf and b/vendor/assets/potlatch2/potlatch2/locales/sr-el.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/sty.swf b/vendor/assets/potlatch2/potlatch2/locales/sty.swf new file mode 100644 index 000000000..e7414bcbe Binary files /dev/null and b/vendor/assets/potlatch2/potlatch2/locales/sty.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/sv_SE.swf b/vendor/assets/potlatch2/potlatch2/locales/sv_SE.swf index 033090cf2..6f59472eb 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/sv_SE.swf and b/vendor/assets/potlatch2/potlatch2/locales/sv_SE.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/ta.swf b/vendor/assets/potlatch2/potlatch2/locales/ta.swf index 8d32a33e1..d211e831b 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/ta.swf and b/vendor/assets/potlatch2/potlatch2/locales/ta.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/te.swf b/vendor/assets/potlatch2/potlatch2/locales/te.swf index cce8b495a..e45aab2de 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/te.swf and b/vendor/assets/potlatch2/potlatch2/locales/te.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/th.swf b/vendor/assets/potlatch2/potlatch2/locales/th.swf new file mode 100644 index 000000000..1482eed0b Binary files /dev/null and b/vendor/assets/potlatch2/potlatch2/locales/th.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/tl.swf b/vendor/assets/potlatch2/potlatch2/locales/tl.swf index 28cacedb9..0597c8783 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/tl.swf and b/vendor/assets/potlatch2/potlatch2/locales/tl.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/tly.swf b/vendor/assets/potlatch2/potlatch2/locales/tly.swf index 32230921f..cbc29e38f 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/tly.swf and b/vendor/assets/potlatch2/potlatch2/locales/tly.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/tr.swf b/vendor/assets/potlatch2/potlatch2/locales/tr.swf index 43455a791..f7a482dbf 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/tr.swf and b/vendor/assets/potlatch2/potlatch2/locales/tr.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/tyv.swf b/vendor/assets/potlatch2/potlatch2/locales/tyv.swf index 2b86df955..87ba6464b 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/tyv.swf and b/vendor/assets/potlatch2/potlatch2/locales/tyv.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/tzm.swf b/vendor/assets/potlatch2/potlatch2/locales/tzm.swf index ce2996332..b0681b6a3 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/tzm.swf and b/vendor/assets/potlatch2/potlatch2/locales/tzm.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/uk.swf b/vendor/assets/potlatch2/potlatch2/locales/uk.swf index f8da48aa9..e5b88f365 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/uk.swf and b/vendor/assets/potlatch2/potlatch2/locales/uk.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/vi_VN.swf b/vendor/assets/potlatch2/potlatch2/locales/vi_VN.swf index 15520a2af..ef308f093 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/vi_VN.swf and b/vendor/assets/potlatch2/potlatch2/locales/vi_VN.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/vo.swf b/vendor/assets/potlatch2/potlatch2/locales/vo.swf index e92534998..de3a2d599 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/vo.swf and b/vendor/assets/potlatch2/potlatch2/locales/vo.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/yi.swf b/vendor/assets/potlatch2/potlatch2/locales/yi.swf index 8d133c737..ea316ba89 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/yi.swf and b/vendor/assets/potlatch2/potlatch2/locales/yi.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/zh_CN.swf b/vendor/assets/potlatch2/potlatch2/locales/zh_CN.swf index 1123be539..149f27415 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/zh_CN.swf and b/vendor/assets/potlatch2/potlatch2/locales/zh_CN.swf differ diff --git a/vendor/assets/potlatch2/potlatch2/locales/zh_TW.swf b/vendor/assets/potlatch2/potlatch2/locales/zh_TW.swf index 8c8901e55..1ea0dbc5b 100644 Binary files a/vendor/assets/potlatch2/potlatch2/locales/zh_TW.swf and b/vendor/assets/potlatch2/potlatch2/locales/zh_TW.swf differ diff --git a/vendor/assets/swfobject/expressInstall.swf b/vendor/assets/swfobject/expressInstall.swf old mode 100644 new mode 100755 diff --git a/vendor/assets/swfobject/swfobject.js b/vendor/assets/swfobject/swfobject.js old mode 100644 new mode 100755 index 8eafe9dd8..9378c8f75 --- a/vendor/assets/swfobject/swfobject.js +++ b/vendor/assets/swfobject/swfobject.js @@ -1,4 +1,777 @@ -/* SWFObject v2.2 +/*! SWFObject v2.2 is released under the MIT License */ -var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab 0) { + for (var i = 0; i < rl; i++) { // for each registered object element + var id = regObjArr[i].id; + var cb = regObjArr[i].callbackFn; + var cbObj = {success:false, id:id}; + if (ua.pv[0] > 0) { + var obj = getElementById(id); + if (obj) { + if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match! + setVisibility(id, true); + if (cb) { + cbObj.success = true; + cbObj.ref = getObjectById(id); + cb(cbObj); + } + } + else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported + var att = {}; + att.data = regObjArr[i].expressInstall; + att.width = obj.getAttribute("width") || "0"; + att.height = obj.getAttribute("height") || "0"; + if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); } + if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); } + // parse HTML object param element's name-value pairs + var par = {}; + var p = obj.getElementsByTagName("param"); + var pl = p.length; + for (var j = 0; j < pl; j++) { + if (p[j].getAttribute("name").toLowerCase() != "movie") { + par[p[j].getAttribute("name")] = p[j].getAttribute("value"); + } + } + showExpressInstall(att, par, id, cb); + } + else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF + displayAltContent(obj); + if (cb) { cb(cbObj); } + } + } + } + else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content) + setVisibility(id, true); + if (cb) { + var o = getObjectById(id); // test whether there is an HTML object element or not + if (o && typeof o.SetVariable != UNDEF) { + cbObj.success = true; + cbObj.ref = o; + } + cb(cbObj); + } + } + } + } + } + + function getObjectById(objectIdStr) { + var r = null; + var o = getElementById(objectIdStr); + if (o && o.nodeName == "OBJECT") { + if (typeof o.SetVariable != UNDEF) { + r = o; + } + else { + var n = o.getElementsByTagName(OBJECT)[0]; + if (n) { + r = n; + } + } + } + return r; + } + + /* Requirements for Adobe Express Install + - only one instance can be active at a time + - fp 6.0.65 or higher + - Win/Mac OS only + - no Webkit engines older than version 312 + */ + function canExpressInstall() { + return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312); + } + + /* Show the Adobe Express Install dialog + - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75 + */ + function showExpressInstall(att, par, replaceElemIdStr, callbackFn) { + isExpressInstallActive = true; + storedCallbackFn = callbackFn || null; + storedCallbackObj = {success:false, id:replaceElemIdStr}; + var obj = getElementById(replaceElemIdStr); + if (obj) { + if (obj.nodeName == "OBJECT") { // static publishing + storedAltContent = abstractAltContent(obj); + storedAltContentId = null; + } + else { // dynamic publishing + storedAltContent = obj; + storedAltContentId = replaceElemIdStr; + } + att.id = EXPRESS_INSTALL_ID; + if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; } + if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; } + doc.title = doc.title.slice(0, 47) + " - Flash Player Installation"; + var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn", + fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title; + if (typeof par.flashvars != UNDEF) { + par.flashvars += "&" + fv; + } + else { + par.flashvars = fv; + } + // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, + // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work + if (ua.ie && ua.win && obj.readyState != 4) { + var newObj = createElement("div"); + replaceElemIdStr += "SWFObjectNew"; + newObj.setAttribute("id", replaceElemIdStr); + obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf + obj.style.display = "none"; + (function(){ + if (obj.readyState == 4) { + obj.parentNode.removeChild(obj); + } + else { + setTimeout(arguments.callee, 10); + } + })(); + } + createSWF(att, par, replaceElemIdStr); + } + } + + /* Functions to abstract and display alternative content + */ + function displayAltContent(obj) { + if (ua.ie && ua.win && obj.readyState != 4) { + // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, + // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work + var el = createElement("div"); + obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content + el.parentNode.replaceChild(abstractAltContent(obj), el); + obj.style.display = "none"; + (function(){ + if (obj.readyState == 4) { + obj.parentNode.removeChild(obj); + } + else { + setTimeout(arguments.callee, 10); + } + })(); + } + else { + obj.parentNode.replaceChild(abstractAltContent(obj), obj); + } + } + + function abstractAltContent(obj) { + var ac = createElement("div"); + if (ua.win && ua.ie) { + ac.innerHTML = obj.innerHTML; + } + else { + var nestedObj = obj.getElementsByTagName(OBJECT)[0]; + if (nestedObj) { + var c = nestedObj.childNodes; + if (c) { + var cl = c.length; + for (var i = 0; i < cl; i++) { + if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) { + ac.appendChild(c[i].cloneNode(true)); + } + } + } + } + } + return ac; + } + + /* Cross-browser dynamic SWF creation + */ + function createSWF(attObj, parObj, id) { + var r, el = getElementById(id); + if (ua.wk && ua.wk < 312) { return r; } + if (el) { + if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content + attObj.id = id; + } + if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML + var att = ""; + for (var i in attObj) { + if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries + if (i.toLowerCase() == "data") { + parObj.movie = attObj[i]; + } + else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword + att += ' class="' + attObj[i] + '"'; + } + else if (i.toLowerCase() != "classid") { + att += ' ' + i + '="' + attObj[i] + '"'; + } + } + } + var par = ""; + for (var j in parObj) { + if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries + par += ''; + } + } + el.outerHTML = '' + par + ''; + objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only) + r = getElementById(attObj.id); + } + else { // well-behaving browsers + var o = createElement(OBJECT); + o.setAttribute("type", FLASH_MIME_TYPE); + for (var m in attObj) { + if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries + if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword + o.setAttribute("class", attObj[m]); + } + else if (m.toLowerCase() != "classid") { // filter out IE specific attribute + o.setAttribute(m, attObj[m]); + } + } + } + for (var n in parObj) { + if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element + createObjParam(o, n, parObj[n]); + } + } + el.parentNode.replaceChild(o, el); + r = o; + } + } + return r; + } + + function createObjParam(el, pName, pValue) { + var p = createElement("param"); + p.setAttribute("name", pName); + p.setAttribute("value", pValue); + el.appendChild(p); + } + + /* Cross-browser SWF removal + - Especially needed to safely and completely remove a SWF in Internet Explorer + */ + function removeSWF(id) { + var obj = getElementById(id); + if (obj && obj.nodeName == "OBJECT") { + if (ua.ie && ua.win) { + obj.style.display = "none"; + (function(){ + if (obj.readyState == 4) { + removeObjectInIE(id); + } + else { + setTimeout(arguments.callee, 10); + } + })(); + } + else { + obj.parentNode.removeChild(obj); + } + } + } + + function removeObjectInIE(id) { + var obj = getElementById(id); + if (obj) { + for (var i in obj) { + if (typeof obj[i] == "function") { + obj[i] = null; + } + } + obj.parentNode.removeChild(obj); + } + } + + /* Functions to optimize JavaScript compression + */ + function getElementById(id) { + var el = null; + try { + el = doc.getElementById(id); + } + catch (e) {} + return el; + } + + function createElement(el) { + return doc.createElement(el); + } + + /* Updated attachEvent function for Internet Explorer + - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks + */ + function addListener(target, eventType, fn) { + target.attachEvent(eventType, fn); + listenersArr[listenersArr.length] = [target, eventType, fn]; + } + + /* Flash Player and SWF content version matching + */ + function hasPlayerVersion(rv) { + var pv = ua.pv, v = rv.split("."); + v[0] = parseInt(v[0], 10); + v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0" + v[2] = parseInt(v[2], 10) || 0; + return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false; + } + + /* Cross-browser dynamic CSS creation + - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php + */ + function createCSS(sel, decl, media, newStyle) { + if (ua.ie && ua.mac) { return; } + var h = doc.getElementsByTagName("head")[0]; + if (!h) { return; } // to also support badly authored HTML pages that lack a head element + var m = (media && typeof media == "string") ? media : "screen"; + if (newStyle) { + dynamicStylesheet = null; + dynamicStylesheetMedia = null; + } + if (!dynamicStylesheet || dynamicStylesheetMedia != m) { + // create dynamic stylesheet + get a global reference to it + var s = createElement("style"); + s.setAttribute("type", "text/css"); + s.setAttribute("media", m); + dynamicStylesheet = h.appendChild(s); + if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) { + dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1]; + } + dynamicStylesheetMedia = m; + } + // add style rule + if (ua.ie && ua.win) { + if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) { + dynamicStylesheet.addRule(sel, decl); + } + } + else { + if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) { + dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}")); + } + } + } + + function setVisibility(id, isVisible) { + if (!autoHideShow) { return; } + var v = isVisible ? "visible" : "hidden"; + if (isDomLoaded && getElementById(id)) { + getElementById(id).style.visibility = v; + } + else { + createCSS("#" + id, "visibility:" + v); + } + } + + /* Filter to avoid XSS attacks + */ + function urlEncodeIfNecessary(s) { + var regex = /[\\\"<>\.;]/; + var hasBadChars = regex.exec(s) != null; + return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s; + } + + /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only) + */ + var cleanup = function() { + if (ua.ie && ua.win) { + window.attachEvent("onunload", function() { + // remove listeners to avoid memory leaks + var ll = listenersArr.length; + for (var i = 0; i < ll; i++) { + listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]); + } + // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect + var il = objIdArr.length; + for (var j = 0; j < il; j++) { + removeSWF(objIdArr[j]); + } + // cleanup library's main closures to avoid memory leaks + for (var k in ua) { + ua[k] = null; + } + ua = null; + for (var l in swfobject) { + swfobject[l] = null; + } + swfobject = null; + }); + } + }(); + + return { + /* Public API + - Reference: http://code.google.com/p/swfobject/wiki/documentation + */ + registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) { + if (ua.w3 && objectIdStr && swfVersionStr) { + var regObj = {}; + regObj.id = objectIdStr; + regObj.swfVersion = swfVersionStr; + regObj.expressInstall = xiSwfUrlStr; + regObj.callbackFn = callbackFn; + regObjArr[regObjArr.length] = regObj; + setVisibility(objectIdStr, false); + } + else if (callbackFn) { + callbackFn({success:false, id:objectIdStr}); + } + }, + + getObjectById: function(objectIdStr) { + if (ua.w3) { + return getObjectById(objectIdStr); + } + }, + + embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) { + var callbackObj = {success:false, id:replaceElemIdStr}; + if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) { + setVisibility(replaceElemIdStr, false); + addDomLoadEvent(function() { + widthStr += ""; // auto-convert to string + heightStr += ""; + var att = {}; + if (attObj && typeof attObj === OBJECT) { + for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs + att[i] = attObj[i]; + } + } + att.data = swfUrlStr; + att.width = widthStr; + att.height = heightStr; + var par = {}; + if (parObj && typeof parObj === OBJECT) { + for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs + par[j] = parObj[j]; + } + } + if (flashvarsObj && typeof flashvarsObj === OBJECT) { + for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs + if (typeof par.flashvars != UNDEF) { + par.flashvars += "&" + k + "=" + flashvarsObj[k]; + } + else { + par.flashvars = k + "=" + flashvarsObj[k]; + } + } + } + if (hasPlayerVersion(swfVersionStr)) { // create SWF + var obj = createSWF(att, par, replaceElemIdStr); + if (att.id == replaceElemIdStr) { + setVisibility(replaceElemIdStr, true); + } + callbackObj.success = true; + callbackObj.ref = obj; + } + else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install + att.data = xiSwfUrlStr; + showExpressInstall(att, par, replaceElemIdStr, callbackFn); + return; + } + else { // show alternative content + setVisibility(replaceElemIdStr, true); + } + if (callbackFn) { callbackFn(callbackObj); } + }); + } + else if (callbackFn) { callbackFn(callbackObj); } + }, + + switchOffAutoHideShow: function() { + autoHideShow = false; + }, + + ua: ua, + + getFlashPlayerVersion: function() { + return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] }; + }, + + hasFlashPlayerVersion: hasPlayerVersion, + + createSWF: function(attObj, parObj, replaceElemIdStr) { + if (ua.w3) { + return createSWF(attObj, parObj, replaceElemIdStr); + } + else { + return undefined; + } + }, + + showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) { + if (ua.w3 && canExpressInstall()) { + showExpressInstall(att, par, replaceElemIdStr, callbackFn); + } + }, + + removeSWF: function(objElemIdStr) { + if (ua.w3) { + removeSWF(objElemIdStr); + } + }, + + createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) { + if (ua.w3) { + createCSS(selStr, declStr, mediaStr, newStyleBoolean); + } + }, + + addDomLoadEvent: addDomLoadEvent, + + addLoadEvent: addLoadEvent, + + getQueryParamValue: function(param) { + var q = doc.location.search || doc.location.hash; + if (q) { + if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark + if (param == null) { + return urlEncodeIfNecessary(q); + } + var pairs = q.split("&"); + for (var i = 0; i < pairs.length; i++) { + if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) { + return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1))); + } + } + } + return ""; + }, + + // For internal usage only + expressInstallCallback: function() { + if (isExpressInstallActive) { + var obj = getElementById(EXPRESS_INSTALL_ID); + if (obj && storedAltContent) { + obj.parentNode.replaceChild(storedAltContent, obj); + if (storedAltContentId) { + setVisibility(storedAltContentId, true); + if (ua.ie && ua.win) { storedAltContent.style.display = "block"; } + } + if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); } + } + isExpressInstallActive = false; + } + } + }; +}();